Files
2024-02-19 00:25:23 -05:00

411 lines
15 KiB
Plaintext

NEC æPD765 - Floppy Disk Controller - 8272A
PS/2 FDC Diskette Status Register A at 3F0h
³7³6³5³4³3³2³1³0³ 3F0h PS/2 Disk Status Register A (read-only)
³ ³ ³ ³ ³ ³ ³ ÀÄÄÄÄ direction
³ ³ ³ ³ ³ ³ ÀÄÄÄÄÄ write protect
³ ³ ³ ³ ³ ÀÄÄÄÄÄÄ index
³ ³ ³ ³ ÀÄÄÄÄÄÄÄ head 1 select
³ ³ ³ ÀÄÄÄÄÄÄÄÄ track 0
³ ³ ÀÄÄÄÄÄÄÄÄÄ step
³ ÀÄÄÄÄÄÄÄÄÄÄ second drive installed
ÀÄÄÄÄÄÄÄÄÄÄÄ interrupt pending
PS/2 FDC Diskette Status Register B at 3F1h
³7³6³5³4³3³2³1³0³ 3F1h PS/2 Disk Status Register B (read-only)
³ ³ ³ ³ ³ ³ ³ ÀÄÄÄÄ motor enable 0
³ ³ ³ ³ ³ ³ ÀÄÄÄÄ motor enable 1
³ ³ ³ ³ ³ ÀÄÄÄÄ write enable
³ ³ ³ ³ ÀÄÄÄÄ read data (toggles w/positive transition in -RD DATA)
³ ³ ³ ÀÄÄÄÄ write data (toggles w/positive transition in WR DATA)
³ ³ ÀÄÄÄÄ drive select
ÀÄÁÄÄÄÄ reserved
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
PS/2 FDC Digital Input Register at 3F7h
³7³6³5³4³3³2³1³0³ 3F7h PS/2 Digital Input Register (read only)
³ ³ ³ ³ ³ ³ ³ ÀÄÄÄ high density select
³ ÀÄÁÄÁÄÁÄÁÄÁÄÄÄÄ reserved
ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ diskette change
PS/2 FDC Configuration Control Register at 3F7h
³7³6³5³4³3³2³1³0³ 3F7h PS/2 Config. Control Register (write only)
³ ³ ³ ³ ³ ³ ÀÄÁÄÄ DRC1, DRC0 (see below)
ÀÄÁÄÁÄÁÄÁÄÁÄÄÄÄÄ reserved
DRC1 DRC0
0 0 500000 bit per second mode
0 1 reserved
1 0 250000 bit per second mode
1 1 reserved
- Digital Input Register is used to sense the state of the
(-diskette change) and the (-high density select) signals
- Configuration Control Register is used to set the transfer rate
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
æ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 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 æ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