?? usbio.c
字號:
/*++
Copyright (c) 1999 Microsoft Corporation
Module Name:
UsbIo.c
Abstract:
IOS port driver for USB LS-120 drive
I/O module
Environment:
kernel mode only
Notes:
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
PURPOSE.
Copyright (c) 1999 Microsoft Corporation. All Rights Reserved.
Revision History:
03/19/99: MRB Original
--*/
#define WANTVXDWRAPS
#define _NTDEF_
#include <debug.h>
#include <vxdwraps.h>
#include <srb.h>
#include <scsi.h>
#include <aep.h>
#include <drp.h>
#include <isp.h>
#include <srb.h>
#include <ior.h>
#include <iop.h>
#include <dcb.h>
#include <ilb.h>
#include "usbstor.h"
#include "usbdebug.h"
// NOTE: This module cannot include VMM.H, due to conflicts in base
// definitions that occur when SCSI.H is included. Any calls to
// VMM or VxD services should be made from another source file.
// Indicate locked code and data. We can't use macros defined in VMM.H,
// so we use the same pragmas defined in VMM.H for locked code and data.
#pragma code_seg("_LTEXT", "LCODE")
#pragma data_seg("_LDATA", "LCODE")
// IOS ILB function type definitions
typedef PVOID (__cdecl *ILB_internal_request_func)( struct ISP * );
typedef PVOID (__cdecl *ILB_enqueue_iop_func)( pIOP, PDCB);
typedef pIOP (__cdecl *ILB_dequeue_iop_func)( PDCB);
USHORT
USBSTOR_Device_Inquiry(
PAEP_inquiry_device Aep
)
{
/*++
Routine Description:
AEP_DEVICE_INQUIRY handler. Builds INQUIRY SRB and sends it to
our USB device to find out what device is attached. INQUIRY data
is copied into the DCB.
Arguments:
None
Return Value:
AEP_SUCCESS if INQUIRY data returned,
AEP_NO_INQ_DATA otherwise
--*/
PDCB Dcb;
pIOP Iop;
PIOR Ior;
ISP_IOP_alloc IOPCreateISP;
ISP_mem_alloc AllocISP;
ULONG IOPLength;
PSCSI_REQUEST_BLOCK Srb;
PCDB Cdb;
PINQUIRYDATA pInquiryBuf;
USHORT AepResult=AEP_SUCCESS;
USBSTOR_DebugPrintf(DBG_DEFAULT, ("Device Inquiry\n"));
// Allocate an IOP for our INQUIRY command
IOPLength = sizeof( IOP ) +
sizeof( SCSI_REQUEST_BLOCK ) +
sizeof( INQUIRYDATA );
((PISP)&IOPCreateISP)->ISP_func = ISP_CREATE_IOP;
IOPCreateISP.ISP_IOP_size = IOPLength;
IOPCreateISP.ISP_delta_to_ior = (ULONG)&(((pIOP)0L)->IOP_ior);
IOPCreateISP.ISP_i_c_flags = ISP_M_FL_MUST_SUCCEED;
// Call IOS
ILBService(&IOPCreateISP);
// Our allocated IOP memory will be formatted like this:
// ---------------------------
// | IOP/IOR |
// ---------------------------
// | SRB |
// ---------------------------
// | INQUIRY DATA BUFFER |
// ---------------------------
//
// Build our I/O request
//
Iop = (pIOP)(PVOID)IOPCreateISP.ISP_IOP_ptr;
Ior = (PIOR)&(Iop->IOP_ior);
Srb = (SCSI_REQUEST_BLOCK *)(Iop + 1);
Dcb = (PDCB)Aep->AEP_i_d_dcb;
pInquiryBuf = (PINQUIRYDATA) (((PCHAR)Iop)+ IOPLength - sizeof(INQUIRYDATA));
Iop->IOP_original_dcb = Iop->IOP_physical_dcb = (ULONG)Dcb;
Iop->IOP_srb = (ULONG)Srb;
Ior->IOR_func = IOR_SCSI_PASS_THROUGH;
Ior->IOR_req_vol_handle = 0L;
Ior->IOR_flags = IORF_SYNC_COMMAND |
IORF_CHAR_COMMAND |
IORF_VERSION_002 |
IORF_SRB_VALID |
IORF_BYPASS_VOLTRK |
IORF_INHIBIT_GEOM_RECOMPUTE;
Ior->IOR_buffer_ptr = (ULONG) pInquiryBuf;
Ior->IOR_xfer_count = sizeof( INQUIRYDATA );
Ior->IOR_sgd_lin_phys = (ULONG)0;
Ior->IOR_next = 0L;
Srb->Length = sizeof( SCSI_REQUEST_BLOCK );
Srb->TimeOutValue = 30;
Srb->CdbLength = 6;
// We won't do a REQUEST SENSE if the INQUIRY command fails,
// since we will always fail on any error that occurs for
// INQUIRY.
Srb->SenseInfoBuffer = NULL;
Srb->SrbFlags = SRB_FLAGS_DATA_IN |
SRB_FLAGS_DISABLE_AUTOSENSE;
Srb->DataBuffer = (PVOID) Ior->IOR_buffer_ptr;
Srb->DataTransferLength = sizeof( INQUIRYDATA );
Srb->PathId = Dcb->DCB_bus_number;
Srb->TargetId = Dcb->DCB_scsi_target_id;
Srb->Lun = Dcb->DCB_scsi_lun;
Srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
Srb->SrbExtension = (PCHAR)Srb;
// Setup INQUIRY CDB
Cdb = (PCDB)Srb->Cdb;
Cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
Cdb->CDB6INQUIRY.LogicalUnitNumber = Srb->Lun;
Cdb->CDB6INQUIRY.Reserved1 = 0;
Cdb->CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE;
Cdb->CDB6INQUIRY.PageCode = 0;
Cdb->CDB6INQUIRY.IReserved = 0;
Cdb->CDB6INQUIRY.Control = 0;
// Call IOS to fill in SG descriptors, etc.
ILBCriteria(Iop);
// Submit request to IOS
ILBRequest(Iop, Dcb);
if( SRB_STATUS( Srb->SrbStatus ) == SRB_STATUS_SUCCESS ||
SRB_STATUS( Srb->SrbStatus ) == SRB_STATUS_DATA_OVERRUN )
{
USBSTOR_DebugPrintf(DBG_DEFAULT, ("INQUIRY succeeded\n"));
// Copy INQUIRY data into the DCB. It is very important
// that the INQUIRY Peripheral Device Type field be
// correct, as this is what IOS uses to determine what
// kind of device has been enumerated (this is true for
// all bus types, including SCSI, IDE, ATAPI).
_lmemcpy( (PCHAR)(Dcb->DCB_inquiry_flags),
(PCHAR)pInquiryBuf,
sizeof( Dcb->DCB_inquiry_flags ) +
sizeof( Dcb->DCB_vendor_id ) +
sizeof( Dcb->DCB_product_id ) +
sizeof( Dcb->DCB_rev_level ));
}
else
{
USBSTOR_DebugPrintf(DBG_MIN, ("No INQUIRY data found!\n"));
AepResult = AEP_NO_INQ_DATA;
}
// Free our IOP
((PISP)&AllocISP)->ISP_func = ISP_DEALLOC_MEM;
((PISP_mem_dealloc)&AllocISP)->ISP_mem_ptr_da = (ULONG)Iop;
((ILB_internal_request_func)(USBSTOR_Ilb.ILB_service_rtn))((PISP)&AllocISP);
return AepResult;
}
void
USBSTOR_Request(
pIOP piop
)
{
/*++
Routine Description:
I/O request handler for the USB device.
Arguments:
piop - I/O Packet containing request information
Return Value:
None
--*/
DWORD DeviceObject;
PDCB Dcb;
pIOP Iop;
PIOR Ior;
PUSBDDB Ddb;
USBSTOR_DebugPrintf(DBG_MAX, ("Enter USBSTOR_Request()\n"));
DeviceObject = (DWORD)((pDCB_cd_entry)piop->IOP_calldown_ptr)->DCB_cd_ddb;
Dcb = (PDCB)piop->IOP_physical_dcb;
Ddb = (PUSBDDB)((pDCB_cd_entry)piop->IOP_calldown_ptr)->DCB_cd_ddb;
// Put the IOP on the queue for this DCB
ILBEnqueueIop(piop, Dcb);
//Need to handle busy case
if (Ddb->Flags & USBDDB_FLAG_BUSY)
{
USBSTOR_DebugPrintf(DBG_MAX, ("Device Busy!!\n"));
// Device is already busy, so just return. IOP will be
// dequeued and processed after current request completes
return;
}
// Mark this device as now busy
Ddb->Flags |= USBDDB_FLAG_BUSY;
// Device is not busy, so get next IOP for processing
Iop = ILBDequeueIop(Dcb);
if (Iop)
USBSTOR_StartIo(Iop);
else
{
Trap(); // This should never happen
Ddb->Flags &= ~USBDDB_FLAG_BUSY;
}
}
VOID
USBSTOR_StartIo(
pIOP Iop
)
{
/*++
Routine Description:
Function that calls WDM driver to initiate I/O transaction.
Arguments:
Iop - Dequeued IOP for next request.
Return Value:
None
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -