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
7 * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
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 */
31 #define DPRINTF printk
37 module_t
*modules
[MODULE_MAX
];
40 #define SN00_SERIAL_FUDGE 0x3b1af409d513c2
41 #define SN0_SERIAL_FUDGE 0x6e
44 encode_int_serial(uint64_t src
,uint64_t *dest
)
49 val
= src
+ SN00_SERIAL_FUDGE
;
52 for (i
= 0; i
< sizeof(long long); i
++) {
54 ((char*)&val
)[sizeof(long long)/2 +
55 ((i
%2) ? ((i
/2 * -1) - 1) : (i
/2))];
61 decode_int_serial(uint64_t src
, uint64_t *dest
)
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))] =
72 *dest
= val
- SN00_SERIAL_FUDGE
;
77 encode_str_serial(const char *src
, char *dest
)
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))] +
90 decode_str_serial(const char *src
, char *dest
)
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
] -
102 module_t
*module_lookup(moduleid_t id
)
106 for (i
= 0; i
< nummodules
; i
++)
107 if (modules
[i
]->id
== id
) {
108 DPRINTF("module_lookup: found m=0x%p\n", modules
[i
]);
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
)
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
));
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];
156 m
->nodes
[m
->nodecnt
] = cnodeid
;
157 m
->geoid
[m
->nodecnt
] = geoid
;
160 DPRINTF("module_add_node: module %s now has %d nodes\n", buffer
, m
->nodecnt
);
165 int module_probe_snum(module_t
*m
, nasid_t nasid
)
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
))
180 printf ("module_probe_snum: no IP35 board found!\n");
185 board_serial_number_get( board
, serial_number
);
186 if( serial_number
[0] != '\0' ) {
187 encode_str_serial( serial_number
, m
->snum
.snum_str
);
192 printf("module_probe_snum: brick serial number is null!\n");
194 printf("module_probe_snum: brick serial number == %s\n", serial_number
);
197 board
= find_lboard((lboard_t
*) KL_CONFIG_INFO(nasid
),
198 KLTYPE_IOBRICK_XBOW
);
200 if (! board
|| KL_CONFIG_DUPLICATE_BOARD(board
))
203 comp
= GET_SNUM_COMP(board
);
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 */
217 if (comp
->snum
.snum_str
[0] != '\0') {
218 bcopy(comp
->snum
.snum_str
,
220 MAX_SERIAL_NUM_SIZE
);
221 m
->sys_snum_valid
= 1;
225 if (m
->sys_snum_valid
)
228 DPRINTF("Invalid serial number for module %d, "
229 "possible missing or invalid NIC.", m
->id
);
243 DPRINTF("*******module_init\n");
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
);
253 m
= module_add_node(board
->brd_geoid
, node
);
255 if (! m
->snum_valid
&& module_probe_snum(m
, nasid
))
259 DPRINTF("********found total of %d serial numbers in the system\n",
263 DPRINTF(KERN_WARNING
"io_module_init: No serial number found.\n");