i2o_block.c

来自「优龙2410linux2.6.8内核源代码」· C语言 代码 · 共 1,694 行 · 第 1/3 页

C
1,694
字号
	else		ireq->req->errors = 0;	/*	 *	Dequeue the request. We use irqsave locks as one day we	 *	may be running polled controllers from a BH...	 */		i2ob_free_sglist(dev, ireq);	spin_lock_irqsave(dev->req_queue->queue_lock, flags);	i2ob_unhook_request(ireq, c->unit);	i2ob_end_request(ireq->req);	i2ob_queues[c->unit]->queue_depth --;		/*	 *	We may be able to do more I/O	 */	 	i2ob_request(dev->gd->queue);	spin_unlock_irqrestore(dev->req_queue->queue_lock, flags);}/*  * Event handler.  Needs to be a separate thread b/c we may have * to do things like scan a partition table, or query parameters * which cannot be done from an interrupt or from a bottom half. */static int i2ob_evt(void *dummy){	unsigned int evt;	unsigned long flags;	struct i2ob_device *dev;	int unit;	//The only event that has data is the SCSI_SMART event.	struct i2o_reply {		u32 header[4];		u32 evt_indicator;		u8 ASC;		u8 ASCQ;		u16 pad;		u8 data[16];		} *evt_local;	daemonize("i2oblock");	allow_signal(SIGKILL);	evt_running = 1;	while(1)	{		if(down_interruptible(&i2ob_evt_sem))		{			evt_running = 0;			printk("exiting...");			break;		}		/*		 * Keep another CPU/interrupt from overwriting the 		 * message while we're reading it		 *		 * We stuffed the unit in the TxContext and grab the event mask		 * None of the BSA we care about events have EventData		 */		spin_lock_irqsave(&i2ob_evt_lock, flags);		evt_local = (struct i2o_reply *)evt_msg;		spin_unlock_irqrestore(&i2ob_evt_lock, flags);		unit = le32_to_cpu(evt_local->header[3]);		evt = le32_to_cpu(evt_local->evt_indicator);		dev = &i2ob_dev[unit];		switch(evt)		{			/*			 * New volume loaded on same TID, so we just re-install.			 * The TID/controller don't change as it is the same			 * I2O device.  It's just new media that we have to			 * rescan.			 */			case I2O_EVT_IND_BSA_VOLUME_LOAD:			{				i2ob_install_device(dev->i2odev->controller,					dev->i2odev, unit);				add_disk(dev->gd);				break;			}			/*			 * No media, so set all parameters to 0 and set the media			 * change flag. The I2O device is still valid, just doesn't			 * have media, so we don't want to clear the controller or			 * device pointer.			 */			case I2O_EVT_IND_BSA_VOLUME_UNLOAD:			{				struct gendisk *p = dev->gd;				blk_queue_max_sectors(dev->gd->queue, 0);				del_gendisk(p);				put_disk(p);				dev->gd = NULL;				dev->media_change_flag = 1;				break;			}			case I2O_EVT_IND_BSA_VOLUME_UNLOAD_REQ:				printk(KERN_WARNING "%s: Attempt to eject locked media\n", 					dev->i2odev->dev_name);				break;			/*			 * The capacity has changed and we are going to be			 * updating the max_sectors and other information 			 * about this disk.  We try a revalidate first. If			 * the block device is in use, we don't want to			 * do that as there may be I/Os bound for the disk			 * at the moment.  In that case we read the size 			 * from the device and update the information ourselves			 * and the user can later force a partition table			 * update through an ioctl.			 */			case I2O_EVT_IND_BSA_CAPACITY_CHANGE:			{				u64 size;	  			if(i2ob_query_device(dev, 0x0004, 0, &size, 8) !=0 )					i2ob_query_device(dev, 0x0000, 4, &size, 8);				spin_lock_irqsave(dev->req_queue->queue_lock, flags);				set_capacity(dev->gd, size>>9);				spin_unlock_irqrestore(dev->req_queue->queue_lock, flags);				break;			}			/* 			 * We got a SCSI SMART event, we just log the relevant			 * information and let the user decide what they want			 * to do with the information.			 */			case I2O_EVT_IND_BSA_SCSI_SMART:			{				char buf[16];				printk(KERN_INFO "I2O Block: %s received a SCSI SMART Event\n",dev->i2odev->dev_name);				evt_local->data[16]='\0';				sprintf(buf,"%s",&evt_local->data[0]);				printk(KERN_INFO "      Disk Serial#:%s\n",buf);				printk(KERN_INFO "      ASC 0x%02x \n",evt_local->ASC);				printk(KERN_INFO "      ASCQ 0x%02x \n",evt_local->ASCQ);				break;			}					/*			 *	Non event			 */			 			case 0:				break;							/*			 * An event we didn't ask for.  Call the card manufacturer			 * and tell them to fix their firmware :)			 */			 			case 0x20:				/*				 * If a promise card reports 0x20 event then the brown stuff				 * hit the fan big time. The card seems to recover but loses				 * the pending writes. Deeply ungood except for testing fsck				 */				if(dev->i2odev->controller->promise)					panic("I2O controller firmware failed. Reboot and force a filesystem check.\n");			default:				printk(KERN_INFO "%s: Received event 0x%X we didn't register for\n"					KERN_INFO "   Blame the I2O card manufacturer 8)\n", 					dev->i2odev->dev_name, evt);				break;		}	};	complete_and_exit(&i2ob_thread_dead,0);	return 0;}/* *	The I2O block driver is listed as one of those that pulls the *	front entry off the queue before processing it. This is important *	to remember here. If we drop the io lock then CURRENT will change *	on us. We must unlink CURRENT in this routine before we return, if *	we use it. */static void i2ob_request(request_queue_t *q){	struct request *req;	struct i2ob_request *ireq;	struct i2ob_device *dev;	u32 m;		while ((req = elv_next_request(q)) != NULL) {		dev = req->rq_disk->private_data;		/* 		 *	Queue depths probably belong with some kind of 		 *	generic IOP commit control. Certainly it's not right 		 *	its global!  		 */		if(i2ob_queues[dev->unit]->queue_depth >= dev->depth)			break;				/* Get a message */		m = i2ob_get(dev);		if(m==0xFFFFFFFF)		{			if(i2ob_queues[dev->unit]->queue_depth == 0)				printk(KERN_ERR "i2o_block: message queue and request queue empty!!\n");			break;		}		/*		 * Everything ok, so pull from kernel queue onto our queue		 */		req->errors = 0;		blkdev_dequeue_request(req);					ireq = i2ob_queues[dev->unit]->i2ob_qhead;		i2ob_queues[dev->unit]->i2ob_qhead = ireq->next;		ireq->req = req;		i2ob_send(m, dev, ireq, dev->index);	}}/* *	SCSI-CAM for ioctl geometry mapping *	Duplicated with SCSI - this should be moved into somewhere common *	perhaps genhd ? * * LBA -> CHS mapping table taken from: * * "Incorporating the I2O Architecture into BIOS for Intel Architecture  *  Platforms"  * * This is an I2O document that is only available to I2O members, * not developers. * * From my understanding, this is how all the I2O cards do this * * Disk Size      | Sectors | Heads | Cylinders * ---------------+---------+-------+------------------- * 1 < X <= 528M  | 63      | 16    | X/(63 * 16 * 512) * 528M < X <= 1G | 63      | 32    | X/(63 * 32 * 512) * 1 < X <528M    | 63      | 16    | X/(63 * 16 * 512) * 1 < X <528M    | 63      | 16    | X/(63 * 16 * 512) * */#define	BLOCK_SIZE_528M		1081344#define	BLOCK_SIZE_1G		2097152#define	BLOCK_SIZE_21G		4403200#define	BLOCK_SIZE_42G		8806400#define	BLOCK_SIZE_84G		17612800static void i2o_block_biosparam(	unsigned long capacity,	unsigned short *cyls,	unsigned char *hds,	unsigned char *secs) { 	unsigned long heads, sectors, cylinders; 	sectors = 63L;      			/* Maximize sectors per track */ 	if(capacity <= BLOCK_SIZE_528M)		heads = 16;	else if(capacity <= BLOCK_SIZE_1G)		heads = 32;	else if(capacity <= BLOCK_SIZE_21G)		heads = 64;	else if(capacity <= BLOCK_SIZE_42G)		heads = 128;	else		heads = 255;	cylinders = (unsigned long)capacity / (heads * sectors);	*cyls = (unsigned short) cylinders;	/* Stuff return values */ 	*secs = (unsigned char) sectors; 	*hds  = (unsigned char) heads; }/* *	Issue device specific ioctl calls. */static int i2ob_ioctl(struct inode *inode, struct file *file,		     unsigned int cmd, unsigned long arg){	struct gendisk *disk = inode->i_bdev->bd_disk;	struct i2ob_device *dev = disk->private_data;	void __user *argp = (void __user *)arg;	/* Anyone capable of this syscall can do *real bad* things */	if (!capable(CAP_SYS_ADMIN))		return -EPERM;	switch (cmd) {		case HDIO_GETGEO:		{			struct hd_geometry g;			i2o_block_biosparam(get_capacity(disk), 					&g.cylinders, &g.heads, &g.sectors);			g.start = get_start_sect(inode->i_bdev);			return copy_to_user(argp, &g, sizeof(g))?-EFAULT:0;		}				case BLKI2OGRSTRAT:			return put_user(dev->rcache, (int __user *)argp);		case BLKI2OGWSTRAT:			return put_user(dev->wcache, (int __user *)argp);		case BLKI2OSRSTRAT:			if(arg<0||arg>CACHE_SMARTFETCH)				return -EINVAL;			dev->rcache = arg;			break;		case BLKI2OSWSTRAT:			if(arg!=0 && (arg<CACHE_WRITETHROUGH || arg>CACHE_SMARTBACK))				return -EINVAL;			dev->wcache = arg;			break;	}	return -ENOTTY;}/* *	Close the block device down */ static int i2ob_release(struct inode *inode, struct file *file){	struct gendisk *disk = inode->i_bdev->bd_disk;	struct i2ob_device *dev = disk->private_data;	/*	 * This is to deail with the case of an application	 * opening a device and then the device dissapears while	 * it's in use, and then the application tries to release	 * it.  ex: Unmounting a deleted RAID volume at reboot. 	 * If we send messages, it will just cause FAILs since	 * the TID no longer exists.	 */	if(!dev->i2odev)		return 0;	if (dev->refcnt <= 0)		printk(KERN_ALERT "i2ob_release: refcount(%d) <= 0\n", dev->refcnt);	dev->refcnt--;	if(dev->refcnt==0)	{		/*		 *	Flush the onboard cache on unmount		 */		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;		DEBUG("Flushing...");		i2o_post_wait(dev->controller, msg, 20, 60);		/*		 *	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;		DEBUG("Unlocking...");		i2o_post_wait(dev->controller, msg, 20, 2);		DEBUG("Unlocked.\n");		msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;		msg[1] = I2O_CMD_BLOCK_POWER<<24 | HOST_TID << 12 | dev->tid;		if(dev->flags & (1<<3|1<<4))	/* Removable */			msg[4] = 0x21 << 24;		else			msg[4] = 0x24 << 24;		if(i2o_post_wait(dev->controller, msg, 20, 60)==0)			dev->power = 0x24;		/* 		 * Now unclaim the device.		 */		if (i2o_release_device(dev->i2odev, &i2o_block_handler))			printk(KERN_ERR "i2ob_release: controller rejected unclaim.\n");				DEBUG("Unclaim\n");	}	return 0;}/* *	Open the block device. */ static int i2ob_open(struct inode *inode, struct file *file){	struct gendisk *disk = inode->i_bdev->bd_disk;	struct i2ob_device *dev = disk->private_data;	if(!dev->i2odev)			return -ENODEV;		if(dev->refcnt++==0)	{ 		u32 msg[6];				DEBUG("Claim ");		if(i2o_claim_device(dev->i2odev, &i2o_block_handler))		{			dev->refcnt--;			printk(KERN_INFO "I2O Block: Could not open device\n");			return -EBUSY;		}		DEBUG("Claimed ");		/*	 	 *	Power up if needed	 	 */		if(dev->power > 0x1f)		{			msg[0] = FOUR_WORD_MSG_SIZE|SGL_OFFSET_0;			msg[1] = I2O_CMD_BLOCK_POWER<<24 | HOST_TID << 12 | dev->tid;			msg[4] = 0x02 << 24;			if(i2o_post_wait(dev->controller, msg, 20, 60) == 0)				dev->power = 0x02;		}		/*		 *	Mount the media if needed. Note that we don't use		 *	the lock bit. Since we have to issue a lock if it		 *	refuses a mount (quite possible) then we might as		 *	well just send two messages out.		 */		msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;				msg[1] = I2O_CMD_BLOCK_MMOUNT<<24|HOST_TID<<12|dev->tid;		msg[4] = -1;		msg[5] = 0;		DEBUG("Mount ");		i2o_post_wait(dev->controller, msg, 24, 2);		/*		 *	Lock the media		 */		msg[0] = FIVE_WORD_MSG_SIZE|SGL_OFFSET_0;		msg[1] = I2O_CMD_BLOCK_MLOCK<<24|HOST_TID<<12|dev->tid;		msg[4] = -1;		DEBUG("Lock ");		i2o_post_wait(dev->controller, msg, 20, 2);		DEBUG("Ready.\n");	}			return 0;}/* *	Issue a device query */ static int i2ob_query_device(struct i2ob_device *dev, int table, 	int field, void *buf, int buflen){	return i2o_query_scalar(dev->controller, dev->tid,		table, field, buf, buflen);}/* *	Install the I2O block device we found. */ static int i2ob_install_device(struct i2o_controller *c, struct i2o_device *d, int unit){	u64 size;	u32 blocksize;	u8 type;	u16 power;	u32 flags, status;	struct i2ob_device *dev=&i2ob_dev[unit];	struct gendisk *disk;	request_queue_t *q;	int segments;	/*	 * For logging purposes...	 */	printk(KERN_INFO "i2ob: Installing tid %d device at unit %d\n", 			d->lct_data.tid, 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;	}	q = i2ob_queues[c->unit]->req_queue;	/*	 * 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 = q;	/*	 * Allocate a gendisk structure and initialize it	 */	disk = alloc_disk(16);	if (!disk)		return 1;	dev->gd = disk;	/* initialize gendik structure */	disk->major = MAJOR_NR;	disk->first_minor = unit<<4;	disk->queue = q;	disk->fops = &i2ob_fops;	sprintf(disk->disk_name, "i2o/hd%c", 'a' + unit);	disk->private_data = dev;	/*	 *	Ask for the current media data. If that isn't supported	 *	then we ask for the device capacity data	 */	if(i2ob_query_device(dev, 0x0004, 1, &blocksize, 4) != 0	  || i2ob_query_device(dev, 0x0004, 0, &size, 8) !=0 )	{		i2ob_query_device(dev, 0x0000, 3, &blocksize, 4);		i2ob_query_device(dev, 0x0000, 4, &size, 8);	}		if(i2ob_query_device(dev, 0x0000, 2, &power, 2)!=0)		power = 0;	i2ob_query_device(dev, 0x0000, 5, &flags, 4);	i2ob_query_device(dev, 0x0000, 6, &status, 4);	set_capacity(disk, size>>9);	/*	 * Max number of Scatter-Gather Elements	 */		dev->power = power;	/* Save power state in device proper */	dev->flags = flags;	segments = (d->controller->status_block->inbound_frame_size - 7) / 2;	if(segments > 16)

⌨️ 快捷键说明

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