2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
9 #include <linux/types.h>
10 #include <linux/slab.h>
11 #include <linux/init.h>
12 #include <linux/string.h>
13 #include <asm/sn/sgi.h>
14 #include <asm/sn/sn_sal.h>
15 #include <asm/sn/io.h>
16 #include <asm/sn/hcl.h>
17 #include <asm/sn/labelcl.h>
18 #include <asm/sn/xtalk/xbow.h>
19 #include <asm/sn/klconfig.h>
20 #include <asm/sn/module.h>
21 #include <asm/sn/pci/pcibr.h>
22 #include <asm/sn/xtalk/xswitch.h>
23 #include <asm/sn/nodepda.h>
24 #include <asm/sn/sn_cpuid.h>
27 /* #define LDEBUG 1 */
30 #define DPRINTF printk
36 module_t *sn_modules[MODULE_MAX];
39 #define SN00_SERIAL_FUDGE 0x3b1af409d513c2
40 #define SN0_SERIAL_FUDGE 0x6e
44 encode_str_serial(const char *src, char *dest)
48 for (i = 0; i < MAX_SERIAL_NUM_SIZE; i++) {
50 dest[i] = src[MAX_SERIAL_NUM_SIZE/2 +
51 ((i%2) ? ((i/2 * -1) - 1) : (i/2))] +
57 module_lookup(moduleid_t id)
61 for (i = 0; i < nummodules; i++)
62 if (sn_modules[i]->id == id) {
63 DPRINTF("module_lookup: found m=0x%p\n", sn_modules[i]);
73 * The first time a new module number is seen, a module structure is
74 * inserted into the module list in order sorted by module number
75 * and the structure is initialized.
77 * The node number is added to the list of nodes in the module.
79 static module_t * __init
80 module_add_node(geoid_t geoid, cnodeid_t cnodeid)
88 memset(buffer, 0, 16);
89 moduleid = geo_module(geoid);
90 format_module_id(buffer, moduleid, MODULE_FORMAT_BRIEF);
91 DPRINTF("module_add_node: moduleid=%s node=%d\n", buffer, cnodeid);
93 if ((m = module_lookup(moduleid)) == 0) {
94 m = kmalloc(sizeof (module_t), GFP_KERNEL);
96 memset(m, 0 , sizeof(module_t));
98 for (slab_number = 0; slab_number <= MAX_SLABS; slab_number++) {
99 m->nodes[slab_number] = -1;
103 spin_lock_init(&m->lock);
105 /* Insert in sorted order by module number */
107 for (i = nummodules; i > 0 && sn_modules[i - 1]->id > moduleid; i--)
108 sn_modules[i] = sn_modules[i - 1];
115 * Save this information in the correct slab number of the node in the
118 slab_number = geo_slab(geoid);
119 DPRINTF("slab number added 0x%x\n", slab_number);
121 if (m->nodes[slab_number] != -1) {
122 printk("module_add_node .. slab previously found\n");
126 m->nodes[slab_number] = cnodeid;
127 m->geoid[slab_number] = geoid;
133 module_probe_snum(module_t *m, nasid_t host_nasid, nasid_t nasid)
136 klmod_serial_num_t *comp;
137 char serial_number[16];
140 * record brick serial number
142 board = find_lboard_nasid((lboard_t *) KL_CONFIG_INFO(host_nasid), host_nasid, KLTYPE_SNIA);
144 if (! board || KL_CONFIG_DUPLICATE_BOARD(board))
149 board_serial_number_get( board, serial_number );
150 if( serial_number[0] != '\0' ) {
151 encode_str_serial( serial_number, m->snum.snum_str );
155 board = find_lboard_nasid((lboard_t *) KL_CONFIG_INFO(nasid),
156 nasid, KLTYPE_IOBRICK_XBOW);
158 if (! board || KL_CONFIG_DUPLICATE_BOARD(board))
161 comp = GET_SNUM_COMP(board);
164 if (comp->snum.snum_str[0] != '\0') {
165 memcpy(m->sys_snum, comp->snum.snum_str,
166 MAX_SERIAL_NUM_SIZE);
167 m->sys_snum_valid = 1;
171 if (m->sys_snum_valid)
174 DPRINTF("Invalid serial number for module %d, "
175 "possible missing or invalid NIC.", m->id);
188 extern int numionodes;
190 DPRINTF("*******module_init\n");
195 * First pass just scan for compute node boards KLTYPE_SNIA.
196 * We do not support memoryless compute nodes.
198 for (node = 0; node < numnodes; node++) {
199 nasid = cnodeid_to_nasid(node);
200 board = find_lboard_nasid((lboard_t *) KL_CONFIG_INFO(nasid), nasid, KLTYPE_SNIA);
203 HWGRAPH_DEBUG(__FILE__, __FUNCTION__, __LINE__, NULL, NULL, "Found Shub lboard 0x%lx nasid 0x%x cnode 0x%x \n", (unsigned long)board, (int)nasid, (int)node);
205 m = module_add_node(board->brd_geoid, node);
206 if (! m->snum_valid && module_probe_snum(m, nasid, nasid))
211 * Second scan, look for headless/memless board hosted by compute nodes.
213 for (node = numnodes; node < numionodes; node++) {
215 char serial_number[16];
217 nasid = cnodeid_to_nasid(node);
218 board = find_lboard_nasid((lboard_t *) KL_CONFIG_INFO(nasid),
222 HWGRAPH_DEBUG(__FILE__, __FUNCTION__, __LINE__, NULL, NULL, "Found headless/memless lboard 0x%lx node %d nasid %d cnode %d\n", (unsigned long)board, node, (int)nasid, (int)node);
224 m = module_add_node(board->brd_geoid, node);
227 * Get and initialize the serial number.
229 board_serial_number_get( board, serial_number );
230 if( serial_number[0] != '\0' ) {
231 encode_str_serial( serial_number, m->snum.snum_str );