diff --git a/src/add-ons/kernel/bus_managers/ata/ata.c b/src/add-ons/kernel/bus_managers/ata/ata.c index 0f1ce09806..1990955937 100644 --- a/src/add-ons/kernel/bus_managers/ata/ata.c +++ b/src/add-ons/kernel/bus_managers/ata/ata.c @@ -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; diff --git a/src/add-ons/kernel/bus_managers/ata/ide_internal.h b/src/add-ons/kernel/bus_managers/ata/ide_internal.h index cb67873e97..d723f81c39 100644 --- a/src/add-ons/kernel/bus_managers/ata/ide_internal.h +++ b/src/add-ons/kernel/bus_managers/ata/ide_internal.h @@ -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); diff --git a/src/add-ons/kernel/bus_managers/ata/ide_sim.c b/src/add-ons/kernel/bus_managers/ata/ide_sim.c index a58c6eed44..26119e7cc7 100644 --- a/src/add-ons/kernel/bus_managers/ata/ide_sim.c +++ b/src/add-ons/kernel/bus_managers/ata/ide_sim.c @@ -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); diff --git a/src/add-ons/kernel/bus_managers/ata/scsi2ata.c b/src/add-ons/kernel/bus_managers/ata/scsi2ata.c index 695243d445..d94d2b8ab4 100644 --- a/src/add-ons/kernel/bus_managers/ata/scsi2ata.c +++ b/src/add-ons/kernel/bus_managers/ata/scsi2ata.c @@ -18,6 +18,8 @@ #include +#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); }