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