1 /* $NetBSD: mongoose.c,v 1.16 2009/08/19 15:13:24 dyoung Exp $ */
3 /* $OpenBSD: mongoose.c,v 1.7 2000/08/15 19:42:56 mickey Exp $ */
6 * Copyright (c) 1998-2003 Michael Shalayeff
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGE.
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: mongoose.c,v 1.16 2009/08/19 15:13:24 dyoung Exp $");
34 #define MONGOOSE_DEBUG 9
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/device.h>
39 #include <sys/reboot.h>
41 #include <machine/bus.h>
42 #include <machine/iomod.h>
43 #include <machine/autoconf.h>
45 #include <hp700/hp700/intr.h>
46 #include <hp700/dev/cpudevs.h>
47 #include <hp700/dev/viper.h>
49 #include <dev/eisa/eisareg.h>
50 #include <dev/eisa/eisavar.h>
52 #include <dev/isa/isareg.h>
53 #include <dev/isa/isavar.h>
55 /* EISA Bus Adapter registers definitions */
56 #define MONGOOSE_MONGOOSE 0x10000
57 struct mongoose_regs
{
62 uint8_t reserved
[0xf000 - 4];
66 #define MONGOOSE_CTRL 0x00000
67 #define MONGOOSE_NINTS 16
68 struct mongoose_ctrl
{
85 uint8_t irr0
; /* 0x20 */
87 uint8_t iack
; /* 0x22 -- 2 b2b reads generate
88 (e)isa Iack cycle & returns int level */
97 } tmr
[2]; /* 0x40 -- timers control */
100 uint16_t inmi
; /* 0x60 NMI control */
118 uint8_t irr1
; /* 0xa0 */
133 uint8_t mask_channel
;
137 uint8_t clr_byte_ptr
;
139 uint8_t master_clear
;
143 uint8_t master_write
;
147 uint8_t master_req
; /* 0xe0 master request register */
150 uint8_t pad5
[0x3d0]; /* 0x4d0 */
151 uint8_t pic0
; /* 0 - edge, 1 - level */
156 #define MONGOOSE_NMI_BUSRESET 0x01
157 #define MONGOOSE_NMI_IOPORT_EN 0x02
158 #define MONGOOSE_NMI_EN 0x04
159 #define MONGOOSE_NMI_MTMO_EN 0x08
160 #define MONGOOSE_NMI_RES4 0x10
161 #define MONGOOSE_NMI_IOPORT_INT 0x20
162 #define MONGOOSE_NMI_MASTER_INT 0x40
163 #define MONGOOSE_NMI_INT 0x80
166 #define MONGOOSE_IOMAP 0x100000
169 int (*iv_handler
)(void *arg
);
173 struct evcnt iv_evcnt
;
174 /* don't do sharing, we won't have many slots anyway
175 struct hppa_isa_iv *iv_next;
179 struct mongoose_softc
{
183 bus_space_tag_t sc_bt
;
184 volatile struct mongoose_regs
*sc_regs
;
185 volatile struct mongoose_ctrl
*sc_ctrl
;
188 /* interrupts section */
189 struct hppa_eisa_chipset sc_ec
;
190 struct hppa_isa_chipset sc_ic
;
191 struct hppa_isa_iv sc_iv
[MONGOOSE_NINTS
];
193 /* isa/eisa bus guts */
194 struct hppa_bus_space_tag sc_eiot
;
195 struct hppa_bus_space_tag sc_ememt
;
196 struct hppa_bus_dma_tag sc_edmat
;
197 struct hppa_bus_space_tag sc_iiot
;
198 struct hppa_bus_space_tag sc_imemt
;
199 struct hppa_bus_dma_tag sc_idmat
;
202 union mongoose_attach_args
{
203 struct eisabus_attach_args mongoose_eisa
;
204 struct isabus_attach_args mongoose_isa
;
207 void mg_eisa_attach_hook(device_t
, device_t
, struct eisabus_attach_args
*);
208 int mg_intr_map(void *, u_int
, eisa_intr_handle_t
*);
209 const char *mg_intr_string(void *, int);
210 void mg_isa_attach_hook(device_t
, device_t
, struct isabus_attach_args
*);
211 void mg_isa_detach_hook(isa_chipset_tag_t
, device_t
);
212 void *mg_intr_establish(void *, int, int, int, int (*)(void *), void *);
213 void mg_intr_disestablish(void *, void *);
214 int mg_intr_check(void *, int, int);
216 int mg_eisa_iomap(void *, bus_addr_t
, bus_size_t
, int, bus_space_handle_t
*);
217 int mg_eisa_memmap(void *, bus_addr_t
, bus_size_t
, int, bus_space_handle_t
*);
218 void mg_eisa_memunmap(void *, bus_space_handle_t
, bus_size_t
);
219 void mg_isa_barrier(void *, bus_space_handle_t
, bus_size_t
, bus_size_t
, int);
220 uint16_t mg_isa_r2(void *, bus_space_handle_t
, bus_size_t
);
221 uint32_t mg_isa_r4(void *, bus_space_handle_t
, bus_size_t
);
222 void mg_isa_w2(void *, bus_space_handle_t
, bus_size_t
, uint16_t);
223 void mg_isa_w4(void *, bus_space_handle_t
, bus_size_t
, uint32_t);
224 void mg_isa_rm_2(void *, bus_space_handle_t
, bus_size_t
, uint16_t *, bus_size_t
);
225 void mg_isa_rm_4(void *, bus_space_handle_t
, bus_size_t
, uint32_t *, bus_size_t
);
226 void mg_isa_wm_2(void *, bus_space_handle_t
, bus_size_t
, const uint16_t *, bus_size_t
);
227 void mg_isa_wm_4(void *, bus_space_handle_t
, bus_size_t
, const uint32_t *, bus_size_t
);
228 void mg_isa_sm_2(void *, bus_space_handle_t
, bus_size_t
, uint16_t, bus_size_t
);
229 void mg_isa_sm_4(void *, bus_space_handle_t
, bus_size_t
, uint32_t, bus_size_t
);
230 void mg_isa_rr_2(void *, bus_space_handle_t
, bus_size_t
, uint16_t *, bus_size_t
);
231 void mg_isa_rr_4(void *, bus_space_handle_t
, bus_size_t
, uint32_t *, bus_size_t
);
232 void mg_isa_wr_2(void *, bus_space_handle_t
, bus_size_t
, const uint16_t *, bus_size_t
);
233 void mg_isa_wr_4(void *, bus_space_handle_t
, bus_size_t
, const uint32_t *, bus_size_t
);
234 void mg_isa_sr_2(void *, bus_space_handle_t
, bus_size_t
, uint16_t, bus_size_t
);
235 void mg_isa_sr_4(void *, bus_space_handle_t
, bus_size_t
, uint32_t, bus_size_t
);
237 int mgmatch(device_t
, cfdata_t
, void *);
238 void mgattach(device_t
, device_t
, void *);
240 CFATTACH_DECL_NEW(mongoose
, sizeof(struct mongoose_softc
),
241 mgmatch
, mgattach
, NULL
, NULL
);
246 mg_eisa_attach_hook(device_t parent
, device_t self
,
247 struct eisabus_attach_args
*mg
)
252 mg_intr_map(void *v
, u_int irq
, eisa_intr_handle_t
*ehp
)
259 mg_intr_string(void *v
, int irq
)
263 sprintf (buf
, "isa irq %d", irq
);
268 mg_isa_attach_hook(device_t parent
, device_t self
,
269 struct isabus_attach_args
*iba
)
275 mg_isa_detach_hook(isa_chipset_tag_t ic
, device_t self
)
281 mg_intr_establish(void *v
, int irq
, int type
, int pri
,
282 int (*handler
)(void *), void *arg
)
284 struct hppa_isa_iv
*iv
;
285 struct mongoose_softc
*sc
= v
;
286 volatile uint8_t *imr
, *pic
;
288 if (!sc
|| irq
< 0 || irq
>= MONGOOSE_NINTS
||
289 (0 <= irq
&& irq
< MONGOOSE_NINTS
&& sc
->sc_iv
[irq
].iv_handler
))
292 if (type
!= IST_LEVEL
&& type
!= IST_EDGE
) {
293 aprint_debug_dev(sc
->sc_dev
, "bad interrupt level (%d)\n",
298 iv
= &sc
->sc_iv
[irq
];
299 if (iv
->iv_handler
) {
300 aprint_debug_dev(sc
->sc_dev
, "irq %d already established\n",
306 iv
->iv_handler
= handler
;
310 imr
= &sc
->sc_ctrl
->imr0
;
311 pic
= &sc
->sc_ctrl
->pic0
;
313 imr
= &sc
->sc_ctrl
->imr1
;
314 pic
= &sc
->sc_ctrl
->pic1
;
319 *pic
|= (type
== IST_LEVEL
) << irq
;
327 mg_intr_disestablish(void *v
, void *cookie
)
329 struct hppa_isa_iv
*iv
= cookie
;
330 struct mongoose_softc
*sc
= v
;
331 int irq
= iv
- sc
->sc_iv
;
332 volatile uint8_t *imr
;
338 imr
= &sc
->sc_ctrl
->imr0
;
340 imr
= &sc
->sc_ctrl
->imr1
;
344 iv
->iv_handler
= NULL
;
348 mg_intr_check(void *v
, int irq
, int type
)
356 struct mongoose_softc
*sc
= v
;
357 struct hppa_isa_iv
*iv
;
360 iv
= &sc
->sc_iv
[irq
];
361 s
= splraise(imask
[iv
->iv_pri
]);
362 (iv
->iv_handler
)(iv
->iv_arg
);
369 mg_eisa_iomap(void *v
, bus_addr_t addr
, bus_size_t size
, int cacheable
,
370 bus_space_handle_t
*bshp
)
372 struct mongoose_softc
*sc
= v
;
374 /* see if it's ISA space we are mapping */
375 if (0x100 <= addr
&& addr
< 0x400) {
376 #define TOISA(a) ((((a) & 0x3f8) << 9) + ((a) & 7))
377 size
= TOISA(addr
+ size
) - TOISA(addr
);
381 return (sc
->sc_bt
->hbt_map
)(NULL
, sc
->sc_iomap
+ addr
, size
,
386 mg_eisa_memmap(void *v
, bus_addr_t addr
, bus_size_t size
, int cacheable
,
387 bus_space_handle_t
*bshp
)
389 /* TODO: eisa memory map */
394 mg_eisa_memunmap(void *v
, bus_space_handle_t bsh
, bus_size_t size
)
396 /* TODO: eisa memory unmap */
400 mg_isa_barrier(void *v
, bus_space_handle_t h
, bus_size_t o
, bus_size_t l
, int op
)
406 mg_isa_r2(void *v
, bus_space_handle_t h
, bus_size_t o
)
408 uint16_t r
= *((volatile uint16_t *)(h
+ o
));
414 mg_isa_r4(void *v
, bus_space_handle_t h
, bus_size_t o
)
416 uint32_t r
= *((volatile uint32_t *)(h
+ o
));
422 mg_isa_w2(void *v
, bus_space_handle_t h
, bus_size_t o
, uint16_t vv
)
424 *((volatile uint16_t *)(h
+ o
)) = htole16(vv
);
428 mg_isa_w4(void *v
, bus_space_handle_t h
, bus_size_t o
, uint32_t vv
)
430 *((volatile uint32_t *)(h
+ o
)) = htole32(vv
);
434 mg_isa_rm_2(void *v
, bus_space_handle_t h
, bus_size_t o
, uint16_t *a
, bus_size_t c
)
438 *(a
++) = le16toh(*(volatile uint16_t *)h
);
442 mg_isa_rm_4(void *v
, bus_space_handle_t h
, bus_size_t o
, uint32_t *a
, bus_size_t c
)
446 *(a
++) = le32toh(*(volatile uint32_t *)h
);
450 mg_isa_wm_2(void *v
, bus_space_handle_t h
, bus_size_t o
, const uint16_t *a
, bus_size_t c
)
457 *(volatile uint16_t *)h
= htole16(r
);
462 mg_isa_wm_4(void *v
, bus_space_handle_t h
, bus_size_t o
, const uint32_t *a
, bus_size_t c
)
469 *(volatile uint32_t *)h
= htole32(r
);
474 mg_isa_sm_2(void *v
, bus_space_handle_t h
, bus_size_t o
, uint16_t vv
, bus_size_t c
)
479 *(volatile uint16_t *)h
= vv
;
483 mg_isa_sm_4(void *v
, bus_space_handle_t h
, bus_size_t o
, uint32_t vv
, bus_size_t c
)
488 *(volatile uint32_t *)h
= vv
;
492 mg_isa_rr_2(void *v
, bus_space_handle_t h
, bus_size_t o
, uint16_t *a
, bus_size_t c
)
495 volatile uint16_t *p
;
506 mg_isa_rr_4(void *v
, bus_space_handle_t h
, bus_size_t o
, uint32_t *a
, bus_size_t c
)
509 volatile uint32_t *p
;
520 mg_isa_wr_2(void *v
, bus_space_handle_t h
, bus_size_t o
, const uint16_t *a
, bus_size_t c
)
523 volatile uint16_t *p
;
534 mg_isa_wr_4(void *v
, bus_space_handle_t h
, bus_size_t o
, const uint32_t *a
, bus_size_t c
)
537 volatile uint32_t *p
;
548 mg_isa_sr_2(void *v
, bus_space_handle_t h
, bus_size_t o
, uint16_t vv
, bus_size_t c
)
550 volatile uint16_t *p
;
560 mg_isa_sr_4(void *v
, bus_space_handle_t h
, bus_size_t o
, uint32_t vv
, bus_size_t c
)
562 volatile uint32_t *p
;
572 mgmatch(device_t parent
, cfdata_t cf
, void *aux
)
574 struct confargs
*ca
= aux
;
575 bus_space_handle_t ioh
;
577 if (ca
->ca_type
.iodc_type
!= HPPA_TYPE_BHA
||
578 ca
->ca_type
.iodc_sv_model
!= HPPA_BHA_EISA
)
581 if (bus_space_map(ca
->ca_iot
, ca
->ca_hpa
+ MONGOOSE_MONGOOSE
,
582 sizeof(struct mongoose_regs
), 0, &ioh
))
585 /* XXX check EISA signature */
587 bus_space_unmap(ca
->ca_iot
, ioh
, sizeof(struct mongoose_regs
));
593 mgattach(device_t parent
, device_t self
, void *aux
)
595 struct confargs
*ca
= aux
;
596 struct mongoose_softc
*sc
= device_private(self
);
597 struct hppa_bus_space_tag
*bt
;
598 union mongoose_attach_args ea
;
599 char brid
[EISA_IDSTRINGLEN
];
600 bus_space_handle_t ioh
;
603 sc
->sc_bt
= ca
->ca_iot
;
604 sc
->sc_iomap
= ca
->ca_hpa
;
605 if (bus_space_map(ca
->ca_iot
, ca
->ca_hpa
+ MONGOOSE_MONGOOSE
,
606 sizeof(struct mongoose_regs
), 0, &ioh
))
607 panic("mgattach: can't map registers");
608 sc
->sc_regs
= (struct mongoose_regs
*)ioh
;
609 if (bus_space_map(ca
->ca_iot
, ca
->ca_hpa
+ MONGOOSE_CTRL
,
610 sizeof(struct mongoose_ctrl
), 0, &ioh
))
611 panic("mgattach: can't map control registers");
612 sc
->sc_ctrl
= (struct mongoose_ctrl
*)ioh
;
617 sc
->sc_ctrl
->nmi_ext
= MONGOOSE_NMI_BUSRESET
;
619 sc
->sc_ctrl
->nmi_ext
= 0;
622 /* determine eisa board id */
625 /* XXX this is awful */
626 p
= (uint8_t *)(ioh
+ EISA_SLOTOFF_VID
);
632 brid
[0] = EISA_VENDID_0(id
);
633 brid
[1] = EISA_VENDID_1(id
);
634 brid
[2] = EISA_VENDID_2(id
);
635 brid
[3] = EISA_PRODID_0(id
+ 2);
636 brid
[4] = EISA_PRODID_1(id
+ 2);
637 brid
[5] = EISA_PRODID_2(id
+ 2);
638 brid
[6] = EISA_PRODID_3(id
+ 2);
642 aprint_normal(": %s rev %d, %d MHz\n", brid
, sc
->sc_regs
->version
,
643 (sc
->sc_regs
->clock
? 33 : 25));
644 sc
->sc_regs
->liowait
= 1; /* disable isa wait states */
645 sc
->sc_regs
->lock
= 1; /* bus unlock */
649 sc
->sc_ec
.ec_attach_hook
= mg_eisa_attach_hook
;
650 sc
->sc_ec
.ec_intr_establish
= mg_intr_establish
;
651 sc
->sc_ec
.ec_intr_disestablish
= mg_intr_disestablish
;
652 sc
->sc_ec
.ec_intr_string
= mg_intr_string
;
653 sc
->sc_ec
.ec_intr_map
= mg_intr_map
;
655 /* inherit the bus tags for eisa from the mainbus */
657 memcpy(bt
, ca
->ca_iot
, sizeof(*bt
));
659 bt
->hbt_map
= mg_eisa_iomap
;
660 #define R(n) bt->__CONCAT(hbt_,n) = &__CONCAT(mg_isa_,n)
662 R(r2
); R(r4
); R(w2
); R(w4
);
663 R(rm_2
);R(rm_4
);R(wm_2
);R(wm_4
);R(sm_2
);R(sm_4
);
664 R(rr_2
);R(rr_4
);R(wr_2
);R(wr_4
);R(sr_2
);R(sr_4
);
667 memcpy(bt
, ca
->ca_iot
, sizeof(*bt
));
669 bt
->hbt_map
= mg_eisa_memmap
;
670 bt
->hbt_unmap
= mg_eisa_memunmap
;
672 /* attachment guts */
673 ea
.mongoose_eisa
.eba_iot
= &sc
->sc_eiot
;
674 ea
.mongoose_eisa
.eba_memt
= &sc
->sc_ememt
;
675 ea
.mongoose_eisa
.eba_dmat
= NULL
/* &sc->sc_edmat */;
676 ea
.mongoose_eisa
.eba_ec
= &sc
->sc_ec
;
677 config_found_ia(self
, "eisabus", &ea
.mongoose_eisa
, eisabusprint
);
680 sc
->sc_ic
.ic_attach_hook
= mg_isa_attach_hook
;
681 sc
->sc_ic
.ic_detach_hook
= mg_isa_detach_hook
;
682 sc
->sc_ic
.ic_intr_establish
= mg_intr_establish
;
683 sc
->sc_ic
.ic_intr_disestablish
= mg_intr_disestablish
;
684 sc
->sc_ic
.ic_intr_check
= mg_intr_check
;
686 /* inherit the bus tags for isa from the eisa */
688 memcpy(bt
, &sc
->sc_ememt
, sizeof(*bt
));
690 memcpy(bt
, &sc
->sc_eiot
, sizeof(*bt
));
694 /* attachment guts */
695 ea
.mongoose_isa
.iba_iot
= &sc
->sc_iiot
;
696 ea
.mongoose_isa
.iba_memt
= &sc
->sc_imemt
;
698 ea
.mongoose_isa
.iba_dmat
= &sc
->sc_idmat
;
700 ea
.mongoose_isa
.iba_ic
= &sc
->sc_ic
;
701 config_found_ia(self
, "isabus", &ea
.mongoose_isa
, isabusprint
);
704 /* attach interrupt */
705 sc
->sc_ih
= hp700_intr_establish(sc
->sc_dev
, IPL_NONE
, mg_intr
, sc
,
706 &int_reg_cpu
, ca
->ca_irq
);