|
|
1.1 root 1: /*++
2:
3: Copyright (c) 1993 - Colorado Memory Systems, Inc.
4: All Rights Reserved
5:
6: Module Name:
7:
8: readwrt.c
9:
10: Abstract:
11:
12: Performs low-level read and write operations (with position logic).
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: Q117iReadWrite(
37: IN PTAPE_EXTENSION TapeExtension,
38: IN OUT PIO_REQUEST IoRequestCurrent,
39: IN OUT PIRP Irp
40: )
41:
42: /*++
43:
44:
45: Routine Description:
46:
47: Process a data read or write.
48:
49: The first Wrong Cylinder error is ignored incase of a bad seek. On the
50: system 50, 60, 80 the first N Over Run errors are ignored due to the VGA
51: 16-bit access bug (see PS/2 compatability manual).
52:
53: Arguments:
54:
55: TapeExtension -
56:
57: IoRequestCurrent -
58:
59: Irp -
60:
61: Return Value:
62:
63:
64:
65: --*/
66: {
67: STATUS retval = NoErr;
68: UCHAR i;
69: BOOLEAN dmaDir;
70: STATUS status = NoErr;
71: STATUS sleep_ret = NoErr;
72: RDV_COMMAND rdWrCmd;
73: PIO_STACK_LOCATION irpSp;
74: struct PerpMode perpMode;
75:
76: perpMode.command = PERP_MODE_COMMAND;
77: perpMode.drive_select = TapeExtension->QControllerData->PerpModeSelect;
78: perpMode.reserved = 0;
79: perpMode.over_write = TRUE;
80:
81: irpSp = IoGetCurrentIrpStackLocation( Irp );
82:
83: Q117iGetRetryCounts(TapeExtension, IoRequestCurrent->Command);
84:
85: IoRequestCurrent->RetryList = 0l;
86: TapeExtension->RdWrOp.BytesTransferredSoFar = 0l;
87: TapeExtension->RdWrOp.TotalBytesOfTransfer = 0l;
88: TapeExtension->RdWrOp.RetryCount = TapeExtension->RdWrOp.RetryTimes;
89: TapeExtension->RdWrOp.RetrySectorId = 0;
90: TapeExtension->RdWrOp.SeekFlag = TRUE;
91:
92: if ((retval = Q117iCalcPosition(
93: TapeExtension,
94: IoRequestCurrent->Block,
95: IoRequestCurrent->Number)) != NoErr) {
96:
97: return(retval);
98:
99: }
100:
101: TapeExtension->RdWrOp.CurLst = IoRequestCurrent->BadList;
102:
103: TapeExtension->RdWrOp.Scount = 0;
104:
105: for (i = 0; i < IoRequestCurrent->Number; i++) {
106:
107: if ((TapeExtension->RdWrOp.CurLst & 1) == 0) {
108:
109: TapeExtension->RdWrOp.Scount++;
110:
111: }
112:
113: TapeExtension->RdWrOp.CurLst = TapeExtension->RdWrOp.CurLst >> 1;
114:
115: }
116:
117: TapeExtension->RdWrOp.CurLst = IoRequestCurrent->BadList;
118: TapeExtension->RdWrOp.DataAmount = 0;
119:
120: while (TapeExtension->RdWrOp.Scount != 0 ||
121: TapeExtension->RdWrOp.DataAmount != 0) {
122:
123: if (TapeExtension->RdWrOp.DataAmount == 0) {
124:
125: Q117iNextGoodSectors(TapeExtension);
126:
127: }
128:
129: if ((TapeExtension->TapePosition.D_Track !=
130: TapeExtension->TapePosition.C_Track) ||
131: (TapeExtension->TapePosition.C_Segment >
132: TapeExtension->TapePosition.D_Segment) ||
133: ((TapeExtension->TapePosition.C_Segment !=
134: TapeExtension->TapePosition.D_Segment) &&
135: ((TapeExtension->TapePosition.LogFwd != TRUE) ||
136: ((TapeExtension->TapePosition.D_Segment - 1) !=
137: TapeExtension->TapePosition.C_Segment))))
138:
139: if ((retval = Q117iSeek(TapeExtension)) != NoErr) {
140:
141: return(retval);
142:
143: }
144:
145: if (IoRequestCurrent->Command == DWrite ||
146: IoRequestCurrent->Command == DWriteBad) {
147:
148: dmaDir = DMA_READ;
149:
150: if ((TapeExtension->DriveParms.DriveType == QIC500_DRIVE) &&
151: !TapeExtension->QControllerData->PerpendicularMode) {
152:
153: // Enable Perpendicular Mode
154: perpMode.wgate = 1;
155: perpMode.gap = 1;
156:
157: if ((retval = Q117iProgramFDC(
158: TapeExtension,
159: (CHAR *)&perpMode,
160: sizeof(perpMode),
161: FALSE)) != NoErr) {
162:
163: Q117iResetFDC(TapeExtension);
164: Q117iPauseTape(TapeExtension);
165: return(retval);
166: }
167:
168: TapeExtension->QControllerData->PerpendicularMode = TRUE;
169: }
170:
171: } else {
172:
173: dmaDir = DMA_WRITE;
174:
175: if (TapeExtension->QControllerData->PerpendicularMode) {
176:
177: // Disable Perpendicular Mode
178: perpMode.wgate = 0;
179: perpMode.gap = 0;
180:
181: if ((retval = Q117iProgramFDC(
182: TapeExtension,
183: (CHAR *)&perpMode,
184: sizeof(perpMode),
185: FALSE)) != NoErr) {
186:
187: Q117iResetFDC(TapeExtension);
188: Q117iPauseTape(TapeExtension);
189: return(retval);
190: }
191:
192: TapeExtension->QControllerData->PerpendicularMode = FALSE;
193: }
194:
195: }
196:
197: TapeExtension->RdWrOp.TotalBytesOfTransfer =
198: (ULONG)(TapeExtension->RdWrOp.DataAmount * PHY_SIZ);
199:
200: hio_ProgramDMA(TapeExtension, Irp, dmaDir);
201:
202: switch (IoRequestCurrent->Command) {
203:
204: case DWrite:
205: rdWrCmd.command = WRITE;
206: break;
207:
208: case DWriteBad:
209: rdWrCmd.command = WRTDEL;
210: break;
211:
212: default:
213: rdWrCmd.command = READ;
214:
215: }
216:
217: rdWrCmd.drive = (UCHAR)TapeExtension->DriveParms.DriveSelect;
218: rdWrCmd.C = TapeExtension->RdWrOp.D_FTK;
219: rdWrCmd.H = TapeExtension->RdWrOp.D_Head;
220: rdWrCmd.R = TapeExtension->RdWrOp.D_Sect;
221: rdWrCmd.N = WRT_BPS;
222: rdWrCmd.EOT = (UCHAR)TapeExtension->TapeParms.FsectFtrack;
223: rdWrCmd.GPL = (UCHAR)TapeExtension->TapeParms.RwGapLength;
224: rdWrCmd.DTL = 0xff;
225:
226: if ((retval = Q117iStartTape(TapeExtension)) != NoErr) {
227:
228: hio_FlushDMA(TapeExtension, Irp, dmaDir);
229: return(retval);
230:
231: }
232:
233: (VOID) Q117iResetInterruptEvent(TapeExtension);
234: if ((retval = Q117iProgramFDC(
235: TapeExtension,
236: (CHAR *)&rdWrCmd,
237: sizeof(RDV_COMMAND),
238: TRUE)) != NoErr) {
239:
240: hio_FlushDMA(TapeExtension, Irp, dmaDir);
241: Q117iResetFDC(TapeExtension);
242: Q117iPauseTape(TapeExtension);
243: return(retval);
244: }
245:
246: sleep_ret = Q117iSleep(TapeExtension, mt_wttrks, TRUE);
247: hio_FlushDMA(TapeExtension, Irp, dmaDir);
248:
249: switch (sleep_ret) {
250:
251: case TimeOut:
252: if ((retval = Q117iRW_Timeout(
253: TapeExtension,
254: IoRequestCurrent,
255: &status)) != NoErr) {
256:
257: return(retval);
258:
259: }
260:
261: if (TapeExtension->RdWrOp.NoDat == 0) {
262:
263: return(status);
264:
265: }
266:
267: break;
268:
269: case NoErr:
270:
271: if ((retval = Q117iRW_Normal(
272: TapeExtension,
273: IoRequestCurrent,
274: &status)) != NoErr) {
275:
276: return(retval);
277:
278: }
279:
280: if (status == BadMark || TapeExtension->RdWrOp.NoDat == 0) {
281:
282: return(status);
283:
284: }
285:
286: break;
287:
288: }
289: } /* end of while loop */
290:
291: if (IoRequestCurrent->Command == DRetry) {
292:
293: if (TapeExtension->TapePosition.LogFwd == TRUE) {
294:
295: retval = Q117iGetDriveError(TapeExtension);
296:
297: if (retval && (retval != NotRdy)) {
298:
299: return(retval);
300:
301: }
302:
303: Q117iPauseTape(TapeExtension);
304: }
305:
306: if ((retval = Q117iSetBack(TapeExtension, IoRequestCurrent->Command)) !=
307: NoErr) {
308:
309: return(retval);
310:
311: }
312: }
313:
314:
315: #if DBG
316: if ((QIC117DebugLevel & QIC117MAKEBAD) && status == NoErr &&
317: IoRequestCurrent->Command == DWrite) {
318:
319: LARGE_INTEGER time;
320:
321:
322: // Use the system time as a "Randomizer" to fake bad sectors
323: KeQuerySystemTime(&time);
324: time.LowPart /= 10;
325: if (time.LowPart & 1) {
326: status = BadBlk;
327:
328: IoRequestCurrent->BadList |= 1 << (time.LowPart & 31);
329: if (time.LowPart & 0x100) {
330: IoRequestCurrent->BadList |= 1 << ((time.LowPart>>6) & 31);
331: }
332: if ((time.LowPart & 0xa00) == 0xa00) {
333: IoRequestCurrent->BadList |= 1 << ((time.LowPart>>10) & 31);
334: }
335: CheckedDump(QIC117MAKEBAD, ("badblk generated\n"));
336: } else {
337: CheckedDump(QIC117MAKEBAD, ("no sim\n"));
338: }
339: }
340: #endif
341:
342: return(status);
343: }
344:
345:
346: STATUS
347: Q117iCalcPosition(
348: IN PTAPE_EXTENSION TapeExtension,
349: IN ULONG Block,
350: IN UCHAR Number
351: )
352:
353: /*++
354:
355: Routine Description:
356:
357: Calculate the desired tape position from the Logical Sector Number
358: in the I/O Request.
359:
360: Arguments:
361:
362: TapeExtension -
363:
364: Block -
365:
366: Number -
367:
368: Return Value:
369:
370:
371:
372: --*/
373:
374: {
375: ULONG logSect;
376:
377: //
378: // First check if the desired sector is a legal one, i.e. is less
379: // than the maximum number of sectors on the tape.
380: //
381:
382: CheckedDump(QIC117STOP,( "q117i: requested block %lx\n", Block ));
383:
384: if (Block >= TapeExtension->TapeParms.LogSectors) {
385:
386: return(BadReq);
387:
388: }
389:
390: //
391: // Now we need to determine the sector ID information so that we
392: // can properly program the FDC. The ID information required is the
393: // head, cylinder, and sector numbers. The head number is calculated
394: // as logSect / (floppy sectors per floppy side). This calculation
395: // is done in the while loop which also determines the logical floppy
396: // sector on the floppy side. The cylinder number (d_FTK) and the
397: // sector number (d_sect) are calculated last as (logical floppy sector)
398: // / (floppy sectors per floppy cylinder).
399: //
400:
401: logSect = Block;
402: TapeExtension->RdWrOp.D_Head = 0;
403:
404: while (logSect >= TapeExtension->TapeParms.FsectFside) {
405:
406: logSect -= TapeExtension->TapeParms.FsectFside;
407: TapeExtension->RdWrOp.D_Head++;
408:
409: }
410:
411: TapeExtension->RdWrOp.D_FTK = (UCHAR)(logSect / FSC_FTK);
412:
413: //
414: // fast logSect % 128
415: //
416:
417: TapeExtension->RdWrOp.D_Sect = (UCHAR)(logSect % FSC_FTK) + 1;
418: TapeExtension->RdWrOp.S_Sect = (UCHAR)TapeExtension->RdWrOp.D_Sect;
419:
420: //
421: // Next, we need the tape positioning data. This is the data that
422: // we need to find out where, physically, on the tape we need to be.
423: // The tape track is determined first as
424: // (logical sector number) / (floppy sectors per tape track). The
425: // remainder from this calculation is the absolute sector number
426: // on the tape track. Lastly, the physical segment is determined by
427: // dividing the physical sector number by the number of sectors per
428: // segment.
429: //
430:
431: logSect = Block;
432: TapeExtension->TapePosition.D_Track = 0;
433:
434: while (logSect >= TapeExtension->TapeParms.FsectTtrack) {
435:
436: logSect -= TapeExtension->TapeParms.FsectTtrack;
437: TapeExtension->TapePosition.D_Track++;
438:
439: }
440:
441: logSect = logSect / FSC_SEG;
442: TapeExtension->TapePosition.D_Segment = (SHORT)logSect;
443:
444: //
445: // Finally, if the IO Request requests a read that will cross a segment
446: // boundary then an error is returned.
447: //
448:
449: if((((TapeExtension->RdWrOp.D_Sect - 1) & 0x1f) + Number) >
450: TapeExtension->TapeParms.FsectSeg) {
451:
452: return(BadReq);
453:
454: }
455:
456: return(NoErr);
457: }
458:
459:
460: VOID
461: Q117iGetRetryCounts(
462: IN PTAPE_EXTENSION TapeExtension,
463: IN DRIVER_COMMAND Command
464: )
465:
466: /*++
467:
468: Routine Description:
469:
470: Determine the retry count information according to the drive command
471: eiher read, write, verify, or retry.
472:
473: Arguments:
474:
475: TapeExtension -
476:
477: Command -
478:
479: Return Value:
480:
481: None
482:
483: --*/
484:
485: {
486: switch (Command) {
487:
488: case DWrite:
489: case DWriteBad:
490: TapeExtension->RdWrOp.RetryTimes = WTIMES;
491: TapeExtension->RdWrOp.NoDat = 3;
492: break;
493:
494: case DRead:
495: case DReadBad:
496: TapeExtension->RdWrOp.RetryTimes = ANTIMES;
497: TapeExtension->RdWrOp.NoDat = 3;
498: break;
499:
500: case DVerify:
501: TapeExtension->RdWrOp.RetryTimes = VTIMES;
502: TapeExtension->RdWrOp.NoDat = 2;
503: break;
504:
505: case DRetry:
506: TapeExtension->RdWrOp.RetryTimes = ARTIMES;
507: TapeExtension->RdWrOp.NoDat = ARTIMES;
508: TapeExtension->RetrySeqNum = 0;
509:
510: }
511: }
512:
513:
514: void
515: Q117iNextGoodSectors(
516: IN PTAPE_EXTENSION TapeExtension
517: )
518:
519: /*++
520:
521: Routine Description:
522:
523: Determine the next block of good sectors to read/write/verify.
524:
525: Arguments:
526:
527: TapeExtension -
528:
529: Return Value:
530:
531: None
532:
533: --*/
534:
535: {
536: TapeExtension->RdWrOp.DataAmount = 0;
537:
538: while (TapeExtension->RdWrOp.CurLst & 1) {
539:
540: TapeExtension->RdWrOp.CurLst = TapeExtension->RdWrOp.CurLst >> 1;
541: TapeExtension->RdWrOp.D_Sect++;
542:
543: }
544:
545: do {
546:
547: TapeExtension->RdWrOp.DataAmount++;
548: TapeExtension->RdWrOp.Scount--;
549: TapeExtension->RdWrOp.CurLst = TapeExtension->RdWrOp.CurLst >> 1;
550:
551: } while (!(TapeExtension->RdWrOp.CurLst & 1) &&
552: TapeExtension->RdWrOp.Scount);
553: }
554:
555:
556: STATUS
557: Q117iRW_Timeout(
558: IN PTAPE_EXTENSION TapeExtension,
559: IN OUT PIO_REQUEST IoRequestCurrent,
560: OUT STATUS *Status
561: )
562:
563: /*++
564:
565: Routine Description:
566:
567: Process a TIMEOUT error while reading/writing/verifying. If the FDC
568: does not report any status within the amount of time that the tape
569: would pass apporximately 4 segments, it must be assumed that there is no
570: data on the tape.
571:
572: Arguments:
573:
574: TapeExtension -
575:
576: IoRequestCurrent -
577:
578: Status -
579:
580: Return Value:
581:
582:
583:
584: --*/
585:
586: {
587: STATUS retval;
588:
589: Q117iResetFDC(TapeExtension);
590:
591: if ((retval = Q117iStopTape(TapeExtension)) != NoErr) {
592:
593: return(retval);
594:
595: }
596:
597: if ((retval = Q117iChangeTrack(
598: TapeExtension,
599: TapeExtension->TapePosition.D_Track)) != NoErr) {
600:
601: return(retval);
602:
603: }
604:
605: if (TapeExtension->DriveParms.Status.BOT ||
606: TapeExtension->DriveParms.Status.EOT) {
607:
608: TapeExtension->TapePosition.C_Segment =
609: TapeExtension->TapeParms.SegTtrack;
610:
611: }
612:
613: if (--TapeExtension->RdWrOp.NoDat == 0) {
614:
615: if ((retval = Q117iSetBack(TapeExtension, IoRequestCurrent->Command))
616: != NoErr) {
617:
618: return(retval);
619:
620: }
621:
622: *Status = BadBlk;
623: IoRequestCurrent->BadList = -
624: 1l << (TapeExtension->RdWrOp.D_Sect -
625: TapeExtension->RdWrOp.S_Sect);
626:
627: }
628: return(retval);
629: }
630:
631:
632: STATUS
633: Q117iRW_Normal(
634: IN PTAPE_EXTENSION TapeExtension,
635: IN OUT PIO_REQUEST IoRequestCurrent,
636: OUT STATUS *Status
637: )
638:
639: /*++
640:
641:
642: Routine Description:
643:
644: Process a read/write/verify operation that has returned normally from
645: the FDC.
646:
647: Arguments:
648:
649: TapeExtension -
650:
651: IoRequestCurrent -
652:
653: Status -
654:
655: Return Value:
656:
657:
658:
659: --*/
660:
661: {
662: STATUS retval;
663: SHORT statLength;
664:
665: if ((retval = Q117iReadFDC(
666: TapeExtension,
667: (CHAR *)&TapeExtension->QControllerData->FdcStat,
668: &statLength)) != NoErr) {
669:
670: Q117iPauseTape(TapeExtension);
671: return(retval);
672:
673: }
674:
675: if (statLength != 7) {
676:
677: Q117iResetFDC(TapeExtension);
678: Q117iGetDriveError(TapeExtension);
679: Q117iPauseTape(TapeExtension);
680:
681: if (TapeExtension->RdWrOp.NoDat == 0) {
682:
683: if ((retval = Q117iSetBack(TapeExtension, IoRequestCurrent->Command))
684: != NoErr) {
685:
686: return(retval);
687:
688: }
689:
690: *Status = BadBlk;
691: IoRequestCurrent->BadList =
692: -1l << (TapeExtension->RdWrOp.D_Sect -
693: TapeExtension->RdWrOp.S_Sect);
694: }
695: return(NoErr);
696: }
697:
698: if (TapeExtension->QControllerData->FdcStat.ST1 == 0 &&
699: TapeExtension->QControllerData->FdcStat.ST2 == 0) {
700:
701: //
702: // no errors
703: //
704:
705: DbgAddEntry(TapeExtension->RdWrOp.D_Sect);
706: DbgAddEntry(TapeExtension->RdWrOp.DataAmount);
707: DbgAddEntry(TapeExtension->RdWrOp.CurLst);
708: DbgAddEntry(TapeExtension->RdWrOp.BytesTransferredSoFar);
709:
710: TapeExtension->RdWrOp.SeekFlag = TRUE;
711: TapeExtension->TapePosition.C_Segment =
712: TapeExtension->TapePosition.D_Segment;
713: TapeExtension->RdWrOp.D_Sect +=
714: (UCHAR)TapeExtension->RdWrOp.DataAmount;
715: TapeExtension->RdWrOp.BytesTransferredSoFar +=
716: (ULONG)(TapeExtension->RdWrOp.DataAmount*PHY_SIZ);
717: TapeExtension->RdWrOp.DataAmount = 0;
718: return(NoErr);
719: }
720:
721: if ((IoRequestCurrent->Command == DReadBad) &&
722: (TapeExtension->QControllerData->FdcStat.ST2 & ST2_CM)) {
723:
724: IoRequestCurrent->BadList = 0xffffffff;
725: *Status = BadMark;
726: return(NoErr);
727:
728: }
729:
730: if ((TapeExtension->QControllerData->FdcStat.ST2 & ST2_WC) ||
731: (TapeExtension->QControllerData->FdcStat.ST1 &
732: (ST1_OR | ST1_ND | ST1_MA))) {
733:
734: if (TapeExtension->RdWrOp.SeekFlag == TRUE) {
735:
736: TapeExtension->TapePosition.C_Segment =
737: TapeExtension->TapePosition.D_Segment + 1;
738: TapeExtension->RdWrOp.SeekFlag = FALSE;
739: return(NoErr);
740:
741: }
742: }
743:
744: if ((IoRequestCurrent->Command == DVerify) &&
745: (TapeExtension->QControllerData->FdcStat.ST1 & ST1_MA)) {
746:
747: if (TapeExtension->RdWrOp.SeekFlag == TRUE) {
748:
749: retval = Q117iGetDriveError(TapeExtension);
750:
751: if (retval && (retval != NotRdy)) {
752:
753: return(retval);
754:
755: }
756:
757: if ((retval = Q117iPauseTape(TapeExtension)) != NoErr) {
758:
759: return(retval);
760:
761: }
762:
763: if ((retval = Q117iReadIDRepeat(TapeExtension)) != NoErr) {
764:
765: return(retval);
766:
767: }
768:
769: TapeExtension->RdWrOp.SeekFlag = FALSE;
770: return(NoErr);
771: }
772: }
773:
774: TapeExtension->TapePosition.C_Segment =
775: TapeExtension->TapePosition.D_Segment;
776:
777: retval = Q117iRetryCode(
778: TapeExtension,
779: IoRequestCurrent,
780: &TapeExtension->QControllerData->FdcStat,
781: Status);
782:
783: return(retval);
784: }
785:
786:
787: STATUS
788: Q117iRetryCode(
789: IN PTAPE_EXTENSION TapeExtension,
790: IN OUT PIO_REQUEST IoRequestCurrent,
791: OUT FDC_STATUS *FdcStatus,
792: OUT STATUS *Status
793: )
794:
795: /*++
796:
797: Routine Description:
798:
799: Orchestrate retries for read/write/verify (and retyr) commands.
800:
801: Arguments:
802:
803: TapeExtension -
804:
805: IoRequestCurrent -
806:
807: FdcStatus -
808:
809: Status -
810:
811: Return Value:
812:
813:
814:
815: --*/
816: {
817: STATUS retval;
818: SHORT sectorsRead;
819:
820: if (TapeExtension->RdWrOp.RetryTimes != 0) {
821:
822: if (IoRequestCurrent->Command != DRetry) {
823:
824: retval = Q117iGetDriveError(TapeExtension);
825:
826: if (retval && (retval != NotRdy)) {
827:
828: return(retval);
829:
830: }
831:
832: if ((retval = Q117iPauseTape(TapeExtension)) != NoErr) {
833:
834: return(retval);
835:
836: }
837:
838: }
839:
840: if ((retval = Q117iReadIDRepeat(TapeExtension)) != NoErr) {
841:
842: return(retval);
843:
844: }
845:
846: } else {
847:
848: TapeExtension->RdWrOp.SeekFlag = TRUE;
849:
850: }
851:
852: if ((TapeExtension->RdWrOp.RetryTimes == 0) ||
853: (FdcStatus->R == TapeExtension->RdWrOp.RetrySectorId)) {
854:
855: if ((TapeExtension->RdWrOp.RetryTimes == 0) ||
856: (--TapeExtension->RdWrOp.RetryCount == 0)) {
857:
858: TapeExtension->RdWrOp.SeekFlag = TRUE;
859: IoRequestCurrent->BadList |=
860: 1l << (FdcStatus->R - TapeExtension->RdWrOp.S_Sect);
861: *Status = BadBlk;
862: sectorsRead = FdcStatus->R + 1 - TapeExtension->RdWrOp.D_Sect;
863: TapeExtension->RdWrOp.D_Sect = FdcStatus->R + 1;
864: TapeExtension->RdWrOp.DataAmount -= sectorsRead;
865: TapeExtension->RdWrOp.BytesTransferredSoFar +=
866: sectorsRead * PHY_SIZ;
867: TapeExtension->RdWrOp.RetryCount =
868: TapeExtension->RdWrOp.RetryTimes;
869: TapeExtension->RdWrOp.RetrySectorId = 0;
870: retval = Q117iSetBack(TapeExtension, IoRequestCurrent->Command);
871:
872: } else {
873:
874: retval = Q117iNextTry(TapeExtension, IoRequestCurrent->Command);
875:
876: }
877:
878: } else {
879:
880: IoRequestCurrent->RetryList |=
881: 1l << (FdcStatus->R - TapeExtension->RdWrOp.S_Sect);
882: TapeExtension->RdWrOp.RetrySectorId = FdcStatus->R;
883: TapeExtension->RdWrOp.RetryCount =
884: TapeExtension->RdWrOp.RetryTimes;
885: sectorsRead = FdcStatus->R - TapeExtension->RdWrOp.D_Sect;
886: TapeExtension->RdWrOp.D_Sect = FdcStatus->R;
887: TapeExtension->RdWrOp.DataAmount -= sectorsRead;
888: TapeExtension->RdWrOp.BytesTransferredSoFar +=
889: sectorsRead * PHY_SIZ;
890:
891: }
892:
893: return(retval);
894: }
895:
896:
897:
898: STATUS
899: Q117iNextTry(
900: IN PTAPE_EXTENSION TapeExtension,
901: IN DRIVER_COMMAND Command
902: )
903:
904: /*++
905:
906: Routine Description:
907:
908: Determines the next tape drive head position during off-track retries.
909:
910: Arguments:
911:
912: TapeExtension -
913:
914: Command -
915:
916: Return Value:
917:
918:
919:
920: --*/
921:
922: {
923: STATUS retval = NoErr;
924:
925: if (Command == DRetry) {
926:
927: retval = Q117iGetDriveError(TapeExtension);
928:
929: if (retval && (retval != NotRdy)) {
930:
931: return(retval);
932:
933: }
934:
935: TapeExtension->RetrySeqNum++;
936:
937: if (TapeExtension->RdWrOp.RetryCount > 3) {
938:
939: retval = Q117iSendByte(TapeExtension, Pause);
940:
941: } else {
942:
943: retval = Q117iSendByte(TapeExtension, Micro_Pause);
944:
945: }
946:
947: if (retval) {
948:
949: return(retval);
950:
951: }
952:
953: retval = Q117iWaitCommandComplete(TapeExtension, mt_wt016s);
954: TapeExtension->TapePosition.LogFwd = FALSE;
955:
956: }
957:
958: return(retval);
959: }
960:
961:
962: STATUS
963: Q117iSetBack(
964: IN PTAPE_EXTENSION TapeExtension,
965: IN DRIVER_COMMAND Command
966: )
967:
968: /*++
969:
970: Routine Description:
971:
972: Reset any tape drive head offset due to off-track retries.
973:
974: Arguments:
975:
976: TapeExtension -
977:
978: Command -
979:
980: Return Value:
981:
982:
983:
984: --*/
985: {
986: STATUS retval = NoErr;
987:
988: if (Command == DRetry) {
989:
990: if (TapeExtension->TapePosition.LogFwd == TRUE) {
991:
992: retval = Q117iGetDriveError(TapeExtension);
993:
994: if (retval && (retval != NotRdy)) {
995:
996: return(retval);
997:
998: }
999:
1000: if ((retval = Q117iPauseTape(TapeExtension)) != NoErr) {
1001:
1002: return(retval);
1003:
1004: }
1005:
1006: }
1007:
1008: if ((retval = Q117iSendByte(TapeExtension, Seek_Track)) != NoErr) {
1009:
1010: return(retval);
1011:
1012: }
1013:
1014: Q117iSleep(TapeExtension, mt_wt2ticks, FALSE);
1015:
1016: if ((retval = Q117iSendByte(
1017: TapeExtension,
1018: (CHAR)(TapeExtension->TapePosition.C_Track + 2))) !=
1019: NoErr) {
1020:
1021: return(retval);
1022:
1023: }
1024:
1025: retval = Q117iWaitCommandComplete(TapeExtension, mt_wt007s);
1026: }
1027:
1028: return(retval);
1029: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.