📄 tffsdrv2.c
字号:
#include "flcustom.h"#include "tffsdrv.h"#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))#include "tffs2lnx.h"#include "extfiltr.h"#define SHUTDOWN_SIGS (sigmask(SIGKILL)|sigmask(SIGINT)|sigmask(SIGTERM)|sigmask(SIGQUIT)) /* 9|2|15|3 == 15 */#include <linux/config.h> /* CONFIG_DEVFS_FS */#include <asm/io.h> /* isa_write...() */#include <linux/ioport.h> /* request_mem_reqion() */#include <linux/delay.h> /* udelay() */#include <linux/init.h> /* __initdata */#include <linux/sched.h>#include <linux/kernel.h> /* printk() */#include <linux/slab.h> /* kmalloc() */#include <linux/vmalloc.h>#include <linux/fs.h> /* everything... */#include <linux/errno.h> /* error codes */#include <linux/timer.h>#include <linux/fcntl.h> /* O_ACCMODE */#include <linux/hdreg.h> /* HDIO_GETGEO */#include <linux/devfs_fs_kernel.h> /* devfs_handle_t */#include <linux/smp_lock.h> /* lock_kernel() */#include <asm/system.h> /* cli(), *_flags */#include <asm/uaccess.h> /* verify_area() */#ifdef CONFIG_SMP#include <asm/spinlock.h>#endif/* definitions for blk.h */#include <linux/major.h>int majorReal; /* our major device number */#define MAJOR_NR majorReal#define DEVICE_ON#define DEVICE_OFF(d) #define DEVICE_NR(device) (MINOR(device)>>DEV2PART_SHIFT)#define DEVICE_NO_RANDOM#include <linux/blk.h>#include <linux/blkpg.h> /* blk_ioctl() *//* end of blk.h definitions *//* module parameters */#ifdef MODULEMODULE_AUTHOR("yurid@msys.com");MODULE_DESCRIPTION("TrueFFS driver");#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,10)MODULE_LICENSE("Proprietary");#endifMODULE_SUPPORTED_DEVICE(TFFS_SUPPORTED_DEVICE);#endifstatic int __initdata major=TFFS_MAJOR;#ifdef MODULEMODULE_PARM(major,"i"); /* set to zero to get dynamic major */MODULE_PARM_DESC(major, "Major device number to use.");#endifstatic int __initdata rahead=TFFS_RAHEAD_DEF;#ifdef MODULEMODULE_PARM(rahead,"i");MODULE_PARM_DESC(rahead, "Set readahead flag for driver.");#endifstatic int __initdata hardsect=TFFS_HARDSECT_DEF;#ifdef MODULEMODULE_PARM(hardsect,"i");MODULE_PARM_DESC(hardsect, "The size of the hardware sector for all devices, in bytes.");#endifstatic int __initdata blksize=0;#ifdef MODULEMODULE_PARM(blksize,"i");MODULE_PARM_DESC(blksize, "The size of the block for all devices, in bytes.");#endif#ifndef DO_NOT_YIELD_CPUstatic int __initdata prio=TFFS_PRIO_DEF; /* max -20, min 19 */# ifdef MODULEMODULE_PARM(prio,"i");MODULE_PARM_DESC(prio,"Kernel thread priority.");# endif#endif#define GetSocket(pDev) ((SocketInfo*)(pDev)->pSocket)static int*fl_blksize_size=NULL;static int*fl_hardsect_size=NULL;static int*fl_blk_size=NULL;static struct hd_struct*hdStruct=NULL;static TheDiskInfo diskInfo;static unsigned char bSockets;static spinlock_t o_c_lock;/* function declarations */int tffs_init(void);void* __init ckmalloc(int size,int mode);void __init lkfree(void**ptr);int Open(struct inode*inode,struct file *filp);int Ioctl(struct inode*inode, struct file *filp, unsigned int cmd, unsigned long arg);int Revalidate(kdev_t i_rdev);int Release(struct inode*inode, struct file*filp);#ifndef DO_NOT_YIELD_CPUstatic int IoKernelThread(void*socket);#endifstatic void DeviceRequest(request_queue_t*q);static void TransferRequests(void);static int TransferRequest(DeviceInfo*pDevice,struct request*pRequest);static struct block_device_operations blockDeviceOper ={ open: Open, release: Release, ioctl: Ioctl, check_media_change: NULL, revalidate: NULL,};static struct gendisk theGendisk ={ 0, /* major Major number, assigned at runtime */ TFFS_DEVICE_NAME, /* major_name Major name */ DEV2PART_SHIFT, /* minor_shift Bits to shift to get real from partition */ 1<<DEV2PART_SHIFT, /* max_p Number of partitions per real */ NULL, /* hd struct */ NULL, /* block sizes */ 0, /* nr_real maximum number of real, assigned at runtime */ NULL, /* internal */ NULL, /* next linked list (not used for modules) */ &blockDeviceOper, NULL, NULL};#ifdef MODULE# define tffs_init init_module#endif/* Initialize the driver, register major and link into gendisk_list. */int tffs_init(void){ int result; unsigned int socket,device,partition; DeviceInfo*pDevice; PrintkInfo("TrueFFS driver %d.%d",TFFS_SVER/100,TFFS_DRV_VER); PrintkDebug("\"%s\" (pid %i)",current->comm,current->pid); majorReal=major; /* 100 by default */ /* Init TrueFFS */ TffsInit(&diskInfo); if(diskInfo.noOfDevices==0) { PrintkError("Cannot find any TrueFFS devices"); goto fl_init_error; } theGendisk.nr_real=diskInfo.noOfDevices; ExtFilterInit(&diskInfo); PrintkDebug("tffs_init: TffsInit OK"); PrintkInfo("%d device(s) found",diskInfo.noOfDevices); bSockets=(diskInfo.pDevices[diskInfo.noOfDevices-1].handle&0xf)+1; PrintkDebug("%d socket(s) found",bSockets); /* partition array must be allocated here, setup_dev() accesses it before calling fl_genit() */ /* allocate per device dynamic structures, these are done here so we can release ckmalloc() */ if (!(fl_blksize_size=ckmalloc((theGendisk.nr_real<<DEV2PART_SHIFT) * sizeof(int),GFP_KERNEL))) { PrintkDebug("tffs_init: ckmalloc(fl_blksize_size) failed"); goto fail_malloc; } if(!(fl_hardsect_size=ckmalloc((theGendisk.nr_real<<DEV2PART_SHIFT) * sizeof(int),GFP_KERNEL))) { PrintkDebug("tffs_init: ckmalloc(fl_hardsect_size) failed"); goto fail_malloc; } if(!(fl_blk_size=ckmalloc((theGendisk.nr_real<<DEV2PART_SHIFT) * sizeof(int),GFP_KERNEL))) { PrintkDebug("tffs_init: ckmalloc(fl_blk_size) failed"); goto fail_malloc; } if(!(hdStruct=ckmalloc((theGendisk.nr_real<<DEV2PART_SHIFT)*sizeof(struct hd_struct),GFP_KERNEL))) { PrintkDebug("tffs_init: ckmalloc(hdStruct) failed"); goto fail_malloc; } spin_lock_init(&o_c_lock); /* init sockets */ for(socket=0;socket<bSockets;socket++) { SocketInfo*pSocket=diskInfo.pSockets+socket; if(!pSocket->threadInit) {#ifndef DO_NOT_YIELD_CPU spin_lock_init(&pSocket->ioLock); /* init available */ spin_unlock(&pSocket->ioLock); sema_init(&pSocket->threadSemaphore,0); /* init down */ init_waitqueue_head(&pSocket->waitQueueHead); pSocket->threadInit=1; kernel_thread(IoKernelThread,(void*)pSocket,0); down_interruptible(&pSocket->threadSemaphore); /* wait to thread */ PrintkDebug("tffs_init: after kernel_thread");#endif } } /* init devices */ for(device=0;device<theGendisk.nr_real;device++) { int hardSecSize,blockSize; pDevice=diskInfo.pDevices+device; if(hardsect) hardSecSize=hardsect; else hardSecSize=pDevice->sectorSize;/* if(hardSecSize<pDevice->sectorSize) hardSecSize=pDevice->sectorSize; */ if(hardSecSize>PAGE_SIZE) /* sector can't be great then block */ hardSecSize=PAGE_SIZE; if(blksize) { blockSize=blksize; if(blockSize<hardSecSize) hardSecSize=blockSize; } else { blockSize=pDevice->sectorSize; if(blockSize<BLOCK_SIZE) /* Set default value. It's better than 512 */ blockSize=BLOCK_SIZE; if(blockSize<hardSecSize) blockSize=hardSecSize; } if(blockSize>PAGE_SIZE) /* kernel limit: blksize_size can't be more then PAGE_SIZE */ blockSize=PAGE_SIZE; pDevice->usage=0; fl_blk_size[device<<DEV2PART_SHIFT]=pDevice->size>>10; for(partition=device<<DEV2PART_SHIFT;partition<((device+1)<<DEV2PART_SHIFT);partition++) { fl_blksize_size[partition]=blockSize; fl_hardsect_size[partition]=hardSecSize; } hdStruct[device<<DEV2PART_SHIFT].nr_sects=diskInfo.pDevices[device].size>>9; } /* Register your major, and/or accept a dynamic number */ if((result=devfs_register_blkdev(majorReal,TFFS_DEVICE_NAME,&blockDeviceOper)) < 0) { PrintkError("Can't get major %d",majorReal); goto fail_malloc; } /* save major if we are using a dynamic major */ if (majorReal==0) { majorReal=result; /* dynamic */ } PrintkInfo("Registered module at major %d",majorReal); /* setup gendisk structure with partition information */ theGendisk.part=hdStruct; theGendisk.major=majorReal; theGendisk.sizes=fl_blk_size; blk_size[majorReal]=fl_blk_size; blksize_size[majorReal]=fl_blksize_size; hardsect_size[majorReal]=fl_hardsect_size; read_ahead[majorReal]=rahead; /* register request method */ blk_init_queue(BLK_DEFAULT_QUEUE(majorReal),DeviceRequest); PrintkDebug("tffs_init: init_queue OK"); /* link into global gendisk list */ add_gendisk(&theGendisk); PrintkDebug("tffs_init: add_gendisk OK"); /* grab blk_size information and spit out some info */ for(device=0;device<theGendisk.nr_real;device++) { pDevice = diskInfo.pDevices+device; /* call resetup/register_disk for each physical device */ if(pDevice->size#ifdef TFFS_ALLOW_UNFORMATTED || (pDevice->pSocket->fDummy && ((pDevice->handle&0xf0)==0)) /* allow 1 dummy device per socket */#endif ) { PrintkDebug("tffs_init: register_disk real %d, device %d, size 0x%lx",majorReal,device<<DEV2PART_SHIFT,hdStruct[device<<DEV2PART_SHIFT].nr_sects); register_disk(&theGendisk,MKDEV(majorReal,device<<DEV2PART_SHIFT),theGendisk.max_p,theGendisk.fops,hdStruct[device<<DEV2PART_SHIFT].nr_sects); PrintkDebug("tffs_init: register_disk OK"); } PrintkInfo("Device 0x%x size 0x%lx hardsect_size 0x%x",(unsigned short)(device<<DEV2PART_SHIFT),diskInfo.pDevices[device].size,(unsigned short)fl_hardsect_size[device<<DEV2PART_SHIFT]); for(partition=(int)(device<<DEV2PART_SHIFT)+1; partition < (int)((device+1)<<DEV2PART_SHIFT);partition++) { ExtFilterAddPartition(partition,theGendisk.part[partition].start_sect,theGendisk.part[partition].nr_sects); fl_blk_size[partition] = ((long)(theGendisk.part[partition].nr_sects))>>1; if(fl_blk_size[partition]>0) { PrintkInfo(" partition 0x%x size 0x%lx start offset 0x%lx",partition,(long)fl_blk_size[partition]*1024,theGendisk.part[partition].start_sect<<9); } } } PrintkDebug("tffs_init: returns 0"); return 0;fail_malloc: PrintkDebug("tffs_init: fails"); /* Failed, free any memory that was allocated and set pointers to NULL */ read_ahead[majorReal]=0; lkfree((void **)&fl_blksize_size); lkfree((void **)&fl_hardsect_size); lkfree((void **)&fl_blk_size); lkfree((void **)&hdStruct); blk_size[majorReal]=NULL; blksize_size[majorReal]=NULL; hardsect_size[majorReal]=NULL; ExtFilterRelease();fl_init_error: TffsCleanup(&diskInfo); return 1;}#ifdef MODULEvoid cleanup_module(void){ unsigned char bSocket; int minor; PrintkDebug("cleanup_module"); /* first of all, flush it all and reset all the data structures */ for(minor=0;minor<(theGendisk.nr_real<<DEV2PART_SHIFT);minor++) { ExtFilterRemovePartition(minor); fsync_dev(MKDEV(majorReal,minor)); /* flush the devices */ } ExtFilterRelease(); for(bSocket=0;bSocket<bSockets;bSocket++) { if(diskInfo.pSockets[bSocket].threadInit) {#ifndef DO_NOT_YIELD_CPU wake_up(&diskInfo.pSockets[bSocket].waitQueueHead); PrintkDebug("cleanup_module: queue waked, socket %d",bSocket);#endif diskInfo.pSockets[bSocket].threadInit=0;#ifndef DO_NOT_YIELD_CPU down_interruptible(&diskInfo.pSockets[bSocket].threadSemaphore); /* wait for last request end */ PrintkDebug("cleanup_module: semaphore down, socket %d",bSocket);#endif } } PrintkDebug("cleanup_module: before TffsCleanup"); TffsCleanup(&diskInfo); blk_cleanup_queue(BLK_DEFAULT_QUEUE(majorReal)); /* unregister our device */ devfs_unregister_blkdev(majorReal,TFFS_DEVICE_NAME); del_gendisk(&theGendisk); /* reset global blk array entries */ read_ahead[majorReal] = 0; blk_size[majorReal] = NULL; blksize_size[majorReal] = NULL; hardsect_size[majorReal] = NULL; /* free our data structures */ lkfree((void **)&fl_blk_size); lkfree((void **)&fl_blksize_size); lkfree((void **)&fl_hardsect_size); lkfree((void **)&hdStruct);}#endif /* MODULE */void* __init ckmalloc(int size, int mode){ void *ptr; if ((ptr = kmalloc(size, mode))) memset(ptr, 0, size); return ptr;}void __init lkfree(void **ptr){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -