Annotation of ntddk/src/scsi/scsitape/class/tape.c, revision 1.1.1.1

1.1       root        1: /*++
                      2: 
                      3: Copyright (c) 1991  Microsoft Corporation
                      4: 
                      5: Module Name:
                      6: 
                      7:     tape.c
                      8: 
                      9: Abstract:
                     10: 
                     11:     This is the tape class driver.
                     12: 
                     13: Authors:
                     14: 
                     15:     Mike Glass
                     16:     Hunter Small
                     17: 
                     18: Environment:
                     19: 
                     20:     kernel mode only
                     21: 
                     22: Revision History:
                     23: 
                     24: --*/
                     25: 
                     26: #include "ntddk.h"
                     27: #include "tape.h"
                     28: 
                     29: //
                     30: // The following prototypes are the internal tape class routines.
                     31: //
                     32: 
                     33: NTSTATUS
                     34: DriverEntry(
                     35:   IN PDRIVER_OBJECT DriverObject,
                     36:   IN PUNICODE_STRING RegistryPath
                     37:   );
                     38: 
                     39: VOID
                     40: UpdateTapeInformationInRegistry(
                     41:   IN PDEVICE_OBJECT     DeviceObject,
                     42:   IN PSCSI_INQUIRY_DATA ScsiInquiryData,
                     43:   IN ULONG              PortNumber,
                     44:   IN ULONG              TapeNumber
                     45:   );
                     46: 
                     47: NTSTATUS
                     48: CreateTapeDeviceObject(
                     49:   IN PDRIVER_OBJECT           DriverObject,
                     50:   IN PULONG                   DeviceCount,
                     51:   IN PIO_SCSI_CAPABILITIES    PortCapabilities,
                     52:   IN PSCSI_INQUIRY_DATA       LunInfo,
                     53:   IN PDEVICE_OBJECT           PortDeviceObject,
                     54:   IN ULONG                    PortNumber
                     55:   );
                     56: 
                     57: BOOLEAN
                     58: FindScsiTapes(
                     59:   IN PDRIVER_OBJECT DriverObject,
                     60:   IN PDEVICE_OBJECT PortDeviceObject,
                     61:   IN ULONG PortNumber
                     62:   );
                     63: 
                     64: VOID
                     65: SplitTapeRequest(
                     66:     IN PDEVICE_OBJECT DeviceObject,
                     67:     IN PIRP Irp,
                     68:     IN ULONG MaximumBytes
                     69:     );
                     70: 
                     71: VOID
                     72: ScsiTapeError(
                     73:     PDEVICE_OBJECT DeviceObject,
                     74:     PSCSI_REQUEST_BLOCK Srb,
                     75:     NTSTATUS *Status,
                     76:     BOOLEAN *Retry
                     77:     );
                     78: 
                     79: NTSTATUS
                     80: ScsiTapeIoCompleteAssociated(
                     81:     IN PDEVICE_OBJECT DeviceObject,
                     82:     IN PIRP Irp,
                     83:     IN PVOID Context
                     84:     );
                     85: 
                     86: #ifdef ALLOC_PRAGMA
                     87: #pragma alloc_text(init, DriverEntry)
                     88: #pragma alloc_text(init, FindScsiTapes)
                     89: #pragma alloc_text(init, CreateTapeDeviceObject)
                     90: #pragma alloc_text(init, UpdateTapeInformationInRegistry)
                     91: #endif
                     92: 
                     93: //
                     94: // Start of code
                     95: //
                     96: 
                     97: 
                     98: NTSTATUS
                     99: DriverEntry(
                    100:   IN PDRIVER_OBJECT DriverObject,
                    101:   IN PUNICODE_STRING RegistryPath
                    102:   )
                    103: 
                    104: /*++
                    105: 
                    106: Routine Description:
                    107: 
                    108:     This is the system initialization entry point for installable drivers.
                    109: 
                    110: Arguments:
                    111: 
                    112:     DriverObject
                    113: 
                    114: Return Value:
                    115: 
                    116:     NT Status
                    117: 
                    118: --*/
                    119: 
                    120: {
                    121:      ULONG          portNumber = 0;
                    122:      PDEVICE_OBJECT portDeviceObject;
                    123:      NTSTATUS       status;
                    124:      STRING         deviceNameString;
                    125:      UNICODE_STRING unicodeDeviceName;
                    126:      PFILE_OBJECT   fileObject;
                    127:      CCHAR          deviceNameBuffer[256];
                    128:      BOOLEAN        tapeDeviceFound = FALSE;
                    129: 
                    130:      DebugPrint((1,"\n\nSCSI Tape Class Driver\n"));
                    131: 
                    132:      //
                    133:      // Update driver object with entry points.
                    134:      //
                    135: 
                    136:      DriverObject->MajorFunction[IRP_MJ_READ]  = ScsiTapeReadWrite;
                    137:      DriverObject->MajorFunction[IRP_MJ_WRITE] = ScsiTapeReadWrite;
                    138:      DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ScsiTapeDeviceControl;
                    139:      DriverObject->MajorFunction[IRP_MJ_CREATE] = ScsiTapeCreate;
                    140: 
                    141:      //
                    142:      // Open port driver controller device objects by name.
                    143:      //
                    144: 
                    145:      do {
                    146: 
                    147:           sprintf(deviceNameBuffer, "\\Device\\ScsiPort%d", portNumber);
                    148: 
                    149:           DebugPrint((2, "ScsiTapeInitialize: Open Port %s\n", deviceNameBuffer));
                    150: 
                    151:           RtlInitString(&deviceNameString, deviceNameBuffer);
                    152: 
                    153:           status = RtlAnsiStringToUnicodeString(&unicodeDeviceName,
                    154:                                                 &deviceNameString,
                    155:                                                 TRUE
                    156:                                                 );
                    157: 
                    158:           ASSERT(NT_SUCCESS(status));
                    159: 
                    160: 
                    161:           status = IoGetDeviceObjectPointer(&unicodeDeviceName,
                    162:                                             FILE_READ_ATTRIBUTES,
                    163:                                             &fileObject,
                    164:                                             &portDeviceObject);
                    165: 
                    166:           if (NT_SUCCESS(status)) {
                    167: 
                    168:                if (FindScsiTapes(DriverObject, portDeviceObject, portNumber)) {
                    169:                     tapeDeviceFound = TRUE;
                    170:                }
                    171:           }
                    172: 
                    173:           //
                    174:           // Check next SCSI adapter.
                    175:           //
                    176: 
                    177:           portNumber++;
                    178: 
                    179:      } while(NT_SUCCESS(status));
                    180: 
                    181:      return(tapeDeviceFound ? STATUS_SUCCESS: STATUS_NO_SUCH_DEVICE);
                    182: 
                    183: } // end DriverEntry()
                    184: 
                    185: 
                    186: BOOLEAN
                    187: FindScsiTapes(
                    188:     IN PDRIVER_OBJECT DriverObject,
                    189:     IN PDEVICE_OBJECT PortDeviceObject,
                    190:     IN ULONG PortNumber
                    191:     )
                    192: 
                    193: /*++
                    194: 
                    195: Routine Description:
                    196: 
                    197:     Call into port driver to get configuration information to find
                    198:     tape devices.
                    199: 
                    200: Arguments:
                    201: 
                    202:     DriverObject
                    203:     DeviceObject - Port driver device object.
                    204: 
                    205: Return Value:
                    206: 
                    207:     TRUE if tape device(s) found.
                    208: 
                    209: --*/
                    210: 
                    211: {
                    212:     PIO_SCSI_CAPABILITIES       portCapabilities;
                    213:     PULONG                      tapeCount;
                    214:     PCHAR                       buffer;
                    215:     PSCSI_INQUIRY_DATA          lunInfo;
                    216:     PSCSI_ADAPTER_BUS_INFO      adapterInfo;
                    217:     PINQUIRYDATA                inquiryData;
                    218:     PCONFIGURATION_INFORMATION  configInfo;
                    219:     NTSTATUS                    status;
                    220:     ULONG                       scsiBus;
                    221:     BOOLEAN                     tapeDeviceFound = FALSE;
                    222: 
                    223:     //
                    224:     // Call port driver to get adapter capabilities.
                    225:     //
                    226: 
                    227:     status = ScsiClassGetCapabilities(PortDeviceObject, &portCapabilities);
                    228: 
                    229:     if (!NT_SUCCESS(status)) {
                    230:          DebugPrint((1, "FindScsiTapes: ScsiClassGetCabilities failed\n"));
                    231: 
                    232:     }
                    233: 
                    234:     //
                    235:     // Call port driver to get inquiry information to find disks.
                    236:     //
                    237: 
                    238:     status = ScsiClassGetInquiryData(PortDeviceObject, (PSCSI_ADAPTER_BUS_INFO *) &buffer);
                    239: 
                    240:     if (!NT_SUCCESS(status)) {
                    241:         DebugPrint((1,"FindScsiDevices: ScsiClassGetInquiryData failed\n"));
                    242:         return FALSE;
                    243:     }
                    244: 
                    245:     configInfo = IoGetConfigurationInformation();
                    246: 
                    247:     tapeCount  = &configInfo->TapeCount;
                    248: 
                    249:     adapterInfo = (PVOID) buffer;
                    250: 
                    251:     //
                    252:     // For each SCSI bus this adapter supports ...
                    253:     //
                    254: 
                    255:     for (scsiBus=0; scsiBus < (ULONG)adapterInfo->NumberOfBuses; scsiBus++) {
                    256: 
                    257:         //
                    258:         // Get the SCSI bus scan data for this bus.
                    259:         //
                    260: 
                    261:         lunInfo = (PVOID) (buffer + adapterInfo->BusData[scsiBus].InquiryDataOffset);
                    262: 
                    263:         //
                    264:         // Search list for unclaimed disk devices.
                    265:         //
                    266: 
                    267:         while (adapterInfo->BusData[scsiBus].InquiryDataOffset) {
                    268: 
                    269:             inquiryData = (PVOID)lunInfo->InquiryData;
                    270: 
                    271:             DebugPrint((3,
                    272:               "FindScsiTapes: Inquiry data at %lx\n",
                    273:               inquiryData));
                    274: 
                    275:             if ((inquiryData->DeviceType == SEQUENTIAL_ACCESS_DEVICE) &&
                    276:               (!lunInfo->DeviceClaimed)) {
                    277: 
                    278:                  if (TapeVerifyInquiry(lunInfo) == TRUE) {
                    279: 
                    280:                       status = CreateTapeDeviceObject(DriverObject,
                    281:                                                       tapeCount,
                    282:                                                       portCapabilities,
                    283:                                                       lunInfo,
                    284:                                                       PortDeviceObject,
                    285:                                                       PortNumber);
                    286: 
                    287:                       if (NT_SUCCESS(status)) {
                    288: 
                    289:                            tapeDeviceFound = TRUE;
                    290: 
                    291:                            //
                    292:                            // Increment tape count
                    293:                            //
                    294: 
                    295:                            (*tapeCount)++;
                    296: 
                    297:                       }
                    298:                  }
                    299:             }
                    300: 
                    301:             //
                    302:             // Get next LunInfo.
                    303:             //
                    304: 
                    305:             if (lunInfo->NextInquiryDataOffset == 0) {
                    306:                 break;
                    307:             }
                    308: 
                    309:             lunInfo = (PVOID) (buffer + lunInfo->NextInquiryDataOffset);
                    310: 
                    311:          }
                    312:     }
                    313: 
                    314:     ExFreePool(buffer);
                    315:     return tapeDeviceFound;
                    316: 
                    317: } // end FindScsiTapes()
                    318: 
                    319: 
                    320: VOID
                    321: UpdateTapeInformationInRegistry(
                    322:   IN PDEVICE_OBJECT     DeviceObject,
                    323:   IN PSCSI_INQUIRY_DATA ScsiInquiryData,
                    324:   IN ULONG              PortNumber,
                    325:   IN ULONG              TapeNumber
                    326:   )
                    327: 
                    328: /*++
                    329: 
                    330: Routine Description:
                    331: 
                    332:     This routine has knowledge about the layout of the device map information
                    333:     in the registry.  It will update this information to include a value
                    334:     entry specifying the dos device name that is assumed to get assigned
                    335:     to this NT device name.  For more information on this assigning of the
                    336:     dos device name look in the drive support routine in the hal that assigns
                    337:     all dos names.  Since most version of tape firmware do not work and most
                    338:     vendor did not bother to follow the specification the entire inquiry
                    339:     information must also be stored in the registry so than someone can
                    340:     figure out the firmware version.
                    341: 
                    342: Arguments:
                    343: 
                    344:     DeviceObject - A pointer to the device object for the tape device.
                    345: 
                    346:     ScsiInquiryData - a pointer to the scsi inquiry data structure defined in
                    347:                       ntddscsi.h
                    348: 
                    349: Return Value:
                    350: 
                    351:     None
                    352: 
                    353: --*/
                    354: 
                    355: {
                    356:     PDEVICE_EXTENSION   deviceExtension = DeviceObject->DeviceExtension;
                    357:     NTSTATUS          status;
                    358:     OBJECT_ATTRIBUTES objectAttributes;
                    359:     PUCHAR            buffer;
                    360:     STRING            string;
                    361:     UNICODE_STRING    unicodeName;
                    362:     UNICODE_STRING    unicodeData;
                    363:     HANDLE            targetKey;
                    364:     PINQUIRYDATA      dataBuffer;
                    365:     SCSI_REQUEST_BLOCK srb;
                    366:     ULONG             length;
                    367:     PCDB              cdb;
                    368: 
                    369:     buffer = ExAllocatePool(NonPagedPool, 1024);
                    370:     dataBuffer = ExAllocatePool(NonPagedPoolCacheAligned, MAXIMUM_TAPE_INQUIRY_DATA);
                    371:     if (buffer == NULL || dataBuffer == NULL) {
                    372: 
                    373:         if (buffer != NULL) {
                    374:             ExFreePool(buffer);
                    375:         }
                    376: 
                    377:         //
                    378:         // There is not return value for this.  Since this is done at
                    379:         // claim device time (currently only system initialization) getting
                    380:         // the registry information correct will be the least of the worries.
                    381:         //
                    382: 
                    383:         return;
                    384:     }
                    385:     sprintf(buffer,
                    386:             "\\Registry\\Machine\\Hardware\\DeviceMap\\Scsi\\Scsi Port %d\\Scsi Bus %d\\Target Id %d\\Logical Unit Id %d",
                    387:             PortNumber,
                    388:             ScsiInquiryData->PathId,
                    389:             ScsiInquiryData->TargetId,
                    390:             ScsiInquiryData->Lun);
                    391: 
                    392:     RtlInitString(&string, buffer);
                    393:     status = RtlAnsiStringToUnicodeString(&unicodeName,
                    394:                                           &string,
                    395:                                           TRUE);
                    396:     if (NT_SUCCESS(status)) {
                    397: 
                    398:         //
                    399:         // Open the registry key for the scsi information for this
                    400:         // scsibus, target, lun.
                    401:         //
                    402: 
                    403:         InitializeObjectAttributes(&objectAttributes,
                    404:                                    &unicodeName,
                    405:                                    OBJ_CASE_INSENSITIVE,
                    406:                                    NULL,
                    407:                                    NULL);
                    408:         status = ZwOpenKey(&targetKey,
                    409:                            KEY_READ | KEY_WRITE,
                    410:                            &objectAttributes);
                    411:         RtlFreeUnicodeString(&unicodeName);
                    412: 
                    413:         if (NT_SUCCESS(status)) {
                    414: 
                    415:             //
                    416:             // Now construct and attempt to create the registry value
                    417:             // specifying the device name in the appropriate place in the
                    418:             // device map.
                    419:             //
                    420: 
                    421:             RtlInitUnicodeString(&unicodeName, L"DeviceName");
                    422: 
                    423:             sprintf(buffer, "Tape%d", TapeNumber);
                    424:             RtlInitString(&string, buffer);
                    425:             RtlAnsiStringToUnicodeString(&unicodeData,
                    426:                                          &string,
                    427:                                          TRUE);
                    428:             if (NT_SUCCESS(status)) {
                    429:                 status = ZwSetValueKey(targetKey,
                    430:                                        &unicodeName,
                    431:                                        0,
                    432:                                        REG_SZ,
                    433:                                        unicodeData.Buffer,
                    434:                                        unicodeData.Length);
                    435:                 RtlFreeUnicodeString(&unicodeData);
                    436:             }
                    437: 
                    438:             //
                    439:             // Now get the full inquiry information for the device.
                    440:             //
                    441: 
                    442:             RtlZeroMemory(&srb, SCSI_REQUEST_BLOCK_SIZE);
                    443: 
                    444:             //
                    445:             // Set timeout value.
                    446:             //
                    447: 
                    448:             srb.TimeOutValue = 2;
                    449: 
                    450:             srb.CdbLength = 6;
                    451: 
                    452:             cdb = (PCDB)srb.Cdb;
                    453: 
                    454:             //
                    455:             // Set CDB operation code.
                    456:             //
                    457: 
                    458:             cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
                    459: 
                    460:             //
                    461:             // Set CDB LUN.
                    462:             //
                    463: 
                    464:             cdb->CDB6INQUIRY.LogicalUnitNumber = deviceExtension->Lun;
                    465: 
                    466:             //
                    467:             // Set allocation length to inquiry data buffer size.
                    468:             //
                    469: 
                    470:             cdb->CDB6INQUIRY.AllocationLength = MAXIMUM_TAPE_INQUIRY_DATA;
                    471: 
                    472:             status = ScsiClassSendSrbSynchronous(DeviceObject,
                    473:                                                  &srb,
                    474:                                                  dataBuffer,
                    475:                                                  MAXIMUM_TAPE_INQUIRY_DATA,
                    476:                                                  FALSE);
                    477: 
                    478:             if (SRB_STATUS(srb.SrbStatus) == SRB_STATUS_SUCCESS ||
                    479:                 SRB_STATUS(srb.SrbStatus) == SRB_STATUS_DATA_OVERRUN) {
                    480: 
                    481:                 //
                    482:                 // Updated the length actually transfered.
                    483:                 //
                    484: 
                    485:                 length = dataBuffer->AdditionalLength +
                    486:                     FIELD_OFFSET(INQUIRYDATA, Reserved);
                    487: 
                    488:                 if (length > srb.DataTransferLength) {
                    489:                     length = srb.DataTransferLength;
                    490:                 }
                    491: 
                    492:                 RtlInitUnicodeString(&unicodeName, L"InquiryData");
                    493: 
                    494:                 status = ZwSetValueKey(targetKey,
                    495:                                        &unicodeName,
                    496:                                        0,
                    497:                                        REG_BINARY,
                    498:                                        dataBuffer,
                    499:                                        length);
                    500: 
                    501:             }
                    502: 
                    503:             ZwClose(targetKey);
                    504:         }
                    505:     }
                    506: 
                    507:     ExFreePool(buffer);
                    508:     ExFreePool(dataBuffer);
                    509: }
                    510: 
                    511: 
                    512: NTSTATUS
                    513: CreateTapeDeviceObject(
                    514:   IN PDRIVER_OBJECT           DriverObject,
                    515:   IN PULONG                   DeviceCount,
                    516:   IN PIO_SCSI_CAPABILITIES    PortCapabilities,
                    517:   IN PSCSI_INQUIRY_DATA       LunInfo,
                    518:   IN PDEVICE_OBJECT           PortDeviceObject,
                    519:   IN ULONG                    PortNumber
                    520:   )
                    521: 
                    522: /*++
                    523: 
                    524: Routine Description:
                    525: 
                    526:     This routine creates an object for the device and then searches
                    527:     the device for partitions and creates an object for each partition.
                    528: 
                    529: Arguments:
                    530: 
                    531:     DriverObject - Pointer to driver object created by system.
                    532:     DeviceCount - Pointer to number of previously installed tapes.
                    533:     PortCapabilities - Pointer to port capabilities structure
                    534:     LunInfo - Pointer to Logical Unit Information structure.
                    535:     PortDeviceObject - Pointer to device object of SCSI adapter.
                    536:     PortNumber - Number of the SCSI port.
                    537: 
                    538: Return Value:
                    539: 
                    540:     NTSTATUS
                    541: 
                    542: --*/
                    543: 
                    544: {
                    545:      CCHAR               deviceNameBuffer[64];
                    546:      CCHAR               dosNameBuffer[64];
                    547:      STRING              deviceNameString;
                    548:      UNICODE_STRING      unicodeString;
                    549:      NTSTATUS            status;
                    550:      PDEVICE_OBJECT      deviceObject;
                    551:      ULONG               requiredStackSize;
                    552:      PDEVICE_EXTENSION   deviceExtension;
                    553:      PTAPE_DATA          tapeData;
                    554:      UCHAR               pathId = LunInfo->PathId;
                    555:      UCHAR               targetId = LunInfo->TargetId;
                    556:      UCHAR               lun = LunInfo->Lun;
                    557:      PVOID               senseData;
                    558:      STRING              dosString;
                    559:      UNICODE_STRING      dosUnicodeString;
                    560: 
                    561:      DebugPrint((3,"CreateDeviceObject: Enter routine\n"));
                    562: 
                    563:      //
                    564:      // Create device object for this device.
                    565:      //
                    566: 
                    567:      sprintf(deviceNameBuffer,
                    568:              "\\Device\\Tape%d",
                    569:              *DeviceCount);
                    570: 
                    571:      RtlInitString(&deviceNameString,
                    572:                    deviceNameBuffer);
                    573: 
                    574:      DebugPrint((2,"CreateDeviceObjects: Create device object %s\n",
                    575:                  deviceNameBuffer));
                    576: 
                    577:      status = RtlAnsiStringToUnicodeString(&unicodeString,
                    578:                                            &deviceNameString,
                    579:                                            TRUE);
                    580: 
                    581:      ASSERT(NT_SUCCESS(status));
                    582: 
                    583:      status = IoCreateDevice(DriverObject,
                    584:                              DEVICE_EXTENSION_SIZE,
                    585:                              &unicodeString,
                    586:                              FILE_DEVICE_TAPE,
                    587:                              FILE_REMOVABLE_MEDIA,
                    588:                              FALSE,
                    589:                              &deviceObject);
                    590: 
                    591:      if (!NT_SUCCESS(status)) {
                    592:           DebugPrint((1,"CreateDeviceObjects: Can not create device %s\n",
                    593:                       deviceNameBuffer));
                    594: 
                    595:           return status;
                    596:      }
                    597: 
                    598:      //
                    599:      // Claim the device.
                    600:      //
                    601: 
                    602:      status = ScsiClassClaimDevice(
                    603:          PortDeviceObject,
                    604:          LunInfo,
                    605:          FALSE,
                    606:          &PortDeviceObject
                    607:          );
                    608: 
                    609:      if (!NT_SUCCESS(status)) {
                    610:          IoDeleteDevice(deviceObject);
                    611:          return(status);
                    612:      }
                    613: 
                    614:      //
                    615:      // Create the dos port driver name.
                    616:      //
                    617: 
                    618:      sprintf(dosNameBuffer,
                    619:              "\\DosDevices\\TAPE%d",
                    620:              *DeviceCount);
                    621: 
                    622:      RtlInitString(&dosString, dosNameBuffer);
                    623: 
                    624:      status = RtlAnsiStringToUnicodeString(&dosUnicodeString,
                    625:                                            &dosString,
                    626:                                            TRUE);
                    627: 
                    628:      if(!NT_SUCCESS(status)) {
                    629:          dosUnicodeString.Buffer = NULL;
                    630:      }
                    631: 
                    632:      if (dosUnicodeString.Buffer != NULL && unicodeString.Buffer != NULL) {
                    633:          IoAssignArcName(&dosUnicodeString, &unicodeString);
                    634:      }
                    635: 
                    636:      if (dosUnicodeString.Buffer != NULL) {
                    637:          RtlFreeUnicodeString(&dosUnicodeString);
                    638:      }
                    639: 
                    640:      if (unicodeString.Buffer != NULL ) {
                    641:          RtlFreeUnicodeString(&unicodeString);
                    642:      }
                    643: 
                    644:      //
                    645:      // Indicate that IRPs should include MDLs.
                    646:      //
                    647: 
                    648:      deviceObject->Flags |= DO_DIRECT_IO;
                    649: 
                    650:      //
                    651:      // Set up required stack size in device object.
                    652:      //
                    653: 
                    654:      deviceExtension = deviceObject->DeviceExtension;
                    655: 
                    656:      requiredStackSize = PortDeviceObject->StackSize + 1;
                    657: 
                    658:      deviceExtension->PortDeviceObject = PortDeviceObject;
                    659: 
                    660:      //
                    661:      // Allocate spinlock for split request completion.
                    662:      //
                    663: 
                    664:      KeInitializeSpinLock(&deviceExtension->SplitRequestSpinLock);
                    665: 
                    666:      deviceObject->StackSize = (CCHAR)requiredStackSize;
                    667: 
                    668:      //
                    669:      // Save address of port driver capabilities.
                    670:      //
                    671: 
                    672:      deviceExtension->PortCapabilities = PortCapabilities;
                    673: 
                    674:      //
                    675:      // Save Current Partition number and inquiry data.
                    676:      //
                    677: 
                    678:      tapeData = (PTAPE_DATA )(deviceExtension + 1 );
                    679: 
                    680:      tapeData->CurrentPartition = 0;
                    681: 
                    682:      tapeData->InquiryData = LunInfo;
                    683: 
                    684:      //
                    685:      // Disable synchronous transfer for tape requests.
                    686:      //
                    687: 
                    688:      deviceExtension->SrbFlags = SRB_FLAGS_DISABLE_SYNCH_TRANSFER;
                    689: 
                    690:      //
                    691:      // Allocate request sense buffer.
                    692:      //
                    693: 
                    694:      senseData = ExAllocatePool(NonPagedPoolCacheAligned,
                    695:                                 SENSE_BUFFER_SIZE);
                    696: 
                    697:      if (senseData == NULL) {
                    698: 
                    699:           //
                    700:           // The buffer could not be allocated.
                    701:           //
                    702: 
                    703:           IoDeleteDevice(deviceObject);
                    704: 
                    705:           return(STATUS_INSUFFICIENT_RESOURCES);
                    706:      }
                    707: 
                    708:      //
                    709:      // Set the sense data pointer in the device extension.
                    710:      //
                    711: 
                    712:      deviceExtension->SenseData = senseData;
                    713: 
                    714:      //
                    715:      // TargetId/LUN describes a device location on the SCSI bus.
                    716:      // This information comes from the inquiry buffer.
                    717:      //
                    718: 
                    719:      deviceExtension->PortNumber = (UCHAR) PortNumber;
                    720:      deviceExtension->PathId = pathId;
                    721:      deviceExtension->TargetId = targetId;
                    722:      deviceExtension->Lun = lun;
                    723: 
                    724:      //
                    725:      // Set timeout value in seconds.
                    726:      //
                    727: 
                    728:      deviceExtension->TimeOutValue = 180;
                    729: 
                    730:      //
                    731:      // Back pointer to device object.
                    732:      //
                    733: 
                    734:      deviceExtension->DeviceObject = deviceObject;
                    735: 
                    736:      //
                    737:      // Allocate buffer for drive geometry.
                    738:      //
                    739: 
                    740:      deviceExtension->DiskGeometry =
                    741:          ExAllocatePool(NonPagedPool, sizeof(DISK_GEOMETRY));
                    742: 
                    743:      if (!deviceExtension->DiskGeometry) {
                    744: 
                    745:          ExFreePool(senseData);
                    746: 
                    747:          //
                    748:          // Release device.
                    749:          //
                    750: 
                    751:          ScsiClassClaimDevice(PortDeviceObject,
                    752:                               LunInfo,
                    753:                               TRUE,
                    754:                               &PortDeviceObject);
                    755: 
                    756: 
                    757:          IoDeleteDevice(deviceObject);
                    758:          return(STATUS_INSUFFICIENT_RESOURCES);
                    759:      }
                    760: 
                    761:      //
                    762:      // Initialize fixed block size of 512 bytes.
                    763:      //
                    764: 
                    765:      deviceExtension->DiskGeometry->BytesPerSector = 512;
                    766:      deviceExtension->SectorShift = 9;
                    767: 
                    768:      //
                    769:      // Set tape error handler.
                    770:      //
                    771: 
                    772:      deviceExtension->ClassError = ScsiTapeError;
                    773: 
                    774:      //
                    775:      // Add tape device number to registry
                    776:      //
                    777: 
                    778:      UpdateTapeInformationInRegistry(deviceObject,
                    779:                                      LunInfo,
                    780:                                      PortNumber,
                    781:                                      *DeviceCount);
                    782: 
                    783:      return STATUS_SUCCESS;
                    784: 
                    785: } // end CreateTapeDeviceObject()
                    786: 
                    787: 
                    788: NTSTATUS
                    789: ScsiTapeReadWrite(
                    790:     IN PDEVICE_OBJECT DeviceObject,
                    791:     IN PIRP Irp
                    792:     )
                    793: 
                    794: /*++
                    795: 
                    796: Routine Description:
                    797: 
                    798:     This is the tape class driver IO handler routine. It is the system entry
                    799:     point for read and write requests. The number of bytes in the request are
                    800:     checked against the maximum byte counts that the adapter supports and
                    801:     requests are broken up into smaller sizes if necessary. Then the
                    802:     device-specific handler is called.
                    803: 
                    804: Arguments:
                    805: 
                    806:     DeviceObject
                    807:     Irp - IO request
                    808: 
                    809: Return Value:
                    810: 
                    811:     NT Status
                    812: 
                    813: --*/
                    814: 
                    815: {
                    816:     PDEVICE_EXTENSION   deviceExtension = DeviceObject->DeviceExtension;
                    817:     PIO_STACK_LOCATION  currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
                    818:     ULONG transferPages;
                    819:     ULONG               transferByteCount =
                    820:         currentIrpStack->Parameters.Read.Length;
                    821:     LARGE_INTEGER       startingOffset =
                    822:         currentIrpStack->Parameters.Read.ByteOffset;
                    823:     ULONG               maximumTransferLength =
                    824:         deviceExtension->PortCapabilities->MaximumTransferLength;
                    825:     NTSTATUS            status;
                    826: 
                    827:     DebugPrint((3,"ScsiTapeRead: Enter routine\n"));
                    828: 
                    829:     if (DeviceObject->Flags & DO_VERIFY_VOLUME &&
                    830:         !(currentIrpStack->Flags & SL_OVERRIDE_VERIFY_VOLUME)) {
                    831: 
                    832:         //
                    833:         // if DO_VERIFY_VOLUME bit is set
                    834:         // in device object flags, fail request.
                    835:         //
                    836: 
                    837:         DebugPrint((3,"ScsiTapeRead: Volume verfication needed\n"));
                    838: 
                    839:         Irp->IoStatus.Status = STATUS_VERIFY_REQUIRED;
                    840:         Irp->IoStatus.Information = 0;
                    841: 
                    842:         IoSetHardErrorOrVerifyDevice(Irp, DeviceObject);
                    843: 
                    844:         IoCompleteRequest(Irp, 0);
                    845: 
                    846:         return STATUS_VERIFY_REQUIRED;
                    847:     }
                    848: 
                    849:     //
                    850:     // Calculate number of pages in this transfer.
                    851:     //
                    852: 
                    853:     transferPages = ADDRESS_AND_SIZE_TO_SPAN_PAGES(
                    854:         MmGetMdlVirtualAddress(Irp->MdlAddress),
                    855:         currentIrpStack->Parameters.Read.Length);
                    856: 
                    857:     //
                    858:     // Check if request length is greater than the maximum number of
                    859:     // bytes that the hardware can transfer.
                    860:     //
                    861: 
                    862:     if (currentIrpStack->Parameters.Read.Length > maximumTransferLength ||
                    863:         transferPages > deviceExtension->PortCapabilities->MaximumPhysicalPages) {
                    864: 
                    865:          DebugPrint((2,"ScsiTapeRead: Request greater than maximum\n"));
                    866:          DebugPrint((2,"ScsiTapeRead: Maximum is %lx\n",
                    867:                      maximumTransferLength));
                    868:          DebugPrint((2,"ScsiTapeRead: Byte count is %lx\n",
                    869:                      currentIrpStack->Parameters.Read.Length));
                    870: 
                    871:          transferPages =
                    872:             deviceExtension->PortCapabilities->MaximumPhysicalPages - 1;
                    873: 
                    874:          if (maximumTransferLength > transferPages << PAGE_SHIFT ) {
                    875:              maximumTransferLength = transferPages << PAGE_SHIFT;
                    876:          }
                    877: 
                    878:         //
                    879:         // Check that maximum transfer size is not zero.
                    880:         //
                    881: 
                    882:         if (maximumTransferLength == 0) {
                    883:             maximumTransferLength = PAGE_SIZE;
                    884:         }
                    885: 
                    886:         //
                    887:         // Mark IRP with status pending.
                    888:         //
                    889: 
                    890:         IoMarkIrpPending(Irp);
                    891: 
                    892:         //
                    893:         // Request greater than port driver maximum.
                    894:         // Break up into smaller routines.
                    895:         //
                    896: 
                    897:         SplitTapeRequest(DeviceObject, Irp, maximumTransferLength);
                    898: 
                    899: 
                    900:         return STATUS_PENDING;
                    901:     }
                    902: 
                    903:     //
                    904:     // Build SRB and CDB for this IRP.
                    905:     //
                    906: 
                    907:     status = TapeReadWrite(DeviceObject, Irp);
                    908: 
                    909:     if (status == STATUS_PENDING) {
                    910: 
                    911:         //
                    912:         // Return the results of the call to the port driver.
                    913:         //
                    914: 
                    915:         return IoCallDriver(deviceExtension->PortDeviceObject, Irp);
                    916: 
                    917:     } else {
                    918: 
                    919:         //
                    920:         // Complete request.
                    921:         //
                    922: 
                    923:         IoCompleteRequest(Irp, 0);
                    924: 
                    925:         return status;
                    926:     }
                    927: 
                    928: } // end ScsiTapeReadWrite()
                    929: 
                    930: 
                    931: NTSTATUS
                    932: ScsiTapeDeviceControl(
                    933:   IN PDEVICE_OBJECT DeviceObject,
                    934:   IN PIRP Irp
                    935:   )
                    936: 
                    937: /*++
                    938: 
                    939: Routine Description:
                    940: 
                    941:     This routine is the dispatcher for device control requests. It
                    942:     looks at the IOCTL code and calls the appropriate tape device
                    943:     routine.
                    944: 
                    945: Arguments:
                    946: 
                    947:     DeviceObject
                    948:     Irp - Request packet
                    949: 
                    950: Return Value:
                    951: 
                    952: --*/
                    953: 
                    954: {
                    955:     PIO_STACK_LOCATION  irpStack = IoGetCurrentIrpStackLocation(Irp);
                    956:     PDEVICE_EXTENSION   deviceExtension = DeviceObject->DeviceExtension;
                    957:     NTSTATUS            status;
                    958:     BOOLEAN             retried = FALSE;
                    959: 
                    960:     DebugPrint((3,"ScsiTapeDeviceControl: Enter routine\n"));
                    961: 
                    962:     switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
                    963: 
                    964:     case IOCTL_TAPE_GET_DRIVE_PARAMS:
                    965: 
                    966:          //
                    967:          // Validate buffer length.
                    968:          //
                    969: 
                    970:          if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
                    971:              sizeof(TAPE_GET_DRIVE_PARAMETERS)) {
                    972: 
                    973:              status = STATUS_INFO_LENGTH_MISMATCH;
                    974:              break;
                    975:          }
                    976: 
                    977:         status = TapeGetDriveParameters(DeviceObject, Irp);
                    978:         break;
                    979: 
                    980:     case IOCTL_TAPE_SET_DRIVE_PARAMS:
                    981: 
                    982:          //
                    983:          // Validate buffer length.
                    984:          //
                    985: 
                    986:          if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
                    987:              sizeof(TAPE_SET_DRIVE_PARAMETERS)) {
                    988: 
                    989:              status = STATUS_INFO_LENGTH_MISMATCH;
                    990:              break;
                    991:          }
                    992: 
                    993:          status = TapeSetDriveParameters(DeviceObject, Irp);
                    994:          break;
                    995: 
                    996:     case IOCTL_TAPE_GET_MEDIA_PARAMS:
                    997: 
                    998:          //
                    999:          // Validate buffer length.
                   1000:          //
                   1001: 
                   1002:          if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
                   1003:              sizeof(TAPE_GET_MEDIA_PARAMETERS)) {
                   1004: 
                   1005:              status = STATUS_INFO_LENGTH_MISMATCH;
                   1006:              break;
                   1007:          }
                   1008: 
                   1009:          status = TapeGetMediaParameters(DeviceObject, Irp);
                   1010:          break;
                   1011: 
                   1012:     case IOCTL_TAPE_SET_MEDIA_PARAMS:
                   1013:     {
                   1014:         PTAPE_SET_MEDIA_PARAMETERS tapeSetMediaParams =
                   1015:             Irp->AssociatedIrp.SystemBuffer;
                   1016:         ULONG sectorShift;
                   1017: 
                   1018:          //
                   1019:          // Validate buffer length.
                   1020:          //
                   1021: 
                   1022:          if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
                   1023:              sizeof(TAPE_SET_MEDIA_PARAMETERS)) {
                   1024: 
                   1025:              status = STATUS_INFO_LENGTH_MISMATCH;
                   1026:              break;
                   1027:          }
                   1028: 
                   1029:         //
                   1030:         // Make sure the block size is a power of 2.
                   1031:         //
                   1032: 
                   1033:         WHICH_BIT(tapeSetMediaParams->BlockSize, sectorShift);
                   1034: 
                   1035:         if (tapeSetMediaParams->BlockSize != (ULONG)(1 << sectorShift)) {
                   1036: 
                   1037:             status = STATUS_INVALID_PARAMETER;
                   1038:             break;
                   1039:         }
                   1040: 
                   1041:         status = TapeSetMediaParameters(DeviceObject, Irp);
                   1042: 
                   1043:         if (NT_SUCCESS(status)) {
                   1044: 
                   1045:             //
                   1046:             // Set the block size in the device object.
                   1047:             //
                   1048: 
                   1049:             deviceExtension->DiskGeometry->BytesPerSector =
                   1050:                 tapeSetMediaParams->BlockSize;
                   1051:             deviceExtension->SectorShift = (UCHAR)sectorShift;
                   1052: 
                   1053:         }
                   1054: 
                   1055:          break;
                   1056: 
                   1057:     }
                   1058: 
                   1059:     case IOCTL_TAPE_CREATE_PARTITION:
                   1060: 
                   1061:          //
                   1062:          // Validate buffer length.
                   1063:          //
                   1064: 
                   1065:          if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
                   1066:              sizeof(TAPE_CREATE_PARTITION)) {
                   1067: 
                   1068:              status = STATUS_INFO_LENGTH_MISMATCH;
                   1069:              break;
                   1070:          }
                   1071: 
                   1072:          status = TapeCreatePartition (DeviceObject, Irp);
                   1073:          break;
                   1074: 
                   1075:     case IOCTL_TAPE_ERASE:
                   1076: 
                   1077:          //
                   1078:          // Validate buffer length.
                   1079:          //
                   1080: 
                   1081:          if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
                   1082:              sizeof(TAPE_ERASE)) {
                   1083: 
                   1084:              status = STATUS_INFO_LENGTH_MISMATCH;
                   1085:              break;
                   1086:          }
                   1087: 
                   1088:          status = TapeErase(DeviceObject, Irp);
                   1089:          break;
                   1090: 
                   1091:     case IOCTL_TAPE_PREPARE:
                   1092: 
                   1093:          //
                   1094:          // Validate buffer length.
                   1095:          //
                   1096: 
                   1097:          if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
                   1098:              sizeof(TAPE_PREPARE)) {
                   1099: 
                   1100:              status = STATUS_INFO_LENGTH_MISMATCH;
                   1101:              break;
                   1102:          }
                   1103: 
                   1104:          status = TapePrepare(DeviceObject, Irp);
                   1105:          break;
                   1106: 
                   1107:     case IOCTL_TAPE_WRITE_MARKS:
                   1108: 
                   1109:          //
                   1110:          // Validate buffer length.
                   1111:          //
                   1112: 
                   1113:          if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
                   1114:              sizeof(TAPE_WRITE_MARKS)) {
                   1115: 
                   1116:              status = STATUS_INFO_LENGTH_MISMATCH;
                   1117:              break;
                   1118:          }
                   1119: 
                   1120:          status = TapeWriteMarks(DeviceObject, Irp);
                   1121:          break;
                   1122: 
                   1123:     case IOCTL_TAPE_GET_POSITION:
                   1124: 
                   1125:          //
                   1126:          // Validate buffer length.
                   1127:          //
                   1128: 
                   1129:          if (irpStack->Parameters.DeviceIoControl.OutputBufferLength <
                   1130:              sizeof(TAPE_GET_POSITION)) {
                   1131: 
                   1132:              status = STATUS_INFO_LENGTH_MISMATCH;
                   1133:              break;
                   1134:          }
                   1135: 
                   1136:          status = TapeGetPosition(DeviceObject, Irp);
                   1137:          break;
                   1138: 
                   1139:     case IOCTL_TAPE_SET_POSITION:
                   1140: 
                   1141:          //
                   1142:          // Validate buffer length.
                   1143:          //
                   1144: 
                   1145:          if (irpStack->Parameters.DeviceIoControl.InputBufferLength <
                   1146:              sizeof(TAPE_SET_POSITION)) {
                   1147: 
                   1148:              status = STATUS_INFO_LENGTH_MISMATCH;
                   1149:              break;
                   1150:          }
                   1151: 
                   1152:          status = TapeSetPosition(DeviceObject, Irp);
                   1153:          break;
                   1154: 
                   1155:     case IOCTL_TAPE_GET_STATUS:
                   1156: 
                   1157:           status = TapeGetStatus (DeviceObject, Irp);
                   1158:           break;
                   1159: 
                   1160:     default:
                   1161: 
                   1162:             //
                   1163:             // Pass the request to the common device control routine.
                   1164:             //
                   1165: 
                   1166:             return(ScsiClassDeviceControl(DeviceObject, Irp));
                   1167: 
                   1168:     } // end switch()
                   1169: 
                   1170:     ASSERT(status != STATUS_VERIFY_REQUIRED);
                   1171: 
                   1172:     //
                   1173:     // Complete the request.
                   1174:     //
                   1175: 
                   1176:     Irp->IoStatus.Status = status;
                   1177:     IoCompleteRequest(Irp, 2);
                   1178: 
                   1179:     return status;
                   1180: 
                   1181: } // end ScsiScsiTapeDeviceControl()
                   1182: 
                   1183: 
                   1184: NTSTATUS
                   1185: ScsiTapeCreate (
                   1186:   IN PDEVICE_OBJECT DeviceObject,
                   1187:   IN PIRP Irp
                   1188:   )
                   1189: 
                   1190: /*++
                   1191: 
                   1192: Routine Description:
                   1193: 
                   1194:     This routine handles CREATE/OPEN requests and does
                   1195:     nothing more than return successful status.
                   1196: 
                   1197: Arguments:
                   1198: 
                   1199:     DeviceObject
                   1200:     Irp
                   1201: 
                   1202: Return Value:
                   1203: 
                   1204:     NT Status
                   1205: 
                   1206: --*/
                   1207: 
                   1208: {
                   1209:      UNREFERENCED_PARAMETER(DeviceObject);
                   1210: 
                   1211:      Irp->IoStatus.Status = STATUS_SUCCESS;
                   1212: 
                   1213:      IoCompleteRequest(Irp, 0);
                   1214: 
                   1215:      return STATUS_SUCCESS;
                   1216: 
                   1217: } // end ScsiTapeCreate()
                   1218: 
                   1219: 
                   1220: VOID
                   1221: SplitTapeRequest(
                   1222:     IN PDEVICE_OBJECT DeviceObject,
                   1223:     IN PIRP Irp,
                   1224:     IN ULONG MaximumBytes
                   1225:     )
                   1226: 
                   1227: /*++
                   1228: 
                   1229: Routine Description:
                   1230: 
                   1231:     Break request into smaller requests.
                   1232:     Each new request will be the maximum transfer
                   1233:     size that the port driver can handle or if it
                   1234:     is the final request, it may be the residual
                   1235:     size.
                   1236: 
                   1237:     The number of IRPs required to process this
                   1238:     request is written in the current stack of
                   1239:     the original IRP. Then as each new IRP completes
                   1240:     the count in the original IRP is decremented.
                   1241:     When the count goes to zero, the original IRP
                   1242:     is completed.
                   1243: 
                   1244: Arguments:
                   1245: 
                   1246:     DeviceObject - Pointer to the device object
                   1247:     Irp - Pointer to Irp
                   1248: 
                   1249: Return Value:
                   1250: 
                   1251:     None.
                   1252: 
                   1253: --*/
                   1254: 
                   1255: {
                   1256:     PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
                   1257:     PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
                   1258:     PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
                   1259:     ULONG irpCount;
                   1260:     ULONG transferByteCount =
                   1261:         currentIrpStack->Parameters.Read.Length;
                   1262:     PSCSI_REQUEST_BLOCK srb;
                   1263:     LARGE_INTEGER startingOffset =
                   1264:         currentIrpStack->Parameters.Read.ByteOffset;
                   1265:     ULONG dataLength = MaximumBytes;
                   1266:     PVOID dataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
                   1267:     INTERLOCKED_RESULT remainingIrps;
                   1268:     BOOLEAN completeOriginalIrp = FALSE;
                   1269:     NTSTATUS status;
                   1270:     ULONG i;
                   1271: 
                   1272:     //
                   1273:     // Caluculate number of requests to break this IRP into.
                   1274:     //
                   1275: 
                   1276:     irpCount = (transferByteCount + MaximumBytes - 1) / MaximumBytes;
                   1277: 
                   1278:     DebugPrint((2, "SplitTapeRequest: Requires %d IRPs\n", irpCount));
                   1279: 
                   1280:     DebugPrint((2, "SplitTapeRequest: Original IRP %lx\n", Irp));
                   1281: 
                   1282:     //
                   1283:     // If all partial transfers complete successfully then
                   1284:     // the status is already set up.
                   1285:     // Failing partial transfer IRP will set status to
                   1286:     // error and bytes transferred to 0 during IoCompletion.
                   1287:     // Setting bytes transferred to 0 if an IRP
                   1288:     // fails allows asynchronous partial transfers. This is an
                   1289:     // optimization for the successful case.  As the irps complete
                   1290:     // with partital or full transfers they will update the bytes
                   1291:     // transfered.  This is handle as a special case since a read or
                   1292:     // write can succeed but on part of the data is transfered.
                   1293:     //
                   1294: 
                   1295:     Irp->IoStatus.Status = STATUS_SUCCESS;
                   1296: 
                   1297:     //
                   1298:     // Save number of IRPs to complete count on current stack
                   1299:     // of original IRP.
                   1300:     //
                   1301: 
                   1302:     nextIrpStack->Parameters.Others.Argument1 = (PVOID)irpCount;
                   1303: 
                   1304:     for (i = 0; i < irpCount; i++) {
                   1305: 
                   1306:         PIRP newIrp;
                   1307:         PIO_STACK_LOCATION newIrpStack;
                   1308: 
                   1309:         //
                   1310:         // Allocate new IRP.
                   1311:         //
                   1312: 
                   1313:         newIrp = IoAllocateIrp(DeviceObject->StackSize, FALSE);
                   1314: 
                   1315:         if (newIrp == NULL) {
                   1316: 
                   1317:             DebugPrint((1,"SplitTapeRequest: Can't allocate Irp\n"));
                   1318: 
                   1319:             //
                   1320:             // Decrement count of outstanding partial requests.
                   1321:             //
                   1322: 
                   1323:             remainingIrps = ExInterlockedDecrementLong(
                   1324:                 (PLONG)&nextIrpStack->Parameters.Others.Argument1,
                   1325:                 &deviceExtension->SplitRequestSpinLock);
                   1326: 
                   1327:             //
                   1328:             // Check if any outstanding IRPs.
                   1329:             //
                   1330: 
                   1331:             if (remainingIrps == ResultZero) {
                   1332:                 completeOriginalIrp = TRUE;
                   1333:             }
                   1334: 
                   1335:             //
                   1336:             // Update original IRP with failing status.
                   1337:             //
                   1338: 
                   1339:             Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES;
                   1340:             Irp->IoStatus.Information = 0;
                   1341: 
                   1342:             //
                   1343:             // Keep going with this request as outstanding partials
                   1344:             // may be in progress.
                   1345:             //
                   1346: 
                   1347:             goto KeepGoing;
                   1348:         }
                   1349: 
                   1350:         DebugPrint((2, "SplitTapeRequest: New IRP %lx\n", newIrp));
                   1351: 
                   1352:         //
                   1353:         // Write MDL address to new IRP.
                   1354:         // In the port driver the SRB data length
                   1355:         // field is used as an offset into the MDL,
                   1356:         // so the same MDL can be used for each partial
                   1357:         // transfer. This saves having to build a new
                   1358:         // MDL for each partial transfer.
                   1359:         //
                   1360: 
                   1361:         newIrp->MdlAddress = Irp->MdlAddress;
                   1362: 
                   1363:         //
                   1364:         // At this point there is no current stack.
                   1365:         // IoSetNextIrpStackLocation will make the
                   1366:         // first stack location the current stack
                   1367:         // so that the SRB address can be written
                   1368:         // there.
                   1369:         //
                   1370: 
                   1371:         IoSetNextIrpStackLocation(newIrp);
                   1372: 
                   1373:         newIrpStack = IoGetCurrentIrpStackLocation(newIrp);
                   1374: 
                   1375:         newIrpStack->MajorFunction = currentIrpStack->MajorFunction;
                   1376: 
                   1377:         newIrpStack->Parameters.Read.Length = dataLength;
                   1378:         newIrpStack->Parameters.Read.ByteOffset = startingOffset;
                   1379: 
                   1380:         newIrpStack->DeviceObject = DeviceObject;
                   1381: 
                   1382:         //
                   1383:         // Build SRB and CDB.
                   1384:         //
                   1385: 
                   1386:         status = TapeReadWrite(DeviceObject, newIrp);
                   1387: 
                   1388:         if (!NT_SUCCESS(status)) {
                   1389: 
                   1390:             DebugPrint((1,"SplitTapeRequest: TapeReadWrite failed\n"));
                   1391: 
                   1392:             //
                   1393:             // Decrement count of outstanding partial requests.
                   1394:             //
                   1395: 
                   1396:             remainingIrps =ExInterlockedDecrementLong(
                   1397:                 (PLONG)&nextIrpStack->Parameters.Others.Argument1,
                   1398:                 &deviceExtension->SplitRequestSpinLock);
                   1399: 
                   1400:             //
                   1401:             // Check if any outstanding IRPs.
                   1402:             //
                   1403: 
                   1404:             if (remainingIrps == ResultZero) {
                   1405:                 completeOriginalIrp = TRUE;
                   1406:             }
                   1407: 
                   1408:             //
                   1409:             // Update original IRP with failing status.
                   1410:             //
                   1411: 
                   1412:             Irp->IoStatus.Status = status;
                   1413:             Irp->IoStatus.Information = 0;
                   1414: 
                   1415:             //
                   1416:             // Deallocate this partial IRP.
                   1417:             //
                   1418: 
                   1419:             IoFreeIrp(newIrp);
                   1420: 
                   1421:             //
                   1422:             // Keep going with this request as outstanding partials
                   1423:             // may be in progress.
                   1424:             //
                   1425: 
                   1426:             goto KeepGoing;
                   1427:         }
                   1428: 
                   1429:         //
                   1430:         // Adjust SRB for this partial transfer.
                   1431:         //
                   1432: 
                   1433:         newIrpStack = IoGetNextIrpStackLocation(newIrp);
                   1434: 
                   1435:         srb = newIrpStack->Parameters.Others.Argument1;
                   1436: 
                   1437:         srb->DataBuffer = dataBuffer;
                   1438: 
                   1439:         //
                   1440:         // Write original IRP address to new IRP.
                   1441:         //
                   1442: 
                   1443:         newIrp->AssociatedIrp.MasterIrp = Irp;
                   1444: 
                   1445:         //
                   1446:         // Set the completion routine to ScsiTapeIoCompleteAssociated.
                   1447:         //
                   1448: 
                   1449:         IoSetCompletionRoutine(newIrp,
                   1450:                                ScsiTapeIoCompleteAssociated,
                   1451:                                srb,
                   1452:                                TRUE,
                   1453:                                TRUE,
                   1454:                                TRUE);
                   1455: 
                   1456:         //
                   1457:         // Call port driver with new request.
                   1458:         //
                   1459: 
                   1460:         status = IoCallDriver(deviceExtension->PortDeviceObject, newIrp);
                   1461: 
                   1462:         if (!NT_SUCCESS(status)) {
                   1463: 
                   1464:             DebugPrint((1,"SplitTapeRequest: IoCallDriver returned error\n"));
                   1465: 
                   1466:             //
                   1467:             // Decrement count of outstanding partial requests.
                   1468:             //
                   1469: 
                   1470:             remainingIrps = ExInterlockedDecrementLong(
                   1471:                 (PLONG)&nextIrpStack->Parameters.Others.Argument1,
                   1472:                 &deviceExtension->SplitRequestSpinLock);
                   1473: 
                   1474:             //
                   1475:             // Check if any outstanding IRPs.
                   1476:             //
                   1477: 
                   1478:             if (remainingIrps == ResultZero) {
                   1479:                 completeOriginalIrp = TRUE;
                   1480:             }
                   1481: 
                   1482:             //
                   1483:             // Update original IRP with failing status.
                   1484:             //
                   1485: 
                   1486:             Irp->IoStatus.Status = status;
                   1487:             Irp->IoStatus.Information = 0;
                   1488: 
                   1489:             //
                   1490:             // Deallocate this partial IRP.
                   1491:             //
                   1492: 
                   1493:             IoFreeIrp(newIrp);
                   1494:         }
                   1495: 
                   1496: KeepGoing:
                   1497: 
                   1498:         //
                   1499:         // Set up for next request.
                   1500:         //
                   1501: 
                   1502:         dataBuffer = (PCHAR)dataBuffer + MaximumBytes;
                   1503: 
                   1504:         transferByteCount -= MaximumBytes;
                   1505: 
                   1506:         if (transferByteCount > MaximumBytes) {
                   1507: 
                   1508:             dataLength = MaximumBytes;
                   1509: 
                   1510:         } else {
                   1511: 
                   1512:             dataLength = transferByteCount;
                   1513:         }
                   1514: 
                   1515:         //
                   1516:         // Adjust disk byte offset.
                   1517:         //
                   1518: 
                   1519:         startingOffset = RtlLargeIntegerAdd(startingOffset, RtlConvertUlongToLargeInteger(MaximumBytes));
                   1520:     }
                   1521: 
                   1522:     //
                   1523:     // Check if original IRP should be completed.
                   1524:     //
                   1525: 
                   1526:     if (completeOriginalIrp) {
                   1527: 
                   1528:         IoCompleteRequest(Irp, 0);
                   1529:     }
                   1530: 
                   1531:     return;
                   1532: 
                   1533: } // end SplitTapeRequest()
                   1534: 
                   1535: 
                   1536: VOID
                   1537: ScsiTapeError(
                   1538:     PDEVICE_OBJECT DeviceObject,
                   1539:     PSCSI_REQUEST_BLOCK Srb,
                   1540:     NTSTATUS *Status,
                   1541:     BOOLEAN *Retry
                   1542:     )
                   1543: 
                   1544: /*++
                   1545: 
                   1546: Routine Description:
                   1547: 
                   1548:     When a request completes with error, the routine ScsiClassInterpretSenseInfo is
                   1549:     called to determine from the sense data whether the request should be
                   1550:     retried and what NT status to set in the IRP. Then this routine is called
                   1551:     for tape requests to handle tape-specific errors and update the nt status
                   1552:     and retry boolean.
                   1553: 
                   1554: Arguments:
                   1555: 
                   1556:     DeviceObject - Supplies a pointer to the device object.
                   1557: 
                   1558:     Srb - Supplies a pointer to the failing Srb.
                   1559: 
                   1560:     Status - NT Status used to set the IRP's completion status.
                   1561: 
                   1562:     Retry - Indicates that this request should be retried.
                   1563: 
                   1564: Return Value:
                   1565: 
                   1566:     None.
                   1567: 
                   1568: --*/
                   1569: 
                   1570: {
                   1571:     PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
                   1572:     PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer;
                   1573:     PIRP irp = Srb->OriginalRequest;
                   1574:     ULONG residualBlocks;
                   1575:     LONG length;
                   1576: 
                   1577:     //
                   1578:     // Never retry tape requests.
                   1579:     //
                   1580: 
                   1581:     *Retry = FALSE;
                   1582: 
                   1583:     //
                   1584:     // Check that request sense buffer is valid.
                   1585:     //
                   1586: 
                   1587:     if (Srb->SrbStatus & SRB_STATUS_AUTOSENSE_VALID) {
                   1588: 
                   1589:         switch (senseBuffer->SenseKey & 0xf) {
                   1590: 
                   1591:             case SCSI_SENSE_UNIT_ATTENTION:
                   1592: 
                   1593:                 switch (senseBuffer->AdditionalSenseCode) {
                   1594: 
                   1595:                     case SCSI_ADSENSE_MEDIUM_CHANGED:
                   1596:                         DebugPrint((1,
                   1597:                                     "InterpretSenseInfo: Media changed\n"));
                   1598: 
                   1599:                         *Status = STATUS_MEDIA_CHANGED;
                   1600: 
                   1601:                         break;
                   1602: 
                   1603:                     default:
                   1604:                         DebugPrint((1,
                   1605:                                     "InterpretSenseInfo: Bus reset\n"));
                   1606: 
                   1607:                         *Status = STATUS_BUS_RESET;
                   1608: 
                   1609:                         break;
                   1610: 
                   1611:                 }
                   1612: 
                   1613:                 break;
                   1614: 
                   1615:             case SCSI_SENSE_RECOVERED_ERROR:
                   1616: 
                   1617:                 //
                   1618:                 // Check other indicators
                   1619:                 //
                   1620: 
                   1621:                 if (senseBuffer->FileMark) {
                   1622: 
                   1623:                     switch (senseBuffer->AdditionalSenseCodeQualifier) {
                   1624: 
                   1625:                         case SCSI_SENSEQ_SETMARK_DETECTED :
                   1626: 
                   1627:                             DebugPrint((1,
                   1628:                                         "InterpretSenseInfo: Setmark detected\n"));
                   1629: 
                   1630:                             *Status = STATUS_SETMARK_DETECTED;
                   1631:                             break ;
                   1632: 
                   1633:                         case SCSI_SENSEQ_FILEMARK_DETECTED :
                   1634:                         default:
                   1635: 
                   1636:                             DebugPrint((1,
                   1637:                                         "InterpretSenseInfo: Filemark detected\n"));
                   1638: 
                   1639:                             *Status = STATUS_FILEMARK_DETECTED;
                   1640:                             break ;
                   1641: 
                   1642:                     }
                   1643: 
                   1644:                 } else if ( senseBuffer->EndOfMedia ) {
                   1645: 
                   1646:                     switch( senseBuffer->AdditionalSenseCodeQualifier ) {
                   1647: 
                   1648:                         case SCSI_SENSEQ_BEGINNING_OF_MEDIA_DETECTED :
                   1649: 
                   1650:                             DebugPrint((1,
                   1651:                                         "InterpretSenseInfo: Beginning of media detected\n"));
                   1652: 
                   1653:                             *Status = STATUS_BEGINNING_OF_MEDIA;
                   1654:                             break ;
                   1655: 
                   1656:                         case SCSI_SENSEQ_END_OF_MEDIA_DETECTED :
                   1657:                         default:
                   1658: 
                   1659:                             DebugPrint((1,
                   1660:                                         "InterpretSenseInfo: End of media detected\n"));
                   1661: 
                   1662:                             *Status = STATUS_END_OF_MEDIA;
                   1663:                             break ;
                   1664: 
                   1665:                     }
                   1666:                 }
                   1667: 
                   1668:                 break;
                   1669: 
                   1670:             case SCSI_SENSE_NO_SENSE:
                   1671: 
                   1672:                 //
                   1673:                 // Check other indicators
                   1674:                 //
                   1675: 
                   1676:                 if (senseBuffer->FileMark) {
                   1677: 
                   1678:                     switch( senseBuffer->AdditionalSenseCodeQualifier ) {
                   1679: 
                   1680:                         case SCSI_SENSEQ_SETMARK_DETECTED :
                   1681: 
                   1682:                             DebugPrint((1,
                   1683:                                         "InterpretSenseInfo: Setmark detected\n"));
                   1684: 
                   1685:                             *Status = STATUS_SETMARK_DETECTED;
                   1686:                             break ;
                   1687: 
                   1688:                         case SCSI_SENSEQ_FILEMARK_DETECTED :
                   1689:                         default:
                   1690: 
                   1691:                             DebugPrint((1,
                   1692:                                         "InterpretSenseInfo: Filemark detected\n"));
                   1693: 
                   1694:                             *Status = STATUS_FILEMARK_DETECTED;
                   1695:                             break ;
                   1696:                     }
                   1697: 
                   1698:                 } else if (senseBuffer->EndOfMedia) {
                   1699: 
                   1700:                     switch(senseBuffer->AdditionalSenseCodeQualifier) {
                   1701: 
                   1702:                         case SCSI_SENSEQ_BEGINNING_OF_MEDIA_DETECTED :
                   1703: 
                   1704:                             DebugPrint((1,
                   1705:                                         "InterpretSenseInfo: Beginning of media detected\n"));
                   1706: 
                   1707:                             *Status = STATUS_BEGINNING_OF_MEDIA;
                   1708:                             break ;
                   1709: 
                   1710:                         case SCSI_SENSEQ_END_OF_MEDIA_DETECTED :
                   1711:                         default:
                   1712: 
                   1713:                             DebugPrint((1,
                   1714:                                         "InterpretSenseInfo: End of media detected\n"));
                   1715: 
                   1716:                             *Status = STATUS_END_OF_MEDIA;
                   1717:                             break;
                   1718: 
                   1719:                     }
                   1720:                 }
                   1721: 
                   1722:                 break;
                   1723: 
                   1724:             case SCSI_SENSE_BLANK_CHECK:
                   1725: 
                   1726:                 DebugPrint((1,
                   1727:                             "InterpretSenseInfo: Media blank check\n"));
                   1728: 
                   1729:                 *Status = STATUS_NO_DATA_DETECTED;
                   1730: 
                   1731: 
                   1732:                 break;
                   1733: 
                   1734:             case SCSI_SENSE_VOL_OVERFLOW:
                   1735: 
                   1736:                 DebugPrint((1,
                   1737:                     "InterpretSenseInfo: End of Media Overflow\n"));
                   1738: 
                   1739:                 *Status = STATUS_EOM_OVERFLOW;
                   1740: 
                   1741: 
                   1742:                 break;
                   1743: 
                   1744:             case SCSI_SENSE_NOT_READY:
                   1745: 
                   1746:                 switch (senseBuffer->AdditionalSenseCode) {
                   1747: 
                   1748:                     case SCSI_ADSENSE_NO_MEDIA_IN_DEVICE:
                   1749: 
                   1750:                         DebugPrint((1,
                   1751:                                     "InterpretSenseInfo:"
                   1752:                                     " No Media in device.\n"));
                   1753:                         *Status = STATUS_NO_MEDIA;
                   1754:                         break;
                   1755:                 }
                   1756: 
                   1757:                 break;
                   1758: 
                   1759:         } // end switch
                   1760: 
                   1761:         //
                   1762:         // Check if a filemark or setmark was encountered,
                   1763:         // or an end-of-media or no-data condition exists.
                   1764:         //
                   1765: 
                   1766:         if (NT_WARNING(*Status) &&
                   1767:             (Srb->Cdb[0] == SCSIOP_WRITE6 || Srb->Cdb[0] == SCSIOP_READ6)) {
                   1768: 
                   1769:             //
                   1770:             // Not all bytes were transfered. Update information field with
                   1771:             // number of bytes transfered from sense buffer.
                   1772:             //
                   1773: 
                   1774:             if (senseBuffer->Valid) {
                   1775:                 REVERSE_BYTES((PFOUR_BYTE)&residualBlocks,
                   1776:                               (PFOUR_BYTE)senseBuffer->Information);
                   1777:             } else {
                   1778:                 residualBlocks = 0;
                   1779:             }
                   1780: 
                   1781:             length = ((PCDB) Srb->Cdb)->CDB6READWRITETAPE.TransferLenLSB;
                   1782:             length |= ((PCDB) Srb->Cdb)->CDB6READWRITETAPE.TransferLen << 8;
                   1783:             length |= ((PCDB) Srb->Cdb)->CDB6READWRITETAPE.TransferLenMSB << 16;
                   1784: 
                   1785:             length -= residualBlocks;
                   1786: 
                   1787:             if (length < 0) {
                   1788: 
                   1789:                 length = 0;
                   1790:                 *Status = STATUS_IO_DEVICE_ERROR;
                   1791:             }
                   1792: 
                   1793: 
                   1794:             length *= deviceExtension->DiskGeometry->BytesPerSector;
                   1795: 
                   1796:             //
                   1797:             // If the miniport indicates fewer bytes were transfered then
                   1798:             // use that value.
                   1799:             //
                   1800: 
                   1801:             if ((ULONG) length > Srb->DataTransferLength) {
                   1802:                 length = (LONG) Srb->DataTransferLength;
                   1803:                 DebugPrint((1,"ScsiTapeError: Calculated length wronge using miniport length. \n"));
                   1804: 
                   1805:             }
                   1806: 
                   1807:             irp->IoStatus.Information = length;
                   1808: 
                   1809:             DebugPrint((1,"ScsiTapeError:  Transfer Count: %lx\n", Srb->DataTransferLength));
                   1810:             DebugPrint((1," Residual Bytes: %lx\n", residualBlocks * deviceExtension->DiskGeometry->BytesPerSector));
                   1811:             DebugPrint((1," Irp IoStatus Information = %lx\n", irp->IoStatus.Information));
                   1812:         }
                   1813: 
                   1814:     }
                   1815: 
                   1816:     //
                   1817:     // Call tape device specific error handler.
                   1818:     //
                   1819: 
                   1820:     TapeError(DeviceObject->DeviceExtension,
                   1821:               Srb,
                   1822:               Status,
                   1823:               Retry);
                   1824: 
                   1825:     return;
                   1826: 
                   1827: } // end ScsiTapeError()
                   1828: 
                   1829: NTSTATUS
                   1830: ScsiTapeIoCompleteAssociated(
                   1831:     IN PDEVICE_OBJECT DeviceObject,
                   1832:     IN PIRP Irp,
                   1833:     IN PVOID Context
                   1834:     )
                   1835: 
                   1836: /*++
                   1837: 
                   1838: Routine Description:
                   1839: 
                   1840:     This routine executes when the port driver has completed a request.
                   1841:     It looks at the SRB status in the completing SRB and if not success
                   1842:     it checks for valid request sense buffer information. If valid, the
                   1843:     info is used to update status with more precise message of type of
                   1844:     error. This routine deallocates the SRB.  This routine is used for
                   1845:     requests which were build by split request.  After it has processed
                   1846:     the request it decrements the Irp count in the master Irp.  If the
                   1847:     count goes to zero then the master Irp is completed.
                   1848: 
                   1849: Arguments:
                   1850: 
                   1851:     DeviceObject - Supplies the device object which represents the logical
                   1852:         unit.
                   1853: 
                   1854:     Irp - Supplies the Irp which has completed.
                   1855: 
                   1856:     Context - Supplies a pointer to the SRB.
                   1857: 
                   1858: Return Value:
                   1859: 
                   1860:     NT status
                   1861: 
                   1862: --*/
                   1863: 
                   1864: {
                   1865:     PIO_STACK_LOCATION irpStack = IoGetCurrentIrpStackLocation(Irp);
                   1866:     PSCSI_REQUEST_BLOCK srb = Context;
                   1867:     PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
                   1868:     INTERLOCKED_RESULT irpCount;
                   1869:     PIRP originalIrp = Irp->AssociatedIrp.MasterIrp;
                   1870:     NTSTATUS status;
                   1871: 
                   1872:     //
                   1873:     // Check SRB status for success of completing request.
                   1874:     //
                   1875: 
                   1876:     if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_SUCCESS) {
                   1877: 
                   1878:         DebugPrint((2,"ScsiTapeIoCompleteAssociated: IRP %lx, SRB %lx", Irp, srb));
                   1879: 
                   1880:         //
                   1881:         // Release the queue if it is frozen.
                   1882:         //
                   1883: 
                   1884:         if (srb->SrbStatus & SRB_STATUS_QUEUE_FROZEN) {
                   1885:             ScsiClassReleaseQueue(DeviceObject);
                   1886:         }
                   1887: 
                   1888:         ScsiClassInterpretSenseInfo(
                   1889:             DeviceObject,
                   1890:             srb,
                   1891:             irpStack->MajorFunction,
                   1892:             irpStack->MajorFunction == IRP_MJ_DEVICE_CONTROL ? irpStack->Parameters.DeviceIoControl.IoControlCode : 0,
                   1893:             MAXIMUM_RETRIES - ((ULONG)irpStack->Parameters.Others.Argument4),
                   1894:             &status);
                   1895: 
                   1896:         //
                   1897:         // Return the highest error that occurs.  This way warning take precedence
                   1898:         // over success and errors take precedence over errors.
                   1899:         //
                   1900: 
                   1901:         if ((ULONG) status > (ULONG) originalIrp->IoStatus.Status) {
                   1902: 
                   1903:             //
                   1904:             // Ignore any requests which were flushed.
                   1905:             //
                   1906: 
                   1907:             if (SRB_STATUS(srb->SrbStatus) != SRB_STATUS_REQUEST_FLUSHED) {
                   1908: 
                   1909:                 originalIrp->IoStatus.Status = status;
                   1910: 
                   1911:             }
                   1912: 
                   1913:         }
                   1914: 
                   1915: 
                   1916:     } // end if (SRB_STATUS(srb->SrbStatus) ...
                   1917: 
                   1918:     //
                   1919:     // Return SRB to nonpaged pool.
                   1920:     //
                   1921: 
                   1922:     if (srb->SrbFlags & SRB_FLAGS_ALLOCATED_FROM_ZONE) {
                   1923: 
                   1924:         ExInterlockedFreeToZone( deviceExtension->SrbZone,
                   1925:                                  srb,
                   1926:                                  deviceExtension->SrbZoneSpinLock);
                   1927: 
                   1928:     } else {
                   1929: 
                   1930:         ExFreePool(srb);
                   1931: 
                   1932:     }
                   1933: 
                   1934:     DebugPrint((2, "ScsiTapeIoCompleteAssociated: Partial xfer IRP %lx\n", Irp));
                   1935: 
                   1936:     //
                   1937:     // Get next stack location. This original request is unused
                   1938:     // except to keep track of the completing partial IRPs so the
                   1939:     // stack location is valid.
                   1940:     //
                   1941: 
                   1942:     irpStack = IoGetNextIrpStackLocation(originalIrp);
                   1943: 
                   1944:     //
                   1945:     // Increment the status information with number of bytes transfered.
                   1946:     //
                   1947: 
                   1948:     ExInterlockedAddUlong(&originalIrp->IoStatus.Information,
                   1949:                           Irp->IoStatus.Information,
                   1950:                           &deviceExtension->SplitRequestSpinLock );
                   1951: 
                   1952:     //
                   1953:     //
                   1954:     // If any of the asynchronous partial transfer IRPs fail with an error
                   1955:     // with an error then the original IRP will return 0 bytes transfered.
                   1956:     // This is an optimization for successful transfers.
                   1957:     //
                   1958: 
                   1959:     if (NT_ERROR(originalIrp->IoStatus.Status)) {
                   1960: 
                   1961:         originalIrp->IoStatus.Information = 0;
                   1962: 
                   1963:         //
                   1964:         // Set the hard error if necessary.
                   1965:         //
                   1966: 
                   1967:         if (IoIsErrorUserInduced(originalIrp->IoStatus.Status)) {
                   1968: 
                   1969:             //
                   1970:             // Store DeviceObject for filesystem.
                   1971:             //
                   1972: 
                   1973:             IoSetHardErrorOrVerifyDevice(originalIrp, DeviceObject);
                   1974: 
                   1975:         }
                   1976: 
                   1977:     }
                   1978: 
                   1979:     //
                   1980:     // Decrement and get the count of remaining IRPs.
                   1981:     //
                   1982: 
                   1983:     irpCount = ExInterlockedDecrementLong(
                   1984:             (PLONG)&irpStack->Parameters.Others.Argument1,
                   1985:             &deviceExtension->SplitRequestSpinLock);
                   1986: 
                   1987:     DebugPrint((2, "ScsiTapeIoCompleteAssociated: Partial IRPs left %d\n",
                   1988:                 irpCount));
                   1989: 
                   1990:     if (irpCount == ResultZero) {
                   1991: 
                   1992: 
                   1993: #if DBG
                   1994:         irpStack = IoGetCurrentIrpStackLocation(originalIrp);
                   1995: 
                   1996:         if (originalIrp->IoStatus.Information != irpStack->Parameters.Read.Length) {
                   1997:             DebugPrint((1, "ScsiTapeIoCompleteAssociated: Short transfer.  Request length: %lx, Return length: %lx, Status: %lx\n",
                   1998:                 irpStack->Parameters.Read.Length, originalIrp->IoStatus.Information, originalIrp->IoStatus.Status));
                   1999:         }
                   2000: #endif
                   2001:         //
                   2002:         // All partial IRPs have completed.
                   2003:         //
                   2004: 
                   2005:         DebugPrint((2,
                   2006:                  "ScsiTapeIoCompleteAssociated: All partial IRPs complete %lx\n",
                   2007:                  originalIrp));
                   2008: 
                   2009:         IoCompleteRequest(originalIrp, IO_DISK_INCREMENT);
                   2010:     }
                   2011: 
                   2012:     //
                   2013:     // Deallocate IRP and indicate the I/O system should not attempt any more
                   2014:     // processing.
                   2015:     //
                   2016: 
                   2017:     IoFreeIrp(Irp);
                   2018: 
                   2019:     return STATUS_MORE_PROCESSING_REQUIRED;
                   2020: 
                   2021: } // end ScsiTapeIoCompleteAssociated()
                   2022: 
                   2023: 

unix.superglobalmegacorp.com

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