Page 1 of 1
HDD - PIO Driver [SOLVED]
Posted: Tue Jun 03, 2008 5:17 pm
by 01000101
hey,
I just started fiddling around with harddisk driver writing (using PIO), and I've been going through the specs in The Indespincable PC Hardware Book r3 and it looks all pretty clear-cut and easy to implement, but I'm running into an issue with my read command.
Everything is ZEROs!
im sure it's a stupid mistake, but its annoying the crap out of me.
Code: Select all
void Read_Sector(char Type)
{
outportb(0x1F6, Type); // Drive/Head
outportb(0x1F5, 0x00); // Cylinder MSB
outportb(0x1F4, 0x00); // Cylinder LSB
outportb(0x1F3, 0x00); // Sector Number
outportb(0x1F2, 0x01); // Sector Count
outportb(0x1F1, 0x20); // Command
while(inportb(0x1F7) & 0x80){} // wait for BSY bit to go low
if(inportb(0x1F7) & 0x01){printf("HDD - ERR ERROR 4. \n",0);}
int i = 0;
for(i = 0; i < 256; i++)
{
if(inportw(0x1F0) != 0xD0C4) // I wrote 0xD0C4 256 times and now im trying to read it.
{
printf("ERROR %x \nStatus %x \nSectors Left %u \n", inportb(0x1F1), inportb(0x1F7), inportb(0x1F2));
break;
}
else{printf("YAY \n",0);}
}
printf("HDD - Read Completed \n",0);
}
this returns 0's.
I havent got to putting in dynamic addressing, but I'm not too concerned with it yet, at least until i can read sectors properly.
BTW, this is just part of an experimental kernel I have going, so no DiNS work with this one. =)
not looking for someone to fix it for me, but to push me in the right direction if this is completely wrong lol.
Posted: Tue Jun 03, 2008 5:47 pm
by Pyrofan1
I thought hard drives fire irq 14 when they have data to be read. So have you tried adding an irq 14 handler?
Posted: Tue Jun 03, 2008 6:11 pm
by 01000101
yesss indeed. i just read that. It says that once the IRQ14 has been fired, the interrupt handler transfers sector data into main memory. Is that done through the 0x1F0 port?
Posted: Tue Jun 03, 2008 7:34 pm
by Dex
Maybe you should take a look at your command reg
Code: Select all
; Technical Information on the ports:
; Port Read/Write Misc
; ------ ------------ -------------------------------------------------
; 1f0 r/w data register, the bytes are written/read here
; 1f1 r error register (look these values up yourself)
; 1f2 r/w sector count, how many sectors to read/write
; 1f3 r/w sector number, the actual sector wanted
; 1f4 r/w cylinder low, cylinders is 0-1024
; 1f5 r/w cylinder high, this makes up the rest of the 1024
; 1f6 r/w drive/head
; bit 7 = 1
; bit 6 = 0
; bit 5 = 1
; bit 4 = 0 drive 0 select
; = 1 drive 1 select
; bit 3-0 head select bits
; 1f7 r status register
; bit 7 = 1 controller is executing a command
; bit 6 = 1 drive is ready
; bit 5 = 1 write fault
; bit 4 = 1 seek complete
; bit 3 = 1 sector buffer requires servicing
; bit 2 = 1 disk data read corrected
; bit 1 = 1 index - set to 1 each revolution
; bit 0 = 1 previous command ended in an error
; 1f7 w command register
; commands:
; 50h format track
; 20h read sectors with retry
; 21h read sectors without retry
; 22h read long with retry
; 23h read long without retry
; 30h write sectors with retry
; 31h write sectors without retry
; 32h write long with retry
; 33h write long without retry
;
; Most of these should work on even non-IDE hard disks.
; This code is for reading, the code for writing is the next article.
mov dx,1f6h ;Drive and head port
mov al,0a0h ;Drive 0, head 0
out dx,al
mov dx,1f2h ;Sector count port
mov al,1 ;Read one sector
out dx,al
mov dx,1f3h ;Sector number port
mov al,1 ;Read sector one
out dx,al
mov dx,1f4h ;Cylinder low port
mov al,0 ;Cylinder 0
out dx,al
mov dx,1f5h ;Cylinder high port
mov al,0 ;The rest of the cylinder 0
out dx,al
mov dx,1f7h ;Command port
mov al,20h ;Read with retry.
out dx,al
still_going:
in al,dx
test al,8 ;This means the sector buffer requires
;servicing.
jz still_going ;Don't continue until the sector buffer
;is ready.
mov cx,512/2 ;One sector /2
mov di,offset buffer
mov dx,1f0h ;Data port - data comes in and out of here.
rep insw
; ------
mov ax,201h ;Read using int13h then compare buffers.
mov dx,80h
mov cx,1
mov bx,offset buffer2
int 13h
mov cx,512
mov si,offset buffer
mov di,offset buffer2
repe cmpsb
jne failure
mov ah,9
mov dx,offset readmsg
int 21h
jmp good_exit
failure:
mov ah,9
mov dx,offset failmsg
int 21h
good_exit:
mov ax,4c00h ;Exit the program
int 21h
Posted: Tue Jun 03, 2008 7:43 pm
by 01000101
lol great.
fixed. =)
Thanks.
Posted: Tue Jun 03, 2008 9:49 pm
by bewing
I assume that the two problems were that you never sent the "read" command to port 1f7, and that you were requesting "sector 0" which is always illegal?
You'd probably still be well off to check the wiki article -- I put a whole bunch of things in there that are not to be found anywhere else.
http://www.osdev.org/wiki/ATA_PIO_Mode
Posted: Wed Jun 04, 2008 7:36 am
by 01000101
yes & yes.
It's odd not 'starting' at zero. But all is well now, I can read and write fine and without the use of a IRQ14 handler. And I was able to use the IDENTIFY command successfully and parse the useful words.
I'll head over to that site later (once i have more time online) and check out what they have.
Posted: Wed Jun 04, 2008 2:40 pm
by 01000101
out of curiousity (since I will eventually need a logging method for DiNS), is PIO a viable method of parse logging or is the latency to great? All I will need to do is fill up a sector of logs, and then write it and then wait until another sector is filled and write that.. and so on. It doesnt seem like it would take that much time out of the actual network operations being done.
Posted: Wed Jun 04, 2008 4:54 pm
by pcmattman
I would personally suggest using DMA, simply because while you're waiting for the logs to be written your OS will be able to continue receiving packets without any noticeable drop in performance.
If you consider that a sector is 512 bytes, and you send words down the line, that's 256 outw calls (unless you write bytes, in which case it's the full 512). Per sector.
It really is up to you, but the easiest thing to do would be to put together a benchmark, with some flag that makes your system use PIO or DMA. That way you can test with either PIO or DMA and figure out whether the latency of PIO is too much.
EDIT: Additional advantage to writing both a DMA and a PIO based driver is that you'll already have both ready to be used, which might be helpful later on in your project.
Posted: Wed Jun 04, 2008 7:19 pm
by bewing
I'm not so sure. The disk DMA would go through your PCI memory busmastering -- as I'm sure your network packets do too. Writing using PIO uses the IO bus, as we all know. One would assume that the log is going to end up in L1 cache.
So to write through DMA, you'd have to flush the cache to main memory through the Northbridge, then read it over the Southbridge, while fighting the network card for PCI Busmastering time/packets.
But to write it using PIO, the CPU would just have to read it from L1 cache, and pipe it over the IO Port bus ... the main problem with that is that all 512 writes are to the same IO port ... and there are automatic delays built into the IO port bus if you write multiple times to the same port, AFAIK.
It seems like it would depend on just how much support the networking cards need from the IO port bus. If they don't need much, maybe PIO would be better.
Posted: Wed Jun 04, 2008 7:44 pm
by 01000101
Network Card I/O is minimal unless there is a packet/nic error (which there 99.9% of the time isnt). For a normal operation there is one OUT to acknowledge the interrupt and one IN to see if the buffer is empty.