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