⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cpqphp_core.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Compaq 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. * * 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> * */#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/types.h>#include <linux/proc_fs.h>#include <linux/miscdevice.h>#include <linux/slab.h>#include <linux/pci.h>#include <linux/init.h>#include <asm/uaccess.h>#include "cpqphp.h"#include "cpqphp_nvram.h"#include "../../arch/i386/kernel/pci-i386.h"	/* horrible hack showing how processor dependant we are... *//* Global variables */int cpqhp_debug;struct controller *cpqhp_ctrl_list;	/* = NULL */struct pci_func *cpqhp_slot_list[256];/* local variables */static void *smbios_table;static void *smbios_start;static void *cpqhp_rom_start;static u8 power_mode;static int debug;#define DRIVER_VERSION	"0.9.6"#define DRIVER_AUTHOR	"Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>"#define DRIVER_DESC	"Compaq Hot Plug PCI Controller Driver"MODULE_AUTHOR(DRIVER_AUTHOR);MODULE_DESCRIPTION(DRIVER_DESC);MODULE_LICENSE("GPL");MODULE_PARM(power_mode, "b");MODULE_PARM_DESC(power_mode, "Power mode enabled or not");MODULE_PARM(debug, "i");MODULE_PARM_DESC(debug, "Debugging mode enabled or not");#define CPQHPC_MODULE_MINOR 208static int one_time_init (void);static int set_attention_status (struct hotplug_slot *slot, u8 value);static int process_SI		(struct hotplug_slot *slot);static int process_SS		(struct hotplug_slot *slot);static int hardware_test	(struct hotplug_slot *slot, u32 value);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 struct hotplug_slot_ops cpqphp_hotplug_slot_ops = {	owner:			THIS_MODULE,	set_attention_status:	set_attention_status,	enable_slot:		process_SI,	disable_slot:		process_SS,	hardware_test:		hardware_test,	get_power_status:	get_power_status,	get_attention_status:	get_attention_status,	get_latch_status:	get_latch_status,	get_adapter_status:	get_adapter_status,};static inline int is_slot64bit (struct slot *slot){	if (!slot || !slot->p_sm_slot)		return 0;	if (readb(slot->p_sm_slot + SMBIOS_SLOT_WIDTH) == 0x06)		return 1;	return 0;}static inline int is_slot66mhz (struct slot *slot){	if (!slot || !slot->p_sm_slot)		return 0;	if (readb(slot->p_sm_slot + SMBIOS_SLOT_TYPE) == 0x0E)		return 1;	return 0;}/** * detect_SMBIOS_pointer - find the system Management BIOS Table in the specified region of memory. * * @begin: begin pointer for region to be scanned. * @end: end pointer for region to be scanned. * * Returns pointer to the head of the SMBIOS tables (or NULL) * */static void * detect_SMBIOS_pointer(void *begin, void *end){	void *fp;	void *endp;	u8 temp1, temp2, temp3, temp4;	int status = 0;	endp = (end - sizeof(u32) + 1);	for (fp = begin; fp <= endp; fp += 16) {		temp1 = readb(fp);		temp2 = readb(fp+1);		temp3 = readb(fp+2);		temp4 = readb(fp+3);		if (temp1 == '_' &&		    temp2 == 'S' &&		    temp3 == 'M' &&		    temp4 == '_') {			status = 1;			break;		}	}		if (!status)		fp = NULL;	dbg("Discovered SMBIOS Entry point at %p\n", fp);	return fp;}/** * init_SERR - Initializes the per slot SERR generation. * * For unexpected switch opens * */static int init_SERR(struct controller * ctrl){	u32 tempdword;	u32 number_of_slots;	u8 physical_slot;	if (!ctrl)		return 1;	tempdword = ctrl->first_slot;	number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;	// Loop through slots	while (number_of_slots) {		physical_slot = tempdword;		writeb(0, ctrl->hpc_reg + SLOT_SERR);		tempdword++;		number_of_slots--;	}	return 0;}/* nice debugging output */static int pci_print_IRQ_route (void){	struct irq_routing_table *routing_table;	int len;	int loop;	u8 tbus, tdevice, tslot;	routing_table = pcibios_get_irq_routing_table();	if (routing_table == NULL) {		err("No BIOS Routing Table??? Not good\n");		return -ENOMEM;	}	len = (routing_table->size - sizeof(struct irq_routing_table)) / sizeof(struct irq_info);	// Make sure I got at least one entry	if (len == 0) {		kfree(routing_table);		return -1;	}	dbg("bus dev func slot\n");	for (loop = 0; loop < len; ++loop) {		tbus = routing_table->slots[loop].bus;		tdevice = routing_table->slots[loop].devfn;		tslot = routing_table->slots[loop].slot;		dbg("%d %d %d %d\n", tbus, tdevice >> 3, tdevice & 0x7, tslot);	}	kfree(routing_table);	return 0;}/* * get_subsequent_smbios_entry * * Gets the first entry if previous == NULL * Otherwise, returns the next entry * Uses global SMBIOS Table pointer * * @curr: %NULL or pointer to previously returned structure * * returns a pointer to an SMBIOS structure or NULL if none found */static void * get_subsequent_smbios_entry(void *smbios_start, void *smbios_table, void *curr){	u8 bail = 0;	u8 previous_byte = 1;	void *p_temp;	void *p_max;	if (!smbios_table || !curr)		return(NULL);	// set p_max to the end of the table	p_max = smbios_start + readw(smbios_table + ST_LENGTH);	p_temp = curr;	p_temp += readb(curr + SMBIOS_GENERIC_LENGTH);	while ((p_temp < p_max) && !bail) {		// Look for the double NULL terminator		// The first condition is the previous byte and the second is the curr		if (!previous_byte && !(readb(p_temp))) {			bail = 1;		}		previous_byte = readb(p_temp);		p_temp++;	}	if (p_temp < p_max) {		return p_temp;	} else {		return NULL;	}}/** * get_SMBIOS_entry * * @type:SMBIOS structure type to be returned * @previous: %NULL or pointer to previously returned structure * * Gets the first entry of the specified type if previous == NULL * Otherwise, returns the next entry of the given type. * Uses global SMBIOS Table pointer * Uses get_subsequent_smbios_entry * * returns a pointer to an SMBIOS structure or %NULL if none found */static void *get_SMBIOS_entry (void *smbios_start, void *smbios_table, u8 type, void * previous){	if (!smbios_table)		return NULL;	if (!previous) {		  		previous = smbios_start;	} else {		previous = get_subsequent_smbios_entry(smbios_start, smbios_table, previous);	}	while (previous) {	       	if (readb(previous + SMBIOS_GENERIC_TYPE) != type) {			previous = get_subsequent_smbios_entry(smbios_start, smbios_table, previous);		} else {			break;		}	}	return previous;}static int ctrl_slot_setup (struct controller * ctrl, void *smbios_start, void *smbios_table){	struct slot *new_slot;	u8 number_of_slots;	u8 slot_device;	u8 slot_number;	u8 ctrl_slot;	u32 tempdword;	void *slot_entry= NULL;	int result;	dbg(__FUNCTION__"\n");	tempdword = readl(ctrl->hpc_reg + INT_INPUT_CLEAR);	number_of_slots = readb(ctrl->hpc_reg + SLOT_MASK) & 0x0F;	slot_device = readb(ctrl->hpc_reg + SLOT_MASK) >> 4;	slot_number = ctrl->first_slot;	while (number_of_slots) {		new_slot = (struct slot *) kmalloc(sizeof(struct slot), GFP_KERNEL);		if (!new_slot)			return -ENOMEM;		memset(new_slot, 0, sizeof(struct slot));		new_slot->hotplug_slot = kmalloc (sizeof (struct hotplug_slot), GFP_KERNEL);		if (!new_slot->hotplug_slot) {			kfree (new_slot);			return -ENOMEM;		}		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) {			kfree (new_slot->hotplug_slot);			kfree (new_slot);			return -ENOMEM;		}		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) {			kfree (new_slot->hotplug_slot->info);			kfree (new_slot->hotplug_slot);			kfree (new_slot);			return -ENOMEM;		}		new_slot->magic = SLOT_MAGIC;		new_slot->ctrl = ctrl;		new_slot->bus = ctrl->bus;		new_slot->device = slot_device;		new_slot->number = slot_number;		dbg("slot->number = %d\n",new_slot->number);		slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9, slot_entry);		while (slot_entry && (readw(slot_entry + SMBIOS_SLOT_NUMBER) != new_slot->number)) {			slot_entry = get_SMBIOS_entry(smbios_start, smbios_table, 9, slot_entry);		}		new_slot->p_sm_slot = slot_entry;		init_timer(&new_slot->task_event);		new_slot->task_event.expires = jiffies + 5 * HZ;		new_slot->task_event.function = cpqhp_pushbutton_thread;		//FIXME: these capabilities aren't used but if they are		//       they need to be correctly implemented		new_slot->capabilities |= PCISLOT_REPLACE_SUPPORTED;		new_slot->capabilities |= PCISLOT_INTERLOCK_SUPPORTED;		if (is_slot64bit(new_slot))			new_slot->capabilities |= PCISLOT_64_BIT_SUPPORTED;		if (is_slot66mhz(new_slot))			new_slot->capabilities |= PCISLOT_66_MHZ_SUPPORTED;		if (ctrl->speed == 1)			new_slot->capabilities |= PCISLOT_66_MHZ_OPERATION;		ctrl_slot = slot_device - (readb(ctrl->hpc_reg + SLOT_MASK) >> 4);		// Check presence		new_slot->capabilities |= ((((~tempdword) >> 23) | ((~tempdword) >> 15)) >> ctrl_slot) & 0x02;		// Check the switch state		new_slot->capabilities |= ((~tempdword & 0xFF) >> ctrl_slot) & 0x01;		// Check the slot enable		new_slot->capabilities |= ((read_slot_enable(ctrl) << 2) >> ctrl_slot) & 0x04;		/* register this slot with the hotplug pci core */		new_slot->hotplug_slot->private = new_slot;		make_slot_name (new_slot->hotplug_slot->name, SLOT_NAME_SIZE, new_slot);		new_slot->hotplug_slot->ops = &cpqphp_hotplug_slot_ops;				new_slot->hotplug_slot->info->power_status = get_slot_enabled(ctrl, new_slot);		new_slot->hotplug_slot->info->attention_status = cpq_get_attention_status(ctrl, new_slot);		new_slot->hotplug_slot->info->latch_status = cpq_get_latch_status(ctrl, new_slot);		new_slot->hotplug_slot->info->adapter_status = get_presence_status(ctrl, new_slot);				dbg ("registering bus %d, dev %d, number %d, ctrl->slot_device_offset %d, slot %d\n", 		     new_slot->bus, new_slot->device, new_slot->number, ctrl->slot_device_offset, slot_number);		result = pci_hp_register (new_slot->hotplug_slot);		if (result) {			err ("pci_hp_register failed with error %d\n", result);			kfree (new_slot->hotplug_slot->info);			kfree (new_slot->hotplug_slot->name);			kfree (new_slot->hotplug_slot);			kfree (new_slot);			return result;		}				new_slot->next = ctrl->slot;		ctrl->slot = new_slot;		number_of_slots--;		slot_device++;		slot_number++;	}	return(0);}static int ctrl_slot_cleanup (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);		kfree(old_slot->hotplug_slot->info);		kfree(old_slot->hotplug_slot->name);		kfree(old_slot->hotplug_slot);		kfree(old_slot);		old_slot = next_slot;	}	//Free IRQ associated with hot plug device	free_irq(ctrl->interrupt, ctrl);	//Unmap the memory	iounmap(ctrl->hpc_reg);	//Finally reclaim PCI mem	release_mem_region(pci_resource_start(ctrl->pci_dev, 0),			   pci_resource_len(ctrl->pci_dev, 0));	return(0);}//============================================================================// function:	get_slot_mapping//// Description: Attempts to determine a logical slot mapping for a PCI//		device.  Won't work for more than one PCI-PCI bridge//		in a slot.//// Input:	u8 bus_num - bus number of PCI device//		u8 dev_num - device number of PCI device//		u8 *slot - Pointer to u8 where slot number will//			be returned//// Output:	SUCCESS or FAILURE//=============================================================================static int get_slot_mapping (struct pci_ops *ops, u8 bus_num, u8 dev_num, u8 *slot){	struct irq_routing_table *PCIIRQRoutingInfoLength;	u32 work;	long len;	long loop;	u8 tbus, tdevice, tslot, bridgeSlot;	dbg(__FUNCTION__" %p, %d, %d, %p\n", ops, bus_num, dev_num, slot);	bridgeSlot = 0xFF;	PCIIRQRoutingInfoLength = pcibios_get_irq_routing_table();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -