summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/arch/hppa/dev/dino.c184
1 files changed, 175 insertions, 9 deletions
diff --git a/sys/arch/hppa/dev/dino.c b/sys/arch/hppa/dev/dino.c
index 9bbbea7eba9..fd805848d8c 100644
--- a/sys/arch/hppa/dev/dino.c
+++ b/sys/arch/hppa/dev/dino.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dino.c,v 1.19 2006/12/18 18:49:46 miod Exp $ */
+/* $OpenBSD: dino.c,v 1.20 2007/01/11 21:59:52 miod Exp $ */
/*
* Copyright (c) 2003-2005 Michael Shalayeff
@@ -48,6 +48,9 @@
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
+#include <machine/pdc.h>
+#include <dev/cons.h>
+
#define DINO_MEM_CHUNK 0x800000
#define DINO_MEM_WINDOW (2 * DINO_MEM_CHUNK)
@@ -115,6 +118,8 @@ struct dino_softc {
char sc_memexname[20];
struct extent *sc_memex;
struct hppa_bus_dma_tag sc_dmatag;
+
+ u_int32_t io_shadow;
};
int dinomatch(struct device *, void *, void *);
@@ -150,6 +155,137 @@ dinomatch(parent, cfdata, aux)
return (1);
}
+void dino_attach_hook(struct device *, struct device *,
+ struct pcibus_attach_args *);
+int dino_maxdevs(void *, int);
+pcitag_t dino_make_tag(void *, int, int, int);
+void dino_decompose_tag(void *, pcitag_t, int *, int *, int *);
+pcireg_t dino_conf_read(void *, pcitag_t, int);
+void dino_conf_write(void *, pcitag_t, int, pcireg_t);
+int dino_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
+const char *dino_intr_string(void *, pci_intr_handle_t);
+void * dino_intr_establish(void *, pci_intr_handle_t, int, int (*)(void *),
+ void *, char *);
+void dino_intr_disestablish(void *, void *);
+int dino_iomap(void *, bus_addr_t, bus_size_t, int, bus_space_handle_t *);
+int dino_memmap(void *, bus_addr_t, bus_size_t, int, bus_space_handle_t *);
+int dino_subregion(void *, bus_space_handle_t, bus_size_t, bus_size_t,
+ bus_space_handle_t *);
+int dino_ioalloc(void *, bus_addr_t, bus_addr_t, bus_size_t, bus_size_t,
+ bus_size_t, int, bus_addr_t *, bus_space_handle_t *);
+int dino_memalloc(void *, bus_addr_t, bus_addr_t, bus_size_t, bus_size_t,
+ bus_size_t, int, bus_addr_t *, bus_space_handle_t *);
+void dino_unmap(void *, bus_space_handle_t, bus_size_t);
+void dino_free(void *, bus_space_handle_t, bus_size_t);
+void dino_barrier(void *, bus_space_handle_t, bus_size_t, bus_size_t, int);
+void * dino_alloc_parent(struct device *, struct pci_attach_args *, int);
+u_int8_t dino_r1(void *, bus_space_handle_t, bus_size_t);
+u_int16_t dino_r2(void *, bus_space_handle_t, bus_size_t);
+u_int32_t dino_r4(void *, bus_space_handle_t, bus_size_t);
+u_int64_t dino_r8(void *, bus_space_handle_t, bus_size_t);
+void dino_w1(void *, bus_space_handle_t, bus_size_t, u_int8_t);
+void dino_w2(void *, bus_space_handle_t, bus_size_t, u_int16_t);
+void dino_w4(void *, bus_space_handle_t, bus_size_t, u_int32_t);
+void dino_w8(void *, bus_space_handle_t, bus_size_t, u_int64_t);
+void dino_rm_1(void *, bus_space_handle_t, bus_size_t, u_int8_t *,
+ bus_size_t);
+void dino_rm_2(void *, bus_space_handle_t, bus_size_t, u_int16_t *,
+ bus_size_t);
+void dino_rm_4(void *, bus_space_handle_t, bus_size_t, u_int32_t *,
+ bus_size_t);
+void dino_rm_8(void *, bus_space_handle_t, bus_size_t, u_int64_t *,
+ bus_size_t);
+void dino_wm_1(void *, bus_space_handle_t, bus_size_t, const u_int8_t *,
+ bus_size_t);
+void dino_wm_2(void *, bus_space_handle_t, bus_size_t, const u_int16_t *,
+ bus_size_t);
+void dino_wm_4(void *, bus_space_handle_t, bus_size_t, const u_int32_t *,
+ bus_size_t);
+void dino_wm_8(void *, bus_space_handle_t, bus_size_t, const u_int64_t *,
+ bus_size_t);
+void dino_sm_1(void *, bus_space_handle_t, bus_size_t, u_int8_t, bus_size_t);
+void dino_sm_2(void *, bus_space_handle_t, bus_size_t, u_int16_t,
+ bus_size_t);
+void dino_sm_4(void *, bus_space_handle_t, bus_size_t, u_int32_t,
+ bus_size_t);
+void dino_sm_8(void *, bus_space_handle_t, bus_size_t, u_int64_t,
+ bus_size_t);
+void dino_rrm_2(void *, bus_space_handle_t, bus_size_t, u_int8_t *,
+ bus_size_t);
+void dino_rrm_4(void *, bus_space_handle_t, bus_size_t, u_int8_t *,
+ bus_size_t);
+void dino_rrm_8(void *, bus_space_handle_t, bus_size_t, u_int8_t *,
+ bus_size_t);
+void dino_wrm_2(void *, bus_space_handle_t, bus_size_t, const u_int8_t *,
+ bus_size_t);
+void dino_wrm_4(void *, bus_space_handle_t, bus_size_t, const u_int8_t *,
+ bus_size_t);
+void dino_wrm_8(void *, bus_space_handle_t, bus_size_t, const u_int8_t *,
+ bus_size_t);
+void dino_rr_1(void *, bus_space_handle_t, bus_size_t, u_int8_t *,
+ bus_size_t);
+void dino_rr_2(void *, bus_space_handle_t, bus_size_t, u_int16_t *,
+ bus_size_t);
+void dino_rr_4(void *, bus_space_handle_t, bus_size_t, u_int32_t *,
+ bus_size_t);
+void dino_rr_8(void *, bus_space_handle_t, bus_size_t, u_int64_t *,
+ bus_size_t);
+void dino_wr_1(void *, bus_space_handle_t, bus_size_t, const u_int8_t *,
+ bus_size_t);
+void dino_wr_2(void *, bus_space_handle_t, bus_size_t, const u_int16_t *,
+ bus_size_t);
+void dino_wr_4(void *, bus_space_handle_t, bus_size_t, const u_int32_t *,
+ bus_size_t);
+void dino_wr_8(void *, bus_space_handle_t, bus_size_t, const u_int64_t *,
+ bus_size_t);
+void dino_rrr_2(void *, bus_space_handle_t, bus_size_t, u_int8_t *,
+ bus_size_t);
+void dino_rrr_4(void *, bus_space_handle_t, bus_size_t, u_int8_t *,
+ bus_size_t);
+void dino_rrr_8(void *, bus_space_handle_t, bus_size_t, u_int8_t *,
+ bus_size_t);
+void dino_wrr_2(void *, bus_space_handle_t, bus_size_t, const u_int8_t *,
+ bus_size_t);
+void dino_wrr_4(void *, bus_space_handle_t, bus_size_t, const u_int8_t *,
+ bus_size_t);
+void dino_wrr_8(void *, bus_space_handle_t, bus_size_t, const u_int8_t *,
+ bus_size_t);
+void dino_sr_1(void *, bus_space_handle_t, bus_size_t, u_int8_t, bus_size_t);
+void dino_sr_2(void *, bus_space_handle_t, bus_size_t, u_int16_t,
+ bus_size_t);
+void dino_sr_4(void *, bus_space_handle_t, bus_size_t, u_int32_t,
+ bus_size_t);
+void dino_sr_8(void *, bus_space_handle_t, bus_size_t, u_int64_t,
+ bus_size_t);
+void dino_cp_1(void *, bus_space_handle_t, bus_size_t, bus_space_handle_t,
+ bus_size_t, bus_size_t);
+void dino_cp_2(void *, bus_space_handle_t, bus_size_t, bus_space_handle_t,
+ bus_size_t, bus_size_t);
+void dino_cp_4(void *, bus_space_handle_t, bus_size_t, bus_space_handle_t,
+ bus_size_t, bus_size_t);
+void dino_cp_8(void *, bus_space_handle_t, bus_size_t, bus_space_handle_t,
+ bus_size_t, bus_size_t);
+int dino_dmamap_create(void *, bus_size_t, int, bus_size_t, bus_size_t, int,
+ bus_dmamap_t *);
+void dino_dmamap_destroy(void *, bus_dmamap_t);
+int dino_dmamap_load(void *, bus_dmamap_t, void *, bus_size_t,
+ struct proc *, int);
+int dino_dmamap_load_mbuf(void *, bus_dmamap_t, struct mbuf *, int);
+int dino_dmamap_load_uio(void *, bus_dmamap_t, struct uio *, int);
+int dino_dmamap_load_raw(void *, bus_dmamap_t, bus_dma_segment_t *, int,
+ bus_size_t, int);
+void dino_dmamap_unload(void *, bus_dmamap_t);
+void dino_dmamap_sync(void *, bus_dmamap_t, bus_addr_t, bus_size_t, int);
+int dino_dmamem_alloc(void *, bus_size_t, bus_size_t, bus_size_t,
+ bus_dma_segment_t *, int, int *, int);
+void dino_dmamem_free(void *, bus_dma_segment_t *, int);
+int dino_dmamem_map(void *, bus_dma_segment_t *, int, size_t, caddr_t *,
+ int);
+void dino_dmamem_unmap(void *, caddr_t, size_t);
+paddr_t dino_dmamem_mmap(void *, bus_dma_segment_t *, int, off_t, int, int);
+int dinoprint(void *, const char *);
+void dino_clear_pdc_mappings(void *);
+
void
dino_attach_hook(struct device *parent, struct device *self,
struct pcibus_attach_args *pba)
@@ -306,30 +442,32 @@ dino_memmap(void *v, bus_addr_t bpa, bus_size_t size,
struct dino_softc *sc = v;
volatile struct dino_regs *r = sc->sc_regs;
bus_addr_t sbpa;
+ bus_space_handle_t bush;
u_int32_t reg;
int first = 1;
int error;
while (size != 0) {
sbpa = bpa & 0xff800000;
- reg = r->io_addr_en;
+ reg = sc->io_shadow;
reg |= 1 << ((bpa >> 23) & 0x1f);
#ifdef DEBUG
if (reg & 0x80000001)
panic("mapping outside the mem extent range");
#endif
/* map into the upper bus space, if not yet mapped this 8M */
- if (reg != r->io_addr_en) {
+ if (reg != sc->io_shadow) {
if ((error = bus_space_map(sc->sc_bt, sbpa,
- DINO_MEM_CHUNK, flags, bshp))) {
+ DINO_MEM_CHUNK, flags, &bush))) {
return (error);
}
- r->io_addr_en = reg;
+ r->io_addr_en |= reg;
+ sc->io_shadow = reg;
if (first) {
if (bshp)
- *bshp += (bpa - sbpa);
+ *bshp = bush + (bpa - sbpa);
}
} else {
if (first) {
@@ -400,13 +538,14 @@ dino_memalloc(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
align, boundary, flags, addrp, bshp))
return (ENOMEM);
- reg = r->io_addr_en;
+ reg = sc->io_shadow;
reg |= 1 << ((*addrp >> 23) & 0x1f);
#ifdef DEBUG
if (reg & 0x80000001)
panic("mapping outside the mem extent range");
#endif
- r->io_addr_en = reg;
+ r->io_addr_en |= reg;
+ sc->io_shadow = reg;
return (0);
}
@@ -1547,7 +1686,15 @@ dinoattach(parent, self, aux)
sc->sc_regs = r = (volatile struct dino_regs *)sc->sc_bh;
r->pciror = 0;
r->pciwor = 0;
- r->io_addr_en = 0;
+
+ /*
+ * Do not reset enabled io mappings mask if we are still running
+ * with PDC console - we'll do it after autoconf.
+ */
+ if (cn_tab->cn_putc != pdccnputc)
+ r->io_addr_en = 0;
+ sc->io_shadow = 0;
+
r->gmask &= ~1; /* allow GSC bus req */
r->brdg_feat &= ~0xf00;
r->brdg_feat |= 3;
@@ -1649,6 +1796,25 @@ dinoattach(parent, self, aux)
pba.pba_bridgetag = NULL;
config_found(self, &pba, dinoprint);
+ /* postpone cleanup if necessary */
+ if (r->io_addr_en != sc->io_shadow)
+ startuphook_establish(dino_clear_pdc_mappings, sc);
+
/* enable interrupts now that all the devices are there */
r->imr = sc->sc_imr;
}
+
+void
+dino_clear_pdc_mappings(void *v)
+{
+ struct dino_softc *sc = (struct dino_softc *)v;
+ volatile struct dino_regs *r;
+
+ if (cn_tab->cn_putc == pdccnputc) {
+ /* damn! */
+ return;
+ }
+
+ r = sc->sc_regs;
+ r->io_addr_en = sc->io_shadow;
+}