xref: /openbsd/sys/arch/hppa/dev/dino.c (revision d89ec533)
1 /*	$OpenBSD: dino.c,v 1.32 2018/05/14 13:54:39 kettenis Exp $	*/
2 
3 /*
4  * Copyright (c) 2003-2005 Michael Shalayeff
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19  * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
20  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22  * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26  * THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "cardbus.h"
30 
31 #include <sys/param.h>
32 #include <sys/systm.h>
33 #include <sys/device.h>
34 #include <sys/reboot.h>
35 #include <sys/malloc.h>
36 #include <sys/extent.h>
37 
38 #include <machine/iomod.h>
39 #include <machine/autoconf.h>
40 
41 #include <hppa/dev/cpudevs.h>
42 
43 #if NCARDBUS > 0
44 #include <dev/cardbus/rbus.h>
45 #endif
46 
47 #include <dev/pci/pcireg.h>
48 #include <dev/pci/pcivar.h>
49 #include <dev/pci/pcidevs.h>
50 
51 #include <machine/pdc.h>
52 #include <dev/cons.h>
53 
54 #define	DINO_MEM_CHUNK	0x800000
55 #define	DINO_MEM_WINDOW	(2 * DINO_MEM_CHUNK)
56 
57 struct dino_regs {
58 	u_int32_t	pad0;		/* 0x000 */
59 	u_int32_t	iar0;		/* 0x004 rw intr addr reg 0 */
60 	u_int32_t	iodc;		/* 0x008 rw iodc data/addr */
61 	u_int32_t	irr0;		/* 0x00c r  intr req reg 0 */
62 	u_int32_t	iar1;		/* 0x010 rw intr addr reg 1 */
63 	u_int32_t	irr1;		/* 0x014 r  intr req reg 1 */
64 	u_int32_t	imr;		/* 0x018 rw intr mask reg */
65 	u_int32_t	ipr;		/* 0x01c rw intr pending reg */
66 	u_int32_t	toc_addr;	/* 0x020 rw TOC addr reg */
67 	u_int32_t	icr;		/* 0x024 rw intr control reg */
68 	u_int32_t	ilr;		/* 0x028 r  intr level reg */
69 	u_int32_t	pad1;		/* 0x02c */
70 	u_int32_t	io_command;	/* 0x030  w command register */
71 	u_int32_t	io_status;	/* 0x034 r  status register */
72 	u_int32_t	io_control;	/* 0x038 rw control register */
73 	u_int32_t	pad2;		/* 0x03c AUX registers follow */
74 	u_int32_t	io_gsc_err_addr;/* 0x040 GSC error address */
75 	u_int32_t	io_err_info;	/* 0x044 error info register */
76 	u_int32_t	io_pci_err_addr;/* 0x048 PCI error address */
77 	u_int32_t	pad3[4];	/* 0x04c */
78 	u_int32_t	io_fbb_en;	/* 0x05c fast back2back enable reg */
79 	u_int32_t	io_addr_en;	/* 0x060 address enable reg */
80 	u_int32_t	pci_addr;	/* 0x064 PCI conf/io/mem addr reg */
81 	u_int32_t	pci_conf_data;	/* 0x068 PCI conf data reg */
82 	u_int32_t	pci_io_data;	/* 0x06c PCI io data reg */
83 	u_int32_t	pci_mem_data;	/* 0x070 PCI memory data reg */
84 	u_int32_t	pad4[0x740/4];	/* 0x074 */
85 	u_int32_t	gsc2x_config;	/* 0x7b4 GSC2X config reg */
86 	u_int32_t	pad5[0x48/4];	/* 0x7b8: BSRS registers follow */
87 	u_int32_t	gmask;		/* 0x800 GSC arbitration mask */
88 	u_int32_t	pamr;		/* 0x804 PCI arbitration mask */
89 	u_int32_t	papr;		/* 0x808 PCI arbitration priority */
90 	u_int32_t	damode;		/* 0x80c PCI arbitration mode */
91 	u_int32_t	pcicmd;		/* 0x810 PCI command register */
92 	u_int32_t	pcists;		/* 0x814 PCI status register */
93 	u_int32_t	pad6;		/* 0x818 */
94 	u_int32_t	mltim;		/* 0x81c PCI master latency timer */
95 	u_int32_t	brdg_feat;	/* 0x820 PCI bridge feature enable */
96 	u_int32_t	pciror;		/* 0x824 PCI read optimization reg */
97 	u_int32_t	pciwor;		/* 0x828 PCI write optimization reg */
98 	u_int32_t	pad7;		/* 0x82c */
99 	u_int32_t	tltim;		/* 0x830 PCI target latency reg */
100 };
101 
102 struct dino_softc {
103 	struct  device sc_dv;
104 
105 	int sc_ver;
106 	void *sc_ih;
107 	u_int32_t sc_imr;
108 	bus_space_tag_t sc_bt;
109 	bus_space_handle_t sc_bh;
110 	bus_dma_tag_t sc_dmat;
111 	volatile struct dino_regs *sc_regs;
112 
113 	struct hppa_pci_chipset_tag sc_pc;
114 	struct hppa_bus_space_tag sc_iot;
115 	char sc_ioexname[20];
116 	struct extent *sc_ioex;
117 	struct hppa_bus_space_tag sc_memt;
118 	char sc_memexname[20];
119 	struct extent *sc_memex;
120 	struct hppa_bus_dma_tag sc_dmatag;
121 
122 	u_int32_t io_shadow;
123 };
124 
125 int	dinomatch(struct device *, void *, void *);
126 void	dinoattach(struct device *, struct device *, void *);
127 int	dino_intr(void *);
128 
129 struct cfattach dino_ca = {
130 	sizeof(struct dino_softc), dinomatch, dinoattach
131 };
132 
133 struct cfdriver dino_cd = {
134 	NULL, "dino", DV_DULL
135 };
136 
137 int
138 dinomatch(parent, cfdata, aux)
139 	struct device *parent;
140 	void *cfdata;
141 	void *aux;
142 {
143 	struct confargs *ca = aux;
144 	/* struct cfdata *cf = cfdata; */
145 
146 	/* there will be only one */
147 	if (ca->ca_type.iodc_type != HPPA_TYPE_BRIDGE ||
148 	    ca->ca_type.iodc_sv_model != HPPA_BRIDGE_DINO)
149 		return (0);
150 
151 	/* do not match on the elroy family */
152 	if (ca->ca_type.iodc_model == 0x78)
153 		return (0);
154 
155 	return (1);
156 }
157 
158 void	dino_attach_hook(struct device *, struct device *,
159 	    struct pcibus_attach_args *);
160 int	dino_maxdevs(void *, int);
161 pcitag_t dino_make_tag(void *, int, int, int);
162 void	dino_decompose_tag(void *, pcitag_t, int *, int *, int *);
163 int	dino_conf_size(void *, pcitag_t);
164 pcireg_t dino_conf_read(void *, pcitag_t, int);
165 void	dino_conf_write(void *, pcitag_t, int, pcireg_t);
166 int	dino_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
167 const char *dino_intr_string(void *, pci_intr_handle_t);
168 void *	dino_intr_establish(void *, pci_intr_handle_t, int, int (*)(void *),
169 	    void *, const char *);
170 void	dino_intr_disestablish(void *, void *);
171 int	dino_iomap(void *, bus_addr_t, bus_size_t, int, bus_space_handle_t *);
172 int	dino_memmap(void *, bus_addr_t, bus_size_t, int, bus_space_handle_t *);
173 int	dino_subregion(void *, bus_space_handle_t, bus_size_t, bus_size_t,
174 	    bus_space_handle_t *);
175 int	dino_ioalloc(void *, bus_addr_t, bus_addr_t, bus_size_t, bus_size_t,
176 	    bus_size_t, int, bus_addr_t *, bus_space_handle_t *);
177 int	dino_memalloc(void *, bus_addr_t, bus_addr_t, bus_size_t, bus_size_t,
178 	    bus_size_t, int, bus_addr_t *, bus_space_handle_t *);
179 void	dino_unmap(void *, bus_space_handle_t, bus_size_t);
180 void	dino_free(void *, bus_space_handle_t, bus_size_t);
181 void	dino_barrier(void *, bus_space_handle_t, bus_size_t, bus_size_t, int);
182 void *	dino_alloc_parent(struct device *, struct pci_attach_args *, int);
183 void *	dino_vaddr(void *, bus_space_handle_t);
184 u_int8_t dino_r1(void *, bus_space_handle_t, bus_size_t);
185 u_int16_t dino_r2(void *, bus_space_handle_t, bus_size_t);
186 u_int32_t dino_r4(void *, bus_space_handle_t, bus_size_t);
187 u_int64_t dino_r8(void *, bus_space_handle_t, bus_size_t);
188 void	dino_w1(void *, bus_space_handle_t, bus_size_t, u_int8_t);
189 void	dino_w2(void *, bus_space_handle_t, bus_size_t, u_int16_t);
190 void	dino_w4(void *, bus_space_handle_t, bus_size_t, u_int32_t);
191 void	dino_w8(void *, bus_space_handle_t, bus_size_t, u_int64_t);
192 void	dino_rm_1(void *, bus_space_handle_t, bus_size_t, u_int8_t *,
193 	    bus_size_t);
194 void	dino_rm_2(void *, bus_space_handle_t, bus_size_t, u_int16_t *,
195 	    bus_size_t);
196 void	dino_rm_4(void *, bus_space_handle_t, bus_size_t, u_int32_t *,
197 	    bus_size_t);
198 void	dino_rm_8(void *, bus_space_handle_t, bus_size_t, u_int64_t *,
199 	    bus_size_t);
200 void	dino_wm_1(void *, bus_space_handle_t, bus_size_t, const u_int8_t *,
201 	    bus_size_t);
202 void	dino_wm_2(void *, bus_space_handle_t, bus_size_t, const u_int16_t *,
203 	    bus_size_t);
204 void	dino_wm_4(void *, bus_space_handle_t, bus_size_t, const u_int32_t *,
205 	    bus_size_t);
206 void	dino_wm_8(void *, bus_space_handle_t, bus_size_t, const u_int64_t *,
207 	    bus_size_t);
208 void	dino_sm_1(void *, bus_space_handle_t, bus_size_t, u_int8_t, bus_size_t);
209 void	dino_sm_2(void *, bus_space_handle_t, bus_size_t, u_int16_t,
210 	    bus_size_t);
211 void	dino_sm_4(void *, bus_space_handle_t, bus_size_t, u_int32_t,
212 	    bus_size_t);
213 void	dino_sm_8(void *, bus_space_handle_t, bus_size_t, u_int64_t,
214 	    bus_size_t);
215 void	dino_rrm_2(void *, bus_space_handle_t, bus_size_t, u_int8_t *,
216 	    bus_size_t);
217 void	dino_rrm_4(void *, bus_space_handle_t, bus_size_t, u_int8_t *,
218 	    bus_size_t);
219 void	dino_rrm_8(void *, bus_space_handle_t, bus_size_t, u_int8_t *,
220 	    bus_size_t);
221 void	dino_wrm_2(void *, bus_space_handle_t, bus_size_t, const u_int8_t *,
222 	    bus_size_t);
223 void	dino_wrm_4(void *, bus_space_handle_t, bus_size_t, const u_int8_t *,
224 	    bus_size_t);
225 void	dino_wrm_8(void *, bus_space_handle_t, bus_size_t, const u_int8_t *,
226 	    bus_size_t);
227 void	dino_rr_1(void *, bus_space_handle_t, bus_size_t, u_int8_t *,
228 	    bus_size_t);
229 void	dino_rr_2(void *, bus_space_handle_t, bus_size_t, u_int16_t *,
230 	    bus_size_t);
231 void	dino_rr_4(void *, bus_space_handle_t, bus_size_t, u_int32_t *,
232 	    bus_size_t);
233 void	dino_rr_8(void *, bus_space_handle_t, bus_size_t, u_int64_t *,
234 	    bus_size_t);
235 void	dino_wr_1(void *, bus_space_handle_t, bus_size_t, const u_int8_t *,
236 	    bus_size_t);
237 void	dino_wr_2(void *, bus_space_handle_t, bus_size_t, const u_int16_t *,
238 	    bus_size_t);
239 void	dino_wr_4(void *, bus_space_handle_t, bus_size_t, const u_int32_t *,
240 	    bus_size_t);
241 void	dino_wr_8(void *, bus_space_handle_t, bus_size_t, const u_int64_t *,
242 	    bus_size_t);
243 void	dino_rrr_2(void *, bus_space_handle_t, bus_size_t, u_int8_t *,
244 	    bus_size_t);
245 void	dino_rrr_4(void *, bus_space_handle_t, bus_size_t, u_int8_t *,
246 	    bus_size_t);
247 void	dino_rrr_8(void *, bus_space_handle_t, bus_size_t, u_int8_t *,
248 	    bus_size_t);
249 void	dino_wrr_2(void *, bus_space_handle_t, bus_size_t, const u_int8_t *,
250 	    bus_size_t);
251 void	dino_wrr_4(void *, bus_space_handle_t, bus_size_t, const u_int8_t *,
252 	    bus_size_t);
253 void	dino_wrr_8(void *, bus_space_handle_t, bus_size_t, const u_int8_t *,
254 	    bus_size_t);
255 void	dino_sr_1(void *, bus_space_handle_t, bus_size_t, u_int8_t, bus_size_t);
256 void	dino_sr_2(void *, bus_space_handle_t, bus_size_t, u_int16_t,
257 	    bus_size_t);
258 void	dino_sr_4(void *, bus_space_handle_t, bus_size_t, u_int32_t,
259 	    bus_size_t);
260 void	dino_sr_8(void *, bus_space_handle_t, bus_size_t, u_int64_t,
261 	    bus_size_t);
262 void	dino_cp_1(void *, bus_space_handle_t, bus_size_t, bus_space_handle_t,
263 	    bus_size_t, bus_size_t);
264 void	dino_cp_2(void *, bus_space_handle_t, bus_size_t, bus_space_handle_t,
265 	    bus_size_t, bus_size_t);
266 void	dino_cp_4(void *, bus_space_handle_t, bus_size_t, bus_space_handle_t,
267 	    bus_size_t, bus_size_t);
268 void	dino_cp_8(void *, bus_space_handle_t, bus_size_t, bus_space_handle_t,
269 	    bus_size_t, bus_size_t);
270 int	dino_dmamap_create(void *, bus_size_t, int, bus_size_t, bus_size_t, int,
271 	    bus_dmamap_t *);
272 void	dino_dmamap_destroy(void *, bus_dmamap_t);
273 int	dino_dmamap_load(void *, bus_dmamap_t, void *, bus_size_t,
274 	    struct proc *, int);
275 int	dino_dmamap_load_mbuf(void *, bus_dmamap_t, struct mbuf *, int);
276 int	dino_dmamap_load_uio(void *, bus_dmamap_t, struct uio *, int);
277 int	dino_dmamap_load_raw(void *, bus_dmamap_t, bus_dma_segment_t *, int,
278 	    bus_size_t, int);
279 void	dino_dmamap_unload(void *, bus_dmamap_t);
280 void	dino_dmamap_sync(void *, bus_dmamap_t, bus_addr_t, bus_size_t, int);
281 int	dino_dmamem_alloc(void *, bus_size_t, bus_size_t, bus_size_t,
282 	    bus_dma_segment_t *, int, int *, int);
283 void	dino_dmamem_free(void *, bus_dma_segment_t *, int);
284 int	dino_dmamem_map(void *, bus_dma_segment_t *, int, size_t, caddr_t *,
285 	    int);
286 void	dino_dmamem_unmap(void *, caddr_t, size_t);
287 paddr_t	dino_dmamem_mmap(void *, bus_dma_segment_t *, int, off_t, int, int);
288 int	dinoprint(void *, const char *);
289 void	dino_clear_pdc_mappings(void *);
290 
291 void
292 dino_attach_hook(struct device *parent, struct device *self,
293     struct pcibus_attach_args *pba)
294 {
295 
296 }
297 
298 int
299 dino_maxdevs(void *v, int bus)
300 {
301 	return (32);
302 }
303 
304 pcitag_t
305 dino_make_tag(void *v, int bus, int dev, int func)
306 {
307 	if (bus > 255 || dev > 31 || func > 7)
308 		panic("dino_make_tag: bad request");
309 
310 	return ((bus << 16) | (dev << 11) | (func << 8));
311 }
312 
313 void
314 dino_decompose_tag(void *v, pcitag_t tag, int *bus, int *dev, int *func)
315 {
316 	if (bus)
317 		*bus = (tag >> 16) & 0xff;
318 	if (dev)
319 		*dev = (tag >> 11) & 0x1f;
320 	if (func)
321 		*func= (tag >>  8) & 0x07;
322 }
323 
324 int
325 dino_conf_size(void *v, pcitag_t tag)
326 {
327 	return PCI_CONFIG_SPACE_SIZE;
328 }
329 
330 pcireg_t
331 dino_conf_read(void *v, pcitag_t tag, int reg)
332 {
333 	struct dino_softc *sc = v;
334 	volatile struct dino_regs *r = sc->sc_regs;
335 	pcireg_t data;
336 	u_int32_t pamr;
337 
338 	/* fix arbitration errata by disabling all pci devs on config read */
339 	pamr = r->pamr;
340 	r->pamr = 0;
341 
342 	r->pci_addr = tag | reg;
343 	data = r->pci_conf_data;
344 
345 	/* restore arbitration */
346 	r->pamr = pamr;
347 
348 	return (letoh32(data));
349 }
350 
351 void
352 dino_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data)
353 {
354 	struct dino_softc *sc = v;
355 	volatile struct dino_regs *r = sc->sc_regs;
356 	pcireg_t data1;
357 	u_int32_t pamr;
358 
359 	/* fix arbitration errata by disabling all pci devs on config read */
360 	pamr = r->pamr;
361 	r->pamr = 0;
362 
363 	r->pci_addr = tag | reg;
364 	r->pci_conf_data = htole32(data);
365 
366 	/* fix coalescing config and io writes by interleaving w/ a read */
367 	r->pci_addr = tag | PCI_ID_REG;
368 	data1 = r->pci_conf_data;
369 
370 	/* restore arbitration */
371 	r->pamr = pamr;
372 }
373 
374 int
375 dino_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
376 {
377 	/* struct dino_softc *sc = v;
378 	volatile struct dino_regs *r = sc->sc_regs; */
379 	pci_chipset_tag_t pc = pa->pa_pc;
380 	pcitag_t tag = pa->pa_tag;
381 	pcireg_t reg;
382 
383 	reg = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
384 
385 	if (PCI_INTERRUPT_LINE(reg) == 0xff)
386 		return (1);
387 
388 	*ihp = PCI_INTERRUPT_LINE(reg) + 1;
389 	return (0);
390 }
391 
392 const char *
393 dino_intr_string(void *v, pci_intr_handle_t ih)
394 {
395 	static char buf[32];
396 
397 	snprintf(buf, 32, "dino irq %ld", ih);
398 
399 	return (buf);
400 }
401 
402 void *
403 dino_intr_establish(void *v, pci_intr_handle_t ih,
404     int pri, int (*handler)(void *), void *arg, const char *name)
405 {
406 	struct dino_softc *sc = v;
407 	volatile struct dino_regs *r = sc->sc_regs;
408 	void *iv;
409 
410 	/* no mapping or bogus */
411 	if (ih <= 0 || ih > 11)
412 		return (NULL);
413 
414 	if ((iv = cpu_intr_map(sc->sc_ih, pri, ih - 1, handler, arg, name))) {
415 		if (cold)
416 			sc->sc_imr |= (1 << (ih - 1));
417 		else
418 			r->imr = sc->sc_imr |= (1 << (ih - 1));
419 	}
420 
421 	return (iv);
422 }
423 
424 void
425 dino_intr_disestablish(void *v, void *cookie)
426 {
427 #if 0
428 	struct dino_softc *sc = v;
429 	volatile struct dino_regs *r = sc->sc_regs;
430 
431 	r->imr &= ~(1 << (ih - 1));
432 
433 	TODO cpu_intr_unmap(sc->sc_ih, cookie);
434 #endif
435 }
436 
437 int
438 dino_iomap(void *v, bus_addr_t bpa, bus_size_t size,
439     int flags, bus_space_handle_t *bshp)
440 {
441 	struct dino_softc *sc = v;
442 	int error;
443 
444 	if ((error = extent_alloc_region(sc->sc_ioex, bpa, size, EX_NOWAIT)))
445 		return (error);
446 
447 	if (bshp)
448 		*bshp = bpa;
449 
450 	return (0);
451 }
452 
453 int
454 dino_memmap(void *v, bus_addr_t bpa, bus_size_t size,
455     int flags, bus_space_handle_t *bshp)
456 {
457 	struct dino_softc *sc = v;
458 	volatile struct dino_regs *r = sc->sc_regs;
459 	bus_addr_t sbpa;
460 	bus_space_handle_t bush;
461 	u_int32_t reg;
462 	int first = 1;
463 	int error;
464 
465 	while (size != 0) {
466 		sbpa = bpa & 0xff800000;
467 		reg = sc->io_shadow;
468 		reg |= 1 << ((bpa >> 23) & 0x1f);
469 		if (reg & 0x80000001) {
470 #ifdef DEBUG
471 			panic("mapping outside the mem extent range");
472 #endif
473 			return (EINVAL);
474 		}
475 		/* map into the upper bus space, if not yet mapped this 8M */
476 		if (reg != sc->io_shadow) {
477 
478 			if ((error = bus_space_map(sc->sc_bt, sbpa,
479 			    DINO_MEM_CHUNK, flags, &bush))) {
480 				return (error);
481 			}
482 			r->io_addr_en |= reg;
483 			sc->io_shadow = reg;
484 
485 			if (first) {
486 				if (bshp)
487 					*bshp = bush + (bpa - sbpa);
488 			}
489 		} else {
490 			if (first) {
491 				if (bshp)
492 					*bshp = bpa;
493 			}
494 		}
495 
496 		if (first) {
497 			size += (bpa - sbpa);
498 			first = 0;
499 		}
500 
501 		if (size < DINO_MEM_CHUNK)
502 			size = 0;
503 		else {
504 			size -= DINO_MEM_CHUNK;
505 			bpa = sbpa + DINO_MEM_CHUNK;
506 		}
507 	}
508 
509 	return (0);
510 }
511 
512 int
513 dino_subregion(void *v, bus_space_handle_t bsh, bus_size_t offset,
514     bus_size_t size, bus_space_handle_t *nbshp)
515 {
516 	*nbshp = bsh + offset;
517 	return (0);
518 }
519 
520 int
521 dino_ioalloc(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
522     bus_size_t align, bus_size_t boundary, int flags, bus_addr_t *addrp,
523     bus_space_handle_t *bshp)
524 {
525 	struct dino_softc *sc = v;
526 	struct extent *ex = sc->sc_ioex;
527 	bus_addr_t bpa;
528 	int error;
529 
530 	if (rstart < ex->ex_start || rend > ex->ex_end)
531 		panic("dino_ioalloc: bad region start/end");
532 
533 	if ((error = extent_alloc_subregion(ex, rstart, rend, size,
534 	    align, 0, boundary, EX_NOWAIT, &bpa)))
535 		return (error);
536 
537 	if (addrp)
538 		*addrp = bpa;
539 	if (bshp)
540 		*bshp = bpa;
541 
542 	return (0);
543 }
544 
545 int
546 dino_memalloc(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
547     bus_size_t align, bus_size_t boundary, int flags, bus_addr_t *addrp,
548     bus_space_handle_t *bshp)
549 {
550 	struct dino_softc *sc = v;
551 	volatile struct dino_regs *r = sc->sc_regs;
552 	u_int32_t reg;
553 
554 	if (bus_space_alloc(sc->sc_bt, rstart, rend, size,
555 	    align, boundary, flags, addrp, bshp))
556 		return (ENOMEM);
557 
558 	reg = sc->io_shadow;
559 	reg |= 1 << ((*addrp >> 23) & 0x1f);
560 	if (reg & 0x80000001) {
561 #ifdef DEBUG
562 		panic("mapping outside the mem extent range");
563 #endif
564 		return (EINVAL);
565 	}
566 	r->io_addr_en |= reg;
567 	sc->io_shadow = reg;
568 
569 	return (0);
570 }
571 
572 void
573 dino_unmap(void *v, bus_space_handle_t bsh, bus_size_t size)
574 {
575 	struct dino_softc *sc = v;
576 	struct extent *ex;
577 	bus_addr_t bpa;
578 
579 	bpa = bsh;
580 	if (bsh & 0xf0000000) {
581 		/* TODO dino_unmap mem */
582 		/* TODO unmap from the upper bus if the last use in this 8M */
583 		return;
584 	} else
585 		ex = sc->sc_ioex;
586 
587 	if (extent_free(ex, bpa, size, EX_NOWAIT))
588 		printf("dino_unmap: ps 0x%lx, size 0x%lx\n"
589 		    "dino_unmap: can't free region\n", bpa, size);
590 }
591 
592 void
593 dino_free(void *v, bus_space_handle_t bh, bus_size_t size)
594 {
595 	/* should be enough */
596 	dino_unmap(v, bh, size);
597 }
598 
599 void
600 dino_barrier(void *v, bus_space_handle_t h, bus_size_t o, bus_size_t l, int op)
601 {
602 	sync_caches();
603 }
604 
605 #if NCARDBUS > 0
606 void *
607 dino_alloc_parent(struct device *self, struct pci_attach_args *pa, int io)
608 {
609 	struct dino_softc *sc = pa->pa_pc->_cookie;
610 	struct extent *ex;
611 	bus_space_tag_t tag;
612 	bus_addr_t start;
613 	bus_size_t size;
614 
615 	if (io) {
616 		ex = sc->sc_ioex;
617 		tag = pa->pa_iot;
618 		start = 0xa000;
619 		size = 0x1000;
620 	} else {
621 		if (!sc->sc_memex) {
622 			bus_space_handle_t memh;
623 			bus_addr_t mem_start;
624 
625 			if (dino_memalloc(sc, 0xf0800000, 0xff7fffff,
626 			    DINO_MEM_WINDOW, DINO_MEM_WINDOW, EX_NOBOUNDARY,
627 			    0, &mem_start, &memh))
628 				return (NULL);
629 
630 			snprintf(sc->sc_memexname, sizeof(sc->sc_memexname),
631 			    "%s_mem", sc->sc_dv.dv_xname);
632 			if ((sc->sc_memex = extent_create(sc->sc_memexname,
633 			    mem_start, mem_start + DINO_MEM_WINDOW, M_DEVBUF,
634 			    NULL, 0, EX_NOWAIT | EX_MALLOCOK)) == NULL) {
635 				extent_destroy(sc->sc_ioex);
636 				bus_space_free(sc->sc_bt, memh,
637 				    DINO_MEM_WINDOW);
638 				return (NULL);
639 			}
640 		}
641 		ex = sc->sc_memex;
642 		tag = pa->pa_memt;
643 		start = ex->ex_start;
644 		size = DINO_MEM_CHUNK;
645 	}
646 
647 	if (extent_alloc_subregion(ex, start, ex->ex_end, size, size, 0,
648 	    EX_NOBOUNDARY, EX_NOWAIT, &start))
649 		return (NULL);
650 
651 	extent_free(ex, start, size, EX_NOWAIT);
652 	return rbus_new_root_share(tag, ex, start, size);
653 }
654 #endif
655 
656 void *
657 dino_vaddr(void *v, bus_space_handle_t h)
658 {
659 	if (h & 0xf0000000)
660 		return ((void *)h);
661 	else
662 		return (NULL);
663 }
664 
665 u_int8_t
666 dino_r1(void *v, bus_space_handle_t h, bus_size_t o)
667 {
668 	h += o;
669 	if (h & 0xf0000000)
670 		return *(volatile u_int8_t *)h;
671 	else {
672 		struct dino_softc *sc = v;
673 		volatile struct dino_regs *r = sc->sc_regs;
674 		u_int8_t data;
675 
676 		r->pci_addr = h;
677 		data = *((volatile u_int8_t *)&r->pci_io_data + (h & 3));
678 		return (data);
679 	}
680 }
681 
682 u_int16_t
683 dino_r2(void *v, bus_space_handle_t h, bus_size_t o)
684 {
685 	volatile u_int16_t *p;
686 
687 	h += o;
688 	if (h & 0xf0000000)
689 		p = (volatile u_int16_t *)h;
690 	else {
691 		struct dino_softc *sc = v;
692 		volatile struct dino_regs *r = sc->sc_regs;
693 
694 		r->pci_addr = h;
695 		p = (volatile u_int16_t *)&r->pci_io_data;
696 		if (h & 2)
697 			p++;
698 	}
699 
700 	return (letoh16(*p));
701 }
702 
703 u_int32_t
704 dino_r4(void *v, bus_space_handle_t h, bus_size_t o)
705 {
706 	u_int32_t data;
707 
708 	h += o;
709 	if (h & 0xf0000000)
710 		data = *(volatile u_int32_t *)h;
711 	else {
712 		struct dino_softc *sc = v;
713 		volatile struct dino_regs *r = sc->sc_regs;
714 
715 		r->pci_addr = h;
716 		data = r->pci_io_data;
717 	}
718 
719 	return (letoh32(data));
720 }
721 
722 u_int64_t
723 dino_r8(void *v, bus_space_handle_t h, bus_size_t o)
724 {
725 	u_int64_t data;
726 
727 	h += o;
728 	if (h & 0xf0000000)
729 		data = *(volatile u_int64_t *)h;
730 	else
731 		panic("dino_r8: not implemented");
732 
733 	return (letoh64(data));
734 }
735 
736 void
737 dino_w1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv)
738 {
739 	h += o;
740 	if (h & 0xf0000000)
741 		*(volatile u_int8_t *)h = vv;
742 	else {
743 		struct dino_softc *sc = v;
744 		volatile struct dino_regs *r = sc->sc_regs;
745 
746 		r->pci_addr = h;
747 		*((volatile u_int8_t *)&r->pci_io_data + (h & 3)) = vv;
748 	}
749 }
750 
751 void
752 dino_w2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv)
753 {
754 	volatile u_int16_t *p;
755 
756 	h += o;
757 	if (h & 0xf0000000)
758 		p = (volatile u_int16_t *)h;
759 	else {
760 		struct dino_softc *sc = v;
761 		volatile struct dino_regs *r = sc->sc_regs;
762 
763 		r->pci_addr = h;
764 		p = (volatile u_int16_t *)&r->pci_io_data;
765 		if (h & 2)
766 			p++;
767 	}
768 
769 	*p = htole16(vv);
770 }
771 
772 void
773 dino_w4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv)
774 {
775 	h += o;
776 	vv = htole32(vv);
777 	if (h & 0xf0000000)
778 		*(volatile u_int32_t *)h = vv;
779 	else {
780 		struct dino_softc *sc = v;
781 		volatile struct dino_regs *r = sc->sc_regs;
782 
783 		r->pci_addr = h;
784 		r->pci_io_data = vv;
785 	}
786 }
787 
788 void
789 dino_w8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv)
790 {
791 	h += o;
792 	if (h & 0xf0000000)
793 		*(volatile u_int64_t *)h = htole64(vv);
794 	else
795 		panic("dino_w8: not implemented");
796 }
797 
798 
799 void
800 dino_rm_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t *a, bus_size_t c)
801 {
802 	volatile u_int8_t *p;
803 
804 	h += o;
805 	if (h & 0xf0000000)
806 		p = (volatile u_int8_t *)h;
807 	else {
808 		struct dino_softc *sc = v;
809 		volatile struct dino_regs *r = sc->sc_regs;
810 
811 		r->pci_addr = h;
812 		p = (volatile u_int8_t *)&r->pci_io_data + (h & 3);
813 	}
814 
815 	while (c--)
816 		*a++ = *p;
817 }
818 
819 void
820 dino_rm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c)
821 {
822 	volatile u_int16_t *p;
823 
824 	h += o;
825 	if (h & 0xf0000000)
826 		p = (volatile u_int16_t *)h;
827 	else {
828 		struct dino_softc *sc = v;
829 		volatile struct dino_regs *r = sc->sc_regs;
830 
831 		r->pci_addr = h;
832 		p = (volatile u_int16_t *)&r->pci_io_data;
833 		if (h & 2)
834 			p++;
835 	}
836 
837 	while (c--)
838 		*a++ = letoh16(*p);
839 }
840 
841 void
842 dino_rm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c)
843 {
844 	volatile u_int32_t *p;
845 
846 	h += o;
847 	if (h & 0xf0000000)
848 		p = (volatile u_int32_t *)h;
849 	else {
850 		struct dino_softc *sc = v;
851 		volatile struct dino_regs *r = sc->sc_regs;
852 
853 		r->pci_addr = h;
854 		p = (volatile u_int32_t *)&r->pci_io_data;
855 	}
856 
857 	while (c--)
858 		*a++ = letoh32(*p);
859 }
860 
861 void
862 dino_rm_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t *a, bus_size_t c)
863 {
864 	panic("dino_rm_8: not implemented");
865 }
866 
867 void
868 dino_wm_1(void *v, bus_space_handle_t h, bus_size_t o, const u_int8_t *a, bus_size_t c)
869 {
870 	volatile u_int8_t *p;
871 
872 	h += o;
873 	if (h & 0xf0000000)
874 		p = (volatile u_int8_t *)h;
875 	else {
876 		struct dino_softc *sc = v;
877 		volatile struct dino_regs *r = sc->sc_regs;
878 
879 		r->pci_addr = h;
880 		p = (volatile u_int8_t *)&r->pci_io_data + (h & 3);
881 	}
882 
883 	while (c--)
884 		*p = *a++;
885 }
886 
887 void
888 dino_wm_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c)
889 {
890 	volatile u_int16_t *p;
891 
892 	h += o;
893 	if (h & 0xf0000000)
894 		p = (volatile u_int16_t *)h;
895 	else {
896 		struct dino_softc *sc = v;
897 		volatile struct dino_regs *r = sc->sc_regs;
898 
899 		r->pci_addr = h;
900 		p = (volatile u_int16_t *)&r->pci_io_data;
901 		if (h & 2)
902 			p++;
903 	}
904 
905 	while (c--)
906 		*p = htole16(*a++);
907 }
908 
909 void
910 dino_wm_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c)
911 {
912 	volatile u_int32_t *p;
913 
914 	h += o;
915 	if (h & 0xf0000000)
916 		p = (volatile u_int32_t *)h;
917 	else {
918 		struct dino_softc *sc = v;
919 		volatile struct dino_regs *r = sc->sc_regs;
920 
921 		r->pci_addr = h;
922 		p = (volatile u_int32_t *)&r->pci_io_data;
923 	}
924 
925 	while (c--)
926 		*p = htole32(*a++);
927 }
928 
929 void
930 dino_wm_8(void *v, bus_space_handle_t h, bus_size_t o, const u_int64_t *a, bus_size_t c)
931 {
932 	panic("dino_wm_8: not implemented");
933 }
934 
935 void
936 dino_sm_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv, bus_size_t c)
937 {
938 	volatile u_int8_t *p;
939 
940 	h += o;
941 	if (h & 0xf0000000)
942 		p = (volatile u_int8_t *)h;
943 	else {
944 		struct dino_softc *sc = v;
945 		volatile struct dino_regs *r = sc->sc_regs;
946 
947 		r->pci_addr = h;
948 		p = (volatile u_int8_t *)&r->pci_io_data + (h & 3);
949 	}
950 
951 	while (c--)
952 		*p = vv;
953 }
954 
955 void
956 dino_sm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c)
957 {
958 	volatile u_int16_t *p;
959 
960 	h += o;
961 	if (h & 0xf0000000)
962 		p = (volatile u_int16_t *)h;
963 	else {
964 		struct dino_softc *sc = v;
965 		volatile struct dino_regs *r = sc->sc_regs;
966 
967 		r->pci_addr = h;
968 		p = (volatile u_int16_t *)&r->pci_io_data;
969 		if (h & 2)
970 			p++;
971 	}
972 
973 	vv = htole16(vv);
974 	while (c--)
975 		*p = vv;
976 }
977 
978 void
979 dino_sm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c)
980 {
981 	volatile u_int32_t *p;
982 
983 	h += o;
984 	if (h & 0xf0000000)
985 		p = (volatile u_int32_t *)h;
986 	else {
987 		struct dino_softc *sc = v;
988 		volatile struct dino_regs *r = sc->sc_regs;
989 
990 		r->pci_addr = h;
991 		p = (volatile u_int32_t *)&r->pci_io_data;
992 	}
993 
994 	vv = htole32(vv);
995 	while (c--)
996 		*p = vv;
997 }
998 
999 void
1000 dino_sm_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv, bus_size_t c)
1001 {
1002 	panic("dino_sm_8: not implemented");
1003 }
1004 
1005 void
1006 dino_rrm_2(void *v, bus_space_handle_t h, bus_size_t o,
1007     u_int8_t *a, bus_size_t c)
1008 {
1009 	volatile u_int16_t *p, *q = (u_int16_t *)a;
1010 
1011 	h += o;
1012 	if (h & 0xf0000000)
1013 		p = (volatile u_int16_t *)h;
1014 	else {
1015 		struct dino_softc *sc = v;
1016 		volatile struct dino_regs *r = sc->sc_regs;
1017 
1018 		r->pci_addr = h;
1019 		p = (volatile u_int16_t *)&r->pci_io_data;
1020 		if (h & 2)
1021 			p++;
1022 	}
1023 
1024 	c /= 2;
1025 	while (c--)
1026 		*q++ = *p;
1027 }
1028 
1029 void
1030 dino_rrm_4(void *v, bus_space_handle_t h, bus_size_t o,
1031     u_int8_t *a, bus_size_t c)
1032 {
1033 	volatile u_int32_t *p, *q = (u_int32_t *)a;
1034 
1035 	h += o;
1036 	if (h & 0xf0000000)
1037 		p = (volatile u_int32_t *)h;
1038 	else {
1039 		struct dino_softc *sc = v;
1040 		volatile struct dino_regs *r = sc->sc_regs;
1041 
1042 		r->pci_addr = h;
1043 		p = (volatile u_int32_t *)&r->pci_io_data;
1044 	}
1045 
1046 	c /= 4;
1047 	while (c--)
1048 		*q++ = *p;
1049 }
1050 
1051 void
1052 dino_rrm_8(void *v, bus_space_handle_t h, bus_size_t o,
1053     u_int8_t *a, bus_size_t c)
1054 {
1055 	panic("dino_rrm_8: not implemented");
1056 }
1057 
1058 void
1059 dino_wrm_2(void *v, bus_space_handle_t h, bus_size_t o,
1060     const u_int8_t *a, bus_size_t c)
1061 {
1062 	volatile u_int16_t *p;
1063 	const u_int16_t *q = (const u_int16_t *)a;
1064 
1065 	h += o;
1066 	if (h & 0xf0000000)
1067 		p = (volatile u_int16_t *)h;
1068 	else {
1069 		struct dino_softc *sc = v;
1070 		volatile struct dino_regs *r = sc->sc_regs;
1071 
1072 		r->pci_addr = h;
1073 		p = (volatile u_int16_t *)&r->pci_io_data;
1074 		if (h & 2)
1075 			p++;
1076 	}
1077 
1078 	c /= 2;
1079 	while (c--)
1080 		*p = *q++;
1081 }
1082 
1083 void
1084 dino_wrm_4(void *v, bus_space_handle_t h, bus_size_t o,
1085     const u_int8_t *a, bus_size_t c)
1086 {
1087 	volatile u_int32_t *p;
1088 	const u_int32_t *q = (const u_int32_t *)a;
1089 
1090 	h += o;
1091 	if (h & 0xf0000000)
1092 		p = (volatile u_int32_t *)h;
1093 	else {
1094 		struct dino_softc *sc = v;
1095 		volatile struct dino_regs *r = sc->sc_regs;
1096 
1097 		r->pci_addr = h;
1098 		p = (volatile u_int32_t *)&r->pci_io_data;
1099 	}
1100 
1101 	c /= 4;
1102 	while (c--)
1103 		*p = *q++;
1104 }
1105 
1106 void
1107 dino_wrm_8(void *v, bus_space_handle_t h, bus_size_t o,
1108     const u_int8_t *a, bus_size_t c)
1109 {
1110 	panic("dino_wrm_8: not implemented");
1111 }
1112 
1113 void
1114 dino_rr_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t *a, bus_size_t c)
1115 {
1116 	volatile u_int8_t *p;
1117 
1118 	h += o;
1119 	if (h & 0xf0000000) {
1120 		p = (volatile u_int8_t *)h;
1121 		while (c--)
1122 			*a++ = *p++;
1123 	} else {
1124 		struct dino_softc *sc = v;
1125 		volatile struct dino_regs *r = sc->sc_regs;
1126 
1127 		for (; c--; h++) {
1128 		  	r->pci_addr = h;
1129 			p = (volatile u_int8_t *)&r->pci_io_data + (h & 3);
1130 			*a++ = *p;
1131 		}
1132 	}
1133 }
1134 
1135 void
1136 dino_rr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c)
1137 {
1138 	volatile u_int16_t *p, data;
1139 
1140 	h += o;
1141 	if (h & 0xf0000000) {
1142 		p = (volatile u_int16_t *)h;
1143 		while (c--) {
1144 			data = *p++;
1145 			*a++ = letoh16(data);
1146 		}
1147 	} else {
1148 		struct dino_softc *sc = v;
1149 		volatile struct dino_regs *r = sc->sc_regs;
1150 
1151 		for (; c--; h += 2) {
1152 			r->pci_addr = h;
1153 			p = (volatile u_int16_t *)&r->pci_io_data;
1154 			if (h & 2)
1155 				p++;
1156 			data = *p;
1157 			*a++ = letoh16(data);
1158 		}
1159 	}
1160 }
1161 
1162 void
1163 dino_rr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c)
1164 {
1165 	volatile u_int32_t *p, data;
1166 
1167 	h += o;
1168 	if (h & 0xf0000000) {
1169 		p = (volatile u_int32_t *)h;
1170 		while (c--) {
1171 			data = *p++;
1172 			*a++ = letoh32(data);
1173 		}
1174 	} else {
1175 		struct dino_softc *sc = v;
1176 		volatile struct dino_regs *r = sc->sc_regs;
1177 
1178 		for (; c--; h += 4) {
1179 			r->pci_addr = h;
1180 			data = r->pci_io_data;
1181 			*a++ = letoh32(data);
1182 		}
1183 	}
1184 }
1185 
1186 void
1187 dino_rr_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t *a, bus_size_t c)
1188 {
1189 	panic("dino_rr_8: not implemented");
1190 }
1191 
1192 void
1193 dino_wr_1(void *v, bus_space_handle_t h, bus_size_t o, const u_int8_t *a, bus_size_t c)
1194 {
1195 	volatile u_int8_t *p;
1196 
1197 	h += o;
1198 	if (h & 0xf0000000) {
1199 		p = (volatile u_int8_t *)h;
1200 		while (c--)
1201 			*p++ = *a++;
1202 	} else {
1203 		struct dino_softc *sc = v;
1204 		volatile struct dino_regs *r = sc->sc_regs;
1205 
1206 		for (; c--; h++) {
1207 			r->pci_addr = h;
1208 			p = (volatile u_int8_t *)&r->pci_io_data + (h & 3);
1209 			*p = *a++;
1210 		}
1211 	}
1212 }
1213 
1214 void
1215 dino_wr_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c)
1216 {
1217 	volatile u_int16_t *p, data;
1218 
1219 	h += o;
1220 	if (h & 0xf0000000) {
1221 		p = (volatile u_int16_t *)h;
1222 		while (c--) {
1223 			data = *a++;
1224 			*p++ = htole16(data);
1225 		}
1226 	} else {
1227 		struct dino_softc *sc = v;
1228 		volatile struct dino_regs *r = sc->sc_regs;
1229 
1230 		for (; c--; h += 2) {
1231 			r->pci_addr = h;
1232 			p = (volatile u_int16_t *)&r->pci_io_data;
1233 			if (h & 2)
1234 				p++;
1235 			data = *a++;
1236 			*p = htole16(data);
1237 		}
1238 	}
1239 }
1240 
1241 void
1242 dino_wr_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c)
1243 {
1244 	volatile u_int32_t *p, data;
1245 
1246 	h += o;
1247 	if (h & 0xf0000000) {
1248 		p = (volatile u_int32_t *)h;
1249 		while (c--) {
1250 			data = *a++;
1251 			*p++ = htole32(data);
1252 		}
1253 	} else {
1254 		struct dino_softc *sc = v;
1255 		volatile struct dino_regs *r = sc->sc_regs;
1256 
1257 		for (; c--; h += 4) {
1258 			r->pci_addr = h;
1259 			data = *a++;
1260 			r->pci_io_data = htole32(data);
1261 		}
1262 	}
1263 }
1264 
1265 void
1266 dino_wr_8(void *v, bus_space_handle_t h, bus_size_t o, const u_int64_t *a, bus_size_t c)
1267 {
1268 	panic("dino_wr_8: not implemented");
1269 }
1270 
1271 void
1272 dino_rrr_2(void *v, bus_space_handle_t h, bus_size_t o,
1273     u_int8_t *a, bus_size_t c)
1274 {
1275 	volatile u_int16_t *p, *q = (u_int16_t *)a;
1276 
1277 	c /= 2;
1278 	h += o;
1279 	if (h & 0xf0000000) {
1280 		p = (volatile u_int16_t *)h;
1281 		while (c--)
1282 			*q++ = *p++;
1283 	} else {
1284 		struct dino_softc *sc = v;
1285 		volatile struct dino_regs *r = sc->sc_regs;
1286 
1287 		for (; c--; h += 2) {
1288 			r->pci_addr = h;
1289 			p = (volatile u_int16_t *)&r->pci_io_data;
1290 			if (h & 2)
1291 				p++;
1292 			*q++ = *p;
1293 		}
1294 	}
1295 }
1296 
1297 void
1298 dino_rrr_4(void *v, bus_space_handle_t h, bus_size_t o,
1299     u_int8_t *a, bus_size_t c)
1300 {
1301 	volatile u_int32_t *p, *q = (u_int32_t *)a;
1302 
1303 	c /= 4;
1304 	h += o;
1305 	if (h & 0xf0000000) {
1306 		p = (volatile u_int32_t *)h;
1307 		while (c--)
1308 			*q++ = *p++;
1309 	} else {
1310 		struct dino_softc *sc = v;
1311 		volatile struct dino_regs *r = sc->sc_regs;
1312 
1313 		for (; c--; h += 4) {
1314 			r->pci_addr = h;
1315 			*q++ = r->pci_io_data;
1316 		}
1317 	}
1318 }
1319 
1320 void
1321 dino_rrr_8(void *v, bus_space_handle_t h, bus_size_t o,
1322     u_int8_t *a, bus_size_t c)
1323 {
1324 	panic("dino_rrr_8: not implemented");
1325 }
1326 
1327 void
1328 dino_wrr_2(void *v, bus_space_handle_t h, bus_size_t o,
1329     const u_int8_t *a, bus_size_t c)
1330 {
1331 	volatile u_int16_t *p;
1332 	const u_int16_t *q = (u_int16_t *)a;
1333 
1334 	c /= 2;
1335 	h += o;
1336 	if (h & 0xf0000000) {
1337 		p = (volatile u_int16_t *)h;
1338 		while (c--)
1339 			*p++ = *q++;
1340 	} else {
1341 		struct dino_softc *sc = v;
1342 		volatile struct dino_regs *r = sc->sc_regs;
1343 
1344 		for (; c--; h += 2) {
1345 			r->pci_addr = h;
1346 			p = (volatile u_int16_t *)&r->pci_io_data;
1347 			if (h & 2)
1348 				p++;
1349 			*p = *q++;
1350 		}
1351 	}
1352 }
1353 
1354 void
1355 dino_wrr_4(void *v, bus_space_handle_t h, bus_size_t o,
1356     const u_int8_t *a, bus_size_t c)
1357 {
1358 	volatile u_int32_t *p;
1359 	const u_int32_t *q = (u_int32_t *)a;
1360 
1361 	c /= 4;
1362 	h += o;
1363 	if (h & 0xf0000000) {
1364 		p = (volatile u_int32_t *)h;
1365 		while (c--)
1366 			*p++ = *q++;
1367 	} else {
1368 		struct dino_softc *sc = v;
1369 		volatile struct dino_regs *r = sc->sc_regs;
1370 
1371 		for (; c--; h += 4) {
1372 			r->pci_addr = h;
1373 			r->pci_io_data = *q++;
1374 		}
1375 	}
1376 }
1377 
1378 void
1379 dino_wrr_8(void *v, bus_space_handle_t h, bus_size_t o,
1380     const u_int8_t *a, bus_size_t c)
1381 {
1382 	panic("dino_wrr_8: not implemented");
1383 }
1384 
1385 void
1386 dino_sr_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv, bus_size_t c)
1387 {
1388 	volatile u_int8_t *p;
1389 
1390 	h += o;
1391 	if (h & 0xf0000000) {
1392 		p = (volatile u_int8_t *)h;
1393 		while (c--)
1394 			*p++ = vv;
1395 	} else {
1396 		struct dino_softc *sc = v;
1397 		volatile struct dino_regs *r = sc->sc_regs;
1398 
1399 		for (; c--; h++) {
1400 			r->pci_addr = h;
1401 			p = (volatile u_int8_t *)&r->pci_io_data + (h & 3);
1402 			*p = vv;
1403 		}
1404 	}
1405 }
1406 
1407 void
1408 dino_sr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c)
1409 {
1410 	volatile u_int16_t *p;
1411 
1412 	h += o;
1413 	vv = htole16(vv);
1414 	if (h & 0xf0000000) {
1415 		p = (volatile u_int16_t *)h;
1416 		while (c--)
1417 			*p++ = vv;
1418 	} else {
1419 		struct dino_softc *sc = v;
1420 		volatile struct dino_regs *r = sc->sc_regs;
1421 
1422 		for (; c--; h += 2) {
1423 			r->pci_addr = h;
1424 			p = (volatile u_int16_t *)&r->pci_io_data;
1425 			if (h & 2)
1426 				p++;
1427 			*p = vv;
1428 		}
1429 	}
1430 }
1431 
1432 void
1433 dino_sr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c)
1434 {
1435 	volatile u_int32_t *p;
1436 
1437 	h += o;
1438 	vv = htole32(vv);
1439 	if (h & 0xf0000000) {
1440 		p = (volatile u_int32_t *)h;
1441 		while (c--)
1442 			*p++ = vv;
1443 	} else {
1444 		struct dino_softc *sc = v;
1445 		volatile struct dino_regs *r = sc->sc_regs;
1446 
1447 		for (; c--; h += 4) {
1448 			r->pci_addr = h;
1449 			r->pci_io_data = vv;
1450 		}
1451 	}
1452 }
1453 
1454 void
1455 dino_sr_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv, bus_size_t c)
1456 {
1457 	panic("dino_sr_8: not implemented");
1458 }
1459 
1460 void
1461 dino_cp_1(void *v, bus_space_handle_t h1, bus_size_t o1,
1462 	  bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
1463 {
1464 	while (c--)
1465 		dino_w1(v, h1, o1++, dino_r1(v, h2, o2++));
1466 }
1467 
1468 void
1469 dino_cp_2(void *v, bus_space_handle_t h1, bus_size_t o1,
1470 	  bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
1471 {
1472 	while (c--) {
1473 		dino_w2(v, h1, o1, dino_r2(v, h2, o2));
1474 		o1 += 2;
1475 		o2 += 2;
1476 	}
1477 }
1478 
1479 void
1480 dino_cp_4(void *v, bus_space_handle_t h1, bus_size_t o1,
1481 	  bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
1482 {
1483 	while (c--) {
1484 		dino_w4(v, h1, o1, dino_r4(v, h2, o2));
1485 		o1 += 4;
1486 		o2 += 4;
1487 	}
1488 }
1489 
1490 void
1491 dino_cp_8(void *v, bus_space_handle_t h1, bus_size_t o1,
1492 	  bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
1493 {
1494 	while (c--) {
1495 		dino_w8(v, h1, o1, dino_r8(v, h2, o2));
1496 		o1 += 8;
1497 		o2 += 8;
1498 	}
1499 }
1500 
1501 
1502 const struct hppa_bus_space_tag dino_iomemt = {
1503 	NULL,
1504 
1505 	NULL, dino_unmap, dino_subregion, NULL, dino_free,
1506 	dino_barrier, dino_vaddr,
1507 	dino_r1,    dino_r2,    dino_r4,    dino_r8,
1508 	dino_w1,    dino_w2,    dino_w4,    dino_w8,
1509 	dino_rm_1,  dino_rm_2,  dino_rm_4,  dino_rm_8,
1510 	dino_wm_1,  dino_wm_2,  dino_wm_4,  dino_wm_8,
1511 	dino_sm_1,  dino_sm_2,  dino_sm_4,  dino_sm_8,
1512 	            dino_rrm_2, dino_rrm_4, dino_rrm_8,
1513 	            dino_wrm_2, dino_wrm_4, dino_wrm_8,
1514 	dino_rr_1,  dino_rr_2,  dino_rr_4,  dino_rr_8,
1515 	dino_wr_1,  dino_wr_2,  dino_wr_4,  dino_wr_8,
1516 	            dino_rrr_2, dino_rrr_4, dino_rrr_8,
1517 	            dino_wrr_2, dino_wrr_4, dino_wrr_8,
1518 	dino_sr_1,  dino_sr_2,  dino_sr_4,  dino_sr_8,
1519 	dino_cp_1,  dino_cp_2,  dino_cp_4,  dino_cp_8
1520 };
1521 
1522 int
1523 dino_dmamap_create(void *v, bus_size_t size, int nsegments,
1524     bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp)
1525 {
1526 	struct dino_softc *sc = v;
1527 
1528 	/* TODO check the addresses, boundary, enable dma */
1529 
1530 	return (bus_dmamap_create(sc->sc_dmat, size, nsegments,
1531 	    maxsegsz, boundary, flags, dmamp));
1532 }
1533 
1534 void
1535 dino_dmamap_destroy(void *v, bus_dmamap_t map)
1536 {
1537 	struct dino_softc *sc = v;
1538 
1539 	bus_dmamap_destroy(sc->sc_dmat, map);
1540 }
1541 
1542 int
1543 dino_dmamap_load(void *v, bus_dmamap_t map, void *addr, bus_size_t size,
1544     struct proc *p, int flags)
1545 {
1546 	struct dino_softc *sc = v;
1547 
1548 	return (bus_dmamap_load(sc->sc_dmat, map, addr, size, p, flags));
1549 }
1550 
1551 int
1552 dino_dmamap_load_mbuf(void *v, bus_dmamap_t map, struct mbuf *m, int flags)
1553 {
1554 	struct dino_softc *sc = v;
1555 
1556 	return (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, flags));
1557 }
1558 
1559 int
1560 dino_dmamap_load_uio(void *v, bus_dmamap_t map, struct uio *uio, int flags)
1561 {
1562 	struct dino_softc *sc = v;
1563 
1564 	return (bus_dmamap_load_uio(sc->sc_dmat, map, uio, flags));
1565 }
1566 
1567 int
1568 dino_dmamap_load_raw(void *v, bus_dmamap_t map, bus_dma_segment_t *segs,
1569     int nsegs, bus_size_t size, int flags)
1570 {
1571 	struct dino_softc *sc = v;
1572 
1573 	return (bus_dmamap_load_raw(sc->sc_dmat, map, segs, nsegs, size, flags));
1574 }
1575 
1576 void
1577 dino_dmamap_unload(void *v, bus_dmamap_t map)
1578 {
1579 	struct dino_softc *sc = v;
1580 
1581 	bus_dmamap_unload(sc->sc_dmat, map);
1582 }
1583 
1584 void
1585 dino_dmamap_sync(void *v, bus_dmamap_t map, bus_addr_t off,
1586     bus_size_t len, int ops)
1587 {
1588 	struct dino_softc *sc = v;
1589 
1590 	return (bus_dmamap_sync(sc->sc_dmat, map, off, len, ops));
1591 }
1592 
1593 int
1594 dino_dmamem_alloc(void *v, bus_size_t size, bus_size_t alignment,
1595     bus_size_t boundary, bus_dma_segment_t *segs,
1596     int nsegs, int *rsegs, int flags)
1597 {
1598 	struct dino_softc *sc = v;
1599 
1600 	return (bus_dmamem_alloc(sc->sc_dmat, size, alignment, boundary,
1601 	    segs, nsegs, rsegs, flags));
1602 }
1603 
1604 void
1605 dino_dmamem_free(void *v, bus_dma_segment_t *segs, int nsegs)
1606 {
1607 	struct dino_softc *sc = v;
1608 
1609 	bus_dmamem_free(sc->sc_dmat, segs, nsegs);
1610 }
1611 
1612 int
1613 dino_dmamem_map(void *v, bus_dma_segment_t *segs, int nsegs, size_t size,
1614     caddr_t *kvap, int flags)
1615 {
1616 	struct dino_softc *sc = v;
1617 
1618 	return (bus_dmamem_map(sc->sc_dmat, segs, nsegs, size, kvap, flags));
1619 }
1620 
1621 void
1622 dino_dmamem_unmap(void *v, caddr_t kva, size_t size)
1623 {
1624 	struct dino_softc *sc = v;
1625 
1626 	bus_dmamem_unmap(sc->sc_dmat, kva, size);
1627 }
1628 
1629 paddr_t
1630 dino_dmamem_mmap(void *v, bus_dma_segment_t *segs, int nsegs, off_t off,
1631     int prot, int flags)
1632 {
1633 	struct dino_softc *sc = v;
1634 
1635 	return (bus_dmamem_mmap(sc->sc_dmat, segs, nsegs, off, prot, flags));
1636 }
1637 
1638 const struct hppa_bus_dma_tag dino_dmat = {
1639 	NULL,
1640 	dino_dmamap_create, dino_dmamap_destroy,
1641 	dino_dmamap_load, dino_dmamap_load_mbuf,
1642 	dino_dmamap_load_uio, dino_dmamap_load_raw,
1643 	dino_dmamap_unload, dino_dmamap_sync,
1644 
1645 	dino_dmamem_alloc, dino_dmamem_free, dino_dmamem_map,
1646 	dino_dmamem_unmap, dino_dmamem_mmap
1647 };
1648 
1649 const struct hppa_pci_chipset_tag dino_pc = {
1650 	NULL,
1651 	dino_attach_hook, dino_maxdevs, dino_make_tag, dino_decompose_tag,
1652 	dino_conf_size, dino_conf_read, dino_conf_write,
1653 	dino_intr_map, dino_intr_string,
1654 	dino_intr_establish, dino_intr_disestablish,
1655 #if NCARDBUS > 0
1656 	dino_alloc_parent
1657 #else
1658 	NULL
1659 #endif
1660 };
1661 
1662 int
1663 dinoprint(void *aux, const char *pnp)
1664 {
1665 	struct pcibus_attach_args *pba = aux;
1666 
1667 	if (pnp)
1668 		printf("%s at %s\n", pba->pba_busname, pnp);
1669 	return (UNCONF);
1670 }
1671 
1672 void
1673 dinoattach(parent, self, aux)
1674 	struct device *parent;
1675 	struct device *self;
1676 	void *aux;
1677 {
1678 	struct dino_softc *sc = (struct dino_softc *)self;
1679 	struct confargs *ca = (struct confargs *)aux;
1680 	struct pcibus_attach_args pba;
1681 	volatile struct dino_regs *r;
1682 	const char *p = NULL;
1683 	u_int data;
1684 	int s, irqbit;
1685 
1686 	sc->sc_bt = ca->ca_iot;
1687 	sc->sc_dmat = ca->ca_dmatag;
1688 	if (bus_space_map(sc->sc_bt, ca->ca_hpa, PAGE_SIZE, 0, &sc->sc_bh)) {
1689 		printf(": can't map space\n");
1690 		return;
1691 	}
1692 
1693 	sc->sc_regs = r = (volatile struct dino_regs *)sc->sc_bh;
1694 	r->pciror = 0;
1695 	r->pciwor = 0;
1696 
1697 	/*
1698 	 * Do not reset enabled io mappings mask if we are still running
1699 	 * with PDC console - we'll do it after autoconf.
1700 	 */
1701 	if (cn_tab->cn_putc != pdccnputc)
1702 		r->io_addr_en = 0;
1703 	sc->io_shadow = 0;
1704 
1705 	r->gmask &= ~1;	/* allow GSC bus req */
1706 	r->brdg_feat &= ~0xf00;
1707 	r->brdg_feat |= 3;
1708 #ifdef notyet_card_mode
1709 	r->io_control = 0x80;
1710 	r->pamr = 0;
1711 	r->papr = 0;
1712 	r->io_fbb_en |= 1;
1713 	r->damode = 0;
1714 	r->brdg_feat = 0xc0000000 XXX;
1715 	r->mltim = 0x40;	/* 64 clocks */
1716 	r->tltim = 0x8c;	/* 12 clocks */
1717 
1718 	/* PCI reset */
1719 	r->pcicmd = 0x6f;
1720 	DELAY(10000);		/* 10ms for reset to settle */
1721 #endif
1722 
1723 	snprintf(sc->sc_ioexname, sizeof(sc->sc_ioexname),
1724 	    "%s_io", sc->sc_dv.dv_xname);
1725 	if ((sc->sc_ioex = extent_create(sc->sc_ioexname, 0, 0xffff,
1726 	    M_DEVBUF, NULL, 0, EX_NOWAIT | EX_MALLOCOK)) == NULL) {
1727 		printf(": cannot allocate I/O extent map\n");
1728 		bus_space_unmap(sc->sc_bt, sc->sc_bh, PAGE_SIZE);
1729 		return;
1730 	}
1731 
1732 	/* TODO reserve dino's pci space ? */
1733 
1734 	sc->sc_ver = ca->ca_type.iodc_revision;
1735 	switch ((ca->ca_type.iodc_model << 4) |
1736 	    (ca->ca_type.iodc_revision >> 4)) {
1737 	case 0x05d:	/* j2240 */
1738 		p = "Dino(card)";
1739 	case 0x680:
1740 		if (!p)
1741 			p = "Dino";
1742 		switch (ca->ca_type.iodc_revision & 0xf) {
1743 		case 0:	sc->sc_ver = 0x20;	break;
1744 		case 1:	sc->sc_ver = 0x21;	break;
1745 		case 2:	sc->sc_ver = 0x30;	break;
1746 		case 3:	sc->sc_ver = 0x31;	break;
1747 		}
1748 		break;
1749 
1750 	case 0x682:
1751 		p = "Cujo";
1752 		switch (ca->ca_type.iodc_revision & 0xf) {
1753 		case 0:	sc->sc_ver = 0x10;	break;
1754 		case 1:	sc->sc_ver = 0x20;	break;
1755 		}
1756 		break;
1757 
1758 	default:
1759 		p = "Mojo";
1760 		break;
1761 	}
1762 
1763 	irqbit = cpu_intr_findirq();
1764 	if (irqbit >= 0)
1765 		printf(" irq %d", irqbit);
1766 
1767 	printf(": %s V%d.%d\n", p, sc->sc_ver >> 4, sc->sc_ver & 0xf);
1768 
1769 	s = splhigh();
1770 	r->imr = ~0;
1771 	data = r->irr0;
1772 	data = r->irr1;
1773 	r->imr = 0;
1774 	__asm volatile ("" ::: "memory");
1775 	r->icr = 0;
1776 	if (irqbit >= 0)
1777 		r->iar0 = cpu_gethpa(0) | (31 - irqbit);
1778 	splx(s);
1779 
1780 	if (irqbit < 0)
1781 		sc->sc_ih = NULL;
1782 	else
1783 		sc->sc_ih = cpu_intr_establish(IPL_NESTED, irqbit,
1784 		    dino_intr, (void *)sc->sc_regs, sc->sc_dv.dv_xname);
1785 	if (sc->sc_ih == NULL) {
1786 		printf("%s: can't establish interrupt\n", sc->sc_dv.dv_xname);
1787 		return;
1788 	}
1789 
1790 	/* TODO establish the bus error interrupt */
1791 
1792 	/* scan for ps2 kbd/ms, serial, and flying toasters */
1793 	ca->ca_hpamask = -1;
1794 	pdc_scanbus(self, ca, MAXMODBUS, 0, 0);
1795 
1796 	sc->sc_iot = dino_iomemt;
1797 	sc->sc_iot.hbt_cookie = sc;
1798 	sc->sc_iot.hbt_map = dino_iomap;
1799 	sc->sc_iot.hbt_alloc = dino_ioalloc;
1800 	sc->sc_memt = dino_iomemt;
1801 	sc->sc_memt.hbt_cookie = sc;
1802 	sc->sc_memt.hbt_map = dino_memmap;
1803 	sc->sc_memt.hbt_alloc = dino_memalloc;
1804 	sc->sc_pc = dino_pc;
1805 	sc->sc_pc._cookie = sc;
1806 	sc->sc_dmatag = dino_dmat;
1807 	sc->sc_dmatag._cookie = sc;
1808 
1809 	bzero(&pba, sizeof(pba));
1810 	pba.pba_busname = "pci";
1811 	pba.pba_iot = &sc->sc_iot;
1812 	pba.pba_memt = &sc->sc_memt;
1813 	pba.pba_dmat = &sc->sc_dmatag;
1814 	pba.pba_pc = &sc->sc_pc;
1815 	pba.pba_domain = pci_ndomains++;
1816 	pba.pba_bus = 0;
1817 	config_found(self, &pba, dinoprint);
1818 
1819 	/* postpone cleanup if necessary */
1820 	if (r->io_addr_en != sc->io_shadow)
1821 		startuphook_establish(dino_clear_pdc_mappings, sc);
1822 
1823 	/* enable interrupts now that all the devices are there */
1824 	r->imr = sc->sc_imr;
1825 }
1826 
1827 void
1828 dino_clear_pdc_mappings(void *v)
1829 {
1830 	struct dino_softc *sc = (struct dino_softc *)v;
1831 	volatile struct dino_regs *r;
1832 
1833 	if (cn_tab->cn_putc == pdccnputc) {
1834 		/* damn! */
1835 		return;
1836 	}
1837 
1838 	r = sc->sc_regs;
1839 	r->io_addr_en = sc->io_shadow;
1840 }
1841