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

📄 i2o_block.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *	Block OSM * * 	Copyright (C) 1999-2002	Red Hat Software * *	Written by Alan Cox, Building Number Three Ltd * *	This program is free software; you can redistribute it and/or modify it *	under the terms of the GNU General Public License as published by the *	Free Software Foundation; either version 2 of the License, or (at your *	option) any later version. * *	This program is distributed in the hope that it will be useful, but *	WITHOUT ANY WARRANTY; without even the implied warranty of *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU *	General Public License for more details. * *	For the purpose of avoiding doubt the preferred form of the work *	for making modifications shall be a standards compliant form such *	gzipped tar and not one requiring a proprietary or patent encumbered *	tool to unpack. * *	Fixes/additions: *		Steve Ralston: *			Multiple device handling error fixes, *			Added a queue depth. *		Alan Cox: *			FC920 has an rmw bug. Dont or in the end marker. *			Removed queue walk, fixed for 64bitness. *			Rewrote much of the code over time *			Added indirect block lists *			Handle 64K limits on many controllers *			Don't use indirects on the Promise (breaks) *			Heavily chop down the queue depths *		Deepak Saxena: *			Independent queues per IOP *			Support for dynamic device creation/deletion *			Code cleanup *	    		Support for larger I/Os through merge* functions *			(taken from DAC960 driver) *		Boji T Kannanthanam: *			Set the I2O Block devices to be detected in increasing *			order of TIDs during boot. *			Search and set the I2O block device that we boot off *			from as the first device to be claimed (as /dev/i2o/hda) *			Properly attach/detach I2O gendisk structure from the *			system gendisk list. The I2O block devices now appear in *			/proc/partitions. *		Markus Lidel <Markus.Lidel@shadowconnect.com>: *			Minor bugfixes for 2.6. */#include <linux/module.h>#include <linux/i2o.h>#include <linux/mempool.h>#include <linux/genhd.h>#include <linux/blkdev.h>#include <linux/hdreg.h>#include "i2o_block.h"#define OSM_NAME	"block-osm"#define OSM_VERSION	"1.287"#define OSM_DESCRIPTION	"I2O Block Device OSM"static struct i2o_driver i2o_block_driver;/* global Block OSM request mempool */static struct i2o_block_mempool i2o_blk_req_pool;/* Block OSM class handling definition */static struct i2o_class_id i2o_block_class_id[] = {	{I2O_CLASS_RANDOM_BLOCK_STORAGE},	{I2O_CLASS_END}};/** *	i2o_block_device_free - free the memory of the I2O Block device *	@dev: I2O Block device, which should be cleaned up * *	Frees the request queue, gendisk and the i2o_block_device structure. */static void i2o_block_device_free(struct i2o_block_device *dev){	blk_cleanup_queue(dev->gd->queue);	put_disk(dev->gd);	kfree(dev);};/** *	i2o_block_remove - remove the I2O Block device from the system again *	@dev: I2O Block device which should be removed * *	Remove gendisk from system and free all allocated memory. * *	Always returns 0. */static int i2o_block_remove(struct device *dev){	struct i2o_device *i2o_dev = to_i2o_device(dev);	struct i2o_block_device *i2o_blk_dev = dev_get_drvdata(dev);	osm_info("device removed (TID: %03x): %s\n", i2o_dev->lct_data.tid,		 i2o_blk_dev->gd->disk_name);	i2o_event_register(i2o_dev, &i2o_block_driver, 0, 0);	del_gendisk(i2o_blk_dev->gd);	dev_set_drvdata(dev, NULL);	i2o_device_claim_release(i2o_dev);	i2o_block_device_free(i2o_blk_dev);	return 0;};/** *	i2o_block_device flush - Flush all dirty data of I2O device dev *	@dev: I2O device which should be flushed * *	Flushes all dirty data on device dev. * *	Returns 0 on success or negative error code on failure. */static int i2o_block_device_flush(struct i2o_device *dev){	struct i2o_message __iomem *msg;	u32 m;	m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);	if (m == I2O_QUEUE_EMPTY)		return -ETIMEDOUT;	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);	writel(I2O_CMD_BLOCK_CFLUSH << 24 | HOST_TID << 12 | dev->lct_data.tid,	       &msg->u.head[1]);	writel(60 << 16, &msg->body[0]);	osm_debug("Flushing...\n");	return i2o_msg_post_wait(dev->iop, m, 60);};/** *	i2o_block_issue_flush - device-flush interface for block-layer *	@queue: the request queue of the device which should be flushed *	@disk: gendisk *	@error_sector: error offset * *	Helper function to provide flush functionality to block-layer. * *	Returns 0 on success or negative error code on failure. */static int i2o_block_issue_flush(request_queue_t * queue, struct gendisk *disk,				 sector_t * error_sector){	struct i2o_block_device *i2o_blk_dev = queue->queuedata;	int rc = -ENODEV;	if (likely(i2o_blk_dev))		rc = i2o_block_device_flush(i2o_blk_dev->i2o_dev);	return rc;}/** *	i2o_block_device_mount - Mount (load) the media of device dev *	@dev: I2O device which should receive the mount request *	@media_id: Media Identifier * *	Load a media into drive. Identifier should be set to -1, because the *	spec does not support any other value. * *	Returns 0 on success or negative error code on failure. */static int i2o_block_device_mount(struct i2o_device *dev, u32 media_id){	struct i2o_message __iomem *msg;	u32 m;	m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);	if (m == I2O_QUEUE_EMPTY)		return -ETIMEDOUT;	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);	writel(I2O_CMD_BLOCK_MMOUNT << 24 | HOST_TID << 12 | dev->lct_data.tid,	       &msg->u.head[1]);	writel(-1, &msg->body[0]);	writel(0, &msg->body[1]);	osm_debug("Mounting...\n");	return i2o_msg_post_wait(dev->iop, m, 2);};/** *	i2o_block_device_lock - Locks the media of device dev *	@dev: I2O device which should receive the lock request *	@media_id: Media Identifier * *	Lock media of device dev to prevent removal. The media identifier *	should be set to -1, because the spec does not support any other value. * *	Returns 0 on success or negative error code on failure. */static int i2o_block_device_lock(struct i2o_device *dev, u32 media_id){	struct i2o_message __iomem *msg;	u32 m;	m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);	if (m == I2O_QUEUE_EMPTY)		return -ETIMEDOUT;	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);	writel(I2O_CMD_BLOCK_MLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid,	       &msg->u.head[1]);	writel(-1, &msg->body[0]);	osm_debug("Locking...\n");	return i2o_msg_post_wait(dev->iop, m, 2);};/** *	i2o_block_device_unlock - Unlocks the media of device dev *	@dev: I2O device which should receive the unlocked request *	@media_id: Media Identifier * *	Unlocks the media in device dev. The media identifier should be set to *	-1, because the spec does not support any other value. * *	Returns 0 on success or negative error code on failure. */static int i2o_block_device_unlock(struct i2o_device *dev, u32 media_id){	struct i2o_message __iomem *msg;	u32 m;	m = i2o_msg_get_wait(dev->iop, &msg, I2O_TIMEOUT_MESSAGE_GET);	if (m == I2O_QUEUE_EMPTY)		return -ETIMEDOUT;	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);	writel(I2O_CMD_BLOCK_MUNLOCK << 24 | HOST_TID << 12 | dev->lct_data.tid,	       &msg->u.head[1]);	writel(media_id, &msg->body[0]);	osm_debug("Unlocking...\n");	return i2o_msg_post_wait(dev->iop, m, 2);};/** *	i2o_block_device_power - Power management for device dev *	@dev: I2O device which should receive the power management request *	@operation: Operation which should be send * *	Send a power management request to the device dev. * *	Returns 0 on success or negative error code on failure. */static int i2o_block_device_power(struct i2o_block_device *dev, u8 op){	struct i2o_device *i2o_dev = dev->i2o_dev;	struct i2o_controller *c = i2o_dev->iop;	struct i2o_message __iomem *msg;	u32 m;	int rc;	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);	if (m == I2O_QUEUE_EMPTY)		return -ETIMEDOUT;	writel(FOUR_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);	writel(I2O_CMD_BLOCK_POWER << 24 | HOST_TID << 12 | i2o_dev->lct_data.	       tid, &msg->u.head[1]);	writel(op << 24, &msg->body[0]);	osm_debug("Power...\n");	rc = i2o_msg_post_wait(c, m, 60);	if (!rc)		dev->power = op;	return rc;};/** *	i2o_block_request_alloc - Allocate an I2O block request struct * *	Allocates an I2O block request struct and initialize the list. * *	Returns a i2o_block_request pointer on success or negative error code *	on failure. */static inline struct i2o_block_request *i2o_block_request_alloc(void){	struct i2o_block_request *ireq;	ireq = mempool_alloc(i2o_blk_req_pool.pool, GFP_ATOMIC);	if (!ireq)		return ERR_PTR(-ENOMEM);	INIT_LIST_HEAD(&ireq->queue);	return ireq;};/** *	i2o_block_request_free - Frees a I2O block request *	@ireq: I2O block request which should be freed * *	Fres the allocated memory (give it back to the request mempool). */static inline void i2o_block_request_free(struct i2o_block_request *ireq){	mempool_free(ireq, i2o_blk_req_pool.pool);};/** *	i2o_block_sglist_alloc - Allocate the SG list and map it *	@c: I2O controller to which the request belongs *	@ireq: I2O block request * *	Builds the SG list and map it to be accessable by the controller. * *	Returns 0 on failure or 1 on success. */static inline int i2o_block_sglist_alloc(struct i2o_controller *c,					 struct i2o_block_request *ireq,					 u32 __iomem ** mptr){	int nents;	enum dma_data_direction direction;	ireq->dev = &c->pdev->dev;	nents = blk_rq_map_sg(ireq->req->q, ireq->req, ireq->sg_table);	if (rq_data_dir(ireq->req) == READ)		direction = PCI_DMA_FROMDEVICE;	else		direction = PCI_DMA_TODEVICE;	ireq->sg_nents = nents;	return i2o_dma_map_sg(c, ireq->sg_table, nents, direction, mptr);};/** *	i2o_block_sglist_free - Frees the SG list *	@ireq: I2O block request from which the SG should be freed * *	Frees the SG list from the I2O block request. */static inline void i2o_block_sglist_free(struct i2o_block_request *ireq){	enum dma_data_direction direction;	if (rq_data_dir(ireq->req) == READ)		direction = PCI_DMA_FROMDEVICE;	else		direction = PCI_DMA_TODEVICE;	dma_unmap_sg(ireq->dev, ireq->sg_table, ireq->sg_nents, direction);};/** *	i2o_block_prep_req_fn - Allocates I2O block device specific struct *	@q: request queue for the request *	@req: the request to prepare * *	Allocate the necessary i2o_block_request struct and connect it to *	the request. This is needed that we not loose the SG list later on. * *	Returns BLKPREP_OK on success or BLKPREP_DEFER on failure. */static int i2o_block_prep_req_fn(struct request_queue *q, struct request *req){	struct i2o_block_device *i2o_blk_dev = q->queuedata;	struct i2o_block_request *ireq;	if (unlikely(!i2o_blk_dev)) {		osm_err("block device already removed\n");		return BLKPREP_KILL;	}	/* request is already processed by us, so return */	if (req->flags & REQ_SPECIAL) {		osm_debug("REQ_SPECIAL already set!\n");		req->flags |= REQ_DONTPREP;		return BLKPREP_OK;	}	/* connect the i2o_block_request to the request */	if (!req->special) {		ireq = i2o_block_request_alloc();		if (unlikely(IS_ERR(ireq))) {			osm_debug("unable to allocate i2o_block_request!\n");			return BLKPREP_DEFER;		}		ireq->i2o_blk_dev = i2o_blk_dev;		req->special = ireq;		ireq->req = req;	} else		ireq = req->special;	/* do not come back here */	req->flags |= REQ_DONTPREP | REQ_SPECIAL;	return BLKPREP_OK;};/** *	i2o_block_delayed_request_fn - delayed request queue function

⌨️ 快捷键说明

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