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

📄 rt_pci.c

📁 最新rtlinux内核源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*********************************************************************************//* This file has been written by Sergio Perez Alca駃z <serpeal@upvnet.upv.es>    *//*            Departamento de Inform醫ica de Sistemas y Computadores             *//*            Universidad Polit閏nica de Valencia                                *//*            Valencia (Spain)                                                   *//*                                                                               *//* The RTL-lwIP project has been supported by the Spanish Government Research    *//* Office (CICYT) under grant TIC2002-04123-C03-03                               *//*                                                                               *//* Copyright (c) March, 2003 SISTEMAS DE TIEMPO REAL EMPOTRADOS, FIABLES Y       *//* DISTRIBUIDOS BASADOS EN COMPONENTES                                           *//*                                                                               *//*  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.  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA    *//*                                                                               *//*  Linking RTL-lwIP statically or dynamically with other modules is making a    *//*  combined work based on RTL-lwIP.  Thus, the terms and conditions of the GNU  *//*  General Public License cover the whole combination.                          *//*                                                                               *//*  As a special exception, the copyright holders of RTL-lwIP give you           *//*  permission to link RTL-lwIP with independent modules that communicate with   *//*  RTL-lwIP solely through the interfaces, regardless of the license terms of   *//*  these independent modules, and to copy and distribute the resulting combined *//*  work under terms of your choice, provided that every copy of the combined    *//*  work is accompanied by a complete copy of the source code of RTL-lwIP (the   *//*  version of RTL-lwIP used to produce the combined work), being distributed    *//*  under the terms of the GNU General Public License plus this exception.  An   *//*  independent module is a module which is not derived from or based on         *//*  RTL-lwIP.                                                                    *//*                                                                               *//*  Note that people who make modified versions of RTL-lwIP are not obligated to *//*  grant this special exception for their modified versions; it is their choice *//*  whether to do so.  The GNU General Public License gives permission to        *//*  release a modified version without this exception; this exception also makes *//*  it possible to release a modified version which carries forward this         *//*  exception.                                                                   *//*                                                                               *//*  CONTRIBUTORS: -Miguel Masmano Tello <mmasmano@disca.upv.es>                  *//*                -COMEDI                                                        *//*                 The Linux Control and Measurement Device Interface            *//*                 David Schleef <ds@schleef.org>                                *//*********************************************************************************/#include <time.h>#include "rt_pci.h"#ifdef	CONFIG_PCI_DIRECT#define  PCIBIOS_SUCCESSFUL                0x00#define CONFIG_CMD(bus, device_fn, where)   (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))/***************************************************************************************//** * rt_pci_enable_wake - enable device to generate PME# when suspended * @dev: - PCI device to operate on * @state: - Current state of device. * @enable: - Flag to enable or disable generation *  * Set the bits in the device's PM Capabilities to generate PME# when * the system is suspended.  * * -EIO is returned if device doesn't have PM Capabilities.  * -EINVAL is returned if device supports it, but can't generate wake events. * 0 if operation is successful. *  */int rt_pci_enable_wake(struct pci_dev *dev, u32 state, int enable){  int pm;  u16 value;    /* find PCI PM capability in list */  pm = rt_pci_find_capability(dev, PCI_CAP_ID_PM);    /* If device doesn't support PM Capabilities, but request is to disable   * wake events, it's a nop; otherwise fail */  if (!pm)     return enable ? -EIO : 0;     /* Check device's ability to generate PME# */  rt_pci_read_config_word(dev,pm+PCI_PM_PMC,&value);    value &= PCI_PM_CAP_PME_MASK;  value >>= ffs(value);   /* First bit of mask */  	/* Check if it can generate PME# from requested state. */  if (!value || !(value & (1 << state)))     return enable ? -EINVAL : 0;    rt_pci_read_config_word(dev, pm + PCI_PM_CTRL, &value);    /* Clear PME_Status by writing 1 to it and enable PME# */  value |= PCI_PM_CTRL_PME_STATUS | PCI_PM_CTRL_PME_ENABLE;    if (!enable)    value &= ~PCI_PM_CTRL_PME_ENABLE;    rt_pci_write_config_word(dev, pm + PCI_PM_CTRL, value);    return 0;}/***************************************************************************************//** * rt_pci_save_state - save the PCI configuration space of a device before suspending * @dev: - PCI device that we're dealing with * @buffer: - buffer to hold config space context * * @buffer must be large enough to hold the entire PCI 2.2 config space  * (>= 64 bytes). */int rt_pci_save_state(struct pci_dev *dev, u32 *buffer){	int i;	if (buffer) {		/* XXX: 100% dword access ok here? */		for (i = 0; i < 16; i++)			rt_pci_read_config_dword(dev, i * 4,&buffer[i]);	}	return 0;}/***************************************************************************************/int rt_pcibios_read_config_byte(unsigned int bus, unsigned int device_fn,			       unsigned int where, unsigned char *value){    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);    *value = inb(0xCFC + (where&3));    return PCIBIOS_SUCCESSFUL;}/***************************************************************************************/int rt_pcibios_read_config_word (unsigned int bus,    unsigned int device_fn, unsigned int where, unsigned short *value){    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);    *value = inw(0xCFC + (where&2));    return PCIBIOS_SUCCESSFUL;}/***************************************************************************************/int rt_pcibios_read_config_dword (unsigned int bus, unsigned int device_fn,				 unsigned int where, unsigned int *value){    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);    *value = inl(0xCFC);    return PCIBIOS_SUCCESSFUL;}/***************************************************************************************/int rt_pcibios_write_config_byte (unsigned int bus, unsigned int device_fn,				 unsigned int where, unsigned char value){    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);    outb(value, 0xCFC + (where&3));    return PCIBIOS_SUCCESSFUL;}/***************************************************************************************/int rt_pcibios_write_config_word (unsigned int bus, unsigned int device_fn,				 unsigned int where, unsigned short value){    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);    outw(value, 0xCFC + (where&2));    return PCIBIOS_SUCCESSFUL;}/***************************************************************************************/int rt_pcibios_write_config_dword (unsigned int bus, unsigned int device_fn, unsigned int where, unsigned int value){    outl(CONFIG_CMD(bus,device_fn,where), 0xCF8);    outl(value, 0xCFC);    return PCIBIOS_SUCCESSFUL;}/***************************************************************************************/int rt_pcibios_set_irq_routing(struct pci_dev *dev, int pin, int irq){  rt_pcibios_write_config_byte ((int) dev->bus, (int) dev->devfn,			     PCI_INTERRUPT_LINE, irq);  rt_pcibios_write_config_byte ((int) dev->bus, (int)dev->devfn,			     PCI_INTERRUPT_PIN, pin);  return 1;}#undef CONFIG_CMD#else	 /* CONFIG_PCI_DIRECT  no definido */static struct {	unsigned long address;	unsigned short segment;} bios32_indirect = { 0, KERN_CODE_SEG };static long pcibios_entry;static struct {	unsigned long address;	unsigned short segment;} pci_indirect = { 0, KERN_CODE_SEG };/***************************************************************************************/static unsigned long bios32_service(unsigned long service){	unsigned char return_code;	/* %al */	unsigned long address;		/* %ebx */	unsigned long length;		/* %ecx */	unsigned long entry;		/* %edx */	unsigned long flags;	save_flags(flags);	__asm__(#ifdef ABSOLUTE_WITHOUT_ASTERISK		"lcall (%%edi)"#else		"lcall *(%%edi)"#endif		: "=a" (return_code),		  "=b" (address),		  "=c" (length),		  "=d" (entry)		: "0" (service),		  "1" (0),		  "D" (&bios32_indirect));	restore_flags(flags);	switch (return_code) {		case 0:			return address + entry;		case 0x80:	/* No presente */			ethernet_printf("bios32_service(%d) : no presente\n", service);			return 0;		default: /* No deberia pasar */			ethernet_printf("bios32_service(%d) : devuelto %#X\n",				service, return_code);			return 0;	}}/***************************************************************************************/int rt_pcibios_read_config_byte(unsigned int bus,        unsigned int device_fn, unsigned int where, unsigned char *value){        unsigned long ret;        unsigned long bx = (bus << 8) | device_fn;        unsigned long flags;        save_flags(flags);        __asm__(#ifdef ABSOLUTE_WITHOUT_ASTERISK		"lcall (%%esi)\n\t"#else		"lcall *(%%esi)\n\t"#endif                "jc 1f\n\t"                "xor %%ah, %%ah\n"                "1:"                : "=c" (*value),                  "=a" (ret)                : "1" (PCIBIOS_READ_CONFIG_BYTE),                  "b" (bx),                  "D" ((long) where),                  "S" (&pci_indirect));        restore_flags(flags);        return (int) (ret & 0xff00) >> 8;}/***************************************************************************************/int rt_pcibios_read_config_word(unsigned int bus,        unsigned int device_fn, unsigned int where, unsigned short *value){        unsigned long ret;        unsigned long bx = (bus << 8) | device_fn;        unsigned long flags;        save_flags(flags);        __asm__(#ifdef ABSOLUTE_WITHOUT_ASTERISK		"lcall (%%esi)\n\t"#else		"lcall *(%%esi)\n\t"#endif                "jc 1f\n\t"                "xor %%ah, %%ah\n"                "1:"                : "=c" (*value),                  "=a" (ret)                : "1" (PCIBIOS_READ_CONFIG_WORD),                  "b" (bx),                  "D" ((long) where),                  "S" (&pci_indirect));        restore_flags(flags);        return (int) (ret & 0xff00) >> 8;}/***************************************************************************************/int rt_pcibios_read_config_dword(unsigned int bus,        unsigned int device_fn, unsigned int where, unsigned int *value){        unsigned long ret;        unsigned long bx = (bus << 8) | device_fn;        unsigned long flags;        save_flags(flags);        __asm__(#ifdef ABSOLUTE_WITHOUT_ASTERISK		"lcall (%%esi)\n\t"#else		"lcall *(%%esi)\n\t"#endif                "jc 1f\n\t"                "xor %%ah, %%ah\n"                "1:"                : "=c" (*value),                  "=a" (ret)                : "1" (PCIBIOS_READ_CONFIG_DWORD),                  "b" (bx),                  "D" ((long) where),                  "S" (&pci_indirect));        restore_flags(flags);        return (int) (ret & 0xff00) >> 8;}/***************************************************************************************/int rt_pcibios_write_config_byte (unsigned int bus,	unsigned int device_fn, unsigned int where, unsigned char value){	unsigned long ret;	unsigned long bx = (bus << 8) | device_fn;	unsigned long flags;	save_flags(flags); cli();	__asm__(#ifdef ABSOLUTE_WITHOUT_ASTERISK		"lcall (%%esi)\n\t"#else		"lcall *(%%esi)\n\t"#endif		"jc 1f\n\t"		"xor %%ah, %%ah\n"		"1:"

⌨️ 快捷键说明

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