DEVICE_PTR APIFindDev (const ADAPTER_PTR HA, const unsigned TID, const unsigned LUN) { return ScsiPortGetLogicalUnit(HA, 0, (char)TID, (char)LUN); }
BOOLEAN StartIO (IN PVOID HAObject, IN PSCSI_REQUEST_BLOCK Req) { ADAPTER_PTR HA = HAObject; DEVICE_PTR DevP; int i; TRACE(2, ("StartIO(): Req @%x, Function = 0x%x, Req->SrbExtension @%x\n", Req, Req->Function, Req->SrbExtension)); switch (Req->Function) { case SRB_FUNCTION_EXECUTE_SCSI: ReqNext(Req) = (IO_REQ_PTR)NILL; ReqAdapterPtr(Req) = HA; for (i=0; i < sizeof(ReqState(Req)); i++) ((U8 *)&ReqState(Req))[i] = 0; ReqState(Req).ReqType = RTNormalReq; if ( (DevP = ScsiPortGetLogicalUnit(HA, Req->PathId, ReqTargetID(Req), ReqTargetLUN(Req))) == NILL) { TRACE(3, ("ExecuteReq(): Unable to get device info\n")); Req->SrbStatus = SRB_STATUS_NO_DEVICE; return FALSE; } ReqDevP(Req) = DevP; if (!DevP->Flags.Initialized) QueueInternalRequest(HA, Req, RTGetInfoReq); else IExecuteReq(HA, DevP, Req, NORMAL_REQ); break; case SRB_FUNCTION_RESET_BUS: TRACE(3, ("StartIO(): RESET_BUS command\n")); ResetBus(HAObject, Req->PathId); break; case SRB_FUNCTION_RESET_DEVICE: case SRB_FUNCTION_TERMINATE_IO: case SRB_FUNCTION_FLUSH: case SRB_FUNCTION_SHUTDOWN: Req->SrbStatus = SRB_STATUS_SUCCESS; ScsiPortNotification(RequestComplete, HA, Req); break; case SRB_FUNCTION_ABORT_COMMAND: TRACE(0, ("StartIO(): Request at %x to abort request %x\n", Req, Req->NextSrb)); if ((DevP = ScsiPortGetLogicalUnit(HA, Req->PathId, ReqTargetID(Req), ReqTargetLUN(Req))) == NILL || (DevP->Flags.Initialized == 0) || !AbortRequest(HA, DevP, Req->NextSrb) ) { TRACE(0, ("StartIO(): Abort operation failed\n")); Req->SrbStatus = SRB_STATUS_ABORT_FAILED; } else { TRACE(0, ("StartIO(): Abort operation success\n")); Req->SrbStatus = SRB_STATUS_SUCCESS; } ScsiPortNotification(RequestComplete, HA, Req); break; case SRB_FUNCTION_RELEASE_RECOVERY: case SRB_FUNCTION_RECEIVE_EVENT: case SRB_FUNCTION_IO_CONTROL: default: TRACE(0, ("StartIO(): Unsupported command: 0x%x\n", Req->Function)); APISetStatus(Req, S_REQ_OPCODE, Terminal, NotSenseable); return FALSE; break; } ScsiPortNotification(NextLuRequest, HA, Req->PathId, Req->TargetId, Req->Lun); return TRUE; }
static BOOLEAN XenScsi_HwScsiStartIo(PVOID DeviceExtension, PSCSI_REQUEST_BLOCK Srb) { PXENSCSI_DEVICE_DATA xsdd = DeviceExtension; scsi_dev_t *dev; //FUNCTION_ENTER(); XenScsi_CheckNewDevice(DeviceExtension); if (xsdd->scsiport_paused) { KdPrint((__DRIVER_NAME " Busy\n")); Srb->SrbStatus = SRB_STATUS_BUSY; ScsiPortNotification(RequestComplete, DeviceExtension, Srb); //FUNCTION_EXIT(); return TRUE; } for (dev = (scsi_dev_t *)xsdd->dev_list_head.Flink; dev != (scsi_dev_t *)&xsdd->dev_list_head; dev = (scsi_dev_t * )dev->entry.Flink) { if (dev->channel == Srb->PathId && dev->id == Srb->TargetId && dev->lun == Srb->Lun) break; } if (dev == (scsi_dev_t *)&xsdd->dev_list_head) { Srb->SrbStatus = SRB_STATUS_NO_DEVICE; ScsiPortNotification(RequestComplete, DeviceExtension, Srb); //KdPrint((__DRIVER_NAME " Out of bounds\n")); ScsiPortNotification(NextRequest, DeviceExtension); //FUNCTION_EXIT(); return TRUE; } switch (Srb->Function) { case SRB_FUNCTION_EXECUTE_SCSI: switch (Srb->Cdb[0]) { case 0x03: { /* REQUEST_SENSE*/ /* but what about when we allow multiple requests per lu? */ PXENSCSI_LU_DATA lud = ScsiPortGetLogicalUnit(DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun); if (lud != NULL && lud->sense_len) { int i; KdPrint((__DRIVER_NAME " Emulating REQUEST_SENSE (lu data = %p)\n", lud)); memcpy(Srb->DataBuffer, lud->sense_buffer, min(lud->sense_len, Srb->DataTransferLength)); if (lud->sense_len > Srb->DataTransferLength) { KdPrint((__DRIVER_NAME " Sense overrun Srb->DataTransferLength = %d, lud->sense_len = %d\n", Srb->DataTransferLength, lud->sense_len)); Srb->DataTransferLength = lud->sense_len; Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN; } else { Srb->SrbStatus = SRB_STATUS_SUCCESS; } for (i = 0; i < min(lud->sense_len, 8); i++) KdPrint((__DRIVER_NAME " sense %02x: %02x\n", i, (ULONG)((PUCHAR)lud->sense_buffer)[i])); lud->sense_len = 0; ScsiPortNotification(RequestComplete, DeviceExtension, Srb); ScsiPortNotification(NextRequest, DeviceExtension); break; } else { KdPrint((__DRIVER_NAME " Issuing REQUEST_SENSE (lud = %p)\n", lud)); } // fall through } default: XenScsi_PutSrbOnRing(xsdd, Srb); Srb->SrbStatus = SRB_STATUS_PENDING; break; } break; case SRB_FUNCTION_IO_CONTROL: KdPrint((__DRIVER_NAME " SRB_FUNCTION_IO_CONTROL\n")); Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; ScsiPortNotification(RequestComplete, DeviceExtension, Srb); ScsiPortNotification(NextRequest, DeviceExtension); break; case SRB_FUNCTION_FLUSH: KdPrint((__DRIVER_NAME " SRB_FUNCTION_FLUSH\n")); Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; ScsiPortNotification(RequestComplete, DeviceExtension, Srb); ScsiPortNotification(NextRequest, DeviceExtension); break; default: KdPrint((__DRIVER_NAME " Unhandled Srb->Function = %08X\n", Srb->Function)); Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST; ScsiPortNotification(RequestComplete, DeviceExtension, Srb); ScsiPortNotification(NextRequest, DeviceExtension); break; } //FUNCTION_EXIT(); return TRUE; }
static BOOLEAN XenScsi_HwScsiInterrupt(PVOID DeviceExtension) { PXENSCSI_DEVICE_DATA xsdd = DeviceExtension; PSCSI_REQUEST_BLOCK Srb; RING_IDX i, rp; int j; vscsiif_response_t *rep; int more_to_do = TRUE; vscsiif_shadow_t *shadow; BOOLEAN last_interrupt = FALSE; XenScsi_CheckNewDevice(DeviceExtension); if (!dump_mode && !xsdd->vectors.EvtChn_AckEvent(xsdd->vectors.context, xsdd->event_channel, &last_interrupt)) { return FALSE; } //FUNCTION_ENTER(); while (more_to_do) { rp = xsdd->ring.sring->rsp_prod; KeMemoryBarrier(); for (i = xsdd->ring.rsp_cons; i != rp; i++) { rep = RING_GET_RESPONSE(&xsdd->ring, i); shadow = &xsdd->shadows[rep->rqid]; Srb = shadow->Srb; Srb->ScsiStatus = (UCHAR)rep->rslt; memset(Srb->SenseInfoBuffer, 0, Srb->SenseInfoBufferLength); if (rep->sense_len > 0 && Srb->SenseInfoBuffer != NULL) { memcpy(Srb->SenseInfoBuffer, rep->sense_buffer, min(Srb->SenseInfoBufferLength, rep->sense_len)); } switch(rep->rslt) { case 0: //KdPrint((__DRIVER_NAME " Xen Operation complete - result = 0x%08x, sense_len = %d, residual = %d\n", rep->rslt, rep->sense_len, rep->residual_len)); Srb->SrbStatus = SRB_STATUS_SUCCESS; if (Srb->Cdb[0] == 0x03) { KdPrint((__DRIVER_NAME " REQUEST_SENSE DataTransferLength = %d, residual = %d\n", Srb->DataTransferLength, rep->residual_len)); //for (j = 0; j < Srb->DataTransferLength - rep->residual_len; j++) // KdPrint((__DRIVER_NAME " sense %02x: %02x\n", j, (ULONG)((PUCHAR)Srb->DataBuffer)[j])); } break; case 0x00010000: /* Device does not exist */ KdPrint((__DRIVER_NAME " Xen Operation error - cdb[0] = %02x, result = 0x%08x, sense_len = %d, residual = %d\n", (ULONG)Srb->Cdb[0], rep->rslt, rep->sense_len, rep->residual_len)); Srb->SrbStatus = SRB_STATUS_NO_DEVICE; break; default: KdPrint((__DRIVER_NAME " Xen Operation error - cdb[0] = %02x, result = 0x%08x, sense_len = %d, residual = %d\n", (ULONG)Srb->Cdb[0], rep->rslt, rep->sense_len, rep->residual_len)); Srb->SrbStatus = SRB_STATUS_ERROR; //for (j = 0; j < Srb->SenseInfoBufferLength; j++) // KdPrint((__DRIVER_NAME " sense %02x: %02x\n", j, (ULONG)((PUCHAR)Srb->SenseInfoBuffer)[j])); if (rep->sense_len > 0 && !(Srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) && Srb->SenseInfoBuffer != NULL) { KdPrint((__DRIVER_NAME " Doing autosense\n")); Srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID; } else if (Srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE) { PXENSCSI_LU_DATA lud = ScsiPortGetLogicalUnit(DeviceExtension, Srb->PathId, Srb->TargetId, Srb->Lun); KdPrint((__DRIVER_NAME " Autosense disabled\n")); if (lud != NULL) { KdPrint((__DRIVER_NAME " Saving sense data\n")); lud->sense_len = rep->sense_len; memcpy(lud->sense_buffer, Srb->SenseInfoBuffer, lud->sense_len); } } } /* work around a bug in scsiback that gives an incorrect result to REPORT_LUNS - fail it if the output is only 8 bytes */ if (Srb->Cdb[0] == 0xa0 && Srb->SrbStatus == SRB_STATUS_SUCCESS && Srb->DataTransferLength - rep->residual_len == 8) { /* SRB_STATUS_ERROR appears to be sufficient here - no need to worry about sense data or anything */ KdPrint((__DRIVER_NAME " Worked around bad REPORT_LUNS emulation for %d:%d:%d\n", Srb->PathId, Srb->TargetId, Srb->Lun)); Srb->SrbStatus = SRB_STATUS_ERROR; } //remaining = Srb->DataTransferLength; for (j = 0; j < shadow->req.nr_segments; j++) { xsdd->vectors.GntTbl_EndAccess(xsdd->vectors.context, shadow->req.seg[j].gref, TRUE, (ULONG)'SCSI'); put_grant_on_freelist(xsdd, shadow->req.seg[j].gref); shadow->req.seg[j].gref = 0; } if (Srb->SrbStatus == SRB_STATUS_SUCCESS && rep->residual_len) { // KdPrint((__DRIVER_NAME " SRB_STATUS_DATA_OVERRUN DataTransferLength = %d, adjusted = %d\n", // Srb->DataTransferLength, Srb->DataTransferLength - rep->residual_len)); Srb->DataTransferLength -= rep->residual_len; Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN; } put_shadow_on_freelist(xsdd, shadow); ScsiPortNotification(RequestComplete, xsdd, Srb); if (!xsdd->scsiport_paused) ScsiPortNotification(NextRequest, DeviceExtension); } xsdd->ring.rsp_cons = i; if (i != xsdd->ring.req_prod_pvt) { RING_FINAL_CHECK_FOR_RESPONSES(&xsdd->ring, more_to_do); } else { xsdd->ring.sring->rsp_event = i + 1; more_to_do = FALSE; } } //FUNCTION_EXIT(); return last_interrupt; }