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

📄 ibmphp_core.c

📁 优龙2410linux2.6.8内核源代码
💻 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 <linux/smp_lock.h>#include "../pci.h"#include "../../../arch/i386/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_PARM (debug, "i");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)		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");				return 0;			}		}	}	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;	}	long_delay (3 * HZ); /* 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;	debug ("set_attention_status - Entry hotplug_slot[%lx] value[%x]\n", (ulong) hotplug_slot, value);	ibmphp_lock_operations ();	cmd = 0x00;     // avoid compiler warning	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 = (struct slot *) 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 && value) {		pslot = (struct slot *) hotplug_slot->private;		if (pslot) {			memcpy ((void *) &myslot, (void *) 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 && value) {		pslot = (struct slot *) hotplug_slot->private;		if (pslot) {			memcpy ((void *) &myslot, (void *) 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 && value) {		pslot = (struct slot *) hotplug_slot->private;		if (pslot) {			memcpy ((void *) &myslot, (void *) 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 && value) {		pslot = (struct slot *) hotplug_slot->private;		if (pslot) {			memcpy ((void *) &myslot, (void *) 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", __FUNCTION__,		hotplug_slot, value);	ibmphp_lock_operations ();	if (hotplug_slot && value) {		pslot = (struct slot *) 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", __FUNCTION__, 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", __FUNCTION__,		hotplug_slot, value);	ibmphp_lock_operations ();	if (hotplug_slot && value) {		pslot = (struct slot *) 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;				}			}		}	}	ibmphp_unlock_operations ();	debug ("%s - Exit rc[%d] value[%x]\n", __FUNCTION__, rc, *value);	return rc;}/*static int get_max_adapter_speed_1 (struct hotplug_slot *hotplug_slot, u8 * value, u8 flag){	int rc = -ENODEV;	struct slot *pslot;	struct slot myslot;	debug ("get_max_adapter_speed_1 - Entry hotplug_slot[%lx] pvalue[%lx]\n", (ulong)hotplug_slot, (ulong) value);

⌨️ 快捷键说明

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