📄 shpchp_core.c
字号:
/* * Standard Hot Plug Controller Driver * * Copyright (C) 1995,2001 Compaq Computer Corporation * Copyright (C) 2001 Greg Kroah-Hartman (greg@kroah.com) * Copyright (C) 2001 IBM Corp. * Copyright (C) 2003-2004 Intel Corporation * * All rights reserved. * * 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 program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or * NON INFRINGEMENT. See the GNU General Public License for more * details. * * 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. * * Send feedback to <greg@kroah.com>, <dely.l.sy@intel.com> * */#include <linux/config.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/kernel.h>#include <linux/types.h>#include <linux/proc_fs.h>#include <linux/miscdevice.h>#include <linux/slab.h>#include <linux/workqueue.h>#include <linux/pci.h>#include <linux/init.h>#include <asm/uaccess.h>#include "shpchp.h"#include "shpchprm.h"/* Global variables */int shpchp_debug;int shpchp_poll_mode;int shpchp_poll_time;struct controller *shpchp_ctrl_list; /* = NULL */struct pci_func *shpchp_slot_list[256];#define DRIVER_VERSION "0.4"#define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"#define DRIVER_DESC "Standard Hot Plug PCI Controller Driver"MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");module_param(shpchp_debug, bool, 644);module_param(shpchp_poll_mode, bool, 644);module_param(shpchp_poll_time, int, 644);MODULE_PARM_DESC(shpchp_debug, "Debugging mode enabled or not");MODULE_PARM_DESC(shpchp_poll_mode, "Using polling mechanism for hot-plug events or not");MODULE_PARM_DESC(shpchp_poll_time, "Polling mechanism frequency, in seconds");#define SHPC_MODULE_NAME "shpchp"static int shpc_start_thread (void);static int set_attention_status (struct hotplug_slot *slot, u8 value);static int enable_slot (struct hotplug_slot *slot);static int disable_slot (struct hotplug_slot *slot);static int get_power_status (struct hotplug_slot *slot, u8 *value);static int get_attention_status (struct hotplug_slot *slot, u8 *value);static int get_latch_status (struct hotplug_slot *slot, u8 *value);static int get_adapter_status (struct hotplug_slot *slot, u8 *value);static int get_max_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);static int get_cur_bus_speed (struct hotplug_slot *slot, enum pci_bus_speed *value);static struct hotplug_slot_ops shpchp_hotplug_slot_ops = { .owner = THIS_MODULE, .set_attention_status = set_attention_status, .enable_slot = enable_slot, .disable_slot = disable_slot, .get_power_status = get_power_status, .get_attention_status = get_attention_status, .get_latch_status = get_latch_status, .get_adapter_status = get_adapter_status, .get_max_bus_speed = get_max_bus_speed, .get_cur_bus_speed = get_cur_bus_speed,};/** * release_slot - free up the memory used by a slot * @hotplug_slot: slot to free */static void release_slot(struct hotplug_slot *hotplug_slot){ struct slot *slot = (struct slot *)hotplug_slot->private; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); kfree(slot->hotplug_slot->info); kfree(slot->hotplug_slot->name); kfree(slot->hotplug_slot); kfree(slot);}static int init_slots(struct controller *ctrl){ struct slot *new_slot; u8 number_of_slots; u8 slot_device; u32 slot_number, sun; int result = -ENOMEM; dbg("%s\n",__FUNCTION__); number_of_slots = ctrl->num_slots; slot_device = ctrl->slot_device_offset; slot_number = ctrl->first_slot; while (number_of_slots) { new_slot = (struct slot *) kmalloc(sizeof(struct slot), GFP_KERNEL); if (!new_slot) goto error; memset(new_slot, 0, sizeof(struct slot)); new_slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL); if (!new_slot->hotplug_slot) goto error_slot; memset(new_slot->hotplug_slot, 0, sizeof (struct hotplug_slot)); new_slot->hotplug_slot->info = kmalloc (sizeof (struct hotplug_slot_info), GFP_KERNEL); if (!new_slot->hotplug_slot->info) goto error_hpslot; memset(new_slot->hotplug_slot->info, 0, sizeof (struct hotplug_slot_info)); new_slot->hotplug_slot->name = kmalloc (SLOT_NAME_SIZE, GFP_KERNEL); if (!new_slot->hotplug_slot->name) goto error_info; new_slot->magic = SLOT_MAGIC; new_slot->ctrl = ctrl; new_slot->bus = ctrl->slot_bus; new_slot->device = slot_device; new_slot->hpc_ops = ctrl->hpc_ops; if (shpchprm_get_physical_slot_number(ctrl, &sun, new_slot->bus, new_slot->device)) goto error_name; new_slot->number = sun; new_slot->hp_slot = slot_device - ctrl->slot_device_offset; /* register this slot with the hotplug pci core */ new_slot->hotplug_slot->private = new_slot; new_slot->hotplug_slot->release = &release_slot; make_slot_name(new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot); new_slot->hotplug_slot->ops = &shpchp_hotplug_slot_ops; new_slot->hpc_ops->get_power_status(new_slot, &(new_slot->hotplug_slot->info->power_status)); new_slot->hpc_ops->get_attention_status(new_slot, &(new_slot->hotplug_slot->info->attention_status)); new_slot->hpc_ops->get_latch_status(new_slot, &(new_slot->hotplug_slot->info->latch_status)); new_slot->hpc_ops->get_adapter_status(new_slot, &(new_slot->hotplug_slot->info->adapter_status)); dbg("Registering bus=%x dev=%x hp_slot=%x sun=%x slot_device_offset=%x\n", new_slot->bus, new_slot->device, new_slot->hp_slot, new_slot->number, ctrl->slot_device_offset); result = pci_hp_register (new_slot->hotplug_slot); if (result) { err ("pci_hp_register failed with error %d\n", result); goto error_name; } new_slot->next = ctrl->slot; ctrl->slot = new_slot; number_of_slots--; slot_device++; slot_number += ctrl->slot_num_inc; } return 0;error_name: kfree(new_slot->hotplug_slot->name);error_info: kfree(new_slot->hotplug_slot->info);error_hpslot: kfree(new_slot->hotplug_slot);error_slot: kfree(new_slot);error: return result;}static void cleanup_slots(struct controller *ctrl){ struct slot *old_slot, *next_slot; old_slot = ctrl->slot; ctrl->slot = NULL; while (old_slot) { next_slot = old_slot->next; pci_hp_deregister(old_slot->hotplug_slot); old_slot = next_slot; }}static int get_ctlr_slot_config(struct controller *ctrl){ int num_ctlr_slots; int first_device_num; int physical_slot_num; int updown; int rc; int flags; rc = shpc_get_ctlr_slot_config(ctrl, &num_ctlr_slots, &first_device_num, &physical_slot_num, &updown, &flags); if (rc) { err("%s: get_ctlr_slot_config fail for b:d (%x:%x)\n", __FUNCTION__, ctrl->bus, ctrl->device); return -1; } ctrl->num_slots = num_ctlr_slots; ctrl->slot_device_offset = first_device_num; ctrl->first_slot = physical_slot_num; ctrl->slot_num_inc = updown; /* either -1 or 1 */ dbg("%s: num_slot(0x%x) 1st_dev(0x%x) psn(0x%x) updown(%d) for b:d (%x:%x)\n", __FUNCTION__, num_ctlr_slots, first_device_num, physical_slot_num, updown, ctrl->bus, ctrl->device); return 0;}/* * set_attention_status - Turns the Amber LED for a slot on, off or blink */static int set_attention_status (struct hotplug_slot *hotplug_slot, u8 status){ struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); hotplug_slot->info->attention_status = status; slot->hpc_ops->set_attention_status(slot, status); return 0;}static int enable_slot (struct hotplug_slot *hotplug_slot){ struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); return shpchp_enable_slot(slot);}static int disable_slot (struct hotplug_slot *hotplug_slot){ struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); return shpchp_disable_slot(slot);}static int get_power_status (struct hotplug_slot *hotplug_slot, u8 *value){ struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); retval = slot->hpc_ops->get_power_status(slot, value); if (retval < 0) *value = hotplug_slot->info->power_status; return 0;}static int get_attention_status (struct hotplug_slot *hotplug_slot, u8 *value){ struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); retval = slot->hpc_ops->get_attention_status(slot, value); if (retval < 0) *value = hotplug_slot->info->attention_status; return 0;}static int get_latch_status (struct hotplug_slot *hotplug_slot, u8 *value){ struct slot *slot = get_slot (hotplug_slot, __FUNCTION__); int retval; dbg("%s - physical_slot = %s\n", __FUNCTION__, hotplug_slot->name); retval = slot->hpc_ops->get_latch_status(slot, value); if (retval < 0) *value = hotplug_slot->info->latch_status; return 0;}static int get_adapter_status (struct hotplug_slot *hotplug_slot, u8 *value){ struct slot *slot = get_slot (hotplug_slot, __FUNCTION__);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -