⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 umssio.c

📁 usb海量存储的驱动程序
💻 C
📖 第 1 页 / 共 2 页
字号:
        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 + -