1 /* pdp11_xq.c: DEQNA/DELQA ethernet controller simulator
2 ------------------------------------------------------------------------------
4 Copyright (c) 2002-2007, David T. Hittner
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:
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
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.
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.
27 ------------------------------------------------------------------------------
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
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
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.
48 Known Bugs or Unsupported features, in priority order:
50 2) MOP functionality not implemented
51 3) Local packet processing not implemented
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)
62 PDP11: 1. RT-11 v5.3 - FTPSB copy test
63 2. RSTS/E v10.1 - detects/enables device
65 ------------------------------------------------------------------------------
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
92 - Fixed output format in show_xq_sanity to end in "\n"
93 - Added display of All Multicase and promiscuous to
95 - The stuck in All Multicast or Promiscuous issue is
96 worse than previously thought. See comments in
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
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
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
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
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
207 ------------------------------------------------------------------------------
211 #include "pdp11_xq.h"
212 #include "pdp11_xq_bootrom.h"
214 extern int32 tmxr_poll
;
215 extern FILE* sim_deb
;
216 extern char* read_line (char *ptr
, int32 size
, FILE *stream
);
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
);
252 void xq_csr_set_clr(CTLR
* xq
, uint16 set_bits
, uint16 clear_bits
);
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 */
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 */
272 /* SIMH device structures */
273 DIB xqa_dib
= { IOBA_XQ
, IOLN_XQ
, &xq_rd
, &xq_wr
,
274 1, IVCL (XQ
), 0, { &xq_int
} };
277 { UDATA (&xq_svc
, UNIT_IDLE
|UNIT_ATTABLE
|UNIT_DISABLE
, 2047) }, /* receive timer */
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
},
304 DIB xqb_dib
= { IOBA_XQB
, IOLN_XQB
, &xq_rd
, &xq_wr
,
305 1, IVCL (XQ
), 0, { &xq_int
} };
308 { UDATA (&xq_svc
, UNIT_IDLE
|UNIT_ATTABLE
|UNIT_DISABLE
, 2047) }, /* receive timer */
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
},
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
, ð_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
},
357 DEBTAB xq_debug
[] = {
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
,
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
,
389 {&xq_dev
, xqa_unit
, &xqa_dib
, &xqa
}, /* XQA controller */
390 {&xqb_dev
, xqb_unit
, &xqb_dib
, &xqb
} /* XQB controller */
393 const char* const xq_recv_regnames
[] = {
394 "MAC0", "MAC1", "MAC2", "MAC3", "MAC4", "MAC5", "VAR", "CSR"
397 const char* const xq_xmit_regnames
[] = {
398 "", "", "RBDL-Lo", "RBDL-Hi", "XBDL-Lo", "XBDL-Hi", "VAR", "CSR"
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"
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"
411 /* internal debugging routines */
412 void xq_debug_setup(CTLR
* xq
);
414 /*============================================================================*/
416 /* Multicontroller support */
418 CTLR
* xq_unit2ctlr(UNIT
* uptr
)
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
)
429 CTLR
* xq_dev2ctlr(DEVICE
* dptr
)
432 for (i
=0; i
<XQ_MAX_CONTROLLERS
; i
++)
433 if (xq_ctrl
[i
].dev
== dptr
)
439 CTLR
* xq_pa2ctlr(uint32 PA
)
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
)))
449 /*============================================================================*/
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
)
454 /* on PDP-11, allow EX command to look at bootrom */
456 if (addr
<= sizeof(xq_bootrom
)/2)
457 *vptr
= xq_bootrom
[addr
];
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
)
472 t_stat
xq_showmac (FILE* st
, UNIT
* uptr
, int32 val
, void* desc
)
474 CTLR
* xq
= xq_unit2ctlr(uptr
);
477 eth_mac_fmt((ETH_MAC
*)xq
->var
->mac
, buffer
);
478 fprintf(st
, "MAC=%s", buffer
);
482 void xq_make_checksum(CTLR
* xq
)
484 /* checksum calculation routine detailed in vaxboot.zip/xqbtdrivr.mar */
486 const uint32 wmask
= 0xFFFF;
489 for (i
= 0; i
< sizeof(ETH_MAC
); i
+= 2) {
491 if (checksum
> wmask
)
493 checksum
+= (xq
->var
->mac
[i
] << 8) | xq
->var
->mac
[i
+1];
494 if (checksum
> wmask
)
497 if (checksum
== wmask
)
500 /* set checksum bytes */
501 xq
->var
->mac_checksum
[0] = checksum
& 0xFF;
502 xq
->var
->mac_checksum
[1] = checksum
>> 8;
505 t_stat
xq_setmac (UNIT
* uptr
, int32 val
, char* cptr
, void* desc
)
508 CTLR
* xq
= xq_unit2ctlr(uptr
);
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
)
516 /* calculate mac checksum */
517 xq_make_checksum(xq
);
521 t_stat
xq_set_stats (UNIT
* uptr
, int32 val
, char* cptr
, void* desc
)
523 /* this sets all ints in the stats structure to the integer passed */
524 CTLR
* xq
= xq_unit2ctlr(uptr
);
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);
532 for (i
=0; i
<elements
; i
++)
533 stat_array
[i
] = init
;
535 /* set stats to zero */
536 memset(&xq
->var
->stats
, 0, sizeof(struct xq_stats
));
541 t_stat
xq_show_stats (FILE* st
, UNIT
* uptr
, int32 val
, void* desc
)
543 char* fmt
= " %-15s%d\n";
544 CTLR
* xq
= xq_unit2ctlr(uptr
);
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
);
559 t_stat
xq_show_filters (FILE* st
, UNIT
* uptr
, int32 val
, void* desc
)
561 CTLR
* xq
= xq_unit2ctlr(uptr
);
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
);
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");
577 t_stat
xq_show_type (FILE* st
, UNIT
* uptr
, int32 val
, void* desc
)
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;
588 t_stat
xq_set_type (UNIT
* uptr
, int32 val
, char* cptr
, void* desc
)
590 CTLR
* xq
= xq_unit2ctlr(uptr
);
591 if (!cptr
) return SCPE_IERR
;
592 if (uptr
->flags
& UNIT_ATT
) return SCPE_ALATT
;
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
;
602 t_stat
xq_show_poll (FILE* st
, UNIT
* uptr
, int32 val
, void* desc
)
604 CTLR
* xq
= xq_unit2ctlr(uptr
);
605 fprintf(st
, "poll=%d", xq
->var
->poll
);
609 t_stat
xq_set_poll (UNIT
* uptr
, int32 val
, char* cptr
, void* desc
)
611 CTLR
* xq
= xq_unit2ctlr(uptr
);
612 if (!cptr
) return SCPE_IERR
;
613 if (uptr
->flags
& UNIT_ATT
) return SCPE_ALATT
;
615 /* this assumes that the parameter has already been upcased */
616 if (!strcmp(cptr
, "DEFAULT"))
617 xq
->var
->poll
= XQ_SERVICE_INTERVAL
;
620 sscanf(cptr
, "%d", &newpoll
);
621 if ((newpoll
>= 4) && (newpoll
<= 2500))
622 xq
->var
->poll
= newpoll
;
630 t_stat
xq_show_sanity (FILE* st
, UNIT
* uptr
, int32 val
, void* desc
)
632 CTLR
* xq
= xq_unit2ctlr(uptr
);
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;
642 t_stat
xq_set_sanity (UNIT
* uptr
, int32 val
, char* cptr
, void* desc
)
644 CTLR
* xq
= xq_unit2ctlr(uptr
);
645 if (!cptr
) return SCPE_IERR
;
646 if (uptr
->flags
& UNIT_ATT
) return SCPE_ALATT
;
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
;
656 /*============================================================================*/
658 t_stat
xq_nxm_error(CTLR
* xq
)
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");
663 /* set NXM and associated bits in CSR */
664 xq_csr_set_clr(xq
, set_bits
, 0);
671 void xq_write_callback (CTLR
* xq
, int status
)
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> */
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
);
696 xq_csr_set_clr(xq
, XQ_CSR_XI
, 0);
698 /* reset sanity timer */
701 /* clear write buffer */
702 xq
->var
->write_buffer
.len
= 0;
704 /* next descriptor (implicit) */
705 xq
->var
->xbdl_ba
+= 12;
707 /* finish processing xbdl */
708 rstatus
= xq_process_xbdl(xq
);
711 void xqa_write_callback (int status
)
713 xq_write_callback(&xq_ctrl
[0], status
);
716 void xqb_write_callback (int status
)
718 xq_write_callback(&xq_ctrl
[1], status
);
721 /* read registers: */
722 t_stat
xq_rd(int32
* data
, int32 PA
, int32 access
)
724 CTLR
* xq
= xq_pa2ctlr(PA
);
725 int index
= (PA
>> 1) & 07; /* word index */
727 sim_debug(DBG_REG
, xq
->dev
, "xq_rd(PA=0x%08X [%s], access=%d)\n", PA
, xq_recv_regnames
[index
], access
);
731 /* return checksum in external loopback mode */
732 if (xq
->var
->csr
& XQ_CSR_EL
)
733 *data
= 0xFF00 | xq
->var
->mac_checksum
[index
];
735 *data
= 0xFF00 | xq
->var
->mac
[index
];
741 *data
= 0xFF00 | xq
->var
->mac
[index
];
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
;
749 sim_debug_u16(DBG_CSR
, xq
->dev
, xq_csr_bits
, xq
->var
->csr
, xq
->var
->csr
, 1);
750 *data
= xq
->var
->csr
;
757 /* dispatch ethernet read request
758 procedure documented in sec. 3.2.2 */
760 t_stat
xq_process_rbdl(CTLR
* xq
)
762 int32 rstatus
, wstatus
;
763 uint16 b_length
, w_length
, rbl
;
768 sim_debug(DBG_TRC
, xq
->dev
, "xq_process_rdbl\n");
770 /* process buffer descriptors */
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
);
779 /* invalid buffer? */
780 if (~xq
->var
->rbdl_buf
[1] & XQ_DSC_V
) {
781 xq_csr_set_clr(xq
, XQ_CSR_RL
, 0);
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];
791 /* stop processing if nothing in read queue */
792 if (!xq
->var
->ReadQ
.count
) break;
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
);
798 /* get host memory address */
799 address
= ((xq
->var
->rbdl_buf
[1] & 0x3F) << 16) | xq
->var
->rbdl_buf
[2];
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;
807 item
= &xq
->var
->ReadQ
.item
[xq
->var
->ReadQ
.head
];
808 rbl
= item
->packet
.len
;
809 rbuf
= item
->packet
.msg
;
811 /* see if packet must be size-adjusted or is splitting */
812 if (item
->packet
.used
) {
813 int used
= item
->packet
.used
;
815 rbuf
= &item
->packet
.msg
[used
];
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
;
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
;
837 /* make sure entire packet fits in buffer - if not, will need to split into multiple buffers */
840 item
->packet
.used
+= rbl
;
842 /* send data to host */
843 wstatus
= Map_WriteB(address
, rbl
, rbuf
);
844 if (wstatus
) return xq_nxm_error(xq
);
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) */
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 */
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 */
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 */
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 */
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
);
878 /* remove packet from queue */
879 if (item
->packet
.used
>= item
->packet
.len
)
880 ethq_remove(&xq
->var
->ReadQ
);
882 /* mark transmission complete */
883 xq_csr_set_clr(xq
, XQ_CSR_RI
, 0);
885 /* set to next bdl (implicit chain) */
886 xq
->var
->rbdl_ba
+= 12;
893 t_stat
xq_process_mop(CTLR
* xq
)
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];
901 sim_debug(DBG_TRC
, xq
->dev
, "xq_process_mop()\n");
903 if (xq
->var
->type
== XQ_T_DEQNA
) /* DEQNA's don't MOP */
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
;
910 /* MOP stuff here - NOT YET FULLY IMPLEMENTED */
911 sim_debug (DBG_WRN
, xq
->dev
, "Processing MEB type: %d\n", meb
->type
);
913 case 0: /* MOP Termination */
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
);
919 case 2: /* MOP Reset System ID */
921 case 3: /* MOP Read Last MOP Boot */
923 case 4: /* MOP Read Boot Password */
925 case 5: /* MOP Write Boot Password */
927 case 6: /* MOP Read System ID */
929 case 7: /* MOP Write System ID */
931 case 8: /* MOP Read Counters */
933 case 9: /* Mop Read/Clear Counters */
937 /* process next meb */
938 meb
+= sizeof(struct xq_meb
);
944 t_stat
xq_process_setup(CTLR
* xq
)
950 ETH_MAC zeros
= {0, 0, 0, 0, 0, 0};
951 ETH_MAC filters
[XQ_FILTER_MAX
+ 1];
953 sim_debug(DBG_TRC
, xq
->dev
, "xq_process_setup()\n");
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)];
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.
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
;
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) {
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;
1008 /* set sanity timer timeout */
1009 san
= (len
& XQ_SETUP_ST
) >> 4;
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 */
1020 xq
->var
->sanity
.quarter_secs
= (int) (secs
* 4);
1021 xq
->var
->sanity
.max
= (int) (secs
* xq
->var
->poll
);
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;
1030 xq
->var
->sanity
.enabled
= 0;
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
);
1040 /* process MOP information */
1041 if (xq
->var
->write_buffer
.msg
[0])
1042 status
= xq_process_mop(xq
);
1044 /* mark setup block valid */
1045 xq
->var
->setup
.valid
= 1;
1047 if (sim_deb
&& (xq
->dev
->dctrl
& DBG_SET
))
1053 Dispatch Write Operation
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.
1059 t_stat
xq_process_xbdl(CTLR
* xq
)
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
;
1068 sim_debug(DBG_TRC
, xq
->dev
, "xq_process_xbdl()\n");
1070 /* clear write buffer */
1071 xq
->var
->write_buffer
.len
= 0;
1073 /* process buffer descriptors until not valid */
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
);
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");
1089 /* compute host memory address */
1090 address
= ((xq
->var
->xbdl_buf
[1] & 0x3F) << 16) | xq
->var
->xbdl_buf
[2];
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;
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
);
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
;
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
);
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);
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
);
1130 /* clear write buffer */
1131 xq
->var
->write_buffer
.len
= 0;
1133 /* reset sanity timer */
1134 xq_reset_santmr(xq
);
1136 /* mark transmission complete */
1137 xq_csr_set_clr(xq
, XQ_CSR_XI
, 0);
1139 /* now trigger "read" of setup or loopback packet */
1140 if (~xq
->var
->csr
& XQ_CSR_RL
)
1141 status
= xq_process_rbdl(xq
);
1143 } else { /* not loopback */
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 */
1150 xq_svc(&xq
->unit
[0]); /* service any received data */
1152 sim_debug(DBG_WRN
, xq
->dev
, "XBDL completed processing write\n");
1155 } /* loopback/non-loopback */
1156 } else { /* not at end-of-message */
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
);
1164 /* set to next bdl (implicit chain) */
1165 xq
->var
->xbdl_ba
+= 12;
1170 t_stat
xq_dispatch_rbdl(CTLR
* xq
)
1173 int32 rstatus
, wstatus
;
1176 sim_debug(DBG_TRC
, xq
->dev
, "xq_dispatch_rbdl()\n");
1178 /* mark receive bdl valid */
1179 xq_csr_set_clr(xq
, 0, XQ_CSR_RL
);
1181 /* init receive bdl buffer */
1183 xq
->var
->rbdl_buf
[i
] = 0;
1185 /* get address of first receive buffer */
1186 xq
->var
->rbdl_ba
= ((xq
->var
->rbdl
[1] & 0x3F) << 16) | (xq
->var
->rbdl
[0] & ~01);
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
);
1194 /* is buffer valid? */
1195 if (~xq
->var
->rbdl_buf
[1] & XQ_DSC_V
) {
1196 xq_csr_set_clr(xq
, XQ_CSR_RL
, 0);
1200 /* process any waiting packets in receive queue */
1201 if (xq
->var
->ReadQ
.count
)
1202 status
= xq_process_rbdl(xq
);
1207 t_stat
xq_dispatch_xbdl(CTLR
* xq
)
1212 sim_debug(DBG_TRC
, xq
->dev
, "xq_dispatch_xbdl()\n");
1214 /* mark transmit bdl valid */
1215 xq_csr_set_clr(xq
, 0, XQ_CSR_XL
);
1217 /* initialize transmit bdl buffers */
1219 xq
->var
->xbdl_buf
[i
] = 0;
1221 /* clear transmit buffer */
1222 xq
->var
->write_buffer
.len
= 0;
1224 /* get base address of first transmit descriptor */
1225 xq
->var
->xbdl_ba
= ((xq
->var
->xbdl
[1] & 0x3F) << 16) | (xq
->var
->xbdl
[0] & ~01);
1228 status
= xq_process_xbdl(xq
);
1233 t_stat
xq_process_loopback(CTLR
* xq
, ETH_PACK
* pack
)
1236 ETH_MAC physical_address
;
1238 int offset
= pack
->msg
[14] | (pack
->msg
[15] << 8);
1239 int function
= pack
->msg
[offset
] | (pack
->msg
[offset
+1] << 8);
1241 sim_debug(DBG_TRC
, xq
->dev
, "xq_process_loopback()\n");
1243 if (function
!= 2 /*forward*/)
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;
1254 reply
.msg
[14] = offset
& 0xFF;
1255 reply
.msg
[15] = (offset
>> 8) & 0xFF;
1257 /* send reply packet */
1258 status
= eth_write(xq
->var
->etherface
, &reply
, NULL
);
1263 t_stat
xq_process_remote_console (CTLR
* xq
, ETH_PACK
* pack
)
1268 int code
= pack
->msg
[16];
1270 sim_debug(DBG_TRC
, xq
->dev
, "xq_process_remote_console()\n");
1273 case 0x05: /* request id */
1274 receipt
= pack
->msg
[18] | (pack
->msg
[19] << 8);
1275 memcpy(source
, &pack
->msg
[6], sizeof(ETH_MAC
));
1277 /* send system id to requestor */
1278 status
= xq_system_id (xq
, source
, receipt
);
1281 case 0x06: /* boot */
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.
1288 Verification is not implemented, since the setup packet processing code
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.
1296 status
= xq_boot_host(xq
);
1304 t_stat
xq_process_local (CTLR
* xq
, ETH_PACK
* pack
)
1306 /* returns SCPE_OK if local processing occurred,
1307 otherwise returns SCPE_NOFNC or some other code */
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
)
1315 protocol
= pack
->msg
[12] | (pack
->msg
[13] << 8);
1317 case 0x0090: /* ethernet loopback */
1318 return xq_process_loopback(xq
, pack
);
1320 case 0x0260: /* MOP remote console */
1321 return xq_process_remote_console(xq
, pack
);
1327 void xq_read_callback(CTLR
* xq
, int status
)
1329 xq
->var
->stats
.recv
+= 1;
1330 if (xq
->var
->csr
& XQ_CSR_RE
) { /* receiver enabled */
1332 /* process any packets locally that can be */
1333 t_stat status
= xq_process_local (xq
, &xq
->var
->read_buffer
);
1335 /* add packet to read queue */
1336 if (status
!= SCPE_OK
)
1337 ethq_insert(&xq
->var
->ReadQ
, 2, &xq
->var
->read_buffer
, status
);
1339 sim_debug(DBG_WRN
, xq
->dev
, "packet received with receiver disabled\n");
1343 void xqa_read_callback(int status
)
1345 xq_read_callback(&xq_ctrl
[0], status
);
1348 void xqb_read_callback(int status
)
1350 xq_read_callback(&xq_ctrl
[1], status
);
1353 void xq_sw_reset(CTLR
* xq
)
1355 const uint16 set_bits
= XQ_CSR_XL
| XQ_CSR_RL
;
1358 sim_debug(DBG_TRC
, xq
->dev
, "xq_sw_reset()\n");
1360 /* reset csr bits */
1361 xq_csr_set_clr(xq
, set_bits
, (uint16
) ~set_bits
);
1363 if (xq
->var
->etherface
)
1364 xq_csr_set_clr(xq
, XQ_CSR_OK
, 0);
1366 /* clear interrupt unconditionally */
1369 /* flush read queue */
1370 ethq_clear(&xq
->var
->ReadQ
);
1372 /* clear setup info */
1373 xq
->var
->setup
.multicast
= 0;
1374 xq
->var
->setup
.promiscuous
= 0;
1375 if (xq
->var
->etherface
) {
1377 ETH_MAC zeros
= {0, 0, 0, 0, 0, 0};
1378 ETH_MAC filters
[XQ_FILTER_MAX
+ 1];
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
);
1389 /* write registers: */
1391 t_stat
xq_wr_var(CTLR
* xq
, int32 data
)
1393 uint16 save_var
= xq
->var
->var
;
1394 sim_debug(DBG_REG
, xq
->dev
, "xq_wr_var(data= 0x%08X\n", data
);
1396 switch (xq
->var
->type
) {
1398 xq
->var
->var
= (data
& XQ_VEC_IV
);
1401 xq
->var
->var
= (xq
->var
->var
& XQ_VEC_RO
) | (data
& XQ_VEC_RW
);
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
);
1409 /* set vector of SIMH device */
1410 if (data
& XQ_VEC_IV
)
1411 xq
->dib
->vec
= (data
& XQ_VEC_IV
) + VEC_Q
;
1415 sim_debug_u16(DBG_VAR
, xq
->dev
, xq_var_bits
, save_var
, xq
->var
->var
, 1);
1421 t_stat
xq_process_bootrom (CTLR
* xq
)
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.
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!).
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.
1436 int32 rstatus
, wstatus
;
1437 uint16 b_length
, w_length
;
1439 uint8
* bootrom
= (uint8
*) xq_bootrom
;
1442 sim_debug(DBG_TRC
, xq
->dev
, "xq_process_bootrom()\n");
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
1449 70$: MOV (R2),R0 ;get the status word
1451 70$: CLR R0 ;force success
1452 to cause the Citizenship test to return success to RSTS/E.
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.
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 */
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
];
1468 /* set new checksum */
1469 xq_bootrom
[sizeof(xq_bootrom
)/2-1] = checksum
;
1471 /* --------------------------- bootrom part 1 -----------------------------*/
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
);
1479 /* invalid buffer? */
1480 if (~xq
->var
->rbdl_buf
[1] & XQ_DSC_V
) {
1481 xq_csr_set_clr(xq
, XQ_CSR_RL
, 0);
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
);
1489 /* get host memory address */
1490 address
= ((xq
->var
->rbdl_buf
[1] & 0x3F) << 16) | xq
->var
->rbdl_buf
[2];
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;
1498 /* make sure entire packet fits in buffer */
1499 assert(b_length
>= sizeof(xq_bootrom
)/2);
1501 /* send data to host */
1502 wstatus
= Map_WriteB(address
, sizeof(xq_bootrom
)/2, bootrom
);
1503 if (wstatus
) return xq_nxm_error(xq
);
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;
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
);
1513 /* set to next bdl (implicit chain) */
1514 xq
->var
->rbdl_ba
+= 12;
1516 /* --------------------------- bootrom part 2 -----------------------------*/
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
);
1524 /* invalid buffer? */
1525 if (~xq
->var
->rbdl_buf
[1] & XQ_DSC_V
) {
1526 xq_csr_set_clr(xq
, XQ_CSR_RL
, 0);
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
);
1534 /* get host memory address */
1535 address
= ((xq
->var
->rbdl_buf
[1] & 0x3F) << 16) | xq
->var
->rbdl_buf
[2];
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;
1543 /* make sure entire packet fits in buffer */
1544 assert(b_length
>= sizeof(xq_bootrom
)/2);
1546 /* send data to host */
1547 wstatus
= Map_WriteB(address
, sizeof(xq_bootrom
)/2, &bootrom
[2048]);
1548 if (wstatus
) return xq_nxm_error(xq
);
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;
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
);
1558 /* set to next bdl (implicit chain) */
1559 xq
->var
->rbdl_ba
+= 12;
1561 /* --------------------------- bootrom part 3 -----------------------------*/
1563 switch (xq
->var
->type
) {
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
);
1572 /* invalid buffer? */
1573 if (~xq
->var
->rbdl_buf
[1] & XQ_DSC_V
) {
1574 xq_csr_set_clr(xq
, XQ_CSR_RL
, 0);
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
);
1582 /* update read status words */
1583 xq
->var
->rbdl_buf
[4] = XQ_DSC_V
; /* valid */
1584 xq
->var
->rbdl_buf
[5] = 0;
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
);
1590 /* set to next bdl (implicit chain) */
1591 xq
->var
->rbdl_ba
+= 12;
1595 /* --------------------------- Done, finish up -----------------------------*/
1597 /* mark transmission complete */
1598 xq_csr_set_clr(xq
, XQ_CSR_RI
, 0);
1600 /* reset sanity timer */
1601 xq_reset_santmr(xq
);
1605 #endif /* ifdef VM_PDP11 */
1607 t_stat
xq_wr_csr(CTLR
* xq
, int32 data
)
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 */
1614 sim_debug(DBG_REG
, xq
->dev
, "xq_wr_csr(data=0x%08X)\n", data
);
1616 /* reset controller when SR transitions to cleared */
1617 if (xq
->var
->csr
& XQ_CSR_SR
& ~data
) {
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
));
1628 sim_cancel(&xq
->unit
[0]);
1632 /* update CSR bits */
1633 xq_csr_set_clr (xq
, set_bits
, clr_bits
);
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
);
1644 t_stat
xq_wr(int32 data
, int32 PA
, int32 access
)
1647 CTLR
* xq
= xq_pa2ctlr(PA
);
1648 int index
= (PA
>> 1) & 07; /* word index */
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
);
1653 case 0: /* these should not be written */
1656 case 2: /* receive bdl low bits */
1657 xq
->var
->rbdl
[0] = data
;
1659 case 3: /* receive bdl high bits */
1660 xq
->var
->rbdl
[1] = data
;
1661 status
= xq_dispatch_rbdl(xq
); /* start receive operation */
1663 case 4: /* transmit bdl low bits */
1664 xq
->var
->xbdl
[0] = data
;
1666 case 5: /* transmit bdl high bits */
1667 xq
->var
->xbdl
[1] = data
;
1668 status
= xq_dispatch_xbdl(xq
); /* start transmit operation */
1670 case 6: /* vector address register */
1671 status
= xq_wr_var(xq
, data
);
1673 case 7: /* control and status register */
1674 status
= xq_wr_csr(xq
, data
);
1682 t_stat
xq_reset(DEVICE
* dptr
)
1685 CTLR
* xq
= xq_dev2ctlr(dptr
);
1686 const uint16 set_bits
= XQ_CSR_RL
| XQ_CSR_XL
;
1688 sim_debug(DBG_TRC
, xq
->dev
, "xq_reset()\n");
1690 /* calculate MAC checksum */
1691 xq_make_checksum(xq
);
1693 /* init vector address register */
1694 switch (xq
->var
->type
) {
1699 xq
->var
->var
= XQ_VEC_MS
| XQ_VEC_OS
;
1704 /* init control status register */
1705 xq_csr_set_clr(xq
, set_bits
, (uint16
) ~set_bits
);
1707 /* clear interrupts unconditionally */
1710 /* init read queue (first time only) */
1711 status
= ethq_init(&xq
->var
->ReadQ
, XQ_QUE_MAX
);
1712 if (status
!= SCPE_OK
)
1715 /* clear read queue */
1716 ethq_clear(&xq
->var
->ReadQ
);
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);
1723 /* start service timer */
1724 sim_activate_abs(&xq
->unit
[0], tmxr_poll
);
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
;
1735 void xq_reset_santmr(CTLR
* xq
)
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
);
1741 /* reset sanity countdown timer to max count */
1742 xq
->var
->sanity
.timer
= xq
->var
->sanity
.max
;
1746 t_stat
xq_boot_host(CTLR
* xq
)
1748 sim_debug(DBG_TRC
, xq
->dev
, "xq_boot_host()\n");
1750 The manual says the hardware should force the Qbus BDCOK low for
1751 3.6 microseconds, which will cause the host to reboot.
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.
1760 t_stat
xq_system_id (CTLR
* xq
, const ETH_MAC dest
, uint16 receipt_id
)
1762 static uint16 receipt
= 0;
1764 uint8
* const msg
= &system_id
.msg
[0];
1767 sim_debug(DBG_TRC
, xq
->dev
, "xq_system_id()\n");
1768 if (xq
->var
->type
!= XQ_T_DELQA
) /* DELQA-only function */
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 */
1781 msg
[18] = receipt_id
& 0xFF; /* receipt number */
1782 msg
[19] = (receipt_id
>> 8) & 0xFF; /* receipt number */
1784 msg
[18] = receipt
& 0xFF; /* receipt number */
1785 msg
[19] = (receipt
++ >> 8) & 0xFF; /* receipt number */
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 */
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 */
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 */
1810 msg
[40] = 37; /* type */
1811 msg
[41] = 0x00; /* type */
1812 msg
[42] = 0x01; /* length */
1813 msg
[43] = 0x11; /* value (0x11=DELQA) */
1815 /* write system id */
1817 status
= eth_write(xq
->var
->etherface
, &system_id
, NULL
);
1823 ** service routine - used for ethernet reading loop
1825 t_stat
xq_svc(UNIT
* uptr
)
1827 CTLR
* xq
= xq_unit2ctlr(uptr
);
1829 /* if the receiver is enabled */
1830 if (xq
->var
->csr
& XQ_CSR_RE
) {
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
);
1838 /* Now read and queue packets that have arrived */
1839 /* This is repeated as long as they are available and we have room */
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
);
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
);
1852 /* has sanity timer expired? if so, reboot */
1853 if (xq
->var
->sanity
.enabled
)
1854 if (--xq
->var
->sanity
.timer
<= 0)
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);
1862 /* reset system ID counter for next event */
1863 xq
->var
->idtmr
= XQ_SYSTEM_ID_SECS
* xq
->var
->poll
;
1866 /* resubmit service timer */
1867 sim_activate(&xq
->unit
[0], tmxr_poll
);
1873 /* attach device: */
1874 t_stat
xq_attach(UNIT
* uptr
, char* cptr
)
1878 CTLR
* xq
= xq_unit2ctlr(uptr
);
1879 char buffer
[80]; /* buffer for runtime input */
1881 sim_debug(DBG_TRC
, xq
->dev
, "xq_attach(cptr=%s)\n", cptr
);
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 */
1893 tptr
= (char *) malloc(strlen(cptr
) + 1);
1894 if (tptr
== NULL
) return SCPE_MEM
;
1897 xq
->var
->etherface
= (ETH_DEV
*) malloc(sizeof(ETH_DEV
));
1898 if (!xq
->var
->etherface
) return SCPE_MEM
;
1900 status
= eth_open(xq
->var
->etherface
, cptr
, xq
->dev
, DBG_ETH
);
1901 if (status
!= SCPE_OK
) {
1903 free(xq
->var
->etherface
);
1904 xq
->var
->etherface
= 0;
1907 uptr
->filename
= tptr
;
1908 uptr
->flags
|= UNIT_ATT
;
1910 /* turn on transceiver power indicator */
1911 xq_csr_set_clr(xq
, XQ_CSR_OK
, 0);
1913 /* reset the device with the new attach info */
1919 /* detach device: */
1921 t_stat
xq_detach(UNIT
* uptr
)
1923 CTLR
* xq
= xq_unit2ctlr(uptr
);
1924 sim_debug(DBG_TRC
, xq
->dev
, "xq_detach()\n");
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]);
1937 /* turn off transceiver power indicator */
1938 xq_csr_set_clr(xq
, 0, XQ_CSR_OK
);
1943 void xq_setint(CTLR
* xq
)
1950 void xq_clrint(CTLR
* xq
)
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 */
1960 CLR_INT(XQ
); /* clear master interrupt */
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 */
1974 return 0; /* no interrupt request active */
1977 void xq_csr_set_clr (CTLR
* xq
, uint16 set_bits
, uint16 clear_bits
)
1979 uint16 saved_csr
= xq
->var
->csr
;
1981 /* set the bits in the csr */
1982 xq
->var
->csr
= (xq
->var
->csr
| set_bits
) & ~clear_bits
;
1984 sim_debug_u16(DBG_CSR
, xq
->dev
, xq_csr_bits
, saved_csr
, xq
->var
->csr
, 1);
1986 /* check and correct the state of controller interrupt */
1988 /* if IE is transitioning, process it */
1989 if ((saved_csr
^ xq
->var
->csr
) & XQ_CSR_IE
) {
1991 /* if IE transitioning low and interrupt set, clear interrupt */
1992 if ((clear_bits
& XQ_CSR_IE
) && xq
->var
->irq
)
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
)
2000 } else { /* IE is not transitioning */
2002 /* if interrupts are enabled */
2003 if (xq
->var
->csr
& XQ_CSR_IE
) {
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
) {
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
)
2021 } /* IE transitioning */
2024 /*==============================================================================
2025 / debugging routines
2026 /=============================================================================*/
2029 void xq_debug_setup(CTLR
* xq
)
2033 if (xq
->var
->write_buffer
.msg
[0])
2034 printf ("%s: setup> MOP info present!\n", xq
->dev
->name
);
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
);
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
);