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

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

unix.superglobalmegacorp.com

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