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