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:
parent
17b30c87ea
commit
dd7579a79b
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user