Code: Select all
unsigned char buf[512];
memset(buf,1,512);
transfer(ATA_WRITE_CMD,0x200,1,(unsigned char*)buf);//write one sector data from buf to LBA: 0x200 in disk
memset(buf,0,512);
transfer(ATA_READ_CMD,0x200,1,(unsigned char*)buf);//read one sector data from LBA: 0x200 to buf
for(int i=0;i<512;i++){
printk(RED,YELLOW,"%x ",buf[i]);
}
PS: The only one exception this code works well is when LBA address start with 0, screen can print 512 bytes full 1 array and image file can also preserve the modifications on the first sector.
Here is core code for function transfer:
Code: Select all
switch(node->cmd){
case ATA_WRITE_CMD:
io_out8(PORT_DISK0_DEVICE,0x40);
// 48 bits LBA address, should divide in to two part and send each of them
io_out8(PORT_DISK0_ERR_FEATURE,0);
io_out8(PORT_DISK0_SECTOR_CNT, (node->count>>8) &0xff);
io_out8(PORT_DISK0_SECTOR_LOW, (node->LBA>>24) &0xff);
io_out8(PORT_DISK0_SECTOR_MID, (node->LBA>>32) &0xff);
io_out8(PORT_DISK0_SECTOR_HIGH, (node->LBA>>40) &0xff);
io_out8(PORT_DISK0_ERR_FEATURE,0);
io_out8(PORT_DISK0_SECTOR_CNT, (node->count) &0xff);
io_out8(PORT_DISK0_SECTOR_LOW, (node->LBA) &0xff);
io_out8(PORT_DISK0_SECTOR_MID, (node->LBA>>8) &0xff);
io_out8(PORT_DISK0_SECTOR_HIGH, (node->LBA>>16) &0xff);
//if disk not ready, wait
while(!(io_in8(PORT_DISK0_STATUS_CMD)&DISK_STATUS_READY)){
nop();
}
io_out8(PORT_DISK0_STATUS_CMD,node->cmd);
//if disk not require for data, wait
while(!(io_in8(PORT_DISK0_STATUS_CMD)&DISK_STATUS_REQ)){
nop();
}
port_outsw(PORT_DISK0_DATA,node->buffer,256);
break;
case ATA_READ_CMD:
io_out8(PORT_DISK0_DEVICE,0x40);
io_out8(PORT_DISK0_ERR_FEATURE,0);
io_out8(PORT_DISK0_SECTOR_CNT, (node->count>>8) &0xff);
io_out8(PORT_DISK0_SECTOR_LOW, (node->LBA>>24) &0xff);
io_out8(PORT_DISK0_SECTOR_MID, (node->LBA>>32) &0xff);
io_out8(PORT_DISK0_SECTOR_HIGH, (node->LBA>>40) &0xff);
io_out8(PORT_DISK0_ERR_FEATURE,0);
io_out8(PORT_DISK0_SECTOR_CNT, (node->count) &0xff);
io_out8(PORT_DISK0_SECTOR_LOW, (node->LBA) &0xff);
io_out8(PORT_DISK0_SECTOR_MID, (node->LBA>>8) &0xff);
io_out8(PORT_DISK0_SECTOR_HIGH, (node->LBA>>16) &0xff);
//if disk not ready, wait
while(!io_in8(PORT_DISK0_STATUS_CMD)&DISK_STATUS_READY){
nop();
}
io_out8(PORT_DISK0_STATUS_CMD,node->cmd);
break;
default:
printk(BLACK,WHITE,"ATA CMD ERROR\n");
break;
}
Code: Select all
/*
cmd: ATA_READ_CMD or ATA_WRITE_CMD
blocks: LBA address
count: number of sectors
*buffer: I/O buffer address
*/
unsigned long transfer(long cmd, unsigned long blocks, long count, unsigned char *buffer){