📄 tffsdrv2.c
字号:
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(¤t->blocked, SHUTDOWN_SIGS); spin_lock(¤t->sigmask_lock); flush_signals(current); spin_unlock(¤t->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 + -