Annotation of ntddk/src/scsi/scsitape/exabyte1/exabyte1.c, revision 1.1

1.1     ! root        1: /*++
        !             2: 
        !             3: Copyright (c) 1992  Microsoft Corporation
        !             4: 
        !             5: Module Name:
        !             6: 
        !             7:     exabyte1.c
        !             8: 
        !             9: Abstract:
        !            10: 
        !            11:     This module contains the device-specific routines for the Exabyte
        !            12:     EXB-8200 tape drive and the Exabyte EXB-8200sx handled as an EXB-8200.
        !            13: 
        !            14: Author:
        !            15: 
        !            16:     Mike Glass
        !            17:     Hunter Small (Maynard)
        !            18:     Lori Brown (Maynard)
        !            19:     Chris Hugh Sam (Maynard)
        !            20: 
        !            21: Environment:
        !            22: 
        !            23:     kernel mode only
        !            24: 
        !            25: Revision History:
        !            26: 
        !            27: --*/
        !            28: 
        !            29: #include "ntddk.h"
        !            30: #include "tape.h"
        !            31: 
        !            32: //
        !            33: //  Internal (module wide) defines that symbolize
        !            34: //  the 8mm drives supported by this module.
        !            35: //
        !            36: #define EXABYTE_8200    1  // aka the Maynard 2200hs & 2200+
        !            37: #define EXABYTE_8200SX  2  // Exabyte's own brand (OEM?) 8200SX
        !            38: #define EXABYTE_8205    3  // An Exabyte 8200 with data compresion
        !            39: 
        !            40: //
        !            41: // Define EXABYTE vendor unique mode select/sense information.
        !            42: //
        !            43: 
        !            44: #define EXABYTE_MODE_LENGTH          0x11
        !            45: #define EXABYTE_CARTRIDGE            0x80
        !            46: #define EXABYTE_NO_DATA_DISCONNECT   0x20
        !            47: #define EXABYTE_NO_BUSY_ENABLE       0x08
        !            48: #define EXABYTE_EVEN_BYTE_DISCONNECT 0x04
        !            49: #define EXABYTE_PARITY_ENABLE        0x02
        !            50: #define EXABYTE_NO_AUTO_LOAD         0X01
        !            51: 
        !            52: //
        !            53: //
        !            54: //  Function prototype(s) for internal function(s)
        !            55: //
        !            56: static  ULONG  WhichIsIt(IN PINQUIRYDATA InquiryData);
        !            57: 
        !            58: 
        !            59: NTSTATUS
        !            60: TapeCreatePartition(
        !            61:     IN PDEVICE_OBJECT DeviceObject,
        !            62:     IN PIRP Irp
        !            63:     )
        !            64: 
        !            65: /*++
        !            66: Routine Description:
        !            67: 
        !            68:     This routine would partition the tape if the drive was able to do
        !            69:     so: because the drive cannot do so, this routine always returns a
        !            70:     STATUS_NOT_IMPLEMENTED status.
        !            71: 
        !            72: Arguments:
        !            73: 
        !            74:     DeviceObject
        !            75:     Irp
        !            76: 
        !            77: Return Value:
        !            78: 
        !            79:     NTSTATUS
        !            80: 
        !            81: --*/
        !            82: 
        !            83: {
        !            84:     DebugPrint((3,"TapeCreatePartition: Enter routine\n"));
        !            85:     DebugPrint((1,"TapeCreatePartition: operation not supported\n"));
        !            86:     return STATUS_NOT_IMPLEMENTED;
        !            87: 
        !            88: } // end TapeCreatePartition()
        !            89: 
        !            90: 
        !            91: NTSTATUS
        !            92: TapeErase(
        !            93:     IN PDEVICE_OBJECT DeviceObject,
        !            94:     IN PIRP Irp
        !            95:     )
        !            96: 
        !            97: /*++
        !            98: Routine Description:
        !            99: 
        !           100:     This routine will erase to EOT from the "current position" on tape;
        !           101:     i.e., tape will be erased to EOT from the point on tape at which the
        !           102:     tape is positioned at the time of entry herein.
        !           103: 
        !           104: Arguments:
        !           105: 
        !           106:     DeviceObject
        !           107:     Irp
        !           108: 
        !           109: Return Value:
        !           110: 
        !           111:     NTSTATUS
        !           112: 
        !           113: --*/
        !           114: 
        !           115: {
        !           116:     PTAPE_ERASE         tapeErase = Irp->AssociatedIrp.SystemBuffer;
        !           117:     SCSI_REQUEST_BLOCK  srb;
        !           118:     PCDB                cdb = (PCDB)srb.Cdb;
        !           119:     NTSTATUS            status;
        !           120: 
        !           121:     DebugPrint((3,"TapeErase: Enter routine\n"));
        !           122: 
        !           123:     if (tapeErase->Immediate) {
        !           124:         DebugPrint((1,"TapeErase: EraseType, immediate -- operation not supported\n"));
        !           125:         return STATUS_NOT_IMPLEMENTED;
        !           126:     }
        !           127: 
        !           128:     switch (tapeErase->Type) {
        !           129:         case TAPE_ERASE_LONG:
        !           130:             DebugPrint((3,"TapeErase: long\n"));
        !           131:             break;
        !           132: 
        !           133:         case TAPE_ERASE_SHORT:
        !           134:         default:
        !           135:             DebugPrint((1,"TapeErase: EraseType -- operation not supported\n"));
        !           136:             return STATUS_NOT_IMPLEMENTED;
        !           137:     }
        !           138: 
        !           139:     //
        !           140:     // Zero CDB in SRB on stack.
        !           141:     //
        !           142: 
        !           143:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           144: 
        !           145:     //
        !           146:     // Prepare SCSI command (CDB)
        !           147:     //
        !           148: 
        !           149:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !           150: 
        !           151:     cdb->ERASE.OperationCode = SCSIOP_ERASE;
        !           152:     cdb->ERASE.Long = SETBITON;
        !           153: 
        !           154:     //
        !           155:     // Set timeout value.
        !           156:     //
        !           157: 
        !           158:     srb.TimeOutValue = 18000;
        !           159: 
        !           160:     //
        !           161:     // Send SCSI command (CDB) to device
        !           162:     //
        !           163: 
        !           164:     DebugPrint((3,"TapeErase: SendSrb (erase)\n"));
        !           165: 
        !           166:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           167:                                          &srb,
        !           168:                                          NULL,
        !           169:                                          0,
        !           170:                                          FALSE);
        !           171: 
        !           172:     if (!NT_SUCCESS(status)) {
        !           173:         DebugPrint((1,"TapeErase: erase, SendSrb unsuccessful\n"));
        !           174:     }
        !           175: 
        !           176:     return status;
        !           177: 
        !           178: } // end TapeErase()
        !           179: 
        !           180: 
        !           181: VOID
        !           182: TapeError(
        !           183:     PDEVICE_OBJECT DeviceObject,
        !           184:     PSCSI_REQUEST_BLOCK Srb,
        !           185:     NTSTATUS *Status,
        !           186:     BOOLEAN *Retry
        !           187:     )
        !           188: 
        !           189: /*++
        !           190: 
        !           191: Routine Description:
        !           192: 
        !           193:     When a request completes with error, the routine InterpretSenseInfo is
        !           194:     called to determine from the sense data whether the request should be
        !           195:     retried and what NT status to set in the IRP. Then this routine is called
        !           196:     for tape requests to handle tape-specific errors and update the nt status
        !           197:     and retry boolean.
        !           198: 
        !           199: Arguments:
        !           200: 
        !           201:     DeviceObject - Supplies a pointer to the device object.
        !           202: 
        !           203:     Srb - Supplies a pointer to the failing Srb.
        !           204: 
        !           205:     Status - NT Status used to set the IRP's completion status.
        !           206: 
        !           207:     Retry - Indicates that this request should be retried.
        !           208: 
        !           209: Return Value:
        !           210: 
        !           211:     None.
        !           212: 
        !           213: --*/
        !           214: 
        !           215: {
        !           216:     PDEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
        !           217:     PSENSE_DATA        senseBuffer = Srb->SenseInfoBuffer;
        !           218:     NTSTATUS           status = *Status;
        !           219:     BOOLEAN            retry = *Retry;
        !           220:     UCHAR              adsenseq = senseBuffer->AdditionalSenseCodeQualifier;
        !           221:     UCHAR              adsense = senseBuffer->AdditionalSenseCode;
        !           222: 
        !           223:     DebugPrint((3,"TapeError: Enter routine\n"));
        !           224:     DebugPrint((1,"TapeError: Status 0x%.8X, Retry %d\n", status, retry));
        !           225: 
        !           226:     switch (status) {
        !           227:         case STATUS_DEVICE_NOT_READY:
        !           228:             *Status = STATUS_NO_MEDIA;
        !           229:             *Retry = FALSE;
        !           230:             break;
        !           231: 
        !           232:         case STATUS_NO_DATA_DETECTED:
        !           233:             break;
        !           234:     }
        !           235: 
        !           236:     DebugPrint((1,"TapeError: Status 0x%.8X, Retry %d\n", *Status, *Retry));
        !           237:     return;
        !           238: 
        !           239: } // end TapeError()
        !           240: 
        !           241: 
        !           242: NTSTATUS
        !           243: TapeGetDriveParameters(
        !           244:     IN PDEVICE_OBJECT DeviceObject,
        !           245:     IN PIRP Irp
        !           246:     )
        !           247: 
        !           248: /*++
        !           249: Routine Description:
        !           250: 
        !           251:     This routine returns an indication if reporting setmarks is disabled or
        !           252:     enabled, the default fixed-block size, the maximum block size, the
        !           253:     minimum block size, the maximum number of partitions, and the device
        !           254:     features flag.
        !           255: 
        !           256: Arguments:
        !           257: 
        !           258:     DeviceObject
        !           259:     Irp
        !           260: 
        !           261: Return Value:
        !           262: 
        !           263:     NTSTATUS
        !           264: 
        !           265: --*/
        !           266: 
        !           267: {
        !           268:     PDEVICE_EXTENSION          deviceExtension = DeviceObject->DeviceExtension;
        !           269:     PTAPE_GET_DRIVE_PARAMETERS tapeGetDriveParams = Irp->AssociatedIrp.SystemBuffer;
        !           270:     PREAD_BLOCK_LIMITS_DATA    blockLimits;
        !           271:     SCSI_REQUEST_BLOCK         srb;
        !           272:     PCDB                       cdb = (PCDB)srb.Cdb;
        !           273:     NTSTATUS                   status;
        !           274: 
        !           275:     DebugPrint((3,"TapeGetDriveParameters: Enter routine\n"));
        !           276: 
        !           277:     RtlZeroMemory(tapeGetDriveParams, sizeof(TAPE_GET_DRIVE_PARAMETERS));
        !           278:     Irp->IoStatus.Information = sizeof(TAPE_GET_DRIVE_PARAMETERS);
        !           279: 
        !           280:     blockLimits = ExAllocatePool(NonPagedPoolCacheAligned,
        !           281:                                  sizeof(READ_BLOCK_LIMITS_DATA));
        !           282: 
        !           283:     if (!blockLimits) {
        !           284:         DebugPrint((1,"TapeGetDriveParameters: insufficient resources (blockLimits)\n"));
        !           285:         return STATUS_INSUFFICIENT_RESOURCES;
        !           286:     }
        !           287: 
        !           288:     RtlZeroMemory(blockLimits, sizeof(READ_BLOCK_LIMITS_DATA));
        !           289: 
        !           290:     //
        !           291:     // Zero CDB in SRB on stack.
        !           292:     //
        !           293: 
        !           294:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           295: 
        !           296:     //
        !           297:     // Prepare SCSI command (CDB)
        !           298:     //
        !           299: 
        !           300:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !           301: 
        !           302:     cdb->CDB6GENERIC.OperationCode = SCSIOP_READ_BLOCK_LIMITS;
        !           303: 
        !           304:     //
        !           305:     // Set timeout value.
        !           306:     //
        !           307: 
        !           308:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !           309: 
        !           310:     //
        !           311:     // Send SCSI command (CDB) to device
        !           312:     //
        !           313: 
        !           314:     DebugPrint((3,"TapeGetDriveParameters: SendSrb (read block limits)\n"));
        !           315: 
        !           316:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           317:                                          &srb,
        !           318:                                          blockLimits,
        !           319:                                          sizeof(READ_BLOCK_LIMITS_DATA),
        !           320:                                          FALSE);
        !           321: 
        !           322:     if (NT_SUCCESS(status)) {
        !           323:         tapeGetDriveParams->MaximumBlockSize = blockLimits->BlockMaximumSize[2];
        !           324:         tapeGetDriveParams->MaximumBlockSize += (blockLimits->BlockMaximumSize[1] << 8);
        !           325:         tapeGetDriveParams->MaximumBlockSize += (blockLimits->BlockMaximumSize[0] << 16);
        !           326:             
        !           327:         tapeGetDriveParams->MinimumBlockSize = blockLimits->BlockMinimumSize[1];
        !           328:         tapeGetDriveParams->MinimumBlockSize += (blockLimits->BlockMinimumSize[0] << 8);
        !           329:     }
        !           330: 
        !           331:     ExFreePool(blockLimits);
        !           332: 
        !           333:     if (!NT_SUCCESS(status)) {
        !           334:         DebugPrint((1,"TapeGetDriveParameters: read block limits, SendSrb unsuccessful\n"));
        !           335:         return status;
        !           336:     }
        !           337: 
        !           338:     tapeGetDriveParams->ECC = 0;
        !           339:     tapeGetDriveParams->Compression = 0;
        !           340:     tapeGetDriveParams->DataPadding = 0;
        !           341:     tapeGetDriveParams->ReportSetmarks = 0;
        !           342:     tapeGetDriveParams->MaximumPartitionCount = 0;
        !           343:     tapeGetDriveParams->DefaultBlockSize = 1024;
        !           344: 
        !           345:     tapeGetDriveParams->FeaturesLow |=
        !           346:         TAPE_DRIVE_ERASE_LONG |
        !           347:         TAPE_DRIVE_FIXED_BLOCK |
        !           348:         TAPE_DRIVE_VARIABLE_BLOCK |
        !           349:         TAPE_DRIVE_WRITE_PROTECT;
        !           350: 
        !           351:     tapeGetDriveParams->FeaturesHigh |=
        !           352:         TAPE_DRIVE_LOAD_UNLOAD |
        !           353: //        TAPE_DRIVE_LOCK_UNLOCK |
        !           354:         TAPE_DRIVE_REWIND_IMMEDIATE |
        !           355:         TAPE_DRIVE_SET_BLOCK_SIZE |
        !           356:         TAPE_DRIVE_LOAD_UNLD_IMMED |
        !           357:         TAPE_DRIVE_RELATIVE_BLKS |
        !           358:         TAPE_DRIVE_FILEMARKS |
        !           359:         TAPE_DRIVE_REVERSE_POSITION |
        !           360:         TAPE_DRIVE_WRITE_SHORT_FMKS |
        !           361:         TAPE_DRIVE_WRITE_LONG_FMKS;
        !           362: 
        !           363:     tapeGetDriveParams->FeaturesHigh &= ~TAPE_DRIVE_HIGH_FEATURES;
        !           364: 
        !           365:     DebugPrint((3,"TapeGetDriveParameters: FeaturesLow == 0x%.8X\n",
        !           366:         tapeGetDriveParams->FeaturesLow));
        !           367:     DebugPrint((3,"TapeGetDriveParameters: FeaturesHigh == 0x%.8X\n",
        !           368:         tapeGetDriveParams->FeaturesHigh));
        !           369: 
        !           370:     return status;
        !           371: 
        !           372: } // end TapeGetDriveParameters()
        !           373: 
        !           374: 
        !           375: NTSTATUS
        !           376: TapeGetMediaParameters(
        !           377:     IN PDEVICE_OBJECT DeviceObject,
        !           378:     IN PIRP Irp
        !           379:     )
        !           380: 
        !           381: /*++
        !           382: Routine Description:
        !           383: 
        !           384:     This routine determines and returns the "media parameters" of the
        !           385:     Exabyte 8200 tape drive associated with "DeviceObject". Tape media
        !           386:     must be present (loaded) in the drive for this function to return
        !           387:     "no error".
        !           388: 
        !           389: Arguments:
        !           390: 
        !           391:     DeviceObject
        !           392:     Irp
        !           393: 
        !           394: Return Value:
        !           395: 
        !           396:     NTSTATUS
        !           397: 
        !           398: --*/
        !           399: 
        !           400: {
        !           401:     PDEVICE_EXTENSION          deviceExtension = DeviceObject->DeviceExtension;
        !           402:     PTAPE_GET_MEDIA_PARAMETERS tapeGetMediaParams = Irp->AssociatedIrp.SystemBuffer;
        !           403:     PMODE_PARM_READ_WRITE_DATA modeBuffer;
        !           404:     ULONG                      sectorShift;
        !           405:     SCSI_REQUEST_BLOCK         srb;
        !           406:     PCDB                       cdb = (PCDB)srb.Cdb;
        !           407:     NTSTATUS                   status;
        !           408: 
        !           409:     DebugPrint((3,"TapeGetMediaParameters: Enter routine\n"));
        !           410: 
        !           411:     RtlZeroMemory(tapeGetMediaParams, sizeof(TAPE_GET_MEDIA_PARAMETERS));
        !           412:     Irp->IoStatus.Information = sizeof(TAPE_GET_MEDIA_PARAMETERS);
        !           413: 
        !           414:     //
        !           415:     // Zero CDB in SRB on stack.
        !           416:     //
        !           417: 
        !           418:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           419: 
        !           420:     //
        !           421:     // Prepare SCSI command (CDB)
        !           422:     //
        !           423: 
        !           424:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !           425: 
        !           426:     cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
        !           427: 
        !           428:     //
        !           429:     // Set timeout value.
        !           430:     //
        !           431: 
        !           432:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !           433: 
        !           434:     //
        !           435:     // Send SCSI command (CDB) to device
        !           436:     //
        !           437: 
        !           438:     DebugPrint((3,"TapeGetMediaParameters: SendSrb (test unit ready)\n"));
        !           439: 
        !           440:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           441:                                          &srb,
        !           442:                                          NULL,
        !           443:                                          0,
        !           444:                                          FALSE);
        !           445: 
        !           446:     if (!NT_SUCCESS(status)) {
        !           447:         DebugPrint((1,"TapeGetMediaParameters: test unit ready, SendSrb unsuccessful\n"));
        !           448:         return status;
        !           449:     }
        !           450: 
        !           451:     modeBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
        !           452:                                 EXABYTE_MODE_LENGTH);
        !           453: 
        !           454:     if (!modeBuffer) {
        !           455:         DebugPrint((1,"TapeGetMediaParameters: insufficient resources (modeBuffer)\n"));
        !           456:         return STATUS_INSUFFICIENT_RESOURCES;
        !           457:     }
        !           458: 
        !           459:     RtlZeroMemory(modeBuffer, EXABYTE_MODE_LENGTH);
        !           460: 
        !           461:     //
        !           462:     // Zero CDB in SRB on stack.
        !           463:     //
        !           464: 
        !           465:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           466: 
        !           467:     //
        !           468:     // Prepare SCSI command (CDB)
        !           469:     //
        !           470: 
        !           471:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !           472: 
        !           473:     cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE;
        !           474:     cdb->MODE_SENSE.AllocationLength = EXABYTE_MODE_LENGTH;
        !           475: 
        !           476:     //
        !           477:     // Set timeout value.
        !           478:     //
        !           479: 
        !           480:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !           481: 
        !           482:     //
        !           483:     // Send SCSI command (CDB) to device
        !           484:     //
        !           485: 
        !           486:     DebugPrint((3,"TapeGetMediaParameters: SendSrb (mode sense)\n"));
        !           487: 
        !           488:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           489:                                          &srb,
        !           490:                                          modeBuffer,
        !           491:                                          EXABYTE_MODE_LENGTH,
        !           492:                                          FALSE);
        !           493: 
        !           494:     if (NT_SUCCESS(status)) {
        !           495: 
        !           496:         tapeGetMediaParams->BlockSize = modeBuffer->ParameterListBlock.BlockLength[2];
        !           497:         tapeGetMediaParams->BlockSize += (modeBuffer->ParameterListBlock.BlockLength[1] << 8);
        !           498:         tapeGetMediaParams->BlockSize += (modeBuffer->ParameterListBlock.BlockLength[0] << 16);
        !           499: 
        !           500:         WHICH_BIT(tapeGetMediaParams->BlockSize, sectorShift);
        !           501:         deviceExtension->DiskGeometry->BytesPerSector = tapeGetMediaParams->BlockSize;
        !           502:         deviceExtension->SectorShift = sectorShift;
        !           503: 
        !           504:         tapeGetMediaParams->WriteProtected =
        !           505:             ((modeBuffer->ParameterListHeader.DeviceSpecificParameter >> 7) & 0x01);
        !           506: 
        !           507:         //
        !           508:         // Set the even byte disconnect flag in the mode data.  This is the
        !           509:         // first byte of the vendor unique data.
        !           510:         //
        !           511: 
        !           512:         *((PUCHAR)(modeBuffer+1)) |= EXABYTE_EVEN_BYTE_DISCONNECT;
        !           513: 
        !           514:         modeBuffer->ParameterListHeader.ModeDataLength = 0;
        !           515:         modeBuffer->ParameterListHeader.MediumType = 0;
        !           516:         modeBuffer->ParameterListHeader.DeviceSpecificParameter = 0x10;
        !           517:         modeBuffer->ParameterListBlock.DensityCode = 0;
        !           518:         modeBuffer->ParameterListBlock.NumberOfBlocks[0] = 0;
        !           519:         modeBuffer->ParameterListBlock.NumberOfBlocks[1] = 0;
        !           520:         modeBuffer->ParameterListBlock.NumberOfBlocks[2] = 0;
        !           521:         cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
        !           522:             
        !           523:         ScsiClassSendSrbSynchronous(DeviceObject,
        !           524:                                     &srb,
        !           525:                                     modeBuffer,
        !           526:                                     EXABYTE_MODE_LENGTH,
        !           527:                                     TRUE);
        !           528:     
        !           529: 
        !           530:     } else {
        !           531: 
        !           532:         DebugPrint((1,"TapeGetMediaParameters: mode sense, SendSrb unsuccessful\n"));
        !           533: 
        !           534:     }
        !           535: 
        !           536:     ExFreePool(modeBuffer);
        !           537: 
        !           538:     return status;
        !           539: 
        !           540: } // end TapeGetMediaParameters()
        !           541: 
        !           542: 
        !           543: NTSTATUS
        !           544: TapeGetPosition(
        !           545:     IN PDEVICE_OBJECT DeviceObject,
        !           546:     IN PIRP Irp
        !           547:     )
        !           548: 
        !           549: /*++
        !           550: Routine Description:
        !           551: 
        !           552:     This routine would return the current position of the tape;
        !           553:     however, this drive does not support doing so. Hence, this
        !           554:     routine always returns a STATUS_NOT_IMPLEMENTED status.
        !           555: 
        !           556: Arguments:
        !           557: 
        !           558:     DeviceObject
        !           559:     Irp
        !           560: 
        !           561: Return Value:
        !           562: 
        !           563:     NTSTATUS
        !           564: 
        !           565: --*/
        !           566: 
        !           567: {
        !           568:     DebugPrint((3,"TapeGetPosition: Enter routine\n"));
        !           569:     DebugPrint((1,"TapeGetPosition: operation not supported\n"));
        !           570:     return STATUS_NOT_IMPLEMENTED;
        !           571: 
        !           572: } // end TapeGetPosition()
        !           573: 
        !           574: 
        !           575: NTSTATUS
        !           576: TapeGetStatus(
        !           577:     IN PDEVICE_OBJECT DeviceObject,
        !           578:     IN PIRP Irp
        !           579:     )
        !           580: 
        !           581: /*++
        !           582: Routine Description:
        !           583: 
        !           584:     This routine returns the status of the device.
        !           585: 
        !           586: Arguments:
        !           587: 
        !           588:     DeviceObject
        !           589:     Irp
        !           590: 
        !           591: Return Value:
        !           592: 
        !           593:     NTSTATUS
        !           594: 
        !           595: --*/
        !           596: 
        !           597: {
        !           598:     PDEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
        !           599:     SCSI_REQUEST_BLOCK srb;
        !           600:     PCDB               cdb = (PCDB)srb.Cdb;
        !           601:     NTSTATUS           status;
        !           602: 
        !           603:     DebugPrint((3,"TapeGetStatus: Enter routine\n"));
        !           604: 
        !           605:     //
        !           606:     // Zero CDB in SRB on stack.
        !           607:     //
        !           608: 
        !           609:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           610: 
        !           611:     //
        !           612:     // Prepare SCSI command (CDB)
        !           613:     //
        !           614: 
        !           615:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !           616: 
        !           617:     cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
        !           618: 
        !           619:     //
        !           620:     // Set timeout value.
        !           621:     //
        !           622: 
        !           623:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !           624: 
        !           625:     //
        !           626:     // Send SCSI command (CDB) to device
        !           627:     //
        !           628: 
        !           629:     DebugPrint((3,"TapeGetStatus: SendSrb (test unit ready)\n"));
        !           630: 
        !           631:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           632:                                          &srb,
        !           633:                                          NULL,
        !           634:                                          0,
        !           635:                                          FALSE);
        !           636: 
        !           637:     if (!NT_SUCCESS(status)) {
        !           638:         DebugPrint((1,"TapeGetStatus: test unit ready, SendSrb unsuccessful\n"));
        !           639:     }
        !           640: 
        !           641:     return status;
        !           642: 
        !           643: } // end TapeGetStatus()
        !           644: 
        !           645: 
        !           646: NTSTATUS
        !           647: TapePrepare(
        !           648:     IN PDEVICE_OBJECT DeviceObject,
        !           649:     IN PIRP Irp
        !           650:     )
        !           651: 
        !           652: /*++
        !           653: Routine Description:
        !           654: 
        !           655:     This routine loads, unloads, locks, or unlocks the tape.
        !           656: 
        !           657: Arguments:
        !           658: 
        !           659:     DeviceObject
        !           660:     Irp
        !           661: 
        !           662: Return Value:
        !           663: 
        !           664:     NTSTATUS
        !           665: 
        !           666: --*/
        !           667: 
        !           668: {
        !           669:     PDEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
        !           670:     PTAPE_PREPARE      tapePrepare = Irp->AssociatedIrp.SystemBuffer;
        !           671:     SCSI_REQUEST_BLOCK srb;
        !           672:     PCDB               cdb = (PCDB)srb.Cdb;
        !           673:     NTSTATUS           status;
        !           674: 
        !           675:     DebugPrint((3,"TapePrepare: Enter routine\n"));
        !           676: 
        !           677:     if (tapePrepare->Immediate) {
        !           678:         switch (tapePrepare->Operation) {
        !           679:             case TAPE_LOAD:
        !           680:             case TAPE_UNLOAD:
        !           681:                 DebugPrint((3,"TapePrepare: immediate\n"));
        !           682:                 break;
        !           683: 
        !           684:             case TAPE_TENSION:
        !           685:             case TAPE_LOCK:
        !           686:             case TAPE_UNLOCK:
        !           687:             default:
        !           688:                 DebugPrint((1,"TapePrepare: Operation, immediate -- operation not supported\n"));
        !           689:                 return STATUS_NOT_IMPLEMENTED;
        !           690:         }
        !           691:     }
        !           692: 
        !           693:     //
        !           694:     // Zero CDB in SRB on stack.
        !           695:     //
        !           696: 
        !           697:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           698: 
        !           699:     //
        !           700:     // Prepare SCSI command (CDB)
        !           701:     //
        !           702: 
        !           703:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !           704: 
        !           705:     cdb->CDB6GENERIC.Immediate = tapePrepare->Immediate;
        !           706: 
        !           707:     switch (tapePrepare->Operation) {
        !           708:         case TAPE_LOAD:
        !           709:             DebugPrint((3,"TapePrepare: Operation == load\n"));
        !           710:             cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD;
        !           711:             cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x01;
        !           712:             srb.TimeOutValue = 150;
        !           713:             break;
        !           714: 
        !           715:         case TAPE_UNLOAD:
        !           716:             DebugPrint((3,"TapePrepare: Operation == unload\n"));
        !           717:             cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD;
        !           718:             srb.TimeOutValue = 150;
        !           719:             break;
        !           720: 
        !           721:         case TAPE_LOCK:
        !           722:             DebugPrint((3,"TapePrepare: Operation == lock\n"));
        !           723:             cdb->CDB6GENERIC.OperationCode = SCSIOP_MEDIUM_REMOVAL;
        !           724:             cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x01;
        !           725:             srb.TimeOutValue = 150;
        !           726:             break;
        !           727: 
        !           728:         case TAPE_UNLOCK:
        !           729:             DebugPrint((3,"TapePrepare: Operation == unlock\n"));
        !           730:             cdb->CDB6GENERIC.OperationCode = SCSIOP_MEDIUM_REMOVAL;
        !           731:             srb.TimeOutValue = 150;
        !           732:             break;
        !           733: 
        !           734:         default:
        !           735:             DebugPrint((1,"TapePrepare: Operation -- operation not supported\n"));
        !           736:             return STATUS_NOT_IMPLEMENTED;
        !           737:     }
        !           738: 
        !           739:     //
        !           740:     // Send SCSI command (CDB) to device
        !           741:     //
        !           742: 
        !           743:     DebugPrint((3,"TapePrepare: SendSrb (Operation)\n"));
        !           744: 
        !           745:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !           746:                                          &srb,
        !           747:                                          NULL,
        !           748:                                          0,
        !           749:                                          FALSE);
        !           750: 
        !           751:     if (!NT_SUCCESS(status)) {
        !           752:         DebugPrint((1,"TapePrepare: Operation, SendSrb unsuccessful\n"));
        !           753:     }
        !           754: 
        !           755:     return status;
        !           756: 
        !           757: } // end TapePrepare()
        !           758: 
        !           759: 
        !           760: NTSTATUS
        !           761: TapeReadWrite(
        !           762:     IN PDEVICE_OBJECT DeviceObject,
        !           763:     IN PIRP Irp
        !           764:     )
        !           765: 
        !           766: /*++
        !           767: 
        !           768: Routine Description:
        !           769: 
        !           770:     This routine builds SRBs and CDBs for read and write requests to
        !           771:     Exabyte 8200 drives.
        !           772: 
        !           773: Arguments:
        !           774: 
        !           775:     DeviceObject
        !           776:     Irp
        !           777: 
        !           778: Return Value:
        !           779: 
        !           780:     Returns STATUS_PENDING.
        !           781: 
        !           782: --*/
        !           783: 
        !           784:   {
        !           785:     PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension;
        !           786:     PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
        !           787:     PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp);
        !           788:     PSCSI_REQUEST_BLOCK srb;
        !           789:     PCDB cdb;
        !           790:     KIRQL currentIrql;
        !           791:     ULONG transferBlocks;
        !           792:     LARGE_INTEGER startingOffset =
        !           793:       currentIrpStack->Parameters.Read.ByteOffset;
        !           794: 
        !           795:     DebugPrint((3,"TapeReadWrite: Enter routine\n"));
        !           796: 
        !           797:     //
        !           798:     // Allocate an Srb.
        !           799:     //
        !           800: 
        !           801:     if (deviceExtension->SrbZone != NULL &&
        !           802:         (srb = ExInterlockedAllocateFromZone(
        !           803:             deviceExtension->SrbZone,
        !           804:             deviceExtension->SrbZoneSpinLock)) != NULL) {
        !           805: 
        !           806:         srb->SrbFlags = SRB_FLAGS_ALLOCATED_FROM_ZONE;
        !           807: 
        !           808:     } else {
        !           809: 
        !           810:         //
        !           811:         // Allocate Srb from non-paged pool.
        !           812:         // This call must succeed.
        !           813:         //
        !           814: 
        !           815:         srb = ExAllocatePool(NonPagedPoolMustSucceed, SCSI_REQUEST_BLOCK_SIZE);
        !           816: 
        !           817:         srb->SrbFlags = 0;
        !           818: 
        !           819:     }
        !           820: 
        !           821:     //
        !           822:     // Write length to SRB.
        !           823:     //
        !           824: 
        !           825:     srb->Length = SCSI_REQUEST_BLOCK_SIZE;
        !           826: 
        !           827:     //
        !           828:     // Set up IRP Address.
        !           829:     //
        !           830: 
        !           831:     srb->OriginalRequest = Irp;
        !           832: 
        !           833:     //
        !           834:     // Set up target id and logical unit number.
        !           835:     //
        !           836: 
        !           837:     srb->PathId = deviceExtension->PathId;
        !           838:     srb->TargetId = deviceExtension->TargetId;
        !           839:     srb->Lun = deviceExtension->Lun;
        !           840: 
        !           841: 
        !           842:     srb->Function = SRB_FUNCTION_EXECUTE_SCSI;
        !           843: 
        !           844:     srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress);
        !           845: 
        !           846:     //
        !           847:     // Save byte count of transfer in SRB Extension.
        !           848:     //
        !           849: 
        !           850:     srb->DataTransferLength = currentIrpStack->Parameters.Read.Length;
        !           851: 
        !           852:     //
        !           853:     // Indicate auto request sense by specifying buffer and size.
        !           854:     //
        !           855: 
        !           856:     srb->SenseInfoBuffer = deviceExtension->SenseData;
        !           857: 
        !           858:     srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE;
        !           859: 
        !           860:     //
        !           861:     // Initialize the queue actions field.
        !           862:     //
        !           863: 
        !           864:     srb->QueueAction = SRB_SIMPLE_TAG_REQUEST;
        !           865: 
        !           866:     //
        !           867:     // Set timeout value in seconds.
        !           868:     //
        !           869: 
        !           870:     srb->TimeOutValue = deviceExtension->TimeOutValue;
        !           871: 
        !           872:     //
        !           873:     // Zero statuses.
        !           874:     //
        !           875: 
        !           876:     srb->SrbStatus = srb->ScsiStatus = 0;
        !           877: 
        !           878:     srb->NextSrb = 0;
        !           879: 
        !           880:     //
        !           881:     // Indicate that 6-byte CDB's will be used.
        !           882:     //
        !           883: 
        !           884:     srb->CdbLength = CDB6GENERIC_LENGTH;
        !           885: 
        !           886:     //
        !           887:     // Fill in CDB fields.
        !           888:     //
        !           889: 
        !           890:     cdb = (PCDB)srb->Cdb;
        !           891: 
        !           892:     //
        !           893:     // Zero CDB in SRB.
        !           894:     //
        !           895: 
        !           896:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !           897: 
        !           898:     //
        !           899:     // Since we are writing fixed block mode, normalize transfer count
        !           900:     // to number of blocks.
        !           901:     //
        !           902: 
        !           903:     transferBlocks =
        !           904:         currentIrpStack->Parameters.Read.Length >> deviceExtension->SectorShift;
        !           905: 
        !           906:     //
        !           907:     // Set up transfer length
        !           908:     //
        !           909: 
        !           910:     cdb->CDB6READWRITETAPE.TransferLenMSB = (UCHAR)((transferBlocks >> 16) & 0xff);
        !           911:     cdb->CDB6READWRITETAPE.TransferLen    = (UCHAR)((transferBlocks >> 8) & 0xff);
        !           912:     cdb->CDB6READWRITETAPE.TransferLenLSB = (UCHAR)(transferBlocks & 0xff);
        !           913: 
        !           914:     //
        !           915:     // Tell the drive we are in fixed block mode
        !           916:     //
        !           917: 
        !           918:     cdb->CDB6READWRITETAPE.VendorSpecific = 1;
        !           919: 
        !           920:     //
        !           921:     // Set transfer direction flag and Cdb command.
        !           922:     //
        !           923: 
        !           924:     if (currentIrpStack->MajorFunction == IRP_MJ_READ) {
        !           925: 
        !           926:          DebugPrint((3, "TapeRequest: Read Command\n"));
        !           927: 
        !           928:          srb->SrbFlags = SRB_FLAGS_DATA_IN;
        !           929:          cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_READ6;
        !           930: 
        !           931:     } else {
        !           932: 
        !           933:          DebugPrint((3, "TapeRequest: Write Command\n"));
        !           934: 
        !           935:          srb->SrbFlags = SRB_FLAGS_DATA_OUT;
        !           936:          cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_WRITE6;
        !           937:     }
        !           938: 
        !           939:     //
        !           940:     // Or in the default flags from the device object.
        !           941:     //
        !           942: 
        !           943:     srb->SrbFlags |= deviceExtension->SrbFlags;
        !           944: 
        !           945:     //
        !           946:     // Set up major SCSI function.
        !           947:     //
        !           948: 
        !           949:     nextIrpStack->MajorFunction = IRP_MJ_SCSI;
        !           950: 
        !           951:     //
        !           952:     // Save SRB address in next stack for port driver.
        !           953:     //
        !           954: 
        !           955:     nextIrpStack->Parameters.Scsi.Srb = srb;
        !           956: 
        !           957:     //
        !           958:     // Save retry count in current IRP stack.
        !           959:     //
        !           960: 
        !           961:     currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES;
        !           962: 
        !           963:     //
        !           964:     // Set up IoCompletion routine address.
        !           965:     //
        !           966: 
        !           967:     IoSetCompletionRoutine(Irp,
        !           968:                            ScsiClassIoComplete,
        !           969:                            srb,
        !           970:                            TRUE,
        !           971:                            TRUE,
        !           972:                            FALSE);
        !           973: 
        !           974:     return STATUS_PENDING;
        !           975: 
        !           976: } // end TapeReadWrite()
        !           977: 
        !           978: 
        !           979: NTSTATUS
        !           980: TapeSetDriveParameters(
        !           981:     IN PDEVICE_OBJECT DeviceObject,
        !           982:     IN PIRP Irp
        !           983:     )
        !           984: 
        !           985: /*++
        !           986: Routine Description:
        !           987: 
        !           988:     This routine would "set" the "drive parameters", but this drive does not
        !           989:     support doing so: this routine always returns a STATUS_NOT_IMPLEMENTED
        !           990:     status
        !           991: 
        !           992: Arguments:
        !           993: 
        !           994:     DeviceObject
        !           995:     Irp
        !           996: 
        !           997: Return Value:
        !           998: 
        !           999:     NTSTATUS
        !          1000: 
        !          1001: --*/
        !          1002: 
        !          1003: {
        !          1004:     DebugPrint((3,"TapeSetDriveParameters: Enter routine\n"));
        !          1005:     DebugPrint((1,"TapeSetDriveParameters: operation not supported\n"));
        !          1006:     return STATUS_NOT_IMPLEMENTED;
        !          1007: 
        !          1008: } // end TapeSetDriveParameters()
        !          1009: 
        !          1010: 
        !          1011: NTSTATUS
        !          1012: TapeSetMediaParameters(
        !          1013:     IN PDEVICE_OBJECT DeviceObject,
        !          1014:     IN PIRP Irp
        !          1015:     )
        !          1016: 
        !          1017: /*++
        !          1018: Routine Description:
        !          1019: 
        !          1020:     This routine "sets" the "media parameters" of the Exabyte 8200 tape
        !          1021:     drive associated with "DeviceObject". Tape media must be present
        !          1022:     (loaded) in the drive for this function to return "no error".
        !          1023: 
        !          1024: Arguments:
        !          1025: 
        !          1026:     DeviceObject
        !          1027:     Irp
        !          1028: 
        !          1029: Return Value:
        !          1030: 
        !          1031:     NTSTATUS
        !          1032: 
        !          1033: --*/
        !          1034: 
        !          1035: {
        !          1036:     PDEVICE_EXTENSION          deviceExtension = DeviceObject->DeviceExtension;
        !          1037:     PTAPE_SET_MEDIA_PARAMETERS tapeSetMediaParams = Irp->AssociatedIrp.SystemBuffer;
        !          1038:     PMODE_PARM_READ_WRITE_DATA modeBuffer;
        !          1039:     SCSI_REQUEST_BLOCK         srb;
        !          1040:     PCDB                       cdb = (PCDB)srb.Cdb;
        !          1041:     NTSTATUS                   status;
        !          1042: 
        !          1043:     DebugPrint((3,"TapeSetMediaParameters: Enter routine\n"));
        !          1044: 
        !          1045:     //
        !          1046:     // Zero CDB in SRB on stack.
        !          1047:     //
        !          1048: 
        !          1049:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1050: 
        !          1051:     //
        !          1052:     // Prepare SCSI command (CDB)
        !          1053:     //
        !          1054: 
        !          1055:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1056: 
        !          1057:     cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY;
        !          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,"TapeSetMediaParameters: SendSrb (test unit ready)\n"));
        !          1070: 
        !          1071:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          1072:                                          &srb,
        !          1073:                                          NULL,
        !          1074:                                          0,
        !          1075:                                          FALSE);
        !          1076: 
        !          1077:     if (!NT_SUCCESS(status)) {
        !          1078:         DebugPrint((1,"TapeSetMediaParameters: test unit ready, SendSrb unsuccessful\n"));
        !          1079:         return status;
        !          1080:     }
        !          1081: 
        !          1082:     modeBuffer = ExAllocatePool(NonPagedPoolCacheAligned,
        !          1083:                                 sizeof(MODE_PARM_READ_WRITE_DATA));
        !          1084: 
        !          1085:     if (!modeBuffer) {
        !          1086:         DebugPrint((1,"TapeSetMediaParameters: insufficient resources (modeBuffer)\n"));
        !          1087:         return STATUS_INSUFFICIENT_RESOURCES;
        !          1088:     }
        !          1089: 
        !          1090:     RtlZeroMemory(modeBuffer, sizeof(MODE_PARM_READ_WRITE_DATA));
        !          1091: 
        !          1092:     modeBuffer->ParameterListHeader.ModeDataLength = 0;
        !          1093:     modeBuffer->ParameterListHeader.MediumType = 0;
        !          1094:     modeBuffer->ParameterListHeader.DeviceSpecificParameter = 0x10;
        !          1095:     modeBuffer->ParameterListHeader.BlockDescriptorLength =
        !          1096:         MODE_BLOCK_DESC_LENGTH;
        !          1097: 
        !          1098:     modeBuffer->ParameterListBlock.DensityCode = 0;
        !          1099:     modeBuffer->ParameterListBlock.BlockLength[0] =
        !          1100:         ((tapeSetMediaParams->BlockSize >> 16) & 0xFF);
        !          1101:     modeBuffer->ParameterListBlock.BlockLength[1] =
        !          1102:         ((tapeSetMediaParams->BlockSize >> 8) & 0xFF);
        !          1103:     modeBuffer->ParameterListBlock.BlockLength[2] =
        !          1104:         (tapeSetMediaParams->BlockSize & 0xFF);
        !          1105: 
        !          1106:     //
        !          1107:     // Zero CDB in SRB on stack.
        !          1108:     //
        !          1109: 
        !          1110:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1111: 
        !          1112:     //
        !          1113:     // Prepare SCSI command (CDB)
        !          1114:     //
        !          1115: 
        !          1116:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1117: 
        !          1118:     cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT;
        !          1119:     cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_PARM_READ_WRITE_DATA);
        !          1120: 
        !          1121:     //
        !          1122:     // Set timeout value.
        !          1123:     //
        !          1124: 
        !          1125:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !          1126: 
        !          1127:     //
        !          1128:     // Send SCSI command (CDB) to device
        !          1129:     //
        !          1130: 
        !          1131:     DebugPrint((3,"TapeSetMediaParameters: SendSrb (mode select)\n"));
        !          1132: 
        !          1133:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          1134:                                          &srb,
        !          1135:                                          modeBuffer,
        !          1136:                                          sizeof(MODE_PARM_READ_WRITE_DATA),
        !          1137:                                          TRUE);
        !          1138: 
        !          1139:     ExFreePool(modeBuffer);
        !          1140: 
        !          1141:     if (!NT_SUCCESS(status)) {
        !          1142:         DebugPrint((1,"TapeSetMediaParameters: mode select, SendSrb unsuccessful\n"));
        !          1143:     }
        !          1144: 
        !          1145:     return status;
        !          1146: 
        !          1147: } // end TapeSetMediaParameters()
        !          1148: 
        !          1149: 
        !          1150: NTSTATUS
        !          1151: TapeSetPosition(
        !          1152:     IN PDEVICE_OBJECT DeviceObject,
        !          1153:     IN PIRP Irp
        !          1154:     )
        !          1155: 
        !          1156: /*++
        !          1157: Routine Description:
        !          1158: 
        !          1159:     This routine sets the position of the tape.
        !          1160: 
        !          1161: Arguments:
        !          1162: 
        !          1163:     DeviceObject
        !          1164:     Irp
        !          1165: 
        !          1166: Return Value:
        !          1167: 
        !          1168:     NTSTATUS
        !          1169: 
        !          1170: --*/
        !          1171: 
        !          1172: {
        !          1173:     PDEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
        !          1174:     PTAPE_SET_POSITION tapeSetPosition = Irp->AssociatedIrp.SystemBuffer;
        !          1175:     ULONG              tapePositionVector;
        !          1176:     ULONG              method;
        !          1177:     SCSI_REQUEST_BLOCK srb;
        !          1178:     PCDB               cdb = (PCDB)srb.Cdb;
        !          1179:     NTSTATUS           status;
        !          1180: 
        !          1181: 
        !          1182:     DebugPrint((3,"TapeSetPosition: Enter routine\n"));
        !          1183: 
        !          1184:     if (tapeSetPosition->Immediate) {
        !          1185:         switch (tapeSetPosition->Method) {
        !          1186:             case TAPE_REWIND:
        !          1187:                 DebugPrint((3,"TapeSetPosition: immediate\n"));
        !          1188:                 break;
        !          1189: 
        !          1190:             case TAPE_ABSOLUTE_BLOCK:
        !          1191:             case TAPE_LOGICAL_BLOCK:
        !          1192:             case TAPE_SPACE_END_OF_DATA:
        !          1193:             case TAPE_SPACE_RELATIVE_BLOCKS:
        !          1194:             case TAPE_SPACE_FILEMARKS:
        !          1195:             case TAPE_SPACE_SEQUENTIAL_FMKS:
        !          1196:             case TAPE_SPACE_SETMARKS:
        !          1197:             case TAPE_SPACE_SEQUENTIAL_SMKS:
        !          1198:             default:
        !          1199:                 DebugPrint((1,"TapeSetPosition: PositionMethod, immediate -- operation not supported\n"));
        !          1200:                 return STATUS_NOT_IMPLEMENTED;
        !          1201:         }
        !          1202:     }
        !          1203: 
        !          1204:     method = tapeSetPosition->Method;
        !          1205:     tapePositionVector = tapeSetPosition->Offset.LowPart;
        !          1206: 
        !          1207:     //
        !          1208:     // Zero CDB in SRB on stack.
        !          1209:     //
        !          1210: 
        !          1211:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1212: 
        !          1213:     //
        !          1214:     // Prepare SCSI command (CDB)
        !          1215:     //
        !          1216: 
        !          1217:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1218: 
        !          1219:     cdb->CDB6GENERIC.Immediate = tapeSetPosition->Immediate;
        !          1220: 
        !          1221:     switch (method) {
        !          1222:         case TAPE_REWIND:
        !          1223:             DebugPrint((3,"TapeSetPosition: method == rewind\n"));
        !          1224:             cdb->CDB6GENERIC.OperationCode = SCSIOP_REWIND;
        !          1225:             srb.TimeOutValue = 150;
        !          1226:             break;
        !          1227: 
        !          1228:         case TAPE_SPACE_RELATIVE_BLOCKS:
        !          1229:             DebugPrint((3,"TapeSetPosition: method == space blocks\n"));
        !          1230:             cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
        !          1231:             cdb->SPACE_TAPE_MARKS.Code = 0;
        !          1232:             cdb->SPACE_TAPE_MARKS.NumMarksMSB =
        !          1233:                 ((tapePositionVector >> 16) & 0xFF);
        !          1234:             cdb->SPACE_TAPE_MARKS.NumMarks =
        !          1235:                 ((tapePositionVector >> 8) & 0xFF);
        !          1236:             cdb->SPACE_TAPE_MARKS.NumMarksLSB =
        !          1237:                 (tapePositionVector & 0xFF);
        !          1238:             srb.TimeOutValue = 4100;
        !          1239:             break;
        !          1240: 
        !          1241:         case TAPE_SPACE_FILEMARKS:
        !          1242:             DebugPrint((3,"TapeSetPosition: method == space filemarks\n"));
        !          1243:             cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE;
        !          1244:             cdb->SPACE_TAPE_MARKS.Code = 1;
        !          1245:             cdb->SPACE_TAPE_MARKS.NumMarksMSB =
        !          1246:                 ((tapePositionVector >> 16) & 0xFF);
        !          1247:             cdb->SPACE_TAPE_MARKS.NumMarks =
        !          1248:                 ((tapePositionVector >> 8) & 0xFF);
        !          1249:             cdb->SPACE_TAPE_MARKS.NumMarksLSB =
        !          1250:                 (tapePositionVector & 0xFF);
        !          1251:             srb.TimeOutValue = 4100;
        !          1252:             break;
        !          1253: 
        !          1254:         case TAPE_ABSOLUTE_BLOCK:
        !          1255:         case TAPE_LOGICAL_BLOCK:
        !          1256:         case TAPE_SPACE_END_OF_DATA:
        !          1257:         case TAPE_SPACE_SEQUENTIAL_FMKS:
        !          1258:         case TAPE_SPACE_SETMARKS:
        !          1259:         case TAPE_SPACE_SEQUENTIAL_SMKS:
        !          1260:         default:
        !          1261:             DebugPrint((1,"TapeSetPosition: PositionMethod -- operation not supported\n"));
        !          1262:             return STATUS_NOT_IMPLEMENTED;
        !          1263:     }
        !          1264: 
        !          1265:     //
        !          1266:     // Send SCSI command (CDB) to device
        !          1267:     //
        !          1268: 
        !          1269:     DebugPrint((3,"TapeSetPosition: SendSrb (method)\n"));
        !          1270: 
        !          1271:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          1272:                                          &srb,
        !          1273:                                          NULL,
        !          1274:                                          0,
        !          1275:                                          FALSE);
        !          1276: 
        !          1277:     if (!NT_SUCCESS(status)) {
        !          1278:         DebugPrint((1,"TapeSetPosition: method, SendSrb unsuccessful\n"));
        !          1279:     }
        !          1280: 
        !          1281:     return status;
        !          1282: 
        !          1283: } // end TapeSetPosition()
        !          1284: 
        !          1285: 
        !          1286: BOOLEAN
        !          1287: TapeVerifyInquiry(
        !          1288:     IN PSCSI_INQUIRY_DATA LunInfo
        !          1289:     )
        !          1290: 
        !          1291: /*++
        !          1292: Routine Description:
        !          1293: 
        !          1294:     This routine determines if this driver should claim this drive.
        !          1295: 
        !          1296: Arguments:
        !          1297: 
        !          1298:     LunInfo
        !          1299: 
        !          1300: Return Value:
        !          1301: 
        !          1302:     TRUE  - driver should claim this drive.
        !          1303:     FALSE - driver should not claim this drive.
        !          1304: 
        !          1305: --*/
        !          1306: 
        !          1307: {
        !          1308:     PINQUIRYDATA inquiryData;
        !          1309: 
        !          1310:     DebugPrint((3,"TapeVerifyInquiry: Enter routine\n"));
        !          1311: 
        !          1312:     inquiryData = (PVOID)LunInfo->InquiryData;
        !          1313: 
        !          1314:     //
        !          1315:     //  Determine, from the Product ID field in the
        !          1316:     //  inquiry data, whether or not to "claim" this drive.
        !          1317:     //
        !          1318: 
        !          1319:     return WhichIsIt(inquiryData)? TRUE : FALSE;
        !          1320: 
        !          1321: } // end TapeVerifyInquiry()
        !          1322: 
        !          1323: 
        !          1324: NTSTATUS
        !          1325: TapeWriteMarks(
        !          1326:     IN PDEVICE_OBJECT DeviceObject,
        !          1327:     IN PIRP Irp
        !          1328:     )
        !          1329: 
        !          1330: /*++
        !          1331: Routine Description:
        !          1332: 
        !          1333:     This routine writes tapemarks on the tape.
        !          1334: 
        !          1335: Arguments:
        !          1336: 
        !          1337:     DeviceObject
        !          1338:     Irp
        !          1339: 
        !          1340: Return Value:
        !          1341: 
        !          1342:     NTSTATUS
        !          1343: 
        !          1344: --*/
        !          1345: 
        !          1346: {
        !          1347:     PDEVICE_EXTENSION  deviceExtension = DeviceObject->DeviceExtension;
        !          1348:     PTAPE_WRITE_MARKS  tapeWriteMarks = Irp->AssociatedIrp.SystemBuffer;
        !          1349:     SCSI_REQUEST_BLOCK srb;
        !          1350:     PCDB               cdb = (PCDB)srb.Cdb;
        !          1351:     NTSTATUS           status;
        !          1352: 
        !          1353:     DebugPrint((3,"TapeWriteMarks: Enter routine\n"));
        !          1354: 
        !          1355:     if (tapeWriteMarks->Immediate) {
        !          1356:         DebugPrint((1,"TapeWriteMarks: TapemarkType, immediate -- operation not supported\n"));
        !          1357:         return STATUS_NOT_IMPLEMENTED;
        !          1358:     }
        !          1359: 
        !          1360:     //
        !          1361:     // Zero CDB in SRB on stack.
        !          1362:     //
        !          1363: 
        !          1364:     RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE);
        !          1365: 
        !          1366:     //
        !          1367:     // Prepare SCSI command (CDB)
        !          1368:     //
        !          1369: 
        !          1370:     srb.CdbLength = CDB6GENERIC_LENGTH;
        !          1371: 
        !          1372:     cdb->WRITE_TAPE_MARKS.OperationCode = SCSIOP_WRITE_FILEMARKS;
        !          1373: 
        !          1374:     switch (tapeWriteMarks->Type) {
        !          1375:         case TAPE_SHORT_FILEMARKS:
        !          1376:             DebugPrint((3,"TapeWriteMarks: TapemarkType == short filemarks\n"));
        !          1377:             cdb->WRITE_TAPE_MARKS.Control = 0x80;
        !          1378:             break;
        !          1379: 
        !          1380:         case TAPE_LONG_FILEMARKS:
        !          1381:             DebugPrint((3,"TapeWriteMarks: TapemarkType == long filemarks\n"));
        !          1382:             break;
        !          1383: 
        !          1384:         case TAPE_SETMARKS:
        !          1385:         case TAPE_FILEMARKS:
        !          1386:         default:
        !          1387:             DebugPrint((1,"TapeWriteMarks: TapemarkType -- operation not supported\n"));
        !          1388:             return STATUS_NOT_IMPLEMENTED;
        !          1389:     }
        !          1390: 
        !          1391:     cdb->WRITE_TAPE_MARKS.TransferLength[0] =
        !          1392:         ((tapeWriteMarks->Count >> 16) & 0xFF);
        !          1393:     cdb->WRITE_TAPE_MARKS.TransferLength[1] =
        !          1394:         ((tapeWriteMarks->Count >> 8) & 0xFF);
        !          1395:     cdb->WRITE_TAPE_MARKS.TransferLength[2] =
        !          1396:         (tapeWriteMarks->Count & 0xFF);
        !          1397: 
        !          1398:     //
        !          1399:     // Set timeout value.
        !          1400:     //
        !          1401: 
        !          1402:     srb.TimeOutValue = deviceExtension->TimeOutValue;
        !          1403: 
        !          1404:     //
        !          1405:     // Send SCSI command (CDB) to device
        !          1406:     //
        !          1407: 
        !          1408:     DebugPrint((3,"TapeWriteMarks: SendSrb (TapemarkType)\n"));
        !          1409: 
        !          1410:     status = ScsiClassSendSrbSynchronous(DeviceObject,
        !          1411:                                          &srb,
        !          1412:                                          NULL,
        !          1413:                                          0,
        !          1414:                                          FALSE);
        !          1415: 
        !          1416:     if (!NT_SUCCESS(status)) {
        !          1417:         DebugPrint((1,"TapeWriteMarks: TapemarkType, SendSrb unsuccessful\n"));
        !          1418:     }
        !          1419: 
        !          1420:     return status;
        !          1421: 
        !          1422: } // end TapeWriteMarks()
        !          1423: 
        !          1424: 
        !          1425: static
        !          1426: ULONG
        !          1427: WhichIsIt(
        !          1428:     IN PINQUIRYDATA InquiryData
        !          1429:     )
        !          1430: 
        !          1431: /*++
        !          1432: Routine Description:
        !          1433: 
        !          1434:     This routine determines a drive's identity from the Product ID field
        !          1435:     in its inquiry data.
        !          1436: 
        !          1437: Arguments:
        !          1438: 
        !          1439:     InquiryData (from an Inquiry command)
        !          1440: 
        !          1441: Return Value:
        !          1442: 
        !          1443:     driveID
        !          1444: 
        !          1445: --*/
        !          1446: 
        !          1447: {
        !          1448:     if (RtlCompareMemory(InquiryData->VendorId,"EXABYTE ",8) == 8) {
        !          1449: 
        !          1450:         if (RtlCompareMemory(InquiryData->ProductId,"EXB-8200",8) == 8) {
        !          1451:             return EXABYTE_8200;
        !          1452:         }
        !          1453: 
        !          1454:         if (RtlCompareMemory(InquiryData->ProductId,"EXB8200C",8) == 8) {
        !          1455:             return EXABYTE_8200;
        !          1456:         }
        !          1457: 
        !          1458:         if (RtlCompareMemory(InquiryData->ProductId,"8200SX",6) == 6) {
        !          1459:             return EXABYTE_8200SX;
        !          1460:         }
        !          1461: 
        !          1462:         if (RtlCompareMemory(InquiryData->ProductId,"EXB-8205",8) == 8) {
        !          1463:             return EXABYTE_8205;
        !          1464:         }
        !          1465: 
        !          1466:     }
        !          1467:     return 0;
        !          1468: }

unix.superglobalmegacorp.com

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