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

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

unix.superglobalmegacorp.com

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