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

📄 tffsdrv2.c

📁 Linux下msys公司提供的doc2000的驱动源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	if(*ptr)	{		kfree(*ptr);		*ptr = NULL;	}}int Open(struct inode*inode,struct file*filp){	DeviceInfo*pDevice=diskInfo.pDevices;	int dev_nr;	PrintkDebug("Open 0x%x",(unsigned short)inode->i_rdev);	dev_nr=DEVICE_NR(inode->i_rdev);	pDevice+=dev_nr;#ifdef TFFS_ALLOW_UNFORMATTED	if(pDevice->pSocket->fDummy)		return 0;#endif	if(dev_nr>=theGendisk.nr_real)	{		PrintkError("Open: can't access device %d",dev_nr);		return -ENODEV;	}#ifdef HW_PROTECTION	if(TffsIsWriteProtected(pDevice))	/* write protected */	{		if(filp->f_mode&0x02)		{			PrintkDebug("Open: device %d write protected",dev_nr);			return -EROFS;		}	}#endif	spin_lock(&o_c_lock);	if(!pDevice->usage)	{		if(!TffsOpen(pDevice))		{			PrintkError("Open: can't access device %d",dev_nr);			return -ENODEV;		}	}	pDevice->usage++;#ifdef MODULE	MOD_INC_USE_COUNT;#endif	spin_unlock(&o_c_lock);	return 0;					/* success */}int Release(struct inode*inode,struct file*filp){	DeviceInfo*pDevice;	int dev_nr;	PrintkDebug("Release 0x%x",(unsigned short)inode->i_rdev);	/* get the real device number */	dev_nr=DEVICE_NR(inode->i_rdev);	pDevice=diskInfo.pDevices+dev_nr;#ifdef TFFS_ALLOW_UNFORMATTED	if(pDevice->pSocket->fDummy)		return 0;#endif	if(dev_nr>=theGendisk.nr_real)	{		PrintkError("Open: can't access device %d",dev_nr);		return -ENODEV;	}	/* lock and dec usage count */	spin_lock(&o_c_lock);	pDevice->usage--;	/* if there are no more open we want to ensure that we flush all blocks.		sync_dev can cause sleep, so this should be _before_ MOD_DEC_USE_COUNT. */	if(!pDevice->usage)	{		/* flush it right now */		sync_dev(inode->i_rdev);		invalidate_buffers(inode->i_rdev);		if(!TffsRelease(pDevice))		{			PrintkError("Open: can't access device %d",dev_nr);			return -ENODEV;		}	}#ifdef MODULE	MOD_DEC_USE_COUNT;#endif	spin_unlock(&o_c_lock);	return 0;}/* The ioctl() implementation */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=diskInfo.pDevices+DEVICE_NR(inode->i_rdev);#endif	int res=0;	PrintkDebug("Ioctl: cmd 0x%x",cmd);#ifndef DO_NOT_YIELD_CPU	spin_lock(&GetSocket(pDevice)->ioLock);	spin_unlock(&GetSocket(pDevice)->ioLock);#endif#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 BLKGETSIZE:		{			PrintkDebug("Ioctl: BLKGETSIZE");			/* Return the device size, expressed in sectors */			if(!arg)			{				res=-EINVAL;		/* NULL pointer: not valid */				break;			}			if(!access_ok(VERIFY_WRITE,(void*)arg,sizeof(long)))			{				res=-EFAULT;				break;			}			put_user(theGendisk.part[MINOR(inode->i_rdev)].nr_sects,(long*)arg);			break;		}	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/fl_hardsect_size[MINOR(inode->i_rdev)],1024/((fl_hardsect_size[MINOR(inode->i_rdev)])>>9),&geometry.heads,&geometry.sectors,(unsigned int*)(&geometry.cylinders));			geometry.start=theGendisk.part[MINOR(inode->i_rdev)].start_sect;			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;		}#ifdef HDIO_GETGEO_BIG	case HDIO_GETGEO_BIG:		{			struct hd_big_geometry geometry;			PrintkDebug("Ioctl: HDIO_GETGEO_BIG");			/* 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/fl_hardsect_size[MINOR(inode->i_rdev)],1024/((fl_hardsect_size[MINOR(inode->i_rdev)])>>9),&geometry.heads,&geometry.sectors,&geometry.cylinders);			geometry.start=theGendisk.part[MINOR(inode->i_rdev)].start_sect;			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;		}#endif /* HDIO_GETGEO_BIG */	case BLKRRPART:		/* re-read partition table */		PrintkDebug("Ioctl: BLKRRPART");		res=Revalidate(inode->i_rdev);		break;	default:			/* unknown command */		PrintkDebug("Ioctl: Other");		res=blk_ioctl(inode->i_rdev,cmd,arg);	}	if(res)		PrintkError("Ioctl: cmd 0x%x error",cmd);	return res;}int Revalidate(kdev_t i_rdev){	/* first partition, # of partitions */	int part1 = (DEVICE_NR(i_rdev)<<DEV2PART_SHIFT) + 1;	int npart = (1<<DEV2PART_SHIFT) - 1;	int dev_nr;	int partition;	PrintkDebug("Revalidate:");	dev_nr=DEVICE_NR(i_rdev);	/* first clear old partition information  */	memset(theGendisk.sizes + part1, 0, npart * sizeof(int));	memset(theGendisk.part + part1, 0, npart * sizeof(struct hd_struct));	/* then fill new info  */	/* The partition code eventually wants to read	a block and wait for it.  We'd better not lock out the	low level routine TransferRequest() or we're hosed. */	grok_partitions(&theGendisk,dev_nr,theGendisk.max_p,diskInfo.pDevices[dev_nr].size>>9);	for(partition=(int)(dev_nr<<DEV2PART_SHIFT)+1; partition < (int)((dev_nr+1)<<DEV2PART_SHIFT);partition++)	{		ExtFilterRemovePartition(partition);		ExtFilterAddPartition(partition,theGendisk.part[partition].start_sect,theGendisk.part[partition].nr_sects);		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);		}	}	return 0;}#ifndef DO_NOT_YIELD_CPU/* Like Nicolas Pitre's mtd driver */static int IoKernelThread(void*socket) {	SocketInfo*pSocket=socket;	PrintkDebug("IoKernelThread");	/* Detach as best we can from the process that started us. */	lock_kernel();	/* struct task_struct current */	exit_mm(current);	exit_files(current);	exit_fs(current);	current->leader=1;	current->session=current->pgrp=current->pid;	current->tty=NULL;	current->tty_old_pgrp=0;	current->exit_signal=SIGCHLD;	/* Run at a high priority, ahead of sync and friends */	current->policy = SCHED_OTHER;#ifdef REDHAT_KERNEL_EXTENSION	set_user_nice(current,prio);#else	current->nice = prio;#endif	siginitsetinv(&current->blocked, SHUTDOWN_SIGS);	spin_lock(&current->sigmask_lock);	flush_signals(current);	spin_unlock(&current->sigmask_lock);	/* Name this thread */	sprintf(current->comm,"tffs%c",'1'+(pSocket-diskInfo.pSockets));	/* Replace the initialization/termination semaphore with our "requests to do" semaphore. */	unlock_kernel();	up(&pSocket->threadSemaphore);	PrintkDebug("IoKernelThread: threadSemaphore released");	while(pSocket->threadInit)	{		set_current_state(TASK_INTERRUPTIBLE);/*		PrintkDebug("IoKernelThread: going sleep"); */		sleep_on(&pSocket->waitQueueHead);		spin_unlock(&pSocket->ioLock);/* 		PrintkDebug("IoKernelThread: up(ioLock)");  *//*		PrintkDebug("IoKernelThread: awaked"); */		set_current_state(TASK_RUNNING);		TransferRequests();		spin_unlock_irq(&io_request_lock);	}	/* Let the process terminating us know we are done. */	up(&pSocket->threadSemaphore);	PrintkDebug("IoKernelThread: exit from thread");	return 0;}#endif /* DO_NOT_YIELD_CPU */static void DeviceRequest(request_queue_t*q){	DeviceInfo*pDevice;/*	PrintkDebug("DeviceRequest"); */	pDevice=diskInfo.pDevices+CURRENT_DEV;/*	PrintkDebug("DeviceRequest: down(ioLock)"); */#ifndef DO_NOT_YIELD_CPU	spin_lock(&GetSocket(pDevice)->ioLock);	wake_up(&GetSocket(pDevice)->waitQueueHead);#else	TransferRequests();#endif}static void TransferRequests(){	struct request*pRequest;	int endRequest;/*	PrintkDebug("TransferRequests"); */#ifndef DO_NOT_YIELD_CPU	spin_lock_irq(&io_request_lock);#endif	while(!QUEUE_EMPTY)	{		INIT_REQUEST;		pRequest=CURRENT;		/* Check if the minor number is in range */		if(DEVICE_NR(pRequest->rq_dev)>theGendisk.nr_real)		{			PrintkError("DeviceRequest: request for non-existent device %d",CURRENT_DEV);			end_request(0);			continue;		}#ifndef DO_NOT_YIELD_CPU		spin_unlock_irq(&io_request_lock);#endif		endRequest=TransferRequest(&diskInfo.pDevices[DEVICE_NR(pRequest->rq_dev)],pRequest);#ifndef DO_NOT_YIELD_CPU		spin_lock_irq(&io_request_lock);#endif		end_request(endRequest);	}	return;}static int TransferRequest(DeviceInfo*pDevice,struct request*pRequest){	int partition=MINOR(pRequest->rq_dev);#ifdef TFFS_ALLOW_UNFORMATTED		if(pDevice->pSocket->fDummy)			return 0;#endif	/* check sectors are in range */	if((pRequest->sector+pRequest->current_nr_sectors) > theGendisk.part[partition].nr_sects)	{		PrintkError("DeviceRequest: request past end of device: %4lx >= %4lx",pRequest->sector+pRequest->current_nr_sectors,theGendisk.part[partition].nr_sects);		return 0;	}	switch(pRequest->cmd)	{	case READ:/*		PrintkDebug("TransferRequest: READ start_sect 0x%lx current_nr_sectors 0x%lx part %u start 0x%lx",pRequest->sector,pRequest->current_nr_sectors,partition,hdStruct[partition].start_sect);*/		return TffsRead(pDevice,pRequest->buffer,pRequest->sector+hdStruct[partition].start_sect,pRequest->current_nr_sectors);	case WRITE:/*		PrintkDebug("TransferRequest: WRITE start_sect 0x%lx current_nr_sectors 0x%lx part %u start 0x%lx",pRequest->sector,pRequest->current_nr_sectors,partition,hdStruct[partition].start_sect); */		ExtFilter(partition,pRequest->buffer,pRequest->sector,pRequest->current_nr_sectors);		return TffsWrite(pDevice,pRequest->buffer,pRequest->sector+hdStruct[partition].start_sect,pRequest->current_nr_sectors);	default:		PrintkError("DeviceRequest: pRequest->cmd not valid");		return 0;	}}#ifndef DO_NOT_YIELD_CPUvoid LnxSleep(unsigned long milliseconds,unsigned char bSocket){#if FL_SKIP_SLEEPS	static unsigned short wSkipSleep=0;	if(++wSkipSleep<=FL_SKIP_SLEEPS)	{		return;	}	wSkipSleep=0;#endif	sleep_on_timeout(&diskInfo.pSockets[bSocket].waitQueueHead,(HZ*milliseconds)>>10);}#endif#endif /* #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)) && (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)) */

⌨️ 快捷键说明

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