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

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

unix.superglobalmegacorp.com

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