diff --git a/0readme_39.txt b/0readme_39.txt index d5fb4b10..e5b3509e 100644 --- a/0readme_39.txt +++ b/0readme_39.txt @@ -2,7 +2,8 @@ Notes For V3.9 The makefile now works for all *nix platforms and with cygwin and MinGW32 -on Windows. +on Windows. It will automatically detect the availability of libpcap +components and build network capable simulators if they are available. 1. New Features @@ -14,15 +15,32 @@ on Windows. - added *nix READLINE support (Mark Pizzolato) - added "SHOW SHOW" and "SHOW SHOW" commands (Mark Pizzolato) - added support for BREAK key on Windows (Mark Pizzolato) - + - added ethernet support (Mark Pizzolato) + windows host <-> simulator NIC sharing + native tap interfaces on BSD, Linux and OSX + vde (Virtual Distributed Ethernet) networking + Large Send Offload support + UDP and TCP Checksum offload support + dynamic libpcap loading on *nix platforms 1.1.2 PDP-8 - floating point processor is now enabled - -1.1.3 IA64 VMS Ethernet Support + +1.1.3 HP2100 (Dave Bryan) + + - added support for 12821A HP-IB disk controller, + 7906H/20H/25H disks + +1.1.4 PDP11 and VAX (Mark Pizzolato) + + - Added DELQA-Plus device. + +1.1.5 IA64 VMS Ethernet Support - Identified compiler version issues and added IA64 support (Matt Burke) + +1.1.6 Visual Studio Projects (Mark Pizzolato) 2. Bugs Fixed diff --git a/HP2100/hp2100_bugfixes.txt b/HP2100/hp2100_bugfixes.txt index 90c3bd0f..80793696 100644 --- a/HP2100/hp2100_bugfixes.txt +++ b/HP2100/hp2100_bugfixes.txt @@ -1,6 +1,6 @@ HP 2100 SIMULATOR BUG FIX WRITEUPS ================================== - Last update: 2012-03-23 + Last update: 2012-03-25 1. PROBLEM: Booting from magnetic tape reports "HALT instruction, P: 77756 @@ -6257,3 +6257,26 @@ 16-bit dimension count. STATUS: Fixed in version 3.9-0. + + + +246. PROBLEM: SHOW MTC SHOW lists the FORMAT modifier twice. + + VERSION: 3.8-1 + + OBSERVATION: Entering the planned SHOW MTC SHOW command results in the + following display: + + sim> SHOW MTC SHOW + sh{ow} MTC FORMAT, SC, DEVNO + sh{ow} MTCn FORMAT + + FORMAT is listed both as a device and as a unit modifier. + + CAUSE: The FORMAT entry in the modifier table contains both the MTAB_VDV + and the MTAB_VUN flags. + + RESOLUTION: Remove the redundant MTAB_VUN flag from the "mtc_mod" array + (hp2100_mt.c). + + STATUS: Fixed in version 3.9-0. diff --git a/HP2100/hp2100_di.c b/HP2100/hp2100_di.c index 4b790ff1..98cc4ef0 100644 --- a/HP2100/hp2100_di.c +++ b/HP2100/hp2100_di.c @@ -39,21 +39,21 @@ The 12821A was a high-speed implementation of the Hewlett-Packard Interface Bus (HP-IB, formalized as IEEE Std. 488-1978). It was used to interface HP-IB disc and tape devices, such as the HP 7906H, 7908A, and 7974A, to the - HP 1000 running RTE-IVB and RTE-6/VM. Three device command protocols were + HP 1000 running RTE-IVB or RTE-6/VM. Three device command protocols were supported by the I/O drivers: Amigo discs by driver DVA32, CS/80 discs by DVM33, and Amigo tapes by DVS23. In an RTE environment, the 12821A was the system controller. While electrically compatible with the HP-IB specification and capable of receiving addressing commands from the bus, the 12821A did not use the full IEEE-488 - protocol. Card talker and listener states were set by bits in a control + protocol. Card talker and listener states were set by bits in the control register, rather than by receiving talk and listen commands over the bus. The bus address of the card could be set via DIP switches, but this feature was only used by the diagnostic. The card supported packed and unpacked transfers across the bus. Up to four - devices could be connected to each card; the limit was imposed by the maximum - electrical loading on the bus compatible with the high data rate. + devices could be connected to each card; this limit was imposed by the + maximum electrical loading on the bus compatible with the high data rate. The 12821A had a 16-word FIFO buffer and could sustain DCPC transfers of one megabyte per second. Burst transfers by the CPU to fill or empty the FIFO @@ -69,15 +69,15 @@ The simulator is logically partitioned into three sets of functions: the interface card simulation, the HP-IB bus simulation, and the device simulation. This is the card simulation and the card portion of the HP-IB - simulation. Separate files for the tape and disc devices contain the device - simulations and the device portions of the HP-IB simulations. + simulation. Separate modules for the tape and disc devices contain the + device simulations and the device portions of the HP-IB simulations. - This simulation is written to allow the definition of multiple DI cards in a + This simulator is written to allow the definition of multiple DI cards in a system. The RTE operating system provided separate I/O drivers for the Amigo disc, Amigo tape, and CS/80 disc devices. As only one I/O driver could control a given interface, separate interfaces were required if more than one - device class was installed. For example, it was not possible to install an - Amigo disc and an Amigo tape on the same interface card. + device class was installed. For example, it was not possible to control an + Amigo disc and an Amigo tape connected to the same interface card. Implementation notes: @@ -92,7 +92,7 @@ to be the system controller. This cannot be changed by the user. 3. The simulator behaves as though card jumper W1 (DCPC pacing) is in - position B. This cannot be changed by the user. + position B. This currently cannot be changed by the user. */ @@ -119,7 +119,7 @@ /* Control Word Register */ #define CNTL_SRQ 0100000 /* enable service request interrupt */ -#define CNTL_IFC 0040000 /* assert IFC, enable IFC interrupt */ +#define CNTL_IFC 0040000 /* assert IFC or enable IFC interrupt */ #define CNTL_REN 0020000 /* assert remote enable */ #define CNTL_IRL 0010000 /* enable input-register-loaded interrupt */ #define CNTL_LBO 0004000 /* enable last-byte-out interrupt */ @@ -144,8 +144,8 @@ #define STAT_IRL 0010000 /* input register loaded */ #define STAT_LBO 0004000 /* last byte out */ #define STAT_LBI 0002000 /* last byte in */ -#define STAT_EOIBUS 0001000 /* end or identify */ -#define STAT_ATNBUS 0000400 /* attention */ +#define STAT_EOIBUS 0001000 /* end or identify bus state */ +#define STAT_ATNBUS 0000400 /* attention bus state */ #define STAT_IFC 0000200 /* interface clear seen */ #define STAT_ODD 0000020 /* odd number of bytes */ #define STAT_SYSCTL 0000010 /* system controller */ @@ -167,7 +167,7 @@ #define DATA_SHIFT 8 /* left shift count to align DATA_ATN, EOI with tag */ #define TAG_ATN 0000200000 /* bit 16: attention */ -#define TAG_EOI 0000400000 /* bit 17: end-or-identify */ +#define TAG_EOI 0000400000 /* bit 17: end or identify */ #define TAG_EDT 0001000000 /* bit 18: end of data transfer */ #define TAG_LBR 0002000000 /* bit 19: last byte received */ @@ -219,16 +219,16 @@ static void di_bus_poll (CARD_ID card); static void master_reset (CARD_ID card); static void update_state (CARD_ID card); -static void fifo_load (CARD_ID card, uint16 data, FIFO_ACCESS access); +static void fifo_load (CARD_ID card, uint16 data, FIFO_ACCESS access); static uint16 fifo_unload (CARD_ID card, FIFO_ACCESS access); -static void fprint_bus (FILE *file, char *format, uint8 cntl); +static void fprint_bus (FILE *file, char *format, uint8 cntl); /* Dummy DC device. - This dummy device allows the DI diagnostic to test inter-card signals. Test - 15 can only be performed if there are two DIs available. + This temporary dummy device allows the DI diagnostic to test inter-card + signals. Test 15 can only be performed if there are two DIs available. This device provides a second "bare" card. Normally, it is disabled and cannot be enabled by the user. Enabling or disabling DIAG mode on the DA @@ -331,28 +331,28 @@ DEBTAB di_deb [] = { written to the FIFO. The flip-flop is set by the EDT backplane signal when the last cycle of a DCPC transfer is executing, or during programmed output transfers when CLF does not accompany IOO in packed mode, or when bit 15 of - the data word is set in unpacked mode. It remains set until cleared by a - master reset. The output of the EDT flip-flop drives the EDT tag input of + the data word is set in unpacked mode. It remains set until it is cleared by + a master reset. The output of the EDT flip-flop drives the EDT tag input of the FIFO. The LBO signal indicates that the final data byte of a transfer has been sourced to the bus. The flip-flop is set when the last byte of the entry tagged with EDT has been unloaded from the FIFO. It is cleared by a master - reset, or when an entry not tagged with EDT is unloaded. The output of the + reset or when an entry not tagged with EDT is unloaded. The output of the LBO flip-flop drives the LBO bit in the Status Word. The LBI signal indicates that the final byte of an input transfer has been accepted from the bus. The flip-flop is set when a byte tagged with EOI is received and the EOI bit in the control register is set, or a line-feed byte is received and the LF bit in the control register is set. It is cleared by - a master reset, or when neither of these conditions is true. The input of - the LBI flip-flop also drives the LBR (last byte received) tag input of the - FIFO, and the output of the flip-flop drives the LBI bit in the Status Word. + a master reset or when neither of these conditions is true. The input of the + LBI flip-flop also drives the LBR (last byte received) tag input of the FIFO, + and the output of the flip-flop drives the LBI bit in the Status Word. The EOR signal indicates that the final data word of a transfer is available in the Input Data Register. The flip-flop is set when the last byte of the entry tagged with LBR has been unloaded from the FIFO and written to the IDR. - It is cleared by a master reset, or when an entry not tagged with LBR is + It is cleared by a master reset or when an entry not tagged with LBR is unloaded and written to the IDR. The output of the EOR flip-flop sets the flag flip-flop when the IDR is unloaded. @@ -367,21 +367,21 @@ DEBTAB di_deb [] = { 2. The DIAG, T, and L control bits enable a data loopback path on the card. An IOO issued to the card unloads a word from the FIFO and then loads the - lower byte into both bytes of the FIFO. The data word output with the - IOO instruction is not used. + lower byte back into both bytes of the FIFO. The data word output with + the IOO instruction is not used. In hardware, IOO triggers the FIFO unload and reload; T and L are - required only for the loopback path. If L is not asserted, the FIFO is - loaded with 177777 due to the floating bus. If L is asserted and T is - not, the FIFO is loaded with 000000 due to pullups on the DIO lines. + required only for the loopback path. If L is not asserted, then the FIFO + is loaded with 177777 due to the floating bus. If L is asserted and T is + not, then the FIFO is loaded with 000000 due to pullups on the DIO lines. In simulation, we look only for DIAG and assume that T/L are set properly, i.e., unloaded data is reloaded. 3. In hardware, the SRQ and NRFD lines are open-collector and may be driven simultaneously from several bus devices. Simulating this fully would - require keeping the state of the lines for each device, and deriving the - common bus signals from the logical AND/OR of the state values. - Fortunately, some simplifications are possible. + require keeping the state of the lines for each device and deriving the + common bus signals from the logical OR of the state values. Fortunately, + some simplifications are possible. The DI asserts SRQ only if control word bit 15 is 1 and bit 0 is 0. Other bit combinations deny SRQ; as neither the Amigo nor CS/80 protocols @@ -434,25 +434,25 @@ DI_STATE * const di_card = &di [card]; uint8 assert, deny; /* new bus control states */ uint16 data; -t_bool update_required = TRUE; /* TRUE if CLF must update card state */ +t_bool update_required = TRUE; /* TRUE if CLF must update the card state */ IOSIGNAL signal; IOCYCLE working_set = IOADDSIR (signal_set); /* add ioSIR if needed */ while (working_set) { - signal = IONEXT (working_set); /* isolate next signal */ + signal = IONEXT (working_set); /* isolate the next signal */ - switch (signal) { /* dispatch I/O signal */ + switch (signal) { /* dispatch an I/O signal */ case ioCLF: /* clear flag flip-flop */ - di_card->flag = CLEAR; /* clear flag */ + di_card->flag = CLEAR; /* clear the flag */ di_card->flagbuf = CLEAR; /* and flag buffer */ if (DEBUG_PRJ (dptrs [card], DEB_CMDS)) fprintf (sim_deb, ">>%s cmds: [CLF] Flag cleared\n", dptrs [card]->name); - if (update_required) /* if card state has changed */ + if (update_required) /* if the card state has changed */ update_state (card); /* then update the state */ break; @@ -465,7 +465,7 @@ while (working_set) { /* fall into ENF handler */ case ioENF: /* enable flag */ - di_card->flag = SET; /* set flag */ + di_card->flag = SET; /* set the flag */ di_card->flagbuf = SET; /* and flag buffer */ break; @@ -481,21 +481,21 @@ while (working_set) { case ioIOI: /* I/O data input */ - if (di_card->control == SET) { /* control set = data mode? */ - data = di_card->input_data_register; /* read input data register */ - di_card->status_register &= ~STAT_IRL; /* clear input register loaded status */ + if (di_card->control == SET) { /* is the card in data mode? */ + data = di_card->input_data_register; /* read the input data register */ + di_card->status_register &= ~STAT_IRL; /* clear the input register loaded status */ - if (FIFO_EMPTY && di_card->eor == CLEAR) { /* FIFO empty and end of record not seen? */ + if (FIFO_EMPTY && di_card->eor == CLEAR) { /* is the FIFO empty and end of record not seen? */ if (di_card->srq == SET && DEBUG_PRJ (dptrs [card], DEB_CMDS)) fprintf (sim_deb, ">>%s cmds: SRQ cleared\n", dptrs [card]->name); di_card->srq = CLEAR; /* clear SRQ */ - update_required = FALSE; /* card state does not change */ + update_required = FALSE; /* the card state does not change */ } } - else { /* control clear = status mode */ + else { /* the card is in status mode */ di_card->status_register &= /* clear the values to be computed, */ STAT_IRL | STAT_LBO /* preserving those set elsewhere */ | STAT_LBI | STAT_IFC; @@ -505,14 +505,14 @@ while (working_set) { & (CNTL_CIC | CNTL_TALK | CNTL_LSTN); - if (SW8_SYSCTL) /* if SW8 set, card is system controller */ - di_card->status_register |= STAT_SYSCTL; + if (SW8_SYSCTL) /* if SW8 is set, */ + di_card->status_register |= STAT_SYSCTL; /* the card is the system controller */ if (di_card->ibp == lower) /* if lower byte input is next */ - di_card->status_register |= STAT_ODD; /* then last transfer was odd */ + di_card->status_register |= STAT_ODD; /* then the last transfer was odd */ - di_card->status_register |= /* set bus status bits */ - (di_card->bus_cntl /* from corresponding bus control lines */ + di_card->status_register |= /* set the bus status bits */ + (di_card->bus_cntl /* from the corresponding bus control lines */ & (BUS_SRQ | BUS_IFC | BUS_REN | BUS_EOI | BUS_ATN)) << DATA_SHIFT; @@ -524,10 +524,10 @@ while (working_set) { dptrs [card]->name, hold_or_clear, input_state [di_card->control], data); - if (update_required && !(signal_set & ioCLF)) /* if update and CLF not present, */ - update_state (card); /* update state, else ioCLF will update */ + if (update_required && !(signal_set & ioCLF)) /* if an update is required and CLF is not present, */ + update_state (card); /* update the state, else ioCLF will update it */ - stat_data = IORETURN (SCPE_OK, data); /* merge in return status */ + stat_data = IORETURN (SCPE_OK, data); /* merge in the return status */ break; @@ -539,26 +539,26 @@ while (working_set) { dptrs [card]->name, hold_or_clear, output_state [di_card->control], data); - if (di_card->control == SET) { /* control set = data mode */ + if (di_card->control == SET) { /* is the card in data mode? */ if (signal_set & ioEDT) /* if end of DCPC transfer */ - di_card->edt = SET; /* set EDT flip-flop */ + di_card->edt = SET; /* set the EDT flip-flop */ - else if (di_card->cntl_register & CNTL_PACK) { /* packed transfer? */ + else if (di_card->cntl_register & CNTL_PACK) { /* is this a packed transfer? */ if (!(signal_set & ioCLF)) /* and CLF not given? */ - di_card->edt = SET; /* set EDT flip-flop */ + di_card->edt = SET; /* set the EDT flip-flop */ } - else /* unpacked transfer */ - if (data & DATA_LBO) /* and last byte out? */ - di_card->edt = SET; /* set EDT flip-flop */ + else /* it's an unpacked transfer */ + if (data & DATA_LBO) /* is the last byte out? */ + di_card->edt = SET; /* set the EDT flip-flop */ - if (di_card->cntl_register & CNTL_DIAG) { /* DIAG loopback? */ - data = fifo_unload (card, diag_access); /* unload data from FIFO */ - fifo_load (card, data, diag_access); /* and load back in */ + if (di_card->cntl_register & CNTL_DIAG) { /* set for DIAG loopback? */ + data = fifo_unload (card, diag_access); /* unload data from the FIFO */ + fifo_load (card, data, diag_access); /* and load it back in */ } - else { /* normal mode */ - fifo_load (card, data, cpu_access); /* load data word into FIFO */ + else { /* the card is set for normal operation */ + fifo_load (card, data, cpu_access); /* load the data word into the FIFO */ if (FIFO_FULL && (di_card->bus_cntl & BUS_NRFD)) { /* FIFO full and listener not ready? */ if (di_card->srq == SET && DEBUG_PRJ (dptrs [card], DEB_CMDS)) @@ -566,12 +566,12 @@ while (working_set) { dptrs [card]->name); di_card->srq = CLEAR; /* clear SRQ */ - update_required = FALSE; /* card state does not change */ + update_required = FALSE; /* the card state does not change */ } } } - else { /* control clear = write control word */ + else { /* the card is in control mode */ assert = 0; /* initialize bus control assertions */ deny = 0; /* and denials */ @@ -580,39 +580,39 @@ while (working_set) { if (data & CNTL_TALK) { /* talking enables ATN and EOI outputs */ if ((data & (CNTL_PPE | CNTL_CIC)) /* if parallel poll is enabled */ - == (CNTL_PPE | CNTL_CIC)) /* and card is CIC */ - assert = BUS_PPOLL; /* then conduct parallel poll */ + == (CNTL_PPE | CNTL_CIC)) /* and the card is CIC */ + assert = BUS_PPOLL; /* then conduct a parallel poll */ else if ((di_card->cntl_register /* if PP was enabled */ & (CNTL_PPE | CNTL_CIC)) /* but is not now */ == (CNTL_PPE | CNTL_CIC)) - deny = BUS_PPOLL; /* then end the parallel poll */ + deny = BUS_PPOLL; /* then end the parallel poll */ else if ((data /* if packed mode */ - & (CNTL_PACK | CNTL_CIC | CNTL_ATN)) /* and card is CIC */ - == (CNTL_PACK | CNTL_CIC | CNTL_ATN)) /* then ATN control output */ + & (CNTL_PACK | CNTL_CIC | CNTL_ATN)) /* and the card is CIC */ + == (CNTL_PACK | CNTL_CIC | CNTL_ATN)) /* then the ATN control output */ assert = BUS_ATN; /* is coupled to the bus */ else /* if none of the above */ - deny = BUS_ATN; /* ATN is not driven */ + deny = BUS_ATN; /* then ATN is not driven */ } - else /* not talking */ + else /* the card is not talking */ deny = BUS_ATN | BUS_EOI; /* so ATN and EOI are disabled */ - if (data & CNTL_NRFD) /* card not ready set explicitly? */ - assert |= BUS_NRFD; /* assert NRFD on bus */ + if (data & CNTL_NRFD) /* is card not ready set explicitly? */ + assert |= BUS_NRFD; /* assert NRFD on the bus */ else if (di_card->cntl_register & CNTL_NRFD) /* NRFD was set but is not now? */ - deny |= BUS_NRFD; /* deny NRFD on bus */ + deny |= BUS_NRFD; /* deny NRFD on the bus */ - if (FIFO_FULL) /* is FIFO full? */ + if (FIFO_FULL) /* is the FIFO full? */ if (data & CNTL_LSTN) /* is card now listening? */ - assert |= BUS_NRFD; /* listener and full FIFO asserts NRFD */ + assert |= BUS_NRFD; /* listener and a full FIFO asserts NRFD */ - else if (di_card->cntl_register & CNTL_LSTN) /* was listener but is not now? */ - deny |= BUS_NRFD; /* deny NRFD on bus */ + else if (di_card->cntl_register & CNTL_LSTN) /* was card a listener but is not now? */ + deny |= BUS_NRFD; /* deny NRFD on the bus */ if (SW8_SYSCTL) { /* system controller drives REN and IFC */ @@ -621,35 +621,35 @@ while (working_set) { else /* coupled to */ deny |= BUS_REN; /* the bus */ - if (data & CNTL_IFC) { /* IFC set? */ - assert |= BUS_IFC; /* assert IFC on bus */ + if (data & CNTL_IFC) { /* is IFC set? */ + assert |= BUS_IFC; /* assert IFC on the bus */ di_card->status_register = di_card->status_register & ~(STAT_LSTN | STAT_TALK) /* clear listen and talk status */ | STAT_IFC; /* and set IFC status */ - di_card->ifc_timer = /* start IFC timer by calculating */ - sim_gtime () + IFC_TIMEOUT; /* IFC stop time (100 microseconds) */ + di_card->ifc_timer = /* start the IFC timer by calculating */ + sim_gtime () + IFC_TIMEOUT; /* the IFC stop time (now + 100 microseconds) */ } } - if ((data & (CNTL_SRQ | CNTL_CIC)) == CNTL_SRQ) /* service request and not controller? */ - assert |= BUS_SRQ; /* assert SRQ on bus */ + if ((data & (CNTL_SRQ | CNTL_CIC)) == CNTL_SRQ) /* if service request and not the controller */ + assert |= BUS_SRQ; /* then assert SRQ on the bus */ else /* else */ - deny |= BUS_SRQ; /* deny SRQ on bus */ + deny |= BUS_SRQ; /* deny SRQ on the bus */ - di_card->cntl_register = data; /* save control word */ - di_bus_control (card, CONTROLLER, assert, deny); /* update bus control state */ + di_card->cntl_register = data; /* save the control word */ + di_bus_control (card, CONTROLLER, assert, deny); /* update the bus control state */ } - if (update_required && !(signal_set & ioCLF)) /* if update and CLF not present, */ - update_state (card); /* update state, else ioCLF will update */ + if (update_required && !(signal_set & ioCLF)) /* if update required and CLF is not present, */ + update_state (card); /* update the state, else ioCLF will update it */ break; case ioPOPIO: /* power-on preset to I/O */ - di_card->flag = SET; /* set flag */ + di_card->flag = SET; /* set the flag */ di_card->flagbuf = SET; /* and flag buffer */ if (DEBUG_PRJ (dptrs [card], DEB_CMDS)) @@ -666,19 +666,19 @@ while (working_set) { di_card->status_register &= /* clear listen and talk status */ ~(STAT_LSTN | STAT_TALK); - deny = BUS_SRQ | BUS_REN | BUS_ATN | BUS_EOI; /* clear lines driven by control register */ + deny = BUS_SRQ | BUS_REN | BUS_ATN | BUS_EOI; /* clear the lines driven by the control register */ if (di_card->cntl_register & (CNTL_NRFD | CNTL_LSTN)) /* if asserting NRFD or listening */ - deny |= BUS_NRFD; /* deny because we're clearing */ + deny |= BUS_NRFD; /* then deny because we're clearing */ - di_card->cntl_register = 0; /* clear control word register */ + di_card->cntl_register = 0; /* clear the control word register */ di_card->control = CLEAR; /* clear control */ - di_card->srq = CLEAR; /* clear srq */ + di_card->srq = CLEAR; /* clear SRQ */ - master_reset (card); /* master reset */ + master_reset (card); /* perform a master reset */ - di_bus_control (card, CONTROLLER, 0, deny); /* update bus control state */ - update_state (card); /* update card state */ + di_bus_control (card, CONTROLLER, 0, deny); /* update the bus control state */ + update_state (card); /* update the card state */ break; @@ -689,14 +689,14 @@ while (working_set) { fprintf (sim_deb, ">>%s cmds: [CLC%s] Control cleared (configure mode)", dptrs [card]->name, hold_or_clear); - if (signal_set & ioCLF) /* if ioCLF given, */ - fputs (", master reset\n", sim_deb); /* then report master reset */ + if (signal_set & ioCLF) /* if ioCLF is given, */ + fputs (", master reset\n", sim_deb); /* then report a master reset */ else fputc ('\n', sim_deb); } - if (signal_set & ioCLF) /* if ioCLF given, */ - master_reset (card); /* then do master reset */ + if (signal_set & ioCLF) /* if ioCLF is given, */ + master_reset (card); /* then do a master reset */ break; /* (ioCLF will call update_state for us) */ @@ -717,16 +717,16 @@ while (working_set) { case ioSIR: /* set interrupt request */ - setstdPRL (di [card]); /* set standard PRL signal */ - setstdIRQ (di [card]); /* set standard IRQ signal */ + setstdPRL (di [card]); /* set the standard PRL signal */ + setstdIRQ (di [card]); /* set the standard IRQ signal */ - setSRQ (dibptr->select_code, /* set SRQ signal from control and SRQ */ + setSRQ (dibptr->select_code, /* set the SRQ signal if control and SRQ are set */ di_card->srq == SET && di_card->control == SET); break; case ioIAK: /* interrupt acknowledge */ - di_card->flagbuf = CLEAR; /* clear flag buffer */ + di_card->flagbuf = CLEAR; /* clear the flag buffer */ break; @@ -734,7 +734,7 @@ while (working_set) { break; /* are ignored */ } - working_set = working_set & ~signal; /* remove current signal from set */ + working_set = working_set & ~signal; /* remove the current signal from the set */ } return stat_data; @@ -745,7 +745,7 @@ return stat_data; During a hardware PRESET, POPIO sets the flag buffer and flag flip-flops, and CRS clears the control flip-flop and Control Word Register. In addition, CRS - asserts a master reset on the card. + performs a master reset on the card. PON is not used by the card. @@ -754,33 +754,33 @@ return stat_data; 1. During a power-on reset, a pointer to the FIFO simulation register is saved to allow access to the "qptr" field during FIFO loading and - unloading. This enables the SCP to view the FIFO as a circular queue, so + unloading. This enables SCP to view the FIFO as a circular queue, so that the bottom word of the FIFO is always displayed as FIFO[0], regardless of where it is in the actual FIFO array. */ t_stat di_reset (DEVICE *dptr) { -DIB *dibptr = (DIB *) dptr->ctxt; /* DIB pointer */ -const CARD_ID card = (CARD_ID) (dibptr->card_index); /* card number */ +DIB *dibptr = (DIB *) dptr->ctxt; /* get the DIB pointer */ +const CARD_ID card = (CARD_ID) (dibptr->card_index); /* get the card number */ -if (sim_switches & SWMASK ('P')) { /* power-on reset? */ +if (sim_switches & SWMASK ('P')) { /* is this a power-on reset? */ di [card].fifo_reg = find_reg ("FIFO", NULL, dptr); /* find the FIFO register entry */ - if (di [card].fifo_reg == NULL) /* not there? */ - return SCPE_IERR; /* is a programming error! */ + if (di [card].fifo_reg == NULL) /* if not there */ + return SCPE_IERR; /* then this is a programming error! */ else /* found it */ - di [card].fifo_reg->qptr = 0; /* reset the FIFO bottom index */ + di [card].fifo_reg->qptr = 0; /* so reset the FIFO bottom index */ di [card].status_register = 0; /* clear the status word */ di [card].bus_cntl = 0; /* deny the HP-IB control lines */ - di [card].listeners = 0; /* clear map of listeners */ - di [card].talker = 0; /* clear map of talker */ - di [card].poll_response = 0; /* clear map of parallel poll responses */ + di [card].listeners = 0; /* clear the map of listeners */ + di [card].talker = 0; /* clear the map of talker */ + di [card].poll_response = 0; /* clear the map of parallel poll responses */ - di [card].ifc_timer = 0.0; /* clear IFC timer */ + di [card].ifc_timer = 0.0; /* clear the IFC timer */ } IOPRESET (dibptr); /* PRESET the device */ @@ -814,9 +814,9 @@ return SCPE_OK; Also, an address cannot be set that duplicates the address of a disabled unit (which cannot be displayed without enabling it). - An alternate method would be to set the new assignments into a "shadow - array" that is set into the unit flags (and checked for validity) only - when a power-on reset is done. This does follow the disc and tape + An alternate implementation would be to set the new assignments into a + "shadow array" that is set into the unit flags (and checked for validity) + only when a power-on reset is done. This would follow the disc and tape controller hardware, which reads the HP-IB address switch settings only at power-up. */ @@ -828,19 +828,19 @@ uint32 index, new_address; uint32 old_address = GET_BUSADR (uptr->flags); DEVICE *dptr = (DEVICE *) desc; -if (cptr == NULL) /* if address not given */ +if (cptr == NULL) /* if the address is not given */ return SCPE_ARG; /* report a missing argument */ new_address = get_uint (cptr, 10, 7, &status); /* parse the address value */ -if (status == SCPE_OK) { /* parse OK? */ - if (value) /* setting the card address? */ - dptr->flags = dptr->flags & ~DEV_BUSADR /* store new address in the device flags */ +if (status == SCPE_OK) { /* is the parse OK? */ + if (value) /* are we setting the card address? */ + dptr->flags = dptr->flags & ~DEV_BUSADR /* store the new address in the device flags */ | SET_DIADR (new_address); - else { /* setting a unit address */ - for (index = 0; index < dptr->numunits; index++) /* look through units */ - if (new_address != old_address /* to ensure address is unique */ + else { /* we are setting a unit address */ + for (index = 0; index < dptr->numunits; index++) /* look through the units */ + if (new_address != old_address /* to ensure that the address is unique */ && new_address == GET_BUSADR (dptr->units [index].flags)) { printf ("Bus address conflict: DA%d\n", index); @@ -850,8 +850,8 @@ if (status == SCPE_OK) { /* parse OK? */ return SCPE_NOFNC; /* a duplicate address gives an error */ } - uptr->flags = uptr->flags & ~UNIT_BUSADR /* address is valid; change */ - | SET_BUSADR (new_address); /* the address in the unit flags */ + uptr->flags = uptr->flags & ~UNIT_BUSADR /* the address is valid; change it */ + | SET_BUSADR (new_address); /* in the unit flags */ } } @@ -869,10 +869,10 @@ t_stat di_show_address (FILE *st, UNIT *uptr, int32 value, void *desc) { DEVICE *dptr = (DEVICE *) desc; -if (value) /* card address? */ - fprintf (st, "address=%d", GET_DIADR (dptr->flags)); /* get from device flags */ -else /* unit address */ - fprintf (st, "bus=%d", GET_BUSADR (uptr->flags)); /* get from unit flags */ +if (value) /* do we want the card address? */ + fprintf (st, "address=%d", GET_DIADR (dptr->flags)); /* get it from the device flags */ +else /* we want the unit address */ + fprintf (st, "bus=%d", GET_BUSADR (uptr->flags)); /* get it from the unit flags */ return SCPE_OK; } @@ -898,14 +898,14 @@ return SCPE_OK; t_stat di_set_cable (UNIT *uptr, int32 value, char *cptr, void *desc) { -if (value) { /* diagnostic cable selected? */ - ((DEVICE *) desc)->flags |= DEV_DIAG; /* set diagnostic flag */ - dc_dev.flags &= ~DEV_DIS; /* enable dummy device */ +if (value) { /* is the diagnostic cable selected? */ + ((DEVICE *) desc)->flags |= DEV_DIAG; /* set the diagnostic flag */ + dc_dev.flags &= ~DEV_DIS; /* enable the dummy device */ dc_dev.flags |= DEV_DIAG; /* and set its flag as well */ } -else { /* peripheral cable selected */ - ((DEVICE *) desc)->flags &= ~DEV_DIAG; /* clear diagnostic flag */ - dc_dev.flags |= DEV_DIS; /* disable dummy device */ +else { /* the peripheral cable is selected */ + ((DEVICE *) desc)->flags &= ~DEV_DIAG; /* clear the diagnostic flag */ + dc_dev.flags |= DEV_DIS; /* disable the dummy device */ dc_dev.flags &= ~DEV_DIAG; /* and clear its flag */ } @@ -921,9 +921,9 @@ return SCPE_OK; t_stat di_show_cable (FILE *st, UNIT *uptr, int32 value, void *desc) { -if (((DEVICE *) desc)->flags & DEV_DIAG) /* is cable connected for diagnostics? */ +if (((DEVICE *) desc)->flags & DEV_DIAG) /* is the cable connected for diagnostics? */ fputs ("diagnostic cable", st); /* report it */ -else /* cable is connected for normal use */ +else /* the cable is connected for device use */ fputs ("HP-IB cable", st); /* report the condition */ return SCPE_OK; @@ -936,13 +936,13 @@ return SCPE_OK; In hardware, the HP-IB bus consists of eight control lines and eight data lines. Signals are asserted on the control lines to establish communication between a source and one or more acceptors. For commands, the source is - always the controller (the 12821A card), and the acceptors are all connected - devices. For data, the source is the current talker, and the acceptors are - one or more current listeners. A three-wire interlocking handshake enables - communication at the rate of the slowest of the multiple acceptors. The - controller conducts a parallel poll by asserting ATN and EOI together. - Devices whose parallel poll responses are enabled each assert one of the data - lines to indicate that service is required. + always the controller (the 12821A card), and the acceptors are all of the + connected devices. For data, the source is the current talker, and the + acceptors are one or more current listeners. A three-wire interlocking + handshake enables communication at the rate of the slowest of the multiple + acceptors. The controller conducts a parallel poll by asserting ATN and EOI + together. Devices whose parallel poll responses are enabled each assert one + of the data lines to indicate that service is required. In simulation, a disabled or detached unit logically is not connected to the bus. The card maintains a bitmap of acceptors (all devices currently @@ -970,18 +970,18 @@ return SCPE_OK; listeners) and FALSE if it was not. Called by the controller to send commands to devices, and called by the current talker to send data to the listener(s). ATN - and EOI should be set as required in the control word - before calling. + and EOI should be asserted as required on the bus before + calling. *_bus_accept -- Accept a data byte from the bus. Returns TRUE if the byte was accepted and FALSE if it was not. Called by di_bus_source to handshake between source and acceptor. - If ATN is set in the control word, the byte is a - command; otherwise, it is data. If EOI is set for a - data byte, it is the last byte of a transmission. + If ATN is asserted on the bus, the byte is a command; + otherwise, it is data. If EOI is asserted for a data + byte, it is the last byte of a transmission. di_bus_control -- Set the control lines on the bus. Called by the system - controller to assert or deny REN or IFC, by the + controller to assert or deny REN or IFC, by the current controller to assert or deny SRQ, NRFD, or ATN and EOI (to conduct or conclude a parallel poll), and by the current listener to assert or deny NRFD. All connected @@ -1008,8 +1008,8 @@ return SCPE_OK; card is not in diagnostic mode, then the byte is sent to all acceptors (if a command) or to all listeners (if data) on the bus. - An indication is returned showing whether or not there were any acceptors on - the bus. + The return value indicates whether or not there were any acceptors on the + bus. Implementation notes: @@ -1032,29 +1032,29 @@ if (DEBUG_PRJ (dptrs [card], DEB_XFER)) { fprint_bus (sim_deb, "[%s]\n", di [card].bus_cntl); } -if (dptrs [card]->flags & DEV_DIAG) /* diagnostic run? */ - for (other = first_card; other <= last_card; other++) { /* look through list of cards */ +if (dptrs [card]->flags & DEV_DIAG) /* is this a diagnostic run? */ + for (other = first_card; other <= last_card; other++) { /* look through the list of cards */ if (other != card && dptrs [other] /* for the other card */ - && (dptrs [other]->flags & DEV_DIAG) /* that is configured for diagnostic */ + && (dptrs [other]->flags & DEV_DIAG) /* that is configured for diagnostic mode */ && (di [other].cntl_register & CNTL_LSTN)) /* and is listening */ - accepted = di_bus_accept (other, data); /* call interface acceptor for other card */ + accepted = di_bus_accept (other, data); /* call the interface acceptor for the other card */ } -else if ((di [card].bus_cntl & BUS_PPOLL) != BUS_PPOLL) { /* normal run; not a fake poll? */ - if (di [card].cntl_register & CNTL_LSTN) /* is card a listener? */ - accepted = di_bus_accept (card, data); /* call interface acceptor for this card */ +else if ((di [card].bus_cntl & BUS_PPOLL) != BUS_PPOLL) { /* this is a normal run; not a fake poll? */ + if (di [card].cntl_register & CNTL_LSTN) /* is the card a listener? */ + accepted = di_bus_accept (card, data); /* call the interface acceptor for this card */ - acceptors = di [card].acceptors; /* get map of acceptors */ + acceptors = di [card].acceptors; /* get the map of acceptors */ if (!(di [card].bus_cntl & BUS_ATN) /* if a data transfer, */ || (data & BUS_COMMAND) == BUS_ACG) /* or an addressed command, e.g., SDC */ acceptors = di [card].listeners; /* then limit just to listeners */ - for (unit = 0; acceptors; unit++) { /* loop through units */ - if (acceptors & 1) /* is current unit accepting? */ - accepted |= (*bus_accept [card]) (unit, data); /* call acceptor for this card */ + for (unit = 0; acceptors; unit++) { /* loop through the units */ + if (acceptors & 1) /* is the current unit accepting? */ + accepted |= (*bus_accept [card]) (unit, data); /* call the acceptor for this card */ - acceptors = acceptors >> 1; /* move to next acceptor */ + acceptors = acceptors >> 1; /* move to the next acceptor */ } } @@ -1114,13 +1114,13 @@ uint32 acceptors, responder; t_bool responded; uint8 new_state, new_assertions, new_denials; -new_state = di [card].bus_cntl & ~deny | assert; /* set up new control state */ +new_state = di [card].bus_cntl & ~deny | assert; /* set up the new control state */ -if (new_state == di [card].bus_cntl) /* if control state did not change */ +if (new_state == di [card].bus_cntl) /* if the control state did not change */ return; /* return now */ -new_assertions = ~di [card].bus_cntl & assert; /* get changing assertions */ -new_denials = di [card].bus_cntl & deny; /* get changing denials */ +new_assertions = ~di [card].bus_cntl & assert; /* get the changing assertions */ +new_denials = di [card].bus_cntl & deny; /* get the changing denials */ di [card].bus_cntl = new_state; /* establish the new control state */ @@ -1140,31 +1140,31 @@ if (DEBUG_PRJ (dptrs [card], DEB_XFER)) { fprint_bus (sim_deb, ", bus is [%s]\n", new_state); } -if ((dptrs [card]->flags & DEV_DIAG) /* diagnostic mode? */ - || (new_assertions & ASSERT_SET) /* or changed signals in the */ - || (new_denials & DENY_SET)) { /* set that must be broadcast? */ - responded = FALSE; /* assume no response */ +if ((dptrs [card]->flags & DEV_DIAG) /* is the card in diagnostic mode? */ + || (new_assertions & ASSERT_SET) /* or are changed signals in the */ + || (new_denials & DENY_SET)) { /* set that must be broadcast? */ + responded = FALSE; /* assume no response was received */ - if (dptrs [card]->flags & DEV_DIAG) { /* diagnostic run? */ - for (other = first_card; other <= last_card; other++) /* look through list of cards */ + if (dptrs [card]->flags & DEV_DIAG) { /* is this a diagnostic run? */ + for (other = first_card; other <= last_card; other++) /* look through the list of cards */ if (other != card && dptrs [other] /* for the other card */ - && (dptrs [other]->flags & DEV_DIAG)) { /* that is configured for diagnostic */ - di_bus_respond (other, new_state); /* notify other card of new control state */ + && (dptrs [other]->flags & DEV_DIAG)) { /* that is configured for diagnostic */ + di_bus_respond (other, new_state); /* notify the other card of the new control state */ responded = TRUE; /* and note that there was a responder */ } } - else { /* normal run */ - update_state (card); /* update card for new control state */ + else { /* this is a normal run */ + update_state (card); /* update the card for the new control state */ - acceptors = di [card].acceptors; /* get map of acceptors */ - responded = (acceptors != 0); /* set if there are any acceptors */ + acceptors = di [card].acceptors; /* get the map of acceptors */ + responded = (acceptors != 0); /* set response if there are any acceptors */ - for (responder = 0; acceptors; responder++) { /* loop through units */ - if ((acceptors & 1) && responder != unit) /* is current unit accepting? */ - (*bus_respond [card]) (card, responder, new_state); /* call responder for this card */ + for (responder = 0; acceptors; responder++) { /* loop the through units */ + if ((acceptors & 1) && responder != unit) /* is the current unit accepting? */ + (*bus_respond [card]) (card, responder, new_state); /* call the responder for this card */ - acceptors = acceptors >> 1; /* move to next acceptor */ + acceptors = acceptors >> 1; /* move to the next acceptor */ } } @@ -1173,7 +1173,7 @@ if ((dptrs [card]->flags & DEV_DIAG) /* diagnostic mo dptrs [card]->name); } -if ((new_state & BUS_PPOLL) == BUS_PPOLL) /* parallel poll requested? */ +if ((new_state & BUS_PPOLL) == BUS_PPOLL) /* was a parallel poll requested? */ di_bus_poll (card); /* conduct the poll */ return; @@ -1192,14 +1192,14 @@ void di_poll_response (CARD_ID card, uint32 unit, FLIP_FLOP response) const uint32 address = GET_BUSADR (dptrs [card]->units [unit].flags); uint32 previous_response = di [card].poll_response; -if (response == SET) { /* enable PPR? */ - di [card].poll_response |= PPR (address); /* set response bit */ +if (response == SET) { /* enable the poll response? */ + di [card].poll_response |= PPR (address); /* set the response bit */ - if ((di [card].bus_cntl & BUS_PPOLL) == BUS_PPOLL) /* is parallel poll in progress? */ - di_bus_poll (card); /* conduct with new response */ + if ((di [card].bus_cntl & BUS_PPOLL) == BUS_PPOLL) /* is a parallel poll in progress? */ + di_bus_poll (card); /* conduct again with the new response */ } -else /* disable PPR */ - di [card].poll_response &= ~PPR (address); /* clear response bit */ +else /* disable the poll response */ + di [card].poll_response &= ~PPR (address); /* by clearing the response bit */ if (DEBUG_PRJ (dptrs [card], DEB_XFER) && previous_response != di [card].poll_response) @@ -1218,11 +1218,11 @@ return; A controller asserting ATN and EOI simultaneously on the bus is conducting a parallel poll. In hardware, each device whose poll response is enabled - asserts one of the data lines corresponding to its bus address. The - controller terminates the poll by denying ATN and EOI. + asserts the data line corresponding to its bus address. The controller + terminates the poll by denying ATN and EOI. Setting the CIC (controller in charge) and PPE (parallel poll enable) bits in - the Control Word Register directs the disc interface to conduct a poll. + the Control Word Register direct the disc interface to conduct a poll. Setting PPE without CIC enables the poll response for the interface. In the diagnostic mode, one card is set to conduct the poll, and the other is @@ -1243,30 +1243,30 @@ CARD_ID other; uint8 response; if ((di [card].cntl_register - & (CNTL_PPE | CNTL_CIC)) == CNTL_PPE) /* card poll response enabled? */ - response = di [card].poll_response /* add card's response */ + & (CNTL_PPE | CNTL_CIC)) == CNTL_PPE) /* is the card's poll response enabled? */ + response = di [card].poll_response /* add the card's response */ | PPR (GET_DIADR (dptrs [card]->flags)); /* to the devices' responses */ else - response = di [card].poll_response; /* card disabled, so just use devices */ + response = di [card].poll_response; /* the card response is disabled, so just use devices */ -if (dptrs [card]->flags & DEV_DIAG) /* diagnostic run? */ - for (other = first_card; other <= last_card; other++) /* look through list of cards */ +if (dptrs [card]->flags & DEV_DIAG) /* is this a diagnostic run? */ + for (other = first_card; other <= last_card; other++) /* look through the list of cards */ if (other != card && dptrs [other] /* for another card */ - && (dptrs [other]->flags & DEV_DIAG) /* that is configured for diagnostic */ - && (di [other].cntl_register /* and has PPE asserted */ + && (dptrs [other]->flags & DEV_DIAG) /* that is configured for the diagnostic */ + && (di [other].cntl_register /* and has PPE asserted */ & (CNTL_PPE | CNTL_CIC)) == CNTL_PPE) response |= /* merge its poll response */ PPR (GET_DIADR (dptrs [other]->flags)); -if (response) { /* poll response indicated? */ +if (response) { /* is a poll response indicated? */ if (DEBUG_PRJ (dptrs [card], DEB_XFER)) fprintf (sim_deb, ">>%s xfer: HP-IB parallel poll DIO %03o\n", dptrs [card]->name, response); - while (di [card].fifo_count != FIFO_SIZE) /* fill card FIFO with responses */ + while (di [card].fifo_count != FIFO_SIZE) /* fill the card FIFO with the responses */ fifo_load (card, (uint16) response, diag_access); /* (hardware feature) */ - update_state (card); /* update card state */ + update_state (card); /* update the card state */ } return; @@ -1278,7 +1278,7 @@ return; The indicated card accepts a byte that has been sourced to the bus. The byte is loaded into the FIFO, and the card state is updated to reflect the load. - Bus acceptors return TRUE to indicate if the byte was accepted. A card + Bus acceptors return TRUE to indicate that the byte was accepted. A card always accepts a byte, so the routine always returns TRUE. */ @@ -1288,9 +1288,9 @@ if (DEBUG_PRJ (dptrs [card], DEB_XFER)) fprintf (sim_deb, ">>%s xfer: HP-IB card %d accepted data %03o \n", dptrs [card]->name, card, data); -fifo_load (card, data, bus_access); /* load data byte into the FIFO */ +fifo_load (card, data, bus_access); /* load the data byte into the FIFO */ update_state (card); /* and update the card state */ -return TRUE; /* indicate the byte was accepted */ +return TRUE; /* indicate that the byte was accepted */ } @@ -1303,8 +1303,8 @@ return TRUE; /* indicate the byte was static void di_bus_respond (CARD_ID card, uint8 new_cntl) { -di [card].bus_cntl = new_cntl; /* update bus control */ -update_state (card); /* update card state */ +di [card].bus_cntl = new_cntl; /* update the bus control lines */ +update_state (card); /* update the card state */ return; } @@ -1320,11 +1320,11 @@ return; The primary use, other than during a PRESET, is to clear the FIFO in preparation to changing the card from a listener to a talker or vice versa. This ensures that unneeded FIFO data is not transmitted inadvertently to the - bus or the CPU. It is also used when changing the data mode from unpacked to - packed to release the byte pointer flip-flops, which are held in the "lower - byte" position during unpacked transfers. + bus or to the CPU. It is also used when changing the data mode from unpacked + to packed to release the byte pointer flip-flops, which are held in the + "lower byte" position during unpacked transfers. - In hardware, master reset: + In hardware, a master reset: - clears the EDT, EOR, IRL, LBO, LBI, and IFC flip-flops - clears the Input Data Register - clears the FIFO @@ -1339,11 +1339,11 @@ di [card].edt = CLEAR; /* clear the EDT flip-fl di [card].eor = CLEAR; /* clear the EOR flip-flop */ if (di [card].cntl_register & CNTL_PACK) /* if packed mode is set, */ - di [card].ibp = di [card].obp = upper; /* MR sets selectors to the upper byte */ + di [card].ibp = di [card].obp = upper; /* MR sets the selectors to the upper byte */ else /* otherwise, unpacked mode overrides */ di [card].ibp = di [card].obp = lower; /* and sets the selectors to the lower byte */ -di [card].status_register &= /* clear status flip-flops */ +di [card].status_register &= /* clear the status flip-flops */ ~(STAT_IRL | STAT_LBO | STAT_LBI | STAT_IFC); di [card].input_data_register = 0; /* clear the input data register */ @@ -1368,31 +1368,31 @@ return; In simulation, this routine must be called whenever the FIFO, card control, or bus control state changes. It determines whether: - 1. the next word from the FIFO should be unloaded into the IDR. If the card - is listening, and the IDR is empty, and the FIFO contains data, then a - word is unloaded and stored in the IDR, and the Input Register Loaded + 1. ...the next word from the FIFO should be unloaded into the IDR. If the + card is listening, and the IDR is empty, and the FIFO contains data, then + a word is unloaded and stored in the IDR, and the Input Register Loaded status bit is set. - 2. the next word from the FIFO should be unloaded and sourced to the bus. + 2. ...the next word from the FIFO should be unloaded and sourced to the bus. If the card is talking (but not polling), and the listener is ready to accept data, and the last byte has not been sent, and the FIFO contains data, then a word is unloaded and sourced to the bus. This occurs regardless of whether or not there are any listeners. - 3. an interface clear operation has completed. If IFC is asserted, and the - current simulation time is later than the IFC expiration time, then IFC - is denied, and the timer is reset. + 3. ...an interface clear operation has completed. If IFC is asserted, and + the current simulation time is later than the IFC expiration time, then + IFC is denied, and the timer is reset. - 4. the card should assert NRFD to prevent FIFO overflow. If the card is + 4. ...the card should assert NRFD to prevent FIFO overflow. If the card is listening, and the FIFO is full, or the last byte has been received, or a pause has been explicitly requested, then NRFD is asserted. - 5. the SRQ flip-flop should be set or cleared. If the card is listening and - the Input Data Register has been loaded, or the card is talking and the - FIFO is not full, then SRQ is asserted to request a DCPC transfer. + 5. ...the SRQ flip-flop should be set or cleared. If the card is listening + and the Input Data Register has been loaded, or the card is talking and + the FIFO is not full, then SRQ is asserted to request a DCPC transfer. - 6. the flag flip-flop should be set or cleared. If the Input Data Register - has been loaded or the Last Byte Out flip-flop is set and the + 6. ...the flag flip-flop should be set or cleared. If the Input Data + Register has been loaded or the Last Byte Out flip-flop is set and the corresponding Control Word Register IRL or LBO bits are set, or the End of Record flip-flop is set and the Input Data Register has been unloaded, or SRQ is asserted on the bus and the corresponding Control Word Register @@ -1424,55 +1424,55 @@ uint8 deny = 0; uint16 data; FLIP_FLOP previous_state; -if (di_card->cntl_register & CNTL_LSTN) { /* is card a listener? */ - if (!(di_card->status_register & STAT_IRL) /* is IDR empty? */ - && ! FIFO_EMPTY) { /* and more in FIFO? */ - data = fifo_unload (card, cpu_access); /* unload FIFO */ - di_card->input_data_register = data; /* into IDR */ - di_card->status_register |= STAT_IRL; /* set input register loaded status */ +if (di_card->cntl_register & CNTL_LSTN) { /* is the card a listener? */ + if (!(di_card->status_register & STAT_IRL) /* is the IDR empty? */ + && ! FIFO_EMPTY) { /* and data remains in the FIFO? */ + data = fifo_unload (card, cpu_access); /* unload the FIFO */ + di_card->input_data_register = data; /* into the IDR */ + di_card->status_register |= STAT_IRL; /* set the input register loaded status */ } } -else if ((di_card->cntl_register /* is card a talker? */ +else if ((di_card->cntl_register /* is the card a talker? */ & (CNTL_TALK | CNTL_PPE)) == CNTL_TALK) /* and not polling? */ while (! FIFO_EMPTY /* is data remaining in FIFO? */ - && !(di_card->bus_cntl & BUS_NRFD) /* and NRFD denied? */ - && !(di_card->status_register & STAT_LBO)) { /* and last byte not sent? */ - data = fifo_unload (card, bus_access); /* unload FIFO byte */ - di_bus_source (card, (uint8) data); /* source it to bus */ + && !(di_card->bus_cntl & BUS_NRFD) /* and NRFD is denied? */ + && !(di_card->status_register & STAT_LBO)) { /* and the last byte has not been sent? */ + data = fifo_unload (card, bus_access); /* unload a FIFO byte */ + di_bus_source (card, (uint8) data); /* source it to the bus */ } -if (di_card->bus_cntl & BUS_IFC /* IFC in progress? */ +if (di_card->bus_cntl & BUS_IFC /* is an IFC in progress? */ && di_card->ifc_timer != 0.0 /* and I am timing? */ - && sim_gtime () > di_card->ifc_timer) { /* and timeout has elapsed? */ - deny = BUS_IFC; /* deny IFC on bus */ - di_card->ifc_timer = 0.0; /* clear IFC timer */ - di_card->status_register &= ~STAT_IFC; /* clear IFC status */ + && sim_gtime () > di_card->ifc_timer) { /* and has the timeout elapsed? */ + deny = BUS_IFC; /* deny IFC on the bus */ + di_card->ifc_timer = 0.0; /* clear the IFC timer */ + di_card->status_register &= ~STAT_IFC; /* and clear IFC status */ } -if (di_card->cntl_register & CNTL_LSTN) /* is card a listener? */ +if (di_card->cntl_register & CNTL_LSTN) /* is the card a listener? */ if (di_card->cntl_register & CNTL_NRFD /* if explicitly requested */ - || di_card->status_register & STAT_LBI /* or last byte is in */ - || FIFO_FULL) /* or FIFO is full */ + || di_card->status_register & STAT_LBI /* or the last byte is in */ + || FIFO_FULL) /* or the FIFO is full */ assert = BUS_NRFD; /* then assert NRFD */ - else /* otherwise card is ready for data */ + else /* otherwise the card is ready for data */ deny |= BUS_NRFD; /* so deny NRFD */ -if (assert != deny) /* any change in bus state? */ - di_bus_control (card, CONTROLLER, assert, deny); /* update bus control */ +if (assert != deny) /* was there any change in bus state? */ + di_bus_control (card, CONTROLLER, assert, deny); /* update the bus control */ -previous_state = di_card->srq; /* save current SRQ state */ +previous_state = di_card->srq; /* save the current SRQ state */ -if (di_card->cntl_register & CNTL_LSTN /* if card is a listener */ - && di_card->status_register & STAT_IRL /* and input register is loaded, */ - || di_card->cntl_register & CNTL_TALK /* or card is a talker */ - && ! FIFO_FULL) /* and FIFO is not full */ +if (di_card->cntl_register & CNTL_LSTN /* if the card is a listener */ + && di_card->status_register & STAT_IRL /* and the input register is loaded, */ + || di_card->cntl_register & CNTL_TALK /* or the card is a talker */ + && ! FIFO_FULL) /* and the FIFO is not full */ di_card->srq = SET; /* then request a DCPC cycle */ else - di_card->srq = CLEAR; /* else DCPC service is not needed */ + di_card->srq = CLEAR; /* otherwise, DCPC service is not needed */ if (DEBUG_PRJ (dptrs [card], DEB_CMDS) @@ -1481,27 +1481,27 @@ if (DEBUG_PRJ (dptrs [card], DEB_CMDS) dptrs [card]->name, di_card->srq == SET ? "set" : "cleared"); -if (di_card->status_register & STAT_IRL /* input register loaded */ - && di_card->cntl_register & CNTL_IRL /* and notification wanted? */ - || di_card->status_register & STAT_LBO /* or last byte out */ - && di_card->cntl_register & CNTL_LBO /* and notification wanted? */ - || di_card->eor == SET /* or end of record seen */ - && !(di_card->status_register & STAT_IRL) /* and input register unloaded? */ - || di_card->bus_cntl & BUS_SRQ /* or SRQ is asserted on the bus */ - && di_card->cntl_register & CNTL_SRQ /* and notification wanted */ - && di_card->cntl_register & CNTL_CIC /* and card is not controller? */ - || !SW8_SYSCTL /* or card is not system controller */ +if (di_card->status_register & STAT_IRL /* is the input register loaded */ + && di_card->cntl_register & CNTL_IRL /* and notification is wanted? */ + || di_card->status_register & STAT_LBO /* or is the last byte out */ + && di_card->cntl_register & CNTL_LBO /* and notification is wanted? */ + || di_card->eor == SET /* or was the end of record seen */ + && !(di_card->status_register & STAT_IRL) /* and the input register was unloaded? */ + || di_card->bus_cntl & BUS_SRQ /* or is SRQ asserted on the bus */ + && di_card->cntl_register & CNTL_SRQ /* and notification is wanted */ + && di_card->cntl_register & CNTL_CIC /* and the card is not controller? */ + || !SW8_SYSCTL /* or is the card not the system controller */ && di_card->bus_cntl & BUS_REN /* and REN is asserted on the bus */ - && di_card->cntl_register & CNTL_REN /* and notification wanted? */ - || !SW8_SYSCTL /* or card is not system controller */ + && di_card->cntl_register & CNTL_REN /* and notification is wanted? */ + || !SW8_SYSCTL /* or is the card not the system controller */ && di_card->status_register & STAT_IFC /* and IFC is asserted on the bus */ - && di_card->cntl_register & CNTL_IFC) { /* and notification wanted? */ + && di_card->cntl_register & CNTL_IFC) { /* and notification is wanted? */ if (DEBUG_PRJ (dptrs [card], DEB_CMDS)) fprintf (sim_deb, ">>%s cmds: Flag set\n", dptrs [card]->name); - di_io (dibptr, ioENF, 0); /* set flag and recalculate interrupts */ + di_io (dibptr, ioENF, 0); /* set the flag and recalculate interrupts */ } else if (di_card->srq != previous_state) /* if SRQ changed state, */ @@ -1610,70 +1610,70 @@ if (FIFO_FULL) { /* is the FIFO already f fprintf (sim_deb, ">>%s buf: Attempted load to full FIFO, data %0*o\n", dptrs [card]->name, (access == bus_access ? 3 : 6), data); - return; /* return with load ignored */ + return; /* return with the load ignored */ } -if (di_card->cntl_register & CNTL_LSTN) { /* is card receiving? */ - tag = (di_card->bus_cntl /* set tag from bus signals */ - & (BUS_ATN | BUS_EOI)) << BUS_SHIFT; /* shifted to tag locations */ +if (di_card->cntl_register & CNTL_LSTN) { /* is the card receiving? */ + tag = (di_card->bus_cntl /* set the tag from the bus signals */ + & (BUS_ATN | BUS_EOI)) << BUS_SHIFT; /* shifted to the tag locations */ - if ((di_card->cntl_register & CNTL_EOI /* EOI detection enabled, */ + if ((di_card->cntl_register & CNTL_EOI /* EOI detection is enabled, */ && di_card->bus_cntl & BUS_EOI) /* and data was tagged with EOI? */ - || (di_card->cntl_register & CNTL_LF /* or LF detection enabled, */ - && GET_LOWER (data) == LF)) { /* and byte is a line feed? */ - tag = tag | TAG_LBR; /* tag as last byte received */ - di_card->status_register |= STAT_LBI; /* set last byte in status */ + || (di_card->cntl_register & CNTL_LF /* or LF detection is enabled, */ + && GET_LOWER (data) == LF)) { /* and the byte is a line feed? */ + tag = tag | TAG_LBR; /* tag as the last byte received */ + di_card->status_register |= STAT_LBI; /* set the last byte in status */ } - else /* neither termination condition seen */ - di_card->status_register &= ~STAT_LBI; /* so clear last byte in status */ + else /* neither termination condition was seen */ + di_card->status_register &= ~STAT_LBI; /* so clear the last byte in status */ } -else /* card is transmitting */ - tag = (data & (DATA_ATN | DATA_EOI)) << DATA_SHIFT; /* set tag from data shifted to tag location */ +else /* the card is transmitting */ + tag = (data & (DATA_ATN | DATA_EOI)) << DATA_SHIFT; /* set the tag from the data shifted to the tag location */ -if (di_card->edt == SET) /* end of data transfer? */ - tag = tag | TAG_EDT; /* set EDT tag */ +if (di_card->edt == SET) /* is this the end of the data transfer? */ + tag = tag | TAG_EDT; /* set the EDT tag */ -index = (di_card->fifo_reg->qptr /* calculate index */ - + di_card->fifo_count) % FIFO_SIZE; /* of next available location */ +index = (di_card->fifo_reg->qptr /* calculate the index */ + + di_card->fifo_count) % FIFO_SIZE; /* of the next available location */ -if (access == bus_access) { /* bus access? */ - if (di_card->ibp == upper) { /* packed and this is the upper byte? */ - di_card->ibp = lower; /* set lower byte as next */ +if (access == bus_access) { /* is this a bus access */ + if (di_card->ibp == upper) { /* in packed mode for the upper byte? */ + di_card->ibp = lower; /* set the lower byte as next */ if (tag & TAG_LBR) /* is this the last byte? */ - di_card->fifo [index] = /* copy to both bytes of FIFO */ - tag | SET_BOTH (data); /* and store with tag */ - else { /* more bytes expected */ + di_card->fifo [index] = /* copy to both bytes of the FIFO */ + tag | SET_BOTH (data); /* and store with the tag */ + else { /* more bytes are expected */ di_card->fifo [index] = /* so position this byte */ - tag | SET_UPPER (data); /* and store with tag */ - add_word = FALSE; /* wait for second byte before adding */ + tag | SET_UPPER (data); /* and store it with the tag */ + add_word = FALSE; /* wait for the second byte before adding */ } } else /* this is the lower byte */ - if (di_card->cntl_register & CNTL_PACK) { /* packed mode? */ - di_card->ibp = upper; /* set upper byte as next */ + if (di_card->cntl_register & CNTL_PACK) { /* is the card in packed mode? */ + di_card->ibp = upper; /* set the upper byte as next */ - di_card->fifo [index] = /* merge in data and tag */ + di_card->fifo [index] = /* merge the data and tag values */ tag | di_card->fifo [index] | SET_LOWER (data); } - else /* unpacked mode */ + else /* the card is in unpacked mode */ di_card->fifo [index] = /* position this byte */ - tag | SET_LOWER (data); /* and store with tag */ + tag | SET_LOWER (data); /* and store with the tag */ } -else if (access == cpu_access) /* cpu access? */ - di_card->fifo [index] = tag | data; /* store tag and full word in FIFO */ +else if (access == cpu_access) /* is this a cpu access? */ + di_card->fifo [index] = tag | data; /* store the tag and full word in the FIFO */ -else { /* diag access */ - data = SET_BOTH (GET_LOWER (data)); /* copy lower byte to upper byte */ - di_card->fifo [index] = tag | data; /* and store tag and full word in FIFO */ +else { /* must be diagnostic access */ + data = SET_BOTH (GET_LOWER (data)); /* copy the lower byte to the upper byte */ + di_card->fifo [index] = tag | data; /* and store the tag and full word in the FIFO */ } if (add_word) /* did we add a word to the FIFO? */ - di_card->fifo_count = di_card->fifo_count + 1; /* increment count of words stored */ + di_card->fifo_count = di_card->fifo_count + 1; /* increment the count of words stored */ if (DEBUG_PRJ (dptrs [card], DEB_BUF)) { fprintf (sim_deb, ">>%s buf: Data %0*o tag ", @@ -1746,10 +1746,10 @@ return; listening, or asserts the bus EOI line if talking; in packed mode, the tag is ignored). - ATN and EOI tag handling is a bit complex. If the card is listening in - the unpacked mode, the ATN tag substitutes for bit 8 of the data word, - and the EOI tag substitutes for bit 9. In the packed mode, bits 8 and 9 - are as stored in the FIFO (they are upper-byte data bits). + ATN and EOI tag handling is complex. If the card is listening in the + unpacked mode, the ATN tag substitutes for bit 8 of the data word, and + the EOI tag substitutes for bit 9. In the packed mode, bits 8 and 9 are + as stored in the FIFO (they are upper-byte data bits). If the card is talking in the unpacked mode, the ATN tag asserts or denies ATN on the bus if the card is the CIC, and the EOI tag asserts or @@ -1800,7 +1800,7 @@ if (FIFO_EMPTY) { /* is the FIFO already e return 0; /* return with no data */ } -data = di_card->fifo [di_card->fifo_reg->qptr]; /* get tag and data from the FIFO */ +data = di_card->fifo [di_card->fifo_reg->qptr]; /* get the tag and data from the FIFO */ tag = data & TAG_MASK; /* mask the tag to just the tag bits */ data = data & DMASK; /* and the data to just the data bits */ @@ -1811,9 +1811,9 @@ if (tag & TAG_EDT /* is this the end of a di_card->status_register |= STAT_LBO; /* set the last byte out status */ -if (access == cpu_access) { /* cpu access? */ - if (!(di_card->cntl_register & CNTL_PACK)) /* unpacked data format? */ - data = data & ~(DATA_ATN | DATA_EOI) /* substitute ATN/EOI tag values */ +if (access == cpu_access) { /* is this a cpu access? */ + if (!(di_card->cntl_register & CNTL_PACK)) /* in unpacked mode? */ + data = data & ~(DATA_ATN | DATA_EOI) /* substitute the ATN/EOI tag values */ | (tag & (TAG_ATN | TAG_EOI)) >> DATA_SHIFT; /* into the data word */ if (tag & TAG_LBR) /* is this the last byte? */ @@ -1822,7 +1822,7 @@ if (access == cpu_access) { /* cpu access? */ di_card->eor = CLEAR; /* the end-of-record flip-flop */ } -else if (access == bus_access) /* bus access? */ +else if (access == bus_access) /* is this a bus access? */ if (di_card->obp == upper) { /* is this the upper byte? */ di_card->obp = lower; /* set the lower byte as next */ data = GET_UPPER (data); /* mask and position the upper byte in the data word */ @@ -1832,11 +1832,11 @@ else if (access == bus_access) /* bus access? */ else { /* this is the lower byte */ data = GET_LOWER (data); /* mask and position it in the data word */ - if (di_card->cntl_register & CNTL_PACK) /* in packed mode? */ + if (di_card->cntl_register & CNTL_PACK) /* is the card in the packed mode? */ di_card->obp = upper; /* set the upper byte as next */ } -else /* diagnostic access */ +else /* must be a diagnostic access */ data = GET_LOWER (data); /* access is to the lower byte only */ @@ -1857,15 +1857,15 @@ if (DEBUG_PRJ (dptrs [card], DEB_BUF)) { if (di_card->cntl_register & CNTL_TALK) /* is the card talking? */ - if (di_card->cntl_register & CNTL_PACK) /* in packed mode? */ + if (di_card->cntl_register & CNTL_PACK) /* is it in the packed mode? */ if (di_card->status_register & STAT_LBO /* yes, is the last byte out? */ - && di_card->cntl_register & CNTL_EOI) /* and EOI control enabled? */ - di_card->bus_cntl |= BUS_EOI; /* assert EOI */ + && di_card->cntl_register & CNTL_EOI) /* and is EOI control enabled? */ + di_card->bus_cntl |= BUS_EOI; /* assert EOI on the bus */ else - di_card->bus_cntl &= ~BUS_EOI; /* deny EOI */ + di_card->bus_cntl &= ~BUS_EOI; /* deny EOI on the bus */ - else { /* in unpacked mode */ - if (di_card->cntl_register & CNTL_CIC) /* is card the controller in charge? */ + else { /* the card is in the unpacked mode */ + if (di_card->cntl_register & CNTL_CIC) /* is the card the controller in charge? */ di_card->bus_cntl = /* assert or deny the ATN bus line */ di_card->bus_cntl & ~BUS_ATN /* from the ATN tag value */ | (tag & TAG_ATN) >> BUS_SHIFT; @@ -1908,7 +1908,7 @@ static const char *cntl_names [] = { uint32 signal; char mnemonics [40]; -if (cntl == 0) /* any control signal asserted? */ +if (cntl == 0) /* are any control signals asserted? */ strcpy (mnemonics, "---"); /* no; use dashes in lieu of an empty string */ else { /* one or more signals are asserted */ diff --git a/HP2100/hp2100_di.h b/HP2100/hp2100_di.h index 79d742ab..08171b21 100644 --- a/HP2100/hp2100_di.h +++ b/HP2100/hp2100_di.h @@ -1,4 +1,4 @@ -/* hp2100_di.h: HP 12821A HP-IB Disc Interface simulator common definitions +/* hp2100_di.h: HP 12821A HP-IB Disc Interface simulator definitions Copyright (c) 2010-2012, J. David Bryan @@ -41,8 +41,8 @@ only the DA device is implemented. However, as the 12821A diagnostic requires two cards to test I/O fully, a dummy DC device is provided by the DA simulator. It is enabled only when the DA card is configured for - diagnostic mode. This dummy device may be removed when either the DC or - MA device is implemented. + diagnostic mode. This dummy device should be removed when either the DC + or MA device is implemented. */ @@ -51,19 +51,21 @@ #define FIFO_SIZE 16 /* FIFO depth */ -typedef enum { da, dc, ma, /* card IDs */ - first_card = da, /* first card ID */ - last_card = ma, /* last card ID */ - card_count } CARD_ID; /* count of card IDs */ +typedef enum { + da, dc, ma, /* card IDs */ + first_card = da, /* first card ID */ + last_card = ma, /* last card ID */ + card_count /* count of card IDs */ + } CARD_ID; -/* Device flags and accessors (leaves space for disc/tape flags) */ +/* Device flags and accessors (bits 7-0 are reserved for disc/tape flags) */ -#define DEV_V_BUSADR (DEV_V_UF + 8) /* bits 10-8: HP-IB address */ +#define DEV_V_BUSADR (DEV_V_UF + 8) /* bits 10-8: interface HP-IB address */ #define DEV_V_DIAG (DEV_V_UF + 11) /* bit 11: diagnostic mode */ #define DEV_V_W1 (DEV_V_UF + 12) /* bit 12: DCPC pacing jumper */ -#define DEV_M_BUSADR 7 /* bus address mask */ +#define DEV_M_BUSADR 07 /* bus address mask */ #define DEV_BUSADR (DEV_M_BUSADR << DEV_V_BUSADR) #define DEV_DIAG (1 << DEV_V_DIAG) @@ -73,11 +75,11 @@ typedef enum { da, dc, ma, /* card IDs */ #define SET_DIADR(f) (((f) & DEV_M_BUSADR) << DEV_V_BUSADR) -/* Unit flags and accessors (leaves space for disc/tape flags) */ +/* Unit flags and accessors (bits 7-0 are reserved for disc/tape flags) */ -#define UNIT_V_BUSADR (UNIT_V_UF + 8) /* bits 10-8: HP-IB address */ +#define UNIT_V_BUSADR (UNIT_V_UF + 8) /* bits 10-8: unit HP-IB address */ -#define UNIT_M_BUSADR 7 /* bus address mask */ +#define UNIT_M_BUSADR 07 /* bus address mask */ #define UNIT_BUSADR (UNIT_M_BUSADR << UNIT_V_BUSADR) @@ -95,10 +97,10 @@ typedef enum { da, dc, ma, /* card IDs */ #define DEB_SERV (1 << 5) /* unit service scheduling calls */ -/* HP-IB control state bit flags. +/* HP-IB control line state bit flags. NOTE that these flags align with the corresponding flags in the DI status - register, so don't change the order! + register, so don't change the numerical values! */ #define BUS_ATN 0001 /* attention */ @@ -128,7 +130,7 @@ typedef enum { da, dc, ma, /* card IDs */ #define BUS_UCG 0020 /* universal command group */ #define BUS_ACG 0000 /* addressed command group */ -#define BUS_UNADDRESS 0037 /* unlisten and untalk */ +#define BUS_UNADDRESS 0037 /* unlisten and untalk addresses */ #define PPR(a) (uint8) (1 << (7 - (a))) /* parallel poll response */ @@ -146,8 +148,10 @@ typedef enum { da, dc, ma, /* card IDs */ #define SET_LOWER(b) (b) #define SET_BOTH(b) (SET_UPPER (b) | SET_LOWER (b)) -typedef enum { upper, /* byte selector */ - lower } SELECTOR; +typedef enum { + upper, /* upper byte selected */ + lower /* lower byte selected */ + } SELECTOR; /* Per-card state variables */ @@ -170,9 +174,9 @@ typedef struct { uint32 fifo_count; /* FIFO occupancy counter */ REG *fifo_reg; /* FIFO register pointer */ - uint32 acceptors; /* unit bitmap of bus acceptors */ - uint32 listeners; /* unit bitmap of bus listeners */ - uint32 talker; /* unit bitmap of bus talker */ + uint32 acceptors; /* unit bitmap of the bus acceptors */ + uint32 listeners; /* unit bitmap of the bus listeners */ + uint32 talker; /* unit bitmap of the bus talker */ uint8 bus_cntl; /* HP-IB bus control state (ATN, EOI, etc.) */ uint8 poll_response; /* address bitmap of parallel poll responses */ @@ -183,7 +187,7 @@ typedef struct { /* Disc interface VM global register definitions. - Include these definitions before any device-specific registers. + These definitions should be included before any device-specific registers. Implementation notes: @@ -222,7 +226,7 @@ typedef struct { /* Disc interface VM global modifier definitions. - Include these definitions before any device-specific modifiers. + These definitions should be included before any device-specific modifiers. */ #define DI_MODS(dev) \ diff --git a/HP2100/hp2100_di_da.c b/HP2100/hp2100_di_da.c index 24b1766d..005a6215 100644 --- a/HP2100/hp2100_di_da.c +++ b/HP2100/hp2100_di_da.c @@ -25,7 +25,7 @@ DA 12821A Disc Interface with Amigo disc drives - 21-Feb-12 JDB First release + 29-Mar-12 JDB First release 04-Nov-11 JDB Created DA device References: @@ -45,13 +45,14 @@ connected via an 12821A disc interface and provided 20MB, 50MB, and 120MB capacities. The drives were identical to the 7906M, 7920M, and 7925M Multi-Access Controller (MAC) units but incorporated internal two-card - controllers in each drive and connected to the CPU interface via HP-IB. Each + controllers in each drive and connected to the CPU interface via the + Hewlett-Packard Interface Bus (HP-IB), HP's implementation of IEEE-488. Each controller was dedicated to a single drive and operated similarly to the 12745 Disc Controller to HP-IB Adapter option for the 13037 Disc Controller - box. The 7906H was introduced in 1980 (there was no 7905H version, as the - 7905 was obsolete by that time). Up to four ICD drives could be connected to - a single 12821A card. The limitation was imposed by the bus loading and the - data transfer rate. + chassis. The 7906H was introduced in 1980 (there was no 7905H version, as + the 7905 was obsolete by that time). Up to four ICD drives could be + connected to a single 12821A card. The limitation was imposed by the bus + loading and the target data transfer rate. The ICD command set essentially was the MAC command set modified for single-unit operation. The unit number and CPU hold bit fields in the opcode @@ -61,12 +62,12 @@ controller did not support ECC. Controller status values 02B (Unit Available) and 27B (Unit Unavailable) were dropped as the controller supported only single units, 12B (I/O Program Error) was reused to indicate - HP-IB sequence errors, 13B (Sync Not Received) was added, and 17B (Possibly + HP-IB protocol errors, 13B (Sync Not Received) was added, and 17B (Possibly Correctable Data Error) was removed as error correction was not supported. Some minor redefinitions also occurred. For example, status 14B (End of Cylinder) was expanded to include an auto-seek beyond the drive limits, and - 37B (Drive Attention) was restricted from head loads and unloads to just head + 37B (Drive Attention) was restricted just head unloads from head loads and unloads. The command set was expanded to include several commands related to HP-IB @@ -76,12 +77,6 @@ sequences, Read and Write Loopback channel tests, and controller Self Test commands. - Unfortunately, the primary reference for the ICD controller (the HP 13365 - Integrated Controller Programming Guide) does not indicate parallel poll - responses for these HP-IB commands. Therefore, the responses have been - derived from the sequences in the 7910 and 12745 manuals, although they - sometimes conflict. - This simulator implements the Amigo disc protocol. It calls the 12821A Disc Interface (DI) simulator to send and receive bytes across the HP-IB to and from the CPU, and it calls the HP Disc Library to implement the controller @@ -89,8 +84,15 @@ Four units are provided, and any combination of 7906H/20H/25H drives may be defined. - The drives respond to the following commands; numeric values are in hex, and - bus addressing is indicated by U [untalk], L [listen], and T [talk]: + Unfortunately, the primary reference for the ICD controller (the HP 13365 + Integrated Controller Programming Guide) does not indicate parallel poll + responses for these HP-IB commands. Therefore, the responses have been + derived from the sequences in the 7910 and 12745 manuals, although they + sometimes conflict. + + The drives respond to the following commands; the secondary and opcode + numeric values are in hex, and the bus addressing state is indicated by U + [untalk], L [listen], and T [talk]: Bus Sec Op Operation --- --- -- -------------------------------- @@ -410,18 +412,15 @@ static const IF_STATE next_state [] = { typedef enum { invalid = 0, /* invalid = default for reset */ - disc_command, /* MLA 08 */ crc_listen, /* MLA 09 */ amigo_clear, /* MLA 10 */ write_loopback, /* MLA 1E */ initiate_self_test, /* MLA 1F */ - crc_talk, /* MTA 09 */ device_specified_jump, /* MTA 10 */ read_loopback, /* MTA 1E */ return_self_test_result, /* MTA 1F */ - amigo_identify /* UNT MSA */ } IF_COMMAND; @@ -429,18 +428,15 @@ typedef enum { static const char *if_command_name [] = { "invalid", - "disc command", "CRC listen", "Amigo clear", "write loopback", "initiate self-test", - "CRC talk", "device specified jump", "read loopback", "return self-test result", - "Amigo identify" }; @@ -488,7 +484,7 @@ static void complete_write (uint32 unit); static void complete_abort (uint32 unit); static uint8 get_buffer_byte (CVPTR cvptr); static void put_buffer_byte (CVPTR cvptr, uint8 data); -static t_stat activate_unit (UNIT *uptr); +static t_stat activate_unit (UNIT *uptr); @@ -514,6 +510,14 @@ static t_stat activate_unit (UNIT *uptr); 2. The CNVARS register is included to ensure that the controller state variables array is saved by a SAVE command. It is declared as a hidden, read-only byte array of a depth compatible with the size of the array. + + There does not appear to be a way to expose the fields of the four + controller state variables as arrayed registers. Access to an array + always assumes that elements appear at memory offsets equal to the + element size, i.e., a 32-bit arrayed register has elements at four-byte + offsets. There's no way to specify an array of structure elements where + a given 32-bit field appears at, say, 92-byte offsets (i.e., the size of + the structure). */ DEVICE da_dev; @@ -523,10 +527,10 @@ DIB da_dib = { &di_io, DI_DA, da }; #define UNIT_FLAGS (UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | UNIT_DISABLE | UNIT_UNLOAD) UNIT da_unit [] = { - { UDATA (&da_service, UNIT_FLAGS | MODEL_7906 | SET_BUSADR (0), D7906_WORDS) }, /* bus address 0 */ - { UDATA (&da_service, UNIT_FLAGS | MODEL_7906 | SET_BUSADR (1), D7906_WORDS) }, /* bus address 1 */ - { UDATA (&da_service, UNIT_FLAGS | MODEL_7906 | SET_BUSADR (2), D7906_WORDS) }, /* bus address 2 */ - { UDATA (&da_service, UNIT_FLAGS | MODEL_7906 | SET_BUSADR (3), D7906_WORDS) } /* bus address 3 */ + { UDATA (&da_service, UNIT_FLAGS | MODEL_7906 | SET_BUSADR (0), D7906_WORDS) }, /* drive unit 0 */ + { UDATA (&da_service, UNIT_FLAGS | MODEL_7906 | SET_BUSADR (1), D7906_WORDS) }, /* drive unit 1 */ + { UDATA (&da_service, UNIT_FLAGS | MODEL_7906 | SET_BUSADR (2), D7906_WORDS) }, /* drive unit 2 */ + { UDATA (&da_service, UNIT_FLAGS | MODEL_7906 | SET_BUSADR (3), D7906_WORDS) } /* drive unit 3 */ }; REG da_reg [] = { @@ -535,8 +539,8 @@ REG da_reg [] = { { BRDATA (BUFFER, buffer, 8, 16, DL_BUFSIZE) }, { BRDATA (DSJ, if_dsj, 10, 2, DA_UNITS) }, - { BRDATA (IFSTAT, if_state, 10, sizeof (IF_STATE) * CHAR_BIT, DA_UNITS), PV_LEFT }, - { BRDATA (IFCMD, if_command, 10, sizeof (IF_COMMAND) * CHAR_BIT, DA_UNITS), PV_LEFT }, + { BRDATA (ISTATE, if_state, 10, sizeof (IF_STATE) * CHAR_BIT, DA_UNITS), PV_LEFT }, + { BRDATA (ICMD, if_command, 10, sizeof (IF_COMMAND) * CHAR_BIT, DA_UNITS), PV_LEFT }, { BRDATA (CNVARS, icd_cntlr, 10, CHAR_BIT, sizeof (CNTLR_VARS) * DA_UNITS), REG_HRO }, @@ -594,14 +598,14 @@ DEVICE da_dev = { /* Service an Amigo disc drive I/O event. - The service routine is called to start commands and control the transfer of + The service routine is called to execute commands and control the transfer of data to and from the HP-IB card. The actions to be taken depend on the current state of the ICD interface. The possibilities are: 1. A command is pending on the interface. This occurs only when a command is received while a Seek or Recalibrate command is in progress. - 2. A command is ready for execution. + 2. A command is executing. 3. Data is being sent or received over the HP-IB during command execution. @@ -640,7 +644,7 @@ DEVICE da_dev = { into the sector buffer, a data phase that transfers bytes from the buffer to the card, and an end phase that schedules the intersector gap time and resets to the start phase. Data phase transfers are performed in the - read_exec or write_exec interface states. + read_xfer or write_xfer interface states. The results of the disc library service are inferred by the controller state. If the controller is busy, then the command continues in a new @@ -675,8 +679,8 @@ DEVICE da_dev = { has already stored the received byte in the sector buffer and has asserted NRFD to hold off the card. If the buffer is now full, or the byte was tagged with EOI, then we terminate the transfer and move to the end phase - of the command. Otherwise, we deny NRFD and exit, as we will be - rescheduled when the next byte arrives. + of the command. Otherwise, we deny NRFD and exit; we will be rescheduled + when the next byte arrives. error_source ============ @@ -692,13 +696,14 @@ DEVICE da_dev = { If an error occurred during the data transfer phase of a write command, dummy bytes are sunk from the bus until EOI is seen or the card is unaddressed. This allows the OS driver to complete the command as expected - and to determine the failure by requesting the controller's status. + and then determine the cause of the failure by requesting the controller's + status. Implementation notes: 1. The disc library sets the controller state to idle for a normal End, - Seek, or Recalibrate command and to Wait for all other commands that end + Seek, or Recalibrate command and to wait for all other commands that end normally. So we determine command completion by checking if the controller is not busy, rather than checking if the controller is idle. @@ -720,7 +725,7 @@ DEVICE da_dev = { that was started by the ICD boot loader ROM. In hardware, if the LSTN control bit is cleared, e.g., by CRS, - transmission stops because the card denies NDAC and NRFD (the GPIB + transmission stops because the card denies NDAC and NRFD (the HP-IB handshake requires NDAC and NRFD to be asserted to start the handshake sequence; TACS * SDYS * ~NDAC * ~NRFD is an error condition). In simulation, we handle this by terminating a read transfer if the card @@ -733,15 +738,15 @@ t_stat da_service (UNIT *uptr) { uint8 data; CNTLR_CLASS command_class; -const uint32 unit = uptr - da_dev.units; /* disc unit number */ -const CVPTR cvptr = &icd_cntlr [unit]; /* pointer to controller */ +const int32 unit = uptr - da_unit; /* get the disc unit number */ +const CVPTR cvptr = &icd_cntlr [unit]; /* get a pointer to the controller */ t_stat result = SCPE_OK; t_bool release_interface = FALSE; -switch (if_state [unit]) { /* dispatch interface state */ +switch (if_state [unit]) { /* dispatch the interface state */ case command_wait: /* command is waiting */ - release_interface = TRUE; /* release interface at end if idle */ + release_interface = TRUE; /* release the interface at then end if it's idle */ /* fall into the command_exec handler to process the current command */ @@ -751,50 +756,50 @@ switch (if_state [unit]) { /* dispatch interfac case disc_command: /* execute a disc command */ result = dl_service_drive (cvptr, uptr); /* service the disc unit */ - if (cvptr->opcode == clear) /* Clear command? */ - if_dsj [unit] = 2; /* indicate self test complete */ + if (cvptr->opcode == clear) /* is this a Clear command? */ + if_dsj [unit] = 2; /* indicate that the self test is complete */ if (cvptr->state != cntlr_busy) { /* has the controller stopped? */ if_state [unit] = idle; /* idle the interface */ - if (cvptr->status == normal_completion || /* normal completion? */ + if (cvptr->status == normal_completion || /* do we have normal completion */ cvptr->status == drive_attention) /* or drive attention? */ break; /* we're done */ - else { /* if status is abnormal */ + else { /* if the status is abnormal */ if_dsj [unit] = 1; /* an error has occurred */ - command_class = dl_classify (*cvptr); /* classify command */ + command_class = dl_classify (*cvptr); /* classify the command */ - if (command_class == class_write) { /* write command failed? */ - if_state [unit] = error_sink; /* sink remaining bytes */ + if (command_class == class_write) { /* did a write command fail? */ + if_state [unit] = error_sink; /* sink the remaining bytes */ uptr->wait = cvptr->cmd_time; /* activate to complete processing */ } - else if (command_class != class_control) { /* read or status command failed? */ + else if (command_class != class_control) { /* did a read or status command fail? */ if_state [unit] = error_source; /* source an error byte */ uptr->wait = cvptr->cmd_time; /* activate to complete processing */ } } } - else if (uptr->PHASE == data_phase) { /* starting the data phase? */ - cvptr->length = cvptr->length * 2; /* convert buffer length to bytes */ + else if (uptr->PHASE == data_phase) { /* are we starting the data phase? */ + cvptr->length = cvptr->length * 2; /* convert the buffer length to bytes */ - if (dl_classify (*cvptr) == class_write) /* write command? */ - if_state [unit] = write_xfer; /* set for write data transfer */ - else /* read or status command */ - if_state [unit] = read_xfer; /* set for read data transfer */ + if (dl_classify (*cvptr) == class_write) /* is this a write command? */ + if_state [unit] = write_xfer; /* set for a write data transfer */ + else /* it is a read or status command */ + if_state [unit] = read_xfer; /* set for a read data transfer */ } break; case amigo_identify: /* Amigo Identify */ - buffer [0] = 0x0003; /* store response in buffer */ + buffer [0] = 0x0003; /* store the response in the buffer */ cvptr->length = 2; /* return two bytes */ - if_state [unit] = read_xfer; /* ready to transfer data */ + if_state [unit] = read_xfer; /* we are ready to transfer the data */ uptr->wait = cvptr->cmd_time; /* schedule the transfer */ if (DEBUG_PRI (da_dev, DEB_RWSC)) @@ -805,11 +810,11 @@ switch (if_state [unit]) { /* dispatch interfac case initiate_self_test: /* Initiate a self test */ sim_cancel (&da_unit [unit]); /* cancel any operation in progress */ - dl_clear_controller (cvptr, /* hard clear the controller */ + dl_clear_controller (cvptr, /* hard-clear the controller */ &da_unit [unit], hard_clear); - if_dsj [unit] = 2; /* set DSJ for self test */ - if_state [unit] = idle; /* command is complete */ + if_dsj [unit] = 2; /* set DSJ for self test completion */ + if_state [unit] = idle; /* the command is complete */ di_poll_response (da, unit, SET); /* with PPR enabled */ break; @@ -817,7 +822,7 @@ switch (if_state [unit]) { /* dispatch interfac case amigo_clear: /* Amigo clear */ dl_idle_controller (cvptr); /* idle the controller */ if_dsj [unit] = 0; /* clear the DSJ value */ - if_state [unit] = idle; /* command is complete */ + if_state [unit] = idle; /* the command is complete */ di_poll_response (da, unit, SET); /* with PPR enabled */ break; @@ -830,23 +835,23 @@ switch (if_state [unit]) { /* dispatch interfac case error_source: /* send data after an error */ - if (! (di [da].bus_cntl & (BUS_ATN | BUS_NRFD))) { /* is card ready for data? */ + if (! (di [da].bus_cntl & (BUS_ATN | BUS_NRFD))) { /* is the card ready for data? */ di [da].bus_cntl |= BUS_EOI; /* set EOI */ - di_bus_source (da, 0); /* send a dummy byte to the card */ - if_state [unit] = idle; /* command is complete */ + di_bus_source (da, 0); /* and send a dummy byte to the card */ + if_state [unit] = idle; /* the command is complete */ } break; case read_xfer: /* send read data */ - if (! (di [da].bus_cntl & (BUS_ATN | BUS_NRFD))) /* is card ready for data? */ + if (! (di [da].bus_cntl & (BUS_ATN | BUS_NRFD))) /* is the card ready for data? */ switch (if_command [unit]) { /* dispatch the interface command */ case disc_command: /* disc read or status commands */ data = get_buffer_byte (cvptr); /* get the next byte from the buffer */ - if (di_bus_source (da, data) == FALSE) /* send data to card; is it listening? */ - cvptr->eod = SET; /* no, so terminate read */ + if (di_bus_source (da, data) == FALSE) /* send the byte to the card; is it listening? */ + cvptr->eod = SET; /* no, so terminate the read */ if (cvptr->length == 0 || cvptr->eod == SET) { /* is the data phase complete? */ uptr->PHASE = end_phase; /* set the end phase */ @@ -858,7 +863,7 @@ switch (if_state [unit]) { /* dispatch interfac uptr->wait = cvptr->cmd_time; /* and reschedule the service */ } - else /* data phase continues */ + else /* the data phase continues */ uptr->wait = cvptr->data_time; /* reschedule the next transfer */ break; @@ -872,13 +877,13 @@ switch (if_state [unit]) { /* dispatch interfac if (cvptr->length == 0) /* is the transfer complete? */ di [da].bus_cntl |= BUS_EOI; /* set EOI */ - if (di_bus_source (da, data) /* send data to card; is it listening? */ - && cvptr->length > 0) /* and more to transfer? */ + if (di_bus_source (da, data) /* send the byte to the card; is it listening? */ + && cvptr->length > 0) /* and is there more to transfer? */ uptr->wait = cvptr->data_time; /* reschedule the next transfer */ - else { /* transfer is complete */ - if_state [unit] = idle; /* command is complete */ - di_poll_response (da, unit, SET); /* enable PPR */ + else { /* the transfer is complete */ + if_state [unit] = idle; /* the command is complete */ + di_poll_response (da, unit, SET); /* enable the PPR */ } break; @@ -886,7 +891,7 @@ switch (if_state [unit]) { /* dispatch interfac case device_specified_jump: di [da].bus_cntl |= BUS_EOI; /* set EOI */ di_bus_source (da, if_dsj [unit]); /* send the DSJ value to the card */ - if_state [unit] = idle; /* command is complete */ + if_state [unit] = idle; /* the command is complete */ break; @@ -904,10 +909,10 @@ switch (if_state [unit]) { /* dispatch interfac case error_sink: /* absorb data after an error */ - cvptr->index = 0; /* absorb data until EOI */ + cvptr->index = 0; /* absorb data until EOI asserts */ if (cvptr->eod == SET) /* is the transfer complete? */ - if_state [unit] = idle; /* command is complete */ + if_state [unit] = idle; /* the command is complete */ di_bus_control (da, unit, 0, BUS_NRFD); /* deny NRFD to allow the card to resume */ break; @@ -934,7 +939,7 @@ switch (if_state [unit]) { /* dispatch interfac case write_loopback: if (cvptr->eod == SET) { /* is the transfer complete? */ cvptr->length = 16 - cvptr->length; /* set the count of bytes transferred */ - if_state [unit] = idle; /* command is complete */ + if_state [unit] = idle; /* the command is complete */ } di_bus_control (da, unit, 0, BUS_NRFD); /* deny NRFD to allow the card to resume */ @@ -957,8 +962,8 @@ switch (if_state [unit]) { /* dispatch interfac if (uptr->wait) /* is service requested? */ activate_unit (uptr); /* schedule the next event */ -if (result == SCPE_IERR && DEBUG_PRI (da_dev, DEB_RWSC)) { /* internal error? */ - fprintf (sim_deb, ">>DA rwsc: Unit %d ", unit); +if (result == SCPE_IERR && DEBUG_PRI (da_dev, DEB_RWSC)) { /* did an internal error occur? */ + fprintf (sim_deb, ">>DA rwsc: Unit %d ", unit); /* report it if debugging */ if (if_state [unit] == command_exec && if_command [unit] == disc_command) @@ -988,7 +993,7 @@ if (if_state [unit] == idle) { /* is the command no fprintf (sim_deb, ">>DA rwsc: Unit %d %s command completed\n", unit, if_command_name [if_command [unit]]); - if (release_interface) /* if next command is already pending */ + if (release_interface) /* if the next command is already pending */ di_bus_control (da, unit, 0, BUS_NRFD); /* deny NRFD to allow the card to resume */ } @@ -1015,20 +1020,20 @@ t_stat status; status = di_reset (dptr); /* reset the card */ -if (status == SCPE_OK && (sim_switches & SWMASK ('P'))) /* card OK and power-on reset? */ - for (unit = 0; unit < dptr->numunits; unit++) { /* loop through units */ - sim_cancel (dptr->units + unit); /* cancel activation */ +if (status == SCPE_OK && (sim_switches & SWMASK ('P'))) /* is the card OK and is this a power-on reset? */ + for (unit = 0; unit < dptr->numunits; unit++) { /* loop through the units */ + sim_cancel (dptr->units + unit); /* cancel any current activation */ dptr->units [unit].CYL = 0; /* reset the head position */ dptr->units [unit].pos = 0; /* to cylinder 0 */ - dl_clear_controller (&icd_cntlr [unit], /* hard clear the controller */ + dl_clear_controller (&icd_cntlr [unit], /* hard-clear the controller */ dptr->units + unit, hard_clear); if_state [unit] = idle; /* reset the interface state */ if_command [unit] = invalid; /* reset the interface command */ - if_dsj [unit] = 2; /* set DSJ for power up */ + if_dsj [unit] = 2; /* set the DSJ for power up complete */ } return status; @@ -1037,18 +1042,18 @@ return status; /* Attach a unit to a disc image file. - The simulator considers an attached unit to be connected to the bus, and an + The simulator considers an attached unit to be connected to the bus and an unattached unit to be disconnected, so we set the card's acceptor bit for the selected unit if the attach is successful. An attached unit is ready if the - heads are loaded and not ready of not. + heads are loaded or not ready if not. This model is slightly different than the MAC (DS) simulation, where an - unattached unit is considered "connected but not ready" -- the same indication - returned by an attached unit whose heads are unloaded. Therefore, the - situation when the simulator is started is that all DS units are "connected to - the controller but not ready," whereas all DA units are "not connected to the - controller." This eliminates the overhead of sending HP-IB messages to unused - units. + unattached unit is considered "connected but not ready" -- the same + indication returned by an attached unit whose heads are unloaded. Therefore, + the situation when the simulator is started is that all DS units are + "connected to the controller but not ready," whereas all DA units are "not + connected to the bus." This eliminates the overhead of sending HP-IB + messages to unused units. In tabular form, the simulator responses are: @@ -1082,11 +1087,11 @@ return status; t_stat da_attach (UNIT *uptr, char *cptr) { t_stat result; -const uint32 unit = uptr - da_unit; /* calculate the unit number */ +const int32 unit = uptr - da_unit; /* calculate the unit number */ result = dl_attach (&icd_cntlr [unit], uptr, cptr); /* attach the drive */ -if (result == SCPE_OK) /* attach successful? */ +if (result == SCPE_OK) /* was the attach successful? */ di [da].acceptors |= (1 << unit); /* set the unit's accepting bit */ return result; @@ -1096,18 +1101,18 @@ return result; /* Detach a disc image file from a unit. As explained above, detaching a unit is the hardware equivalent of - disconnecting the drive from the bus, so we clear the unit's acceptor bit is + disconnecting the drive from the bus, so we clear the unit's acceptor bit if the detach is successful. */ t_stat da_detach (UNIT *uptr) { t_stat result; -const uint32 unit = uptr - da_unit; /* calculate the unit number */ +const int32 unit = uptr - da_unit; /* calculate the unit number */ result = dl_detach (&icd_cntlr [unit], uptr); /* detach the drive */ -if (result == SCPE_OK) { /* detach successful? */ +if (result == SCPE_OK) { /* was the detach successful? */ di [da].acceptors &= ~(1 << unit); /* clear the unit's accepting bit */ di_poll_response (da, unit, CLEAR); /* and its PPR, as it's no longer present */ } @@ -1118,8 +1123,8 @@ return result; /* Boot an Amigo disc drive. - The ICD disc bootstrap prorgam is loaded from the HP 12992H Boot Loader ROM - into memory, the I/O instructions are configured from the interface card + The ICD disc bootstrap program is loaded from the HP 12992H Boot Loader ROM + into memory, the I/O instructions are configured for the interface card's select code, and the program is run to boot from the specified unit. The loader supports booting the disc at bus address 0 only. Before execution, the S register is automatically set as follows: @@ -1204,11 +1209,11 @@ static const BOOT_ROM da_rom = { t_stat da_boot (int32 unitno, DEVICE *dptr) { -if (GET_BUSADR (da_unit [unitno].flags) != 0) /* boot supported on bus address 0 only */ +if (GET_BUSADR (da_unit [unitno].flags) != 0) /* booting is supported on bus address 0 only */ return SCPE_NOFNC; /* report "Command not allowed" if attempted */ if (ibl_copy (da_rom, da_dib.select_code)) /* copy the boot ROM to memory and configure */ - return SCPE_IERR; /* return an internal error if failed */ + return SCPE_IERR; /* return an internal error if the copy failed */ SR = SR & (IBL_OPT | IBL_DS_HEAD) /* set S to a reasonable value */ | IBL_DS | IBL_MAN | (da_dib.select_code << IBL_V_DEV); /* before boot execution */ @@ -1252,13 +1257,13 @@ return SCPE_OK; t_stat da_load_unload (UNIT *uptr, int32 value, char *cptr, void *desc) { -const uint32 unit = uptr - da_unit; /* calculate the unit number */ -const t_bool load = (value != UNIT_UNLOAD); /* true if heads are loading */ +const int32 unit = uptr - da_unit; /* calculate the unit number */ +const t_bool load = (value != UNIT_UNLOAD); /* true if the heads are loading */ t_stat result; result = dl_load_unload (&icd_cntlr [unit], uptr, load); /* load or unload the heads */ -if (result == SCPE_OK && ! load) { /* unload successful? */ +if (result == SCPE_OK && ! load) { /* was the unload successful? */ icd_cntlr [unit].status = drive_attention; /* set Drive Attention status */ if (uptr->OP == end) /* is the controller in idle state 2? */ @@ -1283,20 +1288,21 @@ return result; addressed (applying only to those acceptors that have been addressed to listen). Data bytes are accepted only if the unit has been addressed to listen. As we are called for a data transfer or an addressed command only if - we are currently listening, the only bytes that we do not accept are talk or - listen commands directed to another address, or secondary commands when we - are not addressed to listen. + we are currently listening, the only bytes that we do not accept are primary + talk or listen commands directed to another address, or secondary commands + when we are not addressed to listen. This routine handles the HP-IB protocol. The type of byte passed is - determined by the state of the ATN signal and, if asserted, by the high-order - bits of the value. Most of the work involves decoding secondary commands and - their associated data parameters. The interface state is changed as needed - to track the command protocol. The states processed in this routine are: + determined by the state of the ATN signal and, if ATN is asserted, by the + high-order bits of the value. Most of the work involves decoding secondary + commands and their associated data parameters. The interface state is + changed as needed to track the command protocol. The states processed in + this routine are: opcode_wait =========== - A receive disc command secondary has been received, and the interface is + A Receive Disc Command secondary has been received, and the interface is waiting for the opcode that should follow. parameter_wait @@ -1309,19 +1315,19 @@ return result; ========== A disc write command has been received, and the interface is waiting for - the receive write data secondary that should follow. + the Receive Write Data secondary that should follow. read_wait ========= A disc read command has been received, and the interface is waiting for the - send read data secondary that should follow. + Send Read Data secondary that should follow. status_wait =========== A disc status command has been received, and the interface is waiting for - the send disc status secondary that should follow. + the Send Disc Status secondary that should follow. write_xfer ========== @@ -1338,18 +1344,18 @@ return result; Disc commands and parameters are assembled in the sector buffer before being passed to the disc library to start the command. Once the command is - started, then the interface state is set either to execute the command or to - wait for the receipt of a data transfer secondary before executing, depending - on the command. + started, the interface state is set either to execute the command or to wait + for the receipt of a data transfer secondary before executing, depending on + the command. Two disc command protocol errors are detected. First, an Illegal Opcode is - identified during the check for the expected number of disc command opcode + identified during the check for the expected number of disc command parameters. This allows us to sink an arbitrary number of parameter bytes. - Second, an I/O Program Error occurs if an unsupported secondary is received, + Second, an I/O Program Error occurs if an unsupported secondary is received or the HP-IB sequence is incorrect. The latter occurs if a command has the - wrong number of parameters, or a secondary data transfer sequence is invalid. + wrong number of parameters or a secondary data transfer sequence is invalid. - Disc commands that require data transfers (e.g., read, write, request status) + Disc commands that require data transfers (e.g., Read, Write, Request Status) involve a pair of secondaries. The first transmits the command, and the second transmits or receives the data. If one occurs without the other, an I/O Program Error occurs. @@ -1360,26 +1366,27 @@ return result; - An unsupported talk secondary sends a single data byte tagged with EOI. - An unsupported listen secondary accepts and discards any accompanying data - bytes until EOI or unlisten. + bytes until EOI is asserted or an Unlisten is received. - A supported command with too few parameter bytes or for which the last parameter byte is not tagged with EOI (before unlisten) does nothing. - A supported command with too many parameter bytes accepts and discards - excess parameter bytes until EOI or unlisten. + excess parameter bytes until EOI is asserted or an Unlisten is received. - - A read or status command that is not followed by a send data or send - status secondary does nothing. The unexpected secondary is executed - normally. + - A read or status command that is not followed by a Send Read Data or a + Send Disc Status secondary does nothing. The unexpected secondary is + executed normally. - - A write command that is not followed by a receive data secondary does - nothing. The unexpected secondary is executed normally. + - A write command that is not followed by a Receive Write Data secondary + does nothing. The unexpected secondary is executed normally. - - A send data or send status secondary that is not preceded by a read or - status command sends a single data byte tagged with EOI. + - A Send Read Data or a Send Disc Status secondary that is not preceded by a + read or status command sends a single data byte tagged with EOI. - - A receive data secondary that is not preceded by a write command accepts - and discards data bytes until EOI or unlisten. + - A Receive Write Data secondary that is not preceded by a write command + accepts and discards data bytes until EOI is asserted or an Unlisten is + received. The Amigo command sequence does not provide a byte count for disc read and write commands, so the controller continues to source or accept data bytes @@ -1387,22 +1394,22 @@ return result; Untalk. However, per IEEE-488, a listening device may be unaddressed by IFC, by an Unlisten, or by addressing the device to talk, and a talking device may be unaddressed by IFC, by addressing another device to talk (or no device via - Untalk), or by addressing the device to listen. Therefore, we keep track of - whether the unit stopped talking or listening, and if it has, we check for - command termination. + Untalk), or by addressing the device to listen. Therefore, we must keep + track of whether the unit stopped talking or listening, and if it has, we + check for command termination. If the controller is unaddressed in the middle of a sector transfer, the read or write must be terminated cleanly to ensure that the disc image is - coherent. It is also permissable to untalk the controller before all of the + coherent. It is also permissible to untalk the controller before all of the requested status bytes are returned. In addition, the controller has no way to inform the host that an error has - occurred that prevents the command from continuing. For example, a data - error encountered while reading, or a protected track encountered while - writing must still source or sink data bytes until the command is terminated - by the host. The controller handles read errors by sourcing a single data - byte tagged with EOI, and write errors by sinking data bytes until EOI is - seen or the unit is unaddressed. + occurred that prevents the command from continuing. For example, if a data + error is encountered while reading or a protected track is encountered while + writing, the controller must still source or sink data bytes until the + command is terminated by the host. The controller handles read errors by + sourcing a single data byte tagged with EOI and write errors by sinking data + bytes until EOI is seen or the unit is unaddressed. Therefore, if the unit is unaddressed while a read, write, or status command is transferring data, the unit service must be scheduled to end the current @@ -1418,11 +1425,6 @@ return result; 2. It is not necessary to check for listening when processing addressed commands, as only listeners are called by the bus source. - - 3. The dl_prepare_command routine returns FALSE if the command accesses a - busy unit. However, we check for a busy unit during addressing and hold - off the CPU if it is. Therefore, the unit will never be busy when the - routine is called, so a FALSE return will indicate a rejected command. */ t_bool da_bus_accept (uint32 unit, uint8 data) @@ -1469,28 +1471,28 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma case BUS_LAG: /* listen address group */ my_address = GET_BUSADR (da_unit [unit].flags); /* get my bus address */ - if (message_address == my_address) { /* my listen address? */ + if (message_address == my_address) { /* is it my listen address? */ di [da].listeners |= (1 << unit); /* set my listener bit */ di [da].talker &= ~(1 << unit); /* clear my talker bit */ addressed = TRUE; /* unit is now addressed */ - stopped_talking = TRUE; /* MLA stops unit from talking */ + stopped_talking = TRUE; /* MLA stops the unit from talking */ if (DEBUG_PRI (da_dev, DEB_XFER)) sprintf (action, "listen %d", message_address); } - else if (message_address == BUS_UNADDRESS) { /* unlisten? */ - di [da].listeners = 0; /* clear all listeners */ + else if (message_address == BUS_UNADDRESS) { /* is it an Unlisten? */ + di [da].listeners = 0; /* clear all of the listeners */ - stopped_listening = TRUE; /* UNL stops unit from listening */ + stopped_listening = TRUE; /* UNL stops the unit from listening */ if (DEBUG_PRI (da_dev, DEB_XFER)) strcpy (action, "unlisten"); } - else /* other listen address */ - accepted = FALSE; /* is not accepted */ + else /* other listen addresses */ + accepted = FALSE; /* are not accepted */ break; @@ -1498,26 +1500,26 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma case BUS_TAG: /* talk address group */ my_address = GET_BUSADR (da_unit [unit].flags); /* get my bus address */ - if (message_address == my_address) { /* my talk address? */ - di [da].talker = (1 << unit); /* set my talker bit and clear others */ + if (message_address == my_address) { /* is it my talk address? */ + di [da].talker = (1 << unit); /* set my talker bit and clear the others */ di [da].listeners &= ~(1 << unit); /* clear my listener bit */ - addressed = TRUE; /* unit is now addressed */ - stopped_listening = TRUE; /* MTA stops unit from listening */ + addressed = TRUE; /* the unit is now addressed */ + stopped_listening = TRUE; /* MTA stops the unit from listening */ if (DEBUG_PRI (da_dev, DEB_XFER)) sprintf (action, "talk %d", message_address); } - else { /* some other talker (or untalk) */ - di [da].talker &= ~(1 << unit); /* clear talker */ + else { /* it is some other talker (or Untalk) */ + di [da].talker &= ~(1 << unit); /* clear my talker bit */ - stopped_talking = TRUE; /* UNT or OTA stops unit from talking */ + stopped_talking = TRUE; /* UNT or OTA stops the unit from talking */ - if (message_address != BUS_UNADDRESS) /* other talk address? */ - accepted = FALSE; /* is not accepted */ + if (message_address != BUS_UNADDRESS) /* other talk addresses */ + accepted = FALSE; /* are not accepted */ - else /* untalk */ + else /* it's an Untalk */ if (DEBUG_PRI (da_dev, DEB_XFER)) strcpy (action, "untalk"); } @@ -1529,7 +1531,7 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma icd_cntlr [unit].index = 0; /* reset the buffer index */ if (di [da].listeners & (1 << unit)) { /* is it a listen secondary? */ - if (if_state [unit] == write_wait /* if waiting for a write data secondary */ + if (if_state [unit] == write_wait /* if we're waiting for a write data secondary */ && message_address != 0x00) /* but it's not there, */ abort_command (unit, io_program_error, /* then abort the pending command */ idle); /* and process the new command */ @@ -1540,8 +1542,8 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma if (if_state [unit] != write_wait) /* if we're not expecting it */ abort_command (unit, io_program_error, /* abort and sink any data */ error_sink); - else { /* sequence is correct */ - if_state [unit] = command_exec; /* now ready to execute */ + else { /* the sequence is correct */ + if_state [unit] = command_exec; /* the command is ready to execute */ da_unit [unit].wait = icd_cntlr [unit].cmd_time; /* schedule the unit */ di_bus_control (da, unit, BUS_NRFD, 0); /* assert NRFD to hold off the card */ } @@ -1550,36 +1552,36 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma break; case 0x08: /* disc commands */ - if_command [unit] = disc_command; /* set the command */ - if_state [unit] = opcode_wait; /* opcode must follow */ + if_command [unit] = disc_command; /* set the command and wait */ + if_state [unit] = opcode_wait; /* for the opcode that must follow */ break; case 0x09: /* CRC (Listen) */ - if_command [unit] = crc_listen; /* set the command */ + if_command [unit] = crc_listen; /* set up the command */ if_state [unit] = error_sink; /* sink any data that will be coming */ initiated = TRUE; /* log the command initiation */ break; case 0x10: /* Amigo Clear */ - if_command [unit] = amigo_clear; /* set the command */ + if_command [unit] = amigo_clear; /* set up the command */ if_state [unit] = parameter_wait; /* a parameter must follow */ - icd_cntlr [unit].length = 1; /* expect one (unused) byte */ + icd_cntlr [unit].length = 1; /* set to expect one (unused) byte */ break; case 0x1E: /* Write Loopback */ - if_command [unit] = write_loopback; /* set the command */ + if_command [unit] = write_loopback; /* set up the command */ if_state [unit] = write_xfer; /* data will be coming */ icd_cntlr [unit].length = 16; /* accept only the first 16 bytes */ initiated = TRUE; /* log the command initiation */ break; case 0x1F: /* Initiate Self-Test */ - if_command [unit] = initiate_self_test; /* set the command */ + if_command [unit] = initiate_self_test; /* set up the command */ if_state [unit] = parameter_wait; /* a parameter must follow */ - icd_cntlr [unit].length = 1; /* expect the test ID byte */ + icd_cntlr [unit].length = 1; /* set to expect the test ID byte */ break; - default: /* an unsupported listen secondary */ + default: /* an unsupported listen secondary was received */ abort_command (unit, io_program_error, /* abort and sink any data */ error_sink); /* that might accompany the command */ initiated = TRUE; /* log the abort initiation */ @@ -1592,7 +1594,7 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma da_unit [unit].wait = icd_cntlr [unit].cmd_time; /* these are always scheduled and */ initiated = TRUE; /* logged as initiated */ - if (if_state [unit] == read_wait /* if waiting for a send data secondary */ + if (if_state [unit] == read_wait /* if we're waiting for a send data secondary */ && message_address != 0x00 /* but it's not there */ || if_state [unit] == status_wait /* or a send status secondary, */ && message_address != 0x08) /* but it's not there */ @@ -1604,42 +1606,42 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma case 0x00: /* Send Read Data */ if (if_state [unit] != read_wait) /* if we're not expecting it */ abort_command (unit, io_program_error, /* abort and source a data byte */ - error_source); /* tagged with EOI */ + error_source); /* tagged with EOI */ else - if_state [unit] = command_exec; /* now ready to execute */ + if_state [unit] = command_exec; /* the command is ready to execute */ break; case 0x08: /* Read Status */ - if (if_state [unit] != status_wait) /* if we're not expecting it */ + if (if_state [unit] != status_wait) /* if we're not expecting it, */ abort_command (unit, io_program_error, /* abort and source a data byte */ - error_source); /* tagged with EOI */ + error_source); /* tagged with EOI */ else /* all status commands */ if_state [unit] = read_xfer; /* are ready to transfer data */ break; case 0x09: /* CRC (Talk) */ - if_command [unit] = crc_talk; /* set the command */ + if_command [unit] = crc_talk; /* set up the command */ if_state [unit] = read_xfer; /* data will be going */ break; case 0x10: /* Device-Specified Jump */ - if_command [unit] = device_specified_jump; /* set the command */ + if_command [unit] = device_specified_jump; /* set up the command */ if_state [unit] = read_xfer; /* data will be going */ break; case 0x1E: /* Read Loopback */ - if_command [unit] = read_loopback; /* set the command */ + if_command [unit] = read_loopback; /* set up the command */ if_state [unit] = read_xfer; /* data will be going */ break; case 0x1F: /* Return Self-Test Result */ - if_command [unit] = return_self_test_result; /* set the command */ + if_command [unit] = return_self_test_result; /* set up the command */ if_state [unit] = read_xfer; /* data will be going */ icd_cntlr [unit].length = 1; /* return one byte that indicates */ buffer [0] = 0; /* that the self-test passed */ break; - default: /* an unsupported talk secondary */ + default: /* an unsupported talk secondary was received */ abort_command (unit, io_program_error, /* abort and source a data byte */ error_source); /* tagged with EOI */ break; @@ -1652,14 +1654,14 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma if (di [da].talker == 0 && di [da].listeners == 0 /* if there are no talkers or listeners */ && message_address == my_address) { /* and this is my secondary address, */ - if_command [unit] = amigo_identify; /* then this is an Amigo ID sequence */ - if_state [unit] = command_exec; /* set up execution */ + if_command [unit] = amigo_identify; /* then this is an Amigo ID sequence */ + if_state [unit] = command_exec; /* set up for execution */ da_unit [unit].wait = icd_cntlr [unit].cmd_time; /* schedule the unit */ initiated = TRUE; /* log the command initiation */ } - else /* an unaddressed secondary */ - accepted = FALSE; /* is not accepted */ + else /* unaddressed secondaries */ + accepted = FALSE; /* are not accepted */ } @@ -1675,7 +1677,7 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma } - if (addressed && sim_is_active (&da_unit [unit])) { /* is the unit being addressed while busy? */ + if (addressed && sim_is_active (&da_unit [unit])) { /* is the unit being addressed while it is busy? */ if_state [unit] = command_wait; /* change the interface state to wait */ di_bus_control (da, unit, BUS_NRFD, 0); /* and assert NRFD to hold off the card */ @@ -1683,7 +1685,7 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma fprintf (sim_deb, ">>DA rwsc: Unit %d addressed while controller is busy\n", unit); } - if (stopped_listening) { /* was the unit unlistened? */ + if (stopped_listening) { /* was the unit Unlistened? */ if (icd_cntlr [unit].state == cntlr_busy) /* if the controller is busy, */ complete_write (unit); /* then check for write completion */ @@ -1695,8 +1697,8 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma abort_command (unit, io_program_error, idle); /* then abort the pending command */ } - else if (stopped_talking) { /* was the unit untalked? */ - if (icd_cntlr [unit].state == cntlr_busy) /* if the controller is busy */ + else if (stopped_talking) { /* was the unit Untalked? */ + if (icd_cntlr [unit].state == cntlr_busy) /* if the controller is busy, */ complete_read (unit); /* then check for read completion */ else if (if_command [unit] == invalid) /* if a command was aborting, */ @@ -1705,10 +1707,10 @@ if (di [da].bus_cntl & BUS_ATN) { /* is it a bus comma } /* end of bus command processing */ -else { /* it is bus data (ATN denied) */ +else { /* it is bus data (ATN is denied) */ switch (if_state [unit]) { /* dispatch the interface state */ - case opcode_wait: /* wait for an opcode */ + case opcode_wait: /* waiting for an opcode */ if (DEBUG_PRI (da_dev, DEB_XFER)) sprintf (action, "opcode %02XH", data & DL_OPCODE_MASK); @@ -1716,8 +1718,8 @@ else { /* it is bus data (A if (dl_prepare_command (&icd_cntlr [unit], /* is the command valid? */ da_unit, unit)) { - if_state [unit] = parameter_wait; /* set up to get pad byte */ - icd_cntlr [unit].index = 0; /* reset the word index for byte 1 */ + if_state [unit] = parameter_wait; /* set up to get the pad byte */ + icd_cntlr [unit].index = 0; /* reset the word index for the next byte */ icd_cntlr [unit].length = /* convert the parameter count to bytes */ icd_cntlr [unit].length * 2 + 1; /* and include the pad byte */ } @@ -1730,7 +1732,7 @@ else { /* it is bus data (A break; - case parameter_wait: /* wait for a parameter */ + case parameter_wait: /* waiting for a parameter */ if (DEBUG_PRI (da_dev, DEB_XFER)) sprintf (action, "parameter %02XH", data); @@ -1748,13 +1750,13 @@ else { /* it is bus data (A break; - case write_xfer: /* transfer write data */ + case write_xfer: /* transferring write data */ if (icd_cntlr [unit].length > 0) /* if there is more to transfer */ put_buffer_byte (&icd_cntlr [unit], data); /* then add the byte to the buffer */ /* fall into error_sink handler */ - case error_sink: /* sink data after an error */ + case error_sink: /* sinking data after an error */ if (DEBUG_PRI (da_dev, DEB_XFER)) sprintf (action, "data %03o", data); @@ -1767,7 +1769,7 @@ else { /* it is bus data (A break; - default: /* data was received in wrong state */ + default: /* data was received in the wrong state */ abort_command (unit, io_program_error, /* report the error */ error_sink); /* and sink any data that follows */ @@ -1782,7 +1784,7 @@ if (accepted && DEBUG_PRI (da_dev, DEB_XFER)) fprintf (sim_deb, ">>DA xfer: HP-IB address %d accepted %s\n", GET_BUSADR (da_unit [unit].flags), action); -if (da_unit [unit].wait > 0) /* is service requested? */ +if (da_unit [unit].wait > 0) /* was service requested? */ activate_unit (&da_unit [unit]); /* schedule the unit */ if (initiated && DEBUG_PRI (da_dev, DEB_RWSC)) @@ -1811,14 +1813,13 @@ return accepted; /* indicate the acceptan has asserted NRFD must deny it before a talker may send data. If the interface is sending data and both ATN and NRFD are denied, then we reschedule the service routine to send the next byte. - */ void da_bus_respond (CARD_ID card, uint32 unit, uint8 new_cntl) { if (new_cntl & BUS_IFC) { /* is interface clear asserted? */ - di [da].listeners = 0; /* unlisten */ - di [da].talker = 0; /* untalk */ + di [da].listeners = 0; /* perform an Unlisten */ + di [da].talker = 0; /* and an Untalk */ if (icd_cntlr [unit].state == cntlr_busy) { /* is the controller busy? */ complete_write (unit); /* check for write completion */ @@ -1831,13 +1832,13 @@ if (new_cntl & BUS_IFC) { /* is interface clear as else if (if_command [unit] == invalid) /* if a command was aborting, */ complete_abort (unit); /* then complete it */ - else if (if_state [unit] == opcode_wait /* if waiting for an opcode */ + else if (if_state [unit] == opcode_wait /* if we're waiting for an opcode */ || if_state [unit] == parameter_wait) /* or a parameter, */ abort_command (unit, io_program_error, idle); /* then abort the pending command */ } -if (! (new_cntl & (BUS_ATN | BUS_NRFD)) /* in data mode and card is ready for data? */ - && (if_state [unit] == read_xfer /* is interface waiting to send data */ +if (!(new_cntl & (BUS_ATN | BUS_NRFD)) /* is the card in data mode and ready for data? */ + && (if_state [unit] == read_xfer /* is the interface waiting to send data */ || if_state [unit] == error_source)) /* or source error bytes? */ da_service (&da_unit [unit]); /* start or resume the transfer */ } @@ -1849,57 +1850,58 @@ if (! (new_cntl & (BUS_ATN | BUS_NRFD)) /* in data mode and card /* Start a command with parameters. - A command that has been pending until all of its parameters were received is + A command that has been waiting for all of its parameters to be received is now ready to start. If this is a disc command, call the disc library to validate the parameters and, if they are OK, to start the command. Status commands return the status values in the sector buffer and the number of words that were returned in the buffer length, which we convert to a byte count. - If the disc command was accepted, the controller will be busy. In this case, + If the disc command was accepted, the library returns a pointer to the unit + to be scheduled. For an ICD controller, the unit is always the one currently + addressed, so we simply test if the return is not NULL. If it isn't, then we set the next interface state as determined by the command that is executing. For example, a Read command sets the interface to read_wait status in order - to wait until the accompanying Send Read Data secondary is received. If the - controller is not busy, then the command was rejected, so we set DSJ = 1 and - leave the interface state in parameter_wait; the controller status will have - been set to the reason for rejection. + to wait until the accompanying Send Read Data secondary is received. - If the interface state is command_exec, then the disc command is ready for - execution, and we return TRUE to schedule the unit service. Otherwise, we - return FALSE, and the appropriate action will be taken by the caller. + If the return is NULL, then the command was rejected, so we set DSJ = 1 and + leave the interface state in parameter_wait; the controller status will have + been set to the reason for the rejection. + + If the next interface state is command_exec, then the disc command is ready + for execution, and we return TRUE to schedule the unit service. Otherwise, + we return FALSE, and the appropriate action will be taken by the caller. For all other commands, execution begins as soon as the correct parameters are received, so we set command_exec state and return TRUE. (Only Amigo - Clear and Inititate Self Test require parameters, so they will be the only + Clear and Initiate Self Test require parameters, so they will be the only other commands that must be started here.) -set wait = 0 if not executing (e.g., for read wait) Implementation notes: - 1. The ICD implemenation does not need to differentiate between unit and + 1. As the ICD implementation does not need to differentiate between unit and controller commands, the return value from the dl_start_command routine - is not used. + is not used other than as an indication of success or failure. */ static t_bool start_command (uint32 unit) { -if (if_command [unit] == disc_command) { /* starting a disc command? */ - dl_start_command (&icd_cntlr [unit], da_unit, unit); /* ask the controller to start the command */ - - icd_cntlr [unit].length = icd_cntlr [unit].length * 2; /* convert return length from words to bytes */ - - if (icd_cntlr [unit].state == cntlr_busy) /* was the command accepted? */ +if (if_command [unit] == disc_command) { /* are we starting a disc command? */ + if (dl_start_command (&icd_cntlr [unit], da_unit, unit)) { /* start the command; was it successful? */ + icd_cntlr [unit].length = icd_cntlr [unit].length * 2; /* convert the return length from words to bytes */ if_state [unit] = next_state [icd_cntlr [unit].opcode]; /* set the next interface state */ + } + else /* the command was rejected */ if_dsj [unit] = 1; /* so indicate an error */ - if (if_state [unit] == command_exec) /* if command is executing */ + if (if_state [unit] == command_exec) /* if the command is executing */ return TRUE; /* activate the unit */ else { /* if we must wait */ - da_unit [unit].wait = 0; /* for another secondary */ - return FALSE; /* skip the activation */ + da_unit [unit].wait = 0; /* for another secondary, */ + return FALSE; /* then skip the activation */ } } @@ -1926,7 +1928,7 @@ static void abort_command (uint32 unit, CNTLR_STATUS status, IF_STATE state) if_command [unit] = invalid; /* indicate an invalid command */ if_state [unit] = state; /* set the interface state as directed */ if_dsj [unit] = 1; /* set DSJ to indicate an error condition */ -dl_end_command (&icd_cntlr [unit], status); /* place the disc controller into a wait state */ +dl_end_command (&icd_cntlr [unit], status); /* place the disc controller into the wait state */ return; } @@ -1967,8 +1969,8 @@ static void complete_read (uint32 unit) if ((if_state [unit] == command_exec /* is a command executing */ || if_state [unit] == read_xfer) /* or is data transferring */ && (dl_classify (icd_cntlr [unit]) == class_read /* and the controller is executing */ - || dl_classify (icd_cntlr [unit]) == class_status)) { /* a read or status? */ - icd_cntlr [unit].eod = SET; /* set the end of data */ + || dl_classify (icd_cntlr [unit]) == class_status)) { /* a read or status command? */ + icd_cntlr [unit].eod = SET; /* set the end of data flag */ if_state [unit] = command_exec; /* set to execute */ da_unit [unit].PHASE = end_phase; /* the completion phase */ @@ -2016,7 +2018,7 @@ static void complete_write (uint32 unit) if ((if_state [unit] == command_exec /* is a command executing */ || if_state [unit] == write_xfer) /* or is data transferring */ && dl_classify (icd_cntlr [unit]) == class_write) { /* and the controller is executing a write? */ - icd_cntlr [unit].eod = SET; /* set the end of data */ + icd_cntlr [unit].eod = SET; /* set the end of data flag */ if_state [unit] = command_exec; /* set to execute */ da_unit [unit].PHASE = end_phase; /* the completion phase */ @@ -2049,7 +2051,7 @@ return; static void complete_abort (uint32 unit) { if (if_state [unit] != idle) { /* is the interface busy? */ - icd_cntlr [unit].eod = SET; /* set the end of data */ + icd_cntlr [unit].eod = SET; /* set the end of data flag */ da_service (&da_unit [unit]); /* and process the abort completion */ } @@ -2083,7 +2085,7 @@ else /* the lower byte is nex The supplied byte is stored in the sector buffer. The determination of which byte of the 16-bit buffer word to store is made by the polarity of the buffer - byte count. The count always begins with an even number, as it is set by + byte count. The count always begins with an even number, as it is set by doubling the word count returned from the disc library. Therefore, because we decrement the count first, the upper byte is indicated by an odd count, and the lower byte is indicated by an even count. The buffer index is @@ -2110,7 +2112,7 @@ return; static t_stat activate_unit (UNIT *uptr) { -uint32 unit; +int32 unit; t_stat result; if (DEBUG_PRI (da_dev, DEB_SERV)) { diff --git a/HP2100/hp2100_diag.txt b/HP2100/hp2100_diag.txt index 358e0bb5..c9382484 100644 --- a/HP2100/hp2100_diag.txt +++ b/HP2100/hp2100_diag.txt @@ -1,6 +1,6 @@ SIMH/HP 21XX DIAGNOSTICS PERFORMANCE ==================================== - Last update: 2012-02-20 + Last update: 2012-03-30 The HP 24396 diagnostic suite has been run against the SIMH HP 21xx simulation. @@ -70,7 +70,7 @@ The results of the diagnostic runs are summarized below: 103116 12967 Synchronous Interface 1438 - No simulation 103017 12966 Asynchronous Data Set 1519 3.8-0 Passed 103121 12968 Asynchronous Comm. Interface 1602 - No simulation -103024 12821 ICD Disc Interface 1928 3.8-2 Passed +103024 12821 ICD Disc Interface 1928 3.9-0 Passed 104000 2600 Keyboard Display Terminal 1615 - No simulation 104003 Teleprinter 1509 3.2-3 Partial @@ -128,8 +128,9 @@ offline diagnostics: Part Number Diagnostic Name Code Op. Sys. Code Vers. Result ----------- ------------------------------- ---- -------- ---- ----- ---------- 12824-16002 Vector Instruction Set Firmware 2026 RTE-IVB 5010 3.8-0 Passed -91711-12032 ICD/MAC Disc Diagnostic 2201 RTE-IVB 5010 3.8-2 Partial +91711-12032 ICD/MAC Disc Diagnostic 2201 RTE-IVB 5010 3.9-0 Partial 92067-16013 Extended Memory Area Firmware 1805 RTE-IVB 5010 3.8-0 Passed + 12829-16006 Vector Instruction Set Firmware 2226 RTE-6/VM 6200 3.8-0 Passed 92084-16423 Virtual Memory Area Firmware 2121 RTE-6/VM 6200 3.8-0 Passed 92835-16006 SIGNAL/1000 Firmware Diagnostic 2040 RTE-6/VM 6200 3.8-0 Passed @@ -3527,7 +3528,9 @@ BINARY FILE: 91711-12032 Rev. 2201 HOST SYSTEM: RTE-IVB Rev. 5010 -CONFIGURATION: sim> set DS0 FORMAT +CONFIGURATION: sim> set DA1 7906H + sim> set DA1 FORMAT + sim> attach DA1 scratch.U1.7906H.disc sim> go TEST REPORT: DIAG : HP-IB DISC DIAGNOSTIC @@ -3540,12 +3543,12 @@ TEST REPORT: DIAG : HP-IB DISC DIAGNOSTIC DIAG : Start trace at what step ? 0 DIAG : Trace operations which are not part of the test steps ? NO DIAG : Stop after first failure ? NO - DIAG : Disc LU ? 41 - DIAG : Disc address ? 0 + DIAG : Disc LU ? 14 + DIAG : Disc address ? 1 DIAG : Drive model number ? 06 DIAG : Do you want to run the interactive part of the test ? YES - DIAG : LU 41 address 0 select code 25 7906 drive + DIAG : LU 14 address 1 select code 12 7906 drive DIAG : CHECK THAT ALL SWITCHES ARE SET CORRECTLY. DIAG : THE RUN/STOP SWITCH SHOULD BE IN THE RUN POSITION. @@ -3569,7 +3572,7 @@ TEST REPORT: DIAG : HP-IB DISC DIAGNOSTIC DIAG : STEP 1 PASSED DIAG : operation parameters/results spd cs ds DSJ - DIAG : REQUEST STATUS drive type 0 0 0 50 0 + DIAG : REQUEST STATUS drive type 0 0 0 40 0 DIAG : IDENTIFY result 3 0 0 40 0 DIAG : STEP 3 PASSED @@ -3580,19 +3583,19 @@ TEST REPORT: DIAG : HP-IB DISC DIAGNOSTIC DIAG : cylinders: 0 - 410 heads: 0 - 3 sectors: 0 - 47 DIAG : First and last tracks on LU: DIAG : cylinder 0 head 0 (track 0) - DIAG : cylinder 199 head 1 (track 399) + DIAG : cylinder 49 head 1 (track 99) DIAG : First and last spares on LU: - DIAG : cylinder 200 head 0 (track 400) - DIAG : cylinder 202 head 1 (track 405) + DIAG : cylinder 50 head 0 + DIAG : cylinder 49 head 1 (track 99) DIAG : Heads on LU (first - last): 0 - 1 DIAG : Searching entire LU for file directory: DIAG : NO DIRECTORY OR UNABLE TO READ DIRECTORY ON TEST LU DIAG : First and last tracks available for testing: DIAG : cylinder 0 head 0 (track 0) - DIAG : cylinder 199 head 1 (track 399) + DIAG : cylinder 49 head 1 (track 99) DIAG : Default test tracks: - DIAG : cylinder 199 head 0 (track 398) - DIAG : cylinder 199 head 1 (track 399) + DIAG : cylinder 49 head 0 (track 98) + DIAG : cylinder 49 head 1 (track 99) DIAG : Use default test tracks ? YES DIAG : Checking test track preambles. @@ -3601,11 +3604,11 @@ TEST REPORT: DIAG : HP-IB DISC DIAGNOSTIC DIAG : Beginning part 2 of diagnostic. DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 DIAG : STEP 4 PASSED DIAG : operation parameters/results spd cs ds DSJ - DIAG : REQUEST DISC ADDR cy 199 hd 0 sec 0 0 0 40 0 + DIAG : REQUEST DISC ADDR cy 49 hd 0 sec 0 0 0 40 0 DIAG : STEP 5 PASSED DIAG : operation parameters/results spd cs ds DSJ @@ -3614,8 +3617,8 @@ TEST REPORT: DIAG : HP-IB DISC DIAGNOSTIC DIAG : STEP 6 PASSED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 - DIAG : REQUEST SECTOR ADDR sec 2 0 0 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 + DIAG : REQUEST SECTOR ADDR sec 6 0 0 40 0 DIAG : STEP 7 PASSED DIAG : operation parameters/results spd cs ds DSJ @@ -3626,153 +3629,153 @@ TEST REPORT: DIAG : HP-IB DISC DIAGNOSTIC DIAG : STEP 8 PASSED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 DIAG : READ FULL SECTOR length 138 0 0 40 0 - DIAG : decode preamble cy 199 hd 0 sec 0 spd 0 + DIAG : decode preamble cy 49 hd 0 sec 0 spd 0 DIAG : STEP 9 PASSED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 DIAG : WRITE FULL SECTOR length 138 0 0 40 0 DIAG : STEP 10 PASSED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 DIAG : VERIFY sector count 1 0 0 40 0 DIAG : STEP 11 FAILED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 DIAG : READ length 128 0 0 40 0 DIAG : STEP 12 FAILED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 DIAG : READ WITH OFFSET length 128 offset 55 0 0 40 0 DIAG : STEP 13 FAILED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 DIAG : READ WITHOUT VERIFY length 128 0 0 40 0 DIAG : STEP 14 FAILED DIAG : operation parameters/results spd cs ds DSJ DIAG : SET FILE MASK mask 0 0 0 40 0 - DIAG : SEEK cy 199 hd 0 sec 47 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 47 0 37 40 0 DIAG : READ FULL SECTOR length 140 0 14 40 1 DIAG : STEP 16 PASSED DIAG : operation parameters/results spd cs ds DSJ DIAG : SET FILE MASK mask 2 0 0 40 0 - DIAG : SEEK cy 199 hd 0 sec 47 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 47 0 37 40 0 DIAG : READ FULL SECTOR length 140 0 0 40 0 DIAG : STEP 17 PASSED DIAG : operation parameters/results spd cs ds DSJ DIAG : SET FILE MASK mask 2 0 0 40 0 - DIAG : SEEK cy 199 hd 3 sec 47 0 37 40 0 + DIAG : SEEK cy 49 hd 3 sec 47 0 37 40 0 DIAG : READ FULL SECTOR length 140 0 14 40 1 DIAG : STEP 18 PASSED DIAG : operation parameters/results spd cs ds DSJ DIAG : SET FILE MASK mask 3 0 0 40 0 - DIAG : SEEK cy 199 hd 3 sec 47 0 37 40 0 + DIAG : SEEK cy 49 hd 3 sec 47 0 37 40 0 DIAG : READ FULL SECTOR length 140 0 0 40 0 - DIAG : REQUEST DISC ADDR cy 200 hd 0 sec 1 0 0 40 0 + DIAG : REQUEST DISC ADDR cy 50 hd 0 sec 1 0 0 40 0 DIAG : STEP 19 PASSED DIAG : operation parameters/results spd cs ds DSJ DIAG : SET FILE MASK mask 11 0 0 40 0 - DIAG : SEEK cy 199 hd 0 sec 47 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 47 0 37 40 0 DIAG : READ FULL SECTOR length 140 0 0 40 0 - DIAG : REQUEST DISC ADDR cy 198 hd 0 sec 1 0 0 40 0 + DIAG : REQUEST DISC ADDR cy 48 hd 0 sec 1 0 0 40 0 DIAG : STEP 20 PASSED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 - DIAG : ADDRESS RECORD cy 199 hd 1 sec 0 0 0 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 + DIAG : ADDRESS RECORD cy 49 hd 1 sec 0 0 0 40 0 DIAG : INITIALIZE length 6144 spd 1 1 0 40 0 - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 DIAG : READ FULL SECTOR length 3 0 0 40 0 - DIAG : decode preamble cy 199 hd 0 sec 0 spd 0 + DIAG : decode preamble cy 49 hd 0 sec 0 spd 0 DIAG : STEP 21 FAILED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 - DIAG : ADDRESS RECORD cy 199 hd 0 sec 0 0 0 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 + DIAG : ADDRESS RECORD cy 49 hd 0 sec 0 0 0 40 0 DIAG : INITIALIZE length 6144 spd 4 4 0 40 0 - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 DIAG : READ FULL SECTOR length 3 0 0 40 0 - DIAG : decode preamble cy 199 hd 1 sec 0 spd 0 + DIAG : decode preamble cy 49 hd 1 sec 0 spd 0 DIAG : STEP 22 FAILED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 - DIAG : ADDRESS RECORD cy 199 hd 1 sec 0 0 0 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 + DIAG : ADDRESS RECORD cy 49 hd 1 sec 0 0 0 40 0 DIAG : INITIALIZE length 6144 spd 2 2 0 40 0 - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 DIAG : READ FULL SECTOR length 3 0 0 40 0 - DIAG : decode preamble cy 199 hd 1 sec 0 spd 0 + DIAG : decode preamble cy 49 hd 1 sec 0 spd 0 DIAG : STEP 25 FAILED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 - DIAG : ADDRESS RECORD cy 199 hd 0 sec 0 0 0 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 + DIAG : ADDRESS RECORD cy 49 hd 0 sec 0 0 0 40 0 DIAG : INITIALIZE length 6144 spd 6 6 0 40 0 - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 DIAG : READ FULL SECTOR length 3 0 0 40 0 - DIAG : decode preamble cy 199 hd 1 sec 0 spd 0 + DIAG : decode preamble cy 49 hd 1 sec 0 spd 0 DIAG : STEP 26 FAILED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 - DIAG : ADDRESS RECORD cy 199 hd 1 sec 0 0 0 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 + DIAG : ADDRESS RECORD cy 49 hd 1 sec 0 0 0 40 0 DIAG : INITIALIZE length 6144 spd 3 3 0 40 0 - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 DIAG : READ FULL SECTOR length 3 0 0 40 0 - DIAG : decode preamble cy 199 hd 1 sec 0 spd 0 + DIAG : decode preamble cy 49 hd 1 sec 0 spd 0 DIAG : STEP 28 FAILED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 - DIAG : ADDRESS RECORD cy 199 hd 0 sec 0 0 0 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 + DIAG : ADDRESS RECORD cy 49 hd 0 sec 0 0 0 40 0 DIAG : INITIALIZE length 6144 spd 4 4 0 40 0 - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 DIAG : READ FULL SECTOR length 3 0 0 40 0 - DIAG : decode preamble cy 199 hd 1 sec 0 spd 0 + DIAG : decode preamble cy 49 hd 1 sec 0 spd 0 DIAG : STEP 30 FAILED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 - DIAG : ADDRESS RECORD cy 199 hd 0 sec 0 0 0 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 + DIAG : ADDRESS RECORD cy 49 hd 0 sec 0 0 0 40 0 DIAG : INITIALIZE length 6144 spd 0 0 0 40 0 - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 DIAG : READ FULL SECTOR length 3 0 0 40 0 - DIAG : decode preamble cy 199 hd 0 sec 0 spd 0 + DIAG : decode preamble cy 49 hd 0 sec 0 spd 0 DIAG : SET FILE MASK mask 0 0 0 40 0 - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 DIAG : READ length 128 0 0 40 0 DIAG : STEP 31 PASSED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 - DIAG : ADDRESS RECORD cy 199 hd 1 sec 0 0 0 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 + DIAG : ADDRESS RECORD cy 49 hd 1 sec 0 0 0 40 0 DIAG : INITIALIZE length 6144 spd 0 0 0 40 0 - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 DIAG : READ FULL SECTOR length 3 0 0 40 0 - DIAG : decode preamble cy 199 hd 1 sec 0 spd 0 + DIAG : decode preamble cy 49 hd 1 sec 0 spd 0 DIAG : SET FILE MASK mask 0 0 0 40 0 - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 DIAG : READ length 128 0 0 40 0 DIAG : STEP 32 PASSED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 DIAG : WRITE length 128 0 0 40 0 DIAG : STEP 35 PASSED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 DIAG : READ length 128 0 0 40 0 DIAG : test data read test passed DIAG : STEP 36 PASSED @@ -3801,19 +3804,19 @@ TEST REPORT: DIAG : HP-IB DISC DIAGNOSTIC DIAG : STEP 40 PASSED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 DIAG : VERIFY sector count 1 0 0 40 0 - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 DIAG : VERIFY sector count 2 0 0 40 0 - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 DIAG : VERIFY sector count 4 0 0 40 0 - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 DIAG : VERIFY sector count 8 0 0 40 0 - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 DIAG : VERIFY sector count 16 0 0 40 0 - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 DIAG : VERIFY sector count 32 0 0 40 0 - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 DIAG : VERIFY sector count 48 0 0 40 0 DIAG : STEP 45 PASSED @@ -3854,38 +3857,38 @@ TEST REPORT: DIAG : HP-IB DISC DIAGNOSTIC DIAG : STEP 50 PASSED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 - DIAG : ADDRESS RECORD cy 198 hd 1 sec 0 0 0 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 + DIAG : ADDRESS RECORD cy 48 hd 1 sec 0 0 0 40 0 DIAG : INITIALIZE length 6144 spd 0 0 0 40 0 - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 DIAG : READ FULL SECTOR length 3 0 0 40 0 - DIAG : decode preamble cy 199 hd 1 sec 0 spd 0 + DIAG : decode preamble cy 49 hd 1 sec 0 spd 0 DIAG : STEP 52 FAILED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 - DIAG : ADDRESS RECORD cy 199 hd 0 sec 0 0 0 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 + DIAG : ADDRESS RECORD cy 49 hd 0 sec 0 0 0 40 0 DIAG : INITIALIZE length 6144 spd 0 0 0 40 0 - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 DIAG : READ FULL SECTOR length 3 0 0 40 0 - DIAG : decode preamble cy 199 hd 1 sec 0 spd 0 + DIAG : decode preamble cy 49 hd 1 sec 0 spd 0 DIAG : STEP 54 FAILED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 - DIAG : ADDRESS RECORD cy 199 hd 1 sec 0 0 0 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 + DIAG : ADDRESS RECORD cy 49 hd 1 sec 0 0 0 40 0 DIAG : INITIALIZE length 6144 spd 0 0 0 40 0 - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 DIAG : READ FULL SECTOR length 3 0 0 40 0 - DIAG : decode preamble cy 199 hd 1 sec 0 spd 0 + DIAG : decode preamble cy 49 hd 1 sec 0 spd 0 DIAG : SET FILE MASK mask 0 0 0 40 0 - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 DIAG : READ length 128 0 0 40 0 - DIAG : SEEK cy 199 hd 1 sec 5 0 37 40 0 + DIAG : SEEK cy 49 hd 1 sec 5 0 37 40 0 DIAG : READ FULL SECTOR length 138 0 0 40 0 - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 DIAG : WRITE FULL SECTOR length 138 0 0 40 0 - DIAG : SEEK cy 199 hd 1 sec 1 0 37 40 0 + DIAG : SEEK cy 49 hd 1 sec 1 0 37 40 0 DIAG : READ length 128 0 0 40 0 DIAG : STEP 55 FAILED @@ -3912,7 +3915,7 @@ TEST REPORT: DIAG : HP-IB DISC DIAGNOSTIC DIAG : STEP 60 PASSED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 4 sec 0 0 23 44 1 + DIAG : SEEK cy 49 hd 4 sec 0 0 23 44 1 DIAG : SEEK cy 0 hd 0 sec 0 0 37 40 0 DIAG : STEP 72 PASSED @@ -3922,7 +3925,7 @@ TEST REPORT: DIAG : HP-IB DISC DIAGNOSTIC DIAG : STEP 73 PASSED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 1 sec 49 0 23 44 1 + DIAG : SEEK cy 49 hd 1 sec 49 0 23 44 1 DIAG : SEEK cy 0 hd 0 sec 0 0 37 40 0 DIAG : STEP 74 PASSED @@ -3948,12 +3951,12 @@ TEST REPORT: DIAG : HP-IB DISC DIAGNOSTIC DIAG : STEP 81 PASSED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 - DIAG : ADDRESS RECORD cy 199 hd 1 sec 0 0 0 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 + DIAG : ADDRESS RECORD cy 49 hd 1 sec 0 0 0 40 0 DIAG : INITIALIZE length 6144 spd 2 2 0 40 0 - DIAG : SEEK cy 199 hd 1 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 40 0 DIAG : READ FULL SECTOR length 3 0 0 40 0 - DIAG : decode preamble cy 199 hd 1 sec 0 spd 0 + DIAG : decode preamble cy 49 hd 1 sec 0 spd 0 DIAG : STEP 82 FAILED @@ -3965,17 +3968,17 @@ TEST REPORT: DIAG : HP-IB DISC DIAGNOSTIC DIAG : STEP 83 PASSED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 1 sec 0 0 37 0 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 0 0 DIAG : WRITE length 1 0 0 0 0 DIAG : STEP 84 FAILED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 1 sec 0 0 37 0 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 0 0 DIAG : WRITE FULL SECTOR length 1 0 23 0 1 DIAG : STEP 85 PASSED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 1 sec 0 0 37 0 0 + DIAG : SEEK cy 49 hd 1 sec 0 0 37 0 0 DIAG : INITIALIZE length 1 spd 0 0 23 0 1 DIAG : STEP 86 PASSED @@ -3992,21 +3995,21 @@ TEST REPORT: DIAG : HP-IB DISC DIAGNOSTIC DIAG : Type , DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 0 sec 0 0 37 140 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 140 0 DIAG : STEP 89 PASSED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 0 sec 0 0 37 140 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 140 0 DIAG : WRITE length 1 0 23 140 1 DIAG : STEP 90 PASSED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 0 sec 0 0 37 140 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 140 0 DIAG : WRITE FULL SECTOR length 1 0 23 140 1 DIAG : STEP 91 PASSED DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 0 sec 0 0 37 140 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 140 0 DIAG : INITIALIZE length 1 spd 0 0 23 140 1 DIAG : STEP 92 PASSED @@ -4015,7 +4018,7 @@ TEST REPORT: DIAG : HP-IB DISC DIAGNOSTIC DIAG : Type , DIAG : operation parameters/results spd cs ds DSJ - DIAG : SEEK cy 199 hd 0 sec 0 0 37 40 0 + DIAG : SEEK cy 49 hd 0 sec 0 0 37 40 0 DIAG : STEP 97 PASSED DIAG : Part 3 of diagnostic completed. diff --git a/HP2100/hp2100_dp.c b/HP2100/hp2100_dp.c index f244d356..c26d16e6 100644 --- a/HP2100/hp2100_dp.c +++ b/HP2100/hp2100_dp.c @@ -859,7 +859,7 @@ t_stat dpc_svc (UNIT *uptr) int32 da, drv, err; err = 0; /* assume no err */ -drv = uptr - dpc_dev.units; /* get drive no */ +drv = uptr - dpc_unit; /* get drive no */ if (uptr->flags & UNIT_UNLOAD) { /* drive down? */ dpc.command = CLEAR; /* clr cch cmd */ @@ -1052,7 +1052,7 @@ return detach_unit (uptr); /* detach unit */ t_stat dpc_load_unload (UNIT *uptr, int32 value, char *cptr, void *desc) { -uint32 drv; +int32 drv; if ((uptr->flags & UNIT_ATT) == 0) return SCPE_UNATT; /* must be attached to load */ @@ -1060,7 +1060,7 @@ if (value == UNIT_UNLOAD) /* unload heads? */ uptr->flags = uptr->flags | UNIT_UNLOAD; /* indicate unload */ else { /* load heads */ uptr->flags = uptr->flags & ~UNIT_UNLOAD; /* indicate load */ - drv = uptr - dpc_dev.units; /* get drive no */ + drv = uptr - dpc_unit; /* get drive no */ dpc_sta[drv] = dpc_sta[drv] | STA_ATN | STA_1ST; /* update status */ if (dpc_poll) /* polling enabled? */ dpcio (&dpc_dib, ioENF, 0); /* set flag */ diff --git a/HP2100/hp2100_dq.c b/HP2100/hp2100_dq.c index 3f4062f8..06c92b2b 100644 --- a/HP2100/hp2100_dq.c +++ b/HP2100/hp2100_dq.c @@ -678,7 +678,7 @@ t_stat dqc_svc (UNIT *uptr) int32 da, drv, err; err = 0; /* assume no err */ -drv = uptr - dqc_dev.units; /* get drive no */ +drv = uptr - dqc_unit; /* get drive no */ if (uptr->flags & UNIT_UNLOAD) { /* drive down? */ dqc.command = CLEAR; /* clr cch cmd */ dqcio (&dqc_dib, ioENF, 0); /* set cch flg */ diff --git a/HP2100/hp2100_ds.c b/HP2100/hp2100_ds.c index 79552417..29df4589 100644 --- a/HP2100/hp2100_ds.c +++ b/HP2100/hp2100_ds.c @@ -26,7 +26,7 @@ DS 13037D/13175D disc controller/interface - 02-Mar-12 JDB Rewritten to use the MAC/ICD disc controller library + 29-Mar-12 JDB Rewritten to use the MAC/ICD disc controller library ioIOO now notifies controller service of parameter output 14-Feb-12 JDB Corrected SRQ generation and FIFO under/overrun detection Corrected Clear command to conform to the hardware @@ -60,15 +60,14 @@ The 13037D multiple-access (MAC) disc controller supports from one to eight HP 7905 (15 MB), 7906 (20MB), 7920 (50 MB), and 7925 (120 MB) disc drives accessed by one to eight CPUs. The controller hardware consists of a 16-bit - microprogrammed processor constructed from 74S181 bit slices and operating at - 5 MHz, a device controller providing the interconnections to the drives and - CPU interfaces, and error correction circuitry that enables the controller to - correct up to a 32-bit error burst. 1024 words of 24-bit firmware are stored - in ROM. + microprogrammed processor constructed from 74S181 bit slices operating at 5 + MHz, a device controller providing the interconnections to the drives and CPU + interfaces, and an error correction controller that enables the correction of + up to 32-bit error bursts. 1024 words of 24-bit firmware are stored in ROM. - The 13175D disc interface is used to connect the CPU to the 13037 device - controller. In a multiple-CPU system, one interface is strapped to reset the - controller when the CPU's front panel PRESET button is pressed. + The 13175D disc interface is used to connect the HP 1000 CPU to the 13037 + device controller. In a multiple-CPU system, one interface is strapped to + reset the controller when the CPU's front panel PRESET button is pressed. This module simulates a 13037D connected to a single 13175D interface. From one to eight drives may be connected, and drive types may be freely @@ -134,7 +133,7 @@ #define FIFO_STOP (ds.fifo_count >= 5) /* FIFO stop filling test */ #define FIFO_FULL (ds.fifo_count == FIFO_SIZE) /* FIFO full test */ -#define PRESET_ENABLE TRUE /* Preset Jumper (W4) enabled */ +#define PRESET_ENABLE TRUE /* Preset Jumper (W4) is enabled */ /* Debug flags */ @@ -223,7 +222,7 @@ static t_stat activate_unit (UNIT *uptr); 1. The validation routine does not allow the model number or autosizing option to be changed when the unit is attached. Therefore, specifying - UNIT_ATT in the mask field has no deleterious effect. + UNIT_ATT in the mask field has no adverse effect. 2. The modifier DEVNO is deprecated in favor of SC but is retained for compatibility. @@ -237,14 +236,14 @@ static DIB ds_dib = { &ds_io, DS }; #define UNIT_FLAGS (UNIT_FIX | UNIT_ATTABLE | UNIT_ROABLE | UNIT_DISABLE | UNIT_UNLOAD) static UNIT ds_unit [] = { - { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* unit 0 */ - { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* unit 1 */ - { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* unit 2 */ - { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* unit 3 */ - { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* unit 4 */ - { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* unit 5 */ - { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* unit 6 */ - { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* unit 7 */ + { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* drive unit 0 */ + { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* drive unit 1 */ + { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* drive unit 2 */ + { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* drive unit 3 */ + { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* drive unit 4 */ + { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* drive unit 5 */ + { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* drive unit 6 */ + { UDATA (&ds_service_drive, UNIT_FLAGS | MODEL_7905, D7905_WORDS) }, /* drive unit 7 */ { UDATA (&ds_service_controller, UNIT_DIS, 0) }, /* controller unit */ { UDATA (&ds_service_timer, UNIT_DIS, 0) } /* timer unit */ }; @@ -252,8 +251,8 @@ static UNIT ds_unit [] = { static REG ds_reg [] = { { FLDATA (CMFOL, ds.cmfol, 0) }, { FLDATA (CMRDY, ds.cmrdy, 0) }, - { BRDATA (FIFO, ds.fifo, 8, 16, FIFO_SIZE), REG_CIRC }, { DRDATA (FCNT, ds.fifo_count, 5) }, + { BRDATA (FIFO, ds.fifo, 8, 16, FIFO_SIZE), REG_CIRC }, { ORDATA (FREG, ds.fifo_reg, 32), REG_HRO }, { ORDATA (CNTYPE, mac_cntlr.type, 2), REG_HRO }, @@ -375,13 +374,13 @@ DEVICE ds_dev = { The control path consists of the usual control, flag buffer, flag, and SRQ flip-flops, although flag and SRQ are decoupled to allow the full DCPC transfer rate through the FIFO (driving SRQ from the flag limits transfers to - only every other cycle). SRQ is based on the FIFO level: if data or room in - the FIFO is available, SRQ is set to transfer it. The flag is only used to - signal an interrupt at the end of a command. + every other cycle). SRQ is based on the FIFO level: if data or room in the + FIFO is available, SRQ is set to initiate a transfer. The flag is only used + to signal an interrupt at the end of a command. One unusual aspect is that SFC and SFS test different things, rather than - complementary states of the same thing. SFC tests the busy flip-flop, and - SFS tests the flag flip-flop. + complementary states of the same thing. SFC tests the controller busy state, + and SFS tests the flag flip-flop. In addition, the card contains end-of-data-transfer, command-follows, and command-ready flip-flops. EDT is set when the DCPC EDT signal is asserted @@ -397,16 +396,16 @@ DEVICE ds_dev = { 1. In hardware, SRQ is enabled only when the controller is reading or writing the disc (IFIN or IFOUT functions are asserted) and set when the FIFO is not empty (read) or not full (write). In simulation, SRQ is set - by the unit service read/write data phase transfers and cleared below - when the FIFO is empty (read) or full (write). + by the unit service read/write data phase transfers and cleared in the + IOI and IOO signal handlers when the FIFO is empty (read) or full + (write). 2. The DCPC EDT signal cannot set the controller's end-of-data flag directly because a write EOD must occur only after the FIFO has been drained. - 3. Polling the interface or drives must be deferred to the end of the I/O - signal service. If they are performed in the IOO/STC handlers - themselves, an associated CLF might clear the flag that was set by the - poll. + 3. Polling the interface or drives must be deferred to the end of I/O signal + handling. If they are performed in the IOO/STC handlers themselves, an + associated CLF might clear the flag that was set by the poll. 4. Executing a CLC sets the controller's end-of-data flag, which will abort a read or write data transfer in progress. Parameter transfers are not @@ -417,7 +416,7 @@ DEVICE ds_dev = { 5. The hardware Interface Function and Flag Buses are not implemented explicitly. Instead, interface functions and signals are inferred by the - interface by the current command operation and phase. + interface from the current command operation and phase. */ uint32 ds_io (DIB *dibptr, IOCYCLE signal_set, uint32 stat_data) @@ -512,7 +511,7 @@ while (working_set) { if (ds.srq == SET && DEBUG_PRI (ds_dev, DEB_CMDS)) fprintf (sim_deb, ">>DS cmds: [OTx%s] SRQ cleared\n", hold_or_clear); - ds.srq = CLEAR; /* clear SRQ */ + ds.srq = CLEAR; /* clear SRQ to stop filling */ } } break; @@ -622,7 +621,7 @@ return stat_data; overrun error. Write transfers set the initial SRQ to request words from the CPU. As each - arrives, it is unloaded from the FIFO into the sector buffer, and SRQ is + word arrives, it is unloaded from the FIFO into the sector buffer, and SRQ is enabled. If the current sector transfer is complete, the controller is moved to the end phase. If the FIFO underflows, the write terminates with a data overrun error. @@ -639,12 +638,12 @@ return stat_data; Implementation notes: - 1. Every command except Seek, Recalibrate, and End set the flag when the + 1. Every command except Seek, Recalibrate, and End sets the flag when the command completes. A command completes when the controller is no longer - busy (it becomes idle for Seek, Recalibrate, and End, and becomes waiting - for all others). Seek and Recalibrate may generate errors (e.g., heads - unloaded), in which case the flag must be set. But in these cases, the - controller state is waiting, not idle. + busy (it becomes idle for Seek, Recalibrate, and End, or it becomes + waiting for all others). Seek and Recalibrate may generate errors (e.g., + heads unloaded), in which case the flag must be set. But in these cases, + the controller state is waiting, not idle. However, it is insufficient simply to check that the controller has moved to the wait state, because a seek may complete while the controller is @@ -653,8 +652,9 @@ return stat_data; completes, another command is issued that attempts to access unit 1, which is not ready. The command fails with a Status-2 error, and the controller moves to the wait state. When the seek completes, the - controller is waiting with error status. We must determine if the seek - completed successfully or not, as we must interrupt in the latter case. + controller is waiting with error status. We must determine whether the + seek completed successfully or not, as we must interrupt in the latter + case. Therefore, we determine seek completion by checking if the Attention status was set. Attention sets only if the seek completes successfully. @@ -663,31 +663,31 @@ return stat_data; command terminated before the seek ever started. Also, a seek may complete while the controller is busy, waiting, or idle.) - 2. For debug printouts, we want to print the name of the command that has - completed when the controller returns to the idle or wait state. - Normally, we would use the controller's "opcode" field to identify the - command that completed. However, while waiting for Seek or Recalibrate - completion, "opcode" may be set to another command if that command does - not access this drive. For example, it might be set to a Read of - another unit, or a Request Status for this unit. So we can't rely on - "opcode" to report the correct positioning command completion. + 2. For debug printouts, we want to print the name of the command that has + completed when the controller returns to the idle or wait state. + Normally, we would use the controller's "opcode" field to identify the + command that completed. However, while waiting for Seek or Recalibrate + completion, "opcode" may be set to another command if that command does + not access this drive. For example, it might be set to a Read of another + unit, or a Request Status for this unit. So we can't rely on "opcode" to + report the correct name of the completed positioning command. - However, we cannot rely on "uptr->OP" either, as it can be changed - during the course of a command. For example, Read Without Verify is - changed to Read after a track crossing. + However, we cannot rely on "uptr->OP" either, as that can be changed + during the course of a command. For example, Read Without Verify is + changed to Read after a track crossing. - Instead, we have to determine whether a seek is completing. If it is, - then we report "uptr->OP"; otherwise, we report "opcode". + Instead, we have to determine whether a seek is completing. If it is, + then we report "uptr->OP"; otherwise, we report "opcode". - 3. The initial write SRQ must set only at the transition from the start - phase to the data phase. If a write command begins with an auto-seek, - the drive service will be entered twice in the start phase (the first - entry performs the seek, and the second begins the write). In hardware, - SRQ does not assert until the write begins. + 3. The initial write SRQ must set only at the transition from the start + phase to the data phase. If a write command begins with an auto-seek, + the drive service will be entered twice in the start phase (the first + entry performs the seek, and the second begins the write). In hardware, + SRQ does not assert until the write begins. - 4. The DCPC EDT signal cannot set the controller's end-of-data flag - directly because a write EOD must only occur after the FIFO has been - drained. + 4. The DCPC EDT signal cannot set the controller's end-of-data flag + directly because a write EOD must only occur after the FIFO has been + drained. */ t_stat ds_service_drive (UNIT *uptr) @@ -695,9 +695,10 @@ t_stat ds_service_drive (UNIT *uptr) static const char completion_message [] = ">>DS rwsc: Unit %d %s command completed\n"; t_stat result; t_bool seek_completion; -FLIP_FLOP entry_srq = ds.srq; /* SRQ state on entry */ -CNTLR_PHASE entry_phase = (CNTLR_PHASE) uptr->PHASE; /* operation phase on entry */ -uint32 entry_status = uptr->STAT; /* drive status on entry */ +int32 unit; +FLIP_FLOP entry_srq = ds.srq; /* get the SRQ state on entry */ +CNTLR_PHASE entry_phase = (CNTLR_PHASE) uptr->PHASE; /* get the operation phase on entry */ +uint32 entry_status = uptr->STAT; /* get the drive status on entry */ result = dl_service_drive (&mac_cntlr, uptr); /* service the drive */ @@ -764,7 +765,7 @@ if ((CNTLR_PHASE) uptr->PHASE == data_phase) /* is the drive in the d break; - default: /* entered with an invalid state */ + default: /* we were entered with an invalid state */ result = SCPE_IERR; /* return an internal (programming) error */ break; } /* end of data phase operation dispatch */ @@ -774,13 +775,13 @@ if (DEBUG_PRI (ds_dev, DEB_CMDS) && entry_srq != ds.srq) fprintf (sim_deb, ">>DS cmds: SRQ %s\n", ds.srq == SET ? "set" : "cleared"); -if (uptr->wait) /* is service requested? */ +if (uptr->wait) /* was service requested? */ activate_unit (uptr); /* schedule the next event */ seek_completion = ~entry_status & uptr->STAT & DL_S2ATN; /* seek is complete when Attention sets */ if (mac_cntlr.state != cntlr_busy) { /* is the command complete? */ - if (mac_cntlr.state == cntlr_wait && !seek_completion) /* is it command and not seek completion? */ + if (mac_cntlr.state == cntlr_wait && !seek_completion) /* is it command but not seek completion? */ ds_io (&ds_dib, ioENF, 0); /* set the data flag to interrupt the CPU */ poll_interface (); /* poll the interface for the next command */ @@ -788,22 +789,22 @@ if (mac_cntlr.state != cntlr_busy) { /* is the command co } -if (DEBUG_PRI (ds_dev, DEB_RWSC)) +if (DEBUG_PRI (ds_dev, DEB_RWSC)) { + unit = uptr - ds_unit; /* get the unit number */ + if (result == SCPE_IERR) /* did an internal error occur? */ fprintf (sim_deb, ">>DS rwsc: Unit %d %s command %s phase service not handled\n", - uptr - ds_dev.units, - dl_opcode_name (MAC, (CNTLR_OPCODE) uptr->OP), + unit, dl_opcode_name (MAC, (CNTLR_OPCODE) uptr->OP), dl_phase_name ((CNTLR_PHASE) uptr->PHASE)); else if (seek_completion) /* if a seek has completed */ fprintf (sim_deb, completion_message, /* report the unit command */ - uptr - ds_dev.units, - dl_opcode_name (MAC, (CNTLR_OPCODE) uptr->OP)); + unit, dl_opcode_name (MAC, (CNTLR_OPCODE) uptr->OP)); else if (mac_cntlr.state == cntlr_wait) /* if the controller has stopped */ fprintf (sim_deb, completion_message, /* report the controller command */ - uptr - ds_dev.units, - dl_opcode_name (MAC, mac_cntlr.opcode)); + unit, dl_opcode_name (MAC, mac_cntlr.opcode)); + } return result; /* return the result of the service */ } @@ -862,11 +863,11 @@ switch ((CNTLR_PHASE) uptr->PHASE) { /* dispatch the current case clear: case set_file_mask: case wakeup: - ds_io (&ds_dib, ioENF, 0); /* complete the operation with the flag set */ + ds_io (&ds_dib, ioENF, 0); /* complete the operation and set the flag */ break; - default: /* entered with an invalid state */ + default: /* we were entered with an invalid state */ result = SCPE_IERR; /* return an internal (programming) error */ break; } /* end of operation dispatch */ @@ -917,7 +918,7 @@ switch ((CNTLR_PHASE) uptr->PHASE) { /* dispatch the current break; - default: /* entered with an invalid state */ + default: /* we were entered with an invalid state */ result = SCPE_IERR; /* return an internal (programming) error */ break; } /* end of operation dispatch */ @@ -976,7 +977,7 @@ return result; /* return the result of 1. During a power-on reset, a pointer to the FIFO simulation register is saved to allow access to the "qptr" field during FIFO loading and - unloading. This enables the SCP to view the FIFO as a circular queue, so + unloading. This enables SCP to view the FIFO as a circular queue, so that the bottom word of the FIFO is always displayed as FIFO[0], regardless of where it is in the actual FIFO array. @@ -992,7 +993,7 @@ if (sim_switches & SWMASK ('P')) { /* is this a power-on re ds.fifo_reg = find_reg ("FIFO", NULL, dptr); /* find the FIFO register entry */ if (ds.fifo_reg == NULL) /* if it cannot be found, */ - return SCPE_IERR; /* report a programming error! */ + return SCPE_IERR; /* report a programming error */ else { /* found it */ ds.fifo_reg->qptr = 0; /* so reset the FIFO bottom index */ @@ -1064,7 +1065,7 @@ return result; /* Boot a MAC disc drive. The MAC disc bootstrap program is loaded from the HP 12992B Boot Loader ROM - into memory, the I/O instructions are configured from the interface card + into memory, the I/O instructions are configured for the interface card's select code, and the program is run to boot from the specified unit. The loader supports booting from cylinder 0 of drive unit 0 only. Before execution, the S register is automatically set as follows: @@ -1166,7 +1167,7 @@ if (unitno != 0) /* boot supported on return SCPE_NOFNC; /* report "Command not allowed" if attempted */ if (ibl_copy (ds_rom, ds_dib.select_code)) /* copy the boot ROM to memory and configure */ - return SCPE_IERR; /* return an internal error if failed */ + return SCPE_IERR; /* return an internal error if the copy failed */ SR = SR & (IBL_OPT | IBL_DS_HEAD) /* set S to a reasonable value */ | IBL_DS | IBL_MAN | (ds_dib.select_code << IBL_V_DEV); /* before boot execution */ @@ -1193,7 +1194,7 @@ return SCPE_OK; t_stat ds_load_unload (UNIT *uptr, int32 value, char *cptr, void *desc) { -const t_bool load = (value != UNIT_UNLOAD); /* true if heads are loading */ +const t_bool load = (value != UNIT_UNLOAD); /* true if the heads are loading */ return dl_load_unload (&mac_cntlr, uptr, load); /* load or unload the heads */ } @@ -1265,7 +1266,7 @@ if (uptr) { /* did the command start time = uptr->wait; /* save the activation time */ if (time) /* was the unit scheduled? */ - activate_unit (uptr); /* activate it (clears "wait") */ + activate_unit (uptr); /* activate it (and clear the "wait" field) */ if (DEBUG_PRI (ds_dev, DEB_RWSC)) { unit = uptr - ds_unit; /* get the unit number */ @@ -1337,8 +1338,8 @@ return; void poll_drives (void) { -if (mac_cntlr.state == cntlr_idle && ds.control == SET) /* controller is idle and OK to interrupt? */ - if (dl_poll_drives (&mac_cntlr, ds_unit, DL_MAXDRIVE)) /* poll drives; was Attention seen? */ +if (mac_cntlr.state == cntlr_idle && ds.control == SET) /* is the controller idle and interrupts are allowed? */ + if (dl_poll_drives (&mac_cntlr, ds_unit, DL_MAXDRIVE)) /* poll the drives; was Attention seen? */ ds_io (&ds_dib, ioENF, 0); /* request an interrupt */ return; } @@ -1455,7 +1456,7 @@ return; static t_stat activate_unit (UNIT *uptr) { -uint32 unit; +int32 unit; t_stat result; if (DEBUG_PRI (ds_dev, DEB_SERV)) { diff --git a/HP2100/hp2100_mpx.c b/HP2100/hp2100_mpx.c index 65aa65c2..a4d91dd9 100644 --- a/HP2100/hp2100_mpx.c +++ b/HP2100/hp2100_mpx.c @@ -1658,7 +1658,7 @@ return SCPE_OK; t_stat mpx_line_svc (UNIT *uptr) { -const uint32 port = uptr - mpx_unit; /* port number */ +const int32 port = uptr - mpx_unit; /* port number */ const uint16 rt = mpx_rcvtype [port]; /* receive type for port */ const uint32 data_bits = 5 + GET_BPC (mpx_config [port]); /* number of data bits */ const uint32 data_mask = (1 << data_bits) - 1; /* mask for data bits */ diff --git a/HP2100/hp2100_ms.c b/HP2100/hp2100_ms.c index bc3acca6..c78c5e0c 100644 --- a/HP2100/hp2100_ms.c +++ b/HP2100/hp2100_ms.c @@ -690,7 +690,7 @@ int32 unum; t_mtrlnt tbc; t_stat st, r = SCPE_OK; -unum = uptr - msc_dev.units; /* get unit number */ +unum = uptr - msc_unit; /* get unit number */ if ((uptr->FNC != FNC_RWS) && (uptr->flags & UNIT_OFFLINE)) { /* offline? */ msc_sta = (msc_sta | STA_REJ) & ~STA_BUSY; /* reject */ @@ -905,7 +905,7 @@ else t_stat ms_map_err (UNIT *uptr, t_stat st) { -int32 unum = uptr - msc_dev.units; /* get unit number */ +int32 unum = uptr - msc_unit; /* get unit number */ if (DEBUG_PRI (msc_dev, DEB_RWS)) fprintf (sim_deb, diff --git a/HP2100/hp2100_mt.c b/HP2100/hp2100_mt.c index 144db5de..72066de9 100644 --- a/HP2100/hp2100_mt.c +++ b/HP2100/hp2100_mt.c @@ -25,6 +25,7 @@ MT 12559A 3030 nine track magnetic tape + 25-Mar-12 JDB Removed redundant MTAB_VUN from "format" MTAB entry 10-Feb-12 JDB Deprecated DEVNO in favor of SC 28-Mar-11 JDB Tidied up signal handling 29-Oct-10 JDB Fixed command scanning error in mtcio ioIOO handler @@ -220,7 +221,7 @@ REG mtc_reg[] = { MTAB mtc_mod[] = { { MTUF_WLK, 0, "write enabled", "WRITEENABLED", NULL }, { MTUF_WLK, MTUF_WLK, "write locked", "LOCKED", NULL }, - { MTAB_XTD | MTAB_VDV | MTAB_VUN, 0, "FORMAT", "FORMAT", + { MTAB_XTD | MTAB_VDV, 0, "FORMAT", "FORMAT", &sim_tape_set_fmt, &sim_tape_show_fmt, NULL }, { MTAB_XTD | MTAB_VDV, 1, "SC", "SC", &hp_setsc, &hp_showsc, &mtd_dev }, { MTAB_XTD | MTAB_VDV | MTAB_NMO, 1, "DEVNO", "DEVNO", &hp_setdev, &hp_showdev, &mtd_dev }, diff --git a/HP2100/hp2100_stddev.c b/HP2100/hp2100_stddev.c index 82740889..92208b00 100644 --- a/HP2100/hp2100_stddev.c +++ b/HP2100/hp2100_stddev.c @@ -985,7 +985,7 @@ return SCPE_OK; t_stat tty_set_opt (UNIT *uptr, int32 val, char *cptr, void *desc) { -int32 u = uptr - tty_dev.units; +int32 u = uptr - tty_unit; if (u > TTO) return SCPE_NOFNC; if ((u == TTI) && (val == TT_MODE_7P)) @@ -997,7 +997,7 @@ return SCPE_OK; t_stat tty_set_alf (UNIT *uptr, int32 val, char *cptr, void *desc) { -int32 u = uptr - tty_dev.units; +int32 u = uptr - tty_unit; if (u != TTI) return SCPE_NOFNC; return SCPE_OK; diff --git a/HP2100/hp_disclib.c b/HP2100/hp_disclib.c index 14e3aaa7..f5218ff6 100644 --- a/HP2100/hp_disclib.c +++ b/HP2100/hp_disclib.c @@ -24,7 +24,7 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the authors. - 20-Mar-12 JDB First release + 28-Mar-12 JDB First release 09-Nov-11 JDB Created disc controller common library from DS simulator References: @@ -65,6 +65,11 @@ disc heads, classify commands, and provide opcode and phase name strings for debugging. + Autosizing is supported when attaching a disc image. If enabled, the model + of the drive is set to match the disc image size. For example, if a 50 MB + disc image is attached to a unit set for autosizing, the unit's model will be + set to a 7920(H). + The interface simulator declares a structure that contains the state variables for a controller. A MAC controller may handle multiple disc units. An ICD controller handles only a single disc unit, but multiple controllers @@ -79,7 +84,7 @@ stored in the controller state structure. The controller maintains the current index into the buffer, as well as the length of valid data stored there. Other than setting the length when the controller places data into - the buffer, and resetting the index at the start of a sector read or write, + the buffer and resetting the index at the start of a sector read or write, the interface simulator is free to manipulate these values as desired. In general, a user of the library is free to read any of the controller state @@ -87,16 +92,16 @@ with controller operations, with these exceptions: Field Name Description - =========== ======================== + =========== ============================ status controller status eod end of data flag index data buffer index length data buffer length - seek_time seek delay time + seek_time per-cylinder seek delay time sector_time intersector delay time - cmd_time command start delay time - data_time data transfer delay time - wait_time command wait timeout + cmd_time command response time + data_time data transfer response time + wait_time command wait time In hardware, the controller executes in three basic states: @@ -121,10 +126,10 @@ 3. In command execution, which processes the current command. - During command execution, waits for input parameters, seek completion, - data transfers, and output status words are handled internally. Each - wait is governed by the 1.8 second timer; if it expires, the command is - aborted. + During command execution, the waits for input parameters, seek + completion, data transfers, and output status words are handled + internally. Each wait is governed by the 1.8 second timer; if it + expires, the command is aborted. In simulation, these states are represented by the values cntlr_idle, cntlr_wait, and cntlr_busy, respectively. @@ -134,14 +139,15 @@ unit of a contiguous array is passed, and the unit number present in the command is used to index to the target unit. - A MAC controller emulation requires an array of two contiguous auxiliary - units containing a controller unit and a command wait timeout unit. Commands + A MAC controller emulation also requires an array of two contiguous auxiliary + units containing a controller unit and a command wait timeout unit. Commands that do not access the drive, such as Address Record, are scheduled on the controller unit to allow controller commands to execute while drive units are - seeking. The command wait timer limits the amount of time the controller will - wait for the interface to supply a command or parameter. A pointer to the - auxiliary unit array is set up during controller state variable - initialization. + seeking. The command wait timer limits the amount of time the controller + will wait for the interface to supply a command or parameter. A pointer to + the auxiliary unit array is set up during controller state variable + initialization. The auxiliary array may be separate or an extension of the + drive unit array. An ICD controller manages a single unit corresponding to the drive in which the controller is integrated. An interface declares a unit array @@ -179,9 +185,9 @@ the caller uses this feature, the field should be reset to zero before the next service call. - The MAC timer unit is activated by the library, and the "wait" field is not + The MAC timer unit is activated by the library, and its "wait" field is not used. The timer starts when a command other than End, Seek, or Recalibrate - completes, and when the controller is waiting for the interface to supply or + completes, or when the controller is waiting for the interface to supply or accept a parameter during command execution. It stops when an End, Seek, or Recalibrate command completes, a command is prepared for execution, or the final parameter has been supplied or accepted by the interface during command @@ -190,7 +196,7 @@ The controller maintains six variables in each drive's unit structure: wait -- the current service activation time - pos -- the current file offset + pos -- the current byte offset into the disc image file u3 (CYL) -- the current drive cylinder u4 (STAT) -- the drive status (Status-2) u5 (OP) -- the drive operation in process @@ -247,32 +253,32 @@ -/* Command accessors (16-bit word) */ +/* Command accessors */ #define DL_V_OPCODE 8 /* bits 12- 8: general opcode */ #define DL_V_HOLD 7 /* bits 7- 7: general hold flag */ #define DL_V_UNIT 0 /* bits 3- 0: general unit number */ -#define DL_V_SPD 13 /* bits 15-13: initialize S/P/D flags */ -#define DL_V_CHEAD 6 /* bits 7- 6: cold load head */ -#define DL_V_CSECT 0 /* bits 5- 0: cold load sector */ -#define DL_V_FRETRY 4 /* bits 7- 4: file mask retry count */ -#define DL_V_FDECR 3 /* bits 3- 3: file mask seek decrement */ -#define DL_V_FSPEN 2 /* bits 2- 2: file mask sparing enable */ -#define DL_V_FCYLM 1 /* bits 1- 1: file mask cylinder mode */ -#define DL_V_FAUTSK 0 /* bits 0- 0: file mask auto seek */ +#define DL_V_SPD 13 /* bits 15-13: Initialize S/P/D flags */ +#define DL_V_CHEAD 6 /* bits 7- 6: Cold Load Read head number */ +#define DL_V_CSECT 0 /* bits 5- 0: Cold Load Read sector number */ +#define DL_V_FRETRY 4 /* bits 7- 4: Set File Mask retry count */ +#define DL_V_FDECR 3 /* bits 3- 3: Set File Mask seek decrement */ +#define DL_V_FSPEN 2 /* bits 2- 2: Set File Mask sparing enable */ +#define DL_V_FCYLM 1 /* bits 1- 1: Set File Mask cylinder mode */ +#define DL_V_FAUTSK 0 /* bits 0- 0: Set File Mask auto seek */ -#define DL_V_FMASK 0 /* bits 3- 0: file mask (combined) */ +#define DL_V_FMASK 0 /* bits 3- 0: Set File Mask (flags combined) */ -#define DL_M_OPCODE 037 -#define DL_M_UNIT 017 +#define DL_M_OPCODE 037 /* opcode mask */ +#define DL_M_UNIT 017 /* unit mask */ -#define DL_M_SPD 007 -#define DL_M_CHEAD 003 -#define DL_M_CSECT 077 -#define DL_M_FRETRY 017 -#define DL_M_FMASK 017 +#define DL_M_SPD 007 /* S/P/D flags mask */ +#define DL_M_CHEAD 003 /* Cold Load Read head number mask */ +#define DL_M_CSECT 077 /* Cold Load Read sector number mask */ +#define DL_M_FRETRY 017 /* Set File Mask retry count mask */ +#define DL_M_FMASK 017 /* Set File Mask flags mask */ #define GET_OPCODE(c) (CNTLR_OPCODE) (((c) >> DL_V_OPCODE) & DL_M_OPCODE) @@ -290,13 +296,13 @@ #define DL_FAUTSK (1 << DL_V_FAUTSK) -/* Parameter accessors (16-bit word) */ +/* Parameter accessors */ #define DL_V_HEAD 8 /* bits 12- 8: head number */ #define DL_V_SECTOR 0 /* bits 7- 0: sector number */ -#define DL_M_HEAD 0017 -#define DL_M_SECTOR 0377 +#define DL_M_HEAD 0017 /* head number mask */ +#define DL_M_SECTOR 0377 /* sector number mask */ #define GET_HEAD(p) (((p) >> DL_V_HEAD) & DL_M_HEAD) #define GET_SECTOR(p) (((p) >> DL_V_SECTOR) & DL_M_SECTOR) @@ -310,15 +316,15 @@ In hardware, drives report their Drive Type numbers to the controller upon receipt of a Request Status tag bus command. The drive type is used to determine the legal range of head and sector addresses (the drive itself will - validate the cylinder during seeks). + validate the cylinder address during seeks). In simulation, we set up a table of drive properties and use the model ID as an index into the table. The table is used to validate seek parameters and to provide the mapping between CHS addresses and the linear byte addresses required by the host file access routines. - The 7905/06/06H drives consist of removable and fixed platters, whereas the - 7920/20H/25/25H drives have only removable multi-platter packs. As a result, + The 7905/06(H) drives consist of removable and fixed platters, whereas the + 7920(H)/25(H) drives have only removable multi-platter packs. As a result, 7905/06 drives are almost always accessed in platter mode, i.e., a given logical disc area is fully contained on either the removable or fixed platter, whereas the 7920/25 drives are almost always accessed in cylinder @@ -332,12 +338,12 @@ The simulator maps the tracks on the 7905/06 removable platter (heads 0 and 1) to the first half of the disc image, and the tracks on the fixed platter (heads 2 and, for the 7906 only, 3) to the second half of the image. For the - 7906/06H, the cylinder-head order of the tracks is 0-0, 0-1, 1-0, 1-1, ..., + 7906(H), the cylinder-head order of the tracks is 0-0, 0-1, 1-0, 1-1, ..., 410-0, 410-1, 0-2, 0-3, 1-2, 1-3, ..., 410-2, 410-3. The 7905 order is the same, except that head 3 tracks are omitted. - For the 7920/20H/25/25H, all tracks appear in cylinder-head order, e.g., 0-0, - 0-1, 0-2, 0-3, 0-4, 1-0, 1-1, ..., 822-2, 822-3, 822-4 for the 7920/20H. + For the 7920(H)/25(H), all tracks appear in cylinder-head order, e.g., 0-0, + 0-1, 0-2, 0-3, 0-4, 1-0, 1-1, ..., 822-2, 822-3, 822-4 for the 7920(H). This variable-access geometry is accomplished by defining additional "heads per cylinder" values for the fixed and removable sections of each drive that @@ -430,7 +436,7 @@ static const DRIVE_PROPERTIES drive_props [] = { /* Command properties table. - The validity of each command for a given type of controller is checked + The validity of each command for a specified controller type is checked against the command properties table when it is prepared. The table also includes the count of inbound and outbound properties, the class of the command, and flags to indicate certain common actions that should be taken. @@ -440,10 +446,10 @@ typedef struct { uint32 params_in; /* count of input parameters */ uint32 params_out; /* count of output parameters */ CNTLR_CLASS classification; /* command classification */ - t_bool valid [TYPE_COUNT]; /* per-type command validity */ - t_bool clear_status; /* command clears status */ + t_bool valid [type_count]; /* per-type command validity */ + t_bool clear_status; /* command clears the controller status */ t_bool unit_field; /* command has a unit field */ - t_bool unit_check; /* command checks unit number validity */ + t_bool unit_check; /* command checks the unit number validity */ t_bool unit_access; /* command accesses the drive unit */ t_bool seek_wait; /* command waits for seek completion */ } DS_PROPS; @@ -606,7 +612,7 @@ if (props->clear_status) { /* clear the prior contr cvptr->spd_unit = SET_S1UNIT (unit); /* save the unit number for status requests */ } -if (cvptr->type <= last_type /* is the controller type legal? */ +if (cvptr->type <= last_type /* is the controller type legal, */ && props->valid [cvptr->type]) /* and the opcode defined for this controller? */ if (props->unit_check && unit > DL_MAXUNIT) /* if the unit number is checked and is illegal, */ dl_end_command (cvptr, unit_unavailable); /* end with a unit unavailable error */ @@ -617,13 +623,13 @@ if (cvptr->type <= last_type /* is the controller typ cvptr->length = props->params_in; /* set the inbound parameter count */ cvptr->index = 1; /* point at the first parameter element (if any) */ - if (cvptr->type == MAC && cvptr->length) { /* MAC controller and inbound parameters? */ + if (cvptr->type == MAC && cvptr->length) { /* is this a MAC controller with inbound parameters? */ cvptr->aux [controller].OP = opcode; /* save the opcode */ cvptr->aux [controller].PHASE = data_phase; /* and set the phase for parameter pickup */ set_timer (cvptr, SET); /* start the timer to wait for the first parameter */ } - return TRUE; /* command is now prepared for execution */ + return TRUE; /* the command is now prepared for execution */ } else /* the opcode is undefined */ @@ -649,8 +655,8 @@ return FALSE; /* the preparation has f If a seek is in progress on a drive when a command accessing that drive is started, the unit pointer is returned but the unit's "wait" field is set to zero. In this case, the unit must not be activated (as it already is). - Instead, the unit's opcode and phase fields are set to start the command - automatically when the seek completes. + Instead, the unit's opcode and phase fields will have been set to start the + command automatically when the seek completes. For commands that return status from the controller, the buffer will contain the returned value(s), the buffer index will be zero, and the buffer length @@ -671,9 +677,9 @@ return FALSE; /* the preparation has f permanently offline. 2. Commands that check for a valid unit do some processing before failing - with a Status-2 (not ready) error. For example, the Seek command accepts - its parameters from the CPU and sets the CHS values into the controller - before failing. + with a Status-2 (not ready) error if the unit is invalid. For example, + the Seek command accepts its parameters from the CPU and sets the CHS + values into the controller before failing. 3. In hardware, read, write, and recalibrate commands wait in an internal loop for a pending seek completion and clear the resulting Attention @@ -692,7 +698,7 @@ return FALSE; /* the preparation has f a seek command with a Seek Check error. The firmware does not test explicitly for Access Not Ready before executing the command, so the parameters (e.g., controller CHS addresses) are still set as though the - command succeeded. + command had succeeded. A Seek command will return to the Poll Loop with Seek Check status set. When the seek in progress completes, the controller will interrupt with @@ -723,8 +729,8 @@ return FALSE; /* the preparation has f 8. The activation time is set to the intersector time (latency) for read and write commands, and to the controller processing time for all others. - This time cannot be shorter than 20 instructions, or DVR32 will be unable - to start DCPC in time to avoid an over/underrun. + The read/write start time cannot be shorter than 20 instructions, or + DVR32 will be unable to start DCPC in time to avoid an over/underrun. */ UNIT *dl_start_command (CVPTR cvptr, UNIT *units, uint32 unit_limit) @@ -752,11 +758,11 @@ if (cvptr->type == MAC) { /* is this a MAC control else { /* for an ICD controller, */ unit = 0; /* the unit value is ignored */ - uptr = units + unit_limit; /* and we use the indicated unit */ + uptr = units + unit_limit; /* and we use the indicated unit */ } if (props->unit_check && !uptr /* if the unit number is checked and is invalid */ - || props->seek_wait && (drive_status (uptr) & DL_S2STOPS)) { /* or if waiting for an offline drive */ + || props->seek_wait && (drive_status (uptr) & DL_S2STOPS)) { /* or if we're waiting for an offline drive */ dl_end_command (cvptr, status_2_error); /* then the command ends with a Status-2 error */ uptr = NULL; /* prevent the command from starting */ } @@ -788,16 +794,16 @@ cvptr->eod = CLEAR; /* clear the end of data switch (cvptr->opcode) { /* dispatch the command */ case cold_load_read: - cvptr->cylinder = 0; /* set cylinder to 0 */ - cvptr->head = GET_CHEAD (cvptr->buffer [0]); /* get the head */ + cvptr->cylinder = 0; /* set the cylinder address to 0 */ + cvptr->head = GET_CHEAD (cvptr->buffer [0]); /* set the head */ cvptr->sector = GET_CSECT (cvptr->buffer [0]); /* and sector from the command */ if (is_seeking) { /* if a seek is in progress, */ uptr->STAT |= DL_S2SC; /* a Seek Check occurs */ - cvptr->file_mask = DL_FSPEN; /* set sparing enabled */ - uptr->OP = read; /* start the read on seek completion */ + cvptr->file_mask = DL_FSPEN; /* enable sparing */ + uptr->OP = read; /* start the read on the seek completion */ uptr->PHASE = start_phase; /* and reset the command phase */ - return uptr; /* to allow the seek to complete normally */ + return uptr; /* to allow the seek to complete normally */ } else /* the drive is not seeking */ @@ -809,7 +815,7 @@ switch (cvptr->opcode) { /* dispatch the command case seek: cvptr->cylinder = cvptr->buffer [1]; /* get the supplied cylinder */ cvptr->head = GET_HEAD (cvptr->buffer [2]); /* and head */ - cvptr->sector = GET_SECTOR (cvptr->buffer [2]); /* and sector */ + cvptr->sector = GET_SECTOR (cvptr->buffer [2]); /* and sector addresses */ if (is_seeking) { /* if a seek is in progress, */ uptr->STAT |= DL_S2SC; /* a Seek Check occurs */ @@ -824,10 +830,13 @@ switch (cvptr->opcode) { /* dispatch the command cvptr->buffer [0] = /* set the Status-1 value */ cvptr->spd_unit | SET_S1STAT (cvptr->status); /* into the buffer */ - if (unit > unit_limit) /* if the unit number is invalid */ - rptr = NULL; /* it does not correspond to a unit */ - else /* otherwise, the unit is valid */ - rptr = &units [unit]; /* so get the address of the referenced unit */ + if (cvptr->type == MAC) /* is this a MAC controller? */ + if (unit > unit_limit) /* if the unit number is invalid */ + rptr = NULL; /* it does not correspond to a unit */ + else /* otherwise, the unit is valid */ + rptr = &units [unit]; /* so get the address of the referenced unit */ + else /* if not a MAC controller */ + rptr = uptr; /* then the referenced unit is the current unit */ cvptr->buffer [1] = drive_status (rptr); /* set the Status-2 value */ @@ -878,7 +887,7 @@ switch (cvptr->opcode) { /* dispatch the command case address_record: cvptr->cylinder = cvptr->buffer [1]; /* get the supplied cylinder */ cvptr->head = GET_HEAD (cvptr->buffer [2]); /* and head */ - cvptr->sector = GET_SECTOR (cvptr->buffer [2]); /* and sector */ + cvptr->sector = GET_SECTOR (cvptr->buffer [2]); /* and sector addresses */ cvptr->eoc = CLEAR; /* clear the end-of-cylinder flag */ break; @@ -886,8 +895,8 @@ switch (cvptr->opcode) { /* dispatch the command case set_file_mask: cvptr->file_mask = GET_FMASK (cvptr->buffer [0]); /* get the supplied file mask */ - if (cvptr->type == MAC) /* if a MAC controller */ - cvptr->retry = GET_FRETRY (cvptr->buffer [0]); /* the retry counter is supplied too */ + if (cvptr->type == MAC) /* if this is a MAC controller, */ + cvptr->retry = GET_FRETRY (cvptr->buffer [0]); /* the retry count is supplied too */ break; @@ -904,7 +913,7 @@ switch (cvptr->opcode) { /* dispatch the command default: /* the remaining commands */ - break; /* are handled in the service routines */ + break; /* are handled by the service routines */ } @@ -926,7 +935,7 @@ else /* Complete a command. - The current command is terminated with the indicated status. The command + The current command is completed with the indicated status. The command result status is set, the controller enters the command wait state, and the CPU timer is restarted. */ @@ -940,14 +949,14 @@ return; } -/* Poll the drives for attention status. +/* Poll the drives for Attention status. If interrupts are enabled on the interface, this routine is called to check if any drive is requesting attention. The routine returns TRUE if a drive is - requestion attention and FALSE if not. + requesting attention and FALSE if not. Starting with the last unit requesting attention, each drive is checked in - sequence. If a drive has its Attention status set, the controller sets its + sequence. If a drive has its Attention status set, the controller saves its unit number, sets the result status to Drive Attention, and enters the command wait state. The routine returns TRUE to indicate that an interrupt should be generated. The next time the routine is called, the poll begins @@ -970,12 +979,12 @@ for (unit = 0; unit <= unit_limit; unit++) { /* check each unit i units [cvptr->poll_unit].STAT &= ~DL_S2ATN; /* clear the Attention status */ cvptr->spd_unit = SET_S1UNIT (cvptr->poll_unit); /* set the controller's unit number */ cvptr->status = drive_attention; /* and status */ - cvptr->state = cntlr_wait; /* and wait for a command */ + cvptr->state = cntlr_wait; /* and wait for a command */ return TRUE; /* tell the caller to interrupt */ } } -return FALSE; /* no requests, so no interrupt */ +return FALSE; /* no requests, so do not generate an interrupt */ } @@ -989,7 +998,7 @@ return FALSE; /* no requests, so n service routine accesses these six variables in the UNIT structure: wait -- the current service activation time - pos -- the current file offset + pos -- the current byte offset into the disc image file u3 (CYL) -- the current drive cylinder u4 (STAT) -- the drive status (Status-2) u5 (OP) -- the drive operation in process @@ -1026,13 +1035,13 @@ return FALSE; /* no requests, so n An operation in the data phase is in the process of transferring data between the CPU and sector buffer. Because this process is interface-specific, the - service routine does nothing (other than validate) with this phase. It is up + service routine does nothing (other than validate) in this phase. It is up to the caller to transition from the data phase to the end phase when the transfer is complete. If an operation is completed, or an error has occurred, the controller state on return will be either idle or waiting, instead of busy. The caller should - check the controller state to determine if normal completion or error + check the controller status to determine if normal completion or error recovery is appropriate. If the command is continuing, the service activation time will be set @@ -1072,7 +1081,7 @@ switch ((CNTLR_PHASE) uptr->PHASE) { /* dispatch the phase */ case seek: if (start_seek (cvptr, uptr, opcode, end_phase) /* start the seek; if it succeeded, */ && (cvptr->type == MAC)) /* and this a MAC controller, */ - dl_idle_controller (cvptr); /* idle until the seek completes */ + dl_idle_controller (cvptr); /* then go idle until it completes */ break; @@ -1101,7 +1110,7 @@ switch ((CNTLR_PHASE) uptr->PHASE) { /* dispatch the phase */ result = start_read (cvptr, uptr); /* start the sector read */ if (uptr->PHASE == data_phase) { /* did the read start successfully? */ - uptr->PHASE = end_phase; /* skip the data phase for Verify */ + uptr->PHASE = end_phase; /* skip the data phase */ uptr->wait = cvptr->sector_time /* reschedule for the intersector time */ + cvptr->data_time * DL_WPSEC; /* plus the data read time */ } @@ -1131,11 +1140,11 @@ switch ((CNTLR_PHASE) uptr->PHASE) { /* dispatch the phase */ case request_disc_address: case end: case wakeup: - dl_service_controller (cvptr, uptr); /* call the controller for service */ + dl_service_controller (cvptr, uptr); /* the controller service handles these */ break; - default: /* entered with an invalid state */ + default: /* we were entered with an invalid state */ result = SCPE_IERR; /* return an internal (programming) error */ break; } /* end of operation dispatch */ @@ -1167,7 +1176,7 @@ switch ((CNTLR_PHASE) uptr->PHASE) { /* dispatch the phase */ case recalibrate: case seek: if (cvptr->type == ICD) /* is this an ICD controller? */ - dl_end_command (cvptr, drive_attention); /* seek ends with drive attention status */ + dl_end_command (cvptr, drive_attention); /* seeks end with Drive Attention status */ else /* if not an ICD controller, */ uptr->STAT |= DL_S2ATN; /* set Attention in the unit status */ break; @@ -1182,7 +1191,7 @@ switch ((CNTLR_PHASE) uptr->PHASE) { /* dispatch the phase */ case read_without_verify: if (cvptr->sector == 0) /* have we reached the end of the track? */ - uptr->OP = read; /* begin verifying next time */ + uptr->OP = read; /* begin verifying the next time */ end_read (cvptr, uptr); /* end the sector read */ break; @@ -1192,7 +1201,7 @@ switch ((CNTLR_PHASE) uptr->PHASE) { /* dispatch the phase */ cvptr->verify_count = /* decrement the count */ (cvptr->verify_count - 1) & DMASK; /* modulo 65536 */ - if (cvptr->verify_count == 0) /* more sectors to verify? */ + if (cvptr->verify_count == 0) /* are there more sectors to verify? */ cvptr->eod = SET; /* no, so terminate the command cleanly */ end_read (cvptr, uptr); /* end the sector read */ @@ -1209,11 +1218,11 @@ switch ((CNTLR_PHASE) uptr->PHASE) { /* dispatch the phase */ case request_status: case request_sector_address: case request_disc_address: - dl_service_controller (cvptr, uptr); /* call the controller for service */ + dl_service_controller (cvptr, uptr); /* the controller service handles these */ break; - default: /* entered with an invalid state */ + default: /* we were entered with an invalid state */ result = SCPE_IERR; /* return an internal (programming) error */ break; } /* end of operation dispatch */ @@ -1241,9 +1250,10 @@ return result; /* return the result of to indicate that it is ready for the second word. For ICD controllers, the controller unit is not used, and all commands are - scheduled on the drive unit. To reduce code duplication, however, the drive - unit service calls the controller service directly to handle controller - commands. + scheduled on the drive unit. This is possible because ICD controllers always + wait for seeks to complete before executing additional commands. To reduce + code duplication, however, the drive unit service calls the controller + service directly to handle controller commands. The service routine validates phase assignments and returns SCPE_IERR (Internal Error) if entry is made with an illegal operation phase or a phase @@ -1268,13 +1278,13 @@ switch ((CNTLR_PHASE) uptr->PHASE) { /* dispatch the phase */ case end_phase: switch (opcode) { /* dispatch the current operation */ case request_status: - dl_end_command (cvptr, cvptr->status); /* command is complete with no status change */ + dl_end_command (cvptr, cvptr->status); /* the command completes with no status change */ break; case clear: dl_clear_controller (cvptr, uptr, soft_clear); /* clear the controller */ - dl_end_command (cvptr, normal_completion); /* command is complete */ + dl_end_command (cvptr, normal_completion); /* the command is complete */ break; @@ -1284,21 +1294,21 @@ switch ((CNTLR_PHASE) uptr->PHASE) { /* dispatch the phase */ case set_file_mask: case load_tio_register: case request_disc_address: - dl_end_command (cvptr, normal_completion); /* command is complete */ + dl_end_command (cvptr, normal_completion); /* the command is complete */ break; case end: - dl_idle_controller (cvptr); /* command is complete with controller idle */ + dl_idle_controller (cvptr); /* the command completes with the controller idle */ break; case wakeup: - dl_end_command (cvptr, unit_available); /* command is complete with unit available */ + dl_end_command (cvptr, unit_available); /* the command completes with Unit Available status */ break; - default: /* entered with an invalid state */ + default: /* we were entered with an invalid state */ result = SCPE_IERR; /* return an internal (programming) error */ break; } /* end of operation dispatch */ @@ -1331,7 +1341,7 @@ switch ((CNTLR_PHASE) uptr->PHASE) { /* dispatch the phase */ break; - default: /* entered with an invalid state */ + default: /* we were entered with an invalid state */ result = SCPE_IERR; /* return an internal (programming) error */ break; } /* end of operation dispatch */ @@ -1346,7 +1356,7 @@ return result; /* return the result of The command wait timer service routine is called if the command wait timer expires. This indicates that the CPU did not respond to a parameter transfer - or did not issue a new command within the 1.8 second timeout period. The + or did not issue a new command within the ~1.8 second timeout period. The timer is used with the MAC controller to ensure that a hung CPU does not tie up the controller, preventing it from servicing other CPUs or drives. ICD controllers do not use the command wait timer; they will wait forever, as @@ -1368,7 +1378,7 @@ return result; /* return the result of t_stat dl_service_timer (CVPTR cvptr, UNIT *uptr) { -sim_cancel (cvptr->aux); /* cancel the controller */ +sim_cancel (cvptr->aux); /* cancel any controller activation */ dl_idle_controller (cvptr); /* idle the controller */ cvptr->file_mask = 0; /* clear the file mask */ @@ -1393,8 +1403,8 @@ return SCPE_OK; The first two conditions, called "hard clears," are equivalent and cause a firmware restart with the PWRON flag set. The 13175 interface for the HP - 1000 asserts CLEAR in response to the backplane CRS signal if the PRESET - ENABLE jumper is not installed (which is the usual case). The third + 1000 asserts the CLEAR signal in response to the backplane CRS signal if the + PRESET ENABLE jumper is not installed (which is the usual case). The third condition also causes a firmware restart but with the PWRON flag clear. The last condition is executed in the command handler and therefore returns to the Command Wait Loop instead of the Poll Loop. @@ -1406,7 +1416,7 @@ return SCPE_OK; - issue a Controller Preset to clear all connected drives - clear the clock offset - clear the file mask - - enter the Poll Loop (clears the controller status) + - enter the Poll Loop (which clears the controller status) For a timeout clear, the 13037 controller will: @@ -1414,7 +1424,7 @@ return SCPE_OK; - clear the hold bits of any drives held by the interface that timed out - clear the clock offset - clear the file mask - - enter the Poll Loop (clears the controller status) + - enter the Poll Loop (which clears the controller status) For a programmed "soft" clear, the 13037 controller will: @@ -1447,7 +1457,7 @@ return SCPE_OK; Implementation notes: 1. The specific 13365 controller actions on hard or soft clears are not - documented. Therefore, an ICD controller clear is handled as a MAC + documented. Therefore, an ICD controller clear is handled as a MAC controller clear, except that only the current drive is preset (as an ICD controller manages only a single drive). @@ -1459,7 +1469,7 @@ return SCPE_OK; aborted for a hard or timeout clear, whereas in hardware it would complete normally. This is OK, however, because an internal seek always clears the drive's Attention status on completion, so aborting the - simulated seek is equivalent to seek completion. + simulated seek is equivalent to an immediate seek completion. 4. In simulation, a Controller Preset only resets the specified status bits, as the remainder of the hardware actions are not implemented. @@ -1482,7 +1492,7 @@ if (cvptr->type == ICD) /* is this an ICD contro else { /* a MAC controller clears all units */ dptr = find_dev_from_unit (uptr); /* find the associated device */ - if (dptr == NULL) /* device doesn't exist?!? */ + if (dptr == NULL) /* the device doesn't exist?!? */ return SCPE_IERR; /* this is an impossible condition! */ else /* the device was found */ unit_count = dptr->numunits; /* so get the number of units */ @@ -1534,7 +1544,7 @@ return; In simulation, the unit must be attached before the heads may be unloaded or loaded. As the heads should be automatically loaded when a unit is attached and unloaded when a unit is detached, this routine must be called after - attaching or before detaching. + attaching and before detaching. Implementation notes: @@ -1550,7 +1560,7 @@ return; t_stat dl_load_unload (CVPTR cvptr, UNIT *uptr, t_bool load) { -if ((uptr->flags & UNIT_ATT) == 0) /* must be attached to [un]load */ +if ((uptr->flags & UNIT_ATT) == 0) /* the unit must be attached to [un]load */ return SCPE_UNATT; /* return "Unit not attached" if not */ else if (!(sim_switches & SIM_SW_REST)) /* modify the flags only if not restoring */ @@ -1585,11 +1595,11 @@ return SCPE_OK; CNTLR_CLASS dl_classify (CNTLR_VARS cntlr) { -if (cntlr.type <= last_type /* if the controller type is legal, */ +if (cntlr.type <= last_type /* if the controller type is legal */ && cntlr.opcode <= last_opcode /* and the opcode is legal */ && cmd_props [cntlr.opcode].valid [cntlr.type]) /* and is defined for this controller, */ return cmd_props [cntlr.opcode].classification; /* then return the command classification */ -else /* type or opcode is illegal */ +else /* the type or opcode is illegal */ return class_invalid; /* so return an invalid classification */ } @@ -1603,11 +1613,11 @@ else /* type or opcode is ill const char *dl_opcode_name (CNTLR_TYPE controller, CNTLR_OPCODE opcode) { -if (controller <= last_type /* if the controller type is legal, */ +if (controller <= last_type /* if the controller type is legal */ && opcode <= last_opcode /* and the opcode is legal */ && cmd_props [opcode].valid [controller]) /* and is defined for this controller, */ return opcode_name [opcode]; /* then return the opcode name */ -else /* type or opcode is illegal, */ +else /* the type or opcode is illegal, */ return invalid_name; /* so return an error indication */ } @@ -1622,7 +1632,7 @@ const char *dl_phase_name (CNTLR_PHASE phase) { if (phase <= last_phase) /* if the phase is legal, */ return phase_name [phase]; /* return the phase name */ -else /* phase is illegal, */ +else /* the phase is illegal, */ return invalid_name; /* so return an error indication */ } @@ -1636,9 +1646,9 @@ else /* phase is illegal, */ The file specified by the supplied filename is attached to the indicated unit. If the attach was successful, the heads are loaded on the drive. - If the drive is set to auto-type, the size of the image file is compared to - the table of drive capacities to determine which type of drive was used to - create it. If the image file is new, then the previous drive type is + If the drive is set to autosize, the size of the image file is compared to + the table of drive capacities to determine which model of drive was used to + create it. If the image file is new, then the previous drive model is retained. */ @@ -1654,13 +1664,13 @@ if (result != SCPE_OK) /* did the attach fa dl_load_unload (cvptr, uptr, TRUE); /* if the attach succeeded, load the heads */ -if (uptr->flags & UNIT_AUTO) { /* is auto-typing desired? */ +if (uptr->flags & UNIT_AUTO) { /* is autosizing enabled? */ size = sim_fsize (uptr->fileref) / sizeof (uint16); /* get the file size in words */ - if (size > 0) /* a new file retains the current drive type */ - for (id = 0; id < PROPS_COUNT; id++) /* find the best fit to the drive types */ + if (size > 0) /* a new file retains the current drive model */ + for (id = 0; id < PROPS_COUNT; id++) /* find the best fit to the drive models */ if (size <= drive_props [id].words /* if the file size fits the drive capacity */ - || id == PROPS_COUNT - 1) { /* or this is the largest drive */ + || id == PROPS_COUNT - 1) { /* or this is the largest available drive */ uptr->capac = drive_props [id].words; /* then set the capacity */ uptr->flags = (uptr->flags & ~UNIT_MODEL) /* and the model */ | SET_MODEL (id); @@ -1668,7 +1678,7 @@ if (uptr->flags & UNIT_AUTO) { /* is auto-typing de } } -return SCPE_OK; /* unit was successfully attached */ +return SCPE_OK; /* the unit was successfully attached */ } @@ -1694,7 +1704,7 @@ return detach_unit (uptr); /* and detach the unit t_stat dl_set_model (UNIT *uptr, int32 value, char *cptr, void *desc) { -if (uptr->flags & UNIT_ATT) /* cannot alter the disc model */ +if (uptr->flags & UNIT_ATT) /* we cannot alter the disc model */ return SCPE_ALATT; /* if the unit is attached */ if (value != UNIT_AUTO) /* if we are not autosizing */ @@ -1760,12 +1770,12 @@ uint32 count, offset; t_bool verify; const CNTLR_OPCODE opcode = (CNTLR_OPCODE) uptr->OP; -if (cvptr->eod == SET) { /* end of data indicated? */ +if (cvptr->eod == SET) { /* is the end of data indicated? */ dl_end_command (cvptr, normal_completion); /* complete the command */ return SCPE_OK; } -if (opcode == read_full_sector) { /* starting a Read Full Sector command? */ +if (opcode == read_full_sector) { /* are we starting a Read Full Sector command? */ if (cvptr->type == ICD) /* is this an ICD controller? */ cvptr->buffer [0] = 0100377; /* ICD does not support ECC */ else @@ -1773,30 +1783,30 @@ if (opcode == read_full_sector) { /* starting a Read Full set_address (cvptr, 1); /* set the current address into buffer 1-2 */ offset = 3; /* start the data after the header */ - verify = FALSE; /* no address verification */ + verify = FALSE; /* set for no address verification */ } else { /* it's another read command */ offset = 0; /* data starts at the beginning */ - verify = (opcode != read_without_verify); /* verify unless RWV */ + verify = (opcode != read_without_verify); /* set for address verification unless it's a RWV */ } if (! position_sector (cvptr, uptr, verify)) /* position the sector */ - return SCPE_OK; /* seek in progress or an error occurred */ + return SCPE_OK; /* a seek is in progress or an error occurred */ count = sim_fread (cvptr->buffer + offset, /* read the sector from the image */ - sizeof (uint16), DL_WPSEC, /* into the sector buffer */ + sizeof (uint16), DL_WPSEC, /* into the sector buffer */ uptr->fileref); -for (count = count + offset; count < cvptr->length; count++) /* pad sector as needed */ +for (count = count + offset; count < cvptr->length; count++) /* pad the sector as needed */ cvptr->buffer [count] = 0; /* e.g., if reading from a new file */ if (ferror (uptr->fileref)) /* did a host file system error occur? */ - return io_error (cvptr, uptr); /* set up data error status and stop the simulation */ + return io_error (cvptr, uptr); /* set up the data error status and stop the simulation */ next_sector (cvptr, uptr); /* address the next sector */ -uptr->PHASE = data_phase; /* set up data transfer phase */ +uptr->PHASE = data_phase; /* set up the data transfer phase */ cvptr->index = 0; /* reset the data index */ return SCPE_OK; /* the read was successfully started */ @@ -1823,7 +1833,7 @@ return SCPE_OK; /* the read was successf static void end_read (CVPTR cvptr, UNIT *uptr) { -if (cvptr->eod == SET) /* end of data indicated? */ +if (cvptr->eod == SET) /* is the end of data indicated? */ dl_end_command (cvptr, normal_completion); /* complete the command */ else { /* reading continues */ @@ -1839,7 +1849,8 @@ return; The current sector indicated by the controller address is positioned for writing from the sector buffer to the disc image file after data transfer - from the CPU. + from the CPU. If the end of the track had been reached, and the file mask + permits, an auto-seek is scheduled instead to allow the write to continue. On entry, if writing is not permitted, or formatting is required but not enabled, the command is terminated with an error. Otherwise, the disc image @@ -1866,14 +1877,14 @@ return; static void start_write (CVPTR cvptr, UNIT *uptr) { -const t_bool verify = (CNTLR_OPCODE) uptr->OP == write; /* only Write verifies the sector */ +const t_bool verify = (CNTLR_OPCODE) uptr->OP == write; /* only Write verifies the sector address */ -if ((uptr->flags & UNIT_WPROT) /* is the unit write protected? */ +if ((uptr->flags & UNIT_WPROT) /* is the unit write protected, */ || !verify && !(uptr->flags & UNIT_FMT)) /* or is formatting required but not enabled? */ dl_end_command (cvptr, status_2_error); /* terminate the write with an error */ -else if (position_sector (cvptr, uptr, verify)) { /* write OK; position the sector */ - uptr->PHASE = data_phase; /* position OK; set up data transfer phase */ +else if (position_sector (cvptr, uptr, verify)) { /* writing is permitted; position the sector */ + uptr->PHASE = data_phase; /* positioning succeeded; set up data transfer phase */ cvptr->index = 0; /* reset the data index */ } @@ -1884,17 +1895,16 @@ return; /* Finish a write operation on the current sector. The current sector is written from the sector buffer to the disc image file - at the current file position. If the end of the track had been reached, and - the file mask permits, an auto-seek is scheduled instead to allow the write - to continue. + at the current file position. The next sector address is then updated to + allow writing to continue. On entry, the drive is checked to ensure that it is ready for the write. Then the sector buffer is padded appropriately if a full sector of data was not transferred. The buffer is written to the disc image file at the position corresponding to the controller address as set when the sector was started. The write begins at a buffer offset determined by the command (a - Write Full Sector leaves room at the start of the buffer for the sector - header). + Write Full Sector has header words at the start of the buffer that are not + written to the disc image). If the image write failed with a file system error, SCPE_IOERR is returned from the service routine to cause a simulation stop; resumption is handled as @@ -1929,14 +1939,14 @@ if (cvptr->index < DL_WPSEC + offset) { /* was a partial sector pad = cvptr->buffer [cvptr->index - 1]; /* pads with the last word written */ for (count = cvptr->index; count < DL_WPSEC + offset; count++) - cvptr->buffer [count] = pad; /* pad the sector buffer */ + cvptr->buffer [count] = pad; /* pad the sector buffer as needed */ } sim_fwrite (cvptr->buffer + offset, sizeof (uint16), /* write the sector to the file */ DL_WPSEC, uptr->fileref); if (ferror (uptr->fileref)) /* did a host file system error occur? */ - return io_error (cvptr, uptr); /* set up data error status and stop the simulation */ + return io_error (cvptr, uptr); /* set up the data error status and stop the simulation */ next_sector (cvptr, uptr); /* address the next sector */ @@ -1952,16 +1962,16 @@ return SCPE_OK; } -/* Position the disc image file to the current sector. +/* Position the disc image file at the current sector. - The image file is positioned to the byte address corresponding to the + The image file is positioned at the byte address corresponding to the controller's current cylinder, head, and sector address. Positioning may - involve an auto-seek if the prior read or write addressed the final sector in - a cylinder. If a seek is initiated or an error is detected, the routine + involve an auto-seek if a prior read or write addressed the final sector in a + cylinder. If a seek is initiated or an error is detected, the routine returns FALSE to indicate that the positioning was not performed. If the file was positioned, the routine returns TRUE. - On entry, if the controller's end-of-cylinder flag is set, the prior read or + On entry, if the controller's end-of-cylinder flag is set, a prior read or write addressed the final sector in the current cylinder. If the file mask does not permit auto-seeking, the current command is terminated with an End of Cylinder error. Otherwise, the cylinder is incremented or decremented as @@ -1970,8 +1980,8 @@ return SCPE_OK; If the increment or decrement resulted in an out-of-bounds value, the seek will return Seek Check status, and the command is terminated with an error. If the seek is legal, the routine returns with the disc service scheduled for - seek completion and the command state unchanged. When the service is called, - the read or write will continue on the new cylinder. + seek completion and the command state unchanged. When the service is + reentered, the read or write will continue on the new cylinder. If the EOC flag was not set, the drive position is checked against the controller position. If they are different (as may occur with an Address @@ -2003,34 +2013,34 @@ static t_bool position_sector (CVPTR cvptr, UNIT *uptr, t_bool verify) uint32 block; uint32 model = GET_MODEL (uptr->flags); -if (cvptr->eoc == SET) /* positioned at the end of a cylinder? */ +if (cvptr->eoc == SET) /* are we at the end of a cylinder? */ if (cvptr->file_mask & DL_FAUTSK) { /* is an auto-seek allowed? */ - if (cvptr->file_mask & DL_FDECR) /* decremental seek? */ - cvptr->cylinder = (cvptr->cylinder - 1) & DMASK; /* decrease cylinder with wraparound */ - else /* incremental seek */ - cvptr->cylinder = (cvptr->cylinder + 1) & DMASK; /* increase cylinder with wraparound */ + if (cvptr->file_mask & DL_FDECR) /* is a decremental seek requested? */ + cvptr->cylinder = (cvptr->cylinder - 1) & DMASK; /* decrease the cylinder address with wraparound */ + else /* an incremental seek is requested */ + cvptr->cylinder = (cvptr->cylinder + 1) & DMASK; /* increase the cylinder address with wraparound */ start_seek (cvptr, uptr, /* start the auto-seek */ (CNTLR_OPCODE) uptr->OP, /* with the current operation */ - (CNTLR_PHASE) uptr->PHASE); /* and phase unchanged */ + (CNTLR_PHASE) uptr->PHASE); /* and phase unchanged */ if (uptr->STAT & DL_S2SC) /* did a seek check occur? */ - if (cvptr->type == ICD) /* ICD controller? */ - dl_end_command (cvptr, end_of_cylinder); /* report as end of cylinder error */ - else /* MAC controller? */ - dl_end_command (cvptr, status_2_error); /* report as Status-2 error */ + if (cvptr->type == ICD) /* is this ICD controller? */ + dl_end_command (cvptr, end_of_cylinder); /* report it as an End of Cylinder error */ + else /* it is a MAC controller */ + dl_end_command (cvptr, status_2_error); /* report it as a Status-2 error */ } - else /* file mask does not permit auto-seek */ + else /* the file mask does not permit an auto-seek */ dl_end_command (cvptr, end_of_cylinder); /* so terminate with an EOC error */ else if (verify && (uint32) uptr->CYL != cvptr->cylinder) { /* is the positioner on the wrong cylinder? */ start_seek (cvptr, uptr, /* start a seek to the correct cylinder */ (CNTLR_OPCODE) uptr->OP, /* with the current operation */ - (CNTLR_PHASE) uptr->PHASE); /* and phase unchanged */ + (CNTLR_PHASE) uptr->PHASE); /* and phase unchanged */ if (uptr->STAT & DL_S2SC) /* did a seek check occur? */ - dl_end_command (cvptr, status_2_error); /* report as Status-2 error */ + dl_end_command (cvptr, status_2_error); /* report a Status-2 error */ } else if (((uint32) uptr->CYL >= drive_props [model].cylinders) /* is the cylinder out of bounds? */ @@ -2043,10 +2053,10 @@ else if (((uint32) uptr->CYL >= drive_props [model].cylinders) /* is the cylind else if (uptr->flags & UNIT_UNLOAD) /* is the drive ready for positioning? */ dl_end_command (cvptr, access_not_ready); /* terminate the command with an access error */ -else { /* ready to position the image file */ +else { /* we are ready to position the image file */ block = TO_BLOCK (uptr->CYL, cvptr->head, /* calculate the new block position */ cvptr->sector, model); /* (for inspection only) */ - uptr->pos = TO_OFFSET (block); /* and then convert to a byte offset */ + uptr->pos = TO_OFFSET (block); /* and then convert to a byte offset */ sim_fseek (uptr->fileref, uptr->pos, SEEK_SET); /* set the image file position */ @@ -2071,7 +2081,7 @@ return FALSE; /* report that positioni The new cylinder address is not set here, because cylinder validation must only occur when the next sector is actually accessed. Otherwise, reading or writing the last sector on a track or cylinder with auto-seek disabled would - cause an End of Cylinder error even if the transfer ended with that sector. + cause an End of Cylinder error, even if the transfer ended with that sector. Instead, we set the EOC flag to indicate that a cylinder update is pending. As a result of this deferred update method, the state of the EOC flag must be @@ -2084,7 +2094,7 @@ const uint32 model = GET_MODEL (uptr->flags); /* get the disc model */ cvptr->sector = cvptr->sector + 1; /* increment the sector number */ -if (cvptr->sector < drive_props [model].sectors) /* at the end of the track? */ +if (cvptr->sector < drive_props [model].sectors) /* are we at the end of the track? */ return; /* no, so the next sector value is OK */ cvptr->sector = 0; /* wrap the sector number */ @@ -2092,7 +2102,7 @@ cvptr->sector = 0; /* wrap the sector numbe if (cvptr->file_mask & DL_FCYLM) { /* are we in cylinder mode? */ cvptr->head = cvptr->head + 1; /* yes, so increment the head */ - if (cvptr->head < drive_props [model].heads) /* at the end of the cylinder? */ + if (cvptr->head < drive_props [model].heads) /* are we at the end of the cylinder? */ return; /* no, so the next head value is OK */ cvptr->head = 0; /* wrap the head number */ @@ -2132,7 +2142,7 @@ return; /* indicate that an up Implementation notes: 1. EOC is not reset for recalibrate so that a reseek will return to the same - location as was pending when the recalibrate was done. + location as was current when the recalibrate was done. 2. Calculation of the file offset is performed here simply to keep the unit position register available for inspection. The actual file positioning @@ -2150,14 +2160,14 @@ uint32 block, target_cylinder; const uint32 model = GET_MODEL (uptr->flags); /* get the drive model */ if (uptr->flags & UNIT_UNLOAD) { /* are the heads unloaded? */ - dl_end_command (cvptr, status_2_error); /* seek ends with Status-2 error */ - return FALSE; /* drive was not ready */ + dl_end_command (cvptr, status_2_error); /* the seek ends with Status-2 error */ + return FALSE; /* as the drive was not ready */ } if ((CNTLR_OPCODE) uptr->OP == recalibrate) /* is the unit recalibrating? */ - target_cylinder = 0; /* seek to cylinder 0 and don't reset EOC */ + target_cylinder = 0; /* seek to cylinder 0 and don't reset the EOC flag */ -else { /* Seek command or auto-seek request */ +else { /* it's a Seek command or an auto-seek request */ target_cylinder = cvptr->cylinder; /* seek to the controller cylinder */ cvptr->eoc = CLEAR; /* clear the end-of-cylinder flag */ } @@ -2167,12 +2177,12 @@ if (target_cylinder >= drive_props [model].cylinders) { /* is the cylinder out o uptr->STAT = uptr->STAT | DL_S2SC; /* and set Seek Check status */ } -else { /* cylinder value is OK */ +else { /* the cylinder value is OK */ delta = abs (uptr->CYL - target_cylinder); /* calculate the relative movement */ uptr->CYL = target_cylinder; /* and move the positioner */ if ((cvptr->head >= drive_props [model].heads) /* if the head */ - || (cvptr->sector >= drive_props [model].sectors)) /* or sector is out of bounds, */ + || (cvptr->sector >= drive_props [model].sectors)) /* or the sector is out of bounds, */ uptr->STAT = uptr->STAT | DL_S2SC; /* set Seek Check status */ else { /* the head and sector are OK */ @@ -2184,14 +2194,14 @@ else { /* cylinder value is OK } } -if ((uptr->STAT & DL_S2SC) && cvptr->type == ICD) /* Seek Check and ICD controller? */ - dl_end_command (cvptr, status_2_error); /* command ends with Status-2 error */ +if ((uptr->STAT & DL_S2SC) && cvptr->type == ICD) /* did a Seek Check occur for an ICD controller? */ + dl_end_command (cvptr, status_2_error); /* the command ends with a Status-2 error */ -else { /* seek OK or this is a MAC controller */ - if (delta == 0) /* if seek is to the same cylinder */ - delta = 1; /* schedule as a one-cylinder seek */ +else { /* the seek was OK or this is a MAC controller */ + if (delta == 0) /* if the seek is to the same cylinder, */ + delta = 1; /* then schedule as a one-cylinder seek */ - uptr->wait = cvptr->seek_time * delta; /* seek delay is based on the relative movement */ + uptr->wait = cvptr->seek_time * delta; /* the seek delay is based on the relative movement */ } uptr->OP = next_opcode; /* set the next operation */ @@ -2202,7 +2212,7 @@ return TRUE; /* and report that t /* Report an I/O error. - Errors indicated by the host file system are reported to the console and + Errors indicated by the host file system are reported to the console, and simulation is stopped with an "I/O error" message. If the simulation is continued, the CPU will receive an Uncorrectable Data Error indication from the controller. @@ -2228,7 +2238,7 @@ return SCPE_IOERR; /* return an I/O error t The controller's current cylinder, head, and sector are packed into two words and stored in the sector buffer, starting at the index specified. If the end-of-cylinder flag is set, the cylinder is incremented to reflect the - auto-seek that will be attempted when the next disc access is made. + auto-seek that will be attempted when the next sequential access is made. Implementation notes: @@ -2240,7 +2250,7 @@ return SCPE_IOERR; /* return an I/O error t static void set_address (CVPTR cvptr, uint32 index) { -cvptr->buffer [index] = cvptr->cylinder + (cvptr->eoc == SET ? 1 : 0); /* update the cylinder if EOC */ +cvptr->buffer [index] = cvptr->cylinder + (cvptr->eoc == SET ? 1 : 0); /* update the cylinder if EOC is set */ cvptr->buffer [index + 1] = SET_HEAD (cvptr) | SET_SECTOR (cvptr); /* merge the head and sector */ return; } @@ -2253,7 +2263,7 @@ return; interfaces supply an auxiliary timer unit that is activated when the command wait timer is started and cancelled when the timer is stopped. - ICD interfaces do not use the command wait timer. + ICD interfaces do not use the command wait timer or supply an auxiliary unit. Implementation notes: @@ -2265,10 +2275,10 @@ return; static void set_timer (CVPTR cvptr, FLIP_FLOP action) { if (cvptr->type == MAC) /* is this a MAC controller? */ - if (action == SET) /* start the timer? */ + if (action == SET) /* should we start the timer? */ sim_activate_abs (cvptr->aux + timer, /* activate the auxiliary unit */ cvptr->wait_time); - else /* stop the timer */ + else /* we stop the timer */ sim_cancel (cvptr->aux + timer); /* by canceling the unit */ return; } @@ -2292,15 +2302,15 @@ return; Implementation notes: - 1. The Attention, Drive Fault, First Status, and Seek Check flags are stored - in the unit status word. The other status flags are determined + 1. The Attention, Drive Fault, First Status, and Seek Check bits are stored + in the unit status word. The other status bits are determined dynamically. 2. The Drive Busy bit is set if the unit service is scheduled. In hardware, this bit indicates that the heads are not positioned over a track, i.e., that a seek is in progress. In simulation, the only time a Request Status command is allowed is either when the controller is waiting for - seek completion or for another command. In the latter case, unit service + seek completion or for a new command. In the latter case, unit service will not be scheduled, so activation can only be for seek completion. */ @@ -2312,7 +2322,7 @@ uint32 model; if (uptr == NULL) /* if the unit is invalid */ return DL_S2ERR | DL_S2NR; /* then it does not respond */ -model = GET_MODEL (uptr->flags); /* get the drive type */ +model = GET_MODEL (uptr->flags); /* get the drive model */ status = drive_props [model].type | uptr->STAT; /* start with the drive type and unit status */ if (uptr->flags & UNIT_WPROT) /* is the write protect switch set? */ diff --git a/HP2100/hp_disclib.h b/HP2100/hp_disclib.h index 52c4a161..315fc6ec 100644 --- a/HP2100/hp_disclib.h +++ b/HP2100/hp_disclib.h @@ -24,7 +24,7 @@ used in advertising or otherwise to promote the sale, use or other dealings in this Software without prior written authorization from the authors. - 19-Mar-12 JDB First release + 30-Mar-12 JDB First release 09-Nov-11 JDB Created disc controller common library from DS simulator @@ -66,7 +66,7 @@ #define CYL u3 /* current drive cylinder */ #define STAT u4 /* current drive status (Status 2) */ #define OP u5 /* current drive operation in process */ -#define PHASE u6 /* current command phase */ +#define PHASE u6 /* current drive operation phase */ /* Unit flags and accessors */ @@ -78,7 +78,7 @@ #define UNIT_V_AUTO (UNIT_V_UF + 5) /* bits 5-5: autosize */ #define DL_V_UF (UNIT_V_UF + 6) /* first free unit flag bit */ -#define UNIT_M_MODEL 3 /* model ID mask */ +#define UNIT_M_MODEL 03 /* model ID mask */ #define UNIT_MODEL (UNIT_M_MODEL << UNIT_V_MODEL) #define UNIT_WLK (1 << UNIT_V_WLK) @@ -96,9 +96,9 @@ #define DL_V_S1SPD 13 /* bits 15-13: S/P/D flags */ #define DL_V_S1STAT 8 /* bits 12- 8: controller status */ -#define DL_V_S1UNIT 0 /* bits 7- 0: last unit number */ +#define DL_V_S1UNIT 0 /* bits 3- 0: last unit number */ -#define DL_M_S1UNIT 15 /* unit mask */ +#define DL_M_S1UNIT 017 /* unit number mask */ #define GET_S1UNIT(v) (((v) >> DL_V_S1UNIT) & DL_M_S1UNIT) @@ -107,7 +107,7 @@ #define SET_S1UNIT(v) ((v) << DL_V_S1UNIT) -/* Status-2 accessors (+ = kept in unit status, - = determined dynamically */ +/* Status-2 accessors (+ = kept in unit status, - = determined dynamically) */ #define DL_V_S2ERR 15 /* bits 15-15: (-) any error flag */ #define DL_V_S2DTYP 9 /* bits 12- 9: (-) drive type */ @@ -116,7 +116,7 @@ #define DL_V_S2FMT 5 /* bits 5- 5: (-) format enabled flag */ #define DL_V_S2FAULT 4 /* bits 4- 4: (+) drive fault flag */ #define DL_V_S2FS 3 /* bits 3- 3: (+) first status flag */ -#define DL_V_S2SC 2 /* bits 2- 2: (+) seek error flag */ +#define DL_V_S2SC 2 /* bits 2- 2: (+) seek check flag */ #define DL_V_S2NR 1 /* bits 1- 1: (-) not ready flag */ #define DL_V_S2BUSY 0 /* bits 0- 1: (-) drive busy flag */ @@ -195,8 +195,9 @@ typedef enum { MAC = 0, - ICD, last_type = ICD, /* last valid type */ - TYPE_COUNT /* count of controller types */ + ICD, + last_type = ICD, /* last valid type */ + type_count /* count of controller types */ } CNTLR_TYPE; @@ -224,7 +225,8 @@ typedef enum { load_tio_register = 023, request_disc_address = 024, end = 025, - wakeup = 026, last_opcode = wakeup /* last valid opcode */ + wakeup = 026, + last_opcode = wakeup /* last valid opcode */ } CNTLR_OPCODE; #define DL_OPCODE_MASK 037 @@ -235,7 +237,8 @@ typedef enum { typedef enum { start_phase = 0, data_phase, - end_phase, last_phase = end_phase /* last valid phase */ + end_phase, + last_phase = end_phase /* last valid phase */ } CNTLR_PHASE; @@ -324,22 +327,22 @@ typedef struct { uint32 verify_count; /* count of sectors to verify */ uint32 poll_unit; /* last unit polled for attention */ uint16 *buffer; /* data buffer pointer */ - uint32 index; /* data buffer index */ - uint32 length; /* data buffer length */ - UNIT *aux; /* auxiliary units (controller and timer) */ - int32 seek_time; /* seek delay time (per cylinder) */ + uint32 index; /* data buffer current index */ + uint32 length; /* data buffer valid length */ + UNIT *aux; /* MAC auxiliary units (controller and timer) */ + int32 seek_time; /* per-cylinder seek delay time */ int32 sector_time; /* intersector delay time */ - int32 cmd_time; /* command start delay time */ - int32 data_time; /* data transfer delay time */ - int32 wait_time; /* command wait timeout */ + int32 cmd_time; /* command response time */ + int32 data_time; /* data transfer response time */ + int32 wait_time; /* command wait time */ } CNTLR_VARS; typedef CNTLR_VARS *CVPTR; /* pointer to controller state variables */ -/* Controller state variables initialiation. +/* Controller state variables initialization. - Parameters are: + The parameters are: ctype - type of the controller (CNTLR_TYPE) bufptr - pointer to the data buffer diff --git a/doc/hp2100_doc.doc b/doc/hp2100_doc.doc index 987acf03..5a1ee522 100644 Binary files a/doc/hp2100_doc.doc and b/doc/hp2100_doc.doc differ