patch-2.4.21 linux-2.4.21/arch/ia64/sn/io/ifconfig_bus.c
Next file: linux-2.4.21/arch/ia64/sn/io/invent.c
Previous file: linux-2.4.21/arch/ia64/sn/io/hubspc.c
Back to the patch index
Back to the overall index
- Lines: 346
- Date:
2003-06-13 07:51:30.000000000 -0700
- Orig file:
linux-2.4.20/arch/ia64/sn/io/ifconfig_bus.c
- Orig date:
1969-12-31 16:00:00.000000000 -0800
diff -urN linux-2.4.20/arch/ia64/sn/io/ifconfig_bus.c linux-2.4.21/arch/ia64/sn/io/ifconfig_bus.c
@@ -0,0 +1,345 @@
+/* $Id$
+ *
+ * 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.
+ *
+ * ifconfig_bus - SGI's Persistent PCI Bus Numbering.
+ *
+ * Copyright (C) 1992-1997, 2000-2002 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 <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>
+
+#define SGI_IFCONFIG_BUS "SGI-PERSISTENT PCI BUS NUMBERING"
+#define SGI_IFCONFIG_BUS_VERSION "1.0"
+
+/*
+ * Some Global definitions.
+ */
+devfs_handle_t ioconfig_bus_handle = NULL;
+unsigned long ioconfig_bus_debug = 0;
+
+#define IFCONFIG_BUS_DEBUG 1
+#ifdef IFCONFIG_BUS_DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif
+
+u64 ioconfig_file = 0;
+u64 ioconfig_file_size = 0;
+
+
+/*
+ * PCI Bus Name for PCI
+ * module/001c02/Ibrick/xtalk/14/pci - only 1 bus per widget
+ *
+ * PCI Bus Name for PCI-X
+ * module/001c02/Ibrick/xtalk/14/pci-x/0 - PCI bus 0 on Widget 14
+ * module/001c02/Ibrick/xtalk/14/pci-x/1 - PCI bus 1 on Widget 14
+ */
+
+struct pcipath_to_busnum{
+ unsigned int num; /* persistent bus number */
+ unsigned int len; /* pci path length */
+ unsigned char path[120]; /* pci path name */
+};
+
+struct pcipath_to_busnum *ioconfig_bus_table;
+u64 ioconfig_bus_table_size = 0;
+
+
+struct pcipath_to_busnum pcibus_names[256];
+
+/*
+ * highest_pcibus_num : The highest PCI bus number allocated. Use for next
+ * PCI Bus Number to be assigned.
+ * pcibus_names_index : The starting entry of any new configuration. It also
+ * tracks the number of old config in the table.
+ * current_index : Next free index in the table for new config.
+ * current_index - pcibus_names_index = number new config.
+ */
+
+int highest_pcibus_num = 0;
+int pcibus_names_index = 0; /* Start of new config */
+int current_index = 0; /* Next entry for new config */
+
+/*
+ * ioconfig_get_busnum():
+ * ioconfig_get_busnum() returns the bus number given a pci path name.
+ * If the pci path name exist in the persistent naming table, the
+ * corresponding bun number is returned. If the pci path name does not
+ * exist, the next bus number is assigned to that path, added to the
+ * persistent naming table and the new bus num returned.
+ */
+void
+ioconfig_get_busnum(char *pci_path, int *bus_num)
+{
+ struct pcipath_to_busnum *temp;
+ int index;
+
+ *bus_num = -1;
+ temp = ioconfig_bus_table;
+ for (index = 0; index < current_index; ioconfig_bus_table++, index++) {
+ if ( (strncmp(pci_path, ioconfig_bus_table->path, strlen(pci_path) == 0)) ){
+ *bus_num = ioconfig_bus_table->num;
+ return;
+ }
+ }
+
+ /*
+ * This is a new path and it is not in the config table.
+ * Add it to the end.
+ */
+ *bus_num = highest_pcibus_num;
+ highest_pcibus_num++;
+ ioconfig_bus_table->num = *bus_num;
+ strcpy((char *)&(ioconfig_bus_table->path), pci_path);
+ ioconfig_bus_table->len = strlen(pci_path);
+ current_index++;
+
+}
+
+void
+dump_ioconfig_table(struct pcipath_to_busnum *ioconfig_bus_table)
+{
+
+ int index = 0;
+ struct pcipath_to_busnum *temp;
+
+ temp = ioconfig_bus_table;
+ while (index < pcibus_names_index) {
+ printk("Bus Number %d PCI path %s\n", temp->num, temp->path);
+ 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.
+ */
+void
+build_pcibus_name(char *file_contents, struct pcipath_to_busnum *table)
+{
+ /*
+ * Read the whole file into memory.
+ */
+ int busnum;
+ int rc;
+ char *name;
+ char *temp;
+ char *next;
+ char *current;
+ char *line;
+ struct pcipath_to_busnum *pcibus;
+
+ line = kmalloc(256, GFP_KERNEL);
+ memset(line, 0,256);
+ name = kmalloc(125, GFP_KERNEL);
+ memset(name, 0, 125);
+ pcibus = table;
+ current = file_contents;
+ while (nextline(current, &next, line)){
+printk("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, "%d %s", &busnum, name);
+ pcibus->num = busnum;
+ pcibus->len = strlen(name);
+ strcpy(&pcibus->path[0], name);
+ DBG("pci number = %d pci path = %s\n", pcibus->num, pcibus->path);
+ if (busnum > highest_pcibus_num)
+ highest_pcibus_num = busnum;
+ else
+ highest_pcibus_num = busnum;
+
+ pcibus_names_index++;
+ pcibus++;
+ current = next;
+ memset(line, 0, 256);
+ }
+
+ DBG("highest_pcibus_num %d pcibus_names_index %d\n", highest_pcibus_num, pcibus_names_index);
+
+ current_index = pcibus_names_index;
+ kfree(line);
+ kfree(name);
+
+ return;
+}
+
+void
+ioconfig_bus_init(void)
+{
+
+ struct ia64_sal_retval ret_stuff;
+
+ DBG("ioconfig_bus_init called.\n");
+
+ /*
+ * 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;
+ SAL_CALL(ret_stuff, SN_SAL_BUS_CONFIG, 0, get_nasid(), 0, 0, 0, 0, 0);
+ if (ret_stuff.status != 0) {
+ DBG("ifconfig_bus_init: No Address given\n");
+ }
+
+ ioconfig_file = ret_stuff.v0;
+ ioconfig_file_size = ret_stuff.v1;
+ DBG("ioconfig_bus_init: ioconfig_file %p %d\n",
+ (void *)ioconfig_file, (int)ioconfig_file_size);
+
+ /*
+ * Convert the address to a Cache Address.
+ */
+ ioconfig_file = (CACHEABLE_MEM_SPACE |
+ (ioconfig_file & TO_PHYS_MASK));
+
+ ioconfig_bus_table = kmalloc( 512*sizeof(struct pcipath_to_busnum),
+ GFP_KERNEL );
+
+ DBG("ioconfig_bus_init: Kernel virtual ioconfig_file %p ioconfig_bus_table %p\n",
+ (void *)ioconfig_file, (void *)ioconfig_bus_table);
+
+ (void) build_pcibus_name((char *)ioconfig_file, ioconfig_bus_table);
+
+ (void) dump_ioconfig_table(ioconfig_bus_table);
+
+}
+
+/*
+ * 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) {
+ printk("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) {
+ printk("ioconfig_bus_close called.\n");
+ }
+
+ return(0);
+}
+
+struct file_operations ioconfig_bus_fops = {
+ /* ioctl:ioconfig_bus_ioctl, ioctl */
+ open:ioconfig_bus_open, /* open */
+ release:ioconfig_bus_close /* release */
+};
+
+
+/*
+ * init_ifconfig_net() - 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);
+
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)