diff options
author | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 1998-07-01 05:32:44 +0000 |
---|---|---|
committer | Angelos D. Keromytis <angelos@cvs.openbsd.org> | 1998-07-01 05:32:44 +0000 |
commit | d4d2a1e95f0392f25d6ce9ce5fab4a3aa4134782 (patch) | |
tree | ba62f244d55b394f7206a3362c56a5387ce6ea47 | |
parent | 9de2636b8cca04a381ee2886ac99eadce51dd7ca (diff) |
First shot for EB164SX/LX support; kernels for those should be much
more stable now, but by no means production-strong. A lot of code from
NetBSD.
-rw-r--r-- | sys/arch/alpha/pci/cia.c | 20 | ||||
-rw-r--r-- | sys/arch/alpha/pci/pci_2100_a50.c | 7 | ||||
-rw-r--r-- | sys/arch/alpha/pci/pci_axppci_33.c | 7 | ||||
-rw-r--r-- | sys/arch/alpha/pci/pci_eb164.c | 156 | ||||
-rw-r--r-- | sys/arch/alpha/pci/pci_kn20aa.c | 7 | ||||
-rw-r--r-- | sys/arch/alpha/pci/sio_pic.c | 190 | ||||
-rw-r--r-- | sys/arch/alpha/pci/siovar.h | 4 |
7 files changed, 307 insertions, 84 deletions
diff --git a/sys/arch/alpha/pci/cia.c b/sys/arch/alpha/pci/cia.c index 556058a511e..4630e5c72ed 100644 --- a/sys/arch/alpha/pci/cia.c +++ b/sys/arch/alpha/pci/cia.c @@ -1,4 +1,4 @@ -/* $OpenBSD: cia.c,v 1.7 1997/01/24 19:57:36 niklas Exp $ */ +/* $OpenBSD: cia.c,v 1.8 1998/07/01 05:32:35 angelos Exp $ */ /* $NetBSD: cia.c,v 1.15 1996/12/05 01:39:35 cgd Exp $ */ /* @@ -112,6 +112,24 @@ cia_init(ccp, mallocsafe) ccp->cc_hae_mem = REGVAL(CIA_CSR_HAE_MEM); ccp->cc_hae_io = REGVAL(CIA_CSR_HAE_IO); + /* + * Determine if we have a Pyxis. Only two systypes can + * have this: the EB164 systype (AlphaPC164LX and AlphaPC164SX) + * and the DEC_550 systype (Miata). + */ + if ((hwrpb->rpb_type == ST_EB164 && + (hwrpb->rpb_variation & SV_ST_MASK) >= SV_ST_ALPHAPC164LX_400) || + hwrpb->rpb_type == ST_DEC_550) + ccp->cc_flags |= CCF_ISPYXIS; + + /* + * ALCOR/ALCOR2 Revisions >= 2 and Pyxis have the CNFG register. + */ + if (ccp->cc_rev >= 2 || (ccp->cc_flags & CCF_ISPYXIS) != 0) + ccp->cc_cnfg = REGVAL(CIA_CSR_CNFG); + else + ccp->cc_cnfg = 0; + if (!ccp->cc_initted) { /* don't do these twice since they set up extents */ ccp->cc_iot = cia_bus_io_init(ccp); diff --git a/sys/arch/alpha/pci/pci_2100_a50.c b/sys/arch/alpha/pci/pci_2100_a50.c index 0deeac43f6a..fd864d5c80e 100644 --- a/sys/arch/alpha/pci/pci_2100_a50.c +++ b/sys/arch/alpha/pci/pci_2100_a50.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pci_2100_a50.c,v 1.10 1997/01/24 19:57:47 niklas Exp $ */ +/* $OpenBSD: pci_2100_a50.c,v 1.11 1998/07/01 05:32:37 angelos Exp $ */ /* $NetBSD: pci_2100_a50.c,v 1.12 1996/11/13 21:13:29 cgd Exp $ */ /* @@ -83,8 +83,11 @@ pci_2100_a50_pickintr(acp) pc->pc_intr_establish = dec_2100_a50_intr_establish; pc->pc_intr_disestablish = dec_2100_a50_intr_disestablish; + /* Not supported on 2100 A50. */ + pc->pc_pciide_compat_intr_establish = NULL; + #if NSIO - sio_intr_setup(iot); + sio_intr_setup(pc, iot); set_iointr(&sio_iointr); #else panic("pci_2100_a50_pickintr: no I/O interrupt handler (no sio)"); diff --git a/sys/arch/alpha/pci/pci_axppci_33.c b/sys/arch/alpha/pci/pci_axppci_33.c index 07bb01096db..56464a68a33 100644 --- a/sys/arch/alpha/pci/pci_axppci_33.c +++ b/sys/arch/alpha/pci/pci_axppci_33.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pci_axppci_33.c,v 1.9 1997/01/24 19:57:48 niklas Exp $ */ +/* $OpenBSD: pci_axppci_33.c,v 1.10 1998/07/01 05:32:38 angelos Exp $ */ /* $NetBSD: pci_axppci_33.c,v 1.10 1996/11/13 21:13:29 cgd Exp $ */ /* @@ -84,8 +84,11 @@ pci_axppci_33_pickintr(lcp) pc->pc_intr_establish = dec_axppci_33_intr_establish; pc->pc_intr_disestablish = dec_axppci_33_intr_disestablish; + /* Not supported on AXPpci33. */ + pc->pc_pciide_compat_intr_establish = NULL; + #if NSIO - sio_intr_setup(iot); + sio_intr_setup(pc, iot); set_iointr(&sio_iointr); #else panic("pci_axppci_33_pickintr: no I/O interrupt handler (no sio)"); diff --git a/sys/arch/alpha/pci/pci_eb164.c b/sys/arch/alpha/pci/pci_eb164.c index 90c9e6c2661..c97464fae51 100644 --- a/sys/arch/alpha/pci/pci_eb164.c +++ b/sys/arch/alpha/pci/pci_eb164.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pci_eb164.c,v 1.1 1997/01/24 19:57:48 niklas Exp $ */ +/* $OpenBSD: pci_eb164.c,v 1.2 1998/07/01 05:32:40 angelos Exp $ */ /* $NetBSD: pci_eb164.c,v 1.4 1996/11/25 03:47:05 cgd Exp $ */ /* @@ -40,6 +40,7 @@ #include <vm/vm.h> #include <machine/autoconf.h> +#include <machine/rpb.h> #include <dev/pci/pcireg.h> #include <dev/pci/pcivar.h> @@ -49,6 +50,9 @@ #include <alpha/pci/pci_eb164.h> +#include <dev/pci/pciidereg.h> +#include <dev/pci/pciidevar.h> + #ifndef EVCNT_COUNTERS #include <machine/intrcnt.h> #endif @@ -65,6 +69,9 @@ void *dec_eb164_intr_establish __P((void *, pci_intr_handle_t, int, int (*)(void *), void *, char *)); void dec_eb164_intr_disestablish __P((void *, void *)); +void *dec_eb164_pciide_compat_intr_establish __P((void *, struct device *, + struct pci_attach_args *, int, int (*)(void *), void *)); + #define EB164_SIO_IRQ 4 #define EB164_MAX_IRQ 24 #define PCI_STRAY_MAX 5 @@ -95,6 +102,9 @@ pci_eb164_pickintr(ccp) pc->pc_intr_establish = dec_eb164_intr_establish; pc->pc_intr_disestablish = dec_eb164_intr_disestablish; + pc->pc_pciide_compat_intr_establish = + dec_eb164_pciide_compat_intr_establish; + eb164_intrgate_iot = iot; if (bus_space_map(eb164_intrgate_iot, 0x804, 3, 0, &eb164_intrgate_ioh) != 0) @@ -108,7 +118,7 @@ pci_eb164_pickintr(ccp) PCI_STRAY_MAX); #if NSIO - sio_intr_setup(iot); + sio_intr_setup(pc, iot); eb164_intr_enable(EB164_SIO_IRQ); #endif @@ -124,75 +134,69 @@ dec_eb164_intr_map(ccv, bustag, buspin, line, ihp) { struct cia_config *ccp = ccv; pci_chipset_tag_t pc = &ccp->cc_pc; - int device; - int eb164_irq, pinbase, pinoff; + int bus, device, function; + u_int64_t variation; if (buspin == 0) { /* No IRQ used. */ return 1; } if (buspin > 4) { - printf("pci_map_int: bad interrupt pin %d\n", buspin); + printf("dec_eb164_intr_map: bad interrupt pin %d\n", buspin); return 1; } - pci_decompose_tag(pc, bustag, NULL, &device, NULL); - switch (device) { -#if 0 /* THIS CODE SHOULD NEVER BE CALLED FOR THE SIO */ - case 8: /* SIO */ - eb164_irq = 4; - break; -#endif - - case 11: - eb164_irq = 5; /* IDE */ - break; - - case 5: - case 6: - case 7: - case 9: - switch (buspin) { - case 1: - pinbase = 0; - break; - case 2: - case 3: - case 4: - pinbase = (buspin * 4) - 1; - break; -#ifdef DIAGNOSTIC - default: - panic("dec_eb164_intr_map: slot buspin switch"); -#endif - }; - switch (device) { - case 5: - pinoff = 2; - break; - - case 6: - case 7: - case 9: - pinoff = device - 6; - break; -#ifdef DIAGNOSTIC - default: - panic("dec_eb164_intr_map: slot device switch"); -#endif - } - eb164_irq = pinoff + pinbase; - break; - default: - panic("pci_eb164_map_int: invalid device number %d\n", - device); - } + alpha_pci_decompose_tag(pc, bustag, &bus, &device, &function); + + variation = hwrpb->rpb_variation & SV_ST_MASK; + + /* + * + * The AlphaPC 164 and AlphaPC 164LX have a CMD PCI IDE controller + * at bus 0 device 11. These are wired to compatibility mode, + * so do not map their interrupts. + * + * The AlphaPC 164SX has PCI IDE on functions 1 and 2 of the + * Cypress PCI-ISA bridge at bus 0 device 8. These, too, are + * wired to compatibility mode. + * + * Real EB164s have ISA IDE on the Super I/O chip. + */ + if (bus == 0) { + if (variation >= SV_ST_ALPHAPC164_366 && + variation <= SV_ST_ALPHAPC164LX_600) { + if (device == 8) + panic("dec_eb164_intr_map: SIO device"); + if (device == 11) + return (1); + } else if (variation >= SV_ST_ALPHAPC164SX_400 && + variation <= SV_ST_ALPHAPC164SX_600) { + if (device == 8) { + if (function == 0) + panic("dec_eb164_intr_map: SIO device"); + return (1); + } + } else { + if (device == 8) + panic("dec_eb164_intr_map: SIO device"); + } + } - if (eb164_irq > EB164_MAX_IRQ) - panic("pci_eb164_map_int: eb164_irq too large (%d)\n", - eb164_irq); + /* + * The console places the interrupt mapping in the "line" value. + * A value of (char)-1 indicates there is no mapping. + */ + if (line == 0xff) { + printf("dec_eb164_intr_map: no mapping for %d/%d/%d\n", + bus, device, function); + return (1); + } + + if (line > EB164_MAX_IRQ) + panic("dec_eb164_map_int: eb164_irq too large (%d)\n", + line); - *ihp = eb164_irq; + *ihp = line; return (0); } @@ -244,6 +248,35 @@ dec_eb164_intr_disestablish(ccv, cookie) panic("dec_eb164_intr_disestablish not implemented"); /* XXX */ } +void * +dec_eb164_pciide_compat_intr_establish(v, dev, pa, chan, func, arg) + void *v; + struct device *dev; + struct pci_attach_args *pa; + int chan; + int (*func) __P((void *)); + void *arg; +{ + pci_chipset_tag_t pc = pa->pa_pc; + void *cookie = NULL; + int bus, irq; + + alpha_pci_decompose_tag(pc, pa->pa_tag, &bus, NULL, NULL); + + /* + * If this isn't PCI bus #0, all bets are off. + */ + if (bus != 0) + return (NULL); + + irq = PCIIDE_COMPAT_IRQ(chan); +#if NSIO + cookie = sio_intr_establish(NULL /*XXX*/, irq, IST_EDGE, IPL_BIO, + func, arg, "eb164 irq"); +#endif + return (cookie); +} + void eb164_iointr(framep, vec) void *framep; @@ -268,7 +301,8 @@ eb164_iointr(framep, vec) alpha_shared_intr_stray(eb164_pci_intr, irq, "eb164 irq"); if (eb164_pci_intr[irq].intr_nstrays == - eb164_pci_intr[irq].intr_maxstrays) + eb164_pci_intr[irq].intr_maxstrays + && TAILQ_FIRST(&eb164_pci_intr[irq].intr_q) == NULL) eb164_intr_disable(irq); } return; diff --git a/sys/arch/alpha/pci/pci_kn20aa.c b/sys/arch/alpha/pci/pci_kn20aa.c index 1f46fb45ca4..4c1fa0c0f82 100644 --- a/sys/arch/alpha/pci/pci_kn20aa.c +++ b/sys/arch/alpha/pci/pci_kn20aa.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pci_kn20aa.c,v 1.9 1997/01/24 19:57:51 niklas Exp $ */ +/* $OpenBSD: pci_kn20aa.c,v 1.10 1998/07/01 05:32:41 angelos Exp $ */ /* $NetBSD: pci_kn20aa.c,v 1.21 1996/11/17 02:05:27 cgd Exp $ */ /* @@ -92,13 +92,16 @@ pci_kn20aa_pickintr(ccp) pc->pc_intr_establish = dec_kn20aa_intr_establish; pc->pc_intr_disestablish = dec_kn20aa_intr_disestablish; + /* Not supported on KN20AA. */ + pc->pc_pciide_compat_intr_establish = NULL; + kn20aa_pci_intr = alpha_shared_intr_alloc(KN20AA_MAX_IRQ); for (i = 0; i < KN20AA_MAX_IRQ; i++) alpha_shared_intr_set_maxstrays(kn20aa_pci_intr, i, PCI_STRAY_MAX); #if NSIO - sio_intr_setup(iot); + sio_intr_setup(pc, iot); kn20aa_enable_intr(KN20AA_PCEB_IRQ); #endif diff --git a/sys/arch/alpha/pci/sio_pic.c b/sys/arch/alpha/pci/sio_pic.c index a219f89a30c..041f87de3d4 100644 --- a/sys/arch/alpha/pci/sio_pic.c +++ b/sys/arch/alpha/pci/sio_pic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sio_pic.c,v 1.11 1998/06/29 05:32:55 downsj Exp $ */ +/* $OpenBSD: sio_pic.c,v 1.12 1998/07/01 05:32:42 angelos Exp $ */ /* $NetBSD: sio_pic.c,v 1.16 1996/11/17 02:05:26 cgd Exp $ */ /* @@ -37,6 +37,10 @@ #include <machine/intr.h> #include <machine/bus.h> +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcidevs.h> + #include <dev/isa/isareg.h> #include <dev/isa/isavar.h> #include <alpha/pci/siovar.h> @@ -63,6 +67,7 @@ * Private functions and variables. */ bus_space_tag_t sio_iot; +pci_chipset_tag_t sio_pc; bus_space_handle_t sio_ioh_icu1, sio_ioh_icu2, sio_ioh_elcr; #define ICU_LEN 16 /* number of ISA IRQs */ @@ -104,6 +109,156 @@ void sio_setirqstat __P((int, int, int)); void sio_setirqstat __P((int, int, int)); +u_int8_t (*sio_read_elcr) __P((int)); +void (*sio_write_elcr) __P((int, u_int8_t)); + +/******************** i82378 SIO ELCR functions ********************/ + +int i82378_setup_elcr __P((void)); +u_int8_t i82378_read_elcr __P((int)); +void i82378_write_elcr __P((int, u_int8_t)); + +int +i82378_setup_elcr() +{ + int rv; + + /* + * We could probe configuration space to see that there's + * actually an SIO present, but we are using this as a + * fall-back in case nothing else matches. + */ + + rv = bus_space_map(sio_iot, 0x4d0, 2, 0, &sio_ioh_elcr); + + if (rv == 0) { + sio_read_elcr = i82378_read_elcr; + sio_write_elcr = i82378_write_elcr; + } + + return (rv); +} + +u_int8_t +i82378_read_elcr(elcr) + int elcr; +{ + + return (bus_space_read_1(sio_iot, sio_ioh_elcr, elcr)); +} + +void +i82378_write_elcr(elcr, val) + int elcr; + u_int8_t val; +{ + + bus_space_write_1(sio_iot, sio_ioh_elcr, elcr, val); +} + +/******************** Cypress CY82C693 ELCR functions ********************/ + +int cy82c693_setup_elcr __P((void)); +u_int8_t cy82c693_read_elcr __P((int)); +void cy82c693_write_elcr __P((int, u_int8_t)); + +int +cy82c693_setup_elcr() +{ + int device, maxndevs; + pcireg_t id; + + /* + * Search PCI configuration space for a Cypress CY82C693. + * + * Note we can make some assumptions about our bus number + * here, because: + * + * (1) there can be at most one ISA/EISA bridge per PCI bus, and + * + * (2) any ISA/EISA bridges must be attached to primary PCI + * busses (i.e. bus zero). + */ + + maxndevs = pci_bus_maxdevs(sio_pc, 0); + + for (device = 0; device < maxndevs; device++) { + id = pci_conf_read(sio_pc, pci_make_tag(sio_pc, 0, device, 0), + PCI_ID_REG); + + /* Invalid vendor ID value? */ + if (PCI_VENDOR(id) == PCI_VENDOR_INVALID) + continue; + /* XXX Not invalid, but we've done this ~forever. */ + if (PCI_VENDOR(id) == 0) + continue; + + if (PCI_VENDOR(id) != PCI_VENDOR_CONTAQ || + PCI_PRODUCT(id) != PCI_PRODUCT_CONTAQ_SIO) + continue; + + /* + * Found one! + */ + +#if 0 + printf("cy82c693_setup_elcr: found 82C693 at device %d\n", + device); +#endif + + /* + * The CY82C693's ELCR registers are accessed indirectly + * via (IO_ICU1 + 2) (address) and (IO_ICU1 + 3) (data). + */ + sio_ioh_elcr = sio_ioh_icu1; + + sio_read_elcr = cy82c693_read_elcr; + sio_write_elcr = cy82c693_write_elcr; + + return (0); + } + + /* + * Didn't find a CY82C693. + */ + return (ENODEV); +} + +u_int8_t +cy82c693_read_elcr(elcr) + int elcr; +{ + + bus_space_write_1(sio_iot, sio_ioh_elcr, 0x02, 0x03 + elcr); + return (bus_space_read_1(sio_iot, sio_ioh_elcr, 0x03)); +} + +void +cy82c693_write_elcr(elcr, val) + int elcr; + u_int8_t val; +{ + + bus_space_write_1(sio_iot, sio_ioh_elcr, 0x02, 0x03 + elcr); + bus_space_write_1(sio_iot, sio_ioh_elcr, 0x03, val); +} + +/******************** ELCR access function configuration ********************/ + +/* + * Put the Intel SIO at the end, so we fall back on it if we don't + * find anything else. If any of the non-Intel functions find a + * matching device, but are unable to map it for whatever reason, + * they should panic. + */ + +int (*sio_elcr_setup_funcs[]) __P((void)) = { + cy82c693_setup_elcr, + i82378_setup_elcr, + NULL, +}; + +/******************** Shared SIO/Cypress functions ********************/ void sio_setirqstat(irq, enabled, type) int irq, enabled; @@ -122,8 +277,8 @@ sio_setirqstat(irq, enabled, type) ocw1[0] = bus_space_read_1(sio_iot, sio_ioh_icu1, 1); ocw1[1] = bus_space_read_1(sio_iot, sio_ioh_icu2, 1); - elcr[0] = bus_space_read_1(sio_iot, sio_ioh_elcr, 0); /* XXX */ - elcr[1] = bus_space_read_1(sio_iot, sio_ioh_elcr, 1); /* XXX */ + elcr[0] = (*sio_read_elcr)(0); /* XXX */ + elcr[1] = (*sio_read_elcr)(1); /* XXX */ /* * interrupt enable: set bit to mask (disable) interrupt. @@ -169,31 +324,38 @@ sio_setirqstat(irq, enabled, type) bus_space_write_1(sio_iot, sio_ioh_icu1, 1, ocw1[0]); bus_space_write_1(sio_iot, sio_ioh_icu2, 1, ocw1[1]); - bus_space_write_1(sio_iot, sio_ioh_elcr, 0, elcr[0]); /* XXX */ - bus_space_write_1(sio_iot, sio_ioh_elcr, 1, elcr[1]); /* XXX */ + (*sio_write_elcr)(0, elcr[0]); /* XXX */ + (*sio_write_elcr)(1, elcr[1]); /* XXX */ } void -sio_intr_setup(iot) +sio_intr_setup(pc, iot) + pci_chipset_tag_t pc; bus_space_tag_t iot; { int i; sio_iot = iot; - + sio_pc = pc; + if (bus_space_map(sio_iot, IO_ICU1, IO_ICUSIZE, 0, &sio_ioh_icu1) || - bus_space_map(sio_iot, IO_ICU2, IO_ICUSIZE, 0, &sio_ioh_icu2) || - bus_space_map(sio_iot, 0x4d0, 2, 0, &sio_ioh_elcr)) + bus_space_map(sio_iot, IO_ICU2, IO_ICUSIZE, 0, &sio_ioh_icu2)) panic("sio_intr_setup: can't map I/O ports"); + for (i = 0; sio_elcr_setup_funcs[i] != NULL; i++) + if ((*sio_elcr_setup_funcs[i])() == 0) + break; + if (sio_elcr_setup_funcs[i] == NULL) + panic("sio_intr_setup: can't map ELCR"); + #ifdef BROKEN_PROM_CONSOLE /* * Remember the initial values, because the prom is stupid. */ initial_ocw1[0] = bus_space_read_1(sio_iot, sio_ioh_icu1, 1); initial_ocw1[1] = bus_space_read_1(sio_iot, sio_ioh_icu2, 1); - initial_elcr[0] = bus_space_read_1(sio_iot, sio_ioh_elcr, 0); /* XXX */ - initial_elcr[1] = bus_space_read_1(sio_iot, sio_ioh_elcr, 1); /* XXX */ + initial_elcr[0] = (*sio_read_elcr)(0); /* XXX */ + initial_elcr[1] = (*sio_read_elcr)(1); /* XXX */ #if 0 printf("initial_ocw1[0] = 0x%x\n", initial_ocw1[0]); printf("initial_ocw1[1] = 0x%x\n", initial_ocw1[1]); @@ -275,10 +437,10 @@ sio_intr_check(v, irq, type) void *v; int irq, type; { - if (irq > ICU_LEN || type == IST_NONE) + if (irq > ICU_LEN || type == IST_NONE) return (0); - - return (alpha_shared_intr_check(sio_intr, irq, type)); + + return (alpha_shared_intr_check(sio_intr, irq, type)); } void * diff --git a/sys/arch/alpha/pci/siovar.h b/sys/arch/alpha/pci/siovar.h index 9cf8866b82b..2e75cf02f81 100644 --- a/sys/arch/alpha/pci/siovar.h +++ b/sys/arch/alpha/pci/siovar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: siovar.h,v 1.6 1998/06/29 05:32:57 downsj Exp $ */ +/* $OpenBSD: siovar.h,v 1.7 1998/07/01 05:32:43 angelos Exp $ */ /* $NetBSD: siovar.h,v 1.5 1996/10/23 04:12:34 cgd Exp $ */ /* @@ -28,7 +28,7 @@ * rights to redistribute these changes. */ -void sio_intr_setup __P((bus_space_tag_t)); +void sio_intr_setup __P((pci_chipset_tag_t, bus_space_tag_t)); void sio_iointr __P((void *framep, unsigned long vec)); const char *sio_intr_string __P((void *, int)); |