|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1992 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: 4mmdat.c ! 8: ! 9: Abstract: ! 10: ! 11: This module contains the device-specific routines for the Archive ! 12: Python DDS, DDS-DC, and Turbo-Speed DDS-DC DAT tape drives, the ! 13: HP 35470A DDS and 35480A DDS-DC DAT tape drives, the WangDAT ! 14: Model 3200 DDS-DC DAT tape drive, and the Compaq DDS-DC DAT tape ! 15: drive. ! 16: ! 17: Author: ! 18: ! 19: Mike Glass ! 20: Hunter Small (Maynard) ! 21: Lori Brown (Maynard) ! 22: Chris Hugh Sam (Maynard) ! 23: ! 24: Environment: ! 25: ! 26: kernel mode only ! 27: ! 28: Revision History: ! 29: ! 30: --*/ ! 31: ! 32: #include "ntddk.h" ! 33: #include "tape.h" ! 34: #include "4mmdat.h" ! 35: ! 36: static ULONG gb_PartitionCount; ! 37: static UCHAR gb_VendorId[8]; ! 38: static UCHAR gb_ProductId[16]; ! 39: ! 40: // ! 41: // Internal (module wide) defines that symbolize ! 42: // the 4mm DAT drives supported by this module. ! 43: // ! 44: #define ARCHIVE_PYTHON 1 ; ! 45: #define DEC_TLZ06 2 ; ! 46: #define EXABYTE_4200 3 ; ! 47: #define EXABYTE_4200C 4 ; ! 48: #define HP_35470A 5 ; ! 49: #define HP_35480A 6 ; ! 50: #define HP_IBM35480A 7 ; ! 51: #define WANGDAT_1300 8 ; ! 52: #define WANGDAT_3100 9 ; ! 53: #define WANGDAT_3200 10 ; ! 54: ! 55: // ! 56: // Function prototype(s) for internal function(s) ! 57: // ! 58: static ULONG WhichIsIt(IN PINQUIRYDATA InquiryData); ! 59: ! 60: ! 61: NTSTATUS ! 62: TapeCreatePartition( ! 63: IN PDEVICE_OBJECT DeviceObject, ! 64: IN PIRP Irp ! 65: ) ! 66: ! 67: /*++ ! 68: Routine Description: ! 69: ! 70: This routine creates initiator-defined partitions on the tape. ! 71: ! 72: Arguments: ! 73: ! 74: DeviceObject ! 75: Irp ! 76: ! 77: Return Value: ! 78: ! 79: NTSTATUS ! 80: ! 81: --*/ ! 82: ! 83: { ! 84: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 85: PTAPE_CREATE_PARTITION tapePartition = Irp->AssociatedIrp.SystemBuffer; ! 86: PMODE_MEDIUM_PART_PAGE buffer; ! 87: SCSI_REQUEST_BLOCK srb; ! 88: PCDB cdb = (PCDB)srb.Cdb; ! 89: NTSTATUS status; ! 90: ! 91: // ! 92: // Zero CDB in SRB on stack. ! 93: // ! 94: ! 95: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 96: ! 97: srb.CdbLength = CDB6GENERIC_LENGTH; ! 98: ! 99: cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT; ! 100: ! 101: // ! 102: // Set timeout value. ! 103: // ! 104: ! 105: srb.TimeOutValue = 8000; ! 106: ! 107: cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_MEDIUM_PART_PAGE); ! 108: cdb->MODE_SELECT.PFBit = 1; ! 109: ! 110: buffer = ExAllocatePool(NonPagedPoolCacheAligned, ! 111: sizeof(MODE_MEDIUM_PART_PAGE)); ! 112: ! 113: if (!buffer) { ! 114: return STATUS_INSUFFICIENT_RESOURCES; ! 115: } ! 116: ! 117: RtlZeroMemory(buffer, sizeof(MODE_MEDIUM_PART_PAGE)); ! 118: ! 119: buffer->ParameterListHeader.DeviceSpecificParameter = 0x10; ! 120: ! 121: buffer->MediumPartPage.PageCode = MODE_PAGE_MEDIUM_PARTITION; ! 122: ! 123: if (tapePartition->Count != 1 && tapePartition->Count != 2) { ! 124: DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n")); ! 125: ExFreePool(buffer); ! 126: return STATUS_INVALID_DEVICE_REQUEST; ! 127: } ! 128: ! 129: buffer->MediumPartPage.AdditionalPartitionDefined = tapePartition->Count - 1; ! 130: ! 131: switch (tapePartition->Method) { ! 132: case TAPE_FIXED_PARTITIONS: ! 133: if (RtlCompareMemory(gb_VendorId,"WangDAT ",8) == 8) { ! 134: DebugPrint((3,"TapeIoControl: Create Fixed Tape Partitions\n")); ! 135: buffer->MediumPartPage.FDPBit = SETBITON; ! 136: buffer->MediumPartPage.PageLength = 0x0A; ! 137: } else { ! 138: DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n")); ! 139: ExFreePool(buffer); ! 140: return STATUS_INVALID_DEVICE_REQUEST; ! 141: } ! 142: break; ! 143: ! 144: case TAPE_SELECT_PARTITIONS: ! 145: if (RtlCompareMemory(gb_VendorId,"WangDAT ",8) == 8) { ! 146: DebugPrint((3,"TapeIoControl: Create Select Tape Partitions\n")); ! 147: buffer->MediumPartPage.SDPBit = SETBITON; ! 148: buffer->MediumPartPage.PageLength = 0x0A; ! 149: } else { ! 150: DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n")); ! 151: ExFreePool(buffer); ! 152: return STATUS_INVALID_DEVICE_REQUEST; ! 153: } ! 154: break; ! 155: ! 156: case TAPE_INITIATOR_PARTITIONS: ! 157: DebugPrint((3,"TapeIoControl: Create Initiator Defined Tape Partitions\n")); ! 158: buffer->MediumPartPage.IDPBit = SETBITON; ! 159: ! 160: if (buffer->MediumPartPage.AdditionalPartitionDefined) { ! 161: if (RtlCompareMemory(gb_VendorId,"WangDAT ",8) == 8) { ! 162: buffer->MediumPartPage.PageLength = 0x0A; ! 163: ! 164: buffer->MediumPartPage.Partition1Size[0] = ! 165: ((tapePartition->Size >> 8) & 0xFF); ! 166: buffer->MediumPartPage.Partition1Size[1] = ! 167: (tapePartition->Size & 0xFF); ! 168: ! 169: buffer->MediumPartPage.PSUMBit = 2; ! 170: } else { ! 171: buffer->MediumPartPage.PageLength = 0x08; ! 172: cdb->MODE_SELECT.ParameterListLength -= 2; ! 173: ! 174: buffer->MediumPartPage.Partition0Size[0] = ! 175: ((tapePartition->Size >> 8) & 0xFF); ! 176: buffer->MediumPartPage.Partition0Size[1] = ! 177: (tapePartition->Size & 0xFF); ! 178: ! 179: buffer->MediumPartPage.PSUMBit = 2; ! 180: } ! 181: } else { ! 182: if (RtlCompareMemory(gb_VendorId,"WangDAT ",8) == 8) { ! 183: buffer->MediumPartPage.PageLength = 0x0A; ! 184: } else { ! 185: buffer->MediumPartPage.PageLength = 0x06; ! 186: cdb->MODE_SELECT.ParameterListLength -= 4; ! 187: } ! 188: } ! 189: ! 190: break; ! 191: ! 192: default: ! 193: DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n")); ! 194: ExFreePool(buffer); ! 195: return STATUS_INVALID_DEVICE_REQUEST; ! 196: } ! 197: ! 198: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 199: &srb, ! 200: buffer, ! 201: cdb->MODE_SELECT.ParameterListLength, ! 202: TRUE); ! 203: ! 204: ExFreePool(buffer); ! 205: ! 206: return status; ! 207: ! 208: } // end TapeCreatePartition() ! 209: ! 210: ! 211: NTSTATUS ! 212: TapeErase( ! 213: IN PDEVICE_OBJECT DeviceObject, ! 214: IN PIRP Irp ! 215: ) ! 216: ! 217: /*++ ! 218: Routine Description: ! 219: ! 220: This routine erases the current partition of the device by writing an ! 221: end-of-recorded data marker beginning at the current position. ! 222: ! 223: Arguments: ! 224: ! 225: DeviceObject ! 226: Irp ! 227: ! 228: Return Value: ! 229: ! 230: NTSTATUS ! 231: ! 232: --*/ ! 233: ! 234: { ! 235: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 236: PTAPE_ERASE tapeErase = Irp->AssociatedIrp.SystemBuffer; ! 237: SCSI_REQUEST_BLOCK srb; ! 238: PCDB cdb = (PCDB)srb.Cdb; ! 239: NTSTATUS status; ! 240: ! 241: // ! 242: // Zero CDB in SRB on stack. ! 243: // ! 244: ! 245: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 246: ! 247: srb.CdbLength = CDB6GENERIC_LENGTH; ! 248: ! 249: cdb->ERASE.OperationCode = SCSIOP_ERASE; ! 250: ! 251: // ! 252: // Set timeout value. ! 253: // ! 254: ! 255: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 256: ! 257: if (tapeErase->Type != TAPE_ERASE_SHORT) { ! 258: DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n")); ! 259: return STATUS_INVALID_DEVICE_REQUEST; ! 260: } ! 261: ! 262: DebugPrint((3,"TapeIoControl: Short Erase Tape\n")); ! 263: ! 264: // ! 265: // Set immediate bit if indicated. ! 266: // ! 267: ! 268: cdb->ERASE.Immediate = tapeErase->Immediate; ! 269: ! 270: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 271: &srb, ! 272: NULL, ! 273: 0, ! 274: FALSE); ! 275: ! 276: return status; ! 277: ! 278: } // end TapeErase() ! 279: ! 280: ! 281: ! 282: VOID ! 283: TapeError( ! 284: PDEVICE_OBJECT DeviceObject, ! 285: PSCSI_REQUEST_BLOCK Srb, ! 286: NTSTATUS *Status, ! 287: BOOLEAN *Retry ! 288: ) ! 289: ! 290: /*++ ! 291: ! 292: Routine Description: ! 293: ! 294: When a request completes with error, the routine InterpretSenseInfo is ! 295: called to determine from the sense data whether the request should be ! 296: retried and what NT status to set in the IRP. Then this routine is called ! 297: for tape requests to handle tape-specific errors and update the nt status ! 298: and retry boolean. ! 299: ! 300: Arguments: ! 301: ! 302: DeviceObject - Supplies a pointer to the device object. ! 303: ! 304: Srb - Supplies a pointer to the failing Srb. ! 305: ! 306: Status - NT Status used to set the IRP's completion status. ! 307: ! 308: Retry - Indicates that this request should be retried. ! 309: ! 310: Return Value: ! 311: ! 312: None. ! 313: ! 314: --*/ ! 315: ! 316: { ! 317: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 318: PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer; ! 319: NTSTATUS status = *Status; ! 320: BOOLEAN retry = *Retry; ! 321: UCHAR adsenseq = senseBuffer->AdditionalSenseCodeQualifier; ! 322: UCHAR adsense = senseBuffer->AdditionalSenseCode; ! 323: ! 324: if (status == STATUS_DEVICE_NOT_READY) { ! 325: if ((adsense == SCSI_ADSENSE_LUN_NOT_READY) && ! 326: (adsenseq == SCSI_SENSEQ_BECOMING_READY) ) { ! 327: ! 328: *Status = STATUS_NO_MEDIA; ! 329: *Retry = FALSE; ! 330: ! 331: } ! 332: } ! 333: return; ! 334: ! 335: } // end TapeError() ! 336: ! 337: ! 338: NTSTATUS ! 339: TapeGetDriveParameters( ! 340: IN PDEVICE_OBJECT DeviceObject, ! 341: IN PIRP Irp ! 342: ) ! 343: ! 344: /*++ ! 345: Routine Description: ! 346: ! 347: This routine returns an indication if reporting setmarks is disabled or ! 348: enabled, the default fixed-block size, the maximum block size, the ! 349: minimum block size, the maximum number of partitions, and the device ! 350: features flag. ! 351: ! 352: Arguments: ! 353: ! 354: DeviceObject ! 355: Irp ! 356: ! 357: Return Value: ! 358: ! 359: NTSTATUS ! 360: ! 361: --*/ ! 362: ! 363: { ! 364: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 365: PTAPE_GET_DRIVE_PARAMETERS tapeGetDriveParams = Irp->AssociatedIrp.SystemBuffer; ! 366: PMODE_DEVICE_CONFIG_PAGE buffer; ! 367: PREAD_BLOCK_LIMITS_DATA blockLimits; ! 368: SCSI_REQUEST_BLOCK srb; ! 369: PCDB cdb = (PCDB)srb.Cdb; ! 370: NTSTATUS status; ! 371: PMODE_DATA_COMPRESS_PAGE dcbuff; ! 372: ! 373: DebugPrint((3,"TapeIoControl: Get Tape Drive Parameters\n")); ! 374: ! 375: // ! 376: // Zero CDB in SRB on stack. ! 377: // ! 378: ! 379: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 380: ! 381: srb.CdbLength = CDB6GENERIC_LENGTH; ! 382: ! 383: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; ! 384: ! 385: // ! 386: // Set timeout value. ! 387: // ! 388: ! 389: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 390: ! 391: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DEVICE_CONFIG_PAGE); ! 392: cdb->MODE_SENSE.Dbd = SETBITON; ! 393: cdb->MODE_SENSE.PageCode = MODE_PAGE_DEVICE_CONFIG; ! 394: ! 395: buffer = ExAllocatePool(NonPagedPoolCacheAligned, ! 396: sizeof(MODE_DEVICE_CONFIG_PAGE)); ! 397: ! 398: if (!buffer) { ! 399: return STATUS_INSUFFICIENT_RESOURCES; ! 400: } ! 401: ! 402: RtlZeroMemory(buffer, sizeof(MODE_DEVICE_CONFIG_PAGE)); ! 403: ! 404: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 405: &srb, ! 406: buffer, ! 407: sizeof( MODE_DEVICE_CONFIG_PAGE ), ! 408: FALSE); ! 409: ! 410: if (NT_SUCCESS(status)) { ! 411: Irp->IoStatus.Information = sizeof(TAPE_GET_DRIVE_PARAMETERS); ! 412: ! 413: tapeGetDriveParams->ECC = 0; ! 414: tapeGetDriveParams->DataPadding = 0; ! 415: tapeGetDriveParams->Compression = 0; ! 416: tapeGetDriveParams->ReportSetmarks = (buffer->DeviceConfigPage.RSmk ? 1 : 0 ); ! 417: tapeGetDriveParams->DefaultBlockSize = 0x200; ! 418: tapeGetDriveParams->MaximumPartitionCount = 2; ! 419: ! 420: tapeGetDriveParams->FeaturesLow = ! 421: TAPE_DRIVE_INITIATOR | ! 422: TAPE_DRIVE_ERASE_SHORT | ! 423: TAPE_DRIVE_ERASE_BOP_ONLY | ! 424: TAPE_DRIVE_ERASE_IMMEDIATE | ! 425: TAPE_DRIVE_TAPE_CAPACITY | ! 426: TAPE_DRIVE_FIXED_BLOCK | ! 427: TAPE_DRIVE_VARIABLE_BLOCK | ! 428: TAPE_DRIVE_WRITE_PROTECT | ! 429: TAPE_DRIVE_REPORT_SMKS | ! 430: TAPE_DRIVE_GET_ABSOLUTE_BLK | ! 431: TAPE_DRIVE_GET_LOGICAL_BLK; ! 432: ! 433: tapeGetDriveParams->FeaturesHigh = ! 434: TAPE_DRIVE_LOAD_UNLOAD | ! 435: TAPE_DRIVE_LOCK_UNLOCK | ! 436: TAPE_DRIVE_REWIND_IMMEDIATE | ! 437: TAPE_DRIVE_SET_BLOCK_SIZE | ! 438: TAPE_DRIVE_LOAD_UNLD_IMMED | ! 439: TAPE_DRIVE_SET_REPORT_SMKS | ! 440: TAPE_DRIVE_ABSOLUTE_BLK | ! 441: TAPE_DRIVE_ABS_BLK_IMMED | ! 442: TAPE_DRIVE_LOGICAL_BLK | ! 443: TAPE_DRIVE_END_OF_DATA | ! 444: TAPE_DRIVE_RELATIVE_BLKS | ! 445: TAPE_DRIVE_FILEMARKS | ! 446: TAPE_DRIVE_SEQUENTIAL_FMKS | ! 447: TAPE_DRIVE_SETMARKS | ! 448: TAPE_DRIVE_REVERSE_POSITION | ! 449: TAPE_DRIVE_WRITE_SETMARKS | ! 450: TAPE_DRIVE_WRITE_FILEMARKS | ! 451: TAPE_DRIVE_WRITE_MARK_IMMED; ! 452: ! 453: if (RtlCompareMemory(gb_VendorId,"WangDAT ",8) == 8) { ! 454: tapeGetDriveParams->FeaturesLow |= ! 455: TAPE_DRIVE_FIXED | ! 456: TAPE_DRIVE_SELECT; ! 457: tapeGetDriveParams->FeaturesHigh |= ! 458: TAPE_DRIVE_LOG_BLK_IMMED | ! 459: TAPE_DRIVE_SEQUENTIAL_SMKS; ! 460: } else if (RtlCompareMemory(gb_VendorId,"HP ",8) == 8) { ! 461: tapeGetDriveParams->FeaturesHigh |= ! 462: TAPE_DRIVE_LOG_BLK_IMMED | ! 463: TAPE_DRIVE_SEQUENTIAL_SMKS; ! 464: } else { ! 465: tapeGetDriveParams->FeaturesLow |= ! 466: TAPE_DRIVE_TAPE_REMAINING; ! 467: } ! 468: ! 469: } ! 470: ! 471: ExFreePool(buffer); ! 472: ! 473: if (!NT_SUCCESS(status)) { ! 474: return status; ! 475: } ! 476: ! 477: // ! 478: // Zero CDB in SRB on stack. ! 479: // ! 480: ! 481: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 482: ! 483: srb.CdbLength = CDB6GENERIC_LENGTH; ! 484: ! 485: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; ! 486: ! 487: // ! 488: // Set timeout value. ! 489: // ! 490: ! 491: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 492: ! 493: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DATA_COMPRESS_PAGE); ! 494: cdb->MODE_SENSE.Dbd = SETBITON; ! 495: cdb->MODE_SENSE.PageCode = MODE_PAGE_DATA_COMPRESS; ! 496: ! 497: dcbuff = ExAllocatePool(NonPagedPoolCacheAligned, ! 498: sizeof(MODE_DATA_COMPRESS_PAGE)); ! 499: ! 500: if (!dcbuff) { ! 501: return STATUS_INSUFFICIENT_RESOURCES; ! 502: } ! 503: ! 504: RtlZeroMemory(dcbuff, sizeof(MODE_DATA_COMPRESS_PAGE)); ! 505: ! 506: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 507: &srb, ! 508: dcbuff, ! 509: sizeof( MODE_DATA_COMPRESS_PAGE ), ! 510: FALSE); ! 511: ! 512: if (NT_SUCCESS(status)) { ! 513: if (dcbuff->DataCompressPage.DCC == 1) { ! 514: tapeGetDriveParams->FeaturesLow |= TAPE_DRIVE_COMPRESSION; ! 515: tapeGetDriveParams->FeaturesHigh |= TAPE_DRIVE_SET_COMPRESSION; ! 516: tapeGetDriveParams->Compression = (dcbuff->DataCompressPage.DCE == 1 ? TRUE : FALSE); ! 517: } ! 518: } ! 519: ! 520: ExFreePool(dcbuff); ! 521: ! 522: if (!NT_SUCCESS(status) && (status != STATUS_INVALID_DEVICE_REQUEST)) { ! 523: return status; ! 524: } ! 525: ! 526: // ! 527: // Zero CDB in SRB on stack. ! 528: // ! 529: ! 530: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 531: ! 532: srb.CdbLength = CDB6GENERIC_LENGTH; ! 533: ! 534: cdb->CDB6GENERIC.OperationCode = SCSIOP_READ_BLOCK_LIMITS; ! 535: ! 536: // ! 537: // Set timeout value. ! 538: // ! 539: ! 540: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 541: ! 542: blockLimits = ExAllocatePool(NonPagedPoolCacheAligned, ! 543: sizeof(READ_BLOCK_LIMITS_DATA)); ! 544: ! 545: if (!blockLimits) { ! 546: return STATUS_INSUFFICIENT_RESOURCES; ! 547: } ! 548: ! 549: RtlZeroMemory(blockLimits, sizeof(READ_BLOCK_LIMITS_DATA)); ! 550: ! 551: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 552: &srb, ! 553: blockLimits, ! 554: sizeof(READ_BLOCK_LIMITS_DATA), ! 555: FALSE); ! 556: ! 557: if (NT_SUCCESS(status)) { ! 558: tapeGetDriveParams->MaximumBlockSize = blockLimits->BlockMaximumSize[2]; ! 559: tapeGetDriveParams->MaximumBlockSize += (blockLimits->BlockMaximumSize[1] << 8); ! 560: tapeGetDriveParams->MaximumBlockSize += (blockLimits->BlockMaximumSize[0] << 16); ! 561: ! 562: tapeGetDriveParams->MinimumBlockSize = blockLimits->BlockMinimumSize[1]; ! 563: tapeGetDriveParams->MinimumBlockSize += (blockLimits->BlockMinimumSize[0] << 8); ! 564: } ! 565: ! 566: ExFreePool(blockLimits); ! 567: ! 568: tapeGetDriveParams->FeaturesHigh &= ~TAPE_DRIVE_HIGH_FEATURES; ! 569: ! 570: return status; ! 571: ! 572: } // end TapeGetDriveParameters() ! 573: ! 574: ! 575: NTSTATUS ! 576: TapeGetMediaParameters( ! 577: IN PDEVICE_OBJECT DeviceObject, ! 578: IN PIRP Irp ! 579: ) ! 580: ! 581: /*++ ! 582: Routine Description: ! 583: ! 584: This routine returns the maximum tape capacity, the remaining tape ! 585: capacity, the fixed-length logical block size, the number of partitions ! 586: on the tape, and an indication if the tape is write protected. A block ! 587: size of 0 indicates variable-length block mode. ! 588: ! 589: Arguments: ! 590: ! 591: DeviceObject ! 592: Irp ! 593: ! 594: Return Value: ! 595: ! 596: NTSTATUS ! 597: ! 598: --*/ ! 599: ! 600: { ! 601: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 602: PTAPE_GET_MEDIA_PARAMETERS tapeGetMediaParams = Irp->AssociatedIrp.SystemBuffer; ! 603: PMODE_TAPE_MEDIA_INFORMATION modeBuffer; ! 604: PLOG_SENSE_PARAMETER_FORMAT logBuffer; ! 605: SCSI_REQUEST_BLOCK srb; ! 606: PCDB cdb = (PCDB)srb.Cdb; ! 607: NTSTATUS status; ! 608: LARGE_INTEGER capacityBuffer[2]; ! 609: LARGE_INTEGER remainingBuffer[2]; ! 610: ULONG sectorShift; ! 611: ! 612: DebugPrint((3,"TapeIoControl: Get Tape Media Parameters\n")); ! 613: ! 614: // ! 615: // Zero CDB in SRB on stack. ! 616: // ! 617: ! 618: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 619: ! 620: srb.CdbLength = CDB6GENERIC_LENGTH; ! 621: ! 622: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; ! 623: ! 624: // ! 625: // Set timeout value. ! 626: // ! 627: ! 628: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 629: ! 630: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_TAPE_MEDIA_INFORMATION); ! 631: cdb->MODE_SENSE.PageCode = MODE_PAGE_MEDIUM_PARTITION; ! 632: ! 633: modeBuffer = ExAllocatePool(NonPagedPoolCacheAligned, ! 634: sizeof(MODE_TAPE_MEDIA_INFORMATION)); ! 635: ! 636: if (!modeBuffer) { ! 637: return STATUS_INSUFFICIENT_RESOURCES; ! 638: } ! 639: ! 640: RtlZeroMemory(modeBuffer, sizeof(MODE_TAPE_MEDIA_INFORMATION)); ! 641: ! 642: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 643: &srb, ! 644: modeBuffer, ! 645: sizeof( MODE_TAPE_MEDIA_INFORMATION ), ! 646: FALSE); ! 647: ! 648: if (status == STATUS_DATA_OVERRUN) { ! 649: status = STATUS_SUCCESS; ! 650: } ! 651: ! 652: if (NT_SUCCESS(status)) { ! 653: Irp->IoStatus.Information = sizeof(TAPE_GET_MEDIA_PARAMETERS); ! 654: ! 655: tapeGetMediaParams->BlockSize = modeBuffer->ParameterListBlock.BlockLength[2]; ! 656: tapeGetMediaParams->BlockSize += (modeBuffer->ParameterListBlock.BlockLength[1] << 8); ! 657: tapeGetMediaParams->BlockSize += (modeBuffer->ParameterListBlock.BlockLength[0] << 16); ! 658: ! 659: tapeGetMediaParams->PartitionCount = ! 660: modeBuffer->MediumPartPage.AdditionalPartitionDefined + 1; ! 661: ! 662: tapeGetMediaParams->WriteProtected = ! 663: ((modeBuffer->ParameterListHeader.DeviceSpecificParameter >> 7) & ! 664: 0x01); ! 665: ! 666: gb_PartitionCount = ! 667: modeBuffer->MediumPartPage.AdditionalPartitionDefined + 1; ! 668: ! 669: if (RtlCompareMemory(gb_VendorId,"WangDAT ",8) == 8) { ! 670: capacityBuffer[0].LowPart = modeBuffer->MediumPartPage.Partition0Size[1]; ! 671: capacityBuffer[0].LowPart += (modeBuffer->MediumPartPage.Partition0Size[0] << 8); ! 672: ! 673: capacityBuffer[0].HighPart = 0; ! 674: ! 675: if (tapeGetMediaParams->PartitionCount == 2) { ! 676: capacityBuffer[1].LowPart = modeBuffer->MediumPartPage.Partition1Size[1]; ! 677: capacityBuffer[1].LowPart += (modeBuffer->MediumPartPage.Partition1Size[0] << 8); ! 678: ! 679: capacityBuffer[1].HighPart = 0; ! 680: } else { ! 681: capacityBuffer[1].LowPart = 0; ! 682: capacityBuffer[1].HighPart = 0; ! 683: } ! 684: ! 685: capacityBuffer[0] = ! 686: RtlLargeIntegerAdd( capacityBuffer[0], capacityBuffer[1]); ! 687: capacityBuffer[0] = ! 688: RtlExtendedIntegerMultiply(capacityBuffer[0], 1024000); ! 689: ! 690: tapeGetMediaParams->Capacity = capacityBuffer[0]; ! 691: ! 692: tapeGetMediaParams->Remaining.LowPart = 0; ! 693: tapeGetMediaParams->Remaining.HighPart = 0; ! 694: ! 695: WHICH_BIT(tapeGetMediaParams->BlockSize, sectorShift); ! 696: deviceExtension->DiskGeometry->BytesPerSector = tapeGetMediaParams->BlockSize; ! 697: deviceExtension->SectorShift = sectorShift; ! 698: ! 699: ! 700: } ! 701: } ! 702: ! 703: ExFreePool(modeBuffer); ! 704: ! 705: if (!NT_SUCCESS(status)) { ! 706: ! 707: return status; ! 708: } ! 709: ! 710: if (!(RtlCompareMemory(gb_VendorId,"WangDAT ",8) == 8)) { ! 711: // ! 712: // Zero CDB in SRB on stack. ! 713: // ! 714: ! 715: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 716: ! 717: srb.CdbLength = CDB10GENERIC_LENGTH; ! 718: ! 719: cdb->LOGSENSE.OperationCode = SCSIOP_LOG_SENSE; ! 720: ! 721: // ! 722: // Set timeout value. ! 723: // ! 724: ! 725: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 726: ! 727: cdb->LOGSENSE.AllocationLength[0] = 0; ! 728: cdb->LOGSENSE.AllocationLength[1] = 0x24; ! 729: ! 730: cdb->LOGSENSE.PageCode = LOGSENSEPAGE31; ! 731: cdb->LOGSENSE.PCBit = 0x01; ! 732: ! 733: logBuffer = ExAllocatePool(NonPagedPoolCacheAligned, ! 734: sizeof(LOG_SENSE_PARAMETER_FORMAT)); ! 735: ! 736: if (!logBuffer) { ! 737: return STATUS_INSUFFICIENT_RESOURCES; ! 738: } ! 739: ! 740: RtlZeroMemory(logBuffer, sizeof(LOG_SENSE_PARAMETER_FORMAT)); ! 741: ! 742: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 743: &srb, ! 744: logBuffer, ! 745: 0x24, ! 746: FALSE); ! 747: ! 748: if (status == STATUS_DATA_OVERRUN) { ! 749: status = STATUS_SUCCESS; ! 750: } ! 751: ! 752: if (NT_SUCCESS(status)) { ! 753: capacityBuffer[0].LowPart = logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart0[3]; ! 754: capacityBuffer[0].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart0[2] << 8); ! 755: capacityBuffer[0].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart0[1] << 16); ! 756: capacityBuffer[0].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart0[0] << 24); ! 757: ! 758: capacityBuffer[0].HighPart = 0; ! 759: ! 760: remainingBuffer[0].LowPart = logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart0[3]; ! 761: remainingBuffer[0].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart0[2] << 8); ! 762: remainingBuffer[0].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart0[1] << 16); ! 763: remainingBuffer[0].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart0[0] << 24); ! 764: ! 765: remainingBuffer[0].HighPart = 0; ! 766: ! 767: if (tapeGetMediaParams->PartitionCount == 2) { ! 768: capacityBuffer[1].LowPart = logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart1[3]; ! 769: capacityBuffer[1].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart1[2] << 8); ! 770: capacityBuffer[1].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart1[1] << 16); ! 771: capacityBuffer[1].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.MaximumCapacityPart1[0] << 24); ! 772: ! 773: capacityBuffer[1].HighPart = 0; ! 774: ! 775: remainingBuffer[1].LowPart = logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart1[3]; ! 776: remainingBuffer[1].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart1[2] << 8); ! 777: remainingBuffer[1].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart1[1] << 16); ! 778: remainingBuffer[1].LowPart += (logBuffer->LogSensePageInfo.LogSensePage.Page31.RemainingCapacityPart1[0] << 24); ! 779: ! 780: remainingBuffer[1].HighPart = 0; ! 781: ! 782: } else { ! 783: capacityBuffer[1].LowPart = 0; ! 784: capacityBuffer[1].HighPart = 0; ! 785: remainingBuffer[1].LowPart = 0; ! 786: remainingBuffer[1].HighPart = 0; ! 787: } ! 788: ! 789: capacityBuffer[0] = ! 790: RtlLargeIntegerAdd( capacityBuffer[0], capacityBuffer[1]); ! 791: capacityBuffer[0] = ! 792: RtlExtendedIntegerMultiply(capacityBuffer[0], 1024); ! 793: ! 794: tapeGetMediaParams->Capacity = capacityBuffer[0]; ! 795: ! 796: remainingBuffer[0] = ! 797: RtlLargeIntegerAdd( remainingBuffer[0], remainingBuffer[1]); ! 798: remainingBuffer[0] = ! 799: RtlExtendedIntegerMultiply(remainingBuffer[0], 1024); ! 800: ! 801: tapeGetMediaParams->Remaining = remainingBuffer[0]; ! 802: } ! 803: ! 804: ExFreePool(logBuffer); ! 805: } ! 806: ! 807: return status; ! 808: ! 809: } // end TapeGetMediaParameters() ! 810: ! 811: ! 812: NTSTATUS ! 813: TapeGetPosition( ! 814: IN PDEVICE_OBJECT DeviceObject, ! 815: IN PIRP Irp ! 816: ) ! 817: ! 818: /*++ ! 819: Routine Description: ! 820: ! 821: This routine returns the current position of the tape. ! 822: ! 823: Arguments: ! 824: ! 825: DeviceObject ! 826: Irp ! 827: ! 828: Return Value: ! 829: ! 830: NTSTATUS ! 831: ! 832: --*/ ! 833: ! 834: { ! 835: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 836: PTAPE_GET_POSITION tapeGetPosition = Irp->AssociatedIrp.SystemBuffer; ! 837: PTAPE_POSITION_DATA logicalBuffer; ! 838: PUCHAR absoluteBuffer; ! 839: SCSI_REQUEST_BLOCK srb; ! 840: PCDB cdb = (PCDB)srb.Cdb; ! 841: NTSTATUS status; ! 842: ! 843: // ! 844: // Zero CDB in SRB on stack. ! 845: // ! 846: ! 847: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 848: ! 849: // ! 850: // Set timeout value. ! 851: // ! 852: ! 853: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 854: ! 855: switch (tapeGetPosition->Type) { ! 856: case TAPE_ABSOLUTE_POSITION: ! 857: DebugPrint((3,"TapeIoControl: Get Absolute Position\n")); ! 858: srb.CdbLength = CDB6GENERIC_LENGTH; ! 859: cdb->CDB6GENERIC.OperationCode = SCSIOP_REQUEST_BLOCK_ADDR; ! 860: absoluteBuffer = ExAllocatePool(NonPagedPoolCacheAligned, 3); ! 861: ! 862: if (!absoluteBuffer) { ! 863: return STATUS_INSUFFICIENT_RESOURCES; ! 864: } ! 865: ! 866: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 867: &srb, ! 868: absoluteBuffer, ! 869: 3, ! 870: FALSE); ! 871: ! 872: if (NT_SUCCESS(status)) { ! 873: Irp->IoStatus.Information = sizeof(TAPE_GET_POSITION); ! 874: ! 875: tapeGetPosition->Partition = 0; ! 876: tapeGetPosition->Offset.HighPart = 0; ! 877: tapeGetPosition->Offset.LowPart = absoluteBuffer[2]; ! 878: tapeGetPosition->Offset.LowPart += (absoluteBuffer[1] << 8); ! 879: tapeGetPosition->Offset.LowPart += (absoluteBuffer[0] << 16); ! 880: } ! 881: ! 882: ExFreePool(absoluteBuffer); ! 883: break; ! 884: ! 885: case TAPE_LOGICAL_POSITION: ! 886: DebugPrint((3,"TapeIoControl: Get Logical Position\n")); ! 887: srb.CdbLength = CDB10GENERIC_LENGTH; ! 888: cdb->READ_POSITION.Operation = SCSIOP_READ_POSITION; ! 889: logicalBuffer = ExAllocatePool(NonPagedPoolCacheAligned, ! 890: sizeof(TAPE_POSITION_DATA)); ! 891: ! 892: if (!logicalBuffer) { ! 893: return STATUS_INSUFFICIENT_RESOURCES; ! 894: } ! 895: ! 896: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 897: &srb, ! 898: logicalBuffer, ! 899: sizeof( TAPE_POSITION_DATA ), ! 900: FALSE); ! 901: ! 902: if (NT_SUCCESS(status)) { ! 903: Irp->IoStatus.Information = sizeof(TAPE_GET_POSITION); ! 904: ! 905: if (logicalBuffer->BlockPositionUnsupported) { ! 906: DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n")); ! 907: return STATUS_INVALID_DEVICE_REQUEST; ! 908: } ! 909: ! 910: tapeGetPosition->Partition = logicalBuffer->PartitionNumber + 1; ! 911: tapeGetPosition->Offset.HighPart = 0; ! 912: REVERSE_BYTES((PFOUR_BYTE)&tapeGetPosition->Offset.LowPart, ! 913: (PFOUR_BYTE)logicalBuffer->FirstBlock); ! 914: } ! 915: ! 916: ExFreePool(logicalBuffer); ! 917: break; ! 918: ! 919: default: ! 920: DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n")); ! 921: return STATUS_INVALID_DEVICE_REQUEST; ! 922: } ! 923: ! 924: return status; ! 925: ! 926: } // end TapeGetPosition() ! 927: ! 928: ! 929: NTSTATUS ! 930: TapeGetStatus( ! 931: IN PDEVICE_OBJECT DeviceObject, ! 932: IN PIRP Irp ! 933: ) ! 934: ! 935: /*++ ! 936: Routine Description: ! 937: ! 938: This routine returns the status of the device. ! 939: ! 940: Arguments: ! 941: ! 942: DeviceObject ! 943: Irp ! 944: ! 945: Return Value: ! 946: ! 947: NTSTATUS ! 948: ! 949: --*/ ! 950: ! 951: { ! 952: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 953: SCSI_REQUEST_BLOCK srb; ! 954: PCDB cdb = (PCDB)srb.Cdb; ! 955: NTSTATUS status; ! 956: ! 957: DebugPrint((3,"TapeIoControl: Get Tape Status\n")); ! 958: ! 959: // ! 960: // Zero CDB in SRB on stack. ! 961: // ! 962: ! 963: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 964: ! 965: srb.CdbLength = CDB6GENERIC_LENGTH; ! 966: ! 967: cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY; ! 968: ! 969: // ! 970: // Set timeout value. ! 971: // ! 972: ! 973: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 974: ! 975: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 976: &srb, ! 977: NULL, ! 978: 0, ! 979: FALSE); ! 980: ! 981: return status; ! 982: ! 983: } // end TapeGetStatus() ! 984: ! 985: ! 986: NTSTATUS ! 987: TapePrepare( ! 988: IN PDEVICE_OBJECT DeviceObject, ! 989: IN PIRP Irp ! 990: ) ! 991: ! 992: /*++ ! 993: Routine Description: ! 994: ! 995: This routine loads, unloads, locks, or unlocks the tape. ! 996: ! 997: Arguments: ! 998: ! 999: DeviceObject ! 1000: Irp ! 1001: ! 1002: Return Value: ! 1003: ! 1004: NTSTATUS ! 1005: ! 1006: --*/ ! 1007: ! 1008: { ! 1009: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 1010: PTAPE_PREPARE tapePrepare = Irp->AssociatedIrp.SystemBuffer; ! 1011: SCSI_REQUEST_BLOCK srb; ! 1012: PCDB cdb = (PCDB)srb.Cdb; ! 1013: NTSTATUS status; ! 1014: ! 1015: // ! 1016: // Zero CDB in SRB on stack. ! 1017: // ! 1018: ! 1019: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 1020: ! 1021: // ! 1022: // Set timeout value. ! 1023: // ! 1024: ! 1025: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 1026: ! 1027: switch (tapePrepare->Operation) { ! 1028: case TAPE_LOAD: ! 1029: DebugPrint((3,"TapeIoControl: Load Tape\n")); ! 1030: srb.CdbLength = CDB6GENERIC_LENGTH; ! 1031: cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD; ! 1032: cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x01; ! 1033: break; ! 1034: ! 1035: case TAPE_UNLOAD: ! 1036: DebugPrint((3,"TapeIoControl: Unload Tape\n")); ! 1037: srb.CdbLength = CDB6GENERIC_LENGTH; ! 1038: cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD; ! 1039: break; ! 1040: ! 1041: case TAPE_LOCK: ! 1042: DebugPrint((3,"TapeIoControl: Prevent Tape Removal\n")); ! 1043: srb.CdbLength = CDB6GENERIC_LENGTH; ! 1044: cdb->CDB6GENERIC.OperationCode = SCSIOP_MEDIUM_REMOVAL; ! 1045: cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x01; ! 1046: break; ! 1047: ! 1048: case TAPE_UNLOCK: ! 1049: DebugPrint((3,"TapeIoControl: Allow Tape Removal\n")); ! 1050: srb.CdbLength = CDB6GENERIC_LENGTH; ! 1051: cdb->CDB6GENERIC.OperationCode = SCSIOP_MEDIUM_REMOVAL; ! 1052: break; ! 1053: ! 1054: default: ! 1055: DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n")); ! 1056: return STATUS_INVALID_DEVICE_REQUEST; ! 1057: } ! 1058: ! 1059: // ! 1060: // Set immediate bit if indicated. ! 1061: // ! 1062: ! 1063: cdb->CDB6GENERIC.Immediate = tapePrepare->Immediate; ! 1064: ! 1065: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 1066: &srb, ! 1067: NULL, ! 1068: 0, ! 1069: FALSE); ! 1070: ! 1071: return status; ! 1072: ! 1073: } // end TapePrepare() ! 1074: ! 1075: NTSTATUS ! 1076: TapeReadWrite( ! 1077: IN PDEVICE_OBJECT DeviceObject, ! 1078: IN PIRP Irp ! 1079: ) ! 1080: ! 1081: /*++ ! 1082: ! 1083: Routine Description: ! 1084: ! 1085: This routine builds SRBs and CDBs for read and write requests to 4MM DAT ! 1086: devices. ! 1087: ! 1088: Arguments: ! 1089: ! 1090: DeviceObject ! 1091: Irp ! 1092: ! 1093: Return Value: ! 1094: ! 1095: Returns STATUS_PENDING. ! 1096: ! 1097: --*/ ! 1098: ! 1099: { ! 1100: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 1101: PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); ! 1102: PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); ! 1103: PSCSI_REQUEST_BLOCK srb; ! 1104: PCDB cdb; ! 1105: KIRQL currentIrql; ! 1106: ULONG transferBlocks; ! 1107: LARGE_INTEGER startingOffset = ! 1108: currentIrpStack->Parameters.Read.ByteOffset; ! 1109: ! 1110: // ! 1111: // Allocate an Srb. ! 1112: // ! 1113: ! 1114: if (deviceExtension->SrbZone != NULL && ! 1115: (srb = ExInterlockedAllocateFromZone( ! 1116: deviceExtension->SrbZone, ! 1117: deviceExtension->SrbZoneSpinLock)) != NULL) { ! 1118: ! 1119: srb->SrbFlags = SRB_FLAGS_ALLOCATED_FROM_ZONE; ! 1120: ! 1121: } else { ! 1122: ! 1123: // ! 1124: // Allocate Srb from non-paged pool. ! 1125: // This call must succeed. ! 1126: // ! 1127: ! 1128: srb = ExAllocatePool(NonPagedPoolMustSucceed, SCSI_REQUEST_BLOCK_SIZE); ! 1129: ! 1130: srb->SrbFlags = 0; ! 1131: ! 1132: } ! 1133: ! 1134: // ! 1135: // Write length to SRB. ! 1136: // ! 1137: ! 1138: srb->Length = SCSI_REQUEST_BLOCK_SIZE; ! 1139: ! 1140: // ! 1141: // Set up IRP Address. ! 1142: // ! 1143: ! 1144: srb->OriginalRequest = Irp; ! 1145: ! 1146: // ! 1147: // Set up target id and logical unit number. ! 1148: // ! 1149: ! 1150: srb->PathId = deviceExtension->PathId; ! 1151: srb->TargetId = deviceExtension->TargetId; ! 1152: srb->Lun = deviceExtension->Lun; ! 1153: ! 1154: ! 1155: srb->Function = SRB_FUNCTION_EXECUTE_SCSI; ! 1156: ! 1157: srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress); ! 1158: ! 1159: // ! 1160: // Save byte count of transfer in SRB Extension. ! 1161: // ! 1162: ! 1163: srb->DataTransferLength = currentIrpStack->Parameters.Read.Length; ! 1164: ! 1165: // ! 1166: // Indicate auto request sense by specifying buffer and size. ! 1167: // ! 1168: ! 1169: srb->SenseInfoBuffer = deviceExtension->SenseData; ! 1170: ! 1171: srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; ! 1172: ! 1173: // ! 1174: // Initialize the queue actions field. ! 1175: // ! 1176: ! 1177: srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; ! 1178: ! 1179: // ! 1180: // Indicate auto request sense by specifying buffer and size. ! 1181: // ! 1182: ! 1183: srb->SenseInfoBuffer = deviceExtension->SenseData; ! 1184: ! 1185: srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; ! 1186: ! 1187: // ! 1188: // Set timeout value in seconds. ! 1189: // ! 1190: ! 1191: srb->TimeOutValue = deviceExtension->TimeOutValue; ! 1192: ! 1193: // ! 1194: // Zero statuses. ! 1195: // ! 1196: ! 1197: srb->SrbStatus = srb->ScsiStatus = 0; ! 1198: ! 1199: srb->NextSrb = 0; ! 1200: ! 1201: // ! 1202: // Indicate that 6-byte CDB's will be used. ! 1203: // ! 1204: ! 1205: srb->CdbLength = CDB6GENERIC_LENGTH; ! 1206: ! 1207: // ! 1208: // Fill in CDB fields. ! 1209: // ! 1210: ! 1211: cdb = (PCDB)srb->Cdb; ! 1212: ! 1213: // ! 1214: // Zero CDB in SRB. ! 1215: // ! 1216: ! 1217: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 1218: ! 1219: // ! 1220: // Since we are writing fixed block mode, normalize transfer count ! 1221: // to number of blocks. ! 1222: // ! 1223: ! 1224: transferBlocks = ! 1225: currentIrpStack->Parameters.Read.Length >> deviceExtension->SectorShift; ! 1226: ! 1227: // ! 1228: // Set up transfer length ! 1229: // ! 1230: ! 1231: cdb->CDB6READWRITETAPE.TransferLenMSB = (UCHAR)((transferBlocks >> 16) & 0xff); ! 1232: cdb->CDB6READWRITETAPE.TransferLen = (UCHAR)((transferBlocks >> 8) & 0xff); ! 1233: cdb->CDB6READWRITETAPE.TransferLenLSB = (UCHAR)(transferBlocks & 0xff); ! 1234: ! 1235: // ! 1236: // Tell the python we are in fixed block mode ! 1237: // ! 1238: ! 1239: cdb->CDB6READWRITETAPE.VendorSpecific = 1; ! 1240: ! 1241: // ! 1242: // Set transfer direction flag and Cdb command. ! 1243: // ! 1244: ! 1245: if (currentIrpStack->MajorFunction == IRP_MJ_READ) { ! 1246: ! 1247: DebugPrint((3, "TapeRequest: Read Command\n")); ! 1248: ! 1249: srb->SrbFlags = SRB_FLAGS_DATA_IN; ! 1250: cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_READ6; ! 1251: ! 1252: } else { ! 1253: ! 1254: DebugPrint((3, "TapeRequest: Write Command\n")); ! 1255: ! 1256: srb->SrbFlags = SRB_FLAGS_DATA_OUT; ! 1257: cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_WRITE6; ! 1258: } ! 1259: ! 1260: // ! 1261: // Or in the default flags from the device object. ! 1262: // ! 1263: ! 1264: srb->SrbFlags |= deviceExtension->SrbFlags; ! 1265: ! 1266: // ! 1267: // Set up major SCSI function. ! 1268: // ! 1269: ! 1270: nextIrpStack->MajorFunction = IRP_MJ_SCSI; ! 1271: ! 1272: // ! 1273: // Save SRB address in next stack for port driver. ! 1274: // ! 1275: ! 1276: nextIrpStack->Parameters.Scsi.Srb = srb; ! 1277: ! 1278: // ! 1279: // Save retry count in current IRP stack. ! 1280: // ! 1281: ! 1282: currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES; ! 1283: ! 1284: // ! 1285: // Set up IoCompletion routine address. ! 1286: // ! 1287: ! 1288: IoSetCompletionRoutine(Irp, ! 1289: ScsiClassIoComplete, ! 1290: srb, ! 1291: TRUE, ! 1292: TRUE, ! 1293: FALSE); ! 1294: ! 1295: return STATUS_PENDING; ! 1296: ! 1297: } // end TapeReadWrite() ! 1298: ! 1299: NTSTATUS ! 1300: TapeSetDriveParameters( ! 1301: IN PDEVICE_OBJECT DeviceObject, ! 1302: IN PIRP Irp ! 1303: ) ! 1304: ! 1305: /*++ ! 1306: Routine Description: ! 1307: ! 1308: This routine enables/disables reporting of setmarks. ! 1309: ! 1310: Arguments: ! 1311: ! 1312: DeviceObject ! 1313: Irp ! 1314: ! 1315: Return Value: ! 1316: ! 1317: NTSTATUS ! 1318: ! 1319: --*/ ! 1320: ! 1321: { ! 1322: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 1323: PTAPE_SET_DRIVE_PARAMETERS tapeSetDriveParams = Irp->AssociatedIrp.SystemBuffer; ! 1324: PMODE_DEVICE_CONFIG_PAGE buffer; ! 1325: SCSI_REQUEST_BLOCK srb; ! 1326: PCDB cdb = (PCDB)srb.Cdb; ! 1327: NTSTATUS status; ! 1328: PMODE_DATA_COMPRESS_PAGE dcbuff; ! 1329: ! 1330: DebugPrint((3,"TapeIoControl: Set Tape Drive Parameters\n")); ! 1331: ! 1332: // ! 1333: // Zero CDB in SRB on stack. ! 1334: // ! 1335: ! 1336: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 1337: ! 1338: srb.CdbLength = CDB6GENERIC_LENGTH; ! 1339: ! 1340: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; ! 1341: ! 1342: // ! 1343: // Set timeout value. ! 1344: // ! 1345: ! 1346: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 1347: ! 1348: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DEVICE_CONFIG_PAGE); ! 1349: cdb->MODE_SENSE.Dbd = SETBITON; ! 1350: cdb->MODE_SENSE.PageCode = MODE_PAGE_DEVICE_CONFIG; ! 1351: ! 1352: buffer = ExAllocatePool(NonPagedPoolCacheAligned, ! 1353: sizeof(MODE_DEVICE_CONFIG_PAGE)); ! 1354: ! 1355: if (!buffer) { ! 1356: return STATUS_INSUFFICIENT_RESOURCES; ! 1357: } ! 1358: ! 1359: RtlZeroMemory(buffer, sizeof(MODE_DEVICE_CONFIG_PAGE)); ! 1360: ! 1361: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 1362: &srb, ! 1363: buffer, ! 1364: sizeof( MODE_DEVICE_CONFIG_PAGE ), ! 1365: FALSE); ! 1366: ! 1367: if (!NT_SUCCESS(status)) { ! 1368: ExFreePool(buffer); ! 1369: return status; ! 1370: } ! 1371: ! 1372: // ! 1373: // Zero CDB in SRB on stack. ! 1374: // ! 1375: ! 1376: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 1377: ! 1378: srb.CdbLength = CDB6GENERIC_LENGTH; ! 1379: ! 1380: cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT; ! 1381: ! 1382: // ! 1383: // Set timeout value. ! 1384: // ! 1385: ! 1386: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 1387: ! 1388: cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_DEVICE_CONFIG_PAGE); ! 1389: cdb->MODE_SELECT.PFBit = 1; ! 1390: ! 1391: buffer->ParameterListHeader.ModeDataLength = 0; ! 1392: buffer->ParameterListHeader.MediumType = 0; ! 1393: buffer->ParameterListHeader.DeviceSpecificParameter = 0x10; ! 1394: buffer->ParameterListHeader.BlockDescriptorLength = 0; ! 1395: ! 1396: buffer->DeviceConfigPage.PageCode = MODE_PAGE_DEVICE_CONFIG; ! 1397: buffer->DeviceConfigPage.PageLength = 0x0E; ! 1398: ! 1399: if (tapeSetDriveParams->ReportSetmarks) { ! 1400: buffer->DeviceConfigPage.RSmk = SETBITON; ! 1401: } else { ! 1402: buffer->DeviceConfigPage.RSmk = SETBITOFF; ! 1403: } ! 1404: ! 1405: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 1406: &srb, ! 1407: buffer, ! 1408: sizeof( MODE_DEVICE_CONFIG_PAGE ), ! 1409: TRUE); ! 1410: ! 1411: ExFreePool(buffer); ! 1412: ! 1413: if (!NT_SUCCESS(status)) { ! 1414: return status; ! 1415: } ! 1416: ! 1417: // ! 1418: // Zero CDB in SRB on stack. ! 1419: // ! 1420: ! 1421: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 1422: ! 1423: srb.CdbLength = CDB6GENERIC_LENGTH; ! 1424: ! 1425: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; ! 1426: ! 1427: // ! 1428: // Set timeout value. ! 1429: // ! 1430: ! 1431: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 1432: ! 1433: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DATA_COMPRESS_PAGE); ! 1434: cdb->MODE_SENSE.Dbd = SETBITON; ! 1435: cdb->MODE_SENSE.PageCode = MODE_PAGE_DATA_COMPRESS; ! 1436: ! 1437: dcbuff = ExAllocatePool(NonPagedPoolCacheAligned, ! 1438: sizeof(MODE_DATA_COMPRESS_PAGE)); ! 1439: ! 1440: if (!dcbuff) { ! 1441: return STATUS_INSUFFICIENT_RESOURCES; ! 1442: } ! 1443: ! 1444: RtlZeroMemory(dcbuff, sizeof(MODE_DATA_COMPRESS_PAGE)); ! 1445: ! 1446: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 1447: &srb, ! 1448: dcbuff, ! 1449: sizeof( MODE_DATA_COMPRESS_PAGE ), ! 1450: FALSE); ! 1451: ! 1452: if (!NT_SUCCESS(status) && (status != STATUS_INVALID_DEVICE_REQUEST)) { ! 1453: ExFreePool(dcbuff); ! 1454: return status; ! 1455: } ! 1456: ! 1457: if (NT_SUCCESS(status) && dcbuff->DataCompressPage.DCC == 1) { ! 1458: // ! 1459: // Zero CDB in SRB on stack. ! 1460: // ! 1461: ! 1462: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 1463: ! 1464: srb.CdbLength = CDB6GENERIC_LENGTH; ! 1465: ! 1466: cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT; ! 1467: ! 1468: // ! 1469: // Set timeout value. ! 1470: // ! 1471: ! 1472: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 1473: ! 1474: cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_DATA_COMPRESS_PAGE); ! 1475: cdb->MODE_SELECT.PFBit = 1; ! 1476: ! 1477: dcbuff->ParameterListHeader.ModeDataLength = 0; ! 1478: dcbuff->ParameterListHeader.MediumType = 0; ! 1479: dcbuff->ParameterListHeader.DeviceSpecificParameter = 0x10; ! 1480: dcbuff->ParameterListHeader.BlockDescriptorLength = 0; ! 1481: ! 1482: dcbuff->DataCompressPage.PageCode = MODE_PAGE_DATA_COMPRESS; ! 1483: dcbuff->DataCompressPage.PageLength = 0x0E; ! 1484: ! 1485: if (tapeSetDriveParams->Compression) { ! 1486: dcbuff->DataCompressPage.DCE = SETBITON; ! 1487: } else { ! 1488: dcbuff->DataCompressPage.DCE = SETBITOFF; ! 1489: } ! 1490: ! 1491: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 1492: &srb, ! 1493: dcbuff, ! 1494: sizeof( MODE_DATA_COMPRESS_PAGE ), ! 1495: TRUE); ! 1496: } else if (status == STATUS_INVALID_DEVICE_REQUEST) { ! 1497: status = STATUS_SUCCESS; ! 1498: } ! 1499: ! 1500: ExFreePool(dcbuff); ! 1501: ! 1502: return status; ! 1503: ! 1504: } // end TapeSetDriveParameters() ! 1505: ! 1506: ! 1507: NTSTATUS ! 1508: TapeSetMediaParameters( ! 1509: IN PDEVICE_OBJECT DeviceObject, ! 1510: IN PIRP Irp ! 1511: ) ! 1512: ! 1513: /*++ ! 1514: Routine Description: ! 1515: ! 1516: This routine sets the fixed-length logical block size or variable-length ! 1517: block mode (if the block size is 0). ! 1518: ! 1519: Arguments: ! 1520: ! 1521: DeviceObject ! 1522: Irp ! 1523: ! 1524: Return Value: ! 1525: ! 1526: NTSTATUS ! 1527: ! 1528: --*/ ! 1529: ! 1530: { ! 1531: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 1532: PTAPE_SET_MEDIA_PARAMETERS tapeSetMediaParams = Irp->AssociatedIrp.SystemBuffer; ! 1533: PMODE_PARM_READ_WRITE_DATA buffer; ! 1534: SCSI_REQUEST_BLOCK srb; ! 1535: PCDB cdb = (PCDB)srb.Cdb; ! 1536: NTSTATUS status; ! 1537: ! 1538: DebugPrint((3,"TapeIoControl: Set Tape Media Parameters \n")); ! 1539: ! 1540: // ! 1541: // Zero CDB in SRB on stack. ! 1542: // ! 1543: ! 1544: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 1545: ! 1546: srb.CdbLength = CDB6GENERIC_LENGTH; ! 1547: ! 1548: cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT; ! 1549: ! 1550: // ! 1551: // Set timeout value. ! 1552: // ! 1553: ! 1554: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 1555: ! 1556: cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_PARM_READ_WRITE_DATA); ! 1557: cdb->MODE_SELECT.PFBit = 1; ! 1558: ! 1559: buffer = ExAllocatePool(NonPagedPoolCacheAligned, ! 1560: sizeof(MODE_PARM_READ_WRITE_DATA)); ! 1561: ! 1562: if (!buffer) { ! 1563: return STATUS_INSUFFICIENT_RESOURCES; ! 1564: } ! 1565: ! 1566: RtlZeroMemory(buffer, sizeof(MODE_PARM_READ_WRITE_DATA)); ! 1567: ! 1568: buffer->ParameterListHeader.DeviceSpecificParameter = 0x10; ! 1569: buffer->ParameterListHeader.BlockDescriptorLength = MODE_BLOCK_DESC_LENGTH; ! 1570: ! 1571: buffer->ParameterListBlock.BlockLength[0] = ! 1572: ((tapeSetMediaParams->BlockSize >> 16) & 0xFF); ! 1573: buffer->ParameterListBlock.BlockLength[1] = ! 1574: ((tapeSetMediaParams->BlockSize >> 8) & 0xFF); ! 1575: buffer->ParameterListBlock.BlockLength[2] = ! 1576: (tapeSetMediaParams->BlockSize & 0xFF); ! 1577: ! 1578: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 1579: &srb, ! 1580: buffer, ! 1581: sizeof( MODE_PARM_READ_WRITE_DATA ), ! 1582: TRUE); ! 1583: ! 1584: ExFreePool(buffer); ! 1585: ! 1586: return status; ! 1587: ! 1588: } // end TapeSetMediaParameters() ! 1589: ! 1590: ! 1591: NTSTATUS ! 1592: TapeSetPosition( ! 1593: IN PDEVICE_OBJECT DeviceObject, ! 1594: IN PIRP Irp ! 1595: ) ! 1596: ! 1597: /*++ ! 1598: Routine Description: ! 1599: ! 1600: This routine sets the position of the tape. ! 1601: ! 1602: Arguments: ! 1603: ! 1604: DeviceObject ! 1605: Irp ! 1606: ! 1607: Return Value: ! 1608: ! 1609: NTSTATUS ! 1610: ! 1611: --*/ ! 1612: ! 1613: { ! 1614: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 1615: PTAPE_DATA tapeData = (PTAPE_DATA)(deviceExtension + 1); ! 1616: PTAPE_SET_POSITION tapeSetPosition = Irp->AssociatedIrp.SystemBuffer; ! 1617: SCSI_REQUEST_BLOCK srb; ! 1618: PCDB cdb = (PCDB)srb.Cdb; ! 1619: NTSTATUS status; ! 1620: ! 1621: if (tapeSetPosition->Immediate) { ! 1622: switch (tapeSetPosition->Method) { ! 1623: case TAPE_REWIND: ! 1624: case TAPE_ABSOLUTE_BLOCK: ! 1625: case TAPE_LOGICAL_BLOCK: ! 1626: break; ! 1627: ! 1628: case TAPE_SPACE_END_OF_DATA: ! 1629: case TAPE_SPACE_RELATIVE_BLOCKS: ! 1630: case TAPE_SPACE_FILEMARKS: ! 1631: case TAPE_SPACE_SEQUENTIAL_FMKS: ! 1632: case TAPE_SPACE_SETMARKS: ! 1633: case TAPE_SPACE_SEQUENTIAL_SMKS: ! 1634: default: ! 1635: return STATUS_NOT_IMPLEMENTED; ! 1636: } ! 1637: } ! 1638: ! 1639: // ! 1640: // Zero CDB in SRB on stack. ! 1641: // ! 1642: ! 1643: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 1644: ! 1645: // ! 1646: // Set timeout value. ! 1647: // ! 1648: ! 1649: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 1650: ! 1651: srb.CdbLength = CDB6GENERIC_LENGTH; ! 1652: ! 1653: // ! 1654: // Set immediate bit if indicated. ! 1655: // ! 1656: ! 1657: cdb->CDB6GENERIC.Immediate = tapeSetPosition->Immediate; ! 1658: ! 1659: switch (tapeSetPosition->Method) { ! 1660: case TAPE_REWIND: ! 1661: DebugPrint((3,"TapeIoControl: Rewind Tape\n")); ! 1662: cdb->CDB6GENERIC.OperationCode = SCSIOP_REWIND; ! 1663: ! 1664: break; ! 1665: ! 1666: case TAPE_ABSOLUTE_BLOCK: ! 1667: DebugPrint((3,"TapeIoControl: Position Tape to an Absolute Block\n")); ! 1668: ! 1669: srb.TimeOutValue = 360; ! 1670: ! 1671: cdb->CDB6GENERIC.OperationCode = SCSIOP_SEEK_BLOCK; ! 1672: ! 1673: cdb->CDB6GENERIC.CommandUniqueBytes[0] = ! 1674: ((tapeSetPosition->Offset.LowPart >> 16) & 0xFF); ! 1675: cdb->CDB6GENERIC.CommandUniqueBytes[1] = ! 1676: ((tapeSetPosition->Offset.LowPart >> 8) & 0xFF); ! 1677: cdb->CDB6GENERIC.CommandUniqueBytes[2] = ! 1678: (tapeSetPosition->Offset.LowPart & 0xFF); ! 1679: break; ! 1680: ! 1681: case TAPE_LOGICAL_BLOCK: ! 1682: DebugPrint((3,"TapeIoControl: Position Tape to a Logical Block\n")); ! 1683: ! 1684: srb.TimeOutValue = 360; ! 1685: ! 1686: cdb->LOCATE.OperationCode = SCSIOP_LOCATE; ! 1687: ! 1688: srb.CdbLength = CDB10GENERIC_LENGTH; ! 1689: ! 1690: if ((tapeSetPosition->Partition != (ULONG)0) && ! 1691: (tapeSetPosition->Partition != (ULONG)tapeData->CurrentPartition) && ! 1692: gb_PartitionCount > 1) { ! 1693: cdb->LOCATE.CPBit = SETBITON; ! 1694: cdb->LOCATE.Partition = ! 1695: tapeSetPosition->Partition - 1; ! 1696: } ! 1697: cdb->LOCATE.LogicalBlockAddress[0] = ! 1698: ((tapeSetPosition->Offset.LowPart >> 24) & 0xFF); ! 1699: cdb->LOCATE.LogicalBlockAddress[1] = ! 1700: ((tapeSetPosition->Offset.LowPart >> 16) & 0xFF); ! 1701: cdb->LOCATE.LogicalBlockAddress[2] = ! 1702: ((tapeSetPosition->Offset.LowPart >> 8) & 0xFF); ! 1703: cdb->LOCATE.LogicalBlockAddress[3] = ! 1704: (tapeSetPosition->Offset.LowPart & 0xFF); ! 1705: ! 1706: break; ! 1707: ! 1708: case TAPE_SPACE_END_OF_DATA: ! 1709: DebugPrint((3,"TapeIoControl: Position Tape to End-of-Data\n")); ! 1710: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE; ! 1711: cdb->SPACE_TAPE_MARKS.Code = 3; ! 1712: break; ! 1713: ! 1714: case TAPE_SPACE_RELATIVE_BLOCKS: ! 1715: DebugPrint((3,"TapeIoControl: Position Tape by Spacing Blocks\n")); ! 1716: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE; ! 1717: cdb->SPACE_TAPE_MARKS.Code = 0; ! 1718: cdb->SPACE_TAPE_MARKS.NumMarksMSB = ! 1719: ((tapeSetPosition->Offset.LowPart >> 16) & 0xFF); ! 1720: cdb->SPACE_TAPE_MARKS.NumMarks = ! 1721: ((tapeSetPosition->Offset.LowPart >> 8) & 0xFF); ! 1722: cdb->SPACE_TAPE_MARKS.NumMarksLSB = ! 1723: (tapeSetPosition->Offset.LowPart & 0xFF); ! 1724: break; ! 1725: ! 1726: case TAPE_SPACE_FILEMARKS: ! 1727: DebugPrint((3,"TapeIoControl: Position Tape by Spacing Filemarks\n")); ! 1728: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE; ! 1729: cdb->SPACE_TAPE_MARKS.Code = 1; ! 1730: cdb->SPACE_TAPE_MARKS.NumMarksMSB = ! 1731: ((tapeSetPosition->Offset.LowPart >> 16) & 0xFF); ! 1732: cdb->SPACE_TAPE_MARKS.NumMarks = ! 1733: ((tapeSetPosition->Offset.LowPart >> 8) & 0xFF); ! 1734: cdb->SPACE_TAPE_MARKS.NumMarksLSB = ! 1735: (tapeSetPosition->Offset.LowPart & 0xFF); ! 1736: break; ! 1737: ! 1738: case TAPE_SPACE_SEQUENTIAL_FMKS: ! 1739: DebugPrint((3,"TapeIoControl: Position Tape by Spacing Sequential Filemarks\n")); ! 1740: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE; ! 1741: cdb->SPACE_TAPE_MARKS.Code = 2; ! 1742: cdb->SPACE_TAPE_MARKS.NumMarksMSB = ! 1743: ((tapeSetPosition->Offset.LowPart >> 16) & 0xFF); ! 1744: cdb->SPACE_TAPE_MARKS.NumMarks = ! 1745: ((tapeSetPosition->Offset.LowPart >> 8) & 0xFF); ! 1746: cdb->SPACE_TAPE_MARKS.NumMarksLSB = ! 1747: (tapeSetPosition->Offset.LowPart & 0xFF); ! 1748: break; ! 1749: ! 1750: case TAPE_SPACE_SETMARKS: ! 1751: DebugPrint((3,"TapeIoControl: Position Tape by Spacing Setmarks\n")); ! 1752: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE; ! 1753: cdb->SPACE_TAPE_MARKS.Code = 4; ! 1754: cdb->SPACE_TAPE_MARKS.NumMarksMSB = ! 1755: ((tapeSetPosition->Offset.LowPart >> 16) & 0xFF); ! 1756: cdb->SPACE_TAPE_MARKS.NumMarks = ! 1757: ((tapeSetPosition->Offset.LowPart >> 8) & 0xFF); ! 1758: cdb->SPACE_TAPE_MARKS.NumMarksLSB = ! 1759: (tapeSetPosition->Offset.LowPart & 0xFF); ! 1760: break; ! 1761: ! 1762: case TAPE_SPACE_SEQUENTIAL_SMKS: ! 1763: default: ! 1764: DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n")); ! 1765: return STATUS_INVALID_DEVICE_REQUEST; ! 1766: } ! 1767: ! 1768: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 1769: &srb, ! 1770: NULL, ! 1771: 0, ! 1772: FALSE); ! 1773: ! 1774: if (NT_SUCCESS(status)) { ! 1775: switch (tapeSetPosition->Method) { ! 1776: case TAPE_LOGICAL_BLOCK: ! 1777: tapeData->CurrentPartition = tapeSetPosition->Partition; ! 1778: break; ! 1779: } ! 1780: } ! 1781: ! 1782: return status; ! 1783: ! 1784: } // end TapeSetPosition() ! 1785: ! 1786: ! 1787: BOOLEAN ! 1788: TapeVerifyInquiry( ! 1789: IN PSCSI_INQUIRY_DATA LunInfo ! 1790: ) ! 1791: ! 1792: /*++ ! 1793: Routine Description: ! 1794: ! 1795: This routine determines if the driver should claim this device. ! 1796: ! 1797: Arguments: ! 1798: ! 1799: LunInfo ! 1800: ! 1801: Return Value: ! 1802: ! 1803: TRUE - driver should claim this device. ! 1804: FALSE - driver should not claim this device. ! 1805: ! 1806: --*/ ! 1807: ! 1808: { ! 1809: PINQUIRYDATA inquiryData; ! 1810: ! 1811: DebugPrint((3,"TapeIoControl: Verify Tape Inquiry Data\n")); ! 1812: ! 1813: inquiryData = (PVOID)LunInfo->InquiryData; ! 1814: ! 1815: // ! 1816: // Determine, from the Product ID field in the ! 1817: // inquiry data, whether or not to "claim" this drive. ! 1818: // ! 1819: ! 1820: if (WhichIsIt(inquiryData)) { ! 1821: ! 1822: RtlMoveMemory(gb_VendorId,inquiryData->VendorId,8); ! 1823: RtlMoveMemory(gb_ProductId,inquiryData->ProductId,16); ! 1824: return TRUE; ! 1825: ! 1826: } ! 1827: return FALSE; ! 1828: ! 1829: } // end TapeVerifyInquiry() ! 1830: ! 1831: ! 1832: NTSTATUS ! 1833: TapeWriteMarks( ! 1834: IN PDEVICE_OBJECT DeviceObject, ! 1835: IN PIRP Irp ! 1836: ) ! 1837: ! 1838: /*++ ! 1839: Routine Description: ! 1840: ! 1841: This routine writes tapemarks on the tape. ! 1842: ! 1843: Arguments: ! 1844: ! 1845: DeviceObject ! 1846: Irp ! 1847: ! 1848: Return Value: ! 1849: ! 1850: NTSTATUS ! 1851: ! 1852: --*/ ! 1853: ! 1854: { ! 1855: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 1856: PTAPE_WRITE_MARKS tapeWriteMarks = Irp->AssociatedIrp.SystemBuffer; ! 1857: SCSI_REQUEST_BLOCK srb; ! 1858: PCDB cdb = (PCDB)srb.Cdb; ! 1859: NTSTATUS status; ! 1860: ! 1861: // ! 1862: // Zero CDB in SRB on stack. ! 1863: // ! 1864: ! 1865: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 1866: ! 1867: srb.CdbLength = CDB6GENERIC_LENGTH; ! 1868: ! 1869: cdb->WRITE_TAPE_MARKS.OperationCode = SCSIOP_WRITE_FILEMARKS; ! 1870: ! 1871: cdb->WRITE_TAPE_MARKS.TransferLength[0] = ! 1872: ((tapeWriteMarks->Count >> 16) & 0xFF); ! 1873: ! 1874: cdb->WRITE_TAPE_MARKS.TransferLength[1] = ! 1875: ((tapeWriteMarks->Count >> 8) & 0xFF); ! 1876: ! 1877: cdb->WRITE_TAPE_MARKS.TransferLength[2] = ! 1878: (tapeWriteMarks->Count & 0xFF); ! 1879: ! 1880: // ! 1881: // Set timeout value. ! 1882: // ! 1883: ! 1884: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 1885: ! 1886: switch (tapeWriteMarks->Type) { ! 1887: case TAPE_SETMARKS: ! 1888: DebugPrint((3,"TapeIoControl: Write Setmarks to Tape\n")); ! 1889: cdb->WRITE_TAPE_MARKS.WriteSetMarks = SETBITON; ! 1890: break; ! 1891: ! 1892: case TAPE_FILEMARKS: ! 1893: DebugPrint((3,"TapeIoControl: Write Filemarks to Tape\n")); ! 1894: break; ! 1895: ! 1896: case TAPE_SHORT_FILEMARKS: ! 1897: case TAPE_LONG_FILEMARKS: ! 1898: default: ! 1899: DebugPrint((3,"TapeIoControl: Tape Operation Not Supported\n")); ! 1900: return STATUS_INVALID_DEVICE_REQUEST; ! 1901: } ! 1902: ! 1903: // ! 1904: // Set immediate bit if indicated. ! 1905: // ! 1906: ! 1907: cdb->WRITE_TAPE_MARKS.Immediate = tapeWriteMarks->Immediate; ! 1908: ! 1909: ! 1910: srb.CdbLength = CDB6GENERIC_LENGTH; ! 1911: ! 1912: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 1913: &srb, ! 1914: NULL, ! 1915: 0, ! 1916: FALSE); ! 1917: ! 1918: return status; ! 1919: ! 1920: } // end TapeWriteMarks() ! 1921: ! 1922: ! 1923: static ! 1924: ULONG ! 1925: WhichIsIt( ! 1926: IN PINQUIRYDATA InquiryData ! 1927: ) ! 1928: ! 1929: /*++ ! 1930: Routine Description: ! 1931: ! 1932: This routine determines a drive's identity from the Product ID field ! 1933: in its inquiry data. ! 1934: ! 1935: Arguments: ! 1936: ! 1937: InquiryData (from an Inquiry command) ! 1938: ! 1939: Return Value: ! 1940: ! 1941: driveID ! 1942: ! 1943: --*/ ! 1944: ! 1945: { ! 1946: if (RtlCompareMemory(InquiryData->VendorId,"ARCHIVE ",8) == 8) { ! 1947: ! 1948: if (RtlCompareMemory(InquiryData->ProductId,"Python",6) == 6) { ! 1949: return ARCHIVE_PYTHON; ! 1950: } ! 1951: ! 1952: } ! 1953: ! 1954: if (RtlCompareMemory(InquiryData->VendorId,"DEC ",8) == 8) { ! 1955: ! 1956: if (RtlCompareMemory(InquiryData->ProductId,"TLZ06",5) == 5) { ! 1957: return DEC_TLZ06; ! 1958: } ! 1959: ! 1960: } ! 1961: ! 1962: if (RtlCompareMemory(InquiryData->VendorId,"EXABYTE ",8) == 8) { ! 1963: ! 1964: if (RtlCompareMemory(InquiryData->ProductId,"EXB-4200 ",9) == 9) { ! 1965: return EXABYTE_4200; ! 1966: } ! 1967: ! 1968: if (RtlCompareMemory(InquiryData->ProductId,"EXB-4200c",9) == 9) { ! 1969: return EXABYTE_4200C; ! 1970: } ! 1971: ! 1972: } ! 1973: ! 1974: if (RtlCompareMemory(InquiryData->VendorId,"HP ",8) == 8) { ! 1975: ! 1976: if (RtlCompareMemory(InquiryData->ProductId,"HP35470A",8) == 8) { ! 1977: return HP_35470A; ! 1978: } ! 1979: ! 1980: if (RtlCompareMemory(InquiryData->ProductId,"HP35480A",8) == 8) { ! 1981: return HP_35480A; ! 1982: } ! 1983: ! 1984: if (RtlCompareMemory(InquiryData->ProductId,"IBM35480A",9) == 9) { ! 1985: return HP_IBM35480A; ! 1986: } ! 1987: ! 1988: } ! 1989: ! 1990: if (RtlCompareMemory(InquiryData->VendorId,"WangDAT ",8) == 8) { ! 1991: ! 1992: if (RtlCompareMemory(InquiryData->ProductId,"Model 1300",10) == 10) { ! 1993: return WANGDAT_1300; ! 1994: } ! 1995: ! 1996: if (RtlCompareMemory(InquiryData->ProductId,"Model 3100",10) == 10) { ! 1997: return WANGDAT_3100; ! 1998: } ! 1999: ! 2000: if (RtlCompareMemory(InquiryData->ProductId,"Model 3200",10) == 10) { ! 2001: return WANGDAT_3200; ! 2002: } ! 2003: ! 2004: } ! 2005: ! 2006: return 0; ! 2007: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.