1*c7fb772bSthorpej /* $NetBSD: mongoose.c,v 1.7 2021/08/07 16:18:55 thorpej Exp $ */
26d3ceb1dSskrll
36d3ceb1dSskrll /* $OpenBSD: mongoose.c,v 1.19 2010/01/01 20:28:42 kettenis Exp $ */
46d3ceb1dSskrll
56d3ceb1dSskrll /*
66d3ceb1dSskrll * Copyright (c) 1998-2003 Michael Shalayeff
76d3ceb1dSskrll * All rights reserved.
86d3ceb1dSskrll *
96d3ceb1dSskrll * Redistribution and use in source and binary forms, with or without
106d3ceb1dSskrll * modification, are permitted provided that the following conditions
116d3ceb1dSskrll * are met:
126d3ceb1dSskrll * 1. Redistributions of source code must retain the above copyright
136d3ceb1dSskrll * notice, this list of conditions and the following disclaimer.
146d3ceb1dSskrll * 2. Redistributions in binary form must reproduce the above copyright
156d3ceb1dSskrll * notice, this list of conditions and the following disclaimer in the
166d3ceb1dSskrll * documentation and/or other materials provided with the distribution.
176d3ceb1dSskrll *
186d3ceb1dSskrll * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
196d3ceb1dSskrll * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
206d3ceb1dSskrll * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
216d3ceb1dSskrll * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
226d3ceb1dSskrll * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
236d3ceb1dSskrll * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
246d3ceb1dSskrll * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
256d3ceb1dSskrll * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
266d3ceb1dSskrll * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
276d3ceb1dSskrll * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
286d3ceb1dSskrll * THE POSSIBILITY OF SUCH DAMAGE.
296d3ceb1dSskrll */
306d3ceb1dSskrll
316d3ceb1dSskrll #include <sys/cdefs.h>
32*c7fb772bSthorpej __KERNEL_RCSID(0, "$NetBSD: mongoose.c,v 1.7 2021/08/07 16:18:55 thorpej Exp $");
336d3ceb1dSskrll
346d3ceb1dSskrll #define MONGOOSE_DEBUG 9
356d3ceb1dSskrll
366d3ceb1dSskrll #include <sys/param.h>
376d3ceb1dSskrll #include <sys/systm.h>
386d3ceb1dSskrll #include <sys/device.h>
396d3ceb1dSskrll #include <sys/reboot.h>
406d3ceb1dSskrll
416d3ceb1dSskrll #include <sys/bus.h>
426d3ceb1dSskrll #include <machine/iomod.h>
436d3ceb1dSskrll #include <machine/autoconf.h>
446d3ceb1dSskrll
456d3ceb1dSskrll #include <hppa/dev/cpudevs.h>
466d3ceb1dSskrll #include <hppa/dev/viper.h>
476d3ceb1dSskrll
486d3ceb1dSskrll #include <dev/eisa/eisareg.h>
496d3ceb1dSskrll #include <dev/eisa/eisavar.h>
506d3ceb1dSskrll
516d3ceb1dSskrll #include <dev/isa/isareg.h>
526d3ceb1dSskrll #include <dev/isa/isavar.h>
536d3ceb1dSskrll
546d3ceb1dSskrll /* EISA Bus Adapter registers definitions */
556d3ceb1dSskrll #define MONGOOSE_MONGOOSE 0x10000
566d3ceb1dSskrll struct mongoose_regs {
576d3ceb1dSskrll uint8_t version;
586d3ceb1dSskrll uint8_t lock;
596d3ceb1dSskrll uint8_t liowait;
606d3ceb1dSskrll uint8_t clock;
616d3ceb1dSskrll uint8_t reserved[0xf000 - 4];
626d3ceb1dSskrll uint8_t intack;
636d3ceb1dSskrll };
646d3ceb1dSskrll
656d3ceb1dSskrll #define MONGOOSE_CTRL 0x00000
666d3ceb1dSskrll #define MONGOOSE_NINTS 16
676d3ceb1dSskrll struct mongoose_ctrl {
686d3ceb1dSskrll struct dma0 {
696d3ceb1dSskrll struct {
706d3ceb1dSskrll uint32_t addr : 8;
716d3ceb1dSskrll uint32_t count: 8;
726d3ceb1dSskrll } ch[4];
736d3ceb1dSskrll uint8_t command;
746d3ceb1dSskrll uint8_t request;
756d3ceb1dSskrll uint8_t mask_channel;
766d3ceb1dSskrll uint8_t mode;
776d3ceb1dSskrll uint8_t clr_byte_ptr;
786d3ceb1dSskrll uint8_t master_clear;
796d3ceb1dSskrll uint8_t mask_clear;
806d3ceb1dSskrll uint8_t master_write;
816d3ceb1dSskrll uint8_t pad[8];
826d3ceb1dSskrll } dma0;
836d3ceb1dSskrll
846d3ceb1dSskrll uint8_t irr0; /* 0x20 */
856d3ceb1dSskrll uint8_t imr0;
866d3ceb1dSskrll uint8_t iack; /* 0x22 -- 2 b2b reads generate
876d3ceb1dSskrll (e)isa Iack cycle & returns int level */
886d3ceb1dSskrll uint8_t pad0[29];
896d3ceb1dSskrll
906d3ceb1dSskrll struct timers {
916d3ceb1dSskrll uint8_t sysclk;
926d3ceb1dSskrll uint8_t refresh;
936d3ceb1dSskrll uint8_t spkr;
946d3ceb1dSskrll uint8_t ctrl;
956d3ceb1dSskrll uint32_t pad;
966d3ceb1dSskrll } tmr[2]; /* 0x40 -- timers control */
976d3ceb1dSskrll uint8_t pad1[16];
986d3ceb1dSskrll
996d3ceb1dSskrll uint16_t inmi; /* 0x60 NMI control */
1006d3ceb1dSskrll uint8_t pad2[30];
1016d3ceb1dSskrll struct {
1026d3ceb1dSskrll uint8_t pad0;
1036d3ceb1dSskrll uint8_t ch2;
1046d3ceb1dSskrll uint8_t ch3;
1056d3ceb1dSskrll uint8_t ch1;
1066d3ceb1dSskrll uint8_t pad1;
1076d3ceb1dSskrll uint8_t pad2[3];
1086d3ceb1dSskrll uint8_t ch0;
1096d3ceb1dSskrll uint8_t pad4;
1106d3ceb1dSskrll uint8_t ch6;
1116d3ceb1dSskrll uint8_t ch7;
1126d3ceb1dSskrll uint8_t ch5;
1136d3ceb1dSskrll uint8_t pad5[3];
1146d3ceb1dSskrll uint8_t pad6[16];
1156d3ceb1dSskrll } pr; /* 0x80 */
1166d3ceb1dSskrll
1176d3ceb1dSskrll uint8_t irr1; /* 0xa0 */
1186d3ceb1dSskrll uint8_t imr1;
1196d3ceb1dSskrll uint8_t pad3[30];
1206d3ceb1dSskrll
1216d3ceb1dSskrll struct dma1 {
1226d3ceb1dSskrll struct {
1236d3ceb1dSskrll uint32_t addr : 8;
1246d3ceb1dSskrll uint32_t pad0 : 8;
1256d3ceb1dSskrll uint32_t count: 8;
1266d3ceb1dSskrll uint32_t pad1 : 8;
1276d3ceb1dSskrll } ch[4];
1286d3ceb1dSskrll uint8_t command;
1296d3ceb1dSskrll uint8_t pad0;
1306d3ceb1dSskrll uint8_t request;
1316d3ceb1dSskrll uint8_t pad1;
1326d3ceb1dSskrll uint8_t mask_channel;
1336d3ceb1dSskrll uint8_t pad2;
1346d3ceb1dSskrll uint8_t mode;
1356d3ceb1dSskrll uint8_t pad3;
1366d3ceb1dSskrll uint8_t clr_byte_ptr;
1376d3ceb1dSskrll uint8_t pad4;
1386d3ceb1dSskrll uint8_t master_clear;
1396d3ceb1dSskrll uint8_t pad5;
1406d3ceb1dSskrll uint8_t mask_clear;
1416d3ceb1dSskrll uint8_t pad6;
1426d3ceb1dSskrll uint8_t master_write;
1436d3ceb1dSskrll uint8_t pad7;
1446d3ceb1dSskrll } dma1; /* 0xc0 */
1456d3ceb1dSskrll
1466d3ceb1dSskrll uint8_t master_req; /* 0xe0 master request register */
1476d3ceb1dSskrll uint8_t pad4[31];
1486d3ceb1dSskrll
1496d3ceb1dSskrll uint8_t pad5[0x3d0]; /* 0x4d0 */
1506d3ceb1dSskrll uint8_t pic0; /* 0 - edge, 1 - level */
1516d3ceb1dSskrll uint8_t pic1;
1526d3ceb1dSskrll uint8_t pad6[0x460];
1536d3ceb1dSskrll uint8_t nmi;
1546d3ceb1dSskrll uint8_t nmi_ext;
1556d3ceb1dSskrll #define MONGOOSE_NMI_BUSRESET 0x01
1566d3ceb1dSskrll #define MONGOOSE_NMI_IOPORT_EN 0x02
1576d3ceb1dSskrll #define MONGOOSE_NMI_EN 0x04
1586d3ceb1dSskrll #define MONGOOSE_NMI_MTMO_EN 0x08
1596d3ceb1dSskrll #define MONGOOSE_NMI_RES4 0x10
1606d3ceb1dSskrll #define MONGOOSE_NMI_IOPORT_INT 0x20
1616d3ceb1dSskrll #define MONGOOSE_NMI_MASTER_INT 0x40
1626d3ceb1dSskrll #define MONGOOSE_NMI_INT 0x80
1636d3ceb1dSskrll };
1646d3ceb1dSskrll
1656d3ceb1dSskrll #define MONGOOSE_IOMAP 0x100000
1666d3ceb1dSskrll
1676d3ceb1dSskrll struct hppa_isa_iv {
1686d3ceb1dSskrll int (*iv_handler)(void *arg);
1696d3ceb1dSskrll void *iv_arg;
1706d3ceb1dSskrll int iv_pri;
1716d3ceb1dSskrll
1726d3ceb1dSskrll struct evcnt iv_evcnt;
1736d3ceb1dSskrll /* don't do sharing, we won't have many slots anyway
1746d3ceb1dSskrll struct hppa_isa_iv *iv_next;
1756d3ceb1dSskrll */
1766d3ceb1dSskrll };
1776d3ceb1dSskrll
1786d3ceb1dSskrll struct mongoose_softc {
1796d3ceb1dSskrll device_t sc_dev;
1806d3ceb1dSskrll void *sc_ih;
1816d3ceb1dSskrll
1826d3ceb1dSskrll bus_space_tag_t sc_bt;
1836d3ceb1dSskrll volatile struct mongoose_regs *sc_regs;
1846d3ceb1dSskrll volatile struct mongoose_ctrl *sc_ctrl;
1856d3ceb1dSskrll bus_addr_t sc_iomap;
1866d3ceb1dSskrll
1876d3ceb1dSskrll /* interrupts section */
1886d3ceb1dSskrll struct hppa_eisa_chipset sc_ec;
1896d3ceb1dSskrll struct hppa_isa_chipset sc_ic;
1906d3ceb1dSskrll struct hppa_isa_iv sc_iv[MONGOOSE_NINTS];
1916d3ceb1dSskrll
1926d3ceb1dSskrll /* isa/eisa bus guts */
1936d3ceb1dSskrll struct hppa_bus_space_tag sc_eiot;
1946d3ceb1dSskrll struct hppa_bus_space_tag sc_ememt;
1956d3ceb1dSskrll struct hppa_bus_dma_tag sc_edmat;
1966d3ceb1dSskrll struct hppa_bus_space_tag sc_iiot;
1976d3ceb1dSskrll struct hppa_bus_space_tag sc_imemt;
1986d3ceb1dSskrll struct hppa_bus_dma_tag sc_idmat;
1996d3ceb1dSskrll };
2006d3ceb1dSskrll
2016d3ceb1dSskrll union mongoose_attach_args {
2026d3ceb1dSskrll struct eisabus_attach_args mongoose_eisa;
2036d3ceb1dSskrll struct isabus_attach_args mongoose_isa;
2046d3ceb1dSskrll };
2056d3ceb1dSskrll
2066d3ceb1dSskrll void mg_eisa_attach_hook(device_t, device_t, struct eisabus_attach_args *);
2076d3ceb1dSskrll int mg_intr_map(void *, u_int, eisa_intr_handle_t *);
20826c6de43Schristos const char *mg_intr_string(void *, int, char *, size_t);
2096d3ceb1dSskrll void mg_isa_attach_hook(device_t, device_t, struct isabus_attach_args *);
2106d3ceb1dSskrll void mg_isa_detach_hook(isa_chipset_tag_t, device_t);
2116d3ceb1dSskrll void *mg_intr_establish(void *, int, int, int, int (*)(void *), void *);
2126d3ceb1dSskrll void mg_intr_disestablish(void *, void *);
2136d3ceb1dSskrll int mg_intr_check(void *, int, int);
2146d3ceb1dSskrll int mg_intr(void *);
2156d3ceb1dSskrll int mg_eisa_iomap(void *, bus_addr_t, bus_size_t, int, bus_space_handle_t *);
2166d3ceb1dSskrll int mg_eisa_memmap(void *, bus_addr_t, bus_size_t, int, bus_space_handle_t *);
2176d3ceb1dSskrll void mg_eisa_memunmap(void *, bus_space_handle_t, bus_size_t);
2186d3ceb1dSskrll void mg_isa_barrier(void *, bus_space_handle_t, bus_size_t, bus_size_t, int);
2196d3ceb1dSskrll uint16_t mg_isa_r2(void *, bus_space_handle_t, bus_size_t);
2206d3ceb1dSskrll uint32_t mg_isa_r4(void *, bus_space_handle_t, bus_size_t);
2216d3ceb1dSskrll void mg_isa_w2(void *, bus_space_handle_t, bus_size_t, uint16_t);
2226d3ceb1dSskrll void mg_isa_w4(void *, bus_space_handle_t, bus_size_t, uint32_t);
2236d3ceb1dSskrll void mg_isa_rm_2(void *, bus_space_handle_t, bus_size_t, uint16_t *, bus_size_t);
2246d3ceb1dSskrll void mg_isa_rm_4(void *, bus_space_handle_t, bus_size_t, uint32_t *, bus_size_t);
2256d3ceb1dSskrll void mg_isa_wm_2(void *, bus_space_handle_t, bus_size_t, const uint16_t *, bus_size_t);
2266d3ceb1dSskrll void mg_isa_wm_4(void *, bus_space_handle_t, bus_size_t, const uint32_t *, bus_size_t);
2276d3ceb1dSskrll void mg_isa_sm_2(void *, bus_space_handle_t, bus_size_t, uint16_t, bus_size_t);
2286d3ceb1dSskrll void mg_isa_sm_4(void *, bus_space_handle_t, bus_size_t, uint32_t, bus_size_t);
2296d3ceb1dSskrll void mg_isa_rr_2(void *, bus_space_handle_t, bus_size_t, uint16_t *, bus_size_t);
2306d3ceb1dSskrll void mg_isa_rr_4(void *, bus_space_handle_t, bus_size_t, uint32_t *, bus_size_t);
2316d3ceb1dSskrll void mg_isa_wr_2(void *, bus_space_handle_t, bus_size_t, const uint16_t *, bus_size_t);
2326d3ceb1dSskrll void mg_isa_wr_4(void *, bus_space_handle_t, bus_size_t, const uint32_t *, bus_size_t);
2336d3ceb1dSskrll void mg_isa_sr_2(void *, bus_space_handle_t, bus_size_t, uint16_t, bus_size_t);
2346d3ceb1dSskrll void mg_isa_sr_4(void *, bus_space_handle_t, bus_size_t, uint32_t, bus_size_t);
2356d3ceb1dSskrll
2366d3ceb1dSskrll int mgmatch(device_t, cfdata_t, void *);
2376d3ceb1dSskrll void mgattach(device_t, device_t, void *);
2386d3ceb1dSskrll
2396d3ceb1dSskrll CFATTACH_DECL_NEW(mongoose, sizeof(struct mongoose_softc),
2406d3ceb1dSskrll mgmatch, mgattach, NULL, NULL);
2416d3ceb1dSskrll
2426d3ceb1dSskrll /* TODO: DMA guts */
2436d3ceb1dSskrll
2446d3ceb1dSskrll void
mg_eisa_attach_hook(device_t parent,device_t self,struct eisabus_attach_args * mg)2456d3ceb1dSskrll mg_eisa_attach_hook(device_t parent, device_t self,
2466d3ceb1dSskrll struct eisabus_attach_args *mg)
2476d3ceb1dSskrll {
2486d3ceb1dSskrll }
2496d3ceb1dSskrll
2506d3ceb1dSskrll int
mg_intr_map(void * v,u_int irq,eisa_intr_handle_t * ehp)2516d3ceb1dSskrll mg_intr_map(void *v, u_int irq, eisa_intr_handle_t *ehp)
2526d3ceb1dSskrll {
2536d3ceb1dSskrll *ehp = irq;
2546d3ceb1dSskrll return 0;
2556d3ceb1dSskrll }
2566d3ceb1dSskrll
2576d3ceb1dSskrll const char *
mg_intr_string(void * v,int irq,char * buf,size_t len)25826c6de43Schristos mg_intr_string(void *v, int irq, char *buf, size_t len)
2596d3ceb1dSskrll {
26026c6de43Schristos snprintf (buf, len, "isa irq %d", irq);
2616d3ceb1dSskrll return buf;
2626d3ceb1dSskrll }
2636d3ceb1dSskrll
2646d3ceb1dSskrll void
mg_isa_attach_hook(device_t parent,device_t self,struct isabus_attach_args * iba)2656d3ceb1dSskrll mg_isa_attach_hook(device_t parent, device_t self,
2666d3ceb1dSskrll struct isabus_attach_args *iba)
2676d3ceb1dSskrll {
2686d3ceb1dSskrll
2696d3ceb1dSskrll }
2706d3ceb1dSskrll
2716d3ceb1dSskrll void
mg_isa_detach_hook(isa_chipset_tag_t ic,device_t self)2726d3ceb1dSskrll mg_isa_detach_hook(isa_chipset_tag_t ic, device_t self)
2736d3ceb1dSskrll {
2746d3ceb1dSskrll
2756d3ceb1dSskrll }
2766d3ceb1dSskrll
2776d3ceb1dSskrll void *
mg_intr_establish(void * v,int irq,int type,int pri,int (* handler)(void *),void * arg)2786d3ceb1dSskrll mg_intr_establish(void *v, int irq, int type, int pri,
2796d3ceb1dSskrll int (*handler)(void *), void *arg)
2806d3ceb1dSskrll {
2816d3ceb1dSskrll struct hppa_isa_iv *iv;
2826d3ceb1dSskrll struct mongoose_softc *sc = v;
2836d3ceb1dSskrll volatile uint8_t *imr, *pic;
2846d3ceb1dSskrll
2856d3ceb1dSskrll if (!sc || irq < 0 || irq >= MONGOOSE_NINTS ||
2866d3ceb1dSskrll (0 <= irq && irq < MONGOOSE_NINTS && sc->sc_iv[irq].iv_handler))
2876d3ceb1dSskrll return NULL;
2886d3ceb1dSskrll
2896d3ceb1dSskrll if (type != IST_LEVEL && type != IST_EDGE) {
2906d3ceb1dSskrll aprint_debug_dev(sc->sc_dev, "bad interrupt level (%d)\n",
2916d3ceb1dSskrll type);
2926d3ceb1dSskrll return NULL;
2936d3ceb1dSskrll }
2946d3ceb1dSskrll
2956d3ceb1dSskrll iv = &sc->sc_iv[irq];
2966d3ceb1dSskrll if (iv->iv_handler) {
2976d3ceb1dSskrll aprint_debug_dev(sc->sc_dev, "irq %d already established\n",
2986d3ceb1dSskrll irq);
2996d3ceb1dSskrll return NULL;
3006d3ceb1dSskrll }
3016d3ceb1dSskrll
3026d3ceb1dSskrll iv->iv_pri = pri;
3036d3ceb1dSskrll iv->iv_handler = handler;
3046d3ceb1dSskrll iv->iv_arg = arg;
3056d3ceb1dSskrll
3066d3ceb1dSskrll if (irq < 8) {
3076d3ceb1dSskrll imr = &sc->sc_ctrl->imr0;
3086d3ceb1dSskrll pic = &sc->sc_ctrl->pic0;
3096d3ceb1dSskrll } else {
3106d3ceb1dSskrll imr = &sc->sc_ctrl->imr1;
3116d3ceb1dSskrll pic = &sc->sc_ctrl->pic1;
3126d3ceb1dSskrll irq -= 8;
3136d3ceb1dSskrll }
3146d3ceb1dSskrll
3156d3ceb1dSskrll *imr |= 1 << irq;
3166d3ceb1dSskrll *pic |= (type == IST_LEVEL) << irq;
3176d3ceb1dSskrll
3186d3ceb1dSskrll /* TODO: ack it? */
3196d3ceb1dSskrll
3206d3ceb1dSskrll return iv;
3216d3ceb1dSskrll }
3226d3ceb1dSskrll
3236d3ceb1dSskrll void
mg_intr_disestablish(void * v,void * cookie)3246d3ceb1dSskrll mg_intr_disestablish(void *v, void *cookie)
3256d3ceb1dSskrll {
3266d3ceb1dSskrll struct hppa_isa_iv *iv = cookie;
3276d3ceb1dSskrll struct mongoose_softc *sc = v;
3281155f048Smaya int irq;
3296d3ceb1dSskrll volatile uint8_t *imr;
3306d3ceb1dSskrll
3316d3ceb1dSskrll if (!sc || !cookie)
3326d3ceb1dSskrll return;
3336d3ceb1dSskrll
3341155f048Smaya irq = iv - sc->sc_iv;
3351155f048Smaya
3366d3ceb1dSskrll if (irq < 8)
3376d3ceb1dSskrll imr = &sc->sc_ctrl->imr0;
3386d3ceb1dSskrll else
3396d3ceb1dSskrll imr = &sc->sc_ctrl->imr1;
3406d3ceb1dSskrll *imr &= ~(1 << irq);
3416d3ceb1dSskrll /* TODO: ack it? */
3426d3ceb1dSskrll
3436d3ceb1dSskrll iv->iv_handler = NULL;
3446d3ceb1dSskrll }
3456d3ceb1dSskrll
3466d3ceb1dSskrll int
mg_intr_check(void * v,int irq,int type)3476d3ceb1dSskrll mg_intr_check(void *v, int irq, int type)
3486d3ceb1dSskrll {
3496d3ceb1dSskrll return 0;
3506d3ceb1dSskrll }
3516d3ceb1dSskrll
3526d3ceb1dSskrll int
mg_intr(void * v)3536d3ceb1dSskrll mg_intr(void *v)
3546d3ceb1dSskrll {
3556d3ceb1dSskrll struct mongoose_softc *sc = v;
3566d3ceb1dSskrll struct hppa_isa_iv *iv;
3576d3ceb1dSskrll int s, irq = 0;
3586d3ceb1dSskrll
3596d3ceb1dSskrll iv = &sc->sc_iv[irq];
3606d3ceb1dSskrll s = splraise(iv->iv_pri);
3616d3ceb1dSskrll (iv->iv_handler)(iv->iv_arg);
3626d3ceb1dSskrll splx(s);
3636d3ceb1dSskrll
3646d3ceb1dSskrll return 0;
3656d3ceb1dSskrll }
3666d3ceb1dSskrll
3676d3ceb1dSskrll int
mg_eisa_iomap(void * v,bus_addr_t addr,bus_size_t size,int cacheable,bus_space_handle_t * bshp)3686d3ceb1dSskrll mg_eisa_iomap(void *v, bus_addr_t addr, bus_size_t size, int cacheable,
3696d3ceb1dSskrll bus_space_handle_t *bshp)
3706d3ceb1dSskrll {
3716d3ceb1dSskrll struct mongoose_softc *sc = v;
3726d3ceb1dSskrll
3736d3ceb1dSskrll /* see if it's ISA space we are mapping */
3746d3ceb1dSskrll if (0x100 <= addr && addr < 0x400) {
3756d3ceb1dSskrll #define TOISA(a) ((((a) & 0x3f8) << 9) + ((a) & 7))
3766d3ceb1dSskrll size = TOISA(addr + size) - TOISA(addr);
3776d3ceb1dSskrll addr = TOISA(addr);
3786d3ceb1dSskrll }
3796d3ceb1dSskrll
3806d3ceb1dSskrll return (sc->sc_bt->hbt_map)(NULL, sc->sc_iomap + addr, size,
3816d3ceb1dSskrll cacheable, bshp);
3826d3ceb1dSskrll }
3836d3ceb1dSskrll
3846d3ceb1dSskrll int
mg_eisa_memmap(void * v,bus_addr_t addr,bus_size_t size,int cacheable,bus_space_handle_t * bshp)3856d3ceb1dSskrll mg_eisa_memmap(void *v, bus_addr_t addr, bus_size_t size, int cacheable,
3866d3ceb1dSskrll bus_space_handle_t *bshp)
3876d3ceb1dSskrll {
3886d3ceb1dSskrll /* TODO: eisa memory map */
3896d3ceb1dSskrll return -1;
3906d3ceb1dSskrll }
3916d3ceb1dSskrll
3926d3ceb1dSskrll void
mg_eisa_memunmap(void * v,bus_space_handle_t bsh,bus_size_t size)3936d3ceb1dSskrll mg_eisa_memunmap(void *v, bus_space_handle_t bsh, bus_size_t size)
3946d3ceb1dSskrll {
3956d3ceb1dSskrll /* TODO: eisa memory unmap */
3966d3ceb1dSskrll }
3976d3ceb1dSskrll
3986d3ceb1dSskrll void
mg_isa_barrier(void * v,bus_space_handle_t h,bus_size_t o,bus_size_t l,int op)3996d3ceb1dSskrll mg_isa_barrier(void *v, bus_space_handle_t h, bus_size_t o, bus_size_t l, int op)
4006d3ceb1dSskrll {
4016d3ceb1dSskrll sync_caches();
4026d3ceb1dSskrll }
4036d3ceb1dSskrll
4046d3ceb1dSskrll uint16_t
mg_isa_r2(void * v,bus_space_handle_t h,bus_size_t o)4056d3ceb1dSskrll mg_isa_r2(void *v, bus_space_handle_t h, bus_size_t o)
4066d3ceb1dSskrll {
4076d3ceb1dSskrll uint16_t r = *((volatile uint16_t *)(h + o));
4086d3ceb1dSskrll
4096d3ceb1dSskrll return le16toh(r);
4106d3ceb1dSskrll }
4116d3ceb1dSskrll
4126d3ceb1dSskrll uint32_t
mg_isa_r4(void * v,bus_space_handle_t h,bus_size_t o)4136d3ceb1dSskrll mg_isa_r4(void *v, bus_space_handle_t h, bus_size_t o)
4146d3ceb1dSskrll {
4156d3ceb1dSskrll uint32_t r = *((volatile uint32_t *)(h + o));
4166d3ceb1dSskrll
4176d3ceb1dSskrll return le32toh(r);
4186d3ceb1dSskrll }
4196d3ceb1dSskrll
4206d3ceb1dSskrll void
mg_isa_w2(void * v,bus_space_handle_t h,bus_size_t o,uint16_t vv)4216d3ceb1dSskrll mg_isa_w2(void *v, bus_space_handle_t h, bus_size_t o, uint16_t vv)
4226d3ceb1dSskrll {
4236d3ceb1dSskrll *((volatile uint16_t *)(h + o)) = htole16(vv);
4246d3ceb1dSskrll }
4256d3ceb1dSskrll
4266d3ceb1dSskrll void
mg_isa_w4(void * v,bus_space_handle_t h,bus_size_t o,uint32_t vv)4276d3ceb1dSskrll mg_isa_w4(void *v, bus_space_handle_t h, bus_size_t o, uint32_t vv)
4286d3ceb1dSskrll {
4296d3ceb1dSskrll *((volatile uint32_t *)(h + o)) = htole32(vv);
4306d3ceb1dSskrll }
4316d3ceb1dSskrll
4326d3ceb1dSskrll void
mg_isa_rm_2(void * v,bus_space_handle_t h,bus_size_t o,uint16_t * a,bus_size_t c)4336d3ceb1dSskrll mg_isa_rm_2(void *v, bus_space_handle_t h, bus_size_t o, uint16_t *a, bus_size_t c)
4346d3ceb1dSskrll {
4356d3ceb1dSskrll h += o;
4366d3ceb1dSskrll while (c--)
4376d3ceb1dSskrll *(a++) = le16toh(*(volatile uint16_t *)h);
4386d3ceb1dSskrll }
4396d3ceb1dSskrll
4406d3ceb1dSskrll void
mg_isa_rm_4(void * v,bus_space_handle_t h,bus_size_t o,uint32_t * a,bus_size_t c)4416d3ceb1dSskrll mg_isa_rm_4(void *v, bus_space_handle_t h, bus_size_t o, uint32_t *a, bus_size_t c)
4426d3ceb1dSskrll {
4436d3ceb1dSskrll h += o;
4446d3ceb1dSskrll while (c--)
4456d3ceb1dSskrll *(a++) = le32toh(*(volatile uint32_t *)h);
4466d3ceb1dSskrll }
4476d3ceb1dSskrll
4486d3ceb1dSskrll void
mg_isa_wm_2(void * v,bus_space_handle_t h,bus_size_t o,const uint16_t * a,bus_size_t c)4496d3ceb1dSskrll mg_isa_wm_2(void *v, bus_space_handle_t h, bus_size_t o, const uint16_t *a, bus_size_t c)
4506d3ceb1dSskrll {
4516d3ceb1dSskrll uint16_t r;
4526d3ceb1dSskrll
4536d3ceb1dSskrll h += o;
4546d3ceb1dSskrll while (c--) {
4556d3ceb1dSskrll r = *(a++);
4566d3ceb1dSskrll *(volatile uint16_t *)h = htole16(r);
4576d3ceb1dSskrll }
4586d3ceb1dSskrll }
4596d3ceb1dSskrll
4606d3ceb1dSskrll void
mg_isa_wm_4(void * v,bus_space_handle_t h,bus_size_t o,const uint32_t * a,bus_size_t c)4616d3ceb1dSskrll mg_isa_wm_4(void *v, bus_space_handle_t h, bus_size_t o, const uint32_t *a, bus_size_t c)
4626d3ceb1dSskrll {
4636d3ceb1dSskrll uint32_t r;
4646d3ceb1dSskrll
4656d3ceb1dSskrll h += o;
4666d3ceb1dSskrll while (c--) {
4676d3ceb1dSskrll r = *(a++);
4686d3ceb1dSskrll *(volatile uint32_t *)h = htole32(r);
4696d3ceb1dSskrll }
4706d3ceb1dSskrll }
4716d3ceb1dSskrll
4726d3ceb1dSskrll void
mg_isa_sm_2(void * v,bus_space_handle_t h,bus_size_t o,uint16_t vv,bus_size_t c)4736d3ceb1dSskrll mg_isa_sm_2(void *v, bus_space_handle_t h, bus_size_t o, uint16_t vv, bus_size_t c)
4746d3ceb1dSskrll {
4756d3ceb1dSskrll vv = htole16(vv);
4766d3ceb1dSskrll h += o;
4776d3ceb1dSskrll while (c--)
4786d3ceb1dSskrll *(volatile uint16_t *)h = vv;
4796d3ceb1dSskrll }
4806d3ceb1dSskrll
4816d3ceb1dSskrll void
mg_isa_sm_4(void * v,bus_space_handle_t h,bus_size_t o,uint32_t vv,bus_size_t c)4826d3ceb1dSskrll mg_isa_sm_4(void *v, bus_space_handle_t h, bus_size_t o, uint32_t vv, bus_size_t c)
4836d3ceb1dSskrll {
4846d3ceb1dSskrll vv = htole32(vv);
4856d3ceb1dSskrll h += o;
4866d3ceb1dSskrll while (c--)
4876d3ceb1dSskrll *(volatile uint32_t *)h = vv;
4886d3ceb1dSskrll }
4896d3ceb1dSskrll
4906d3ceb1dSskrll void
mg_isa_rr_2(void * v,bus_space_handle_t h,bus_size_t o,uint16_t * a,bus_size_t c)4916d3ceb1dSskrll mg_isa_rr_2(void *v, bus_space_handle_t h, bus_size_t o, uint16_t *a, bus_size_t c)
4926d3ceb1dSskrll {
4936d3ceb1dSskrll uint16_t r;
4946d3ceb1dSskrll volatile uint16_t *p;
4956d3ceb1dSskrll
4966d3ceb1dSskrll h += o;
4976d3ceb1dSskrll p = (void *)h;
4986d3ceb1dSskrll while (c--) {
4996d3ceb1dSskrll r = *p++;
5006d3ceb1dSskrll *a++ = le16toh(r);
5016d3ceb1dSskrll }
5026d3ceb1dSskrll }
5036d3ceb1dSskrll
5046d3ceb1dSskrll void
mg_isa_rr_4(void * v,bus_space_handle_t h,bus_size_t o,uint32_t * a,bus_size_t c)5056d3ceb1dSskrll mg_isa_rr_4(void *v, bus_space_handle_t h, bus_size_t o, uint32_t *a, bus_size_t c)
5066d3ceb1dSskrll {
5076d3ceb1dSskrll uint32_t r;
5086d3ceb1dSskrll volatile uint32_t *p;
5096d3ceb1dSskrll
5106d3ceb1dSskrll h += o;
5116d3ceb1dSskrll p = (void *)h;
5126d3ceb1dSskrll while (c--) {
5136d3ceb1dSskrll r = *p++;
5146d3ceb1dSskrll *a++ = le32toh(r);
5156d3ceb1dSskrll }
5166d3ceb1dSskrll }
5176d3ceb1dSskrll
5186d3ceb1dSskrll void
mg_isa_wr_2(void * v,bus_space_handle_t h,bus_size_t o,const uint16_t * a,bus_size_t c)5196d3ceb1dSskrll mg_isa_wr_2(void *v, bus_space_handle_t h, bus_size_t o, const uint16_t *a, bus_size_t c)
5206d3ceb1dSskrll {
5216d3ceb1dSskrll uint16_t r;
5226d3ceb1dSskrll volatile uint16_t *p;
5236d3ceb1dSskrll
5246d3ceb1dSskrll h += o;
5256d3ceb1dSskrll p = (void *)h;
5266d3ceb1dSskrll while (c--) {
5276d3ceb1dSskrll r = *a++;
5286d3ceb1dSskrll *p++ = htole16(r);
5296d3ceb1dSskrll }
5306d3ceb1dSskrll }
5316d3ceb1dSskrll
5326d3ceb1dSskrll void
mg_isa_wr_4(void * v,bus_space_handle_t h,bus_size_t o,const uint32_t * a,bus_size_t c)5336d3ceb1dSskrll mg_isa_wr_4(void *v, bus_space_handle_t h, bus_size_t o, const uint32_t *a, bus_size_t c)
5346d3ceb1dSskrll {
5356d3ceb1dSskrll uint32_t r;
5366d3ceb1dSskrll volatile uint32_t *p;
5376d3ceb1dSskrll
5386d3ceb1dSskrll h += o;
5396d3ceb1dSskrll p = (void *)h;
5406d3ceb1dSskrll while (c--) {
5416d3ceb1dSskrll r = *a++;
5426d3ceb1dSskrll *p++ = htole32(r);
5436d3ceb1dSskrll }
5446d3ceb1dSskrll }
5456d3ceb1dSskrll
5466d3ceb1dSskrll void
mg_isa_sr_2(void * v,bus_space_handle_t h,bus_size_t o,uint16_t vv,bus_size_t c)5476d3ceb1dSskrll mg_isa_sr_2(void *v, bus_space_handle_t h, bus_size_t o, uint16_t vv, bus_size_t c)
5486d3ceb1dSskrll {
5496d3ceb1dSskrll volatile uint16_t *p;
5506d3ceb1dSskrll
5516d3ceb1dSskrll vv = htole16(vv);
5526d3ceb1dSskrll h += o;
5536d3ceb1dSskrll p = (void *)h;
5546d3ceb1dSskrll while (c--)
5556d3ceb1dSskrll *p++ = vv;
5566d3ceb1dSskrll }
5576d3ceb1dSskrll
5586d3ceb1dSskrll void
mg_isa_sr_4(void * v,bus_space_handle_t h,bus_size_t o,uint32_t vv,bus_size_t c)5596d3ceb1dSskrll mg_isa_sr_4(void *v, bus_space_handle_t h, bus_size_t o, uint32_t vv, bus_size_t c)
5606d3ceb1dSskrll {
5616d3ceb1dSskrll volatile uint32_t *p;
5626d3ceb1dSskrll
5636d3ceb1dSskrll vv = htole32(vv);
5646d3ceb1dSskrll h += o;
5656d3ceb1dSskrll p = (void *)h;
5666d3ceb1dSskrll while (c--)
5676d3ceb1dSskrll *p++ = vv;
5686d3ceb1dSskrll }
5696d3ceb1dSskrll
5706d3ceb1dSskrll int
mgmatch(device_t parent,cfdata_t cf,void * aux)5716d3ceb1dSskrll mgmatch(device_t parent, cfdata_t cf, void *aux)
5726d3ceb1dSskrll {
5736d3ceb1dSskrll struct confargs *ca = aux;
5746d3ceb1dSskrll bus_space_handle_t ioh;
5756d3ceb1dSskrll
5766d3ceb1dSskrll if (ca->ca_type.iodc_type != HPPA_TYPE_BHA ||
5776d3ceb1dSskrll ca->ca_type.iodc_sv_model != HPPA_BHA_EISA)
5786d3ceb1dSskrll return 0;
5796d3ceb1dSskrll
5806d3ceb1dSskrll if (bus_space_map(ca->ca_iot, ca->ca_hpa + MONGOOSE_MONGOOSE,
5816d3ceb1dSskrll sizeof(struct mongoose_regs), 0, &ioh))
5826d3ceb1dSskrll return 0;
5836d3ceb1dSskrll
5846d3ceb1dSskrll /* XXX check EISA signature */
5856d3ceb1dSskrll
5866d3ceb1dSskrll bus_space_unmap(ca->ca_iot, ioh, sizeof(struct mongoose_regs));
5876d3ceb1dSskrll
5886d3ceb1dSskrll return 1;
5896d3ceb1dSskrll }
5906d3ceb1dSskrll
5916d3ceb1dSskrll void
mgattach(device_t parent,device_t self,void * aux)5926d3ceb1dSskrll mgattach(device_t parent, device_t self, void *aux)
5936d3ceb1dSskrll {
5946d3ceb1dSskrll struct confargs *ca = aux;
5956d3ceb1dSskrll struct mongoose_softc *sc = device_private(self);
5966d3ceb1dSskrll struct cpu_info *ci = &cpus[0];
5976d3ceb1dSskrll struct hppa_bus_space_tag *bt;
5986d3ceb1dSskrll union mongoose_attach_args ea;
5996d3ceb1dSskrll char brid[EISA_IDSTRINGLEN];
6006d3ceb1dSskrll bus_space_handle_t ioh;
6016d3ceb1dSskrll
6026d3ceb1dSskrll sc->sc_dev = self;
6036d3ceb1dSskrll sc->sc_bt = ca->ca_iot;
6046d3ceb1dSskrll sc->sc_iomap = ca->ca_hpa;
6056d3ceb1dSskrll if (bus_space_map(ca->ca_iot, ca->ca_hpa + MONGOOSE_MONGOOSE,
6066d3ceb1dSskrll sizeof(struct mongoose_regs), 0, &ioh)) {
6076d3ceb1dSskrll aprint_error(": can't map registers\n");
6086d3ceb1dSskrll return;
6096d3ceb1dSskrll }
6106d3ceb1dSskrll sc->sc_regs = (struct mongoose_regs *)ioh;
6116d3ceb1dSskrll
6126d3ceb1dSskrll if (bus_space_map(ca->ca_iot, ca->ca_hpa + MONGOOSE_CTRL,
6136d3ceb1dSskrll sizeof(struct mongoose_ctrl), 0, &ioh)) {
6146d3ceb1dSskrll aprint_error(": can't map control registers\n");
6156d3ceb1dSskrll bus_space_unmap(ca->ca_iot, (bus_space_handle_t)sc->sc_regs,
6166d3ceb1dSskrll sizeof(struct mongoose_regs));
6176d3ceb1dSskrll return;
6186d3ceb1dSskrll }
6196d3ceb1dSskrll
6206d3ceb1dSskrll ca->ca_irq = hppa_intr_allocate_bit(&ci->ci_ir, ca->ca_irq);
6216d3ceb1dSskrll if (ca->ca_irq == HPPACF_IRQ_UNDEF) {
6226d3ceb1dSskrll aprint_error(": can't allocate interrupt\n");
6236d3ceb1dSskrll return;
6246d3ceb1dSskrll }
6256d3ceb1dSskrll
6266d3ceb1dSskrll sc->sc_ctrl = (struct mongoose_ctrl *)ioh;
6276d3ceb1dSskrll
6286d3ceb1dSskrll viper_eisa_en();
6296d3ceb1dSskrll
6306d3ceb1dSskrll /* BUS RESET */
6316d3ceb1dSskrll sc->sc_ctrl->nmi_ext = MONGOOSE_NMI_BUSRESET;
6326d3ceb1dSskrll DELAY(1);
6336d3ceb1dSskrll sc->sc_ctrl->nmi_ext = 0;
6346d3ceb1dSskrll DELAY(100);
6356d3ceb1dSskrll
6366d3ceb1dSskrll /* determine eisa board id */
6376d3ceb1dSskrll {
6386d3ceb1dSskrll uint8_t id[4], *p;
6396d3ceb1dSskrll /* XXX this is awful */
6406d3ceb1dSskrll p = (uint8_t *)(ioh + EISA_SLOTOFF_VID);
6416d3ceb1dSskrll id[0] = *p++;
6426d3ceb1dSskrll id[1] = *p++;
6436d3ceb1dSskrll id[2] = *p++;
6446d3ceb1dSskrll id[3] = *p++;
6456d3ceb1dSskrll
6466d3ceb1dSskrll brid[0] = EISA_VENDID_0(id);
6476d3ceb1dSskrll brid[1] = EISA_VENDID_1(id);
6486d3ceb1dSskrll brid[2] = EISA_VENDID_2(id);
6496d3ceb1dSskrll brid[3] = EISA_PRODID_0(id + 2);
6506d3ceb1dSskrll brid[4] = EISA_PRODID_1(id + 2);
6516d3ceb1dSskrll brid[5] = EISA_PRODID_2(id + 2);
6526d3ceb1dSskrll brid[6] = EISA_PRODID_3(id + 2);
6536d3ceb1dSskrll brid[7] = '\0';
6546d3ceb1dSskrll }
6556d3ceb1dSskrll
6566d3ceb1dSskrll aprint_normal(": %s rev %d, %d MHz\n", brid, sc->sc_regs->version,
6576d3ceb1dSskrll (sc->sc_regs->clock? 33 : 25));
6586d3ceb1dSskrll sc->sc_regs->liowait = 1; /* disable isa wait states */
6596d3ceb1dSskrll sc->sc_regs->lock = 1; /* bus unlock */
6606d3ceb1dSskrll
6616d3ceb1dSskrll /* attach EISA */
6626d3ceb1dSskrll sc->sc_ec.ec_v = sc;
6636d3ceb1dSskrll sc->sc_ec.ec_attach_hook = mg_eisa_attach_hook;
6646d3ceb1dSskrll sc->sc_ec.ec_intr_establish = mg_intr_establish;
6656d3ceb1dSskrll sc->sc_ec.ec_intr_disestablish = mg_intr_disestablish;
6666d3ceb1dSskrll sc->sc_ec.ec_intr_string = mg_intr_string;
6676d3ceb1dSskrll sc->sc_ec.ec_intr_map = mg_intr_map;
6686d3ceb1dSskrll
6696d3ceb1dSskrll /* inherit the bus tags for eisa from the mainbus */
6706d3ceb1dSskrll bt = &sc->sc_eiot;
6716d3ceb1dSskrll memcpy(bt, ca->ca_iot, sizeof(*bt));
6726d3ceb1dSskrll bt->hbt_cookie = sc;
6736d3ceb1dSskrll bt->hbt_map = mg_eisa_iomap;
6746d3ceb1dSskrll #define R(n) bt->__CONCAT(hbt_,n) = &__CONCAT(mg_isa_,n)
6756d3ceb1dSskrll /* R(barrier); */
6766d3ceb1dSskrll R(r2); R(r4); R(w2); R(w4);
6776d3ceb1dSskrll R(rm_2);R(rm_4);R(wm_2);R(wm_4);R(sm_2);R(sm_4);
6786d3ceb1dSskrll R(rr_2);R(rr_4);R(wr_2);R(wr_4);R(sr_2);R(sr_4);
6796d3ceb1dSskrll
6806d3ceb1dSskrll bt = &sc->sc_ememt;
6816d3ceb1dSskrll memcpy(bt, ca->ca_iot, sizeof(*bt));
6826d3ceb1dSskrll bt->hbt_cookie = sc;
6836d3ceb1dSskrll bt->hbt_map = mg_eisa_memmap;
6846d3ceb1dSskrll bt->hbt_unmap = mg_eisa_memunmap;
6856d3ceb1dSskrll
6866d3ceb1dSskrll /* attachment guts */
6876d3ceb1dSskrll ea.mongoose_eisa.eba_iot = &sc->sc_eiot;
6886d3ceb1dSskrll ea.mongoose_eisa.eba_memt = &sc->sc_ememt;
6896d3ceb1dSskrll ea.mongoose_eisa.eba_dmat = NULL /* &sc->sc_edmat */;
6906d3ceb1dSskrll ea.mongoose_eisa.eba_ec = &sc->sc_ec;
6912685996bSthorpej config_found(self, &ea.mongoose_eisa, eisabusprint,
692*c7fb772bSthorpej CFARGS(.iattr = "eisabus"));
6936d3ceb1dSskrll
6946d3ceb1dSskrll sc->sc_ic.ic_v = sc;
6956d3ceb1dSskrll sc->sc_ic.ic_attach_hook = mg_isa_attach_hook;
6966d3ceb1dSskrll sc->sc_ic.ic_detach_hook = mg_isa_detach_hook;
6976d3ceb1dSskrll sc->sc_ic.ic_intr_establish = mg_intr_establish;
6986d3ceb1dSskrll sc->sc_ic.ic_intr_disestablish = mg_intr_disestablish;
6996d3ceb1dSskrll sc->sc_ic.ic_intr_check = mg_intr_check;
7006d3ceb1dSskrll
7016d3ceb1dSskrll /* inherit the bus tags for isa from the eisa */
7026d3ceb1dSskrll bt = &sc->sc_imemt;
7036d3ceb1dSskrll memcpy(bt, &sc->sc_ememt, sizeof(*bt));
7046d3ceb1dSskrll bt = &sc->sc_iiot;
7056d3ceb1dSskrll memcpy(bt, &sc->sc_eiot, sizeof(*bt));
7066d3ceb1dSskrll
7076d3ceb1dSskrll /* TODO: DMA tags */
7086d3ceb1dSskrll
7096d3ceb1dSskrll /* attachment guts */
7106d3ceb1dSskrll ea.mongoose_isa.iba_iot = &sc->sc_iiot;
7116d3ceb1dSskrll ea.mongoose_isa.iba_memt = &sc->sc_imemt;
7126d3ceb1dSskrll #if NISADMA > 0
7136d3ceb1dSskrll ea.mongoose_isa.iba_dmat = &sc->sc_idmat;
7146d3ceb1dSskrll #endif
7156d3ceb1dSskrll ea.mongoose_isa.iba_ic = &sc->sc_ic;
7162685996bSthorpej config_found(self, &ea.mongoose_isa, isabusprint,
717*c7fb772bSthorpej CFARGS(.iattr = "isabus"));
7186d3ceb1dSskrll #undef R
7196d3ceb1dSskrll
7206d3ceb1dSskrll /* attach interrupt */
7216d3ceb1dSskrll sc->sc_ih = hppa_intr_establish(IPL_NONE, mg_intr, sc, &ci->ci_ir,
7226d3ceb1dSskrll ca->ca_irq);
7236d3ceb1dSskrll }
724