亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频

? 歡迎來到蟲蟲下載站! | ?? 資源下載 ?? 資源專輯 ?? 關于我們
? 蟲蟲下載站

?? fw-device.c

?? linux 內核源代碼
?? C
?? 第 1 頁 / 共 2 頁
字號:
		 * As per IEEE1212 7.2, during power-up, devices can		 * reply with a 0 for the first quadlet of the config		 * rom to indicate that they are booting (for example,		 * if the firmware is on the disk of a external		 * harddisk).  In that case we just fail, and the		 * retry mechanism will try again later.		 */		if (i == 0 && rom[i] == 0)			return -1;	}	device->max_speed = device->node->max_speed;	/*	 * Determine the speed of	 *   - devices with link speed less than PHY speed,	 *   - devices with 1394b PHY (unless only connected to 1394a PHYs),	 *   - all devices if there are 1394b repeaters.	 * Note, we cannot use the bus info block's link_spd as starting point	 * because some buggy firmwares set it lower than necessary and because	 * 1394-1995 nodes do not have the field.	 */	if ((rom[2] & 0x7) < device->max_speed ||	    device->max_speed == SCODE_BETA ||	    device->card->beta_repeaters_present) {		u32 dummy;		/* for S1600 and S3200 */		if (device->max_speed == SCODE_BETA)			device->max_speed = device->card->link_speed;		while (device->max_speed > SCODE_100) {			if (read_rom(device, 0, &dummy) == RCODE_COMPLETE)				break;			device->max_speed--;		}	}	/*	 * Now parse the config rom.  The config rom is a recursive	 * directory structure so we parse it using a stack of	 * references to the blocks that make up the structure.  We	 * push a reference to the root directory on the stack to	 * start things off.	 */	length = i;	sp = 0;	stack[sp++] = 0xc0000005;	while (sp > 0) {		/*		 * Pop the next block reference of the stack.  The		 * lower 24 bits is the offset into the config rom,		 * the upper 8 bits are the type of the reference the		 * block.		 */		key = stack[--sp];		i = key & 0xffffff;		if (i >= ARRAY_SIZE(rom))			/*			 * The reference points outside the standard			 * config rom area, something's fishy.			 */			return -1;		/* Read header quadlet for the block to get the length. */		if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)			return -1;		end = i + (rom[i] >> 16) + 1;		i++;		if (end > ARRAY_SIZE(rom))			/*			 * This block extends outside standard config			 * area (and the array we're reading it			 * into).  That's broken, so ignore this			 * device.			 */			return -1;		/*		 * Now read in the block.  If this is a directory		 * block, check the entries as we read them to see if		 * it references another block, and push it in that case.		 */		while (i < end) {			if (read_rom(device, i, &rom[i]) != RCODE_COMPLETE)				return -1;			if ((key >> 30) == 3 && (rom[i] >> 30) > 1 &&			    sp < ARRAY_SIZE(stack))				stack[sp++] = i + rom[i];			i++;		}		if (length < i)			length = i;	}	device->config_rom = kmalloc(length * 4, GFP_KERNEL);	if (device->config_rom == NULL)		return -1;	memcpy(device->config_rom, rom, length * 4);	device->config_rom_length = length;	return 0;}static void fw_unit_release(struct device *dev){	struct fw_unit *unit = fw_unit(dev);	kfree(unit);}static struct device_type fw_unit_type = {	.uevent		= fw_unit_uevent,	.release	= fw_unit_release,};static int is_fw_unit(struct device *dev){	return dev->type == &fw_unit_type;}static void create_units(struct fw_device *device){	struct fw_csr_iterator ci;	struct fw_unit *unit;	int key, value, i;	i = 0;	fw_csr_iterator_init(&ci, &device->config_rom[5]);	while (fw_csr_iterator_next(&ci, &key, &value)) {		if (key != (CSR_UNIT | CSR_DIRECTORY))			continue;		/*		 * Get the address of the unit directory and try to		 * match the drivers id_tables against it.		 */		unit = kzalloc(sizeof(*unit), GFP_KERNEL);		if (unit == NULL) {			fw_error("failed to allocate memory for unit\n");			continue;		}		unit->directory = ci.p + value - 1;		unit->device.bus = &fw_bus_type;		unit->device.type = &fw_unit_type;		unit->device.parent = &device->device;		snprintf(unit->device.bus_id, sizeof(unit->device.bus_id),			 "%s.%d", device->device.bus_id, i++);		init_fw_attribute_group(&unit->device,					fw_unit_attributes,					&unit->attribute_group);		if (device_register(&unit->device) < 0)			goto skip_unit;		continue;	skip_unit:		kfree(unit);	}}static int shutdown_unit(struct device *device, void *data){	device_unregister(device);	return 0;}static DECLARE_RWSEM(idr_rwsem);static DEFINE_IDR(fw_device_idr);int fw_cdev_major;struct fw_device *fw_device_from_devt(dev_t devt){	struct fw_device *device;	down_read(&idr_rwsem);	device = idr_find(&fw_device_idr, MINOR(devt));	up_read(&idr_rwsem);	return device;}static void fw_device_shutdown(struct work_struct *work){	struct fw_device *device =		container_of(work, struct fw_device, work.work);	int minor = MINOR(device->device.devt);	down_write(&idr_rwsem);	idr_remove(&fw_device_idr, minor);	up_write(&idr_rwsem);	fw_device_cdev_remove(device);	device_for_each_child(&device->device, NULL, shutdown_unit);	device_unregister(&device->device);}static struct device_type fw_device_type = {	.release	= fw_device_release,};/* * These defines control the retry behavior for reading the config * rom.  It shouldn't be necessary to tweak these; if the device * doesn't respond to a config rom read within 10 seconds, it's not * going to respond at all.  As for the initial delay, a lot of * devices will be able to respond within half a second after bus * reset.  On the other hand, it's not really worth being more * aggressive than that, since it scales pretty well; if 10 devices * are plugged in, they're all getting read within one second. */#define MAX_RETRIES	10#define RETRY_DELAY	(3 * HZ)#define INITIAL_DELAY	(HZ / 2)static void fw_device_init(struct work_struct *work){	struct fw_device *device =		container_of(work, struct fw_device, work.work);	int minor, err;	/*	 * All failure paths here set node->data to NULL, so that we	 * don't try to do device_for_each_child() on a kfree()'d	 * device.	 */	if (read_bus_info_block(device) < 0) {		if (device->config_rom_retries < MAX_RETRIES) {			device->config_rom_retries++;			schedule_delayed_work(&device->work, RETRY_DELAY);		} else {			fw_notify("giving up on config rom for node id %x\n",				  device->node_id);			if (device->node == device->card->root_node)				schedule_delayed_work(&device->card->work, 0);			fw_device_release(&device->device);		}		return;	}	err = -ENOMEM;	down_write(&idr_rwsem);	if (idr_pre_get(&fw_device_idr, GFP_KERNEL))		err = idr_get_new(&fw_device_idr, device, &minor);	up_write(&idr_rwsem);	if (err < 0)		goto error;	device->device.bus = &fw_bus_type;	device->device.type = &fw_device_type;	device->device.parent = device->card->device;	device->device.devt = MKDEV(fw_cdev_major, minor);	snprintf(device->device.bus_id, sizeof(device->device.bus_id),		 "fw%d", minor);	init_fw_attribute_group(&device->device,				fw_device_attributes,				&device->attribute_group);	if (device_add(&device->device)) {		fw_error("Failed to add device.\n");		goto error_with_cdev;	}	create_units(device);	/*	 * Transition the device to running state.  If it got pulled	 * out from under us while we did the intialization work, we	 * have to shut down the device again here.  Normally, though,	 * fw_node_event will be responsible for shutting it down when	 * necessary.  We have to use the atomic cmpxchg here to avoid	 * racing with the FW_NODE_DESTROYED case in	 * fw_node_event().	 */	if (atomic_cmpxchg(&device->state,		    FW_DEVICE_INITIALIZING,		    FW_DEVICE_RUNNING) == FW_DEVICE_SHUTDOWN)		fw_device_shutdown(&device->work.work);	else		fw_notify("created new fw device %s "			  "(%d config rom retries, S%d00)\n",			  device->device.bus_id, device->config_rom_retries,			  1 << device->max_speed);	/*	 * Reschedule the IRM work if we just finished reading the	 * root node config rom.  If this races with a bus reset we	 * just end up running the IRM work a couple of extra times -	 * pretty harmless.	 */	if (device->node == device->card->root_node)		schedule_delayed_work(&device->card->work, 0);	return; error_with_cdev:	down_write(&idr_rwsem);	idr_remove(&fw_device_idr, minor);	up_write(&idr_rwsem); error:	put_device(&device->device);}static int update_unit(struct device *dev, void *data){	struct fw_unit *unit = fw_unit(dev);	struct fw_driver *driver = (struct fw_driver *)dev->driver;	if (is_fw_unit(dev) && driver != NULL && driver->update != NULL) {		down(&dev->sem);		driver->update(unit);		up(&dev->sem);	}	return 0;}static void fw_device_update(struct work_struct *work){	struct fw_device *device =		container_of(work, struct fw_device, work.work);	fw_device_cdev_update(device);	device_for_each_child(&device->device, NULL, update_unit);}void fw_node_event(struct fw_card *card, struct fw_node *node, int event){	struct fw_device *device;	switch (event) {	case FW_NODE_CREATED:	case FW_NODE_LINK_ON:		if (!node->link_on)			break;		device = kzalloc(sizeof(*device), GFP_ATOMIC);		if (device == NULL)			break;		/*		 * Do minimal intialization of the device here, the		 * rest will happen in fw_device_init().  We need the		 * card and node so we can read the config rom and we		 * need to do device_initialize() now so		 * device_for_each_child() in FW_NODE_UPDATED is		 * doesn't freak out.		 */		device_initialize(&device->device);		atomic_set(&device->state, FW_DEVICE_INITIALIZING);		device->card = fw_card_get(card);		device->node = fw_node_get(node);		device->node_id = node->node_id;		device->generation = card->generation;		INIT_LIST_HEAD(&device->client_list);		/*		 * Set the node data to point back to this device so		 * FW_NODE_UPDATED callbacks can update the node_id		 * and generation for the device.		 */		node->data = device;		/*		 * Many devices are slow to respond after bus resets,		 * especially if they are bus powered and go through		 * power-up after getting plugged in.  We schedule the		 * first config rom scan half a second after bus reset.		 */		INIT_DELAYED_WORK(&device->work, fw_device_init);		schedule_delayed_work(&device->work, INITIAL_DELAY);		break;	case FW_NODE_UPDATED:		if (!node->link_on || node->data == NULL)			break;		device = node->data;		device->node_id = node->node_id;		device->generation = card->generation;		if (atomic_read(&device->state) == FW_DEVICE_RUNNING) {			PREPARE_DELAYED_WORK(&device->work, fw_device_update);			schedule_delayed_work(&device->work, 0);		}		break;	case FW_NODE_DESTROYED:	case FW_NODE_LINK_OFF:		if (!node->data)			break;		/*		 * Destroy the device associated with the node.  There		 * are two cases here: either the device is fully		 * initialized (FW_DEVICE_RUNNING) or we're in the		 * process of reading its config rom		 * (FW_DEVICE_INITIALIZING).  If it is fully		 * initialized we can reuse device->work to schedule a		 * full fw_device_shutdown().  If not, there's work		 * scheduled to read it's config rom, and we just put		 * the device in shutdown state to have that code fail		 * to create the device.		 */		device = node->data;		if (atomic_xchg(&device->state,				FW_DEVICE_SHUTDOWN) == FW_DEVICE_RUNNING) {			PREPARE_DELAYED_WORK(&device->work, fw_device_shutdown);			schedule_delayed_work(&device->work, 0);		}		break;	}}

?? 快捷鍵說明

復制代碼 Ctrl + C
搜索代碼 Ctrl + F
全屏模式 F11
切換主題 Ctrl + Shift + D
顯示快捷鍵 ?
增大字號 Ctrl + =
減小字號 Ctrl + -
亚洲欧美第一页_禁久久精品乱码_粉嫩av一区二区三区免费野_久草精品视频
成人免费高清在线| 久久综合精品国产一区二区三区| 在线观看亚洲专区| 精品国产乱子伦一区| 亚洲三级久久久| 精品一区二区日韩| 欧美四级电影网| 国产日韩av一区| 五月天亚洲精品| www.亚洲色图| 久久精品欧美一区二区三区不卡| 午夜视频久久久久久| 色噜噜久久综合| 欧美国产综合色视频| 国产伦精一区二区三区| 欧美一区二区三区四区久久| 亚洲综合一二区| 99re视频这里只有精品| 国产日韩欧美一区二区三区综合 | 欧美性高清videossexo| 国产亚洲精品7777| 国产一区二区剧情av在线| 欧美一区二区在线观看| 婷婷综合久久一区二区三区| 欧美中文字幕一区二区三区| 中文字幕巨乱亚洲| 成人在线一区二区三区| 久久婷婷久久一区二区三区| 国产真实乱子伦精品视频| 精品久久久久香蕉网| 男人操女人的视频在线观看欧美| 91精品欧美福利在线观看| 亚洲国产一区二区在线播放| 欧美性淫爽ww久久久久无| 亚洲资源中文字幕| 欧美三级日韩三级国产三级| 亚洲精品中文在线观看| 在线观看中文字幕不卡| 亚洲一区二区高清| 在线成人av网站| 亚洲成人av电影| 日韩一区二区电影在线| 精品亚洲porn| 欧美激情一区二区三区不卡| 高清成人免费视频| 亚洲视频一区二区免费在线观看 | 久久一区二区三区国产精品| 精品影院一区二区久久久| 欧美精品一区二区三区蜜桃| 成人深夜福利app| 中文字幕亚洲一区二区va在线| 91麻豆国产精品久久| 午夜精品久久久久久| 日韩一区二区三区免费观看 | 五月天激情综合| 欧美大片在线观看一区二区| 国产另类ts人妖一区二区| 亚洲天堂精品在线观看| 欧美色偷偷大香| 国产精品99久久久久久久女警 | 91婷婷韩国欧美一区二区| 香蕉乱码成人久久天堂爱免费| 欧美大片在线观看| 国产凹凸在线观看一区二区| 亚洲精品国产a| 欧美xxxxxxxxx| 色哟哟一区二区在线观看 | 成人高清在线视频| 亚洲在线中文字幕| 久久久亚洲精品一区二区三区 | 亚洲第一福利视频在线| 久久亚洲精精品中文字幕早川悠里| 成人av在线资源| 麻豆成人免费电影| 亚洲理论在线观看| 久久综合久久鬼色| 欧美日韩综合在线免费观看| 国产一区欧美日韩| 日韩精品一二三区| 亚洲色图.com| 日本一区二区在线不卡| 欧美一区二区三区系列电影| 99久久国产综合精品色伊| 日本视频在线一区| 亚洲精品视频自拍| 国产日韩欧美一区二区三区综合| 欧美精品电影在线播放| 色婷婷亚洲婷婷| 国产一区二区三区四| 婷婷成人激情在线网| 综合久久国产九一剧情麻豆| 精品国产电影一区二区| 欧美午夜精品理论片a级按摩| 国产成人欧美日韩在线电影| 美国三级日本三级久久99 | 久久国产福利国产秒拍| 一区二区不卡在线播放| 国产女同性恋一区二区| 欧美xingq一区二区| 日韩欧美中文一区| 欧美日韩国产不卡| 色视频成人在线观看免| 色婷婷精品大视频在线蜜桃视频| 成人免费电影视频| 成人精品国产一区二区4080| 精品午夜一区二区三区在线观看| 另类小说欧美激情| 免费三级欧美电影| 日韩国产高清在线| 日韩综合小视频| 日韩精品乱码免费| 免费成人美女在线观看.| 偷窥少妇高潮呻吟av久久免费 | 中文字幕在线观看不卡视频| 国产蜜臀av在线一区二区三区| 国产日韩精品一区二区三区| 国产片一区二区| 国产精品美女久久久久久2018| 国产精品视频线看| 亚洲欧洲成人自拍| 亚洲综合网站在线观看| 亚洲一区二区三区三| 亚洲国产裸拍裸体视频在线观看乱了 | 亚洲色图都市小说| 亚洲美女淫视频| 亚洲电影第三页| 麻豆精品新av中文字幕| 久久国产综合精品| 国产麻豆精品95视频| 成人免费毛片app| 色综合网站在线| 91精品国产黑色紧身裤美女| 日韩亚洲欧美综合| 国产三级欧美三级日产三级99| 中文字幕视频一区二区三区久| 中文字幕永久在线不卡| 亚洲一区在线免费观看| 日本aⅴ精品一区二区三区| 免费在线观看成人| gogo大胆日本视频一区| 91久久精品国产91性色tv| 在线成人小视频| 国产午夜精品一区二区三区视频| 亚洲欧洲日韩女同| 日韩国产一二三区| 波多野结衣一区二区三区| 欧美主播一区二区三区| 精品国产成人系列| 亚洲综合视频在线观看| 日本va欧美va精品发布| 99久久婷婷国产精品综合| 91精品午夜视频| 亚洲欧洲日韩av| 精品一区二区在线看| 色偷偷久久人人79超碰人人澡| 欧美一区二区三区婷婷月色| 最新久久zyz资源站| 免费成人av在线播放| 99精品欧美一区二区蜜桃免费 | 成人污污视频在线观看| 欧美日韩黄色影视| 久久久久久久久伊人| 一区二区三区国产豹纹内裤在线| 免费成人av资源网| 色婷婷综合五月| 久久人人97超碰com| 日日夜夜精品视频免费| 成人av小说网| 精品国产乱码久久久久久免费 | 亚洲aaa精品| 成人免费视频网站在线观看| 在线成人av网站| 一区二区三区在线免费视频| 国产成人精品网址| 欧美日韩另类一区| 一区二区三区丝袜| 懂色av中文一区二区三区| 欧美一区二区三区播放老司机| 一区二区三区四区不卡视频| 国产69精品久久久久777| 日韩欧美国产系列| 午夜电影一区二区三区| 在线视频国内自拍亚洲视频| 国产精品嫩草99a| 久久99国产精品免费| 91麻豆精品国产91| 亚洲国产综合在线| 欧美在线不卡视频| 亚洲女厕所小便bbb| 99久久精品情趣| 国产精品免费人成网站| 国产一区二区三区久久悠悠色av| 日韩欧美一二区| 日本午夜精品视频在线观看| 欧美精品三级日韩久久| 亚洲一区二区黄色| 欧美三级电影精品| 日韩专区一卡二卡| 欧美一二三四区在线| 日韩av不卡在线观看|