File:  [WindowsNT SDKs] / ntddk / src / scsi / qic117 / stbk.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:

    stbk.c

Abstract:

    These routines setup all of the global variables for appending
    to current tape.


Revision History:




--*/

//
// include files
//

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


STATUS
q117StartBack(
    IN OUT PVOLUME_TABLE_ENTRY TheVolumeTable,
    IN PQ117_CONTEXT Context
    )

/*++

Routine Description:

    This routine gets the necessry information for backing up to the
    end of the current tape.

Arguments:

    TheVolumeTable - volume table entry to be used for updating the tape
    directory and for tape linking.

Return value:

    Error in return value.

--*/

{
    STATUS ret = NoErr;       // Return value from other routines called
    LONG i;                  // Loop variable.
    VOLUME_TABLE_ENTRY temp;

    //
    // Check to see if anyone has read the last
    // volume entry since Init was called
    //

    if (Context->CurrentOperation.EndOfUsedTape==0) {

        //
        // read tape directory (this sets CurrentOperation.EndOfUsedTape)
        //
        if (ret=q117GetEndBlock(&temp,&i,Context))

            //
            // RdncUnsc (had to skip over the bad sector map), any
            // Driver error except BadBlk, <EndOfVol>, <LinkRC>.
            //
            return(ret);
    }

    if (Context->ActiveVolumeNumber == Context->CurrentTape.MaximumVolumes) {
        return(VolFull);
    }

    if (Context->CurrentOperation.EndOfUsedTape ==
            Context->CurrentTape.LastSegment) {

        return(TapeFull);

    }

    //
    // fill in the appropriate information in
    // the volume entry
    //
    TheVolumeTable->Signature=VolumeTableSig;
    TheVolumeTable->CreationTime = 0;        // lbt_qictime()
    TheVolumeTable->NotVerified = TRUE;      // set if volume not verified yet
    TheVolumeTable->NoNewName = FALSE;       // set if new file names (redirection) disallowed
    TheVolumeTable->SequenceNumber = 1;      // multi-cartridge sequence number

    ret = q117StartComm(TheVolumeTable,Context);

    //
    // do common initialization (start or link)
    //

    return(ret);
}


STATUS
q117StartAppend(
    IN OUT ULONG BytesAlreadyThere,
    IN PVOLUME_TABLE_ENTRY TheVolumeTable,
    IN OUT PQ117_CONTEXT Context
    )

/*++

Routine Description:




Arguments:

    BytesAlreadyThere -

    TheVolumeTable -

    Context -

Return Value:


--*/

{
    STATUS ret = NoErr;            // Return value from other routines called.
    PSEGMENT_BUFFER bufferInfo;
    PIO_REQUEST ioreq;
    int queuePointer;


    //
    // Set up as if we were starting a backup from scratch
    //

    ret = q117StartBack(TheVolumeTable,Context);

    if (!ret) {

        //
        // Now advance past the existing data
        //

        //
        // Walk through the previous backup
        // to find the ending data and segment
        //

        while (BytesAlreadyThere >=
                (ULONG)Context->CurrentOperation.SegmentBytesRemaining) {

            //
            // Adjust counters as if we had backed up the data
            //
            BytesAlreadyThere -=
                Context->CurrentOperation.SegmentBytesRemaining;

            Context->CurrentOperation.BytesOnTape +=
                Context->CurrentOperation.SegmentBytesRemaining;

            ++Context->CurrentOperation.CurrentSegment;

            Context->CurrentOperation.SegmentBytesRemaining =
                q117GoodDataBytes(
                    Context->CurrentOperation.CurrentSegment,
                    Context);
        }

        //
        // If there is data in the segment we are going to append to
        //
        if (BytesAlreadyThere) {
            Context->CurrentOperation.BytesOnTape += BytesAlreadyThere;

            //
            // Get pointer to current buffer and buffer info
            //
            Context->CurrentOperation.SegmentPointer =
                q117GetFreeBuffer(&bufferInfo,Context);

            queuePointer = q117GetQueueIndex(Context);

            //
            // Read this data block into memory
            //
            ret=q117IssIOReq(
                    Context->CurrentOperation.SegmentPointer,
                    DRead,
                    SEGMENT_TO_BLOCK( Context->CurrentOperation.CurrentSegment),
                    bufferInfo,
                    Context);

            if (!ret) {

                //
                // Wait for data to be read
                //
                ioreq=q117Dequeue(WaitForItem,Context);

                if (ioreq->Status != BadBlk && ioreq->Status) {
                    ret = ioreq->Status;
                } else {

                    //
                    // correct data segment with Reed-Solomon and
                    // Heroic retries
                    //
                    ret = q117ReconstructSegment(ioreq,Context);
                }
            }

            //
            // Setup queue to write this buffer back out
            //
            q117SetQueueIndex(queuePointer,Context);

            //
            // Now adjust pointer into buffer to point pass data
            //  that is already there.
            //
            (UCHAR *)Context->CurrentOperation.SegmentPointer +=
                BytesAlreadyThere;

            Context->CurrentOperation.SegmentBytesRemaining -=
                (USHORT)BytesAlreadyThere;

        }
    }

    return(ret);

}


STATUS
q117StartComm(
    OUT PVOLUME_TABLE_ENTRY TheVolumeTable,
    IN OUT PQ117_CONTEXT Context
    )

/*++

Routine Description:

    This routine gets the necessary information for backing up to the end
    of the current tape.

Arguments:

    TheVolumeTable -  volume table entry to be used for updating the tape
    directory and for tape linking.

Return Value:

    Error in return value.

--*/

{
    LONG ret = NoErr;

    //
    // zero out appropriate information
    //
    TheVolumeTable->MultiCartridge = FALSE;  // set if volume spans another tape
    TheVolumeTable->DirectorySize = 0;       // number of bytes reserved for directory
    TheVolumeTable->DataSize = 0;            // size of data area (includes other cartridges)
    TheVolumeTable->EndingSegment = 0;
    TheVolumeTable->NoNewName = FALSE;       // allow restoring to new name (re-direction)
    TheVolumeTable->reserved = 0;            // QIC-40 spec. says to zero this out

    //
    // set global variables
    //
    Context->CurrentOperation.CurrentSegment =
        Context->CurrentOperation.EndOfUsedTape+1;

    Context->CurrentOperation.LastSegment = Context->CurrentTape.LastSegment;

    // clear out the flag for update of bad map
    Context->CurrentOperation.UpdateBadMap = FALSE;

    Context->CurrentOperation.BytesZeroFilled = 0;
    Context->CurrentOperation.BytesOnTape = 0;
    Context->CurrentOperation.SegmentPointer = q117GetFreeBuffer(NULL, Context);

#ifndef NO_MARKS

    //
    // We need to skip segments with no data area (too many bad sectors)
    //
    while ((Context->CurrentOperation.SegmentBytesRemaining =
            q117GoodDataBytes(
                Context->CurrentOperation.CurrentSegment,
                Context)
            ) <= 0) {

        ++Context->CurrentOperation.CurrentSegment;
    }


    //
    // Use the directorySize field to store the segment that has marks
    //
    TheVolumeTable->DirectorySize =
        (ULONG)Context->CurrentOperation.CurrentSegment++;

#endif

    //
    // We need to skip segments with no data area (too many bad sectors)
    //
    while ((Context->CurrentOperation.SegmentBytesRemaining = q117GoodDataBytes(
                                    Context->CurrentOperation.CurrentSegment,
                                    Context)) <= 0) {
        ++Context->CurrentOperation.CurrentSegment;
    }

    TheVolumeTable->StartSegment = Context->CurrentOperation.CurrentSegment;
    return(ret);
}

unix.superglobalmegacorp.com

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