Annotation of ntddk/src/scsi/qic117/main.c, revision 1.1

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1993 - Colorado Memory Systems, Inc.
        !             4: All Rights Reserved
        !             5: 
        !             6: Module Name:
        !             7: 
        !             8:     main.c
        !             9: 
        !            10: Abstract:
        !            11: 
        !            12:     This is the tape class driver.
        !            13: 
        !            14: Revision History:
        !            15: 
        !            16: 
        !            17: 
        !            18: 
        !            19: --*/
        !            20: 
        !            21: //
        !            22: // Includes
        !            23: //
        !            24: 
        !            25: #include <ntddk.h>
        !            26: #include <ntddtape.h>   // tape device driver I/O control codes
        !            27: #include <ntiologc.h>
        !            28: #include "common.h"
        !            29: #include "q117.h"
        !            30: #include "cms.h"
        !            31: #include "protos.h"
        !            32: #include "hilevel.h"
        !            33: #include "q117log.h"
        !            34: 
        !            35: //
        !            36: // Protos for entry points
        !            37: //
        !            38: 
        !            39: NTSTATUS
        !            40: q117CreateNumericKey(
        !            41:     IN HANDLE Root,
        !            42:     IN ULONG Name,
        !            43:     IN PWSTR Prefix,
        !            44:     OUT PHANDLE NewKey
        !            45:     );
        !            46: 
        !            47: NTSTATUS
        !            48: q117CreateRegistryInfo(
        !            49:     IN ULONG TapeNumber,
        !            50:     IN PUNICODE_STRING RegistryPath,
        !            51:     IN PQ117_CONTEXT Context
        !            52:     );
        !            53: 
        !            54: #ifdef ALLOC_PRAGMA
        !            55: #pragma alloc_text(init,q117Initialize)
        !            56: #endif
        !            57: 
        !            58: 
        !            59: //
        !            60: // Start of code
        !            61: //
        !            62: 
        !            63: 
        !            64: NTSTATUS
        !            65: q117Initialize(
        !            66:     IN PDRIVER_OBJECT DriverObject,
        !            67:     IN PDEVICE_OBJECT q117iDeviceObject,
        !            68:     IN PUNICODE_STRING RegistryPath,
        !            69:     PADAPTER_OBJECT AdapterObject,
        !            70:     ULONG           NumberOfMapRegisters
        !            71:     )
        !            72: 
        !            73: /*++
        !            74: 
        !            75: Routine Description:
        !            76: 
        !            77:     This routine initializes the SCSI Tape class driver.
        !            78: 
        !            79: Arguments:
        !            80: 
        !            81:     DriverObject
        !            82: 
        !            83: Return Value:
        !            84: 
        !            85:     NT Status
        !            86: 
        !            87: --*/
        !            88: 
        !            89: {
        !            90:     PDEVICE_OBJECT  q117DeviceObject;
        !            91:     NTSTATUS        status;
        !            92:     UNICODE_STRING  ntUnicodeString;
        !            93:     UCHAR           ntNameBuffer[256];
        !            94:     STRING          ntNameString;
        !            95:     BOOLEAN         tapeDeviceFound = FALSE;
        !            96:     PQ117_CONTEXT   context;
        !            97:     ULONG           tapeNumber;
        !            98:     STRING          dosString;
        !            99:     UNICODE_STRING  dosUnicodeString;
        !           100:     CCHAR           dosNameBuffer[64];
        !           101: 
        !           102:     //
        !           103:     // Build the unicode name for the floppy tape.
        !           104:     //
        !           105:     tapeNumber = IoGetConfigurationInformation()->TapeCount;
        !           106: 
        !           107:     sprintf(ntNameBuffer,
        !           108:             "\\Device\\Tape%d",
        !           109:             tapeNumber);
        !           110: 
        !           111:     RtlInitString(&ntNameString, ntNameBuffer);
        !           112: 
        !           113:     status = RtlAnsiStringToUnicodeString(
        !           114:         &ntUnicodeString,
        !           115:         &ntNameString,
        !           116:         TRUE );
        !           117: 
        !           118:     if (!NT_SUCCESS(status)) {
        !           119:         return(status);
        !           120:     }
        !           121: 
        !           122:     //
        !           123:     // Create a device object for this floppy drive.
        !           124:     //
        !           125: 
        !           126:     status = IoCreateDevice(
        !           127:         DriverObject,
        !           128:         sizeof( struct _Q117_CONTEXT ),
        !           129:         &ntUnicodeString,
        !           130:         FILE_DEVICE_UNKNOWN,
        !           131:         FILE_REMOVABLE_MEDIA,
        !           132:         FALSE,
        !           133:         &q117DeviceObject );
        !           134: 
        !           135: 
        !           136:     if (!NT_SUCCESS(status)) {
        !           137:         return(status);
        !           138:     }
        !           139: 
        !           140:     //
        !           141:     // Create the DOS port driver name.
        !           142:     //
        !           143: 
        !           144:     sprintf(dosNameBuffer,
        !           145:             "\\DosDevices\\TAPE%d",
        !           146:             tapeNumber);
        !           147: 
        !           148:     RtlInitString(&dosString, dosNameBuffer);
        !           149: 
        !           150:     status = RtlAnsiStringToUnicodeString(&dosUnicodeString,
        !           151:                                           &dosString,
        !           152:                                           TRUE);
        !           153: 
        !           154:     if (!NT_SUCCESS(status)) {
        !           155: 
        !           156:         dosUnicodeString.Buffer = NULL;
        !           157: 
        !           158:     } else {
        !           159: 
        !           160:         IoAssignArcName(&dosUnicodeString, &ntUnicodeString);
        !           161: 
        !           162:     }
        !           163: 
        !           164:     RtlFreeUnicodeString(&ntUnicodeString);
        !           165: 
        !           166:     if (dosUnicodeString.Buffer != NULL) {
        !           167: 
        !           168:         RtlFreeUnicodeString(&dosUnicodeString);
        !           169: 
        !           170:     }
        !           171: 
        !           172: 
        !           173:     //
        !           174:     // Increment system tape count.
        !           175:     //
        !           176:     ++IoGetConfigurationInformation()->TapeCount;
        !           177: 
        !           178:     //
        !           179:     // Get device extension address.
        !           180:     //
        !           181: 
        !           182:     context = q117DeviceObject->DeviceExtension;
        !           183:     context->q117iDeviceObject = q117iDeviceObject;
        !           184: 
        !           185:     //
        !           186:     // Allocate memory for the filer
        !           187:     //
        !           188: 
        !           189:     status = q117AllocatePermanentMemory(
        !           190:         context,
        !           191:         AdapterObject,
        !           192:         NumberOfMapRegisters
        !           193:         );
        !           194: 
        !           195:     if (status) {
        !           196:         IoDeleteDevice(q117DeviceObject);
        !           197:         return status;
        !           198:     }
        !           199: 
        !           200:     //
        !           201:     // Indicate MDLs required.
        !           202:     //
        !           203: 
        !           204:     q117DeviceObject->Flags = DO_DIRECT_IO;
        !           205: 
        !           206:     status = q117CreateRegistryInfo(tapeNumber, RegistryPath, context);
        !           207: 
        !           208:     q117RdsInitReed();
        !           209: 
        !           210:     return status;
        !           211: 
        !           212: } // end Q117Initialize()
        !           213: 
        !           214: NTSTATUS
        !           215: q117CreateRegistryInfo(
        !           216:     IN ULONG TapeNumber,
        !           217:     IN PUNICODE_STRING RegistryPath,
        !           218:     IN PQ117_CONTEXT Context
        !           219:     )
        !           220: 
        !           221: /*++
        !           222: 
        !           223: Routine Description:
        !           224: 
        !           225:     This function adds Tape\Unit x to the devicemap and puts the Id info
        !           226:     and type info values in it.
        !           227: 
        !           228: Arguments:
        !           229: 
        !           230:     tapeNumber - unit number of the tape (current tape count)
        !           231: 
        !           232:     Context - current context of the driver (this is used to
        !           233:                 identify the device).
        !           234: 
        !           235: 
        !           236: Return Value:
        !           237: 
        !           238:    Returns the status of the operation.
        !           239: 
        !           240: --*/
        !           241: 
        !           242: {
        !           243:     HANDLE          lunKey;
        !           244:     HANDLE          unitKey;
        !           245:     UNICODE_STRING  ntUnicodeString;
        !           246:     UCHAR           ntNameBuffer[80];
        !           247:     STRING          ntNameString;
        !           248:     UNICODE_STRING  name;
        !           249:     OBJECT_ATTRIBUTES objectAttributes;
        !           250:     ULONG           disposition;
        !           251:     NTSTATUS        status;
        !           252: 
        !           253:     //
        !           254:     // Create the Tape key in the device map.
        !           255:     //
        !           256: 
        !           257:     RtlInitUnicodeString(
        !           258:         &name,
        !           259:         L"\\Registry\\Machine\\Hardware\\DeviceMap\\Tape"
        !           260:         );
        !           261: 
        !           262:     //
        !           263:     // Initialize the object for the key.
        !           264:     //
        !           265: 
        !           266:     InitializeObjectAttributes( &objectAttributes,
        !           267:                                 &name,
        !           268:                                 OBJ_CASE_INSENSITIVE,
        !           269:                                 NULL,
        !           270:                                 (PSECURITY_DESCRIPTOR) NULL );
        !           271: 
        !           272:     //
        !           273:     // Create the key or open it.
        !           274:     //
        !           275: 
        !           276:     status = ZwCreateKey(&lunKey,
        !           277:                         KEY_READ | KEY_WRITE,
        !           278:                         &objectAttributes,
        !           279:                         0,
        !           280:                         (PUNICODE_STRING) NULL,
        !           281:                         REG_OPTION_VOLATILE,
        !           282:                         &disposition );
        !           283: 
        !           284:     if (!NT_SUCCESS(status)) {
        !           285:         return status;
        !           286:     }
        !           287: 
        !           288:     status = q117CreateNumericKey(lunKey, TapeNumber, L"Unit ", &unitKey);
        !           289: 
        !           290:     ZwClose(lunKey);
        !           291: 
        !           292:     if (!NT_SUCCESS(status)) {
        !           293:         return status;
        !           294:     }
        !           295: 
        !           296: 
        !           297:     //
        !           298:     // Add Identifier value.
        !           299:     //
        !           300: 
        !           301:     RtlInitUnicodeString(&name, L"Identifier");
        !           302: 
        !           303:     status = ZwSetValueKey(
        !           304:         unitKey,
        !           305:         &name,
        !           306:         0,
        !           307:         REG_SZ,
        !           308:         L"QIC-40/QIC-80 floppy tape drive",
        !           309:         sizeof(L"QIC-40/QIC-80 floppy tape drive")
        !           310:         );
        !           311: 
        !           312:     if ( NT_SUCCESS(status) ) {
        !           313:         //
        !           314:         // Add driver value.
        !           315:         //
        !           316: 
        !           317:         RtlInitUnicodeString(&name, L"Driver");
        !           318: 
        !           319:         status = ZwSetValueKey(
        !           320:             unitKey,
        !           321:             &name,
        !           322:             0,
        !           323:             REG_SZ,
        !           324:             RegistryPath->Buffer,
        !           325:             RegistryPath->Length
        !           326:             );
        !           327:     }
        !           328: 
        !           329:     if ( NT_SUCCESS(status) ) {
        !           330:         //
        !           331:         // Add DeviceName value.
        !           332:         //
        !           333: 
        !           334:         RtlInitUnicodeString(&name, L"DeviceName");
        !           335: 
        !           336:         sprintf(ntNameBuffer,
        !           337:                 "Tape%d",
        !           338:                 TapeNumber);
        !           339: 
        !           340:         RtlInitString(&ntNameString, ntNameBuffer);
        !           341: 
        !           342:         status = RtlAnsiStringToUnicodeString(&ntUnicodeString,
        !           343:                                               &ntNameString,
        !           344:                                               TRUE);
        !           345: 
        !           346:         status = ZwSetValueKey(
        !           347:             unitKey,
        !           348:             &name,
        !           349:             0,
        !           350:             REG_SZ,
        !           351:             ntUnicodeString.Buffer,
        !           352:             ntUnicodeString.Length
        !           353:             );
        !           354: 
        !           355:         RtlFreeUnicodeString(&ntUnicodeString);
        !           356:     }
        !           357: 
        !           358:     if ( NT_SUCCESS(status) ) {
        !           359:         //
        !           360:         // Add UniqueID
        !           361:         //
        !           362: 
        !           363:         RtlInitUnicodeString(&name, L"UniqueId");
        !           364: 
        !           365:         status = ZwSetValueKey(
        !           366:             unitKey,
        !           367:             &name,
        !           368:             0,
        !           369:             REG_SZ,
        !           370:             L"",
        !           371:             0
        !           372:             );
        !           373:     }
        !           374: 
        !           375: 
        !           376:     ZwClose(unitKey);
        !           377: 
        !           378:     return status;
        !           379: 
        !           380: } // end q117CreateRegistryInfo
        !           381: 
        !           382: NTSTATUS
        !           383: q117CreateNumericKey(
        !           384:     IN HANDLE Root,
        !           385:     IN ULONG Name,
        !           386:     IN PWSTR Prefix,
        !           387:     OUT PHANDLE NewKey
        !           388:     )
        !           389: 
        !           390: /*++
        !           391: 
        !           392: Routine Description:
        !           393: 
        !           394:     This function creates a registry key.  The name of the key is a string
        !           395:     version of numeric value passed in.
        !           396: 
        !           397: Arguments:
        !           398: 
        !           399:     RootKey - Supplies a handle to the key where the new key should be inserted.
        !           400: 
        !           401:     Name - Supplies the numeric value to name the key.
        !           402: 
        !           403:     Prefix - Supplies a prefix name to add to name.
        !           404: 
        !           405:     NewKey - Returns the handle for the new key.
        !           406: 
        !           407: Return Value:
        !           408: 
        !           409:    Returns the status of the operation.
        !           410: 
        !           411: --*/
        !           412: 
        !           413: {
        !           414: 
        !           415:     UNICODE_STRING string;
        !           416:     UNICODE_STRING stringNum;
        !           417:     OBJECT_ATTRIBUTES objectAttributes;
        !           418:     WCHAR bufferNum[16];
        !           419:     WCHAR buffer[64];
        !           420:     ULONG disposition;
        !           421:     NTSTATUS status;
        !           422: 
        !           423:     //
        !           424:     // Copy the Prefix into a string.
        !           425:     //
        !           426: 
        !           427:     string.Length = 0;
        !           428:     string.MaximumLength=64;
        !           429:     string.Buffer = buffer;
        !           430: 
        !           431:     RtlInitUnicodeString(&stringNum, Prefix);
        !           432: 
        !           433:     RtlCopyUnicodeString(&string, &stringNum);
        !           434: 
        !           435:     //
        !           436:     // Create a port number key entry.
        !           437:     //
        !           438: 
        !           439:     stringNum.Length = 0;
        !           440:     stringNum.MaximumLength = 16;
        !           441:     stringNum.Buffer = bufferNum;
        !           442: 
        !           443:     status = RtlIntegerToUnicodeString(Name, 10, &stringNum);
        !           444: 
        !           445:     if (!NT_SUCCESS(status)) {
        !           446:         return status;
        !           447:     }
        !           448: 
        !           449:     //
        !           450:     // Append the prefix and the numeric name.
        !           451:     //
        !           452: 
        !           453:     RtlAppendUnicodeStringToString(&string, &stringNum);
        !           454: 
        !           455:     InitializeObjectAttributes( &objectAttributes,
        !           456:                                 &string,
        !           457:                                 OBJ_CASE_INSENSITIVE,
        !           458:                                 Root,
        !           459:                                 (PSECURITY_DESCRIPTOR) NULL );
        !           460: 
        !           461:     status = ZwCreateKey(NewKey,
        !           462:                         KEY_READ | KEY_WRITE,
        !           463:                         &objectAttributes,
        !           464:                         0,
        !           465:                         (PUNICODE_STRING) NULL,
        !           466:                         REG_OPTION_VOLATILE,
        !           467:                         &disposition );
        !           468: 
        !           469:     return(status);
        !           470: 
        !           471: } // end q117CreateNumericKey
        !           472: 
        !           473: NTSTATUS
        !           474: q117Read(
        !           475:     IN PDEVICE_OBJECT DeviceObject,
        !           476:     IN PIRP Irp
        !           477:     )
        !           478: 
        !           479: /*++
        !           480: 
        !           481: Routine Description:
        !           482: 
        !           483:     This is the tape class driver IO handler routine.
        !           484: 
        !           485: Arguments:
        !           486: 
        !           487:     DeviceObject
        !           488:     Irp - IO request
        !           489: 
        !           490: Return Value:
        !           491: 
        !           492:     NT Status
        !           493: 
        !           494: --*/
        !           495: 
        !           496: {
        !           497: 
        !           498:     PIO_STACK_LOCATION  currentIrpStack;
        !           499:     KIRQL               currentIrql;
        !           500:     STATUS              status;
        !           501:     NTSTATUS            ntStatus;
        !           502:     PVOID               usrBuf;
        !           503:     PQ117_CONTEXT       context;
        !           504:     ULONG               amount;
        !           505:     BOOLEAN             endOfVolume = FALSE;
        !           506: 
        !           507: 
        !           508:     context = DeviceObject->DeviceExtension;
        !           509:     currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
        !           510: 
        !           511:     status = NoErr;
        !           512:     ntStatus = STATUS_SUCCESS;
        !           513: 
        !           514:     //
        !           515:     // If this is the first read,  find the NT volume and read
        !           516:     if (context->CurrentOperation.Type == NoOperation) {
        !           517: 
        !           518:         ntStatus = q117OpenForRead(
        !           519:                     context->CurrentOperation.BytesRead,
        !           520:                     context,
        !           521:                     DeviceObject);
        !           522: 
        !           523:         if (ntStatus == STATUS_NO_DATA_DETECTED) {
        !           524: 
        !           525:             //
        !           526:             // Flag no bytes read (end of media,  end of data,  etc.)
        !           527:             //
        !           528: 
        !           529:             ntStatus = STATUS_SUCCESS;
        !           530:             Irp->IoStatus.Information = 0;
        !           531:             endOfVolume = TRUE;
        !           532: 
        !           533:         }
        !           534: 
        !           535:     }
        !           536: 
        !           537: 
        !           538:     if (NT_SUCCESS(ntStatus)) {
        !           539: 
        !           540:         //
        !           541:         // Return the results of the call to the port driver.
        !           542:         //
        !           543:         usrBuf = MmGetSystemAddressForMdl(Irp->MdlAddress);
        !           544: 
        !           545:         //
        !           546:         // Check to see if user is asking for more data than is there
        !           547:         //  (bytes on tape - current offset)
        !           548:         //
        !           549: 
        !           550:         amount = currentIrpStack->Parameters.Read.Length;
        !           551: 
        !           552:         ntStatus = q117ConvertStatus(
        !           553:             DeviceObject,
        !           554:             q117ReadTape(usrBuf,&amount,context)
        !           555:             );
        !           556: 
        !           557:         //
        !           558:         // Set the amount read to the amount we copied out of the buffer
        !           559:         //
        !           560:         Irp->IoStatus.Information = amount;
        !           561: 
        !           562:         CheckedDump(QIC117SHOWTD,("%x=Read(%x) - Status: %x\n",amount,currentIrpStack->Parameters.Read.Length, status));
        !           563: 
        !           564:     }
        !           565: 
        !           566:     if (endOfVolume && NT_SUCCESS(ntStatus)) {
        !           567: 
        !           568:         status = STATUS_NO_DATA_DETECTED;
        !           569: 
        !           570:     }
        !           571: 
        !           572:     Irp->IoStatus.Status = ntStatus;
        !           573: 
        !           574:     KeRaiseIrql(DISPATCH_LEVEL, &currentIrql);
        !           575:     IoCompleteRequest(Irp, 0);
        !           576:     KeLowerIrql(currentIrql);
        !           577: 
        !           578:     return ntStatus;
        !           579: 
        !           580: 
        !           581: } // end Q117Read()
        !           582: 
        !           583: 
        !           584: NTSTATUS
        !           585: q117Write(
        !           586:     IN PDEVICE_OBJECT DeviceObject,
        !           587:     IN PIRP Irp
        !           588:     )
        !           589: 
        !           590: /*++
        !           591: 
        !           592: Routine Description:
        !           593: 
        !           594:     This is the tape class driver IO handler routine.
        !           595: 
        !           596: Arguments:
        !           597: 
        !           598:     DeviceObject
        !           599:     Irp - IO request
        !           600: 
        !           601: Return Value:
        !           602: 
        !           603:     NT Status
        !           604: 
        !           605: --*/
        !           606: 
        !           607: {
        !           608: 
        !           609:     PIO_STACK_LOCATION  currentIrpStack;
        !           610:     KIRQL               currentIrql;
        !           611:     STATUS              status;
        !           612:     NTSTATUS            ntStatus;
        !           613:     PVOID               usrBuf;
        !           614:     PQ117_CONTEXT       context;
        !           615: 
        !           616:     context = DeviceObject->DeviceExtension;
        !           617:     currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
        !           618: 
        !           619:     //
        !           620:     // Make sure we are in write mode
        !           621:     //
        !           622:     status = q117OpenForWrite(context);
        !           623: 
        !           624:     if (!status) {
        !           625: 
        !           626:         //
        !           627:         // Return the results of the call to the port driver.
        !           628:         //
        !           629:         usrBuf = MmGetSystemAddressForMdl(Irp->MdlAddress);
        !           630: 
        !           631:         status = q117WriteTape(usrBuf,currentIrpStack->Parameters.Write.Length,context);
        !           632:         //
        !           633:         // Set the amount written to the amount we copied out of the buffer
        !           634:         //
        !           635:         if (!status || status == EarlyWarning)
        !           636:             Irp->IoStatus.Information = currentIrpStack->Parameters.Write.Length;
        !           637:     }
        !           638: 
        !           639:     ntStatus = q117ConvertStatus(DeviceObject, status);
        !           640: 
        !           641:     Irp->IoStatus.Status = ntStatus;
        !           642: 
        !           643:     KeRaiseIrql(DISPATCH_LEVEL, &currentIrql);
        !           644:     IoCompleteRequest(Irp, 0);
        !           645:     KeLowerIrql(currentIrql);
        !           646: 
        !           647:     return ntStatus;
        !           648: 
        !           649: } // end Q117Write()
        !           650: 
        !           651: NTSTATUS
        !           652: q117ConvertStatus(
        !           653:     IN PDEVICE_OBJECT DeviceObject,
        !           654:     IN STATUS Status
        !           655:     )
        !           656: {
        !           657:     NTSTATUS            ntStatus;
        !           658:     PQ117_CONTEXT       context;
        !           659:     BOOLEAN             suppressLog = FALSE;
        !           660: 
        !           661:     context = DeviceObject->DeviceExtension;
        !           662: 
        !           663:     switch(Status) {
        !           664:     case NoVols:
        !           665:     case InvalVol:
        !           666:     case EndOfVol:
        !           667:         // or maybe STATUS_END_OF_RECORDED_DATA?
        !           668:         ntStatus = STATUS_NO_DATA_DETECTED;
        !           669:         suppressLog = TRUE;
        !           670:         break;
        !           671: 
        !           672:     case EarlyWarning:
        !           673:         ntStatus = STATUS_END_OF_MEDIA;
        !           674:         suppressLog = TRUE;
        !           675:         break;
        !           676: 
        !           677:     case NoTape:
        !           678:         ntStatus = STATUS_NO_MEDIA_IN_DEVICE;
        !           679:         break;
        !           680: 
        !           681:     case NoErr:
        !           682:         ntStatus = STATUS_SUCCESS;
        !           683:         break;
        !           684: 
        !           685: #ifndef NO_MARKS
        !           686:     case FileMark:
        !           687:     case LongFileMark:
        !           688:     case ShortFileMark:
        !           689:         ntStatus = STATUS_FILEMARK_DETECTED;
        !           690:         suppressLog = TRUE;
        !           691:         break;
        !           692: 
        !           693:     case SetMark:
        !           694:         ntStatus = STATUS_SETMARK_DETECTED;
        !           695:         suppressLog = TRUE;
        !           696:         break;
        !           697: #endif
        !           698: 
        !           699:     case UnknownFormat:
        !           700:     case Unformat:
        !           701:     case BadFmt:
        !           702:         ntStatus = STATUS_UNRECOGNIZED_MEDIA;
        !           703:         break;
        !           704: 
        !           705:     case FMemErr:
        !           706:         ntStatus = STATUS_INSUFFICIENT_RESOURCES;
        !           707:         break;
        !           708: 
        !           709:     case WProt:
        !           710:         ntStatus = STATUS_MEDIA_WRITE_PROTECTED;
        !           711:         break;
        !           712: 
        !           713:     case NewCart:
        !           714:         ntStatus = STATUS_MEDIA_CHANGED;
        !           715:         break;
        !           716: 
        !           717:     case UpdErr:
        !           718:     case BadTape:
        !           719:         ntStatus = STATUS_DATA_ERROR;
        !           720:         break;
        !           721: 
        !           722:     case RdncUnsc:
        !           723:         ntStatus = STATUS_CRC_ERROR;
        !           724:         break;
        !           725: 
        !           726:     default:
        !           727:         CheckedDump(QIC117DBGP,("Error %d reported\n",Status));
        !           728:         ntStatus = (NTSTATUS)(STATUS_SEVERITY_WARNING << 30);
        !           729:         ntStatus |= (FILE_DEVICE_TAPE << 16) & 0x3fff0000;
        !           730:         ntStatus |= Status & 0x0000ffff;
        !           731: 
        !           732:     }
        !           733: 
        !           734:     if (Status != NoErr && !suppressLog) {
        !           735:         NTSTATUS logStatus = q117MapStatus(Status);
        !           736: 
        !           737:         if (logStatus != QIC117_NOTAPE) {
        !           738:             CheckedDump(QIC117SHOWTD,("Error %d logged\n",Status));
        !           739:     
        !           740:             q117LogError(
        !           741:                 DeviceObject,
        !           742:                 context->ErrorSequence++,
        !           743:                 context->MajorFunction,
        !           744:                 0,
        !           745:                 Status,
        !           746:                 ntStatus,
        !           747:                 logStatus
        !           748:                 );
        !           749:         }
        !           750: 
        !           751:     } else {
        !           752: #if DBG
        !           753:         if (Status) {
        !           754:             CheckedDump(QIC117SHOWTD,("Error %d reported to API\n",Status));
        !           755:         }
        !           756: #endif
        !           757:     }
        !           758: 
        !           759:     return ntStatus;
        !           760: }
        !           761: 
        !           762: NTSTATUS q117MapStatus(
        !           763:     IN STATUS Status
        !           764:     )
        !           765: {
        !           766:     NTSTATUS            mapped;
        !           767: 
        !           768:     switch(Status) {
        !           769:         case UnusTape:
        !           770:             mapped = QIC117_UNUSTAPE;
        !           771:             break;
        !           772:         case BadTape:
        !           773:             mapped = QIC117_BADTAPE;
        !           774:             break;
        !           775:         case FMemErr:
        !           776:             mapped = QIC117_FMEMERR;
        !           777:             break;
        !           778:         case TapeFull:
        !           779:             mapped = QIC117_TAPEFULL;
        !           780:             break;
        !           781:         case VolFull:
        !           782:             mapped = QIC117_VOLFULL;
        !           783:             break;
        !           784:         case RdncUnsc:
        !           785:             mapped = QIC117_RDNCUNSC;
        !           786:             break;
        !           787:         case EndOfVol:
        !           788:             mapped = QIC117_ENDOFVOL;
        !           789:             break;
        !           790:         case FCodeErr:
        !           791:             mapped = QIC117_FCODEERR;
        !           792:             break;
        !           793:         case UpdErr:
        !           794:             mapped = QIC117_UPDERR;
        !           795:             break;
        !           796:         case InvalVol:
        !           797:             mapped = QIC117_INVALVOL;
        !           798:             break;
        !           799:         case NoVols:
        !           800:             mapped = QIC117_NOVOLS;
        !           801:             break;
        !           802:         case Unformat:
        !           803:             mapped = QIC117_UNFORMAT;
        !           804:             break;
        !           805:         case UnknownFormat:
        !           806:             mapped = QIC117_UNKNOWNFORMAT;
        !           807:             break;
        !           808:         case BadBlk:
        !           809:             mapped = QIC117_BADBLK;
        !           810:             break;
        !           811:         case EndTapeErr:
        !           812:             mapped = QIC117_ENDTAPEERR;
        !           813:             break;
        !           814:         case DriveFlt:
        !           815:             mapped = QIC117_DRIVEFLT;
        !           816:             break;
        !           817:         case WProt:
        !           818:             mapped = QIC117_WPROT;
        !           819:             break;
        !           820:         case NoTape:
        !           821:             mapped = QIC117_NOTAPE;
        !           822:             break;
        !           823:         case SeekErr:
        !           824:             mapped = QIC117_SEEKERR;
        !           825:             break;
        !           826:         case NoDrive:
        !           827:             mapped = QIC117_NODRIVE;
        !           828:             break;
        !           829:         case InvalCmd:
        !           830:             mapped = QIC117_INVALCMD;
        !           831:             break;
        !           832:         case CodeErr:
        !           833:             mapped = QIC117_CODEERR;
        !           834:             break;
        !           835:         case NECFlt:
        !           836:             mapped = QIC117_NECFLT;
        !           837:             break;
        !           838:         case NoFDC:
        !           839:             mapped = QIC117_NOFDC;
        !           840:             break;
        !           841:         case BadFmt:
        !           842:             mapped = QIC117_BADFMT;
        !           843:             break;
        !           844:         case CmdFlt:
        !           845:             mapped = QIC117_CMDFLT;
        !           846:             break;
        !           847:         case BadNEC:
        !           848:             mapped = QIC117_BADNEC;
        !           849:             break;
        !           850:         case BadReq:
        !           851:             mapped = QIC117_BADREQ;
        !           852:             break;
        !           853:         case TooFast:
        !           854:             mapped = QIC117_TOOFAST;
        !           855:             break;
        !           856:         case NoData:
        !           857:             mapped = QIC117_NODATA;
        !           858:             break;
        !           859:         case DAbort:
        !           860:             mapped = QIC117_DABORT;
        !           861:             break;
        !           862:         case TapeFlt:
        !           863:             mapped = QIC117_TAPEFLT;
        !           864:             break;
        !           865:         case UnspRate:
        !           866:             mapped = QIC117_UNSPRATE;
        !           867:             break;
        !           868:         case Already:
        !           869:             mapped = QIC117_ALREADY;
        !           870:             break;
        !           871:         case TooNoisy:
        !           872:             mapped = QIC117_TOONOISY;
        !           873:             break;
        !           874:         case TimeOut:
        !           875:             mapped = QIC117_TIMEOUT;
        !           876:             break;
        !           877:         case BadMark:
        !           878:             mapped = QIC117_BADMARK;
        !           879:             break;
        !           880:         case NewCart:
        !           881:             mapped = QIC117_NEWCART;
        !           882:             break;
        !           883:         case WrongFmt:
        !           884:             mapped = QIC117_WRONGFMT;
        !           885:             break;
        !           886:         case FmtMisMatch:
        !           887:             mapped = QIC117_FMTMISMATCH;
        !           888:             break;
        !           889:         case IncompTapeFmt:
        !           890:             mapped = QIC117_INCOMPTAPEFMT;
        !           891:             break;
        !           892:         case SCSIFmtMsmtch:
        !           893:             mapped = QIC117_SCSIFMTMSMTCH;
        !           894:             break;
        !           895:         case QIC40InEagle:
        !           896:             mapped = QIC117_QIC40INEAGLE;
        !           897:             break;
        !           898:         case QIC80InEagle:
        !           899:             mapped = QIC117_QIC80INEAGLE;
        !           900:             break;
        !           901:         case ControllerBusy:
        !           902:             mapped = QIC117_CONTROLLERBUSY;
        !           903:             break;
        !           904:         case InQue:
        !           905:             mapped = QIC117_INQUE;
        !           906:             break;
        !           907:         case SplitRequests:
        !           908:             mapped = QIC117_SPLITREQUESTS;
        !           909:             break;
        !           910:         case EarlyWarning:
        !           911:             mapped = QIC117_EARLYWARNING;
        !           912:             break;
        !           913:         default:
        !           914:             mapped = QIC117_BOGUS;
        !           915:     }
        !           916:     return mapped;
        !           917: }
        !           918: 
        !           919: NTSTATUS
        !           920: q117DeviceControl(
        !           921:     IN PDEVICE_OBJECT DeviceObject,
        !           922:     IN PIRP Irp
        !           923:     )
        !           924: 
        !           925: /*++
        !           926: 
        !           927: Routine Description:
        !           928: 
        !           929:     This routine is the dispatcher for device control requests. It
        !           930:     looks at the IOCTL code and calls the appropriate tape device
        !           931:     routine.
        !           932: 
        !           933: Arguments:
        !           934: 
        !           935:     DeviceObject
        !           936:     Irp - Request packet
        !           937: 
        !           938: Return Value:
        !           939: 
        !           940: --*/
        !           941: 
        !           942: {
        !           943:     PIO_STACK_LOCATION  irpStack;
        !           944:     KIRQL               currentIrql;
        !           945:     NTSTATUS            status;
        !           946:     PQ117_CONTEXT       context;
        !           947: 
        !           948:     context = DeviceObject->DeviceExtension;
        !           949:     irpStack = IoGetCurrentIrpStackLocation(Irp);
        !           950: 
        !           951:     status = 0;
        !           952: 
        !           953:     CheckedDump(QIC117SHOWPOLL,("Curmark: %x TotalMarks: %x\n", context->CurrentMark, context->MarkArray.TotalMarks));
        !           954: 
        !           955:     switch (irpStack->Parameters.DeviceIoControl.IoControlCode) {
        !           956: 
        !           957:     case IOCTL_TAPE_GET_DRIVE_PARAMS:
        !           958: 
        !           959:         status = q117IoCtlGetDriveParameters(DeviceObject, Irp);
        !           960:         CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_GET_DRIVE_PARAMS done"));
        !           961:         break;
        !           962: 
        !           963:     case IOCTL_TAPE_SET_DRIVE_PARAMS:
        !           964: 
        !           965:         status = q117IoCtlSetDriveParameters(DeviceObject, Irp);
        !           966:         CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_SET_DRIVE_PARAMS done"));
        !           967:         break;
        !           968: 
        !           969:     case IOCTL_TAPE_GET_MEDIA_PARAMS:
        !           970: 
        !           971:         status = q117IoCtlGetMediaParameters(DeviceObject, Irp);
        !           972:         CheckedDump(QIC117SHOWPOLL,("IOCTL_TAPE_GET_MEDIA_PARAMS done"));
        !           973:         break;
        !           974: 
        !           975:     case IOCTL_TAPE_SET_MEDIA_PARAMS:
        !           976: 
        !           977:         status = q117IoCtlSetMediaParameters(DeviceObject, Irp);
        !           978:         CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_SET_MEDIA_PARAMS done\n"));
        !           979:         break;
        !           980: 
        !           981:     case IOCTL_TAPE_CREATE_PARTITION:
        !           982: 
        !           983:         CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_CREATE_PARTITION attempted\n"));
        !           984:         status = STATUS_INVALID_DEVICE_REQUEST;
        !           985:         break;
        !           986: 
        !           987:     case IOCTL_TAPE_ERASE:
        !           988: 
        !           989:         status = q117IoCtlErase(DeviceObject, Irp);
        !           990:         CheckedDump(QIC117SHOWTD,("Curmark: %x TotalMarks: %x\n", context->CurrentMark, context->MarkArray.TotalMarks));
        !           991:         CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_ERASE done"));
        !           992:         break;
        !           993: 
        !           994:     case IOCTL_TAPE_PREPARE:
        !           995: 
        !           996:         status = q117IoCtlPrepare(DeviceObject, Irp);
        !           997:         CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_PREPARE done"));
        !           998:         break;
        !           999: 
        !          1000:     case IOCTL_TAPE_WRITE_MARKS:
        !          1001: 
        !          1002:         status = q117IoCtlWriteMarks(DeviceObject, Irp);
        !          1003:         CheckedDump(QIC117SHOWTD,("Curmark: %x TotalMarks: %x\n", context->CurrentMark, context->MarkArray.TotalMarks));
        !          1004:         CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_WRITE_MARKS done"));
        !          1005:         break;
        !          1006: 
        !          1007:     case IOCTL_TAPE_GET_POSITION:
        !          1008: 
        !          1009:         status = q117IoCtlGetPosition(DeviceObject, Irp);
        !          1010:         CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_GET_POSITION done"));
        !          1011:         break;
        !          1012: 
        !          1013:     case IOCTL_TAPE_SET_POSITION:
        !          1014: 
        !          1015:         status = q117IoCtlSetPosition(DeviceObject, Irp);
        !          1016:         CheckedDump(QIC117SHOWTD,("Curmark: %x TotalMarks: %x\n", context->CurrentMark, context->MarkArray.TotalMarks));
        !          1017:         CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_SET_POSITION done"));
        !          1018:         break;
        !          1019: 
        !          1020:     case IOCTL_TAPE_GET_STATUS:
        !          1021: 
        !          1022:         status = q117IoCtlGetStatus (DeviceObject, Irp);
        !          1023:         CheckedDump(QIC117SHOWPOLL,("IOCTL_TAPE_GET_STATUS done"));
        !          1024:         break;
        !          1025: 
        !          1026:     case IOCTL_CMS_WRITE_ABS_BLOCK:
        !          1027: 
        !          1028:         status = q117IoCtlWriteAbs(DeviceObject, Irp);
        !          1029:         CheckedDump(QIC117SHOWTD,("IOCTL_CMS_WRITE_ABS_BLOCK done"));
        !          1030:         break;
        !          1031: 
        !          1032:     case IOCTL_CMS_READ_ABS_BLOCK:
        !          1033: 
        !          1034:         status = q117IoCtlReadAbs(DeviceObject, Irp);
        !          1035:         CheckedDump(QIC117SHOWTD,("IOCTL_CMS_READ_ABS_BLOCK done"));
        !          1036:         break;
        !          1037: 
        !          1038: 
        !          1039:     default:
        !          1040: 
        !          1041:         status = STATUS_INVALID_DEVICE_REQUEST;
        !          1042: 
        !          1043:     } // end switch()
        !          1044: 
        !          1045:     //
        !          1046:     // Complete the request.
        !          1047:     //
        !          1048: 
        !          1049:     CheckedDump(QIC117SHOWTD,(" -- Status:  %x\n",status));
        !          1050:     Irp->IoStatus.Status = status;
        !          1051: 
        !          1052:     KeRaiseIrql(DISPATCH_LEVEL, &currentIrql);
        !          1053:     IoCompleteRequest(Irp, 2);
        !          1054:     KeLowerIrql(currentIrql);
        !          1055: 
        !          1056:     return status;
        !          1057: 
        !          1058: } // end Q117DeviceControl()
        !          1059: 
        !          1060: 
        !          1061: NTSTATUS
        !          1062: q117Create (
        !          1063:     IN PDEVICE_OBJECT DeviceObject,
        !          1064:     IN PIRP Irp
        !          1065:     )
        !          1066: 
        !          1067: /*++
        !          1068: 
        !          1069: Routine Description:
        !          1070: 
        !          1071:     This routine handles CREATE/OPEN requests and does
        !          1072:     nothing more than return successful status.
        !          1073: 
        !          1074: Arguments:
        !          1075: 
        !          1076:     DeviceObject
        !          1077:     Irp
        !          1078: 
        !          1079: Return Value:
        !          1080: 
        !          1081:     NT Status
        !          1082: 
        !          1083: --*/
        !          1084: 
        !          1085: {
        !          1086:     KIRQL currentIrql;
        !          1087:     PQ117_CONTEXT     context;
        !          1088:     NTSTATUS ntStatus;
        !          1089: 
        !          1090:     context = DeviceObject->DeviceExtension;
        !          1091: 
        !          1092:     if (!context->DriverOpened) {
        !          1093: 
        !          1094:         ntStatus = q117ConvertStatus(DeviceObject, q117Start(context));
        !          1095: 
        !          1096:         //
        !          1097:         // If everything went OK,  then flag that the driver is now open
        !          1098:         //
        !          1099:         if (NT_SUCCESS(ntStatus)) {
        !          1100:             context->DriverOpened = TRUE;
        !          1101:         } else {
        !          1102:             q117Stop(context);
        !          1103:         }
        !          1104: 
        !          1105:     } else {
        !          1106: 
        !          1107:         ntStatus = STATUS_DEVICE_BUSY;
        !          1108: 
        !          1109:     }
        !          1110: 
        !          1111:     Irp->IoStatus.Status = ntStatus;
        !          1112: 
        !          1113:     KeRaiseIrql(DISPATCH_LEVEL, &currentIrql);
        !          1114:     IoCompleteRequest(Irp, 0);
        !          1115:     KeLowerIrql(currentIrql);
        !          1116: 
        !          1117:     return ntStatus;
        !          1118: 
        !          1119: } // end Q117Create()
        !          1120: 
        !          1121: NTSTATUS
        !          1122: q117Close (
        !          1123:     IN PDEVICE_OBJECT DeviceObject,
        !          1124:     IN PIRP Irp
        !          1125:     )
        !          1126: 
        !          1127: /*++
        !          1128: 
        !          1129: Routine Description:
        !          1130: 
        !          1131: 
        !          1132: Arguments:
        !          1133: 
        !          1134:     DeviceObject
        !          1135:     Irp
        !          1136: 
        !          1137: Return Value:
        !          1138: 
        !          1139:     NT Status
        !          1140: 
        !          1141: --*/
        !          1142: 
        !          1143: {
        !          1144:     KIRQL currentIrql;
        !          1145:     PQ117_CONTEXT     context;
        !          1146:     NTSTATUS ntStatus;
        !          1147: 
        !          1148:     context = DeviceObject->DeviceExtension;
        !          1149: 
        !          1150:     ntStatus = q117ConvertStatus(DeviceObject, q117Stop(context));
        !          1151: 
        !          1152:     context->DriverOpened = FALSE;
        !          1153: 
        !          1154:     Irp->IoStatus.Status = ntStatus;
        !          1155: 
        !          1156:     KeRaiseIrql(DISPATCH_LEVEL, &currentIrql);
        !          1157:     IoCompleteRequest(Irp, 0);
        !          1158:     KeLowerIrql(currentIrql);
        !          1159: 
        !          1160:     return ntStatus;
        !          1161: 
        !          1162: } // end Q117Close()
        !          1163: 
        !          1164: VOID
        !          1165: q117LogError(
        !          1166:     IN PDEVICE_OBJECT DeviceObject,
        !          1167:     IN ULONG SequenceNumber,
        !          1168:     IN UCHAR MajorFunctionCode,
        !          1169:     IN UCHAR RetryCount,
        !          1170:     IN ULONG UniqueErrorValue,
        !          1171:     IN NTSTATUS FinalStatus,
        !          1172:     IN NTSTATUS SpecificIOStatus
        !          1173:     )
        !          1174: 
        !          1175: /*++
        !          1176: 
        !          1177: Routine Description:
        !          1178: 
        !          1179:     This routine allocates an error log entry, copies the supplied data
        !          1180:     to it, and requests that it be written to the error log file.
        !          1181: 
        !          1182: Arguments:
        !          1183: 
        !          1184:     DeviceObject - a pointer to the device object associated with the
        !          1185:     device that had the error.
        !          1186: 
        !          1187:     SequenceNumber - A ulong value that is unique to an IRP over the
        !          1188:     life of the irp in this driver - 0 generally means an error not
        !          1189:     associated with an irp.
        !          1190: 
        !          1191:     MajorFunctionCode - If there is an error associated with the irp,
        !          1192:     this is the major function code of that irp.
        !          1193: 
        !          1194:     RetryCount - The number of times a particular operation has been
        !          1195:     retried.
        !          1196: 
        !          1197:     UniqueErrorValue - A unique long word that identifies the particular
        !          1198:     call to this function.
        !          1199: 
        !          1200:     FinalStatus - The final status given to the irp that was associated
        !          1201:     with this error.  If this log entry is being made during one of
        !          1202:     the retries this value will be STATUS_SUCCESS.
        !          1203: 
        !          1204:     SpecificIOStatus - The IO status for a particular error.
        !          1205: 
        !          1206: Return Value:
        !          1207: 
        !          1208:     None.
        !          1209: 
        !          1210: --*/
        !          1211: 
        !          1212: {
        !          1213:     PIO_ERROR_LOG_PACKET errorLogEntry;
        !          1214: 
        !          1215:     errorLogEntry = IoAllocateErrorLogEntry(
        !          1216:                         DeviceObject,
        !          1217:                         sizeof(IO_ERROR_LOG_PACKET)
        !          1218:                         );
        !          1219: 
        !          1220:     if ( errorLogEntry != NULL ) {
        !          1221:         errorLogEntry->ErrorCode = SpecificIOStatus;
        !          1222:         errorLogEntry->SequenceNumber = SequenceNumber;
        !          1223:         errorLogEntry->MajorFunctionCode = MajorFunctionCode;
        !          1224:         errorLogEntry->RetryCount = RetryCount;
        !          1225:         errorLogEntry->UniqueErrorValue = UniqueErrorValue;
        !          1226:         errorLogEntry->FinalStatus = FinalStatus;
        !          1227:         errorLogEntry->DumpDataSize = 0;
        !          1228:         IoWriteErrorLogEntry(errorLogEntry);
        !          1229: 
        !          1230:     }
        !          1231: 
        !          1232: }
        !          1233: #ifdef NOT_NOW
        !          1234: 
        !          1235: VOID
        !          1236: q117Cancel(
        !          1237:     IN PDEVICE_OBJECT DeviceObject,
        !          1238:     IN PIRP Irp
        !          1239:     )
        !          1240: 
        !          1241: /*++
        !          1242: 
        !          1243: Routine Description:
        !          1244: 
        !          1245:     This routine is called from the I/O system when a request is cancelled.
        !          1246: 
        !          1247:     N.B.  The cancel spinlock is already held upon entry to this routine.
        !          1248: 
        !          1249: Arguments:
        !          1250: 
        !          1251:     DeviceObject - Pointer to class device object.
        !          1252: 
        !          1253:     Irp - Pointer to the request packet to be cancelled.
        !          1254: 
        !          1255: Return Value:
        !          1256: 
        !          1257:     None.
        !          1258: 
        !          1259: --*/
        !          1260: 
        !          1261: {
        !          1262: 
        !          1263:     CheckedDump(QIC117INFO,("q117Cancel: enter\n"));
        !          1264: 
        !          1265:     if (Irp == DeviceObject->CurrentIrp) {
        !          1266: 
        !          1267:         //
        !          1268:         // The current request is being cancelled.  Set the CurrentIrp to
        !          1269:         // null and release the cancel spinlock before starting the next packet.
        !          1270:         //
        !          1271: 
        !          1272:         DeviceObject->CurrentIrp = NULL;
        !          1273:         IoReleaseCancelSpinLock(Irp->CancelIrql);
        !          1274:         IoStartNextPacket(DeviceObject, TRUE);
        !          1275: 
        !          1276:     } else {
        !          1277: 
        !          1278:         //
        !          1279:         // Cancel a request in the device queue.  Remove it from queue and
        !          1280:         // release the cancel spinlock.
        !          1281:         //
        !          1282: 
        !          1283:         if (TRUE != KeRemoveEntryDeviceQueue(
        !          1284:                         &DeviceObject->DeviceQueue,
        !          1285:                         &Irp->Tail.Overlay.DeviceQueueEntry
        !          1286:                         )) {
        !          1287:             CheckedDump(QIC117SHOWTD,(
        !          1288:                 "q117Cancel: Irp 0x%x not in device queue?!?\n",
        !          1289:                 Irp
        !          1290:                 ));
        !          1291:         }
        !          1292:         IoReleaseCancelSpinLock(Irp->CancelIrql);
        !          1293:     }
        !          1294: 
        !          1295:     //
        !          1296:     // Complete the request with STATUS_CANCELLED.
        !          1297:     //
        !          1298: 
        !          1299:     Irp->IoStatus.Status = STATUS_CANCELLED;
        !          1300:     Irp->IoStatus.Information = 0;
        !          1301:     IoCompleteRequest (Irp, IO_NO_INCREMENT);
        !          1302: 
        !          1303:     CheckedDump(QIC117INFO,("q117Cancel: exit\n"));
        !          1304: 
        !          1305:     return;
        !          1306: }
        !          1307: #endif
        !          1308: 
        !          1309: NTSTATUS
        !          1310: q117Cleanup(
        !          1311:     IN PDEVICE_OBJECT DeviceObject,
        !          1312:     IN PIRP Irp
        !          1313:     )
        !          1314: 
        !          1315: /*++
        !          1316: 
        !          1317: Routine Description:
        !          1318: 
        !          1319:     This routine is the dispatch routine for cleanup requests.
        !          1320:     All queued q117 requests are completed with STATUS_CANCELLED,
        !          1321:     and the lower level driver's queue is cleared.
        !          1322: 
        !          1323: Arguments:
        !          1324: 
        !          1325:     DeviceObject - Pointer to class device object.
        !          1326: 
        !          1327:     Irp - Pointer to the request packet.
        !          1328: 
        !          1329: Return Value:
        !          1330: 
        !          1331:     Status is returned.
        !          1332: 
        !          1333: --*/
        !          1334: 
        !          1335: {
        !          1336:     KIRQL currentIrql;
        !          1337:     KIRQL cancelIrql;
        !          1338:     PKDEVICE_QUEUE_ENTRY packet;
        !          1339:     PIRP  currentIrp;
        !          1340: 
        !          1341:     CheckedDump(QIC117INFO,("q117Cleanup: enter\n"));
        !          1342: 
        !          1343:     /* clear everything from the low-level driver */
        !          1344:     q117ClearQueue(
        !          1345:         DeviceObject->DeviceExtension
        !          1346:         );
        !          1347:     //
        !          1348:     // Raise IRQL to DISPATCH_LEVEL.
        !          1349:     //
        !          1350: 
        !          1351:     KeRaiseIrql(DISPATCH_LEVEL, &currentIrql);
        !          1352: 
        !          1353:     //
        !          1354:     // Acquire the cancel spinlock.
        !          1355:     //
        !          1356: 
        !          1357:     IoAcquireCancelSpinLock(&cancelIrql);
        !          1358: 
        !          1359:     //
        !          1360:     // Complete all queued requests with STATUS_CANCELLED.
        !          1361:     // Start with the real CurrentIrp, and run down the list of requests in the
        !          1362:     // device queue.  Be sure to set the real CurrentIrp to NULL, so that
        !          1363:     // the interrupt service callback routine won't attempt to complete it.
        !          1364:     //
        !          1365: 
        !          1366:     currentIrp = DeviceObject->CurrentIrp;
        !          1367:     DeviceObject->CurrentIrp = NULL;
        !          1368: 
        !          1369:     while (currentIrp != NULL) {
        !          1370: 
        !          1371:         //
        !          1372:         // Remove the CurrentIrp from the cancellable state.
        !          1373:         //
        !          1374:         //
        !          1375: 
        !          1376:         IoSetCancelRoutine(currentIrp, NULL);
        !          1377: 
        !          1378:         //
        !          1379:         // Set Status to CANCELLED, release the cancel spinlock,
        !          1380:         // and complete the request.  Note that the IRQL is reset to
        !          1381:         // DISPATCH_LEVEL when we release the cancel spinlock.
        !          1382:         //
        !          1383: 
        !          1384:         currentIrp->IoStatus.Status = STATUS_CANCELLED;
        !          1385:         currentIrp->IoStatus.Information = 0;
        !          1386: 
        !          1387:         IoReleaseCancelSpinLock(cancelIrql);
        !          1388:         IoCompleteRequest(currentIrp, IO_NO_INCREMENT);
        !          1389: 
        !          1390:         //
        !          1391:         // Reacquire the cancel spinlock.
        !          1392:         //
        !          1393: 
        !          1394:         IoAcquireCancelSpinLock(&cancelIrql);
        !          1395: 
        !          1396:         //
        !          1397:         // Dequeue the next packet (IRP) from the device work queue.
        !          1398:         //
        !          1399: 
        !          1400:         packet = KeRemoveDeviceQueue(&DeviceObject->DeviceQueue);
        !          1401:         if (packet != NULL) {
        !          1402:             currentIrp =
        !          1403:                 CONTAINING_RECORD(packet, IRP, Tail.Overlay.DeviceQueueEntry);
        !          1404:         } else {
        !          1405:             currentIrp = (PIRP) NULL;
        !          1406:         }
        !          1407:     } // end while
        !          1408: 
        !          1409:     //
        !          1410:     // Release the cancel spinlock and lower IRQL.
        !          1411:     //
        !          1412: 
        !          1413:     IoReleaseCancelSpinLock(cancelIrql);
        !          1414:     KeLowerIrql(currentIrql);
        !          1415: 
        !          1416:     //
        !          1417:     // Complete the cleanup request with STATUS_SUCCESS.
        !          1418:     //
        !          1419: 
        !          1420:     Irp->IoStatus.Status = STATUS_SUCCESS;
        !          1421:     Irp->IoStatus.Information = 0;
        !          1422:     IoCompleteRequest (Irp, IO_NO_INCREMENT);
        !          1423: 
        !          1424:     CheckedDump(QIC117INFO,("q117Cleanup: exit\n"));
        !          1425: 
        !          1426:     return(STATUS_SUCCESS);
        !          1427: 
        !          1428: }
        !          1429: 

unix.superglobalmegacorp.com

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