back2root:ibm-pc-ms-dos:hardware:8272-pd765
8275A- NEC µPD765 - Floppy Disk Controller
8275A-µPD765 Registers
3F0h - FDC Diskette Status Register A (PS/2)
bit | 3F0h PS/2 Disk Status Register A (read-only) |
0 | direction |
1 | write protect |
2 | index |
3 | head 1 select |
4 | track 0 |
5 | step |
6 | second drive installed |
7 | interrupt pending |
3F1h - FDC Diskette Status Register B (PS/2)
bit | 3F1h PS/2 Disk Status Register B (read-only) |
0 | motor enable 0 |
1 | motor enable 1 |
2 | write enable |
3 | read data (toggles w/positive transition in -RD DATA) |
4 | write data (toggles w/positive transition in WR DATA) |
5 | drive select |
6-7 | reserved |
FDC Digital Output Register at 3F2h (all systems)
bit | port 3F2h (write only) |
0-1 | floppy drive select (0=A, 1=B, 2=floppy C, …) |
2 | 1 = FDC enable, 0 = hold FDC at reset |
3 | 1 = DMA & I/O interface enabled (reserved PS/2) |
4 | 1 = turn floppy drive A motor on |
5 | 1 = turn floppy drive B motor on |
6 | 1 = turn floppy drive C motor on; (reserved PS/2) |
7 | 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)
bit | port 3F4h (read only) |
0 | floppy drive 0 in seek mode/busy |
1 | floppy drive 1 in seek mode/busy |
2 | floppy drive 2 in seek mode/busy (reserved PS/2) |
3 | floppy drive 3 in seek mode/busy (reserved PS/2) |
4 | FDC read or write command in progress |
5 | FDC is in non-DMA mode |
6 | I/O direction; 1 = FDC to CPU; 0 = CPU to FDC |
7 | data reg ready for I/O to/from CPU (request for master) |
FDC Command Status Register 0 at 3F5h (all systems)
bit | Command Status Register 0 at port 3F5h |
0-1 | unit selected at interrupt (0=A, 1=B, 2=…) |
2 | head number at interrupt (head 0 or 1) |
3 | not ready on read/write or SS access to head 1 |
4 | equipment check (see note) |
5 | set to 1 when FDD completes a seek command |
6-7 | last command status (see below) |
Bits 7-6 | 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) |
FDC Command Status Register 1 at 3F5h (all systems)
bit | Command Status Register 1 at port 3F5h |
0 | FDC cannot find ID address mark (see reg 2) |
1 | write protect detected during write |
2 | FDC cannot find sector ID |
3 | unused (always zero) |
4 | over-run; FDC not serviced in reasonable time |
5 | data error (CRC) in ID field or data field |
6 | unused (always zero) |
7 | end of cylinder; sector# greater than sectors/track |
3F5h - FDC Command Status Register 2 (all systems)
bit | Command Status Register 2 at port 3F5h |
0 | missing address mark in data field |
1 | bad cylinder, ID not found and Cyl Id=FFh |
2 | scan command failed, sector not found in cylinder |
3 | scan command equal condition satisfied |
4 | wrong cylinder detected |
5 | CRC error detected in sector data |
6 | sector with deleted data address mark detected |
7 | unused (always zero) |
3F5h - FDC Command Status Register 3 (FDD status, all systems)
bit | Floppy Disk Drive Status at port 3F5h |
0-1 | FDD unit selected status (0=A, 1=B, 2=…) |
2 | FDD side head select status (0=head 0, 1=head 1) |
3 | FDD two sided status signal |
4 | FDD track zero status signal |
5 | FDD ready status signal |
6 | FDD write protect status signal |
7 | FDD fault status signal |
bit | 3F7h PS/2 Digital Input Register (read only) |
0 | high density select |
1-6 | reserved |
7 | diskette change |
3F7h - FDC Configuration Control Register (PS/2)
bit | 3F7h PS/2 Config. Control Register (write only) |
0-1 | DRC1, DRC0 (see below) |
2-7 | reserved |
DRC1 | DRC0 | |
0 | 0 | 500000 bit per second mode |
0 | 1 | reserved |
1 | 0 | 250000 bit per second mode |
1 | 1 | reserved |
FDC Programming Considerations
Three phases of command execution:
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
Execution phase; FDC executes instruction & generates INT 6
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:
turn disk motor on and set delay time for drive spin up
perform seek operation; wait for disk interrupt
prepare DMA chip to move data to memory
send read command and wait for transfer complete interrupt
read status information
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
(Diagnostic) | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
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
(Write Sector IDs) | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
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
Status | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
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 &
Head Load | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
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
Status | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
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 | |
µPD765 Version | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
command byte 0: | ? | ? | ? | 1 | 0 | 0 | 0 | 0 |
result byte 0: | status register 0 |
| 90h = µPD765B; 80h = µPD765A or µPD765A-2 |
Invalid Command | |
result byte 0: | status register 0 (value of 80h) |
Key to Abbreviations
HD | Head Number Selected |
MT | Multi-Track |
MF | MFM mode |
ND | Non-DMA mode |
SK | SKip Deleted-data address mark |
US0 | drive select bit 0 |
US1 | drive select bit 1 |
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 µPD765
accessed through ports 3F0h-3F7h;
NEC µPD765 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
back2root/ibm-pc-ms-dos/hardware/8272-pd765.txt · Dernière modification : 2023/02/23 22:30 de frater