umss.c
来自「ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机」· C语言 代码 · 共 1,933 行 · 第 1/5 页
C
1,933 行
inq->Versions = 0x04;
//
// the format is in scsi-2 format
//
inq->ResponseDataFormat = 0x02;
//
// we are the poor scsi device
//
inq->AdditionalLength = 31;
inq->SoftReset = 0;
inq->CommandQueue = 0;
inq->LinkedCommands = 0;
inq->RelativeAddressing = 0;
RtlCopyMemory(&inq->VendorId, "Unknown", 7);
RtlCopyMemory(&inq->ProductId, "USB Mass Storage", 16);
irp->IoStatus.Information = required_size;
EXIT_DISPATCH(STATUS_SUCCESS, irp);
}
case IOCTL_SCSI_GET_CAPABILITIES:
{
PIO_SCSI_CAPABILITIES port_cap;
if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(IO_SCSI_CAPABILITIES))
EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
port_cap = (PIO_SCSI_CAPABILITIES) irp->AssociatedIrp.SystemBuffer;
port_cap->Length = sizeof(IO_SCSI_CAPABILITIES);
port_cap->MaximumTransferLength = 65536;
port_cap->MaximumPhysicalPages = 65536 / PAGE_SIZE;
port_cap->SupportedAsynchronousEvents = 0;
port_cap->AlignmentMask = 0x10;
port_cap->TaggedQueuing = FALSE;
port_cap->AdapterScansDown = FALSE;
port_cap->AdapterUsesPio = FALSE;
irp->IoStatus.Information = sizeof(IO_SCSI_CAPABILITIES);
EXIT_DISPATCH(STATUS_SUCCESS, irp);
}
case IOCTL_SCSI_GET_ADDRESS:
{
PSCSI_ADDRESS paddr;
if (irp_stack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SCSI_ADDRESS))
EXIT_DISPATCH(STATUS_INVALID_PARAMETER, irp);
paddr = (PSCSI_ADDRESS) irp->AssociatedIrp.SystemBuffer;
paddr->Length = sizeof(SCSI_ADDRESS);
paddr->PortNumber = 0;
paddr->PathId = 0;
paddr->TargetId = pdev_ext->umss_dev_id;
paddr->Lun = (UCHAR) (pdev_ext->dev_handle >> 16);
irp->IoStatus.Information = sizeof(SCSI_ADDRESS);
EXIT_DISPATCH(STATUS_SUCCESS, irp);
}
case IOCTL_SCSI_RESCAN_BUS:
{
irp->IoStatus.Information = 0;
EXIT_DISPATCH(STATUS_SUCCESS, irp);
}
default:
{
EXIT_DISPATCH(STATUS_INVALID_DEVICE_REQUEST, irp);
}
}
}
}
EXIT_DISPATCH(STATUS_NOT_SUPPORTED, irp);
}
VOID
umss_reset_pipe_completion(PURB purb, PVOID context)
{
PUMSS_DEVICE_EXTENSION pdev_ext;
if (context == NULL)
return;
pdev_ext = (PUMSS_DEVICE_EXTENSION) context;
pdev_ext->reset_pipe_status = purb->status;
KeSetEvent(&pdev_ext->sync_event, 0, FALSE);
return;
}
//can only be called at passive level
NTSTATUS
umss_reset_pipe(PUMSS_DEVICE_EXTENSION pdev_ext, DEV_HANDLE endp_handle)
{
NTSTATUS status;
PUSB_DEV pdev;
if (pdev_ext == NULL)
return STATUS_INVALID_PARAMETER;
status = usb_query_and_lock_dev(pdev_ext->dev_mgr, pdev_ext->dev_handle, &pdev);
if (status != STATUS_SUCCESS)
return STATUS_UNSUCCESSFUL;
status = usb_reset_pipe_ex(pdev_ext->dev_mgr, endp_handle, umss_reset_pipe_completion, pdev_ext);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&pdev_ext->sync_event, Executive, KernelMode, TRUE, NULL);
status = pdev_ext->reset_pipe_status;
}
usb_unlock_dev(pdev);
return status;
}
BOOLEAN
umss_gen_result_srb(PIO_PACKET io_packet, PSCSI_REQUEST_BLOCK srb, NTSTATUS status)
{
if (srb == NULL || io_packet == NULL)
{
return FALSE;
}
if (status == STATUS_SUCCESS)
{
PULONG dest_buf, src_buf;
ULONG i;
srb->SrbStatus = SRB_STATUS_SUCCESS;
io_packet->pirp->IoStatus.Information = srb->DataTransferLength;
if ((io_packet->pirp->Flags & IRP_READ_OPERATION) && !(io_packet->pirp->Flags & IRP_PAGING_IO))
{
src_buf = (PULONG) io_packet->data_buffer;
dest_buf = (PULONG) srb->DataBuffer;
if (src_buf && dest_buf)
{
for(i = 0; i < (srb->DataTransferLength >> 2); i++)
{
dest_buf[i] = src_buf[i];
}
}
}
}
else if (status == STATUS_DEVICE_DOES_NOT_EXIST)
{
PSENSE_DATA sense_buf;
srb->SrbStatus = SRB_STATUS_NO_DEVICE;
srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
//
// let's build the srb status for class driver
//
srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
sense_buf = (PSENSE_DATA) srb->SenseInfoBuffer;
if (!(srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE))
{
RtlZeroMemory(srb->SenseInfoBuffer, srb->SenseInfoBufferLength);
sense_buf->ErrorCode = 0x70;
sense_buf->Valid = 1;
sense_buf->SenseKey = SCSI_SENSE_NOT_READY;
sense_buf->AdditionalSenseCode = SCSI_ADSENSE_NO_MEDIA_IN_DEVICE;
sense_buf->AdditionalSenseLength = 10;
}
}
else if (status == USB_STATUS_STALL_PID || status == USB_STATUS_CRC ||
status == USB_STATUS_BTSTUFF || status == USB_STATUS_DATA_OVERRUN)
{
PSENSE_DATA sense_buf;
srb->SrbStatus = SRB_STATUS_ERROR;
srb->ScsiStatus = SCSISTAT_CHECK_CONDITION;
srb->SrbStatus |= SRB_STATUS_AUTOSENSE_VALID;
sense_buf = (PSENSE_DATA) srb->SenseInfoBuffer;
if (!(srb->SrbFlags & SRB_FLAGS_DISABLE_AUTOSENSE))
{
RtlZeroMemory(srb->SenseInfoBuffer, srb->SenseInfoBufferLength);
sense_buf->ErrorCode = 0x70;
sense_buf->Valid = 1;
sense_buf->SenseKey = SCSI_SENSE_HARDWARE_ERROR;
sense_buf->AdditionalSenseCode = 0;
sense_buf->AdditionalSenseLength = 10;
}
}
else
{
srb->SrbStatus = SRB_STATUS_ERROR;
}
if ((io_packet->pirp->Flags & (IRP_READ_OPERATION | IRP_WRITE_OPERATION))
&& !(io_packet->pirp->Flags & IRP_PAGING_IO))
{
if (io_packet->data_buffer)
{
usb_free_mem(io_packet->data_buffer);
io_packet->data_buffer = NULL;
}
}
return TRUE;
}
BOOLEAN
umss_gen_result_ctrl(PDEVICE_OBJECT dev_obj, PIRP irp, NTSTATUS status)
{
PIO_STACK_LOCATION irp_stack;
ULONG ctrl_code;
PUMSS_DEVICE_EXTENSION pdev_ext;
if (irp == NULL)
return FALSE;
irp->IoStatus.Information = 0;
irp_stack = IoGetCurrentIrpStackLocation(irp);
ctrl_code = irp_stack->Parameters.DeviceIoControl.IoControlCode;
pdev_ext = dev_obj->DeviceExtension;
switch (ctrl_code)
{
case IOCTL_SCSI_PASS_THROUGH:
{
PSCSI_PASS_THROUGH pass_through;
pass_through = irp->AssociatedIrp.SystemBuffer;
irp->IoStatus.Status = status;
// we have set these two value in bulkonly.c when data transfer complete
// pass_through_direct->DataTransferLength = pdev_ext->io_packet.data_length;
// pass_through_direct->SenseInfoLength = pdev_ext->io_packet.sense_data_length;
if (status == STATUS_SUCCESS)
irp->IoStatus.Information = pass_through->SenseInfoOffset + pass_through->SenseInfoLength;
else
pass_through->ScsiStatus = SCSISTAT_CHECK_CONDITION;
return TRUE;
}
case IOCTL_SCSI_PASS_THROUGH_DIRECT:
{
PSCSI_PASS_THROUGH_DIRECT pass_through_direct;
pass_through_direct = irp->AssociatedIrp.SystemBuffer;
pass_through_direct->ScsiStatus = 0;
irp->IoStatus.Status = status;
// we have set these two value in bulkonly.c when data transfer complete
// pass_through_direct->DataTransferLength = pdev_ext->io_packet.data_length;
// pass_through_direct->SenseInfoLength = pdev_ext->io_packet.sense_data_length;
if (status == STATUS_SUCCESS)
irp->IoStatus.Information =
pass_through_direct->SenseInfoOffset + pass_through_direct->SenseInfoLength;
else
pass_through_direct->ScsiStatus = SCSISTAT_CHECK_CONDITION;
return TRUE;
}
}
return FALSE;
}
VOID
umss_complete_request(PUMSS_DEVICE_EXTENSION pdev_ext, NTSTATUS status)
{
PIRP pirp;
KIRQL old_irql;
PDEVICE_OBJECT dev_obj;
PIO_STACK_LOCATION irp_stack;
usb_dbg_print(DBGLVL_MAXIMUM, ("umss_complete_request(): entering...\n"));
pirp = pdev_ext->io_packet.pirp;
dev_obj = pdev_ext->pdo;
irp_stack = IoGetCurrentIrpStackLocation(pirp);
if (pdev_ext->io_packet.flags & IOP_FLAG_SRB_TRANSFER)
{
if (pdev_ext->pif_desc->bInterfaceSubClass == UMSS_SUBCLASS_SFF8070I)
{
umss_fix_sff_result(&pdev_ext->io_packet, irp_stack->Parameters.Scsi.Srb);
}
umss_gen_result_srb(&pdev_ext->io_packet, irp_stack->Parameters.Scsi.Srb, status);
}
else if (pdev_ext->io_packet.flags & IOP_FLAG_SCSI_CTRL_TRANSFER)
umss_gen_result_ctrl(dev_obj, pirp, status);
//this device has its irp queued
if (status == STATUS_CANCELLED)
{
IoAcquireCancelSpinLock(&old_irql);
if (dev_obj->CurrentIrp == pirp)
{
IoReleaseCancelSpinLock(old_irql);
IoStartNextPacket(dev_obj, FALSE);
}
else
{
KeRemoveEntryDeviceQueue(&dev_obj->DeviceQueue, &pirp->Tail.Overlay.DeviceQueueEntry);
IoReleaseCancelSpinLock(old_irql);
}
}
else
// all requests come to this point from the irp queue
IoStartNextPacket(dev_obj, FALSE);
pirp->IoStatus.Status = status;
if (status != STATUS_SUCCESS)
pirp->IoStatus.Information = 0;
IoCompleteRequest(pirp, IO_NO_INCREMENT);
return;
}
BOOLEAN
umss_if_connect(PDEV_CONNECT_DATA params, DEV_HANDLE if_handle)
{
PURB purb;
LONG if_idx, i;
PUCHAR desc_buf;
NTSTATUS status;
PUSB_DEV pdev;
PUSB_DRIVER pdrvr;
PUSB_INTERFACE_DESC pif_desc;
PUSB_CTRL_SETUP_PACKET psetup;
PUMSS_DEVICE_EXTENSION pdev_ext;
PUSB_CONFIGURATION_DESC pconfig_desc;
PUSB_DEV_MANAGER dev_mgr;
PUSB_ENDPOINT_DESC pendp_desc;
PUMSS_DRVR_EXTENSION pdrvr_ext;
PDEVICE_OBJECT pdev_obj;
USE_BASIC_NON_PENDING_IRQL;
//configuration is already set
purb = NULL;
desc_buf = NULL;
pdev = NULL;
usb_dbg_print(DBGLVL_MAXIMUM, ("umss_if_connect(): entering...\n"));
if (params == NULL)
return FALSE;
dev_mgr = params->dev_mgr;
pdrvr = params->pdriver;
if_idx = if_idx_from_handle(if_handle);
purb = usb_alloc_mem(NonPagedPool, sizeof(URB));
if (purb == NULL)
goto ERROR_OUT;
desc_buf = usb_alloc_mem(NonPagedPool, 512);
if (desc_buf == NULL)
goto ERROR_OUT;
psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet;
urb_init((purb));
// now let's get the descs, one configuration, one interface and two endpoint
psetup = (PUSB_CTRL_SETUP_PACKET) (purb)->setup_packet;
purb->endp_handle = if_handle | 0xffff;
purb->data_buffer = desc_buf;
purb->data_length = 512;
purb->completion = NULL; // this is an immediate request, no needs completion
purb->context = dev_mgr;
purb->reference = 0;
psetup->bmRequestType = 0x80;
psetup->bRequest = USB_REQ_GET_DESCRIPTOR;
psetup->wValue = USB_DT_CONFIG << 8;
psetup->wIndex = 0;
psetup->wLength = 512;
status = usb_submit_urb(dev_mgr, purb);
if (status == STATUS_PENDING)
{
TRAP();
}
usb_free_mem(purb);
purb = NULL;
if (status != STATUS_SUCCESS)
{
goto ERROR_OUT;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?