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