pci_machdep.c

来自「国产CPU-龙芯(loongson)BIOS源代码」· C语言 代码 · 共 361 行

C
361
字号
/*	$Id: pci_machdep.c,v 1.2 2003/12/10 09:23:35 wlin Exp $ *//* * Copyright (c) 2001 Opsycon AB  (www.opsycon.se) *  * 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 by Opsycon AB, Sweden. * 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. * */#include <sys/param.h>#include <sys/device.h>#include <sys/systm.h>#include <sys/malloc.h>#include <dev/pci/pcivar.h>#include <dev/pci/pcireg.h>#include <dev/pci/nppbreg.h>#include <machine/bus.h>#include "include/bonito.h"#include <pmon.h>extern void *pmalloc __P((size_t ));extern int _pciverbose;extern char hwethadr[6];struct pci_device *_pci_bus[16];int _max_pci_bus = 0;/* PCI mem regions in PCI space *//* soft versions of above */static pcireg_t pci_local_mem_pci_base;/********************************************************************//*initial PCI                                                       *//********************************************************************/int_pci_hwinit (initialise, iot, memt)	int initialise;	bus_space_tag_t iot;	bus_space_tag_t memt;{/*	pcireg_t stat;*/	struct pci_device *pd;	struct pci_bus *pb;	if (!initialise) {		return(0);	}	pci_local_mem_pci_base = PCI_LOCAL_MEM_PCI_BASE;	/*	 *  Allocate and initialize PCI bus heads.	 */	/*	 * PCI Bus 0	 */	pd = pmalloc(sizeof(struct pci_device));	pb = pmalloc(sizeof(struct pci_bus));	if(pd == NULL || pb == NULL) {		printf("pci: can't alloc memory. pci not initialized\n");		return(-1);	}	pd->pa.pa_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED;	pd->pa.pa_iot = pmalloc(sizeof(bus_space_tag_t));	pd->pa.pa_iot->bus_reverse = 1;	pd->pa.pa_iot->bus_base = BONITO_PCIIO_BASE_VA;	pd->pa.pa_memt = pmalloc(sizeof(bus_space_tag_t));	pd->pa.pa_memt->bus_reverse = 1;	pd->pa.pa_memt->bus_base = PCI_LOCAL_MEM_PCI_BASE;	pd->pa.pa_dmat = &bus_dmamap_tag;	pd->bridge.secbus = pb;	_pci_head = pd;	pb->minpcimemaddr  = PCI_MEM_SPACE_PCI_BASE+0x01000000;	pb->nextpcimemaddr = PCI_MEM_SPACE_PCI_BASE+BONITO_PCILO_SIZE;	pb->minpciioaddr  = PCI_IO_SPACE_BASE+0x000a000;	pb->nextpciioaddr =PCI_IO_SPACE_BASE+ BONITO_PCIIO_SIZE;	pb->pci_mem_base   = BONITO_PCILO_BASE_VA;	pb->pci_io_base    = BONITO_PCIIO_BASE_VA;	pb->max_lat = 255;	pb->fast_b2b = 1;	pb->prefetch = 1;	pb->bandwidth = 4000000;	pb->ndev = 1;	_pci_bushead = pb;	_pci_bus[_max_pci_bus++] = pd;		bus_dmamap_tag._dmamap_offs = 0;	/*set Bonito register*/	BONITO_PCIMAP =	    BONITO_PCIMAP_WIN(0, PCI_MEM_SPACE_PCI_BASE+0x00000000) |		    BONITO_PCIMAP_WIN(1, PCI_MEM_SPACE_PCI_BASE+0x04000000) |	    BONITO_PCIMAP_WIN(2, PCI_MEM_SPACE_PCI_BASE+0x08000000) |	    BONITO_PCIMAP_PCIMAP_2;		BONITO_PCIBASE0 = PCI_LOCAL_MEM_PCI_BASE;	BONITO_PCIBASE1 = PCI_LOCAL_MEM_ISA_BASE;	BONITO_PCIBASE2 = PCI_LOCAL_MEM_PCI_BASE + 0x10000000;	return(1);}/* * Called to reinitialise the bridge after we've scanned each PCI device * and know what is possible. We also set up the interrupt controller * routing and level control registers. */void_pci_hwreinit (void){}void_pci_flush (void){}/* *  Map the CPU virtual address of an area of local memory to a PCI *  address that can be used by a PCI bus master to access it. */vm_offset_t_pci_dmamap(va, len)	vm_offset_t va;	unsigned int len;{#if 0	return(VA_TO_PA(va) + bus_dmamap_tag._dmamap_offs);#endif	return(pci_local_mem_pci_base + VA_TO_PA (va));}#if 0/* *  Map the PCI address of an area of local memory to a CPU physical *  address. */vm_offset_t_pci_cpumap(pcia, len)	vm_offset_t pcia;	unsigned int len;{	return PA_TO_VA(pcia - pci_local_mem_pci_base);}#endif/* *  Make pci tag from bus, device and function data. */pcitag_t_pci_make_tag(bus, device, function)	int bus;	int device;	int function;{	pcitag_t tag;	tag = (bus << 16) | (device << 11) | (function << 8);	return(tag);}/* *  Break up a pci tag to bus, device function components. */void_pci_break_tag(tag, busp, devicep, functionp)	pcitag_t tag;	int *busp;	int *devicep;	int *functionp;{	if (busp) {		*busp = (tag >> 16) & 255;	}	if (devicep) {		*devicep = (tag >> 11) & 31;	}	if (functionp) {		*functionp = (tag >> 8) & 7;	}}int_pci_canscan (pcitag_t tag){	int bus, device, function;	_pci_break_tag (tag, &bus, &device, &function); 	if((bus == 0 || bus == 1) && device == 0) {		return(0);		/* Ignore the Discovery itself */	}	return (1);}pcireg_t_pci_conf_read(pcitag_t tag,int reg){	return _pci_conf_readn(tag,reg,4);}pcireg_t_pci_conf_readn(pcitag_t tag, int reg, int width){    u_int32_t addr, type;    pcireg_t data;    int bus, device, function;    if ((reg & (width-1)) || reg < 0 || reg >= 0x100) {	if (_pciverbose >= 1)	    _pci_tagprintf (tag, "_pci_conf_read: bad reg 0x%x\n", reg);	return ~0;    }    _pci_break_tag (tag, &bus, &device, &function);     if (bus == 0) {	/* Type 0 configuration on onboard PCI bus */	if (device > 20 || function > 7)	    return ~0;		/* device out of range */	addr = (1 << (device+11)) | (function << 8) | reg;	type = 0x00000;    }    else {	/* Type 1 configuration on offboard PCI bus */	if (bus > 255 || device > 31 || function > 7)	    return ~0;	/* device out of range */	addr = (bus << 16) | (device << 11) | (function << 8) | reg;	type = 0x10000;    }    /* clear aborts */    BONITO_PCICMD |= PCI_STATUS_MASTER_ABORT | PCI_STATUS_MASTER_TARGET_ABORT;    BONITO_PCIMAP_CFG = (addr >> 16) | type;    data = *(volatile pcireg_t *)PHYS_TO_UNCACHED(BONITO_PCICFG_BASE | (addr & 0xfffc));    if (BONITO_PCICMD & PCI_STATUS_MASTER_ABORT) {	BONITO_PCICMD |= PCI_STATUS_MASTER_ABORT;#if 0	if (_pciverbose >= 1)	    _pci_tagprintf (tag, "_pci_conf_read: reg=%x master abort\n", reg);#endif	return ~0;    }    if (BONITO_PCICMD & PCI_STATUS_MASTER_TARGET_ABORT) {	BONITO_PCICMD |= PCI_STATUS_MASTER_TARGET_ABORT;	if (_pciverbose >= 1)	    _pci_tagprintf (tag, "_pci_conf_read: target abort\n");	return ~0;    }    return data;}void_pci_conf_write(pcitag_t tag, int reg, pcireg_t data){	return _pci_conf_writen(tag,reg,data,4);}void_pci_conf_writen(pcitag_t tag, int reg, pcireg_t data,int width){    u_int32_t addr, type;    int bus, device, function;    if ((reg &(width-1)) || reg < 0 || reg >= 0x100) {	if (_pciverbose >= 1)	    _pci_tagprintf (tag, "_pci_conf_write: bad reg %x\n", reg);	return;    }    _pci_break_tag (tag, &bus, &device, &function);    if (bus == 0) {	/* Type 0 configuration on onboard PCI bus */	if (device > 20 || function > 7)	    return;		/* device out of range */	addr = (1 << (device+11)) | (function << 8) | reg;	type = 0x00000;    }    else {	/* Type 1 configuration on offboard PCI bus */	if (bus > 255 || device > 31 || function > 7)	    return;	/* device out of range */	addr = (bus << 16) | (device << 11) | (function << 8) | reg;	type = 0x10000;    }    /* clear aborts */    BONITO_PCICMD |= PCI_STATUS_MASTER_ABORT | PCI_STATUS_MASTER_TARGET_ABORT;    BONITO_PCIMAP_CFG = (addr >> 16);    *(volatile pcireg_t *)PHYS_TO_UNCACHED(BONITO_PCICFG_BASE | (addr & 0xfffc)) = data;    if (BONITO_PCICMD & PCI_STATUS_MASTER_ABORT) {	BONITO_PCICMD |= PCI_STATUS_MASTER_ABORT;	if (_pciverbose >= 1)	    _pci_tagprintf (tag, "_pci_conf_write: master abort\n");    }    if (BONITO_PCICMD & PCI_STATUS_MASTER_TARGET_ABORT) {	BONITO_PCICMD |= PCI_STATUS_MASTER_TARGET_ABORT;	if (_pciverbose >= 1)	    _pci_tagprintf (tag, "_pci_conf_write: target abort\n");    }}voidpci_sync_cache(p, adr, size, rw)	void *p;	vm_offset_t adr;	size_t size;	int rw;{	CPU_IOFlushDCache(adr, size, rw);}

⌨️ 快捷键说明

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