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.
I have looked at the AHCI spec as well as the AHCI article on osdev wiki (http://wiki.osdev.org/AHCI) but I am very confused about one simple thing. I am sending the IDENTIFY commands follows:
// we must now identify the device to find out its size
// just use the first header
cmdhead->cfl = sizeof(FIS_REG_H2D)/4;
cmdhead->w = 0;
cmdhead->prdtl = 1;
cmdhead->p = 1;
AHCICommandTable *cmdtbl =
(AHCICommandTable*) ((char*)dmaGetPtr(&dev->dmabuf) + 1024+256+8*1024);
memset(cmdtbl, 0, sizeof(AHCICommandTable));
cmdtbl->prdt_entry[0].dba = dmaGetPhys(&dev->iobuf);
cmdtbl->prdt_entry[0].dbc = 2048;
cmdtbl->prdt_entry[0].i = 1; // interrupt when identify complete
FIS_REG_H2D *cmdfis = (FIS_REG_H2D*) cmdtbl->cfis;
cmdfis->fis_type = FIS_TYPE_REG_H2D;
cmdfis->c = 1;
cmdfis->command = ATA_CMD_IDENTIFY;
__sync_synchronize();
port->ci = 1;
__sync_synchronize();
kprintf("IDENTIFY command sent\n");
while (1)
{
if ((port->ci & 1) == 0)
{
break;
};
__sync_synchronize();
};
kprintf("IDENTIFY command complete\n");
uint32_t size = *((uint32_t*)((char*)dmaGetPtr(&dev->iobuf) + ATA_IDENT_MAX_LBA_EXT));
kprintf("Size in MB: %d\n", (int) (size * 512 / 1024 / 1024));
It reports the size in MB to be 0 (the drive is actually 4GB). If I use ATA_IDENT_MAX_LBA instead of ATA_IDENT_MAX_LBA_EXT, it also reports 0. I therefore assume that the IDENTIFY data is in fact not loaded into the buffer specified by the PRDT??? In that case, how do I extract the IDENTIFY structure so I can find the disk size?
Check your port interrupt status register for errors. If the error flag is set, that would explain why you are getting a zero back.
Project: OZone
Source: GitHub
Current Task: LIB/OBJ file support
"The more they overthink the plumbing, the easier it is to stop up the drain." - Montgomery Scott
I now fixed it so that it does memset(cmdfis, 0, sizeof(FIS_REG_H2D)) beofre filling in the structure, and also set the size dbc to 511 as suggested, but it's still givving exactly the same result.
I have decided to do a dump of the iobuf, and I have attached the screenshot. There is obviously something in the data.
Hmm, my offsets were correct (I gave them in bytes). I changed the pointer arithmetic a bit, so that I cast to uint8_t* in one step and then dereference the various fields in later steps, and somehow it works. Not sure where the mistake was.
mariuszp wrote:i call __sync_synchronize() to prevent optimisations from messing with the i/o
I see. I don't know why it's happened. I don't see UB in this code. However, there may be a problem with bit fields (I did not encounter itself). Bit fields are not recommended use for MMIO.