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

📄 i2o_scsi.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 2 页
字号:
 */static void i2o_scsi_notify_device_remove(struct i2o_device *i2o_dev){	switch (i2o_dev->lct_data.class_id) {	case I2O_CLASS_EXECUTIVE:	case I2O_CLASS_RANDOM_BLOCK_STORAGE:		i2o_scsi_remove(&i2o_dev->device);		break;	default:		break;	}};/** *	i2o_scsi_notify_controller_add - Retrieve notifications of added *					 controllers *	@c: the controller which was added * *	If a I2O controller is added, we catch the notification to add a *	corresponding Scsi_Host. */static void i2o_scsi_notify_controller_add(struct i2o_controller *c){	struct i2o_scsi_host *i2o_shost;	int rc;	i2o_shost = i2o_scsi_host_alloc(c);	if (IS_ERR(i2o_shost)) {		osm_err("Could not initialize SCSI host\n");		return;	}	rc = scsi_add_host(i2o_shost->scsi_host, &c->device);	if (rc) {		osm_err("Could not add SCSI host\n");		scsi_host_put(i2o_shost->scsi_host);		return;	}	c->driver_data[i2o_scsi_driver.context] = i2o_shost;	osm_debug("new I2O SCSI host added\n");};/** *	i2o_scsi_notify_controller_remove - Retrieve notifications of removed *					    controllers *	@c: the controller which was removed * *	If a I2O controller is removed, we catch the notification to remove the *	corresponding Scsi_Host. */static void i2o_scsi_notify_controller_remove(struct i2o_controller *c){	struct i2o_scsi_host *i2o_shost;	i2o_shost = i2o_scsi_get_host(c);	if (!i2o_shost)		return;	c->driver_data[i2o_scsi_driver.context] = NULL;	scsi_remove_host(i2o_shost->scsi_host);	scsi_host_put(i2o_shost->scsi_host);	osm_debug("I2O SCSI host removed\n");};/* SCSI OSM driver struct */static struct i2o_driver i2o_scsi_driver = {	.name = OSM_NAME,	.reply = i2o_scsi_reply,	.classes = i2o_scsi_class_id,	.notify_device_add = i2o_scsi_notify_device_add,	.notify_device_remove = i2o_scsi_notify_device_remove,	.notify_controller_add = i2o_scsi_notify_controller_add,	.notify_controller_remove = i2o_scsi_notify_controller_remove,	.driver = {		   .probe = i2o_scsi_probe,		   .remove = i2o_scsi_remove,		   },};/** *	i2o_scsi_queuecommand - queue a SCSI command *	@SCpnt: scsi command pointer *	@done: callback for completion * *	Issue a scsi command asynchronously. Return 0 on success or 1 if *	we hit an error (normally message queue congestion). The only *	minor complication here is that I2O deals with the device addressing *	so we have to map the bus/dev/lun back to an I2O handle as well *	as faking absent devices ourself. * *	Locks: takes the controller lock on error path only */static int i2o_scsi_queuecommand(struct scsi_cmnd *SCpnt,				 void (*done) (struct scsi_cmnd *)){	struct i2o_controller *c;	struct i2o_device *i2o_dev;	int tid;	struct i2o_message __iomem *msg;	u32 m;	/*	 * ENABLE_DISCONNECT	 * SIMPLE_TAG	 * RETURN_SENSE_DATA_IN_REPLY_MESSAGE_FRAME	 */	u32 scsi_flags = 0x20a00000;	u32 sgl_offset;	u32 __iomem *mptr;	u32 cmd = I2O_CMD_SCSI_EXEC << 24;	int rc = 0;	/*	 *      Do the incoming paperwork	 */	i2o_dev = SCpnt->device->hostdata;	c = i2o_dev->iop;	SCpnt->scsi_done = done;	if (unlikely(!i2o_dev)) {		osm_warn("no I2O device in request\n");		SCpnt->result = DID_NO_CONNECT << 16;		done(SCpnt);		goto exit;	}	tid = i2o_dev->lct_data.tid;	osm_debug("qcmd: Tid = %03x\n", tid);	osm_debug("Real scsi messages.\n");	/*	 *      Put together a scsi execscb message	 */	switch (SCpnt->sc_data_direction) {	case PCI_DMA_NONE:		/* DATA NO XFER */		sgl_offset = SGL_OFFSET_0;		break;	case PCI_DMA_TODEVICE:		/* DATA OUT (iop-->dev) */		scsi_flags |= 0x80000000;		sgl_offset = SGL_OFFSET_10;		break;	case PCI_DMA_FROMDEVICE:		/* DATA IN  (iop<--dev) */		scsi_flags |= 0x40000000;		sgl_offset = SGL_OFFSET_10;		break;	default:		/* Unknown - kill the command */		SCpnt->result = DID_NO_CONNECT << 16;		done(SCpnt);		goto exit;	}	/*	 *      Obtain an I2O message. If there are none free then	 *      throw it back to the scsi layer	 */	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);	if (m == I2O_QUEUE_EMPTY) {		rc = SCSI_MLQUEUE_HOST_BUSY;		goto exit;	}	mptr = &msg->body[0];#ifdef CONFIG_I2O_EXT_ADAPTEC	if (c->adaptec) {		u32 adpt_flags = 0;		if (SCpnt->sc_request && SCpnt->sc_request->upper_private_data) {			i2o_sg_io_hdr_t __user *usr_ptr =			    ((Sg_request *) (SCpnt->sc_request->					     upper_private_data))->header.			    usr_ptr;			if (usr_ptr)				get_user(adpt_flags, &usr_ptr->flags);		}		switch (i2o_dev->lct_data.class_id) {		case I2O_CLASS_EXECUTIVE:		case I2O_CLASS_RANDOM_BLOCK_STORAGE:			/* interpret flag has to be set for executive */			adpt_flags ^= I2O_DPT_SG_FLAG_INTERPRET;			break;		default:			break;		}		/*		 * for Adaptec controllers we use the PRIVATE command, because		 * the normal SCSI EXEC doesn't support all SCSI commands on		 * all controllers (for example READ CAPACITY).		 */		if (sgl_offset == SGL_OFFSET_10)			sgl_offset = SGL_OFFSET_12;		cmd = I2O_CMD_PRIVATE << 24;		writel(I2O_VENDOR_DPT << 16 | I2O_CMD_SCSI_EXEC, mptr++);		writel(adpt_flags | tid, mptr++);	}#endif	writel(cmd | HOST_TID << 12 | tid, &msg->u.head[1]);	writel(i2o_scsi_driver.context, &msg->u.s.icntxt);	/* We want the SCSI control block back */	writel(i2o_cntxt_list_add(c, SCpnt), &msg->u.s.tcntxt);	/* LSI_920_PCI_QUIRK	 *	 *      Intermittant observations of msg frame word data corruption	 *      observed on msg[4] after:	 *        WRITE, READ-MODIFY-WRITE	 *      operations.  19990606 -sralston	 *	 *      (Hence we build this word via tag. Its good practice anyway	 *       we don't want fetches over PCI needlessly)	 */	/* Attach tags to the devices */	/* FIXME: implement	   if(SCpnt->device->tagged_supported) {	   if(SCpnt->tag == HEAD_OF_QUEUE_TAG)	   scsi_flags |= 0x01000000;	   else if(SCpnt->tag == ORDERED_QUEUE_TAG)	   scsi_flags |= 0x01800000;	   }	 */	writel(scsi_flags | SCpnt->cmd_len, mptr++);	/* Write SCSI command into the message - always 16 byte block */	memcpy_toio(mptr, SCpnt->cmnd, 16);	mptr += 4;	if (sgl_offset != SGL_OFFSET_0) {		/* write size of data addressed by SGL */		writel(SCpnt->request_bufflen, mptr++);		/* Now fill in the SGList and command */		if (SCpnt->use_sg) {			if (!i2o_dma_map_sg(c, SCpnt->request_buffer,					    SCpnt->use_sg,					    SCpnt->sc_data_direction, &mptr))				goto nomem;		} else {			SCpnt->SCp.dma_handle =			    i2o_dma_map_single(c, SCpnt->request_buffer,					       SCpnt->request_bufflen,					       SCpnt->sc_data_direction, &mptr);			if (dma_mapping_error(SCpnt->SCp.dma_handle))				goto nomem;		}	}	/* Stick the headers on */	writel(I2O_MESSAGE_SIZE(mptr - &msg->u.head[0]) | sgl_offset,	       &msg->u.head[0]);	/* Queue the message */	i2o_msg_post(c, m);	osm_debug("Issued %ld\n", SCpnt->serial_number);	return 0;      nomem:	rc = -ENOMEM;	i2o_msg_nop(c, m);      exit:	return rc;};/** *	i2o_scsi_abort - abort a running command *	@SCpnt: command to abort * *	Ask the I2O controller to abort a command. This is an asynchrnous *	process and our callback handler will see the command complete with an *	aborted message if it succeeds. * *	Returns 0 if the command is successfully aborted or negative error code *	on failure. */static int i2o_scsi_abort(struct scsi_cmnd *SCpnt){	struct i2o_device *i2o_dev;	struct i2o_controller *c;	struct i2o_message __iomem *msg;	u32 m;	int tid;	int status = FAILED;	osm_warn("Aborting command block.\n");	i2o_dev = SCpnt->device->hostdata;	c = i2o_dev->iop;	tid = i2o_dev->lct_data.tid;	m = i2o_msg_get_wait(c, &msg, I2O_TIMEOUT_MESSAGE_GET);	if (m == I2O_QUEUE_EMPTY)		return SCSI_MLQUEUE_HOST_BUSY;	writel(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0, &msg->u.head[0]);	writel(I2O_CMD_SCSI_ABORT << 24 | HOST_TID << 12 | tid,	       &msg->u.head[1]);	writel(i2o_cntxt_list_get_ptr(c, SCpnt), &msg->body[0]);	if (!i2o_msg_post_wait(c, msg, I2O_TIMEOUT_SCSI_SCB_ABORT))		status = SUCCESS;	return status;}/** *	i2o_scsi_bios_param	-	Invent disk geometry *	@sdev: scsi device *	@dev: block layer device *	@capacity: size in sectors *	@ip: geometry array * *	This is anyones guess quite frankly. We use the same rules everyone *	else appears to and hope. It seems to work. */static int i2o_scsi_bios_param(struct scsi_device *sdev,			       struct block_device *dev, sector_t capacity,			       int *ip){	int size;	size = capacity;	ip[0] = 64;		/* heads                        */	ip[1] = 32;		/* sectors                      */	if ((ip[2] = size >> 11) > 1024) {	/* cylinders, test for big disk */		ip[0] = 255;	/* heads                        */		ip[1] = 63;	/* sectors                      */		ip[2] = size / (255 * 63);	/* cylinders                    */	}	return 0;}static struct scsi_host_template i2o_scsi_host_template = {	.proc_name = OSM_NAME,	.name = OSM_DESCRIPTION,	.info = i2o_scsi_info,	.queuecommand = i2o_scsi_queuecommand,	.eh_abort_handler = i2o_scsi_abort,	.bios_param = i2o_scsi_bios_param,	.can_queue = I2O_SCSI_CAN_QUEUE,	.sg_tablesize = 8,	.cmd_per_lun = 6,	.use_clustering = ENABLE_CLUSTERING,};/** *	i2o_scsi_init - SCSI OSM initialization function * *	Register SCSI OSM into I2O core. * *	Returns 0 on success or negative error code on failure. */static int __init i2o_scsi_init(void){	int rc;	printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");	/* Register SCSI OSM into I2O core */	rc = i2o_driver_register(&i2o_scsi_driver);	if (rc) {		osm_err("Could not register SCSI driver\n");		return rc;	}	return 0;};/** *	i2o_scsi_exit - SCSI OSM exit function * *	Unregisters SCSI OSM from I2O core. */static void __exit i2o_scsi_exit(void){	/* Unregister I2O SCSI OSM from I2O core */	i2o_driver_unregister(&i2o_scsi_driver);};MODULE_AUTHOR("Red Hat Software");MODULE_LICENSE("GPL");MODULE_DESCRIPTION(OSM_DESCRIPTION);MODULE_VERSION(OSM_VERSION);module_init(i2o_scsi_init);module_exit(i2o_scsi_exit);

⌨️ 快捷键说明

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