blob: fb7d0eb23b834fc67ae355eaa20acb08bac06f6c [file] [log] [blame] [raw]
Mark Pizzolato45246a32012-03-21 06:14:01 -07001/* hp2100_ds.c: HP 13037D/13175D disc controller/interface simulator
Bob Supnike2ba6722004-07-10 06:13:00 -07002
Mark Pizzolato45246a32012-03-21 06:14:01 -07003 Copyright (c) 2004-2012, Robert M. Supnik
Mark Pizzolato486427c2018-06-03 14:38:38 -07004 Copyright (c) 2012-2018 J. David Bryan
Bob Supnike2ba6722004-07-10 06:13:00 -07005
6 Permission is hereby granted, free of charge, to any person obtaining a
7 copy of this software and associated documentation files (the "Software"),
8 to deal in the Software without restriction, including without limitation
9 the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 and/or sell copies of the Software, and to permit persons to whom the
11 Software is furnished to do so, subject to the following conditions:
12
13 The above copyright notice and this permission notice shall be included in
14 all copies or substantial portions of the Software.
15
16 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
Mark Pizzolato45246a32012-03-21 06:14:01 -070019 THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
Bob Supnike2ba6722004-07-10 06:13:00 -070020 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
Mark Pizzolato45246a32012-03-21 06:14:01 -070023 Except as contained in this notice, the names of the authors shall not be
Bob Supnikb7c1eae2005-09-09 18:09:00 -070024 used in advertising or otherwise to promote the sale, use or other dealings
Mark Pizzolato45246a32012-03-21 06:14:01 -070025 in this Software without prior written authorization from the authors.
Bob Supnike2ba6722004-07-10 06:13:00 -070026
Mark Pizzolato45246a32012-03-21 06:14:01 -070027 DS 13037D/13175D disc controller/interface
Bob Supnikec60bbf2005-05-03 04:10:00 -070028
Mark Pizzolato486427c2018-06-03 14:38:38 -070029 07-May-18 JDB Removed "dl_clear_controller" status return
30 27-Feb-18 JDB Added the BMDL
31 21-Feb-18 JDB ATTACH -N now creates a full-size disc image
Mark Pizzolatoa6552b82017-09-06 22:16:14 -070032 11-Jul-17 JDB Renamed "ibl_copy" to "cpu_ibl"
33 15-Mar-17 JDB Trace flags are now global
34 Changed DEBUG_PRI calls to tprintfs
35 10-Mar-17 JDB Added IOBUS to the debug table
36 09-Mar-17 JDB Deprecated LOCKED/WRITEENABLED for PROTECT/UNPROTECT
Mark Pizzolato5531ccb2016-05-15 15:25:33 -070037 13-May-16 JDB Modified for revised SCP API function parameter types
Mark Pizzolato53b68092016-03-07 20:42:19 -080038 04-Mar-16 JDB Name changed to "hp2100_disclib" until HP 3000 integration
Mark Pizzolatoecbb20f2015-01-08 03:39:22 -080039 30-Dec-14 JDB Added S-register parameters to ibl_copy
40 24-Dec-14 JDB Use T_ADDR_FMT with t_addr values for 64-bit compatibility
Mark Pizzolatoa262dd92013-03-19 01:11:22 -070041 18-Mar-13 JDB Fixed poll_drives definition to match declaration
Mark Pizzolatoef147d22012-10-24 12:57:37 -070042 24-Oct-12 JDB Changed CNTLR_OPCODE to title case to avoid name clash
Mark Pizzolato40deb202012-04-04 12:31:43 -070043 29-Mar-12 JDB Rewritten to use the MAC/ICD disc controller library
Mark Pizzolato45246a32012-03-21 06:14:01 -070044 ioIOO now notifies controller service of parameter output
45 14-Feb-12 JDB Corrected SRQ generation and FIFO under/overrun detection
46 Corrected Clear command to conform to the hardware
47 Fixed Request Status to return Unit Unavailable if illegal
48 Seek and Cold Load Read now Seek Check if seek in progress
49 Remodeled command wait for seek completion
50 10-Feb-12 JDB Deprecated DEVNO in favor of SC
Mark Pizzolatofffad7c2012-03-19 16:05:24 -070051 21-Jun-11 JDB Corrected status returns for disabled drive, auto-seek
52 beyond drive limits, Request Sector Address and Wakeup
53 with invalid or offline unit
54 Address verification reenabled if auto-seek during
55 Read Without Verify
56 28-Mar-11 JDB Tidied up signal handling
57 26-Oct-10 JDB Changed I/O signal handler for revised signal model
Bob Supnik9c4779c2009-02-08 09:06:00 -080058 26-Jun-08 JDB Rewrote device I/O to model backplane signals
Bob Supnik59aa4a72008-06-24 14:21:00 -070059 31-Dec-07 JDB Corrected and verified ioCRS action
60 20-Dec-07 JDB Corrected DPTR register definition from FLDATA to DRDATA
61 28-Dec-06 JDB Added ioCRS state to I/O decoders
Bob Supnik53d02f72007-02-03 14:59:00 -080062 03-Aug-06 JDB Fixed REQUEST STATUS command to clear status-1
63 Removed redundant attached test in "ds_detach"
Bob Supnikb7c1eae2005-09-09 18:09:00 -070064 18-Mar-05 RMS Added attached test to detach routine
65 01-Mar-05 JDB Added SET UNLOAD/LOAD
Bob Supnik9c4779c2009-02-08 09:06:00 -080066
Mark Pizzolato45246a32012-03-21 06:14:01 -070067 References:
Bob Supnik9c4779c2009-02-08 09:06:00 -080068 - 13037 Disc Controller Technical Information Package (13037-90902, Aug-1980)
Mark Pizzolato45246a32012-03-21 06:14:01 -070069 - 7925D Disc Drive Service Manual (07925-90913, Apr-1984)
70 - HP 12992 Loader ROMs Installation Manual (12992-90001, Apr-1986)
71 - DVR32 RTE Moving Head Driver source (92084-18711, Revision 5000)
Bob Supnik9c4779c2009-02-08 09:06:00 -080072
Bob Supnike2ba6722004-07-10 06:13:00 -070073
Mark Pizzolato45246a32012-03-21 06:14:01 -070074 The 13037D multiple-access (MAC) disc controller supports from one to eight
75 HP 7905 (15 MB), 7906 (20MB), 7920 (50 MB), and 7925 (120 MB) disc drives
76 accessed by one to eight CPUs. The controller hardware consists of a 16-bit
Mark Pizzolato40deb202012-04-04 12:31:43 -070077 microprogrammed processor constructed from 74S181 bit slices operating at 5
78 MHz, a device controller providing the interconnections to the drives and CPU
79 interfaces, and an error correction controller that enables the correction of
80 up to 32-bit error bursts. 1024 words of 24-bit firmware are stored in ROM.
Bob Supnike2ba6722004-07-10 06:13:00 -070081
Mark Pizzolato40deb202012-04-04 12:31:43 -070082 The 13175D disc interface is used to connect the HP 1000 CPU to the 13037
83 device controller. In a multiple-CPU system, one interface is strapped to
84 reset the controller when the CPU's front panel PRESET button is pressed.
Bob Supnike2ba6722004-07-10 06:13:00 -070085
Mark Pizzolato45246a32012-03-21 06:14:01 -070086 This module simulates a 13037D connected to a single 13175D interface. From
87 one to eight drives may be connected, and drive types may be freely
88 intermixed. A unit that is enabled but not attached appears to be a
89 connected drive that does not have a disc pack in place. A unit that is
90 disabled appears to be disconnected.
Bob Supnik9b5c8c92005-01-09 13:55:00 -080091
Mark Pizzolato45246a32012-03-21 06:14:01 -070092 This simulator is an adaptation of the code originally written by Bob Supnik.
93 The functions of the controller have been separated from the functions of the
94 interface, with the former placed into a separate disc controller library.
95 This allows the library to support other CPU interfaces, such as the 12821A
96 HP-IB disc interface, that use substantially different communication
97 protocols. The library functions implement the controller command set for
98 the drive units. The interface functions handle the transfer of commands and
99 data to and from the CPU.
Bob Supnike2ba6722004-07-10 06:13:00 -0700100
Mark Pizzolato45246a32012-03-21 06:14:01 -0700101 In hardware, the controller runs continuously in one of three states: in the
102 Poll Loop (idle state), in the Command Wait Loop (wait state), or in command
103 execution (busy state). In simulation, the controller is run only when a
104 command is executing or when a transition into or out of the two loops might
105 occur. Internally, the controller handles these transitions:
106
107 - when a command other than End terminates (busy => wait)
108 - when the End command terminates (busy => idle)
109 - when a command timeout occurs (wait => idle)
110 - when a parameter timeout occurs (busy => idle)
111 - when a seek completes (if idle and interrupts are enabled, idle => wait)
112
113 The interface must call the controller library to handle these transitions:
114
115 - when a command is received from the CPU (idle or wait => busy)
116 - when interrupts are enabled (if idle and drive Attention, idle => wait)
117
118 In addition, each transition to the wait state must check for a pending
119 command, and each transition to the idle state must check for both a pending
120 command and a drive with Attention status asserted.
121
122
123 Implementation notes:
124
125 1. Although the 13175D has a 16-word FIFO, the "full" level is set at 5
126 entries in hardware to avoid a long DCPC preemption time at the start of
127 a disc write as the FIFO fills.
Bob Supnike2ba6722004-07-10 06:13:00 -0700128*/
129
Mark Pizzolato45246a32012-03-21 06:14:01 -0700130
131
Bob Supnik9c4779c2009-02-08 09:06:00 -0800132#include "hp2100_defs.h"
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700133#include "hp2100_cpu.h"
Mark Pizzolato53b68092016-03-07 20:42:19 -0800134#include "hp2100_disclib.h"
Bob Supnike2ba6722004-07-10 06:13:00 -0700135
Bob Supnike2ba6722004-07-10 06:13:00 -0700136
Bob Supnike2ba6722004-07-10 06:13:00 -0700137
Mark Pizzolato45246a32012-03-21 06:14:01 -0700138/* Program constants */
Bob Supnike2ba6722004-07-10 06:13:00 -0700139
Mark Pizzolato45246a32012-03-21 06:14:01 -0700140#define DS_DRIVES (DL_MAXDRIVE + 1) /* number of disc drive units */
141#define DS_UNITS (DS_DRIVES + DL_AUXUNITS) /* total number of units */
Bob Supnike2ba6722004-07-10 06:13:00 -0700142
Mark Pizzolato45246a32012-03-21 06:14:01 -0700143#define ds_cntlr ds_unit [DL_MAXDRIVE + 1] /* controller unit alias */
Bob Supnike2ba6722004-07-10 06:13:00 -0700144
Mark Pizzolato45246a32012-03-21 06:14:01 -0700145#define FIFO_SIZE 16 /* FIFO depth */
Bob Supnike2ba6722004-07-10 06:13:00 -0700146
Mark Pizzolato45246a32012-03-21 06:14:01 -0700147#define FIFO_EMPTY (ds.fifo_count == 0) /* FIFO empty test */
148#define FIFO_STOP (ds.fifo_count >= 5) /* FIFO stop filling test */
149#define FIFO_FULL (ds.fifo_count == FIFO_SIZE) /* FIFO full test */
Bob Supnike2ba6722004-07-10 06:13:00 -0700150
Mark Pizzolato40deb202012-04-04 12:31:43 -0700151#define PRESET_ENABLE TRUE /* Preset Jumper (W4) is enabled */
Bob Supnike2ba6722004-07-10 06:13:00 -0700152
Bob Supnike2ba6722004-07-10 06:13:00 -0700153
Mark Pizzolato45246a32012-03-21 06:14:01 -0700154/* Per-card state variables */
Bob Supnike2ba6722004-07-10 06:13:00 -0700155
Mark Pizzolato45246a32012-03-21 06:14:01 -0700156typedef struct {
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700157 FLIP_FLOP control; /* control flip-flop */
158 FLIP_FLOP flag; /* flag flip-flop */
159 FLIP_FLOP flagbuf; /* flag buffer flip-flop */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700160 FLIP_FLOP srq; /* SRQ flip-flop */
161 FLIP_FLOP edt; /* EDT flip-flop */
162 FLIP_FLOP cmfol; /* command follows flip-flop */
163 FLIP_FLOP cmrdy; /* command ready flip-flop */
164 uint16 fifo [FIFO_SIZE]; /* FIFO buffer */
165 uint32 fifo_count; /* FIFO occupancy counter */
166 REG *fifo_reg; /* FIFO register pointer */
167 } CARD_STATE;
Bob Supnike2ba6722004-07-10 06:13:00 -0700168
Bob Supnike2ba6722004-07-10 06:13:00 -0700169
Mark Pizzolato45246a32012-03-21 06:14:01 -0700170/* MAC disc state variables */
Bob Supnike2ba6722004-07-10 06:13:00 -0700171
Mark Pizzolato45246a32012-03-21 06:14:01 -0700172static UNIT ds_unit [DS_UNITS]; /* unit array */
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700173
Mark Pizzolato45246a32012-03-21 06:14:01 -0700174static CARD_STATE ds; /* card state */
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700175
Mark Pizzolato45246a32012-03-21 06:14:01 -0700176static uint16 buffer [DL_BUFSIZE]; /* command/status/sector buffer */
177
178static CNTLR_VARS mac_cntlr = /* MAC controller */
179 { CNTLR_INIT (MAC, buffer, &ds_cntlr) };
180
181
182
183/* MAC disc global VM routines */
184
185IOHANDLER ds_io;
186t_stat ds_service_drive (UNIT *uptr);
187t_stat ds_service_controller (UNIT *uptr);
188t_stat ds_service_timer (UNIT *uptr);
189t_stat ds_reset (DEVICE *dptr);
Mark Pizzolato5531ccb2016-05-15 15:25:33 -0700190t_stat ds_attach (UNIT *uptr, CONST char *cptr);
Mark Pizzolato45246a32012-03-21 06:14:01 -0700191t_stat ds_detach (UNIT *uptr);
192t_stat ds_boot (int32 unitno, DEVICE *dptr);
193
194/* MAC disc global SCP routines */
195
Mark Pizzolato5531ccb2016-05-15 15:25:33 -0700196t_stat ds_load_unload (UNIT *uptr, int32 value, CONST char *cptr, void *desc);
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700197
Mark Pizzolato45246a32012-03-21 06:14:01 -0700198/* MAC disc local utility routines */
Bob Supnike2ba6722004-07-10 06:13:00 -0700199
Mark Pizzolato45246a32012-03-21 06:14:01 -0700200static void start_command (void);
201static void poll_interface (void);
202static void poll_drives (void);
203static void fifo_load (uint16 data);
204static uint16 fifo_unload (void);
205static void fifo_clear (void);
206static t_stat activate_unit (UNIT *uptr);
207
208
209
210/* MAC disc VM data structures.
211
212 ds_dib DS device information block
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700213 ds_unit DS unit list
214 ds_reg DS register list
215 ds_mod DS modifier list
Mark Pizzolato45246a32012-03-21 06:14:01 -0700216 ds_deb DS debug table
217 ds_dev DS device descriptor
218
219 For the drive models, the modifiers provide this SHOW behavior:
220
221 - when detached and autosized, prints "autosize"
222 - when detached and not autosized, prints the model number
223 - when attached, prints the model number (regardless of autosizing)
224
225
226 Implementation notes:
227
228 1. The validation routine does not allow the model number or autosizing
229 option to be changed when the unit is attached. Therefore, specifying
Mark Pizzolato40deb202012-04-04 12:31:43 -0700230 UNIT_ATT in the mask field has no adverse effect.
Mark Pizzolato45246a32012-03-21 06:14:01 -0700231
232 2. The modifier DEVNO is deprecated in favor of SC but is retained for
233 compatibility.
Bob Supnike2ba6722004-07-10 06:13:00 -0700234*/
235
Bob Supnike2ba6722004-07-10 06:13:00 -0700236
Mark Pizzolato45246a32012-03-21 06:14:01 -0700237DEVICE ds_dev;
238
239static DIB ds_dib = { &ds_io, DS };
240
241#define UNIT_FLAGS (UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | UNIT_DISABLE | UNIT_UNLOAD)
242
243static UNIT ds_unit [] = {
Mark Pizzolato40deb202012-04-04 12:31:43 -0700244 { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* drive unit 0 */
245 { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* drive unit 1 */
246 { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* drive unit 2 */
247 { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* drive unit 3 */
248 { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* drive unit 4 */
249 { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* drive unit 5 */
250 { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* drive unit 6 */
251 { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* drive unit 7 */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700252 { UDATA (&ds_service_controller, UNIT_DIS, 0) }, /* controller unit */
253 { UDATA (&ds_service_timer, UNIT_DIS, 0) } /* timer unit */
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700254 };
Bob Supnike2ba6722004-07-10 06:13:00 -0700255
Mark Pizzolato45246a32012-03-21 06:14:01 -0700256static REG ds_reg [] = {
257 { FLDATA (CMFOL, ds.cmfol, 0) },
258 { FLDATA (CMRDY, ds.cmrdy, 0) },
Mark Pizzolato45246a32012-03-21 06:14:01 -0700259 { DRDATA (FCNT, ds.fifo_count, 5) },
Mark Pizzolato40deb202012-04-04 12:31:43 -0700260 { BRDATA (FIFO, ds.fifo, 8, 16, FIFO_SIZE), REG_CIRC },
Mark Pizzolato45246a32012-03-21 06:14:01 -0700261 { ORDATA (FREG, ds.fifo_reg, 32), REG_HRO },
262
263 { ORDATA (CNTYPE, mac_cntlr.type, 2), REG_HRO },
264 { ORDATA (STATE, mac_cntlr.state, 2) },
265 { ORDATA (OPCODE, mac_cntlr.opcode, 6) },
266 { ORDATA (STATUS, mac_cntlr.status, 6) },
267 { FLDATA (EOC, mac_cntlr.eoc, 0) },
268 { FLDATA (EOD, mac_cntlr.eod, 0) },
269 { ORDATA (SPDU, mac_cntlr.spd_unit, 16) },
270 { ORDATA (FLMASK, mac_cntlr.file_mask, 4) },
271 { ORDATA (RETRY, mac_cntlr.retry, 4), REG_HRO },
272 { ORDATA (CYL, mac_cntlr.cylinder, 16) },
273 { ORDATA (HEAD, mac_cntlr.head, 6) },
274 { ORDATA (SECTOR, mac_cntlr.sector, 8) },
275 { ORDATA (VFYCNT, mac_cntlr.verify_count, 16) },
276 { ORDATA (LASPOL, mac_cntlr.poll_unit, 3) },
277 { HRDATA (BUFPTR, mac_cntlr.buffer, 32), REG_HRO },
278 { BRDATA (BUFFER, buffer, 8, 16, DL_BUFSIZE) },
279 { DRDATA (INDEX, mac_cntlr.index, 8) },
280 { DRDATA (LENGTH, mac_cntlr.length, 8) },
281 { HRDATA (AUXPTR, mac_cntlr.aux, 32), REG_HRO },
282 { DRDATA (STIME, mac_cntlr.seek_time, 24), PV_LEFT | REG_NZ },
283 { DRDATA (ITIME, mac_cntlr.sector_time, 24), PV_LEFT | REG_NZ },
284 { DRDATA (CTIME, mac_cntlr.cmd_time, 24), PV_LEFT | REG_NZ },
285 { DRDATA (DTIME, mac_cntlr.data_time, 24), PV_LEFT | REG_NZ },
286 { DRDATA (WTIME, mac_cntlr.wait_time, 31), PV_LEFT | REG_NZ },
287
288 { FLDATA (CTL, ds.control, 0) },
289 { FLDATA (FLG, ds.flag, 0) },
290 { FLDATA (FBF, ds.flagbuf, 0) },
291 { FLDATA (SRQ, ds.srq, 0) },
292 { FLDATA (EDT, ds.edt, 0) },
293
294 { URDATA (UCYL, ds_unit[0].CYL, 10, 10, 0, DS_UNITS, PV_LEFT) },
295 { URDATA (UOP, ds_unit[0].OP, 8, 6, 0, DS_UNITS, PV_RZRO) },
296 { URDATA (USTAT, ds_unit[0].STAT, 2, 8, 0, DS_UNITS, PV_RZRO) },
297 { URDATA (UPHASE, ds_unit[0].PHASE, 8, 3, 0, DS_UNITS, PV_RZRO) },
298 { URDATA (UPOS, ds_unit[0].pos, 8, T_ADDR_W, 0, DS_UNITS, PV_LEFT) },
299 { URDATA (UWAIT, ds_unit[0].wait, 8, 32, 0, DS_UNITS, PV_LEFT) },
300
301 { ORDATA (SC, ds_dib.select_code, 6), REG_HRO },
302 { ORDATA (DEVNO, ds_dib.select_code, 6), REG_HRO },
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700303 { NULL }
304 };
Bob Supnike2ba6722004-07-10 06:13:00 -0700305
Mark Pizzolato45246a32012-03-21 06:14:01 -0700306static MTAB ds_mod [] = {
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700307/* Mask Value Match Value Print String Match String Validation Display Descriptor */
308/* ------------ ------------ ----------------- --------------- ---------------- ------- ---------- */
309 { UNIT_UNLOAD, UNIT_UNLOAD, "heads unloaded", "UNLOADED", &ds_load_unload, NULL, NULL },
310 { UNIT_UNLOAD, 0, "heads loaded", "LOADED", &ds_load_unload, NULL, NULL },
Mark Pizzolato45246a32012-03-21 06:14:01 -0700311
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700312 { UNIT_WLK, UNIT_WLK, "protected", "PROTECT", NULL, NULL, NULL },
313 { UNIT_WLK, 0, "unprotected", "UNPROTECT", NULL, NULL, NULL },
Mark Pizzolato45246a32012-03-21 06:14:01 -0700314
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700315 { UNIT_WLK, UNIT_WLK, NULL, "LOCKED", NULL, NULL, NULL },
316 { UNIT_WLK, 0, NULL, "WRITEENABLED", NULL, NULL, NULL },
Mark Pizzolato45246a32012-03-21 06:14:01 -0700317
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700318 { UNIT_FMT, UNIT_FMT, "format enabled", "FORMAT", NULL, NULL, NULL },
319 { UNIT_FMT, 0, "format disabled", "NOFORMAT", NULL, NULL, NULL },
320
321/* Print Match */
322/* Mask Value Match Value String String Validation Disp Desc */
323/* --------------------------------- --------------------- ---------- ---------- ------------- ---- ---- */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700324 { UNIT_AUTO | UNIT_ATT, UNIT_AUTO, "autosize", "AUTOSIZE", &dl_set_model, NULL, NULL },
325 { UNIT_AUTO | UNIT_ATT | UNIT_MODEL, MODEL_7905, "7905", "7905", &dl_set_model, NULL, NULL },
326 { UNIT_AUTO | UNIT_ATT | UNIT_MODEL, MODEL_7906, "7906", "7906", &dl_set_model, NULL, NULL },
327 { UNIT_AUTO | UNIT_ATT | UNIT_MODEL, MODEL_7920, "7920", "7920", &dl_set_model, NULL, NULL },
328 { UNIT_AUTO | UNIT_ATT | UNIT_MODEL, MODEL_7925, "7925", "7925", &dl_set_model, NULL, NULL },
329 { UNIT_ATT | UNIT_MODEL, UNIT_ATT | MODEL_7905, "7905", NULL, NULL, NULL, NULL },
330 { UNIT_ATT | UNIT_MODEL, UNIT_ATT | MODEL_7906, "7906", NULL, NULL, NULL, NULL },
331 { UNIT_ATT | UNIT_MODEL, UNIT_ATT | MODEL_7920, "7920", NULL, NULL, NULL, NULL },
332 { UNIT_ATT | UNIT_MODEL, UNIT_ATT | MODEL_7925, "7925", NULL, NULL, NULL, NULL },
333
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700334/* Entry Flags Value Print String Match String Validation Display Descriptor */
335/* ------------------- ----- ------------ ------------ ------------ ------------- ---------------- */
336 { MTAB_XDV, 1u, "SC", "SC", &hp_set_dib, &hp_show_dib, (void *) &ds_dib },
337 { MTAB_XDV | MTAB_NMO, ~1u, "DEVNO", "DEVNO", &hp_set_dib, &hp_show_dib, (void *) &ds_dib },
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700338 { 0 }
339 };
Bob Supnike2ba6722004-07-10 06:13:00 -0700340
Mark Pizzolato45246a32012-03-21 06:14:01 -0700341static DEBTAB ds_deb [] = {
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700342 { "RWSC", DEB_RWSC },
343 { "CMDS", DEB_CMDS },
344 { "CPU", DEB_CPU },
345 { "BUF", DEB_BUF },
346 { "SERV", DEB_SERV },
347 { "IOBUS", TRACE_IOBUS },
348 { NULL, 0 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700349 };
Mark Pizzolato45246a32012-03-21 06:14:01 -0700350
351DEVICE ds_dev = {
352 "DS", /* device name */
353 ds_unit, /* unit array */
354 ds_reg, /* register array */
355 ds_mod, /* modifier array */
356 DS_UNITS, /* number of units */
357 8, /* address radix */
358 27, /* address width = 128 MB */
359 1, /* address increment */
360 8, /* data radix */
361 16, /* data width */
362 NULL, /* examine routine */
363 NULL, /* deposit routine */
364 &ds_reset, /* reset routine */
365 &ds_boot, /* boot routine */
366 &ds_attach, /* attach routine */
367 &ds_detach, /* detach routine */
368 &ds_dib, /* device information block */
369 DEV_DEBUG | DEV_DISABLE, /* device flags */
370 0, /* debug control flags */
371 ds_deb, /* debug flag name table */
372 NULL, /* memory size change routine */
373 NULL /* logical device name */
374 };
375
376
377
378/* MAC disc global VM routines */
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700379
Bob Supnike2ba6722004-07-10 06:13:00 -0700380
Bob Supnik9c4779c2009-02-08 09:06:00 -0800381/* I/O signal handler.
382
Mark Pizzolato45246a32012-03-21 06:14:01 -0700383 The 13175D disc interface data path consists of an input multiplexer/latch
384 and a 16-word FIFO buffer. The FIFO source may be either the CPU's I/O
385 input bus or the controller's interface data bus. The output of the FIFO may
386 be enabled either to the CPU's I/O output bus or the interface data bus.
Bob Supnik9c4779c2009-02-08 09:06:00 -0800387
Mark Pizzolato45246a32012-03-21 06:14:01 -0700388 The control path consists of the usual control, flag buffer, flag, and SRQ
389 flip-flops, although flag and SRQ are decoupled to allow the full DCPC
390 transfer rate through the FIFO (driving SRQ from the flag limits transfers to
Mark Pizzolato40deb202012-04-04 12:31:43 -0700391 every other cycle). SRQ is based on the FIFO level: if data or room in the
392 FIFO is available, SRQ is set to initiate a transfer. The flag is only used
393 to signal an interrupt at the end of a command.
Mark Pizzolato45246a32012-03-21 06:14:01 -0700394
395 One unusual aspect is that SFC and SFS test different things, rather than
Mark Pizzolato40deb202012-04-04 12:31:43 -0700396 complementary states of the same thing. SFC tests the controller busy state,
397 and SFS tests the flag flip-flop.
Bob Supnik9c4779c2009-02-08 09:06:00 -0800398
Mark Pizzolato45246a32012-03-21 06:14:01 -0700399 In addition, the card contains end-of-data-transfer, command-follows, and
400 command-ready flip-flops. EDT is set when the DCPC EDT signal is asserted
401 and is used in conjunction with the FIFO level to assert the end-of-data
402 signal to the controller. The command-follows flip-flop is set by a CLC to
403 indicate that the next data word output from the CPU is a disc command. The
404 command-ready flip-flop is set when a command is received to schedule an
405 interface poll.
406
407
Bob Supnik9c4779c2009-02-08 09:06:00 -0800408 Implementation notes:
409
Mark Pizzolato45246a32012-03-21 06:14:01 -0700410 1. In hardware, SRQ is enabled only when the controller is reading or
411 writing the disc (IFIN or IFOUT functions are asserted) and set when the
412 FIFO is not empty (read) or not full (write). In simulation, SRQ is set
Mark Pizzolato40deb202012-04-04 12:31:43 -0700413 by the unit service read/write data phase transfers and cleared in the
414 IOI and IOO signal handlers when the FIFO is empty (read) or full
415 (write).
Mark Pizzolato45246a32012-03-21 06:14:01 -0700416
417 2. The DCPC EDT signal cannot set the controller's end-of-data flag directly
418 because a write EOD must occur only after the FIFO has been drained.
419
Mark Pizzolato40deb202012-04-04 12:31:43 -0700420 3. Polling the interface or drives must be deferred to the end of I/O signal
421 handling. If they are performed in the IOO/STC handlers themselves, an
422 associated CLF might clear the flag that was set by the poll.
Mark Pizzolato45246a32012-03-21 06:14:01 -0700423
424 4. Executing a CLC sets the controller's end-of-data flag, which will abort
425 a read or write data transfer in progress. Parameter transfers are not
426 affected. If a command is received when a parameter is expected, the
427 word is interpreted as data, even though the command-ready flip-flop is
428 set. The controller firmware only checks DTRDY for a parameter transfer,
429 and DTRDY is asserted whenever the FIFO is not empty.
430
431 5. The hardware Interface Function and Flag Buses are not implemented
432 explicitly. Instead, interface functions and signals are inferred by the
Mark Pizzolato40deb202012-04-04 12:31:43 -0700433 interface from the current command operation and phase.
Bob Supnik9c4779c2009-02-08 09:06:00 -0800434*/
435
Mark Pizzolato45246a32012-03-21 06:14:01 -0700436uint32 ds_io (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
Bob Supnike2ba6722004-07-10 06:13:00 -0700437{
Mark Pizzolato45246a32012-03-21 06:14:01 -0700438static const char * const output_state [] = { "Data", "Command" };
439const char * const hold_or_clear = (signal_set & ioCLF ? ",C" : "");
440
441uint16 data;
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700442IOSIGNAL signal;
443IOCYCLE working_set = IOADDSIR (signal_set); /* add ioSIR if needed */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700444t_bool command_issued = FALSE;
445t_bool interrupt_enabled = FALSE;
Bob Supnike2ba6722004-07-10 06:13:00 -0700446
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700447while (working_set) {
Mark Pizzolato45246a32012-03-21 06:14:01 -0700448 signal = IONEXT (working_set); /* isolate the next signal */
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700449
Mark Pizzolato45246a32012-03-21 06:14:01 -0700450 switch (signal) { /* dispatch the I/O signal */
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700451
452 case ioCLF: /* clear flag flip-flop */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700453 ds.flag = CLEAR; /* clear the flag */
454 ds.flagbuf = CLEAR; /* and flag buffer */
455
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700456 tprintf (ds_dev, DEB_CMDS, "[CLF] Flag cleared\n");
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700457 break;
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700458
Bob Supnik9c4779c2009-02-08 09:06:00 -0800459
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700460 case ioSTF: /* set flag flip-flop */
461 case ioENF: /* enable flag */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700462 ds.flag = SET; /* set the flag */
463 ds.flagbuf = SET; /* and flag buffer */
464
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700465 tprintf (ds_dev, DEB_CMDS, "[STF] Flag set\n");
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700466 break;
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700467
Bob Supnik9c4779c2009-02-08 09:06:00 -0800468
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700469 case ioSFC: /* skip if flag is clear */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700470 setSKF (mac_cntlr.state != cntlr_busy); /* skip if the controller is not busy */
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700471 break;
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700472
Bob Supnik9c4779c2009-02-08 09:06:00 -0800473
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700474 case ioSFS: /* skip if flag is set */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700475 setstdSKF (ds); /* assert SKF if the flag is set */
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700476 break;
Bob Supnik9c4779c2009-02-08 09:06:00 -0800477
478
Mark Pizzolato45246a32012-03-21 06:14:01 -0700479 case ioIOI: /* I/O data input */
480 data = fifo_unload (); /* unload the next word from the FIFO */
481 stat_data = IORETURN (SCPE_OK, data); /* merge in the return status */
482
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700483 tprintf (ds_dev, DEB_CPU, "[LIx%s] Data = %06o\n", hold_or_clear, data);
Mark Pizzolato45246a32012-03-21 06:14:01 -0700484
485 if (FIFO_EMPTY) { /* is the FIFO now empty? */
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700486 if (ds.srq == SET)
487 tprintf (ds_dev, DEB_CMDS, "[LIx%s] SRQ cleared\n", hold_or_clear);
Mark Pizzolato45246a32012-03-21 06:14:01 -0700488
489 ds.srq = CLEAR; /* clear SRQ */
490
491 if (ds_cntlr.PHASE == data_phase) { /* is this an outbound parameter? */
492 ds_cntlr.wait = mac_cntlr.data_time; /* activate the controller */
493 activate_unit (&ds_cntlr); /* to acknowledge the data */
494 }
495 }
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700496 break;
Bob Supnik9c4779c2009-02-08 09:06:00 -0800497
498
Mark Pizzolato45246a32012-03-21 06:14:01 -0700499 case ioIOO: /* I/O data output */
500 data = IODATA (stat_data); /* mask to just the data word */
501
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700502 tprintf (ds_dev, DEB_CPU, "[OTx%s] %s = %06o\n",
503 hold_or_clear, output_state [ds.cmfol], data);
Mark Pizzolato45246a32012-03-21 06:14:01 -0700504
505 fifo_load (data); /* load the word into the FIFO */
506
507 if (ds.cmfol == SET) { /* are we expecting a command? */
508 ds.cmfol = CLEAR; /* clear the command follows flip-flop */
509 ds.cmrdy = SET; /* set the command ready flip-flop */
510 command_issued = TRUE; /* and request an interface poll */
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700511 }
Bob Supnik9c4779c2009-02-08 09:06:00 -0800512
Mark Pizzolato45246a32012-03-21 06:14:01 -0700513 else { /* not a command */
514 if (ds_cntlr.PHASE == data_phase) { /* is this an inbound parameter? */
515 ds_cntlr.wait = mac_cntlr.data_time; /* activate the controller */
516 activate_unit (&ds_cntlr); /* to receive the data */
517 }
518
519 if (FIFO_STOP) { /* is the FIFO now full enough? */
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700520 if (ds.srq == SET)
521 tprintf (ds_dev, DEB_CMDS, "[OTx%s] SRQ cleared\n", hold_or_clear);
Mark Pizzolato45246a32012-03-21 06:14:01 -0700522
Mark Pizzolato40deb202012-04-04 12:31:43 -0700523 ds.srq = CLEAR; /* clear SRQ to stop filling */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700524 }
525 }
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700526 break;
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700527
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700528
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700529 case ioPOPIO: /* power-on preset to I/O */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700530 ds.flag = SET; /* set the flag */
531 ds.flagbuf = SET; /* and flag buffer */
532 ds.cmrdy = CLEAR; /* clear the command ready flip-flop */
533
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700534 tprintf (ds_dev, DEB_CMDS, "[POPIO] Flag set\n");
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700535 break;
Bob Supnik59aa4a72008-06-24 14:21:00 -0700536
Bob Supnik9c4779c2009-02-08 09:06:00 -0800537
Mark Pizzolato45246a32012-03-21 06:14:01 -0700538 case ioCRS: /* control reset */
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700539 tprintf (ds_dev, DEB_CMDS, "[CRS] Master reset\n");
Mark Pizzolato45246a32012-03-21 06:14:01 -0700540
541 ds.control = CLEAR; /* clear the control */
542 ds.cmfol = CLEAR; /* and command follows flip-flops */
543
544 if (PRESET_ENABLE) { /* is preset enabled for this interface? */
545 fifo_clear (); /* clear the FIFO */
546
Mark Pizzolato486427c2018-06-03 14:38:38 -0700547 dl_clear_controller (&mac_cntlr, ds_unit, /* do a hard clear of the controller */
548 hard_clear);
Mark Pizzolato45246a32012-03-21 06:14:01 -0700549 }
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700550 break;
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700551
Bob Supnik9c4779c2009-02-08 09:06:00 -0800552
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700553 case ioCLC: /* clear control flip-flop */
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700554 tprintf (ds_dev, DEB_CMDS, "[CLC%s] Control cleared\n", hold_or_clear);
Mark Pizzolato45246a32012-03-21 06:14:01 -0700555
556 ds.control = CLEAR; /* clear the control */
557 ds.edt = CLEAR; /* and EDT flip-flops */
558 ds.cmfol = SET; /* set the command follows flip-flop */
559 mac_cntlr.eod = SET; /* set the controller's EOD flag */
560
561 fifo_clear (); /* clear the FIFO */
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700562 break;
Bob Supnik9c4779c2009-02-08 09:06:00 -0800563
564
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700565 case ioSTC: /* set control flip-flop */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700566 ds.control = SET; /* set the control flip-flop */
567
568 interrupt_enabled = TRUE; /* check for drive attention */
569
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700570 tprintf (ds_dev, DEB_CMDS, "[STC%s] Control set\n", hold_or_clear);
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700571 break;
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700572
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700573
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700574 case ioEDT: /* end data transfer */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700575 ds.edt = SET; /* set the EDT flip-flop */
576
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700577 tprintf (ds_dev, DEB_CPU, "[EDT] DCPC transfer ended\n");
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700578 break;
Bob Supnik9c4779c2009-02-08 09:06:00 -0800579
580
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700581 case ioSIR: /* set interrupt request */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700582 setstdPRL (ds); /* set the standard PRL signal */
583 setstdIRQ (ds); /* set the standard IRQ signal */
584 setSRQ (dibptr->select_code, ds.srq); /* set the SRQ signal */
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700585 break;
Bob Supnik9c4779c2009-02-08 09:06:00 -0800586
587
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700588 case ioIAK: /* interrupt acknowledge */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700589 ds.flagbuf = CLEAR; /* clear the flag */
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700590 break;
591
592
593 default: /* all other signals */
594 break; /* are ignored */
595 }
596
Mark Pizzolato45246a32012-03-21 06:14:01 -0700597 working_set = working_set & ~signal; /* remove the current signal from the set */
Bob Supnik9c4779c2009-02-08 09:06:00 -0800598 }
599
Mark Pizzolato45246a32012-03-21 06:14:01 -0700600
601if (command_issued) /* was a command received? */
602 poll_interface (); /* poll the interface for the next command */
603else if (interrupt_enabled) /* were interrupts enabled? */
604 poll_drives (); /* poll the drives for Attention */
Bob Supnik9c4779c2009-02-08 09:06:00 -0800605
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700606return stat_data;
Bob Supnike2ba6722004-07-10 06:13:00 -0700607}
Bob Supnik9c4779c2009-02-08 09:06:00 -0800608
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700609
Mark Pizzolato45246a32012-03-21 06:14:01 -0700610/* Service the disc drive unit.
Bob Supnike2ba6722004-07-10 06:13:00 -0700611
Mark Pizzolato45246a32012-03-21 06:14:01 -0700612 The unit service routine is called to execute scheduled controller commands
613 for the specified unit. The actions to be taken depend on the current state
614 of the controller and the unit.
615
616 Generally, the controller library service routine handles all of the disc
617 operations except data transfer to and from the interface. Read transfers
618 are responsible for loading words from the sector buffer into the FIFO and
619 enabling SRQ. If the current sector transfer is complete, either due to EDT
620 assertion or buffer exhaustion, the controller is moved to the end phase to
621 complete or continue the read with the next sector. In either case, the unit
622 is rescheduled. If the FIFO overflows, the read terminates with a data
623 overrun error.
624
625 Write transfers set the initial SRQ to request words from the CPU. As each
Mark Pizzolato40deb202012-04-04 12:31:43 -0700626 word arrives, it is unloaded from the FIFO into the sector buffer, and SRQ is
Mark Pizzolato45246a32012-03-21 06:14:01 -0700627 enabled. If the current sector transfer is complete, the controller is moved
628 to the end phase. If the FIFO underflows, the write terminates with a data
629 overrun error.
630
631 The synchronous nature of the disc drive requires that data be supplied or
632 accepted continuously by the CPU. DCPC generally assures that this occurs,
633 and the FIFO allows for some latency before an overrun or underrun occurs.
634
635 The other operation the interface must handle is seek completion. The
636 controller handles seek completion by setting Attention status in the drive's
637 status word. The interface is responsible for polling the drives if the
638 controller is idle and interrupts are enabled.
639
640
641 Implementation notes:
642
Mark Pizzolato40deb202012-04-04 12:31:43 -0700643 1. Every command except Seek, Recalibrate, and End sets the flag when the
Mark Pizzolato45246a32012-03-21 06:14:01 -0700644 command completes. A command completes when the controller is no longer
Mark Pizzolato40deb202012-04-04 12:31:43 -0700645 busy (it becomes idle for Seek, Recalibrate, and End, or it becomes
646 waiting for all others). Seek and Recalibrate may generate errors (e.g.,
647 heads unloaded), in which case the flag must be set. But in these cases,
648 the controller state is waiting, not idle.
Mark Pizzolato45246a32012-03-21 06:14:01 -0700649
650 However, it is insufficient simply to check that the controller has moved
651 to the wait state, because a seek may complete while the controller is
652 waiting for the next command. For example, a Seek is started on unit 0,
653 and the controller moves to the idle state. But before the seek
654 completes, another command is issued that attempts to access unit 1,
655 which is not ready. The command fails with a Status-2 error, and the
656 controller moves to the wait state. When the seek completes, the
Mark Pizzolato40deb202012-04-04 12:31:43 -0700657 controller is waiting with error status. We must determine whether the
658 seek completed successfully or not, as we must interrupt in the latter
659 case.
Mark Pizzolato45246a32012-03-21 06:14:01 -0700660
661 Therefore, we determine seek completion by checking if the Attention
662 status was set. Attention sets only if the seek completes successfully.
663
664 (Actually, Attention sets if a seek check occurs, but in that case, the
665 command terminated before the seek ever started. Also, a seek may
666 complete while the controller is busy, waiting, or idle.)
667
Mark Pizzolato40deb202012-04-04 12:31:43 -0700668 2. For debug printouts, we want to print the name of the command that has
669 completed when the controller returns to the idle or wait state.
670 Normally, we would use the controller's "opcode" field to identify the
671 command that completed. However, while waiting for Seek or Recalibrate
672 completion, "opcode" may be set to another command if that command does
673 not access this drive. For example, it might be set to a Read of another
674 unit, or a Request Status for this unit. So we can't rely on "opcode" to
675 report the correct name of the completed positioning command.
Mark Pizzolato45246a32012-03-21 06:14:01 -0700676
Mark Pizzolato40deb202012-04-04 12:31:43 -0700677 However, we cannot rely on "uptr->OP" either, as that can be changed
678 during the course of a command. For example, Read Without Verify is
679 changed to Read after a track crossing.
Mark Pizzolato45246a32012-03-21 06:14:01 -0700680
Mark Pizzolato40deb202012-04-04 12:31:43 -0700681 Instead, we have to determine whether a seek is completing. If it is,
682 then we report "uptr->OP"; otherwise, we report "opcode".
Mark Pizzolato45246a32012-03-21 06:14:01 -0700683
Mark Pizzolato40deb202012-04-04 12:31:43 -0700684 3. The initial write SRQ must set only at the transition from the start
685 phase to the data phase. If a write command begins with an auto-seek,
686 the drive service will be entered twice in the start phase (the first
687 entry performs the seek, and the second begins the write). In hardware,
688 SRQ does not assert until the write begins.
Mark Pizzolato45246a32012-03-21 06:14:01 -0700689
Mark Pizzolato40deb202012-04-04 12:31:43 -0700690 4. The DCPC EDT signal cannot set the controller's end-of-data flag
691 directly because a write EOD must only occur after the FIFO has been
692 drained.
Bob Supnike2ba6722004-07-10 06:13:00 -0700693*/
694
Mark Pizzolato45246a32012-03-21 06:14:01 -0700695t_stat ds_service_drive (UNIT *uptr)
Bob Supnike2ba6722004-07-10 06:13:00 -0700696{
Mark Pizzolato45246a32012-03-21 06:14:01 -0700697t_stat result;
698t_bool seek_completion;
Mark Pizzolato40deb202012-04-04 12:31:43 -0700699FLIP_FLOP entry_srq = ds.srq; /* get the SRQ state on entry */
700CNTLR_PHASE entry_phase = (CNTLR_PHASE) uptr->PHASE; /* get the operation phase on entry */
701uint32 entry_status = uptr->STAT; /* get the drive status on entry */
Bob Supnik9c4779c2009-02-08 09:06:00 -0800702
Mark Pizzolato45246a32012-03-21 06:14:01 -0700703result = dl_service_drive (&mac_cntlr, uptr); /* service the drive */
Bob Supnike2ba6722004-07-10 06:13:00 -0700704
Mark Pizzolato45246a32012-03-21 06:14:01 -0700705if ((CNTLR_PHASE) uptr->PHASE == data_phase) /* is the drive in the data phase? */
706 switch ((CNTLR_OPCODE) uptr->OP) { /* dispatch the current operation */
Bob Supnike2ba6722004-07-10 06:13:00 -0700707
Mark Pizzolatoef147d22012-10-24 12:57:37 -0700708 case Read: /* read operations */
709 case Read_Full_Sector:
710 case Read_With_Offset:
711 case Read_Without_Verify:
Mark Pizzolato45246a32012-03-21 06:14:01 -0700712 if (mac_cntlr.length == 0 || ds.edt == SET) { /* is the data phase complete? */
713 mac_cntlr.eod = ds.edt; /* set EOD if DCPC is done */
714 uptr->PHASE = end_phase; /* set the end phase */
715 uptr->wait = mac_cntlr.cmd_time; /* and schedule the controller */
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700716 }
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700717
Mark Pizzolato45246a32012-03-21 06:14:01 -0700718 else if (FIFO_FULL) /* is the FIFO already full? */
719 dl_end_command (&mac_cntlr, data_overrun); /* terminate the command with an overrun */
Bob Supnike2ba6722004-07-10 06:13:00 -0700720
Mark Pizzolato45246a32012-03-21 06:14:01 -0700721 else {
722 fifo_load (buffer [mac_cntlr.index++]); /* load the next word into the FIFO */
723 mac_cntlr.length--; /* count it */
724 ds.srq = SET; /* ask DCPC to pick it up */
725 ds_io (&ds_dib, ioSIR, 0); /* and recalculate the interrupts */
726 uptr->wait = mac_cntlr.data_time; /* schedule the next data transfer */
727 }
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700728
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700729 break;
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700730
Bob Supnike2ba6722004-07-10 06:13:00 -0700731
Mark Pizzolatoef147d22012-10-24 12:57:37 -0700732 case Write: /* write operations */
733 case Write_Full_Sector:
734 case Initialize:
Mark Pizzolato45246a32012-03-21 06:14:01 -0700735 if (entry_phase == start_phase) { /* is this the phase transition? */
736 ds.srq = SET; /* start the DCPC transfer */
737 ds_io (&ds_dib, ioSIR, 0); /* and recalculate the interrupts */
738 }
Bob Supnike2ba6722004-07-10 06:13:00 -0700739
Mark Pizzolato45246a32012-03-21 06:14:01 -0700740 else if (FIFO_EMPTY) /* is the FIFO empty? */
741 dl_end_command (&mac_cntlr, data_overrun); /* terminate the command with an underrun */
Bob Supnikb6393b32004-11-23 15:49:00 -0800742
Mark Pizzolato45246a32012-03-21 06:14:01 -0700743 else {
744 buffer [mac_cntlr.index++] = fifo_unload (); /* unload the next word from the FIFO */
745 mac_cntlr.length--; /* count it */
Bob Supnike2ba6722004-07-10 06:13:00 -0700746
Mark Pizzolato45246a32012-03-21 06:14:01 -0700747 if (ds.edt == SET && FIFO_EMPTY) /* if DCPC is complete and the FIFO is empty */
748 mac_cntlr.eod = SET; /* then set the end-of-data flag */
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700749
Mark Pizzolato45246a32012-03-21 06:14:01 -0700750 if (mac_cntlr.length == 0 || mac_cntlr.eod == SET) { /* is the data phase complete? */
751 uptr->PHASE = end_phase; /* set the end phase */
752 uptr->wait = mac_cntlr.cmd_time; /* and schedule the controller */
753 }
754
755 else {
756 if (ds.edt == CLEAR) { /* if DCPC is still transferring */
757 ds.srq = SET; /* then request the next word */
758 ds_io (&ds_dib, ioSIR, 0); /* and recalculate the interrupts */
759 }
760
761 uptr->wait = mac_cntlr.data_time; /* schedule the next data transfer */
762 }
763 }
764
765 break;
766
767
Mark Pizzolato40deb202012-04-04 12:31:43 -0700768 default: /* we were entered with an invalid state */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700769 result = SCPE_IERR; /* return an internal (programming) error */
770 break;
771 } /* end of data phase operation dispatch */
772
773
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700774if (entry_srq != ds.srq)
775 tprintf (ds_dev, DEB_CMDS, "SRQ %s\n", ds.srq == SET ? "set" : "cleared");
Mark Pizzolato45246a32012-03-21 06:14:01 -0700776
Mark Pizzolato40deb202012-04-04 12:31:43 -0700777if (uptr->wait) /* was service requested? */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700778 activate_unit (uptr); /* schedule the next event */
779
780seek_completion = ~entry_status & uptr->STAT & DL_S2ATN; /* seek is complete when Attention sets */
781
782if (mac_cntlr.state != cntlr_busy) { /* is the command complete? */
Mark Pizzolato40deb202012-04-04 12:31:43 -0700783 if (mac_cntlr.state == cntlr_wait && !seek_completion) /* is it command but not seek completion? */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700784 ds_io (&ds_dib, ioENF, 0); /* set the data flag to interrupt the CPU */
785
786 poll_interface (); /* poll the interface for the next command */
787 poll_drives (); /* poll the drives for Attention */
788 }
789
790
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700791if (result == SCPE_IERR) /* did an internal error occur? */
792 tprintf (ds_dev, DEB_RWSC, "Unit %d %s command %s phase service not handled\n",
793 uptr - ds_unit, dl_opcode_name (MAC, (CNTLR_OPCODE) uptr->OP),
794 dl_phase_name ((CNTLR_PHASE) uptr->PHASE));
Mark Pizzolato40deb202012-04-04 12:31:43 -0700795
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700796else if (seek_completion) /* if a seek has completed */
797 tprintf (ds_dev, DEB_RWSC, "Unit %d %s command completed\n", /* report the unit command */
798 uptr - ds_unit, dl_opcode_name (MAC, (CNTLR_OPCODE) uptr->OP));
Mark Pizzolato45246a32012-03-21 06:14:01 -0700799
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700800else if (mac_cntlr.state == cntlr_wait) /* if the controller has stopped */
801 tprintf (ds_dev, DEB_RWSC, "Unit %d %s command completed\n", /* report the controller command */
802 uptr - ds_unit, dl_opcode_name (MAC, mac_cntlr.opcode));
Mark Pizzolato45246a32012-03-21 06:14:01 -0700803
804return result; /* return the result of the service */
Bob Supnik53d02f72007-02-03 14:59:00 -0800805}
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700806
Bob Supnik9c4779c2009-02-08 09:06:00 -0800807
Mark Pizzolato45246a32012-03-21 06:14:01 -0700808/* Service the controller unit.
Bob Supnike2ba6722004-07-10 06:13:00 -0700809
Mark Pizzolato45246a32012-03-21 06:14:01 -0700810 The controller service routine is called to execute scheduled controller
811 commands that do not access drive units. It is also called to obtain command
812 parameters from the interface and to return command result values to the
813 interface.
Bob Supnike2ba6722004-07-10 06:13:00 -0700814
Mark Pizzolato45246a32012-03-21 06:14:01 -0700815 Most controller commands are handled completely in the library's service
816 routine, so we call that first. Commands that neither accept nor supply
817 parameters are complete when the library routine returns, so all we have to
818 do is set the interface flag if required.
819
820 For parameter transfers in the data phase, the interface is responsible for
821 moving words between the sector buffer and the FIFO and setting the flag to
822 notify the CPU.
Bob Supnik9c4779c2009-02-08 09:06:00 -0800823
Bob Supnike2ba6722004-07-10 06:13:00 -0700824
Mark Pizzolato45246a32012-03-21 06:14:01 -0700825 Implementation notes:
Bob Supnike2ba6722004-07-10 06:13:00 -0700826
Mark Pizzolato45246a32012-03-21 06:14:01 -0700827 1. In hardware, the Read With Offset command sets the data flag after the
828 offset parameter has been read and the head positioner has been moved by
829 the indicated amount. The intent is to delay the DCPC start until the
830 drive is ready to supply data from the disc.
Bob Supnike2ba6722004-07-10 06:13:00 -0700831
Mark Pizzolato45246a32012-03-21 06:14:01 -0700832 In simulation, the flag is set as soon as the parameter is received.
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700833*/
Bob Supnike2ba6722004-07-10 06:13:00 -0700834
Mark Pizzolato45246a32012-03-21 06:14:01 -0700835t_stat ds_service_controller (UNIT *uptr)
Bob Supnike2ba6722004-07-10 06:13:00 -0700836{
Mark Pizzolato45246a32012-03-21 06:14:01 -0700837t_stat result;
838const CNTLR_OPCODE opcode = (CNTLR_OPCODE) uptr->OP;
Bob Supnike2ba6722004-07-10 06:13:00 -0700839
Mark Pizzolato45246a32012-03-21 06:14:01 -0700840result = dl_service_controller (&mac_cntlr, uptr); /* service the controller */
841
842switch ((CNTLR_PHASE) uptr->PHASE) { /* dispatch the current phase */
843
844 case start_phase: /* most controller operations */
845 case end_phase: /* start and end on the same phase */
846 switch (opcode) { /* dispatch the current operation */
847
Mark Pizzolatoef147d22012-10-24 12:57:37 -0700848 case Request_Status:
849 case Request_Sector_Address:
850 case Address_Record:
851 case Request_Syndrome:
852 case Load_TIO_Register:
853 case Request_Disc_Address:
854 case End:
Mark Pizzolato45246a32012-03-21 06:14:01 -0700855 break; /* complete the operation without setting the flag */
Bob Supnike2ba6722004-07-10 06:13:00 -0700856
Bob Supnik9c4779c2009-02-08 09:06:00 -0800857
Mark Pizzolatoef147d22012-10-24 12:57:37 -0700858 case Clear:
859 case Set_File_Mask:
860 case Wakeup:
Mark Pizzolato40deb202012-04-04 12:31:43 -0700861 ds_io (&ds_dib, ioENF, 0); /* complete the operation and set the flag */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700862 break;
Bob Supnike2ba6722004-07-10 06:13:00 -0700863
Bob Supnik9c4779c2009-02-08 09:06:00 -0800864
Mark Pizzolato40deb202012-04-04 12:31:43 -0700865 default: /* we were entered with an invalid state */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700866 result = SCPE_IERR; /* return an internal (programming) error */
867 break;
868 } /* end of operation dispatch */
869 break; /* end of start and end phase handlers */
Bob Supnik9c4779c2009-02-08 09:06:00 -0800870
Bob Supnike2ba6722004-07-10 06:13:00 -0700871
Mark Pizzolato45246a32012-03-21 06:14:01 -0700872 case data_phase:
873 switch (opcode) { /* dispatch the current operation */
Bob Supnike2ba6722004-07-10 06:13:00 -0700874
Mark Pizzolatoef147d22012-10-24 12:57:37 -0700875 case Seek: /* operations that accept parameters */
876 case Verify:
877 case Address_Record:
878 case Read_With_Offset:
879 case Load_TIO_Register:
Mark Pizzolato45246a32012-03-21 06:14:01 -0700880 buffer [mac_cntlr.index++] = fifo_unload (); /* unload the next word from the FIFO */
881 mac_cntlr.length--; /* count it */
Bob Supnike2ba6722004-07-10 06:13:00 -0700882
Mark Pizzolato45246a32012-03-21 06:14:01 -0700883 if (mac_cntlr.length) /* are there more words to transfer? */
884 ds_io (&ds_dib, ioENF, 0); /* set the flag to request the next one */
885
886 else { /* all parameters have been received */
887 uptr->PHASE = end_phase; /* set the end phase */
888
Mark Pizzolatoef147d22012-10-24 12:57:37 -0700889 if (opcode == Read_With_Offset) /* a Read With Offset command sets the flag */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700890 ds_io (&ds_dib, ioENF, 0); /* to indicate that offsetting is complete */
891
892 start_command (); /* the command is now ready to execute */
893 }
894 break;
895
896
Mark Pizzolatoef147d22012-10-24 12:57:37 -0700897 case Request_Status: /* operations that supply parameters */
898 case Request_Sector_Address:
899 case Request_Syndrome:
900 case Request_Disc_Address:
Mark Pizzolato45246a32012-03-21 06:14:01 -0700901 if (mac_cntlr.length) { /* are there more words to return? */
902 fifo_load (buffer [mac_cntlr.index++]); /* load the next word into the FIFO */
903 mac_cntlr.length--; /* count it */
904
905 ds_io (&ds_dib, ioENF, 0); /* set the flag to request pickup by the CPU */
906 }
907
908 else { /* all parameters have been sent */
909 uptr->PHASE = end_phase; /* set the end phase */
910 uptr->wait = mac_cntlr.cmd_time; /* schedule the controller */
911 activate_unit (uptr); /* to complete the command */
912 }
913 break;
914
915
Mark Pizzolato40deb202012-04-04 12:31:43 -0700916 default: /* we were entered with an invalid state */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700917 result = SCPE_IERR; /* return an internal (programming) error */
918 break;
919 } /* end of operation dispatch */
920 break; /* end of data phase handlers */
921 } /* end of phase dispatch */
922
923
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700924if (result == SCPE_IERR) /* did an internal error occur? */
925 tprintf (ds_dev, DEB_RWSC, "Controller %s command %s phase service not handled\n",
Mark Pizzolato45246a32012-03-21 06:14:01 -0700926 dl_opcode_name (MAC, opcode), dl_phase_name ((CNTLR_PHASE) uptr->PHASE));
927
928
929if (mac_cntlr.state != cntlr_busy) { /* has the controller stopped? */
930 poll_interface (); /* poll the interface for the next command */
931 poll_drives (); /* poll the drives for Attention status */
932
Mark Pizzolatoa6552b82017-09-06 22:16:14 -0700933 tprintf (ds_dev, DEB_RWSC, "Controller %s command completed\n",
934 dl_opcode_name (MAC, opcode));
Bob Supnikb7c1eae2005-09-09 18:09:00 -0700935 }
Mark Pizzolato45246a32012-03-21 06:14:01 -0700936
937return result; /* return the result of the service */
Bob Supnike2ba6722004-07-10 06:13:00 -0700938}
Bob Supnik9c4779c2009-02-08 09:06:00 -0800939
Bob Supnike2ba6722004-07-10 06:13:00 -0700940
Mark Pizzolato45246a32012-03-21 06:14:01 -0700941/* Service the command wait timer unit.
Bob Supnike2ba6722004-07-10 06:13:00 -0700942
Mark Pizzolato45246a32012-03-21 06:14:01 -0700943 The command wait timer service routine is called if the command wait timer
944 expires. The library is called to reset the file mask and idle the
945 controller. Then the interface is polled for a command and the drives are
946 polled for Attention status.
Mark Pizzolatofffad7c2012-03-19 16:05:24 -0700947*/
Bob Supnike2ba6722004-07-10 06:13:00 -0700948
Mark Pizzolato45246a32012-03-21 06:14:01 -0700949t_stat ds_service_timer (UNIT *uptr)
Bob Supnike2ba6722004-07-10 06:13:00 -0700950{
Mark Pizzolato45246a32012-03-21 06:14:01 -0700951t_stat result;
Bob Supnike2ba6722004-07-10 06:13:00 -0700952
Mark Pizzolato45246a32012-03-21 06:14:01 -0700953result = dl_service_timer (&mac_cntlr, uptr); /* service the timer */
954
955poll_interface (); /* poll the interface for the next command */
956poll_drives (); /* poll the drives for Attention status */
957
958return result; /* return the result of the service */
Bob Supnike2ba6722004-07-10 06:13:00 -0700959}
960
Bob Supnik9c4779c2009-02-08 09:06:00 -0800961
Mark Pizzolato45246a32012-03-21 06:14:01 -0700962/* Reset the simulator.
Bob Supnike2ba6722004-07-10 06:13:00 -0700963
Mark Pizzolato45246a32012-03-21 06:14:01 -0700964 In hardware, the PON signal clears the Interface Selected flip-flop,
965 disconnecting the interface from the disc controller. In simulation, the
966 interface always remains connected to the controller, so no special action is
967 needed.
Bob Supnike2ba6722004-07-10 06:13:00 -0700968
Bob Supnik9c4779c2009-02-08 09:06:00 -0800969
Mark Pizzolato45246a32012-03-21 06:14:01 -0700970 Implementation notes:
Bob Supnike2ba6722004-07-10 06:13:00 -0700971
Mark Pizzolato45246a32012-03-21 06:14:01 -0700972 1. During a power-on reset, a pointer to the FIFO simulation register is
973 saved to allow access to the "qptr" field during FIFO loading and
Mark Pizzolato40deb202012-04-04 12:31:43 -0700974 unloading. This enables SCP to view the FIFO as a circular queue, so
Mark Pizzolato45246a32012-03-21 06:14:01 -0700975 that the bottom word of the FIFO is always displayed as FIFO[0],
976 regardless of where it is in the actual FIFO array.
Bob Supnike2ba6722004-07-10 06:13:00 -0700977
Mark Pizzolato45246a32012-03-21 06:14:01 -0700978 2. SRQ is denied because neither IFIN nor IFOUT is asserted when the
979 interface is not selected.
Bob Supnik9c4779c2009-02-08 09:06:00 -0800980*/
981
Bob Supnike2ba6722004-07-10 06:13:00 -0700982t_stat ds_reset (DEVICE *dptr)
983{
Mark Pizzolato45246a32012-03-21 06:14:01 -0700984uint32 unit;
985
986if (sim_switches & SWMASK ('P')) { /* is this a power-on reset? */
987 ds.fifo_reg = find_reg ("FIFO", NULL, dptr); /* find the FIFO register entry */
988
989 if (ds.fifo_reg == NULL) /* if it cannot be found, */
Mark Pizzolato40deb202012-04-04 12:31:43 -0700990 return SCPE_IERR; /* report a programming error */
Mark Pizzolato45246a32012-03-21 06:14:01 -0700991
992 else { /* found it */
993 ds.fifo_reg->qptr = 0; /* so reset the FIFO bottom index */
994 ds.fifo_count = 0; /* and clear the FIFO */
995 }
996
997 for (unit = 0; unit < dptr->numunits; unit++) { /* loop through all of the units */
998 sim_cancel (dptr->units + unit); /* cancel activation */
999 dptr->units [unit].CYL = 0; /* reset the head position to cylinder 0 */
1000 dptr->units [unit].pos = 0; /* (irrelevant for the controller and timer) */
1001 }
1002 }
1003
1004IOPRESET (&ds_dib); /* PRESET the device */
Mark Pizzolatofffad7c2012-03-19 16:05:24 -07001005ds.srq = CLEAR; /* clear SRQ */
Mark Pizzolato45246a32012-03-21 06:14:01 -07001006
Bob Supnik9c4779c2009-02-08 09:06:00 -08001007return SCPE_OK;
Bob Supnike2ba6722004-07-10 06:13:00 -07001008}
Bob Supnik9c4779c2009-02-08 09:06:00 -08001009
Bob Supnike2ba6722004-07-10 06:13:00 -07001010
Mark Pizzolato45246a32012-03-21 06:14:01 -07001011/* Attach a drive unit.
1012
1013 The specified file is attached to the indicated drive unit. The library
1014 attach routine will load the heads. This will set the First Status and
1015 Attention bits in the drive status, so we poll the drives to ensure that the
1016 CPU is notified that the drive is now online.
1017
Mark Pizzolato486427c2018-06-03 14:38:38 -07001018 If a new file is specified, the file is initialized to its capacity by
1019 writing a zero to the last byte in the file.
1020
Mark Pizzolato45246a32012-03-21 06:14:01 -07001021
1022 Implementation notes:
1023
1024 1. If we are called during a RESTORE command, the drive status will not be
1025 changed, so polling the drives will have no effect.
Mark Pizzolato486427c2018-06-03 14:38:38 -07001026
1027 2. The C standard says, "A binary stream need not meaningfully support fseek
1028 calls with a whence value of SEEK_END," so instead we determine the
1029 offset from the start of the file to the last byte and seek there.
Mark Pizzolato45246a32012-03-21 06:14:01 -07001030*/
Bob Supnike2ba6722004-07-10 06:13:00 -07001031
Mark Pizzolato5531ccb2016-05-15 15:25:33 -07001032t_stat ds_attach (UNIT *uptr, CONST char *cptr)
Bob Supnike2ba6722004-07-10 06:13:00 -07001033{
Mark Pizzolato486427c2018-06-03 14:38:38 -07001034t_stat result;
1035t_addr offset;
1036const uint8 zero = 0;
Bob Supnike2ba6722004-07-10 06:13:00 -07001037
Mark Pizzolato45246a32012-03-21 06:14:01 -07001038result = dl_attach (&mac_cntlr, uptr, cptr); /* attach the drive */
1039
Mark Pizzolato486427c2018-06-03 14:38:38 -07001040if (result == SCPE_OK) { /* if the attach was successful */
1041 poll_drives (); /* then poll the drives to notify the CPU */
Mark Pizzolato45246a32012-03-21 06:14:01 -07001042
Mark Pizzolato486427c2018-06-03 14:38:38 -07001043 if (sim_switches & SWMASK ('N')) { /* if this is a new disc image */
1044 offset = (t_addr) /* then determine the offset of */
1045 (uptr->capac * sizeof (int16) - sizeof zero); /* the last byte in a full-sized file */
1046
1047 if (sim_fseek (uptr->fileref, offset, SEEK_SET) != 0 /* seek to the last byte */
1048 || fwrite (&zero, sizeof zero, 1, uptr->fileref) == 0 /* and write a zero to fill */
1049 || fflush (uptr->fileref) != 0) /* the file to its capacity */
1050 clearerr (uptr->fileref); /* clear and ignore any errors */
1051 }
1052 }
1053
1054return result; /* return the result of the attach */
Bob Supnike2ba6722004-07-10 06:13:00 -07001055}
1056
Bob Supnik9c4779c2009-02-08 09:06:00 -08001057
Mark Pizzolato45246a32012-03-21 06:14:01 -07001058/* Detach a drive unit.
1059
1060 The specified file is detached from the indicated drive unit. The library
1061 detach routine will unload the heads. This will set the Attention bit in the
1062 drive status, so we poll the drives to ensure that the CPU is notified that
1063 the drive is now offline.
1064*/
Bob Supnike2ba6722004-07-10 06:13:00 -07001065
1066t_stat ds_detach (UNIT *uptr)
1067{
Mark Pizzolato45246a32012-03-21 06:14:01 -07001068t_stat result;
1069
1070result = dl_detach (&mac_cntlr, uptr); /* detach the drive */
1071
1072if (result == SCPE_OK) /* was the detach successful? */
1073 poll_drives (); /* poll the drives to notify the CPU */
1074
1075return result;
Bob Supnike2ba6722004-07-10 06:13:00 -07001076}
Bob Supnik9c4779c2009-02-08 09:06:00 -08001077
Bob Supnike2ba6722004-07-10 06:13:00 -07001078
Mark Pizzolato486427c2018-06-03 14:38:38 -07001079/* MAC disc bootstrap loaders (BMDL and 12992B).
Bob Supnikec60bbf2005-05-03 04:10:00 -07001080
Mark Pizzolato486427c2018-06-03 14:38:38 -07001081 The Basic Moving-Head Disc Loader (BMDL) consists of two programs. The
1082 program starting at address x7700 loads absolute paper tapes into memory.
1083 The program starting at address x7750 loads a disc-resident bootstrap from
1084 the MAC disc drive into memory. The S register specifies the head to use.
Mark Pizzolato45246a32012-03-21 06:14:01 -07001085
Mark Pizzolato486427c2018-06-03 14:38:38 -07001086 For a 2100/14/15/16 CPU, entering a LOAD DS or BOOT DS command loads the BMDL
1087 into memory and executes the disc portion starting at x7750. The bootstrap
1088 reads 2047 words from cylinder 0 sector 0 of the specified head into memory
1089 starting at location 2011 octal. Loader execution ends with one of the
1090 following instructions:
Mark Pizzolato45246a32012-03-21 06:14:01 -07001091
Mark Pizzolato486427c2018-06-03 14:38:38 -07001092 * HLT 11B - the disc read failed.
1093 * JSB 2055,I - the disc read completed.
1094
1095 The HP 1000 uses the 12992B boot loader ROM to bootstrap the disc. The head
1096 number is obtained from bits 2-0 of the existing S-register value when the
1097 loader is executed. Bits 5-3 of the existing S-register value are also
1098 retained and are available to the boot extension program. The loader reads
1099 6144 words from cylinder 0 sector 0 of the specified head into memory
1100 starting at location 2011 octal. Loader execution ends with one of the
1101 following instructions:
1102
1103 * HLT 30 - the drive is not ready..
1104 * JSB 2055,I - the disc read succeeded.
1105
1106 The loader automatically retries the operations for all disc errors other
1107 than a drive fault.
Bob Supnikec60bbf2005-05-03 04:10:00 -07001108
Bob Supnik9c4779c2009-02-08 09:06:00 -08001109
Mark Pizzolato45246a32012-03-21 06:14:01 -07001110 Implementation notes:
Bob Supnike2ba6722004-07-10 06:13:00 -07001111
Mark Pizzolato486427c2018-06-03 14:38:38 -07001112 1. After the BMDL has been loaded into memory, the paper tape portion may be
1113 executed manually by setting the P register to the starting address
1114 (x7700).
1115
1116 2. For compatibility with the "cpu_copy_loader" routine, the BMDL device I/O
1117 instructions address select codes 10 and 11.
Mark Pizzolato45246a32012-03-21 06:14:01 -07001118*/
Bob Supnike2ba6722004-07-10 06:13:00 -07001119
Mark Pizzolato486427c2018-06-03 14:38:38 -07001120static const LOADER_ARRAY ds_loaders = {
1121 { /* HP 21xx Basic Moving-Head Disc Loader (BMDL-7905) */
1122 050, /* loader starting index */
1123 076, /* DMA index */
1124 034, /* FWA index */
1125 { 0002401, /* 77700: PTAPE CLA,RSS Paper Tape start */
1126 0063722, /* 77701: LDA 77722 */
1127 0107700, /* 77702: CLC 0,C */
1128 0002307, /* 77703: CCE,INA,SZA,RSS */
1129 0102077, /* 77704: HLT 77 */
1130 0017735, /* 77705: JSB 77735 */
1131 0007307, /* 77706: CMB,CCE,INB,SZB,RSS */
1132 0027702, /* 77707: JMP 77702 */
1133 0077733, /* 77710: STB 77733 */
1134 0017735, /* 77711: JSB 77735 */
1135 0017735, /* 77712: JSB 77735 */
1136 0074000, /* 77713: STB 0 */
1137 0077747, /* 77714: STB 77747 */
1138 0047734, /* 77715: ADB 77734 */
1139 0002140, /* 77716: SEZ,CLE */
1140 0102055, /* 77717: HLT 55 */
1141 0017735, /* 77720: JSB 77735 */
1142 0040001, /* 77721: ADA 1 */
1143 0177747, /* 77722: STB 77747,I */
1144 0067747, /* 77723: LDB 77747 */
1145 0006104, /* 77724: CLE,INB */
1146 0037733, /* 77725: ISZ 77733 */
1147 0027714, /* 77726: JMP 77714 */
1148 0017735, /* 77727: JSB 77735 */
1149 0054000, /* 77730: CPB 0 */
1150 0027701, /* 77731: JMP 77701 */
1151 0102011, /* 77732: HLT 11 */
1152 0000000, /* 77733: NOP */
1153 0100100, /* 77734: RRL 16 */
1154 0000000, /* 77735: NOP */
1155 0006400, /* 77736: CLB */
1156 0103710, /* 77737: STC 10,C */
1157 0102310, /* 77740: SFS 10 */
1158 0027740, /* 77741: JMP 77740 */
1159 0106410, /* 77742: MIB 10 */
1160 0002240, /* 77743: SEZ,CME */
1161 0127735, /* 77744: JMP 77735,I */
1162 0005727, /* 77745: BLF,BLF */
1163 0027737, /* 77746: JMP 77737 */
1164 0000000, /* 77747: NOP */
1165 0067777, /* 77750: DISC LDB 77777 */
1166 0174001, /* 77751: STB 1,I */
1167 0006004, /* 77752: INB */
1168 0063732, /* 77753: LDA 77732 */
1169 0170001, /* 77754: STA 1,I */
1170 0067776, /* 77755: LDB 77776 */
1171 0106606, /* 77756: OTB 6 */
1172 0106702, /* 77757: CLC 2 */
1173 0102602, /* 77760: OTA 2 */
1174 0102702, /* 77761: STC 2 */
1175 0063751, /* 77762: LDA 77751 */
1176 0102602, /* 77763: OTA 2 */
1177 0102501, /* 77764: LIA 1 */
1178 0001027, /* 77765: ALS,ALF */
1179 0013767, /* 77766: AND 77767 */
1180 0000160, /* 77767: CLE,ALS */
1181 0106710, /* 77770: CLC 10 */
1182 0103610, /* 77771: OTA 10,C */
1183 0103706, /* 77772: STC 6,C */
1184 0102310, /* 77773: SFS 10 */
1185 0027773, /* 77774: JMP 77773 */
1186 0117717, /* 77775: JSB 77717,I */
1187 0000010, /* 77776: SLA */
1188 0002055 } }, /* 77777: SEZ,SLA,INA,RSS */
Bob Supnike2ba6722004-07-10 06:13:00 -07001189
Mark Pizzolato486427c2018-06-03 14:38:38 -07001190 { /* HP 1000 Loader ROM (12992B) */
1191 IBL_START, /* loader starting index */
1192 IBL_DMA, /* DMA index */
1193 IBL_FWA, /* FWA index */
1194 { 0017727, /* 77700: START JSB STAT GET STATUS */
1195 0002021, /* 77701: SSA,RSS IS DRIVE READY ? */
1196 0027742, /* 77702: JMP DMA YES, SET UP DMA */
1197 0013714, /* 77703: AND B20 NO, CHECK STATUS BITS */
1198 0002002, /* 77704: SZA IS DRIVE FAULTY OR HARD DOWN ? */
1199 0102030, /* 77705: HLT 30B YES, HALT 30B, "RUN" TO TRY AGAIN */
1200 0027700, /* 77706: JMP START NO, TRY AGAIN FOR DISC READY */
1201 0102011, /* 77707: ADDR1 OCT 102011 */
1202 0102055, /* 77710: ADDR2 OCT 102055 */
1203 0164000, /* 77711: CNT DEC -6144 */
1204 0000007, /* 77712: D7 OCT 7 */
1205 0001400, /* 77713: STCMD OCT 1400 */
1206 0000020, /* 77714: B20 OCT 20 */
1207 0017400, /* 77715: STMSK OCT 17400 */
1208 0000000, /* 77716: NOP */
1209 0000000, /* 77717: NOP */
1210 0000000, /* 77720: NOP */
1211 0000000, /* 77721: NOP */
1212 0000000, /* 77722: NOP */
1213 0000000, /* 77723: NOP */
1214 0000000, /* 77724: NOP */
1215 0000000, /* 77725: NOP */
1216 0000000, /* 77726: NOP */
1217 0000000, /* 77727: STAT NOP STATUS CHECK SUBROUTINE */
1218 0107710, /* 77730: CLC DC,C SET STATUS COMMAND MODE */
1219 0063713, /* 77731: LDA STCMD GET STATUS COMMAND */
1220 0102610, /* 77732: OTA DC OUTPUT STATUS COMMAND */
1221 0102310, /* 77733: SFS DC WAIT FOR STATUS#1 WORD */
1222 0027733, /* 77734: JMP *-1 */
1223 0107510, /* 77735: LIB DC,C B-REG = STATUS#1 WORD */
1224 0102310, /* 77736: SFS DC WAIT FOR STATUS#2 WORD */
1225 0027736, /* 77737: JMP *-1 */
1226 0103510, /* 77740: LIA DC,C A-REG = STATUS#2 WORD */
1227 0127727, /* 77741: JMP STAT,I RETURN */
1228 0067776, /* 77742: DMA LDB DMACW GET DMA CONTROL WORD */
1229 0106606, /* 77743: OTB 6 OUTPUT DMA CONTROL WORD */
1230 0067707, /* 77744: LDB ADDR1 GET MEMORY ADDRESS */
1231 0106702, /* 77745: CLC 2 SET MEMORY ADDRESS INPUT MODE */
1232 0106602, /* 77746: OTB 2 OUTPUT MEMORY ADDRESS TO DMA */
1233 0102702, /* 77747: STC 2 SET WORD COUNT INPUT MODE */
1234 0067711, /* 77750: LDB CNT GET WORD COUNT */
1235 0106602, /* 77751: OTB 2 OUTPUT WORD COUNT TO DMA */
1236 0106710, /* 77752: CLDLD CLC DC SET COMMAND INPUT MODE */
1237 0102501, /* 77753: LIA 1 LOAD SWITCH */
1238 0106501, /* 77754: LIB 1 REGISTER SETTINGS */
1239 0013712, /* 77755: AND D7 ISOLATE HEAD NUMBER */
1240 0005750, /* 77756: BLF,CLE,SLB BIT 12=0? */
1241 0027762, /* 77757: JMP *+3 NO,MANUAL BOOT */
1242 0002002, /* 77760: SZA YES,RPL BOOT. HEAD#=0? */
1243 0001000, /* 77761: ALS NO,HEAD#1, MAKE HEAD#=2 */
1244 0001720, /* 77762: ALF,ALS FORM COLD LOAD */
1245 0001000, /* 77763: ALS COMMAND WORD */
1246 0103706, /* 77764: STC 6,C ACTIVATE DMA */
1247 0103610, /* 77765: OTA DC,C OUTPUT COLD LOAD COMMAND */
1248 0102310, /* 77766: SFS DC IS COLD LOAD COMPLETED ? */
1249 0027766, /* 77767: JMP *-1 NO, WAIT */
1250 0017727, /* 77770: JSB STAT YES, GET STATUS */
1251 0060001, /* 77771: LDA 1 */
1252 0013715, /* 77772: AND STMSK A-REG = STATUS BITS OF STATUS#1 WD */
1253 0002002, /* 77773: SZA IS TRANSFER OK ? */
1254 0027700, /* 77774: JMP START NO,TRY AGAIN */
1255 0117710, /* 77775: EXIT JSB ADDR2,I YES, EXEC LOADED PROGRAM @ 2055B */
1256 0000010, /* 77776: DMACW ABS DC */
1257 0170100 } } /* 77777: ABS -START */
Bob Supnikb7c1eae2005-09-09 18:09:00 -07001258 };
Mark Pizzolato486427c2018-06-03 14:38:38 -07001259
1260
1261/* Device boot routine.
1262
1263 This routine is called directly by the BOOT DS and LOAD DS commands to copy
1264 the device bootstrap into the upper 64 words of the logical address space.
1265 It is also called indirectly by a BOOT CPU or LOAD CPU command when the
1266 specified HP 1000 loader ROM socket contains a 12992B ROM.
1267
1268 When called in response to a BOOT DS or LOAD DS command, the "unitno"
1269 parameter indicates the unit number specified in the BOOT command or is zero
1270 for the LOAD command, and "dptr" points at the DS device structure. The
1271 bootstrap supports loading only from unit 0, and the command will be rejected
1272 if another unit is specified (e.g., BOOT DS1). Otherwise, depending on the
1273 current CPU model, the BMDL or 12992B loader ROM will be copied into memory
1274 and configured for the DS select code. If the CPU is a 1000, the S register
1275 will be set as it would be by the front-panel microcode.
1276
1277 When called for a BOOT/LOAD CPU command, the "unitno" parameter indicates the
1278 select code to be used for configuration, and "dptr" will be NULL. As above,
1279 the BMDL or 12992B loader ROM will be copied into memory and configured for
1280 the specified select code. The S register is assumed to be set correctly on
1281 entry and is not modified.
1282
1283 In either case, if the CPU is a 21xx model, the paper tape portion of the
1284 BMDL will be automatically configured for the select code of the paper tape
1285 reader.
1286
1287 For the 12992B boot loader ROM for the HP 1000, the S register is set as
1288 follows:
1289
1290 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
1291 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1292 | ROM # | 0 1 | select code | reserved | 0 | head |
1293 +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
1294
1295 Bit 12 must be 1 for a manual boot. Bits 5-3 are nominally zero but are
1296 reserved for the target operating system. For example, RTE uses bit 5 to
1297 indicate whether a standard (0) or reconfiguration (1) boot is desired.
1298
1299
1300 Implementation notes:
1301
1302 1. In hardware, the BMDL was hand-configured for the disc and paper tape
1303 reader select codes when it was installed on a given system. Under
1304 simulation, the LOAD and BOOT commands automatically configure the BMDL
1305 to the current select codes of the PTR and DS devices.
1306
1307 2. The HP 1000 Loader ROMs manual indicates that bits 2-0 select the head to
1308 use, implying that heads 0-7 are valid. However, Table 5 has entries
1309 only for heads 0-3, and the boot loader code will malfunction if heads
1310 4-7 are specified. The code masks the head number to three bits but
1311 forms the Cold Load Read command by shifting the head number six bits to
1312 the left. As the head field in the command is only two bits wide,
1313 specifying heads 4-7 will result in bit 2 being shifted into the opcode
1314 field, resulting in a Recalibrate command.
1315*/
Bob Supnike2ba6722004-07-10 06:13:00 -07001316
1317t_stat ds_boot (int32 unitno, DEVICE *dptr)
1318{
Mark Pizzolato486427c2018-06-03 14:38:38 -07001319static const HP_WORD ds_preserved = 0000073u; /* S-register bits 5-3 and 1-0 are preserved */
1320static const HP_WORD ds_manual_boot = 0010000u; /* S-register bit 12 set for a manual boot */
Bob Supnike2ba6722004-07-10 06:13:00 -07001321
Mark Pizzolato486427c2018-06-03 14:38:38 -07001322if (dptr == NULL) /* if we are being called for a BOOT/LOAD CPU */
1323 return cpu_copy_loader (ds_loaders, unitno, /* then copy the boot loader to memory */
1324 IBL_S_NOCLEAR, IBL_S_NOSET); /* but do not alter the S register */
Mark Pizzolatoa6552b82017-09-06 22:16:14 -07001325
Mark Pizzolato486427c2018-06-03 14:38:38 -07001326else if (unitno != 0) /* otherwise a BOOT DS for a non-zero unit */
1327 return SCPE_NOFNC; /* is rejected as unsupported */
1328
1329else /* otherwise this is a BOOT/LOAD DS */
1330 return cpu_copy_loader (ds_loaders, ds_dib.select_code, /* so copy the boot loader to memory */
1331 ds_preserved, ds_manual_boot); /* and configure the S register if 1000 CPU */
Bob Supnike2ba6722004-07-10 06:13:00 -07001332}
Mark Pizzolato45246a32012-03-21 06:14:01 -07001333
1334
1335
1336/* MAC disc global SCP routines */
1337
1338
1339/* Load or unload the drive heads.
1340
1341 The SCP command SET DSn UNLOADED simulates setting the hardware RUN/STOP
1342 switch to STOP. The heads are unloaded, and the drive is spun down.
1343
1344 The SET DSn LOADED command simulates setting the switch to RUN. The drive is
1345 spun up, and the heads are loaded.
1346
1347 The library handles command validation and setting the appropriate drive unit
1348 status.
1349*/
1350
Mark Pizzolato5531ccb2016-05-15 15:25:33 -07001351t_stat ds_load_unload (UNIT *uptr, int32 value, CONST char *cptr, void *desc)
Mark Pizzolato45246a32012-03-21 06:14:01 -07001352{
Mark Pizzolato40deb202012-04-04 12:31:43 -07001353const t_bool load = (value != UNIT_UNLOAD); /* true if the heads are loading */
Mark Pizzolato45246a32012-03-21 06:14:01 -07001354
1355return dl_load_unload (&mac_cntlr, uptr, load); /* load or unload the heads */
1356}
1357
1358
1359
1360/* MAC disc local utility routines */
1361
1362
1363/* Start a command.
1364
1365 The previously prepared command is executed by calling the corresponding
1366 library routine. On entry, the controller's opcode field contains the
1367 command to start, and the buffer contains the command word in element 0 and
1368 the parameters required by the command, if any, beginning in element 1.
1369
1370 If the command started, the returned pointer will point at the unit to
1371 activate (if that unit's "wait" field is non-zero). If the returned pointer
1372 is NULL, the command failed to start, and the controller status has been set
1373 to indicate the reason. The interface flag is set to notify the CPU of the
1374 failure.
1375
1376
1377 Implementation notes:
1378
1379 1. If a command that accesses the drive is attempted on a drive currently
1380 seeking, the returned pointer will be valid, but the unit's "wait" time
1381 will be zero. The unit must not be activated (as it already is active).
1382 When the seek completes, the command will be executed automatically.
1383
1384 If a Seek or Cold Load Read command is attempted on a drive currently
1385 seeking, seek completion will occur normally, but Seek Check status will
1386 be set.
1387
1388 2. For debug printouts, we want to print the name of the command (Seek or
1389 Recalibrate) in progress when a new command is started. However, when
1390 the library routine returns, the unit operation and controller opcode
1391 have been changed to reflect the new command. Therefore, we must record
1392 the operation in progress before calling the library.
1393
1394 The problem is in determining which unit's operation code to record. We
1395 cannot blindly use the unit field from the new command, as recorded in
1396 the controller, as preparation has ensured only that the target unit
1397 number is legal but not necessarily valid. Therefore, we must validate
1398 the unit number before accessing the unit's operation code.
1399
1400 If the unit number is invalid, the command will not start, but the
1401 compiler does not know this. Therefore, we must ensure that the saved
1402 operation code is initialized, or a "variable used uninitialized" warning
1403 will occur.
1404*/
1405
1406static void start_command (void)
1407{
1408int32 unit, time;
1409UNIT *uptr;
1410CNTLR_OPCODE drive_command;
1411
1412unit = GET_S1UNIT (mac_cntlr.spd_unit); /* get the (prepared) unit from the command */
1413
1414if (unit <= DL_MAXDRIVE) /* is the unit number valid? */
1415 drive_command = (CNTLR_OPCODE) ds_unit [unit].OP; /* get the opcode from the unit that will be used */
1416else /* the unit is invalid, so the command will not start */
Mark Pizzolatoef147d22012-10-24 12:57:37 -07001417 drive_command = End; /* but the compiler doesn't know this! */
Mark Pizzolato45246a32012-03-21 06:14:01 -07001418
1419uptr = dl_start_command (&mac_cntlr, ds_unit, DL_MAXDRIVE); /* ask the controller to start the command */
1420
1421if (uptr) { /* did the command start? */
1422 time = uptr->wait; /* save the activation time */
1423
1424 if (time) /* was the unit scheduled? */
Mark Pizzolato40deb202012-04-04 12:31:43 -07001425 activate_unit (uptr); /* activate it (and clear the "wait" field) */
Mark Pizzolato45246a32012-03-21 06:14:01 -07001426
Mark Pizzolatoa6552b82017-09-06 22:16:14 -07001427 if (time == 0) /* was the unit busy? */
1428 tprintf (ds_dev, DEB_RWSC, "Unit %d %s in progress\n",
1429 uptr - ds_unit, dl_opcode_name (MAC, drive_command));
Mark Pizzolato45246a32012-03-21 06:14:01 -07001430
Mark Pizzolatoa6552b82017-09-06 22:16:14 -07001431 if (uptr - ds_unit > DL_MAXDRIVE)
1432 tprintf (ds_dev, DEB_RWSC, "Controller %s command initiated\n",
Mark Pizzolato45246a32012-03-21 06:14:01 -07001433 dl_opcode_name (MAC, mac_cntlr.opcode));
Mark Pizzolatoa6552b82017-09-06 22:16:14 -07001434 else
1435 tprintf (ds_dev, DEB_RWSC, "Unit %d position %" T_ADDR_FMT "d %s command initiated\n",
1436 uptr - ds_unit, uptr->pos, dl_opcode_name (MAC, mac_cntlr.opcode));
Mark Pizzolato45246a32012-03-21 06:14:01 -07001437 }
1438
1439else /* the command failed to start */
1440 ds_io (&ds_dib, ioENF, 0); /* so set the flag to notify the CPU */
1441
1442return;
1443}
1444
1445
1446/* Poll the interface for a new command.
1447
1448 If a new command is available, and the controller is not busy, prepare the
1449 command for execution. If preparation succeeded, and the command needs
1450 parameters before executing, set the flag to request the first one from the
1451 CPU. If no parameters are needed, the command is ready to execute.
1452
1453 If preparation failed, set the flag to notify the CPU. The controller
1454 status contains the reason for the failure.
1455*/
1456
1457static void poll_interface (void)
1458{
1459if (ds.cmrdy == SET && mac_cntlr.state != cntlr_busy) { /* are the interface and controller ready? */
1460 buffer [0] = fifo_unload (); /* unload the command into the buffer */
1461
1462 if (dl_prepare_command (&mac_cntlr, ds_unit, DL_MAXDRIVE)) { /* prepare the command; did it succeed? */
1463 if (mac_cntlr.length) /* does the command require parameters? */
1464 ds_io (&ds_dib, ioENF, 0); /* set the flag to request the first one */
1465 else /* if not waiting for parameters */
1466 start_command (); /* start the command */
1467 }
1468
1469 else /* preparation failed */
1470 ds_io (&ds_dib, ioENF, 0); /* so set the flag to notify the CPU */
1471
1472 ds.cmrdy = CLEAR; /* flush the command from the interface */
1473 }
1474
1475return;
1476}
1477
1478
1479/* Poll the drives for attention requests.
1480
1481 If the controller is idle and interrupts are allowed, the drives are polled
1482 to see if any drive is requesting attention. If one is found, the controller
1483 resets that drive's Attention status, saves the drive's unit number, sets
1484 Drive Attention status, and waits for a command from the CPU. The interface
1485 sets the flag to notify the CPU.
1486*/
1487
Mark Pizzolatoa262dd92013-03-19 01:11:22 -07001488static void poll_drives (void)
Mark Pizzolato45246a32012-03-21 06:14:01 -07001489{
Mark Pizzolato40deb202012-04-04 12:31:43 -07001490if (mac_cntlr.state == cntlr_idle && ds.control == SET) /* is the controller idle and interrupts are allowed? */
1491 if (dl_poll_drives (&mac_cntlr, ds_unit, DL_MAXDRIVE)) /* poll the drives; was Attention seen? */
Mark Pizzolato45246a32012-03-21 06:14:01 -07001492 ds_io (&ds_dib, ioENF, 0); /* request an interrupt */
1493return;
1494}
1495
1496
1497/* Load a word into the FIFO.
1498
1499 A word is loaded into the next available location in the FIFO, and the FIFO
1500 occupancy count is incremented. If the FIFO is full on entry, the load is
1501 ignored.
1502
1503
1504 Implementation notes:
1505
1506 1. The FIFO is implemented as circular queue to take advantage of REG_CIRC
1507 EXAMINE semantics. REG->qptr is the index of the first word currently in
1508 the FIFO. By specifying REG_CIRC, examining FIFO[0-n] will always
1509 display the words in load order, regardless of the actual array index of
1510 the start of the list. The number of words currently present in the FIFO
1511 is kept in fifo_count (0 = empty, 1-16 = number of words available).
1512
1513 If fifo_count < FIFO_SIZE, (REG->qptr + fifo_count) mod FIFO_SIZE is the
1514 index of the new word location. Loading stores the word there and then
1515 increments fifo_count.
1516
1517 2. Because the load and unload routines need access to qptr in the REG
1518 structure for the FIFO array, a pointer to the REG is stored in the
1519 fifo_reg variable during device reset.
1520*/
1521
1522static void fifo_load (uint16 data)
1523{
1524uint32 index;
1525
1526if (FIFO_FULL) { /* is the FIFO already full? */
Mark Pizzolatoa6552b82017-09-06 22:16:14 -07001527 tprintf (ds_dev, DEB_BUF, "Attempted load to full FIFO, data %06o\n", data);
Mark Pizzolato45246a32012-03-21 06:14:01 -07001528
1529 return; /* return with the load ignored */
1530 }
1531
1532index = (ds.fifo_reg->qptr + ds.fifo_count) % FIFO_SIZE; /* calculate the index of the next available location */
1533
1534ds.fifo [index] = data; /* store the word in the FIFO */
1535ds.fifo_count = ds.fifo_count + 1; /* increment the count of words stored */
1536
Mark Pizzolatoa6552b82017-09-06 22:16:14 -07001537tprintf (ds_dev, DEB_BUF, "Data %06o loaded into FIFO (%d)\n",
1538 data, ds.fifo_count);
Mark Pizzolato45246a32012-03-21 06:14:01 -07001539
1540return;
1541}
1542
1543
1544/* Unload a word from the FIFO.
1545
1546 A word is unloaded from the first location in the FIFO, and the FIFO
1547 occupancy count is decremented. If the FIFO is empty on entry, the unload
1548 returns dummy data.
1549
1550
1551 Implementation notes:
1552
1553 1. If fifo_count > 0, REG->qptr is the index of the word to remove. Removal
1554 gets the word and then increments qptr (mod FIFO_SIZE) and decrements
1555 fifo_count.
1556*/
1557
1558static uint16 fifo_unload (void)
1559{
1560uint16 data;
1561
1562if (FIFO_EMPTY) { /* is the FIFO already empty? */
Mark Pizzolatoa6552b82017-09-06 22:16:14 -07001563 tprintf (ds_dev, DEB_BUF, "Attempted unload from empty FIFO\n");
Mark Pizzolato45246a32012-03-21 06:14:01 -07001564 return 0; /* return with no data */
1565 }
1566
1567data = ds.fifo [ds.fifo_reg->qptr]; /* get the word from the FIFO */
1568
1569ds.fifo_reg->qptr = (ds.fifo_reg->qptr + 1) % FIFO_SIZE; /* update the FIFO queue pointer */
1570ds.fifo_count = ds.fifo_count - 1; /* decrement the count of words stored */
1571
Mark Pizzolatoa6552b82017-09-06 22:16:14 -07001572tprintf (ds_dev, DEB_BUF, "Data %06o unloaded from FIFO (%d)\n",
1573 data, ds.fifo_count);
Mark Pizzolato45246a32012-03-21 06:14:01 -07001574
1575return data;
1576}
1577
1578
1579/* Clear the FIFO.
1580
1581 The FIFO is cleared by setting the occupancy counter to zero.
1582*/
1583
1584static void fifo_clear (void)
1585{
1586ds.fifo_count = 0; /* clear the FIFO */
1587
Mark Pizzolatoa6552b82017-09-06 22:16:14 -07001588tprintf (ds_dev, DEB_BUF, "FIFO cleared\n");
Mark Pizzolato45246a32012-03-21 06:14:01 -07001589
1590return;
1591}
1592
1593
1594/* Activate the unit.
1595
1596 The specified unit is activated using the unit's "wait" time. If debugging
1597 is enabled, the activation is logged to the debug file.
1598*/
1599
1600static t_stat activate_unit (UNIT *uptr)
1601{
Mark Pizzolato45246a32012-03-21 06:14:01 -07001602t_stat result;
1603
Mark Pizzolatoa6552b82017-09-06 22:16:14 -07001604if (uptr == &ds_cntlr)
1605 tprintf (ds_dev, DEB_SERV, "Controller delay %d service scheduled\n",
1606 uptr->wait);
1607else
1608 tprintf (ds_dev, DEB_SERV, "Unit %d delay %d service scheduled\n",
1609 uptr - ds_unit, uptr->wait);
Mark Pizzolato45246a32012-03-21 06:14:01 -07001610
1611result = sim_activate (uptr, uptr->wait); /* activate the unit */
1612uptr->wait = 0; /* reset the activation time */
1613
1614return result; /* return the activation status */
1615}