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