Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1 | /* hp2100_ds.c: HP 13037D/13175D disc controller/interface simulator
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 2 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 3 | Copyright (c) 2004-2012, Robert M. Supnik
|
Mark Pizzolato | 486427c | 2018-06-03 14:38:38 -0700 | [diff] [blame] | 4 | Copyright (c) 2012-2018 J. David Bryan
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 5 |
|
| 6 | Permission is hereby granted, free of charge, to any person obtaining a
|
| 7 | copy of this software and associated documentation files (the "Software"),
|
| 8 | to deal in the Software without restriction, including without limitation
|
| 9 | the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
| 10 | and/or sell copies of the Software, and to permit persons to whom the
|
| 11 | Software is furnished to do so, subject to the following conditions:
|
| 12 |
|
| 13 | The above copyright notice and this permission notice shall be included in
|
| 14 | all copies or substantial portions of the Software.
|
| 15 |
|
| 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
| 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
| 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 19 | THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 20 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
| 21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
| 22 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 23 | Except as contained in this notice, the names of the authors shall not be
|
Bob Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 24 | used in advertising or otherwise to promote the sale, use or other dealings
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 25 | in this Software without prior written authorization from the authors.
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 26 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 27 | DS 13037D/13175D disc controller/interface
|
Bob Supnik | ec60bbf | 2005-05-03 04:10:00 -0700 | [diff] [blame] | 28 |
|
Mark Pizzolato | 486427c | 2018-06-03 14:38:38 -0700 | [diff] [blame] | 29 | 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 Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 32 | 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 Pizzolato | 5531ccb | 2016-05-15 15:25:33 -0700 | [diff] [blame] | 37 | 13-May-16 JDB Modified for revised SCP API function parameter types
|
Mark Pizzolato | 53b6809 | 2016-03-07 20:42:19 -0800 | [diff] [blame] | 38 | 04-Mar-16 JDB Name changed to "hp2100_disclib" until HP 3000 integration
|
Mark Pizzolato | ecbb20f | 2015-01-08 03:39:22 -0800 | [diff] [blame] | 39 | 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 Pizzolato | a262dd9 | 2013-03-19 01:11:22 -0700 | [diff] [blame] | 41 | 18-Mar-13 JDB Fixed poll_drives definition to match declaration
|
Mark Pizzolato | ef147d2 | 2012-10-24 12:57:37 -0700 | [diff] [blame] | 42 | 24-Oct-12 JDB Changed CNTLR_OPCODE to title case to avoid name clash
|
Mark Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 43 | 29-Mar-12 JDB Rewritten to use the MAC/ICD disc controller library
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 44 | 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 Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 51 | 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 Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 58 | 26-Jun-08 JDB Rewrote device I/O to model backplane signals
|
Bob Supnik | 59aa4a7 | 2008-06-24 14:21:00 -0700 | [diff] [blame] | 59 | 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 Supnik | 53d02f7 | 2007-02-03 14:59:00 -0800 | [diff] [blame] | 62 | 03-Aug-06 JDB Fixed REQUEST STATUS command to clear status-1
|
| 63 | Removed redundant attached test in "ds_detach"
|
Bob Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 64 | 18-Mar-05 RMS Added attached test to detach routine
|
| 65 | 01-Mar-05 JDB Added SET UNLOAD/LOAD
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 66 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 67 | References:
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 68 | - 13037 Disc Controller Technical Information Package (13037-90902, Aug-1980)
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 69 | - 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 Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 72 |
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 73 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 74 | 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 Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 77 | 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 Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 81 |
|
Mark Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 82 | 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 Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 85 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 86 | 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 Supnik | 9b5c8c9 | 2005-01-09 13:55:00 -0800 | [diff] [blame] | 91 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 92 | 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 Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 100 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 101 | 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 Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 128 | */
|
| 129 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 130 |
|
| 131 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 132 | #include "hp2100_defs.h"
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 133 | #include "hp2100_cpu.h"
|
Mark Pizzolato | 53b6809 | 2016-03-07 20:42:19 -0800 | [diff] [blame] | 134 | #include "hp2100_disclib.h"
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 135 |
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 136 |
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 137 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 138 | /* Program constants */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 139 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 140 | #define DS_DRIVES (DL_MAXDRIVE + 1) /* number of disc drive units */
|
| 141 | #define DS_UNITS (DS_DRIVES + DL_AUXUNITS) /* total number of units */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 142 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 143 | #define ds_cntlr ds_unit [DL_MAXDRIVE + 1] /* controller unit alias */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 144 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 145 | #define FIFO_SIZE 16 /* FIFO depth */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 146 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 147 | #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 Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 150 |
|
Mark Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 151 | #define PRESET_ENABLE TRUE /* Preset Jumper (W4) is enabled */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 152 |
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 153 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 154 | /* Per-card state variables */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 155 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 156 | typedef struct {
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 157 | FLIP_FLOP control; /* control flip-flop */
|
| 158 | FLIP_FLOP flag; /* flag flip-flop */
|
| 159 | FLIP_FLOP flagbuf; /* flag buffer flip-flop */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 160 | 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 Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 168 |
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 169 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 170 | /* MAC disc state variables */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 171 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 172 | static UNIT ds_unit [DS_UNITS]; /* unit array */
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 173 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 174 | static CARD_STATE ds; /* card state */
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 175 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 176 | static uint16 buffer [DL_BUFSIZE]; /* command/status/sector buffer */
|
| 177 |
|
| 178 | static CNTLR_VARS mac_cntlr = /* MAC controller */
|
| 179 | { CNTLR_INIT (MAC, buffer, &ds_cntlr) };
|
| 180 |
|
| 181 |
|
| 182 |
|
| 183 | /* MAC disc global VM routines */
|
| 184 |
|
| 185 | IOHANDLER ds_io;
|
| 186 | t_stat ds_service_drive (UNIT *uptr);
|
| 187 | t_stat ds_service_controller (UNIT *uptr);
|
| 188 | t_stat ds_service_timer (UNIT *uptr);
|
| 189 | t_stat ds_reset (DEVICE *dptr);
|
Mark Pizzolato | 5531ccb | 2016-05-15 15:25:33 -0700 | [diff] [blame] | 190 | t_stat ds_attach (UNIT *uptr, CONST char *cptr);
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 191 | t_stat ds_detach (UNIT *uptr);
|
| 192 | t_stat ds_boot (int32 unitno, DEVICE *dptr);
|
| 193 |
|
| 194 | /* MAC disc global SCP routines */
|
| 195 |
|
Mark Pizzolato | 5531ccb | 2016-05-15 15:25:33 -0700 | [diff] [blame] | 196 | t_stat ds_load_unload (UNIT *uptr, int32 value, CONST char *cptr, void *desc);
|
Bob Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 197 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 198 | /* MAC disc local utility routines */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 199 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 200 | static void start_command (void);
|
| 201 | static void poll_interface (void);
|
| 202 | static void poll_drives (void);
|
| 203 | static void fifo_load (uint16 data);
|
| 204 | static uint16 fifo_unload (void);
|
| 205 | static void fifo_clear (void);
|
| 206 | static t_stat activate_unit (UNIT *uptr);
|
| 207 |
|
| 208 |
|
| 209 |
|
| 210 | /* MAC disc VM data structures.
|
| 211 |
|
| 212 | ds_dib DS device information block
|
Bob Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 213 | ds_unit DS unit list
|
| 214 | ds_reg DS register list
|
| 215 | ds_mod DS modifier list
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 216 | 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 Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 230 | UNIT_ATT in the mask field has no adverse effect.
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 231 |
|
| 232 | 2. The modifier DEVNO is deprecated in favor of SC but is retained for
|
| 233 | compatibility.
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 234 | */
|
| 235 |
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 236 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 237 | DEVICE ds_dev;
|
| 238 |
|
| 239 | static DIB ds_dib = { &ds_io, DS };
|
| 240 |
|
| 241 | #define UNIT_FLAGS (UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | UNIT_DISABLE | UNIT_UNLOAD)
|
| 242 |
|
| 243 | static UNIT ds_unit [] = {
|
Mark Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 244 | { 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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 252 | { UDATA (&ds_service_controller, UNIT_DIS, 0) }, /* controller unit */
|
| 253 | { UDATA (&ds_service_timer, UNIT_DIS, 0) } /* timer unit */
|
Bob Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 254 | };
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 255 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 256 | static REG ds_reg [] = {
|
| 257 | { FLDATA (CMFOL, ds.cmfol, 0) },
|
| 258 | { FLDATA (CMRDY, ds.cmrdy, 0) },
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 259 | { DRDATA (FCNT, ds.fifo_count, 5) },
|
Mark Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 260 | { BRDATA (FIFO, ds.fifo, 8, 16, FIFO_SIZE), REG_CIRC },
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 261 | { 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 Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 303 | { NULL }
|
| 304 | };
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 305 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 306 | static MTAB ds_mod [] = {
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 307 | /* 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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 311 |
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 312 | { UNIT_WLK, UNIT_WLK, "protected", "PROTECT", NULL, NULL, NULL },
|
| 313 | { UNIT_WLK, 0, "unprotected", "UNPROTECT", NULL, NULL, NULL },
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 314 |
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 315 | { UNIT_WLK, UNIT_WLK, NULL, "LOCKED", NULL, NULL, NULL },
|
| 316 | { UNIT_WLK, 0, NULL, "WRITEENABLED", NULL, NULL, NULL },
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 317 |
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 318 | { 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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 324 | { 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 Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 334 | /* 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 Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 338 | { 0 }
|
| 339 | };
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 340 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 341 | static DEBTAB ds_deb [] = {
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 342 | { "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 Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 349 | };
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 350 |
|
| 351 | DEVICE 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 Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 379 |
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 380 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 381 | /* I/O signal handler.
|
| 382 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 383 | 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 Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 387 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 388 | 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 Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 391 | 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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 394 |
|
| 395 | One unusual aspect is that SFC and SFS test different things, rather than
|
Mark Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 396 | complementary states of the same thing. SFC tests the controller busy state,
|
| 397 | and SFS tests the flag flip-flop.
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 398 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 399 | 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 Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 408 | Implementation notes:
|
| 409 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 410 | 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 Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 413 | 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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 416 |
|
| 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 Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 420 | 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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 423 |
|
| 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 Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 433 | interface from the current command operation and phase.
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 434 | */
|
| 435 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 436 | uint32 ds_io (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data)
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 437 | {
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 438 | static const char * const output_state [] = { "Data", "Command" };
|
| 439 | const char * const hold_or_clear = (signal_set & ioCLF ? ",C" : "");
|
| 440 |
|
| 441 | uint16 data;
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 442 | IOSIGNAL signal;
|
| 443 | IOCYCLE working_set = IOADDSIR (signal_set); /* add ioSIR if needed */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 444 | t_bool command_issued = FALSE;
|
| 445 | t_bool interrupt_enabled = FALSE;
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 446 |
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 447 | while (working_set) {
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 448 | signal = IONEXT (working_set); /* isolate the next signal */
|
Bob Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 449 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 450 | switch (signal) { /* dispatch the I/O signal */
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 451 |
|
| 452 | case ioCLF: /* clear flag flip-flop */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 453 | ds.flag = CLEAR; /* clear the flag */
|
| 454 | ds.flagbuf = CLEAR; /* and flag buffer */
|
| 455 |
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 456 | tprintf (ds_dev, DEB_CMDS, "[CLF] Flag cleared\n");
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 457 | break;
|
Bob Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 458 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 459 |
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 460 | case ioSTF: /* set flag flip-flop */
|
| 461 | case ioENF: /* enable flag */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 462 | ds.flag = SET; /* set the flag */
|
| 463 | ds.flagbuf = SET; /* and flag buffer */
|
| 464 |
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 465 | tprintf (ds_dev, DEB_CMDS, "[STF] Flag set\n");
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 466 | break;
|
Bob Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 467 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 468 |
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 469 | case ioSFC: /* skip if flag is clear */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 470 | setSKF (mac_cntlr.state != cntlr_busy); /* skip if the controller is not busy */
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 471 | break;
|
Bob Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 472 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 473 |
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 474 | case ioSFS: /* skip if flag is set */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 475 | setstdSKF (ds); /* assert SKF if the flag is set */
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 476 | break;
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 477 |
|
| 478 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 479 | 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 Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 483 | tprintf (ds_dev, DEB_CPU, "[LIx%s] Data = %06o\n", hold_or_clear, data);
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 484 |
|
| 485 | if (FIFO_EMPTY) { /* is the FIFO now empty? */
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 486 | if (ds.srq == SET)
|
| 487 | tprintf (ds_dev, DEB_CMDS, "[LIx%s] SRQ cleared\n", hold_or_clear);
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 488 |
|
| 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 Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 496 | break;
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 497 |
|
| 498 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 499 | case ioIOO: /* I/O data output */
|
| 500 | data = IODATA (stat_data); /* mask to just the data word */
|
| 501 |
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 502 | tprintf (ds_dev, DEB_CPU, "[OTx%s] %s = %06o\n",
|
| 503 | hold_or_clear, output_state [ds.cmfol], data);
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 504 |
|
| 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 Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 511 | }
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 512 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 513 | 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 Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 520 | if (ds.srq == SET)
|
| 521 | tprintf (ds_dev, DEB_CMDS, "[OTx%s] SRQ cleared\n", hold_or_clear);
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 522 |
|
Mark Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 523 | ds.srq = CLEAR; /* clear SRQ to stop filling */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 524 | }
|
| 525 | }
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 526 | break;
|
Bob Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 527 |
|
Bob Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 528 |
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 529 | case ioPOPIO: /* power-on preset to I/O */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 530 | 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 Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 534 | tprintf (ds_dev, DEB_CMDS, "[POPIO] Flag set\n");
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 535 | break;
|
Bob Supnik | 59aa4a7 | 2008-06-24 14:21:00 -0700 | [diff] [blame] | 536 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 537 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 538 | case ioCRS: /* control reset */
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 539 | tprintf (ds_dev, DEB_CMDS, "[CRS] Master reset\n");
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 540 |
|
| 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 Pizzolato | 486427c | 2018-06-03 14:38:38 -0700 | [diff] [blame] | 547 | dl_clear_controller (&mac_cntlr, ds_unit, /* do a hard clear of the controller */
|
| 548 | hard_clear);
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 549 | }
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 550 | break;
|
Bob Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 551 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 552 |
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 553 | case ioCLC: /* clear control flip-flop */
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 554 | tprintf (ds_dev, DEB_CMDS, "[CLC%s] Control cleared\n", hold_or_clear);
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 555 |
|
| 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 Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 562 | break;
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 563 |
|
| 564 |
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 565 | case ioSTC: /* set control flip-flop */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 566 | ds.control = SET; /* set the control flip-flop */
|
| 567 |
|
| 568 | interrupt_enabled = TRUE; /* check for drive attention */
|
| 569 |
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 570 | tprintf (ds_dev, DEB_CMDS, "[STC%s] Control set\n", hold_or_clear);
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 571 | break;
|
Bob Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 572 |
|
Bob Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 573 |
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 574 | case ioEDT: /* end data transfer */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 575 | ds.edt = SET; /* set the EDT flip-flop */
|
| 576 |
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 577 | tprintf (ds_dev, DEB_CPU, "[EDT] DCPC transfer ended\n");
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 578 | break;
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 579 |
|
| 580 |
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 581 | case ioSIR: /* set interrupt request */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 582 | 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 Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 585 | break;
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 586 |
|
| 587 |
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 588 | case ioIAK: /* interrupt acknowledge */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 589 | ds.flagbuf = CLEAR; /* clear the flag */
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 590 | break;
|
| 591 |
|
| 592 |
|
| 593 | default: /* all other signals */
|
| 594 | break; /* are ignored */
|
| 595 | }
|
| 596 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 597 | working_set = working_set & ~signal; /* remove the current signal from the set */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 598 | }
|
| 599 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 600 |
|
| 601 | if (command_issued) /* was a command received? */
|
| 602 | poll_interface (); /* poll the interface for the next command */
|
| 603 | else if (interrupt_enabled) /* were interrupts enabled? */
|
| 604 | poll_drives (); /* poll the drives for Attention */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 605 |
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 606 | return stat_data;
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 607 | }
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 608 |
|
Bob Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 609 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 610 | /* Service the disc drive unit.
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 611 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 612 | 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 Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 626 | word arrives, it is unloaded from the FIFO into the sector buffer, and SRQ is
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 627 | 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 Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 643 | 1. Every command except Seek, Recalibrate, and End sets the flag when the
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 644 | command completes. A command completes when the controller is no longer
|
Mark Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 645 | 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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 649 |
|
| 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 Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 657 | 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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 660 |
|
| 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 Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 668 | 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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 676 |
|
Mark Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 677 | 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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 680 |
|
Mark Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 681 | Instead, we have to determine whether a seek is completing. If it is,
|
| 682 | then we report "uptr->OP"; otherwise, we report "opcode".
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 683 |
|
Mark Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 684 | 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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 689 |
|
Mark Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 690 | 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 Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 693 | */
|
| 694 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 695 | t_stat ds_service_drive (UNIT *uptr)
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 696 | {
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 697 | t_stat result;
|
| 698 | t_bool seek_completion;
|
Mark Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 699 | FLIP_FLOP entry_srq = ds.srq; /* get the SRQ state on entry */
|
| 700 | CNTLR_PHASE entry_phase = (CNTLR_PHASE) uptr->PHASE; /* get the operation phase on entry */
|
| 701 | uint32 entry_status = uptr->STAT; /* get the drive status on entry */
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 702 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 703 | result = dl_service_drive (&mac_cntlr, uptr); /* service the drive */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 704 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 705 | if ((CNTLR_PHASE) uptr->PHASE == data_phase) /* is the drive in the data phase? */
|
| 706 | switch ((CNTLR_OPCODE) uptr->OP) { /* dispatch the current operation */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 707 |
|
Mark Pizzolato | ef147d2 | 2012-10-24 12:57:37 -0700 | [diff] [blame] | 708 | case Read: /* read operations */
|
| 709 | case Read_Full_Sector:
|
| 710 | case Read_With_Offset:
|
| 711 | case Read_Without_Verify:
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 712 | 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 Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 716 | }
|
Bob Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 717 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 718 | else if (FIFO_FULL) /* is the FIFO already full? */
|
| 719 | dl_end_command (&mac_cntlr, data_overrun); /* terminate the command with an overrun */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 720 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 721 | 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 Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 728 |
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 729 | break;
|
Bob Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 730 |
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 731 |
|
Mark Pizzolato | ef147d2 | 2012-10-24 12:57:37 -0700 | [diff] [blame] | 732 | case Write: /* write operations */
|
| 733 | case Write_Full_Sector:
|
| 734 | case Initialize:
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 735 | 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 Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 739 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 740 | else if (FIFO_EMPTY) /* is the FIFO empty? */
|
| 741 | dl_end_command (&mac_cntlr, data_overrun); /* terminate the command with an underrun */
|
Bob Supnik | b6393b3 | 2004-11-23 15:49:00 -0800 | [diff] [blame] | 742 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 743 | else {
|
| 744 | buffer [mac_cntlr.index++] = fifo_unload (); /* unload the next word from the FIFO */
|
| 745 | mac_cntlr.length--; /* count it */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 746 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 747 | 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 Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 749 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 750 | 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 Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 768 | default: /* we were entered with an invalid state */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 769 | result = SCPE_IERR; /* return an internal (programming) error */
|
| 770 | break;
|
| 771 | } /* end of data phase operation dispatch */
|
| 772 |
|
| 773 |
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 774 | if (entry_srq != ds.srq)
|
| 775 | tprintf (ds_dev, DEB_CMDS, "SRQ %s\n", ds.srq == SET ? "set" : "cleared");
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 776 |
|
Mark Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 777 | if (uptr->wait) /* was service requested? */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 778 | activate_unit (uptr); /* schedule the next event */
|
| 779 |
|
| 780 | seek_completion = ~entry_status & uptr->STAT & DL_S2ATN; /* seek is complete when Attention sets */
|
| 781 |
|
| 782 | if (mac_cntlr.state != cntlr_busy) { /* is the command complete? */
|
Mark Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 783 | if (mac_cntlr.state == cntlr_wait && !seek_completion) /* is it command but not seek completion? */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 784 | 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 Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 791 | if (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 Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 795 |
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 796 | else 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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 799 |
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 800 | else 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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 803 |
|
| 804 | return result; /* return the result of the service */
|
Bob Supnik | 53d02f7 | 2007-02-03 14:59:00 -0800 | [diff] [blame] | 805 | }
|
Bob Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 806 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 807 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 808 | /* Service the controller unit.
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 809 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 810 | 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 Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 814 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 815 | 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 Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 823 |
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 824 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 825 | Implementation notes:
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 826 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 827 | 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 Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 831 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 832 | In simulation, the flag is set as soon as the parameter is received.
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 833 | */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 834 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 835 | t_stat ds_service_controller (UNIT *uptr)
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 836 | {
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 837 | t_stat result;
|
| 838 | const CNTLR_OPCODE opcode = (CNTLR_OPCODE) uptr->OP;
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 839 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 840 | result = dl_service_controller (&mac_cntlr, uptr); /* service the controller */
|
| 841 |
|
| 842 | switch ((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 Pizzolato | ef147d2 | 2012-10-24 12:57:37 -0700 | [diff] [blame] | 848 | 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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 855 | break; /* complete the operation without setting the flag */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 856 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 857 |
|
Mark Pizzolato | ef147d2 | 2012-10-24 12:57:37 -0700 | [diff] [blame] | 858 | case Clear:
|
| 859 | case Set_File_Mask:
|
| 860 | case Wakeup:
|
Mark Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 861 | ds_io (&ds_dib, ioENF, 0); /* complete the operation and set the flag */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 862 | break;
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 863 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 864 |
|
Mark Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 865 | default: /* we were entered with an invalid state */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 866 | 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 Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 870 |
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 871 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 872 | case data_phase:
|
| 873 | switch (opcode) { /* dispatch the current operation */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 874 |
|
Mark Pizzolato | ef147d2 | 2012-10-24 12:57:37 -0700 | [diff] [blame] | 875 | case Seek: /* operations that accept parameters */
|
| 876 | case Verify:
|
| 877 | case Address_Record:
|
| 878 | case Read_With_Offset:
|
| 879 | case Load_TIO_Register:
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 880 | buffer [mac_cntlr.index++] = fifo_unload (); /* unload the next word from the FIFO */
|
| 881 | mac_cntlr.length--; /* count it */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 882 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 883 | 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 Pizzolato | ef147d2 | 2012-10-24 12:57:37 -0700 | [diff] [blame] | 889 | if (opcode == Read_With_Offset) /* a Read With Offset command sets the flag */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 890 | 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 Pizzolato | ef147d2 | 2012-10-24 12:57:37 -0700 | [diff] [blame] | 897 | case Request_Status: /* operations that supply parameters */
|
| 898 | case Request_Sector_Address:
|
| 899 | case Request_Syndrome:
|
| 900 | case Request_Disc_Address:
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 901 | 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 Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 916 | default: /* we were entered with an invalid state */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 917 | 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 Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 924 | if (result == SCPE_IERR) /* did an internal error occur? */
|
| 925 | tprintf (ds_dev, DEB_RWSC, "Controller %s command %s phase service not handled\n",
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 926 | dl_opcode_name (MAC, opcode), dl_phase_name ((CNTLR_PHASE) uptr->PHASE));
|
| 927 |
|
| 928 |
|
| 929 | if (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 Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 933 | tprintf (ds_dev, DEB_RWSC, "Controller %s command completed\n",
|
| 934 | dl_opcode_name (MAC, opcode));
|
Bob Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 935 | }
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 936 |
|
| 937 | return result; /* return the result of the service */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 938 | }
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 939 |
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 940 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 941 | /* Service the command wait timer unit.
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 942 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 943 | 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 Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 947 | */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 948 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 949 | t_stat ds_service_timer (UNIT *uptr)
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 950 | {
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 951 | t_stat result;
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 952 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 953 | result = dl_service_timer (&mac_cntlr, uptr); /* service the timer */
|
| 954 |
|
| 955 | poll_interface (); /* poll the interface for the next command */
|
| 956 | poll_drives (); /* poll the drives for Attention status */
|
| 957 |
|
| 958 | return result; /* return the result of the service */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 959 | }
|
| 960 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 961 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 962 | /* Reset the simulator.
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 963 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 964 | 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 Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 968 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 969 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 970 | Implementation notes:
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 971 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 972 | 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 Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 974 | unloading. This enables SCP to view the FIFO as a circular queue, so
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 975 | 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 Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 977 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 978 | 2. SRQ is denied because neither IFIN nor IFOUT is asserted when the
|
| 979 | interface is not selected.
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 980 | */
|
| 981 |
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 982 | t_stat ds_reset (DEVICE *dptr)
|
| 983 | {
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 984 | uint32 unit;
|
| 985 |
|
| 986 | if (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 Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 990 | return SCPE_IERR; /* report a programming error */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 991 |
|
| 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 |
|
| 1004 | IOPRESET (&ds_dib); /* PRESET the device */
|
Mark Pizzolato | fffad7c | 2012-03-19 16:05:24 -0700 | [diff] [blame] | 1005 | ds.srq = CLEAR; /* clear SRQ */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1006 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1007 | return SCPE_OK;
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 1008 | }
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1009 |
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 1010 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1011 | /* 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 Pizzolato | 486427c | 2018-06-03 14:38:38 -0700 | [diff] [blame] | 1018 | 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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1021 |
|
| 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 Pizzolato | 486427c | 2018-06-03 14:38:38 -0700 | [diff] [blame] | 1026 |
|
| 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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1030 | */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 1031 |
|
Mark Pizzolato | 5531ccb | 2016-05-15 15:25:33 -0700 | [diff] [blame] | 1032 | t_stat ds_attach (UNIT *uptr, CONST char *cptr)
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 1033 | {
|
Mark Pizzolato | 486427c | 2018-06-03 14:38:38 -0700 | [diff] [blame] | 1034 | t_stat result;
|
| 1035 | t_addr offset;
|
| 1036 | const uint8 zero = 0;
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 1037 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1038 | result = dl_attach (&mac_cntlr, uptr, cptr); /* attach the drive */
|
| 1039 |
|
Mark Pizzolato | 486427c | 2018-06-03 14:38:38 -0700 | [diff] [blame] | 1040 | if (result == SCPE_OK) { /* if the attach was successful */
|
| 1041 | poll_drives (); /* then poll the drives to notify the CPU */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1042 |
|
Mark Pizzolato | 486427c | 2018-06-03 14:38:38 -0700 | [diff] [blame] | 1043 | 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 |
|
| 1054 | return result; /* return the result of the attach */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 1055 | }
|
| 1056 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1057 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1058 | /* 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 Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 1065 |
|
| 1066 | t_stat ds_detach (UNIT *uptr)
|
| 1067 | {
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1068 | t_stat result;
|
| 1069 |
|
| 1070 | result = dl_detach (&mac_cntlr, uptr); /* detach the drive */
|
| 1071 |
|
| 1072 | if (result == SCPE_OK) /* was the detach successful? */
|
| 1073 | poll_drives (); /* poll the drives to notify the CPU */
|
| 1074 |
|
| 1075 | return result;
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 1076 | }
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1077 |
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 1078 |
|
Mark Pizzolato | 486427c | 2018-06-03 14:38:38 -0700 | [diff] [blame] | 1079 | /* MAC disc bootstrap loaders (BMDL and 12992B).
|
Bob Supnik | ec60bbf | 2005-05-03 04:10:00 -0700 | [diff] [blame] | 1080 |
|
Mark Pizzolato | 486427c | 2018-06-03 14:38:38 -0700 | [diff] [blame] | 1081 | 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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1085 |
|
Mark Pizzolato | 486427c | 2018-06-03 14:38:38 -0700 | [diff] [blame] | 1086 | 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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1091 |
|
Mark Pizzolato | 486427c | 2018-06-03 14:38:38 -0700 | [diff] [blame] | 1092 | * 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 Supnik | ec60bbf | 2005-05-03 04:10:00 -0700 | [diff] [blame] | 1108 |
|
Bob Supnik | 9c4779c | 2009-02-08 09:06:00 -0800 | [diff] [blame] | 1109 |
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1110 | Implementation notes:
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 1111 |
|
Mark Pizzolato | 486427c | 2018-06-03 14:38:38 -0700 | [diff] [blame] | 1112 | 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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1118 | */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 1119 |
|
Mark Pizzolato | 486427c | 2018-06-03 14:38:38 -0700 | [diff] [blame] | 1120 | static 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 Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 1189 |
|
Mark Pizzolato | 486427c | 2018-06-03 14:38:38 -0700 | [diff] [blame] | 1190 | { /* 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 Supnik | b7c1eae | 2005-09-09 18:09:00 -0700 | [diff] [blame] | 1258 | };
|
Mark Pizzolato | 486427c | 2018-06-03 14:38:38 -0700 | [diff] [blame] | 1259 |
|
| 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 Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 1316 |
|
| 1317 | t_stat ds_boot (int32 unitno, DEVICE *dptr)
|
| 1318 | {
|
Mark Pizzolato | 486427c | 2018-06-03 14:38:38 -0700 | [diff] [blame] | 1319 | static const HP_WORD ds_preserved = 0000073u; /* S-register bits 5-3 and 1-0 are preserved */
|
| 1320 | static const HP_WORD ds_manual_boot = 0010000u; /* S-register bit 12 set for a manual boot */
|
Bob Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 1321 |
|
Mark Pizzolato | 486427c | 2018-06-03 14:38:38 -0700 | [diff] [blame] | 1322 | if (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 Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 1325 |
|
Mark Pizzolato | 486427c | 2018-06-03 14:38:38 -0700 | [diff] [blame] | 1326 | else if (unitno != 0) /* otherwise a BOOT DS for a non-zero unit */
|
| 1327 | return SCPE_NOFNC; /* is rejected as unsupported */
|
| 1328 |
|
| 1329 | else /* 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 Supnik | e2ba672 | 2004-07-10 06:13:00 -0700 | [diff] [blame] | 1332 | }
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1333 |
|
| 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 Pizzolato | 5531ccb | 2016-05-15 15:25:33 -0700 | [diff] [blame] | 1351 | t_stat ds_load_unload (UNIT *uptr, int32 value, CONST char *cptr, void *desc)
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1352 | {
|
Mark Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 1353 | const t_bool load = (value != UNIT_UNLOAD); /* true if the heads are loading */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1354 |
|
| 1355 | return 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 |
|
| 1406 | static void start_command (void)
|
| 1407 | {
|
| 1408 | int32 unit, time;
|
| 1409 | UNIT *uptr;
|
| 1410 | CNTLR_OPCODE drive_command;
|
| 1411 |
|
| 1412 | unit = GET_S1UNIT (mac_cntlr.spd_unit); /* get the (prepared) unit from the command */
|
| 1413 |
|
| 1414 | if (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 */
|
| 1416 | else /* the unit is invalid, so the command will not start */
|
Mark Pizzolato | ef147d2 | 2012-10-24 12:57:37 -0700 | [diff] [blame] | 1417 | drive_command = End; /* but the compiler doesn't know this! */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1418 |
|
| 1419 | uptr = dl_start_command (&mac_cntlr, ds_unit, DL_MAXDRIVE); /* ask the controller to start the command */
|
| 1420 |
|
| 1421 | if (uptr) { /* did the command start? */
|
| 1422 | time = uptr->wait; /* save the activation time */
|
| 1423 |
|
| 1424 | if (time) /* was the unit scheduled? */
|
Mark Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 1425 | activate_unit (uptr); /* activate it (and clear the "wait" field) */
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1426 |
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 1427 | 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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1430 |
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 1431 | if (uptr - ds_unit > DL_MAXDRIVE)
|
| 1432 | tprintf (ds_dev, DEB_RWSC, "Controller %s command initiated\n",
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1433 | dl_opcode_name (MAC, mac_cntlr.opcode));
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 1434 | 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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1437 | }
|
| 1438 |
|
| 1439 | else /* the command failed to start */
|
| 1440 | ds_io (&ds_dib, ioENF, 0); /* so set the flag to notify the CPU */
|
| 1441 |
|
| 1442 | return;
|
| 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 |
|
| 1457 | static void poll_interface (void)
|
| 1458 | {
|
| 1459 | if (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 |
|
| 1475 | return;
|
| 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 Pizzolato | a262dd9 | 2013-03-19 01:11:22 -0700 | [diff] [blame] | 1488 | static void poll_drives (void)
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1489 | {
|
Mark Pizzolato | 40deb20 | 2012-04-04 12:31:43 -0700 | [diff] [blame] | 1490 | if (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 Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1492 | ds_io (&ds_dib, ioENF, 0); /* request an interrupt */
|
| 1493 | return;
|
| 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 |
|
| 1522 | static void fifo_load (uint16 data)
|
| 1523 | {
|
| 1524 | uint32 index;
|
| 1525 |
|
| 1526 | if (FIFO_FULL) { /* is the FIFO already full? */
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 1527 | tprintf (ds_dev, DEB_BUF, "Attempted load to full FIFO, data %06o\n", data);
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1528 |
|
| 1529 | return; /* return with the load ignored */
|
| 1530 | }
|
| 1531 |
|
| 1532 | index = (ds.fifo_reg->qptr + ds.fifo_count) % FIFO_SIZE; /* calculate the index of the next available location */
|
| 1533 |
|
| 1534 | ds.fifo [index] = data; /* store the word in the FIFO */
|
| 1535 | ds.fifo_count = ds.fifo_count + 1; /* increment the count of words stored */
|
| 1536 |
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 1537 | tprintf (ds_dev, DEB_BUF, "Data %06o loaded into FIFO (%d)\n",
|
| 1538 | data, ds.fifo_count);
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1539 |
|
| 1540 | return;
|
| 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 |
|
| 1558 | static uint16 fifo_unload (void)
|
| 1559 | {
|
| 1560 | uint16 data;
|
| 1561 |
|
| 1562 | if (FIFO_EMPTY) { /* is the FIFO already empty? */
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 1563 | tprintf (ds_dev, DEB_BUF, "Attempted unload from empty FIFO\n");
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1564 | return 0; /* return with no data */
|
| 1565 | }
|
| 1566 |
|
| 1567 | data = ds.fifo [ds.fifo_reg->qptr]; /* get the word from the FIFO */
|
| 1568 |
|
| 1569 | ds.fifo_reg->qptr = (ds.fifo_reg->qptr + 1) % FIFO_SIZE; /* update the FIFO queue pointer */
|
| 1570 | ds.fifo_count = ds.fifo_count - 1; /* decrement the count of words stored */
|
| 1571 |
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 1572 | tprintf (ds_dev, DEB_BUF, "Data %06o unloaded from FIFO (%d)\n",
|
| 1573 | data, ds.fifo_count);
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1574 |
|
| 1575 | return data;
|
| 1576 | }
|
| 1577 |
|
| 1578 |
|
| 1579 | /* Clear the FIFO.
|
| 1580 |
|
| 1581 | The FIFO is cleared by setting the occupancy counter to zero.
|
| 1582 | */
|
| 1583 |
|
| 1584 | static void fifo_clear (void)
|
| 1585 | {
|
| 1586 | ds.fifo_count = 0; /* clear the FIFO */
|
| 1587 |
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 1588 | tprintf (ds_dev, DEB_BUF, "FIFO cleared\n");
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1589 |
|
| 1590 | return;
|
| 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 |
|
| 1600 | static t_stat activate_unit (UNIT *uptr)
|
| 1601 | {
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1602 | t_stat result;
|
| 1603 |
|
Mark Pizzolato | a6552b8 | 2017-09-06 22:16:14 -0700 | [diff] [blame] | 1604 | if (uptr == &ds_cntlr)
|
| 1605 | tprintf (ds_dev, DEB_SERV, "Controller delay %d service scheduled\n",
|
| 1606 | uptr->wait);
|
| 1607 | else
|
| 1608 | tprintf (ds_dev, DEB_SERV, "Unit %d delay %d service scheduled\n",
|
| 1609 | uptr - ds_unit, uptr->wait);
|
Mark Pizzolato | 45246a3 | 2012-03-21 06:14:01 -0700 | [diff] [blame] | 1610 |
|
| 1611 | result = sim_activate (uptr, uptr->wait); /* activate the unit */
|
| 1612 | uptr->wait = 0; /* reset the activation time */
|
| 1613 |
|
| 1614 | return result; /* return the activation status */
|
| 1615 | }
|