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