|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1993 - Colorado Memory Systems, Inc. ! 4: All Rights Reserved ! 5: ! 6: Module Name: ! 7: ! 8: tapecmd.c ! 9: ! 10: Abstract: ! 11: ! 12: ! 13: Revision History: ! 14: ! 15: ! 16: ! 17: ! 18: --*/ ! 19: ! 20: // ! 21: // include files ! 22: // ! 23: ! 24: #include <ntddk.h> // various NT definitions ! 25: #include <ntdddisk.h> // disk device driver I/O control codes ! 26: #include <ntiologc.h> ! 27: #include "common.h" ! 28: #include "drvtask.h" // this driver's data declarations ! 29: #include "mt1defs.h" // this driver's data declarations ! 30: #include "mt1strc.h" // this driver's data declarations ! 31: #include "q117data.h" // this driver's data declarations ! 32: ! 33: ! 34: STATUS ! 35: Q117iTapeCommands( ! 36: IN PTAPE_EXTENSION TapeExtension, ! 37: IN OUT PIO_REQUEST IoRequestCurrent, ! 38: IN OUT PIRP Irp ! 39: ) ! 40: ! 41: /*++ ! 42: ! 43: Routine Description: ! 44: ! 45: Execute an IORequest command. TapeCommands is merely a command controller, ! 46: calling the appropriate routines to execute the IORequiest commands. ! 47: ! 48: Arguments: ! 49: ! 50: TapeExtension - ! 51: ! 52: IoRequestCurrent - ! 53: ! 54: Irp - ! 55: ! 56: Return Value: ! 57: ! 58: ! 59: --*/ ! 60: ! 61: { ! 62: int retval = NoErr; ! 63: ! 64: if (TapeExtension->Found == FALSE && ! 65: IoRequestCurrent->Command != DFndDrv && ! 66: IoRequestCurrent->Command != DGetFDC ! 67: ) { ! 68: ! 69: return(NoDrive); ! 70: ! 71: } ! 72: ! 73: switch (IoRequestCurrent->Command) { ! 74: ! 75: case DFndDrv: ! 76: retval = Q117iDFndDrv(TapeExtension); ! 77: break; ! 78: ! 79: case DRead: ! 80: case DWrite: ! 81: case DVerify: ! 82: case DRetry: ! 83: case DWriteBad: ! 84: case DReadBad: ! 85: retval = Q117iReadWrite(TapeExtension, IoRequestCurrent, Irp); ! 86: break; ! 87: ! 88: case DFmt: ! 89: retval = Q117iDFmt(TapeExtension, Irp, IoRequestCurrent); ! 90: break; ! 91: ! 92: case DEject: ! 93: retval = Q117iDEject(TapeExtension); ! 94: break; ! 95: ! 96: case DFast: ! 97: case DSlow: ! 98: retval = Q117iDFast_DSlow(TapeExtension, IoRequestCurrent->Command); ! 99: break; ! 100: ! 101: case DSndWPro: ! 102: retval = Q117iDSndWPro(TapeExtension); ! 103: break; ! 104: ! 105: case DGetRev: ! 106: retval = Q117iDGetRev(TapeExtension, IoRequestCurrent->Data); ! 107: break; ! 108: ! 109: case DReten: ! 110: retval = Q117iDReten(TapeExtension); ! 111: break; ! 112: ! 113: case DGetCap: ! 114: retval = Q117iDGetCap(TapeExtension, IoRequestCurrent->Data); ! 115: break; ! 116: ! 117: case DChkDrv: ! 118: retval = Q117iDChkDrv(TapeExtension, IoRequestCurrent->Data); ! 119: break; ! 120: ! 121: case DSndReel: ! 122: retval = Q117iDSndReel(TapeExtension); ! 123: break; ! 124: ! 125: case DGetCart: ! 126: retval = Q117iDGetCart(TapeExtension, IoRequestCurrent->Data); ! 127: break; ! 128: ! 129: case DGetSpeed: ! 130: retval = Q117iDGetSpeed(TapeExtension, IoRequestCurrent->Data); ! 131: break; ! 132: ! 133: case DStatus: ! 134: retval = Q117iDStatus(TapeExtension, IoRequestCurrent->Data); ! 135: break; ! 136: ! 137: case DGetFDC: ! 138: retval = Q117iDGetFDC(TapeExtension, IoRequestCurrent->Data); ! 139: break; ! 140: ! 141: case DReportProtoVer: ! 142: retval = Q117iDReportProtoVer(TapeExtension, IoRequestCurrent->Data); ! 143: break; ! 144: ! 145: case DSelPart: ! 146: case DGetPos: ! 147: case DIgnore: ! 148: case DUseLock: ! 149: break; ! 150: ! 151: case DGetDriveInfo: ! 152: retval = Q117iDGetDriveInfo(TapeExtension, IoRequestCurrent->Data); ! 153: break; ! 154: ! 155: case DChkFmt: ! 156: retval = Q117iDChkFmt(TapeExtension); ! 157: break; ! 158: ! 159: case DDeselect: ! 160: retval = Q117iDDeselect(TapeExtension); ! 161: break; ! 162: ! 163: case DClearNewCart: ! 164: CheckedDump(QIC117SHOWTD,("Q117i: DClearNewCart received\n")); ! 165: TapeExtension->PersistentNewCart = FALSE; ! 166: retval = NoErr; ! 167: break; ! 168: ! 169: default: ! 170: retval = InvalCmd; ! 171: break; ! 172: ! 173: } ! 174: ! 175: return(retval); ! 176: } ! 177: ! 178: ! 179: STATUS ! 180: Q117iDEject( ! 181: IN PTAPE_EXTENSION TapeExtension ! 182: ) ! 183: ! 184: /*++ ! 185: ! 186: Routine Description: ! 187: ! 188: Position the tape to the physical BOT and track 0. ! 189: ! 190: Arguments: ! 191: ! 192: TapeExtension - ! 193: ! 194: Return Value: ! 195: ! 196: ! 197: --*/ ! 198: ! 199: { ! 200: STATUS retval; ! 201: ! 202: if ((retval = Q117iStopTape(TapeExtension)) != NoErr) { ! 203: ! 204: return(retval); ! 205: ! 206: } ! 207: ! 208: if((retval = Q117iSendByte(TapeExtension, Physical_Rev)) != NoErr) { ! 209: ! 210: return(retval); ! 211: ! 212: } ! 213: ! 214: if((retval = Q117iWaitCommandComplete( ! 215: TapeExtension, ! 216: TapeExtension->TapeParms.TimeOut[PHYSICAL])) != NoErr) { ! 217: ! 218: return(retval); ! 219: ! 220: } ! 221: ! 222: TapeExtension->TapePosition.C_Segment = 0; ! 223: ! 224: if (TapeExtension->DriveParms.Flavor == ! 225: CMS && !TapeExtension->DriveParms.Status.Referenced) { ! 226: ! 227: // ! 228: // Park the head if the tape is not referenced and the drive is Jumbo ! 229: // A. (Do nothing if tape not referenced and the drive is Jumbo B). ! 230: // ! 231: ! 232: if (TapeExtension->DriveParms.Version < FIRM_VERSION_60) { ! 233: ! 234: if ((retval = Q117iSetDriveMode(TapeExtension, DIAGNOSTIC_1_MODE)) != NoErr) { ! 235: ! 236: return(retval); ! 237: ! 238: } ! 239: ! 240: if ((retval = Q117iSendByte(TapeExtension, Park_Head)) != NoErr) { ! 241: ! 242: return(retval); ! 243: ! 244: } ! 245: ! 246: // ! 247: // Can't use Q117iWaitCommandComplete since the drive ready bit ! 248: // of the status byte is not updated during the Park_Head command. ! 249: // Because of this, you must sleep until the head is parked or ! 250: // the drive will not "see" the set primary mode command. ! 251: // ! 252: ! 253: Q117iSleep(TapeExtension, mt_wt007s, FALSE); ! 254: Q117iSetDriveMode(TapeExtension, PRIMARY_MODE); ! 255: retval = Q117iWaitCommandComplete(TapeExtension, mt_wt007s); ! 256: TapeExtension->TapePosition.C_Track = -1; ! 257: ! 258: } ! 259: ! 260: } else { ! 261: ! 262: if ((retval = Q117iSendByte(TapeExtension, Seek_Track)) != NoErr) { ! 263: ! 264: return(retval); ! 265: ! 266: } ! 267: ! 268: Q117iSleep(TapeExtension, mt_wt2ticks, FALSE); ! 269: ! 270: if ((retval = Q117iSendByte(TapeExtension, 2 /* Track 0 */)) != NoErr) { ! 271: ! 272: return(retval); ! 273: ! 274: } ! 275: ! 276: retval = Q117iWaitCommandComplete(TapeExtension, mt_wt007s); ! 277: TapeExtension->TapePosition.C_Track = 0; ! 278: ! 279: } ! 280: ! 281: return(retval); ! 282: } ! 283: ! 284: ! 285: STATUS ! 286: Q117iDReten( ! 287: IN PTAPE_EXTENSION TapeExtension ! 288: ) ! 289: ! 290: /*++ ! 291: ! 292: Routine Description: ! 293: ! 294: Retension the tape by first going to physical EOT then turning around and ! 295: going to physical BOT ! 296: ! 297: Arguments: ! 298: ! 299: TapeExtension - ! 300: ! 301: Return Value: ! 302: ! 303: ! 304: --*/ ! 305: ! 306: { ! 307: STATUS retval; ! 308: ! 309: if ((retval = Q117iSendByte(TapeExtension, Physical_Fwd)) != NoErr) { ! 310: ! 311: return(retval); ! 312: ! 313: } ! 314: ! 315: if ((retval = Q117iWaitCommandComplete( ! 316: TapeExtension, ! 317: TapeExtension->TapeParms.TimeOut[PHYSICAL])) ! 318: != NoErr) { ! 319: ! 320: return(retval); ! 321: ! 322: } ! 323: ! 324: if ((retval = Q117iSendByte(TapeExtension, Physical_Rev)) != NoErr) { ! 325: ! 326: return(retval); ! 327: ! 328: } ! 329: ! 330: if ((retval = Q117iWaitCommandComplete( ! 331: TapeExtension, ! 332: TapeExtension->TapeParms.TimeOut[PHYSICAL])) ! 333: != NoErr) { ! 334: ! 335: return(retval); ! 336: ! 337: } ! 338: ! 339: TapeExtension->TapePosition.C_Segment = 0; ! 340: return(NoErr); ! 341: ! 342: } ! 343: ! 344: ! 345: STATUS ! 346: Q117iDFast_DSlow( ! 347: IN PTAPE_EXTENSION TapeExtension, ! 348: IN DRIVER_COMMAND Command ! 349: ) ! 350: ! 351: /*++ ! 352: ! 353: Routine Description: ! 354: ! 355: Set the operating speed of the tape drive and the corresponding transfer ! 356: rate of the FDC. Setting the operating speed can currently be done only ! 357: on CMS drives. It is assumed that no ther drive manufacturers have ! 358: multi-speed drive. ! 359: ! 360: Arguments: ! 361: ! 362: TapeExtension - ! 363: ! 364: Command - ! 365: ! 366: Return Value: ! 367: ! 368: ! 369: --*/ ! 370: ! 371: { ! 372: STATUS retval; ! 373: struct DriveConfiguration driveConfig; ! 374: CHAR newSpeed; ! 375: ! 376: if ((retval = Q117iStopTape(TapeExtension)) != NoErr) { ! 377: ! 378: return(retval); ! 379: ! 380: } ! 381: ! 382: if (Command == DFast) { ! 383: ! 384: TapeExtension->XferRate.XferRate = FAST; ! 385: ! 386: } else { ! 387: ! 388: TapeExtension->XferRate.XferRate = SLOW; ! 389: ! 390: } ! 391: ! 392: if ((retval = Q117iSendByte(TapeExtension, Select_Speed)) != NoErr) { ! 393: ! 394: return(retval); ! 395: ! 396: } ! 397: ! 398: Q117iSleep(TapeExtension, mt_wt2ticks, FALSE); ! 399: ! 400: if (Command == DFast) { ! 401: ! 402: newSpeed = TapeExtension->XferRate.TapeFast + 2; ! 403: ! 404: } else { ! 405: ! 406: newSpeed = TapeExtension->XferRate.TapeSlow + 2; ! 407: ! 408: } ! 409: ! 410: if ((retval = Q117iSendByte(TapeExtension, newSpeed)) != NoErr) { ! 411: ! 412: return(retval); ! 413: ! 414: } ! 415: ! 416: Q117iConfigureFDC(TapeExtension); ! 417: ! 418: if ((retval = Q117iWaitCommandComplete(TapeExtension, mt_wt010s)) != NoErr) { ! 419: ! 420: return(retval); ! 421: ! 422: } ! 423: ! 424: if ((retval = Q117iReport(TapeExtension, ! 425: Report_Confg, ! 426: (USHORT *)&driveConfig, ! 427: READ_BYTE, ! 428: NULL)) ! 429: != NoErr) { ! 430: ! 431: return(retval); ! 432: ! 433: } ! 434: ! 435: if (Command == DFast ? ! 436: driveConfig.XferRate != TapeExtension->XferRate.TapeFast : ! 437: driveConfig.XferRate != TapeExtension->XferRate.TapeSlow) { ! 438: ! 439: retval = TapeFlt; ! 440: TapeExtension->FirmwareError = Speed_not_Avail; ! 441: ! 442: } ! 443: ! 444: return(retval); ! 445: } ! 446: ! 447: ! 448: STATUS ! 449: Q117iDGetRev( ! 450: IN PTAPE_EXTENSION TapeExtension, ! 451: OUT PUCHAR Version ! 452: ) ! 453: ! 454: /*++ ! 455: ! 456: Routine Description: ! 457: ! 458: Get the current version of firmware in the tape drive. ! 459: ! 460: Arguments: ! 461: ! 462: TapeExtension - ! 463: ! 464: Version - ! 465: ! 466: Return Value: ! 467: ! 468: ! 469: --*/ ! 470: ! 471: { ! 472: STATUS retval; ! 473: UCHAR ROM_Version; ! 474: ! 475: if ((retval = Q117iReport(TapeExtension, ! 476: Report_ROM, ! 477: (USHORT *)&ROM_Version, ! 478: READ_BYTE, ! 479: NULL)) ! 480: != NoErr) { ! 481: ! 482: return(retval); ! 483: ! 484: } ! 485: ! 486: *Version = ROM_Version; ! 487: return(NoErr); ! 488: } ! 489: ! 490: ! 491: STATUS ! 492: Q117iDGetCap( ! 493: IN PTAPE_EXTENSION TapeExtension, ! 494: struct S_O_DGetCap *Capacity ! 495: ) ! 496: ! 497: /*++ ! 498: ! 499: Routine Description: ! 500: ! 501: Get the current tape type, which includes the tape format (if any) and ! 502: the tape length ( in the case of a QIC-40 format tape). If the tape is ! 503: not referenced then that information must be included. ! 504: ! 505: Arguments: ! 506: ! 507: TapeExtension - ! 508: ! 509: Capacity - ! 510: ! 511: Return Value: ! 512: ! 513: ! 514: --*/ ! 515: ! 516: { ! 517: STATUS retval; ! 518: ! 519: retval = Q117iGetTapeParameters(TapeExtension); ! 520: ! 521: if (!retval) { ! 522: ! 523: // ! 524: // floppy sectors per segment ! 525: // ! 526: Capacity->SectsPerSegment = TapeExtension->TapeParms.FsectSeg; ! 527: ! 528: // ! 529: // segments per tape track ! 530: // ! 531: Capacity->SegmentsPerTrack = TapeExtension->TapeParms.SegTtrack; ! 532: ! 533: // ! 534: // number of tape tracks ! 535: // ! 536: Capacity->TracksPerTape = TapeExtension->TapeParms.NumTtrack; ! 537: ! 538: // ! 539: // segments per floppy track ! 540: // ! 541: Capacity->SegmentsPerFTrack = TapeExtension->TapeParms.SegFtrack; ! 542: ! 543: // ! 544: // floppy tracks per floppy side ! 545: // ! 546: Capacity->FTrackPerFSide = TapeExtension->TapeParms.FtrackFside; ! 547: ! 548: // ! 549: // floppy sectors per floppy track ! 550: // ! 551: Capacity->MaxFSector = TapeExtension->TapeParms.FsectFtrack; ! 552: ! 553: Capacity->drive_type = TapeExtension->DriveParms.DriveType; ! 554: ! 555: if (TapeExtension->DriveParms.Status.Referenced) { ! 556: ! 557: Capacity->referenced = TRUE; ! 558: ! 559: } else { ! 560: ! 561: Capacity->referenced = FALSE; ! 562: ! 563: } ! 564: ! 565: Capacity->TapeFormatCode = TapeExtension->TapeParms.TapeFormatCode; ! 566: ! 567: Capacity->FormattableSegments = ! 568: TapeExtension->TapeParms.FormattableSegs; ! 569: ! 570: } ! 571: ! 572: return(retval); ! 573: } ! 574: ! 575: ! 576: ! 577: STATUS ! 578: Q117iDComFirm( ! 579: IN PTAPE_EXTENSION TapeExtension, ! 580: IN OUT PUCHAR CommandString ! 581: ) ! 582: ! 583: /*++ ! 584: ! 585: Routine Description: ! 586: ! 587: Send and receive non-standard data to/from the tape drive. ! 588: ! 589: Arguments: ! 590: ! 591: TapeExtension - ! 592: ! 593: CommandString - ! 594: ! 595: Return Value: ! 596: ! 597: ! 598: --*/ ! 599: ! 600: { ! 601: STATUS retval = NoErr; ! 602: UCHAR tCount; ! 603: CHAR sendData; ! 604: USHORT receiveData; ! 605: SHORT waitTime; ! 606: SHORT receiveLength; ! 607: ! 608: tCount = *CommandString++; ! 609: ! 610: while (tCount) { ! 611: ! 612: Q117iSleep(TapeExtension, mt_wt2ticks, FALSE); ! 613: ! 614: sendData = *CommandString++; ! 615: ! 616: if ((retval = Q117iSendByte(TapeExtension, sendData)) != NoErr) { ! 617: ! 618: return(retval); ! 619: } ! 620: ! 621: --tCount; ! 622: ! 623: } ! 624: ! 625: tCount = *CommandString++; ! 626: ! 627: switch (tCount) { ! 628: ! 629: case 0xff: ! 630: retval = Q117iWaitCommandComplete(TapeExtension, mt_wt300s); ! 631: break; ! 632: ! 633: case 0xfe: ! 634: waitTime = *(SHORT *)CommandString; ! 635: ! 636: if (waitTime) { ! 637: ! 638: Q117iSleep(TapeExtension, waitTime, FALSE); ! 639: ! 640: } ! 641: ! 642: break; ! 643: ! 644: default: ! 645: if (tCount == 0xfd) { ! 646: ! 647: TapeExtension->NoPause = TRUE; ! 648: tCount = *CommandString++; ! 649: ! 650: } ! 651: ! 652: Q117iSleep(TapeExtension, mt_wt2ticks, FALSE); ! 653: ! 654: if (tCount != 0) { ! 655: ! 656: if (tCount == 1) { ! 657: ! 658: receiveLength = READ_BYTE; ! 659: ! 660: } else { ! 661: ! 662: receiveLength = READ_WORD; ! 663: ! 664: } ! 665: ! 666: if ((retval = Q117iReceiveByte(TapeExtension, ! 667: receiveLength, ! 668: &receiveData)) ! 669: != NoErr) { ! 670: ! 671: return(retval); ! 672: ! 673: } ! 674: ! 675: if (tCount == 1) { ! 676: ! 677: *CommandString = (CHAR)receiveData; ! 678: ! 679: } else { ! 680: ! 681: *(USHORT *)CommandString = receiveData; ! 682: ! 683: } ! 684: ! 685: } ! 686: ! 687: break; ! 688: ! 689: } ! 690: return(retval); ! 691: } ! 692: ! 693: STATUS ! 694: Q117iDSndWPro( ! 695: IN PTAPE_EXTENSION TapeExtension ! 696: ) ! 697: ! 698: /*++ ! 699: ! 700: Routine Description: ! 701: ! 702: Report the write protect status of the tape. ! 703: ! 704: Arguments: ! 705: ! 706: TapeExtension - ! 707: ! 708: Return Value: ! 709: ! 710: ! 711: --*/ ! 712: ! 713: { ! 714: STATUS retval; ! 715: ! 716: if((retval = Q117iGetDriveError(TapeExtension)) == NoErr) { ! 717: ! 718: if (TapeExtension->DriveParms.Status.WriteProtect) { ! 719: ! 720: retval = WProt; ! 721: ! 722: } ! 723: ! 724: } ! 725: ! 726: return(retval); ! 727: } ! 728: ! 729: STATUS ! 730: Q117iDSndReel( ! 731: IN PTAPE_EXTENSION TapeExtension ! 732: ) ! 733: ! 734: /*++ ! 735: ! 736: Routine Description: ! 737: ! 738: Return cartridge in status. ! 739: ! 740: Arguments: ! 741: ! 742: TapeExtension - ! 743: ! 744: Return Value: ! 745: ! 746: ! 747: --*/ ! 748: ! 749: { ! 750: STATUS retval; ! 751: ! 752: retval = Q117iGetDriveError(TapeExtension); ! 753: ! 754: if (retval == NoErr || retval == NewCart) { ! 755: ! 756: if (TapeExtension->NewCart) { ! 757: ! 758: Q117iNewTape(TapeExtension); ! 759: ! 760: } ! 761: ! 762: retval = NoErr; ! 763: ! 764: } else { ! 765: ! 766: if (retval == NotRdy) { ! 767: ! 768: retval = NoTape; ! 769: ! 770: } ! 771: ! 772: } ! 773: ! 774: return(retval); ! 775: } ! 776: ! 777: STATUS ! 778: Q117iDGetCart( ! 779: IN PTAPE_EXTENSION TapeExtension, ! 780: OUT PUCHAR TapeType ! 781: ) ! 782: ! 783: /*++ ! 784: ! 785: Routine Description: ! 786: ! 787: Return new cartidge status as necessary. ! 788: ! 789: Arguments: ! 790: ! 791: TapeExtension - ! 792: ! 793: TapeType - ! 794: ! 795: Return Value: ! 796: ! 797: ! 798: --*/ ! 799: ! 800: { ! 801: STATUS retval; ! 802: ! 803: retval = Q117iWaitCommandComplete(TapeExtension, mt_wt150s); ! 804: ! 805: if (retval == NoErr || retval == NewCart) { ! 806: ! 807: if (TapeExtension->NewCart) { ! 808: ! 809: // ! 810: // If there is an illegitimate write protect status due to the ! 811: // firmware 63 bug, the call to Q117iNewTape will clear the ! 812: // write-protect bit from the status byte. ! 813: // ! 814: ! 815: retval = Q117iNewTape(TapeExtension); ! 816: ! 817: if (retval == NoErr) { ! 818: ! 819: retval = NewCart; ! 820: } ! 821: ! 822: } ! 823: ! 824: } else { ! 825: ! 826: // ! 827: // This is to test to see if the tape drive erroneously thought the ! 828: // tape was invalide media and correct the error if so ! 829: // ! 830: ! 831: if (retval == TapeFlt && TapeExtension->FirmwareError == Inval_Media) { ! 832: ! 833: retval = Q117iNewTape(TapeExtension); ! 834: ! 835: if (retval == NoErr) { ! 836: ! 837: retval = NewCart; ! 838: } ! 839: ! 840: } ! 841: ! 842: } ! 843: ! 844: *TapeType = TapeExtension->TapeParms.TapeType; ! 845: return(retval); ! 846: } ! 847: ! 848: ! 849: STATUS ! 850: Q117iDChkDrv( ! 851: IN PTAPE_EXTENSION TapeExtension, ! 852: OUT PUCHAR DriveType ! 853: ) ! 854: ! 855: /*++ ! 856: ! 857: Routine Description: ! 858: ! 859: Return the drive manufacturer (CMS or ALIEN). ! 860: ! 861: Arguments: ! 862: ! 863: TapeExtension - ! 864: ! 865: DriveType - ! 866: ! 867: Return Value: ! 868: ! 869: ! 870: --*/ ! 871: ! 872: { ! 873: *DriveType = TapeExtension->DriveParms.Flavor; ! 874: return(NoErr); ! 875: } ! 876: ! 877: STATUS ! 878: Q117iDGetSpeed( ! 879: IN PTAPE_EXTENSION TapeExtension, ! 880: OUT struct S_O_DGetSpeed *TransferRate ! 881: ) ! 882: ! 883: /*++ ! 884: ! 885: Routine Description: ! 886: ! 887: Return the current FDC transfer rate. ! 888: ! 889: Arguments: ! 890: ! 891: TapeExtension - ! 892: ! 893: TransferRate- ! 894: ! 895: Return Value: ! 896: ! 897: ! 898: --*/ ! 899: ! 900: { ! 901: switch (TapeExtension->XferRate.XferRate ? ! 902: TapeExtension->XferRate.TapeFast : ! 903: TapeExtension->XferRate.TapeSlow) { ! 904: ! 905: case TAPE_250Kbps: ! 906: TransferRate->CurSpeed = 250/8; ! 907: break; ! 908: ! 909: case TAPE_500Kbps: ! 910: TransferRate->CurSpeed = 500/8; ! 911: break; ! 912: ! 913: case TAPE_1Mbps: ! 914: TransferRate->CurSpeed = 1000/8; ! 915: break; ! 916: ! 917: case TAPE_2Mbps: ! 918: TransferRate->CurSpeed = 2000/8; ! 919: break; ! 920: ! 921: } ! 922: ! 923: switch (TapeExtension->XferRate.MaxRate ? ! 924: TapeExtension->XferRate.FDC_Fast : ! 925: TapeExtension->XferRate.FDC_Slow) { ! 926: ! 927: case FDC_250Kbps: ! 928: TransferRate->FmtSpeed = 250/8; ! 929: break; ! 930: ! 931: case FDC_500Kbps: ! 932: TransferRate->FmtSpeed = 500/8; ! 933: break; ! 934: ! 935: case FDC_1Mbps: ! 936: TransferRate->FmtSpeed = 1000/8; ! 937: break; ! 938: ! 939: case FDC_2Mbps: ! 940: TransferRate->FmtSpeed = 2000/8; ! 941: break; ! 942: ! 943: } ! 944: ! 945: return(NoErr); ! 946: } ! 947: ! 948: STATUS ! 949: Q117iDStatus( ! 950: IN PTAPE_EXTENSION TapeExtension, ! 951: OUT struct S_O_DStatus *DriveStatus ! 952: ) ! 953: ! 954: /*++ ! 955: ! 956: Routine Description: ! 957: ! 958: ! 959: ! 960: Arguments: ! 961: ! 962: TapeExtension - ! 963: ! 964: DriveStatus - ! 965: ! 966: Return Value: ! 967: ! 968: ! 969: --*/ ! 970: ! 971: { ! 972: DriveStatus->underruns = 0; ! 973: // DriveStatus->retries = cmd_SoftErrors; ! 974: ! 975: return(NoErr); ! 976: } ! 977: ! 978: ! 979: ! 980: STATUS ! 981: Q117iDGetFDC( ! 982: IN PTAPE_EXTENSION TapeExtension, ! 983: OUT PUCHAR FdcType ! 984: ) ! 985: ! 986: /*++ ! 987: ! 988: Routine Description: ! 989: ! 990: Determine whether or not the floppy controller is an 82077. ! 991: ! 992: Arguments: ! 993: ! 994: TapeExtension - ! 995: ! 996: FdcType - ! 997: ! 998: Return Value: ! 999: ! 1000: ! 1001: --*/ ! 1002: ! 1003: { ! 1004: STATUS retval = NoErr; ! 1005: SHORT i, test; ! 1006: UCHAR status = 0; ! 1007: SHORT statLength = 0; ! 1008: struct version_cmd verCmd; ! 1009: struct national_cmd nscCmd; ! 1010: struct PerpMode perpMode; ! 1011: struct part_id_cmd partId; ! 1012: ! 1013: // Set up the Perp Mode Command ! 1014: ! 1015: perpMode.command = PERP_MODE_COMMAND; ! 1016: perpMode.drive_select = 0; ! 1017: perpMode.wgate = 0; ! 1018: perpMode.gap = 0; ! 1019: perpMode.reserved = 0; ! 1020: perpMode.over_write = TRUE; ! 1021: ! 1022: verCmd.command = FDC_VERSION; ! 1023: nscCmd.command = NSC_VERSION; ! 1024: partId.command = FDC_PART_ID; ! 1025: *FdcType = FDC_UNKNOWN; ! 1026: ! 1027: ! 1028: // ! 1029: // Check for an enhanced type controller by issuing the version command. ! 1030: // ! 1031: ! 1032: if ((retval = Q117iProgramFDC(TapeExtension, ! 1033: (CHAR *)&verCmd, ! 1034: sizeof(verCmd), ! 1035: FALSE)) ! 1036: == NoErr) { ! 1037: ! 1038: if((retval = Q117iReadFDC(TapeExtension, ! 1039: (CHAR *)&status, ! 1040: (SHORT *)&statLength)) ! 1041: == NoErr) { ! 1042: ! 1043: if (statLength != 1) { ! 1044: ! 1045: retval = NECFlt; ! 1046: ! 1047: } else { ! 1048: ! 1049: if (status == VALID_NEC_FDC) { ! 1050: ! 1051: *FdcType = FDC_ENHANCED; ! 1052: ! 1053: } else { ! 1054: ! 1055: *FdcType = FDC_NORMAL; ! 1056: ! 1057: } ! 1058: } ! 1059: ! 1060: } ! 1061: } ! 1062: ! 1063: // ! 1064: // Determine if the controller is a National 8477 by issuing the NSC ! 1065: // command which is specific to National parts and returns 0x71. The ! 1066: // lower four bits are subject to change by National and will reflect ! 1067: // the version of the part in question. At this point we will only test ! 1068: // the high four bits. ! 1069: // ! 1070: ! 1071: if (*FdcType == FDC_ENHANCED && retval == NoErr) { ! 1072: ! 1073: if ((retval = Q117iProgramFDC(TapeExtension, ! 1074: (CHAR *)&nscCmd, ! 1075: sizeof(nscCmd), ! 1076: FALSE)) ! 1077: == NoErr) { ! 1078: ! 1079: if ((retval = Q117iReadFDC(TapeExtension, ! 1080: (CHAR *)&status, ! 1081: (SHORT *)&statLength)) ! 1082: == NoErr) { ! 1083: ! 1084: if (statLength != 1) { ! 1085: ! 1086: retval = NECFlt; ! 1087: ! 1088: } else { ! 1089: ! 1090: if ((status & NSC_MASK) == NSC_PRIMARY_VERSION) { ! 1091: ! 1092: *FdcType = FDC_NATIONAL; ! 1093: ! 1094: } ! 1095: ! 1096: } ! 1097: ! 1098: } ! 1099: } ! 1100: } ! 1101: ! 1102: // ! 1103: // Determine if the controller is an 82077 by issuing the perpendicular ! 1104: // mode command which at this time is only valid on 82077's. ! 1105: // ! 1106: ! 1107: if (*FdcType == FDC_ENHANCED && retval == NoErr) { ! 1108: ! 1109: if ((retval = Q117iProgramFDC(TapeExtension, ! 1110: (CHAR *)&perpMode, ! 1111: sizeof(perpMode), ! 1112: FALSE)) ! 1113: == NECFlt) { ! 1114: ! 1115: if ((retval = Q117iReadFDC(TapeExtension, ! 1116: (CHAR *)&status, ! 1117: (SHORT *)&statLength)) ! 1118: == NoErr) { ! 1119: ! 1120: if (statLength != 1) { ! 1121: ! 1122: retval = NECFlt; ! 1123: ! 1124: } ! 1125: ! 1126: } ! 1127: ! 1128: } else { ! 1129: ! 1130: *FdcType = FDC_82077; ! 1131: ! 1132: } ! 1133: } ! 1134: ! 1135: // ! 1136: // Determine if the controller is an 82077AA by setting the tdr to several ! 1137: // valid values and reading the results to determine if in fact the tdr ! 1138: // is active. Only the AA parts have an active tdr. ! 1139: // ! 1140: ! 1141: if (*FdcType == FDC_82077 && retval == NoErr) { ! 1142: ! 1143: for (i = 0, test = 0; i < FDC_REPEAT; i++) { ! 1144: ! 1145: WRITE_CONTROLLER(&TapeExtension->QControllerData->FDC_Addr->tdr, i); ! 1146: ! 1147: if (i == (FDC_TDR_MASK & READ_CONTROLLER( ! 1148: &TapeExtension->QControllerData->FDC_Addr->tdr))) { ! 1149: ! 1150: test++; ! 1151: ! 1152: } ! 1153: ! 1154: } ! 1155: ! 1156: if (test == FDC_REPEAT) { ! 1157: ! 1158: *FdcType = FDC_82077AA; ! 1159: CheckedDump(QIC117INFO,( "Q117i: FdcType = FDC_82077AA\n")); ! 1160: ! 1161: } ! 1162: ! 1163: } ! 1164: ! 1165: #if DBG ! 1166: ! 1167: switch (*FdcType) { ! 1168: case FDC_NORMAL: ! 1169: CheckedDump(QIC117INFO,( "Q117i: FdcType = FDC_NORMAL\n")); ! 1170: break; ! 1171: case FDC_ENHANCED: ! 1172: CheckedDump(QIC117INFO,( "Q117i: FdcType = FDC_ENHANCED\n")); ! 1173: break; ! 1174: case FDC_NATIONAL: ! 1175: CheckedDump(QIC117INFO,( "Q117i: FdcType = FDC_NATIONAL\n")); ! 1176: break; ! 1177: case FDC_82077: ! 1178: CheckedDump(QIC117INFO,( "Q117i: FdcType = FDC_82077\n")); ! 1179: break; ! 1180: case FDC_82077AA: ! 1181: CheckedDump(QIC117INFO,( "Q117i: FdcType = FDC_82077AA\n")); ! 1182: break; ! 1183: default: ! 1184: CheckedDump(QIC117INFO,( "Q117i: FdcType = FDC_UNKNOWN\n")); ! 1185: } ! 1186: ! 1187: #endif ! 1188: ! 1189: return(retval); ! 1190: } ! 1191: ! 1192: ! 1193: STATUS ! 1194: Q117iDGetDriveInfo( ! 1195: IN PTAPE_EXTENSION TapeExtension, ! 1196: OUT struct S_O_DMiscInfo *MiscellaneousInformation ! 1197: ) ! 1198: ! 1199: /*++ ! 1200: ! 1201: Routine Description: ! 1202: ! 1203: Gets the followin information: ! 1204: 1) Drive Type/Model ! 1205: 2) Firmware Revision ! 1206: 3) Info Exists Flag ! 1207: 4) OEM Field ! 1208: 5) Serial Number ! 1209: 6) Date of manufacture ! 1210: ! 1211: Arguments: ! 1212: ! 1213: TapeExtension - ! 1214: ! 1215: MiscellaneousInformation - ! 1216: ! 1217: Return Value: ! 1218: ! 1219: ! 1220: ! 1221: --*/ ! 1222: ! 1223: { ! 1224: CHAR i; ! 1225: ! 1226: MiscellaneousInformation->drive_type = ! 1227: TapeExtension->MiscDriveInfo.DriveType; ! 1228: MiscellaneousInformation->ROM_Version = ! 1229: TapeExtension->MiscDriveInfo.ROM_Version; ! 1230: MiscellaneousInformation->info_exists = ! 1231: TapeExtension->MiscDriveInfo.InfoExists; ! 1232: ! 1233: for (i=0; i<SERIAL_NUM_LENGTH; ++i) { ! 1234: ! 1235: MiscellaneousInformation->serial_number[i] = ! 1236: TapeExtension->MiscDriveInfo.SerialNumber[i]; ! 1237: ! 1238: } ! 1239: ! 1240: for (i=0; i<MAN_DATE_LENGTH; ++i) { ! 1241: ! 1242: MiscellaneousInformation->man_date[i] = ! 1243: TapeExtension->MiscDriveInfo.ManDate[i]; ! 1244: ! 1245: } ! 1246: ! 1247: for (i=0; i<OEM_LENGTH; ++i) { ! 1248: ! 1249: MiscellaneousInformation->oem[i] = ! 1250: TapeExtension->MiscDriveInfo.Oem[i]; ! 1251: ! 1252: } ! 1253: ! 1254: return(NoErr); ! 1255: } ! 1256: ! 1257: ! 1258: STATUS ! 1259: Q117iDChkFmt( ! 1260: IN PTAPE_EXTENSION TapeExtension ! 1261: ) ! 1262: ! 1263: /*++ ! 1264: ! 1265: Routine Description: ! 1266: ! 1267: Checks the tape format and compares it to the drive type. ! 1268: ! 1269: If the drive type is CMS and the firmware version is 80 or greater, the ! 1270: following status condition are returned: ! 1271: ! 1272: WrongFmt - Indicates that a QIC-40 tape was detected in a QIC-80 ! 1273: drive. ! 1274: ! 1275: IncompTapeFmt - Indicates that a QIC-80 tape was detected in a QIC-40 ! 1276: drive. ! 1277: ! 1278: If the drive type is not CMS or the firmware version is earlier then the ! 1279: following error condition are returned: ! 1280: ! 1281: WrongFmt - Indicates that a QIC-40 tape was detected in a QIC-80 ! 1282: drive. ! 1283: ! 1284: IncompTapeFmt - Indicates that the drive is not reference and it is ! 1285: suspected that a QIC-80 tape is in a QIC-40 drive. ! 1286: ! 1287: Arguments: ! 1288: ! 1289: TapeExtension - ! 1290: ! 1291: Return Value: ! 1292: ! 1293: ! 1294: --*/ ! 1295: ! 1296: { ! 1297: STATUS retval = NoErr; ! 1298: SHORT fmtStat = NoErr; ! 1299: CHAR currentMode; ! 1300: struct CmsStatus cmsStatus; ! 1301: ! 1302: ! 1303: if (TapeExtension->DriveParms.Flavor == CMS && ! 1304: TapeExtension->DriveParms.Version >= FIRM_VERSION_80) { ! 1305: ! 1306: // ! 1307: // Save current drive mode and put drive into diagnostics mode ! 1308: // ! 1309: ! 1310: currentMode = TapeExtension->DriveParms.Mode; ! 1311: retval = Q117iSetDriveMode(TapeExtension, DIAGNOSTIC_1_MODE); ! 1312: ! 1313: if (retval != NoErr) { ! 1314: ! 1315: return(retval); ! 1316: ! 1317: } ! 1318: ! 1319: // ! 1320: // Get the drive type via the Rpt_cmsStatus command ! 1321: // ! 1322: ! 1323: retval = Q117iReport(TapeExtension, ! 1324: Rpt_CMS_Status, ! 1325: (USHORT *)&cmsStatus, ! 1326: READ_BYTE, ! 1327: NULL); ! 1328: ! 1329: if (retval != NoErr) { ! 1330: ! 1331: return(retval); ! 1332: ! 1333: } ! 1334: ! 1335: if (!cmsStatus.DriveType) { ! 1336: ! 1337: // ! 1338: // If drive type is QIC80, the drive_type bit is set low ! 1339: // and the eagle bit is low. ! 1340: // ! 1341: ! 1342: if (!cmsStatus.Eagle) { ! 1343: ! 1344: if ((TapeExtension->TapeParms.TapeType == QIC40_SHORT) || ! 1345: (TapeExtension->TapeParms.TapeType == QIC40_LONG) || ! 1346: (TapeExtension->TapeParms.TapeType == QICEST_40)) { ! 1347: ! 1348: fmtStat = WrongFmt; ! 1349: ! 1350: } ! 1351: ! 1352: } else { ! 1353: ! 1354: // Drive Type is Eagle ! 1355: ! 1356: if ((TapeExtension->TapeParms.TapeType == QIC40_SHORT) || ! 1357: (TapeExtension->TapeParms.TapeType == QIC40_LONG) || ! 1358: (TapeExtension->TapeParms.TapeType == QICEST_40)) { ! 1359: ! 1360: fmtStat = QIC40InEagle; ! 1361: ! 1362: } ! 1363: if ((TapeExtension->TapeParms.TapeType == QIC80_SHORT) || ! 1364: (TapeExtension->TapeParms.TapeType == QIC80_LONG) || ! 1365: (TapeExtension->TapeParms.TapeType == QICEST_80)) { ! 1366: ! 1367: fmtStat = QIC80InEagle; ! 1368: ! 1369: } ! 1370: } ! 1371: ! 1372: } else { ! 1373: ! 1374: // ! 1375: // It must be a QIC40 Drive ! 1376: // ! 1377: ! 1378: if ((TapeExtension->TapeParms.TapeType == QIC80_SHORT) || ! 1379: (TapeExtension->TapeParms.TapeType == QIC80_LONG) || ! 1380: (TapeExtension->TapeParms.TapeType == QICEST_80)) { ! 1381: ! 1382: fmtStat = IncompTapeFmt; ! 1383: ! 1384: } ! 1385: ! 1386: } ! 1387: ! 1388: // ! 1389: // To exit DIAGNOSTIC_1_MODE, put drive into PRIMARY_MODE ! 1390: // ! 1391: ! 1392: retval = Q117iSetDriveMode(TapeExtension, PRIMARY_MODE); ! 1393: ! 1394: if (retval != NoErr) { ! 1395: ! 1396: return(retval); ! 1397: ! 1398: } ! 1399: ! 1400: // ! 1401: // Restore drive to its original mode ! 1402: // ! 1403: ! 1404: if (currentMode != PRIMARY_MODE) { ! 1405: ! 1406: retval = Q117iSetDriveMode(TapeExtension, currentMode); ! 1407: ! 1408: if (retval != NoErr) { ! 1409: ! 1410: return(retval); ! 1411: ! 1412: } ! 1413: ! 1414: } ! 1415: ! 1416: } else { ! 1417: ! 1418: // ! 1419: // It is not a CMS Drive or it is not firmware version 80 or better ! 1420: // ! 1421: ! 1422: if ((TapeExtension->DriveParms.DriveType == QIC80_DRIVE) && ! 1423: ((TapeExtension->TapeParms.TapeType == QIC40_SHORT) || ! 1424: (TapeExtension->TapeParms.TapeType == QIC40_LONG) || ! 1425: (TapeExtension->TapeParms.TapeType == QICEST_40))) { ! 1426: ! 1427: fmtStat = WrongFmt; ! 1428: ! 1429: } ! 1430: ! 1431: } ! 1432: ! 1433: return(fmtStat); ! 1434: } ! 1435: ! 1436: ! 1437: STATUS ! 1438: Q117iDReportProtoVer( ! 1439: IN PTAPE_EXTENSION TapeExtension, ! 1440: OUT PUCHAR PrototypeVersion ! 1441: ) ! 1442: ! 1443: /*++ ! 1444: ! 1445: Routine Description: ! 1446: ! 1447: Gets the Prototype firmware version from the drive. ! 1448: ! 1449: Arguments: ! 1450: ! 1451: TapeExtension - ! 1452: ! 1453: PrototypeVersion - ! 1454: ! 1455: Return Value: ! 1456: ! 1457: ! 1458: --*/ ! 1459: ! 1460: { ! 1461: UBYTE protoVersion = 0; ! 1462: CHAR currentMode; ! 1463: STATUS retval = NoErr; ! 1464: ! 1465: if (TapeExtension->DriveParms.Flavor == CMS && ! 1466: TapeExtension->DriveParms.Version >= FIRM_VERSION_80) { ! 1467: ! 1468: // ! 1469: // Save current drive mode and put drive into diagnostics mode ! 1470: // ! 1471: ! 1472: currentMode = TapeExtension->DriveParms.Mode; ! 1473: retval = Q117iSetDriveMode(TapeExtension, DIAGNOSTIC_1_MODE); ! 1474: ! 1475: // ! 1476: // Since we are only looking at the firmware, ignore all NoTape ! 1477: // errors. ! 1478: // ! 1479: ! 1480: if (retval != NoErr && retval != NoTape) { ! 1481: ! 1482: return(retval); ! 1483: ! 1484: } ! 1485: ! 1486: // ! 1487: // Get the firmware prototype version number ! 1488: // ! 1489: ! 1490: retval = Q117iReport(TapeExtension, ! 1491: ReportProtoVer, ! 1492: (USHORT *)&protoVersion, ! 1493: READ_BYTE, ! 1494: NULL); ! 1495: ! 1496: // ! 1497: // Since we are only looking at the firmware, ignore all NoTape errors ! 1498: // ! 1499: ! 1500: if (retval != NoErr && retval != NoTape) { ! 1501: ! 1502: return(retval); ! 1503: ! 1504: } ! 1505: ! 1506: // ! 1507: // To exit DIAGNOSTIC_1_MODE, put drive into PRIMARY_MODE ! 1508: // ! 1509: ! 1510: retval = Q117iSetDriveMode(TapeExtension, PRIMARY_MODE); ! 1511: ! 1512: // ! 1513: // Since we are only looking at the firmware, ignore all NoTape errors ! 1514: // ! 1515: ! 1516: if (retval != NoErr && retval != NoTape) { ! 1517: ! 1518: return(retval); ! 1519: ! 1520: } ! 1521: ! 1522: // ! 1523: // Restore drive to its original mode ! 1524: // Since we are only looking at the firmware, ignore all NoTape errors ! 1525: // ! 1526: ! 1527: if (currentMode != PRIMARY_MODE) { ! 1528: ! 1529: retval = Q117iSetDriveMode(TapeExtension, currentMode); ! 1530: ! 1531: if (retval != NoErr && retval != NoTape) { ! 1532: ! 1533: return(retval); ! 1534: ! 1535: } ! 1536: ! 1537: } ! 1538: ! 1539: } ! 1540: ! 1541: *PrototypeVersion = protoVersion; ! 1542: return(NoErr); ! 1543: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.