Merge with 2.5.75.
[linux-2.6/linux-mips.git] / arch / ia64 / sn / io / sn2 / module.c
blobe7a32c49b4a0fd3c04df865af7e32ed7e8cae4ab
1 /* $Id$
3 * This file is subject to the terms and conditions of the GNU General Public
4 * License. See the file "COPYING" in the main directory of this archive
5 * for more details.
7 * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
8 */
10 #include <linux/types.h>
11 #include <linux/slab.h>
12 #include <asm/sn/sgi.h>
13 #include <asm/sn/sn_sal.h>
14 #include <asm/sn/io.h>
15 #include <asm/sn/invent.h>
16 #include <asm/sn/hcl.h>
17 #include <asm/sn/labelcl.h>
18 #include <asm/sn/xtalk/xbow.h>
19 #include <asm/sn/pci/bridge.h>
20 #include <asm/sn/klconfig.h>
21 #include <asm/sn/module.h>
22 #include <asm/sn/pci/pcibr.h>
23 #include <asm/sn/xtalk/xswitch.h>
24 #include <asm/sn/nodepda.h>
25 #include <asm/sn/sn_cpuid.h>
28 /* #define LDEBUG 1 */
30 #ifdef LDEBUG
31 #define DPRINTF printk
32 #define printf printk
33 #else
34 #define DPRINTF(x...)
35 #endif
37 module_t *modules[MODULE_MAX];
38 int nummodules;
40 #define SN00_SERIAL_FUDGE 0x3b1af409d513c2
41 #define SN0_SERIAL_FUDGE 0x6e
43 void
44 encode_int_serial(uint64_t src,uint64_t *dest)
46 uint64_t val;
47 int i;
49 val = src + SN00_SERIAL_FUDGE;
52 for (i = 0; i < sizeof(long long); i++) {
53 ((char*)dest)[i] =
54 ((char*)&val)[sizeof(long long)/2 +
55 ((i%2) ? ((i/2 * -1) - 1) : (i/2))];
60 void
61 decode_int_serial(uint64_t src, uint64_t *dest)
63 uint64_t val;
64 int i;
66 for (i = 0; i < sizeof(long long); i++) {
67 ((char*)&val)[sizeof(long long)/2 +
68 ((i%2) ? ((i/2 * -1) - 1) : (i/2))] =
69 ((char*)&src)[i];
72 *dest = val - SN00_SERIAL_FUDGE;
76 void
77 encode_str_serial(const char *src, char *dest)
79 int i;
81 for (i = 0; i < MAX_SERIAL_NUM_SIZE; i++) {
83 dest[i] = src[MAX_SERIAL_NUM_SIZE/2 +
84 ((i%2) ? ((i/2 * -1) - 1) : (i/2))] +
85 SN0_SERIAL_FUDGE;
89 void
90 decode_str_serial(const char *src, char *dest)
92 int i;
94 for (i = 0; i < MAX_SERIAL_NUM_SIZE; i++) {
95 dest[MAX_SERIAL_NUM_SIZE/2 +
96 ((i%2) ? ((i/2 * -1) - 1) : (i/2))] = src[i] -
97 SN0_SERIAL_FUDGE;
102 module_t *module_lookup(moduleid_t id)
104 int i;
106 for (i = 0; i < nummodules; i++)
107 if (modules[i]->id == id) {
108 DPRINTF("module_lookup: found m=0x%p\n", modules[i]);
109 return modules[i];
112 return NULL;
116 * module_add_node
118 * The first time a new module number is seen, a module structure is
119 * inserted into the module list in order sorted by module number
120 * and the structure is initialized.
122 * The node number is added to the list of nodes in the module.
125 module_t *module_add_node(geoid_t geoid, cnodeid_t cnodeid)
127 module_t *m;
128 int i;
129 char buffer[16];
130 moduleid_t moduleid;
132 memset(buffer, 0, 16);
133 moduleid = geo_module(geoid);
134 format_module_id(buffer, moduleid, MODULE_FORMAT_BRIEF);
135 DPRINTF("module_add_node: moduleid=%s node=%d\n", buffer, cnodeid);
137 if ((m = module_lookup(moduleid)) == 0) {
138 m = kmalloc(sizeof (module_t), GFP_KERNEL);
139 memset(m, 0 , sizeof(module_t));
140 ASSERT_ALWAYS(m);
142 m->id = moduleid;
143 spin_lock_init(&m->lock);
145 mutex_init_locked(&m->thdcnt);
147 /* Insert in sorted order by module number */
149 for (i = nummodules; i > 0 && modules[i - 1]->id > moduleid; i--)
150 modules[i] = modules[i - 1];
152 modules[i] = m;
153 nummodules++;
156 m->nodes[m->nodecnt] = cnodeid;
157 m->geoid[m->nodecnt] = geoid;
158 m->nodecnt++;
160 DPRINTF("module_add_node: module %s now has %d nodes\n", buffer, m->nodecnt);
162 return m;
165 int module_probe_snum(module_t *m, nasid_t nasid)
167 lboard_t *board;
168 klmod_serial_num_t *comp;
169 char * bcopy(const char * src, char * dest, int count);
170 char serial_number[16];
173 * record brick serial number
175 board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
177 if (! board || KL_CONFIG_DUPLICATE_BOARD(board))
179 #if LDEBUG
180 printf ("module_probe_snum: no IP35 board found!\n");
181 #endif
182 return 0;
185 board_serial_number_get( board, serial_number );
186 if( serial_number[0] != '\0' ) {
187 encode_str_serial( serial_number, m->snum.snum_str );
188 m->snum_valid = 1;
190 #if LDEBUG
191 else {
192 printf("module_probe_snum: brick serial number is null!\n");
194 printf("module_probe_snum: brick serial number == %s\n", serial_number);
195 #endif /* DEBUG */
197 board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid),
198 KLTYPE_IOBRICK_XBOW);
200 if (! board || KL_CONFIG_DUPLICATE_BOARD(board))
201 return 0;
203 comp = GET_SNUM_COMP(board);
205 if (comp) {
206 #if LDEBUG
207 int i;
209 printf("********found module with id %x and string", m->id);
211 for (i = 0; i < MAX_SERIAL_NUM_SIZE; i++)
212 printf(" %x ", comp->snum.snum_str[i]);
214 printf("\n"); /* Fudged string is not ASCII */
215 #endif
217 if (comp->snum.snum_str[0] != '\0') {
218 bcopy(comp->snum.snum_str,
219 m->sys_snum,
220 MAX_SERIAL_NUM_SIZE);
221 m->sys_snum_valid = 1;
225 if (m->sys_snum_valid)
226 return 1;
227 else {
228 DPRINTF("Invalid serial number for module %d, "
229 "possible missing or invalid NIC.", m->id);
230 return 0;
234 void
235 io_module_init(void)
237 cnodeid_t node;
238 lboard_t *board;
239 nasid_t nasid;
240 int nserial;
241 module_t *m;
243 DPRINTF("*******module_init\n");
245 nserial = 0;
247 for (node = 0; node < numnodes; node++) {
248 nasid = COMPACT_TO_NASID_NODEID(node);
250 board = find_lboard((lboard_t *) KL_CONFIG_INFO(nasid), KLTYPE_SNIA);
251 ASSERT(board);
253 m = module_add_node(board->brd_geoid, node);
255 if (! m->snum_valid && module_probe_snum(m, nasid))
256 nserial++;
259 DPRINTF("********found total of %d serial numbers in the system\n",
260 nserial);
262 if (nserial == 0)
263 DPRINTF(KERN_WARNING "io_module_init: No serial number found.\n");