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

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

unix.superglobalmegacorp.com

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