|
|
1.1 ! root 1: /*++ ! 2: ! 3: Copyright (c) 1993 - Colorado Memory Systems, Inc. ! 4: All Rights Reserved ! 5: ! 6: Module Name: ! 7: ! 8: init.c ! 9: ! 10: Abstract: ! 11: ! 12: This section reads the QIC40 Header and initalizes some ! 13: of the Context for the rest of the system. ! 14: ! 15: ! 16: Revision History: ! 17: ! 18: ! 19: ! 20: ! 21: --*/ ! 22: ! 23: // ! 24: // Includes ! 25: // ! 26: ! 27: #include <ntddk.h> ! 28: #include <ntddtape.h> ! 29: #include "common.h" ! 30: #include "q117.h" ! 31: #include "protos.h" ! 32: ! 33: ! 34: STATUS ! 35: q117LoadTape ( ! 36: IN OUT PTAPE_HEADER *HeaderPointer, ! 37: IN OUT PQ117_CONTEXT Context ! 38: ) ! 39: ! 40: /*++ ! 41: ! 42: Routine Description: ! 43: ! 44: Initialize the tape interface for read or write ! 45: This routine reads the bad sector map into memory. ! 46: ! 47: Arguments: ! 48: ! 49: HeaderPointer - ! 50: ! 51: Context - Context of the driver ! 52: ! 53: Return Value: ! 54: ! 55: NoErr, BadTape, any ! 56: Driver error except BadBlk, <EndOfVol> ! 57: ! 58: --*/ ! 59: ! 60: { ! 61: STATUS ret; // Return value from other routines called or ! 62: // the status of block 1 of tracks 1-5 when read in. ! 63: PTAPE_HEADER hdr; ! 64: unsigned badSize; ! 65: ! 66: if (ret = q117InitFiler(Context)) { ! 67: ! 68: return(ret); ! 69: ! 70: } ! 71: ! 72: q117ClearQueue(Context); ! 73: ! 74: // ! 75: // Is defined later at ReadVolumeEntry(). ! 76: // ! 77: ! 78: Context->CurrentOperation.EndOfUsedTape=0; ! 79: ! 80: if (!ret) { ! 81: ! 82: // ! 83: // this memset allows IssIOReq to find the first two ! 84: // good segments on the tape ! 85: // ! 86: ! 87: RtlZeroMemory( ! 88: Context->CurrentTape.BadMapPtr, ! 89: sizeof(BAD_MAP)); ! 90: ! 91: if (!(ret = q117ReadHeaderSegment(&hdr, Context))) { ! 92: ! 93: if (HeaderPointer) { ! 94: ! 95: *HeaderPointer = (PVOID)hdr; ! 96: ! 97: } ! 98: ! 99: if (Context->CurrentTape.TapeFormatCode == QIC_FORMAT) { ! 100: ! 101: badSize = sizeof(LONG) * (hdr->LastSegment+1); ! 102: ! 103: if (badSize > Context->CurrentTape.BadSectorMapSize) { ! 104: ! 105: ret = BadTape; ! 106: ! 107: } ! 108: ! 109: } ! 110: ! 111: if (ret == NoErr) { ! 112: ! 113: // ! 114: // move the bad sector map into BadSectorMap array ! 115: // ! 116: ! 117: RtlMoveMemory(Context->CurrentTape.BadMapPtr, ! 118: &(hdr->BadMap), sizeof(BAD_MAP)); ! 119: Context->CurrentTape.CurBadListIndex = 0; ! 120: ! 121: // ! 122: // if any bad sectors in the tape directory then don't ! 123: // read ahead ! 124: // ! 125: ! 126: if (q117CountBits(Context, Context->CurrentTape.VolumeSegment, 0l)) { ! 127: ! 128: Context->tapedir = (PIO_REQUEST)NULL; ! 129: ! 130: } ! 131: ! 132: // ! 133: // set global variables ! 134: // ! 135: ! 136: Context->CurrentTape.LastUsedSegment = Context->CurrentTape.VolumeSegment; ! 137: ! 138: // ! 139: // Last data block that can be written to on tape ! 140: // ! 141: ! 142: Context->CurrentTape.LastSegment = hdr->LastSegment; ! 143: Context->CurrentTape.MaximumVolumes = (USHORT) ( ! 144: q117GoodDataBytes(hdr->FirstSegment,Context) / ! 145: sizeof(VOLUME_TABLE_ENTRY)); ! 146: ! 147: // ! 148: // get number of bad sectors on tape and set CurrentTape.LastSegment to ! 149: // last good block ! 150: // ! 151: ! 152: q117GetBadSectors(Context); ! 153: } ! 154: } ! 155: } ! 156: return(ret); ! 157: } ! 158: ! 159: ! 160: STATUS ! 161: q117InitFiler ( ! 162: IN OUT PQ117_CONTEXT Context ! 163: ) ! 164: ! 165: /*++ ! 166: ! 167: Routine Description: ! 168: ! 169: Initialize filer parameters before reading the tape header. ! 170: ! 171: Arguments: ! 172: ! 173: Context - Context of the driver ! 174: ! 175: Return Value: ! 176: ! 177: Driver error except BadBlk, <EndOfVol> ! 178: ! 179: --*/ ! 180: ! 181: { ! 182: STATUS ret; ! 183: ! 184: ret = q117GetTapeCapacity(NULL,Context); ! 185: ! 186: return ret; ! 187: } ! 188: ! 189: ! 190: void ! 191: q117GetBadSectors ( ! 192: IN OUT PQ117_CONTEXT Context ! 193: ) ! 194: ! 195: /*++ ! 196: ! 197: Routine Description: ! 198: ! 199: Gets the number of bad sectors on the whole tape. ! 200: ! 201: Arguments: ! 202: ! 203: Context - Context of the driver ! 204: ! 205: Return Value: ! 206: ! 207: Driver error except BadBlk, <EndOfVol> ! 208: ! 209: --*/ ! 210: ! 211: { ! 212: ULONG badBits; ! 213: SEGMENT segment,lastGood; ! 214: ! 215: Context->CurrentTape.BadSectors = 0; ! 216: ! 217: // ! 218: // count up the bad blocks for status information ! 219: // ! 220: ! 221: for ( segment = 0; segment <= Context->CurrentTape.LastSegment; ++segment ) { ! 222: ! 223: badBits = q117CountBits(Context, segment, 0l); ! 224: ! 225: if (badBits >= BLOCKS_PER_SEGMENT-ECC_BLOCKS_PER_SEGMENT) { ! 226: ! 227: badBits = BLOCKS_PER_SEGMENT; ! 228: ! 229: } else { ! 230: ! 231: lastGood = segment; ! 232: ! 233: } ! 234: ! 235: Context->CurrentTape.BadSectors += badBits; ! 236: ! 237: } ! 238: ! 239: ! 240: // ! 241: // set CurrentTape.LastSegment to last good segment ! 242: // ! 243: ! 244: Context->CurrentTape.LastSegment = lastGood; ! 245: } ! 246: ! 247: ! 248: STATUS ! 249: q117ReadHeaderSegment ( ! 250: OUT PTAPE_HEADER *HeaderPointer, ! 251: IN OUT PQ117_CONTEXT Context ! 252: ) ! 253: ! 254: /*++ ! 255: ! 256: Routine Description: ! 257: ! 258: Reads a QIC40 tape header. This includes reconstructing the header ! 259: using 100% redundancy and Reed-Solomon Error correction. ! 260: ! 261: Arguments: ! 262: ! 263: HeaderPointer - ! 264: ! 265: Context - Context of the driver ! 266: ! 267: Return Value: ! 268: ! 269: Driver error except BadBlk, <EndOfVol> ! 270: ! 271: --*/ ! 272: ! 273: { ! 274: STATUS ret; ! 275: int i,j; ! 276: BLOCK headerBlock[2]; ! 277: LONG headerBlockCount; ! 278: PVOID data; ! 279: PIO_REQUEST ioreq; ! 280: PTAPE_HEADER hdr; ! 281: ! 282: // ! 283: // default volume directory not loaded ! 284: // ! 285: ! 286: Context->tapedir = NULL; ! 287: ! 288: // ! 289: // read first segment from tape ! 290: // ! 291: ! 292: Context->CurrentOperation.CurrentSegment=0; ! 293: ! 294: Context->CurrentTape.BadSectors = headerBlockCount = 0; ! 295: ! 296: // ! 297: // Read the first block of the bad sector map into memory to get the ! 298: // size of the bad sector map. ! 299: // ! 300: ! 301: do { ! 302: ! 303: while (Context->CurrentOperation.CurrentSegment <= ! 304: Context->CurrentTape.LastSegment && ! 305: !q117QueueFull(Context)) { ! 306: ! 307: if (ret = q117IssIOReq( ! 308: (PVOID)NULL, ! 309: DReadBad, ! 310: SEGMENT_TO_BLOCK(Context->CurrentOperation.CurrentSegment), ! 311: NULL, ! 312: Context)) { ! 313: ! 314: return(ret); ! 315: ! 316: } ! 317: ! 318: ++Context->CurrentOperation.CurrentSegment; ! 319: ! 320: } ! 321: ! 322: ioreq = q117Dequeue(WaitForItem, Context); ! 323: ! 324: ret = ioreq->Status; ! 325: ! 326: if (ret == BadBlk || ret == NoErr) { ! 327: ! 328: headerBlock[headerBlockCount++] = ioreq->Block; ! 329: ! 330: if (q117DoCorrect(ioreq->Data,0l,ioreq->BadList)) { ! 331: ! 332: ret = BadBlk; ! 333: ! 334: } else { ! 335: ! 336: ret = NoErr; ! 337: ! 338: } ! 339: ! 340: } ! 341: ! 342: if ((ret != NoErr) && (ret != BadBlk) && ! 343: (ret != NoData) && (ret != BadMark)) { ! 344: ! 345: // ! 346: // A Driver error other tan BadBlk has occurred. ! 347: // ! 348: ! 349: return(ret); ! 350: ! 351: } ! 352: ! 353: } while (ret && headerBlockCount < 2 && (!q117QueueEmpty(Context) || ! 354: Context->CurrentOperation.CurrentSegment <= ! 355: Context->CurrentTape.LastSegment)); ! 356: ! 357: // ! 358: // if we did not find both tape header blocks and we got a bad block ! 359: // (or other driver error) return to caller with BadTape tape ! 360: // ! 361: ! 362: if (headerBlockCount < 2 && ret) { ! 363: ! 364: // ! 365: // All copies of the tape header are bad. ! 366: // ! 367: return(BadTape); ! 368: } ! 369: ! 370: ! 371: // ! 372: // if we got a bad block then we need to do 100% redundancy ! 373: // reconstruction ! 374: // ! 375: ! 376: if (ret == BadBlk) { ! 377: ! 378: ULONG badBits,curentBit; ! 379: ! 380: // ! 381: // clear out any pending requests ! 382: // ! 383: ! 384: q117ClearQueue(Context); ! 385: ! 386: // ! 387: // re-read the first segment (error correction ! 388: // routines corrupt data if they fail) ! 389: // ! 390: ! 391: ret = q117IssIOReq((PVOID)NULL, DReadBad, headerBlock[0],NULL,Context); ! 392: ioreq = q117Dequeue(WaitForItem,Context); ! 393: badBits = ioreq->BadList; ! 394: data = ioreq->Data; ! 395: curentBit = 1; ! 396: ! 397: for (i = 0; i < BLOCKS_PER_SEGMENT; ++i) { ! 398: ! 399: if (badBits & curentBit) { ! 400: ! 401: // ! 402: // try to read bad sector out of either header segment ! 403: // ! 404: ! 405: for ( j = 0; j < 2; ++j ) { ! 406: ! 407: if (ret = q117IssIOReq( ! 408: (UCHAR *)data+(BYTES_PER_SECTOR * i), ! 409: DRetry, ! 410: headerBlock[j]+i, ! 411: ioreq->BufferInfo, ! 412: Context)) { ! 413: ! 414: return(ret); ! 415: ! 416: } ! 417: ! 418: if (q117Dequeue(WaitForItem, Context)->Status == NoErr) { ! 419: ! 420: // ! 421: // turn off the bit (we just got a good copy ! 422: // of this sector) ! 423: // ! 424: ! 425: badBits &= ~curentBit; ! 426: ! 427: // ! 428: // don't try the duplicate header segment ! 429: // ! 430: ! 431: break; ! 432: ! 433: } ! 434: ! 435: } ! 436: ! 437: } ! 438: ! 439: // ! 440: // shift bit left once (optimized) ! 441: // ! 442: ! 443: curentBit += curentBit; ! 444: } ! 445: ! 446: // ! 447: // re-try the error correction after 100% correction ! 448: // ! 449: ! 450: if (q117DoCorrect(data,0l,badBits)) { ! 451: ! 452: return(BadTape); ! 453: ! 454: } ! 455: ! 456: } else { ! 457: ! 458: data = ioreq->Data; ! 459: ! 460: ! 461: // ! 462: // go on and read the volume directory if we have ! 463: // already queued it up ! 464: // ! 465: ! 466: Context->CurrentTape.VolumeSegment = ! 467: ((PTAPE_HEADER)ioreq->Data)->FirstSegment; ! 468: ! 469: if (Context->CurrentTape.VolumeSegment < ! 470: Context->CurrentOperation.CurrentSegment) { ! 471: ! 472: do { ! 473: ! 474: ioreq = q117Dequeue(WaitForItem, Context); ! 475: ! 476: } while (ioreq->Block != ! 477: SEGMENT_TO_BLOCK( Context->CurrentTape.VolumeSegment ) ); ! 478: ! 479: Context->tapedir = ioreq; ! 480: } ! 481: ! 482: q117ClearQueue(Context); ! 483: } ! 484: ! 485: *HeaderPointer = hdr = (PTAPE_HEADER)data; ! 486: ! 487: // ! 488: // make sure this is a valid QIC40 tape ! 489: // ! 490: ! 491: if (hdr->Signature != TapeHeaderSig) { ! 492: ! 493: return(Unformat); ! 494: ! 495: } ! 496: ! 497: if ((hdr->FormatCode != QIC_FORMAT) && ! 498: (hdr->FormatCode != QICEST_FORMAT)) { ! 499: ! 500: return(UnknownFormat); ! 501: ! 502: } else { ! 503: ! 504: Context->CurrentTape.TapeFormatCode = hdr->FormatCode; ! 505: ! 506: } ! 507: ! 508: if (hdr->HeaderSegment != BLOCK_TO_SEGMENT( headerBlock[0] ) ) { ! 509: ! 510: // ! 511: // segment number of header ! 512: // ! 513: ! 514: return(BadTape); ! 515: ! 516: } ! 517: ! 518: if (headerBlockCount > 1 && ! 519: hdr->DupHeaderSegment != BLOCK_TO_SEGMENT( headerBlock[1] ) ) { ! 520: ! 521: // ! 522: // segment number of duplicate header ! 523: // ! 524: ! 525: return(BadTape); ! 526: ! 527: } ! 528: ! 529: ! 530: Context->CurrentTape.VolumeSegment = hdr->FirstSegment; ! 531: ! 532: return(NoErr); ! 533: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.