Annotation of ntddk/src/scsi/scsiscan/scsiscan.c, revision 1.1.1.1

1.1       root        1: /*++
                      2: 
                      3: Copyright (c) 1992  Microsoft Corporation
                      4: 
                      5: Module Name:
                      6: 
                      7:     scsiscan.c
                      8: 
                      9: Abstract:
                     10: 
                     11:     The scsi scanner class driver tranlates IRPs to SRBs with embedded CDBs
                     12:     and sends them to its devices through the port driver.
                     13: 
                     14: Author:
                     15: 
                     16:     Mike Glass (mglass)
                     17: 
                     18: Environment:
                     19: 
                     20:     kernel mode only
                     21: 
                     22: Notes:
                     23: 
                     24: Revision History:
                     25: 
                     26: --*/
                     27: 
                     28: #include "ntddk.h"
                     29: #include "scsi.h"
                     30: #include "class.h"
                     31: 
                     32: #define DEVICE_EXTENSION_SIZE sizeof(DEVICE_EXTENSION)
                     33: 
                     34: 
                     35: BOOLEAN
                     36: FindScsiScanners(
                     37:     IN PDRIVER_OBJECT DriveObject,
                     38:     IN PDEVICE_OBJECT PortDeviceObject
                     39:     );
                     40: 
                     41: NTSTATUS
                     42: CreateScannerDeviceObject(
                     43:     IN PDRIVER_OBJECT DriverObject,
                     44:     IN PDEVICE_OBJECT PortDeviceObject,
                     45:     IN PULONG DeviceCount,
                     46:     IN PCHAR ArcName,
                     47:     IN PIO_SCSI_CAPABILITIES PortCapabilities,
                     48:     IN PSCSI_INQUIRY_DATA LunInfo
                     49:     );
                     50: 
                     51: NTSTATUS
                     52: ScsiScannerOpen(
                     53:     IN PDEVICE_OBJECT DeviceObject,
                     54:     IN PIRP Irp
                     55:     );
                     56: 
                     57: NTSTATUS
                     58: ScsiScannerReadWrite(
                     59:     IN PDEVICE_OBJECT DeviceObject,
                     60:     IN PIRP Irp
                     61:     );
                     62: 
                     63: NTSTATUS
                     64: ScsiScannerDeviceControl(
                     65:     IN PDEVICE_OBJECT DeviceObject,
                     66:     IN PIRP Irp
                     67:     );
                     68: 
                     69: VOID
                     70: BuildScannerRequest(
                     71:     PDEVICE_OBJECT DeviceObject,
                     72:     PIRP Irp
                     73:     );
                     74: 
                     75: VOID
                     76: ScsiScannerError(
                     77:     PDEVICE_OBJECT DeviceObject,
                     78:     IN PSCSI_REQUEST_BLOCK Srb,
                     79:     IN OUT NTSTATUS *Status,
                     80:     IN OUT BOOLEAN *Retry
                     81:     );
                     82: 
                     83: VOID
                     84: SplitRequest(
                     85:     IN PDEVICE_OBJECT DeviceObject,
                     86:     IN PIRP Irp,
                     87:     IN ULONG MaximumBytes
                     88:     );
                     89: 
                     90: 
                     91: NTSTATUS
                     92: DriverEntry(
                     93:     IN PDRIVER_OBJECT DriverObject,
                     94:     IN PUNICODE_STRING RegistryPath
                     95:     )
                     96: 
                     97: /*++
                     98: 
                     99: Routine Description:
                    100: 
                    101:     This routine initializes the scanner class driver. The driver
                    102:     opens the port driver by name and then receives configuration
                    103:     information used to attach to the scanner devices.
                    104: 
                    105: Arguments:
                    106: 
                    107:     DriverObject
                    108: 
                    109: Return Value:
                    110: 
                    111:     NT Status
                    112: 
                    113: --*/
                    114: 
                    115: {
                    116:     ULONG portNumber = 0;
                    117:     NTSTATUS status;
                    118:     PFILE_OBJECT fileObject;
                    119:     PDEVICE_OBJECT portDeviceObject;
                    120:     STRING deviceNameString;
                    121:     CCHAR deviceNameBuffer[64];
                    122:     UNICODE_STRING unicodeDeviceName;
                    123:     BOOLEAN foundOne = FALSE;
                    124: 
                    125:     DebugPrint((1,"\n\nSCSI Scanner Class Driver\n"));
                    126: 
                    127:     //
                    128:     // Set up the device driver entry points.
                    129:     //
                    130: 
                    131:     DriverObject->MajorFunction[IRP_MJ_READ] = ScsiScannerReadWrite;
                    132:     DriverObject->MajorFunction[IRP_MJ_WRITE] = ScsiScannerReadWrite;
                    133:     DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiScannerDeviceControl;
                    134:     DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiScannerOpen;
                    135: 
                    136:     //
                    137:     // Open port driver device objects by name.
                    138:     //
                    139: 
                    140:     do {
                    141: 
                    142:         //
                    143:         // Create port driver name.
                    144:         //
                    145: 
                    146:         sprintf(deviceNameBuffer,
                    147:                 "\\Device\\ScsiPort%d",
                    148:                 portNumber++);
                    149: 
                    150:         DebugPrint((2,"ScsiScannerInitialize: Open %s\n",
                    151:                     deviceNameBuffer));
                    152: 
                    153:         RtlInitString(&deviceNameString,
                    154:                       deviceNameBuffer);
                    155: 
                    156:         status = RtlAnsiStringToUnicodeString(&unicodeDeviceName,
                    157:                                               &deviceNameString,
                    158:                                               TRUE);
                    159: 
                    160:         if (!NT_SUCCESS(status)) {
                    161: 
                    162:             DebugPrint((1,
                    163:                         "ScsiScannerInitialize: Could not initalize unicode string %s\n",
                    164:                         deviceNameString));
                    165: 
                    166:             break;
                    167:         }
                    168: 
                    169:         status = IoGetDeviceObjectPointer(&unicodeDeviceName,
                    170:                                           FILE_READ_ATTRIBUTES,
                    171:                                           &fileObject,
                    172:                                           &portDeviceObject);
                    173: 
                    174:         if (NT_SUCCESS(status)) {
                    175: 
                    176:             //
                    177:             // SCSI port driver exists.
                    178:             //
                    179: 
                    180:             if (FindScsiScanners(DriverObject,
                    181:                            portDeviceObject)) {
                    182: 
                    183:                 foundOne = TRUE;
                    184:             }
                    185: 
                    186:             //
                    187:             // Dereference the file object since the port device pointer is no
                    188:             // longer needed.  The claim device code refences the port driver
                    189:             // pointer that is actually being used.
                    190:             //
                    191: 
                    192:             ObDereferenceObject(fileObject);
                    193:         }
                    194: 
                    195:     } while (NT_SUCCESS(status));
                    196: 
                    197:     if (foundOne) {
                    198:         return STATUS_SUCCESS;
                    199:     } else {
                    200:         return STATUS_NO_SUCH_DEVICE;
                    201:     }
                    202: 
                    203: } // end DriverEntry()
                    204: 
                    205: 
                    206: BOOLEAN
                    207: FindScsiScanners(
                    208:     IN PDRIVER_OBJECT DriverObject,
                    209:     IN PDEVICE_OBJECT PortDeviceObject
                    210:     )
                    211: 
                    212: /*++
                    213: 
                    214: Routine Description:
                    215: 
                    216:     Connect to SCSI port driver. Get adapter capabilities and
                    217:     SCSI bus configuration information. Search inquiry data
                    218:     for scanner devices to process.
                    219: 
                    220: Arguments:
                    221: 
                    222:     Scanner class driver object
                    223:     SCSI port driver device object
                    224: 
                    225: Return Value:
                    226: 
                    227:     NONE
                    228: 
                    229: --*/
                    230: 
                    231: {
                    232:     PIO_SCSI_CAPABILITIES portCapabilities;
                    233:     PCHAR buffer;
                    234:     PSCSI_INQUIRY_DATA lunInfo;
                    235:     PSCSI_ADAPTER_BUS_INFO  adapterInfo;
                    236:     PINQUIRYDATA inquiryData;
                    237:     ULONG scsiBus;
                    238:     ULONG scannerCount = 0;
                    239:     NTSTATUS status;
                    240: 
                    241:     //
                    242:     // Call port driver to get adapter capabilities.
                    243:     //
                    244: 
                    245:     status = ScsiClassGetCapabilities(PortDeviceObject, &portCapabilities);
                    246: 
                    247:     if (!NT_SUCCESS(status)) {
                    248:         DebugPrint((1,"FindScsiDevices: ScsiClassGetCapabilities failed\n"));
                    249:         return FALSE;
                    250:     }
                    251: 
                    252:     //
                    253:     // Call port driver to get inquiry information to find Scanners.
                    254:     //
                    255: 
                    256:     status = ScsiClassGetInquiryData(PortDeviceObject, (PSCSI_ADAPTER_BUS_INFO *)&buffer);
                    257: 
                    258:     if (!NT_SUCCESS(status)) {
                    259:         DebugPrint((1,"FindScsiDevices: ScsiClassGetInquiryData failed\n"));
                    260:         return FALSE;
                    261:     }
                    262: 
                    263:     adapterInfo = (PVOID)buffer;
                    264: 
                    265:     //
                    266:     // For each SCSI bus this adapter supports ...
                    267:     //
                    268: 
                    269:     for (scsiBus=0; scsiBus < (ULONG)adapterInfo->NumberOfBuses; scsiBus++) {
                    270: 
                    271:         //
                    272:         // Get the SCSI bus scan data for this bus.
                    273:         //
                    274: 
                    275:         lunInfo = (PVOID)(buffer + adapterInfo->BusData[scsiBus].InquiryDataOffset);
                    276: 
                    277:         //
                    278:         // Search list for unclaimed disk devices.
                    279:         //
                    280: 
                    281:         while (adapterInfo->BusData[scsiBus].InquiryDataOffset) {
                    282: 
                    283:             inquiryData = (PVOID)lunInfo->InquiryData;
                    284: 
                    285:             DebugPrint((3,"FindScsiDevices: Inquiry data at %lx\n",
                    286:                         inquiryData));
                    287: 
                    288:             //
                    289:             // Check for SCANNER devices and PROCESSOR devices, as some
                    290:             // scanners use this device type.
                    291:             //
                    292: 
                    293:             if (((inquiryData->DeviceType == SCANNER_DEVICE) ||
                    294:                  (inquiryData->DeviceType == PROCESSOR_DEVICE)) &&
                    295:                 (!lunInfo->DeviceClaimed)) {
                    296: 
                    297:                 DebugPrint((1,"FindScsiDevices: Vendor string is %.24s\n",
                    298:                             inquiryData->VendorId));
                    299: 
                    300:                 //
                    301:                 // Create device objects for device
                    302:                 //
                    303: 
                    304:                 status = CreateScannerDeviceObject(DriverObject,
                    305:                                                    PortDeviceObject,
                    306:                                                    &scannerCount,
                    307:                                                    NULL,
                    308:                                                    portCapabilities,
                    309:                                                    lunInfo);
                    310: 
                    311:                 if (NT_SUCCESS(status)) {
                    312: 
                    313:                     //
                    314:                     // Increment device count.
                    315:                     //
                    316: 
                    317:                     scannerCount++;
                    318: 
                    319:                 }
                    320:              }
                    321: 
                    322:             //
                    323:             // Get next LunInfo.
                    324:             //
                    325: 
                    326:             if (lunInfo->NextInquiryDataOffset == 0) {
                    327:                 break;
                    328:             }
                    329: 
                    330:             lunInfo = (PVOID)(buffer + lunInfo->NextInquiryDataOffset);
                    331:         }
                    332:     }
                    333: 
                    334:     ExFreePool(buffer);
                    335:     if (scannerCount > 0) {;
                    336:         return TRUE;
                    337:     } else {
                    338:         return FALSE;
                    339:     }
                    340: 
                    341: } // end FindScsiScanners()
                    342: 
                    343: 
                    344: NTSTATUS
                    345: CreateScannerDeviceObject(
                    346:     IN PDRIVER_OBJECT DriverObject,
                    347:     IN PDEVICE_OBJECT PortDeviceObject,
                    348:     IN PULONG DeviceCount,
                    349:     IN PCHAR ArcName,
                    350:     IN PIO_SCSI_CAPABILITIES PortCapabilities,
                    351:     IN PSCSI_INQUIRY_DATA LunInfo
                    352:     )
                    353: 
                    354: /*++
                    355: 
                    356: Routine Description:
                    357: 
                    358:     This routine creates an object for the device and then calls the
                    359:     SCSI port driver for media capacity and sector size.
                    360: 
                    361: Arguments:
                    362: 
                    363:     DriverObject - Pointer to driver object created by system.
                    364:     PortDeviceObject - to connect to SCSI port driver.
                    365:     DeviceCount - Number of previously installed scanners.
                    366:     PortCapabilities - Pointer to structure returned by SCSI port
                    367:         driver describing adapter capabilites (and limitations).
                    368:     LunInfo - Pointer to configuration information for this device.
                    369: 
                    370: Return Value:
                    371: 
                    372:     NTSTATUS
                    373: 
                    374: --*/
                    375: {
                    376:     UCHAR ntNameBuffer[64];
                    377:     STRING ntNameString;
                    378:     UNICODE_STRING ntUnicodeString;
                    379:     UCHAR dosNameBuffer[64];
                    380:     STRING dosString;
                    381:     UNICODE_STRING dosUnicodeString;
                    382:     NTSTATUS status;
                    383:     PDEVICE_OBJECT deviceObject = NULL;
                    384:     PDEVICE_EXTENSION deviceExtension;
                    385:     PVOID senseData = NULL;
                    386: 
                    387:     //
                    388:     // Claim the device.
                    389:     //
                    390: 
                    391:     status = ScsiClassClaimDevice(PortDeviceObject,
                    392:                               LunInfo,
                    393:                               FALSE,
                    394:                               &PortDeviceObject);
                    395: 
                    396:     if (!NT_SUCCESS(status)) {
                    397:         return(status);
                    398:     }
                    399: 
                    400:     //
                    401:     // Create device object for this device.
                    402:     //
                    403: 
                    404:     sprintf(ntNameBuffer,
                    405:             "\\Device\\Scanner%d",
                    406:             *DeviceCount);
                    407: 
                    408:     RtlInitString(&ntNameString,
                    409:                   ntNameBuffer);
                    410: 
                    411:     DebugPrint((2,"CreateScannerDeviceObjects: Create device object %s\n",
                    412:                 ntNameBuffer));
                    413: 
                    414:     //
                    415:     // Convert ANSI string to Unicode.
                    416:     //
                    417: 
                    418:     status = RtlAnsiStringToUnicodeString(&ntUnicodeString,
                    419:                                           &ntNameString,
                    420:                                           TRUE);
                    421: 
                    422:     if (!NT_SUCCESS(status)) {
                    423: 
                    424:         DebugPrint((1,
                    425:                     "CreateDiskDeviceObjects: Cannot convert string %s\n",
                    426:                     ntNameBuffer));
                    427: 
                    428:         //
                    429:         // Release the device since an error occured.
                    430:         //
                    431: 
                    432:         ScsiClassClaimDevice(PortDeviceObject,
                    433:                          LunInfo,
                    434:                          TRUE,
                    435:                          NULL);
                    436: 
                    437:         return(status);
                    438:     }
                    439: 
                    440:     //
                    441:     // Create device object for this scanner.
                    442:     //
                    443: 
                    444:     status = IoCreateDevice(DriverObject,
                    445:                             DEVICE_EXTENSION_SIZE,
                    446:                             &ntUnicodeString,
                    447:                             FILE_DEVICE_SCANNER,
                    448:                             0,
                    449:                             FALSE,
                    450:                             &deviceObject);
                    451: 
                    452:     if (!NT_SUCCESS(status)) {
                    453:         DebugPrint((1,"CreateScannerDeviceObjects: Can not create device %s\n",
                    454:                     ntNameBuffer));
                    455: 
                    456:         RtlFreeUnicodeString(&ntUnicodeString);
                    457:         deviceObject = NULL;
                    458:         goto CreateScannerDeviceObjectExit;
                    459:     }
                    460: 
                    461:     //
                    462:     // Create the DosDevice name.
                    463:     //
                    464: 
                    465:     sprintf(dosNameBuffer,
                    466:             "\\DosDevices\\Scanner%d",
                    467:             *DeviceCount);
                    468: 
                    469:     RtlInitString(&dosString, dosNameBuffer);
                    470: 
                    471:     status = RtlAnsiStringToUnicodeString(&dosUnicodeString,
                    472:                                           &dosString,
                    473:                                           TRUE);
                    474: 
                    475:     if (!NT_SUCCESS(status)) {
                    476:         dosUnicodeString.Buffer = NULL;
                    477:     }
                    478: 
                    479:     if (dosUnicodeString.Buffer != NULL && ntUnicodeString.Buffer != NULL) {
                    480:         IoAssignArcName(&dosUnicodeString, &ntUnicodeString);
                    481:     }
                    482: 
                    483:     if (dosUnicodeString.Buffer != NULL) {
                    484:         RtlFreeUnicodeString(&dosUnicodeString);
                    485:     }
                    486: 
                    487:     RtlFreeUnicodeString(&ntUnicodeString);
                    488: 
                    489:     //
                    490:     // Indicate that IRPs should include MDLs.
                    491:     //
                    492: 
                    493:     deviceObject->Flags |= DO_DIRECT_IO;
                    494: 
                    495:     //
                    496:     // Set up required stack size in device object.
                    497:     //
                    498: 
                    499:     deviceObject->StackSize = PortDeviceObject->StackSize + 1;
                    500: 
                    501:     deviceExtension = deviceObject->DeviceExtension;
                    502: 
                    503:     //
                    504:     // Allocate spinlock for split request completion.
                    505:     //
                    506: 
                    507:     KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock);
                    508: 
                    509:     //
                    510:     // This is the physical device.
                    511:     //
                    512: 
                    513:     deviceExtension->PhysicalDevice = deviceObject;
                    514: 
                    515:     //
                    516:     // Copy port device object to device extension.
                    517:     //
                    518: 
                    519:     deviceExtension->PortDeviceObject = PortDeviceObject;
                    520: 
                    521:     //
                    522:     // Save address of port driver capabilities.
                    523:     //
                    524: 
                    525:     deviceExtension->PortCapabilities = PortCapabilities;
                    526: 
                    527:     //
                    528:     // Disable synchronous transfer for scanner requests.
                    529:     //
                    530: 
                    531:     deviceExtension->SrbFlags = SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
                    532: 
                    533:     //
                    534:     // Allocate request sense buffer.
                    535:     //
                    536: 
                    537:     senseData = ExAllocatePool(NonPagedPoolCacheAligned, SENSE_BUFFER_SIZE);
                    538: 
                    539:     if (senseData == NULL) {
                    540: 
                    541:         //
                    542:         // The buffer cannot be allocated.
                    543:         //
                    544: 
                    545:         status = STATUS_INSUFFICIENT_RESOURCES;
                    546:         goto CreateScannerDeviceObjectExit;
                    547:     }
                    548: 
                    549:     //
                    550:     // Set the sense data pointer in the device extension.
                    551:     //
                    552: 
                    553:     deviceExtension->SenseData = senseData;
                    554: 
                    555:     //
                    556:     // Scanners are not partitionable so starting offset is 0.
                    557:     //
                    558: 
                    559:     deviceExtension->StartingOffset.LowPart = 0;
                    560:     deviceExtension->StartingOffset.HighPart = 0;
                    561: 
                    562:     //
                    563:     // Path/TargetId/LUN describes a device location on the SCSI bus.
                    564:     // This information comes from the LunInfo buffer.
                    565:     //
                    566: 
                    567:     deviceExtension->PathId = LunInfo->PathId;
                    568:     deviceExtension->TargetId = LunInfo->TargetId;
                    569:     deviceExtension->Lun = LunInfo->Lun;
                    570: 
                    571:     //
                    572:     // Set timeout value in seconds.
                    573:     //
                    574: 
                    575:     deviceExtension->TimeOutValue = 60;
                    576: 
                    577:     //
                    578:     // Back pointer to device object.
                    579:     //
                    580: 
                    581:     deviceExtension->DeviceObject = deviceObject;
                    582: 
                    583:     //
                    584:     // Set routine address in device extension to be called
                    585:     // when a request completes with error.
                    586:     //
                    587: 
                    588:     deviceExtension->ClassError = ScsiScannerError;
                    589: 
                    590:     return(STATUS_SUCCESS);
                    591: 
                    592: CreateScannerDeviceObjectExit:
                    593: 
                    594:     //
                    595:     // Release the device since an error occured.
                    596:     //
                    597: 
                    598:     ScsiClassClaimDevice(PortDeviceObject,
                    599:                      LunInfo,
                    600:                      TRUE,
                    601:                      NULL);
                    602: 
                    603:     if (senseData != NULL) {
                    604:         ExFreePool(senseData);
                    605:     }
                    606: 
                    607:     if (deviceObject != NULL) {
                    608:         IoDeleteDevice(deviceObject);
                    609:     }
                    610: 
                    611:     return status;
                    612: 
                    613: } // end CreateScannerDeviceObject()
                    614: 
                    615: 
                    616: NTSTATUS
                    617: ScsiScannerOpen(
                    618:     IN PDEVICE_OBJECT DeviceObject,
                    619:     IN PIRP Irp
                    620:     )
                    621: 
                    622: /*++
                    623: 
                    624: Routine Description:
                    625: 
                    626:     This routine is called to establish a connection to the device
                    627:     class driver. It does no more than return STATUS_SUCCESS.
                    628: 
                    629: Arguments:
                    630: 
                    631:     DeviceObject - Device object for a device.
                    632:     Irp - Open request packet
                    633: 
                    634: Return Value:
                    635: 
                    636:     NT Status - STATUS_SUCCESS
                    637: 
                    638: --*/
                    639: 
                    640: {
                    641:     //
                    642:     // Set status in Irp.
                    643:     //
                    644: 
                    645:     Irp->IoStatus.Status = STATUS_SUCCESS;
                    646: 
                    647:     //
                    648:     // Complete request at raised IRQ.
                    649:     //
                    650: 
                    651:     IoCompleteRequest(Irp, IO_NO_INCREMENT);
                    652:     return STATUS_SUCCESS;
                    653: 
                    654: } // end ScsiScannerOpen()
                    655: 
                    656: 
                    657: NTSTATUS
                    658: ScsiScannerReadWrite(
                    659:     IN PDEVICE_OBJECT DeviceObject,
                    660:     IN PIRP Irp
                    661:     )
                    662: 
                    663: /*++
                    664: 
                    665: Routine Description:
                    666: 
                    667:     This is the entry called by the I/O system for scanner IO.
                    668: 
                    669: Arguments:
                    670: 
                    671:     DeviceObject - the system object for the device.
                    672:     Irp - IRP involved.
                    673: 
                    674: Return Value:
                    675: 
                    676:     NT Status
                    677: 
                    678: --*/
                    679: 
                    680: {
                    681:     PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
                    682:     PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
                    683:     ULONG transferByteCount = currentIrpStack->Parameters.Write.Length;
                    684:     LARGE_INTEGER startingOffset =
                    685:         currentIrpStack->Parameters.Write.ByteOffset;
                    686:     ULONG maximumTransferLength =
                    687:         deviceExtension->PortCapabilities->MaximumTransferLength;
                    688:     ULONG transferPages;
                    689: 
                    690:     DebugPrint((3,"ScsiScannerReadWrite: Enter routine\n"));
                    691: 
                    692:     //
                    693:     // Mark IRP with status pending.
                    694:     //
                    695: 
                    696:     IoMarkIrpPending(Irp);
                    697: 
                    698:     //
                    699:     // Check if request length is greater than the maximum number of
                    700:     // bytes that the hardware can transfer.
                    701:     //
                    702: 
                    703:     if (currentIrpStack->Parameters.Read.Length > maximumTransferLength) {
                    704: 
                    705:         DebugPrint((2,"ScsiScannerReadWrite: Request greater than maximum\n"));
                    706:         DebugPrint((2,"ScsiScannerReadWrite: Maximum is %lx\n",
                    707:                     maximumTransferLength));
                    708:         DebugPrint((2,"ScsiScannerReadWrite: Byte count is %lx\n",
                    709:                     currentIrpStack->Parameters.Write.Length));
                    710: 
                    711:         //
                    712:         // Request greater than port driver maximum.
                    713:         // Break up into smaller routines.
                    714:         //
                    715: 
                    716:         SplitRequest(DeviceObject, Irp, maximumTransferLength);
                    717: 
                    718:         return STATUS_PENDING;
                    719:     }
                    720: 
                    721:     //
                    722:     // Calculate number of pages in this transfer.
                    723:     //
                    724: 
                    725:     transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(
                    726:                         MmGetMdlVirtualAddress(Irp->MdlAddress),
                    727:                         currentIrpStack->Parameters.Write.Length);
                    728: 
                    729:     //
                    730:     // Check if number of pages is greater than adapter's maximum
                    731:     // number of physical breaks.
                    732:     //
                    733: 
                    734:     if (transferPages >
                    735:         deviceExtension->PortCapabilities->MaximumPhysicalPages) {
                    736: 
                    737:         DebugPrint((1,"ScsiScannerReadWrite: Request greater than maximum\n"));
                    738:         DebugPrint((1,"ScsiScannerReadWrite: Maximum pages is %lx\n",
                    739:                     deviceExtension->PortCapabilities->MaximumPhysicalPages));
                    740:         DebugPrint((1,"ScsiScannerReadWrite: Number of pages is %lx\n",
                    741:                     transferPages));
                    742: 
                    743:         //
                    744:         // Calculate maximum bytes to transfer that gaurantees
                    745:         // not exceeding the maximum number of page breaks,
                    746:         // assuming that the transfer may not be page alligned.
                    747:         //
                    748: 
                    749:         maximumTransferLength =
                    750:             (deviceExtension->PortCapabilities->MaximumPhysicalPages - 1) * PAGE_SIZE;
                    751: 
                    752:         //
                    753:         // Request greater than port driver maximum.
                    754:         // Break up into smaller routines.
                    755:         //
                    756: 
                    757:         SplitRequest(DeviceObject, Irp, maximumTransferLength);
                    758: 
                    759:         return STATUS_PENDING;
                    760:     }
                    761: 
                    762:     //
                    763:     // Build SRB and CDB for this IRP.
                    764:     //
                    765: 
                    766:     BuildScannerRequest(DeviceObject, Irp);
                    767: 
                    768:     //
                    769:     // Return the results of the call to the port driver.
                    770:     //
                    771: 
                    772:     return IoCallDriver(deviceExtension->PortDeviceObject, Irp);
                    773: 
                    774: } // end ScsiScannerReadWrite()
                    775: 
                    776: 
                    777: NTSTATUS
                    778: ScsiScannerDeviceControl(
                    779:     IN PDEVICE_OBJECT DeviceObject,
                    780:     IN PIRP Irp
                    781:     )
                    782: 
                    783: /*++
                    784: 
                    785: Routine Description:
                    786: 
                    787:     This is the NT device control handler for Scanners.
                    788: 
                    789: Arguments:
                    790: 
                    791:     DeviceObject - for this Scanner
                    792: 
                    793:     Irp - IO Request packet
                    794: 
                    795: Return Value:
                    796: 
                    797:     NTSTATUS
                    798: 
                    799: --*/
                    800: 
                    801: {
                    802:     PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
                    803:     PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
                    804:     SCSI_REQUEST_BLOCK srb;
                    805:     PCDB cdb = (PCDB)srb.Cdb;
                    806:     PVOID outputBuffer = Irp->AssociatedIrp.SystemBuffer;
                    807:     ULONG bytesTransferred = 0;
                    808:     NTSTATUS status;
                    809: 
                    810:     DebugPrint((3,"ScsiScannerDeviceControl: Enter routine\n"));
                    811: 
                    812:     //
                    813:     // Zero CDB in SRB on stack.
                    814:     //
                    815: 
                    816:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
                    817: 
                    818:     switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
                    819: 
                    820:         default:
                    821: 
                    822:             //
                    823:             // Pass the request to the common device control routine.
                    824:             //
                    825: 
                    826:             return(ScsiClassDeviceControl(DeviceObject, Irp));
                    827: 
                    828:             break;
                    829: 
                    830:     } // end switch()
                    831: 
                    832:     //
                    833:     // Update IRP with completion status.
                    834:     //
                    835: 
                    836:     Irp->IoStatus.Status = status;
                    837: 
                    838:     //
                    839:     // Complete the request.
                    840:     //
                    841: 
                    842:     IoCompleteRequest(Irp, IO_DISK_INCREMENT);
                    843:     DebugPrint((2, "ScsiScannerDeviceControl: Status is %lx\n", status));
                    844:     return status;
                    845: 
                    846: } // end ScsiScannerDeviceControl()
                    847: 
                    848: VOID
                    849: BuildScannerRequest(
                    850:         PDEVICE_OBJECT DeviceObject,
                    851:         PIRP Irp
                    852:         )
                    853: 
                    854: /*++
                    855: 
                    856: Routine Description:
                    857: 
                    858:     Build SRB and CDB requests to scsi device.
                    859: 
                    860: Arguments:
                    861: 
                    862:     DeviceObject - Device object representing this scanner device.
                    863:     Irp - System IO request packet.
                    864: 
                    865: Return Value:
                    866: 
                    867:     None.
                    868: 
                    869: --*/
                    870: 
                    871: {
                    872:     PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
                    873:     PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
                    874:     PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
                    875:     PSCSI_REQUEST_BLOCK srb;
                    876:     PCDB cdb;
                    877:     ULONG transferLength;
                    878: 
                    879:     //
                    880:     // Allocate an Srb.
                    881:     //
                    882: 
                    883:     if (deviceExtension->SrbZone != NULL &&
                    884:         (srb = ExInterlockedAllocateFromZone(
                    885:             deviceExtension->SrbZone,
                    886:             deviceExtension->SrbZoneSpinLock)) != NULL) {
                    887: 
                    888:         srb->SrbFlags = SRB_FLAGS_ALLOCATED_FROM_ZONE;
                    889: 
                    890:     } else {
                    891: 
                    892:         //
                    893:         // Allocate Srb from non-paged pool.
                    894:         // This call must succeed.
                    895:         //
                    896: 
                    897:         srb = ExAllocatePool(NonPagedPoolMustSucceed, SCSI_REQUEST_BLOCK_SIZE);
                    898: 
                    899:         srb->SrbFlags = 0;
                    900:     }
                    901: 
                    902:     //
                    903:     // Write length to SRB.
                    904:     //
                    905: 
                    906:     srb->Length = SCSI_REQUEST_BLOCK_SIZE;
                    907: 
                    908:     //
                    909:     // Set up IRP Address.
                    910:     //
                    911: 
                    912:     srb->OriginalRequest = Irp;
                    913: 
                    914:     //
                    915:     // Set up target id and logical unit number.
                    916:     //
                    917: 
                    918:     srb->PathId = deviceExtension->PathId;
                    919:     srb->TargetId = deviceExtension->TargetId;
                    920:     srb->Lun = deviceExtension->Lun;
                    921: 
                    922:     srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
                    923: 
                    924:     srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
                    925: 
                    926:     //
                    927:     // Save byte count of transfer in SRB Extension.
                    928:     //
                    929: 
                    930:     srb->DataTransferLength = currentIrpStack->Parameters.Write.Length;
                    931: 
                    932:     //
                    933:     // Initialize the queue actions field.
                    934:     //
                    935: 
                    936:     srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
                    937: 
                    938:     //
                    939:     // Queue sort key is not used.
                    940:     //
                    941: 
                    942:     srb->QueueSortKey = 0;
                    943: 
                    944:     //
                    945:     // Indicate auto request sense by specifying buffer and size.
                    946:     //
                    947: 
                    948:     srb->SenseInfoBuffer = deviceExtension->SenseData;
                    949: 
                    950:     srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
                    951: 
                    952:     //
                    953:     // Set timeout value in seconds.
                    954:     //
                    955: 
                    956:     srb->TimeOutValue = deviceExtension->TimeOutValue;
                    957: 
                    958:     //
                    959:     // Zero statuses.
                    960:     //
                    961: 
                    962:     srb->SrbStatus = srb->ScsiStatus = 0;
                    963: 
                    964:     srb->NextSrb = 0;
                    965: 
                    966:     //
                    967:     // Calculate number of blocks to transfer.
                    968:     //
                    969: 
                    970:     transferLength = currentIrpStack->Parameters.Write.Length;
                    971: 
                    972:     //
                    973:     // Get pointer to CDB in SRB.
                    974:     //
                    975: 
                    976:     cdb = (PCDB)srb->Cdb;
                    977: 
                    978:     //
                    979:     // Indicate that 6-byte CDB's will be used.
                    980:     //
                    981: 
                    982:     srb->CdbLength = 6;
                    983: 
                    984:     cdb->PRINT.LogicalUnitNumber = deviceExtension->Lun;
                    985: 
                    986:     //
                    987:     // Zero out reserved field.
                    988:     //
                    989: 
                    990:     cdb->PRINT.Reserved = 0;
                    991: 
                    992:     //
                    993:     // Move little endian values into CDB in big endian format.
                    994:     //
                    995: 
                    996:     cdb->PRINT.TransferLength[2] = ((PFOUR_BYTE)&transferLength)->Byte0;
                    997:     cdb->PRINT.TransferLength[1] = ((PFOUR_BYTE)&transferLength)->Byte1;
                    998:     cdb->PRINT.TransferLength[0] = ((PFOUR_BYTE)&transferLength)->Byte2;
                    999: 
                   1000:     cdb->PRINT.Control = 0;
                   1001: 
                   1002:     //
                   1003:     // Set transfer direction flag and Cdb command.
                   1004:     //
                   1005: 
                   1006:     if (currentIrpStack->MajorFunction == IRP_MJ_READ) {
                   1007: 
                   1008:         srb->SrbFlags |= SRB_FLAGS_DATA_IN;
                   1009:         cdb->CDB6READWRITE.OperationCode = SCSIOP_READ6;
                   1010: 
                   1011:     } else {
                   1012: 
                   1013:         srb->SrbFlags |= SRB_FLAGS_DATA_OUT;
                   1014:         cdb->CDB6READWRITE.OperationCode = SCSIOP_WRITE6;
                   1015:     }
                   1016: 
                   1017:     //
                   1018:     // Or in the default flags from the device object.
                   1019:     //
                   1020: 
                   1021:     srb->SrbFlags |= deviceExtension->SrbFlags;
                   1022: 
                   1023:     //
                   1024:     // Set up major SCSI function.
                   1025:     //
                   1026: 
                   1027:     nextIrpStack->MajorFunction = IRP_MJ_SCSI;
                   1028: 
                   1029:     //
                   1030:     // Save SRB address in next stack for port driver.
                   1031:     //
                   1032: 
                   1033:     nextIrpStack->Parameters.Scsi.Srb = srb;
                   1034: 
                   1035:     //
                   1036:     // Save retry count in current IRP stack.
                   1037:     //
                   1038: 
                   1039:     currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
                   1040: 
                   1041:     //
                   1042:     // Set up IoCompletion routine address.
                   1043:     //
                   1044: 
                   1045:     IoSetCompletionRoutine(Irp, ScsiClassIoComplete, srb, TRUE, TRUE, FALSE);
                   1046: 
                   1047:     return;
                   1048: 
                   1049: } // end BuildScannerRequest()
                   1050: 
                   1051: VOID
                   1052: 
                   1053: ScsiScannerError(
                   1054:     PDEVICE_OBJECT DeviceObject,
                   1055:     IN PSCSI_REQUEST_BLOCK Srb,
                   1056:     IN OUT NTSTATUS *Status,
                   1057:     IN OUT BOOLEAN *Retry
                   1058:     )
                   1059: 
                   1060: /*++
                   1061: 
                   1062: Routine Description:
                   1063: 
                   1064:     Build SRB and CDB requests to scsi device.
                   1065: 
                   1066: Arguments:
                   1067: 
                   1068:     DeviceObject - Device object representing this scanner device.
                   1069:     Srb - Scsi request block.
                   1070: 
                   1071: Return Value:
                   1072: 
                   1073:     None.
                   1074: 
                   1075: --*/
                   1076: 
                   1077: {
                   1078:     PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
                   1079: 
                   1080:     //
                   1081:     // Check if status is underrun. STATUS_DATA_OVERRUN is an indication of
                   1082:     // either data underrun or overrun.
                   1083:     //
                   1084: 
                   1085:     if (*Status == STATUS_DATA_OVERRUN) {
                   1086:         *Status = STATUS_SUCCESS;
                   1087:     }
                   1088: 
                   1089:     return;
                   1090: 
                   1091: } // end ScsiScannerError()
                   1092: 
                   1093: 
                   1094: VOID
                   1095: SplitRequest(
                   1096:     IN PDEVICE_OBJECT DeviceObject,
                   1097:     IN PIRP Irp,
                   1098:     IN ULONG MaximumBytes
                   1099:     )
                   1100: 
                   1101: /*++
                   1102: 
                   1103: Routine Description:
                   1104: 
                   1105:     Break request into smaller requests.  Each new request will be the
                   1106:     maximum transfer size that the port driver can handle or if it
                   1107:     is the final request, it may be the residual size.
                   1108: 
                   1109:     The number of IRPs required to process this request is written in the
                   1110:     current stack of the original IRP. Then as each new IRP completes
                   1111:     the count in the original IRP is decremented. When the count goes to
                   1112:     zero, the original IRP is completed.
                   1113: 
                   1114: Arguments:
                   1115: 
                   1116:     DeviceObject - Pointer to the class device object to be addressed.
                   1117: 
                   1118:     Irp - Pointer to Irp the orginal request.
                   1119: 
                   1120: Return Value:
                   1121: 
                   1122:     None.
                   1123: 
                   1124: --*/
                   1125: 
                   1126: {
                   1127:     PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
                   1128:     PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
                   1129:     PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
                   1130:     ULONG transferByteCount = currentIrpStack->Parameters.Read.Length;
                   1131:     LARGE_INTEGER startingOffset = currentIrpStack->Parameters.Read.ByteOffset;
                   1132:     PVOID dataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
                   1133:     ULONG dataLength = MaximumBytes;
                   1134:     ULONG irpCount = (transferByteCount + MaximumBytes - 1) / MaximumBytes;
                   1135:     PSCSI_REQUEST_BLOCK srb;
                   1136:     ULONG i;
                   1137: 
                   1138:     DebugPrint((1, "SplitRequest: Requires %d IRPs\n", irpCount));
                   1139:     DebugPrint((1, "SplitRequest: Original IRP %lx\n", Irp));
                   1140: 
                   1141:     //
                   1142:     // If all partial transfers complete successfully then the status and
                   1143:     // bytes transferred are already set up. Failing a partial-transfer IRP
                   1144:     // will set status to error and bytes transferred to 0 during
                   1145:     // IoCompletion. Setting bytes transferred to 0 if an IRP fails allows
                   1146:     // asynchronous partial transfers. This is an optimization for the
                   1147:     // successful case.
                   1148:     //
                   1149: 
                   1150:     Irp->IoStatus.Status = STATUS_SUCCESS;
                   1151:     Irp->IoStatus.Information = transferByteCount;
                   1152: 
                   1153:     //
                   1154:     // Save number of IRPs to complete count on current stack
                   1155:     // of original IRP.
                   1156:     //
                   1157: 
                   1158:     nextIrpStack->Parameters.Others.Argument1 = (PVOID) irpCount;
                   1159: 
                   1160:     for (i = 0; i < irpCount; i++) {
                   1161: 
                   1162:         PIRP newIrp;
                   1163:         PIO_STACK_LOCATION newIrpStack;
                   1164: 
                   1165:         //
                   1166:         // Allocate new IRP.
                   1167:         //
                   1168: 
                   1169:         newIrp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
                   1170: 
                   1171:         if (newIrp == NULL) {
                   1172: 
                   1173:             DebugPrint((1,"SplitRequest: Can't allocate Irp\n"));
                   1174: 
                   1175:             //
                   1176:             // If an Irp can't be allocated then the orginal request cannot
                   1177:             // be executed.  If this is the first request then just fail the
                   1178:             // orginal request; otherwise just return.  When the pending
                   1179:             // requests complete, they will complete the original request.
                   1180:             // In either case set the IRP status to failure.
                   1181:             //
                   1182: 
                   1183:             Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
                   1184:             Irp->IoStatus.Information = 0;
                   1185: 
                   1186:             if (i == 0) {
                   1187:                 IoCompleteRequest(Irp, IO_NO_INCREMENT);
                   1188:             }
                   1189: 
                   1190:             return;
                   1191:         }
                   1192: 
                   1193:         DebugPrint((2, "SplitRequest: New IRP %lx\n", newIrp));
                   1194: 
                   1195:         //
                   1196:         // Write MDL address to new IRP. In the port driver the SRB data
                   1197:         // buffer field is used as an offset into the MDL, so the same MDL
                   1198:         // can be used for each partial transfer. This saves having to build
                   1199:         // a new MDL for each partial transfer.
                   1200:         //
                   1201: 
                   1202:         newIrp->MdlAddress = Irp->MdlAddress;
                   1203: 
                   1204:         //
                   1205:         // At this point there is no current stack. IoSetNextIrpStackLocation
                   1206:         // will make the first stack location the current stack so that the
                   1207:         // SRB address can be written there.
                   1208:         //
                   1209: 
                   1210:         IoSetNextIrpStackLocation(newIrp);
                   1211:         newIrpStack = IoGetCurrentIrpStackLocation(newIrp);
                   1212: 
                   1213:         newIrpStack->MajorFunction = currentIrpStack->MajorFunction;
                   1214:         newIrpStack->Parameters.Read.Length = dataLength;
                   1215:         newIrpStack->Parameters.Read.ByteOffset = startingOffset;
                   1216:         newIrpStack->DeviceObject = DeviceObject;
                   1217: 
                   1218:         //
                   1219:         // Build SRB and CDB.
                   1220:         //
                   1221: 
                   1222:         BuildScannerRequest(DeviceObject, newIrp);
                   1223: 
                   1224:         //
                   1225:         // Adjust SRB for this partial transfer.
                   1226:         //
                   1227: 
                   1228:         newIrpStack = IoGetNextIrpStackLocation(newIrp);
                   1229: 
                   1230:         srb = newIrpStack->Parameters.Others.Argument1;
                   1231:         srb->DataBuffer = dataBuffer;
                   1232: 
                   1233:         //
                   1234:         // Write original IRP address to new IRP.
                   1235:         //
                   1236: 
                   1237:         newIrp->AssociatedIrp.MasterIrp = Irp;
                   1238: 
                   1239:         //
                   1240:         // Set the completion routine to ScsiClassIoCompleteAssociated.
                   1241:         //
                   1242: 
                   1243:         IoSetCompletionRoutine(newIrp,
                   1244:                                ScsiClassIoCompleteAssociated,
                   1245:                                srb,
                   1246:                                TRUE,
                   1247:                                TRUE,
                   1248:                                TRUE);
                   1249: 
                   1250:         //
                   1251:         // Call port driver with new request.
                   1252:         //
                   1253: 
                   1254:         IoCallDriver(deviceExtension->PortDeviceObject, newIrp);
                   1255: 
                   1256:         //
                   1257:         // Set up for next request.
                   1258:         //
                   1259: 
                   1260:         dataBuffer = (PCHAR)dataBuffer + MaximumBytes;
                   1261: 
                   1262:         transferByteCount -= MaximumBytes;
                   1263: 
                   1264:         if (transferByteCount > MaximumBytes) {
                   1265: 
                   1266:             dataLength = MaximumBytes;
                   1267: 
                   1268:         } else {
                   1269: 
                   1270:             dataLength = transferByteCount;
                   1271:         }
                   1272: 
                   1273:         //
                   1274:         // Adjust disk byte offset.
                   1275:         //
                   1276: 
                   1277:         startingOffset = LiAdd(startingOffset, LiFromUlong(MaximumBytes));
                   1278:     }
                   1279: 
                   1280:     return;
                   1281: 
                   1282: } // end SplitRequest()
                   1283: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.