diff options
Diffstat (limited to 'sys/arch/sgi')
-rw-r--r-- | sys/arch/sgi/hpc/hpc.c | 86 | ||||
-rw-r--r-- | sys/arch/sgi/hpc/hpcvar.h | 12 | ||||
-rw-r--r-- | sys/arch/sgi/hpc/if_sq.c | 67 | ||||
-rw-r--r-- | sys/arch/sgi/hpc/if_sqvar.h | 11 | ||||
-rw-r--r-- | sys/arch/sgi/include/autoconf.h | 5 | ||||
-rw-r--r-- | sys/arch/sgi/localbus/imcreg.h | 50 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/bus_dma.c | 18 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/ip22.h | 6 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/ip22_machdep.c | 122 | ||||
-rw-r--r-- | sys/arch/sgi/sgi/machdep.c | 3 |
10 files changed, 325 insertions, 55 deletions
diff --git a/sys/arch/sgi/hpc/hpc.c b/sys/arch/sgi/hpc/hpc.c index 99c1cea1a64..6c21704dd51 100644 --- a/sys/arch/sgi/hpc/hpc.c +++ b/sys/arch/sgi/hpc/hpc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: hpc.c,v 1.12 2012/05/17 19:38:59 miod Exp $ */ +/* $OpenBSD: hpc.c,v 1.13 2012/05/27 14:27:08 miod Exp $ */ /* $NetBSD: hpc.c,v 1.66 2011/07/01 18:53:46 dyoung Exp $ */ /* $NetBSD: ioc.c,v 1.9 2011/07/01 18:53:47 dyoung Exp $ */ @@ -363,6 +363,18 @@ void hpc_blink_ioc(void *); int hpc_read_eeprom(int, bus_space_tag_t, bus_space_handle_t, uint8_t *, size_t); +struct hpc_dma_desc *hpc_read_dma_desc_par(struct hpc_dma_desc *, + struct hpc_dma_desc *); +struct hpc_dma_desc *hpc_read_dma_desc_ecc(struct hpc_dma_desc *, + struct hpc_dma_desc *); +void hpc_write_dma_desc_par(struct hpc_dma_desc *, struct hpc_dma_desc *); +void hpc_write_dma_desc_ecc(struct hpc_dma_desc *, struct hpc_dma_desc *); + +/* globals since they depend upon the system type, not the hpc version */ +struct hpc_dma_desc *(*hpc_read_dma_desc_fn)(struct hpc_dma_desc *, + struct hpc_dma_desc *); +void (*hpc_write_dma_desc_fn)(struct hpc_dma_desc *, struct hpc_dma_desc *); + const struct cfattach hpc_ca = { sizeof(struct hpc_softc), hpc_match, hpc_attach }; @@ -423,6 +435,17 @@ hpc_attach(struct device *parent, struct device *self, void *aux) sc->sc_ch = PHYS_TO_XKPHYS(sc->sc_base, CCA_NC); sc->sc_dmat = ga->ga_dmat; + /* setup HPC DMA helpers if not done already */ + if (hpc_read_dma_desc_fn == NULL) { + if (ip22_ecc) { + hpc_read_dma_desc_fn = hpc_read_dma_desc_ecc; + hpc_write_dma_desc_fn = hpc_write_dma_desc_ecc; + } else { + hpc_read_dma_desc_fn = hpc_read_dma_desc_par; + hpc_write_dma_desc_fn = hpc_write_dma_desc_par; + } + } + switch (sys_config.system_type) { case SGI_IP20: sysmask = HPCDEV_IP20; @@ -749,7 +772,7 @@ hpc_attach(struct device *parent, struct device *self, void *aux) * o Indigo2, Challenge M * One on-board HPC3. * - * All we really have to worry about is the IP22 case. + * All we really have to worry about is the IP24 case. */ int hpc_revision(struct hpc_softc *sc, struct gio_attach_args *ga) @@ -775,12 +798,16 @@ hpc_revision(struct hpc_softc *sc, struct gio_attach_args *ga) case SGI_IP22: case SGI_IP26: case SGI_IP28: + if (ga->ga_addr == HPC_BASE_ADDRESS_0) + return 3; + + if (sys_config.system_subtype == IP22_INDIGO2) + return 0; + /* - * If IP22, probe slot 0 to determine if HPC1.5 or HPC3. Slot 1 + * If IP24, probe slot 0 to determine if HPC1.5 or HPC3. Slot 1 * must be HPC1.5. */ - if (ga->ga_addr == HPC_BASE_ADDRESS_0) - return 3; if (ga->ga_addr == HPC_BASE_ADDRESS_2) return 15; @@ -943,3 +970,52 @@ hpc_read_eeprom(int hpctype, bus_space_tag_t t, bus_space_handle_t h, return 0; } + +/* + * Routines to copy and update HPC DMA descriptors in uncached memory. + */ + +struct hpc_dma_desc * +hpc_read_dma_desc(struct hpc_dma_desc *src, struct hpc_dma_desc *store) +{ + return (*hpc_read_dma_desc_fn)(src, store); +} + +void +hpc_write_dma_desc(struct hpc_dma_desc *dst, struct hpc_dma_desc *src) +{ + (*hpc_write_dma_desc_fn)(dst, src); +} + +/* parity MC flavour: no copy */ +struct hpc_dma_desc * +hpc_read_dma_desc_par(struct hpc_dma_desc *src, struct hpc_dma_desc *store) +{ + return src; +} + +void +hpc_write_dma_desc_par(struct hpc_dma_desc *dst, struct hpc_dma_desc *src) +{ +} + +/* ECC MC flavour: copy, and update in slow mode */ +struct hpc_dma_desc * +hpc_read_dma_desc_ecc(struct hpc_dma_desc *src, struct hpc_dma_desc *store) +{ + bcopy(src, store, sizeof(struct hpc_dma_desc)); + return store; +} + +void +hpc_write_dma_desc_ecc(struct hpc_dma_desc *dst, struct hpc_dma_desc *src) +{ + uint32_t sr; + int mode; + + sr = disableintr(); + mode = ip22_slow_mode(); + bcopy(src, dst, sizeof(struct hpc_dma_desc)); + ip22_restore_mode(mode); + setsr(sr); +} diff --git a/sys/arch/sgi/hpc/hpcvar.h b/sys/arch/sgi/hpc/hpcvar.h index 9a1e656c6b7..6c0f7a86aed 100644 --- a/sys/arch/sgi/hpc/hpcvar.h +++ b/sys/arch/sgi/hpc/hpcvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: hpcvar.h,v 1.7 2012/04/30 21:30:33 miod Exp $ */ +/* $OpenBSD: hpcvar.h,v 1.8 2012/05/27 14:27:08 miod Exp $ */ /* $NetBSD: hpcvar.h,v 1.12 2011/01/25 12:21:04 tsutsui Exp $ */ /* @@ -110,4 +110,14 @@ int hpc_is_intr_pending(int); void hpc_intr_disable(void *); void hpc_intr_enable(void *); +/* + * Routines to copy and update HPC DMA descriptors in uncached memory; + * needed for proper operation on ECC MC systems. + */ +struct hpc_dma_desc; + +struct hpc_dma_desc *hpc_read_dma_desc(struct hpc_dma_desc *src, + struct hpc_dma_desc *store); +void hpc_write_dma_desc(struct hpc_dma_desc *dst, struct hpc_dma_desc *src); + extern bus_space_t hpc3bus_tag; diff --git a/sys/arch/sgi/hpc/if_sq.c b/sys/arch/sgi/hpc/if_sq.c index e9fdd98218e..df697555416 100644 --- a/sys/arch/sgi/hpc/if_sq.c +++ b/sys/arch/sgi/hpc/if_sq.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_sq.c,v 1.6 2012/05/22 19:53:40 miod Exp $ */ +/* $OpenBSD: if_sq.c,v 1.7 2012/05/27 14:27:08 miod Exp $ */ /* $NetBSD: if_sq.c,v 1.42 2011/07/01 18:53:47 dyoung Exp $ */ /* @@ -229,9 +229,15 @@ sq_attach(struct device *parent, struct device *self, void *aux) goto fail_0; } + /* + * Note that we need to pass BUS_DMA_BUS1 in order to get this + * allocation to succeed on ECC MC systems. This code is + * uncached-write safe, as all updates of the DMA descriptors are + * handled in RCU style with hpc_{read,write}_dma_desc(). + */ if ((rc = bus_dmamem_map(sc->sc_dmat, &sc->sc_cdseg, sc->sc_ncdseg, sizeof(struct sq_control), (caddr_t *)&sc->sc_control, - BUS_DMA_NOWAIT | BUS_DMA_COHERENT)) != 0) { + BUS_DMA_NOWAIT | BUS_DMA_COHERENT | BUS_DMA_BUS1)) != 0) { printf(": unable to map control data, error = %d\n", rc); goto fail_1; } @@ -656,9 +662,10 @@ void sq_start(struct ifnet *ifp) { struct sq_softc *sc = ifp->if_softc; - uint32_t status; struct mbuf *m0, *m; + struct hpc_dma_desc *txd, txd_store; bus_dmamap_t dmamap; + uint32_t status; int err, len, totlen, nexttx, firsttx, lasttx = -1, ofree, seg; if ((ifp->if_flags & (IFF_RUNNING|IFF_OACTIVE)) != IFF_RUNNING) @@ -789,31 +796,31 @@ sq_start(struct ifnet *ifp) for (nexttx = sc->sc_nexttx, seg = 0, totlen = 0; seg < dmamap->dm_nsegs; seg++, nexttx = SQ_NEXTTX(nexttx)) { + txd = hpc_read_dma_desc(sc->sc_txdesc + nexttx, + &txd_store); if (sc->hpc_regs->revision == 3) { - sc->sc_txdesc[nexttx].hpc3_hdd_bufptr = + txd->hpc3_hdd_bufptr = dmamap->dm_segs[seg].ds_addr; - sc->sc_txdesc[nexttx].hpc3_hdd_ctl = - dmamap->dm_segs[seg].ds_len; + txd->hpc3_hdd_ctl = dmamap->dm_segs[seg].ds_len; } else { - sc->sc_txdesc[nexttx].hpc1_hdd_bufptr = + txd->hpc1_hdd_bufptr = dmamap->dm_segs[seg].ds_addr; - sc->sc_txdesc[nexttx].hpc1_hdd_ctl = - dmamap->dm_segs[seg].ds_len; + txd->hpc1_hdd_ctl = dmamap->dm_segs[seg].ds_len; } - sc->sc_txdesc[nexttx].hdd_descptr = - SQ_CDTXADDR(sc, SQ_NEXTTX(nexttx)); + txd->hdd_descptr = SQ_CDTXADDR(sc, SQ_NEXTTX(nexttx)); + hpc_write_dma_desc(sc->sc_txdesc + nexttx, txd); lasttx = nexttx; totlen += dmamap->dm_segs[seg].ds_len; } /* Last descriptor gets end-of-packet */ KASSERT(lasttx != -1); + /* txd = hpc_read_dma_desc(sc->sc_txdesc + lasttx, &txd_store); */ if (sc->hpc_regs->revision == 3) - sc->sc_txdesc[lasttx].hpc3_hdd_ctl |= - HPC3_HDD_CTL_EOPACKET; + txd->hpc3_hdd_ctl |= HPC3_HDD_CTL_EOPACKET; else - sc->sc_txdesc[lasttx].hpc1_hdd_ctl |= - HPC1_HDD_CTL_EOPACKET; + txd->hpc1_hdd_ctl |= HPC1_HDD_CTL_EOPACKET; + hpc_write_dma_desc(sc->sc_txdesc + lasttx, txd); SQ_DPRINTF(("%s: transmit %d-%d, len %d\n", sc->sc_dev.dv_xname, sc->sc_nexttx, lasttx, totlen)); @@ -869,15 +876,15 @@ sq_start(struct ifnet *ifp) * addition to HPC3_HDD_CTL_INTR to interrupt. */ KASSERT(lasttx != -1); + txd = hpc_read_dma_desc(sc->sc_txdesc + lasttx, &txd_store); if (sc->hpc_regs->revision == 3) { - sc->sc_txdesc[lasttx].hpc3_hdd_ctl |= + txd->hpc3_hdd_ctl |= HPC3_HDD_CTL_INTR | HPC3_HDD_CTL_EOCHAIN; } else { - sc->sc_txdesc[lasttx].hpc1_hdd_ctl |= HPC1_HDD_CTL_INTR; - sc->sc_txdesc[lasttx].hpc1_hdd_bufptr |= - HPC1_HDD_CTL_EOCHAIN; + txd->hpc1_hdd_ctl |= HPC1_HDD_CTL_INTR; + txd->hpc1_hdd_bufptr |= HPC1_HDD_CTL_EOCHAIN; } - + hpc_write_dma_desc(sc->sc_txdesc + lasttx, txd); SQ_CDTXSYNC(sc, lasttx, 1, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); @@ -898,17 +905,18 @@ sq_start(struct ifnet *ifp) if ((status & sc->hpc_regs->enetx_ctl_active) != 0) { SQ_TRACE(SQ_ADD_TO_DMA, sc, firsttx, status); + txd = hpc_read_dma_desc(sc->sc_txdesc + + SQ_PREVTX(firsttx), &txd_store); /* * NB: hpc3_hdd_ctl == hpc1_hdd_bufptr, and * HPC1_HDD_CTL_EOCHAIN == HPC3_HDD_CTL_EOCHAIN */ - sc->sc_txdesc[SQ_PREVTX(firsttx)].hpc3_hdd_ctl &= - ~HPC3_HDD_CTL_EOCHAIN; - + txd->hpc3_hdd_ctl &= ~HPC3_HDD_CTL_EOCHAIN; if (sc->hpc_regs->revision != 3) - sc->sc_txdesc[SQ_PREVTX(firsttx)].hpc1_hdd_ctl - &= ~HPC1_HDD_CTL_INTR; + txd->hpc1_hdd_ctl &= ~HPC1_HDD_CTL_INTR; + hpc_write_dma_desc(sc->sc_txdesc + SQ_PREVTX(firsttx), + txd); SQ_CDTXSYNC(sc, SQ_PREVTX(firsttx), 1, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); } else if (sc->hpc_regs->revision == 3) { @@ -1105,6 +1113,7 @@ sq_rxintr(struct sq_softc *sc) { struct ifnet *ifp = &sc->sc_ac.ac_if; struct mbuf* m; + struct hpc_dma_desc *rxd, rxd_store; int i, framelen; uint8_t pktstat; uint32_t status; @@ -1206,12 +1215,16 @@ sq_rxintr(struct sq_softc *sc) */ new_end = SQ_PREVRX(i); - sc->sc_rxdesc[new_end].hpc3_hdd_ctl |= HPC3_HDD_CTL_EOCHAIN; + rxd = hpc_read_dma_desc(sc->sc_rxdesc + new_end, &rxd_store); + rxd->hpc3_hdd_ctl |= HPC3_HDD_CTL_EOCHAIN; + hpc_write_dma_desc(sc->sc_rxdesc + new_end, rxd); SQ_CDRXSYNC(sc, new_end, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); orig_end = SQ_PREVRX(sc->sc_nextrx); - sc->sc_rxdesc[orig_end].hpc3_hdd_ctl &= ~HPC3_HDD_CTL_EOCHAIN; + rxd = hpc_read_dma_desc(sc->sc_rxdesc + orig_end, &rxd_store); + rxd->hpc3_hdd_ctl &= ~HPC3_HDD_CTL_EOCHAIN; + hpc_write_dma_desc(sc->sc_rxdesc + orig_end, rxd); SQ_CDRXSYNC(sc, orig_end, BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); diff --git a/sys/arch/sgi/hpc/if_sqvar.h b/sys/arch/sgi/hpc/if_sqvar.h index 4f55053acc5..9bf5df1323b 100644 --- a/sys/arch/sgi/hpc/if_sqvar.h +++ b/sys/arch/sgi/hpc/if_sqvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: if_sqvar.h,v 1.2 2012/04/30 21:31:03 miod Exp $ */ +/* $OpenBSD: if_sqvar.h,v 1.3 2012/05/27 14:27:08 miod Exp $ */ /* $NetBSD: sqvar.h,v 1.12 2011/01/25 13:12:39 tsutsui Exp $ */ /* @@ -159,6 +159,7 @@ struct sq_softc { #define SQ_CDTXADDR(sc, x) ((sc)->sc_cddma + SQ_CDTXOFF((x))) #define SQ_CDRXADDR(sc, x) ((sc)->sc_cddma + SQ_CDRXOFF((x))) +#if 0 /* not necessary as this memory is mapped uncached */ static inline void SQ_CDTXSYNC(struct sq_softc *sc, int __x, int __n, int ops) { @@ -179,13 +180,18 @@ SQ_CDTXSYNC(struct sq_softc *sc, int __x, int __n, int ops) #define SQ_CDRXSYNC(sc, x, ops) \ bus_dmamap_sync((sc)->sc_dmat, (sc)->sc_cdmap, \ SQ_CDRXOFF((x)), sizeof(struct hpc_dma_desc), (ops)) +#else +#define SQ_CDTXSYNC(sc, x, n, ops) do { } while (0) +#define SQ_CDRXSYNC(sc, x, ops) do { } while (0) +#endif static inline void SQ_INIT_RXDESC(struct sq_softc *sc, unsigned int x) { - struct hpc_dma_desc* __rxd = &(sc)->sc_rxdesc[(x)]; + struct hpc_dma_desc *__rxd, rxd_store; struct mbuf *__m = (sc)->sc_rxmbuf[(x)]; + __rxd = hpc_read_dma_desc(&(sc)->sc_rxdesc[(x)], &rxd_store); __m->m_data = __m->m_ext.ext_buf; if (sc->hpc_regs->revision == 3) { __rxd->hpc3_hdd_bufptr = @@ -201,5 +207,6 @@ SQ_INIT_RXDESC(struct sq_softc *sc, unsigned int x) HPC1_HDD_CTL_INTR | HPC1_HDD_CTL_EOPACKET; } __rxd->hdd_descptr = SQ_CDRXADDR((sc), SQ_NEXTRX((x))); + hpc_write_dma_desc(&(sc)->sc_rxdesc[(x)], __rxd); SQ_CDRXSYNC((sc), (x), BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); } diff --git a/sys/arch/sgi/include/autoconf.h b/sys/arch/sgi/include/autoconf.h index eba8e8b5786..6fdb3a55034 100644 --- a/sys/arch/sgi/include/autoconf.h +++ b/sys/arch/sgi/include/autoconf.h @@ -1,4 +1,4 @@ -/* $OpenBSD: autoconf.h,v 1.35 2012/04/21 12:20:30 miod Exp $ */ +/* $OpenBSD: autoconf.h,v 1.36 2012/05/27 14:27:10 miod Exp $ */ /* * Copyright (c) 2001-2003 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -110,4 +110,7 @@ extern struct sgi_device_location console_output, console_input; int location_match(struct sgi_device_location *, struct sgi_device_location *); +extern void (*md_halt)(int); +void arcbios_halt(int); + #endif /* _MACHINE_AUTOCONF_H_ */ diff --git a/sys/arch/sgi/localbus/imcreg.h b/sys/arch/sgi/localbus/imcreg.h index 14a437fe4f3..e340764794c 100644 --- a/sys/arch/sgi/localbus/imcreg.h +++ b/sys/arch/sgi/localbus/imcreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: imcreg.h,v 1.2 2012/05/25 18:17:20 miod Exp $ */ +/* $OpenBSD: imcreg.h,v 1.3 2012/05/27 14:27:10 miod Exp $ */ /* $NetBSD: imcreg.h,v 1.4 2005/12/11 12:18:52 christos Exp $ */ /* @@ -32,19 +32,19 @@ #define IMC_CPUCTRL0 0x04 /* CPU control, register 0 */ -#define IMC_CPUCTRL0_REFMASK 0x000f /* # lines to refresh */ -#define IMC_CPUCTRL0_RFE 0x0010 /* refresh enable */ -#define IMC_CPUCTRL0_GPR 0x0020 /* GIO parity enable */ -#define IMC_CPUCTRL0_MPR 0x0040 /* memory parity enable */ -#define IMC_CPUCTRL0_CPR 0x0080 /* cpu bus parity enable */ -#define IMC_CPUCTRL0_WDOG 0x0100 /* watchdog enable */ -#define IMC_CPUCTRL0_SIN 0x0200 /* reset system */ -#define IMC_CPUCTRL0_GRR 0x0400 /* graphics reset */ -#define IMC_CPUCTRL0_ENLOCK 0x0800 /* enable EISA memory lock */ -#define IMC_CPUCTRL0_CMDPAR 0x1000 /* SysCmd parity enable */ -#define IMC_CPUCTRL0_INTENA 0x2000 /* enable CPU interrupts */ -#define IMC_CPUCTRL0_SNOOPENA 0x4000 /* enable gfx DMA snoop */ -#define IMC_CPUCTRL0_PROM_WRENA 0x8000 /* disable buserr on PROM +#define IMC_CPUCTRL0_REFMASK 0x0000000f /* # lines to refresh */ +#define IMC_CPUCTRL0_RFE 0x00000010 /* refresh enable */ +#define IMC_CPUCTRL0_GPR 0x00000020 /* GIO parity enable */ +#define IMC_CPUCTRL0_MPR 0x00000040 /* memory parity enable */ +#define IMC_CPUCTRL0_CPR 0x00000080 /* cpu bus parity enable */ +#define IMC_CPUCTRL0_WDOG 0x00000100 /* watchdog enable */ +#define IMC_CPUCTRL0_SIN 0x00000200 /* reset system */ +#define IMC_CPUCTRL0_GRR 0x00000400 /* graphics reset */ +#define IMC_CPUCTRL0_ENLOCK 0x00000800 /* enable EISA memory lock */ +#define IMC_CPUCTRL0_CMDPAR 0x00001000 /* SysCmd parity enable */ +#define IMC_CPUCTRL0_INTENA 0x00002000 /* enable CPU interrupts */ +#define IMC_CPUCTRL0_SNOOPENA 0x00004000 /* enable gfx DMA snoop */ +#define IMC_CPUCTRL0_PROM_WRENA 0x00008000 /* disable buserr on PROM * writes */ #define IMC_CPUCTRL0_WRST 0x00010000 /* warm restart (reset cpu) */ /* Bit 17 reserved 0x00020000 */ @@ -143,4 +143,26 @@ #define IMC_GIO_ERRADDR 0xf4 /* GIO error address */ #define IMC_GIO_ERRSTAT 0xfc /* GIO error status */ +/* {CPU,GIO}_ERRSTAT bits in ECC mode */ +#define IMC_ECC_ERRSTAT_FUW 0x00000001 /* fast mode uncached write */ +#define IMC_ECC_ERRSTAT_MULTI 0x00000002 /* multi bit error */ + #define IMC_RPSS 0x1004 /* RPSS counter */ + +/* + * IP26/IP28 ECC Controller defines + */ + +#define ECC_BASE 0x60000000 +/* control register */ +#define ECC_CTRL 0x00 +#define ECC_CTRL_ENABLE 0x00000000 /* fast mode */ +#define ECC_CTRL_DISABLE 0x00010000 /* slow mode */ +#define ECC_CTRL_WRITE 0x00020000 /* write low bits to chip */ +#define ECC_CTRL_INT_CLR 0x00030000 /* clear pending interrupts */ +#define ECC_CTRL_CHK_ENABLE 0x00050000 /* enable ECC err generation */ +#define ECC_CTRL_CHK_DISABLE 0x00060000 /* disable ECC err generation */ + +/* ecc control chip modes */ +#define ECC_MODE_PASSTHROUGH 0x0002 /* error detection only */ +#define ECC_MODE_NORMAL 0x0003 /* error detection and correction */ diff --git a/sys/arch/sgi/sgi/bus_dma.c b/sys/arch/sgi/sgi/bus_dma.c index 699fca6754d..924e64b5a34 100644 --- a/sys/arch/sgi/sgi/bus_dma.c +++ b/sys/arch/sgi/sgi/bus_dma.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bus_dma.c,v 1.28 2012/05/20 11:41:11 miod Exp $ */ +/* $OpenBSD: bus_dma.c,v 1.29 2012/05/27 14:27:10 miod Exp $ */ /* * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -70,6 +70,10 @@ #include <machine/bus.h> +#if defined(TGT_INDIGO2) +#include <sgi/sgi/ip22.h> +#endif + /* * Common function for DMA map creation. May be called by bus-specific * DMA map creation functions. @@ -440,6 +444,18 @@ _dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, size_t size, bus_addr_t addr; int curseg, error; +#if defined(TGT_INDIGO2) + /* + * On ECC MC systems, which do not allow uncached writes to memory + * during regular operation, fail requests for uncached (coherent) + * memory, unless the caller tells us it is aware of this and will + * do the right thing, by passing BUS_DMA_BUS1 as well. + */ + if ((flags & (BUS_DMA_COHERENT | BUS_DMA_BUS1)) == BUS_DMA_COHERENT && + ip22_ecc) + return EINVAL; +#endif + if (nsegs == 1) { pa = (*t->_device_to_pa)(segs[0].ds_addr); #ifndef TGT_COHERENT diff --git a/sys/arch/sgi/sgi/ip22.h b/sys/arch/sgi/sgi/ip22.h index e6531f9d959..974655933bd 100644 --- a/sys/arch/sgi/sgi/ip22.h +++ b/sys/arch/sgi/sgi/ip22.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ip22.h,v 1.5 2012/05/27 14:13:00 miod Exp $ */ +/* $OpenBSD: ip22.h,v 1.6 2012/05/27 14:27:10 miod Exp $ */ /* * Copyright (c) 2012 Miodrag Vallat. @@ -35,3 +35,7 @@ extern int hpc_old; /* nonzero if at least one HPC 1.x device found */ extern int bios_year; extern int ip22_ecc; /* nonzero if runinng with an ECC memory system */ + +int ip22_fast_mode(void); +int ip22_slow_mode(void); +int ip22_restore_mode(int); diff --git a/sys/arch/sgi/sgi/ip22_machdep.c b/sys/arch/sgi/sgi/ip22_machdep.c index 3a5542d346d..c5c52f89e5b 100644 --- a/sys/arch/sgi/sgi/ip22_machdep.c +++ b/sys/arch/sgi/sgi/ip22_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ip22_machdep.c,v 1.9 2012/05/27 14:13:00 miod Exp $ */ +/* $OpenBSD: ip22_machdep.c,v 1.10 2012/05/27 14:27:10 miod Exp $ */ /* * Copyright (c) 2012 Miodrag Vallat. @@ -56,6 +56,8 @@ int ip22_ecc = 0; void ip22_arcbios_walk(void); int ip22_arcbios_walk_component(arc_config_t *); +void ip22_ecc_halt(int); +void ip22_ecc_init(void); void ip22_memory_setup(void); void ip22_video_setup(void); @@ -467,6 +469,11 @@ ip22_setup() break; } + if (ip22_ecc) { + ip22_ecc_init(); + md_halt = ip22_ecc_halt; + } + /* * Figure out how many TLB entries are available. */ @@ -542,4 +549,117 @@ ip22_post_autoconf() bufhighpages = bufpages; } } + + if (ip22_ecc) { + ip22_fast_mode(); + } +} + +/* + * ECC board specific routines + */ + +#define sync() \ + __asm__ __volatile__ ("sync" ::: "memory"); + +#define ecc_write(o,v) \ + *(volatile uint64_t *)PHYS_TO_XKPHYS(ECC_BASE + (o), CCA_NC) = (v) + +static __inline__ uint32_t ip22_ecc_map(void); +static __inline__ void ip22_ecc_unmap(uint32_t); + +static int ip22_ecc_mode; /* 0 if slow mode, 1 if fast mode */ + +static __inline__ uint32_t +ip22_ecc_map() +{ + uint32_t omemc1, nmemc1; + + omemc1 = imc_read(IMC_MEMCFG1); + nmemc1 = omemc1 & ~IMC_MEMC_BANK_MASK; + nmemc1 |= IMC_MEMC_VALID | (ECC_BASE >> IMC_MEMC_LSHIFT_HUGE); + imc_write(IMC_MEMCFG1, nmemc1); + (void)imc_read(IMC_MEMCFG1); + sync(); + + return omemc1; +} + +static __inline__ void +ip22_ecc_unmap(uint32_t omemc1) +{ + imc_write(IMC_MEMCFG1, omemc1); + (void)imc_read(IMC_MEMCFG1); + sync(); +} + +int +ip22_fast_mode() +{ + uint32_t memc1; + + if (ip22_ecc_mode == 0) { + memc1 = ip22_ecc_map(); + ecc_write(ECC_CTRL, ECC_CTRL_ENABLE); + sync(); + (void)imc_read(IMC_MEMCFG1); + imc_write(IMC_CPU_MEMACC, imc_read(IMC_CPU_MEMACC) & ~2); + ip22_ecc_unmap(memc1); + ip22_ecc_mode = 1; + return 0; + } + + return 1; +} + +int +ip22_slow_mode() +{ + uint32_t memc1; + + if (ip22_ecc_mode != 0) { + memc1 = ip22_ecc_map(); + imc_write(IMC_CPU_MEMACC, imc_read(IMC_CPU_MEMACC) | 2); + ecc_write(ECC_CTRL, ECC_CTRL_DISABLE); + sync(); + (void)imc_read(IMC_MEMCFG1); + ip22_ecc_unmap(memc1); + ip22_ecc_mode = 0; + return 1; + } + + return 0; +} + +int +ip22_restore_mode(int mode) +{ + return mode ? ip22_fast_mode() : ip22_slow_mode(); +} + +void +ip22_ecc_init() +{ + uint32_t memc1; + + memc1 = ip22_ecc_map(); + imc_write(IMC_CPU_MEMACC, imc_read(IMC_CPU_MEMACC) | 2); + ecc_write(ECC_CTRL, ECC_CTRL_DISABLE); + sync(); + (void)imc_read(IMC_MEMCFG1); + ecc_write(ECC_CTRL, ECC_CTRL_INT_CLR); + sync(); + (void)imc_read(IMC_MEMCFG1); + ecc_write(ECC_CTRL, ECC_CTRL_CHK_DISABLE); /* XXX for now */ + sync(); + (void)imc_read(IMC_MEMCFG1); + ip22_ecc_unmap(memc1); + ip22_ecc_mode = 0; +} + +void +ip22_ecc_halt(int howto) +{ + ip22_slow_mode(); + arcbios_halt(howto); } diff --git a/sys/arch/sgi/sgi/machdep.c b/sys/arch/sgi/sgi/machdep.c index ddd67ad2b68..0247d1f44bc 100644 --- a/sys/arch/sgi/sgi/machdep.c +++ b/sys/arch/sgi/sgi/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.123 2012/05/10 21:28:31 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.124 2012/05/27 14:27:10 miod Exp $ */ /* * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -126,7 +126,6 @@ void dumpconf(void); static void dobootopts(int, void *); -void arcbios_halt(int); boolean_t is_memory_range(paddr_t, psize_t, psize_t); void (*md_halt)(int) = arcbios_halt; |