|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1993 - Colorado Memory Systems, Inc. ! 4: All Rights Reserved ! 5: ! 6: Module Name: ! 7: ! 8: iformat.c ! 9: ! 10: Abstract: ! 11: ! 12: Performs low level format of tape. ! 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: Q117iDFmt( ! 37: IN PTAPE_EXTENSION TapeExtension, ! 38: IN PIRP Irp, ! 39: OUT PIO_REQUEST IoRequestCurrent ! 40: ) ! 41: ! 42: /*++ ! 43: ! 44: Routine Description: ! 45: ! 46: ! 47: ! 48: Arguments: ! 49: ! 50: TapeExtension - ! 51: ! 52: Irp - ! 53: ! 54: IoRequestCurrent - ! 55: ! 56: Return Value: ! 57: ! 58: ! 59: ! 60: --*/ ! 61: ! 62: { ! 63: STATUS retval; // return value ! 64: SHORT trk = 0; // current track counter ! 65: UCHAR speed; // holds change speed request ! 66: struct PerpMode perpMode; ! 67: ! 68: perpMode.command = PERP_MODE_COMMAND; ! 69: perpMode.drive_select = TapeExtension->QControllerData->PerpModeSelect; ! 70: perpMode.reserved = 0; ! 71: perpMode.over_write = TRUE; ! 72: ! 73: IoRequestCurrent->Data = MmGetSystemAddressForMdl(Irp->MdlAddress); ! 74: ! 75: // ! 76: // Set up NumTracks depending on drive type. ! 77: // ! 78: ! 79: switch (TapeExtension->DriveParms.DriveType) { ! 80: ! 81: case QIC40_DRIVE: ! 82: ! 83: TapeExtension->NumTracks = NUM_TTRK_40; ! 84: break; ! 85: ! 86: case QIC80_DRIVE: ! 87: ! 88: TapeExtension->NumTracks = NUM_TTRK_80; ! 89: break; ! 90: ! 91: case QIC500_DRIVE: ! 92: ! 93: TapeExtension->NumTracks = NUM_TTRK_500; ! 94: break; ! 95: } ! 96: ! 97: // ! 98: // Reset the FDC to make sure it is not in perpendicular Mode. ! 99: // ! 100: ! 101: Q117iResetFDC(TapeExtension); ! 102: ! 103: // ! 104: // Make sure that the tape drive is stopped and ready to start the format ! 105: // operation. ! 106: // ! 107: ! 108: if ((retval = Q117iStopTape(TapeExtension)) == NoErr) { ! 109: ! 110: // ! 111: // Retension the tape before each format since this is not now ! 112: // regularly done when a tape is inserted in the drive. ! 113: // ! 114: ! 115: if (retval == NoErr && TapeExtension->DriveParms.Version >= ! 116: FIRM_VERSION_60) { ! 117: ! 118: if ((retval = Q117iSetDriveMode(TapeExtension, PRIMARY_MODE)) == ! 119: NoErr); { ! 120: ! 121: if ((retval = Q117iDReten(TapeExtension)) == NoErr); { ! 122: ! 123: retval = Q117iSetDriveMode(TapeExtension, FORMAT_MODE); ! 124: ! 125: } ! 126: } ! 127: } ! 128: ! 129: if (retval == NoErr) { ! 130: ! 131: if ((retval = Q117iWriteReferenceBurst(TapeExtension)) == NoErr) { ! 132: ! 133: // ! 134: // This is for the case where a QIC40 tape is fomatted in ! 135: // a QIC80 drive. The speed is set to FAST if the FDC ! 136: // supports the faster transfer rate. ! 137: // ! 138: ! 139: if (TapeExtension->XferRate.XferRate == SLOW && ! 140: TapeExtension->XferRate.MaxRate == FAST) { ! 141: ! 142: speed = DFast; ! 143: retval = Q117iDFast_DSlow(TapeExtension, speed); ! 144: ! 145: } ! 146: ! 147: // ! 148: // Find out what the new tape format will be. This is ! 149: // necessary in case a QIC-40 tape is being formatted in ! 150: // a QIC-80 drive. ! 151: // ! 152: ! 153: if (retval == NoErr) { ! 154: ! 155: if ((retval = Q117iSetDriveMode( ! 156: TapeExtension, ! 157: PRIMARY_MODE)) == NoErr); { ! 158: ! 159: if ((retval = Q117iGetTapeParameters(TapeExtension)) == NoErr); { ! 160: ! 161: retval = Q117iSetDriveMode(TapeExtension, FORMAT_MODE); ! 162: ! 163: } ! 164: ! 165: } ! 166: ! 167: if (retval == NoErr) { ! 168: ! 169: // ! 170: // Now set up the FDC format command data. This is ! 171: // done now since it only needs to be done once and ! 172: // we don't want to use up any more time between ! 173: // segments than we have to. ! 174: // ! 175: ! 176: TapeExtension->QControllerData->FmtCmd.command = 0x4d; ! 177: TapeExtension->QControllerData->FmtCmd.N = FMT_BPS; ! 178: TapeExtension->QControllerData->FmtCmd.SC = FSC_SEG; ! 179: TapeExtension->QControllerData->FmtCmd.GPL = FMT_GPL; ! 180: TapeExtension->QControllerData->FmtCmd.drive = ! 181: (UCHAR)TapeExtension->DriveParms.DriveSelect; ! 182: TapeExtension->QControllerData->FmtCmd.D = ! 183: *(PUCHAR)(IoRequestCurrent->Data); ! 184: ! 185: CheckedDump(QIC117INFO,( "Q117i: Format pattern %x\n", ! 186: TapeExtension->QControllerData->FmtCmd.D)); ! 187: ! 188: if (retval == NoErr) { ! 189: ! 190: do { ! 191: ! 192: // Enable Perpendicular Mode ! 193: if ((TapeExtension->DriveParms.DriveType == QIC500_DRIVE) && ! 194: !TapeExtension->QControllerData->PerpendicularMode) { ! 195: ! 196: perpMode.wgate = 1; ! 197: perpMode.gap = 1; ! 198: ! 199: if ((retval = Q117iProgramFDC( ! 200: TapeExtension, ! 201: (CHAR *)&perpMode, ! 202: sizeof(perpMode), ! 203: FALSE)) != NoErr) { ! 204: ! 205: Q117iResetFDC(TapeExtension); ! 206: Q117iPauseTape(TapeExtension); ! 207: ! 208: } else { ! 209: ! 210: TapeExtension->QControllerData->PerpendicularMode = TRUE; ! 211: ! 212: } ! 213: } ! 214: ! 215: if (retval == NoErr) { ! 216: ! 217: *(PSHORT)IoRequestCurrent->Data = trk; ! 218: retval = Q117iFormatTrack(TapeExtension, ! 219: Irp, ! 220: trk, ! 221: IoRequestCurrent); ! 222: ! 223: CheckedDump(QIC117INFO,( "Q117i: Format track return %d (decimal)\n", retval)); ! 224: ! 225: } ! 226: ! 227: if ((retval == BadFmt) || ! 228: (retval == TapeFlt) || ! 229: (retval == TimeOut)) { ! 230: ! 231: if ((retval = Q117iSetDriveMode( ! 232: TapeExtension, ! 233: PRIMARY_MODE)) == NoErr); { ! 234: ! 235: if ((retval = Q117iLogicalBOT(TapeExtension)) == NoErr); { ! 236: ! 237: retval = Q117iSetDriveMode(TapeExtension, FORMAT_MODE); ! 238: ! 239: } ! 240: ! 241: } ! 242: ! 243: if (retval == NoErr) { ! 244: ! 245: // Enable Perpendicular Mode ! 246: if ((TapeExtension->DriveParms.DriveType == QIC500_DRIVE) && ! 247: !TapeExtension->QControllerData->PerpendicularMode) { ! 248: ! 249: perpMode.wgate = 1; ! 250: perpMode.gap = 1; ! 251: ! 252: if ((retval = Q117iProgramFDC( ! 253: TapeExtension, ! 254: (CHAR *)&perpMode, ! 255: sizeof(perpMode), ! 256: FALSE)) != NoErr) { ! 257: ! 258: Q117iResetFDC(TapeExtension); ! 259: Q117iPauseTape(TapeExtension); ! 260: ! 261: } else { ! 262: ! 263: TapeExtension->QControllerData->PerpendicularMode = TRUE; ! 264: ! 265: } ! 266: } ! 267: ! 268: if (retval == NoErr) { ! 269: ! 270: *(PSHORT)IoRequestCurrent->Data = trk; ! 271: retval = Q117iFormatTrack(TapeExtension, ! 272: Irp, ! 273: trk, ! 274: IoRequestCurrent); ! 275: ! 276: CheckedDump(QIC117INFO,( "Q117i: Format track retry return %d (decimal)\n", retval)); ! 277: } ! 278: ! 279: } ! 280: ! 281: } ! 282: ! 283: } while (++trk < (SHORT)TapeExtension->NumTracks && retval == NoErr); ! 284: ! 285: } ! 286: ! 287: // ! 288: // Finish up the format by putting the tape drive ! 289: // back into primary mode, and ejecting the tape. ! 290: // ! 291: ! 292: if (retval == NoErr) { ! 293: ! 294: if ((retval = Q117iSetDriveMode( ! 295: TapeExtension, ! 296: PRIMARY_MODE)) == NoErr) { ! 297: ! 298: retval = Q117iDEject(TapeExtension); ! 299: ! 300: } ! 301: ! 302: } ! 303: ! 304: } ! 305: ! 306: } ! 307: ! 308: } ! 309: ! 310: } ! 311: ! 312: } ! 313: ! 314: if (TapeExtension->DriveParms.DriveType == QIC500_DRIVE) { ! 315: ! 316: // Disable Perpendicular Mode ! 317: perpMode.wgate = 0; ! 318: perpMode.gap = 0; ! 319: ! 320: if ((retval = Q117iProgramFDC( ! 321: TapeExtension, ! 322: (CHAR *)&perpMode, ! 323: sizeof(perpMode), ! 324: FALSE)) != NoErr) { ! 325: ! 326: Q117iResetFDC(TapeExtension); ! 327: Q117iPauseTape(TapeExtension); ! 328: return(retval); ! 329: } ! 330: ! 331: TapeExtension->QControllerData->PerpendicularMode = FALSE; ! 332: ! 333: } ! 334: ! 335: return(retval); ! 336: } ! 337: ! 338: ! 339: STATUS ! 340: Q117iFormatTrack( ! 341: IN PTAPE_EXTENSION TapeExtension, ! 342: IN PIRP Irp, ! 343: IN SHORT Track, ! 344: IN OUT PIO_REQUEST IoRequestCurrent ! 345: ) ! 346: ! 347: /*++ ! 348: ! 349: Routine Description: ! 350: ! 351: Format a track. ! 352: ! 353: This routine must first calculate the floppy id information for ! 354: the first sector on the requested tape track. First, the logical sector ! 355: is calculated. Next the head, cylinder, and starting sector are ! 356: calculated as follows: ! 357: ! 358: logical sector ! 359: head = ----------------------- ! 360: sectors per floppy side ! 361: ! 362: logical sector % sectors per floppy side ! 363: cylinder = ------------------------------------------ ! 364: floppy sectors per floppy track ! 365: ! 366: sector = logical sector % sectors per floppy side + 1 ! 367: ! 368: ! 369: ! 370: Arguments: ! 371: ! 372: TapeExtension - ! 373: ! 374: Irp - ! 375: ! 376: Track - tape track to format. ! 377: ! 378: IoRequestCurrent - current Request Queue entry ! 379: ! 380: Return Value: ! 381: ! 382: ! 383: ! 384: --*/ ! 385: ! 386: { ! 387: STATUS retval; // return value ! 388: LONG logSector; // logical sector number ! 389: SHORT i; // loop counter ! 390: union format_header hdrData; // sector id data ! 391: ULONG *hdrPtr; // pointer to sector id data for format ! 392: FDC_STATUS fStat; // FDC status response ! 393: SHORT statLength; // length of FDC status response ! 394: struct fdc_result result; ! 395: ! 396: ! 397: TapeExtension->FmtOp.Segments = TapeExtension->FmtOp.Head = 0; ! 398: logSector = (LONG)Track * (LONG)TapeExtension->TapeParms.FsectTtrack; ! 399: ! 400: while (logSector >= (SHORT)TapeExtension->TapeParms.FsectFside) { ! 401: ! 402: logSector -= TapeExtension->TapeParms.FsectFside; ! 403: TapeExtension->FmtOp.Head++; ! 404: ! 405: } ! 406: ! 407: TapeExtension->FmtOp.Cylinder = (UCHAR)((SHORT)logSector / ! 408: (SHORT)TapeExtension->TapeParms.FsectFtrack); ! 409: TapeExtension->FmtOp.Sector = (UCHAR)(((SHORT)logSector % ! 410: (SHORT)TapeExtension->TapeParms.FsectFtrack) + 1); ! 411: ! 412: TapeExtension->FmtOp.MdlAddress = Irp->MdlAddress; ! 413: TapeExtension->FmtOp.HdrPtr = (ULONG *)(IoRequestCurrent->Data); ! 414: ! 415: // ! 416: // Set the tape drive to the specified tape track. ! 417: // ! 418: ! 419: if ((retval = Q117iChangeTrack(TapeExtension, (SHORT)Track)) == NoErr) { ! 420: ! 421: // ! 422: // start the tape ! 423: // ! 424: ! 425: TapeExtension->FmtOp.retval = NoErr; ! 426: TapeExtension->TapePosition.LogFwd = TRUE; ! 427: TapeExtension->QControllerData->StartFormatMode = TRUE; ! 428: TapeExtension->QControllerData->EndFormatMode = FALSE; ! 429: ! 430: Q117iDLockUnlockDMA(TapeExtension, TRUE); ! 431: ! 432: retval = Q117iSendByte(TapeExtension, Logical_Fwd); ! 433: ! 434: CheckedDump(QIC117INFO,( "Q117i: FmtOp int retval %d (decimal)\n", TapeExtension->FmtOp.retval)); ! 435: CheckedDump(QIC117INFO,( "Q117i: FmtOp retval %d (decimal)\n", retval)); ! 436: ! 437: if (retval) { ! 438: ! 439: Q117iResetFDC(TapeExtension); ! 440: retval = Q117iStopTape(TapeExtension); ! 441: ! 442: if (retval == NoErr) { ! 443: ! 444: retval = BadFmt; ! 445: ! 446: } ! 447: ! 448: } else { ! 449: ! 450: // ! 451: // Complete the send byte we started during an interrupt ! 452: // ! 453: ! 454: if ((retval = Q117iReadFDC(TapeExtension, (CHAR *)&result, &statLength)) ! 455: == NoErr) { ! 456: ! 457: if (! (result.ST0 & ST0_IC)) { ! 458: ! 459: if( TapeExtension->QControllerData->InterfaceType != MicroChannel) { ! 460: ! 461: if (result.ST0 != ! 462: (UCHAR)(TapeExtension->DriveParms.DriveSelect | ST0_SE)) { ! 463: ! 464: retval = NECFlt; ! 465: ! 466: } ! 467: } ! 468: ! 469: if (TapeExtension->FmtOp.NCN != result.PCN) { ! 470: ! 471: retval = CmdFlt; ! 472: ! 473: } ! 474: ! 475: TapeExtension->QControllerData->FDC_Pcn = result.PCN; ! 476: ! 477: } else { ! 478: ! 479: retval = NECFlt; ! 480: ! 481: } ! 482: ! 483: } ! 484: ! 485: Q117iSleep(TapeExtension, mt_wt090ms, FALSE); ! 486: ! 487: // ! 488: // If the tape drive is ready when all of the segments have been ! 489: // formatted we must assume something went wrong (probably missed ! 490: // index pulses). ! 491: // ! 492: ! 493: if (Q117iGetDriveError(TapeExtension) == NotRdy) { ! 494: ! 495: if ((retval = Q117iWaitCommandComplete( ! 496: TapeExtension, ! 497: mt_wt035s)) == NoErr) { ! 498: ! 499: TapeExtension->TapePosition.LogFwd = FALSE; ! 500: ! 501: if (!TapeExtension->DriveParms.Status.BOT ! 502: && !TapeExtension->DriveParms.Status.EOT) { ! 503: ! 504: TapeExtension->FirmwareError = Bad_Log_Fwd; ! 505: retval = TapeFlt; ! 506: ! 507: } ! 508: ! 509: } else { ! 510: ! 511: Q117iStopTape(TapeExtension); ! 512: TapeExtension->FirmwareError = Motion_Timeout; ! 513: ! 514: } ! 515: ! 516: } else { ! 517: ! 518: retval = BadFmt; ! 519: ! 520: } ! 521: ! 522: } ! 523: ! 524: } ! 525: ! 526: TapeExtension->QControllerData->StartFormatMode = FALSE; ! 527: TapeExtension->QControllerData->EndFormatMode = FALSE; ! 528: ! 529: return(retval); ! 530: } ! 531: ! 532: STATUS ! 533: Q117iWriteReferenceBurst( ! 534: IN PTAPE_EXTENSION TapeExtension ! 535: ) ! 536: ! 537: /*++ ! 538: ! 539: Routine Description: ! 540: ! 541: Write the regerence burst on the tape. ! 542: ! 543: This operation may be attempted more than once if necessary to ! 544: successfully write the regerence burst. If the drive reports an ! 545: unreferenced tape after this operation then abort the format. ! 546: ! 547: Arguments: ! 548: ! 549: TapeExtension - ! 550: ! 551: Return Value: ! 552: ! 553: ! 554: ! 555: --*/ ! 556: ! 557: { ! 558: STATUS retval; // return value ! 559: SHORT i = 0; // loop counter ! 560: ! 561: do { ! 562: ! 563: if ((retval = Q117iSendByte(TapeExtension, Write_Ref)) == NoErr) { ! 564: ! 565: retval = Q117iWaitCommandComplete(TapeExtension, mt_wt460s); ! 566: ! 567: } ! 568: ! 569: } while (++i < WRITE_REF_RPT && ! 570: !TapeExtension->DriveParms.Status.Referenced && ! 571: retval == NoErr); ! 572: ! 573: if ((retval == NoErr) && !TapeExtension->DriveParms.Status.Referenced) { ! 574: ! 575: retval = BadFmt; ! 576: ! 577: } ! 578: ! 579: return(retval); ! 580: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.