Sector count register for the ATA/ATAPI read command

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
Rivusqc
Posts: 4
Joined: Fri Aug 23, 2019 8:27 am
Freenode IRC: Rivusqc

Sector count register for the ATA/ATAPI read command

Post by Rivusqc »

What is the use of "sector count" register for the ATA/ATAPI read command ?
The description given by ATA/ATAPI specification seems quite straightforward :
Sector Count - number of sectors to be transferred. A value of 00h specifies that 256 sectors are to be transferred.
However, all tutorial and code examples I could find show that we are supposed to read one sector at a time and control ourselves the number of time we do so.
for example, taken from https://wiki.osdev.org/ATA_PIO_Mode
The pio28_read procedure reads one sector and decrements ebx that contains initially the sector count :

Code: Select all

    
    mov cx, 256
    rep insw        ; gulp one 512b sector into edi

 ...
   
    dec ebx         ; decrement the "sectors to read" count 


And pio28_read is called until ebx reaches 0

Code: Select all


.read28:
    test ebx, ebx       ; no more sectors to read?
    je short .r_don
    call pio28_read     ; read up to 256 more sectors, updating registers
    je short .read28    ; if successful, is there more to read?    
.r_don:

Why the ATA controller expects we provide the sector count if we need to control it ourselves anyway ?
(of course it applies to the write function as well. )
User avatar
Octacone
Member
Member
Posts: 1134
Joined: Fri Aug 07, 2015 6:13 am

Re: Sector count register for the ATA/ATAPI read command

Post by Octacone »

I don't know about PIO, since I use DMA.
With DMA you just specify how many sectors you want to read and read them in.
You should consider writing a DMA only driver, PIO is basically a pointless, painfully slow method of communicating with the drive.
DMA is much faster and allows for sequential reads up to 65536 sectors at a time.
OS: Basic OS
About: 32 Bit Monolithic Kernel Written in C++ and Assembly, Custom FAT 32 Bootloader
Rivusqc
Posts: 4
Joined: Fri Aug 23, 2019 8:27 am
Freenode IRC: Rivusqc

Re: Sector count register for the ATA/ATAPI read command

Post by Rivusqc »

Thanks for your answer.

I am very new to OS developement. So far I just have a simple piece of code that runs in pmode and I assumed it was easier to start experimenting with PIO, an that it would not be a big problem on booting. I am aware of DMA vs PIO, and I expect to experiment with that as well.

According to your answer, I guess that the sector count is for DMA only, but the documentation is not really clear on that.
It seems that everbody sets this value while using PIO mode and I don't unserstand why.

regards
Klakap
Member
Member
Posts: 297
Joined: Sat Mar 10, 2018 10:16 am

Re: Sector count register for the ATA/ATAPI read command

Post by Klakap »

Sector count is for defined how many sectors you want read. In PIO48 you can define this for 65536 sectors.

Using PIO in bootloader isnt very good idea. Try use BIOS interrupt in real mode e.g.:

Code: Select all

  ;read usb/cdrom sectors 0 to 50
  mov ax, 0x1000  ;load kernel to 10000h < segment
  mov es, ax  ;load kernel to 10000h
  mov bx, 0  ;offset 0 < segment offset
  mov ah, 0x02  ;read function
  mov al, 50  ;50 sectors < add here your value
  mov ch, 0  ;track 0
  mov cl, 2  ;start sector is 2
  mov dh, 0  ;head 0
  mov dl, 0x00  ;bootable usb/cdrom
  int 13h  ;read
and after that jump into protected mode and run kernel with jmp 0x10000.

PIO vs DMA? Difference is with this: PIO use ports to read/write and eat processor time. DMA is read/write to memory without processor. But if you have good scheduler, PIO can give good results and maybe you dont have to use DMA!

//EDIT: If you looking for code for learn, my operation system is open source https://github.com/Klaykap/LightningOS/ ... vers/ata.c
Rivusqc
Posts: 4
Joined: Fri Aug 23, 2019 8:27 am
Freenode IRC: Rivusqc

Re: Sector count register for the ATA/ATAPI read command

Post by Rivusqc »

Thank you,

I just had a look at your code and it brings me back to my very first question :


you tell the controller the number of sectors to read/write

Code: Select all

 outb(base+2, (unsigned char)(number_of_sectors >> 8));


and yet you need to iterate on this same value

Code: Select all

    for(int i=0; i<number_of_sectors; i++) {
        for (int j=0; j<256; j++) {
            if(type==READ) {
                buffer[offset] = inw(base + 0);
            }
            else {
                outw(base + 0, buffer[offset]);
            }
            offset++;
        }
    }

why the ATA controller needs this value ?
What would be the effect of providing a different value on sector count register (base+2) and number_of_sectors in your loop ?

regards
Klakap
Member
Member
Posts: 297
Joined: Sat Mar 10, 2018 10:16 am

Re: Sector count register for the ATA/ATAPI read command

Post by Klakap »

At first, little comment to my code, I dont choose drive, because you should choose drive only one. You can choose master drive(hard disc are usually on it) with:

Code: Select all

//base is 0x1F0
outb(base+6, 0x40);
on start you operation system.

ABOUT NUMBERS OF SECTORS

If you want read/write from hard disc, you must tell it three things:
1. First sector who you want read
2. Numbers of sectors from first sector
3. If you want read or write

Now read driver code:

Code: Select all

    outb(base+2, (unsigned char)(number_of_sectors >> 8));
    outb(base+2, (unsigned char)number_of_sectors);
I am sending number of sectors. If I want read only 1 sector, same result is with:

Code: Select all

    outb(base+2, 0); //0x0001 >> 8 = 0x00
    outb(base+2, 1); //0x0001 & 0xFF = 0x01
Next code is send first sector and command for read/write.

Now hard disc have all values and it start work. In PIO48 hard disc use port base+0 (0x1F0) for sending data if we reading or getting data if we writing.

One sector have 512 bytes, and port base+0 is word type, than we must read for one sector port base+0 256 times. But sometimes we have in numbers of sectors more sectors than 1 and we must read/write all data. I use two cycles, but too same is:

Code: Select all

	for(int i=0; i< (number_of_sectors * 256); i++) {  //one sector is reading/writing 256 times
        	if(type==READ) {
            	buffer[offset] = inw(base + 0);
        	}
        	else {
            	outw(base + 0, buffer[offset]);
        	}
			offset++;
	}
E. g. You want read 10 sectors. One sector must be read from port base+0 256 times, so you must read base+0 2560 times. Did you see how it work?

Summary: Number of sectors defines how times you must read output for read/ write input for write to port base+0.

If you have heavy head from something, ask me.
Octocontrabass
Member
Member
Posts: 5218
Joined: Mon Mar 25, 2013 7:01 pm

Re: Sector count register for the ATA/ATAPI read command

Post by Octocontrabass »

Rivusqc wrote:However, all tutorial and code examples I could find show that we are supposed to read one sector at a time and control ourselves the number of time we do so.
The drive has an internal buffer where it must hold the sector before you can read it. Very old drives could only hold one sector in the buffer, so you had to wait for the drive to refill the buffer after each sector you read.

For example, to read two sectors, you would set the sector count register to 2, then send your "read" command to the drive, then wait for the buffer to fill, then read one sector, then wait for the buffer to fill again, then read the second sector.

Modern drives have much larger buffers, but they still make you wait after each sector for backwards compatibility.
Rivusqc
Posts: 4
Joined: Fri Aug 23, 2019 8:27 am
Freenode IRC: Rivusqc

Re: Sector count register for the ATA/ATAPI read command

Post by Rivusqc »

That makes sense,
thank you for your answer!
Post Reply