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
6 * ioconfig_bus - SGI's Persistent PCI Bus Numbering.
8 * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
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>
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)
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
;
56 int next_basebus_number
;
59 ioconfig_get_busnum(char *io_moduleid
, int *bus_num
)
61 struct ascii_moduleid
*temp
;
64 DBG("ioconfig_get_busnum io_moduleid %s\n", io_moduleid
);
67 temp
= ioconfig_bus_table
;
68 if (!ioconfig_bus_table
)
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;
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
);
90 strcpy((char *)&(ioconfig_bus_table
[free_entry
].io_moduleid
), io_moduleid
);
91 *bus_num
= free_entry
* 0x10;
96 dump_ioconfig_table(void)
100 struct ascii_moduleid
*temp
;
102 temp
= ioconfig_bus_table
;
104 DBG("ioconfig_bus_table tabel empty\n");
107 while (index
< free_entry
) {
108 DBG("ASSCI Module ID %s\n", temp
->io_moduleid
);
116 * This routine returns the nextline in the buffer.
118 int nextline(char *buffer
, char **next
, char *line
)
123 if (buffer
[0] == 0x0) {
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.
163 struct ascii_moduleid
*moduleid
;
165 line
= kmalloc(256, GFP_KERNEL
);
166 name
= kmalloc(125, GFP_KERNEL
);
167 if (!line
|| !name
) {
172 printk("build_moduleid_table(): Unabled to allocate memmory");
177 memset(name
, 0, 125);
179 curr
= file_contents
;
180 while (nextline(curr
, &next
, line
)){
182 DBG("curr 0x%lx next 0x%lx\n", curr
, next
);
186 * Skip all leading Blank lines ..
188 while (isspace(*temp
))
196 memset(line
, 0, 256);
205 memset(line
, 0, 256);
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
);
218 memset(line
, 0, 256);
221 new_entry
= free_entry
;
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");
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 )
252 (void) dump_ioconfig_table();
258 ioconfig_bus_new_entries(void)
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");
270 if (!ioconfig_bus_table
) {
271 printk("ioconfig_bus_table table is empty\n");
274 temp
= &ioconfig_bus_table
[index
];
275 while (index
< free_entry
) {
276 printk("%s\n", (char *)temp
);
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
)))
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
)))
296 if (!ioconfig_bus_table
)
299 if (copy_to_user((char *)parm
.buffer
, &ioconfig_bus_table
[new_entry
], sizeof(struct ascii_moduleid
) * (free_entry
- new_entry
)))
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");
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");
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",
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");
358 static int __init
ioconfig_bus_setup (char *str
)
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
) ) {
382 __setup("ioconfig=", ioconfig_bus_setup
);