Annotation of ntddk/src/scsi/qic117/init.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.