diff --git a/sys/alpha/alpha/cpuconf.c b/sys/alpha/alpha/cpuconf.c index a9304fd555ad..0a6f3d9989af 100644 --- a/sys/alpha/alpha/cpuconf.c +++ b/sys/alpha/alpha/cpuconf.c @@ -116,6 +116,12 @@ extern void dec_1000a_init __P((int)); #define dec_1000a_init platform_not_configured #endif +#ifdef DEC_2100_A500 +extern void dec_2100_a500_init __P((int)); +#else +#define dec_2100_a500_init platform_not_configured +#endif + struct cpuinit cpuinit[] = { cpu_notsupp("???"), /* 0: ??? */ cpu_notsupp("ST_ADU"), /* 1: ST_ADU */ @@ -126,7 +132,7 @@ struct cpuinit cpuinit[] = { cpu_notsupp("ST_DEC_2000_300"), /* 6: ST_DEC_2000_300 */ cpu_init(dec_3000_300_init,"DEC_3000_300"), /* 7: ST_DEC_3000_300 */ cpu_init(avalon_a12_init,"ST_AVALON_A12"), /* 8: ST_AVALON_A12 */ - cpu_notsupp("ST_DEC_2100_A500"), /* 9: ST_DEC_2100_A500 */ + cpu_init(dec_2100_a500_init, "ST_DEC_2100_A500"), /* 9: ST_DEC_2100_A500 */ cpu_notsupp("ST_DEC_APXVME_64"), /* 10: ST_DEC_APXVME_64 */ cpu_init(dec_axppci_33_init,"DEC_AXPPCI_33"),/* 11: ST_DEC_AXPPCI_33 */ cpu_init(dec_kn8ae_init,"DEC_KN8AE"), /* 12: ST_DEC_21000 */ @@ -141,7 +147,7 @@ struct cpuinit cpuinit[] = { cpu_notsupp("ST_ALPHABOOK1"), /* 21: ST_ALPHABOOK1 */ cpu_init(dec_kn300_init,"DEC_KN300"), /* 22: ST_DEC_4100 */ cpu_notsupp("ST_DEC_EV45_PBP"), /* 23: ST_DEC_EV45_PBP */ - cpu_notsupp("ST_DEC_2100A_A500"), /* 24: ST_DEC_2100A_A500 */ + cpu_init(dec_2100_a500_init, "ST_DEC_2100A_A500"), /* 24: ST_DEC_2100A_A500 */ cpu_notsupp("???"), /* 25: ??? */ cpu_init(dec_eb164_init,"DEC_EB164"), /* 26: ST_EB164 */ cpu_init(dec_1000a_init,"ST_DEC_1000A"), /* 27: ST_DEC_1000A */ diff --git a/sys/alpha/alpha/dec_2100_a500.c b/sys/alpha/alpha/dec_2100_a500.c new file mode 100644 index 000000000000..0297e6036bdd --- /dev/null +++ b/sys/alpha/alpha/dec_2100_a500.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2000 Andrew Gallatin + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. + * + * $FreeBSD$ + */ + +#include "opt_ddb.h" + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "sio.h" +#include "sc.h" +#ifndef CONSPEED +#define CONSPEED TTYDEF_SPEED +#endif +static int comcnrate = CONSPEED; + +void dec_2100_a500_init __P((int)); +static void dec_2100_a500_cons_init __P((void)); +static void dec_2100_a500_intr_map __P((void *)); +static void dec_2100_a500_intr_init __P((void )); + +extern int siocnattach __P((int, int)); +extern int siogdbattach __P((int, int)); +extern int sccnattach __P((void)); + +extern vm_offset_t t2_csr_base; + +void +dec_2100_a500_init(cputype) +{ + + /* + * see if we're a Sable or a Lynx + */ + if (cputype == ST_DEC_2100_A500) { + t2_csr_base = SABLE_BASE; + platform.family = "DEC AlphaServer 2100"; + } else if (cputype == ST_DEC_2100A_A500) { + t2_csr_base = LYNX_BASE; + platform.family = "DEC AlphaServer 2100A"; + } else { + t2_csr_base = SABLE_BASE; + platform.family = "DEC AlphaServer 2100?????"; + } + + + if ((platform.model = alpha_dsr_sysname()) == NULL) { + platform.model = alpha_unknown_sysname(); + } + + platform.iobus = "t2"; + platform.cons_init = dec_2100_a500_cons_init; + platform.pci_intr_map = dec_2100_a500_intr_map; + platform.pci_intr_init = dec_2100_a500_intr_init; + + + t2_init(); +} + +extern int comconsole; /* XXX for forcing comconsole when srm serial console is used */ + +static void +dec_2100_a500_cons_init() +{ + struct ctb *ctb; + t2_init(); + +#ifdef DDB + siogdbattach(0x2f8, 9600); +#endif + ctb = (struct ctb *)(((caddr_t)hwrpb) + hwrpb->rpb_ctb_off); + + switch (ctb->ctb_term_type) { + case 2: + /* serial console ... */ + /* XXX */ + /* + * Delay to allow PROM putchars to complete. + * FIFO depth * character time, + * character time = (1000000 / (defaultrate / 10)) + */ + DELAY(160000000 / comcnrate); + /* + * force a comconsole on com1 if the SRM has a serial console + */ + comconsole = 0; + if (siocnattach(0x3f8, comcnrate)) + panic("can't init serial console"); + break; + + case 3: + /* display console ... */ + /* XXX */ +#if NSC > 0 + sccnattach(); +#else + panic("not configured to use display && keyboard console"); +#endif + break; + + default: + printf("ctb->ctb_term_type = 0x%lx\n", ctb->ctb_term_type); + panic("consinit: unknown console type"); + } +} + +void +dec_2100_a500_intr_map(void *arg) +{ + pcicfgregs *cfg = (pcicfgregs *)arg; + + cfg->intline += 32; +} + +void +dec_2100_a500_intr_init(void ) +{ + outb(SLAVE0_ICU, 0); + outb(SLAVE1_ICU, 0); + outb(SLAVE2_ICU, 0); + outb(MASTER_ICU, 0x44); +} diff --git a/sys/alpha/conf/GENERIC b/sys/alpha/conf/GENERIC index 1917eb14f8d3..069d631ef771 100644 --- a/sys/alpha/conf/GENERIC +++ b/sys/alpha/conf/GENERIC @@ -34,6 +34,7 @@ options DEC_AXPPCI_33 # UDB, Multia, AXPpci33, Noname options DEC_EB164 # EB164, PC164, PC164LX, PC164SX options DEC_EB64PLUS # EB64+, Aspen Alpine, etc options DEC_2100_A50 # AlphaStation 200, 250, 255, 400 +options DEC_2100_A500 # AlphaServer 2000, 2100, 2100A options DEC_KN20AA # AlphaStation 500, 600 options DEC_ST550 # Personal Workstation 433, 500, 600 options DEC_ST6600 # xp1000, dp264, ds20, ds10, family diff --git a/sys/alpha/conf/NOTES b/sys/alpha/conf/NOTES index 1917eb14f8d3..069d631ef771 100644 --- a/sys/alpha/conf/NOTES +++ b/sys/alpha/conf/NOTES @@ -34,6 +34,7 @@ options DEC_AXPPCI_33 # UDB, Multia, AXPpci33, Noname options DEC_EB164 # EB164, PC164, PC164LX, PC164SX options DEC_EB64PLUS # EB64+, Aspen Alpine, etc options DEC_2100_A50 # AlphaStation 200, 250, 255, 400 +options DEC_2100_A500 # AlphaServer 2000, 2100, 2100A options DEC_KN20AA # AlphaStation 500, 600 options DEC_ST550 # Personal Workstation 433, 500, 600 options DEC_ST6600 # xp1000, dp264, ds20, ds10, family diff --git a/sys/alpha/pci/t2.c b/sys/alpha/pci/t2.c new file mode 100644 index 000000000000..554fc4849d6b --- /dev/null +++ b/sys/alpha/pci/t2.c @@ -0,0 +1,658 @@ +/* + * Copyright (c) 2000 Andrew Gallatin & Doug Rabson + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. + * + * $FreeBSD$ + */ + +/* + * T2 CBUS to PCI bridge + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define KV(pa) ALPHA_PHYS_TO_K0SEG(pa + t2_csr_base) + +vm_offset_t t2_csr_base = 0UL; + +static devclass_t t2_devclass; +static device_t t2_0; /* XXX only one for now */ + +struct t2_softc { + int junk; +}; + +#define T2_SOFTC(dev) (struct t2_softc*) device_get_softc(dev) + +static alpha_chipset_inb_t t2_inb; +static alpha_chipset_inw_t t2_inw; +static alpha_chipset_inl_t t2_inl; +static alpha_chipset_outb_t t2_outb; +static alpha_chipset_outw_t t2_outw; +static alpha_chipset_outl_t t2_outl; +static alpha_chipset_readb_t t2_readb; +static alpha_chipset_readw_t t2_readw; +static alpha_chipset_readl_t t2_readl; +static alpha_chipset_writeb_t t2_writeb; +static alpha_chipset_writew_t t2_writew; +static alpha_chipset_writel_t t2_writel; +static alpha_chipset_maxdevs_t t2_maxdevs; +static alpha_chipset_cfgreadb_t t2_cfgreadb; +static alpha_chipset_cfgreadw_t t2_cfgreadw; +static alpha_chipset_cfgreadl_t t2_cfgreadl; +static alpha_chipset_cfgwriteb_t t2_cfgwriteb; +static alpha_chipset_cfgwritew_t t2_cfgwritew; +static alpha_chipset_cfgwritel_t t2_cfgwritel; +static alpha_chipset_addrcvt_t t2_cvt_dense; +static alpha_chipset_read_hae_t t2_read_hae; +static alpha_chipset_write_hae_t t2_write_hae; + +static alpha_chipset_t t2_chipset = { + t2_inb, + t2_inw, + t2_inl, + t2_outb, + t2_outw, + t2_outl, + t2_readb, + t2_readw, + t2_readl, + t2_writeb, + t2_writew, + t2_writel, + t2_maxdevs, + t2_cfgreadb, + t2_cfgreadw, + t2_cfgreadl, + t2_cfgwriteb, + t2_cfgwritew, + t2_cfgwritel, + t2_cvt_dense, + NULL, + t2_read_hae, + t2_write_hae, +}; + +static u_int8_t +t2_inb(u_int32_t port) +{ + alpha_mb(); + return SPARSE_READ_BYTE(KV(T2_PCI_SIO), port); +} + +static u_int16_t +t2_inw(u_int32_t port) +{ + alpha_mb(); + return SPARSE_READ_WORD(KV(T2_PCI_SIO), port); +} + +static u_int32_t +t2_inl(u_int32_t port) +{ + alpha_mb(); + return SPARSE_READ_LONG(KV(T2_PCI_SIO), port); +} + +static void +t2_outb(u_int32_t port, u_int8_t data) +{ + SPARSE_WRITE_BYTE(KV(T2_PCI_SIO), port, data); + alpha_wmb(); +} + +static void +t2_outw(u_int32_t port, u_int16_t data) +{ + SPARSE_WRITE_WORD(KV(T2_PCI_SIO), port, data); + alpha_wmb(); +} + +static void +t2_outl(u_int32_t port, u_int32_t data) +{ + SPARSE_WRITE_LONG(KV(T2_PCI_SIO), port, data); + alpha_wmb(); +} + +static u_int32_t t2_hae_mem; + +#define REG1 (1UL << 24) + +static __inline void +t2_set_hae_mem(u_int32_t *pa) +{ + int s; + u_int32_t msb; + + if(*pa >= REG1){ + msb = *pa & 0xf8000000; + *pa -= msb; + msb >>= 27; /* t2 puts high bits in the bottom of the register */ + s = splhigh(); + if (msb != t2_hae_mem) { + t2_hae_mem = msb; + REGVAL(T2_HAE0_1) = t2_hae_mem; + alpha_mb(); + t2_hae_mem = REGVAL(T2_HAE0_1); + } + splx(s); + } +} + +static u_int8_t +t2_readb(u_int32_t pa) +{ + alpha_mb(); + t2_set_hae_mem(&pa); + return SPARSE_READ_BYTE(KV(T2_PCI_SPARSE), pa); +} + +static u_int16_t +t2_readw(u_int32_t pa) +{ + alpha_mb(); + t2_set_hae_mem(&pa); + return SPARSE_READ_WORD(KV(T2_PCI_SPARSE), pa); +} + +static u_int32_t +t2_readl(u_int32_t pa) +{ + alpha_mb(); + t2_set_hae_mem(&pa); + return SPARSE_READ_LONG(KV(T2_PCI_SPARSE), pa); +} + +static void +t2_writeb(u_int32_t pa, u_int8_t data) +{ + t2_set_hae_mem(&pa); + SPARSE_WRITE_BYTE(KV(T2_PCI_SPARSE), pa, data); + alpha_wmb(); +} + +static void +t2_writew(u_int32_t pa, u_int16_t data) +{ + t2_set_hae_mem(&pa); + SPARSE_WRITE_WORD(KV(T2_PCI_SPARSE), pa, data); + alpha_wmb(); +} + +static void +t2_writel(u_int32_t pa, u_int32_t data) +{ + t2_set_hae_mem(&pa); + SPARSE_WRITE_LONG(KV(T2_PCI_SPARSE), pa, data); + alpha_wmb(); +} + +static int +t2_maxdevs(u_int b) +{ + return 12; /* XXX */ +} + + + +/* XXX config space access? */ + +static vm_offset_t +t2_cvt_dense(vm_offset_t addr) +{ + addr &= 0xffffffffUL; + return (addr | T2_PCI_DENSE); + +} + +static u_int64_t +t2_read_hae(void) +{ + return t2_hae_mem << 27; +} + +static void +t2_write_hae(u_int64_t hae) +{ + u_int32_t pa = hae; + t2_set_hae_mem(&pa); +} + +#define T2_CFGOFF(b, s, f, r) \ + ((b) ? (((b) << 16) | ((s) << 11) | ((f) << 8) | (r)) \ + : ((1 << ((s) + 11)) | ((f) << 8) | (r))) + +#define T2_TYPE1_SETUP(b,s,old_hae3) if((b)) { \ + do { \ + (s) = splhigh(); \ + (old_hae3) = REGVAL(T2_HAE0_3); \ + alpha_mb(); \ + REGVAL(T2_HAE0_3) = (old_hae3) | (1<<30); \ + alpha_mb(); \ + } while(0); \ +} + +#define T2_TYPE1_TEARDOWN(b,s,old_hae3) if((b)) { \ + do { \ + alpha_mb(); \ + REGVAL(T2_HAE0_3) = (old_hae3); \ + alpha_mb(); \ + splx((s)); \ + } while(0); \ +} + +#define SWIZ_CFGREAD(b, s, f, r, width, type) \ + type val = ~0; \ + int ipl = 0; \ + u_int32_t old_hae3 = 0; \ + vm_offset_t off = T2_CFGOFF(b, s, f, r); \ + vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(T2_PCI_CONF), off); \ + alpha_mb(); \ + T2_TYPE1_SETUP(b,ipl,old_hae3); \ + if (!badaddr((caddr_t)kv, sizeof(type))) { \ + val = SPARSE_##width##_EXTRACT(off, SPARSE_READ(kv)); \ + } \ + T2_TYPE1_TEARDOWN(b,ipl,old_hae3); \ + return val; + +#define SWIZ_CFGWRITE(b, s, f, r, data, width, type) \ + int ipl = 0; \ + u_int32_t old_hae3 = 0; \ + vm_offset_t off = T2_CFGOFF(b, s, f, r); \ + vm_offset_t kv = SPARSE_##width##_ADDRESS(KV(T2_PCI_CONF), off); \ + alpha_mb(); \ + T2_TYPE1_SETUP(b,ipl,old_hae3); \ + if (!badaddr((caddr_t)kv, sizeof(type))) { \ + SPARSE_WRITE(kv, SPARSE_##width##_INSERT(off, data)); \ + alpha_wmb(); \ + } \ + T2_TYPE1_TEARDOWN(b,ipl,old_hae3); \ + return; + +static u_int8_t +t2_cfgreadb(u_int h, u_int b, u_int s, u_int f, u_int r) +{ + SWIZ_CFGREAD(b, s, f, r, BYTE, u_int8_t); +} + +static u_int16_t +t2_cfgreadw(u_int h, u_int b, u_int s, u_int f, u_int r) +{ + SWIZ_CFGREAD(b, s, f, r, WORD, u_int16_t); +} + +static u_int32_t +t2_cfgreadl(u_int h, u_int b, u_int s, u_int f, u_int r) +{ + SWIZ_CFGREAD(b, s, f, r, LONG, u_int32_t); +} + +static void +t2_cfgwriteb(u_int h, u_int b, u_int s, u_int f, u_int r, u_int8_t data) +{ + SWIZ_CFGWRITE(b, s, f, r, data, BYTE, u_int8_t); +} + +static void +t2_cfgwritew(u_int h, u_int b, u_int s, u_int f, u_int r, u_int16_t data) +{ + SWIZ_CFGWRITE(b, s, f, r, data, WORD, u_int16_t); +} + +static void +t2_cfgwritel(u_int h, u_int b, u_int s, u_int f, u_int r, u_int32_t data) +{ + SWIZ_CFGWRITE(b, s, f, r, data, LONG, u_int32_t); +} + +static int t2_probe(device_t dev); +static int t2_attach(device_t dev); +static int t2_setup_intr(device_t dev, device_t child, + struct resource *irq, int flags, + void *intr, void *arg, void **cookiep); +static int t2_teardown_intr(device_t dev, device_t child, + struct resource *irq, void *cookie); +static void +t2_dispatch_intr(void *frame, unsigned long vector); +static void +t2_machine_check(unsigned long mces, struct trapframe *framep, + unsigned long vector, unsigned long param); + + +static device_method_t t2_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, t2_probe), + DEVMETHOD(device_attach, t2_attach), + + /* Bus interface */ + DEVMETHOD(bus_alloc_resource, pci_alloc_resource), + DEVMETHOD(bus_release_resource, pci_release_resource), + DEVMETHOD(bus_activate_resource, pci_activate_resource), + DEVMETHOD(bus_deactivate_resource, pci_deactivate_resource), + DEVMETHOD(bus_setup_intr, t2_setup_intr), + DEVMETHOD(bus_teardown_intr, t2_teardown_intr), + + { 0, 0 } +}; + +static driver_t t2_driver = { + "t2", + t2_methods, + sizeof(struct t2_softc), +}; + + +#define T2_SGMAP_BASE (8*1024*1024) +#define T2_SGMAP_SIZE (8*1024*1024) + +static void +t2_sgmap_invalidate(void) +{ + u_int64_t val; + + alpha_mb(); + val = REGVAL64(T2_IOCSR); + val |= T2_IOCSRL_ITLB; + REGVAL64(T2_IOCSR) = val; + alpha_mb(); + alpha_mb(); + val = REGVAL64(T2_IOCSR); + val &= ~T2_IOCSRL_ITLB; + REGVAL64(T2_IOCSR) = val; + alpha_mb(); + alpha_mb(); +} + +static void +t2_sgmap_map(void *arg, vm_offset_t ba, vm_offset_t pa) +{ + u_int64_t *sgtable = arg; + int index = alpha_btop(ba - T2_SGMAP_BASE); + + if (pa) { + if (pa > (1L<<32)) + panic("t2_sgmap_map: can't map address 0x%lx", pa); + sgtable[index] = ((pa >> 13) << 1) | 1; + } else { + sgtable[index] = 0; + } + alpha_mb(); + t2_sgmap_invalidate(); +} + + +static void +t2_init_sgmap(void) +{ + void *sgtable; + + /* + * First setup Window 2 to map 8Mb to 16Mb with an + * sgmap. Allocate the map aligned to a 32 boundary. + * + * bits 31..20 of WBASE represent the pci start address + * (in units of 1Mb), and bits 11..0 represent the pci + * end address + */ + REGVAL(T2_WBASE2) = T2_WSIZE_8M|T2_WINDOW_ENABLE|T2_WINDOW_SG + | ((T2_SGMAP_BASE >> 20) << 20) + | ((T2_SGMAP_BASE + T2_SGMAP_SIZE) >> 20); + REGVAL(T2_WMASK2) = T2_WMASK_8M; + alpha_mb(); + + sgtable = contigmalloc(8192, M_DEVBUF, M_NOWAIT, + 0, (1L<<34), + 32*1024, (1L<<34)); + if (!sgtable) + panic("t2_init_sgmap: can't allocate page table"); + + REGVAL(T2_TBASE2) = + (pmap_kextract((vm_offset_t) sgtable) >> T2_TBASE_SHIFT); + + chipset.sgmap = sgmap_map_create(T2_SGMAP_BASE, + T2_SGMAP_BASE + T2_SGMAP_SIZE, + t2_sgmap_map, sgtable); +} + +/* + * Perform basic chipset init/fixup. Called by various early + * consumers to ensure that the system will work before the + * bus methods are invoked. + * + */ + +void +t2_init() +{ + static int initted = 0; + + if (initted) return; + initted = 1; + + chipset = t2_chipset; +} + +static int +t2_probe(device_t dev) +{ + device_t child; + + if (t2_0) + return ENXIO; + t2_0 = dev; + device_set_desc(dev, "T2 Core Logic chipset"); + + pci_init_resources(); + + /* + * initialize the DMA windows + */ + + REGVAL(T2_WBASE1) = T2_WSIZE_1G|T2_WINDOW_ENABLE|T2_WINDOW_DIRECT|0x7ff; + REGVAL(T2_WMASK1) = T2_WMASK_1G; + REGVAL(T2_TBASE1) = 0; + + REGVAL(T2_WBASE2) = 0x0; + + + /* + * enable the PCI "Hole" for ISA devices which use memory in + * the 512k - 1MB range + */ + REGVAL(T2_HBASE) = 1 << 13; + t2_init_sgmap(); + + + /* initialize the HAEs */ + REGVAL(T2_HAE0_1) = 0x0; + alpha_mb(); + REGVAL(T2_HAE0_2) = 0x0; + alpha_mb(); + REGVAL(T2_HAE0_3) = 0x0; + alpha_mb(); + + child = device_add_child(dev, "pcib", 0); + device_set_ivars(child, 0); + + return 0; +} + +static int +t2_attach(device_t dev) +{ + t2_init(); + + platform.mcheck_handler = t2_machine_check; + set_iointr(t2_dispatch_intr); + platform.isa_setup_intr = t2_setup_intr; + platform.isa_teardown_intr = t2_teardown_intr; + + snprintf(chipset_type, sizeof(chipset_type), "t2"); + + bus_generic_attach(dev); + + return 0; +} + +/* + * magical mystery table partly obtained from Linux + * at least some of their values for PCI masks + * were incorrect, and I've filled in my own extrapolations + * XXX this needs more testers + */ + +unsigned long t2_shadow_mask = -1L; +static const char irq_to_mask[40] = { + -1, 6, -1, 8, 15, 12, 7, 9, /* ISA 0-7 */ + -1, 16, 17, 18, 3, -1, 21, 22, /* ISA 8-15 */ + -1, -1, -1, -1, -1, -1, -1, -1, /* ?? EISA XXX */ + -1, -1, -1, -1, -1, -1, -1, -1, /* ?? EISA XXX */ + 0, 1, 2, 3, 4, 5, 6, 7 /* PCI 0-7 XXX */ +}; + +static int +t2_setup_intr(device_t dev, device_t child, + struct resource *irq, int flags, + void *intr, void *arg, void **cookiep) +{ + int error, mask, vector; + + mask = irq_to_mask[irq->r_start]; + vector = 0x800 + (mask << 4); + + error = rman_activate_resource(irq); + if (error) + return error; + + error = alpha_setup_intr(vector, + intr, arg, cookiep, + &intrcnt[irq->r_start]); + if (error) + return error; + + /* Enable interrupt */ + + t2_shadow_mask &= ~(1UL << mask); + + if (mask <= 7) + outb(SLAVE0_ICU, t2_shadow_mask); + else if (mask <= 15) + outb(SLAVE1_ICU, t2_shadow_mask >> 8); + else + outb(SLAVE2_ICU, t2_shadow_mask >> 16); + + device_printf(child, "interrupting at T2 irq %d\n", + (int) irq->r_start); + + return 0; +} + +static int +t2_teardown_intr(device_t dev, device_t child, + struct resource *irq, void *cookie) +{ + int mask; + + mask = irq_to_mask[irq->r_start]; + + /* Disable interrupt */ + + t2_shadow_mask |= (1UL << mask); + + if (mask <= 7) + outb(SLAVE0_ICU, t2_shadow_mask); + else if (mask <= 15) + outb(SLAVE1_ICU, t2_shadow_mask >> 8); + else + outb(SLAVE2_ICU, t2_shadow_mask >> 16); + + alpha_teardown_intr(cookie); + return rman_deactivate_resource(irq); +} + +static void +t2_ack_intr(unsigned long vector) +{ + int mask = (vector - 0x800) >> 4; + + switch (mask) { + case 0 ... 7: + outb(SLAVE0_ICU-1, (0xe0 | (mask))); + outb(MASTER_ICU-1, (0xe0 | 1)); + break; + case 8 ... 15: + outb(SLAVE1_ICU-1, (0xe0 | (mask - 8))); + outb(MASTER_ICU-1, (0xe0 | 3)); + break; + case 16 ... 24: + outb(SLAVE2_ICU-1, (0xe0 | (mask - 16))); + outb(MASTER_ICU-1, (0xe0 | 4)); + break; + } +} + + +static void +t2_dispatch_intr(void *frame, unsigned long vector) +{ + alpha_dispatch_intr(frame, vector); + t2_ack_intr(vector); +} + +static void +t2_machine_check(unsigned long mces, struct trapframe *framep, + unsigned long vector, unsigned long param) +{ + int expected; + + expected = mc_expected; + machine_check(mces, framep, vector, param); + /* for some reason the alpha_pal_wrmces() doesn't clear all + pending machine checks & we may take another */ + mc_expected = expected; +} + +DRIVER_MODULE(t2, root, t2_driver, t2_devclass, 0, 0); diff --git a/sys/alpha/pci/t2_pci.c b/sys/alpha/pci/t2_pci.c new file mode 100644 index 000000000000..2213bb386030 --- /dev/null +++ b/sys/alpha/pci/t2_pci.c @@ -0,0 +1,87 @@ +/*- + * Copyright (c) 2000 Doug Rabson + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPELCAL, 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. + * + * $FreeBSD$ + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +static devclass_t pcib_devclass; + +static int +t2_pcib_probe(device_t dev) +{ + device_t child; + + device_set_desc(dev, "T2 PCI host bus adapter"); + + child = device_add_child(dev, "pci", 0); + device_set_ivars(child, 0); + + return 0; +} + +static int +t2_pcib_read_ivar(device_t dev, device_t child, int which, u_long *result) +{ + if (which == PCIB_IVAR_HOSE) { + *result = 0; + return 0; + } + return ENOENT; +} + +static device_method_t t2_pcib_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, t2_pcib_probe), + DEVMETHOD(device_attach, bus_generic_attach), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_read_ivar, t2_pcib_read_ivar), + DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + { 0, 0 } +}; + +static driver_t t2_pcib_driver = { + "pcib", + t2_pcib_methods, + 1, +}; + +DRIVER_MODULE(pcib, t2, t2_pcib_driver, pcib_devclass, 0, 0); diff --git a/sys/alpha/pci/t2reg.h b/sys/alpha/pci/t2reg.h new file mode 100644 index 000000000000..339c4e1b8118 --- /dev/null +++ b/sys/alpha/pci/t2reg.h @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2000 Doug Rabson & Andrew Gallatin + * 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``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 OR CONTRIBUTORS 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. + * + * $FreeBSD$ + */ + + + +/* + * Registers in the T2 CBUS-to-PCI bridge as used in the SABLE + * systems. + */ + +#define REGVAL(r) (*(volatile int32_t *) \ + ALPHA_PHYS_TO_K0SEG(r + t2_csr_base)) +#define REGVAL64(r) (*(volatile int64_t *) \ + ALPHA_PHYS_TO_K0SEG(r + t2_csr_base)) + +#define SABLE_BASE 0x0UL /* offset of SABLE CSRs */ +#define LYNX_BASE 0x8000000000UL /* offset of LYNX CSRs */ + +#define CBUS_BASE 0x380000000 /* CBUS CSRs */ +#define T2_PCI_SIO 0x3a0000000 /* PCI sparse I/O space */ +#define T2_PCI_CONF 0x390000000 /* PCI configuration space */ +#define T2_PCI_SPARSE 0x200000000 /* PCI sparse memory space */ +#define T2_PCI_DENSE 0x3c0000000 /* PCI dense memory space */ + +#define T2_IOCSR (CBUS_BASE + 0xe000000) + /* Low word */ +#define T2_IOCSRL_EL 0x00000002UL /* loopback enable */ +#define T2_IOCSRL_ESMV 0x00000004UL /* enable state machine visibility */ +#define T2_IOCSRL_PDBP 0x00000008UL /* PCI drive bad parity */ +#define T2_IOCSRL_SLOT0 0x00000030UL /* PCI slot 0 present bits */ +#define T2_IOCSRL_PINT 0x00000040UL /* PCI interrupt */ +#define T2_IOCSRL_ENTLBEC 0x00000080UL /* enable TLB error check */ +#define T2_IOCSRL_ENCCDMA 0x00000100UL /* enable CXACK for DMA */ +#define T2_IOCSRL_ENXXCHG 0x00000400UL /* enable exclusive exchange for EV5 */ +#define T2_IOCSRL_CAWWP0 0x00001000UL /* CBUS command/address write wrong parity 0 */ +#define T2_IOCSRL_CAWWP2 0x00002000UL /* CBUS command/address write wrong parity 2 */ +#define T2_IOCSRL_CDWWPE 0x00004000UL /* CBUS data write wrong parity even */ +#define T2_IOCSRL_SLOT2 0x00008000UL /* PCI slot 2 present bit */ +#define T2_IOCSRL_PSERR 0x00010000UL /* power supply error */ +#define T2_IOCSRL_MBA7 0x00020000UL /* MBA7 asserted */ +#define T2_IOCSRL_SLOT1 0x000c0000UL /* PCI slot 1 present bits */ +#define T2_IOCSRL_PDWWP1 0x00100000UL /* PCI DMA write wrong parity HW1 */ +#define T2_IOCSRL_PDWWP0 0x00200000UL /* PCI DMA write wrong parity HW0 */ +#define T2_IOCSRL_PBR 0x00400000UL /* PCI bus reset */ +#define T2_IOCSRL_PIR 0x00800000UL /* PCI interface reset */ +#define T2_IOCSRL_ENCOI 0x01000000UL /* enable NOACK, CUCERR and out-of-sync int */ +#define T2_IOCSRL_EPMS 0x02000000UL /* enable PCI memory space */ +#define T2_IOCSRL_ETLB 0x04000000UL /* enable TLB */ +#define T2_IOCSRL_EACC 0x08000000UL /* enable atomic CBUS cycles */ +#define T2_IOCSRL_ITLB 0x10000000UL /* flush TLB */ +#define T2_IOCSRL_ECPC 0x20000000UL /* enable CBUS parity check */ +#define T2_IOCSRL_CIR 0x40000000UL /* CBUS interface reset */ +#define T2_IOCSRL_EPL 0x80000000UL /* enable PCI lock */ + /* High word */ +#define T2_IOCSRH_CBBCE 0x00000001UL /* CBUS back-to-back cycle enable */ +#define T2_IOCSRH_TM 0x0000000eUL /* T2 revision number */ +#define T2_IOCSRH_SMVL 0x00000070UL /* state machine visibility select */ +#define T2_IOCSRH_SLOT2 0x00000080UL /* PCI slot 2 present bit */ +#define T2_IOCSRH_EPR 0x00000100UL /* enable passive release */ +#define T2_IOCSRH_CAWWP1 0x00001000UL /* cbus command/address write wrong parity 1 */ +#define T2_IOCSRH_CAWWP3 0x00002000UL /* cbus command/address write wrong parity 3 */ +#define T2_IOCSRH_DWWPO 0x00004000UL /* CBUS data write wrong parity odd */ +#define T2_IOCSRH_PRM 0x00100000UL /* PCI read multiple */ +#define T2_IOCSRH_PWM 0x00200000UL /* PCI write multiple */ +#define T2_IOCSRH_FPRDPED 0x00400000UL /* force PCI RDPE detect */ +#define T2_IOCSRH_PFAPED 0x00800000UL /* force PCI APE detect */ +#define T2_IOCSRH_FPWDPED 0x01000000UL /* force PCI WDPE detect */ +#define T2_IOCSRH_EPNMI 0x02000000UL /* enable PCI NMI */ +#define T2_IOCSRH_EPDTI 0x04000000UL /* enable PCI DTI */ +#define T2_IOCSRH_EPSEI 0x08000000UL /* enable PCI SERR interrupt */ +#define T2_IOCSRH_EPPEI 0x10000000UL /* enable PCI PERR interrupt */ +#define T2_IOCSRH_ERDPC 0x20000000UL /* enable PCI RDP interrupt */ +#define T2_IOCSRH_EADPC 0x40000000UL /* enable PCI AP interrupt */ +#define T2_IOCSRH_EWDPC 0x80000000UL /* enable PCI WDP interrupt */ + +#define T2_CERR1 (CBUS_BASE + 0xe000020) +#define T2_CERR2 (CBUS_BASE + 0xe000040) +#define T2_CERR3 (CBUS_BASE + 0xe000060) +#define T2_PERR1 (CBUS_BASE + 0xe000080) +#define T2_PERR1_PWDPE 0x00000001 /* PCI write data parity error */ +#define T2_PERR1_PAPE 0x00000002 /* PCI address parity error */ +#define T2_PERR1_PRDPE 0x00000004 /* PCI read data parity error */ +#define T2_PERR1_PPE 0x00000008 /* PCI parity error */ +#define T2_PERR1_PSE 0x00000010 /* PCI system error */ +#define T2_PERR1_PDTE 0x00000020 /* PCI device timeout error */ +#define T2_PERR1_NMI 0x00000040 /* PCI NMI */ + +#define T2_PERR2 (CBUS_BASE + 0xe0000a0) +#define T2_PSCR (CBUS_BASE + 0xe0000c0) +#define T2_HAE0_1 (CBUS_BASE + 0xe0000e0) +#define T2_HAE0_2 (CBUS_BASE + 0xe000100) +#define T2_HBASE (CBUS_BASE + 0xe000120) +#define T2_WBASE1 (CBUS_BASE + 0xe000140) +#define T2_WMASK1 (CBUS_BASE + 0xe000160) +#define T2_TBASE1 (CBUS_BASE + 0xe000180) +#define T2_WBASE2 (CBUS_BASE + 0xe0001a0) +#define T2_WMASK2 (CBUS_BASE + 0xe0001c0) +#define T2_TBASE2 (CBUS_BASE + 0xe0001e0) +#define T2_TLBBR (CBUS_BASE + 0xe000200) +#define T2_HAE0_3 (CBUS_BASE + 0xe000240) +#define T2_HAE0_4 (CBUS_BASE + 0xe000280) + +/* + * DMA window constants, section 5.2.1.1.1 of the + * Sable I/O Specification + */ + +#define T2_WINDOW_ENABLE 0x00080000 +#define T2_WINDOW_DISABLE 0x00000000 +#define T2_WINDOW_SG 0x00040000 +#define T2_WINDOW_DIRECT 0x00000000 + +#define T2_WMASK_2G 0x7ff00000 +#define T2_WMASK_1G 0x3ff00000 +#define T2_WMASK_512M 0x1ff00000 +#define T2_WMASK_256M 0x0ff00000 +#define T2_WMASK_128M 0x07f00000 +#define T2_WMASK_64M 0x03f00000 +#define T2_WMASK_32M 0x01f00000 +#define T2_WMASK_16M 0x00f00000 +#define T2_WMASK_8M 0x00700000 +#define T2_WMASK_4M 0x00300000 +#define T2_WMASK_2M 0x00100000 +#define T2_WMASK_1M 0x00000000 + + +#define T2_WSIZE_2G 0x80000000 +#define T2_WSIZE_1G 0x40000000 +#define T2_WSIZE_512M 0x20000000 +#define T2_WSIZE_256M 0x10000000 +#define T2_WSIZE_128M 0x08000000 +#define T2_WSIZE_64M 0x04000000 +#define T2_WSIZE_32M 0x02000000 +#define T2_WSIZE_16M 0x01000000 +#define T2_WSIZE_8M 0x00800000 +#define T2_WSIZE_4M 0x00400000 +#define T2_WSIZE_2M 0x00200000 +#define T2_WSIZE_1M 0x00100000 +#define T2_WSIZE_0M 0x00000000 + +#define T2_TBASE_SHIFT 1 + +#define MASTER_ICU 0x535 +#define SLAVE0_ICU 0x537 +#define SLAVE1_ICU 0x53b +#define SLAVE2_ICU 0x53d +#define SLAVE3_ICU 0x53f diff --git a/sys/conf/files.alpha b/sys/conf/files.alpha index cfa8e326b810..adc2f7d1b663 100644 --- a/sys/conf/files.alpha +++ b/sys/conf/files.alpha @@ -33,6 +33,7 @@ alpha/alpha/dec_kn20aa.c optional dec_kn20aa alpha/alpha/dec_1000a.c optional dec_1000a alpha/alpha/dec_1000a.c optional dec_1000a alpha/alpha/dec_2100_a50.c optional dec_2100_a50 +alpha/alpha/dec_2100_a500.c optional dec_2100_a500 alpha/alpha/dec_st550.c optional dec_st550 alpha/alpha/dec_st6600.c optional dec_st6600 alpha/alpha/dec_axppci_33.c optional dec_axppci_33 @@ -136,6 +137,8 @@ alpha/pci/pci_eb164_intr.s optional dec_st550 alpha/pci/pci_eb64plus_intr.s optional dec_2100_a50 alpha/pci/pci_eb64plus_intr.s optional dec_eb64plus alpha/pci/pcibus.c optional pci +alpha/pci/t2.c optional dec_2100_a500 +alpha/pci/t2_pci.c optional dec_2100_a500 alpha/pci/tsunami.c optional dec_st6600 alpha/pci/tsunami_pci.c optional dec_st6600 dev/advansys/adv_isa.c optional adv isa diff --git a/sys/conf/options.alpha b/sys/conf/options.alpha index 56978552fb56..f0c1a4a5e00b 100644 --- a/sys/conf/options.alpha +++ b/sys/conf/options.alpha @@ -8,6 +8,7 @@ DEC_EB164 opt_cpu.h DEC_EB64PLUS opt_cpu.h DEC_KN20AA opt_cpu.h DEC_2100_A50 opt_cpu.h +DEC_2100_A500 opt_cpu.h DEC_ST550 opt_cpu.h DEC_ST6600 opt_cpu.h DEC_AXPPCI_33 opt_cpu.h