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

📄 pci.c

📁 一款类linux的操作系统源码
💻 C
字号:
/* *  Roadrunner/pk *    Copyright (C) 1989-2001  Cornfed Systems, Inc. * *  The Roadrunner/pk operating system is free software; you can *  redistribute and/or modify it under the terms of the GNU General *  Public License, version 2, as published by the Free Software *  Foundation. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT 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 * *  More information about the Roadrunner/pk operating system of *  which this file is a part is available on the World-Wide Web *  at: http://www.cornfed.com. * */#include <bus/pci.h>#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys.h>#include <sys/mem.h>/* Slots per PCI bus */#define PCI_SLOTS				32/* PCI function classes */#define PCI_CLASS_PRE				0#define PCI_CLASS_STORAGE			0x01#define PCI_CLASS_NETWORK			0x02#define PCI_CLASS_DISPLAY			0x03#define PCI_CLASS_MULTIMEDIA			0x04#define PCI_CLASS_MEMORY			0x05#define PCI_CLASS_BRIDGE			0x06#define PCI_CLASS_COMM				0x07#define PCI_CLASS_BASE				0x08#define PCI_CLASS_INPUT				0x09#define PCI_CLASS_DOCK				0x0a#define PCI_CLASS_CPU				0x0b#define PCI_CLASS_SERIAL			0x0c#define PCI_CLASS_WIRELESS			0x0d#define PCI_CLASS_IIO				0x0e#define PCI_CLASS_SATELLITE			0x0f#define PCI_CLASS_SEC				0x10#define PCI_CLASS_DSP				0x11/* PCI storage function subclasses */#define PCI_STORAGE_SCSI			0#define PCI_STORAGE_IDE				1#define PCI_STORAGE_FLOPPY			2#define PCI_STORAGE_RAID			4/* PCI network function subclasses */#define PCI_NETWORK_ETHERNET			0#define PCI_NETWORK_TOKEN			1#define PCI_NETWORK_FDDI			2#define PCI_NETWORK_ATM				3#define PCI_NETWORK_ISDN			4/* PCI display function subclasses */#define PCI_DISPLAY_VGA				0#define PCI_DISPLAY_XGA				1#define PCI_DISPLAY_3D				2/* PCI multimedia function subclasses */#define PCI_MULTIMEDIA_VIDEO			0#define PCI_MULTIMEDIA_AUDIO			1#define PCI_MULTIMEDIA_TELEPHONY		2/* PCI memory controller function subclasses */#define PCI_MEMORY_RAM				0#define PCI_MEMORY_FLASH			1/* PCI bridge function subclasses */#define PCI_BRIDGE_HOST				0#define PCI_BRIDGE_ISA				1#define PCI_BRIDGE_EISA				2#define PCI_BRIDGE_MICROCHAN			3#define PCI_BRIDGE_PCI				4#define PCI_BRIDGE_PCMCIA			5#define PCI_BRIDGE_NUBUS			6#define PCI_BRIDGE_CARDBUS			7#define PCI_BRIDGE_RACEWAY			8/* PCI serial bus controller function subclasses */#define PCI_SERIAL_IEEE1394			0#define PCI_SERIAL_USB				3#define PCI_SERIAL_FIBRE_CHANNEL		4/* Name lengths */#define PCI_VENDOR_NAME_LEN			18#define PCI_CLASS_NAME_LEN			26#define PCI_STORAGE_SUBCLASS_NAME_LEN		18#define PCI_NETWORK_SUBCLASS_NAME_LEN		20#define PCI_DISPLAY_SUBCLASS_NAME_LEN		14#define PCI_MULTIMEDIA_SUBCLASS_NAME_LEN	20#define PCI_MEMORY_SUBCLASS_NAME_LEN		16#define PCI_BRIDGE_SUBCLASS_NAME_LEN		12#define PCI_SERIAL_SUBCLASS_NAME_LEN		24struct pci_vendor {    u_short id;    char name[PCI_VENDOR_NAME_LEN];};struct pci_class {    u_short id;    char name[PCI_CLASS_NAME_LEN];};struct pci_storage_subclass {    u_short id;    char name[PCI_STORAGE_SUBCLASS_NAME_LEN];};struct pci_network_subclass {    u_short id;    char name[PCI_NETWORK_SUBCLASS_NAME_LEN];};struct pci_display_subclass {    u_short id;    char name[PCI_DISPLAY_SUBCLASS_NAME_LEN];};struct pci_multimedia_subclass {    u_short id;    char name[PCI_MULTIMEDIA_SUBCLASS_NAME_LEN];};struct pci_memory_subclass {    u_short id;    char name[PCI_MEMORY_SUBCLASS_NAME_LEN];};struct pci_bridge_subclass {    u_short id;    char name[PCI_BRIDGE_SUBCLASS_NAME_LEN];};struct pci_serial_subclass {    u_short id;    char name[PCI_SERIAL_SUBCLASS_NAME_LEN];};struct pci_vendor pci_vendors[] = {    {PCI_VENDOR_COMPAQ, "Compaq"},    {PCI_VENDOR_NCR, "NCR"},    {PCI_VENDOR_ATI, "ATI"},    {PCI_VENDOR_VLSI, "VLSI"},    {PCI_VENDOR_TSENG, "Tseng"},    {PCI_VENDOR_WEITEK, "Weitek"},    {PCI_VENDOR_DEC, "DEC"},    {PCI_VENDOR_CIRRUS, "Cirrus Logic"},    {PCI_VENDOR_IBM, "IBM"},    {PCI_VENDOR_AMD, "AMD"},    {PCI_VENDOR_TRIDENT, "Trident"},    {PCI_VENDOR_MATROX, "Matrox"},    {PCI_VENDOR_NEC, "NEC"},    {PCI_VENDOR_HP, "HP"},    {PCI_VENDOR_BUSLOGIC, "Buslogic"},    {PCI_VENDOR_TI, "Texas Instruments"},    {PCI_VENDOR_MOTOROLA, "Motorola"},    {PCI_VENDOR_NUMBER9, "Number 9"},    {PCI_VENDOR_APPLE, "Apple"},    {PCI_VENDOR_CYRIX, "Cyrix"},    {PCI_VENDOR_SUN, "Sun"},    {PCI_VENDOR_3COM, "3Com"},    {PCI_VENDOR_ACER, "Acer Labs"},    {PCI_VENDOR_MITSUBISHI, "Mitsubishi"},    {PCI_VENDOR_NVIDIA, "Nvidia"},    {PCI_VENDOR_FORE, "Fore"},    {PCI_VENDOR_PHILLIPS, "Phillips"},    {PCI_VENDOR_RENDITION, "Rendition"},    {PCI_VENDOR_TOSHIBA, "Toshiba"},    {PCI_VENDOR_ENSONIQ, "Ensoniq"},    {PCI_VENDOR_ROCKWELL, "Rockwell"},    {PCI_VENDOR_NETGEAR, "Netgear"},    {PCI_VENDOR_VMWARE, "VMware"},    {PCI_VENDOR_S3, "S3"},    {PCI_VENDOR_INTEL, "Intel"},    {PCI_VENDOR_ADAPTEC, "Adaptec"},    {PCI_VENDOR_ADAPTEC2, "Adaptec"}};struct pci_class pci_classes[] = {    {PCI_CLASS_PRE, "pre ver 2.0"},    {PCI_CLASS_STORAGE, "mass storage controller"},    {PCI_CLASS_NETWORK, "network interface"},    {PCI_CLASS_DISPLAY, "display controller"},    {PCI_CLASS_MULTIMEDIA, "multimedia controller"},    {PCI_CLASS_MEMORY, "memory controller"},    {PCI_CLASS_BRIDGE, "bridge controller"},    {PCI_CLASS_COMM, "communications controller"},    {PCI_CLASS_BASE, "base system peripheral"},    {PCI_CLASS_INPUT, "input controller"},    {PCI_CLASS_DOCK, "docking station"},    {PCI_CLASS_CPU, "processor"},    {PCI_CLASS_SERIAL, "serial bus controller"},    {PCI_CLASS_WIRELESS, "wireless interface"},    {PCI_CLASS_IIO, "intelligent I/O controller"},    {PCI_CLASS_SATELLITE, "satellite interface"},    {PCI_CLASS_SEC, "encryption/decryption"},    {PCI_CLASS_DSP, "digital signal processor"}};struct pci_storage_subclass pci_storage_subclasses[] = {    {PCI_STORAGE_SCSI, "SCSI controller"},    {PCI_STORAGE_IDE, "IDE controller"},    {PCI_STORAGE_FLOPPY, "floppy controller"},    {PCI_STORAGE_RAID, "RAID controller"}};struct pci_network_subclass pci_network_subclasses[] = {    {PCI_NETWORK_ETHERNET, "Ethernet interface"},    {PCI_NETWORK_TOKEN, "Token Ring interface"},    {PCI_NETWORK_FDDI, "FDDI interface"},    {PCI_NETWORK_ATM, "ATM interface"},    {PCI_NETWORK_ISDN, "ISDN interface"}};struct pci_display_subclass pci_display_subclasses[] = {    {PCI_DISPLAY_VGA, "VGA controller"},    {PCI_DISPLAY_XGA, "XGA controller"},    {PCI_DISPLAY_3D, "3D controller"}};struct pci_multimedia_subclass pci_multimedia_subclasses[] = {    {PCI_MULTIMEDIA_VIDEO, "video controller"},    {PCI_MULTIMEDIA_AUDIO, "audio controller"},    {PCI_MULTIMEDIA_TELEPHONY, "telephony controller"}};struct pci_memory_subclass pci_memory_subclasses[] = {    {PCI_MEMORY_RAM, "RAM controller"},    {PCI_MEMORY_FLASH, "Flash controller"}};struct pci_bridge_subclass pci_bridge_subclasses[] = {    {PCI_BRIDGE_HOST, "host"},    {PCI_BRIDGE_ISA, "ISA"},    {PCI_BRIDGE_EISA, "EISA"},    {PCI_BRIDGE_MICROCHAN, "Microchannel"},    {PCI_BRIDGE_PCI, "PCI"},    {PCI_BRIDGE_PCMCIA, "PCMCIA"},    {PCI_BRIDGE_NUBUS, "Nubus"},    {PCI_BRIDGE_CARDBUS, "Cardbus"},    {PCI_BRIDGE_RACEWAY, "Raceway"}};struct pci_serial_subclass pci_serial_subclasses[] = {    {PCI_SERIAL_IEEE1394, "IEEE 1394 controller"},    {PCI_SERIAL_USB, "USB controller"},    {PCI_SERIAL_FIBRE_CHANNEL, "Fibre Channel controller"}};static int pcifuncs = 0;static int pcifunc = 0;static pci_func_t pcitab;static int vendors = (sizeof(pci_vendors) / sizeof(struct pci_vendor));static int classes = (sizeof(pci_classes) / sizeof(struct pci_class));static int storagesubclasses =    (sizeof(pci_storage_subclasses) / sizeof(struct pci_storage_subclass));static int networksubclasses =    (sizeof(pci_network_subclasses) / sizeof(struct pci_network_subclass));static int displaysubclasses =    (sizeof(pci_display_subclasses) / sizeof(struct pci_display_subclass));static int multimediasubclasses =    (sizeof(pci_multimedia_subclasses) /     sizeof(struct pci_multimedia_subclass));static int memorysubclasses =    (sizeof(pci_memory_subclasses) / sizeof(struct pci_memory_subclass));static int bridgesubclasses =    (sizeof(pci_bridge_subclasses) / sizeof(struct pci_bridge_subclass));static int serialsubclasses =    (sizeof(pci_serial_subclasses) / sizeof(struct pci_serial_subclass));u_longpci_config_read(int bus, int dev, int func, int dword){    outl(PCI_CONFIG_ADDR, ((u_long) 0x80000000 | (bus << 16) |			   (dev << 11) | (func << 8) | (dword << 2)));    return inl(PCI_CONFIG_DATA);}voidpci_config_write(int bus, int dev, int func, int dword, u_long val){    outl(PCI_CONFIG_ADDR, ((u_long) 0x80000000 | (bus << 16) |			   (dev << 11) | (func << 8) | (dword << 2)));    outl(PCI_CONFIG_DATA, val);}voidpci_busmaster_enable(int bus, int dev, int func){    u_long cmdstat;    cmdstat = pci_config_read(bus, dev, func, PCI_CONFIG_CMD_STAT);    cmdstat |= 0x04;    pci_config_write(bus, dev, func, PCI_CONFIG_CMD_STAT, cmdstat);}static intpci_device_count(int bus){    u_long vendorid;    int devs = 0, dev;    for (dev = 0; dev < PCI_SLOTS; dev++) {	vendorid = pci_config_read(bus, dev, 0, PCI_CONFIG_VENDOR) & 0xffff;	if (vendorid < 0xffff)	    devs++;    }#if _DEBUG    if (devs > 0)	kprintf("pci_device_count: %d devices on pci bus %d\n", devs, bus);#endif    return devs;}static voiddump_pcivendor(u_short vendorid){    int i;    for (i = 0; i < vendors; i++)	if (pci_vendors[i].id == vendorid) {	    kprintf("%s", pci_vendors[i].name);	    break;	}    if (i == vendors)	kprintf("vendor id %04x", vendorid);}static voiddump_pciclass(u_short class, u_short subclass){    int i, j;    for (i = 0; i < classes; i++)	if (pci_classes[i].id == class) {	    switch (class) {	    case PCI_CLASS_STORAGE:		for (j = 0; j < storagesubclasses; j++)		    if (pci_storage_subclasses[j].id == subclass) {			kprintf(" %s", pci_storage_subclasses[j].name);			break;		    }		if (j == storagesubclasses)		    kprintf(" %s", pci_classes[i].name);		break;	    case PCI_CLASS_NETWORK:		for (j = 0; j < networksubclasses; j++)		    if (pci_network_subclasses[j].id == subclass) {			kprintf(" %s", pci_network_subclasses[j].name);			break;		    }		if (j == networksubclasses)		    kprintf(" %s", pci_classes[i].name);		break;	    case PCI_CLASS_DISPLAY:		for (j = 0; j < displaysubclasses; j++)		    if (pci_display_subclasses[j].id == subclass) {			kprintf(" %s", pci_display_subclasses[j].name);			break;		    }		if (j == displaysubclasses)		    kprintf(" %s", pci_classes[i].name);		break;	    case PCI_CLASS_MULTIMEDIA:		for (j = 0; j < multimediasubclasses; j++)		    if (pci_multimedia_subclasses[j].id == subclass) {			kprintf(" %s", pci_multimedia_subclasses[j].name);			break;		    }		if (j == multimediasubclasses)		    kprintf(" %s", pci_classes[i].name);		break;	    case PCI_CLASS_MEMORY:		for (j = 0; j < memorysubclasses; j++)		    if (pci_memory_subclasses[j].id == subclass) {			kprintf(" %s", pci_memory_subclasses[j].name);			break;		    }		if (j == memorysubclasses)		    kprintf(" %s", pci_classes[i].name);		break;	    case PCI_CLASS_BRIDGE:		for (j = 0; j < bridgesubclasses; j++)		    if (pci_bridge_subclasses[j].id == subclass) {			kprintf(" %s", pci_bridge_subclasses[j].name);			break;		    }		kprintf(" %s", pci_classes[i].name);		break;	    case PCI_CLASS_SERIAL:		for (j = 0; j < serialsubclasses; j++)		    if (pci_serial_subclasses[j].id == subclass) {			kprintf(" %s", pci_serial_subclasses[j].name);			break;		    }		if (j == serialsubclasses)		    kprintf(" %s", pci_classes[i].name);		break;	    default:		kprintf(" %s", pci_classes[i].name);	    }	    break;	}    if (i == classes)	kprintf(" class code %02x", class);}#if _DEBUGstatic voiddump_pci_func(int slot, pci_func_t func){    kprintf("dump_pci_func: ");    kprintf("<%d,%d,%d> slot %d", func->bus, func->dev, func->func, slot);    kprintf(" vendor %04x device %04x iobase 0x%x irq %d\n",	    func->vendorid, func->deviceid, func->iobase, func->irq);}static voiddump_pcitab(){    int i;    for (i = 0; i < pcifuncs; i++)	dump_pci_func(i, &(pcitab[i]));}#endifstatic voidpci_scan_bus(int bus){    u_long dword, iobase;    u_short vendorid, deviceid;    u_char class, subclass, intrpin;    int dev, intrline, i;    for (dev = 0; dev < PCI_SLOTS; dev++) {	/* Function and vendor ids */	dword = pci_config_read(bus, dev, 0, PCI_CONFIG_VENDOR);	vendorid = dword & 0xffff;	deviceid = dword >> 16;	if (vendorid < 0xffff) {	    kprintf("pci%d: ", pcifunc);	    dump_pcivendor((u_short) vendorid);	    /* Function class code */	    dword = pci_config_read(bus, dev, 0, PCI_CONFIG_CLASS_REV);	    class = dword >> 24;	    subclass = (dword >> 16) & 0xff;	    dump_pciclass(class, subclass);	    /* Function iobase addresses */	    for (iobase = 0, i = 0; i < 6; i++) {		dword = pci_config_read(bus, dev, 0,					PCI_CONFIG_BASE_ADDR_0 + i);		if (dword & 0x01) {		    iobase = dword & 0xfffffffc;		    kprintf(" iobase 0x%x", iobase);		}	    }	    /* Function interrupt line */	    dword = pci_config_read(bus, dev, 0, PCI_CONFIG_INTR);	    intrpin = (u_char) (dword >> 8) & 0xff;	    intrline = dword & 0xff;	    if (intrpin > 0 && intrpin < 5 && intrline < 32)		kprintf(" irq %d", intrline);	    kprintf(" \n");	    /* Fill in pci device table entry */	    pcitab[pcifunc].bus = bus;	    pcitab[pcifunc].dev = dev;	    pcitab[pcifunc].func = 0;	    pcitab[pcifunc].vendorid = (u_short) vendorid;	    pcitab[pcifunc].deviceid = deviceid;	    pcitab[pcifunc].iobase = iobase;	    pcitab[pcifunc].irq = intrline;	    pcifunc++;	}    }}intpci_init(){    int devices[4], i;    for (pcifuncs = 0, i = 0; i < 4; i++) {	devices[i] = pci_device_count(i);	pcifuncs += devices[i];    }#if _DEBUG    kprintf("pci_init: %d pci functions\n", pcifuncs);#endif    pcitab = (pci_func_t) kmalloc(pcifuncs * sizeof(struct pci_func));    bzero(pcitab, pcifuncs * sizeof(struct pci_func));    for (i = 0; i < 4; i++)	if (devices[i] > 0)	    pci_scan_bus(i);#if _DEBUG    kprintf("pci_init: pci device table\n");    dump_pcitab();#endif    return 0;}pci_func_tpci_lookup(u_short vendorid, u_short deviceid){    int i;    for (i = 0; i < pcifuncs; i++)	if (pcitab[i].vendorid == vendorid && pcitab[i].deviceid == deviceid)	    break;    if (i == pcifuncs)	return NULL;    return &(pcitab[i]);}

⌨️ 快捷键说明

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