started reimplementing pio command completition...

git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23336 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Marcus Overhagen 2008-01-09 23:59:00 +00:00
parent 17b30c87ea
commit dd7579a79b
4 changed files with 78 additions and 48 deletions

View File

@ -125,6 +125,17 @@ ata_wait_for_drdy(ide_bus_info *bus)
}
// busy wait for device beeing ready,
// using the timeout set by the previous ata_send_command
status_t
ata_pio_wait_drdy(ide_device_info *device)
{
ASSERT(bus->state == ata_state_pio);
return ata_wait(bus, ide_status_drdy, ide_status_bsy, false, device->bus->pio_timeout);
}
status_t
ata_send_command(ide_device_info *device, ata_request *request,
bool need_drdy, uint32 timeout, ata_bus_state new_state)
@ -189,6 +200,7 @@ ata_send_command(ide_device_info *device, ata_request *request,
ASSERT(bus->state == ata_state_busy);
bus->state = new_state;
bus->pio_timeout = timeout * 1000;
IDE_UNLOCK(bus);
@ -205,6 +217,11 @@ err:
return B_ERROR;
}
status_t
ata_finish_command(ide_device_info *device)
{
}
status_t
ata_reset_bus(ide_bus_info *bus, bool *_devicePresent0, uint32 *_sigDev0, bool *_devicePresent1, uint32 *_sigDev1)
@ -275,7 +292,7 @@ ata_reset_bus(ide_bus_info *bus, bool *_devicePresent0, uint32 *_sigDev0, bool *
dprintf("ATA: reset_bus: timeout\n");
goto error;
}
timeout
if (controller->read_command_block_regs(channel, &tf, ide_mask_sector_count |
ide_mask_LBA_low | ide_mask_LBA_mid | ide_mask_LBA_high | ide_mask_error) != B_OK)
goto error;
@ -594,7 +611,7 @@ err:
*/
void
ata_send_rw(ide_device_info *device, ata_request *request,
ata_exec_read_write(ide_device_info *device, ata_request *request,
uint64 pos, size_t length, bool write)
{
ide_bus_info *bus = device->bus;

View File

@ -62,15 +62,26 @@ typedef struct 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
struct ide_device_info * device;
scsi_ccb * ccb; // basic scsi 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;
//void init_ata_request(ata_request *request, struct ide_device_info *device, scsi_ccb *ccb);
static inline void
init_ata_request(ata_request *request, struct ide_device_info *device, scsi_ccb *ccb)
{
request->device = device;
request->ccb = ccb;
request->is_write = 0;
request->uses_dma = 0;
request->packet_irq = 0;
}
typedef struct ide_device_info {
struct ide_bus_info *bus;
@ -118,6 +129,7 @@ typedef struct ide_device_info {
uint8 device_type; // atapi device type
// pio from here on
bigtime_t pio_timeout;
int left_sg_elem; // remaining sg elements
const physical_entry *cur_sg_elem; // active sg element
int cur_sg_ofs; // offset in active sg element
@ -160,8 +172,8 @@ struct ide_bus_info {
ata_bus_state state; // current state of bus
struct ata_request * qreqActive;
struct ata_request * qreqFree;
struct ata_request * requestActive;
struct ata_request * requestFree;
benaphore status_report_ben; // to lock when you report XPT about bus state
@ -218,12 +230,12 @@ 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_device(ide_device_info *device, bool *_devicePresent);
status_t ata_send_command(ide_device_info *device, ata_request *request, bool need_drdy, uint32 timeout, ata_bus_state new_state);
status_t ata_finish_command(ide_device_info *device);
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);
void ata_send_rw(ide_device_info *device, ata_request *request,
uint64 pos, size_t length, bool write);
void ata_exec_read_write(ide_device_info *device, ata_request *request, uint64 pos, size_t length, bool write);
void ata_dpc_DMA(ata_request *request);
void ata_dpc_PIO(ata_request *request);

View File

@ -46,8 +46,6 @@ static void
sim_scsi_io(ide_bus_info *bus, scsi_ccb *ccb)
{
ide_device_info *device;
ata_request *request;
//ide_request_priv *priv;
FLOW("sim_scsi_iobus %p, %d:%d\n", bus, ccb->target_id, ccb->target_lun);
@ -76,7 +74,7 @@ sim_scsi_io(ide_bus_info *bus, scsi_ccb *ccb)
goto err_bus_busy;
// bail out if device can't accept further requests
if (bus->qreqFree == NULL)
if (bus->requestFree == NULL)
goto err_device_busy;
bus->state = ata_state_busy;
@ -85,17 +83,15 @@ sim_scsi_io(ide_bus_info *bus, scsi_ccb *ccb)
RELEASE_BEN(&bus->status_report_ben);
// as we own the bus, noone can bother us
request = bus->qreqFree;
bus->qreqFree = NULL;
bus->qreqActive = request;
ASSERT(bus->requestActive == NULL);
bus->requestActive = bus->requestFree;
bus->requestFree = NULL;
request->device = device;
request->ccb = ccb;
request->uses_dma = false;
init_ata_request(bus->requestActive, device, ccb);
FLOW("calling exec_io: %p, %d:%d\n", bus, ccb->target_id, ccb->target_lun);
device->exec_io(device, request);
device->exec_io(device, bus->requestActive);
return;
@ -187,14 +183,12 @@ scan_bus(ide_bus_info *bus)
if (bus->disconnected)
return;
// XXX fix me
IDE_LOCK(bus);
ASSERT(bus->state == ata_state_idle);
bus->state = ata_state_busy;
IDE_UNLOCK(bus);
for (i = 0; i < bus->max_devices; ++i) {
if (bus->devices[i])
destroy_device(bus->devices[i]);
@ -224,7 +218,6 @@ scan_bus(ide_bus_info *bus)
}
}
// XXX fix me
IDE_LOCK(bus);
ASSERT(bus->state == ata_state_busy);
@ -346,8 +339,8 @@ finish_request(ata_request *request, bool resubmit)
ccb = request->ccb;
bus->qreqFree = bus->qreqActive;
bus->qreqActive = NULL;
bus->requestFree = bus->requestActive;
bus->requestActive = NULL;
// release bus, handling service requests;
// TBD:
@ -446,8 +439,8 @@ finish_norelease(ata_request *request, bool resubmit)
ide_device_info *device = request->device;
ide_bus_info *bus = device->bus;
bus->qreqFree = bus->qreqActive;
bus->qreqActive = 0;
bus->requestFree = bus->requestActive;
bus->requestActive = 0;
ACQUIRE_BEN(&bus->status_report_ben);
@ -549,10 +542,10 @@ ide_sim_init_bus(device_node_handle node, void *user_cookie, void **cookie)
bus->first_device = NULL;
bus->qreqActive = NULL;
bus->qreqFree = (ata_request *)malloc(sizeof(ata_request));
bus->requestActive = NULL;
bus->requestFree = (ata_request *)malloc(sizeof(ata_request));
memset(bus->qreqFree, 0, sizeof(ata_request));
memset(bus->requestFree, 0, sizeof(ata_request));
// read restrictions of controller
@ -612,9 +605,9 @@ ide_sim_uninit_bus(ide_bus_info *bus)
DELETE_BEN(&bus->status_report_ben);
scsi->free_dpc(bus->irq_dpc);
if (bus->qreqActive)
if (bus->requestActive)
dprintf("ide_sim_uninit_bus: Warning request still active\n");
free(bus->qreqFree);
free(bus->requestFree);
free(bus);

View File

@ -18,6 +18,8 @@
#include <string.h>
#define TRACE dprintf
#define FLOW dprintf
/** emulate MODE SENSE 10 command */
@ -202,36 +204,38 @@ err:
/*! Emulate TEST UNIT READY */
static bool
static status_t
ata_test_unit_ready(ide_device_info *device, ata_request *request)
{
#if 0
SHOW_FLOW0(3, "");
TRACE("ata_test_unit_ready\n");
if (!device->infoblock.RMSN_supported
|| device->infoblock._127_RMSN_support != 1)
return true;
return B_OK;
// ask device about status
device->tf_param_mask = 0;
device->tf.write.command = IDE_CMD_GET_MEDIA_STATUS;
if (!send_command(device, request, true, 15, ide_state_sync_waiting))
return false;
if (ata_send_command(device, request, true, 15, ide_state_pio) != B_OK)
return B_ERROR;
if (ata_pio_wait_drdy(device) != B_OK)
return B_ERROR;
// 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
// we don't want to loose media change (ccb) reports
// we don't want to loose media change (request) reports
if (!check_output(device, true,
ide_error_nm | ide_error_abrt | ide_error_mcr | ide_error_mc,
false)) {
// SCSI spec is unclear here: we shouldn't report "media change (ccb)"
// SCSI spec is unclear here: we shouldn't report "media change (request)"
// but what to do if there is one? anyway - we report them
;
}
#endif
return true;
return B_OK;
}
@ -389,10 +393,11 @@ ata_exec_io(ide_device_info *device, ata_request *request)
{
scsi_ccb *ccb = request->ccb;
SHOW_FLOW(3, "command=%x", ccb->cdb[0]);
FLOW("ata_exec_io: scsi command 0x%02x\n", ccb->cdb[0]);
// ATA devices have one LUN only
if (ccb->target_lun != 0) {
FLOW("ata_exec_io: wrong target lun\n");
ccb->subsys_status = SCSI_SEL_TIMEOUT;
finish_request(request, false);
return;
@ -498,9 +503,9 @@ ata_exec_io(ide_device_info *device, ata_request *request)
| (uint32)cmd->low_lba;
length = cmd->length != 0 ? cmd->length : 256;
SHOW_FLOW(3, "READ6/WRITE6 pos=%lx, length=%lx", pos, length);
FLOW("READ6/WRITE6 pos=%lx, length=%lx\n", pos, length);
ata_send_rw(device, request, pos, length, cmd->opcode == SCSI_OP_WRITE_6);
ata_exec_read_write(device, request, pos, length, cmd->opcode == SCSI_OP_WRITE_6);
return;
}
@ -514,8 +519,10 @@ ata_exec_io(ide_device_info *device, ata_request *request)
pos = B_BENDIAN_TO_HOST_INT32(cmd->lba);
length = B_BENDIAN_TO_HOST_INT16(cmd->length);
FLOW("READ10/WRITE10 pos=%lx, length=%lx\n", pos, length);
if (length != 0) {
ata_send_rw(device, request, pos, length, cmd->opcode == SCSI_OP_WRITE_10);
ata_exec_read_write(device, request, pos, length, cmd->opcode == SCSI_OP_WRITE_10);
} else {
// we cannot transfer zero blocks (apart from LBA48)
finish_request(request, false);
@ -524,6 +531,7 @@ ata_exec_io(ide_device_info *device, ata_request *request)
}
default:
FLOW("command not implemented\n");
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_OPCODE);
}