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

📄 nodemgr.c

📁 IEE1394 火线接口驱动 for linux
💻 C
📖 第 1 页 / 共 3 页
字号:
		ud->model_name_size = model_name_size;	}	return ud;}/* 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 node_entry *ne, octlet_t address, struct unit_directory *parent){	struct unit_directory *ud;	quadlet_t quad;	quadlet_t *infop;	int length;	struct unit_directory *ud_temp = NULL;	if (!(ud = nodemgr_scan_unit_directory(ne, address)))		goto unit_directory_error;	ud->ne = ne;	ud->address = address;	if (parent) {		ud->flags |= UNIT_DIRECTORY_LUN_DIRECTORY;		ud->parent = parent;	}	if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,				 address, &quad))		goto unit_directory_error;	length = CONFIG_ROM_DIRECTORY_LENGTH(quad) ;	address += 4;	infop = (quadlet_t *) ud->quadlets;	for (; length > 0; length--, address += 4) {		int code;		quadlet_t value;		quadlet_t *quadp;		if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,					 address, &quad))			goto unit_directory_error;		code = CONFIG_ROM_KEY(quad) ;		value = CONFIG_ROM_VALUE(quad);		switch (code) {		case CONFIG_ROM_VENDOR_ID:			ud->vendor_id = value;			ud->flags |= UNIT_DIRECTORY_VENDOR_ID;			if (ud->vendor_id)				ud->vendor_oui = nodemgr_find_oui_name(ud->vendor_id);			if ((ud->flags & UNIT_DIRECTORY_VENDOR_TEXT) != 0) {				length--;				address += 4;				quadp = &(ud->quadlets[ud->length]);				if (nodemgr_read_text_leaf(ne, address, quadp) == 0				    && quadp[0] == 0 && quadp[1] == 0) {				    	/* We only support minimal					   ASCII and English. */					quadp[ud->vendor_name_size] = 0;					ud->vendor_name						= (const char *) &(quadp[2]);				}			}			break;		case CONFIG_ROM_MODEL_ID:			ud->model_id = value;			ud->flags |= UNIT_DIRECTORY_MODEL_ID;			if ((ud->flags & UNIT_DIRECTORY_MODEL_TEXT) != 0) {				length--;				address += 4;				quadp = &(ud->quadlets[ud->length + ud->vendor_name_size + 1]);				if (nodemgr_read_text_leaf(ne, address, quadp) == 0				    && quadp[0] == 0 && quadp[1] == 0) {				    	/* We only support minimal					   ASCII and English. */					quadp[ud->model_name_size] = 0;					ud->model_name						= (const char *) &(quadp[2]);				}			}			break;		case CONFIG_ROM_SPECIFIER_ID:			ud->specifier_id = value;			ud->flags |= UNIT_DIRECTORY_SPECIFIER_ID;			break;		case CONFIG_ROM_UNIT_SW_VERSION:			ud->version = value;			ud->flags |= UNIT_DIRECTORY_VERSION;			break;		case CONFIG_ROM_DESCRIPTOR_LEAF:		case CONFIG_ROM_DESCRIPTOR_DIRECTORY:			/* TODO: read strings... icons? */			break;		case CONFIG_ROM_LOGICAL_UNIT_DIRECTORY:			ud->flags |= UNIT_DIRECTORY_HAS_LUN_DIRECTORY;			ud_temp = nodemgr_process_unit_directory(ne, address + value * 4, ud);			if (ud_temp == NULL)				break;			/* inherit unspecified values */			if ((ud->flags & UNIT_DIRECTORY_VENDOR_ID) &&				!(ud_temp->flags & UNIT_DIRECTORY_VENDOR_ID))			{				ud_temp->flags |=  UNIT_DIRECTORY_VENDOR_ID;				ud_temp->vendor_id = ud->vendor_id;			}			if ((ud->flags & UNIT_DIRECTORY_MODEL_ID) &&				!(ud_temp->flags & UNIT_DIRECTORY_MODEL_ID))			{				ud_temp->flags |=  UNIT_DIRECTORY_MODEL_ID;				ud_temp->model_id = ud->model_id;			}			if ((ud->flags & UNIT_DIRECTORY_SPECIFIER_ID) &&				!(ud_temp->flags & UNIT_DIRECTORY_SPECIFIER_ID))			{				ud_temp->flags |=  UNIT_DIRECTORY_SPECIFIER_ID;				ud_temp->specifier_id = ud->specifier_id;			}			if ((ud->flags & UNIT_DIRECTORY_VERSION) &&				!(ud_temp->flags & UNIT_DIRECTORY_VERSION))			{				ud_temp->flags |=  UNIT_DIRECTORY_VERSION;				ud_temp->version = ud->version;			}			break;		default:			/* Which types of quadlets do we want to			   store?  Only count immediate values and			   CSR offsets for now.  */			code &= CONFIG_ROM_KEY_TYPE_MASK;			if ((code & CONFIG_ROM_KEY_TYPE_LEAF) == 0)				*infop++ = quad;			break;		}	}	list_add_tail(&ud->node_list, &ne->unit_directories);	list_add_tail(&ud->driver_list, &unit_directory_list);	return ud;unit_directory_error:		if (ud != NULL)		kfree(ud);	return NULL;}static void nodemgr_process_root_directory(struct node_entry *ne){	octlet_t address;	quadlet_t quad;	int length;	address = CSR_REGISTER_BASE + CSR_CONFIG_ROM;		if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,				 address, &quad))		return;	address += 4 + CONFIG_ROM_BUS_INFO_LENGTH(quad) * 4;	if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,				 address, &quad))		return;	length = CONFIG_ROM_ROOT_LENGTH(quad);	address += 4;	for (; length > 0; length--, address += 4) {		int code, value;		if (nodemgr_read_quadlet(ne->host, ne->nodeid, ne->generation,					 address, &quad))			return;		code = CONFIG_ROM_KEY(quad);		value = CONFIG_ROM_VALUE(quad);		switch (code) {		case CONFIG_ROM_VENDOR_ID:			ne->vendor_id = value;			if (ne->vendor_id)				ne->vendor_oui = nodemgr_find_oui_name(ne->vendor_id);			/* Now check if there is a vendor name text			   string.  */			if (ne->vendor_name != NULL) {				length--;				address += 4;				if (nodemgr_read_text_leaf(ne, address, ne->quadlets) != 0				    || ne->quadlets[0] != 0 || ne->quadlets[1] != 0)				    	/* We only support minimal					   ASCII and English. */					ne->vendor_name = NULL;			}			break;		case CONFIG_ROM_NODE_CAPABILITES:			ne->capabilities = value;			break;		case CONFIG_ROM_UNIT_DIRECTORY:			nodemgr_process_unit_directory(ne, address + value * 4, NULL);			break;					case CONFIG_ROM_DESCRIPTOR_LEAF:		case CONFIG_ROM_DESCRIPTOR_DIRECTORY:			/* TODO: read strings... icons? */			break;		}	}}#ifdef CONFIG_HOTPLUGstatic void nodemgr_call_policy(char *verb, struct unit_directory *ud){	char *argv [3], **envp, *buf, *scratch;	int i = 0, value;	if (!hotplug_path [0])		return;	if (!current->fs->root)		return;	if (!(envp = (char **) kmalloc(20 * sizeof (char *), GFP_KERNEL))) {		HPSB_DEBUG ("ENOMEM");		return;	}	if (!(buf = kmalloc(256, GFP_KERNEL))) {		kfree(envp);		HPSB_DEBUG("ENOMEM2");		return;	}	/* only one standardized param to hotplug command: type */	argv[0] = hotplug_path;	argv[1] = "ieee1394";	argv[2] = 0;	/* minimal command environment */	envp[i++] = "HOME=/";	envp[i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";#ifdef CONFIG_IEEE1394_VERBOSEDEBUG	/* hint that policy agent should enter no-stdout debug mode */	envp[i++] = "DEBUG=kernel";#endif	/* extensible set of named bus-specific parameters,	 * supporting multiple driver selection algorithms.	 */	scratch = buf;	envp[i++] = scratch;	scratch += sprintf(scratch, "ACTION=%s", verb) + 1;	envp[i++] = scratch;	scratch += sprintf(scratch, "VENDOR_ID=%06x", ud->vendor_id) + 1;	envp[i++] = scratch;	scratch += sprintf(scratch, "GUID=%016Lx", (long long unsigned)ud->ne->guid) + 1;	envp[i++] = scratch;	scratch += sprintf(scratch, "SPECIFIER_ID=%06x", ud->specifier_id) + 1;	envp[i++] = scratch;	scratch += sprintf(scratch, "VERSION=%06x", ud->version) + 1;	envp[i++] = 0;	/* NOTE: user mode daemons can call the agents too */	HPSB_VERBOSE("NodeMgr: %s %s %016Lx", argv[0], verb, (long long unsigned)ud->ne->guid);	value = call_usermodehelper(argv[0], argv, envp);	kfree(buf);	kfree(envp);	if (value != 0)		HPSB_DEBUG("NodeMgr: hotplug policy returned %d", value);}#elsestatic inline voidnodemgr_call_policy(char *verb, struct unit_directory *ud){	HPSB_VERBOSE("NodeMgr: nodemgr_call_policy(): hotplug not enabled");	return;} #endif /* CONFIG_HOTPLUG */static void nodemgr_claim_unit_directory(struct unit_directory *ud,					 struct hpsb_protocol_driver *driver){	ud->driver = driver;	list_move_tail(&ud->driver_list, &driver->unit_directories);}static void nodemgr_release_unit_directory(struct unit_directory *ud){	ud->driver = NULL;	list_move_tail(&ud->driver_list, &unit_directory_list);}void hpsb_release_unit_directory(struct unit_directory *ud){	down(&nodemgr_serialize);	nodemgr_release_unit_directory(ud);	up(&nodemgr_serialize);}static void nodemgr_free_unit_directories(struct node_entry *ne){	struct list_head *lh, *next;	struct unit_directory *ud;	list_for_each_safe(lh, next, &ne->unit_directories) {		ud = list_entry(lh, struct unit_directory, node_list);		if (ud->driver && ud->driver->disconnect)			ud->driver->disconnect(ud);		nodemgr_release_unit_directory(ud);		nodemgr_call_policy("remove", ud);		list_del(&ud->driver_list);		list_del(&ud->node_list);		kfree(ud);	}}static struct ieee1394_device_id *nodemgr_match_driver(struct hpsb_protocol_driver *driver, 		     struct unit_directory *ud){	struct ieee1394_device_id *id;	for (id = driver->id_table; id->match_flags != 0; id++) {		if ((id->match_flags & IEEE1394_MATCH_VENDOR_ID) &&		    id->vendor_id != ud->vendor_id)			continue;		if ((id->match_flags & IEEE1394_MATCH_MODEL_ID) &&		    id->model_id != ud->model_id)			continue;		if ((id->match_flags & IEEE1394_MATCH_SPECIFIER_ID) &&		    id->specifier_id != ud->specifier_id)			continue;		/* software version does a bitwise comparison instead of equality */		if ((id->match_flags & IEEE1394_MATCH_VERSION) &&		    !(id->version & ud->version))			continue;		return id;	}	return NULL;}static struct hpsb_protocol_driver *nodemgr_find_driver(struct unit_directory *ud){	struct list_head *l;	struct hpsb_protocol_driver *match, *driver;	struct ieee1394_device_id *device_id;	match = NULL;	list_for_each(l, &driver_list) {		driver = list_entry(l, struct hpsb_protocol_driver, list);		device_id = nodemgr_match_driver(driver, ud);		if (device_id != NULL) {			match = driver;			break;		}	}	return match;}static void nodemgr_bind_drivers (struct node_entry *ne){	struct list_head *lh;	struct hpsb_protocol_driver *driver;	struct unit_directory *ud;	list_for_each(lh, &ne->unit_directories) {		ud = list_entry(lh, struct unit_directory, node_list);		driver = nodemgr_find_driver(ud);		if (driver && (!driver->probe || driver->probe(ud) == 0))			nodemgr_claim_unit_directory(ud, driver);		nodemgr_call_policy("add", ud);	}}int hpsb_register_protocol(struct hpsb_protocol_driver *driver){	struct unit_directory *ud;	struct list_head *lh, *next;	if (down_interruptible(&nodemgr_serialize))		return -EINTR;	list_add_tail(&driver->list, &driver_list);	INIT_LIST_HEAD(&driver->unit_directories);	list_for_each_safe (lh, next, &unit_directory_list) {		ud = list_entry(lh, struct unit_directory, driver_list);		if (nodemgr_match_driver(driver, ud) &&		    (!driver->probe || driver->probe(ud) == 0))			nodemgr_claim_unit_directory(ud, driver);	}	up(&nodemgr_serialize);	/*	 * Right now registration always succeeds, but maybe we should	 * detect clashes in protocols handled by other drivers.     * DRD> No because multiple drivers are needed to handle certain devices.     * For example, a DV camera is an IEC 61883 device (dv1394) and AV/C (raw1394).     * This will become less an issue with libiec61883 using raw1394.     *     * BenC: But can we handle this with an ALLOW_SHARED flag for a     * protocol? When we get an SBP-3 driver, it will be nice if they were     * mutually exclusive, since SBP-3 can handle SBP-2 protocol.     *     * Not to mention that we currently do not seem to support multiple     * drivers claiming the same unitdirectory. If we implement both of     * those, then we'll need to keep probing when a driver claims a     * unitdirectory, but is sharable.	 */	return 0;}void hpsb_unregister_protocol(struct hpsb_protocol_driver *driver){	struct list_head *lh, *next;	struct unit_directory *ud;	down(&nodemgr_serialize);	list_del(&driver->list);	list_for_each_safe (lh, next, &driver->unit_directories) {		ud = list_entry(lh, struct unit_directory, driver_list);		if (ud->driver && ud->driver->disconnect)			ud->driver->disconnect(ud);		nodemgr_release_unit_directory(ud);	}	up(&nodemgr_serialize);}static void nodemgr_process_config_rom(struct node_entry *ne, 				       quadlet_t busoptions){	ne->busopt.irmc		= (busoptions >> 31) & 1;	ne->busopt.cmc		= (busoptions >> 30) & 1;	ne->busopt.isc		= (busoptions >> 29) & 1;	ne->busopt.bmc		= (busoptions >> 28) & 1;	ne->busopt.pmc		= (busoptions >> 27) & 1;	ne->busopt.cyc_clk_acc	= (busoptions >> 16) & 0xff;	ne->busopt.max_rec	= 1 << (((busoptions >> 12) & 0xf) + 1);	ne->busopt.generation	= (busoptions >> 4) & 0xf;	ne->busopt.lnkspd	= busoptions & 0x7;	HPSB_VERBOSE("NodeMgr: raw=0x%08x irmc=%d cmc=%d isc=%d bmc=%d pmc=%d "		     "cyc_clk_acc=%d max_rec=%d gen=%d lspd=%d",		     busoptions, ne->busopt.irmc, ne->busopt.cmc,		     ne->busopt.isc, ne->busopt.bmc, ne->busopt.pmc,		     ne->busopt.cyc_clk_acc, ne->busopt.max_rec,		     ne->busopt.generation, ne->busopt.lnkspd);	/*	 * When the config rom changes we disconnect all drivers and	 * free the cached unit directories and reread the whole	 * thing.  If this was a new device, the call to	 * nodemgr_disconnect_drivers is a no-op and all is well.	 */	nodemgr_free_unit_directories(ne);	nodemgr_process_root_directory(ne);	nodemgr_bind_drivers(ne);}/* * 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, quadlet_t busoptions,				struct host_info *hi, nodeid_t nodeid,

⌨️ 快捷键说明

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