📄 pci_machdep.c
字号:
/* $Id: pci_machdep.c,v 1.4 2002/11/17 16:30:48 patrik 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 Unplugged 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. * */#include <sys/param.h>#include <sys/device.h>#include <sys/systm.h>#include <dev/pci/pcivar.h>#include <dev/pci/pcireg.h>#include <machine/pio.h>#include <include/palomarii.h>#include <pmon/dev/cpc700.h>#include <pmon.h>#include <stdlib.h>#ifndef VA_TO_PA#define VA_TO_PA(x) (x)#endif#ifndef PA_TO_VA#define PA_TO_VA(x) (x)#endif#define _256MB 0x10000000 /* One BAT reg mapping limit *//* PCI i/o regions in PCI space */#define PCI_IO_SPACE_PCI_BASE 0x00000000/* PCI mem regions in PCI space */#define PCI_MEM_SPACE_PCI_BASE 0x00000000 /* PCI Mem accessed from PCI */#define PCI_LOCAL_MEM_PCI_BASE 0x00000000 /* CPU Mem accessed from PCI */#define PCI_LOCAL_MEM_ISA_BASE 0x00000000 /* ISA Mem accessed from PCI *//* soft versions of above */static pcireg_t pci_mem_space_pci_base = PCI_MEM_SPACE_PCI_BASE;static pcireg_t pci_local_mem_pci_base = PCI_LOCAL_MEM_PCI_BASE;static pcireg_t pci_local_mem_isa_base = PCI_LOCAL_MEM_ISA_BASE;extern int _pciverbose;extern int monarch_mode;extern char hwethadr[6];/* * Called to initialise the bridge at the beginning of time */int_pci_hwinit(initialise, iot, memt) int initialise; bus_space_tag_t iot; bus_space_tag_t memt;{ struct pci_device *pd; struct pci_bus *pb; iot->bus_base = PA_TO_VA(CPC700_PCI_IO_BASE); iot->bus_reverse = 1; memt->bus_base = PA_TO_VA(CPC700_PCI_MEM_BASE); memt->bus_reverse = 1; pci_local_mem_pci_base = PCI_LOCAL_MEM_PCI_BASE; pci_local_mem_isa_base = PCI_LOCAL_MEM_ISA_BASE; pci_mem_space_pci_base = PCI_MEM_SPACE_PCI_BASE; if (!initialise) { return(0); } monarch_mode = 1; /* * Initialize PCI Head device (Northbridge). */ pd = malloc(sizeof(struct pci_device)); if(pd == NULL) { /* Can't Alloc memory */ printf("pci: can't alloc memory for northbridge\n"); return(-1); } bzero((void *)pd, sizeof(struct pci_device)); pd->pa.pa_flags = PCI_FLAGS_IO_ENABLED | PCI_FLAGS_MEM_ENABLED; pd->pa.pa_iot = iot; pd->pa.pa_memt = memt; _pci_head = pd; pd->bridge.secbus = malloc(sizeof(struct pci_bus)); if(pd->bridge.secbus == NULL) { /* Can't Alloc memory */ printf("pci: can't alloc memory for new pci bus\n"); return(-1); } bzero((void *)pd->bridge.secbus, sizeof(struct pci_bus)); pb = pd->bridge.secbus; pb->max_lat = 255; pb->fast_b2b = 1; pb->prefetch = 1; pb->bandwidth = 4000000; pb->ndev = 1; _pci_bushead = pb; /* point to start and end of region (leaving bottom 16M for ISA) */ pb->minpcimemaddr = PCI_MEM_SPACE_PCI_BASE + 0x1000000; pb->nextpcimemaddr = PCI_MEM_SPACE_PCI_BASE + _256MB; /* * leave 512M at beginning of PCI i/o space for ISA bridge (it * actually uses only 64K, but this is needed for a ISA DMA * h/w fix which needs a higher address bit to spot ISA cycles). */ pb->minpciioaddr = PCI_IO_SPACE_PCI_BASE + 0x800000; pb->nextpciioaddr = PCI_IO_SPACE_PCI_BASE + 0x3000000;#ifdef POCONO /* Setup predefined interrupt routing list */ InitInterruptRouting();#endif /* POCONO */ return(1);}/* * Called to reinitialise the bridge after we've scanned each PCI device * and know what is possible. */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;{ return(pci_local_mem_pci_base + VA_TO_PA (va));}/* * 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(pcia - pci_local_mem_pci_base);}/* * Map the CPU virtual address of an area of local memory to an ISA * address that can be used by a ISA bus master to access it. */vm_offset_t_isa_dmamap(va, len) vm_offset_t va; unsigned int len;{ unsigned long pa = VA_TO_PA (va); /* restrict ISA DMA access to bottom 8/16MB of local memory */ if (pa + len > 0x1000000 - pci_local_mem_isa_base) { return (vm_offset_t)-1; } return(pci_local_mem_isa_base + pa);}/* * Map the ISA address of an area of local memory to a CPU physical * address. */vm_offset_t_isa_cpumap(pcia, len) vm_offset_t pcia; unsigned int len;{ return(pcia - pci_local_mem_isa_base);}int_pci_canscan (pcitag_t tag){ pcitag_t dev = pci_make_tag(0, 0, 0); if(dev == tag) return(0); else return (1);}/* * Get contents of PCI Mapping register and do any machine * dependent mapping setup. */int_pci_map_port(tag, reg, port) pcitag_t tag; int reg; unsigned int *port;{ pcireg_t address; if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) { if (_pciverbose >= 1) { _pci_tagprintf(tag, "_pci_map_port: bad request\r\n"); } return -1; } address = _pci_conf_read(tag, reg); if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_IO) { if (_pciverbose >= 1) { _pci_tagprintf (tag, "_pci_map_port: attempt to i/o map a memory region\r\n"); } return(-1); } *port = (address & PCI_MAPREG_IO_ADDR_MASK) - PCI_IO_SPACE_PCI_BASE; return(0);}int_pci_map_io(tag, reg, vap, pap) pcitag_t tag; int reg; vm_offset_t *vap; vm_offset_t *pap;{ pcireg_t address; vm_offset_t pa; if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) { if (_pciverbose >= 1) { _pci_tagprintf(tag, "_pci_map_io: bad request\r\n"); } return(-1); } address = _pci_conf_read(tag, reg); if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_IO) { if (_pciverbose >= 1) { _pci_tagprintf (tag, "_pci_map_io: attempt to i/o map a memory region\r\n"); } return(-1); } pa = (address & PCI_MAPREG_IO_ADDR_MASK) - PCI_IO_SPACE_PCI_BASE; *pap = pa; *vap = (vm_offset_t) PA_TO_VA (CPC700_PCI_IO_BASE + pa); if (_pciverbose >= 3) { _pci_tagprintf(tag, "_pci_map_io: mapping i/o at virtual %08x, physical %08x\n", *vap, *pap); } return(0);}int_pci_map_mem(tag, reg, vap, pap) pcitag_t tag; int reg; vm_offset_t *vap; vm_offset_t *pap;{ pcireg_t address; vm_offset_t pa; if (reg == PCI_MAPREG_ROM) { /* expansion ROM */ address = _pci_conf_read(tag, reg); if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_ROM) { _pci_tagprintf (tag, "_pci_map_mem: attempt to map missing rom\r\n"); return(-1); } pa = PCI_MAPREG_ROM_ADDR(address); } else { if (reg < PCI_MAPREG_START || reg >= PCI_MAPREG_END || (reg & 3)) { if (_pciverbose >= 1) { _pci_tagprintf(tag, "_pci_map_mem: bad request\r\n"); } return(-1); } address = _pci_conf_read(tag, reg); if (PCI_MAPREG_TYPE(address) != PCI_MAPREG_TYPE_MEM) { if (_pciverbose >= 1) { _pci_tagprintf(tag, "pci_map_mem: attempt to memory map an I/O region\r\n"); } return(-1); } switch (PCI_MAPREG_MEM_TYPE(address)) { case PCI_MAPREG_MEM_TYPE_32BIT: case PCI_MAPREG_MEM_TYPE_32BIT_1M: break; case PCI_MAPREG_MEM_TYPE_64BIT: if (_pciverbose >= 1) { _pci_tagprintf (tag, "_pci_map_mem: attempt to map 64-bit region\r\n"); } return(-1); default: if (_pciverbose >= 1) { _pci_tagprintf (tag, "_pci_map_mem: reserved mapping type\r\n"); } return(-1); } pa = address & PCI_MAPREG_MEM_ADDR_MASK; } /* * Physical address returned should be what the PCI bus master uses * when accessing the PCI bus mem space. Therefore don't remove the * PCI bus offset. Hope this doesn't break something. */#if 0 pa -= pci_mem_space_pci_base; *pap = pa;#else *pap = pa; pa -= pci_mem_space_pci_base;#endif *pap = pa; *vap = (vm_offset_t) PA_TO_VA (CPC700_PCI_MEM_BASE + pa); if (_pciverbose >= 3) { _pci_tagprintf (tag, "_pci_map_mem: mapping memory at virtual 0x%x, physical 0x%x\r\n", *vap, *pap); } return(0);}void *_pci_map_int(tag, level, func, arg) pcitag_t tag; int level; int (*func) __P((void *)); void *arg;{ pcireg_t data; int pin, bus, device; data = _pci_conf_read(tag, PCI_INTERRUPT_REG); pin = PCI_INTERRUPT_PIN(data); if (pin == 0) { /* No IRQ used. */ return NULL; } if (pin > 4) { if (_pciverbose >= 1) { _pci_tagprintf (tag, "_pci_map_int: bad interrupt pin %d\r\n", pin); } return(NULL); } _pci_break_tag (tag, &bus, &device, NULL); if (bus != 0 || device > 5) { return(NULL); } /* XXX need to work this out based on device number etc. */ _pci_tagprintf(tag, "_pci_map_int: attempt to map device %d pin %c\n", device, '@' + pin); return(NULL);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -