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

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

unix.superglobalmegacorp.com

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