91dea65c3fceb55c93ce80a1d8b777573f1a31d2
[linux-flexiantxendom0-3.2.10.git] / arch / ia64 / sn / io / ioconfig_bus.c
1 /* $Id$
2  *
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.
6  *
7  *  ioconfig_bus - SGI's Persistent PCI Bus Numbering.
8  *
9  * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc.  All rights reserved.
10  */
11
12 #include <linux/types.h>
13 #include <linux/slab.h>
14 #include <linux/ctype.h>
15 #include <linux/module.h>
16 #include <linux/init.h>
17
18 #include <linux/pci.h>
19
20 #include <asm/sn/sgi.h>
21 #include <linux/devfs_fs.h>
22 #include <linux/devfs_fs_kernel.h>
23 #include <asm/io.h>
24 #include <asm/sn/iograph.h>
25 #include <asm/sn/invent.h>
26 #include <asm/sn/hcl.h>
27 #include <asm/sn/labelcl.h>
28 #include <asm//sn/sn_sal.h>
29 #include <asm/sn/addrs.h>
30 #include <asm/sn/ioconfig_bus.h>
31
32 #define SGI_IOCONFIG_BUS "SGI-PERSISTENT PCI BUS NUMBERING"
33 #define SGI_IOCONFIG_BUS_VERSION "1.0"
34
35 /*
36  * Some Global definitions.
37  */
38 devfs_handle_t ioconfig_bus_handle = NULL;
39 unsigned long ioconfig_bus_debug = 0;
40
41 #ifdef IOCONFIG_BUS_DEBUG
42 #define DBG(x...)       printk(x)
43 #else
44 #define DBG(x...)
45 #endif
46
47 u64 ioconfig_file = 0;
48 u64 ioconfig_file_size = 0;
49 u64 ioconfig_activated = 0;
50 char ioconfig_kernopts[128];
51
52 /*
53  * For debugging purpose .. hardcode a table ..
54  */
55 struct  ascii_moduleid *ioconfig_bus_table;
56 u64 ioconfig_bus_table_size = 0;
57
58
59 int free_entry = 0;
60 int new_entry = 0;
61
62 int next_basebus_number = 0;
63
64 void
65 ioconfig_get_busnum(char *io_moduleid, int *bus_num)
66 {
67         struct  ascii_moduleid  *temp;
68         int index;
69
70         DBG("ioconfig_get_busnum io_moduleid %s\n", io_moduleid);
71
72         *bus_num = -1;
73         temp = ioconfig_bus_table;
74         for (index = 0; index < free_entry; temp++, index++) {
75                 if ( (io_moduleid[0] == temp->io_moduleid[0]) &&
76                      (io_moduleid[1] == temp->io_moduleid[1]) &&
77                      (io_moduleid[2] == temp->io_moduleid[2]) &&
78                      (io_moduleid[4] == temp->io_moduleid[4]) &&
79                      (io_moduleid[5] == temp->io_moduleid[5]) ) {
80                         *bus_num = index * 0x10;
81                         return;
82                 }
83         }
84
85         /*
86          * New IO Brick encountered.
87          */
88         if (((int)io_moduleid[0]) == 0) {
89                 DBG("ioconfig_get_busnum: Invalid Module Id given %s\n", io_moduleid);
90                 return;
91         }
92
93         io_moduleid[3] = '#';
94         strcpy((char *)&(ioconfig_bus_table[free_entry].io_moduleid), io_moduleid);
95         *bus_num = free_entry * 0x10;
96         free_entry++;
97 }
98
99 void
100 dump_ioconfig_table()
101 {
102
103         int index = 0;
104         struct ascii_moduleid *temp;
105
106         temp = ioconfig_bus_table;
107         while (index < free_entry) {
108                 DBG("ASSCI Module ID %s\n", temp->io_moduleid);
109                 temp++;
110                 index++;
111         }
112 }
113
114 /*
115  * nextline
116  *      This routine returns the nextline in the buffer.
117  */
118 int nextline(char *buffer, char **next, char *line)
119 {
120
121         char *temp;
122
123         if (buffer[0] == 0x0) {
124                 return(0);
125         }
126
127         temp = buffer;
128         while (*temp != 0) {
129                 *line = *temp;
130                 if (*temp != '\n'){
131                         *line = *temp;
132                         temp++; line++;
133                 } else
134                         break;
135         }
136
137         if (*temp == 0)
138                 *next = temp;
139         else
140                 *next = ++temp;
141
142         return(1);
143 }
144
145 /*
146  * build_pcibus_name
147  *      This routine parses the ioconfig contents read into
148  *      memory by ioconfig command in EFI and builds the
149  *      persistent pci bus naming table.
150  */
151 void
152 build_moduleid_table(char *file_contents, struct ascii_moduleid *table)
153 {
154         /*
155          * Read the whole file into memory.
156          */
157         int rc;
158         char *name;
159         char *temp;
160         char *next;
161         char *current;
162         char *line;
163         struct ascii_moduleid *moduleid;
164
165         line = kmalloc(256, GFP_KERNEL);
166         memset(line, 0,256);
167         name = kmalloc(125, GFP_KERNEL);
168         memset(name, 0, 125);
169         moduleid = table;
170         current = file_contents;
171         while (nextline(current, &next, line)){
172
173                 DBG("current 0x%lx next 0x%lx\n", current, next);
174
175                 temp = line;
176                 /*
177                  * Skip all leading Blank lines ..
178                  */
179                 while (isspace(*temp))
180                         if (*temp != '\n')
181                                 temp++;
182                         else
183                                 break;
184
185                 if (*temp == '\n') {
186                         current = next;
187                         memset(line, 0, 256);
188                         continue;
189                 }
190  
191                 /*
192                  * Skip comment lines
193                  */
194                 if (*temp == '#') {
195                         current = next;
196                         memset(line, 0, 256);
197                         continue;
198                 }
199
200                 /*
201                  * Get the next free entry in the table.
202                  */
203                 rc = sscanf(temp, "%s", name);
204                 strcpy(&moduleid->io_moduleid[0], name);
205                 DBG("Found %s\n", name);
206                 moduleid++;
207                 free_entry++;
208                 current = next;
209                 memset(line, 0, 256);
210         }
211
212         new_entry = free_entry;
213         kfree(line);
214         kfree(name);
215
216         return;
217 }
218
219 void
220 ioconfig_bus_init(void)
221 {
222
223         struct ia64_sal_retval ret_stuff;
224         u64     *temp;
225         int     cnode;
226
227         DBG("ioconfig_bus_init called.\n");
228
229         for (cnode = 0; cnode < numnodes; cnode++) {
230                 nasid_t nasid;
231                 /*
232                  * Make SAL call to get the address of the bus configuration table.
233                  */
234                 ret_stuff.status = (uint64_t)0;
235                 ret_stuff.v0 = (uint64_t)0;
236                 ret_stuff.v1 = (uint64_t)0;
237                 ret_stuff.v2 = (uint64_t)0;
238                 nasid = COMPACT_TO_NASID_NODEID(cnode);
239                 SAL_CALL(ret_stuff, SN_SAL_BUS_CONFIG, 0, nasid, 0, 0, 0, 0, 0);
240                 temp = (u64 *)TO_NODE_CAC(nasid, ret_stuff.v0);
241                 ioconfig_file = *temp;
242                 DBG("ioconfig_bus_init: Nasid %d ret_stuff.v0 0x%lx\n", nasid,
243                         ret_stuff.v0);
244                 if (ioconfig_file) {
245                         ioconfig_file_size = ret_stuff.v1;
246                         ioconfig_file = (ioconfig_file | CACHEABLE_MEM_SPACE);
247                         ioconfig_activated = 1;
248                         break;
249                 }
250         }
251
252         DBG("ioconfig_bus_init: ret_stuff.v0 %p ioconfig_file %p %d\n",
253                 ret_stuff.v0, (void *)ioconfig_file, (int)ioconfig_file_size);
254
255         ioconfig_bus_table = kmalloc( 512, GFP_KERNEL );
256         memset(ioconfig_bus_table, 0, 512);
257
258         /*
259          * If ioconfig options are given on the bootline .. take it.
260          */
261         if (*ioconfig_kernopts != '\0') {
262                 /*
263                  * ioconfig="..." kernel options given.
264                  */
265                 DBG("ioconfig_bus_init: Kernel Options given.\n");
266                 (void) build_moduleid_table((char *)ioconfig_kernopts, ioconfig_bus_table);
267                 (void) dump_ioconfig_table(ioconfig_bus_table);
268                 return;
269         }
270
271         if (ioconfig_activated) {
272                 DBG("ioconfig_bus_init: ioconfig file given.\n");
273                 (void) build_moduleid_table((char *)ioconfig_file, ioconfig_bus_table);
274                 (void) dump_ioconfig_table(ioconfig_bus_table);
275         } else {
276                 DBG("ioconfig_bus_init: ioconfig command not executed in prom\n");
277         }
278
279 }
280
281 void
282 ioconfig_bus_new_entries(void)
283 {
284
285         
286         int index = 0;
287         struct ascii_moduleid *temp;
288
289         if ((ioconfig_activated) && (free_entry > new_entry)) {
290                 printk("### Please add the following new IO Bricks Module ID \n");
291                 printk("### to your Persistent Bus Numbering Config File\n");
292         } else
293                 return;
294
295         index = new_entry;
296         temp = &ioconfig_bus_table[index];
297         while (index < free_entry) {
298                 printk("%s\n", temp);
299                 temp++;
300                 index++;
301         }
302         printk("### End\n");
303
304 }
305 static int ioconfig_bus_ioctl(struct inode * inode, struct file * file,
306         unsigned int cmd, unsigned long arg)
307 {
308
309         struct ioconfig_parm parm;
310
311         /*
312          * Copy in the parameters.
313          */
314         copy_from_user(&parm, (char *)arg, sizeof(struct ioconfig_parm));
315         parm.number = free_entry - new_entry;
316         parm.ioconfig_activated = ioconfig_activated;
317         copy_to_user((char *)arg, &parm, sizeof(struct ioconfig_parm));
318         copy_to_user((char *)parm.buffer, &ioconfig_bus_table[new_entry], sizeof(struct  ascii_moduleid) * (free_entry - new_entry));
319
320         return 0;
321 }
322
323 /*
324  * ioconfig_bus_open - Opens the special device node "/dev/hw/.ioconfig_bus".
325  */
326 static int ioconfig_bus_open(struct inode * inode, struct file * filp)
327 {
328         if (ioconfig_bus_debug) {
329                 DBG("ioconfig_bus_open called.\n");
330         }
331
332         return(0);
333
334 }
335
336 /*
337  * ioconfig_bus_close - Closes the special device node "/dev/hw/.ioconfig_bus".
338  */
339 static int ioconfig_bus_close(struct inode * inode, struct file * filp)
340 {
341
342         if (ioconfig_bus_debug) {
343                 DBG("ioconfig_bus_close called.\n");
344         }
345
346         return(0);
347 }
348
349 struct file_operations ioconfig_bus_fops = {
350         ioctl:ioconfig_bus_ioctl,
351         open:ioconfig_bus_open,         /* open */
352         release:ioconfig_bus_close      /* release */
353 };
354
355
356 /*
357  * init_ifconfig_bus() - Boot time initialization.  Ensure that it is called 
358  *      after devfs has been initialized.
359  *
360  */
361 int init_ioconfig_bus(void)
362 {
363         ioconfig_bus_handle = NULL;
364         ioconfig_bus_handle = hwgraph_register(hwgraph_root, ".ioconfig_bus",
365                         0, DEVFS_FL_AUTO_DEVNUM,
366                         0, 0,
367                         S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
368                         &ioconfig_bus_fops, NULL);
369
370         if (ioconfig_bus_handle == NULL) {
371                 panic("Unable to create SGI PERSISTENT BUS NUMBERING Driver.\n");
372         }
373
374         return(0);
375
376 }
377
378 static int __init ioconfig_bus_setup (char *str)
379 {
380
381         char *temp;
382
383         DBG("ioconfig_bus_setup: Kernel Options %s\n", str);
384
385         temp = (char *)ioconfig_kernopts;
386         memset(temp, 0, 128);
387         while ( (*str != '\0') && !isspace (*str) ) {
388                 if (*str == ',') {
389                         *temp = '\n';
390                         temp++;
391                         str++;
392                         continue;
393                 }
394                 *temp = *str;
395                 temp++;
396                 str++;
397         }
398
399         return(0);
400                 
401 }
402 __setup("ioconfig=", ioconfig_bus_setup);