Re: [PATCH] PCI hotplug changes for 2.5.46

Greg KH (greg@kroah.com)
Tue, 5 Nov 2002 17:43:58 -0800


ChangeSet 1.875.1.6, 2002/11/02 23:14:54-08:00, scottm@somanetworks.com

[PATCH] 2.5.45 CompactPCI driver patch 4/4

This is a patch 4 of 4 of my CompactPCI hotplug core and
drivers, consisting of the generic port I/O cPCI hotplug driver.

Let me know if the kernel parameter parsing code that's #ifndef MODULE is
objectionable. I spent quite a while today testing it, it seems reasonably
robust. Without it, this driver would only be useable as a module, which
I've not figured out how to do with the new kernel configuration stuff.

diff -Nru a/CREDITS b/CREDITS
--- a/CREDITS Tue Nov 5 17:26:06 2002
+++ b/CREDITS Tue Nov 5 17:26:06 2002
@@ -2223,7 +2223,7 @@
E: scott@spiteful.org
D: OPL3-SA2, OPL3-SA3 sound driver
D: CompactPCI hotplug core
-D: Ziatech ZT5550 CompactPCI hotplug drivers
+D: Ziatech ZT5550 and generic CompactPCI hotplug drivers
S: Toronto, Ontario
S: Canada

diff -Nru a/MAINTAINERS b/MAINTAINERS
--- a/MAINTAINERS Tue Nov 5 17:26:06 2002
+++ b/MAINTAINERS Tue Nov 5 17:26:06 2002
@@ -331,6 +331,13 @@
L: pcihpd-discuss@lists.sourceforge.net
S: Supported

+COMPACTPCI HOTPLUG GENERIC DRIVER
+P: Scott Murray
+M: scottm@somanetworks.com
+M: scott@spiteful.org
+L: pcihpd-discuss@lists.sourceforge.net
+S: Supported
+
COMPAQ FIBRE CHANNEL 64-bit/66MHz PCI non-intelligent HBA
P: Amy Vanzant-Hodge
M: Amy Vanzant-Hodge (fibrechannel@compaq.com)
diff -Nru a/drivers/hotplug/Kconfig b/drivers/hotplug/Kconfig
--- a/drivers/hotplug/Kconfig Tue Nov 5 17:26:06 2002
+++ b/drivers/hotplug/Kconfig Tue Nov 5 17:26:06 2002
@@ -101,5 +101,20 @@

When in doubt, say N.

+config HOTPLUG_PCI_CPCI_GENERIC
+ tristate "Generic port I/O CompactPCI Hotplug driver"
+ depends on HOTPLUG_PCI_CPCI && X86
+ help
+ Say Y here if you have a CompactPCI system card that exposes the #ENUM
+ hotswap signal as a bit in a system register that can be read through
+ standard port I/O.
+
+ This code is also available as a module ( = code which can be
+ inserted in and removed from the running kernel whenever you want).
+ The module will be called cpcihp_generic.o. If you want to compile it
+ as a module, say M here and read <file:Documentation/modules.txt>.
+
+ When in doubt, say N.
+
endmenu

diff -Nru a/drivers/hotplug/Makefile b/drivers/hotplug/Makefile
--- a/drivers/hotplug/Makefile Tue Nov 5 17:26:06 2002
+++ b/drivers/hotplug/Makefile Tue Nov 5 17:26:06 2002
@@ -10,6 +10,7 @@
obj-$(CONFIG_HOTPLUG_PCI_ACPI) += acpiphp.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI) += cpci_hotplug.o
obj-$(CONFIG_HOTPLUG_PCI_CPCI_ZT5550) += cpcihp_zt5550.o
+obj-$(CONFIG_HOTPLUG_PCI_CPCI_GENERIC) += cpcihp_generic.o

pci_hotplug-objs := pci_hotplug_core.o \
pci_hotplug_util.o
diff -Nru a/drivers/hotplug/cpcihp_generic.c b/drivers/hotplug/cpcihp_generic.c
--- /dev/null Wed Dec 31 16:00:00 1969
+++ b/drivers/hotplug/cpcihp_generic.c Tue Nov 5 17:26:06 2002
@@ -0,0 +1,291 @@
+/*
+ * cpcihp_generic.c
+ *
+ * Generic port I/O CompactPCI driver
+ *
+ * Copyright 2002 SOMA Networks, Inc.
+ * Copyright 2001 Intel San Luis Obispo
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * This generic CompactPCI hotplug driver should allow using the PCI hotplug
+ * mechanism on any CompactPCI board that exposes the #ENUM signal as a bit
+ * in a system register that can be read through standard port I/O.
+ *
+ * Send feedback to <scottm@somanetworks.com>
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include "cpci_hotplug.h"
+
+#define DRIVER_VERSION "0.1"
+#define DRIVER_AUTHOR "Scott Murray <scottm@somanetworks.com>"
+#define DRIVER_DESC "Generic port I/O CompactPCI Hot Plug Driver"
+
+#if !defined(CONFIG_HOTPLUG_CPCI_GENERIC_MODULE)
+#define MY_NAME "cpcihp_generic"
+#else
+#define MY_NAME THIS_MODULE->name
+#endif
+
+#define dbg(format, arg...) \
+ do { \
+ if(debug) \
+ printk (KERN_DEBUG "%s: " format "\n", \
+ MY_NAME , ## arg); \
+ } while(0)
+#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
+#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
+#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
+
+/* local variables */
+static int debug;
+static int setup;
+static char* bridge;
+static u8 bridge_busnr;
+static u8 bridge_slot;
+static struct pci_bus *bus;
+static u8 first_slot;
+static u8 last_slot;
+static u16 port;
+static unsigned int enum_bit;
+static u8 enum_mask;
+
+static struct cpci_hp_controller_ops generic_hpc_ops;
+static struct cpci_hp_controller generic_hpc;
+
+/* The following allows configuring the driver when it's compiled into the kernel */
+#ifndef MODULE
+static int __init cpcihp_generic_setup(char* str)
+{
+ char* p;
+ unsigned long tmp;
+
+ if(!str)
+ return -EINVAL;
+ bridge = str;
+
+ p = strchr(str, ',');
+ str = p + 1;
+ if(!(p && *str && *p == ','))
+ goto setup_error;
+ tmp = simple_strtoul(str, &p, 0);
+ if(p == str || tmp > 0xff) {
+ err("hotplug bus first slot number out of range");
+ goto setup_error;
+ }
+ first_slot = (u8) tmp;
+
+ str = p + 1;
+ if(!(*str && *p == ','))
+ return -EINVAL;
+ tmp = simple_strtoul(str, &p, 0);
+ if(p == str || tmp > 0xff) {
+ err("hotplug bus last slot number out of range");
+ goto setup_error;
+ }
+ last_slot = (u8) tmp;
+
+ str = p + 1;
+ if(!(*str && *p == ','))
+ goto setup_error;
+ tmp = simple_strtoul(str, &p, 0);
+ if(p == str || tmp > 0xffff) {
+ err("port number out of range");
+ goto setup_error;
+ }
+ port = (u16) tmp;
+
+ str = p + 1;
+ if(!(*str && *p == ','))
+ goto setup_error;
+ tmp = simple_strtoul(str, &p, 0);
+ if(p == str) {
+ err("invalid #ENUM bit number");
+ goto setup_error;
+ }
+ enum_bit = (u8) tmp;
+
+ str = p + 1;
+ if(*str && *p == ',') {
+ tmp = simple_strtoul(str, &p, 0);
+ if(p != str)
+ debug = (int) tmp;
+ }
+ return 0;
+setup_error:
+ bridge = NULL;
+ return -EINVAL;
+}
+
+__setup("cpcihp_generic=", cpcihp_generic_setup);
+#endif
+
+static int __init validate_parameters(void)
+{
+ char* str;
+ char* p;
+ unsigned long tmp;
+
+ if(!bridge) {
+ info("not configured, disabling.");
+ return 1;
+ }
+ str = bridge;
+ if(!*str)
+ return -EINVAL;
+
+ tmp = simple_strtoul(str, &p, 16);
+ if(p == str || tmp > 0xff) {
+ err("Invalid hotplug bus bridge device bus number");
+ return -EINVAL;
+ }
+ bridge_busnr = (u8) tmp;
+ dbg("bridge_busnr = 0x%02x", bridge_busnr);
+ if(*p != ':') {
+ err("Invalid hotplug bus bridge device");
+ return -EINVAL;
+ }
+ str = p + 1;
+ tmp = simple_strtoul(str, &p, 16);
+ if(p == str || tmp > 0x1f) {
+ err("Invalid hotplug bus bridge device slot number");
+ return -EINVAL;
+ }
+ bridge_slot = (u8) tmp;
+ dbg("bridge_slot = 0x%02x", bridge_slot);
+
+ dbg("first_slot = 0x%02x", first_slot);
+ dbg("last_slot = 0x%02x", last_slot);
+ if(!(first_slot && last_slot)) {
+ err("Need to specify first_slot and last_slot");
+ return -EINVAL;
+ }
+ if(last_slot < first_slot) {
+ err("first_slot must be less than last_slot");
+ return -EINVAL;
+ }
+
+ dbg("port = 0x%04x", port);
+ dbg("enum_bit = 0x%02x", enum_bit);
+ if(enum_bit > 7) {
+ err("Invalid #ENUM bit");
+ return -EINVAL;
+ }
+ enum_mask = 1 << enum_bit;
+ return 0;
+}
+
+static int query_enum(void)
+{
+ u8 value;
+
+ value = inb_p(port);
+ return ((value & enum_mask) == enum_mask);
+}
+
+static int __init cpcihp_generic_init(void)
+{
+ int status;
+ struct resource* r;
+ struct pci_dev* dev;
+
+ info(DRIVER_DESC " version: " DRIVER_VERSION);
+ status = validate_parameters();
+ if(status != 0)
+ return status;
+
+ r = request_region(port, 1, "#ENUM hotswap signal register");
+ if(!r)
+ return -EBUSY;
+
+ dev = pci_find_slot(bridge_busnr, PCI_DEVFN(bridge_slot, 0));
+ if(!dev || dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
+ err("Invalid bridge device %s", bridge);
+ return -EINVAL;
+ }
+ bus = dev->subordinate;
+
+ memset(&generic_hpc, 0, sizeof (struct cpci_hp_controller));
+ generic_hpc_ops.query_enum = query_enum;
+ generic_hpc.ops = &generic_hpc_ops;
+
+ status = cpci_hp_register_controller(&generic_hpc);
+ if(status != 0) {
+ err("Could not register cPCI hotplug controller");
+ return -ENODEV;
+ }
+ dbg("registered controller");
+
+ status = cpci_hp_register_bus(bus, first_slot, last_slot);
+ if(status != 0) {
+ err("Could not register cPCI hotplug bus");
+ goto init_bus_register_error;
+ }
+ dbg("registered bus");
+
+ status = cpci_hp_start();
+ if(status != 0) {
+ err("Could not started cPCI hotplug system");
+ goto init_start_error;
+ }
+ dbg("started cpci hp system");
+ return 0;
+init_start_error:
+ cpci_hp_unregister_bus(bus);
+init_bus_register_error:
+ cpci_hp_unregister_controller(&generic_hpc);
+ err("status = %d", status);
+ return status;
+
+}
+
+static void __exit cpcihp_generic_exit(void)
+{
+ cpci_hp_stop();
+ cpci_hp_unregister_bus(bus);
+ cpci_hp_unregister_controller(&generic_hpc);
+ release_region(port, 1);
+}
+
+module_init(cpcihp_generic_init);
+module_exit(cpcihp_generic_exit);
+
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_LICENSE("GPL");
+MODULE_PARM(debug, "i");
+MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
+MODULE_PARM(bridge, "s");
+MODULE_PARM_DESC(bridge, "Hotswap bus bridge device, <bus>:<slot> (bus and slot are in hexadecimal)");
+MODULE_PARM(first_slot, "b");
+MODULE_PARM_DESC(first_slot, "Hotswap bus first slot number");
+MODULE_PARM(last_slot, "b");
+MODULE_PARM_DESC(last_slot, "Hotswap bus last slot number");
+MODULE_PARM(port, "h");
+MODULE_PARM_DESC(port, "#ENUM signal I/O port");
+MODULE_PARM(enum_bit, "i");
+MODULE_PARM_DESC(enum_bit, "#ENUM signal bit (0-7)");
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/