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

📄 pciconf.c

📁 国产CPU-龙芯(loongson)BIOS源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/*	$Id: pciconf.c,v 1.2 2004/05/17 10:39:22 wlin Exp $ *//* * Copyright (c) 2000 Opsycon AB  (www.opsycon.se) * Copyright (c) 2000 Rtmx, Inc   (www.rtmx.com) * Copyright (c) 2001 IP Unplugged AB  (www.ipunplugged.com) *  * 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. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed for Rtmx, Inc by *	Opsycon Open System Consulting AB, Sweden. *      This product includes software developed for IP Inplugged AB, by *      Patrik Lindergren. * 4. 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. * *//* *  This work is derivate work created from code written at Algorithmics UK. *  It was part of PMON which is not copyrighted. After modifications and *  extensions it is now released under standard BSD copyright. *//* * pciconf.c: generic PCI bus configuration */#include <sys/param.h>#include <stdarg.h>#include <progress.h>#include <sys/device.h>#include <sys/malloc.h>#include <machine/bus.h>#include <include/pmon_target.h>#include "pcivar.h"#include "pcireg.h"#define PCIVERBOSE 5#ifdef PCIVERBOSE#include "pcidevs.h"#endif#undef PCI_ALLOC_UPWARDS#include <sys/systm.h>#include <pmon.h>extern char *getenv __P((const char *));extern long atol __P((const char *));extern void *pmalloc __P((size_t ));extern void pfree __P((void * ));static int _pci_roundup(int , int );static int _pci_getIntRouting(struct pci_device *);static int _pci_setupIntRouting(struct pci_device *);static void _pci_scan_dev(struct pci_device *dev, int bus, int device, int initialise);static void _insertsort_window(struct pci_win **, struct pci_win *);static void _pci_device_insert(struct pci_device *parent, struct pci_device *device);static pcireg_t _pci_allocate_mem __P((struct pci_device *, vm_size_t));static pcireg_t _pci_allocate_io __P((struct pci_device *, vm_size_t));static void _setup_pcibuses(int );static void _pci_bus_insert(struct pci_bus *);#ifndef MIN#define MIN(a,b)	((a) < (b) ? (a) : (b))#endif#ifndef MAX#define MAX(a,b)	((a) > (b) ? (a) : (b))#endif#define PRINTF printf#define VPRINTF vprintf#ifndef PCIVERBOSE#define _PCIVERBOSE 0#else#define _PCIVERBOSE PCIVERBOSE#endifpcitag_t have_vga = 0;			/* Have tag if VGA board found */int monarch_mode = 1;			/* Default as master on the bus! */int pci_roots;				/* How many pci roots to init */int _pciverbose = _PCIVERBOSE;static int _pci_nbus = 8;		/* Allow for eight roots */struct tgt_bus_space def_bus_iot;		/* Default bus tags */struct tgt_bus_space def_bus_memt;		/* Default bus tags */struct pci_device *_pci_head;struct pci_bus *_pci_bushead;struct pci_intline_routing *_pci_inthead;struct pci_device *vga_dev = NULL;static voidprint_bdf (int bus, int device, int function){    PRINTF ("PCI");    PRINTF (" bus %d", bus);    if (device >= 0)	PRINTF (" slot %d", device);    if (function >= 0)	PRINTF ("/%d", function);    PRINTF (": ");}void_pci_bdfprintf (int bus, int device, int function, const char *fmt, ...){    va_list arg;    print_bdf (bus, device, function);    va_start(arg, fmt);    VPRINTF (fmt, arg);    va_end(arg);}void_pci_tagprintf (pcitag_t tag, const char *fmt, ...){    va_list arg;    int bus, device, function;    _pci_break_tag (tag, &bus, &device, &function);     print_bdf (bus, device, function);    va_start(arg, fmt);    VPRINTF (fmt, arg);    va_end(arg);}/* * Scan each PCI device on the system and record its configuration * requirements. */static void_pci_query_dev_func (struct pci_device *dev, pcitag_t tag, int initialise){	pcireg_t id, class;	pcireg_t old, mask;	pcireg_t stat;	pcireg_t bparam;	int reg;	struct pci_bus *pb;	struct pci_device *pd;	unsigned int x;	int bus, device, function;    	class = _pci_conf_read(tag, PCI_CLASS_REG);	id = _pci_conf_read(tag, PCI_ID_REG);	if (_pciverbose) {		int supported;		char devinfo[256];		_pci_devinfo(id, class, &supported, devinfo);		_pci_tagprintf (tag, "%s\n", devinfo);	}	pd = pmalloc(sizeof(struct pci_device));	if(pd == NULL) {		PRINTF ("pci: can't alloc memory for device\n");		return;	}        	_pci_break_tag (tag, &bus, &device, &function);	pd->pa.pa_bus = bus;	pd->pa.pa_device = device;	pd->pa.pa_function = function;	pd->pa.pa_tag = tag;	pd->pa.pa_id = id;	pd->pa.pa_class = class;	pd->pa.pa_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;	pd->pa.pa_iot = dev->pa.pa_iot;	pd->pa.pa_memt = dev->pa.pa_memt;	pd->pa.pa_dmat = dev->pa.pa_dmat;	pd->parent = dev;	pd->pcibus = dev->bridge.secbus;	pb = pd->pcibus;	_pci_device_insert(dev, pd);	/*	 * Calculated Interrupt routing	 */	_pci_setupIntRouting(pd);	/*	 *  Shut off device if we initialize from non reset.	 */	stat = _pci_conf_read(tag, PCI_COMMAND_STATUS_REG);	stat &= ~(PCI_COMMAND_MASTER_ENABLE |		  PCI_COMMAND_IO_ENABLE |		  PCI_COMMAND_MEM_ENABLE);	_pci_conf_write(tag, PCI_COMMAND_STATUS_REG, stat);	pd->stat = stat;    	/* do all devices support fast back-to-back */	if ((stat & PCI_STATUS_BACKTOBACK_SUPPORT) == 0) {		pb->fast_b2b = 0;		/* no, sorry */	}	/* do all devices run at 66 MHz */	if ((stat & PCI_STATUS_66MHZ_SUPPORT) == 0) {		pb->freq66 = 0; 		/* no, sorry */	}	/* find slowest devsel */	x = stat & PCI_STATUS_DEVSEL_MASK;	if (x > pb->devsel) {		pb->devsel = x;	}	/* Funny looking code which deals with any 32bit read only cfg... */	bparam = _pci_conf_read(tag, (PCI_MINGNT & ~0x3));	pd->min_gnt = 0xff & (bparam >> ((PCI_MINGNT & 3) * 8));	bparam = _pci_conf_read(tag, (PCI_MAXLAT & ~0x3));	pd->max_lat = 0xff & (bparam >> ((PCI_MAXLAT & 3) * 8));	if (pd->min_gnt != 0 || pd->max_lat != 0) {		/* find largest minimum grant time of all devices */		if (pd->min_gnt != 0 && pd->min_gnt > pb->min_gnt) {			pb->min_gnt = pd->min_gnt;		}			/* find smallest maximum latency time of all devices */		if (pd->max_lat != 0 && pd->max_lat < pb->max_lat) {			    pb->max_lat = pd->max_lat;		}			/* subtract our min on-bus time per second from bus bandwidth */		if (initialise) {			pb->bandwidth -= pd->min_gnt * 4000000 / (pd->min_gnt + pd->max_lat);		}	}	/* Map interrupt to interrupt line (software function only) */	bparam = _pci_conf_read(tag, PCI_INTERRUPT_REG);	bparam &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);	bparam |= ((_pci_getIntRouting(pd) & 0xff) << PCI_INTERRUPT_LINE_SHIFT);	_pci_conf_write(tag, PCI_INTERRUPT_REG, bparam);	/*	 * Check to see if device is a PCI Bridge	 */	if (PCI_ISCLASS(class, PCI_CLASS_BRIDGE, PCI_SUBCLASS_BRIDGE_PCI)) {		struct pci_device *pcidev;		struct pci_win *pm_mem = NULL;		struct pci_win *pm_io = NULL;		struct pci_win *pm;		pcireg_t tmp;		pd->bridge.pribus_num = bus;		pd->bridge.secbus_num =  ++_pci_nbus;		/* Set it temperary to same as secondary bus number */		pd->bridge.subbus_num =  pd->bridge.secbus_num;		tmp = _pci_conf_read(tag, PCI_PRIBUS_1);		tmp &= 0xff000000;		tmp |= pd->bridge.pribus_num;		tmp |= pd->bridge.secbus_num << 8;		tmp |= pd->bridge.subbus_num << 16;		_pci_conf_write(tag, PCI_PRIBUS_1, tmp);		/* Update sub bus number */		for(pcidev = dev; pcidev != NULL; pcidev = pcidev->parent) {			pcidev->bridge.subbus_num = pd->bridge.secbus_num;			tmp = _pci_conf_read(pcidev->pa.pa_tag, PCI_PRIBUS_1);			tmp &= 0xff00ffff;			tmp |= pd->bridge.secbus_num << 16;			_pci_conf_write(pcidev->pa.pa_tag, PCI_PRIBUS_1, tmp);		}		pd->bridge.secbus = pmalloc(sizeof(struct pci_bus));		if(pd->bridge.secbus == NULL) {			PRINTF ("pci: can't alloc memory for new pci bus\n");			return;		}        		pd->bridge.secbus->max_lat = 255;		pd->bridge.secbus->fast_b2b = 1;		pd->bridge.secbus->prefetch = 1;		pd->bridge.secbus->freq66 = 1;		pd->bridge.secbus->bandwidth = 4000000;		pd->bridge.secbus->ndev = 1;		pd->bridge.secbus->bus = pd->bridge.secbus_num;		_pci_bus_insert(pd->bridge.secbus);		/* Scan secondary bus of the bridge */		_pci_scan_dev(pd, pd->bridge.secbus_num, 0, initialise);		/*		 * Sum up the address space needed by secondary side of bridge		 */		/* Sum up I/O Space needed */		for(pm = pd->bridge.iospace; pm != NULL; pm = pm->next) {			if(pm_io == NULL) {				pm_io = pmalloc(sizeof(struct pci_win));				if(pm_io == NULL) {					PRINTF ("pci: can't alloc memory for pci memory window\n");					return;				}				pm_io->device = pd;				pm_io->reg = PCI_IOBASEL_1;				pm_io->flags = PCI_MAPREG_TYPE_IO;			}			pm_io->size += pm->size;		}		/* Sum up Memory Space needed */		for(pm = pd->bridge.memspace; pm != NULL; pm = pm->next) {			if(pm_mem == NULL) {				pm_mem = pmalloc(sizeof(struct pci_win));				if(pm_mem == NULL) {					PRINTF ("pci: can't alloc memory for pci memory window\n");					return;				}            				pm_mem->device = pd;				pm_mem->reg = PCI_MEMBASE_1; 				pm_mem->flags = PCI_MAPREG_MEM_TYPE_32BIT;			}			pm_mem->size += pm->size;		}        		/* Round to minimum granularity requierd for a bridge */		pm_io->size = _pci_roundup(pm_io->size, 0x1000);		pm_mem->size = _pci_roundup(pm_mem->size, 0x100000);		if(pm_io) {			_insertsort_window(&pd->parent->bridge.iospace, pm_io);		}		if(pm_mem) {			_insertsort_window(&pd->parent->bridge.memspace,pm_mem);		}	}	else if (PCI_ISCLASS(class, PCI_CLASS_MASS_STORAGE,		    PCI_SUBCLASS_MASS_STORAGE_IDE) &&		dev->bridge.secbus->minpciioaddr == 0) {        /*	 * There is no need to setup memory regions for IDE storage devices	 * but only if PCI/ISA I/O space is accessables	 */		return;	} else {		int skipnext = 0;		for (reg = PCI_MAPREG_START; reg < PCI_MAPREG_END; reg += 4) {			struct pci_win *pm;			if (skipnext) {				skipnext = 0;				continue;			}			old = _pci_conf_read(tag, reg);			_pci_conf_write(tag, reg, 0xfffffffe);			mask = _pci_conf_read(tag, reg);			_pci_conf_write(tag, reg, old);			if (mask == 0 || mask == 0xffffffff) {				break;			}			if (_pciverbose >= 3) {				_pci_tagprintf (tag, "reg 0x%x = 0x%x\n",							reg, mask);			}			if (PCI_MAPREG_TYPE(mask) == PCI_MAPREG_TYPE_IO) {				mask |= 0xffff0000; /* must be ones */				pm = pmalloc(sizeof(struct pci_win));				if(pm == NULL) {					PRINTF ("pci: can't alloc memory for pci memory window\n");					return;				}            				pm->device = pd;				pm->reg = reg;				pm->flags = PCI_MAPREG_TYPE_IO;				pm->size = -(PCI_MAPREG_IO_ADDR(mask));				_insertsort_window(&pd->parent->bridge.iospace, pm);			}			else {				switch (PCI_MAPREG_MEM_TYPE(mask)) {				case PCI_MAPREG_MEM_TYPE_32BIT:				case PCI_MAPREG_MEM_TYPE_32BIT_1M:					break;				case PCI_MAPREG_MEM_TYPE_64BIT:					_pci_conf_write(tag, reg + 4, 0x0);					skipnext = 1;					break;				default:					_pci_tagprintf (tag, "reserved mapping type 0x%x\n",					      PCI_MAPREG_MEM_TYPE(mask));					continue;				}				if  (!PCI_MAPREG_MEM_PREFETCHABLE(mask)) {					pb->prefetch = 0;				}				pm = pmalloc(sizeof(struct pci_win));				if(pm == NULL) {					PRINTF ("pci: can't alloc memory for pci memory window\n");					return;				}				pm->device = pd;				pm->reg = reg;				pm->flags = PCI_MAPREG_MEM_TYPE_32BIT;				pm->size = -(PCI_MAPREG_MEM_ADDR(mask));				_insertsort_window(&pd->parent->bridge.memspace, pm);			}		}		/* Finally check for Expansion ROM */		reg = PCI_MAPREG_ROM;		old = _pci_conf_read(tag, reg);		_pci_conf_write(tag, reg, 0xfffffffe);		mask = _pci_conf_read(tag, reg);		_pci_conf_write(tag, reg, old);		if (mask != 0 && mask != 0xffffffff) {			struct pci_win *pm;			if (_pciverbose >= 3) {				_pci_tagprintf (tag, "reg 0x%x = 0x%x\n", reg, mask);			}			pm = pmalloc(sizeof(struct pci_win));			if(pm == NULL) {				PRINTF ("pci: can't alloc memory for pci memory window\n");				return;			}			pm->device = pd;			pm->reg = reg;			pm->size = -(PCI_MAPREG_ROM_ADDR(mask));			_insertsort_window(&pd->parent->bridge.memspace, pm);		}	}}static int_pci_roundup(value, round)    int value;    int round;{    int result = (value / round) * round;    if(value % round)        result += round;    return(result);}static void_pci_bus_insert(bus)    struct pci_bus *bus;{    struct pci_bus *pb;    for(pb = _pci_bushead; pb->next != NULL; pb = pb->next)        ;;    pb->next = bus;

⌨️ 快捷键说明

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