config_roms.c 4.5 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
/*
 * IEEE 1394 for Linux
 *
 * ConfigROM  entries
 *
 * Copyright (C) 2004 Ben Collins
 *
 * This code is licensed under the GPL.  See the file COPYING in the root
 * directory of the kernel sources for details.
 */

#include <linux/types.h>

#include "csr1212.h"
#include "ieee1394.h"
#include "ieee1394_types.h"
#include "hosts.h"
#include "ieee1394_core.h"
#include "highlevel.h"
#include "csr.h"
#include "config_roms.h"

struct hpsb_config_rom_entry {
	const char *name;

	/* Base initialization, called at module load */
	int (*init)(void);

	/* Cleanup called at module exit */
	void (*cleanup)(void);

	/* The flag added to host->config_roms */
	unsigned int flag;
};

36
/* The default host entry. This must succeed. */
L
Linus Torvalds 已提交
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
int hpsb_default_host_entry(struct hpsb_host *host)
{
	struct csr1212_keyval *root;
	struct csr1212_keyval *vend_id = NULL;
	struct csr1212_keyval *text = NULL;
	char csr_name[128];
	int ret;

	sprintf(csr_name, "Linux - %s", host->driver->name);
	root = host->csr.rom->root_kv;

	vend_id = csr1212_new_immediate(CSR1212_KV_ID_VENDOR, host->csr.guid_hi >> 8);
	text = csr1212_new_string_descriptor_leaf(csr_name);

	if (!vend_id || !text) {
		if (vend_id)
			csr1212_release_keyval(vend_id);
		if (text)
			csr1212_release_keyval(text);
		csr1212_destroy_csr(host->csr.rom);
		return -ENOMEM;
	}

60
	csr1212_associate_keyval(vend_id, text);
L
Linus Torvalds 已提交
61
	csr1212_release_keyval(text);
62
	ret = csr1212_attach_keyval_to_directory(root, vend_id);
L
Linus Torvalds 已提交
63 64 65 66 67 68 69 70 71 72 73 74
	csr1212_release_keyval(vend_id);
	if (ret != CSR1212_SUCCESS) {
		csr1212_destroy_csr(host->csr.rom);
		return -ENOMEM;
	}

	host->update_config_rom = 1;

	return 0;
}


75
#ifdef CONFIG_IEEE1394_ETH1394_ROM_ENTRY
L
Linus Torvalds 已提交
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
#include "eth1394.h"

static struct csr1212_keyval *ip1394_ud;

static int config_rom_ip1394_init(void)
{
	struct csr1212_keyval *spec_id = NULL;
	struct csr1212_keyval *spec_desc = NULL;
	struct csr1212_keyval *ver = NULL;
	struct csr1212_keyval *ver_desc = NULL;
	int ret = -ENOMEM;

	ip1394_ud = csr1212_new_directory(CSR1212_KV_ID_UNIT);

	spec_id = csr1212_new_immediate(CSR1212_KV_ID_SPECIFIER_ID,
					ETHER1394_GASP_SPECIFIER_ID);
	spec_desc = csr1212_new_string_descriptor_leaf("IANA");
	ver = csr1212_new_immediate(CSR1212_KV_ID_VERSION,
				    ETHER1394_GASP_VERSION);
	ver_desc = csr1212_new_string_descriptor_leaf("IPv4");

	if (!ip1394_ud || !spec_id || !spec_desc || !ver || !ver_desc)
		goto ip1394_fail;

100 101 102 103 104 105
	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)
L
Linus Torvalds 已提交
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
		ret = 0;

ip1394_fail:
	if (ret && ip1394_ud) {
		csr1212_release_keyval(ip1394_ud);
		ip1394_ud = NULL;
	}

	if (spec_id)
		csr1212_release_keyval(spec_id);
	if (spec_desc)
		csr1212_release_keyval(spec_desc);
	if (ver)
		csr1212_release_keyval(ver);
	if (ver_desc)
		csr1212_release_keyval(ver_desc);

	return ret;
}

static void config_rom_ip1394_cleanup(void)
{
	if (ip1394_ud) {
		csr1212_release_keyval(ip1394_ud);
		ip1394_ud = NULL;
	}
}

134
int hpsb_config_rom_ip1394_add(struct hpsb_host *host)
L
Linus Torvalds 已提交
135 136 137 138 139 140 141 142
{
	if (!ip1394_ud)
		return -ENODEV;

	if (csr1212_attach_keyval_to_directory(host->csr.rom->root_kv,
					       ip1394_ud) != CSR1212_SUCCESS)
		return -ENOMEM;

143 144
	host->config_roms |= HPSB_CONFIG_ROM_ENTRY_IP1394;
	host->update_config_rom = 1;
L
Linus Torvalds 已提交
145 146
	return 0;
}
147
EXPORT_SYMBOL_GPL(hpsb_config_rom_ip1394_add);
L
Linus Torvalds 已提交
148

149
void hpsb_config_rom_ip1394_remove(struct hpsb_host *host)
L
Linus Torvalds 已提交
150 151
{
	csr1212_detach_keyval_from_directory(host->csr.rom->root_kv, ip1394_ud);
152 153
	host->config_roms &= ~HPSB_CONFIG_ROM_ENTRY_IP1394;
	host->update_config_rom = 1;
L
Linus Torvalds 已提交
154
}
155
EXPORT_SYMBOL_GPL(hpsb_config_rom_ip1394_remove);
L
Linus Torvalds 已提交
156 157 158 159 160 161 162 163

static struct hpsb_config_rom_entry ip1394_entry = {
	.name		= "ip1394",
	.init		= config_rom_ip1394_init,
	.cleanup	= config_rom_ip1394_cleanup,
	.flag		= HPSB_CONFIG_ROM_ENTRY_IP1394,
};

164
#endif /* CONFIG_IEEE1394_ETH1394_ROM_ENTRY */
L
Linus Torvalds 已提交
165 166

static struct hpsb_config_rom_entry *const config_rom_entries[] = {
167
#ifdef CONFIG_IEEE1394_ETH1394_ROM_ENTRY
L
Linus Torvalds 已提交
168 169 170 171
	&ip1394_entry,
#endif
};

172
/* Initialize all config roms */
L
Linus Torvalds 已提交
173 174 175 176
int hpsb_init_config_roms(void)
{
	int i, error = 0;

177
	for (i = 0; i < ARRAY_SIZE(config_rom_entries); i++)
L
Linus Torvalds 已提交
178 179 180 181
		if (config_rom_entries[i]->init()) {
			HPSB_ERR("Failed to initialize config rom entry `%s'",
				 config_rom_entries[i]->name);
			error = -1;
182
		}
L
Linus Torvalds 已提交
183 184 185 186

	return error;
}

187
/* Cleanup all config roms */
L
Linus Torvalds 已提交
188 189 190 191
void hpsb_cleanup_config_roms(void)
{
	int i;

192 193
	for (i = 0; i < ARRAY_SIZE(config_rom_entries); i++)
		config_rom_entries[i]->cleanup();
L
Linus Torvalds 已提交
194
}