1 /* hp2100_ds.c: HP 13037D/13175D disc controller/interface simulator
2 
3    Copyright (c) 2004-2012, Robert M. Supnik
4    Copyright (c) 2012-2021, J. David Bryan
5 
6    Permission is hereby granted, free of charge, to any person obtaining a copy
7    of this software and associated documentation files (the "Software"), to deal
8    in the Software without restriction, including without limitation the rights
9    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10    copies of the Software, and to permit persons to whom the Software is
11    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 THE
19    AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20    ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21    WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 
23    Except as contained in this notice, the names of the authors shall not be
24    used in advertising or otherwise to promote the sale, use or other dealings
25    in this Software without prior written authorization from the authors.
26 
27    DS           13037D/13175D disc controller/interface
28 
29    09-Apr-21    JDB     Replaced "find_reg" call with inline search in "ds_reset"
30    02-Apr-21    JDB     Changed u3-u6 synonyms to title case to avoid conflicts
31    09-Dec-20    JDB     Replaced "io_assert" with "io_assert_ENF/SIR"
32    02-Dec-20    JDB     RESET no longer presets the interface
33    13-Jun-18    JDB     Revised I/O model
34    07-May-18    JDB     Removed "dl_clear_controller" status return
35    27-Feb-18    JDB     Added the BMDL
36    21-Feb-18    JDB     ATTACH -N now creates a full-size disc image
37    11-Jul-17    JDB     Renamed "ibl_copy" to "cpu_ibl"
38    15-Mar-17    JDB     Trace flags are now global
39                         Changed DEBUG_PRI calls to tprintfs
40    10-Mar-17    JDB     Added IOBUS to the debug table
41    09-Mar-17    JDB     Deprecated LOCKED/WRITEENABLED for PROTECT/UNPROTECT
42    13-May-16    JDB     Modified for revised SCP API function parameter types
43    04-Mar-16    JDB     Name changed to "hp2100_disclib" until HP 3000 integration
44    30-Dec-14    JDB     Added S-register parameters to ibl_copy
45    24-Dec-14    JDB     Use T_ADDR_FMT with t_addr values for 64-bit compatibility
46    18-Mar-13    JDB     Fixed poll_drives definition to match declaration
47    24-Oct-12    JDB     Changed CNTLR_OPCODE to title case to avoid name clash
48    29-Mar-12    JDB     Rewritten to use the MAC/ICD disc controller library
49                         ioIOO now notifies controller service of parameter output
50    14-Feb-12    JDB     Corrected SRQ generation and FIFO under/overrun detection
51                         Corrected Clear command to conform to the hardware
52                         Fixed Request Status to return Unit Unavailable if illegal
53                         Seek and Cold Load Read now Seek Check if seek in progress
54                         Remodeled command wait for seek completion
55    10-Feb-12    JDB     Deprecated DEVNO in favor of SC
56    21-Jun-11    JDB     Corrected status returns for disabled drive, auto-seek
57                         beyond drive limits, Request Sector Address and Wakeup
58                         with invalid or offline unit
59                         Address verification reenabled if auto-seek during
60                         Read Without Verify
61    28-Mar-11    JDB     Tidied up signal handling
62    26-Oct-10    JDB     Changed I/O signal handler for revised signal model
63    26-Jun-08    JDB     Rewrote device I/O to model backplane signals
64    31-Dec-07    JDB     Corrected and verified ioCRS action
65    20-Dec-07    JDB     Corrected DPTR register definition from FLDATA to DRDATA
66    28-Dec-06    JDB     Added ioCRS state to I/O decoders
67    03-Aug-06    JDB     Fixed REQUEST STATUS command to clear status-1
68                         Removed redundant attached test in "ds_detach"
69    18-Mar-05    RMS     Added attached test to detach routine
70    01-Mar-05    JDB     Added SET UNLOAD/LOAD
71 
72    References:
73      - 13037 Disc Controller Technical Information Package
74          (13037-90902, August 1980)
75      - 7925D Disc Drive Service Manual
76          (07925-90913, April 1984)
77      - HP 12992 Loader ROMs Installation Manual
78          (12992-90001, April 1986)
79      - DVR32 RTE Moving Head Driver source
80          (92084-18711, Revision 5000)
81 
82 
83    The 13037D multiple-access (MAC) disc controller supports from one to eight
84    HP 7905 (15 MB), 7906 (20MB), 7920 (50 MB), and 7925 (120 MB) disc drives
85    accessed by one to eight CPUs.  The controller hardware consists of a 16-bit
86    microprogrammed processor constructed from 74S181 bit slices operating at 5
87    MHz, a device controller providing the interconnections to the drives and CPU
88    interfaces, and an error correction controller that enables the correction of
89    up to 32-bit error bursts.  1024 words of 24-bit firmware are stored in ROM.
90 
91    The 13175D disc interface is used to connect the HP 1000 CPU to the 13037
92    device controller.  In a multiple-CPU system, one interface is strapped to
93    reset the controller when the CPU's front panel PRESET button is pressed.
94 
95    This module simulates a 13037D connected to a single 13175D interface.  From
96    one to eight drives may be connected, and drive types may be freely
97    intermixed.  A unit that is enabled but not attached appears to be a
98    connected drive that does not have a disc pack in place.  A unit that is
99    disabled appears to be disconnected.
100 
101    This simulator is an adaptation of the code originally written by Bob Supnik.
102    The functions of the controller have been separated from the functions of the
103    interface, with the former placed into a separate disc controller library.
104    This allows the library to support other CPU interfaces, such as the 12821A
105    HP-IB disc interface, that use substantially different communication
106    protocols.  The library functions implement the controller command set for
107    the drive units.  The interface functions handle the transfer of commands and
108    data to and from the CPU.
109 
110    In hardware, the controller runs continuously in one of three states: in the
111    Poll Loop (idle state), in the Command Wait Loop (wait state), or in command
112    execution (busy state).  In simulation, the controller is run only when a
113    command is executing or when a transition into or out of the two loops might
114    occur.  Internally, the controller handles these transitions:
115 
116     - when a command other than End terminates (busy => wait)
117     - when the End command terminates (busy => idle)
118     - when a command timeout occurs (wait => idle)
119     - when a parameter timeout occurs (busy => idle)
120     - when a seek completes (if idle and interrupts are enabled, idle => wait)
121 
122    The interface must call the controller library to handle these transitions:
123 
124     - when a command is received from the CPU (idle or wait => busy)
125     - when interrupts are enabled (if idle and drive Attention, idle => wait)
126 
127    In addition, each transition to the wait state must check for a pending
128    command, and each transition to the idle state must check for both a pending
129    command and a drive with Attention status asserted.
130 
131 
132    Implementation notes:
133 
134     1. Although the 13175D has a 16-word FIFO, the "full" level is set at 5
135        entries in hardware to avoid a long DCPC preemption time at the start of
136        a disc write as the FIFO fills.
137 */
138 
139 
140 
141 #include "hp2100_defs.h"
142 #include "hp2100_io.h"
143 #include "hp2100_disclib.h"
144 
145 
146 
147 /* Program constants */
148 
149 #define DS_DRIVES       (DL_MAXDRIVE + 1)               /* number of disc drive units */
150 #define DS_UNITS        (DS_DRIVES + DL_AUXUNITS)       /* total number of units */
151 
152 #define ds_cntlr        ds_unit [DL_MAXDRIVE + 1]       /* controller unit alias */
153 
154 #define FIFO_SIZE       16                              /* FIFO depth */
155 
156 #define FIFO_EMPTY      (ds.fifo_count == 0)            /* FIFO empty test */
157 #define FIFO_STOP       (ds.fifo_count >= 5)            /* FIFO stop filling test */
158 #define FIFO_FULL       (ds.fifo_count == FIFO_SIZE)    /* FIFO full test */
159 
160 #define PRESET_ENABLE   TRUE                            /* Preset Jumper (W4) is enabled */
161 
162 
163 /* Per-card state variables */
164 
165 typedef struct {
166     FLIP_FLOP    control;                       /* control flip-flop */
167     FLIP_FLOP    flag;                          /* flag flip-flop */
168     FLIP_FLOP    flag_buffer;                   /* flag buffer flip-flop */
169     FLIP_FLOP    srq;                           /* SRQ flip-flop */
170     FLIP_FLOP    edt;                           /* EDT flip-flop */
171     FLIP_FLOP    cmfol;                         /* command follows flip-flop */
172     FLIP_FLOP    cmrdy;                         /* command ready flip-flop */
173     uint16       fifo [FIFO_SIZE];              /* FIFO buffer */
174     uint32       fifo_count;                    /* FIFO occupancy counter */
175     REG          *fifo_reg;                     /* FIFO register pointer */
176     } CARD_STATE;
177 
178 
179 /* MAC disc state variables */
180 
181 static UNIT ds_unit [DS_UNITS];                         /* unit array */
182 
183 static CARD_STATE ds;                                   /* card state */
184 
185 static uint16 buffer [DL_BUFSIZE];                      /* command/status/sector buffer */
186 
187 static CNTLR_VARS mac_cntlr =                           /* MAC controller */
188     { CNTLR_INIT (MAC, buffer, &ds_cntlr) };
189 
190 
191 
192 /* Interface local SCP support routines */
193 
194 static IO_INTERFACE ds_interface;
195 
196 
197 /* Interface local SCP support routines */
198 
199 static t_stat ds_service_drive      (UNIT   *uptr);
200 static t_stat ds_service_controller (UNIT   *uptr);
201 static t_stat ds_service_timer      (UNIT   *uptr);
202 static t_stat ds_reset              (DEVICE *dptr);
203 static t_stat ds_attach             (UNIT   *uptr,  char   *cptr);
204 static t_stat ds_detach             (UNIT   *uptr);
205 static t_stat ds_boot               (int32  unitno, DEVICE *dptr);
206 static t_stat ds_load_unload        (UNIT   *uptr,  int32  value, char *cptr, void *desc);
207 
208 
209 /* MAC disc local utility routines */
210 
211 static void   start_command     (void);
212 static void   poll_interface    (void);
213 static void   poll_drives       (void);
214 static void   fifo_load         (uint16 data);
215 static uint16 fifo_unload       (void);
216 static void   fifo_clear        (void);
217 static t_stat activate_unit     (UNIT *uptr);
218 
219 
220 /* Interface SCP data structures */
221 
222 
223 /* Device information block */
224 
225 static DIB ds_dib = {
226     &ds_interface,                              /* the device's I/O interface function pointer */
227     NULL,                                       /* the power state function pointer */
228     DS,                                         /* the device's select code (02-77) */
229     0,                                          /* the card index */
230     "13175D Disc Controller Interface",         /* the card description */
231     "12992B 7905/7906/7920/7925 Disc Loader"    /* the ROM description */
232     };
233 
234 
235 /* Units list */
236 
237 #define UNIT_FLAGS  (UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | UNIT_DISABLE | UNIT_UNLOAD)
238 
239 static UNIT ds_unit [] = {
240     { UDATA (&ds_service_drive,      UNIT_FLAGS | MODEL_7905, D7905_WORDS) },   /* drive unit 0 */
241     { UDATA (&ds_service_drive,      UNIT_FLAGS | MODEL_7905, D7905_WORDS) },   /* drive unit 1 */
242     { UDATA (&ds_service_drive,      UNIT_FLAGS | MODEL_7905, D7905_WORDS) },   /* drive unit 2 */
243     { UDATA (&ds_service_drive,      UNIT_FLAGS | MODEL_7905, D7905_WORDS) },   /* drive unit 3 */
244     { UDATA (&ds_service_drive,      UNIT_FLAGS | MODEL_7905, D7905_WORDS) },   /* drive unit 4 */
245     { UDATA (&ds_service_drive,      UNIT_FLAGS | MODEL_7905, D7905_WORDS) },   /* drive unit 5 */
246     { UDATA (&ds_service_drive,      UNIT_FLAGS | MODEL_7905, D7905_WORDS) },   /* drive unit 6 */
247     { UDATA (&ds_service_drive,      UNIT_FLAGS | MODEL_7905, D7905_WORDS) },   /* drive unit 7 */
248     { UDATA (&ds_service_controller, UNIT_DIS,                0)           },   /* controller unit */
249     { UDATA (&ds_service_timer,      UNIT_DIS,                0)           }    /* timer unit */
250     };
251 
252 
253 /* Register list */
254 
255 static REG ds_reg [] = {
256 /*    Macro   Name    Location                  Radix   Width     Offset      Depth            Flags       */
257 /*    ------  ------  ------------------------  ----- ----------  ------  -------------  ----------------- */
258     { FLDATA (CMFOL,  ds.cmfol,                                      0)                                    },
259     { FLDATA (CMRDY,  ds.cmrdy,                                      0)                                    },
260     { DRDATA (FCNT,   ds.fifo_count,                     5)                                                },
261     { BRDATA (FIFO,   ds.fifo,                    8,    16,               FIFO_SIZE),    REG_CIRC          },
262     { ORDATA (FREG,   ds.fifo_reg,                      32),                             REG_HRO           },
263 
264     { ORDATA (CNTYPE, mac_cntlr.type,                    2),                             REG_HRO           },
265     { ORDATA (STATE,  mac_cntlr.state,                   2)                                                },
266     { ORDATA (OPCODE, mac_cntlr.opcode,                  6)                                                },
267     { ORDATA (STATUS, mac_cntlr.status,                  6)                                                },
268     { FLDATA (EOC,    mac_cntlr.eoc,                                 0)                                    },
269     { FLDATA (EOD,    mac_cntlr.eod,                                 0)                                    },
270     { ORDATA (SPDU,   mac_cntlr.spd_unit,               16)                                                },
271     { ORDATA (FLMASK, mac_cntlr.file_mask,               4)                                                },
272     { ORDATA (RETRY,  mac_cntlr.retry,                   4),                             REG_HRO           },
273     { ORDATA (CYL,    mac_cntlr.cylinder,               16)                                                },
274     { ORDATA (HEAD,   mac_cntlr.head,                    6)                                                },
275     { ORDATA (SECTOR, mac_cntlr.sector,                  8)                                                },
276     { ORDATA (VFYCNT, mac_cntlr.verify_count,           16)                                                },
277     { ORDATA (LASPOL, mac_cntlr.poll_unit,               3)                                                },
278     { HRDATA (BUFPTR, mac_cntlr.buffer,                 32),                             REG_HRO           },
279     { BRDATA (BUFFER, buffer,                     8,    16,               DL_BUFSIZE)                      },
280     { DRDATA (INDEX,  mac_cntlr.index,                   8)                                                },
281     { DRDATA (LENGTH, mac_cntlr.length,                  8)                                                },
282     { HRDATA (AUXPTR, mac_cntlr.aux,                    32),                             REG_HRO           },
283     { DRDATA (STIME,  mac_cntlr.seek_time,              24),                             PV_LEFT | REG_NZ  },
284     { DRDATA (ITIME,  mac_cntlr.sector_time,            24),                             PV_LEFT | REG_NZ  },
285     { DRDATA (CTIME,  mac_cntlr.cmd_time,               24),                             PV_LEFT | REG_NZ  },
286     { DRDATA (DTIME,  mac_cntlr.data_time,              24),                             PV_LEFT | REG_NZ  },
287     { DRDATA (WTIME,  mac_cntlr.wait_time,              31),                             PV_LEFT | REG_NZ  },
288 
289     { FLDATA (CTL,    ds.control,                                    0)                                    },
290     { FLDATA (FLG,    ds.flag,                                       0)                                    },
291     { FLDATA (FBF,    ds.flag_buffer,                                0)                                    },
292     { FLDATA (SRQ,    ds.srq,                                        0)                                    },
293     { FLDATA (EDT,    ds.edt,                                        0)                                    },
294 
295     { URDATA (UCYL,   ds_unit[0].Cyl,            10,    10,          0,   DS_UNITS,      PV_LEFT)          },
296     { URDATA (UOP,    ds_unit[0].Op,              8,     6,          0,   DS_UNITS,      PV_RZRO)          },
297     { URDATA (USTAT,  ds_unit[0].Stat,            2,     8,          0,   DS_UNITS,      PV_RZRO)          },
298     { URDATA (UPHASE, ds_unit[0].Phase,           8,     3,          0,   DS_UNITS,      PV_RZRO)          },
299     { URDATA (UPOS,   ds_unit[0].pos,             8,  T_ADDR_W,      0,   DS_UNITS,      PV_LEFT)          },
300     { URDATA (UWAIT,  ds_unit[0].wait,            8,    32,          0,   DS_UNITS,      PV_LEFT)          },
301 
302       DIB_REGS (ds_dib),
303 
304     { NULL }
305     };
306 
307 
308 /* Modifier list.
309 
310    For the drive models, the modifiers provide this SHOW behavior:
311 
312     - when detached and autosized, prints "autosize"
313     - when detached and not autosized, prints the model number
314     - when attached, prints the model number (regardless of autosizing)
315 
316 
317    Implementation notes:
318 
319     1. The validation routine does not allow the model number or autosizing
320        option to be changed when the unit is attached.  Therefore, specifying
321        UNIT_ATT in the mask field has no adverse effect.
322 
323     2. The modifier DEVNO is deprecated in favor of SC but is retained for
324        compatibility.
325 */
326 
327 static MTAB ds_mod [] = {
328 /*    Mask Value    Match Value   Print String       Match String     Validation        Display  Descriptor */
329 /*    ------------  ------------  -----------------  ---------------  ----------------  -------  ---------- */
330     { UNIT_UNLOAD,  UNIT_UNLOAD,  "heads unloaded",  "UNLOADED",      &ds_load_unload,  NULL,    NULL       },
331     { UNIT_UNLOAD,  0,            "heads loaded",    "LOADED",        &ds_load_unload,  NULL,    NULL       },
332 
333     { UNIT_WLK,     UNIT_WLK,     "protected",       "PROTECT",       NULL,             NULL,    NULL       },
334     { UNIT_WLK,     0,            "unprotected",     "UNPROTECT",     NULL,             NULL,    NULL       },
335 
336     { UNIT_WLK,     UNIT_WLK,     NULL,              "LOCKED",        NULL,             NULL,    NULL       },
337     { UNIT_WLK,     0,            NULL,              "WRITEENABLED",  NULL,             NULL,    NULL       },
338 
339     { UNIT_FMT,     UNIT_FMT,     "format enabled",  "FORMAT",        NULL,             NULL,    NULL       },
340     { UNIT_FMT,     0,            "format disabled", "NOFORMAT",      NULL,             NULL,    NULL       },
341 
342 /*                                                              Print       Match                                 */
343 /*    Mask Value                         Match Value            String      String      Validation     Disp  Desc */
344 /*    ---------------------------------  ---------------------  ----------  ----------  -------------  ----  ---- */
345     { UNIT_AUTO | UNIT_ATT,              UNIT_AUTO,             "autosize", "AUTOSIZE", &dl_set_model, NULL, NULL },
346     { UNIT_AUTO | UNIT_ATT | UNIT_MODEL, MODEL_7905,            "7905",     "7905",     &dl_set_model, NULL, NULL },
347     { UNIT_AUTO | UNIT_ATT | UNIT_MODEL, MODEL_7906,            "7906",     "7906",     &dl_set_model, NULL, NULL },
348     { UNIT_AUTO | UNIT_ATT | UNIT_MODEL, MODEL_7920,            "7920",     "7920",     &dl_set_model, NULL, NULL },
349     { UNIT_AUTO | UNIT_ATT | UNIT_MODEL, MODEL_7925,            "7925",     "7925",     &dl_set_model, NULL, NULL },
350     { UNIT_ATT | UNIT_MODEL,             UNIT_ATT | MODEL_7905, "7905",     NULL,       NULL,          NULL, NULL },
351     { UNIT_ATT | UNIT_MODEL,             UNIT_ATT | MODEL_7906, "7906",     NULL,       NULL,          NULL, NULL },
352     { UNIT_ATT | UNIT_MODEL,             UNIT_ATT | MODEL_7920, "7920",     NULL,       NULL,          NULL, NULL },
353     { UNIT_ATT | UNIT_MODEL,             UNIT_ATT | MODEL_7925, "7925",     NULL,       NULL,          NULL, NULL },
354 
355 /*    Entry Flags          Value  Print String  Match String  Validation    Display        Descriptor       */
356 /*    -------------------  -----  ------------  ------------  ------------  -------------  ---------------- */
357     { MTAB_XDV,              1u,  "SC",         "SC",         &hp_set_dib,  &hp_show_dib,  (void *) &ds_dib },
358     { MTAB_XDV | MTAB_NMO,  ~1u,  "DEVNO",      "DEVNO",      &hp_set_dib,  &hp_show_dib,  (void *) &ds_dib },
359     { 0 }
360     };
361 
362 
363 /* Debugging trace list */
364 
365 static DEBTAB ds_deb [] = {
366     { "RWSC",  DEB_RWSC    },
367     { "CMDS",  DEB_CMDS    },
368     { "CPU",   DEB_CPU     },
369     { "BUF",   DEB_BUF     },
370     { "SERV",  TRACE_SERV  },
371     { "IOBUS", TRACE_IOBUS },
372     { NULL,    0           }
373     };
374 
375 
376 /* Device descriptor */
377 
378 DEVICE ds_dev = {
379     "DS",                                       /* device name */
380     ds_unit,                                    /* unit array */
381     ds_reg,                                     /* register array */
382     ds_mod,                                     /* modifier array */
383     DS_UNITS,                                   /* number of units */
384     8,                                          /* address radix */
385     27,                                         /* address width = 128 MB */
386     1,                                          /* address increment */
387     8,                                          /* data radix */
388     16,                                         /* data width */
389     NULL,                                       /* examine routine */
390     NULL,                                       /* deposit routine */
391     &ds_reset,                                  /* reset routine */
392     &ds_boot,                                   /* boot routine */
393     &ds_attach,                                 /* attach routine */
394     &ds_detach,                                 /* detach routine */
395     &ds_dib,                                    /* device information block */
396     DEV_DISABLE | DEV_DEBUG,                    /* device flags */
397     0,                                          /* debug control flags */
398     ds_deb,                                     /* debug flag name table */
399     NULL,                                       /* memory size change routine */
400     NULL                                        /* logical device name */
401     };
402 
403 
404 
405 /* Interface local SCP support routines */
406 
407 
408 
409 /* Disc interface.
410 
411    The 13175D disc interface data path consists of an input multiplexer/latch
412    and a 16-word FIFO buffer.  The FIFO source may be either the CPU's I/O
413    input bus or the controller's interface data bus.  The output of the FIFO may
414    be enabled either to the CPU's I/O output bus or the interface data bus.
415 
416    The control path consists of the usual control, flag buffer, flag, and SRQ
417    flip-flops, although flag and SRQ are decoupled to allow the full DCPC
418    transfer rate through the FIFO (driving SRQ from the flag limits transfers to
419    every other cycle).  SRQ is based on the FIFO level: if data or room in the
420    FIFO is available, SRQ is set to initiate a transfer.  The flag is only used
421    to signal an interrupt at the end of a command.
422 
423    One unusual aspect is that SFC and SFS test different things, rather than
424    complementary states of the same thing.  SFC tests the controller busy state,
425    and SFS tests the flag flip-flop.
426 
427    In addition, the card contains end-of-data-transfer, command-follows, and
428    command-ready flip-flops.  EDT is set when the DCPC EDT signal is asserted
429    and is used in conjunction with the FIFO level to assert the end-of-data
430    signal to the controller.  The command-follows flip-flop is set by a CLC to
431    indicate that the next data word output from the CPU is a disc command.  The
432    command-ready flip-flop is set when a command is received to schedule an
433    interface poll.
434 
435 
436    Implementation notes:
437 
438     1. In hardware, SRQ is enabled only when the controller is reading or
439        writing the disc (IFIN or IFOUT functions are asserted) and set when the
440        FIFO is not empty (read) or not full (write).  In simulation, SRQ is set
441        by the unit service read/write data phase transfers and cleared in the
442        IOI and IOO signal handlers when the FIFO is empty (read) or full
443        (write).
444 
445     2. The DCPC EDT signal cannot set the controller's end-of-data flag directly
446        because a write EOD must occur only after the FIFO has been drained.
447 
448     3. Polling the interface or drives must be deferred to the end of I/O signal
449        handling.  If they are performed in the IOO/STC handlers themselves, an
450        associated CLF might clear the flag that was set by the poll.
451 
452     4. Executing a CLC sets the controller's end-of-data flag, which will abort
453        a read or write data transfer in progress.  Parameter transfers are not
454        affected.  If a command is received when a parameter is expected, the
455        word is interpreted as data, even though the command-ready flip-flop is
456        set.  The controller firmware only checks DTRDY for a parameter transfer,
457        and DTRDY is asserted whenever the FIFO is not empty.
458 
459     5. The hardware Interface Function and Flag Buses are not implemented
460        explicitly.  Instead, interface functions and signals are inferred by the
461        interface from the current command operation and phase.
462 */
463 
ds_interface(const DIB * dibptr,INBOUND_SET inbound_signals,HP_WORD inbound_value)464 static SIGNALS_VALUE ds_interface (const DIB *dibptr, INBOUND_SET inbound_signals, HP_WORD inbound_value)
465 {
466 static const char * const output_state [] = { "Data", "Command" };
467 const char * const hold_or_clear = (inbound_signals & ioCLF ? ",C" : "");
468 INBOUND_SIGNAL signal;
469 INBOUND_SET    working_set = inbound_signals;
470 SIGNALS_VALUE  outbound    = { ioNONE, 0 };
471 t_bool         irq_enabled = FALSE;
472 t_bool         command_issued = FALSE;
473 t_bool         interrupt_enabled = FALSE;
474 
475 while (working_set) {
476     signal = IONEXTSIG (working_set);                   /* isolate the next signal */
477 
478     switch (signal) {                                   /* dispatch the I/O signal */
479 
480         case ioCLF:                                     /* clear flag flip-flop */
481             ds.flag_buffer = CLEAR;                     /* clear the flag buffer */
482             ds.flag        = CLEAR;                     /*   and flag */
483 
484             tprintf (ds_dev, DEB_CMDS, "[CLF] Flag cleared\n");
485             break;
486 
487 
488         case ioSTF:                                     /* set flag flip-flop */
489             ds.flag_buffer = SET;                       /* set the flag buffer */
490 
491             tprintf (ds_dev, DEB_CMDS, "[STF] Flag set\n");
492             break;
493 
494 
495         case ioENF:                                     /* enable flag */
496             if (ds.flag_buffer == SET)                  /* if the flag buffer flip-flop is set */
497                 ds.flag = SET;                          /*   then set the flag flip-flop */
498             break;
499 
500 
501         case ioSFC:                                     /* skip if flag is clear */
502             if (mac_cntlr.state != cntlr_busy)          /* skip if the controller is not busy */
503                 outbound.signals |= ioSKF;
504             break;
505 
506 
507         case ioSFS:                                     /* skip if flag is set */
508             if (ds.flag == SET)                         /* assert SKF if the flag is set */
509                 outbound.signals |= ioSKF;
510             break;
511 
512 
513         case ioIOI:                                         /* I/O data input */
514             outbound.value = fifo_unload ();                /* unload the next word from the FIFO */
515 
516             tprintf (ds_dev, DEB_CPU, "[LIx%s] Data = %06o\n", hold_or_clear, outbound.value);
517 
518             if (FIFO_EMPTY) {                               /* is the FIFO now empty? */
519                 if (ds.srq == SET)
520                     tprintf (ds_dev, DEB_CMDS, "[LIx%s] SRQ cleared\n", hold_or_clear);
521 
522                 ds.srq = CLEAR;                             /* clear SRQ */
523 
524                 if (ds_cntlr.Phase == data_phase) {         /* is this an outbound parameter? */
525                     ds_cntlr.wait = mac_cntlr.data_time;    /* activate the controller */
526                     activate_unit (&ds_cntlr);              /*   to acknowledge the data */
527                     }
528                 }
529             break;
530 
531 
532         case ioIOO:                                         /* I/O data output */
533             tprintf (ds_dev, DEB_CPU, "[OTx%s] %s = %06o\n",
534                      hold_or_clear, output_state [ds.cmfol], inbound_value);
535 
536             fifo_load ((uint16) inbound_value);             /* load the word into the FIFO */
537 
538             if (ds.cmfol == SET) {                          /* are we expecting a command? */
539                 ds.cmfol = CLEAR;                           /* clear the command follows flip-flop */
540                 ds.cmrdy = SET;                             /* set the command ready flip-flop */
541                 command_issued = TRUE;                      /*   and request an interface poll */
542                 }
543 
544             else {                                          /* not a command */
545                 if (ds_cntlr.Phase == data_phase) {         /* is this an inbound parameter? */
546                     ds_cntlr.wait = mac_cntlr.data_time;    /* activate the controller */
547                     activate_unit (&ds_cntlr);              /*   to receive the data */
548                     }
549 
550                 if (FIFO_STOP) {                            /* is the FIFO now full enough? */
551                     if (ds.srq == SET)
552                         tprintf (ds_dev, DEB_CMDS, "[OTx%s] SRQ cleared\n", hold_or_clear);
553 
554                     ds.srq = CLEAR;                         /* clear SRQ to stop filling */
555                     }
556                 }
557             break;
558 
559 
560         case ioPOPIO:                                   /* power-on preset to I/O */
561             ds.flag_buffer = SET;                       /* set flag buffer */
562             ds.cmrdy       = CLEAR;                     /* clear the command ready flip-flop */
563 
564             tprintf (ds_dev, DEB_CMDS, "[POPIO] Flag set\n");
565             break;
566 
567 
568         case ioCRS:                                         /* control reset */
569             tprintf (ds_dev, DEB_CMDS, "[CRS] Master reset\n");
570 
571             ds.control = CLEAR;                             /* clear the control */
572             ds.cmfol = CLEAR;                               /*   and command follows flip-flops */
573 
574             if (PRESET_ENABLE) {                            /* is preset enabled for this interface? */
575                 fifo_clear ();                              /* clear the FIFO */
576 
577                 dl_clear_controller (&mac_cntlr, ds_unit,   /* do a hard clear of the controller */
578                                      hard_clear);
579                 }
580             break;
581 
582 
583         case ioCLC:                                     /* clear control flip-flop */
584             tprintf (ds_dev, DEB_CMDS, "[CLC%s] Control cleared\n", hold_or_clear);
585 
586             ds.control = CLEAR;                         /* clear the control */
587             ds.edt = CLEAR;                             /*   and EDT flip-flops */
588             ds.cmfol = SET;                             /* set the command follows flip-flop */
589             mac_cntlr.eod = SET;                        /* set the controller's EOD flag */
590 
591             fifo_clear ();                              /* clear the FIFO */
592             break;
593 
594 
595         case ioSTC:                                     /* set control flip-flop */
596             ds.control = SET;                           /* set the control flip-flop */
597 
598             interrupt_enabled = TRUE;                   /* check for drive attention */
599 
600             tprintf (ds_dev, DEB_CMDS, "[STC%s] Control set\n", hold_or_clear);
601             break;
602 
603 
604         case ioEDT:                                     /* end data transfer */
605             ds.edt = SET;                               /* set the EDT flip-flop */
606 
607             tprintf (ds_dev, DEB_CPU, "[EDT] DCPC transfer ended\n");
608             break;
609 
610 
611         case ioSIR:                                     /* set interrupt request */
612             if (ds.control & ds.flag)                   /* if control and flag are set */
613                 outbound.signals |= cnVALID;            /*   then deny PRL */
614             else                                        /* otherwise */
615                 outbound.signals |= cnPRL | cnVALID;    /*   conditionally assert PRL */
616 
617             if (ds.control & ds.flag & ds.flag_buffer)  /* if control and flag and flag buffer are set */
618                 outbound.signals |= cnIRQ;              /*   then conditionally assert IRQ */
619 
620             if (ds.srq == SET)                          /* if the SRQ flip-flop is set */
621                 outbound.signals |= ioSRQ;              /*   then assert SRQ */
622             break;
623 
624 
625         case ioIAK:                                     /* interrupt acknowledge */
626             ds.flag_buffer = CLEAR;
627             break;
628 
629 
630         case ioIEN:                                     /* interrupt enable */
631             irq_enabled = TRUE;
632             break;
633 
634 
635         case ioPRH:                                         /* priority high */
636             if (irq_enabled && outbound.signals & cnIRQ)    /* if IRQ is enabled and conditionally asserted */
637                 outbound.signals |= ioIRQ | ioFLG;          /*   then assert IRQ and FLG */
638 
639             if (not irq_enabled || outbound.signals & cnPRL)    /* if IRQ is disabled or PRL is conditionally asserted */
640                 outbound.signals |= ioPRL;                      /*   then assert it unconditionally */
641             break;
642 
643 
644         case ioPON:                                     /* not used by this interface */
645             break;
646         }
647 
648     IOCLEARSIG (working_set, signal);                   /* remove the current signal from the set */
649     }
650 
651 
652 if (command_issued)                                     /* was a command received? */
653     poll_interface ();                                  /* poll the interface for the next command */
654 else if (interrupt_enabled)                             /* were interrupts enabled? */
655     poll_drives ();                                     /* poll the drives for Attention */
656 
657 return outbound;                                        /* return the outbound signals and value */
658 }
659 
660 
661 /* Service the disc drive unit.
662 
663    The unit service routine is called to execute scheduled controller commands
664    for the specified unit.  The actions to be taken depend on the current state
665    of the controller and the unit.
666 
667    Generally, the controller library service routine handles all of the disc
668    operations except data transfer to and from the interface.  Read transfers
669    are responsible for loading words from the sector buffer into the FIFO and
670    enabling SRQ.  If the current sector transfer is complete, either due to EDT
671    assertion or buffer exhaustion, the controller is moved to the end phase to
672    complete or continue the read with the next sector.  In either case, the unit
673    is rescheduled.  If the FIFO overflows, the read terminates with a data
674    overrun error.
675 
676    Write transfers set the initial SRQ to request words from the CPU.  As each
677    word arrives, it is unloaded from the FIFO into the sector buffer, and SRQ is
678    enabled.  If the current sector transfer is complete, the controller is moved
679    to the end phase.  If the FIFO underflows, the write terminates with a data
680    overrun error.
681 
682    The synchronous nature of the disc drive requires that data be supplied or
683    accepted continuously by the CPU.  DCPC generally assures that this occurs,
684    and the FIFO allows for some latency before an overrun or underrun occurs.
685 
686    The other operation the interface must handle is seek completion.  The
687    controller handles seek completion by setting Attention status in the drive's
688    status word.  The interface is responsible for polling the drives if the
689    controller is idle and interrupts are enabled.
690 
691 
692    Implementation notes:
693 
694     1. Every command except Seek, Recalibrate, and End sets the flag when the
695        command completes.  A command completes when the controller is no longer
696        busy (it becomes idle for Seek, Recalibrate, and End, or it becomes
697        waiting for all others).  Seek and Recalibrate may generate errors (e.g.,
698        heads unloaded), in which case the flag must be set.  But in these cases,
699        the controller state is waiting, not idle.
700 
701        However, it is insufficient simply to check that the controller has moved
702        to the wait state, because a seek may complete while the controller is
703        waiting for the next command.  For example, a Seek is started on unit 0,
704        and the controller moves to the idle state.  But before the seek
705        completes, another command is issued that attempts to access unit 1,
706        which is not ready.  The command fails with a Status-2 error, and the
707        controller moves to the wait state.  When the seek completes, the
708        controller is waiting with error status.  We must determine whether the
709        seek completed successfully or not, as we must interrupt in the latter
710        case.
711 
712        Therefore, we determine seek completion by checking if the Attention
713        status was set.  Attention sets only if the seek completes successfully.
714 
715        (Actually, Attention sets if a seek check occurs, but in that case, the
716        command terminated before the seek ever started.  Also, a seek may
717        complete while the controller is busy, waiting, or idle.)
718 
719     2. For debug printouts, we want to print the name of the command that has
720        completed when the controller returns to the idle or wait state.
721        Normally, we would use the controller's "opcode" field to identify the
722        command that completed.  However, while waiting for Seek or Recalibrate
723        completion, "opcode" may be set to another command if that command does
724        not access this drive.  For example, it might be set to a Read of another
725        unit, or a Request Status for this unit.  So we can't rely on "opcode" to
726        report the correct name of the completed positioning command.
727 
728        However, we cannot rely on "uptr->Op" either, as that can be changed
729        during the course of a command.  For example, Read Without Verify is
730        changed to Read after a track crossing.
731 
732        Instead, we have to determine whether a seek is completing.  If it is,
733        then we report "uptr->Op"; otherwise, we report "opcode".
734 
735     3. The initial write SRQ must set only at the transition from the start
736        phase to the data phase.  If a write command begins with an auto-seek,
737        the drive service will be entered twice in the start phase (the first
738        entry performs the seek, and the second begins the write).  In hardware,
739        SRQ does not assert until the write begins.
740 
741     4. The DCPC EDT signal cannot set the controller's end-of-data flag
742        directly because a write EOD must only occur after the FIFO has been
743        drained.
744 */
745 
ds_service_drive(UNIT * uptr)746 static t_stat ds_service_drive (UNIT *uptr)
747 {
748 t_stat result;
749 t_bool seek_completion;
750 FLIP_FLOP entry_srq = ds.srq;                           /* get the SRQ state on entry */
751 CNTLR_PHASE entry_phase = (CNTLR_PHASE) uptr->Phase;    /* get the operation phase on entry */
752 uint32 entry_status = uptr->Stat;                       /* get the drive status on entry */
753 
754 result = dl_service_drive (&mac_cntlr, uptr);           /* service the drive */
755 
756 if ((CNTLR_PHASE) uptr->Phase == data_phase)            /* is the drive in the data phase? */
757     switch ((CNTLR_OPCODE) uptr->Op) {                  /* dispatch the current operation */
758 
759         case Read:                                      /* read operations */
760         case Read_Full_Sector:
761         case Read_With_Offset:
762         case Read_Without_Verify:
763             if (mac_cntlr.length == 0 || ds.edt == SET) {   /* is the data phase complete? */
764                 mac_cntlr.eod = ds.edt;                     /* set EOD if DCPC is done */
765                 uptr->Phase = end_phase;                    /* set the end phase */
766                 uptr->wait = mac_cntlr.cmd_time;            /*   and schedule the controller */
767                 }
768 
769             else if (FIFO_FULL)                             /* is the FIFO already full? */
770                 dl_end_command (&mac_cntlr, data_overrun);  /* terminate the command with an overrun */
771 
772             else {
773                 fifo_load (buffer [mac_cntlr.index++]);     /* load the next word into the FIFO */
774                 mac_cntlr.length--;                         /* count it */
775                 ds.srq = SET;                               /* ask DCPC to pick it up */
776                 io_assert_SIR (&ds_dib);                    /*   and assert SRQ */
777                 uptr->wait = mac_cntlr.data_time;           /* schedule the next data transfer */
778                 }
779 
780             break;
781 
782 
783         case Write:                                     /* write operations */
784         case Write_Full_Sector:
785         case Initialize:
786             if (entry_phase == start_phase) {               /* is this the phase transition? */
787                 ds.srq = SET;                               /* start the DCPC transfer */
788                 io_assert_SIR (&ds_dib);                    /*   and assert SRQ */
789                 }
790 
791             else if (FIFO_EMPTY)                            /* is the FIFO empty? */
792                 dl_end_command (&mac_cntlr, data_overrun);  /* terminate the command with an underrun */
793 
794             else {
795                 buffer [mac_cntlr.index++] = fifo_unload ();    /* unload the next word from the FIFO */
796                 mac_cntlr.length--;                             /* count it */
797 
798                 if (ds.edt == SET && FIFO_EMPTY)                /* if DCPC is complete and the FIFO is empty */
799                     mac_cntlr.eod = SET;                        /*   then set the end-of-data flag */
800 
801                 if (mac_cntlr.length == 0 || mac_cntlr.eod == SET) {    /* is the data phase complete? */
802                     uptr->Phase = end_phase;                            /* set the end phase */
803                     uptr->wait = mac_cntlr.cmd_time;                    /*   and schedule the controller */
804                     }
805 
806                 else {
807                     if (ds.edt == CLEAR) {              /* if DCPC is still transferring */
808                         ds.srq = SET;                   /*   then request the next word */
809                         io_assert_SIR (&ds_dib);        /*     and assert SRQ */
810                         }
811 
812                     uptr->wait = mac_cntlr.data_time;   /* schedule the next data transfer */
813                     }
814                 }
815 
816             break;
817 
818 
819         default:                                        /* we were entered with an invalid state */
820             result = SCPE_IERR;                         /* return an internal (programming) error */
821             break;
822         }                                               /* end of data phase operation dispatch */
823 
824 
825 if (entry_srq != ds.srq)
826     tprintf (ds_dev, DEB_CMDS, "SRQ %s\n", ds.srq == SET ? "set" : "cleared");
827 
828 if (uptr->wait)                                         /* was service requested? */
829     activate_unit (uptr);                               /* schedule the next event */
830 
831 seek_completion = ~entry_status & uptr->Stat & DL_S2ATN;    /* seek is complete when Attention sets */
832 
833 if (mac_cntlr.state != cntlr_busy) {                            /* is the command complete? */
834     if (mac_cntlr.state == cntlr_wait && not seek_completion) { /* is it command but not seek completion? */
835         ds.flag_buffer = SET;                                   /* set the data flag */
836         io_assert_ENF (&ds_dib);                                /*   to interrupt the CPU */
837         }
838 
839     poll_interface ();                                  /* poll the interface for the next command */
840     poll_drives ();                                     /* poll the drives for Attention */
841     }
842 
843 
844 if (result == SCPE_IERR)                                    /* did an internal error occur? */
845     tprintf (ds_dev, DEB_RWSC, "Unit %d %s command %s phase service not handled\n",
846              uptr - ds_unit, dl_opcode_name (MAC, (CNTLR_OPCODE) uptr->Op),
847              dl_phase_name ((CNTLR_PHASE) uptr->Phase));
848 
849 else if (seek_completion)                                           /* if a seek has completed */
850     tprintf (ds_dev, DEB_RWSC, "Unit %d %s command completed\n",    /*   report the unit command */
851              uptr - ds_unit, dl_opcode_name (MAC, (CNTLR_OPCODE) uptr->Op));
852 
853 else if (mac_cntlr.state == cntlr_wait)                             /* if the controller has stopped */
854     tprintf (ds_dev, DEB_RWSC, "Unit %d %s command completed\n",    /*   report the controller command */
855              uptr - ds_unit, dl_opcode_name (MAC, mac_cntlr.opcode));
856 
857 return result;                                              /* return the result of the service */
858 }
859 
860 
861 /* Service the controller unit.
862 
863    The controller service routine is called to execute scheduled controller
864    commands that do not access drive units.  It is also called to obtain command
865    parameters from the interface and to return command result values to the
866    interface.
867 
868    Most controller commands are handled completely in the library's service
869    routine, so we call that first.  Commands that neither accept nor supply
870    parameters are complete when the library routine returns, so all we have to
871    do is set the interface flag if required.
872 
873    For parameter transfers in the data phase, the interface is responsible for
874    moving words between the sector buffer and the FIFO and setting the flag to
875    notify the CPU.
876 
877 
878    Implementation notes:
879 
880     1. In hardware, the Read With Offset command sets the data flag after the
881        offset parameter has been read and the head positioner has been moved by
882        the indicated amount.  The intent is to delay the DCPC start until the
883        drive is ready to supply data from the disc.
884 
885        In simulation, the flag is set as soon as the parameter is received.
886 */
887 
ds_service_controller(UNIT * uptr)888 static t_stat ds_service_controller (UNIT *uptr)
889 {
890 t_stat result;
891 const CNTLR_OPCODE opcode = (CNTLR_OPCODE) uptr->Op;
892 
893 result = dl_service_controller (&mac_cntlr, uptr);      /* service the controller */
894 
895 switch ((CNTLR_PHASE) uptr->Phase) {                    /* dispatch the current phase */
896 
897     case start_phase:                                   /* most controller operations */
898     case end_phase:                                     /*   start and end on the same phase */
899         switch (opcode) {                               /* dispatch the current operation */
900 
901             case Request_Status:
902             case Request_Sector_Address:
903             case Address_Record:
904             case Request_Syndrome:
905             case Load_TIO_Register:
906             case Request_Disc_Address:
907             case End:
908                 break;                                  /* complete the operation without setting the flag */
909 
910 
911             case Clear:
912             case Set_File_Mask:
913             case Wakeup:
914                 ds.flag_buffer = SET;                   /* complete the operation */
915                 io_assert_ENF (&ds_dib);                /*   and set the flag */
916                 break;
917 
918 
919             default:                                    /* we were entered with an invalid state */
920                 result = SCPE_IERR;                     /* return an internal (programming) error */
921                 break;
922             }                                           /* end of operation dispatch */
923         break;                                          /* end of start and end phase handlers */
924 
925 
926     case data_phase:
927         switch (opcode) {                               /* dispatch the current operation */
928 
929             case Seek:                                  /* operations that accept parameters */
930             case Verify:
931             case Address_Record:
932             case Read_With_Offset:
933             case Load_TIO_Register:
934                 buffer [mac_cntlr.index++] = fifo_unload ();    /* unload the next word from the FIFO */
935                 mac_cntlr.length--;                             /* count it */
936 
937                 if (mac_cntlr.length) {                 /* are there more words to transfer? */
938                     ds.flag_buffer = SET;               /* set the flag */
939                     io_assert_ENF (&ds_dib);            /*   to request the next one */
940                     }
941 
942                 else {                                  /* all parameters have been received */
943                     uptr->Phase = end_phase;            /* set the end phase */
944 
945                     if (opcode == Read_With_Offset) {   /* a Read With Offset command sets the flag */
946                         ds.flag_buffer = SET;           /*   to indicate that offsetting */
947                         io_assert_ENF (&ds_dib);        /*     is complete */
948                         }
949 
950                     start_command ();                   /* the command is now ready to execute */
951                     }
952                 break;
953 
954 
955             case Request_Status:                        /* operations that supply parameters */
956             case Request_Sector_Address:
957             case Request_Syndrome:
958             case Request_Disc_Address:
959                 if (mac_cntlr.length) {                         /* are there more words to return? */
960                     fifo_load (buffer [mac_cntlr.index++]);     /* load the next word into the FIFO */
961                     mac_cntlr.length--;                         /* count it */
962 
963                     ds.flag_buffer = SET;               /* set the data flag */
964                     io_assert_ENF (&ds_dib);            /*   to request pickup by the CPU */
965                     }
966 
967                 else {                                  /* all parameters have been sent */
968                     uptr->Phase = end_phase;            /* set the end phase */
969                     uptr->wait = mac_cntlr.cmd_time;    /* schedule the controller */
970                     activate_unit (uptr);               /*   to complete the command */
971                     }
972                 break;
973 
974 
975             default:                                    /* we were entered with an invalid state */
976                 result = SCPE_IERR;                     /* return an internal (programming) error */
977                 break;
978             }                                           /* end of operation dispatch */
979         break;                                          /* end of data phase handlers */
980     }                                                   /* end of phase dispatch */
981 
982 
983 if (result == SCPE_IERR)                                /* did an internal error occur? */
984     tprintf (ds_dev, DEB_RWSC, "Controller %s command %s phase service not handled\n",
985              dl_opcode_name (MAC, opcode), dl_phase_name ((CNTLR_PHASE) uptr->Phase));
986 
987 
988 if (mac_cntlr.state != cntlr_busy) {                    /* has the controller stopped? */
989     poll_interface ();                                  /* poll the interface for the next command */
990     poll_drives ();                                     /* poll the drives for Attention status */
991 
992     tprintf (ds_dev, DEB_RWSC, "Controller %s command completed\n",
993              dl_opcode_name (MAC, opcode));
994     }
995 
996 return result;                                          /* return the result of the service */
997 }
998 
999 
1000 /* Service the command wait timer unit.
1001 
1002    The command wait timer service routine is called if the command wait timer
1003    expires.  The library is called to reset the file mask and idle the
1004    controller.  Then the interface is polled for a command and the drives are
1005    polled for Attention status.
1006 */
1007 
ds_service_timer(UNIT * uptr)1008 static t_stat ds_service_timer (UNIT *uptr)
1009 {
1010 t_stat result;
1011 
1012 result = dl_service_timer (&mac_cntlr, uptr);           /* service the timer */
1013 
1014 poll_interface ();                                      /* poll the interface for the next command */
1015 poll_drives ();                                         /* poll the drives for Attention status */
1016 
1017 return result;                                          /* return the result of the service */
1018 }
1019 
1020 
1021 /* Reset the simulator.
1022 
1023    In hardware, the PON signal clears the Interface Selected flip-flop,
1024    disconnecting the interface from the disc controller.  In simulation, the
1025    interface always remains connected to the controller, so no special action is
1026    needed.
1027 
1028 
1029    Implementation notes:
1030 
1031     1. During a power-on reset, a pointer to the FIFO simulation register is
1032        saved to allow access to the "qptr" field during FIFO loading and
1033        unloading.  This enables SCP to view the FIFO as a circular queue, so
1034        that the bottom word of the FIFO is always displayed as FIFO[0],
1035        regardless of where it is in the actual FIFO array.
1036 
1037     2. SRQ is denied because neither IFIN nor IFOUT is asserted when the
1038        interface is not selected.
1039 */
1040 
ds_reset(DEVICE * dptr)1041 static t_stat ds_reset (DEVICE *dptr)
1042 {
1043 uint32 unit;
1044 REG    *rptr;
1045 
1046 if (sim_switches & SWMASK ('P')) {                      /* is this a power-on reset? */
1047     for (rptr = dptr->registers;                        /* find the FIFO register entry */
1048          rptr->loc != &ds.fifo && rptr->loc != NULL;    /*   in the register array */
1049          rptr++);
1050 
1051     if (rptr == NULL)                                   /* if it cannot be found, */
1052         return SCPE_IERR;                               /*   report a programming error */
1053 
1054     else {                                              /* otherwise */
1055         ds.fifo_reg = rptr;                             /*   save the pointer to the register */
1056         ds.fifo_reg->qptr = 0;                          /*     and reset the FIFO bottom index */
1057         ds.fifo_count = 0;                              /*       and clear the FIFO */
1058         }
1059 
1060     for (unit = 0; unit < dptr->numunits; unit++) {     /* loop through all of the units */
1061         sim_cancel (dptr->units + unit);                /* cancel activation */
1062         dptr->units [unit].Cyl = 0;                     /* reset the head position to cylinder 0 */
1063         dptr->units [unit].pos = 0;                     /* (irrelevant for the controller and timer) */
1064         }
1065     }
1066 
1067 ds.srq = CLEAR;                                         /* clear SRQ */
1068 
1069 return SCPE_OK;
1070 }
1071 
1072 
1073 /* Attach a drive unit.
1074 
1075    The specified file is attached to the indicated drive unit.  The library
1076    attach routine will load the heads.  This will set the First Status and
1077    Attention bits in the drive status, so we poll the drives to ensure that the
1078    CPU is notified that the drive is now online.
1079 
1080    If a new file is specified, the file is initialized to its capacity by
1081    writing a zero to the last byte in the file.
1082 
1083 
1084    Implementation notes:
1085 
1086     1. If we are called during a RESTORE command, the drive status will not be
1087        changed, so polling the drives will have no effect.
1088 
1089     2. The C standard says, "A binary stream need not meaningfully support fseek
1090        calls with a whence value of SEEK_END," so instead we determine the
1091        offset from the start of the file to the last byte and seek there.
1092 */
1093 
ds_attach(UNIT * uptr,char * cptr)1094 static t_stat ds_attach (UNIT *uptr, char *cptr)
1095 {
1096 t_stat      result;
1097 t_addr      offset;
1098 const uint8 zero = 0;
1099 
1100 result = dl_attach (&mac_cntlr, uptr, cptr);            /* attach the drive */
1101 
1102 if (result == SCPE_OK) {                                /* if the attach was successful */
1103     poll_drives ();                                     /*   then poll the drives to notify the CPU */
1104 
1105     if (sim_switches & SWMASK ('N')) {                  /* if this is a new disc image */
1106         offset = (t_addr)                               /*   then determine the offset of */
1107           (uptr->capac * sizeof (int16) - sizeof zero); /*     the last byte in a full-sized file */
1108 
1109         if (sim_fseek (uptr->fileref, offset, SEEK_SET) != 0    /* seek to the last byte */
1110           || fwrite (&zero, sizeof zero, 1, uptr->fileref) == 0 /*   and write a zero to fill */
1111           || fflush (uptr->fileref) != 0)                       /*     the file to its capacity */
1112             clearerr (uptr->fileref);                           /* clear and ignore any errors */
1113         }
1114     }
1115 
1116 return result;                                          /* return the result of the attach */
1117 }
1118 
1119 
1120 /* Detach a drive unit.
1121 
1122    The specified file is detached from the indicated drive unit.  The library
1123    detach routine will unload the heads.  This will set the Attention bit in the
1124    drive status, so we poll the drives to ensure that the CPU is notified that
1125    the drive is now offline.
1126 */
1127 
ds_detach(UNIT * uptr)1128 static t_stat ds_detach (UNIT *uptr)
1129 {
1130 t_stat result;
1131 
1132 result = dl_detach (&mac_cntlr, uptr);                  /* detach the drive */
1133 
1134 if (result == SCPE_OK)                                  /* was the detach successful? */
1135     poll_drives ();                                     /* poll the drives to notify the CPU */
1136 
1137 return result;
1138 }
1139 
1140 
1141 /* MAC disc bootstrap loaders (BMDL and 12992B).
1142 
1143    The Basic Moving-Head Disc Loader (BMDL) consists of two programs.  The
1144    program starting at address x7700 loads absolute paper tapes into memory.
1145    The program starting at address x7750 loads a disc-resident bootstrap from
1146    the MAC disc drive into memory.  The S register specifies the head to use.
1147 
1148    For a 2100/14/15/16 CPU, entering a LOAD DS or BOOT DS command loads the BMDL
1149    into memory and executes the disc portion starting at x7750.  The bootstrap
1150    reads 2047 words from cylinder 0 sector 0 of the specified head into memory
1151    starting at location 2011 octal.  Loader execution ends with one of the
1152    following instructions:
1153 
1154      * HLT 11B    - the disc read failed.
1155      * JSB 2055,I - the disc read completed.
1156 
1157    The HP 1000 uses the 12992B boot loader ROM to bootstrap the disc.  The head
1158    number is obtained from bits 2-0 of the existing S-register value when the
1159    loader is executed.  Bits 5-3 of the existing S-register value are also
1160    retained and are available to the boot extension program.  The loader reads
1161    6144 words from cylinder 0 sector 0 of the specified head into memory
1162    starting at location 2011 octal.  Loader execution ends with one of the
1163    following instructions:
1164 
1165      * HLT 30     - the drive is not ready..
1166      * JSB 2055,I - the disc read succeeded.
1167 
1168    The loader automatically retries the operations for all disc errors other
1169    than a drive fault.
1170 
1171 
1172    Implementation notes:
1173 
1174     1. After the BMDL has been loaded into memory, the paper tape portion may be
1175        executed manually by setting the P register to the starting address
1176        (x7700).
1177 
1178     2. For compatibility with the "cpu_copy_loader" routine, the BMDL device I/O
1179        instructions address select codes 10 and 11.
1180 */
1181 
1182 static const LOADER_ARRAY ds_loaders = {
1183     {                               /* HP 21xx Basic Moving-Head Disc Loader (BMDL-7905) */
1184       050,                          /*   loader starting index */
1185       076,                          /*   DMA index */
1186       034,                          /*   FWA index */
1187       { 0002401,                    /*   77700:  PTAPE CLA,RSS             Paper Tape start */
1188         0063722,                    /*   77701:        LDA 77722           */
1189         0107700,                    /*   77702:        CLC 0,C             */
1190         0002307,                    /*   77703:        CCE,INA,SZA,RSS     */
1191         0102077,                    /*   77704:        HLT 77              */
1192         0017735,                    /*   77705:        JSB 77735           */
1193         0007307,                    /*   77706:        CMB,CCE,INB,SZB,RSS */
1194         0027702,                    /*   77707:        JMP 77702           */
1195         0077733,                    /*   77710:        STB 77733           */
1196         0017735,                    /*   77711:        JSB 77735           */
1197         0017735,                    /*   77712:        JSB 77735           */
1198         0074000,                    /*   77713:        STB 0               */
1199         0077747,                    /*   77714:        STB 77747           */
1200         0047734,                    /*   77715:        ADB 77734           */
1201         0002140,                    /*   77716:        SEZ,CLE             */
1202         0102055,                    /*   77717:        HLT 55              */
1203         0017735,                    /*   77720:        JSB 77735           */
1204         0040001,                    /*   77721:        ADA 1               */
1205         0177747,                    /*   77722:        STB 77747,I         */
1206         0067747,                    /*   77723:        LDB 77747           */
1207         0006104,                    /*   77724:        CLE,INB             */
1208         0037733,                    /*   77725:        ISZ 77733           */
1209         0027714,                    /*   77726:        JMP 77714           */
1210         0017735,                    /*   77727:        JSB 77735           */
1211         0054000,                    /*   77730:        CPB 0               */
1212         0027701,                    /*   77731:        JMP 77701           */
1213         0102011,                    /*   77732:        HLT 11              */
1214         0000000,                    /*   77733:        NOP                 */
1215         0100100,                    /*   77734:        RRL 16              */
1216         0000000,                    /*   77735:        NOP                 */
1217         0006400,                    /*   77736:        CLB                 */
1218         0103710,                    /*   77737:        STC 10,C            */
1219         0102310,                    /*   77740:        SFS 10              */
1220         0027740,                    /*   77741:        JMP 77740           */
1221         0106410,                    /*   77742:        MIB 10              */
1222         0002240,                    /*   77743:        SEZ,CME             */
1223         0127735,                    /*   77744:        JMP 77735,I         */
1224         0005727,                    /*   77745:        BLF,BLF             */
1225         0027737,                    /*   77746:        JMP 77737           */
1226         0000000,                    /*   77747:        NOP                 */
1227         0067777,                    /*   77750: DISC   LDB 77777           */
1228         0174001,                    /*   77751:        STB 1,I             */
1229         0006004,                    /*   77752:        INB                 */
1230         0063732,                    /*   77753:        LDA 77732           */
1231         0170001,                    /*   77754:        STA 1,I             */
1232         0067776,                    /*   77755:        LDB 77776           */
1233         0106606,                    /*   77756:        OTB 6               */
1234         0106702,                    /*   77757:        CLC 2               */
1235         0102602,                    /*   77760:        OTA 2               */
1236         0102702,                    /*   77761:        STC 2               */
1237         0063751,                    /*   77762:        LDA 77751           */
1238         0102602,                    /*   77763:        OTA 2               */
1239         0102501,                    /*   77764:        LIA 1               */
1240         0001027,                    /*   77765:        ALS,ALF             */
1241         0013767,                    /*   77766:        AND 77767           */
1242         0000160,                    /*   77767:        CLE,ALS             */
1243         0106710,                    /*   77770:        CLC 10              */
1244         0103610,                    /*   77771:        OTA 10,C            */
1245         0103706,                    /*   77772:        STC 6,C             */
1246         0102310,                    /*   77773:        SFS 10              */
1247         0027773,                    /*   77774:        JMP 77773           */
1248         0117717,                    /*   77775:        JSB 77717,I         */
1249         0000010,                    /*   77776:        SLA                 */
1250         0002055 } },                /*   77777:        SEZ,SLA,INA,RSS     */
1251 
1252     {                               /* HP 1000 Loader ROM (12992B) */
1253       IBL_START,                    /*   loader starting index */
1254       IBL_DMA,                      /*   DMA index */
1255       IBL_FWA,                      /*   FWA index */
1256       { 0017727,                    /*   77700:  START JSB STAT      GET STATUS */
1257         0002021,                    /*   77701:        SSA,RSS       IS DRIVE READY ? */
1258         0027742,                    /*   77702:        JMP DMA       YES, SET UP DMA */
1259         0013714,                    /*   77703:        AND B20       NO, CHECK STATUS BITS */
1260         0002002,                    /*   77704:        SZA           IS DRIVE FAULTY OR HARD DOWN ? */
1261         0102030,                    /*   77705:        HLT 30B       YES, HALT 30B, "RUN" TO TRY AGAIN */
1262         0027700,                    /*   77706:        JMP START     NO, TRY AGAIN FOR DISC READY */
1263         0102011,                    /*   77707:  ADDR1 OCT 102011    */
1264         0102055,                    /*   77710:  ADDR2 OCT 102055    */
1265         0164000,                    /*   77711:  CNT   DEC -6144     */
1266         0000007,                    /*   77712:  D7    OCT 7         */
1267         0001400,                    /*   77713:  STCMD OCT 1400      */
1268         0000020,                    /*   77714:  B20   OCT 20        */
1269         0017400,                    /*   77715:  STMSK OCT 17400     */
1270         0000000,                    /*   77716:        NOP           */
1271         0000000,                    /*   77717:        NOP           */
1272         0000000,                    /*   77720:        NOP           */
1273         0000000,                    /*   77721:        NOP           */
1274         0000000,                    /*   77722:        NOP           */
1275         0000000,                    /*   77723:        NOP           */
1276         0000000,                    /*   77724:        NOP           */
1277         0000000,                    /*   77725:        NOP           */
1278         0000000,                    /*   77726:        NOP           */
1279         0000000,                    /*   77727:  STAT  NOP           STATUS CHECK SUBROUTINE */
1280         0107710,                    /*   77730:        CLC DC,C      SET STATUS COMMAND MODE */
1281         0063713,                    /*   77731:        LDA STCMD     GET STATUS COMMAND */
1282         0102610,                    /*   77732:        OTA DC        OUTPUT STATUS COMMAND */
1283         0102310,                    /*   77733:        SFS DC        WAIT FOR STATUS#1 WORD */
1284         0027733,                    /*   77734:        JMP *-1       */
1285         0107510,                    /*   77735:        LIB DC,C      B-REG = STATUS#1 WORD */
1286         0102310,                    /*   77736:        SFS DC        WAIT FOR STATUS#2 WORD */
1287         0027736,                    /*   77737:        JMP *-1       */
1288         0103510,                    /*   77740:        LIA DC,C      A-REG = STATUS#2 WORD */
1289         0127727,                    /*   77741:        JMP STAT,I    RETURN */
1290         0067776,                    /*   77742:  DMA   LDB DMACW     GET DMA CONTROL WORD */
1291         0106606,                    /*   77743:        OTB 6         OUTPUT DMA CONTROL WORD */
1292         0067707,                    /*   77744:        LDB ADDR1     GET MEMORY ADDRESS */
1293         0106702,                    /*   77745:        CLC 2         SET MEMORY ADDRESS INPUT MODE */
1294         0106602,                    /*   77746:        OTB 2         OUTPUT MEMORY ADDRESS TO DMA */
1295         0102702,                    /*   77747:        STC 2         SET WORD COUNT INPUT MODE */
1296         0067711,                    /*   77750:        LDB CNT       GET WORD COUNT */
1297         0106602,                    /*   77751:        OTB 2         OUTPUT WORD COUNT TO DMA */
1298         0106710,                    /*   77752:  CLDLD CLC DC        SET COMMAND INPUT MODE */
1299         0102501,                    /*   77753:        LIA 1         LOAD SWITCH */
1300         0106501,                    /*   77754:        LIB 1         REGISTER SETTINGS */
1301         0013712,                    /*   77755:        AND D7        ISOLATE HEAD NUMBER */
1302         0005750,                    /*   77756:        BLF,CLE,SLB   BIT 12=0? */
1303         0027762,                    /*   77757:        JMP *+3       NO,MANUAL BOOT */
1304         0002002,                    /*   77760:        SZA           YES,RPL BOOT. HEAD#=0? */
1305         0001000,                    /*   77761:        ALS           NO,HEAD#1, MAKE HEAD#=2 */
1306         0001720,                    /*   77762:        ALF,ALS       FORM COLD LOAD */
1307         0001000,                    /*   77763:        ALS           COMMAND WORD */
1308         0103706,                    /*   77764:        STC 6,C       ACTIVATE DMA */
1309         0103610,                    /*   77765:        OTA DC,C      OUTPUT COLD LOAD COMMAND */
1310         0102310,                    /*   77766:        SFS DC        IS COLD LOAD COMPLETED ? */
1311         0027766,                    /*   77767:        JMP *-1       NO, WAIT */
1312         0017727,                    /*   77770:        JSB STAT      YES, GET STATUS */
1313         0060001,                    /*   77771:        LDA 1         */
1314         0013715,                    /*   77772:        AND STMSK     A-REG = STATUS BITS OF STATUS#1 WD */
1315         0002002,                    /*   77773:        SZA           IS TRANSFER OK ? */
1316         0027700,                    /*   77774:        JMP START     NO,TRY AGAIN */
1317         0117710,                    /*   77775:  EXIT  JSB ADDR2,I   YES, EXEC LOADED PROGRAM @ 2055B */
1318         0000010,                    /*   77776:  DMACW ABS DC        */
1319         0170100 } }                 /*   77777:        ABS -START    */
1320     };
1321 
1322 
1323 /* Device boot routine.
1324 
1325    This routine is called directly by the BOOT DS and LOAD DS commands to copy
1326    the device bootstrap into the upper 64 words of the logical address space.
1327    It is also called indirectly by a BOOT CPU or LOAD CPU command when the
1328    specified HP 1000 loader ROM socket contains a 12992B ROM.
1329 
1330    When called in response to a BOOT DS or LOAD DS command, the "unitno"
1331    parameter indicates the unit number specified in the BOOT command or is zero
1332    for the LOAD command, and "dptr" points at the DS device structure.  The
1333    bootstrap supports loading only from unit 0, and the command will be rejected
1334    if another unit is specified (e.g., BOOT DS1).  Otherwise, depending on the
1335    current CPU model, the BMDL or 12992B loader ROM will be copied into memory
1336    and configured for the DS select code.  If the CPU is a 1000, the S register
1337    will be set as it would be by the front-panel microcode.
1338 
1339    When called for a BOOT/LOAD CPU command, the "unitno" parameter indicates the
1340    select code to be used for configuration, and "dptr" will be NULL.  As above,
1341    the BMDL or 12992B loader ROM will be copied into memory and configured for
1342    the specified select code.  The S register is assumed to be set correctly on
1343    entry and is not modified.
1344 
1345    In either case, if the CPU is a 21xx model, the paper tape portion of the
1346    BMDL will be automatically configured for the select code of the paper tape
1347    reader.
1348 
1349    For the 12992B boot loader ROM for the HP 1000, the S register is set as
1350    follows:
1351 
1352       15  14  13  12  11  10   9   8   7   6   5   4   3   2   1   0
1353      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1354      | ROM # | 0   1 |      select code      | reserved  | 0 | head  |
1355      +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1356 
1357    Bit 12 must be 1 for a manual boot.  Bits 5-3 are nominally zero but are
1358    reserved for the target operating system.  For example, RTE uses bit 5 to
1359    indicate whether a standard (0) or reconfiguration (1) boot is desired.
1360 
1361 
1362    Implementation notes:
1363 
1364     1. In hardware, the BMDL was hand-configured for the disc and paper tape
1365        reader select codes when it was installed on a given system.  Under
1366        simulation, the LOAD and BOOT commands automatically configure the BMDL
1367        to the current select codes of the PTR and DS devices.
1368 
1369     2. The HP 1000 Loader ROMs manual indicates that bits 2-0 select the head to
1370        use, implying that heads 0-7 are valid.  However, Table 5 has entries
1371        only for heads 0-3, and the boot loader code will malfunction if heads
1372        4-7 are specified.  The code masks the head number to three bits but
1373        forms the Cold Load Read command by shifting the head number six bits to
1374        the left.  As the head field in the command is only two bits wide,
1375        specifying heads 4-7 will result in bit 2 being shifted into the opcode
1376        field, resulting in a Recalibrate command.
1377 */
1378 
ds_boot(int32 unitno,DEVICE * dptr)1379 static t_stat ds_boot (int32 unitno, DEVICE *dptr)
1380 {
1381 static const HP_WORD ds_preserved   = 0000073u;             /* S-register bits 5-3 and 1-0 are preserved */
1382 static const HP_WORD ds_manual_boot = 0010000u;             /* S-register bit 12 set for a manual boot */
1383 uint32 start;
1384 
1385 if (dptr == NULL)                                           /* if we are being called for a BOOT/LOAD CPU */
1386     start = cpu_copy_loader (ds_loaders, unitno,            /*   then copy the boot loader to memory */
1387                              IBL_S_NOCLEAR, IBL_S_NOSET);   /*     but do not alter the S register */
1388 
1389 else if (unitno != 0)                                       /* otherwise a BOOT DS for a non-zero unit */
1390     return SCPE_NOFNC;                                      /*   is rejected as unsupported */
1391 
1392 else                                                            /* otherwise this is a BOOT/LOAD DS */
1393     start = cpu_copy_loader (ds_loaders, ds_dib.select_code,    /*   so copy the boot loader to memory */
1394                              ds_preserved, ds_manual_boot);     /*     and configure the S register if 1000 CPU */
1395 
1396 if (start == 0)                                         /* if the copy failed */
1397     return SCPE_NOFNC;                                  /*   then reject the command */
1398 else                                                    /* otherwise */
1399     return SCPE_OK;                                     /*   the boot loader was successfully copied */
1400 }
1401 
1402 
1403 
1404 /* MAC disc global SCP routines */
1405 
1406 
1407 /* Load or unload the drive heads.
1408 
1409    The SCP command SET DSn UNLOADED simulates setting the hardware RUN/STOP
1410    switch to STOP.  The heads are unloaded, and the drive is spun down.
1411 
1412    The SET DSn LOADED command simulates setting the switch to RUN.  The drive is
1413    spun up, and the heads are loaded.
1414 
1415    The library handles command validation and setting the appropriate drive unit
1416    status.
1417 */
1418 
ds_load_unload(UNIT * uptr,int32 value,char * cptr,void * desc)1419 static t_stat ds_load_unload (UNIT *uptr, int32 value, char *cptr, void *desc)
1420 {
1421 const t_bool load = (value != UNIT_UNLOAD);             /* true if the heads are loading */
1422 
1423 return dl_load_unload (&mac_cntlr, uptr, load);         /* load or unload the heads */
1424 }
1425 
1426 
1427 
1428 /* MAC disc local utility routines */
1429 
1430 
1431 /* Start a command.
1432 
1433    The previously prepared command is executed by calling the corresponding
1434    library routine.  On entry, the controller's opcode field contains the
1435    command to start, and the buffer contains the command word in element 0 and
1436    the parameters required by the command, if any, beginning in element 1.
1437 
1438    If the command started, the returned pointer will point at the unit to
1439    activate (if that unit's "wait" field is non-zero).  If the returned pointer
1440    is NULL, the command failed to start, and the controller status has been set
1441    to indicate the reason.  The interface flag is set to notify the CPU of the
1442    failure.
1443 
1444 
1445    Implementation notes:
1446 
1447     1. If a command that accesses the drive is attempted on a drive currently
1448        seeking, the returned pointer will be valid, but the unit's "wait" time
1449        will be zero.  The unit must not be activated (as it already is active).
1450        When the seek completes, the command will be executed automatically.
1451 
1452        If a Seek or Cold Load Read command is attempted on a drive currently
1453        seeking, seek completion will occur normally, but Seek Check status will
1454        be set.
1455 
1456     2. For debug printouts, we want to print the name of the command (Seek or
1457        Recalibrate) in progress when a new command is started.  However, when
1458        the library routine returns, the unit operation and controller opcode
1459        have been changed to reflect the new command.  Therefore, we must record
1460        the operation in progress before calling the library.
1461 
1462        The problem is in determining which unit's operation code to record.  We
1463        cannot blindly use the unit field from the new command, as recorded in
1464        the controller, as preparation has ensured only that the target unit
1465        number is legal but not necessarily valid.  Therefore, we must validate
1466        the unit number before accessing the unit's operation code.
1467 
1468        If the unit number is invalid, the command will not start, but the
1469        compiler does not know this.  Therefore, we must ensure that the saved
1470        operation code is initialized, or a "variable used uninitialized" warning
1471        will occur.
1472 */
1473 
start_command(void)1474 static void start_command (void)
1475 {
1476 int32 unit, time;
1477 UNIT *uptr;
1478 CNTLR_OPCODE drive_command;
1479 
1480 unit = GET_S1UNIT (mac_cntlr.spd_unit);                 /* get the (prepared) unit from the command */
1481 
1482 if (unit <= DL_MAXDRIVE)                                /* is the unit number valid? */
1483     drive_command = (CNTLR_OPCODE) ds_unit [unit].Op;   /* get the opcode from the unit that will be used */
1484 else                                                    /* the unit is invalid, so the command will not start */
1485     drive_command = End;                                /*   but the compiler doesn't know this! */
1486 
1487 uptr = dl_start_command (&mac_cntlr, ds_unit, DL_MAXDRIVE); /* ask the controller to start the command */
1488 
1489 if (uptr) {                                             /* did the command start? */
1490     time = uptr->wait;                                  /* save the activation time */
1491 
1492     if (time)                                           /* was the unit scheduled? */
1493         activate_unit (uptr);                           /* activate it (and clear the "wait" field) */
1494 
1495     if (time == 0)                                  /* was the unit busy? */
1496         tprintf (ds_dev, DEB_RWSC, "Unit %d %s in progress\n",
1497                  uptr - ds_unit, dl_opcode_name (MAC, drive_command));
1498 
1499     if (uptr - ds_unit > DL_MAXDRIVE)
1500         tprintf (ds_dev, DEB_RWSC, "Controller %s command initiated\n",
1501                  dl_opcode_name (MAC, mac_cntlr.opcode));
1502     else
1503         tprintf (ds_dev, DEB_RWSC, "Unit %d position %" T_ADDR_FMT "d %s command initiated\n",
1504                  uptr - ds_unit, uptr->pos, dl_opcode_name (MAC, mac_cntlr.opcode));
1505     }
1506 
1507 else {                                                  /* the command failed to start */
1508     ds.flag_buffer = SET;                               /*   so set the data flag */
1509     io_assert_ENF (&ds_dib);                            /*   then assert it to notify the CPU */
1510     }
1511 
1512 return;
1513 }
1514 
1515 
1516 /* Poll the interface for a new command.
1517 
1518    If a new command is available, and the controller is not busy, prepare the
1519    command for execution.  If preparation succeeded, and the command needs
1520    parameters before executing, set the flag to request the first one from the
1521    CPU.  If no parameters are needed, the command is ready to execute.
1522 
1523    If preparation failed, set the flag to notify the CPU.  The controller
1524    status contains the reason for the failure.
1525 */
1526 
poll_interface(void)1527 static void poll_interface (void)
1528 {
1529 if (ds.cmrdy == SET && mac_cntlr.state != cntlr_busy) {     /* are the interface and controller ready? */
1530     buffer [0] = fifo_unload ();                            /* unload the command into the buffer */
1531 
1532     if (dl_prepare_command (&mac_cntlr, ds_unit, DL_MAXDRIVE))  /* prepare the command; did it succeed? */
1533         if (mac_cntlr.length) {                                 /* does the command require parameters? */
1534             ds.flag_buffer = SET;                               /* set the data flag */
1535             io_assert_ENF (&ds_dib);                            /*   then assert it to request the first parameter */
1536             }
1537 
1538         else                                            /* otherwise if not waiting for parameters */
1539             start_command ();                           /*   then start the command immediately */
1540 
1541     else {                                              /* otherwise command preparation failed */
1542         ds.flag_buffer = SET;                           /*   so set the data flag */
1543         io_assert_ENF (&ds_dib);                        /*     then and assert it to request an interrupt */
1544         }
1545 
1546     ds.cmrdy = CLEAR;                                   /* flush the command from the interface */
1547     }
1548 
1549 return;
1550 }
1551 
1552 
1553 /* Poll the drives for attention requests.
1554 
1555    If the controller is idle and interrupts are allowed, the drives are polled
1556    to see if any drive is requesting attention.  If one is found, the controller
1557    resets that drive's Attention status, saves the drive's unit number, sets
1558    Drive Attention status, and waits for a command from the CPU.  The interface
1559    sets the flag to notify the CPU.
1560 */
1561 
poll_drives(void)1562 static void poll_drives (void)
1563 {
1564 if (mac_cntlr.state == cntlr_idle && ds.control == SET) {   /* is the controller idle and interrupts are allowed? */
1565     tprintf (ds_dev, DEB_RWSC, "Controller polled drives for attention\n");
1566 
1567     if (dl_poll_drives (&mac_cntlr, ds_unit, DL_MAXDRIVE)) {    /* poll the drives; was Attention seen? */
1568         ds.flag_buffer = SET;                                   /* set the data flag */
1569 
1570         tprintf (ds_dev, DEB_RWSC, "Unit %u requested attention\n",
1571                  mac_cntlr.poll_unit);
1572 
1573         io_assert_ENF (&ds_dib);                        /* assert it to request an interrupt */
1574         }
1575     }
1576 
1577 return;
1578 }
1579 
1580 
1581 /* Load a word into the FIFO.
1582 
1583    A word is loaded into the next available location in the FIFO, and the FIFO
1584    occupancy count is incremented.  If the FIFO is full on entry, the load is
1585    ignored.
1586 
1587 
1588    Implementation notes:
1589 
1590     1. The FIFO is implemented as circular queue to take advantage of REG_CIRC
1591        EXAMINE semantics.  REG->qptr is the index of the first word currently in
1592        the FIFO.  By specifying REG_CIRC, examining FIFO[0-n] will always
1593        display the words in load order, regardless of the actual array index of
1594        the start of the list.  The number of words currently present in the FIFO
1595        is kept in fifo_count (0 = empty, 1-16 = number of words available).
1596 
1597        If fifo_count < FIFO_SIZE, (REG->qptr + fifo_count) mod FIFO_SIZE is the
1598        index of the new word location.  Loading stores the word there and then
1599        increments fifo_count.
1600 
1601     2. Because the load and unload routines need access to qptr in the REG
1602        structure for the FIFO array, a pointer to the REG is stored in the
1603        fifo_reg variable during device reset.
1604 */
1605 
fifo_load(uint16 data)1606 static void fifo_load (uint16 data)
1607 {
1608 uint32 index;
1609 
1610 if (FIFO_FULL) {                                            /* is the FIFO already full? */
1611     tprintf (ds_dev, DEB_BUF, "Attempted load to full FIFO, data %06o\n", data);
1612 
1613     return;                                                 /* return with the load ignored */
1614     }
1615 
1616 index = (ds.fifo_reg->qptr + ds.fifo_count) % FIFO_SIZE;    /* calculate the index of the next available location */
1617 
1618 ds.fifo [index] = data;                                     /* store the word in the FIFO */
1619 ds.fifo_count = ds.fifo_count + 1;                          /* increment the count of words stored */
1620 
1621 tprintf (ds_dev, DEB_BUF, "Data %06o loaded into FIFO [%d]\n",
1622          data, ds.fifo_count);
1623 
1624 return;
1625 }
1626 
1627 
1628 /* Unload a word from the FIFO.
1629 
1630    A word is unloaded from the first location in the FIFO, and the FIFO
1631    occupancy count is decremented.  If the FIFO is empty on entry, the unload
1632    returns dummy data.
1633 
1634 
1635    Implementation notes:
1636 
1637     1. If fifo_count > 0, REG->qptr is the index of the word to remove.  Removal
1638        gets the word and then increments qptr (mod FIFO_SIZE) and decrements
1639        fifo_count.
1640 */
1641 
fifo_unload(void)1642 static uint16 fifo_unload (void)
1643 {
1644 uint16 data;
1645 
1646 if (FIFO_EMPTY) {                                           /* is the FIFO already empty? */
1647     tprintf (ds_dev, DEB_BUF, "Attempted unload from empty FIFO\n");
1648     return 0;                                               /* return with no data */
1649     }
1650 
1651 data = ds.fifo [ds.fifo_reg->qptr];                         /* get the word from the FIFO */
1652 
1653 ds.fifo_reg->qptr = (ds.fifo_reg->qptr + 1) % FIFO_SIZE;    /* update the FIFO queue pointer */
1654 ds.fifo_count = ds.fifo_count - 1;                          /* decrement the count of words stored */
1655 
1656 tprintf (ds_dev, DEB_BUF, "Data %06o unloaded from FIFO [%d]\n",
1657          data, ds.fifo_count);
1658 
1659 return data;
1660 }
1661 
1662 
1663 /* Clear the FIFO.
1664 
1665    The FIFO is cleared by setting the occupancy counter to zero.
1666 */
1667 
fifo_clear(void)1668 static void fifo_clear (void)
1669 {
1670 ds.fifo_count = 0;                                      /* clear the FIFO */
1671 
1672 tprintf (ds_dev, DEB_BUF, "FIFO cleared\n");
1673 
1674 return;
1675 }
1676 
1677 
1678 /* Activate the unit.
1679 
1680    The specified unit is activated using the unit's "wait" time.  If debugging
1681    is enabled, the activation is logged to the debug file.
1682 */
1683 
activate_unit(UNIT * uptr)1684 static t_stat activate_unit (UNIT *uptr)
1685 {
1686 t_stat result;
1687 
1688 if (uptr == &ds_cntlr)
1689     tprintf (ds_dev, TRACE_SERV, "Controller delay %d service scheduled\n",
1690              uptr->wait);
1691 else
1692     tprintf (ds_dev, TRACE_SERV, "Unit %d delay %d service scheduled\n",
1693              uptr - ds_unit, uptr->wait);
1694 
1695 result = sim_activate (uptr, uptr->wait);               /* activate the unit */
1696 uptr->wait = 0;                                         /* reset the activation time */
1697 
1698 return result;                                          /* return the activation status */
1699 }
1700