原文:可编程软盘控制器
Command Set
总共有13个命令在uPD765和兼容的FDC上可用。还有4个命令将会在8207x的控制器上可用。
扇区的识别由柱面,磁头,扇区号和扇区大小组成。这些可以告诉控制器命令执行的位置和扇区数目。
所有命令和状态通过数据寄存器传输,端口号为3f7h或者377h。在写命令或者读状态之前,需要读取main status register的MRQ位。它决定了数据寄存器是否已经准备好接收或者提供一个字节。在任何读,写或格式化操作前需要优先修复驱动器格式。
对于大多数的数据传输,都会使用DMA。尽管DMA的编程已经超出了这篇文章的范畴,我还是提供了一个例子代码来展示如何建立DMA把软盘的一个扇区写到主存中。所有的数据传输都涉及到从开始扇区到末扇区的整个扇区。这种操作可以早点停止通过命令字节设定磁道长度或扇区数目来操作最后的一个扇区,也可以通过设定DMA控制器的count value让传输到需要的扇区数目后发送TC(terminal count)讯号(后面的方法在下面DMA代码中有演示)。
如果你想一个命令在两个磁头上同时执行,你需要设定multiple track bit位。它会告诉控制器操作完第一个磁头后,在另外一个磁头执行相同的命令。
一旦命令执行完成,那么状态寄存器ST0-3会返回信息帮助你确认命令执行的正确性或者查看错误的类型。
命令分为3个部分。数据传输命令和控制命令适用于所有的控制器。扩展命令只使用在AT机和PS/2机上。
Data Transfer Commands
x2h - read complete track
x5h - write sector
x6h - read sector
x9h - write deleted sector
xch - read deleted sector
xdh - format track
Control Commands
x3h - fix drive data
x4h - check drive status
x7h - calibrate drive
x8h - check interrupt status
xah - read sector ID
xfh - seek/park head
- invalid command
Extended Commands
0fh - register summary
x10h - determine controller version
x16h - verify
1xfh - seek relative
在上面的命令中,'x'对应0字节的bit7-5位。注意在seek relative命令中,'x'对应的是bit6和5位,bit7位始终为1。剩余扩展的两个命令对应bit4-0位。bit4位只在AT机和PS/2机中使用。
上面的命令只运用到了第一个字节。命令的大小在1-9个字节之间,控制器知道这个命令有多少个字节。比如,如果第一个从数据寄存器接收到的字节为66h,它的前5位为06h,控制器就知道你发送了一个read sector的命令,它会从CPU那里在接收到8个字节。另外,你不必担心每个命令在内部寄存器中字节的对应关系,控制器会为你做好一切。
许多命令都有的公共字段如下:
M:multi-track operation.
1 = carry out operation on both tracks of programmed cylinder
0 = carry out operation on single track
F:FM/MFM mode.
1 = operate in MFM (double density) mode (default)
0 = operate in FM (single density) mode
S:skip mode.
1 = skip deleted data address masks, 0 = do not skip
HD:head number.
(always equal to head address in byte 3 of all commands using a sector ID)
DR1,DR0:drive.
00= drive 0 (A:), 01= drive 1 (B:), 10 = drive 2 (C:), 11 = drive 3 (D:)
cylinder, head, sector number:address of first sector to read.
sector size code:sector size = 128 * 2^x where x is the value in this field.
eg. if this field is 2 (the default), sector size = 128 * 2^2 = 512 bytes
track length/max sector number:number of sectors per track or max sector number to operate command on.
length of GAP 3:standard value = 42, minimal values = 32 (5.5 floppy size). standard value = 27 (3.5 floppy size).
data length:length of data to read.
in bytes (only valid if sector size = 0, else equal 0ffh)
Data Transfer Commands
下面的命令被用来在磁盘和主存之间传输数据或者格式化一个磁道。
每个命令的返回值格式都相同,下面仅对read track命令进行了描述。
- read track (x2h)
一个read track命令发生,整个磁道的数据都会被读出。指明的sector位置会被忽略,直接从index address mask (IDAM)后的第一个扇区开始读,一个扇区一个扇区读(不会去管在ID address mask里面的逻辑扇区号)直到磁道的末尾。
磁道会被看作连续的数据块,因此在主存中的buffer需要足够大来存储这些数据。而这个命令不支持milti-track操作。如果你想在同一个磁道用不同的磁头读,你必须发送这个命令两次,不像其他的读命令只需发送一次multi-track操作。
- results phase
ST0,ST1,ST2:status register 0-2 (Data Register).
cylinder,head,sector number,sector size:sector ID. (看下表)
sector ID包含了cylinder,head,sector和sector size。给的值M(multi-track),HD(head number)和sector ID的值指明了影响的最后一个扇区是否是命令的最后一个扇区。
- write sector (x5h)
这个write sector命令把一个或多个扇区的数据从主存传输到控制器,在从这里传输到磁盘。在控制器每写一个扇区的同时,它也会写一个有效的data address mask到磁盘。这个命令可以在两个磁头进行操作,在第一个磁头到达末尾时第二个磁头从第一个扇区开始。
它的results phase和read track命令一样。
- read sector (x6h)
这个read sector命令从磁盘读取一个或多个有效的data address mask扇区到主存。它可以在两个磁头上操作。
它的results phase和read track命令一样。
- write deleted sector (x9h)
这个write deleted sector命令和write sector命令一样,除了每个扇区的时候它写的是一个deleted data address mask而不是一个正常的data address mask。
它的results phase和read track命令一样。
- read deleted sector (xch)
这个read deleted sector命令和read sector命令一样,除了它读的是有deleted data address mask的扇区。所有是有效的data address mask的扇区都将会被忽略。
它的results phase和read track命令一样。
- format track (xdh)
这个命令格式化一个磁道。一个4字节格式的buffer会提供给每个扇区。这个buffer控制着对应扇区的sector ID。这个格式的buffer应该要足够大能够能控制一个磁道的所有扇区的数据。它的格式如下。
为了减轻使用的负担,可以使用DMA控制器,让控制器通过DMA channel 2来读取格式的buffer数据。或者说,格式数据通过驱动器的中断进行传输。在即将要格式化一个扇区前控制器响应一个硬件中断。然后每次传输一个4字节的格式化下一个扇区的格式信息。
当驱动器在IDX line提供一个信号时格式化开始,它表示磁道的开始。直到驱动器再次接收到相同的信号扇区格式化结束,这个时间点指明了一个磁道的末尾(注意,磁道的开始和末尾是在相同的位置,用一个index孔标记在磁盘上)。
对于格式化命令,GAP字段的长度会比读写数据的时候要长。除非我能找到其他的一些关于GAP字段长度的信息,否则这篇文章我仅仅用它的默认长度。
format buffer for one sector
在上面的表中,sector size和上面描述的命令是一样的。
Control Commands
这个命令集合包含了关于驱动器或者磁盘相关状态的不同的混杂的命令,包括了新柱面的定位和无效命令的应答。
- fix drive data (x3h)
NDM:non-DMA mode.
0 = data transfer via DMA
1 = data transfer not via DMA
这个命令是用来控制控制器连接的驱动器的机械控制数据。注意,上面的3个图表,它们的值依赖数据传输率,可以通过control configuration register设定在AT机和PS/2机上。
这个命令没有result phase。
- check drive status (x4h)
这个命令可以提供驱动器的状态信息。
result phase
status register 3包含了驱动器信息。
- calibrate drive (x7h)
这个命令可以将读写磁头移动到柱面0处。如果一个定位操作在扇区行进的过程中出错,磁头为了重新校正驱动器会被移动到一个绝对的柱面上。
这个命令不会返回一个result phase,但是会有一个中断结束发生。为了检查这个命令的状态信息,你应该发送一个check interrupt status命令去查看状态信息。
当控制器看见这个命令,它会设定DIR信号为0,把它抬高到79个步脉冲。在每个脉冲后,控制器会去检车TRK0信号。如果它是激活状态(表明,磁头在磁道0上),控制器就会设定status register 0的SE标志,然后中止该命令。如果TRK0信号没有激活在79个脉冲后,控制器会去设定status register 0的SE和UC标志,然后结束命令。
为了校正驱动器,你可能需要发送几次校正命令,特别是如果驱动器超过了80个磁道。在命令完成后,你需要经常使用check interrupt status命令去检查磁头是否在磁头0上。在驱动器启动后,为了初始化磁头的正确位置,通常需要做一次校正。
- check interrupt status (x8h)
这个命令用来检查控制器的状态信息当控制器返回一个中断时。
中断信号会被该命令复位,它也可以通过status register ST0查看中断源。如果命令没有中断,会返回ST0的值为80h,对应的信息为invalid command。
以下是中断发生的条件:
at the beginning of the result phase of the commands:
read sector
read deleted sector
write sector
write deleted sector
read track
format track
read sector ID
verify
after completion of the following commands without a result phase:
calibrate drive
seek
seek relative
for data exchange between main memory and controller when interrupt-driven data exchange is active and the controller is not using DMA
result phase
- read sector ID (xah)
这个命令读取控制器能检测到的第一个ID address mask的sector ID。使用这个命令,可以确定当前读写磁头的位置。如果在读完整个磁盘没有ID address mask,那么控制器会发送一个错误信息,可以在返回的ST0-2的值中检查。
它的result phase和read track命令一样。
- seek/park head (xfh)
这个seek head命令,有时也叫做park head命令,移动读写磁头到指定的柱面。当控制器接收到这个命令,它会和当前的柱面号进行比较。方向信号会被设定,发送步脉冲直到两个柱面号匹配。
这个命令没有result phase。为了验证命令的成功完成,需要在命令完成后立刻使用check interrupt status命令检查磁头位置。
- invalid command (all invalid opcodes)
无论什么时候发送一个无效的命令,控制器会切换到等待状态,置位ST0的bit7位。如果check interrupt status时没有中断也会同样发生。
result phase
Extended Commands
这些命令不适用所有的控制器,仅在AT机和PS/2机上使用。如果控制器不支持这些命令,它会认为是无效命令。
- register summary (0fh)
这个命令返回控制器内部寄存器。
result phase
current cylinder D0,DR1,DR2,DR3:cylinder on drive 0,1,2,3 where read/write head is currently positioned.
step rate,head unload time,head load time:mechanical characteristics by the fix drive data command.
NDM:non-DMA mode.
1 = DMA disabled
0 = DMA enabled
number of sectors/track length:number of sectors per track.
- determine controller version (10h)
这个命令可以确定当前控制器是否支持extended的命令。如果控制器不支持,这个命令会被当做无效命令,然后返回一个错误信息。
result phase
如果控制器支持extended命令,就会返回这个值。
- verify (x16h)
EC:enable count value.
1 = command byte 8 specifies the number of sectors to verify
0 = command byte 8 specifies the data length, if sector size =0
data length/verify sectors:if EC =0 and sector size =0, length of data to verify, in bytes. else number of sectors to verify.
这个命令和读命令相似,不过它不会传输数据到主存。一个或多个扇区中的有效DAMs会从磁盘中读取,然后计算出它们的CRC值。这个值会和读取到的CRC进行比较,按照顺序检查数据的内部一致性。当没有数据被传输的时候,这个命令也不会被DMA控制器的TC信号中止。然而,如果你设定EC位为1,控制器会暗地里发送一个TC信号当在data len/verify sectors总的这个计数减小到0的时候。在这种情况下,data length/verify sectors指明了多少扇区被验证了。如果这个值是0就是告诉控制器检查256个扇区。当EC位为0的时候,data length/verify sectors应该要设为ffh。
result phase
这个命令的result phase和read track命令一样。
- seek relative (1xfh)
DIR:step direction.
1 = inward (to larger cylinder numbers)
0 = outward (to smaller cylinder numbers)
cylinder step:number of cylinders to step.
这个命令可以移动读写磁头相对于当前柱面的步长。它没有result phase,但是可以通过read sector ID或者register dump命令来检查。