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