You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
287 lines
8.5 KiB
287 lines
8.5 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1992 - 1998
|
|
|
|
Module Name:
|
|
|
|
physlogi.c
|
|
|
|
Abstract:
|
|
|
|
This module contains functions used specifically by tape drivers.
|
|
It contains functions that do physical to pseudo-logical and pseudo-
|
|
logical to physical tape block address/position translation.
|
|
|
|
Environment:
|
|
|
|
kernel mode only
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "ntddk.h"
|
|
#include "physlogi.h"
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE, TapeClassPhysicalBlockToLogicalBlock)
|
|
#pragma alloc_text(PAGE, TapeClassLogicalBlockToPhysicalBlock)
|
|
#endif
|
|
|
|
//
|
|
// defines for various QIC physical tape format constants
|
|
//
|
|
|
|
#define QIC_150_BOT_OFFSET 2
|
|
#define QIC_525_PSEUDO_PHYSICAL_BLOCK_SIZE 512
|
|
#define QIC_525_PHYSICAL_BLOCK_SIZE 1024
|
|
#define QIC_525_DATA_BLKS_PER_FRAME 14
|
|
#define QIC_525_ECC_BLKS_PER_FRAME 2
|
|
#define QIC_525_BLKS_PER_FRAME 16
|
|
#define QIC_525_BOT_OFFSET 16
|
|
#define QIC_1350_PHYSICAL_BLOCK_SIZE 512
|
|
#define QIC_1350_DATA_BLKS_PER_FRAME 52
|
|
#define QIC_1350_ECC_BLKS_PER_FRAME 12
|
|
#define QIC_1350_BLKS_PER_FRAME 64
|
|
#define QIC_1350_BOT_OFFSET 64
|
|
|
|
|
|
ULONG
|
|
TapeClassPhysicalBlockToLogicalBlock(
|
|
IN UCHAR DensityCode,
|
|
IN ULONG PhysicalBlockAddress,
|
|
IN ULONG BlockLength,
|
|
IN BOOLEAN FromBOT
|
|
)
|
|
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine will translate from a QIC physical tape format
|
|
specific physical/absolute block address to a pseudo-logical
|
|
block address.
|
|
|
|
Arguments:
|
|
|
|
DensityCode // tape media density code
|
|
PhysicalBlockAddress // tape format specific tape block address
|
|
BlockLength // mode select/sense block length setting
|
|
FromBOT // true/false - translate from BOT
|
|
|
|
Return Value:
|
|
|
|
ULONG
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG logicalBlockAddress;
|
|
ULONG frames;
|
|
|
|
PAGED_CODE();
|
|
|
|
logicalBlockAddress = PhysicalBlockAddress;
|
|
|
|
switch ( DensityCode ) {
|
|
case 0:
|
|
logicalBlockAddress = 0xFFFFFFFF;
|
|
break;
|
|
|
|
case QIC_24:
|
|
logicalBlockAddress--;
|
|
break;
|
|
|
|
case QIC_120:
|
|
logicalBlockAddress--;
|
|
break;
|
|
|
|
case QIC_150:
|
|
if (FromBOT) {
|
|
if (logicalBlockAddress > QIC_150_BOT_OFFSET) {
|
|
logicalBlockAddress -= QIC_150_BOT_OFFSET;
|
|
} else {
|
|
logicalBlockAddress = 0;
|
|
}
|
|
} else {
|
|
logicalBlockAddress--;
|
|
}
|
|
break;
|
|
|
|
case QIC_525:
|
|
case QIC_1000:
|
|
case QIC_2GB:
|
|
if (FromBOT && (logicalBlockAddress >= QIC_525_BOT_OFFSET)) {
|
|
logicalBlockAddress -= QIC_525_BOT_OFFSET;
|
|
}
|
|
if (logicalBlockAddress != 0) {
|
|
frames = logicalBlockAddress/QIC_525_BLKS_PER_FRAME;
|
|
logicalBlockAddress -= QIC_525_ECC_BLKS_PER_FRAME*frames;
|
|
switch (BlockLength) {
|
|
case QIC_525_PHYSICAL_BLOCK_SIZE:
|
|
break;
|
|
|
|
case QIC_525_PSEUDO_PHYSICAL_BLOCK_SIZE:
|
|
logicalBlockAddress *= 2;
|
|
break;
|
|
|
|
default:
|
|
if (BlockLength > QIC_525_PHYSICAL_BLOCK_SIZE) {
|
|
if ((BlockLength%QIC_525_PHYSICAL_BLOCK_SIZE) == 0) {
|
|
logicalBlockAddress /=
|
|
BlockLength/QIC_525_PHYSICAL_BLOCK_SIZE;
|
|
} else {
|
|
logicalBlockAddress /=
|
|
1+(BlockLength/QIC_525_PHYSICAL_BLOCK_SIZE);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case QIC_1350:
|
|
case QIC_2100:
|
|
if (FromBOT && (logicalBlockAddress >= QIC_1350_BOT_OFFSET)) {
|
|
logicalBlockAddress -= QIC_1350_BOT_OFFSET;
|
|
}
|
|
if (logicalBlockAddress != 0) {
|
|
frames = logicalBlockAddress/QIC_1350_BLKS_PER_FRAME;
|
|
logicalBlockAddress -= QIC_1350_ECC_BLKS_PER_FRAME*frames;
|
|
if (BlockLength > QIC_1350_PHYSICAL_BLOCK_SIZE) {
|
|
if ((BlockLength%QIC_1350_PHYSICAL_BLOCK_SIZE) == 0) {
|
|
logicalBlockAddress /=
|
|
BlockLength/QIC_1350_PHYSICAL_BLOCK_SIZE;
|
|
} else {
|
|
logicalBlockAddress /=
|
|
1+(BlockLength/QIC_1350_PHYSICAL_BLOCK_SIZE);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return logicalBlockAddress;
|
|
|
|
} // end TapeClassPhysicalBlockToLogicalBlock()
|
|
|
|
|
|
TAPE_PHYS_POSITION
|
|
TapeClassLogicalBlockToPhysicalBlock(
|
|
IN UCHAR DensityCode,
|
|
IN ULONG LogicalBlockAddress,
|
|
IN ULONG BlockLength,
|
|
IN BOOLEAN FromBOT
|
|
)
|
|
|
|
/*++
|
|
Routine Description:
|
|
|
|
This routine will translate from a pseudo-logical block address
|
|
to a QIC physical tape format specific physical/absolute block
|
|
address and (space) block delta.
|
|
|
|
Arguments:
|
|
|
|
DensityCode // tape media density code
|
|
LogicalBlockAddress // pseudo-logical tape block address
|
|
BlockLength // mode select/sense block length setting
|
|
FromBOT // true/false - translate from BOT
|
|
|
|
Return Value:
|
|
|
|
TAPE_PHYS_POSITION info/structure
|
|
|
|
--*/
|
|
|
|
{
|
|
TAPE_PHYS_POSITION physPosition;
|
|
ULONG physicalBlockAddress;
|
|
ULONG remainder = 0;
|
|
ULONG frames;
|
|
|
|
PAGED_CODE();
|
|
|
|
physicalBlockAddress = LogicalBlockAddress;
|
|
|
|
switch ( DensityCode ) {
|
|
case 0:
|
|
physicalBlockAddress = 0xFFFFFFFF;
|
|
break;
|
|
|
|
case QIC_24:
|
|
physicalBlockAddress++;
|
|
break;
|
|
|
|
case QIC_120:
|
|
physicalBlockAddress++;
|
|
break;
|
|
|
|
case QIC_150:
|
|
if (FromBOT) {
|
|
physicalBlockAddress += QIC_150_BOT_OFFSET;
|
|
} else {
|
|
physicalBlockAddress++;
|
|
}
|
|
break;
|
|
|
|
case QIC_525:
|
|
case QIC_1000:
|
|
case QIC_2GB:
|
|
if (physicalBlockAddress != 0) {
|
|
switch (BlockLength) {
|
|
case QIC_525_PHYSICAL_BLOCK_SIZE:
|
|
break;
|
|
|
|
case QIC_525_PSEUDO_PHYSICAL_BLOCK_SIZE:
|
|
remainder = physicalBlockAddress & 0x00000001;
|
|
physicalBlockAddress >>= 1;
|
|
break;
|
|
|
|
default:
|
|
if (BlockLength > QIC_525_PHYSICAL_BLOCK_SIZE) {
|
|
if ((BlockLength%QIC_525_PHYSICAL_BLOCK_SIZE) == 0) {
|
|
physicalBlockAddress *=
|
|
BlockLength/QIC_525_PHYSICAL_BLOCK_SIZE;
|
|
} else {
|
|
physicalBlockAddress *=
|
|
1+(BlockLength/QIC_525_PHYSICAL_BLOCK_SIZE);
|
|
}
|
|
}
|
|
break;
|
|
|
|
}
|
|
frames = physicalBlockAddress/QIC_525_DATA_BLKS_PER_FRAME;
|
|
physicalBlockAddress += QIC_525_ECC_BLKS_PER_FRAME*frames;
|
|
}
|
|
if (FromBOT) {
|
|
physicalBlockAddress += QIC_525_BOT_OFFSET;
|
|
}
|
|
break;
|
|
|
|
case QIC_1350:
|
|
case QIC_2100:
|
|
if (physicalBlockAddress != 0) {
|
|
if (BlockLength > QIC_1350_PHYSICAL_BLOCK_SIZE) {
|
|
if ((BlockLength%QIC_1350_PHYSICAL_BLOCK_SIZE) == 0) {
|
|
physicalBlockAddress *=
|
|
BlockLength/QIC_1350_PHYSICAL_BLOCK_SIZE;
|
|
} else {
|
|
physicalBlockAddress *=
|
|
1+(BlockLength/QIC_1350_PHYSICAL_BLOCK_SIZE);
|
|
}
|
|
}
|
|
frames = physicalBlockAddress/QIC_1350_DATA_BLKS_PER_FRAME;
|
|
physicalBlockAddress += QIC_1350_ECC_BLKS_PER_FRAME*frames;
|
|
}
|
|
if (FromBOT) {
|
|
physicalBlockAddress += QIC_1350_BOT_OFFSET;
|
|
}
|
|
break;
|
|
}
|
|
|
|
physPosition.SeekBlockAddress = physicalBlockAddress;
|
|
physPosition.SpaceBlockCount = remainder;
|
|
|
|
return physPosition;
|
|
|
|
} // end TapeClassLogicalBlockToPhysicalBlock()
|