File:  [WindowsNT SDKs] / ntddk / src / scsi / qic117 / mapbad.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Thu Aug 9 18:31:12 2018 UTC (7 years, 9 months ago) by root
Branches: msft, MAIN
CVS tags: ntddk-nov-1993, HEAD
Microsoft Windows NT Build 511 (DDK SDK) 11-01-1993

/*++

Copyright (c) 1993 - Colorado Memory Systems, Inc.
All Rights Reserved

Module Name:

    mapbad.c

Abstract:

    These routines map out bad blocks.

Revision History:




--*/

//
// include files
//

#include <ntddk.h>
#include <ntddtape.h>
#include "common.h"
#include "q117.h"
#include "protos.h"

#define SECTOR_POINTER(i,x)  (((UBYTE *)ioArray[i].Data)+(x)*BYTES_PER_SECTOR)

void
q117RotateData(
    IN OUT PQ117_CONTEXT Context,
    IN PIO_REQUEST IoArray,
    IN int IoLast,
    IN int ShiftAmount
    );


STATUS
q117MapBadBlock (
    IN PIO_REQUEST IoRequest,
    OUT PVOID *DataPointer,
    IN OUT USHORT *BytesLeft,
    IN OUT SEGMENT *CurrentSegment,
    IN OUT USHORT *Remainder,
    IN OUT PQ117_CONTEXT Context
    )

/*++

Routine Description:

    Moves existing blocks out of bad sector area and into other
    segments (that already have data in them).

Arguments:

    IoRequest -

    DataPointer -

    BytesLeft -

    CurrentSegment -

    Remainder -

    Context -

Return Value:



--*/

{
    IO_REQUEST ioArray[UNIX_MAXBFS];
    LONG queueItemsUsed;
    LONG i;
    UCHAR newBadSectors;
    UCHAR overflowSectors;
    LONG cur_bad;
    ULONG oldBadSectorMap;
    ULONG currentIndex;
    LONG ret;
    SEGMENT currentSegment;
    USHORT bytesBad;

    //
    // get current queue position
    //
    currentIndex = q117GetQueueIndex(Context);

    //
    // get the current queue list (and clear queue)
    //
    queueItemsUsed = 0;
    ioArray[queueItemsUsed++] = *IoRequest;
    CheckedDump(QIC117SHOWTD,("Re-mapping: %x ", ioArray[0].Block));

    while (!q117QueueEmpty(Context)) {

        ioArray[queueItemsUsed++] = *q117Dequeue(FlushItem, Context);
        CheckedDump(QIC117SHOWTD,("%x " ,
            ioArray[queueItemsUsed-1].Block));

    }
    CheckedDump(QIC117SHOWTD,("\n"));

    q117ClearQueue(Context);

    //
    // write out current buffer
    //
    Context->CurrentOperation.UpdateBadMap = TRUE;
    bytesBad = overflowSectors = 0;
    currentSegment = BLOCK_TO_SEGMENT(IoRequest->Block);
    cur_bad = q117CountBits(Context, currentSegment, 0l);

    while (newBadSectors = q117CountBits(NULL, 0,
                        (~(oldBadSectorMap =
                        q117ReadBadSectorList(Context, currentSegment))) &
                        ioArray[0].BadList)) {


        CheckedDump(QIC117SHOWTD | QIC117SHOWBAD,("Current: %x New: %x\n" ,
            oldBadSectorMap,
            ioArray[0].BadList
            ));

        //
        // add bits to bad sector map and set global flag to update bad
        // sector map
        //
        ret = q117UpdateBadMap(Context, currentSegment, ioArray[0].BadList);
        if (ret != NoErr) {
            return(ret);
        }

        //
        // update total number of mapped out sectors
        //
        cur_bad += newBadSectors;
        bytesBad += newBadSectors * BYTES_PER_SECTOR;
        overflowSectors += newBadSectors;

        if (cur_bad+ECC_BLOCKS_PER_SEGMENT >= BLOCKS_PER_SEGMENT) {
            //
            // fake a write (because all data blocks are bad)
            //
            ioArray[0].BadList = 0;

        } else {

            //
            // move extra data out of the way of correction sectors
            //
            CheckedDump(QIC117SHOWTD,("moving %x to %x (%x bytes)\n" ,
                DATA_BLOCKS_PER_SEGMENT-cur_bad,
                BLOCKS_PER_SEGMENT-overflowSectors,
                bytesBad));

            RtlMoveMemory(
                SECTOR_POINTER(0,BLOCKS_PER_SEGMENT-overflowSectors),
                SECTOR_POINTER(0,DATA_BLOCKS_PER_SEGMENT-cur_bad),
                bytesBad);

            //
            // compute error correction and write out smaller chunk of data
            //
            q117IssIOReq(
                ioArray[0].Data,
                DWrite,
                ioArray[0].Block,
                ioArray[0].BufferInfo,
                Context);

            IoRequest = q117Dequeue(WaitForItem, Context);

            if (IoRequest->Status && IoRequest->Status != BadBlk) {
                return(IoRequest->Status);
            }


            //
            // Get new bad sectors (if any)
            //
            ioArray[0].BadList = IoRequest->BadList;

            //
            // move data back to contiguous form
            //
            CheckedDump(QIC117SHOWTD,("moving %x to %x (%x bytes)\n" ,
                BLOCKS_PER_SEGMENT-overflowSectors,
                DATA_BLOCKS_PER_SEGMENT-cur_bad,
                bytesBad));

            RtlMoveMemory(
                SECTOR_POINTER(0,DATA_BLOCKS_PER_SEGMENT-cur_bad),
                SECTOR_POINTER(0,BLOCKS_PER_SEGMENT-overflowSectors),
                bytesBad);
        }

    } // end of while

    //
    // move bytes mapped out into start of current segment
    //
    if (cur_bad+ECC_BLOCKS_PER_SEGMENT < BLOCKS_PER_SEGMENT) {

        CheckedDump(QIC117SHOWTD,("moving %x to %x (%x bytes)\n" ,
            DATA_BLOCKS_PER_SEGMENT-cur_bad,
            0,
            bytesBad));

        RtlMoveMemory(
            SECTOR_POINTER(0,0),
            SECTOR_POINTER(0,DATA_BLOCKS_PER_SEGMENT-cur_bad),
            bytesBad);

    }

    //
    // We need to skip segments with no data area (less than 4 good segments)
    //
    while ((*BytesLeft = q117GoodDataBytes(*CurrentSegment,Context)) <= 0) {
        ++(*CurrentSegment);
    }

    //
    // if we hit the end of the tape or we are in the directory
    //
    if (*CurrentSegment == Context->CurrentOperation.LastSegment) {
        //
        // if fill data >= number of new bad sectors then continue
        //
        if (Context->CurrentOperation.BytesZeroFilled < bytesBad) {
            //
            // update the bad sector map and return BadBlk detected
            //
            if (ret = q117DoUpdateBad(Context))
                return(ret);
            else
                return(BadBlk);
        }
    }

    //
    // if insufficient space in next good segment then error out
    //
    if (bytesBad > *BytesLeft) {
        //
        // update the bad sector map and return BadBlk detected
        //
        if (ret = q117DoUpdateBad(Context))
            return(ret);
        else
            return(BadBlk);
    }

    //
    // if more than one item was queued, move all previous data
    // out of queue 0 and put overflow into queue 0.
    //

    if (queueItemsUsed > 1) {

        //
        // Rotate the memory through the
        // buffers leaving the most recent data in the item 0
        //
        q117RotateData(
            Context,
            ioArray,
            queueItemsUsed-1,
            overflowSectors
            );
    }

    //
    // set current queue position back (and re-queue data)
    //
    q117SetQueueIndex(currentIndex, Context);

    for (i=1;i<queueItemsUsed;++i)
        q117IssIOReq((PVOID)NULL,DWrite,ioArray[i].Block,NULL,Context);

    //
    // set the current data pointer and bytes left in buffer
    //

    if (Context->CurrentOperation.BytesZeroFilled) {

        if (Context->CurrentOperation.BytesZeroFilled >= bytesBad) {
            Context->CurrentOperation.BytesZeroFilled -= bytesBad;
            *Remainder = 0;
        } else {
            *Remainder = bytesBad - Context->CurrentOperation.BytesZeroFilled;
        }

    } else {

        *Remainder = bytesBad;

    }

    *DataPointer = (UCHAR *)ioArray[0].Data + *Remainder;
    *BytesLeft -= *Remainder;

    return(NoErr);
}

STATUS
q117UpdateBadMap(
    IN OUT PQ117_CONTEXT Context,
    IN SEGMENT Segment,
    IN ULONG BadSectors
    )

/*++

Routine Description:

    if bitmap bad sector map, or in bad sectors
    else
        make badsectors bitmap into a list of sectors
        and merge them into the existing bad sector map.

Arguments:

    IoRequest -

    DataPointer -

    BytesLeft -

    CurrentSegment -

    Remainder -

    Context -

Return Value:



--*/

{
    BAD_LIST badList[BLOCKS_PER_SEGMENT];
    ULONG  curSector;
    ULONG  newSector;
    USHORT insertionPoint = 0;
    USHORT listEnd = 0;
    USHORT currentSectorIndex = 0;
    UCHAR newCount;

#if DBG

    USHORT i,j;
    ULONG  tmpSector;

#endif

    if (Context->CurrentTape.TapeFormatCode == QIC_FORMAT) {

        Context->CurrentTape.BadMapPtr->BadSectors[Segment] |=
            BadSectors;

    } else {

        newCount = q117CountBits(NULL, 0,
                        (~(q117ReadBadSectorList(Context, Segment))) &
                        BadSectors);

                CheckedDump(QIC117SHOWBAD,( "UpdateBadMap newCount = %d\n", newCount));

        // Convert bad sector map (bit field) into a list of sectors
        // that need to be inserted into the list
        q117BadMapToBadList(Segment, 
                                  ((~(q117ReadBadSectorList(Context, Segment))) &
                        BadSectors), badList);

        // Get first entry to add
        newSector = q117BadListEntryToSector(badList[currentSectorIndex].ListEntry);

        // Get first entry in table
        curSector = q117BadListEntryToSector(Context->CurrentTape.BadMapPtr->BadList[listEnd++].ListEntry);

        // While entry in table valid,   and not at end of the list
        while (curSector && (listEnd < MAX_BAD_LIST) ) {

            // If entry less than new item,  then increment insertionPoint
            if (newSector > curSector) {

                insertionPoint++;

            }

            // Get next sector
            curSector = q117BadListEntryToSector(Context->CurrentTape.BadMapPtr->BadList[listEnd++].ListEntry);
        }

        //
        // Now,  list end will be the real end of list
        // and insertionPoint will be the point at which the first
        // sector int the new sector list needs to be added.
        //
        listEnd--;

#if DBG

    CheckedDump(QIC117SHOWBAD,( "\n\nQ117 BSL: BSL to add ---\n"));
         for (i=0; i < newCount; i++) {
        tmpSector = q117BadListEntryToSector(badList[i].ListEntry);
             CheckedDump(QIC117SHOWBAD,( "  %08lx",tmpSector));
                  if (!((i+1) % 5)) {
                        CheckedDump(QIC117SHOWBAD,( "\n"));
                  }
         }
    CheckedDump(QIC117SHOWBAD,( "\n"));

#endif

        // make sure there is enough room for the new items
        if ((listEnd + newCount) >= MAX_BAD_LIST) {

            return(UnusTape);

        }

        //
        // While more sectors to merge
        //
        while (currentSectorIndex < newCount) {

            newSector = q117BadListEntryToSector(
                            badList[currentSectorIndex].ListEntry
                            );

            //
            // get new insertion point (skip any lessor sectors).  First
            // time through,  this will already be done.
            //

            while (insertionPoint <= listEnd) {

                //
                // Get sector at insertionPoint
                //
                curSector = q117BadListEntryToSector(
                            Context->CurrentTape.BadMapPtr->
                            BadList[insertionPoint].ListEntry
                            );

                //
                // if new sector is bigger than the current sector
                // get the next one
                //
                if (newSector > curSector) {

                    ++insertionPoint;

                } else {

                    // We found our next insertion point
                    break;

                }

            }

            //
            // If the sector we need to add is not the same as the current
            // sector at the insertionPoint or we are past the end of the
            // current list,  then we need to add the sector
            // to the list.
            // NOTE:  curSector will not be valid at end of list,  but
            // we don't care.
            //

            if (curSector != newSector || insertionPoint > listEnd) {

                //
                // make space for the new entry (if inserting)
                //
                if (listEnd >= insertionPoint) {
                    RtlMoveMemory(
                        Context->CurrentTape.BadMapPtr->
                            BadList[insertionPoint+1].ListEntry,
                        Context->CurrentTape.BadMapPtr->
                            BadList[insertionPoint].ListEntry,
                        ((ULONG)(listEnd - insertionPoint + 1)
                            * LIST_ENTRY_SIZE)
                        );

                }

                //
                // add the new entry
                //
                RtlMoveMemory(
                    Context->CurrentTape.BadMapPtr->
                        BadList[insertionPoint].ListEntry,
                    badList[currentSectorIndex].ListEntry,
                    LIST_ENTRY_SIZE);

                ++insertionPoint;

                //
                // we just made our list bigger
                //
                ++listEnd;

            }

            //
            // Now get next sector to add
            //
            ++currentSectorIndex;

        }

#if DBG

    CheckedDump(QIC117SHOWBAD,( "\n\nQ117 BSL: New BSL ------\n"));
         for (i=0; i < listEnd; i++) {
        tmpSector = q117BadListEntryToSector(Context->CurrentTape.BadMapPtr->BadList[i].ListEntry);
             CheckedDump(QIC117SHOWBAD,( "  %08lx",tmpSector));
                  if (!((i+1) % 5)) {
                        CheckedDump(QIC117SHOWBAD,( "\n"));
                  }
         }
        CheckedDump(QIC117SHOWBAD,( "\n"));

#endif

    }

    return(NoErr);
}

VOID
q117BadMapToBadList(
    IN SEGMENT Segment,
    IN ULONG BadSectors,
    IN BAD_LIST_PTR BadListPtr
    )

/*++

Routine Description:

Arguments:

    IoRequest -

    DataPointer -

    BytesLeft -

    CurrentSegment -

    Remainder -

    Context -

Return Value:



--*/

{
    USHORT listIndex = 0;
    ULONG sector;

    CheckedDump(QIC117SHOWBAD,( "BadMapToList Segment -> %08lx\n",Segment));
    sector = (ULONG)((Segment * BLOCKS_PER_SEGMENT) + 1);

    while (BadSectors &&
            (listIndex < BLOCKS_PER_SEGMENT)) {

        if (BadSectors & 1l) {

            BadListPtr[listIndex].ListEntry[0] = (UBYTE)(sector & 0xff);
            BadListPtr[listIndex].ListEntry[1] = (UBYTE)((sector >> 8) & 0xff);
            BadListPtr[listIndex].ListEntry[2] = (UBYTE)((sector >> 16) & 0xff);
                        CheckedDump(QIC117SHOWBAD,( "BadMapToList -> %08lx\n",sector));
            listIndex++;

        }

        sector++;
        BadSectors >>= 1;
    }

    if (listIndex < BLOCKS_PER_SEGMENT) {

        BadListPtr[listIndex].ListEntry[0] = (UBYTE)0;
        BadListPtr[listIndex].ListEntry[1] = (UBYTE)0;
        BadListPtr[listIndex].ListEntry[2] = (UBYTE)0;

    }

    return;
}

ULONG
q117BadListEntryToSector(
    IN UCHAR *ListEntry
    )

/*++

Routine Description:

Arguments:

    IoRequest -

    DataPointer -

    BytesLeft -

    CurrentSegment -

    Remainder -

    Context -

Return Value:



--*/

{
    ULONG sector = 0l;

#ifndef i386

    sector = (UBYTE)ListEntry[2];
    sector <<= 8;
    sector |= (UBYTE)ListEntry[1];
    sector <<= 8;
    sector |= (UBYTE)ListEntry[0];

    return(sector);

#else

    return((0x00FFFFFF & *(ULONG *)ListEntry));

#endif

}

void
q117RotateData(
    IN OUT PQ117_CONTEXT Context,
    IN PIO_REQUEST IoArray,
    IN int IoLast,
    IN int ShiftAmount
    )
/*++

Routine Description:

    This routine shifts the data around _ShiftAmount_ times,  by one
    sector.

    Sample:

    IoArray[        0       1       2       3
    data sector     0 1     2 3 4   5 6 7   8

    Step 1: data 0 shifted up

    IoArray[        0       1       2       3
    data sector     0 0 1   2 3 4   5 6 7   8
                    s                       d

    Step 2: source copied to dest

    IoArray[        0       1       2       3
    data sector     8 0 1   2 3 4   5 6 7   8
                                        d   s

    Step 3: pointers decremented (source wraps) and source copied to dest

    IoArray[        0       1       2       3
    data sector     8 0 1   2 3 4   5 6 7   7
                                      d s

    Step 4: pointers decremented and source copied to dest

    IoArray[        0       1       2       3
    data sector     8 0 1   2 3 4   5 6 6   7
                                    d s


    Step 5: pointers decremented and source copied to dest

    IoArray[        0       1       2       3
    data sector     8 0 1   2 3 4   5 5 6   7
                                d   s


    Step 6: pointers decremented and source copied to dest

    IoArray[        0       1       2       3
    data sector     8 0 1   2 3 4   4 5 6   7
                              d s


    Step 7: pointers decremented and source copied to dest

    IoArray[        0       1       2       3
    data sector     8 0 1   2 3 3   4 5 6   7
                            d s


    Step 8: pointers decremented and source copied to dest

    IoArray[        0       1       2       3
    data sector     8 0 1   2 2 3   4 5 6   7
                        d   s

    Step 9: pointers decremented and source copied to dest

    IoArray[        0       1       2       3
    data sector     8 0 1   1 2 3   4 5 6   7
                      d s

    Step 10: pointers decremented and source copied to dest

    IoArray[        0       1       2       3
    data sector     8 0 0   1 2 3   4 5 6   7
                    d s

    Step 10: pointers decremented and source copied to dest

    IoArray[        0       1       2       3
    data sector     8 8 0   1 2 3   4 5 6   7
                    s                       d

    Step 11: process starts over at step 2

    Step 12: data in buffer 0 shifted back down.



Arguments:

Return Value:



--*/
{
    UCHAR *finish;
    UCHAR *source;
    int sourceSize;
    int sourceIndex;
    UCHAR *destination;
    int destinationSize;
    int destinationIndex;
    int loop;

    //
    // Shift over by one (possibly into ECC area to allow for a non
    // destructive rotate.  This will be shifted back after operation
    //
    RtlMoveMemory((UCHAR *)IoArray[0].Data + BYTES_PER_SECTOR, IoArray[0].Data,
        ShiftAmount * BYTES_PER_SECTOR);

    for (loop = 0; loop < ShiftAmount; ++loop) {

        //
        // Begin by overwriting area we just moved out of (see above move)
        //

        destination = IoArray[0].Data;
        destinationSize = BYTES_PER_SECTOR;
        destinationIndex = 0;

        //
        // source points to last sector in queue
        //
        sourceIndex = IoLast;
        sourceSize =
            q117GoodDataBytes(
                BLOCK_TO_SEGMENT(IoArray[sourceIndex].Block),
                Context
                );
        source = (UCHAR *)IoArray[sourceIndex].Data + sourceSize
                    - BYTES_PER_SECTOR;

        finish = source;

        do {

            //
            // shift the data
            //
            CheckedDump(QIC117SHOWTD,("shifting %x-%x[%x]{%x} to %x-%x[%x]\n" ,
                sourceIndex, IoArray[sourceIndex].Block,
                sourceSize - BYTES_PER_SECTOR,
                (ULONG *)source,
                destinationIndex,  IoArray[destinationIndex].Block,
                destinationSize - BYTES_PER_SECTOR));

            RtlMoveMemory(destination, source, BYTES_PER_SECTOR);

            //
            // Decrement the pointer
            //
            destinationSize -= BYTES_PER_SECTOR;
            destination -= BYTES_PER_SECTOR;

            if (destinationSize == 0) {

                if (destinationIndex == 0) {

                    destinationIndex = IoLast;

                } else {

                    --destinationIndex;

                }

                if (destinationIndex == 0) {

                    destinationSize = (ShiftAmount+1) * BYTES_PER_SECTOR;

                } else {

                    destinationSize =
                        q117GoodDataBytes(
                            BLOCK_TO_SEGMENT(IoArray[destinationIndex].Block),
                            Context
                            );

                }
                destination = (UCHAR *)IoArray[destinationIndex].Data
                            + destinationSize
                            - BYTES_PER_SECTOR;
            }

            //
            // Decrement the pointer
            //
            sourceSize -= BYTES_PER_SECTOR;
            source -= BYTES_PER_SECTOR;

            //
            // If we hit the begining of the buffer,
            // go to the previous buffer.
            //
            if (sourceSize == 0) {

                if (sourceIndex == 0) {

                    sourceIndex = IoLast;

                } else {

                    --sourceIndex;

                }

                if (sourceIndex == 0) {

                    sourceSize = (ShiftAmount+1) * BYTES_PER_SECTOR;

                } else {

                    sourceSize =
                        q117GoodDataBytes(
                            BLOCK_TO_SEGMENT(IoArray[sourceIndex].Block),
                            Context
                            );

                }
                source = (UCHAR *)IoArray[sourceIndex].Data + sourceSize
                    - BYTES_PER_SECTOR;
            }

        } while (source != finish);

    }

    //
    // move the data back to the start of the buffer
    //
    RtlMoveMemory(
        (UCHAR *)IoArray[0].Data,
        (UCHAR *)IoArray[0].Data + BYTES_PER_SECTOR,
        ShiftAmount * BYTES_PER_SECTOR
        );
}

unix.superglobalmegacorp.com

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