Renamed ide_qrequest *qrequest into ata_request *request.
Removed synced pcs. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23331 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
6e796d9fbe
commit
5558f70663
@ -126,7 +126,7 @@ ata_wait_for_drdy(ide_bus_info *bus)
|
|||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ata_send_command(ide_device_info *device, ide_qrequest *qrequest,
|
ata_send_command(ide_device_info *device, ata_request *request,
|
||||||
bool need_drdy, uint32 timeout, ata_bus_state new_state)
|
bool need_drdy, uint32 timeout, ata_bus_state new_state)
|
||||||
{
|
{
|
||||||
ide_bus_info *bus = device->bus;
|
ide_bus_info *bus = device->bus;
|
||||||
@ -137,9 +137,9 @@ ata_send_command(ide_device_info *device, ide_qrequest *qrequest,
|
|||||||
|
|
||||||
ASSERT(new_state == ata_state_pio); // XXX only pio for now
|
ASSERT(new_state == ata_state_pio); // XXX only pio for now
|
||||||
|
|
||||||
FLOW("ata_send_command: %d:%d, qrequest %p, request %p, tf %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
|
FLOW("ata_send_command: %d:%d, request %p, ccb %p, tf %02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x\n",
|
||||||
device->target_id, device->is_device1,
|
device->target_id, device->is_device1,
|
||||||
qrequest, qrequest ? qrequest->request : NULL,
|
request, request ? request->ccb : NULL,
|
||||||
device->tf.raw.r[0], device->tf.raw.r[1], device->tf.raw.r[2],
|
device->tf.raw.r[0], device->tf.raw.r[1], device->tf.raw.r[2],
|
||||||
device->tf.raw.r[3], device->tf.raw.r[4], device->tf.raw.r[5],
|
device->tf.raw.r[3], device->tf.raw.r[4], device->tf.raw.r[5],
|
||||||
device->tf.raw.r[6], device->tf.raw.r[7], device->tf.raw.r[8],
|
device->tf.raw.r[6], device->tf.raw.r[7], device->tf.raw.r[8],
|
||||||
@ -348,25 +348,25 @@ check_rw_status(ide_device_info *device, bool drqStatus)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ata_dpc_PIO(ide_qrequest *qrequest)
|
ata_dpc_PIO(ata_request *request)
|
||||||
{
|
{
|
||||||
ide_device_info *device = qrequest->device;
|
ide_device_info *device = request->device;
|
||||||
uint32 timeout = qrequest->request->timeout > 0 ?
|
uint32 timeout = request->ccb->timeout > 0 ?
|
||||||
qrequest->request->timeout : IDE_STD_TIMEOUT;
|
request->ccb->timeout : IDE_STD_TIMEOUT;
|
||||||
|
|
||||||
SHOW_FLOW0(3, "");
|
SHOW_FLOW0(3, "");
|
||||||
|
|
||||||
if (check_rw_error(device, qrequest)
|
if (check_rw_error(device, request)
|
||||||
|| !check_rw_status(device, qrequest->is_write ? device->left_blocks > 0 : true))
|
|| !check_rw_status(device, request->is_write ? device->left_blocks > 0 : true))
|
||||||
{
|
{
|
||||||
// failure reported by device
|
// failure reported by device
|
||||||
SHOW_FLOW0( 3, "command finished unsuccessfully" );
|
SHOW_FLOW0( 3, "command finished unsuccessfully" );
|
||||||
|
|
||||||
finish_checksense(qrequest);
|
finish_checksense(request);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qrequest->is_write) {
|
if (request->is_write) {
|
||||||
if (device->left_blocks == 0) {
|
if (device->left_blocks == 0) {
|
||||||
// this was the end-of-transmission IRQ
|
// this was the end-of-transmission IRQ
|
||||||
SHOW_FLOW0(3, "write access finished");
|
SHOW_FLOW0(3, "write access finished");
|
||||||
@ -395,7 +395,7 @@ ata_dpc_PIO(ide_qrequest *qrequest)
|
|||||||
// having a too short data buffer shouldn't happen here
|
// having a too short data buffer shouldn't happen here
|
||||||
// anyway - we are prepared
|
// anyway - we are prepared
|
||||||
SHOW_FLOW0(3, "Writing one block");
|
SHOW_FLOW0(3, "Writing one block");
|
||||||
if (write_PIO_block(qrequest, 512) == B_ERROR)
|
if (write_PIO_block(request, 512) == B_ERROR)
|
||||||
goto finish_cancel_timeout;
|
goto finish_cancel_timeout;
|
||||||
|
|
||||||
--device->left_blocks;
|
--device->left_blocks;
|
||||||
@ -407,13 +407,13 @@ ata_dpc_PIO(ide_qrequest *qrequest)
|
|||||||
|
|
||||||
// see write
|
// see write
|
||||||
SHOW_FLOW0( 3, "Reading one block" );
|
SHOW_FLOW0( 3, "Reading one block" );
|
||||||
if (read_PIO_block(qrequest, 512) == B_ERROR)
|
if (read_PIO_block(request, 512) == B_ERROR)
|
||||||
goto finish_cancel_timeout;
|
goto finish_cancel_timeout;
|
||||||
|
|
||||||
--device->left_blocks;
|
--device->left_blocks;
|
||||||
|
|
||||||
if (device->left_blocks == 0) {
|
if (device->left_blocks == 0) {
|
||||||
// at end of transmission, wait for data request going low
|
// at end of transmission, wait for data ccb going low
|
||||||
SHOW_FLOW0( 3, "Waiting for device to finish transmission" );
|
SHOW_FLOW0( 3, "Waiting for device to finish transmission" );
|
||||||
|
|
||||||
if (!wait_for_drqdown(device))
|
if (!wait_for_drqdown(device))
|
||||||
@ -430,26 +430,26 @@ finish_cancel_timeout:
|
|||||||
cancel_irq_timeout(device->bus);
|
cancel_irq_timeout(device->bus);
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
finish_checksense(qrequest);
|
finish_checksense(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
/** DPC called when IRQ was fired at end of DMA transmission */
|
/** DPC called when IRQ was fired at end of DMA transmission */
|
||||||
|
|
||||||
void
|
void
|
||||||
ata_dpc_DMA(ide_qrequest *qrequest)
|
ata_dpc_DMA(ata_request *request)
|
||||||
{
|
{
|
||||||
ide_device_info *device = qrequest->device;
|
ide_device_info *device = request->device;
|
||||||
bool dma_success, dev_err;
|
bool dma_success, dev_err;
|
||||||
|
|
||||||
dma_success = finish_dma(device);
|
dma_success = finish_dma(device);
|
||||||
dev_err = check_rw_error(device, qrequest);
|
dev_err = check_rw_error(device, request);
|
||||||
|
|
||||||
if (dma_success && !dev_err) {
|
if (dma_success && !dev_err) {
|
||||||
// reset error count if DMA worked
|
// reset error count if DMA worked
|
||||||
device->DMA_failures = 0;
|
device->DMA_failures = 0;
|
||||||
qrequest->request->data_resid = 0;
|
request->ccb->data_resid = 0;
|
||||||
finish_checksense(qrequest);
|
finish_checksense(request);
|
||||||
} else {
|
} else {
|
||||||
SHOW_ERROR0( 2, "Error in DMA transmission" );
|
SHOW_ERROR0( 2, "Error in DMA transmission" );
|
||||||
|
|
||||||
@ -461,20 +461,20 @@ ata_dpc_DMA(ide_qrequest *qrequest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// reset queue in case queuing is active
|
// reset queue in case queuing is active
|
||||||
finish_reset_queue(qrequest);
|
finish_reset_queue(request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// list of LBA48 opcodes
|
// list of LBA48 opcodes
|
||||||
static uint8 cmd_48[2][2] = {
|
static const uint8 cmd_48[2][2] = {
|
||||||
{ IDE_CMD_READ_SECTORS_EXT, IDE_CMD_WRITE_SECTORS_EXT },
|
{ IDE_CMD_READ_SECTORS_EXT, IDE_CMD_WRITE_SECTORS_EXT },
|
||||||
{ IDE_CMD_READ_DMA_EXT, IDE_CMD_WRITE_DMA_EXT }
|
{ IDE_CMD_READ_DMA_EXT, IDE_CMD_WRITE_DMA_EXT }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// list of normal LBA opcodes
|
// list of normal LBA opcodes
|
||||||
static uint8 cmd_28[2][2] = {
|
static const uint8 cmd_28[2][2] = {
|
||||||
{ IDE_CMD_READ_SECTORS, IDE_CMD_WRITE_SECTORS },
|
{ IDE_CMD_READ_SECTORS, IDE_CMD_WRITE_SECTORS },
|
||||||
{ IDE_CMD_READ_DMA, IDE_CMD_WRITE_DMA }
|
{ IDE_CMD_READ_DMA, IDE_CMD_WRITE_DMA }
|
||||||
};
|
};
|
||||||
@ -483,7 +483,7 @@ static uint8 cmd_28[2][2] = {
|
|||||||
/** create IDE read/write command */
|
/** create IDE read/write command */
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
create_rw_taskfile(ide_device_info *device, ide_qrequest *qrequest,
|
create_rw_taskfile(ide_device_info *device, ata_request *request,
|
||||||
uint64 pos, size_t length, bool write)
|
uint64 pos, size_t length, bool write)
|
||||||
{
|
{
|
||||||
SHOW_FLOW0( 3, "" );
|
SHOW_FLOW0( 3, "" );
|
||||||
@ -514,7 +514,7 @@ create_rw_taskfile(ide_device_info *device, ide_qrequest *qrequest,
|
|||||||
device->tf.lba48.lba_24_31 = (pos >> 24) & 0xff;
|
device->tf.lba48.lba_24_31 = (pos >> 24) & 0xff;
|
||||||
device->tf.lba48.lba_32_39 = (pos >> 32) & 0xff;
|
device->tf.lba48.lba_32_39 = (pos >> 32) & 0xff;
|
||||||
device->tf.lba48.lba_40_47 = (pos >> 40) & 0xff;
|
device->tf.lba48.lba_40_47 = (pos >> 40) & 0xff;
|
||||||
device->tf.lba48.command = cmd_48[qrequest->uses_dma][write];
|
device->tf.lba48.command = cmd_48[request->uses_dma][write];
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// normal LBA
|
// normal LBA
|
||||||
@ -536,7 +536,7 @@ create_rw_taskfile(ide_device_info *device, ide_qrequest *qrequest,
|
|||||||
device->tf.lba.lba_8_15 = (pos >> 8) & 0xff;
|
device->tf.lba.lba_8_15 = (pos >> 8) & 0xff;
|
||||||
device->tf.lba.lba_16_23 = (pos >> 16) & 0xff;
|
device->tf.lba.lba_16_23 = (pos >> 16) & 0xff;
|
||||||
device->tf.lba.lba_24_27 = (pos >> 24) & 0xf;
|
device->tf.lba.lba_24_27 = (pos >> 24) & 0xf;
|
||||||
device->tf.lba.command = cmd_28[qrequest->uses_dma][write];
|
device->tf.lba.command = cmd_28[request->uses_dma][write];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -576,7 +576,7 @@ create_rw_taskfile(ide_device_info *device, ide_qrequest *qrequest,
|
|||||||
device->tf.chs.sector_number = (cylinder_offset % infoblock->current_sectors + 1) & 0xff;
|
device->tf.chs.sector_number = (cylinder_offset % infoblock->current_sectors + 1) & 0xff;
|
||||||
device->tf.chs.head = cylinder_offset / infoblock->current_sectors;
|
device->tf.chs.head = cylinder_offset / infoblock->current_sectors;
|
||||||
|
|
||||||
device->tf.chs.command = cmd_28[qrequest->uses_dma][write];
|
device->tf.chs.command = cmd_28[request->uses_dma][write];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,44 +594,44 @@ err:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
ata_send_rw(ide_device_info *device, ide_qrequest *qrequest,
|
ata_send_rw(ide_device_info *device, ata_request *request,
|
||||||
uint64 pos, size_t length, bool write)
|
uint64 pos, size_t length, bool write)
|
||||||
{
|
{
|
||||||
ide_bus_info *bus = device->bus;
|
ide_bus_info *bus = device->bus;
|
||||||
uint32 timeout;
|
uint32 timeout;
|
||||||
|
|
||||||
// make a copy first as settings may get changed by user during execution
|
// make a copy first as settings may get changed by user during execution
|
||||||
qrequest->is_write = write;
|
request->is_write = write;
|
||||||
qrequest->uses_dma = device->DMA_enabled;
|
request->uses_dma = device->DMA_enabled;
|
||||||
|
|
||||||
if (qrequest->uses_dma) {
|
if (request->uses_dma) {
|
||||||
if (!prepare_dma(device, qrequest)) {
|
if (!prepare_dma(device, request)) {
|
||||||
// fall back to PIO on error
|
// fall back to PIO on error
|
||||||
|
|
||||||
qrequest->uses_dma = false;
|
request->uses_dma = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!qrequest->uses_dma) {
|
if (!request->uses_dma) {
|
||||||
prep_PIO_transfer(device, qrequest);
|
prep_PIO_transfer(device, request);
|
||||||
device->left_blocks = length;
|
device->left_blocks = length;
|
||||||
}
|
}
|
||||||
|
|
||||||
// compose command
|
// compose command
|
||||||
if (!create_rw_taskfile(device, qrequest, pos, length, write))
|
if (!create_rw_taskfile(device, request, pos, length, write))
|
||||||
goto err_setup;
|
goto err_setup;
|
||||||
|
|
||||||
// if no timeout is specified, use standard
|
// if no timeout is specified, use standard
|
||||||
timeout = qrequest->request->timeout > 0 ?
|
timeout = request->ccb->timeout > 0 ?
|
||||||
qrequest->request->timeout : IDE_STD_TIMEOUT;
|
request->ccb->timeout : IDE_STD_TIMEOUT;
|
||||||
|
|
||||||
if (ata_send_command(device, qrequest, !device->is_atapi, timeout,
|
if (ata_send_command(device, request, !device->is_atapi, timeout,
|
||||||
qrequest->uses_dma ? ata_state_dma : ata_state_pio) != B_OK)
|
request->uses_dma ? ata_state_dma : ata_state_pio) != B_OK)
|
||||||
goto err_send;
|
goto err_send;
|
||||||
|
|
||||||
if (qrequest->uses_dma) {
|
if (request->uses_dma) {
|
||||||
|
|
||||||
start_dma_wait_no_lock(device, qrequest);
|
start_dma_wait_no_lock(device, request);
|
||||||
} else {
|
} else {
|
||||||
// on PIO read, we start with waiting, on PIO write we can
|
// on PIO read, we start with waiting, on PIO write we can
|
||||||
// transmit data immediately; we let the service thread do
|
// transmit data immediately; we let the service thread do
|
||||||
@ -639,7 +639,7 @@ ata_send_rw(ide_device_info *device, ide_qrequest *qrequest,
|
|||||||
// immediately (this optimisation really pays on SMP systems
|
// immediately (this optimisation really pays on SMP systems
|
||||||
// only)
|
// only)
|
||||||
SHOW_FLOW0(3, "Ready for PIO");
|
SHOW_FLOW0(3, "Ready for PIO");
|
||||||
if (qrequest->is_write) {
|
if (request->is_write) {
|
||||||
SHOW_FLOW0(3, "Scheduling write DPC");
|
SHOW_FLOW0(3, "Scheduling write DPC");
|
||||||
scsi->schedule_dpc(bus->scsi_cookie, bus->irq_dpc, ide_dpc, bus);
|
scsi->schedule_dpc(bus->scsi_cookie, bus->irq_dpc, ide_dpc, bus);
|
||||||
}
|
}
|
||||||
@ -649,19 +649,19 @@ ata_send_rw(ide_device_info *device, ide_qrequest *qrequest,
|
|||||||
|
|
||||||
err_setup:
|
err_setup:
|
||||||
// error during setup
|
// error during setup
|
||||||
if (qrequest->uses_dma)
|
if (request->uses_dma)
|
||||||
abort_dma(device, qrequest);
|
abort_dma(device, request);
|
||||||
|
|
||||||
finish_checksense(qrequest);
|
finish_checksense(request);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
err_send:
|
err_send:
|
||||||
// error during/after send;
|
// error during/after send;
|
||||||
// in this case, the device discards queued request automatically
|
// in this case, the device discards queued ccb automatically
|
||||||
if (qrequest->uses_dma)
|
if (request->uses_dma)
|
||||||
abort_dma(device, qrequest);
|
abort_dma(device, request);
|
||||||
|
|
||||||
finish_reset_queue(qrequest);
|
finish_reset_queue(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -670,7 +670,7 @@ err_send:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
bool
|
bool
|
||||||
check_rw_error(ide_device_info *device, ide_qrequest *qrequest)
|
check_rw_error(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
ide_bus_info *bus = device->bus;
|
ide_bus_info *bus = device->bus;
|
||||||
@ -694,7 +694,7 @@ check_rw_error(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qrequest->is_write) {
|
if (request->is_write) {
|
||||||
if ((error & ide_error_wp) != 0) {
|
if ((error & ide_error_wp) != 0) {
|
||||||
set_sense(device, SCSIS_KEY_DATA_PROTECT, SCSIS_ASC_WRITE_PROTECTED);
|
set_sense(device, SCSIS_KEY_DATA_PROTECT, SCSIS_ASC_WRITE_PROTECTED);
|
||||||
return true;
|
return true;
|
||||||
@ -995,7 +995,6 @@ status_t
|
|||||||
ata_read_infoblock(ide_device_info *device, bool isAtapi)
|
ata_read_infoblock(ide_device_info *device, bool isAtapi)
|
||||||
{
|
{
|
||||||
ide_bus_info *bus = device->bus;
|
ide_bus_info *bus = device->bus;
|
||||||
int status;
|
|
||||||
|
|
||||||
TRACE("ata_read_infoblock: bus %p, device %d, isAtapi %d\n", device->bus, device->is_device1, isAtapi);
|
TRACE("ata_read_infoblock: bus %p, device %d, isAtapi %d\n", device->bus, device->is_device1, isAtapi);
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
return: true - device reported error
|
return: true - device reported error
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
check_packet_error(ide_device_info *device, ide_qrequest *qrequest)
|
check_packet_error(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
ide_bus_info *bus = device->bus;
|
ide_bus_info *bus = device->bus;
|
||||||
int status;
|
int status;
|
||||||
@ -78,7 +78,7 @@ check_packet_error(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
// tell SCSI layer that sense must be requested
|
// tell SCSI layer that sense must be requested
|
||||||
// (we don't take care of auto-sense ourselve)
|
// (we don't take care of auto-sense ourselve)
|
||||||
device->subsys_status = SCSI_REQ_CMP_ERR;
|
device->subsys_status = SCSI_REQ_CMP_ERR;
|
||||||
qrequest->request->device_status = SCSI_STATUS_CHECK_CONDITION;
|
request->ccb->device_status = SCSI_STATUS_CHECK_CONDITION;
|
||||||
// reset pending emulated sense - its overwritten by a real one
|
// reset pending emulated sense - its overwritten by a real one
|
||||||
device->combined_sense = 0;
|
device->combined_sense = 0;
|
||||||
return true;
|
return true;
|
||||||
@ -90,14 +90,14 @@ check_packet_error(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
|
|
||||||
/*! IRQ handler of packet transfer (executed as DPC) */
|
/*! IRQ handler of packet transfer (executed as DPC) */
|
||||||
void
|
void
|
||||||
packet_dpc(ide_qrequest *qrequest)
|
packet_dpc(ata_request *request)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
ide_device_info *device = qrequest->device;
|
ide_device_info *device = request->device;
|
||||||
ide_bus_info *bus = device->bus;
|
ide_bus_info *bus = device->bus;
|
||||||
int status;
|
int status;
|
||||||
uint32 timeout = qrequest->request->timeout > 0 ?
|
uint32 timeout = request->ccb->timeout > 0 ?
|
||||||
qrequest->request->timeout : IDE_STD_TIMEOUT;
|
request->ccb->timeout : IDE_STD_TIMEOUT;
|
||||||
|
|
||||||
SHOW_FLOW0(3, "");
|
SHOW_FLOW0(3, "");
|
||||||
|
|
||||||
@ -106,9 +106,9 @@ packet_dpc(ide_qrequest *qrequest)
|
|||||||
|
|
||||||
status = bus->controller->get_altstatus(bus->channel_cookie);
|
status = bus->controller->get_altstatus(bus->channel_cookie);
|
||||||
|
|
||||||
if (qrequest->packet_irq) {
|
if (request->packet_irq) {
|
||||||
// device requests packet
|
// device requests packet
|
||||||
qrequest->packet_irq = false;
|
request->packet_irq = false;
|
||||||
|
|
||||||
if (!device->tf.packet_res.cmd_or_data
|
if (!device->tf.packet_res.cmd_or_data
|
||||||
|| device->tf.packet_res.input_or_output
|
|| device->tf.packet_res.input_or_output
|
||||||
@ -132,7 +132,7 @@ packet_dpc(ide_qrequest *qrequest)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qrequest->uses_dma) {
|
if (request->uses_dma) {
|
||||||
// DMA transmission finished
|
// DMA transmission finished
|
||||||
bool dma_err, dev_err;
|
bool dma_err, dev_err;
|
||||||
|
|
||||||
@ -142,13 +142,13 @@ packet_dpc(ide_qrequest *qrequest)
|
|||||||
SHOW_FLOW0(3, "DMA done");
|
SHOW_FLOW0(3, "DMA done");
|
||||||
|
|
||||||
dma_err = !finish_dma(device);
|
dma_err = !finish_dma(device);
|
||||||
dev_err = check_packet_error(device, qrequest);
|
dev_err = check_packet_error(device, request);
|
||||||
|
|
||||||
// what to do if both the DMA controller and the device reports an error?
|
// what to do if both the DMA controller and the device reports an error?
|
||||||
// let's assume that the DMA controller got problems because there was a
|
// let's assume that the DMA controller got problems because there was a
|
||||||
// device error, so we ignore the dma error and use the device error instead
|
// device error, so we ignore the dma error and use the device error instead
|
||||||
if (dev_err) {
|
if (dev_err) {
|
||||||
finish_checksense(qrequest);
|
finish_checksense(request);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,8 +159,8 @@ packet_dpc(ide_qrequest *qrequest)
|
|||||||
device->DMA_failures = 0;
|
device->DMA_failures = 0;
|
||||||
// this is a lie, but there is no way to find out
|
// this is a lie, but there is no way to find out
|
||||||
// how much has been transmitted
|
// how much has been transmitted
|
||||||
qrequest->request->data_resid = 0;
|
request->ccb->data_resid = 0;
|
||||||
finish_checksense(qrequest);
|
finish_checksense(request);
|
||||||
} else {
|
} else {
|
||||||
// DMA transmission went wrong
|
// DMA transmission went wrong
|
||||||
set_sense(device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_LUN_COM_FAILURE);
|
set_sense(device, SCSIS_KEY_HARDWARE_ERROR, SCSIS_ASC_LUN_COM_FAILURE);
|
||||||
@ -171,7 +171,7 @@ packet_dpc(ide_qrequest *qrequest)
|
|||||||
device->DMA_enabled = false;
|
device->DMA_enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
finish_checksense(qrequest);
|
finish_checksense(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return;
|
||||||
@ -191,7 +191,7 @@ packet_dpc(ide_qrequest *qrequest)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check whether transmission direction matches
|
// check whether transmission direction matches
|
||||||
if ((device->tf.packet_res.input_or_output ^ qrequest->is_write) == 0) {
|
if ((device->tf.packet_res.input_or_output ^ request->is_write) == 0) {
|
||||||
SHOW_ERROR0(2, "data transmission in wrong way!?");
|
SHOW_ERROR0(2, "data transmission in wrong way!?");
|
||||||
|
|
||||||
// TODO: hm, either the device is broken or the caller has specified
|
// TODO: hm, either the device is broken or the caller has specified
|
||||||
@ -202,9 +202,9 @@ packet_dpc(ide_qrequest *qrequest)
|
|||||||
// TODO: the device will abort next command with a reset condition
|
// TODO: the device will abort next command with a reset condition
|
||||||
// perhaps we should hide that by reading sense?
|
// perhaps we should hide that by reading sense?
|
||||||
SHOW_FLOW0(3, "Reset");
|
SHOW_FLOW0(3, "Reset");
|
||||||
// reset_device(device, qrequest);
|
// reset_device(device, request);
|
||||||
|
|
||||||
finish_checksense(qrequest);
|
finish_checksense(request);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,9 +224,9 @@ packet_dpc(ide_qrequest *qrequest)
|
|||||||
start_waiting_nolock(device->bus, timeout, ide_state_async_waiting);
|
start_waiting_nolock(device->bus, timeout, ide_state_async_waiting);
|
||||||
|
|
||||||
if (device->tf.packet_res.input_or_output)
|
if (device->tf.packet_res.input_or_output)
|
||||||
err = read_PIO_block(qrequest, length);
|
err = read_PIO_block(request, length);
|
||||||
else
|
else
|
||||||
err = write_PIO_block(qrequest, length);
|
err = write_PIO_block(request, length);
|
||||||
|
|
||||||
// only report "real" errors;
|
// only report "real" errors;
|
||||||
// discarding data (ERR_TOO_BIG) can happen but is OK
|
// discarding data (ERR_TOO_BIG) can happen but is OK
|
||||||
@ -241,16 +241,16 @@ packet_dpc(ide_qrequest *qrequest)
|
|||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
// device has done job and doesn't want to transmit data anymore
|
// device has done job and doesn't want to transmit data anymore
|
||||||
// -> finish request
|
// -> finish ccb
|
||||||
SHOW_FLOW0(3, "no data");
|
SHOW_FLOW0(3, "no data");
|
||||||
|
|
||||||
check_packet_error(device, qrequest);
|
check_packet_error(device, request);
|
||||||
|
|
||||||
SHOW_FLOW(3, "finished: %d of %d left",
|
SHOW_FLOW(3, "finished: %d of %d left",
|
||||||
(int)qrequest->request->data_resid,
|
(int)request->ccb->data_resid,
|
||||||
(int)qrequest->request->data_length);
|
(int)request->ccb->data_length);
|
||||||
|
|
||||||
finish_checksense(qrequest);
|
finish_checksense(request);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,27 +259,27 @@ packet_dpc(ide_qrequest *qrequest)
|
|||||||
err_cancel_timer:
|
err_cancel_timer:
|
||||||
cancel_irq_timeout(device->bus);
|
cancel_irq_timeout(device->bus);
|
||||||
err:
|
err:
|
||||||
finish_checksense(qrequest);
|
finish_checksense(request);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Create taskfile for ATAPI packet */
|
/*! Create taskfile for ATAPI packet */
|
||||||
static bool
|
static bool
|
||||||
create_packet_taskfile(ide_device_info *device, ide_qrequest *qrequest,
|
create_packet_taskfile(ide_device_info *device, ata_request *request,
|
||||||
bool write)
|
bool write)
|
||||||
{
|
{
|
||||||
scsi_ccb *request = qrequest->request;
|
scsi_ccb *ccb = request->ccb;
|
||||||
|
|
||||||
SHOW_FLOW(3, "DMA enabled=%d, uses_dma=%d, scsi_cmd=%x",
|
SHOW_FLOW(3, "DMA enabled=%d, uses_dma=%d, scsi_cmd=%x",
|
||||||
device->DMA_enabled, qrequest->uses_dma, device->packet[0]);
|
device->DMA_enabled, request->uses_dma, device->packet[0]);
|
||||||
|
|
||||||
device->tf_param_mask = ide_mask_features | ide_mask_byte_count;
|
device->tf_param_mask = ide_mask_features | ide_mask_byte_count;
|
||||||
|
|
||||||
device->tf.packet.dma = qrequest->uses_dma;
|
device->tf.packet.dma = request->uses_dma;
|
||||||
device->tf.packet.ovl = 0;
|
device->tf.packet.ovl = 0;
|
||||||
device->tf.packet.byte_count_0_7 = request->data_length & 0xff;
|
device->tf.packet.byte_count_0_7 = ccb->data_length & 0xff;
|
||||||
device->tf.packet.byte_count_8_15 = request->data_length >> 8;
|
device->tf.packet.byte_count_8_15 = ccb->data_length >> 8;
|
||||||
device->tf.packet.command = IDE_CMD_PACKET;
|
device->tf.packet.command = IDE_CMD_PACKET;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -288,14 +288,14 @@ create_packet_taskfile(ide_device_info *device, ide_qrequest *qrequest,
|
|||||||
|
|
||||||
/*! Send ATAPI packet */
|
/*! Send ATAPI packet */
|
||||||
void
|
void
|
||||||
send_packet(ide_device_info *device, ide_qrequest *qrequest, bool write)
|
send_packet(ide_device_info *device, ata_request *request, bool write)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
ide_bus_info *bus = device->bus;
|
ide_bus_info *bus = device->bus;
|
||||||
bool packet_irq = device->atapi.packet_irq;
|
bool packet_irq = device->atapi.packet_irq;
|
||||||
uint8 scsi_cmd = device->packet[0];
|
uint8 scsi_cmd = device->packet[0];
|
||||||
|
|
||||||
SHOW_FLOW( 3, "qrequest=%p, command=%x", qrequest, scsi_cmd );
|
SHOW_FLOW( 3, "request=%p, command=%x", request, scsi_cmd );
|
||||||
|
|
||||||
/*{
|
/*{
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
@ -309,47 +309,47 @@ send_packet(ide_device_info *device, ide_qrequest *qrequest, bool write)
|
|||||||
device->packet[3], device->packet[4], device->packet[5],
|
device->packet[3], device->packet[4], device->packet[5],
|
||||||
device->packet[6], device->packet[7], device->packet[8],
|
device->packet[6], device->packet[7], device->packet[8],
|
||||||
device->packet[9], device->packet[10], device->packet[11],
|
device->packet[9], device->packet[10], device->packet[11],
|
||||||
qrequest->request->cdb_length);
|
request->ccb->cdb_length);
|
||||||
|
|
||||||
//snooze( 1000000 );
|
//snooze( 1000000 );
|
||||||
|
|
||||||
qrequest->is_write = write;
|
request->is_write = write;
|
||||||
// if needed, mark first IRQ as being packet request IRQ
|
// if needed, mark first IRQ as being packet ccb IRQ
|
||||||
qrequest->packet_irq = packet_irq;
|
request->packet_irq = packet_irq;
|
||||||
|
|
||||||
// only READ/WRITE commands can use DMA
|
// only READ/WRITE commands can use DMA
|
||||||
// (the device may support it always, but IDE controllers don't
|
// (the device may support it always, but IDE controllers don't
|
||||||
// report how much data is transmitted, and this information is
|
// report how much data is transmitted, and this information is
|
||||||
// crucial for the SCSI protocol)
|
// crucial for the SCSI protocol)
|
||||||
// special offer: let READ_CD commands use DMA too
|
// special offer: let READ_CD commands use DMA too
|
||||||
qrequest->uses_dma = device->DMA_enabled
|
request->uses_dma = device->DMA_enabled
|
||||||
&& (scsi_cmd == SCSI_OP_READ_6 || scsi_cmd == SCSI_OP_WRITE_6
|
&& (scsi_cmd == SCSI_OP_READ_6 || scsi_cmd == SCSI_OP_WRITE_6
|
||||||
|| scsi_cmd == SCSI_OP_READ_10 || scsi_cmd == SCSI_OP_WRITE_10
|
|| scsi_cmd == SCSI_OP_READ_10 || scsi_cmd == SCSI_OP_WRITE_10
|
||||||
|| scsi_cmd == SCSI_OP_READ_12 || scsi_cmd == SCSI_OP_WRITE_12
|
|| scsi_cmd == SCSI_OP_READ_12 || scsi_cmd == SCSI_OP_WRITE_12
|
||||||
|| scsi_cmd == SCSI_OP_READ_CD);
|
|| scsi_cmd == SCSI_OP_READ_CD);
|
||||||
|
|
||||||
// try preparing DMA, if that fails, fall back to PIO
|
// try preparing DMA, if that fails, fall back to PIO
|
||||||
if (qrequest->uses_dma) {
|
if (request->uses_dma) {
|
||||||
SHOW_FLOW0(3, "0");
|
SHOW_FLOW0(3, "0");
|
||||||
if (!prepare_dma( device, qrequest))
|
if (!prepare_dma( device, request))
|
||||||
qrequest->uses_dma = false;
|
request->uses_dma = false;
|
||||||
|
|
||||||
SHOW_FLOW(3, "0->%d", qrequest->uses_dma);
|
SHOW_FLOW(3, "0->%d", request->uses_dma);
|
||||||
}
|
}
|
||||||
|
|
||||||
SHOW_FLOW0(3, "1");
|
SHOW_FLOW0(3, "1");
|
||||||
|
|
||||||
if (!qrequest->uses_dma)
|
if (!request->uses_dma)
|
||||||
prep_PIO_transfer(device, qrequest);
|
prep_PIO_transfer(device, request);
|
||||||
|
|
||||||
SHOW_FLOW0(3, "2");
|
SHOW_FLOW0(3, "2");
|
||||||
|
|
||||||
if (!create_packet_taskfile(device, qrequest, write))
|
if (!create_packet_taskfile(device, request, write))
|
||||||
goto err_setup;
|
goto err_setup;
|
||||||
|
|
||||||
SHOW_FLOW0(3, "3");
|
SHOW_FLOW0(3, "3");
|
||||||
|
|
||||||
if (!send_command(device, qrequest, false,
|
if (!send_command(device, request, false,
|
||||||
device->atapi.packet_irq_timeout,
|
device->atapi.packet_irq_timeout,
|
||||||
device->atapi.packet_irq ? ide_state_async_waiting : ide_state_accessing))
|
device->atapi.packet_irq ? ide_state_async_waiting : ide_state_accessing))
|
||||||
goto err_setup;
|
goto err_setup;
|
||||||
@ -407,15 +407,15 @@ send_packet(ide_device_info *device, ide_qrequest *qrequest, bool write)
|
|||||||
goto err_packet2;
|
goto err_packet2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qrequest->uses_dma) {
|
if (request->uses_dma) {
|
||||||
SHOW_FLOW0( 3, "ready for DMA" );
|
SHOW_FLOW0( 3, "ready for DMA" );
|
||||||
|
|
||||||
// S/G table must already be setup - we hold the bus lock, so
|
// S/G table must already be setup - we hold the bus lock, so
|
||||||
// we really have to hurry up
|
// we really have to hurry up
|
||||||
start_dma_wait(device, qrequest);
|
start_dma_wait(device, request);
|
||||||
} else {
|
} else {
|
||||||
uint32 timeout = qrequest->request->timeout > 0 ?
|
uint32 timeout = request->ccb->timeout > 0 ?
|
||||||
qrequest->request->timeout : IDE_STD_TIMEOUT;
|
request->ccb->timeout : IDE_STD_TIMEOUT;
|
||||||
|
|
||||||
start_waiting(bus, timeout, ide_state_async_waiting);
|
start_waiting(bus, timeout, ide_state_async_waiting);
|
||||||
}
|
}
|
||||||
@ -430,38 +430,38 @@ err_packet:
|
|||||||
device->subsys_status = SCSI_HBA_ERR;
|
device->subsys_status = SCSI_HBA_ERR;
|
||||||
|
|
||||||
err_setup:
|
err_setup:
|
||||||
if (qrequest->uses_dma)
|
if (request->uses_dma)
|
||||||
abort_dma(device, qrequest);
|
abort_dma(device, request);
|
||||||
|
|
||||||
finish_checksense(qrequest);
|
finish_checksense(request);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Execute SCSI I/O for atapi devices */
|
/*! Execute SCSI I/O for atapi devices */
|
||||||
void
|
void
|
||||||
atapi_exec_io(ide_device_info *device, ide_qrequest *qrequest)
|
atapi_exec_io(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
scsi_ccb *request = qrequest->request;
|
scsi_ccb *ccb = request->ccb;
|
||||||
|
|
||||||
SHOW_FLOW(3, "command=%x", qrequest->request->cdb[0]);
|
SHOW_FLOW(3, "command=%x", request->ccb->cdb[0]);
|
||||||
|
|
||||||
// ATAPI command packets are 12 bytes long;
|
// ATAPI command packets are 12 bytes long;
|
||||||
// if the command is shorter, remaining bytes must be padded with zeros
|
// if the command is shorter, remaining bytes must be padded with zeros
|
||||||
memset(device->packet, 0, sizeof(device->packet));
|
memset(device->packet, 0, sizeof(device->packet));
|
||||||
memcpy(device->packet, request->cdb, request->cdb_length);
|
memcpy(device->packet, ccb->cdb, ccb->cdb_length);
|
||||||
|
|
||||||
if (request->cdb[0] == SCSI_OP_REQUEST_SENSE && device->combined_sense) {
|
if (ccb->cdb[0] == SCSI_OP_REQUEST_SENSE && device->combined_sense) {
|
||||||
// we have a pending emulated sense - return it on REQUEST SENSE
|
// we have a pending emulated sense - return it on REQUEST SENSE
|
||||||
ide_request_sense(device, qrequest);
|
ide_request_sense(device, request);
|
||||||
finish_checksense(qrequest);
|
finish_checksense(request);
|
||||||
} else {
|
} else {
|
||||||
// reset all error codes for new request
|
// reset all error codes for new ccb
|
||||||
start_request(device, qrequest);
|
start_request(device, request);
|
||||||
|
|
||||||
// now we have an IDE packet
|
// now we have an IDE packet
|
||||||
send_packet(device, qrequest,
|
send_packet(device, request,
|
||||||
(request->flags & SCSI_DIR_MASK) == SCSI_DIR_OUT);
|
(ccb->flags & SCSI_DIR_MASK) == SCSI_DIR_OUT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,10 +58,6 @@ destroy_device(ide_device_info *device)
|
|||||||
device->exec_io = NULL;
|
device->exec_io = NULL;
|
||||||
|
|
||||||
cleanup_device_links(device);
|
cleanup_device_links(device);
|
||||||
|
|
||||||
if (device->qreqActive)
|
|
||||||
dprintf("destroy_device: Warning request still active\n");
|
|
||||||
free(device->qreqFree);
|
|
||||||
|
|
||||||
free(device);
|
free(device);
|
||||||
}
|
}
|
||||||
@ -121,14 +117,6 @@ create_device(ide_bus_info *bus, bool is_device1)
|
|||||||
|
|
||||||
device->combined_sense = 0;
|
device->combined_sense = 0;
|
||||||
|
|
||||||
device->qreqActive = NULL;
|
|
||||||
device->qreqFree = (ide_qrequest *)malloc(sizeof(ide_qrequest));
|
|
||||||
|
|
||||||
memset(device->qreqFree, 0, sizeof(ide_qrequest));
|
|
||||||
device->qreqFree->running = false;
|
|
||||||
device->qreqFree->device = device;
|
|
||||||
device->qreqFree->request = NULL;
|
|
||||||
|
|
||||||
device->total_sectors = 0;
|
device->total_sectors = 0;
|
||||||
|
|
||||||
// disable interrupts
|
// disable interrupts
|
||||||
@ -141,10 +129,6 @@ create_device(ide_bus_info *bus, bool is_device1)
|
|||||||
bus->controller->write_command_block_regs(bus->channel_cookie, &device->tf, ide_mask_device_head);
|
bus->controller->write_command_block_regs(bus->channel_cookie, &device->tf, ide_mask_device_head);
|
||||||
|
|
||||||
return device;
|
return device;
|
||||||
|
|
||||||
err:
|
|
||||||
destroy_device(device);
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if B_HOST_IS_LENDIAN
|
#if B_HOST_IS_LENDIAN
|
||||||
|
@ -71,7 +71,7 @@ configure_dma(ide_device_info *device)
|
|||||||
must be called _before_ start_dma_wait
|
must be called _before_ start_dma_wait
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
abort_dma(ide_device_info *device, ide_qrequest *qrequest)
|
abort_dma(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
ide_bus_info *bus = device->bus;
|
ide_bus_info *bus = device->bus;
|
||||||
|
|
||||||
@ -86,14 +86,14 @@ abort_dma(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
warning: doesn't set sense data on error
|
warning: doesn't set sense data on error
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
prepare_dma(ide_device_info *device, ide_qrequest *qrequest)
|
prepare_dma(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
ide_bus_info *bus = device->bus;
|
ide_bus_info *bus = device->bus;
|
||||||
scsi_ccb *request = qrequest->request;
|
scsi_ccb *ccb = request->ccb;
|
||||||
status_t res;
|
status_t res;
|
||||||
|
|
||||||
res = bus->controller->prepare_dma(bus->channel_cookie, request->sg_list,
|
res = bus->controller->prepare_dma(bus->channel_cookie, ccb->sg_list,
|
||||||
request->sg_count, qrequest->is_write);
|
ccb->sg_count, request->is_write);
|
||||||
if (res != B_OK)
|
if (res != B_OK)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -103,27 +103,27 @@ prepare_dma(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
|
|
||||||
/*! Start waiting for DMA to be finished */
|
/*! Start waiting for DMA to be finished */
|
||||||
void
|
void
|
||||||
start_dma_wait(ide_device_info *device, ide_qrequest *qrequest)
|
start_dma_wait(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
ide_bus_info *bus = device->bus;
|
ide_bus_info *bus = device->bus;
|
||||||
|
|
||||||
bus->controller->start_dma(bus->channel_cookie);
|
bus->controller->start_dma(bus->channel_cookie);
|
||||||
|
|
||||||
start_waiting(bus, qrequest->request->timeout > 0 ?
|
start_waiting(bus, request->ccb->timeout > 0 ?
|
||||||
qrequest->request->timeout : IDE_STD_TIMEOUT, ide_state_async_waiting);
|
request->ccb->timeout : IDE_STD_TIMEOUT, ide_state_async_waiting);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Start waiting for DMA to be finished with bus lock not hold */
|
/*! Start waiting for DMA to be finished with bus lock not hold */
|
||||||
void
|
void
|
||||||
start_dma_wait_no_lock(ide_device_info *device, ide_qrequest *qrequest)
|
start_dma_wait_no_lock(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
ide_bus_info *bus = device->bus;
|
ide_bus_info *bus = device->bus;
|
||||||
|
|
||||||
IDE_LOCK(bus);
|
IDE_LOCK(bus);
|
||||||
start_dma_wait(device, qrequest);
|
start_dma_wait(device, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -18,10 +18,10 @@
|
|||||||
|
|
||||||
/*! Emulate REQUEST SENSE */
|
/*! Emulate REQUEST SENSE */
|
||||||
void
|
void
|
||||||
ide_request_sense(ide_device_info *device, ide_qrequest *qrequest)
|
ide_request_sense(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
scsi_ccb *request = qrequest->request;
|
scsi_ccb *ccb = request->ccb;
|
||||||
scsi_cmd_request_sense *cmd = (scsi_cmd_request_sense *)request->cdb;
|
scsi_cmd_request_sense *cmd = (scsi_cmd_request_sense *)ccb->cdb;
|
||||||
scsi_sense sense;
|
scsi_sense sense;
|
||||||
uint32 transferSize;
|
uint32 transferSize;
|
||||||
|
|
||||||
@ -33,39 +33,39 @@ ide_request_sense(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
else
|
else
|
||||||
memset(&sense, 0, sizeof(sense));
|
memset(&sense, 0, sizeof(sense));
|
||||||
|
|
||||||
copy_sg_data(request, 0, cmd->allocation_length, &sense, sizeof(sense), false);
|
copy_sg_data(ccb, 0, cmd->allocation_length, &sense, sizeof(sense), false);
|
||||||
|
|
||||||
// reset sense information on read
|
// reset sense information on read
|
||||||
device->combined_sense = 0;
|
device->combined_sense = 0;
|
||||||
|
|
||||||
transferSize = min(sizeof(sense), cmd->allocation_length);
|
transferSize = min(sizeof(sense), cmd->allocation_length);
|
||||||
transferSize = min(transferSize, request->data_length);
|
transferSize = min(transferSize, ccb->data_length);
|
||||||
|
|
||||||
request->data_resid = request->data_length - transferSize;
|
ccb->data_resid = ccb->data_length - transferSize;
|
||||||
|
|
||||||
// normally, all flags are set to "success", but for Request Sense
|
// normally, all flags are set to "success", but for Request Sense
|
||||||
// this would have overwritten the sense we want to read
|
// this would have overwritten the sense we want to read
|
||||||
device->subsys_status = SCSI_REQ_CMP;
|
device->subsys_status = SCSI_REQ_CMP;
|
||||||
request->device_status = SCSI_STATUS_GOOD;
|
ccb->device_status = SCSI_STATUS_GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Copy data between request data and buffer
|
/*! Copy data between ccb data and buffer
|
||||||
request - request to copy data from/to
|
ccb - ccb to copy data from/to
|
||||||
offset - offset of data in request
|
offset - offset of data in ccb
|
||||||
allocation_length- limit of request's data buffer according to CDB
|
allocation_length- limit of ccb's data buffer according to CDB
|
||||||
buffer - data to copy data from/to
|
buffer - data to copy data from/to
|
||||||
size - number of bytes to copy
|
size - number of bytes to copy
|
||||||
to_buffer - true: copy from request to buffer
|
to_buffer - true: copy from ccb to buffer
|
||||||
false: copy from buffer to request
|
false: copy from buffer to ccb
|
||||||
return: true, if data of request was large enough
|
return: true, if data of ccb was large enough
|
||||||
*/
|
*/
|
||||||
bool
|
bool
|
||||||
copy_sg_data(scsi_ccb *request, uint offset, uint allocationLength,
|
copy_sg_data(scsi_ccb *ccb, uint offset, uint allocationLength,
|
||||||
void *buffer, int size, bool toBuffer)
|
void *buffer, int size, bool toBuffer)
|
||||||
{
|
{
|
||||||
const physical_entry *sgList = request->sg_list;
|
const physical_entry *sgList = ccb->sg_list;
|
||||||
int sgCount = request->sg_count;
|
int sgCount = ccb->sg_count;
|
||||||
int requestSize;
|
int requestSize;
|
||||||
|
|
||||||
SHOW_FLOW(3, "offset=%u, req_size_limit=%d, size=%d, sg_list=%p, sg_cnt=%d, %s buffer",
|
SHOW_FLOW(3, "offset=%u, req_size_limit=%d, size=%d, sg_list=%p, sg_cnt=%d, %s buffer",
|
||||||
@ -81,8 +81,8 @@ copy_sg_data(scsi_ccb *request, uint offset, uint allocationLength,
|
|||||||
if (sgCount == 0)
|
if (sgCount == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// remaining bytes we are allowed to copy from/to request
|
// remaining bytes we are allowed to copy from/to ccb
|
||||||
requestSize = min(allocationLength, request->data_length) - offset;
|
requestSize = min(allocationLength, ccb->data_length) - offset;
|
||||||
|
|
||||||
// copy one S/G entry at a time
|
// copy one S/G entry at a time
|
||||||
for (; size > 0 && requestSize > 0 && sgCount > 0; ++sgList, --sgCount) {
|
for (; size > 0 && requestSize > 0 && sgCount > 0; ++sgList, --sgCount) {
|
||||||
|
@ -37,20 +37,15 @@
|
|||||||
#define IDE_CHANNEL_ID_GENERATOR "ide/channel_id"
|
#define IDE_CHANNEL_ID_GENERATOR "ide/channel_id"
|
||||||
// node item containing channel id (uint32)
|
// node item containing channel id (uint32)
|
||||||
#define IDE_CHANNEL_ID_ITEM "ide/channel_id"
|
#define IDE_CHANNEL_ID_ITEM "ide/channel_id"
|
||||||
|
// SIM interface
|
||||||
|
#define IDE_SIM_MODULE_NAME "bus_managers/ide/sim/v1"
|
||||||
|
|
||||||
|
|
||||||
extern device_manager_info *pnp;
|
extern device_manager_info *pnp;
|
||||||
|
|
||||||
|
|
||||||
typedef struct ide_bus_info ide_bus_info;
|
typedef struct ide_bus_info ide_bus_info;
|
||||||
|
|
||||||
typedef void (*ide_synced_pc_func)(ide_bus_info *bus, void *arg);
|
|
||||||
|
|
||||||
typedef struct ide_synced_pc {
|
|
||||||
struct ide_synced_pc *next;
|
|
||||||
ide_synced_pc_func func;
|
|
||||||
void *arg;
|
|
||||||
bool registered;
|
|
||||||
} ide_synced_pc;
|
|
||||||
|
|
||||||
// structure for device time-outs
|
// structure for device time-outs
|
||||||
typedef struct ide_device_timer_info {
|
typedef struct ide_device_timer_info {
|
||||||
@ -64,6 +59,18 @@ typedef struct ide_bus_timer_info {
|
|||||||
struct ide_bus_info *bus;
|
struct ide_bus_info *bus;
|
||||||
} ide_bus_timer_info;
|
} ide_bus_timer_info;
|
||||||
|
|
||||||
|
// ide request
|
||||||
|
typedef struct ata_request {
|
||||||
|
|
||||||
|
struct ide_device_info *device;
|
||||||
|
|
||||||
|
scsi_ccb *ccb; // basic request
|
||||||
|
uint8 is_write : 1; // true for write request
|
||||||
|
uint8 uses_dma : 1; // true if using dma
|
||||||
|
uint8 packet_irq : 1; // true if waiting for command packet irq
|
||||||
|
} ata_request;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typedef struct ide_device_info {
|
typedef struct ide_device_info {
|
||||||
struct ide_bus_info *bus;
|
struct ide_bus_info *bus;
|
||||||
@ -87,13 +94,10 @@ typedef struct ide_device_info {
|
|||||||
// pending error codes
|
// pending error codes
|
||||||
uint32 combined_sense; // emulated sense of device
|
uint32 combined_sense; // emulated sense of device
|
||||||
|
|
||||||
struct ide_qrequest *qreqActive;
|
|
||||||
struct ide_qrequest *qreqFree;
|
|
||||||
|
|
||||||
struct ide_device_info *other_device; // other device on same bus
|
struct ide_device_info *other_device; // other device on same bus
|
||||||
|
|
||||||
// entry for scsi's exec_io request
|
// entry for scsi's exec_io request
|
||||||
void (*exec_io)( struct ide_device_info *device, struct ide_qrequest *qrequest );
|
void (*exec_io)( struct ide_device_info *device, struct ata_request *request );
|
||||||
|
|
||||||
int target_id; // target id (currently, same as is_device1)
|
int target_id; // target id (currently, same as is_device1)
|
||||||
|
|
||||||
@ -134,18 +138,6 @@ typedef enum {
|
|||||||
ide_request_autosense = 2
|
ide_request_autosense = 2
|
||||||
} ide_request_state;*/
|
} ide_request_state;*/
|
||||||
|
|
||||||
// ide request
|
|
||||||
typedef struct ide_qrequest {
|
|
||||||
struct ide_qrequest *next;
|
|
||||||
ide_device_info *device;
|
|
||||||
scsi_ccb *request; // basic request
|
|
||||||
|
|
||||||
uint8 is_write : 1; // true for write request
|
|
||||||
uint8 running : 1; // true if "on bus"
|
|
||||||
uint8 uses_dma : 1; // true if using dma
|
|
||||||
uint8 packet_irq : 1; // true if waiting for command packet irq
|
|
||||||
} ide_qrequest;
|
|
||||||
|
|
||||||
|
|
||||||
// state of ide bus
|
// state of ide bus
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -157,7 +149,6 @@ typedef enum {
|
|||||||
|
|
||||||
|
|
||||||
struct ide_bus_info {
|
struct ide_bus_info {
|
||||||
ide_qrequest *active_qrequest;
|
|
||||||
|
|
||||||
// controller
|
// controller
|
||||||
ide_controller_interface *controller;
|
ide_controller_interface *controller;
|
||||||
@ -167,7 +158,11 @@ struct ide_bus_info {
|
|||||||
spinlock lock;
|
spinlock lock;
|
||||||
cpu_status prev_irq_state;
|
cpu_status prev_irq_state;
|
||||||
|
|
||||||
ata_bus_state state; // current state of bus
|
ata_bus_state state; // current state of bus
|
||||||
|
|
||||||
|
struct ata_request * qreqActive;
|
||||||
|
struct ata_request * qreqFree;
|
||||||
|
|
||||||
|
|
||||||
benaphore status_report_ben; // to lock when you report XPT about bus state
|
benaphore status_report_ben; // to lock when you report XPT about bus state
|
||||||
// i.e. during requeue, resubmit or finished
|
// i.e. during requeue, resubmit or finished
|
||||||
@ -178,14 +173,11 @@ struct ide_bus_info {
|
|||||||
|
|
||||||
ide_bus_timer_info timer; // timeout
|
ide_bus_timer_info timer; // timeout
|
||||||
scsi_dpc_cookie irq_dpc;
|
scsi_dpc_cookie irq_dpc;
|
||||||
ide_synced_pc *synced_pc_list;
|
|
||||||
|
|
||||||
ide_device_info *active_device;
|
ide_device_info *active_device;
|
||||||
ide_device_info *devices[2];
|
ide_device_info *devices[2];
|
||||||
ide_device_info *first_device;
|
ide_device_info *first_device;
|
||||||
|
|
||||||
ide_synced_pc disconnect_syncinfo; // used to handle lost controller
|
|
||||||
|
|
||||||
uchar path_id;
|
uchar path_id;
|
||||||
|
|
||||||
device_node_handle node; // our pnp node
|
device_node_handle node; // our pnp node
|
||||||
@ -213,67 +205,6 @@ struct ide_bus_info {
|
|||||||
restore_interrupts( prev_irq_state ); \
|
restore_interrupts( prev_irq_state ); \
|
||||||
}
|
}
|
||||||
|
|
||||||
// SIM interface
|
|
||||||
#define IDE_SIM_MODULE_NAME "bus_managers/ide/sim/v1"
|
|
||||||
|
|
||||||
|
|
||||||
enum {
|
|
||||||
ev_ide_send_command = 1,
|
|
||||||
ev_ide_device_start_service,
|
|
||||||
ev_ide_device_start_service2,
|
|
||||||
ev_ide_dpc_service,
|
|
||||||
ev_ide_dpc_continue,
|
|
||||||
ev_ide_irq_handle,
|
|
||||||
ev_ide_cancel_irq_timeout,
|
|
||||||
ev_ide_start_waiting,
|
|
||||||
ev_ide_timeout_dpc,
|
|
||||||
ev_ide_timeout,
|
|
||||||
ev_ide_reset_bus,
|
|
||||||
ev_ide_reset_device,
|
|
||||||
|
|
||||||
ev_ide_scsi_io,
|
|
||||||
ev_ide_scsi_io_exec,
|
|
||||||
ev_ide_scsi_io_invalid_device,
|
|
||||||
ev_ide_scsi_io_bus_busy,
|
|
||||||
ev_ide_scsi_io_device_busy,
|
|
||||||
ev_ide_scsi_io_disconnected,
|
|
||||||
ev_ide_finish_request,
|
|
||||||
ev_ide_finish_norelease,
|
|
||||||
|
|
||||||
ev_ide_scan_device_int,
|
|
||||||
ev_ide_scan_device_int_cant_send,
|
|
||||||
ev_ide_scan_device_int_keeps_busy,
|
|
||||||
ev_ide_scan_device_int_found
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// get selected device
|
|
||||||
static inline
|
|
||||||
ide_device_info *get_current_device(ide_bus_info *bus)
|
|
||||||
{
|
|
||||||
ide_task_file tf;
|
|
||||||
|
|
||||||
bus->controller->read_command_block_regs(bus->channel_cookie, &tf,
|
|
||||||
ide_mask_device_head);
|
|
||||||
|
|
||||||
return bus->devices[tf.lba.device];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// check if device has released the bus
|
|
||||||
// return: true, if bus was released
|
|
||||||
static inline int
|
|
||||||
device_released_bus(ide_device_info *device)
|
|
||||||
{
|
|
||||||
ide_bus_info *bus = device->bus;
|
|
||||||
|
|
||||||
bus->controller->read_command_block_regs(bus->channel_cookie,
|
|
||||||
&device->tf, ide_mask_sector_count);
|
|
||||||
|
|
||||||
return device->tf.queued.release;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ata.c
|
// ata.c
|
||||||
|
|
||||||
@ -286,18 +217,18 @@ status_t ata_wait_for_drqdown(ide_bus_info *bus);
|
|||||||
status_t ata_wait_for_drdy(ide_bus_info *bus);
|
status_t ata_wait_for_drdy(ide_bus_info *bus);
|
||||||
status_t ata_reset_bus(ide_bus_info *bus, bool *_devicePresent0, uint32 *_sigDev0, bool *_devicePresent1, uint32 *_sigDev1);
|
status_t ata_reset_bus(ide_bus_info *bus, bool *_devicePresent0, uint32 *_sigDev0, bool *_devicePresent1, uint32 *_sigDev1);
|
||||||
status_t ata_reset_device(ide_device_info *device, bool *_devicePresent);
|
status_t ata_reset_device(ide_device_info *device, bool *_devicePresent);
|
||||||
status_t ata_send_command(ide_device_info *device, ide_qrequest *qrequest, bool need_drdy, uint32 timeout, ata_bus_state new_state);
|
status_t ata_send_command(ide_device_info *device, ata_request *request, bool need_drdy, uint32 timeout, ata_bus_state new_state);
|
||||||
|
|
||||||
bool check_rw_error(ide_device_info *device, ide_qrequest *qrequest);
|
bool check_rw_error(ide_device_info *device, ata_request *request);
|
||||||
bool check_output(ide_device_info *device, bool drdy_required, int error_mask, bool is_write);
|
bool check_output(ide_device_info *device, bool drdy_required, int error_mask, bool is_write);
|
||||||
|
|
||||||
void ata_send_rw(ide_device_info *device, ide_qrequest *qrequest,
|
void ata_send_rw(ide_device_info *device, ata_request *request,
|
||||||
uint64 pos, size_t length, bool write);
|
uint64 pos, size_t length, bool write);
|
||||||
|
|
||||||
void ata_dpc_DMA(ide_qrequest *qrequest);
|
void ata_dpc_DMA(ata_request *request);
|
||||||
void ata_dpc_PIO(ide_qrequest *qrequest);
|
void ata_dpc_PIO(ata_request *request);
|
||||||
|
|
||||||
void ata_exec_io(ide_device_info *device, ide_qrequest *qrequest);
|
void ata_exec_io(ide_device_info *device, ata_request *request);
|
||||||
|
|
||||||
status_t ata_read_infoblock(ide_device_info *device, bool isAtapi);
|
status_t ata_read_infoblock(ide_device_info *device, bool isAtapi);
|
||||||
|
|
||||||
@ -305,9 +236,9 @@ status_t configure_ata_device(ide_device_info *device);
|
|||||||
|
|
||||||
// atapi.c
|
// atapi.c
|
||||||
status_t configure_atapi_device(ide_device_info *device);
|
status_t configure_atapi_device(ide_device_info *device);
|
||||||
void send_packet(ide_device_info *device, ide_qrequest *qrequest, bool write);
|
void send_packet(ide_device_info *device, ata_request *request, bool write);
|
||||||
void packet_dpc(ide_qrequest *qrequest);
|
void packet_dpc(ata_request *request);
|
||||||
void atapi_exec_io(ide_device_info *device, ide_qrequest *qrequest);
|
void atapi_exec_io(ide_device_info *device, ata_request *request);
|
||||||
|
|
||||||
|
|
||||||
// basic_prot.c
|
// basic_prot.c
|
||||||
@ -329,12 +260,12 @@ status_t configure_device(ide_device_info *device, bool isAtapi);
|
|||||||
|
|
||||||
// dma.c
|
// dma.c
|
||||||
|
|
||||||
bool prepare_dma(ide_device_info *device, ide_qrequest *qrequest);
|
bool prepare_dma(ide_device_info *device, ata_request *request);
|
||||||
void start_dma(ide_device_info *device, ide_qrequest *qrequest);
|
void start_dma(ide_device_info *device, ata_request *request);
|
||||||
void start_dma_wait(ide_device_info *device, ide_qrequest *qrequest);
|
void start_dma_wait(ide_device_info *device, ata_request *request);
|
||||||
void start_dma_wait_no_lock(ide_device_info *device, ide_qrequest *qrequest);
|
void start_dma_wait_no_lock(ide_device_info *device, ata_request *request);
|
||||||
bool finish_dma(ide_device_info *device);
|
bool finish_dma(ide_device_info *device);
|
||||||
void abort_dma(ide_device_info *device, ide_qrequest *qrequest);
|
void abort_dma(ide_device_info *device, ata_request *request);
|
||||||
|
|
||||||
bool configure_dma(ide_device_info *device);
|
bool configure_dma(ide_device_info *device);
|
||||||
|
|
||||||
@ -343,14 +274,14 @@ bool configure_dma(ide_device_info *device);
|
|||||||
|
|
||||||
bool copy_sg_data(scsi_ccb *request, uint offset, uint req_size_limit,
|
bool copy_sg_data(scsi_ccb *request, uint offset, uint req_size_limit,
|
||||||
void *buffer, int size, bool to_buffer);
|
void *buffer, int size, bool to_buffer);
|
||||||
void ide_request_sense(ide_device_info *device, ide_qrequest *qrequest);
|
void ide_request_sense(ide_device_info *device, ata_request *request);
|
||||||
|
|
||||||
|
|
||||||
// pio.c
|
// pio.c
|
||||||
|
|
||||||
void prep_PIO_transfer(ide_device_info *device, ide_qrequest *qrequest);
|
void prep_PIO_transfer(ide_device_info *device, ata_request *request);
|
||||||
status_t read_PIO_block(ide_qrequest *qrequest, int length);
|
status_t read_PIO_block(ata_request *request, int length);
|
||||||
status_t write_PIO_block(ide_qrequest *qrequest, int length);
|
status_t write_PIO_block(ata_request *request, int length);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -362,9 +293,6 @@ void start_waiting_nolock(ide_bus_info *bus, uint32 timeout, int new_state);
|
|||||||
void wait_for_sync(ide_bus_info *bus);
|
void wait_for_sync(ide_bus_info *bus);
|
||||||
void cancel_irq_timeout(ide_bus_info *bus);
|
void cancel_irq_timeout(ide_bus_info *bus);
|
||||||
|
|
||||||
status_t schedule_synced_pc(ide_bus_info *bus, ide_synced_pc *pc, void *arg);
|
|
||||||
void init_synced_pc(ide_synced_pc *pc, ide_synced_pc_func func);
|
|
||||||
void uninit_synced_pc(ide_synced_pc *pc);
|
|
||||||
|
|
||||||
void ide_dpc(void *arg);
|
void ide_dpc(void *arg);
|
||||||
void access_finished(ide_bus_info *bus, ide_device_info *device);
|
void access_finished(ide_bus_info *bus, ide_device_info *device);
|
||||||
|
@ -39,18 +39,17 @@
|
|||||||
scsi_for_sim_interface *scsi;
|
scsi_for_sim_interface *scsi;
|
||||||
|
|
||||||
|
|
||||||
static void disconnect_worker(ide_bus_info *bus, void *arg);
|
static void set_check_condition(ata_request *request);
|
||||||
static void set_check_condition(ide_qrequest *qrequest);
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
sim_scsi_io(ide_bus_info *bus, scsi_ccb *request)
|
sim_scsi_io(ide_bus_info *bus, scsi_ccb *ccb)
|
||||||
{
|
{
|
||||||
ide_device_info *device;
|
ide_device_info *device;
|
||||||
ide_qrequest *qrequest;
|
ata_request *request;
|
||||||
//ide_request_priv *priv;
|
//ide_request_priv *priv;
|
||||||
|
|
||||||
FLOW("sim_scsi_iobus %p, %d:%d\n", bus, request->target_id, request->target_lun);
|
FLOW("sim_scsi_iobus %p, %d:%d\n", bus, ccb->target_id, ccb->target_lun);
|
||||||
|
|
||||||
if (bus->disconnected)
|
if (bus->disconnected)
|
||||||
goto err_disconnected;
|
goto err_disconnected;
|
||||||
@ -59,14 +58,14 @@ sim_scsi_io(ide_bus_info *bus, scsi_ccb *request)
|
|||||||
// I've read that there are ATAPI devices with more then one LUN,
|
// I've read that there are ATAPI devices with more then one LUN,
|
||||||
// but it seems that most (all?) devices ignore LUN, so we have
|
// but it seems that most (all?) devices ignore LUN, so we have
|
||||||
// to restrict to LUN 0 to avoid mirror devices
|
// to restrict to LUN 0 to avoid mirror devices
|
||||||
if (request->target_id >= 2)
|
if (ccb->target_id >= 2)
|
||||||
goto err_inv_device;
|
goto err_inv_device;
|
||||||
|
|
||||||
device = bus->devices[request->target_id];
|
device = bus->devices[ccb->target_id];
|
||||||
if (device == NULL)
|
if (device == NULL)
|
||||||
goto err_inv_device;
|
goto err_inv_device;
|
||||||
|
|
||||||
if (request->target_lun > device->last_lun)
|
if (ccb->target_lun > device->last_lun)
|
||||||
goto err_inv_device;
|
goto err_inv_device;
|
||||||
|
|
||||||
// grab the bus
|
// grab the bus
|
||||||
@ -77,7 +76,7 @@ sim_scsi_io(ide_bus_info *bus, scsi_ccb *request)
|
|||||||
goto err_bus_busy;
|
goto err_bus_busy;
|
||||||
|
|
||||||
// bail out if device can't accept further requests
|
// bail out if device can't accept further requests
|
||||||
if (device->qreqFree == NULL)
|
if (bus->qreqFree == NULL)
|
||||||
goto err_device_busy;
|
goto err_device_busy;
|
||||||
|
|
||||||
bus->state = ata_state_busy;
|
bus->state = ata_state_busy;
|
||||||
@ -86,35 +85,32 @@ sim_scsi_io(ide_bus_info *bus, scsi_ccb *request)
|
|||||||
RELEASE_BEN(&bus->status_report_ben);
|
RELEASE_BEN(&bus->status_report_ben);
|
||||||
|
|
||||||
// as we own the bus, noone can bother us
|
// as we own the bus, noone can bother us
|
||||||
qrequest = device->qreqFree;
|
request = bus->qreqFree;
|
||||||
device->qreqFree = NULL;
|
bus->qreqFree = NULL;
|
||||||
device->qreqActive = qrequest;
|
bus->qreqActive = request;
|
||||||
|
|
||||||
|
request->device = device;
|
||||||
|
request->ccb = ccb;
|
||||||
|
request->uses_dma = false;
|
||||||
|
|
||||||
qrequest->request = request;
|
FLOW("calling exec_io: %p, %d:%d\n", bus, ccb->target_id, ccb->target_lun);
|
||||||
qrequest->running = true;
|
|
||||||
qrequest->uses_dma = false;
|
|
||||||
|
|
||||||
bus->active_qrequest = qrequest; // XXX whats this!?!?!
|
device->exec_io(device, request);
|
||||||
|
|
||||||
|
|
||||||
FLOW("calling exec_io: %p, %d:%d\n", bus, request->target_id, request->target_lun);
|
|
||||||
|
|
||||||
device->exec_io(device, qrequest);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
err_inv_device:
|
err_inv_device:
|
||||||
FLOW("Invalid device %d:%d\n", request->target_id, request->target_lun);
|
FLOW("Invalid device %d:%d\n", ccb->target_id, ccb->target_lun);
|
||||||
|
|
||||||
request->subsys_status = SCSI_SEL_TIMEOUT;
|
ccb->subsys_status = SCSI_SEL_TIMEOUT;
|
||||||
scsi->finished(request, 1);
|
scsi->finished(ccb, 1);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
err_bus_busy:
|
err_bus_busy:
|
||||||
FLOW("Bus busy\n");
|
FLOW("Bus busy\n");
|
||||||
|
|
||||||
IDE_UNLOCK(bus);
|
IDE_UNLOCK(bus);
|
||||||
scsi->requeue(request, true);
|
scsi->requeue(ccb, true);
|
||||||
RELEASE_BEN(&bus->status_report_ben);
|
RELEASE_BEN(&bus->status_report_ben);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -122,14 +118,14 @@ err_device_busy:
|
|||||||
FLOW("Device busy\n");
|
FLOW("Device busy\n");
|
||||||
|
|
||||||
IDE_UNLOCK(bus);
|
IDE_UNLOCK(bus);
|
||||||
scsi->requeue(request, false);
|
scsi->requeue(ccb, false);
|
||||||
RELEASE_BEN(&bus->status_report_ben);
|
RELEASE_BEN(&bus->status_report_ben);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
err_disconnected:
|
err_disconnected:
|
||||||
TRACE("No controller anymore\n");
|
TRACE("No controller anymore\n");
|
||||||
request->subsys_status = SCSI_NO_HBA;
|
ccb->subsys_status = SCSI_NO_HBA;
|
||||||
scsi->finished(request, 1);
|
scsi->finished(ccb, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,25 +306,25 @@ create_sense(ide_device_info *device, scsi_sense *sense)
|
|||||||
/** finish command, updating sense of device and request, and release bus */
|
/** finish command, updating sense of device and request, and release bus */
|
||||||
|
|
||||||
void
|
void
|
||||||
finish_checksense(ide_qrequest *qrequest)
|
finish_checksense(ata_request *request)
|
||||||
{
|
{
|
||||||
SHOW_FLOW(3, "%p, subsys_status=%d, sense=%x",
|
SHOW_FLOW(3, "%p, subsys_status=%d, sense=%x",
|
||||||
qrequest->request,
|
request->ccb,
|
||||||
qrequest->request->subsys_status,
|
request->ccb->subsys_status,
|
||||||
(int)qrequest->device->new_combined_sense);
|
(int)request->device->new_combined_sense);
|
||||||
|
|
||||||
qrequest->request->subsys_status = qrequest->device->subsys_status;
|
request->ccb->subsys_status = request->device->subsys_status;
|
||||||
|
|
||||||
if (qrequest->request->subsys_status == SCSI_REQ_CMP) {
|
if (request->ccb->subsys_status == SCSI_REQ_CMP) {
|
||||||
// device or emulation code completed command
|
// device or emulation code completed command
|
||||||
qrequest->device->combined_sense = qrequest->device->new_combined_sense;
|
request->device->combined_sense = request->device->new_combined_sense;
|
||||||
|
|
||||||
// if emulation code detected error, set CHECK CONDITION
|
// if emulation code detected error, set CHECK CONDITION
|
||||||
if (qrequest->device->combined_sense)
|
if (request->device->combined_sense)
|
||||||
set_check_condition(qrequest);
|
set_check_condition(request);
|
||||||
}
|
}
|
||||||
|
|
||||||
finish_request(qrequest, false);
|
finish_request(request, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -337,25 +333,21 @@ finish_checksense(ide_qrequest *qrequest)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
finish_request(ide_qrequest *qrequest, bool resubmit)
|
finish_request(ata_request *request, bool resubmit)
|
||||||
{
|
{
|
||||||
ide_device_info *device = qrequest->device;
|
ide_device_info *device = request->device;
|
||||||
ide_bus_info *bus = device->bus;
|
ide_bus_info *bus = device->bus;
|
||||||
scsi_ccb *request;
|
scsi_ccb *ccb;
|
||||||
|
|
||||||
SHOW_FLOW0(3, "");
|
SHOW_FLOW0(3, "");
|
||||||
|
|
||||||
// save request first, as qrequest can be reused as soon as
|
// save request first, as request can be reused as soon as
|
||||||
// access_finished is called!
|
// access_finished is called!
|
||||||
request = qrequest->request;
|
ccb = request->ccb;
|
||||||
|
|
||||||
qrequest->running = false;
|
|
||||||
|
|
||||||
device->qreqFree = device->qreqActive;
|
bus->qreqFree = bus->qreqActive;
|
||||||
device->qreqActive = NULL;
|
bus->qreqActive = NULL;
|
||||||
|
|
||||||
// paranoia
|
|
||||||
bus->active_qrequest = NULL;
|
|
||||||
|
|
||||||
// release bus, handling service requests;
|
// release bus, handling service requests;
|
||||||
// TBD:
|
// TBD:
|
||||||
@ -369,9 +361,9 @@ finish_request(ide_qrequest *qrequest, bool resubmit)
|
|||||||
ACQUIRE_BEN(&bus->status_report_ben);
|
ACQUIRE_BEN(&bus->status_report_ben);
|
||||||
|
|
||||||
if (resubmit)
|
if (resubmit)
|
||||||
scsi->resubmit(request);
|
scsi->resubmit(ccb);
|
||||||
else
|
else
|
||||||
scsi->finished(request, 1);
|
scsi->finished(ccb, 1);
|
||||||
|
|
||||||
RELEASE_BEN(&bus->status_report_ben);
|
RELEASE_BEN(&bus->status_report_ben);
|
||||||
}
|
}
|
||||||
@ -383,18 +375,18 @@ finish_request(ide_qrequest *qrequest, bool resubmit)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
static void
|
||||||
set_check_condition(ide_qrequest *qrequest)
|
set_check_condition(ata_request *request)
|
||||||
{
|
{
|
||||||
scsi_ccb *request = qrequest->request;
|
scsi_ccb *ccb = request->ccb;
|
||||||
ide_device_info *device = qrequest->device;
|
ide_device_info *device = request->device;
|
||||||
|
|
||||||
SHOW_FLOW0(3, "");
|
SHOW_FLOW0(3, "");
|
||||||
|
|
||||||
request->subsys_status = SCSI_REQ_CMP_ERR;
|
ccb->subsys_status = SCSI_REQ_CMP_ERR;
|
||||||
request->device_status = SCSI_STATUS_CHECK_CONDITION;
|
ccb->device_status = SCSI_STATUS_CHECK_CONDITION;
|
||||||
|
|
||||||
// copy sense only if caller requested it
|
// copy sense only if caller requested it
|
||||||
if ((request->flags & SCSI_DIS_AUTOSENSE) == 0) {
|
if ((ccb->flags & SCSI_DIS_AUTOSENSE) == 0) {
|
||||||
scsi_sense sense;
|
scsi_sense sense;
|
||||||
int sense_len;
|
int sense_len;
|
||||||
|
|
||||||
@ -405,9 +397,9 @@ set_check_condition(ide_qrequest *qrequest)
|
|||||||
|
|
||||||
sense_len = min(SCSI_MAX_SENSE_SIZE, sizeof(sense));
|
sense_len = min(SCSI_MAX_SENSE_SIZE, sizeof(sense));
|
||||||
|
|
||||||
memcpy(request->sense, &sense, sense_len);
|
memcpy(ccb->sense, &sense, sense_len);
|
||||||
request->sense_resid = SCSI_MAX_SENSE_SIZE - sense_len;
|
ccb->sense_resid = SCSI_MAX_SENSE_SIZE - sense_len;
|
||||||
request->subsys_status |= SCSI_AUTOSNS_VALID;
|
ccb->subsys_status |= SCSI_AUTOSNS_VALID;
|
||||||
|
|
||||||
// device sense gets reset once it's read
|
// device sense gets reset once it's read
|
||||||
device->combined_sense = 0;
|
device->combined_sense = 0;
|
||||||
@ -416,10 +408,10 @@ set_check_condition(ide_qrequest *qrequest)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
finish_retry(ide_qrequest *qrequest)
|
finish_retry(ata_request *request)
|
||||||
{
|
{
|
||||||
qrequest->device->combined_sense = 0;
|
request->device->combined_sense = 0;
|
||||||
finish_request(qrequest, true);
|
finish_request(request, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -428,17 +420,17 @@ finish_retry(ide_qrequest *qrequest)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
finish_reset_queue(ide_qrequest *qrequest)
|
finish_reset_queue(ata_request *request)
|
||||||
{
|
{
|
||||||
ide_bus_info *bus = qrequest->device->bus;
|
ide_bus_info *bus = request->device->bus;
|
||||||
|
|
||||||
// don't remove block_bus!!!
|
// don't remove block_bus!!!
|
||||||
// during finish_checksense, the bus is released, so
|
// during finish_checksense, the bus is released, so
|
||||||
// the SCSI bus manager could send us further commands
|
// the SCSI bus manager could send us further commands
|
||||||
scsi->block_bus(bus->scsi_cookie);
|
scsi->block_bus(bus->scsi_cookie);
|
||||||
|
|
||||||
finish_checksense(qrequest);
|
finish_checksense(request);
|
||||||
// send_abort_queue(qrequest->device); // XXX fix this
|
// send_abort_queue(request->device); // XXX fix this
|
||||||
|
|
||||||
scsi->unblock_bus(bus->scsi_cookie);
|
scsi->unblock_bus(bus->scsi_cookie);
|
||||||
}
|
}
|
||||||
@ -447,40 +439,33 @@ finish_reset_queue(ide_qrequest *qrequest)
|
|||||||
/** finish request, but don't release bus
|
/** finish request, but don't release bus
|
||||||
* if resubmit is true, the request will be resubmitted
|
* if resubmit is true, the request will be resubmitted
|
||||||
*/
|
*/
|
||||||
|
/*
|
||||||
static void
|
static void
|
||||||
finish_norelease(ide_qrequest *qrequest, bool resubmit)
|
finish_norelease(ata_request *request, bool resubmit)
|
||||||
{
|
{
|
||||||
ide_device_info *device = qrequest->device;
|
ide_device_info *device = request->device;
|
||||||
ide_bus_info *bus = device->bus;
|
ide_bus_info *bus = device->bus;
|
||||||
|
|
||||||
|
bus->qreqFree = bus->qreqActive;
|
||||||
qrequest->running = false;
|
bus->qreqActive = 0;
|
||||||
|
|
||||||
|
|
||||||
device->qreqFree = device->qreqActive;
|
|
||||||
device->qreqActive = 0;
|
|
||||||
|
|
||||||
if (bus->active_qrequest == qrequest)
|
|
||||||
bus->active_qrequest = NULL;
|
|
||||||
|
|
||||||
ACQUIRE_BEN(&bus->status_report_ben);
|
ACQUIRE_BEN(&bus->status_report_ben);
|
||||||
|
|
||||||
if (resubmit)
|
if (resubmit)
|
||||||
scsi->resubmit(qrequest->request);
|
scsi->resubmit(request->ccb);
|
||||||
else
|
else
|
||||||
scsi->finished(qrequest->request, 1);
|
scsi->finished(request->ccb, 1);
|
||||||
|
|
||||||
RELEASE_BEN(&bus->status_report_ben);
|
RELEASE_BEN(&bus->status_report_ben);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/** finish all queued requests but <ignore> of the device;
|
/** finish all queued requests but <ignore> of the device;
|
||||||
* set resubmit, if requests are to be resubmitted by xpt
|
* set resubmit, if requests are to be resubmitted by xpt
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
finish_all_requests(ide_device_info *device, ide_qrequest *ignore,
|
finish_all_requests(ide_device_info *device, ata_request *ignore,
|
||||||
int subsys_status, bool resubmit)
|
int subsys_status, bool resubmit)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -496,11 +481,11 @@ finish_all_requests(ide_device_info *device, ide_qrequest *ignore,
|
|||||||
// XXX fix this
|
// XXX fix this
|
||||||
/*
|
/*
|
||||||
for (i = 0; i < device->queue_depth; ++i) {
|
for (i = 0; i < device->queue_depth; ++i) {
|
||||||
ide_qrequest *qrequest = &device->qreq_array[i];
|
ata_request *request = &device->qreq_array[i];
|
||||||
|
|
||||||
if (qrequest->running && qrequest != ignore) {
|
if (request->running && request != ignore) {
|
||||||
qrequest->request->subsys_status = subsys_status;
|
request->ccb->subsys_status = subsys_status;
|
||||||
finish_norelease(qrequest, resubmit);
|
finish_norelease(request, resubmit);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
@ -526,7 +511,6 @@ ide_sim_init_bus(device_node_handle node, void *user_cookie, void **cookie)
|
|||||||
memset(bus, 0, sizeof(*bus));
|
memset(bus, 0, sizeof(*bus));
|
||||||
bus->node = node;
|
bus->node = node;
|
||||||
bus->lock = 0;
|
bus->lock = 0;
|
||||||
bus->active_qrequest = NULL;
|
|
||||||
bus->disconnected = false;
|
bus->disconnected = false;
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -537,13 +521,9 @@ ide_sim_init_bus(device_node_handle node, void *user_cookie, void **cookie)
|
|||||||
sprintf(bus->name, "ide_bus %d", (int)channel_id);
|
sprintf(bus->name, "ide_bus %d", (int)channel_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
init_synced_pc(&bus->disconnect_syncinfo, disconnect_worker);
|
|
||||||
|
|
||||||
bus->scsi_cookie = user_cookie;
|
bus->scsi_cookie = user_cookie;
|
||||||
bus->state = ata_state_idle;
|
bus->state = ata_state_idle;
|
||||||
bus->timer.bus = bus;
|
bus->timer.bus = bus;
|
||||||
bus->synced_pc_list = NULL;
|
|
||||||
|
|
||||||
if ((status = scsi->alloc_dpc(&bus->irq_dpc)) < B_OK)
|
if ((status = scsi->alloc_dpc(&bus->irq_dpc)) < B_OK)
|
||||||
goto err1;
|
goto err1;
|
||||||
@ -568,6 +548,12 @@ ide_sim_init_bus(device_node_handle node, void *user_cookie, void **cookie)
|
|||||||
|
|
||||||
bus->first_device = NULL;
|
bus->first_device = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
bus->qreqActive = NULL;
|
||||||
|
bus->qreqFree = (ata_request *)malloc(sizeof(ata_request));
|
||||||
|
|
||||||
|
memset(bus->qreqFree, 0, sizeof(ata_request));
|
||||||
|
|
||||||
// read restrictions of controller
|
// read restrictions of controller
|
||||||
|
|
||||||
if (pnp->get_attr_uint8(node, IDE_CONTROLLER_MAX_DEVICES_ITEM,
|
if (pnp->get_attr_uint8(node, IDE_CONTROLLER_MAX_DEVICES_ITEM,
|
||||||
@ -606,8 +592,6 @@ err5:
|
|||||||
err4:
|
err4:
|
||||||
scsi->free_dpc(bus->irq_dpc);
|
scsi->free_dpc(bus->irq_dpc);
|
||||||
err1:
|
err1:
|
||||||
uninit_synced_pc(&bus->disconnect_syncinfo);
|
|
||||||
err:
|
|
||||||
free(bus);
|
free(bus);
|
||||||
|
|
||||||
return status;
|
return status;
|
||||||
@ -627,7 +611,10 @@ ide_sim_uninit_bus(ide_bus_info *bus)
|
|||||||
|
|
||||||
DELETE_BEN(&bus->status_report_ben);
|
DELETE_BEN(&bus->status_report_ben);
|
||||||
scsi->free_dpc(bus->irq_dpc);
|
scsi->free_dpc(bus->irq_dpc);
|
||||||
uninit_synced_pc(&bus->disconnect_syncinfo);
|
|
||||||
|
if (bus->qreqActive)
|
||||||
|
dprintf("ide_sim_uninit_bus: Warning request still active\n");
|
||||||
|
free(bus->qreqFree);
|
||||||
|
|
||||||
free(bus);
|
free(bus);
|
||||||
|
|
||||||
@ -635,22 +622,6 @@ ide_sim_uninit_bus(ide_bus_info *bus)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// abort all running requests with SCSI_NO_HBA; finally, unblock bus
|
|
||||||
static void
|
|
||||||
disconnect_worker(ide_bus_info *bus, void *arg)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (i = 0; i < bus->max_devices; ++i) {
|
|
||||||
if (bus->devices[i])
|
|
||||||
// is this the proper error code?
|
|
||||||
finish_all_requests(bus->devices[i], NULL, SCSI_NO_HBA, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
scsi->unblock_bus(bus->scsi_cookie);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ide_sim_bus_removed(device_node_handle node, ide_bus_info *bus)
|
ide_sim_bus_removed(device_node_handle node, ide_bus_info *bus)
|
||||||
{
|
{
|
||||||
@ -664,9 +635,9 @@ ide_sim_bus_removed(device_node_handle node, ide_bus_info *bus)
|
|||||||
scsi->block_bus(bus->scsi_cookie);
|
scsi->block_bus(bus->scsi_cookie);
|
||||||
// make sure, we refuse all new commands
|
// make sure, we refuse all new commands
|
||||||
bus->disconnected = true;
|
bus->disconnected = true;
|
||||||
|
|
||||||
// abort all running commands with SCSI_NO_HBA
|
// abort all running commands with SCSI_NO_HBA
|
||||||
// (the scheduled function also unblocks the bus when finished)
|
// XXX
|
||||||
schedule_synced_pc(bus, &bus->disconnect_syncinfo, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
extern scsi_for_sim_interface *scsi;
|
extern scsi_for_sim_interface *scsi;
|
||||||
extern scsi_sim_interface ide_sim_module;
|
extern scsi_sim_interface ide_sim_module;
|
||||||
|
|
||||||
// set sense of current request
|
// set sense of current ccb
|
||||||
static inline void
|
static inline void
|
||||||
set_sense(ide_device_info *device, int sense_key, int sense_asc)
|
set_sense(ide_device_info *device, int sense_key, int sense_asc)
|
||||||
{
|
{
|
||||||
@ -54,21 +54,21 @@ decode_sense_asc_ascq(uint32 combined_sense)
|
|||||||
return combined_sense & 0xffff;
|
return combined_sense & 0xffff;
|
||||||
}
|
}
|
||||||
|
|
||||||
void finish_request(ide_qrequest *qrequest, bool resubmit);
|
void finish_request(ata_request *request, bool resubmit);
|
||||||
void finish_reset_queue(ide_qrequest *qrequest);
|
void finish_reset_queue(ata_request *request);
|
||||||
void finish_retry(ide_qrequest *qrequest);
|
void finish_retry(ata_request *request);
|
||||||
void finish_all_requests(ide_device_info *device, ide_qrequest *ignore,
|
void finish_all_requests(ide_device_info *device, ata_request *ignore,
|
||||||
int subsys_status, bool resubmit);
|
int subsys_status, bool resubmit);
|
||||||
void finish_checksense(ide_qrequest *qrequest);
|
void finish_checksense(ata_request *request);
|
||||||
|
|
||||||
|
|
||||||
// start request by resetting sense
|
// start ccb by resetting sense
|
||||||
static inline void
|
static inline void
|
||||||
start_request(ide_device_info *device, ide_qrequest *qrequest)
|
start_request(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
device->new_combined_sense = 0;
|
device->new_combined_sense = 0;
|
||||||
device->subsys_status = SCSI_REQ_CMP;
|
device->subsys_status = SCSI_REQ_CMP;
|
||||||
qrequest->request->device_status = SCSI_STATUS_GOOD;
|
request->ccb->device_status = SCSI_STATUS_GOOD;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,15 +50,15 @@
|
|||||||
|
|
||||||
/*! Prepare PIO transfer */
|
/*! Prepare PIO transfer */
|
||||||
void
|
void
|
||||||
prep_PIO_transfer(ide_device_info *device, ide_qrequest *qrequest)
|
prep_PIO_transfer(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
SHOW_FLOW0(4, "");
|
SHOW_FLOW0(4, "");
|
||||||
|
|
||||||
device->left_sg_elem = qrequest->request->sg_count;
|
device->left_sg_elem = request->ccb->sg_count;
|
||||||
device->cur_sg_elem = qrequest->request->sg_list;
|
device->cur_sg_elem = request->ccb->sg_list;
|
||||||
device->cur_sg_ofs = 0;
|
device->cur_sg_ofs = 0;
|
||||||
device->has_odd_byte = false;
|
device->has_odd_byte = false;
|
||||||
qrequest->request->data_resid = qrequest->request->data_length;
|
request->ccb->data_resid = request->ccb->data_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -280,22 +280,22 @@ read_discard_PIO(ide_device_info *device, int length)
|
|||||||
B_ERROR - something serious went wrong, sense data was set
|
B_ERROR - something serious went wrong, sense data was set
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
write_PIO_block(ide_qrequest *qrequest, int length)
|
write_PIO_block(ata_request *request, int length)
|
||||||
{
|
{
|
||||||
ide_device_info *device = qrequest->device;
|
ide_device_info *device = request->device;
|
||||||
int transferred;
|
int transferred;
|
||||||
status_t err;
|
status_t err;
|
||||||
|
|
||||||
transferred = 0;
|
transferred = 0;
|
||||||
err = transfer_PIO_block(device, length, true, &transferred);
|
err = transfer_PIO_block(device, length, true, &transferred);
|
||||||
|
|
||||||
qrequest->request->data_resid -= transferred;
|
request->ccb->data_resid -= transferred;
|
||||||
|
|
||||||
if (err != ERR_TOO_BIG)
|
if (err != ERR_TOO_BIG)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
// there may be a pending odd byte - transmit that now
|
// there may be a pending odd byte - transmit that now
|
||||||
if (qrequest->device->has_odd_byte) {
|
if (request->device->has_odd_byte) {
|
||||||
uint8 buffer[2];
|
uint8 buffer[2];
|
||||||
|
|
||||||
buffer[0] = device->odd_byte;
|
buffer[0] = device->odd_byte;
|
||||||
@ -303,7 +303,7 @@ write_PIO_block(ide_qrequest *qrequest, int length)
|
|||||||
|
|
||||||
device->has_odd_byte = false;
|
device->has_odd_byte = false;
|
||||||
|
|
||||||
qrequest->request->data_resid -= 1;
|
request->ccb->data_resid -= 1;
|
||||||
transferred += 2;
|
transferred += 2;
|
||||||
|
|
||||||
device->bus->controller->write_pio(device->bus->channel_cookie, (uint16 *)buffer, 1, false);
|
device->bus->controller->write_pio(device->bus->channel_cookie, (uint16 *)buffer, 1, false);
|
||||||
@ -318,7 +318,7 @@ write_PIO_block(ide_qrequest *qrequest, int length)
|
|||||||
// Sadly, this behaviour is OK for ATAPI packets, but there is no
|
// Sadly, this behaviour is OK for ATAPI packets, but there is no
|
||||||
// way to tell the device that we don't have any data left;
|
// way to tell the device that we don't have any data left;
|
||||||
// only solution is to send zero bytes, though it's BAD BAD BAD
|
// only solution is to send zero bytes, though it's BAD BAD BAD
|
||||||
write_discard_PIO(qrequest->device, length - transferred);
|
write_discard_PIO(request->device, length - transferred);
|
||||||
return ERR_TOO_BIG;
|
return ERR_TOO_BIG;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,23 +327,23 @@ write_PIO_block(ide_qrequest *qrequest, int length)
|
|||||||
return: see write_PIO_block
|
return: see write_PIO_block
|
||||||
*/
|
*/
|
||||||
status_t
|
status_t
|
||||||
read_PIO_block(ide_qrequest *qrequest, int length)
|
read_PIO_block(ata_request *request, int length)
|
||||||
{
|
{
|
||||||
ide_device_info *device = qrequest->device;
|
ide_device_info *device = request->device;
|
||||||
int transferred;
|
int transferred;
|
||||||
status_t err;
|
status_t err;
|
||||||
|
|
||||||
transferred = 0;
|
transferred = 0;
|
||||||
err = transfer_PIO_block(qrequest->device, length, false, &transferred);
|
err = transfer_PIO_block(request->device, length, false, &transferred);
|
||||||
|
|
||||||
qrequest->request->data_resid -= transferred;
|
request->ccb->data_resid -= transferred;
|
||||||
|
|
||||||
// if length was odd, there's an extra byte waiting in device->odd_byte
|
// if length was odd, there's an extra byte waiting in device->odd_byte
|
||||||
if (device->has_odd_byte) {
|
if (device->has_odd_byte) {
|
||||||
// discard byte
|
// discard byte
|
||||||
device->has_odd_byte = false;
|
device->has_odd_byte = false;
|
||||||
// adjust res_id as the extra byte didn't reach the buffer
|
// adjust res_id as the extra byte didn't reach the buffer
|
||||||
++qrequest->request->data_resid;
|
++request->ccb->data_resid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err != ERR_TOO_BIG)
|
if (err != ERR_TOO_BIG)
|
||||||
@ -358,6 +358,6 @@ read_PIO_block(ide_qrequest *qrequest, int length)
|
|||||||
return err;
|
return err;
|
||||||
|
|
||||||
SHOW_FLOW(3, "discarding after %d bytes", transferred);
|
SHOW_FLOW(3, "discarding after %d bytes", transferred);
|
||||||
read_discard_PIO(qrequest->device, length - transferred);
|
read_discard_PIO(request->device, length - transferred);
|
||||||
return ERR_TOO_BIG;
|
return ERR_TOO_BIG;
|
||||||
}
|
}
|
||||||
|
@ -22,10 +22,10 @@
|
|||||||
/** emulate MODE SENSE 10 command */
|
/** emulate MODE SENSE 10 command */
|
||||||
|
|
||||||
static void
|
static void
|
||||||
ata_mode_sense_10(ide_device_info *device, ide_qrequest *qrequest)
|
ata_mode_sense_10(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
scsi_ccb *request = qrequest->request;
|
scsi_ccb *ccb = request->ccb;
|
||||||
scsi_cmd_mode_sense_10 *cmd = (scsi_cmd_mode_sense_10 *)request->cdb;
|
scsi_cmd_mode_sense_10 *cmd = (scsi_cmd_mode_sense_10 *)ccb->cdb;
|
||||||
scsi_mode_param_header_10 param_header;
|
scsi_mode_param_header_10 param_header;
|
||||||
scsi_modepage_control control;
|
scsi_modepage_control control;
|
||||||
scsi_mode_param_block_desc block_desc;
|
scsi_mode_param_block_desc block_desc;
|
||||||
@ -53,17 +53,17 @@ ata_mode_sense_10(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//param_header = (scsi_mode_param_header_10 *)request->data;
|
//param_header = (scsi_mode_param_header_10 *)ccb->data;
|
||||||
param_header.mode_data_length = B_HOST_TO_BENDIAN_INT16(totalLength - 1);
|
param_header.mode_data_length = B_HOST_TO_BENDIAN_INT16(totalLength - 1);
|
||||||
param_header.medium_type = 0; // XXX standard is a bit vague here
|
param_header.medium_type = 0; // XXX standard is a bit vague here
|
||||||
param_header.dev_spec_parameter = *(uint8 *)&devspec;
|
param_header.dev_spec_parameter = *(uint8 *)&devspec;
|
||||||
param_header.block_desc_length
|
param_header.block_desc_length
|
||||||
= B_HOST_TO_BENDIAN_INT16(sizeof(scsi_mode_param_block_desc));
|
= B_HOST_TO_BENDIAN_INT16(sizeof(scsi_mode_param_block_desc));
|
||||||
|
|
||||||
copy_sg_data(request, 0, allocationLength, ¶m_header,
|
copy_sg_data(ccb, 0, allocationLength, ¶m_header,
|
||||||
sizeof(param_header), false);
|
sizeof(param_header), false);
|
||||||
|
|
||||||
/*block_desc = (scsi_mode_param_block_desc *)(request->data
|
/*block_desc = (scsi_mode_param_block_desc *)(ccb->data
|
||||||
+ sizeof(*param_header));*/
|
+ sizeof(*param_header));*/
|
||||||
memset(&block_desc, 0, sizeof(block_desc));
|
memset(&block_desc, 0, sizeof(block_desc));
|
||||||
// density is reserved (0), descriptor apply to entire medium (num_blocks=0)
|
// density is reserved (0), descriptor apply to entire medium (num_blocks=0)
|
||||||
@ -72,10 +72,10 @@ ata_mode_sense_10(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
block_desc.med_blocklen = 512 >> 8;
|
block_desc.med_blocklen = 512 >> 8;
|
||||||
block_desc.low_blocklen = 512 & 0xff;
|
block_desc.low_blocklen = 512 & 0xff;
|
||||||
|
|
||||||
copy_sg_data(request, sizeof(param_header), allocationLength,
|
copy_sg_data(ccb, sizeof(param_header), allocationLength,
|
||||||
&block_desc, sizeof(block_desc), false);
|
&block_desc, sizeof(block_desc), false);
|
||||||
|
|
||||||
/*contr = (scsi_modepage_contr *)(request->data
|
/*contr = (scsi_modepage_contr *)(ccb->data
|
||||||
+ sizeof(*param_header)
|
+ sizeof(*param_header)
|
||||||
+ ((uint16)param_header->high_block_desc_len << 8)
|
+ ((uint16)param_header->high_block_desc_len << 8)
|
||||||
+ param_header->low_block_desc_len);*/
|
+ param_header->low_block_desc_len);*/
|
||||||
@ -88,22 +88,22 @@ ata_mode_sense_10(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
// lost commands automagically
|
// lost commands automagically
|
||||||
control.QAM = SCSI_QAM_UNRESTRICTED;
|
control.QAM = SCSI_QAM_UNRESTRICTED;
|
||||||
|
|
||||||
copy_sg_data(request, sizeof(param_header)
|
copy_sg_data(ccb, sizeof(param_header)
|
||||||
+ B_BENDIAN_TO_HOST_INT16(param_header.block_desc_length),
|
+ B_BENDIAN_TO_HOST_INT16(param_header.block_desc_length),
|
||||||
allocationLength, &control, sizeof(control), false);
|
allocationLength, &control, sizeof(control), false);
|
||||||
|
|
||||||
// the number of bytes that were transferred to buffer is
|
// the number of bytes that were transferred to buffer is
|
||||||
// restricted by allocation length and by request data buffer size
|
// restricted by allocation length and by ccb data buffer size
|
||||||
totalLength = min(totalLength, allocationLength);
|
totalLength = min(totalLength, allocationLength);
|
||||||
totalLength = min(totalLength, request->data_length);
|
totalLength = min(totalLength, ccb->data_length);
|
||||||
|
|
||||||
request->data_resid = request->data_length - totalLength;
|
ccb->data_resid = ccb->data_length - totalLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Emulate modifying control page */
|
/*! Emulate modifying control page */
|
||||||
static bool
|
static bool
|
||||||
ata_mode_select_control_page(ide_device_info *device, ide_qrequest *qrequest,
|
ata_mode_select_control_page(ide_device_info *device, ata_request *request,
|
||||||
scsi_modepage_control *page)
|
scsi_modepage_control *page)
|
||||||
{
|
{
|
||||||
if (page->header.page_length != sizeof(*page) - sizeof(page->header)) {
|
if (page->header.page_length != sizeof(*page) - sizeof(page->header)) {
|
||||||
@ -119,10 +119,10 @@ ata_mode_select_control_page(ide_device_info *device, ide_qrequest *qrequest,
|
|||||||
|
|
||||||
/*! Emulate MODE SELECT 10 command */
|
/*! Emulate MODE SELECT 10 command */
|
||||||
static void
|
static void
|
||||||
ata_mode_select_10(ide_device_info *device, ide_qrequest *qrequest)
|
ata_mode_select_10(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
scsi_ccb *request = qrequest->request;
|
scsi_ccb *ccb = request->ccb;
|
||||||
scsi_cmd_mode_select_10 *cmd = (scsi_cmd_mode_select_10 *)request->cdb;
|
scsi_cmd_mode_select_10 *cmd = (scsi_cmd_mode_select_10 *)ccb->cdb;
|
||||||
scsi_mode_param_header_10 param_header;
|
scsi_mode_param_header_10 param_header;
|
||||||
scsi_modepage_header page_header;
|
scsi_modepage_header page_header;
|
||||||
uint32 totalLength;
|
uint32 totalLength;
|
||||||
@ -134,12 +134,12 @@ ata_mode_select_10(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
totalLength = min(request->data_length,
|
totalLength = min(ccb->data_length,
|
||||||
B_BENDIAN_TO_HOST_INT16(cmd->param_list_length));
|
B_BENDIAN_TO_HOST_INT16(cmd->param_list_length));
|
||||||
|
|
||||||
// first, retrieve page header to get size of different chunks
|
// first, retrieve page header to get size of different chunks
|
||||||
//param_header = (scsi_mode_param_header_10 *)request->data;
|
//param_header = (scsi_mode_param_header_10 *)ccb->data;
|
||||||
if (!copy_sg_data(request, 0, totalLength, ¶m_header, sizeof(param_header), true))
|
if (!copy_sg_data(ccb, 0, totalLength, ¶m_header, sizeof(param_header), true))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
totalLength = min(totalLength,
|
totalLength = min(totalLength,
|
||||||
@ -155,7 +155,7 @@ ata_mode_select_10(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
uint32 pageLength;
|
uint32 pageLength;
|
||||||
|
|
||||||
// get header to know how long page is
|
// get header to know how long page is
|
||||||
if (!copy_sg_data(request, modepageOffset, totalLength,
|
if (!copy_sg_data(ccb, modepageOffset, totalLength,
|
||||||
&page_header, sizeof(page_header), true))
|
&page_header, sizeof(page_header), true))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
@ -167,7 +167,7 @@ ata_mode_select_10(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
if (pageLength > sizeof(modepage_buffer))
|
if (pageLength > sizeof(modepage_buffer))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
if (!copy_sg_data(request, modepageOffset, totalLength,
|
if (!copy_sg_data(ccb, modepageOffset, totalLength,
|
||||||
&modepage_buffer, min(pageLength, sizeof(modepage_buffer)), true))
|
&modepage_buffer, min(pageLength, sizeof(modepage_buffer)), true))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
@ -175,7 +175,7 @@ ata_mode_select_10(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
// currently, we only support the control mode page
|
// currently, we only support the control mode page
|
||||||
switch (page_header.page_code) {
|
switch (page_header.page_code) {
|
||||||
case SCSI_MODEPAGE_CONTROL:
|
case SCSI_MODEPAGE_CONTROL:
|
||||||
if (!ata_mode_select_control_page(device, qrequest,
|
if (!ata_mode_select_control_page(device, request,
|
||||||
(scsi_modepage_control *)modepage_buffer))
|
(scsi_modepage_control *)modepage_buffer))
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
@ -192,7 +192,7 @@ ata_mode_select_10(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
if (modepageOffset != totalLength)
|
if (modepageOffset != totalLength)
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
request->data_resid = request->data_length - totalLength;
|
ccb->data_resid = ccb->data_length - totalLength;
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// if we arrive here, data length was incorrect
|
// if we arrive here, data length was incorrect
|
||||||
@ -203,7 +203,7 @@ err:
|
|||||||
|
|
||||||
/*! Emulate TEST UNIT READY */
|
/*! Emulate TEST UNIT READY */
|
||||||
static bool
|
static bool
|
||||||
ata_test_unit_ready(ide_device_info *device, ide_qrequest *qrequest)
|
ata_test_unit_ready(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
SHOW_FLOW0(3, "");
|
SHOW_FLOW0(3, "");
|
||||||
@ -216,16 +216,16 @@ ata_test_unit_ready(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
device->tf_param_mask = 0;
|
device->tf_param_mask = 0;
|
||||||
device->tf.write.command = IDE_CMD_GET_MEDIA_STATUS;
|
device->tf.write.command = IDE_CMD_GET_MEDIA_STATUS;
|
||||||
|
|
||||||
if (!send_command(device, qrequest, true, 15, ide_state_sync_waiting))
|
if (!send_command(device, request, true, 15, ide_state_sync_waiting))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// bits ide_error_mcr | ide_error_mc | ide_error_wp are also valid
|
// bits ide_error_mcr | ide_error_mc | ide_error_wp are also valid
|
||||||
// but not requested by TUR; ide_error_wp can safely be ignored, but
|
// but not requested by TUR; ide_error_wp can safely be ignored, but
|
||||||
// we don't want to loose media change (request) reports
|
// we don't want to loose media change (ccb) reports
|
||||||
if (!check_output(device, true,
|
if (!check_output(device, true,
|
||||||
ide_error_nm | ide_error_abrt | ide_error_mcr | ide_error_mc,
|
ide_error_nm | ide_error_abrt | ide_error_mcr | ide_error_mc,
|
||||||
false)) {
|
false)) {
|
||||||
// SCSI spec is unclear here: we shouldn't report "media change (request)"
|
// SCSI spec is unclear here: we shouldn't report "media change (ccb)"
|
||||||
// but what to do if there is one? anyway - we report them
|
// but what to do if there is one? anyway - we report them
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
@ -237,7 +237,7 @@ ata_test_unit_ready(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
|
|
||||||
/*! Flush internal device cache */
|
/*! Flush internal device cache */
|
||||||
static bool
|
static bool
|
||||||
ata_flush_cache(ide_device_info *device, ide_qrequest *qrequest)
|
ata_flush_cache(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
// we should also ask for FLUSH CACHE support, but everyone denies it
|
// we should also ask for FLUSH CACHE support, but everyone denies it
|
||||||
@ -251,7 +251,7 @@ ata_flush_cache(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
: IDE_CMD_FLUSH_CACHE;
|
: IDE_CMD_FLUSH_CACHE;
|
||||||
|
|
||||||
// spec says that this may take more then 30s, how much more?
|
// spec says that this may take more then 30s, how much more?
|
||||||
if (!send_command(device, qrequest, true, 60, ide_state_sync_waiting))
|
if (!send_command(device, request, true, 60, ide_state_sync_waiting))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
wait_for_sync(device->bus);
|
wait_for_sync(device->bus);
|
||||||
@ -266,7 +266,7 @@ ata_flush_cache(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
load = true - load medium
|
load = true - load medium
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
ata_load_eject(ide_device_info *device, ide_qrequest *qrequest, bool load)
|
ata_load_eject(ide_device_info *device, ata_request *request, bool load)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
if (load) {
|
if (load) {
|
||||||
@ -278,7 +278,7 @@ ata_load_eject(ide_device_info *device, ide_qrequest *qrequest, bool load)
|
|||||||
device->tf_param_mask = 0;
|
device->tf_param_mask = 0;
|
||||||
device->tf.lba.command = IDE_CMD_MEDIA_EJECT;
|
device->tf.lba.command = IDE_CMD_MEDIA_EJECT;
|
||||||
|
|
||||||
if (!send_command(device, qrequest, true, 15, ide_state_sync_waiting))
|
if (!send_command(device, request, true, 15, ide_state_sync_waiting))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
wait_for_sync(device->bus);
|
wait_for_sync(device->bus);
|
||||||
@ -300,11 +300,11 @@ ata_prevent_allow(ide_device_info *device, bool prevent)
|
|||||||
|
|
||||||
/*! Emulate INQUIRY command */
|
/*! Emulate INQUIRY command */
|
||||||
static void
|
static void
|
||||||
ata_inquiry(ide_device_info *device, ide_qrequest *qrequest)
|
ata_inquiry(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
scsi_ccb *request = qrequest->request;
|
scsi_ccb *ccb = request->ccb;
|
||||||
scsi_res_inquiry data;
|
scsi_res_inquiry data;
|
||||||
scsi_cmd_inquiry *cmd = (scsi_cmd_inquiry *)request->cdb;
|
scsi_cmd_inquiry *cmd = (scsi_cmd_inquiry *)ccb->cdb;
|
||||||
uint32 allocation_length = cmd->allocation_length;
|
uint32 allocation_length = cmd->allocation_length;
|
||||||
uint32 transfer_size;
|
uint32 transfer_size;
|
||||||
|
|
||||||
@ -349,22 +349,22 @@ ata_inquiry(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
sizeof(data.product_ident));
|
sizeof(data.product_ident));
|
||||||
memcpy(data.product_rev, " ", sizeof(data.product_rev));
|
memcpy(data.product_rev, " ", sizeof(data.product_rev));
|
||||||
|
|
||||||
copy_sg_data(request, 0, allocation_length, &data, sizeof(data), false);
|
copy_sg_data(ccb, 0, allocation_length, &data, sizeof(data), false);
|
||||||
|
|
||||||
transfer_size = min(sizeof(data), allocation_length);
|
transfer_size = min(sizeof(data), allocation_length);
|
||||||
transfer_size = min(transfer_size, request->data_length);
|
transfer_size = min(transfer_size, ccb->data_length);
|
||||||
|
|
||||||
request->data_resid = request->data_length - transfer_size;
|
ccb->data_resid = ccb->data_length - transfer_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Emulate READ CAPACITY command */
|
/*! Emulate READ CAPACITY command */
|
||||||
static void
|
static void
|
||||||
read_capacity(ide_device_info *device, ide_qrequest *qrequest)
|
read_capacity(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
scsi_ccb *request = qrequest->request;
|
scsi_ccb *ccb = request->ccb;
|
||||||
scsi_res_read_capacity data;
|
scsi_res_read_capacity data;
|
||||||
scsi_cmd_read_capacity *cmd = (scsi_cmd_read_capacity *)request->cdb;
|
scsi_cmd_read_capacity *cmd = (scsi_cmd_read_capacity *)ccb->cdb;
|
||||||
uint32 lastBlock;
|
uint32 lastBlock;
|
||||||
|
|
||||||
if (cmd->pmi || cmd->lba) {
|
if (cmd->pmi || cmd->lba) {
|
||||||
@ -378,58 +378,58 @@ read_capacity(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
lastBlock = device->total_sectors - 1;
|
lastBlock = device->total_sectors - 1;
|
||||||
data.lba = B_HOST_TO_BENDIAN_INT32(lastBlock);
|
data.lba = B_HOST_TO_BENDIAN_INT32(lastBlock);
|
||||||
|
|
||||||
copy_sg_data(request, 0, request->data_length, &data, sizeof(data), false);
|
copy_sg_data(ccb, 0, ccb->data_length, &data, sizeof(data), false);
|
||||||
request->data_resid = max(request->data_length - sizeof(data), 0);
|
ccb->data_resid = max(ccb->data_length - sizeof(data), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*! Execute SCSI command */
|
/*! Execute SCSI command */
|
||||||
void
|
void
|
||||||
ata_exec_io(ide_device_info *device, ide_qrequest *qrequest)
|
ata_exec_io(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
scsi_ccb *request = qrequest->request;
|
scsi_ccb *ccb = request->ccb;
|
||||||
|
|
||||||
SHOW_FLOW(3, "command=%x", request->cdb[0]);
|
SHOW_FLOW(3, "command=%x", ccb->cdb[0]);
|
||||||
|
|
||||||
// ATA devices have one LUN only
|
// ATA devices have one LUN only
|
||||||
if (request->target_lun != 0) {
|
if (ccb->target_lun != 0) {
|
||||||
request->subsys_status = SCSI_SEL_TIMEOUT;
|
ccb->subsys_status = SCSI_SEL_TIMEOUT;
|
||||||
finish_request(qrequest, false);
|
finish_request(request, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// starting a request means deleting sense, so don't do it if
|
// starting a ccb means deleting sense, so don't do it if
|
||||||
// the command wants to read it
|
// the command wants to read it
|
||||||
if (request->cdb[0] != SCSI_OP_REQUEST_SENSE)
|
if (ccb->cdb[0] != SCSI_OP_REQUEST_SENSE)
|
||||||
start_request(device, qrequest);
|
start_request(device, request);
|
||||||
|
|
||||||
switch (request->cdb[0]) {
|
switch (ccb->cdb[0]) {
|
||||||
case SCSI_OP_TEST_UNIT_READY:
|
case SCSI_OP_TEST_UNIT_READY:
|
||||||
ata_test_unit_ready(device, qrequest);
|
ata_test_unit_ready(device, request);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCSI_OP_REQUEST_SENSE:
|
case SCSI_OP_REQUEST_SENSE:
|
||||||
ide_request_sense(device, qrequest);
|
ide_request_sense(device, request);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case SCSI_OP_FORMAT: /* FORMAT UNIT */
|
case SCSI_OP_FORMAT: /* FORMAT UNIT */
|
||||||
// we could forward request to disk, but modern disks cannot
|
// we could forward ccb to disk, but modern disks cannot
|
||||||
// be formatted anyway, so we just refuse request
|
// be formatted anyway, so we just refuse ccb
|
||||||
// (exceptions are removable media devices, but to my knowledge
|
// (exceptions are removable media devices, but to my knowledge
|
||||||
// they don't have to be formatted as well)
|
// they don't have to be formatted as well)
|
||||||
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_OPCODE);
|
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_OPCODE);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCSI_OP_INQUIRY:
|
case SCSI_OP_INQUIRY:
|
||||||
ata_inquiry(device, qrequest);
|
ata_inquiry(device, request);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCSI_OP_MODE_SELECT_10:
|
case SCSI_OP_MODE_SELECT_10:
|
||||||
ata_mode_select_10(device, qrequest);
|
ata_mode_select_10(device, request);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCSI_OP_MODE_SENSE_10:
|
case SCSI_OP_MODE_SENSE_10:
|
||||||
ata_mode_sense_10(device, qrequest);
|
ata_mode_sense_10(device, request);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCSI_OP_MODE_SELECT_6:
|
case SCSI_OP_MODE_SELECT_6:
|
||||||
@ -446,7 +446,7 @@ ata_exec_io(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case SCSI_OP_START_STOP: {
|
case SCSI_OP_START_STOP: {
|
||||||
scsi_cmd_ssu *cmd = (scsi_cmd_ssu *)request->cdb;
|
scsi_cmd_ssu *cmd = (scsi_cmd_ssu *)ccb->cdb;
|
||||||
|
|
||||||
// with no LoEj bit set, we should only allow/deny further access
|
// with no LoEj bit set, we should only allow/deny further access
|
||||||
// we ignore that (unsupported for ATA)
|
// we ignore that (unsupported for ATA)
|
||||||
@ -455,23 +455,23 @@ ata_exec_io(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
|
|
||||||
if (!cmd->start)
|
if (!cmd->start)
|
||||||
// we must always flush cache if start = 0
|
// we must always flush cache if start = 0
|
||||||
ata_flush_cache(device, qrequest);
|
ata_flush_cache(device, request);
|
||||||
|
|
||||||
if (cmd->load_eject)
|
if (cmd->load_eject)
|
||||||
ata_load_eject(device, qrequest, cmd->start);
|
ata_load_eject(device, request, cmd->start);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SCSI_OP_PREVENT_ALLOW: {
|
case SCSI_OP_PREVENT_ALLOW: {
|
||||||
scsi_cmd_prevent_allow *cmd = (scsi_cmd_prevent_allow *)request->cdb;
|
scsi_cmd_prevent_allow *cmd = (scsi_cmd_prevent_allow *)ccb->cdb;
|
||||||
|
|
||||||
ata_prevent_allow(device, cmd->prevent);
|
ata_prevent_allow(device, cmd->prevent);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SCSI_OP_READ_CAPACITY:
|
case SCSI_OP_READ_CAPACITY:
|
||||||
read_capacity(device, qrequest);
|
read_capacity(device, request);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SCSI_OP_VERIFY:
|
case SCSI_OP_VERIFY:
|
||||||
@ -482,7 +482,7 @@ ata_exec_io(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
|
|
||||||
case SCSI_OP_SYNCHRONIZE_CACHE:
|
case SCSI_OP_SYNCHRONIZE_CACHE:
|
||||||
// we ignore range and immediate bit, we always immediately flush everything
|
// we ignore range and immediate bit, we always immediately flush everything
|
||||||
ata_flush_cache(device, qrequest);
|
ata_flush_cache(device, request);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// sadly, there are two possible read/write operation codes;
|
// sadly, there are two possible read/write operation codes;
|
||||||
@ -490,7 +490,7 @@ ata_exec_io(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
case SCSI_OP_READ_6:
|
case SCSI_OP_READ_6:
|
||||||
case SCSI_OP_WRITE_6:
|
case SCSI_OP_WRITE_6:
|
||||||
{
|
{
|
||||||
scsi_cmd_rw_6 *cmd = (scsi_cmd_rw_6 *)request->cdb;
|
scsi_cmd_rw_6 *cmd = (scsi_cmd_rw_6 *)ccb->cdb;
|
||||||
uint32 pos;
|
uint32 pos;
|
||||||
size_t length;
|
size_t length;
|
||||||
|
|
||||||
@ -500,14 +500,14 @@ ata_exec_io(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
|
|
||||||
SHOW_FLOW(3, "READ6/WRITE6 pos=%lx, length=%lx", pos, length);
|
SHOW_FLOW(3, "READ6/WRITE6 pos=%lx, length=%lx", pos, length);
|
||||||
|
|
||||||
ata_send_rw(device, qrequest, pos, length, cmd->opcode == SCSI_OP_WRITE_6);
|
ata_send_rw(device, request, pos, length, cmd->opcode == SCSI_OP_WRITE_6);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SCSI_OP_READ_10:
|
case SCSI_OP_READ_10:
|
||||||
case SCSI_OP_WRITE_10:
|
case SCSI_OP_WRITE_10:
|
||||||
{
|
{
|
||||||
scsi_cmd_rw_10 *cmd = (scsi_cmd_rw_10 *)request->cdb;
|
scsi_cmd_rw_10 *cmd = (scsi_cmd_rw_10 *)ccb->cdb;
|
||||||
uint32 pos;
|
uint32 pos;
|
||||||
size_t length;
|
size_t length;
|
||||||
|
|
||||||
@ -515,10 +515,10 @@ ata_exec_io(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
length = B_BENDIAN_TO_HOST_INT16(cmd->length);
|
length = B_BENDIAN_TO_HOST_INT16(cmd->length);
|
||||||
|
|
||||||
if (length != 0) {
|
if (length != 0) {
|
||||||
ata_send_rw(device, qrequest, pos, length, cmd->opcode == SCSI_OP_WRITE_10);
|
ata_send_rw(device, request, pos, length, cmd->opcode == SCSI_OP_WRITE_10);
|
||||||
} else {
|
} else {
|
||||||
// we cannot transfer zero blocks (apart from LBA48)
|
// we cannot transfer zero blocks (apart from LBA48)
|
||||||
finish_request(qrequest, false);
|
finish_request(request, false);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -527,5 +527,5 @@ ata_exec_io(ide_device_info *device, ide_qrequest *qrequest)
|
|||||||
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_OPCODE);
|
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_OPCODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
finish_checksense(qrequest);
|
finish_checksense(request);
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ ide_dpc(void *arg)
|
|||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
ide_bus_info *bus = (ide_bus_info *)arg;
|
ide_bus_info *bus = (ide_bus_info *)arg;
|
||||||
ide_qrequest *qrequest;
|
ata_request *request;
|
||||||
ide_device_info *device;
|
ide_device_info *device;
|
||||||
|
|
||||||
TRACE(("\n"));
|
TRACE(("\n"));
|
||||||
@ -48,17 +48,17 @@ ide_dpc(void *arg)
|
|||||||
// cancel timeout
|
// cancel timeout
|
||||||
cancel_timer(&bus->timer.te);
|
cancel_timer(&bus->timer.te);
|
||||||
|
|
||||||
qrequest = bus->active_qrequest;
|
request = bus->active_qrequest;
|
||||||
device = qrequest->device;
|
device = request->device;
|
||||||
|
|
||||||
// not perfect but simple: we simply know who is waiting why
|
// not perfect but simple: we simply know who is waiting why
|
||||||
if (device->is_atapi)
|
if (device->is_atapi)
|
||||||
packet_dpc(qrequest);
|
packet_dpc(request);
|
||||||
else {
|
else {
|
||||||
if (qrequest->uses_dma)
|
if (request->uses_dma)
|
||||||
ata_dpc_DMA(qrequest);
|
ata_dpc_DMA(request);
|
||||||
else
|
else
|
||||||
ata_dpc_PIO(qrequest);
|
ata_dpc_PIO(request);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// no request active, so this must be a service request or
|
// no request active, so this must be a service request or
|
||||||
@ -139,7 +139,9 @@ ide_irq_handler(ide_bus_info *bus, uint8 status)
|
|||||||
if (bus->num_running_reqs == 0) {
|
if (bus->num_running_reqs == 0) {
|
||||||
IDE_UNLOCK(bus);
|
IDE_UNLOCK(bus);
|
||||||
return B_UNHANDLED_INTERRUPT;
|
return B_UNHANDLED_INTERRUPT;
|
||||||
}
|
}mmand
|
||||||
|
if (bus->controller->write_command_block_regs(bus->channel_cookie, &device->tf, ide_mask_command) != B_OK)
|
||||||
|
goto err_clearint;
|
||||||
|
|
||||||
bus->state = ide_state_accessing;
|
bus->state = ide_state_accessing;
|
||||||
|
|
||||||
@ -154,7 +156,9 @@ ide_irq_handler(ide_bus_info *bus, uint8 status)
|
|||||||
bus->state = ide_state_accessing;
|
bus->state = ide_state_accessing;
|
||||||
bus->sync_wait_timeout = false;
|
bus->sync_wait_timeout = false;
|
||||||
|
|
||||||
IDE_UNLOCK(bus);
|
IDE_UNLOCK(bus);mmand
|
||||||
|
if (bus->controller->write_command_block_regs(bus->channel_cookie, &device->tf, ide_mask_command) != B_OK)
|
||||||
|
goto err_clearint;
|
||||||
|
|
||||||
release_sem_etc(bus->sync_wait_sem, 1, B_DO_NOT_RESCHEDULE);
|
release_sem_etc(bus->sync_wait_sem, 1, B_DO_NOT_RESCHEDULE);
|
||||||
return B_INVOKE_SCHEDULER;
|
return B_INVOKE_SCHEDULER;
|
||||||
@ -199,7 +203,9 @@ cancel_irq_timeout(ide_bus_info *bus)
|
|||||||
|
|
||||||
void
|
void
|
||||||
start_waiting(ide_bus_info *bus, uint32 timeout, int new_state)
|
start_waiting(ide_bus_info *bus, uint32 timeout, int new_state)
|
||||||
{
|
{mmand
|
||||||
|
if (bus->controller->write_command_block_regs(bus->channel_cookie, &device->tf, ide_mask_command) != B_OK)
|
||||||
|
goto err_clearint;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
TRACE(("timeout = %u\n", (uint)timeout));
|
TRACE(("timeout = %u\n", (uint)timeout));
|
||||||
@ -241,21 +247,21 @@ wait_for_sync(ide_bus_info *bus)
|
|||||||
static void
|
static void
|
||||||
ide_timeout_dpc(void *arg)
|
ide_timeout_dpc(void *arg)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
ide_bus_info *bus = (ide_bus_info *)arg;
|
ide_bus_info *bus = (ide_bus_info *)arg;
|
||||||
ide_qrequest *qrequest;
|
ata_request *request;
|
||||||
ide_device_info *device;
|
ide_device_info *device;
|
||||||
|
|
||||||
qrequest = bus->active_qrequest;
|
device = request->device;
|
||||||
device = qrequest->device;
|
|
||||||
|
|
||||||
dprintf("ide: ide_timeout_dpc() bus %p, device %p\n", bus, device);
|
dprintf("ide: ide_timeout_dpc() bus %p, device %p\n", bus, device);
|
||||||
|
|
||||||
// this also resets overlapped commands
|
// this also resets overlapped commands
|
||||||
// reset_device(device, qrequest);
|
// reset_device(device, request);
|
||||||
|
|
||||||
device->subsys_status = SCSI_CMD_TIMEOUT;
|
device->subsys_status = SCSI_CMD_TIMEOUT;
|
||||||
|
|
||||||
if (qrequest->uses_dma) {
|
if (request->uses_dma) {
|
||||||
if (++device->DMA_failures >= MAX_DMA_FAILURES) {
|
if (++device->DMA_failures >= MAX_DMA_FAILURES) {
|
||||||
dprintf("Disabling DMA because of too many errors\n");
|
dprintf("Disabling DMA because of too many errors\n");
|
||||||
|
|
||||||
@ -264,7 +270,8 @@ ide_timeout_dpc(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// let upper layer do the retry
|
// let upper layer do the retry
|
||||||
finish_checksense(qrequest);
|
finish_checksense(request);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -325,99 +332,6 @@ ide_timeout(timer *arg)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
init_synced_pc(ide_synced_pc *pc, ide_synced_pc_func func)
|
|
||||||
{
|
|
||||||
pc->func = func;
|
|
||||||
pc->registered = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
uninit_synced_pc(ide_synced_pc *pc)
|
|
||||||
{
|
|
||||||
if (pc->registered)
|
|
||||||
panic("Tried to clean up pending synced PC\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** schedule a synced pc
|
|
||||||
* a synced pc gets executed as soon as the bus becomes idle
|
|
||||||
*/
|
|
||||||
|
|
||||||
status_t
|
|
||||||
schedule_synced_pc(ide_bus_info *bus, ide_synced_pc *pc, void *arg)
|
|
||||||
{
|
|
||||||
//TRACE(());
|
|
||||||
|
|
||||||
IDE_LOCK(bus);
|
|
||||||
|
|
||||||
if (pc->registered) {
|
|
||||||
// spc cannot be registered twice
|
|
||||||
TRACE(("already registered\n"));
|
|
||||||
return B_ERROR;
|
|
||||||
} else if( bus->state != ata_state_idle ) {
|
|
||||||
// bus isn't idle - spc must be added to pending list
|
|
||||||
TRACE(("adding to pending list\n"));
|
|
||||||
|
|
||||||
pc->next = bus->synced_pc_list;
|
|
||||||
bus->synced_pc_list = pc;
|
|
||||||
pc->arg = arg;
|
|
||||||
pc->registered = true;
|
|
||||||
|
|
||||||
IDE_UNLOCK(bus);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// we have luck - bus is idle, so grab it before
|
|
||||||
// releasing the lock
|
|
||||||
|
|
||||||
TRACE(("exec immediately\n"));
|
|
||||||
|
|
||||||
bus->state = ata_state_busy;
|
|
||||||
IDE_UNLOCK(bus);
|
|
||||||
|
|
||||||
TRACE(("go\n"));
|
|
||||||
pc->func(bus, arg);
|
|
||||||
|
|
||||||
TRACE(("finished\n"));
|
|
||||||
access_finished(bus, bus->first_device);
|
|
||||||
|
|
||||||
// meanwhile, we may have rejected SCSI commands;
|
|
||||||
// usually, the XPT resends them once a command
|
|
||||||
// has finished, but in this case XPT doesn't know
|
|
||||||
// about our "private" command, so we have to tell about
|
|
||||||
// idle bus manually
|
|
||||||
TRACE(("tell SCSI bus manager about idle bus\n"));
|
|
||||||
scsi->cont_send_bus(bus->scsi_cookie);
|
|
||||||
return B_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** execute list of synced pcs */
|
|
||||||
|
|
||||||
static void
|
|
||||||
exec_synced_pcs(ide_bus_info *bus, ide_synced_pc *pc_list)
|
|
||||||
{
|
|
||||||
ide_synced_pc *pc;
|
|
||||||
|
|
||||||
// noone removes items from pc_list, so we don't need lock
|
|
||||||
// to access entries
|
|
||||||
for (pc = pc_list; pc; pc = pc->next) {
|
|
||||||
pc->func(bus, pc->arg);
|
|
||||||
}
|
|
||||||
|
|
||||||
// need lock now as items can be added to pc_list again as soon
|
|
||||||
// as <registered> is reset
|
|
||||||
IDE_LOCK(bus);
|
|
||||||
|
|
||||||
for (pc = pc_list; pc; pc = pc->next) {
|
|
||||||
pc->registered = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
IDE_UNLOCK(bus);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/** finish bus access;
|
/** finish bus access;
|
||||||
* check if any device wants to service pending commands + execute synced_pc
|
* check if any device wants to service pending commands + execute synced_pc
|
||||||
@ -428,33 +342,5 @@ access_finished(ide_bus_info *bus, ide_device_info *device)
|
|||||||
{
|
{
|
||||||
TRACE(("bus = %p, device = %p\n", bus, device));
|
TRACE(("bus = %p, device = %p\n", bus, device));
|
||||||
|
|
||||||
while (true) {
|
// this would be the correct place to called synced pc
|
||||||
ide_synced_pc *synced_pc_list;
|
|
||||||
|
|
||||||
IDE_LOCK(bus);
|
|
||||||
|
|
||||||
// normally, there is always an device; only exception is a
|
|
||||||
// bus without devices, not sure whether this can really happen though
|
|
||||||
if (device) {
|
|
||||||
// if (try_service(device))
|
|
||||||
// return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// noone wants it, so execute pending synced_pc
|
|
||||||
if (bus->synced_pc_list == NULL) {
|
|
||||||
bus->state = ata_state_idle;
|
|
||||||
IDE_UNLOCK(bus);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
synced_pc_list = bus->synced_pc_list;
|
|
||||||
bus->synced_pc_list = NULL;
|
|
||||||
|
|
||||||
IDE_UNLOCK(bus);
|
|
||||||
|
|
||||||
exec_synced_pcs(bus, synced_pc_list);
|
|
||||||
|
|
||||||
// executed synced_pc may have generated other sync_pc,
|
|
||||||
// thus the loop
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user