Annotation of sys/arch/macppc/pci/mpcpcibus.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: mpcpcibus.c,v 1.36 2006/12/14 17:36:12 kettenis Exp $ */
2:
3: /*
4: * Copyright (c) 1997 Per Fogelstrom
5: *
6: * Redistribution and use in source and binary forms, with or without
7: * modification, are permitted provided that the following conditions
8: * are met:
9: * 1. Redistributions of source code must retain the above copyright
10: * notice, this list of conditions and the following disclaimer.
11: * 2. Redistributions in binary form must reproduce the above copyright
12: * notice, this list of conditions and the following disclaimer in the
13: * documentation and/or other materials provided with the distribution.
14: *
15: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
16: * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
19: * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25: * SUCH DAMAGE.
26: *
27: */
28:
29: /*
30: * Generic PCI BUS Bridge driver.
31: * specialized hooks for different config methods.
32: */
33:
34: #include <sys/param.h>
35: #include <sys/systm.h>
36: #include <sys/kernel.h>
37: #include <sys/malloc.h>
38: #include <sys/device.h>
39: #include <sys/proc.h>
40: #include <uvm/uvm_extern.h>
41:
42: #include <machine/autoconf.h>
43: #include <machine/pcb.h>
44: #include <machine/bat.h>
45: #include <machine/powerpc.h>
46:
47: #include <dev/pci/pcireg.h>
48: #include <dev/pci/pcivar.h>
49: #include <dev/pci/pcidevs.h>
50:
51: #include <macppc/pci/pcibrvar.h>
52: #include <macppc/pci/mpc106reg.h>
53:
54: #include <dev/ofw/openfirm.h>
55:
56: int mpcpcibrmatch(struct device *, void *, void *);
57: void mpcpcibrattach(struct device *, struct device *, void *);
58:
59: void mpc_attach_hook(struct device *, struct device *,
60: struct pcibus_attach_args *);
61: int mpc_bus_maxdevs(void *, int);
62: pcitag_t mpc_make_tag(void *, int, int, int);
63: void mpc_decompose_tag(void *, pcitag_t, int *, int *, int *);
64: pcireg_t mpc_conf_read(void *, pcitag_t, int);
65: void mpc_conf_write(void *, pcitag_t, int, pcireg_t);
66:
67: int mpc_intr_map(void *, pcitag_t, int, int, pci_intr_handle_t *);
68: const char *mpc_intr_string(void *, pci_intr_handle_t);
69: int mpc_intr_line(void *, pci_intr_handle_t);
70: void *mpc_intr_establish(void *, pci_intr_handle_t,
71: int, int (*func)(void *), void *, char *);
72: void mpc_intr_disestablish(void *, void *);
73: int mpc_ether_hw_addr(struct ppc_pci_chipset *, u_int8_t *);
74: u_int32_t mpc_gen_config_reg(void *cpv, pcitag_t tag, int offset);
75: int of_ether_hw_addr(struct ppc_pci_chipset *, u_int8_t *);
76: int find_node_intr (int parent, u_int32_t *addr, u_int32_t *intr);
77: u_int32_t pci_iack(void);
78:
79: void fix_node_irq(int node, struct pcibus_attach_args *pba);
80:
81: struct cfattach mpcpcibr_ca = {
82: sizeof(struct pcibr_softc), mpcpcibrmatch, mpcpcibrattach,
83: };
84:
85: struct cfdriver mpcpcibr_cd = {
86: NULL, "mpcpcibr", DV_DULL,
87: };
88:
89: static int mpcpcibrprint(void *, const char *pnp);
90:
91: struct pcibr_config mpc_config;
92:
93: /*
94: * config types
95: * bit meanings
96: * 0 - standard cf8/cfc type configurations,
97: * sometimes the base addresses for these are different
98: * 1 - Config Method #2 configuration - uni-north
99: *
100: * 2 - 64 bit config bus, data for accesses &4 is at daddr+4;
101: */
102: struct config_type{
103: char * compat;
104: u_int32_t addr; /* offset */
105: u_int32_t data; /* offset */
106: int config_type;
107: };
108: struct config_type config_offsets[] = {
109: {"grackle", 0x00c00cf8, 0x00e00cfc, 0 },
110: {"bandit", 0x00800000, 0x00c00000, 1 },
111: {"uni-north", 0x00800000, 0x00c00000, 3 },
112: {"u3-agp", 0x00800000, 0x00c00000, 3 },
113: {"u3-ht", 0x00000cf8, 0x00000cfc, 3 },
114: {"legacy", 0x00000cf8, 0x00000cfc, 0 },
115: {"IBM,27-82660", 0x00000cf8, 0x00000cfc, 0 },
116: {NULL, 0x00000000, 0x00000000, 0 },
117: };
118:
119: struct powerpc_bus_dma_tag pci_bus_dma_tag = {
120: NULL,
121: _dmamap_create,
122: _dmamap_destroy,
123: _dmamap_load,
124: _dmamap_load_mbuf,
125: _dmamap_load_uio,
126: _dmamap_load_raw,
127: _dmamap_unload,
128: _dmamap_sync,
129: _dmamem_alloc,
130: _dmamem_free,
131: _dmamem_map,
132: _dmamem_unmap,
133: _dmamem_mmap
134: };
135:
136: int
137: mpcpcibrmatch(struct device *parent, void *match, void *aux)
138: {
139: struct confargs *ca = aux;
140: int found = 0;
141:
142: if (strcmp(ca->ca_name, mpcpcibr_cd.cd_name) != 0)
143: return (found);
144:
145: found = 1;
146:
147: return found;
148: }
149:
150: int pci_map_a = 0;
151:
152: struct ranges_32 {
153: u_int32_t flags;
154: u_int32_t pad1;
155: u_int32_t pad2;
156: u_int32_t base;
157: u_int32_t pad3;
158: u_int32_t size;
159: };
160: void
161: mpcpcibus_find_ranges_32 (struct pcibr_softc *sc, u_int32_t *range_store,
162: int rangesize);
163: void
164: mpcpcibus_find_ranges_64 (struct pcibr_softc *sc, u_int32_t *range_store,
165: int rangesize);
166: void
167: mpcpcibus_find_ranges_32 (struct pcibr_softc *sc, u_int32_t *range_store,
168: int rangesize)
169: {
170: int found;
171: unsigned int base = 0;
172: unsigned int size = 0;
173: struct ranges_32 *prange = (void *)range_store;
174: int rangelen;
175: int i;
176:
177: rangelen = rangesize / sizeof (struct ranges_32);
178:
179: /* mac configs */
180: sc->sc_membus_space.bus_base = 0;
181: sc->sc_membus_space.bus_io = 0;
182: sc->sc_iobus_space.bus_base = 0;
183: sc->sc_iobus_space.bus_io = 1;
184:
185: /* find io(config) base, flag == 0x01000000 */
186: found = 0;
187: for (i = 0; i < rangelen ; i++) {
188: if (prange[i].flags == 0x01000000) {
189: /* find last? */
190: found = i;
191: }
192: }
193: /* found the io space ranges */
194: if (prange[found].flags == 0x01000000) {
195: sc->sc_iobus_space.bus_base =
196: prange[found].base;
197: sc->sc_iobus_space.bus_size =
198: prange[found].size;
199: }
200:
201: /* the mem space ranges
202: * apple openfirmware always puts full
203: * addresses in config information,
204: * it is not necessary to have correct bus
205: * base address, but since 0 is reserved
206: * and all IO and device memory will be in
207: * upper 2G of address space, set to
208: * 0x80000000
209: * start with segment 1 not 0, 0 is config.
210: */
211: for (i = 0; i < rangelen ; i++) {
212: if (prange[i].flags == 0x02000000) {
213: #ifdef DEBUG_PCI
214: printf("\nfound mem %x %x",
215: prange[i].base,
216: prange[i].size);
217: #endif
218: if (base != 0) {
219: if ((base + size) == prange[i].base)
220: size += prange[i].size;
221: else {
222: size = prange[i].size;
223: base = prange[i].base;
224: }
225: } else {
226: base = prange[i].base;
227: size = prange[i].size;
228: }
229: }
230: }
231: sc->sc_membus_space.bus_base = base;
232: sc->sc_membus_space.bus_size = size;
233: }
234:
235: struct ranges_64 {
236: u_int32_t flags;
237: u_int32_t pad1;
238: u_int32_t pad2;
239: u_int32_t pad3;
240: u_int32_t base;
241: u_int32_t pad4;
242: u_int32_t size;
243: };
244: void
245: mpcpcibus_find_ranges_64 (struct pcibr_softc *sc, u_int32_t *range_store,
246: int rangesize)
247: {
248: int i, found;
249: unsigned int base = 0;
250: unsigned int size = 0;
251: int rangelen;
252: struct ranges_64 *prange = (void *)range_store;
253:
254: rangelen = rangesize / sizeof (struct ranges_64);
255:
256: /* mac configs */
257:
258: sc->sc_membus_space.bus_base = 0;
259: sc->sc_membus_space.bus_io = 0;
260: sc->sc_iobus_space.bus_base = 0;
261: sc->sc_iobus_space.bus_io = 1;
262:
263: if (prange[0].flags == 0xabb10113) { /* appl U3; */
264: prange[0].flags = 0x01000000;
265: prange[0].base = 0xf8070000;
266: prange[0].size = 0x00001000;
267: prange[1].flags = 0x02000000;
268: prange[1].base = 0xf2000000;
269: prange[1].size = 0x02800000;
270: rangelen = 2;
271: }
272:
273: /* find io(config) base, flag == 0x01000000 */
274: found = 0;
275: for (i = 0; i < rangelen ; i++) {
276: if (prange[i].flags == 0x01000000) {
277: /* find last? */
278: found = i;
279: }
280: }
281: /* found the io space ranges */
282: if (prange[found].flags == 0x01000000) {
283: sc->sc_iobus_space.bus_base = prange[found].base;
284: sc->sc_iobus_space.bus_size = prange[found].size;
285: }
286:
287: /* the mem space ranges
288: * apple openfirmware always puts full
289: * addresses in config information,
290: * it is not necessary to have correct bus
291: * base address, but since 0 is reserved
292: * and all IO and device memory will be in
293: * upper 2G of address space, set to
294: * 0x80000000
295: * start with segment 1 not 0, 0 is config.
296: */
297: for (i = 0; i < rangelen ; i++) {
298: if (prange[i].flags == 0x02000000) {
299: #ifdef DEBUG_PCI
300: printf("\nfound mem %x %x",
301: prange[i].base,
302: prange[i].size);
303: #endif
304:
305: if (base != 0) {
306: if ((base + size) == prange[i].base) {
307: size += prange[i].size;
308: } else {
309: base = prange[i].base;
310: size = prange[i].size;
311: }
312: } else {
313: base = prange[i].base;
314: size = prange[i].size;
315: }
316: }
317: }
318: sc->sc_membus_space.bus_base = base;
319: sc->sc_membus_space.bus_size = size;
320: }
321:
322: void
323: mpcpcibrattach(struct device *parent, struct device *self, void *aux)
324: {
325: struct pcibr_softc *sc = (struct pcibr_softc *)self;
326: struct confargs *ca = aux;
327: struct pcibr_config *lcp;
328: struct pcibus_attach_args pba;
329: int node;
330: int of_node = 0;
331: char compat[32];
332: u_int32_t addr_offset;
333: u_int32_t data_offset;
334: int i;
335: int len;
336: int rangesize;
337: u_int32_t range_store[32];
338:
339: if (ca->ca_node == 0) {
340: printf("invalid node on mpcpcibr config\n");
341: return;
342: }
343: len=OF_getprop(ca->ca_node, "name", compat, sizeof (compat));
344: compat[len] = '\0';
345: if (len > 0)
346: printf(" %s", compat);
347:
348: len=OF_getprop(ca->ca_node, "compatible", compat,
349: sizeof (compat));
350: if (len <= 0 ) {
351: len=OF_getprop(ca->ca_node, "name", compat,
352: sizeof (compat));
353: if (len <= 0) {
354: printf(" compatible and name not found\n");
355: return;
356: }
357: compat[len] = 0;
358: if (strcmp (compat, "bandit") != 0) {
359: printf(" compatible not found and name %s found\n",
360: compat);
361: return;
362: }
363: }
364: compat[len] = 0;
365: if ((rangesize = OF_getprop(ca->ca_node, "ranges",
366: range_store, sizeof (range_store))) <= 0) {
367: if (strcmp(compat, "u3-ht") == 0) {
368: range_store[0] = 0xabb10113; /* appl U3; */
369: } else
370: printf("range lookup failed, node %x\n", ca->ca_node);
371: }
372: /* translate byte(s) into item count*/
373:
374: lcp = sc->sc_pcibr = &sc->pcibr_config;
375:
376: if (ppc_proc_is_64b)
377: mpcpcibus_find_ranges_64 (sc, range_store, rangesize);
378: else
379: mpcpcibus_find_ranges_32 (sc, range_store, rangesize);
380:
381: addr_offset = 0;
382: for (i = 0; config_offsets[i].compat != NULL; i++) {
383: struct config_type *co = &config_offsets[i];
384: if (strcmp(co->compat, compat) == 0) {
385: addr_offset = co->addr;
386: data_offset = co->data;
387: lcp->config_type = co->config_type;
388: break;
389: }
390: }
391: if (addr_offset == 0) {
392: printf("unable to find match for"
393: " compatible %s\n", compat);
394: return;
395: }
396: #ifdef DEBUG_FIXUP
397: printf(" mem base %x sz %x io base %x sz %x\n"
398: " config addr %x config data %x\n",
399: sc->sc_membus_space.bus_base,
400: sc->sc_membus_space.bus_size,
401: sc->sc_iobus_space.bus_base,
402: sc->sc_iobus_space.bus_size,
403: addr_offset, data_offset);
404: #endif
405:
406: if ( bus_space_map(&(sc->sc_iobus_space), addr_offset,
407: NBPG, 0, &lcp->ioh_cf8) != 0 )
408: panic("mpcpcibus: unable to map self");
409:
410: if ( bus_space_map(&(sc->sc_iobus_space), data_offset,
411: NBPG, 0, &lcp->ioh_cfc) != 0 )
412: panic("mpcpcibus: unable to map self");
413:
414: of_node = ca->ca_node;
415:
416: lcp->node = ca->ca_node;
417: lcp->lc_pc.pc_conf_v = lcp;
418: lcp->lc_pc.pc_attach_hook = mpc_attach_hook;
419: lcp->lc_pc.pc_bus_maxdevs = mpc_bus_maxdevs;
420: lcp->lc_pc.pc_make_tag = mpc_make_tag;
421: lcp->lc_pc.pc_decompose_tag = mpc_decompose_tag;
422: lcp->lc_pc.pc_conf_read = mpc_conf_read;
423: lcp->lc_pc.pc_conf_write = mpc_conf_write;
424: lcp->lc_pc.pc_ether_hw_addr = of_ether_hw_addr;
425: lcp->lc_iot = &sc->sc_iobus_space;
426: lcp->lc_memt = &sc->sc_membus_space;
427:
428: lcp->lc_pc.pc_intr_v = lcp;
429: lcp->lc_pc.pc_intr_map = mpc_intr_map;
430: lcp->lc_pc.pc_intr_string = mpc_intr_string;
431: lcp->lc_pc.pc_intr_line = mpc_intr_line;
432: lcp->lc_pc.pc_intr_establish = mpc_intr_establish;
433: lcp->lc_pc.pc_intr_disestablish = mpc_intr_disestablish;
434:
435: printf(": %s, Revision 0x%x\n", compat,
436: mpc_cfg_read_1(lcp, MPC106_PCI_REVID));
437:
438: if ((strcmp(compat, "bandit")) != 0)
439: pci_addr_fixup(sc, &lcp->lc_pc, 32);
440:
441: pba.pba_dmat = &pci_bus_dma_tag;
442:
443: pba.pba_busname = "pci";
444: pba.pba_iot = &sc->sc_iobus_space;
445: pba.pba_memt = &sc->sc_membus_space;
446: pba.pba_pc = &lcp->lc_pc;
447: pba.pba_domain = pci_ndomains++;
448: pba.pba_bus = 0;
449: pba.pba_bridgetag = NULL;
450:
451: /* we want to check pci irq settings */
452: if (of_node != 0) {
453: int nn;
454:
455: for (node = OF_child(of_node); node; node = nn) {
456: char name[32];
457: int len;
458: len = OF_getprop(node, "name", name,
459: sizeof(name));
460: name[len] = 0;
461: fix_node_irq(node, &pba);
462:
463: /* iterate section */
464: if ((nn = OF_child(node)) != 0)
465: continue;
466:
467: while ((nn = OF_peer(node)) == 0) {
468: node = OF_parent(node);
469: if (node == of_node) {
470: nn = 0; /* done */
471: break;
472: }
473: }
474: }
475: }
476:
477: config_found(self, &pba, mpcpcibrprint);
478:
479: }
480:
481: #define OFW_PCI_PHYS_HI_BUSMASK 0x00ff0000
482: #define OFW_PCI_PHYS_HI_BUSSHIFT 16
483: #define OFW_PCI_PHYS_HI_DEVICEMASK 0x0000f800
484: #define OFW_PCI_PHYS_HI_DEVICESHIFT 11
485: #define OFW_PCI_PHYS_HI_FUNCTIONMASK 0x00000700
486: #define OFW_PCI_PHYS_HI_FUNCTIONSHIFT 8
487:
488: #define pcibus(x) \
489: (((x) & OFW_PCI_PHYS_HI_BUSMASK) >> OFW_PCI_PHYS_HI_BUSSHIFT)
490: #define pcidev(x) \
491: (((x) & OFW_PCI_PHYS_HI_DEVICEMASK) >> OFW_PCI_PHYS_HI_DEVICESHIFT)
492: #define pcifunc(x) \
493: (((x) & OFW_PCI_PHYS_HI_FUNCTIONMASK) >> OFW_PCI_PHYS_HI_FUNCTIONSHIFT)
494:
495: /*
496: * Find PCI IRQ from OF.
497: */
498: int
499: find_node_intr(int parent, u_int32_t *addr, u_int32_t *intr)
500: {
501: int iparent, len, mlen, alen, ilen;
502: int match, i, step;
503: u_int32_t map[144], *mp, *mp1;
504: u_int32_t imask[8], maskedaddr[8];
505: u_int32_t address_cells, interrupt_cells, mask_cells;
506:
507: len = OF_getprop(parent, "interrupt-map", map, sizeof(map));
508: mlen = OF_getprop(parent, "interrupt-map-mask", imask, sizeof(imask));
509: alen = OF_getprop(parent, "#address-cells",
510: &address_cells, sizeof(address_cells));
511: ilen = OF_getprop(parent, "#interrupt-cells",
512: &interrupt_cells, sizeof(interrupt_cells));
513:
514: if (len == -1 || mlen == -1 || alen == -1 || ilen == -1)
515: goto nomap;
516:
517: mask_cells = address_cells + interrupt_cells;
518: if (mask_cells != (mlen / sizeof(u_int32_t)))
519: goto nomap;
520: for (i = 0; i < mask_cells; i++)
521: maskedaddr[i] = addr[i] & imask[i];
522:
523: /* interrupt-map is formatted as follows
524: * int * #address-cells, int * #interrupt-cells, int, int, int
525: * eg
526: * address-cells = 3
527: * interrupt-cells = 1
528: * 00001000 00000000 00000000 00000000 ff911258 00000034 00000001
529: * 00001800 00000000 00000000 00000000 ff911258 00000035 00000001
530: * 00002000 00000000 00000000 00000000 ff911258 00000036 00000001
531: * | address cells | | intr | |parent| | irq | |edge/level|
532: * | cells| | interrupt cells |
533: * | of parent |
534: * or at least something close to that.
535: */
536:
537: mp = map;
538: while (len > mlen) {
539: mp1 = mp + mask_cells;
540:
541: iparent = *mp1;
542: alen = OF_getprop(iparent, "#address-cells",
543: &address_cells, sizeof(address_cells));
544: if (alen == -1)
545: address_cells = 0;
546: ilen = OF_getprop(iparent, "#interrupt-cells",
547: &interrupt_cells, sizeof(interrupt_cells));
548: if (ilen == -1)
549: goto nomap;
550:
551: step = mask_cells + 1 + address_cells + interrupt_cells;
552:
553: match = bcmp(maskedaddr, mp, mlen);
554: if (match == 0) {
555: if (OF_getprop(iparent, "interrupt-controller",
556: NULL, 0) == 0) {
557: *intr = mp1[1];
558: return 1;
559: }
560: /* Recurse with new 'addr'. */
561: return find_node_intr(iparent, &mp1[1], intr);
562: }
563: len -= step * sizeof(u_int32_t);
564: mp += step;
565: }
566: nomap:
567: return -1;
568: }
569:
570: void
571: fix_node_irq(int node, struct pcibus_attach_args *pba)
572: {
573: struct {
574: u_int32_t phys_hi, phys_mid, phys_lo;
575: u_int32_t size_hi, size_lo;
576: } addr [8];
577: u_int32_t map[144];
578: int len;
579: pcitag_t tag;
580: u_int32_t irq;
581: u_int32_t intr;
582: int parent;
583:
584: pci_chipset_tag_t pc = pba->pba_pc;
585:
586: len = OF_getprop(node, "assigned-addresses", addr, sizeof(addr));
587: if (len == -1 || len < sizeof(addr[0]))
588: return;
589:
590: /* if this node has a AAPL,interrupts property, firmware
591: * has initialized the register correctly.
592: */
593: len = OF_getprop(node, "AAPL,interrupts", &intr, 4);
594: if (len != 4) {
595:
596: parent = OF_parent(node);
597:
598: irq = -1;
599:
600: /* we want the first interrupt, set size_hi to 1 */
601: addr[0].size_hi = 1;
602: if (find_node_intr(parent, &addr[0].phys_hi, &irq) == -1) {
603: len = OF_getprop(node, "interrupts", map,
604: sizeof(map));
605: if (len != -1 && len != 4) {
606: irq = map[0];
607: } else
608: return;
609: }
610: } else
611: irq = intr;
612: /* program the interrupt line register with the value
613: * found in openfirmware
614: */
615:
616: tag = pci_make_tag(pc, pcibus(addr[0].phys_hi),
617: pcidev(addr[0].phys_hi), pcifunc(addr[0].phys_hi));
618:
619: intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
620: intr &= ~PCI_INTERRUPT_LINE_MASK;
621: intr |= irq & PCI_INTERRUPT_LINE_MASK;
622: pci_conf_write(pc, tag, PCI_INTERRUPT_REG, intr);
623: }
624:
625: static int
626: mpcpcibrprint(void *aux, const char *pnp)
627: {
628: struct pcibus_attach_args *pba = aux;
629:
630: if (pnp)
631: printf("%s at %s", pba->pba_busname, pnp);
632: printf(" bus %d", pba->pba_bus);
633: return(UNCONF);
634: }
635:
636: void
637: mpc_attach_hook(struct device *parent, struct device *self,
638: struct pcibus_attach_args *pba)
639: {
640: }
641:
642: int
643: of_ether_hw_addr(struct ppc_pci_chipset *lcpc, u_int8_t *oaddr)
644: {
645: u_int8_t laddr[6];
646: struct pcibr_config *lcp = lcpc->pc_conf_v;
647: int of_node = lcp->node;
648: int node, nn;
649: for (node = OF_child(of_node); node; node = nn) {
650: char name[32];
651: int len;
652: len = OF_getprop(node, "name", name,
653: sizeof(name));
654: name[len] = 0;
655:
656: len = OF_getprop(node, "local-mac-address", laddr,
657: sizeof laddr);
658: if (sizeof (laddr) == len) {
659: bcopy (laddr, oaddr, sizeof laddr);
660: return 1;
661: }
662:
663: /* iterate section */
664: if ((nn = OF_child(node)) != 0) {
665: continue;
666: }
667: while ((nn = OF_peer(node)) == 0) {
668: node = OF_parent(node);
669: if (node == of_node) {
670: nn = 0; /* done */
671: break;
672: }
673: }
674: }
675: oaddr[0] = oaddr[1] = oaddr[2] = 0xff;
676: oaddr[3] = oaddr[4] = oaddr[5] = 0xff;
677: return 0;
678: }
679:
680: int
681: mpc_ether_hw_addr(struct ppc_pci_chipset *p, u_int8_t *s)
682: {
683: printf("mpc_ether_hw_addr not supported\n");
684: return(0);
685: }
686:
687: int
688: mpc_bus_maxdevs(void *cpv, int busno)
689: {
690: return(32);
691: }
692:
693: #define BUS_SHIFT 16
694: #define DEVICE_SHIFT 11
695: #define FNC_SHIFT 8
696:
697: pcitag_t
698: mpc_make_tag(void *cpv, int bus, int dev, int fnc)
699: {
700: return (bus << BUS_SHIFT) | (dev << DEVICE_SHIFT) | (fnc << FNC_SHIFT);
701: }
702:
703: void
704: mpc_decompose_tag(void *cpv, pcitag_t tag, int *busp, int *devp, int *fncp)
705: {
706: if (busp != NULL)
707: *busp = (tag >> BUS_SHIFT) & 0xff;
708: if (devp != NULL)
709: *devp = (tag >> DEVICE_SHIFT) & 0x1f;
710: if (fncp != NULL)
711: *fncp = (tag >> FNC_SHIFT) & 0x7;
712: }
713:
714: u_int32_t
715: mpc_gen_config_reg(void *cpv, pcitag_t tag, int offset)
716: {
717: struct pcibr_config *cp = cpv;
718: unsigned int bus, dev, fcn;
719: u_int32_t reg;
720:
721: mpc_decompose_tag(cpv, tag, &bus, &dev, &fcn);
722:
723: if (cp->config_type & 1) {
724: /* Config Mechanism #2 */
725: if (bus == 0) {
726: if (dev < 11)
727: return 0xffffffff;
728: /*
729: * Need to do config type 0 operation
730: * 1 << (11?+dev) | fcn << 8 | reg
731: * 11? is because pci spec states
732: * that 11-15 is reserved.
733: */
734: reg = 1 << (dev) | fcn << 8 | offset;
735:
736: } else {
737: if (dev > 15)
738: return 0xffffffff;
739: /*
740: * config type 1
741: */
742: reg = tag | offset | 1;
743: }
744: } else {
745: /* config mechanism #2, type 0
746: * standard cf8/cfc config
747: */
748: reg = 0x80000000 | tag | offset;
749: }
750:
751: return reg;
752: }
753:
754: /* #define DEBUG_CONFIG */
755: pcireg_t
756: mpc_conf_read(void *cpv, pcitag_t tag, int offset)
757: {
758: struct pcibr_config *cp = cpv;
759: pcireg_t data;
760: u_int32_t reg;
761: int s;
762: int daddr = 0;
763: faultbuf env;
764: void *oldh;
765:
766: if (offset & 3 || offset < 0 || offset >= 0x100) {
767: #ifdef DEBUG_CONFIG
768: printf ("pci_conf_read: bad reg %x\n", offset);
769: #endif /* DEBUG_CONFIG */
770: return(~0);
771: }
772:
773: reg = mpc_gen_config_reg(cpv, tag, offset);
774: /* if invalid tag, return -1 */
775: if (reg == 0xffffffff)
776: return(~0);
777:
778: if ((cp->config_type & 2) && (offset & 0x04))
779: daddr += 4;
780:
781: s = splhigh();
782:
783: oldh = curpcb->pcb_onfault;
784: if (setfault(&env)) {
785: /* we faulted during the read? */
786: curpcb->pcb_onfault = oldh;
787: splx(s);
788: return 0xffffffff;
789: }
790:
791: bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, reg);
792: bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
793: data = bus_space_read_4(cp->lc_iot, cp->ioh_cfc, daddr);
794: bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, 0); /* disable */
795: bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
796:
797: curpcb->pcb_onfault = oldh;
798:
799: splx(s);
800: #ifdef DEBUG_CONFIG
801: if (!((offset == 0) && (data == 0xffffffff))) {
802: unsigned int bus, dev, fcn;
803: mpc_decompose_tag(cpv, tag, &bus, &dev, &fcn);
804: printf("mpc_conf_read bus %x dev %x fcn %x offset %x", bus, dev, fcn,
805: offset);
806: printf(" daddr %x reg %x",daddr, reg);
807: printf(" data %x\n", data);
808: }
809: #endif
810:
811: return(data);
812: }
813:
814: void
815: mpc_conf_write(void *cpv, pcitag_t tag, int offset, pcireg_t data)
816: {
817: struct pcibr_config *cp = cpv;
818: u_int32_t reg;
819: int s;
820: int daddr = 0;
821:
822: reg = mpc_gen_config_reg(cpv, tag, offset);
823:
824: /* if invalid tag, return ??? */
825: if (reg == 0xffffffff)
826: return;
827:
828: if ((cp->config_type & 2) && (offset & 0x04))
829: daddr += 4;
830:
831: #ifdef DEBUG_CONFIG
832: {
833: unsigned int bus, dev, fcn;
834: mpc_decompose_tag(cpv, tag, &bus, &dev, &fcn);
835: printf("mpc_conf_write bus %x dev %x fcn %x offset %x", bus,
836: dev, fcn, offset);
837: printf(" daddr %x reg %x",daddr, reg);
838: printf(" data %x\n", data);
839: }
840: #endif
841:
842: s = splhigh();
843:
844: bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, reg);
845: bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
846: bus_space_write_4(cp->lc_iot, cp->ioh_cfc, daddr, data);
847: bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, 0); /* disable */
848: bus_space_read_4(cp->lc_iot, cp->ioh_cf8, 0); /* XXX */
849:
850: splx(s);
851: }
852:
853:
854: /*ARGSUSED*/
855: int
856: mpc_intr_map(void *lcv, pcitag_t bustag, int buspin, int line,
857: pci_intr_handle_t *ihp)
858: {
859: int error = 0;
860:
861: *ihp = -1;
862: if (buspin == 0)
863: error = 1; /* No IRQ used. */
864: else if (buspin > 4) {
865: printf("mpc_intr_map: bad interrupt pin %d\n", buspin);
866: error = 1;
867: }
868:
869: if (!error)
870: *ihp = line;
871: return error;
872: }
873:
874: const char *
875: mpc_intr_string(void *lcv, pci_intr_handle_t ih)
876: {
877: static char str[16];
878:
879: snprintf(str, sizeof str, "irq %ld", ih);
880: return(str);
881: }
882:
883: int
884: mpc_intr_line(void *lcv, pci_intr_handle_t ih)
885: {
886: return (ih);
887: }
888:
889: void *
890: mpc_intr_establish(void *lcv, pci_intr_handle_t ih, int level,
891: int (*func)(void *), void *arg, char *name)
892: {
893: return (*intr_establish_func)(lcv, ih, IST_LEVEL, level, func, arg,
894: name);
895: }
896:
897: void
898: mpc_intr_disestablish(void *lcv, void *cookie)
899: {
900: /* XXX We should probably do something clever here.... later */
901: }
902:
903: u_int32_t
904: pci_iack()
905: {
906: /* do pci IACK cycle */
907: /* this should be bus allocated. */
908: volatile u_int8_t *iack = (u_int8_t *)0xbffffff0;
909: u_int8_t val;
910:
911: val = *iack;
912: return val;
913: }
914:
915: void
916: mpc_cfg_write_1(struct pcibr_config *cp, u_int32_t reg, u_int8_t val)
917: {
918: int s;
919: s = splhigh();
920: bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg));
921: bus_space_write_1(cp->lc_iot, cp->ioh_cfc, 0, val);
922: splx(s);
923: }
924:
925: void
926: mpc_cfg_write_2(struct pcibr_config *cp, u_int32_t reg, u_int16_t val)
927: {
928: int s;
929: s = splhigh();
930: bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg));
931: bus_space_write_2(cp->lc_iot, cp->ioh_cfc, 0, val);
932: splx(s);
933: }
934:
935: void
936: mpc_cfg_write_4(struct pcibr_config *cp, u_int32_t reg, u_int32_t val)
937: {
938:
939: int s;
940: s = splhigh();
941: bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg));
942: bus_space_write_4(cp->lc_iot, cp->ioh_cfc, 0, val);
943: splx(s);
944: }
945:
946: u_int8_t
947: mpc_cfg_read_1(struct pcibr_config *cp, u_int32_t reg)
948: {
949: u_int8_t _v_;
950:
951: int s;
952: s = splhigh();
953: bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg));
954: _v_ = bus_space_read_1(cp->lc_iot, cp->ioh_cfc, 0);
955: splx(s);
956: return(_v_);
957: }
958:
959: u_int16_t
960: mpc_cfg_read_2(struct pcibr_config *cp, u_int32_t reg)
961: {
962: u_int16_t _v_;
963:
964: int s;
965: s = splhigh();
966: bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg));
967: _v_ = bus_space_read_2(cp->lc_iot, cp->ioh_cfc, 0);
968: splx(s);
969: return(_v_);
970: }
971:
972: u_int32_t
973: mpc_cfg_read_4(struct pcibr_config *cp, u_int32_t reg)
974: {
975: u_int32_t _v_;
976:
977: int s;
978: s = splhigh();
979: bus_space_write_4(cp->lc_iot, cp->ioh_cf8, 0, MPC106_REGOFFS(reg));
980: _v_ = bus_space_read_4(cp->lc_iot, cp->ioh_cfc, 0);
981: splx(s);
982: return(_v_);
983: }
CVSweb