⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tffsdrv1.c

📁 Linux下msys公司提供的doc2000的驱动源代码
💻 C
字号:
#include "flcustom.h"#include "tffsdrv.h"#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,7,0))#include "flsystem.h"#include "tffs2lnx.h"#include <linux/blkdev.h>#include <linux/hdreg.h>			/* HDIO_GETGEO */#include <linux/sockios.h>			/* for SIOCDEVPRIVATE *//* module parameters */#ifdef MODULEMODULE_AUTHOR("yurid@msys.com");MODULE_DESCRIPTION("TrueFFS driver");MODULE_LICENSE("Proprietary");MODULE_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.");#endif#if 0static int __initdata rahead=0;#ifdef MODULEMODULE_PARM(rahead,"i");MODULE_PARM_DESC(rahead,"Set readahead flag for driver.");#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#endifstatic int __initdata hardsect=0;#ifdef MODULEMODULE_PARM(hardsect,"i");MODULE_PARM_DESC(hardsect,"The size of the hardware sector for all devices, in bytes.");#endif#ifndef DO_NOT_YIELD_CPUstatic int __initdata prio=-20;	/* max -20 */# ifdef MODULEMODULE_PARM(prio,"i");MODULE_PARM_DESC(prio,"Kernel thread priority.");# endif#endifstatic void InitFree(unsigned char bStep);static int Open(struct inode*inode,struct file*filp);static void Request(request_queue_t*q);int Ioctl(struct inode*inode,struct file*filp,unsigned int cmd,unsigned long arg);static void TransferRequests(request_queue_t*q);#ifndef DO_NOT_YIELD_CPUstatic int IoKernelThread(void*device);#endifstatic TheDiskInfo diskInfo;static struct block_device_operations blockDeviceOper={	.owner=THIS_MODULE,	.ioctl=Ioctl,	.open=Open,};/* Initialize the driver, register major and link into gendisk_list. */int tffs_init(void){	int result;	unsigned char bDevice;	PrintkInfo("TrueFFS driver %d.%d",TFFS_SVER/100,TFFS_DRV_VER);	PrintkDebug("\"%s\" (pid %i)",current->comm,current->pid);	/* init TFFS */	TffsInit(&diskInfo);	if(diskInfo.noOfDevices==0)	{		PrintkError("Cannot find any TrueFFS devices");		InitFree(1);		return -EBUSY;	}	/* get major number */	diskInfo.major=major;	if((result=register_blkdev(diskInfo.major,TFFS_DEVICE_NAME)) < 0)	{		PrintkError("Can't get major %d",diskInfo.major);		InitFree(1);		return result;	}	if (diskInfo.major==0)	{		diskInfo.major=result;			/* dynamic */	}	PrintkInfo("Registered module at major %d",diskInfo.major);	/* device loop */	for(bDevice=0;bDevice<diskInfo.noOfDevices;bDevice++)	{		DeviceInfo*pDevice=diskInfo.pDevices+bDevice;		if(pDevice->fValid /* find next valid device */#ifdef TFFS_ALLOW_UNFORMATTED			|| (pDevice->pSocket->fDummy && ((pDevice->handle&0xf0)==0))	/* allow 1 dummy device per socket */#endif			)		{			spin_lock_init(&pDevice->queueLock);#ifndef DO_NOT_YIELD_CPU			/* Init thread */			sema_init(&pDevice->threadSemaphore,0);		/* init down */			init_waitqueue_head(&pDevice->waitQueueHead);			pDevice->threadInit=1;			kernel_thread(IoKernelThread,(void*)pDevice,0);			down_interruptible(&pDevice->threadSemaphore);	/* wait to thread */			PrintkDebug("tffs_init: after kernel_thread");#endif			/* init queue */			pDevice->requestQueue=blk_init_queue(Request,&pDevice->queueLock);			if(pDevice->requestQueue==NULL)			{				InitFree(3);				return -ENOMEM;			}			PrintkDebug("blk_init_queue(%d) OK",bDevice);#ifndef DO_NOT_YIELD_CPU			pDevice->requestQueue->queuedata=pDevice;#endif			blk_queue_hardsect_size(pDevice->requestQueue,(hardsect==0)?pDevice->pSocket->maxSectorSize:hardsect);			PrintkDebug("tffs_init:blk_queue_hardsect_size(%d,%d)",bDevice,pDevice->pSocket->maxSectorSize);			pDevice->usage=0;			spin_lock_init(&pDevice->o_c_lock);				/* init gendisk */			pDevice->genDisk=alloc_disk(TFFS_NO_OF_PARTS_PER_DEVICE);			if(pDevice->genDisk==NULL)			{				InitFree(3);				return -ENOMEM;			}			PrintkDebug("alloc_disk(%d) OK",bDevice);			pDevice->genDisk->major=diskInfo.major;			pDevice->genDisk->first_minor=bDevice*(1<<DEV2PART_SHIFT); /* don't use TFFS_NO_OF_PARTS_PER_DEVICE here */			pDevice->genDisk->fops=&blockDeviceOper;			pDevice->genDisk->private_data=pDevice;			sprintf(pDevice->genDisk->disk_name,"%s%c",TFFS_DEVICE_NAME,'a'+bDevice);			set_capacity(pDevice->genDisk,pDevice->size>>9);			pDevice->genDisk->queue=pDevice->requestQueue;			add_disk(pDevice->genDisk);		}	}	return 0;}module_init(tffs_init);static void InitFree(unsigned char bStep){	unsigned char bDevice,bSocket;	PrintkDebug("InitFree");	switch(bStep)	{	case 0:	case 3:#ifndef DO_NOT_YIELD_CPU		for(bSocket=0;bSocket<diskInfo.noOfSockets;bSocket++)		{		}#endif		for(bDevice=0;bDevice<diskInfo.noOfDevices;bDevice++)		{			DeviceInfo*pDevice=diskInfo.pDevices+bDevice;			if(pDevice->threadInit==1)			{				/* flush devices */				/* TODO */				/* stop IO thread */				pDevice->threadInit=0;				wake_up(&pDevice->waitQueueHead);				PrintkDebug("cleanup_module: queue waked, device %d",bDevice);				down_interruptible(&pDevice->threadSemaphore); /* wait for last request end */				PrintkDebug("cleanup_module: semaphore down, device %d",bDevice);			}			if(pDevice->genDisk!=NULL)			{				del_gendisk(pDevice->genDisk);				pDevice->genDisk=NULL;				blk_cleanup_queue(pDevice->requestQueue);				pDevice->requestQueue=NULL;			}		}	case 2:		unregister_blkdev(diskInfo.major,TFFS_DEVICE_NAME);	case 1:		TffsCleanup(&diskInfo);	}}#ifdef MODULEvoid tffs_exit(void){	InitFree(0);}module_exit(tffs_exit);#endif	/* MODULE */static int Open(struct inode*inode,struct file*filp){	DeviceInfo*pDevice=inode->i_bdev->bd_disk->private_data;	PrintkDebug("Open 0x%x",pDevice->handle);#ifdef TFFS_ALLOW_UNFORMATTED	if(pDevice->pSocket->fDummy)	{		PrintkDebug("Open 0x%x: not valid",pDevice->handle);		return 0;	}#endif#ifdef HW_PROTECTION	if(TffsIsWriteProtected(pDevice))	/* write protected */	{		if(filp->f_mode&0x02)		{			PrintkDebug("Open: device write protected");			return -EROFS;		}	}#endif	spin_lock(&pDevice->o_c_lock);	if(!pDevice->usage)	{		if(!TffsOpen(pDevice))		{			PrintkError("Open: can't access device %d",iminor(inode));			return -ENODEV;		}	}	pDevice->usage++;	spin_unlock(&pDevice->o_c_lock);	PrintkDebug("Open 0x%x OK",pDevice->handle);	return 0;					/* success */}int Release(struct inode*inode,struct file*filp){	DeviceInfo*pDevice=inode->i_bdev->bd_disk->private_data;	PrintkDebug("Release 0x%x",(unsigned short)iminor(inode));#ifdef TFFS_ALLOW_UNFORMATTED	if(pDevice->pSocket->fDummy)		return 0;#endif	/* lock and dec usage count */	spin_lock(&pDevice->o_c_lock);	pDevice->usage--;	if(!pDevice->usage)	{		if(!TffsRelease(pDevice))		{			PrintkError("Release: can't access device %d",iminor(inode));			return -ENODEV;		}	}	spin_unlock(&pDevice->o_c_lock);	return 0;}int Ioctl(struct inode*inode,struct file*filp,unsigned int cmd,unsigned long arg){#if defined(IOCTL_INTERFACE) || !defined(DO_NOT_YIELD_CPU)	DeviceInfo*pDevice=inode->i_bdev->bd_disk->private_data;#endif	int res=0;	PrintkDebug("Ioctl: cmd 0x%x",cmd);#ifdef IOCTL_INTERFACE	if(cmd>=SIOCDEVPRIVATE)	{		PrintkDebug("Ioctl: TffsIoctl(0x%lx) = 0x%lx -0x%lx",(unsigned long)(cmd-SIOCDEVPRIVATE),(unsigned long)cmd,(unsigned long)SIOCDEVPRIVATE);		res=TffsIoctl(pDevice,cmd-SIOCDEVPRIVATE,arg);		switch(res)		{		case 0: /* OK */			return 0;		case 1: /* not tffs ioctl - continue */			break;		default: /* error */			PrintkError("Ioctl: cmd 0x%x error",cmd);			return res;		}	}#endif	/* IOCTL_INTERFACE */	switch(cmd)	{	case HDIO_GETGEO:		{			struct hd_geometry geometry;			PrintkDebug("Ioctl: HDIO_GETGEO");			/* check arg */			if((void*)arg==NULL)			{				res=-EINVAL;				break;			}			if(!access_ok(VERIFY_WRITE,(void*)arg,sizeof(struct hd_geometry)))			{				res=-EFAULT;				break;			}			TffsGetDriveGeometry(pDevice->size/pDevice->pSocket->maxSectorSize,1024/(pDevice->pSocket->maxSectorSize>>9),&geometry.heads,&geometry.sectors,(unsigned int*)(&geometry.cylinders));			geometry.start=get_start_sect(inode->i_bdev);			PrintkDebug("Ioctl: heads 0x%x cylinders 0x%x sectors 0x%x start_sect 0x%lx",geometry.heads,geometry.cylinders,geometry.sectors,geometry.start);			if(copy_to_user((void*)arg,&geometry,sizeof(struct hd_geometry)))				return -EFAULT;			break;		}	default:			/* unknown command */		res=-ENOTTY;	}	if(res)		PrintkError("Ioctl: cmd 0x%x error",cmd);	return res;}static void Request(request_queue_t*q){/*	PrintkDebug("Request"); */#ifdef DO_NOT_YIELD_CPU	TransferRequests(q);#else	/* DO_NOT_YIELD_CPU */	wake_up_interruptible(&((DeviceInfo*)q->queuedata)->waitQueueHead);#endif /* DO_NOT_YIELD_CPU *//*	PrintkDebug("Request: exit"); */}static void TransferRequests(request_queue_t*q){	struct request*pRequest;#ifdef CONFIG_PREEMPT	BOOL fNeedYetCheck=FALSE;yet_check:#endif/*	PrintkDebug("TransferRequests: queue begin"); */	while((pRequest=elv_next_request(q))!= NULL)	/* ask for first request */	{		DeviceInfo*pDevice=pRequest->rq_disk->private_data;		BOOL fStat=0;#ifdef CONFIG_PREEMPT		fNeedYetCheck=TRUE;#endif/*	PrintkDebug("TransferRequests: request begin"); */#ifdef TFFS_ALLOW_UNFORMATTED		if(pDevice->pSocket->fDummy)		{			end_request(pRequest,0);		/* return error */			continue;		}#endif		if(!blk_fs_request(pRequest))		/* check the request */		{			end_request(pRequest,0);		/* return error */			continue;		}#ifdef DRIVER_DEBUG		/* check sectors are in range */		if((pRequest->sector+pRequest->current_nr_sectors) > (pDevice->size>>9))		{			PrintkError("TransferRequests: request not in range: %lx+%lx >= %lx",(DWORD)pRequest->sector,(DWORD)pRequest->current_nr_sectors,(DWORD)pDevice->size>>9);			end_request(pRequest,0);			continue;		}#endif		if(pRequest->flags&1)		{			spin_unlock_irq(q->queue_lock);/*			PrintkDebug("TransferRequest: WRITE start_sect 0x%lx current_nr_sectors 0x%lx",(DWORD)pRequest->sector,(DWORD)pRequest->current_nr_sectors); */			fStat=TffsWrite(pDevice,pRequest->buffer,pRequest->sector,pRequest->current_nr_sectors);		}		else		{			spin_unlock_irq(q->queue_lock);/*	 		PrintkDebug("TransferRequest: READ start_sect 0x%lx current_nr_sectors 0x%lx",(DWORD)pRequest->sector,(DWORD)pRequest->current_nr_sectors); */			fStat=TffsRead(pDevice,pRequest->buffer,pRequest->sector,pRequest->current_nr_sectors);		}/*		PrintkDebug("TransferRequests:request end"); */		spin_lock_irq(q->queue_lock);		end_request(pRequest,fStat);	}#ifdef CONFIG_PREEMPT	/* It's special stupid patch for preemptive kernels.	The Request() adds next request to queue immediatly after previous end_request()	called and queue_lock unlocked. */	if(fNeedYetCheck)	{		spin_unlock_irq(q->queue_lock);		fNeedYetCheck=FALSE;		spin_lock_irq(q->queue_lock);		goto yet_check;	}#endif/*	PrintkDebug("TransferRequests:queue end"); */}#ifndef DO_NOT_YIELD_CPUstatic int IoKernelThread(void*device) {	DeviceInfo*pDevice=(DeviceInfo*)device;	PrintkDebug("IoKernelThread");	current->flags|=PF_MEMALLOC;	daemonize("tffs%c",'a'+(pDevice-diskInfo.pDevices));	spin_lock_irq(&current->sighand->siglock);	sigfillset(&current->blocked);	recalc_sigpending();	spin_unlock_irq(&current->sighand->siglock);	set_user_nice(current,prio);	up(&pDevice->threadSemaphore);	PrintkDebug("IoKernelThread: threadSemaphore released");	spin_lock_irq(&pDevice->queueLock);	while(pDevice->threadInit)	{#if defined(DRIVER_DEBUG) && defined(CONFIG_PREEMPT)		unsigned long timeot;#endif/*		PrintkDebug("IoKernelThread: going sleep"); */		spin_unlock_irq(&pDevice->queueLock);#ifdef CONFIG_PREEMPT		/* my own preemptive paranoia */# ifdef DRIVER_DEBUG		timeot=interruptible_sleep_on_timeout(&pDevice->waitQueueHead,HZ*20);		if(timeot==0)			PrintkDebug("EXIT ON TIMEOUT");# else		interruptible_sleep_on_timeout(&pDevice->waitQueueHead,HZ);# endif/*		PrintkDebug("IoKernelThread: awaked"); */#else /* CONFIG_PREEMPT */		interruptible_sleep_on(&pDevice->waitQueueHead);#endif /* CONFIG_PREEMPT */		spin_lock_irq(&pDevice->queueLock);		TransferRequests(pDevice->requestQueue);	}	spin_unlock_irq(&pDevice->queueLock);	/* Let the process terminating us know we are done. */	up(&pDevice->threadSemaphore);	PrintkDebug("IoKernelThread: exit from thread");	return 0;}void LnxSleep(unsigned long milliseconds,unsigned char bSocket){	wait_queue_head_t qw;#if FL_SKIP_SLEEPS	static unsigned short wSkipSleep=0;	if(++wSkipSleep<=FL_SKIP_SLEEPS)	{		return;	}	wSkipSleep=0;#endif/*	PrintkDebug("LnxSleep: enter"); *//*	sleep_on_timeout(&diskInfo.pSockets[bSocket].waitQueueHead,(HZ*milliseconds)>>10); */	init_waitqueue_head(&qw);	sleep_on_timeout(&qw,(HZ*milliseconds)>>10);/*	PrintkDebug("LnxSleep: exit"); */}#endif /* DO_NOT_YIELD_CPU */#endif /* #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,7,0)) */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -