|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1993 - Colorado Memory Systems, Inc. ! 4: All Rights Reserved ! 5: ! 6: Module Name: ! 7: ! 8: fnddrv.c ! 9: ! 10: Abstract: ! 11: ! 12: scans the floppy bus for a qic117 device. ! 13: ! 14: Revision History: ! 15: ! 16: ! 17: ! 18: ! 19: --*/ ! 20: ! 21: // ! 22: // include files ! 23: // ! 24: ! 25: #include <ntddk.h> // various NT definitions ! 26: #include <ntdddisk.h> // disk device driver I/O control codes ! 27: #include <ntiologc.h> ! 28: #include "common.h" ! 29: #include "drvtask.h" // this driver's data declarations ! 30: #include "mt1defs.h" // this driver's data declarations ! 31: #include "mt1strc.h" // this driver's data declarations ! 32: #include "q117data.h" // this driver's data declarations ! 33: ! 34: ! 35: STATUS ! 36: Q117iDFndDrv( ! 37: IN PTAPE_EXTENSION TapeExtension ! 38: ) ! 39: ! 40: /*++ ! 41: ! 42: Routine Description: ! 43: ! 44: Find if and where tape drive is (B or D). Configure the drive and tape ! 45: drive as necessary. ! 46: ! 47: Arguments: ! 48: ! 49: TapeExtension - ! 50: ! 51: Return Value: ! 52: ! 53: ! 54: ! 55: --*/ ! 56: ! 57: { ! 58: ! 59: STATUS retval = NoErr; // return value ! 60: SHORT i; // loop variable ! 61: LARGE_INTEGER controllerWait; ! 62: NTSTATUS waitStatus; ! 63: ! 64: ! 65: controllerWait = RtlLargeIntegerNegate( ! 66: RtlConvertLongToLargeInteger( ! 67: (LONG)(10 * 1000 * 15000) ! 68: ) ! 69: ); ! 70: ! 71: waitStatus = STATUS_SUCCESS; ! 72: ! 73: CheckedDump(QIC117INFO,( "Q117i: Waiting Controller Event\n")); ! 74: ! 75: waitStatus = KeWaitForSingleObject( ! 76: TapeExtension->QControllerData->ControllerEvent, ! 77: Executive, ! 78: KernelMode, ! 79: FALSE, ! 80: &controllerWait); ! 81: ! 82: ! 83: if (waitStatus == STATUS_TIMEOUT) { ! 84: ! 85: CheckedDump(QIC117INFO,( "Q117i: Timeout Controller Event\n")); ! 86: return (ControllerBusy); ! 87: ! 88: } ! 89: ! 90: CheckedDump(QIC117INFO,( "Q117i: Have Controller Event\n")); ! 91: ! 92: TapeExtension->QControllerData->CurrentInterrupt = TRUE; ! 93: ! 94: if (!TapeExtension->Found) { ! 95: ! 96: // ! 97: // If the tape drive address is already known, there is no need to ! 98: // look for it again. ! 99: // ! 100: ! 101: if ((retval = Q117iDLocateDrv(TapeExtension)) == NoErr) { ! 102: ! 103: // ! 104: // Now that we know where the tape drive is we must prepare ! 105: // it for the forthcoming operations. First thing is to make ! 106: // sure that it is in Primary mode so there are no Invalid Command ! 107: // surprises. Once in Primary mode, we can determine what flavor ! 108: // of drive is out there (CMS or alien; QIC-40, QIC-80, XR4, etc). ! 109: // Next, we need to determine the speed of the FDC so we can set the ! 110: // corresponding speed on our drive (currently this only applies to ! 111: // the CMS drive since we are the only multiple speed drive out ! 112: // there). Finally, armed with the drive type and the FDC speed, ! 113: // we need to set the necessary speed in the tape drive which is ! 114: // done in ConfigureDrive. ! 115: // ! 116: ! 117: if (retval == NoErr) { ! 118: ! 119: retval = Q117iSelectDrive(TapeExtension); ! 120: TapeExtension->QControllerData->PerpModeSelect = ! 121: (UCHAR)(1 << (TapeExtension->QControllerData->DriveSelect.SelectByte & ! 122: DRIVE_ID_MASK)); ! 123: ! 124: } ! 125: ! 126: if (retval != NoErr) { ! 127: ! 128: if (TapeExtension->QControllerData->AdapterLocked) { ! 129: ! 130: Q117iDLockUnlockDMA(TapeExtension, FALSE); ! 131: ! 132: } ! 133: ! 134: (VOID) Q117iResetFDC(TapeExtension); ! 135: ! 136: CheckedDump(QIC117INFO,( "Q117iDFndDrv: Setting Controller Event\n")); ! 137: ! 138: TapeExtension->NoPause = TRUE; ! 139: TapeExtension->NewCart = FALSE; ! 140: TapeExtension->QControllerData->CurrentInterrupt = FALSE; ! 141: ! 142: (VOID) KeSetEvent( ! 143: TapeExtension->QControllerData->ControllerEvent, ! 144: (KPRIORITY) 0, ! 145: FALSE ); ! 146: ! 147: return(retval); ! 148: ! 149: } ! 150: ! 151: // ! 152: // This fixes the Jumbo B firmware bug where a tape put into ! 153: // the drive slowly is perceive (incorrectly) as invalid media. ! 154: // Since there is no way of knowing the maker of the drive ! 155: // (e.g. CMS, Irwin, etc.), or the type of drive (QIC40, QIC80), ! 156: // it is assumed that it is a CMS QIC80 drive, and Q117ifrmware_fix ! 157: // is called. ! 158: // ! 159: ! 160: if (TapeExtension->FirmwareError == Inval_Media) { ! 161: ! 162: if ((retval = Q117iClearTapeError(TapeExtension)) != NoErr) { ! 163: ! 164: Q117iDDeselect(TapeExtension); ! 165: return(retval); ! 166: ! 167: } ! 168: } ! 169: ! 170: TapeExtension->DriveParms.Mode = DIAGNOSTIC_1_MODE; ! 171: retval = Q117iSetDriveMode(TapeExtension, PRIMARY_MODE); ! 172: ! 173: if (retval && retval != NoTape) { ! 174: ! 175: Q117iDDeselect(TapeExtension); ! 176: return(retval); ! 177: ! 178: } ! 179: ! 180: TapeExtension->DriveParms.Flavor = UNKNOWN; ! 181: if ((retval = Q117iGetDriveType(TapeExtension)) != NoErr) { ! 182: ! 183: CheckedDump(QIC117INFO,( "Q117i: GetDriveType Failed %d (decimal)\n", retval)); ! 184: Q117iDDeselect(TapeExtension); ! 185: return(retval); ! 186: ! 187: } ! 188: ! 189: if ((retval = Q117iSenseSpeed(TapeExtension)) != NoErr) { ! 190: ! 191: CheckedDump(QIC117INFO,( "Q117i: SenseSpeed Failed %d (decimal)\n", retval)); ! 192: Q117iDDeselect(TapeExtension); ! 193: return(retval); ! 194: ! 195: } ! 196: ! 197: if ((retval = Q117iConfigureDrive(TapeExtension)) != NoErr) { ! 198: ! 199: CheckedDump(QIC117INFO,( "Q117i: ConfigureDrive Failed %d (decimal)\n", retval)); ! 200: Q117iDDeselect(TapeExtension); ! 201: return(retval); ! 202: ! 203: } ! 204: ! 205: TapeExtension->Found = TRUE; ! 206: ! 207: } ! 208: ! 209: } else { ! 210: ! 211: if ((retval = Q117iSelectDrive(TapeExtension)) != NoErr) { ! 212: ! 213: CheckedDump(QIC117INFO,( "Q117i: Select Failed %d (decimal)\n", retval)); ! 214: Q117iDDeselect(TapeExtension); ! 215: return(retval); ! 216: ! 217: } ! 218: ! 219: } ! 220: ! 221: if (retval == NoErr) { ! 222: ! 223: retval = Q117iNewTape(TapeExtension); ! 224: ! 225: if (retval && (retval != NoTape) && (retval != NewCart)) { ! 226: ! 227: Q117iDDeselect(TapeExtension); ! 228: return(retval); ! 229: ! 230: } else { ! 231: ! 232: retval = NoErr; ! 233: ! 234: } ! 235: ! 236: } ! 237: ! 238: return(retval); ! 239: } ! 240: ! 241: ! 242: STATUS ! 243: Q117iDLocateDrv( ! 244: IN PTAPE_EXTENSION TapeExtension ! 245: ) ! 246: ! 247: /*++ ! 248: ! 249: Routine Description: ! 250: ! 251: ! 252: ! 253: Arguments: ! 254: ! 255: TapeExtension - ! 256: ! 257: Return Value: ! 258: ! 259: ! 260: ! 261: --*/ ! 262: ! 263: { ! 264: STATUS retval = NoErr; // return value ! 265: SHORT i; // loop variable ! 266: ! 267: // ! 268: // If the tape drive address is already known, there is no need to look for ! 269: // it again. ! 270: // ! 271: ! 272: if (!TapeExtension->Found) { ! 273: ! 274: // ! 275: // Reset the FDC to start in a known state. ! 276: // ! 277: ! 278: Q117iResetFDC(TapeExtension); ! 279: ! 280: // ! 281: // Look for the tape drive at drive B then at drive D. Since the PCN ! 282: // of each channel of the FDC is independant, the global 'pcn must be ! 283: // manually maintained when switching between channels. We can assume ! 284: // that the drive has been found (i.e. we can communicate) when we get ! 285: // any response except communication errors (DriveFlt or CmdFlt). ! 286: // ! 287: ! 288: Q117iSleep(TapeExtension, mt_wt001s, FALSE); ! 289: ! 290: for (i = 0; i < FIND_RETRIES; i++) { ! 291: ! 292: TapeExtension->DriveParms.Flavor = UNKNOWN; ! 293: Q117iResetFDC(TapeExtension); ! 294: retval = Q117iLookForDrive(TapeExtension, DRIVEU, TRUE); ! 295: ! 296: if (retval != DriveFlt && retval != CmdFlt) { ! 297: ! 298: break; ! 299: ! 300: } ! 301: ! 302: TapeExtension->DriveParms.Flavor = CMS; ! 303: Q117iResetFDC(TapeExtension); ! 304: retval = Q117iLookForDrive(TapeExtension, DRIVEU, TRUE); ! 305: ! 306: if (retval != DriveFlt && retval != CmdFlt) { ! 307: ! 308: break; ! 309: ! 310: } ! 311: ! 312: TapeExtension->DriveParms.Flavor = SUMMIT; ! 313: Q117iResetFDC(TapeExtension); ! 314: retval = Q117iLookForDrive(TapeExtension, DRIVEU, TRUE); ! 315: ! 316: if (retval != DriveFlt && retval != CmdFlt) { ! 317: ! 318: break; ! 319: ! 320: } ! 321: ! 322: TapeExtension->DriveParms.Flavor = UNKNOWN; ! 323: Q117iResetFDC(TapeExtension); ! 324: retval = Q117iLookForDrive(TapeExtension, DRIVEB, TRUE); ! 325: ! 326: if (retval != DriveFlt && retval != CmdFlt) { ! 327: ! 328: break; ! 329: ! 330: } ! 331: ! 332: Q117iResetFDC(TapeExtension); ! 333: retval = Q117iLookForDrive(TapeExtension, DRIVED, TRUE); ! 334: ! 335: if (retval != DriveFlt && retval != CmdFlt) { ! 336: ! 337: break; ! 338: ! 339: } ! 340: ! 341: TapeExtension->DriveParms.Flavor = UNKNOWN; ! 342: Q117iResetFDC(TapeExtension); ! 343: retval = Q117iLookForDrive(TapeExtension, DRIVEUB, TRUE); ! 344: ! 345: if (retval != DriveFlt && retval != CmdFlt) { ! 346: ! 347: break; ! 348: ! 349: } ! 350: ! 351: TapeExtension->DriveParms.Flavor = CMS; ! 352: Q117iResetFDC(TapeExtension); ! 353: retval = Q117iLookForDrive(TapeExtension, DRIVEUB, TRUE); ! 354: ! 355: if (retval != DriveFlt && retval != CmdFlt) { ! 356: ! 357: break; ! 358: ! 359: } ! 360: ! 361: TapeExtension->DriveParms.Flavor = SUMMIT; ! 362: Q117iResetFDC(TapeExtension); ! 363: retval = Q117iLookForDrive(TapeExtension, DRIVEUB, TRUE); ! 364: ! 365: if (retval != DriveFlt && retval != CmdFlt) { ! 366: ! 367: break; ! 368: ! 369: } ! 370: ! 371: Q117iSleep(TapeExtension, mt_wt001s, FALSE); ! 372: ! 373: } ! 374: ! 375: // ! 376: // Sort out the results of the drive address search. A DriveFlt or a ! 377: // CmdFlt indicate that we could never successfully communicate with ! 378: // the tape drive at either address so we must assume that there is ! 379: // no tape drive present. A NECFlt indicates that we had serious ! 380: // trouble talking to the FDC so we must assume that it is either ! 381: // broken or not there. The last thing to consider here is a TapeFlt. ! 382: // If the TapeFlt indicates either a hardware or software reset it is ! 383: // save to continue and the error can be ignored (since we must be ! 384: // starting a tape session neither of these errors should bother us). ! 385: // If the TapeFlt indicates any other error, it probably means some ! 386: // badness has happened. ! 387: // ! 388: ! 389: switch (retval) { ! 390: ! 391: case DriveFlt: ! 392: case CmdFlt: ! 393: CheckedDump(QIC117INFO,( "Q117i: DLocateDrv Failed %d (decimal)\n", NoDrive)); ! 394: return(NoDrive); ! 395: ! 396: case NECFlt: ! 397: CheckedDump(QIC117INFO,( "Q117i: DLocateDrv Failed %d (decimal)\n", NoFDC)); ! 398: return(NoFDC); ! 399: ! 400: case NotRdy: ! 401: case InvalCmd: ! 402: retval = NoErr; ! 403: break; ! 404: ! 405: case TapeFlt: ! 406: ! 407: if (TapeExtension->FirmwareError == Swre_Reset || ! 408: TapeExtension->FirmwareError == Pwr_On_Reset || ! 409: TapeExtension->FirmwareError == Inval_Media || ! 410: TapeExtension->FirmwareError == Wtchdog_Reset) { ! 411: ! 412: retval = NoErr; ! 413: ! 414: break; ! 415: ! 416: } ! 417: ! 418: if (TapeExtension->FirmwareError == Xmit_Overrun) { ! 419: ! 420: retval = NoDrive; ! 421: ! 422: } ! 423: ! 424: CheckedDump(QIC117INFO,( "Q117i: DLocateDrv Failed %d (decimal)\n", retval)); ! 425: return(retval); ! 426: ! 427: default: ! 428: break; ! 429: ! 430: } ! 431: } ! 432: ! 433: #if DBG ! 434: ! 435: if (retval) { ! 436: ! 437: CheckedDump(QIC117INFO,( "Q117i: DLocateDrv Failed %d (decimal)\n", retval)); ! 438: ! 439: } ! 440: ! 441: #endif ! 442: ! 443: return retval; ! 444: } ! 445: ! 446: ! 447: STATUS ! 448: Q117iClearTapeError( ! 449: IN PTAPE_EXTENSION TapeExtension ! 450: ) ! 451: ! 452: /*++ ! 453: ! 454: Routine Description: ! 455: ! 456: To correct errors in the Jumbo B drive and firmware version 63. ! 457: ! 458: This piece of code added due to the face that the Jumbo B drives with ! 459: firmware 63 have a bug where you put a tape in very slowly, they sense ! 460: that they have a tape and engage the motor before the tape is actually ! 461: in. It may also cause the drive to think that the tape is write protected ! 462: when it actually is not. Sending it the New tape command causes it to go ! 463: through the tape loading sequence and fixes these 2 bugs. ! 464: ! 465: Arguments: ! 466: ! 467: TapeExtension - ! 468: ! 469: Return Value: ! 470: ! 471: ! 472: ! 473: --*/ ! 474: ! 475: { ! 476: STATUS retval; ! 477: ! 478: // ! 479: // Send the NewTape command, and then clear the error byte. ! 480: // ! 481: ! 482: if ((retval = Q117iSendByte(TapeExtension, New_Tape)) == NoErr) { ! 483: ! 484: retval = Q117iWaitCommandComplete(TapeExtension, mt_wt150s); ! 485: ! 486: } ! 487: ! 488: return(retval); ! 489: } ! 490: ! 491: ! 492: STATUS ! 493: Q117iLookForDrive( ! 494: IN PTAPE_EXTENSION TapeExtension, ! 495: IN UCHAR DriveSelector, ! 496: IN BOOLEAN WaitForTape ! 497: ) ! 498: /*++ ! 499: ! 500: Routine Description: ! 501: ! 502: ! 503: ! 504: Arguments: ! 505: ! 506: TapeExtension - ! 507: ! 508: DriveSelector - ! 509: ! 510: Return Value: ! 511: ! 512: ! 513: ! 514: --*/ ! 515: ! 516: { ! 517: STATUS retval; // Return value ! 518: ! 519: // ! 520: // Set the drive select parameters according to the desired target drive ! 521: // selector. ! 522: // ! 523: ! 524: switch (DriveSelector) { ! 525: ! 526: case DRIVEB: ! 527: TapeExtension->QControllerData->DriveSelect.SelectByte = selb; ! 528: TapeExtension->QControllerData->DriveSelect.DeselectByte = dselb; ! 529: TapeExtension->DriveParms.DriveSelect = curb; ! 530: break; ! 531: ! 532: case DRIVED: ! 533: TapeExtension->QControllerData->DriveSelect.SelectByte = seld; ! 534: TapeExtension->QControllerData->DriveSelect.DeselectByte = dseld; ! 535: TapeExtension->DriveParms.DriveSelect = curd; ! 536: break; ! 537: ! 538: case DRIVEU: ! 539: TapeExtension->QControllerData->DriveSelect.SelectByte = selu; ! 540: TapeExtension->QControllerData->DriveSelect.DeselectByte = dselu; ! 541: TapeExtension->DriveParms.DriveSelect = curu; ! 542: break; ! 543: ! 544: case DRIVEUB: ! 545: TapeExtension->QControllerData->DriveSelect.SelectByte = selub; ! 546: TapeExtension->QControllerData->DriveSelect.DeselectByte = dselub; ! 547: TapeExtension->DriveParms.DriveSelect = curub; ! 548: break; ! 549: ! 550: } ! 551: ! 552: // ! 553: // Try to communicate with the tape drive by requesting drive status. ! 554: // If we can successfully communicate with the drive, wait up to the ! 555: // approximate maximum autoload time (150 seconds) for the tape drive ! 556: // to become ready. This should cover a new tape being inserted ! 557: // immediatley before starting a tape session. ! 558: // ! 559: ! 560: if ((retval = Q117iSelectDrive(TapeExtension)) == NoErr) { ! 561: ! 562: if (WaitForTape) { ! 563: retval = Q117iWaitCommandComplete(TapeExtension, mt_wt460s); ! 564: } else { ! 565: retval = Q117iGetDriveError(TapeExtension); ! 566: } ! 567: ! 568: Q117iDeselectDrive(TapeExtension); ! 569: ! 570: } ! 571: ! 572: return(retval); ! 573: } ! 574: ! 575: STATUS ! 576: Q117iGetDriveType( ! 577: IN PTAPE_EXTENSION TapeExtension ! 578: ) ! 579: ! 580: /*++ ! 581: ! 582: Routine Description: ! 583: ! 584: Determine what flavor tape drive the drive is talking to. Specifically, ! 585: is the current drive a CMS drive or a non-CMS drive. ! 586: ! 587: Arguments: ! 588: ! 589: TapeExtension - ! 590: ! 591: Return Value: ! 592: ! 593: ! 594: ! 595: --*/ ! 596: ! 597: { ! 598: ! 599: STATUS retval; // return value ! 600: USHORT vendorId = 0; // vendor id number from tape drive ! 601: UCHAR signature; ! 602: BOOLEAN reportFailed=FALSE; ! 603: struct CmsStatus cmsStatus; ! 604: ! 605: // ! 606: // Assume that the tape drive is not a CMS drive and get the ROM version ! 607: // number. ! 608: // ! 609: ! 610: if ((retval = Q117iReport( ! 611: TapeExtension, ! 612: Report_ROM, ! 613: (USHORT *)&TapeExtension->DriveParms.Version, ! 614: READ_BYTE, NULL)) != NoErr) { ! 615: ! 616: return(retval); ! 617: ! 618: } ! 619: ! 620: CheckedDump(QIC117INFO,( "Q117i: FW Version %x\n", TapeExtension->DriveParms.Version)); ! 621: ! 622: if ((retval = Q117iSendByte(TapeExtension, Report_Vendor32)) != ! 623: NoErr) { ! 624: ! 625: return(retval); ! 626: ! 627: } ! 628: ! 629: if ((retval = Q117iReceiveByte( ! 630: TapeExtension, ! 631: READ_WORD, ! 632: (USHORT *)&vendorId)) != NoErr) { ! 633: ! 634: Q117iGetDriveError(TapeExtension); ! 635: ! 636: if ((retval = Q117iSendByte(TapeExtension, Report_Vendor32)) != ! 637: NoErr) { ! 638: ! 639: return(retval); ! 640: ! 641: } ! 642: ! 643: if ((retval = Q117iReceiveByte( ! 644: TapeExtension, ! 645: READ_BYTE, ! 646: (USHORT *)&vendorId)) != NoErr) { ! 647: ! 648: Q117iGetDriveError(TapeExtension); ! 649: ! 650: if ((retval = Q117iSendByte(TapeExtension, Report_Vendor)) != ! 651: NoErr) { ! 652: ! 653: return(retval); ! 654: ! 655: } ! 656: ! 657: if ((retval = Q117iReceiveByte( ! 658: TapeExtension, ! 659: READ_BYTE, ! 660: (USHORT *)&vendorId)) != NoErr) { ! 661: ! 662: Q117iGetDriveError(TapeExtension); ! 663: retval = NoErr; ! 664: reportFailed = TRUE; ! 665: CheckedDump(QIC117INFO,( "Q117i: Report Vendor ID Failed\n")); ! 666: ! 667: } ! 668: ! 669: } ! 670: ! 671: } ! 672: ! 673: CheckedDump(QIC117INFO,( "Q117i: Vendor ID %x\n", vendorId)); ! 674: ! 675: if (vendorId == CMS_VEND_NO || reportFailed) { ! 676: ! 677: if ((retval = Q117iSetDriveMode(TapeExtension, DIAGNOSTIC_1_MODE)) != ! 678: NoErr) { ! 679: ! 680: return(retval); ! 681: ! 682: } ! 683: ! 684: if ((retval = Q117iSendByte(TapeExtension, Rpt_Signature)) != NoErr) { ! 685: ! 686: return(retval); ! 687: ! 688: } ! 689: ! 690: if ((retval = Q117iReceiveByte( ! 691: TapeExtension, ! 692: READ_BYTE, ! 693: (USHORT *)&signature)) != NoErr) { ! 694: ! 695: Q117iGetDriveError(TapeExtension); ! 696: retval = NoErr; ! 697: ! 698: } ! 699: ! 700: retval = Q117iSetDriveMode(TapeExtension, PRIMARY_MODE); ! 701: ! 702: if (retval != NoErr && retval != NoTape) { ! 703: ! 704: return(retval); ! 705: ! 706: } ! 707: ! 708: } ! 709: ! 710: CheckedDump(QIC117INFO,( "Q117i: Signature %x\n", signature)); ! 711: ! 712: if (vendorId == CMS_VEND_NO) { ! 713: ! 714: if (signature == CMS_SIG) { ! 715: ! 716: // Issue the Rpt_cmsStatus command to determine if the drive ! 717: // is an IOMEGA. ! 718: ! 719: if ((retval = Q117iSetDriveMode(TapeExtension, ! 720: DIAGNOSTIC_1_MODE)) != NoErr) { ! 721: ! 722: return(retval); ! 723: ! 724: } ! 725: ! 726: if ((retval = Q117iReport( ! 727: TapeExtension, ! 728: Rpt_CMS_Status, ! 729: (USHORT *)&cmsStatus, ! 730: READ_BYTE, ! 731: NULL)) != NoErr) { ! 732: ! 733: if ( TapeExtension->DriveParms.Version >= FIRM_VERSION_63 ) { ! 734: ! 735: TapeExtension->DriveParms.Flavor = IOMEGA; ! 736: CheckedDump(QIC117INFO,( "Q117i: Drive Vendor IOMEGA\n")); ! 737: ! 738: } else { ! 739: ! 740: TapeExtension->DriveParms.Flavor = CMS; ! 741: CheckedDump(QIC117INFO,( "Q117i: Drive Vendor CMS\n")); ! 742: ! 743: } ! 744: Q117iGetDriveError(TapeExtension); ! 745: retval = NoErr; ! 746: ! 747: } else { ! 748: ! 749: TapeExtension->DriveParms.Flavor = CMS; ! 750: CheckedDump(QIC117INFO,( "Q117i: Drive Vendor CMS\n")); ! 751: ! 752: } ! 753: ! 754: // ! 755: // Put drive back into its original mode. ! 756: // ! 757: ! 758: if ((retval = Q117iSetDriveMode(TapeExtension, ! 759: PRIMARY_MODE)) != NoErr) { ! 760: ! 761: return(retval); ! 762: ! 763: } ! 764: ! 765: ! 766: } else { ! 767: ! 768: TapeExtension->DriveParms.Flavor = UNSUPPORTED; ! 769: CheckedDump(QIC117INFO,( "Q117i: Drive Vendor UNSUPPORTED\n")); ! 770: ! 771: } ! 772: ! 773: } else { ! 774: ! 775: if (vendorId == ARCHIVE_VEND_NO_OLD) { ! 776: ! 777: TapeExtension->DriveParms.Flavor = ARCHIVE; ! 778: CheckedDump(QIC117INFO,( "Q117i: Drive Vendor ARCHIVE (old version)\n")); ! 779: ! 780: } else { ! 781: ! 782: switch (vendorId & VENDOR_MASK) { ! 783: case SUMMIT_VEND_NO: ! 784: TapeExtension->DriveParms.Flavor = SUMMIT; ! 785: CheckedDump(QIC117INFO,( "Q117i: Drive Vendor SUMMIT\n")); ! 786: break; ! 787: ! 788: case IOMEGA_VEND_NO: ! 789: TapeExtension->DriveParms.Flavor = IOMEGA; ! 790: CheckedDump(QIC117INFO,( "Q117i: Drive Vendor IOMEGA\n")); ! 791: break; ! 792: ! 793: case WANGTEK_VEND_NO: ! 794: TapeExtension->DriveParms.Flavor = WANGTEK; ! 795: CheckedDump(QIC117INFO,( "Q117i: Drive Vendor WANGTEK\n")); ! 796: break; ! 797: ! 798: case CORE_VEND_NO: ! 799: TapeExtension->DriveParms.Flavor = CORE; ! 800: CheckedDump(QIC117INFO,( "Q117i: Drive Vendor CORE\n")); ! 801: break; ! 802: ! 803: case ARCHIVE_VEND_NO_NEW: ! 804: TapeExtension->DriveParms.Flavor = ARCHIVE; ! 805: CheckedDump(QIC117INFO,( "Q117i: Drive Vendor ARCHIVE (new version)\n")); ! 806: break; ! 807: ! 808: default: ! 809: TapeExtension->DriveParms.Flavor = UNSUPPORTED; ! 810: CheckedDump(QIC117INFO,( "Q117i: Drive Vendor UNSUPPORTED\n")); ! 811: ! 812: if (reportFailed && (signature == CMS_SIG)) { ! 813: TapeExtension->DriveParms.Flavor = CMS_ENHANCEMENTS; ! 814: CheckedDump(QIC117INFO,( "Q117i: Drive Vendor CMS_ENHANCEMENTS\n")); ! 815: } ! 816: if (reportFailed && (signature != CMS_SIG)) { ! 817: TapeExtension->DriveParms.Flavor = WANGTEK; ! 818: CheckedDump(QIC117INFO,( "Q117i: Drive Vendor WANGTEK\n")); ! 819: } ! 820: } ! 821: } ! 822: } ! 823: ! 824: // ! 825: // Get the miscellaneous drive train information from the drive ! 826: // ! 827: ! 828: if ((retval = Q117iGetDriveInfo(TapeExtension)) != NoErr) { ! 829: ! 830: CheckedDump(QIC117INFO,( "Q117i: GetDriveInfo Failed %d (decimal)\n", retval)); ! 831: return(retval); ! 832: ! 833: } ! 834: ! 835: if ((retval = Q117iGetDriveSize( ! 836: TapeExtension, ! 837: reportFailed, ! 838: vendorId, ! 839: signature)) != NoErr) { ! 840: ! 841: CheckedDump(QIC117INFO,( "Q117i: GetDriveSize Failed %d (decimal)\n", retval)); ! 842: return(retval); ! 843: ! 844: } ! 845: ! 846: q117iUpdateRegistryInfo( TapeExtension ); ! 847: ! 848: return(retval); ! 849: } ! 850: ! 851: ! 852: STATUS ! 853: Q117iGetDriveSize( ! 854: IN PTAPE_EXTENSION TapeExtension, ! 855: IN BOOLEAN ReportFailed, ! 856: IN USHORT VendorId, ! 857: IN UCHAR Signature ! 858: ) ! 859: ! 860: /*++ ! 861: ! 862: Routine Description: ! 863: ! 864: Determine the size of the tape drive (QIC40 or QIC80). ! 865: ! 866: To determine the drive type, an attempt is made to set the drive to ! 867: 250Kbs speed. If the drive is a QIC40 this is a valid speed. If the drive ! 868: is a QIC80 this is an invalid speed and an error is returned. ! 869: ! 870: ! 871: ! 872: Arguments: ! 873: ! 874: TapeExtension - ! 875: ! 876: Return Value: ! 877: ! 878: ! 879: ! 880: --*/ ! 881: ! 882: { ! 883: STATUS retval=NoErr; ! 884: struct DriveConfiguration driveConfig; ! 885: struct CmsStatus cmsStatus; ! 886: CHAR orgMode; ! 887: USHORT manDate=0; ! 888: ! 889: TapeExtension->DriveParms.ArchiveNativeMode = 0; ! 890: TapeExtension->DriveParms.SeekMode = SEEK_TIMED; ! 891: ! 892: switch (TapeExtension->DriveParms.Flavor) { ! 893: ! 894: case CMS: ! 895: ! 896: TapeExtension->SpeedChangeOK = TRUE; ! 897: TapeExtension->PegasusSupported = FALSE; ! 898: ! 899: if (TapeExtension->DriveParms.Version >= FIRM_VERSION_60) { ! 900: ! 901: TapeExtension->DriveParms.SeekMode = SEEK_SKIP; ! 902: ! 903: if (TapeExtension->DriveParms.Version >= FIRM_VERSION_87) { ! 904: ! 905: TapeExtension->DriveParms.SeekMode = SEEK_SKIP_EXTENDED; ! 906: ! 907: } ! 908: ! 909: } ! 910: ! 911: if (TapeExtension->DriveParms.Version < FIRM_VERSION_110) { ! 912: ! 913: if ((retval = Q117iSendByte(TapeExtension, Select_Speed)) == NoErr) { ! 914: ! 915: Q117iSleep(TapeExtension, mt_wt2ticks, FALSE); ! 916: ! 917: if ((retval = Q117iSendByte(TapeExtension, TAPE_250Kbps + 2)) == ! 918: NoErr) { ! 919: ! 920: retval = Q117iWaitCommandComplete(TapeExtension, mt_wt010s); ! 921: ! 922: if (retval == NoErr) { ! 923: ! 924: TapeExtension->DriveParms.DriveType = QIC40_DRIVE; ! 925: CheckedDump(QIC117INFO,( "Q117i: Drive Type QIC40_DRIVE\n")); ! 926: ! 927: } else if (retval == UnspRate) { ! 928: ! 929: TapeExtension->DriveParms.DriveType = QIC80_DRIVE; ! 930: CheckedDump(QIC117INFO,( "Q117i: Drive Type QIC80_DRIVE\n")); ! 931: retval = NoErr; ! 932: ! 933: } ! 934: } ! 935: } ! 936: ! 937: } else { ! 938: ! 939: // For versions of 110 and greater, the drive type may be QIC500. ! 940: // Let's just issue the Rpt_cmsStatus command. ! 941: ! 942: orgMode = TapeExtension->DriveParms.Mode; ! 943: ! 944: if ((retval = Q117iSetDriveMode(TapeExtension, ! 945: DIAGNOSTIC_1_MODE)) != NoErr) { ! 946: ! 947: return(retval); ! 948: ! 949: } ! 950: ! 951: if ((retval = Q117iReport( ! 952: TapeExtension, ! 953: Rpt_CMS_Status, ! 954: (USHORT *)&cmsStatus, ! 955: READ_BYTE, ! 956: NULL)) != NoErr) { ! 957: ! 958: return(retval); ! 959: ! 960: } ! 961: ! 962: // ! 963: // Put drive back into its original mode. ! 964: // ! 965: ! 966: if ((retval = Q117iSetDriveMode(TapeExtension, ! 967: PRIMARY_MODE)) != NoErr) { ! 968: ! 969: return(retval); ! 970: ! 971: } ! 972: ! 973: if (orgMode != PRIMARY_MODE) { ! 974: ! 975: if ((retval = Q117iSetDriveMode(TapeExtension, ! 976: orgMode)) != NoErr) { ! 977: ! 978: return(retval); ! 979: ! 980: } ! 981: } ! 982: ! 983: if (!cmsStatus.DriveType) { ! 984: ! 985: // If drive type is QIC80, the drive_type bit is set low ! 986: // and the eagle bit is high. ! 987: ! 988: if (!cmsStatus.Eagle) { ! 989: ! 990: TapeExtension->DriveParms.DriveType = QIC500_DRIVE; ! 991: CheckedDump(QIC117INFO,( "Q117i: Drive Type QIC500_DRIVE\n")); ! 992: ! 993: } else { ! 994: ! 995: // Drive Type is QIC80 ! 996: ! 997: TapeExtension->DriveParms.DriveType = QIC80_DRIVE; ! 998: CheckedDump(QIC117INFO,( "Q117i: Drive Type QIC80_DRIVE\n")); ! 999: ! 1000: } ! 1001: ! 1002: } else { ! 1003: ! 1004: // It must be a QIC40 Drive ! 1005: ! 1006: TapeExtension->DriveParms.DriveType = QIC40_DRIVE; ! 1007: CheckedDump(QIC117INFO,( "Q117i: Drive Type QIC40_DRIVE\n")); ! 1008: ! 1009: } ! 1010: } ! 1011: ! 1012: manDate = (UBYTE)TapeExtension->MiscDriveInfo.ManDate[0]; ! 1013: manDate <<= 8; ! 1014: manDate |= (UBYTE)TapeExtension->MiscDriveInfo.ManDate[1]; ! 1015: ! 1016: CheckedDump(QIC117INFO,( "Q117i: CMS Manufacture Date %d (decimal)\n", ! 1017: manDate)); ! 1018: ! 1019: if ((TapeExtension->DriveParms.Version >= FIRM_VERSION_87) && ! 1020: (manDate >= PEGASUS_START_DATE) && ! 1021: (TapeExtension->DriveParms.DriveType != QIC40_DRIVE)) { ! 1022: ! 1023: CheckedDump(QIC117INFO,( "Q117i: Pegasus Drive Supported (CMS)\n")); ! 1024: TapeExtension->PegasusSupported = TRUE; ! 1025: ! 1026: } ! 1027: break; ! 1028: ! 1029: case SUMMIT: ! 1030: ! 1031: TapeExtension->DriveParms.SeekMode = SEEK_SKIP; ! 1032: ! 1033: if ((retval = Q117iSendByte(TapeExtension, Select_Speed)) == NoErr) { ! 1034: ! 1035: Q117iSleep(TapeExtension, mt_wt2ticks, FALSE); ! 1036: ! 1037: if ((retval = Q117iSendByte(TapeExtension, (TAPE_1Mbps + 2))) == NoErr) { ! 1038: ! 1039: retval = Q117iWaitCommandComplete(TapeExtension, mt_wt010s); ! 1040: ! 1041: if (retval == NoErr) { ! 1042: ! 1043: if ((retval = Q117iReport(TapeExtension, ! 1044: Report_Confg, ! 1045: (USHORT *)&driveConfig, ! 1046: READ_BYTE, ! 1047: NULL)) ! 1048: == NoErr) { ! 1049: ! 1050: if (driveConfig.XferRate == TAPE_1Mbps) { ! 1051: ! 1052: TapeExtension->SpeedChangeOK = TRUE; ! 1053: TapeExtension->DriveParms.DriveType = QIC80_DRIVE; ! 1054: CheckedDump(QIC117INFO,( "Q117i: Drive Type QIC80_DRIVE\n")); ! 1055: ! 1056: } else { ! 1057: ! 1058: TapeExtension->SpeedChangeOK = FALSE; ! 1059: TapeExtension->DriveParms.DriveType = QIC40_DRIVE; ! 1060: CheckedDump(QIC117INFO,( "Q117i: Drive Type QIC40_DRIVE\n")); ! 1061: ! 1062: } ! 1063: ! 1064: } ! 1065: ! 1066: } else if (retval == UnspRate) { ! 1067: ! 1068: TapeExtension->SpeedChangeOK = FALSE; ! 1069: TapeExtension->DriveParms.DriveType = QIC40_DRIVE; ! 1070: CheckedDump(QIC117INFO,( "Q117i: Drive Type QIC40_DRIVE\n")); ! 1071: retval = NoErr; ! 1072: ! 1073: } ! 1074: } ! 1075: } ! 1076: ! 1077: break; ! 1078: ! 1079: case WANGTEK: ! 1080: ! 1081: TapeExtension->DriveParms.SeekMode = SEEK_SKIP; ! 1082: ! 1083: if (!ReportFailed && ! 1084: ((VendorId & ~VENDOR_MASK) == WANGTEK_QIC80)) { ! 1085: ! 1086: TapeExtension->SpeedChangeOK = TRUE; ! 1087: TapeExtension->DriveParms.DriveType = QIC80_DRIVE; ! 1088: CheckedDump(QIC117INFO,( "Q117i: Drive Type QIC80_DRIVE\n")); ! 1089: ! 1090: } else { ! 1091: ! 1092: TapeExtension->DriveParms.DriveType = QIC40_DRIVE; ! 1093: CheckedDump(QIC117INFO,( "Q117i: Drive Type QIC40_DRIVE\n")); ! 1094: ! 1095: } ! 1096: break; ! 1097: ! 1098: case CORE: ! 1099: ! 1100: if ((VendorId & ~VENDOR_MASK) == CORE_QIC80) { ! 1101: ! 1102: TapeExtension->DriveParms.DriveType = QIC80_DRIVE; ! 1103: CheckedDump(QIC117INFO,( "Q117i: Drive Type QIC80_DRIVE\n")); ! 1104: ! 1105: } else { ! 1106: ! 1107: TapeExtension->DriveParms.DriveType = QIC40_DRIVE; ! 1108: CheckedDump(QIC117INFO,( "Q117i: Drive Type QIC40_DRIVE\n")); ! 1109: ! 1110: } ! 1111: break; ! 1112: ! 1113: case IOMEGA: ! 1114: ! 1115: TapeExtension->DriveParms.SeekMode = SEEK_SKIP; ! 1116: TapeExtension->DriveParms.DriveType = QIC80_DRIVE; ! 1117: TapeExtension->SpeedChangeOK = TRUE; ! 1118: CheckedDump(QIC117INFO,( "Q117i: Drive Type QIC80_DRIVE\n")); ! 1119: break; ! 1120: ! 1121: case ARCHIVE: ! 1122: ! 1123: TapeExtension->DriveParms.SeekMode = SEEK_SKIP; ! 1124: ! 1125: if ((retval = Q117iSetDriveMode(TapeExtension, DIAGNOSTIC_1_MODE)) != ! 1126: NoErr) { ! 1127: ! 1128: return(retval); ! 1129: ! 1130: } ! 1131: ! 1132: retval = Q117iGetDriveError(TapeExtension); ! 1133: ! 1134: if (retval == NoErr || retval == NoTape) { ! 1135: ! 1136: if ((retval = Q117iSendByte(TapeExtension, Rpt_Archive_Native_Mode)) != NoErr) { ! 1137: ! 1138: return(retval); ! 1139: ! 1140: } ! 1141: ! 1142: if ((retval = Q117iReceiveByte( ! 1143: TapeExtension, ! 1144: READ_WORD, ! 1145: (USHORT *)&TapeExtension->DriveParms.ArchiveNativeMode ! 1146: )) == NoErr) { ! 1147: ! 1148: TapeExtension->SpeedChangeOK = TRUE; ! 1149: ! 1150: CheckedDump(QIC117INFO,( "Q117i: Archive Native Mode = %x)\n", ! 1151: TapeExtension->DriveParms.ArchiveNativeMode)); ! 1152: ! 1153: if ((TapeExtension->DriveParms.ArchiveNativeMode & ! 1154: ARCHIVE_MODEL_XKEII) != 0) { ! 1155: ! 1156: TapeExtension->DriveParms.SeekMode = SEEK_SKIP_EXTENDED; ! 1157: ! 1158: } ! 1159: ! 1160: if ((TapeExtension->DriveParms.ArchiveNativeMode & ! 1161: ARCHIVE_20_TRACK) != 0) { ! 1162: ! 1163: TapeExtension->DriveParms.DriveType = QIC40_DRIVE; ! 1164: CheckedDump(QIC117INFO,( "Q117i: Drive Type QIC40_DRIVE (Archive Native Mode)\n")); ! 1165: ! 1166: } ! 1167: ! 1168: if ((TapeExtension->DriveParms.ArchiveNativeMode & ! 1169: ARCHIVE_28_TRACK) != 0) { ! 1170: ! 1171: TapeExtension->DriveParms.DriveType = QIC80_DRIVE; ! 1172: CheckedDump(QIC117INFO,( "Q117i: Drive Type QIC80_DRIVE (Archive Native Mode)\n")); ! 1173: ! 1174: } ! 1175: ! 1176: retval = Q117iSetDriveMode(TapeExtension, PRIMARY_MODE); ! 1177: ! 1178: if (retval != NoErr && retval != NoTape) { ! 1179: ! 1180: return(retval); ! 1181: ! 1182: } ! 1183: ! 1184: } ! 1185: ! 1186: } else { ! 1187: ! 1188: if (retval == InvalCmd) { ! 1189: ! 1190: if ((retval = Q117iSendByte(TapeExtension, Soft_Reset)) == NoErr) { ! 1191: ! 1192: Q117iSleep(TapeExtension, (mt_wt001s + mt_wt2ticks), FALSE); ! 1193: ! 1194: if ((retval = Q117iSelectDrive(TapeExtension)) == NoErr) { ! 1195: ! 1196: if ((retval = Q117iReport( ! 1197: TapeExtension, ! 1198: Report_Confg, ! 1199: (USHORT *)&driveConfig, ! 1200: READ_BYTE, ! 1201: NULL)) == NoErr) { ! 1202: ! 1203: if (driveConfig.QIC80) { ! 1204: ! 1205: TapeExtension->DriveParms.DriveType = QIC80_DRIVE; ! 1206: CheckedDump(QIC117INFO,( "Q117i: Drive Type QIC80_DRIVE (Archive Soft Reset)\n")); ! 1207: ! 1208: } else { ! 1209: ! 1210: TapeExtension->DriveParms.DriveType = QIC40_DRIVE; ! 1211: CheckedDump(QIC117INFO,( "Q117i: Drive Type QIC40_DRIVE (Archive Soft Reset)\n")); ! 1212: ! 1213: } ! 1214: } ! 1215: } ! 1216: } ! 1217: ! 1218: } else { ! 1219: ! 1220: return(retval); ! 1221: ! 1222: } ! 1223: } ! 1224: ! 1225: ! 1226: break; ! 1227: ! 1228: default: ! 1229: ! 1230: if ((retval = Q117iSendByte(TapeExtension, Soft_Reset)) == NoErr) { ! 1231: ! 1232: Q117iSleep(TapeExtension, (mt_wt001s + mt_wt2ticks), FALSE); ! 1233: ! 1234: if ((retval = Q117iSelectDrive(TapeExtension)) == NoErr) { ! 1235: ! 1236: if ((retval = Q117iReport( ! 1237: TapeExtension, ! 1238: Report_Confg, ! 1239: (USHORT *)&driveConfig, ! 1240: READ_BYTE, ! 1241: NULL)) == NoErr) { ! 1242: ! 1243: if (driveConfig.QIC80) { ! 1244: ! 1245: TapeExtension->DriveParms.DriveType = QIC80_DRIVE; ! 1246: CheckedDump(QIC117INFO,( "Q117i: Drive Type QIC80_DRIVE\n")); ! 1247: ! 1248: } else { ! 1249: ! 1250: TapeExtension->DriveParms.DriveType = QIC40_DRIVE; ! 1251: CheckedDump(QIC117INFO,( "Q117i: Drive Type QIC40_DRIVE\n")); ! 1252: ! 1253: } ! 1254: } ! 1255: } ! 1256: } ! 1257: } ! 1258: ! 1259: return(retval); ! 1260: } ! 1261: ! 1262: VOID ! 1263: q117iUpdateRegistryInfo( ! 1264: IN PTAPE_EXTENSION TapeExtension ! 1265: ) ! 1266: ! 1267: /*++ ! 1268: ! 1269: Routine Description: ! 1270: ! 1271: This function updates the devicemap. ! 1272: ! 1273: Arguments: ! 1274: ! 1275: TapeExtension - ! 1276: ! 1277: Return Value: ! 1278: ! 1279: Returns the status of the operation. ! 1280: ! 1281: --*/ ! 1282: ! 1283: { ! 1284: HANDLE lunKey; ! 1285: HANDLE unitKey; ! 1286: UNICODE_STRING ntUnicodeString; ! 1287: UNICODE_STRING name; ! 1288: OBJECT_ATTRIBUTES objectAttributes; ! 1289: UNICODE_STRING string; ! 1290: UNICODE_STRING stringNum; ! 1291: WCHAR bufferNum[16]; ! 1292: WCHAR buffer[64]; ! 1293: NTSTATUS status; ! 1294: ! 1295: // ! 1296: // Create the Tape key in the device map. ! 1297: // ! 1298: ! 1299: RtlInitUnicodeString( ! 1300: &name, ! 1301: L"\\Registry\\Machine\\Hardware\\DeviceMap\\Tape" ! 1302: ); ! 1303: ! 1304: // ! 1305: // Initialize the object for the key. ! 1306: // ! 1307: ! 1308: InitializeObjectAttributes( &objectAttributes, ! 1309: &name, ! 1310: OBJ_CASE_INSENSITIVE, ! 1311: NULL, ! 1312: (PSECURITY_DESCRIPTOR) NULL ); ! 1313: ! 1314: // ! 1315: // Create the key or open it. ! 1316: // ! 1317: ! 1318: status = ZwOpenKey(&lunKey, ! 1319: KEY_READ | KEY_WRITE, ! 1320: &objectAttributes ); ! 1321: ! 1322: if (!NT_SUCCESS(status)) { ! 1323: return; ! 1324: } ! 1325: ! 1326: // ! 1327: // Copy the Prefix into a string. ! 1328: // ! 1329: ! 1330: string.Length = 0; ! 1331: string.MaximumLength=64; ! 1332: string.Buffer = buffer; ! 1333: ! 1334: RtlInitUnicodeString(&stringNum, ! 1335: L"Unit "); ! 1336: ! 1337: RtlCopyUnicodeString(&string, &stringNum); ! 1338: ! 1339: // ! 1340: // Create a port number key entry. ! 1341: // ! 1342: ! 1343: stringNum.Length = 0; ! 1344: stringNum.MaximumLength = 16; ! 1345: stringNum.Buffer = bufferNum; ! 1346: ! 1347: CheckedDump(QIC117INFO,( "Q117i: Tape Device Number %d (decimal)\n", TapeExtension->TapeNumber)); ! 1348: status = RtlIntegerToUnicodeString(TapeExtension->TapeNumber, 10, &stringNum); ! 1349: ! 1350: if (!NT_SUCCESS(status)) { ! 1351: return; ! 1352: } ! 1353: ! 1354: // ! 1355: // Append the prefix and the numeric name. ! 1356: // ! 1357: ! 1358: RtlAppendUnicodeStringToString(&string, &stringNum); ! 1359: ! 1360: InitializeObjectAttributes( &objectAttributes, ! 1361: &string, ! 1362: OBJ_CASE_INSENSITIVE, ! 1363: lunKey, ! 1364: (PSECURITY_DESCRIPTOR) NULL ); ! 1365: ! 1366: status = ZwOpenKey(&unitKey, ! 1367: KEY_READ | KEY_WRITE, ! 1368: &objectAttributes ); ! 1369: ! 1370: ZwClose(lunKey); ! 1371: ! 1372: switch (TapeExtension->DriveParms.Flavor) { ! 1373: ! 1374: case CMS: ! 1375: ! 1376: if (TapeExtension->DriveParms.DriveType == QIC80_DRIVE) { ! 1377: ! 1378: RtlInitUnicodeString(&ntUnicodeString, ! 1379: L"Colorado Memory Systems Jumbo 250"); ! 1380: ! 1381: } else { ! 1382: ! 1383: RtlInitUnicodeString(&ntUnicodeString, ! 1384: L"Colorado Memory Systems Jumbo 120"); ! 1385: ! 1386: } ! 1387: ! 1388: break; ! 1389: ! 1390: case SUMMIT: ! 1391: ! 1392: if (TapeExtension->DriveParms.DriveType == QIC80_DRIVE) { ! 1393: ! 1394: RtlInitUnicodeString(&ntUnicodeString, ! 1395: L"Summit QIC-80 floppy tape drive"); ! 1396: ! 1397: } else { ! 1398: ! 1399: RtlInitUnicodeString(&ntUnicodeString, ! 1400: L"Summit QIC-40 floppy tape drive"); ! 1401: ! 1402: } ! 1403: ! 1404: break; ! 1405: ! 1406: case WANGTEK: ! 1407: ! 1408: if (TapeExtension->DriveParms.DriveType == QIC80_DRIVE) { ! 1409: ! 1410: RtlInitUnicodeString(&ntUnicodeString, ! 1411: L"Wangtek QIC-80 floppy tape drive"); ! 1412: ! 1413: } else { ! 1414: ! 1415: RtlInitUnicodeString(&ntUnicodeString, ! 1416: L"Wangtek QIC-40 floppy tape drive"); ! 1417: ! 1418: } ! 1419: ! 1420: break; ! 1421: ! 1422: case CORE: ! 1423: ! 1424: if (TapeExtension->DriveParms.DriveType == QIC80_DRIVE) { ! 1425: ! 1426: RtlInitUnicodeString(&ntUnicodeString, ! 1427: L"Core QIC-80 floppy tape drive"); ! 1428: ! 1429: } else { ! 1430: ! 1431: RtlInitUnicodeString(&ntUnicodeString, ! 1432: L"Core QIC-40 floppy tape drive"); ! 1433: ! 1434: } ! 1435: ! 1436: break; ! 1437: ! 1438: case IOMEGA: ! 1439: ! 1440: if (TapeExtension->DriveParms.DriveType == QIC80_DRIVE) { ! 1441: ! 1442: RtlInitUnicodeString(&ntUnicodeString, ! 1443: L"Iomega QIC-80 floppy tape drive"); ! 1444: ! 1445: } else { ! 1446: ! 1447: RtlInitUnicodeString(&ntUnicodeString, ! 1448: L"Iomega QIC-40 floppy tape drive"); ! 1449: ! 1450: } ! 1451: ! 1452: break; ! 1453: ! 1454: case CMS_ENHANCEMENTS: ! 1455: ! 1456: if (TapeExtension->DriveParms.DriveType == QIC80_DRIVE) { ! 1457: ! 1458: RtlInitUnicodeString(&ntUnicodeString, ! 1459: L"CMS Enhancements QIC-80 floppy tape drive"); ! 1460: ! 1461: } else { ! 1462: ! 1463: RtlInitUnicodeString(&ntUnicodeString, ! 1464: L"CMS Enhancements QIC-40 floppy tape drive"); ! 1465: ! 1466: } ! 1467: ! 1468: break; ! 1469: ! 1470: case ARCHIVE: ! 1471: ! 1472: if (TapeExtension->DriveParms.DriveType == QIC80_DRIVE) { ! 1473: ! 1474: RtlInitUnicodeString(&ntUnicodeString, ! 1475: L"Conner QIC-80 floppy tape drive"); ! 1476: ! 1477: } else { ! 1478: ! 1479: RtlInitUnicodeString(&ntUnicodeString, ! 1480: L"Conner QIC-40 floppy tape drive"); ! 1481: ! 1482: } ! 1483: ! 1484: break; ! 1485: ! 1486: default: ! 1487: ! 1488: RtlInitUnicodeString(&ntUnicodeString, ! 1489: L"QIC-40/QIC-80 floppy tape drive"); ! 1490: } ! 1491: ! 1492: // ! 1493: // Add Identifier value. ! 1494: // ! 1495: ! 1496: RtlInitUnicodeString(&name, L"Identifier"); ! 1497: ! 1498: status = ZwSetValueKey( ! 1499: unitKey, ! 1500: &name, ! 1501: 0, ! 1502: REG_SZ, ! 1503: ntUnicodeString.Buffer, ! 1504: ntUnicodeString.Length ! 1505: ); ! 1506: ! 1507: ZwClose(unitKey); ! 1508: ! 1509: return; ! 1510: ! 1511: } // end q117iUpdateRegistryInfo ! 1512: ! 1513: STATUS ! 1514: Q117iNewTape( ! 1515: IN PTAPE_EXTENSION TapeExtension ! 1516: ) ! 1517: ! 1518: /*++ ! 1519: ! 1520: Routine Description: ! 1521: ! 1522: Determine the format (if any) on a tape cartridge. This routine is ! 1523: executed whenever the driver detects that a new tape has been inserted ! 1524: into the tape drive. ! 1525: ! 1526: Arguments: ! 1527: ! 1528: TapeExtension - ! 1529: ! 1530: Return Value: ! 1531: ! 1532: ! 1533: ! 1534: --*/ ! 1535: ! 1536: { ! 1537: STATUS retval; ! 1538: SHORT writeProtect; ! 1539: ! 1540: // ! 1541: // if we have a qic80 of firmware below a certain value ! 1542: // (FIRM_VERSION_63), and if we have an ! 1543: // unreferenced tape, and a cartridge is in the drive, ! 1544: // then we re-try the reference burst. Only if the ! 1545: // retry fails do we return an error. ! 1546: // ! 1547: // The firmware should do the retry automatically, but at the moment ! 1548: // it does not. This will be corrected, and the retry not commanded, ! 1549: // at some time to be determined. At that time, it should only be ! 1550: // necessary to change the #define used to determine the firmware ! 1551: // rev level. -- crc ! 1552: // ! 1553: // Check to see if the drive is a Jumbo B with firmware 63. This ! 1554: // firmware has 2 bugs. If the tape is put in slowly, it can incorrectly ! 1555: // return an invalid media error or write protect status. ! 1556: // ! 1557: ! 1558: if (TapeExtension->DriveParms.Version <= FIRM_VERSION_63 && ! 1559: TapeExtension->DriveParms.Version >= FIRM_VERSION_60 && ! 1560: TapeExtension->DriveParms.Flavor == CMS) { ! 1561: ! 1562: retval = Q117iGetDriveError(TapeExtension); ! 1563: ! 1564: if (retval == TapeFlt && TapeExtension->FirmwareError == Inval_Media) { ! 1565: ! 1566: // ! 1567: // Fix both the invalid media error by sending a NewTape command ! 1568: // to the drive. ! 1569: ! 1570: retval = Q117iClearTapeError(TapeExtension); ! 1571: ! 1572: } else { ! 1573: ! 1574: // ! 1575: // Read the write protect status directly from port 2 on ! 1576: // the Jumbo B processor to determine if the drive got a ! 1577: // bogus write protect error. ! 1578: // ! 1579: ! 1580: if (TapeExtension->DriveParms.Status.WriteProtect && ! 1581: (retval = Q117iReadWrtProtect(TapeExtension, &writeProtect)) ! 1582: == NoErr) { ! 1583: ! 1584: if (writeProtect == FALSE) { ! 1585: ! 1586: retval = Q117iClearTapeError(TapeExtension); ! 1587: ! 1588: } ! 1589: } ! 1590: } ! 1591: ! 1592: if (retval != NoErr) { ! 1593: ! 1594: return(retval); ! 1595: ! 1596: } ! 1597: } ! 1598: ! 1599: retval = Q117iGetDriveError(TapeExtension); ! 1600: ! 1601: if (TapeExtension->DriveParms.Status.Referenced == FALSE && ! 1602: TapeExtension->DriveParms.Status.CartPresent == TRUE && ! 1603: TapeExtension->DriveParms.Flavor == CMS && ! 1604: TapeExtension->DriveParms.Version >= FIRM_VERSION_60 && ! 1605: TapeExtension->DriveParms.Version <= FIRM_VERSION_63) { ! 1606: ! 1607: // ! 1608: // command: seek reference burst. N.b: Non-interruptible! ! 1609: // ! 1610: ! 1611: if ((retval = Q117iSendByte(TapeExtension, Seek_LP)) != NoErr) { ! 1612: ! 1613: return(retval); ! 1614: ! 1615: } ! 1616: ! 1617: // ! 1618: // Wait for the drive to become ready again. ! 1619: // ! 1620: ! 1621: if ((retval = Q117iWaitCommandComplete(TapeExtension, mt_wt105s)) != ! 1622: NoErr) { ! 1623: ! 1624: return(retval); ! 1625: ! 1626: } ! 1627: } ! 1628: ! 1629: // ! 1630: // Rewind tape -- needed for Archive drives ! 1631: // ! 1632: ! 1633: if ((TapeExtension->DriveParms.Status.CartPresent == TRUE) && ! 1634: ((TapeExtension->DriveParms.Flavor == IOMEGA) || ! 1635: (TapeExtension->DriveParms.Flavor == ARCHIVE))) { ! 1636: ! 1637: retval = Q117iGetDriveError(TapeExtension); ! 1638: ! 1639: if (TapeExtension->DriveParms.Status.BOT == FALSE) { ! 1640: ! 1641: if ((retval = Q117iSendByte(TapeExtension, Physical_Rev)) != NoErr) { ! 1642: ! 1643: return(retval); ! 1644: ! 1645: } ! 1646: ! 1647: // ! 1648: // Wait for the drive to become ready again. ! 1649: // ! 1650: ! 1651: if ((retval = Q117iWaitCommandComplete(TapeExtension, mt_wt460s)) != ! 1652: NoErr) { ! 1653: ! 1654: return(retval); ! 1655: ! 1656: } ! 1657: } ! 1658: ! 1659: if (TapeExtension->DriveParms.Status.Referenced == FALSE) { ! 1660: ! 1661: // ! 1662: // command: seek reference burst. N.b: Non-interruptible! ! 1663: // ! 1664: ! 1665: if ((retval = Q117iSendByte(TapeExtension, Seek_LP)) != NoErr) { ! 1666: ! 1667: return(retval); ! 1668: ! 1669: } ! 1670: ! 1671: // ! 1672: // Wait for the drive to become ready again. ! 1673: // ! 1674: ! 1675: if ((retval = Q117iWaitCommandComplete(TapeExtension, mt_wt460s)) != ! 1676: NoErr) { ! 1677: ! 1678: return(retval); ! 1679: ! 1680: } ! 1681: } ! 1682: } ! 1683: ! 1684: ! 1685: if ((retval = Q117iGetTapeParameters(TapeExtension)) != NoErr) { ! 1686: ! 1687: return(retval); ! 1688: ! 1689: } ! 1690: ! 1691: TapeExtension->TapePosition.C_Track = -1; ! 1692: TapeExtension->DriveParms.Mode = PRIMARY_MODE; ! 1693: TapeExtension->NewCart = FALSE; ! 1694: ! 1695: if ((TapeExtension->TapeParms.TapeType == QIC80_SHORT || ! 1696: TapeExtension->TapeParms.TapeType == QIC80_LONG || ! 1697: TapeExtension->TapeParms.TapeType == QICEST_80) && ! 1698: (TapeExtension->DriveParms.DriveType == QIC40_DRIVE)) { ! 1699: ! 1700: return(WrongFmt); ! 1701: ! 1702: } ! 1703: ! 1704: if (TapeExtension->XferRate.TapeFast == TAPE_2Mbps) { ! 1705: ! 1706: if (TapeExtension->TapeParms.TapeType == QIC40_SHORT || ! 1707: TapeExtension->TapeParms.TapeType == QIC40_LONG || ! 1708: TapeExtension->TapeParms.TapeType == QICEST_40) { ! 1709: ! 1710: TapeExtension->XferRate.XferRate = SLOW; ! 1711: TapeExtension->XferRate.MaxRate = SLOW; ! 1712: TapeExtension->XferRate.TapeSlow = TAPE_500Kbps; ! 1713: TapeExtension->XferRate.FDC_Slow = FDC_500Kbps; ! 1714: TapeExtension->XferRate.SRT_Slow = SRT_500Kbps; ! 1715: retval = Q117iDFast_DSlow(TapeExtension, DSlow); ! 1716: ! 1717: } else { ! 1718: ! 1719: if (TapeExtension->TapeParms.TapeType == QIC80_SHORT || ! 1720: TapeExtension->TapeParms.TapeType == QIC80_LONG || ! 1721: TapeExtension->TapeParms.TapeType == QICEST_80) { ! 1722: ! 1723: TapeExtension->XferRate.XferRate = SLOW; ! 1724: retval = Q117iDFast_DSlow(TapeExtension, DSlow); ! 1725: ! 1726: } ! 1727: } ! 1728: } ! 1729: ! 1730: if (TapeExtension->XferRate.TapeFast == TAPE_1Mbps) { ! 1731: ! 1732: if (TapeExtension->TapeParms.TapeType == QIC40_SHORT || ! 1733: TapeExtension->TapeParms.TapeType == QIC40_LONG || ! 1734: TapeExtension->TapeParms.TapeType == QICEST_40) { ! 1735: ! 1736: TapeExtension->XferRate.XferRate = SLOW; ! 1737: retval = Q117iDFast_DSlow(TapeExtension, DSlow); ! 1738: ! 1739: } else { ! 1740: ! 1741: TapeExtension->XferRate.XferRate = TapeExtension->XferRate.MaxRate; ! 1742: ! 1743: if (TapeExtension->XferRate.XferRate == SLOW) { ! 1744: ! 1745: retval = Q117iDFast_DSlow(TapeExtension, DSlow); ! 1746: ! 1747: } else { ! 1748: ! 1749: retval = Q117iDFast_DSlow(TapeExtension, DFast); ! 1750: ! 1751: } ! 1752: } ! 1753: } ! 1754: ! 1755: return(retval); ! 1756: } ! 1757: ! 1758: ! 1759: STATUS ! 1760: Q117iReadWrtProtect( ! 1761: IN PTAPE_EXTENSION TapeExtension, ! 1762: OUT SHORT *WriteProtect ! 1763: ) ! 1764: ! 1765: /*++ ! 1766: ! 1767: Routine Description: ! 1768: ! 1769: Reads the write protect status from the drive processor itself. ! 1770: ! 1771: This procedure is used due to the firmware 63 error where a tape put ! 1772: into the drive very slowly can cause the status byte to say (incorrectly) ! 1773: that the tape is write protected. It uses a Diagnostic command to read ! 1774: port 2 of the processor on the drive. ! 1775: ! 1776: Arguments: ! 1777: ! 1778: TapeExtension - ! 1779: ! 1780: WriteProtect - ! 1781: ! 1782: Return Value: ! 1783: ! 1784: ! 1785: ! 1786: --*/ ! 1787: ! 1788: { ! 1789: STATUS retval; ! 1790: UCHAR port2Val; // The port value from which the "real" ! 1791: // write protect is read (bit 5) ! 1792: ! 1793: if ((retval = Q117iSetDriveMode(TapeExtension, DIAGNOSTIC_1_MODE)) == ! 1794: NoErr) { ! 1795: ! 1796: if ((retval = Q117iReport( ! 1797: TapeExtension, ! 1798: Read_Port2, ! 1799: (USHORT *)&port2Val, ! 1800: READ_BYTE, ! 1801: NULL)) == NoErr) { ! 1802: ! 1803: // ! 1804: // If bit 5 of port 2 on the return byte is 1, then the tape ! 1805: // is "really" write protected. ! 1806: // ! 1807: ! 1808: if (port2Val & WRITE_PROTECT_MASK) { ! 1809: ! 1810: *WriteProtect = TRUE; ! 1811: ! 1812: } else { ! 1813: ! 1814: *WriteProtect = FALSE; ! 1815: ! 1816: } ! 1817: ! 1818: retval = Q117iSetDriveMode(TapeExtension, PRIMARY_MODE); ! 1819: } ! 1820: } ! 1821: ! 1822: return(retval); ! 1823: } ! 1824: ! 1825: ! 1826: STATUS ! 1827: Q117iGetTapeParameters( ! 1828: IN PTAPE_EXTENSION TapeExtension ! 1829: ) ! 1830: ! 1831: /*++ ! 1832: ! 1833: Routine Description: ! 1834: ! 1835: Sets up the necessary tape capacity parameters in the driver according ! 1836: to the tape type (QIC40 or QIC80) and tape length (normal or extra length). ! 1837: ! 1838: Arguments : ! 1839: ! 1840: TapeExtension - ! 1841: ! 1842: Return Value: ! 1843: ! 1844: ! 1845: ! 1846: --*/ ! 1847: ! 1848: { ! 1849: STATUS retval; ! 1850: CHAR orgMode; ! 1851: struct DriveConfiguration driveConfig; ! 1852: struct CmsStatus cmsStatus; ! 1853: struct TapeFormatLgth tapeFormatLength; ! 1854: BOOLEAN reportFailed = FALSE; ! 1855: ! 1856: if ((retval = Q117iReport( ! 1857: TapeExtension, ! 1858: Report_Confg, ! 1859: (USHORT *)&driveConfig, ! 1860: READ_BYTE, ! 1861: NULL)) != NoErr) { ! 1862: ! 1863: return(retval); ! 1864: ! 1865: } ! 1866: ! 1867: /* Make a call to Report Tape Status */ ! 1868: if ((retval = Q117iReport( ! 1869: TapeExtension, ! 1870: Report_Tape_Stat, ! 1871: (USHORT *)&tapeFormatLength, ! 1872: READ_BYTE, ! 1873: NULL)) != NoErr) { ! 1874: ! 1875: Q117iGetDriveError(TapeExtension); ! 1876: retval = NoErr; ! 1877: reportFailed = TRUE; ! 1878: tapeFormatLength.Format = 0; ! 1879: tapeFormatLength.Length = 0; ! 1880: } ! 1881: ! 1882: if (!driveConfig.XL_Tape) { ! 1883: ! 1884: if (!driveConfig.QIC80) { ! 1885: ! 1886: if (!reportFailed && tapeFormatLength.Format == QIC_500) { ! 1887: ! 1888: CheckedDump(QIC117INFO,( "Q117i: Tape Type QIC500_SHORT\n")); ! 1889: TapeExtension->TapeParms.TapeType = QIC500_SHORT; ! 1890: TapeExtension->TapeParms.FtrackFside = FTK_FSD_500; ! 1891: TapeExtension->TapeParms.SegTtrack = SEG_TTRK_500; ! 1892: TapeExtension->TapeParms.FsectFside = FSC_FTK * FTK_FSD_500; ! 1893: TapeExtension->TapeParms.LogSectors = FSC_SEG * SEG_TTRK_500 * NUM_TTRK_500; ! 1894: TapeExtension->TapeParms.FsectTtrack = FSC_SEG * SEG_TTRK_500; ! 1895: TapeExtension->TapeParms.TimeOut[L_SLOW] = mt_wt130s; ! 1896: TapeExtension->TapeParms.TimeOut[L_FAST] = mt_wt065s; ! 1897: TapeExtension->TapeParms.TimeOut[PHYSICAL] = mt_wt065s; ! 1898: ! 1899: } else { ! 1900: ! 1901: // Assume that the tape is a Standard length QIC40 ! 1902: CheckedDump(QIC117INFO,( "Q117i: Tape Type QIC40_SHORT\n")); ! 1903: TapeExtension->TapeParms.TapeType = QIC40_SHORT; ! 1904: TapeExtension->TapeParms.FtrackFside = FTK_FSD_40; ! 1905: TapeExtension->TapeParms.SegTtrack = SEG_TTRK_40; ! 1906: TapeExtension->TapeParms.FsectFside = FSC_FTK * FTK_FSD_40; ! 1907: TapeExtension->TapeParms.LogSectors = FSC_SEG * SEG_TTRK_40 * NUM_TTRK_40; ! 1908: TapeExtension->TapeParms.FsectTtrack = FSC_SEG * SEG_TTRK_40; ! 1909: TapeExtension->TapeParms.TimeOut[L_SLOW] = mt_wt130s; ! 1910: TapeExtension->TapeParms.TimeOut[L_FAST] = mt_wt065s; ! 1911: TapeExtension->TapeParms.TimeOut[PHYSICAL] = mt_wt065s; ! 1912: ! 1913: } ! 1914: ! 1915: ! 1916: } else { ! 1917: ! 1918: CheckedDump(QIC117INFO,( "Q117i: Tape Type QIC80_SHORT\n")); ! 1919: TapeExtension->TapeParms.TapeType = QIC80_SHORT; ! 1920: TapeExtension->TapeParms.FtrackFside = FTK_FSD_80; ! 1921: TapeExtension->TapeParms.SegTtrack = SEG_TTRK_80; ! 1922: TapeExtension->TapeParms.FsectFside = FSC_FTK * FTK_FSD_80; ! 1923: TapeExtension->TapeParms.LogSectors = (ULONG)FSC_SEG * ! 1924: (ULONG)SEG_TTRK_80 * ! 1925: (ULONG)NUM_TTRK_80; ! 1926: TapeExtension->TapeParms.FsectTtrack = FSC_SEG * SEG_TTRK_80; ! 1927: TapeExtension->TapeParms.TimeOut[L_SLOW] = mt_wt100s; ! 1928: TapeExtension->TapeParms.TimeOut[L_FAST] = mt_wt050s; ! 1929: TapeExtension->TapeParms.TimeOut[PHYSICAL] = mt_wt050s; ! 1930: ! 1931: } ! 1932: ! 1933: } else { ! 1934: ! 1935: ! 1936: if (!driveConfig.QIC80) { ! 1937: ! 1938: if (!reportFailed) { ! 1939: ! 1940: switch (tapeFormatLength.Length) { ! 1941: ! 1942: case (QICEST_900): ! 1943: ! 1944: CheckedDump(QIC117INFO,( "Q117i: Tape Type QICEST_500\n")); ! 1945: TapeExtension->TapeParms.TapeType = QICEST_500; ! 1946: TapeExtension->TapeParms.FtrackFside = FTK_FSD_QICEST_500; ! 1947: TapeExtension->TapeParms.SegTtrack = SEG_TTRK_500; ! 1948: TapeExtension->TapeParms.FsectFside = FSC_FTK * FTK_FSD_QICEST_500; ! 1949: TapeExtension->TapeParms.LogSectors = FSC_SEG * SEG_TTRK_500 * NUM_TTRK_500; ! 1950: TapeExtension->TapeParms.FsectTtrack = FSC_SEG * SEG_TTRK_500; ! 1951: TapeExtension->TapeParms.TimeOut[L_SLOW] = mt_wt700s; ! 1952: TapeExtension->TapeParms.TimeOut[L_FAST] = mt_wt350s; ! 1953: TapeExtension->TapeParms.TimeOut[PHYSICAL] = mt_wt350s; ! 1954: break; ! 1955: ! 1956: case (QICEST): ! 1957: ! 1958: CheckedDump(QIC117INFO,( "Q117i: Tape Type QICEST_40\n")); ! 1959: TapeExtension->TapeParms.TapeType = QICEST_40; ! 1960: TapeExtension->TapeParms.FtrackFside = FTK_FSD_QICEST_40; ! 1961: TapeExtension->TapeParms.SegTtrack = SEG_TTRK_QICEST_40; ! 1962: TapeExtension->TapeParms.FsectFside = FSC_FTK * FTK_FSD_QICEST_40; ! 1963: TapeExtension->TapeParms.LogSectors = (ULONG)FSC_SEG * ! 1964: (ULONG)SEG_TTRK_QICEST_40 * ! 1965: (ULONG)NUM_TTRK_40; ! 1966: TapeExtension->TapeParms.FsectTtrack = FSC_SEG * SEG_TTRK_QICEST_40; ! 1967: TapeExtension->TapeParms.TimeOut[L_SLOW] = mt_wt700s; ! 1968: TapeExtension->TapeParms.TimeOut[L_FAST] = mt_wt350s; ! 1969: TapeExtension->TapeParms.TimeOut[PHYSICAL] = mt_wt350s; ! 1970: break; ! 1971: ! 1972: case (QIC_LONG): ! 1973: ! 1974: CheckedDump(QIC117INFO,( "Q117i: Tape Type QIC40_LONG\n")); ! 1975: TapeExtension->TapeParms.TapeType = QIC40_LONG; ! 1976: TapeExtension->TapeParms.FtrackFside = FTK_FSD_40L; ! 1977: TapeExtension->TapeParms.SegTtrack = SEG_TTRK_40L; ! 1978: TapeExtension->TapeParms.FsectFside = FSC_FTK * FTK_FSD_40L; ! 1979: TapeExtension->TapeParms.LogSectors = FSC_SEG * SEG_TTRK_40L * NUM_TTRK_40; ! 1980: TapeExtension->TapeParms.FsectTtrack = FSC_SEG * SEG_TTRK_40L; ! 1981: TapeExtension->TapeParms.TimeOut[L_SLOW] = mt_wt200s; ! 1982: TapeExtension->TapeParms.TimeOut[L_FAST] = mt_wt100s; ! 1983: TapeExtension->TapeParms.TimeOut[PHYSICAL] = mt_wt100s; ! 1984: break; ! 1985: } ! 1986: ! 1987: } else { ! 1988: ! 1989: // Assume that the tape type is QIC40_Long ! 1990: CheckedDump(QIC117INFO,( "Q117i: Tape Type QIC40_LONG\n")); ! 1991: TapeExtension->TapeParms.TapeType = QIC40_LONG; ! 1992: TapeExtension->TapeParms.FtrackFside = FTK_FSD_40L; ! 1993: TapeExtension->TapeParms.SegTtrack = SEG_TTRK_40L; ! 1994: TapeExtension->TapeParms.FsectFside = ! 1995: FSC_FTK * FTK_FSD_40L; ! 1996: TapeExtension->TapeParms.LogSectors = ! 1997: FSC_SEG * SEG_TTRK_40L * NUM_TTRK_40; ! 1998: TapeExtension->TapeParms.FsectTtrack = ! 1999: FSC_SEG * SEG_TTRK_40L; ! 2000: TapeExtension->TapeParms.TimeOut[L_SLOW] = mt_wt200s; ! 2001: TapeExtension->TapeParms.TimeOut[L_FAST] = mt_wt100s; ! 2002: TapeExtension->TapeParms.TimeOut[PHYSICAL] = mt_wt100s; ! 2003: } ! 2004: ! 2005: } else { ! 2006: ! 2007: // drive_config.QIC80 == TRUE ! 2008: ! 2009: if (!reportFailed) { ! 2010: ! 2011: switch (tapeFormatLength.Length) { ! 2012: ! 2013: case (QICEST): ! 2014: ! 2015: CheckedDump(QIC117INFO,( "Q117i: Tape Type QICEST_80\n")); ! 2016: TapeExtension->TapeParms.TapeType = QICEST_80; ! 2017: TapeExtension->TapeParms.FtrackFside = FTK_FSD_QICEST_80; ! 2018: TapeExtension->TapeParms.SegTtrack = SEG_TTRK_QICEST_80; ! 2019: TapeExtension->TapeParms.FsectFside = FSC_FTK * FTK_FSD_QICEST_80; ! 2020: TapeExtension->TapeParms.LogSectors = (ULONG)FSC_SEG * ! 2021: (ULONG)SEG_TTRK_QICEST_80 * ! 2022: (ULONG)NUM_TTRK_80; ! 2023: TapeExtension->TapeParms.FsectTtrack = FSC_SEG * SEG_TTRK_QICEST_80; ! 2024: TapeExtension->TapeParms.TimeOut[L_SLOW] = mt_wt475s; ! 2025: TapeExtension->TapeParms.TimeOut[L_FAST] = mt_wt250s; ! 2026: TapeExtension->TapeParms.TimeOut[PHYSICAL] = mt_wt250s; ! 2027: break; ! 2028: ! 2029: case (QIC_LONG): ! 2030: ! 2031: CheckedDump(QIC117INFO,( "Q117i: Tape Type QIC80_LONG\n")); ! 2032: TapeExtension->TapeParms.TapeType = QIC80_LONG; ! 2033: TapeExtension->TapeParms.FtrackFside = FTK_FSD_80L; ! 2034: TapeExtension->TapeParms.SegTtrack = SEG_TTRK_80L; ! 2035: TapeExtension->TapeParms.FsectFside = FSC_FTK * FTK_FSD_80L; ! 2036: TapeExtension->TapeParms.LogSectors = (ULONG)FSC_SEG * ! 2037: (ULONG)SEG_TTRK_80L * ! 2038: (ULONG)NUM_TTRK_80; ! 2039: TapeExtension->TapeParms.FsectTtrack = FSC_SEG * SEG_TTRK_80L; ! 2040: TapeExtension->TapeParms.TimeOut[L_SLOW] = mt_wt130s; ! 2041: TapeExtension->TapeParms.TimeOut[L_FAST] = mt_wt065s; ! 2042: TapeExtension->TapeParms.TimeOut[PHYSICAL] = mt_wt065s; ! 2043: break; ! 2044: ! 2045: } ! 2046: ! 2047: } else { ! 2048: ! 2049: // Assume it is a QIC80_LONG ! 2050: ! 2051: CheckedDump(QIC117INFO,( "Q117i: Tape Type QIC80_LONG\n")); ! 2052: TapeExtension->TapeParms.TapeType = QIC80_LONG; ! 2053: TapeExtension->TapeParms.FtrackFside = FTK_FSD_80L; ! 2054: TapeExtension->TapeParms.SegTtrack = SEG_TTRK_80L; ! 2055: TapeExtension->TapeParms.FsectFside = FSC_FTK * FTK_FSD_80L; ! 2056: TapeExtension->TapeParms.LogSectors = (ULONG)FSC_SEG * ! 2057: (ULONG)SEG_TTRK_80L * ! 2058: (ULONG)NUM_TTRK_80; ! 2059: TapeExtension->TapeParms.FsectTtrack = FSC_SEG * SEG_TTRK_80L; ! 2060: TapeExtension->TapeParms.TimeOut[L_SLOW] = mt_wt130s; ! 2061: TapeExtension->TapeParms.TimeOut[L_FAST] = mt_wt065s; ! 2062: TapeExtension->TapeParms.TimeOut[PHYSICAL] = mt_wt065s; ! 2063: ! 2064: } ! 2065: } ! 2066: } ! 2067: ! 2068: TapeExtension->TapeParms.FsectSeg = FSC_SEG; ! 2069: TapeExtension->TapeParms.SegFtrack = SEG_FTK; ! 2070: TapeExtension->TapeParms.FsectFtrack = FSC_FTK; ! 2071: TapeExtension->TapeParms.RwGapLength = WRT_GPL; ! 2072: ! 2073: ! 2074: if ((TapeExtension->DriveParms.Flavor == CMS) && ! 2075: ((TapeExtension->DriveParms.Version >= FIRM_VERSION_60) && ! 2076: (TapeExtension->DriveParms.Version < FIRM_VERSION_87 ))) { ! 2077: ! 2078: if (driveConfig.XL_Tape) { ! 2079: ! 2080: if ((retval = Q117iSetDriveMode(TapeExtension, ! 2081: DIAGNOSTIC_1_MODE)) != NoErr) { ! 2082: ! 2083: return(retval); ! 2084: ! 2085: } ! 2086: ! 2087: if ((retval = Q117iReport( ! 2088: TapeExtension, ! 2089: Rpt_CMS_Status, ! 2090: (USHORT *)&cmsStatus, ! 2091: READ_BYTE, ! 2092: NULL)) != NoErr) { ! 2093: ! 2094: return(retval); ! 2095: ! 2096: } else { ! 2097: ! 2098: if (cmsStatus.Pegasus) { ! 2099: ! 2100: tapeFormatLength.Length = QICEST; ! 2101: ! 2102: } ! 2103: ! 2104: ! 2105: } ! 2106: ! 2107: // ! 2108: // Put drive back into its original mode. ! 2109: // ! 2110: ! 2111: if ((retval = Q117iSetDriveMode(TapeExtension, ! 2112: PRIMARY_MODE)) != NoErr) { ! 2113: ! 2114: return(retval); ! 2115: ! 2116: } ! 2117: ! 2118: ! 2119: } ! 2120: ! 2121: } ! 2122: ! 2123: // Determine the Tape Format Code ! 2124: ! 2125: if (tapeFormatLength.Length == QICEST || ! 2126: tapeFormatLength.Length == QICEST_900) { ! 2127: ! 2128: CheckedDump(QIC117INFO,( "Q117i: Tape Format Code QICEST_FORMAT\n")); ! 2129: TapeExtension->TapeParms.TapeFormatCode = QICEST_FORMAT; ! 2130: ! 2131: if ( TapeExtension->DriveParms.Flavor == WANGTEK) { ! 2132: ! 2133: TapeExtension->DriveParms.SeekMode = SEEK_SKIP_EXTENDED; ! 2134: ! 2135: } ! 2136: ! 2137: if (!TapeExtension->PegasusSupported) { ! 2138: ! 2139: retval = TapeFlt; ! 2140: ! 2141: } else { ! 2142: ! 2143: if ( (TapeExtension->DriveParms.Flavor == CMS) && ! 2144: (TapeExtension->TapeParms.TapeType == QICEST_40) ) { ! 2145: ! 2146: retval = TapeFlt; ! 2147: ! 2148: } ! 2149: ! 2150: } ! 2151: } else { ! 2152: ! 2153: CheckedDump(QIC117INFO,( "Q117i: Tape Format Code QIC_FORMAT\n")); ! 2154: TapeExtension->TapeParms.TapeFormatCode = QIC_FORMAT; ! 2155: ! 2156: } ! 2157: ! 2158: Q117iCalcFmtSegmentsAndTracks( TapeExtension ); ! 2159: ! 2160: return(retval); ! 2161: } ! 2162: ! 2163: ! 2164: VOID ! 2165: Q117iCalcFmtSegmentsAndTracks( ! 2166: IN PTAPE_EXTENSION TapeExtension ! 2167: ) ! 2168: ! 2169: /*++ ! 2170: ! 2171: Routine Description: ! 2172: ! 2173: Calculate the number of formattable segments given the current tape and ! 2174: drive type, and the number of tracks. ! 2175: ! 2176: Arguments: ! 2177: ! 2178: TapeExtension - ! 2179: ! 2180: FormattableSegments - ! 2181: ! 2182: Tracks - ! 2183: ! 2184: Return Value: ! 2185: ! 2186: None ! 2187: ! 2188: --*/ ! 2189: ! 2190: { ! 2191: switch (TapeExtension->DriveParms.DriveType) { ! 2192: ! 2193: case (QIC80_DRIVE): ! 2194: ! 2195: // ! 2196: //Choose the segments per tape track value according to the length ! 2197: // of the tape. ! 2198: // ! 2199: ! 2200: switch (TapeExtension->TapeParms.TapeType) { ! 2201: ! 2202: case (QIC40_SHORT): ! 2203: case (QIC80_SHORT): ! 2204: ! 2205: TapeExtension->TapeParms.FormattableSegs = (USHORT)SEG_TTRK_80; ! 2206: break; ! 2207: ! 2208: case (QIC40_LONG): ! 2209: case (QIC80_LONG): ! 2210: ! 2211: TapeExtension->TapeParms.FormattableSegs = (USHORT)SEG_TTRK_80L; ! 2212: break; ! 2213: ! 2214: case (QICEST_40): ! 2215: case (QICEST_80): ! 2216: ! 2217: TapeExtension->TapeParms.FormattableSegs = (USHORT)SEG_TTRK_QICEST_80; ! 2218: break; ! 2219: ! 2220: } ! 2221: ! 2222: if ((TapeExtension->NumTracks > NUM_TTRK_80) || ! 2223: (TapeExtension->NumTracks == 0)) { ! 2224: ! 2225: TapeExtension->TapeParms.FormattableSegs *= (USHORT)NUM_TTRK_80; ! 2226: TapeExtension->TapeParms.NumTtrack = (USHORT)NUM_TTRK_80; ! 2227: ! 2228: } else { ! 2229: ! 2230: TapeExtension->TapeParms.FormattableSegs *= (USHORT)TapeExtension->NumTracks; ! 2231: TapeExtension->TapeParms.NumTtrack = (USHORT)TapeExtension->NumTracks; ! 2232: ! 2233: } ! 2234: break; ! 2235: ! 2236: case (QIC40_DRIVE): ! 2237: ! 2238: // ! 2239: // Since a QIC40 drive can not detect a QIC80 formatted tape, ! 2240: // the seg_ttrack field in Q117itape_parms is correct. ! 2241: // ! 2242: ! 2243: TapeExtension->TapeParms.FormattableSegs = (USHORT)TapeExtension->TapeParms.SegTtrack; ! 2244: ! 2245: if ((TapeExtension->NumTracks == 0) || ! 2246: (TapeExtension->NumTracks > NUM_TTRK_40)) { ! 2247: ! 2248: TapeExtension->TapeParms.FormattableSegs *= (USHORT)NUM_TTRK_40; ! 2249: TapeExtension->TapeParms.NumTtrack = (USHORT)NUM_TTRK_40; ! 2250: ! 2251: } else { ! 2252: ! 2253: TapeExtension->TapeParms.FormattableSegs *= (USHORT)TapeExtension->NumTracks; ! 2254: TapeExtension->TapeParms.NumTtrack = (USHORT)TapeExtension->NumTracks; ! 2255: ! 2256: } ! 2257: break; ! 2258: ! 2259: case (QIC500_DRIVE): ! 2260: ! 2261: if (TapeExtension->TapeParms.TapeType == QICEST_500 || ! 2262: TapeExtension->TapeParms.TapeType == QIC500_SHORT) { ! 2263: ! 2264: TapeExtension->TapeParms.FormattableSegs = (USHORT)TapeExtension->TapeParms.SegTtrack; ! 2265: ! 2266: } else { ! 2267: ! 2268: // A QIC40 or a QIC80 tape was detected in a QIC500_DRIVE drive ! 2269: ! 2270: TapeExtension->TapeParms.FormattableSegs = (USHORT)0; ! 2271: ! 2272: } ! 2273: ! 2274: if ((TapeExtension->NumTracks == 0) || ! 2275: (TapeExtension->NumTracks > NUM_TTRK_500)) { ! 2276: ! 2277: TapeExtension->TapeParms.FormattableSegs *= (USHORT)NUM_TTRK_500; ! 2278: TapeExtension->TapeParms.NumTtrack = (USHORT)NUM_TTRK_500; ! 2279: ! 2280: } else { ! 2281: ! 2282: TapeExtension->TapeParms.FormattableSegs *= (USHORT)TapeExtension->NumTracks; ! 2283: TapeExtension->TapeParms.NumTtrack = (USHORT)TapeExtension->NumTracks; ! 2284: ! 2285: } ! 2286: break; ! 2287: ! 2288: } ! 2289: ! 2290: } ! 2291: ! 2292: ! 2293: STATUS ! 2294: Q117iMtnPreamble( ! 2295: IN PTAPE_EXTENSION TapeExtension, ! 2296: IN BOOLEAN Select ! 2297: ) ! 2298: ! 2299: /*++ ! 2300: ! 2301: Routine Description: ! 2302: ! 2303: ! 2304: Arguments: ! 2305: ! 2306: TapeExtension - ! 2307: ! 2308: Return Value: ! 2309: ! 2310: None ! 2311: ! 2312: --*/ ! 2313: ! 2314: { ! 2315: STATUS retval; ! 2316: ! 2317: if (Select) { ! 2318: ! 2319: if ((retval = Q117iSendByte(TapeExtension, Mtn_Select_1)) == NoErr) { ! 2320: ! 2321: Q117iSleep(TapeExtension, mt_wt2ticks, FALSE); ! 2322: retval = Q117iSendByte(TapeExtension, Mtn_Select_2); ! 2323: Q117iSleep(TapeExtension, mt_wt2ticks, FALSE); ! 2324: ! 2325: } ! 2326: ! 2327: } else { ! 2328: ! 2329: retval = Q117iSendByte(TapeExtension, Mtn_Deselect); ! 2330: Q117iSleep(TapeExtension, mt_wt2ticks, FALSE); ! 2331: ! 2332: } ! 2333: ! 2334: return(retval); ! 2335: } ! 2336: ! 2337: ! 2338: STATUS ! 2339: Q117iGetDriveInfo( ! 2340: IN PTAPE_EXTENSION TapeExtension ! 2341: ) ! 2342: ! 2343: /*++ ! 2344: ! 2345: Routine Description: ! 2346: ! 2347: Gets the following Drive information: ! 2348: ! 2349: 1) Drive Type/Model ! 2350: 2) Firmware Revision ! 2351: 3) OEM Field Flag ! 2352: 4) OEM Field ! 2353: 5) Serial Number ! 2354: 6) Date of manufacture ! 2355: ! 2356: The OEM, Serial Number and the Date of manufacture are miscellaneous ! 2357: drive train information that is embedded in the drive's firmware. ! 2358: ! 2359: If the drive type is not CMS and/or the firmware revision is pre-80 ! 2360: then zeros are returned in these fields. The drive type is obtained by ! 2361: making a call to Rpt_Cms_Status. This has been done to support the Jumbo ! 2362: B platform. ! 2363: ! 2364: Arguments: ! 2365: ! 2366: TapeExtension - ! 2367: ! 2368: Return Value: ! 2369: ! 2370: ! 2371: ! 2372: --*/ ! 2373: ! 2374: { ! 2375: struct CmsStatus cmsStatus; ! 2376: CHAR currentMode; ! 2377: UCHAR bitBucket; ! 2378: SHORT i; ! 2379: STATUS retval; ! 2380: ! 2381: // ! 2382: // Initialize the Drive Train Miscellaneous Information value to NULL ! 2383: // ! 2384: ! 2385: TapeExtension->MiscDriveInfo.InfoExists = FALSE; ! 2386: TapeExtension->MiscDriveInfo.SerialNumber[0] = '\0'; ! 2387: TapeExtension->MiscDriveInfo.ManDate[0] = '\0'; ! 2388: TapeExtension->MiscDriveInfo.ManDate[1] = '\0'; ! 2389: TapeExtension->MiscDriveInfo.Oem[0] = '\0'; ! 2390: ! 2391: // ! 2392: // Get the firmware revision number and store it in ! 2393: // TapeExtension->MiscDriveInfo.ROM_Version ! 2394: // ! 2395: ! 2396: TapeExtension->MiscDriveInfo.ROM_Version = ! 2397: TapeExtension->DriveParms.Version; ! 2398: ! 2399: if (TapeExtension->DriveParms.Flavor == CMS) { ! 2400: ! 2401: if (TapeExtension->MiscDriveInfo.ROM_Version >= ! 2402: FIRM_VERSION_60) { ! 2403: ! 2404: // ! 2405: // Save the current drive mode ! 2406: // ! 2407: ! 2408: currentMode = TapeExtension->DriveParms.Mode; ! 2409: retval = Q117iSetDriveMode(TapeExtension, DIAGNOSTIC_1_MODE); ! 2410: ! 2411: // ! 2412: // Since we are only looking at the firmware, ignore all ! 2413: // NoTape errors. ! 2414: // ! 2415: ! 2416: if (retval != NoErr && retval != NoTape) { ! 2417: ! 2418: return(retval); ! 2419: ! 2420: } ! 2421: ! 2422: // ! 2423: // In order to support the Jumbo-B platform, the drive type ! 2424: // is gotten from cmsStatus and the drive type obtained from ! 2425: // the drive train info is thrown away. ! 2426: // ! 2427: ! 2428: // ! 2429: // Get the Drive Type and store it in ! 2430: // TapeExtension->MiscDriveInfo.DriveType ! 2431: // ! 2432: ! 2433: retval = Q117iReport( ! 2434: TapeExtension, ! 2435: Rpt_CMS_Status, ! 2436: (USHORT *)&cmsStatus, ! 2437: READ_BYTE, ! 2438: NULL); ! 2439: ! 2440: // ! 2441: // Since we are only looking at the firmware, ignore all ! 2442: // NoTape errors. ! 2443: // ! 2444: ! 2445: if (retval != NoErr && retval != NoTape) { ! 2446: ! 2447: return(retval); ! 2448: ! 2449: } ! 2450: ! 2451: TapeExtension->MiscDriveInfo.DriveType = ! 2452: (CHAR)cmsStatus.DriveType; ! 2453: ! 2454: } else { ! 2455: ! 2456: TapeExtension->MiscDriveInfo.DriveType = -1; ! 2457: ! 2458: } ! 2459: ! 2460: if (TapeExtension->MiscDriveInfo.ROM_Version >= FIRM_VERSION_80) { ! 2461: ! 2462: // ! 2463: // Send the Get Drive Training Information Command to the Drive. ! 2464: // ! 2465: ! 2466: retval = Q117iSendByte(TapeExtension, Dtrain_Info); ! 2467: ! 2468: // ! 2469: // Since we are only looking at the firmware, ignore all ! 2470: // NoTape errors. ! 2471: // ! 2472: ! 2473: if (retval != NoErr && retval != NoTape) { ! 2474: ! 2475: return(retval); ! 2476: ! 2477: } ! 2478: ! 2479: Q117iSleep(TapeExtension, mt_wt2ticks, FALSE); ! 2480: ! 2481: // ! 2482: // Send the Get Descriptive Info Command to the Drive. ! 2483: // ! 2484: ! 2485: retval = Q117iSendByte(TapeExtension, Gdesp_Info); ! 2486: ! 2487: // ! 2488: // Since we are only looking at the firmware, ignore all ! 2489: // NoTape errors. ! 2490: // ! 2491: ! 2492: if (retval != NoErr && retval != NoTape) { ! 2493: ! 2494: return(retval); ! 2495: ! 2496: } ! 2497: ! 2498: Q117iSleep(TapeExtension, mt_wt2ticks, FALSE); ! 2499: ! 2500: // ! 2501: // Set the info_exists flag to true. ! 2502: // ! 2503: ! 2504: TapeExtension->MiscDriveInfo.InfoExists = TRUE; ! 2505: ! 2506: // ! 2507: // Get the Drive Type and through it in the bit_bucket -- ! 2508: // just to keep the data in sync. ! 2509: // ! 2510: ! 2511: retval = Q117iReport( ! 2512: TapeExtension, ! 2513: Read_Ram, ! 2514: (USHORT *)&bitBucket, ! 2515: READ_BYTE, ! 2516: NULL); ! 2517: ! 2518: // ! 2519: // Since we are only looking at the firmware, ignore all ! 2520: // NoTape errors. ! 2521: // ! 2522: ! 2523: if (retval != NoErr && retval != NoTape) { ! 2524: ! 2525: return(retval); ! 2526: ! 2527: } ! 2528: ! 2529: // ! 2530: // Get the Serial Number from the drive and store it in ! 2531: // TapeExtension->MiscDriveInfo.SerialNumber[] ! 2532: // ! 2533: ! 2534: for (i=0; i<SERIAL_NUM_LENGTH; ++i) { ! 2535: ! 2536: retval = Q117iReport( ! 2537: TapeExtension, ! 2538: Read_Ram, ! 2539: (USHORT *)&TapeExtension->MiscDriveInfo.SerialNumber[i], ! 2540: READ_BYTE, ! 2541: NULL); ! 2542: ! 2543: // ! 2544: // Since we are only looking at the firmware, ignore ! 2545: // all NoTape errors. ! 2546: // ! 2547: ! 2548: if (retval != NoErr && retval != NoTape) { ! 2549: ! 2550: return(retval); ! 2551: ! 2552: } ! 2553: } ! 2554: ! 2555: // ! 2556: // Get the Manufacturing date from the drive and store it in ! 2557: // TapeExtension->MiscDriveInfo.ManDate[] ! 2558: // ! 2559: ! 2560: for (i=0; i<MAN_DATE_LENGTH; ++i) { ! 2561: ! 2562: retval = Q117iReport( ! 2563: TapeExtension, ! 2564: Read_Ram, ! 2565: (USHORT *)&TapeExtension->MiscDriveInfo.ManDate[i], ! 2566: READ_BYTE, ! 2567: NULL); ! 2568: ! 2569: // ! 2570: // Since we are only looking at the firmware, ignore ! 2571: // all NoTape errors. ! 2572: // ! 2573: ! 2574: if (retval != NoErr && retval != NoTape) { ! 2575: ! 2576: return(retval); ! 2577: ! 2578: } ! 2579: ! 2580: } ! 2581: ! 2582: // ! 2583: // Get the OEM field from the drive and store it in ! 2584: // TapeExtension->MiscDriveInfo.Oem[] ! 2585: // ! 2586: ! 2587: for (i=0; i<OEM_LENGTH; ++i) { ! 2588: ! 2589: retval = Q117iReport( ! 2590: TapeExtension, ! 2591: Read_Ram, ! 2592: (USHORT *)&TapeExtension->MiscDriveInfo.Oem[i], ! 2593: READ_BYTE, ! 2594: NULL); ! 2595: ! 2596: // ! 2597: // Since we are only looking at the firmware, ignore ! 2598: // all NoTape errors. ! 2599: // ! 2600: ! 2601: if (retval != NoErr && retval != NoTape) { ! 2602: ! 2603: return(retval); ! 2604: ! 2605: } ! 2606: ! 2607: if (TapeExtension->MiscDriveInfo.Oem[i] == '\0') { ! 2608: ! 2609: break; ! 2610: ! 2611: } ! 2612: } ! 2613: } ! 2614: } ! 2615: ! 2616: if ((TapeExtension->DriveParms.Flavor == CMS) && ! 2617: (TapeExtension->MiscDriveInfo.ROM_Version >= FIRM_VERSION_60)) { ! 2618: ! 2619: // ! 2620: // Exit the Diagnostics Mode by entering the Primary Mode ! 2621: // ! 2622: ! 2623: retval = Q117iSetDriveMode(TapeExtension, PRIMARY_MODE); ! 2624: ! 2625: // ! 2626: // Since we are only looking at the firmware, ignore all NoTape errors ! 2627: // ! 2628: ! 2629: if (retval != NoErr && retval != NoTape) { ! 2630: ! 2631: return(retval); ! 2632: ! 2633: } ! 2634: ! 2635: // ! 2636: // Restore drive to original mode (current_mode) ! 2637: // ! 2638: ! 2639: if (currentMode != PRIMARY_MODE){ ! 2640: ! 2641: retval = Q117iSetDriveMode(TapeExtension, currentMode); ! 2642: ! 2643: // ! 2644: // Since we are only looking at the firmware, ignore all NoTape errors ! 2645: // ! 2646: ! 2647: if (retval != NoErr && retval != NoTape) { ! 2648: ! 2649: return(retval); ! 2650: ! 2651: } ! 2652: } ! 2653: } ! 2654: ! 2655: return(NoErr); ! 2656: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.