|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1993 - Colorado Memory Systems, Inc. ! 4: All Rights Reserved ! 5: ! 6: Module Name: ! 7: ! 8: main.c ! 9: ! 10: Abstract: ! 11: ! 12: This is the tape class driver. ! 13: ! 14: Revision History: ! 15: ! 16: ! 17: ! 18: ! 19: --*/ ! 20: ! 21: // ! 22: // Includes ! 23: // ! 24: ! 25: #include <ntddk.h> ! 26: #include <ntddtape.h> // tape device driver I/O control codes ! 27: #include <ntiologc.h> ! 28: #include "common.h" ! 29: #include "q117.h" ! 30: #include "cms.h" ! 31: #include "protos.h" ! 32: #include "hilevel.h" ! 33: #include "q117log.h" ! 34: ! 35: // ! 36: // Protos for entry points ! 37: // ! 38: ! 39: NTSTATUS ! 40: q117CreateNumericKey( ! 41: IN HANDLE Root, ! 42: IN ULONG Name, ! 43: IN PWSTR Prefix, ! 44: OUT PHANDLE NewKey ! 45: ); ! 46: ! 47: NTSTATUS ! 48: q117CreateRegistryInfo( ! 49: IN ULONG TapeNumber, ! 50: IN PUNICODE_STRING RegistryPath, ! 51: IN PQ117_CONTEXT Context ! 52: ); ! 53: ! 54: #ifdef ALLOC_PRAGMA ! 55: #pragma alloc_text(init,q117Initialize) ! 56: #endif ! 57: ! 58: ! 59: // ! 60: // Start of code ! 61: // ! 62: ! 63: ! 64: NTSTATUS ! 65: q117Initialize( ! 66: IN PDRIVER_OBJECT DriverObject, ! 67: IN PDEVICE_OBJECT q117iDeviceObject, ! 68: IN PUNICODE_STRING RegistryPath, ! 69: PADAPTER_OBJECT AdapterObject, ! 70: ULONG NumberOfMapRegisters ! 71: ) ! 72: ! 73: /*++ ! 74: ! 75: Routine Description: ! 76: ! 77: This routine initializes the SCSI Tape class driver. ! 78: ! 79: Arguments: ! 80: ! 81: DriverObject ! 82: ! 83: Return Value: ! 84: ! 85: NT Status ! 86: ! 87: --*/ ! 88: ! 89: { ! 90: PDEVICE_OBJECT q117DeviceObject; ! 91: NTSTATUS status; ! 92: UNICODE_STRING ntUnicodeString; ! 93: UCHAR ntNameBuffer[256]; ! 94: STRING ntNameString; ! 95: BOOLEAN tapeDeviceFound = FALSE; ! 96: PQ117_CONTEXT context; ! 97: ULONG tapeNumber; ! 98: STRING dosString; ! 99: UNICODE_STRING dosUnicodeString; ! 100: CCHAR dosNameBuffer[64]; ! 101: ! 102: // ! 103: // Build the unicode name for the floppy tape. ! 104: // ! 105: tapeNumber = IoGetConfigurationInformation()->TapeCount; ! 106: ! 107: sprintf(ntNameBuffer, ! 108: "\\Device\\Tape%d", ! 109: tapeNumber); ! 110: ! 111: RtlInitString(&ntNameString, ntNameBuffer); ! 112: ! 113: status = RtlAnsiStringToUnicodeString( ! 114: &ntUnicodeString, ! 115: &ntNameString, ! 116: TRUE ); ! 117: ! 118: if (!NT_SUCCESS(status)) { ! 119: return(status); ! 120: } ! 121: ! 122: // ! 123: // Create a device object for this floppy drive. ! 124: // ! 125: ! 126: status = IoCreateDevice( ! 127: DriverObject, ! 128: sizeof( struct _Q117_CONTEXT ), ! 129: &ntUnicodeString, ! 130: FILE_DEVICE_UNKNOWN, ! 131: FILE_REMOVABLE_MEDIA, ! 132: FALSE, ! 133: &q117DeviceObject ); ! 134: ! 135: ! 136: if (!NT_SUCCESS(status)) { ! 137: return(status); ! 138: } ! 139: ! 140: // ! 141: // Create the DOS port driver name. ! 142: // ! 143: ! 144: sprintf(dosNameBuffer, ! 145: "\\DosDevices\\TAPE%d", ! 146: tapeNumber); ! 147: ! 148: RtlInitString(&dosString, dosNameBuffer); ! 149: ! 150: status = RtlAnsiStringToUnicodeString(&dosUnicodeString, ! 151: &dosString, ! 152: TRUE); ! 153: ! 154: if (!NT_SUCCESS(status)) { ! 155: ! 156: dosUnicodeString.Buffer = NULL; ! 157: ! 158: } else { ! 159: ! 160: IoAssignArcName(&dosUnicodeString, &ntUnicodeString); ! 161: ! 162: } ! 163: ! 164: RtlFreeUnicodeString(&ntUnicodeString); ! 165: ! 166: if (dosUnicodeString.Buffer != NULL) { ! 167: ! 168: RtlFreeUnicodeString(&dosUnicodeString); ! 169: ! 170: } ! 171: ! 172: ! 173: // ! 174: // Increment system tape count. ! 175: // ! 176: ++IoGetConfigurationInformation()->TapeCount; ! 177: ! 178: // ! 179: // Get device extension address. ! 180: // ! 181: ! 182: context = q117DeviceObject->DeviceExtension; ! 183: context->q117iDeviceObject = q117iDeviceObject; ! 184: ! 185: // ! 186: // Allocate memory for the filer ! 187: // ! 188: ! 189: status = q117AllocatePermanentMemory( ! 190: context, ! 191: AdapterObject, ! 192: NumberOfMapRegisters ! 193: ); ! 194: ! 195: if (status) { ! 196: IoDeleteDevice(q117DeviceObject); ! 197: return status; ! 198: } ! 199: ! 200: // ! 201: // Indicate MDLs required. ! 202: // ! 203: ! 204: q117DeviceObject->Flags = DO_DIRECT_IO; ! 205: ! 206: status = q117CreateRegistryInfo(tapeNumber, RegistryPath, context); ! 207: ! 208: q117RdsInitReed(); ! 209: ! 210: return status; ! 211: ! 212: } // end Q117Initialize() ! 213: ! 214: NTSTATUS ! 215: q117CreateRegistryInfo( ! 216: IN ULONG TapeNumber, ! 217: IN PUNICODE_STRING RegistryPath, ! 218: IN PQ117_CONTEXT Context ! 219: ) ! 220: ! 221: /*++ ! 222: ! 223: Routine Description: ! 224: ! 225: This function adds Tape\Unit x to the devicemap and puts the Id info ! 226: and type info values in it. ! 227: ! 228: Arguments: ! 229: ! 230: tapeNumber - unit number of the tape (current tape count) ! 231: ! 232: Context - current context of the driver (this is used to ! 233: identify the device). ! 234: ! 235: ! 236: Return Value: ! 237: ! 238: Returns the status of the operation. ! 239: ! 240: --*/ ! 241: ! 242: { ! 243: HANDLE lunKey; ! 244: HANDLE unitKey; ! 245: UNICODE_STRING ntUnicodeString; ! 246: UCHAR ntNameBuffer[80]; ! 247: STRING ntNameString; ! 248: UNICODE_STRING name; ! 249: OBJECT_ATTRIBUTES objectAttributes; ! 250: ULONG disposition; ! 251: NTSTATUS status; ! 252: ! 253: // ! 254: // Create the Tape key in the device map. ! 255: // ! 256: ! 257: RtlInitUnicodeString( ! 258: &name, ! 259: L"\\Registry\\Machine\\Hardware\\DeviceMap\\Tape" ! 260: ); ! 261: ! 262: // ! 263: // Initialize the object for the key. ! 264: // ! 265: ! 266: InitializeObjectAttributes( &objectAttributes, ! 267: &name, ! 268: OBJ_CASE_INSENSITIVE, ! 269: NULL, ! 270: (PSECURITY_DESCRIPTOR) NULL ); ! 271: ! 272: // ! 273: // Create the key or open it. ! 274: // ! 275: ! 276: status = ZwCreateKey(&lunKey, ! 277: KEY_READ | KEY_WRITE, ! 278: &objectAttributes, ! 279: 0, ! 280: (PUNICODE_STRING) NULL, ! 281: REG_OPTION_VOLATILE, ! 282: &disposition ); ! 283: ! 284: if (!NT_SUCCESS(status)) { ! 285: return status; ! 286: } ! 287: ! 288: status = q117CreateNumericKey(lunKey, TapeNumber, L"Unit ", &unitKey); ! 289: ! 290: ZwClose(lunKey); ! 291: ! 292: if (!NT_SUCCESS(status)) { ! 293: return status; ! 294: } ! 295: ! 296: ! 297: // ! 298: // Add Identifier value. ! 299: // ! 300: ! 301: RtlInitUnicodeString(&name, L"Identifier"); ! 302: ! 303: status = ZwSetValueKey( ! 304: unitKey, ! 305: &name, ! 306: 0, ! 307: REG_SZ, ! 308: L"QIC-40/QIC-80 floppy tape drive", ! 309: sizeof(L"QIC-40/QIC-80 floppy tape drive") ! 310: ); ! 311: ! 312: if ( NT_SUCCESS(status) ) { ! 313: // ! 314: // Add driver value. ! 315: // ! 316: ! 317: RtlInitUnicodeString(&name, L"Driver"); ! 318: ! 319: status = ZwSetValueKey( ! 320: unitKey, ! 321: &name, ! 322: 0, ! 323: REG_SZ, ! 324: RegistryPath->Buffer, ! 325: RegistryPath->Length ! 326: ); ! 327: } ! 328: ! 329: if ( NT_SUCCESS(status) ) { ! 330: // ! 331: // Add DeviceName value. ! 332: // ! 333: ! 334: RtlInitUnicodeString(&name, L"DeviceName"); ! 335: ! 336: sprintf(ntNameBuffer, ! 337: "Tape%d", ! 338: TapeNumber); ! 339: ! 340: RtlInitString(&ntNameString, ntNameBuffer); ! 341: ! 342: status = RtlAnsiStringToUnicodeString(&ntUnicodeString, ! 343: &ntNameString, ! 344: TRUE); ! 345: ! 346: status = ZwSetValueKey( ! 347: unitKey, ! 348: &name, ! 349: 0, ! 350: REG_SZ, ! 351: ntUnicodeString.Buffer, ! 352: ntUnicodeString.Length ! 353: ); ! 354: ! 355: RtlFreeUnicodeString(&ntUnicodeString); ! 356: } ! 357: ! 358: if ( NT_SUCCESS(status) ) { ! 359: // ! 360: // Add UniqueID ! 361: // ! 362: ! 363: RtlInitUnicodeString(&name, L"UniqueId"); ! 364: ! 365: status = ZwSetValueKey( ! 366: unitKey, ! 367: &name, ! 368: 0, ! 369: REG_SZ, ! 370: L"", ! 371: 0 ! 372: ); ! 373: } ! 374: ! 375: ! 376: ZwClose(unitKey); ! 377: ! 378: return status; ! 379: ! 380: } // end q117CreateRegistryInfo ! 381: ! 382: NTSTATUS ! 383: q117CreateNumericKey( ! 384: IN HANDLE Root, ! 385: IN ULONG Name, ! 386: IN PWSTR Prefix, ! 387: OUT PHANDLE NewKey ! 388: ) ! 389: ! 390: /*++ ! 391: ! 392: Routine Description: ! 393: ! 394: This function creates a registry key. The name of the key is a string ! 395: version of numeric value passed in. ! 396: ! 397: Arguments: ! 398: ! 399: RootKey - Supplies a handle to the key where the new key should be inserted. ! 400: ! 401: Name - Supplies the numeric value to name the key. ! 402: ! 403: Prefix - Supplies a prefix name to add to name. ! 404: ! 405: NewKey - Returns the handle for the new key. ! 406: ! 407: Return Value: ! 408: ! 409: Returns the status of the operation. ! 410: ! 411: --*/ ! 412: ! 413: { ! 414: ! 415: UNICODE_STRING string; ! 416: UNICODE_STRING stringNum; ! 417: OBJECT_ATTRIBUTES objectAttributes; ! 418: WCHAR bufferNum[16]; ! 419: WCHAR buffer[64]; ! 420: ULONG disposition; ! 421: NTSTATUS status; ! 422: ! 423: // ! 424: // Copy the Prefix into a string. ! 425: // ! 426: ! 427: string.Length = 0; ! 428: string.MaximumLength=64; ! 429: string.Buffer = buffer; ! 430: ! 431: RtlInitUnicodeString(&stringNum, Prefix); ! 432: ! 433: RtlCopyUnicodeString(&string, &stringNum); ! 434: ! 435: // ! 436: // Create a port number key entry. ! 437: // ! 438: ! 439: stringNum.Length = 0; ! 440: stringNum.MaximumLength = 16; ! 441: stringNum.Buffer = bufferNum; ! 442: ! 443: status = RtlIntegerToUnicodeString(Name, 10, &stringNum); ! 444: ! 445: if (!NT_SUCCESS(status)) { ! 446: return status; ! 447: } ! 448: ! 449: // ! 450: // Append the prefix and the numeric name. ! 451: // ! 452: ! 453: RtlAppendUnicodeStringToString(&string, &stringNum); ! 454: ! 455: InitializeObjectAttributes( &objectAttributes, ! 456: &string, ! 457: OBJ_CASE_INSENSITIVE, ! 458: Root, ! 459: (PSECURITY_DESCRIPTOR) NULL ); ! 460: ! 461: status = ZwCreateKey(NewKey, ! 462: KEY_READ | KEY_WRITE, ! 463: &objectAttributes, ! 464: 0, ! 465: (PUNICODE_STRING) NULL, ! 466: REG_OPTION_VOLATILE, ! 467: &disposition ); ! 468: ! 469: return(status); ! 470: ! 471: } // end q117CreateNumericKey ! 472: ! 473: NTSTATUS ! 474: q117Read( ! 475: IN PDEVICE_OBJECT DeviceObject, ! 476: IN PIRP Irp ! 477: ) ! 478: ! 479: /*++ ! 480: ! 481: Routine Description: ! 482: ! 483: This is the tape class driver IO handler routine. ! 484: ! 485: Arguments: ! 486: ! 487: DeviceObject ! 488: Irp - IO request ! 489: ! 490: Return Value: ! 491: ! 492: NT Status ! 493: ! 494: --*/ ! 495: ! 496: { ! 497: ! 498: PIO_STACK_LOCATION currentIrpStack; ! 499: KIRQL currentIrql; ! 500: STATUS status; ! 501: NTSTATUS ntStatus; ! 502: PVOID usrBuf; ! 503: PQ117_CONTEXT context; ! 504: ULONG amount; ! 505: BOOLEAN endOfVolume = FALSE; ! 506: ! 507: ! 508: context = DeviceObject->DeviceExtension; ! 509: currentIrpStack = IoGetCurrentIrpStackLocation(Irp); ! 510: ! 511: status = NoErr; ! 512: ntStatus = STATUS_SUCCESS; ! 513: ! 514: // ! 515: // If this is the first read, find the NT volume and read ! 516: if (context->CurrentOperation.Type == NoOperation) { ! 517: ! 518: ntStatus = q117OpenForRead( ! 519: context->CurrentOperation.BytesRead, ! 520: context, ! 521: DeviceObject); ! 522: ! 523: if (ntStatus == STATUS_NO_DATA_DETECTED) { ! 524: ! 525: // ! 526: // Flag no bytes read (end of media, end of data, etc.) ! 527: // ! 528: ! 529: ntStatus = STATUS_SUCCESS; ! 530: Irp->IoStatus.Information = 0; ! 531: endOfVolume = TRUE; ! 532: ! 533: } ! 534: ! 535: } ! 536: ! 537: ! 538: if (NT_SUCCESS(ntStatus)) { ! 539: ! 540: // ! 541: // Return the results of the call to the port driver. ! 542: // ! 543: usrBuf = MmGetSystemAddressForMdl(Irp->MdlAddress); ! 544: ! 545: // ! 546: // Check to see if user is asking for more data than is there ! 547: // (bytes on tape - current offset) ! 548: // ! 549: ! 550: amount = currentIrpStack->Parameters.Read.Length; ! 551: ! 552: ntStatus = q117ConvertStatus( ! 553: DeviceObject, ! 554: q117ReadTape(usrBuf,&amount,context) ! 555: ); ! 556: ! 557: // ! 558: // Set the amount read to the amount we copied out of the buffer ! 559: // ! 560: Irp->IoStatus.Information = amount; ! 561: ! 562: CheckedDump(QIC117SHOWTD,("%x=Read(%x) - Status: %x\n",amount,currentIrpStack->Parameters.Read.Length, status)); ! 563: ! 564: } ! 565: ! 566: if (endOfVolume && NT_SUCCESS(ntStatus)) { ! 567: ! 568: status = STATUS_NO_DATA_DETECTED; ! 569: ! 570: } ! 571: ! 572: Irp->IoStatus.Status = ntStatus; ! 573: ! 574: KeRaiseIrql(DISPATCH_LEVEL, ¤tIrql); ! 575: IoCompleteRequest(Irp, 0); ! 576: KeLowerIrql(currentIrql); ! 577: ! 578: return ntStatus; ! 579: ! 580: ! 581: } // end Q117Read() ! 582: ! 583: ! 584: NTSTATUS ! 585: q117Write( ! 586: IN PDEVICE_OBJECT DeviceObject, ! 587: IN PIRP Irp ! 588: ) ! 589: ! 590: /*++ ! 591: ! 592: Routine Description: ! 593: ! 594: This is the tape class driver IO handler routine. ! 595: ! 596: Arguments: ! 597: ! 598: DeviceObject ! 599: Irp - IO request ! 600: ! 601: Return Value: ! 602: ! 603: NT Status ! 604: ! 605: --*/ ! 606: ! 607: { ! 608: ! 609: PIO_STACK_LOCATION currentIrpStack; ! 610: KIRQL currentIrql; ! 611: STATUS status; ! 612: NTSTATUS ntStatus; ! 613: PVOID usrBuf; ! 614: PQ117_CONTEXT context; ! 615: ! 616: context = DeviceObject->DeviceExtension; ! 617: currentIrpStack = IoGetCurrentIrpStackLocation(Irp); ! 618: ! 619: // ! 620: // Make sure we are in write mode ! 621: // ! 622: status = q117OpenForWrite(context); ! 623: ! 624: if (!status) { ! 625: ! 626: // ! 627: // Return the results of the call to the port driver. ! 628: // ! 629: usrBuf = MmGetSystemAddressForMdl(Irp->MdlAddress); ! 630: ! 631: status = q117WriteTape(usrBuf,currentIrpStack->Parameters.Write.Length,context); ! 632: // ! 633: // Set the amount written to the amount we copied out of the buffer ! 634: // ! 635: if (!status || status == EarlyWarning) ! 636: Irp->IoStatus.Information = currentIrpStack->Parameters.Write.Length; ! 637: } ! 638: ! 639: ntStatus = q117ConvertStatus(DeviceObject, status); ! 640: ! 641: Irp->IoStatus.Status = ntStatus; ! 642: ! 643: KeRaiseIrql(DISPATCH_LEVEL, ¤tIrql); ! 644: IoCompleteRequest(Irp, 0); ! 645: KeLowerIrql(currentIrql); ! 646: ! 647: return ntStatus; ! 648: ! 649: } // end Q117Write() ! 650: ! 651: NTSTATUS ! 652: q117ConvertStatus( ! 653: IN PDEVICE_OBJECT DeviceObject, ! 654: IN STATUS Status ! 655: ) ! 656: { ! 657: NTSTATUS ntStatus; ! 658: PQ117_CONTEXT context; ! 659: BOOLEAN suppressLog = FALSE; ! 660: ! 661: context = DeviceObject->DeviceExtension; ! 662: ! 663: switch(Status) { ! 664: case NoVols: ! 665: case InvalVol: ! 666: case EndOfVol: ! 667: // or maybe STATUS_END_OF_RECORDED_DATA? ! 668: ntStatus = STATUS_NO_DATA_DETECTED; ! 669: suppressLog = TRUE; ! 670: break; ! 671: ! 672: case EarlyWarning: ! 673: ntStatus = STATUS_END_OF_MEDIA; ! 674: suppressLog = TRUE; ! 675: break; ! 676: ! 677: case NoTape: ! 678: ntStatus = STATUS_NO_MEDIA_IN_DEVICE; ! 679: break; ! 680: ! 681: case NoErr: ! 682: ntStatus = STATUS_SUCCESS; ! 683: break; ! 684: ! 685: #ifndef NO_MARKS ! 686: case FileMark: ! 687: case LongFileMark: ! 688: case ShortFileMark: ! 689: ntStatus = STATUS_FILEMARK_DETECTED; ! 690: suppressLog = TRUE; ! 691: break; ! 692: ! 693: case SetMark: ! 694: ntStatus = STATUS_SETMARK_DETECTED; ! 695: suppressLog = TRUE; ! 696: break; ! 697: #endif ! 698: ! 699: case UnknownFormat: ! 700: case Unformat: ! 701: case BadFmt: ! 702: ntStatus = STATUS_UNRECOGNIZED_MEDIA; ! 703: break; ! 704: ! 705: case FMemErr: ! 706: ntStatus = STATUS_INSUFFICIENT_RESOURCES; ! 707: break; ! 708: ! 709: case WProt: ! 710: ntStatus = STATUS_MEDIA_WRITE_PROTECTED; ! 711: break; ! 712: ! 713: case NewCart: ! 714: ntStatus = STATUS_MEDIA_CHANGED; ! 715: break; ! 716: ! 717: case UpdErr: ! 718: case BadTape: ! 719: ntStatus = STATUS_DATA_ERROR; ! 720: break; ! 721: ! 722: case RdncUnsc: ! 723: ntStatus = STATUS_CRC_ERROR; ! 724: break; ! 725: ! 726: default: ! 727: CheckedDump(QIC117DBGP,("Error %d reported\n",Status)); ! 728: ntStatus = (NTSTATUS)(STATUS_SEVERITY_WARNING << 30); ! 729: ntStatus |= (FILE_DEVICE_TAPE << 16) & 0x3fff0000; ! 730: ntStatus |= Status & 0x0000ffff; ! 731: ! 732: } ! 733: ! 734: if (Status != NoErr && !suppressLog) { ! 735: NTSTATUS logStatus = q117MapStatus(Status); ! 736: ! 737: if (logStatus != QIC117_NOTAPE) { ! 738: CheckedDump(QIC117SHOWTD,("Error %d logged\n",Status)); ! 739: ! 740: q117LogError( ! 741: DeviceObject, ! 742: context->ErrorSequence++, ! 743: context->MajorFunction, ! 744: 0, ! 745: Status, ! 746: ntStatus, ! 747: logStatus ! 748: ); ! 749: } ! 750: ! 751: } else { ! 752: #if DBG ! 753: if (Status) { ! 754: CheckedDump(QIC117SHOWTD,("Error %d reported to API\n",Status)); ! 755: } ! 756: #endif ! 757: } ! 758: ! 759: return ntStatus; ! 760: } ! 761: ! 762: NTSTATUS q117MapStatus( ! 763: IN STATUS Status ! 764: ) ! 765: { ! 766: NTSTATUS mapped; ! 767: ! 768: switch(Status) { ! 769: case UnusTape: ! 770: mapped = QIC117_UNUSTAPE; ! 771: break; ! 772: case BadTape: ! 773: mapped = QIC117_BADTAPE; ! 774: break; ! 775: case FMemErr: ! 776: mapped = QIC117_FMEMERR; ! 777: break; ! 778: case TapeFull: ! 779: mapped = QIC117_TAPEFULL; ! 780: break; ! 781: case VolFull: ! 782: mapped = QIC117_VOLFULL; ! 783: break; ! 784: case RdncUnsc: ! 785: mapped = QIC117_RDNCUNSC; ! 786: break; ! 787: case EndOfVol: ! 788: mapped = QIC117_ENDOFVOL; ! 789: break; ! 790: case FCodeErr: ! 791: mapped = QIC117_FCODEERR; ! 792: break; ! 793: case UpdErr: ! 794: mapped = QIC117_UPDERR; ! 795: break; ! 796: case InvalVol: ! 797: mapped = QIC117_INVALVOL; ! 798: break; ! 799: case NoVols: ! 800: mapped = QIC117_NOVOLS; ! 801: break; ! 802: case Unformat: ! 803: mapped = QIC117_UNFORMAT; ! 804: break; ! 805: case UnknownFormat: ! 806: mapped = QIC117_UNKNOWNFORMAT; ! 807: break; ! 808: case BadBlk: ! 809: mapped = QIC117_BADBLK; ! 810: break; ! 811: case EndTapeErr: ! 812: mapped = QIC117_ENDTAPEERR; ! 813: break; ! 814: case DriveFlt: ! 815: mapped = QIC117_DRIVEFLT; ! 816: break; ! 817: case WProt: ! 818: mapped = QIC117_WPROT; ! 819: break; ! 820: case NoTape: ! 821: mapped = QIC117_NOTAPE; ! 822: break; ! 823: case SeekErr: ! 824: mapped = QIC117_SEEKERR; ! 825: break; ! 826: case NoDrive: ! 827: mapped = QIC117_NODRIVE; ! 828: break; ! 829: case InvalCmd: ! 830: mapped = QIC117_INVALCMD; ! 831: break; ! 832: case CodeErr: ! 833: mapped = QIC117_CODEERR; ! 834: break; ! 835: case NECFlt: ! 836: mapped = QIC117_NECFLT; ! 837: break; ! 838: case NoFDC: ! 839: mapped = QIC117_NOFDC; ! 840: break; ! 841: case BadFmt: ! 842: mapped = QIC117_BADFMT; ! 843: break; ! 844: case CmdFlt: ! 845: mapped = QIC117_CMDFLT; ! 846: break; ! 847: case BadNEC: ! 848: mapped = QIC117_BADNEC; ! 849: break; ! 850: case BadReq: ! 851: mapped = QIC117_BADREQ; ! 852: break; ! 853: case TooFast: ! 854: mapped = QIC117_TOOFAST; ! 855: break; ! 856: case NoData: ! 857: mapped = QIC117_NODATA; ! 858: break; ! 859: case DAbort: ! 860: mapped = QIC117_DABORT; ! 861: break; ! 862: case TapeFlt: ! 863: mapped = QIC117_TAPEFLT; ! 864: break; ! 865: case UnspRate: ! 866: mapped = QIC117_UNSPRATE; ! 867: break; ! 868: case Already: ! 869: mapped = QIC117_ALREADY; ! 870: break; ! 871: case TooNoisy: ! 872: mapped = QIC117_TOONOISY; ! 873: break; ! 874: case TimeOut: ! 875: mapped = QIC117_TIMEOUT; ! 876: break; ! 877: case BadMark: ! 878: mapped = QIC117_BADMARK; ! 879: break; ! 880: case NewCart: ! 881: mapped = QIC117_NEWCART; ! 882: break; ! 883: case WrongFmt: ! 884: mapped = QIC117_WRONGFMT; ! 885: break; ! 886: case FmtMisMatch: ! 887: mapped = QIC117_FMTMISMATCH; ! 888: break; ! 889: case IncompTapeFmt: ! 890: mapped = QIC117_INCOMPTAPEFMT; ! 891: break; ! 892: case SCSIFmtMsmtch: ! 893: mapped = QIC117_SCSIFMTMSMTCH; ! 894: break; ! 895: case QIC40InEagle: ! 896: mapped = QIC117_QIC40INEAGLE; ! 897: break; ! 898: case QIC80InEagle: ! 899: mapped = QIC117_QIC80INEAGLE; ! 900: break; ! 901: case ControllerBusy: ! 902: mapped = QIC117_CONTROLLERBUSY; ! 903: break; ! 904: case InQue: ! 905: mapped = QIC117_INQUE; ! 906: break; ! 907: case SplitRequests: ! 908: mapped = QIC117_SPLITREQUESTS; ! 909: break; ! 910: case EarlyWarning: ! 911: mapped = QIC117_EARLYWARNING; ! 912: break; ! 913: default: ! 914: mapped = QIC117_BOGUS; ! 915: } ! 916: return mapped; ! 917: } ! 918: ! 919: NTSTATUS ! 920: q117DeviceControl( ! 921: IN PDEVICE_OBJECT DeviceObject, ! 922: IN PIRP Irp ! 923: ) ! 924: ! 925: /*++ ! 926: ! 927: Routine Description: ! 928: ! 929: This routine is the dispatcher for device control requests. It ! 930: looks at the IOCTL code and calls the appropriate tape device ! 931: routine. ! 932: ! 933: Arguments: ! 934: ! 935: DeviceObject ! 936: Irp - Request packet ! 937: ! 938: Return Value: ! 939: ! 940: --*/ ! 941: ! 942: { ! 943: PIO_STACK_LOCATION irpStack; ! 944: KIRQL currentIrql; ! 945: NTSTATUS status; ! 946: PQ117_CONTEXT context; ! 947: ! 948: context = DeviceObject->DeviceExtension; ! 949: irpStack = IoGetCurrentIrpStackLocation(Irp); ! 950: ! 951: status = 0; ! 952: ! 953: CheckedDump(QIC117SHOWPOLL,("Curmark: %x TotalMarks: %x\n", context->CurrentMark, context->MarkArray.TotalMarks)); ! 954: ! 955: switch (irpStack->Parameters.DeviceIoControl.IoControlCode) { ! 956: ! 957: case IOCTL_TAPE_GET_DRIVE_PARAMS: ! 958: ! 959: status = q117IoCtlGetDriveParameters(DeviceObject, Irp); ! 960: CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_GET_DRIVE_PARAMS done")); ! 961: break; ! 962: ! 963: case IOCTL_TAPE_SET_DRIVE_PARAMS: ! 964: ! 965: status = q117IoCtlSetDriveParameters(DeviceObject, Irp); ! 966: CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_SET_DRIVE_PARAMS done")); ! 967: break; ! 968: ! 969: case IOCTL_TAPE_GET_MEDIA_PARAMS: ! 970: ! 971: status = q117IoCtlGetMediaParameters(DeviceObject, Irp); ! 972: CheckedDump(QIC117SHOWPOLL,("IOCTL_TAPE_GET_MEDIA_PARAMS done")); ! 973: break; ! 974: ! 975: case IOCTL_TAPE_SET_MEDIA_PARAMS: ! 976: ! 977: status = q117IoCtlSetMediaParameters(DeviceObject, Irp); ! 978: CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_SET_MEDIA_PARAMS done\n")); ! 979: break; ! 980: ! 981: case IOCTL_TAPE_CREATE_PARTITION: ! 982: ! 983: CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_CREATE_PARTITION attempted\n")); ! 984: status = STATUS_INVALID_DEVICE_REQUEST; ! 985: break; ! 986: ! 987: case IOCTL_TAPE_ERASE: ! 988: ! 989: status = q117IoCtlErase(DeviceObject, Irp); ! 990: CheckedDump(QIC117SHOWTD,("Curmark: %x TotalMarks: %x\n", context->CurrentMark, context->MarkArray.TotalMarks)); ! 991: CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_ERASE done")); ! 992: break; ! 993: ! 994: case IOCTL_TAPE_PREPARE: ! 995: ! 996: status = q117IoCtlPrepare(DeviceObject, Irp); ! 997: CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_PREPARE done")); ! 998: break; ! 999: ! 1000: case IOCTL_TAPE_WRITE_MARKS: ! 1001: ! 1002: status = q117IoCtlWriteMarks(DeviceObject, Irp); ! 1003: CheckedDump(QIC117SHOWTD,("Curmark: %x TotalMarks: %x\n", context->CurrentMark, context->MarkArray.TotalMarks)); ! 1004: CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_WRITE_MARKS done")); ! 1005: break; ! 1006: ! 1007: case IOCTL_TAPE_GET_POSITION: ! 1008: ! 1009: status = q117IoCtlGetPosition(DeviceObject, Irp); ! 1010: CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_GET_POSITION done")); ! 1011: break; ! 1012: ! 1013: case IOCTL_TAPE_SET_POSITION: ! 1014: ! 1015: status = q117IoCtlSetPosition(DeviceObject, Irp); ! 1016: CheckedDump(QIC117SHOWTD,("Curmark: %x TotalMarks: %x\n", context->CurrentMark, context->MarkArray.TotalMarks)); ! 1017: CheckedDump(QIC117SHOWTD,("IOCTL_TAPE_SET_POSITION done")); ! 1018: break; ! 1019: ! 1020: case IOCTL_TAPE_GET_STATUS: ! 1021: ! 1022: status = q117IoCtlGetStatus (DeviceObject, Irp); ! 1023: CheckedDump(QIC117SHOWPOLL,("IOCTL_TAPE_GET_STATUS done")); ! 1024: break; ! 1025: ! 1026: case IOCTL_CMS_WRITE_ABS_BLOCK: ! 1027: ! 1028: status = q117IoCtlWriteAbs(DeviceObject, Irp); ! 1029: CheckedDump(QIC117SHOWTD,("IOCTL_CMS_WRITE_ABS_BLOCK done")); ! 1030: break; ! 1031: ! 1032: case IOCTL_CMS_READ_ABS_BLOCK: ! 1033: ! 1034: status = q117IoCtlReadAbs(DeviceObject, Irp); ! 1035: CheckedDump(QIC117SHOWTD,("IOCTL_CMS_READ_ABS_BLOCK done")); ! 1036: break; ! 1037: ! 1038: ! 1039: default: ! 1040: ! 1041: status = STATUS_INVALID_DEVICE_REQUEST; ! 1042: ! 1043: } // end switch() ! 1044: ! 1045: // ! 1046: // Complete the request. ! 1047: // ! 1048: ! 1049: CheckedDump(QIC117SHOWTD,(" -- Status: %x\n",status)); ! 1050: Irp->IoStatus.Status = status; ! 1051: ! 1052: KeRaiseIrql(DISPATCH_LEVEL, ¤tIrql); ! 1053: IoCompleteRequest(Irp, 2); ! 1054: KeLowerIrql(currentIrql); ! 1055: ! 1056: return status; ! 1057: ! 1058: } // end Q117DeviceControl() ! 1059: ! 1060: ! 1061: NTSTATUS ! 1062: q117Create ( ! 1063: IN PDEVICE_OBJECT DeviceObject, ! 1064: IN PIRP Irp ! 1065: ) ! 1066: ! 1067: /*++ ! 1068: ! 1069: Routine Description: ! 1070: ! 1071: This routine handles CREATE/OPEN requests and does ! 1072: nothing more than return successful status. ! 1073: ! 1074: Arguments: ! 1075: ! 1076: DeviceObject ! 1077: Irp ! 1078: ! 1079: Return Value: ! 1080: ! 1081: NT Status ! 1082: ! 1083: --*/ ! 1084: ! 1085: { ! 1086: KIRQL currentIrql; ! 1087: PQ117_CONTEXT context; ! 1088: NTSTATUS ntStatus; ! 1089: ! 1090: context = DeviceObject->DeviceExtension; ! 1091: ! 1092: if (!context->DriverOpened) { ! 1093: ! 1094: ntStatus = q117ConvertStatus(DeviceObject, q117Start(context)); ! 1095: ! 1096: // ! 1097: // If everything went OK, then flag that the driver is now open ! 1098: // ! 1099: if (NT_SUCCESS(ntStatus)) { ! 1100: context->DriverOpened = TRUE; ! 1101: } else { ! 1102: q117Stop(context); ! 1103: } ! 1104: ! 1105: } else { ! 1106: ! 1107: ntStatus = STATUS_DEVICE_BUSY; ! 1108: ! 1109: } ! 1110: ! 1111: Irp->IoStatus.Status = ntStatus; ! 1112: ! 1113: KeRaiseIrql(DISPATCH_LEVEL, ¤tIrql); ! 1114: IoCompleteRequest(Irp, 0); ! 1115: KeLowerIrql(currentIrql); ! 1116: ! 1117: return ntStatus; ! 1118: ! 1119: } // end Q117Create() ! 1120: ! 1121: NTSTATUS ! 1122: q117Close ( ! 1123: IN PDEVICE_OBJECT DeviceObject, ! 1124: IN PIRP Irp ! 1125: ) ! 1126: ! 1127: /*++ ! 1128: ! 1129: Routine Description: ! 1130: ! 1131: ! 1132: Arguments: ! 1133: ! 1134: DeviceObject ! 1135: Irp ! 1136: ! 1137: Return Value: ! 1138: ! 1139: NT Status ! 1140: ! 1141: --*/ ! 1142: ! 1143: { ! 1144: KIRQL currentIrql; ! 1145: PQ117_CONTEXT context; ! 1146: NTSTATUS ntStatus; ! 1147: ! 1148: context = DeviceObject->DeviceExtension; ! 1149: ! 1150: ntStatus = q117ConvertStatus(DeviceObject, q117Stop(context)); ! 1151: ! 1152: context->DriverOpened = FALSE; ! 1153: ! 1154: Irp->IoStatus.Status = ntStatus; ! 1155: ! 1156: KeRaiseIrql(DISPATCH_LEVEL, ¤tIrql); ! 1157: IoCompleteRequest(Irp, 0); ! 1158: KeLowerIrql(currentIrql); ! 1159: ! 1160: return ntStatus; ! 1161: ! 1162: } // end Q117Close() ! 1163: ! 1164: VOID ! 1165: q117LogError( ! 1166: IN PDEVICE_OBJECT DeviceObject, ! 1167: IN ULONG SequenceNumber, ! 1168: IN UCHAR MajorFunctionCode, ! 1169: IN UCHAR RetryCount, ! 1170: IN ULONG UniqueErrorValue, ! 1171: IN NTSTATUS FinalStatus, ! 1172: IN NTSTATUS SpecificIOStatus ! 1173: ) ! 1174: ! 1175: /*++ ! 1176: ! 1177: Routine Description: ! 1178: ! 1179: This routine allocates an error log entry, copies the supplied data ! 1180: to it, and requests that it be written to the error log file. ! 1181: ! 1182: Arguments: ! 1183: ! 1184: DeviceObject - a pointer to the device object associated with the ! 1185: device that had the error. ! 1186: ! 1187: SequenceNumber - A ulong value that is unique to an IRP over the ! 1188: life of the irp in this driver - 0 generally means an error not ! 1189: associated with an irp. ! 1190: ! 1191: MajorFunctionCode - If there is an error associated with the irp, ! 1192: this is the major function code of that irp. ! 1193: ! 1194: RetryCount - The number of times a particular operation has been ! 1195: retried. ! 1196: ! 1197: UniqueErrorValue - A unique long word that identifies the particular ! 1198: call to this function. ! 1199: ! 1200: FinalStatus - The final status given to the irp that was associated ! 1201: with this error. If this log entry is being made during one of ! 1202: the retries this value will be STATUS_SUCCESS. ! 1203: ! 1204: SpecificIOStatus - The IO status for a particular error. ! 1205: ! 1206: Return Value: ! 1207: ! 1208: None. ! 1209: ! 1210: --*/ ! 1211: ! 1212: { ! 1213: PIO_ERROR_LOG_PACKET errorLogEntry; ! 1214: ! 1215: errorLogEntry = IoAllocateErrorLogEntry( ! 1216: DeviceObject, ! 1217: sizeof(IO_ERROR_LOG_PACKET) ! 1218: ); ! 1219: ! 1220: if ( errorLogEntry != NULL ) { ! 1221: errorLogEntry->ErrorCode = SpecificIOStatus; ! 1222: errorLogEntry->SequenceNumber = SequenceNumber; ! 1223: errorLogEntry->MajorFunctionCode = MajorFunctionCode; ! 1224: errorLogEntry->RetryCount = RetryCount; ! 1225: errorLogEntry->UniqueErrorValue = UniqueErrorValue; ! 1226: errorLogEntry->FinalStatus = FinalStatus; ! 1227: errorLogEntry->DumpDataSize = 0; ! 1228: IoWriteErrorLogEntry(errorLogEntry); ! 1229: ! 1230: } ! 1231: ! 1232: } ! 1233: #ifdef NOT_NOW ! 1234: ! 1235: VOID ! 1236: q117Cancel( ! 1237: IN PDEVICE_OBJECT DeviceObject, ! 1238: IN PIRP Irp ! 1239: ) ! 1240: ! 1241: /*++ ! 1242: ! 1243: Routine Description: ! 1244: ! 1245: This routine is called from the I/O system when a request is cancelled. ! 1246: ! 1247: N.B. The cancel spinlock is already held upon entry to this routine. ! 1248: ! 1249: Arguments: ! 1250: ! 1251: DeviceObject - Pointer to class device object. ! 1252: ! 1253: Irp - Pointer to the request packet to be cancelled. ! 1254: ! 1255: Return Value: ! 1256: ! 1257: None. ! 1258: ! 1259: --*/ ! 1260: ! 1261: { ! 1262: ! 1263: CheckedDump(QIC117INFO,("q117Cancel: enter\n")); ! 1264: ! 1265: if (Irp == DeviceObject->CurrentIrp) { ! 1266: ! 1267: // ! 1268: // The current request is being cancelled. Set the CurrentIrp to ! 1269: // null and release the cancel spinlock before starting the next packet. ! 1270: // ! 1271: ! 1272: DeviceObject->CurrentIrp = NULL; ! 1273: IoReleaseCancelSpinLock(Irp->CancelIrql); ! 1274: IoStartNextPacket(DeviceObject, TRUE); ! 1275: ! 1276: } else { ! 1277: ! 1278: // ! 1279: // Cancel a request in the device queue. Remove it from queue and ! 1280: // release the cancel spinlock. ! 1281: // ! 1282: ! 1283: if (TRUE != KeRemoveEntryDeviceQueue( ! 1284: &DeviceObject->DeviceQueue, ! 1285: &Irp->Tail.Overlay.DeviceQueueEntry ! 1286: )) { ! 1287: CheckedDump(QIC117SHOWTD,( ! 1288: "q117Cancel: Irp 0x%x not in device queue?!?\n", ! 1289: Irp ! 1290: )); ! 1291: } ! 1292: IoReleaseCancelSpinLock(Irp->CancelIrql); ! 1293: } ! 1294: ! 1295: // ! 1296: // Complete the request with STATUS_CANCELLED. ! 1297: // ! 1298: ! 1299: Irp->IoStatus.Status = STATUS_CANCELLED; ! 1300: Irp->IoStatus.Information = 0; ! 1301: IoCompleteRequest (Irp, IO_NO_INCREMENT); ! 1302: ! 1303: CheckedDump(QIC117INFO,("q117Cancel: exit\n")); ! 1304: ! 1305: return; ! 1306: } ! 1307: #endif ! 1308: ! 1309: NTSTATUS ! 1310: q117Cleanup( ! 1311: IN PDEVICE_OBJECT DeviceObject, ! 1312: IN PIRP Irp ! 1313: ) ! 1314: ! 1315: /*++ ! 1316: ! 1317: Routine Description: ! 1318: ! 1319: This routine is the dispatch routine for cleanup requests. ! 1320: All queued q117 requests are completed with STATUS_CANCELLED, ! 1321: and the lower level driver's queue is cleared. ! 1322: ! 1323: Arguments: ! 1324: ! 1325: DeviceObject - Pointer to class device object. ! 1326: ! 1327: Irp - Pointer to the request packet. ! 1328: ! 1329: Return Value: ! 1330: ! 1331: Status is returned. ! 1332: ! 1333: --*/ ! 1334: ! 1335: { ! 1336: KIRQL currentIrql; ! 1337: KIRQL cancelIrql; ! 1338: PKDEVICE_QUEUE_ENTRY packet; ! 1339: PIRP currentIrp; ! 1340: ! 1341: CheckedDump(QIC117INFO,("q117Cleanup: enter\n")); ! 1342: ! 1343: /* clear everything from the low-level driver */ ! 1344: q117ClearQueue( ! 1345: DeviceObject->DeviceExtension ! 1346: ); ! 1347: // ! 1348: // Raise IRQL to DISPATCH_LEVEL. ! 1349: // ! 1350: ! 1351: KeRaiseIrql(DISPATCH_LEVEL, ¤tIrql); ! 1352: ! 1353: // ! 1354: // Acquire the cancel spinlock. ! 1355: // ! 1356: ! 1357: IoAcquireCancelSpinLock(&cancelIrql); ! 1358: ! 1359: // ! 1360: // Complete all queued requests with STATUS_CANCELLED. ! 1361: // Start with the real CurrentIrp, and run down the list of requests in the ! 1362: // device queue. Be sure to set the real CurrentIrp to NULL, so that ! 1363: // the interrupt service callback routine won't attempt to complete it. ! 1364: // ! 1365: ! 1366: currentIrp = DeviceObject->CurrentIrp; ! 1367: DeviceObject->CurrentIrp = NULL; ! 1368: ! 1369: while (currentIrp != NULL) { ! 1370: ! 1371: // ! 1372: // Remove the CurrentIrp from the cancellable state. ! 1373: // ! 1374: // ! 1375: ! 1376: IoSetCancelRoutine(currentIrp, NULL); ! 1377: ! 1378: // ! 1379: // Set Status to CANCELLED, release the cancel spinlock, ! 1380: // and complete the request. Note that the IRQL is reset to ! 1381: // DISPATCH_LEVEL when we release the cancel spinlock. ! 1382: // ! 1383: ! 1384: currentIrp->IoStatus.Status = STATUS_CANCELLED; ! 1385: currentIrp->IoStatus.Information = 0; ! 1386: ! 1387: IoReleaseCancelSpinLock(cancelIrql); ! 1388: IoCompleteRequest(currentIrp, IO_NO_INCREMENT); ! 1389: ! 1390: // ! 1391: // Reacquire the cancel spinlock. ! 1392: // ! 1393: ! 1394: IoAcquireCancelSpinLock(&cancelIrql); ! 1395: ! 1396: // ! 1397: // Dequeue the next packet (IRP) from the device work queue. ! 1398: // ! 1399: ! 1400: packet = KeRemoveDeviceQueue(&DeviceObject->DeviceQueue); ! 1401: if (packet != NULL) { ! 1402: currentIrp = ! 1403: CONTAINING_RECORD(packet, IRP, Tail.Overlay.DeviceQueueEntry); ! 1404: } else { ! 1405: currentIrp = (PIRP) NULL; ! 1406: } ! 1407: } // end while ! 1408: ! 1409: // ! 1410: // Release the cancel spinlock and lower IRQL. ! 1411: // ! 1412: ! 1413: IoReleaseCancelSpinLock(cancelIrql); ! 1414: KeLowerIrql(currentIrql); ! 1415: ! 1416: // ! 1417: // Complete the cleanup request with STATUS_SUCCESS. ! 1418: // ! 1419: ! 1420: Irp->IoStatus.Status = STATUS_SUCCESS; ! 1421: Irp->IoStatus.Information = 0; ! 1422: IoCompleteRequest (Irp, IO_NO_INCREMENT); ! 1423: ! 1424: CheckedDump(QIC117INFO,("q117Cleanup: exit\n")); ! 1425: ! 1426: return(STATUS_SUCCESS); ! 1427: ! 1428: } ! 1429:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.