|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.