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