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

📄 i2o_block.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
 *	delayed_request: the delayed request with the queue to start * *	If the request queue is stopped for a disk, and there is no open *	request, a new event is created, which calls this function to start *	the queue after I2O_BLOCK_REQUEST_TIME. Otherwise the queue will never *	be started again. */static void i2o_block_delayed_request_fn(void *delayed_request){	struct i2o_block_delayed_request *dreq = delayed_request;	struct request_queue *q = dreq->queue;	unsigned long flags;	spin_lock_irqsave(q->queue_lock, flags);	blk_start_queue(q);	spin_unlock_irqrestore(q->queue_lock, flags);	kfree(dreq);};/** *	i2o_block_end_request - Post-processing of completed commands *	@req: request which should be completed *	@uptodate: 1 for success, 0 for I/O error, < 0 for specific error *	@nr_bytes: number of bytes to complete * *	Mark the request as complete. The lock must not be held when entering. * */static void i2o_block_end_request(struct request *req, int uptodate,				  int nr_bytes){	struct i2o_block_request *ireq = req->special;	struct i2o_block_device *dev = ireq->i2o_blk_dev;	request_queue_t *q = req->q;	unsigned long flags;	if (end_that_request_chunk(req, uptodate, nr_bytes)) {		int leftover = (req->hard_nr_sectors << KERNEL_SECTOR_SHIFT);		if (blk_pc_request(req))			leftover = req->data_len;		if (end_io_error(uptodate))			end_that_request_chunk(req, 0, leftover);	}	add_disk_randomness(req->rq_disk);	spin_lock_irqsave(q->queue_lock, flags);	end_that_request_last(req);	if (likely(dev)) {		dev->open_queue_depth--;		list_del(&ireq->queue);	}	blk_start_queue(q);	spin_unlock_irqrestore(q->queue_lock, flags);	i2o_block_sglist_free(ireq);	i2o_block_request_free(ireq);};/** *	i2o_block_reply - Block OSM reply handler. *	@c: I2O controller from which the message arrives *	@m: message id of reply *	qmsg: the actuall I2O message reply * *	This function gets all the message replies. * */static int i2o_block_reply(struct i2o_controller *c, u32 m,			   struct i2o_message *msg){	struct request *req;	int uptodate = 1;	req = i2o_cntxt_list_get(c, le32_to_cpu(msg->u.s.tcntxt));	if (unlikely(!req)) {		osm_err("NULL reply received!\n");		return -1;	}	/*	 *      Lets see what is cooking. We stuffed the	 *      request in the context.	 */	if ((le32_to_cpu(msg->body[0]) >> 24) != 0) {		u32 status = le32_to_cpu(msg->body[0]);		/*		 *      Device not ready means two things. One is that the		 *      the thing went offline (but not a removal media)		 *		 *      The second is that you have a SuperTrak 100 and the		 *      firmware got constipated. Unlike standard i2o card		 *      setups the supertrak returns an error rather than		 *      blocking for the timeout in these cases.		 *		 *      Don't stick a supertrak100 into cache aggressive modes		 */		osm_err("TID %03x error status: 0x%02x, detailed status: "			"0x%04x\n", (le32_to_cpu(msg->u.head[1]) >> 12 & 0xfff),			status >> 24, status & 0xffff);		req->errors++;		uptodate = 0;	}	i2o_block_end_request(req, uptodate, le32_to_cpu(msg->body[1]));	return 1;};static void i2o_block_event(struct i2o_event *evt){	osm_debug("event received\n");	kfree(evt);};/* *	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;}/** *	i2o_block_open - Open the block device * *	Power up the device, mount and lock the media. This function is called, *	if the block device is opened for access. * *	Returns 0 on success or negative error code on failure. */static int i2o_block_open(struct inode *inode, struct file *file){	struct i2o_block_device *dev = inode->i_bdev->bd_disk->private_data;	if (!dev->i2o_dev)		return -ENODEV;	if (dev->power > 0x1f)		i2o_block_device_power(dev, 0x02);	i2o_block_device_mount(dev->i2o_dev, -1);	i2o_block_device_lock(dev->i2o_dev, -1);	osm_debug("Ready.\n");	return 0;};/** *	i2o_block_release - Release the I2O block device * *	Unlock and unmount the media, and power down the device. Gets called if *	the block device is closed. * *	Returns 0 on success or negative error code on failure. */static int i2o_block_release(struct inode *inode, struct file *file){	struct gendisk *disk = inode->i_bdev->bd_disk;	struct i2o_block_device *dev = disk->private_data;	u8 operation;	/*	 * 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->i2o_dev)		return 0;	i2o_block_device_flush(dev->i2o_dev);	i2o_block_device_unlock(dev->i2o_dev, -1);	if (dev->flags & (1 << 3 | 1 << 4))	/* Removable */		operation = 0x21;	else		operation = 0x24;	i2o_block_device_power(dev, operation);	return 0;}/** *	i2o_block_ioctl - Issue device specific ioctl calls. *	@cmd: ioctl command *	@arg: arg * *	Handles ioctl request for the block device. * *	Return 0 on success or negative error on failure. */static int i2o_block_ioctl(struct inode *inode, struct file *file,			   unsigned int cmd, unsigned long arg){	struct gendisk *disk = inode->i_bdev->bd_disk;	struct i2o_block_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 *)arg);	case BLKI2OGWSTRAT:		return put_user(dev->wcache, (int __user *)arg);	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;};/** *	i2o_block_media_changed - Have we seen a media change? *	@disk: gendisk which should be verified * *	Verifies if the media has changed. * *	Returns 1 if the media was changed or 0 otherwise. */static int i2o_block_media_changed(struct gendisk *disk){	struct i2o_block_device *p = disk->private_data;	if (p->media_change_flag) {		p->media_change_flag = 0;		return 1;	}	return 0;}/** *	i2o_block_transfer - Transfer a request to/from the I2O controller *	@req: the request which should be transfered * *	This function converts the request into a I2O message. The necessary *	DMA buffers are allocated and after everything is setup post the message *	to the I2O controller. No cleanup is done by this function. It is done *	on the interrupt side when the reply arrives. * *	Return 0 on success or negative error code on failure. */static int i2o_block_transfer(struct request *req){	struct i2o_block_device *dev = req->rq_disk->private_data;	struct i2o_controller *c;	int tid = dev->i2o_dev->lct_data.tid;	struct i2o_message __iomem *msg;	u32 __iomem *mptr;	struct i2o_block_request *ireq = req->special;	u32 m;	u32 tcntxt;	u32 sgl_offset = SGL_OFFSET_8;	u32 ctl_flags = 0x00000000;	int rc;	u32 cmd;	if (unlikely(!dev->i2o_dev)) {		osm_err("transfer to removed drive\n");		rc = -ENODEV;		goto exit;	}	c = dev->i2o_dev->iop;	m = i2o_msg_get(c, &msg);	if (m == I2O_QUEUE_EMPTY) {		rc = -EBUSY;		goto exit;	}	tcntxt = i2o_cntxt_list_add(c, req);	if (!tcntxt) {		rc = -ENOMEM;		goto nop_msg;	}	writel(i2o_block_driver.context, &msg->u.s.icntxt);	writel(tcntxt, &msg->u.s.tcntxt);	mptr = &msg->body[0];	if (rq_data_dir(req) == READ) {		cmd = I2O_CMD_BLOCK_READ << 24;		switch (dev->rcache) {		case CACHE_PREFETCH:			ctl_flags = 0x201F0008;			break;		case CACHE_SMARTFETCH:			if (req->nr_sectors > 16)				ctl_flags = 0x201F0008;			else				ctl_flags = 0x001F0000;			break;		default:			break;		}	} else {		cmd = I2O_CMD_BLOCK_WRITE << 24;		switch (dev->wcache) {		case CACHE_WRITETHROUGH:			ctl_flags = 0x001F0008;			break;		case CACHE_WRITEBACK:			ctl_flags = 0x001F0010;			break;		case CACHE_SMARTBACK:			if (req->nr_sectors > 16)				ctl_flags = 0x001F0004;			else				ctl_flags = 0x001F0010;			break;		case CACHE_SMARTTHROUGH:			if (req->nr_sectors > 16)				ctl_flags = 0x001F0004;			else				ctl_flags = 0x001F0010;		default:			break;		}	}#ifdef CONFIG_I2O_EXT_ADAPTEC	if (c->adaptec) {		u8 cmd[10];		u32 scsi_flags;		u16 hwsec = queue_hardsect_size(req->q) >> KERNEL_SECTOR_SHIFT;		memset(cmd, 0, 10);		sgl_offset = SGL_OFFSET_12;

⌨️ 快捷键说明

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