start_seek - cold load read 0/h/s -> set CH - recal (not set) -> set C - seek c/h/s -> set CH - position_sector (at EOC for next cyl -> set C, maybe H and at reseek for cyl miscompare -> set CH) HP 13037/13365 MAC/ICD Disc Controllers ======================================= The SIMH DS module simulates the 13037 MAC disc controller and the 13175 disc interface for the HP 1000. Future plans for SIMH include simulations of the 13365 ICD disc controller and the 12821 disc interface for the 1000, and the 13037 controller and the 30229 disc interface for the 3000. As all three of these sets of hardware use essentially the same command set, it would be advantageous if the commonality of the software could be leveraged. The goal is to create a disc library that could be called by all three modules to handle most of the simulation code for the discs. The individual modules would handle the interface simulations while calling disc library routines to execute the controller commands. This would require abstracting the controller code to segregate interface functions from controller functions. It would also require parameterizing the functions to replace global variables. The initial implementation of the disc library would be for the 13365 ICD controller. This controller is a subset of the MAC controller. All commands except Wakeup and Request Syndrome are implemented. One major difference is that each ICD controller is self-contained. That is, there is one set of controller state variables per unit, rather than one set shared among all units as in the MAC. For example, each ICD unit has its own file mask. Also, because each ICD controller is dedicated, the controller timeout is eliminated, and the End command serves only to disable PPR. Implementing this would require that: - Controller and unit state are accessed via parameters rather than globally. - CPU interface functions (e.g., set flag) are performed by the callers. - Command busy is performed by the callers. - Calls to the controller or timeout units are performed by the callers (or are passed as parameters, with NULL if no scheduling needed, e.g., ICD). For ICD, if the controller is busy, the DA simulator must set NRFD as part of the listen process to hold off the next command. For example, if a Seek is followed immediately by a Write, the accompanying data cannot be transferred until the seek completes. The controller must also be able to handle a command, such as Request Status, after a seek is started but before it finishes. Main issue is to separate interface-specific code from generic disc code. - move parameter read/writes from unit service to controller service (ICD parameters are handled by 12821A interface); unit service should have only disc action calls - move read/write data transfer actions out of unit service (as they are interface-specific) and into a unit service wrapper that calls the common service routine; wrapper is called by sim_activate() and in turn calls common service for all commands except data xfer (e.g., wrapper processes DSC_READ | DSC_2ND but not DSC_1ST or DSC_3RD) - move "set flag" calls out of common and into interface-specific code; could return STDFL, STINT, DVEND, etc. codes to caller and have caller act - ICD sends disc data as bytes, whereas MAC sends data as words. SIMH writes MAC disc data as little-endian 16-bit words. ICD must do the same. - If a command is issued that requires the selected drive to be idle, but that drive is still busy executing a prior command, the MAC controller leaves the command pending on the interface. When the prior command completes, the pending command is executed. For example, a Seek is issued and then a Read is issued without waiting for drive attention from the seek. The Read remains on the interface until the Seek completes; during this time, the controller is looping internally, waiting for Access Not Ready to deny or the 1.4 second timeout to expire. The 9134A Amigo drive will handshake the next primary but then leave the next secondary on the bus until the previous command completes. The ICD manual does not specify what happens if a command is issued while a previous command is still executing. Every ICD disc command other than Request Status requires the drive to be idle, so it may be reasonable to wait (by asserting NRFD) after any disc command if the unit is busy. When a command completes, if the interface status is opcode_wait (or parameter_wait), the interface can deny NRFD and continue to process the incoming command. Note that this does not affect interface commands, such as DSJ, which may execute while a seek is in progress. NRFD must be set after recognizing the disc command opcode. It cannot be set after receiving the entire command and parameters. [or can it? data buffer isn't used except for parameters and read/write, but cannot send a new command with a read/write still in operation -- the untalk/unlisten terminates! so maybe can set NRFD after command fully read in? but what if wrong number of params or bad opcode? gets correct status when it resumes?] - Data pacing occurs naturally on reads, as di_bus_source() isn't called until unit service. For writes, the card will send Write and then Receive Data in succession, and the disc must be ready to accept. This means writing the data into a sector buffer and then asserting NRFD while waiting (because of the intersector delay, as well as a potential auto-seek) for the next unit service. - An IFC or untalk must terminate any transfer of data from the disc to the interface (e.g., a Read), and an IFC or unlisten must terminate any transfer from the interface to the disc (e.g., a Write). - A Read (or Write) followed by something other than a Send Data (or Receive Data), or a Send or Receive Data not preceded by a Read or Write, must generate an I/O Program Error. - ICD controllers do not time out. - Parameters for invalid secondaries or opcodes must be handled by sinking or sourcing dummy bytes. Invalid opcodes must return status 01 and not 12 (I/O program error, due to wrong number of parameters). Interface Flag Bus ------------------ The interface flag bus delivers status from the CPU interface to the controller, as follows: Code 1000 3000 Description ----- ---- ---- ---------------- * CLEAR Y Y Hard Clear CMRDY Y Y Command Ready DTRDY Y Y Data Ready EOD Y Y End of Data OVRUN Y Y Read Overrun XFRNG - Y Transfer No Good INTOK Y Y Interrupt OK * Actually, CLEAR is a separate signal line, not considered as part of the flag bus. Note that the 1000 interface does not assert XFRNG. Interface Function Bus ---------------------- The IFN bus issues commands from the controller to the CPU interface. The 1000 and 3000 interfaces respond to different function sets, as follows: Bus Code 1000 3000 Description --- ----- ---- ---- -------------------- 00 STINT Y Y Interrupt Request 01 STDFL Y - Information Request 02 IFPRF Y - Pre-Fetch Command 03 SELIF Y Y Select Interface 04 SRTRY - Y Set Retry Counter 05 DVEND Y Y Device End 06 - - - (unused) 07 RQSRV - Y Request Service 10 - - - (unused) 11 DSCIF Y Y Disconnect Interface 12 WRTIO - Y Write TIO Register 13 IFOUT Y Y Data Out to Disc 14 IFIN Y Y Data In from Disc 15 IFGTC Y Y Get Command 16 BUSY Y - Set/Clear Busy Flag 17 - - (unused) The CPU interface implements IFPRF by gating the command word onto the data bus in response to ENID (Enable Interface Drivers); IFPRF is not decoded explicitly. Commands are issued sequentially, but a given operation may generate multiple commands. For example, a normal Read termination generates STDFL, WRTIO, BUSY, and RQSRV. Note that the 1000 interface ORs STINT, STDFL, and DVEND to set the CPU flag. MAC Controller States --------------------- The controller has three states: idle, waiting, or busy. The idle and waiting states are implied by the execution of the Poll and Command loops, respectively. The busy state is implied by execution of all code outside of the two loops. The "controller busy" flag indicates when the controller has accepted a command, the requested drive (if any) is available, and command execution is underway. The busy bit is cleared when the command is complete and control has returned to the Poll or Command loops. In hardware, the controller sends a BUSY function to the interface to clock bit 0 of the data bus into the interface's busy flip-flop. A testable flag is needed so that the interface may determine if it is safe to send a command to the controller without interfering with an in-progress DCPC transfer. It is also needed to differentiate between a normal and an error interrupt. For example, after receiving a Seek command, the controller sets the interface flag to request the cylinder address word. The controller also sets the interface flag if the command is illegal. However, the busy bit is set in the former case and not in the latter. In simulation, the controller is run only when there is something to do, rather than continuously. Therefore, the controller state is maintained in a variable. >>> THIS PART IS WRONG: The busy bit is maintained in a separate variable because the controller can be busy, i.e., outside of the equivalent of the Poll and Command loops, but not yet processing a command. For example, the firmware waits in a separate loop for the CPU to send the seek address words. The busy bit isn't set until both words have been received. In simulation, we must record that the controller is busy, i.e., not in the Poll or Command loops, but the busy bit as seen by the interface must not be set. ACTUALLY, IT'S THE OTHER WAY AROUND! THE BUSY BIT IS SET AS SOON AS THE SEEK COMMAND IS RECEIVED, BUT THE CONTROLLER DOESN'T EXECUTE THE COMMAND (AND SO SET CNTLR_BUSY) UNTIL THE PARAMETERS ARE RECEIVED. SO BUSY = 1 AND STATE = WAIT WHILE THE PARAMETERS ARE COMING IN. 13175 Interface FIFO and SRQ ---------------------------- The 1000 interface to the controller has a 16-word FIFO, and SRQ generation is decoupled from the Flag and Flag Buffer flip-flops. This allows DCPC transfers to use the full bandwidth of the I/O backplane. When reading from the disc, the SRQ logic attempts to keep the FIFO empty. That is, SRQ is generated at every I/O cycle as long as words remain in the FIFO. When writing, the SRQ logic attempts to keep the FIFO partly full. Specifically, SRQ is generated whenever there are fewer than five words in the FIFO. Although the FIFO can hold 16 words, SRQ generation is limited to avoid a long lockout of the other DCPC channel during the initial FIFO fill. If the CPU or controller attempts to write a word to a full FIFO or read a word from an empty FIFO, the Overrun flip-flop on the interface is set. In addition, the controller independently monitors the DTRDY line during a write. If a word is input with DTRDY and EOD both inactive, an internal write underrun is indicated. For the 1000 interface, this duplicates the check for an empty FIFO read. Diagnostics ----------- The ICD offline diagnostic ("DIAG") is hosted on an RTE-IVE system. The bootable tape image is 91711-13504. The DIAG relocatable is 91711-12032. The source files are 91711-18374 and 91711-18361 though -18368. Operator design is provided by "DISCZ" on the same tape. The relocatable is 91711-16283, and the source is 91711-18283. DIAG is documented in Chapter 5 of the "HP 1000 ICD/MAC Disc Diagnostic Reference Manual" (5955-4355, June 1984), and DISCZ is documented in Chapter 7. ICD Controller Hardware ----------------------- Reference: - 7925 Disc Drive Service Manual (07925-90903 March 1982) The controller in the ICD drives is designated as HP 13365. It consists of two PCAs: the 13365-60101 Data PCA that installs in the otherwise empty slot A1 in the drive, and the 13365-60202 Microprocessor PCA that replaces the 07906-60001 I/O Sector PCA in slot A2. Page A-6 of the service manual says that "all data transferred during a read or write operation flows through the PHI integrated circuit and a 16-byte FIFO buffer memory. Therefore, the maximum number of bytes of data that the controller can buffer is 24." It continues, "During a READ or WRITE, a hardware DMA configuration handshakes data between the FIFO and the PHI chip. The microprocessor is used only to switch the data path between the actual data and the CRC bytes." The controller mnemonics table on page A-7 says that the ALU clock has a 276-nanosecond period, which is approximately 3.6 MHz. Other mnemonics indicate that data transfers are possible between the FIFO and ALU, and the PHI and ALU. An overrun indication occurs if the FIFO is empty during a write or full during a read. Page A-9 describes the Microprocessor PCA as containing an eight-bit processor composed of two 2901 ALUs and 3072 words of 24-bit microcode. Page A-10 describes the Data PCA as containing the PHI chip, and two 9403 16 word x 4 bit FIFOs that are used as serial (disc side) to parallel (PHI side) converters, and and a 9401 CRC generator/checker. The identities of the chips used appears in the Self-Test Function Test Description table on pages A-42 and A-43. Page A-49 of the service manual has a functional diagram of the two PCAs. From the diagram, it appears that the 16-byte FIFO can be parallel loaded or unloaded from the ALU. Presumably this capability is used for the Read/Write Loopback commands. All parallel data paths within the controller are eight bits wide, and the drive tag bus is manipulated directly to control seeking, reading, and writing. ICD Controller Seek Completion ------------------------------ The 13365 manual is not clear on whether or not the controller waits for seek completion before processing the next command, and whether PPR is asserted when the command is initiated or when the seek completes. The 13037 controller is shared among multiple drives, so it idles after a seek is started and will process commands that do not access the busy drive. For example, a Request Status directed to the busy drive is allowed while a seek is in progress (to ensure that the seek was accepted), but a Read command will be left pending on the CPU interface until the seek completes. If the seek completes without a command pending, then the controller interrupts the CPU with Drive Attention status. Otherwise, the pending command is started, and the drive attention is never reported. The 13365 controller is dedicated to a single drive. Therefore, the controller might remain "busy" until the seek completes without affecting other controllers connected to other drives. Or it might mimic the 13037 controller by allowing commands that do not access the busy drive (e.g., DSJ, Request Status) and waiting for seek completion for commands that do (e.g., Read). The illustrations on pages 19 and 21 of the 13365 manual show that PPE occurs concurrently with the Unlistens that terminate the command sequences. The the Recalibrate and Seek descriptions say: The disc drive performs a low-speed absolute seek to cylinder 0. The controller sets drive attention status and enters Idle State 1 (asserts Parallel Poll Response) at command completion. ...and: The heads are moved to the specified cylinder. At command completion the controller sets disc drive attention status and enters Idle State 1 with the Rotational Position Sensing (RPS) feature enabled or disabled. What is not clear is whether "command completion" occurs when the Unlisten is received (per the illustrations) or when the seek completes (per the descriptions). Drive attention implies seek completion, and the "7925D Disc Drive Service Manual" (07925-90913, April 1984) states, on page A-24, that PPR occurs when the seek completes and not concurrently with the Unlisten: When jumper W360 is in place on microprocessor PCA-A2, a sector look-ahead algorithm called Rotational Position Sensing (RPS) is in effect. [...] Then, after a SEEK has been completed, the response of the drive to a PARALLEL POLL command on the HP-IB is enabled only during a period of time (n + 1) milliseconds long on each revolution of the disc, when n is the unit number. This parallel poll response window closes two sectors before the target sector. If the host CPU does not give the parallel poll within this window, it must wait until the next revolution. If RPS is not enabled, the disc drive will respond to parallel poll immediately upon completing the SEEK, even though the heads might not be anywhere near the target sector. This could tie up the HP-IB for nearly 16 milliseconds waiting for a data transfer to begin. As commands cannot be processed unless the controller is in one of the (three) idle states, and if the controller enters Idle State 1 only after asserting drive attention and PPR, then the implication is that all commands are held off while the heads are moving. This is supported by the action of the ICD disc diagnostic, which checks for Drive Attention status after issuing a Seek. In particular, step 4 does: C SEEK to CY1, HD1, sector 0. C Check for DRIVE ATTENTION status. C CALL QSEEK(LU,ADR,CY1,HD1,0,STAT(1),STAT(2),ER) CALL DECST(STAT,ID) CALL ESTEP(ER .NE. 0 .OR. ID(2) .NE. 37B) The DECST routine decodes the two status words into five separate status bytes. ESTEP reports an error for the current step if the parameter is true). The code for QSEEK results in this call chain: - XSEEK - XDSJ - ZDSJ - DVA32 to issue DSJ - ZCTRL - DVA32 to issue Seek - XDSJ - ZDSJ - DVA32 to issue DSJ - XSTAT - XDSJ - ZDSJ - DVA32 to issue DSJ - ZSENS - DVA32 to issue Request Status - XDSJ - ZDSJ - DVA32 to issue DSJ Note that there are no parallel polls, so the diagnostic is relying on the controller holding off the Request Status (or the second DSJ) until the Seek completes in order to obtain the correct status. Additional corroboration for this behavior is present in the design of the RTE-A DD*30 and DDM30 drivers for the ICD and MAC HP-IB drives. When processing an RTE read (or write) request, DDM30 (92077-18666) issues a parallel poll after a Seek and exits the driver until PPR is asserted at the end of the seek. Then it issues a Request Status and the Read (or Write) command. By contrast, DD*30 (92077-18669) issues a Seek, a DSJ, and a Read/Write command with no intervening waits. This is similar to DVA32, which depends on interrupts from the card when the commands are accepted by the device to provide the wait for seek completion. Finally, the PHI chip description in the 264x terminal HP-IB interface card manual (13255-91128, page 28) says that the PHI (a) has an eight-byte inbound FIFO, (b) only enters secondary and data bytes into the FIFO, and then only if the device is addressed, and (c) will "hold off the HP-IB handshake" when the FIFO is full until a byte is read by the host. As there is no special handling of the DSJ by the PHI chip, it would appear that the ICD controller simply waits in a busy loop until the seek completes and then asserts PPR before looking for the next Amigo command. DDM30 would wait for the PPR and then return to the device driver to send the Request Status and Read commands. DD*30 would send the DSJ immediately after the Seek was accepted, but the secondary would remain in the PHI until the controller had seen the seek completion, and the HP-IB interface card would wait for the DSJ data byte until the controller serviced the PHI and processed the DSJ command. Therefore, the simulation initiates Recalibrate and Seek commands but does not assert PPR until the seeks complete. While the seeks are in progress, all commands are held off by asserting NRFD after the last parameter of the next command is received; this prevents the DI from sending the Unlisten that completes the command sequence. When the seek completes, Drive Attention status is set. If a command is pending, NRFD is denied, and the pending command is processed. The Unit 10 Hold ---------------- The MAC controller firmware allows access to unit numbers 8-10 without causing a Unit Unavailable error. Instead, the controller reports these legal-but-invalid units as permanently offline. Unit number 10 is used by the RTE disc driver (DVR32) to implement a "CPU lock" feature to arbitrate multiple-CPU access to the controller. This feature is intended to hold the controller across multiple disc commands, as might be used when doing a read/modify/write sequence on a sector. In hardware, when a program requests a lock, the driver issues a Recalibrate to unit 10 with the hold bit set. The controller firmware first checks if another CPU interface is holding unit number 10. If it is, the command is left pending on the CPU interface until the other CPU clears the hold bit on unit number 10. If it is not, then the hold bit is set for this CPU. As the unit number is not in the range 0-7, no drive is connected for the subsequent ready check. This results in the command failing with a Status-2 error (not ready), which interrupts the CPU. When the driver sees the interrupt from the controller for unit number 10, it allows the program to continue. If unit number 10 is held by another CPU, the interrupt does not occur, and the program is suspended. When unit number 10 is eventually released, the interrupt occurs, and the suspended program is rescheduled. (The actual mechanism involves global resource numbers. The program allocates and locks the RN and then calls the driver to request a controller lock. When the driver returns, the program attempts a second lock. When the driver receives the interrupt detailed above, it clears the lock on the RN. So if unit number 10 was free, the clear will remove the first lock, allowing the second to succeed. If unit number 10 was not free, the second lock will suspend the program. When unit number 10 is freed and the interrupt occurs, the lock will be removed, rescheduling the program.) In simulation, only a single CPU is ever connected to the controller, so accessing unit number 10 always succeeds and returns Status-2 (not ready). ICD Controller End of Track Handling ------------------------------------ The Amigo disc protocol implemented in the MAC and ICD controllers does not specify the length of a read transfer. Instead, a read transfer continues to transfer data until the controller receives an end-of-data (EOD) indication from the CPU. Typically, the CPU will set up a DMA transfer of a specified length, and EOD will be indicated when that length is reached. The HP 13037 MAC controller has a dedicated status line for EOD. In the HP 13175 MAC disc interface, DMA completion asserts the EDT I/O backplane signal, and the interface asserts EOD to the controller in response. The controller firmware tests EOD approximately 10 microseconds after the final ECC word has been read from the sector postamble, or about 25 microseconds after the final data word has been sent to the CPU. As EOD is asserted by hardware, the controller will always terminate cleanly at the end of an exact sector transfer. The HP-IB interface used by the ICD controller has no provision for passing separate hardware status between devices. Therefore, the CPU indicates an end-of-data condition by untalking the controller. In the absence of an Untalk at the end of a sector, the controller continues to read data from the next sector. Therefore, the timing of the Untalk is critical in determining whether or not to continue the transfer. The HP 12821 ICD disc interface hardware could have been designed to transmit an Untalk in response to the DMA EDT backplane signal, giving a predictable response time. Unfortunately, it was not. Instead, the DMA completion interrupt that is coincident with the EDT backplane signal causes the CPU to run the OS software driver to reconfigure the interface from receiving to transmitting and to send an Untalk. Although the 1000 CPU provides a vectored interrupt system, the operating systems that support the ICD drives (RTE-IVB and RTE-6/VM) do not use it. Instead, all interrupts are vectored to a central interrupt handler than determines, via a software table lookup, which driver is to handle the request. In addition, the memory mapping hardware must be set up so that the driver has access to the I/O buffer being used. All of this takes time. With the final OS versions, the CPU executes 152 instructions on RTE-IVB and 92 instructions on RTE-6/VM (which uses firmware to improve interrupt response time) from DMA completion to HP-IB Untalk, assuming that the I/O buffer is in the user memory map and must be mapped into the system address space. The 1000 M-Series CPU with standard-performance memory is the slowest hardware configuration; the completion-to-Untalk time is about 550 microseconds. This represents a minimum time that will increase if the CPU is busy handling another interrupt when DMA completes. This presents a problem when the end of a track is reached. The controller must not attempt to seek to the next track unless the CPU continues the read with the next sector. This is to prevent errors if the CPU terminates the read after accepting the last byte of the last sector of the track. If the controller tries to address the next track without determining if the CPU had completed the transfer, it would return an End of Cylinder error if the file mask does not allow auto-seeking, or an End of Cylinder (ICD) or Status-2/Seek Check error (MAC) if auto-seeking is allowed but the CPU had just read the last sector on the drive. These errors are proper if the read continued but must not occur if the read terminated with the end of the last sector on the track. Another, less-significant problem occurs for sequential reads. If the CPU ends a read on a sector boundary but untalks the controller too late, the controller will have started transferring the next sector. Because the DMA transfer has been completed, the data will be held in the disc interface FIFO until it fills, and then NRFD will assert. The CPU will hold NRFD asserted while it clears the FIFO and transmits the Untalk. By then, however, the controller will have incremented its internal sector address. If the CPU now issues another read without an intervening seek, the controller will return the contents of the sector beyond the one the CPU is expecting. These problems do not occur with the MAC interface because EOD is asserted by hardware in a predictable time. They do occur with the ICD interface because the timing of the Untalk is dependent on OS software execution. They also occur for the same reason when the MAC controller is used with an HP 12745 HP-IB interface to connect to HP 3000 or 64000 systems. This is mentioned in the notes for section 3-24, "High-Speed Read," of the "12745A Disc Controller (13037) to HP-IB Adapter Kit Installation and Service Manual" (12745-90901, December 1981): "Because the subsystem must assume that the transfer is continuing until it has been notified otherwise by the unaddress command, the length of time needed to unaddress the subsystem becomes important. If too much time is taken, the internal logical address used by the controller will be incremented unnecessarily. This might result in status 1 errors. If the length of time to unaddress cannot be shortened, the REQUEST DISC ADDRESS operation may be used to determine if these errors are included in the data buffer previously read." However, neither the RTE driver for the ICD drives nor the system utilities that directly access these drives make use of the Request Disc Address command to recover from an End of Cylinder error. More significantly, the OS bootstrap extension for ICD drives sets the file mask to surface mode with no auto-seek, does full-track reads, and yet does not handle End of Cylinder errors specially (disc errors simply cause retries). These actions suggest that the ICD controller gives the CPU sufficient time to send an Untalk to avoid EOC errors. The boot extension code does not rely on interrupts to determine DMA completion. Instead, the CPU executes a loop that tests the DMA channel completion flag and the ICD disc interface error flag. The maximum execution path from DMA completion to NRFD assertion is 10 instructions and to Untalk transmission is 19 instructions. Elapsed time on an M-Series is about 85 microseconds from the final data byte to the Untalk. Therefore, positive indication of read termination will not occur until after the next sector had passed (the time from the last CRC byte to the first byte of the next sector's preamble is about 40 microseconds). There are no firmware listings or design documents available for the ICD controller. The controller manual, "13365 Integrated Controller Programming Guide" (13365-90901, February 1980), does not mention the problem in the Read command description. So it is impossible to determine precisely how the ICD controller handles this situation. Clearly, the controller cannot delay checking for Untalk between sectors, or read performance would be poor (a delay of more than the 40 microsecond intersector time would require a full disc revolution before each sector transfer). However, the controller might delay between tracks to avoid End of Cylinder errors. This delay would be needed only when an auto-seek is required but not permitted (a permitted auto-seek may be unnecessary if the CPU terminates the read at the end of the track, but it will not cause an error). This would allow permitted multiple-track transfers to continue at full speed, while imposing a time penalty only on transfers that will end in End of Cylinder errors if they are continued. And if the controller monitored the bus for an Untalk during the delay, there would be no penalty if the CPU properly terminated the read at the end of the track. There is no definite upper limit on the interrupt response time and therefore on the delay from the last byte to the Untalk transmission. A worst-case situation would be when the DMA completion interrupt occurred immediately after a device had interrupted, and the user instruction to be executed upon completion of the device interrupt handler was a system EXEC call (which intentionally violates memory protection, causing an interrupt of a higher priority than that of DMA completion). In this case, the delay in transmitting an Untalk might range into the 1-2 millisecond area. However, the OS driver will retry End of Cylinder errors up to ten times, and it is likely that one of these would complete within the expected time. None of these problems pertain to writes, because writes are positively terminated by asserting EOI with the final data byte. The ICD interface uses the EDT signal that indicates DMA completion to tag the final byte as it is loaded into the FIFO. When that byte is unloaded and transmitted over the bus, EOI is asserted concurrently to terminate the write. RTE Disc Utility Library ------------------------ The RTE disc utility library ($DSCLB) contains these subroutines: XPRTY (ICMD) 92067-1X518 Add odd parity bit IFDVR (LU) 92067-1X542 Return 0 if DVR32, -1 if DVA32 XIDEN (LU,DVID,IDENT,IER) 92067-1X520 Amigo Identify XSTAT (LU,IDVID,IS1,IS2,IER) 92067-1X521 Request Status XSEEK (LU,IDVID,ICYL,IHD,ISEC,IS1,IS2,IER) 92067-1X522 Seek XLGAD (LU,IDVID,ICYL,IHD,ISEC,IER) 92067-1X523 Request Disc Address XINIT (LU,IDVID,IBUF,LEN,ISPD,IS1,IS2,IER) 92067-1X524 Initialize XDRED (LU,IDVID,IBUF,LEN,IS1,IS2,IER) 92067-1X525 Read XDWRT (LU,IDVID,IBUF,LEN,IS1,IS2,IER) 92067-1X526 Write XFMSK (LU,IDVID,MSK,IER) 92067-1X527 Set File Mask XRCAL (LU,IDVID,IER) 92067-1X528 Recalibrate XADRC (LU,IDVID,ICYL,IHD,ISEC,IER) 92067-1X529 Address Record XVRFY (LU,IDVID,ISC,IS1,IS2,IER) 92067-1X530 Verify XRDFS (LU,IDVID,IBUF,LEN,IS1,IS2,IER) 92067-1X531 Read Full Sector XWRFS (LU,IDVID,IBUF,LEN,IS1,IS2,IER) 92067-1X532 Write Full Sector XRDOF (LU,IDVID,IBUF,LEN,IOFSET,IS1,IS2,IER) 92067-1X533 Read with Offset XRDNV (LU,IDVID,IBUF,LEN,IS1,IS2,IER) 92067-1X534 Read without Verify XPHAD (LU,IDVID,ICYL,IHD,ISEC,IER) 92067-1X535 Request Physical Address (9895A) XFRMT (LU,IDVID,IDATA,ITYPE,ISTAG,IER) 92067-1X536 Format (9895A) XSPAR (LU,LASTRK,IER) 92067-1X537 Return first avail spare track XGTAD (LU,IDVID,LTRK,LSEC,ICYL,IHD,ISEC) 92067-1X538 Get track map entry XEND (LU,IDVID) 92067-1X539 End XTTBL (LU,DP) 92067-1X540 Get disc parameters XDSJ (LU,IDVID,KDSJ) 92067-1X541 DSJ XSECA (LU,IDVID,ISEC,IER) 92067-1X552 Request Sector Address There are no library routines for the Cold Load Read (00), Clear (12), Load TIO Register (23), or Wakeup (26) command codes. NOTE: The XLGAD (request logical disc address) and XPHAD (request physical disc address) routines are identical, except that the latter works only with DVA32 and passes the unit number in the byte following the opcode ("not used" according to the ICD controller manual). All bus commands (i.e., with ATN asserted) have odd parity set by the XPRTY routine. Parameters are: ICMD = Bus command word LU = Any LU that points at a DVA32 device DVID = Device ID (bus address 0-7) of target disc unit IDVID = Unit number in upper byte, bus address in lower byte IDENT = Amigo ID return IER = DSJ return after disc command IS1 = Status-1 return IS2 = Status-2 return ICYL = Cylinder IHD = Head ISEC = Sector IBUF = Data buffer LEN = Data buffer length ISPD = S/P/D bits in bits 2-0 MSK = File Mask IOFSET = Offset DP = Disc parameter array (8 words) KDSJ = Device specified jump value Sector Addressing ----------------- Sector addressing is complicated by sparing, in that the CHS address written in the sector preamble may not match the physical CHS of the sector. It is also complicated by the file mask auto-seek configuration, the fact that the controller and drive both maintain CHS addresses, and that address verification after head switching wants to be as efficient as possible. Typically, these complications are significant only for MAC controllers with multiple units, but it still comes into play for ICD controllers and the diagnostic. The two issues are controller vs. drive addressing, and sector skew. Both the drive and the controller store the cylinder, head, and sector addresses supplied by the CPU for a Seek command, while an Address Record command stores the CHS addresses in the controller without transmitting them to the drive. The drive has separate commands to store the cylinder ("Seek"), the head-sector ("Address Record") address pair, and the sector address ("Transmit Sector"). Storing the cylinder address initiates head positioning, storing the head address connects the head to the read/write circuits, and storing the sector address gates the head to read or write at the target sector. RTE and MPE drivers are written to follow a controller Seek with a controller Address Record command before reading or writing, so the distinction between drive and controller addresses is usually irrelevant. However, when initializing spare tracks or running the diagnostics, the distinction becomes important. The MAC and ICD controller documentation states that a read or write operation (2) the cylinder and head last addressed by a SEEK command and the sector last addressed by an ADDRESS RECORD command, or (3) the sector following the last sector transferred, whichever occurred most recently." The MAC microcode shows that a Seek command obtains the CHS values, writes them to the controller's CYLAD and HSAD registers, and then writes the CYLAD value with the SEEKC tag and the HSAD value with the ADREC tag to the drive. The Address Record command performs the first two steps only. So Seek sets both drive and controller to the same CHS address, while Address Record sets only the controller address. For read and write commands that perform address verification of the sector prior to the starting sector (e.g., Read, Write, Verify, etc.), the controller's decremented sector address is sent to the drive with the XSECT tag. Then a read of that preceding sector is initiated, and the CHS addresses in the preamble are verified against the decremented controller's CHS values. If they do not compare, an automatic re-seek is performed to align the drive's CHS location with the controller's. This is done transparently. The commands that do not perform address verification, i.e., Read Full Sector, Write Full Sector, and Initialize, the controller's sector address is sent to the drive with the XSECT tag, and the read or write commences at the drive's cylinder and head addresses. The controller's cylinder and head addresses are used only to write the preambles. So, for example, seeking to CHS 10/0/5 and then reading would verify the preamble from 10/0/4, and read from 10/0/5. Seeking to 10/0/5, addressing record 11/1/7, and reading would verify the preamble from 10/0/6, find that it doesn't match the controller's CHS address, automatically re-seek to 11/1/6, verify the address, and then read from 11/1/7. Substituting a full sector read would skip the verification step and read from 10/0/7. A read or write, then, regardless of address verification, will start at the drive's cylinder and head and the controller's sector. However, with verification, a read or write will effectively start at the controller's CHS address. The only user-observable difference is that the operation may take longer than expected due to an internal re-seek. This does not hold true if address verification is not done. Therefore, the drive must store the cylinder and head addresses supplied in a Seek command (it could also store the sector address, although this is not used in simulation). (The current implementation stores only the cylinder address with the drive. This is a BUG that causes a defective or sparing operation, i.e., one that initializes a track with a different preamble address, to write to the wrong location -- it writes to the Address Record head instead of the Seek head.) A continuing unverified read or write will access subsequent sectors on the drive's cylinder and head. At the end of the track, the file mask is checked: * If auto-seek is inhibited, an End of Cylinder error is returned. * If auto-seek in surface mode is enabled, then the updated cylinder (and sector 0) are sent to the drive, continuing the operation on the same (i.e., drive's) head. * If auto-seek in cylinder mode is enabled, then the incremented controller's head (and sector 0) is sent to the drive, continuing the operation on the same (i.e., the drive's) cylinder. Once the end of the cylinder is reached, the incremented cylinder and reset head and sector are transmitted to the drive. From that point on, the controller and drive CHS addresses are equal. The sector skew issue arises because the MAC and ICD controllers skew the logical sectors on heads 1-N. When writing the preambles, which define the logical addressing scheme, the controllers add the head number to the sector number modulo the sector count. So, for example, physical sector 0 on head 0 is also logical sector 0, but physical sector 0 on head 1 is logical sector 47 (i.e., logical sector 0 is at physical sector 1). This is done to allow automatic head switching to verify the preceding sector without having to wait for an entire disc revolution. Sector skew is related to disc rotation timing, which isn't relevant for simulation. However, the ICD diagnostic depends on the skew and checks it. In Step 22, the diagnostic does a Seek to 199/1/0, storing cylinder 199 head 1 in the drive. It then does an Address Record to 199/0/0, followed by an Initialize for a spare track. Because the skew is based on the logical address -- in this case, 199/0/0 -- the sectors on head 1 are written with no skew, i.e., logical sector 0 is physical sector 0. The diagnostic then does another Seek to 199/1/0 and a Read Full Sector. As there is no Address Record after the seek, logical sector 0 is skewed to physical sector 1, so the read begins at physical sector 1. The read returns 199/0/1 in the preamble because the track was initialized with 1:1 mapping (skewing is done on the physical address only when initializing a defective track). There is no way for RFS to know this, so an override is necessary to satisfy the diagnostic.