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

📄 csr1212.c

📁 这是关于ieee1394的最新源码,上面包含了所有更新的部分!
💻 C
📖 第 1 页 / 共 3 页
字号:
	int pixel_size = (hscan * vscan + 3) & ~0x3;	if (!pixels || (!palette && palette_depth) ||	    (palette_depth & ~0x3) || (color_space & ~0xf))		return NULL;	palette_size = pd[palette_depth] * cs[color_space];	kv = csr1212_new_descriptor_leaf(1, 0, NULL,					 palette_size + pixel_size +					 CSR1212_ICON_DESCRIPTOR_LEAF_OVERHEAD);	if (!kv)		return NULL;	CSR1212_ICON_DESCRIPTOR_LEAF_SET_VERSION(kv, version);	CSR1212_ICON_DESCRIPTOR_LEAF_SET_PALETTE_DEPTH(kv, palette_depth);	CSR1212_ICON_DESCRIPTOR_LEAF_SET_COLOR_SPACE(kv, color_space);	CSR1212_ICON_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language);	CSR1212_ICON_DESCRIPTOR_LEAF_SET_HSCAN(kv, hscan);	CSR1212_ICON_DESCRIPTOR_LEAF_SET_VSCAN(kv, vscan);	if (palette_size)		memcpy(CSR1212_ICON_DESCRIPTOR_LEAF_PALETTE(kv), palette,		       palette_size);	memcpy(CSR1212_ICON_DESCRIPTOR_LEAF_PIXELS(kv), pixels, pixel_size);	return kv;}struct csr1212_keyval *csr1212_new_modifiable_descriptor_leaf(u_int16_t max_size,							      u_int64_t address){	struct csr1212_keyval *kv;	/* IEEE 1212, par. 7.5.4.3  Modifiable descriptors */	kv = csr1212_new_leaf(CSR1212_KV_ID_MODIFIABLE_DESCRIPTOR, NULL, sizeof(u_int64_t));	if(!kv)		return NULL;	CSR1212_MODIFIABLE_DESCRIPTOR_SET_MAX_SIZE(kv, max_size);	CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_HI(kv, address);	CSR1212_MODIFIABLE_DESCRIPTOR_SET_ADDRESS_LO(kv, address);	return kv;}static int csr1212_check_keyword(const char *s){	for (; *s; s++) {		if (('A' <= *s) && (*s <= 'Z'))			continue;		if (('0' <= *s) && (*s <= '9'))			continue;		if (*s == '-')			continue;		return -1; /* failed */	}	/* String conforms to keyword, as specified by IEEE 1212,	 * par. 7.6.5 */	return CSR1212_SUCCESS;}struct csr1212_keyval *csr1212_new_keyword_leaf(int strc, const char *strv[]){	struct csr1212_keyval *kv;	char *buffer;	int i, data_len = 0;	/* Check all keywords to see if they conform to restrictions:	 * Only the following characters is allowed ['A'..'Z','0'..'9','-']	 * Each word is zero-terminated.	 * Also calculate the total length of the keywords.	 */	for (i = 0; i < strc; i++) {		if (!strv[i] || csr1212_check_keyword(strv[i])) {			return NULL;		}		data_len += strlen(strv[i]) + 1; /* Add zero-termination char. */	}	/* IEEE 1212, par. 7.6.5 Keyword leaves */	kv = csr1212_new_leaf(CSR1212_KV_ID_KEYWORD, NULL, data_len);	if (!kv)		return NULL;	buffer = (char *)kv->value.leaf.data;	/* make sure last quadlet is zeroed out */	*((u_int32_t*)&(buffer[(data_len - 1) & ~0x3])) = 0;	/* Copy keyword(s) into leaf data buffer */	for (i = 0; i < strc; i++) {		int len = strlen(strv[i]) + 1;		memcpy(buffer, strv[i], len);		buffer += len;	}	return kv;}/* Destruction Routines */void csr1212_detach_keyval_from_directory(struct csr1212_keyval *dir,					  struct csr1212_keyval *kv){	struct csr1212_dentry *dentry;	if (!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY)		return;	dentry = csr1212_find_keyval(dir, kv);	if (!dentry)		return;	if (dentry->prev)		dentry->prev->next = dentry->next;	if (dentry->next)		dentry->next->prev = dentry->prev;	if (dir->value.directory.dentries_head == dentry)		dir->value.directory.dentries_head = dentry->next;	if (dir->value.directory.dentries_tail == dentry)		dir->value.directory.dentries_tail = dentry->prev;	CSR1212_FREE(dentry);	csr1212_release_keyval(kv);}void csr1212_disassociate_keyval(struct csr1212_keyval *kv){	if (kv->associate) {		csr1212_release_keyval(kv->associate);	}	kv->associate = NULL;}/* This function is used to free the memory taken by a keyval.  If the given * keyval is a directory type, then any keyvals contained in that directory * will be destroyed as well if their respective refcnts are 0.  By means of * list manipulation, this routine will descend a directory structure in a * non-recursive manner. */void _csr1212_destroy_keyval(struct csr1212_keyval *kv){	struct csr1212_keyval *k, *a;	struct csr1212_dentry dentry;	struct csr1212_dentry *head, *tail;	dentry.kv = kv;	dentry.next = NULL;	dentry.prev = NULL;	head = &dentry;	tail = head;	while (head) {		k = head->kv;		while (k) {			k->refcnt--;			if (k->refcnt > 0)				break;			a = k->associate;			if (k->key.type == CSR1212_KV_TYPE_DIRECTORY) {				/* If the current entry is a directory, then move all				 * the entries to the destruction list. */				if (k->value.directory.dentries_head) {					tail->next = k->value.directory.dentries_head;					k->value.directory.dentries_head->prev = tail;					tail = k->value.directory.dentries_tail;				}			}			free_keyval(k);			k = a;		}		head = head->next;		if (head) {			if (head->prev && head->prev != &dentry) {				CSR1212_FREE(head->prev);			}			head->prev = NULL;		} else if (tail != &dentry)			CSR1212_FREE(tail);	}}void csr1212_destroy_csr(struct csr1212_csr *csr){	struct csr1212_csr_rom_cache *c, *oc;	struct csr1212_cache_region *cr, *ocr;	csr1212_release_keyval(csr->root_kv);	c = csr->cache_head;	while (c) {		oc = c;		cr = c->filled_head;		while (cr) {			ocr = cr;			cr = cr->next;			CSR1212_FREE(ocr);		}		c = c->next;		CSR1212_FREE(oc);	}	CSR1212_FREE(csr);}/* CSR Image Creation */static int csr1212_append_new_cache(struct csr1212_csr *csr, size_t romsize){	struct csr1212_csr_rom_cache *cache;	u_int64_t csr_addr;	if (!csr || !csr->ops || !csr->ops->allocate_addr_range ||	    !csr->ops->release_addr || csr->max_rom < 1)		return CSR1212_EINVAL;	/* ROM size must be a multiple of csr->max_rom */	romsize = (romsize + (csr->max_rom - 1)) & ~(csr->max_rom - 1);	csr_addr = csr->ops->allocate_addr_range(romsize, csr->max_rom, csr->private);	if (csr_addr == CSR1212_INVALID_ADDR_SPACE) {		return CSR1212_ENOMEM;	}	if (csr_addr < CSR1212_REGISTER_SPACE_BASE) {		/* Invalid address returned from allocate_addr_range(). */		csr->ops->release_addr(csr_addr, csr->private);		return CSR1212_ENOMEM;	}	cache = csr1212_rom_cache_malloc(csr_addr - CSR1212_REGISTER_SPACE_BASE, romsize);	if (!cache) {		csr->ops->release_addr(csr_addr, csr->private);		return CSR1212_ENOMEM;	}	cache->ext_rom = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, CSR1212_KV_ID_EXTENDED_ROM);	if (!cache->ext_rom) {		csr->ops->release_addr(csr_addr, csr->private);		CSR1212_FREE(cache);		return CSR1212_ENOMEM;	}	if (csr1212_attach_keyval_to_directory(csr->root_kv, cache->ext_rom) != CSR1212_SUCCESS) {		csr1212_release_keyval(cache->ext_rom);		csr->ops->release_addr(csr_addr, csr->private);		CSR1212_FREE(cache);		return CSR1212_ENOMEM;	}	cache->ext_rom->offset = csr_addr - CSR1212_REGISTER_SPACE_BASE;	cache->ext_rom->value.leaf.len = -1;	cache->ext_rom->value.leaf.data = cache->data;	/* Add cache to tail of cache list */	cache->prev = csr->cache_tail;	csr->cache_tail->next = cache;	csr->cache_tail = cache;	return CSR1212_SUCCESS;}static inline void csr1212_remove_cache(struct csr1212_csr *csr,					struct csr1212_csr_rom_cache *cache){	if (csr->cache_head == cache)		csr->cache_head = cache->next;	if (csr->cache_tail == cache)		csr->cache_tail = cache->prev;	if (cache->prev)		cache->prev->next = cache->next;	if (cache->next)		cache->next->prev = cache->prev;	if (cache->ext_rom) {		csr1212_detach_keyval_from_directory(csr->root_kv, cache->ext_rom);		csr1212_release_keyval(cache->ext_rom);	}	CSR1212_FREE(cache);}static int csr1212_generate_layout_subdir(struct csr1212_keyval *dir,					  struct csr1212_keyval **layout_tail){	struct csr1212_dentry *dentry;	struct csr1212_keyval *dkv;	struct csr1212_keyval *last_extkey_spec = NULL;	struct csr1212_keyval *last_extkey = NULL;	int num_entries = 0;	for (dentry = dir->value.directory.dentries_head; dentry;	     dentry = dentry->next) {		for (dkv = dentry->kv; dkv; dkv = dkv->associate) {			/* Special Case: Extended Key Specifier_ID */			if (dkv->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) {				if (last_extkey_spec == NULL) {					last_extkey_spec = dkv;				} else if (dkv->value.immediate != last_extkey_spec->value.immediate) {					last_extkey_spec = dkv;				} else {					continue;				}			/* Special Case: Extended Key */			} else if (dkv->key.id == CSR1212_KV_ID_EXTENDED_KEY) {				if (last_extkey == NULL) {					last_extkey = dkv;				} else if (dkv->value.immediate != last_extkey->value.immediate) {					last_extkey = dkv;				} else {					continue;				}			}			num_entries += 1;			switch(dkv->key.type) {			default:			case CSR1212_KV_TYPE_IMMEDIATE:			case CSR1212_KV_TYPE_CSR_OFFSET:				break;			case CSR1212_KV_TYPE_LEAF:			case CSR1212_KV_TYPE_DIRECTORY:				/* Remove from list */				if (dkv->prev && (dkv->prev->next == dkv))					dkv->prev->next = dkv->next;				if (dkv->next && (dkv->next->prev == dkv))					dkv->next->prev = dkv->prev;				//if (dkv == *layout_tail)				//	*layout_tail = dkv->prev;				/* Special case: Extended ROM leafs */				if (dkv->key.id == CSR1212_KV_ID_EXTENDED_ROM) {					dkv->value.leaf.len = -1;					/* Don't add Extended ROM leafs in the layout list,					 * they are handled differently. */					break;				}				/* Add to tail of list */				dkv->next = NULL;				dkv->prev = *layout_tail;				(*layout_tail)->next = dkv;				*layout_tail = dkv;				break;			}		}	}	return num_entries;}size_t csr1212_generate_layout_order(struct csr1212_keyval *kv){	struct csr1212_keyval *ltail = kv;	size_t agg_size = 0;	while(kv) {		switch(kv->key.type) {		case CSR1212_KV_TYPE_LEAF:			/* Add 1 quadlet for crc/len field */			agg_size += kv->value.leaf.len + 1;			break;		case CSR1212_KV_TYPE_DIRECTORY:			kv->value.directory.len = csr1212_generate_layout_subdir(kv, &ltail);			/* Add 1 quadlet for crc/len field */			agg_size += kv->value.directory.len + 1;			break;		}		kv = kv->next;	}	return quads_to_bytes(agg_size);}struct csr1212_keyval *csr1212_generate_positions(struct csr1212_csr_rom_cache *cache,						  struct csr1212_keyval *start_kv,						  int start_pos){	struct csr1212_keyval *kv = start_kv;	struct csr1212_keyval *okv = start_kv;	int pos = start_pos;	int kv_len = 0, okv_len = 0;	cache->layout_head = kv;	while(kv && pos < cache->size) {		/* Special case: Extended ROM leafs */		if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM) {			kv->offset = cache->offset + pos;		}		switch(kv->key.type) {		case CSR1212_KV_TYPE_LEAF:			kv_len = kv->value.leaf.len;			break;		case CSR1212_KV_TYPE_DIRECTORY:			kv_len = kv->value.directory.len;			break;		default:			/* Should never get here */			break;		}		pos += quads_to_bytes(kv_len + 1);		if (pos <= cache->size) {			okv = kv;			okv_len = kv_len;			kv = kv->next;		}	}	cache->layout_tail = okv;	cache->len = (okv->offset - cache->offset) + quads_to_bytes(okv_len + 1);	return kv;}static void csr1212_generate_tree_subdir(struct csr1212_keyval *dir,					 u_int32_t *data_buffer){	struct csr1212_dentry *dentry;	struct csr1212_keyval *last_extkey_spec = NULL;	struct csr1212_keyval *last_extkey = NULL;	int index = 0;	for (dentry = dir->value.directory.dentries_head; dentry; dentry = dentry->next) {		struct csr1212_keyval *a;		for (a = dentry->kv; a; a = a->associate) {			u_int32_t value = 0;			/* Special Case: Extended Key Specifier_ID */			if (a->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) {				if (last_extkey_spec == NULL) {					last_extkey_spec = a;				} else if (a->value.immediate != last_extkey_spec->value.immediate) {					last_extkey_spec = a;				} else {					continue;				}			/* Special Case: Extended Key */			} else if (a->key.id == CSR1212_KV_ID_EXTENDED_KEY) {				if (last_extkey == NULL) {					last_extkey = a;				} else if (a->value.immediate != last_extkey->value.immediate) {					last_extkey = a;				} else {					continue;				}			}			switch(a->key.type) {			case CSR1212_KV_TYPE_IMMEDIATE:				value = a->value.immediate;				break;			case CSR1212_KV_TYPE_CSR_OFFSET:				value = a->value.csr_offset;				break;			case CSR1212_KV_TYPE_LEAF:				value = a->offset;				value -= dir->offset + quads_to_bytes(1+index);				value = bytes_to_quads(value);				break;			case CSR1212_KV_TYPE_DIRECTORY:				value = a->offset;				value -= dir->offset + quads_to_bytes(1+index);				value = bytes_to_quads(value);				break;			default:				/* Should never get here */				break; /* GDB breakpoint */			}			value |= (a->key.id & CSR1212_KV_KEY_ID_MASK) << CSR1212_KV_KEY_SHIFT;			value |= (a->key.type & CSR1212_KV_KEY_TYPE_MASK) <<				(CSR1212_KV_KEY_SHIFT + CSR1212_KV_KEY_TYPE_SHIFT);			data_buffer[index] = CSR1212_CPU_TO_BE32(value);			index++;		}	}}void csr1212_fill_cache(struct csr1212_csr_rom_cache *cache){	struct csr1212_keyval *kv, *nkv;	struct csr1212_keyval_img *kvi;	for (kv = cache->layout_head; kv != cache->layout_tail->next; kv = nkv) {		kvi = (struct csr1212_keyval_img *)			(cache->data + bytes_to_quads(kv->offset - cache->offset));		switch(kv->key.type) {		default:		case CSR1212_KV_TYPE_IMMEDIATE:		case CSR1212_KV_TYPE_CSR_OFFSET:			/* Should never get here */			break; /* GDB breakpoint */		case CSR1212_KV_TYPE_LEAF:			/* Don't copy over Extended ROM areas, they are			 * already filled out! */			if (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)				memcpy(kvi->data, kv->value.leaf.data,				       quads_to_bytes(kv->value.leaf.len));			kvi->length = CSR1212_CPU_TO_BE16(kv->value.leaf.len);			kvi->crc = csr1212_crc16(kvi->data, kv->value.leaf.len);			break;		case CSR1212_KV_TYPE_DIRECTORY:			csr1212_generate_tree_subdir(kv, kvi->data);			kvi->length = CSR1212_CPU_TO_BE16(kv->value.directory.len);			kvi->crc = csr1212_crc16(kvi->data, kv->value.directory.len);			break;		}		nkv = kv->next;		if (kv->prev)			kv->prev->next = NULL;		if (kv->next)			kv->next->prev = NULL;		kv->prev = NULL;		kv->next = NULL;	}}

⌨️ 快捷键说明

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