xref: /openbsd-src/sys/arch/hppa/dev/elroy.c (revision a28daedfc357b214be5c701aa8ba8adb29a7f1c2)
1 /*	$OpenBSD: elroy.c,v 1.5 2009/03/30 21:24:57 kettenis Exp $	*/
2 
3 /*
4  * Copyright (c) 2005 Michael Shalayeff
5  * All rights reserved.
6  *
7  * Permission to use, copy, modify, and distribute this software for any
8  * purpose with or without fee is hereby granted, provided that the above
9  * copyright notice and this permission notice appear in all copies.
10  *
11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER IN
16  * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
17  * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 #include "cardbus.h"
21 
22 #include <sys/param.h>
23 #include <sys/systm.h>
24 #include <sys/device.h>
25 #include <sys/reboot.h>
26 #include <sys/malloc.h>
27 #include <sys/extent.h>
28 
29 #include <machine/iomod.h>
30 #include <machine/autoconf.h>
31 
32 #include <arch/hppa/dev/cpudevs.h>
33 
34 #if NCARDBUS > 0
35 #include <dev/cardbus/rbus.h>
36 #endif
37 
38 #include <dev/pci/pcireg.h>
39 #include <dev/pci/pcivar.h>
40 #include <dev/pci/pcidevs.h>
41 
42 #include <hppa/dev/elroyreg.h>
43 #include <hppa/dev/elroyvar.h>
44 
45 #define	ELROY_MEM_CHUNK		0x800000
46 #define	ELROY_MEM_WINDOW	(2 * ELROY_MEM_CHUNK)
47 
48 int	elroy_match(struct device *, void *, void *);
49 void	elroy_attach(struct device *, struct device *, void *);
50 int	elroy_intr(void *);
51 
52 struct cfattach elroy_ca = {
53 	sizeof(struct elroy_softc), elroy_match, elroy_attach
54 };
55 
56 struct cfdriver elroy_cd = {
57 	NULL, "elroy", DV_DULL
58 };
59 
60 int
61 elroy_match(struct device *parent, void *cfdata, void *aux)
62 {
63 	struct confargs *ca = aux;
64 	/* struct cfdata *cf = cfdata; */
65 
66 	if ((ca->ca_name && !strcmp(ca->ca_name, "lba")) ||
67 	    (ca->ca_type.iodc_type == HPPA_TYPE_BRIDGE &&
68 	     ca->ca_type.iodc_sv_model == HPPA_BRIDGE_DINO &&
69 	     ca->ca_type.iodc_model == 0x78))
70 		return (1);
71 
72 	return (0);
73 }
74 
75 void
76 elroy_write32(volatile u_int32_t *p, u_int32_t v)
77 {
78 	*p = v;
79 }
80 
81 u_int32_t
82 elroy_read32(volatile u_int32_t *p)
83 {
84 	return *p;
85 }
86 
87 void
88 elroy_attach_hook(struct device *parent, struct device *self,
89     struct pcibus_attach_args *pba)
90 {
91 
92 }
93 
94 int
95 elroy_maxdevs(void *v, int bus)
96 {
97 	return (32);
98 }
99 
100 pcitag_t
101 elroy_make_tag(void *v, int bus, int dev, int func)
102 {
103 	if (bus > 255 || dev > 31 || func > 7)
104 		panic("elroy_make_tag: bad request");
105 
106 	return ((bus << 16) | (dev << 11) | (func << 8));
107 }
108 
109 void
110 elroy_decompose_tag(void *v, pcitag_t tag, int *bus, int *dev, int *func)
111 {
112 	*bus = (tag >> 16) & 0xff;
113 	*dev = (tag >> 11) & 0x1f;
114 	*func= (tag >>  8) & 0x07;
115 }
116 
117 pcireg_t
118 elroy_conf_read(void *v, pcitag_t tag, int reg)
119 {
120 	struct elroy_softc *sc = v;
121 	volatile struct elroy_regs *r = sc->sc_regs;
122 	u_int32_t arb_mask, err_cfg, control;
123 	pcireg_t data, data1;
124 
125 /* printf("elroy_conf_read(%p, 0x%08x, 0x%x)", v, tag, reg); */
126 	arb_mask = elroy_read32(&r->arb_mask);
127 	err_cfg = elroy_read32(&r->err_cfg);
128 	control = elroy_read32(&r->control);
129 	if (!arb_mask)
130 		elroy_write32(&r->arb_mask, htole64(ELROY_ARB_ENABLE));
131 	elroy_write32(&r->err_cfg, err_cfg |
132 	    htole32(ELROY_ERRCFG_SMART | ELROY_ERRCFG_CM));
133 	elroy_write32(&r->control, (control | htole32(ELROY_CONTROL_CE)) &
134 	    ~htole32(ELROY_CONTROL_HF));
135 
136 	elroy_write32(&r->pci_conf_addr, htole32(tag | reg));
137 	data1 = elroy_read32(&r->pci_conf_addr);
138 	data = elroy_read32(&r->pci_conf_data);
139 
140 	elroy_write32(&r->control, control |
141 	    htole32(ELROY_CONTROL_CE|ELROY_CONTROL_CL));
142 	elroy_write32(&r->control, control);
143 	elroy_write32(&r->err_cfg, err_cfg);
144 	if (!arb_mask)
145 		elroy_write32(&r->arb_mask, arb_mask);
146 
147 	data = letoh32(data);
148 /* printf("=0x%08x (@ 0x%08x)\n", data, letoh32(data1)); */
149 	return (data);
150 }
151 
152 void
153 elroy_conf_write(void *v, pcitag_t tag, int reg, pcireg_t data)
154 {
155 	struct elroy_softc *sc = v;
156 	volatile struct elroy_regs *r = sc->sc_regs;
157 	u_int32_t arb_mask, err_cfg, control;
158 	pcireg_t data1;
159 
160 /* printf("elroy_conf_write(%p, 0x%08x, 0x%x, 0x%x)\n", v, tag, reg, data); */
161 	arb_mask = elroy_read32(&r->arb_mask);
162 	err_cfg = elroy_read32(&r->err_cfg);
163 	control = elroy_read32(&r->control);
164 	if (!arb_mask)
165 		elroy_write32(&r->arb_mask, htole64(ELROY_ARB_ENABLE));
166 	elroy_write32(&r->err_cfg, err_cfg |
167 	    htole32(ELROY_ERRCFG_SMART | ELROY_ERRCFG_CM));
168 	elroy_write32(&r->control, (control | htole32(ELROY_CONTROL_CE)) &
169 	    ~htole32(ELROY_CONTROL_HF));
170 
171 	/* fix coalescing config writes errata by interleaving w/ a read */
172 	elroy_write32(&r->pci_conf_addr, htole32(tag | PCI_ID_REG));
173 	data1 = elroy_read32(&r->pci_conf_addr);
174 	data1 = elroy_read32(&r->pci_conf_data);
175 
176 	elroy_write32(&r->pci_conf_addr, htole32(tag | reg));
177 	data1 = elroy_read32(&r->pci_conf_addr);
178 	elroy_write32(&r->pci_conf_data, htole32(data));
179 	data1 = elroy_read32(&r->pci_conf_addr);
180 
181 	elroy_write32(&r->control, control |
182 	    htole32(ELROY_CONTROL_CE|ELROY_CONTROL_CL));
183 	elroy_write32(&r->control, control);
184 	elroy_write32(&r->err_cfg, err_cfg);
185 	if (!arb_mask)
186 		elroy_write32(&r->arb_mask, arb_mask);
187 }
188 
189 int
190 elroy_iomap(void *v, bus_addr_t bpa, bus_size_t size,
191     int flags, bus_space_handle_t *bshp)
192 {
193 	struct elroy_softc *sc = v;
194 	/* volatile struct elroy_regs *r = sc->sc_regs; */
195 	int error;
196 
197 	if ((error = bus_space_map(sc->sc_bt, bpa + sc->sc_iobase, size,
198 	    flags, bshp)))
199 		return (error);
200 
201 	return (0);
202 }
203 
204 int
205 elroy_memmap(void *v, bus_addr_t bpa, bus_size_t size,
206     int flags, bus_space_handle_t *bshp)
207 {
208 	struct elroy_softc *sc = v;
209 	/* volatile struct elroy_regs *r = sc->sc_regs; */
210 	int error;
211 
212 	if ((error = bus_space_map(sc->sc_bt, bpa, size, flags, bshp)))
213 		return (error);
214 
215 	return (0);
216 }
217 
218 int
219 elroy_subregion(void *v, bus_space_handle_t bsh, bus_size_t offset,
220     bus_size_t size, bus_space_handle_t *nbshp)
221 {
222 	*nbshp = bsh + offset;
223 	return (0);
224 }
225 
226 int
227 elroy_ioalloc(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
228     bus_size_t align, bus_size_t boundary, int flags, bus_addr_t *addrp,
229     bus_space_handle_t *bshp)
230 {
231 	struct elroy_softc *sc = v;
232 	volatile struct elroy_regs *r = sc->sc_regs;
233 	bus_addr_t iostart, ioend;
234 
235 	iostart = r->io_base & ~htole32(ELROY_BASE_RE);
236 	ioend = iostart + ~htole32(r->io_mask) + 1;
237 	if (rstart < iostart || rend > ioend)
238 		panic("elroy_ioalloc: bad region start/end");
239 
240 	rstart += sc->sc_iobase;
241 	rend += sc->sc_iobase;
242 	if (bus_space_alloc(sc->sc_bt, rstart, rend, size,
243 	    align, boundary, flags, addrp, bshp))
244 		return (ENOMEM);
245 
246 	return (0);
247 }
248 
249 int
250 elroy_memalloc(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
251     bus_size_t align, bus_size_t boundary, int flags, bus_addr_t *addrp,
252     bus_space_handle_t *bshp)
253 {
254 	struct elroy_softc *sc = v;
255 	/* volatile struct elroy_regs *r = sc->sc_regs; */
256 
257 	if (bus_space_alloc(sc->sc_bt, rstart, rend, size,
258 	    align, boundary, flags, addrp, bshp))
259 		return (ENOMEM);
260 
261 	return (0);
262 }
263 
264 void
265 elroy_unmap(void *v, bus_space_handle_t bsh, bus_size_t size)
266 {
267 	struct elroy_softc *sc = v;
268 
269 	bus_space_free(sc->sc_bt, bsh, size);
270 }
271 
272 void
273 elroy_free(void *v, bus_space_handle_t bh, bus_size_t size)
274 {
275 	/* should be enough */
276 	elroy_unmap(v, bh, size);
277 }
278 
279 void
280 elroy_barrier(void *v, bus_space_handle_t h, bus_size_t o, bus_size_t l, int op)
281 {
282 	struct elroy_softc *sc = v;
283 	volatile struct elroy_regs *r = sc->sc_regs;
284 	u_int32_t data;
285 
286 	sync_caches();
287 	if (op & BUS_SPACE_BARRIER_WRITE) {
288 		data = r->pci_id;	/* flush write fifo */
289 		sync_caches();
290 	}
291 }
292 
293 #if NCARDBUS > 0
294 void *
295 elroy_alloc_parent(struct device *self, struct pci_attach_args *pa, int io)
296 {
297 #if 0	/* TODO */
298 
299 	struct elroy_softc *sc = pa->pa_pc->_cookie;
300 	struct extent *ex;
301 	bus_space_tag_t tag;
302 	bus_addr_t start;
303 	bus_size_t size;
304 
305 	if (io) {
306 		ex = sc->sc_ioex;
307 		tag = pa->pa_iot;
308 		start = 0xa000;
309 		size = 0x1000;
310 	} else {
311 		if (!sc->sc_memex) {
312 			bus_space_handle_t memh;
313 			bus_addr_t mem_start;
314 
315 			if (elroy_memalloc(sc, 0xf0800000, 0xff7fffff,
316 			    ELROY_MEM_WINDOW, ELROY_MEM_WINDOW, EX_NOBOUNDARY,
317 			    0, &mem_start, &memh))
318 				return (NULL);
319 
320 			snprintf(sc->sc_memexname, sizeof(sc->sc_memexname),
321 			    "%s_mem", sc->sc_dv.dv_xname);
322 			if ((sc->sc_memex = extent_create(sc->sc_memexname,
323 			    mem_start, mem_start + ELROY_MEM_WINDOW, M_DEVBUF,
324 			    NULL, 0, EX_NOWAIT | EX_MALLOCOK)) == NULL) {
325 				extent_destroy(sc->sc_ioex);
326 				bus_space_free(sc->sc_bt, memh,
327 				    ELROY_MEM_WINDOW);
328 				return (NULL);
329 			}
330 		}
331 		ex = sc->sc_memex;
332 		tag = pa->pa_memt;
333 		start = ex->ex_start;
334 		size = ELROY_MEM_CHUNK;
335 	}
336 
337 	if (extent_alloc_subregion(ex, start, ex->ex_end, size, size, 0,
338 	    EX_NOBOUNDARY, EX_NOWAIT, &start))
339 		return (NULL);
340 
341 	extent_free(ex, start, size, EX_NOWAIT);
342 	return rbus_new_root_share(tag, ex, start, size, 0);
343 #else
344 	return (NULL);
345 #endif
346 }
347 #endif
348 
349 void *
350 elroy_vaddr(void *v, bus_space_handle_t h)
351 {
352 	return ((void *)h);
353 }
354 
355 u_int8_t
356 elroy_r1(void *v, bus_space_handle_t h, bus_size_t o)
357 {
358 	h += o;
359 	return *(volatile u_int8_t *)h;
360 }
361 
362 u_int16_t
363 elroy_r2(void *v, bus_space_handle_t h, bus_size_t o)
364 {
365 	volatile u_int16_t *p;
366 
367 	h += o;
368 	p = (volatile u_int16_t *)h;
369 	return (letoh16(*p));
370 }
371 
372 u_int32_t
373 elroy_r4(void *v, bus_space_handle_t h, bus_size_t o)
374 {
375 	u_int32_t data;
376 
377 	h += o;
378 	data = *(volatile u_int32_t *)h;
379 	return (letoh32(data));
380 }
381 
382 u_int64_t
383 elroy_r8(void *v, bus_space_handle_t h, bus_size_t o)
384 {
385 	u_int64_t data;
386 
387 	h += o;
388 	data = *(volatile u_int64_t *)h;
389 	return (letoh64(data));
390 }
391 
392 void
393 elroy_w1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv)
394 {
395 	h += o;
396 	*(volatile u_int8_t *)h = vv;
397 }
398 
399 void
400 elroy_w2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv)
401 {
402 	volatile u_int16_t *p;
403 
404 	h += o;
405 	p = (volatile u_int16_t *)h;
406 	*p = htole16(vv);
407 }
408 
409 void
410 elroy_w4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv)
411 {
412 	h += o;
413 	vv = htole32(vv);
414 	*(volatile u_int32_t *)h = vv;
415 }
416 
417 void
418 elroy_w8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv)
419 {
420 	h += o;
421 	*(volatile u_int64_t *)h = htole64(vv);
422 }
423 
424 
425 void
426 elroy_rm_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t *a, bus_size_t c)
427 {
428 	volatile u_int8_t *p;
429 
430 	h += o;
431 	p = (volatile u_int8_t *)h;
432 	while (c--)
433 		*a++ = *p;
434 }
435 
436 void
437 elroy_rm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c)
438 {
439 	volatile u_int16_t *p;
440 
441 	h += o;
442 	p = (volatile u_int16_t *)h;
443 	while (c--)
444 		*a++ = letoh16(*p);
445 }
446 
447 void
448 elroy_rm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c)
449 {
450 	volatile u_int32_t *p;
451 
452 	h += o;
453 	p = (volatile u_int32_t *)h;
454 	while (c--)
455 		*a++ = letoh32(*p);
456 }
457 
458 void
459 elroy_rm_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t *a, bus_size_t c)
460 {
461 	volatile u_int64_t *p;
462 
463 	h += o;
464 	p = (volatile u_int64_t *)h;
465 	while (c--)
466 		*a++ = letoh64(*p);
467 }
468 
469 void
470 elroy_wm_1(void *v, bus_space_handle_t h, bus_size_t o, const u_int8_t *a, bus_size_t c)
471 {
472 	volatile u_int8_t *p;
473 
474 	h += o;
475 	p = (volatile u_int8_t *)h;
476 	while (c--)
477 		*p = *a++;
478 }
479 
480 void
481 elroy_wm_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c)
482 {
483 	volatile u_int16_t *p;
484 
485 	h += o;
486 	p = (volatile u_int16_t *)h;
487 	while (c--)
488 		*p = htole16(*a++);
489 }
490 
491 void
492 elroy_wm_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c)
493 {
494 	volatile u_int32_t *p;
495 
496 	h += o;
497 	p = (volatile u_int32_t *)h;
498 	while (c--)
499 		*p = htole32(*a++);
500 }
501 
502 void
503 elroy_wm_8(void *v, bus_space_handle_t h, bus_size_t o, const u_int64_t *a, bus_size_t c)
504 {
505 	volatile u_int64_t *p;
506 
507 	h += o;
508 	p = (volatile u_int64_t *)h;
509 	while (c--)
510 		*p = htole64(*a++);
511 }
512 
513 void
514 elroy_sm_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv, bus_size_t c)
515 {
516 	volatile u_int8_t *p;
517 
518 	h += o;
519 	p = (volatile u_int8_t *)h;
520 	while (c--)
521 		*p = vv;
522 }
523 
524 void
525 elroy_sm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c)
526 {
527 	volatile u_int16_t *p;
528 
529 	h += o;
530 	p = (volatile u_int16_t *)h;
531 	vv = htole16(vv);
532 	while (c--)
533 		*p = vv;
534 }
535 
536 void
537 elroy_sm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c)
538 {
539 	volatile u_int32_t *p;
540 
541 	h += o;
542 	p = (volatile u_int32_t *)h;
543 	vv = htole32(vv);
544 	while (c--)
545 		*p = vv;
546 }
547 
548 void
549 elroy_sm_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv, bus_size_t c)
550 {
551 	volatile u_int64_t *p;
552 
553 	h += o;
554 	p = (volatile u_int64_t *)h;
555 	vv = htole64(vv);
556 	while (c--)
557 		*p = vv;
558 }
559 
560 void
561 elroy_rrm_2(void *v, bus_space_handle_t h, bus_size_t o,
562     u_int8_t *a, bus_size_t c)
563 {
564 	volatile u_int16_t *p, *q = (u_int16_t *)a;
565 
566 	h += o;
567 	p = (volatile u_int16_t *)h;
568 	c /= 2;
569 	while (c--)
570 		*q++ = *p;
571 }
572 
573 void
574 elroy_rrm_4(void *v, bus_space_handle_t h, bus_size_t o,
575     u_int8_t *a, bus_size_t c)
576 {
577 	volatile u_int32_t *p, *q = (u_int32_t *)a;
578 
579 	h += o;
580 	p = (volatile u_int32_t *)h;
581 	c /= 4;
582 	while (c--)
583 		*q++ = *p;
584 }
585 
586 void
587 elroy_rrm_8(void *v, bus_space_handle_t h, bus_size_t o,
588     u_int8_t *a, bus_size_t c)
589 {
590 	volatile u_int64_t *p, *q = (u_int64_t *)a;
591 
592 	h += o;
593 	p = (volatile u_int64_t *)h;
594 	c /= 8;
595 	while (c--)
596 		*q++ = *p;
597 }
598 
599 void
600 elroy_wrm_2(void *v, bus_space_handle_t h, bus_size_t o,
601     const u_int8_t *a, bus_size_t c)
602 {
603 	volatile u_int16_t *p;
604 	const u_int16_t *q = (const u_int16_t *)a;
605 
606 	h += o;
607 	p = (volatile u_int16_t *)h;
608 	c /= 2;
609 	while (c--)
610 		*p = *q++;
611 }
612 
613 void
614 elroy_wrm_4(void *v, bus_space_handle_t h, bus_size_t o,
615     const u_int8_t *a, bus_size_t c)
616 {
617 	volatile u_int32_t *p;
618 	const u_int32_t *q = (const u_int32_t *)a;
619 
620 	h += o;
621 	p = (volatile u_int32_t *)h;
622 	c /= 4;
623 	while (c--)
624 		*p = *q++;
625 }
626 
627 void
628 elroy_wrm_8(void *v, bus_space_handle_t h, bus_size_t o,
629     const u_int8_t *a, bus_size_t c)
630 {
631 	volatile u_int64_t *p;
632 	const u_int64_t *q = (const u_int64_t *)a;
633 
634 	h += o;
635 	p = (volatile u_int64_t *)h;
636 	c /= 8;
637 	while (c--)
638 		*p = *q++;
639 }
640 
641 void
642 elroy_rr_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t *a, bus_size_t c)
643 {
644 	volatile u_int8_t *p;
645 
646 	h += o;
647 	p = (volatile u_int8_t *)h;
648 	while (c--)
649 		*a++ = *p++;
650 }
651 
652 void
653 elroy_rr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c)
654 {
655 	volatile u_int16_t *p, data;
656 
657 	h += o;
658 	p = (volatile u_int16_t *)h;
659 	while (c--) {
660 		data = *p++;
661 		*a++ = letoh16(data);
662 	}
663 }
664 
665 void
666 elroy_rr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c)
667 {
668 	volatile u_int32_t *p, data;
669 
670 	h += o;
671 	p = (volatile u_int32_t *)h;
672 	while (c--) {
673 		data = *p++;
674 		*a++ = letoh32(data);
675 	}
676 }
677 
678 void
679 elroy_rr_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t *a, bus_size_t c)
680 {
681 	volatile u_int64_t *p, data;
682 
683 	h += o;
684 	p = (volatile u_int64_t *)h;
685 	while (c--) {
686 		data = *p++;
687 		*a++ = letoh64(data);
688 	}
689 }
690 
691 void
692 elroy_wr_1(void *v, bus_space_handle_t h, bus_size_t o, const u_int8_t *a, bus_size_t c)
693 {
694 	volatile u_int8_t *p;
695 
696 	h += o;
697 	p = (volatile u_int8_t *)h;
698 	while (c--)
699 		*p++ = *a++;
700 }
701 
702 void
703 elroy_wr_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c)
704 {
705 	volatile u_int16_t *p, data;
706 
707 	h += o;
708 	p = (volatile u_int16_t *)h;
709 	while (c--) {
710 		data = *a++;
711 		*p++ = htole16(data);
712 	}
713 }
714 
715 void
716 elroy_wr_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c)
717 {
718 	volatile u_int32_t *p, data;
719 
720 	h += o;
721 	p = (volatile u_int32_t *)h;
722 	while (c--) {
723 		data = *a++;
724 		*p++ = htole32(data);
725 	}
726 }
727 
728 void
729 elroy_wr_8(void *v, bus_space_handle_t h, bus_size_t o, const u_int64_t *a, bus_size_t c)
730 {
731 	volatile u_int64_t *p, data;
732 
733 	h += o;
734 	p = (volatile u_int64_t *)h;
735 	while (c--) {
736 		data = *a++;
737 		*p++ = htole64(data);
738 	}
739 }
740 
741 void
742 elroy_rrr_2(void *v, bus_space_handle_t h, bus_size_t o,
743     u_int8_t *a, bus_size_t c)
744 {
745 	volatile u_int16_t *p, *q = (u_int16_t *)a;
746 
747 	c /= 2;
748 	h += o;
749 	p = (volatile u_int16_t *)h;
750 	while (c--)
751 		*q++ = *p++;
752 }
753 
754 void
755 elroy_rrr_4(void *v, bus_space_handle_t h, bus_size_t o,
756     u_int8_t *a, bus_size_t c)
757 {
758 	volatile u_int32_t *p, *q = (u_int32_t *)a;
759 
760 	c /= 4;
761 	h += o;
762 	p = (volatile u_int32_t *)h;
763 	while (c--)
764 		*q++ = *p++;
765 }
766 
767 void
768 elroy_rrr_8(void *v, bus_space_handle_t h, bus_size_t o,
769     u_int8_t *a, bus_size_t c)
770 {
771 	volatile u_int64_t *p, *q = (u_int64_t *)a;
772 
773 	c /= 8;
774 	h += o;
775 	p = (volatile u_int64_t *)h;
776 	while (c--)
777 		*q++ = *p++;
778 }
779 
780 void
781 elroy_wrr_2(void *v, bus_space_handle_t h, bus_size_t o,
782     const u_int8_t *a, bus_size_t c)
783 {
784 	volatile u_int16_t *p;
785 	const u_int16_t *q = (u_int16_t *)a;
786 
787 	c /= 2;
788 	h += o;
789 	p = (volatile u_int16_t *)h;
790 	while (c--)
791 		*p++ = *q++;
792 }
793 
794 void
795 elroy_wrr_4(void *v, bus_space_handle_t h, bus_size_t o,
796     const u_int8_t *a, bus_size_t c)
797 {
798 	volatile u_int32_t *p;
799 	const u_int32_t *q = (u_int32_t *)a;
800 
801 	c /= 4;
802 	h += o;
803 	p = (volatile u_int32_t *)h;
804 	while (c--)
805 		*p++ = *q++;
806 }
807 
808 void
809 elroy_wrr_8(void *v, bus_space_handle_t h, bus_size_t o,
810     const u_int8_t *a, bus_size_t c)
811 {
812 	volatile u_int64_t *p;
813 	const u_int64_t *q = (u_int64_t *)a;
814 
815 	c /= 8;
816 	h += o;
817 	p = (volatile u_int64_t *)h;
818 	while (c--)
819 		*p++ = *q++;
820 }
821 
822 void
823 elroy_sr_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv, bus_size_t c)
824 {
825 	volatile u_int8_t *p;
826 
827 	h += o;
828 	p = (volatile u_int8_t *)h;
829 	while (c--)
830 		*p++ = vv;
831 }
832 
833 void
834 elroy_sr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c)
835 {
836 	volatile u_int16_t *p;
837 
838 	h += o;
839 	vv = htole16(vv);
840 	p = (volatile u_int16_t *)h;
841 	while (c--)
842 		*p++ = vv;
843 }
844 
845 void
846 elroy_sr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c)
847 {
848 	volatile u_int32_t *p;
849 
850 	h += o;
851 	vv = htole32(vv);
852 	p = (volatile u_int32_t *)h;
853 	while (c--)
854 		*p++ = vv;
855 }
856 
857 void
858 elroy_sr_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv, bus_size_t c)
859 {
860 	volatile u_int64_t *p;
861 
862 	h += o;
863 	vv = htole64(vv);
864 	p = (volatile u_int64_t *)h;
865 	while (c--)
866 		*p++ = vv;
867 }
868 
869 void
870 elroy_cp_1(void *v, bus_space_handle_t h1, bus_size_t o1,
871 	  bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
872 {
873 	while (c--)
874 		elroy_w1(v, h1, o1++, elroy_r1(v, h2, o2++));
875 }
876 
877 void
878 elroy_cp_2(void *v, bus_space_handle_t h1, bus_size_t o1,
879 	  bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
880 {
881 	while (c--) {
882 		elroy_w2(v, h1, o1, elroy_r2(v, h2, o2));
883 		o1 += 2;
884 		o2 += 2;
885 	}
886 }
887 
888 void
889 elroy_cp_4(void *v, bus_space_handle_t h1, bus_size_t o1,
890 	  bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
891 {
892 	while (c--) {
893 		elroy_w4(v, h1, o1, elroy_r4(v, h2, o2));
894 		o1 += 4;
895 		o2 += 4;
896 	}
897 }
898 
899 void
900 elroy_cp_8(void *v, bus_space_handle_t h1, bus_size_t o1,
901 	  bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
902 {
903 	while (c--) {
904 		elroy_w8(v, h1, o1, elroy_r8(v, h2, o2));
905 		o1 += 8;
906 		o2 += 8;
907 	}
908 }
909 
910 const struct hppa_bus_space_tag elroy_iomemt = {
911 	NULL,
912 
913 	NULL, elroy_unmap, elroy_subregion, NULL, elroy_free,
914 	elroy_barrier, elroy_vaddr,
915 	elroy_r1,    elroy_r2,    elroy_r4,    elroy_r8,
916 	elroy_w1,    elroy_w2,    elroy_w4,    elroy_w8,
917 	elroy_rm_1,  elroy_rm_2,  elroy_rm_4,  elroy_rm_8,
918 	elroy_wm_1,  elroy_wm_2,  elroy_wm_4,  elroy_wm_8,
919 	elroy_sm_1,  elroy_sm_2,  elroy_sm_4,  elroy_sm_8,
920 		     elroy_rrm_2, elroy_rrm_4, elroy_rrm_8,
921 		     elroy_wrm_2, elroy_wrm_4, elroy_wrm_8,
922 	elroy_rr_1,  elroy_rr_2,  elroy_rr_4,  elroy_rr_8,
923 	elroy_wr_1,  elroy_wr_2,  elroy_wr_4,  elroy_wr_8,
924 		     elroy_rrr_2, elroy_rrr_4, elroy_rrr_8,
925 		     elroy_wrr_2, elroy_wrr_4, elroy_wrr_8,
926 	elroy_sr_1,  elroy_sr_2,  elroy_sr_4,  elroy_sr_8,
927 	elroy_cp_1,  elroy_cp_2,  elroy_cp_4,  elroy_cp_8
928 };
929 
930 int
931 elroy_dmamap_create(void *v, bus_size_t size, int nsegments,
932     bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp)
933 {
934 	struct elroy_softc *sc = v;
935 
936 	/* TODO check the addresses, boundary, enable dma */
937 
938 	return (bus_dmamap_create(sc->sc_dmat, size, nsegments,
939 	    maxsegsz, boundary, flags, dmamp));
940 }
941 
942 void
943 elroy_dmamap_destroy(void *v, bus_dmamap_t map)
944 {
945 	struct elroy_softc *sc = v;
946 
947 	bus_dmamap_destroy(sc->sc_dmat, map);
948 }
949 
950 int
951 elroy_dmamap_load(void *v, bus_dmamap_t map, void *addr, bus_size_t size,
952     struct proc *p, int flags)
953 {
954 	struct elroy_softc *sc = v;
955 
956 	return (bus_dmamap_load(sc->sc_dmat, map, addr, size, p, flags));
957 }
958 
959 int
960 elroy_dmamap_load_mbuf(void *v, bus_dmamap_t map, struct mbuf *m, int flags)
961 {
962 	struct elroy_softc *sc = v;
963 
964 	return (bus_dmamap_load_mbuf(sc->sc_dmat, map, m, flags));
965 }
966 
967 int
968 elroy_dmamap_load_uio(void *v, bus_dmamap_t map, struct uio *uio, int flags)
969 {
970 	struct elroy_softc *sc = v;
971 
972 	return (bus_dmamap_load_uio(sc->sc_dmat, map, uio, flags));
973 }
974 
975 int
976 elroy_dmamap_load_raw(void *v, bus_dmamap_t map, bus_dma_segment_t *segs,
977     int nsegs, bus_size_t size, int flags)
978 {
979 	struct elroy_softc *sc = v;
980 
981 	return (bus_dmamap_load_raw(sc->sc_dmat, map, segs, nsegs, size, flags));
982 }
983 
984 void
985 elroy_dmamap_unload(void *v, bus_dmamap_t map)
986 {
987 	struct elroy_softc *sc = v;
988 
989 	bus_dmamap_unload(sc->sc_dmat, map);
990 }
991 
992 void
993 elroy_dmamap_sync(void *v, bus_dmamap_t map, bus_addr_t off,
994     bus_size_t len, int ops)
995 {
996 	struct elroy_softc *sc = v;
997 
998 	bus_dmamap_sync(sc->sc_dmat, map, off, len, ops);
999 }
1000 
1001 int
1002 elroy_dmamem_alloc(void *v, bus_size_t size, bus_size_t alignment,
1003     bus_size_t boundary, bus_dma_segment_t *segs,
1004     int nsegs, int *rsegs, int flags)
1005 {
1006 	struct elroy_softc *sc = v;
1007 
1008 	return (bus_dmamem_alloc(sc->sc_dmat, size, alignment, boundary,
1009 	    segs, nsegs, rsegs, flags));
1010 }
1011 
1012 void
1013 elroy_dmamem_free(void *v, bus_dma_segment_t *segs, int nsegs)
1014 {
1015 	struct elroy_softc *sc = v;
1016 
1017 	bus_dmamem_free(sc->sc_dmat, segs, nsegs);
1018 }
1019 
1020 int
1021 elroy_dmamem_map(void *v, bus_dma_segment_t *segs, int nsegs, size_t size,
1022     caddr_t *kvap, int flags)
1023 {
1024 	struct elroy_softc *sc = v;
1025 
1026 	return (bus_dmamem_map(sc->sc_dmat, segs, nsegs, size, kvap, flags));
1027 }
1028 
1029 void
1030 elroy_dmamem_unmap(void *v, caddr_t kva, size_t size)
1031 {
1032 	struct elroy_softc *sc = v;
1033 
1034 	bus_dmamem_unmap(sc->sc_dmat, kva, size);
1035 }
1036 
1037 paddr_t
1038 elroy_dmamem_mmap(void *v, bus_dma_segment_t *segs, int nsegs, off_t off,
1039     int prot, int flags)
1040 {
1041 	struct elroy_softc *sc = v;
1042 
1043 	return (bus_dmamem_mmap(sc->sc_dmat, segs, nsegs, off, prot, flags));
1044 }
1045 
1046 const struct hppa_bus_dma_tag elroy_dmat = {
1047 	NULL,
1048 	elroy_dmamap_create, elroy_dmamap_destroy,
1049 	elroy_dmamap_load, elroy_dmamap_load_mbuf,
1050 	elroy_dmamap_load_uio, elroy_dmamap_load_raw,
1051 	elroy_dmamap_unload, elroy_dmamap_sync,
1052 
1053 	elroy_dmamem_alloc, elroy_dmamem_free, elroy_dmamem_map,
1054 	elroy_dmamem_unmap, elroy_dmamem_mmap
1055 };
1056 
1057 const struct hppa_pci_chipset_tag elroy_pc = {
1058 	NULL,
1059 	elroy_attach_hook, elroy_maxdevs, elroy_make_tag, elroy_decompose_tag,
1060 	elroy_conf_read, elroy_conf_write,
1061 	apic_intr_map, apic_intr_string,
1062 	apic_intr_establish, apic_intr_disestablish,
1063 #if NCARDBUS > 0
1064 	elroy_alloc_parent
1065 #else
1066 	NULL
1067 #endif
1068 };
1069 
1070 int
1071 elroy_print(void *aux, const char *pnp)
1072 {
1073 	struct pcibus_attach_args *pba = aux;
1074 
1075 	if (pnp)
1076 		printf("%s at %s\n", pba->pba_busname, pnp);
1077 	return (UNCONF);
1078 }
1079 
1080 void
1081 elroy_attach(struct device *parent, struct device *self, void *aux)
1082 {
1083 	struct elroy_softc *sc = (struct elroy_softc *)self;
1084 	struct confargs *ca = (struct confargs *)aux;
1085 	struct pcibus_attach_args pba;
1086 	volatile struct elroy_regs *r;
1087 	const char *p = NULL, *q;
1088 	int i;
1089 
1090 	sc->sc_hpa = ca->ca_hpa;
1091 	sc->sc_bt = ca->ca_iot;
1092 	sc->sc_dmat = ca->ca_dmatag;
1093 	if (bus_space_map(sc->sc_bt, ca->ca_hpa, ca->ca_hpasz, 0, &sc->sc_bh)) {
1094 		printf(": can't map space\n");
1095 		return;
1096 	}
1097 
1098 	sc->sc_regs = r = bus_space_vaddr(sc->sc_bt, sc->sc_bh);
1099 	elroy_write32(&r->pci_cmdstat, htole32(PCI_COMMAND_IO_ENABLE |
1100 	    PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE));
1101 
1102 	elroy_write32(&r->control, elroy_read32(&r->control) &
1103 	    ~htole32(ELROY_CONTROL_RF));
1104 	for (i = 5000; i-- &&
1105 	    elroy_read32(&r->status) & htole32(ELROY_STATUS_RC); DELAY(10));
1106 	if (i < 0) {
1107 		printf(": reset failed; status %b\n",
1108 		    ELROY_STATUS_BITS, htole32(r->status));
1109 		return;
1110 	}
1111 
1112 	q = "";
1113 	sc->sc_ver = PCI_REVISION(letoh32(elroy_read32(&r->pci_class)));
1114 	switch ((ca->ca_type.iodc_model << 4) |
1115 	    (ca->ca_type.iodc_revision >> 4)) {
1116 	case 0x782:
1117 		p = "Elroy";
1118 		switch (sc->sc_ver) {
1119 		default:
1120 			q = "+";
1121 		case 5:	sc->sc_ver = 0x40;	break;
1122 		case 4:	sc->sc_ver = 0x30;	break;
1123 		case 3:	sc->sc_ver = 0x22;	break;
1124 		case 2:	sc->sc_ver = 0x21;	break;
1125 		case 1:	sc->sc_ver = 0x20;	break;
1126 		case 0:	sc->sc_ver = 0x10;	break;
1127 		}
1128 		break;
1129 
1130 	case 0x783:
1131 		p = "Mercury";
1132 		break;
1133 
1134 	case 0x784:
1135 		p = "Quicksilver";
1136 		break;
1137 
1138 	default:
1139 		p = "Mojo";
1140 		break;
1141 	}
1142 
1143 	printf(": %s TR%d.%d%s", p, sc->sc_ver >> 4, sc->sc_ver & 0xf, q);
1144 	apic_attach(sc);
1145 	printf("\n");
1146 
1147 	elroy_write32(&r->imask, htole32(0xffffffff << 30));
1148 	elroy_write32(&r->ibase, htole32(ELROY_BASE_RE));
1149 
1150 	/* TODO reserve elroy's pci space ? */
1151 
1152 #if 0
1153 printf("lmm %llx/%llx gmm %llx/%llx wlm %llx/%llx wgm %llx/%llx io %llx/%llx eio %llx/%llx\n",
1154 letoh64(r->lmmio_base), letoh64(r->lmmio_mask),
1155 letoh64(r->gmmio_base), letoh64(r->gmmio_mask),
1156 letoh64(r->wlmmio_base), letoh64(r->wlmmio_mask),
1157 letoh64(r->wgmmio_base), letoh64(r->wgmmio_mask),
1158 letoh64(r->io_base), letoh64(r->io_mask),
1159 letoh64(r->eio_base), letoh64(r->eio_mask));
1160 #endif
1161 
1162 	/* XXX evil hack! */
1163 	sc->sc_iobase = 0xfee00000;
1164 
1165 	sc->sc_iot = elroy_iomemt;
1166 	sc->sc_iot.hbt_cookie = sc;
1167 	sc->sc_iot.hbt_map = elroy_iomap;
1168 	sc->sc_iot.hbt_alloc = elroy_ioalloc;
1169 	sc->sc_memt = elroy_iomemt;
1170 	sc->sc_memt.hbt_cookie = sc;
1171 	sc->sc_memt.hbt_map = elroy_memmap;
1172 	sc->sc_memt.hbt_alloc = elroy_memalloc;
1173 	sc->sc_pc = elroy_pc;
1174 	sc->sc_pc._cookie = sc;
1175 	sc->sc_dmatag = elroy_dmat;
1176 	sc->sc_dmatag._cookie = sc;
1177 
1178 	bzero(&pba, sizeof(pba));
1179 	pba.pba_busname = "pci";
1180 	pba.pba_iot = &sc->sc_iot;
1181 	pba.pba_memt = &sc->sc_memt;
1182 	pba.pba_dmat = &sc->sc_dmatag;
1183 	pba.pba_pc = &sc->sc_pc;
1184 	pba.pba_domain = pci_ndomains++;
1185 	pba.pba_bus = 0; /* (letoh32(elroy_read32(&r->busnum)) & 0xff) >> 4; */
1186 	config_found(self, &pba, elroy_print);
1187 }
1188