Annotation of sys/arch/sparc64/dev/psycho.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: psycho.c,v 1.52 2007/08/04 16:44:15 kettenis Exp $ */
2: /* $NetBSD: psycho.c,v 1.39 2001/10/07 20:30:41 eeh Exp $ */
3:
4: /*
5: * Copyright (c) 1999, 2000 Matthew R. Green
6: * Copyright (c) 2003 Henric Jungheim
7: * All rights reserved.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. The name of the author may not be used to endorse or promote products
18: * derived from this software without specific prior written permission.
19: *
20: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25: * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26: * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27: * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30: * SUCH DAMAGE.
31: */
32:
33: /*
34: * Support for `psycho' and `psycho+' UPA to PCI bridge and
35: * UltraSPARC IIi and IIe `sabre' PCI controllers.
36: */
37:
38: #include <sys/param.h>
39: #include <sys/device.h>
40: #include <sys/errno.h>
41: #include <sys/extent.h>
42: #include <sys/malloc.h>
43: #include <sys/systm.h>
44: #include <sys/time.h>
45: #include <sys/reboot.h>
46:
47: #include <uvm/uvm_extern.h>
48:
49: #define _SPARC_BUS_DMA_PRIVATE
50: #include <machine/bus.h>
51: #include <machine/autoconf.h>
52: #include <machine/psl.h>
53:
54: #include <dev/pci/pcivar.h>
55: #include <dev/pci/pcireg.h>
56:
57: #include <sparc64/dev/iommureg.h>
58: #include <sparc64/dev/iommuvar.h>
59: #include <sparc64/dev/psychoreg.h>
60: #include <sparc64/dev/psychovar.h>
61: #include <sparc64/sparc64/cache.h>
62:
63: #ifdef DEBUG
64: #define PDB_PROM 0x01
65: #define PDB_BUSMAP 0x02
66: #define PDB_INTR 0x04
67: #define PDB_CONF 0x08
68: int psycho_debug = ~0;
69: #define DPRINTF(l, s) do { if (psycho_debug & l) printf s; } while (0)
70: #else
71: #define DPRINTF(l, s)
72: #endif
73:
74: pci_chipset_tag_t psycho_alloc_chipset(struct psycho_pbm *, int,
75: pci_chipset_tag_t);
76: void psycho_get_bus_range(int, int *);
77: void psycho_get_ranges(int, struct psycho_ranges **, int *);
78: void psycho_set_intr(struct psycho_softc *, int, void *,
79: u_int64_t *, u_int64_t *, const char *);
80: bus_space_tag_t psycho_alloc_bus_tag(struct psycho_pbm *,
81: const char *, int, int, int);
82:
83: /* Interrupt handlers */
84: int psycho_ue(void *);
85: int psycho_ce(void *);
86: int psycho_bus_a(void *);
87: int psycho_bus_b(void *);
88: int psycho_bus_error(struct psycho_softc *, int);
89: int psycho_powerfail(void *);
90: int psycho_wakeup(void *);
91:
92: /* IOMMU support */
93: void psycho_iommu_init(struct psycho_softc *, int);
94:
95: /*
96: * bus space and bus dma support for UltraSPARC `psycho'. note that most
97: * of the bus dma support is provided by the iommu dvma controller.
98: */
99: int psycho_bus_map(bus_space_tag_t, bus_space_tag_t, bus_addr_t,
100: bus_size_t, int, bus_space_handle_t *);
101: paddr_t psycho_bus_mmap(bus_space_tag_t, bus_space_tag_t, bus_addr_t, off_t,
102: int, int);
103: bus_addr_t psycho_bus_addr(bus_space_tag_t, bus_space_tag_t,
104: bus_space_handle_t);
105: void *psycho_intr_establish(bus_space_tag_t, bus_space_tag_t, int, int, int,
106: int (*)(void *), void *, const char *);
107:
108: int psycho_dmamap_create(bus_dma_tag_t, bus_dma_tag_t, bus_size_t, int,
109: bus_size_t, bus_size_t, int, bus_dmamap_t *);
110: void psycho_sabre_dvmamap_sync(bus_dma_tag_t, bus_dma_tag_t, bus_dmamap_t,
111: bus_size_t, bus_size_t, int);
112: void psycho_map_psycho(struct psycho_softc *, int, bus_addr_t, bus_size_t,
113: bus_addr_t, bus_size_t);
114: int psycho_intr_map(struct pci_attach_args *, pci_intr_handle_t *);
115: void psycho_identify_pbm(struct psycho_softc *sc, struct psycho_pbm *pp,
116: struct pcibus_attach_args *pa);
117:
118: /* base pci_chipset */
119: extern struct sparc_pci_chipset _sparc_pci_chipset;
120:
121: /*
122: * autoconfiguration
123: */
124: int psycho_match(struct device *, void *, void *);
125: void psycho_attach(struct device *, struct device *, void *);
126: int psycho_print(void *aux, const char *p);
127:
128:
129: struct cfattach psycho_ca = {
130: sizeof(struct psycho_softc), psycho_match, psycho_attach
131: };
132:
133: struct cfdriver psycho_cd = {
134: NULL, "psycho", DV_DULL
135: };
136:
137: /*
138: * "sabre" is the UltraSPARC IIi onboard UPA to PCI bridge. It manages a
139: * single PCI bus and does not have a streaming buffer. It often has an APB
140: * (advanced PCI bridge) connected to it, which was designed specifically for
141: * the IIi. The APB let's the IIi handle two independednt PCI buses, and
142: * appears as two "simba"'s underneath the sabre.
143: *
144: * "psycho" and "psycho+" is a dual UPA to PCI bridge. It sits on the UPA bus
145: * and manages two PCI buses. "psycho" has two 64-bit 33MHz buses, while
146: * "psycho+" controls both a 64-bit 33MHz and a 64-bit 66MHz PCI bus. You
147: * will usually find a "psycho+" since I don't think the original "psycho"
148: * ever shipped, and if it did it would be in the U30.
149: *
150: * Each "psycho" PCI bus appears as a separate OFW node, but since they are
151: * both part of the same IC, they only have a single register space. As such,
152: * they need to be configured together, even though the autoconfiguration will
153: * attach them separately.
154: *
155: * On UltraIIi machines, "sabre" itself usually takes pci0, with "simba" often
156: * as pci1 and pci2, although they have been implemented with other PCI bus
157: * numbers on some machines.
158: *
159: * On UltraII machines, there can be any number of "psycho+" ICs, each
160: * providing two PCI buses.
161: *
162: *
163: * XXXX The psycho/sabre node has an `interrupts' attribute. They contain
164: * the values of the following interrupts in this order:
165: *
166: * PCI Bus Error (30)
167: * DMA UE (2e)
168: * DMA CE (2f)
169: * Power Fail (25)
170: *
171: * We really should attach handlers for each.
172: *
173: */
174: #define ROM_PCI_NAME "pci"
175:
176: struct psycho_type {
177: char *p_name;
178: int p_type;
179: } psycho_types[] = {
180: { "SUNW,psycho", PSYCHO_MODE_PSYCHO },
181: { "pci108e,8000", PSYCHO_MODE_PSYCHO },
182: { "SUNW,sabre", PSYCHO_MODE_SABRE },
183: { "pci108e,a000", PSYCHO_MODE_SABRE },
184: { "pci108e,a001", PSYCHO_MODE_SABRE },
185: { NULL, 0 }
186: };
187:
188: int
189: psycho_match(struct device *parent, void *match, void *aux)
190: {
191: struct mainbus_attach_args *ma = aux;
192: struct psycho_type *ptype;
193: char *str;
194:
195: /* match on a name of "pci" and a sabre or a psycho */
196: if (strcmp(ma->ma_name, ROM_PCI_NAME) != 0)
197: return (0);
198:
199: for (ptype = psycho_types; ptype->p_name != NULL; ptype++) {
200: str = getpropstring(ma->ma_node, "model");
201: if (strcmp(str, ptype->p_name) == 0)
202: return (1);
203: str = getpropstring(ma->ma_node, "compatible");
204: if (strcmp(str, ptype->p_name) == 0)
205: return (1);
206: }
207: return (0);
208: }
209:
210: /*
211: * SUNW,psycho initialization ...
212: * - find the per-psycho registers
213: * - figure out the IGN.
214: * - find our partner psycho
215: * - configure ourselves
216: * - bus range, bus,
217: * - get interrupt-map and interrupt-map-mask
218: * - setup the chipsets.
219: * - if we're the first of the pair, initialise the IOMMU, otherwise
220: * just copy its tags and addresses.
221: */
222: void
223: psycho_attach(struct device *parent, struct device *self, void *aux)
224: {
225: struct psycho_softc *sc = (struct psycho_softc *)self;
226: struct psycho_softc *osc = NULL;
227: struct psycho_pbm *pp;
228: struct pcibus_attach_args pba;
229: struct mainbus_attach_args *ma = aux;
230: u_int64_t csr;
231: int psycho_br[2], n;
232: struct psycho_type *ptype;
233:
234: sc->sc_node = ma->ma_node;
235: sc->sc_bustag = ma->ma_bustag;
236: sc->sc_dmatag = ma->ma_dmatag;
237:
238: /*
239: * call the model-specific initialization routine.
240: */
241:
242: for (ptype = psycho_types; ptype->p_name != NULL; ptype++) {
243: char *str;
244:
245: str = getpropstring(ma->ma_node, "model");
246: if (strcmp(str, ptype->p_name) == 0)
247: break;
248: str = getpropstring(ma->ma_node, "compatible");
249: if (strcmp(str, ptype->p_name) == 0)
250: break;
251: }
252: if (ptype->p_name == NULL)
253: panic("psycho_attach: unknown model?");
254: sc->sc_mode = ptype->p_type;
255:
256: /*
257: * The psycho gets three register banks:
258: * (0) per-PBM configuration and status registers
259: * (1) per-PBM PCI configuration space, containing only the
260: * PBM 256-byte PCI header
261: * (2) the shared psycho configuration registers (struct psychoreg)
262: *
263: * XXX use the prom address for the psycho registers? we do so far.
264: */
265:
266: /* Register layouts are different. stuupid. */
267: if (sc->sc_mode == PSYCHO_MODE_PSYCHO) {
268: sc->sc_basepaddr = (paddr_t)ma->ma_reg[2].ur_paddr;
269:
270: if (ma->ma_naddress > 2) {
271: psycho_map_psycho(sc, 0,
272: ma->ma_address[2], sizeof(struct psychoreg),
273: ma->ma_address[0], sizeof(struct pci_ctl));
274: } else if (ma->ma_nreg > 2) {
275: psycho_map_psycho(sc, 1,
276: ma->ma_reg[2].ur_paddr, ma->ma_reg[2].ur_len,
277: ma->ma_reg[0].ur_paddr, ma->ma_reg[0].ur_len);
278: } else
279: panic("psycho_attach: %d not enough registers",
280: ma->ma_nreg);
281: } else {
282: sc->sc_basepaddr = (paddr_t)ma->ma_reg[0].ur_paddr;
283:
284: if (ma->ma_naddress) {
285: psycho_map_psycho(sc, 0,
286: ma->ma_address[0], sizeof(struct psychoreg),
287: ma->ma_address[0] +
288: offsetof(struct psychoreg, psy_pcictl[0]),
289: sizeof(struct pci_ctl));
290: } else if (ma->ma_nreg) {
291: psycho_map_psycho(sc, 1,
292: ma->ma_reg[0].ur_paddr, ma->ma_reg[0].ur_len,
293: ma->ma_reg[0].ur_paddr +
294: offsetof(struct psychoreg, psy_pcictl[0]),
295: sizeof(struct pci_ctl));
296: } else
297: panic("psycho_attach: %d not enough registers",
298: ma->ma_nreg);
299: }
300:
301: csr = psycho_psychoreg_read(sc, psy_csr);
302: sc->sc_ign = INTMAP_IGN; /* APB IGN is always 0x1f << 6 = 0x7c */
303: if (sc->sc_mode == PSYCHO_MODE_PSYCHO)
304: sc->sc_ign = PSYCHO_GCSR_IGN(csr) << 6;
305:
306: printf(": %s, impl %d, version %d, ign %x\n", ptype->p_name,
307: PSYCHO_GCSR_IMPL(csr), PSYCHO_GCSR_VERS(csr), sc->sc_ign);
308:
309: /*
310: * Match other psycho's that are already configured against
311: * the base physical address. This will be the same for a
312: * pair of devices that share register space.
313: */
314: for (n = 0; n < psycho_cd.cd_ndevs; n++) {
315: struct psycho_softc *asc =
316: (struct psycho_softc *)psycho_cd.cd_devs[n];
317:
318: if (asc == NULL || asc == sc)
319: /* This entry is not there or it is me */
320: continue;
321:
322: if (asc->sc_basepaddr != sc->sc_basepaddr)
323: /* This is an unrelated psycho */
324: continue;
325:
326: /* Found partner */
327: osc = asc;
328: break;
329: }
330:
331: /* Oh, dear. OK, lets get started */
332:
333: /*
334: * Setup the PCI control register
335: */
336: csr = psycho_pcictl_read(sc, pci_csr);
337: csr |= PCICTL_MRLM | PCICTL_ARB_PARK | PCICTL_ERRINTEN |
338: PCICTL_4ENABLE;
339: csr &= ~(PCICTL_SERR | PCICTL_CPU_PRIO | PCICTL_ARB_PRIO |
340: PCICTL_RTRYWAIT);
341: psycho_pcictl_write(sc, pci_csr, csr);
342:
343: /*
344: * Allocate our psycho_pbm
345: */
346: pp = sc->sc_psycho_this = malloc(sizeof *pp, M_DEVBUF, M_NOWAIT);
347: if (pp == NULL)
348: panic("could not allocate psycho pbm");
349:
350: memset(pp, 0, sizeof *pp);
351:
352: pp->pp_sc = sc;
353:
354: /* grab the psycho ranges */
355: psycho_get_ranges(sc->sc_node, &pp->pp_range, &pp->pp_nrange);
356:
357: /* get the bus-range for the psycho */
358: psycho_get_bus_range(sc->sc_node, psycho_br);
359:
360: pba.pba_domain = pci_ndomains++;
361: pba.pba_bus = psycho_br[0];
362: pba.pba_bridgetag = NULL;
363:
364: printf("%s: bus range %u-%u, PCI bus %d\n", sc->sc_dev.dv_xname,
365: psycho_br[0], psycho_br[1], psycho_br[0]);
366:
367: pp->pp_pcictl = sc->sc_pcictl;
368:
369: /* allocate our tags */
370: pp->pp_memt = psycho_alloc_mem_tag(pp);
371: pp->pp_iot = psycho_alloc_io_tag(pp);
372: pp->pp_dmat = psycho_alloc_dma_tag(pp);
373: pp->pp_flags = (pp->pp_memt ? PCI_FLAGS_MEM_ENABLED : 0) |
374: (pp->pp_iot ? PCI_FLAGS_IO_ENABLED : 0);
375:
376: /* allocate a chipset for this */
377: pp->pp_pc = psycho_alloc_chipset(pp, sc->sc_node, &_sparc_pci_chipset);
378:
379: /* setup the rest of the psycho pbm */
380: pba.pba_pc = pp->pp_pc;
381:
382: /*
383: * And finally, if we're a sabre or the first of a pair of psycho's to
384: * arrive here, start up the IOMMU and get a config space tag.
385: */
386:
387: if (osc == NULL) {
388: uint64_t timeo;
389:
390: /*
391: * Establish handlers for interesting interrupts....
392: *
393: * XXX We need to remember these and remove this to support
394: * hotplug on the UPA/FHC bus.
395: *
396: * XXX Not all controllers have these, but installing them
397: * is better than trying to sort through this mess.
398: */
399: psycho_set_intr(sc, 15, psycho_ue,
400: psycho_psychoreg_vaddr(sc, ue_int_map),
401: psycho_psychoreg_vaddr(sc, ue_clr_int), "ue");
402: psycho_set_intr(sc, 1, psycho_ce,
403: psycho_psychoreg_vaddr(sc, ce_int_map),
404: psycho_psychoreg_vaddr(sc, ce_clr_int), "ce");
405: psycho_set_intr(sc, 15, psycho_bus_a,
406: psycho_psychoreg_vaddr(sc, pciaerr_int_map),
407: psycho_psychoreg_vaddr(sc, pciaerr_clr_int), "bus_a");
408: #if 0
409: psycho_set_intr(sc, 15, psycho_powerfail,
410: psycho_psychoreg_vaddr(sc, power_int_map),
411: psycho_psychoreg_vaddr(sc, power_clr_int), "powerfail");
412: #endif
413: if (sc->sc_mode == PSYCHO_MODE_PSYCHO) {
414: psycho_set_intr(sc, 15, psycho_bus_b,
415: psycho_psychoreg_vaddr(sc, pciberr_int_map),
416: psycho_psychoreg_vaddr(sc, pciberr_clr_int),
417: "bus_b");
418: psycho_set_intr(sc, 1, psycho_wakeup,
419: psycho_psychoreg_vaddr(sc, pwrmgt_int_map),
420: psycho_psychoreg_vaddr(sc, pwrmgt_clr_int),
421: "wakeup");
422: }
423:
424: /*
425: * Apparently a number of machines with psycho and psycho+
426: * controllers have interrupt latency issues. We'll try
427: * setting the interrupt retry timeout to 0xff which gives us
428: * a retry of 3-6 usec (which is what sysio is set to) for the
429: * moment, which seems to help alleviate this problem.
430: */
431: timeo = psycho_psychoreg_read(sc, intr_retry_timer);
432: if (timeo > 0xfff) {
433: #ifdef DEBUG
434: printf("decreasing interrupt retry timeout "
435: "from %lx to 0xff\n", (long)timeo);
436: #endif
437: psycho_psychoreg_write(sc, intr_retry_timer, 0xff);
438: }
439:
440: /*
441: * Setup IOMMU and PCI configuration if we're the first
442: * of a pair of psycho's to arrive here.
443: *
444: * We should calculate a TSB size based on the amount of RAM,
445: * number of bus controllers, and number and type of child
446: * devices.
447: *
448: * For the moment, 32KB should be more than enough.
449: */
450: sc->sc_is = malloc(sizeof(struct iommu_state),
451: M_DEVBUF, M_NOWAIT);
452: if (sc->sc_is == NULL)
453: panic("psycho_attach: malloc iommu_state");
454:
455: memset(sc->sc_is, 0, sizeof *sc->sc_is);
456:
457: if (getproplen(sc->sc_node, "no-streaming-cache") < 0) {
458: struct strbuf_ctl *sb = &pp->pp_sb;
459: vaddr_t va = (vaddr_t)&pp->pp_flush[0x40];
460:
461: /*
462: * Initialize the strbuf_ctl.
463: *
464: * The flush sync buffer must be 64-byte aligned.
465: */
466:
467: sb->sb_flush = (void *)(va & ~0x3f);
468:
469: sb->sb_bustag = sc->sc_bustag;
470: if (bus_space_subregion(sc->sc_bustag, sc->sc_pcictl,
471: offsetof(struct pci_ctl, pci_strbuf),
472: sizeof(struct iommu_strbuf),
473: &sb->sb_sb)) {
474: printf("STC0 subregion failed\n");
475: sb->sb_flush = 0;
476: }
477: }
478:
479: /* Point out iommu at the strbuf_ctl. */
480: sc->sc_is->is_sb[0] = &pp->pp_sb;
481:
482: printf("%s: ", sc->sc_dev.dv_xname);
483: psycho_iommu_init(sc, 2);
484:
485: sc->sc_configtag = psycho_alloc_config_tag(sc->sc_psycho_this);
486: if (bus_space_map(sc->sc_configtag,
487: sc->sc_basepaddr, 0x01000000, 0, &sc->sc_configaddr))
488: panic("could not map psycho PCI configuration space");
489: } else {
490: /* Just copy IOMMU state, config tag and address */
491: sc->sc_is = osc->sc_is;
492: sc->sc_configtag = osc->sc_configtag;
493: sc->sc_configaddr = osc->sc_configaddr;
494:
495: if (getproplen(sc->sc_node, "no-streaming-cache") < 0) {
496: struct strbuf_ctl *sb = &pp->pp_sb;
497: vaddr_t va = (vaddr_t)&pp->pp_flush[0x40];
498:
499: /*
500: * Initialize the strbuf_ctl.
501: *
502: * The flush sync buffer must be 64-byte aligned.
503: */
504:
505: sb->sb_flush = (void *)(va & ~0x3f);
506:
507: sb->sb_bustag = sc->sc_bustag;
508: if (bus_space_subregion(sc->sc_bustag, sc->sc_pcictl,
509: offsetof(struct pci_ctl, pci_strbuf),
510: sizeof(struct iommu_strbuf),
511: &sb->sb_sb)) {
512: printf("STC1 subregion failed\n");
513: sb->sb_flush = 0;
514: }
515:
516: /* Point out iommu at the strbuf_ctl. */
517: sc->sc_is->is_sb[1] = sb;
518: }
519:
520: /* Point out iommu at the strbuf_ctl. */
521: sc->sc_is->is_sb[1] = &pp->pp_sb;
522:
523: printf("%s: ", sc->sc_dev.dv_xname);
524: printf("dvma map %x-%x, ", sc->sc_is->is_dvmabase,
525: sc->sc_is->is_dvmaend);
526: printf("iotdb %llx-%llx",
527: (unsigned long long)sc->sc_is->is_ptsb,
528: (unsigned long long)(sc->sc_is->is_ptsb +
529: (PAGE_SIZE << sc->sc_is->is_tsbsize)));
530: iommu_reset(sc->sc_is);
531: printf("\n");
532: }
533:
534: /*
535: * attach the pci.. note we pass PCI A tags, etc., for the sabre here.
536: */
537: pba.pba_busname = "pci";
538: #if 0
539: pba.pba_flags = sc->sc_psycho_this->pp_flags;
540: #endif
541: pba.pba_dmat = sc->sc_psycho_this->pp_dmat;
542: pba.pba_iot = sc->sc_psycho_this->pp_iot;
543: pba.pba_memt = sc->sc_psycho_this->pp_memt;
544: pba.pba_pc->bustag = sc->sc_configtag;
545: pba.pba_pc->bushandle = sc->sc_configaddr;
546: pba.pba_pc->intr_map = psycho_intr_map;
547:
548: if (sc->sc_mode == PSYCHO_MODE_PSYCHO)
549: psycho_identify_pbm(sc, pp, &pba);
550: else
551: pp->pp_id = PSYCHO_PBM_UNKNOWN;
552:
553: config_found(self, &pba, psycho_print);
554: }
555:
556: void
557: psycho_identify_pbm(struct psycho_softc *sc, struct psycho_pbm *pp,
558: struct pcibus_attach_args *pa)
559: {
560: vaddr_t pci_va = (vaddr_t)bus_space_vaddr(sc->sc_bustag, sc->sc_pcictl);
561: paddr_t pci_pa;
562:
563: if (pmap_extract(pmap_kernel(), pci_va, &pci_pa) == 0)
564: pp->pp_id = PSYCHO_PBM_UNKNOWN;
565: else switch(pci_pa & 0xffff) {
566: case 0x2000:
567: pp->pp_id = PSYCHO_PBM_A;
568: break;
569: case 0x4000:
570: pp->pp_id = PSYCHO_PBM_B;
571: break;
572: default:
573: pp->pp_id = PSYCHO_PBM_UNKNOWN;
574: break;
575: }
576: }
577:
578: void
579: psycho_map_psycho(struct psycho_softc* sc, int do_map, bus_addr_t reg_addr,
580: bus_size_t reg_size, bus_addr_t pci_addr, bus_size_t pci_size)
581: {
582: if (do_map) {
583: if (bus_space_map(sc->sc_bustag,
584: reg_addr, reg_size, 0, &sc->sc_regsh))
585: panic("psycho_attach: cannot map regs");
586:
587: if (pci_addr >= reg_addr &&
588: pci_addr + pci_size <= reg_addr + reg_size) {
589: if (bus_space_subregion(sc->sc_bustag, sc->sc_regsh,
590: pci_addr - reg_addr, pci_size, &sc->sc_pcictl))
591: panic("psycho_map_psycho: map ctl");
592: }
593: else if (bus_space_map(sc->sc_bustag, pci_addr, pci_size,
594: 0, &sc->sc_pcictl))
595: panic("psycho_map_psycho: cannot map pci");
596: } else {
597: if (bus_space_map(sc->sc_bustag, reg_addr, reg_size,
598: BUS_SPACE_MAP_PROMADDRESS, &sc->sc_regsh))
599: panic("psycho_map_psycho: cannot map ctl");
600: if (bus_space_map(sc->sc_bustag, pci_addr, pci_size,
601: BUS_SPACE_MAP_PROMADDRESS, &sc->sc_pcictl))
602: panic("psycho_map_psycho: cannot map pci");
603: }
604: }
605:
606: int
607: psycho_print(void *aux, const char *p)
608: {
609: if (p == NULL)
610: return (UNCONF);
611: return (QUIET);
612: }
613:
614: void
615: psycho_set_intr(struct psycho_softc *sc, int ipl, void *handler,
616: u_int64_t *mapper, u_int64_t *clearer, const char *suffix)
617: {
618: struct intrhand *ih;
619:
620: ih = (struct intrhand *)malloc(sizeof(struct intrhand),
621: M_DEVBUF, M_NOWAIT);
622: if (ih == NULL)
623: panic("couldn't malloc intrhand");
624: memset(ih, 0, sizeof(struct intrhand));
625: ih->ih_arg = sc;
626: ih->ih_map = mapper;
627: ih->ih_clr = clearer;
628: ih->ih_fun = handler;
629: ih->ih_pil = (1 << ipl);
630: ih->ih_number = INTVEC(*(ih->ih_map));
631: snprintf(ih->ih_name, sizeof(ih->ih_name),
632: "%s:%s", sc->sc_dev.dv_xname, suffix);
633:
634: DPRINTF(PDB_INTR, (
635: "\ninstalling handler %p arg %p for %s with number %x pil %u",
636: ih->ih_fun, ih->ih_arg, sc->sc_dev.dv_xname, ih->ih_number,
637: ih->ih_pil));
638:
639: intr_establish(ipl, ih);
640: *(ih->ih_map) |= INTMAP_V;
641: }
642:
643: /*
644: * PCI bus support
645: */
646:
647: /*
648: * allocate a PCI chipset tag and set its cookie.
649: */
650: pci_chipset_tag_t
651: psycho_alloc_chipset(struct psycho_pbm *pp, int node, pci_chipset_tag_t pc)
652: {
653: pci_chipset_tag_t npc;
654:
655: npc = malloc(sizeof *npc, M_DEVBUF, M_NOWAIT);
656: if (npc == NULL)
657: panic("could not allocate pci_chipset_tag_t");
658: memcpy(npc, pc, sizeof *pc);
659: npc->cookie = pp;
660: npc->rootnode = node;
661:
662: return (npc);
663: }
664:
665: /*
666: * grovel the OBP for various psycho properties
667: */
668: void
669: psycho_get_bus_range(node, brp)
670: int node;
671: int *brp;
672: {
673: int n, error;
674:
675: error = getprop(node, "bus-range", sizeof(*brp), &n, (void **)&brp);
676: if (error)
677: panic("could not get psycho bus-range, error %d", error);
678: if (n != 2)
679: panic("broken psycho bus-range");
680: DPRINTF(PDB_PROM,
681: ("psycho debug: got `bus-range' for node %08x: %u - %u\n",
682: node, brp[0], brp[1]));
683: }
684:
685: void
686: psycho_get_ranges(int node, struct psycho_ranges **rp, int *np)
687: {
688:
689: if (getprop(node, "ranges", sizeof(**rp), np, (void **)rp))
690: panic("could not get psycho ranges");
691: DPRINTF(PDB_PROM,
692: ("psycho debug: got `ranges' for node %08x: %d entries\n",
693: node, *np));
694: }
695:
696: /*
697: * Interrupt handlers.
698: */
699:
700: int
701: psycho_ue(void *arg)
702: {
703: struct psycho_softc *sc = arg;
704: unsigned long long afsr = psycho_psychoreg_read(sc, psy_ue_afsr);
705: unsigned long long afar = psycho_psychoreg_read(sc, psy_ue_afar);
706:
707: /*
708: * It's uncorrectable. Dump the regs and panic.
709: */
710: panic("%s: uncorrectable DMA error AFAR %llx (pa=%lx tte=%llx/%llx) "
711: "AFSR %llx", sc->sc_dev.dv_xname, afar,
712: iommu_extract(sc->sc_is, (vaddr_t)afar),
713: iommu_lookup_tte(sc->sc_is, (vaddr_t)afar),
714: iommu_fetch_tte(sc->sc_is, (paddr_t)afar),
715: afsr);
716: return (1);
717: }
718:
719: int
720: psycho_ce(void *arg)
721: {
722: struct psycho_softc *sc = arg;
723:
724: /*
725: * It's correctable. Dump the regs and continue.
726: */
727:
728: printf("%s: correctable DMA error AFAR %llx AFSR %llx\n",
729: sc->sc_dev.dv_xname,
730: (long long)psycho_psychoreg_read(sc, psy_ce_afar),
731: (long long)psycho_psychoreg_read(sc, psy_ce_afsr));
732: return (1);
733: }
734:
735: int
736: psycho_bus_error(struct psycho_softc *sc, int bus)
737: {
738: u_int64_t afsr, afar, bits;
739:
740: afar = psycho_psychoreg_read(sc, psy_pcictl[bus].pci_afar);
741: afsr = psycho_psychoreg_read(sc, psy_pcictl[bus].pci_afsr);
742:
743: bits = afsr & (PSY_PCIAFSR_PMA | PSY_PCIAFSR_PTA | PSY_PCIAFSR_PTRY |
744: PSY_PCIAFSR_PPERR | PSY_PCIAFSR_SMA | PSY_PCIAFSR_STA |
745: PSY_PCIAFSR_STRY | PSY_PCIAFSR_SPERR);
746:
747: if (bits == 0)
748: return (0);
749:
750: /*
751: * It's uncorrectable. Dump the regs and panic.
752: */
753: printf("%s: PCI bus %c error AFAR %llx (pa=%llx) AFSR %llx\n",
754: sc->sc_dev.dv_xname, 'A' + bus, (long long)afar,
755: (long long)iommu_extract(sc->sc_is, (vaddr_t)afar),
756: (long long)afsr);
757:
758: psycho_psychoreg_write(sc, psy_pcictl[bus].pci_afsr, bits);
759: return (1);
760: }
761:
762: int
763: psycho_bus_a(void *arg)
764: {
765: struct psycho_softc *sc = arg;
766:
767: return (psycho_bus_error(sc, 0));
768: }
769:
770: int
771: psycho_bus_b(void *arg)
772: {
773: struct psycho_softc *sc = arg;
774:
775: return (psycho_bus_error(sc, 1));
776: }
777:
778: int
779: psycho_powerfail(void *arg)
780: {
781: /*
782: * We lost power. Try to shut down NOW.
783: */
784: printf("Power Failure Detected: Shutting down NOW.\n");
785: boot(RB_POWERDOWN|RB_HALT);
786: return (1);
787: }
788:
789: int
790: psycho_wakeup(void *arg)
791: {
792: struct psycho_softc *sc = arg;
793:
794: /*
795: * Gee, we don't really have a framework to deal with this
796: * properly.
797: */
798: printf("%s: power management wakeup\n", sc->sc_dev.dv_xname);
799: return (1);
800: }
801:
802: /*
803: * initialise the IOMMU..
804: */
805: void
806: psycho_iommu_init(struct psycho_softc *sc, int tsbsize)
807: {
808: struct iommu_state *is = sc->sc_is;
809: int *vdma = NULL, nitem;
810: u_int32_t iobase = -1;
811: char *name;
812:
813: /* punch in our copies */
814: is->is_bustag = sc->sc_bustag;
815: bus_space_subregion(sc->sc_bustag, sc->sc_regsh,
816: offsetof(struct psychoreg, psy_iommu), sizeof(struct iommureg),
817: &is->is_iommu);
818:
819: /*
820: * Separate the men from the boys. If it has a `virtual-dma'
821: * property, use it.
822: */
823: if (!getprop(sc->sc_node, "virtual-dma", sizeof(vdma), &nitem,
824: (void **)&vdma)) {
825: /* Damn. Gotta use these values. */
826: iobase = vdma[0];
827: #define TSBCASE(x) case 1 << ((x) + 23): tsbsize = (x); break
828: switch (vdma[1]) {
829: TSBCASE(1); TSBCASE(2); TSBCASE(3);
830: TSBCASE(4); TSBCASE(5); TSBCASE(6);
831: default:
832: printf("bogus tsb size %x, using 7\n", vdma[1]);
833: TSBCASE(7);
834: }
835: #undef TSBCASE
836: DPRINTF(PDB_CONF, ("psycho_iommu_init: iobase=0x%x\n", iobase));
837: free(vdma, M_DEVBUF);
838: } else {
839: DPRINTF(PDB_CONF, ("psycho_iommu_init: getprop failed, "
840: "iobase=0x%x, tsbsize=%d\n", iobase, tsbsize));
841: }
842:
843: /* give us a nice name.. */
844: name = (char *)malloc(32, M_DEVBUF, M_NOWAIT);
845: if (name == NULL)
846: panic("couldn't malloc iommu name");
847: snprintf(name, 32, "%s dvma", sc->sc_dev.dv_xname);
848:
849: iommu_init(name, is, tsbsize, iobase);
850: }
851:
852: /*
853: * below here is bus space and bus dma support
854: */
855:
856: bus_space_tag_t
857: psycho_alloc_mem_tag(struct psycho_pbm *pp)
858: {
859: return (psycho_alloc_bus_tag(pp, "mem",
860: 0x02, /* 32-bit mem space (where's the #define???) */
861: ASI_PRIMARY, ASI_PRIMARY_LITTLE));
862: }
863:
864: bus_space_tag_t
865: psycho_alloc_io_tag(struct psycho_pbm *pp)
866: {
867: return (psycho_alloc_bus_tag(pp, "io",
868: 0x01, /* IO space (where's the #define???) */
869: ASI_PHYS_NON_CACHED_LITTLE, ASI_PHYS_NON_CACHED));
870: }
871:
872: bus_space_tag_t
873: psycho_alloc_config_tag(struct psycho_pbm *pp)
874: {
875: return (psycho_alloc_bus_tag(pp, "cfg",
876: 0x00, /* Config space (where's the #define???) */
877: ASI_PHYS_NON_CACHED_LITTLE, ASI_PHYS_NON_CACHED));
878: }
879:
880: bus_space_tag_t
881: psycho_alloc_bus_tag(struct psycho_pbm *pp,
882: const char *name, int ss, int asi, int sasi)
883: {
884: struct psycho_softc *sc = pp->pp_sc;
885: struct sparc_bus_space_tag *bt;
886:
887: bt = malloc(sizeof(*bt), M_DEVBUF, M_NOWAIT);
888: if (bt == NULL)
889: panic("could not allocate psycho bus tag");
890:
891: bzero(bt, sizeof *bt);
892:
893: snprintf(bt->name, sizeof(bt->name), "%s-pbm_%s(%d-%2.2x)",
894: sc->sc_dev.dv_xname, name, ss, asi);
895:
896: bt->cookie = pp;
897: bt->parent = sc->sc_bustag;
898: bt->default_type = ss;
899: bt->asi = asi;
900: bt->sasi = sasi;
901: bt->sparc_bus_map = psycho_bus_map;
902: bt->sparc_bus_mmap = psycho_bus_mmap;
903: bt->sparc_bus_addr = psycho_bus_addr;
904: bt->sparc_intr_establish = psycho_intr_establish;
905:
906: return (bt);
907: }
908:
909: bus_dma_tag_t
910: psycho_alloc_dma_tag(struct psycho_pbm *pp)
911: {
912: struct psycho_softc *sc = pp->pp_sc;
913: bus_dma_tag_t dt, pdt = sc->sc_dmatag;
914:
915: dt = (bus_dma_tag_t)malloc(sizeof(struct sparc_bus_dma_tag),
916: M_DEVBUF, M_NOWAIT);
917: if (dt == NULL)
918: panic("could not allocate psycho dma tag");
919:
920: bzero(dt, sizeof *dt);
921: dt->_cookie = pp;
922: dt->_parent = pdt;
923: dt->_dmamap_create = psycho_dmamap_create;
924: dt->_dmamap_destroy = iommu_dvmamap_destroy;
925: dt->_dmamap_load = iommu_dvmamap_load;
926: dt->_dmamap_load_raw = iommu_dvmamap_load_raw;
927: dt->_dmamap_unload = iommu_dvmamap_unload;
928: if (sc->sc_mode == PSYCHO_MODE_PSYCHO)
929: dt->_dmamap_sync = iommu_dvmamap_sync;
930: else
931: dt->_dmamap_sync = psycho_sabre_dvmamap_sync;
932: dt->_dmamem_alloc = iommu_dvmamem_alloc;
933: dt->_dmamem_free = iommu_dvmamem_free;
934: dt->_dmamem_map = iommu_dvmamem_map;
935: dt->_dmamem_unmap = iommu_dvmamem_unmap;
936:
937: return (dt);
938: }
939:
940: /*
941: * bus space support. <sparc64/dev/psychoreg.h> has a discussion about
942: * PCI physical addresses.
943: */
944:
945: int
946: psycho_bus_map(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t offset,
947: bus_size_t size, int flags, bus_space_handle_t *hp)
948: {
949: struct psycho_pbm *pp = t->cookie;
950: int i, ss;
951:
952: DPRINTF(PDB_BUSMAP, ("\npsycho_bus_map: type %d off %qx sz %qx "
953: "flags %d", t->default_type, (unsigned long long)offset,
954: (unsigned long long)size, flags));
955:
956: ss = t->default_type;
957: DPRINTF(PDB_BUSMAP, (" cspace %d", ss));
958:
959: if (t->parent == 0 || t->parent->sparc_bus_map == 0) {
960: printf("\npsycho_bus_map: invalid parent");
961: return (EINVAL);
962: }
963:
964: t = t->parent;
965:
966: if (flags & BUS_SPACE_MAP_PROMADDRESS) {
967: return ((*t->sparc_bus_map)
968: (t, t0, offset, size, flags, hp));
969: }
970:
971: for (i = 0; i < pp->pp_nrange; i++) {
972: bus_addr_t paddr;
973:
974: if (((pp->pp_range[i].cspace >> 24) & 0x03) != ss)
975: continue;
976:
977: paddr = pp->pp_range[i].phys_lo + offset;
978: paddr |= ((bus_addr_t)pp->pp_range[i].phys_hi << 32);
979: DPRINTF(PDB_BUSMAP,
980: ("\n_psycho_bus_map: mapping paddr space %lx offset %lx "
981: "paddr %qx",
982: (long)ss, (long)offset,
983: (unsigned long long)paddr));
984: return ((*t->sparc_bus_map)(t, t0, paddr, size, flags, hp));
985: }
986: DPRINTF(PDB_BUSMAP, (" FAILED\n"));
987: return (EINVAL);
988: }
989:
990: paddr_t
991: psycho_bus_mmap(bus_space_tag_t t, bus_space_tag_t t0, bus_addr_t paddr,
992: off_t off, int prot, int flags)
993: {
994: bus_addr_t offset = paddr;
995: struct psycho_pbm *pp = t->cookie;
996: int i, ss;
997:
998: ss = t->default_type;
999:
1000: DPRINTF(PDB_BUSMAP, ("\n_psycho_bus_mmap: prot %d flags %d pa %qx",
1001: prot, flags, (unsigned long long)paddr));
1002:
1003: if (t->parent == 0 || t->parent->sparc_bus_mmap == 0) {
1004: printf("\npsycho_bus_mmap: invalid parent");
1005: return (-1);
1006: }
1007:
1008: t = t->parent;
1009:
1010: for (i = 0; i < pp->pp_nrange; i++) {
1011: bus_addr_t paddr;
1012:
1013: if (((pp->pp_range[i].cspace >> 24) & 0x03) != ss)
1014: continue;
1015:
1016: paddr = pp->pp_range[i].phys_lo + offset;
1017: paddr |= ((bus_addr_t)pp->pp_range[i].phys_hi << 32);
1018: DPRINTF(PDB_BUSMAP, ("\npsycho_bus_mmap: mapping paddr "
1019: "space %lx offset %lx paddr %qx",
1020: (long)ss, (long)offset,
1021: (unsigned long long)paddr));
1022: return ((*t->sparc_bus_mmap)(t, t0, paddr, off, prot, flags));
1023: }
1024:
1025: return (-1);
1026: }
1027:
1028: bus_addr_t
1029: psycho_bus_addr(bus_space_tag_t t, bus_space_tag_t t0, bus_space_handle_t h)
1030: {
1031: struct psycho_pbm *pp = t->cookie;
1032: bus_addr_t addr;
1033: int i, ss;
1034:
1035: ss = t->default_type;
1036:
1037: if (t->parent == 0 || t->parent->sparc_bus_addr == 0) {
1038: printf("\npsycho_bus_addr: invalid parent");
1039: return (-1);
1040: }
1041:
1042: t = t->parent;
1043:
1044: addr = ((*t->sparc_bus_addr)(t, t0, h));
1045: if (addr == -1)
1046: return (-1);
1047:
1048: for (i = 0; i < pp->pp_nrange; i++) {
1049: if (((pp->pp_range[i].cspace >> 24) & 0x03) != ss)
1050: continue;
1051:
1052: return (BUS_ADDR_PADDR(addr) - pp->pp_range[i].phys_lo);
1053: }
1054:
1055: return (-1);
1056: }
1057:
1058: /*
1059: * Bus-specific interrupt mapping
1060: */
1061: int
1062: psycho_intr_map(struct pci_attach_args *pa, pci_intr_handle_t *ihp)
1063: {
1064: struct psycho_pbm *pp = pa->pa_pc->cookie;
1065: struct psycho_softc *sc = pp->pp_sc;
1066: u_int dev;
1067:
1068: if (*ihp != (pci_intr_handle_t)-1) {
1069: *ihp |= sc->sc_ign;
1070: return (0);
1071: }
1072:
1073: /*
1074: * We didn't find a PROM mapping for this interrupt. Try to
1075: * construct one ourselves based on the swizzled interrupt pin
1076: * and the interrupt mapping for PCI slots documented in the
1077: * UltraSPARC-IIi User's Manual.
1078: */
1079:
1080: if (pa->pa_intrpin == 0)
1081: return (-1);
1082:
1083: /*
1084: * This deserves some documentation. Should anyone
1085: * have anything official looking, please speak up.
1086: */
1087: if (sc->sc_mode == PSYCHO_MODE_PSYCHO &&
1088: pp->pp_id == PSYCHO_PBM_B)
1089: dev = PCITAG_DEV(pa->pa_intrtag) - 2;
1090: else
1091: dev = PCITAG_DEV(pa->pa_intrtag) - 1;
1092:
1093: *ihp = (pa->pa_intrpin - 1) & INTMAP_PCIINT;
1094: *ihp |= ((pp->pp_id == PSYCHO_PBM_B) ? INTMAP_PCIBUS : 0);
1095: *ihp |= (dev << 2) & INTMAP_PCISLOT;
1096: *ihp |= sc->sc_ign;
1097:
1098: return (0);
1099: }
1100:
1101: /*
1102: * install an interrupt handler for a PCI device
1103: */
1104: void *
1105: psycho_intr_establish(bus_space_tag_t t, bus_space_tag_t t0, int ihandle,
1106: int level, int flags, int (*handler)(void *), void *arg, const char *what)
1107: {
1108: struct psycho_pbm *pp = t->cookie;
1109: struct psycho_softc *sc = pp->pp_sc;
1110: struct intrhand *ih;
1111: volatile u_int64_t *intrmapptr = NULL, *intrclrptr = NULL;
1112: int64_t intrmap = 0;
1113: int ino;
1114: long vec = INTVEC(ihandle);
1115:
1116: /*
1117: * Hunt through all the interrupt mapping regs to look for our
1118: * interrupt vector.
1119: *
1120: * XXX We only compare INOs rather than IGNs since the firmware may
1121: * not provide the IGN and the IGN is constant for all device on that
1122: * PCI controller. This could cause problems for the FFB/external
1123: * interrupt which has a full vector that can be set arbitrarily.
1124: */
1125:
1126: DPRINTF(PDB_INTR,
1127: ("\npsycho_intr_establish: ihandle %x vec %lx", ihandle, vec));
1128: ino = INTINO(vec);
1129: DPRINTF(PDB_INTR, (" ino %x", ino));
1130:
1131: /* If the device didn't ask for an IPL, use the one encoded. */
1132: if (level == IPL_NONE)
1133: level = INTLEV(vec);
1134: /* If it still has no level, print a warning and assign IPL 2 */
1135: if (level == IPL_NONE) {
1136: printf("ERROR: no IPL, setting IPL 2.\n");
1137: level = 2;
1138: }
1139:
1140: if (flags & BUS_INTR_ESTABLISH_SOFTINTR)
1141: goto found;
1142:
1143: DPRINTF(PDB_INTR,
1144: ("\npsycho: intr %lx: %p\nHunting for IRQ...\n",
1145: (long)ino, intrlev[ino]));
1146:
1147: /*
1148: * First look for PCI interrupts, otherwise the PCI A slot 0
1149: * INTA# interrupt might match an unused non-PCI (obio)
1150: * interrupt.
1151: */
1152:
1153: for (intrmapptr = psycho_psychoreg_vaddr(sc, pcia_slot0_int),
1154: intrclrptr = psycho_psychoreg_vaddr(sc, pcia0_clr_int[0]);
1155: intrmapptr <= (volatile u_int64_t *)
1156: psycho_psychoreg_vaddr(sc, pcib_slot3_int);
1157: intrmapptr++, intrclrptr += 4) {
1158: /* Skip PCI-A Slot 2 and PCI-A Slot 3 on psycho's */
1159: if (sc->sc_mode == PSYCHO_MODE_PSYCHO &&
1160: (intrmapptr ==
1161: psycho_psychoreg_vaddr(sc, pcia_slot2_int) ||
1162: intrmapptr ==
1163: psycho_psychoreg_vaddr(sc, pcia_slot3_int)))
1164: continue;
1165:
1166: if (((*intrmapptr ^ vec) & 0x3c) == 0) {
1167: intrclrptr += vec & 0x3;
1168: goto found;
1169: }
1170: }
1171:
1172: /* Now hunt through obio. */
1173: for (intrmapptr = psycho_psychoreg_vaddr(sc, scsi_int_map),
1174: intrclrptr = psycho_psychoreg_vaddr(sc, scsi_clr_int);
1175: intrmapptr < (volatile u_int64_t *)
1176: psycho_psychoreg_vaddr(sc, ffb0_int_map);
1177: intrmapptr++, intrclrptr++) {
1178: if (INTINO(*intrmapptr) == ino)
1179: goto found;
1180: }
1181:
1182: printf("Cannot find interrupt vector %lx\n", vec);
1183: return (NULL);
1184:
1185: found:
1186: ih = bus_intr_allocate(t0, handler, arg, ino | sc->sc_ign, level,
1187: intrmapptr, intrclrptr, what);
1188: if (ih == NULL) {
1189: printf("Cannot allocate interrupt vector %lx\n", vec);
1190: return (NULL);
1191: }
1192:
1193: DPRINTF(PDB_INTR, (
1194: "\ninstalling handler %p arg %p with number %x pil %u",
1195: ih->ih_fun, ih->ih_arg, ih->ih_number, ih->ih_pil));
1196:
1197: intr_establish(ih->ih_pil, ih);
1198:
1199: /*
1200: * Enable the interrupt now we have the handler installed.
1201: * Read the current value as we can't change it besides the
1202: * valid bit so so make sure only this bit is changed.
1203: *
1204: * XXXX --- we really should use bus_space for this.
1205: */
1206: if (intrmapptr) {
1207: intrmap = *intrmapptr;
1208: DPRINTF(PDB_INTR, ("; read intrmap = %016qx",
1209: (unsigned long long)intrmap));
1210:
1211: /* Enable the interrupt */
1212: intrmap |= INTMAP_V;
1213: DPRINTF(PDB_INTR, ("; addr of intrmapptr = %p", intrmapptr));
1214: DPRINTF(PDB_INTR, ("; writing intrmap = %016qx",
1215: (unsigned long long)intrmap));
1216: *intrmapptr = intrmap;
1217: DPRINTF(PDB_INTR, ("; reread intrmap = %016qx",
1218: (unsigned long long)(intrmap = *intrmapptr)));
1219: }
1220: return (ih);
1221: }
1222:
1223: /*
1224: * hooks into the iommu dvma calls.
1225: */
1226: int
1227: psycho_dmamap_create(bus_dma_tag_t t, bus_dma_tag_t t0, bus_size_t size,
1228: int nsegments, bus_size_t maxsegsz, bus_size_t boundary, int flags,
1229: bus_dmamap_t *dmamp)
1230: {
1231: struct psycho_pbm *pp = t->_cookie;
1232:
1233: return (iommu_dvmamap_create(t, t0, &pp->pp_sb, size, nsegments,
1234: maxsegsz, boundary, flags, dmamp));
1235: }
1236:
1237: void
1238: psycho_sabre_dvmamap_sync(bus_dma_tag_t t, bus_dma_tag_t t0, bus_dmamap_t map,
1239: bus_size_t offset, bus_size_t len, int ops)
1240: {
1241: struct psycho_pbm *pp = t->_cookie;
1242: struct psycho_softc *sc = pp->pp_sc;
1243:
1244: if (ops & BUS_DMASYNC_POSTREAD)
1245: psycho_psychoreg_read(sc, pci_dma_write_sync);
1246:
1247: if (ops & (BUS_DMASYNC_POSTREAD | BUS_DMASYNC_PREWRITE))
1248: membar(MemIssue);
1249: }
1250:
CVSweb