📄 ioconfig_bus.c
字号:
/* * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * ioconfig_bus - SGI's Persistent PCI Bus Numbering. * * Copyright (C) 1992-1997, 2000-2003 Silicon Graphics, Inc. All rights reserved. */#include <linux/types.h>#include <linux/slab.h>#include <linux/ctype.h>#include <linux/module.h>#include <linux/init.h>#include <linux/pci.h>#include <asm/sn/sgi.h>#include <asm/uaccess.h>#include <linux/devfs_fs.h>#include <linux/devfs_fs_kernel.h>#include <asm/io.h>#include <asm/sn/iograph.h>#include <asm/sn/invent.h>#include <asm/sn/hcl.h>#include <asm/sn/labelcl.h>#include <asm//sn/sn_sal.h>#include <asm/sn/addrs.h>#include <asm/sn/ioconfig_bus.h>#define SGI_IOCONFIG_BUS "SGI-PERSISTENT PCI BUS NUMBERING"#define SGI_IOCONFIG_BUS_VERSION "1.0"/* * Some Global definitions. */static vertex_hdl_t ioconfig_bus_handle;static unsigned long ioconfig_bus_debug;static struct ioconfig_parm parm;#ifdef IOCONFIG_BUS_DEBUG#define DBG(x...) printk(x)#else#define DBG(x...)#endifstatic u64 ioconfig_file;static u64 ioconfig_file_size;static u64 ioconfig_activated;static char ioconfig_kernopts[128];/* * For debugging purpose .. hardcode a table .. */struct ascii_moduleid *ioconfig_bus_table;u64 ioconfig_bus_table_size;static int free_entry;static int new_entry;int next_basebus_number;voidioconfig_get_busnum(char *io_moduleid, int *bus_num){ struct ascii_moduleid *temp; int index; DBG("ioconfig_get_busnum io_moduleid %s\n", io_moduleid); *bus_num = -1; temp = ioconfig_bus_table; for (index = 0; index < free_entry; temp++, index++) { if ( (io_moduleid[0] == temp->io_moduleid[0]) && (io_moduleid[1] == temp->io_moduleid[1]) && (io_moduleid[2] == temp->io_moduleid[2]) && (io_moduleid[4] == temp->io_moduleid[4]) && (io_moduleid[5] == temp->io_moduleid[5]) ) { *bus_num = index * 0x10; return; } } /* * New IO Brick encountered. */ if (((int)io_moduleid[0]) == 0) { DBG("ioconfig_get_busnum: Invalid Module Id given %s\n", io_moduleid); return; } io_moduleid[3] = '#'; strcpy((char *)&(ioconfig_bus_table[free_entry].io_moduleid), io_moduleid); *bus_num = free_entry * 0x10; free_entry++;}static voiddump_ioconfig_table(void){ int index = 0; struct ascii_moduleid *temp; temp = ioconfig_bus_table; while (index < free_entry) { DBG("ASSCI Module ID %s\n", temp->io_moduleid); temp++; index++; }}/* * nextline * This routine returns the nextline in the buffer. */int nextline(char *buffer, char **next, char *line){ char *temp; if (buffer[0] == 0x0) { return(0); } temp = buffer; while (*temp != 0) { *line = *temp; if (*temp != '\n'){ *line = *temp; temp++; line++; } else break; } if (*temp == 0) *next = temp; else *next = ++temp; return(1);}/* * build_pcibus_name * This routine parses the ioconfig contents read into * memory by ioconfig command in EFI and builds the * persistent pci bus naming table. */voidbuild_moduleid_table(char *file_contents, struct ascii_moduleid *table){ /* * Read the whole file into memory. */ int rc; char *name; char *temp; char *next; char *current; char *line; struct ascii_moduleid *moduleid; line = kmalloc(256, GFP_KERNEL); if (line <= 0) BUG(); /* Do not want to continue system boot .. */ memset(line, 0,256); name = kmalloc(125, GFP_KERNEL); if (name <= 0){ BUG(); /* Do not want to continue system boot .. */ } memset(name, 0, 125); moduleid = table; current = file_contents; while (nextline(current, &next, line)){ DBG("current 0x%lx next 0x%lx\n", current, next); temp = line; /* * Skip all leading Blank lines .. */ while (isspace(*temp)) if (*temp != '\n') temp++; else break; if (*temp == '\n') { current = next; memset(line, 0, 256); continue; } /* * Skip comment lines */ if (*temp == '#') { current = next; memset(line, 0, 256); continue; } /* * Get the next free entry in the table. */ rc = sscanf(temp, "%s", name); strcpy(&moduleid->io_moduleid[0], name); DBG("Found %s\n", name); moduleid++; free_entry++; current = next; memset(line, 0, 256); } new_entry = free_entry; kfree(line); kfree(name); return;}voidioconfig_bus_init(void){ struct ia64_sal_retval ret_stuff; u64 *temp; int cnode; DBG("ioconfig_bus_init called.\n"); for (cnode = 0; cnode < numnodes; cnode++) { nasid_t nasid; /* * Make SAL call to get the address of the bus configuration table. */ ret_stuff.status = (uint64_t)0; ret_stuff.v0 = (uint64_t)0; ret_stuff.v1 = (uint64_t)0; ret_stuff.v2 = (uint64_t)0; nasid = COMPACT_TO_NASID_NODEID(cnode); SAL_CALL(ret_stuff, SN_SAL_BUS_CONFIG, 0, nasid, 0, 0, 0, 0, 0); temp = (u64 *)TO_NODE_CAC(nasid, ret_stuff.v0); ioconfig_file = *temp; DBG("ioconfig_bus_init: Nasid %d ret_stuff.v0 0x%lx\n", nasid, ret_stuff.v0); if (ioconfig_file) { ioconfig_file_size = ret_stuff.v1; ioconfig_file = (ioconfig_file | CACHEABLE_MEM_SPACE); ioconfig_activated = 1; break; } } DBG("ioconfig_bus_init: ret_stuff.v0 %p ioconfig_file %p %d\n", ret_stuff.v0, (void *)ioconfig_file, (int)ioconfig_file_size); ioconfig_bus_table = kmalloc( 512, GFP_KERNEL ); if (ioconfig_bus_table <= 0) BUG(); /* Seriously, we should not be out of memory at init */ memset(ioconfig_bus_table, 0, 512); /* * If ioconfig options are given on the bootline .. take it. */ if (*ioconfig_kernopts != '\0') { /* * ioconfig="..." kernel options given. */ DBG("ioconfig_bus_init: Kernel Options given.\n"); (void) build_moduleid_table((char *)ioconfig_kernopts, ioconfig_bus_table); (void) dump_ioconfig_table(); } if (ioconfig_activated) { DBG("ioconfig_bus_init: ioconfig file given.\n"); (void) build_moduleid_table((char *)ioconfig_file, ioconfig_bus_table); (void) dump_ioconfig_table(); } else { DBG("ioconfig_bus_init: ioconfig command not executed in prom\n"); }}voidioconfig_bus_new_entries(void){ int index = 0; struct ascii_moduleid *temp; if ((ioconfig_activated) && (free_entry > new_entry)) { printk("### Please add the following new IO Bricks Module ID \n"); printk("### to your Persistent Bus Numbering Config File\n"); } else return; index = new_entry; temp = &ioconfig_bus_table[index]; while (index < free_entry) { printk("%s\n", (char *)temp); temp++; index++; } printk("### End\n");}static int ioconfig_bus_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg){ int length; /* * Copy in the parameters. */ length = copy_from_user(&parm, (char *)arg, sizeof(struct ioconfig_parm)); if (length <= 0) return -EFAULT; parm.number = free_entry - new_entry; parm.ioconfig_activated = ioconfig_activated; if (copy_to_user((char *)arg, &parm, sizeof(struct ioconfig_parm))) return -EFAULT; if (copy_to_user((char *)parm.buffer, &ioconfig_bus_table[new_entry], sizeof(struct ascii_moduleid) * (free_entry - new_entry))) return -EFAULT; return 0;}/* * ioconfig_bus_open - Opens the special device node "/dev/hw/.ioconfig_bus". */static int ioconfig_bus_open(struct inode * inode, struct file * filp){ if (ioconfig_bus_debug) { DBG("ioconfig_bus_open called.\n"); } return(0);}/* * ioconfig_bus_close - Closes the special device node "/dev/hw/.ioconfig_bus". */static int ioconfig_bus_close(struct inode * inode, struct file * filp){ if (ioconfig_bus_debug) { DBG("ioconfig_bus_close called.\n"); } return(0);}struct file_operations ioconfig_bus_fops = { ioctl:ioconfig_bus_ioctl, open:ioconfig_bus_open, /* open */ release:ioconfig_bus_close /* release */};/* * init_ifconfig_bus() - Boot time initialization. Ensure that it is called * after devfs has been initialized. * */int init_ioconfig_bus(void){ ioconfig_bus_handle = NULL; ioconfig_bus_handle = hwgraph_register(hwgraph_root, ".ioconfig_bus", 0, DEVFS_FL_AUTO_DEVNUM, 0, 0, S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0, &ioconfig_bus_fops, NULL); if (ioconfig_bus_handle == NULL) { panic("Unable to create SGI PERSISTENT BUS NUMBERING Driver.\n"); } return(0);}static int __init ioconfig_bus_setup (char *str){ char *temp; DBG("ioconfig_bus_setup: Kernel Options %s\n", str); temp = (char *)ioconfig_kernopts; memset(temp, 0, 128); while ( (*str != '\0') && !isspace (*str) ) { if (*str == ',') { *temp = '\n'; temp++; str++; continue; } *temp = *str; temp++; str++; } return(0); }__setup("ioconfig=", ioconfig_bus_setup);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -