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:
Marcus Overhagen 2008-01-09 21:58:23 +00:00
parent 6e796d9fbe
commit 5558f70663
11 changed files with 388 additions and 620 deletions

View File

@ -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);

View File

@ -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);
} }
} }

View File

@ -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

View File

@ -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);
} }

View File

@ -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) {

View File

@ -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);

View File

@ -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);
} }

View File

@ -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;
} }

View File

@ -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;
} }

View File

@ -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, &param_header, copy_sg_data(ccb, 0, allocationLength, &param_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, &param_header, sizeof(param_header), true)) if (!copy_sg_data(ccb, 0, totalLength, &param_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);
} }

View File

@ -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
}
} }