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

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

unix.superglobalmegacorp.com

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