Unable to read sector for atapi device
Posted: Sat Dec 07, 2013 12:38 pm
Hi, I am writing a atapi driver to implement iso9660 filesystem but after reading a sector i am unable to read the same sector or any other sector
above is the code to read a sector from atapi device
for the first time i can read the sector properly ie i am able to see all the directories and files in the root dir but if i try to read the root dir again or some sub dir only 0xc bytes are transferred
so what am i missing here ??
PS i know IRQ should be used for transfer but interrupt is fired too quickly before the scheduler can queue the process to the driver queue
Code: Select all
void atapi_read_pio(u32int bus, u32int drive, u32int lba, u32int num_lba,u8int *buffer)
{
u8int read_pkt[12] = {0,0, 0, 0,0, 0, 0, 0, 0, 0, 0, 0 };
read_pkt[2] = (lba >> 0x18) & 0xFF; /* most sig. byte of LBA */
read_pkt[3] = (lba >> 0x10) & 0xFF;
read_pkt[4] = (lba >> 0x08) & 0xFF;
read_pkt[5] = (lba >> 0x00) & 0xFF; /* least sig. byte of LBA */
if(num_lba > 0xFFFF)
{
//read12 command
read_pkt[0] = ATAPI_READ12_CMD;
read_pkt[6] = (num_lba >> 0x18) & 0xFF; //msb transfer len
read_pkt[7] = (num_lba >> 0x10) & 0xFF;
read_pkt[8] = (num_lba >> 0x08) & 0xFF;
read_pkt[9] = (num_lba >> 0x00) & 0xFF; //lsb transfer len
}
else
{
//read10 command
read_pkt[0] = ATAPI_READ10_CMD;
read_pkt[7] = (num_lba >> 0x08) & 0xFF; //msb transfer len
read_pkt[8] = (num_lba >> 0x00) & 0xFF; //lsb transfer len
}
//atapi pkt req 6 words to be pushed not 12 bytes
u16int read_pkt_w[6];
int i,j;
for(i=0,j=0;i<6;i++,j+=2)
read_pkt_w[i] = read_pkt[j+1]<<8 | read_pkt[j];
//Selecting up device to be read from
outportb(ATA_DRIVE_SELECT_PORT(bus),drive);
outportb(ATA_FEATURES_PORT(bus),0);
outportb (ATA_LBA_MID_PORT(bus), ATAPI_SECTOR_SIZE & 0xFF);
outportb (ATA_LBA_HI_PORT(bus), ATAPI_SECTOR_SIZE >> 8);
//ATATPI PKT cmd
outportb(ATA_COMMAND_PORT(bus),ATAPI_PKT_CMD);
//waiting for dev to get ready
while((inportb(ATA_STATUS_PORT(bus)) & ATA_STATUS_REG_BSY)
&& !(inportb(ATA_STATUS_PORT(bus)) & ATA_STATUS_REG_DRQ) );
//pushing the packet to the data port
for(i=0;i<6;i++)
outportw(ATA_DATA_PORT(bus),read_pkt_w[i]);
//IRQ response wait***not implemented
while((inportb(ATA_STATUS_PORT(bus)) & ATA_STATUS_REG_BSY)
&& !(inportb(ATA_STATUS_PORT(bus)) & ATA_STATUS_REG_DRQ) );
if(( inportb(ATA_STATUS_PORT(bus)) & ATA_STATUS_REG_ERR))kprintf("WTF JJJJJJJJ");
//timer_wait(12);
//a=true;
//wait_for_interrupt();
//Actual size that is to transferred
u32int size =
(((u32int) inportb (ATA_LBA_HI_PORT (bus))) << 8) | (u32int) (inportb (ATA_LBA_MID_PORT (bus)));
kprintf("\nActual Size to be transferred 0x%x",size);
u16int words = size/2;
//transferring data
u16int temp;
for(i=0,j=0;i<words;i++)
{
temp = inportw (ATA_DATA_PORT (bus));
buffer[j++] = temp & 0xFF;
buffer[j++] = (temp>>8) & 0xFF;
}
}
Code: Select all
iso9660_vol_desc_primary *pri;
iso9660_vol_desc *vol_desc = (iso9660_vol_desc *)kmalloc(sizeof(iso9660_vol_desc));
atapi_read_pio(bus, drive, ISO9660_VOL_DESC_START_SECTOR+0, 1,(u8int *)vol_desc);
pri = (iso9660_vol_desc_primary *)vol_desc;
iso9660_dir_record root_dir = (iso9660_dir_record)&pri->root_dir_entry;
iso9660_dir_table root = (iso9660_dir_table)kmalloc(ISO9660_LOGICAL_SECTOR_SIZE); //*******
atapi_read_pio(bus, drive, iso9660_dir_record_get_lba(root_dir),1,root);
so what am i missing here ??
PS i know IRQ should be used for transfer but interrupt is fired too quickly before the scheduler can queue the process to the driver queue