diff options
Diffstat (limited to 'sys/arch/hppa')
-rw-r--r-- | sys/arch/hppa/dev/apic.c | 211 | ||||
-rw-r--r-- | sys/arch/hppa/dev/elroy.c | 1180 | ||||
-rw-r--r-- | sys/arch/hppa/dev/elroyreg.h | 148 | ||||
-rw-r--r-- | sys/arch/hppa/dev/elroyvar.h | 50 |
4 files changed, 1589 insertions, 0 deletions
diff --git a/sys/arch/hppa/dev/apic.c b/sys/arch/hppa/dev/apic.c new file mode 100644 index 00000000000..032afe8cbda --- /dev/null +++ b/sys/arch/hppa/dev/apic.c @@ -0,0 +1,211 @@ +/* $OpenBSD: apic.c,v 1.1 2007/05/21 22:43:38 kettenis Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * Copyright (c) 2007 Mark Kettenis + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/malloc.h> + +#include <machine/autoconf.h> +#include <machine/pdc.h> + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcidevs.h> + +#include <hppa/dev/elroyreg.h> +#include <hppa/dev/elroyvar.h> + +struct apic_iv { + struct elroy_softc *sc; + pci_intr_handle_t ih; + int (*handler)(void *); + void *arg; + struct apic_iv *next; +}; + +struct apic_iv *apic_intr_list[CPU_NINTS]; + +#ifdef DEBUG +void apic_dump(struct elroy_softc *); +#endif + +void +apic_write(volatile struct elroy_regs *r, u_int32_t reg, u_int32_t val) +{ + elroy_write32(&r->apic_addr, htole32(reg)); + elroy_write32(&r->apic_data, htole32(val)); + elroy_read32(&r->apic_data); +} + +u_int32_t +apic_read(volatile struct elroy_regs *r, u_int32_t reg) +{ + elroy_write32(&r->apic_addr, htole32(reg)); + return letoh32(elroy_read32(&r->apic_data)); +} + +void +apic_attach(struct elroy_softc *sc) +{ + volatile struct elroy_regs *r = sc->sc_regs; + u_int32_t data; + + data = apic_read(r, APIC_VERSION); + sc->sc_nints = (data & APIC_VERSION_NENT) >> APIC_VERSION_NENT_SHIFT; + printf(" APIC ver %x, %d pins", + data & APIC_VERSION_MASK, sc->sc_nints); + +#ifdef DEBUG + apic_dump(sc); +#endif +} + +int +apic_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp) +{ + pci_chipset_tag_t pc = pa->pa_pc; + pcitag_t tag = pa->pa_tag; + pcireg_t reg; + + reg = pci_conf_read(pc, tag, PCI_INTERRUPT_REG); +#ifdef DEBUG + printf(" pin=%d line=%d ", PCI_INTERRUPT_PIN(reg), + PCI_INTERRUPT_LINE(reg)); +#endif + *ihp = PCI_INTERRUPT_LINE(reg) + 1; + return (*ihp == 0); +} + +const char * +apic_intr_string(void *v, pci_intr_handle_t ih) +{ + static char buf[32]; + + snprintf(buf, 32, "irq %ld", (ih + 8 - 1)); + + return (buf); +} + +void * +apic_intr_establish(void *v, pci_intr_handle_t ih, + int pri, int (*handler)(void *), void *arg, char *name) +{ + struct elroy_softc *sc = v; + volatile struct elroy_regs *r = sc->sc_regs; + hppa_hpa_t hpa = cpu_gethpa(0); + u_int32_t ent0; + struct apic_iv *aiv, *biv; + void *iv; + + /* no mapping or bogus */ + if (ih <= 0 || ih > 31) + return (NULL); + + aiv = malloc(sizeof(struct apic_iv), M_DEVBUF, M_NOWAIT); + if (aiv == NULL) + return NULL; + + aiv->sc = sc; + aiv->ih = ih; + aiv->handler = handler; + aiv->arg = arg; + aiv->next = NULL; + if (apic_intr_list[(ih + 8 - 1)]) { + biv = apic_intr_list[(ih + 8 - 1)]; + while (biv->next) + biv = biv->next; + biv->next = aiv; + return (arg); + } + + if ((iv = cpu_intr_establish(pri, (ih + 8 - 1), apic_intr, aiv, name))) { + ent0 = (31 - (ih + 8 - 1)) & APIC_ENT0_VEC; + ent0 |= APIC_ENT0_LOW; + ent0 |= APIC_ENT0_LEV; +#if 0 + if (cold) { + sc->sc_imr |= (1 << (ih + 8 - 1)); + ent0 |= APIC_ENT0_MASK; + } +#endif + apic_write(sc->sc_regs, APIC_ENT0(ih - 1), APIC_ENT0_MASK); + apic_write(sc->sc_regs, APIC_ENT1(ih - 1), + ((hpa & 0x0ff00000) >> 4) | ((hpa & 0x000ff000) << 12)); + apic_write(sc->sc_regs, APIC_ENT0(ih - 1), ent0); + + elroy_write32(&r->apic_eoi, htole32((31 - (ih + 8 - 1)) & APIC_ENT0_VEC)); + + apic_intr_list[(ih + 8 - 1)] = aiv; + } + + return (arg); +} + +void +apic_intr_disestablish(void *v, void *cookie) +{ +} + +int +apic_intr(void *v) +{ + struct apic_iv *iv = v; + struct elroy_softc *sc = iv->sc; + volatile struct elroy_regs *r = sc->sc_regs; + int claimed = 0; + + while (iv) { + claimed |= iv->handler(iv->arg); + iv = iv->next; + } + + elroy_write32(&r->apic_eoi, htole32((31 - (iv->ih + 8 - 1)) & APIC_ENT0_VEC)); + + return (claimed); +} + +#ifdef DEBUG +void +apic_dump(struct elroy_softc *sc) +{ + struct pdc_pat_io_num int_tbl_sz PDC_ALIGNMENT; + struct pdc_pat_pci_rt int_tbl[5] PDC_ALIGNMENT; + int i; + + for (i = 0; i < sc->sc_nints; i++) + printf("0x%04x 0x%04x\n", apic_read(sc->sc_regs, APIC_ENT0(i)), + apic_read(sc->sc_regs, APIC_ENT1(i))); + + if (pdc_call((iodcio_t)pdc, 0, PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL_SZ, + &int_tbl_sz, 0, 0, 0, 0, 0)) + printf("pdc_call failed\n"); + printf("int_tbl_sz=%d\n", int_tbl_sz.num); + + if (pdc_call((iodcio_t)pdc, 0, PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL, + &int_tbl_sz, 0, &int_tbl, 0, 0, 0)) + printf("pdc_call failed\n"); + for (i = 0; i < 5; i++) { + printf("type=%x, len=%d ", int_tbl[i].type, int_tbl[i].len); + printf("itype=%d, trigger=%x ", int_tbl[i].itype, int_tbl[i].trigger); + printf("pin=%x, bus=%d ", int_tbl[i].pin, int_tbl[i].bus); + printf("line=%d, addr=%x\n", int_tbl[i].line, int_tbl[i].addr); + } +} +#endif diff --git a/sys/arch/hppa/dev/elroy.c b/sys/arch/hppa/dev/elroy.c new file mode 100644 index 00000000000..94dc261df6b --- /dev/null +++ b/sys/arch/hppa/dev/elroy.c @@ -0,0 +1,1180 @@ +/* $OpenBSD: elroy.c,v 1.1 2007/05/21 22:43:38 kettenis Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "cardbus.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/device.h> +#include <sys/reboot.h> +#include <sys/malloc.h> +#include <sys/extent.h> + +#include <machine/iomod.h> +#include <machine/autoconf.h> + +#include <arch/hppa/dev/cpudevs.h> + +#if NCARDBUS > 0 +#include <dev/cardbus/rbus.h> +#endif + +#include <dev/pci/pcireg.h> +#include <dev/pci/pcivar.h> +#include <dev/pci/pcidevs.h> + +#include <hppa/dev/elroyreg.h> +#include <hppa/dev/elroyvar.h> + +#define ELROY_MEM_CHUNK 0x800000 +#define ELROY_MEM_WINDOW (2 * ELROY_MEM_CHUNK) + +int elroy_match(struct device *, void *, void *); +void elroy_attach(struct device *, struct device *, void *); +int elroy_intr(void *); + +struct cfattach elroy_ca = { + sizeof(struct elroy_softc), elroy_match, elroy_attach +}; + +struct cfdriver elroy_cd = { + NULL, "elroy", DV_DULL +}; + +int +elroy_match(struct device *parent, void *cfdata, void *aux) +{ + struct confargs *ca = aux; + /* struct cfdata *cf = cfdata; */ + + if ((ca->ca_name && !strcmp(ca->ca_name, "lba")) || + (ca->ca_type.iodc_type == HPPA_TYPE_BRIDGE && + ca->ca_type.iodc_sv_model == HPPA_BRIDGE_DINO && + ca->ca_type.iodc_model == 0x78)) + return (1); + + return (0); +} + +void +elroy_write32(volatile u_int32_t *p, u_int32_t v) +{ + *p = v; +} + +u_int32_t +elroy_read32(volatile u_int32_t *p) +{ + return *p; +} + +void +elroy_attach_hook(struct device *parent, struct device *self, + struct pcibus_attach_args *pba) +{ + +} + +int +elroy_maxdevs(void *v, int bus) +{ + return (32); +} + +pcitag_t +elroy_make_tag(void *v, int bus, int dev, int func) +{ + if (bus > 255 || dev > 31 || func > 7) + panic("elroy_make_tag: bad request"); + + return ((bus << 16) | (dev << 11) | (func << 8)); +} + +void +elroy_decompose_tag(void *v, pcitag_t tag, int *bus, int *dev, int *func) +{ + *bus = (tag >> 16) & 0xff; + *dev = (tag >> 11) & 0x1f; + *func= (tag >> 8) & 0x07; +} + +pcireg_t +elroy_conf_read(void *v, pcitag_t tag, int reg) +{ + struct elroy_softc *sc = v; + volatile struct elroy_regs *r = sc->sc_regs; + u_int32_t arb_mask, err_cfg, control; + pcireg_t data, data1; + +/* printf("elroy_conf_read(%p, 0x%08x, 0x%x)", v, tag, reg); */ + arb_mask = elroy_read32(&r->arb_mask); + err_cfg = elroy_read32(&r->err_cfg); + control = elroy_read32(&r->control); + if (!arb_mask) + elroy_write32(&r->arb_mask, htole64(ELROY_ARB_ENABLE)); + elroy_write32(&r->err_cfg, err_cfg | + htole32(ELROY_ERRCFG_SMART | ELROY_ERRCFG_CM)); + elroy_write32(&r->control, (control | htole32(ELROY_CONTROL_CE)) & + ~htole32(ELROY_CONTROL_HF)); + + elroy_write32(&r->pci_conf_addr, htole32(tag | reg)); + data1 = elroy_read32(&r->pci_conf_addr); + data = elroy_read32(&r->pci_conf_data); + + elroy_write32(&r->control, control | + htole32(ELROY_CONTROL_CE|ELROY_CONTROL_CL)); + elroy_write32(&r->control, control); + elroy_write32(&r->err_cfg, err_cfg); + if (!arb_mask) + elroy_write32(&r->arb_mask, arb_mask); + + data = letoh32(data); +/* printf("=0x%08x (@ 0x%08x)\n", data, letoh32(data1)); */ + return (data); +} + +void +elroy_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data) +{ + struct elroy_softc *sc = v; + volatile struct elroy_regs *r = sc->sc_regs; + u_int32_t arb_mask, err_cfg, control; + pcireg_t data1; + +/* printf("elroy_conf_write(%p, 0x%08x, 0x%x, 0x%x)\n", v, tag, reg, data); */ + arb_mask = elroy_read32(&r->arb_mask); + err_cfg = elroy_read32(&r->err_cfg); + control = elroy_read32(&r->control); + if (!arb_mask) + elroy_write32(&r->arb_mask, htole64(ELROY_ARB_ENABLE)); + elroy_write32(&r->err_cfg, err_cfg | + htole32(ELROY_ERRCFG_SMART | ELROY_ERRCFG_CM)); + elroy_write32(&r->control, (control | htole32(ELROY_CONTROL_CE)) & + ~htole32(ELROY_CONTROL_HF)); + + /* fix coalescing config writes errata by interleaving w/ a read */ + elroy_write32(&r->pci_conf_addr, htole32(tag | PCI_ID_REG)); + data1 = elroy_read32(&r->pci_conf_addr); + data1 = elroy_read32(&r->pci_conf_data); + + elroy_write32(&r->pci_conf_addr, htole32(tag | reg)); + data1 = elroy_read32(&r->pci_conf_addr); + elroy_write32(&r->pci_conf_data, htole32(data)); + data1 = elroy_read32(&r->pci_conf_addr); + + elroy_write32(&r->control, control | + htole32(ELROY_CONTROL_CE|ELROY_CONTROL_CL)); + elroy_write32(&r->control, control); + elroy_write32(&r->err_cfg, err_cfg); + if (!arb_mask) + elroy_write32(&r->arb_mask, arb_mask); +} + +int +elroy_iomap(void *v, bus_addr_t bpa, bus_size_t size, + int flags, bus_space_handle_t *bshp) +{ + struct elroy_softc *sc = v; + /* volatile struct elroy_regs *r = sc->sc_regs; */ + int error; + + if ((error = bus_space_map(sc->sc_bt, bpa + sc->sc_iobase, size, + flags, bshp))) + return (error); + + return (0); +} + +int +elroy_memmap(void *v, bus_addr_t bpa, bus_size_t size, + int flags, bus_space_handle_t *bshp) +{ + struct elroy_softc *sc = v; + /* volatile struct elroy_regs *r = sc->sc_regs; */ + int error; + + if ((error = bus_space_map(sc->sc_bt, bpa, size, flags, bshp))) + return (error); + + return (0); +} + +int +elroy_subregion(void *v, bus_space_handle_t bsh, bus_size_t offset, + bus_size_t size, bus_space_handle_t *nbshp) +{ + *nbshp = bsh + offset; + return (0); +} + +int +elroy_ioalloc(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size, + bus_size_t align, bus_size_t boundary, int flags, bus_addr_t *addrp, + bus_space_handle_t *bshp) +{ + struct elroy_softc *sc = v; + volatile struct elroy_regs *r = sc->sc_regs; + bus_addr_t iostart, ioend; + + iostart = r->io_base & ~htole32(ELROY_BASE_RE); + ioend = iostart + ~htole32(r->io_mask) + 1; + if (rstart < iostart || rend > ioend) + panic("elroy_ioalloc: bad region start/end"); + + rstart += sc->sc_iobase; + rend += sc->sc_iobase; + if (bus_space_alloc(sc->sc_bt, rstart, rend, size, + align, boundary, flags, addrp, bshp)) + return (ENOMEM); + + return (0); +} + +int +elroy_memalloc(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size, + bus_size_t align, bus_size_t boundary, int flags, bus_addr_t *addrp, + bus_space_handle_t *bshp) +{ + struct elroy_softc *sc = v; + /* volatile struct elroy_regs *r = sc->sc_regs; */ + + if (bus_space_alloc(sc->sc_bt, rstart, rend, size, + align, boundary, flags, addrp, bshp)) + return (ENOMEM); + + return (0); +} + +void +elroy_unmap(void *v, bus_space_handle_t bsh, bus_size_t size) +{ + struct elroy_softc *sc = v; + + bus_space_free(sc->sc_bt, bsh, size); +} + +void +elroy_free(void *v, bus_space_handle_t bh, bus_size_t size) +{ + /* should be enough */ + elroy_unmap(v, bh, size); +} + +void +elroy_barrier(void *v, bus_space_handle_t h, bus_size_t o, bus_size_t l, int op) +{ + struct elroy_softc *sc = v; + volatile struct elroy_regs *r = sc->sc_regs; + u_int32_t data; + + sync_caches(); + if (op & BUS_SPACE_BARRIER_WRITE) { + data = r->pci_id; /* flush write fifo */ + sync_caches(); + } +} + +#if NCARDBUS > 0 +void * +elroy_alloc_parent(struct device *self, struct pci_attach_args *pa, int io) +{ +#if 0 /* TODO */ + + struct elroy_softc *sc = pa->pa_pc->_cookie; + struct extent *ex; + bus_space_tag_t tag; + bus_addr_t start; + bus_size_t size; + + if (io) { + ex = sc->sc_ioex; + tag = pa->pa_iot; + start = 0xa000; + size = 0x1000; + } else { + if (!sc->sc_memex) { + bus_space_handle_t memh; + bus_addr_t mem_start; + + if (elroy_memalloc(sc, 0xf0800000, 0xff7fffff, + ELROY_MEM_WINDOW, ELROY_MEM_WINDOW, EX_NOBOUNDARY, + 0, &mem_start, &memh)) + return (NULL); + + snprintf(sc->sc_memexname, sizeof(sc->sc_memexname), + "%s_mem", sc->sc_dv.dv_xname); + if ((sc->sc_memex = extent_create(sc->sc_memexname, + mem_start, mem_start + ELROY_MEM_WINDOW, M_DEVBUF, + NULL, 0, EX_NOWAIT | EX_MALLOCOK)) == NULL) { + extent_destroy(sc->sc_ioex); + bus_space_free(sc->sc_bt, memh, + ELROY_MEM_WINDOW); + return (NULL); + } + } + ex = sc->sc_memex; + tag = pa->pa_memt; + start = ex->ex_start; + size = ELROY_MEM_CHUNK; + } + + if (extent_alloc_subregion(ex, start, ex->ex_end, size, size, 0, + EX_NOBOUNDARY, EX_NOWAIT, &start)) + return (NULL); + + extent_free(ex, start, size, EX_NOWAIT); + return rbus_new_root_share(tag, ex, start, size, 0); +#else + return (NULL); +#endif +} +#endif + +u_int8_t +elroy_r1(void *v, bus_space_handle_t h, bus_size_t o) +{ + h += o; + return *(volatile u_int8_t *)h; +} + +u_int16_t +elroy_r2(void *v, bus_space_handle_t h, bus_size_t o) +{ + volatile u_int16_t *p; + + h += o; + p = (volatile u_int16_t *)h; + return (letoh16(*p)); +} + +u_int32_t +elroy_r4(void *v, bus_space_handle_t h, bus_size_t o) +{ + u_int32_t data; + + h += o; + data = *(volatile u_int32_t *)h; + return (letoh32(data)); +} + +u_int64_t +elroy_r8(void *v, bus_space_handle_t h, bus_size_t o) +{ + u_int64_t data; + + h += o; + data = *(volatile u_int64_t *)h; + return (letoh64(data)); +} + +void +elroy_w1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv) +{ + h += o; + *(volatile u_int8_t *)h = vv; +} + +void +elroy_w2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv) +{ + volatile u_int16_t *p; + + h += o; + p = (volatile u_int16_t *)h; + *p = htole16(vv); +} + +void +elroy_w4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv) +{ + h += o; + vv = htole32(vv); + *(volatile u_int32_t *)h = vv; +} + +void +elroy_w8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv) +{ + h += o; + *(volatile u_int64_t *)h = htole64(vv); +} + + +void +elroy_rm_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t *a, bus_size_t c) +{ + volatile u_int8_t *p; + + h += o; + p = (volatile u_int8_t *)h; + while (c--) + *a++ = *p; +} + +void +elroy_rm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c) +{ + volatile u_int16_t *p; + + h += o; + p = (volatile u_int16_t *)h; + while (c--) + *a++ = letoh16(*p); +} + +void +elroy_rm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c) +{ + volatile u_int32_t *p; + + h += o; + p = (volatile u_int32_t *)h; + while (c--) + *a++ = letoh32(*p); +} + +void +elroy_rm_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t *a, bus_size_t c) +{ + volatile u_int64_t *p; + + h += o; + p = (volatile u_int64_t *)h; + while (c--) + *a++ = letoh64(*p); +} + +void +elroy_wm_1(void *v, bus_space_handle_t h, bus_size_t o, const u_int8_t *a, bus_size_t c) +{ + volatile u_int8_t *p; + + h += o; + p = (volatile u_int8_t *)h; + while (c--) + *p = *a++; +} + +void +elroy_wm_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c) +{ + volatile u_int16_t *p; + + h += o; + p = (volatile u_int16_t *)h; + while (c--) + *p = htole16(*a++); +} + +void +elroy_wm_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c) +{ + volatile u_int32_t *p; + + h += o; + p = (volatile u_int32_t *)h; + while (c--) + *p = htole32(*a++); +} + +void +elroy_wm_8(void *v, bus_space_handle_t h, bus_size_t o, const u_int64_t *a, bus_size_t c) +{ + volatile u_int64_t *p; + + h += o; + p = (volatile u_int64_t *)h; + while (c--) + *p = htole64(*a++); +} + +void +elroy_sm_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv, bus_size_t c) +{ + volatile u_int8_t *p; + + h += o; + p = (volatile u_int8_t *)h; + while (c--) + *p = vv; +} + +void +elroy_sm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c) +{ + volatile u_int16_t *p; + + h += o; + p = (volatile u_int16_t *)h; + vv = htole16(vv); + while (c--) + *p = vv; +} + +void +elroy_sm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c) +{ + volatile u_int32_t *p; + + h += o; + p = (volatile u_int32_t *)h; + vv = htole32(vv); + while (c--) + *p = vv; +} + +void +elroy_sm_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv, bus_size_t c) +{ + volatile u_int64_t *p; + + h += o; + p = (volatile u_int64_t *)h; + vv = htole64(vv); + while (c--) + *p = vv; +} + +void +elroy_rrm_2(void *v, bus_space_handle_t h, bus_size_t o, + u_int8_t *a, bus_size_t c) +{ + volatile u_int16_t *p, *q = (u_int16_t *)a; + + h += o; + p = (volatile u_int16_t *)h; + c /= 2; + while (c--) + *q++ = *p; +} + +void +elroy_rrm_4(void *v, bus_space_handle_t h, bus_size_t o, + u_int8_t *a, bus_size_t c) +{ + volatile u_int32_t *p, *q = (u_int32_t *)a; + + h += o; + p = (volatile u_int32_t *)h; + c /= 4; + while (c--) + *q++ = *p; +} + +void +elroy_rrm_8(void *v, bus_space_handle_t h, bus_size_t o, + u_int8_t *a, bus_size_t c) +{ + volatile u_int64_t *p, *q = (u_int64_t *)a; + + h += o; + p = (volatile u_int64_t *)h; + c /= 8; + while (c--) + *q++ = *p; +} + +void +elroy_wrm_2(void *v, bus_space_handle_t h, bus_size_t o, + const u_int8_t *a, bus_size_t c) +{ + volatile u_int16_t *p; + const u_int16_t *q = (const u_int16_t *)a; + + h += o; + p = (volatile u_int16_t *)h; + c /= 2; + while (c--) + *p = *q++; +} + +void +elroy_wrm_4(void *v, bus_space_handle_t h, bus_size_t o, + const u_int8_t *a, bus_size_t c) +{ + volatile u_int32_t *p; + const u_int32_t *q = (const u_int32_t *)a; + + h += o; + p = (volatile u_int32_t *)h; + c /= 4; + while (c--) + *p = *q++; +} + +void +elroy_wrm_8(void *v, bus_space_handle_t h, bus_size_t o, + const u_int8_t *a, bus_size_t c) +{ + volatile u_int64_t *p; + const u_int64_t *q = (const u_int64_t *)a; + + h += o; + p = (volatile u_int64_t *)h; + c /= 8; + while (c--) + *p = *q++; +} + +void +elroy_rr_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t *a, bus_size_t c) +{ + volatile u_int8_t *p; + + h += o; + p = (volatile u_int8_t *)h; + while (c--) + *a++ = *p++; +} + +void +elroy_rr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c) +{ + volatile u_int16_t *p, data; + + h += o; + p = (volatile u_int16_t *)h; + while (c--) { + data = *p++; + *a++ = letoh16(data); + } +} + +void +elroy_rr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c) +{ + volatile u_int32_t *p, data; + + h += o; + p = (volatile u_int32_t *)h; + while (c--) { + data = *p++; + *a++ = letoh32(data); + } +} + +void +elroy_rr_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t *a, bus_size_t c) +{ + volatile u_int64_t *p, data; + + h += o; + p = (volatile u_int64_t *)h; + while (c--) { + data = *p++; + *a++ = letoh64(data); + } +} + +void +elroy_wr_1(void *v, bus_space_handle_t h, bus_size_t o, const u_int8_t *a, bus_size_t c) +{ + volatile u_int8_t *p; + + h += o; + p = (volatile u_int8_t *)h; + while (c--) + *p++ = *a++; +} + +void +elroy_wr_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c) +{ + volatile u_int16_t *p, data; + + h += o; + p = (volatile u_int16_t *)h; + while (c--) { + data = *a++; + *p++ = htole16(data); + } +} + +void +elroy_wr_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c) +{ + volatile u_int32_t *p, data; + + h += o; + p = (volatile u_int32_t *)h; + while (c--) { + data = *a++; + *p++ = htole32(data); + } +} + +void +elroy_wr_8(void *v, bus_space_handle_t h, bus_size_t o, const u_int64_t *a, bus_size_t c) +{ + volatile u_int64_t *p, data; + + h += o; + p = (volatile u_int64_t *)h; + while (c--) { + data = *a++; + *p++ = htole64(data); + } +} + +void +elroy_rrr_2(void *v, bus_space_handle_t h, bus_size_t o, + u_int8_t *a, bus_size_t c) +{ + volatile u_int16_t *p, *q = (u_int16_t *)a; + + c /= 2; + h += o; + p = (volatile u_int16_t *)h; + while (c--) + *q++ = *p++; +} + +void +elroy_rrr_4(void *v, bus_space_handle_t h, bus_size_t o, + u_int8_t *a, bus_size_t c) +{ + volatile u_int32_t *p, *q = (u_int32_t *)a; + + c /= 4; + h += o; + p = (volatile u_int32_t *)h; + while (c--) + *q++ = *p++; +} + +void +elroy_rrr_8(void *v, bus_space_handle_t h, bus_size_t o, + u_int8_t *a, bus_size_t c) +{ + volatile u_int64_t *p, *q = (u_int64_t *)a; + + c /= 8; + h += o; + p = (volatile u_int64_t *)h; + while (c--) + *q++ = *p++; +} + +void +elroy_wrr_2(void *v, bus_space_handle_t h, bus_size_t o, + const u_int8_t *a, bus_size_t c) +{ + volatile u_int16_t *p; + const u_int16_t *q = (u_int16_t *)a; + + c /= 2; + h += o; + p = (volatile u_int16_t *)h; + while (c--) + *p++ = *q++; +} + +void +elroy_wrr_4(void *v, bus_space_handle_t h, bus_size_t o, + const u_int8_t *a, bus_size_t c) +{ + volatile u_int32_t *p; + const u_int32_t *q = (u_int32_t *)a; + + c /= 4; + h += o; + p = (volatile u_int32_t *)h; + while (c--) + *p++ = *q++; +} + +void +elroy_wrr_8(void *v, bus_space_handle_t h, bus_size_t o, + const u_int8_t *a, bus_size_t c) +{ + volatile u_int64_t *p; + const u_int64_t *q = (u_int64_t *)a; + + c /= 8; + h += o; + p = (volatile u_int64_t *)h; + while (c--) + *p++ = *q++; +} + +void +elroy_sr_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv, bus_size_t c) +{ + volatile u_int8_t *p; + + h += o; + p = (volatile u_int8_t *)h; + while (c--) + *p++ = vv; +} + +void +elroy_sr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c) +{ + volatile u_int16_t *p; + + h += o; + vv = htole16(vv); + p = (volatile u_int16_t *)h; + while (c--) + *p++ = vv; +} + +void +elroy_sr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c) +{ + volatile u_int32_t *p; + + h += o; + vv = htole32(vv); + p = (volatile u_int32_t *)h; + while (c--) + *p++ = vv; +} + +void +elroy_sr_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv, bus_size_t c) +{ + volatile u_int64_t *p; + + h += o; + vv = htole64(vv); + p = (volatile u_int64_t *)h; + while (c--) + *p++ = vv; +} + +void +elroy_cp_1(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + while (c--) + elroy_w1(v, h1, o1++, elroy_r1(v, h2, o2++)); +} + +void +elroy_cp_2(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + while (c--) { + elroy_w2(v, h1, o1, elroy_r2(v, h2, o2)); + o1 += 2; + o2 += 2; + } +} + +void +elroy_cp_4(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + while (c--) { + elroy_w4(v, h1, o1, elroy_r4(v, h2, o2)); + o1 += 4; + o2 += 4; + } +} + +void +elroy_cp_8(void *v, bus_space_handle_t h1, bus_size_t o1, + bus_space_handle_t h2, bus_size_t o2, bus_size_t c) +{ + while (c--) { + elroy_w8(v, h1, o1, elroy_r8(v, h2, o2)); + o1 += 8; + o2 += 8; + } +} + +const struct hppa_bus_space_tag elroy_iomemt = { + NULL, + + NULL, elroy_unmap, elroy_subregion, NULL, elroy_free, + elroy_barrier, + elroy_r1, elroy_r2, elroy_r4, elroy_r8, + elroy_w1, elroy_w2, elroy_w4, elroy_w8, + elroy_rm_1, elroy_rm_2, elroy_rm_4, elroy_rm_8, + elroy_wm_1, elroy_wm_2, elroy_wm_4, elroy_wm_8, + elroy_sm_1, elroy_sm_2, elroy_sm_4, elroy_sm_8, + elroy_rrm_2, elroy_rrm_4, elroy_rrm_8, + elroy_wrm_2, elroy_wrm_4, elroy_wrm_8, + elroy_rr_1, elroy_rr_2, elroy_rr_4, elroy_rr_8, + elroy_wr_1, elroy_wr_2, elroy_wr_4, elroy_wr_8, + elroy_rrr_2, elroy_rrr_4, elroy_rrr_8, + elroy_wrr_2, elroy_wrr_4, elroy_wrr_8, + elroy_sr_1, elroy_sr_2, elroy_sr_4, elroy_sr_8, + elroy_cp_1, elroy_cp_2, elroy_cp_4, elroy_cp_8 +}; + +int +elroy_dmamap_create(void *v, bus_size_t size, int nsegments, + bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp) +{ + struct elroy_softc *sc = v; + + /* TODO check the addresses, boundary, enable dma */ + + return (bus_dmamap_create(sc->sc_dmat, size, nsegments, + maxsegsz, boundary, flags, dmamp)); +} + +void +elroy_dmamap_destroy(void *v, bus_dmamap_t map) +{ + struct elroy_softc *sc = v; + + bus_dmamap_destroy(sc->sc_dmat, map); +} + +int +elroy_dmamap_load(void *v, bus_dmamap_t map, void *addr, bus_size_t size, + struct proc *p, int flags) +{ + struct elroy_softc *sc = v; + + return (bus_dmamap_load(sc->sc_dmat, map, addr, size, p, flags)); +} + +int +elroy_dmamap_load_mbuf(void *v, bus_dmamap_t map, struct mbuf *m, int flags) +{ + struct elroy_softc *sc = v; + + return (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, flags)); +} + +int +elroy_dmamap_load_uio(void *v, bus_dmamap_t map, struct uio *uio, int flags) +{ + struct elroy_softc *sc = v; + + return (bus_dmamap_load_uio(sc->sc_dmat, map, uio, flags)); +} + +int +elroy_dmamap_load_raw(void *v, bus_dmamap_t map, bus_dma_segment_t *segs, + int nsegs, bus_size_t size, int flags) +{ + struct elroy_softc *sc = v; + + return (bus_dmamap_load_raw(sc->sc_dmat, map, segs, nsegs, size, flags)); +} + +void +elroy_dmamap_unload(void *v, bus_dmamap_t map) +{ + struct elroy_softc *sc = v; + + bus_dmamap_unload(sc->sc_dmat, map); +} + +void +elroy_dmamap_sync(void *v, bus_dmamap_t map, bus_addr_t off, + bus_size_t len, int ops) +{ + struct elroy_softc *sc = v; + + bus_dmamap_sync(sc->sc_dmat, map, off, len, ops); +} + +int +elroy_dmamem_alloc(void *v, bus_size_t size, bus_size_t alignment, + bus_size_t boundary, bus_dma_segment_t *segs, + int nsegs, int *rsegs, int flags) +{ + struct elroy_softc *sc = v; + + return (bus_dmamem_alloc(sc->sc_dmat, size, alignment, boundary, + segs, nsegs, rsegs, flags)); +} + +void +elroy_dmamem_free(void *v, bus_dma_segment_t *segs, int nsegs) +{ + struct elroy_softc *sc = v; + + bus_dmamem_free(sc->sc_dmat, segs, nsegs); +} + +int +elroy_dmamem_map(void *v, bus_dma_segment_t *segs, int nsegs, size_t size, + caddr_t *kvap, int flags) +{ + struct elroy_softc *sc = v; + + return (bus_dmamem_map(sc->sc_dmat, segs, nsegs, size, kvap, flags)); +} + +void +elroy_dmamem_unmap(void *v, caddr_t kva, size_t size) +{ + struct elroy_softc *sc = v; + + bus_dmamem_unmap(sc->sc_dmat, kva, size); +} + +paddr_t +elroy_dmamem_mmap(void *v, bus_dma_segment_t *segs, int nsegs, off_t off, + int prot, int flags) +{ + struct elroy_softc *sc = v; + + return (bus_dmamem_mmap(sc->sc_dmat, segs, nsegs, off, prot, flags)); +} + +const struct hppa_bus_dma_tag elroy_dmat = { + NULL, + elroy_dmamap_create, elroy_dmamap_destroy, + elroy_dmamap_load, elroy_dmamap_load_mbuf, + elroy_dmamap_load_uio, elroy_dmamap_load_raw, + elroy_dmamap_unload, elroy_dmamap_sync, + + elroy_dmamem_alloc, elroy_dmamem_free, elroy_dmamem_map, + elroy_dmamem_unmap, elroy_dmamem_mmap +}; + +const struct hppa_pci_chipset_tag elroy_pc = { + NULL, + elroy_attach_hook, elroy_maxdevs, elroy_make_tag, elroy_decompose_tag, + elroy_conf_read, elroy_conf_write, + apic_intr_map, apic_intr_string, + apic_intr_establish, apic_intr_disestablish, +#if NCARDBUS > 0 + elroy_alloc_parent +#else + NULL +#endif +}; + +int +elroy_print(void *aux, const char *pnp) +{ + struct pcibus_attach_args *pba = aux; + + if (pnp) + printf("%s at %s\n", pba->pba_busname, pnp); + return (UNCONF); +} + +void +elroy_attach(struct device *parent, struct device *self, void *aux) +{ + struct elroy_softc *sc = (struct elroy_softc *)self; + struct confargs *ca = (struct confargs *)aux; + struct pcibus_attach_args pba; + volatile struct elroy_regs *r; + const char *p = NULL, *q; + int i; + + sc->sc_bt = ca->ca_iot; + sc->sc_dmat = ca->ca_dmatag; + if (bus_space_map(sc->sc_bt, ca->ca_hpa, ca->ca_hpasz, 0, &sc->sc_bh)) { + printf(": can't map space\n"); + return; + } + + sc->sc_regs = r = (void *)bus_space_vaddr(sc->sc_bt, sc->sc_bh); + elroy_write32(&r->pci_cmdstat, htole32(PCI_COMMAND_IO_ENABLE | + PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE)); + + elroy_write32(&r->control, elroy_read32(&r->control) & + ~htole32(ELROY_CONTROL_RF)); + for (i = 5000; i-- && + elroy_read32(&r->status) & htole32(ELROY_STATUS_RC); DELAY(10)); + if (i < 0) { + printf(": reset failed; status %b\n", + ELROY_STATUS_BITS, htole32(r->status)); + return; + } + + q = ""; + sc->sc_ver = PCI_REVISION(letoh32(elroy_read32(&r->pci_class))); + switch ((ca->ca_type.iodc_model << 4) | + (ca->ca_type.iodc_revision >> 4)) { + case 0x782: + p = "Elroy"; + switch (sc->sc_ver) { + default: + q = "+"; + case 5: sc->sc_ver = 0x40; break; + case 4: sc->sc_ver = 0x30; break; + case 3: sc->sc_ver = 0x22; break; + case 2: sc->sc_ver = 0x21; break; + case 1: sc->sc_ver = 0x20; break; + case 0: sc->sc_ver = 0x10; break; + } + break; + + case 0x783: + p = "Mercury"; + break; + + case 0x784: + p = "Quicksilver"; + break; + + default: + p = "Mojo"; + break; + } + + printf(": %s TR%d.%d%s", p, sc->sc_ver >> 4, sc->sc_ver & 0xf, q); + apic_attach(sc); + printf("\n"); + + elroy_write32(&r->imask, htole32(0xffffffff << 30)); + elroy_write32(&r->ibase, htole32(ELROY_BASE_RE)); + + /* TODO reserve elroy's pci space ? */ + +#if 0 +printf("lmm %llx/%llx gmm %llx/%llx wlm %llx/%llx wgm %llx/%llx io %llx/%llx eio %llx/%llx\n", +letoh64(r->lmmio_base), letoh64(r->lmmio_mask), +letoh64(r->gmmio_base), letoh64(r->gmmio_mask), +letoh64(r->wlmmio_base), letoh64(r->wlmmio_mask), +letoh64(r->wgmmio_base), letoh64(r->wgmmio_mask), +letoh64(r->io_base), letoh64(r->io_mask), +letoh64(r->eio_base), letoh64(r->eio_mask)); +#endif + + /* XXX evil hack! */ + sc->sc_iobase = 0xfee00000; + + sc->sc_iot = elroy_iomemt; + sc->sc_iot.hbt_cookie = sc; + sc->sc_iot.hbt_map = elroy_iomap; + sc->sc_iot.hbt_alloc = elroy_ioalloc; + sc->sc_memt = elroy_iomemt; + sc->sc_memt.hbt_cookie = sc; + sc->sc_memt.hbt_map = elroy_memmap; + sc->sc_memt.hbt_alloc = elroy_memalloc; + sc->sc_pc = elroy_pc; + sc->sc_pc._cookie = sc; + sc->sc_dmatag = elroy_dmat; + sc->sc_dmatag._cookie = sc; + + pba.pba_busname = "pci"; + pba.pba_iot = &sc->sc_iot; + pba.pba_memt = &sc->sc_memt; + pba.pba_dmat = &sc->sc_dmatag; + pba.pba_pc = &sc->sc_pc; + pba.pba_bridgetag = NULL; + pba.pba_domain = pci_ndomains++; + pba.pba_bus = 0; /* (letoh32(elroy_read32(&r->busnum)) & 0xff) >> 4; */ + config_found(self, &pba, elroy_print); +} diff --git a/sys/arch/hppa/dev/elroyreg.h b/sys/arch/hppa/dev/elroyreg.h new file mode 100644 index 00000000000..ed28e9fb0f9 --- /dev/null +++ b/sys/arch/hppa/dev/elroyreg.h @@ -0,0 +1,148 @@ +/* $OpenBSD: elroyreg.h,v 1.1 2007/05/21 22:43:38 kettenis Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct elroy_regs { + /* std PCI bridge header */ + u_int32_t pci_id; /* 0x000 rw PCI_ID */ + u_int32_t pci_cmdstat; /* 0x004 rw PCI_COMMAND_STATUS_REG */ + u_int32_t pci_class; /* 0x008 ro PCI_CLASS_REG */ + u_int32_t pci_bhlc; /* 0x00c rw PCI_BHLC_REG */ + u_int32_t res0[0x30/4]; /* 0x010 */ + + /* HW Bridge registers */ + u_int32_t pci_conf_addr; /* 0x040 rw config space address */ + u_int32_t pad040; + u_int32_t pci_conf_data; /* 0x048 rw config space data */ + u_int32_t pad048; + u_int64_t elroy_mtlt; /* 0x050 */ + u_int32_t busnum; /* 0x058 bus number/scratch */ + u_int32_t par058; + u_int64_t res1; /* 0x060 */ + u_int64_t rope; /* 0x068 rope parity, loopback */ + u_int64_t err_addr; /* 0x070 error log: address */ + u_int64_t suspend; /* 0x078 rw suspend control */ + u_int32_t arb_mask; /* 0x080 rw arbitration mask */ + u_int32_t pad080; +#define ELROY_ARB_ENABLE 0x01 /* enable arbitration */ +#define ELROY_ARB_PCIDEVA 0x02 /* PCI device A allow */ +#define ELROY_ARB_PCIDEVB 0x04 /* PCI device A allow */ +#define ELROY_ARB_PCIDEVC 0x08 /* PCI device A allow */ +#define ELROY_ARB_PCIDEVD 0x10 /* PCI device A allow */ +#define ELROY_ARB_PCIDEVE 0x20 /* PCI device A allow */ +#define ELROY_ARB_PCIDEVF 0x40 /* PCI device A allow */ +#define ELROY_ARB_PCIDEVG 0x80 /* PCI device A allow */ + u_int64_t arb_pri; /* 0x088 arbitration priority */ + u_int64_t arb_mode; /* 0x090 arbitration mode */ + u_int64_t mtlt; /* 0x098 */ + u_int64_t res2[12]; /* 0x0a0 */ + u_int64_t mod_info; /* 0x100 */ + u_int32_t control; /* 0x108 */ +#define ELROY_CONTROL_RF 0x01 /* reset pci */ +#define ELROY_CONTROL_VE 0x08 /* VGA enable */ +#define ELROY_CONTROL_CL 0x10 /* clear error log */ +#define ELROY_CONTROL_CE 0x20 /* clear error log enable */ +#define ELROY_CONTROL_HF 0x40 /* hard fail enable */ + u_int32_t status; /* 0x10c */ +#define ELROY_STATUS_RC 0x01 /* reset complete */ +#define ELROY_STATUS_BITS "\020\01RC" + u_int64_t res3[30]; /* 0x110 */ + u_int64_t lmmio_base; /* 0x200 */ + u_int64_t lmmio_mask; /* 0x208 */ + u_int64_t gmmio_base; /* 0x210 */ + u_int64_t gmmio_mask; /* 0x218 */ + u_int64_t wlmmio_base; /* 0x220 */ + u_int64_t wlmmio_mask; /* 0x228 */ + u_int64_t wgmmio_base; /* 0x230 */ + u_int64_t wgmmio_mask; /* 0x238 */ + u_int32_t io_base; /* 0x240 */ + u_int32_t pad240; + u_int32_t io_mask; /* 0x248 */ + u_int32_t pad248; + u_int32_t res4[4]; /* 0x250 */ + u_int32_t eio_base; /* 0x260 */ + u_int32_t pad260; + u_int32_t eio_mask; /* 0x268 */ + u_int32_t pad268; +#define ELROY_BASE_RE 0x01 /* range enable */ + u_int64_t res5; /* 0x270 */ + u_int64_t dmac_ctrl; /* 0x278 DMA connection control */ + u_int64_t res6[16]; /* 0x280 */ + u_int32_t ibase; /* 0x300 */ + u_int32_t pad300; + u_int32_t imask; /* 0x308 */ + u_int32_t pad308; + u_int64_t hint_cfg; /* 0x310 */ + u_int64_t res7[13]; /* 0x318 */ + u_int64_t hints[14]; /* 0x380 */ + u_int64_t res8[2]; /* 0x3f0 */ + u_int64_t res9[64]; /* 0x400 */ + u_int64_t pad0; /* 0x600 */ + u_int64_t pci_drive; /* 0x608 */ + u_int64_t rope_cfg; /* 0x610 */ + u_int64_t clk_ctl; /* 0x618 */ + u_int32_t pad1; /* 0x620 */ + u_int32_t res10[23]; /* 0x624 */ + u_int32_t err_cfg; /* 0x680 error config */ + u_int32_t pad680; +#define ELROY_ERRCFG_PW 0x01 /* PIO writes parity errors */ +#define ELROY_ERRCFG_PR 0x02 /* PIO reads parity errors */ +#define ELROY_ERRCFG_DW 0x04 /* DMA writes parity errors */ +#define ELROY_ERRCFG_DR 0x08 /* DMA reads parity errors */ +#define ELROY_ERRCFG_CM 0x10 /* no fatal on config space */ +#define ELROY_ERRCFG_SMART 0x20 /* smart bus mode */ + u_int64_t err_stat; /* 0x688 error status */ + u_int64_t err_mid; /* 0x690 error log: master id */ + u_int64_t rope_estat; /* 0x698 rope error status */ + u_int64_t rope_eclr; /* 0x6a0 rope error clear */ + u_int64_t res11[42]; /* 0x6a8 */ + u_int64_t regbus; /* 0x7f8 reads 0x3ff */ + u_int32_t apic_addr; /* 0x800 APIC address register */ + u_int32_t pad800; + u_int64_t res12; + u_int32_t apic_data; /* 0x810 APIC data register */ + u_int32_t pad808; + u_int64_t res13[5]; + u_int32_t apic_eoi; /* 0x840 APIC interrupt ack */ + u_int32_t pad840; + u_int32_t apic_softint; /* 0x850 write generates softint */ + u_int32_t pad850; + u_int64_t res14[123]; /* 0x858 */ + /*0x1000 */ +} __packed; + +/* APIC registers */ +#define APIC_VERSION 0x01 +#define APIC_VERSION_MASK 0xff +#define APIC_VERSION_NENT 0xff0000 +#define APIC_VERSION_NENT_SHIFT 16 +#define APIC_ENT0(i) (0x10 + (i)*2) +#define APIC_ENT0_VEC 0x000ff +#define APIC_ENT0_MOD 0x00700 /* delivery mode */ +#define APIC_ENT0_FXD 0x00000 +#define APIC_ENT0_RDR 0x00100 +#define APIC_ENT0_PMI 0x00200 +#define APIC_ENT0_NMI 0x00400 +#define APIC_ENT0_INI 0x00500 +#define APIC_ENT0_EXT 0x00700 +#define APIC_ENT0_PEND 0x01000 /* int is pending */ +#define APIC_ENT0_LOW 0x02000 /* polarity */ +#define APIC_ENT0_LEV 0x08000 /* edge/level */ +#define APIC_ENT0_MASK 0x10000 /* mask int */ +#define APIC_ENT1(i) (0x11 + (i)*2) + diff --git a/sys/arch/hppa/dev/elroyvar.h b/sys/arch/hppa/dev/elroyvar.h new file mode 100644 index 00000000000..48b2f74d7b1 --- /dev/null +++ b/sys/arch/hppa/dev/elroyvar.h @@ -0,0 +1,50 @@ +/* $OpenBSD: elroyvar.h,v 1.1 2007/05/21 22:43:38 kettenis Exp $ */ + +/* + * Copyright (c) 2005 Michael Shalayeff + * All rights reserved. + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN + * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT + * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +struct elroy_softc { + struct device sc_dv; + + int sc_ver; + bus_space_tag_t sc_bt; + bus_space_handle_t sc_bh; + bus_dma_tag_t sc_dmat; + volatile struct elroy_regs *sc_regs; + bus_addr_t sc_iobase; + + u_int32_t sc_imr; + int sc_nints; + + struct hppa_pci_chipset_tag sc_pc; + struct hppa_bus_space_tag sc_iot; + struct hppa_bus_space_tag sc_memt; + char sc_memexname[20]; + struct extent *sc_memex; + struct hppa_bus_dma_tag sc_dmatag; +}; + +void apic_attach(struct elroy_softc *sc); +int apic_intr(void *v); +int apic_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp); +const char *apic_intr_string(void *v, pci_intr_handle_t ih); +void *apic_intr_establish(void *v, pci_intr_handle_t ih, int pri, + int (*handler)(void *), void *arg, char *name); +void apic_intr_disestablish(void *v, void *cookie); + +void elroy_write32(volatile u_int32_t *p, u_int32_t v); +u_int32_t elroy_read32(volatile u_int32_t *p); |