iop.c

来自「linux 内核源代码」· C语言 代码 · 共 1,249 行 · 第 1/3 页

C
1,249
字号
	}	/* Header + IOPs */	i2o_systab.len = sizeof(struct i2o_sys_tbl) + num_controllers *	    sizeof(struct i2o_sys_tbl_entry);	systab = i2o_systab.virt = kzalloc(i2o_systab.len, GFP_KERNEL);	if (!systab) {		osm_err("unable to allocate memory for System Table\n");		return -ENOMEM;	}	systab->version = I2OVERSION;	systab->change_ind = change_ind + 1;	list_for_each_entry_safe(c, tmp, &i2o_controllers, list) {		i2o_status_block *sb;		if (count >= num_controllers) {			osm_err("controller added while building system table"				"\n");			break;		}		sb = c->status_block.virt;		/*		 * Get updated IOP state so we have the latest information		 *		 * We should delete the controller at this point if it		 * doesn't respond since if it's not on the system table		 * it is techninically not part of the I2O subsystem...		 */		if (unlikely(i2o_status_get(c))) {			osm_err("%s: Deleting b/c could not get status while "				"attempting to build system table\n", c->name);			i2o_iop_remove(c);			continue;	// try the next one		}		systab->iops[count].org_id = sb->org_id;		systab->iops[count].iop_id = c->unit + 2;		systab->iops[count].seg_num = 0;		systab->iops[count].i2o_version = sb->i2o_version;		systab->iops[count].iop_state = sb->iop_state;		systab->iops[count].msg_type = sb->msg_type;		systab->iops[count].frame_size = sb->inbound_frame_size;		systab->iops[count].last_changed = change_ind;		systab->iops[count].iop_capabilities = sb->iop_capabilities;		systab->iops[count].inbound_low =		    i2o_dma_low(c->base.phys + I2O_IN_PORT);		systab->iops[count].inbound_high =		    i2o_dma_high(c->base.phys + I2O_IN_PORT);		count++;	}	systab->num_entries = count;	return 0;};/** *	i2o_parse_hrt - Parse the hardware resource table. *	@c: I2O controller * *	We don't do anything with it except dumping it (in debug mode). * *	Returns 0. */static int i2o_parse_hrt(struct i2o_controller *c){	i2o_dump_hrt(c);	return 0;};/** *	i2o_status_get - Get the status block from the I2O controller *	@c: I2O controller * *	Issue a status query on the controller. This updates the attached *	status block. The status block could then be accessed through *	c->status_block. * *	Returns 0 on sucess or negative error code on failure. */int i2o_status_get(struct i2o_controller *c){	struct i2o_message *msg;	volatile u8 *status_block;	unsigned long timeout;	status_block = (u8 *) c->status_block.virt;	memset(c->status_block.virt, 0, sizeof(i2o_status_block));	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);	if (IS_ERR(msg))		return PTR_ERR(msg);	msg->u.head[0] = cpu_to_le32(NINE_WORD_MSG_SIZE | SGL_OFFSET_0);	msg->u.head[1] =	    cpu_to_le32(I2O_CMD_STATUS_GET << 24 | HOST_TID << 12 |			ADAPTER_TID);	msg->u.s.icntxt = cpu_to_le32(i2o_exec_driver.context);	msg->u.s.tcntxt = cpu_to_le32(0x00000000);	msg->body[0] = cpu_to_le32(0x00000000);	msg->body[1] = cpu_to_le32(0x00000000);	msg->body[2] = cpu_to_le32(i2o_dma_low(c->status_block.phys));	msg->body[3] = cpu_to_le32(i2o_dma_high(c->status_block.phys));	msg->body[4] = cpu_to_le32(sizeof(i2o_status_block));	/* always 88 bytes */	i2o_msg_post(c, msg);	/* Wait for a reply */	timeout = jiffies + I2O_TIMEOUT_STATUS_GET * HZ;	while (status_block[87] != 0xFF) {		if (time_after(jiffies, timeout)) {			osm_err("%s: Get status timeout.\n", c->name);			return -ETIMEDOUT;		}		schedule_timeout_uninterruptible(1);	}#ifdef DEBUG	i2o_debug_state(c);#endif	return 0;}/* *	i2o_hrt_get - Get the Hardware Resource Table from the I2O controller *	@c: I2O controller from which the HRT should be fetched * *	The HRT contains information about possible hidden devices but is *	mostly useless to us. * *	Returns 0 on success or negative error code on failure. */static int i2o_hrt_get(struct i2o_controller *c){	int rc;	int i;	i2o_hrt *hrt = c->hrt.virt;	u32 size = sizeof(i2o_hrt);	struct device *dev = &c->pdev->dev;	for (i = 0; i < I2O_HRT_GET_TRIES; i++) {		struct i2o_message *msg;		msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);		if (IS_ERR(msg))			return PTR_ERR(msg);		msg->u.head[0] = cpu_to_le32(SIX_WORD_MSG_SIZE | SGL_OFFSET_4);		msg->u.head[1] =		    cpu_to_le32(I2O_CMD_HRT_GET << 24 | HOST_TID << 12 |				ADAPTER_TID);		msg->body[0] = cpu_to_le32(0xd0000000 | c->hrt.len);		msg->body[1] = cpu_to_le32(c->hrt.phys);		rc = i2o_msg_post_wait_mem(c, msg, 20, &c->hrt);		if (rc < 0) {			osm_err("%s: Unable to get HRT (status=%#x)\n", c->name,				-rc);			return rc;		}		size = hrt->num_entries * hrt->entry_len << 2;		if (size > c->hrt.len) {			if (i2o_dma_realloc(dev, &c->hrt, size, GFP_KERNEL))				return -ENOMEM;			else				hrt = c->hrt.virt;		} else			return i2o_parse_hrt(c);	}	osm_err("%s: Unable to get HRT after %d tries, giving up\n", c->name,		I2O_HRT_GET_TRIES);	return -EBUSY;}/** *	i2o_iop_release - release the memory for a I2O controller *	@dev: I2O controller which should be released * *	Release the allocated memory. This function is called if refcount of *	device reaches 0 automatically. */static void i2o_iop_release(struct device *dev){	struct i2o_controller *c = to_i2o_controller(dev);	i2o_iop_free(c);};/** *	i2o_iop_alloc - Allocate and initialize a i2o_controller struct * *	Allocate the necessary memory for a i2o_controller struct and *	initialize the lists and message mempool. * *	Returns a pointer to the I2O controller or a negative error code on *	failure. */struct i2o_controller *i2o_iop_alloc(void){	static int unit = 0;	/* 0 and 1 are NULL IOP and Local Host */	struct i2o_controller *c;	char poolname[32];	c = kzalloc(sizeof(*c), GFP_KERNEL);	if (!c) {		osm_err("i2o: Insufficient memory to allocate a I2O controller."			"\n");		return ERR_PTR(-ENOMEM);	}	c->unit = unit++;	sprintf(c->name, "iop%d", c->unit);	snprintf(poolname, sizeof(poolname), "i2o_%s_msg_inpool", c->name);	if (i2o_pool_alloc	    (&c->in_msg, poolname, I2O_INBOUND_MSG_FRAME_SIZE * 4 + sizeof(u32),	     I2O_MSG_INPOOL_MIN)) {		kfree(c);		return ERR_PTR(-ENOMEM);	};	INIT_LIST_HEAD(&c->devices);	spin_lock_init(&c->lock);	mutex_init(&c->lct_lock);	device_initialize(&c->device);	c->device.release = &i2o_iop_release;	snprintf(c->device.bus_id, BUS_ID_SIZE, "iop%d", c->unit);#if BITS_PER_LONG == 64	spin_lock_init(&c->context_list_lock);	atomic_set(&c->context_list_counter, 0);	INIT_LIST_HEAD(&c->context_list);#endif	return c;};/** *	i2o_iop_add - Initialize the I2O controller and add him to the I2O core *	@c: controller * *	Initialize the I2O controller and if no error occurs add him to the I2O *	core. * *	Returns 0 on success or negative error code on failure. */int i2o_iop_add(struct i2o_controller *c){	int rc;	if ((rc = device_add(&c->device))) {		osm_err("%s: could not add controller\n", c->name);		goto iop_reset;	}	osm_info("%s: Activating I2O controller...\n", c->name);	osm_info("%s: This may take a few minutes if there are many devices\n",		 c->name);	if ((rc = i2o_iop_activate(c))) {		osm_err("%s: could not activate controller\n", c->name);		goto device_del;	}	osm_debug("%s: building sys table...\n", c->name);	if ((rc = i2o_systab_build()))		goto device_del;	osm_debug("%s: online controller...\n", c->name);	if ((rc = i2o_iop_online(c)))		goto device_del;	osm_debug("%s: getting LCT...\n", c->name);	if ((rc = i2o_exec_lct_get(c)))		goto device_del;	list_add(&c->list, &i2o_controllers);	i2o_driver_notify_controller_add_all(c);	osm_info("%s: Controller added\n", c->name);	return 0;      device_del:	device_del(&c->device);      iop_reset:	i2o_iop_reset(c);	return rc;};/** *	i2o_event_register - Turn on/off event notification for a I2O device *	@dev: I2O device which should receive the event registration request *	@drv: driver which want to get notified *	@tcntxt: transaction context to use with this notifier *	@evt_mask: mask of events * *	Create and posts an event registration message to the task. No reply *	is waited for, or expected. If you do not want further notifications, *	call the i2o_event_register again with a evt_mask of 0. * *	Returns 0 on success or negative error code on failure. */int i2o_event_register(struct i2o_device *dev, struct i2o_driver *drv,		       int tcntxt, u32 evt_mask){	struct i2o_controller *c = dev->iop;	struct i2o_message *msg;	msg = i2o_msg_get_wait(c, I2O_TIMEOUT_MESSAGE_GET);	if (IS_ERR(msg))		return PTR_ERR(msg);	msg->u.head[0] = cpu_to_le32(FIVE_WORD_MSG_SIZE | SGL_OFFSET_0);	msg->u.head[1] =	    cpu_to_le32(I2O_CMD_UTIL_EVT_REGISTER << 24 | HOST_TID << 12 | dev->			lct_data.tid);	msg->u.s.icntxt = cpu_to_le32(drv->context);	msg->u.s.tcntxt = cpu_to_le32(tcntxt);	msg->body[0] = cpu_to_le32(evt_mask);	i2o_msg_post(c, msg);	return 0;};/** *	i2o_iop_init - I2O main initialization function * *	Initialize the I2O drivers (OSM) functions, register the Executive OSM, *	initialize the I2O PCI part and finally initialize I2O device stuff. * *	Returns 0 on success or negative error code on failure. */static int __init i2o_iop_init(void){	int rc = 0;	printk(KERN_INFO OSM_DESCRIPTION " v" OSM_VERSION "\n");	if ((rc = i2o_driver_init()))		goto exit;	if ((rc = i2o_exec_init()))		goto driver_exit;	if ((rc = i2o_pci_init()))		goto exec_exit;	return 0;      exec_exit:	i2o_exec_exit();      driver_exit:	i2o_driver_exit();      exit:	return rc;}/** *	i2o_iop_exit - I2O main exit function * *	Removes I2O controllers from PCI subsystem and shut down OSMs. */static void __exit i2o_iop_exit(void){	i2o_pci_exit();	i2o_exec_exit();	i2o_driver_exit();};module_init(i2o_iop_init);module_exit(i2o_iop_exit);MODULE_AUTHOR("Red Hat Software");MODULE_LICENSE("GPL");MODULE_DESCRIPTION(OSM_DESCRIPTION);MODULE_VERSION(OSM_VERSION);#if BITS_PER_LONG == 64EXPORT_SYMBOL(i2o_cntxt_list_add);EXPORT_SYMBOL(i2o_cntxt_list_get);EXPORT_SYMBOL(i2o_cntxt_list_remove);EXPORT_SYMBOL(i2o_cntxt_list_get_ptr);#endifEXPORT_SYMBOL(i2o_msg_get_wait);EXPORT_SYMBOL(i2o_find_iop);EXPORT_SYMBOL(i2o_iop_find_device);EXPORT_SYMBOL(i2o_event_register);EXPORT_SYMBOL(i2o_status_get);EXPORT_SYMBOL(i2o_controllers);

⌨️ 快捷键说明

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