First Commit of my working state
[simh.git] / PDP11 / pdp11_xq.c
1 /* pdp11_xq.c: DEQNA/DELQA ethernet controller simulator
2 ------------------------------------------------------------------------------
3
4 Copyright (c) 2002-2007, David T. Hittner
5
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
23 Except as contained in this notice, the name of the author shall not be
24 used in advertising or otherwise to promote the sale, use or other dealings
25 in this Software without prior written authorization from the author.
26
27 ------------------------------------------------------------------------------
28
29 This DEQNA/DELQA simulation is based on:
30 Digital DELQA Users Guide, Part# EK-DELQA-UG-002
31 Digital DEQNA Users Guide, Part# EK-DEQNA-UG-001
32 These manuals can be found online at:
33 http://www.spies.com/~aek/pdf/dec/qbus
34
35 Certain adaptations have been made because this is an emulation:
36 Ethernet transceiver power flag CSR<12> is ON when attached.
37 External Loopback does not go out to the physical adapter, it is
38 implemented more like an extended Internal Loopback
39 Time Domain Reflectometry (TDR) numbers are faked
40 The 10-second approx. hardware/software reset delay does not exist
41 Some physical ethernet receive events like Runts, Overruns, etc. are
42 never reported back, since the packet-level driver never sees them
43
44 Certain advantages are derived from this emulation:
45 If the real ethernet controller is faster than 10Mbit/sec, the speed is
46 seen by the simulated cpu since there are no minimum response times.
47
48 Known Bugs or Unsupported features, in priority order:
49 1) PDP11 bootstrap
50 2) MOP functionality not implemented
51 3) Local packet processing not implemented
52
53 Regression Tests:
54 VAX: 1. Console SHOW DEVICE
55 2. VMS v7.2 boots/initializes/shows device
56 3. VMS DECNET - SET HOST and COPY tests
57 4. VMS MultiNet - SET HOST/TELNET and FTP tests
58 5. VMS LAT - SET HOST/LAT tests
59 6. VMS Cluster - SHOW CLUSTER, SHOW DEVICE, and cluster COPY tests
60 7. Console boot into VMSCluster (>>>B XQAO)
61
62 PDP11: 1. RT-11 v5.3 - FTPSB copy test
63 2. RSTS/E v10.1 - detects/enables device
64
65 ------------------------------------------------------------------------------
66
67 Modification history:
68
69 18-Jun-07 RMS Added UNIT_IDLE flag
70 29-Oct-06 RMS Synced poll and clock
71 27-Jan-06 RMS Fixed unaligned accesses in XQB (found by Doug Carman)
72 07-Jan-06 RMS Fixed unaligned access bugs (found by Doug Carman)
73 07-Sep-05 DTH Removed unused variable
74 16-Aug-05 RMS Fixed C++ declaration and cast problems
75 01-Dec-04 DTH Added runtime attach prompt
76 27-Feb-04 DTH Removed struct timeb deuggers
77 31-Jan-04 DTH Replaced #ifdef debuggers with inline debugging
78 19-Jan-04 DTH Combined service timers into one for efficiency
79 16-Jan-04 DTH Added more info to SHOW MOD commands, added SET/SHOW XQ DEBUG
80 13-Jan-04 DTH Corrected interrupt code with help from Tom Evans
81 06-Jan-04 DTH Added protection against changing mac and type if attached
82 05-Jan-04 DTH Moved most of xq_setmac to sim_ether
83 26-Dec-03 DTH Moved ethernet show and queue functions to sim_ether
84 03-Dec-03 DTH Added minimum name length to show xq eth
85 25-Nov-03 DTH Reworked interrupts to fix broken XQB implementation
86 19-Nov-03 MP Rearranged timer reset sequencing to allow for a device to be
87 disabled after it had been enabled.
88 17-Nov-03 DTH Standardized #include of timeb.h
89 28-Sep-03 MP - Fixed bug in xq_process_setup which would leave the
90 device in promiscuous or all multicast mode once it
91 ever had been there.
92 - Fixed output format in show_xq_sanity to end in "\n"
93 - Added display of All Multicase and promiscuous to
94 xq_show_filters
95 - The stuck in All Multicast or Promiscuous issue is
96 worse than previously thought. See comments in
97 xq_process_setup.
98 - Change xq_setmac to also allow ":" as a address
99 separator character, since sim_ether's eth_mac_fmt
100 formats them with this separator character.
101 - Changed xq_sw_reset to behave more like the set of
102 actions described in Table 3-6 of the DELQA manua.
103 The manual mentions "N/A" which I'm interpreting to
104 mean "Not Affected".
105 05-Jun-03 DTH Added receive packet splitting
106 03-Jun-03 DTH Added SHOW XQ FILTERS
107 02-Jun-03 DTH Added SET/SHOW XQ STATS (packet statistics), runt & giant processing
108 28-May-03 DTH Modified message queue for dynamic size to shrink executable
109 28-May-03 MP Fixed bug in xq_setmac
110 06-May-03 DTH Changed 32-bit t_addr to uint32 for v3.0
111 Removed SET ADDRESS functionality
112 05-May-03 DTH Added second controller
113 26-Mar-03 DTH Added PDP11 bootrom loader
114 Adjusted xq_ex and xq_dev to allow pdp11 to look at bootrom
115 Patched bootrom to allow "pass" of diagnostics on RSTS/E
116 06-Mar-03 DTH Corrected interrupts on IE state transition (code by Tom Evans)
117 Added interrupt clear on soft reset (first noted by Bob Supnik)
118 Removed interrupt when setting XL or RL (multiple people)
119 16-Jan-03 DTH Merged Mark Pizzolato's enhancements with main source
120 Corrected PDP11 XQ_DEBUG compilation
121 15-Jan-03 MP Fixed the number of units in the xq device structure.
122 13-Jan-03 MP Reworked the timer management logic which initiated
123 the system id broadcast messages. The original
124 implementation triggered this on the CSR transition
125 of Receiver Enabled. This was an issue since the
126 it seems that at least VMS's XQ driver makes this
127 transition often and the resulting overhead reduces
128 the simulated CPU instruction execution throughput by
129 about 40%. I start the system id timer on device
130 reset and it fires once a second so that it can
131 leverage the reasonably recalibrated tmr_poll value.
132 13-Jan-03 MP Changed the scheduling of xq_svc to leverage the
133 dynamically computed clock values to achieve an
134 approximate interval of 100 per second. This is
135 more than sufficient for normal system behaviour
136 expecially since we service receives with every
137 transmit. The previous fixed value of 2500
138 attempted to get 200/sec but it was a guess that
139 didn't adapt. On faster host systems (possibly
140 most of them) the 2500 number spends too much time
141 polling.
142 10-Jan-03 DTH Removed XQ_DEBUG dependency from Borland #pragmas
143 Added SET XQ BOOTROM command for PDP11s
144 07-Jan-03 DTH Added pointer to online manuals
145 02-Jan-03 DTH Added local packet processing
146 30-Dec-02 DTH Added automatic system id broadcast
147 27-Dec-02 DTH Merged Mark Pizzolato's enhancements with main source
148 20-Dec-02 MP Fix bug that caused VMS system crashes when attempting cluster
149 operations. Added additional conditionally compiled debug
150 info needed to track down the issue.
151 17-Dec-02 MP Added SIMH "registers" describing the Ethernet state
152 so this information can be recorded in a "saved" snapshot.
153 05-Dec-02 MP Adjusted the rtime value from 100 to 2500 which increased the
154 available CPU cycles for Instruction execution by almost 100%.
155 This made sense after the below enhancements which, in general
156 caused the draining of the received data stream much more
157 agressively with less overhead.
158 05-Dec-02 MP Added a call to xq_svc after all successful calls to eth_write
159 to allow receive processing to happen before the next event
160 service time.
161 05-Dec-02 MP Restructured the flow of processing in xq_svc so that eth_read
162 is called repeatedly until either a packet isn't found or
163 there is no room for another one in the queue. Once that has
164 been done, xq_process_rdbl is called to pass the queued packets
165 into the simulated system as space is available there.
166 xq_process_rdbl is also called at the beginning of xq_svc to
167 drain the queue into the simulated system, making more room
168 available in the queue. No processing is done at all in
169 xq_svc if the receiver is disabled.
170 04-Dec-02 MP Changed interface and usage to xq_insert_queue to pass
171 the packet to be inserted by reference. This avoids 3K bytes
172 of buffer copy operations for each packet received. Now only
173 copy actual received packet data.
174 31-Oct-02 DTH Cleaned up pointer warnings (found by Federico Schwindt)
175 Corrected unattached and no network behavior
176 Added message when SHOW XQ ETH finds no devices
177 23-Oct-02 DTH Beta 5 released
178 22-Oct-02 DTH Added all_multicast and promiscuous support
179 21-Oct-02 DTH Added write buffer max size check (code by Jason Thorpe)
180 Corrected copyright again
181 Implemented NXM testing and recovery
182 16-Oct-02 DTH Beta 4 released
183 Added and debugged Sanity Timer code
184 Corrected copyright
185 15-Oct-02 DTH Rollback to known good Beta3 and roll forward; TCP broken
186 12-Oct-02 DTH Fixed VAX network bootstrap; setup packets must return TDR > 0
187 11-Oct-02 DTH Added SET/SHOW XQ TYPE and SET/SHOW XQ SANITY commands
188 10-Oct-02 DTH Beta 3 released; Integrated with 2.10-0b1
189 Fixed off-by-1 bug on xq->setup.macs[7..13]
190 Added xq_make_checksum
191 Added rejection of multicast addresses in SET XQ MAC
192 08-Oct-02 DTH Beta 2 released; Integrated with 2.10-0p4
193 Added variable vector (fixes PDP11) and copyrights
194 03-Oct-02 DTH Beta version of xq/sim_ether released for SIMH 2.09-11
195 24-Sep-02 DTH Moved more code to Sim_Ether module, added SHOW ETH command
196 23-Sep-02 DTH Added SET/SHOW MAC command
197 22-Sep-02 DTH Multinet TCP/IP loaded, tests OK via SET HOST/TELNET
198 20-Sep-02 DTH Cleaned up code fragments, fixed non-DECNET MAC use
199 19-Sep-02 DTH DECNET finally stays up; successful SET HOST to another node
200 15-Sep-02 DTH Added ethernet packet read/write
201 13-Sep-02 DTH DECNET starts, but circuit keeps going up & down
202 26-Aug-02 DTH DECNET loaded, returns device timeout
203 22-Aug-02 DTH VMS 7.2 recognizes device as XQA0
204 18-Aug-02 DTH VAX sees device as XQA0; shows hardcoded MAC correctly
205 15-Aug-02 DTH Started XQ simulation
206
207 ------------------------------------------------------------------------------
208 */
209
210 #include <assert.h>
211 #include "pdp11_xq.h"
212 #include "pdp11_xq_bootrom.h"
213
214 extern int32 tmxr_poll;
215 extern FILE* sim_deb;
216 extern char* read_line (char *ptr, int32 size, FILE *stream);
217
218 /* forward declarations */
219 t_stat xq_rd(int32* data, int32 PA, int32 access);
220 t_stat xq_wr(int32 data, int32 PA, int32 access);
221 t_stat xq_svc(UNIT * uptr);
222 t_stat xq_reset (DEVICE * dptr);
223 t_stat xq_attach (UNIT * uptr, char * cptr);
224 t_stat xq_detach (UNIT * uptr);
225 t_stat xq_showmac (FILE* st, UNIT* uptr, int32 val, void* desc);
226 t_stat xq_setmac (UNIT* uptr, int32 val, char* cptr, void* desc);
227 t_stat xq_show_filters (FILE* st, UNIT* uptr, int32 val, void* desc);
228 t_stat xq_show_stats (FILE* st, UNIT* uptr, int32 val, void* desc);
229 t_stat xq_set_stats (UNIT* uptr, int32 val, char* cptr, void* desc);
230 t_stat xq_show_type (FILE* st, UNIT* uptr, int32 val, void* desc);
231 t_stat xq_set_type (UNIT* uptr, int32 val, char* cptr, void* desc);
232 t_stat xq_show_sanity (FILE* st, UNIT* uptr, int32 val, void* desc);
233 t_stat xq_set_sanity (UNIT* uptr, int32 val, char* cptr, void* desc);
234 t_stat xq_show_poll (FILE* st, UNIT* uptr, int32 val, void* desc);
235 t_stat xq_set_poll (UNIT* uptr, int32 val, char* cptr, void* desc);
236 t_stat xq_process_xbdl(CTLR* xq);
237 t_stat xq_dispatch_xbdl(CTLR* xq);
238 void xq_start_receiver(void);
239 void xq_sw_reset(CTLR* xq);
240 t_stat xq_ex (t_value *vptr, t_addr addr, UNIT *uptr, int32 sw);
241 t_stat xq_dep (t_value val, t_addr addr, UNIT *uptr, int32 sw);
242 void xq_reset_santmr(CTLR* xq);
243 t_stat xq_boot_host(CTLR* xq);
244 t_stat xq_system_id(CTLR* xq, const ETH_MAC dst, uint16 receipt_id);
245 void xqa_read_callback(int status);
246 void xqb_read_callback(int status);
247 void xqa_write_callback(int status);
248 void xqb_write_callback(int status);
249 void xq_setint (CTLR* xq);
250 void xq_clrint (CTLR* xq);
251 int32 xq_int (void);
252 void xq_csr_set_clr(CTLR* xq, uint16 set_bits, uint16 clear_bits);
253
254 struct xq_device xqa = {
255 xqa_read_callback, /* read callback routine */
256 xqa_write_callback, /* write callback routine */
257 {0x08, 0x00, 0x2B, 0xAA, 0xBB, 0xCC}, /* mac */
258 XQ_T_DELQA, /* type */
259 XQ_SERVICE_INTERVAL, /* poll */
260 {0} /* sanity */
261 };
262
263 struct xq_device xqb = {
264 xqb_read_callback, /* read callback routine */
265 xqb_write_callback, /* write callback routine */
266 {0x08, 0x00, 0x2B, 0xBB, 0xCC, 0xDD}, /* mac */
267 XQ_T_DELQA, /* type */
268 XQ_SERVICE_INTERVAL, /* poll */
269 {0} /* sanity */
270 };
271
272 /* SIMH device structures */
273 DIB xqa_dib = { IOBA_XQ, IOLN_XQ, &xq_rd, &xq_wr,
274 1, IVCL (XQ), 0, { &xq_int } };
275
276 UNIT xqa_unit[] = {
277 { UDATA (&xq_svc, UNIT_IDLE|UNIT_ATTABLE|UNIT_DISABLE, 2047) }, /* receive timer */
278 };
279
280 REG xqa_reg[] = {
281 { GRDATA ( SA0, xqa.addr[0], XQ_RDX, 8, 0), REG_RO|REG_FIT},
282 { GRDATA ( SA1, xqa.addr[1], XQ_RDX, 8, 0), REG_RO|REG_FIT},
283 { GRDATA ( SA2, xqa.addr[2], XQ_RDX, 8, 0), REG_RO|REG_FIT},
284 { GRDATA ( SA3, xqa.addr[3], XQ_RDX, 8, 0), REG_RO|REG_FIT},
285 { GRDATA ( SA4, xqa.addr[4], XQ_RDX, 8, 0), REG_RO|REG_FIT},
286 { GRDATA ( SA5, xqa.addr[5], XQ_RDX, 8, 0), REG_RO|REG_FIT},
287 { GRDATA ( RBDL, xqa.rbdl[0], XQ_RDX, 16, 0), REG_FIT },
288 { GRDATA ( RBDH, xqa.rbdl[1], XQ_RDX, 16, 0), REG_FIT },
289 { GRDATA ( XBDL, xqa.xbdl[0], XQ_RDX, 16, 0), REG_FIT },
290 { GRDATA ( XBDH, xqa.xbdl[1], XQ_RDX, 16, 0), REG_FIT },
291 { GRDATA ( VAR, xqa.var, XQ_RDX, 16, 0), REG_FIT },
292 { GRDATA ( CSR, xqa.csr, XQ_RDX, 16, 0), REG_FIT },
293 { FLDATA ( INT, xqa.irq, 0) },
294 { GRDATA ( SETUP_PRM, xqa.setup.promiscuous, XQ_RDX, 32, 0), REG_HRO},
295 { GRDATA ( SETUP_MLT, xqa.setup.multicast, XQ_RDX, 32, 0), REG_HRO},
296 { GRDATA ( SETUP_L1, xqa.setup.l1, XQ_RDX, 32, 0), REG_HRO},
297 { GRDATA ( SETUP_L2, xqa.setup.l2, XQ_RDX, 32, 0), REG_HRO},
298 { GRDATA ( SETUP_L3, xqa.setup.l3, XQ_RDX, 32, 0), REG_HRO},
299 { GRDATA ( SETUP_SAN, xqa.setup.sanity_timer, XQ_RDX, 32, 0), REG_HRO},
300 { BRDATA ( SETUP_MACS, &xqa.setup.macs, XQ_RDX, 8, sizeof(xqa.setup.macs)), REG_HRO},
301 { NULL },
302 };
303
304 DIB xqb_dib = { IOBA_XQB, IOLN_XQB, &xq_rd, &xq_wr,
305 1, IVCL (XQ), 0, { &xq_int } };
306
307 UNIT xqb_unit[] = {
308 { UDATA (&xq_svc, UNIT_IDLE|UNIT_ATTABLE|UNIT_DISABLE, 2047) }, /* receive timer */
309 };
310
311 REG xqb_reg[] = {
312 { GRDATA ( SA0, xqb.addr[0], XQ_RDX, 8, 0), REG_RO|REG_FIT},
313 { GRDATA ( SA1, xqb.addr[1], XQ_RDX, 8, 0), REG_RO|REG_FIT},
314 { GRDATA ( SA2, xqb.addr[2], XQ_RDX, 8, 0), REG_RO|REG_FIT},
315 { GRDATA ( SA3, xqb.addr[3], XQ_RDX, 8, 0), REG_RO|REG_FIT},
316 { GRDATA ( SA4, xqb.addr[4], XQ_RDX, 8, 0), REG_RO|REG_FIT},
317 { GRDATA ( SA5, xqb.addr[5], XQ_RDX, 8, 0), REG_RO|REG_FIT},
318 { GRDATA ( RBDL, xqb.rbdl[0], XQ_RDX, 16, 0), REG_FIT },
319 { GRDATA ( RBDH, xqb.rbdl[1], XQ_RDX, 16, 0), REG_FIT },
320 { GRDATA ( XBDL, xqb.xbdl[0], XQ_RDX, 16, 0), REG_FIT },
321 { GRDATA ( XBDH, xqb.xbdl[1], XQ_RDX, 16, 0), REG_FIT },
322 { GRDATA ( VAR, xqb.var, XQ_RDX, 16, 0), REG_FIT },
323 { GRDATA ( CSR, xqb.csr, XQ_RDX, 16, 0), REG_FIT },
324 { FLDATA ( INT, xqb.irq, 0) },
325 { GRDATA ( SETUP_PRM, xqb.setup.promiscuous, XQ_RDX, 32, 0), REG_HRO},
326 { GRDATA ( SETUP_MLT, xqb.setup.multicast, XQ_RDX, 32, 0), REG_HRO},
327 { GRDATA ( SETUP_L1, xqb.setup.l1, XQ_RDX, 32, 0), REG_HRO},
328 { GRDATA ( SETUP_L2, xqb.setup.l2, XQ_RDX, 32, 0), REG_HRO},
329 { GRDATA ( SETUP_L3, xqb.setup.l3, XQ_RDX, 32, 0), REG_HRO},
330 { GRDATA ( SETUP_SAN, xqb.setup.sanity_timer, XQ_RDX, 32, 0), REG_HRO},
331 { BRDATA ( SETUP_MACS, &xqb.setup.macs, XQ_RDX, 8, sizeof(xqb.setup.macs)), REG_HRO},
332 { NULL },
333 };
334
335 MTAB xq_mod[] = {
336 { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", NULL,
337 NULL, &show_addr, NULL },
338 { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
339 NULL, &show_vec, NULL },
340 { MTAB_XTD | MTAB_VDV, 0, "MAC", "MAC=xx:xx:xx:xx:xx:xx",
341 &xq_setmac, &xq_showmac, NULL },
342 { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "ETH", "ETH",
343 NULL, &eth_show, NULL },
344 { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "FILTERS", "FILTERS",
345 NULL, &xq_show_filters, NULL },
346 { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "STATS", "STATS",
347 &xq_set_stats, &xq_show_stats, NULL },
348 { MTAB_XTD | MTAB_VDV, 0, "TYPE", "TYPE={DEQNA|DELQA}",
349 &xq_set_type, &xq_show_type, NULL },
350 { MTAB_XTD | MTAB_VDV, 0, "POLL", "POLL={DEFAULT|4..2500]",
351 &xq_set_poll, &xq_show_poll, NULL },
352 { MTAB_XTD | MTAB_VDV | MTAB_NMO, 0, "SANITY", "SANITY={ON|OFF}",
353 &xq_set_sanity, &xq_show_sanity, NULL },
354 { 0 },
355 };
356
357 DEBTAB xq_debug[] = {
358 {"TRACE", DBG_TRC},
359 {"CSR", DBG_CSR},
360 {"VAR", DBG_VAR},
361 {"WARN", DBG_WRN},
362 {"SETUP", DBG_SET},
363 {"SANITY", DBG_SAN},
364 {"REG", DBG_REG},
365 {"PACKET", DBG_PCK},
366 {"ETH", DBG_ETH},
367 {0}
368 };
369
370 DEVICE xq_dev = {
371 "XQ", xqa_unit, xqa_reg, xq_mod,
372 1, XQ_RDX, 11, 1, XQ_RDX, 16,
373 &xq_ex, &xq_dep, &xq_reset,
374 NULL, &xq_attach, &xq_detach,
375 &xqa_dib, DEV_DISABLE | DEV_QBUS | DEV_DEBUG,
376 0, xq_debug
377 };
378
379 DEVICE xqb_dev = {
380 "XQB", xqb_unit, xqb_reg, xq_mod,
381 1, XQ_RDX, 11, 1, XQ_RDX, 16,
382 &xq_ex, &xq_dep, &xq_reset,
383 NULL, &xq_attach, &xq_detach,
384 &xqb_dib, DEV_DISABLE | DEV_DIS | DEV_QBUS | DEV_DEBUG,
385 0, xq_debug
386 };
387
388 CTLR xq_ctrl[] = {
389 {&xq_dev, xqa_unit, &xqa_dib, &xqa}, /* XQA controller */
390 {&xqb_dev, xqb_unit, &xqb_dib, &xqb} /* XQB controller */
391 };
392
393 const char* const xq_recv_regnames[] = {
394 "MAC0", "MAC1", "MAC2", "MAC3", "MAC4", "MAC5", "VAR", "CSR"
395 };
396
397 const char* const xq_xmit_regnames[] = {
398 "", "", "RBDL-Lo", "RBDL-Hi", "XBDL-Lo", "XBDL-Hi", "VAR", "CSR"
399 };
400
401 const char* const xq_csr_bits[] = {
402 "RE", "SR", "NI", "BD", "XL", "RL", "IE", "XI",
403 "IL", "EL", "SE", "RR", "OK", "CA", "PE", "RI"
404 };
405
406 const char* const xq_var_bits[] = {
407 "ID", "RR", "V0", "V1", "V2", "V3", "V4", "V5",
408 "V6", "V7", "S1", "S2", "S3", "RS", "OS", "MS"
409 };
410
411 /* internal debugging routines */
412 void xq_debug_setup(CTLR* xq);
413
414 /*============================================================================*/
415
416 /* Multicontroller support */
417
418 CTLR* xq_unit2ctlr(UNIT* uptr)
419 {
420 unsigned int i,j;
421 for (i=0; i<XQ_MAX_CONTROLLERS; i++)
422 for (j=0; j<xq_ctrl[i].dev->numunits; j++)
423 if (&xq_ctrl[i].unit[j] == uptr)
424 return &xq_ctrl[i];
425 /* not found */
426 return 0;
427 }
428
429 CTLR* xq_dev2ctlr(DEVICE* dptr)
430 {
431 int i;
432 for (i=0; i<XQ_MAX_CONTROLLERS; i++)
433 if (xq_ctrl[i].dev == dptr)
434 return &xq_ctrl[i];
435 /* not found */
436 return 0;
437 }
438
439 CTLR* xq_pa2ctlr(uint32 PA)
440 {
441 int i;
442 for (i=0; i<XQ_MAX_CONTROLLERS; i++)
443 if ((PA >= xq_ctrl[i].dib->ba) && (PA < (xq_ctrl[i].dib->ba + xq_ctrl[i].dib->lnt)))
444 return &xq_ctrl[i];
445 /* not found */
446 return 0;
447 }
448
449 /*============================================================================*/
450
451 /* stop simh from reading non-existant unit data stream */
452 t_stat xq_ex (t_value* vptr, t_addr addr, UNIT* uptr, int32 sw)
453 {
454 /* on PDP-11, allow EX command to look at bootrom */
455 #ifdef VM_PDP11
456 if (addr <= sizeof(xq_bootrom)/2)
457 *vptr = xq_bootrom[addr];
458 else
459 *vptr = 0;
460 return SCPE_OK;
461 #else
462 return SCPE_NOFNC;
463 #endif
464 }
465
466 /* stop simh from writing non-existant unit data stream */
467 t_stat xq_dep (t_value val, t_addr addr, UNIT* uptr, int32 sw)
468 {
469 return SCPE_NOFNC;
470 }
471
472 t_stat xq_showmac (FILE* st, UNIT* uptr, int32 val, void* desc)
473 {
474 CTLR* xq = xq_unit2ctlr(uptr);
475 char buffer[20];
476
477 eth_mac_fmt((ETH_MAC*)xq->var->mac, buffer);
478 fprintf(st, "MAC=%s", buffer);
479 return SCPE_OK;
480 }
481
482 void xq_make_checksum(CTLR* xq)
483 {
484 /* checksum calculation routine detailed in vaxboot.zip/xqbtdrivr.mar */
485 uint32 checksum = 0;
486 const uint32 wmask = 0xFFFF;
487 int i;
488
489 for (i = 0; i < sizeof(ETH_MAC); i += 2) {
490 checksum <<= 1;
491 if (checksum > wmask)
492 checksum -= wmask;
493 checksum += (xq->var->mac[i] << 8) | xq->var->mac[i+1];
494 if (checksum > wmask)
495 checksum -= wmask;
496 }
497 if (checksum == wmask)
498 checksum = 0;
499
500 /* set checksum bytes */
501 xq->var->mac_checksum[0] = checksum & 0xFF;
502 xq->var->mac_checksum[1] = checksum >> 8;
503 }
504
505 t_stat xq_setmac (UNIT* uptr, int32 val, char* cptr, void* desc)
506 {
507 t_stat status;
508 CTLR* xq = xq_unit2ctlr(uptr);
509
510 if (!cptr) return SCPE_IERR;
511 if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
512 status = eth_mac_scan(&xq->var->mac, cptr);
513 if (status != SCPE_OK)
514 return status;
515
516 /* calculate mac checksum */
517 xq_make_checksum(xq);
518 return SCPE_OK;
519 }
520
521 t_stat xq_set_stats (UNIT* uptr, int32 val, char* cptr, void* desc)
522 {
523 /* this sets all ints in the stats structure to the integer passed */
524 CTLR* xq = xq_unit2ctlr(uptr);
525
526 if (cptr) {
527 /* set individual stats to passed parameter value */
528 int init = atoi(cptr);
529 int* stat_array = (int*) &xq->var->stats;
530 int elements = sizeof(struct xq_stats)/sizeof(int);
531 int i;
532 for (i=0; i<elements; i++)
533 stat_array[i] = init;
534 } else {
535 /* set stats to zero */
536 memset(&xq->var->stats, 0, sizeof(struct xq_stats));
537 }
538 return SCPE_OK;
539 }
540
541 t_stat xq_show_stats (FILE* st, UNIT* uptr, int32 val, void* desc)
542 {
543 char* fmt = " %-15s%d\n";
544 CTLR* xq = xq_unit2ctlr(uptr);
545
546 fprintf(st, "Ethernet statistics:\n");
547 fprintf(st, fmt, "Recv:", xq->var->stats.recv);
548 fprintf(st, fmt, "Filtered:", xq->var->stats.filter);
549 fprintf(st, fmt, "Xmit:", xq->var->stats.xmit);
550 fprintf(st, fmt, "Xmit Fail:", xq->var->stats.fail);
551 fprintf(st, fmt, "Runts:", xq->var->stats.runt);
552 fprintf(st, fmt, "Oversize:", xq->var->stats.giant);
553 fprintf(st, fmt, "Setup:", xq->var->stats.setup);
554 fprintf(st, fmt, "Loopback:", xq->var->stats.loop);
555 fprintf(st, fmt, "ReadQ high:", xq->var->ReadQ.high);
556 return SCPE_OK;
557 }
558
559 t_stat xq_show_filters (FILE* st, UNIT* uptr, int32 val, void* desc)
560 {
561 CTLR* xq = xq_unit2ctlr(uptr);
562 char buffer[20];
563 int i;
564
565 fprintf(st, "Filters:\n");
566 for (i=0; i<XQ_FILTER_MAX; i++) {
567 eth_mac_fmt((ETH_MAC*)xq->var->setup.macs[i], buffer);
568 fprintf(st, " [%2d]: %s\n", i, buffer);
569 };
570 if (xq->var->setup.multicast)
571 fprintf(st, "All Multicast Receive Mode\n");
572 if (xq->var->setup.promiscuous)
573 fprintf(st, "Promiscuous Receive Mode\n");
574 return SCPE_OK;
575 }
576
577 t_stat xq_show_type (FILE* st, UNIT* uptr, int32 val, void* desc)
578 {
579 CTLR* xq = xq_unit2ctlr(uptr);
580 fprintf(st, "type=");
581 switch (xq->var->type) {
582 case XQ_T_DEQNA: fprintf(st, "DEQNA"); break;
583 case XQ_T_DELQA: fprintf(st, "DELQA"); break;
584 }
585 return SCPE_OK;
586 }
587
588 t_stat xq_set_type (UNIT* uptr, int32 val, char* cptr, void* desc)
589 {
590 CTLR* xq = xq_unit2ctlr(uptr);
591 if (!cptr) return SCPE_IERR;
592 if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
593
594 /* this assumes that the parameter has already been upcased */
595 if (!strcmp(cptr, "DEQNA")) xq->var->type = XQ_T_DEQNA;
596 else if (!strcmp(cptr, "DELQA")) xq->var->type = XQ_T_DELQA;
597 else return SCPE_ARG;
598
599 return SCPE_OK;
600 }
601
602 t_stat xq_show_poll (FILE* st, UNIT* uptr, int32 val, void* desc)
603 {
604 CTLR* xq = xq_unit2ctlr(uptr);
605 fprintf(st, "poll=%d", xq->var->poll);
606 return SCPE_OK;
607 }
608
609 t_stat xq_set_poll (UNIT* uptr, int32 val, char* cptr, void* desc)
610 {
611 CTLR* xq = xq_unit2ctlr(uptr);
612 if (!cptr) return SCPE_IERR;
613 if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
614
615 /* this assumes that the parameter has already been upcased */
616 if (!strcmp(cptr, "DEFAULT"))
617 xq->var->poll = XQ_SERVICE_INTERVAL;
618 else {
619 int newpoll = 0;
620 sscanf(cptr, "%d", &newpoll);
621 if ((newpoll >= 4) && (newpoll <= 2500))
622 xq->var->poll = newpoll;
623 else
624 return SCPE_ARG;
625 }
626
627 return SCPE_OK;
628 }
629
630 t_stat xq_show_sanity (FILE* st, UNIT* uptr, int32 val, void* desc)
631 {
632 CTLR* xq = xq_unit2ctlr(uptr);
633
634 fprintf(st, "sanity=");
635 switch (xq->var->sanity.enabled) {
636 case 2: fprintf(st, "ON\n"); break;
637 default: fprintf(st, "OFF\n"); break;
638 }
639 return SCPE_OK;
640 }
641
642 t_stat xq_set_sanity (UNIT* uptr, int32 val, char* cptr, void* desc)
643 {
644 CTLR* xq = xq_unit2ctlr(uptr);
645 if (!cptr) return SCPE_IERR;
646 if (uptr->flags & UNIT_ATT) return SCPE_ALATT;
647
648 /* this assumes that the parameter has already been upcased */
649 if (!strcmp(cptr, "ON")) xq->var->sanity.enabled = 2;
650 else if (!strcmp(cptr, "OFF")) xq->var->sanity.enabled = 0;
651 else return SCPE_ARG;
652
653 return SCPE_OK;
654 }
655
656 /*============================================================================*/
657
658 t_stat xq_nxm_error(CTLR* xq)
659 {
660 const uint16 set_bits = XQ_CSR_NI | XQ_CSR_XI | XQ_CSR_XL | XQ_CSR_RL;
661 sim_debug(DBG_WRN, xq->dev, "Non Existent Memory Error!\n");
662
663 /* set NXM and associated bits in CSR */
664 xq_csr_set_clr(xq, set_bits , 0);
665 return SCPE_OK;
666 }
667
668 /*
669 ** write callback
670 */
671 void xq_write_callback (CTLR* xq, int status)
672 {
673 t_stat rstatus;
674 int32 wstatus;
675 const uint16 TDR = 100 + xq->var->write_buffer.len * 8; /* arbitrary value */
676 uint16 write_success[2] = {0};
677 uint16 write_failure[2] = {XQ_DSC_C};
678 write_success[1] = TDR & 0x03FF; /* Does TDR get set on successful packets ?? */
679 write_failure[1] = TDR & 0x03FF; /* TSW2<09:00> */
680
681 xq->var->stats.xmit += 1;
682 /* update write status words */
683 if (status == 0) { /* success */
684 wstatus = Map_WriteW(xq->var->xbdl_ba + 8, 4, write_success);
685 } else { /* failure */
686 sim_debug(DBG_WRN, xq->dev, "Packet Write Error!\n");
687 xq->var->stats.fail += 1;
688 wstatus = Map_WriteW(xq->var->xbdl_ba + 8, 4, write_failure);
689 }
690 if (wstatus) {
691 xq_nxm_error(xq);
692 return;
693 }
694
695 /* update csr */
696 xq_csr_set_clr(xq, XQ_CSR_XI, 0);
697
698 /* reset sanity timer */
699 xq_reset_santmr(xq);
700
701 /* clear write buffer */
702 xq->var->write_buffer.len = 0;
703
704 /* next descriptor (implicit) */
705 xq->var->xbdl_ba += 12;
706
707 /* finish processing xbdl */
708 rstatus = xq_process_xbdl(xq);
709 }
710
711 void xqa_write_callback (int status)
712 {
713 xq_write_callback(&xq_ctrl[0], status);
714 }
715
716 void xqb_write_callback (int status)
717 {
718 xq_write_callback(&xq_ctrl[1], status);
719 }
720
721 /* read registers: */
722 t_stat xq_rd(int32* data, int32 PA, int32 access)
723 {
724 CTLR* xq = xq_pa2ctlr(PA);
725 int index = (PA >> 1) & 07; /* word index */
726
727 sim_debug(DBG_REG, xq->dev, "xq_rd(PA=0x%08X [%s], access=%d)\n", PA, xq_recv_regnames[index], access);
728 switch (index) {
729 case 0:
730 case 1:
731 /* return checksum in external loopback mode */
732 if (xq->var->csr & XQ_CSR_EL)
733 *data = 0xFF00 | xq->var->mac_checksum[index];
734 else
735 *data = 0xFF00 | xq->var->mac[index];
736 break;
737 case 2:
738 case 3:
739 case 4:
740 case 5:
741 *data = 0xFF00 | xq->var->mac[index];
742 break;
743 case 6:
744 sim_debug_u16(DBG_VAR, xq->dev, xq_var_bits, xq->var->var, xq->var->var, 0);
745 sim_debug (DBG_VAR, xq->dev, ", vec = 0%o\n", (xq->var->var & XQ_VEC_IV));
746 *data = xq->var->var;
747 break;
748 case 7:
749 sim_debug_u16(DBG_CSR, xq->dev, xq_csr_bits, xq->var->csr, xq->var->csr, 1);
750 *data = xq->var->csr;
751 break;
752 }
753 return SCPE_OK;
754 }
755
756
757 /* dispatch ethernet read request
758 procedure documented in sec. 3.2.2 */
759
760 t_stat xq_process_rbdl(CTLR* xq)
761 {
762 int32 rstatus, wstatus;
763 uint16 b_length, w_length, rbl;
764 uint32 address;
765 ETH_ITEM* item;
766 uint8* rbuf;
767
768 sim_debug(DBG_TRC, xq->dev, "xq_process_rdbl\n");
769
770 /* process buffer descriptors */
771 while(1) {
772
773 /* get receive bdl from memory */
774 xq->var->rbdl_buf[0] = 0xFFFF;
775 wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0]);
776 rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1]);
777 if (rstatus || wstatus) return xq_nxm_error(xq);
778
779 /* invalid buffer? */
780 if (~xq->var->rbdl_buf[1] & XQ_DSC_V) {
781 xq_csr_set_clr(xq, XQ_CSR_RL, 0);
782 return SCPE_OK;
783 }
784
785 /* explicit chain buffer? */
786 if (xq->var->rbdl_buf[1] & XQ_DSC_C) {
787 xq->var->rbdl_ba = ((xq->var->rbdl_buf[1] & 0x3F) << 16) | xq->var->rbdl_buf[2];
788 continue;
789 }
790
791 /* stop processing if nothing in read queue */
792 if (!xq->var->ReadQ.count) break;
793
794 /* get status words */
795 rstatus = Map_ReadW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4]);
796 if (rstatus) return xq_nxm_error(xq);
797
798 /* get host memory address */
799 address = ((xq->var->rbdl_buf[1] & 0x3F) << 16) | xq->var->rbdl_buf[2];
800
801 /* decode buffer length - two's complement (in words) */
802 w_length = ~xq->var->rbdl_buf[3] + 1;
803 b_length = w_length * 2;
804 if (xq->var->rbdl_buf[1] & XQ_DSC_H) b_length -= 1;
805 if (xq->var->rbdl_buf[1] & XQ_DSC_L) b_length -= 1;
806
807 item = &xq->var->ReadQ.item[xq->var->ReadQ.head];
808 rbl = item->packet.len;
809 rbuf = item->packet.msg;
810
811 /* see if packet must be size-adjusted or is splitting */
812 if (item->packet.used) {
813 int used = item->packet.used;
814 rbl -= used;
815 rbuf = &item->packet.msg[used];
816 } else {
817 /* adjust runt packets */
818 if (rbl < ETH_MIN_PACKET) {
819 xq->var->stats.runt += 1;
820 sim_debug(DBG_WRN, xq->dev, "Runt detected, size = %d\n", rbl);
821 /* pad runts with zeros up to minimum size - this allows "legal" (size - 60)
822 processing of those weird short ARP packets that seem to occur occasionally */
823 memset(&item->packet.msg[rbl], 0, ETH_MIN_PACKET-rbl);
824 rbl = ETH_MIN_PACKET;
825 };
826
827 /* adjust oversized packets */
828 if (rbl > ETH_MAX_PACKET) {
829 xq->var->stats.giant += 1;
830 sim_debug(DBG_WRN, xq->dev, "Giant detected, size=%d\n", rbl);
831 /* trim giants down to maximum size - no documentation on how to handle the data loss */
832 item->packet.len = ETH_MAX_PACKET;
833 rbl = ETH_MAX_PACKET;
834 };
835 };
836
837 /* make sure entire packet fits in buffer - if not, will need to split into multiple buffers */
838 if (rbl > b_length)
839 rbl = b_length;
840 item->packet.used += rbl;
841
842 /* send data to host */
843 wstatus = Map_WriteB(address, rbl, rbuf);
844 if (wstatus) return xq_nxm_error(xq);
845
846 /* set receive size into RBL - RBL<10:8> maps into Status1<10:8>,
847 RBL<7:0> maps into Status2<7:0>, and Status2<15:8> (copy) */
848
849 xq->var->rbdl_buf[4] = 0;
850 switch (item->type) {
851 case 0: /* setup packet */
852 xq->var->stats.setup += 1;
853 xq->var->rbdl_buf[4] = 0x2700; /* set esetup and RBL 10:8 */
854 break;
855 case 1: /* loopback packet */
856 xq->var->stats.loop += 1;
857 xq->var->rbdl_buf[4] = 0x2000; /* loopback flag */
858 xq->var->rbdl_buf[4] |= (rbl & 0x0700); /* high bits of rbl */
859 break;
860 case 2: /* normal packet */
861 rbl -= 60; /* keeps max packet size in 11 bits */
862 xq->var->rbdl_buf[4] = (rbl & 0x0700); /* high bits of rbl */
863 break;
864 }
865 if (item->packet.used < item->packet.len)
866 xq->var->rbdl_buf[4] |= 0xC000; /* not last segment */
867 xq->var->rbdl_buf[5] = ((rbl & 0x00FF) << 8) | (rbl & 0x00FF);
868 if (xq->var->ReadQ.loss) {
869 sim_debug(DBG_WRN, xq->dev, "ReadQ overflow!\n");
870 xq->var->rbdl_buf[4] |= 0x0001; /* set overflow bit */
871 xq->var->ReadQ.loss = 0; /* reset loss counter */
872 }
873
874 /* update read status words*/
875 wstatus = Map_WriteW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4]);
876 if (wstatus) return xq_nxm_error(xq);
877
878 /* remove packet from queue */
879 if (item->packet.used >= item->packet.len)
880 ethq_remove(&xq->var->ReadQ);
881
882 /* mark transmission complete */
883 xq_csr_set_clr(xq, XQ_CSR_RI, 0);
884
885 /* set to next bdl (implicit chain) */
886 xq->var->rbdl_ba += 12;
887
888 } /* while */
889
890 return SCPE_OK;
891 }
892
893 t_stat xq_process_mop(CTLR* xq)
894 {
895 uint32 address;
896 uint16 size;
897 int32 wstatus;
898 struct xq_meb* meb = (struct xq_meb*) &xq->var->write_buffer.msg[0200];
899 const struct xq_meb* limit = (struct xq_meb*) &xq->var->write_buffer.msg[0400];
900
901 sim_debug(DBG_TRC, xq->dev, "xq_process_mop()\n");
902
903 if (xq->var->type == XQ_T_DEQNA) /* DEQNA's don't MOP */
904 return SCPE_NOFNC;
905
906 while ((meb->type != 0) && (meb < limit)) {
907 address = (meb->add_hi << 16) || (meb->add_mi << 8) || meb->add_lo;
908 size = (meb->siz_hi << 8) || meb->siz_lo;
909
910 /* MOP stuff here - NOT YET FULLY IMPLEMENTED */
911 sim_debug (DBG_WRN, xq->dev, "Processing MEB type: %d\n", meb->type);
912 switch (meb->type) {
913 case 0: /* MOP Termination */
914 break;
915 case 1: /* MOP Read Ethernet Address */
916 wstatus = Map_WriteB(address, sizeof(ETH_MAC), (uint8*) &xq->var->setup.macs[0]);
917 if (wstatus) return xq_nxm_error(xq);
918 break;
919 case 2: /* MOP Reset System ID */
920 break;
921 case 3: /* MOP Read Last MOP Boot */
922 break;
923 case 4: /* MOP Read Boot Password */
924 break;
925 case 5: /* MOP Write Boot Password */
926 break;
927 case 6: /* MOP Read System ID */
928 break;
929 case 7: /* MOP Write System ID */
930 break;
931 case 8: /* MOP Read Counters */
932 break;
933 case 9: /* Mop Read/Clear Counters */
934 break;
935 } /* switch */
936
937 /* process next meb */
938 meb += sizeof(struct xq_meb);
939
940 } /* while */
941 return SCPE_OK;
942 }
943
944 t_stat xq_process_setup(CTLR* xq)
945 {
946 int i,j;
947 int count = 0;
948 float secs;
949 t_stat status;
950 ETH_MAC zeros = {0, 0, 0, 0, 0, 0};
951 ETH_MAC filters[XQ_FILTER_MAX + 1];
952
953 sim_debug(DBG_TRC, xq->dev, "xq_process_setup()\n");
954
955 /* extract filter addresses from setup packet */
956 memset(xq->var->setup.macs, '\0', sizeof(xq->var->setup.macs));
957 for (i = 0; i < 7; i++)
958 for (j = 0; j < 6; j++) {
959 xq->var->setup.macs[i] [j] = xq->var->write_buffer.msg[(i + 01) + (j * 8)];
960 if (xq->var->write_buffer.len > 112)
961 xq->var->setup.macs[i+7][j] = xq->var->write_buffer.msg[(i + 0101) + (j * 8)];
962 }
963
964 /*
965 Under VMS the setup packet that is passed to turn promiscuous
966 off after it has been on doesn't seem to follow the rules documented
967 in both the DEQNA and DELQA manuals.
968 These rules seem to say that setup packets less than 128 should only
969 modify the address filter set and probably not the All-Multicast and
970 Promiscuous modes, however, VMS V5-5 and V7.3 seem to send a 127 byte
971 packet to turn this functionality off. I'm not sure how real hardware
972 behaves in this case, since the only consequence is extra interrupt
973 load. To realize and retain the benefits of the newly added BPF
974 functionality in sim_ether, I've modified the logic implemented here
975 to disable Promiscuous mode when a "small" setup packet is processed.
976 I'm deliberately not modifying the All-Multicast mode the same way
977 since I don't have an observable case of its behavior. These two
978 different modes come from very different usage situations:
979 1) Promiscuous mode is usually entered for relatively short periods
980 of time due to the needs of a specific application program which
981 is doing some sort of management/monitoring function (i.e. tcpdump)
982 2) All-Multicast mode is only entered by the OS Kernel Port Driver
983 when it happens to have clients (usually network stacks or service
984 programs) which as a group need to listen to more multicast ethernet
985 addresses than the 12 (or so) which the hardware supports directly.
986 so, I believe that the All-Multicast mode, is first rarely used, and if
987 it ever is used, once set, it will probably be set either forever or for
988 long periods of time, and the additional interrupt processing load to
989 deal with the distinctly lower multicast traffic set is clearly lower than
990 that of the promiscuous mode.
991 */
992 xq->var->setup.promiscuous = 0;
993 /* process high byte count */
994 if (xq->var->write_buffer.len > 128) {
995 uint16 len = xq->var->write_buffer.len;
996 uint16 led, san;
997
998 xq->var->setup.multicast = (0 != (len & XQ_SETUP_MC));
999 xq->var->setup.promiscuous = (0 != (len & XQ_SETUP_PM));
1000 if (led = (len & XQ_SETUP_LD) >> 2) {
1001 switch (led) {
1002 case 1: xq->var->setup.l1 = 0; break;
1003 case 2: xq->var->setup.l2 = 0; break;
1004 case 3: xq->var->setup.l3 = 0; break;
1005 } /* switch */
1006 } /* if led */
1007
1008 /* set sanity timer timeout */
1009 san = (len & XQ_SETUP_ST) >> 4;
1010 switch(san) {
1011 case 0: secs = 0.25; break; /* 1/4 second */
1012 case 1: secs = 1; break; /* 1 second */
1013 case 2: secs = 4; break; /* 4 seconds */
1014 case 3: secs = 16; break; /* 16 seconds */
1015 case 4: secs = 1 * 60; break; /* 1 minute */
1016 case 5: secs = 4 * 60; break; /* 4 minutes */
1017 case 6: secs = 16 * 60; break; /* 16 minutes */
1018 case 7: secs = 64 * 60; break; /* 64 minutes */
1019 }
1020 xq->var->sanity.quarter_secs = (int) (secs * 4);
1021 xq->var->sanity.max = (int) (secs * xq->var->poll);
1022 }
1023
1024 /* finalize sanity timer state */
1025 xq->var->sanity.timer = xq->var->sanity.max;
1026 if (xq->var->sanity.enabled != 2) {
1027 if (xq->var->csr & XQ_CSR_SE)
1028 xq->var->sanity.enabled = 1;
1029 else
1030 xq->var->sanity.enabled = 0;
1031 }
1032
1033 /* set ethernet filter */
1034 /* memcpy (filters[count++], xq->mac, sizeof(ETH_MAC)); */
1035 for (i = 0; i < XQ_FILTER_MAX; i++)
1036 if (memcmp(zeros, &xq->var->setup.macs[i], sizeof(ETH_MAC)))
1037 memcpy (filters[count++], xq->var->setup.macs[i], sizeof(ETH_MAC));
1038 status = eth_filter (xq->var->etherface, count, filters, xq->var->setup.multicast, xq->var->setup.promiscuous);
1039
1040 /* process MOP information */
1041 if (xq->var->write_buffer.msg[0])
1042 status = xq_process_mop(xq);
1043
1044 /* mark setup block valid */
1045 xq->var->setup.valid = 1;
1046
1047 if (sim_deb && (xq->dev->dctrl & DBG_SET))
1048 xq_debug_setup(xq);
1049 return SCPE_OK;
1050 }
1051
1052 /*
1053 Dispatch Write Operation
1054
1055 The DELQA manual does not explicitly state whether or not multiple packets
1056 can be written in one transmit operation, so a maximum of 1 packet is assumed.
1057
1058 */
1059 t_stat xq_process_xbdl(CTLR* xq)
1060 {
1061 const uint16 implicit_chain_status[2] = {XQ_DSC_V | XQ_DSC_C, 1};
1062 const uint16 write_success[2] = {0, 1 /*Non-Zero TDR*/};
1063 uint16 b_length, w_length;
1064 int32 rstatus, wstatus;
1065 uint32 address;
1066 t_stat status;
1067
1068 sim_debug(DBG_TRC, xq->dev, "xq_process_xbdl()\n");
1069
1070 /* clear write buffer */
1071 xq->var->write_buffer.len = 0;
1072
1073 /* process buffer descriptors until not valid */
1074 while (1) {
1075
1076 /* Get transmit bdl from memory */
1077 rstatus = Map_ReadW (xq->var->xbdl_ba, 12, &xq->var->xbdl_buf[0]);
1078 xq->var->xbdl_buf[0] = 0xFFFF;
1079 wstatus = Map_WriteW(xq->var->xbdl_ba, 2, &xq->var->xbdl_buf[0]);
1080 if (rstatus || wstatus) return xq_nxm_error(xq);
1081
1082 /* invalid buffer? */
1083 if (~xq->var->xbdl_buf[1] & XQ_DSC_V) {
1084 xq_csr_set_clr(xq, XQ_CSR_XL, 0);
1085 sim_debug(DBG_WRN, xq->dev, "XBDL List empty\n");
1086 return SCPE_OK;
1087 }
1088
1089 /* compute host memory address */
1090 address = ((xq->var->xbdl_buf[1] & 0x3F) << 16) | xq->var->xbdl_buf[2];
1091
1092 /* decode buffer length - two's complement (in words) */
1093 w_length = ~xq->var->xbdl_buf[3] + 1;
1094 b_length = w_length * 2;
1095 if (xq->var->xbdl_buf[1] & XQ_DSC_H) b_length -= 1;
1096 if (xq->var->xbdl_buf[1] & XQ_DSC_L) b_length -= 1;
1097
1098 /* explicit chain buffer? */
1099 if (xq->var->xbdl_buf[1] & XQ_DSC_C) {
1100 xq->var->xbdl_ba = address;
1101 sim_debug(DBG_WRN, xq->dev, "XBDL chained buffer encountered: %d\n", b_length);
1102 continue;
1103 }
1104
1105 /* add to transmit buffer, making sure it's not too big */
1106 if ((xq->var->write_buffer.len + b_length) > sizeof(xq->var->write_buffer.msg))
1107 b_length = sizeof(xq->var->write_buffer.msg) - xq->var->write_buffer.len;
1108 rstatus = Map_ReadB(address, b_length, &xq->var->write_buffer.msg[xq->var->write_buffer.len]);
1109 if (rstatus) return xq_nxm_error(xq);
1110 xq->var->write_buffer.len += b_length;
1111
1112 /* end of message? */
1113 if (xq->var->xbdl_buf[1] & XQ_DSC_E) {
1114 if (((~xq->var->csr & XQ_CSR_RE) && ((~xq->var->csr & XQ_CSR_IL) || (xq->var->csr & XQ_CSR_EL))) || /* loopback */
1115 (xq->var->xbdl_buf[1] & XQ_DSC_S)) { /* or setup packet (forces loopback regardless of state) */
1116 if (xq->var->xbdl_buf[1] & XQ_DSC_S) { /* setup packet */
1117 status = xq_process_setup(xq);
1118
1119 /* put packet in read buffer */
1120 ethq_insert (&xq->var->ReadQ, 0, &xq->var->write_buffer, status);
1121 } else { /* loopback */
1122 /* put packet in read buffer */
1123 ethq_insert (&xq->var->ReadQ, 1, &xq->var->write_buffer, 0);
1124 }
1125
1126 /* update write status */
1127 wstatus = Map_WriteW(xq->var->xbdl_ba + 8, 4, (uint16*) write_success);
1128 if (wstatus) return xq_nxm_error(xq);
1129
1130 /* clear write buffer */
1131 xq->var->write_buffer.len = 0;
1132
1133 /* reset sanity timer */
1134 xq_reset_santmr(xq);
1135
1136 /* mark transmission complete */
1137 xq_csr_set_clr(xq, XQ_CSR_XI, 0);
1138
1139 /* now trigger "read" of setup or loopback packet */
1140 if (~xq->var->csr & XQ_CSR_RL)
1141 status = xq_process_rbdl(xq);
1142
1143 } else { /* not loopback */
1144
1145 status = eth_write(xq->var->etherface, &xq->var->write_buffer, xq->var->wcallback);
1146 if (status != SCPE_OK) /* not implemented or unattached */
1147 xq_write_callback(xq, 1); /* fake failure */
1148 #if 0
1149 else
1150 xq_svc(&xq->unit[0]); /* service any received data */
1151 #endif
1152 sim_debug(DBG_WRN, xq->dev, "XBDL completed processing write\n");
1153 return SCPE_OK;
1154
1155 } /* loopback/non-loopback */
1156 } else { /* not at end-of-message */
1157
1158 sim_debug(DBG_WRN, xq->dev, "XBDL processing implicit chain buffer segment\n");
1159 /* update bdl status words */
1160 wstatus = Map_WriteW(xq->var->xbdl_ba + 8, 4, (uint16*) implicit_chain_status);
1161 if(wstatus) return xq_nxm_error(xq);
1162 }
1163
1164 /* set to next bdl (implicit chain) */
1165 xq->var->xbdl_ba += 12;
1166
1167 } /* while */
1168 }
1169
1170 t_stat xq_dispatch_rbdl(CTLR* xq)
1171 {
1172 int i;
1173 int32 rstatus, wstatus;
1174 t_stat status;
1175
1176 sim_debug(DBG_TRC, xq->dev, "xq_dispatch_rbdl()\n");
1177
1178 /* mark receive bdl valid */
1179 xq_csr_set_clr(xq, 0, XQ_CSR_RL);
1180
1181 /* init receive bdl buffer */
1182 for (i=0; i<6; i++)
1183 xq->var->rbdl_buf[i] = 0;
1184
1185 /* get address of first receive buffer */
1186 xq->var->rbdl_ba = ((xq->var->rbdl[1] & 0x3F) << 16) | (xq->var->rbdl[0] & ~01);
1187
1188 /* get first receive buffer */
1189 xq->var->rbdl_buf[0] = 0xFFFF;
1190 wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0]);
1191 rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1]);
1192 if (rstatus || wstatus) return xq_nxm_error(xq);
1193
1194 /* is buffer valid? */
1195 if (~xq->var->rbdl_buf[1] & XQ_DSC_V) {
1196 xq_csr_set_clr(xq, XQ_CSR_RL, 0);
1197 return SCPE_OK;
1198 }
1199
1200 /* process any waiting packets in receive queue */
1201 if (xq->var->ReadQ.count)
1202 status = xq_process_rbdl(xq);
1203
1204 return SCPE_OK;
1205 }
1206
1207 t_stat xq_dispatch_xbdl(CTLR* xq)
1208 {
1209 int i;
1210 t_stat status;
1211
1212 sim_debug(DBG_TRC, xq->dev, "xq_dispatch_xbdl()\n");
1213
1214 /* mark transmit bdl valid */
1215 xq_csr_set_clr(xq, 0, XQ_CSR_XL);
1216
1217 /* initialize transmit bdl buffers */
1218 for (i=0; i<6; i++)
1219 xq->var->xbdl_buf[i] = 0;
1220
1221 /* clear transmit buffer */
1222 xq->var->write_buffer.len = 0;
1223
1224 /* get base address of first transmit descriptor */
1225 xq->var->xbdl_ba = ((xq->var->xbdl[1] & 0x3F) << 16) | (xq->var->xbdl[0] & ~01);
1226
1227 /* process xbdl */
1228 status = xq_process_xbdl(xq);
1229
1230 return status;
1231 }
1232
1233 t_stat xq_process_loopback(CTLR* xq, ETH_PACK* pack)
1234 {
1235 ETH_PACK reply;
1236 ETH_MAC physical_address;
1237 t_stat status;
1238 int offset = pack->msg[14] | (pack->msg[15] << 8);
1239 int function = pack->msg[offset] | (pack->msg[offset+1] << 8);
1240
1241 sim_debug(DBG_TRC, xq->dev, "xq_process_loopback()\n");
1242
1243 if (function != 2 /*forward*/)
1244 return SCPE_NOFNC;
1245
1246 /* create reply packet */
1247 memcpy (&reply, pack, sizeof(ETH_PACK));
1248 memcpy (physical_address, xq->var->setup.valid ? xq->var->setup.macs[0] : xq->var->mac, sizeof(ETH_MAC));
1249 memcpy (&reply.msg[0], &reply.msg[offset+2], sizeof(ETH_MAC));
1250 memcpy (&reply.msg[6], physical_address, sizeof(ETH_MAC));
1251 memcpy (&reply.msg[offset+2], physical_address, sizeof(ETH_MAC));
1252 reply.msg[offset] = 0x01;
1253 offset += 8;
1254 reply.msg[14] = offset & 0xFF;
1255 reply.msg[15] = (offset >> 8) & 0xFF;
1256
1257 /* send reply packet */
1258 status = eth_write(xq->var->etherface, &reply, NULL);
1259
1260 return status;
1261 }
1262
1263 t_stat xq_process_remote_console (CTLR* xq, ETH_PACK* pack)
1264 {
1265 t_stat status;
1266 ETH_MAC source;
1267 uint16 receipt;
1268 int code = pack->msg[16];
1269
1270 sim_debug(DBG_TRC, xq->dev, "xq_process_remote_console()\n");
1271
1272 switch (code) {
1273 case 0x05: /* request id */
1274 receipt = pack->msg[18] | (pack->msg[19] << 8);
1275 memcpy(source, &pack->msg[6], sizeof(ETH_MAC));
1276
1277 /* send system id to requestor */
1278 status = xq_system_id (xq, source, receipt);
1279 return status;
1280 break;
1281 case 0x06: /* boot */
1282 /*
1283 NOTE: the verification field should be checked here against the
1284 verification value established in the setup packet. If they match the
1285 reboot should occur, otherwise nothing happens, and the packet
1286 is passed on to the host.
1287
1288 Verification is not implemented, since the setup packet processing code
1289 isn't complete yet.
1290
1291 Various values are also passed: processor, control, and software id.
1292 These control the various boot parameters, however SIMH does not
1293 have a mechanism to pass these to the host, so just reboot.
1294 */
1295
1296 status = xq_boot_host(xq);
1297 return status;
1298 break;
1299 } /* switch */
1300
1301 return SCPE_NOFNC;
1302 }
1303
1304 t_stat xq_process_local (CTLR* xq, ETH_PACK* pack)
1305 {
1306 /* returns SCPE_OK if local processing occurred,
1307 otherwise returns SCPE_NOFNC or some other code */
1308 int protocol;
1309
1310 sim_debug(DBG_TRC, xq->dev, "xq_process_local()\n");
1311 /* DEQNA's have no local processing capability */
1312 if (xq->var->type == XQ_T_DEQNA)
1313 return SCPE_NOFNC;
1314
1315 protocol = pack->msg[12] | (pack->msg[13] << 8);
1316 switch (protocol) {
1317 case 0x0090: /* ethernet loopback */
1318 return xq_process_loopback(xq, pack);
1319 break;
1320 case 0x0260: /* MOP remote console */
1321 return xq_process_remote_console(xq, pack);
1322 break;
1323 }
1324 return SCPE_NOFNC;
1325 }
1326
1327 void xq_read_callback(CTLR* xq, int status)
1328 {
1329 xq->var->stats.recv += 1;
1330 if (xq->var->csr & XQ_CSR_RE) { /* receiver enabled */
1331
1332 /* process any packets locally that can be */
1333 t_stat status = xq_process_local (xq, &xq->var->read_buffer);
1334
1335 /* add packet to read queue */
1336 if (status != SCPE_OK)
1337 ethq_insert(&xq->var->ReadQ, 2, &xq->var->read_buffer, status);
1338 } else {
1339 sim_debug(DBG_WRN, xq->dev, "packet received with receiver disabled\n");
1340 }
1341 }
1342
1343 void xqa_read_callback(int status)
1344 {
1345 xq_read_callback(&xq_ctrl[0], status);
1346 }
1347
1348 void xqb_read_callback(int status)
1349 {
1350 xq_read_callback(&xq_ctrl[1], status);
1351 }
1352
1353 void xq_sw_reset(CTLR* xq)
1354 {
1355 const uint16 set_bits = XQ_CSR_XL | XQ_CSR_RL;
1356 int i;
1357
1358 sim_debug(DBG_TRC, xq->dev, "xq_sw_reset()\n");
1359
1360 /* reset csr bits */
1361 xq_csr_set_clr(xq, set_bits, (uint16) ~set_bits);
1362
1363 if (xq->var->etherface)
1364 xq_csr_set_clr(xq, XQ_CSR_OK, 0);
1365
1366 /* clear interrupt unconditionally */
1367 xq_clrint(xq);
1368
1369 /* flush read queue */
1370 ethq_clear(&xq->var->ReadQ);
1371
1372 /* clear setup info */
1373 xq->var->setup.multicast = 0;
1374 xq->var->setup.promiscuous = 0;
1375 if (xq->var->etherface) {
1376 int count = 0;
1377 ETH_MAC zeros = {0, 0, 0, 0, 0, 0};
1378 ETH_MAC filters[XQ_FILTER_MAX + 1];
1379
1380 /* set ethernet filter */
1381 /* memcpy (filters[count++], xq->mac, sizeof(ETH_MAC)); */
1382 for (i = 0; i < XQ_FILTER_MAX; i++)
1383 if (memcmp(zeros, &xq->var->setup.macs[i], sizeof(ETH_MAC)))
1384 memcpy (filters[count++], xq->var->setup.macs[i], sizeof(ETH_MAC));
1385 eth_filter (xq->var->etherface, count, filters, xq->var->setup.multicast, xq->var->setup.promiscuous);
1386 }
1387 }
1388
1389 /* write registers: */
1390
1391 t_stat xq_wr_var(CTLR* xq, int32 data)
1392 {
1393 uint16 save_var = xq->var->var;
1394 sim_debug(DBG_REG, xq->dev, "xq_wr_var(data= 0x%08X\n", data);
1395
1396 switch (xq->var->type) {
1397 case XQ_T_DEQNA:
1398 xq->var->var = (data & XQ_VEC_IV);
1399 break;
1400 case XQ_T_DELQA:
1401 xq->var->var = (xq->var->var & XQ_VEC_RO) | (data & XQ_VEC_RW);
1402
1403 /* if switching to DEQNA-LOCK mode clear VAR<14:10> */
1404 if (~xq->var->var & XQ_VEC_MS)
1405 xq->var->var &= ~(XQ_VEC_OS | XQ_VEC_RS | XQ_VEC_ST);
1406 break;
1407 }
1408
1409 /* set vector of SIMH device */
1410 if (data & XQ_VEC_IV)
1411 xq->dib->vec = (data & XQ_VEC_IV) + VEC_Q;
1412 else
1413 xq->dib->vec = 0;
1414
1415 sim_debug_u16(DBG_VAR, xq->dev, xq_var_bits, save_var, xq->var->var, 1);
1416
1417 return SCPE_OK;
1418 }
1419
1420 #ifdef VM_PDP11
1421 t_stat xq_process_bootrom (CTLR* xq)
1422 {
1423 /*
1424 NOTE: BOOT ROMs are a PDP-11ism, since they contain PDP-11 binary code.
1425 the host is responsible for creating two *2KB* receive buffers.
1426
1427 RSTS/E v10.1 source (INIONE.MAR/XHLOOK:) indicates that both the DEQNA and
1428 DELQA will set receive status word 1 bits 15 & 14 on both packets. It also
1429 states that a hardware bug in the DEQNA will set receive status word 1 bit 15
1430 (only) in the *third* receive buffer (oops!).
1431
1432 RSTS/E v10.1 will run the Citizenship test from the bootrom after loading it.
1433 Documentation on the Boot ROM can be found in INIQNA.MAR.
1434 */
1435
1436 int32 rstatus, wstatus;
1437 uint16 b_length, w_length;
1438 uint32 address;
1439 uint8* bootrom = (uint8*) xq_bootrom;
1440 int i, checksum;
1441
1442 sim_debug(DBG_TRC, xq->dev, "xq_process_bootrom()\n");
1443
1444 /*
1445 RSTS/E v10.1 invokes the Citizenship tests in the Bootrom. For some
1446 reason, the current state of the XQ emulator cannot pass these. So,
1447 to get moving on RSTE/E support, we will replace the following line in
1448 INIQNA.MAR/CITQNA::
1449 70$: MOV (R2),R0 ;get the status word
1450 with
1451 70$: CLR R0 ;force success
1452 to cause the Citizenship test to return success to RSTS/E.
1453
1454 At some point, the real problem (failure to pass citizenship diagnostics)
1455 does need to be corrected to find incompatibilities in the emulation, and to
1456 ultimately allow it to pass Digital hardware diagnostic tests.
1457 */
1458 for (i=0; i<sizeof(xq_bootrom)/2; i++)
1459 if (xq_bootrom[i] == 011200) { /* MOV (R2),R0 */
1460 xq_bootrom[i] = 005000; /* CLR R0 */
1461 break;
1462 }
1463
1464 /* recalculate checksum, which is a simple byte sum */
1465 for (i=0, checksum=0; i<sizeof(xq_bootrom)-2; i++)
1466 checksum += bootrom[i];
1467
1468 /* set new checksum */
1469 xq_bootrom[sizeof(xq_bootrom)/2-1] = checksum;
1470
1471 /* --------------------------- bootrom part 1 -----------------------------*/
1472
1473 /* get receive bdl from memory */
1474 xq->var->rbdl_buf[0] = 0xFFFF;
1475 wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0]);
1476 rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1]);
1477 if (rstatus || wstatus) return xq_nxm_error(xq);
1478
1479 /* invalid buffer? */
1480 if (~xq->var->rbdl_buf[1] & XQ_DSC_V) {
1481 xq_csr_set_clr(xq, XQ_CSR_RL, 0);
1482 return SCPE_OK;
1483 }
1484
1485 /* get status words */
1486 rstatus = Map_ReadW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4]);
1487 if (rstatus) return xq_nxm_error(xq);
1488
1489 /* get host memory address */
1490 address = ((xq->var->rbdl_buf[1] & 0x3F) << 16) | xq->var->rbdl_buf[2];
1491
1492 /* decode buffer length - two's complement (in words) */
1493 w_length = ~xq->var->rbdl_buf[3] + 1;
1494 b_length = w_length * 2;
1495 if (xq->var->rbdl_buf[1] & XQ_DSC_H) b_length -= 1;
1496 if (xq->var->rbdl_buf[1] & XQ_DSC_L) b_length -= 1;
1497
1498 /* make sure entire packet fits in buffer */
1499 assert(b_length >= sizeof(xq_bootrom)/2);
1500
1501 /* send data to host */
1502 wstatus = Map_WriteB(address, sizeof(xq_bootrom)/2, bootrom);
1503 if (wstatus) return xq_nxm_error(xq);
1504
1505 /* update read status words */
1506 xq->var->rbdl_buf[4] = XQ_DSC_V | XQ_DSC_C; /* valid, chain */
1507 xq->var->rbdl_buf[5] = 0;
1508
1509 /* update read status words*/
1510 wstatus = Map_WriteW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4]);
1511 if (wstatus) return xq_nxm_error(xq);
1512
1513 /* set to next bdl (implicit chain) */
1514 xq->var->rbdl_ba += 12;
1515
1516 /* --------------------------- bootrom part 2 -----------------------------*/
1517
1518 /* get receive bdl from memory */
1519 xq->var->rbdl_buf[0] = 0xFFFF;
1520 wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0]);
1521 rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1]);
1522 if (rstatus || wstatus) return xq_nxm_error(xq);
1523
1524 /* invalid buffer? */
1525 if (~xq->var->rbdl_buf[1] & XQ_DSC_V) {
1526 xq_csr_set_clr(xq, XQ_CSR_RL, 0);
1527 return SCPE_OK;
1528 }
1529
1530 /* get status words */
1531 rstatus = Map_ReadW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4]);
1532 if (rstatus) return xq_nxm_error(xq);
1533
1534 /* get host memory address */
1535 address = ((xq->var->rbdl_buf[1] & 0x3F) << 16) | xq->var->rbdl_buf[2];
1536
1537 /* decode buffer length - two's complement (in words) */
1538 w_length = ~xq->var->rbdl_buf[3] + 1;
1539 b_length = w_length * 2;
1540 if (xq->var->rbdl_buf[1] & XQ_DSC_H) b_length -= 1;
1541 if (xq->var->rbdl_buf[1] & XQ_DSC_L) b_length -= 1;
1542
1543 /* make sure entire packet fits in buffer */
1544 assert(b_length >= sizeof(xq_bootrom)/2);
1545
1546 /* send data to host */
1547 wstatus = Map_WriteB(address, sizeof(xq_bootrom)/2, &bootrom[2048]);
1548 if (wstatus) return xq_nxm_error(xq);
1549
1550 /* update read status words */
1551 xq->var->rbdl_buf[4] = XQ_DSC_V | XQ_DSC_C; /* valid, chain */
1552 xq->var->rbdl_buf[5] = 0;
1553
1554 /* update read status words*/
1555 wstatus = Map_WriteW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4]);
1556 if (wstatus) return xq_nxm_error(xq);
1557
1558 /* set to next bdl (implicit chain) */
1559 xq->var->rbdl_ba += 12;
1560
1561 /* --------------------------- bootrom part 3 -----------------------------*/
1562
1563 switch (xq->var->type) {
1564 case XQ_T_DEQNA:
1565
1566 /* get receive bdl from memory */
1567 xq->var->rbdl_buf[0] = 0xFFFF;
1568 wstatus = Map_WriteW(xq->var->rbdl_ba, 2, &xq->var->rbdl_buf[0]);
1569 rstatus = Map_ReadW (xq->var->rbdl_ba + 2, 6, &xq->var->rbdl_buf[1]);
1570 if (rstatus || wstatus) return xq_nxm_error(xq);
1571
1572 /* invalid buffer? */
1573 if (~xq->var->rbdl_buf[1] & XQ_DSC_V) {
1574 xq_csr_set_clr(xq, XQ_CSR_RL, 0);
1575 return SCPE_OK;
1576 }
1577
1578 /* get status words */
1579 rstatus = Map_ReadW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4]);
1580 if (rstatus) return xq_nxm_error(xq);
1581
1582 /* update read status words */
1583 xq->var->rbdl_buf[4] = XQ_DSC_V; /* valid */
1584 xq->var->rbdl_buf[5] = 0;
1585
1586 /* update read status words*/
1587 wstatus = Map_WriteW(xq->var->rbdl_ba + 8, 4, &xq->var->rbdl_buf[4]);
1588 if (wstatus) return xq_nxm_error(xq);
1589
1590 /* set to next bdl (implicit chain) */
1591 xq->var->rbdl_ba += 12;
1592 break;
1593 } /* switch */
1594
1595 /* --------------------------- Done, finish up -----------------------------*/
1596
1597 /* mark transmission complete */
1598 xq_csr_set_clr(xq, XQ_CSR_RI, 0);
1599
1600 /* reset sanity timer */
1601 xq_reset_santmr(xq);
1602
1603 return SCPE_OK;
1604 }
1605 #endif /* ifdef VM_PDP11 */
1606
1607 t_stat xq_wr_csr(CTLR* xq, int32 data)
1608 {
1609 uint16 set_bits = data & XQ_CSR_RW; /* set RW set bits */
1610 uint16 clr_bits = ((data ^ XQ_CSR_RW) & XQ_CSR_RW) /* clear RW cleared bits */
1611 | (data & XQ_CSR_W1) /* write 1 to clear bits */
1612 | ((data & XQ_CSR_XI) ? XQ_CSR_NI : 0); /* clearing XI clears NI */
1613
1614 sim_debug(DBG_REG, xq->dev, "xq_wr_csr(data=0x%08X)\n", data);
1615
1616 /* reset controller when SR transitions to cleared */
1617 if (xq->var->csr & XQ_CSR_SR & ~data) {
1618 xq_sw_reset(xq);
1619 return SCPE_OK;
1620 }
1621
1622 #if 0 /* controller should ALWAYS have an active timer if enabled (for HW sanity) */
1623 /* start/stop receive timer when RE transitions */
1624 if ((xq->var->csr ^ data) & XQ_CSR_RE) {
1625 if (data & XQ_CSR_RE)
1626 sim_activate(&xq->unit[0], clock_cosched (tmxr_poll));
1627 else
1628 sim_cancel(&xq->unit[0]);
1629 }
1630 #endif
1631
1632 /* update CSR bits */
1633 xq_csr_set_clr (xq, set_bits, clr_bits);
1634
1635 #ifdef VM_PDP11
1636 /* request boot/diagnostic rom? [PDP-11 only] */
1637 if ((xq->var->csr & XQ_CSR_BP) == XQ_CSR_BP) /* all bits must be on */
1638 xq_process_bootrom(xq);
1639 #endif
1640
1641 return SCPE_OK;
1642 }
1643
1644 t_stat xq_wr(int32 data, int32 PA, int32 access)
1645 {
1646 t_stat status;
1647 CTLR* xq = xq_pa2ctlr(PA);
1648 int index = (PA >> 1) & 07; /* word index */
1649
1650 sim_debug(DBG_REG, xq->dev, "xq_wr(data=0x%08X, PA=0x%08X[%s], access=%d)\n", data, PA, xq_xmit_regnames[index], access);
1651
1652 switch (index) {
1653 case 0: /* these should not be written */
1654 case 1:
1655 break;
1656 case 2: /* receive bdl low bits */
1657 xq->var->rbdl[0] = data;
1658 break;
1659 case 3: /* receive bdl high bits */
1660 xq->var->rbdl[1] = data;
1661 status = xq_dispatch_rbdl(xq); /* start receive operation */
1662 break;
1663 case 4: /* transmit bdl low bits */
1664 xq->var->xbdl[0] = data;
1665 break;
1666 case 5: /* transmit bdl high bits */
1667 xq->var->xbdl[1] = data;
1668 status = xq_dispatch_xbdl(xq); /* start transmit operation */
1669 break;
1670 case 6: /* vector address register */
1671 status = xq_wr_var(xq, data);
1672 break;
1673 case 7: /* control and status register */
1674 status = xq_wr_csr(xq, data);
1675 break;
1676 }
1677 return SCPE_OK;
1678 }
1679
1680
1681 /* reset device */
1682 t_stat xq_reset(DEVICE* dptr)
1683 {
1684 t_stat status;
1685 CTLR* xq = xq_dev2ctlr(dptr);
1686 const uint16 set_bits = XQ_CSR_RL | XQ_CSR_XL;
1687
1688 sim_debug(DBG_TRC, xq->dev, "xq_reset()\n");
1689
1690 /* calculate MAC checksum */
1691 xq_make_checksum(xq);
1692
1693 /* init vector address register */
1694 switch (xq->var->type) {
1695 case XQ_T_DEQNA:
1696 xq->var->var = 0;
1697 break;
1698 case XQ_T_DELQA:
1699 xq->var->var = XQ_VEC_MS | XQ_VEC_OS;
1700 break;
1701 }
1702 xq->dib->vec = 0;
1703
1704 /* init control status register */
1705 xq_csr_set_clr(xq, set_bits, (uint16) ~set_bits);
1706
1707 /* clear interrupts unconditionally */
1708 xq_clrint(xq);
1709
1710 /* init read queue (first time only) */
1711 status = ethq_init(&xq->var->ReadQ, XQ_QUE_MAX);
1712 if (status != SCPE_OK)
1713 return status;
1714
1715 /* clear read queue */
1716 ethq_clear(&xq->var->ReadQ);
1717
1718 /* reset ethernet interface */
1719 if (xq->var->etherface) {
1720 status = eth_filter (xq->var->etherface, 1, &xq->var->mac, 0, 0);
1721 xq_csr_set_clr(xq, XQ_CSR_OK, 0);
1722
1723 /* start service timer */
1724 sim_activate_abs(&xq->unit[0], tmxr_poll);
1725 }
1726
1727 /* set hardware sanity controls */
1728 if (xq->var->sanity.enabled) {
1729 xq->var->sanity.quarter_secs = XQ_HW_SANITY_SECS * 4/*qsec*/;
1730 xq->var->sanity.max = XQ_HW_SANITY_SECS * xq->var->poll;
1731 }
1732 return SCPE_OK;
1733 }
1734
1735 void xq_reset_santmr(CTLR* xq)
1736 {
1737 sim_debug(DBG_TRC, xq->dev, "xq_reset_santmr()\n");
1738 if (xq->var->sanity.enabled) {
1739 sim_debug(DBG_SAN, xq->dev, "SANITY TIMER RESETTING, qsecs: %d\n", xq->var->sanity.quarter_secs);
1740
1741 /* reset sanity countdown timer to max count */
1742 xq->var->sanity.timer = xq->var->sanity.max;
1743 }
1744 }
1745
1746 t_stat xq_boot_host(CTLR* xq)
1747 {
1748 sim_debug(DBG_TRC, xq->dev, "xq_boot_host()\n");
1749 /*
1750 The manual says the hardware should force the Qbus BDCOK low for
1751 3.6 microseconds, which will cause the host to reboot.
1752
1753 Since the SIMH Qbus emulator does not have this functionality, we call
1754 a special STOP_ code, and let the CPU stop dispatch routine decide
1755 what the appropriate cpu-specific behavior should be.
1756 */
1757 return STOP_SANITY;
1758 }
1759
1760 t_stat xq_system_id (CTLR* xq, const ETH_MAC dest, uint16 receipt_id)
1761 {
1762 static uint16 receipt = 0;
1763 ETH_PACK system_id;
1764 uint8* const msg = &system_id.msg[0];
1765 t_stat status;
1766
1767 sim_debug(DBG_TRC, xq->dev, "xq_system_id()\n");
1768 if (xq->var->type != XQ_T_DELQA) /* DELQA-only function */
1769 return SCPE_NOFNC;
1770
1771 memset (&system_id, 0, sizeof(system_id));
1772 memcpy (&msg[0], dest, sizeof(ETH_MAC));
1773 memcpy (&msg[6], xq->var->setup.valid ? xq->var->setup.macs[0] : xq->var->mac, sizeof(ETH_MAC));
1774 msg[12] = 0x60; /* type */
1775 msg[13] = 0x02; /* type */
1776 msg[14] = 0x1C; /* character count */
1777 msg[15] = 0x00; /* character count */
1778 msg[16] = 0x07; /* code */
1779 msg[17] = 0x00; /* zero pad */
1780 if (receipt_id) {
1781 msg[18] = receipt_id & 0xFF; /* receipt number */
1782 msg[19] = (receipt_id >> 8) & 0xFF; /* receipt number */
1783 } else {
1784 msg[18] = receipt & 0xFF; /* receipt number */
1785 msg[19] = (receipt++ >> 8) & 0xFF; /* receipt number */
1786 }
1787
1788 /* MOP VERSION */
1789 msg[20] = 0x01; /* type */
1790 msg[21] = 0x00; /* type */
1791 msg[22] = 0x03; /* length */
1792 msg[23] = 0x03; /* version */
1793 msg[24] = 0x01; /* eco */
1794 msg[25] = 0x00; /* user eco */
1795
1796 /* FUNCTION */
1797 msg[26] = 0x02; /* type */
1798 msg[27] = 0x00; /* type */
1799 msg[28] = 0x02; /* length */
1800 msg[29] = 0x00; /* value 1 ??? */
1801 msg[30] = 0x00; /* value 2 */
1802
1803 /* HARDWARE ADDRESS */
1804 msg[31] = 0x07; /* type */
1805 msg[32] = 0x00; /* type */
1806 msg[33] = 0x06; /* length */
1807 memcpy (&msg[34], xq->var->mac, sizeof(ETH_MAC)); /* ROM address */
1808
1809 /* DEVICE TYPE */
1810 msg[40] = 37; /* type */
1811 msg[41] = 0x00; /* type */
1812 msg[42] = 0x01; /* length */
1813 msg[43] = 0x11; /* value (0x11=DELQA) */
1814
1815 /* write system id */
1816 system_id.len = 60;
1817 status = eth_write(xq->var->etherface, &system_id, NULL);
1818
1819 return status;
1820 }
1821
1822 /*
1823 ** service routine - used for ethernet reading loop
1824 */
1825 t_stat xq_svc(UNIT* uptr)
1826 {
1827 CTLR* xq = xq_unit2ctlr(uptr);
1828
1829 /* if the receiver is enabled */
1830 if (xq->var->csr & XQ_CSR_RE) {
1831 t_stat status;
1832 int queue_size;
1833
1834 /* First pump any queued packets into the system */
1835 if ((xq->var->ReadQ.count > 0) && (~xq->var->csr & XQ_CSR_RL))
1836 status = xq_process_rbdl(xq);
1837
1838 /* Now read and queue packets that have arrived */
1839 /* This is repeated as long as they are available and we have room */
1840 do
1841 {
1842 queue_size = xq->var->ReadQ.count;
1843 /* read a packet from the ethernet - processing is via the callback */
1844 status = eth_read (xq->var->etherface, &xq->var->read_buffer, xq->var->rcallback);
1845 } while (queue_size != xq->var->ReadQ.count);
1846
1847 /* Now pump any still queued packets into the system */
1848 if ((xq->var->ReadQ.count > 0) && (~xq->var->csr & XQ_CSR_RL))
1849 status = xq_process_rbdl(xq);
1850 }
1851
1852 /* has sanity timer expired? if so, reboot */
1853 if (xq->var->sanity.enabled)
1854 if (--xq->var->sanity.timer <= 0)
1855 xq_boot_host(xq);
1856
1857 /* has system id timer expired? if so, do system id */
1858 if (--xq->var->idtmr <= 0) {
1859 const ETH_MAC mop_multicast = {0xAB, 0x00, 0x00, 0x02, 0x00, 0x00};
1860 xq_system_id(xq, mop_multicast, 0);
1861
1862 /* reset system ID counter for next event */
1863 xq->var->idtmr = XQ_SYSTEM_ID_SECS * xq->var->poll;
1864 }
1865
1866 /* resubmit service timer */
1867 sim_activate(&xq->unit[0], tmxr_poll);
1868
1869 return SCPE_OK;
1870 }
1871
1872
1873 /* attach device: */
1874 t_stat xq_attach(UNIT* uptr, char* cptr)
1875 {
1876 t_stat status;
1877 char* tptr;
1878 CTLR* xq = xq_unit2ctlr(uptr);
1879 char buffer[80]; /* buffer for runtime input */
1880
1881 sim_debug(DBG_TRC, xq->dev, "xq_attach(cptr=%s)\n", cptr);
1882
1883 /* runtime selection of ethernet port? */
1884 if (*cptr == '?') { /* I/O style derived from main() */
1885 memset (buffer, 0, sizeof(buffer)); /* clear read buffer */
1886 eth_show (stdout, uptr, 0, NULL); /* show ETH devices */
1887 printf ("Select device (ethX or <device_name>)? "); /* prompt for device */
1888 cptr = read_line (buffer, sizeof(buffer), stdin); /* read command line */
1889 if (cptr == NULL) return SCPE_ARG; /* ignore EOF */
1890 if (*cptr == 0) return SCPE_ARG; /* ignore blank */
1891 } /* resume attaching */
1892
1893 tptr = (char *) malloc(strlen(cptr) + 1);
1894 if (tptr == NULL) return SCPE_MEM;
1895 strcpy(tptr, cptr);
1896
1897 xq->var->etherface = (ETH_DEV *) malloc(sizeof(ETH_DEV));
1898 if (!xq->var->etherface) return SCPE_MEM;
1899
1900 status = eth_open(xq->var->etherface, cptr, xq->dev, DBG_ETH);
1901 if (status != SCPE_OK) {
1902 free(tptr);
1903 free(xq->var->etherface);
1904 xq->var->etherface = 0;
1905 return status;
1906 }
1907 uptr->filename = tptr;
1908 uptr->flags |= UNIT_ATT;
1909
1910 /* turn on transceiver power indicator */
1911 xq_csr_set_clr(xq, XQ_CSR_OK, 0);
1912
1913 /* reset the device with the new attach info */
1914 xq_reset(xq->dev);
1915
1916 return SCPE_OK;
1917 }
1918
1919 /* detach device: */
1920
1921 t_stat xq_detach(UNIT* uptr)
1922 {
1923 CTLR* xq = xq_unit2ctlr(uptr);
1924 sim_debug(DBG_TRC, xq->dev, "xq_detach()\n");
1925
1926 if (uptr->flags & UNIT_ATT) {
1927 eth_close (xq->var->etherface);
1928 free(xq->var->etherface);
1929 xq->var->etherface = 0;
1930 free(uptr->filename);
1931 uptr->filename = NULL;
1932 uptr->flags &= ~UNIT_ATT;
1933 /* cancel service timer */
1934 sim_cancel(&xq->unit[0]);
1935 }
1936
1937 /* turn off transceiver power indicator */
1938 xq_csr_set_clr(xq, 0, XQ_CSR_OK);
1939
1940 return SCPE_OK;
1941 }
1942
1943 void xq_setint(CTLR* xq)
1944 {
1945 xq->var->irq = 1;
1946 SET_INT(XQ);
1947 return;
1948 }
1949
1950 void xq_clrint(CTLR* xq)
1951 {
1952 int i;
1953 xq->var->irq = 0; /* set controller irq off */
1954 /* clear master interrupt? */
1955 for (i=0; i<XQ_MAX_CONTROLLERS; i++) /* check all controllers.. */
1956 if (xq_ctrl[i].var->irq) { /* if any irqs enabled */
1957 SET_INT(XQ); /* set master interrupt on */
1958 return;
1959 }
1960 CLR_INT(XQ); /* clear master interrupt */
1961 return;
1962 }
1963
1964 int32 xq_int (void)
1965 {
1966 int i;
1967 for (i=0; i<XQ_MAX_CONTROLLERS; i++) {
1968 CTLR* xq = &xq_ctrl[i];
1969 if (xq->var->irq) { /* if interrupt pending */
1970 xq_clrint(xq); /* clear interrupt */
1971 return xq->dib->vec; /* return vector */
1972 }
1973 }
1974 return 0; /* no interrupt request active */
1975 }
1976
1977 void xq_csr_set_clr (CTLR* xq, uint16 set_bits, uint16 clear_bits)
1978 {
1979 uint16 saved_csr = xq->var->csr;
1980
1981 /* set the bits in the csr */
1982 xq->var->csr = (xq->var->csr | set_bits) & ~clear_bits;
1983
1984 sim_debug_u16(DBG_CSR, xq->dev, xq_csr_bits, saved_csr, xq->var->csr, 1);
1985
1986 /* check and correct the state of controller interrupt */
1987
1988 /* if IE is transitioning, process it */
1989 if ((saved_csr ^ xq->var->csr) & XQ_CSR_IE) {
1990
1991 /* if IE transitioning low and interrupt set, clear interrupt */
1992 if ((clear_bits & XQ_CSR_IE) && xq->var->irq)
1993 xq_clrint(xq);
1994
1995 /* if IE transitioning high, and XI or RI is high,
1996 set interrupt if interrupt is off */
1997 if ((set_bits & XQ_CSR_IE) && (xq->var->csr & XQ_CSR_XIRI) && !xq->var->irq)
1998 xq_setint(xq);
1999
2000 } else { /* IE is not transitioning */
2001
2002 /* if interrupts are enabled */
2003 if (xq->var->csr & XQ_CSR_IE) {
2004
2005 /* if XI or RI transitioning high and interrupt off, set interrupt */
2006 if (((saved_csr ^ xq->var->csr) & (set_bits & XQ_CSR_XIRI)) && !xq->var->irq) {
2007 xq_setint(xq);
2008
2009 } else {
2010
2011 /* if XI or RI transitioning low, and both XI and RI are now low,
2012 clear interrupt if interrupt is on */
2013 if (((saved_csr ^ xq->var->csr) & (clear_bits & XQ_CSR_XIRI))
2014 && !(xq->var->csr & XQ_CSR_XIRI)
2015 && xq->var->irq)
2016 xq_clrint(xq);
2017 }
2018
2019 } /* IE enabled */
2020
2021 } /* IE transitioning */
2022 }
2023
2024 /*==============================================================================
2025 / debugging routines
2026 /=============================================================================*/
2027
2028
2029 void xq_debug_setup(CTLR* xq)
2030 {
2031 int i;
2032 char buffer[20];
2033 if (xq->var->write_buffer.msg[0])
2034 printf ("%s: setup> MOP info present!\n", xq->dev->name);
2035
2036 for (i = 0; i < XQ_FILTER_MAX; i++) {
2037 eth_mac_fmt(&xq->var->setup.macs[i], buffer);
2038 printf ("%s: setup> set addr[%d]: %s\n", xq->dev->name, i, buffer);
2039 }
2040
2041 if (xq->var->write_buffer.len > 128) {
2042 char buffer[20] = {0};
2043 uint16 len = xq->var->write_buffer.len;
2044 if (len & XQ_SETUP_MC) strcat(buffer, "MC ");
2045 if (len & XQ_SETUP_PM) strcat(buffer, "PM ");
2046 if (len & XQ_SETUP_LD) strcat(buffer, "LD ");
2047 if (len & XQ_SETUP_ST) strcat(buffer, "ST ");
2048 printf ("%s: setup> Length [%d =0x%X, LD:%d, ST:%d] info: %s\n",
2049 xq->dev->name, len, len, (len & XQ_SETUP_LD) >> 2, (len & XQ_SETUP_ST) >> 4, buffer);
2050 }
2051 }