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

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1992 Microsoft Corporation
        !             4: 
        !             5: Module Name:
        !             6: 
        !             7:     tandqic.c
        !             8: 
        !             9: Abstract:
        !            10: 
        !            11:     This module contains device specific routines for Tandberg QIC
        !            12:     drives with SCSI-2 interfaces -- TDC 4220, TDC 4120, TDC 3820,
        !            13:     and TDC 3660.
        !            14: 
        !            15: Author:
        !            16: 
        !            17:     Mike Colandreo  (Maynard)
        !            18: 
        !            19: Environment:
        !            20: 
        !            21:     kernel mode only
        !            22: 
        !            23: Revision History:
        !            24: 
        !            25: --*/
        !            26: 
        !            27: #include "ntddk.h"
        !            28: #include "tape.h"
        !            29: #include "physlogi.h"
        !            30: 
        !            31: //
        !            32: //  Internal (module wide) defines that symbolize
        !            33: //  non-QFA mode and the two QFA mode partitions.
        !            34: //
        !            35: #define NO_PARTITIONS        0  // non-QFA mode
        !            36: #define DIRECTORY_PARTITION  1  // QFA mode, directory partition #
        !            37: #define DATA_PARTITION       2  // QFA mode, data partition #
        !            38: 
        !            39: //
        !            40: //  Internal (module wide) defines that symbolize
        !            41: //  the Tandberg QIC drives supported by this module.
        !            42: //
        !            43: #define TDC_3600  (ULONG)1  // aka the TDC 3660
        !            44: #define TDC_3800  (ULONG)2  // aka the TDC 3820
        !            45: #define TDC_4100  (ULONG)3  // aka the TDC 4120
        !            46: #define TDC_4200  (ULONG)4  // aka the TDC 4220
        !            47: 
        !            48: //
        !            49: //  Function Prototype(s) for internal function(s)
        !            50: //
        !            51: static
        !            52: NTSTATUS
        !            53: GetInquiryInformationData (
        !            54:     IN  PDEVICE_OBJECT  DeviceObject,
        !            55:     IN  PIRP            Irp,
        !            56:     OUT PINQUIRYDATA    InquiryBuffer
        !            57:     );
        !            58: 
        !            59: static
        !            60: NTSTATUS
        !            61: RewindToBOT(
        !            62:     IN PDEVICE_OBJECT  DeviceObject,
        !            63:     IN PIRP            Irp
        !            64:     );
        !            65:     
        !            66: static
        !            67: ULONG
        !            68: WhichIsIt(
        !            69:     IN PINQUIRYDATA  InquiryData
        !            70:     );
        !            71: 
        !            72: 
        !            73: NTSTATUS
        !            74: TapeCreatePartition(
        !            75:     IN PDEVICE_OBJECT DeviceObject,
        !            76:     IN PIRP Irp
        !            77:     )
        !            78: 
        !            79: /*++
        !            80: Routine Description:
        !            81: 
        !            82:     This routine can either "create" two, fixed, QFA partitions on a QIC
        !            83:     tape by selecting/enabling the drive's dual-partition, QFA mode or
        !            84:     return the drive to the not partitioned mode (i.e., disable QFA mode).
        !            85:     Note that this function "creates" two partitions only in a conceptual
        !            86:     sense -- it does not physically affect tape.
        !            87:     
        !            88: Arguments:
        !            89: 
        !            90:     DeviceObject
        !            91:     Irp
        !            92: 
        !            93: Return Value:
        !            94: 
        !            95:     NTSTATUS
        !            96: 
        !            97: --*/
        !            98: 
        !            99: {
        !           100:     PDEVICE_EXTENSION      deviceExtension = DeviceObject->DeviceExtension;
        !           101:     PTAPE_CREATE_PARTITION tapePartition = Irp->AssociatedIrp.SystemBuffer;
        !           102:     PTAPE_DATA             tapeData = (PTAPE_DATA)(deviceExtension + 1);
        !           103:     PMODE_MEDIUM_PART_PAGE buffer;
        !           104:     SCSI_REQUEST_BLOCK     srb;
        !           105:     PCDB                   cdb = (PCDB)srb.Cdb;
        !           106:     NTSTATUS               status;
        !           107: 
        !           108:     //
        !           109:     //  Only support 2 partitions, QFA mode
        !           110:     //  Partition 1 = Used as directory
        !           111:     //  Partition 0 = used as data
        !           112:     //
        !           113:     //  Note that 0 & 1 are partition numbers used
        !           114:     //  by the drive -- they are not tape API partition
        !           115:     //  numbers.
        !           116:     //
        !           117:     
        !           118:     DebugPrint((3,"TapeCreatePartition: Enter routine\n"));
        !           119: 
        !           120:     switch (tapePartition->Method) {
        !           121:         case TAPE_FIXED_PARTITIONS:
        !           122:             DebugPrint((3,"TapeCreatePartition: fixed partitions\n"));
        !           123:             break;
        !           124: 
        !           125:         case TAPE_SELECT_PARTITIONS:
        !           126:         case TAPE_INITIATOR_PARTITIONS:
        !           127:         default:
        !           128:             DebugPrint((1,"TapeCreatePartition: "));
        !           129:             DebugPrint((1,"PartitionMethod -- operation not supported\n"));
        !           130:             return STATUS_NOT_IMPLEMENTED;
        !           131:     }
        !           132: 
        !           133:     //
        !           134:     // Must rewind to BOT before one can enable/disable QFA mode.
        !           135:     // Changing the value of the FDP bit is only valid at BOT.
        !           136:     // FDP bit is used to enable/disable "additional partitions"
        !           137:     // (mode sense command).
        !           138:     //
        !           139:     
        !           140:     DebugPrint((3,"TapeCreatePartition: SendSrb (rewind)\n"));
        !           141: 
        !           142:     status = RewindToBOT(DeviceObject, Irp);
        !           143: 
        !           144:     if (!NT_SUCCESS(status)) {
        !           145:         DebugPrint((1,"TapeCreatePartition: rewind, SendSrb unsuccessful\n"));
        !           146:         return status;
        !           147:     }
        !           148:     
        !           149:     //
        !           150:     // Performing mode select command, medium partition parameters page,
        !           151:     // to enable/disable QFA mode: set the FDP bit accordingly.
        !           152:     //
        !           153:     
        !           154:     buffer = ExAllocatePool(NonPagedPoolCacheAligned,
        !           155:                             sizeof(MODE_MEDIUM_PART_PAGE));
        !           156: 
        !           157:     if (!buffer) {
        !           158:         DebugPrint((1,"TapeCreatePartition: insufficient resources (buffer)\n"));
        !           159:         return STATUS_INSUFFICIENT_RESOURCES;
        !           160:     }
        !           161: 
        !           162:     RtlZeroMemory(buffer, sizeof(MODE_MEDIUM_PART_PAGE));
        !           163: 
        !           164:     buffer->ParameterListHeader.DeviceSpecificParameter = 0x10;
        !           165:     
        !           166:     buffer->MediumPartPage.PageCode = MODE_PAGE_MEDIUM_PARTITION;
        !           167:     buffer->MediumPartPage.PageLength = 0x06;
        !           168:     buffer->MediumPartPage.MaximumAdditionalPartitions = 1;
        !           169: 
        !           170:     //
        !           171:     // Setup FDP bit to enable/disable "additional partition".
        !           172:     //
        !           173: 
        !           174:     if (tapePartition->Count == 0) {
        !           175:         buffer->MediumPartPage.FDPBit = SETBITOFF;
        !           176:     } else {
        !           177:         buffer->MediumPartPage.FDPBit = SETBITON;
        !           178:     }
        !           179:     
        !           180:     //
        !           181:     // Zero CDB in SRB on stack.
        !           182:     //
        !           183:     
        !           184:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           185:     
        !           186:     //
        !           187:     // Prepare SCSI command (CDB)
        !           188:     //
        !           189: 
        !           190:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !           191:     
        !           192:     cdb->MODE_SELECT.OperationCode  = SCSIOP_MODE_SELECT;
        !           193:     cdb->MODE_SELECT.PFBit = SETBITON;
        !           194:     cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_MEDIUM_PART_PAGE) - 4;
        !           195:          
        !           196:     //
        !           197:     // Set timeout value.
        !           198:     //
        !           199:     
        !           200:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !           201: 
        !           202:     //
        !           203:     // Send SCSI command (CDB) to device
        !           204:     //
        !           205:     
        !           206:     DebugPrint((3,"TapeCreatePartition: SendSrb (mode select)\n"));
        !           207: 
        !           208:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           209:                                          &srb,
        !           210:                                          buffer,
        !           211:                                          sizeof(MODE_MEDIUM_PART_PAGE) - 4,
        !           212:                                          TRUE);
        !           213:     
        !           214:     ExFreePool(buffer);
        !           215:     
        !           216:     if (NT_SUCCESS(status)) {
        !           217: 
        !           218:         if (tapePartition->Count == 0) {
        !           219:             tapeData->CurrentPartition = NO_PARTITIONS;
        !           220:             DebugPrint((3,"TapeCreatePartition: QFA disabled\n"));
        !           221:         } else {
        !           222:             tapeData->CurrentPartition = DATA_PARTITION;
        !           223:             DebugPrint((3,"TapeCreatePartition: QFA enabled\n"));
        !           224:         }
        !           225: 
        !           226:     } else {
        !           227: 
        !           228:         DebugPrint((1,"TapeCreatePartition: mode select, SendSrb unsuccessful\n"));
        !           229: 
        !           230:     }
        !           231: 
        !           232:     return status;
        !           233: 
        !           234: } // end TapeCreatePartition()
        !           235: 
        !           236: 
        !           237: NTSTATUS
        !           238: TapeErase(
        !           239:     IN PDEVICE_OBJECT DeviceObject,
        !           240:     IN PIRP Irp
        !           241:     )
        !           242: 
        !           243: /*++
        !           244: Routine Description:
        !           245: 
        !           246:     This routine erases the entire tape. The Tandberg QIC drives cannot
        !           247:     partially erase tape. Positioning the tape at BOT is a prerequisite:
        !           248:     the drive rejects the command if the tape is not at BOT.
        !           249: 
        !           250: Arguments:
        !           251: 
        !           252:     DeviceObject
        !           253:     Irp
        !           254: 
        !           255: Return Value:
        !           256: 
        !           257:     NTSTATUS
        !           258: 
        !           259: --*/
        !           260: 
        !           261: {
        !           262:     PDEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
        !           263:     PTAPE_ERASE        tapeErase = Irp->AssociatedIrp.SystemBuffer;
        !           264:     PTAPE_DATA         tapeData = (PTAPE_DATA)(deviceExtension + 1);
        !           265:     SCSI_REQUEST_BLOCK srb;
        !           266:     PCDB               cdb = (PCDB)srb.Cdb;
        !           267:     NTSTATUS           status;
        !           268: 
        !           269:     DebugPrint((3,"TapeErase: Enter routine\n"));
        !           270: 
        !           271:     if (tapeErase->Immediate) {
        !           272:         switch (tapeErase->Type) {
        !           273:             case TAPE_ERASE_LONG:
        !           274:                 DebugPrint((3,"TapeErase: immediate\n"));
        !           275:                 break;
        !           276: 
        !           277:             case TAPE_ERASE_SHORT:
        !           278:             default:
        !           279:                 DebugPrint((1,"TapeErase: EraseType, immediate -- operation not supported\n"));
        !           280:                 return STATUS_NOT_IMPLEMENTED;
        !           281:         }
        !           282:     }
        !           283: 
        !           284:     switch (tapeErase->Type) {
        !           285:         case TAPE_ERASE_LONG:
        !           286:             DebugPrint((3,"TapeErase: long\n"));
        !           287:             break;
        !           288: 
        !           289:         case TAPE_ERASE_SHORT:
        !           290:         default:
        !           291:             DebugPrint((1,"TapeErase: EraseType -- operation not supported\n"));
        !           292:             return STATUS_NOT_IMPLEMENTED;
        !           293:     }
        !           294: 
        !           295:     //
        !           296:     // Zero CDB in SRB on stack.
        !           297:     //
        !           298: 
        !           299:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           300: 
        !           301:     //
        !           302:     // Prepare SCSI command (CDB)
        !           303:     //
        !           304: 
        !           305:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !           306: 
        !           307:     cdb->ERASE.OperationCode = SCSIOP_ERASE;
        !           308:     cdb->ERASE.Immediate = tapeErase->Immediate;
        !           309:     cdb->ERASE.Long = SETBITON;
        !           310: 
        !           311:     //
        !           312:     // Set timeout value.
        !           313:     //
        !           314: 
        !           315:     srb.TimeOutValue = 360;
        !           316: 
        !           317:     //
        !           318:     // Send SCSI command (CDB) to device
        !           319:     //
        !           320: 
        !           321:     DebugPrint((3,"TapeErase: SendSrb (erase)\n"));
        !           322: 
        !           323:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           324:                                          &srb,
        !           325:                                          NULL,
        !           326:                                          0,
        !           327:                                          FALSE);
        !           328: 
        !           329:     if (!NT_SUCCESS(status)) {
        !           330:         DebugPrint((1,"TapeErase: erase, SendSrb unsuccessful\n"));
        !           331:         return status;
        !           332:     }
        !           333: 
        !           334:     if (tapeData->CurrentPartition) {
        !           335:         tapeData->CurrentPartition = DATA_PARTITION;
        !           336:     }
        !           337: 
        !           338:     return status;
        !           339: 
        !           340: } // end TapeErase()
        !           341: 
        !           342: 
        !           343: VOID
        !           344: TapeError(
        !           345:     PDEVICE_OBJECT DeviceObject,
        !           346:     PSCSI_REQUEST_BLOCK Srb,
        !           347:     NTSTATUS *Status,
        !           348:     BOOLEAN *Retry
        !           349:     )
        !           350: 
        !           351: /*++
        !           352: 
        !           353: Routine Description:
        !           354: 
        !           355:     When a request completes with error, the routine InterpretSenseInfo is
        !           356:     called to determine from the sense data whether the request should be
        !           357:     retried and what NT status to set in the IRP. Then this routine is called
        !           358:     for tape requests to handle tape-specific errors and update the nt status
        !           359:     and retry boolean.
        !           360: 
        !           361: Arguments:
        !           362: 
        !           363:     DeviceObject - Supplies a pointer to the device object.
        !           364: 
        !           365:     Srb - Supplies a pointer to the failing Srb.
        !           366: 
        !           367:     Status - NT Status used to set the IRP's completion status.
        !           368: 
        !           369:     Retry - Indicates that this request should be retried.
        !           370: 
        !           371: Return Value:
        !           372: 
        !           373:     None.
        !           374: 
        !           375: --*/
        !           376: 
        !           377: {
        !           378:     PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
        !           379:     PSENSE_DATA       senseBuffer = Srb->SenseInfoBuffer;
        !           380:     NTSTATUS          status = *Status;
        !           381:     BOOLEAN           retry = *Retry;
        !           382: 
        !           383:     DebugPrint((3,"TapeError: Enter routine\n"));
        !           384:     DebugPrint((1,"TapeError: Status 0x%.8X, Retry %d\n", status, retry));
        !           385:     return;
        !           386: 
        !           387: } // end TapeError()
        !           388: 
        !           389: 
        !           390: NTSTATUS
        !           391: TapeGetDriveParameters(
        !           392:     IN PDEVICE_OBJECT DeviceObject,
        !           393:     IN PIRP Irp
        !           394:     )
        !           395: 
        !           396: /*++
        !           397: Routine Description:
        !           398: 
        !           399:     This routine determines and returns the "drive parameters" of the
        !           400:     Tandberg QIC tape drive associated with "DeviceObject". From time
        !           401:     to time, the drive paramater set of a given drive will vary. It will
        !           402:     change as drive operating characteristics change: e.g., tape media
        !           403:     type loaded, recording density of the media type loaded, etc.
        !           404: 
        !           405: Arguments:
        !           406: 
        !           407:     DeviceObject
        !           408:     Irp
        !           409: 
        !           410: Return Value:
        !           411: 
        !           412:     NTSTATUS
        !           413: 
        !           414: --*/
        !           415: 
        !           416: {
        !           417:     PDEVICE_EXTENSION          deviceExtension = DeviceObject->DeviceExtension;
        !           418:     PTAPE_GET_DRIVE_PARAMETERS tapeGetDriveParams = Irp->AssociatedIrp.SystemBuffer;
        !           419:     PMODE_PARM_READ_WRITE_DATA modeParmBuffer;
        !           420:     PREAD_BLOCK_LIMITS_DATA    blockLimits;
        !           421:     PINQUIRYDATA               inquiryBuffer;
        !           422:     UCHAR                      densityCode;
        !           423:     UCHAR                      mediumType;
        !           424:     ULONG                      tapeBlockLength;
        !           425:     ULONG                      whichdrive;
        !           426:     SCSI_REQUEST_BLOCK         srb;
        !           427:     PCDB                       cdb = (PCDB)srb.Cdb;
        !           428:     NTSTATUS                   status;
        !           429: 
        !           430:     DebugPrint((3,"TapeGetDriveParameters: Enter routine\n"));
        !           431:     
        !           432:     RtlZeroMemory(tapeGetDriveParams, sizeof(TAPE_GET_DRIVE_PARAMETERS));
        !           433:     Irp->IoStatus.Information = sizeof(TAPE_GET_DRIVE_PARAMETERS);
        !           434: 
        !           435:     modeParmBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
        !           436:                                     sizeof(MODE_PARM_READ_WRITE_DATA));
        !           437: 
        !           438:     if (!modeParmBuffer) {
        !           439:         DebugPrint((1,"TapeGetDriveParameters: insufficient resources (modeParmBuffer)\n"));
        !           440:         return STATUS_INSUFFICIENT_RESOURCES;
        !           441:     }
        !           442: 
        !           443:     RtlZeroMemory(modeParmBuffer, sizeof(MODE_PARM_READ_WRITE_DATA));
        !           444: 
        !           445:     //
        !           446:     // Zero CDB in SRB on stack.
        !           447:     //
        !           448: 
        !           449:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           450: 
        !           451:     //
        !           452:     // Prepare SCSI command (CDB)
        !           453:     //
        !           454: 
        !           455:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !           456: 
        !           457:     cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
        !           458:     cdb->MODE_SENSE.AllocationLength = sizeof(MODE_PARM_READ_WRITE_DATA);
        !           459: 
        !           460:     //
        !           461:     // Set timeout value.
        !           462:     //
        !           463: 
        !           464:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !           465: 
        !           466:     //
        !           467:     // Send SCSI command (CDB) to device
        !           468:     //
        !           469: 
        !           470:     DebugPrint((3,"TapeGetDriveParameters: SendSrb (mode sense)\n"));
        !           471: 
        !           472:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           473:                                          &srb,
        !           474:                                          modeParmBuffer,
        !           475:                                          sizeof(MODE_PARM_READ_WRITE_DATA),
        !           476:                                          FALSE);
        !           477: 
        !           478:     if (NT_SUCCESS(status)) {
        !           479: 
        !           480:         mediumType = modeParmBuffer->ParameterListHeader.MediumType;
        !           481:         densityCode = modeParmBuffer->ParameterListBlock.DensityCode;
        !           482:         tapeBlockLength  = modeParmBuffer->ParameterListBlock.BlockLength[2];
        !           483:         tapeBlockLength += (modeParmBuffer->ParameterListBlock.BlockLength[1] << 8);
        !           484:         tapeBlockLength += (modeParmBuffer->ParameterListBlock.BlockLength[0] << 16);
        !           485: 
        !           486:         switch (mediumType) {
        !           487:             case 1:
        !           488:                mediumType = DC600;
        !           489:                break;
        !           490: 
        !           491:             case 2:
        !           492:                mediumType = DC6150;
        !           493:                break;
        !           494: 
        !           495:             case 3:
        !           496:                mediumType = DC6320;
        !           497:                break;
        !           498: 
        !           499:         }
        !           500: 
        !           501:     }
        !           502: 
        !           503:     ExFreePool(modeParmBuffer);
        !           504: 
        !           505:     if (!NT_SUCCESS(status)) {
        !           506:         DebugPrint((1,"TapeGetDriveParameters: mode sense, SendSrb unsuccessful\n"));
        !           507:         return status;
        !           508:     }
        !           509: 
        !           510:     blockLimits = ExAllocatePool(NonPagedPoolCacheAligned,
        !           511:                                  sizeof(READ_BLOCK_LIMITS_DATA));
        !           512: 
        !           513:     if (!blockLimits) {
        !           514:         DebugPrint((1,"TapeGetDriveParameters: insufficient resources (blockLimits)\n"));
        !           515:         return STATUS_INSUFFICIENT_RESOURCES;
        !           516:     }
        !           517: 
        !           518:     RtlZeroMemory(blockLimits, sizeof(READ_BLOCK_LIMITS_DATA));
        !           519: 
        !           520:     //
        !           521:     // Zero CDB in SRB on stack.
        !           522:     //
        !           523: 
        !           524:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           525: 
        !           526:     //
        !           527:     // Prepare SCSI command (CDB)
        !           528:     //
        !           529: 
        !           530:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !           531: 
        !           532:     cdb->CDB6GENERIC.OperationCode = SCSIOP_READ_BLOCK_LIMITS;
        !           533: 
        !           534:     //
        !           535:     // Set timeout value.
        !           536:     //
        !           537: 
        !           538:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !           539: 
        !           540:     //
        !           541:     // Send SCSI command (CDB) to device
        !           542:     //
        !           543: 
        !           544:     DebugPrint((3,"TapeGetDriveParameters: SendSrb (read block limits)\n"));
        !           545: 
        !           546:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           547:                                          &srb,
        !           548:                                          blockLimits,
        !           549:                                          sizeof(READ_BLOCK_LIMITS_DATA),
        !           550:                                          FALSE);
        !           551: 
        !           552:     if (NT_SUCCESS(status)) {
        !           553:         tapeGetDriveParams->MaximumBlockSize = blockLimits->BlockMaximumSize[2];
        !           554:         tapeGetDriveParams->MaximumBlockSize += (blockLimits->BlockMaximumSize[1] << 8);
        !           555:         tapeGetDriveParams->MaximumBlockSize += (blockLimits->BlockMaximumSize[0] << 16);
        !           556:             
        !           557:         tapeGetDriveParams->MinimumBlockSize = blockLimits->BlockMinimumSize[1];
        !           558:         tapeGetDriveParams->MinimumBlockSize += (blockLimits->BlockMinimumSize[0] << 8);
        !           559:     }
        !           560: 
        !           561:     ExFreePool(blockLimits);
        !           562: 
        !           563:     if (!NT_SUCCESS(status)) {
        !           564:         DebugPrint((1,"TapeGetDriveParameters: read block limits, SendSrb unsuccessful\n"));
        !           565:         return status;
        !           566:     }
        !           567: 
        !           568:     inquiryBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
        !           569:                                    sizeof(INQUIRYDATA));
        !           570: 
        !           571:     if (!inquiryBuffer) {
        !           572:         DebugPrint((1,"TapeGetDriveParameters: insufficient resources (inquiryBuffer)\n"));
        !           573:         return STATUS_INSUFFICIENT_RESOURCES;
        !           574:     }
        !           575: 
        !           576:     RtlZeroMemory(inquiryBuffer, sizeof(INQUIRYDATA));
        !           577: 
        !           578:     //
        !           579:     // Send SCSI command (CDB) to device
        !           580:     //
        !           581: 
        !           582:     DebugPrint((3,"TapeGetDriveParameters: SendSrb (inquiry)\n"));
        !           583: 
        !           584:     status = GetInquiryInformationData(DeviceObject, Irp, inquiryBuffer);
        !           585: 
        !           586:     if (NT_SUCCESS(status)) {
        !           587: 
        !           588:         //
        !           589:         // Which drive do we have, TDC 3660, 3820, 4120 or 4220?
        !           590:         //
        !           591: 
        !           592:         whichdrive = WhichIsIt(inquiryBuffer);
        !           593:     }
        !           594: 
        !           595:     ExFreePool(inquiryBuffer);
        !           596: 
        !           597:     if (!NT_SUCCESS(status)) {
        !           598:         DebugPrint((1,"TapeGetDriveParameters: inquiry, SendSrb unsuccessful\n"));
        !           599:         return status;
        !           600:     }
        !           601:          
        !           602:     tapeGetDriveParams->ECC = 0;
        !           603:     tapeGetDriveParams->Compression = 0;
        !           604:     tapeGetDriveParams->DataPadding = 0;
        !           605:     tapeGetDriveParams->MaximumPartitionCount = 2;
        !           606:     
        !           607:     if ((whichdrive == TDC_4100) || (whichdrive == TDC_4200)) {
        !           608: 
        !           609:         tapeGetDriveParams->ReportSetmarks = TRUE;
        !           610: 
        !           611:         tapeGetDriveParams->FeaturesLow |=
        !           612:             TAPE_DRIVE_REPORT_SMKS;
        !           613: 
        !           614:         tapeGetDriveParams->FeaturesHigh |=
        !           615:             TAPE_DRIVE_SETMARKS |
        !           616:             TAPE_DRIVE_WRITE_SETMARKS;
        !           617: 
        !           618:     } 
        !           619: 
        !           620:     if (whichdrive != TDC_3600) {
        !           621:              
        !           622:         tapeGetDriveParams->FeaturesLow |=
        !           623:             TAPE_DRIVE_VARIABLE_BLOCK;
        !           624:             
        !           625:         tapeGetDriveParams->FeaturesHigh |=
        !           626:             TAPE_DRIVE_SET_BLOCK_SIZE;
        !           627: 
        !           628:     }
        !           629:     
        !           630:     switch (densityCode) {
        !           631:         case QIC_XX:
        !           632:             switch (mediumType) {
        !           633:                 case DC6320:
        !           634:                 case DC6525:
        !           635:                 case DC9100:
        !           636:                 case DC9100XL:
        !           637:                     tapeGetDriveParams->DefaultBlockSize = 1024;
        !           638:                     break;
        !           639: 
        !           640:                 default:
        !           641:                     tapeGetDriveParams->DefaultBlockSize = 512;
        !           642:                     break;
        !           643:             }
        !           644:             break;
        !           645: 
        !           646:         case QIC_525:
        !           647:         case QIC_1000:
        !           648:         case QIC_2GB:
        !           649:             tapeGetDriveParams->DefaultBlockSize = 1024;
        !           650:             break;
        !           651:             
        !           652:         default:
        !           653:             tapeGetDriveParams->DefaultBlockSize = 512;
        !           654:             break;
        !           655:     }
        !           656: 
        !           657:     tapeGetDriveParams->FeaturesLow |=
        !           658:         TAPE_DRIVE_FIXED |
        !           659:         TAPE_DRIVE_ERASE_LONG |
        !           660:         TAPE_DRIVE_ERASE_BOP_ONLY |
        !           661:         TAPE_DRIVE_ERASE_IMMEDIATE |
        !           662:         TAPE_DRIVE_FIXED_BLOCK |
        !           663:         TAPE_DRIVE_WRITE_PROTECT |
        !           664:         TAPE_DRIVE_GET_ABSOLUTE_BLK |
        !           665:         TAPE_DRIVE_GET_LOGICAL_BLK;
        !           666: 
        !           667:     tapeGetDriveParams->FeaturesHigh |=
        !           668:         TAPE_DRIVE_LOAD_UNLOAD |
        !           669:         TAPE_DRIVE_TENSION |
        !           670:         TAPE_DRIVE_LOCK_UNLOCK |
        !           671:         TAPE_DRIVE_REWIND_IMMEDIATE |
        !           672:         TAPE_DRIVE_LOAD_UNLD_IMMED |
        !           673:         TAPE_DRIVE_TENSION_IMMED |
        !           674:         TAPE_DRIVE_ABSOLUTE_BLK |
        !           675:         TAPE_DRIVE_LOGICAL_BLK |
        !           676:         TAPE_DRIVE_END_OF_DATA |
        !           677:         TAPE_DRIVE_RELATIVE_BLKS |
        !           678:         TAPE_DRIVE_FILEMARKS |
        !           679:         TAPE_DRIVE_SEQUENTIAL_FMKS |
        !           680:         TAPE_DRIVE_REVERSE_POSITION |
        !           681:         TAPE_DRIVE_WRITE_FILEMARKS |
        !           682:         TAPE_DRIVE_WRITE_MARK_IMMED;
        !           683: 
        !           684:     tapeGetDriveParams->FeaturesHigh &= ~TAPE_DRIVE_HIGH_FEATURES;
        !           685: 
        !           686:     DebugPrint((3,"TapeGetDriveParameters: FeaturesLow == 0x%.8X\n",
        !           687:         tapeGetDriveParams->FeaturesLow));
        !           688:     DebugPrint((3,"TapeGetDriveParameters: FeaturesHigh == 0x%.8X\n",
        !           689:         tapeGetDriveParams->FeaturesHigh));
        !           690: 
        !           691:     return status;
        !           692: 
        !           693: } // end TapeGetDriveParameters()
        !           694: 
        !           695: 
        !           696: NTSTATUS
        !           697: TapeGetMediaParameters(
        !           698:     IN PDEVICE_OBJECT DeviceObject,
        !           699:     IN PIRP Irp
        !           700:     )
        !           701: 
        !           702: /*++
        !           703: Routine Description:
        !           704: 
        !           705:     This routine determines and returns the "media parameters" of the
        !           706:     Tandberg QIC tape drive associated with "DeviceObject". Tape media
        !           707:     must be present (loaded) in the drive for this function to return
        !           708:     "no error".
        !           709: 
        !           710: Arguments:
        !           711: 
        !           712:     DeviceObject
        !           713:     Irp
        !           714: 
        !           715: Return Value:
        !           716: 
        !           717:     NTSTATUS
        !           718: 
        !           719: --*/
        !           720: 
        !           721: {
        !           722:     PDEVICE_EXTENSION            deviceExtension = DeviceObject->DeviceExtension;
        !           723:     PTAPE_DATA                   tapeData = (PTAPE_DATA)(deviceExtension + 1);
        !           724:     PTAPE_GET_MEDIA_PARAMETERS   tapeGetMediaParams = Irp->AssociatedIrp.SystemBuffer;
        !           725:     PMODE_TAPE_MEDIA_INFORMATION mediaInfoBuffer;
        !           726:     PMODE_DEVICE_CONFIG_PAGE     deviceConfigBuffer; 
        !           727:     ULONG                        sectorShift;
        !           728:     SCSI_REQUEST_BLOCK           srb;
        !           729:     PCDB                         cdb = (PCDB)srb.Cdb;
        !           730:     NTSTATUS                     status;
        !           731: 
        !           732:     DebugPrint((3,"TapeGetMediaParameters: Enter routine\n"));
        !           733: 
        !           734:     RtlZeroMemory(tapeGetMediaParams, sizeof(TAPE_GET_MEDIA_PARAMETERS));
        !           735:     Irp->IoStatus.Information = sizeof(TAPE_GET_MEDIA_PARAMETERS);
        !           736: 
        !           737:     //
        !           738:     // Zero CDB in SRB on stack.
        !           739:     //
        !           740: 
        !           741:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           742: 
        !           743:     //
        !           744:     // Prepare SCSI command (CDB)
        !           745:     //
        !           746: 
        !           747:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !           748: 
        !           749:     cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
        !           750: 
        !           751:     //
        !           752:     // Set timeout value.
        !           753:     //
        !           754: 
        !           755:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !           756: 
        !           757:     //
        !           758:     // Send SCSI command (CDB) to device
        !           759:     //
        !           760: 
        !           761:     DebugPrint((3,"TapeGetMediaParameters: SendSrb (test unit ready)\n"));
        !           762: 
        !           763:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           764:                                          &srb,
        !           765:                                          NULL,
        !           766:                                          0,
        !           767:                                          FALSE);
        !           768: 
        !           769:     if (!NT_SUCCESS(status)) {
        !           770:         DebugPrint((1,"TapeGetMediaParameters: test unit ready, SendSrb unsuccessful\n"));
        !           771:         return status;
        !           772:     }
        !           773: 
        !           774:     mediaInfoBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
        !           775:                                      sizeof(MODE_TAPE_MEDIA_INFORMATION));
        !           776: 
        !           777:     if (!mediaInfoBuffer) {
        !           778:         DebugPrint((1,"TapeGetMediaParameters: insufficient resources (mediaInfoBuffer)\n"));
        !           779:         return STATUS_INSUFFICIENT_RESOURCES;
        !           780:     }
        !           781: 
        !           782:     RtlZeroMemory(mediaInfoBuffer, sizeof(MODE_TAPE_MEDIA_INFORMATION));
        !           783: 
        !           784:     //
        !           785:     // Zero CDB in SRB on stack.
        !           786:     //
        !           787: 
        !           788:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           789: 
        !           790:     //
        !           791:     // Prepare SCSI command (CDB)
        !           792:     //
        !           793: 
        !           794:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !           795: 
        !           796:     cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
        !           797:     cdb->MODE_SENSE.PageCode = MODE_PAGE_MEDIUM_PARTITION;
        !           798:     cdb->MODE_SENSE.AllocationLength = sizeof(MODE_TAPE_MEDIA_INFORMATION) - 4;
        !           799: 
        !           800:     //
        !           801:     // Set timeout value.
        !           802:     //
        !           803: 
        !           804:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !           805: 
        !           806:     //
        !           807:     // Send SCSI command (CDB) to device
        !           808:     //
        !           809: 
        !           810:     DebugPrint((3,"TapeGetMediaParameters: SendSrb (mode sense #1)\n"));
        !           811: 
        !           812:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           813:                                          &srb,
        !           814:                                          mediaInfoBuffer,
        !           815:                                          sizeof(MODE_TAPE_MEDIA_INFORMATION) - 4,
        !           816:                                          FALSE);
        !           817: 
        !           818:     if (!NT_SUCCESS(status)) {
        !           819:         DebugPrint((1,"TapeGetMediaParameters: mode sense #1, SendSrb unsuccessful\n"));
        !           820:         ExFreePool(mediaInfoBuffer);
        !           821:         return status;
        !           822:     }
        !           823: 
        !           824:     if (mediaInfoBuffer->MediumPartPage.FDPBit) {
        !           825: 
        !           826:         deviceConfigBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
        !           827:                                             sizeof(MODE_DEVICE_CONFIG_PAGE));
        !           828: 
        !           829:         if (!deviceConfigBuffer) {
        !           830:             DebugPrint((1,"TapeGetMediaParameters: insufficient resources (deviceConfigBuffer)\n"));
        !           831:             ExFreePool(mediaInfoBuffer);
        !           832:             return STATUS_INSUFFICIENT_RESOURCES;
        !           833:         }
        !           834: 
        !           835:         RtlZeroMemory(deviceConfigBuffer, sizeof(MODE_DEVICE_CONFIG_PAGE));
        !           836: 
        !           837:         //
        !           838:         // Zero CDB in SRB on stack.
        !           839:         //
        !           840: 
        !           841:         RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           842: 
        !           843:         //
        !           844:         // Prepare SCSI command (CDB)
        !           845:         //
        !           846: 
        !           847:         srb.CdbLength = CDB6GENERIC_LENGTH;
        !           848: 
        !           849:         cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
        !           850:         cdb->MODE_SENSE.Dbd = SETBITON;
        !           851:         cdb->MODE_SENSE.PageCode = MODE_PAGE_DEVICE_CONFIG;
        !           852:         cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DEVICE_CONFIG_PAGE);
        !           853: 
        !           854:         //
        !           855:         // Set timeout value.
        !           856:         //
        !           857: 
        !           858:         srb.TimeOutValue = deviceExtension->TimeOutValue;
        !           859: 
        !           860:         //
        !           861:         // Send SCSI command (CDB) to device
        !           862:         //
        !           863: 
        !           864:         DebugPrint((3,"TapeGetMediaParameters: SendSrb (mode sense #2)\n"));
        !           865: 
        !           866:         status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           867:                                              &srb,
        !           868:                                              deviceConfigBuffer,
        !           869:                                              sizeof(MODE_DEVICE_CONFIG_PAGE),
        !           870:                                              FALSE);
        !           871: 
        !           872:         if (!NT_SUCCESS(status)) {
        !           873:             DebugPrint((1,"TapeGetMediaParameters: mode sense #2, SendSrb unsuccessful\n"));
        !           874:             ExFreePool(deviceConfigBuffer);
        !           875:             ExFreePool(mediaInfoBuffer);
        !           876:             return status;
        !           877:         }
        !           878: 
        !           879:         tapeData->CurrentPartition =
        !           880:             deviceConfigBuffer->DeviceConfigPage.ActivePartition?
        !           881:             DIRECTORY_PARTITION : DATA_PARTITION;
        !           882: 
        !           883:         tapeGetMediaParams->PartitionCount = 2;
        !           884: 
        !           885:         ExFreePool(deviceConfigBuffer);
        !           886: 
        !           887:     } else {
        !           888: 
        !           889:         tapeGetMediaParams->PartitionCount = 1 ;
        !           890: 
        !           891:         tapeData->CurrentPartition = NO_PARTITIONS;
        !           892: 
        !           893:     }
        !           894: 
        !           895:     tapeGetMediaParams->BlockSize = mediaInfoBuffer->ParameterListBlock.BlockLength[2];
        !           896:     tapeGetMediaParams->BlockSize += (mediaInfoBuffer->ParameterListBlock.BlockLength[1] << 8);
        !           897:     tapeGetMediaParams->BlockSize += (mediaInfoBuffer->ParameterListBlock.BlockLength[0] << 16);
        !           898: 
        !           899:     WHICH_BIT(tapeGetMediaParams->BlockSize, sectorShift);
        !           900:     deviceExtension->DiskGeometry->BytesPerSector = tapeGetMediaParams->BlockSize;
        !           901:     deviceExtension->SectorShift = sectorShift;
        !           902: 
        !           903:     tapeGetMediaParams->WriteProtected =
        !           904:         ((mediaInfoBuffer->ParameterListHeader.DeviceSpecificParameter >> 7) & 0x01);
        !           905: 
        !           906:     ExFreePool(mediaInfoBuffer);
        !           907: 
        !           908:     return status;
        !           909: 
        !           910: } // end TapeGetMediaParameters()
        !           911: 
        !           912: 
        !           913: NTSTATUS
        !           914: TapeGetPosition(
        !           915:     IN PDEVICE_OBJECT DeviceObject,
        !           916:     IN PIRP Irp
        !           917:     )
        !           918: 
        !           919: /*++
        !           920: Routine Description:
        !           921: 
        !           922:     This routine returns the current position of the tape.
        !           923: 
        !           924: Arguments:
        !           925: 
        !           926:     DeviceObject
        !           927:     Irp
        !           928: 
        !           929: Return Value:
        !           930: 
        !           931:     NTSTATUS
        !           932: 
        !           933: --*/
        !           934: 
        !           935: {
        !           936:     PDEVICE_EXTENSION            deviceExtension = DeviceObject->DeviceExtension;
        !           937:     PTAPE_GET_POSITION           tapeGetPosition = Irp->AssociatedIrp.SystemBuffer;
        !           938:     PTAPE_DATA                   tapeData = (PTAPE_DATA)(deviceExtension + 1);
        !           939:     PMODE_TAPE_MEDIA_INFORMATION mediaInfoBuffer;
        !           940:     PMODE_DEVICE_CONFIG_PAGE     deviceConfigBuffer; 
        !           941:     PTAPE_POSITION_DATA          absoluteBuffer;
        !           942:     UCHAR                        densityCode;
        !           943:     ULONG                        tapeBlockLength;
        !           944:     ULONG                        tapeBlockAddress;
        !           945:     ULONG                        type;
        !           946:     SCSI_REQUEST_BLOCK           srb;
        !           947:     PCDB                         cdb = (PCDB)srb.Cdb;
        !           948:     NTSTATUS                     status;
        !           949: 
        !           950:     DebugPrint((3,"TapeGetPosition: Enter routine\n"));
        !           951: 
        !           952:     type = tapeGetPosition->Type;
        !           953:     RtlZeroMemory(tapeGetPosition, sizeof(TAPE_GET_POSITION));
        !           954:     Irp->IoStatus.Information = sizeof(TAPE_GET_POSITION);
        !           955:     tapeGetPosition->Type = type;
        !           956: 
        !           957:     //
        !           958:     // Zero CDB in SRB on stack.
        !           959:     //
        !           960: 
        !           961:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           962: 
        !           963:     //
        !           964:     // Prepare SCSI command (CDB)
        !           965:     //
        !           966: 
        !           967:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !           968: 
        !           969:     cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
        !           970: 
        !           971:     //
        !           972:     // Set timeout value.
        !           973:     //
        !           974: 
        !           975:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !           976: 
        !           977:     //
        !           978:     // Send SCSI command (CDB) to device
        !           979:     //
        !           980: 
        !           981:     DebugPrint((3,"TapeGetPosition: SendSrb (test unit ready)\n"));
        !           982: 
        !           983:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           984:                                          &srb,
        !           985:                                          NULL,
        !           986:                                          0,
        !           987:                                          FALSE);
        !           988: 
        !           989:     if (!NT_SUCCESS(status)) {
        !           990:         DebugPrint((1,"TapeGetPosition: test unit ready, SendSrb unsuccessful\n"));
        !           991:         return status;
        !           992:     }
        !           993: 
        !           994:     if (type == TAPE_LOGICAL_POSITION) {
        !           995: 
        !           996:         DebugPrint((3,"TapeGetPosition: pseudo logical\n"));
        !           997: 
        !           998:         type = TAPE_PSEUDO_LOGICAL_POSITION;
        !           999: 
        !          1000:         mediaInfoBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
        !          1001:                                          sizeof(MODE_TAPE_MEDIA_INFORMATION));
        !          1002: 
        !          1003:         if (!mediaInfoBuffer) {
        !          1004:             DebugPrint((1,"TapeGetPosition: insufficient resources (mediaInfoBuffer)\n"));
        !          1005:             return STATUS_INSUFFICIENT_RESOURCES;
        !          1006:         }
        !          1007: 
        !          1008:         RtlZeroMemory(mediaInfoBuffer, sizeof(MODE_TAPE_MEDIA_INFORMATION));
        !          1009: 
        !          1010:         //
        !          1011:         // Zero CDB in SRB on stack.
        !          1012:         //
        !          1013: 
        !          1014:         RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1015: 
        !          1016:         //
        !          1017:         // Prepare SCSI command (CDB)
        !          1018:         //
        !          1019: 
        !          1020:         srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1021:         
        !          1022:         cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
        !          1023:         cdb->MODE_SENSE.PageCode = MODE_PAGE_MEDIUM_PARTITION;
        !          1024:         cdb->MODE_SENSE.AllocationLength = sizeof(MODE_TAPE_MEDIA_INFORMATION) - 4;
        !          1025: 
        !          1026:         //
        !          1027:         // Set timeout value.
        !          1028:         //
        !          1029: 
        !          1030:         srb.TimeOutValue = deviceExtension->TimeOutValue;
        !          1031: 
        !          1032:         //
        !          1033:         // Send SCSI command (CDB) to device
        !          1034:         //
        !          1035: 
        !          1036:         DebugPrint((3,"TapeGetPosition: SendSrb (mode sense #1)\n"));
        !          1037: 
        !          1038:         status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          1039:                                              &srb,
        !          1040:                                              mediaInfoBuffer,
        !          1041:                                              sizeof(MODE_TAPE_MEDIA_INFORMATION) - 4,
        !          1042:                                              FALSE);
        !          1043: 
        !          1044:         if (!NT_SUCCESS(status)) {
        !          1045:             DebugPrint((1,"TapeGetPosition: mode sense #1, SendSrb unsuccessful\n"));
        !          1046:             ExFreePool(mediaInfoBuffer);
        !          1047:             return status;
        !          1048:         }
        !          1049: 
        !          1050:         if (mediaInfoBuffer->MediumPartPage.FDPBit) {
        !          1051: 
        !          1052:             deviceConfigBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
        !          1053:                                                 sizeof(MODE_DEVICE_CONFIG_PAGE));
        !          1054: 
        !          1055:             if (!deviceConfigBuffer) {
        !          1056:                 DebugPrint((1,"TapeGetPosition: insufficient resources (deviceConfigBuffer)\n"));
        !          1057:                 ExFreePool(mediaInfoBuffer);
        !          1058:                 return STATUS_INSUFFICIENT_RESOURCES;
        !          1059:             }
        !          1060: 
        !          1061:             RtlZeroMemory(deviceConfigBuffer, sizeof(MODE_DEVICE_CONFIG_PAGE));
        !          1062: 
        !          1063:             //
        !          1064:             // Zero CDB in SRB on stack.
        !          1065:             //
        !          1066: 
        !          1067:             RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1068: 
        !          1069:             //
        !          1070:             // Prepare SCSI command (CDB)
        !          1071:             //
        !          1072: 
        !          1073:             srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1074: 
        !          1075:             cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
        !          1076:             cdb->MODE_SENSE.Dbd = SETBITON;
        !          1077:             cdb->MODE_SENSE.PageCode = MODE_PAGE_DEVICE_CONFIG;
        !          1078:             cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DEVICE_CONFIG_PAGE);
        !          1079: 
        !          1080:             //
        !          1081:             // Set timeout value.
        !          1082:             //
        !          1083: 
        !          1084:             srb.TimeOutValue = deviceExtension->TimeOutValue;
        !          1085: 
        !          1086:             //
        !          1087:             // Send SCSI command (CDB) to device
        !          1088:             //
        !          1089: 
        !          1090:             DebugPrint((3,"TapeGetPosition: SendSrb (mode sense #2)\n"));
        !          1091: 
        !          1092:             status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          1093:                                                  &srb,
        !          1094:                                                  deviceConfigBuffer,
        !          1095:                                                  sizeof(MODE_DEVICE_CONFIG_PAGE),
        !          1096:                                                  FALSE);
        !          1097: 
        !          1098:             if (!NT_SUCCESS(status)) {
        !          1099:                 DebugPrint((1,"TapeGetPosition: mode sense #2, SendSrb unsuccessful\n"));
        !          1100:                 ExFreePool(deviceConfigBuffer);
        !          1101:                 ExFreePool(mediaInfoBuffer);
        !          1102:                 return status;
        !          1103:             }
        !          1104: 
        !          1105:             tapeData->CurrentPartition =
        !          1106:                  deviceConfigBuffer->DeviceConfigPage.ActivePartition?
        !          1107:                  DIRECTORY_PARTITION : DATA_PARTITION;
        !          1108: 
        !          1109:             ExFreePool(deviceConfigBuffer);
        !          1110: 
        !          1111:         } else {
        !          1112: 
        !          1113:             tapeData->CurrentPartition = NO_PARTITIONS;
        !          1114: 
        !          1115:         }
        !          1116: 
        !          1117:         densityCode      = mediaInfoBuffer->ParameterListBlock.DensityCode;
        !          1118:         tapeBlockLength  = mediaInfoBuffer->ParameterListBlock.BlockLength[2];
        !          1119:         tapeBlockLength += (mediaInfoBuffer->ParameterListBlock.BlockLength[1] << 8);
        !          1120:         tapeBlockLength += (mediaInfoBuffer->ParameterListBlock.BlockLength[0] << 16);
        !          1121: 
        !          1122:         ExFreePool(mediaInfoBuffer);
        !          1123: 
        !          1124:     }
        !          1125: 
        !          1126:     switch (type) {
        !          1127:         case TAPE_PSEUDO_LOGICAL_POSITION:
        !          1128:         case TAPE_ABSOLUTE_POSITION:
        !          1129:             absoluteBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
        !          1130:                                             sizeof(TAPE_POSITION_DATA));
        !          1131:     
        !          1132:             if (!absoluteBuffer) {
        !          1133:                 DebugPrint((1,"TapeGetPosition: insufficient resources (absoluteBuffer)\n"));
        !          1134:                 return STATUS_INSUFFICIENT_RESOURCES;
        !          1135:             }
        !          1136:     
        !          1137:             RtlZeroMemory(absoluteBuffer, sizeof(TAPE_POSITION_DATA));
        !          1138: 
        !          1139:             //
        !          1140:             // Zero CDB in SRB on stack.
        !          1141:             //
        !          1142: 
        !          1143:             RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1144: 
        !          1145:             //
        !          1146:             // Prepare SCSI command (CDB)
        !          1147:             //
        !          1148: 
        !          1149:             srb.CdbLength = CDB10GENERIC_LENGTH;
        !          1150: 
        !          1151:             cdb->READ_POSITION.Operation = SCSIOP_READ_POSITION;
        !          1152:             cdb->READ_POSITION.BlockType = SETBITON;
        !          1153: 
        !          1154:             //
        !          1155:             // Set timeout value.
        !          1156:             //
        !          1157:     
        !          1158:             srb.TimeOutValue = deviceExtension->TimeOutValue;
        !          1159:     
        !          1160:             //
        !          1161:             // Send SCSI command (CDB) to device
        !          1162:             //
        !          1163: 
        !          1164:             DebugPrint((3,"TapeGetPosition: SendSrb (read position)\n"));
        !          1165: 
        !          1166:             status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          1167:                                                  &srb,
        !          1168:                                                  absoluteBuffer,
        !          1169:                                                  sizeof(TAPE_POSITION_DATA),
        !          1170:                                                  FALSE);
        !          1171: 
        !          1172:             if (NT_SUCCESS(status)) {
        !          1173: 
        !          1174:                 REVERSE_BYTES((PFOUR_BYTE)&tapeBlockAddress,
        !          1175:                               (PFOUR_BYTE)absoluteBuffer->FirstBlock);
        !          1176:             }
        !          1177: 
        !          1178:             ExFreePool(absoluteBuffer);
        !          1179: 
        !          1180:             if (!NT_SUCCESS(status)) {
        !          1181:                 DebugPrint((1,"TapeGetPosition: read position, SendSrb unsuccessful\n"));
        !          1182:                 return status;
        !          1183:             }
        !          1184: 
        !          1185:             if (type == TAPE_ABSOLUTE_POSITION) {
        !          1186:                 tapeGetPosition->Partition = 0;
        !          1187:                 tapeGetPosition->Offset.HighPart = 0;
        !          1188:                 tapeGetPosition->Offset.LowPart  = tapeBlockAddress;
        !          1189:                 break;
        !          1190:             }
        !          1191: 
        !          1192:             tapeBlockAddress =
        !          1193:                 TapePhysicalBlockToLogicalBlock(
        !          1194:                     densityCode,
        !          1195:                     tapeBlockAddress,
        !          1196:                     tapeBlockLength,
        !          1197:                     (BOOLEAN)(
        !          1198:                         (tapeData->CurrentPartition
        !          1199:                             == DIRECTORY_PARTITION)?
        !          1200:                         NOT_FROM_BOT : FROM_BOT
        !          1201:                     )
        !          1202:                 );
        !          1203: 
        !          1204:             tapeGetPosition->Offset.HighPart = 0;
        !          1205:             tapeGetPosition->Offset.LowPart  = tapeBlockAddress;
        !          1206:             tapeGetPosition->Partition = tapeData->CurrentPartition;
        !          1207:             break;
        !          1208: 
        !          1209:         default:
        !          1210:             DebugPrint((1,"TapeGetPosition: PositionType -- operation not supported\n"));
        !          1211:             return STATUS_NOT_IMPLEMENTED;
        !          1212:     }
        !          1213: 
        !          1214:     return status;
        !          1215: 
        !          1216: } // end TapeGetPosition()
        !          1217: 
        !          1218: 
        !          1219: NTSTATUS
        !          1220: TapeGetStatus(
        !          1221:     IN PDEVICE_OBJECT DeviceObject,
        !          1222:     IN PIRP Irp
        !          1223:     )
        !          1224: 
        !          1225: /*++
        !          1226: Routine Description:
        !          1227: 
        !          1228:     This routine returns the status of the device.
        !          1229: 
        !          1230: Arguments:
        !          1231: 
        !          1232:     DeviceObject
        !          1233:     Irp
        !          1234: 
        !          1235: Return Value:
        !          1236: 
        !          1237:     NTSTATUS
        !          1238: 
        !          1239: --*/
        !          1240: 
        !          1241: {
        !          1242:     PDEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
        !          1243:     SCSI_REQUEST_BLOCK srb;
        !          1244:     PCDB               cdb = (PCDB)srb.Cdb;
        !          1245:     NTSTATUS           status;
        !          1246: 
        !          1247:     DebugPrint((3,"TapeGetStatus: Enter routine\n"));
        !          1248: 
        !          1249:     //
        !          1250:     // Zero CDB in SRB on stack.
        !          1251:     //
        !          1252: 
        !          1253:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1254: 
        !          1255:     //
        !          1256:     // Prepare SCSI command (CDB)
        !          1257:     //
        !          1258: 
        !          1259:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1260: 
        !          1261:     cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
        !          1262: 
        !          1263:     //
        !          1264:     // Set timeout value.
        !          1265:     //
        !          1266: 
        !          1267:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !          1268: 
        !          1269:     //
        !          1270:     // Send SCSI command (CDB) to device
        !          1271:     //
        !          1272: 
        !          1273:     DebugPrint((3,"TapeGetStatus: SendSrb (test unit ready)\n"));
        !          1274: 
        !          1275:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          1276:                                          &srb,
        !          1277:                                          NULL,
        !          1278:                                          0,
        !          1279:                                          FALSE);
        !          1280: 
        !          1281:     if (!NT_SUCCESS(status)) {
        !          1282:         DebugPrint((1,"TapeGetStatus: test unit ready, SendSrb unsuccessful\n"));
        !          1283:     }
        !          1284: 
        !          1285:     return status;
        !          1286: 
        !          1287: } // end TapeGetStatus()
        !          1288: 
        !          1289: 
        !          1290: NTSTATUS
        !          1291: TapePrepare(
        !          1292:     IN PDEVICE_OBJECT DeviceObject,
        !          1293:     IN PIRP Irp
        !          1294:     )
        !          1295: 
        !          1296: /*++
        !          1297: Routine Description:
        !          1298: 
        !          1299:     This routine loads, unloads, tensions, locks, or unlocks the tape.
        !          1300: 
        !          1301: Arguments:
        !          1302: 
        !          1303:     DeviceObject
        !          1304:     Irp
        !          1305: 
        !          1306: Return Value:
        !          1307: 
        !          1308:     NTSTATUS
        !          1309: 
        !          1310: --*/
        !          1311: 
        !          1312: {
        !          1313:     PDEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
        !          1314:     PTAPE_PREPARE      tapePrepare = Irp->AssociatedIrp.SystemBuffer;
        !          1315:     SCSI_REQUEST_BLOCK srb;
        !          1316:     PCDB               cdb = (PCDB)srb.Cdb;
        !          1317:     NTSTATUS           status;
        !          1318: 
        !          1319:     DebugPrint((3,"TapePrepare: Enter routine\n"));
        !          1320: 
        !          1321:     if (tapePrepare->Immediate) {
        !          1322:         switch (tapePrepare->Operation) {
        !          1323:             case TAPE_LOAD:
        !          1324:             case TAPE_UNLOAD:
        !          1325:             case TAPE_TENSION:
        !          1326:                 DebugPrint((3,"TapePrepare: immediate\n"));
        !          1327:                 break;
        !          1328: 
        !          1329:             case TAPE_LOCK:
        !          1330:             case TAPE_UNLOCK:
        !          1331:             default:
        !          1332:                 DebugPrint((1,"TapePrepare: Operation, immediate -- operation not supported\n"));
        !          1333:                 return STATUS_NOT_IMPLEMENTED;
        !          1334:         }
        !          1335:     }
        !          1336: 
        !          1337:     //
        !          1338:     // Zero CDB in SRB on stack.
        !          1339:     //
        !          1340: 
        !          1341:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1342: 
        !          1343:     //
        !          1344:     // Prepare SCSI command (CDB)
        !          1345:     //
        !          1346: 
        !          1347:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1348: 
        !          1349:     cdb->CDB6GENERIC.Immediate = tapePrepare->Immediate;
        !          1350: 
        !          1351:     switch (tapePrepare->Operation) {
        !          1352:         case TAPE_LOAD:
        !          1353:             DebugPrint((3,"TapePrepare: Operation == load\n"));
        !          1354:             cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD;
        !          1355:             cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x01;
        !          1356:             srb.TimeOutValue = 180;
        !          1357:             break;
        !          1358: 
        !          1359:         case TAPE_UNLOAD:
        !          1360:             DebugPrint((3,"TapePrepare: Operation == unload\n"));
        !          1361:             cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD;
        !          1362:             srb.TimeOutValue = 180;
        !          1363:             break;
        !          1364: 
        !          1365:         case TAPE_TENSION:
        !          1366:             DebugPrint((3,"TapePrepare: Operation == tension\n"));
        !          1367:             cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD;
        !          1368:             cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x03;
        !          1369:             srb.TimeOutValue = 360;
        !          1370:             break;
        !          1371: 
        !          1372:         case TAPE_LOCK:
        !          1373:             DebugPrint((3,"TapePrepare: Operation == lock\n"));
        !          1374:             cdb->CDB6GENERIC.OperationCode = SCSIOP_MEDIUM_REMOVAL;
        !          1375:             cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x01;
        !          1376:             srb.TimeOutValue = 180;
        !          1377:             break;
        !          1378: 
        !          1379:         case TAPE_UNLOCK:
        !          1380:             DebugPrint((3,"TapePrepare: Operation == unlock\n"));
        !          1381:             cdb->CDB6GENERIC.OperationCode = SCSIOP_MEDIUM_REMOVAL;
        !          1382:             srb.TimeOutValue = 180;
        !          1383:             break;
        !          1384: 
        !          1385:         default:
        !          1386:             DebugPrint((1,"TapePrepare: Operation -- operation not supported\n"));
        !          1387:             return STATUS_NOT_IMPLEMENTED;
        !          1388:     }
        !          1389: 
        !          1390:     //
        !          1391:     // Send SCSI command (CDB) to device
        !          1392:     //
        !          1393: 
        !          1394:     DebugPrint((3,"TapePrepare: SendSrb (Operation)\n"));
        !          1395: 
        !          1396:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          1397:                                          &srb,
        !          1398:                                          NULL,
        !          1399:                                          0,
        !          1400:                                          FALSE);
        !          1401: 
        !          1402:     if (!NT_SUCCESS(status)) {
        !          1403:         DebugPrint((1,"TapePrepare: Operation, SendSrb unsuccessful\n"));
        !          1404:     }
        !          1405: 
        !          1406:     return status;
        !          1407: 
        !          1408: } // end TapePrepare()
        !          1409: 
        !          1410: 
        !          1411: NTSTATUS
        !          1412: TapeReadWrite(
        !          1413:     IN PDEVICE_OBJECT DeviceObject,
        !          1414:     IN PIRP Irp
        !          1415:     )
        !          1416: 
        !          1417: /*++
        !          1418: 
        !          1419: Routine Description:
        !          1420: 
        !          1421:     This routine builds SRBs and CDBs for read and write requests to
        !          1422:     Tandberg QIC drives.
        !          1423: 
        !          1424: Arguments:
        !          1425: 
        !          1426:     DeviceObject
        !          1427:     Irp
        !          1428: 
        !          1429: Return Value:
        !          1430: 
        !          1431:     Returns STATUS_PENDING.
        !          1432: 
        !          1433: --*/
        !          1434: 
        !          1435:   {
        !          1436:     PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
        !          1437:     PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
        !          1438:     PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
        !          1439:     PSCSI_REQUEST_BLOCK srb;
        !          1440:     PCDB cdb;
        !          1441:     KIRQL currentIrql;
        !          1442:     ULONG transferBlocks;
        !          1443:     LARGE_INTEGER startingOffset =
        !          1444:       currentIrpStack->Parameters.Read.ByteOffset;
        !          1445: 
        !          1446:     DebugPrint((3,"TapeReadWrite: Enter routine\n"));
        !          1447: 
        !          1448:     //
        !          1449:     // Allocate an Srb.
        !          1450:     //
        !          1451: 
        !          1452:     if (deviceExtension->SrbZone != NULL &&
        !          1453:         (srb = ExInterlockedAllocateFromZone(
        !          1454:             deviceExtension->SrbZone,
        !          1455:             deviceExtension->SrbZoneSpinLock)) != NULL) {
        !          1456: 
        !          1457:         srb->SrbFlags = SRB_FLAGS_ALLOCATED_FROM_ZONE;
        !          1458: 
        !          1459:     } else {
        !          1460: 
        !          1461:         //
        !          1462:         // Allocate Srb from non-paged pool.
        !          1463:         // This call must succeed.
        !          1464:         //
        !          1465: 
        !          1466:         srb = ExAllocatePool(NonPagedPoolMustSucceed, SCSI_REQUEST_BLOCK_SIZE);
        !          1467: 
        !          1468:         srb->SrbFlags = 0;
        !          1469: 
        !          1470:     }
        !          1471: 
        !          1472:     //
        !          1473:     // Write length to SRB.
        !          1474:     //
        !          1475: 
        !          1476:     srb->Length = SCSI_REQUEST_BLOCK_SIZE;
        !          1477: 
        !          1478:     //
        !          1479:     // Set up IRP Address.
        !          1480:     //
        !          1481: 
        !          1482:     srb->OriginalRequest = Irp;
        !          1483: 
        !          1484:     //
        !          1485:     // Set up target id and logical unit number.
        !          1486:     //
        !          1487: 
        !          1488:     srb->PathId = deviceExtension->PathId;
        !          1489:     srb->TargetId = deviceExtension->TargetId;
        !          1490:     srb->Lun = deviceExtension->Lun;
        !          1491: 
        !          1492: 
        !          1493:     srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
        !          1494: 
        !          1495:     srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
        !          1496: 
        !          1497:     //
        !          1498:     // Save byte count of transfer in SRB Extension.
        !          1499:     //
        !          1500: 
        !          1501:     srb->DataTransferLength = currentIrpStack->Parameters.Read.Length;
        !          1502: 
        !          1503:     //
        !          1504:     // Indicate auto request sense by specifying buffer and size.
        !          1505:     //
        !          1506: 
        !          1507:     srb->SenseInfoBuffer = deviceExtension->SenseData;
        !          1508: 
        !          1509:     srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
        !          1510: 
        !          1511:     //
        !          1512:     // Initialize the queue actions field.
        !          1513:     //
        !          1514: 
        !          1515:     srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
        !          1516: 
        !          1517:     //
        !          1518:     // Indicate auto request sense by specifying buffer and size.
        !          1519:     //
        !          1520: 
        !          1521:     srb->SenseInfoBuffer = deviceExtension->SenseData;
        !          1522: 
        !          1523:     srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
        !          1524: 
        !          1525:     //
        !          1526:     // Set timeout value in seconds.
        !          1527:     //
        !          1528: 
        !          1529:     srb->TimeOutValue = deviceExtension->TimeOutValue;
        !          1530: 
        !          1531:     //
        !          1532:     // Zero statuses.
        !          1533:     //
        !          1534: 
        !          1535:     srb->SrbStatus = srb->ScsiStatus = 0;
        !          1536: 
        !          1537:     srb->NextSrb = 0;
        !          1538: 
        !          1539:     //
        !          1540:     // Indicate that 6-byte CDB's will be used.
        !          1541:     //
        !          1542: 
        !          1543:     srb->CdbLength = CDB6GENERIC_LENGTH;
        !          1544: 
        !          1545:     //
        !          1546:     // Fill in CDB fields.
        !          1547:     //
        !          1548: 
        !          1549:     cdb = (PCDB)srb->Cdb;
        !          1550: 
        !          1551:     //
        !          1552:     // Zero CDB in SRB.
        !          1553:     //
        !          1554: 
        !          1555:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1556: 
        !          1557:     //
        !          1558:     // Since we are writing fixed block mode, normalize transfer count
        !          1559:     // to number of blocks.
        !          1560:     //
        !          1561: 
        !          1562:     transferBlocks =
        !          1563:         currentIrpStack->Parameters.Read.Length >> deviceExtension->SectorShift;
        !          1564: 
        !          1565:     //
        !          1566:     // Set up transfer length
        !          1567:     //
        !          1568: 
        !          1569:     cdb->CDB6READWRITETAPE.TransferLenMSB = (UCHAR)((transferBlocks >> 16) & 0xff);
        !          1570:     cdb->CDB6READWRITETAPE.TransferLen    = (UCHAR)((transferBlocks >> 8) & 0xff);
        !          1571:     cdb->CDB6READWRITETAPE.TransferLenLSB = (UCHAR)(transferBlocks & 0xff);
        !          1572: 
        !          1573:     //
        !          1574:     // Tell the python we are in fixed block mode
        !          1575:     //
        !          1576: 
        !          1577:     cdb->CDB6READWRITETAPE.VendorSpecific = 1;
        !          1578: 
        !          1579:     //
        !          1580:     // Set transfer direction flag and Cdb command.
        !          1581:     //
        !          1582: 
        !          1583:     if (currentIrpStack->MajorFunction == IRP_MJ_READ) {
        !          1584: 
        !          1585:          DebugPrint((3, "TapeRequest: Read Command\n"));
        !          1586: 
        !          1587:          srb->SrbFlags = SRB_FLAGS_DATA_IN;
        !          1588:          cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_READ6;
        !          1589: 
        !          1590:     } else {
        !          1591: 
        !          1592:          DebugPrint((3, "TapeRequest: Write Command\n"));
        !          1593: 
        !          1594:          srb->SrbFlags = SRB_FLAGS_DATA_OUT;
        !          1595:          cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_WRITE6;
        !          1596:     }
        !          1597: 
        !          1598:     //
        !          1599:     // Or in the default flags from the device object.
        !          1600:     //
        !          1601: 
        !          1602:     srb->SrbFlags |= deviceExtension->SrbFlags;
        !          1603: 
        !          1604:     //
        !          1605:     // Set up major SCSI function.
        !          1606:     //
        !          1607: 
        !          1608:     nextIrpStack->MajorFunction = IRP_MJ_SCSI;
        !          1609: 
        !          1610:     //
        !          1611:     // Save SRB address in next stack for port driver.
        !          1612:     //
        !          1613: 
        !          1614:     nextIrpStack->Parameters.Scsi.Srb = srb;
        !          1615: 
        !          1616:     //
        !          1617:     // Save retry count in current IRP stack.
        !          1618:     //
        !          1619: 
        !          1620:     currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
        !          1621: 
        !          1622:     //
        !          1623:     // Set up IoCompletion routine address.
        !          1624:     //
        !          1625: 
        !          1626:     IoSetCompletionRoutine(Irp,
        !          1627:                            ScsiClassIoComplete,
        !          1628:                            srb,
        !          1629:                            TRUE,
        !          1630:                            TRUE,
        !          1631:                            FALSE);
        !          1632: 
        !          1633:     return STATUS_PENDING;
        !          1634: 
        !          1635: } // end TapeReadWrite()
        !          1636: 
        !          1637: 
        !          1638: NTSTATUS
        !          1639: TapeSetDriveParameters(
        !          1640:     IN PDEVICE_OBJECT DeviceObject,
        !          1641:     IN PIRP Irp
        !          1642:     )
        !          1643: 
        !          1644: /*++
        !          1645: Routine Description:
        !          1646: 
        !          1647:     This routine would "set" the "drive parameters" of the Tandberg QIC
        !          1648:     tape drive associated with "DeviceObject" if any could be set, but
        !          1649:     none can! Hence, this routine always returns a STATUS_NOT_IMPLEMENTED
        !          1650:     status.
        !          1651: 
        !          1652: Arguments:
        !          1653: 
        !          1654:     DeviceObject
        !          1655:     Irp
        !          1656: 
        !          1657: Return Value:
        !          1658: 
        !          1659:     NTSTATUS
        !          1660: 
        !          1661: --*/
        !          1662: 
        !          1663: {
        !          1664:     DebugPrint((3,"TapeSetDriveParameters: Enter routine\n"));
        !          1665: 
        !          1666:     DebugPrint((1,"TapeSetDriveParameters: Operation -- operation not supported\n"));
        !          1667: 
        !          1668:     return STATUS_NOT_IMPLEMENTED;
        !          1669: 
        !          1670: } // end TapeSetDriveParameters()
        !          1671: 
        !          1672: 
        !          1673: 
        !          1674: NTSTATUS
        !          1675: TapeSetMediaParameters(
        !          1676:     IN PDEVICE_OBJECT DeviceObject,
        !          1677:     IN PIRP Irp
        !          1678:     )
        !          1679: 
        !          1680: /*++
        !          1681: Routine Description:
        !          1682: 
        !          1683:     This routine "sets" the "media parameters" of the Tandberg QIC tape
        !          1684:     drive associated with "DeviceObject". Tape media must be present
        !          1685:     (loaded) in the drive for this function to return "no error".
        !          1686: 
        !          1687: Arguments:
        !          1688: 
        !          1689:     DeviceObject
        !          1690:     Irp
        !          1691: 
        !          1692: Return Value:
        !          1693: 
        !          1694:     NTSTATUS
        !          1695: 
        !          1696: --*/
        !          1697: 
        !          1698: {
        !          1699:     PDEVICE_EXTENSION          deviceExtension = DeviceObject->DeviceExtension;
        !          1700:     PTAPE_SET_MEDIA_PARAMETERS tapeSetMediaParams = Irp->AssociatedIrp.SystemBuffer;
        !          1701:     PMODE_PARM_READ_WRITE_DATA modeBuffer;
        !          1702:     PINQUIRYDATA               inquiryBuffer;
        !          1703:     ULONG                      whichdrive;
        !          1704:     SCSI_REQUEST_BLOCK         srb;
        !          1705:     PCDB                       cdb = (PCDB)srb.Cdb;
        !          1706:     NTSTATUS                   status;
        !          1707: 
        !          1708:     DebugPrint((3,"TapeSetMediaParameters: Enter routine\n"));
        !          1709: 
        !          1710:     inquiryBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
        !          1711:                                    sizeof(INQUIRYDATA));
        !          1712: 
        !          1713:     if (!inquiryBuffer) {
        !          1714:         DebugPrint((1,"TapeSetMediaParameters: insufficient resources (inquiryBuffer)\n"));
        !          1715:         return STATUS_INSUFFICIENT_RESOURCES;
        !          1716:     }
        !          1717: 
        !          1718:     RtlZeroMemory(inquiryBuffer, sizeof(INQUIRYDATA));
        !          1719: 
        !          1720:     //
        !          1721:     // Send SCSI command (CDB) to device
        !          1722:     //
        !          1723: 
        !          1724:     DebugPrint((3,"TapeSetMediaParameters: SendSrb (inquiry)\n"));
        !          1725: 
        !          1726:     status = GetInquiryInformationData(DeviceObject, Irp, inquiryBuffer);
        !          1727: 
        !          1728:     if (NT_SUCCESS(status)) {
        !          1729: 
        !          1730:         //
        !          1731:         // Which drive do we have, TDC 3660, 3820, 4120 or 4220?
        !          1732:         //
        !          1733: 
        !          1734:         whichdrive = WhichIsIt(inquiryBuffer);
        !          1735:     }
        !          1736:     
        !          1737:     ExFreePool(inquiryBuffer);
        !          1738: 
        !          1739:     if (!NT_SUCCESS(status)) {
        !          1740:         DebugPrint((1,"TapeSetMediaParameters: inquiry, SendSrb unsuccessful\n"));
        !          1741:         return status;
        !          1742:     }
        !          1743:          
        !          1744:     if (whichdrive == TDC_3600) {
        !          1745:         DebugPrint((1,"TapeSetMediaParameters: whichdrive -- operation not supported\n"));
        !          1746:         return STATUS_NOT_IMPLEMENTED;
        !          1747:     }
        !          1748: 
        !          1749:     //
        !          1750:     // Zero CDB in SRB on stack.
        !          1751:     //
        !          1752: 
        !          1753:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1754: 
        !          1755:     //
        !          1756:     // Prepare SCSI command (CDB)
        !          1757:     //
        !          1758: 
        !          1759:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1760: 
        !          1761:     cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
        !          1762: 
        !          1763:     //
        !          1764:     // Set timeout value.
        !          1765:     //
        !          1766: 
        !          1767:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !          1768: 
        !          1769:     //
        !          1770:     // Send SCSI command (CDB) to device
        !          1771:     //
        !          1772: 
        !          1773:     DebugPrint((3,"TapeSetMediaParameters: SendSrb (test unit ready)\n"));
        !          1774: 
        !          1775:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          1776:                                          &srb,
        !          1777:                                          NULL,
        !          1778:                                          0,
        !          1779:                                          FALSE);
        !          1780: 
        !          1781:     if (!NT_SUCCESS(status)) {
        !          1782:         DebugPrint((1,"TapeSetMediaParameters: test unit ready, SendSrb unsuccessful\n"));
        !          1783:         return status;
        !          1784:     }
        !          1785: 
        !          1786:     modeBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
        !          1787:                                 sizeof(MODE_PARM_READ_WRITE_DATA));
        !          1788: 
        !          1789:     if (!modeBuffer) {
        !          1790:         DebugPrint((1,"TapeSetMediaParameters: insufficient resources (modeBuffer)\n"));
        !          1791:         return STATUS_INSUFFICIENT_RESOURCES;
        !          1792:     }
        !          1793: 
        !          1794:     RtlZeroMemory(modeBuffer, sizeof(MODE_PARM_READ_WRITE_DATA));
        !          1795: 
        !          1796:     modeBuffer->ParameterListHeader.DeviceSpecificParameter = 0x10;
        !          1797:     modeBuffer->ParameterListHeader.BlockDescriptorLength = MODE_BLOCK_DESC_LENGTH;
        !          1798:         
        !          1799:     modeBuffer->ParameterListBlock.DensityCode = 0x7F;
        !          1800:     modeBuffer->ParameterListBlock.BlockLength[0] =
        !          1801:         ((tapeSetMediaParams->BlockSize >> 16) & 0xFF);
        !          1802:     modeBuffer->ParameterListBlock.BlockLength[1] =
        !          1803:         ((tapeSetMediaParams->BlockSize >> 8) & 0xFF);
        !          1804:     modeBuffer->ParameterListBlock.BlockLength[2] =
        !          1805:         (tapeSetMediaParams->BlockSize & 0xFF);
        !          1806: 
        !          1807:     //
        !          1808:     // Zero CDB in SRB on stack.
        !          1809:     //
        !          1810: 
        !          1811:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1812: 
        !          1813:     //
        !          1814:     // Prepare SCSI command (CDB)
        !          1815:     //
        !          1816: 
        !          1817:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1818: 
        !          1819:     cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
        !          1820:     cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_PARM_READ_WRITE_DATA);
        !          1821: 
        !          1822:     //
        !          1823:     // Set timeout value.
        !          1824:     //
        !          1825: 
        !          1826:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !          1827: 
        !          1828:     //
        !          1829:     // Send SCSI command (CDB) to device
        !          1830:     //
        !          1831:     
        !          1832:     DebugPrint((3,"TapeSetMediaParameters: SendSrb (mode select)\n"));
        !          1833: 
        !          1834:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          1835:                                          &srb,
        !          1836:                                          modeBuffer,
        !          1837:                                          sizeof(MODE_PARM_READ_WRITE_DATA),
        !          1838:                                          TRUE);
        !          1839: 
        !          1840:     ExFreePool(modeBuffer);
        !          1841: 
        !          1842:     if (!NT_SUCCESS(status)) {
        !          1843:         DebugPrint((1,"TapeSetMediaParameters: mode select, SendSrb unsuccessful\n"));
        !          1844:     }
        !          1845: 
        !          1846:     return status;
        !          1847: 
        !          1848: } // end TapeSetMediaParameters()
        !          1849: 
        !          1850: 
        !          1851: NTSTATUS
        !          1852: TapeSetPosition(
        !          1853:     IN PDEVICE_OBJECT DeviceObject,
        !          1854:     IN PIRP Irp
        !          1855:     )
        !          1856: 
        !          1857: /*++
        !          1858: Routine Description:
        !          1859: 
        !          1860:     This routine sets the position of the tape.
        !          1861: 
        !          1862: Arguments:
        !          1863: 
        !          1864:     DeviceObject
        !          1865:     Irp
        !          1866: 
        !          1867: Return Value:
        !          1868: 
        !          1869:     NTSTATUS
        !          1870: 
        !          1871: --*/
        !          1872: 
        !          1873: {
        !          1874:     PDEVICE_EXTENSION            deviceExtension = DeviceObject->DeviceExtension;
        !          1875:     PTAPE_SET_POSITION           tapeSetPosition = Irp->AssociatedIrp.SystemBuffer;
        !          1876:     PTAPE_DATA                   tapeData = (PTAPE_DATA)(deviceExtension + 1);
        !          1877:     BOOLEAN                      changePartition = FALSE;
        !          1878:     PMODE_TAPE_MEDIA_INFORMATION mediaInfoBuffer;
        !          1879:     PMODE_DEVICE_CONFIG_PAGE     deviceConfigBuffer; 
        !          1880:     TAPE_PHYS_POSITION           physPosition;
        !          1881:     UCHAR                        densityCode;
        !          1882:     ULONG                        tapePositionVector;
        !          1883:     ULONG                        tapeBlockLength;
        !          1884:     ULONG                        method;
        !          1885:     SCSI_REQUEST_BLOCK           srb;
        !          1886:     PCDB                         cdb = (PCDB)srb.Cdb;
        !          1887:     NTSTATUS                     status;
        !          1888: 
        !          1889:     DebugPrint((3,"TapeSetPosition: Enter routine\n"));
        !          1890: 
        !          1891:     if (tapeSetPosition->Immediate) {
        !          1892:         switch (tapeSetPosition->Method) {
        !          1893:             case TAPE_REWIND:
        !          1894:                 DebugPrint((3,"TapeSetPosition: immediate\n"));
        !          1895:                 break;
        !          1896: 
        !          1897:             case TAPE_LOGICAL_BLOCK:
        !          1898:             case TAPE_ABSOLUTE_BLOCK:
        !          1899:             case TAPE_SPACE_END_OF_DATA:
        !          1900:             case TAPE_SPACE_RELATIVE_BLOCKS:
        !          1901:             case TAPE_SPACE_FILEMARKS:
        !          1902:             case TAPE_SPACE_SEQUENTIAL_FMKS:
        !          1903:             case TAPE_SPACE_SETMARKS:
        !          1904:             case TAPE_SPACE_SEQUENTIAL_SMKS:
        !          1905:             default:
        !          1906:                 DebugPrint((1,"TapeSetPosition: PositionMethod, immediate -- operation not supported\n"));
        !          1907:                 return STATUS_NOT_IMPLEMENTED;
        !          1908:         }
        !          1909:     }
        !          1910: 
        !          1911:     method = tapeSetPosition->Method;
        !          1912:     tapePositionVector = tapeSetPosition->Offset.LowPart;
        !          1913:     
        !          1914:     if (method == TAPE_LOGICAL_BLOCK) {
        !          1915: 
        !          1916:         DebugPrint((3,"TapeSetPosition: pseudo logical\n"));
        !          1917: 
        !          1918:         method = TAPE_PSEUDO_LOGICAL_BLOCK;
        !          1919: 
        !          1920:         mediaInfoBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
        !          1921:                                          sizeof(MODE_TAPE_MEDIA_INFORMATION));
        !          1922: 
        !          1923:         if (!mediaInfoBuffer) {
        !          1924:             DebugPrint((1,"TapeSetPosition: insufficient resources (mediaInfoBuffer)\n"));
        !          1925:             return STATUS_INSUFFICIENT_RESOURCES;
        !          1926:         }
        !          1927: 
        !          1928:         RtlZeroMemory(mediaInfoBuffer, sizeof(MODE_TAPE_MEDIA_INFORMATION));
        !          1929: 
        !          1930:         //
        !          1931:         // Zero CDB in SRB on stack.
        !          1932:         //
        !          1933: 
        !          1934:         RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1935: 
        !          1936:         //
        !          1937:         // Prepare SCSI command (CDB)
        !          1938:         //
        !          1939: 
        !          1940:         srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1941:         
        !          1942:         cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
        !          1943:         cdb->MODE_SENSE.PageCode = MODE_PAGE_MEDIUM_PARTITION;
        !          1944:         cdb->MODE_SENSE.AllocationLength = sizeof(MODE_TAPE_MEDIA_INFORMATION) - 4;
        !          1945: 
        !          1946:         //
        !          1947:         // Set timeout value.
        !          1948:         //
        !          1949: 
        !          1950:         srb.TimeOutValue = deviceExtension->TimeOutValue;
        !          1951: 
        !          1952:         //
        !          1953:         // Send SCSI command (CDB) to device
        !          1954:         //
        !          1955:     
        !          1956:         DebugPrint((3,"TapeSetPosition: SendSrb (mode sense #1)\n"));
        !          1957: 
        !          1958:         status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          1959:                                              &srb,
        !          1960:                                              mediaInfoBuffer,
        !          1961:                                              sizeof(MODE_TAPE_MEDIA_INFORMATION) - 4,
        !          1962:                                              FALSE);
        !          1963: 
        !          1964:         if (!NT_SUCCESS(status)) {
        !          1965:             DebugPrint((1,"TapeSetPosition: mode sense #1, SendSrb unsuccessful\n"));
        !          1966:             ExFreePool(mediaInfoBuffer);
        !          1967:             return status;
        !          1968:         }
        !          1969: 
        !          1970:         if (mediaInfoBuffer->MediumPartPage.FDPBit) {
        !          1971: 
        !          1972:             deviceConfigBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
        !          1973:                                                 sizeof(MODE_DEVICE_CONFIG_PAGE));
        !          1974:             
        !          1975:             if (!deviceConfigBuffer) {
        !          1976:                 DebugPrint((1,"TapeSetPosition: insufficient resources (deviceConfigBuffer)\n"));
        !          1977:                 ExFreePool(mediaInfoBuffer);
        !          1978:                 return STATUS_INSUFFICIENT_RESOURCES;
        !          1979:             }
        !          1980:             
        !          1981:             RtlZeroMemory(deviceConfigBuffer, sizeof(MODE_DEVICE_CONFIG_PAGE));
        !          1982: 
        !          1983:             //
        !          1984:             // Zero CDB in SRB on stack.
        !          1985:             //
        !          1986: 
        !          1987:             RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1988:             
        !          1989:             //
        !          1990:             // Prepare SCSI command (CDB)
        !          1991:             //
        !          1992: 
        !          1993:             srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1994:             
        !          1995:             cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
        !          1996:             cdb->MODE_SENSE.Dbd = SETBITON;
        !          1997:             cdb->MODE_SENSE.PageCode = MODE_PAGE_DEVICE_CONFIG;
        !          1998:             cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DEVICE_CONFIG_PAGE);
        !          1999:             
        !          2000:             //
        !          2001:             // Set timeout value.
        !          2002:             //
        !          2003:             
        !          2004:             srb.TimeOutValue = deviceExtension->TimeOutValue;
        !          2005:             
        !          2006:             //
        !          2007:             // Send SCSI command (CDB) to device
        !          2008:             //
        !          2009:     
        !          2010:             DebugPrint((3,"TapeSetPosition: SendSrb (mode sense #2)\n"));
        !          2011: 
        !          2012:             status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          2013:                                                  &srb,
        !          2014:                                                  deviceConfigBuffer,
        !          2015:                                                  sizeof(MODE_DEVICE_CONFIG_PAGE),
        !          2016:                                                  FALSE);
        !          2017:             
        !          2018:             if (!NT_SUCCESS(status)) {
        !          2019:                 DebugPrint((1,"TapeSetPosition: mode sense #2, SendSrb unsuccessful\n"));
        !          2020:                 ExFreePool(deviceConfigBuffer);
        !          2021:                 ExFreePool(mediaInfoBuffer);
        !          2022:                 return status;
        !          2023:             }
        !          2024: 
        !          2025:             tapeData->CurrentPartition =
        !          2026:                 deviceConfigBuffer->DeviceConfigPage.ActivePartition?
        !          2027:                 DIRECTORY_PARTITION : DATA_PARTITION;
        !          2028: 
        !          2029:             ExFreePool(deviceConfigBuffer);
        !          2030: 
        !          2031:         } else {
        !          2032: 
        !          2033:             tapeData->CurrentPartition = NO_PARTITIONS;
        !          2034: 
        !          2035:         }
        !          2036: 
        !          2037:         densityCode      = mediaInfoBuffer->ParameterListBlock.DensityCode;
        !          2038:         tapeBlockLength  = mediaInfoBuffer->ParameterListBlock.BlockLength[2];
        !          2039:         tapeBlockLength += (mediaInfoBuffer->ParameterListBlock.BlockLength[1] << 8);
        !          2040:         tapeBlockLength += (mediaInfoBuffer->ParameterListBlock.BlockLength[0] << 16);
        !          2041: 
        !          2042:         ExFreePool(mediaInfoBuffer);
        !          2043: 
        !          2044:         switch (tapeSetPosition->Partition) {
        !          2045:             case 0:
        !          2046:                 break;
        !          2047: 
        !          2048:             case DIRECTORY_PARTITION:
        !          2049:             case DATA_PARTITION:
        !          2050:                 if (tapeData->CurrentPartition != NO_PARTITIONS) {
        !          2051:                     if (tapeSetPosition->Partition
        !          2052:                         != tapeData->CurrentPartition) {
        !          2053:                         changePartition = TRUE;
        !          2054:                     }
        !          2055:                     break;
        !          2056:                 }
        !          2057:                 // else: fall through to next case
        !          2058: 
        !          2059:             default:
        !          2060:                 DebugPrint((1,"TapeSetPosition: Partition -- invalid parameter\n"));
        !          2061:                 return STATUS_INVALID_PARAMETER;
        !          2062:         }
        !          2063: 
        !          2064:         physPosition =
        !          2065:             TapeLogicalBlockToPhysicalBlock(
        !          2066:                 densityCode,
        !          2067:                 tapePositionVector,
        !          2068:                 tapeBlockLength,
        !          2069:                 (BOOLEAN)(
        !          2070:                     (tapeData->CurrentPartition
        !          2071:                         == DIRECTORY_PARTITION)?
        !          2072:                     NOT_FROM_BOT : FROM_BOT
        !          2073:                 )
        !          2074:             );
        !          2075: 
        !          2076:         tapePositionVector = physPosition.SeekBlockAddress;
        !          2077: 
        !          2078:     }
        !          2079: 
        !          2080:     //
        !          2081:     // Zero CDB in SRB on stack.
        !          2082:     //
        !          2083: 
        !          2084:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          2085: 
        !          2086:     //
        !          2087:     // Prepare SCSI command (CDB)
        !          2088:     //
        !          2089: 
        !          2090:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !          2091: 
        !          2092:     cdb->CDB6GENERIC.Immediate = tapeSetPosition->Immediate;
        !          2093: 
        !          2094:     switch (method) {
        !          2095:         case TAPE_REWIND:
        !          2096:             DebugPrint((3,"TapeSetPosition: method == rewind\n"));
        !          2097:             cdb->CDB6GENERIC.OperationCode = SCSIOP_REWIND;
        !          2098:             srb.TimeOutValue = 180;
        !          2099:             break;
        !          2100: 
        !          2101:         case TAPE_PSEUDO_LOGICAL_BLOCK:
        !          2102:         case TAPE_ABSOLUTE_BLOCK:
        !          2103:             DebugPrint((3,"TapeSetPosition: method == locate (absolute)\n"));
        !          2104:             srb.CdbLength = CDB10GENERIC_LENGTH;
        !          2105:             cdb->LOCATE.OperationCode = SCSIOP_LOCATE;
        !          2106:             cdb->LOCATE.CPBit = changePartition? SETBITON : SETBITOFF;
        !          2107:             cdb->LOCATE.BTBit = SETBITON;
        !          2108:             cdb->LOCATE.LogicalBlockAddress[1] =
        !          2109:                 ((tapePositionVector >> 16) & 0xFF);
        !          2110:             cdb->LOCATE.LogicalBlockAddress[2] =
        !          2111:                 ((tapePositionVector >> 8) & 0xFF);
        !          2112:             cdb->LOCATE.LogicalBlockAddress[3] =
        !          2113:                 (tapePositionVector & 0xFF);
        !          2114:             if (changePartition &&
        !          2115:                 (tapeSetPosition->Partition == DIRECTORY_PARTITION)) {
        !          2116:                 cdb->LOCATE.Partition = 1;
        !          2117:             }
        !          2118:             srb.TimeOutValue = 480;
        !          2119:             if ((physPosition.SpaceBlockCount != 0) &&
        !          2120:                 (method == TAPE_PSEUDO_LOGICAL_BLOCK)) {
        !          2121: 
        !          2122:                 //
        !          2123:                 // Send SCSI command (CDB) to device
        !          2124:                 //
        !          2125: 
        !          2126:                 DebugPrint((3,"TapeSetPosition: SendSrb (locate)\n"));
        !          2127: 
        !          2128:                 status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          2129:                                                      &srb,
        !          2130:                                                      NULL,
        !          2131:                                                      0,
        !          2132:                                                      FALSE);
        !          2133: 
        !          2134:                 if (!NT_SUCCESS(status)) {
        !          2135:                     DebugPrint((1,"TapeSetPosition: locate, SendSrb unsuccessful\n"));
        !          2136:                     return status;
        !          2137:                 }
        !          2138: 
        !          2139:                 //
        !          2140:                 // Zero CDB in SRB on stack.
        !          2141:                 //
        !          2142: 
        !          2143:                 RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          2144: 
        !          2145:                 //
        !          2146:                 // Prepare SCSI command (CDB)
        !          2147:                 //
        !          2148: 
        !          2149:                 srb.CdbLength = CDB6GENERIC_LENGTH;
        !          2150: 
        !          2151:                 DebugPrint((3,"TapeSetPosition: method == space block(s)\n"));
        !          2152:                 cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
        !          2153:                 cdb->SPACE_TAPE_MARKS.Code = 0;
        !          2154:                 cdb->SPACE_TAPE_MARKS.NumMarksMSB =
        !          2155:                      ((physPosition.SpaceBlockCount >> 16) & 0xFF);
        !          2156:                 cdb->SPACE_TAPE_MARKS.NumMarks =
        !          2157:                      ((physPosition.SpaceBlockCount >> 8) & 0xFF);
        !          2158:                 cdb->SPACE_TAPE_MARKS.NumMarksLSB =
        !          2159:                      (physPosition.SpaceBlockCount & 0xFF);
        !          2160:                 srb.TimeOutValue = deviceExtension->TimeOutValue;
        !          2161: 
        !          2162:             }
        !          2163:             break;
        !          2164: 
        !          2165:         case TAPE_SPACE_END_OF_DATA:
        !          2166:             DebugPrint((3,"TapeSetPosition: method == space to end-of-data\n"));
        !          2167:             cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
        !          2168:             cdb->SPACE_TAPE_MARKS.Code = 3;
        !          2169:             srb.TimeOutValue = 480;
        !          2170:             break;
        !          2171: 
        !          2172:         case TAPE_SPACE_RELATIVE_BLOCKS:
        !          2173:             DebugPrint((3,"TapeSetPosition: method == space blocks\n"));
        !          2174:             cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
        !          2175:             cdb->SPACE_TAPE_MARKS.Code = 0;
        !          2176:             cdb->SPACE_TAPE_MARKS.NumMarksMSB =
        !          2177:                 ((tapePositionVector >> 16) & 0xFF);
        !          2178:             cdb->SPACE_TAPE_MARKS.NumMarks =
        !          2179:                 ((tapePositionVector >> 8) & 0xFF);
        !          2180:             cdb->SPACE_TAPE_MARKS.NumMarksLSB =
        !          2181:                 (tapePositionVector & 0xFF);
        !          2182:             srb.TimeOutValue = 4100;
        !          2183:             break;
        !          2184: 
        !          2185:         case TAPE_SPACE_FILEMARKS:
        !          2186:             DebugPrint((3,"TapeSetPosition: method == space filemarks\n"));
        !          2187:             cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
        !          2188:             cdb->SPACE_TAPE_MARKS.Code = 1;
        !          2189:             cdb->SPACE_TAPE_MARKS.NumMarksMSB =
        !          2190:                 ((tapePositionVector >> 16) & 0xFF);
        !          2191:             cdb->SPACE_TAPE_MARKS.NumMarks =
        !          2192:                 ((tapePositionVector >> 8) & 0xFF);
        !          2193:             cdb->SPACE_TAPE_MARKS.NumMarksLSB =
        !          2194:                 (tapePositionVector & 0xFF);
        !          2195:             srb.TimeOutValue = 4100;
        !          2196:             break;
        !          2197: 
        !          2198:         case TAPE_SPACE_SEQUENTIAL_FMKS:
        !          2199:             DebugPrint((3,"TapeSetPosition: method == space sequential filemarks\n"));
        !          2200:             cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
        !          2201:             cdb->SPACE_TAPE_MARKS.Code = 2;
        !          2202:             cdb->SPACE_TAPE_MARKS.NumMarksMSB =
        !          2203:                 ((tapePositionVector >> 16) & 0xFF);
        !          2204:             cdb->SPACE_TAPE_MARKS.NumMarks =
        !          2205:                 ((tapePositionVector >> 8) & 0xFF);
        !          2206:             cdb->SPACE_TAPE_MARKS.NumMarksLSB =
        !          2207:                 (tapePositionVector & 0xFF);
        !          2208:             srb.TimeOutValue = 4100;
        !          2209:             break;
        !          2210: 
        !          2211:         case TAPE_SPACE_SETMARKS:
        !          2212:             DebugPrint((3,"TapeSetPosition: method == space setmarks\n"));
        !          2213:             cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
        !          2214:             cdb->SPACE_TAPE_MARKS.Code = 4;
        !          2215:             cdb->SPACE_TAPE_MARKS.NumMarksMSB =
        !          2216:                 ((tapePositionVector >> 16) & 0xFF);
        !          2217:             cdb->SPACE_TAPE_MARKS.NumMarks =
        !          2218:                 ((tapePositionVector >> 8) & 0xFF);
        !          2219:             cdb->SPACE_TAPE_MARKS.NumMarksLSB =
        !          2220:                 (tapePositionVector & 0xFF);
        !          2221:             srb.TimeOutValue = 4100;
        !          2222:             break;
        !          2223: 
        !          2224:         default:
        !          2225:             DebugPrint((1,"TapeSetPosition: PositionMethod -- operation not supported\n"));
        !          2226:             return STATUS_NOT_IMPLEMENTED;
        !          2227:     }
        !          2228: 
        !          2229:     //
        !          2230:     // Send SCSI command (CDB) to device
        !          2231:     //
        !          2232: 
        !          2233:     DebugPrint((3,"TapeSetPosition: SendSrb (method)\n"));
        !          2234: 
        !          2235:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          2236:                                          &srb,
        !          2237:                                          NULL,
        !          2238:                                          0,
        !          2239:                                          FALSE);
        !          2240: 
        !          2241:     if (NT_SUCCESS(status)) {
        !          2242:         if (changePartition) {
        !          2243:             tapeData->CurrentPartition = tapeSetPosition->Partition;
        !          2244:         }
        !          2245:     } else {
        !          2246:         DebugPrint((1,"TapeSetPosition: method, SendSrb unsuccessful\n"));
        !          2247:     }
        !          2248: 
        !          2249:     return status;
        !          2250: 
        !          2251: } // end TapeSetPosition()
        !          2252: 
        !          2253: 
        !          2254: BOOLEAN
        !          2255: TapeVerifyInquiry(
        !          2256:     IN PSCSI_INQUIRY_DATA LunInfo
        !          2257:     )
        !          2258: 
        !          2259: /*++
        !          2260: Routine Description:
        !          2261: 
        !          2262:     This routine determines if this driver should claim this device.
        !          2263: 
        !          2264: Arguments:
        !          2265: 
        !          2266:     LunInfo
        !          2267: 
        !          2268: Return Value:
        !          2269: 
        !          2270:     TRUE  - driver should claim this device.
        !          2271:     FALSE - driver should not claim this device.
        !          2272: 
        !          2273: --*/
        !          2274: 
        !          2275: {
        !          2276:     PINQUIRYDATA inquiryData;
        !          2277: 
        !          2278:     DebugPrint((3,"TapeVerifyInquiry: Enter routine\n"));
        !          2279: 
        !          2280:     inquiryData = (PVOID)LunInfo->InquiryData;
        !          2281: 
        !          2282:     //
        !          2283:     //  Determine, from the Product ID field in the
        !          2284:     //  inquiry data, whether or not to "claim" this drive.
        !          2285:     //
        !          2286: 
        !          2287:     return WhichIsIt(inquiryData)? TRUE : FALSE;
        !          2288: 
        !          2289: } // end TapeVerifyInquiry()
        !          2290: 
        !          2291: 
        !          2292: NTSTATUS
        !          2293: TapeWriteMarks(
        !          2294:     IN PDEVICE_OBJECT DeviceObject,
        !          2295:     IN PIRP Irp
        !          2296:     )
        !          2297: 
        !          2298: /*++
        !          2299: Routine Description:
        !          2300: 
        !          2301:     This routine writes tapemarks on the tape.
        !          2302: 
        !          2303: Arguments:
        !          2304: 
        !          2305:     DeviceObject
        !          2306:     Irp
        !          2307: 
        !          2308: Return Value:
        !          2309: 
        !          2310:     NTSTATUS
        !          2311: 
        !          2312: --*/
        !          2313: 
        !          2314: {
        !          2315:     PDEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
        !          2316:     PTAPE_WRITE_MARKS  tapeWriteMarks = Irp->AssociatedIrp.SystemBuffer;
        !          2317:     SCSI_REQUEST_BLOCK srb;
        !          2318:     PCDB               cdb = (PCDB)srb.Cdb;
        !          2319:     NTSTATUS           status;
        !          2320: 
        !          2321:     DebugPrint((3,"TapeWriteMarks: Enter routine\n"));
        !          2322: 
        !          2323:     if (tapeWriteMarks->Immediate) {
        !          2324:         switch (tapeWriteMarks->Type) {
        !          2325:             case TAPE_SETMARKS:
        !          2326:             case TAPE_FILEMARKS:
        !          2327:                 DebugPrint((3,"TapeWriteMarks: immediate\n"));
        !          2328:                 break;
        !          2329: 
        !          2330:             case TAPE_SHORT_FILEMARKS:
        !          2331:             case TAPE_LONG_FILEMARKS:
        !          2332:             default:
        !          2333:                 DebugPrint((1,"TapeWriteMarks: TapemarkType, immediate -- operation not supported\n"));
        !          2334:                 return STATUS_NOT_IMPLEMENTED;
        !          2335:         }
        !          2336:     }
        !          2337: 
        !          2338:     //
        !          2339:     // Zero CDB in SRB on stack.
        !          2340:     //
        !          2341: 
        !          2342:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          2343: 
        !          2344:     //
        !          2345:     // Prepare SCSI command (CDB)
        !          2346:     //
        !          2347: 
        !          2348:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !          2349: 
        !          2350:     cdb->WRITE_TAPE_MARKS.OperationCode = SCSIOP_WRITE_FILEMARKS;
        !          2351:     cdb->WRITE_TAPE_MARKS.Immediate = tapeWriteMarks->Immediate;
        !          2352: 
        !          2353:     switch (tapeWriteMarks->Type) {
        !          2354:         case TAPE_SETMARKS:
        !          2355:             DebugPrint((3,"TapeWriteMarks: TapemarkType == setmarks\n"));
        !          2356:             cdb->WRITE_TAPE_MARKS.WriteSetMarks = SETBITON;
        !          2357:             break;
        !          2358: 
        !          2359:         case TAPE_FILEMARKS:
        !          2360:             DebugPrint((3,"TapeWriteMarks: TapemarkType == filemarks\n"));
        !          2361:             break;
        !          2362: 
        !          2363:         case TAPE_SHORT_FILEMARKS:
        !          2364:         case TAPE_LONG_FILEMARKS:
        !          2365:         default:
        !          2366:             DebugPrint((1,"TapeWriteMarks: TapemarkType -- operation not supported\n"));
        !          2367:             return STATUS_NOT_IMPLEMENTED;
        !          2368:     }
        !          2369: 
        !          2370:     cdb->WRITE_TAPE_MARKS.TransferLength[0] =
        !          2371:         ((tapeWriteMarks->Count >> 16) & 0xFF);
        !          2372:     cdb->WRITE_TAPE_MARKS.TransferLength[1] =
        !          2373:         ((tapeWriteMarks->Count >> 8) & 0xFF);
        !          2374:     cdb->WRITE_TAPE_MARKS.TransferLength[2] =
        !          2375:         (tapeWriteMarks->Count & 0xFF);
        !          2376: 
        !          2377:     //
        !          2378:     // Set timeout value.
        !          2379:     //
        !          2380: 
        !          2381:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !          2382: 
        !          2383:     //
        !          2384:     // Send SCSI command (CDB) to device
        !          2385:     //
        !          2386: 
        !          2387:     DebugPrint((3,"TapeWriteMarks: SendSrb (TapemarkType)\n"));
        !          2388: 
        !          2389:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          2390:                                          &srb,
        !          2391:                                          NULL,
        !          2392:                                          0,
        !          2393:                                          FALSE);
        !          2394: 
        !          2395:     if (!NT_SUCCESS(status)) {
        !          2396:         DebugPrint((1,"TapeWriteMarks: TapemarkType, SendSrb unsuccessful\n"));
        !          2397:     }
        !          2398: 
        !          2399:     return status;
        !          2400: 
        !          2401: } // end TapeWriteMarks()
        !          2402: 
        !          2403: 
        !          2404: static
        !          2405: NTSTATUS
        !          2406: GetInquiryInformationData (
        !          2407:     IN  PDEVICE_OBJECT  DeviceObject,
        !          2408:     IN  PIRP            Irp,
        !          2409:     OUT PINQUIRYDATA    InquiryBuffer
        !          2410:     )
        !          2411: 
        !          2412: /*++
        !          2413: Routine Description:
        !          2414: 
        !          2415:      Get the inquiry parameter list buffer
        !          2416:      
        !          2417: Arguments:
        !          2418: 
        !          2419:     DeviceObject
        !          2420:     Irp
        !          2421:     InquiryBuffer
        !          2422: 
        !          2423: Return Value:
        !          2424: 
        !          2425:     NTSTATUS
        !          2426: 
        !          2427: --*/
        !          2428: 
        !          2429: {
        !          2430:     PDEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
        !          2431:     SCSI_REQUEST_BLOCK srb;
        !          2432:     PCDB               cdb = (PCDB)srb.Cdb;
        !          2433:     NTSTATUS           status;
        !          2434:      
        !          2435:     RtlZeroMemory(InquiryBuffer, sizeof(INQUIRYDATA));
        !          2436: 
        !          2437:     //
        !          2438:     // Zero CDB in SRB on stack.
        !          2439:     //
        !          2440: 
        !          2441:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          2442: 
        !          2443:     //
        !          2444:     // Prepare SCSI command (CDB)
        !          2445:     //
        !          2446: 
        !          2447:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !          2448: 
        !          2449:     cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY;
        !          2450:     cdb->CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE;
        !          2451: 
        !          2452:     //
        !          2453:     // Set timeout value.
        !          2454:     //
        !          2455: 
        !          2456:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !          2457: 
        !          2458:     //
        !          2459:     // Send SCSI command (CDB) to device
        !          2460:     //
        !          2461: 
        !          2462:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          2463:                                          &srb,
        !          2464:                                          InquiryBuffer,
        !          2465:                                          INQUIRYDATABUFFERSIZE,
        !          2466:                                          FALSE);
        !          2467:                                 
        !          2468:     return status;
        !          2469: }
        !          2470: 
        !          2471: 
        !          2472: static
        !          2473: NTSTATUS
        !          2474: RewindToBOT(
        !          2475:     IN PDEVICE_OBJECT DeviceObject,
        !          2476:     IN PIRP Irp
        !          2477:     )
        !          2478: 
        !          2479: /*++
        !          2480: Routine Description:
        !          2481: 
        !          2482:      This routine will rewind to BOT.  Note: BOP is BOT for both the
        !          2483:      data partition and the directory partition; thus, if QFA is enabled,
        !          2484:      a rewind to BOT is a rewind to BOP of the active partition.
        !          2485:     
        !          2486: Arguments:
        !          2487: 
        !          2488:     DeviceObject
        !          2489:     Irp
        !          2490: 
        !          2491: Return Value:
        !          2492: 
        !          2493:     NTSTATUS
        !          2494: 
        !          2495: --*/
        !          2496: 
        !          2497: {
        !          2498:     PDEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
        !          2499:     SCSI_REQUEST_BLOCK srb;
        !          2500:     PCDB               cdb = (PCDB)srb.Cdb;
        !          2501:     NTSTATUS           status;
        !          2502: 
        !          2503:     //
        !          2504:     // Zero CDB in SRB on stack.
        !          2505:     //
        !          2506: 
        !          2507:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          2508:     
        !          2509:     //
        !          2510:     // Prepare SCSI command (CDB)
        !          2511:     //
        !          2512: 
        !          2513:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !          2514:     
        !          2515:     cdb->CDB6INQUIRY.OperationCode = SCSIOP_REWIND;
        !          2516:     
        !          2517:     //
        !          2518:     // Set timeout value.
        !          2519:     //
        !          2520:     
        !          2521:     srb.TimeOutValue = 180;
        !          2522:     
        !          2523:     //
        !          2524:     // Send SCSI command (CDB) to device
        !          2525:     //
        !          2526: 
        !          2527:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          2528:                                          &srb,
        !          2529:                                          NULL,
        !          2530:                                          0,
        !          2531:                                          FALSE);
        !          2532:     return status;
        !          2533: }
        !          2534: 
        !          2535: 
        !          2536: static
        !          2537: ULONG
        !          2538: WhichIsIt(
        !          2539:     IN PINQUIRYDATA InquiryData
        !          2540:     )
        !          2541: 
        !          2542: /*++
        !          2543: Routine Description:
        !          2544: 
        !          2545:     This routine determines a drive's identity from the Product ID field
        !          2546:     in its inquiry data.
        !          2547: 
        !          2548: Arguments:
        !          2549: 
        !          2550:     InquiryData (from an Inquiry command)
        !          2551: 
        !          2552: Return Value:
        !          2553: 
        !          2554:     driveID
        !          2555: 
        !          2556: --*/
        !          2557: 
        !          2558: {
        !          2559:     if (RtlCompareMemory(InquiryData->VendorId,"TANDBERG",8) == 8) {
        !          2560: 
        !          2561:         if (RtlCompareMemory(InquiryData->ProductId," TDC 3600",9) == 9) {
        !          2562:             return TDC_3600;
        !          2563:         }
        !          2564: 
        !          2565:         if (RtlCompareMemory(InquiryData->ProductId," TDC 3800",9) == 9) {
        !          2566:             return TDC_3800;
        !          2567:         }
        !          2568: 
        !          2569:         if (RtlCompareMemory(InquiryData->ProductId," TDC 4100",9) == 9) {
        !          2570:             return TDC_4100;
        !          2571:         }
        !          2572: 
        !          2573:         if (RtlCompareMemory(InquiryData->ProductId," IBM 4100",9) == 9) {
        !          2574:             return TDC_4100;
        !          2575:         }
        !          2576: 
        !          2577:         if (RtlCompareMemory(InquiryData->ProductId," TDC 4200",9) == 9) {
        !          2578:             return TDC_4200;
        !          2579:         }
        !          2580: 
        !          2581:     }
        !          2582: 
        !          2583:     if (RtlCompareMemory(InquiryData->VendorId,"DEC     ",8) == 8) {
        !          2584: 
        !          2585:         if (RtlCompareMemory(InquiryData->ProductId,"TZK10",5) == 5) {
        !          2586:             return TDC_3800;
        !          2587:         }
        !          2588: 
        !          2589:     }
        !          2590: 
        !          2591:     return (ULONG)0;
        !          2592: }

unix.superglobalmegacorp.com

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