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