📄 umssio.c
字号:
IoPacket->Iop = (PVOID)Iop;
IoPacket->Flags = 0;
IoPacket->Status = IO_STATUS_PENDING;
IoPacket->BlockSize = Dcb->DCB_bdd.DCB_apparent_blk_size;
if (Ior->IOR_flags & IORF_SCATTER_GATHER)
IoPacket->Flags |= IO_FLAGS_SCATTER_GATHER;
if (Srb->SrbFlags & SRB_FLAGS_DATA_IN)
IoPacket->Flags |= IO_FLAGS_DATA_IN;
else if (Srb->SrbFlags & SRB_FLAGS_DATA_OUT)
IoPacket->Flags |= IO_FLAGS_DATA_OUT;
UMSSPDR_ProcessIoPacket(IoPacket, Iop);
// Call WDM driver
pfnStartRequest(IoPacket);
}
else
{
UMSSPDR_DebugPrintf(DBGLVL_DEFAULT, ("IOP with no SRB, IOR_func=%x\n",
Ior->IOR_func));
// We only handle request with valid SRBs
Ior->IOR_status = IORS_INVALID_COMMAND;
UMSSPDR_CompleteIOP(Iop);
}
EXIT(UMSSPDR_StartIo)
}
VOID
UMSSPDR_ProcessIoPacket(
PIOPACKET IoPacket,
pIOP Iop
)
{
SCSI_REQUEST_BLOCK * Srb;
PIOR Ior;
ENTER(UMSSPDR_ProcessIoPacket)
Ior = &(Iop->IOP_ior);
Srb = (PSCSI_REQUEST_BLOCK)Iop->IOP_srb;
switch (Srb->Cdb[0])
{
case SCSIOP_READCD:
// CDVSD bug - doesn't set SRB data length for READ_CD commands
IoPacket->DataLength = Ior->IOR_xfer_count;
if (!(Ior->IOR_flags & IORF_CHAR_COMMAND))
{
IoPacket->DataLength *= IoPacket->BlockSize;
}
break;
}
EXIT(UMSSPDR_ProcessIoPacket)
}
void _stdcall
UMSSPDR_CompleteRequest(
PIOPACKET IoPacket
)
{
/*++
Routine Description:
I/O completion handler for the USB device.
Arguments:
IoPacket - IOPACKET containing request info
Return Value:
None
--*/
PSCSI_REQUEST_BLOCK Srb;
PUSBDDB Ddb;
int i;
pIOP Iop;
ENTER(UMSSPDR_CompleteRequest)
Iop = (pIOP)IoPacket->Iop;
Ddb = (PUSBDDB)((pDCB_cd_entry)Iop->IOP_calldown_ptr)->DCB_cd_ddb;
Srb = (PSCSI_REQUEST_BLOCK)Iop->IOP_srb;
UMSSPDR_DebugPrintf(DBGLVL_MAXIMUM, ("UMSSPDR_CompleteRequest - IOP=%x, IOPACKET=%x\n", Iop, IoPacket));
// Are we completing a REQUEST SENSE command?
if (Ddb->Flags & USBDDB_FLAG_ERROR)
{
UMSSPDR_DebugPrintf(DBGLVL_MAXIMUM, ("REQUEST SENSE complete\n"));
if (IoPacket->Status == IO_STATUS_DEVICE_ERROR)
{
UMSSPDR_DebugPrintf(DBGLVL_MINIMUM, ("REQUEST SENSE Failed!\n"));
// Our request sense failed, so just return error without
// sense data.
Srb->SrbStatus = SRB_STATUS_ERROR;
Trap();
}
else
if (IoPacket->Status == IO_STATUS_SUCCESS)
{
//BUGBUG - put in debug code to dump sense info
Srb->SrbStatus = SRB_STATUS_ERROR | SRB_STATUS_AUTOSENSE_VALID;
}
Ddb->Flags &= ~USBDDB_FLAG_ERROR;
}
// Normal I/O request
else switch (IoPacket->Status)
{
case IO_STATUS_DEVICE_ERROR:
UMSSPDR_DebugPrintf(DBGLVL_DEFAULT, ("I/O request failed\n"));
// Call error handler for REQUEST SENSE handling
UMSSPDR_ErrorHandler(Iop);
EXIT(UMSSPDR_CompleteRequest)
case IO_STATUS_OUT_OF_MEMORY:
UMSSPDR_DebugPrintf(DBGLVL_MINIMUM, ("I/O request failed with memory error\n"));
Srb->SrbStatus = SRB_STATUS_ERROR;
Trap();
break;
case IO_STATUS_SUCCESS:
UMSSPDR_DebugPrintf(DBGLVL_MAXIMUM, ("I/O request succeeded\n"));
// I/O request succeeded
Srb->SrbStatus = SRB_STATUS_SUCCESS;
break;
case IO_STATUS_DATA_OVERRUN:
UMSSPDR_DebugPrintf(DBGLVL_MAXIMUM, ("I/O request succeeded - Data overrun/underrun\n"));
// I/O request succeeded
Srb->SrbStatus = SRB_STATUS_DATA_OVERRUN;
break;
default:
UMSSPDR_DebugPrintf(DBGLVL_MINIMUM, ("Unknown error occurred!\n"));
// This should never happen
Srb->SrbStatus = SRB_STATUS_ERROR;
Trap();
}
// Complete the request
UMSSPDR_CompleteIOP(Iop);
EXIT(UMSSPDR_CompleteRequest)
}
VOID
UMSSPDR_ErrorHandler(
pIOP Iop
)
{
/*++
Routine Description:
Error handler for failed I/O requests. Will send a REQUEST SENSE
command to the device to find out why it failed, if SRB indicates
autosense.
Arguments:
Iop - IOP for failed request
Return Value:
None
--*/
SCSI_REQUEST_BLOCK *Srb;
PUSBDDB Ddb;
PIOPACKET IoPacket;
ENTER(UMSSPDR_ErrorHandler)
Srb = (PSCSI_REQUEST_BLOCK)Iop->IOP_srb;
Ddb = (PUSBDDB)((pDCB_cd_entry)Iop->IOP_calldown_ptr)->DCB_cd_ddb;
if (Srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE)
{
// Client does not want sense data, so just set error status
// and complete the request.
Srb->SrbStatus = SRB_STATUS_ERROR;
// Complete the request
UMSSPDR_CompleteIOP(Iop);
EXIT(UMSSPDR_ErrorHandler)
}
if ((NULL == Srb->SenseInfoBuffer) || (0 == Srb->SenseInfoBufferLength))
{
UMSSPDR_DebugPrintf(DBGLVL_MINIMUM, ("Invalid Sense Info buffer\n"));
// Invalid Sense Info buffer without the
// SRB_FLAGS_DISABLE_AUTOSENSE flag. This shouldn't happen.
Srb->SrbStatus = SRB_STATUS_ERROR;
Trap();
// Complete the request
UMSSPDR_CompleteIOP(Iop);
EXIT(UMSSPDR_ErrorHandler)
}
// Indicate that we are processing an error
Ddb->Flags |= USBDDB_FLAG_ERROR;
// Build a REQUEST SENSE CDB
Ddb->Cdb[0] = SCSIOP_REQUEST_SENSE;
Ddb->Cdb[1] = 0x00;
Ddb->Cdb[2] = 0x00;
Ddb->Cdb[3] = 0x00;
Ddb->Cdb[4] = Srb->SenseInfoBufferLength;
Ddb->Cdb[5] = 0x00;
Ddb->Cdb[6] = 0x00;
Ddb->Cdb[7] = 0x00;
Ddb->Cdb[8] = 0x00;
Ddb->Cdb[9] = 0x00;
Ddb->Cdb[10] = 0x00;
Ddb->Cdb[11] = 0x00;
IoPacket = &(Ddb->IoPacket);
// Populate the IOPACKET structure sent to our WDM driver
IoPacket->Fdo = Ddb->Fdo;
IoPacket->Cdb = Ddb->Cdb;
IoPacket->CdbLength = 12;
IoPacket->DataBuffer = Srb->SenseInfoBuffer;
IoPacket->DataLength = Srb->SenseInfoBufferLength;
IoPacket->Iop = (PVOID)Iop;
IoPacket->Flags = IO_FLAGS_DATA_IN;
IoPacket->Status = IO_STATUS_PENDING;
IoPacket->BlockSize = 512;
// Call the WDM driver
pfnStartRequest(IoPacket);
EXIT(UMSSPDR_ErrorHandler)
}
VOID
UMSSPDR_CompleteIOP(
pIOP Iop
)
{
/*++
Routine Description:
Completes IOP request
Arguments:
Iop - IOP to complete
Return Value:
None
--*/
IOP_callback_entry * IopCB;
pIOP NextIop;
PUSBDDB Ddb;
PDCB Dcb;
ENTER(UMSSPDR_CompleteIOP)
Ddb = (PUSBDDB)((pDCB_cd_entry)Iop->IOP_calldown_ptr)->DCB_cd_ddb;
Dcb = (PDCB)Iop->IOP_physical_dcb;
UMSSPDR_DebugPrintf(DBGLVL_MAXIMUM, ("Complete - IOP = %x, DCB=%x\n", Iop, Dcb));
// Find address of first callback handler
Iop->IOP_callback_ptr -= sizeof (IOP_callback_entry);
IopCB = (IOP_callback_entry *)(Iop->IOP_callback_ptr);
// Complete the IOP by calling the first entry in the callback chain
SaveEbx();
IOPCallBack(IopCB, Iop);
RestoreEbx();
// We are no longer busy
Ddb->Flags &= ~USBDDB_FLAG_BUSY;
// See if there are any queued requests
NextIop = ILBDequeueIop(Dcb);
// No IOP pending for current LUN, so check if other LUNs have I/O pending
if (NULL == NextIop)
NextIop = UMSSPDR_GetNextIop(Ddb);
UMSSPDR_DebugPrintf(DBGLVL_MAXIMUM, ("Request - NextIOP %x\n", NextIop));
if (NextIop)
{
Ddb->Flags |= USBDDB_FLAG_BUSY;
// There is a queued IOP, so go process it
UMSSPDR_StartIo(NextIop);
}
EXIT(UMSSPDR_CompleteIOP)
}
pIOP
UMSSPDR_GetNextIop(
PUSBDDB Ddb
)
/*++
Routine Description:
Dequeues next IOP for the device
Arguments:
Ddb - DDB for device
Return Value:
Next pending IOP, or NULL
--*/
{
pIOP Iop=NULL;
PDCB Dcb;
ENTER(UMSSPDR_GetNextIop)
// Get the first DCB attached to this DDB
Dcb = UMSSPDR_GetFirstDcb(Ddb);
if (NULL == Dcb)
RETURN(NULL, UMSSPDR_GetNextIop)
UMSSPDR_DebugPrintf(DBGLVL_MAXIMUM, ("First DCB = %x\n", Dcb));
// Loop thru all DCBs attached to this DDB, until we either find an IOP
// or run out of DCBs
while (!(Iop = ILBDequeueIop(Dcb)) && (Dcb = UMSSPDR_GetNextDcb(Ddb, Dcb)));
RETURN(Iop, UMSSPDR_GetNextIop)
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -