Annotation of ntddk/src/scsi/qic117/init.c, revision 1.1.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.