|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1993 - Colorado Memory Systems, Inc.
4: All Rights Reserved
5:
6: Module Name:
7:
8: seek.c
9:
10: Abstract:
11:
12: positions tape to correct location to be before the desired track and block
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: Q117iSeek(
37: IN PTAPE_EXTENSION TapeExtension
38: )
39:
40: /*++
41:
42: Routine Description:
43:
44: Reposition tape for desired track and block.
45:
46: Change track first if necessary.
47:
48: Seek at high speed to approximately get to the specified area on
49: the tape.
50:
51: Read ID marks from the tape until the tape is positioned 1 block in
52: front of (logically) the desired block.
53:
54: Arguments:
55:
56: TapeExtension -
57:
58: Return Value:
59:
60:
61:
62: --*/
63:
64: {
65: STATUS retval = NoErr;
66: BOOLEAN newTrack;
67: SHORT seekCount;
68: BOOLEAN retensionFlag = FALSE;
69:
70: newTrack = FALSE;
71: seekCount = MAX_SEEK_COUNT;
72:
73: do {
74:
75: if (TapeExtension->TapePosition.D_Segment == 0)
76:
77: if ((retval = Q117iLogicalBOT(TapeExtension)) != NoErr) {
78:
79: return(retval);
80:
81: }
82:
83: if (TapeExtension->TapePosition.D_Track !=
84: TapeExtension->TapePosition.C_Track) {
85:
86: if ((retval = Q117iChangeTrack(
87: TapeExtension,
88: TapeExtension->TapePosition.D_Track)) != NoErr) {
89:
90: return(retval);
91:
92: }
93:
94: if (!TapeExtension->DriveParms.Status.BOT &&
95: !TapeExtension->DriveParms.Status.EOT) {
96:
97: newTrack = TRUE;
98:
99: }
100:
101: }
102:
103: if (TapeExtension->TapePosition.D_Segment == 0)
104: return(NoErr);
105:
106: if (newTrack == TRUE) {
107:
108: retval = Q117iReadIDRepeat(TapeExtension);
109:
110: }
111:
112: if (retval == NoErr) {
113:
114: retval = Q117iHighSpeedSeek(TapeExtension);
115:
116: }
117:
118: if (retval == NoErr) {
119:
120: retval = Q117iReadIDRepeat(TapeExtension);
121:
122: }
123:
124: --seekCount;
125:
126: if ((retval == SeekErr || seekCount == 0) && retensionFlag == FALSE) {
127:
128: if ((retval = Q117iStopTape(TapeExtension)) != NoErr) {
129:
130: return(retval);
131:
132: }
133:
134: if ((retval = Q117iDReten(TapeExtension)) != NoErr) {
135:
136: return(retval);
137:
138: }
139:
140: seekCount = MAX_SEEK_COUNT;
141: retensionFlag = TRUE;
142: retval = NoErr;
143:
144: }
145:
146: if (retval != NoErr) {
147:
148: return(retval);
149:
150: }
151:
152: } while (!((0 <= ((TapeExtension->TapePosition.D_Segment - 1) -
153: TapeExtension->TapePosition.C_Segment)) &&
154: (((TapeExtension->TapePosition.D_Segment - 1) -
155: TapeExtension->TapePosition.C_Segment) <= 10)) &&
156: (seekCount > 0));
157:
158: if (seekCount == 0) {
159:
160: CheckedDump(QIC117WARN,( "SeekErr - seekCount = 0\n" ));
161: return(SeekErr);
162:
163: }
164:
165: do {
166:
167: if ((retval = Q117iReadIDRepeat(TapeExtension)) != NoErr) {
168:
169: return(retval);
170:
171: }
172:
173:
174: } while ((TapeExtension->TapePosition.D_Segment - 1) >
175: TapeExtension->TapePosition.C_Segment);
176:
177: return(retval);
178: }
179:
180:
181: STATUS
182: Q117iChangeTrack(
183: IN PTAPE_EXTENSION TapeExtension,
184: IN SHORT DestinationTrack
185: )
186:
187: /*++
188:
189: Routine Description:
190:
191: Position the tape drive head to a new track.
192:
193: Arguments:
194:
195: TapeExtension -
196:
197: DestinationTrack -
198:
199: Return Value:
200:
201:
202:
203: --*/
204:
205: {
206: STATUS retval;
207:
208: if ((retval = Q117iStopTape(TapeExtension)) != NoErr) {
209:
210: return(retval);
211:
212: }
213:
214: if ((retval = Q117iSendByte(TapeExtension, Seek_Track)) != NoErr) {
215:
216: return(retval);
217:
218: }
219:
220: Q117iSleep(TapeExtension, mt_wt2ticks, FALSE);
221:
222: if ((retval = Q117iSendByte(TapeExtension, (CHAR)(DestinationTrack + 2)))
223: != NoErr) {
224:
225: return(retval);
226:
227: }
228:
229: if ((retval = Q117iWaitCommandComplete(TapeExtension, mt_wt007s)) !=
230: NoErr) {
231:
232: return(retval);
233:
234: }
235:
236: TapeExtension->TapePosition.C_Track =
237: TapeExtension->TapePosition.D_Track;
238:
239: if (TapeExtension->DriveParms.Status.BOT ||
240: TapeExtension->DriveParms.Status.EOT) {
241:
242: if (((TapeExtension->TapePosition.C_Track / 2 * 2 ==
243: TapeExtension->TapePosition.C_Track) &&
244: (TapeExtension->DriveParms.Status.BOT)) ||
245: ((TapeExtension->TapePosition.C_Track / 2 * 2 !=
246: TapeExtension->TapePosition.C_Track) &&
247: (TapeExtension->DriveParms.Status.EOT))) {
248:
249: TapeExtension->TapePosition.C_Segment = 0;
250:
251: } else {
252:
253: TapeExtension->TapePosition.C_Segment =
254: TapeExtension->TapeParms.SegTtrack;
255:
256: }
257:
258: }
259: return(retval);
260: }
261:
262:
263: STATUS
264: Q117iReadIDRepeat(
265: IN PTAPE_EXTENSION TapeExtension
266: )
267:
268: /*++
269:
270: Routine Description:
271:
272: Read an ID field off of the tape with the FDC. Read_id_repeat will
273: attempt 10 times to read a legal ID field before a failure is returned.
274:
275: Arguments:
276:
277: TapeExtension -
278:
279: Return Value:
280:
281:
282:
283: --*/
284:
285: {
286: STATUS retval;
287: SHORT readIdCnt;
288: FDC_STATUS status;
289:
290: readIdCnt = NumBad;
291:
292: while (readIdCnt > 0) {
293:
294: --readIdCnt;
295:
296: if ((retval = Q117iStartTape(TapeExtension)) != NoErr) {
297:
298: return(retval);
299:
300: }
301:
302: retval = Q117iDoReadID(TapeExtension, mt_wttrks, &status);
303:
304: if (retval && retval != TimeOut) {
305:
306: return(retval);
307:
308: }
309:
310: if (!retval && !(status.ST0 & ST0_IC) &&
311: (TapeExtension->QControllerData->InterfaceType != MicroChannel ||
312: !(status.ST1 & ST1_MA))) {
313:
314: break;
315:
316: } else {
317:
318: if ((retval = Q117iChangeTrack(
319: TapeExtension,
320: TapeExtension->TapePosition.D_Track)) != NoErr) {
321:
322: return(retval);
323:
324: }
325:
326: if (TapeExtension->DriveParms.Status.BOT ||
327: TapeExtension->DriveParms.Status.EOT) {
328:
329: if (((TapeExtension->TapePosition.C_Track / 2 * 2 ==
330: TapeExtension->TapePosition.C_Track) &&
331: (TapeExtension->DriveParms.Status.BOT)) ||
332: ((TapeExtension->TapePosition.C_Track / 2 * 2 !=
333: TapeExtension->TapePosition.C_Track) &&
334: (TapeExtension->DriveParms.Status.EOT))) {
335:
336: TapeExtension->TapePosition.C_Segment = 0;
337: return(NoErr);
338:
339: } else {
340:
341: TapeExtension->TapePosition.C_Segment =
342: TapeExtension->TapeParms.SegTtrack;
343: return(NoErr);
344:
345: }
346: }
347: }
348: }
349:
350: if (readIdCnt == 0) {
351: CheckedDump(QIC117WARN,( "SeekErr - readIdCnt = 0\n" ));
352: return(SeekErr);
353: }
354:
355: TapeExtension->TapePosition.C_Segment =
356: (status.H * TapeExtension->TapeParms.FtrackFside +
357: status.C) * SEG_FTK + (status.R - 1) / FSC_SEG;
358: TapeExtension->TapePosition.C_Track =
359: TapeExtension->TapePosition.C_Segment /
360: TapeExtension->TapeParms.SegTtrack;
361: TapeExtension->TapePosition.C_Segment =
362: TapeExtension->TapePosition.C_Segment %
363: TapeExtension->TapeParms.SegTtrack;
364:
365: return(retval);
366: }
367:
368:
369: STATUS
370: Q117iDoReadID(
371: IN PTAPE_EXTENSION TapeExtension,
372: IN QIC_TIME ReadIdDelay,
373: IN FDC_STATUS *ReadIdStatus
374: )
375:
376: /*++
377:
378: Routine Description:
379:
380: Try to read an ID fiedl off of the tape via the FDC.
381:
382: Arguments:
383:
384: TapeExtension -
385:
386: ReadIdDelay -
387:
388: ReadIdStatus -
389:
390: Return Value:
391:
392:
393:
394: --*/
395:
396: {
397: STATUS retval;
398: SHORT statLength;
399: struct read_id_cmd readId;
400:
401: readId.command = 0x4a;
402: readId.drive = (UCHAR)TapeExtension->DriveParms.DriveSelect;
403:
404: (VOID) Q117iResetInterruptEvent(TapeExtension);
405: if ((retval = Q117iProgramFDC(
406: TapeExtension,
407: (CHAR *)&readId,
408: sizeof(readId),
409: TRUE)) != NoErr) {
410:
411: Q117iResetFDC(TapeExtension);
412: return(retval);
413:
414: }
415:
416: if ((retval = Q117iSleep(
417: TapeExtension,
418: ReadIdDelay,
419: TRUE)) == TimeOut) {
420:
421: Q117iResetFDC(TapeExtension);
422: return(retval);
423:
424: }
425:
426: if ((retval = Q117iReadFDC(
427: TapeExtension,
428: (CHAR *)ReadIdStatus,
429: &statLength)) != NoErr) {
430:
431: return(retval);
432:
433: }
434:
435: return(retval);
436: }
437:
438:
439: VOID
440: Q117iGetComFirmStr(
441: IN PTAPE_EXTENSION TapeExtension,
442: IN OUT CHAR **Ptr,
443: IN SHORT Index
444: )
445:
446: /*++
447:
448: Routine Description:
449:
450: Takes a string and fills it with a requested DComFirm string.
451:
452: Arguments:
453:
454: TapeExtension -
455:
456: Ptr - a byte pointer that points to memory into which the requested
457: DComFirm string is to be placed.
458:
459: Index - a number that indicates which DcomFirm string to place in the
460: memory pointed to by the Ptr parameter.
461:
462: Return Value:
463:
464: None
465:
466: --*/
467:
468: {
469: SHORT numChars; // number of chars in requested DComfirm str
470:
471:
472: switch(Index) {
473:
474: case DCOMFIRM_READ_RAM_REQ:
475: *Ptr = DCOMFIRM_READ_RAM_STRING;
476: numChars = DCOMFIRM_NUM_READ_RAM_CHARS;
477: break;
478:
479: case DCOMFIRM_SET_RAM_REQ:
480: *Ptr = DCOMFIRM_SET_RAM_STRING;
481: numChars = DCOMFIRM_NUM_SET_RAM_CHARS;
482: break;
483:
484: case DCOMFIRM_WRITE_RAM_REQ:
485: *Ptr = DCOMFIRM_WRITE_RAM_STRING;
486: numChars = DCOMFIRM_NUM_WRITE_RAM_CHARS;
487: break;
488:
489: }
490:
491: }
492:
493:
494: STATUS
495: Q117iLogicalBOT(
496: IN PTAPE_EXTENSION TapeExtension
497: )
498:
499: /*++
500:
501: Routine Description:
502:
503: Go at high speed to logical BOT. Logical BOT is physical BOT for even
504: numbered tracks and physical EOT for odd numbered tracks.
505:
506: Arguments:
507:
508: TapeExtension -
509:
510: Return Value:
511:
512:
513:
514: --*/
515:
516: {
517: STATUS retval;
518: CHAR *string; // holds DComFirm string
519: SHORT direction; // tells physical direction of tape movement
520:
521:
522: if ((retval = Q117iStopTape(TapeExtension)) != NoErr) {
523:
524: return(retval);
525:
526: }
527:
528: if ((TapeExtension->TapePosition.D_Track / 2 * 2) ==
529: TapeExtension->TapePosition.D_Track) {
530:
531: retval = Q117iSendByte(TapeExtension, Physical_Rev);
532: direction = REVERSE;
533:
534: } else {
535:
536: retval = Q117iSendByte(TapeExtension, Physical_Fwd);
537: direction = FORWARD;
538:
539: }
540:
541: if (retval) {
542:
543: return(retval);
544:
545: }
546:
547: //
548: // This is part of the Sankyo motor "hack." While the motor is moving
549: // at high speed to the end of the tape, the driver sets the RAM pointer
550: // on the 8051 to point to the byte in memory that contains the bit that
551: // tells whether or not the EOT/BOT sensor is over a hole. This
552: // concurrent operation is purely for performance enhancement (saves
553: // ~220 msec).
554: //
555:
556: if ((TapeExtension->DriveParms.Version == FIRM_VERSION_64) &&
557: (TapeExtension->DriveParms.Flavor == CMS)) {
558:
559: Q117iSleep(TapeExtension, mt_wt200ms, FALSE);
560:
561: //
562: // Set the ram ptr to the byte with the hole_flag bit.
563: //
564:
565: Q117iGetComFirmStr(TapeExtension, &string, DCOMFIRM_SET_RAM_REQ);
566: string[DCOMFIRM_SETRAM_HI_NIB_INDEX] =
567: HOLE_FLAG_BYTE_ADD_UPPER_NIBBLE;
568: string[DCOMFIRM_SETRAM_LOW_NIB_INDEX] =
569: HOLE_FLAG_BYTE_ADD_LOWER_NIBBLE;
570:
571: if ((retval = Q117iDComFirm(TapeExtension, (CHAR *)string)) !=
572: NoErr) {
573:
574: return(retval);
575:
576: }
577: }
578:
579: if ((retval = Q117iWaitCommandComplete(
580: TapeExtension,
581: TapeExtension->TapeParms.TimeOut[PHYSICAL])) !=
582: NoErr) {
583:
584: return(retval);
585:
586: }
587:
588: if (TapeExtension->DriveParms.Version == FIRM_VERSION_64) {
589:
590: //
591: // Prepare the communication string to read the byte with the
592: // hole_flag bit in it.
593: //
594:
595: //
596: // Wait for the motor to stop.
597: //
598:
599: Q117iSleep(TapeExtension, mt_wt260ms, FALSE);
600:
601:
602: //
603: // Read the byte with the hole flag bit in it. If the bit is 0,
604: // that means the drive has stopped over a hole. In that case,
605: // the tape zone counter must be adjusted and written to the drive,
606: // and the driver saves the day.
607: //
608:
609: Q117iGetComFirmStr(TapeExtension, &string,DCOMFIRM_READ_RAM_REQ);
610:
611: if ((retval = Q117iDComFirm(TapeExtension, (CHAR *)string)) !=
612: NoErr) {
613:
614: return(retval);
615:
616: }
617:
618: if (!(string[DCOMFIRM_READ_RTRN_BYTE_INDEX] & HOLE_INDICATOR_MASK)) {
619:
620: if (direction == REVERSE) {
621:
622: //
623: // If at BOT, the only cause for concern is when the EOT/BOT
624: // sensor is over the rightmost hole of the BOT pair. To
625: // differentiate this from the case where the sensor is
626: // sitting over the leftmost hole, read the double hole
627: // distance counter. If it is non-zero, do nothing.
628: //
629:
630: //
631: // Set the ram ptr to 0x3B, the double hole counter,
632: //
633:
634: Q117iGetComFirmStr(
635: TapeExtension, &string, DCOMFIRM_SET_RAM_REQ);
636: string[DCOMFIRM_SETRAM_HI_NIB_INDEX] =
637: DBL_HOLE_CNTER_ADD_UPPER_NIBBLE;
638: string[DCOMFIRM_SETRAM_LOW_NIB_INDEX] =
639: DBL_HOLE_CNTER_ADD_LOWER_NIBBLE;
640: if ( (retval = Q117iDComFirm(
641: TapeExtension,
642: (CHAR *)string)) != NoErr) {
643:
644: return(retval);
645:
646: }
647:
648: //
649: // Read the double hole counter.
650: //
651:
652: Q117iGetComFirmStr(
653: TapeExtension, &string,DCOMFIRM_READ_RAM_REQ);
654:
655: if ((retval = Q117iDComFirm(
656: TapeExtension,
657: (CHAR *)string)) != NoErr) {
658:
659: return(retval);
660:
661: }
662:
663: if (!(string[DCOMFIRM_READ_RTRN_BYTE_INDEX])) {
664:
665: if ((retval = Q117iAdjustTapeZone(TapeExtension, (SHORT) AT_BOT))
666: != NoErr) {
667:
668: return(retval);
669:
670: }
671: }
672:
673: } else {
674:
675: if ((retval = Q117iAdjustTapeZone(TapeExtension, (SHORT) AT_EOT)) !=
676: NoErr) {
677:
678: return(retval);
679:
680: }
681: }
682: }
683: }
684: if ((TapeExtension->TapePosition.D_Track / 2 * 2) ==
685: TapeExtension->TapePosition.D_Track) {
686:
687: if (!TapeExtension->DriveParms.Status.BOT) {
688:
689: CheckedDump(QIC117WARN,( "SeekErr - not at BOT\n" ));
690: return(SeekErr);
691:
692: }
693:
694: } else {
695:
696: if (!TapeExtension->DriveParms.Status.EOT) {
697:
698: CheckedDump(QIC117WARN,( "SeekErr - not at EOT\n" ));
699: return(SeekErr);
700:
701: }
702: }
703:
704: TapeExtension->TapePosition.C_Segment = 0;
705: return(NoErr);
706: }
707:
708:
709: STATUS
710: Q117iAdjustTapeZone(
711: IN PTAPE_EXTENSION TapeExtension,
712: IN SHORT TapePosition
713: )
714:
715: /*++
716:
717: Routine Description:
718:
719: Adjust the tape zone counter to compensate for stopping with the EOT/BOT
720: sensor over a hole.
721:
722: Arguments:
723:
724: TapeExtension -
725:
726: TapePosition - tells wheather EOT or BOT
727:
728: Return Value:
729:
730:
731:
732: --*/
733:
734: {
735:
736: CHAR highNibble;
737: CHAR lowNibble;
738: CHAR *string;
739: STATUS retval = NoErr;
740:
741: //
742: // Set the pointer in the 8051 RAM to the tape zone counter.
743: //
744:
745: Q117iGetComFirmStr(TapeExtension, &string, DCOMFIRM_SET_RAM_REQ);
746: string[DCOMFIRM_SETRAM_HI_NIB_INDEX] = TAPE_ZONE_BYTE_ADD_UPPER_NIBBLE;
747: string[DCOMFIRM_SETRAM_LOW_NIB_INDEX] = TAPE_ZONE_BTYE_ADD_LOWER_NIBBLE;
748:
749: retval = Q117iDComFirm(TapeExtension, (CHAR *)string);
750:
751: if (retval == NoErr) {
752:
753: if (TapePosition == AT_EOT) {
754:
755: highNibble = EOT_ZONE_COUNTER_UPPER_NIBBLE;
756: lowNibble = EOT_ZONE_COUNTER_LOWER_NIBBLE;
757:
758: } else {
759:
760: highNibble = BOT_ZONE_COUNTER_UPPER_NIBBLE;
761: lowNibble = BOT_ZONE_COUNTER_LOWER_NIBBLE;
762:
763: }
764:
765: //
766: // Write the upper and lower nybbles of the tape zone counter.
767: //
768:
769: Q117iGetComFirmStr(TapeExtension, &string, DCOMFIRM_WRITE_RAM_REQ);
770: string[DCOMFIRM_WRTRAM_HI_NIB_INDEX] = highNibble;
771: string[DCOMFIRM_WRTRAM_LOW_NIB_INDEX] = lowNibble;
772: retval = Q117iDComFirm(TapeExtension, (CHAR *)string);
773: }
774:
775: return(retval);
776: }
777:
778:
779: STATUS
780: Q117iHighSpeedSeek(
781: IN PTAPE_EXTENSION TapeExtension
782: )
783:
784: /*++
785:
786: Routine Description:
787:
788: Execute a High Speed Seek. There are two methods of doing this now.
789: First, if the Skip commands are not implemented, the high speed seek
790: is accomplished by calculating the approximate amount of time needed
791: at high speed to reach the target position and allowing the tape drive
792: to go at 90 ips for that amount of time. If the Skip commands are
793: implemented, the high speed seek is merely the proper command with
794: a calculated offset.
795:
796: The Seeking is done by using either the Skip_N_Segments command or by using
797: the time seeking algorithm provided by Q117iWaitSeek. The Skip_N_Segments commands
798: are not reliable in all versions of the firmware. Only in versions for JUMBO_B
799: and greater are the commands available at all and only in versions of 65 and
800: greater are the Skip_N_Segment commands reliable for skipping past the
801: DC erased gap.
802:
803: Arguments:
804:
805: TapeExtension -
806:
807: Return Value:
808:
809:
810:
811: --*/
812:
813: {
814: STATUS retval = NoErr;
815: SHORT seekOffset;
816: SHORT i;
817: CHAR seekDir;
818: CHAR skipNSegs;
819: USHORT skip;
820:
821: //
822: // Determine the logical direction that the tape needs to be moved
823: //
824:
825: if ((seekOffset = (TapeExtension->TapePosition.D_Segment - 1) -
826: TapeExtension->TapePosition.C_Segment) >= 0) {
827:
828: seekDir = FWD;
829:
830: } else {
831:
832: seekDir = REV;
833: seekOffset = 0 - seekOffset;
834:
835: }
836:
837: if (seekDir == REV || seekOffset > STOP_LEN) {
838:
839: if((retval = Q117iStopTape(TapeExtension)) != NoErr) {
840:
841: return(retval);
842:
843: }
844:
845: if (seekDir == FWD) {
846:
847: if (TapeExtension->DriveParms.SeekMode == SEEK_TIMED) {
848:
849: seekOffset -= SEEK_SLOP;
850:
851: } else {
852:
853: seekOffset -= 1;
854:
855: }
856:
857: } else {
858:
859: //
860: // seek direction is reverse
861: //
862:
863: if (TapeExtension->DriveParms.Status.BOT ||
864: TapeExtension->DriveParms.Status.EOT) {
865:
866: switch (TapeExtension->TapeParms.TapeType) {
867:
868: case QIC40_SHORT:
869: case QIC80_SHORT:
870: seekOffset += QIC_REV_OFFSET;
871: break;
872:
873: case QIC40_LONG:
874: case QIC80_LONG:
875: case QIC500_SHORT:
876: seekOffset += QIC_REV_OFFSET_L;
877: break;
878:
879: case QICEST_40:
880: case QICEST_80:
881: case QICEST_500:
882: seekOffset += QICEST_REV_OFFSET;
883: break;
884:
885: }
886:
887: } else {
888:
889: if (TapeExtension->DriveParms.SeekMode == SEEK_TIMED) {
890:
891: seekOffset += SEEK_SLOP;
892:
893: } else {
894:
895: seekOffset += 1;
896:
897: }
898:
899: }
900: }
901:
902: switch (TapeExtension->DriveParms.SeekMode) {
903:
904: case SEEK_SKIP:
905: //
906: // Determine the offset to be used for the Skip_N_Segment commands
907: //
908:
909: CheckedDump(QIC117SHOWQD,( "Q117i: Skip_N_Segments Seek\n"));
910:
911: if (seekDir == FWD) {
912:
913: skipNSegs = Skip_N_Fwd;
914:
915: } else {
916:
917: skipNSegs = Skip_N_Rev;
918:
919: }
920:
921: // Skip the first bytes worth of segments
922:
923: if ((retval = Q117iSendByte(
924: TapeExtension,
925: skipNSegs)) != NoErr) {
926:
927: return(retval);
928:
929: }
930:
931: Q117iSleep(TapeExtension, mt_wt2ticks, FALSE);
932:
933: if ((retval = Q117iSendByte(
934: TapeExtension,
935: ((seekOffset & 0xf) + 2))) != NoErr) {
936:
937: return(retval);
938:
939: }
940:
941: Q117iSleep(TapeExtension, mt_wt2ticks, FALSE);
942:
943: seekOffset >>= 4;
944:
945: if ((retval = Q117iSendByte(
946: TapeExtension,
947: ((seekOffset & 0x0f)+2))) != NoErr) {
948:
949: return(retval);
950:
951: }
952:
953: Q117iSleep(TapeExtension, mt_wt2ticks, FALSE);
954:
955: if ((retval = Q117iWaitCommandComplete(
956: TapeExtension,
957: TapeExtension->TapeParms.TimeOut[PHYSICAL])) != NoErr) {
958:
959: return(retval);
960:
961: }
962:
963: seekOffset >>= 4;
964:
965: for (;seekOffset != 0; --seekOffset) {
966:
967: // Skip the second bytes worth of segments
968:
969: for (i=0; i<2; ++i) {
970: if (i) {
971:
972: skip = 1;
973:
974: } else {
975:
976: skip = MAX_SKIP;
977:
978: }
979:
980: if ((retval = Q117iSendByte(
981: TapeExtension,
982: skipNSegs)) != NoErr) {
983:
984: return(retval);
985:
986: }
987:
988: Q117iSleep(TapeExtension, mt_wt2ticks, FALSE);
989:
990: if ((retval = Q117iSendByte(
991: TapeExtension,
992: ((skip & 0xf) + 2))) != NoErr) {
993:
994: return(retval);
995:
996: }
997:
998: Q117iSleep(TapeExtension, mt_wt2ticks, FALSE);
999:
1000: if ((retval = Q117iSendByte(
1001: TapeExtension,
1002: ((skip >> 4) + 2))) != NoErr) {
1003:
1004: return(retval);
1005:
1006: }
1007:
1008: Q117iSleep(TapeExtension, mt_wt2ticks, FALSE);
1009:
1010: if ((retval = Q117iWaitCommandComplete(
1011: TapeExtension,
1012: TapeExtension->TapeParms.TimeOut[PHYSICAL])) != NoErr) {
1013:
1014: return(retval);
1015:
1016: }
1017: }
1018: }
1019:
1020: break;
1021:
1022: case SEEK_SKIP_EXTENDED:
1023:
1024: if (seekDir == FWD) {
1025:
1026: skipNSegs = Skip_N_Fwd_Ext;
1027:
1028: } else {
1029:
1030: skipNSegs = Skip_N_Rev_Ext;
1031:
1032: }
1033:
1034:
1035: if ((retval = Q117iSendByte(
1036: TapeExtension,
1037: skipNSegs)) != NoErr) {
1038:
1039: return(retval);
1040:
1041: }
1042:
1043: Q117iSleep(TapeExtension, mt_wt2ticks, FALSE);
1044:
1045: for (i = 0; i < MAX_SEEK_NIBBLES; i++) {
1046:
1047: if ((retval = Q117iSendByte(
1048: TapeExtension,
1049: ((seekOffset & 0xf) + 2))) != NoErr) {
1050:
1051: return(retval);
1052:
1053: }
1054:
1055: Q117iSleep(TapeExtension, mt_wt2ticks, FALSE);
1056:
1057: seekOffset >>= 4;
1058:
1059: }
1060:
1061: if ((retval = Q117iWaitCommandComplete(
1062: TapeExtension,
1063: TapeExtension->TapeParms.TimeOut[PHYSICAL])) != NoErr) {
1064:
1065: return(retval);
1066:
1067: }
1068:
1069: break;
1070:
1071: default: // SEEK_TIMED
1072:
1073: //
1074: // Skip segments commands are not available
1075: //
1076:
1077: CheckedDump(QIC117SHOWQD,( "Q117i: Timed Seek\n"));
1078:
1079:
1080: if (((seekDir == FWD) &&
1081: (TapeExtension->TapePosition.C_Track / 2 * 2 ==
1082: TapeExtension->TapePosition.C_Track)) ||
1083: ((seekDir == REV) &&
1084: (TapeExtension->TapePosition.C_Track / 2 * 2 !=
1085: TapeExtension->TapePosition.C_Track))) {
1086:
1087: if ((retval = Q117iSendByte(TapeExtension, Physical_Fwd)) !=
1088: NoErr) {
1089:
1090: return(retval);
1091:
1092: }
1093:
1094: } else {
1095:
1096: if ((retval = Q117iSendByte(TapeExtension, Physical_Rev)) !=
1097: NoErr) {
1098:
1099: return(retval);
1100:
1101: }
1102: }
1103:
1104: if ((retval = Q117iWaitSeek(TapeExtension, seekOffset)) != NoErr) {
1105:
1106: return(retval);
1107:
1108: }
1109:
1110: if ((retval = Q117iStopTape(TapeExtension)) != NoErr) {
1111:
1112: return(retval);
1113:
1114: }
1115: }
1116: }
1117: return(retval);
1118: }
1119:
1120:
1121: STATUS
1122: Q117iWaitSeek(
1123: IN PTAPE_EXTENSION TapeExtension,
1124: SHORT SeekDelay
1125: )
1126:
1127: /*++
1128:
1129: Routine Description:
1130:
1131: Execute a timed high speed seek. This routine is used for CMS drives
1132: that have not implemented the Skip commands (all those before firmware
1133: version 34) and all non-CMS drives.
1134:
1135: Arguments:
1136:
1137: TapeExtension -
1138:
1139: SeekDelay -
1140:
1141: Return Value:
1142:
1143:
1144:
1145: --*/
1146:
1147: {
1148: STATUS retval;
1149:
1150: do {
1151:
1152: Q117iSleep(TapeExtension, mt_wt200ms, FALSE);
1153: retval = Q117iGetDriveError(TapeExtension);
1154:
1155: if (retval && retval != NotRdy) {
1156:
1157: return(retval);
1158:
1159: }
1160:
1161: if (retval == NoErr) {
1162:
1163: if (TapeExtension->DriveParms.Status.BOT ||
1164: TapeExtension->DriveParms.Status.EOT) {
1165:
1166: break;
1167:
1168: }
1169:
1170: return(DriveFlt);
1171: }
1172:
1173: --SeekDelay;
1174:
1175: } while (SeekDelay > 0);
1176:
1177: return(NoErr);
1178: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.