diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-04-30 08:59:57 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-04-30 08:59:57 -0700 |
commit | 40caf5ea5a7d47f8a33e26b63ca81dea4b5109d2 (patch) | |
tree | 3f879353d5cb69d2dee707108e4aaeae075f5a0c /drivers | |
parent | d6454706c382ab74e2ecad7803c434cc6bd30343 (diff) | |
parent | bcfd09ee48f77a4fe903dbc3757e7af931998ce1 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6: (56 commits)
ieee1394: remove garbage from Kconfig
ieee1394: more help in Kconfig
ieee1394: ohci1394: Fix mistake in printk message.
ieee1394: ohci1394: remove unnecessary rcvPhyPkt bit flipping in LinkControl register
ieee1394: ohci1394: fix cosmetic problem in error logging
ieee1394: eth1394: send async streams at S100 on 1394b buses
ieee1394: eth1394: fix error path in module_init
ieee1394: eth1394: correct return codes in hard_start_xmit
ieee1394: eth1394: hard_start_xmit is called in atomic context
ieee1394: eth1394: some conditions are unlikely
ieee1394: eth1394: clean up fragment_overlap
ieee1394: eth1394: don't use alloc_etherdev
ieee1394: eth1394: omit useless set_mac_address callback
ieee1394: eth1394: CONFIG_INET is always defined
ieee1394: eth1394: allow MTU bigger than 1500
ieee1394: unexport highlevel_host_reset
ieee1394: eth1394: contain host reset
ieee1394: eth1394: shorter error messages
ieee1394: eth1394: correct a memset argument
ieee1394: eth1394: refactor .probe and .update
...
Diffstat (limited to 'drivers')
26 files changed, 1446 insertions, 2013 deletions
diff --git a/drivers/ieee1394/Kconfig b/drivers/ieee1394/Kconfig index cd84a55ecf2..61d7809a5a2 100644 --- a/drivers/ieee1394/Kconfig +++ b/drivers/ieee1394/Kconfig @@ -1,11 +1,8 @@ -# -*- shell-script -*- - menu "IEEE 1394 (FireWire) support" config IEEE1394 tristate "IEEE 1394 (FireWire) support" depends on PCI || BROKEN - select NET help IEEE 1394 describes a high performance serial bus, which is also known as FireWire(tm) or i.Link(tm) and is used for connecting all @@ -35,24 +32,7 @@ config IEEE1394_VERBOSEDEBUG Say Y if you really want or need the debugging output, everyone else says N. -config IEEE1394_EXTRA_CONFIG_ROMS - bool "Build in extra config rom entries for certain functionality" - depends on IEEE1394 - help - Some IEEE1394 functionality depends on extra config rom entries - being available in the host adapters CSR. These options will - allow you to choose which ones. - -config IEEE1394_CONFIG_ROM_IP1394 - bool "IP-1394 Entry" - depends on IEEE1394_EXTRA_CONFIG_ROMS && IEEE1394 - help - Adds an entry for using IP-over-1394. If you want to use your - IEEE1394 bus as a network for IP systems (including interacting - with MacOSX and WinXP IP-over-1394), enable this option and the - eth1394 option below. - -comment "Device Drivers" +comment "Controllers" depends on IEEE1394 comment "Texas Instruments PCILynx requires I2C" @@ -70,6 +50,10 @@ config IEEE1394_PCILYNX To compile this driver as a module, say M here: the module will be called pcilynx. + Only some old and now very rare PCI and CardBus cards and + PowerMacs G3 B&W contain the PCILynx controller. Therefore + almost everybody can say N here. + config IEEE1394_OHCI1394 tristate "OHCI-1394 support" depends on PCI && IEEE1394 @@ -83,7 +67,7 @@ config IEEE1394_OHCI1394 To compile this driver as a module, say M here: the module will be called ohci1394. -comment "Protocol Drivers" +comment "Protocols" depends on IEEE1394 config IEEE1394_VIDEO1394 @@ -121,11 +105,15 @@ config IEEE1394_SBP2_PHYS_DMA This option is buggy and currently broken on some architectures. If unsure, say N. +config IEEE1394_ETH1394_ROM_ENTRY + depends on IEEE1394 + bool + default n + config IEEE1394_ETH1394 - tristate "Ethernet over 1394" + tristate "IP over 1394" depends on IEEE1394 && EXPERIMENTAL && INET - select IEEE1394_CONFIG_ROM_IP1394 - select IEEE1394_EXTRA_CONFIG_ROMS + select IEEE1394_ETH1394_ROM_ENTRY help This driver implements a functional majority of RFC 2734: IPv4 over 1394. It will provide IP connectivity with implementations of RFC @@ -134,6 +122,8 @@ config IEEE1394_ETH1394 This driver is still considered experimental. It does not yet support MCAP, therefore multicast support is significantly limited. + The module is called eth1394 although it does not emulate Ethernet. + config IEEE1394_DV1394 tristate "OHCI-DV I/O support (deprecated)" depends on IEEE1394 && IEEE1394_OHCI1394 @@ -146,12 +136,12 @@ config IEEE1394_RAWIO tristate "Raw IEEE1394 I/O support" depends on IEEE1394 help - Say Y here if you want support for the raw device. This is generally - a good idea, so you should say Y here. The raw device enables - direct communication of user programs with the IEEE 1394 bus and - thus with the attached peripherals. + This option adds support for the raw1394 device file which enables + direct communication of user programs with the IEEE 1394 bus and thus + with the attached peripherals. Almost all application programs which + access FireWire require this option. - To compile this driver as a module, say M here: the - module will be called raw1394. + To compile this driver as a module, say M here: the module will be + called raw1394. endmenu diff --git a/drivers/ieee1394/config_roms.c b/drivers/ieee1394/config_roms.c index e2de6fa0c9f..1b981207fa7 100644 --- a/drivers/ieee1394/config_roms.c +++ b/drivers/ieee1394/config_roms.c @@ -26,12 +26,6 @@ struct hpsb_config_rom_entry { /* Base initialization, called at module load */ int (*init)(void); - /* Add entry to specified host */ - int (*add)(struct hpsb_host *host); - - /* Remove entry from specified host */ - void (*remove)(struct hpsb_host *host); - /* Cleanup called at module exit */ void (*cleanup)(void); @@ -39,7 +33,7 @@ struct hpsb_config_rom_entry { unsigned int flag; }; - +/* The default host entry. This must succeed. */ int hpsb_default_host_entry(struct hpsb_host *host) { struct csr1212_keyval *root; @@ -63,9 +57,9 @@ int hpsb_default_host_entry(struct hpsb_host *host) return -ENOMEM; } - ret = csr1212_associate_keyval(vend_id, text); + csr1212_associate_keyval(vend_id, text); csr1212_release_keyval(text); - ret |= csr1212_attach_keyval_to_directory(root, vend_id); + ret = csr1212_attach_keyval_to_directory(root, vend_id); csr1212_release_keyval(vend_id); if (ret != CSR1212_SUCCESS) { csr1212_destroy_csr(host->csr.rom); @@ -78,7 +72,7 @@ int hpsb_default_host_entry(struct hpsb_host *host) } -#ifdef CONFIG_IEEE1394_CONFIG_ROM_IP1394 +#ifdef CONFIG_IEEE1394_ETH1394_ROM_ENTRY #include "eth1394.h" static struct csr1212_keyval *ip1394_ud; @@ -103,10 +97,12 @@ static int config_rom_ip1394_init(void) if (!ip1394_ud || !spec_id || !spec_desc || !ver || !ver_desc) goto ip1394_fail; - if (csr1212_associate_keyval(spec_id, spec_desc) == CSR1212_SUCCESS && - csr1212_associate_keyval(ver, ver_desc) == CSR1212_SUCCESS && - csr1212_attach_keyval_to_directory(ip1394_ud, spec_id) == CSR1212_SUCCESS && - csr1212_attach_keyval_to_directory(ip1394_ud, ver) == CSR1212_SUCCESS) + csr1212_associate_keyval(spec_id, spec_desc); + csr1212_associate_keyval(ver, ver_desc); + if (csr1212_attach_keyval_to_directory(ip1394_ud, spec_id) + == CSR1212_SUCCESS && + csr1212_attach_keyval_to_directory(ip1394_ud, ver) + == CSR1212_SUCCESS) ret = 0; ip1394_fail: @@ -135,7 +131,7 @@ static void config_rom_ip1394_cleanup(void) } } -static int config_rom_ip1394_add(struct hpsb_host *host) +int hpsb_config_rom_ip1394_add(struct hpsb_host *host) { if (!ip1394_ud) return -ENODEV; @@ -144,92 +140,55 @@ static int config_rom_ip1394_add(struct hpsb_host *host) ip1394_ud) != CSR1212_SUCCESS) return -ENOMEM; + host->config_roms |= HPSB_CONFIG_ROM_ENTRY_IP1394; + host->update_config_rom = 1; return 0; } +EXPORT_SYMBOL_GPL(hpsb_config_rom_ip1394_add); -static void config_rom_ip1394_remove(struct hpsb_host *host) +void hpsb_config_rom_ip1394_remove(struct hpsb_host *host) { csr1212_detach_keyval_from_directory(host->csr.rom->root_kv, ip1394_ud); + host->config_roms &= ~HPSB_CONFIG_ROM_ENTRY_IP1394; + host->update_config_rom = 1; } +EXPORT_SYMBOL_GPL(hpsb_config_rom_ip1394_remove); static struct hpsb_config_rom_entry ip1394_entry = { .name = "ip1394", .init = config_rom_ip1394_init, - .add = config_rom_ip1394_add, - .remove = config_rom_ip1394_remove, .cleanup = config_rom_ip1394_cleanup, .flag = HPSB_CONFIG_ROM_ENTRY_IP1394, }; -#endif /* CONFIG_IEEE1394_CONFIG_ROM_IP1394 */ +#endif /* CONFIG_IEEE1394_ETH1394_ROM_ENTRY */ static struct hpsb_config_rom_entry *const config_rom_entries[] = { -#ifdef CONFIG_IEEE1394_CONFIG_ROM_IP1394 +#ifdef CONFIG_IEEE1394_ETH1394_ROM_ENTRY &ip1394_entry, #endif - NULL, }; - +/* Initialize all config roms */ int hpsb_init_config_roms(void) { int i, error = 0; - for (i = 0; config_rom_entries[i]; i++) { - if (!config_rom_entries[i]->init) - continue; - + for (i = 0; i < ARRAY_SIZE(config_rom_entries); i++) if (config_rom_entries[i]->init()) { HPSB_ERR("Failed to initialize config rom entry `%s'", config_rom_entries[i]->name); error = -1; - } else - HPSB_DEBUG("Initialized config rom entry `%s'", - config_rom_entries[i]->name); - } - - return error; -} - -void hpsb_cleanup_config_roms(void) -{ - int i; - - for (i = 0; config_rom_entries[i]; i++) { - if (config_rom_entries[i]->cleanup) - config_rom_entries[i]->cleanup(); - } -} - -int hpsb_add_extra_config_roms(struct hpsb_host *host) -{ - int i, error = 0; - - for (i = 0; config_rom_entries[i]; i++) { - if (config_rom_entries[i]->add(host)) { - HPSB_ERR("fw-host%d: Failed to attach config rom entry `%s'", - host->id, config_rom_entries[i]->name); - error = -1; - } else { - host->config_roms |= config_rom_entries[i]->flag; - host->update_config_rom = 1; } - } return error; } -void hpsb_remove_extra_config_roms(struct hpsb_host *host) +/* Cleanup all config roms */ +void hpsb_cleanup_config_roms(void) { int i; - for (i = 0; config_rom_entries[i]; i++) { - if (!(host->config_roms & config_rom_entries[i]->flag)) - continue; - - config_rom_entries[i]->remove(host); - - host->config_roms &= ~config_rom_entries[i]->flag; - host->update_config_rom = 1; - } + for (i = 0; i < ARRAY_SIZE(config_rom_entries); i++) + config_rom_entries[i]->cleanup(); } diff --git a/drivers/ieee1394/config_roms.h b/drivers/ieee1394/config_roms.h index 0a70544cfe6..1f5cd1f16c4 100644 --- a/drivers/ieee1394/config_roms.h +++ b/drivers/ieee1394/config_roms.h @@ -1,27 +1,19 @@ #ifndef _IEEE1394_CONFIG_ROMS_H #define _IEEE1394_CONFIG_ROMS_H -#include "ieee1394_types.h" -#include "hosts.h" +struct hpsb_host; -/* The default host entry. This must succeed. */ int hpsb_default_host_entry(struct hpsb_host *host); - -/* Initialize all config roms */ int hpsb_init_config_roms(void); - -/* Cleanup all config roms */ void hpsb_cleanup_config_roms(void); -/* Add extra config roms to specified host */ -int hpsb_add_extra_config_roms(struct hpsb_host *host); - -/* Remove extra config roms from specified host */ -void hpsb_remove_extra_config_roms(struct hpsb_host *host); - - /* List of flags to check if a host contains a certain extra config rom * entry. Available in the host->config_roms member. */ #define HPSB_CONFIG_ROM_ENTRY_IP1394 0x00000001 +#ifdef CONFIG_IEEE1394_ETH1394_ROM_ENTRY +int hpsb_config_rom_ip1394_add(struct hpsb_host *host); +void hpsb_config_rom_ip1394_remove(struct hpsb_host *host); +#endif + #endif /* _IEEE1394_CONFIG_ROMS_H */ diff --git a/drivers/ieee1394/csr1212.c b/drivers/ieee1394/csr1212.c index c28f639823d..d08166bda1c 100644 --- a/drivers/ieee1394/csr1212.c +++ b/drivers/ieee1394/csr1212.c @@ -31,12 +31,13 @@ /* TODO List: * - Verify interface consistency: i.e., public functions that take a size * parameter expect size to be in bytes. - * - Convenience functions for reading a block of data from a given offset. */ -#ifndef __KERNEL__ -#include <string.h> -#endif +#include <linux/errno.h> +#include <linux/kernel.h> +#include <linux/string.h> +#include <asm/bug.h> +#include <asm/byteorder.h> #include "csr1212.h" @@ -46,7 +47,7 @@ #define __C (1 << CSR1212_KV_TYPE_CSR_OFFSET) #define __D (1 << CSR1212_KV_TYPE_DIRECTORY) #define __L (1 << CSR1212_KV_TYPE_LEAF) -static const u_int8_t csr1212_key_id_type_map[0x30] = { +static const u8 csr1212_key_id_type_map[0x30] = { __C, /* used by Apple iSight */ __D | __L, /* Descriptor */ __I | __D | __L, /* Bus_Dependent_Info */ @@ -82,10 +83,10 @@ static const u_int8_t csr1212_key_id_type_map[0x30] = { #undef __L -#define quads_to_bytes(_q) ((_q) * sizeof(u_int32_t)) -#define bytes_to_quads(_b) (((_b) + sizeof(u_int32_t) - 1) / sizeof(u_int32_t)) +#define quads_to_bytes(_q) ((_q) * sizeof(u32)) +#define bytes_to_quads(_b) (((_b) + sizeof(u32) - 1) / sizeof(u32)) -static inline void free_keyval(struct csr1212_keyval *kv) +static void free_keyval(struct csr1212_keyval *kv) { if ((kv->key.type == CSR1212_KV_TYPE_LEAF) && (kv->key.id != CSR1212_KV_ID_EXTENDED_ROM)) @@ -94,14 +95,14 @@ static inline void free_keyval(struct csr1212_keyval *kv) CSR1212_FREE(kv); } -static u_int16_t csr1212_crc16(const u_int32_t *buffer, size_t length) +static u16 csr1212_crc16(const u32 *buffer, size_t length) { int shift; - u_int32_t data; - u_int16_t sum, crc = 0; + u32 data; + u16 sum, crc = 0; for (; length; length--) { - data = CSR1212_BE32_TO_CPU(*buffer); + data = be32_to_cpu(*buffer); buffer++; for (shift = 28; shift >= 0; shift -= 4 ) { sum = ((crc >> 12) ^ (data >> shift)) & 0xf; @@ -110,21 +111,18 @@ static u_int16_t csr1212_crc16(const u_int32_t *buffer, size_t length) crc &= 0xffff; } - return CSR1212_CPU_TO_BE16(crc); + return cpu_to_be16(crc); } -#if 0 -/* Microsoft computes the CRC with the bytes in reverse order. Therefore we - * have a special version of the CRC algorithm to account for their buggy - * software. */ -static u_int16_t csr1212_msft_crc16(const u_int32_t *buffer, size_t length) +/* Microsoft computes the CRC with the bytes in reverse order. */ +static u16 csr1212_msft_crc16(const u32 *buffer, size_t length) { int shift; - u_int32_t data; - u_int16_t sum, crc = 0; + u32 data; + u16 sum, crc = 0; for (; length; length--) { - data = CSR1212_LE32_TO_CPU(*buffer); + data = le32_to_cpu(*buffer); buffer++; for (shift = 28; shift >= 0; shift -= 4 ) { sum = ((crc >> 12) ^ (data >> shift)) & 0xf; @@ -133,38 +131,35 @@ static u_int16_t csr1212_msft_crc16(const u_int32_t *buffer, size_t length) crc &= 0xffff; } - return CSR1212_CPU_TO_BE16(crc); + return cpu_to_be16(crc); } -#endif -static inline struct csr1212_dentry *csr1212_find_keyval(struct csr1212_keyval *dir, - struct csr1212_keyval *kv) +static struct csr1212_dentry * +csr1212_find_keyval(struct csr1212_keyval *dir, struct csr1212_keyval *kv) { struct csr1212_dentry *pos; for (pos = dir->value.directory.dentries_head; - pos != NULL; pos = pos->next) { + pos != NULL; pos = pos->next) if (pos->kv == kv) return pos; - } return NULL; } - -static inline struct csr1212_keyval *csr1212_find_keyval_offset(struct csr1212_keyval *kv_list, - u_int32_t offset) +static struct csr1212_keyval * +csr1212_find_keyval_offset(struct csr1212_keyval *kv_list, u32 offset) { struct csr1212_keyval *kv; - for (kv = kv_list->next; kv && (kv != kv_list); kv = kv->next) { + for (kv = kv_list->next; kv && (kv != kv_list); kv = kv->next) if (kv->offset == offset) return kv; - } return NULL; } /* Creation Routines */ + struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops, size_t bus_info_size, void *private) { @@ -202,27 +197,17 @@ struct csr1212_csr *csr1212_create_csr(struct csr1212_bus_ops *ops, return csr; } - - void csr1212_init_local_csr(struct csr1212_csr *csr, - const u_int32_t *bus_info_data, int max_rom) + const u32 *bus_info_data, int max_rom) { static const int mr_map[] = { 4, 64, 1024, 0 }; -#ifdef __KERNEL__ BUG_ON(max_rom & ~0x3); csr->max_rom = mr_map[max_rom]; -#else - if (max_rom & ~0x3) /* caller supplied invalid argument */ - csr->max_rom = 0; - else - csr->max_rom = mr_map[max_rom]; -#endif memcpy(csr->bus_info_data, bus_info_data, csr->bus_info_len); } - -static struct csr1212_keyval *csr1212_new_keyval(u_int8_t type, u_int8_t key) +static struct csr1212_keyval *csr1212_new_keyval(u8 type, u8 key) { struct csr1212_keyval *kv; @@ -246,10 +231,11 @@ static struct csr1212_keyval *csr1212_new_keyval(u_int8_t type, u_int8_t key) return kv; } -struct csr1212_keyval *csr1212_new_immediate(u_int8_t key, u_int32_t value) +struct csr1212_keyval *csr1212_new_immediate(u8 key, u32 value) { - struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_IMMEDIATE, key); + struct csr1212_keyval *kv; + kv = csr1212_new_keyval(CSR1212_KV_TYPE_IMMEDIATE, key); if (!kv) return NULL; @@ -258,10 +244,12 @@ struct csr1212_keyval *csr1212_new_immediate(u_int8_t key, u_int32_t value) return kv; } -struct csr1212_keyval *csr1212_new_leaf(u_int8_t key, const void *data, size_t data_len) +static struct csr1212_keyval * +csr1212_new_leaf(u8 key, const void *data, size_t data_len) { - struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, key); + struct csr1212_keyval *kv; + kv = csr1212_new_keyval(CSR1212_KV_TYPE_LEAF, key); if (!kv) return NULL; @@ -285,10 +273,12 @@ struct csr1212_keyval *csr1212_new_leaf(u_int8_t key, const void *data, size_t d return kv; } -struct csr1212_keyval *csr1212_new_csr_offset(u_int8_t key, u_int32_t csr_offset) +static struct csr1212_keyval * +csr1212_new_csr_offset(u8 key, u32 csr_offset) { - struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_CSR_OFFSET, key); + struct csr1212_keyval *kv; + kv = csr1212_new_keyval(CSR1212_KV_TYPE_CSR_OFFSET, key); if (!kv) return NULL; @@ -299,10 +289,11 @@ struct csr1212_keyval *csr1212_new_csr_offset(u_int8_t key, u_int32_t csr_offset return kv; } -struct csr1212_keyval *csr1212_new_directory(u_int8_t key) +struct csr1212_keyval *csr1212_new_directory(u8 key) { - struct csr1212_keyval *kv = csr1212_new_keyval(CSR1212_KV_TYPE_DIRECTORY, key); + struct csr1212_keyval *kv; + kv = csr1212_new_keyval(CSR1212_KV_TYPE_DIRECTORY, key); if (!kv) return NULL; @@ -314,43 +305,29 @@ struct csr1212_keyval *csr1212_new_directory(u_int8_t key) return kv; } -int csr1212_associate_keyval(struct csr1212_keyval *kv, - struct csr1212_keyval *associate) +void csr1212_associate_keyval(struct csr1212_keyval *kv, + struct csr1212_keyval *associate) { - if (!kv || !associate) - return CSR1212_EINVAL; - - if (kv->key.id == CSR1212_KV_ID_DESCRIPTOR || - (associate->key.id != CSR1212_KV_ID_DESCRIPTOR && - associate->key.id != CSR1212_KV_ID_DEPENDENT_INFO && - associate->key.id != CSR1212_KV_ID_EXTENDED_KEY && - associate->key.id != CSR1212_KV_ID_EXTENDED_DATA && - associate->key.id < 0x30)) - return CSR1212_EINVAL; - - if (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID && - associate->key.id != CSR1212_KV_ID_EXTENDED_KEY) - return CSR1212_EINVAL; - - if (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY && - associate->key.id != CSR1212_KV_ID_EXTENDED_DATA) - return CSR1212_EINVAL; - - if (associate->key.id == CSR1212_KV_ID_EXTENDED_KEY && - kv->key.id != CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) - return CSR1212_EINVAL; - - if (associate->key.id == CSR1212_KV_ID_EXTENDED_DATA && - kv->key.id != CSR1212_KV_ID_EXTENDED_KEY) - return CSR1212_EINVAL; + BUG_ON(!kv || !associate || kv->key.id == CSR1212_KV_ID_DESCRIPTOR || + (associate->key.id != CSR1212_KV_ID_DESCRIPTOR && + associate->key.id != CSR1212_KV_ID_DEPENDENT_INFO && + associate->key.id != CSR1212_KV_ID_EXTENDED_KEY && + associate->key.id != CSR1212_KV_ID_EXTENDED_DATA && + associate->key.id < 0x30) || + (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID && + associate->key.id != CSR1212_KV_ID_EXTENDED_KEY) || + (kv->key.id == CSR1212_KV_ID_EXTENDED_KEY && + associate->key.id != CSR1212_KV_ID_EXTENDED_DATA) || + (associate->key.id == CSR1212_KV_ID_EXTENDED_KEY && + kv->key.id != CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID) || + (associate->key.id == CSR1212_KV_ID_EXTENDED_DATA && + kv->key.id != CSR1212_KV_ID_EXTENDED_KEY)); if (kv->associate) csr1212_release_keyval(kv->associate); associate->refcnt++; kv->associate = associate; - - return CSR1212_SUCCESS; } int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir, @@ -358,12 +335,11 @@ int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir, { struct csr1212_dentry *dentry; - if (!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY) - return CSR1212_EINVAL; + BUG_ON(!kv || !dir || dir->key.type != CSR1212_KV_TYPE_DIRECTORY); dentry = CSR1212_MALLOC(sizeof(*dentry)); if (!dentry) - return CSR1212_ENOMEM; + return -ENOMEM; dentry->kv = kv; @@ -382,66 +358,22 @@ int csr1212_attach_keyval_to_directory(struct csr1212_keyval *dir, return CSR1212_SUCCESS; } -struct csr1212_keyval *csr1212_new_extended_immediate(u_int32_t spec, u_int32_t key, - u_int32_t value) -{ - struct csr1212_keyval *kvs, *kvk, *kvv; - - kvs = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID, spec); - kvk = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY, key); - kvv = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_DATA, value); - - if (!kvs || !kvk || !kvv) { - if (kvs) - free_keyval(kvs); - if (kvk) - free_keyval(kvk); - if (kvv) - free_keyval(kvv); - return NULL; - } - - /* Don't keep a local reference to the extended key or value. */ - kvk->refcnt = 0; - kvv->refcnt = 0; - - csr1212_associate_keyval(kvk, kvv); - csr1212_associate_keyval(kvs, kvk); - - return kvs; -} - -struct csr1212_keyval *csr1212_new_extended_leaf(u_int32_t spec, u_int32_t key, - const void *data, size_t data_len) -{ - struct csr1212_keyval *kvs, *kvk, *kvv; - - kvs = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY_SPECIFIER_ID, spec); - kvk = csr1212_new_immediate(CSR1212_KV_ID_EXTENDED_KEY, key); - kvv = csr1212_new_leaf(CSR1212_KV_ID_EXTENDED_DATA, data, data_len); - - if (!kvs || !kvk || !kvv) { - if (kvs) - free_keyval(kvs); - if (kvk) - free_keyval(kvk); - if (kvv) - free_keyval(kvv); - return NULL; - } - - /* Don't keep a local reference to the extended key or value. */ - kvk->refcnt = 0; - kvv->refcnt = 0; - - csr1212_associate_keyval(kvk, kvv); - csr1212_associate_keyval(kvs, kvk); - - return kvs; -} - -struct csr1212_keyval *csr1212_new_descriptor_leaf(u_int8_t dtype, u_int32_t specifier_id, - const void *data, size_t data_len) +#define CSR1212_DESCRIPTOR_LEAF_DATA(kv) \ + (&((kv)->value.leaf.data[1])) + +#define CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, type) \ + ((kv)->value.leaf.data[0] = \ + cpu_to_be32(CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID(kv) | \ + ((type) << CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT))) +#define CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, spec_id) \ + ((kv)->value.leaf.data[0] = \ + cpu_to_be32((CSR1212_DESCRIPTOR_LEAF_TYPE(kv) << \ + CSR1212_DESCRIPTOR_LEAF_TYPE_SHIFT) | \ + ((spec_id) & CSR1212_DESCRIPTOR_LEAF_SPECIFIER_ID_MASK))) + +static struct csr1212_keyval * +csr1212_new_descriptor_leaf(u8 dtype, u32 specifier_id, + const void *data, size_t data_len) { struct csr1212_keyval *kv; @@ -453,197 +385,72 @@ struct csr1212_keyval *csr1212_new_descriptor_leaf(u_int8_t dtype, u_int32_t spe CSR1212_DESCRIPTOR_LEAF_SET_TYPE(kv, dtype); CSR1212_DESCRIPTOR_LEAF_SET_SPECIFIER_ID(kv, specifier_id); - if (data) { + if (data) memcpy(CSR1212_DESCRIPTOR_LEAF_DATA(kv), data, data_len); - } - - return kv; -} - - -struct csr1212_keyval *csr1212_new_textual_descriptor_leaf(u_int8_t cwidth, - u_int16_t cset, - u_int16_t language, - const void *data, - size_t data_len) -{ - struct csr1212_keyval *kv; - char *lstr; - - kv = csr1212_new_descriptor_leaf(0, 0, NULL, data_len + - CSR1212_TEXTUAL_DESCRIPTOR_LEAF_OVERHEAD); - if (!kv) - return NULL; - - CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_WIDTH(kv, cwidth); - CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_CHAR_SET(kv, cset); - CSR1212_TEXTUAL_DESCRIPTOR_LEAF_SET_LANGUAGE(kv, language); - - lstr = (char*)CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(kv); - - /* make sure last quadlet is zeroed out */ - *((u_int32_t*)&(lstr[(data_len - 1) & ~0x3])) = 0; - - /* don't copy the NUL terminator */ - memcpy(lstr, data, data_len); return kv; } +/* Check if string conforms to minimal ASCII as per IEEE 1212 clause 7.4 */ static int csr1212_check_minimal_ascii(const char *s) { static const char minimal_ascii_table[] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, - 0x00, 0x00, 0x0a, 0x00, 0x0C, 0x0D, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x20, 0x21, 0x22, 0x00, 0x00, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, - 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, - 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, - 0x58, 0x59, 0x5a, 0x00, 0x00, 0x00, 0x00, 0x5f, - 0x00, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, - 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, - 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, - 0x78, 0x79, 0x7a, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 1 2 4 8 16 32 64 128 */ + 128, /* --, --, --, --, --, --, --, 07, */ + 4 + 16 + 32, /* --, --, 0a, --, 0C, 0D, --, --, */ + 0, /* --, --, --, --, --, --, --, --, */ + 0, /* --, --, --, --, --, --, --, --, */ + 255 - 8 - 16, /* 20, 21, 22, --, --, 25, 26, 27, */ + 255, /* 28, 29, 2a, 2b, 2c, 2d, 2e, 2f, */ + 255, /* 30, 31, 32, 33, 34, 35, 36, 37, */ + 255, /* 38, 39, 3a, 3b, 3c, 3d, 3e, 3f, */ + 255, /* 40, 41, 42, 43, 44, 45, 46, 47, */ + 255, /* 48, 49, 4a, 4b, 4c, 4d, 4e, 4f, */ + 255, /* 50, 51, 52, 53, 54, 55, 56, 57, */ + 1 + 2 + 4 + 128, /* 58, 59, 5a, --, --, --, --, 5f, */ + 255 - 1, /* --, 61, 62, 63, 64, 65, 66, 67, */ + 255, /* 68, 69, 6a, 6b, 6c, 6d, 6e, 6f, */ + 255, /* 70, 71, 72, 73, 74, 75, 76, 77, */ + 1 + 2 + 4, /* 78, 79, 7a, --, --, --, --, --, */ }; + int i, j; + for (; *s; s++) { - if (minimal_ascii_table[*s & 0x7F] != *s) - return -1; /* failed */ + i = *s >> 3; /* i = *s / 8; */ + j = 1 << (*s & 3); /* j = 1 << (*s % 8); */ + + if (i >= ARRAY_SIZE(minimal_ascii_table) || + !(minimal_ascii_table[i] & j)) + return -EINVAL; } - /* String conforms to minimal-ascii, as specified by IEEE 1212, - * par. 7.4 */ return 0; } +/* IEEE 1212 clause 7.5.4.1 textual descriptors (English, minimal ASCII) */ struct csr1212_keyval *csr1212_new_string_descriptor_leaf(const char *s) { - /* Check if string conform to minimal_ascii format */ - if (csr1212_check_minimal_ascii(s)) - return NULL; - - /* IEEE 1212, par. 7.5.4.1 Textual descriptors (minimal ASCII) */ - return csr1212_new_textual_descriptor_leaf(0, 0, 0, s, strlen(s)); -} - -struct csr1212_keyval *csr1212_new_icon_descriptor_leaf(u_int32_t version, - u_int8_t palette_depth, - u_int8_t color_space, - u_int16_t language, - u_int16_t hscan, - u_int16_t vscan, - u_int32_t *palette, - u_int32_t *pixels) -{ - static const int pd[4] = { 0, 4, 16, 256 }; - static const int cs[16] = { 4, 2 }; struct csr1212_keyval *kv; - int palette_size; - int pixel_size = (hscan * vscan + 3) & ~0x3; + u32 *text; + size_t str_len, quads; - if (!pixels || (!palette && palette_depth) || - (palette_depth & ~0x3) || (color_space & ~0xf)) + if (!s || !*s || csr1212_check_minimal_ascii(s)) 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_OVERH |