Annotation of ntddk/src/scsi/scsitape/archqic/archqic.c, revision 1.1.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.