1 /* $OpenBSD: mainbus.c,v 1.91 2024/02/07 20:32:54 miod Exp $ */
2
3 /*
4 * Copyright (c) 1998-2004 Michael Shalayeff
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
26 * THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include "lcd.h"
30 #include "power.h"
31
32 #undef BTLBDEBUG
33
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/proc.h>
37 #include <sys/device.h>
38 #include <sys/reboot.h>
39 #include <sys/extent.h>
40 #include <sys/mbuf.h>
41
42 #include <uvm/uvm_extern.h>
43
44 #include <machine/bus.h>
45 #include <machine/pdc.h>
46 #include <machine/iomod.h>
47 #include <machine/autoconf.h>
48
49 #include <hppa/dev/cpudevs.h>
50
51 struct mainbus_softc {
52 struct device sc_dv;
53
54 hppa_hpa_t sc_hpa;
55 };
56
57 int mbmatch(struct device *, void *, void *);
58 void mbattach(struct device *, struct device *, void *);
59
60 const struct cfattach mainbus_ca = {
61 sizeof(struct mainbus_softc), mbmatch, mbattach
62 };
63
64 struct cfdriver mainbus_cd = {
65 NULL, "mainbus", DV_DULL
66 };
67
68 struct pdc_hpa pdc_hpa PDC_ALIGNMENT;
69 struct pdc_power_info pdc_power_info PDC_ALIGNMENT;
70 struct pdc_chassis_info pdc_chassis_info PDC_ALIGNMENT;
71 struct pdc_chassis_lcd pdc_chassis_lcd PDC_ALIGNMENT;
72
73 /* from machdep.c */
74 extern struct extent *hppa_ex;
75 extern struct pdc_btlb pdc_btlb;
76
77 int mbus_add_mapping(bus_addr_t bpa, bus_size_t size, int flags,
78 bus_space_handle_t *bshp);
79 int mbus_map(void *v, bus_addr_t bpa, bus_size_t size,
80 int flags, bus_space_handle_t *bshp);
81 void mbus_unmap(void *v, bus_space_handle_t bsh, bus_size_t size);
82 int mbus_alloc(void *v, bus_addr_t rstart, bus_addr_t rend,
83 bus_size_t size, bus_size_t align, bus_size_t boundary,
84 int flags, bus_addr_t *addrp, bus_space_handle_t *bshp);
85 void mbus_free(void *v, bus_space_handle_t h, bus_size_t size);
86 int mbus_subregion(void *v, bus_space_handle_t bsh,
87 bus_size_t offset, bus_size_t size,
88 bus_space_handle_t *nbshp);
89 void mbus_barrier(void *v, bus_space_handle_t h, bus_size_t o,
90 bus_size_t l, int op);
91 void *mbus_vaddr(void *v, bus_space_handle_t h);
92 u_int8_t mbus_r1(void *v, bus_space_handle_t h, bus_size_t o);
93 u_int16_t mbus_r2(void *v, bus_space_handle_t h, bus_size_t o);
94 u_int32_t mbus_r4(void *v, bus_space_handle_t h, bus_size_t o);
95 u_int64_t mbus_r8(void *v, bus_space_handle_t h, bus_size_t o);
96 void mbus_w1(void *v, bus_space_handle_t h, bus_size_t o,
97 u_int8_t vv);
98 void mbus_w2(void *v, bus_space_handle_t h, bus_size_t o,
99 u_int16_t vv);
100 void mbus_w4(void *v, bus_space_handle_t h, bus_size_t o,
101 u_int32_t vv);
102 void mbus_w8(void *v, bus_space_handle_t h, bus_size_t o,
103 u_int64_t vv);
104 void mbus_rm_1(void *v, bus_space_handle_t h, bus_size_t o,
105 u_int8_t *a, bus_size_t c);
106 void mbus_rm_2(void *v, bus_space_handle_t h, bus_size_t o,
107 u_int16_t *a, bus_size_t c);
108 void mbus_rm_4(void *v, bus_space_handle_t h, bus_size_t o,
109 u_int32_t *a, bus_size_t c);
110 void mbus_rm_8(void *v, bus_space_handle_t h, bus_size_t o,
111 u_int64_t *a, bus_size_t c);
112 void mbus_wm_1(void *v, bus_space_handle_t h, bus_size_t o,
113 const u_int8_t *a, bus_size_t c);
114 void mbus_wm_2(void *v, bus_space_handle_t h, bus_size_t o,
115 const u_int16_t *a, bus_size_t c);
116 void mbus_wm_4(void *v, bus_space_handle_t h, bus_size_t o,
117 const u_int32_t *a, bus_size_t c);
118 void mbus_wm_8(void *v, bus_space_handle_t h, bus_size_t o,
119 const u_int64_t *a, bus_size_t c);
120 void mbus_sm_1(void *v, bus_space_handle_t h, bus_size_t o,
121 u_int8_t vv, bus_size_t c);
122 void mbus_sm_2(void *v, bus_space_handle_t h, bus_size_t o,
123 u_int16_t vv, bus_size_t c);
124 void mbus_sm_4(void *v, bus_space_handle_t h, bus_size_t o,
125 u_int32_t vv, bus_size_t c);
126 void mbus_sm_8(void *v, bus_space_handle_t h, bus_size_t o,
127 u_int64_t vv, bus_size_t c);
128
129 void mbus_rr_1(void *v, bus_space_handle_t h, bus_size_t o,
130 u_int8_t *a, bus_size_t c);
131 void mbus_rr_2(void *v, bus_space_handle_t h, bus_size_t o,
132 u_int16_t *a, bus_size_t c);
133 void mbus_rr_4(void *v, bus_space_handle_t h, bus_size_t o,
134 u_int32_t *a, bus_size_t c);
135 void mbus_rr_8(void *v, bus_space_handle_t h, bus_size_t o,
136 u_int64_t *a, bus_size_t c);
137 void mbus_wr_1(void *v, bus_space_handle_t h, bus_size_t o,
138 const u_int8_t *a, bus_size_t c);
139 void mbus_wr_2(void *v, bus_space_handle_t h, bus_size_t o,
140 const u_int16_t *a, bus_size_t c);
141 void mbus_wr_4(void *v, bus_space_handle_t h, bus_size_t o,
142 const u_int32_t *a, bus_size_t c);
143 void mbus_wr_8(void *v, bus_space_handle_t h, bus_size_t o,
144 const u_int64_t *a, bus_size_t c);
145 void mbus_sr_1(void *v, bus_space_handle_t h, bus_size_t o,
146 u_int8_t vv, bus_size_t c);
147 void mbus_sr_2(void *v, bus_space_handle_t h, bus_size_t o,
148 u_int16_t vv, bus_size_t c);
149 void mbus_sr_4(void *v, bus_space_handle_t h, bus_size_t o,
150 u_int32_t vv, bus_size_t c);
151 void mbus_sr_8(void *v, bus_space_handle_t h, bus_size_t o,
152 u_int64_t vv, bus_size_t c);
153 void mbus_cp_1(void *v, bus_space_handle_t h1, bus_size_t o1,
154 bus_space_handle_t h2, bus_size_t o2, bus_size_t c);
155 void mbus_cp_2(void *v, bus_space_handle_t h1, bus_size_t o1,
156 bus_space_handle_t h2, bus_size_t o2, bus_size_t c);
157 void mbus_cp_4(void *v, bus_space_handle_t h1, bus_size_t o1,
158 bus_space_handle_t h2, bus_size_t o2, bus_size_t c);
159 void mbus_cp_8(void *v, bus_space_handle_t h1, bus_size_t o1,
160 bus_space_handle_t h2, bus_size_t o2, bus_size_t c);
161
162 int
mbus_add_mapping(bus_addr_t bpa,bus_size_t size,int flags,bus_space_handle_t * bshp)163 mbus_add_mapping(bus_addr_t bpa, bus_size_t size, int flags,
164 bus_space_handle_t *bshp)
165 {
166 static u_int32_t bmm[0x4000/32];
167 int bank, off, flex;
168 vaddr_t pa, spa, epa;
169 vsize_t len;
170
171 #ifdef BTLBDEBUG
172 printf("bus_mem_add_mapping(%lx,%lx,%scachable,%p)\n",
173 bpa, size, flags? "" : "non", bshp);
174 #endif
175
176 if ((bank = vm_physseg_find(atop(bpa), &off)) >= 0)
177 panic("mbus_add_mapping: mapping real memory @0x%lx", bpa);
178
179 #ifdef DEBUG
180 if (flags & BUS_SPACE_MAP_CACHEABLE) {
181 printf("WARNING: mapping I/O space cacheable\n");
182 flags &= ~BUS_SPACE_MAP_CACHEABLE;
183 }
184 #endif
185
186 /*
187 * Mappings are established in HPPA_FLEX_SIZE units,
188 * either with BTLB, or regular mappings of the whole area.
189 */
190 pa = bpa;
191 while (size != 0) {
192 flex = HPPA_FLEX(pa);
193 spa = pa & HPPA_FLEX_MASK;
194 epa = spa + HPPA_FLEX_SIZE; /* may wrap to 0... */
195
196 size -= min(size, HPPA_FLEX_SIZE - (pa - spa));
197
198 /* do need a new mapping? */
199 if (!(bmm[flex / 32] & (1U << (flex % 32)))) {
200 #ifdef BTLBDEBUG
201 printf("bus_mem_add_mapping: adding flex=%x "
202 "%lx-%lx, ", flex, spa, epa - 1);
203 #endif
204 while (spa != epa) {
205 len = epa - spa;
206
207 /*
208 * Try to map with a BTLB first (might map
209 * much more than what we are requesting
210 * for, and cross HPPA_FLEX boundaries).
211 *
212 * Note that this code assumes that
213 * BTLB size are a power of two, so if
214 * the size is larger than HPPA_FLEX_SIZE
215 * it will span an integral number of
216 * HPPA_FLEX_SIZE slots.
217 */
218 if (len > pdc_btlb.max_size << PGSHIFT)
219 len = pdc_btlb.max_size << PGSHIFT;
220
221 if (btlb_insert(HPPA_SID_KERNEL, spa, spa, &len,
222 pmap_sid2pid(HPPA_SID_KERNEL) |
223 pmap_prot(pmap_kernel(), PROT_READ | PROT_WRITE))
224 >= 0) {
225 pa = spa + len; /* may wrap to 0... */
226 #ifdef BTLBDEBUG
227 printf("--- %x/%lx, %lx-%lx ",
228 flex, HPPA_FLEX(pa - 1),
229 spa, pa - 1);
230 #endif
231 /* register all ranges */
232 for (; flex <= HPPA_FLEX(pa - 1);
233 flex++) {
234 #ifdef BTLBDEBUG
235 printf("mask %x ", flex);
236 #endif
237 bmm[flex / 32] |=
238 (1U << (flex % 32));
239 }
240 if (len > epa - spa)
241 spa = epa;
242 else
243 spa = pa;
244 } else {
245 #ifdef BTLBDEBUG
246 printf("kenter 0x%lx-0x%lx", spa, epa);
247 #endif
248 for (; spa != epa; spa += PAGE_SIZE)
249 pmap_kenter_pa(spa, spa,
250 PROT_READ | PROT_WRITE);
251 }
252 #ifdef BTLBDEBUG
253 printf("\n");
254 #endif
255 }
256 }
257 #ifdef BTLBDEBUG
258 else {
259 printf("+++ already b-mapped flex=%x, mask=%x\n",
260 flex, bmm[flex / 32]);
261 }
262 #endif
263
264 pa = epa;
265 }
266
267 *bshp = bpa;
268 return (0);
269 }
270
271 int
mbus_map(void * v,bus_addr_t bpa,bus_size_t size,int flags,bus_space_handle_t * bshp)272 mbus_map(void *v, bus_addr_t bpa, bus_size_t size,
273 int flags, bus_space_handle_t *bshp)
274 {
275 int error;
276
277 if ((error = extent_alloc_region(hppa_ex, bpa, size, EX_NOWAIT)))
278 return (error);
279
280 if ((error = mbus_add_mapping(bpa, size, flags, bshp))) {
281 if (extent_free(hppa_ex, bpa, size, EX_NOWAIT)) {
282 printf("bus_space_map: pa 0x%lx, size 0x%lx\n",
283 bpa, size);
284 printf("bus_space_map: can't free region\n");
285 }
286 }
287
288 return error;
289 }
290
291 void
mbus_unmap(void * v,bus_space_handle_t bsh,bus_size_t size)292 mbus_unmap(void *v, bus_space_handle_t bsh, bus_size_t size)
293 {
294 u_long sva, eva;
295
296 sva = trunc_page(bsh);
297 eva = round_page(bsh + size);
298
299 #ifdef DIAGNOSTIC
300 if (eva <= sva)
301 panic("bus_space_unmap: overflow");
302 #endif
303
304 if (pmap_extract(pmap_kernel(), bsh, NULL))
305 pmap_kremove(sva, eva - sva);
306 else
307 ; /* XXX assuming equ b-mapping been done */
308
309 if (extent_free(hppa_ex, bsh, size, EX_NOWAIT)) {
310 printf("bus_space_unmap: ps 0x%lx, size 0x%lx\n",
311 bsh, size);
312 printf("bus_space_unmap: can't free region\n");
313 }
314 }
315
316 int
mbus_alloc(void * v,bus_addr_t rstart,bus_addr_t rend,bus_size_t size,bus_size_t align,bus_size_t boundary,int flags,bus_addr_t * addrp,bus_space_handle_t * bshp)317 mbus_alloc(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
318 bus_size_t align, bus_size_t boundary, int flags,
319 bus_addr_t *addrp, bus_space_handle_t *bshp)
320 {
321 u_long bpa;
322 int error;
323
324 if (rstart < hppa_ex->ex_start || rend > hppa_ex->ex_end)
325 panic("bus_space_alloc: bad region start/end");
326
327 if ((error = extent_alloc_subregion(hppa_ex, rstart, rend, size,
328 align, 0, boundary, EX_NOWAIT, &bpa)))
329 return (error);
330
331 if ((error = mbus_add_mapping(bpa, size, flags, bshp))) {
332 if (extent_free(hppa_ex, bpa, size, EX_NOWAIT)) {
333 printf("bus_space_alloc: pa 0x%lx, size 0x%lx\n",
334 bpa, size);
335 printf("bus_space_alloc: can't free region\n");
336 }
337 }
338
339 *addrp = bpa;
340 return (error);
341 }
342
343 void
mbus_free(void * v,bus_space_handle_t h,bus_size_t size)344 mbus_free(void *v, bus_space_handle_t h, bus_size_t size)
345 {
346 /* bus_space_unmap() does all that we need to do. */
347 mbus_unmap(v, h, size);
348 }
349
350 int
mbus_subregion(void * v,bus_space_handle_t bsh,bus_size_t offset,bus_size_t size,bus_space_handle_t * nbshp)351 mbus_subregion(void *v, bus_space_handle_t bsh, bus_size_t offset,
352 bus_size_t size, bus_space_handle_t *nbshp)
353 {
354 *nbshp = bsh + offset;
355 return (0);
356 }
357
358 void
mbus_barrier(void * v,bus_space_handle_t h,bus_size_t o,bus_size_t l,int op)359 mbus_barrier(void *v, bus_space_handle_t h, bus_size_t o, bus_size_t l, int op)
360 {
361 sync_caches();
362 }
363
364 void *
mbus_vaddr(void * v,bus_space_handle_t h)365 mbus_vaddr(void *v, bus_space_handle_t h)
366 {
367 return ((void *)h);
368 }
369
370 u_int8_t
mbus_r1(void * v,bus_space_handle_t h,bus_size_t o)371 mbus_r1(void *v, bus_space_handle_t h, bus_size_t o)
372 {
373 return *((volatile u_int8_t *)(h + o));
374 }
375
376 u_int16_t
mbus_r2(void * v,bus_space_handle_t h,bus_size_t o)377 mbus_r2(void *v, bus_space_handle_t h, bus_size_t o)
378 {
379 return *((volatile u_int16_t *)(h + o));
380 }
381
382 u_int32_t
mbus_r4(void * v,bus_space_handle_t h,bus_size_t o)383 mbus_r4(void *v, bus_space_handle_t h, bus_size_t o)
384 {
385 return *((volatile u_int32_t *)(h + o));
386 }
387
388 u_int64_t
mbus_r8(void * v,bus_space_handle_t h,bus_size_t o)389 mbus_r8(void *v, bus_space_handle_t h, bus_size_t o)
390 {
391 return *((volatile u_int64_t *)(h + o));
392 }
393
394 void
mbus_w1(void * v,bus_space_handle_t h,bus_size_t o,u_int8_t vv)395 mbus_w1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv)
396 {
397 *((volatile u_int8_t *)(h + o)) = vv;
398 }
399
400 void
mbus_w2(void * v,bus_space_handle_t h,bus_size_t o,u_int16_t vv)401 mbus_w2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv)
402 {
403 *((volatile u_int16_t *)(h + o)) = vv;
404 }
405
406 void
mbus_w4(void * v,bus_space_handle_t h,bus_size_t o,u_int32_t vv)407 mbus_w4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv)
408 {
409 *((volatile u_int32_t *)(h + o)) = vv;
410 }
411
412 void
mbus_w8(void * v,bus_space_handle_t h,bus_size_t o,u_int64_t vv)413 mbus_w8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv)
414 {
415 *((volatile u_int64_t *)(h + o)) = vv;
416 }
417
418
419 void
mbus_rm_1(void * v,bus_space_handle_t h,bus_size_t o,u_int8_t * a,bus_size_t c)420 mbus_rm_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t *a, bus_size_t c)
421 {
422 h += o;
423 while (c--)
424 *(a++) = *(volatile u_int8_t *)h;
425 }
426
427 void
mbus_rm_2(void * v,bus_space_handle_t h,bus_size_t o,u_int16_t * a,bus_size_t c)428 mbus_rm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c)
429 {
430 h += o;
431 while (c--)
432 *(a++) = *(volatile u_int16_t *)h;
433 }
434
435 void
mbus_rm_4(void * v,bus_space_handle_t h,bus_size_t o,u_int32_t * a,bus_size_t c)436 mbus_rm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c)
437 {
438 h += o;
439 while (c--)
440 *(a++) = *(volatile u_int32_t *)h;
441 }
442
443 void
mbus_rm_8(void * v,bus_space_handle_t h,bus_size_t o,u_int64_t * a,bus_size_t c)444 mbus_rm_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t *a, bus_size_t c)
445 {
446 h += o;
447 while (c--)
448 *(a++) = *(volatile u_int64_t *)h;
449 }
450
451 void
mbus_wm_1(void * v,bus_space_handle_t h,bus_size_t o,const u_int8_t * a,bus_size_t c)452 mbus_wm_1(void *v, bus_space_handle_t h, bus_size_t o, const u_int8_t *a, bus_size_t c)
453 {
454 h += o;
455 while (c--)
456 *(volatile u_int8_t *)h = *(a++);
457 }
458
459 void
mbus_wm_2(void * v,bus_space_handle_t h,bus_size_t o,const u_int16_t * a,bus_size_t c)460 mbus_wm_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c)
461 {
462 h += o;
463 while (c--)
464 *(volatile u_int16_t *)h = *(a++);
465 }
466
467 void
mbus_wm_4(void * v,bus_space_handle_t h,bus_size_t o,const u_int32_t * a,bus_size_t c)468 mbus_wm_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c)
469 {
470 h += o;
471 while (c--)
472 *(volatile u_int32_t *)h = *(a++);
473 }
474
475 void
mbus_wm_8(void * v,bus_space_handle_t h,bus_size_t o,const u_int64_t * a,bus_size_t c)476 mbus_wm_8(void *v, bus_space_handle_t h, bus_size_t o, const u_int64_t *a, bus_size_t c)
477 {
478 h += o;
479 while (c--)
480 *(volatile u_int64_t *)h = *(a++);
481 }
482
483 void
mbus_sm_1(void * v,bus_space_handle_t h,bus_size_t o,u_int8_t vv,bus_size_t c)484 mbus_sm_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv, bus_size_t c)
485 {
486 h += o;
487 while (c--)
488 *(volatile u_int8_t *)h = vv;
489 }
490
491 void
mbus_sm_2(void * v,bus_space_handle_t h,bus_size_t o,u_int16_t vv,bus_size_t c)492 mbus_sm_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c)
493 {
494 h += o;
495 while (c--)
496 *(volatile u_int16_t *)h = vv;
497 }
498
499 void
mbus_sm_4(void * v,bus_space_handle_t h,bus_size_t o,u_int32_t vv,bus_size_t c)500 mbus_sm_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c)
501 {
502 h += o;
503 while (c--)
504 *(volatile u_int32_t *)h = vv;
505 }
506
507 void
mbus_sm_8(void * v,bus_space_handle_t h,bus_size_t o,u_int64_t vv,bus_size_t c)508 mbus_sm_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv, bus_size_t c)
509 {
510 h += o;
511 while (c--)
512 *(volatile u_int64_t *)h = vv;
513 }
514
515 void
mbus_rr_1(void * v,bus_space_handle_t h,bus_size_t o,u_int8_t * a,bus_size_t c)516 mbus_rr_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t *a, bus_size_t c)
517 {
518 volatile u_int8_t *p = (u_int8_t *)(h + o);
519
520 while (c--)
521 *a++ = *p++;
522 }
523
524 void
mbus_rr_2(void * v,bus_space_handle_t h,bus_size_t o,u_int16_t * a,bus_size_t c)525 mbus_rr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t *a, bus_size_t c)
526 {
527 volatile u_int16_t *p = (u_int16_t *)(h + o);
528
529 while (c--)
530 *a++ = *p++;
531 }
532
533 void
mbus_rr_4(void * v,bus_space_handle_t h,bus_size_t o,u_int32_t * a,bus_size_t c)534 mbus_rr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t *a, bus_size_t c)
535 {
536 volatile u_int32_t *p = (u_int32_t *)(h + o);
537
538 while (c--)
539 *a++ = *p++;
540 }
541
542 void
mbus_rr_8(void * v,bus_space_handle_t h,bus_size_t o,u_int64_t * a,bus_size_t c)543 mbus_rr_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t *a, bus_size_t c)
544 {
545 volatile u_int64_t *p = (u_int64_t *)(h + o);
546
547 while (c--)
548 *a++ = *p++;
549 }
550
551 void
mbus_wr_1(void * v,bus_space_handle_t h,bus_size_t o,const u_int8_t * a,bus_size_t c)552 mbus_wr_1(void *v, bus_space_handle_t h, bus_size_t o, const u_int8_t *a, bus_size_t c)
553 {
554 volatile u_int8_t *p = (u_int8_t *)(h + o);
555
556 while (c--)
557 *p++ = *a++;
558 }
559
560 void
mbus_wr_2(void * v,bus_space_handle_t h,bus_size_t o,const u_int16_t * a,bus_size_t c)561 mbus_wr_2(void *v, bus_space_handle_t h, bus_size_t o, const u_int16_t *a, bus_size_t c)
562 {
563 volatile u_int16_t *p = (u_int16_t *)(h + o);
564
565 while (c--)
566 *p++ = *a++;
567 }
568
569 void
mbus_wr_4(void * v,bus_space_handle_t h,bus_size_t o,const u_int32_t * a,bus_size_t c)570 mbus_wr_4(void *v, bus_space_handle_t h, bus_size_t o, const u_int32_t *a, bus_size_t c)
571 {
572 volatile u_int32_t *p = (u_int32_t *)(h + o);
573
574 while (c--)
575 *p++ = *a++;
576 }
577
578 void
mbus_wr_8(void * v,bus_space_handle_t h,bus_size_t o,const u_int64_t * a,bus_size_t c)579 mbus_wr_8(void *v, bus_space_handle_t h, bus_size_t o, const u_int64_t *a, bus_size_t c)
580 {
581 volatile u_int64_t *p = (u_int64_t *)(h + o);
582
583 while (c--)
584 *p++ = *a++;
585 }
586
587 void
mbus_sr_1(void * v,bus_space_handle_t h,bus_size_t o,u_int8_t vv,bus_size_t c)588 mbus_sr_1(void *v, bus_space_handle_t h, bus_size_t o, u_int8_t vv, bus_size_t c)
589 {
590 volatile u_int8_t *p = (u_int8_t *)(h + o);
591
592 while (c--)
593 *p++ = vv;
594 }
595
596 void
mbus_sr_2(void * v,bus_space_handle_t h,bus_size_t o,u_int16_t vv,bus_size_t c)597 mbus_sr_2(void *v, bus_space_handle_t h, bus_size_t o, u_int16_t vv, bus_size_t c)
598 {
599 volatile u_int16_t *p = (u_int16_t *)(h + o);
600
601 while (c--)
602 *p++ = vv;
603 }
604
605 void
mbus_sr_4(void * v,bus_space_handle_t h,bus_size_t o,u_int32_t vv,bus_size_t c)606 mbus_sr_4(void *v, bus_space_handle_t h, bus_size_t o, u_int32_t vv, bus_size_t c)
607 {
608 volatile u_int32_t *p = (u_int32_t *)(h + o);
609
610 while (c--)
611 *p++ = vv;
612 }
613
614 void
mbus_sr_8(void * v,bus_space_handle_t h,bus_size_t o,u_int64_t vv,bus_size_t c)615 mbus_sr_8(void *v, bus_space_handle_t h, bus_size_t o, u_int64_t vv, bus_size_t c)
616 {
617 volatile u_int64_t *p = (u_int64_t *)(h + o);
618
619 while (c--)
620 *p++ = vv;
621 }
622
623 void
mbus_cp_1(void * v,bus_space_handle_t h1,bus_size_t o1,bus_space_handle_t h2,bus_size_t o2,bus_size_t c)624 mbus_cp_1(void *v, bus_space_handle_t h1, bus_size_t o1,
625 bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
626 {
627 volatile u_int8_t *p1 = (u_int8_t *)(h1 + o1);
628 volatile u_int8_t *p2 = (u_int8_t *)(h2 + o2);
629
630 while (c--)
631 *p1++ = *p2++;
632 }
633
634 void
mbus_cp_2(void * v,bus_space_handle_t h1,bus_size_t o1,bus_space_handle_t h2,bus_size_t o2,bus_size_t c)635 mbus_cp_2(void *v, bus_space_handle_t h1, bus_size_t o1,
636 bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
637 {
638 volatile u_int16_t *p1 = (u_int16_t *)(h1 + o1);
639 volatile u_int16_t *p2 = (u_int16_t *)(h2 + o2);
640
641 while (c--)
642 *p1++ = *p2++;
643 }
644
645 void
mbus_cp_4(void * v,bus_space_handle_t h1,bus_size_t o1,bus_space_handle_t h2,bus_size_t o2,bus_size_t c)646 mbus_cp_4(void *v, bus_space_handle_t h1, bus_size_t o1,
647 bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
648 {
649 volatile u_int32_t *p1 = (u_int32_t *)(h1 + o1);
650 volatile u_int32_t *p2 = (u_int32_t *)(h2 + o2);
651
652 while (c--)
653 *p1++ = *p2++;
654 }
655
656 void
mbus_cp_8(void * v,bus_space_handle_t h1,bus_size_t o1,bus_space_handle_t h2,bus_size_t o2,bus_size_t c)657 mbus_cp_8(void *v, bus_space_handle_t h1, bus_size_t o1,
658 bus_space_handle_t h2, bus_size_t o2, bus_size_t c)
659 {
660 volatile u_int64_t *p1 = (u_int64_t *)(h1 + o1);
661 volatile u_int64_t *p2 = (u_int64_t *)(h2 + o2);
662
663 while (c--)
664 *p1++ = *p2++;
665 }
666
667
668 /* ugly typecast macro */
669 #define crr(n) ((void (*)(void *, bus_space_handle_t, bus_size_t, u_int8_t *, bus_size_t))(n))
670 #define cwr(n) ((void (*)(void *, bus_space_handle_t, bus_size_t, const u_int8_t *, bus_size_t))(n))
671
672 const struct hppa_bus_space_tag hppa_bustag = {
673 NULL,
674
675 mbus_map, mbus_unmap, mbus_subregion, mbus_alloc, mbus_free,
676 mbus_barrier, mbus_vaddr,
677 mbus_r1, mbus_r2, mbus_r4, mbus_r8,
678 mbus_w1, mbus_w2, mbus_w4, mbus_w8,
679 mbus_rm_1, mbus_rm_2, mbus_rm_4, mbus_rm_8,
680 mbus_wm_1, mbus_wm_2, mbus_wm_4, mbus_wm_8,
681 mbus_sm_1, mbus_sm_2, mbus_sm_4, mbus_sm_8,
682 /* *_raw_* are the same as non-raw for native busses */
683 crr(mbus_rm_1), crr(mbus_rm_1), crr(mbus_rm_1),
684 cwr(mbus_wm_1), cwr(mbus_wm_1), cwr(mbus_wm_1),
685 mbus_rr_1, mbus_rr_2, mbus_rr_4, mbus_rr_8,
686 mbus_wr_1, mbus_wr_2, mbus_wr_4, mbus_wr_8,
687 /* *_raw_* are the same as non-raw for native busses */
688 crr(mbus_rr_1), crr(mbus_rr_1), crr(mbus_rr_1),
689 cwr(mbus_wr_1), cwr(mbus_wr_1), cwr(mbus_wr_1),
690 mbus_sr_1, mbus_sr_2, mbus_sr_4, mbus_sr_8,
691 mbus_cp_1, mbus_cp_2, mbus_cp_4, mbus_cp_8
692 };
693
694 int mbus_dmamap_create(void *v, bus_size_t size, int nsegments,
695 bus_size_t maxsegsz, bus_size_t boundary, int flags,
696 bus_dmamap_t *dmamp);
697 void mbus_dmamap_unload(void *v, bus_dmamap_t map);
698 void mbus_dmamap_destroy(void *v, bus_dmamap_t map);
699 int _bus_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map,
700 void *buf, bus_size_t buflen, struct proc *p, int flags,
701 paddr_t *lastaddrp, int *segp, int first);
702 int mbus_dmamap_load(void *v, bus_dmamap_t map, void *addr,
703 bus_size_t size, struct proc *p, int flags);
704 int mbus_dmamap_load_mbuf(void *v, bus_dmamap_t map,
705 struct mbuf *m0, int flags);
706 int mbus_dmamap_load_uio(void *v, bus_dmamap_t map,
707 struct uio *uio, int flags);
708 int mbus_dmamap_load_raw(void *v, bus_dmamap_t map,
709 bus_dma_segment_t *segs, int nsegs, bus_size_t size,
710 int flags);
711 void mbus_dmamap_sync(void *v, bus_dmamap_t map, bus_addr_t off,
712 bus_size_t len, int ops);
713 int mbus_dmamem_alloc(void *v, bus_size_t size,
714 bus_size_t alignment, bus_size_t boundary,
715 bus_dma_segment_t *segs, int nsegs, int *rsegs, int flags);
716 void mbus_dmamem_free(void *v, bus_dma_segment_t *segs, int nsegs);
717 int mbus_dmamem_map(void *v, bus_dma_segment_t *segs, int nsegs,
718 size_t size, caddr_t *kvap, int flags);
719 void mbus_dmamem_unmap(void *v, caddr_t kva, size_t size);
720 paddr_t mbus_dmamem_mmap(void *v, bus_dma_segment_t *segs, int nsegs,
721 off_t off, int prot, int flags);
722
723 int
mbus_dmamap_create(void * v,bus_size_t size,int nsegments,bus_size_t maxsegsz,bus_size_t boundary,int flags,bus_dmamap_t * dmamp)724 mbus_dmamap_create(void *v, bus_size_t size, int nsegments,
725 bus_size_t maxsegsz, bus_size_t boundary, int flags,
726 bus_dmamap_t *dmamp)
727 {
728 struct hppa_bus_dmamap *map;
729 size_t mapsize;
730
731 mapsize = sizeof(struct hppa_bus_dmamap) +
732 (sizeof(bus_dma_segment_t) * (nsegments - 1));
733 map = malloc(mapsize, M_DEVBUF, (flags & BUS_DMA_NOWAIT) ?
734 (M_NOWAIT | M_ZERO) : (M_WAITOK | M_ZERO));
735 if (!map)
736 return (ENOMEM);
737
738 map->_dm_size = size;
739 map->_dm_segcnt = nsegments;
740 map->_dm_maxsegsz = maxsegsz;
741 map->_dm_boundary = boundary;
742 map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT);
743 map->dm_mapsize = 0;
744 map->dm_nsegs = 0;
745
746 *dmamp = map;
747 return (0);
748 }
749
750 void
mbus_dmamap_unload(void * v,bus_dmamap_t map)751 mbus_dmamap_unload(void *v, bus_dmamap_t map)
752 {
753 map->dm_mapsize = 0;
754 map->dm_nsegs = 0;
755 }
756
757 void
mbus_dmamap_destroy(void * v,bus_dmamap_t map)758 mbus_dmamap_destroy(void *v, bus_dmamap_t map)
759 {
760 if (map->dm_mapsize != 0)
761 mbus_dmamap_unload(v, map);
762
763 free(map, M_DEVBUF, 0);
764 }
765
766 /*
767 * Utility function to load a linear buffer. lastaddrp holds state
768 * between invocations (for multiple-buffer loads). segp contains
769 * the starting segment on entrance, and the ending segment on exit.
770 * first indicates if this is the first invocation of this function.
771 */
772 int
_bus_dmamap_load_buffer(bus_dma_tag_t t,bus_dmamap_t map,void * buf,bus_size_t buflen,struct proc * p,int flags,paddr_t * lastaddrp,int * segp,int first)773 _bus_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
774 bus_size_t buflen, struct proc *p, int flags, paddr_t *lastaddrp,
775 int *segp, int first)
776 {
777 bus_size_t sgsize;
778 bus_addr_t curaddr, lastaddr, baddr, bmask;
779 vaddr_t vaddr = (vaddr_t)buf;
780 int seg;
781 pmap_t pmap;
782
783 pmap = p? p->p_vmspace->vm_map.pmap : pmap_kernel();
784 lastaddr = *lastaddrp;
785 bmask = ~(map->_dm_boundary - 1);
786
787 for (seg = *segp; buflen > 0 ; ) {
788 /*
789 * Get the physical address for this segment.
790 */
791 pmap_extract(pmap, vaddr, (paddr_t *)&curaddr);
792
793 /*
794 * Compute the segment size, and adjust counts.
795 */
796 sgsize = PAGE_SIZE - ((u_long)vaddr & PGOFSET);
797 if (buflen < sgsize)
798 sgsize = buflen;
799
800 /*
801 * Make sure we don't cross any boundaries.
802 */
803 if (map->_dm_boundary > 0) {
804 baddr = (curaddr + map->_dm_boundary) & bmask;
805 if (sgsize > (baddr - curaddr))
806 sgsize = (baddr - curaddr);
807 }
808
809 /*
810 * Insert chunk into a segment, coalescing with
811 * previous segment if possible.
812 */
813 if (first) {
814 map->dm_segs[seg].ds_addr = curaddr;
815 map->dm_segs[seg].ds_len = sgsize;
816 map->dm_segs[seg]._ds_va = vaddr;
817 first = 0;
818 } else {
819 if (curaddr == lastaddr &&
820 (map->dm_segs[seg].ds_len + sgsize) <=
821 map->_dm_maxsegsz &&
822 (map->_dm_boundary == 0 ||
823 (map->dm_segs[seg].ds_addr & bmask) ==
824 (curaddr & bmask)))
825 map->dm_segs[seg].ds_len += sgsize;
826 else {
827 if (++seg >= map->_dm_segcnt)
828 break;
829 map->dm_segs[seg].ds_addr = curaddr;
830 map->dm_segs[seg].ds_len = sgsize;
831 map->dm_segs[seg]._ds_va = vaddr;
832 }
833 }
834
835 lastaddr = curaddr + sgsize;
836 vaddr += sgsize;
837 buflen -= sgsize;
838 }
839
840 *segp = seg;
841 *lastaddrp = lastaddr;
842
843 /*
844 * Did we fit?
845 */
846 if (buflen != 0)
847 return (EFBIG); /* XXX better return value here? */
848 return (0);
849 }
850
851 int
mbus_dmamap_load(void * v,bus_dmamap_t map,void * addr,bus_size_t size,struct proc * p,int flags)852 mbus_dmamap_load(void *v, bus_dmamap_t map, void *addr, bus_size_t size,
853 struct proc *p, int flags)
854 {
855 paddr_t lastaddr;
856 int seg, error;
857
858 /*
859 * Make sure that on error condition we return "no valid mappings".
860 */
861 map->dm_nsegs = 0;
862 map->dm_mapsize = 0;
863
864 if (size > map->_dm_size)
865 return (EINVAL);
866
867 seg = 0;
868 lastaddr = 0;
869 error = _bus_dmamap_load_buffer(NULL, map, addr, size, p, flags,
870 &lastaddr, &seg, 1);
871 if (error == 0) {
872 map->dm_mapsize = size;
873 map->dm_nsegs = seg + 1;
874 }
875
876 return (0);
877 }
878
879 int
mbus_dmamap_load_mbuf(void * v,bus_dmamap_t map,struct mbuf * m0,int flags)880 mbus_dmamap_load_mbuf(void *v, bus_dmamap_t map, struct mbuf *m0, int flags)
881 {
882 paddr_t lastaddr;
883 int seg, error, first;
884 struct mbuf *m;
885
886 map->dm_mapsize = 0;
887 map->dm_nsegs = 0;
888
889 #ifdef DIAGNOSTIC
890 if ((m0->m_flags & M_PKTHDR) == 0)
891 panic("_bus_dmamap_load_mbuf: no packet header");
892 #endif
893
894 if (m0->m_pkthdr.len > map->_dm_size)
895 return (EINVAL);
896
897 first = 1;
898 seg = 0;
899 error = 0;
900 lastaddr = 0;
901 for (m = m0; m != NULL && error == 0; m = m->m_next) {
902 if (m->m_len == 0)
903 continue;
904 error = _bus_dmamap_load_buffer(NULL, map, m->m_data, m->m_len,
905 NULL, flags, &lastaddr, &seg, first);
906 first = 0;
907 }
908 if (error == 0) {
909 map->dm_mapsize = m0->m_pkthdr.len;
910 map->dm_nsegs = seg + 1;
911 }
912
913 return (error);
914 }
915
916 int
mbus_dmamap_load_uio(void * v,bus_dmamap_t map,struct uio * uio,int flags)917 mbus_dmamap_load_uio(void *v, bus_dmamap_t map, struct uio *uio, int flags)
918 {
919 paddr_t lastaddr;
920 int seg, i, error, first;
921 bus_size_t minlen, resid;
922 struct proc *p = NULL;
923 struct iovec *iov;
924 caddr_t addr;
925
926 /*
927 * Make sure that on error condition we return "no valid mappings".
928 */
929 map->dm_mapsize = 0;
930 map->dm_nsegs = 0;
931
932 resid = uio->uio_resid;
933 iov = uio->uio_iov;
934
935 if (resid > map->_dm_size)
936 return (EINVAL);
937
938 if (uio->uio_segflg == UIO_USERSPACE) {
939 p = uio->uio_procp;
940 #ifdef DIAGNOSTIC
941 if (p == NULL)
942 panic("_bus_dmamap_load_uio: USERSPACE but no proc");
943 #endif
944 }
945
946 first = 1;
947 seg = 0;
948 error = 0;
949 lastaddr = 0;
950 for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) {
951 /*
952 * Now at the first iovec to load. Load each iovec
953 * until we have exhausted the residual count.
954 */
955 minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len;
956 addr = (caddr_t)iov[i].iov_base;
957
958 error = _bus_dmamap_load_buffer(NULL, map, addr, minlen,
959 p, flags, &lastaddr, &seg, first);
960 first = 0;
961
962 resid -= minlen;
963 }
964 if (error == 0) {
965 map->dm_mapsize = uio->uio_resid;
966 map->dm_nsegs = seg + 1;
967 }
968 return (error);
969 }
970
971 int
mbus_dmamap_load_raw(void * v,bus_dmamap_t map,bus_dma_segment_t * segs,int nsegs,bus_size_t size,int flags)972 mbus_dmamap_load_raw(void *v, bus_dmamap_t map, bus_dma_segment_t *segs,
973 int nsegs, bus_size_t size, int flags)
974 {
975 if (nsegs > map->_dm_segcnt || size > map->_dm_size)
976 return (EINVAL);
977
978 /*
979 * Make sure we don't cross any boundaries.
980 */
981 if (map->_dm_boundary) {
982 bus_addr_t bmask = ~(map->_dm_boundary - 1);
983 int i;
984
985 for (i = 0; i < nsegs; i++) {
986 if (segs[i].ds_len > map->_dm_maxsegsz)
987 return (EINVAL);
988 if ((segs[i].ds_addr & bmask) !=
989 ((segs[i].ds_addr + segs[i].ds_len - 1) & bmask))
990 return (EINVAL);
991 }
992 }
993
994 bcopy(segs, map->dm_segs, nsegs * sizeof(*segs));
995 map->dm_nsegs = nsegs;
996 map->dm_mapsize = size;
997 return (0);
998 }
999
1000 void
mbus_dmamap_sync(void * v,bus_dmamap_t map,bus_addr_t off,bus_size_t len,int ops)1001 mbus_dmamap_sync(void *v, bus_dmamap_t map, bus_addr_t off, bus_size_t len,
1002 int ops)
1003 {
1004 bus_dma_segment_t *ps = map->dm_segs,
1005 *es = &map->dm_segs[map->dm_nsegs];
1006
1007 if (off >= map->_dm_size)
1008 return;
1009
1010 if ((off + len) > map->_dm_size)
1011 len = map->_dm_size - off;
1012
1013 for (; len && ps < es; ps++)
1014 if (off > ps->ds_len)
1015 off -= ps->ds_len;
1016 else {
1017 bus_size_t l = ps->ds_len - off;
1018 if (l > len)
1019 l = len;
1020 fdcache(HPPA_SID_KERNEL, ps->_ds_va + off, l);
1021 len -= l;
1022 off = 0;
1023 }
1024
1025 /* for either operation sync the shit away */
1026 __asm volatile ("sync\n\tsyncdma\n\tsync\n\t"
1027 "nop\n\tnop\n\tnop\n\tnop\n\tnop\n\tnop\n\tnop");
1028 }
1029
1030 int
mbus_dmamem_alloc(void * v,bus_size_t size,bus_size_t alignment,bus_size_t boundary,bus_dma_segment_t * segs,int nsegs,int * rsegs,int flags)1031 mbus_dmamem_alloc(void *v, bus_size_t size, bus_size_t alignment,
1032 bus_size_t boundary, bus_dma_segment_t *segs, int nsegs,
1033 int *rsegs, int flags)
1034 {
1035 struct pglist pglist;
1036 struct vm_page *pg;
1037 int plaflag;
1038
1039 size = round_page(size);
1040
1041 plaflag = flags & BUS_DMA_NOWAIT ? UVM_PLA_NOWAIT : UVM_PLA_WAITOK;
1042 if (flags & BUS_DMA_ZERO)
1043 plaflag |= UVM_PLA_ZERO;
1044
1045 TAILQ_INIT(&pglist);
1046 if (uvm_pglistalloc(size, 0, -1, alignment, boundary,
1047 &pglist, 1, plaflag))
1048 return (ENOMEM);
1049
1050 pg = TAILQ_FIRST(&pglist);
1051 segs[0]._ds_va = segs[0].ds_addr = VM_PAGE_TO_PHYS(pg);
1052 segs[0].ds_len = size;
1053 *rsegs = 1;
1054
1055 for(; pg; pg = TAILQ_NEXT(pg, pageq))
1056 /* XXX for now */
1057 pmap_changebit(pg, PTE_PROT(TLB_UNCACHABLE), 0);
1058 pmap_update(pmap_kernel());
1059
1060 return (0);
1061 }
1062
1063 void
mbus_dmamem_free(void * v,bus_dma_segment_t * segs,int nsegs)1064 mbus_dmamem_free(void *v, bus_dma_segment_t *segs, int nsegs)
1065 {
1066 struct pglist pglist;
1067 paddr_t pa, epa;
1068
1069 TAILQ_INIT(&pglist);
1070 for(; nsegs--; segs++)
1071 for (pa = segs->ds_addr, epa = pa + segs->ds_len;
1072 pa < epa; pa += PAGE_SIZE) {
1073 struct vm_page *pg = PHYS_TO_VM_PAGE(pa);
1074 if (!pg)
1075 panic("mbus_dmamem_free: no page for pa");
1076 TAILQ_INSERT_TAIL(&pglist, pg, pageq);
1077 pdcache(HPPA_SID_KERNEL, pa, PAGE_SIZE);
1078 pdtlb(HPPA_SID_KERNEL, pa);
1079 pitlb(HPPA_SID_KERNEL, pa);
1080 }
1081 uvm_pglistfree(&pglist);
1082 }
1083
1084 int
mbus_dmamem_map(void * v,bus_dma_segment_t * segs,int nsegs,size_t size,caddr_t * kvap,int flags)1085 mbus_dmamem_map(void *v, bus_dma_segment_t *segs, int nsegs, size_t size,
1086 caddr_t *kvap, int flags)
1087 {
1088 *kvap = (caddr_t)segs[0].ds_addr;
1089 return 0;
1090 }
1091
1092 void
mbus_dmamem_unmap(void * v,caddr_t kva,size_t size)1093 mbus_dmamem_unmap(void *v, caddr_t kva, size_t size)
1094 {
1095 }
1096
1097 paddr_t
mbus_dmamem_mmap(void * v,bus_dma_segment_t * segs,int nsegs,off_t off,int prot,int flags)1098 mbus_dmamem_mmap(void *v, bus_dma_segment_t *segs, int nsegs, off_t off,
1099 int prot, int flags)
1100 {
1101 panic("_dmamem_mmap: not implemented");
1102 }
1103
1104 const struct hppa_bus_dma_tag hppa_dmatag = {
1105 NULL,
1106 mbus_dmamap_create, mbus_dmamap_destroy,
1107 mbus_dmamap_load, mbus_dmamap_load_mbuf,
1108 mbus_dmamap_load_uio, mbus_dmamap_load_raw,
1109 mbus_dmamap_unload, mbus_dmamap_sync,
1110
1111 mbus_dmamem_alloc, mbus_dmamem_free, mbus_dmamem_map,
1112 mbus_dmamem_unmap, mbus_dmamem_mmap
1113 };
1114
1115 int
mbmatch(parent,cfdata,aux)1116 mbmatch(parent, cfdata, aux)
1117 struct device *parent;
1118 void *cfdata;
1119 void *aux;
1120 {
1121 struct cfdata *cf = cfdata;
1122
1123 /* there will be only one */
1124 if (cf->cf_unit)
1125 return 0;
1126
1127 return 1;
1128 }
1129
1130 void
mbattach(parent,self,aux)1131 mbattach(parent, self, aux)
1132 struct device *parent;
1133 struct device *self;
1134 void *aux;
1135 {
1136 struct mainbus_softc *sc = (struct mainbus_softc *)self;
1137 struct confargs nca;
1138 bus_space_handle_t ioh;
1139
1140 /* fetch the "default" cpu hpa */
1141 if (pdc_call((iodcio_t)pdc, 0, PDC_HPA, PDC_HPA_DFLT, &pdc_hpa) < 0)
1142 panic("mbattach: PDC_HPA failed");
1143
1144 printf(" [flex %x]\n", pdc_hpa.hpa & HPPA_FLEX_MASK);
1145
1146 /* map all the way till the end of the memory */
1147 if (bus_space_map(&hppa_bustag, pdc_hpa.hpa,
1148 (~0LU - pdc_hpa.hpa + 1), 0, &ioh))
1149 panic("mbattach: cannot map mainbus IO space");
1150
1151 /*
1152 * Local-Broadcast the HPA to all modules on this bus
1153 */
1154 ((struct iomod *)HPPA_LBCAST)->io_flex =
1155 (pdc_hpa.hpa & HPPA_FLEX_MASK) | DMA_ENABLE;
1156
1157 sc->sc_hpa = pdc_hpa.hpa;
1158
1159 /* PDC first */
1160 bzero(&nca, sizeof(nca));
1161 nca.ca_name = "pdc";
1162 nca.ca_iot = &hppa_bustag;
1163 nca.ca_dmatag = &hppa_dmatag;
1164 config_found(self, &nca, mbprint);
1165
1166 #if NPOWER > 0
1167 /* get some power */
1168 bzero(&nca, sizeof(nca));
1169 nca.ca_name = "power";
1170 nca.ca_irq = -1;
1171 if (!pdc_call((iodcio_t)pdc, 0, PDC_SOFT_POWER,
1172 PDC_SOFT_POWER_INFO, &pdc_power_info, 0)) {
1173 nca.ca_iot = &hppa_bustag;
1174 nca.ca_hpa = pdc_power_info.addr;
1175 nca.ca_hpamask = HPPA_IOBEGIN;
1176 }
1177 config_found(self, &nca, mbprint);
1178 #endif
1179
1180 #if NLCD > 0
1181 if (!pdc_call((iodcio_t)pdc, 0, PDC_CHASSIS, PDC_CHASSIS_INFO,
1182 &pdc_chassis_info, &pdc_chassis_lcd, sizeof(pdc_chassis_lcd)) &&
1183 pdc_chassis_lcd.enabled) {
1184 bzero(&nca, sizeof(nca));
1185 nca.ca_name = "lcd";
1186 nca.ca_irq = -1;
1187 nca.ca_iot = &hppa_bustag;
1188 nca.ca_hpa = pdc_chassis_lcd.cmd_addr;
1189 nca.ca_hpamask = HPPA_IOBEGIN;
1190 nca.ca_pdc_iodc_read = (void *)&pdc_chassis_lcd;
1191
1192 config_found(self, &nca, mbprint);
1193 }
1194 #endif
1195
1196 bzero(&nca, sizeof(nca));
1197 nca.ca_hpa = 0;
1198 nca.ca_irq = -1;
1199 nca.ca_hpamask = HPPA_IOBEGIN;
1200 nca.ca_iot = &hppa_bustag;
1201 nca.ca_dmatag = &hppa_dmatag;
1202 nca.ca_dp.dp_bc[0] = nca.ca_dp.dp_bc[1] = nca.ca_dp.dp_bc[2] =
1203 nca.ca_dp.dp_bc[3] = nca.ca_dp.dp_bc[4] = nca.ca_dp.dp_bc[5] = -1;
1204 nca.ca_dp.dp_mod = -1;
1205 switch (cpu_hvers) {
1206 case HPPA_BOARD_HP809:
1207 case HPPA_BOARD_HP819:
1208 case HPPA_BOARD_HP829:
1209 case HPPA_BOARD_HP839:
1210 case HPPA_BOARD_HP849:
1211 case HPPA_BOARD_HP859:
1212 case HPPA_BOARD_HP869:
1213 #if 0
1214 case HPPA_BOARD_HP770_J200:
1215 case HPPA_BOARD_HP770_J210:
1216 case HPPA_BOARD_HP770_J210XC:
1217 case HPPA_BOARD_HP780_J282:
1218 case HPPA_BOARD_HP782_J2240:
1219 #endif
1220 case HPPA_BOARD_HP780_C160:
1221 case HPPA_BOARD_HP780_C180P:
1222 case HPPA_BOARD_HP780_C180XP:
1223 case HPPA_BOARD_HP780_C200:
1224 case HPPA_BOARD_HP780_C230:
1225 case HPPA_BOARD_HP780_C240:
1226 case HPPA_BOARD_HP785_C360:
1227 /* Attach CPUs first, then everything else... */
1228 ncpusfound = 0;
1229 pdc_scanbus(self, &nca, MAXMODBUS, HPPA_FPA, 1);
1230 pdc_scanbus(self, &nca, MAXMODBUS, HPPA_FPA, 0);
1231 break;
1232 default:
1233 /* Attach CPUs first, then everything else... */
1234 ncpusfound = 0;
1235 pdc_scanbus(self, &nca, MAXMODBUS, 0, 1);
1236 pdc_scanbus(self, &nca, MAXMODBUS, 0, 0);
1237 }
1238 }
1239
1240 /*
1241 * Retrieve CPU #N HPA value
1242 */
1243 hppa_hpa_t
cpu_gethpa(n)1244 cpu_gethpa(n)
1245 int n;
1246 {
1247 struct mainbus_softc *sc;
1248
1249 sc = mainbus_cd.cd_devs[0];
1250
1251 return sc->sc_hpa;
1252 }
1253
1254 int
mbprint(aux,pnp)1255 mbprint(aux, pnp)
1256 void *aux;
1257 const char *pnp;
1258 {
1259 struct confargs *ca = aux;
1260
1261 if (pnp)
1262 printf("\"%s\" at %s (type %x sv %x mod %x hv %x)",
1263 ca->ca_name, pnp,
1264 ca->ca_type.iodc_type, ca->ca_type.iodc_sv_model,
1265 ca->ca_type.iodc_model, ca->ca_type.iodc_revision);
1266 if (ca->ca_hpa) {
1267 if (~ca->ca_hpamask)
1268 printf(" offset %lx", ca->ca_hpa & ~ca->ca_hpamask);
1269 if (!pnp && ca->ca_irq >= 0)
1270 printf(" irq %d", ca->ca_irq);
1271 }
1272
1273 return (UNCONF);
1274 }
1275
1276 int
mbsubmatch(parent,match,aux)1277 mbsubmatch(parent, match, aux)
1278 struct device *parent;
1279 void *match, *aux;
1280 {
1281 struct cfdata *cf = match;
1282 struct confargs *ca = aux;
1283 int ret;
1284
1285 if (autoconf_verbose)
1286 printf(">> hpa %lx off %lx cf_off %lx\n",
1287 ca->ca_hpa, ca->ca_hpa & ~ca->ca_hpamask, cf->hppacf_off);
1288
1289 if (ca->ca_hpa && ~ca->ca_hpamask && cf->hppacf_off != -1 &&
1290 ((ca->ca_hpa & ~ca->ca_hpamask) != cf->hppacf_off))
1291 return (0);
1292
1293 if ((ret = (*cf->cf_attach->ca_match)(parent, match, aux)))
1294 ca->ca_irq = cf->hppacf_irq;
1295
1296 return ret;
1297 }
1298
1299