Source code of Windows XP (NT5)
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.
|
|
/*++
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()
|