📄 tffs2lnx.c
字号:
#include "flcustom.h"#include "tffsdrv.h"#include "flstatus.h"#include "flreq.h"#include "flsocket.h"#include "flsystem.h"#include "fatfilt.h"#include "flioctl.h"#include "blockdev.h"#include "tffs2lnx.h"#include <linux/slab.h>#include <asm/uaccess.h> /* ok_access */#include <linux/vmalloc.h> /* vmalloc, vfree */static TheDiskInfo*pTheDiskInfo;#if (TFFS_SVER>=60000)# define TFFS_LAST_IOCTL FL_IOCTL_COMPLETE_OPERATION#elif (TFFS_SVER>=50000)# define TFFS_LAST_IOCTL FL_IOCTL_EXTENDED_WRITE_IPL#else# define TFFS_LAST_IOCTL 0#endif#ifdef DRIVER_STATISTICunsigned long dwReadCount=0;unsigned long dwWriteCount=0;#endif /* DRIVER_STATISTIC */#ifdef TFFS_POWER_DOWNstatic void TffsPowerDown(SocketInfo*pSocket){ if(pSocket->fPowerOn) { IOreq ioreq; ioreq.irHandle=pSocket->handle; ioreq.irFlags=DEEP_POWER_DOWN; flDeepPowerDownMode(&ioreq); pSocket->fPowerOn=0; }}#else /* TFFS_POWER_DOWN */# define TffsPowerDown(b)#endif /* TFFS_POWER_DOWN */#if defined(TFFS_POWER_DOWN) && (TFFS_SVER>=60000)static void TffsPowerUp(SocketInfo*pSocket){ if(!pSocket->fPowerOn) { IOreq ioreq; ioreq.irHandle=pSocket->handle; ioreq.irFlags=EXIT_DEEP_POWER_DOWN; flDeepPowerDownMode(&ioreq); pSocket->fPowerOn=1; }}#else /* defined(TFFS_POWER_DOWN) && (TFFS_SVER>=60000) */# define TffsPowerUp(b)#endif /* defined(TFFS_POWER_DOWN) && (TFFS_SVER>=60000) */#ifdef HW_PROTECTIONBOOL TffsIsWriteProtected(DeviceInfo*pDevice){ IOreq ioreq; FLStatus stat; ioreq.irHandle=pDevice->handle; stat=flIdentifyProtection(&ioreq); if(stat==flOK) { if(ioreq.irFlags&WRITE_PROTECTED && !(ioreq.irFlags&KEY_INSERTED) ) return TRUE; } else { if(stat!=flFeatureNotSupported && stat!=flNotProtected) { LnxErrorPrint("TffsIsWriteProtected->flIdentifyProtection",stat); } } return FALSE;}#endif /* HW_PROTECTION *//* Initialize TrueFFS. */void TffsInit(TheDiskInfo*pDiskInfo){ extern unsigned char noOfSockets; extern unsigned int noOfDrives; unsigned char bDevice,bSocket;#ifdef TFFS_KEY_FROM_PARAMS#ifdef HW_PROTECTION unsigned char bProtectedDevice; char*pKey;#endif /* HW_PROTECTION */#endif FLStatus stat; IOreq ioreq;#ifndef TFFS_ALLOW_UNFORMATTED BOOL fValidDeviceFound=FALSE;#endif pDiskInfo->pDevices=NULL; pDiskInfo->pSockets=NULL; pDiskInfo->noOfDevices=0; pDiskInfo->noOfSockets=0; pTheDiskInfo=pDiskInfo; /* HW init */ if(!TffsHWInit()) { LnxErrorPrint("TffsInit->TffsHWInit",0); return; } /* TFFS init */ if((stat=flInit())!=flOK) { LnxErrorPrint("TffsInit->flInit",stat); return; } if(!noOfDrives) { PrintkDebug("TffsInit: no devices found"); return; } pDiskInfo->pDevices=kmalloc(sizeof(DeviceInfo)*noOfDrives,GFP_KERNEL);if(pDiskInfo->pDevices==NULL)return; if(pDiskInfo->pDevices==NULL) return; memset(pDiskInfo->pDevices,0,sizeof(DeviceInfo)*noOfDrives); pDiskInfo->pSockets=kmalloc(sizeof(SocketInfo)*noOfSockets,GFP_KERNEL);if(pDiskInfo->pSockets==NULL)return; if(pDiskInfo->pSockets==NULL) return; memset(pDiskInfo->pSockets,0,sizeof(SocketInfo)*noOfSockets); pDiskInfo->noOfDevices=noOfDrives; pDiskInfo->noOfSockets=noOfSockets;#ifdef TFFS_KEY_FROM_PARAMS#ifdef HW_PROTECTION LnxGetKeyFromParam(&bProtectedDevice,&pKey);#endif /* HW_PROTECTION */#endif for(bSocket=0,bDevice=0;bSocket<noOfSockets;bSocket++) { unsigned char bNDevicesOnSocket=0,bDeviceOnSocket; FLFlash*flash; SocketInfo*pSocket=pDiskInfo->pSockets+bSocket; flash=flFlashOf(bSocket);#ifdef TFFS_ALLOW_UNFORMATTED pSocket->fDummy=TRUE;#endif#if (TFFS_SVER>=60000) PrintkInfo("Socket %u: type %u 0x%x chips %u floors %u size %luM", bSocket,flash->mediaType,flash->type,flash->noOfChips,flash->noOfFloors, flash->mediaSize>>20);#else PrintkInfo("Socket %u: type %u 0x%x chips %u floors %u size %luM", bSocket,flash->mediaType,flash->type,flash->noOfChips,flash->noOfFloors, (flash->chipSize>>20)*flash->noOfChips);#endif#ifdef TFFS_POWER_DOWN pSocket->fPowerOn=1;#endif pSocket->handle=bSocket; ioreq.irHandle=bSocket; stat=flCountVolumes(&ioreq); if(stat==flOK) { bNDevicesOnSocket=ioreq.irFlags; } else { LnxErrorPrint("TffsInit->flCountVolumes",stat); } for(bDeviceOnSocket=0;bDeviceOnSocket<bNDevicesOnSocket;bDeviceOnSocket++,bDevice++) { DeviceInfo*pDevice=pDiskInfo->pDevices+bDevice;#if (TFFS_SVER>60000) if(flash->sharedSectors>4) pDevice->sectorSize=4; else pDevice->sectorSize=flash->sharedSectors; #else pDevice->sectorSize=1;#endif PrintkDebug("TffsGetSectorSize: flash->sharedSectors %d",pDevice->sectorSize); pDevice->sectorSize<<=9; if(pSocket->maxSectorSize<pDevice->sectorSize) pSocket->maxSectorSize=pDevice->sectorSize; pDevice->pSocket=pSocket; pDevice->size=0; pDevice->handle=bSocket|(bDeviceOnSocket<<4); pDevice->fValid=FALSE; ioreq.irHandle=pDevice->handle;#ifdef TFFS_KEY_FROM_PARAMS#ifdef HW_PROTECTION if(bDevice==bProtectedDevice && pKey!=NULL) { ioreq.irData=pKey; stat=flInsertProtectionKey(&ioreq); if(stat!=flOK) { LnxErrorPrint("TffsInit->flInsertProtectionKey",stat); } }#endif /* HW_PROTECTION */#endif /* try to mount device */ if(TffsOpen(pDevice)) { if((stat=flSectorsInVolume(&ioreq))!=flOK) { LnxErrorPrint("TffsInit->flSectorsInVolume",stat); } else { pDevice->size=ioreq.irLength; pDevice->size<<=9; pDevice->fValid=TRUE;#ifdef TFFS_ALLOW_UNFORMATTED pSocket->fDummy=FALSE;#else fValidDeviceFound=TRUE;#endif } } } TffsPowerDown(pSocket); }#ifndef TFFS_ALLOW_UNFORMATTED if(!fValidDeviceFound) pDiskInfo->noOfDevices=0; else#endif PrintkDebug("TffsInit OK");}void TffsCleanup(TheDiskInfo*pDiskInfo){ unsigned char bDevice; PrintkDebug("TffsCleanup"); /* unmount all devices */ for(bDevice=0;bDevice<pDiskInfo->noOfDevices;bDevice++) { TffsRelease(pDiskInfo->pDevices+bDevice); }#ifdef EXIT flExit();#endif /* EXIT */ if(pDiskInfo->pDevices!=NULL) { kfree(pDiskInfo->pDevices); pDiskInfo->pDevices=NULL; } if(pDiskInfo->pSockets!=NULL) { kfree(pDiskInfo->pSockets); pDiskInfo->pSockets=NULL; } pDiskInfo->noOfDevices=0; pDiskInfo->noOfSockets=0; PrintkDebug("TffsCleanup OK");}BOOL TffsOpen(DeviceInfo*pDevice){ PrintkDebug("TffsOpen"); if( (pDevice-pTheDiskInfo->pDevices) >= pTheDiskInfo->noOfDevices) { PrintkDebug("TffsOpen: device out of range"); return FALSE; } if(!pDevice->fValid) { IOreq ioreq; ioreq.irHandle=pDevice->handle; if((pDevice->lastTffsError=flAbsMountVolume(&ioreq))==flOK) pDevice->fValid=TRUE; else { LnxErrorPrint("TffsOpen->flAbsMountVolume",pDevice->lastTffsError); pDevice->fValid=FALSE; } } return pDevice->fValid;}BOOL TffsRelease(DeviceInfo*pDevice){ PrintkDebug("TffsRelease"); if(pDevice-pTheDiskInfo->pDevices >= pTheDiskInfo->noOfDevices) { PrintkDebug("TffsRelease: device out of range"); return FALSE; } if(pDevice->fValid) { IOreq ioreq; pDevice->fValid=0; ioreq.irHandle=pDevice->handle; if((pDevice->lastTffsError=flAbsMountVolume(&ioreq))!=flOK) { LnxErrorPrint("TffsRead->TffsRelease",pDevice->lastTffsError); return FALSE; } } return TRUE;}/* Perform read or write of appropriate number of sectors from a DOC volume */BOOL TffsRead(DeviceInfo*pDevice,void*data,int block,int count){ IOreq ioreq; if(pDevice-pTheDiskInfo->pDevices >= pTheDiskInfo->noOfDevices) { PrintkDebug("TffsRead: device out of range"); return FALSE; } if(!pDevice->fValid) if(!TffsOpen(pDevice)) return FALSE;/* PrintkDebug("TffsRead: device 0x%x, sector 0x%x, %d sectors",pDevice->handle,block,count); */#ifdef DRIVER_STATISTIC dwReadCount+=count;#endif /* DRIVER_STATISTIC */ ioreq.irHandle=pDevice->handle; ioreq.irData=data; ioreq.irSectorNo=block; ioreq.irSectorCount=count; TffsPowerUp(pDevice->pSocket); pDevice->lastTffsError=flAbsRead(&ioreq); TffsPowerDown(pDevice->pSocket); if(pDevice->lastTffsError==flOK) return TRUE; else { LnxErrorPrint("TffsRead->flAbsRead",pDevice->lastTffsError); return FALSE; }}/* Perform read or write of appropriate number of sectors from a DOC volume */unsigned char TffsWrite(DeviceInfo*pDevice,void*data,int block,int count){ IOreq ioreq; if(pDevice-pTheDiskInfo->pDevices >= pTheDiskInfo->noOfDevices) { PrintkDebug("TffsWrite: device out of range"); return FALSE; } if(!pDevice->fValid) if(!TffsOpen(pDevice)) return FALSE;#ifdef DRIVER_STATISTIC dwWriteCount+=count;#endif /* DRIVER_STATISTIC *//* PrintkDebug("TffsWrite: device 0x%x, sector 0x%x, %d sectors",pDevice->handle,block,count); */ ioreq.irHandle=pDevice->handle; ioreq.irData=data; ioreq.irSectorNo=block; ioreq.irSectorCount=count; TffsPowerUp(pDevice->pSocket);#ifdef FL_FAT_FILTER ffCheckBeforeWrite(&ioreq);#endif /* FL_FAT_FILTER */ pDevice->lastTffsError=flAbsWrite(&ioreq); TffsPowerDown(pDevice->pSocket); if(pDevice->lastTffsError==flOK) return TRUE; else { LnxErrorPrint("TffsWrite->flAbsWrite",pDevice->lastTffsError); return FALSE; }}#ifdef IOCTL_INTERFACE#define USR2KRN_IOCTL(theHandle) ioreq.irHandle = theHandle;TffsPowerUp(pDevice->pSocket);flIOctl(&ioreq);TffsPowerDown(pDevice->pSocket);#define USR2KRN_IO_START(typeIn,typeOut) {typeIn input;typeOut output;void*tmp;if(!access_ok(VERIFY_READ,ioctlRecord.inputRecord,sizeof(typeIn))) return -EFAULT;if(copy_from_user(&input,ioctlRecord.inputRecord,sizeof(typeIn)))return -EFAULT;if(!access_ok(VERIFY_WRITE,ioctlRecord.outputRecord,sizeof(typeOut)))return -EFAULT;tmp=ioctlRecord.outputRecord;ioctlRecord.inputRecord=&input;ioctlRecord.outputRecord=&output;#define USR2KRN_O_START(typeOut) {typeOut output;void*tmp;tmp=ioctlRecord.outputRecord;if(!access_ok(VERIFY_WRITE,ioctlRecord.outputRecord,sizeof(typeOut)))return -EFAULT;ioctlRecord.outputRecord=&output;#define USR2KRN_END if(copy_to_user(tmp,&output,sizeof(output))) return -EFAULT; return 0;}#define USR2KRN01(theHandle,typeOut) USR2KRN_O_START(typeOut) USR2KRN_IOCTL(theHandle) USR2KRN_END#define USR2KRN11(theHandle,typeIn,typeOut) USR2KRN_IO_START(typeIn,typeOut) USR2KRN_IOCTL(theHandle) USR2KRN_END/* returns: 0 - OK, 1 - no TFFS ioctl, <0 - error */int TffsIoctl(DeviceInfo*pDevice,int cmd,unsigned long arg){ static unsigned char bdkVolume=0; unsigned char bdtlVolume=pDevice->handle; IOreq ioreq; flIOctlRecord ioctlRecord;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -