1 /* pdp11_rq.c: MSCP disk controller simulator
2 
3    Copyright (c) 2002-2010, Robert M Supnik
4    Derived from work by Stephen F. Shirron
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    ROBERT M SUPNIK 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 Robert M Supnik 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 Robert M Supnik.
26 
27    rq           RQDX3 disk controller
28 
29    14-Jan-09    JH      Added support for RD32 disc drive
30    18-Jun-07    RMS     Added UNIT_IDLE flag to timer thread
31    31-Oct-05    RMS     Fixed address width for large files
32    16-Aug-05    RMS     Fixed C++ declaration and cast problems
33    22-Jul-05    RMS     Fixed warning from Solaris C (Doug Gwyn)
34    17-Jan-05    RMS     Added more RA and RD disks
35    31-Oct-04    RMS     Added -L switch (LBNs) to RAUSER size specification
36    01-Oct-04    RMS     Revised Unibus interface
37                         Changed to identify as UDA50 in Unibus configurations
38                         Changed width to be 16b in all configurations
39                         Changed default timing for VAX
40    24-Jul-04    RMS     VAX controllers luns start with 0 (Andreas Cejna)
41    05-Feb-04    RMS     Revised for file I/O library
42    25-Jan-04    RMS     Revised for device debug support
43    12-Jan-04    RMS     Fixed bug in interrupt control (Tom Evans)
44    07-Oct-03    RMS     Fixed problem with multiple RAUSER drives
45    17-Sep-03    RMS     Fixed MB to LBN conversion to be more accurate
46    11-Jul-03    RMS     Fixed bug in user disk size (Chaskiel M Grundman)
47    19-May-03    RMS     Revised for new conditional compilation scheme
48    25-Apr-03    RMS     Revised for extended file support
49    14-Mar-03    RMS     Fixed variable size interaction with save/restore
50    27-Feb-03    RMS     Added user-defined drive support
51    26-Feb-03    RMS     Fixed bug in vector calculation for VAXen
52    22-Feb-03    RMS     Fixed ordering bug in queue process
53    12-Oct-02    RMS     Added multicontroller support
54    29-Sep-02    RMS     Changed addressing to 18b in Unibus mode
55                         Added variable address support to bootstrap
56                         Added vector display support
57                         Fixed status code in HBE error log
58                         Consolidated MSCP/TMSCP header file
59                         New data structures
60    16-Aug-02    RMS     Removed unused variables (David Hittner)
61    04-May-02    RMS     Fixed bug in polling loop for queued operations
62    26-Mar-02    RMS     Fixed bug, reset routine cleared UF_WPH
63    09-Mar-02    RMS     Adjusted delays for M+ timing bugs
64    04-Mar-02    RMS     Added delays to initialization for M+, RSTS/E
65    16-Feb-02    RMS     Fixed bugs in host timeout logic, boot
66    26-Jan-02    RMS     Revised bootstrap to conform to M9312
67    06-Jan-02    RMS     Revised enable/disable support
68    30-Dec-01    RMS     Revised show routines
69    19-Dec-01    RMS     Added bigger drives
70    17-Dec-01    RMS     Added queue process
71 */
72 
73 #if defined (VM_PDP10)                                  /* PDP10 version */
74 #error "RQDX3 not supported on PDP-10!"
75 
76 #elif defined (VM_VAX)                                  /* VAX version */
77 #include "vax_defs.h"
78 #define RQ_QTIME        100
79 #define RQ_XTIME        200
80 #define OLDPC           fault_PC
81 extern int32 fault_PC;
82 
83 #else                                                   /* PDP-11 version */
84 #include "pdp11_defs.h"
85 #define RQ_QTIME        200
86 #define RQ_XTIME        500
87 #define OLDPC           MMR2
88 extern int32 MMR2;
89 extern uint32 cpu_opt;
90 #endif
91 
92 #if !defined (RQ_NUMCT)
93 #define RQ_NUMCT        4
94 #elif (RQ_NUMCT > 4)
95 #error "Assertion failure: RQ_NUMCT exceeds 4"
96 #endif
97 
98 #include "pdp11_uqssp.h"
99 #include "pdp11_mscp.h"
100 
101 #define UF_MSK          (UF_CMR|UF_CMW)                 /* settable flags */
102 
103 #define RQ_SH_MAX       24                              /* max display wds */
104 #define RQ_SH_PPL       8                               /* wds per line */
105 #define RQ_SH_DPL       4                               /* desc per line */
106 #define RQ_SH_RI        001                             /* show rings */
107 #define RQ_SH_FR        002                             /* show free q */
108 #define RQ_SH_RS        004                             /* show resp q */
109 #define RQ_SH_UN        010                             /* show unit q's */
110 #define RQ_SH_ALL       017                             /* show all */
111 
112 #define RQ_CLASS        1                               /* RQ class */
113 #define RQU_UQPM        6                               /* UB port model */
114 #define RQQ_UQPM        19                              /* QB port model */
115 #define RQ_UQPM         (UNIBUS? RQU_UQPM: RQQ_UQPM)
116 #define RQU_MODEL       6                               /* UB MSCP ctrl model */
117 #define RQQ_MODEL       19                              /* QB MSCP ctrl model */
118 #define RQ_MODEL        (UNIBUS? RQU_MODEL: RQQ_MODEL)
119 #define RQ_HVER         1                               /* hardware version */
120 #define RQ_SVER         3                               /* software version */
121 #define RQ_DHTMO        60                              /* def host timeout */
122 #define RQ_DCTMO        120                             /* def ctrl timeout */
123 #define RQ_NUMDR        4                               /* # drives */
124 #define RQ_NUMBY        512                             /* bytes per block */
125 #define RQ_MAXFR        (1 << 16)                       /* max xfer */
126 
127 #define UNIT_V_ONL      (UNIT_V_UF + 0)                 /* online */
128 #define UNIT_V_WLK      (UNIT_V_UF + 1)                 /* hwre write lock */
129 #define UNIT_V_ATP      (UNIT_V_UF + 2)                 /* attn pending */
130 #define UNIT_V_DTYPE    (UNIT_V_UF + 3)                 /* drive type */
131 #define UNIT_M_DTYPE    0x1F
132 #define UNIT_ONL        (1 << UNIT_V_ONL)
133 #define UNIT_WLK        (1 << UNIT_V_WLK)
134 #define UNIT_ATP        (1 << UNIT_V_ATP)
135 #define UNIT_DTYPE      (UNIT_M_DTYPE << UNIT_V_DTYPE)
136 #define GET_DTYPE(x)    (((x) >> UNIT_V_DTYPE) & UNIT_M_DTYPE)
137 #define cpkt            u3                              /* current packet */
138 #define pktq            u4                              /* packet queue */
139 #define uf              buf                             /* settable unit flags */
140 #define cnum            wait                            /* controller index */
141 #define UNIT_WPRT       (UNIT_WLK | UNIT_RO)            /* write prot */
142 #define RQ_RMV(u)       ((drv_tab[GET_DTYPE (u->flags)].flgs & RQDF_RMV)? \
143                         UF_RMV: 0)
144 #define RQ_WPH(u)       (((drv_tab[GET_DTYPE (u->flags)].flgs & RQDF_RO) || \
145                         (u->flags & UNIT_WPRT))? UF_WPH: 0)
146 
147 #define CST_S1          0                               /* init stage 1 */
148 #define CST_S1_WR       1                               /* stage 1 wrap */
149 #define CST_S2          2                               /* init stage 2 */
150 #define CST_S3          3                               /* init stage 3 */
151 #define CST_S3_PPA      4                               /* stage 3 sa wait */
152 #define CST_S3_PPB      5                               /* stage 3 ip wait */
153 #define CST_S4          6                               /* stage 4 */
154 #define CST_UP          7                               /* online */
155 #define CST_DEAD        8                               /* fatal error */
156 
157 #define ERR             0                               /* must be SCPE_OK! */
158 #define OK              1
159 
160 #define RQ_TIMER        (RQ_NUMDR)
161 #define RQ_QUEUE        (RQ_TIMER + 1)
162 
163 /* Internal packet management.  The real RQDX3 manages its packets as true
164    linked lists.  However, use of actual addresses in structures won't work
165    with save/restore.  Accordingly, the packets are an arrayed structure,
166    and links are actually subscripts.  To minimize complexity, packet[0]
167    is not used (0 = end of list), and the number of packets must be a power
168    of two.
169 */
170 
171 #define RQ_NPKTS        32                              /* # packets (pwr of 2) */
172 #define RQ_M_NPKTS      (RQ_NPKTS - 1)                  /* mask */
173 #define RQ_PKT_SIZE_W   32                              /* payload size (wds) */
174 #define RQ_PKT_SIZE     (RQ_PKT_SIZE_W * sizeof (int16))
175 
176 struct rqpkt {
177     int16       link;                                   /* link to next */
178     uint16      d[RQ_PKT_SIZE_W];                       /* data */
179     };
180 
181 /* Packet payload extraction and insertion; cp defines controller */
182 
183 #define GETP(p,w,f)     ((cp->pak[p].d[w] >> w##_V_##f) & w##_M_##f)
184 #define GETP32(p,w)     (((uint32) cp->pak[p].d[w]) | \
185                         (((uint32) cp->pak[p].d[(w)+1]) << 16))
186 #define PUTP32(p,w,x)   cp->pak[p].d[w] = (x) & 0xFFFF; \
187                         cp->pak[p].d[(w)+1] = ((x) >> 16) & 0xFFFF
188 
189 /* Disk formats.  An RQDX3 disk consists of the following regions:
190 
191    XBNs         Extended blocks - contain information about disk format,
192                 also holds track being reformatted during bad block repl.
193                 Size = sectors/track + 1, replicated 3 times.
194    DBNs         Diagnostic blocks - used by diagnostics.  Sized to pad
195                 out the XBNs to a cylinder boundary.
196    LBNs         Logical blocks - contain user information.
197    RCT          Replacement control table - first block contains status,
198                 second contains data from block being replaced, remaining
199                 contain information about replaced bad blocks.
200                 Size = RBNs/128 + 3, replicated 4-8 times.
201    RBNs         Replacement blocks - used to replace bad blocks.
202 
203    The simulator does not need to perform bad block replacement; the
204    information below is for simulating RCT reads, if required.
205 
206    Note that an RA drive has a different order: LBNs, RCT, XBN, DBN;
207    the RBNs are spare blocks at the end of every track.
208 */
209 
210 #define RCT_OVHD        2                               /* #ovhd blks */
211 #define RCT_ENTB        128                             /* entries/blk */
212 #define RCT_END         0x80000000                      /* marks RCT end */
213 
214 /* The RQDX3 supports multiple disk drive types (x = not implemented):
215 
216    type sec     surf    cyl     tpg     gpc     RCT     LBNs
217 
218    RX50 10      1       80      5       16      -       800
219    RX33 15      2       80      2       1       -       2400
220    RD51 18      4       306     4       1       36*4    21600
221    RD31 17      4       615     4       1       3*8     41560
222    RD52 17      8       512     8       1       4*8     60480
223    RD32 17      6       820     6       1       4*8     83204
224 x  RD33 17      7       1170    ?       ?       ?       138565
225    RD53 17      7       1024    7       1       5*8     138672
226    RD54 17      15      1225    15      1       7*8     311200
227 
228    The simulator also supports larger drives that only existed
229    on SDI controllers.
230 
231    RA60 42(+1)  6       1600    6       1       1008    400176
232 x  RA70 33(+1)  11      1507+   11      1       ?       547041
233    RA81 51(+1)  14      1258    14      1       2856    891072
234    RA82 57(+1)  15      1435    15      1       3420    1216665
235    RA71 51(+1)  14      1921    14      1       1428    1367310
236    RA72 51(+1)  20      1921    20      1       2040    1953300
237    RA90 69(+1)  13      2656    13      1       1794    2376153
238    RA92 73(+1)  13      3101    13      1       949     2940951
239 x  RA73 70(+1)  21      2667+   21      1       ?       3920490
240 
241    Each drive can be a different type.  The drive field in the
242    unit flags specified the drive type and thus, indirectly,
243    the drive size.
244 */
245 
246 #define RQDF_RMV        01                              /* removable */
247 #define RQDF_RO         02                              /* read only */
248 #define RQDF_SDI        04                              /* SDI drive */
249 
250 #define RX50_DTYPE      0
251 #define RX50_SECT       10
252 #define RX50_SURF       1
253 #define RX50_CYL        80
254 #define RX50_TPG        5
255 #define RX50_GPC        16
256 #define RX50_XBN        0
257 #define RX50_DBN        0
258 #define RX50_LBN        800
259 #define RX50_RCTS       0
260 #define RX50_RCTC       0
261 #define RX50_RBN        0
262 #define RX50_MOD        7
263 #define RX50_MED        0x25658032
264 #define RX50_FLGS       RQDF_RMV
265 
266 #define RX33_DTYPE      1
267 #define RX33_SECT       15
268 #define RX33_SURF       2
269 #define RX33_CYL        80
270 #define RX33_TPG        2
271 #define RX33_GPC        1
272 #define RX33_XBN        0
273 #define RX33_DBN        0
274 #define RX33_LBN        2400
275 #define RX33_RCTS       0
276 #define RX33_RCTC       0
277 #define RX33_RBN        0
278 #define RX33_MOD        10
279 #define RX33_MED        0x25658021
280 #define RX33_FLGS       RQDF_RMV
281 
282 #define RD51_DTYPE      2
283 #define RD51_SECT       18
284 #define RD51_SURF       4
285 #define RD51_CYL        306
286 #define RD51_TPG        4
287 #define RD51_GPC        1
288 #define RD51_XBN        57
289 #define RD51_DBN        87
290 #define RD51_LBN        21600
291 #define RD51_RCTS       36
292 #define RD51_RCTC       4
293 #define RD51_RBN        144
294 #define RD51_MOD        6
295 #define RD51_MED        0x25644033
296 #define RD51_FLGS       0
297 
298 #define RD31_DTYPE      3
299 #define RD31_SECT       17
300 #define RD31_SURF       4
301 #define RD31_CYL        615                             /* last unused */
302 #define RD31_TPG        RD31_SURF
303 #define RD31_GPC        1
304 #define RD31_XBN        54
305 #define RD31_DBN        14
306 #define RD31_LBN        41560
307 #define RD31_RCTS       3
308 #define RD31_RCTC       8
309 #define RD31_RBN        100
310 #define RD31_MOD        12
311 #define RD31_MED        0x2564401F
312 #define RD31_FLGS       0
313 
314 #define RD52_DTYPE      4                               /* Quantum params */
315 #define RD52_SECT       17
316 #define RD52_SURF       8
317 #define RD52_CYL        512
318 #define RD52_TPG        RD52_SURF
319 #define RD52_GPC        1
320 #define RD52_XBN        54
321 #define RD52_DBN        82
322 #define RD52_LBN        60480
323 #define RD52_RCTS       4
324 #define RD52_RCTC       8
325 #define RD52_RBN        168
326 #define RD52_MOD        8
327 #define RD52_MED        0x25644034
328 #define RD52_FLGS       0
329 
330 #define RD53_DTYPE      5
331 #define RD53_SECT       17
332 #define RD53_SURF       8
333 #define RD53_CYL        1024                            /* last unused */
334 #define RD53_TPG        RD53_SURF
335 #define RD53_GPC        1
336 #define RD53_XBN        54
337 #define RD53_DBN        82
338 #define RD53_LBN        138672
339 #define RD53_RCTS       5
340 #define RD53_RCTC       8
341 #define RD53_RBN        280
342 #define RD53_MOD        9
343 #define RD53_MED        0x25644035
344 #define RD53_FLGS       0
345 
346 #define RD54_DTYPE      6
347 #define RD54_SECT       17
348 #define RD54_SURF       15
349 #define RD54_CYL        1225                            /* last unused */
350 #define RD54_TPG        RD54_SURF
351 #define RD54_GPC        1
352 #define RD54_XBN        54
353 #define RD54_DBN        201
354 #define RD54_LBN        311200
355 #define RD54_RCTS       7
356 #define RD54_RCTC       8
357 #define RD54_RBN        609
358 #define RD54_MOD        13
359 #define RD54_MED        0x25644036
360 #define RD54_FLGS       0
361 
362 #define RA82_DTYPE      7                               /* SDI drive */
363 #define RA82_SECT       57                              /* +1 spare/track */
364 #define RA82_SURF       15
365 #define RA82_CYL        1435                            /* 0-1422 user */
366 #define RA82_TPG        RA82_SURF
367 #define RA82_GPC        1
368 #define RA82_XBN        3480                            /* cyl 1427-1430 */
369 #define RA82_DBN        3480                            /* cyl 1431-1434 */
370 #define RA82_LBN        1216665                         /* 57*15*1423 */
371 #define RA82_RCTS       3420                            /* cyl 1423-1426 */
372 #define RA82_RCTC       1
373 #define RA82_RBN        21345                           /* 1 *15*1423 */
374 #define RA82_MOD        11
375 #define RA82_MED        0x25641052
376 #define RA82_FLGS       RQDF_SDI
377 
378 #define RRD40_DTYPE     8
379 #define RRD40_SECT      128
380 #define RRD40_SURF      1
381 #define RRD40_CYL       10400
382 #define RRD40_TPG       RRD40_SURF
383 #define RRD40_GPC       1
384 #define RRD40_XBN       0
385 #define RRD40_DBN       0
386 #define RRD40_LBN       1331200
387 #define RRD40_RCTS      0
388 #define RRD40_RCTC      0
389 #define RRD40_RBN       0
390 #define RRD40_MOD       26
391 #define RRD40_MED       0x25652228
392 #define RRD40_FLGS      (RQDF_RMV | RQDF_RO)
393 
394 #define RA72_DTYPE      9                               /* SDI drive */
395 #define RA72_SECT       51                              /* +1 spare/trk */
396 #define RA72_SURF       20
397 #define RA72_CYL        1921                            /* 0-1914 user */
398 #define RA72_TPG        RA72_SURF
399 #define RA72_GPC        1
400 #define RA72_XBN        2080                            /* cyl 1917-1918? */
401 #define RA72_DBN        2080                            /* cyl 1920-1921? */
402 #define RA72_LBN        1953300                         /* 51*20*1915 */
403 #define RA72_RCTS       2040                            /* cyl 1915-1916? */
404 #define RA72_RCTC       1
405 #define RA72_RBN        38300                           /* 1 *20*1915 */
406 #define RA72_MOD        37
407 #define RA72_MED        0x25641048
408 #define RA72_FLGS       RQDF_SDI
409 
410 #define RA90_DTYPE      10                              /* SDI drive */
411 #define RA90_SECT       69                              /* +1 spare/trk */
412 #define RA90_SURF       13
413 #define RA90_CYL        2656                            /* 0-2648 user */
414 #define RA90_TPG        RA90_SURF
415 #define RA90_GPC        1
416 #define RA90_XBN        1820                            /* cyl 2651-2652? */
417 #define RA90_DBN        1820                            /* cyl 2653-2654? */
418 #define RA90_LBN        2376153                         /* 69*13*2649 */
419 #define RA90_RCTS       1794                            /* cyl 2649-2650? */
420 #define RA90_RCTC       1
421 #define RA90_RBN        34437                           /* 1 *13*2649 */
422 #define RA90_MOD        19
423 #define RA90_MED        0x2564105A
424 #define RA90_FLGS       RQDF_SDI
425 
426 #define RA92_DTYPE      11                              /* SDI drive */
427 #define RA92_SECT       73                              /* +1 spare/trk */
428 #define RA92_SURF       13
429 #define RA92_CYL        3101                            /* 0-3098 user */
430 #define RA92_TPG        RA92_SURF
431 #define RA92_GPC        1
432 #define RA92_XBN        174                             /* cyl 3100? */
433 #define RA92_DBN        788
434 #define RA92_LBN        2940951                         /* 73*13*3099 */
435 #define RA92_RCTS       949                             /* cyl 3099? */
436 #define RA92_RCTC       1
437 #define RA92_RBN        40287                           /* 1 *13*3099 */
438 #define RA92_MOD        29
439 #define RA92_MED        0x2564105C
440 #define RA92_FLGS       RQDF_SDI
441 
442 #define RA8U_DTYPE      12                              /* user defined */
443 #define RA8U_SECT       57                              /* from RA82 */
444 #define RA8U_SURF       15
445 #define RA8U_CYL        1435                            /* from RA82 */
446 #define RA8U_TPG        RA8U_SURF
447 #define RA8U_GPC        1
448 #define RA8U_XBN        0
449 #define RA8U_DBN        0
450 #define RA8U_LBN        1216665                         /* from RA82 */
451 #define RA8U_RCTS       400
452 #define RA8U_RCTC       8
453 #define RA8U_RBN        21345
454 #define RA8U_MOD        11                              /* RA82 */
455 #define RA8U_MED        0x25641052                      /* RA82 */
456 #define RA8U_FLGS       RQDF_SDI
457 #define RA8U_MINC       10000                           /* min cap LBNs */
458 #define RA8U_MAXC       4000000                         /* max cap LBNs */
459 #define RA8U_EMAXC      2000000000                      /* ext max cap */
460 
461 #define RA60_DTYPE      13                              /* SDI drive */
462 #define RA60_SECT       42                              /* +1 spare/track */
463 #define RA60_SURF       6
464 #define RA60_CYL        1600                            /* 0-1587 user */
465 #define RA60_TPG        RA60_SURF
466 #define RA60_GPC        1
467 #define RA60_XBN        1032                            /* cyl 1592-1595 */
468 #define RA60_DBN        1032                            /* cyl 1596-1599 */
469 #define RA60_LBN        400176                          /* 42*6*1588 */
470 #define RA60_RCTS       1008                            /* cyl 1588-1591 */
471 #define RA60_RCTC       1
472 #define RA60_RBN        9528                            /* 1 *6*1588 */
473 #define RA60_MOD        4
474 #define RA60_MED        0x22A4103C
475 #define RA60_FLGS       (RQDF_RMV | RQDF_SDI)
476 
477 #define RA81_DTYPE      14                              /* SDI drive */
478 #define RA81_SECT       51                              /* +1 spare/track */
479 #define RA81_SURF       14
480 #define RA81_CYL        1258                            /* 0-1247 user */
481 #define RA81_TPG        RA81_SURF
482 #define RA81_GPC        1
483 #define RA81_XBN        2436                            /* cyl 1252-1254? */
484 #define RA81_DBN        2436                            /* cyl 1255-1256? */
485 #define RA81_LBN        891072                          /* 51*14*1248 */
486 #define RA81_RCTS       2856                            /* cyl 1248-1251? */
487 #define RA81_RCTC       1
488 #define RA81_RBN        17472                           /* 1 *14*1248 */
489 #define RA81_MOD        5
490 #define RA81_MED        0x25641051
491 #define RA81_FLGS       RQDF_SDI
492 
493 #define RA71_DTYPE      15                              /* SDI drive */
494 #define RA71_SECT       51                              /* +1 spare/track */
495 #define RA71_SURF       14
496 #define RA71_CYL        1921                            /* 0-1914 user */
497 #define RA71_TPG        RA71_SURF
498 #define RA71_GPC        1
499 #define RA71_XBN        1456                            /* cyl 1917-1918? */
500 #define RA71_DBN        1456                            /* cyl 1919-1920? */
501 #define RA71_LBN        1367310                         /* 51*14*1915 */
502 #define RA71_RCTS       1428                            /* cyl 1915-1916? */
503 #define RA71_RCTC       1
504 #define RA71_RBN        26810                           /* 1 *14*1915 */
505 #define RA71_MOD        40
506 #define RA71_MED        0x25641047
507 #define RA71_FLGS       RQDF_SDI
508 
509 #define RD32_DTYPE      16
510 #define RD32_SECT       17
511 #define RD32_SURF       6
512 #define RD32_CYL        820
513 #define RD32_TPG        RD32_SURF
514 #define RD32_GPC        1
515 #define RD32_XBN        54
516 #define RD32_DBN        48
517 #define RD32_LBN        83204
518 #define RD32_RCTS       4
519 #define RD32_RCTC       8
520 #define RD32_RBN        200
521 #define RD32_MOD        15
522 #define RD32_MED        0x25644020
523 #define RD32_FLGS       0
524 
525 struct drvtyp {
526     int32       sect;                                   /* sectors */
527     int32       surf;                                   /* surfaces */
528     int32       cyl;                                    /* cylinders */
529     int32       tpg;                                    /* trk/grp */
530     int32       gpc;                                    /* grp/cyl */
531     int32       xbn;                                    /* XBN size */
532     int32       dbn;                                    /* DBN size */
533     uint32      lbn;                                    /* LBN size */
534     int32       rcts;                                   /* RCT size */
535     int32       rctc;                                   /* RCT copies */
536     int32       rbn;                                    /* RBNs */
537     int32       mod;                                    /* MSCP model */
538     int32       med;                                    /* MSCP media */
539     int32       flgs;                                   /* flags */
540     char        *name;                                  /* name */
541     };
542 
543 #define RQ_DRV(d) \
544     d##_SECT, d##_SURF, d##_CYL,  d##_TPG, \
545     d##_GPC,  d##_XBN,  d##_DBN,  d##_LBN, \
546     d##_RCTS, d##_RCTC, d##_RBN,  d##_MOD, \
547     d##_MED, d##_FLGS
548 #define RQ_SIZE(d)      (d##_LBN * RQ_NUMBY)
549 
550 static struct drvtyp drv_tab[] = {
551     { RQ_DRV (RX50), "RX50" }, { RQ_DRV (RX33), "RX33" },
552     { RQ_DRV (RD51), "RD51" }, { RQ_DRV (RD31), "RD31" },
553     { RQ_DRV (RD52), "RD52" }, { RQ_DRV (RD53), "RD53" },
554     { RQ_DRV (RD54), "RD54" }, { RQ_DRV (RA82), "RA82" },
555     { RQ_DRV (RRD40), "RRD40" }, { RQ_DRV (RA72), "RA72" },
556     { RQ_DRV (RA90), "RA90" }, { RQ_DRV (RA92), "RA92" },
557     { RQ_DRV (RA8U), "RAUSER" }, { RQ_DRV (RA60), "RA60" },
558     { RQ_DRV (RA81), "RA81" }, { RQ_DRV (RA71), "RA71" },
559     { RQ_DRV (RD32), "RD32" },
560     { 0 }
561     };
562 
563 extern int32 int_req[IPL_HLVL];
564 extern int32 tmr_poll, clk_tps;
565 extern UNIT cpu_unit;
566 extern FILE *sim_deb;
567 extern uint32 sim_taddr_64;
568 extern int32 sim_switches;
569 
570 uint16 *rqxb = NULL;                                    /* xfer buffer */
571 int32 rq_itime = 200;                                   /* init time, except */
572 int32 rq_itime4 = 10;                                   /* stage 4 */
573 int32 rq_qtime = RQ_QTIME;                              /* queue time */
574 int32 rq_xtime = RQ_XTIME;                              /* transfer time */
575 
576 typedef struct {
577     uint32              cnum;                           /* ctrl number */
578     uint32              ubase;                          /* unit base */
579     uint32              sa;                             /* status, addr */
580     uint32              saw;                            /* written data */
581     uint32              s1dat;                          /* S1 data */
582     uint32              comm;                           /* comm region */
583     uint32              csta;                           /* ctrl state */
584     uint32              perr;                           /* last error */
585     uint32              cflgs;                          /* ctrl flags */
586     uint32              irq;                            /* intr request */
587     uint32              prgi;                           /* purge int */
588     uint32              pip;                            /* poll in progress */
589     int32               freq;                           /* free list */
590     int32               rspq;                           /* resp list */
591     uint32              pbsy;                           /* #busy pkts */
592     uint32              credits;                        /* credits */
593     uint32              hat;                            /* host timer */
594     uint32              htmo;                           /* host timeout */
595     struct uq_ring      cq;                             /* cmd ring */
596     struct uq_ring      rq;                             /* rsp ring */
597     struct rqpkt        pak[RQ_NPKTS];                  /* packet queue */
598     } MSC;
599 
600 DEVICE rq_dev, rqb_dev, rqc_dev,rqd_dev;
601 
602 t_stat rq_rd (int32 *data, int32 PA, int32 access);
603 t_stat rq_wr (int32 data, int32 PA, int32 access);
604 t_stat rq_svc (UNIT *uptr);
605 t_stat rq_tmrsvc (UNIT *uptr);
606 t_stat rq_quesvc (UNIT *uptr);
607 t_stat rq_reset (DEVICE *dptr);
608 t_stat rq_attach (UNIT *uptr, char *cptr);
609 t_stat rq_detach (UNIT *uptr);
610 t_stat rq_boot (int32 unitno, DEVICE *dptr);
611 t_stat rq_set_wlk (UNIT *uptr, int32 val, char *cptr, void *desc);
612 t_stat rq_set_type (UNIT *uptr, int32 val, char *cptr, void *desc);
613 t_stat rq_show_type (FILE *st, UNIT *uptr, int32 val, void *desc);
614 t_stat rq_show_wlk (FILE *st, UNIT *uptr, int32 val, void *desc);
615 t_stat rq_show_ctrl (FILE *st, UNIT *uptr, int32 val, void *desc);
616 t_stat rq_show_unitq (FILE *st, UNIT *uptr, int32 val, void *desc);
617 
618 t_bool rq_step4 (MSC *cp);
619 t_bool rq_mscp (MSC *cp, int32 pkt, t_bool q);
620 t_bool rq_abo (MSC *cp, int32 pkt, t_bool q);
621 t_bool rq_avl (MSC *cp, int32 pkt, t_bool q);
622 t_bool rq_fmt (MSC *cp, int32 pkt, t_bool q);
623 t_bool rq_gcs (MSC *cp, int32 pkt, t_bool q);
624 t_bool rq_gus (MSC *cp, int32 pkt, t_bool q);
625 t_bool rq_onl (MSC *cp, int32 pkt, t_bool q);
626 t_bool rq_rw (MSC *cp, int32 pkt, t_bool q);
627 t_bool rq_scc (MSC *cp, int32 pkt, t_bool q);
628 t_bool rq_suc (MSC *cp, int32 pkt, t_bool q);
629 t_bool rq_plf (MSC *cp, uint32 err);
630 t_bool rq_dte (MSC *cp, UNIT *uptr, uint32 err);
631 t_bool rq_hbe (MSC *cp, UNIT *uptr);
632 t_bool rq_una (MSC *cp, int32 un);
633 t_bool rq_deqf (MSC *cp, int32 *pkt);
634 int32 rq_deqh (MSC *cp, int32 *lh);
635 void rq_enqh (MSC *cp, int32 *lh, int32 pkt);
636 void rq_enqt (MSC *cp, int32 *lh, int32 pkt);
637 t_bool rq_getpkt (MSC *cp, int32 *pkt);
638 t_bool rq_putpkt (MSC *cp, int32 pkt, t_bool qt);
639 t_bool rq_getdesc (MSC *cp, struct uq_ring *ring, uint32 *desc);
640 t_bool rq_putdesc (MSC *cp, struct uq_ring *ring, uint32 desc);
641 int32 rq_rw_valid (MSC *cp, int32 pkt, UNIT *uptr, uint32 cmd);
642 t_bool rq_rw_end (MSC *cp, UNIT *uptr, uint32 flg, uint32 sts);
643 void rq_putr (MSC *cp, int32 pkt, uint32 cmd, uint32 flg,
644     uint32 sts, uint32 lnt, uint32 typ);
645 void rq_putr_unit (MSC *cp, int32 pkt, UNIT *uptr, uint32 lu, t_bool all);
646 void rq_setf_unit (MSC *cp, int32 pkt, UNIT *uptr);
647 void rq_init_int (MSC *cp);
648 void rq_ring_int (MSC *cp, struct uq_ring *ring);
649 t_bool rq_fatal (MSC *cp, uint32 err);
650 UNIT *rq_getucb (MSC *cp, uint32 lu);
651 int32 rq_map_pa (uint32 pa);
652 void rq_setint (MSC *cp);
653 void rq_clrint (MSC *cp);
654 int32 rq_inta (void);
655 
656 /* RQ data structures
657 
658    rq_dev       RQ device descriptor
659    rq_unit      RQ unit list
660    rq_reg       RQ register list
661    rq_mod       RQ modifier list
662 */
663 
664 MSC rq_ctx = { 0 };
665 
666 DIB rq_dib = {
667     IOBA_RQ, IOLN_RQ, &rq_rd, &rq_wr,
668     1, IVCL (RQ), 0, { &rq_inta }
669     };
670 
671 UNIT rq_unit[] = {
672     { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+
673             (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) },
674     { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+
675             (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) },
676     { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+
677             (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) },
678     { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+
679             (RX50_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RX50)) },
680     { UDATA (&rq_tmrsvc, UNIT_IDLE|UNIT_DIS, 0) },
681     { UDATA (&rq_quesvc, UNIT_DIS, 0) }
682     };
683 
684 REG rq_reg[] = {
685     { GRDATA (SA, rq_ctx.sa, DEV_RDX, 16, 0) },
686     { GRDATA (SAW, rq_ctx.saw, DEV_RDX, 16, 0) },
687     { GRDATA (S1DAT, rq_ctx.s1dat, DEV_RDX, 16, 0) },
688     { GRDATA (COMM, rq_ctx.comm, DEV_RDX, 22, 0) },
689     { GRDATA (CQBA, rq_ctx.cq.ba, DEV_RDX, 22, 0) },
690     { GRDATA (CQLNT, rq_ctx.cq.lnt, DEV_RDX, 8, 2), REG_NZ },
691     { GRDATA (CQIDX, rq_ctx.cq.idx, DEV_RDX, 8, 2) },
692     { GRDATA (RQBA, rq_ctx.rq.ba, DEV_RDX, 22, 0) },
693     { GRDATA (RQLNT, rq_ctx.rq.lnt, DEV_RDX, 8, 2), REG_NZ },
694     { GRDATA (RQIDX, rq_ctx.rq.idx, DEV_RDX, 8, 2) },
695     { DRDATA (FREE, rq_ctx.freq, 5) },
696     { DRDATA (RESP, rq_ctx.rspq, 5) },
697     { DRDATA (PBSY, rq_ctx.pbsy, 5) },
698     { GRDATA (CFLGS, rq_ctx.cflgs, DEV_RDX, 16, 0) },
699     { GRDATA (CSTA, rq_ctx.csta, DEV_RDX, 4, 0) },
700     { GRDATA (PERR, rq_ctx.perr, DEV_RDX, 9, 0) },
701     { DRDATA (CRED, rq_ctx.credits, 5) },
702     { DRDATA (HAT, rq_ctx.hat, 17) },
703     { DRDATA (HTMO, rq_ctx.htmo, 17) },
704     { FLDATA (PRGI, rq_ctx.prgi, 0), REG_HIDDEN },
705     { FLDATA (PIP, rq_ctx.pip, 0), REG_HIDDEN },
706     { FLDATA (INT, rq_ctx.irq, 0) },
707     { DRDATA (ITIME, rq_itime, 24), PV_LEFT + REG_NZ },
708     { DRDATA (I4TIME, rq_itime4, 24), PV_LEFT + REG_NZ },
709     { DRDATA (QTIME, rq_qtime, 24), PV_LEFT + REG_NZ },
710     { DRDATA (XTIME, rq_xtime, 24), PV_LEFT + REG_NZ },
711     { BRDATA (PKTS, rq_ctx.pak, DEV_RDX, 16, RQ_NPKTS * (RQ_PKT_SIZE_W + 1)) },
712     { URDATA (CPKT, rq_unit[0].cpkt, 10, 5, 0, RQ_NUMDR, 0) },
713     { URDATA (PKTQ, rq_unit[0].pktq, 10, 5, 0, RQ_NUMDR, 0) },
714     { URDATA (UFLG, rq_unit[0].uf, DEV_RDX, 16, 0, RQ_NUMDR, 0) },
715     { URDATA (CAPAC, rq_unit[0].capac, 10, T_ADDR_W, 0, RQ_NUMDR, PV_LEFT | REG_HRO) },
716     { GRDATA (DEVADDR, rq_dib.ba, DEV_RDX, 32, 0), REG_HRO },
717     { GRDATA (DEVVEC, rq_dib.vec, DEV_RDX, 16, 0), REG_HRO },
718     { DRDATA (DEVLBN, drv_tab[RA8U_DTYPE].lbn, 22), REG_HRO },
719     { NULL }
720     };
721 
722 MTAB rq_mod[] = {
723     { UNIT_WLK, 0, NULL, "WRITEENABLED", &rq_set_wlk },
724     { UNIT_WLK, UNIT_WLK, NULL, "LOCKED", &rq_set_wlk },
725     { MTAB_XTD | MTAB_VDV | MTAB_NMO, RQ_SH_RI, "RINGS", NULL,
726       NULL, &rq_show_ctrl, 0 },
727     { MTAB_XTD | MTAB_VDV | MTAB_NMO, RQ_SH_FR, "FREEQ", NULL,
728       NULL, &rq_show_ctrl, 0 },
729     { MTAB_XTD | MTAB_VDV | MTAB_NMO, RQ_SH_RS, "RESPQ", NULL,
730       NULL, &rq_show_ctrl, 0 },
731     { MTAB_XTD | MTAB_VDV | MTAB_NMO, RQ_SH_UN, "UNITQ", NULL,
732       NULL, &rq_show_ctrl, 0 },
733     { MTAB_XTD | MTAB_VDV | MTAB_NMO, RQ_SH_ALL, "ALL", NULL,
734       NULL, &rq_show_ctrl, 0 },
735     { MTAB_XTD | MTAB_VUN | MTAB_NMO, 0, "UNITQ", NULL,
736       NULL, &rq_show_unitq, 0 },
737     { MTAB_XTD | MTAB_VUN, 0, "WRITE", NULL,
738       NULL, &rq_show_wlk, NULL },
739     { MTAB_XTD | MTAB_VUN, RX50_DTYPE, NULL, "RX50",
740       &rq_set_type, NULL, NULL },
741     { MTAB_XTD | MTAB_VUN, RX33_DTYPE, NULL, "RX33",
742       &rq_set_type, NULL, NULL },
743     { MTAB_XTD | MTAB_VUN, RD31_DTYPE, NULL, "RD31",
744       &rq_set_type, NULL, NULL },
745     { MTAB_XTD | MTAB_VUN, RD32_DTYPE, NULL, "RD32",
746       &rq_set_type, NULL, NULL },
747     { MTAB_XTD | MTAB_VUN, RD51_DTYPE, NULL, "RD51",
748       &rq_set_type, NULL, NULL },
749     { MTAB_XTD | MTAB_VUN, RD52_DTYPE, NULL, "RD52",
750       &rq_set_type, NULL, NULL },
751     { MTAB_XTD | MTAB_VUN, RD53_DTYPE, NULL, "RD53",
752       &rq_set_type, NULL, NULL },
753     { MTAB_XTD | MTAB_VUN, RD54_DTYPE, NULL, "RD54",
754       &rq_set_type, NULL, NULL },
755     { MTAB_XTD | MTAB_VUN, RA60_DTYPE, NULL, "RA60",
756       &rq_set_type, NULL, NULL },
757     { MTAB_XTD | MTAB_VUN, RA81_DTYPE, NULL, "RA81",
758       &rq_set_type, NULL, NULL },
759     { MTAB_XTD | MTAB_VUN, RA82_DTYPE, NULL, "RA82",
760       &rq_set_type, NULL, NULL },
761     { MTAB_XTD | MTAB_VUN, RRD40_DTYPE, NULL, "RRD40",
762       &rq_set_type, NULL, NULL },
763     { MTAB_XTD | MTAB_VUN, RRD40_DTYPE, NULL, "CDROM",
764       &rq_set_type, NULL, NULL },
765     { MTAB_XTD | MTAB_VUN, RA71_DTYPE, NULL, "RA71",
766       &rq_set_type, NULL, NULL },
767     { MTAB_XTD | MTAB_VUN, RA72_DTYPE, NULL, "RA72",
768       &rq_set_type, NULL, NULL },
769     { MTAB_XTD | MTAB_VUN, RA90_DTYPE, NULL, "RA90",
770       &rq_set_type, NULL, NULL },
771     { MTAB_XTD | MTAB_VUN, RA92_DTYPE, NULL, "RA92",
772       &rq_set_type, NULL, NULL },
773     { MTAB_XTD | MTAB_VUN, RA8U_DTYPE, NULL, "RAUSER",
774       &rq_set_type, NULL, NULL },
775     { MTAB_XTD | MTAB_VUN, 0, "TYPE", NULL,
776       NULL, &rq_show_type, NULL },
777 #if defined (VM_PDP11)
778     { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", "ADDRESS",
779       &set_addr, &show_addr, NULL },
780     { MTAB_XTD | MTAB_VDV, 0, NULL, "AUTOCONFIGURE",
781       &set_addr_flt, NULL, NULL },
782 #else
783     { MTAB_XTD|MTAB_VDV, 004, "ADDRESS", NULL,
784       NULL, &show_addr, NULL },
785 #endif
786     { MTAB_XTD|MTAB_VDV, 0, "VECTOR", NULL,
787       NULL, &show_vec, NULL },
788     { 0 }
789     };
790 
791 DEVICE rq_dev = {
792     "RQ", rq_unit, rq_reg, rq_mod,
793     RQ_NUMDR + 2, DEV_RDX, T_ADDR_W, 2, DEV_RDX, 16,
794     NULL, NULL, &rq_reset,
795     &rq_boot, &rq_attach, &rq_detach,
796     &rq_dib, DEV_FLTA | DEV_DISABLE | DEV_UBUS | DEV_QBUS | DEV_DEBUG
797     };
798 
799 /* RQB data structures
800 
801    rqb_dev      RQB device descriptor
802    rqb_unit     RQB unit list
803    rqb_reg      RQB register list
804    rqb_mod      RQB modifier list
805 */
806 
807 MSC rqb_ctx = { 1 };
808 
809 DIB rqb_dib = {
810     IOBA_RQB, IOLN_RQB, &rq_rd, &rq_wr,
811     1, IVCL (RQ), 0, { &rq_inta }
812     };
813 
814 UNIT rqb_unit[] = {
815     { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+
816             (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) },
817     { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+
818             (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) },
819     { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+
820             (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) },
821     { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+
822             (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) },
823     { UDATA (&rq_tmrsvc, UNIT_DIS, 0) },
824     { UDATA (&rq_quesvc, UNIT_DIS, 0) }
825     };
826 
827 REG rqb_reg[] = {
828     { GRDATA (SA, rqb_ctx.sa, DEV_RDX, 16, 0) },
829     { GRDATA (SAW, rqb_ctx.saw, DEV_RDX, 16, 0) },
830     { GRDATA (S1DAT, rqb_ctx.s1dat, DEV_RDX, 16, 0) },
831     { GRDATA (COMM, rqb_ctx.comm, DEV_RDX, 22, 0) },
832     { GRDATA (CQBA, rqb_ctx.cq.ba, DEV_RDX, 22, 0) },
833     { GRDATA (CQLNT, rqb_ctx.cq.lnt, DEV_RDX, 8, 2), REG_NZ },
834     { GRDATA (CQIDX, rqb_ctx.cq.idx, DEV_RDX, 8, 2) },
835     { GRDATA (RQBA, rqb_ctx.rq.ba, DEV_RDX, 22, 0) },
836     { GRDATA (RQLNT, rqb_ctx.rq.lnt, DEV_RDX, 8, 2), REG_NZ },
837     { GRDATA (RQIDX, rqb_ctx.rq.idx, DEV_RDX, 8, 2) },
838     { DRDATA (FREE, rqb_ctx.freq, 5) },
839     { DRDATA (RESP, rqb_ctx.rspq, 5) },
840     { DRDATA (PBSY, rqb_ctx.pbsy, 5) },
841     { GRDATA (CFLGS, rqb_ctx.cflgs, DEV_RDX, 16, 0) },
842     { GRDATA (CSTA, rqb_ctx.csta, DEV_RDX, 4, 0) },
843     { GRDATA (PERR, rqb_ctx.perr, DEV_RDX, 9, 0) },
844     { DRDATA (CRED, rqb_ctx.credits, 5) },
845     { DRDATA (HAT, rqb_ctx.hat, 17) },
846     { DRDATA (HTMO, rqb_ctx.htmo, 17) },
847     { FLDATA (PRGI, rqb_ctx.prgi, 0), REG_HIDDEN },
848     { FLDATA (PIP, rqb_ctx.pip, 0), REG_HIDDEN },
849     { FLDATA (INT, rqb_ctx.irq, 0) },
850     { BRDATA (PKTS, rqb_ctx.pak, DEV_RDX, 16, RQ_NPKTS * (RQ_PKT_SIZE_W + 1)) },
851     { URDATA (CPKT, rqb_unit[0].cpkt, 10, 5, 0, RQ_NUMDR, 0) },
852     { URDATA (PKTQ, rqb_unit[0].pktq, 10, 5, 0, RQ_NUMDR, 0) },
853     { URDATA (UFLG, rqb_unit[0].uf, DEV_RDX, 16, 0, RQ_NUMDR, 0) },
854     { URDATA (CAPAC, rqb_unit[0].capac, 10, 31, 0, RQ_NUMDR, PV_LEFT | REG_HRO) },
855     { GRDATA (DEVADDR, rqb_dib.ba, DEV_RDX, 32, 0), REG_HRO },
856     { GRDATA (DEVVEC, rqb_dib.vec, DEV_RDX, 16, 0), REG_HRO },
857     { NULL }
858     };
859 
860 DEVICE rqb_dev = {
861     "RQB", rqb_unit, rqb_reg, rq_mod,
862     RQ_NUMDR + 2, DEV_RDX, T_ADDR_W, 2, DEV_RDX, 16,
863     NULL, NULL, &rq_reset,
864     &rq_boot, &rq_attach, &rq_detach,
865     &rqb_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS | DEV_DEBUG
866     };
867 
868 /* RQC data structures
869 
870    rqc_dev      RQC device descriptor
871    rqc_unit     RQC unit list
872    rqc_reg      RQC register list
873    rqc_mod      RQC modifier list
874 */
875 
876 MSC rqc_ctx = { 2 };
877 
878 DIB rqc_dib = {
879     IOBA_RQC, IOLN_RQC, &rq_rd, &rq_wr,
880     1, IVCL (RQ), 0, { &rq_inta }
881     };
882 
883 UNIT rqc_unit[] = {
884     { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+
885             (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) },
886     { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+
887             (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) },
888     { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+
889             (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) },
890     { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+
891             (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) },
892     { UDATA (&rq_tmrsvc, UNIT_DIS, 0) },
893     { UDATA (&rq_quesvc, UNIT_DIS, 0) }
894     };
895 
896 REG rqc_reg[] = {
897     { GRDATA (SA, rqc_ctx.sa, DEV_RDX, 16, 0) },
898     { GRDATA (SAW, rqc_ctx.saw, DEV_RDX, 16, 0) },
899     { GRDATA (S1DAT, rqc_ctx.s1dat, DEV_RDX, 16, 0) },
900     { GRDATA (COMM, rqc_ctx.comm, DEV_RDX, 22, 0) },
901     { GRDATA (CQBA, rqc_ctx.cq.ba, DEV_RDX, 22, 0) },
902     { GRDATA (CQLNT, rqc_ctx.cq.lnt, DEV_RDX, 8, 2), REG_NZ },
903     { GRDATA (CQIDX, rqc_ctx.cq.idx, DEV_RDX, 8, 2) },
904     { GRDATA (RQBA, rqc_ctx.rq.ba, DEV_RDX, 22, 0) },
905     { GRDATA (RQLNT, rqc_ctx.rq.lnt, DEV_RDX, 8, 2), REG_NZ },
906     { GRDATA (RQIDX, rqc_ctx.rq.idx, DEV_RDX, 8, 2) },
907     { DRDATA (FREE, rqc_ctx.freq, 5) },
908     { DRDATA (RESP, rqc_ctx.rspq, 5) },
909     { DRDATA (PBSY, rqc_ctx.pbsy, 5) },
910     { GRDATA (CFLGS, rqc_ctx.cflgs, DEV_RDX, 16, 0) },
911     { GRDATA (CSTA, rqc_ctx.csta, DEV_RDX, 4, 0) },
912     { GRDATA (PERR, rqc_ctx.perr, DEV_RDX, 9, 0) },
913     { DRDATA (CRED, rqc_ctx.credits, 5) },
914     { DRDATA (HAT, rqc_ctx.hat, 17) },
915     { DRDATA (HTMO, rqc_ctx.htmo, 17) },
916     { FLDATA (PRGI, rqc_ctx.prgi, 0), REG_HIDDEN },
917     { FLDATA (PIP, rqc_ctx.pip, 0), REG_HIDDEN },
918     { FLDATA (INT, rqc_ctx.irq, 0) },
919     { BRDATA (PKTS, rqc_ctx.pak, DEV_RDX, 16, RQ_NPKTS * (RQ_PKT_SIZE_W + 1)) },
920     { URDATA (CPKT, rqc_unit[0].cpkt, 10, 5, 0, RQ_NUMDR, 0) },
921     { URDATA (PKTQ, rqc_unit[0].pktq, 10, 5, 0, RQ_NUMDR, 0) },
922     { URDATA (UFLG, rqc_unit[0].uf, DEV_RDX, 16, 0, RQ_NUMDR, 0) },
923     { URDATA (CAPAC, rqc_unit[0].capac, 10, 31, 0, RQ_NUMDR, PV_LEFT | REG_HRO) },
924     { GRDATA (DEVADDR, rqc_dib.ba, DEV_RDX, 32, 0), REG_HRO },
925     { GRDATA (DEVVEC, rqc_dib.vec, DEV_RDX, 16, 0), REG_HRO },
926     { NULL }
927     };
928 
929 DEVICE rqc_dev = {
930     "RQC", rqc_unit, rqc_reg, rq_mod,
931     RQ_NUMDR + 2, DEV_RDX, T_ADDR_W, 2, DEV_RDX, 16,
932     NULL, NULL, &rq_reset,
933     &rq_boot, &rq_attach, &rq_detach,
934     &rqc_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS | DEV_DEBUG
935     };
936 
937 /* RQD data structures
938 
939    rqd_dev      RQ device descriptor
940    rqd_unit     RQ unit list
941    rqd_reg      RQ register list
942    rqd_mod      RQ modifier list
943 */
944 
945 MSC rqd_ctx = { 3 };
946 
947 DIB rqd_dib = {
948     IOBA_RQD, IOLN_RQD, &rq_rd, &rq_wr,
949     1, IVCL (RQ), 0, { &rq_inta }
950     };
951 
952 UNIT rqd_unit[] = {
953     { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+
954             (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) },
955     { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+
956             (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) },
957     { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+
958             (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) },
959     { UDATA (&rq_svc, UNIT_FIX+UNIT_ATTABLE+UNIT_DISABLE+UNIT_ROABLE+
960             (RD54_DTYPE << UNIT_V_DTYPE), RQ_SIZE (RD54)) },
961     { UDATA (&rq_tmrsvc, UNIT_DIS, 0) },
962     { UDATA (&rq_quesvc, UNIT_DIS, 0) }
963     };
964 
965 REG rqd_reg[] = {
966     { GRDATA (SA, rqd_ctx.sa, DEV_RDX, 16, 0) },
967     { GRDATA (SAW, rqd_ctx.saw, DEV_RDX, 16, 0) },
968     { GRDATA (S1DAT, rqd_ctx.s1dat, DEV_RDX, 16, 0) },
969     { GRDATA (COMM, rqd_ctx.comm, DEV_RDX, 22, 0) },
970     { GRDATA (CQBA, rqd_ctx.cq.ba, DEV_RDX, 22, 0) },
971     { GRDATA (CQLNT, rqd_ctx.cq.lnt, DEV_RDX, 8, 2), REG_NZ },
972     { GRDATA (CQIDX, rqd_ctx.cq.idx, DEV_RDX, 8, 2) },
973     { GRDATA (RQBA, rqd_ctx.rq.ba, DEV_RDX, 22, 0) },
974     { GRDATA (RQLNT, rqd_ctx.rq.lnt, DEV_RDX, 8, 2), REG_NZ },
975     { GRDATA (RQIDX, rqd_ctx.rq.idx, DEV_RDX, 8, 2) },
976     { DRDATA (FREE, rqd_ctx.freq, 5) },
977     { DRDATA (RESP, rqd_ctx.rspq, 5) },
978     { DRDATA (PBSY, rqd_ctx.pbsy, 5) },
979     { GRDATA (CFLGS, rqd_ctx.cflgs, DEV_RDX, 16, 0) },
980     { GRDATA (CSTA, rqd_ctx.csta, DEV_RDX, 4, 0) },
981     { GRDATA (PERR, rqd_ctx.perr, DEV_RDX, 9, 0) },
982     { DRDATA (CRED, rqd_ctx.credits, 5) },
983     { DRDATA (HAT, rqd_ctx.hat, 17) },
984     { DRDATA (HTMO, rqd_ctx.htmo, 17) },
985     { FLDATA (PRGI, rqd_ctx.prgi, 0), REG_HIDDEN },
986     { FLDATA (PIP, rqd_ctx.pip, 0), REG_HIDDEN },
987     { FLDATA (INT, rqd_ctx.irq, 0) },
988     { BRDATA (PKTS, rqd_ctx.pak, DEV_RDX, 16, RQ_NPKTS * (RQ_PKT_SIZE_W + 1)) },
989     { URDATA (CPKT, rqd_unit[0].cpkt, 10, 5, 0, RQ_NUMDR, 0) },
990     { URDATA (PKTQ, rqd_unit[0].pktq, 10, 5, 0, RQ_NUMDR, 0) },
991     { URDATA (UFLG, rqd_unit[0].uf, DEV_RDX, 16, 0, RQ_NUMDR, 0) },
992     { URDATA (CAPAC, rqd_unit[0].capac, 10, 31, 0, RQ_NUMDR, PV_LEFT | REG_HRO) },
993     { GRDATA (DEVADDR, rqd_dib.ba, DEV_RDX, 32, 0), REG_HRO },
994     { GRDATA (DEVVEC, rqd_dib.vec, DEV_RDX, 16, 0), REG_HRO },
995     { NULL }
996     };
997 
998 DEVICE rqd_dev = {
999     "RQD", rqd_unit, rqd_reg, rq_mod,
1000     RQ_NUMDR + 2, DEV_RDX, T_ADDR_W, 2, DEV_RDX, 16,
1001     NULL, NULL, &rq_reset,
1002     &rq_boot, &rq_attach, &rq_detach,
1003     &rqd_dib, DEV_FLTA | DEV_DISABLE | DEV_DIS | DEV_UBUS | DEV_QBUS | DEV_DEBUG
1004     };
1005 
1006 static DEVICE *rq_devmap[RQ_NUMCT] = {
1007     &rq_dev, &rqb_dev, &rqc_dev, &rqd_dev
1008     };
1009 
1010 static MSC *rq_ctxmap[RQ_NUMCT] = {
1011     &rq_ctx, &rqb_ctx, &rqc_ctx, &rqd_ctx
1012     };
1013 
1014 /* I/O dispatch routines, I/O addresses 17772150 - 17772152
1015 
1016    base + 0     IP      read/write
1017    base + 2     SA      read/write
1018 */
1019 
rq_rd(int32 * data,int32 PA,int32 access)1020 t_stat rq_rd (int32 *data, int32 PA, int32 access)
1021 {
1022 int32 cidx = rq_map_pa ((uint32) PA);
1023 MSC *cp = rq_ctxmap[cidx];
1024 DEVICE *dptr = rq_devmap[cidx];
1025 
1026 if (cidx < 0)
1027     return SCPE_IERR;
1028 switch ((PA >> 1) & 01) {                               /* decode PA<1> */
1029 
1030     case 0:                                             /* IP */
1031         *data = 0;                                      /* reads zero */
1032         if (cp->csta == CST_S3_PPB)                     /* waiting for poll? */
1033             rq_step4 (cp);
1034         else if (cp->csta == CST_UP) {                  /* if up */
1035             if (DEBUG_PRD (dptr))
1036                 fprintf (sim_deb, ">>RQ%c: poll started, PC=%X\n",
1037                          'A' + cp->cnum, OLDPC);
1038             cp->pip = 1;                                /* poll host */
1039             sim_activate (dptr->units + RQ_QUEUE, rq_qtime);
1040             }
1041         break;
1042 
1043     case 1:                                             /* SA */
1044         *data = cp->sa;
1045         break;
1046         }
1047 
1048 return SCPE_OK;
1049 }
1050 
rq_wr(int32 data,int32 PA,int32 access)1051 t_stat rq_wr (int32 data, int32 PA, int32 access)
1052 {
1053 int32 cidx = rq_map_pa ((uint32) PA);
1054 MSC *cp = rq_ctxmap[cidx];
1055 DEVICE *dptr = rq_devmap[cidx];
1056 
1057 if (cidx < 0)
1058     return SCPE_IERR;
1059 switch ((PA >> 1) & 01) {                               /* decode PA<1> */
1060 
1061     case 0:                                             /* IP */
1062         rq_reset (rq_devmap[cidx]);                     /* init device */
1063         if (DEBUG_PRD (dptr))
1064             fprintf (sim_deb, ">>RQ%c: initialization started\n",
1065                      'A' + cp->cnum);
1066         break;
1067 
1068     case 1:                                             /* SA */
1069         cp->saw = data;
1070         if (cp->csta < CST_S4)                          /* stages 1-3 */
1071             sim_activate (dptr->units + RQ_QUEUE, rq_itime);
1072         else if (cp->csta == CST_S4)                    /* stage 4 (fast) */
1073             sim_activate (dptr->units + RQ_QUEUE, rq_itime4);
1074         break;
1075         }
1076 
1077 return SCPE_OK;
1078 }
1079 
1080 /* Map physical address to device context */
1081 
rq_map_pa(uint32 pa)1082 int32 rq_map_pa (uint32 pa)
1083 {
1084 int32 i;
1085 DEVICE *dptr;
1086 DIB *dibp;
1087 
1088 for (i = 0; i < RQ_NUMCT; i++) {                        /* loop thru ctrls */
1089     dptr = rq_devmap[i];                                /* get device */
1090     dibp = (DIB *) dptr->ctxt;                          /* get DIB */
1091     if ((pa >= dibp->ba) &&                             /* in range? */
1092         (pa < (dibp->ba + dibp->lnt)))
1093         return i;                                       /* return ctrl idx */
1094     }
1095 return -1;
1096 }
1097 
1098 /* Transition to step 4 - init communications region */
1099 
rq_step4(MSC * cp)1100 t_bool rq_step4 (MSC *cp)
1101 {
1102 int32 i, lnt;
1103 uint32 base;
1104 uint16 zero[SA_COMM_MAX >> 1];
1105 
1106 cp->rq.ioff = SA_COMM_RI;                               /* set intr offset */
1107 cp->rq.ba = cp->comm;                                   /* set rsp q base */
1108 cp->rq.lnt = SA_S1H_RQ (cp->s1dat) << 2;                /* get resp q len */
1109 cp->cq.ioff = SA_COMM_CI;                               /* set intr offset */
1110 cp->cq.ba = cp->comm + cp->rq.lnt;                      /* set cmd q base */
1111 cp->cq.lnt = SA_S1H_CQ (cp->s1dat) << 2;                /* get cmd q len */
1112 cp->cq.idx = cp->rq.idx = 0;                            /* clear q idx's */
1113 if (cp->prgi)
1114     base = cp->comm + SA_COMM_QQ;
1115 else base = cp->comm + SA_COMM_CI;
1116 lnt = cp->comm + cp->cq.lnt + cp->rq.lnt - base;        /* comm lnt */
1117 if (lnt > SA_COMM_MAX)                                  /* paranoia */
1118     lnt = SA_COMM_MAX;
1119 for (i = 0; i < (lnt >> 1); i++)                        /* clr buffer */
1120     zero[i] = 0;
1121 if (Map_WriteW (base, lnt, zero))                       /* zero comm area */
1122     return rq_fatal (cp, PE_QWE);                       /* error? */
1123 cp->sa = SA_S4 | (RQ_UQPM << SA_S4C_V_MOD) |            /* send step 4 */
1124     (RQ_SVER << SA_S4C_V_VER);
1125 cp->csta = CST_S4;                                      /* set step 4 */
1126 rq_init_int (cp);                                       /* poke host */
1127 return OK;
1128 }
1129 
1130 /* Queue service - invoked when any of the queues (host queue, unit
1131    queues, response queue) require servicing.  Also invoked during
1132    initialization to provide some delay to the next step.
1133 
1134    Process at most one item off each unit queue
1135    If the unit queues were empty, process at most one item off the host queue
1136    Process at most one item off the response queue
1137 
1138    If all queues are idle, terminate thread
1139 */
1140 
rq_quesvc(UNIT * uptr)1141 t_stat rq_quesvc (UNIT *uptr)
1142 {
1143 int32 i, cnid;
1144 int32 pkt = 0;
1145 UNIT *nuptr;
1146 MSC *cp = rq_ctxmap[uptr->cnum];
1147 DEVICE *dptr = rq_devmap[uptr->cnum];
1148 DIB *dibp = (DIB *) dptr->ctxt;
1149 
1150 if (cp->csta < CST_UP) {                                /* still init? */
1151     switch (cp->csta) {                                 /* controller state? */
1152 
1153     case CST_S1:                                        /* need S1 reply */
1154         if (cp->saw & SA_S1H_VL) {                      /* valid? */
1155             if (cp->saw & SA_S1H_WR) {                  /* wrap? */
1156                 cp->sa = cp->saw;                       /* echo data */
1157                 cp->csta = CST_S1_WR;                   /* endless loop */
1158                 }
1159             else {
1160                 cp->s1dat = cp->saw;                    /* save data */
1161                 dibp->vec = (cp->s1dat & SA_S1H_VEC) << 2; /* get vector */
1162                 if (dibp->vec)                          /* if nz, bias */
1163                     dibp->vec = dibp->vec + VEC_Q;
1164                 cp->sa = SA_S2 | SA_S2C_PT | SA_S2C_EC (cp->s1dat);
1165                 cp->csta = CST_S2;                      /* now in step 2 */
1166                 rq_init_int (cp);                       /* intr if req */
1167                 }
1168             }                                           /* end if valid */
1169         break;
1170 
1171     case CST_S1_WR:                                     /* wrap mode */
1172         cp->sa = cp->saw;                               /* echo data */
1173         break;
1174 
1175     case CST_S2:                                        /* need S2 reply */
1176         cp->comm = cp->saw & SA_S2H_CLO;                /* get low addr */
1177         cp->prgi = cp->saw & SA_S2H_PI;                 /* get purge int */
1178         cp->sa = SA_S3 | SA_S3C_EC (cp->s1dat);
1179         cp->csta = CST_S3;                              /* now in step 3 */
1180         rq_init_int (cp);                               /* intr if req */
1181         break;
1182 
1183     case CST_S3:                                        /* need S3 reply */
1184         cp->comm = ((cp->saw & SA_S3H_CHI) << 16) | cp->comm;
1185         if (cp->saw & SA_S3H_PP) {                      /* purge/poll test? */
1186             cp->sa = 0;                                 /* put 0 */
1187             cp->csta = CST_S3_PPA;                      /* wait for 0 write */
1188             }
1189         else rq_step4 (cp);                             /* send step 4 */
1190         break;
1191 
1192     case CST_S3_PPA:                                    /* need purge test */
1193         if (cp->saw)                                    /* data not zero? */
1194             rq_fatal (cp, PE_PPF);
1195         else cp->csta = CST_S3_PPB;                     /* wait for poll */
1196         break;
1197 
1198     case CST_S4:                                        /* need S4 reply */
1199         if (cp->saw & SA_S4H_GO) {                      /* go set? */
1200             if (DEBUG_PRD (dptr))
1201                 fprintf (sim_deb, ">>RQ%c: initialization complete\n", 'A' + cp->cnum);
1202             cp->csta = CST_UP;                          /* we're up */
1203             cp->sa = 0;                                 /* clear SA */
1204             sim_activate (dptr->units + RQ_TIMER, tmr_poll * clk_tps);
1205             if ((cp->saw & SA_S4H_LF)
1206                 && cp->perr) rq_plf (cp, cp->perr);
1207             cp->perr = 0;
1208 			}
1209         break;
1210         }                                               /* end switch */
1211 
1212     return SCPE_OK;
1213     }                                                   /* end if */
1214 
1215 for (i = 0; i < RQ_NUMDR; i++) {                        /* chk unit q's */
1216     nuptr = dptr->units + i;                            /* ptr to unit */
1217     if (nuptr->cpkt || (nuptr->pktq == 0))
1218         continue;
1219     pkt = rq_deqh (cp, &nuptr->pktq);                   /* get top of q */
1220     if (!rq_mscp (cp, pkt, FALSE))                      /* process */
1221         return SCPE_OK;
1222     }
1223 if ((pkt == 0) && cp->pip) {                            /* polling? */
1224     if (!rq_getpkt (cp, &pkt))                          /* get host pkt */
1225         return SCPE_OK;
1226     if (pkt) {                                          /* got one? */
1227         if (DEBUG_PRD (dptr)) {
1228             fprintf (sim_deb, ">>RQ%c: cmd=%04X, mod=%04X, unit=%d, ",
1229                 'A' + cp->cnum, cp->pak[pkt].d[CMD_OPC],
1230                 cp->pak[pkt].d[CMD_MOD], cp->pak[pkt].d[CMD_UN]);
1231             fprintf (sim_deb, "bc=%04X%04X, ma=%04X%04X, lbn=%04X%04X\n",
1232                 cp->pak[pkt].d[RW_BCH], cp->pak[pkt].d[RW_BCL],
1233                 cp->pak[pkt].d[RW_BAH], cp->pak[pkt].d[RW_BAL],
1234                 cp->pak[pkt].d[RW_LBNH], cp->pak[pkt].d[RW_LBNL]);
1235             }
1236         if (GETP (pkt, UQ_HCTC, TYP) != UQ_TYP_SEQ)     /* seq packet? */
1237             return rq_fatal (cp, PE_PIE);               /* no, term thread */
1238         cnid = GETP (pkt, UQ_HCTC, CID);                /* get conn ID */
1239         if (cnid == UQ_CID_MSCP) {                      /* MSCP packet? */
1240             if (!rq_mscp (cp, pkt, TRUE))               /* proc, q non-seq */
1241                 return SCPE_OK;
1242             }
1243         else if (cnid == UQ_CID_DUP) {                  /* DUP packet? */
1244             rq_putr (cp, pkt, OP_END, 0, ST_CMD | I_OPCD, RSP_LNT, UQ_TYP_SEQ);
1245             if (!rq_putpkt (cp, pkt, TRUE))             /* ill cmd */
1246                 return SCPE_OK;
1247             }
1248         else return rq_fatal (cp, PE_ICI);              /* no, term thread */
1249         }                                               /* end if pkt */
1250     else cp->pip = 0;                                   /* discontinue poll */
1251     }                                                   /* end if pip */
1252 if (cp->rspq) {                                         /* resp q? */
1253     pkt = rq_deqh (cp, &cp->rspq);                      /* get top of q */
1254     if (!rq_putpkt (cp, pkt, FALSE))                    /* send to host */
1255         return SCPE_OK;
1256     }                                                   /* end if resp q */
1257 if (pkt)                                                /* more to do? */
1258     sim_activate (uptr, rq_qtime);
1259 return SCPE_OK;                                         /* done */
1260 }
1261 
1262 /* Clock service (roughly once per second) */
1263 
rq_tmrsvc(UNIT * uptr)1264 t_stat rq_tmrsvc (UNIT *uptr)
1265 {
1266 int32 i;
1267 UNIT *nuptr;
1268 MSC *cp = rq_ctxmap[uptr->cnum];
1269 DEVICE *dptr = rq_devmap[uptr->cnum];
1270 
1271 sim_activate (uptr, tmr_poll * clk_tps);                /* reactivate */
1272 for (i = 0; i < RQ_NUMDR; i++) {                        /* poll */
1273     nuptr = dptr->units + i;
1274     if ((nuptr->flags & UNIT_ATP) &&                    /* ATN pending? */
1275         (nuptr->flags & UNIT_ATT) &&                    /* still online? */
1276         (cp->cflgs & CF_ATN)) {                         /* wanted? */
1277         if (!rq_una (cp, i))
1278             return SCPE_OK;
1279         }
1280     nuptr->flags = nuptr->flags & ~UNIT_ATP;
1281     }
1282 if ((cp->hat > 0) && (--cp->hat == 0))                  /* host timeout? */
1283     rq_fatal (cp, PE_HAT);                              /* fatal err */
1284 return SCPE_OK;
1285 }
1286 
1287 /* MSCP packet handling */
1288 
rq_mscp(MSC * cp,int32 pkt,t_bool q)1289 t_bool rq_mscp (MSC *cp, int32 pkt, t_bool q)
1290 {
1291 uint32 sts, cmd = GETP (pkt, CMD_OPC, OPC);
1292 
1293 switch (cmd) {
1294 
1295     case OP_ABO:                                        /* abort */
1296         return rq_abo (cp, pkt, q);
1297 
1298     case OP_AVL:                                        /* avail */
1299         return rq_avl (cp, pkt, q);
1300 
1301     case OP_FMT:                                        /* format */
1302         return rq_fmt (cp, pkt, q);
1303 
1304     case OP_GCS:                                        /* get cmd status */
1305         return rq_gcs (cp, pkt, q);
1306 
1307     case OP_GUS:                                        /* get unit status */
1308         return rq_gus (cp, pkt, q);
1309 
1310     case OP_ONL:                                        /* online */
1311         return rq_onl (cp, pkt, q);
1312 
1313     case OP_SCC:                                        /* set ctrl char */
1314         return rq_scc (cp, pkt, q);
1315 
1316     case OP_SUC:                                        /* set unit char */
1317         return rq_suc (cp, pkt, q);
1318 
1319     case OP_ACC:                                        /* access */
1320     case OP_CMP:                                        /* compare */
1321     case OP_ERS:                                        /* erase */
1322     case OP_RD:                                         /* read */
1323     case OP_WR:                                         /* write */
1324         return rq_rw (cp, pkt, q);
1325 
1326     case OP_CCD:                                        /* nops */
1327     case OP_DAP:
1328     case OP_FLU:
1329         cmd = cmd | OP_END;                             /* set end flag */
1330         sts = ST_SUC;                                   /* success */
1331         break;
1332 
1333     default:
1334         cmd = OP_END;                                   /* set end op */
1335         sts = ST_CMD | I_OPCD;                          /* ill op */
1336         break;
1337         }
1338 
1339 rq_putr (cp, pkt, cmd, 0, sts, RSP_LNT, UQ_TYP_SEQ);
1340 return rq_putpkt (cp, pkt, TRUE);
1341 }
1342 
1343 /* Abort a command - 1st parameter is ref # of cmd to abort */
1344 
rq_abo(MSC * cp,int32 pkt,t_bool q)1345 t_bool rq_abo (MSC *cp, int32 pkt, t_bool q)
1346 {
1347 uint32 lu = cp->pak[pkt].d[CMD_UN];                     /* unit # */
1348 uint32 cmd = GETP (pkt, CMD_OPC, OPC);                  /* opcode */
1349 uint32 ref = GETP32 (pkt, ABO_REFL);                    /* cmd ref # */
1350 int32 tpkt, prv;
1351 UNIT *uptr;
1352 DEVICE *dptr = rq_devmap[cp->cnum];
1353 
1354 tpkt = 0;                                               /* set no mtch */
1355 if ((uptr = rq_getucb (cp, lu))) {                        /* get unit */
1356     if (uptr->cpkt &&                                   /* curr pkt? */
1357         (GETP32 (uptr->cpkt, CMD_REFL) == ref)) {       /* match ref? */
1358         tpkt = uptr->cpkt;                              /* save match */
1359         uptr->cpkt = 0;                                 /* gonzo */
1360         sim_cancel (uptr);                              /* cancel unit */
1361         sim_activate (dptr->units + RQ_QUEUE, rq_qtime);
1362         }
1363     else if (uptr->pktq &&                              /* head of q? */
1364         (GETP32 (uptr->pktq, CMD_REFL) == ref)) {       /* match ref? */
1365         tpkt = uptr->pktq;                              /* save match */
1366         uptr->pktq = cp->pak[tpkt].link;                /* unlink */
1367         }
1368     else if ((prv = uptr->pktq)) {                      /* srch pkt q */
1369         while ((tpkt = cp->pak[prv].link)) {            /* walk list */
1370             if (GETP32 (tpkt, RSP_REFL) == ref) {       /* match? unlink */
1371                 cp->pak[prv].link = cp->pak[tpkt].link;
1372                 break;
1373                 }
1374             }
1375         }
1376     if (tpkt) {                                         /* found target? */
1377         uint32 tcmd = GETP (tpkt, CMD_OPC, OPC);        /* get opcode */
1378         rq_putr (cp, tpkt, tcmd | OP_END, 0, ST_ABO, RSP_LNT, UQ_TYP_SEQ);
1379         if (!rq_putpkt (cp, tpkt, TRUE))
1380             return ERR;
1381         }
1382     }                                                   /* end if unit */
1383 rq_putr (cp, pkt, cmd | OP_END, 0, ST_SUC, ABO_LNT, UQ_TYP_SEQ);
1384 return rq_putpkt (cp, pkt, TRUE);
1385 }
1386 
1387 /* Unit available - set unit status to available - defer if q'd cmds */
1388 
rq_avl(MSC * cp,int32 pkt,t_bool q)1389 t_bool rq_avl (MSC *cp, int32 pkt, t_bool q)
1390 {
1391 uint32 lu = cp->pak[pkt].d[CMD_UN];                     /* unit # */
1392 uint32 cmd = GETP (pkt, CMD_OPC, OPC);                  /* opcode */
1393 uint32 sts;
1394 UNIT *uptr;
1395 
1396 if ((uptr = rq_getucb (cp, lu))) {                      /* unit exist? */
1397     if (q && uptr->cpkt) {                              /* need to queue? */
1398         rq_enqt (cp, &uptr->pktq, pkt);                 /* do later */
1399         return OK;
1400         }
1401     uptr->flags = uptr->flags & ~UNIT_ONL;              /* not online */
1402     uptr->uf = 0;                                       /* clr flags */
1403     sts = ST_SUC;                                       /* success */
1404     }
1405 else sts = ST_OFL;                                      /* offline */
1406 rq_putr (cp, pkt, cmd | OP_END, 0, sts, AVL_LNT, UQ_TYP_SEQ);
1407 return rq_putpkt (cp, pkt, TRUE);
1408 }
1409 
1410 /* Get command status - only interested in active xfr cmd */
1411 
rq_gcs(MSC * cp,int32 pkt,t_bool q)1412 t_bool rq_gcs (MSC *cp, int32 pkt, t_bool q)
1413 {
1414 uint32 lu = cp->pak[pkt].d[CMD_UN];                     /* unit # */
1415 uint32 cmd = GETP (pkt, CMD_OPC, OPC);                  /* opcode */
1416 uint32 ref = GETP32 (pkt, GCS_REFL);                    /* ref # */
1417 int32 tpkt;
1418 UNIT *uptr;
1419 
1420 if ((uptr = rq_getucb (cp, lu)) &&                      /* valid lu? */
1421     (tpkt = uptr->cpkt) &&                              /* queued pkt? */
1422     (GETP32 (tpkt, CMD_REFL) == ref) &&                 /* match ref? */
1423     (GETP (tpkt, CMD_OPC, OPC) >= OP_ACC)) {            /* rd/wr cmd? */
1424 	cp->pak[pkt].d[GCS_STSL] = cp->pak[tpkt].d[RW_WBCL];
1425 	cp->pak[pkt].d[GCS_STSH] = cp->pak[tpkt].d[RW_WBCH];
1426 	}
1427 else {
1428     cp->pak[pkt].d[GCS_STSL] = 0;                       /* return 0 */
1429     cp->pak[pkt].d[GCS_STSH] = 0;
1430     }
1431 rq_putr (cp, pkt, cmd | OP_END, 0, ST_SUC, GCS_LNT, UQ_TYP_SEQ);
1432 return rq_putpkt (cp, pkt, TRUE);
1433 }
1434 
1435 /* Get unit status */
1436 
rq_gus(MSC * cp,int32 pkt,t_bool q)1437 t_bool rq_gus (MSC *cp, int32 pkt, t_bool q)
1438 {
1439 uint32 lu = cp->pak[pkt].d[CMD_UN];                     /* unit # */
1440 uint32 cmd = GETP (pkt, CMD_OPC, OPC);                  /* opcode */
1441 uint32 dtyp, sts, rbpar;
1442 UNIT *uptr;
1443 
1444 if (cp->pak[pkt].d[CMD_MOD] & MD_NXU) {                 /* next unit? */
1445     if (lu >= (cp->ubase + RQ_NUMDR)) {                 /* end of range? */
1446         lu = 0;                                         /* reset to 0 */
1447         cp->pak[pkt].d[RSP_UN] = lu;
1448         }
1449     }
1450 if ((uptr = rq_getucb (cp, lu))) {                      /* unit exist? */
1451     if ((uptr->flags & UNIT_ATT) == 0)                  /* not attached? */
1452         sts = ST_OFL | SB_OFL_NV;                       /* offl no vol */
1453     else if (uptr->flags & UNIT_ONL)                    /* online */
1454         sts = ST_SUC;
1455     else sts = ST_AVL;                                  /* avail */
1456     rq_putr_unit (cp, pkt, uptr, lu, FALSE);            /* fill unit fields */
1457     dtyp = GET_DTYPE (uptr->flags);                     /* get drive type */
1458     if (drv_tab[dtyp].rcts)                             /* ctrl bad blk? */
1459         rbpar = 1;
1460     else rbpar = 0;                                     /* fill geom, bblk */
1461     cp->pak[pkt].d[GUS_TRK] = drv_tab[dtyp].sect;
1462     cp->pak[pkt].d[GUS_GRP] = drv_tab[dtyp].tpg;
1463     cp->pak[pkt].d[GUS_CYL] = drv_tab[dtyp].gpc;
1464     cp->pak[pkt].d[GUS_UVER] = 0;
1465     cp->pak[pkt].d[GUS_RCTS] = drv_tab[dtyp].rcts;
1466     cp->pak[pkt].d[GUS_RBSC] =
1467         (rbpar << GUS_RB_V_RBNS) | (rbpar << GUS_RB_V_RCTC);
1468     }
1469 else sts = ST_OFL;                                      /* offline */
1470 cp->pak[pkt].d[GUS_SHUN] = lu;                          /* shadowing */
1471 cp->pak[pkt].d[GUS_SHST] = 0;
1472 rq_putr (cp, pkt, cmd | OP_END, 0, sts, GUS_LNT_D, UQ_TYP_SEQ);
1473 return rq_putpkt (cp, pkt, TRUE);
1474 }
1475 
1476 /* Unit online - defer if q'd commands */
1477 
rq_onl(MSC * cp,int32 pkt,t_bool q)1478 t_bool rq_onl (MSC *cp, int32 pkt, t_bool q)
1479 {
1480 uint32 lu = cp->pak[pkt].d[CMD_UN];                     /* unit # */
1481 uint32 cmd = GETP (pkt, CMD_OPC, OPC);                  /* opcode */
1482 uint32 sts;
1483 UNIT *uptr;
1484 
1485 if ((uptr = rq_getucb (cp, lu))) {                      /* unit exist? */
1486     if (q && uptr->cpkt) {                              /* need to queue? */
1487         rq_enqt (cp, &uptr->pktq, pkt);                 /* do later */
1488         return OK;
1489         }
1490     if ((uptr->flags & UNIT_ATT) == 0)                  /* not attached? */
1491         sts = ST_OFL | SB_OFL_NV;                       /* offl no vol */
1492     else if (uptr->flags & UNIT_ONL)                    /* already online? */
1493         sts = ST_SUC | SB_SUC_ON;
1494     else {                                              /* mark online */
1495         sts = ST_SUC;
1496         uptr->flags = uptr->flags | UNIT_ONL;
1497         rq_setf_unit (cp, pkt, uptr);                   /* hack flags */
1498         }
1499     rq_putr_unit (cp, pkt, uptr, lu, TRUE);             /* set fields */
1500     }
1501 else sts = ST_OFL;                                      /* offline */
1502 cp->pak[pkt].d[ONL_SHUN] = lu;                          /* shadowing */
1503 cp->pak[pkt].d[ONL_SHST] = 0;
1504 rq_putr (cp, pkt, cmd | OP_END, 0, sts, ONL_LNT, UQ_TYP_SEQ);
1505 return rq_putpkt (cp, pkt, TRUE);
1506 }
1507 
1508 /* Set controller characteristics */
1509 
rq_scc(MSC * cp,int32 pkt,t_bool q)1510 t_bool rq_scc (MSC *cp, int32 pkt, t_bool q)
1511 {
1512 int32 sts, cmd;
1513 
1514 if (cp->pak[pkt].d[SCC_MSV]) {                          /* MSCP ver = 0? */
1515     sts = ST_CMD | I_VRSN;                              /* no, lose */
1516     cmd = 0;
1517     }
1518 else {
1519     sts = ST_SUC;                                       /* success */
1520     cmd = GETP (pkt, CMD_OPC, OPC);                     /* get opcode */
1521     cp->cflgs = (cp->cflgs & CF_RPL) |                  /* hack ctrl flgs */
1522         cp->pak[pkt].d[SCC_CFL];
1523     if ((cp->htmo = cp->pak[pkt].d[SCC_TMO]))           /* set timeout */
1524         cp->htmo = cp->htmo + 2;                        /* if nz, round up */
1525     cp->pak[pkt].d[SCC_CFL] = cp->cflgs;                /* return flags */
1526     cp->pak[pkt].d[SCC_TMO] = RQ_DCTMO;                 /* ctrl timeout */
1527     cp->pak[pkt].d[SCC_VER] = (RQ_HVER << SCC_VER_V_HVER) |
1528         (RQ_SVER << SCC_VER_V_SVER);
1529     cp->pak[pkt].d[SCC_CIDA] = 0;                       /* ctrl ID */
1530     cp->pak[pkt].d[SCC_CIDB] = 0;
1531     cp->pak[pkt].d[SCC_CIDC] = 0;
1532     cp->pak[pkt].d[SCC_CIDD] = (RQ_CLASS << SCC_CIDD_V_CLS) |
1533         (RQ_MODEL << SCC_CIDD_V_MOD);
1534     cp->pak[pkt].d[SCC_MBCL] = 0;                       /* max bc */
1535     cp->pak[pkt].d[SCC_MBCH] = 0;
1536     }
1537 rq_putr (cp, pkt, cmd | OP_END, 0, sts, SCC_LNT, UQ_TYP_SEQ);
1538 return rq_putpkt (cp, pkt, TRUE);
1539 }
1540 
1541 /* Set unit characteristics - defer if q'd commands */
1542 
rq_suc(MSC * cp,int32 pkt,t_bool q)1543 t_bool rq_suc (MSC *cp, int32 pkt, t_bool q)
1544 {
1545 uint32 lu = cp->pak[pkt].d[CMD_UN];                     /* unit # */
1546 uint32 cmd = GETP (pkt, CMD_OPC, OPC);                  /* opcode */
1547 uint32 sts;
1548 UNIT *uptr;
1549 
1550 if ((uptr = rq_getucb (cp, lu))) {                      /* unit exist? */
1551     if (q && uptr->cpkt) {                              /* need to queue? */
1552         rq_enqt (cp, &uptr->pktq, pkt);                 /* do later */
1553         return OK;
1554         }
1555     if ((uptr->flags & UNIT_ATT) == 0)                  /* not attached? */
1556         sts = ST_OFL | SB_OFL_NV;                       /* offl no vol */
1557     else {                                              /* avail or onl */
1558         sts = ST_SUC;
1559         rq_setf_unit (cp, pkt, uptr);                   /* hack flags */
1560         }
1561     rq_putr_unit (cp, pkt, uptr, lu, TRUE);             /* set fields */
1562     }
1563 else sts = ST_OFL;                                      /* offline */
1564 cp->pak[pkt].d[ONL_SHUN] = lu;                          /* shadowing */
1565 cp->pak[pkt].d[ONL_SHST] = 0;
1566 rq_putr (cp, pkt, cmd | OP_END, 0, sts, SUC_LNT, UQ_TYP_SEQ);
1567 return rq_putpkt (cp, pkt, TRUE);
1568 }
1569 
1570 /* Format command - floppies only */
1571 
rq_fmt(MSC * cp,int32 pkt,t_bool q)1572 t_bool rq_fmt (MSC *cp, int32 pkt, t_bool q)
1573 {
1574 uint32 lu = cp->pak[pkt].d[CMD_UN];                     /* unit # */
1575 uint32 cmd = GETP (pkt, CMD_OPC, OPC);                  /* opcode */
1576 uint32 sts;
1577 UNIT *uptr;
1578 
1579 if ((uptr = rq_getucb (cp, lu))) {                      /* unit exist? */
1580     if (q && uptr->cpkt) {                              /* need to queue? */
1581         rq_enqt (cp, &uptr->pktq, pkt);                 /* do later */
1582         return OK;
1583         }
1584     if (GET_DTYPE (uptr->flags) != RX33_DTYPE)          /* RX33? */
1585         sts = ST_CMD | I_OPCD;                          /* no, err */
1586     else if ((cp->pak[pkt].d[FMT_IH] & 0100000) == 0)   /* magic bit set? */
1587         sts = ST_CMD | I_FMTI;                          /* no, err */
1588     else if ((uptr->flags & UNIT_ATT) == 0)             /* offline? */
1589         sts = ST_OFL | SB_OFL_NV;                       /* no vol */
1590     else if (uptr->flags & UNIT_ONL) {                  /* online? */
1591         uptr->flags = uptr->flags & ~UNIT_ONL;
1592         uptr->uf = 0;                                   /* clear flags */
1593         sts = ST_AVL | SB_AVL_INU;                      /* avail, in use */
1594         }
1595     else if (RQ_WPH (uptr))                             /* write prot? */
1596         sts = ST_WPR | SB_WPR_HW;                       /* can't fmt */
1597     else sts = ST_SUC;                                  /*** for now ***/
1598     }
1599 else sts = ST_OFL;                                      /* offline */
1600 rq_putr (cp, pkt, cmd | OP_END, 0, sts, FMT_LNT, UQ_TYP_SEQ);
1601 return rq_putpkt (cp, pkt, TRUE);
1602 }
1603 
1604 /* Data transfer commands */
1605 
rq_rw(MSC * cp,int32 pkt,t_bool q)1606 t_bool rq_rw (MSC *cp, int32 pkt, t_bool q)
1607 {
1608 uint32 lu = cp->pak[pkt].d[CMD_UN];                     /* unit # */
1609 uint32 cmd = GETP (pkt, CMD_OPC, OPC);                  /* opcode */
1610 uint32 sts;
1611 UNIT *uptr;
1612 
1613 if ((uptr = rq_getucb (cp, lu))) {                      /* unit exist? */
1614     if (q && uptr->cpkt) {                              /* need to queue? */
1615         rq_enqt (cp, &uptr->pktq, pkt);                 /* do later */
1616         return OK;
1617         }
1618     sts = rq_rw_valid (cp, pkt, uptr, cmd);             /* validity checks */
1619     if (sts == 0) {                                     /* ok? */
1620         uptr->cpkt = pkt;                               /* op in progress */
1621         cp->pak[pkt].d[RW_WBAL] = cp->pak[pkt].d[RW_BAL];
1622         cp->pak[pkt].d[RW_WBAH] = cp->pak[pkt].d[RW_BAH];
1623         cp->pak[pkt].d[RW_WBCL] = cp->pak[pkt].d[RW_BCL];
1624         cp->pak[pkt].d[RW_WBCH] = cp->pak[pkt].d[RW_BCH];
1625         cp->pak[pkt].d[RW_WBLL] = cp->pak[pkt].d[RW_LBNL];
1626         cp->pak[pkt].d[RW_WBLH] = cp->pak[pkt].d[RW_LBNH];
1627         sim_activate (uptr, rq_xtime);                  /* activate */
1628         return OK;                                      /* done */
1629         }
1630     }
1631 else sts = ST_OFL;                                      /* offline */
1632 cp->pak[pkt].d[RW_BCL] = cp->pak[pkt].d[RW_BCH] = 0;    /* bad packet */
1633 rq_putr (cp, pkt, cmd | OP_END, 0, sts, RW_LNT_D, UQ_TYP_SEQ);
1634 return rq_putpkt (cp, pkt, TRUE);
1635 }
1636 
1637 /* Validity checks */
1638 
rq_rw_valid(MSC * cp,int32 pkt,UNIT * uptr,uint32 cmd)1639 int32 rq_rw_valid (MSC *cp, int32 pkt, UNIT *uptr, uint32 cmd)
1640 {
1641 uint32 dtyp = GET_DTYPE (uptr->flags);                  /* get drive type */
1642 uint32 lbn = GETP32 (pkt, RW_LBNL);                     /* get lbn */
1643 uint32 bc = GETP32 (pkt, RW_BCL);                       /* get byte cnt */
1644 uint32 maxlbn = (uint32) (uptr->capac / RQ_NUMBY);      /* get max lbn */
1645 
1646 if ((uptr->flags & UNIT_ATT) == 0)                      /* not attached? */
1647     return (ST_OFL | SB_OFL_NV);                        /* offl no vol */
1648 if ((uptr->flags & UNIT_ONL) == 0)                      /* not online? */
1649     return ST_AVL;                                      /* only avail */
1650 if ((cmd != OP_ACC) && (cmd != OP_ERS) &&               /* 'real' xfer */
1651     (cp->pak[pkt].d[RW_BAL] & 1))                       /* odd address? */
1652     return (ST_HST | SB_HST_OA);                        /* host buf odd */
1653 if (bc & 1)                                             /* odd byte cnt? */
1654     return (ST_HST | SB_HST_OC);
1655 if (bc & 0xF0000000)                                    /* 'reasonable' bc? */
1656     return (ST_CMD | I_BCNT);
1657 /* if (lbn & 0xF0000000) return (ST_CMD | I_LBN);       /* 'reasonable' lbn? */
1658 if (lbn >= maxlbn) {                                    /* accessing RCT? */
1659     if (lbn >= (maxlbn + drv_tab[dtyp].rcts))           /* beyond copy 1? */
1660         return (ST_CMD | I_LBN);                        /* lbn err */
1661     if (bc != RQ_NUMBY)                                 /* bc must be 512 */
1662         return (ST_CMD | I_BCNT);
1663     }
1664 else if ((lbn + ((bc + (RQ_NUMBY - 1)) / RQ_NUMBY)) > maxlbn)
1665     return (ST_CMD | I_BCNT);                           /* spiral to RCT */
1666 if ((cmd == OP_WR) || (cmd == OP_ERS)) {                /* write op? */
1667     if (lbn >= maxlbn)                                  /* accessing RCT? */
1668         return (ST_CMD | I_LBN);                        /* lbn err */
1669     if (uptr->uf & UF_WPS)                              /* swre wlk? */
1670         return (ST_WPR | SB_WPR_SW);
1671     if (RQ_WPH (uptr))                                  /* hwre wlk? */
1672         return (ST_WPR | SB_WPR_HW);
1673     }
1674 return 0;                                               /* success! */
1675 }
1676 
1677 /* Unit service for data transfer commands */
1678 
rq_svc(UNIT * uptr)1679 t_stat rq_svc (UNIT *uptr)
1680 {
1681 MSC *cp = rq_ctxmap[uptr->cnum];
1682 
1683 uint32 i, t, tbc, abc, wwc;
1684 uint32 err = 0;
1685 int32 pkt = uptr->cpkt;                                 /* get packet */
1686 uint32 cmd = GETP (pkt, CMD_OPC, OPC);                  /* get cmd */
1687 uint32 ba = GETP32 (pkt, RW_WBAL);                      /* buf addr */
1688 uint32 bc = GETP32 (pkt, RW_WBCL);                      /* byte count */
1689 uint32 bl = GETP32 (pkt, RW_WBLL);                      /* block addr */
1690 t_addr da = ((t_addr) bl) * RQ_NUMBY;                   /* disk addr */
1691 
1692 if ((cp == NULL) || (pkt == 0))                         /* what??? */
1693     return STOP_RQ;
1694 tbc = (bc > RQ_MAXFR)? RQ_MAXFR: bc;                    /* trim cnt to max */
1695 
1696 if ((uptr->flags & UNIT_ATT) == 0) {                    /* not attached? */
1697     rq_rw_end (cp, uptr, 0, ST_OFL | SB_OFL_NV);        /* offl no vol */
1698     return SCPE_OK;
1699     }
1700 if (bc == 0) {                                          /* no xfer? */
1701     rq_rw_end (cp, uptr, 0, ST_SUC);                    /* ok by me... */
1702     return SCPE_OK;
1703     }
1704 
1705 if ((cmd == OP_ERS) || (cmd == OP_WR)) {                /* write op? */
1706     if (RQ_WPH (uptr)) {
1707         rq_rw_end (cp, uptr, 0, ST_WPR | SB_WPR_HW);
1708         return SCPE_OK;
1709         }
1710     if (uptr->uf & UF_WPS) {
1711         rq_rw_end (cp, uptr, 0, ST_WPR | SB_WPR_SW);
1712         return SCPE_OK;
1713         }
1714     }
1715 
1716 if (cmd == OP_ERS) {                                    /* erase? */
1717     wwc = ((tbc + (RQ_NUMBY - 1)) & ~(RQ_NUMBY - 1)) >> 1;
1718     for (i = 0; i < wwc; i++)                           /* clr buf */
1719         rqxb[i] = 0;
1720     err = sim_fseek (uptr->fileref, da, SEEK_SET);      /* set pos */
1721     if (!err)
1722         sim_fwrite (rqxb, sizeof (int16), wwc, uptr->fileref);
1723     err = ferror (uptr->fileref);                       /* end if erase */
1724     }
1725 
1726 else if (cmd == OP_WR) {                                /* write? */
1727     t = Map_ReadW (ba, tbc, rqxb);                      /* fetch buffer */
1728     if ((abc = tbc - t)) {                              /* any xfer? */
1729         wwc = ((abc + (RQ_NUMBY - 1)) & ~(RQ_NUMBY - 1)) >> 1;
1730         for (i = (abc >> 1); i < wwc; i++)
1731             rqxb[i] = 0;
1732         err = sim_fseek (uptr->fileref, da, SEEK_SET);
1733         if (!err)
1734             sim_fwrite (rqxb, sizeof (int16), wwc, uptr->fileref);
1735         err = ferror (uptr->fileref);
1736         }
1737     if (t) {                                            /* nxm? */
1738         PUTP32 (pkt, RW_WBCL, bc - abc);                /* adj bc */
1739         PUTP32 (pkt, RW_WBAL, ba + abc);                /* adj ba */
1740         if (rq_hbe (cp, uptr))                          /* post err log */
1741             rq_rw_end (cp, uptr, EF_LOG, ST_HST | SB_HST_NXM);
1742         return SCPE_OK;                                 /* end else wr */
1743         }
1744     }
1745 
1746 else {
1747     err = sim_fseek (uptr->fileref, da, SEEK_SET);      /* set pos */
1748     if (!err) {
1749         i = sim_fread (rqxb, sizeof (int16), tbc >> 1, uptr->fileref);
1750         for ( ; i < (tbc >> 1); i++)                    /* fill */
1751             rqxb[i] = 0;
1752         err = ferror (uptr->fileref);
1753         }
1754     if ((cmd == OP_RD) && !err) {                       /* read? */
1755         if ((t = Map_WriteW (ba, tbc, rqxb))) {         /* store, nxm? */
1756             PUTP32 (pkt, RW_WBCL, bc - (tbc - t));      /* adj bc */
1757             PUTP32 (pkt, RW_WBAL, ba + (tbc - t));      /* adj ba */
1758             if (rq_hbe (cp, uptr))                      /* post err log */
1759                 rq_rw_end (cp, uptr, EF_LOG, ST_HST | SB_HST_NXM);
1760             return SCPE_OK;
1761             }
1762         }
1763     else if ((cmd == OP_CMP) && !err) {                 /* compare? */
1764         uint8 dby, mby;
1765         for (i = 0; i < tbc; i++) {                     /* loop */
1766             if (Map_ReadB (ba + i, 1, &mby)) {          /* fetch, nxm? */
1767                 PUTP32 (pkt, RW_WBCL, bc - i);          /* adj bc */
1768                 PUTP32 (pkt, RW_WBAL, bc - i);          /* adj ba */
1769                 if (rq_hbe (cp, uptr))                  /* post err log */
1770                     rq_rw_end (cp, uptr, EF_LOG, ST_HST | SB_HST_NXM);
1771                 return SCPE_OK;
1772                 }
1773             dby = (rqxb[i >> 1] >> ((i & 1)? 8: 0)) & 0xFF;
1774             if (mby != dby) {                           /* cmp err? */
1775                 PUTP32 (pkt, RW_WBCL, bc - i);          /* adj bc */
1776                 rq_rw_end (cp, uptr, 0, ST_CMP);        /* done */
1777                 return SCPE_OK;                         /* exit */
1778                 }                                       /* end if */
1779             }                                           /* end for */
1780         }                                               /* end else if */
1781     }                                                   /* end else read */
1782 if (err != 0) {                                         /* error? */
1783     if (rq_dte (cp, uptr, ST_DRV))                      /* post err log */
1784         rq_rw_end (cp, uptr, EF_LOG, ST_DRV);           /* if ok, report err */
1785     perror ("RQ I/O error");
1786     clearerr (uptr->fileref);
1787     return SCPE_IOERR;
1788     }
1789 ba = ba + tbc;                                          /* incr bus addr */
1790 bc = bc - tbc;                                          /* decr byte cnt */
1791 bl = bl + ((tbc + (RQ_NUMBY - 1)) / RQ_NUMBY);          /* incr blk # */
1792 PUTP32 (pkt, RW_WBAL, ba);                              /* update pkt */
1793 PUTP32 (pkt, RW_WBCL, bc);
1794 PUTP32 (pkt, RW_WBLL, bl);
1795 if (bc)                                                 /* more? resched */
1796     sim_activate (uptr, rq_xtime);
1797 else rq_rw_end (cp, uptr, 0, ST_SUC);                   /* done! */
1798 return SCPE_OK;
1799 }
1800 
1801 /* Transfer command complete */
1802 
rq_rw_end(MSC * cp,UNIT * uptr,uint32 flg,uint32 sts)1803 t_bool rq_rw_end (MSC *cp, UNIT *uptr, uint32 flg, uint32 sts)
1804 {
1805 int32 pkt = uptr->cpkt;                                 /* packet */
1806 uint32 cmd = GETP (pkt, CMD_OPC, OPC);                  /* get cmd */
1807 uint32 bc = GETP32 (pkt, RW_BCL);                       /* init bc */
1808 uint32 wbc = GETP32 (pkt, RW_WBCL);                     /* work bc */
1809 DEVICE *dptr = rq_devmap[uptr->cnum];
1810 
1811 uptr->cpkt = 0;                                         /* done */
1812 PUTP32 (pkt, RW_BCL, bc - wbc);                         /* bytes processed */
1813 cp->pak[pkt].d[RW_WBAL] = 0;                            /* clear temps */
1814 cp->pak[pkt].d[RW_WBAH] = 0;
1815 cp->pak[pkt].d[RW_WBCL] = 0;
1816 cp->pak[pkt].d[RW_WBCH] = 0;
1817 cp->pak[pkt].d[RW_WBLL] = 0;
1818 cp->pak[pkt].d[RW_WBLH] = 0;
1819 rq_putr (cp, pkt, cmd | OP_END, flg, sts, RW_LNT_D, UQ_TYP_SEQ); /* fill pkt */
1820 if (!rq_putpkt (cp, pkt, TRUE))                         /* send pkt */
1821     return ERR;
1822 if (uptr->pktq)                                         /* more to do? */
1823     sim_activate (dptr->units + RQ_QUEUE, rq_qtime);    /* activate thread */
1824 return OK;
1825 }
1826 
1827 /* Data transfer error log packet */
1828 
rq_dte(MSC * cp,UNIT * uptr,uint32 err)1829 t_bool rq_dte (MSC *cp, UNIT *uptr, uint32 err)
1830 {
1831 int32 pkt, tpkt;
1832 uint32 lu, dtyp, lbn, ccyl, csurf, csect, t;
1833 
1834 if ((cp->cflgs & CF_THS) == 0)                          /* logging? */
1835     return OK;
1836 if (!rq_deqf (cp, &pkt))                                /* get log pkt */
1837     return ERR;
1838 tpkt = uptr->cpkt;                                      /* rw pkt */
1839 lu = cp->pak[tpkt].d[CMD_UN];                           /* unit # */
1840 lbn = GETP32 (tpkt, RW_WBLL);                           /* recent LBN */
1841 dtyp = GET_DTYPE (uptr->flags);                         /* drv type */
1842 if (drv_tab[dtyp].flgs & RQDF_SDI)                      /* SDI? ovhd @ end */
1843     t = 0;
1844 else t = (drv_tab[dtyp].xbn + drv_tab[dtyp].dbn) /      /* ovhd cylinders */
1845     (drv_tab[dtyp].sect * drv_tab[dtyp].surf);
1846 ccyl = t + (lbn / drv_tab[dtyp].cyl);                   /* curr real cyl */
1847 t = lbn % drv_tab[dtyp].cyl;                            /* trk relative blk */
1848 csurf = t / drv_tab[dtyp].surf;                         /* curr surf */
1849 csect = t % drv_tab[dtyp].surf;                         /* curr sect */
1850 
1851 cp->pak[pkt].d[ELP_REFL] = cp->pak[tpkt].d[CMD_REFL];   /* copy cmd ref */
1852 cp->pak[pkt].d[ELP_REFH] = cp->pak[tpkt].d[CMD_REFH];
1853 cp->pak[pkt].d[ELP_UN] = lu;                            /* copy unit */
1854 cp->pak[pkt].d[ELP_SEQ] = 0;                            /* clr seq # */
1855 cp->pak[pkt].d[DTE_CIDA] = 0;                           /* ctrl ID */
1856 cp->pak[pkt].d[DTE_CIDB] = 0;
1857 cp->pak[pkt].d[DTE_CIDC] = 0;
1858 cp->pak[pkt].d[DTE_CIDD] = (RQ_CLASS << DTE_CIDD_V_CLS) |
1859     (RQ_MODEL << DTE_CIDD_V_MOD);
1860 cp->pak[pkt].d[DTE_VER] = (RQ_HVER << DTE_VER_V_HVER) |
1861     (RQ_SVER << DTE_VER_V_SVER);
1862 cp->pak[pkt].d[DTE_MLUN] = lu;                          /* MLUN */
1863 cp->pak[pkt].d[DTE_UIDA] = lu;                          /* unit ID */
1864 cp->pak[pkt].d[DTE_UIDB] = 0;
1865 cp->pak[pkt].d[DTE_UIDC] = 0;
1866 cp->pak[pkt].d[DTE_UIDD] = (UID_DISK << DTE_UIDD_V_CLS) |
1867     (drv_tab[dtyp].mod << DTE_UIDD_V_MOD);
1868 cp->pak[pkt].d[DTE_UVER] = 0;                           /* unit versn */
1869 cp->pak[pkt].d[DTE_SCYL] = ccyl;                        /* cylinder */
1870 cp->pak[pkt].d[DTE_VSNL] = 01234 + lu;                  /* vol ser # */
1871 cp->pak[pkt].d[DTE_VSNH] = 0;
1872 cp->pak[pkt].d[DTE_D1] = 0;
1873 cp->pak[pkt].d[DTE_D2] = csect << DTE_D2_V_SECT;        /* geometry */
1874 cp->pak[pkt].d[DTE_D3] = (ccyl << DTE_D3_V_CYL) |
1875     (csurf << DTE_D3_V_SURF);
1876 rq_putr (cp, pkt, FM_SDE, LF_SNR, err, DTE_LNT, UQ_TYP_DAT);
1877 return rq_putpkt (cp, pkt, TRUE);
1878 }
1879 
1880 /* Host bus error log packet */
1881 
rq_hbe(MSC * cp,UNIT * uptr)1882 t_bool rq_hbe (MSC *cp, UNIT *uptr)
1883 {
1884 int32 pkt, tpkt;
1885 
1886 if ((cp->cflgs & CF_THS) == 0)                          /* logging? */
1887     return OK;
1888 if (!rq_deqf (cp, &pkt))                                /* get log pkt */
1889     return ERR;
1890 tpkt = uptr->cpkt;                                      /* rw pkt */
1891 cp->pak[pkt].d[ELP_REFL] = cp->pak[tpkt].d[CMD_REFL];   /* copy cmd ref */
1892 cp->pak[pkt].d[ELP_REFH] = cp->pak[tpkt].d[CMD_REFH];
1893 cp->pak[pkt].d[ELP_UN] = cp->pak[tpkt].d[CMD_UN];       /* copy unit */
1894 cp->pak[pkt].d[ELP_SEQ] = 0;                            /* clr seq # */
1895 cp->pak[pkt].d[HBE_CIDA] = 0;                           /* ctrl ID */
1896 cp->pak[pkt].d[HBE_CIDB] = 0;
1897 cp->pak[pkt].d[HBE_CIDC] = 0;
1898 cp->pak[pkt].d[HBE_CIDD] = (RQ_CLASS << DTE_CIDD_V_CLS) |
1899     (RQ_MODEL << DTE_CIDD_V_MOD);
1900 cp->pak[pkt].d[HBE_VER] = (RQ_HVER << HBE_VER_V_HVER) | /* versions */
1901     (RQ_SVER << HBE_VER_V_SVER);
1902 cp->pak[pkt].d[HBE_RSV] = 0;
1903 cp->pak[pkt].d[HBE_BADL] = cp->pak[tpkt].d[RW_WBAL];    /* bad addr */
1904 cp->pak[pkt].d[HBE_BADH] = cp->pak[tpkt].d[RW_WBAH];
1905 rq_putr (cp, pkt, FM_BAD, LF_SNR, ST_HST | SB_HST_NXM, HBE_LNT, UQ_TYP_DAT);
1906 return rq_putpkt (cp, pkt, TRUE);
1907 }
1908 
1909 /* Port last failure error log packet */
1910 
rq_plf(MSC * cp,uint32 err)1911 t_bool rq_plf (MSC *cp, uint32 err)
1912 {
1913 int32 pkt;
1914 
1915 if (!rq_deqf (cp, &pkt))                                /* get log pkt */
1916     return ERR;
1917 cp->pak[pkt].d[ELP_REFL] = 0;                           /* ref = 0 */
1918 cp->pak[pkt].d[ELP_REFH] = 0;
1919 cp->pak[pkt].d[ELP_UN] = 0;                             /* no unit */
1920 cp->pak[pkt].d[ELP_SEQ] = 0;                            /* no seq */
1921 cp->pak[pkt].d[PLF_CIDA] = 0;                           /* cntl ID */
1922 cp->pak[pkt].d[PLF_CIDB] = 0;
1923 cp->pak[pkt].d[PLF_CIDC] = 0;
1924 cp->pak[pkt].d[PLF_CIDD] = (RQ_CLASS << PLF_CIDD_V_CLS) |
1925     (RQ_MODEL << PLF_CIDD_V_MOD);
1926 cp->pak[pkt].d[PLF_VER] = (RQ_SVER << PLF_VER_V_SVER) |
1927     (RQ_HVER << PLF_VER_V_HVER);
1928 cp->pak[pkt].d[PLF_ERR] = err;
1929 rq_putr (cp, pkt, FM_CNT, LF_SNR, ST_CNT, PLF_LNT, UQ_TYP_DAT);
1930 cp->pak[pkt].d[UQ_HCTC] |= (UQ_CID_DIAG << UQ_HCTC_V_CID);
1931 return rq_putpkt (cp, pkt, TRUE);
1932 }
1933 
1934 /* Unit now available attention packet */
1935 
rq_una(MSC * cp,int32 un)1936 int32 rq_una (MSC *cp, int32 un)
1937 {
1938 int32 pkt;
1939 uint32 lu = cp->ubase + un;
1940 UNIT *uptr = rq_getucb (cp, lu);
1941 
1942 if (uptr == NULL)                                       /* huh? */
1943     return OK;
1944 if (!rq_deqf (cp, &pkt))                                /* get log pkt */
1945     return ERR;
1946 cp->pak[pkt].d[RSP_REFL] = 0;                           /* ref = 0 */
1947 cp->pak[pkt].d[RSP_REFH] = 0;
1948 cp->pak[pkt].d[RSP_UN] = lu;
1949 cp->pak[pkt].d[RSP_RSV] = 0;
1950 rq_putr_unit (cp, pkt, uptr, lu, FALSE);                /* fill unit fields */
1951 rq_putr (cp, pkt, OP_AVA, 0, 0, UNA_LNT, UQ_TYP_SEQ);   /* fill std fields */
1952 return rq_putpkt (cp, pkt, TRUE);
1953 }
1954 
1955 /* List handling
1956 
1957    rq_deqf      -       dequeue head of free list (fatal err if none)
1958    rq_deqh      -       dequeue head of list
1959    rq_enqh      -       enqueue at head of list
1960    rq_enqt      -       enqueue at tail of list
1961 */
1962 
rq_deqf(MSC * cp,int32 * pkt)1963 t_bool rq_deqf (MSC *cp, int32 *pkt)
1964 {
1965 if (cp->freq == 0)                                      /* no free pkts?? */
1966     return rq_fatal (cp, PE_NSR);
1967 cp->pbsy = cp->pbsy + 1;                                /* cnt busy pkts */
1968 *pkt = cp->freq;                                        /* head of list */
1969 cp->freq = cp->pak[cp->freq].link;                      /* next */
1970 return OK;
1971 }
1972 
rq_deqh(MSC * cp,int32 * lh)1973 int32 rq_deqh (MSC *cp, int32 *lh)
1974 {
1975 int32 ptr = *lh;                                        /* head of list */
1976 
1977 if (ptr)                                                /* next */
1978     *lh = cp->pak[ptr].link;
1979 return ptr;
1980 }
1981 
rq_enqh(MSC * cp,int32 * lh,int32 pkt)1982 void rq_enqh (MSC *cp, int32 *lh, int32 pkt)
1983 {
1984 if (pkt == 0)                                           /* any pkt? */
1985     return;
1986 cp->pak[pkt].link = *lh;                                /* link is old lh */
1987 *lh = pkt;                                              /* pkt is new lh */
1988 return;
1989 }
1990 
rq_enqt(MSC * cp,int32 * lh,int32 pkt)1991 void rq_enqt (MSC *cp, int32 *lh, int32 pkt)
1992 {
1993 if (pkt == 0)                                           /* any pkt? */
1994     return;
1995 cp->pak[pkt].link = 0;                                  /* it will be tail */
1996 if (*lh == 0)                                           /* if empty, enqh */
1997     *lh = pkt;
1998 else {
1999     uint32 ptr = *lh;                                   /* chase to end */
2000     while (cp->pak[ptr].link)
2001         ptr = cp->pak[ptr].link;
2002     cp->pak[ptr].link = pkt;                            /* enq at tail */
2003     }
2004 return;
2005 }
2006 
2007 /* Packet and descriptor handling */
2008 
2009 /* Get packet from command ring */
2010 
rq_getpkt(MSC * cp,int32 * pkt)2011 t_bool rq_getpkt (MSC *cp, int32 *pkt)
2012 {
2013 uint32 addr, desc;
2014 
2015 if (!rq_getdesc (cp, &cp->cq, &desc))                   /* get cmd desc */
2016     return ERR;
2017 if ((desc & UQ_DESC_OWN) == 0) {                        /* none */
2018     *pkt = 0;                                           /* pkt = 0 */
2019     return OK;                                          /* no error */
2020     }
2021 if (!rq_deqf (cp, pkt))                                 /* get cmd pkt */
2022     return ERR;
2023 cp->hat = 0;                                            /* dsbl hst timer */
2024 addr = desc & UQ_ADDR;                                  /* get Q22 addr */
2025 if (Map_ReadW (addr + UQ_HDR_OFF, RQ_PKT_SIZE, cp->pak[*pkt].d))
2026     return rq_fatal (cp, PE_PRE);                       /* read pkt */
2027 return rq_putdesc (cp, &cp->cq, desc);                  /* release desc */
2028 }
2029 
2030 /* Put packet to response ring - note the clever hack about credits.
2031    The controller sends all its credits to the host.  Thereafter, it
2032    supplies one credit for every response packet sent over.  Simple!
2033 */
2034 
rq_putpkt(MSC * cp,int32 pkt,t_bool qt)2035 t_bool rq_putpkt (MSC *cp, int32 pkt, t_bool qt)
2036 {
2037 uint32 addr, desc, lnt, cr;
2038 DEVICE *dptr = rq_devmap[cp->cnum];
2039 
2040 if (pkt == 0)                                           /* any packet? */
2041     return OK;
2042 if (DEBUG_PRD (dptr))
2043     fprintf (sim_deb, ">>RQ%c: rsp=%04X, sts=%04X\n", 'A' + cp->cnum,
2044              cp->pak[pkt].d[RSP_OPF], cp->pak[pkt].d[RSP_STS]);
2045 if (!rq_getdesc (cp, &cp->rq, &desc))                   /* get rsp desc */
2046     return ERR;
2047 if ((desc & UQ_DESC_OWN) == 0) {                        /* not valid? */
2048     if (qt)                                             /* normal? q tail */
2049         rq_enqt (cp, &cp->rspq, pkt);
2050     else rq_enqh (cp, &cp->rspq, pkt);                  /* resp q call */
2051     sim_activate (dptr->units + RQ_QUEUE, rq_qtime);    /* activate q thrd */
2052     return OK;
2053     }
2054 addr = desc & UQ_ADDR;                                  /* get Q22 addr */
2055 lnt = cp->pak[pkt].d[UQ_HLNT] - UQ_HDR_OFF;             /* size, with hdr */
2056 if ((GETP (pkt, UQ_HCTC, TYP) == UQ_TYP_SEQ) &&         /* seq packet? */
2057     (GETP (pkt, CMD_OPC, OPC) & OP_END)) {              /* end packet? */
2058     cr = (cp->credits >= 14)? 14: cp->credits;          /* max 14 credits */
2059     cp->credits = cp->credits - cr;                     /* decr credits */
2060     cp->pak[pkt].d[UQ_HCTC] |= ((cr + 1) << UQ_HCTC_V_CR);
2061     }
2062 if (Map_WriteW (addr + UQ_HDR_OFF, lnt, cp->pak[pkt].d))
2063     return rq_fatal (cp, PE_PWE);                       /* write pkt */
2064 rq_enqh (cp, &cp->freq, pkt);                           /* pkt is free */
2065 cp->pbsy = cp->pbsy - 1;                                /* decr busy cnt */
2066 if (cp->pbsy == 0)                                      /* idle? strt hst tmr */
2067     cp->hat = cp->htmo;
2068 return rq_putdesc (cp, &cp->rq, desc);                  /* release desc */
2069 }
2070 
2071 /* Get a descriptor from the host */
2072 
rq_getdesc(MSC * cp,struct uq_ring * ring,uint32 * desc)2073 t_bool rq_getdesc (MSC *cp, struct uq_ring *ring, uint32 *desc)
2074 {
2075 uint32 addr = ring->ba + ring->idx;
2076 uint16 d[2];
2077 
2078 if (Map_ReadW (addr, 4, d))                             /* fetch desc */
2079     return rq_fatal (cp, PE_QRE);                       /* err? dead */
2080 *desc = ((uint32) d[0]) | (((uint32) d[1]) << 16);
2081 return OK;
2082 }
2083 
2084 /* Return a descriptor to the host, clearing owner bit
2085    If rings transitions from "empty" to "not empty" or "full" to
2086    "not full", and interrupt bit was set, interrupt the host.
2087    Actually, test whether previous ring entry was owned by host.
2088 */
2089 
rq_putdesc(MSC * cp,struct uq_ring * ring,uint32 desc)2090 t_bool rq_putdesc (MSC *cp, struct uq_ring *ring, uint32 desc)
2091 {
2092 uint32 prvd, newd = (desc & ~UQ_DESC_OWN) | UQ_DESC_F;
2093 uint32 prva, addr = ring->ba + ring->idx;
2094 uint16 d[2];
2095 
2096 d[0] = newd & 0xFFFF;                                   /* 32b to 16b */
2097 d[1] = (newd >> 16) & 0xFFFF;
2098 if (Map_WriteW (addr, 4, d))                            /* store desc */
2099     return rq_fatal (cp, PE_QWE);                       /* err? dead */
2100 if (desc & UQ_DESC_F) {                                 /* was F set? */
2101     if (ring->lnt <= 4)                                 /* lnt = 1? intr */
2102         rq_ring_int (cp, ring);
2103     else {                                              /* prv desc */
2104         prva = ring->ba + ((ring->idx - 4) & (ring->lnt - 1));
2105         if (Map_ReadW (prva, 4, d))                     /* read prv */
2106             return rq_fatal (cp, PE_QRE);
2107         prvd = ((uint32) d[0]) | (((uint32) d[1]) << 16);
2108         if (prvd & UQ_DESC_OWN)
2109             rq_ring_int (cp, ring);
2110         }
2111     }
2112 ring->idx = (ring->idx + 4) & (ring->lnt - 1);
2113 return OK;
2114 }
2115 
2116 /* Get unit descriptor for logical unit */
2117 
rq_getucb(MSC * cp,uint32 lu)2118 UNIT *rq_getucb (MSC *cp, uint32 lu)
2119 {
2120 DEVICE *dptr = rq_devmap[cp->cnum];
2121 UNIT *uptr;
2122 
2123 if ((lu < cp->ubase) || (lu >= (cp->ubase + RQ_NUMDR)))
2124     return NULL;
2125 uptr = dptr->units + (lu % RQ_NUMDR);
2126 if (uptr->flags & UNIT_DIS)
2127     return NULL;
2128 return uptr;
2129 }
2130 
2131 /* Hack unit flags */
2132 
rq_setf_unit(MSC * cp,int32 pkt,UNIT * uptr)2133 void rq_setf_unit (MSC *cp, int32 pkt, UNIT *uptr)
2134 {
2135 uptr->uf = cp->pak[pkt].d[ONL_UFL] & UF_MSK;            /* settable flags */
2136 if ((cp->pak[pkt].d[CMD_MOD] & MD_SWP) &&               /* swre wrp enb? */
2137     (cp->pak[pkt].d[ONL_UFL] & UF_WPS))                 /* swre wrp on? */
2138     uptr->uf = uptr->uf | UF_WPS;                       /* simon says... */
2139 return;
2140 }
2141 
2142 /* Unit response fields */
2143 
rq_putr_unit(MSC * cp,int32 pkt,UNIT * uptr,uint32 lu,t_bool all)2144 void rq_putr_unit (MSC *cp, int32 pkt, UNIT *uptr, uint32 lu, t_bool all)
2145 {
2146 uint32 dtyp = GET_DTYPE (uptr->flags);                  /* get drive type */
2147 uint32 maxlbn = (uint32) (uptr->capac / RQ_NUMBY);      /* get max lbn */
2148 
2149 cp->pak[pkt].d[ONL_MLUN] = lu;                          /* unit */
2150 cp->pak[pkt].d[ONL_UFL] = uptr->uf | UF_RPL | RQ_WPH (uptr) | RQ_RMV (uptr);
2151 cp->pak[pkt].d[ONL_RSVL] = 0;                           /* reserved */
2152 cp->pak[pkt].d[ONL_RSVH] = 0;
2153 cp->pak[pkt].d[ONL_UIDA] = lu;                          /* UID low */
2154 cp->pak[pkt].d[ONL_UIDB] = 0;
2155 cp->pak[pkt].d[ONL_UIDC] = 0;
2156 cp->pak[pkt].d[ONL_UIDD] = (UID_DISK << ONL_UIDD_V_CLS) |
2157     (drv_tab[dtyp].mod << ONL_UIDD_V_MOD);              /* UID hi */
2158 PUTP32 (pkt, ONL_MEDL, drv_tab[dtyp].med);              /* media type */
2159 if (all) {                                              /* if long form */
2160     PUTP32 (pkt, ONL_SIZL, maxlbn);                     /* user LBNs */
2161     cp->pak[pkt].d[ONL_VSNL] = 01234 + lu;              /* vol serial # */
2162     cp->pak[pkt].d[ONL_VSNH] = 0;
2163     }
2164 return;
2165 }
2166 
2167 /* UQ_HDR and RSP_OP fields */
2168 
rq_putr(MSC * cp,int32 pkt,uint32 cmd,uint32 flg,uint32 sts,uint32 lnt,uint32 typ)2169 void rq_putr (MSC *cp, int32 pkt, uint32 cmd, uint32 flg,
2170           uint32 sts, uint32 lnt, uint32 typ)
2171 {
2172 cp->pak[pkt].d[RSP_OPF] = (cmd << RSP_OPF_V_OPC) |      /* set cmd, flg */
2173     (flg << RSP_OPF_V_FLG);
2174 cp->pak[pkt].d[RSP_STS] = sts;
2175 cp->pak[pkt].d[UQ_HLNT] = lnt;                          /* length */
2176 cp->pak[pkt].d[UQ_HCTC] = (typ << UQ_HCTC_V_TYP) |      /* type, cid */
2177     (UQ_CID_MSCP << UQ_HCTC_V_CID);                     /* clr credits */
2178 return;
2179 }
2180 
2181 /* Post interrupt during init */
2182 
rq_init_int(MSC * cp)2183 void rq_init_int (MSC *cp)
2184 {
2185 if ((cp->s1dat & SA_S1H_IE) &&                          /* int enab & */
2186     (cp->s1dat & SA_S1H_VEC))                           /* ved set? int */
2187     rq_setint (cp);
2188 return;
2189 }
2190 
2191 /* Post interrupt during putpkt - note that NXMs are ignored! */
2192 
rq_ring_int(MSC * cp,struct uq_ring * ring)2193 void rq_ring_int (MSC *cp, struct uq_ring *ring)
2194 {
2195 uint32 iadr = cp->comm + ring->ioff;                    /* addr intr wd */
2196 uint16 flag = 1;
2197 
2198 Map_WriteW (iadr, 2, &flag);                            /* write flag */
2199 if (cp->s1dat & SA_S1H_VEC)                             /* if enb, intr */
2200     rq_setint (cp);
2201 return;
2202 }
2203 
2204 /* Set RQ interrupt */
2205 
rq_setint(MSC * cp)2206 void rq_setint (MSC *cp)
2207 {
2208 cp->irq = 1;                                            /* set ctrl int */
2209 SET_INT (RQ);                                           /* set master int */
2210 return;
2211 }
2212 
2213 /* Clear RQ interrupt */
2214 
rq_clrint(MSC * cp)2215 void rq_clrint (MSC *cp)
2216 {
2217 int32 i;
2218 MSC *ncp;
2219 
2220 cp->irq = 0;                                            /* clr ctrl int */
2221 for (i = 0; i < RQ_NUMCT; i++) {                        /* loop thru ctrls */
2222     ncp = rq_ctxmap[i];                                 /* get context */
2223     if (ncp->irq) {                                     /* other interrupt? */
2224         SET_INT (RQ);                                   /* yes, set master */
2225         return;
2226         }
2227     }
2228 CLR_INT (RQ);                                           /* no, clr master */
2229 return;
2230 }
2231 
2232 /* Return interrupt vector */
2233 
rq_inta(void)2234 int32 rq_inta (void)
2235 {
2236 int32 i;
2237 MSC *ncp;
2238 DEVICE *dptr;
2239 DIB *dibp;
2240 
2241 for (i = 0; i < RQ_NUMCT; i++) {                        /* loop thru ctrl */
2242     ncp = rq_ctxmap[i];                                 /* get context */
2243     if (ncp->irq) {                                     /* ctrl int set? */
2244         dptr = rq_devmap[i];                            /* get device */
2245         dibp = (DIB *) dptr->ctxt;                      /* get DIB */
2246         rq_clrint (ncp);                                /* clear int req */
2247         return dibp->vec;                               /* return vector */
2248         }
2249     }
2250 return 0;                                               /* no intr req */
2251 }
2252 
2253 /* Fatal error */
2254 
rq_fatal(MSC * cp,uint32 err)2255 t_bool rq_fatal (MSC *cp, uint32 err)
2256 {
2257 DEVICE *dptr = rq_devmap[cp->cnum];
2258 
2259 if (DEBUG_PRD (dptr))
2260     fprintf (sim_deb, ">>RQ%c: fatal err=%X\n", 'A' + cp->cnum, err);
2261 rq_reset (rq_devmap[cp->cnum]);                         /* reset device */
2262 cp->sa = SA_ER | err;                                   /* SA = dead code */
2263 cp->csta = CST_DEAD;                                    /* state = dead */
2264 cp->perr = err;                                         /* save error */
2265 return ERR;
2266 }
2267 
2268 /* Set/clear hardware write lock */
2269 
rq_set_wlk(UNIT * uptr,int32 val,char * cptr,void * desc)2270 t_stat rq_set_wlk (UNIT *uptr, int32 val, char *cptr, void *desc)
2271 {
2272 uint32 dtyp = GET_DTYPE (uptr->flags);                  /* get drive type */
2273 
2274 if (drv_tab[dtyp].flgs & RQDF_RO)                       /* not on read only */
2275     return SCPE_NOFNC;
2276 return SCPE_OK;
2277 }
2278 
2279 /* Show write lock status */
2280 
rq_show_wlk(FILE * st,UNIT * uptr,int32 val,void * desc)2281 t_stat rq_show_wlk (FILE *st, UNIT *uptr, int32 val, void *desc)
2282 {
2283 uint32 dtyp = GET_DTYPE (uptr->flags);                  /* get drive type */
2284 
2285 if (drv_tab[dtyp].flgs & RQDF_RO)
2286     fprintf (st, "read only");
2287 else if (uptr->flags & UNIT_WPRT)
2288     fprintf (st, "write locked");
2289 else fprintf (st, "write enabled");
2290 return SCPE_OK;
2291 }
2292 
2293 /* Set unit type (and capacity if user defined) */
2294 
rq_set_type(UNIT * uptr,int32 val,char * cptr,void * desc)2295 t_stat rq_set_type (UNIT *uptr, int32 val, char *cptr, void *desc)
2296 {
2297 uint32 cap;
2298 uint32 max = sim_taddr_64? RA8U_EMAXC: RA8U_MAXC;
2299 t_stat r;
2300 
2301 if ((val < 0) || ((val != RA8U_DTYPE) && cptr))
2302     return SCPE_ARG;
2303 if (uptr->flags & UNIT_ATT)
2304     return SCPE_ALATT;
2305 if (cptr) {
2306     cap = (uint32) get_uint (cptr, 10, 0xFFFFFFFF, &r);
2307     if ((sim_switches & SWMASK ('L')) == 0)
2308         cap = cap * 1954;
2309     if ((r != SCPE_OK) || (cap < RA8U_MINC) || (cap >= max))
2310         return SCPE_ARG;
2311     drv_tab[val].lbn = cap;
2312     }
2313 uptr->flags = (uptr->flags & ~UNIT_DTYPE) | (val << UNIT_V_DTYPE);
2314 uptr->capac = ((t_addr) drv_tab[val].lbn) * RQ_NUMBY;
2315 return SCPE_OK;
2316 }
2317 
2318 /* Show unit type */
2319 
rq_show_type(FILE * st,UNIT * uptr,int32 val,void * desc)2320 t_stat rq_show_type (FILE *st, UNIT *uptr, int32 val, void *desc)
2321 {
2322 fprintf (st, "%s", drv_tab[GET_DTYPE (uptr->flags)].name);
2323 return SCPE_OK;
2324 }
2325 
2326 /* Device attach */
2327 
rq_attach(UNIT * uptr,char * cptr)2328 t_stat rq_attach (UNIT *uptr, char *cptr)
2329 {
2330 MSC *cp = rq_ctxmap[uptr->cnum];
2331 t_stat r;
2332 
2333 r = attach_unit (uptr, cptr);
2334 if (r != SCPE_OK)
2335     return r;
2336 if (cp->csta == CST_UP)
2337     uptr->flags = uptr->flags | UNIT_ATP;
2338 return SCPE_OK;
2339 }
2340 
2341 /* Device detach */
2342 
rq_detach(UNIT * uptr)2343 t_stat rq_detach (UNIT *uptr)
2344 {
2345 t_stat r;
2346 
2347 r = detach_unit (uptr);                                 /* detach unit */
2348 if (r != SCPE_OK)
2349     return r;
2350 uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_ATP);     /* clr onl, atn pend */
2351 uptr->uf = 0;                                           /* clr unit flgs */
2352 return SCPE_OK;
2353 }
2354 
2355 /* Device reset */
2356 
rq_reset(DEVICE * dptr)2357 t_stat rq_reset (DEVICE *dptr)
2358 {
2359 int32 i, j, cidx;
2360 UNIT *uptr;
2361 MSC *cp;
2362 DIB *dibp = (DIB *) dptr->ctxt;
2363 
2364 for (i = 0, cidx = -1; i < RQ_NUMCT; i++) {             /* find ctrl num */
2365     if (rq_devmap[i] == dptr)
2366         cidx = i;
2367     }
2368 if (cidx < 0)                                           /* not found??? */
2369     return SCPE_IERR;
2370 cp = rq_ctxmap[cidx];                                   /* get context */
2371 cp->cnum = cidx;                                        /* init index */
2372 
2373 #if defined (VM_VAX)                                    /* VAX */
2374 cp->ubase = 0;                                          /* unit base = 0 */
2375 #else                                                   /* PDP-11 */
2376 cp->ubase = cidx * RQ_NUMDR;                            /* init unit base */
2377 #endif
2378 
2379 cp->csta = CST_S1;                                      /* init stage 1 */
2380 cp->s1dat = 0;                                          /* no S1 data */
2381 dibp->vec = 0;                                          /* no vector */
2382 cp->comm = 0;                                           /* no comm region */
2383 if (UNIBUS)                                             /* Unibus? */
2384     cp->sa = SA_S1 | SA_S1C_DI | SA_S1C_MP;
2385 else cp->sa = SA_S1 | SA_S1C_Q22 | SA_S1C_DI | SA_S1C_MP; /* init SA val */
2386 cp->cflgs = CF_RPL;                                     /* ctrl flgs off */
2387 cp->htmo = RQ_DHTMO;                                    /* default timeout */
2388 cp->hat = cp->htmo;                                     /* default timer */
2389 cp->cq.ba = cp->cq.lnt = cp->cq.idx = 0;                /* clr cmd ring */
2390 cp->rq.ba = cp->rq.lnt = cp->rq.idx = 0;                /* clr rsp ring */
2391 cp->credits = (RQ_NPKTS / 2) - 1;                       /* init credits */
2392 cp->freq = 1;                                           /* init free list */
2393 for (i = 0; i < RQ_NPKTS; i++) {                        /* all pkts free */
2394     if (i)
2395         cp->pak[i].link = (i + 1) & RQ_M_NPKTS;
2396     else cp->pak[i].link = 0;
2397     for (j = 0; j < RQ_PKT_SIZE_W; j++)
2398         cp->pak[i].d[j] = 0;
2399     }
2400 cp->rspq = 0;                                           /* no q'd rsp pkts */
2401 cp->pbsy = 0;                                           /* all pkts free */
2402 cp->pip = 0;                                            /* not polling */
2403 rq_clrint (cp);                                         /* clr intr req */
2404 for (i = 0; i < (RQ_NUMDR + 2); i++) {                  /* init units */
2405     uptr = dptr->units + i;
2406     sim_cancel (uptr);                                  /* clr activity */
2407     uptr->cnum = cidx;                                  /* set ctrl index */
2408     uptr->flags = uptr->flags & ~(UNIT_ONL | UNIT_ATP);
2409     uptr->uf = 0;                                       /* clr unit flags */
2410     uptr->cpkt = uptr->pktq = 0;                        /* clr pkt q's */
2411     }
2412 if (rqxb == NULL)
2413     rqxb = (uint16 *) calloc (RQ_MAXFR >> 1, sizeof (uint16));
2414 if (rqxb == NULL)
2415     return SCPE_MEM;
2416 return auto_config (0, 0);                              /* run autoconfig */
2417 }
2418 
2419 /* Device bootstrap */
2420 
2421 #if defined (VM_PDP11)
2422 
2423 #define BOOT_START      016000                          /* start */
2424 #define BOOT_ENTRY      (BOOT_START + 002)              /* entry */
2425 #define BOOT_UNIT       (BOOT_START + 010)              /* unit number */
2426 #define BOOT_CSR        (BOOT_START + 014)              /* CSR */
2427 #define BOOT_LEN        (sizeof (boot_rom) / sizeof (int16))
2428 
2429 static const uint16 boot_rom[] = {
2430 
2431     0042125,                        /* st: "UD" */
2432 
2433                                     /* Four step init process */
2434 
2435     0012706, 0016000,               /*   mov  #st,sp */
2436     0012700, 0000000,               /*   mov  #unit,r0 */
2437     0012701, 0172150,               /*   mov  #172150, r1   ; ip addr */
2438     0012704, 0016162,               /*   mov  #it, r4 */
2439     0012705, 0004000,               /*   mov  #4000,r5      ; s1 mask */
2440     0010102,                        /*   mov  r1,r2 */
2441     0005022,                        /*   clr  (r2)+         ; init */
2442     0005712,                        /* 10$: tst (r2)        ; err? */
2443     0100001,                        /*   bpl  20$ */
2444     0000000,                        /*   halt */
2445     0030512,                        /* 20$: bit r5,(r2)     ; step set? */
2446     0001773,                        /*   beq  10$           ; wait */
2447     0012412,                        /*   mov  (r4)+,(r2)    ; send next */
2448     0006305,                        /*   asl  r5            ; next mask */
2449     0100370,                        /*   bpl 10$            ; s4 done? */
2450 
2451                                     /* Send ONL, READ commands */
2452 
2453     0105714,                        /* 30$: tstb    (r4)    ; end tbl? */
2454     0001434,                        /*   beq  done          ; 0 = yes */
2455     0012702, 0007000,               /*   mov  #rpkt-4,r2    ; clr pkts */
2456     0005022,                        /* 40$: clr (r2)+ */
2457     0020227, 0007204,               /*   cmp  r2,#comm */
2458     0103774,                        /*   blo  40$ */
2459     0112437, 0007100,               /*   movb (r4)+,cpkt-4  ; set lnt */
2460     0110037, 0007110,               /*   movb r0,cpkt+4     ; set unit */
2461     0112437, 0007114,               /*   movb (r4)+,cpkt+10 ; set op */
2462     0112437, 0007121,               /*   movb (r4)+,cpkt+15 ; set param */
2463     0012722, 0007004,               /*   mov  #rpkt,(r2)+   ; rq desc */
2464     0010522,                        /*   mov  r5,(r2)+      ; rq own */
2465     0012722, 0007104,               /*   mov  #ckpt,(r2)+   ; cq desc */
2466     0010512,                        /*   mov  r5,(r2)       ; cq own */
2467     0024242,                        /*   cmp  -(r2),-(r2)   ; back up */
2468     0005711,                        /*   tst  (r1)          ; wake ctrl */
2469     0005712,                        /* 50$: tst (r2)        ; rq own clr? */
2470     0100776,                        /*   bmi  50$           ; wait */
2471     0005737, 0007016,               /*   tst  rpkt+12       ; stat ok? */
2472     0001743,                        /*   beq  30$           ; next cmd */
2473     0000000,                        /*   halt */
2474 
2475                                     /* Boot block read in, jump to 0 */
2476 
2477     0005011,                        /* done: clr (r1)       ; for M+ */
2478     0005003,                        /*   clr  r3 */
2479     0012704, BOOT_START+020,        /*   mov  #st+020,r4 */
2480     0005005,                        /*   clr  r5 */
2481     0005007,                        /*   clr  pc */
2482 
2483                                     /* Data */
2484 
2485     0100000,                        /* it: no ints, ring sz = 1 */
2486     0007204,                        /*    .word comm */
2487     0000000,                        /*    .word 0 */
2488     0000001,                        /*    .word 1 */
2489     0004420,                        /*   .byte 20,11 */
2490     0020000,                        /*   .byte 0,40 */
2491     0001041,                        /*   .byte 41,2 */
2492     0000000
2493     };
2494 
rq_boot(int32 unitno,DEVICE * dptr)2495 t_stat rq_boot (int32 unitno, DEVICE *dptr)
2496 {
2497 int32 i;
2498 extern int32 saved_PC;
2499 extern uint16 *M;
2500 DIB *dibp = (DIB *) dptr->ctxt;
2501 
2502 for (i = 0; i < BOOT_LEN; i++)
2503     M[(BOOT_START >> 1) + i] = boot_rom[i];
2504 M[BOOT_UNIT >> 1] = unitno & 3;
2505 M[BOOT_CSR >> 1] = dibp->ba & DMASK;
2506 saved_PC = BOOT_ENTRY;
2507 return SCPE_OK;
2508 }
2509 
2510 #else
2511 
rq_boot(int32 unitno,DEVICE * dptr)2512 t_stat rq_boot (int32 unitno, DEVICE *dptr)
2513 {
2514 return SCPE_NOFNC;
2515 }
2516 #endif
2517 
2518 /* Special show commands */
2519 
rq_show_ring(FILE * st,struct uq_ring * rp)2520 void rq_show_ring (FILE *st, struct uq_ring *rp)
2521 {
2522 uint32 i, desc;
2523 uint16 d[2];
2524 
2525 #if defined (VM_PDP11)
2526 fprintf (st, "ring, base = %o, index = %d, length = %d\n",
2527      rp->ba, rp->idx >> 2, rp->lnt >> 2);
2528 #else
2529 fprintf (st, "ring, base = %x, index = %d, length = %d\n",
2530      rp->ba, rp->idx >> 2, rp->lnt >> 2);
2531 #endif
2532 for (i = 0; i < (rp->lnt >> 2); i++) {
2533     if (Map_ReadW (rp->ba + (i << 2), 4, d)) {
2534         fprintf (st, " %3d: non-existent memory\n", i);
2535         break;
2536         }
2537     desc = ((uint32) d[0]) | (((uint32) d[1]) << 16);
2538 #if defined (VM_PDP11)
2539     fprintf (st, " %3d: %011o\n", i, desc);
2540 #else
2541     fprintf (st, " %3d: %08x\n", i, desc);
2542 #endif
2543     }
2544 return;
2545 }
2546 
rq_show_pkt(FILE * st,MSC * cp,int32 pkt)2547 void rq_show_pkt (FILE *st, MSC *cp, int32 pkt)
2548 {
2549 int32 i, j;
2550 uint32 cr = GETP (pkt, UQ_HCTC, CR);
2551 uint32 typ = GETP (pkt, UQ_HCTC, TYP);
2552 uint32 cid = GETP (pkt, UQ_HCTC, CID);
2553 
2554 fprintf (st, "packet %d, credits = %d, type = %d, cid = %d\n",
2555     pkt, cr, typ, cid);
2556 for (i = 0; i < RQ_SH_MAX; i = i + RQ_SH_PPL) {
2557     fprintf (st, " %2d:", i);
2558     for (j = i; j < (i + RQ_SH_PPL); j++)
2559 #if defined (VM_PDP11)
2560     fprintf (st, " %06o", cp->pak[pkt].d[j]);
2561 #else
2562     fprintf (st, " %04x", cp->pak[pkt].d[j]);
2563 #endif
2564     fprintf (st, "\n");
2565     }
2566 return;
2567 }
2568 
rq_show_unitq(FILE * st,UNIT * uptr,int32 val,void * desc)2569 t_stat rq_show_unitq (FILE *st, UNIT *uptr, int32 val, void *desc)
2570 {
2571 MSC *cp = rq_ctxmap[uptr->cnum];
2572 DEVICE *dptr = rq_devmap[uptr->cnum];
2573 int32 pkt, u;
2574 
2575 u = (int32) (uptr - dptr->units);
2576 if (cp->csta != CST_UP) {
2577     fprintf (st, "Controller is not initialized\n");
2578     return SCPE_OK;
2579     }
2580 if ((uptr->flags & UNIT_ONL) == 0) {
2581     if (uptr->flags & UNIT_ATT)
2582         fprintf (st, "Unit %d is available\n", u);
2583     else fprintf (st, "Unit %d is offline\n", u);
2584     return SCPE_OK;
2585     }
2586 if (uptr->cpkt) {
2587     fprintf (st, "Unit %d current ", u);
2588     rq_show_pkt (st, cp, uptr->cpkt);
2589     if ((pkt = uptr->pktq)) {
2590         do {
2591             fprintf (st, "Unit %d queued ", u);
2592             rq_show_pkt (st, cp, pkt);
2593             } while ((pkt = cp->pak[pkt].link));
2594         }
2595     }
2596 else fprintf (st, "Unit %d queues are empty\n", u);
2597 return SCPE_OK;
2598 }
2599 
rq_show_ctrl(FILE * st,UNIT * uptr,int32 val,void * desc)2600 t_stat rq_show_ctrl (FILE *st, UNIT *uptr, int32 val, void *desc)
2601 {
2602 MSC *cp = rq_ctxmap[uptr->cnum];
2603 DEVICE *dptr = rq_devmap[uptr->cnum];
2604 int32 i, pkt;
2605 
2606 if (cp->csta != CST_UP) {
2607     fprintf (st, "Controller is not initialized\n");
2608     return SCPE_OK;
2609     }
2610 if (val & RQ_SH_RI) {
2611     if (cp->pip)
2612         fprintf (st, "Polling in progress, host timer = %d\n", cp->hat);
2613     else fprintf (st, "Host timer = %d\n", cp->hat);
2614     fprintf (st, "Command ");
2615     rq_show_ring (st, &cp->cq);
2616     fprintf (st, "Response ");
2617     rq_show_ring (st, &cp->rq);
2618     }
2619 if (val & RQ_SH_FR) {
2620     if ((pkt = cp->freq)) {
2621         for (i = 0; pkt != 0; i++, pkt = cp->pak[pkt].link) {
2622             if (i == 0)
2623                 fprintf (st, "Free queue = %d", pkt);
2624             else if ((i % 16) == 0)
2625                 fprintf (st, ",\n %d", pkt);
2626             else fprintf (st, ", %d", pkt);
2627             }
2628         fprintf (st, "\n");
2629         }
2630     else fprintf (st, "Free queue is empty\n");
2631     }
2632 if (val & RQ_SH_RS) {
2633     if ((pkt = cp->rspq)) {
2634         do {
2635             fprintf (st, "Response ");
2636             rq_show_pkt (st, cp, pkt);
2637             } while ((pkt = cp->pak[pkt].link));
2638         }
2639     else fprintf (st, "Response queue is empty\n");
2640     }
2641 if (val & RQ_SH_UN) {
2642     for (i = 0; i < RQ_NUMDR; i++)
2643         rq_show_unitq (st, dptr->units + i, 0, desc);
2644     }
2645 return SCPE_OK;
2646 }
2647