|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1993 - Colorado Memory Systems, Inc. ! 4: All Rights Reserved ! 5: ! 6: Module Name: ! 7: ! 8: format.c ! 9: ! 10: Abstract: ! 11: ! 12: Tells the driver to format the tape and calls Erase(). ! 13: ! 14: If DoFormat is TRUE, does format pass and then bad sector mapping; else ! 15: does only the bad sector mapping. ! 16: ! 17: ! 18: Revision History: ! 19: ! 20: ! 21: ! 22: ! 23: --*/ ! 24: ! 25: // ! 26: // include files ! 27: // ! 28: ! 29: #include <ntddk.h> ! 30: #include <ntddtape.h> ! 31: #include "common.h" ! 32: #include "q117.h" ! 33: #include "protos.h" ! 34: ! 35: #define QIC80_TRACKS_NUM (VU_80TRACKS_PER_CART * 10) ! 36: #define TOTAL_GAS_BLOCKS 20 ! 37: #define QIC80_TRACKS_DENOM_FACTOR 10 ! 38: ! 39: STATUS ! 40: q117Format( ! 41: OUT LONG *NumberBad, ! 42: IN UCHAR DoFormat, ! 43: IN PQIC40_VENDOR_UNIQUE VendorUnique, ! 44: IN OUT PQ117_CONTEXT Context ! 45: ) ! 46: ! 47: /*++ ! 48: ! 49: Routine Description: ! 50: ! 51: Formats the tape. ! 52: ! 53: Arguments: ! 54: ! 55: NumberBad - number of bad sectors ! 56: ! 57: DoFormat - flag of actually do a QIC40 format ! 58: ! 59: VendorUnique - ! 60: ! 61: Context - ! 62: ! 63: Return Value: ! 64: ! 65: NT Status ! 66: ! 67: NoErr, any Driver error, UnusTape, RdncUnsc, <LinkBack> ! 68: ! 69: ! 70: --*/ ! 71: ! 72: { ! 73: STATUS ret; // Return value from other routines called. ! 74: PIO_REQUEST ioreq; ! 75: IO_REQUEST wproIoreq; ! 76: SEGMENT headerSegment[2]; ! 77: SEGMENT segment; ! 78: ULONG numberFound; ! 79: PTAPE_HEADER hdr; ! 80: PVOID scrbuf; ! 81: struct S_O_DGetCap tparms; // tape parameters from the driver ! 82: PSEGMENT_BUFFER bufferInfo; ! 83: ! 84: // ! 85: // Check for write protected cart, DSndWPro will ! 86: // return stat = WProt in this case. ! 87: // ! 88: if (ret = q117DoCmd(&wproIoreq, DSndWPro, NULL, Context)) { ! 89: ! 90: return ret; ! 91: ! 92: } ! 93: ! 94: if (ret = q117InitFiler(Context)) { ! 95: ! 96: return(ret); ! 97: ! 98: } ! 99: ! 100: scrbuf = q117GetFreeBuffer(&bufferInfo,Context); ! 101: ! 102: if (DoFormat) { ! 103: ! 104: // ! 105: // Force the tape header, volume list etc, to be re-loaded ! 106: // ! 107: Context->CurrentTape.State = NeedInfoLoaded; ! 108: ! 109: *(UCHAR *)scrbuf=FORMAT_BYTE; ! 110: ! 111: q117GetTapeCapacity(&tparms,Context); ! 112: ! 113: if (ret=q117IssIOReq(scrbuf,DFmt,1l,bufferInfo,Context)) { ! 114: ! 115: // ! 116: // <FMemErr> ! 117: // ! 118: ! 119: return(ret); ! 120: ! 121: } ! 122: ! 123: ioreq = q117Dequeue(WaitForItem,Context); ! 124: ! 125: if (ioreq->Status) { ! 126: ! 127: return(ioreq->Status); ! 128: ! 129: } ! 130: ! 131: if (ret = q117GetTapeCapacity(NULL,Context)) { ! 132: ! 133: return(ret); ! 134: ! 135: } ! 136: ! 137: // ! 138: // clear the bad block map (erase or's in new bad sectors) ! 139: // ! 140: ! 141: RtlZeroMemory( ! 142: Context->CurrentTape.BadMapPtr, ! 143: sizeof(BAD_MAP)); ! 144: ! 145: // ! 146: // verify the tape (this will set up the bad sector map) ! 147: // ! 148: ! 149: if (ret=q117VerifyFormat(Context)) { ! 150: ! 151: // ! 152: // FMemErr, UnusTape, any Driver error, <LinkBack>, RdncUnsc. ! 153: // ! 154: ! 155: return(ret); ! 156: ! 157: } ! 158: ! 159: // ! 160: // find the first two error free segments for the tape headers ! 161: // ! 162: ! 163: numberFound = segment = 0; ! 164: while (segment <= Context->CurrentTape.LastSegment && numberFound < 2) { ! 165: ! 166: if (q117CountBits(Context, segment, 0l) == 0) { ! 167: ! 168: headerSegment[numberFound++] = segment; ! 169: ! 170: } ! 171: ++segment; ! 172: } ! 173: ! 174: if (segment > Context->CurrentTape.LastSegment) { ! 175: ! 176: return(UnusTape); ! 177: ! 178: } ! 179: ! 180: // ! 181: // find the first segment that data can be stored in (more than ! 182: // 3 good sectors). ! 183: // ! 184: ! 185: while (q117CountBits(Context, segment, 0l) >= ! 186: (BLOCKS_PER_SEGMENT-ECC_BLOCKS_PER_SEGMENT) && segment <= Context->CurrentTape.LastSegment) { ! 187: ! 188: ++segment; ! 189: ! 190: } ! 191: ! 192: Context->CurrentTape.VolumeSegment = segment; ! 193: ! 194: // ! 195: // count up all bad sectors and find the last segment that data ! 196: // can be stored in. ! 197: // ! 198: ! 199: q117GetBadSectors(Context); ! 200: ! 201: *NumberBad = Context->CurrentTape.BadSectors; ! 202: ! 203: if (Context->CurrentTape.VolumeSegment >= Context->CurrentTape.LastSegment) { ! 204: ! 205: return(UnusTape); ! 206: ! 207: } ! 208: ! 209: // ! 210: // create the tape header ! 211: // ! 212: ! 213: hdr = (PTAPE_HEADER)scrbuf; ! 214: ! 215: if (ret = q117BuildHeader(VendorUnique,headerSegment,hdr,Context)) { ! 216: ! 217: return(ret); ! 218: ! 219: } ! 220: ! 221: q117UpdateHeader(hdr,Context); ! 222: ! 223: // ! 224: // Make memory image of header up to date after format. ! 225: // ! 226: RtlMoveMemory( ! 227: Context->CurrentTape.TapeHeader, ! 228: hdr, ! 229: sizeof(*Context->CurrentTape.TapeHeader) ); ! 230: ! 231: if (!ret) { ! 232: ! 233: // ! 234: // erase the tape directory ! 235: // ! 236: ! 237: ret=q117EraseQ(Context); ! 238: ! 239: } ! 240: } ! 241: return(ret); ! 242: } ! 243: ! 244: ! 245: STATUS ! 246: q117BuildHeader( ! 247: OUT PQIC40_VENDOR_UNIQUE VendorUnique, ! 248: IN SEGMENT *HeaderSect, ! 249: IN OUT PTAPE_HEADER Header, ! 250: IN PQ117_CONTEXT Context ! 251: ) ! 252: ! 253: /*++ ! 254: ! 255: Routine Description: ! 256: ! 257: Builds the tape header for a format. ! 258: ! 259: Arguments: ! 260: ! 261: VendorUnique - vendor unique section ! 262: ! 263: HeaderSect - header segment array ! 264: ! 265: Header - JUMBO header ! 266: ! 267: Return Value: ! 268: ! 269: ! 270: ! 271: --*/ ! 272: ! 273: { ! 274: STATUS ret = NoErr; // Return value from other routines called. ! 275: LONG divisor, dividend; ! 276: struct S_O_DGetCap capacity; ! 277: ! 278: // ! 279: // In two of the following calculations, we are changing from the number ! 280: // of items to the highest possible value for that item. Floppy sectors are ! 281: // numbered from 1 count, so the count is also the highest possible number. ! 282: // The rest are numbered 0 through count-1, so the highest possible number ! 283: // is count-1. ! 284: // The only fancy calculation is the number of floppy sides. This is ! 285: // obtained by obtaining the number of logical tape segments (SEG in the ! 286: // QIC-80 spec), and dividing by the number of segments per track. In addition, ! 287: // it may be necessary to round up in case of a remainder. To handle the ! 288: // remainder and the decrement simultaneuously, we decrement only if there ! 289: // is no remainder. ! 290: // See the QIC-80 spec, sec 5.3.1 on the identification of sectors, and ! 291: // 7.1, bytes 24 through 29, for the defined values. Wouldn't it be nice ! 292: // if this stuff were better documented? -- crc. ! 293: // ! 294: ! 295: if (!(ret = q117GetTapeCapacity(&capacity,Context))) { ! 296: ! 297: RtlZeroMemory( ! 298: VendorUnique, ! 299: sizeof(*VendorUnique)); ! 300: ! 301: // ! 302: // Maximum floppy sectors. Warning: #define! ! 303: // ! 304: ! 305: VendorUnique->correct_name.MaxFlopSect = ! 306: capacity.MaxFSector; ! 307: ! 308: // ! 309: // Tape segments per tape track ! 310: // ! 311: ! 312: VendorUnique->correct_name.TrackSeg = ! 313: (USHORT)capacity.SegmentsPerTrack; ! 314: ! 315: // ! 316: // Tape tracks per cartridge ! 317: // ! 318: ! 319: VendorUnique->correct_name.CartTracks = ! 320: (UCHAR)capacity.TracksPerTape; ! 321: ! 322: // ! 323: // Maximum floppy tracks ! 324: // ! 325: ! 326: VendorUnique->correct_name.MaxFlopTrack = ! 327: capacity.FTrackPerFSide-1; ! 328: ! 329: // ! 330: // Maximum floppy sides ! 331: // ! 332: ! 333: dividend = capacity.TracksPerTape * capacity.SegmentsPerTrack; ! 334: divisor = capacity.SegmentsPerFTrack * capacity.FTrackPerFSide; ! 335: VendorUnique->correct_name.MaxFlopSide = ! 336: (UCHAR)(dividend / divisor); ! 337: ! 338: if( !(dividend % divisor) ) { ! 339: ! 340: VendorUnique->correct_name.MaxFlopSide--; ! 341: ! 342: } ! 343: ! 344: } else { ! 345: ! 346: return(ret); ! 347: ! 348: } ! 349: ! 350: // ! 351: // zero the tape header structure to start with ! 352: // ! 353: ! 354: RtlZeroMemory(Header,sizeof(TAPE_HEADER)); ! 355: ! 356: // ! 357: // fill in the valid info ! 358: // ! 359: ! 360: Header->Signature = TapeHeaderSig; // set to 0xaa55aa55l ! 361: Header->FormatCode = capacity.TapeFormatCode; // set to 0x02 ! 362: Header->HeaderSegment = (USHORT)HeaderSect[0]; // segment number of header ! 363: Header->DupHeaderSegment = (USHORT)HeaderSect[1]; // segment number of duplicate header ! 364: Header->FirstSegment = (USHORT)Context->CurrentTape.VolumeSegment; // segment number of Data area ! 365: Header->LastSegment = (USHORT)Context->CurrentTape.LastSegment; // segment number of End of Data area ! 366: ! 367: // ! 368: // time of most recent format ! 369: // ! 370: Header->CurrentFormat = 0l; // lbt_qictime() ! 371: ! 372: // ! 373: // time of most recent write to cartridge ! 374: // ! 375: Header->CurrentUpdate = 0l; // lbt_qictime() ! 376: ! 377: // ! 378: // tape name and name change date ! 379: // ! 380: Header->VendorUnique = *VendorUnique; ! 381: ! 382: Header->ReformatError = 0; // 0xff if any of remaining data is lost ! 383: Header->SegmentsUsed = 0; // incremented every time a segment is used ! 384: Header->InitialFormat = 0l; //lbt_qictime() time of initial format ! 385: Header->FormatCount = 1; // number of times tape has been formatted ! 386: Header->FailedSectors = 0; // the number entries in failed sector log ! 387: ! 388: // ! 389: // Set the name of manufacturer that formatted ! 390: // ! 391: ! 392: strcpy(Header->ManufacturerName,"Microsoft Windows NT (CMS Driver)"); ! 393: q117SpacePadString( ! 394: Header->ManufacturerName, ! 395: sizeof(Header->ManufacturerName)); ! 396: ! 397: // ! 398: // set format lot code ! 399: // ! 400: ! 401: if (Context->drive_type == QIC40_DRIVE) { ! 402: ! 403: strcpy(Header->LotCode,"User Formatted, QIC 40 rev G."); ! 404: ! 405: } else { ! 406: ! 407: strcpy(Header->LotCode,"User Formatted, QIC 80 rev D."); ! 408: ! 409: } ! 410: ! 411: q117SpacePadString(Header->LotCode,sizeof(Header->LotCode)); ! 412: ! 413: // ! 414: // fill in bad sector map just generated ! 415: // ! 416: ! 417: RtlMoveMemory( ! 418: &(Header->BadMap), ! 419: Context->CurrentTape.BadMapPtr, ! 420: sizeof(BAD_MAP)); ! 421: ! 422: return(ret); ! 423: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.