initial commit with v2.6.9
[linux-2.6.9-moxart.git] / arch / ia64 / sn / io / drivers / ioconfig_bus.c
bloba0a1eca2170c13ede8b696986278987887727e76
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.
6 * ioconfig_bus - SGI's Persistent PCI Bus Numbering.
8 * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
9 */
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>
17 #include <linux/pci.h>
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>
29 #define SGI_IOCONFIG_BUS "SGI-PERSISTENT PCI BUS NUMBERING"
30 #define SGI_IOCONFIG_BUS_VERSION "1.0"
33 * Some Global definitions.
35 static vertex_hdl_t ioconfig_bus_handle;
36 static unsigned long ioconfig_bus_debug;
37 static struct ioconfig_parm parm;
39 #ifdef IOCONFIG_BUS_DEBUG
40 #define DBG(x...) printk(x)
41 #else
42 #define DBG(x...)
43 #endif
45 static u64 ioconfig_activated;
46 static char ioconfig_kernopts[128];
49 * For debugging purpose .. hardcode a table ..
51 struct ascii_moduleid *ioconfig_bus_table;
53 static int free_entry;
54 static int new_entry;
56 int next_basebus_number;
58 void
59 ioconfig_get_busnum(char *io_moduleid, int *bus_num)
61 struct ascii_moduleid *temp;
62 int index;
64 DBG("ioconfig_get_busnum io_moduleid %s\n", io_moduleid);
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;
82 * New IO Brick encountered.
84 if (((int)io_moduleid[0]) == 0) {
85 DBG("ioconfig_get_busnum: Invalid Module Id given %s\n", io_moduleid);
86 return;
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++;
95 static void
96 dump_ioconfig_table(void)
99 int index = 0;
100 struct ascii_moduleid *temp;
102 temp = ioconfig_bus_table;
103 if (!temp) {
104 DBG("ioconfig_bus_table tabel empty\n");
105 return;
107 while (index < free_entry) {
108 DBG("ASSCI Module ID %s\n", temp->io_moduleid);
109 temp++;
110 index++;
115 * nextline
116 * This routine returns the nextline in the buffer.
118 int nextline(char *buffer, char **next, char *line)
121 char *temp;
123 if (buffer[0] == 0x0) {
124 return(0);
127 temp = buffer;
128 while (*temp != 0) {
129 *line = *temp;
130 if (*temp != '\n'){
131 *line = *temp;
132 temp++; line++;
133 } else
134 break;
137 if (*temp == 0)
138 *next = temp;
139 else
140 *next = ++temp;
142 return(1);
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.
152 build_moduleid_table(char *file_contents, struct ascii_moduleid *table)
155 * Read the whole file into memory.
157 int rc;
158 char *name;
159 char *temp;
160 char *next;
161 char *curr;
162 char *line;
163 struct ascii_moduleid *moduleid;
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;
176 memset(line, 0,256);
177 memset(name, 0, 125);
178 moduleid = table;
179 curr = file_contents;
180 while (nextline(curr, &next, line)){
182 DBG("curr 0x%lx next 0x%lx\n", curr, next);
184 temp = line;
186 * Skip all leading Blank lines ..
188 while (isspace(*temp))
189 if (*temp != '\n')
190 temp++;
191 else
192 break;
194 if (*temp == '\n') {
195 curr = next;
196 memset(line, 0, 256);
197 continue;
201 * Skip comment lines
203 if (*temp == '#') {
204 curr = next;
205 memset(line, 0, 256);
206 continue;
210 * Get the next free entry in the table.
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);
221 new_entry = free_entry;
222 kfree(line);
223 kfree(name);
225 return 0;
229 ioconfig_bus_init(void)
232 DBG("ioconfig_bus_init called.\n");
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;
240 memset(ioconfig_bus_table, 0, 512);
243 * If ioconfig options are given on the bootline .. take it.
245 if (*ioconfig_kernopts != '\0') {
247 * ioconfig="..." kernel options given.
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();
254 return 0;
257 void
258 ioconfig_bus_new_entries(void)
260 int index;
261 struct ascii_moduleid *temp;
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;
269 index = new_entry;
270 if (!ioconfig_bus_table) {
271 printk("ioconfig_bus_table table is empty\n");
272 return;
274 temp = &ioconfig_bus_table[index];
275 while (index < free_entry) {
276 printk("%s\n", (char *)temp);
277 temp++;
278 index++;
280 printk("### End\n");
283 static int ioconfig_bus_ioctl(struct inode * inode, struct file * file,
284 unsigned int cmd, unsigned long arg)
287 * Copy in the parameters.
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;
296 if (!ioconfig_bus_table)
297 return -EFAULT;
299 if (copy_to_user((char *)parm.buffer, &ioconfig_bus_table[new_entry], sizeof(struct ascii_moduleid) * (free_entry - new_entry)))
300 return -EFAULT;
302 return 0;
306 * ioconfig_bus_open - Opens the special device node "/dev/hw/.ioconfig_bus".
308 static int ioconfig_bus_open(struct inode * inode, struct file * filp)
310 if (ioconfig_bus_debug) {
311 DBG("ioconfig_bus_open called.\n");
314 return(0);
319 * ioconfig_bus_close - Closes the special device node "/dev/hw/.ioconfig_bus".
321 static int ioconfig_bus_close(struct inode * inode, struct file * filp)
324 if (ioconfig_bus_debug) {
325 DBG("ioconfig_bus_close called.\n");
328 return(0);
331 struct file_operations ioconfig_bus_fops = {
332 .ioctl = ioconfig_bus_ioctl,
333 .open = ioconfig_bus_open, /* open */
334 .release=ioconfig_bus_close /* release */
339 * init_ifconfig_bus() - Boot time initialization. Ensure that it is called
340 * after hwgfs has been initialized.
343 int init_ioconfig_bus(void)
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);
351 if (ioconfig_bus_handle == NULL) {
352 panic("Unable to create SGI PERSISTENT BUS NUMBERING Driver.\n");
355 return 0;
358 static int __init ioconfig_bus_setup (char *str)
361 char *temp;
363 DBG("ioconfig_bus_setup: Kernel Options %s\n", str);
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;
374 *temp = *str;
375 temp++;
376 str++;
379 return(0);
382 __setup("ioconfig=", ioconfig_bus_setup);