Annotation of sys/arch/hp300/dev/isabr.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: isabr.c,v 1.2 2007/01/14 17:54:45 miod Exp $ */
2:
3: /*
4: * Copyright (c) 2007 Miodrag Vallat.
5: *
6: * Permission to use, copy, modify, and distribute this software for any
7: * purpose with or without fee is hereby granted, provided that the above
8: * copyright notice, this permission notice, and the disclaimer below
9: * 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 USE, DATA OR PROFITS, WHETHER IN AN
16: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18: */
19:
20: /*
21: * HP 9000/4xx model `t' single ISA slot attachment
22: */
23:
24: #include <sys/param.h>
25: #include <sys/systm.h>
26: #include <sys/device.h>
27: #include <sys/extent.h>
28: #include <sys/malloc.h>
29:
30: #include <machine/autoconf.h>
31: #include <machine/bus.h>
32: #include <machine/cpu.h>
33: #include <machine/hp300spu.h>
34:
35: #include <uvm/uvm_extern.h>
36:
37: #include <dev/isa/isareg.h>
38: #include <dev/isa/isavar.h>
39:
40: #include <hp300/dev/frodoreg.h>
41: #include <hp300/dev/frodovar.h>
42: #include <hp300/dev/isabrreg.h>
43:
44: int isabr_match(struct device *, void *, void *);
45: void isabr_attach(struct device *, struct device *, void *);
46: int isabr_print(void *, const char *);
47:
48: struct isabr_softc {
49: struct device sc_dev;
50: struct extent *sc_io_extent;
51: struct extent *sc_mem_extent;
52: };
53:
54: struct cfattach isabr_ca = {
55: sizeof(struct isabr_softc), isabr_match, isabr_attach
56: };
57:
58: struct cfdriver isabr_cd = {
59: NULL, "isabr", DV_DULL
60: };
61:
62: struct isabr_softc *isabr;
63:
64: int isabr_bus_space_setup(struct isabr_softc *, struct frodo_attach_args *,
65: struct isabus_attach_args *);
66:
67: int
68: isabr_match(struct device *parent, void *match, void *aux)
69: {
70: struct frodo_attach_args *fa = aux;
71: static int isa_matched = 0;
72:
73: if (isa_matched != 0)
74: return (0);
75:
76: if (strcmp(fa->fa_name, isabr_cd.cd_name) != 0)
77: return (0);
78:
79: /*
80: * We assume parent has checked our physical existence for us.
81: */
82:
83: return (isa_matched = 1);
84: }
85:
86: void
87: isabr_attach(struct device *parent, struct device *self, void *aux)
88: {
89: struct isabus_attach_args iba;
90: struct isabr_softc *sc = (struct isabr_softc *)self;
91: struct frodo_attach_args *faa = (struct frodo_attach_args *)aux;
92:
93: bzero(&iba, sizeof(iba));
94:
95: if (isabr_bus_space_setup(sc, faa, &iba) != 0) {
96: printf(": can not initialize bus_space\n");
97: return;
98: }
99: printf("\n");
100:
101: iba.iba_busname = "isa";
102: config_found(self, &iba, isabr_print);
103: }
104:
105: int
106: isabr_print(void *aux, const char *pnp)
107: {
108: if (pnp)
109: printf("isa at %s", pnp);
110: return (UNCONF);
111: }
112:
113: /*
114: * ISA support functions
115: */
116:
117: void
118: isa_attach_hook(struct device *parent, struct device *self,
119: struct isabus_attach_args *iba)
120: {
121: iba->iba_ic = parent; /* isabr0 */
122: }
123:
124: /*
125: * Interrupt handling.
126: *
127: * We are currently registering ISA interrupt handlers as Frodo interrupt
128: * handlers directly. We can because model `t' only have a single slot.
129: *
130: * Eventually this should be replaced with an isabr interrupt dispatcher,
131: * allowing multiple interrupts on the same Frodo line. This would also
132: * move the ISA-specific acknowledge out of non-ISA Frodo lines processing.
133: * And this would allow a real intr_disestablish function.
134: */
135: void *
136: isa_intr_establish(isa_chipset_tag_t ic, int irq, int type, int level,
137: int (*handler)(void *), void *arg, char *name)
138: {
139: struct isabr_softc *sc = (struct isabr_softc *)ic;
140: struct isr *isr;
141: int fline;
142:
143: /*
144: * Frodo is configured for edge interrupts.
145: */
146: if (type != IST_EDGE) {
147: #ifdef DIAGNOSTIC
148: printf("%s: non-edge interrupt type not supported on hp300\n",
149: name);
150: #endif
151: return (NULL);
152: }
153:
154: switch (irq) {
155: case 3:
156: case 4:
157: case 5:
158: case 6:
159: fline = FRODO_INTR_ILOW;
160: break;
161: case 7:
162: case 9:
163: case 10:
164: case 11:
165: fline = FRODO_INTR_IMID;
166: break;
167: case 12:
168: case 14:
169: case 15:
170: fline = FRODO_INTR_IHI;
171: break;
172: default:
173: #ifdef DIAGNOSTIC
174: printf("%s: ISA irq %d not available on " MACHINE "\n", name);
175: #endif
176: return (NULL);
177: }
178:
179: isr = (struct isr *)malloc(sizeof(struct isr), M_DEVBUF, M_NOWAIT);
180: if (isr == NULL)
181: return (NULL);
182:
183: isr->isr_func = handler;
184: isr->isr_arg = arg;
185: isr->isr_priority = level;
186:
187: if (frodo_intr_establish(sc->sc_dev.dv_parent, fline, isr, name) == 0)
188: return (isr);
189:
190: free(isr, M_DEVBUF);
191: return (NULL);
192: }
193:
194: void
195: isa_intr_disestablish(isa_chipset_tag_t ic, void *cookie)
196: {
197: #if 0
198: struct isabr_softc *sc = (struct isabr_softc *)ic;
199: struct isr *isr = cookie;
200:
201: /* XXX how to find fline back? */
202: frodo_intr_disestablish(sc->dv_parent, fline);
203: free(isr, M_DEVBUF);
204: #else
205: panic("isa_intr_disestablish");
206: #endif
207: }
208:
209: /*
210: * Implementation of bus_space mapping for the hp300 isa slot.
211: *
212: * Everything is memory mapped, but the I/O space is scattered for better
213: * userland access control granularity, should we ever provide iopl
214: * facilities, thus i/o space accesses need their own routines set, while
215: * memory space simply reuse the ``canonical'' bus_space routines.
216: *
217: * For the I/O space, all bus_space_map allocations are extended to a 8 ports
218: * granularity, so that they span entire, contiguous pages; the handle value
219: * however needs to keep track of the in-page offset if the first port is
220: * not aligned to a ``line'' boundary.
221: *
222: * I.e, a bus_space_map(0x302, 0xe) call will map the 0x300-0x30f area,
223: * and return a pointer the 0x302 port. Access routines will then, from
224: * this pointer, construct a (0x300, 0x02) tuple, which they can use to
225: * access the remainder of the range.
226: */
227:
228: /*
229: * ISA I/O space
230: */
231:
232: int hp300_isa_io_map(bus_addr_t, bus_size_t, int, bus_space_handle_t *);
233: void hp300_isa_io_unmap(bus_space_handle_t, bus_size_t);
234: int hp300_isa_io_subregion(bus_space_handle_t, bus_size_t, bus_size_t,
235: bus_space_handle_t *);
236: void * hp300_isa_io_vaddr(bus_space_handle_t);
237:
238: u_int8_t hp300_isa_io_bsr1(bus_space_handle_t, bus_size_t);
239: u_int16_t hp300_isa_io_bsr2(bus_space_handle_t, bus_size_t);
240: u_int32_t hp300_isa_io_bsr4(bus_space_handle_t, bus_size_t);
241: u_int16_t __hp300_isa_io_bsr2(bus_space_handle_t, bus_size_t);
242: u_int32_t __hp300_isa_io_bsr4(bus_space_handle_t, bus_size_t);
243: void hp300_isa_io_bsrm1(bus_space_handle_t, bus_size_t, u_int8_t *, size_t);
244: void hp300_isa_io_bsrm2(bus_space_handle_t, bus_size_t, u_int16_t *, size_t);
245: void hp300_isa_io_bsrm4(bus_space_handle_t, bus_size_t, u_int32_t *, size_t);
246: void hp300_isa_io_bsrrm2(bus_space_handle_t, bus_size_t, u_int8_t *, size_t);
247: void hp300_isa_io_bsrrm4(bus_space_handle_t, bus_size_t, u_int8_t *, size_t);
248: void hp300_isa_io_bsrr1(bus_space_handle_t, bus_size_t, u_int8_t *, size_t);
249: void hp300_isa_io_bsrr2(bus_space_handle_t, bus_size_t, u_int16_t *, size_t);
250: void hp300_isa_io_bsrr4(bus_space_handle_t, bus_size_t, u_int32_t *, size_t);
251: void hp300_isa_io_bsrrr2(bus_space_handle_t, bus_size_t, u_int8_t *, size_t);
252: void hp300_isa_io_bsrrr4(bus_space_handle_t, bus_size_t, u_int8_t *, size_t);
253: void hp300_isa_io_bsw1(bus_space_handle_t, bus_size_t, u_int8_t);
254: void hp300_isa_io_bsw2(bus_space_handle_t, bus_size_t, u_int16_t);
255: void hp300_isa_io_bsw4(bus_space_handle_t, bus_size_t, u_int32_t);
256: void __hp300_isa_io_bsw2(bus_space_handle_t, bus_size_t, u_int16_t);
257: void __hp300_isa_io_bsw4(bus_space_handle_t, bus_size_t, u_int32_t);
258: void hp300_isa_io_bswm1(bus_space_handle_t, bus_size_t, const u_int8_t *, size_t);
259: void hp300_isa_io_bswm2(bus_space_handle_t, bus_size_t, const u_int16_t *, size_t);
260: void hp300_isa_io_bswm4(bus_space_handle_t, bus_size_t, const u_int32_t *, size_t);
261: void hp300_isa_io_bswrm2(bus_space_handle_t, bus_size_t, const u_int8_t *, size_t);
262: void hp300_isa_io_bswrm4(bus_space_handle_t, bus_size_t, const u_int8_t *, size_t);
263: void hp300_isa_io_bswr1(bus_space_handle_t, bus_size_t, const u_int8_t *, size_t);
264: void hp300_isa_io_bswr2(bus_space_handle_t, bus_size_t, const u_int16_t *, size_t);
265: void hp300_isa_io_bswr4(bus_space_handle_t, bus_size_t, const u_int32_t *, size_t);
266: void hp300_isa_io_bswrr2(bus_space_handle_t, bus_size_t, const u_int8_t *, size_t);
267: void hp300_isa_io_bswrr4(bus_space_handle_t, bus_size_t, const u_int8_t *, size_t);
268: void hp300_isa_io_bssm1(bus_space_handle_t, bus_size_t, u_int8_t, size_t);
269: void hp300_isa_io_bssm2(bus_space_handle_t, bus_size_t, u_int16_t, size_t);
270: void hp300_isa_io_bssm4(bus_space_handle_t, bus_size_t, u_int32_t, size_t);
271: void hp300_isa_io_bssr1(bus_space_handle_t, bus_size_t, u_int8_t, size_t);
272: void hp300_isa_io_bssr2(bus_space_handle_t, bus_size_t, u_int16_t, size_t);
273: void hp300_isa_io_bssr4(bus_space_handle_t, bus_size_t, u_int32_t, size_t);
274:
275: struct hp300_bus_space_tag hp300_isa_io_tag = {
276: hp300_isa_io_map,
277: hp300_isa_io_unmap,
278: hp300_isa_io_subregion,
279: hp300_isa_io_vaddr,
280:
281: hp300_isa_io_bsr1,
282: hp300_isa_io_bsr2,
283: hp300_isa_io_bsr4,
284:
285: hp300_isa_io_bsrm1,
286: hp300_isa_io_bsrm2,
287: hp300_isa_io_bsrm4,
288:
289: hp300_isa_io_bsrrm2,
290: hp300_isa_io_bsrrm4,
291:
292: hp300_isa_io_bsrr1,
293: hp300_isa_io_bsrr2,
294: hp300_isa_io_bsrr4,
295:
296: hp300_isa_io_bsrrr2,
297: hp300_isa_io_bsrrr4,
298:
299: hp300_isa_io_bsw1,
300: hp300_isa_io_bsw2,
301: hp300_isa_io_bsw4,
302:
303: hp300_isa_io_bswm1,
304: hp300_isa_io_bswm2,
305: hp300_isa_io_bswm4,
306:
307: hp300_isa_io_bswrm2,
308: hp300_isa_io_bswrm4,
309:
310: hp300_isa_io_bswr1,
311: hp300_isa_io_bswr2,
312: hp300_isa_io_bswr4,
313:
314: hp300_isa_io_bswrr2,
315: hp300_isa_io_bswrr4,
316:
317: hp300_isa_io_bssm1,
318: hp300_isa_io_bssm2,
319: hp300_isa_io_bssm4,
320:
321: hp300_isa_io_bssr1,
322: hp300_isa_io_bssr2,
323: hp300_isa_io_bssr4
324: };
325:
326: int
327: hp300_isa_io_map(bus_addr_t bpa, bus_size_t size, int flags,
328: bus_space_handle_t *bshp)
329: {
330: int error;
331: u_int iobase, iosize, npg;
332: vaddr_t va;
333: paddr_t pa;
334:
335: #ifdef DEBUG
336: printf("isa_io_map(%04x, %04x)", bpa, size);
337: #endif
338:
339: /*
340: * Reserve the range in the allocation extent.
341: */
342: if (bpa < IO_ISABEGIN || bpa + size > IO_ISAEND + 1) {
343: #ifdef DEBUG
344: printf(" outside available range\n");
345: #endif
346: return (ERANGE);
347: }
348: error = extent_alloc_region(isabr->sc_io_extent, bpa, size,
349: EX_MALLOCOK);
350: if (error != 0) {
351: #ifdef DEBUG
352: printf(" overlaps extent\n");
353: #endif
354: return (error);
355: }
356:
357: /*
358: * Round the allocation to a multiple of 8 bytes, to end up
359: * with entire pages.
360: */
361: iobase = bpa & ~(ISABR_IOPORT_LINE - 1);
362: iosize = ((bpa + size + (ISABR_IOPORT_LINE - 1)) &
363: ~(ISABR_IOPORT_LINE - 1)) - iobase;
364:
365: /*
366: * Compute how many pages will be necessary to map this range.
367: */
368: npg = iosize / ISABR_IOPORT_LINE;
369: #ifdef DEBUG
370: printf("->(%04x, %04x)=%d@", iobase, iosize, npg);
371: #endif
372:
373: /*
374: * Allocate virtual address space to map this space in.
375: */
376: va = uvm_km_valloc(kernel_map, ptoa(npg));
377: if (va == 0) {
378: #ifdef DEBUG
379: printf("NULL\n");
380: #endif
381: extent_free(isabr->sc_io_extent, bpa, size, EX_MALLOCOK);
382: return (ENOMEM);
383: }
384:
385: *bshp = (bus_space_handle_t)(va + (bpa - iobase));
386:
387: pa = ISABR_IOPORT_BASE + ISAADDR(iobase);
388: #ifdef DEBUG
389: printf("%08x (ret %08x) pa %08x\n", va, *bshp, pa);
390: #endif
391:
392: while (npg != 0) {
393: pmap_kenter_cache(va, pa, PG_RW | PG_CI);
394: npg--;
395: va += PAGE_SIZE;
396: pa += PAGE_SIZE;
397: }
398: pmap_update(pmap_kernel());
399:
400: return (0);
401: }
402:
403: void
404: hp300_isa_io_unmap(bus_space_handle_t bsh, bus_size_t size)
405: {
406: u_int iobase, iosize, npg;
407: vaddr_t va;
408: paddr_t pa;
409:
410: #ifdef DEBUG
411: printf("isa_io_unmap(%08x, %04x)", bsh, size);
412: #endif
413:
414: /*
415: * Find the pa matching this allocation, and the I/O port base
416: * from it.
417: */
418: va = (vaddr_t)bsh;
419: if (pmap_extract(pmap_kernel(), va, &pa) == FALSE) {
420: #ifdef DEBUG
421: printf("-> no pa\n");
422: #endif
423: return; /* XXX be vocal? */
424: }
425:
426: #ifdef DEBUG
427: printf("-> pa %08x ", pa);
428: #endif
429: pa -= ISABR_IOPORT_BASE;
430: iobase = ISAPORT(pa);
431: if (iobase < IO_ISABEGIN || iobase > IO_ISAEND) {
432: #ifdef DEBUG
433: printf("iobase %08x???\n", iobase);
434: #endif
435: return; /* XXX be vocal? */
436: }
437:
438: iosize = size + (iobase & (ISABR_IOPORT_LINE - 1)) +
439: (ISABR_IOPORT_LINE - 1);
440: npg = iosize / ISABR_IOPORT_LINE;
441: #ifdef DEBUG
442: printf(" range %04x-%04x: %d\n", iobase, size, npg);
443: #endif
444:
445: pmap_kremove(va, ptoa(npg));
446: pmap_update(pmap_kernel());
447: uvm_km_free(kernel_map, va, ptoa(npg));
448:
449: (void)extent_free(isabr->sc_io_extent, (u_long)iobase, size,
450: EX_MALLOCOK);
451: }
452:
453: /*
454: * Round down an I/O space bus_space_handle, so that it points to the
455: * beginning of a page.
456: * This is gonna be hell when we support ports above 0x400.
457: */
458: #define REALIGN_IO_HANDLE(h, o) \
459: do { \
460: u_int tmp; \
461: tmp = (h) & (ISABR_IOPORT_LINE - 1); \
462: (h) -= tmp; \
463: (o) += tmp; \
464: } while (0)
465:
466: /* ARGSUSED */
467: int
468: hp300_isa_io_subregion(bus_space_handle_t bsh, bus_size_t offset,
469: bus_size_t size, bus_space_handle_t *nbshp)
470: {
471: REALIGN_IO_HANDLE(bsh, offset);
472: bsh += ISAADDR(offset);
473: *nbshp = bsh;
474: return (0);
475: }
476:
477: void *
478: hp300_isa_io_vaddr(bus_space_handle_t h)
479: {
480: return (NULL);
481: }
482:
483: /* bus_space_read_X */
484:
485: u_int8_t
486: hp300_isa_io_bsr1(bus_space_handle_t bsh, bus_size_t offset)
487: {
488: vaddr_t va;
489: u_int8_t rc;
490:
491: REALIGN_IO_HANDLE(bsh, offset);
492: va = (vaddr_t)bsh + ISAADDR(offset);
493: rc = *(volatile u_int8_t *)va;
494: #ifdef DEBUG
495: printf("R%03x(%x):%02x\t", offset, va, rc);
496: #endif
497: return (rc);
498: }
499:
500: u_int16_t
501: __hp300_isa_io_bsr2(bus_space_handle_t bsh, bus_size_t offset)
502: {
503: u_int16_t rc;
504: vaddr_t va;
505:
506: if (offset & 1) {
507: rc = hp300_isa_io_bsr1(bsh, offset + 1) << 8;
508: rc |= hp300_isa_io_bsr1(bsh, offset);
509: } else {
510: REALIGN_IO_HANDLE(bsh, offset);
511: va = (vaddr_t)bsh + ISAADDR(offset);
512: rc = *(volatile u_int16_t *)va;
513: }
514: #ifdef DEBUG
515: printf("R%03x:%04x\t", offset, rc);
516: #endif
517: return (rc);
518: }
519:
520: u_int16_t
521: hp300_isa_io_bsr2(bus_space_handle_t bsh, bus_size_t offset)
522: {
523: u_int16_t rc;
524:
525: rc = __hp300_isa_io_bsr2(bsh, offset);
526: return (letoh16(rc));
527: }
528:
529: u_int32_t
530: __hp300_isa_io_bsr4(bus_space_handle_t bsh, bus_size_t offset)
531: {
532: u_int32_t rc;
533: vaddr_t va;
534:
535: if (offset & 3) {
536: rc = hp300_isa_io_bsr1(bsh, offset + 3) << 24;
537: rc |= hp300_isa_io_bsr1(bsh, offset + 2) << 16;
538: rc |= hp300_isa_io_bsr1(bsh, offset + 1) << 8;
539: rc |= hp300_isa_io_bsr1(bsh, offset);
540: } else {
541: REALIGN_IO_HANDLE(bsh, offset);
542: va = (vaddr_t)bsh + ISAADDR(offset);
543: rc = *(volatile u_int32_t *)va;
544: }
545: #ifdef DEBUG
546: printf("R%03x:%08x\t", offset, rc);
547: #endif
548: return (rc);
549: }
550:
551: u_int32_t
552: hp300_isa_io_bsr4(bus_space_handle_t bsh, bus_size_t offset)
553: {
554: u_int32_t rc;
555:
556: rc = __hp300_isa_io_bsr4(bsh, offset);
557: return (letoh32(rc));
558: }
559:
560: /* bus_space_read_multi_X */
561:
562: void
563: hp300_isa_io_bsrm1(bus_space_handle_t h, bus_size_t offset,
564: u_int8_t *a, size_t c)
565: {
566: while ((int)--c >= 0)
567: *a++ = hp300_isa_io_bsr1(h, offset);
568: }
569:
570: void
571: hp300_isa_io_bsrm2(bus_space_handle_t h, bus_size_t offset,
572: u_int16_t *a, size_t c)
573: {
574: while ((int)--c >= 0)
575: *a++ = hp300_isa_io_bsr2(h, offset);
576: }
577:
578: void
579: hp300_isa_io_bsrm4(bus_space_handle_t h, bus_size_t offset,
580: u_int32_t *a, size_t c)
581: {
582: while ((int)--c >= 0)
583: *a++ = hp300_isa_io_bsr4(h, offset);
584: }
585:
586: /* bus_space_read_raw_multi_X */
587:
588: void
589: hp300_isa_io_bsrrm2(bus_space_handle_t h, bus_size_t offset,
590: u_int8_t *a, size_t c)
591: {
592: while ((int)--c >= 0) {
593: *(u_int16_t *)a = __hp300_isa_io_bsr2(h, offset);
594: a += 2;
595: }
596: }
597:
598: void
599: hp300_isa_io_bsrrm4(bus_space_handle_t h, bus_size_t offset,
600: u_int8_t *a, size_t c)
601: {
602: while ((int)--c >= 0) {
603: *(u_int32_t *)a = __hp300_isa_io_bsr4(h, offset);
604: a += 4;
605: }
606: }
607:
608: /* bus_space_read_region_X */
609:
610: void
611: hp300_isa_io_bsrr1(bus_space_handle_t h, bus_size_t offset,
612: u_int8_t *a, size_t c)
613: {
614: while ((int)--c >= 0)
615: *a++ = hp300_isa_io_bsr1(h, offset++);
616: }
617:
618: void
619: hp300_isa_io_bsrr2(bus_space_handle_t h, bus_size_t offset,
620: u_int16_t *a, size_t c)
621: {
622: while ((int)--c >= 0) {
623: *a++ = hp300_isa_io_bsr2(h, offset);
624: offset += 2;
625: }
626: }
627:
628: void
629: hp300_isa_io_bsrr4(bus_space_handle_t h, bus_size_t offset,
630: u_int32_t *a, size_t c)
631: {
632: while ((int)--c >= 0) {
633: *a++ = hp300_isa_io_bsr4(h, offset);
634: offset += 4;
635: }
636: }
637:
638: /* bus_space_read_raw_region_X */
639:
640: void
641: hp300_isa_io_bsrrr2(bus_space_handle_t h, bus_size_t offset,
642: u_int8_t *a, size_t c)
643: {
644: c >>= 1;
645: while ((int)--c >= 0) {
646: *(u_int16_t *)a = __hp300_isa_io_bsr2(h, offset);
647: offset += 2;
648: a += 2;
649: }
650: }
651:
652: void
653: hp300_isa_io_bsrrr4(bus_space_handle_t h, bus_size_t offset,
654: u_int8_t *a, size_t c)
655: {
656: c >>= 2;
657: while ((int)--c >= 0) {
658: *(u_int32_t *)a = __hp300_isa_io_bsr4(h, offset);
659: offset += 4;
660: a += 4;
661: }
662: }
663:
664: /* bus_space_write_X */
665:
666: void
667: hp300_isa_io_bsw1(bus_space_handle_t h, bus_size_t offset, u_int8_t v)
668: {
669: vaddr_t va;
670:
671: REALIGN_IO_HANDLE(h, offset);
672: va = (vaddr_t)h + ISAADDR(offset);
673: *(volatile u_int8_t *)va = v;
674: #ifdef DEBUG
675: printf("W%03x:%02x\t", offset, v);
676: #endif
677: }
678:
679: void
680: __hp300_isa_io_bsw2(bus_space_handle_t h, bus_size_t offset, u_int16_t v)
681: {
682: vaddr_t va;
683:
684: if (offset & 1) {
685: hp300_isa_io_bsw1(h, offset + 1, v >> 8);
686: hp300_isa_io_bsw1(h, offset, v);
687: } else {
688: REALIGN_IO_HANDLE(h, offset);
689: va = (vaddr_t)h + ISAADDR(offset);
690: *(volatile u_int16_t *)va = v;
691: }
692: #ifdef DEBUG
693: printf("W%03x:%04x\t", offset, v);
694: #endif
695: }
696:
697: void
698: hp300_isa_io_bsw2(bus_space_handle_t h, bus_size_t offset, u_int16_t v)
699: {
700: __hp300_isa_io_bsw2(h, offset, htole16(v));
701: }
702:
703: void
704: __hp300_isa_io_bsw4(bus_space_handle_t h, bus_size_t offset, u_int32_t v)
705: {
706: vaddr_t va;
707:
708: if (offset & 3) {
709: hp300_isa_io_bsw1(h, offset + 3, v >> 24);
710: hp300_isa_io_bsw1(h, offset + 2, v >> 16);
711: hp300_isa_io_bsw1(h, offset + 1, v >> 8);
712: hp300_isa_io_bsw1(h, offset, v);
713: } else {
714: REALIGN_IO_HANDLE(h, offset);
715: va = (vaddr_t)h + ISAADDR(offset);
716: *(volatile u_int32_t *)va = v;
717: }
718: #ifdef DEBUG
719: printf("W%03x:%08x\t", offset, v);
720: #endif
721: }
722:
723: void
724: hp300_isa_io_bsw4(bus_space_handle_t h, bus_size_t offset, u_int32_t v)
725: {
726: __hp300_isa_io_bsw4(h, offset, htole32(v));
727: }
728:
729: /* bus_space_write_multi_X */
730:
731: void
732: hp300_isa_io_bswm1(bus_space_handle_t h, bus_size_t offset,
733: const u_int8_t *a, size_t c)
734: {
735: while ((int)--c >= 0)
736: hp300_isa_io_bsw1(h, offset, *a++);
737: }
738:
739: void
740: hp300_isa_io_bswm2(bus_space_handle_t h, bus_size_t offset,
741: const u_int16_t *a, size_t c)
742: {
743: while ((int)--c >= 0)
744: hp300_isa_io_bsw2(h, offset, *a++);
745: }
746:
747: void
748: hp300_isa_io_bswm4(bus_space_handle_t h, bus_size_t offset,
749: const u_int32_t *a, size_t c)
750: {
751: while ((int)--c >= 0)
752: hp300_isa_io_bsw4(h, offset, *a++);
753: }
754:
755: /* bus_space_write_raw_multi_X */
756:
757: void
758: hp300_isa_io_bswrm2(bus_space_handle_t h, bus_size_t offset,
759: const u_int8_t *a, size_t c)
760: {
761: while ((int)--c >= 0) {
762: __hp300_isa_io_bsw2(h, offset, *(u_int16_t *)a);
763: a += 2;
764: }
765: }
766:
767: void
768: hp300_isa_io_bswrm4(bus_space_handle_t h, bus_size_t offset,
769: const u_int8_t *a, size_t c)
770: {
771: while ((int)--c >= 0) {
772: __hp300_isa_io_bsw4(h, offset, *(u_int32_t *)a);
773: a += 4;
774: }
775: }
776:
777: /* bus_space_write_region_X */
778:
779: void
780: hp300_isa_io_bswr1(bus_space_handle_t h, bus_size_t offset,
781: const u_int8_t *a, size_t c)
782: {
783: while ((int)--c >= 0)
784: hp300_isa_io_bsw1(h, offset++, *a++);
785: }
786:
787: void
788: hp300_isa_io_bswr2(bus_space_handle_t h, bus_size_t offset,
789: const u_int16_t *a, size_t c)
790: {
791: while ((int)--c >= 0) {
792: hp300_isa_io_bsw2(h, offset, *a++);
793: offset += 2;
794: }
795: }
796:
797: void
798: hp300_isa_io_bswr4(bus_space_handle_t h, bus_size_t offset,
799: const u_int32_t *a, size_t c)
800: {
801: while ((int)--c >= 0) {
802: hp300_isa_io_bsw4(h, offset, *a++);
803: offset += 4;
804: }
805: }
806:
807: /* bus_space_write_raw_region_X */
808:
809: void
810: hp300_isa_io_bswrr2(bus_space_handle_t h, bus_size_t offset,
811: const u_int8_t *a, size_t c)
812: {
813: c >>= 1;
814: while ((int)--c >= 0) {
815: __hp300_isa_io_bsw2(h, offset, *(u_int16_t *)a);
816: offset += 2;
817: a += 2;
818: }
819: }
820:
821: void
822: hp300_isa_io_bswrr4(bus_space_handle_t h, bus_size_t offset,
823: const u_int8_t *a, size_t c)
824: {
825: c >>= 2;
826: while ((int)--c >= 0) {
827: __hp300_isa_io_bsw4(h, offset, *(u_int32_t *)a);
828: offset += 4;
829: a += 4;
830: }
831: }
832:
833: /* bus_space_set_multi_X */
834:
835: void
836: hp300_isa_io_bssm1(bus_space_handle_t h, bus_size_t offset,
837: u_int8_t v, size_t c)
838: {
839: while ((int)--c >= 0)
840: hp300_isa_io_bsw1(h, offset, v);
841: }
842:
843: void
844: hp300_isa_io_bssm2(bus_space_handle_t h, bus_size_t offset,
845: u_int16_t v, size_t c)
846: {
847: while ((int)--c >= 0)
848: hp300_isa_io_bsw2(h, offset, v);
849: }
850:
851: void
852: hp300_isa_io_bssm4(bus_space_handle_t h, bus_size_t offset,
853: u_int32_t v, size_t c)
854: {
855: while ((int)--c >= 0)
856: hp300_isa_io_bsw4(h, offset, v);
857: }
858:
859: /* bus_space_set_region_X */
860:
861: void
862: hp300_isa_io_bssr1(bus_space_handle_t h, bus_size_t offset,
863: u_int8_t v, size_t c)
864: {
865: while ((int)--c >= 0)
866: hp300_isa_io_bsw1(h, offset++, v);
867: }
868:
869: void
870: hp300_isa_io_bssr2(bus_space_handle_t h, bus_size_t offset,
871: u_int16_t v, size_t c)
872: {
873: while ((int)--c >= 0) {
874: hp300_isa_io_bsw2(h, offset, v);
875: offset += 2;
876: }
877: }
878:
879: void
880: hp300_isa_io_bssr4(bus_space_handle_t h, bus_size_t offset,
881: u_int32_t v, size_t c)
882: {
883: while ((int)--c >= 0) {
884: hp300_isa_io_bsw4(h, offset, v);
885: offset += 4;
886: }
887: }
888:
889: /*
890: * ISA memory space
891: */
892:
893: int hp300_isa_mem_map(bus_addr_t, bus_size_t, int, bus_space_handle_t *);
894: void hp300_isa_mem_unmap(bus_space_handle_t, bus_size_t);
895:
896: int
897: hp300_isa_mem_map(bus_addr_t bpa, bus_size_t size, int flags,
898: bus_space_handle_t *bshp)
899: {
900: int error;
901: bus_addr_t membase;
902: bus_size_t rsize;
903: vaddr_t va;
904: paddr_t pa;
905: pt_entry_t template;
906:
907: /*
908: * Reserve the range in the allocation extent.
909: */
910: if (bpa < IOM_BEGIN || bpa + size > IOM_END)
911: return (ERANGE);
912: error = extent_alloc_region(isabr->sc_mem_extent, bpa, size,
913: EX_MALLOCOK);
914: if (error != 0)
915: return (error);
916:
917: /*
918: * Allocate virtual address space to map this space in.
919: */
920: membase = trunc_page(bpa);
921: rsize = round_page(bpa + size) - membase;
922: va = uvm_km_valloc(kernel_map, rsize);
923: if (va == 0) {
924: extent_free(isabr->sc_mem_extent, bpa, size, EX_MALLOCOK);
925: return (ENOMEM);
926: }
927:
928: *bshp = (bus_space_handle_t)(va + (bpa - membase));
929:
930: pa = membase + (ISABR_IOMEM_BASE - IOM_BEGIN);
931:
932: if (flags & BUS_SPACE_MAP_CACHEABLE)
933: template = PG_RW;
934: else
935: template = PG_RW | PG_CI;
936:
937: while (rsize != 0) {
938: pmap_kenter_cache(va, pa, template);
939: rsize -= PAGE_SIZE;
940: va += PAGE_SIZE;
941: pa += PAGE_SIZE;
942: }
943: pmap_update(pmap_kernel());
944:
945: return (0);
946: }
947:
948: void
949: hp300_isa_mem_unmap(bus_space_handle_t bsh, bus_size_t size)
950: {
951: vaddr_t va;
952: vsize_t rsize;
953:
954: va = trunc_page((vaddr_t)bsh);
955: rsize = round_page((vaddr_t)bsh + size) - va;
956:
957: pmap_kremove(va, rsize);
958: pmap_update(pmap_kernel());
959: uvm_km_free(kernel_map, va, rsize);
960:
961: (void)extent_free(isabr->sc_mem_extent, (u_long)bsh, size, EX_MALLOCOK);
962: }
963:
964: struct hp300_bus_space_tag hp300_isa_mem_tag; /* will be filled in */
965:
966: /*
967: * ISA bus_space initialization.
968: * This creates the necessary accounting elements and initializes the
969: * memory space bus_space_tag.
970: */
971:
972: int
973: isabr_bus_space_setup(struct isabr_softc *sc, struct frodo_attach_args *faa,
974: struct isabus_attach_args *iba)
975: {
976: /*
977: * Create the space extents.
978: * We only use them to prevent multiple allocations of the same areas.
979: */
980:
981: sc->sc_io_extent = extent_create("isa_io", IO_ISABEGIN,
982: IO_ISAEND + 1, M_DEVBUF, NULL, 0, EX_NOWAIT | EX_MALLOCOK);
983: if (sc->sc_io_extent == NULL)
984: return (ENOMEM);
985:
986: sc->sc_mem_extent = extent_create("isa_mem", IOM_BEGIN,
987: IOM_END, M_DEVBUF, NULL, 0, EX_NOWAIT | EX_MALLOCOK);
988: if (sc->sc_mem_extent == NULL) {
989: extent_destroy(sc->sc_io_extent);
990: return (ENOMEM);
991: }
992:
993: iba->iba_iot = &hp300_isa_io_tag;
994: bcopy(faa->fa_tag, &hp300_isa_mem_tag,
995: sizeof(struct hp300_bus_space_tag));
996: hp300_isa_mem_tag.bs_map = hp300_isa_mem_map;
997: hp300_isa_mem_tag.bs_unmap = hp300_isa_mem_unmap;
998: iba->iba_memt = &hp300_isa_mem_tag;
999:
1000: isabr = sc;
1001:
1002: return (0);
1003: }
CVSweb