pcisupport.c

来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 1,383 行 · 第 1/3 页

C
1,383
字号
/******************************************************************************  $Id: pcisupport.c,v 1.86.2.6 1999/05/10 13:33:08 peter Exp $****  Device driver for DEC/INTEL PCI chipsets.****  FreeBSD****-------------------------------------------------------------------------****  Written for FreeBSD by**	wolf@cologne.de 	Wolfgang Stanglmeier**	se@mi.Uni-Koeln.de	Stefan Esser****-------------------------------------------------------------------------**** Copyright (c) 1994,1995 Stefan Esser.  All rights reserved.**** Redistribution and use in source and binary forms, with or without** modification, are permitted provided that the following conditions** are met:** 1. Redistributions of source code must retain the above copyright**    notice, this list of conditions and the following disclaimer.** 2. Redistributions in binary form must reproduce the above copyright**    notice, this list of conditions and the following disclaimer in the**    documentation and/or other materials provided with the distribution.** 3. The name of the author may not be used to endorse or promote products**    derived from this software without specific prior written permission.**** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.******************************************************************************/#include "opt_pci.h"#include "opt_smp.h"#include <sys/param.h>#include <sys/systm.h>#include <sys/malloc.h>#include <sys/kernel.h>#include <pci/pcivar.h>#include <pci/pcireg.h>#include <vm/vm.h>#include <vm/vm_object.h>#include <vm/pmap.h>/*---------------------------------------------------------****	Intel chipsets for 486 / Pentium processor****---------------------------------------------------------*/static	const char*	chipset_probe (pcici_t tag, pcidi_t type);static	void	chipset_attach(pcici_t tag, int unit);static	u_long	chipset_count;struct pci_device chipset_device = {	"chip",	chipset_probe,	chipset_attach,	&chipset_count,	NULL};/*DATA_SET (pcidevice_set, chipset_device);*/struct condmsg {    unsigned char	port;    unsigned char	mask;    unsigned char	value;    char		flags;    const char		*text;};static char*generic_pci_bridge (pcici_t tag){    char *descr, tmpbuf[120];    unsigned classreg = pci_conf_read (tag, PCI_CLASS_REG);    if ((classreg & PCI_CLASS_MASK) == PCI_CLASS_BRIDGE) {	unsigned id = pci_conf_read (tag, PCI_ID_REG);	switch (classreg >> 16 & 0xff) {		case 0:	strcpy(tmpbuf, "Host to PCI"); break;		case 1:	strcpy(tmpbuf, "PCI to ISA"); break;		case 2:	strcpy(tmpbuf, "PCI to EISA"); break;		case 4:	strcpy(tmpbuf, "PCI to PCI"); break;		case 5:	strcpy(tmpbuf, "PCI to PCMCIA"); break;		case 7:	strcpy(tmpbuf, "PCI to CardBus"); break;		default: 			snprintf(tmpbuf, sizeof(tmpbuf),			    "PCI to 0x%x", classreg>>16 & 0xff); 			break;	}	snprintf(tmpbuf+strlen(tmpbuf), sizeof(tmpbuf)-strlen(tmpbuf),	    " bridge (vendor=%04x device=%04x)",	    id & 0xffff, (id >> 16) & 0xffff);	descr = malloc (strlen(tmpbuf) +1, M_DEVBUF, M_WAITOK);	strcpy(descr, tmpbuf);	return descr;    }    return 0;}/* * XXX Both fixbushigh_orion() and fixbushigh_i1225() are bogus in that way, * that they store the highest bus number to scan in this device's config  * data, though it is about PCI buses attached to the CPU independently! * The same goes for fixbushigh_450nx. */static voidfixbushigh_orion(pcici_t tag){	tag->secondarybus = pci_cfgread(tag, 0x4a, 1);	tag->subordinatebus = pci_cfgread(tag, 0x4b, 1);}static voidfixbushigh_i1225(pcici_t tag){	int sublementarybus;	sublementarybus = pci_cfgread(tag, 0x41, 1);	if (sublementarybus != 0xff)		tag->secondarybus = tag->subordinatebus = sublementarybus +1;}/* * This reads the PCI config space for the 82451NX MIOC in the 450NX * chipset to determine the PCI bus configuration. * * Assuming the BIOS has set up the MIOC properly, this will correctly * report the number of PCI busses in the system. * * A small problem is that the Host to PCI bridge control is in the MIOC, * while the host-pci bridges are separate PCI devices.  So it really * isn't easily possible to set up the subordinatebus mappings as the * 82454NX PCI expander bridges are probed, although that makes the * most sense. */static voidfixbushigh_450nx(pcici_t tag){	int subordinatebus;	unsigned long devmap;	/*	 * Read the DEVMAP field, so we know which fields to check.	 * If the Host-PCI bridge isn't marked as present by the BIOS,	 * we have to assume it doesn't exist.	 * If this doesn't find all the PCI busses, complain to the	 * BIOS vendor.  There is nothing more we can do.	 */	devmap = pci_cfgread(tag, 0xd6, 2) & 0x3c;	if (!devmap)		panic("450NX MIOC: No host to PCI bridges marked present.\n");	/*	 * Since the buses are configured in order, we just have to	 * find the highest bus, and use those numbers.	 */	if (devmap & 0x20) {			/* B1 */		subordinatebus = pci_cfgread(tag, 0xd5, 1);	} else if (devmap & 0x10) {		/* A1 */		subordinatebus = pci_cfgread(tag, 0xd4, 1);	} else if (devmap & 0x8) {		/* B0 */		subordinatebus = pci_cfgread(tag, 0xd2, 1);	} else /* if (devmap & 0x4) */ {	/* A0 */		subordinatebus = pci_cfgread(tag, 0xd1, 1);	}	if (subordinatebus == 255) {		printf("fixbushigh_450nx: bogus highest PCI bus %d",		       subordinatebus);#ifdef NBUS		subordinatebus = NBUS - 2;#else		subordinatebus = 10;#endif		printf(", reduced to %d\n", subordinatebus);	}			if (bootverbose)		printf("fixbushigh_450nx: subordinatebus is %d\n",			subordinatebus);	tag->secondarybus = tag->subordinatebus = subordinatebus;}static voidfixbushigh_Ross(pcici_t tag){	int secondarybus;	/* just guessing the secondary bus register number ... */	secondarybus = pci_cfgread(tag, 0x45, 1);	if (secondarybus != 0)		tag->secondarybus = tag->subordinatebus = secondarybus + 1;}static voidfixwsc_natoma(pcici_t tag){	int pmccfg;	pmccfg = pci_cfgread(tag, 0x50, 2);#if defined(SMP)	if (pmccfg & 0x8000) {		printf("Correcting Natoma config for SMP\n");		pmccfg &= ~0x8000;		pci_cfgwrite(tag, 0x50, 2, pmccfg);	}#else	if ((pmccfg & 0x8000) == 0) {		printf("Correcting Natoma config for non-SMP\n");		pmccfg |= 0x8000;		pci_cfgwrite(tag, 0x50, 2, pmccfg);	}#endif}		static const char*chipset_probe (pcici_t tag, pcidi_t type){	unsigned	rev;	char		*descr;	switch (type) {	/* Intel -- vendor 0x8086 */	case 0x00088086:		/* Silently ignore this one! What is it, anyway ??? */		return ("");	case 0x04868086:		return ("Intel 82425EX PCI system controller");	case 0x04848086:		rev = (unsigned) pci_conf_read (tag, PCI_CLASS_REG) & 0xff;		if (rev == 3)		    return ("Intel 82378ZB PCI to ISA bridge");		return ("Intel 82378IB PCI to ISA bridge");	case 0x04838086:		return ("Intel 82424ZX (Saturn) cache DRAM controller");	case 0x04828086:		return ("Intel 82375EB PCI-EISA bridge");	case 0x04a38086:		rev = (unsigned) pci_conf_read (tag, PCI_CLASS_REG) & 0xff;		if (rev == 16 || rev == 17)		    return ("Intel 82434NX (Neptune) PCI cache memory controller");		return ("Intel 82434LX (Mercury) PCI cache memory controller");	case 0x12258086:		fixbushigh_i1225(tag);		return ("Intel 824?? host to PCI bridge");	case 0x122d8086:		return ("Intel 82437FX PCI cache memory controller");	case 0x122e8086:		return ("Intel 82371FB PCI to ISA bridge");	case 0x12348086:		return ("Intel 82371MX mobile PCI I/O IDE accelerator (MPIIX)");	case 0x12358086:		return ("Intel 82437MX mobile PCI cache memory controller");	case 0x12508086:		return ("Intel 82439HX PCI cache memory controller");	case 0x70008086:		return ("Intel 82371SB PCI to ISA bridge");	case 0x70308086:		return ("Intel 82437VX PCI cache memory controller");	case 0x71008086:		return ("Intel 82439TX System Controller (MTXC)");	case 0x71108086:		return ("Intel 82371AB PCI to ISA bridge");	case 0x71138086:		return ("Intel 82371AB Power management controller");	case 0x71908086:		return ("Intel 82443BX host to PCI bridge");	case 0x71918086:		return ("Intel 82443BX host to AGP bridge");	case 0x71928086:		return ("Intel 82443BX host to PCI bridge (AGP disabled)");  	case 0x71a08086:  		return ("Intel 82443GX host to PCI bridge");  	case 0x71a18086:  		return ("Intel 82443GX host to AGP bridge");  	case 0x71a28086:  		return ("Intel 82443GX host to PCI bridge (AGP disabled)");	case 0x12378086:		fixwsc_natoma(tag);		return ("Intel 82440FX (Natoma) PCI and memory controller");	case 0x84c48086:		fixbushigh_orion(tag);		return ("Intel 82454KX/GX (Orion) host to PCI bridge");	case 0x84c58086:		return ("Intel 82453KX/GX (Orion) PCI memory controller");	case 0x84ca8086:		fixbushigh_450nx(tag);		return ("Intel 82451NX Memory and I/O Controller");	case 0x84cb8086:		return ("Intel 82454NX PCI Expander Bridge");	case 0x124b8086:		return ("Intel 82380FB mobile PCI to PCI bridge");	/* SiS -- vendor 0x1039 */	case 0x04961039:		return ("SiS 85c496");	case 0x04061039:		return ("SiS 85c501");	case 0x00081039:		return ("SiS 85c503");	case 0x06011039:		return ("SiS 85c601");	case 0x55911039:		return ("SiS 5591 host to PCI bridge");	case 0x00011039:		return ("SiS 5591 host to AGP bridge");		/* VLSI -- vendor 0x1004 */	case 0x00051004:		return ("VLSI 82C592 Host to PCI bridge");	case 0x00061004:		return ("VLSI 82C593 PCI to ISA bridge");	case 0x01011004:		return ("VLSI 82C532 Eagle II Peripheral Controller");	case 0x01021004:		return ("VLSI 82C534 Eagle II PCI Bus bridge");	case 0x01031004:		return ("VLSI 82C538 Eagle II PCI Docking bridge");	case 0x01041004:		return ("VLSI 82C535 Eagle II System Controller");	case 0x01051004:		return ("VLSI 82C147 IrDA Controller");	/* VIA Technologies -- vendor 0x1106 	 * Note that the old Apollo Master chipset is not in here, as VIA	 * does not seem to have any docs on their website for it, and I do	 * not have a Master board in my posession. -LC	 */	case 0x05851106:		return("VIA 82C585 (Apollo VP1/VPX) system controller");	case 0x05861106: /* south bridge section -- IDE is covered in ide_pci.c */		return("VIA 82C586 PCI-ISA bridge");	case 0x05951106:	case 0x15951106:		return("VIA 82C595 (Apollo VP2) system controller");	case 0x05971106:		return("VIA 82C597 (Apollo VP3) system controller");	/* XXX need info on the MVP3 -- any takers? */	case 0x30401106:		return("VIA 82C586B ACPI interface");	/* XXX Here is MVP3, I got the datasheet but NO M/B to test it  */	/* totally. Please let me know if anything wrong.            -F */	case 0x05981106:		return("VIA 82C598MVP (Apollo MVP3) host bridge");	case 0x85981106:		return("VIA 82C598MVP (Apollo MVP3) PCI-PCI bridge");	/* AcerLabs -- vendor 0x10b9 */	/* Funny : The datasheet told me vendor id is "10b8",sub-vendor */	/* id is '10b9" but the register always shows "10b9". -Foxfair  */	case 0x154110b9:		return("AcerLabs M1541 (Aladdin-V) PCI host bridge");	case 0x153310b9:		return("AcerLabs M1533 portable PCI-ISA bridge");	case 0x154310b9:		return("AcerLabs M1543 desktop PCI-ISA bridge");	case 0x524710b9:		return("AcerLabs M5247 PCI-PCI(AGP Supported) bridge");	case 0x524310b9:/* 5243 seems like 5247, need more info to divide*/		return("AcerLabs M5243 PCI-PCI bridge");	/* Cyrix -- vendor 0x1078 */	case 0x00001078:		return ("Cyrix Cx5510 PCI-ISA bridge");	case 0x01001078:		return ("Cyrix Cx5530 PCI-ISA bridge");	/* NEC -- vendor 0x1033 */	case 0x00011033:		return ("NEC 0001 PCI to PC-98 C-bus bridge");	case 0x00021033:		return ("NEC 0002 PCI to PC-98 local bus bridge");	case 0x00161033:		return ("NEC 0016 PCI to PC-98 local bus bridge");	case 0x002c1033:		return ("NEC 002C PCI to PC-98 C-bus bridge");	case 0x003b1033:		return ("NEC 003B PCI to PC-98 C-bus bridge");	/* Ross (?) -- vendor 0x1166 */	case 0x00051166:		fixbushigh_Ross(tag);		return ("Ross (?) host to PCI bridge");	/* Others */	case 0x00221014:		return ("IBM 82351 PCI-PCI bridge");	case 0x00011011:		return ("DEC 21050 PCI-PCI bridge");	};	if (descr = generic_pci_bridge(tag))		return descr;	return NULL;}#ifndef PCI_QUIET#define	M_XX 0	/* end of list */#define M_EQ 1  /* mask and return true if equal */#define M_NE 2  /* mask and return true if not equal */#define M_TR 3  /* don't read config, always true */#define M_EN 4	/* mask and print "enabled" if true, "disabled" if false */#define M_NN 5	/* opposite sense of M_EN */static const struct condmsg conf82425ex[] ={    { 0x00, 0x00, 0x00, M_TR, "\tClock " },    { 0x50, 0x06, 0x00, M_EQ, "25" },    { 0x50, 0x06, 0x02, M_EQ, "33" },    { 0x50, 0x04, 0x04, M_EQ, "??", },    { 0x00, 0x00, 0x00, M_TR, "MHz, L1 Cache " },    { 0x50, 0x01, 0x00, M_EQ, "Disabled\n" },    { 0x50, 0x09, 0x01, M_EQ, "Write-through\n" },    { 0x50, 0x09, 0x09, M_EQ, "Write-back\n" },    { 0x00, 0x00, 0x00, M_TR, "\tL2 Cache " },    { 0x52, 0x07, 0x00, M_EQ, "Disabled" },    { 0x52, 0x0f, 0x01, M_EQ, "64KB Write-through" },    { 0x52, 0x0f, 0x02, M_EQ, "128KB Write-through" },    { 0x52, 0x0f, 0x03, M_EQ, "256KB Write-through" },    { 0x52, 0x0f, 0x04, M_EQ, "512KB Write-through" },    { 0x52, 0x0f, 0x01, M_EQ, "64KB Write-back" },    { 0x52, 0x0f, 0x02, M_EQ, "128KB Write-back" },    { 0x52, 0x0f, 0x03, M_EQ, "256KB Write-back" },    { 0x52, 0x0f, 0x04, M_EQ, "512KB Write-back" },    { 0x53, 0x01, 0x00, M_EQ, ", 3-" },    { 0x53, 0x01, 0x01, M_EQ, ", 2-" },    { 0x53, 0x06, 0x00, M_EQ, "3-3-3" },    { 0x53, 0x06, 0x02, M_EQ, "2-2-2" },    { 0x53, 0x06, 0x04, M_EQ, "1-1-1" },    { 0x53, 0x06, 0x06, M_EQ, "?-?-?" },    { 0x53, 0x18, 0x00, M_EQ, "/4-2-2-2\n" },    { 0x53, 0x18, 0x08, M_EQ, "/3-2-2-2\n" },    { 0x53, 0x18, 0x10, M_EQ, "/?-?-?-?\n" },    { 0x53, 0x18, 0x18, M_EQ, "/2-1-1-1\n" },    { 0x56, 0x00, 0x00, M_TR, "\tDRAM: " },

⌨️ 快捷键说明

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