:765:FDC:NEC 765:8272:floppy controller ^NEC mPD765 - Floppy Disk Controller - 8272A % FDC Digital Output Register at 3F2h (all systems) |7|6|5|4|3|2|1|0| port 3F2h (write only) | | | | | | ------- floppy drive select (0=A, 1=B, 2=floppy C, ...) | | | | | -------- 1 = FDC enable, 0 = hold FDC at reset | | | | --------- 1 = DMA & I/O interface enabled (reserved PS/2) | | | ---------- 1 = turn floppy drive A motor on | | ----------- 1 = turn floppy drive B motor on | ------------ 1 = turn floppy drive C motor on; (reserved PS/2) ------------- 1 = turn floppy drive D motor on; (reserved PS/2) - used to control drive motors, drive selection, and feature enable - PS/2 only uses bit 0 for floppy drive select; bit 1 is reserved - PS/2 only uses bits 5 & 4 for motor enable; bits 7&6 are reserved - all DOR bits are cleared during controller reset % FDC Main Status Register at 3F4h (all systems) |7|6|5|4|3|2|1|0| port 3F4h (read only) | | | | | | | ----- floppy drive 0 in seek mode/busy | | | | | | ------ floppy drive 1 in seek mode/busy | | | | | ------- floppy drive 2 in seek mode/busy (reserved PS/2) | | | | -------- floppy drive 3 in seek mode/busy (reserved PS/2) | | | --------- FDC read or write command in progress | | ---------- FDC is in non-DMA mode | ----------- I/O direction; 1 = FDC to CPU; 0 = CPU to FDC ------------ data reg ready for I/O to/from CPU (request for master) % FDC Command Status Register 0 at 3F5h (all systems) |7|6|5|4|3|2|1|0| Command Status Register 0 at port 3F5h | | | | | | ------- unit selected at interrupt (0=A, 1=B, 2=...) | | | | | -------- head number at interrupt (head 0 or 1) | | | | --------- not ready on read/write or SS access to head 1 | | | ---------- equipment check (see note) | | ----------- set to 1 when FDD completes a seek command -------------- last command status (see below) % Bits % 76 Last Command Status 00 command terminated successfully 01 command execution started but terminated abnormally 10 invalid command issued 11 command terminated abnormally due to a change in state of the Ready Signal from the FDC (reserved on PS/2) - equipment check can occur if FDD signals a fault or track zero is not found after 77 steps on a recalibrate command - PS/2 only uses bits 1-0 for drive (values are 01b and 10b) % FDC Command Status Register 1 at 3F5h (all systems) |7|6|5|4|3|2|1|0| Command Status Register 1 at port 3F5h | | | | | | | ----- FDC cannot find ID address mark (see reg 2) | | | | | | ------ write protect detected during write | | | | | ------- FDC cannot find sector ID | | | | -------- unused (always zero) | | | --------- over-run; FDC not serviced in reasonable time | | ---------- data error (CRC) in ID field or data field | ----------- unused (always zero) ------------ end of cylinder; sector# greater than sectors/track - bit 0 of Status Register 1 and bit 4 of Status Register 2 are related and mimic each other % FDC Command Status Register 2 at 3F5h (all systems) |7|6|5|4|3|2|1|0| Command Status Register 2 at port 3F5h | | | | | | | ----- missing address mark in data field | | | | | | ------ bad cylinder, ID not found and Cyl Id=FFh | | | | | ------- scan command failed, sector not found in cylinder | | | | -------- scan command equal condition satisfied | | | --------- wrong cylinder detected | | ---------- CRC error detected in sector data | ----------- sector with deleted data address mark detected ------------ unused (always zero) - bit 0 of Status Register 1 and bit 4 of Status Register 2 are related and mimic each other % FDC Command Status Register 3 at 3F5h (FDD status, all systems) |7|6|5|4|3|2|1|0| Floppy Disk Drive Status at port 3F5h | | | | | | ------- FDD unit selected status (0=A, 1=B, 2=...) | | | | | -------- FDD side head select status (0=head 0, 1=head 1) | | | | --------- FDD two sided status signal | | | ---------- FDD track zero status signal | | ----------- FDD ready status signal | ------------ FDD write protect status signal ------------- FDD fault status signal ^FDC Programming Considerations % Three phases of command execution: 1. Command phase; commands are sent from the CPU to the FDC via port 3F5h; bit 6 of the Status Register at 3F4h must be zero 2. Execution phase; FDC executes instruction & generates INT 6 3. Result phase; status and other information is available to CPU; INT 6 sets bit 7 of BIOS Data Area location 40:3E which can be polled for completion status % Example of a read operation: 1. turn disk motor on and set delay time for drive spin up 2. perform seek operation; wait for disk interrupt 3. prepare DMA chip to move data to memory 4. send read command and wait for transfer complete interrupt 5. read status information 6. turn disk motor off ^Floppy Diskette Controller Operations (15 commands) % Read Data D7 D6 D5 D4 D3 D2 D1 D0 command byte 0: MT MF SK 0 0 1 1 0 command byte 1: ? ? ? ? ? HD US1 US0 command byte 2: cylinder number command byte 3: head number command byte 4: sector number command byte 5: bytes per sector command byte 6: end of track (last sector in track) command byte 7: gap 3 length command byte 8: data length (if cmd byte 5==0) result byte 0: status register 0 result byte 1: status register 1 result byte 2: status register 2 result byte 3: cylinder number result byte 4: head number result byte 5: sector number result byte 6: bytes per sector % Read Deleted Data D7 D6 D5 D4 D3 D2 D1 D0 command byte 0: MT MF SK 0 1 1 0 0 command byte 1: ? ? ? ? ? HD US1 US0 command byte 2: cylinder number command byte 3: head number command byte 4: sector number command byte 5: bytes per sector command byte 6: end of track (last sector in track) command byte 7: gap 3 length command byte 8: data length (if cmd byte 5==0) result byte 0: status register 0 result byte 1: status register 1 result byte 2: status register 2 result byte 3: cylinder number result byte 4: head number result byte 5: sector number result byte 6: bytes per sector % Write Data D7 D6 D5 D4 D3 D2 D1 D0 command byte 0: MT MF 0 0 0 1 0 1 command byte 1: ? ? ? ? ? HD US1 US0 command byte 2: cylinder number command byte 3: head number command byte 4: sector number command byte 5: bytes per sector command byte 6: end of track (last sector in track) command byte 7: gap 3 length command byte 8: data length (if cmd byte 5==0) result byte 0: status register 0 result byte 1: status register 1 result byte 2: status register 2 result byte 3: cylinder number result byte 4: head number result byte 5: sector number result byte 6: bytes per sector % Write Deleted Data D7 D6 D5 D4 D3 D2 D1 D0 command byte 0: MT MF 0 0 1 0 0 1 command byte 1: ? ? ? ? ? HD US1 US0 command byte 2: cylinder number command byte 3: head number command byte 4: sector number command byte 5: bytes per sector command byte 6: end of track (last sector in track) command byte 7: gap 3 length command byte 8: data length (if cmd byte 5==0) result byte 0: status register 0 result byte 1: status register 1 result byte 2: status register 2 result byte 3: cylinder number result byte 4: head number result byte 5: sector number result byte 6: bytes per sector % Read a Track D7 D6 D5 D4 D3 D2 D1 D0 % (Diagnostic) command byte 0: 0 MF SK 0 0 0 1 0 command byte 1: ? ? ? ? ? HD US1 US0 command byte 2: cylinder number command byte 3: head number command byte 4: sector number command byte 5: bytes per sector command byte 6: end of track (last sector in track) command byte 7: gap 3 length command byte 8: data length (if cmd byte 5==0) result byte 0: status register 0 result byte 1: status register 1 result byte 2: status register 2 result byte 3: cylinder number result byte 4: head number result byte 5: sector number result byte 6: bytes per sector % Read ID D7 D6 D5 D4 D3 D2 D1 D0 command byte 0: 0 MF 0 0 1 0 1 0 command byte 1: ? ? ? ? ? HD US1 US0 result byte 0: status register 0 result byte 1: status register 1 result byte 2: status register 2 result byte 3: cylinder number result byte 4: head number result byte 5: sector number result byte 6: bytes per sector % Format a Track D7 D6 D5 D4 D3 D2 D1 D0 % (Write Sector IDs) command byte 0: 0 MF 0 0 1 1 0 1 command byte 1: ? ? ? ? ? HD US1 US0 command byte 2: bytes per sector command byte 3: sectors per track command byte 4: gap 3 length command byte 5: filler pattern to write in each byte result byte 0: status register 0 result byte 1: status register 1 result byte 2: status register 2 result byte 3: cylinder number result byte 4: head number result byte 5: sector number result byte 6: bytes per sector % Scan Equal D7 D6 D5 D4 D3 D2 D1 D0 command byte 0: MT MF SK 1 0 0 0 1 command byte 1: ? ? ? ? ? HD US1 US0 command byte 2: cylinder number command byte 3: head number command byte 4: sector number command byte 5: bytes per sector command byte 6: end of track (last sector in track) command byte 7: gap 3 length command byte 8: scan test (1=scan contiguous, 2=scan alternate) result byte 0: status register 0 result byte 1: status register 1 result byte 2: status register 2 result byte 3: cylinder number result byte 4: head number result byte 5: sector number result byte 6: bytes per sector % Scan Low or Equal D7 D6 D5 D4 D3 D2 D1 D0 command byte 0: MT MF SK 1 1 0 0 1 command byte 1: ? ? ? ? ? HD US1 US0 command byte 2: cylinder number command byte 3: head number command byte 4: sector number command byte 5: bytes per sector command byte 6: end of track (last sector in track) command byte 7: gap 3 length command byte 8: scan test (1=scan contiguous, 2=scan alternate) result byte 0: status register 0 result byte 1: status register 1 result byte 2: status register 2 result byte 3: cylinder number result byte 4: head number result byte 5: sector number result byte 6: bytes per sector % Scan High or Equal D7 D6 D5 D4 D3 D2 D1 D0 command byte 0: MT MF SK 1 1 1 0 1 command byte 1: ? ? ? ? ? HD US1 US0 command byte 2: cylinder number command byte 3: head number command byte 4: sector number command byte 5: bytes per sector command byte 6: end of track (last sector in track) command byte 7: gap 3 length command byte 8: scan test (1=scan contiguous, 2=scan alternate) result byte 0: status register 0 result byte 1: status register 1 result byte 2: status register 2 result byte 3: cylinder number result byte 4: head number result byte 5: sector number result byte 6: bytes per sector % Recalibrate D7 D6 D5 D4 D3 D2 D1 D0 command byte 0: 0 0 0 0 0 1 1 1 command byte 1: ? ? ? ? ? 0 US1 US0 returns nothing % Sense Interrupt D7 D6 D5 D4 D3 D2 D1 D0 % Status command byte 0: 0 0 0 0 1 0 0 0 result byte 0: status register 0 result byte 1: present cylinder number % Specify Step & D7 D6 D5 D4 D3 D2 D1 D0 % Head Load command byte 0: 0 0 0 0 0 0 1 1 command byte 1: step rate time | head unload time command byte 2: ------head load time------ ND returns nothing % Sense Drive D7 D6 D5 D4 D3 D2 D1 D0 % Status command byte 0: 0 0 0 0 0 1 0 0 command byte 1: ? ? ? ? ? HD US1 US0 result byte 0: status register 3 % Seek D7 D6 D5 D4 D3 D2 D1 D0 command byte 0: 0 0 0 0 1 1 1 1 command byte 1: ? ? ? ? ? HD US1 US0 command byte 2: new cylinder number returns nothing % mPD765 Version D7 D6 D5 D4 D3 D2 D1 D0 command byte 0: ? ? ? 1 0 0 0 0 result byte 0: status register 0 90h = mPD765B; 80h = mPD765A or mPD765A-2 % Invalid Command result byte 0: status register 0 (value of 80h) % Key to Abbreviations HD = Head Number Selected SK = SKip Deleted-data address mark MT = Multi-Track US0 = drive select bit 0 MF = MFM mode US1 = drive select bit 1 ND = Non-DMA mode Head Load Time = 2 to 254ms in 2ms increments Head Unload Time = 16 to 240ms in 16ms increments Step Rate Time = 1 to 16ms in 1ms increments - PS/2 systems use the 8272A diskette controller which is software and port compatible with the NEC mPD765 - accessed through ports 3F0h-3F7h; NEC mPD765 is accessed through ports 3F2h, 3F4h and 3F5h; the 8272A uses ports 3F0h, 3F1h, 3F2h, 3F4h, 3F5h and 3F7h - data, command and status registers are all accessed through port 3F5h a register stack with one address presented to the bus - bit 7 of BIOS Data Area byte 40:3E can be polled to determine if a disk operation has completed; this bit is set by the interrupt handler when the operation has completed; it should be reset before continuing on with the next FDC operation - see ~BIOS Data Area~ ~INT TABLE~ ~INT 13~