linux/drivers/pci/hotplug/pcihp_skeleton.c
<<
>>
Prefs
   1/*
   2 * PCI Hot Plug Controller Skeleton Driver - 0.3
   3 *
   4 * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com)
   5 * Copyright (C) 2001,2003 IBM Corp.
   6 *
   7 * All rights reserved.
   8 *
   9 * This program is free software; you can redistribute it and/or modify
  10 * it under the terms of the GNU General Public License as published by
  11 * the Free Software Foundation; either version 2 of the License, or (at
  12 * your option) any later version.
  13 *
  14 * This program is distributed in the hope that it will be useful, but
  15 * WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
  17 * NON INFRINGEMENT.  See the GNU General Public License for more
  18 * details.
  19 *
  20 * You should have received a copy of the GNU General Public License
  21 * along with this program; if not, write to the Free Software
  22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23 *
  24 * This driver is to be used as a skeleton driver to show how to interface
  25 * with the pci hotplug core easily.
  26 *
  27 * Send feedback to <greg@kroah.com>
  28 *
  29 */
  30
  31#include <linux/module.h>
  32#include <linux/moduleparam.h>
  33#include <linux/kernel.h>
  34#include <linux/slab.h>
  35#include <linux/pci.h>
  36#include <linux/pci_hotplug.h>
  37#include <linux/init.h>
  38
  39#define SLOT_NAME_SIZE  10
  40struct slot {
  41        u8 number;
  42        struct hotplug_slot *hotplug_slot;
  43        struct list_head slot_list;
  44        char name[SLOT_NAME_SIZE];
  45};
  46
  47static LIST_HEAD(slot_list);
  48
  49#define MY_NAME "pcihp_skeleton"
  50
  51#define dbg(format, arg...)                                     \
  52        do {                                                    \
  53                if (debug)                                      \
  54                        printk (KERN_DEBUG "%s: " format "\n",  \
  55                                MY_NAME , ## arg);              \
  56        } while (0)
  57#define err(format, arg...) printk(KERN_ERR "%s: " format "\n", MY_NAME , ## arg)
  58#define info(format, arg...) printk(KERN_INFO "%s: " format "\n", MY_NAME , ## arg)
  59#define warn(format, arg...) printk(KERN_WARNING "%s: " format "\n", MY_NAME , ## arg)
  60
  61/* local variables */
  62static int debug;
  63static int num_slots;
  64
  65#define DRIVER_VERSION  "0.3"
  66#define DRIVER_AUTHOR   "Greg Kroah-Hartman <greg@kroah.com>"
  67#define DRIVER_DESC     "Hot Plug PCI Controller Skeleton Driver"
  68
  69MODULE_AUTHOR(DRIVER_AUTHOR);
  70MODULE_DESCRIPTION(DRIVER_DESC);
  71MODULE_LICENSE("GPL");
  72module_param(debug, bool, 0644);
  73MODULE_PARM_DESC(debug, "Debugging mode enabled or not");
  74
  75static int enable_slot          (struct hotplug_slot *slot);
  76static int disable_slot         (struct hotplug_slot *slot);
  77static int set_attention_status (struct hotplug_slot *slot, u8 value);
  78static int hardware_test        (struct hotplug_slot *slot, u32 value);
  79static int get_power_status     (struct hotplug_slot *slot, u8 *value);
  80static int get_attention_status (struct hotplug_slot *slot, u8 *value);
  81static int get_latch_status     (struct hotplug_slot *slot, u8 *value);
  82static int get_adapter_status   (struct hotplug_slot *slot, u8 *value);
  83
  84static struct hotplug_slot_ops skel_hotplug_slot_ops = {
  85        .enable_slot =          enable_slot,
  86        .disable_slot =         disable_slot,
  87        .set_attention_status = set_attention_status,
  88        .hardware_test =        hardware_test,
  89        .get_power_status =     get_power_status,
  90        .get_attention_status = get_attention_status,
  91        .get_latch_status =     get_latch_status,
  92        .get_adapter_status =   get_adapter_status,
  93};
  94
  95static int enable_slot(struct hotplug_slot *hotplug_slot)
  96{
  97        struct slot *slot = hotplug_slot->private;
  98        int retval = 0;
  99
 100        dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
 101
 102        /*
 103         * Fill in code here to enable the specified slot
 104         */
 105
 106        return retval;
 107}
 108
 109static int disable_slot(struct hotplug_slot *hotplug_slot)
 110{
 111        struct slot *slot = hotplug_slot->private;
 112        int retval = 0;
 113
 114        dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
 115
 116        /*
 117         * Fill in code here to disable the specified slot
 118         */
 119
 120        return retval;
 121}
 122
 123static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 status)
 124{
 125        struct slot *slot = hotplug_slot->private;
 126        int retval = 0;
 127
 128        dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
 129
 130        switch (status) {
 131                case 0:
 132                        /*
 133                         * Fill in code here to turn light off
 134                         */
 135                        break;
 136
 137                case 1:
 138                default:
 139                        /*
 140                         * Fill in code here to turn light on
 141                         */
 142                        break;
 143        }
 144
 145        return retval;
 146}
 147
 148static int hardware_test(struct hotplug_slot *hotplug_slot, u32 value)
 149{
 150        struct slot *slot = hotplug_slot->private;
 151        int retval = 0;
 152
 153        dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
 154
 155        switch (value) {
 156                case 0:
 157                        /* Specify a test here */
 158                        break;
 159                case 1:
 160                        /* Specify another test here */
 161                        break;
 162        }
 163
 164        return retval;
 165}
 166
 167static int get_power_status(struct hotplug_slot *hotplug_slot, u8 *value)
 168{
 169        struct slot *slot = hotplug_slot->private;
 170        int retval = 0;
 171
 172        dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
 173
 174        /*
 175         * Fill in logic to get the current power status of the specific
 176         * slot and store it in the *value location.
 177         */
 178
 179        return retval;
 180}
 181
 182static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 *value)
 183{
 184        struct slot *slot = hotplug_slot->private;
 185        int retval = 0;
 186
 187        dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
 188
 189        /*
 190         * Fill in logic to get the current attention status of the specific
 191         * slot and store it in the *value location.
 192         */
 193
 194        return retval;
 195}
 196
 197static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 *value)
 198{
 199        struct slot *slot = hotplug_slot->private;
 200        int retval = 0;
 201
 202        dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
 203
 204        /*
 205         * Fill in logic to get the current latch status of the specific
 206         * slot and store it in the *value location.
 207         */
 208
 209        return retval;
 210}
 211
 212static int get_adapter_status(struct hotplug_slot *hotplug_slot, u8 *value)
 213{
 214        struct slot *slot = hotplug_slot->private;
 215        int retval = 0;
 216
 217        dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
 218
 219        /*
 220         * Fill in logic to get the current adapter status of the specific
 221         * slot and store it in the *value location.
 222         */
 223
 224        return retval;
 225}
 226
 227static void release_slot(struct hotplug_slot *hotplug_slot)
 228{
 229        struct slot *slot = hotplug_slot->private;
 230
 231        dbg("%s - physical_slot = %s\n", __func__, hotplug_slot->name);
 232        kfree(slot->hotplug_slot->info);
 233        kfree(slot->hotplug_slot);
 234        kfree(slot);
 235}
 236
 237static void make_slot_name(struct slot *slot)
 238{
 239        /*
 240         * Stupid way to make a filename out of the slot name.
 241         * replace this if your hardware provides a better way to name slots.
 242         */
 243        snprintf(slot->hotplug_slot->name, SLOT_NAME_SIZE, "%d", slot->number);
 244}
 245
 246/**
 247 * init_slots - initialize 'struct slot' structures for each slot
 248 *
 249 */
 250static int __init init_slots(void)
 251{
 252        struct slot *slot;
 253        struct hotplug_slot *hotplug_slot;
 254        struct hotplug_slot_info *info;
 255        int retval = -ENOMEM;
 256        int i;
 257
 258        /*
 259         * Create a structure for each slot, and register that slot
 260         * with the pci_hotplug subsystem.
 261         */
 262        for (i = 0; i < num_slots; ++i) {
 263                slot = kzalloc(sizeof(*slot), GFP_KERNEL);
 264                if (!slot)
 265                        goto error;
 266
 267                hotplug_slot = kzalloc(sizeof(*hotplug_slot), GFP_KERNEL);
 268                if (!hotplug_slot)
 269                        goto error_slot;
 270                slot->hotplug_slot = hotplug_slot;
 271
 272                info = kzalloc(sizeof(*info), GFP_KERNEL);
 273                if (!info)
 274                        goto error_hpslot;
 275                hotplug_slot->info = info;
 276
 277                slot->number = i;
 278
 279                hotplug_slot->name = slot->name;
 280                hotplug_slot->private = slot;
 281                hotplug_slot->release = &release_slot;
 282                make_slot_name(slot);
 283                hotplug_slot->ops = &skel_hotplug_slot_ops;
 284                
 285                /*
 286                 * Initialize the slot info structure with some known
 287                 * good values.
 288                 */
 289                get_power_status(hotplug_slot, &info->power_status);
 290                get_attention_status(hotplug_slot, &info->attention_status);
 291                get_latch_status(hotplug_slot, &info->latch_status);
 292                get_adapter_status(hotplug_slot, &info->adapter_status);
 293                
 294                dbg("registering slot %d\n", i);
 295                retval = pci_hp_register(slot->hotplug_slot);
 296                if (retval) {
 297                        err("pci_hp_register failed with error %d\n", retval);
 298                        goto error_info;
 299                }
 300
 301                /* add slot to our internal list */
 302                list_add(&slot->slot_list, &slot_list);
 303        }
 304
 305        return 0;
 306error_info:
 307        kfree(info);
 308error_hpslot:
 309        kfree(hotplug_slot);
 310error_slot:
 311        kfree(slot);
 312error:
 313        return retval;
 314}
 315
 316static void __exit cleanup_slots(void)
 317{
 318        struct list_head *tmp;
 319        struct list_head *next;
 320        struct slot *slot;
 321
 322        /*
 323         * Unregister all of our slots with the pci_hotplug subsystem.
 324         * Memory will be freed in release_slot() callback after slot's
 325         * lifespan is finished.
 326         */
 327        list_for_each_safe(tmp, next, &slot_list) {
 328                slot = list_entry(tmp, struct slot, slot_list);
 329                list_del(&slot->slot_list);
 330                pci_hp_deregister(slot->hotplug_slot);
 331        }
 332}
 333                
 334static int __init pcihp_skel_init(void)
 335{
 336        int retval;
 337
 338        info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
 339        /*
 340         * Do specific initialization stuff for your driver here
 341         * like initializing your controller hardware (if any) and
 342         * determining the number of slots you have in the system
 343         * right now.
 344         */
 345        num_slots = 5;
 346
 347        return init_slots();
 348}
 349
 350static void __exit pcihp_skel_exit(void)
 351{
 352        /*
 353         * Clean everything up.
 354         */
 355        cleanup_slots();
 356}
 357
 358module_init(pcihp_skel_init);
 359module_exit(pcihp_skel_exit);
 360