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

📄 shpchp_ctrl.c

📁 audio driver for hotplug pci on linux 2.6.27
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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>, <kristen.c.accardi@intel.com> * */#include <linux/module.h>#include <linux/kernel.h>#include <linux/types.h>#include <linux/pci.h>#include <linux/workqueue.h>#include "../pci.h"#include "shpchp.h"static void interrupt_event_handler(struct work_struct *work);static int shpchp_enable_slot(struct slot *p_slot);static int shpchp_disable_slot(struct slot *p_slot);static int queue_interrupt_event(struct slot *p_slot, u32 event_type){	struct event_info *info;	info = kmalloc(sizeof(*info), GFP_ATOMIC);	if (!info)		return -ENOMEM;	info->event_type = event_type;	info->p_slot = p_slot;	INIT_WORK(&info->work, interrupt_event_handler);	schedule_work(&info->work);	return 0;}u8 shpchp_handle_attention_button(u8 hp_slot, struct controller *ctrl){	struct slot *p_slot;	u32 event_type;	/* Attention Button Change */	dbg("shpchp:  Attention button interrupt received.\n");	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);	p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));	/*	 *  Button pressed - See if need to TAKE ACTION!!!	 */	info("Button pressed on Slot(%s)\n", slot_name(p_slot));	event_type = INT_BUTTON_PRESS;	queue_interrupt_event(p_slot, event_type);	return 0;}u8 shpchp_handle_switch_change(u8 hp_slot, struct controller *ctrl){	struct slot *p_slot;	u8 getstatus;	u32 event_type;	/* Switch Change */	dbg("shpchp:  Switch interrupt received.\n");	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);	p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));	p_slot->hpc_ops->get_latch_status(p_slot, &getstatus);	dbg("%s: Card present %x Power status %x\n", __func__,		p_slot->presence_save, p_slot->pwr_save);	if (getstatus) {		/*		 * Switch opened		 */		info("Latch open on Slot(%s)\n", slot_name(p_slot));		event_type = INT_SWITCH_OPEN;		if (p_slot->pwr_save && p_slot->presence_save) {			event_type = INT_POWER_FAULT;			err("Surprise Removal of card\n");		}	} else {		/*		 *  Switch closed		 */		info("Latch close on Slot(%s)\n", slot_name(p_slot));		event_type = INT_SWITCH_CLOSE;	}	queue_interrupt_event(p_slot, event_type);	return 1;}u8 shpchp_handle_presence_change(u8 hp_slot, struct controller *ctrl){	struct slot *p_slot;	u32 event_type;	/* Presence Change */	dbg("shpchp:  Presence/Notify input change.\n");	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);	/*	 * Save the presence state	 */	p_slot->hpc_ops->get_adapter_status(p_slot, &(p_slot->presence_save));	if (p_slot->presence_save) {		/*		 * Card Present		 */		info("Card present on Slot(%s)\n", slot_name(p_slot));		event_type = INT_PRESENCE_ON;	} else {		/*		 * Not Present		 */		info("Card not present on Slot(%s)\n", slot_name(p_slot));		event_type = INT_PRESENCE_OFF;	}	queue_interrupt_event(p_slot, event_type);	return 1;}u8 shpchp_handle_power_fault(u8 hp_slot, struct controller *ctrl){	struct slot *p_slot;	u32 event_type;	/* Power fault */	dbg("shpchp:  Power fault interrupt received.\n");	p_slot = shpchp_find_slot(ctrl, hp_slot + ctrl->slot_device_offset);	if ( !(p_slot->hpc_ops->query_power_fault(p_slot))) {		/*		 * Power fault Cleared		 */		info("Power fault cleared on Slot(%s)\n", slot_name(p_slot));		p_slot->status = 0x00;		event_type = INT_POWER_FAULT_CLEAR;	} else {		/*		 *   Power fault		 */		info("Power fault on Slot(%s)\n", slot_name(p_slot));		event_type = INT_POWER_FAULT;		/* set power fault status for this board */		p_slot->status = 0xFF;		info("power fault bit %x set\n", hp_slot);	}	queue_interrupt_event(p_slot, event_type);	return 1;}/* The following routines constitute the bulk of the   hotplug controller logic */static int change_bus_speed(struct controller *ctrl, struct slot *p_slot,		enum pci_bus_speed speed){	int rc = 0;	dbg("%s: change to speed %d\n", __func__, speed);	if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, speed))) {		err("%s: Issue of set bus speed mode command failed\n",		    __func__);		return WRONG_BUS_FREQUENCY;	}	return rc;}static int fix_bus_speed(struct controller *ctrl, struct slot *pslot,		u8 flag, enum pci_bus_speed asp, enum pci_bus_speed bsp,		enum pci_bus_speed msp){	int rc = 0;	/*	 * If other slots on the same bus are occupied, we cannot	 * change the bus speed.	 */	if (flag) {		if (asp < bsp) {			err("%s: speed of bus %x and adapter %x mismatch\n",			    __func__, bsp, asp);			rc = WRONG_BUS_FREQUENCY;		}		return rc;	}	if (asp < msp) {		if (bsp != asp)			rc = change_bus_speed(ctrl, pslot, asp);	} else {		if (bsp != msp)			rc = change_bus_speed(ctrl, pslot, msp);	}	return rc;}/** * board_added - Called after a board has been added to the system. * @p_slot: target &slot * * Turns power on for the board. * Configures board. */static int board_added(struct slot *p_slot){	u8 hp_slot;	u8 slots_not_empty = 0;	int rc = 0;	enum pci_bus_speed asp, bsp, msp;	struct controller *ctrl = p_slot->ctrl;	hp_slot = p_slot->device - ctrl->slot_device_offset;	dbg("%s: p_slot->device, slot_offset, hp_slot = %d, %d ,%d\n",			__func__, p_slot->device,			ctrl->slot_device_offset, hp_slot);	/* Power on slot without connecting to bus */	rc = p_slot->hpc_ops->power_on_slot(p_slot);	if (rc) {		err("%s: Failed to power on slot\n", __func__);		return -1;	}	if ((ctrl->pci_dev->vendor == 0x8086) && (ctrl->pci_dev->device == 0x0332)) {		if (slots_not_empty)			return WRONG_BUS_FREQUENCY;		if ((rc = p_slot->hpc_ops->set_bus_speed_mode(p_slot, PCI_SPEED_33MHz))) {			err("%s: Issue of set bus speed mode command failed\n", __func__);			return WRONG_BUS_FREQUENCY;		}		/* turn on board, blink green LED, turn off Amber LED */		if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) {			err("%s: Issue of Slot Enable command failed\n", __func__);			return rc;		}	}	rc = p_slot->hpc_ops->get_adapter_speed(p_slot, &asp);	if (rc) {		err("%s: Can't get adapter speed or bus mode mismatch\n",		    __func__);		return WRONG_BUS_FREQUENCY;	}	rc = p_slot->hpc_ops->get_cur_bus_speed(p_slot, &bsp);	if (rc) {		err("%s: Can't get bus operation speed\n", __func__);		return WRONG_BUS_FREQUENCY;	}	rc = p_slot->hpc_ops->get_max_bus_speed(p_slot, &msp);	if (rc) {		err("%s: Can't get max bus operation speed\n", __func__);		msp = bsp;	}	/* Check if there are other slots or devices on the same bus */	if (!list_empty(&ctrl->pci_dev->subordinate->devices))		slots_not_empty = 1;	dbg("%s: slots_not_empty %d, adapter_speed %d, bus_speed %d, "	    "max_bus_speed %d\n", __func__, slots_not_empty, asp,	    bsp, msp);	rc = fix_bus_speed(ctrl, p_slot, slots_not_empty, asp, bsp, msp);	if (rc)		return rc;	/* turn on board, blink green LED, turn off Amber LED */	if ((rc = p_slot->hpc_ops->slot_enable(p_slot))) {		err("%s: Issue of Slot Enable command failed\n", __func__);		return rc;	}	/* Wait for ~1 second */	msleep(1000);	dbg("%s: slot status = %x\n", __func__, p_slot->status);	/* Check for a power fault */	if (p_slot->status == 0xFF) {		/* power fault occurred, but it was benign */		dbg("%s: power fault\n", __func__);		rc = POWER_FAILURE;		p_slot->status = 0;		goto err_exit;	}	if (shpchp_configure_device(p_slot)) {		err("Cannot add device at 0x%x:0x%x\n", p_slot->bus,				p_slot->device);		goto err_exit;	}	p_slot->status = 0;	p_slot->is_a_board = 0x01;	p_slot->pwr_save = 1;	p_slot->hpc_ops->green_led_on(p_slot);	return 0;err_exit:	/* turn off slot, turn on Amber LED, turn off Green LED */	rc = p_slot->hpc_ops->slot_disable(p_slot);	if (rc) {		err("%s: Issue of Slot Disable command failed\n", __func__);		return rc;	}	return(rc);}/** * remove_board - Turns off slot and LEDs * @p_slot: target &slot */static int remove_board(struct slot *p_slot){	struct controller *ctrl = p_slot->ctrl;	u8 hp_slot;	int rc;

⌨️ 快捷键说明

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