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

📄 ibmphp_core.c

📁 audio driver for hotplug pci on linux 2.6.27
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * IBM Hot Plug Controller Driver * * Written By: Chuck Cole, Jyoti Shah, Tong Yu, Irene Zubarev, IBM Corporation * * Copyright (C) 2001,2003 Greg Kroah-Hartman (greg@kroah.com) * Copyright (C) 2001-2003 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 <gregkh@us.ibm.com> * */#include <linux/init.h>#include <linux/module.h>#include <linux/slab.h>#include <linux/pci.h>#include <linux/interrupt.h>#include <linux/delay.h>#include <linux/wait.h>#include "../pci.h"#include "../../../arch/x86/pci/pci.h"	/* for struct irq_routing_table */#include "ibmphp.h"#define attn_on(sl)  ibmphp_hpc_writeslot (sl, HPC_SLOT_ATTNON)#define attn_off(sl) ibmphp_hpc_writeslot (sl, HPC_SLOT_ATTNOFF)#define attn_LED_blink(sl) ibmphp_hpc_writeslot (sl, HPC_SLOT_BLINKLED)#define get_ctrl_revision(sl, rev) ibmphp_hpc_readslot (sl, READ_REVLEVEL, rev)#define get_hpc_options(sl, opt) ibmphp_hpc_readslot (sl, READ_HPCOPTIONS, opt)#define DRIVER_VERSION	"0.6"#define DRIVER_DESC	"IBM Hot Plug PCI Controller Driver"int ibmphp_debug;static int debug;module_param(debug, bool, S_IRUGO | S_IWUSR);MODULE_PARM_DESC (debug, "Debugging mode enabled or not");MODULE_LICENSE ("GPL");MODULE_DESCRIPTION (DRIVER_DESC);struct pci_bus *ibmphp_pci_bus;static int max_slots;static int irqs[16];    /* PIC mode IRQ's we're using so far (in case MPS			 * tables don't provide default info for empty slots */static int init_flag;/*static int get_max_adapter_speed_1 (struct hotplug_slot *, u8 *, u8);static inline int get_max_adapter_speed (struct hotplug_slot *hs, u8 *value){	return get_max_adapter_speed_1 (hs, value, 1);}*/static inline int get_cur_bus_info(struct slot **sl) {	int rc = 1;	struct slot * slot_cur = *sl;	debug("options = %x\n", slot_cur->ctrl->options);	debug("revision = %x\n", slot_cur->ctrl->revision);		if (READ_BUS_STATUS(slot_cur->ctrl)) 		rc = ibmphp_hpc_readslot(slot_cur, READ_BUSSTATUS, NULL);		if (rc) 		return rc;	  	slot_cur->bus_on->current_speed = CURRENT_BUS_SPEED(slot_cur->busstatus);	if (READ_BUS_MODE(slot_cur->ctrl))		slot_cur->bus_on->current_bus_mode =				CURRENT_BUS_MODE(slot_cur->busstatus);	else		slot_cur->bus_on->current_bus_mode = 0xFF;	debug("busstatus = %x, bus_speed = %x, bus_mode = %x\n",			slot_cur->busstatus,			slot_cur->bus_on->current_speed,			slot_cur->bus_on->current_bus_mode);		*sl = slot_cur;	return 0;}static inline int slot_update(struct slot **sl){	int rc; 	rc = ibmphp_hpc_readslot(*sl, READ_ALLSTAT, NULL);	if (rc) 		return rc;	if (!init_flag)		rc = get_cur_bus_info(sl);	return rc;}static int __init get_max_slots (void){	struct slot * slot_cur;	struct list_head * tmp;	u8 slot_count = 0;	list_for_each(tmp, &ibmphp_slot_head) {		slot_cur = list_entry(tmp, struct slot, ibm_slot_list);		/* sometimes the hot-pluggable slots start with 4 (not always from 1) */		slot_count = max(slot_count, slot_cur->number);	}	return slot_count;}/* This routine will put the correct slot->device information per slot.  It's * called from initialization of the slot structures. It will also assign * interrupt numbers per each slot. * Parameters: struct slot * Returns 0 or errors */int ibmphp_init_devno(struct slot **cur_slot){	struct irq_routing_table *rtable;	int len;	int loop;	int i;	rtable = pcibios_get_irq_routing_table();	if (!rtable) {		err("no BIOS routing table...\n");		return -ENOMEM;	}	len = (rtable->size - sizeof(struct irq_routing_table)) /			sizeof(struct irq_info);	if (!len) {		kfree(rtable);		return -1;	}	for (loop = 0; loop < len; loop++) {		if ((*cur_slot)->number == rtable->slots[loop].slot) {		if ((*cur_slot)->bus == rtable->slots[loop].bus) {			(*cur_slot)->device = PCI_SLOT(rtable->slots[loop].devfn);			for (i = 0; i < 4; i++)				(*cur_slot)->irq[i] = IO_APIC_get_PCI_irq_vector((int) (*cur_slot)->bus,						(int) (*cur_slot)->device, i);				debug("(*cur_slot)->irq[0] = %x\n",						(*cur_slot)->irq[0]);				debug("(*cur_slot)->irq[1] = %x\n",						(*cur_slot)->irq[1]);				debug("(*cur_slot)->irq[2] = %x\n",						(*cur_slot)->irq[2]);				debug("(*cur_slot)->irq[3] = %x\n",						(*cur_slot)->irq[3]);				debug("rtable->exlusive_irqs = %x\n",					rtable->exclusive_irqs);				debug("rtable->slots[loop].irq[0].bitmap = %x\n",					rtable->slots[loop].irq[0].bitmap);				debug("rtable->slots[loop].irq[1].bitmap = %x\n",					rtable->slots[loop].irq[1].bitmap);				debug("rtable->slots[loop].irq[2].bitmap = %x\n",					rtable->slots[loop].irq[2].bitmap);				debug("rtable->slots[loop].irq[3].bitmap = %x\n",					rtable->slots[loop].irq[3].bitmap);				debug("rtable->slots[loop].irq[0].link = %x\n",					rtable->slots[loop].irq[0].link);				debug("rtable->slots[loop].irq[1].link = %x\n",					rtable->slots[loop].irq[1].link);				debug("rtable->slots[loop].irq[2].link = %x\n",					rtable->slots[loop].irq[2].link);				debug("rtable->slots[loop].irq[3].link = %x\n",					rtable->slots[loop].irq[3].link);				debug("end of init_devno\n");				kfree(rtable);				return 0;			}		}	}	kfree(rtable);	return -1;}static inline int power_on(struct slot *slot_cur){	u8 cmd = HPC_SLOT_ON;	int retval;	retval = ibmphp_hpc_writeslot(slot_cur, cmd);	if (retval) {		err("power on failed\n");		return retval;	}	if (CTLR_RESULT(slot_cur->ctrl->status)) {		err("command not completed successfully in power_on\n");		return -EIO;	}	msleep(3000);	/* For ServeRAID cards, and some 66 PCI */	return 0;}static inline int power_off(struct slot *slot_cur){	u8 cmd = HPC_SLOT_OFF;	int retval;	retval = ibmphp_hpc_writeslot(slot_cur, cmd);	if (retval) {		err("power off failed\n");		return retval;	}	if (CTLR_RESULT(slot_cur->ctrl->status)) {		err("command not completed successfully in power_off\n");		retval = -EIO;	}	return retval;}static int set_attention_status(struct hotplug_slot *hotplug_slot, u8 value){	int rc = 0;	struct slot *pslot;	u8 cmd = 0x00;     /* avoid compiler warning */	debug("set_attention_status - Entry hotplug_slot[%lx] value[%x]\n",			(ulong) hotplug_slot, value);	ibmphp_lock_operations();	if (hotplug_slot) {		switch (value) {		case HPC_SLOT_ATTN_OFF:			cmd = HPC_SLOT_ATTNOFF;			break;		case HPC_SLOT_ATTN_ON:			cmd = HPC_SLOT_ATTNON;			break;		case HPC_SLOT_ATTN_BLINK:			cmd = HPC_SLOT_BLINKLED;			break;		default:			rc = -ENODEV;			err("set_attention_status - Error : invalid input [%x]\n",					value);			break;		}		if (rc == 0) {			pslot = hotplug_slot->private;			if (pslot)				rc = ibmphp_hpc_writeslot(pslot, cmd);			else				rc = -ENODEV;		}	} else			rc = -ENODEV;	ibmphp_unlock_operations();	debug("set_attention_status - Exit rc[%d]\n", rc);	return rc;}static int get_attention_status(struct hotplug_slot *hotplug_slot, u8 * value){	int rc = -ENODEV;	struct slot *pslot;	struct slot myslot;	debug("get_attention_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",					(ulong) hotplug_slot, (ulong) value);        	ibmphp_lock_operations();	if (hotplug_slot) {		pslot = hotplug_slot->private;		if (pslot) {			memcpy(&myslot, pslot, sizeof(struct slot));			rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS,						&(myslot.status));			if (!rc)				rc = ibmphp_hpc_readslot(pslot,						READ_EXTSLOTSTATUS,						&(myslot.ext_status));			if (!rc)				*value = SLOT_ATTN(myslot.status,						myslot.ext_status);		}	}	ibmphp_unlock_operations();	debug("get_attention_status - Exit rc[%d] value[%x]\n", rc, *value);	return rc;}static int get_latch_status(struct hotplug_slot *hotplug_slot, u8 * value){	int rc = -ENODEV;	struct slot *pslot;	struct slot myslot;	debug("get_latch_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",					(ulong) hotplug_slot, (ulong) value);	ibmphp_lock_operations();	if (hotplug_slot) {		pslot = hotplug_slot->private;		if (pslot) {			memcpy(&myslot, pslot, sizeof(struct slot));			rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS,						&(myslot.status));			if (!rc)				*value = SLOT_LATCH(myslot.status);		}	}	ibmphp_unlock_operations();	debug("get_latch_status - Exit rc[%d] rc[%x] value[%x]\n",			rc, rc, *value);	return rc;}static int get_power_status(struct hotplug_slot *hotplug_slot, u8 * value){	int rc = -ENODEV;	struct slot *pslot;	struct slot myslot;	debug("get_power_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",					(ulong) hotplug_slot, (ulong) value);	ibmphp_lock_operations();	if (hotplug_slot) {		pslot = hotplug_slot->private;		if (pslot) {			memcpy(&myslot, pslot, sizeof(struct slot));			rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS,						&(myslot.status));			if (!rc)				*value = SLOT_PWRGD(myslot.status);		}	}	ibmphp_unlock_operations();	debug("get_power_status - Exit rc[%d] rc[%x] value[%x]\n",			rc, rc, *value);	return rc;}static int get_adapter_present(struct hotplug_slot *hotplug_slot, u8 * value){	int rc = -ENODEV;	struct slot *pslot;	u8 present;	struct slot myslot;	debug("get_adapter_status - Entry hotplug_slot[%lx] pvalue[%lx]\n",					(ulong) hotplug_slot, (ulong) value);	ibmphp_lock_operations();	if (hotplug_slot) {		pslot = hotplug_slot->private;		if (pslot) {			memcpy(&myslot, pslot, sizeof(struct slot));			rc = ibmphp_hpc_readslot(pslot, READ_SLOTSTATUS,						&(myslot.status));			if (!rc) {				present = SLOT_PRESENT(myslot.status);				if (present == HPC_SLOT_EMPTY)					*value = 0;				else					*value = 1;			}		}	}	ibmphp_unlock_operations();	debug("get_adapter_present - Exit rc[%d] value[%x]\n", rc, *value);	return rc;}static int get_max_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value){	int rc = -ENODEV;	struct slot *pslot;	u8 mode = 0;	debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __func__,		hotplug_slot, value);	ibmphp_lock_operations();	if (hotplug_slot) {		pslot = hotplug_slot->private;		if (pslot) {			rc = 0;			mode = pslot->supported_bus_mode;			*value = pslot->supported_speed; 			switch (*value) {			case BUS_SPEED_33:				break;			case BUS_SPEED_66:				if (mode == BUS_MODE_PCIX) 					*value += 0x01;				break;			case BUS_SPEED_100:			case BUS_SPEED_133:				*value = pslot->supported_speed + 0x01;				break;			default:				/* Note (will need to change): there would be soon 256, 512 also */				rc = -ENODEV;			}		}	}	ibmphp_unlock_operations();	debug("%s - Exit rc[%d] value[%x]\n", __func__, rc, *value);	return rc;}static int get_cur_bus_speed(struct hotplug_slot *hotplug_slot, enum pci_bus_speed *value){	int rc = -ENODEV;	struct slot *pslot;	u8 mode = 0;	debug("%s - Entry hotplug_slot[%p] pvalue[%p]\n", __func__,		hotplug_slot, value);	ibmphp_lock_operations();	if (hotplug_slot) {		pslot = hotplug_slot->private;		if (pslot) {			rc = get_cur_bus_info(&pslot);			if (!rc) {				mode = pslot->bus_on->current_bus_mode;				*value = pslot->bus_on->current_speed;				switch (*value) {				case BUS_SPEED_33:					break;				case BUS_SPEED_66:					if (mode == BUS_MODE_PCIX) 						*value += 0x01;					else if (mode == BUS_MODE_PCI)						;					else						*value = PCI_SPEED_UNKNOWN;					break;				case BUS_SPEED_100:				case BUS_SPEED_133:					*value += 0x01;					break;				default:					/* Note of change: there would also be 256, 512 soon */					rc = -ENODEV;				}			}		}	}

⌨️ 快捷键说明

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