void AHCIPort::ScsiExecuteRequest(scsi_ccb *request) { // TRACE("AHCIPort::ScsiExecuteRequest port %d, opcode 0x%02x, length %u\n", fIndex, request->cdb[0], request->cdb_length); if (fIsATAPI) { bool isWrite = false; switch (request->flags & SCSI_DIR_MASK) { case SCSI_DIR_NONE: ASSERT(request->data_length == 0); break; case SCSI_DIR_IN: ASSERT(request->data_length > 0); break; case SCSI_DIR_OUT: isWrite = true; ASSERT(request->data_length > 0); break; default: panic("CDB has invalid direction mask"); } // TRACE("AHCIPort::ScsiExecuteRequest ATAPI: port %d, opcode 0x%02x, length %u\n", fIndex, request->cdb[0], request->cdb_length); sata_request *sreq = new(std::nothrow) sata_request(request); if (sreq == NULL) { TRACE("out of memory when allocating atapi request\n"); request->subsys_status = SCSI_REQ_ABORTED; gSCSI->finished(request, 1); return; } sreq->set_atapi_cmd(request->data_length); // uint8 *data = (uint8*) sreq->ccb()->cdb; // for (int i = 0; i < 16; i += 8) { // TRACE(" %02x %02x %02x %02x %02x %02x %02x %02x\n", data[i], data[i+1], data[i+2], data[i+3], data[i+4], data[i+5], data[i+6], data[i+7]); // } ExecuteSataRequest(sreq, isWrite); return; } if (request->cdb[0] == SCSI_OP_REQUEST_SENSE) { panic("ahci: SCSI_OP_REQUEST_SENSE not yet supported\n"); return; } if (!fDevicePresent) { TRACE("no device present on port %d\n", fIndex); request->subsys_status = SCSI_DEV_NOT_THERE; gSCSI->finished(request, 1); return; } request->subsys_status = SCSI_REQ_CMP; switch (request->cdb[0]) { case SCSI_OP_TEST_UNIT_READY: ScsiTestUnitReady(request); break; case SCSI_OP_INQUIRY: ScsiInquiry(request); break; case SCSI_OP_READ_CAPACITY: ScsiReadCapacity(request); break; case SCSI_OP_SERVICE_ACTION_IN: if ((request->cdb[1] & 0x1f) == SCSI_SAI_READ_CAPACITY_16) ScsiReadCapacity16(request); else { request->subsys_status = SCSI_REQ_INVALID; gSCSI->finished(request, 1); } break; case SCSI_OP_SYNCHRONIZE_CACHE: ScsiSynchronizeCache(request); break; case SCSI_OP_READ_6: case SCSI_OP_WRITE_6: { const scsi_cmd_rw_6 *cmd = (const scsi_cmd_rw_6 *)request->cdb; uint32 position = ((uint32)cmd->high_lba << 16) | ((uint32)cmd->mid_lba << 8) | (uint32)cmd->low_lba; size_t length = cmd->length != 0 ? cmd->length : 256; bool isWrite = request->cdb[0] == SCSI_OP_WRITE_6; ScsiReadWrite(request, position, length, isWrite); break; } case SCSI_OP_READ_10: case SCSI_OP_WRITE_10: { const scsi_cmd_rw_10 *cmd = (const scsi_cmd_rw_10 *)request->cdb; uint32 position = B_BENDIAN_TO_HOST_INT32(cmd->lba); size_t length = B_BENDIAN_TO_HOST_INT16(cmd->length); bool isWrite = request->cdb[0] == SCSI_OP_WRITE_10; if (length) { ScsiReadWrite(request, position, length, isWrite); } else { TRACE("AHCIPort::ScsiExecuteRequest error: transfer without " "data!\n"); request->subsys_status = SCSI_REQ_INVALID; gSCSI->finished(request, 1); } break; } case SCSI_OP_READ_12: case SCSI_OP_WRITE_12: { const scsi_cmd_rw_12 *cmd = (const scsi_cmd_rw_12 *)request->cdb; uint32 position = B_BENDIAN_TO_HOST_INT32(cmd->lba); size_t length = B_BENDIAN_TO_HOST_INT32(cmd->length); bool isWrite = request->cdb[0] == SCSI_OP_WRITE_12; if (length) { ScsiReadWrite(request, position, length, isWrite); } else { TRACE("AHCIPort::ScsiExecuteRequest error: transfer without " "data!\n"); request->subsys_status = SCSI_REQ_INVALID; gSCSI->finished(request, 1); } break; } case SCSI_OP_READ_16: case SCSI_OP_WRITE_16: { const scsi_cmd_rw_16 *cmd = (const scsi_cmd_rw_16 *)request->cdb; uint64 position = B_BENDIAN_TO_HOST_INT64(cmd->lba); size_t length = B_BENDIAN_TO_HOST_INT32(cmd->length); bool isWrite = request->cdb[0] == SCSI_OP_WRITE_16; if (length) { ScsiReadWrite(request, position, length, isWrite); } else { TRACE("AHCIPort::ScsiExecuteRequest error: transfer without " "data!\n"); request->subsys_status = SCSI_REQ_INVALID; gSCSI->finished(request, 1); } break; } case SCSI_OP_WRITE_SAME_16: { const scsi_cmd_wsame_16 *cmd = (const scsi_cmd_wsame_16 *)request->cdb; // SCSI unmap is used for trim, otherwise we don't support it if (!cmd->unmap) { TRACE("%s port %d: unsupported request opcode 0x%02x\n", __func__, fIndex, request->cdb[0]); request->subsys_status = SCSI_REQ_ABORTED; gSCSI->finished(request, 1); break; } if (!fTrim) { // Drive doesn't support trim (or atapi) // Just say it was successful and quit request->subsys_status = SCSI_REQ_CMP; } else { TRACE("%s unimplemented: TRIM call\n", __func__); // TODO: Make Serial ATA (sata_request?) trim call here. request->subsys_status = SCSI_REQ_ABORTED; } gSCSI->finished(request, 1); break; } default: TRACE("AHCIPort::ScsiExecuteRequest port %d unsupported request " "opcode 0x%02x\n", fIndex, request->cdb[0]); request->subsys_status = SCSI_REQ_ABORTED; gSCSI->finished(request, 1); } }
uint32 GetMediumInfo(PSCSI_DEVICE pDevice, uint8 Lun) { uint32 dwErr = ERROR_SUCCESS; do { if (SCSI_DEVICE_UNKNOWN == pDevice->DeviceType || SCSI_MEDIUM_UNKNOWN == pDevice->MediumType ) { dwErr = ScsiUnitAttention(pDevice, Lun); if (ERROR_SUCCESS != dwErr) break; } // determine device type if (SCSI_DEVICE_UNKNOWN == pDevice->DeviceType) { hal_HstSendEvent(SYS_EVENT,0x08290012); dwErr = ScsiInquiry(pDevice, Lun); if (ERROR_SUCCESS != dwErr) { break; } } // now that mode sense 6 and mode sense 10 is not mandatory, we don't execute this command /* if (SCSI_DEVICE_UNKNOWN != pDevice->DeviceType && SCSI_MEDIUM_UNKNOWN == pDevice->MediumType ) { dwErr = ScsiModeSense6(pDevice, Lun); hal_HstSendEvent(SYS_EVENT,0x09060001); if (ERROR_SUCCESS != dwErr) { TRANSPORT_DATA tData; uint8 senseData[18]; tData.TransferLength = 0; tData.RequestLength = sizeof(senseData); tData.DataBlock = senseData; memset(senseData,0,sizeof(senseData)); hal_HstSendEvent(SYS_EVENT,0x09060002); dwErr = ScsiRequestSense(pDevice, &tData, Lun); dwErr = ScsiModeSense10(pDevice, Lun); if (ERROR_SUCCESS != dwErr) { break; } } } */ pDevice->Flags.MediumPresent = FALSE; // determine disk information if (!pDevice->Flags.MediumPresent) { DISK_INFO di = {0}; dwErr = ScsiReadCapacity(pDevice, &di, Lun); hal_HstSendEvent(SYS_EVENT,0x09090024); hal_HstSendEvent(SYS_EVENT,dwErr); if (ERROR_SUCCESS != dwErr) { break; } } } while (0); dwErr = ERROR_SUCCESS; return dwErr; }
void AHCIPort::ScsiExecuteRequest(scsi_ccb *request) { // TRACE("AHCIPort::ScsiExecuteRequest port %d, opcode 0x%02x, length %u\n", fIndex, request->cdb[0], request->cdb_length); if (fIsATAPI) { bool isWrite = false; switch (request->flags & SCSI_DIR_MASK) { case SCSI_DIR_NONE: ASSERT(request->data_length == 0); break; case SCSI_DIR_IN: ASSERT(request->data_length > 0); break; case SCSI_DIR_OUT: isWrite = true; ASSERT(request->data_length > 0); break; default: panic("CDB has invalid direction mask"); } // TRACE("AHCIPort::ScsiExecuteRequest ATAPI: port %d, opcode 0x%02x, length %u\n", fIndex, request->cdb[0], request->cdb_length); sata_request *sreq = new(std::nothrow) sata_request(request); sreq->set_atapi_cmd(request->data_length); // uint8 *data = (uint8*) sreq->ccb()->cdb; // for (int i = 0; i < 16; i += 8) { // TRACE(" %02x %02x %02x %02x %02x %02x %02x %02x\n", data[i], data[i+1], data[i+2], data[i+3], data[i+4], data[i+5], data[i+6], data[i+7]); // } ExecuteSataRequest(sreq, isWrite); return; } if (request->cdb[0] == SCSI_OP_REQUEST_SENSE) { panic("ahci: SCSI_OP_REQUEST_SENSE not yet supported\n"); return; } if (!fDevicePresent) { TRACE("no device present on port %d\n", fIndex); request->subsys_status = SCSI_DEV_NOT_THERE; gSCSI->finished(request, 1); return; } request->subsys_status = SCSI_REQ_CMP; switch (request->cdb[0]) { case SCSI_OP_TEST_UNIT_READY: ScsiTestUnitReady(request); break; case SCSI_OP_INQUIRY: ScsiInquiry(request); break; case SCSI_OP_READ_CAPACITY: ScsiReadCapacity(request); break; case SCSI_OP_SYNCHRONIZE_CACHE: ScsiSynchronizeCache(request); break; case SCSI_OP_READ_6: case SCSI_OP_WRITE_6: { scsi_cmd_rw_6 *cmd = (scsi_cmd_rw_6 *)request->cdb; uint32 position = ((uint32)cmd->high_lba << 16) | ((uint32)cmd->mid_lba << 8) | (uint32)cmd->low_lba; size_t length = cmd->length != 0 ? cmd->length : 256; bool isWrite = request->cdb[0] == SCSI_OP_WRITE_6; ScsiReadWrite(request, position, length, isWrite); break; } case SCSI_OP_READ_10: case SCSI_OP_WRITE_10: { scsi_cmd_rw_10 *cmd = (scsi_cmd_rw_10 *)request->cdb; uint32 position = B_BENDIAN_TO_HOST_INT32(cmd->lba); size_t length = B_BENDIAN_TO_HOST_INT16(cmd->length); bool isWrite = request->cdb[0] == SCSI_OP_WRITE_10; if (length) { ScsiReadWrite(request, position, length, isWrite); } else { TRACE("AHCIPort::ScsiExecuteRequest error: transfer without data!\n"); request->subsys_status = SCSI_REQ_INVALID; gSCSI->finished(request, 1); } break; } case SCSI_OP_READ_12: case SCSI_OP_WRITE_12: { scsi_cmd_rw_12 *cmd = (scsi_cmd_rw_12 *)request->cdb; uint32 position = B_BENDIAN_TO_HOST_INT32(cmd->lba); size_t length = B_BENDIAN_TO_HOST_INT32(cmd->length); bool isWrite = request->cdb[0] == SCSI_OP_WRITE_12; if (length) { ScsiReadWrite(request, position, length, isWrite); } else { TRACE("AHCIPort::ScsiExecuteRequest error: transfer without data!\n"); request->subsys_status = SCSI_REQ_INVALID; gSCSI->finished(request, 1); } break; } default: TRACE("AHCIPort::ScsiExecuteRequest port %d unsupported request opcode 0x%02x\n", fIndex, request->cdb[0]); request->subsys_status = SCSI_REQ_ABORTED; gSCSI->finished(request, 1); } }
void AHCIPort::ScsiExecuteRequest(scsi_ccb* request) { // TRACE("AHCIPort::ScsiExecuteRequest port %d, opcode 0x%02x, length %u\n", fIndex, request->cdb[0], request->cdb_length); if (fIsATAPI) { bool isWrite = false; switch (request->flags & SCSI_DIR_MASK) { case SCSI_DIR_NONE: ASSERT(request->data_length == 0); break; case SCSI_DIR_IN: ASSERT(request->data_length > 0); break; case SCSI_DIR_OUT: isWrite = true; ASSERT(request->data_length > 0); break; default: panic("CDB has invalid direction mask"); } // TRACE("AHCIPort::ScsiExecuteRequest ATAPI: port %d, opcode 0x%02x, length %u\n", fIndex, request->cdb[0], request->cdb_length); sata_request* sreq = new(std::nothrow) sata_request(request); if (sreq == NULL) { TRACE("out of memory when allocating atapi request\n"); request->subsys_status = SCSI_REQ_ABORTED; gSCSI->finished(request, 1); return; } sreq->SetATAPICommand(request->data_length); // uint8* data = (uint8*) sreq->ccb()->cdb; // for (int i = 0; i < 16; i += 8) { // TRACE(" %02x %02x %02x %02x %02x %02x %02x %02x\n", data[i], data[i+1], data[i+2], data[i+3], data[i+4], data[i+5], data[i+6], data[i+7]); // } ExecuteSataRequest(sreq, isWrite); return; } if (request->cdb[0] == SCSI_OP_REQUEST_SENSE) { panic("ahci: SCSI_OP_REQUEST_SENSE not yet supported\n"); return; } if (!fDevicePresent) { TRACE("no device present on port %d\n", fIndex); request->subsys_status = SCSI_DEV_NOT_THERE; gSCSI->finished(request, 1); return; } request->subsys_status = SCSI_REQ_CMP; switch (request->cdb[0]) { case SCSI_OP_TEST_UNIT_READY: ScsiTestUnitReady(request); break; case SCSI_OP_INQUIRY: ScsiInquiry(request); break; case SCSI_OP_READ_CAPACITY: ScsiReadCapacity(request); break; case SCSI_OP_SERVICE_ACTION_IN: if ((request->cdb[1] & 0x1f) == SCSI_SAI_READ_CAPACITY_16) ScsiReadCapacity16(request); else { request->subsys_status = SCSI_REQ_INVALID; gSCSI->finished(request, 1); } break; case SCSI_OP_SYNCHRONIZE_CACHE: ScsiSynchronizeCache(request); break; case SCSI_OP_READ_6: case SCSI_OP_WRITE_6: { const scsi_cmd_rw_6* cmd = (const scsi_cmd_rw_6*)request->cdb; uint32 position = ((uint32)cmd->high_lba << 16) | ((uint32)cmd->mid_lba << 8) | (uint32)cmd->low_lba; size_t length = cmd->length != 0 ? cmd->length : 256; bool isWrite = request->cdb[0] == SCSI_OP_WRITE_6; ScsiReadWrite(request, position, length, isWrite); break; } case SCSI_OP_READ_10: case SCSI_OP_WRITE_10: { const scsi_cmd_rw_10* cmd = (const scsi_cmd_rw_10*)request->cdb; uint32 position = B_BENDIAN_TO_HOST_INT32(cmd->lba); size_t length = B_BENDIAN_TO_HOST_INT16(cmd->length); bool isWrite = request->cdb[0] == SCSI_OP_WRITE_10; if (length) { ScsiReadWrite(request, position, length, isWrite); } else { TRACE("AHCIPort::ScsiExecuteRequest error: transfer without " "data!\n"); request->subsys_status = SCSI_REQ_INVALID; gSCSI->finished(request, 1); } break; } case SCSI_OP_READ_12: case SCSI_OP_WRITE_12: { const scsi_cmd_rw_12* cmd = (const scsi_cmd_rw_12*)request->cdb; uint32 position = B_BENDIAN_TO_HOST_INT32(cmd->lba); size_t length = B_BENDIAN_TO_HOST_INT32(cmd->length); bool isWrite = request->cdb[0] == SCSI_OP_WRITE_12; if (length) { ScsiReadWrite(request, position, length, isWrite); } else { TRACE("AHCIPort::ScsiExecuteRequest error: transfer without " "data!\n"); request->subsys_status = SCSI_REQ_INVALID; gSCSI->finished(request, 1); } break; } case SCSI_OP_READ_16: case SCSI_OP_WRITE_16: { const scsi_cmd_rw_16* cmd = (const scsi_cmd_rw_16*)request->cdb; uint64 position = B_BENDIAN_TO_HOST_INT64(cmd->lba); size_t length = B_BENDIAN_TO_HOST_INT32(cmd->length); bool isWrite = request->cdb[0] == SCSI_OP_WRITE_16; if (length) { ScsiReadWrite(request, position, length, isWrite); } else { TRACE("AHCIPort::ScsiExecuteRequest error: transfer without " "data!\n"); request->subsys_status = SCSI_REQ_INVALID; gSCSI->finished(request, 1); } break; } case SCSI_OP_UNMAP: { const scsi_cmd_unmap* cmd = (const scsi_cmd_unmap*)request->cdb; if (!fTrimSupported) { TRACE("%s port %d: unsupported request opcode 0x%02x\n", __func__, fIndex, request->cdb[0]); request->subsys_status = SCSI_REQ_ABORTED; gSCSI->finished(request, 1); break; } scsi_unmap_parameter_list* unmapBlocks = (scsi_unmap_parameter_list*)request->data; if (unmapBlocks == NULL || B_BENDIAN_TO_HOST_INT16(cmd->length) != request->data_length || B_BENDIAN_TO_HOST_INT16(unmapBlocks->data_length) != request->data_length - 1) { TRACE("%s port %d: invalid unmap parameter data length\n", __func__, fIndex); request->subsys_status = SCSI_REQ_ABORTED; gSCSI->finished(request, 1); } else { ScsiUnmap(request, unmapBlocks); } break; } default: TRACE("AHCIPort::ScsiExecuteRequest port %d unsupported request " "opcode 0x%02x\n", fIndex, request->cdb[0]); request->subsys_status = SCSI_REQ_ABORTED; gSCSI->finished(request, 1); } }