4  * Generic port I/O CompactPCI driver
 
   6  * Copyright 2002 SOMA Networks, Inc.
 
   7  * Copyright 2001 Intel San Luis Obispo
 
   8  * Copyright 2000,2001 MontaVista Software Inc.
 
  10  * This program is free software; you can redistribute it and/or modify it
 
  11  * under the terms of the GNU General Public License as published by the
 
  12  * Free Software Foundation; either version 2 of the License, or (at your
 
  13  * option) any later version.
 
  15  * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 
  16  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
 
  17  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
 
  18  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
 
  19  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
 
  20  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
 
  21  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
 
  22  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
 
  23  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
 
  24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
  26  * You should have received a copy of the GNU General Public License along
 
  27  * with this program; if not, write to the Free Software Foundation, Inc.,
 
  28  * 675 Mass Ave, Cambridge, MA 02139, USA.
 
  30  * This generic CompactPCI hotplug driver should allow using the PCI hotplug
 
  31  * mechanism on any CompactPCI board that exposes the #ENUM signal as a bit
 
  32  * in a system register that can be read through standard port I/O.
 
  34  * Send feedback to <scottm@somanetworks.com>
 
  37 #include <linux/module.h>
 
  38 #include <linux/init.h>
 
  39 #include <linux/errno.h>
 
  40 #include <linux/pci.h>
 
  41 #include <linux/string.h>
 
  42 #include "cpci_hotplug.h"
 
  44 #define DRIVER_VERSION  "0.1"
 
  45 #define DRIVER_AUTHOR   "Scott Murray <scottm@somanetworks.com>"
 
  46 #define DRIVER_DESC     "Generic port I/O CompactPCI Hot Plug Driver"
 
  49 #define MY_NAME "cpcihp_generic"
 
  51 #define MY_NAME THIS_MODULE->name
 
  54 #define dbg(format, arg...)                                     \
 
  57                         printk (KERN_DEBUG "%s: " format "\n",  \
 
  60 #define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
 
  61 #define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
 
  62 #define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
 
  67 static u8 bridge_busnr;
 
  68 static u8 bridge_slot;
 
  69 static struct pci_bus *bus;
 
  73 static unsigned int enum_bit;
 
  76 static struct cpci_hp_controller_ops generic_hpc_ops;
 
  77 static struct cpci_hp_controller generic_hpc;
 
  79 static int __init validate_parameters(void)
 
  86                 info("not configured, disabling.");
 
  93         tmp = simple_strtoul(str, &p, 16);
 
  94         if(p == str || tmp > 0xff) {
 
  95                 err("Invalid hotplug bus bridge device bus number");
 
  98         bridge_busnr = (u8) tmp;
 
  99         dbg("bridge_busnr = 0x%02x", bridge_busnr);
 
 101                 err("Invalid hotplug bus bridge device");
 
 105         tmp = simple_strtoul(str, &p, 16);
 
 106         if(p == str || tmp > 0x1f) {
 
 107                 err("Invalid hotplug bus bridge device slot number");
 
 110         bridge_slot = (u8) tmp;
 
 111         dbg("bridge_slot = 0x%02x", bridge_slot);
 
 113         dbg("first_slot = 0x%02x", first_slot);
 
 114         dbg("last_slot = 0x%02x", last_slot);
 
 115         if(!(first_slot && last_slot)) {
 
 116                 err("Need to specify first_slot and last_slot");
 
 119         if(last_slot < first_slot) {
 
 120                 err("first_slot must be less than last_slot");
 
 124         dbg("port = 0x%04x", port);
 
 125         dbg("enum_bit = 0x%02x", enum_bit);
 
 127                 err("Invalid #ENUM bit");
 
 130         enum_mask = 1 << enum_bit;
 
 134 static int query_enum(void)
 
 139         return ((value & enum_mask) == enum_mask);
 
 142 static int __init cpcihp_generic_init(void)
 
 148         info(DRIVER_DESC " version: " DRIVER_VERSION);
 
 149         status = validate_parameters();
 
 153         r = request_region(port, 1, "#ENUM hotswap signal register");
 
 157         dev = pci_find_slot(bridge_busnr, PCI_DEVFN(bridge_slot, 0));
 
 158         if(!dev || dev->hdr_type != PCI_HEADER_TYPE_BRIDGE) {
 
 159                 err("Invalid bridge device %s", bridge);
 
 162         bus = dev->subordinate;
 
 164         memset(&generic_hpc, 0, sizeof (struct cpci_hp_controller));
 
 165         generic_hpc_ops.query_enum = query_enum;
 
 166         generic_hpc.ops = &generic_hpc_ops;
 
 168         status = cpci_hp_register_controller(&generic_hpc);
 
 170                 err("Could not register cPCI hotplug controller");
 
 173         dbg("registered controller");
 
 175         status = cpci_hp_register_bus(bus, first_slot, last_slot);
 
 177                 err("Could not register cPCI hotplug bus");
 
 178                 goto init_bus_register_error;
 
 180         dbg("registered bus");
 
 182         status = cpci_hp_start();
 
 184                 err("Could not started cPCI hotplug system");
 
 185                 goto init_start_error;
 
 187         dbg("started cpci hp system");
 
 190         cpci_hp_unregister_bus(bus);
 
 191 init_bus_register_error:
 
 192         cpci_hp_unregister_controller(&generic_hpc);
 
 193         err("status = %d", status);
 
 198 static void __exit cpcihp_generic_exit(void)
 
 201         cpci_hp_unregister_bus(bus);
 
 202         cpci_hp_unregister_controller(&generic_hpc);
 
 203         release_region(port, 1);
 
 206 module_init(cpcihp_generic_init);
 
 207 module_exit(cpcihp_generic_exit);
 
 209 MODULE_AUTHOR(DRIVER_AUTHOR);
 
 210 MODULE_DESCRIPTION(DRIVER_DESC);
 
 211 MODULE_LICENSE("GPL");
 
 212 module_param(debug, bool, S_IRUGO | S_IWUSR);
 
 213 MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
 
 214 module_param(bridge, charp, 0);
 
 215 MODULE_PARM_DESC(bridge, "Hotswap bus bridge device, <bus>:<slot> (bus and slot are in hexadecimal)");
 
 216 module_param(first_slot, byte, 0);
 
 217 MODULE_PARM_DESC(first_slot, "Hotswap bus first slot number");
 
 218 module_param(last_slot, byte, 0);
 
 219 MODULE_PARM_DESC(last_slot, "Hotswap bus last slot number");
 
 220 module_param(port, ushort, 0);
 
 221 MODULE_PARM_DESC(port, "#ENUM signal I/O port");
 
 222 module_param(enum_bit, uint, 0);
 
 223 MODULE_PARM_DESC(enum_bit, "#ENUM signal bit (0-7)");