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:
@@ -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
|
status_t
|
||||||
ata_send_command(ide_device_info *device, ata_request *request,
|
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)
|
||||||
@@ -189,6 +200,7 @@ ata_send_command(ide_device_info *device, ata_request *request,
|
|||||||
ASSERT(bus->state == ata_state_busy);
|
ASSERT(bus->state == ata_state_busy);
|
||||||
|
|
||||||
bus->state = new_state;
|
bus->state = new_state;
|
||||||
|
bus->pio_timeout = timeout * 1000;
|
||||||
|
|
||||||
IDE_UNLOCK(bus);
|
IDE_UNLOCK(bus);
|
||||||
|
|
||||||
@@ -205,6 +217,11 @@ err:
|
|||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
status_t
|
||||||
|
ata_finish_command(ide_device_info *device)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status_t
|
status_t
|
||||||
ata_reset_bus(ide_bus_info *bus, bool *_devicePresent0, uint32 *_sigDev0, bool *_devicePresent1, uint32 *_sigDev1)
|
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");
|
dprintf("ATA: reset_bus: timeout\n");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
timeout
|
||||||
if (controller->read_command_block_regs(channel, &tf, ide_mask_sector_count |
|
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)
|
ide_mask_LBA_low | ide_mask_LBA_mid | ide_mask_LBA_high | ide_mask_error) != B_OK)
|
||||||
goto error;
|
goto error;
|
||||||
@@ -594,7 +611,7 @@ err:
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
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)
|
uint64 pos, size_t length, bool write)
|
||||||
{
|
{
|
||||||
ide_bus_info *bus = device->bus;
|
ide_bus_info *bus = device->bus;
|
||||||
|
|||||||
@@ -62,15 +62,26 @@ typedef struct ide_bus_timer_info {
|
|||||||
// ide request
|
// ide request
|
||||||
typedef struct ata_request {
|
typedef struct ata_request {
|
||||||
|
|
||||||
struct ide_device_info *device;
|
struct ide_device_info * device;
|
||||||
|
scsi_ccb * ccb; // basic scsi request
|
||||||
scsi_ccb *ccb; // basic request
|
uint8 is_write : 1; // true for write request
|
||||||
uint8 is_write : 1; // true for write request
|
uint8 uses_dma : 1; // true if using dma
|
||||||
uint8 uses_dma : 1; // true if using dma
|
uint8 packet_irq : 1; // true if waiting for command packet irq
|
||||||
uint8 packet_irq : 1; // true if waiting for command packet irq
|
|
||||||
} ata_request;
|
} 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 {
|
typedef struct ide_device_info {
|
||||||
struct ide_bus_info *bus;
|
struct ide_bus_info *bus;
|
||||||
@@ -118,6 +129,7 @@ typedef struct ide_device_info {
|
|||||||
uint8 device_type; // atapi device type
|
uint8 device_type; // atapi device type
|
||||||
|
|
||||||
// pio from here on
|
// pio from here on
|
||||||
|
bigtime_t pio_timeout;
|
||||||
int left_sg_elem; // remaining sg elements
|
int left_sg_elem; // remaining sg elements
|
||||||
const physical_entry *cur_sg_elem; // active sg element
|
const physical_entry *cur_sg_elem; // active sg element
|
||||||
int cur_sg_ofs; // offset in 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
|
ata_bus_state state; // current state of bus
|
||||||
|
|
||||||
struct ata_request * qreqActive;
|
struct ata_request * requestActive;
|
||||||
struct ata_request * qreqFree;
|
struct ata_request * requestFree;
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
@@ -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_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, ata_request *request, 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);
|
||||||
|
status_t ata_finish_command(ide_device_info *device);
|
||||||
|
|
||||||
bool check_rw_error(ide_device_info *device, ata_request *request);
|
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, ata_request *request,
|
void ata_exec_read_write(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(ata_request *request);
|
void ata_dpc_DMA(ata_request *request);
|
||||||
void ata_dpc_PIO(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)
|
sim_scsi_io(ide_bus_info *bus, scsi_ccb *ccb)
|
||||||
{
|
{
|
||||||
ide_device_info *device;
|
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);
|
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;
|
goto err_bus_busy;
|
||||||
|
|
||||||
// bail out if device can't accept further requests
|
// bail out if device can't accept further requests
|
||||||
if (bus->qreqFree == NULL)
|
if (bus->requestFree == NULL)
|
||||||
goto err_device_busy;
|
goto err_device_busy;
|
||||||
|
|
||||||
bus->state = ata_state_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);
|
RELEASE_BEN(&bus->status_report_ben);
|
||||||
|
|
||||||
// as we own the bus, noone can bother us
|
// as we own the bus, noone can bother us
|
||||||
request = bus->qreqFree;
|
ASSERT(bus->requestActive == NULL);
|
||||||
bus->qreqFree = NULL;
|
bus->requestActive = bus->requestFree;
|
||||||
bus->qreqActive = request;
|
bus->requestFree = NULL;
|
||||||
|
|
||||||
request->device = device;
|
init_ata_request(bus->requestActive, device, ccb);
|
||||||
request->ccb = ccb;
|
|
||||||
request->uses_dma = false;
|
|
||||||
|
|
||||||
FLOW("calling exec_io: %p, %d:%d\n", bus, ccb->target_id, ccb->target_lun);
|
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;
|
return;
|
||||||
|
|
||||||
@@ -187,14 +183,12 @@ scan_bus(ide_bus_info *bus)
|
|||||||
if (bus->disconnected)
|
if (bus->disconnected)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
|
||||||
// XXX fix me
|
// XXX fix me
|
||||||
IDE_LOCK(bus);
|
IDE_LOCK(bus);
|
||||||
ASSERT(bus->state == ata_state_idle);
|
ASSERT(bus->state == ata_state_idle);
|
||||||
bus->state = ata_state_busy;
|
bus->state = ata_state_busy;
|
||||||
IDE_UNLOCK(bus);
|
IDE_UNLOCK(bus);
|
||||||
|
|
||||||
|
|
||||||
for (i = 0; i < bus->max_devices; ++i) {
|
for (i = 0; i < bus->max_devices; ++i) {
|
||||||
if (bus->devices[i])
|
if (bus->devices[i])
|
||||||
destroy_device(bus->devices[i]);
|
destroy_device(bus->devices[i]);
|
||||||
@@ -224,7 +218,6 @@ scan_bus(ide_bus_info *bus)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// XXX fix me
|
// XXX fix me
|
||||||
IDE_LOCK(bus);
|
IDE_LOCK(bus);
|
||||||
ASSERT(bus->state == ata_state_busy);
|
ASSERT(bus->state == ata_state_busy);
|
||||||
@@ -346,8 +339,8 @@ finish_request(ata_request *request, bool resubmit)
|
|||||||
ccb = request->ccb;
|
ccb = request->ccb;
|
||||||
|
|
||||||
|
|
||||||
bus->qreqFree = bus->qreqActive;
|
bus->requestFree = bus->requestActive;
|
||||||
bus->qreqActive = NULL;
|
bus->requestActive = NULL;
|
||||||
|
|
||||||
// release bus, handling service requests;
|
// release bus, handling service requests;
|
||||||
// TBD:
|
// TBD:
|
||||||
@@ -446,8 +439,8 @@ finish_norelease(ata_request *request, bool resubmit)
|
|||||||
ide_device_info *device = request->device;
|
ide_device_info *device = request->device;
|
||||||
ide_bus_info *bus = device->bus;
|
ide_bus_info *bus = device->bus;
|
||||||
|
|
||||||
bus->qreqFree = bus->qreqActive;
|
bus->requestFree = bus->requestActive;
|
||||||
bus->qreqActive = 0;
|
bus->requestActive = 0;
|
||||||
|
|
||||||
ACQUIRE_BEN(&bus->status_report_ben);
|
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->first_device = NULL;
|
||||||
|
|
||||||
|
|
||||||
bus->qreqActive = NULL;
|
bus->requestActive = NULL;
|
||||||
bus->qreqFree = (ata_request *)malloc(sizeof(ata_request));
|
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
|
// read restrictions of controller
|
||||||
|
|
||||||
@@ -612,9 +605,9 @@ 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);
|
||||||
|
|
||||||
if (bus->qreqActive)
|
if (bus->requestActive)
|
||||||
dprintf("ide_sim_uninit_bus: Warning request still active\n");
|
dprintf("ide_sim_uninit_bus: Warning request still active\n");
|
||||||
free(bus->qreqFree);
|
free(bus->requestFree);
|
||||||
|
|
||||||
free(bus);
|
free(bus);
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,8 @@
|
|||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
|
#define TRACE dprintf
|
||||||
|
#define FLOW dprintf
|
||||||
|
|
||||||
/** emulate MODE SENSE 10 command */
|
/** emulate MODE SENSE 10 command */
|
||||||
|
|
||||||
@@ -202,36 +204,38 @@ err:
|
|||||||
|
|
||||||
|
|
||||||
/*! Emulate TEST UNIT READY */
|
/*! Emulate TEST UNIT READY */
|
||||||
static bool
|
static status_t
|
||||||
ata_test_unit_ready(ide_device_info *device, ata_request *request)
|
ata_test_unit_ready(ide_device_info *device, ata_request *request)
|
||||||
{
|
{
|
||||||
#if 0
|
TRACE("ata_test_unit_ready\n");
|
||||||
SHOW_FLOW0(3, "");
|
|
||||||
|
|
||||||
if (!device->infoblock.RMSN_supported
|
if (!device->infoblock.RMSN_supported
|
||||||
|| device->infoblock._127_RMSN_support != 1)
|
|| device->infoblock._127_RMSN_support != 1)
|
||||||
return true;
|
return B_OK;
|
||||||
|
|
||||||
// ask device about status
|
// ask device about status
|
||||||
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, request, true, 15, ide_state_sync_waiting))
|
if (ata_send_command(device, request, true, 15, ide_state_pio) != B_OK)
|
||||||
return false;
|
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
|
// 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 (ccb) reports
|
// we don't want to loose media change (request) 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 (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
|
// but what to do if there is one? anyway - we report them
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
return B_OK;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -389,10 +393,11 @@ ata_exec_io(ide_device_info *device, ata_request *request)
|
|||||||
{
|
{
|
||||||
scsi_ccb *ccb = request->ccb;
|
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
|
// ATA devices have one LUN only
|
||||||
if (ccb->target_lun != 0) {
|
if (ccb->target_lun != 0) {
|
||||||
|
FLOW("ata_exec_io: wrong target lun\n");
|
||||||
ccb->subsys_status = SCSI_SEL_TIMEOUT;
|
ccb->subsys_status = SCSI_SEL_TIMEOUT;
|
||||||
finish_request(request, false);
|
finish_request(request, false);
|
||||||
return;
|
return;
|
||||||
@@ -498,9 +503,9 @@ ata_exec_io(ide_device_info *device, ata_request *request)
|
|||||||
| (uint32)cmd->low_lba;
|
| (uint32)cmd->low_lba;
|
||||||
length = cmd->length != 0 ? cmd->length : 256;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -514,8 +519,10 @@ ata_exec_io(ide_device_info *device, ata_request *request)
|
|||||||
pos = B_BENDIAN_TO_HOST_INT32(cmd->lba);
|
pos = B_BENDIAN_TO_HOST_INT32(cmd->lba);
|
||||||
length = B_BENDIAN_TO_HOST_INT16(cmd->length);
|
length = B_BENDIAN_TO_HOST_INT16(cmd->length);
|
||||||
|
|
||||||
|
FLOW("READ10/WRITE10 pos=%lx, length=%lx\n", pos, length);
|
||||||
|
|
||||||
if (length != 0) {
|
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 {
|
} else {
|
||||||
// we cannot transfer zero blocks (apart from LBA48)
|
// we cannot transfer zero blocks (apart from LBA48)
|
||||||
finish_request(request, false);
|
finish_request(request, false);
|
||||||
@@ -524,6 +531,7 @@ ata_exec_io(ide_device_info *device, ata_request *request)
|
|||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
FLOW("command not implemented\n");
|
||||||
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_OPCODE);
|
set_sense(device, SCSIS_KEY_ILLEGAL_REQUEST, SCSIS_ASC_INV_OPCODE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user