ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / ia64 / sn / io / drivers / ioconfig_bus.c
1 /*
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
4  * for more details.
5  *
6  *  ioconfig_bus - SGI's Persistent PCI Bus Numbering.
7  *
8  * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc.  All rights reserved.
9  */
10
11 #include <linux/types.h>
12 #include <linux/slab.h>
13 #include <linux/ctype.h>
14 #include <linux/module.h>
15 #include <linux/init.h>
16
17 #include <linux/pci.h>
18
19 #include <asm/uaccess.h>
20 #include <asm/sn/sgi.h>
21 #include <asm/io.h>
22 #include <asm/sn/iograph.h>
23 #include <asm/sn/hcl.h>
24 #include <asm/sn/labelcl.h>
25 #include <asm/sn/sn_sal.h>
26 #include <asm/sn/addrs.h>
27 #include <asm/sn/ioconfig_bus.h>
28
29 #define SGI_IOCONFIG_BUS "SGI-PERSISTENT PCI BUS NUMBERING"
30 #define SGI_IOCONFIG_BUS_VERSION "1.0"
31
32 /*
33  * Some Global definitions.
34  */
35 static vertex_hdl_t ioconfig_bus_handle;
36 static unsigned long ioconfig_bus_debug;
37 static struct ioconfig_parm parm;
38
39 #ifdef IOCONFIG_BUS_DEBUG
40 #define DBG(x...)       printk(x)
41 #else
42 #define DBG(x...)
43 #endif
44
45 static u64 ioconfig_activated;
46 static char ioconfig_kernopts[128];
47
48 /*
49  * For debugging purpose .. hardcode a table ..
50  */
51 struct  ascii_moduleid *ioconfig_bus_table;
52
53 static int free_entry;
54 static int new_entry;
55
56 int next_basebus_number;
57
58 void
59 ioconfig_get_busnum(char *io_moduleid, int *bus_num)
60 {
61         struct  ascii_moduleid  *temp;
62         int index;
63
64         DBG("ioconfig_get_busnum io_moduleid %s\n", io_moduleid);
65
66         *bus_num = -1;
67         temp = ioconfig_bus_table;
68         if (!ioconfig_bus_table)
69                 return;
70         for (index = 0; index < free_entry; temp++, index++) {
71                 if ( (io_moduleid[0] == temp->io_moduleid[0]) &&
72                      (io_moduleid[1] == temp->io_moduleid[1]) &&
73                      (io_moduleid[2] == temp->io_moduleid[2]) &&
74                      (io_moduleid[4] == temp->io_moduleid[4]) &&
75                      (io_moduleid[5] == temp->io_moduleid[5]) ) {
76                         *bus_num = index * 0x10;
77                         return;
78                 }
79         }
80
81         /*
82          * New IO Brick encountered.
83          */
84         if (((int)io_moduleid[0]) == 0) {
85                 DBG("ioconfig_get_busnum: Invalid Module Id given %s\n", io_moduleid);
86                 return;
87         }
88
89         io_moduleid[3] = '#';
90         strcpy((char *)&(ioconfig_bus_table[free_entry].io_moduleid), io_moduleid);
91         *bus_num = free_entry * 0x10;
92         free_entry++;
93 }
94
95 static void
96 dump_ioconfig_table(void)
97 {
98
99         int index = 0;
100         struct ascii_moduleid *temp;
101
102         temp = ioconfig_bus_table;
103         if (!temp) {
104                 DBG("ioconfig_bus_table tabel empty\n");
105                 return;
106         }
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 int
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 *curr;
162         char *line;
163         struct ascii_moduleid *moduleid;
164
165         line = kmalloc(256, GFP_KERNEL);
166         name = kmalloc(125, GFP_KERNEL);
167         if (!line || !name) {
168                 if (line)
169                         kfree(line);
170                 if (name)
171                         kfree(name);
172                 printk("build_moduleid_table(): Unabled to allocate memmory");
173                 return -ENOMEM;
174         }
175
176         memset(line, 0,256);
177         memset(name, 0, 125);
178         moduleid = table;
179         curr = file_contents;
180         while (nextline(curr, &next, line)){
181
182                 DBG("curr 0x%lx next 0x%lx\n", curr, next);
183
184                 temp = line;
185                 /*
186                  * Skip all leading Blank lines ..
187                  */
188                 while (isspace(*temp))
189                         if (*temp != '\n')
190                                 temp++;
191                         else
192                                 break;
193
194                 if (*temp == '\n') {
195                         curr = next;
196                         memset(line, 0, 256);
197                         continue;
198                 }
199  
200                 /*
201                  * Skip comment lines
202                  */
203                 if (*temp == '#') {
204                         curr = next;
205                         memset(line, 0, 256);
206                         continue;
207                 }
208
209                 /*
210                  * Get the next free entry in the table.
211                  */
212                 rc = sscanf(temp, "%s", name);
213                 strcpy(&moduleid->io_moduleid[0], name);
214                 DBG("Found %s\n", name);
215                 moduleid++;
216                 free_entry++;
217                 curr = next;
218                 memset(line, 0, 256);
219         }
220
221         new_entry = free_entry;
222         kfree(line);
223         kfree(name);
224
225         return 0;
226 }
227
228 int
229 ioconfig_bus_init(void)
230 {
231
232         DBG("ioconfig_bus_init called.\n");
233
234         ioconfig_bus_table = kmalloc( 512, GFP_KERNEL );
235         if (!ioconfig_bus_table) {
236                 printk("ioconfig_bus_init : cannot allocate memory\n");
237                 return -1;
238         }
239
240         memset(ioconfig_bus_table, 0, 512);
241
242         /*
243          * If ioconfig options are given on the bootline .. take it.
244          */
245         if (*ioconfig_kernopts != '\0') {
246                 /*
247                  * ioconfig="..." kernel options given.
248                  */
249                 DBG("ioconfig_bus_init: Kernel Options given.\n");
250                 if ( build_moduleid_table((char *)ioconfig_kernopts, ioconfig_bus_table) < 0 )
251                         return -1;
252                 (void) dump_ioconfig_table();
253         }
254         return 0;
255 }
256
257 void
258 ioconfig_bus_new_entries(void)
259 {
260         int index;
261         struct ascii_moduleid *temp;
262
263         if ((ioconfig_activated) && (free_entry > new_entry)) {
264                 printk("### Please add the following new IO Bricks Module ID \n");
265                 printk("### to your Persistent Bus Numbering Config File\n");
266         } else
267                 return;
268
269         index = new_entry;
270         if (!ioconfig_bus_table) {
271                 printk("ioconfig_bus_table table is empty\n");
272                 return;
273         }
274         temp = &ioconfig_bus_table[index];
275         while (index < free_entry) {
276                 printk("%s\n", (char *)temp);
277                 temp++;
278                 index++;
279         }
280         printk("### End\n");
281
282 }
283 static int ioconfig_bus_ioctl(struct inode * inode, struct file * file,
284         unsigned int cmd, unsigned long arg)
285 {
286         /*
287          * Copy in the parameters.
288          */
289         if (copy_from_user(&parm, (char *)arg, sizeof(struct ioconfig_parm)))
290                 return -EFAULT;
291         parm.number = free_entry - new_entry;
292         parm.ioconfig_activated = ioconfig_activated;
293         if (copy_to_user((char *)arg, &parm, sizeof(struct ioconfig_parm)))
294                 return -EFAULT;
295
296         if (!ioconfig_bus_table)
297                 return -EFAULT;
298
299         if (copy_to_user((char *)parm.buffer, &ioconfig_bus_table[new_entry], sizeof(struct  ascii_moduleid) * (free_entry - new_entry)))
300                 return -EFAULT;
301
302         return 0;
303 }
304
305 /*
306  * ioconfig_bus_open - Opens the special device node "/dev/hw/.ioconfig_bus".
307  */
308 static int ioconfig_bus_open(struct inode * inode, struct file * filp)
309 {
310         if (ioconfig_bus_debug) {
311                 DBG("ioconfig_bus_open called.\n");
312         }
313
314         return(0);
315
316 }
317
318 /*
319  * ioconfig_bus_close - Closes the special device node "/dev/hw/.ioconfig_bus".
320  */
321 static int ioconfig_bus_close(struct inode * inode, struct file * filp)
322 {
323
324         if (ioconfig_bus_debug) {
325                 DBG("ioconfig_bus_close called.\n");
326         }
327
328         return(0);
329 }
330
331 struct file_operations ioconfig_bus_fops = {
332         .ioctl  = ioconfig_bus_ioctl,
333         .open   = ioconfig_bus_open,    /* open */
334         .release=ioconfig_bus_close     /* release */
335 };
336
337
338 /*
339  * init_ifconfig_bus() - Boot time initialization.  Ensure that it is called 
340  *      after hwgfs has been initialized.
341  *
342  */
343 int init_ioconfig_bus(void)
344 {
345         ioconfig_bus_handle = hwgraph_register(hwgraph_root, ".ioconfig_bus",
346                         0, 0,
347                         0, 0,
348                         S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
349                         &ioconfig_bus_fops, NULL);
350
351         if (ioconfig_bus_handle == NULL) {
352                 panic("Unable to create SGI PERSISTENT BUS NUMBERING Driver.\n");
353         }
354
355         return 0;
356 }
357
358 static int __init ioconfig_bus_setup (char *str)
359 {
360
361         char *temp;
362
363         DBG("ioconfig_bus_setup: Kernel Options %s\n", str);
364
365         temp = (char *)ioconfig_kernopts;
366         memset(temp, 0, 128);
367         while ( (*str != '\0') && !isspace (*str) ) {
368                 if (*str == ',') {
369                         *temp = '\n';
370                         temp++;
371                         str++;
372                         continue;
373                 }
374                 *temp = *str;
375                 temp++;
376                 str++;
377         }
378
379         return(0);
380                 
381 }
382 __setup("ioconfig=", ioconfig_bus_setup);