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