xf86_pci.c
来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 1,218 行 · 第 1/3 页
C
1,218 行
/* $XFree86: xc/programs/Xserver/hw/xfree86/common_hw/xf86_PCI.c,v 3.16.2.5 1997/07/26 06:30:48 dawes Exp $ *//* * Copyright 1995 by Robin Cutshaw <robin@XFree86.Org> * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the names of the above listed copyright holder(s) * not be used in advertising or publicity pertaining to distribution of * the software without specific, written prior permission. The above listed * copyright holder(s) make(s) no representations about the suitability of this * software for any purpose. It is provided "as is" without express or * implied warranty. * * THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM(S) ALL WARRANTIES WITH REGARD * TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE * LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * *//* $XConsortium: xf86_PCI.c /main/14 1996/10/27 11:47:50 kaleb $ *//* #define DEBUGPCI 1 */#include <stdio.h>#include "os.h"#include "compiler.h"#ifndef OSKIT#include "input.h"#endif#include "xf86Procs.h"#include "xf86_OSlib.h"#include "xf86_PCI.h"#ifdef PC98#define outb(port,data) _outb(port,data)#define outl(port,data) _outl(port,data)#define inb(port) _inb(port)#define inl(port) _inl(port)#endifstatic pciConfigPtr pci_devp[MAX_PCI_DEVICES + 1] = {NULL, };#ifdef USE_OLD_PCI_CODE /* { */pciConfigPtr *xf86scanpci(scrnIndex)int scrnIndex;{ unsigned long tmplong1, tmplong2, config_cmd; unsigned char tmp1, tmp2; unsigned int i, j, idx = 0; pciConfigRec pcr; unsigned PCI_CtrlIOPorts[] = { PCI_MODE1_ADDRESS_REG, PCI_MODE2_FORWARD_REG, PCI_MODE1_DATA_REG }; int Num_PCI_CtrlIOPorts = 3; unsigned PCI_DevIOAddrPorts[16*16]; int Num_PCI_DevIOAddrPorts = 16*16; if (pci_devp[0]) return (pciConfigPtr *)NULL; for (i=0; i<16; i++) for (j=0; j<16; j++) PCI_DevIOAddrPorts[(i*16)+j] = 0xC000 + (i*0x0100) + (j*4); xf86ClearIOPortList(scrnIndex); xf86AddIOPorts(scrnIndex, Num_PCI_CtrlIOPorts, PCI_CtrlIOPorts); xf86AddIOPorts(scrnIndex, Num_PCI_DevIOAddrPorts, PCI_DevIOAddrPorts); /* Enable I/O access */ xf86EnableIOPorts(scrnIndex); outb(PCI_MODE2_ENABLE_REG, 0x00); outb(PCI_MODE2_FORWARD_REG, 0x00); tmp1 = inb(PCI_MODE2_ENABLE_REG); tmp2 = inb(PCI_MODE2_FORWARD_REG); /* * * Check the configuration type * */ if ((tmp1 == 0x00) && (tmp2 == 0x00)) { pcr._configtype = 2;#ifdef DEBUGPCI printf("PCI says configuration type 2\n");#endif } else { tmplong1 = inl(PCI_MODE1_ADDRESS_REG); /* save previous data */ outl(PCI_MODE1_ADDRESS_REG, PCI_EN); tmplong2 = inl(PCI_MODE1_ADDRESS_REG); outl(PCI_MODE1_ADDRESS_REG, tmplong1); #if 0 if (tmplong2 == PCI_EN) #else if (tmplong2 & PCI_EN) #endif { pcr._configtype = 1;#ifdef DEBUGPCI printf("PCI says configuration type 1\n");#endif } else { pcr._configtype = 0;#ifdef DEBUGPCI printf("No PCI !\n");#endif xf86DisableIOPorts(scrnIndex); xf86ClearIOPortList(scrnIndex); return (pciConfigPtr *)NULL; } } /* Try pci config 1 probe first */#ifdef DEBUGPCI printf("\nPCI probing configuration type 1\n");#endif pcr._pcibuses[0] = 0; pcr._pcinumbus = 1; pcr._pcibusidx = 0;#ifndef DEBUGPCI if (pcr._configtype == 1)#endif do { for (pcr._cardnum = 0x0; pcr._cardnum < PCI_CONFIG1_MAXDEV; pcr._cardnum++) { int func, maxfunc=0; unsigned long config_cmd1; CARD32 device_vendor1, base1; pcr._bus = pcr._pcibuses[pcr._pcibusidx]; for (func = 0; func <= maxfunc; func++) { config_cmd = PCI_EN | (pcr._pcibuses[pcr._pcibusidx] << 16ul) | (pcr._cardnum << 11ul) | (func << 8ul); outl(PCI_MODE1_ADDRESS_REG, config_cmd | PCI_ID_REG); /* ioreg 0 */ pcr._device_vendor = inl(PCI_MODE1_DATA_REG); if (pcr._vendor == 0xFFFF) /* nothing there */ continue;#ifdef DEBUGPCI printf("\npci bus 0x%x cardnum 0x%02x, vendor 0x%04x device 0x%04x\n", pcr._pcibuses[pcr._pcibusidx], pcr._cardnum, pcr._vendor, pcr._device);#endif outl(PCI_MODE1_ADDRESS_REG, config_cmd | PCI_CMD_STAT_REG); pcr._status_command = inl(PCI_MODE1_DATA_REG); outl(PCI_MODE1_ADDRESS_REG, config_cmd | PCI_CLASS_REG); pcr._class_revision = inl(PCI_MODE1_DATA_REG); outl(PCI_MODE1_ADDRESS_REG, config_cmd | PCI_HEADER_MISC); pcr._bist_header_latency_cache = inl(PCI_MODE1_DATA_REG); outl(PCI_MODE1_ADDRESS_REG, config_cmd | PCI_MAP_REG_START); pcr._base0 = inl(PCI_MODE1_DATA_REG); outl(PCI_MODE1_ADDRESS_REG, config_cmd | (PCI_MAP_REG_START+0x04)); pcr._base1 = inl(PCI_MODE1_DATA_REG); outl(PCI_MODE1_ADDRESS_REG, config_cmd | (PCI_MAP_REG_START+0x08)); pcr._base2 = inl(PCI_MODE1_DATA_REG); outl(PCI_MODE1_ADDRESS_REG, config_cmd | (PCI_MAP_REG_START+0x0C)); pcr._base3 = inl(PCI_MODE1_DATA_REG); outl(PCI_MODE1_ADDRESS_REG, config_cmd | (PCI_MAP_REG_START+0x10)); pcr._base4 = inl(PCI_MODE1_DATA_REG); outl(PCI_MODE1_ADDRESS_REG, config_cmd | (PCI_MAP_REG_START+0x14)); pcr._base5 = inl(PCI_MODE1_DATA_REG); outl(PCI_MODE1_ADDRESS_REG, config_cmd | (PCI_MAP_REG_START+0x18)); pcr.rsvd1 = inl(PCI_MODE1_DATA_REG); outl(PCI_MODE1_ADDRESS_REG, config_cmd | (PCI_MAP_REG_START+0x1C)); pcr.rsvd2 = inl(PCI_MODE1_DATA_REG); outl(PCI_MODE1_ADDRESS_REG, config_cmd | 0x30); pcr._baserom = inl(PCI_MODE1_DATA_REG); outl(PCI_MODE1_ADDRESS_REG, config_cmd | PCI_INTERRUPT_REG); pcr._max_min_ipin_iline = inl(PCI_MODE1_DATA_REG); outl(PCI_MODE1_ADDRESS_REG, config_cmd | PCI_REG_USERCONFIG); pcr._user_config = inl(PCI_MODE1_DATA_REG); pcr._func = func; /* Check Multi-function device */ if (pcr._bist_header_latency_cache & PCI_HEADER_MULTIFUNCTION) maxfunc = 7; if (func == 0) { config_cmd1 = PCI_EN | (pcr._pcibuses[pcr._pcibusidx] << 16ul) | (pcr._cardnum << 11ul) | (1<< 8ul); outl(PCI_MODE1_ADDRESS_REG, config_cmd1|PCI_ID_REG); device_vendor1 = inl(PCI_MODE1_DATA_REG); if (device_vendor1 != 0xFFFFFFFF) { /* nothing there */ if (pcr._device_vendor != device_vendor1) maxfunc = 7; outl(PCI_MODE1_ADDRESS_REG, config_cmd1|PCI_MAP_REG_START); base1 = inl(PCI_MODE1_DATA_REG); if (pcr._base0 != base1) maxfunc = 7; } } /* check for pci-pci bridges */ switch(pcr._class_revision & (PCI_CLASS_MASK|PCI_SUBCLASS_MASK)) { case PCI_CLASS_BRIDGE|PCI_SUBCLASS_BRIDGE_PCI: if (pcr._secondary_bus_number > 0) { pcr._pcibuses[pcr._pcinumbus++] = pcr._secondary_bus_number; } break; default: break; } if (idx >= MAX_PCI_DEVICES) continue; if ((pci_devp[idx] = (pciConfigPtr)xalloc(sizeof(pciConfigRec))) == (pciConfigPtr)NULL) { outl(PCI_MODE1_ADDRESS_REG, 0x00); xf86DisableIOPorts(scrnIndex); xf86ClearIOPortList(scrnIndex); return (pciConfigPtr *)NULL; } memcpy(pci_devp[idx++], &pcr, sizeof(pciConfigRec)); pci_devp[idx] = NULL; } } } while (++pcr._pcibusidx < pcr._pcinumbus);#ifndef DEBUGPCI if (pcr._configtype == 1) { outl(PCI_MODE1_ADDRESS_REG, 0x00); xf86DisableIOPorts(scrnIndex); xf86ClearIOPortList(scrnIndex); return pci_devp; }#endif /* Now try pci config 2 probe (deprecated) */ /* The code here doesn't handle multifunction devices. */ /* It doesn't seem to handle multiple busses fully either */ outb(PCI_MODE2_ENABLE_REG, 0xF1); outb(PCI_MODE2_FORWARD_REG, 0x00); /* bus 0 for now */#ifdef DEBUGPCI printf("\nPCI probing configuration type 2\n");#endif pcr._pcibuses[0] = 0; pcr._pcinumbus = 1; pcr._pcibusidx = 0; do { pcr._bus = pcr._pcibuses[pcr._pcibusidx]; for (pcr._ioaddr = 0xC000; pcr._ioaddr < 0xD000; pcr._ioaddr += 0x0100){ outb(PCI_MODE2_FORWARD_REG, pcr._pcibuses[pcr._pcibusidx]); /* bus 0 for now */ pcr._device_vendor = inl(pcr._ioaddr); outb(PCI_MODE2_FORWARD_REG, 0x00); /* bus 0 for now */ pcr._cardnum = (pcr._ioaddr >> 8) & 0x0f; if (pcr._vendor == 0xFFFF) /* nothing there */ continue; /* opti chipsets that use config type 1 look like this on type 2 */ if ((pcr._vendor == 0xFF00) && (pcr._device == 0xFFFF)) continue;#ifdef DEBUGPCI printf("\npci bus 0x%x slot at 0x%04x, vendor 0x%04x device 0x%04x\n", pcr._pcibuses[pcr._pcibusidx], pcr._ioaddr, pcr._vendor, pcr._device);#endif outb(PCI_MODE2_FORWARD_REG, pcr._pcibuses[pcr._pcibusidx]); /* bus 0 for now */ pcr._status_command = inl(pcr._ioaddr + 0x04); pcr._class_revision = inl(pcr._ioaddr + 0x08); pcr._bist_header_latency_cache = inl(pcr._ioaddr + 0x0C); pcr._base0 = inl(pcr._ioaddr + 0x10); pcr._base1 = inl(pcr._ioaddr + 0x14); pcr._base2 = inl(pcr._ioaddr + 0x18); pcr._base3 = inl(pcr._ioaddr + 0x1C); pcr._base4 = inl(pcr._ioaddr + 0x20); pcr._base5 = inl(pcr._ioaddr + 0x24); pcr.rsvd1 = inl(pcr._ioaddr + 0x28); pcr.rsvd2 = inl(pcr._ioaddr + 0x2C); pcr._baserom = inl(pcr._ioaddr + 0x30); pcr._max_min_ipin_iline = inl(pcr._ioaddr + 0x3C); pcr._user_config = inl(pcr._ioaddr + 0x40); outb(PCI_MODE2_FORWARD_REG, 0x00); /* bus 0 for now */ /* check for pci-pci bridges */ switch(pcr._class_revision & (PCI_CLASS_MASK|PCI_SUBCLASS_MASK)) { case PCI_CLASS_BRIDGE|PCI_SUBCLASS_BRIDGE_PCI: if (pcr._secondary_bus_number > 0) { pcr._pcibuses[pcr._pcinumbus++] = pcr._secondary_bus_number; } break; default: break; } if (idx >= MAX_PCI_DEVICES) continue; if ((pci_devp[idx] = (pciConfigPtr)xalloc(sizeof(pciConfigRec))) == (struct pci_config_reg *)NULL) { outb(PCI_MODE2_ENABLE_REG, 0x00); outb(PCI_MODE2_FORWARD_REG, 0x00); xf86DisableIOPorts(scrnIndex); xf86ClearIOPortList(scrnIndex); return (pciConfigPtr *)NULL; } memcpy(pci_devp[idx++], &pcr, sizeof(pciConfigRec)); pci_devp[idx] = NULL; } } while (++pcr._pcibusidx < pcr._pcinumbus); outb(PCI_MODE2_ENABLE_REG, 0x00); outb(PCI_MODE2_FORWARD_REG, 0x00); xf86DisableIOPorts(scrnIndex); xf86ClearIOPortList(scrnIndex); return pci_devp;}voidxf86writepci(scrnIndex, bus, cardnum, func, reg, mask, value) int scrnIndex; int bus; int cardnum; int func; int reg; unsigned long mask; unsigned long value;{ unsigned char tmp1, tmp2; unsigned long tmplong1, tmplong2, tmp, config_cmd; unsigned int i, j; unsigned PCI_CtrlIOPorts[] = { PCI_MODE1_ADDRESS_REG, PCI_MODE2_FORWARD_REG, PCI_MODE1_DATA_REG }; int configtype; int Num_PCI_CtrlIOPorts = 3; unsigned PCI_DevIOAddrPorts[16*16]; int Num_PCI_DevIOAddrPorts = 16*16; for (i=0; i<16; i++) for (j=0; j<16; j++) PCI_DevIOAddrPorts[(i*16)+j] = 0xC000 + (i*0x0100) + (j*4); xf86ClearIOPortList(scrnIndex); xf86AddIOPorts(scrnIndex, Num_PCI_CtrlIOPorts, PCI_CtrlIOPorts); xf86AddIOPorts(scrnIndex, Num_PCI_DevIOAddrPorts, PCI_DevIOAddrPorts); /* Enable I/O access */ xf86EnableIOPorts(scrnIndex); outb(PCI_MODE2_ENABLE_REG, 0x00); outb(PCI_MODE2_FORWARD_REG, 0x00); tmp1 = inb(PCI_MODE2_ENABLE_REG); tmp2 = inb(PCI_MODE2_FORWARD_REG); if ((tmp1 == 0x00) && (tmp2 == 0x00)) { configtype = 2;#ifdef DEBUGPCI printf("PCI says configuration type 2\n");#endif } else { tmplong1 = inl(PCI_MODE1_ADDRESS_REG); outl(PCI_MODE1_ADDRESS_REG, PCI_EN); tmplong2 = inl(PCI_MODE1_ADDRESS_REG); outl(PCI_MODE1_ADDRESS_REG, tmplong1); if (tmplong2 & PCI_EN) { configtype = 1;#ifdef DEBUGPCI printf("PCI says configuration type 1\n");#endif } else { configtype = 0;#ifdef DEBUGPCI printf("No PCI !\n");#endif xf86DisableIOPorts(scrnIndex); xf86ClearIOPortList(scrnIndex); return; } } if (configtype == 1) { config_cmd = PCI_EN | (bus << 16) | (cardnum << 11) | (func << 8); outl(PCI_MODE1_ADDRESS_REG, config_cmd | reg); tmp = inl(PCI_MODE1_DATA_REG) & ~mask; outl(PCI_MODE1_DATA_REG, tmp | (value & mask)); outl(PCI_MODE1_ADDRESS_REG, 0x00); xf86DisableIOPorts(scrnIndex); xf86ClearIOPortList(scrnIndex);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?