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

📄 nodemgr.c

📁 ieee1394驱动,不多说了!直接可以在linux2.6内核中使用
💻 C
📖 第 1 页 / 共 4 页
字号:
	snprintf(ud->class_dev.class_id, BUS_ID_SIZE, "%s-%u",		 ne->device.bus_id, ud->id);	if (device_register(&ud->device))		goto fail_devreg;	if (class_device_register(&ud->class_dev))		goto fail_classdevreg;	get_device(&ud->device);	nodemgr_create_ud_dev_files(ud);	return;fail_classdevreg:	device_unregister(&ud->device);fail_devreg:	HPSB_ERR("Failed to create unit %s", ud->device.bus_id);}	/* This implementation currently only scans the config rom and its * immediate unit directories looking for software_id and * software_version entries, in order to get driver autoloading working. */static struct unit_directory *nodemgr_process_unit_directory	(struct host_info *hi, struct node_entry *ne, struct csr1212_keyval *ud_kv,	 unsigned int *id, struct unit_directory *parent){	struct unit_directory *ud;	struct unit_directory *ud_child = NULL;	struct csr1212_dentry *dentry;	struct csr1212_keyval *kv;	u8 last_key_id = 0;	ud = kzalloc(sizeof(*ud), GFP_KERNEL);	if (!ud)		goto unit_directory_error;	ud->ne = ne;	ud->ignore_driver = ignore_drivers;	ud->address = ud_kv->offset + CSR1212_CONFIG_ROM_SPACE_BASE;	ud->ud_kv = ud_kv;	ud->id = (*id)++;	csr1212_for_each_dir_entry(ne->csr, kv, ud_kv, dentry) {		switch (kv->key.id) {		case CSR1212_KV_ID_VENDOR:			if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {				ud->vendor_id = kv->value.immediate;				ud->flags |= UNIT_DIRECTORY_VENDOR_ID;			}			break;		case CSR1212_KV_ID_MODEL:			ud->model_id = kv->value.immediate;			ud->flags |= UNIT_DIRECTORY_MODEL_ID;			break;		case CSR1212_KV_ID_SPECIFIER_ID:			ud->specifier_id = kv->value.immediate;			ud->flags |= UNIT_DIRECTORY_SPECIFIER_ID;			break;		case CSR1212_KV_ID_VERSION:			ud->version = kv->value.immediate;			ud->flags |= UNIT_DIRECTORY_VERSION;			break;		case CSR1212_KV_ID_DESCRIPTOR:			if (kv->key.type == CSR1212_KV_TYPE_LEAF &&			    CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 &&			    CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 &&			    CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 &&			    CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 &&			    CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) {				switch (last_key_id) {				case CSR1212_KV_ID_VENDOR:					ud->vendor_name_kv = kv;					csr1212_keep_keyval(kv);					break;				case CSR1212_KV_ID_MODEL:					ud->model_name_kv = kv;					csr1212_keep_keyval(kv);					break;				}			} /* else if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) ... */			break;		case CSR1212_KV_ID_DEPENDENT_INFO:			/* Logical Unit Number */			if (kv->key.type == CSR1212_KV_TYPE_IMMEDIATE) {				if (ud->flags & UNIT_DIRECTORY_HAS_LUN) {					ud_child = kmemdup(ud, sizeof(*ud_child), GFP_KERNEL);					if (!ud_child)						goto unit_directory_error;					nodemgr_register_device(ne, ud_child, &ne->device);					ud_child = NULL;										ud->id = (*id)++;				}				ud->lun = kv->value.immediate;				ud->flags |= UNIT_DIRECTORY_HAS_LUN;			/* Logical Unit Directory */			} else if (kv->key.type == CSR1212_KV_TYPE_DIRECTORY) {				/* This should really be done in SBP2 as this is				 * doing SBP2 specific parsing.				 */								/* first register the parent unit */				ud->flags |= UNIT_DIRECTORY_HAS_LUN_DIRECTORY;				if (ud->device.bus != &ieee1394_bus_type)					nodemgr_register_device(ne, ud, &ne->device);								/* process the child unit */				ud_child = nodemgr_process_unit_directory(hi, ne, kv, id, ud);				if (ud_child == NULL)					break;								/* inherit unspecified values, the driver core picks it up */				if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) &&				    !(ud_child->flags & UNIT_DIRECTORY_MODEL_ID))				{					ud_child->flags |=  UNIT_DIRECTORY_MODEL_ID;					ud_child->model_id = ud->model_id;				}				if ((ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) &&				    !(ud_child->flags & UNIT_DIRECTORY_SPECIFIER_ID))				{					ud_child->flags |=  UNIT_DIRECTORY_SPECIFIER_ID;					ud_child->specifier_id = ud->specifier_id;				}				if ((ud->flags & UNIT_DIRECTORY_VERSION) &&				    !(ud_child->flags & UNIT_DIRECTORY_VERSION))				{					ud_child->flags |=  UNIT_DIRECTORY_VERSION;					ud_child->version = ud->version;				}								/* register the child unit */				ud_child->flags |= UNIT_DIRECTORY_LUN_DIRECTORY;				nodemgr_register_device(ne, ud_child, &ud->device);			}			break;		default:			break;		}		last_key_id = kv->key.id;	}		/* do not process child units here and only if not already registered */	if (!parent && ud->device.bus != &ieee1394_bus_type)		nodemgr_register_device(ne, ud, &ne->device);	return ud;unit_directory_error:	kfree(ud);	return NULL;}static void nodemgr_process_root_directory(struct host_info *hi, struct node_entry *ne){	unsigned int ud_id = 0;	struct csr1212_dentry *dentry;	struct csr1212_keyval *kv;	u8 last_key_id = 0;	ne->needs_probe = 0;	csr1212_for_each_dir_entry(ne->csr, kv, ne->csr->root_kv, dentry) {		switch (kv->key.id) {		case CSR1212_KV_ID_VENDOR:			ne->vendor_id = kv->value.immediate;			break;		case CSR1212_KV_ID_NODE_CAPABILITIES:			ne->capabilities = kv->value.immediate;			break;		case CSR1212_KV_ID_UNIT:			nodemgr_process_unit_directory(hi, ne, kv, &ud_id, NULL);			break;		case CSR1212_KV_ID_DESCRIPTOR:			if (last_key_id == CSR1212_KV_ID_VENDOR) {				if (kv->key.type == CSR1212_KV_TYPE_LEAF &&				    CSR1212_DESCRIPTOR_LEAF_TYPE(kv) == 0 &&				    CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) == 0 &&				    CSR1212_TEXTUAL_DESCRIPTOR_LEAF_WIDTH(kv) == 0 &&				    CSR1212_TEXTUAL_DESCRIPTOR_LEAF_CHAR_SET(kv) == 0 &&				    CSR1212_TEXTUAL_DESCRIPTOR_LEAF_LANGUAGE(kv) == 0) {					ne->vendor_name_kv = kv;					csr1212_keep_keyval(kv);				}			}			break;		}		last_key_id = kv->key.id;	}	if (ne->vendor_name_kv &&	    device_create_file(&ne->device, &dev_attr_ne_vendor_name_kv))		goto fail;	return;fail:	HPSB_ERR("Failed to add sysfs attribute for node %016Lx",		 (unsigned long long)ne->guid);}#ifdef CONFIG_HOTPLUGstatic int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,			  char *buffer, int buffer_size){	struct unit_directory *ud;	int i = 0;	int length = 0;	/* ieee1394:venNmoNspNverN */	char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1];	if (!cdev)		return -ENODEV;	ud = container_of(cdev, struct unit_directory, class_dev);	if (ud->ne->in_limbo || ud->ignore_driver)		return -ENODEV;#define PUT_ENVP(fmt,val) 					\do {								\    	int printed;						\	envp[i++] = buffer;					\	printed = snprintf(buffer, buffer_size - length,	\			   fmt, val);				\	if ((buffer_size - (length+printed) <= 0) || (i >= num_envp))	\		return -ENOMEM;					\	length += printed+1;					\	buffer += printed+1;					\} while (0)	PUT_ENVP("VENDOR_ID=%06x", ud->vendor_id);	PUT_ENVP("MODEL_ID=%06x", ud->model_id);	PUT_ENVP("GUID=%016Lx", (unsigned long long)ud->ne->guid);	PUT_ENVP("SPECIFIER_ID=%06x", ud->specifier_id);	PUT_ENVP("VERSION=%06x", ud->version);	snprintf(buf, sizeof(buf), "ieee1394:ven%08Xmo%08Xsp%08Xver%08X",			ud->vendor_id,			ud->model_id,			ud->specifier_id,			ud->version);	PUT_ENVP("MODALIAS=%s", buf);#undef PUT_ENVP	envp[i] = NULL;	return 0;}#elsestatic int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,			  char *buffer, int buffer_size){	return -ENODEV;}#endif /* CONFIG_HOTPLUG */int __hpsb_register_protocol(struct hpsb_protocol_driver *drv,			     struct module *owner){	int error;	drv->driver.bus = &ieee1394_bus_type;	drv->driver.owner = owner;	drv->driver.name = drv->name;	/* This will cause a probe for devices */	error = driver_register(&drv->driver);	if (!error)		nodemgr_create_drv_files(drv);	return error;}void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver){	nodemgr_remove_drv_files(driver);	/* This will subsequently disconnect all devices that our driver	 * is attached to. */	driver_unregister(&driver->driver);}/* * This function updates nodes that were present on the bus before the * reset and still are after the reset.  The nodeid and the config rom * may have changed, and the drivers managing this device must be * informed that this device just went through a bus reset, to allow * the to take whatever actions required. */static void nodemgr_update_node(struct node_entry *ne, struct csr1212_csr *csr,				struct host_info *hi, nodeid_t nodeid,				unsigned int generation){	if (ne->nodeid != nodeid) {		HPSB_DEBUG("Node changed: " NODE_BUS_FMT " -> " NODE_BUS_FMT,			   NODE_BUS_ARGS(ne->host, ne->nodeid),			   NODE_BUS_ARGS(ne->host, nodeid));		ne->nodeid = nodeid;	}	if (ne->busopt.generation != ((be32_to_cpu(csr->bus_info_data[2]) >> 4) & 0xf)) {		kfree(ne->csr->private);		csr1212_destroy_csr(ne->csr);		ne->csr = csr;		/* If the node's configrom generation has changed, we		 * unregister all the unit directories. */		nodemgr_remove_uds(ne);		nodemgr_update_bus_options(ne);		/* Mark the node as new, so it gets re-probed */		ne->needs_probe = 1;	} else {		/* old cache is valid, so update its generation */		struct nodemgr_csr_info *ci = ne->csr->private;		ci->generation = generation;		/* free the partially filled now unneeded new cache */		kfree(csr->private);		csr1212_destroy_csr(csr);	}	if (ne->in_limbo)		nodemgr_resume_ne(ne);	/* Mark the node current */	ne->generation = generation;}static void nodemgr_node_scan_one(struct host_info *hi,				  nodeid_t nodeid, int generation){	struct hpsb_host *host = hi->host;	struct node_entry *ne;	octlet_t guid;	struct csr1212_csr *csr;	struct nodemgr_csr_info *ci;	u8 *speed;	ci = kmalloc(sizeof(*ci), GFP_KERNEL);	if (!ci)		return;	ci->host = host;	ci->nodeid = nodeid;	ci->generation = generation;	/* Prepare for speed probe which occurs when reading the ROM */	speed = &(host->speed[NODEID_TO_NODE(nodeid)]);	if (*speed > host->csr.lnk_spd)		*speed = host->csr.lnk_spd;	ci->speed_unverified = *speed > IEEE1394_SPEED_100;	/* We need to detect when the ConfigROM's generation has changed,	 * so we only update the node's info when it needs to be.  */	csr = csr1212_create_csr(&nodemgr_csr_ops, 5 * sizeof(quadlet_t), ci);	if (!csr || csr1212_parse_csr(csr) != CSR1212_SUCCESS) {		HPSB_ERR("Error parsing configrom for node " NODE_BUS_FMT,			 NODE_BUS_ARGS(host, nodeid));		if (csr)			csr1212_destroy_csr(csr);		kfree(ci);		return;	}	if (csr->bus_info_data[1] != IEEE1394_BUSID_MAGIC) {		/* This isn't a 1394 device, but we let it slide. There		 * was a report of a device with broken firmware which		 * reported '2394' instead of '1394', which is obviously a		 * mistake. One would hope that a non-1394 device never		 * gets connected to Firewire bus. If someone does, we		 * shouldn't be held responsible, so we'll allow it with a		 * warning.  */		HPSB_WARN("Node " NODE_BUS_FMT " has invalid busID magic [0x%08x]",			  NODE_BUS_ARGS(host, nodeid), csr->bus_info_data[1]);	}	guid = ((u64)be32_to_cpu(csr->bus_info_data[3]) << 32) | be32_to_cpu(csr->bus_info_data[4]);	ne = find_entry_by_guid(guid);	if (ne && ne->host != host && ne->in_limbo) {		/* Must have moved this device from one host to another */		nodemgr_remove_ne(ne);		ne = NULL;	}	if (!ne)		nodemgr_create_node(guid, csr, hi, nodeid, generation);	else		nodemgr_update_node(ne, csr, hi, nodeid, generation);}static void nodemgr_node_scan(struct host_info *hi, int generation){	int count;	struct hpsb_host *host = hi->host;	struct selfid *sid = (struct selfid *)host->topology_map;	nodeid_t nodeid = LOCAL_BUS;	/* Scan each node on the bus */	for (count = host->selfid_count; count; count--, sid++) {		if (sid->extended)			continue;		if (!sid->link_active) {			nodeid++;			continue;		}		nodemgr_node_scan_one(hi, nodeid++, generation);	}}static void nodemgr_suspend_ne(struct node_entry *ne){	struct class_device *cdev;	struct unit_directory *ud;	HPSB_DEBUG("Node suspended: ID:BUS[" NODE_BUS_FMT "]  GUID[%016Lx]",		   NODE_BUS_ARGS(ne->host, ne->nodeid), (unsigned long long)ne->guid);	ne->in_limbo = 1;	WARN_ON(device_create_file(&ne->device, &dev_attr_ne_in_limbo));	down(&nodemgr_ud_class.sem);	list_for_each_entry(cdev, &nodemgr_ud_class.children, node) {		ud = container_of(cdev, struct unit_directory, class_dev);		if (ud->ne != ne)			continue;		down_write(&ieee1394_bus_type.subsys.rwsem);		if (ud->device.driver &&		    (!ud->device.driver->suspend ||		      ud->device.driver->suspend(&ud->device, PMSG_SUSPEND)))			device_release_driver(&ud->device);		up_write(&ieee1394_bus_type.subsys.rwsem);	}	up(&nodemgr_ud_class.sem);}static void nodemgr_resume_ne(struct node_entry *ne){	struct class_device *cdev;	struct unit_directory *ud;	ne->in_limbo = 0;	device_remove_file(&ne->device, &dev_attr_ne_in_limbo);

⌨️ 快捷键说明

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