210 lines
4.4 KiB
C
210 lines
4.4 KiB
C
/*++
|
||
|
||
Copyright (c) 1993 - Colorado Memory Systems, Inc.
|
||
All Rights Reserved
|
||
|
||
Module Name:
|
||
|
||
readtape.c
|
||
|
||
Abstract:
|
||
|
||
Reads data as a byte stream from the selected volume.
|
||
|
||
Revision History:
|
||
|
||
|
||
|
||
|
||
--*/
|
||
|
||
//
|
||
// Includes
|
||
//
|
||
|
||
#include <ntddk.h>
|
||
#include <ntddtape.h> // tape device driver I/O control codes
|
||
#include "common.h"
|
||
#include "q117.h"
|
||
#include "protos.h"
|
||
|
||
#define FCT_ID 0x0116
|
||
|
||
dStatus
|
||
q117ReadTape (
|
||
OUT PVOID ToWhere,
|
||
IN OUT ULONG *HowMany,
|
||
IN OUT PQ117_CONTEXT Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Coeleates data from multiple segment buffers to reconstruct
|
||
the original data stream.
|
||
|
||
Arguments:
|
||
|
||
|
||
Return Value:
|
||
|
||
--*/
|
||
|
||
{
|
||
USHORT left;
|
||
UCHAR *ptr;
|
||
dStatus ret,readret;
|
||
ULONG leftToRead;
|
||
ULONG bytesToRead;
|
||
#ifndef NO_MARKS
|
||
ULONG leftTillMark;
|
||
ULONG bytesToSkip;
|
||
#endif
|
||
|
||
|
||
bytesToRead = *HowMany;
|
||
*HowMany = 0;
|
||
|
||
readret = Context->CurrentOperation.SegmentStatus;
|
||
|
||
#ifndef NO_MARKS
|
||
|
||
leftTillMark = Context->MarkArray.MarkEntry[Context->CurrentMark].Offset -
|
||
Context->CurrentOperation.BytesRead;
|
||
|
||
bytesToSkip = 0;
|
||
|
||
if (bytesToRead > leftTillMark) {
|
||
|
||
bytesToRead = leftTillMark;
|
||
|
||
switch(Context->MarkArray.MarkEntry[Context->CurrentMark].Type) {
|
||
|
||
case TAPE_SETMARKS:
|
||
readret = ERROR_ENCODE(ERR_SET_MARK,FCT_ID, 1);;
|
||
break;
|
||
|
||
case TAPE_FILEMARKS:
|
||
readret = ERROR_ENCODE(ERR_FILE_MARK,FCT_ID, 1);
|
||
break;
|
||
|
||
case TAPE_SHORT_FILEMARKS:
|
||
readret = ERROR_ENCODE(ERR_SHORT_FILE_MARK,FCT_ID, 1);
|
||
break;
|
||
|
||
case TAPE_LONG_FILEMARKS:
|
||
readret = ERROR_ENCODE(ERR_LONG_FILE_MARK,FCT_ID, 1);
|
||
break;
|
||
|
||
default:
|
||
return ERROR_ENCODE(ERR_PROGRAM_FAILURE, FCT_ID, 1);
|
||
|
||
}
|
||
bytesToSkip = BLOCK_SIZE;
|
||
++Context->CurrentMark;
|
||
}
|
||
|
||
#endif
|
||
|
||
if (bytesToRead > Context->CurrentOperation.BytesOnTape) {
|
||
|
||
bytesToRead = Context->CurrentOperation.BytesOnTape;
|
||
|
||
readret = ERROR_ENCODE(ERR_END_OF_VOLUME, FCT_ID, 1);
|
||
}
|
||
|
||
if (bytesToRead == Context->CurrentOperation.BytesOnTape) {
|
||
|
||
//
|
||
// Flag end of tape. This will allow for an append
|
||
//
|
||
Context->CurrentOperation.Position = TAPE_SPACE_END_OF_DATA;
|
||
}
|
||
|
||
leftToRead = bytesToRead;
|
||
|
||
#ifndef NO_MARKS
|
||
while (leftToRead+bytesToSkip > 0) {
|
||
#else
|
||
while (leftToRead > 0) {
|
||
#endif
|
||
|
||
if (Context->CurrentOperation.SegmentBytesRemaining == 0) {
|
||
//
|
||
// get CurrentOperation.SegmentPointer and CurrentOperation.SegmentBytesRemaining for new segment
|
||
//
|
||
if (ret = q117NewTrkRC(Context)) {
|
||
//
|
||
// return error (unless error correction failed)
|
||
//
|
||
if (ERROR_DECODE(ret) != ERR_ECC_FAILED) {
|
||
return(ret);
|
||
}
|
||
}
|
||
//
|
||
// set return value for all accesses to this segment
|
||
// if no error then set to error return by newtrkrc
|
||
//
|
||
if (readret == ERR_NO_ERR) {
|
||
readret = ret;
|
||
}
|
||
}
|
||
|
||
ptr = Context->CurrentOperation.SegmentPointer;
|
||
left = Context->CurrentOperation.SegmentBytesRemaining;
|
||
|
||
#ifndef NO_MARKS
|
||
//
|
||
// set up to skip the file mark
|
||
//
|
||
if ( leftToRead == 0 ) {
|
||
leftToRead = bytesToSkip;
|
||
ToWhere = 0;
|
||
bytesToSkip = 0;
|
||
}
|
||
#endif
|
||
|
||
if ( leftToRead > (ULONG)left ) {
|
||
|
||
if (ToWhere) {
|
||
|
||
RtlMoveMemory(ToWhere,ptr,left);
|
||
(PUCHAR)ToWhere += left;
|
||
|
||
}
|
||
|
||
leftToRead -= left;
|
||
Context->CurrentOperation.BytesOnTape -= left;
|
||
Context->CurrentOperation.BytesRead += left;
|
||
left = 0;
|
||
|
||
} else {
|
||
|
||
if (ToWhere) {
|
||
|
||
RtlMoveMemory(ToWhere,ptr,leftToRead);
|
||
|
||
}
|
||
|
||
left -= (USHORT)leftToRead;
|
||
ptr += leftToRead;
|
||
Context->CurrentOperation.BytesOnTape -= leftToRead;
|
||
Context->CurrentOperation.BytesRead += leftToRead;
|
||
leftToRead = 0;
|
||
|
||
}
|
||
|
||
Context->CurrentOperation.SegmentPointer = ptr;
|
||
Context->CurrentOperation.SegmentBytesRemaining = left;
|
||
|
||
}
|
||
|
||
//
|
||
// Return number of bytes read
|
||
|
||
*HowMany = bytesToRead-leftToRead;
|
||
|
||
return readret;
|
||
}
|