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

543 lines
10 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:
ntopen.c
Abstract:
Performs psuedo open, read, close and open write, close.
Revision History:
--*/
#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 0x0112
dStatus
q117Start (
IN OUT PQ117_CONTEXT Context
)
/*++
Routine Description:
Allocates memory and loads current tape information
Arguments:
Context -
Return Value:
--*/
{
dStatus stat;
IO_REQUEST ioreq;
stat = ERR_NO_ERR;
//
// If we nave not allocated our memory, allocate it and
// initialize it.
//
if (Context->IoRequest == NULL) {
stat = q117GetTemporaryMemory(Context);
if (stat != ERR_NO_ERR)
return stat;
//
// Initialize some globals
//
Context->CurrentOperation.Type = NoOperation;
Context->CurrentTape.State = NeedInfoLoaded;
Context->CurrentOperation.SegmentStatus = ERR_NO_ERR;
q117QueueNormal(Context);
}
if (!Context->DeviceConfigured) {
//
// Find the drive and configure it (done only once)
//
RtlZeroMemory(&ioreq, sizeof(ioreq));
ioreq.x.ioDriveCfgData.device_cfg.speed_change = TRUE;
ioreq.x.ioDriveCfgData.device_cfg.new_drive = TRUE;
ioreq.x.ioDriveCfgData.device_cfg.supported_rates = XFER_500Kbps;
stat = q117DoCmd(&ioreq, CMD_REPORT_DEVICE_CFG, NULL, Context);
if (ERROR_DECODE(stat) == ERR_NEW_TAPE) {
stat = ERR_NO_ERR;
}
if (stat) {
return stat;
}
Context->drive_type = ioreq.x.ioDriveCfgData.device_descriptor.drive_class;
Context->DriveCfg = ioreq.x.ioDriveCfgData;
Context->DeviceConfigured = TRUE;
}
if (!Context->DeviceSelected) {
//
// Select the drive
//
stat = q117DoCmd(&ioreq, CMD_SELECT_DEVICE, NULL, Context);
if (ERROR_DECODE(stat) == ERR_NEW_TAPE) {
stat = ERR_NO_ERR;
}
if (stat == ERR_NO_ERR) {
Context->DeviceSelected = TRUE;
}
}
return stat;
}
dStatus
q117Stop (
IN OUT PQ117_CONTEXT Context
)
/*++
Routine Description:
Shut down the lower level driver (q117i)
Arguments:
Context -
Return Value:
--*/
{
IO_REQUEST ioreq;
dStatus stat;
stat = ERR_NO_ERR;
switch(Context->CurrentOperation.Type) {
case BackupInProgress:
stat = q117EndWriteOperation(Context);
break;
case RestoreInProgress:
stat = q117EndReadOperation(Context);
break;
}
if (!stat && Context->DeviceSelected) {
//
// Deselect the driver
//
stat = q117DoCmd(&ioreq, CMD_DESELECT_DEVICE, NULL, Context);
Context->DeviceSelected = FALSE;
}
if (ERROR_DECODE(stat) == ERR_DEVICE_NOT_SELECTED) {
stat = ERR_NO_ERR;
}
if (!stat && Context->DeviceConfigured) {
//
// Free any memory associated with the tape
//
q117ClearQueue(Context);
q117FreeTemporaryMemory(Context);
}
return stat;
}
dStatus
q117OpenForWrite (
IN OUT PQ117_CONTEXT Context
)
/*++
Routine Description:
Prepare driver for a write operation
Arguments:
Context -
Return Value:
--*/
{
dStatus status;
PCMS_VOLUME_VENDOR *vv_ptr;
ULONG saveSize;
USHORT saveVolNum;
status = ERR_NO_ERR;
switch ( Context->CurrentOperation.Type ) {
case BackupInProgress:
//
// We are set
//
return ERR_NO_ERR;
case RestoreInProgress:
//
// Chop the data off at the current position
//
Context->ActiveVolume.DataSize = Context->CurrentOperation.BytesRead;
Context->CurrentOperation.Position = TAPE_SPACE_END_OF_DATA;
//
// Chop off any marks that we will write over
//
Context->MarkArray.TotalMarks = Context->CurrentMark;
Context->MarkArray.MarkEntry[Context->CurrentMark].Offset = 0xffffffff;
//
// End the read operation
//
status = q117EndReadOperation(Context);
if (status) {
return status;
}
break;
case NoOperation:
break;
}
//
// If we got here, then we need to transition into backup mode.
//
CheckedDump(QIC117INFO,("q117CheckNewTape()..."));
if (status = q117CheckNewTape(Context)) {
CheckedDump(QIC117INFO,("Failed\n"));
return(status);
} else {
CheckedDump(QIC117INFO,("OK\n"));
}
//
// Check to see if tape is correct format
//
/*
status = q117DoCmd(&ioreq, DChkFmt, NULL, Context);
if (status) {
return status;
}
*/
if (!Context->CurrentTape.MediaInfo->WriteProtected) {
if (Context->CurrentOperation.Position == TAPE_SPACE_END_OF_DATA) {
saveSize = Context->ActiveVolume.DataSize;
saveVolNum = Context->ActiveVolumeNumber;
#ifndef NO_MARKS
//
// Use the directorySize field as the start of the volume
//
Context->CurrentOperation.EndOfUsedTape =
(SEGMENT)Context->ActiveVolume.DirectorySize-1;
#else
//
// Set the current end of tape to the start of this volume
// (q117StartAppend will skip to the proper place to start
// backup)
Context->CurrentOperation.EndOfUsedTape =
Context->ActiveVolume.StartSegment-1;
#endif
Context->ActiveVolumeNumber = 0;
} else {
CheckedDump(QIC117INFO,("q117EraseQ()\n"));
if (status = q117EraseQ(Context)) {
CheckedDump(QIC117INFO,("Failed\n"));
return(status);
} else {
CheckedDump(QIC117INFO,("OK\n"));
}
//
// Fill in identification information
//
vv_ptr = &(Context->ActiveVolume.Vendor.cms_QIC40);
RtlMoveMemory((PVOID)(vv_ptr->Signature),"CMS",3);
vv_ptr->SoftwareRevision = 0x300;
vv_ptr->FirmwareRevision = 0 /*cmd_firmwarerev */;
vv_ptr->OpSysType = OP_WINDOWS_NT;
Context->ActiveVolume.VendorSpecific = TRUE;
strcpy(Context->ActiveVolume.Description,"Microsoft Windows NT Format 1.0");
q117SpacePadString(Context->ActiveVolume.Description,sizeof(Context->ActiveVolume.Description));
}
if (Context->CurrentOperation.Position == TAPE_SPACE_END_OF_DATA) {
CheckedDump(QIC117INFO,("q117StartAppend(saveSize, &Context->ActiveVolume)..."));
status = q117StartAppend(saveSize, &Context->ActiveVolume, Context);
//
// Set volume number for q117Update back to saved value
// minus one (q117AppVolTd assumes the volume we are working on
// does not exist yet).
//
Context->ActiveVolumeNumber = saveVolNum-1;
} else {
CheckedDump(QIC117INFO,("q117StartBack(&Context->ActiveVolume)..."));
status = q117StartBack(&Context->ActiveVolume,Context);
}
if (status) {
CheckedDump(QIC117INFO,("Failed\n"));
return(status);
} else {
Context->CurrentOperation.Type = BackupInProgress;
CheckedDump(QIC117INFO,("OK\n"));
}
} else {
status = ERROR_ENCODE(ERR_WRITE_PROTECTED, FCT_ID, 1);
}
return status;
}
dStatus
q117EndWriteOperation (
IN OUT PQ117_CONTEXT Context
)
/*++
Routine Description:
Terminates a write operation and updates the tape header
Arguments:
Context -
Return Value:
--*/
{
dStatus status;
//
// We are at end of tape, because we just finished writing.
// If the user writes again, this data will be appended to.
//
Context->CurrentOperation.Type = NoOperation;
if (Context->CurrentTape.State != NeedInfoLoaded) {
Context->CurrentOperation.Position = TAPE_SPACE_END_OF_DATA;
Context->CurrentOperation.BytesRead = Context->CurrentOperation.BytesOnTape;
status = q117EndBack(Context);
if (!status) {
status = q117Update(Context);
}
} else {
status = ERR_NEW_TAPE;
q117ClearQueue(Context);
}
return status;
}
NTSTATUS
q117OpenForRead (
IN ULONG StartPosition,
IN OUT PQ117_CONTEXT Context,
IN PDEVICE_OBJECT DeviceObject
)
/*++
Routine Description:
Prepare for a read operation.
Arguments:
Context -
Return Value:
--*/
{
NTSTATUS ret;
dStatus stat;
ret = STATUS_SUCCESS;
CheckedDump(QIC117INFO,("q117CheckNewTape()..."));
if (ret = q117CheckNewTape (Context)) {
CheckedDump(QIC117INFO,("Failed\n"));
return q117ConvertStatus(DeviceObject, ret);
} else {
CheckedDump(QIC117INFO,("OK\n"));
}
//
// If CheckNewTape did not find a volume
//
if ( Context->ActiveVolumeNumber == 0 ) {
//
// Insure subsequent reads will return no data
//
Context->CurrentOperation.BytesOnTape = 0;
stat = ERROR_ENCODE(ERR_NO_VOLUMES, FCT_ID, 1);
return q117ConvertStatus(DeviceObject, stat);
}
#ifndef NO_MARKS
Context->CurrentMark = 0;
#endif
if ( ret = q117SelectVol(&Context->ActiveVolume,Context) ) {
return q117ConvertStatus(DeviceObject, ret);
}
Context->CurrentOperation.Type = RestoreInProgress;
if (StartPosition) {
CheckedDump(QIC117SHOWAPI,(
"ReadRestore: StartBlock(%d)\n",
StartPosition));
// BOBRI, this is the logical block from one line
// you need to remove -1 if you want it to start from zero
ret = q117SeekToOffset(StartPosition, Context, DeviceObject);
}
return ret;
}
dStatus
q117EndReadOperation (
IN OUT PQ117_CONTEXT Context
)
/*++
Routine Description:
Prepare for a read operation.
Arguments:
Context -
Return Value:
--*/
{
dStatus status;
Context->CurrentOperation.Type = NoOperation;
if (Context->CurrentTape.State != NeedInfoLoaded) {
status = q117EndRest(Context);
} else {
status = ERR_NEW_TAPE;
q117ClearQueue(Context);
}
return status;
}