[Back to DRIVES SWAG index] [Back to Main SWAG index] [Original]
{
> Has anyone any ideas how to interrogate an IDE drive to get
> its setup parameters
{ Read IDE drive info, Arne de Bruijn, 1994, PD }
{ Information from 'Alles over PC Hardware' by Hans-Peter Messmer }
{$G+}
uses Dos;
var
Buffer:pointer;
{ Buffer filled with following information (word offsets):
0 configuration:
bit 0 reserved
1 1=hard-sector drive
2 1=soft-sector drive
3 1=RLL/ARLL format
4 1=headswitchdelay is 15 ms
5 1=less currency mode implented
6 1=hard disk
7 1=exchangable medium (mostly CD-ROM drive)
8 1=internal datatransfer <5 Mbit/s
9 1=internal datatransfer between 5 and 10 Mbit/s
10 1=internal datatransfer >10 Mbit/s
11 1=rotation speed toleration >0,5% (notebook)
12-15 reserved
1 no of physical cylinders
2 reserved
3 no of heads
4 no of not-formatted bytes per physical sector
5 no of not-formatted bytes per sector
6 no of physical sectors
7-9 reserved for manufacturer
10-19 ASCII serial number
20 buffertype (01h one-directional, 02h bi-directional, 03h=cache buffer)
21 buffersize/512
22 no of ECC bytes transferred at read/writelong cmds
23-26 ASCII controller-firmware ID
27-46 ASCII modelnumber
47 bit 0..7 no of sectors between two interrupts, bit 8..15 reserved
48 bit 0: 1=32 bit-I/O, 0 no 32 bit-I/O, bit 1..7 reserved
49 bit 0..7 reserved, bit 8: 1=DMA, 0=no DMA, bit 9: 1=LBA, 0=no LBA
50 reserved
51 bit 0..7 reserved, bit 8..15 PIO cyclus time
(0=600ns, 1=380ns, 2=240ns, 3=180ns)
52 bit 0..7 reserved, bit 8..15 DMA cyclus time
(0=960ns, 1=380ns, 2=240ns, 3=150ns)
53 reserved
54 no of logical cylinders
55 no of logical heads
56 no of logical sectors per track
57-58 Bytes per logical sector
59 bit 0..7 no of sectors
60-61 addressable sectors in LBA mode
62 single DMA: bit 0..7=supported modes, bit 8..15=active modes
63 multiple DMA: bit 0..7=supported modes, bit 8..15=active modes
64-127 reserved
128-159 manufacturer specific
160-255 reserved
}
GotData:boolean;
function SwitchChars(var X; Len:byte):string; assembler;
{ Returns Len bytes from X, each word swapped }
asm
push ds
les di,@Result
xor ah,ah
mov al,Len
mov cx,ax
shl al,1
stosb
jcxz @NoCopy
lds si,X
@Copy:
lodsw
xchg al,ah
stosw
loop @Copy
@NoCopy:
pop ds
end;
procedure HDInt; interrupt;
{ Interrupt called when data is ready }
begin
if Port[$1f7] and 8<>0 then
begin
asm
mov dx,1f0h
les di,Buffer
mov cx,256
rep insw { Get 256 words (512 bytes) }
end;
GotData:=true;
end;
Port[$a0]:=$20; { Send EOI to PIC 2 }
Port[$20]:=$20; { Send EOI to PIC 1 }
end;
type
AWord=array[0..32766] of word;
var
Timer:longint absolute $40:$6c;
Slave:boolean;
LastTimer,T:byte;
OldInt:pointer;
OldPic1M,OldPic2M:byte;
begin
Slave:=false; { True is check for slave, false check for master }
GetMem(Buffer,512);
T:=2; { Wait 2 clock ticks }
while (Port[$1f7] and $c0<>$40) and (T>0) do
if byte(Timer)<>LastTimer then begin Dec(T); LastTimer:=byte(Timer); end;
if Port[$1f7] and $c0<>$40 then
begin
WriteLn('Timeout 1!');
Halt(1);
end;
GetIntVec($76,OldInt); { Set interrupt (IRQ 14 = int $76) }
SetIntVec($76,@HDInt);
OldPic1M:=Port[$21]; OldPic2M:=Port[$a1]; { Save PIC masks }
Port[$21]:=OldPic1M and (not 4); { Enable IRQ 14 }
Port[$a1]:=OldPic2M and (not 64);
GotData:=false;
Port[$1f6]:=$a0+byte(Slave)*16; { Send drive no }
Port[$1f7]:=$EC; { Send command code }
T:=3;
while (not GotData) and (T>0) do
if byte(Timer)<>LastTimer then begin Dec(T); LastTimer:=byte(Timer); end;
Port[$21]:=OldPic1M; Port[$a1]:=OldPic2M; { Restore PIC masks }
SetIntVec($76,OldInt); { Restore interrupt }
if not GotData then
begin
WriteLn('Timeout 2!');
Halt(1);
end;
WriteLn('Heads:',AWord(Buffer^)[3],' Cylinders:',AWord(Buffer^)[1],
' Sectors:',AWord(Buffer^)[6]);
WriteLn('Serial number:',SwitchChars(AWord(Buffer^)[10],10));
WriteLn('Controller firmware ID:',SwitchChars(AWord(Buffer^)[23],4));
WriteLn('Modelnumber:',SwitchChars(AWord(Buffer^)[27],20));
Port[$1F6]:=$a0+byte(Slave)*16;
FreeMem(Buffer,512);
end.
[Back to DRIVES SWAG index] [Back to Main SWAG index] [Original]