Annotation of ntddk/src/scsi/qic117/tapcmd.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.