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