Contributor: ARNE DE.BRUIJN { RP> Has anyone any ideas how to interrogate an IDE drive to get RP> its setup parameters } { Read IDE drive info, Arne de Bruijn, 1994, PD } { Information from 'Alles over PC Hardware' by Hans-Peter Messmer } {$G+} uses Crt,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 Clrscr; 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.