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

📄 nftl.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 3 页
字号:
#endif /* CONFIG_NFTL_RW */static int NFTL_readblock(struct NFTLrecord *nftl, unsigned block, char *buffer){	u16 lastgoodEUN;	u16 thisEUN = nftl->EUNtable[block / (nftl->EraseSize / 512)];	unsigned long blockofs = (block * 512) & (nftl->EraseSize - 1);        unsigned int status;	int silly = MAX_LOOPS;        size_t retlen;        struct nftl_bci bci;	lastgoodEUN = BLOCK_NIL;        if (thisEUN != BLOCK_NIL) {		while (thisEUN < nftl->nb_blocks) {			if (MTD_READOOB(nftl->mtd, (thisEUN * nftl->EraseSize) + blockofs,					8, &retlen, (char *)&bci) < 0)				status = SECTOR_IGNORE;			else				status = bci.Status | bci.Status1;			switch (status) {			case SECTOR_FREE:				/* no modification of a sector should follow a free sector */				goto the_end;			case SECTOR_DELETED:				lastgoodEUN = BLOCK_NIL;				break;			case SECTOR_USED:				lastgoodEUN = thisEUN;				break;			case SECTOR_IGNORE:				break;			default:				printk("Unknown status for block %d in EUN %d: %x\n",				       block, thisEUN, status);				break;			}			if (!silly--) {				printk(KERN_WARNING "Infinite loop in Virtual Unit Chain 0x%x\n",				       block / (nftl->EraseSize / 512));				return 1;			}			thisEUN = nftl->ReplUnitTable[thisEUN];		}        } the_end:	if (lastgoodEUN == BLOCK_NIL) {		/* the requested block is not on the media, return all 0x00 */		memset(buffer, 0, 512);	} else {		loff_t ptr = (lastgoodEUN * nftl->EraseSize) + blockofs;		size_t retlen;		u_char eccbuf[6];		if (MTD_READECC(nftl->mtd, ptr, 512, &retlen, buffer, eccbuf))			return -EIO;	}	return 0;}static int nftl_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg){	struct NFTLrecord *nftl;	nftl = NFTLs[MINOR(inode->i_rdev) / 16];	if (!nftl) return -EINVAL;	switch (cmd) {	case HDIO_GETGEO: {		struct hd_geometry g;		g.heads = nftl->heads;		g.sectors = nftl->sectors;		g.cylinders = nftl->cylinders;		g.start = part_table[MINOR(inode->i_rdev)].start_sect;		return copy_to_user((void *)arg, &g, sizeof g) ? -EFAULT : 0;	}	case BLKGETSIZE:   /* Return device size */		if (!arg) return -EINVAL;		return put_user(part_table[MINOR(inode->i_rdev)].nr_sects,                                (long *) arg);			case BLKFLSBUF:		if (!capable(CAP_SYS_ADMIN)) return -EACCES;		fsync_dev(inode->i_rdev);		invalidate_buffers(inode->i_rdev);		if (nftl->mtd->sync)			nftl->mtd->sync(nftl->mtd);		return 0;	case BLKRRPART:		if (!capable(CAP_SYS_ADMIN)) return -EACCES;		if (nftl->usecount > 1) return -EBUSY;#if LINUX_VERSION_CODE < 0x20328		resetup_one_dev(&nftl_gendisk, MINOR(inode->i_rdev) / 16);#else		grok_partitions(&nftl_gendisk, MINOR(inode->i_rdev) / 16,				1<<4, nftl->nr_sects);#endif		return 0;#if (LINUX_VERSION_CODE < 0x20303)			RO_IOCTLS(inode->i_rdev, arg);  /* ref. linux/blk.h */#else	case BLKROSET:	case BLKROGET:	case BLKSSZGET:		return blk_ioctl(inode->i_rdev, cmd, arg);#endif	default:		return -EINVAL;	}}void nftl_request(RQFUNC_ARG){	unsigned int dev, block, nsect;	struct NFTLrecord *nftl;	char *buffer;	struct request *req;	int res;	while (1) {		INIT_REQUEST;	/* blk.h */		req = CURRENT;				/* We can do this because the generic code knows not to		   touch the request at the head of the queue */		spin_unlock_irq(&io_request_lock);		DEBUG(MTD_DEBUG_LEVEL2, "NFTL_request\n");		DEBUG(MTD_DEBUG_LEVEL3, "NFTL %s request, from sector 0x%04lx for 0x%04lx sectors\n",		      (req->cmd == READ) ? "Read " : "Write",		      req->sector, req->current_nr_sectors);		dev = MINOR(req->rq_dev);		block = req->sector;		nsect = req->current_nr_sectors;		buffer = req->buffer;		res = 1; /* succeed */		if (dev >= MAX_NFTLS * 16) {			/* there is no such partition */			printk("nftl: bad minor number: device = %s\n",			       kdevname(req->rq_dev));			res = 0; /* fail */			goto repeat;		}				nftl = NFTLs[dev / 16];		DEBUG(MTD_DEBUG_LEVEL3, "Waiting for mutex\n");		down(&nftl->mutex);		DEBUG(MTD_DEBUG_LEVEL3, "Got mutex\n");		if (block + nsect > part_table[dev].nr_sects) {			/* access past the end of device */			printk("nftl%c%d: bad access: block = %d, count = %d\n",			       (MINOR(req->rq_dev)>>6)+'a', dev & 0xf, block, nsect);			up(&nftl->mutex);			res = 0; /* fail */			goto repeat;		}				block += part_table[dev].start_sect;				if (req->cmd == READ) {			DEBUG(MTD_DEBUG_LEVEL2, "NFTL read request of 0x%x sectors @ %x "			      "(req->nr_sectors == %lx)\n", nsect, block, req->nr_sectors);				for ( ; nsect > 0; nsect-- , block++, buffer += 512) {				/* Read a single sector to req->buffer + (512 * i) */				if (NFTL_readblock(nftl, block, buffer)) {					DEBUG(MTD_DEBUG_LEVEL2, "NFTL read request failed\n");					up(&nftl->mutex);					res = 0;					goto repeat;				}			}			DEBUG(MTD_DEBUG_LEVEL2,"NFTL read request completed OK\n");			up(&nftl->mutex);			goto repeat;		} else if (req->cmd == WRITE) {			DEBUG(MTD_DEBUG_LEVEL2, "NFTL write request of 0x%x sectors @ %x "			      "(req->nr_sectors == %lx)\n", nsect, block,			      req->nr_sectors);#ifdef CONFIG_NFTL_RW			for ( ; nsect > 0; nsect-- , block++, buffer += 512) {				/* Read a single sector to req->buffer + (512 * i) */				if (NFTL_writeblock(nftl, block, buffer)) {					DEBUG(MTD_DEBUG_LEVEL1,"NFTL write request failed\n");					up(&nftl->mutex);					res = 0;					goto repeat;				}			}			DEBUG(MTD_DEBUG_LEVEL2,"NFTL write request completed OK\n");#else			res = 0; /* Writes always fail */#endif /* CONFIG_NFTL_RW */			up(&nftl->mutex);			goto repeat;		} else {			DEBUG(MTD_DEBUG_LEVEL0, "NFTL unknown request\n");			up(&nftl->mutex);			res = 0;			goto repeat;		}	repeat: 		DEBUG(MTD_DEBUG_LEVEL3, "end_request(%d)\n", res);		spin_lock_irq(&io_request_lock);		end_request(res);	}}static int nftl_open(struct inode *ip, struct file *fp){	int nftlnum = MINOR(ip->i_rdev) / 16;	struct NFTLrecord *thisNFTL;	thisNFTL = NFTLs[nftlnum];	DEBUG(MTD_DEBUG_LEVEL2,"NFTL_open\n");#ifdef CONFIG_KMOD	if (!thisNFTL && nftlnum == 0) {		request_module("docprobe");		thisNFTL = NFTLs[nftlnum];	}#endif	if (!thisNFTL) {		DEBUG(MTD_DEBUG_LEVEL2,"ENODEV: thisNFTL = %d, minor = %d, ip = %p, fp = %p\n", 		      nftlnum, ip->i_rdev, ip, fp);		return -ENODEV;	}#ifndef CONFIG_NFTL_RW	if (fp->f_mode & FMODE_WRITE)		return -EROFS;#endif /* !CONFIG_NFTL_RW */	thisNFTL->usecount++;	MOD_INC_USE_COUNT;	if (!get_mtd_device(thisNFTL->mtd, -1)) {		MOD_DEC_USE_COUNT;		return /* -E'SBUGGEREDOFF */ -ENXIO;	}	return 0;}static int nftl_release(struct inode *inode, struct file *fp){	struct super_block *sb = get_super(inode->i_rdev);	struct NFTLrecord *thisNFTL;	thisNFTL = NFTLs[MINOR(inode->i_rdev) / 16];	DEBUG(MTD_DEBUG_LEVEL2, "NFTL_release\n");	fsync_dev(inode->i_rdev);	if (sb)		invalidate_inodes(sb);	invalidate_buffers(inode->i_rdev);	if (thisNFTL->mtd->sync)		thisNFTL->mtd->sync(thisNFTL->mtd);	thisNFTL->usecount--;	MOD_DEC_USE_COUNT;	put_mtd_device(thisNFTL->mtd);	return 0;}#if LINUX_VERSION_CODE < 0x20326static struct file_operations nftl_fops = {	read:		block_read,	write:		block_write,	ioctl:		nftl_ioctl,	open:		nftl_open,	release:	nftl_release,	fsync:		block_fsync,};#elsestatic struct block_device_operations nftl_fops = {	open:		nftl_open,	release:	nftl_release,	ioctl: 		nftl_ioctl};#endif/**************************************************************************** * * Module stuff * ****************************************************************************/#if LINUX_VERSION_CODE < 0x20212 && defined(MODULE)#define init_nftl init_module#define cleanup_nftl cleanup_module#endifstatic struct mtd_notifier nftl_notifier = {NFTL_notify_add, NFTL_notify_remove, NULL};/* static int __init init_nftl(void) */int __init init_nftl(void){	int i;	printk(KERN_NOTICE	       "M-Systems NAND Flash Translation Layer driver. (C) 1999 MVHI\n");#ifdef PRERELEASE 	printk(KERN_INFO"$Id: nftl.c,v 1.57 2000/12/01 17:51:54 dwmw2 Exp $\n");#endif	if (register_blkdev(MAJOR_NR, "nftl", &nftl_fops)){		printk("unable to register NFTL block device on major %d\n", MAJOR_NR);		return -EBUSY;	} else {#if LINUX_VERSION_CODE < 0x20320		blk_dev[MAJOR_NR].request_fn = nftl_request;#else		blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), &nftl_request);#endif		/* set block size to 1kB each */		for (i = 0; i < 256; i++) {			nftl_blocksizes[i] = 1024;		}		blksize_size[MAJOR_NR] = nftl_blocksizes;		nftl_gendisk.next = gendisk_head;		gendisk_head = &nftl_gendisk;	}		register_mtd_user(&nftl_notifier);	return 0;}static void __exit cleanup_nftl(void){	struct gendisk *gd, **gdp;  	unregister_mtd_user(&nftl_notifier);  	unregister_blkdev(MAJOR_NR, "nftl");  	#if LINUX_VERSION_CODE < 0x20320  	blk_dev[MAJOR_NR].request_fn = 0;#else  	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));#endif		/* remove ourself from generic harddisk list	   FIXME: why can't I found this partition on /proc/partition */  	for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next))    		if (*gdp == &nftl_gendisk) {      			gd = *gdp; *gdp = gd->next;      			break;    	}}module_init(init_nftl);module_exit(cleanup_nftl);

⌨️ 快捷键说明

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