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