windows-nt/Source/XPSP1/NT/drivers/storage/tffsport/docsysp.c
2020-09-26 16:20:57 +08:00

491 lines
16 KiB
C

/*****************************************************************************
* *
* FAT-FTL Lite Software Development Kit *
* Copyright (C) M-Systems Ltd. 1995-2001 *
* *
*****************************************************************************
* *
* In order to make your code faster: *
* *
* 1. Get rid of routines flRead8bitRegPlus()/flPreInitRead8bitReg()Plus, *
* and make M+ MTD calling routine mplusReadReg8() directly. *
* *
* 2. Get rid of routines flWrite8bitRegPlus()/flPreInitWrite8bitReg()Plus, *
* and make M+ MTD calling routine mplusWriteReg8() directly. *
* *
* 3. Eliminate overhead of calling routines tffscpy/tffsset() by *
* adding these routines' code into docPlusRead/docPlusWrite/docPlusSet *
* routines. *
* *
*****************************************************************************/
/*
* $Log: V:/Flite/archives/TrueFFS5/Src/docsysp.c_V $
*
* Rev 1.4 Nov 18 2001 20:26:50 oris
* Bug fix- Bad implementation of 8-bit access when ENVIRNOMENT_VARS is not defined.
*
* Rev 1.3 Nov 16 2001 00:26:54 oris
* When ENVIRONMENT_VARS is not defined use for loop of bytes instead of tffscpy.
*
* Rev 1.2 Sep 25 2001 15:39:38 oris
* Bug fix - Add special support for flUse8Bit environement variable.
*
* Rev 1.1 Sep 24 2001 18:23:32 oris
* Completely revised to support runtime true 16-bit access.
*/
/*
* configuration
*/
/* #define FL_INIT_MMU_PAGES */
/*
* includes
*/
#include "docsysp.h"
/*
* macros
*/
/* types of access to M+: 8 or 16-bit */
#define FL_MPLUS_ACCESS_8BIT 0x10
#define FL_MPLUS_ACCESS_16BIT 0x20
#define FL_MPLUS_ACCESS_MASK 0xf0 /* mask for the above */
/* in case of 16-bit access to M+ */
#define FL_MPLUS_ACCESS_BE 0x100
/*
* routines
*/
#ifdef FL_INIT_MMU_PAGES
static void flInitMMUpages (byte FAR1 *buf, int bufsize);
#endif
/*
* vars
*/
/* run-time configuration of DiskOnChip access */
int flMplusAccessType = FL_MPLUS_ACCESS_8BIT;
/* FL_MPLUS_ACCESS_8BIT
FL_MPLUS_ACCESS_16BIT
FL_MPLUS_ACCESS_BE */
/* ---------------------------------------------------------------------- *
* *
* m p l u s R e a d R e g 8 *
* *
* Read single byte from memory mapped 8-bit M+ register. *
* *
* ---------------------------------------------------------------------- */
unsigned char mplusReadReg8 ( void FAR0 * win, int offset )
{
if( flMplusAccessType & FL_MPLUS_ACCESS_16BIT ) {
/* can't read byte, only short word */
unsigned short sval;
sval = *((volatile unsigned short FAR0 *)win + (offset >> 1));
return *(((unsigned char *) &sval) + (offset & 0x1));
}
/* FL_MPLUS_ACCESS_8BIT case */
return *((volatile unsigned char FAR0 *)win + offset);
}
/* ---------------------------------------------------------------------- *
* *
* m p l u s W r i t e R e g 8 *
* *
* Write single byte to memory mapped 8-bit M+ register. *
* *
* ---------------------------------------------------------------------- */
void mplusWriteReg8 ( void FAR0 * win, int offset, unsigned char val )
{
switch( flMplusAccessType & FL_MPLUS_ACCESS_MASK ) {
case FL_MPLUS_ACCESS_16BIT:
*((volatile unsigned short FAR0 *)win + (offset >> 1)) =
(unsigned short)(val * 0x0101);
break;
default: /* FL_MPLUS_ACCESS_8BIT */
*((volatile unsigned char FAR0 *)win + offset) = val;
break;
}
}
/* ---------------------------------------------------------------------- *
* *
* f l R e a d 1 6 b i t R e g P l u s *
* *
* Read single word from memory mapped 16-bit M+ register. *
* *
* ---------------------------------------------------------------------- */
Reg16bitType flRead16bitRegPlus ( FLFlash vol, unsigned offset )
{
return (Reg16bitType)
(*((volatile unsigned short FAR0 *)((char FAR0 *)NFDC21thisVars->win + (int)offset)));
}
/* ---------------------------------------------------------------------- *
* *
* f l W r i t e 1 6 b i t R e g P l u s *
* *
* Write single word to memory mapped 16-bit M+ register. *
* *
* ---------------------------------------------------------------------- */
void flWrite16bitRegPlus ( FLFlash vol, unsigned offset, Reg16bitType val )
{
*((volatile unsigned short FAR0 *)((char FAR0 *)NFDC21thisVars->win + (int)offset)) =
(unsigned short) val;
}
/* ---------------------------------------------------------------------- *
* *
* d o c P l u s R e a d *
* *
* This routine is called from M+ MTD to read data block from M+. *
* *
* ---------------------------------------------------------------------- */
void docPlusRead ( FLFlash vol, unsigned offset, void FAR1 * dest, unsigned int count )
{
volatile unsigned short FAR0 * swin;
register int i;
register unsigned short tmp;
if (count == 0)
return;
#ifdef FL_INIT_MMU_PAGES
flInitMMUpages( (byte FAR1 *)dest, (int)count );
#endif
if ((vol.interleaving == 1) && (NFDC21thisVars->if_cfg == 16)) {
/* rare case: 16-bit hardware interface AND interleave == 1 */
for (i = 0; i < (int)count; i++) {
*((unsigned char FAR1 *)dest + i) =
mplusReadReg8 ((void FAR0 *)NFDC21thisVars->win, ((int)offset));
}
}
else {
switch( flMplusAccessType & FL_MPLUS_ACCESS_MASK ) {
case FL_MPLUS_ACCESS_16BIT:
swin = (volatile unsigned short FAR0 *)NFDC21thisVars->win + ((int)offset >> 1);
if( pointerToPhysical(dest) & 0x1 ) {
/* rare case: unaligned target buffer */
if( flMplusAccessType & FL_MPLUS_ACCESS_BE ) { /* big endian */
for (i = 0; i < (int)count; ) {
tmp = *(swin + (i >> 1));
*((unsigned char FAR1 *)dest + (i++)) = (unsigned char) (tmp >> 8);
*((unsigned char FAR1 *)dest + (i++)) = (unsigned char) tmp;
}
}
else { /* little endian */
for (i = 0; i < (int)count; ) {
tmp = *(swin + (i >> 1));
*((unsigned char FAR1 *)dest + (i++)) = (unsigned char) tmp;
*((unsigned char FAR1 *)dest + (i++)) = (unsigned char) (tmp >> 8);
}
}
}
else { /* mainstream case */
#ifdef ENVIRONMENT_VARS
if (flUse8Bit == 0) {
tffscpy( dest, (void FAR0 *)((NDOC2window)NFDC21thisWin + offset), count );
}
else
#endif /* ENVIRONMENT_VARS */
{ /* read in short words */ /* andrayk: do we need this ? */
for (i = 0; i < ((int)count >> 1); i++)
*((unsigned short FAR1 *)dest + i) = *(swin + i);
}
}
break;
default: /* FL_MPLUS_ACCESS_8BIT */
#ifdef ENVIRONMENT_VARS
tffscpy( dest, (void FAR0 *)((NDOC2window)NFDC21thisWin + offset), count );
#else
for (i = 0; i < (int)count; i++)
((byte FAR1 *)dest)[i] = *((NDOC2window)NFDC21thisWin + offset);
#endif /* ENVIRONMENT_VARS */
break;
}
}
}
/* ---------------------------------------------------------------------- *
* *
* d o c P l u s W r i t e *
* *
* This routine is called from M+ MTD to write data block to M+. *
* *
* ---------------------------------------------------------------------- */
void docPlusWrite ( FLFlash vol, void FAR1 * src, unsigned int count )
{
volatile unsigned short FAR0 * swin;
register int i;
register unsigned short tmp;
if (count == 0)
return;
if ((vol.interleaving == 1) && (NFDC21thisVars->if_cfg == 16)) {
/* rare case: 16-bit hardware interface AND interleave == 1 */
for (i = 0; i < (int)count; i++) {
mplusWriteReg8( (void FAR0 *)NFDC21thisVars->win, ((int)NFDC21thisIO),
*((unsigned char FAR1 *)src + i) );
}
}
else {
switch( flMplusAccessType & FL_MPLUS_ACCESS_MASK ) {
case FL_MPLUS_ACCESS_16BIT:
swin = (volatile unsigned short FAR0 *)NFDC21thisVars->win + ((int)NFDC21thisIO >> 1);
if( pointerToPhysical(src) & 0x1 ) {
/* rare case: unaligned source buffer */
if( flMplusAccessType & FL_MPLUS_ACCESS_BE ) { /* big endian */
for (i = 0; i < (int)count; ) {
tmp = ((unsigned short) (*((unsigned char FAR1 *)src + (i++)))) << 8;
tmp |= (*((unsigned char FAR1 *)src + (i++)));
*(swin + (i >> 1)) = tmp;
}
}
else {
for (i = 0; i < (int)count; ) { /* little endian */
tmp = (*((unsigned char FAR1 *)src + (i++)));
tmp |= ((unsigned short) (*((unsigned char FAR1 *)src + (i++)))) << 8;
*(swin + (i >> 1)) = tmp;
}
}
}
else { /* mainstream case */
#ifdef ENVIRONMENT_VARS
if (flUse8Bit == 0) {
tffscpy( (void FAR0 *)((NDOC2window)NFDC21thisWin + NFDC21thisIO), src, count );
}
else
#endif /* ENVIRONMENT_VARS */
{ /* write in short words */ /* andrayk: do we need this ? */
for (i = 0; i < ((int)count >> 1); i++)
*(swin + i) = *((unsigned short FAR1 *)src + i);
}
}
break;
default: /* FL_MPLUS_ACCESS_8BIT */
#ifdef ENVIRONMENT_VARS
tffscpy( (void FAR0 *)((NDOC2window)NFDC21thisWin + NFDC21thisIO), src, count );
#else
for (i = 0; i < (int)count; i++)
*((NDOC2window)NFDC21thisWin + NFDC21thisIO) =
((byte FAR1 *)src)[i];
#endif /* ENVIRONMENT_VARS */
break;
}
}
}
/* ---------------------------------------------------------------------- *
* *
* d o c P l u s S e t *
* *
* This routine is called from M+ MTD to set data block on M+ to 'val'. *
* *
* ---------------------------------------------------------------------- */
void docPlusSet ( FLFlash vol, unsigned int count, unsigned char val )
{
volatile unsigned short FAR0 * swin;
register int i;
register unsigned short sval;
if (count == 0)
return;
if ((vol.interleaving == 1) && (NFDC21thisVars->if_cfg == 16)) {
/* rare case: 16-bit hardware interface AND interleave == 1 */
for (i = 0; i < (int)count; i++)
mplusWriteReg8( (void FAR0 *)NFDC21thisVars->win, (int)NFDC21thisIO, val );
}
else { /* mainstream case */
switch( flMplusAccessType & FL_MPLUS_ACCESS_MASK ) {
case FL_MPLUS_ACCESS_16BIT:
#ifdef ENVIRONMENT_VARS
if (flUse8Bit == 0) {
tffsset( (void FAR0 *)((NDOC2window)NFDC21thisWin + NFDC21thisIO), val, count );
}
else
#endif /* ENVIRONMENT_VARS */
{ /* do short word access */ /* andrayk: do we need this ? */
swin = (volatile unsigned short FAR0 *)NFDC21thisVars->win +
((int)NFDC21thisIO >> 1);
sval = ((unsigned short)val << 8) | val;
for (i = 0; i < ((int)count >> 1); i++)
*(swin + i) = sval;
}
break;
default: /* FL_MPLUS_ACCESS_8BIT */
#ifdef ENVIRONMENT_VARS
tffsset( (void FAR0 *)((NDOC2window)NFDC21thisWin + NFDC21thisIO), val, count );
#else
for (i = 0; i < (int)count; i++)
*((NDOC2window)NFDC21thisWin + NFDC21thisIO) = val;
#endif /* ENVIRONMENT_VARS */
break;
}
}
}
/* ---------------------------------------------------------------------- *
* *
* m p l u s W i n S i z e *
* *
* This routine is called from M+ MTD to find out size of M+ window in *
* bytes. *
* *
* ---------------------------------------------------------------------- */
unsigned long mplusWinSize ( void )
{
return 0x2000L;
}
#ifdef FL_INIT_MMU_PAGES
/* ---------------------------------------------------------------------- *
* *
* f l I n i t M M U p a g e s *
* *
* Initializes the first and last byte of the given buffer. *
* When the user buffer resides on separated memory pages the read *
* operation may cause a page fault. Some CPU's return from a page *
* fault (after loading the new page) and reread the bytes that caused *
* the page fault from the new loaded page. In order to prevent such a *
* case the first and last bytes of the buffer are written *
* *
* ---------------------------------------------------------------------- */
static void flInitMMUpages ( byte FAR1 *buf, int bufsize )
{
*buf = (byte)0;
*( addToFarPointer(buf, (bufsize - 1)) ) = (byte)0;
}
#endif /* FL_INIT_MMU_PAGES */