Annotation of ntddk/src/scsi/scsitape/4mmdat/4mmdat.c, revision 1.1

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1992  Microsoft Corporation
        !             4: 
        !             5: Module Name:
        !             6: 
        !             7:     4mmdat.c
        !             8: 
        !             9: Abstract:
        !            10: 
        !            11:     This module contains the device-specific routines for the Archive
        !            12:     Python DDS, DDS-DC, and Turbo-Speed DDS-DC DAT tape drives, the
        !            13:     HP 35470A DDS and 35480A DDS-DC DAT tape drives, the WangDAT
        !            14:     Model 3200 DDS-DC DAT tape drive, and the Compaq DDS-DC DAT tape
        !            15:     drive.
        !            16: 
        !            17: Author:
        !            18: 
        !            19:     Mike Glass
        !            20:     Hunter Small (Maynard)
        !            21:     Lori Brown (Maynard)
        !            22:     Chris Hugh Sam (Maynard)
        !            23: 
        !            24: Environment:
        !            25: 
        !            26:     kernel mode only
        !            27: 
        !            28: Revision History:
        !            29: 
        !            30: --*/
        !            31: 
        !            32: #include "ntddk.h"
        !            33: #include "tape.h"
        !            34: #include "4mmdat.h"
        !            35: 
        !            36: static ULONG gb_PartitionCount;
        !            37: static UCHAR gb_VendorId[8];
        !            38: static UCHAR gb_ProductId[16];
        !            39: 
        !            40: //
        !            41: //  Internal (module wide) defines that symbolize
        !            42: //  the 4mm DAT drives supported by this module.
        !            43: //
        !            44: #define ARCHIVE_PYTHON   1 ;
        !            45: #define DEC_TLZ06        2 ;
        !            46: #define EXABYTE_4200     3 ;
        !            47: #define EXABYTE_4200C    4 ;
        !            48: #define HP_35470A        5 ;
        !            49: #define HP_35480A        6 ;
        !            50: #define HP_IBM35480A     7 ;
        !            51: #define WANGDAT_1300     8 ;
        !            52: #define WANGDAT_3100     9 ;
        !            53: #define WANGDAT_3200    10 ;
        !            54: 
        !            55: //
        !            56: //  Function prototype(s) for internal function(s)
        !            57: //
        !            58: static  ULONG  WhichIsIt(IN PINQUIRYDATA InquiryData);
        !            59: 
        !            60: 
        !            61: NTSTATUS
        !            62: TapeCreatePartition(
        !            63:     IN PDEVICE_OBJECT DeviceObject,
        !            64:     IN PIRP Irp
        !            65:     )
        !            66: 
        !            67: /*++
        !            68: Routine Description:
        !            69: 
        !            70:     This routine creates initiator-defined partitions on the tape.
        !            71: 
        !            72: Arguments:
        !            73: 
        !            74:     DeviceObject
        !            75:     Irp
        !            76: 
        !            77: Return Value:
        !            78: 
        !            79:     NTSTATUS
        !            80: 
        !            81: --*/
        !            82: 
        !            83: {
        !            84:     PDEVICE_EXTENSION      deviceExtension = DeviceObject->DeviceExtension;
        !            85:     PTAPE_CREATE_PARTITION tapePartition = Irp->AssociatedIrp.SystemBuffer;
        !            86:     PMODE_MEDIUM_PART_PAGE buffer;
        !            87:     SCSI_REQUEST_BLOCK     srb;
        !            88:     PCDB                   cdb = (PCDB)srb.Cdb;
        !            89:     NTSTATUS               status;
        !            90: 
        !            91:     //
        !            92:     // Zero CDB in SRB on stack.
        !            93:     //
        !            94: 
        !            95:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !            96: 
        !            97:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !            98: 
        !            99:     cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
        !           100: 
        !           101:     //
        !           102:     // Set timeout value.
        !           103:     //
        !           104: 
        !           105:     srb.TimeOutValue = 8000;
        !           106: 
        !           107:     cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_MEDIUM_PART_PAGE);
        !           108:     cdb->MODE_SELECT.PFBit = 1;
        !           109: 
        !           110:     buffer = ExAllocatePool(NonPagedPoolCacheAligned,
        !           111:         sizeof(MODE_MEDIUM_PART_PAGE));
        !           112: 
        !           113:     if (!buffer) {
        !           114:         return STATUS_INSUFFICIENT_RESOURCES;
        !           115:     }
        !           116: 
        !           117:     RtlZeroMemory(buffer, sizeof(MODE_MEDIUM_PART_PAGE));
        !           118: 
        !           119:     buffer->ParameterListHeader.DeviceSpecificParameter = 0x10;
        !           120: 
        !           121:     buffer->MediumPartPage.PageCode = MODE_PAGE_MEDIUM_PARTITION;
        !           122: 
        !           123:     if (tapePartition->Count != 1 && tapePartition->Count != 2) {
        !           124:         DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n"));
        !           125:         ExFreePool(buffer);
        !           126:         return STATUS_INVALID_DEVICE_REQUEST;
        !           127:     }
        !           128: 
        !           129:     buffer->MediumPartPage.AdditionalPartitionDefined = tapePartition->Count - 1;
        !           130: 
        !           131:     switch (tapePartition->Method) {
        !           132:         case TAPE_FIXED_PARTITIONS:
        !           133:             if (RtlCompareMemory(gb_VendorId,"WangDAT ",8) == 8) {
        !           134:                 DebugPrint((3,"TapeIoControl: Create Fixed Tape Partitions\n"));
        !           135:                 buffer->MediumPartPage.FDPBit = SETBITON;
        !           136:                 buffer->MediumPartPage.PageLength = 0x0A;
        !           137:             } else {
        !           138:                 DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n"));
        !           139:                 ExFreePool(buffer);
        !           140:                 return STATUS_INVALID_DEVICE_REQUEST;
        !           141:             }
        !           142:             break;
        !           143: 
        !           144:         case TAPE_SELECT_PARTITIONS:
        !           145:             if (RtlCompareMemory(gb_VendorId,"WangDAT ",8) == 8) {
        !           146:                 DebugPrint((3,"TapeIoControl: Create Select Tape Partitions\n"));
        !           147:                 buffer->MediumPartPage.SDPBit = SETBITON;
        !           148:                 buffer->MediumPartPage.PageLength = 0x0A;
        !           149:             } else {
        !           150:                 DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n"));
        !           151:                 ExFreePool(buffer);
        !           152:                 return STATUS_INVALID_DEVICE_REQUEST;
        !           153:             }
        !           154:             break;
        !           155: 
        !           156:         case TAPE_INITIATOR_PARTITIONS:
        !           157:             DebugPrint((3,"TapeIoControl: Create Initiator Defined Tape Partitions\n"));
        !           158:             buffer->MediumPartPage.IDPBit = SETBITON;
        !           159: 
        !           160:             if (buffer->MediumPartPage.AdditionalPartitionDefined) {
        !           161:                 if (RtlCompareMemory(gb_VendorId,"WangDAT ",8) == 8) {
        !           162:                     buffer->MediumPartPage.PageLength = 0x0A;
        !           163: 
        !           164:                     buffer->MediumPartPage.Partition1Size[0] =
        !           165:                         ((tapePartition->Size >> 8) & 0xFF);
        !           166:                     buffer->MediumPartPage.Partition1Size[1] =
        !           167:                         (tapePartition->Size & 0xFF);
        !           168: 
        !           169:                     buffer->MediumPartPage.PSUMBit = 2;
        !           170:                 } else {
        !           171:                     buffer->MediumPartPage.PageLength = 0x08;
        !           172:                     cdb->MODE_SELECT.ParameterListLength -= 2;
        !           173: 
        !           174:                     buffer->MediumPartPage.Partition0Size[0] =
        !           175:                         ((tapePartition->Size >> 8) & 0xFF);
        !           176:                     buffer->MediumPartPage.Partition0Size[1] =
        !           177:                         (tapePartition->Size & 0xFF);
        !           178: 
        !           179:                     buffer->MediumPartPage.PSUMBit = 2;
        !           180:                 }
        !           181:             } else {
        !           182:                 if (RtlCompareMemory(gb_VendorId,"WangDAT ",8) == 8) {
        !           183:                     buffer->MediumPartPage.PageLength = 0x0A;
        !           184:                 } else {
        !           185:                     buffer->MediumPartPage.PageLength = 0x06;
        !           186:                     cdb->MODE_SELECT.ParameterListLength -= 4;
        !           187:                 }
        !           188:             }
        !           189: 
        !           190:             break;
        !           191: 
        !           192:         default:
        !           193:             DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n"));
        !           194:             ExFreePool(buffer);
        !           195:             return STATUS_INVALID_DEVICE_REQUEST;
        !           196:     }
        !           197: 
        !           198:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           199:                                 &srb,
        !           200:                                 buffer,
        !           201:                                 cdb->MODE_SELECT.ParameterListLength,
        !           202:                                 TRUE);
        !           203: 
        !           204:     ExFreePool(buffer);
        !           205: 
        !           206:     return status;
        !           207: 
        !           208: } // end TapeCreatePartition()
        !           209: 
        !           210: 
        !           211: NTSTATUS
        !           212: TapeErase(
        !           213:     IN PDEVICE_OBJECT DeviceObject,
        !           214:     IN PIRP Irp
        !           215:     )
        !           216: 
        !           217: /*++
        !           218: Routine Description:
        !           219: 
        !           220:     This routine erases the current partition of the device by writing an
        !           221:     end-of-recorded data marker beginning at the current position.
        !           222: 
        !           223: Arguments:
        !           224: 
        !           225:     DeviceObject
        !           226:     Irp
        !           227: 
        !           228: Return Value:
        !           229: 
        !           230:     NTSTATUS
        !           231: 
        !           232: --*/
        !           233: 
        !           234: {
        !           235:     PDEVICE_EXTENSION   deviceExtension = DeviceObject->DeviceExtension;
        !           236:     PTAPE_ERASE         tapeErase = Irp->AssociatedIrp.SystemBuffer;
        !           237:     SCSI_REQUEST_BLOCK  srb;
        !           238:     PCDB                cdb = (PCDB)srb.Cdb;
        !           239:     NTSTATUS            status;
        !           240: 
        !           241:     //
        !           242:     // Zero CDB in SRB on stack.
        !           243:     //
        !           244: 
        !           245:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           246: 
        !           247:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !           248: 
        !           249:     cdb->ERASE.OperationCode = SCSIOP_ERASE;
        !           250: 
        !           251:     //
        !           252:     // Set timeout value.
        !           253:     //
        !           254: 
        !           255:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !           256: 
        !           257:     if (tapeErase->Type != TAPE_ERASE_SHORT) {
        !           258:         DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n"));
        !           259:         return STATUS_INVALID_DEVICE_REQUEST;
        !           260:     }
        !           261: 
        !           262:     DebugPrint((3,"TapeIoControl: Short Erase Tape\n"));
        !           263: 
        !           264:     //
        !           265:     // Set immediate bit if indicated.
        !           266:     //
        !           267: 
        !           268:     cdb->ERASE.Immediate = tapeErase->Immediate;
        !           269: 
        !           270:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           271:                                 &srb,
        !           272:                                 NULL,
        !           273:                                 0,
        !           274:                                 FALSE);
        !           275: 
        !           276:     return status;
        !           277: 
        !           278: } // end TapeErase()
        !           279: 
        !           280: 
        !           281: 
        !           282: VOID
        !           283: TapeError(
        !           284:     PDEVICE_OBJECT DeviceObject,
        !           285:     PSCSI_REQUEST_BLOCK Srb,
        !           286:     NTSTATUS *Status,
        !           287:     BOOLEAN *Retry
        !           288:     )
        !           289: 
        !           290: /*++
        !           291: 
        !           292: Routine Description:
        !           293: 
        !           294:     When a request completes with error, the routine InterpretSenseInfo is
        !           295:     called to determine from the sense data whether the request should be
        !           296:     retried and what NT status to set in the IRP. Then this routine is called
        !           297:     for tape requests to handle tape-specific errors and update the nt status
        !           298:     and retry boolean.
        !           299: 
        !           300: Arguments:
        !           301: 
        !           302:     DeviceObject - Supplies a pointer to the device object.
        !           303: 
        !           304:     Srb - Supplies a pointer to the failing Srb.
        !           305: 
        !           306:     Status - NT Status used to set the IRP's completion status.
        !           307: 
        !           308:     Retry - Indicates that this request should be retried.
        !           309: 
        !           310: Return Value:
        !           311: 
        !           312:     None.
        !           313: 
        !           314: --*/
        !           315: 
        !           316: {
        !           317:     PDEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
        !           318:     PSENSE_DATA        senseBuffer = Srb->SenseInfoBuffer;
        !           319:     NTSTATUS           status = *Status;
        !           320:     BOOLEAN            retry = *Retry;
        !           321:     UCHAR              adsenseq = senseBuffer->AdditionalSenseCodeQualifier;
        !           322:     UCHAR              adsense = senseBuffer->AdditionalSenseCode;
        !           323: 
        !           324:     if (status == STATUS_DEVICE_NOT_READY) {
        !           325:         if ((adsense == SCSI_ADSENSE_LUN_NOT_READY) &&
        !           326:             (adsenseq == SCSI_SENSEQ_BECOMING_READY) ) {
        !           327: 
        !           328:             *Status = STATUS_NO_MEDIA;
        !           329:             *Retry = FALSE;
        !           330: 
        !           331:         }
        !           332:     }
        !           333:     return;
        !           334: 
        !           335: } // end TapeError()
        !           336: 
        !           337: 
        !           338: NTSTATUS
        !           339: TapeGetDriveParameters(
        !           340:     IN PDEVICE_OBJECT DeviceObject,
        !           341:     IN PIRP Irp
        !           342:     )
        !           343: 
        !           344: /*++
        !           345: Routine Description:
        !           346: 
        !           347:     This routine returns an indication if reporting setmarks is disabled or
        !           348:     enabled, the default fixed-block size, the maximum block size, the
        !           349:     minimum block size, the maximum number of partitions, and the device
        !           350:     features flag.
        !           351: 
        !           352: Arguments:
        !           353: 
        !           354:     DeviceObject
        !           355:     Irp
        !           356: 
        !           357: Return Value:
        !           358: 
        !           359:     NTSTATUS
        !           360: 
        !           361: --*/
        !           362: 
        !           363: {
        !           364:     PDEVICE_EXTENSION          deviceExtension = DeviceObject->DeviceExtension;
        !           365:     PTAPE_GET_DRIVE_PARAMETERS tapeGetDriveParams = Irp->AssociatedIrp.SystemBuffer;
        !           366:     PMODE_DEVICE_CONFIG_PAGE   buffer;
        !           367:     PREAD_BLOCK_LIMITS_DATA    blockLimits;
        !           368:     SCSI_REQUEST_BLOCK         srb;
        !           369:     PCDB                       cdb = (PCDB)srb.Cdb;
        !           370:     NTSTATUS                   status;
        !           371:     PMODE_DATA_COMPRESS_PAGE   dcbuff;
        !           372: 
        !           373:     DebugPrint((3,"TapeIoControl: Get Tape Drive Parameters\n"));
        !           374: 
        !           375:     //
        !           376:     // Zero CDB in SRB on stack.
        !           377:     //
        !           378: 
        !           379:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           380: 
        !           381:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !           382: 
        !           383:     cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
        !           384: 
        !           385:     //
        !           386:     // Set timeout value.
        !           387:     //
        !           388: 
        !           389:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !           390: 
        !           391:     cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DEVICE_CONFIG_PAGE);
        !           392:     cdb->MODE_SENSE.Dbd = SETBITON;
        !           393:     cdb->MODE_SENSE.PageCode = MODE_PAGE_DEVICE_CONFIG;
        !           394: 
        !           395:     buffer = ExAllocatePool(NonPagedPoolCacheAligned,
        !           396:         sizeof(MODE_DEVICE_CONFIG_PAGE));
        !           397: 
        !           398:     if (!buffer) {
        !           399:         return STATUS_INSUFFICIENT_RESOURCES;
        !           400:     }
        !           401: 
        !           402:     RtlZeroMemory(buffer, sizeof(MODE_DEVICE_CONFIG_PAGE));
        !           403: 
        !           404:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           405:                                 &srb,
        !           406:                                 buffer,
        !           407:                                 sizeof( MODE_DEVICE_CONFIG_PAGE ),
        !           408:                                 FALSE);
        !           409: 
        !           410:     if (NT_SUCCESS(status)) {
        !           411:         Irp->IoStatus.Information = sizeof(TAPE_GET_DRIVE_PARAMETERS);
        !           412: 
        !           413:         tapeGetDriveParams->ECC = 0;
        !           414:         tapeGetDriveParams->DataPadding = 0;
        !           415:         tapeGetDriveParams->Compression = 0;
        !           416:         tapeGetDriveParams->ReportSetmarks = (buffer->DeviceConfigPage.RSmk ? 1 : 0 );
        !           417:         tapeGetDriveParams->DefaultBlockSize = 0x200;
        !           418:         tapeGetDriveParams->MaximumPartitionCount = 2;
        !           419: 
        !           420:         tapeGetDriveParams->FeaturesLow =
        !           421:             TAPE_DRIVE_INITIATOR |
        !           422:             TAPE_DRIVE_ERASE_SHORT |
        !           423:             TAPE_DRIVE_ERASE_BOP_ONLY |
        !           424:             TAPE_DRIVE_ERASE_IMMEDIATE |
        !           425:             TAPE_DRIVE_TAPE_CAPACITY |
        !           426:             TAPE_DRIVE_FIXED_BLOCK |
        !           427:             TAPE_DRIVE_VARIABLE_BLOCK |
        !           428:             TAPE_DRIVE_WRITE_PROTECT |
        !           429:             TAPE_DRIVE_REPORT_SMKS |
        !           430:             TAPE_DRIVE_GET_ABSOLUTE_BLK |
        !           431:             TAPE_DRIVE_GET_LOGICAL_BLK;
        !           432: 
        !           433:         tapeGetDriveParams->FeaturesHigh =
        !           434:             TAPE_DRIVE_LOAD_UNLOAD |
        !           435:             TAPE_DRIVE_LOCK_UNLOCK |
        !           436:             TAPE_DRIVE_REWIND_IMMEDIATE |
        !           437:             TAPE_DRIVE_SET_BLOCK_SIZE |
        !           438:             TAPE_DRIVE_LOAD_UNLD_IMMED |
        !           439:             TAPE_DRIVE_SET_REPORT_SMKS |
        !           440:             TAPE_DRIVE_ABSOLUTE_BLK |
        !           441:             TAPE_DRIVE_ABS_BLK_IMMED |
        !           442:             TAPE_DRIVE_LOGICAL_BLK |
        !           443:             TAPE_DRIVE_END_OF_DATA |
        !           444:             TAPE_DRIVE_RELATIVE_BLKS |
        !           445:             TAPE_DRIVE_FILEMARKS |
        !           446:             TAPE_DRIVE_SEQUENTIAL_FMKS |
        !           447:             TAPE_DRIVE_SETMARKS |
        !           448:             TAPE_DRIVE_REVERSE_POSITION |
        !           449:             TAPE_DRIVE_WRITE_SETMARKS |
        !           450:             TAPE_DRIVE_WRITE_FILEMARKS |
        !           451:             TAPE_DRIVE_WRITE_MARK_IMMED;
        !           452: 
        !           453:         if (RtlCompareMemory(gb_VendorId,"WangDAT ",8) == 8) {
        !           454:             tapeGetDriveParams->FeaturesLow |=
        !           455:                 TAPE_DRIVE_FIXED |
        !           456:                 TAPE_DRIVE_SELECT;
        !           457:             tapeGetDriveParams->FeaturesHigh |=
        !           458:                 TAPE_DRIVE_LOG_BLK_IMMED |
        !           459:                 TAPE_DRIVE_SEQUENTIAL_SMKS;
        !           460:         } else if (RtlCompareMemory(gb_VendorId,"HP      ",8) == 8) {
        !           461:             tapeGetDriveParams->FeaturesHigh |=
        !           462:                 TAPE_DRIVE_LOG_BLK_IMMED |
        !           463:                 TAPE_DRIVE_SEQUENTIAL_SMKS;
        !           464:         } else {
        !           465:             tapeGetDriveParams->FeaturesLow |=
        !           466:                 TAPE_DRIVE_TAPE_REMAINING;
        !           467:         }
        !           468: 
        !           469:     }
        !           470: 
        !           471:     ExFreePool(buffer);
        !           472: 
        !           473:     if (!NT_SUCCESS(status)) {
        !           474:         return status;
        !           475:     }
        !           476: 
        !           477:     //
        !           478:     // Zero CDB in SRB on stack.
        !           479:     //
        !           480: 
        !           481:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           482: 
        !           483:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !           484: 
        !           485:     cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
        !           486: 
        !           487:     //
        !           488:     // Set timeout value.
        !           489:     //
        !           490: 
        !           491:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !           492: 
        !           493:     cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DATA_COMPRESS_PAGE);
        !           494:     cdb->MODE_SENSE.Dbd = SETBITON;
        !           495:     cdb->MODE_SENSE.PageCode = MODE_PAGE_DATA_COMPRESS;
        !           496: 
        !           497:     dcbuff = ExAllocatePool(NonPagedPoolCacheAligned,
        !           498:         sizeof(MODE_DATA_COMPRESS_PAGE));
        !           499: 
        !           500:     if (!dcbuff) {
        !           501:         return STATUS_INSUFFICIENT_RESOURCES;
        !           502:     }
        !           503: 
        !           504:     RtlZeroMemory(dcbuff, sizeof(MODE_DATA_COMPRESS_PAGE));
        !           505: 
        !           506:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           507:                                 &srb,
        !           508:                                 dcbuff,
        !           509:                                 sizeof( MODE_DATA_COMPRESS_PAGE ),
        !           510:                                 FALSE);
        !           511: 
        !           512:     if (NT_SUCCESS(status)) {
        !           513:         if (dcbuff->DataCompressPage.DCC == 1) {
        !           514:             tapeGetDriveParams->FeaturesLow |= TAPE_DRIVE_COMPRESSION;
        !           515:             tapeGetDriveParams->FeaturesHigh |= TAPE_DRIVE_SET_COMPRESSION;
        !           516:             tapeGetDriveParams->Compression = (dcbuff->DataCompressPage.DCE == 1 ? TRUE : FALSE);
        !           517:         }
        !           518:     }
        !           519: 
        !           520:     ExFreePool(dcbuff);
        !           521: 
        !           522:     if (!NT_SUCCESS(status) && (status != STATUS_INVALID_DEVICE_REQUEST)) {
        !           523:         return status;
        !           524:     }
        !           525: 
        !           526:     //
        !           527:     // Zero CDB in SRB on stack.
        !           528:     //
        !           529: 
        !           530:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           531: 
        !           532:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !           533: 
        !           534:     cdb->CDB6GENERIC.OperationCode = SCSIOP_READ_BLOCK_LIMITS;
        !           535: 
        !           536:     //
        !           537:     // Set timeout value.
        !           538:     //
        !           539: 
        !           540:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !           541: 
        !           542:     blockLimits = ExAllocatePool(NonPagedPoolCacheAligned,
        !           543:         sizeof(READ_BLOCK_LIMITS_DATA));
        !           544: 
        !           545:     if (!blockLimits) {
        !           546:         return STATUS_INSUFFICIENT_RESOURCES;
        !           547:     }
        !           548: 
        !           549:     RtlZeroMemory(blockLimits, sizeof(READ_BLOCK_LIMITS_DATA));
        !           550: 
        !           551:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           552:                                 &srb,
        !           553:                                 blockLimits,
        !           554:                                 sizeof(READ_BLOCK_LIMITS_DATA),
        !           555:                                 FALSE);
        !           556: 
        !           557:     if (NT_SUCCESS(status)) {
        !           558:         tapeGetDriveParams->MaximumBlockSize = blockLimits->BlockMaximumSize[2];
        !           559:         tapeGetDriveParams->MaximumBlockSize += (blockLimits->BlockMaximumSize[1] << 8);
        !           560:         tapeGetDriveParams->MaximumBlockSize += (blockLimits->BlockMaximumSize[0] << 16);
        !           561: 
        !           562:         tapeGetDriveParams->MinimumBlockSize = blockLimits->BlockMinimumSize[1];
        !           563:         tapeGetDriveParams->MinimumBlockSize += (blockLimits->BlockMinimumSize[0] << 8);
        !           564:     }
        !           565: 
        !           566:     ExFreePool(blockLimits);
        !           567: 
        !           568:     tapeGetDriveParams->FeaturesHigh &= ~TAPE_DRIVE_HIGH_FEATURES;
        !           569: 
        !           570:     return status;
        !           571: 
        !           572: } // end TapeGetDriveParameters()
        !           573: 
        !           574: 
        !           575: NTSTATUS
        !           576: TapeGetMediaParameters(
        !           577:     IN PDEVICE_OBJECT DeviceObject,
        !           578:     IN PIRP Irp
        !           579:     )
        !           580: 
        !           581: /*++
        !           582: Routine Description:
        !           583: 
        !           584:     This routine returns the maximum tape capacity, the remaining tape
        !           585:     capacity, the fixed-length logical block size, the number of partitions
        !           586:     on the tape, and an indication if the tape is write protected.  A block
        !           587:     size of 0 indicates variable-length block mode.
        !           588: 
        !           589: Arguments:
        !           590: 
        !           591:     DeviceObject
        !           592:     Irp
        !           593: 
        !           594: Return Value:
        !           595: 
        !           596:     NTSTATUS
        !           597: 
        !           598: --*/
        !           599: 
        !           600: {
        !           601:     PDEVICE_EXTENSION            deviceExtension = DeviceObject->DeviceExtension;
        !           602:     PTAPE_GET_MEDIA_PARAMETERS   tapeGetMediaParams = Irp->AssociatedIrp.SystemBuffer;
        !           603:     PMODE_TAPE_MEDIA_INFORMATION modeBuffer;
        !           604:     PLOG_SENSE_PARAMETER_FORMAT  logBuffer;
        !           605:     SCSI_REQUEST_BLOCK           srb;
        !           606:     PCDB                         cdb = (PCDB)srb.Cdb;
        !           607:     NTSTATUS                     status;
        !           608:     LARGE_INTEGER                capacityBuffer[2];
        !           609:     LARGE_INTEGER                remainingBuffer[2];
        !           610:     ULONG                        sectorShift;
        !           611: 
        !           612:     DebugPrint((3,"TapeIoControl: Get Tape Media Parameters\n"));
        !           613: 
        !           614:     //
        !           615:     // Zero CDB in SRB on stack.
        !           616:     //
        !           617: 
        !           618:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           619: 
        !           620:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !           621: 
        !           622:     cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
        !           623: 
        !           624:     //
        !           625:     // Set timeout value.
        !           626:     //
        !           627: 
        !           628:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !           629: 
        !           630:     cdb->MODE_SENSE.AllocationLength = sizeof(MODE_TAPE_MEDIA_INFORMATION);
        !           631:     cdb->MODE_SENSE.PageCode = MODE_PAGE_MEDIUM_PARTITION;
        !           632: 
        !           633:     modeBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
        !           634:         sizeof(MODE_TAPE_MEDIA_INFORMATION));
        !           635: 
        !           636:     if (!modeBuffer) {
        !           637:         return STATUS_INSUFFICIENT_RESOURCES;
        !           638:     }
        !           639: 
        !           640:     RtlZeroMemory(modeBuffer, sizeof(MODE_TAPE_MEDIA_INFORMATION));
        !           641: 
        !           642:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           643:                                 &srb,
        !           644:                                 modeBuffer,
        !           645:                                 sizeof( MODE_TAPE_MEDIA_INFORMATION ),
        !           646:                                 FALSE);
        !           647: 
        !           648:     if (status == STATUS_DATA_OVERRUN) {
        !           649:         status = STATUS_SUCCESS;
        !           650:     }
        !           651: 
        !           652:     if (NT_SUCCESS(status)) {
        !           653:         Irp->IoStatus.Information = sizeof(TAPE_GET_MEDIA_PARAMETERS);
        !           654: 
        !           655:         tapeGetMediaParams->BlockSize = modeBuffer->ParameterListBlock.BlockLength[2];
        !           656:         tapeGetMediaParams->BlockSize += (modeBuffer->ParameterListBlock.BlockLength[1] << 8);
        !           657:         tapeGetMediaParams->BlockSize += (modeBuffer->ParameterListBlock.BlockLength[0] << 16);
        !           658: 
        !           659:         tapeGetMediaParams->PartitionCount =
        !           660:             modeBuffer->MediumPartPage.AdditionalPartitionDefined + 1;
        !           661: 
        !           662:         tapeGetMediaParams->WriteProtected =
        !           663:             ((modeBuffer->ParameterListHeader.DeviceSpecificParameter >> 7) &
        !           664:             0x01);
        !           665: 
        !           666:         gb_PartitionCount =
        !           667:             modeBuffer->MediumPartPage.AdditionalPartitionDefined + 1;
        !           668: 
        !           669:         if (RtlCompareMemory(gb_VendorId,"WangDAT ",8) == 8) {
        !           670:             capacityBuffer[0].LowPart = modeBuffer->MediumPartPage.Partition0Size[1];
        !           671:             capacityBuffer[0].LowPart += (modeBuffer->MediumPartPage.Partition0Size[0] << 8);
        !           672: 
        !           673:             capacityBuffer[0].HighPart = 0;
        !           674: 
        !           675:             if (tapeGetMediaParams->PartitionCount == 2) {
        !           676:                 capacityBuffer[1].LowPart = modeBuffer->MediumPartPage.Partition1Size[1];
        !           677:                 capacityBuffer[1].LowPart += (modeBuffer->MediumPartPage.Partition1Size[0] << 8);
        !           678: 
        !           679:                 capacityBuffer[1].HighPart = 0;
        !           680:             } else {
        !           681:                 capacityBuffer[1].LowPart = 0;
        !           682:                 capacityBuffer[1].HighPart = 0;
        !           683:             }
        !           684: 
        !           685:             capacityBuffer[0] =
        !           686:                 RtlLargeIntegerAdd( capacityBuffer[0], capacityBuffer[1]);
        !           687:             capacityBuffer[0] =
        !           688:                 RtlExtendedIntegerMultiply(capacityBuffer[0], 1024000);
        !           689: 
        !           690:             tapeGetMediaParams->Capacity = capacityBuffer[0];
        !           691: 
        !           692:             tapeGetMediaParams->Remaining.LowPart = 0;
        !           693:             tapeGetMediaParams->Remaining.HighPart = 0;
        !           694: 
        !           695:             WHICH_BIT(tapeGetMediaParams->BlockSize, sectorShift);
        !           696:             deviceExtension->DiskGeometry->BytesPerSector = tapeGetMediaParams->BlockSize;
        !           697:             deviceExtension->SectorShift = sectorShift;
        !           698: 
        !           699: 
        !           700:         }
        !           701:     }
        !           702: 
        !           703:     ExFreePool(modeBuffer);
        !           704: 
        !           705:     if (!NT_SUCCESS(status)) {
        !           706: 
        !           707:         return status;
        !           708:     }
        !           709: 
        !           710:     if (!(RtlCompareMemory(gb_VendorId,"WangDAT ",8) == 8)) {
        !           711:         //
        !           712:         // Zero CDB in SRB on stack.
        !           713:         //
        !           714: 
        !           715:         RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           716: 
        !           717:         srb.CdbLength = CDB10GENERIC_LENGTH;
        !           718: 
        !           719:         cdb->LOGSENSE.OperationCode = SCSIOP_LOG_SENSE;
        !           720: 
        !           721:         //
        !           722:         // Set timeout value.
        !           723:         //
        !           724: 
        !           725:         srb.TimeOutValue = deviceExtension->TimeOutValue;
        !           726: 
        !           727:         cdb->LOGSENSE.AllocationLength[0] = 0;
        !           728:         cdb->LOGSENSE.AllocationLength[1] = 0x24;
        !           729: 
        !           730:         cdb->LOGSENSE.PageCode = LOGSENSEPAGE31;
        !           731:         cdb->LOGSENSE.PCBit = 0x01;
        !           732: 
        !           733:         logBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
        !           734:             sizeof(LOG_SENSE_PARAMETER_FORMAT));
        !           735: 
        !           736:         if (!logBuffer) {
        !           737:             return STATUS_INSUFFICIENT_RESOURCES;
        !           738:         }
        !           739: 
        !           740:         RtlZeroMemory(logBuffer, sizeof(LOG_SENSE_PARAMETER_FORMAT));
        !           741: 
        !           742:         status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           743:                                     &srb,
        !           744:                                     logBuffer,
        !           745:                                     0x24,
        !           746:                                     FALSE);
        !           747: 
        !           748:         if (status == STATUS_DATA_OVERRUN) {
        !           749:             status = STATUS_SUCCESS;
        !           750:         }
        !           751: 
        !           752:         if (NT_SUCCESS(status)) {
        !           753:             capacityBuffer[0].LowPart = logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart0[3];
        !           754:             capacityBuffer[0].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart0[2] << 8);
        !           755:             capacityBuffer[0].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart0[1] << 16);
        !           756:             capacityBuffer[0].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart0[0] << 24);
        !           757: 
        !           758:             capacityBuffer[0].HighPart = 0;
        !           759: 
        !           760:             remainingBuffer[0].LowPart = logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart0[3];
        !           761:             remainingBuffer[0].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart0[2] << 8);
        !           762:             remainingBuffer[0].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart0[1] << 16);
        !           763:             remainingBuffer[0].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart0[0] << 24);
        !           764: 
        !           765:             remainingBuffer[0].HighPart = 0;
        !           766: 
        !           767:             if (tapeGetMediaParams->PartitionCount == 2) {
        !           768:                 capacityBuffer[1].LowPart = logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart1[3];
        !           769:                 capacityBuffer[1].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart1[2] << 8);
        !           770:                 capacityBuffer[1].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart1[1] << 16);
        !           771:                 capacityBuffer[1].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart1[0] << 24);
        !           772: 
        !           773:                 capacityBuffer[1].HighPart = 0;
        !           774: 
        !           775:                 remainingBuffer[1].LowPart = logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart1[3];
        !           776:                 remainingBuffer[1].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart1[2] << 8);
        !           777:                 remainingBuffer[1].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart1[1] << 16);
        !           778:                 remainingBuffer[1].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart1[0] << 24);
        !           779: 
        !           780:                 remainingBuffer[1].HighPart = 0;
        !           781: 
        !           782:             } else {
        !           783:                 capacityBuffer[1].LowPart = 0;
        !           784:                 capacityBuffer[1].HighPart = 0;
        !           785:                 remainingBuffer[1].LowPart = 0;
        !           786:                 remainingBuffer[1].HighPart = 0;
        !           787:             }
        !           788: 
        !           789:             capacityBuffer[0] =
        !           790:                 RtlLargeIntegerAdd( capacityBuffer[0], capacityBuffer[1]);
        !           791:             capacityBuffer[0] =
        !           792:                 RtlExtendedIntegerMultiply(capacityBuffer[0], 1024);
        !           793: 
        !           794:             tapeGetMediaParams->Capacity = capacityBuffer[0];
        !           795: 
        !           796:             remainingBuffer[0] =
        !           797:                 RtlLargeIntegerAdd( remainingBuffer[0], remainingBuffer[1]);
        !           798:             remainingBuffer[0] =
        !           799:                 RtlExtendedIntegerMultiply(remainingBuffer[0], 1024);
        !           800: 
        !           801:             tapeGetMediaParams->Remaining = remainingBuffer[0];
        !           802:         }
        !           803: 
        !           804:         ExFreePool(logBuffer);
        !           805:     }
        !           806: 
        !           807:     return status;
        !           808: 
        !           809: } // end TapeGetMediaParameters()
        !           810: 
        !           811: 
        !           812: NTSTATUS
        !           813: TapeGetPosition(
        !           814:     IN PDEVICE_OBJECT DeviceObject,
        !           815:     IN PIRP Irp
        !           816:     )
        !           817: 
        !           818: /*++
        !           819: Routine Description:
        !           820: 
        !           821:     This routine returns the current position of the tape.
        !           822: 
        !           823: Arguments:
        !           824: 
        !           825:     DeviceObject
        !           826:     Irp
        !           827: 
        !           828: Return Value:
        !           829: 
        !           830:     NTSTATUS
        !           831: 
        !           832: --*/
        !           833: 
        !           834: {
        !           835:     PDEVICE_EXTENSION   deviceExtension = DeviceObject->DeviceExtension;
        !           836:     PTAPE_GET_POSITION  tapeGetPosition = Irp->AssociatedIrp.SystemBuffer;
        !           837:     PTAPE_POSITION_DATA logicalBuffer;
        !           838:     PUCHAR              absoluteBuffer;
        !           839:     SCSI_REQUEST_BLOCK  srb;
        !           840:     PCDB                cdb = (PCDB)srb.Cdb;
        !           841:     NTSTATUS            status;
        !           842: 
        !           843:     //
        !           844:     // Zero CDB in SRB on stack.
        !           845:     //
        !           846: 
        !           847:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           848: 
        !           849:     //
        !           850:     // Set timeout value.
        !           851:     //
        !           852: 
        !           853:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !           854: 
        !           855:     switch (tapeGetPosition->Type) {
        !           856:         case TAPE_ABSOLUTE_POSITION:
        !           857:             DebugPrint((3,"TapeIoControl: Get Absolute Position\n"));
        !           858:             srb.CdbLength = CDB6GENERIC_LENGTH;
        !           859:             cdb->CDB6GENERIC.OperationCode = SCSIOP_REQUEST_BLOCK_ADDR;
        !           860:             absoluteBuffer = ExAllocatePool(NonPagedPoolCacheAligned, 3);
        !           861: 
        !           862:             if (!absoluteBuffer) {
        !           863:                 return STATUS_INSUFFICIENT_RESOURCES;
        !           864:             }
        !           865: 
        !           866:             status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           867:                                         &srb,
        !           868:                                         absoluteBuffer,
        !           869:                                         3,
        !           870:                                         FALSE);
        !           871: 
        !           872:             if (NT_SUCCESS(status)) {
        !           873:                 Irp->IoStatus.Information = sizeof(TAPE_GET_POSITION);
        !           874: 
        !           875:                 tapeGetPosition->Partition = 0;
        !           876:                 tapeGetPosition->Offset.HighPart = 0;
        !           877:                 tapeGetPosition->Offset.LowPart = absoluteBuffer[2];
        !           878:                 tapeGetPosition->Offset.LowPart += (absoluteBuffer[1] << 8);
        !           879:                 tapeGetPosition->Offset.LowPart += (absoluteBuffer[0] << 16);
        !           880:             }
        !           881: 
        !           882:             ExFreePool(absoluteBuffer);
        !           883:             break;
        !           884: 
        !           885:         case TAPE_LOGICAL_POSITION:
        !           886:             DebugPrint((3,"TapeIoControl: Get Logical Position\n"));
        !           887:             srb.CdbLength = CDB10GENERIC_LENGTH;
        !           888:             cdb->READ_POSITION.Operation = SCSIOP_READ_POSITION;
        !           889:             logicalBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
        !           890:                 sizeof(TAPE_POSITION_DATA));
        !           891: 
        !           892:             if (!logicalBuffer) {
        !           893:                 return STATUS_INSUFFICIENT_RESOURCES;
        !           894:             }
        !           895: 
        !           896:             status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           897:                                         &srb,
        !           898:                                         logicalBuffer,
        !           899:                                         sizeof( TAPE_POSITION_DATA ),
        !           900:                                         FALSE);
        !           901: 
        !           902:             if (NT_SUCCESS(status)) {
        !           903:                 Irp->IoStatus.Information = sizeof(TAPE_GET_POSITION);
        !           904: 
        !           905:                 if (logicalBuffer->BlockPositionUnsupported) {
        !           906:                     DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n"));
        !           907:                     return STATUS_INVALID_DEVICE_REQUEST;
        !           908:                 }
        !           909: 
        !           910:                 tapeGetPosition->Partition = logicalBuffer->PartitionNumber + 1;
        !           911:                 tapeGetPosition->Offset.HighPart = 0;
        !           912:                 REVERSE_BYTES((PFOUR_BYTE)&tapeGetPosition->Offset.LowPart,
        !           913:                     (PFOUR_BYTE)logicalBuffer->FirstBlock);
        !           914:             }
        !           915: 
        !           916:             ExFreePool(logicalBuffer);
        !           917:             break;
        !           918: 
        !           919:         default:
        !           920:             DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n"));
        !           921:             return STATUS_INVALID_DEVICE_REQUEST;
        !           922:     }
        !           923: 
        !           924:     return status;
        !           925: 
        !           926: } // end TapeGetPosition()
        !           927: 
        !           928: 
        !           929: NTSTATUS
        !           930: TapeGetStatus(
        !           931:     IN PDEVICE_OBJECT DeviceObject,
        !           932:     IN PIRP Irp
        !           933:     )
        !           934: 
        !           935: /*++
        !           936: Routine Description:
        !           937: 
        !           938:     This routine returns the status of the device.
        !           939: 
        !           940: Arguments:
        !           941: 
        !           942:     DeviceObject
        !           943:     Irp
        !           944: 
        !           945: Return Value:
        !           946: 
        !           947:     NTSTATUS
        !           948: 
        !           949: --*/
        !           950: 
        !           951: {
        !           952:     PDEVICE_EXTENSION   deviceExtension = DeviceObject->DeviceExtension;
        !           953:     SCSI_REQUEST_BLOCK  srb;
        !           954:     PCDB                cdb = (PCDB)srb.Cdb;
        !           955:     NTSTATUS            status;
        !           956: 
        !           957:     DebugPrint((3,"TapeIoControl: Get Tape Status\n"));
        !           958: 
        !           959:     //
        !           960:     // Zero CDB in SRB on stack.
        !           961:     //
        !           962: 
        !           963:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           964: 
        !           965:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !           966: 
        !           967:     cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
        !           968: 
        !           969:     //
        !           970:     // Set timeout value.
        !           971:     //
        !           972: 
        !           973:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !           974: 
        !           975:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           976:                                 &srb,
        !           977:                                 NULL,
        !           978:                                 0,
        !           979:                                 FALSE);
        !           980: 
        !           981:     return status;
        !           982: 
        !           983: } // end TapeGetStatus()
        !           984: 
        !           985: 
        !           986: NTSTATUS
        !           987: TapePrepare(
        !           988:     IN PDEVICE_OBJECT DeviceObject,
        !           989:     IN PIRP Irp
        !           990:     )
        !           991: 
        !           992: /*++
        !           993: Routine Description:
        !           994: 
        !           995:     This routine loads, unloads, locks, or unlocks the tape.
        !           996: 
        !           997: Arguments:
        !           998: 
        !           999:     DeviceObject
        !          1000:     Irp
        !          1001: 
        !          1002: Return Value:
        !          1003: 
        !          1004:     NTSTATUS
        !          1005: 
        !          1006: --*/
        !          1007: 
        !          1008: {
        !          1009:     PDEVICE_EXTENSION   deviceExtension = DeviceObject->DeviceExtension;
        !          1010:     PTAPE_PREPARE       tapePrepare = Irp->AssociatedIrp.SystemBuffer;
        !          1011:     SCSI_REQUEST_BLOCK  srb;
        !          1012:     PCDB                cdb = (PCDB)srb.Cdb;
        !          1013:     NTSTATUS            status;
        !          1014: 
        !          1015:     //
        !          1016:     // Zero CDB in SRB on stack.
        !          1017:     //
        !          1018: 
        !          1019:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1020: 
        !          1021:     //
        !          1022:     // Set timeout value.
        !          1023:     //
        !          1024: 
        !          1025:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !          1026: 
        !          1027:     switch (tapePrepare->Operation) {
        !          1028:         case TAPE_LOAD:
        !          1029:             DebugPrint((3,"TapeIoControl: Load Tape\n"));
        !          1030:             srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1031:             cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD;
        !          1032:             cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x01;
        !          1033:             break;
        !          1034: 
        !          1035:         case TAPE_UNLOAD:
        !          1036:             DebugPrint((3,"TapeIoControl: Unload Tape\n"));
        !          1037:             srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1038:             cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD;
        !          1039:             break;
        !          1040: 
        !          1041:         case TAPE_LOCK:
        !          1042:             DebugPrint((3,"TapeIoControl: Prevent Tape Removal\n"));
        !          1043:             srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1044:             cdb->CDB6GENERIC.OperationCode = SCSIOP_MEDIUM_REMOVAL;
        !          1045:             cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x01;
        !          1046:             break;
        !          1047: 
        !          1048:         case TAPE_UNLOCK:
        !          1049:             DebugPrint((3,"TapeIoControl: Allow Tape Removal\n"));
        !          1050:             srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1051:             cdb->CDB6GENERIC.OperationCode = SCSIOP_MEDIUM_REMOVAL;
        !          1052:             break;
        !          1053: 
        !          1054:         default:
        !          1055:             DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n"));
        !          1056:             return STATUS_INVALID_DEVICE_REQUEST;
        !          1057:     }
        !          1058: 
        !          1059:     //
        !          1060:     // Set immediate bit if indicated.
        !          1061:     //
        !          1062: 
        !          1063:     cdb->CDB6GENERIC.Immediate = tapePrepare->Immediate;
        !          1064: 
        !          1065:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          1066:                                 &srb,
        !          1067:                                 NULL,
        !          1068:                                 0,
        !          1069:                                 FALSE);
        !          1070: 
        !          1071:     return status;
        !          1072: 
        !          1073: } // end TapePrepare()
        !          1074: 
        !          1075: NTSTATUS
        !          1076: TapeReadWrite(
        !          1077:     IN PDEVICE_OBJECT DeviceObject,
        !          1078:     IN PIRP Irp
        !          1079:     )
        !          1080: 
        !          1081: /*++
        !          1082: 
        !          1083: Routine Description:
        !          1084: 
        !          1085:     This routine builds SRBs and CDBs for read and write requests to 4MM DAT
        !          1086:     devices.
        !          1087: 
        !          1088: Arguments:
        !          1089: 
        !          1090:     DeviceObject
        !          1091:     Irp
        !          1092: 
        !          1093: Return Value:
        !          1094: 
        !          1095:     Returns STATUS_PENDING.
        !          1096: 
        !          1097: --*/
        !          1098: 
        !          1099:   {
        !          1100:     PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
        !          1101:     PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
        !          1102:     PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
        !          1103:     PSCSI_REQUEST_BLOCK srb;
        !          1104:     PCDB cdb;
        !          1105:     KIRQL currentIrql;
        !          1106:     ULONG transferBlocks;
        !          1107:     LARGE_INTEGER startingOffset =
        !          1108:       currentIrpStack->Parameters.Read.ByteOffset;
        !          1109: 
        !          1110:     //
        !          1111:     // Allocate an Srb.
        !          1112:     //
        !          1113: 
        !          1114:     if (deviceExtension->SrbZone != NULL &&
        !          1115:         (srb = ExInterlockedAllocateFromZone(
        !          1116:             deviceExtension->SrbZone,
        !          1117:             deviceExtension->SrbZoneSpinLock)) != NULL) {
        !          1118: 
        !          1119:         srb->SrbFlags = SRB_FLAGS_ALLOCATED_FROM_ZONE;
        !          1120: 
        !          1121:     } else {
        !          1122: 
        !          1123:         //
        !          1124:         // Allocate Srb from non-paged pool.
        !          1125:         // This call must succeed.
        !          1126:         //
        !          1127: 
        !          1128:         srb = ExAllocatePool(NonPagedPoolMustSucceed, SCSI_REQUEST_BLOCK_SIZE);
        !          1129: 
        !          1130:         srb->SrbFlags = 0;
        !          1131: 
        !          1132:     }
        !          1133: 
        !          1134:     //
        !          1135:     // Write length to SRB.
        !          1136:     //
        !          1137: 
        !          1138:     srb->Length = SCSI_REQUEST_BLOCK_SIZE;
        !          1139: 
        !          1140:     //
        !          1141:     // Set up IRP Address.
        !          1142:     //
        !          1143: 
        !          1144:     srb->OriginalRequest = Irp;
        !          1145: 
        !          1146:     //
        !          1147:     // Set up target id and logical unit number.
        !          1148:     //
        !          1149: 
        !          1150:     srb->PathId = deviceExtension->PathId;
        !          1151:     srb->TargetId = deviceExtension->TargetId;
        !          1152:     srb->Lun = deviceExtension->Lun;
        !          1153: 
        !          1154: 
        !          1155:     srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
        !          1156: 
        !          1157:     srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
        !          1158: 
        !          1159:     //
        !          1160:     // Save byte count of transfer in SRB Extension.
        !          1161:     //
        !          1162: 
        !          1163:     srb->DataTransferLength = currentIrpStack->Parameters.Read.Length;
        !          1164: 
        !          1165:     //
        !          1166:     // Indicate auto request sense by specifying buffer and size.
        !          1167:     //
        !          1168: 
        !          1169:     srb->SenseInfoBuffer = deviceExtension->SenseData;
        !          1170: 
        !          1171:     srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
        !          1172: 
        !          1173:     //
        !          1174:     // Initialize the queue actions field.
        !          1175:     //
        !          1176: 
        !          1177:     srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
        !          1178: 
        !          1179:     //
        !          1180:     // Indicate auto request sense by specifying buffer and size.
        !          1181:     //
        !          1182: 
        !          1183:     srb->SenseInfoBuffer = deviceExtension->SenseData;
        !          1184: 
        !          1185:     srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
        !          1186: 
        !          1187:     //
        !          1188:     // Set timeout value in seconds.
        !          1189:     //
        !          1190: 
        !          1191:     srb->TimeOutValue = deviceExtension->TimeOutValue;
        !          1192: 
        !          1193:     //
        !          1194:     // Zero statuses.
        !          1195:     //
        !          1196: 
        !          1197:     srb->SrbStatus = srb->ScsiStatus = 0;
        !          1198: 
        !          1199:     srb->NextSrb = 0;
        !          1200: 
        !          1201:     //
        !          1202:     // Indicate that 6-byte CDB's will be used.
        !          1203:     //
        !          1204: 
        !          1205:     srb->CdbLength = CDB6GENERIC_LENGTH;
        !          1206: 
        !          1207:     //
        !          1208:     // Fill in CDB fields.
        !          1209:     //
        !          1210: 
        !          1211:     cdb = (PCDB)srb->Cdb;
        !          1212: 
        !          1213:     //
        !          1214:     // Zero CDB in SRB.
        !          1215:     //
        !          1216: 
        !          1217:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1218: 
        !          1219:     //
        !          1220:     // Since we are writing fixed block mode, normalize transfer count
        !          1221:     // to number of blocks.
        !          1222:     //
        !          1223: 
        !          1224:     transferBlocks =
        !          1225:         currentIrpStack->Parameters.Read.Length >> deviceExtension->SectorShift;
        !          1226: 
        !          1227:     //
        !          1228:     // Set up transfer length
        !          1229:     //
        !          1230: 
        !          1231:     cdb->CDB6READWRITETAPE.TransferLenMSB = (UCHAR)((transferBlocks >> 16) & 0xff);
        !          1232:     cdb->CDB6READWRITETAPE.TransferLen    = (UCHAR)((transferBlocks >> 8) & 0xff);
        !          1233:     cdb->CDB6READWRITETAPE.TransferLenLSB = (UCHAR)(transferBlocks & 0xff);
        !          1234: 
        !          1235:     //
        !          1236:     // Tell the python we are in fixed block mode
        !          1237:     //
        !          1238: 
        !          1239:     cdb->CDB6READWRITETAPE.VendorSpecific = 1;
        !          1240: 
        !          1241:     //
        !          1242:     // Set transfer direction flag and Cdb command.
        !          1243:     //
        !          1244: 
        !          1245:     if (currentIrpStack->MajorFunction == IRP_MJ_READ) {
        !          1246: 
        !          1247:          DebugPrint((3, "TapeRequest: Read Command\n"));
        !          1248: 
        !          1249:          srb->SrbFlags = SRB_FLAGS_DATA_IN;
        !          1250:          cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_READ6;
        !          1251: 
        !          1252:     } else {
        !          1253: 
        !          1254:          DebugPrint((3, "TapeRequest: Write Command\n"));
        !          1255: 
        !          1256:          srb->SrbFlags = SRB_FLAGS_DATA_OUT;
        !          1257:          cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_WRITE6;
        !          1258:     }
        !          1259: 
        !          1260:     //
        !          1261:     // Or in the default flags from the device object.
        !          1262:     //
        !          1263: 
        !          1264:     srb->SrbFlags |= deviceExtension->SrbFlags;
        !          1265: 
        !          1266:     //
        !          1267:     // Set up major SCSI function.
        !          1268:     //
        !          1269: 
        !          1270:     nextIrpStack->MajorFunction = IRP_MJ_SCSI;
        !          1271: 
        !          1272:     //
        !          1273:     // Save SRB address in next stack for port driver.
        !          1274:     //
        !          1275: 
        !          1276:     nextIrpStack->Parameters.Scsi.Srb = srb;
        !          1277: 
        !          1278:     //
        !          1279:     // Save retry count in current IRP stack.
        !          1280:     //
        !          1281: 
        !          1282:     currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
        !          1283: 
        !          1284:     //
        !          1285:     // Set up IoCompletion routine address.
        !          1286:     //
        !          1287: 
        !          1288:     IoSetCompletionRoutine(Irp,
        !          1289:                            ScsiClassIoComplete,
        !          1290:                            srb,
        !          1291:                            TRUE,
        !          1292:                            TRUE,
        !          1293:                            FALSE);
        !          1294: 
        !          1295:     return STATUS_PENDING;
        !          1296: 
        !          1297: } // end TapeReadWrite()
        !          1298: 
        !          1299: NTSTATUS
        !          1300: TapeSetDriveParameters(
        !          1301:     IN PDEVICE_OBJECT DeviceObject,
        !          1302:     IN PIRP Irp
        !          1303:     )
        !          1304: 
        !          1305: /*++
        !          1306: Routine Description:
        !          1307: 
        !          1308:     This routine enables/disables reporting of setmarks.
        !          1309: 
        !          1310: Arguments:
        !          1311: 
        !          1312:     DeviceObject
        !          1313:     Irp
        !          1314: 
        !          1315: Return Value:
        !          1316: 
        !          1317:     NTSTATUS
        !          1318: 
        !          1319: --*/
        !          1320: 
        !          1321: {
        !          1322:     PDEVICE_EXTENSION          deviceExtension = DeviceObject->DeviceExtension;
        !          1323:     PTAPE_SET_DRIVE_PARAMETERS tapeSetDriveParams = Irp->AssociatedIrp.SystemBuffer;
        !          1324:     PMODE_DEVICE_CONFIG_PAGE   buffer;
        !          1325:     SCSI_REQUEST_BLOCK         srb;
        !          1326:     PCDB                       cdb = (PCDB)srb.Cdb;
        !          1327:     NTSTATUS                   status;
        !          1328:     PMODE_DATA_COMPRESS_PAGE   dcbuff;
        !          1329: 
        !          1330:     DebugPrint((3,"TapeIoControl: Set Tape Drive Parameters\n"));
        !          1331: 
        !          1332:     //
        !          1333:     // Zero CDB in SRB on stack.
        !          1334:     //
        !          1335: 
        !          1336:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1337: 
        !          1338:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1339: 
        !          1340:     cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
        !          1341: 
        !          1342:     //
        !          1343:     // Set timeout value.
        !          1344:     //
        !          1345: 
        !          1346:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !          1347: 
        !          1348:     cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DEVICE_CONFIG_PAGE);
        !          1349:     cdb->MODE_SENSE.Dbd = SETBITON;
        !          1350:     cdb->MODE_SENSE.PageCode = MODE_PAGE_DEVICE_CONFIG;
        !          1351: 
        !          1352:     buffer = ExAllocatePool(NonPagedPoolCacheAligned,
        !          1353:         sizeof(MODE_DEVICE_CONFIG_PAGE));
        !          1354: 
        !          1355:     if (!buffer) {
        !          1356:         return STATUS_INSUFFICIENT_RESOURCES;
        !          1357:     }
        !          1358: 
        !          1359:     RtlZeroMemory(buffer, sizeof(MODE_DEVICE_CONFIG_PAGE));
        !          1360: 
        !          1361:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          1362:                                 &srb,
        !          1363:                                 buffer,
        !          1364:                                 sizeof( MODE_DEVICE_CONFIG_PAGE ),
        !          1365:                                 FALSE);
        !          1366: 
        !          1367:     if (!NT_SUCCESS(status)) {
        !          1368:         ExFreePool(buffer);
        !          1369:         return status;
        !          1370:     }
        !          1371: 
        !          1372:     //
        !          1373:     // Zero CDB in SRB on stack.
        !          1374:     //
        !          1375: 
        !          1376:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1377: 
        !          1378:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1379: 
        !          1380:     cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
        !          1381: 
        !          1382:     //
        !          1383:     // Set timeout value.
        !          1384:     //
        !          1385: 
        !          1386:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !          1387: 
        !          1388:     cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_DEVICE_CONFIG_PAGE);
        !          1389:     cdb->MODE_SELECT.PFBit = 1;
        !          1390: 
        !          1391:     buffer->ParameterListHeader.ModeDataLength = 0;
        !          1392:     buffer->ParameterListHeader.MediumType = 0;
        !          1393:     buffer->ParameterListHeader.DeviceSpecificParameter = 0x10;
        !          1394:     buffer->ParameterListHeader.BlockDescriptorLength = 0;
        !          1395: 
        !          1396:     buffer->DeviceConfigPage.PageCode = MODE_PAGE_DEVICE_CONFIG;
        !          1397:     buffer->DeviceConfigPage.PageLength = 0x0E;
        !          1398: 
        !          1399:     if (tapeSetDriveParams->ReportSetmarks) {
        !          1400:         buffer->DeviceConfigPage.RSmk = SETBITON;
        !          1401:     } else {
        !          1402:         buffer->DeviceConfigPage.RSmk = SETBITOFF;
        !          1403:     }
        !          1404: 
        !          1405:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          1406:                                 &srb,
        !          1407:                                 buffer,
        !          1408:                                 sizeof( MODE_DEVICE_CONFIG_PAGE ),
        !          1409:                                 TRUE);
        !          1410: 
        !          1411:     ExFreePool(buffer);
        !          1412: 
        !          1413:     if (!NT_SUCCESS(status)) {
        !          1414:         return status;
        !          1415:     }
        !          1416: 
        !          1417:     //
        !          1418:     // Zero CDB in SRB on stack.
        !          1419:     //
        !          1420: 
        !          1421:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1422: 
        !          1423:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1424: 
        !          1425:     cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
        !          1426: 
        !          1427:     //
        !          1428:     // Set timeout value.
        !          1429:     //
        !          1430: 
        !          1431:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !          1432: 
        !          1433:     cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DATA_COMPRESS_PAGE);
        !          1434:     cdb->MODE_SENSE.Dbd = SETBITON;
        !          1435:     cdb->MODE_SENSE.PageCode = MODE_PAGE_DATA_COMPRESS;
        !          1436: 
        !          1437:     dcbuff = ExAllocatePool(NonPagedPoolCacheAligned,
        !          1438:         sizeof(MODE_DATA_COMPRESS_PAGE));
        !          1439: 
        !          1440:     if (!dcbuff) {
        !          1441:         return STATUS_INSUFFICIENT_RESOURCES;
        !          1442:     }
        !          1443: 
        !          1444:     RtlZeroMemory(dcbuff, sizeof(MODE_DATA_COMPRESS_PAGE));
        !          1445: 
        !          1446:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          1447:                                 &srb,
        !          1448:                                 dcbuff,
        !          1449:                                 sizeof( MODE_DATA_COMPRESS_PAGE ),
        !          1450:                                 FALSE);
        !          1451: 
        !          1452:     if (!NT_SUCCESS(status) && (status != STATUS_INVALID_DEVICE_REQUEST)) {
        !          1453:         ExFreePool(dcbuff);
        !          1454:         return status;
        !          1455:     }
        !          1456: 
        !          1457:     if (NT_SUCCESS(status) && dcbuff->DataCompressPage.DCC == 1) {
        !          1458:         //
        !          1459:         // Zero CDB in SRB on stack.
        !          1460:         //
        !          1461: 
        !          1462:         RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1463: 
        !          1464:         srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1465: 
        !          1466:         cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
        !          1467: 
        !          1468:         //
        !          1469:         // Set timeout value.
        !          1470:         //
        !          1471: 
        !          1472:         srb.TimeOutValue = deviceExtension->TimeOutValue;
        !          1473: 
        !          1474:         cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_DATA_COMPRESS_PAGE);
        !          1475:         cdb->MODE_SELECT.PFBit = 1;
        !          1476: 
        !          1477:         dcbuff->ParameterListHeader.ModeDataLength = 0;
        !          1478:         dcbuff->ParameterListHeader.MediumType = 0;
        !          1479:         dcbuff->ParameterListHeader.DeviceSpecificParameter = 0x10;
        !          1480:         dcbuff->ParameterListHeader.BlockDescriptorLength = 0;
        !          1481: 
        !          1482:         dcbuff->DataCompressPage.PageCode = MODE_PAGE_DATA_COMPRESS;
        !          1483:         dcbuff->DataCompressPage.PageLength = 0x0E;
        !          1484: 
        !          1485:         if (tapeSetDriveParams->Compression) {
        !          1486:             dcbuff->DataCompressPage.DCE = SETBITON;
        !          1487:         } else {
        !          1488:             dcbuff->DataCompressPage.DCE = SETBITOFF;
        !          1489:         }
        !          1490: 
        !          1491:         status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          1492:                                     &srb,
        !          1493:                                     dcbuff,
        !          1494:                                     sizeof( MODE_DATA_COMPRESS_PAGE ),
        !          1495:                                     TRUE);
        !          1496:     } else if (status == STATUS_INVALID_DEVICE_REQUEST) {
        !          1497:         status = STATUS_SUCCESS;
        !          1498:     }
        !          1499: 
        !          1500:     ExFreePool(dcbuff);
        !          1501: 
        !          1502:     return status;
        !          1503: 
        !          1504: } // end TapeSetDriveParameters()
        !          1505: 
        !          1506: 
        !          1507: NTSTATUS
        !          1508: TapeSetMediaParameters(
        !          1509:     IN PDEVICE_OBJECT DeviceObject,
        !          1510:     IN PIRP Irp
        !          1511:     )
        !          1512: 
        !          1513: /*++
        !          1514: Routine Description:
        !          1515: 
        !          1516:     This routine sets the fixed-length logical block size or variable-length
        !          1517:     block mode (if the block size is 0).
        !          1518: 
        !          1519: Arguments:
        !          1520: 
        !          1521:     DeviceObject
        !          1522:     Irp
        !          1523: 
        !          1524: Return Value:
        !          1525: 
        !          1526:     NTSTATUS
        !          1527: 
        !          1528: --*/
        !          1529: 
        !          1530: {
        !          1531:     PDEVICE_EXTENSION          deviceExtension = DeviceObject->DeviceExtension;
        !          1532:     PTAPE_SET_MEDIA_PARAMETERS tapeSetMediaParams = Irp->AssociatedIrp.SystemBuffer;
        !          1533:     PMODE_PARM_READ_WRITE_DATA buffer;
        !          1534:     SCSI_REQUEST_BLOCK         srb;
        !          1535:     PCDB                       cdb = (PCDB)srb.Cdb;
        !          1536:     NTSTATUS                   status;
        !          1537: 
        !          1538:     DebugPrint((3,"TapeIoControl: Set Tape Media Parameters \n"));
        !          1539: 
        !          1540:     //
        !          1541:     // Zero CDB in SRB on stack.
        !          1542:     //
        !          1543: 
        !          1544:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1545: 
        !          1546:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1547: 
        !          1548:     cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
        !          1549: 
        !          1550:     //
        !          1551:     // Set timeout value.
        !          1552:     //
        !          1553: 
        !          1554:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !          1555: 
        !          1556:     cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_PARM_READ_WRITE_DATA);
        !          1557:     cdb->MODE_SELECT.PFBit = 1;
        !          1558: 
        !          1559:     buffer = ExAllocatePool(NonPagedPoolCacheAligned,
        !          1560:         sizeof(MODE_PARM_READ_WRITE_DATA));
        !          1561: 
        !          1562:     if (!buffer) {
        !          1563:         return STATUS_INSUFFICIENT_RESOURCES;
        !          1564:     }
        !          1565: 
        !          1566:     RtlZeroMemory(buffer, sizeof(MODE_PARM_READ_WRITE_DATA));
        !          1567: 
        !          1568:     buffer->ParameterListHeader.DeviceSpecificParameter = 0x10;
        !          1569:     buffer->ParameterListHeader.BlockDescriptorLength = MODE_BLOCK_DESC_LENGTH;
        !          1570: 
        !          1571:     buffer->ParameterListBlock.BlockLength[0] =
        !          1572:         ((tapeSetMediaParams->BlockSize >> 16) & 0xFF);
        !          1573:     buffer->ParameterListBlock.BlockLength[1] =
        !          1574:         ((tapeSetMediaParams->BlockSize >> 8) & 0xFF);
        !          1575:     buffer->ParameterListBlock.BlockLength[2] =
        !          1576:         (tapeSetMediaParams->BlockSize & 0xFF);
        !          1577: 
        !          1578:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          1579:                                 &srb,
        !          1580:                                 buffer,
        !          1581:                                 sizeof( MODE_PARM_READ_WRITE_DATA ),
        !          1582:                                 TRUE);
        !          1583: 
        !          1584:     ExFreePool(buffer);
        !          1585: 
        !          1586:     return status;
        !          1587: 
        !          1588: } // end TapeSetMediaParameters()
        !          1589: 
        !          1590: 
        !          1591: NTSTATUS
        !          1592: TapeSetPosition(
        !          1593:     IN PDEVICE_OBJECT DeviceObject,
        !          1594:     IN PIRP Irp
        !          1595:     )
        !          1596: 
        !          1597: /*++
        !          1598: Routine Description:
        !          1599: 
        !          1600:     This routine sets the position of the tape.
        !          1601: 
        !          1602: Arguments:
        !          1603: 
        !          1604:     DeviceObject
        !          1605:     Irp
        !          1606: 
        !          1607: Return Value:
        !          1608: 
        !          1609:     NTSTATUS
        !          1610: 
        !          1611: --*/
        !          1612: 
        !          1613: {
        !          1614:     PDEVICE_EXTENSION   deviceExtension = DeviceObject->DeviceExtension;
        !          1615:     PTAPE_DATA          tapeData = (PTAPE_DATA)(deviceExtension + 1);
        !          1616:     PTAPE_SET_POSITION  tapeSetPosition = Irp->AssociatedIrp.SystemBuffer;
        !          1617:     SCSI_REQUEST_BLOCK  srb;
        !          1618:     PCDB                cdb = (PCDB)srb.Cdb;
        !          1619:     NTSTATUS            status;
        !          1620: 
        !          1621:     if (tapeSetPosition->Immediate) {
        !          1622:         switch (tapeSetPosition->Method) {
        !          1623:             case TAPE_REWIND:
        !          1624:             case TAPE_ABSOLUTE_BLOCK:
        !          1625:             case TAPE_LOGICAL_BLOCK:
        !          1626:                 break;
        !          1627: 
        !          1628:             case TAPE_SPACE_END_OF_DATA:
        !          1629:             case TAPE_SPACE_RELATIVE_BLOCKS:
        !          1630:             case TAPE_SPACE_FILEMARKS:
        !          1631:             case TAPE_SPACE_SEQUENTIAL_FMKS:
        !          1632:             case TAPE_SPACE_SETMARKS:
        !          1633:             case TAPE_SPACE_SEQUENTIAL_SMKS:
        !          1634:             default:
        !          1635:                 return STATUS_NOT_IMPLEMENTED;
        !          1636:         }
        !          1637:     }
        !          1638: 
        !          1639:     //
        !          1640:     // Zero CDB in SRB on stack.
        !          1641:     //
        !          1642: 
        !          1643:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1644: 
        !          1645:     //
        !          1646:     // Set timeout value.
        !          1647:     //
        !          1648: 
        !          1649:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !          1650: 
        !          1651:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1652: 
        !          1653:     //
        !          1654:     // Set immediate bit if indicated.
        !          1655:     //
        !          1656: 
        !          1657:     cdb->CDB6GENERIC.Immediate = tapeSetPosition->Immediate;
        !          1658: 
        !          1659:     switch (tapeSetPosition->Method) {
        !          1660:         case TAPE_REWIND:
        !          1661:             DebugPrint((3,"TapeIoControl: Rewind Tape\n"));
        !          1662:             cdb->CDB6GENERIC.OperationCode = SCSIOP_REWIND;
        !          1663: 
        !          1664:             break;
        !          1665: 
        !          1666:         case TAPE_ABSOLUTE_BLOCK:
        !          1667:             DebugPrint((3,"TapeIoControl: Position Tape to an Absolute Block\n"));
        !          1668: 
        !          1669:             srb.TimeOutValue = 360;
        !          1670: 
        !          1671:             cdb->CDB6GENERIC.OperationCode = SCSIOP_SEEK_BLOCK;
        !          1672: 
        !          1673:             cdb->CDB6GENERIC.CommandUniqueBytes[0] =
        !          1674:                 ((tapeSetPosition->Offset.LowPart >> 16) & 0xFF);
        !          1675:             cdb->CDB6GENERIC.CommandUniqueBytes[1] =
        !          1676:                 ((tapeSetPosition->Offset.LowPart >> 8) & 0xFF);
        !          1677:             cdb->CDB6GENERIC.CommandUniqueBytes[2] =
        !          1678:                 (tapeSetPosition->Offset.LowPart & 0xFF);
        !          1679:             break;
        !          1680: 
        !          1681:         case TAPE_LOGICAL_BLOCK:
        !          1682:             DebugPrint((3,"TapeIoControl: Position Tape to a Logical Block\n"));
        !          1683: 
        !          1684:             srb.TimeOutValue = 360;
        !          1685: 
        !          1686:             cdb->LOCATE.OperationCode = SCSIOP_LOCATE;
        !          1687: 
        !          1688:             srb.CdbLength = CDB10GENERIC_LENGTH;
        !          1689: 
        !          1690:             if ((tapeSetPosition->Partition != (ULONG)0) &&
        !          1691:                 (tapeSetPosition->Partition != (ULONG)tapeData->CurrentPartition) &&
        !          1692:                 gb_PartitionCount > 1) {
        !          1693:                 cdb->LOCATE.CPBit = SETBITON;
        !          1694:                 cdb->LOCATE.Partition =
        !          1695:                     tapeSetPosition->Partition - 1;
        !          1696:             }
        !          1697:             cdb->LOCATE.LogicalBlockAddress[0] =
        !          1698:                 ((tapeSetPosition->Offset.LowPart >> 24) & 0xFF);
        !          1699:             cdb->LOCATE.LogicalBlockAddress[1] =
        !          1700:                 ((tapeSetPosition->Offset.LowPart >> 16) & 0xFF);
        !          1701:             cdb->LOCATE.LogicalBlockAddress[2] =
        !          1702:                 ((tapeSetPosition->Offset.LowPart >> 8) & 0xFF);
        !          1703:             cdb->LOCATE.LogicalBlockAddress[3] =
        !          1704:                 (tapeSetPosition->Offset.LowPart & 0xFF);
        !          1705: 
        !          1706:             break;
        !          1707: 
        !          1708:         case TAPE_SPACE_END_OF_DATA:
        !          1709:             DebugPrint((3,"TapeIoControl: Position Tape to End-of-Data\n"));
        !          1710:             cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
        !          1711:             cdb->SPACE_TAPE_MARKS.Code = 3;
        !          1712:             break;
        !          1713: 
        !          1714:         case TAPE_SPACE_RELATIVE_BLOCKS:
        !          1715:             DebugPrint((3,"TapeIoControl: Position Tape by Spacing Blocks\n"));
        !          1716:             cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
        !          1717:             cdb->SPACE_TAPE_MARKS.Code = 0;
        !          1718:             cdb->SPACE_TAPE_MARKS.NumMarksMSB =
        !          1719:                 ((tapeSetPosition->Offset.LowPart >> 16) & 0xFF);
        !          1720:             cdb->SPACE_TAPE_MARKS.NumMarks =
        !          1721:                 ((tapeSetPosition->Offset.LowPart >> 8) & 0xFF);
        !          1722:             cdb->SPACE_TAPE_MARKS.NumMarksLSB =
        !          1723:                 (tapeSetPosition->Offset.LowPart & 0xFF);
        !          1724:             break;
        !          1725: 
        !          1726:         case TAPE_SPACE_FILEMARKS:
        !          1727:             DebugPrint((3,"TapeIoControl: Position Tape by Spacing Filemarks\n"));
        !          1728:             cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
        !          1729:             cdb->SPACE_TAPE_MARKS.Code = 1;
        !          1730:             cdb->SPACE_TAPE_MARKS.NumMarksMSB =
        !          1731:                 ((tapeSetPosition->Offset.LowPart >> 16) & 0xFF);
        !          1732:             cdb->SPACE_TAPE_MARKS.NumMarks =
        !          1733:                 ((tapeSetPosition->Offset.LowPart >> 8) & 0xFF);
        !          1734:             cdb->SPACE_TAPE_MARKS.NumMarksLSB =
        !          1735:                 (tapeSetPosition->Offset.LowPart & 0xFF);
        !          1736:             break;
        !          1737: 
        !          1738:         case TAPE_SPACE_SEQUENTIAL_FMKS:
        !          1739:             DebugPrint((3,"TapeIoControl: Position Tape by Spacing Sequential Filemarks\n"));
        !          1740:             cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
        !          1741:             cdb->SPACE_TAPE_MARKS.Code = 2;
        !          1742:             cdb->SPACE_TAPE_MARKS.NumMarksMSB =
        !          1743:                 ((tapeSetPosition->Offset.LowPart >> 16) & 0xFF);
        !          1744:             cdb->SPACE_TAPE_MARKS.NumMarks =
        !          1745:                 ((tapeSetPosition->Offset.LowPart >> 8) & 0xFF);
        !          1746:             cdb->SPACE_TAPE_MARKS.NumMarksLSB =
        !          1747:                 (tapeSetPosition->Offset.LowPart & 0xFF);
        !          1748:             break;
        !          1749: 
        !          1750:         case TAPE_SPACE_SETMARKS:
        !          1751:             DebugPrint((3,"TapeIoControl: Position Tape by Spacing Setmarks\n"));
        !          1752:             cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
        !          1753:             cdb->SPACE_TAPE_MARKS.Code = 4;
        !          1754:             cdb->SPACE_TAPE_MARKS.NumMarksMSB =
        !          1755:                 ((tapeSetPosition->Offset.LowPart >> 16) & 0xFF);
        !          1756:             cdb->SPACE_TAPE_MARKS.NumMarks =
        !          1757:                 ((tapeSetPosition->Offset.LowPart >> 8) & 0xFF);
        !          1758:             cdb->SPACE_TAPE_MARKS.NumMarksLSB =
        !          1759:                 (tapeSetPosition->Offset.LowPart & 0xFF);
        !          1760:             break;
        !          1761: 
        !          1762:         case TAPE_SPACE_SEQUENTIAL_SMKS:
        !          1763:         default:
        !          1764:             DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n"));
        !          1765:             return STATUS_INVALID_DEVICE_REQUEST;
        !          1766:     }
        !          1767: 
        !          1768:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          1769:                                 &srb,
        !          1770:                                 NULL,
        !          1771:                                 0,
        !          1772:                                 FALSE);
        !          1773: 
        !          1774:     if (NT_SUCCESS(status)) {
        !          1775:         switch (tapeSetPosition->Method) {
        !          1776:             case TAPE_LOGICAL_BLOCK:
        !          1777:                 tapeData->CurrentPartition = tapeSetPosition->Partition;
        !          1778:                 break;
        !          1779:         }
        !          1780:     }
        !          1781: 
        !          1782:     return status;
        !          1783: 
        !          1784: } // end TapeSetPosition()
        !          1785: 
        !          1786: 
        !          1787: BOOLEAN
        !          1788: TapeVerifyInquiry(
        !          1789:     IN PSCSI_INQUIRY_DATA LunInfo
        !          1790:     )
        !          1791: 
        !          1792: /*++
        !          1793: Routine Description:
        !          1794: 
        !          1795:     This routine determines if the driver should claim this device.
        !          1796: 
        !          1797: Arguments:
        !          1798: 
        !          1799:     LunInfo
        !          1800: 
        !          1801: Return Value:
        !          1802: 
        !          1803:     TRUE - driver should claim this device.
        !          1804:     FALSE - driver should not claim this device.
        !          1805: 
        !          1806: --*/
        !          1807: 
        !          1808: {
        !          1809:     PINQUIRYDATA inquiryData;
        !          1810: 
        !          1811:     DebugPrint((3,"TapeIoControl: Verify Tape Inquiry Data\n"));
        !          1812: 
        !          1813:     inquiryData = (PVOID)LunInfo->InquiryData;
        !          1814: 
        !          1815:     //
        !          1816:     //  Determine, from the Product ID field in the
        !          1817:     //  inquiry data, whether or not to "claim" this drive.
        !          1818:     //
        !          1819: 
        !          1820:     if (WhichIsIt(inquiryData)) {
        !          1821: 
        !          1822:         RtlMoveMemory(gb_VendorId,inquiryData->VendorId,8);
        !          1823:         RtlMoveMemory(gb_ProductId,inquiryData->ProductId,16);
        !          1824:         return TRUE;
        !          1825: 
        !          1826:     }
        !          1827:     return FALSE;
        !          1828: 
        !          1829: } // end TapeVerifyInquiry()
        !          1830: 
        !          1831: 
        !          1832: NTSTATUS
        !          1833: TapeWriteMarks(
        !          1834:     IN PDEVICE_OBJECT DeviceObject,
        !          1835:     IN PIRP Irp
        !          1836:     )
        !          1837: 
        !          1838: /*++
        !          1839: Routine Description:
        !          1840: 
        !          1841:     This routine writes tapemarks on the tape.
        !          1842: 
        !          1843: Arguments:
        !          1844: 
        !          1845:     DeviceObject
        !          1846:     Irp
        !          1847: 
        !          1848: Return Value:
        !          1849: 
        !          1850:     NTSTATUS
        !          1851: 
        !          1852: --*/
        !          1853: 
        !          1854: {
        !          1855:     PDEVICE_EXTENSION   deviceExtension = DeviceObject->DeviceExtension;
        !          1856:     PTAPE_WRITE_MARKS   tapeWriteMarks = Irp->AssociatedIrp.SystemBuffer;
        !          1857:     SCSI_REQUEST_BLOCK  srb;
        !          1858:     PCDB                cdb = (PCDB)srb.Cdb;
        !          1859:     NTSTATUS            status;
        !          1860: 
        !          1861:     //
        !          1862:     // Zero CDB in SRB on stack.
        !          1863:     //
        !          1864: 
        !          1865:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1866: 
        !          1867:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1868: 
        !          1869:     cdb->WRITE_TAPE_MARKS.OperationCode = SCSIOP_WRITE_FILEMARKS;
        !          1870: 
        !          1871:     cdb->WRITE_TAPE_MARKS.TransferLength[0] =
        !          1872:         ((tapeWriteMarks->Count >> 16) & 0xFF);
        !          1873: 
        !          1874:     cdb->WRITE_TAPE_MARKS.TransferLength[1] =
        !          1875:         ((tapeWriteMarks->Count >> 8) & 0xFF);
        !          1876: 
        !          1877:     cdb->WRITE_TAPE_MARKS.TransferLength[2] =
        !          1878:         (tapeWriteMarks->Count & 0xFF);
        !          1879: 
        !          1880:     //
        !          1881:     // Set timeout value.
        !          1882:     //
        !          1883: 
        !          1884:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !          1885: 
        !          1886:     switch (tapeWriteMarks->Type) {
        !          1887:         case TAPE_SETMARKS:
        !          1888:             DebugPrint((3,"TapeIoControl: Write Setmarks to Tape\n"));
        !          1889:             cdb->WRITE_TAPE_MARKS.WriteSetMarks = SETBITON;
        !          1890:             break;
        !          1891: 
        !          1892:         case TAPE_FILEMARKS:
        !          1893:             DebugPrint((3,"TapeIoControl: Write Filemarks to Tape\n"));
        !          1894:             break;
        !          1895: 
        !          1896:         case TAPE_SHORT_FILEMARKS:
        !          1897:         case TAPE_LONG_FILEMARKS:
        !          1898:         default:
        !          1899:             DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n"));
        !          1900:             return STATUS_INVALID_DEVICE_REQUEST;
        !          1901:     }
        !          1902: 
        !          1903:     //
        !          1904:     // Set immediate bit if indicated.
        !          1905:     //
        !          1906: 
        !          1907:     cdb->WRITE_TAPE_MARKS.Immediate = tapeWriteMarks->Immediate;
        !          1908: 
        !          1909: 
        !          1910:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1911: 
        !          1912:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          1913:                                 &srb,
        !          1914:                                 NULL,
        !          1915:                                 0,
        !          1916:                                 FALSE);
        !          1917: 
        !          1918:     return status;
        !          1919: 
        !          1920: } // end TapeWriteMarks()
        !          1921: 
        !          1922: 
        !          1923: static
        !          1924: ULONG
        !          1925: WhichIsIt(
        !          1926:     IN PINQUIRYDATA InquiryData
        !          1927:     )
        !          1928: 
        !          1929: /*++
        !          1930: Routine Description:
        !          1931: 
        !          1932:     This routine determines a drive's identity from the Product ID field
        !          1933:     in its inquiry data.
        !          1934: 
        !          1935: Arguments:
        !          1936: 
        !          1937:     InquiryData (from an Inquiry command)
        !          1938: 
        !          1939: Return Value:
        !          1940: 
        !          1941:     driveID
        !          1942: 
        !          1943: --*/
        !          1944: 
        !          1945: {
        !          1946:     if (RtlCompareMemory(InquiryData->VendorId,"ARCHIVE ",8) == 8) {
        !          1947: 
        !          1948:         if (RtlCompareMemory(InquiryData->ProductId,"Python",6) == 6) {
        !          1949:             return ARCHIVE_PYTHON;
        !          1950:         }
        !          1951: 
        !          1952:     }
        !          1953: 
        !          1954:     if (RtlCompareMemory(InquiryData->VendorId,"DEC     ",8) == 8) {
        !          1955: 
        !          1956:         if (RtlCompareMemory(InquiryData->ProductId,"TLZ06",5) == 5) {
        !          1957:             return DEC_TLZ06;
        !          1958:         }
        !          1959: 
        !          1960:     }
        !          1961: 
        !          1962:     if (RtlCompareMemory(InquiryData->VendorId,"EXABYTE ",8) == 8) {
        !          1963: 
        !          1964:         if (RtlCompareMemory(InquiryData->ProductId,"EXB-4200 ",9) == 9) {
        !          1965:             return EXABYTE_4200;
        !          1966:         }
        !          1967: 
        !          1968:         if (RtlCompareMemory(InquiryData->ProductId,"EXB-4200c",9) == 9) {
        !          1969:             return EXABYTE_4200C;
        !          1970:         }
        !          1971: 
        !          1972:     }
        !          1973: 
        !          1974:     if (RtlCompareMemory(InquiryData->VendorId,"HP      ",8) == 8) {
        !          1975: 
        !          1976:         if (RtlCompareMemory(InquiryData->ProductId,"HP35470A",8) == 8) {
        !          1977:             return HP_35470A;
        !          1978:         }
        !          1979: 
        !          1980:         if (RtlCompareMemory(InquiryData->ProductId,"HP35480A",8) == 8) {
        !          1981:             return HP_35480A;
        !          1982:         }
        !          1983: 
        !          1984:         if (RtlCompareMemory(InquiryData->ProductId,"IBM35480A",9) == 9) {
        !          1985:             return HP_IBM35480A;
        !          1986:         }
        !          1987: 
        !          1988:     }
        !          1989: 
        !          1990:     if (RtlCompareMemory(InquiryData->VendorId,"WangDAT ",8) == 8) {
        !          1991: 
        !          1992:         if (RtlCompareMemory(InquiryData->ProductId,"Model 1300",10) == 10) {
        !          1993:             return WANGDAT_1300;
        !          1994:         }
        !          1995: 
        !          1996:         if (RtlCompareMemory(InquiryData->ProductId,"Model 3100",10) == 10) {
        !          1997:             return WANGDAT_3100;
        !          1998:         }
        !          1999: 
        !          2000:         if (RtlCompareMemory(InquiryData->ProductId,"Model 3200",10) == 10) {
        !          2001:             return WANGDAT_3200;
        !          2002:         }
        !          2003: 
        !          2004:     }
        !          2005: 
        !          2006:     return 0;
        !          2007: }

unix.superglobalmegacorp.com

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