Before this I've got PIO READ working, i think most of the procedure should be similar, but I just can't get it to read things.
I tried reading the Bus Master Status Register, the interrupt bit is 1, error bit is 0, active bit is 1, which means the transfer has not finished yet.
Why would this happen ? I've set up a prdt table containing only one entry and have set the EOT bit.
Also, any advice on how to debug this kind of problem(like looking at what register would tell me what's going on and why)
Code: Select all
char * ata_read_sector(ata_dev_t * dev, uint32_t lba) {
char * buf = kmalloc(SECTOR_SIZE);
// Reset bus master register's command register
outportb(dev->BMR_COMMAND, 0);
// Clear interrupt bit and error bit in status register
outportb(dev->bar4 + 0x2, inportb(dev->bar4 + 0x02) | 0x04 | 0x02);
// Set prdt
outportl(dev->BMR_prdt, (uint32_t)dev->prdt_phys);
// Set DMA in Read mode
//outportb(dev->BMR_COMMAND, 0x08);
// Wait until ata device is ready
wait_device_ready(dev);
// Allow ata device interrupts
outportb(dev->alt_status, 0);
// Send 0xE0 for the "master" or 0xF0 for the "slave", ORed with the highest 4 bits of the LBA to port 0x1F6
outportb(dev->drive, ((0xE + dev->slave) << 4) | ((lba >> 24) & 0xf) );
outportb(dev->error, 0);
outportb(dev->sector_count, 1); // ??
outportb(dev->lba_lo, lba & 0xff);
outportb(dev->lba_mid, (lba & 0xff00) >> 8);
outportb(dev->lba_high, (lba & 0xff0000) >> 16);
/*
Uncomment this to do PIO read
outportb(dev->command, ATA_CMD_READ_PIO);
int times = 0;
unsigned short * sbuf = (void*)buf;
while (times < 256) {
unsigned short data = inports(dev->data);
sbuf[times] = data;
times++;
}
return buf;
*/
printf("0x%p\n", dev->prdt_phys);
printf("prdt[0] pbuffer: 0x%p vbuffer: 0x%p, size: %u, mark: %u\n", dev->prdt[0].buffer_phys, dev->mem_buffer, dev->prdt[0].transfer_size, dev->prdt[0].mark_end);
printf("phys of 0xc0402000 is %p\n", virtual2phys(kpage_dir, (void*)0xc0402000));
outportb(dev->command, 0xC8);
inportb(dev->BMR_COMMAND);
inportb(dev->BMR_STATUS);
outportb(dev->BMR_COMMAND, 9);
uint8_t t;
while(1) {
t = inportb(dev->BMR_STATUS);
if(t & BMR_STATUS_INT)
break;
}
printf("interrupt bit set\n");
io_wait(dev);
for(int i = 1000*1000; i >= 0; i--) {
for(int j = 0; j < 10000; j++);
}
for(int i = 0; i < 100; i++) {
int c = dev->mem_buffer[i];
printf("%d ", c);
}
printf("\n");
memcpy(buf, dev->mem_buffer, SECTOR_SIZE);
return buf;
}
https://github.com/szhou42/simpleos/blo ... /src/ata.c
https://github.com/szhou42/simpleos/blo ... lude/ata.h
Thanks in advance.