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

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

unix.superglobalmegacorp.com

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