|
|
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.