NT4/private/ntos/dd/qic117/stbk.c
2020-09-30 17:12:29 +02:00

344 lines
8.2 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
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"
#define FCT_ID 0x0123
dStatus
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.
--*/
{
dStatus ret = ERR_NO_ERR; // 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))
return(ret);
}
//if (Context->ActiveVolumeNumber == Context->CurrentTape.MaximumVolumes) {
// return(VolFull);
//}
if (Context->CurrentOperation.EndOfUsedTape ==
Context->CurrentTape.LastSegment) {
return ERROR_ENCODE(ERR_TAPE_FULL, FCT_ID, 1);
}
//
// 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);
}
dStatus
q117StartAppend(
IN OUT ULONG BytesAlreadyThere,
IN PVOLUME_TABLE_ENTRY TheVolumeTable,
IN OUT PQ117_CONTEXT Context
)
/*++
Routine Description:
Arguments:
BytesAlreadyThere -
TheVolumeTable -
Context -
Return Value:
--*/
{
dStatus ret = ERR_NO_ERR; // 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,
CMD_READ,
SEGMENT_TO_BLOCK( Context->CurrentOperation.CurrentSegment),
bufferInfo,
Context);
if (!ret) {
//
// Wait for data to be read
//
ioreq=q117Dequeue(WaitForItem,Context);
if (ERROR_DECODE(ioreq->x.adi_hdr.status) != ERR_BAD_BLOCK_DETECTED && ioreq->x.adi_hdr.status) {
ret = ioreq->x.adi_hdr.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);
}
dStatus
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 = ERR_NO_ERR;
//
// 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++;
//
// Calculate the maximum number of marks (based on (the number of
// actual bytes in the segment - count dword) / size of a mark entry)
// NOTE: This value is only useful, and valid, for a backup.
//
Context->MarkArray.MaxMarks = (q117GoodDataBytes(
(SEGMENT)Context->ActiveVolume.DirectorySize, Context ) - sizeof(ULONG))
/ sizeof(struct _MARKLIST);
#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);
}