📄 ide_drv.c
字号:
return(FALSE);
}
pc->drive[phys_drive].atapi_packet.generic.lun=0;
pc->drive[phys_drive].atapi_packet.generic.reserved1=
pc->drive[phys_drive].atapi_packet.generic.reserved2=
pc->drive[phys_drive].atapi_packet.generic.reserved3=
pc->drive[phys_drive].atapi_packet.generic.reserved4=0;
/* Now load the rest of the register file. (send command last) */
if(pc->drive[phys_drive].media_descriptor==0xef)
ide_wr_drive_head(pc, (pc->vo_drive_head|0xa0)&0xb0); /* ALAN CDROM */
else
ide_wr_drive_head(pc, pc->vo_drive_head|0xa0); /* 176 Atapi Drive Select */
while((pc->vi_status = ide_rd_status(pc))&(IDE_STB_BUSY|IDE_STB_DRQ)) /* wait till busy off and drq off*/
{
pc->vi_sector_number = ide_rd_sector_number(pc);
if(pc->vi_sector_number&IDE_IRR_CoD)
{
if(pc->vi_sector_number&IDE_IRR_IO)
INWORD(pc->register_file_address + IDE_OFF_DATA); /* read a word */
else
OUTWORD(pc->register_file_address + IDE_OFF_DATA, 0x0000); /* write a word */
}
else
{
if(loop_count)
loop_count--;
else
{
ide_wr_command(pc, IDE_CMD_SOFT_RESET);
loop_count=8;
}
}
}
utemp=pc->drive[phys_drive].atapi_packet.generic.transfer_length.lsb;
utemp += (word)(pc->drive[phys_drive].atapi_packet.generic.transfer_length.msb<<8);
utemp<<=9;
ide_wr_cyl_low(pc, utemp); /* 174 Atapi Byte Count Register (bits 0-7) */
ide_wr_cyl_high(pc, utemp>>8); /* 175 Atapi Byte Count Register (bits 8-15) */
ide_wr_feature(pc, pc->vo_feature);/* 171 Atapi Features */
/* Write the digital output register (interrupts on/off) */
ide_wr_dig_out(pc, pc->vo_dig_out | 0x08);
/* The register file is loaded.Now load the command into the command register. */
ide_wr_command(pc, ATAPI_CMD_PKT);
if(pc->drive[phys_drive].CMD_DRQ_type == 0x01) /* CDROM Alan*/
{
// DRQ type is == 1. drive interrupts when ready for packet
if (!(pc->vo_dig_out & IDE_OUT_IEN)) /* Interupt mode */
{
if (!OS_IDE_SIGNAL_TEST(pc->controller_number, pc->timer))
return(ide_error(pc,IDE_ERC_BUS));
}
else
{
// DRQ type is == 1. but we aren't using interrupt
// This is not guaranteed to always work
if (!ide_wait_not_busy(pc, pc->timer)) /* Polled mode */
return(ide_error(pc,IDE_ERC_BUS));
}
}
else
{
/* CDROM Alan*/
// DRQ type is != 1. drive drops busy and asserts drq
if (!(ide_wait_not_busy(pc, TIMEOUT_TYPICAL) && ide_wait_drq(pc, TIMEOUT_TYPICAL)))
{
pc->vo_command=save_vo_command;
return(ide_error(pc,IDE_ERC_BUS));
} /* CDROM Alan*/
} /* CDROM Alan*/
// DRQ should be set error should be clear
if(!(ide_rd_status(pc)&IDE_STB_DRQ)||(ide_rd_status(pc)&IDE_STB_ERROR))
{
return(ide_error(pc,IDE_ERC_BUS));
}
save_useraddress=pc->user_address;
pc->user_address=(PFBYTE)&pc->drive[phys_drive].atapi_packet;
// if((ide_rd_sector_count(pc)&0x03)!=0x01)
// _asm int 3
if(!ide_out_words(pc, sizeof(ATAPI_PACKET_DESC)>>1)) /* Packet size /2 */
return(ide_error(pc,IDE_ERC_BUS));
pc->user_address=save_useraddress;
if(pc->drive[phys_drive].atapi_packet.generic.op_code==ATAPI_PKT_CMD_FORMAT_UNIT)
{
if(!ide_out_words(pc, sizeof(HIMAWARI_FORMAT_DESCRIPTOR)>>1)) /* Packet size /2 */
{
return(ide_error(pc,IDE_ERC_BUS));
}
}
if (!(pc->vo_dig_out & IDE_OUT_IEN)) /* Interupt mode */
{
if (!OS_IDE_SIGNAL_TEST(pc->controller_number, pc->timer))
return(ide_error(pc,IDE_ERC_BUS));
}
else
{
if (!ide_wait_not_busy(pc, pc->timer)) /* Polled mode */
return(ide_error(pc,IDE_ERC_BUS));
}
if (ide_rd_status(pc)&IDE_STB_ERROR) /* if error */
{
if (save_vo_command != ATAPI_PKT_CMD_TEST_UNIT_READY)
return(ide_error(pc,IDE_ERC_STATUS));
}
words_remaining = ((dword)pc->sectors_remaining)<<10; /* Calculate the number of words (blocks * 1024) CDROM Jerry; I think this is in error in the Himawari Code */
while(ide_rd_status(pc)&IDE_STB_DRQ) /* if DRQ then data to transfer */
{
words_to_transfer =(dword)(((ide_rd_cyl_low(pc))+(ide_rd_cyl_high(pc)<<8))>>1); /* number of words to transfer */
if(words_remaining)
{
if(words_remaining<words_to_transfer)
words_to_transfer=words_remaining;
switch(ide_rd_sector_count(pc)&0x03)
{
case 0x00: /* write to device */
ide_out_words(pc, (word)words_to_transfer);
break;
case 0x02: /* read from device */
ide_in_words(pc, (word)words_to_transfer);
break;
case 0x01:
case 0x03:
return(ide_error(pc,IDE_ERC_BUS));
}
}
else
{
switch(ide_rd_sector_count(pc)&0x03)
{
case 0x00: /* write to device */
dummyWord = 0;
for (i=0; i < words_to_transfer; i++)
OUTWORD(pc->register_file_address + IDE_OFF_DATA,dummyWord);
break;
case 0x02: /* read from device */
for (i=0; i < words_to_transfer; i++)
dummyWord = INWORD(pc->register_file_address + IDE_OFF_DATA);
break;
case 0x01:
case 0x03:
return(ide_error(pc,IDE_ERC_BUS));
}
}
words_remaining -= words_to_transfer;
if(words_remaining)
{
if (!(pc->vo_dig_out & IDE_OUT_IEN)) /* Interupt mode */
{
if (!OS_IDE_SIGNAL_TEST(pc->controller_number, pc->timer))
return(ide_error(pc,IDE_ERC_BUS));
}
else
{
if (!ide_wait_not_busy(pc, pc->timer)) /* Polled mode */
return(ide_error(pc,IDE_ERC_BUS));
}
}
}
pc->vo_command=save_vo_command;
if (ide_rd_status(pc)&IDE_STB_ERROR) /* if error */
return(ide_error(pc,IDE_ERC_STATUS));
if (ide_rd_status(pc)&IDE_STB_DRQ) /* if drq */
return(ide_error(pc,IDE_ERC_BUS));
}
else
#endif /* (IDE_USE_ATAPI) */
{
/* Now load the rest of the register file. (send command last) */
ide_wr_sector_count(pc, pc->vo_sector_count);
ide_wr_sector_number(pc, pc->vo_sector_number);
ide_wr_cyl_low(pc, pc->vo_cyl_low);
ide_wr_cyl_high(pc, pc->vo_cyl_high);
ide_wr_drive_head(pc, pc->vo_drive_head);
ide_wr_feature(pc, pc->vo_feature);
/* Write the digital output register (interrupts on/off) */
ide_wr_dig_out(pc, pc->vo_dig_out);
/* The register file is loaded.Now load the command into the command register. */
ide_wr_command(pc, pc->vo_command);
if ((pc->vo_command == IDE_CMD_WRITES) ||
(pc->vo_command == IDE_CMD_WRITES_NE) ||
(pc->vo_command == IDE_CMD_WRITEM) ||
(pc->vo_command == IDE_CMD_WRITEM_NE) )
{
/* Busy should deassert. DRQ should assert */
if (!(ide_wait_not_busy(pc, pc->timer) && ide_wait_drq(pc, pc->timer)))
{
pc->error_code = IDE_ERC_BUS;
pc->command_complete = TRUE; /* Shesssaaa hung */
return(FALSE);
}
if (pc->sectors_remaining >= (word) pc->block_size)
utemp = (word) pc->block_size;
else
utemp = pc->sectors_remaining;
ide_out_words(pc, (word) (utemp << 8));/* 256 times xfer size */
pc->sectors_remaining -= utemp;
}
/* The NEW SMART WAY OF DOING IT. DOING THE DATA TRANSFER AT THE APP LAYER */
while (!pc->command_complete)
{
if (!(pc->vo_dig_out & IDE_OUT_IEN)) /* Interupt mode */
{
/* Wait for a signal of completion from ide_interrupt. Pass in
pc->timer (# ticks to wait before detecting a timeout */
if (!OS_IDE_SIGNAL_TEST(pc->controller_number, pc->timer))
goto bail;
}
else
{
io_delay(); /* Give time for BUSY to assert */
io_delay();
if (!ide_wait_not_busy(pc, pc->timer)) /* Polled mode */
{
bail:
pc->error_code = IDE_ERC_TIMEOUT;
pc->command_complete = TRUE; /* Shesssaaa hung */
}
}
if (!pc->command_complete)
ide_interrupt(pc->controller_number);
}
}
if (pc->error_code)
return(FALSE);
else
return(TRUE);
}
/* ide_interrupt - Respond to the ide_disk interupt.
* Inputs:
* uses values in cs (the control structure)
* Outputs:
* pc->command_complete and pc->error_code are set. If error_code is non zero
* the command failed.
* Returns:
* Nothing
*
* This routine is called by ide_isr or do_command if it is polling. Its job
* is to
* determine the cause of the IDE disk interrupt and process it correctly.
* On multi block reads and writes it performs the data transfer and returns if
* the multiblock transfer is incomplete. In other cases it checks the status
* bits for errors. If no errors were found pc->error_code is zero other wise
* pc->error_code is set to an appropriate value. If the driver is in interrupt
* mode the task is woken up when command_complete is set.
*
*/
void ide_interrupt(int controller_number) /* __fn__ */
{
word utemp;
PIDE_CONTROLLER pc;
pc = &controller_s[controller_number];
/* Read the status register. This also clears the interrupt status if pending */
pc->vi_status = ide_rd_status(pc);
/* Read the sector count register. We'll need it in reads and writes */
pc->vi_sector_count = ide_rd_sector_count(pc);
/* Check if the drive reported an error */
if (pc->vi_status & IDE_STB_ERROR)
{
// BUGBUGBUG - For READS and READM commands we need to read the data
// to put the controller in command mode
ide_read_register_file(pc);
/* Report the error on all but diagnostipc-> The error bits
are treated differently on this command. */
if (pc->vo_command != IDE_CMD_DIAG)
{
pc->error_code = IDE_ERC_STATUS;
goto io_done_label;
}
}
/* =================================================================== */
/* ================= Now process command completes==================== */
/* =================================================================== */
/* Reads and Write are treated differently from the rest of the commands.
They may recieve multiple interrupts and the performance of this
routine is very important. To pick up some performance we only read
the register file entries that we need.
*/
/* Command::::: IDE_CMD_READM - read multiple, IDE_CMD_READS - read sector(s) */
if((pc->vo_command == IDE_CMD_READM)||(pc->vo_command == IDE_CMD_READS))
{
if (pc->sectors_remaining >= (word) pc->block_size)
utemp = (word) pc->block_size;
else
utemp = pc->sectors_remaining;
//BUGBUGBUG - We should compare the sector count register.
if (!ide_in_words(pc, (word) (utemp << 8)))/* 256 times xfr size */
{
/* Serious problem. Bus state incorrect */
pc->error_code = IDE_ERC_BUS;
goto io_done_label;
}
pc->sectors_remaining -= utemp;
/* see if we've completed transferring all of our blocks */
if (pc->sectors_remaining)
return; /* NOPE - More to come */
else
{
ide_read_register_file(pc);
if (pc->vi_status & IDE_STB_ERROR)
pc->error_code = IDE_ERC_STATUS;
goto io_done_label;
}
}
/* Command::::: IDE_CMD_WRITEM IDE_CMS_WRITES - write multiple, write sectors */
if ((pc->vo_command == IDE_CMD_WRITES) ||
(pc->vo_command == IDE_CMD_WRITES_NE) ||
(pc->vo_command == IDE_CMD_WRITEM) ||
(pc->vo_command == IDE_CMD_WRITEM_NE))
{
if (!pc->sectors_remaining)
{
/* Sector count reg is 0. we're done. We'll read the register
File in case we want to look at the values */
ide_read_register_file(pc);
goto io_done_label;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -