|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1992 Microsoft Corporation ! 4: ! 5: Module Name: ! 6: ! 7: tandqic.c ! 8: ! 9: Abstract: ! 10: ! 11: This module contains device specific routines for Tandberg QIC ! 12: drives with SCSI-2 interfaces -- TDC 4220, TDC 4120, TDC 3820, ! 13: and TDC 3660. ! 14: ! 15: Author: ! 16: ! 17: Mike Colandreo (Maynard) ! 18: ! 19: Environment: ! 20: ! 21: kernel mode only ! 22: ! 23: Revision History: ! 24: ! 25: --*/ ! 26: ! 27: #include "ntddk.h" ! 28: #include "tape.h" ! 29: #include "physlogi.h" ! 30: ! 31: // ! 32: // Internal (module wide) defines that symbolize ! 33: // non-QFA mode and the two QFA mode partitions. ! 34: // ! 35: #define NO_PARTITIONS 0 // non-QFA mode ! 36: #define DIRECTORY_PARTITION 1 // QFA mode, directory partition # ! 37: #define DATA_PARTITION 2 // QFA mode, data partition # ! 38: ! 39: // ! 40: // Internal (module wide) defines that symbolize ! 41: // the Tandberg QIC drives supported by this module. ! 42: // ! 43: #define TDC_3600 (ULONG)1 // aka the TDC 3660 ! 44: #define TDC_3800 (ULONG)2 // aka the TDC 3820 ! 45: #define TDC_4100 (ULONG)3 // aka the TDC 4120 ! 46: #define TDC_4200 (ULONG)4 // aka the TDC 4220 ! 47: ! 48: // ! 49: // Function Prototype(s) for internal function(s) ! 50: // ! 51: static ! 52: NTSTATUS ! 53: GetInquiryInformationData ( ! 54: IN PDEVICE_OBJECT DeviceObject, ! 55: IN PIRP Irp, ! 56: OUT PINQUIRYDATA InquiryBuffer ! 57: ); ! 58: ! 59: static ! 60: NTSTATUS ! 61: RewindToBOT( ! 62: IN PDEVICE_OBJECT DeviceObject, ! 63: IN PIRP Irp ! 64: ); ! 65: ! 66: static ! 67: ULONG ! 68: WhichIsIt( ! 69: IN PINQUIRYDATA InquiryData ! 70: ); ! 71: ! 72: ! 73: NTSTATUS ! 74: TapeCreatePartition( ! 75: IN PDEVICE_OBJECT DeviceObject, ! 76: IN PIRP Irp ! 77: ) ! 78: ! 79: /*++ ! 80: Routine Description: ! 81: ! 82: This routine can either "create" two, fixed, QFA partitions on a QIC ! 83: tape by selecting/enabling the drive's dual-partition, QFA mode or ! 84: return the drive to the not partitioned mode (i.e., disable QFA mode). ! 85: Note that this function "creates" two partitions only in a conceptual ! 86: sense -- it does not physically affect tape. ! 87: ! 88: Arguments: ! 89: ! 90: DeviceObject ! 91: Irp ! 92: ! 93: Return Value: ! 94: ! 95: NTSTATUS ! 96: ! 97: --*/ ! 98: ! 99: { ! 100: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 101: PTAPE_CREATE_PARTITION tapePartition = Irp->AssociatedIrp.SystemBuffer; ! 102: PTAPE_DATA tapeData = (PTAPE_DATA)(deviceExtension + 1); ! 103: PMODE_MEDIUM_PART_PAGE buffer; ! 104: SCSI_REQUEST_BLOCK srb; ! 105: PCDB cdb = (PCDB)srb.Cdb; ! 106: NTSTATUS status; ! 107: ! 108: // ! 109: // Only support 2 partitions, QFA mode ! 110: // Partition 1 = Used as directory ! 111: // Partition 0 = used as data ! 112: // ! 113: // Note that 0 & 1 are partition numbers used ! 114: // by the drive -- they are not tape API partition ! 115: // numbers. ! 116: // ! 117: ! 118: DebugPrint((3,"TapeCreatePartition: Enter routine\n")); ! 119: ! 120: switch (tapePartition->Method) { ! 121: case TAPE_FIXED_PARTITIONS: ! 122: DebugPrint((3,"TapeCreatePartition: fixed partitions\n")); ! 123: break; ! 124: ! 125: case TAPE_SELECT_PARTITIONS: ! 126: case TAPE_INITIATOR_PARTITIONS: ! 127: default: ! 128: DebugPrint((1,"TapeCreatePartition: ")); ! 129: DebugPrint((1,"PartitionMethod -- operation not supported\n")); ! 130: return STATUS_NOT_IMPLEMENTED; ! 131: } ! 132: ! 133: // ! 134: // Must rewind to BOT before one can enable/disable QFA mode. ! 135: // Changing the value of the FDP bit is only valid at BOT. ! 136: // FDP bit is used to enable/disable "additional partitions" ! 137: // (mode sense command). ! 138: // ! 139: ! 140: DebugPrint((3,"TapeCreatePartition: SendSrb (rewind)\n")); ! 141: ! 142: status = RewindToBOT(DeviceObject, Irp); ! 143: ! 144: if (!NT_SUCCESS(status)) { ! 145: DebugPrint((1,"TapeCreatePartition: rewind, SendSrb unsuccessful\n")); ! 146: return status; ! 147: } ! 148: ! 149: // ! 150: // Performing mode select command, medium partition parameters page, ! 151: // to enable/disable QFA mode: set the FDP bit accordingly. ! 152: // ! 153: ! 154: buffer = ExAllocatePool(NonPagedPoolCacheAligned, ! 155: sizeof(MODE_MEDIUM_PART_PAGE)); ! 156: ! 157: if (!buffer) { ! 158: DebugPrint((1,"TapeCreatePartition: insufficient resources (buffer)\n")); ! 159: return STATUS_INSUFFICIENT_RESOURCES; ! 160: } ! 161: ! 162: RtlZeroMemory(buffer, sizeof(MODE_MEDIUM_PART_PAGE)); ! 163: ! 164: buffer->ParameterListHeader.DeviceSpecificParameter = 0x10; ! 165: ! 166: buffer->MediumPartPage.PageCode = MODE_PAGE_MEDIUM_PARTITION; ! 167: buffer->MediumPartPage.PageLength = 0x06; ! 168: buffer->MediumPartPage.MaximumAdditionalPartitions = 1; ! 169: ! 170: // ! 171: // Setup FDP bit to enable/disable "additional partition". ! 172: // ! 173: ! 174: if (tapePartition->Count == 0) { ! 175: buffer->MediumPartPage.FDPBit = SETBITOFF; ! 176: } else { ! 177: buffer->MediumPartPage.FDPBit = SETBITON; ! 178: } ! 179: ! 180: // ! 181: // Zero CDB in SRB on stack. ! 182: // ! 183: ! 184: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 185: ! 186: // ! 187: // Prepare SCSI command (CDB) ! 188: // ! 189: ! 190: srb.CdbLength = CDB6GENERIC_LENGTH; ! 191: ! 192: cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT; ! 193: cdb->MODE_SELECT.PFBit = SETBITON; ! 194: cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_MEDIUM_PART_PAGE) - 4; ! 195: ! 196: // ! 197: // Set timeout value. ! 198: // ! 199: ! 200: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 201: ! 202: // ! 203: // Send SCSI command (CDB) to device ! 204: // ! 205: ! 206: DebugPrint((3,"TapeCreatePartition: SendSrb (mode select)\n")); ! 207: ! 208: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 209: &srb, ! 210: buffer, ! 211: sizeof(MODE_MEDIUM_PART_PAGE) - 4, ! 212: TRUE); ! 213: ! 214: ExFreePool(buffer); ! 215: ! 216: if (NT_SUCCESS(status)) { ! 217: ! 218: if (tapePartition->Count == 0) { ! 219: tapeData->CurrentPartition = NO_PARTITIONS; ! 220: DebugPrint((3,"TapeCreatePartition: QFA disabled\n")); ! 221: } else { ! 222: tapeData->CurrentPartition = DATA_PARTITION; ! 223: DebugPrint((3,"TapeCreatePartition: QFA enabled\n")); ! 224: } ! 225: ! 226: } else { ! 227: ! 228: DebugPrint((1,"TapeCreatePartition: mode select, SendSrb unsuccessful\n")); ! 229: ! 230: } ! 231: ! 232: return status; ! 233: ! 234: } // end TapeCreatePartition() ! 235: ! 236: ! 237: NTSTATUS ! 238: TapeErase( ! 239: IN PDEVICE_OBJECT DeviceObject, ! 240: IN PIRP Irp ! 241: ) ! 242: ! 243: /*++ ! 244: Routine Description: ! 245: ! 246: This routine erases the entire tape. The Tandberg QIC drives cannot ! 247: partially erase tape. Positioning the tape at BOT is a prerequisite: ! 248: the drive rejects the command if the tape is not at BOT. ! 249: ! 250: Arguments: ! 251: ! 252: DeviceObject ! 253: Irp ! 254: ! 255: Return Value: ! 256: ! 257: NTSTATUS ! 258: ! 259: --*/ ! 260: ! 261: { ! 262: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 263: PTAPE_ERASE tapeErase = Irp->AssociatedIrp.SystemBuffer; ! 264: PTAPE_DATA tapeData = (PTAPE_DATA)(deviceExtension + 1); ! 265: SCSI_REQUEST_BLOCK srb; ! 266: PCDB cdb = (PCDB)srb.Cdb; ! 267: NTSTATUS status; ! 268: ! 269: DebugPrint((3,"TapeErase: Enter routine\n")); ! 270: ! 271: if (tapeErase->Immediate) { ! 272: switch (tapeErase->Type) { ! 273: case TAPE_ERASE_LONG: ! 274: DebugPrint((3,"TapeErase: immediate\n")); ! 275: break; ! 276: ! 277: case TAPE_ERASE_SHORT: ! 278: default: ! 279: DebugPrint((1,"TapeErase: EraseType, immediate -- operation not supported\n")); ! 280: return STATUS_NOT_IMPLEMENTED; ! 281: } ! 282: } ! 283: ! 284: switch (tapeErase->Type) { ! 285: case TAPE_ERASE_LONG: ! 286: DebugPrint((3,"TapeErase: long\n")); ! 287: break; ! 288: ! 289: case TAPE_ERASE_SHORT: ! 290: default: ! 291: DebugPrint((1,"TapeErase: EraseType -- operation not supported\n")); ! 292: return STATUS_NOT_IMPLEMENTED; ! 293: } ! 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->ERASE.OperationCode = SCSIOP_ERASE; ! 308: cdb->ERASE.Immediate = tapeErase->Immediate; ! 309: cdb->ERASE.Long = SETBITON; ! 310: ! 311: // ! 312: // Set timeout value. ! 313: // ! 314: ! 315: srb.TimeOutValue = 360; ! 316: ! 317: // ! 318: // Send SCSI command (CDB) to device ! 319: // ! 320: ! 321: DebugPrint((3,"TapeErase: SendSrb (erase)\n")); ! 322: ! 323: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 324: &srb, ! 325: NULL, ! 326: 0, ! 327: FALSE); ! 328: ! 329: if (!NT_SUCCESS(status)) { ! 330: DebugPrint((1,"TapeErase: erase, SendSrb unsuccessful\n")); ! 331: return status; ! 332: } ! 333: ! 334: if (tapeData->CurrentPartition) { ! 335: tapeData->CurrentPartition = DATA_PARTITION; ! 336: } ! 337: ! 338: return status; ! 339: ! 340: } // end TapeErase() ! 341: ! 342: ! 343: VOID ! 344: TapeError( ! 345: PDEVICE_OBJECT DeviceObject, ! 346: PSCSI_REQUEST_BLOCK Srb, ! 347: NTSTATUS *Status, ! 348: BOOLEAN *Retry ! 349: ) ! 350: ! 351: /*++ ! 352: ! 353: Routine Description: ! 354: ! 355: When a request completes with error, the routine InterpretSenseInfo is ! 356: called to determine from the sense data whether the request should be ! 357: retried and what NT status to set in the IRP. Then this routine is called ! 358: for tape requests to handle tape-specific errors and update the nt status ! 359: and retry boolean. ! 360: ! 361: Arguments: ! 362: ! 363: DeviceObject - Supplies a pointer to the device object. ! 364: ! 365: Srb - Supplies a pointer to the failing Srb. ! 366: ! 367: Status - NT Status used to set the IRP's completion status. ! 368: ! 369: Retry - Indicates that this request should be retried. ! 370: ! 371: Return Value: ! 372: ! 373: None. ! 374: ! 375: --*/ ! 376: ! 377: { ! 378: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 379: PSENSE_DATA senseBuffer = Srb->SenseInfoBuffer; ! 380: NTSTATUS status = *Status; ! 381: BOOLEAN retry = *Retry; ! 382: ! 383: DebugPrint((3,"TapeError: Enter routine\n")); ! 384: DebugPrint((1,"TapeError: Status 0x%.8X, Retry %d\n", status, retry)); ! 385: return; ! 386: ! 387: } // end TapeError() ! 388: ! 389: ! 390: NTSTATUS ! 391: TapeGetDriveParameters( ! 392: IN PDEVICE_OBJECT DeviceObject, ! 393: IN PIRP Irp ! 394: ) ! 395: ! 396: /*++ ! 397: Routine Description: ! 398: ! 399: This routine determines and returns the "drive parameters" of the ! 400: Tandberg QIC tape drive associated with "DeviceObject". From time ! 401: to time, the drive paramater set of a given drive will vary. It will ! 402: change as drive operating characteristics change: e.g., tape media ! 403: type loaded, recording density of the media type loaded, etc. ! 404: ! 405: Arguments: ! 406: ! 407: DeviceObject ! 408: Irp ! 409: ! 410: Return Value: ! 411: ! 412: NTSTATUS ! 413: ! 414: --*/ ! 415: ! 416: { ! 417: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 418: PTAPE_GET_DRIVE_PARAMETERS tapeGetDriveParams = Irp->AssociatedIrp.SystemBuffer; ! 419: PMODE_PARM_READ_WRITE_DATA modeParmBuffer; ! 420: PREAD_BLOCK_LIMITS_DATA blockLimits; ! 421: PINQUIRYDATA inquiryBuffer; ! 422: UCHAR densityCode; ! 423: UCHAR mediumType; ! 424: ULONG tapeBlockLength; ! 425: ULONG whichdrive; ! 426: SCSI_REQUEST_BLOCK srb; ! 427: PCDB cdb = (PCDB)srb.Cdb; ! 428: NTSTATUS status; ! 429: ! 430: DebugPrint((3,"TapeGetDriveParameters: Enter routine\n")); ! 431: ! 432: RtlZeroMemory(tapeGetDriveParams, sizeof(TAPE_GET_DRIVE_PARAMETERS)); ! 433: Irp->IoStatus.Information = sizeof(TAPE_GET_DRIVE_PARAMETERS); ! 434: ! 435: modeParmBuffer = ExAllocatePool(NonPagedPoolCacheAligned, ! 436: sizeof(MODE_PARM_READ_WRITE_DATA)); ! 437: ! 438: if (!modeParmBuffer) { ! 439: DebugPrint((1,"TapeGetDriveParameters: insufficient resources (modeParmBuffer)\n")); ! 440: return STATUS_INSUFFICIENT_RESOURCES; ! 441: } ! 442: ! 443: RtlZeroMemory(modeParmBuffer, sizeof(MODE_PARM_READ_WRITE_DATA)); ! 444: ! 445: // ! 446: // Zero CDB in SRB on stack. ! 447: // ! 448: ! 449: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 450: ! 451: // ! 452: // Prepare SCSI command (CDB) ! 453: // ! 454: ! 455: srb.CdbLength = CDB6GENERIC_LENGTH; ! 456: ! 457: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; ! 458: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_PARM_READ_WRITE_DATA); ! 459: ! 460: // ! 461: // Set timeout value. ! 462: // ! 463: ! 464: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 465: ! 466: // ! 467: // Send SCSI command (CDB) to device ! 468: // ! 469: ! 470: DebugPrint((3,"TapeGetDriveParameters: SendSrb (mode sense)\n")); ! 471: ! 472: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 473: &srb, ! 474: modeParmBuffer, ! 475: sizeof(MODE_PARM_READ_WRITE_DATA), ! 476: FALSE); ! 477: ! 478: if (NT_SUCCESS(status)) { ! 479: ! 480: mediumType = modeParmBuffer->ParameterListHeader.MediumType; ! 481: densityCode = modeParmBuffer->ParameterListBlock.DensityCode; ! 482: tapeBlockLength = modeParmBuffer->ParameterListBlock.BlockLength[2]; ! 483: tapeBlockLength += (modeParmBuffer->ParameterListBlock.BlockLength[1] << 8); ! 484: tapeBlockLength += (modeParmBuffer->ParameterListBlock.BlockLength[0] << 16); ! 485: ! 486: switch (mediumType) { ! 487: case 1: ! 488: mediumType = DC600; ! 489: break; ! 490: ! 491: case 2: ! 492: mediumType = DC6150; ! 493: break; ! 494: ! 495: case 3: ! 496: mediumType = DC6320; ! 497: break; ! 498: ! 499: } ! 500: ! 501: } ! 502: ! 503: ExFreePool(modeParmBuffer); ! 504: ! 505: if (!NT_SUCCESS(status)) { ! 506: DebugPrint((1,"TapeGetDriveParameters: mode sense, SendSrb unsuccessful\n")); ! 507: return status; ! 508: } ! 509: ! 510: blockLimits = ExAllocatePool(NonPagedPoolCacheAligned, ! 511: sizeof(READ_BLOCK_LIMITS_DATA)); ! 512: ! 513: if (!blockLimits) { ! 514: DebugPrint((1,"TapeGetDriveParameters: insufficient resources (blockLimits)\n")); ! 515: return STATUS_INSUFFICIENT_RESOURCES; ! 516: } ! 517: ! 518: RtlZeroMemory(blockLimits, sizeof(READ_BLOCK_LIMITS_DATA)); ! 519: ! 520: // ! 521: // Zero CDB in SRB on stack. ! 522: // ! 523: ! 524: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 525: ! 526: // ! 527: // Prepare SCSI command (CDB) ! 528: // ! 529: ! 530: srb.CdbLength = CDB6GENERIC_LENGTH; ! 531: ! 532: cdb->CDB6GENERIC.OperationCode = SCSIOP_READ_BLOCK_LIMITS; ! 533: ! 534: // ! 535: // Set timeout value. ! 536: // ! 537: ! 538: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 539: ! 540: // ! 541: // Send SCSI command (CDB) to device ! 542: // ! 543: ! 544: DebugPrint((3,"TapeGetDriveParameters: SendSrb (read block limits)\n")); ! 545: ! 546: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 547: &srb, ! 548: blockLimits, ! 549: sizeof(READ_BLOCK_LIMITS_DATA), ! 550: FALSE); ! 551: ! 552: if (NT_SUCCESS(status)) { ! 553: tapeGetDriveParams->MaximumBlockSize = blockLimits->BlockMaximumSize[2]; ! 554: tapeGetDriveParams->MaximumBlockSize += (blockLimits->BlockMaximumSize[1] << 8); ! 555: tapeGetDriveParams->MaximumBlockSize += (blockLimits->BlockMaximumSize[0] << 16); ! 556: ! 557: tapeGetDriveParams->MinimumBlockSize = blockLimits->BlockMinimumSize[1]; ! 558: tapeGetDriveParams->MinimumBlockSize += (blockLimits->BlockMinimumSize[0] << 8); ! 559: } ! 560: ! 561: ExFreePool(blockLimits); ! 562: ! 563: if (!NT_SUCCESS(status)) { ! 564: DebugPrint((1,"TapeGetDriveParameters: read block limits, SendSrb unsuccessful\n")); ! 565: return status; ! 566: } ! 567: ! 568: inquiryBuffer = ExAllocatePool(NonPagedPoolCacheAligned, ! 569: sizeof(INQUIRYDATA)); ! 570: ! 571: if (!inquiryBuffer) { ! 572: DebugPrint((1,"TapeGetDriveParameters: insufficient resources (inquiryBuffer)\n")); ! 573: return STATUS_INSUFFICIENT_RESOURCES; ! 574: } ! 575: ! 576: RtlZeroMemory(inquiryBuffer, sizeof(INQUIRYDATA)); ! 577: ! 578: // ! 579: // Send SCSI command (CDB) to device ! 580: // ! 581: ! 582: DebugPrint((3,"TapeGetDriveParameters: SendSrb (inquiry)\n")); ! 583: ! 584: status = GetInquiryInformationData(DeviceObject, Irp, inquiryBuffer); ! 585: ! 586: if (NT_SUCCESS(status)) { ! 587: ! 588: // ! 589: // Which drive do we have, TDC 3660, 3820, 4120 or 4220? ! 590: // ! 591: ! 592: whichdrive = WhichIsIt(inquiryBuffer); ! 593: } ! 594: ! 595: ExFreePool(inquiryBuffer); ! 596: ! 597: if (!NT_SUCCESS(status)) { ! 598: DebugPrint((1,"TapeGetDriveParameters: inquiry, SendSrb unsuccessful\n")); ! 599: return status; ! 600: } ! 601: ! 602: tapeGetDriveParams->ECC = 0; ! 603: tapeGetDriveParams->Compression = 0; ! 604: tapeGetDriveParams->DataPadding = 0; ! 605: tapeGetDriveParams->MaximumPartitionCount = 2; ! 606: ! 607: if ((whichdrive == TDC_4100) || (whichdrive == TDC_4200)) { ! 608: ! 609: tapeGetDriveParams->ReportSetmarks = TRUE; ! 610: ! 611: tapeGetDriveParams->FeaturesLow |= ! 612: TAPE_DRIVE_REPORT_SMKS; ! 613: ! 614: tapeGetDriveParams->FeaturesHigh |= ! 615: TAPE_DRIVE_SETMARKS | ! 616: TAPE_DRIVE_WRITE_SETMARKS; ! 617: ! 618: } ! 619: ! 620: if (whichdrive != TDC_3600) { ! 621: ! 622: tapeGetDriveParams->FeaturesLow |= ! 623: TAPE_DRIVE_VARIABLE_BLOCK; ! 624: ! 625: tapeGetDriveParams->FeaturesHigh |= ! 626: TAPE_DRIVE_SET_BLOCK_SIZE; ! 627: ! 628: } ! 629: ! 630: switch (densityCode) { ! 631: case QIC_XX: ! 632: switch (mediumType) { ! 633: case DC6320: ! 634: case DC6525: ! 635: case DC9100: ! 636: case DC9100XL: ! 637: tapeGetDriveParams->DefaultBlockSize = 1024; ! 638: break; ! 639: ! 640: default: ! 641: tapeGetDriveParams->DefaultBlockSize = 512; ! 642: break; ! 643: } ! 644: break; ! 645: ! 646: case QIC_525: ! 647: case QIC_1000: ! 648: case QIC_2GB: ! 649: tapeGetDriveParams->DefaultBlockSize = 1024; ! 650: break; ! 651: ! 652: default: ! 653: tapeGetDriveParams->DefaultBlockSize = 512; ! 654: break; ! 655: } ! 656: ! 657: tapeGetDriveParams->FeaturesLow |= ! 658: TAPE_DRIVE_FIXED | ! 659: TAPE_DRIVE_ERASE_LONG | ! 660: TAPE_DRIVE_ERASE_BOP_ONLY | ! 661: TAPE_DRIVE_ERASE_IMMEDIATE | ! 662: TAPE_DRIVE_FIXED_BLOCK | ! 663: TAPE_DRIVE_WRITE_PROTECT | ! 664: TAPE_DRIVE_GET_ABSOLUTE_BLK | ! 665: TAPE_DRIVE_GET_LOGICAL_BLK; ! 666: ! 667: tapeGetDriveParams->FeaturesHigh |= ! 668: TAPE_DRIVE_LOAD_UNLOAD | ! 669: TAPE_DRIVE_TENSION | ! 670: TAPE_DRIVE_LOCK_UNLOCK | ! 671: TAPE_DRIVE_REWIND_IMMEDIATE | ! 672: TAPE_DRIVE_LOAD_UNLD_IMMED | ! 673: TAPE_DRIVE_TENSION_IMMED | ! 674: TAPE_DRIVE_ABSOLUTE_BLK | ! 675: TAPE_DRIVE_LOGICAL_BLK | ! 676: TAPE_DRIVE_END_OF_DATA | ! 677: TAPE_DRIVE_RELATIVE_BLKS | ! 678: TAPE_DRIVE_FILEMARKS | ! 679: TAPE_DRIVE_SEQUENTIAL_FMKS | ! 680: TAPE_DRIVE_REVERSE_POSITION | ! 681: TAPE_DRIVE_WRITE_FILEMARKS | ! 682: TAPE_DRIVE_WRITE_MARK_IMMED; ! 683: ! 684: tapeGetDriveParams->FeaturesHigh &= ~TAPE_DRIVE_HIGH_FEATURES; ! 685: ! 686: DebugPrint((3,"TapeGetDriveParameters: FeaturesLow == 0x%.8X\n", ! 687: tapeGetDriveParams->FeaturesLow)); ! 688: DebugPrint((3,"TapeGetDriveParameters: FeaturesHigh == 0x%.8X\n", ! 689: tapeGetDriveParams->FeaturesHigh)); ! 690: ! 691: return status; ! 692: ! 693: } // end TapeGetDriveParameters() ! 694: ! 695: ! 696: NTSTATUS ! 697: TapeGetMediaParameters( ! 698: IN PDEVICE_OBJECT DeviceObject, ! 699: IN PIRP Irp ! 700: ) ! 701: ! 702: /*++ ! 703: Routine Description: ! 704: ! 705: This routine determines and returns the "media parameters" of the ! 706: Tandberg QIC tape drive associated with "DeviceObject". Tape media ! 707: must be present (loaded) in the drive for this function to return ! 708: "no error". ! 709: ! 710: Arguments: ! 711: ! 712: DeviceObject ! 713: Irp ! 714: ! 715: Return Value: ! 716: ! 717: NTSTATUS ! 718: ! 719: --*/ ! 720: ! 721: { ! 722: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 723: PTAPE_DATA tapeData = (PTAPE_DATA)(deviceExtension + 1); ! 724: PTAPE_GET_MEDIA_PARAMETERS tapeGetMediaParams = Irp->AssociatedIrp.SystemBuffer; ! 725: PMODE_TAPE_MEDIA_INFORMATION mediaInfoBuffer; ! 726: PMODE_DEVICE_CONFIG_PAGE deviceConfigBuffer; ! 727: ULONG sectorShift; ! 728: SCSI_REQUEST_BLOCK srb; ! 729: PCDB cdb = (PCDB)srb.Cdb; ! 730: NTSTATUS status; ! 731: ! 732: DebugPrint((3,"TapeGetMediaParameters: Enter routine\n")); ! 733: ! 734: RtlZeroMemory(tapeGetMediaParams, sizeof(TAPE_GET_MEDIA_PARAMETERS)); ! 735: Irp->IoStatus.Information = sizeof(TAPE_GET_MEDIA_PARAMETERS); ! 736: ! 737: // ! 738: // Zero CDB in SRB on stack. ! 739: // ! 740: ! 741: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 742: ! 743: // ! 744: // Prepare SCSI command (CDB) ! 745: // ! 746: ! 747: srb.CdbLength = CDB6GENERIC_LENGTH; ! 748: ! 749: cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY; ! 750: ! 751: // ! 752: // Set timeout value. ! 753: // ! 754: ! 755: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 756: ! 757: // ! 758: // Send SCSI command (CDB) to device ! 759: // ! 760: ! 761: DebugPrint((3,"TapeGetMediaParameters: SendSrb (test unit ready)\n")); ! 762: ! 763: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 764: &srb, ! 765: NULL, ! 766: 0, ! 767: FALSE); ! 768: ! 769: if (!NT_SUCCESS(status)) { ! 770: DebugPrint((1,"TapeGetMediaParameters: test unit ready, SendSrb unsuccessful\n")); ! 771: return status; ! 772: } ! 773: ! 774: mediaInfoBuffer = ExAllocatePool(NonPagedPoolCacheAligned, ! 775: sizeof(MODE_TAPE_MEDIA_INFORMATION)); ! 776: ! 777: if (!mediaInfoBuffer) { ! 778: DebugPrint((1,"TapeGetMediaParameters: insufficient resources (mediaInfoBuffer)\n")); ! 779: return STATUS_INSUFFICIENT_RESOURCES; ! 780: } ! 781: ! 782: RtlZeroMemory(mediaInfoBuffer, sizeof(MODE_TAPE_MEDIA_INFORMATION)); ! 783: ! 784: // ! 785: // Zero CDB in SRB on stack. ! 786: // ! 787: ! 788: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 789: ! 790: // ! 791: // Prepare SCSI command (CDB) ! 792: // ! 793: ! 794: srb.CdbLength = CDB6GENERIC_LENGTH; ! 795: ! 796: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; ! 797: cdb->MODE_SENSE.PageCode = MODE_PAGE_MEDIUM_PARTITION; ! 798: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_TAPE_MEDIA_INFORMATION) - 4; ! 799: ! 800: // ! 801: // Set timeout value. ! 802: // ! 803: ! 804: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 805: ! 806: // ! 807: // Send SCSI command (CDB) to device ! 808: // ! 809: ! 810: DebugPrint((3,"TapeGetMediaParameters: SendSrb (mode sense #1)\n")); ! 811: ! 812: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 813: &srb, ! 814: mediaInfoBuffer, ! 815: sizeof(MODE_TAPE_MEDIA_INFORMATION) - 4, ! 816: FALSE); ! 817: ! 818: if (!NT_SUCCESS(status)) { ! 819: DebugPrint((1,"TapeGetMediaParameters: mode sense #1, SendSrb unsuccessful\n")); ! 820: ExFreePool(mediaInfoBuffer); ! 821: return status; ! 822: } ! 823: ! 824: if (mediaInfoBuffer->MediumPartPage.FDPBit) { ! 825: ! 826: deviceConfigBuffer = ExAllocatePool(NonPagedPoolCacheAligned, ! 827: sizeof(MODE_DEVICE_CONFIG_PAGE)); ! 828: ! 829: if (!deviceConfigBuffer) { ! 830: DebugPrint((1,"TapeGetMediaParameters: insufficient resources (deviceConfigBuffer)\n")); ! 831: ExFreePool(mediaInfoBuffer); ! 832: return STATUS_INSUFFICIENT_RESOURCES; ! 833: } ! 834: ! 835: RtlZeroMemory(deviceConfigBuffer, sizeof(MODE_DEVICE_CONFIG_PAGE)); ! 836: ! 837: // ! 838: // Zero CDB in SRB on stack. ! 839: // ! 840: ! 841: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 842: ! 843: // ! 844: // Prepare SCSI command (CDB) ! 845: // ! 846: ! 847: srb.CdbLength = CDB6GENERIC_LENGTH; ! 848: ! 849: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; ! 850: cdb->MODE_SENSE.Dbd = SETBITON; ! 851: cdb->MODE_SENSE.PageCode = MODE_PAGE_DEVICE_CONFIG; ! 852: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DEVICE_CONFIG_PAGE); ! 853: ! 854: // ! 855: // Set timeout value. ! 856: // ! 857: ! 858: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 859: ! 860: // ! 861: // Send SCSI command (CDB) to device ! 862: // ! 863: ! 864: DebugPrint((3,"TapeGetMediaParameters: SendSrb (mode sense #2)\n")); ! 865: ! 866: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 867: &srb, ! 868: deviceConfigBuffer, ! 869: sizeof(MODE_DEVICE_CONFIG_PAGE), ! 870: FALSE); ! 871: ! 872: if (!NT_SUCCESS(status)) { ! 873: DebugPrint((1,"TapeGetMediaParameters: mode sense #2, SendSrb unsuccessful\n")); ! 874: ExFreePool(deviceConfigBuffer); ! 875: ExFreePool(mediaInfoBuffer); ! 876: return status; ! 877: } ! 878: ! 879: tapeData->CurrentPartition = ! 880: deviceConfigBuffer->DeviceConfigPage.ActivePartition? ! 881: DIRECTORY_PARTITION : DATA_PARTITION; ! 882: ! 883: tapeGetMediaParams->PartitionCount = 2; ! 884: ! 885: ExFreePool(deviceConfigBuffer); ! 886: ! 887: } else { ! 888: ! 889: tapeGetMediaParams->PartitionCount = 1 ; ! 890: ! 891: tapeData->CurrentPartition = NO_PARTITIONS; ! 892: ! 893: } ! 894: ! 895: tapeGetMediaParams->BlockSize = mediaInfoBuffer->ParameterListBlock.BlockLength[2]; ! 896: tapeGetMediaParams->BlockSize += (mediaInfoBuffer->ParameterListBlock.BlockLength[1] << 8); ! 897: tapeGetMediaParams->BlockSize += (mediaInfoBuffer->ParameterListBlock.BlockLength[0] << 16); ! 898: ! 899: WHICH_BIT(tapeGetMediaParams->BlockSize, sectorShift); ! 900: deviceExtension->DiskGeometry->BytesPerSector = tapeGetMediaParams->BlockSize; ! 901: deviceExtension->SectorShift = sectorShift; ! 902: ! 903: tapeGetMediaParams->WriteProtected = ! 904: ((mediaInfoBuffer->ParameterListHeader.DeviceSpecificParameter >> 7) & 0x01); ! 905: ! 906: ExFreePool(mediaInfoBuffer); ! 907: ! 908: return status; ! 909: ! 910: } // end TapeGetMediaParameters() ! 911: ! 912: ! 913: NTSTATUS ! 914: TapeGetPosition( ! 915: IN PDEVICE_OBJECT DeviceObject, ! 916: IN PIRP Irp ! 917: ) ! 918: ! 919: /*++ ! 920: Routine Description: ! 921: ! 922: This routine returns the current position of the tape. ! 923: ! 924: Arguments: ! 925: ! 926: DeviceObject ! 927: Irp ! 928: ! 929: Return Value: ! 930: ! 931: NTSTATUS ! 932: ! 933: --*/ ! 934: ! 935: { ! 936: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 937: PTAPE_GET_POSITION tapeGetPosition = Irp->AssociatedIrp.SystemBuffer; ! 938: PTAPE_DATA tapeData = (PTAPE_DATA)(deviceExtension + 1); ! 939: PMODE_TAPE_MEDIA_INFORMATION mediaInfoBuffer; ! 940: PMODE_DEVICE_CONFIG_PAGE deviceConfigBuffer; ! 941: PTAPE_POSITION_DATA absoluteBuffer; ! 942: UCHAR densityCode; ! 943: ULONG tapeBlockLength; ! 944: ULONG tapeBlockAddress; ! 945: ULONG type; ! 946: SCSI_REQUEST_BLOCK srb; ! 947: PCDB cdb = (PCDB)srb.Cdb; ! 948: NTSTATUS status; ! 949: ! 950: DebugPrint((3,"TapeGetPosition: Enter routine\n")); ! 951: ! 952: type = tapeGetPosition->Type; ! 953: RtlZeroMemory(tapeGetPosition, sizeof(TAPE_GET_POSITION)); ! 954: Irp->IoStatus.Information = sizeof(TAPE_GET_POSITION); ! 955: tapeGetPosition->Type = type; ! 956: ! 957: // ! 958: // Zero CDB in SRB on stack. ! 959: // ! 960: ! 961: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 962: ! 963: // ! 964: // Prepare SCSI command (CDB) ! 965: // ! 966: ! 967: srb.CdbLength = CDB6GENERIC_LENGTH; ! 968: ! 969: cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY; ! 970: ! 971: // ! 972: // Set timeout value. ! 973: // ! 974: ! 975: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 976: ! 977: // ! 978: // Send SCSI command (CDB) to device ! 979: // ! 980: ! 981: DebugPrint((3,"TapeGetPosition: SendSrb (test unit ready)\n")); ! 982: ! 983: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 984: &srb, ! 985: NULL, ! 986: 0, ! 987: FALSE); ! 988: ! 989: if (!NT_SUCCESS(status)) { ! 990: DebugPrint((1,"TapeGetPosition: test unit ready, SendSrb unsuccessful\n")); ! 991: return status; ! 992: } ! 993: ! 994: if (type == TAPE_LOGICAL_POSITION) { ! 995: ! 996: DebugPrint((3,"TapeGetPosition: pseudo logical\n")); ! 997: ! 998: type = TAPE_PSEUDO_LOGICAL_POSITION; ! 999: ! 1000: mediaInfoBuffer = ExAllocatePool(NonPagedPoolCacheAligned, ! 1001: sizeof(MODE_TAPE_MEDIA_INFORMATION)); ! 1002: ! 1003: if (!mediaInfoBuffer) { ! 1004: DebugPrint((1,"TapeGetPosition: insufficient resources (mediaInfoBuffer)\n")); ! 1005: return STATUS_INSUFFICIENT_RESOURCES; ! 1006: } ! 1007: ! 1008: RtlZeroMemory(mediaInfoBuffer, sizeof(MODE_TAPE_MEDIA_INFORMATION)); ! 1009: ! 1010: // ! 1011: // Zero CDB in SRB on stack. ! 1012: // ! 1013: ! 1014: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 1015: ! 1016: // ! 1017: // Prepare SCSI command (CDB) ! 1018: // ! 1019: ! 1020: srb.CdbLength = CDB6GENERIC_LENGTH; ! 1021: ! 1022: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; ! 1023: cdb->MODE_SENSE.PageCode = MODE_PAGE_MEDIUM_PARTITION; ! 1024: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_TAPE_MEDIA_INFORMATION) - 4; ! 1025: ! 1026: // ! 1027: // Set timeout value. ! 1028: // ! 1029: ! 1030: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 1031: ! 1032: // ! 1033: // Send SCSI command (CDB) to device ! 1034: // ! 1035: ! 1036: DebugPrint((3,"TapeGetPosition: SendSrb (mode sense #1)\n")); ! 1037: ! 1038: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 1039: &srb, ! 1040: mediaInfoBuffer, ! 1041: sizeof(MODE_TAPE_MEDIA_INFORMATION) - 4, ! 1042: FALSE); ! 1043: ! 1044: if (!NT_SUCCESS(status)) { ! 1045: DebugPrint((1,"TapeGetPosition: mode sense #1, SendSrb unsuccessful\n")); ! 1046: ExFreePool(mediaInfoBuffer); ! 1047: return status; ! 1048: } ! 1049: ! 1050: if (mediaInfoBuffer->MediumPartPage.FDPBit) { ! 1051: ! 1052: deviceConfigBuffer = ExAllocatePool(NonPagedPoolCacheAligned, ! 1053: sizeof(MODE_DEVICE_CONFIG_PAGE)); ! 1054: ! 1055: if (!deviceConfigBuffer) { ! 1056: DebugPrint((1,"TapeGetPosition: insufficient resources (deviceConfigBuffer)\n")); ! 1057: ExFreePool(mediaInfoBuffer); ! 1058: return STATUS_INSUFFICIENT_RESOURCES; ! 1059: } ! 1060: ! 1061: RtlZeroMemory(deviceConfigBuffer, sizeof(MODE_DEVICE_CONFIG_PAGE)); ! 1062: ! 1063: // ! 1064: // Zero CDB in SRB on stack. ! 1065: // ! 1066: ! 1067: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 1068: ! 1069: // ! 1070: // Prepare SCSI command (CDB) ! 1071: // ! 1072: ! 1073: srb.CdbLength = CDB6GENERIC_LENGTH; ! 1074: ! 1075: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; ! 1076: cdb->MODE_SENSE.Dbd = SETBITON; ! 1077: cdb->MODE_SENSE.PageCode = MODE_PAGE_DEVICE_CONFIG; ! 1078: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DEVICE_CONFIG_PAGE); ! 1079: ! 1080: // ! 1081: // Set timeout value. ! 1082: // ! 1083: ! 1084: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 1085: ! 1086: // ! 1087: // Send SCSI command (CDB) to device ! 1088: // ! 1089: ! 1090: DebugPrint((3,"TapeGetPosition: SendSrb (mode sense #2)\n")); ! 1091: ! 1092: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 1093: &srb, ! 1094: deviceConfigBuffer, ! 1095: sizeof(MODE_DEVICE_CONFIG_PAGE), ! 1096: FALSE); ! 1097: ! 1098: if (!NT_SUCCESS(status)) { ! 1099: DebugPrint((1,"TapeGetPosition: mode sense #2, SendSrb unsuccessful\n")); ! 1100: ExFreePool(deviceConfigBuffer); ! 1101: ExFreePool(mediaInfoBuffer); ! 1102: return status; ! 1103: } ! 1104: ! 1105: tapeData->CurrentPartition = ! 1106: deviceConfigBuffer->DeviceConfigPage.ActivePartition? ! 1107: DIRECTORY_PARTITION : DATA_PARTITION; ! 1108: ! 1109: ExFreePool(deviceConfigBuffer); ! 1110: ! 1111: } else { ! 1112: ! 1113: tapeData->CurrentPartition = NO_PARTITIONS; ! 1114: ! 1115: } ! 1116: ! 1117: densityCode = mediaInfoBuffer->ParameterListBlock.DensityCode; ! 1118: tapeBlockLength = mediaInfoBuffer->ParameterListBlock.BlockLength[2]; ! 1119: tapeBlockLength += (mediaInfoBuffer->ParameterListBlock.BlockLength[1] << 8); ! 1120: tapeBlockLength += (mediaInfoBuffer->ParameterListBlock.BlockLength[0] << 16); ! 1121: ! 1122: ExFreePool(mediaInfoBuffer); ! 1123: ! 1124: } ! 1125: ! 1126: switch (type) { ! 1127: case TAPE_PSEUDO_LOGICAL_POSITION: ! 1128: case TAPE_ABSOLUTE_POSITION: ! 1129: absoluteBuffer = ExAllocatePool(NonPagedPoolCacheAligned, ! 1130: sizeof(TAPE_POSITION_DATA)); ! 1131: ! 1132: if (!absoluteBuffer) { ! 1133: DebugPrint((1,"TapeGetPosition: insufficient resources (absoluteBuffer)\n")); ! 1134: return STATUS_INSUFFICIENT_RESOURCES; ! 1135: } ! 1136: ! 1137: RtlZeroMemory(absoluteBuffer, sizeof(TAPE_POSITION_DATA)); ! 1138: ! 1139: // ! 1140: // Zero CDB in SRB on stack. ! 1141: // ! 1142: ! 1143: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 1144: ! 1145: // ! 1146: // Prepare SCSI command (CDB) ! 1147: // ! 1148: ! 1149: srb.CdbLength = CDB10GENERIC_LENGTH; ! 1150: ! 1151: cdb->READ_POSITION.Operation = SCSIOP_READ_POSITION; ! 1152: cdb->READ_POSITION.BlockType = SETBITON; ! 1153: ! 1154: // ! 1155: // Set timeout value. ! 1156: // ! 1157: ! 1158: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 1159: ! 1160: // ! 1161: // Send SCSI command (CDB) to device ! 1162: // ! 1163: ! 1164: DebugPrint((3,"TapeGetPosition: SendSrb (read position)\n")); ! 1165: ! 1166: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 1167: &srb, ! 1168: absoluteBuffer, ! 1169: sizeof(TAPE_POSITION_DATA), ! 1170: FALSE); ! 1171: ! 1172: if (NT_SUCCESS(status)) { ! 1173: ! 1174: REVERSE_BYTES((PFOUR_BYTE)&tapeBlockAddress, ! 1175: (PFOUR_BYTE)absoluteBuffer->FirstBlock); ! 1176: } ! 1177: ! 1178: ExFreePool(absoluteBuffer); ! 1179: ! 1180: if (!NT_SUCCESS(status)) { ! 1181: DebugPrint((1,"TapeGetPosition: read position, SendSrb unsuccessful\n")); ! 1182: return status; ! 1183: } ! 1184: ! 1185: if (type == TAPE_ABSOLUTE_POSITION) { ! 1186: tapeGetPosition->Partition = 0; ! 1187: tapeGetPosition->Offset.HighPart = 0; ! 1188: tapeGetPosition->Offset.LowPart = tapeBlockAddress; ! 1189: break; ! 1190: } ! 1191: ! 1192: tapeBlockAddress = ! 1193: TapePhysicalBlockToLogicalBlock( ! 1194: densityCode, ! 1195: tapeBlockAddress, ! 1196: tapeBlockLength, ! 1197: (BOOLEAN)( ! 1198: (tapeData->CurrentPartition ! 1199: == DIRECTORY_PARTITION)? ! 1200: NOT_FROM_BOT : FROM_BOT ! 1201: ) ! 1202: ); ! 1203: ! 1204: tapeGetPosition->Offset.HighPart = 0; ! 1205: tapeGetPosition->Offset.LowPart = tapeBlockAddress; ! 1206: tapeGetPosition->Partition = tapeData->CurrentPartition; ! 1207: break; ! 1208: ! 1209: default: ! 1210: DebugPrint((1,"TapeGetPosition: PositionType -- operation not supported\n")); ! 1211: return STATUS_NOT_IMPLEMENTED; ! 1212: } ! 1213: ! 1214: return status; ! 1215: ! 1216: } // end TapeGetPosition() ! 1217: ! 1218: ! 1219: NTSTATUS ! 1220: TapeGetStatus( ! 1221: IN PDEVICE_OBJECT DeviceObject, ! 1222: IN PIRP Irp ! 1223: ) ! 1224: ! 1225: /*++ ! 1226: Routine Description: ! 1227: ! 1228: This routine returns the status of the device. ! 1229: ! 1230: Arguments: ! 1231: ! 1232: DeviceObject ! 1233: Irp ! 1234: ! 1235: Return Value: ! 1236: ! 1237: NTSTATUS ! 1238: ! 1239: --*/ ! 1240: ! 1241: { ! 1242: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 1243: SCSI_REQUEST_BLOCK srb; ! 1244: PCDB cdb = (PCDB)srb.Cdb; ! 1245: NTSTATUS status; ! 1246: ! 1247: DebugPrint((3,"TapeGetStatus: Enter routine\n")); ! 1248: ! 1249: // ! 1250: // Zero CDB in SRB on stack. ! 1251: // ! 1252: ! 1253: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 1254: ! 1255: // ! 1256: // Prepare SCSI command (CDB) ! 1257: // ! 1258: ! 1259: srb.CdbLength = CDB6GENERIC_LENGTH; ! 1260: ! 1261: cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY; ! 1262: ! 1263: // ! 1264: // Set timeout value. ! 1265: // ! 1266: ! 1267: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 1268: ! 1269: // ! 1270: // Send SCSI command (CDB) to device ! 1271: // ! 1272: ! 1273: DebugPrint((3,"TapeGetStatus: SendSrb (test unit ready)\n")); ! 1274: ! 1275: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 1276: &srb, ! 1277: NULL, ! 1278: 0, ! 1279: FALSE); ! 1280: ! 1281: if (!NT_SUCCESS(status)) { ! 1282: DebugPrint((1,"TapeGetStatus: test unit ready, SendSrb unsuccessful\n")); ! 1283: } ! 1284: ! 1285: return status; ! 1286: ! 1287: } // end TapeGetStatus() ! 1288: ! 1289: ! 1290: NTSTATUS ! 1291: TapePrepare( ! 1292: IN PDEVICE_OBJECT DeviceObject, ! 1293: IN PIRP Irp ! 1294: ) ! 1295: ! 1296: /*++ ! 1297: Routine Description: ! 1298: ! 1299: This routine loads, unloads, tensions, locks, or unlocks the tape. ! 1300: ! 1301: Arguments: ! 1302: ! 1303: DeviceObject ! 1304: Irp ! 1305: ! 1306: Return Value: ! 1307: ! 1308: NTSTATUS ! 1309: ! 1310: --*/ ! 1311: ! 1312: { ! 1313: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 1314: PTAPE_PREPARE tapePrepare = Irp->AssociatedIrp.SystemBuffer; ! 1315: SCSI_REQUEST_BLOCK srb; ! 1316: PCDB cdb = (PCDB)srb.Cdb; ! 1317: NTSTATUS status; ! 1318: ! 1319: DebugPrint((3,"TapePrepare: Enter routine\n")); ! 1320: ! 1321: if (tapePrepare->Immediate) { ! 1322: switch (tapePrepare->Operation) { ! 1323: case TAPE_LOAD: ! 1324: case TAPE_UNLOAD: ! 1325: case TAPE_TENSION: ! 1326: DebugPrint((3,"TapePrepare: immediate\n")); ! 1327: break; ! 1328: ! 1329: case TAPE_LOCK: ! 1330: case TAPE_UNLOCK: ! 1331: default: ! 1332: DebugPrint((1,"TapePrepare: Operation, immediate -- operation not supported\n")); ! 1333: return STATUS_NOT_IMPLEMENTED; ! 1334: } ! 1335: } ! 1336: ! 1337: // ! 1338: // Zero CDB in SRB on stack. ! 1339: // ! 1340: ! 1341: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 1342: ! 1343: // ! 1344: // Prepare SCSI command (CDB) ! 1345: // ! 1346: ! 1347: srb.CdbLength = CDB6GENERIC_LENGTH; ! 1348: ! 1349: cdb->CDB6GENERIC.Immediate = tapePrepare->Immediate; ! 1350: ! 1351: switch (tapePrepare->Operation) { ! 1352: case TAPE_LOAD: ! 1353: DebugPrint((3,"TapePrepare: Operation == load\n")); ! 1354: cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD; ! 1355: cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x01; ! 1356: srb.TimeOutValue = 180; ! 1357: break; ! 1358: ! 1359: case TAPE_UNLOAD: ! 1360: DebugPrint((3,"TapePrepare: Operation == unload\n")); ! 1361: cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD; ! 1362: srb.TimeOutValue = 180; ! 1363: break; ! 1364: ! 1365: case TAPE_TENSION: ! 1366: DebugPrint((3,"TapePrepare: Operation == tension\n")); ! 1367: cdb->CDB6GENERIC.OperationCode = SCSIOP_LOAD_UNLOAD; ! 1368: cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x03; ! 1369: srb.TimeOutValue = 360; ! 1370: break; ! 1371: ! 1372: case TAPE_LOCK: ! 1373: DebugPrint((3,"TapePrepare: Operation == lock\n")); ! 1374: cdb->CDB6GENERIC.OperationCode = SCSIOP_MEDIUM_REMOVAL; ! 1375: cdb->CDB6GENERIC.CommandUniqueBytes[2] = 0x01; ! 1376: srb.TimeOutValue = 180; ! 1377: break; ! 1378: ! 1379: case TAPE_UNLOCK: ! 1380: DebugPrint((3,"TapePrepare: Operation == unlock\n")); ! 1381: cdb->CDB6GENERIC.OperationCode = SCSIOP_MEDIUM_REMOVAL; ! 1382: srb.TimeOutValue = 180; ! 1383: break; ! 1384: ! 1385: default: ! 1386: DebugPrint((1,"TapePrepare: Operation -- operation not supported\n")); ! 1387: return STATUS_NOT_IMPLEMENTED; ! 1388: } ! 1389: ! 1390: // ! 1391: // Send SCSI command (CDB) to device ! 1392: // ! 1393: ! 1394: DebugPrint((3,"TapePrepare: SendSrb (Operation)\n")); ! 1395: ! 1396: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 1397: &srb, ! 1398: NULL, ! 1399: 0, ! 1400: FALSE); ! 1401: ! 1402: if (!NT_SUCCESS(status)) { ! 1403: DebugPrint((1,"TapePrepare: Operation, SendSrb unsuccessful\n")); ! 1404: } ! 1405: ! 1406: return status; ! 1407: ! 1408: } // end TapePrepare() ! 1409: ! 1410: ! 1411: NTSTATUS ! 1412: TapeReadWrite( ! 1413: IN PDEVICE_OBJECT DeviceObject, ! 1414: IN PIRP Irp ! 1415: ) ! 1416: ! 1417: /*++ ! 1418: ! 1419: Routine Description: ! 1420: ! 1421: This routine builds SRBs and CDBs for read and write requests to ! 1422: Tandberg QIC drives. ! 1423: ! 1424: Arguments: ! 1425: ! 1426: DeviceObject ! 1427: Irp ! 1428: ! 1429: Return Value: ! 1430: ! 1431: Returns STATUS_PENDING. ! 1432: ! 1433: --*/ ! 1434: ! 1435: { ! 1436: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 1437: PIO_STACK_LOCATION currentIrpStack = IoGetCurrentIrpStackLocation(Irp); ! 1438: PIO_STACK_LOCATION nextIrpStack = IoGetNextIrpStackLocation(Irp); ! 1439: PSCSI_REQUEST_BLOCK srb; ! 1440: PCDB cdb; ! 1441: KIRQL currentIrql; ! 1442: ULONG transferBlocks; ! 1443: LARGE_INTEGER startingOffset = ! 1444: currentIrpStack->Parameters.Read.ByteOffset; ! 1445: ! 1446: DebugPrint((3,"TapeReadWrite: Enter routine\n")); ! 1447: ! 1448: // ! 1449: // Allocate an Srb. ! 1450: // ! 1451: ! 1452: if (deviceExtension->SrbZone != NULL && ! 1453: (srb = ExInterlockedAllocateFromZone( ! 1454: deviceExtension->SrbZone, ! 1455: deviceExtension->SrbZoneSpinLock)) != NULL) { ! 1456: ! 1457: srb->SrbFlags = SRB_FLAGS_ALLOCATED_FROM_ZONE; ! 1458: ! 1459: } else { ! 1460: ! 1461: // ! 1462: // Allocate Srb from non-paged pool. ! 1463: // This call must succeed. ! 1464: // ! 1465: ! 1466: srb = ExAllocatePool(NonPagedPoolMustSucceed, SCSI_REQUEST_BLOCK_SIZE); ! 1467: ! 1468: srb->SrbFlags = 0; ! 1469: ! 1470: } ! 1471: ! 1472: // ! 1473: // Write length to SRB. ! 1474: // ! 1475: ! 1476: srb->Length = SCSI_REQUEST_BLOCK_SIZE; ! 1477: ! 1478: // ! 1479: // Set up IRP Address. ! 1480: // ! 1481: ! 1482: srb->OriginalRequest = Irp; ! 1483: ! 1484: // ! 1485: // Set up target id and logical unit number. ! 1486: // ! 1487: ! 1488: srb->PathId = deviceExtension->PathId; ! 1489: srb->TargetId = deviceExtension->TargetId; ! 1490: srb->Lun = deviceExtension->Lun; ! 1491: ! 1492: ! 1493: srb->Function = SRB_FUNCTION_EXECUTE_SCSI; ! 1494: ! 1495: srb->DataBuffer = MmGetMdlVirtualAddress(Irp->MdlAddress); ! 1496: ! 1497: // ! 1498: // Save byte count of transfer in SRB Extension. ! 1499: // ! 1500: ! 1501: srb->DataTransferLength = currentIrpStack->Parameters.Read.Length; ! 1502: ! 1503: // ! 1504: // Indicate auto request sense by specifying buffer and size. ! 1505: // ! 1506: ! 1507: srb->SenseInfoBuffer = deviceExtension->SenseData; ! 1508: ! 1509: srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; ! 1510: ! 1511: // ! 1512: // Initialize the queue actions field. ! 1513: // ! 1514: ! 1515: srb->QueueAction = SRB_SIMPLE_TAG_REQUEST; ! 1516: ! 1517: // ! 1518: // Indicate auto request sense by specifying buffer and size. ! 1519: // ! 1520: ! 1521: srb->SenseInfoBuffer = deviceExtension->SenseData; ! 1522: ! 1523: srb->SenseInfoBufferLength = SENSE_BUFFER_SIZE; ! 1524: ! 1525: // ! 1526: // Set timeout value in seconds. ! 1527: // ! 1528: ! 1529: srb->TimeOutValue = deviceExtension->TimeOutValue; ! 1530: ! 1531: // ! 1532: // Zero statuses. ! 1533: // ! 1534: ! 1535: srb->SrbStatus = srb->ScsiStatus = 0; ! 1536: ! 1537: srb->NextSrb = 0; ! 1538: ! 1539: // ! 1540: // Indicate that 6-byte CDB's will be used. ! 1541: // ! 1542: ! 1543: srb->CdbLength = CDB6GENERIC_LENGTH; ! 1544: ! 1545: // ! 1546: // Fill in CDB fields. ! 1547: // ! 1548: ! 1549: cdb = (PCDB)srb->Cdb; ! 1550: ! 1551: // ! 1552: // Zero CDB in SRB. ! 1553: // ! 1554: ! 1555: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 1556: ! 1557: // ! 1558: // Since we are writing fixed block mode, normalize transfer count ! 1559: // to number of blocks. ! 1560: // ! 1561: ! 1562: transferBlocks = ! 1563: currentIrpStack->Parameters.Read.Length >> deviceExtension->SectorShift; ! 1564: ! 1565: // ! 1566: // Set up transfer length ! 1567: // ! 1568: ! 1569: cdb->CDB6READWRITETAPE.TransferLenMSB = (UCHAR)((transferBlocks >> 16) & 0xff); ! 1570: cdb->CDB6READWRITETAPE.TransferLen = (UCHAR)((transferBlocks >> 8) & 0xff); ! 1571: cdb->CDB6READWRITETAPE.TransferLenLSB = (UCHAR)(transferBlocks & 0xff); ! 1572: ! 1573: // ! 1574: // Tell the python we are in fixed block mode ! 1575: // ! 1576: ! 1577: cdb->CDB6READWRITETAPE.VendorSpecific = 1; ! 1578: ! 1579: // ! 1580: // Set transfer direction flag and Cdb command. ! 1581: // ! 1582: ! 1583: if (currentIrpStack->MajorFunction == IRP_MJ_READ) { ! 1584: ! 1585: DebugPrint((3, "TapeRequest: Read Command\n")); ! 1586: ! 1587: srb->SrbFlags = SRB_FLAGS_DATA_IN; ! 1588: cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_READ6; ! 1589: ! 1590: } else { ! 1591: ! 1592: DebugPrint((3, "TapeRequest: Write Command\n")); ! 1593: ! 1594: srb->SrbFlags = SRB_FLAGS_DATA_OUT; ! 1595: cdb->CDB6READWRITETAPE.OperationCode = SCSIOP_WRITE6; ! 1596: } ! 1597: ! 1598: // ! 1599: // Or in the default flags from the device object. ! 1600: // ! 1601: ! 1602: srb->SrbFlags |= deviceExtension->SrbFlags; ! 1603: ! 1604: // ! 1605: // Set up major SCSI function. ! 1606: // ! 1607: ! 1608: nextIrpStack->MajorFunction = IRP_MJ_SCSI; ! 1609: ! 1610: // ! 1611: // Save SRB address in next stack for port driver. ! 1612: // ! 1613: ! 1614: nextIrpStack->Parameters.Scsi.Srb = srb; ! 1615: ! 1616: // ! 1617: // Save retry count in current IRP stack. ! 1618: // ! 1619: ! 1620: currentIrpStack->Parameters.Others.Argument4 = (PVOID)MAXIMUM_RETRIES; ! 1621: ! 1622: // ! 1623: // Set up IoCompletion routine address. ! 1624: // ! 1625: ! 1626: IoSetCompletionRoutine(Irp, ! 1627: ScsiClassIoComplete, ! 1628: srb, ! 1629: TRUE, ! 1630: TRUE, ! 1631: FALSE); ! 1632: ! 1633: return STATUS_PENDING; ! 1634: ! 1635: } // end TapeReadWrite() ! 1636: ! 1637: ! 1638: NTSTATUS ! 1639: TapeSetDriveParameters( ! 1640: IN PDEVICE_OBJECT DeviceObject, ! 1641: IN PIRP Irp ! 1642: ) ! 1643: ! 1644: /*++ ! 1645: Routine Description: ! 1646: ! 1647: This routine would "set" the "drive parameters" of the Tandberg QIC ! 1648: tape drive associated with "DeviceObject" if any could be set, but ! 1649: none can! Hence, this routine always returns a STATUS_NOT_IMPLEMENTED ! 1650: status. ! 1651: ! 1652: Arguments: ! 1653: ! 1654: DeviceObject ! 1655: Irp ! 1656: ! 1657: Return Value: ! 1658: ! 1659: NTSTATUS ! 1660: ! 1661: --*/ ! 1662: ! 1663: { ! 1664: DebugPrint((3,"TapeSetDriveParameters: Enter routine\n")); ! 1665: ! 1666: DebugPrint((1,"TapeSetDriveParameters: Operation -- operation not supported\n")); ! 1667: ! 1668: return STATUS_NOT_IMPLEMENTED; ! 1669: ! 1670: } // end TapeSetDriveParameters() ! 1671: ! 1672: ! 1673: ! 1674: NTSTATUS ! 1675: TapeSetMediaParameters( ! 1676: IN PDEVICE_OBJECT DeviceObject, ! 1677: IN PIRP Irp ! 1678: ) ! 1679: ! 1680: /*++ ! 1681: Routine Description: ! 1682: ! 1683: This routine "sets" the "media parameters" of the Tandberg QIC tape ! 1684: drive associated with "DeviceObject". Tape media must be present ! 1685: (loaded) in the drive for this function to return "no error". ! 1686: ! 1687: Arguments: ! 1688: ! 1689: DeviceObject ! 1690: Irp ! 1691: ! 1692: Return Value: ! 1693: ! 1694: NTSTATUS ! 1695: ! 1696: --*/ ! 1697: ! 1698: { ! 1699: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 1700: PTAPE_SET_MEDIA_PARAMETERS tapeSetMediaParams = Irp->AssociatedIrp.SystemBuffer; ! 1701: PMODE_PARM_READ_WRITE_DATA modeBuffer; ! 1702: PINQUIRYDATA inquiryBuffer; ! 1703: ULONG whichdrive; ! 1704: SCSI_REQUEST_BLOCK srb; ! 1705: PCDB cdb = (PCDB)srb.Cdb; ! 1706: NTSTATUS status; ! 1707: ! 1708: DebugPrint((3,"TapeSetMediaParameters: Enter routine\n")); ! 1709: ! 1710: inquiryBuffer = ExAllocatePool(NonPagedPoolCacheAligned, ! 1711: sizeof(INQUIRYDATA)); ! 1712: ! 1713: if (!inquiryBuffer) { ! 1714: DebugPrint((1,"TapeSetMediaParameters: insufficient resources (inquiryBuffer)\n")); ! 1715: return STATUS_INSUFFICIENT_RESOURCES; ! 1716: } ! 1717: ! 1718: RtlZeroMemory(inquiryBuffer, sizeof(INQUIRYDATA)); ! 1719: ! 1720: // ! 1721: // Send SCSI command (CDB) to device ! 1722: // ! 1723: ! 1724: DebugPrint((3,"TapeSetMediaParameters: SendSrb (inquiry)\n")); ! 1725: ! 1726: status = GetInquiryInformationData(DeviceObject, Irp, inquiryBuffer); ! 1727: ! 1728: if (NT_SUCCESS(status)) { ! 1729: ! 1730: // ! 1731: // Which drive do we have, TDC 3660, 3820, 4120 or 4220? ! 1732: // ! 1733: ! 1734: whichdrive = WhichIsIt(inquiryBuffer); ! 1735: } ! 1736: ! 1737: ExFreePool(inquiryBuffer); ! 1738: ! 1739: if (!NT_SUCCESS(status)) { ! 1740: DebugPrint((1,"TapeSetMediaParameters: inquiry, SendSrb unsuccessful\n")); ! 1741: return status; ! 1742: } ! 1743: ! 1744: if (whichdrive == TDC_3600) { ! 1745: DebugPrint((1,"TapeSetMediaParameters: whichdrive -- operation not supported\n")); ! 1746: return STATUS_NOT_IMPLEMENTED; ! 1747: } ! 1748: ! 1749: // ! 1750: // Zero CDB in SRB on stack. ! 1751: // ! 1752: ! 1753: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 1754: ! 1755: // ! 1756: // Prepare SCSI command (CDB) ! 1757: // ! 1758: ! 1759: srb.CdbLength = CDB6GENERIC_LENGTH; ! 1760: ! 1761: cdb->CDB6GENERIC.OperationCode = SCSIOP_TEST_UNIT_READY; ! 1762: ! 1763: // ! 1764: // Set timeout value. ! 1765: // ! 1766: ! 1767: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 1768: ! 1769: // ! 1770: // Send SCSI command (CDB) to device ! 1771: // ! 1772: ! 1773: DebugPrint((3,"TapeSetMediaParameters: SendSrb (test unit ready)\n")); ! 1774: ! 1775: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 1776: &srb, ! 1777: NULL, ! 1778: 0, ! 1779: FALSE); ! 1780: ! 1781: if (!NT_SUCCESS(status)) { ! 1782: DebugPrint((1,"TapeSetMediaParameters: test unit ready, SendSrb unsuccessful\n")); ! 1783: return status; ! 1784: } ! 1785: ! 1786: modeBuffer = ExAllocatePool(NonPagedPoolCacheAligned, ! 1787: sizeof(MODE_PARM_READ_WRITE_DATA)); ! 1788: ! 1789: if (!modeBuffer) { ! 1790: DebugPrint((1,"TapeSetMediaParameters: insufficient resources (modeBuffer)\n")); ! 1791: return STATUS_INSUFFICIENT_RESOURCES; ! 1792: } ! 1793: ! 1794: RtlZeroMemory(modeBuffer, sizeof(MODE_PARM_READ_WRITE_DATA)); ! 1795: ! 1796: modeBuffer->ParameterListHeader.DeviceSpecificParameter = 0x10; ! 1797: modeBuffer->ParameterListHeader.BlockDescriptorLength = MODE_BLOCK_DESC_LENGTH; ! 1798: ! 1799: modeBuffer->ParameterListBlock.DensityCode = 0x7F; ! 1800: modeBuffer->ParameterListBlock.BlockLength[0] = ! 1801: ((tapeSetMediaParams->BlockSize >> 16) & 0xFF); ! 1802: modeBuffer->ParameterListBlock.BlockLength[1] = ! 1803: ((tapeSetMediaParams->BlockSize >> 8) & 0xFF); ! 1804: modeBuffer->ParameterListBlock.BlockLength[2] = ! 1805: (tapeSetMediaParams->BlockSize & 0xFF); ! 1806: ! 1807: // ! 1808: // Zero CDB in SRB on stack. ! 1809: // ! 1810: ! 1811: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 1812: ! 1813: // ! 1814: // Prepare SCSI command (CDB) ! 1815: // ! 1816: ! 1817: srb.CdbLength = CDB6GENERIC_LENGTH; ! 1818: ! 1819: cdb->MODE_SELECT.OperationCode = SCSIOP_MODE_SELECT; ! 1820: cdb->MODE_SELECT.ParameterListLength = sizeof(MODE_PARM_READ_WRITE_DATA); ! 1821: ! 1822: // ! 1823: // Set timeout value. ! 1824: // ! 1825: ! 1826: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 1827: ! 1828: // ! 1829: // Send SCSI command (CDB) to device ! 1830: // ! 1831: ! 1832: DebugPrint((3,"TapeSetMediaParameters: SendSrb (mode select)\n")); ! 1833: ! 1834: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 1835: &srb, ! 1836: modeBuffer, ! 1837: sizeof(MODE_PARM_READ_WRITE_DATA), ! 1838: TRUE); ! 1839: ! 1840: ExFreePool(modeBuffer); ! 1841: ! 1842: if (!NT_SUCCESS(status)) { ! 1843: DebugPrint((1,"TapeSetMediaParameters: mode select, SendSrb unsuccessful\n")); ! 1844: } ! 1845: ! 1846: return status; ! 1847: ! 1848: } // end TapeSetMediaParameters() ! 1849: ! 1850: ! 1851: NTSTATUS ! 1852: TapeSetPosition( ! 1853: IN PDEVICE_OBJECT DeviceObject, ! 1854: IN PIRP Irp ! 1855: ) ! 1856: ! 1857: /*++ ! 1858: Routine Description: ! 1859: ! 1860: This routine sets the position of the tape. ! 1861: ! 1862: Arguments: ! 1863: ! 1864: DeviceObject ! 1865: Irp ! 1866: ! 1867: Return Value: ! 1868: ! 1869: NTSTATUS ! 1870: ! 1871: --*/ ! 1872: ! 1873: { ! 1874: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 1875: PTAPE_SET_POSITION tapeSetPosition = Irp->AssociatedIrp.SystemBuffer; ! 1876: PTAPE_DATA tapeData = (PTAPE_DATA)(deviceExtension + 1); ! 1877: BOOLEAN changePartition = FALSE; ! 1878: PMODE_TAPE_MEDIA_INFORMATION mediaInfoBuffer; ! 1879: PMODE_DEVICE_CONFIG_PAGE deviceConfigBuffer; ! 1880: TAPE_PHYS_POSITION physPosition; ! 1881: UCHAR densityCode; ! 1882: ULONG tapePositionVector; ! 1883: ULONG tapeBlockLength; ! 1884: ULONG method; ! 1885: SCSI_REQUEST_BLOCK srb; ! 1886: PCDB cdb = (PCDB)srb.Cdb; ! 1887: NTSTATUS status; ! 1888: ! 1889: DebugPrint((3,"TapeSetPosition: Enter routine\n")); ! 1890: ! 1891: if (tapeSetPosition->Immediate) { ! 1892: switch (tapeSetPosition->Method) { ! 1893: case TAPE_REWIND: ! 1894: DebugPrint((3,"TapeSetPosition: immediate\n")); ! 1895: break; ! 1896: ! 1897: case TAPE_LOGICAL_BLOCK: ! 1898: case TAPE_ABSOLUTE_BLOCK: ! 1899: case TAPE_SPACE_END_OF_DATA: ! 1900: case TAPE_SPACE_RELATIVE_BLOCKS: ! 1901: case TAPE_SPACE_FILEMARKS: ! 1902: case TAPE_SPACE_SEQUENTIAL_FMKS: ! 1903: case TAPE_SPACE_SETMARKS: ! 1904: case TAPE_SPACE_SEQUENTIAL_SMKS: ! 1905: default: ! 1906: DebugPrint((1,"TapeSetPosition: PositionMethod, immediate -- operation not supported\n")); ! 1907: return STATUS_NOT_IMPLEMENTED; ! 1908: } ! 1909: } ! 1910: ! 1911: method = tapeSetPosition->Method; ! 1912: tapePositionVector = tapeSetPosition->Offset.LowPart; ! 1913: ! 1914: if (method == TAPE_LOGICAL_BLOCK) { ! 1915: ! 1916: DebugPrint((3,"TapeSetPosition: pseudo logical\n")); ! 1917: ! 1918: method = TAPE_PSEUDO_LOGICAL_BLOCK; ! 1919: ! 1920: mediaInfoBuffer = ExAllocatePool(NonPagedPoolCacheAligned, ! 1921: sizeof(MODE_TAPE_MEDIA_INFORMATION)); ! 1922: ! 1923: if (!mediaInfoBuffer) { ! 1924: DebugPrint((1,"TapeSetPosition: insufficient resources (mediaInfoBuffer)\n")); ! 1925: return STATUS_INSUFFICIENT_RESOURCES; ! 1926: } ! 1927: ! 1928: RtlZeroMemory(mediaInfoBuffer, sizeof(MODE_TAPE_MEDIA_INFORMATION)); ! 1929: ! 1930: // ! 1931: // Zero CDB in SRB on stack. ! 1932: // ! 1933: ! 1934: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 1935: ! 1936: // ! 1937: // Prepare SCSI command (CDB) ! 1938: // ! 1939: ! 1940: srb.CdbLength = CDB6GENERIC_LENGTH; ! 1941: ! 1942: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; ! 1943: cdb->MODE_SENSE.PageCode = MODE_PAGE_MEDIUM_PARTITION; ! 1944: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_TAPE_MEDIA_INFORMATION) - 4; ! 1945: ! 1946: // ! 1947: // Set timeout value. ! 1948: // ! 1949: ! 1950: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 1951: ! 1952: // ! 1953: // Send SCSI command (CDB) to device ! 1954: // ! 1955: ! 1956: DebugPrint((3,"TapeSetPosition: SendSrb (mode sense #1)\n")); ! 1957: ! 1958: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 1959: &srb, ! 1960: mediaInfoBuffer, ! 1961: sizeof(MODE_TAPE_MEDIA_INFORMATION) - 4, ! 1962: FALSE); ! 1963: ! 1964: if (!NT_SUCCESS(status)) { ! 1965: DebugPrint((1,"TapeSetPosition: mode sense #1, SendSrb unsuccessful\n")); ! 1966: ExFreePool(mediaInfoBuffer); ! 1967: return status; ! 1968: } ! 1969: ! 1970: if (mediaInfoBuffer->MediumPartPage.FDPBit) { ! 1971: ! 1972: deviceConfigBuffer = ExAllocatePool(NonPagedPoolCacheAligned, ! 1973: sizeof(MODE_DEVICE_CONFIG_PAGE)); ! 1974: ! 1975: if (!deviceConfigBuffer) { ! 1976: DebugPrint((1,"TapeSetPosition: insufficient resources (deviceConfigBuffer)\n")); ! 1977: ExFreePool(mediaInfoBuffer); ! 1978: return STATUS_INSUFFICIENT_RESOURCES; ! 1979: } ! 1980: ! 1981: RtlZeroMemory(deviceConfigBuffer, sizeof(MODE_DEVICE_CONFIG_PAGE)); ! 1982: ! 1983: // ! 1984: // Zero CDB in SRB on stack. ! 1985: // ! 1986: ! 1987: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 1988: ! 1989: // ! 1990: // Prepare SCSI command (CDB) ! 1991: // ! 1992: ! 1993: srb.CdbLength = CDB6GENERIC_LENGTH; ! 1994: ! 1995: cdb->MODE_SENSE.OperationCode = SCSIOP_MODE_SENSE; ! 1996: cdb->MODE_SENSE.Dbd = SETBITON; ! 1997: cdb->MODE_SENSE.PageCode = MODE_PAGE_DEVICE_CONFIG; ! 1998: cdb->MODE_SENSE.AllocationLength = sizeof(MODE_DEVICE_CONFIG_PAGE); ! 1999: ! 2000: // ! 2001: // Set timeout value. ! 2002: // ! 2003: ! 2004: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 2005: ! 2006: // ! 2007: // Send SCSI command (CDB) to device ! 2008: // ! 2009: ! 2010: DebugPrint((3,"TapeSetPosition: SendSrb (mode sense #2)\n")); ! 2011: ! 2012: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 2013: &srb, ! 2014: deviceConfigBuffer, ! 2015: sizeof(MODE_DEVICE_CONFIG_PAGE), ! 2016: FALSE); ! 2017: ! 2018: if (!NT_SUCCESS(status)) { ! 2019: DebugPrint((1,"TapeSetPosition: mode sense #2, SendSrb unsuccessful\n")); ! 2020: ExFreePool(deviceConfigBuffer); ! 2021: ExFreePool(mediaInfoBuffer); ! 2022: return status; ! 2023: } ! 2024: ! 2025: tapeData->CurrentPartition = ! 2026: deviceConfigBuffer->DeviceConfigPage.ActivePartition? ! 2027: DIRECTORY_PARTITION : DATA_PARTITION; ! 2028: ! 2029: ExFreePool(deviceConfigBuffer); ! 2030: ! 2031: } else { ! 2032: ! 2033: tapeData->CurrentPartition = NO_PARTITIONS; ! 2034: ! 2035: } ! 2036: ! 2037: densityCode = mediaInfoBuffer->ParameterListBlock.DensityCode; ! 2038: tapeBlockLength = mediaInfoBuffer->ParameterListBlock.BlockLength[2]; ! 2039: tapeBlockLength += (mediaInfoBuffer->ParameterListBlock.BlockLength[1] << 8); ! 2040: tapeBlockLength += (mediaInfoBuffer->ParameterListBlock.BlockLength[0] << 16); ! 2041: ! 2042: ExFreePool(mediaInfoBuffer); ! 2043: ! 2044: switch (tapeSetPosition->Partition) { ! 2045: case 0: ! 2046: break; ! 2047: ! 2048: case DIRECTORY_PARTITION: ! 2049: case DATA_PARTITION: ! 2050: if (tapeData->CurrentPartition != NO_PARTITIONS) { ! 2051: if (tapeSetPosition->Partition ! 2052: != tapeData->CurrentPartition) { ! 2053: changePartition = TRUE; ! 2054: } ! 2055: break; ! 2056: } ! 2057: // else: fall through to next case ! 2058: ! 2059: default: ! 2060: DebugPrint((1,"TapeSetPosition: Partition -- invalid parameter\n")); ! 2061: return STATUS_INVALID_PARAMETER; ! 2062: } ! 2063: ! 2064: physPosition = ! 2065: TapeLogicalBlockToPhysicalBlock( ! 2066: densityCode, ! 2067: tapePositionVector, ! 2068: tapeBlockLength, ! 2069: (BOOLEAN)( ! 2070: (tapeData->CurrentPartition ! 2071: == DIRECTORY_PARTITION)? ! 2072: NOT_FROM_BOT : FROM_BOT ! 2073: ) ! 2074: ); ! 2075: ! 2076: tapePositionVector = physPosition.SeekBlockAddress; ! 2077: ! 2078: } ! 2079: ! 2080: // ! 2081: // Zero CDB in SRB on stack. ! 2082: // ! 2083: ! 2084: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 2085: ! 2086: // ! 2087: // Prepare SCSI command (CDB) ! 2088: // ! 2089: ! 2090: srb.CdbLength = CDB6GENERIC_LENGTH; ! 2091: ! 2092: cdb->CDB6GENERIC.Immediate = tapeSetPosition->Immediate; ! 2093: ! 2094: switch (method) { ! 2095: case TAPE_REWIND: ! 2096: DebugPrint((3,"TapeSetPosition: method == rewind\n")); ! 2097: cdb->CDB6GENERIC.OperationCode = SCSIOP_REWIND; ! 2098: srb.TimeOutValue = 180; ! 2099: break; ! 2100: ! 2101: case TAPE_PSEUDO_LOGICAL_BLOCK: ! 2102: case TAPE_ABSOLUTE_BLOCK: ! 2103: DebugPrint((3,"TapeSetPosition: method == locate (absolute)\n")); ! 2104: srb.CdbLength = CDB10GENERIC_LENGTH; ! 2105: cdb->LOCATE.OperationCode = SCSIOP_LOCATE; ! 2106: cdb->LOCATE.CPBit = changePartition? SETBITON : SETBITOFF; ! 2107: cdb->LOCATE.BTBit = SETBITON; ! 2108: cdb->LOCATE.LogicalBlockAddress[1] = ! 2109: ((tapePositionVector >> 16) & 0xFF); ! 2110: cdb->LOCATE.LogicalBlockAddress[2] = ! 2111: ((tapePositionVector >> 8) & 0xFF); ! 2112: cdb->LOCATE.LogicalBlockAddress[3] = ! 2113: (tapePositionVector & 0xFF); ! 2114: if (changePartition && ! 2115: (tapeSetPosition->Partition == DIRECTORY_PARTITION)) { ! 2116: cdb->LOCATE.Partition = 1; ! 2117: } ! 2118: srb.TimeOutValue = 480; ! 2119: if ((physPosition.SpaceBlockCount != 0) && ! 2120: (method == TAPE_PSEUDO_LOGICAL_BLOCK)) { ! 2121: ! 2122: // ! 2123: // Send SCSI command (CDB) to device ! 2124: // ! 2125: ! 2126: DebugPrint((3,"TapeSetPosition: SendSrb (locate)\n")); ! 2127: ! 2128: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 2129: &srb, ! 2130: NULL, ! 2131: 0, ! 2132: FALSE); ! 2133: ! 2134: if (!NT_SUCCESS(status)) { ! 2135: DebugPrint((1,"TapeSetPosition: locate, SendSrb unsuccessful\n")); ! 2136: return status; ! 2137: } ! 2138: ! 2139: // ! 2140: // Zero CDB in SRB on stack. ! 2141: // ! 2142: ! 2143: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 2144: ! 2145: // ! 2146: // Prepare SCSI command (CDB) ! 2147: // ! 2148: ! 2149: srb.CdbLength = CDB6GENERIC_LENGTH; ! 2150: ! 2151: DebugPrint((3,"TapeSetPosition: method == space block(s)\n")); ! 2152: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE; ! 2153: cdb->SPACE_TAPE_MARKS.Code = 0; ! 2154: cdb->SPACE_TAPE_MARKS.NumMarksMSB = ! 2155: ((physPosition.SpaceBlockCount >> 16) & 0xFF); ! 2156: cdb->SPACE_TAPE_MARKS.NumMarks = ! 2157: ((physPosition.SpaceBlockCount >> 8) & 0xFF); ! 2158: cdb->SPACE_TAPE_MARKS.NumMarksLSB = ! 2159: (physPosition.SpaceBlockCount & 0xFF); ! 2160: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 2161: ! 2162: } ! 2163: break; ! 2164: ! 2165: case TAPE_SPACE_END_OF_DATA: ! 2166: DebugPrint((3,"TapeSetPosition: method == space to end-of-data\n")); ! 2167: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE; ! 2168: cdb->SPACE_TAPE_MARKS.Code = 3; ! 2169: srb.TimeOutValue = 480; ! 2170: break; ! 2171: ! 2172: case TAPE_SPACE_RELATIVE_BLOCKS: ! 2173: DebugPrint((3,"TapeSetPosition: method == space blocks\n")); ! 2174: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE; ! 2175: cdb->SPACE_TAPE_MARKS.Code = 0; ! 2176: cdb->SPACE_TAPE_MARKS.NumMarksMSB = ! 2177: ((tapePositionVector >> 16) & 0xFF); ! 2178: cdb->SPACE_TAPE_MARKS.NumMarks = ! 2179: ((tapePositionVector >> 8) & 0xFF); ! 2180: cdb->SPACE_TAPE_MARKS.NumMarksLSB = ! 2181: (tapePositionVector & 0xFF); ! 2182: srb.TimeOutValue = 4100; ! 2183: break; ! 2184: ! 2185: case TAPE_SPACE_FILEMARKS: ! 2186: DebugPrint((3,"TapeSetPosition: method == space filemarks\n")); ! 2187: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE; ! 2188: cdb->SPACE_TAPE_MARKS.Code = 1; ! 2189: cdb->SPACE_TAPE_MARKS.NumMarksMSB = ! 2190: ((tapePositionVector >> 16) & 0xFF); ! 2191: cdb->SPACE_TAPE_MARKS.NumMarks = ! 2192: ((tapePositionVector >> 8) & 0xFF); ! 2193: cdb->SPACE_TAPE_MARKS.NumMarksLSB = ! 2194: (tapePositionVector & 0xFF); ! 2195: srb.TimeOutValue = 4100; ! 2196: break; ! 2197: ! 2198: case TAPE_SPACE_SEQUENTIAL_FMKS: ! 2199: DebugPrint((3,"TapeSetPosition: method == space sequential filemarks\n")); ! 2200: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE; ! 2201: cdb->SPACE_TAPE_MARKS.Code = 2; ! 2202: cdb->SPACE_TAPE_MARKS.NumMarksMSB = ! 2203: ((tapePositionVector >> 16) & 0xFF); ! 2204: cdb->SPACE_TAPE_MARKS.NumMarks = ! 2205: ((tapePositionVector >> 8) & 0xFF); ! 2206: cdb->SPACE_TAPE_MARKS.NumMarksLSB = ! 2207: (tapePositionVector & 0xFF); ! 2208: srb.TimeOutValue = 4100; ! 2209: break; ! 2210: ! 2211: case TAPE_SPACE_SETMARKS: ! 2212: DebugPrint((3,"TapeSetPosition: method == space setmarks\n")); ! 2213: cdb->SPACE_TAPE_MARKS.OperationCode = SCSIOP_SPACE; ! 2214: cdb->SPACE_TAPE_MARKS.Code = 4; ! 2215: cdb->SPACE_TAPE_MARKS.NumMarksMSB = ! 2216: ((tapePositionVector >> 16) & 0xFF); ! 2217: cdb->SPACE_TAPE_MARKS.NumMarks = ! 2218: ((tapePositionVector >> 8) & 0xFF); ! 2219: cdb->SPACE_TAPE_MARKS.NumMarksLSB = ! 2220: (tapePositionVector & 0xFF); ! 2221: srb.TimeOutValue = 4100; ! 2222: break; ! 2223: ! 2224: default: ! 2225: DebugPrint((1,"TapeSetPosition: PositionMethod -- operation not supported\n")); ! 2226: return STATUS_NOT_IMPLEMENTED; ! 2227: } ! 2228: ! 2229: // ! 2230: // Send SCSI command (CDB) to device ! 2231: // ! 2232: ! 2233: DebugPrint((3,"TapeSetPosition: SendSrb (method)\n")); ! 2234: ! 2235: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 2236: &srb, ! 2237: NULL, ! 2238: 0, ! 2239: FALSE); ! 2240: ! 2241: if (NT_SUCCESS(status)) { ! 2242: if (changePartition) { ! 2243: tapeData->CurrentPartition = tapeSetPosition->Partition; ! 2244: } ! 2245: } else { ! 2246: DebugPrint((1,"TapeSetPosition: method, SendSrb unsuccessful\n")); ! 2247: } ! 2248: ! 2249: return status; ! 2250: ! 2251: } // end TapeSetPosition() ! 2252: ! 2253: ! 2254: BOOLEAN ! 2255: TapeVerifyInquiry( ! 2256: IN PSCSI_INQUIRY_DATA LunInfo ! 2257: ) ! 2258: ! 2259: /*++ ! 2260: Routine Description: ! 2261: ! 2262: This routine determines if this driver should claim this device. ! 2263: ! 2264: Arguments: ! 2265: ! 2266: LunInfo ! 2267: ! 2268: Return Value: ! 2269: ! 2270: TRUE - driver should claim this device. ! 2271: FALSE - driver should not claim this device. ! 2272: ! 2273: --*/ ! 2274: ! 2275: { ! 2276: PINQUIRYDATA inquiryData; ! 2277: ! 2278: DebugPrint((3,"TapeVerifyInquiry: Enter routine\n")); ! 2279: ! 2280: inquiryData = (PVOID)LunInfo->InquiryData; ! 2281: ! 2282: // ! 2283: // Determine, from the Product ID field in the ! 2284: // inquiry data, whether or not to "claim" this drive. ! 2285: // ! 2286: ! 2287: return WhichIsIt(inquiryData)? TRUE : FALSE; ! 2288: ! 2289: } // end TapeVerifyInquiry() ! 2290: ! 2291: ! 2292: NTSTATUS ! 2293: TapeWriteMarks( ! 2294: IN PDEVICE_OBJECT DeviceObject, ! 2295: IN PIRP Irp ! 2296: ) ! 2297: ! 2298: /*++ ! 2299: Routine Description: ! 2300: ! 2301: This routine writes tapemarks on the tape. ! 2302: ! 2303: Arguments: ! 2304: ! 2305: DeviceObject ! 2306: Irp ! 2307: ! 2308: Return Value: ! 2309: ! 2310: NTSTATUS ! 2311: ! 2312: --*/ ! 2313: ! 2314: { ! 2315: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 2316: PTAPE_WRITE_MARKS tapeWriteMarks = Irp->AssociatedIrp.SystemBuffer; ! 2317: SCSI_REQUEST_BLOCK srb; ! 2318: PCDB cdb = (PCDB)srb.Cdb; ! 2319: NTSTATUS status; ! 2320: ! 2321: DebugPrint((3,"TapeWriteMarks: Enter routine\n")); ! 2322: ! 2323: if (tapeWriteMarks->Immediate) { ! 2324: switch (tapeWriteMarks->Type) { ! 2325: case TAPE_SETMARKS: ! 2326: case TAPE_FILEMARKS: ! 2327: DebugPrint((3,"TapeWriteMarks: immediate\n")); ! 2328: break; ! 2329: ! 2330: case TAPE_SHORT_FILEMARKS: ! 2331: case TAPE_LONG_FILEMARKS: ! 2332: default: ! 2333: DebugPrint((1,"TapeWriteMarks: TapemarkType, immediate -- operation not supported\n")); ! 2334: return STATUS_NOT_IMPLEMENTED; ! 2335: } ! 2336: } ! 2337: ! 2338: // ! 2339: // Zero CDB in SRB on stack. ! 2340: // ! 2341: ! 2342: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 2343: ! 2344: // ! 2345: // Prepare SCSI command (CDB) ! 2346: // ! 2347: ! 2348: srb.CdbLength = CDB6GENERIC_LENGTH; ! 2349: ! 2350: cdb->WRITE_TAPE_MARKS.OperationCode = SCSIOP_WRITE_FILEMARKS; ! 2351: cdb->WRITE_TAPE_MARKS.Immediate = tapeWriteMarks->Immediate; ! 2352: ! 2353: switch (tapeWriteMarks->Type) { ! 2354: case TAPE_SETMARKS: ! 2355: DebugPrint((3,"TapeWriteMarks: TapemarkType == setmarks\n")); ! 2356: cdb->WRITE_TAPE_MARKS.WriteSetMarks = SETBITON; ! 2357: break; ! 2358: ! 2359: case TAPE_FILEMARKS: ! 2360: DebugPrint((3,"TapeWriteMarks: TapemarkType == filemarks\n")); ! 2361: break; ! 2362: ! 2363: case TAPE_SHORT_FILEMARKS: ! 2364: case TAPE_LONG_FILEMARKS: ! 2365: default: ! 2366: DebugPrint((1,"TapeWriteMarks: TapemarkType -- operation not supported\n")); ! 2367: return STATUS_NOT_IMPLEMENTED; ! 2368: } ! 2369: ! 2370: cdb->WRITE_TAPE_MARKS.TransferLength[0] = ! 2371: ((tapeWriteMarks->Count >> 16) & 0xFF); ! 2372: cdb->WRITE_TAPE_MARKS.TransferLength[1] = ! 2373: ((tapeWriteMarks->Count >> 8) & 0xFF); ! 2374: cdb->WRITE_TAPE_MARKS.TransferLength[2] = ! 2375: (tapeWriteMarks->Count & 0xFF); ! 2376: ! 2377: // ! 2378: // Set timeout value. ! 2379: // ! 2380: ! 2381: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 2382: ! 2383: // ! 2384: // Send SCSI command (CDB) to device ! 2385: // ! 2386: ! 2387: DebugPrint((3,"TapeWriteMarks: SendSrb (TapemarkType)\n")); ! 2388: ! 2389: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 2390: &srb, ! 2391: NULL, ! 2392: 0, ! 2393: FALSE); ! 2394: ! 2395: if (!NT_SUCCESS(status)) { ! 2396: DebugPrint((1,"TapeWriteMarks: TapemarkType, SendSrb unsuccessful\n")); ! 2397: } ! 2398: ! 2399: return status; ! 2400: ! 2401: } // end TapeWriteMarks() ! 2402: ! 2403: ! 2404: static ! 2405: NTSTATUS ! 2406: GetInquiryInformationData ( ! 2407: IN PDEVICE_OBJECT DeviceObject, ! 2408: IN PIRP Irp, ! 2409: OUT PINQUIRYDATA InquiryBuffer ! 2410: ) ! 2411: ! 2412: /*++ ! 2413: Routine Description: ! 2414: ! 2415: Get the inquiry parameter list buffer ! 2416: ! 2417: Arguments: ! 2418: ! 2419: DeviceObject ! 2420: Irp ! 2421: InquiryBuffer ! 2422: ! 2423: Return Value: ! 2424: ! 2425: NTSTATUS ! 2426: ! 2427: --*/ ! 2428: ! 2429: { ! 2430: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 2431: SCSI_REQUEST_BLOCK srb; ! 2432: PCDB cdb = (PCDB)srb.Cdb; ! 2433: NTSTATUS status; ! 2434: ! 2435: RtlZeroMemory(InquiryBuffer, sizeof(INQUIRYDATA)); ! 2436: ! 2437: // ! 2438: // Zero CDB in SRB on stack. ! 2439: // ! 2440: ! 2441: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 2442: ! 2443: // ! 2444: // Prepare SCSI command (CDB) ! 2445: // ! 2446: ! 2447: srb.CdbLength = CDB6GENERIC_LENGTH; ! 2448: ! 2449: cdb->CDB6INQUIRY.OperationCode = SCSIOP_INQUIRY; ! 2450: cdb->CDB6INQUIRY.AllocationLength = INQUIRYDATABUFFERSIZE; ! 2451: ! 2452: // ! 2453: // Set timeout value. ! 2454: // ! 2455: ! 2456: srb.TimeOutValue = deviceExtension->TimeOutValue; ! 2457: ! 2458: // ! 2459: // Send SCSI command (CDB) to device ! 2460: // ! 2461: ! 2462: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 2463: &srb, ! 2464: InquiryBuffer, ! 2465: INQUIRYDATABUFFERSIZE, ! 2466: FALSE); ! 2467: ! 2468: return status; ! 2469: } ! 2470: ! 2471: ! 2472: static ! 2473: NTSTATUS ! 2474: RewindToBOT( ! 2475: IN PDEVICE_OBJECT DeviceObject, ! 2476: IN PIRP Irp ! 2477: ) ! 2478: ! 2479: /*++ ! 2480: Routine Description: ! 2481: ! 2482: This routine will rewind to BOT. Note: BOP is BOT for both the ! 2483: data partition and the directory partition; thus, if QFA is enabled, ! 2484: a rewind to BOT is a rewind to BOP of the active partition. ! 2485: ! 2486: Arguments: ! 2487: ! 2488: DeviceObject ! 2489: Irp ! 2490: ! 2491: Return Value: ! 2492: ! 2493: NTSTATUS ! 2494: ! 2495: --*/ ! 2496: ! 2497: { ! 2498: PDEVICE_EXTENSION deviceExtension = DeviceObject->DeviceExtension; ! 2499: SCSI_REQUEST_BLOCK srb; ! 2500: PCDB cdb = (PCDB)srb.Cdb; ! 2501: NTSTATUS status; ! 2502: ! 2503: // ! 2504: // Zero CDB in SRB on stack. ! 2505: // ! 2506: ! 2507: RtlZeroMemory(cdb, MAXIMUM_CDB_SIZE); ! 2508: ! 2509: // ! 2510: // Prepare SCSI command (CDB) ! 2511: // ! 2512: ! 2513: srb.CdbLength = CDB6GENERIC_LENGTH; ! 2514: ! 2515: cdb->CDB6INQUIRY.OperationCode = SCSIOP_REWIND; ! 2516: ! 2517: // ! 2518: // Set timeout value. ! 2519: // ! 2520: ! 2521: srb.TimeOutValue = 180; ! 2522: ! 2523: // ! 2524: // Send SCSI command (CDB) to device ! 2525: // ! 2526: ! 2527: status = ScsiClassSendSrbSynchronous(DeviceObject, ! 2528: &srb, ! 2529: NULL, ! 2530: 0, ! 2531: FALSE); ! 2532: return status; ! 2533: } ! 2534: ! 2535: ! 2536: static ! 2537: ULONG ! 2538: WhichIsIt( ! 2539: IN PINQUIRYDATA InquiryData ! 2540: ) ! 2541: ! 2542: /*++ ! 2543: Routine Description: ! 2544: ! 2545: This routine determines a drive's identity from the Product ID field ! 2546: in its inquiry data. ! 2547: ! 2548: Arguments: ! 2549: ! 2550: InquiryData (from an Inquiry command) ! 2551: ! 2552: Return Value: ! 2553: ! 2554: driveID ! 2555: ! 2556: --*/ ! 2557: ! 2558: { ! 2559: if (RtlCompareMemory(InquiryData->VendorId,"TANDBERG",8) == 8) { ! 2560: ! 2561: if (RtlCompareMemory(InquiryData->ProductId," TDC 3600",9) == 9) { ! 2562: return TDC_3600; ! 2563: } ! 2564: ! 2565: if (RtlCompareMemory(InquiryData->ProductId," TDC 3800",9) == 9) { ! 2566: return TDC_3800; ! 2567: } ! 2568: ! 2569: if (RtlCompareMemory(InquiryData->ProductId," TDC 4100",9) == 9) { ! 2570: return TDC_4100; ! 2571: } ! 2572: ! 2573: if (RtlCompareMemory(InquiryData->ProductId," IBM 4100",9) == 9) { ! 2574: return TDC_4100; ! 2575: } ! 2576: ! 2577: if (RtlCompareMemory(InquiryData->ProductId," TDC 4200",9) == 9) { ! 2578: return TDC_4200; ! 2579: } ! 2580: ! 2581: } ! 2582: ! 2583: if (RtlCompareMemory(InquiryData->VendorId,"DEC ",8) == 8) { ! 2584: ! 2585: if (RtlCompareMemory(InquiryData->ProductId,"TZK10",5) == 5) { ! 2586: return TDC_3800; ! 2587: } ! 2588: ! 2589: } ! 2590: ! 2591: return (ULONG)0; ! 2592: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.