Annotation of sys/dev/pci/musycc_obsd.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: musycc_obsd.c,v 1.9 2006/01/25 11:02:54 claudio Exp $ */
2:
3: /*
4: * Copyright (c) 2004,2005 Internet Business Solutions AG, Zurich, Switzerland
5: * Written by: Claudio Jeker <jeker@accoom.net>
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 USE, DATA OR PROFITS, WHETHER IN AN
16: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18: */
19:
20: #include <sys/param.h>
21: #include <sys/types.h>
22:
23: #include <sys/device.h>
24: #include <sys/malloc.h>
25: #include <sys/systm.h>
26: #include <sys/socket.h>
27:
28: #include <machine/cpu.h>
29: #include <machine/bus.h>
30: #include <machine/intr.h>
31:
32: #include <net/if.h>
33: #include <net/if_media.h>
34: #include <net/if_sppp.h>
35:
36: #include <dev/pci/musyccvar.h>
37: #include <dev/pci/musyccreg.h>
38:
39: #include <dev/pci/pcivar.h>
40: #include <dev/pci/pcireg.h>
41: #include <dev/pci/pcidevs.h>
42:
43: int musycc_match(struct device *, void *, void *);
44: void musycc_softc_attach(struct device *, struct device *, void *);
45: void musycc_ebus_attach(struct device *, struct musycc_softc *,
46: struct pci_attach_args *);
47: int musycc_ebus_print(void *, const char *);
48:
49: struct cfattach musycc_ca = {
50: sizeof(struct musycc_softc), musycc_match, musycc_softc_attach
51: };
52:
53: struct cfdriver musycc_cd = {
54: NULL, "musycc", DV_DULL
55: };
56:
57: SLIST_HEAD(, musycc_softc) msc_list = SLIST_HEAD_INITIALIZER(msc_list);
58:
59: const struct pci_matchid musycc_pci_devices[] = {
60: { PCI_VENDOR_CONEXANT, PCI_PRODUCT_CONEXANT_MUSYCC8478 },
61: { PCI_VENDOR_CONEXANT, PCI_PRODUCT_CONEXANT_MUSYCC8474 },
62: { PCI_VENDOR_CONEXANT, PCI_PRODUCT_CONEXANT_MUSYCC8472 },
63: { PCI_VENDOR_CONEXANT, PCI_PRODUCT_CONEXANT_MUSYCC8471 }
64: };
65:
66: int
67: musycc_match(struct device *parent, void *match, void *aux)
68: {
69: return (pci_matchbyid((struct pci_attach_args *)aux, musycc_pci_devices,
70: sizeof(musycc_pci_devices)/sizeof(musycc_pci_devices[0])));
71: }
72:
73: void
74: musycc_softc_attach(struct device *parent, struct device *self, void *aux)
75: {
76: struct musycc_softc *sc = (struct musycc_softc *)self;
77: struct pci_attach_args *pa = aux;
78: pci_chipset_tag_t pc = pa->pa_pc;
79: pci_intr_handle_t ih;
80: const char *intrstr = NULL;
81:
82: if (pci_mapreg_map(pa, MUSYCC_PCI_BAR,
83: PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 0,
84: &sc->mc_st, &sc->mc_sh, NULL, &sc->mc_iosize, 0)) {
85: printf(": can't map mem space\n");
86: return;
87: }
88: sc->mc_dmat = pa->pa_dmat;
89:
90: switch (PCI_PRODUCT(pa->pa_id)) {
91: case PCI_PRODUCT_CONEXANT_MUSYCC8478:
92: sc->mc_ngroups = 8;
93: sc->mc_nports = 8;
94: break;
95: case PCI_PRODUCT_CONEXANT_MUSYCC8474:
96: sc->mc_ngroups = 4;
97: sc->mc_nports = 4;
98: break;
99: case PCI_PRODUCT_CONEXANT_MUSYCC8472:
100: sc->mc_ngroups = 2;
101: sc->mc_nports = 2;
102: break;
103: case PCI_PRODUCT_CONEXANT_MUSYCC8471:
104: sc->mc_ngroups = 1;
105: sc->mc_nports = 1;
106: break;
107: }
108:
109: if (pa->pa_function == 1)
110: return (musycc_ebus_attach(parent, sc, pa));
111:
112: sc->bus = parent->dv_unit;
113: sc->device = pa->pa_device;
114: SLIST_INSERT_HEAD(&msc_list, sc, list);
115:
116: /*
117: * Allocate our interrupt.
118: */
119: if (pci_intr_map(pa, &ih)) {
120: printf(": couldn't map interrupt\n");
121: bus_space_unmap(sc->mc_st, sc->mc_sh, sc->mc_iosize);
122: return;
123: }
124:
125: intrstr = pci_intr_string(pc, ih);
126: sc->mc_ih = pci_intr_establish(pc, ih, IPL_NET, musycc_intr, sc,
127: self->dv_xname);
128: if (sc->mc_ih == NULL) {
129: printf(": couldn't establish interrupt");
130: if (intrstr != NULL)
131: printf(" at %s", intrstr);
132: printf("\n");
133: bus_space_unmap(sc->mc_st, sc->mc_sh, sc->mc_iosize);
134: return;
135: }
136:
137: printf(": %s\n", intrstr);
138:
139: /* soft reset device */
140: bus_space_write_4(sc->mc_st, sc->mc_sh, MUSYCC_SERREQ(0),
141: MUSYCC_SREQ_SET(1));
142: bus_space_barrier(sc->mc_st, sc->mc_sh, MUSYCC_SERREQ(0),
143: sizeof(u_int32_t), BUS_SPACE_BARRIER_WRITE);
144:
145: /*
146: * preload global configuration: set EBUS to sane defaults
147: * so that the ROM access will work.
148: * intel mode, elapse = 3, blapse = 3, alapse = 3, disable INTB
149: */
150: sc->mc_global_conf = MUSYCC_CONF_MPUSEL | MUSYCC_CONF_ECKEN |
151: MUSYCC_CONF_ELAPSE_SET(3) | MUSYCC_CONF_ALAPSE_SET(3) |
152: MUSYCC_CONF_BLAPSE_SET(3) | MUSYCC_CONF_INTB;
153:
154: /* Dual Address Cycle Base Pointer */
155: bus_space_write_4(sc->mc_st, sc->mc_sh, MUSYCC_DACB_PTR, 0);
156: /* Global Configuration Descriptor */
157: bus_space_write_4(sc->mc_st, sc->mc_sh, MUSYCC_GLOBALCONF,
158: sc->mc_global_conf);
159:
160: return;
161: }
162:
163: void
164: musycc_ebus_attach(struct device *parent, struct musycc_softc *esc,
165: struct pci_attach_args *pa)
166: {
167: struct ebus_dev rom;
168: struct musycc_attach_args ma;
169: struct musycc_softc *sc;
170: pci_chipset_tag_t pc = pa->pa_pc;
171: #if 0
172: pci_intr_handle_t ih;
173: const char *intrstr = NULL;
174: #endif
175: struct musycc_rom baseconf;
176: struct musycc_rom_framer framerconf;
177: bus_size_t offset;
178: int i;
179:
180: /* find HDLC controller softc ... */
181: SLIST_FOREACH(sc, &msc_list, list)
182: if (sc->bus == parent->dv_unit && sc->device == pa->pa_device)
183: break;
184: if (sc == NULL) {
185: printf(": corresponding hdlc controller not found\n");
186: return;
187: }
188:
189: /* ... and link them together */
190: esc->mc_other = sc;
191: sc->mc_other = esc;
192:
193: #if 0
194: /*
195: * Allocate our interrupt.
196: */
197: if (pci_intr_map(pa, &ih)) {
198: printf(": couldn't map interrupt\n");
199: goto failed;
200: }
201:
202: intrstr = pci_intr_string(pc, ih);
203: esc->mc_ih = pci_intr_establish(pc, ih, IPL_NET, ebus_intr, esc,
204: esc->mc_dev.dv_xname);
205: if (esc->mc_ih == NULL) {
206: printf(": couldn't establish interrupt");
207: if (intrstr != NULL)
208: printf(" at %s", intrstr);
209: printf("\n");
210: goto failed;
211: }
212:
213: /* XXX this printf should actually move to the end of the function */
214: printf(": %s\n", intrstr);
215: #endif
216:
217: if (ebus_attach_device(&rom, sc, 0, 0x400) != 0) {
218: printf(": failed to map rom @ %05p\n", 0);
219: goto failed;
220: }
221:
222: offset = 0;
223: ebus_read_buf(&rom, offset, &baseconf, sizeof(baseconf));
224: offset += sizeof(baseconf);
225:
226: if (baseconf.magic != MUSYCC_ROM_MAGIC) {
227: printf(": bad rom\n");
228: goto failed;
229: }
230:
231: /* Do generic parts of attach. */
232: if (musycc_attach_common(sc, baseconf.portmap, baseconf.portmode))
233: goto failed;
234:
235: /* map and reset leds */
236: /* (15 * 0x4000) << 2 */
237: esc->mc_ledbase = ntohl(baseconf.ledbase) << 2;
238: esc->mc_ledmask = baseconf.ledmask;
239: esc->mc_ledstate = 0;
240: bus_space_write_1(esc->mc_st, esc->mc_sh, esc->mc_ledbase, 0);
241:
242: printf("\n");
243:
244: for (i = 0; i < baseconf.numframer; i++) {
245: if (offset >= 0x400) {
246: printf("%s: bad rom\n", sc->mc_dev.dv_xname);
247: goto failed;
248: }
249: ebus_read_buf(&rom, offset, &framerconf, sizeof(framerconf));
250: offset += sizeof(framerconf);
251:
252: strlcpy(ma.ma_product, baseconf.product, sizeof(ma.ma_product));
253: ma.ma_base = ntohl(framerconf.base);
254: ma.ma_size = ntohl(framerconf.size);
255: ma.ma_type = ntohl(framerconf.type);
256: ma.ma_gnum = framerconf.gnum;
257: ma.ma_port = framerconf.port;
258: ma.ma_flags = framerconf.flags;
259: ma.ma_slot = framerconf.slot;
260:
261: (void)config_found(&sc->mc_dev, &ma, musycc_ebus_print);
262: }
263:
264: return;
265: failed:
266: /* Failed! */
267: pci_intr_disestablish(pc, sc->mc_ih);
268: if (esc->mc_ih != NULL)
269: pci_intr_disestablish(pc, esc->mc_ih);
270: bus_space_unmap(sc->mc_st, sc->mc_sh, sc->mc_iosize);
271: bus_space_unmap(esc->mc_st, esc->mc_sh, esc->mc_iosize);
272: return;
273: }
274:
275: int
276: musycc_ebus_print(void *aux, const char *pnp)
277: {
278: struct musycc_attach_args *ma = aux;
279:
280: if (pnp)
281: printf("framer at %s port %d slot %c",
282: pnp, ma->ma_port, ma->ma_slot);
283: else
284: printf(" port %d slot %c", ma->ma_port, ma->ma_slot);
285: return (UNCONF);
286: }
287:
CVSweb