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