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

    format.c

Abstract:

    Tells the driver to format the tape and calls Erase().

    If DoFormat is TRUE, does format pass and then bad sector mapping; else
    does only the bad sector mapping.


Revision History:




--*/

//
// include files
//

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

#define QIC80_TRACKS_NUM             (VU_80TRACKS_PER_CART * 10)
#define TOTAL_GAS_BLOCKS             20
#define QIC80_TRACKS_DENOM_FACTOR    10

STATUS
q117Format(
    OUT LONG *NumberBad,
    IN UCHAR DoFormat,
    IN PQIC40_VENDOR_UNIQUE VendorUnique,
    IN OUT PQ117_CONTEXT Context
    )

/*++

Routine Description:

    Formats the tape.

Arguments:

    NumberBad - number of bad sectors

    DoFormat - flag of actually do a QIC40 format

    VendorUnique -

    Context -

Return Value:

    NT Status

    NoErr, any Driver error, UnusTape, RdncUnsc, <LinkBack>


--*/

{
    STATUS ret;                     // Return value from other routines called.
    PIO_REQUEST ioreq;
    IO_REQUEST wproIoreq;
    SEGMENT headerSegment[2];
    SEGMENT segment;
    ULONG numberFound;
    PTAPE_HEADER hdr;
    PVOID scrbuf;
    struct S_O_DGetCap tparms;      // tape parameters from the driver
    PSEGMENT_BUFFER bufferInfo;

    //
    // Check for write protected cart,  DSndWPro will
    // return stat = WProt in this case.
    //
    if (ret = q117DoCmd(&wproIoreq, DSndWPro, NULL, Context)) {

        return ret;

    }

    if (ret = q117InitFiler(Context)) {

        return(ret);

    }

    scrbuf = q117GetFreeBuffer(&bufferInfo,Context);

    if (DoFormat)  {

        //
        // Force the tape header,  volume list etc,  to be re-loaded
        //
        Context->CurrentTape.State = NeedInfoLoaded;

        *(UCHAR *)scrbuf=FORMAT_BYTE;

        q117GetTapeCapacity(&tparms,Context);

        if (ret=q117IssIOReq(scrbuf,DFmt,1l,bufferInfo,Context)) {

            //
            // <FMemErr>
            //

            return(ret);

        }

        ioreq = q117Dequeue(WaitForItem,Context);

        if (ioreq->Status) {

            return(ioreq->Status);

        }

        if (ret = q117GetTapeCapacity(NULL,Context)) {

            return(ret);

        }

        //
        // clear the bad block map (erase or's in new bad sectors)
        //

        RtlZeroMemory(
            Context->CurrentTape.BadMapPtr,
            sizeof(BAD_MAP));

        //
        // verify the tape (this will set up the bad sector map)
        //

        if (ret=q117VerifyFormat(Context)) {

            //
            // FMemErr, UnusTape, any Driver error, <LinkBack>, RdncUnsc.
            //

            return(ret);

        }

        //
        // find the first two error free segments for the tape headers
        //

        numberFound = segment = 0;
        while (segment <= Context->CurrentTape.LastSegment && numberFound < 2) {

            if (q117CountBits(Context, segment, 0l) == 0) {

                headerSegment[numberFound++] = segment;

            }
            ++segment;
        }

        if (segment > Context->CurrentTape.LastSegment) {

            return(UnusTape);

        }

        //
        // find the first segment that data can be stored in (more than
        // 3 good sectors).
        //

        while (q117CountBits(Context, segment, 0l) >=
            (BLOCKS_PER_SEGMENT-ECC_BLOCKS_PER_SEGMENT) && segment <= Context->CurrentTape.LastSegment) {

            ++segment;

        }

        Context->CurrentTape.VolumeSegment = segment;

        //
        // count up all bad sectors and find the last segment that data
        // can be stored in.
        //

        q117GetBadSectors(Context);

        *NumberBad = Context->CurrentTape.BadSectors;

        if (Context->CurrentTape.VolumeSegment >= Context->CurrentTape.LastSegment) {

            return(UnusTape);

        }

        //
        // create the tape header
        //

        hdr = (PTAPE_HEADER)scrbuf;

        if (ret = q117BuildHeader(VendorUnique,headerSegment,hdr,Context)) {

            return(ret);

        }

        q117UpdateHeader(hdr,Context);

        //
        // Make memory image of header up to date after format.
        //
        RtlMoveMemory(
            Context->CurrentTape.TapeHeader,
            hdr,
            sizeof(*Context->CurrentTape.TapeHeader) );

        if (!ret) {

            //
            // erase the tape directory
            //

            ret=q117EraseQ(Context);

        }
    }
    return(ret);
}


STATUS
q117BuildHeader(
    OUT PQIC40_VENDOR_UNIQUE VendorUnique,
    IN SEGMENT *HeaderSect,
    IN OUT PTAPE_HEADER Header,
    IN PQ117_CONTEXT Context
    )

/*++

Routine Description:

    Builds the tape header for a format.

Arguments:

    VendorUnique - vendor unique section

    HeaderSect - header segment array

    Header - JUMBO header

Return Value:



--*/

{
    STATUS ret = NoErr;         // Return value from other routines called.
    LONG divisor, dividend;
    struct S_O_DGetCap capacity;

    //
    //      In two of the following calculations, we are changing from the number
    //  of items to the highest possible value for that item. Floppy sectors are
    //  numbered from 1 count, so the count is also the highest possible number.
    //  The rest are numbered 0 through count-1, so the highest possible number
    //  is count-1.
    //      The only fancy calculation is the number of floppy sides. This is
    //  obtained by obtaining the number of logical tape segments (SEG in the
    //  QIC-80 spec), and dividing by the number of segments per track. In addition,
    //  it may be necessary to round up in case of a remainder. To handle the
    //  remainder and the decrement simultaneuously, we decrement only if there
    //  is no remainder.
    //      See the QIC-80 spec, sec 5.3.1 on the identification of sectors, and
    //  7.1, bytes 24 through 29, for the defined values. Wouldn't it be nice
    //  if this stuff were better documented?   -- crc.
    //

    if (!(ret = q117GetTapeCapacity(&capacity,Context))) {

        RtlZeroMemory(
            VendorUnique,
            sizeof(*VendorUnique));

        //
        // Maximum floppy sectors. Warning: #define!
        //

        VendorUnique->correct_name.MaxFlopSect =
            capacity.MaxFSector;

        //
        // Tape segments per tape track
        //

        VendorUnique->correct_name.TrackSeg =
            (USHORT)capacity.SegmentsPerTrack;

        //
        // Tape tracks per cartridge
        //

        VendorUnique->correct_name.CartTracks =
            (UCHAR)capacity.TracksPerTape;

        //
        // Maximum floppy tracks
        //

        VendorUnique->correct_name.MaxFlopTrack =
            capacity.FTrackPerFSide-1;

        //
        // Maximum floppy sides
        //

        dividend = capacity.TracksPerTape * capacity.SegmentsPerTrack;
        divisor = capacity.SegmentsPerFTrack * capacity.FTrackPerFSide;
        VendorUnique->correct_name.MaxFlopSide =
            (UCHAR)(dividend / divisor);

        if( !(dividend % divisor) ) {

            VendorUnique->correct_name.MaxFlopSide--;

        }

    } else {

        return(ret);

    }

    //
    // zero the tape header structure to start with
    //

    RtlZeroMemory(Header,sizeof(TAPE_HEADER));

    //
    // fill in the valid info
    //

    Header->Signature = TapeHeaderSig;                 // set to 0xaa55aa55l
    Header->FormatCode = capacity.TapeFormatCode;      // set to 0x02
    Header->HeaderSegment = (USHORT)HeaderSect[0];     // segment number of header
    Header->DupHeaderSegment = (USHORT)HeaderSect[1];  // segment number of duplicate header
    Header->FirstSegment = (USHORT)Context->CurrentTape.VolumeSegment;  // segment number of Data area
    Header->LastSegment = (USHORT)Context->CurrentTape.LastSegment; // segment number of End of Data area

    //
    // time of most recent format
    //
    Header->CurrentFormat = 0l;    // lbt_qictime()

    //
    // time of most recent write to cartridge
    //
    Header->CurrentUpdate = 0l;    // lbt_qictime()

    //
    // tape name and name change date
    //
    Header->VendorUnique = *VendorUnique;

    Header->ReformatError = 0;     // 0xff if any of remaining data is lost
    Header->SegmentsUsed = 0;      // incremented every time a segment is used
    Header->InitialFormat = 0l;    //lbt_qictime()   time of initial format
    Header->FormatCount = 1;       // number of times tape has been formatted
    Header->FailedSectors = 0;     // the number entries in failed sector log

    //
    //  Set the name of manufacturer that formatted
    //

    strcpy(Header->ManufacturerName,"Microsoft Windows NT (CMS Driver)");
    q117SpacePadString(
        Header->ManufacturerName,
        sizeof(Header->ManufacturerName));

    //
    // set format lot code
    //

    if (Context->drive_type == QIC40_DRIVE) {

        strcpy(Header->LotCode,"User Formatted,  QIC 40 rev G.");

    } else {

        strcpy(Header->LotCode,"User Formatted,  QIC 80 rev D.");

    }

    q117SpacePadString(Header->LotCode,sizeof(Header->LotCode));

    //
    // fill in bad sector map just generated
    //

    RtlMoveMemory(
        &(Header->BadMap),
        Context->CurrentTape.BadMapPtr,
        sizeof(BAD_MAP));

    return(ret);
}

unix.superglobalmegacorp.com

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