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

📄 i2o_block.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
		case 7:	printk("Optical device");break;		default:			printk("Type %d", type);	}	if(status&(1<<10))		printk("(RAID)");	if(((flags & (1<<3)) && !(status & (1<<3))) ||	   ((flags & (1<<4)) && !(status & (1<<4))))	{		printk(KERN_INFO " Not loaded.\n");		return 1;	}	printk("- %dMb, %d byte sectors",		(int)(size>>20), blocksize);	if(status&(1<<0))	{		u32 cachesize;		i2ob_query_device(dev, 0x0003, 0, &cachesize, 4);		cachesize>>=10;		if(cachesize>4095)			printk(", %dMb cache", cachesize>>10);		else			printk(", %dKb cache", cachesize);	}	printk(".\n");	printk(KERN_INFO "%s: Maximum sectors/read set to %d.\n", 		d->dev_name, i2ob_max_sectors[unit]);	/* 	 * If this is the first I2O block device found on this IOP,	 * we need to initialize all the queue data structures	 * before any I/O can be performed. If it fails, this	 * device is useless.	 */	if(!i2ob_queues[c->unit]) {		if(i2ob_init_iop(c->unit))			return 1;	}	/* 	 * This will save one level of lookup/indirection in critical 	 * code so that we can directly get the queue ptr from the	 * device instead of having to go the IOP data structure.	 */	dev->req_queue = &i2ob_queues[c->unit]->req_queue;	grok_partitions(&i2ob_gendisk, unit>>4, 1<<4, (long)(size>>9));	/*	 * Register for the events we're interested in and that the	 * device actually supports.	 */	i2o_event_register(c, d->lct_data.tid, i2ob_context, unit, 		(I2OB_EVENT_MASK & d->lct_data.event_capabilities));	return 0;}/* * Initialize IOP specific queue structures.  This is called * once for each IOP that has a block device sitting behind it. */static int i2ob_init_iop(unsigned int unit){	int i;	i2ob_queues[unit] = (struct i2ob_iop_queue*)		kmalloc(sizeof(struct i2ob_iop_queue), GFP_ATOMIC);	if(!i2ob_queues[unit])	{		printk(KERN_WARNING			"Could not allocate request queue for I2O block device!\n");		return -1;	}	for(i = 0; i< MAX_I2OB_DEPTH; i++)	{		i2ob_queues[unit]->request_queue[i].next = 			&i2ob_queues[unit]->request_queue[i+1];		i2ob_queues[unit]->request_queue[i].num = i;	}		/* Queue is MAX_I2OB + 1... */	i2ob_queues[unit]->request_queue[i].next = NULL;	i2ob_queues[unit]->i2ob_qhead = &i2ob_queues[unit]->request_queue[0];	atomic_set(&i2ob_queues[unit]->queue_depth, 0);	blk_init_queue(&i2ob_queues[unit]->req_queue, i2ob_request);	blk_queue_headactive(&i2ob_queues[unit]->req_queue, 0);	i2ob_queues[unit]->req_queue.back_merge_fn = i2ob_back_merge;	i2ob_queues[unit]->req_queue.front_merge_fn = i2ob_front_merge;	i2ob_queues[unit]->req_queue.merge_requests_fn = i2ob_merge_requests;	i2ob_queues[unit]->req_queue.queuedata = &i2ob_queues[unit];	return 0;}/* * Get the request queue for the given device. */	static request_queue_t* i2ob_get_queue(kdev_t dev){	int unit = MINOR(dev)&0xF0;	return i2ob_dev[unit].req_queue;}/* * Probe the I2O subsytem for block class devices */static void i2ob_probe(void){	int i;	int unit = 0;	int warned = 0;			for(i=0; i< MAX_I2O_CONTROLLERS; i++)	{		struct i2o_controller *c=i2o_find_controller(i);		struct i2o_device *d;			if(c==NULL)			continue;		for(d=c->devices;d!=NULL;d=d->next)		{			if(d->lct_data.class_id!=I2O_CLASS_RANDOM_BLOCK_STORAGE)				continue;			if(d->lct_data.user_tid != 0xFFF)				continue;			if(i2o_claim_device(d, &i2o_block_handler))			{				printk(KERN_WARNING "i2o_block: Controller %d, TID %d\n", c->unit,					d->lct_data.tid);				printk(KERN_WARNING "\tDevice refused claim! Skipping installation\n");				continue;			}			if(unit<MAX_I2OB<<4)			{ 				/*				 * Get the device and fill in the				 * Tid and controller.				 */				struct i2ob_device *dev=&i2ob_dev[unit];				dev->i2odev = d; 				dev->controller = c;				dev->unit = c->unit;				dev->tid = d->lct_data.tid;				if(i2ob_install_device(c,d,unit))					printk(KERN_WARNING "Could not install I2O block device\n");				else				{					unit+=16;					i2ob_dev_count++;					/* We want to know when device goes away */					i2o_device_notify_on(d, &i2o_block_handler);				}			}			else			{				if(!warned++)					printk(KERN_WARNING "i2o_block: too many device, registering only %d.\n", unit>>4);			}			i2o_release_device(d, &i2o_block_handler);		}		i2o_unlock_controller(c);	}}/* * New device notification handler.  Called whenever a new * I2O block storage device is added to the system. *  * Should we spin lock around this to keep multiple devs from  * getting updated at the same time?  *  */void i2ob_new_device(struct i2o_controller *c, struct i2o_device *d){	struct i2ob_device *dev;	int unit = 0;	printk(KERN_INFO "i2o_block: New device detected\n");	printk(KERN_INFO "   Controller %d Tid %d\n",c->unit, d->lct_data.tid);	/* Check for available space */	if(i2ob_dev_count>=MAX_I2OB<<4)	{		printk(KERN_ERR "i2o_block: No more devices allowed!\n");		return;	}	for(unit = 0; unit < (MAX_I2OB<<4); unit += 16)	{		if(!i2ob_dev[unit].i2odev)			break;	}	/*	 * Creating a RAID 5 volume takes a little while and the UTIL_CLAIM	 * will fail if we don't give the card enough time to do it's magic, 	 * so we just sleep for a little while and let it do it's thing	 */	current->state = TASK_INTERRUPTIBLE;	schedule_timeout(3*HZ);	if(i2o_claim_device(d, &i2o_block_handler))	{		printk(KERN_INFO 			"i2o_block: Unable to claim device. Installation aborted\n");		return;	}	dev = &i2ob_dev[unit];	dev->i2odev = d; 	dev->controller = c;	dev->tid = d->lct_data.tid;	if(i2ob_install_device(c,d,unit))		printk(KERN_ERR "i2o_block: Could not install new device\n");	else		{		i2ob_dev_count++;		i2o_device_notify_on(d, &i2o_block_handler);	}	i2o_release_device(d, &i2o_block_handler); 	return;}/* * Deleted device notification handler.  Called when a device we * are talking to has been deleted by the user or some other * mysterious fource outside the kernel. */void i2ob_del_device(struct i2o_controller *c, struct i2o_device *d){		int unit = 0;	int i = 0;	int flags;	spin_lock_irqsave(&io_request_lock, flags);	/*	 * Need to do this...we somtimes get two events from the IRTOS	 * in a row and that causes lots of problems.	 */	i2o_device_notify_off(d, &i2o_block_handler);	printk(KERN_INFO "I2O Block Device Deleted\n");	for(unit = 0; unit < MAX_I2OB<<4; unit += 16)	{		if(i2ob_dev[unit].i2odev == d)		{			printk(KERN_INFO "  /dev/%s: Controller %d Tid %d\n", 				d->dev_name, c->unit, d->lct_data.tid);			break;		}	}	if(unit >= MAX_I2OB<<4)	{		printk(KERN_ERR "i2ob_del_device called, but not in dev table!\n");		return;	}	/* 	 * This will force errors when i2ob_get_queue() is called	 * by the kenrel.	 */	i2ob_dev[unit].req_queue = NULL;	for(i = unit; i <= unit+15; i++)	{		i2ob_dev[i].i2odev = NULL;		i2ob_sizes[i] = 0;		i2ob_hardsizes[i] = 0;		i2ob_max_sectors[i] = 0;		i2ob[i].nr_sects = 0;		i2ob_gendisk.part[i].nr_sects = 0;	}	spin_unlock_irqrestore(&io_request_lock, flags);	/*	 * Sync the device...this will force all outstanding I/Os	 * to attempt to complete, thus causing error messages.	 * We have to do this as the user could immediatelly create	 * a new volume that gets assigned the same minor number.	 * If there are still outstanding writes to the device,	 * that could cause data corruption on the new volume!	 *	 * The truth is that deleting a volume that you are currently	 * accessing will do _bad things_ to your system.  This 	 * handler will keep it from crashing, but must probably 	 * you'll have to do a 'reboot' to get the system running	 * properly.  Deleting disks you are using is dumb.  	 * Umount them first and all will be good!	 *	 * It's not this driver's job to protect the system from	 * dumb user mistakes :)	 */	if(i2ob_dev[unit].refcnt)		fsync_dev(MKDEV(MAJOR_NR,unit));	/*	 * Decrease usage count for module	 */		while(i2ob_dev[unit].refcnt--)		MOD_DEC_USE_COUNT;	i2ob_dev[unit].refcnt = 0;		i2ob_dev[i].tid = 0;	/* 	 * Do we need this?	 * The media didn't really change...the device is just gone	 */	i2ob_media_change_flag[unit] = 1;	i2ob_dev_count--;		return;}/* *	Have we seen a media change ? */static int i2ob_media_change(kdev_t dev){	int i=MINOR(dev);	i>>=4;	if(i2ob_media_change_flag[i])	{		i2ob_media_change_flag[i]=0;		return 1;	}	return 0;}static int i2ob_revalidate(kdev_t dev){	return do_i2ob_revalidate(dev, 0);}/* * Reboot notifier.  This is called by i2o_core when the system * shuts down. */static void i2ob_reboot_event(void){	int i;		for(i=0;i<MAX_I2OB;i++)	{		struct i2ob_device *dev=&i2ob_dev[(i<<4)];				if(dev->refcnt!=0)		{			/*			 *	Flush the onboard cache			 */			u32 msg[5];			int *query_done = &dev->done_flag;			msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;			msg[1] = I2O_CMD_BLOCK_CFLUSH<<24|HOST_TID<<12|dev->tid;			msg[2] = i2ob_context|0x40000000;			msg[3] = (u32)query_done;			msg[4] = 60<<16;			i2o_post_wait(dev->controller, msg, 20, 2);			/*			 *	Unlock the media			 */			msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;			msg[1] = I2O_CMD_BLOCK_MUNLOCK<<24|HOST_TID<<12|dev->tid;			msg[2] = i2ob_context|0x40000000;			msg[3] = (u32)query_done;			msg[4] = -1;			i2o_post_wait(dev->controller, msg, 20, 2);		}	}	}static struct block_device_operations i2ob_fops ={   open:       i2ob_open,   release:    i2ob_release,   ioctl:         i2ob_ioctl,   check_media_change:  i2ob_media_change,   revalidate:    i2ob_revalidate,};static struct gendisk i2ob_gendisk = {	MAJOR_NR,	"i2o/hd",	4,	1<<4,	i2ob,	i2ob_sizes,	0,	NULL,	NULL};/* * And here should be modules and kernel interface  *  (Just smiley confuses emacs :-) */#ifdef MODULE#define i2o_block_init init_module#endifint i2o_block_init(void){	int i;	printk(KERN_INFO "I2O Block Storage OSM v0.9\n");	printk(KERN_INFO "   (c) Copyright 1999, 2000 Red Hat Software.\n");		/*	 *	Register the block device interfaces	 */	if (register_blkdev(MAJOR_NR, "i2o_block", &i2ob_fops)) {		printk(KERN_ERR "Unable to get major number %d for i2o_block\n",		       MAJOR_NR);		return -EIO;	}#ifdef MODULE	printk(KERN_INFO "i2o_block: registered device at major %d\n", MAJOR_NR);#endif	/*	 *	Now fill in the boiler plate	 */	 	blksize_size[MAJOR_NR] = i2ob_blksizes;	hardsect_size[MAJOR_NR] = i2ob_hardsizes;	blk_size[MAJOR_NR] = i2ob_sizes;	max_sectors[MAJOR_NR] = i2ob_max_sectors;	blk_dev[MAJOR_NR].queue = i2ob_get_queue;		blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), i2ob_request);	blk_queue_headactive(BLK_DEFAULT_QUEUE(MAJOR_NR), 0);	for (i = 0; i < MAX_I2OB << 4; i++) {		i2ob_dev[i].refcnt = 0;		i2ob_dev[i].flags = 0;		i2ob_dev[i].controller = NULL;		i2ob_dev[i].i2odev = NULL;		i2ob_dev[i].tid = 0;		i2ob_dev[i].head = NULL;		i2ob_dev[i].tail = NULL;		i2ob_blksizes[i] = 1024;		i2ob_max_sectors[i] = 2;	}		/*	 *	Set up the queue	 */	for(i = 0; i < MAX_I2O_CONTROLLERS; i++)	{		i2ob_queues[i] = NULL;	}	/*	 *	Timers	 */	 	init_timer(&i2ob_timer);	i2ob_timer.function = i2ob_timer_handler;	i2ob_timer.data = 0;		/*	 *	Register the OSM handler as we will need this to probe for	 *	drives, geometry and other goodies.	 */	if(i2o_install_handler(&i2o_block_handler)<0)	{		unregister_blkdev(MAJOR_NR, "i2o_block");		blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));		printk(KERN_ERR "i2o_block: unable to register OSM.\n");		return -EINVAL;	}	i2ob_context = i2o_block_handler.context;	 	/*	 * Initialize event handling thread	 */	init_MUTEX_LOCKED(&i2ob_evt_sem);	evt_pid = kernel_thread(i2ob_evt, NULL, CLONE_SIGHAND);	if(evt_pid < 0)	{		printk(KERN_ERR 			"i2o_block: Could not initialize event thread.  Aborting\n");		i2o_remove_handler(&i2o_block_handler);		return 0;	}	/*	 *	Finally see what is actually plugged in to our controllers	 */	for (i = 0; i < MAX_I2OB; i++)		register_disk(&i2ob_gendisk, MKDEV(MAJOR_NR,i<<4), 1<<4,			&i2ob_fops, 0);	i2ob_probe();		return 0;}#ifdef MODULEEXPORT_NO_SYMBOLS;MODULE_AUTHOR("Red Hat Software");MODULE_DESCRIPTION("I2O Block Device OSM");void cleanup_module(void){	struct gendisk **gdp;	int i;		/*	 * Unregister for updates from any devices..otherwise we still	 * get them and the core jumps to random memory :O	 */	if(i2ob_dev_count) {		struct i2o_device *d;		for(i = 0; i < MAX_I2OB; i++)		if((d=i2ob_dev[i<<4].i2odev)) {			i2o_device_notify_off(d, &i2o_block_handler);			i2o_event_register(d->controller, d->lct_data.tid, 				i2ob_context, i<<4, 0);		}	}		/*	 *	Flush the OSM	 */	i2o_remove_handler(&i2o_block_handler);		 	/*	 *	Return the block device	 */	if (unregister_blkdev(MAJOR_NR, "i2o_block") != 0)		printk("i2o_block: cleanup_module failed\n");	/*	 * free request queue	 */	blk_cleanup_queue(BLK_DEFAULT_QUEUE(MAJOR_NR));	if(evt_running) {		i = kill_proc(evt_pid, SIGTERM, 1);		if(!i) {			int count = 5 * 100;			while(evt_running && --count) {				current->state = TASK_INTERRUPTIBLE;				schedule_timeout(1);			}				if(!count)				printk(KERN_ERR "Giving up on i2oblock thread...\n");			}	}	/*	 *	Why isnt register/unregister gendisk in the kernel ???	 */	for (gdp = &gendisk_head; *gdp; gdp = &((*gdp)->next))		if (*gdp == &i2ob_gendisk)			break;}#endif

⌨️ 快捷键说明

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