This source file includes following definitions.
- musycc_attach_common
- musycc_alloc_groupdesc
- musycc_alloc_intqueue
- musycc_alloc_group
- musycc_free_groupdesc
- musycc_free_intqueue
- musycc_free_dmadesc
- musycc_free_group
- musycc_set_group
- musycc_set_port
- musycc_set_tsmap
- musycc_set_chandesc
- musycc_init_channel
- musycc_activate_channel
- musycc_stop_channel
- musycc_free_channel
- musycc_state_engine
- musycc_dma_get
- musycc_dma_free
- musycc_list_tx_init
- musycc_list_rx_init
- musycc_list_tx_free
- musycc_list_rx_free
- musycc_reinit_dma
- musycc_newbuf
- musycc_encap
- musycc_start
- musycc_watchdog
- musycc_rxeom
- musycc_txeom
- musycc_intr
- musycc_kick
- musycc_sreq
- musycc_tick
- ebus_intr
- ebus_attach_device
- ebus_read
- ebus_write
- ebus_read_buf
- ebus_set_led
- musycc_attach_sppp
- musycc_channel_create
- musycc_channel_attach
- musycc_channel_detach
- musycc_intr_print
- musycc_dump_group
- musycc_dump_desc
- musycc_dump_dma
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include "bpfilter.h"
20
21 #include <sys/param.h>
22 #include <sys/types.h>
23
24 #include <sys/device.h>
25 #include <sys/kernel.h>
26 #include <sys/limits.h>
27 #include <sys/malloc.h>
28 #include <sys/mbuf.h>
29 #include <sys/proc.h>
30 #include <sys/socket.h>
31 #include <sys/syslog.h>
32 #include <sys/systm.h>
33
34 #include <machine/cpu.h>
35 #include <machine/bus.h>
36 #include <machine/intr.h>
37
38 #include <net/if.h>
39 #include <net/if_media.h>
40 #include <net/if_sppp.h>
41
42 #if NBPFILTER > 0
43 #include <net/bpf.h>
44 #endif
45
46 #include <dev/pci/musyccvar.h>
47 #include <dev/pci/musyccreg.h>
48
49 int musycc_alloc_groupdesc(struct musycc_softc *);
50 int musycc_alloc_intqueue(struct musycc_softc *);
51 int musycc_alloc_group(struct musycc_group *);
52 void musycc_free_groupdesc(struct musycc_softc *);
53 void musycc_free_intqueue(struct musycc_softc *);
54 void musycc_free_dmadesc(struct musycc_group *);
55 void musycc_free_group(struct musycc_group *);
56 void musycc_set_group(struct musycc_group *, int, int, int);
57 int musycc_set_tsmap(struct musycc_group *, struct channel_softc *, char);
58 int musycc_set_chandesc(struct musycc_group *, int, int, int);
59 void musycc_activate_channel(struct musycc_group *, int);
60 void musycc_state_engine(struct musycc_group *, int, enum musycc_event);
61
62 struct dma_desc *musycc_dma_get(struct musycc_group *);
63 void musycc_dma_free(struct musycc_group *, struct dma_desc *);
64 int musycc_list_tx_init(struct musycc_group *, int, int);
65 int musycc_list_rx_init(struct musycc_group *, int, int);
66 void musycc_list_tx_free(struct musycc_group *, int);
67 void musycc_list_rx_free(struct musycc_group *, int);
68 void musycc_reinit_dma(struct musycc_group *, int);
69 int musycc_newbuf(struct musycc_group *, struct dma_desc *, struct mbuf *);
70 int musycc_encap(struct musycc_group *, struct mbuf *, int);
71
72 void musycc_rxeom(struct musycc_group *, int, int);
73 void musycc_txeom(struct musycc_group *, int, int);
74 void musycc_kick(struct musycc_group *);
75 void musycc_sreq(struct musycc_group *, int, u_int32_t, int,
76 enum musycc_event);
77
78 #ifndef ACCOOM_DEBUG
79 #define musycc_dump_group(n, x)
80 #define musycc_dump_desc(n, x)
81 #define musycc_dump_dma(n, x, y)
82 #else
83 int accoom_debug = 0;
84
85 char *musycc_intr_print(u_int32_t);
86 void musycc_dump_group(int, struct musycc_group *);
87 void musycc_dump_desc(int, struct musycc_group *);
88 void musycc_dump_dma(int, struct musycc_group *, int);
89 #endif
90
91 int
92 musycc_attach_common(struct musycc_softc *sc, u_int32_t portmap, u_int32_t mode)
93 {
94 struct musycc_group *mg;
95 int i, j;
96
97 if (musycc_alloc_groupdesc(sc) == -1) {
98 printf(": couldn't alloc group descriptors\n");
99 return (-1);
100 }
101
102 if (musycc_alloc_intqueue(sc) == -1) {
103 printf(": couldn't alloc interrupt queue\n");
104 musycc_free_groupdesc(sc);
105 return (-1);
106 }
107
108
109
110
111
112
113 sc->mc_global_conf = (portmap & MUSYCC_CONF_PORTMAP) |
114 MUSYCC_CONF_MPUSEL | MUSYCC_CONF_ECKEN |
115 MUSYCC_CONF_ELAPSE_SET(3) | MUSYCC_CONF_ALAPSE_SET(3) |
116 MUSYCC_CONF_BLAPSE_SET(3) | MUSYCC_CONF_INTB;
117
118
119 sc->mc_groups = (struct musycc_group *)malloc(sc->mc_ngroups *
120 sizeof(struct musycc_group), M_DEVBUF, M_NOWAIT);
121 if (sc->mc_groups == NULL) {
122 printf(": couldn't alloc group descriptors\n");
123 musycc_free_groupdesc(sc);
124 musycc_free_intqueue(sc);
125 return (-1);
126 }
127 bzero(sc->mc_groups, sc->mc_ngroups * sizeof(struct musycc_group));
128
129 for (i = 0; i < sc->mc_ngroups; i++) {
130 mg = &sc->mc_groups[i];
131 mg->mg_hdlc = sc;
132 mg->mg_gnum = i;
133 mg->mg_port = i >> (portmap & MUSYCC_CONF_PORTMAP);
134 mg->mg_dmat = sc->mc_dmat;
135
136 if (musycc_alloc_group(mg) == -1) {
137 printf(": couldn't alloc group structures\n");
138 for (j = 0; j < i; j++)
139 musycc_free_group(&sc->mc_groups[j]);
140 musycc_free_groupdesc(sc);
141 musycc_free_intqueue(sc);
142 return (-1);
143 }
144
145 mg->mg_group = (struct musycc_grpdesc *)
146 (sc->mc_groupkva + MUSYCC_GROUPBASE(i));
147 bzero(mg->mg_group, sizeof(struct musycc_grpdesc));
148 musycc_set_group(mg, MUSYCC_GRCFG_POLL32, MUSYCC_MAXFRM_MAX,
149 MUSYCC_MAXFRM_MAX);
150 musycc_set_port(mg, mode);
151
152 bus_dmamap_sync(sc->mc_dmat, sc->mc_cfgmap,
153 MUSYCC_GROUPBASE(i), sizeof(struct musycc_grpdesc),
154 BUS_DMASYNC_PREWRITE);
155 bus_space_write_4(sc->mc_st, sc->mc_sh, MUSYCC_GROUPBASE(i),
156 sc->mc_cfgmap->dm_segs[0].ds_addr + MUSYCC_GROUPBASE(i));
157 }
158
159
160 bus_space_write_4(sc->mc_st, sc->mc_sh, MUSYCC_DACB_PTR, 0);
161
162 bus_space_write_4(sc->mc_st, sc->mc_sh, MUSYCC_GLOBALCONF,
163 sc->mc_global_conf);
164
165 bus_space_write_4(sc->mc_st, sc->mc_sh, MUSYCC_INTQPTR,
166 sc->mc_intrqptr);
167
168
169
170
171 bus_space_write_4(sc->mc_st, sc->mc_sh, MUSYCC_INTQLEN,
172 MUSYCC_INTLEN - 1);
173
174
175 for (i = 0; i < sc->mc_ngroups; i++) {
176 mg = &sc->mc_groups[i];
177 musycc_sreq(mg, 0, MUSYCC_SREQ_SET(5), MUSYCC_SREQ_BOTH,
178 EV_NULL);
179 mg->mg_loaded = 1;
180 }
181
182 return (0);
183 }
184
185 int
186 musycc_alloc_groupdesc(struct musycc_softc *sc)
187 {
188
189
190
191
192
193 if (bus_dmamem_alloc(sc->mc_dmat, sc->mc_ngroups * 2048,
194 2048, 0, sc->mc_cfgseg, 1, &sc->mc_cfgnseg, BUS_DMA_NOWAIT)) {
195 return (-1);
196 }
197 if (bus_dmamem_map(sc->mc_dmat, sc->mc_cfgseg, sc->mc_cfgnseg,
198 sc->mc_ngroups * 2048, &sc->mc_groupkva, BUS_DMA_NOWAIT)) {
199 bus_dmamem_free(sc->mc_dmat, sc->mc_cfgseg, sc->mc_cfgnseg);
200 return (-1);
201 }
202
203 if (bus_dmamap_create(sc->mc_dmat, sc->mc_ngroups * 2048,
204 1, sc->mc_ngroups * 2048, 0, BUS_DMA_NOWAIT, &sc->mc_cfgmap)) {
205 bus_dmamem_unmap(sc->mc_dmat, sc->mc_groupkva,
206 sc->mc_ngroups * 2048);
207 bus_dmamem_free(sc->mc_dmat, sc->mc_cfgseg, sc->mc_cfgnseg);
208 return (-1);
209 }
210 if (bus_dmamap_load(sc->mc_dmat, sc->mc_cfgmap, sc->mc_groupkva,
211 sc->mc_ngroups * 2048, NULL, BUS_DMA_NOWAIT)) {
212 musycc_free_groupdesc(sc);
213 return (-1);
214 }
215
216 return (0);
217 }
218
219 int
220 musycc_alloc_intqueue(struct musycc_softc *sc)
221 {
222
223
224
225 if (bus_dmamem_alloc(sc->mc_dmat, sizeof(struct musycc_intdesc), 4, 0,
226 sc->mc_intrseg, 1, &sc->mc_intrnseg, BUS_DMA_NOWAIT)) {
227 return (-1);
228 }
229 if (bus_dmamem_map(sc->mc_dmat, sc->mc_intrseg, sc->mc_intrnseg,
230 sizeof(struct musycc_intdesc), (caddr_t *)&sc->mc_intrd,
231 BUS_DMA_NOWAIT)) {
232 bus_dmamem_free(sc->mc_dmat, sc->mc_intrseg, sc->mc_intrnseg);
233 return (-1);
234 }
235
236
237 if (bus_dmamap_create(sc->mc_dmat, sizeof(struct musycc_intdesc),
238 1, sizeof(struct musycc_intdesc), 0, BUS_DMA_NOWAIT,
239 &sc->mc_intrmap)) {
240 bus_dmamem_unmap(sc->mc_dmat, (caddr_t)sc->mc_intrd,
241 sizeof(struct musycc_intdesc));
242 bus_dmamem_free(sc->mc_dmat, sc->mc_intrseg, sc->mc_intrnseg);
243 return (-1);
244 }
245 if (bus_dmamap_load(sc->mc_dmat, sc->mc_intrmap, sc->mc_intrd,
246 sizeof(struct musycc_intdesc), NULL, BUS_DMA_NOWAIT)) {
247 musycc_free_intqueue(sc);
248 return (-1);
249 }
250
251
252 sc->mc_intrqptr = sc->mc_intrmap->dm_segs[0].ds_addr +
253 offsetof(struct musycc_intdesc, md_intrq[0]);
254
255 return (0);
256 }
257
258 int
259 musycc_alloc_group(struct musycc_group *mg)
260 {
261 struct dma_desc *dd;
262 int j;
263
264
265 if (bus_dmamem_alloc(mg->mg_dmat, MUSYCC_DMA_MAPSIZE,
266 PAGE_SIZE, 0, mg->mg_listseg, 1, &mg->mg_listnseg,
267 BUS_DMA_NOWAIT))
268 return (-1);
269 if (bus_dmamem_map(mg->mg_dmat, mg->mg_listseg, mg->mg_listnseg,
270 MUSYCC_DMA_MAPSIZE, &mg->mg_listkva, BUS_DMA_NOWAIT)) {
271 bus_dmamem_free(mg->mg_dmat, mg->mg_listseg, mg->mg_listnseg);
272 return (-1);
273 }
274
275
276 if (bus_dmamap_create(mg->mg_dmat, MUSYCC_DMA_MAPSIZE, 1,
277 MUSYCC_DMA_MAPSIZE, 0, BUS_DMA_NOWAIT, &mg->mg_listmap)) {
278 bus_dmamem_unmap(mg->mg_dmat, mg->mg_listkva,
279 MUSYCC_DMA_MAPSIZE);
280 bus_dmamem_free(mg->mg_dmat, mg->mg_listseg, mg->mg_listnseg);
281 return (-1);
282 }
283 if (bus_dmamap_load(mg->mg_dmat, mg->mg_listmap, mg->mg_listkva,
284 MUSYCC_DMA_MAPSIZE, NULL, BUS_DMA_NOWAIT)) {
285 musycc_free_dmadesc(mg);
286 return (-1);
287 }
288
289
290
291
292
293
294 if (bus_dmamap_create(mg->mg_dmat, MCLBYTES, MUSYCC_DMA_SIZE, MCLBYTES,
295 0, BUS_DMA_NOWAIT, &mg->mg_tx_sparemap) != 0) {
296 musycc_free_dmadesc(mg);
297 return (-1);
298 }
299 if (bus_dmamap_create(mg->mg_dmat, MCLBYTES, MUSYCC_DMA_SIZE, MCLBYTES,
300 0, BUS_DMA_NOWAIT, &mg->mg_rx_sparemap) != 0) {
301 bus_dmamap_destroy(mg->mg_dmat, mg->mg_tx_sparemap);
302 musycc_free_dmadesc(mg);
303 return (-1);
304 }
305
306 mg->mg_dma_pool = (struct dma_desc *)mg->mg_listkva;
307 bzero(mg->mg_dma_pool,
308 MUSYCC_DMA_CNT * sizeof(struct dma_desc));
309
310
311 for (j = 0; j < MUSYCC_DMA_CNT; j++) {
312 dd = &mg->mg_dma_pool[j];
313
314 if (bus_dmamap_create(mg->mg_dmat, MCLBYTES, MUSYCC_DMA_SIZE,
315 MCLBYTES, 0, BUS_DMA_NOWAIT, &dd->map)) {
316 musycc_free_group(mg);
317 return (-1);
318 }
319
320 dd->nextdesc = mg->mg_freelist;
321 mg->mg_freelist = dd;
322 mg->mg_freecnt++;
323 }
324
325 return (0);
326 }
327
328 void
329 musycc_free_groupdesc(struct musycc_softc *sc)
330 {
331 bus_dmamap_destroy(sc->mc_dmat, sc->mc_cfgmap);
332 bus_dmamem_unmap(sc->mc_dmat, sc->mc_groupkva,
333 sc->mc_ngroups * 2048);
334 bus_dmamem_free(sc->mc_dmat, sc->mc_cfgseg, sc->mc_cfgnseg);
335 }
336
337 void
338 musycc_free_intqueue(struct musycc_softc *sc)
339 {
340 bus_dmamap_destroy(sc->mc_dmat, sc->mc_intrmap);
341 bus_dmamem_unmap(sc->mc_dmat, (caddr_t)sc->mc_intrd,
342 sizeof(struct musycc_intdesc));
343 bus_dmamem_free(sc->mc_dmat, sc->mc_intrseg, sc->mc_intrnseg);
344 }
345
346 void
347 musycc_free_dmadesc(struct musycc_group *mg)
348 {
349 bus_dmamap_destroy(mg->mg_dmat, mg->mg_listmap);
350 bus_dmamem_unmap(mg->mg_dmat, mg->mg_listkva,
351 MUSYCC_DMA_MAPSIZE);
352 bus_dmamem_free(mg->mg_dmat, mg->mg_listseg, mg->mg_listnseg);
353 }
354
355 void
356 musycc_free_group(struct musycc_group *mg)
357 {
358 bus_dmamap_destroy(mg->mg_dmat, mg->mg_tx_sparemap);
359 bus_dmamap_destroy(mg->mg_dmat, mg->mg_tx_sparemap);
360
361 musycc_free_dmadesc(mg);
362 mg->mg_dma_pool = NULL;
363 mg->mg_freelist = NULL;
364 mg->mg_freecnt = 0;
365 }
366
367 void
368 musycc_set_group(struct musycc_group *mg, int poll, int maxa, int maxb)
369 {
370
371 mg->mg_group->global_conf = htole32(mg->mg_hdlc->mc_global_conf);
372
373
374
375
376 mg->mg_group->int_queuep = htole32(mg->mg_hdlc->mc_intrqptr);
377 mg->mg_group->int_queuelen = htole32(MUSYCC_INTLEN - 1);
378
379
380 mg->mg_group->group_conf = htole32(MUSYCC_GRCFG_RXENBL |
381 MUSYCC_GRCFG_TXENBL | MUSYCC_GRCFG_SUBDSBL |
382 MUSYCC_GRCFG_MSKCOFA | MUSYCC_GRCFG_MSKOOF |
383 MUSYCC_GRCFG_MCENBL | (poll & MUSYCC_GRCFG_POLL64));
384
385
386
387
388
389 mg->mg_group->msglen_conf = htole32(maxa);
390 mg->mg_group->msglen_conf |= htole32(maxb << MUSYCC_MAXFRM2_SHIFT);
391 }
392
393 void
394 musycc_set_port(struct musycc_group *mg, int mode)
395 {
396
397
398
399
400
401
402 mg->mg_group->port_conf = htole32(MUSYCC_PORT_TSYNC_EDGE |
403 MUSYCC_PORT_TRITX | (mode & MUSYCC_PORT_MODEMASK));
404
405 if (mg->mg_loaded)
406 musycc_sreq(mg, 0, MUSYCC_SREQ_SET(21), MUSYCC_SREQ_RX,
407 EV_NULL);
408 }
409
410
411
412
413 int
414 musycc_set_tsmap(struct musycc_group *mg, struct channel_softc *cc, char slot)
415 {
416 int i, nslots = 0, off, scale;
417 u_int32_t tslots = cc->cc_tslots;
418
419 ACCOOM_PRINTF(1, ("%s: musycc_set_tsmap %08x slot %c\n",
420 cc->cc_ifp->if_xname, tslots, slot));
421
422 switch (slot) {
423 case 'A':
424 off = 0;
425 scale = 1;
426 break;
427 case 'a':
428 case 'b':
429 off = slot - 'a';
430 scale = 2;
431 break;
432 case '1':
433 case '2':
434 case '3':
435 case '4':
436 off = slot - '1';
437 scale = 4;
438 break;
439 default:
440
441 log(LOG_ERR, "%s: accessing unsupported slot %c",
442 cc->cc_ifp->if_xname, slot);
443 return (-1);
444 }
445
446
447
448
449
450
451
452
453 for (i = 0; i < sizeof(u_int32_t) * 8; i++)
454 if (tslots & (1 << i))
455 if (mg->mg_group->tx_tsmap[i * scale + off] &
456 MUSYCC_TSLOT_ENABLED ||
457 mg->mg_group->rx_tsmap[i * scale + off] &
458 MUSYCC_TSLOT_ENABLED)
459 return (0);
460
461 for (i = 0; i < sizeof(u_int32_t) * 8; i++)
462 if (tslots & (1 << i)) {
463 nslots++;
464 mg->mg_group->tx_tsmap[i * scale + off] =
465 MUSYCC_TSLOT_CHAN(cc->cc_channel) |
466 MUSYCC_TSLOT_ENABLED;
467 mg->mg_group->rx_tsmap[i * scale + off] =
468 MUSYCC_TSLOT_CHAN(cc->cc_channel) |
469 MUSYCC_TSLOT_ENABLED;
470 }
471
472 return (nslots);
473 }
474
475 int
476 musycc_set_chandesc(struct musycc_group *mg, int chan, int nslots, int proto)
477 {
478 u_int64_t mask = ULLONG_MAX;
479 int idx, n;
480
481 ACCOOM_PRINTF(1, ("%s: musycc_set_chandesc nslots %d proto %d\n",
482 mg->mg_channels[chan]->cc_ifp->if_xname, nslots, proto));
483
484 if (nslots == 0 || nslots > 32)
485 return (EINVAL);
486
487 n = 64 - 2 * nslots;
488 mask >>= n;
489
490 for (idx = 0; idx <= n; idx += 2)
491 if (!(mg->mg_fifomask & mask << idx))
492 break;
493
494 if (idx > n)
495 return (EBUSY);
496
497 mg->mg_fifomask |= mask << idx;
498
499
500 mg->mg_group->tx_cconf[chan] = htole32(MUSYCC_CHAN_BUFIDX_SET(idx) |
501 MUSYCC_CHAN_BUFLEN_SET(nslots * 2 - 1) |
502 MUSYCC_CHAN_PROTO_SET(proto));
503 mg->mg_group->rx_cconf[chan] = htole32(MUSYCC_CHAN_BUFIDX_SET(idx) |
504 MUSYCC_CHAN_BUFLEN_SET(nslots * 2 - 1) |
505 MUSYCC_CHAN_MSKIDLE | MUSYCC_CHAN_MSKSUERR | MUSYCC_CHAN_MSKSINC |
506 MUSYCC_CHAN_MSKSDEC | MUSYCC_CHAN_MSKSFILT |
507 MUSYCC_CHAN_PROTO_SET(proto));
508
509 return (0);
510 }
511
512 int
513 musycc_init_channel(struct channel_softc *cc, char slot)
514 {
515 struct musycc_group *mg;
516 struct ifnet *ifp = cc->cc_ifp;
517 int nslots, rv, s;
518
519 if (cc->cc_state == CHAN_FLOAT)
520 return (ENOTTY);
521 mg = cc->cc_group;
522
523 ACCOOM_PRINTF(2, ("%s: musycc_init_channel [state %d] slot %c\n",
524 cc->cc_ifp->if_xname, cc->cc_state, slot));
525
526 if (cc->cc_state != CHAN_IDLE) {
527 musycc_sreq(mg, cc->cc_channel, MUSYCC_SREQ_SET(9),
528 MUSYCC_SREQ_BOTH, EV_STOP);
529 tsleep(cc, PZERO | PCATCH, "musycc", hz);
530 if (cc->cc_state != CHAN_IDLE) {
531 ACCOOM_PRINTF(0, ("%s: failed to reset channel\n",
532 cc->cc_ifp->if_xname));
533 return (EIO);
534 }
535 }
536
537 s = splnet();
538
539 nslots = musycc_set_tsmap(mg, cc, slot);
540 if (nslots == -1) {
541 rv = EINVAL;
542 goto fail;
543 } else if (nslots == 0) {
544 rv = EBUSY;
545 goto fail;
546 }
547
548 if ((rv = musycc_set_chandesc(mg, cc->cc_channel, nslots,
549 MUSYCC_PROTO_HDLC16)))
550 goto fail;
551
552
553 musycc_list_tx_init(mg, cc->cc_channel, MUSYCC_DMA_SIZE);
554
555 if ((rv = musycc_list_rx_init(mg, cc->cc_channel, MUSYCC_DMA_SIZE))) {
556 ACCOOM_PRINTF(0, ("%s: initialization failed: "
557 "no memory for rx buffers\n", cc->cc_ifp->if_xname));
558 goto fail;
559 }
560
561
562 ifp->if_flags &= ~IFF_OACTIVE;
563
564 cc->cc_state = CHAN_TRANSIENT;
565 splx(s);
566
567 musycc_dump_group(3, mg);
568 musycc_activate_channel(mg, cc->cc_channel);
569 tsleep(cc, PZERO | PCATCH, "musycc", hz);
570
571
572
573
574
575 return (0);
576
577 fail:
578 splx(s);
579 cc->cc_state = CHAN_IDLE;
580 musycc_free_channel(mg, cc->cc_channel);
581 return (rv);
582 }
583
584 void
585 musycc_activate_channel(struct musycc_group *mg, int chan)
586 {
587 ACCOOM_PRINTF(2, ("%s: musycc_activate_channel\n",
588 mg->mg_channels[chan]->cc_ifp->if_xname));
589 musycc_sreq(mg, chan, MUSYCC_SREQ_SET(26), MUSYCC_SREQ_BOTH,
590 EV_NULL);
591 musycc_sreq(mg, chan, MUSYCC_SREQ_SET(24), MUSYCC_SREQ_BOTH,
592 EV_NULL);
593 musycc_sreq(mg, chan, MUSYCC_SREQ_SET(8), MUSYCC_SREQ_BOTH,
594 EV_ACTIVATE);
595 }
596
597 void
598 musycc_stop_channel(struct channel_softc *cc)
599 {
600 struct musycc_group *mg;
601
602 if (cc->cc_state == CHAN_FLOAT) {
603
604 log(LOG_ERR, "%s: unexpected state in musycc_stop_channel",
605 cc->cc_ifp->if_xname);
606 cc->cc_state = CHAN_IDLE;
607 musycc_free_channel(mg, cc->cc_channel);
608 return;
609 }
610
611 mg = cc->cc_group;
612 ACCOOM_PRINTF(2, ("%s: musycc_stop_channel\n", cc->cc_ifp->if_xname));
613 musycc_sreq(mg, cc->cc_channel, MUSYCC_SREQ_SET(9), MUSYCC_SREQ_BOTH,
614 EV_STOP);
615 tsleep(cc, PZERO | PCATCH, "musycc", hz);
616 }
617
618 void
619 musycc_free_channel(struct musycc_group *mg, int chan)
620 {
621 u_int64_t mask = ULLONG_MAX;
622 int i, idx, s, slots;
623
624 ACCOOM_PRINTF(2, ("%s: musycc_free_channel\n",
625 mg->mg_channels[chan]->cc_ifp->if_xname));
626
627 s = splnet();
628
629 mg->mg_channels[chan]->cc_ifp->if_timer = 0;
630
631
632 for (i = 0; i < 128; i++) {
633 if (mg->mg_group->tx_tsmap[i] & MUSYCC_TSLOT_ENABLED)
634 if ((mg->mg_group->tx_tsmap[i] & MUSYCC_TSLOT_MASK) ==
635 chan)
636 mg->mg_group->tx_tsmap[i] = 0;
637 if (mg->mg_group->rx_tsmap[i] & MUSYCC_TSLOT_ENABLED)
638 if ((mg->mg_group->rx_tsmap[i] & MUSYCC_TSLOT_MASK) ==
639 chan)
640 mg->mg_group->rx_tsmap[i] = 0;
641 }
642
643
644 idx = MUSYCC_CHAN_BUFIDX_GET(letoh32(mg->mg_group->tx_cconf[chan]));
645 slots = MUSYCC_CHAN_BUFLEN_GET(letoh32(mg->mg_group->tx_cconf[chan]));
646 slots = (slots + 1) / 2;
647 mask >>= 64 - 2 * slots;
648 mask <<= idx;
649 mg->mg_fifomask &= ~mask;
650 mg->mg_group->tx_cconf[chan] = 0;
651 mg->mg_group->rx_cconf[chan] = 0;
652
653
654 musycc_list_rx_free(mg, chan);
655 musycc_list_tx_free(mg, chan);
656
657 splx(s);
658
659
660 musycc_sreq(mg, chan, MUSYCC_SREQ_SET(24), MUSYCC_SREQ_BOTH,
661 EV_NULL);
662 musycc_sreq(mg, chan, MUSYCC_SREQ_SET(26), MUSYCC_SREQ_BOTH,
663 EV_IDLE);
664 }
665
666 void
667 musycc_state_engine(struct musycc_group *mg, int chan, enum musycc_event ev)
668 {
669 enum musycc_state state;
670
671 if (mg->mg_channels[chan] == NULL)
672 return;
673
674 state = mg->mg_channels[chan]->cc_state;
675
676 ACCOOM_PRINTF(2, ("%s: musycc_state_engine state %d event %d\n",
677 mg->mg_channels[chan]->cc_ifp->if_xname, state, ev));
678
679 switch (ev) {
680 case EV_NULL:
681
682 return;
683 case EV_ACTIVATE:
684 state = CHAN_RUNNING;
685 break;
686 case EV_STOP:
687
688 mg->mg_channels[chan]->cc_state = CHAN_TRANSIENT;
689 musycc_free_channel(mg, chan);
690 return;
691 case EV_IDLE:
692 state = CHAN_IDLE;
693 break;
694 case EV_WATCHDOG:
695 musycc_reinit_dma(mg, chan);
696 return;
697 }
698
699 mg->mg_channels[chan]->cc_state = state;
700 wakeup(mg->mg_channels[chan]);
701 }
702
703
704
705
706
707 struct dma_desc *
708 musycc_dma_get(struct musycc_group *mg)
709 {
710 struct dma_desc *dd;
711
712 splassert(IPL_NET);
713
714 if (mg->mg_freecnt == 0)
715 return (NULL);
716 mg->mg_freecnt--;
717 dd = mg->mg_freelist;
718 mg->mg_freelist = dd->nextdesc;
719
720 dd->nextdesc = NULL;
721 dd->mbuf = NULL;
722
723 return (dd);
724 }
725
726 void
727 musycc_dma_free(struct musycc_group *mg, struct dma_desc *dd)
728 {
729 splassert(IPL_NET);
730
731 dd->nextdesc = mg->mg_freelist;
732 mg->mg_freelist = dd;
733 mg->mg_freecnt++;
734 }
735
736
737
738
739
740 int
741 musycc_list_tx_init(struct musycc_group *mg, int c, int size)
742 {
743 struct musycc_dma_data *md;
744 struct dma_desc *dd;
745 bus_addr_t base;
746 int i;
747
748 splassert(IPL_NET);
749 ACCOOM_PRINTF(2, ("musycc_list_tx_init\n"));
750 md = &mg->mg_dma_d[c];
751 md->tx_pend = NULL;
752 md->tx_cur = NULL;
753 md->tx_cnt = size;
754 md->tx_pkts = 0;
755
756 base = mg->mg_listmap->dm_segs[0].ds_addr;
757 for (i = 0; i < md->tx_cnt; i++) {
758 dd = musycc_dma_get(mg);
759 if (dd == NULL) {
760 ACCOOM_PRINTF(0, ("musycc_list_tx_init: "
761 "out of dma_desc\n"));
762 musycc_list_tx_free(mg, c);
763 return (ENOBUFS);
764 }
765 dd->status = 0 ;
766 dd->data = 0;
767 if (md->tx_cur) {
768 md->tx_cur->nextdesc = dd;
769 md->tx_cur->next = htole32(base + (caddr_t)dd -
770 mg->mg_listkva);
771 md->tx_cur = dd;
772 } else
773 md->tx_pend = md->tx_cur = dd;
774 }
775
776 dd->nextdesc = md->tx_pend;
777 dd->next = htole32(base + (caddr_t)md->tx_pend - mg->mg_listkva);
778 md->tx_pend = dd;
779
780 mg->mg_group->tx_headp[c] = htole32(base + (caddr_t)dd -
781 mg->mg_listkva);
782
783 bus_dmamap_sync(mg->mg_dmat, mg->mg_listmap, 0, MUSYCC_DMA_MAPSIZE,
784 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
785
786 return (0);
787 }
788
789
790
791
792
793
794
795 int
796 musycc_list_rx_init(struct musycc_group *mg, int c, int size)
797 {
798 struct musycc_dma_data *md;
799 struct dma_desc *dd = NULL, *last;
800 bus_addr_t base;
801 int i;
802
803 splassert(IPL_NET);
804 ACCOOM_PRINTF(2, ("musycc_list_rx_init\n"));
805 md = &mg->mg_dma_d[c];
806 md->rx_cnt = size;
807
808 base = mg->mg_listmap->dm_segs[0].ds_addr;
809 for (i = 0; i < size; i++) {
810 dd = musycc_dma_get(mg);
811 if (dd == NULL) {
812 ACCOOM_PRINTF(0, ("musycc_list_rx_init: "
813 "out of dma_desc\n"));
814 musycc_list_rx_free(mg, c);
815 return (ENOBUFS);
816 }
817 if (musycc_newbuf(mg, dd, NULL) == ENOBUFS) {
818 ACCOOM_PRINTF(0, ("musycc_list_rx_init: "
819 "out of mbufs\n"));
820 musycc_list_rx_free(mg, c);
821 return (ENOBUFS);
822 }
823 if (md->rx_prod) {
824 md->rx_prod->nextdesc = dd;
825 md->rx_prod->next = htole32(base + (caddr_t)dd -
826 mg->mg_listkva);
827 md->rx_prod = dd;
828 } else
829 last = md->rx_prod = dd;
830 }
831
832 dd->nextdesc = last;
833 dd->next = htole32(base + (caddr_t)last - mg->mg_listkva);
834
835 mg->mg_group->rx_headp[c] = htole32(base + (caddr_t)dd -
836 mg->mg_listkva);
837
838 bus_dmamap_sync(mg->mg_dmat, mg->mg_listmap, 0, MUSYCC_DMA_MAPSIZE,
839 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
840
841 return (0);
842 }
843
844 void
845 musycc_list_tx_free(struct musycc_group *mg, int c)
846 {
847 struct musycc_dma_data *md;
848 struct dma_desc *dd, *tmp;
849
850 md = &mg->mg_dma_d[c];
851
852 splassert(IPL_NET);
853 ACCOOM_PRINTF(2, ("musycc_list_tx_free\n"));
854 dd = md->tx_pend;
855 do {
856 if (dd == NULL)
857 break;
858 if (dd->map->dm_nsegs != 0) {
859 bus_dmamap_t map = dd->map;
860
861 bus_dmamap_unload(mg->mg_dmat, map);
862 }
863 if (dd->mbuf != NULL) {
864 m_freem(dd->mbuf);
865 dd->mbuf = NULL;
866 }
867 tmp = dd;
868 dd = dd->nextdesc;
869 musycc_dma_free(mg, tmp);
870 } while (dd != md->tx_pend);
871 md->tx_pend = md->tx_cur = NULL;
872 md->tx_cnt = md->tx_use = md->tx_pkts = 0;
873 }
874
875 void
876 musycc_list_rx_free(struct musycc_group *mg, int c)
877 {
878 struct musycc_dma_data *md;
879 struct dma_desc *dd, *tmp;
880
881 md = &mg->mg_dma_d[c];
882
883 splassert(IPL_NET);
884 ACCOOM_PRINTF(2, ("musycc_list_rx_free\n"));
885 dd = md->rx_prod;
886 do {
887 if (dd == NULL)
888 break;
889 if (dd->map->dm_nsegs != 0) {
890 bus_dmamap_t map = dd->map;
891
892 bus_dmamap_unload(mg->mg_dmat, map);
893 }
894 if (dd->mbuf != NULL) {
895 m_freem(dd->mbuf);
896 dd->mbuf = NULL;
897 }
898 tmp = dd;
899 dd = dd->nextdesc;
900 musycc_dma_free(mg, tmp);
901 } while (dd != md->rx_prod);
902 md->rx_prod = NULL;
903 md->rx_cnt = 0;
904 }
905
906
907 void
908 musycc_reinit_dma(struct musycc_group *mg, int c)
909 {
910 int s;
911
912 s = splnet();
913
914 musycc_list_tx_free(mg, c);
915 musycc_list_rx_free(mg, c);
916
917
918 if (musycc_list_tx_init(mg, c, MUSYCC_DMA_SIZE) ||
919 musycc_list_rx_init(mg, c, MUSYCC_DMA_SIZE)) {
920 log(LOG_ERR, "%s: Failed to malloc memory\n",
921 mg->mg_channels[c]->cc_ifp->if_xname);
922 musycc_free_channel(mg, c);
923 }
924 splx(s);
925
926 musycc_activate_channel(mg, c);
927 }
928
929
930
931
932 int
933 musycc_newbuf(struct musycc_group *mg, struct dma_desc *c, struct mbuf *m)
934 {
935 struct mbuf *m_new = NULL;
936 bus_dmamap_t map;
937
938 if (m == NULL) {
939 MGETHDR(m_new, M_DONTWAIT, MT_DATA);
940 if (m_new == NULL)
941 return (ENOBUFS);
942
943 MCLGET(m_new, M_DONTWAIT);
944 if (!(m_new->m_flags & M_EXT)) {
945 m_freem(m_new);
946 return (ENOBUFS);
947 }
948 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
949 } else {
950 m_new = m;
951 m_new->m_len = m_new->m_pkthdr.len = MCLBYTES;
952 m_new->m_data = m_new->m_ext.ext_buf;
953 }
954
955 if (bus_dmamap_load(mg->mg_dmat, mg->mg_rx_sparemap,
956 mtod(m_new, caddr_t), m_new->m_pkthdr.len, NULL,
957 BUS_DMA_NOWAIT) != 0) {
958 ACCOOM_PRINTF(0, ("%s: rx load failed\n",
959 mg->mg_hdlc->mc_dev.dv_xname));
960 m_freem(m_new);
961 return (ENOBUFS);
962 }
963 map = c->map;
964 c->map = mg->mg_rx_sparemap;
965 mg->mg_rx_sparemap = map;
966
967 bus_dmamap_sync(mg->mg_dmat, c->map, 0, c->map->dm_mapsize,
968 BUS_DMASYNC_PREREAD);
969
970 c->mbuf = m_new;
971 c->data = htole32(c->map->dm_segs[0].ds_addr);
972 c->status = htole32(MUSYCC_STATUS_NOPOLL |
973 MUSYCC_STATUS_LEN(m_new->m_pkthdr.len));
974
975 bus_dmamap_sync(mg->mg_dmat, mg->mg_listmap,
976 ((caddr_t)c - mg->mg_listkva), sizeof(struct dma_desc),
977 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
978
979 return (0);
980 }
981
982
983
984
985
986 int
987 musycc_encap(struct musycc_group *mg, struct mbuf *m_head, int c)
988 {
989 struct dma_desc *cur, *tmp;
990 bus_dmamap_t map;
991 bus_addr_t base;
992 u_int32_t status;
993 int i;
994
995 splassert(IPL_NET);
996
997 map = mg->mg_tx_sparemap;
998 if (bus_dmamap_load_mbuf(mg->mg_dmat, map, m_head,
999 BUS_DMA_NOWAIT) != 0) {
1000 ACCOOM_PRINTF(0, ("%s: musycc_encap: dmamap_load failed\n",
1001 mg->mg_channels[c]->cc_ifp->if_xname));
1002 return (ENOBUFS);
1003 }
1004
1005 cur = mg->mg_dma_d[c].tx_cur;
1006 base = mg->mg_listmap->dm_segs[0].ds_addr;
1007
1008 if (map->dm_nsegs + mg->mg_dma_d[c].tx_use >= mg->mg_dma_d[c].tx_cnt) {
1009 ACCOOM_PRINTF(1, ("%s: tx out of dma bufs\n",
1010 mg->mg_channels[c]->cc_ifp->if_xname));
1011 return (ENOBUFS);
1012 }
1013
1014 i = 0;
1015 while (i < map->dm_nsegs) {
1016 status =
1017 MUSYCC_STATUS_LEN(map->dm_segs[i].ds_len);
1018 if (cur != mg->mg_dma_d[c].tx_cur)
1019 status |= MUSYCC_STATUS_OWNER;
1020
1021 cur->status = htole32(status);
1022 cur->data = htole32(map->dm_segs[i].ds_addr);
1023
1024 bus_dmamap_sync(mg->mg_dmat, mg->mg_listmap,
1025 ((caddr_t)cur - mg->mg_listkva), sizeof(struct dma_desc),
1026 BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
1027
1028 if (++i >= map->dm_nsegs)
1029 break;
1030 cur = cur->nextdesc;
1031 }
1032
1033 bus_dmamap_sync(mg->mg_dmat, map, 0, map->dm_mapsize,
1034 BUS_DMASYNC_PREWRITE);
1035
1036 cur->mbuf = m_head;
1037 mg->mg_tx_sparemap = cur->map;
1038 cur->map = map;
1039 cur->status |= htole32(MUSYCC_STATUS_EOM);
1040 tmp = mg->mg_dma_d[c].tx_cur;
1041 mg->mg_dma_d[c].tx_cur = cur->nextdesc;
1042 mg->mg_dma_d[c].tx_use += i;
1043 mg->mg_dma_d[c].tx_pkts++;
1044
1045
1046
1047
1048
1049
1050 tmp->status |= htole32(MUSYCC_STATUS_OWNER);
1051 #if 0
1052
1053
1054
1055
1056
1057 musycc_txeom(mg, c);
1058 if (mg->mg_dma_d[c].tx_pend == tmp) {
1059
1060 printf("%s: tx needs kick\n",
1061 mg->mg_channels[c]->cc_ifp->if_xname);
1062 mg->mg_group->tx_headp[c] = htole32(base +
1063 (caddr_t)mg->mg_dma_d[c].tx_pend - mg->mg_listkva);
1064
1065 musycc_sreq(mg, c, MUSYCC_SREQ_SET(8), MUSYCC_SREQ_TX);
1066 }
1067 #endif
1068
1069 return (0);
1070 }
1071
1072
1073
1074
1075
1076
1077
1078 void
1079 musycc_start(struct ifnet *ifp)
1080 {
1081 struct musycc_group *mg;
1082 struct channel_softc *cc;
1083 struct mbuf *m = NULL;
1084 int s;
1085
1086 cc = ifp->if_softc;
1087 mg = cc->cc_group;
1088
1089 ACCOOM_PRINTF(3, ("musycc_start\n"));
1090 if (cc->cc_state != CHAN_RUNNING)
1091 return;
1092 if (ifp->if_flags & IFF_OACTIVE)
1093 return;
1094 if (sppp_isempty(ifp))
1095 return;
1096
1097 s = splnet();
1098 while ((m = sppp_pick(ifp)) != NULL) {
1099 if (musycc_encap(mg, m, cc->cc_channel)) {
1100 ifp->if_flags |= IFF_OACTIVE;
1101 break;
1102 }
1103
1104 #if NBPFILTER > 0
1105 if (ifp->if_bpf)
1106 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
1107 #endif
1108
1109
1110 sppp_dequeue(ifp);
1111 }
1112 splx(s);
1113
1114
1115
1116
1117 ifp->if_timer = 5;
1118
1119 return;
1120 }
1121
1122
1123
1124
1125
1126
1127
1128
1129 void
1130 musycc_watchdog(struct ifnet *ifp)
1131 {
1132 struct channel_softc *cc = ifp->if_softc;
1133
1134 log(LOG_ERR, "%s: device timeout\n", cc->cc_ifp->if_xname);
1135 ifp->if_oerrors++;
1136
1137 musycc_sreq(cc->cc_group, cc->cc_channel, MUSYCC_SREQ_SET(9),
1138 MUSYCC_SREQ_BOTH, EV_WATCHDOG);
1139 }
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150 void
1151 musycc_rxeom(struct musycc_group *mg, int channel, int forcekick)
1152 {
1153 struct mbuf *m;
1154 struct ifnet *ifp;
1155 struct dma_desc *cur_rx, *start_rx;
1156 int total_len = 0, consumed = 0;
1157 u_int32_t rxstat;
1158
1159 ACCOOM_PRINTF(3, ("musycc_rxeom\n"));
1160
1161 ifp = mg->mg_channels[channel]->cc_ifp;
1162
1163 start_rx = cur_rx = mg->mg_dma_d[channel].rx_prod;
1164 if (cur_rx == NULL)
1165 return;
1166 do {
1167 bus_dmamap_sync(mg->mg_dmat, mg->mg_listmap,
1168 ((caddr_t)cur_rx - mg->mg_listkva),
1169 sizeof(struct dma_desc),
1170 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1171
1172 rxstat = letoh32(cur_rx->status);
1173 if (!(rxstat & MUSYCC_STATUS_OWNER))
1174 break;
1175
1176 m = cur_rx->mbuf;
1177 cur_rx->mbuf = NULL;
1178 total_len = MUSYCC_STATUS_LEN(rxstat);
1179
1180
1181
1182
1183
1184
1185
1186
1187 if (rxstat & MUSYCC_STATUS_ERROR) {
1188 ifp->if_ierrors++;
1189 ACCOOM_PRINTF(1, ("%s: rx error %08x\n",
1190 ifp->if_xname, rxstat));
1191 musycc_newbuf(mg, cur_rx, m);
1192 cur_rx = cur_rx->nextdesc;
1193 consumed++;
1194 continue;
1195 }
1196
1197
1198 bus_dmamap_sync(mg->mg_dmat, cur_rx->map, 0,
1199 cur_rx->map->dm_mapsize, BUS_DMASYNC_POSTREAD);
1200 if (musycc_newbuf(mg, cur_rx, NULL) != 0) {
1201 cur_rx = cur_rx->nextdesc;
1202 consumed++;
1203 continue;
1204 }
1205
1206 cur_rx = cur_rx->nextdesc;
1207 consumed++;
1208
1209
1210 m->m_pkthdr.rcvif = ifp;
1211 m->m_pkthdr.len = m->m_len = total_len;
1212 ifp->if_ipackets++;
1213
1214 #if NBPFILTER > 0
1215 if (ifp->if_bpf)
1216 bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_IN);
1217 #endif
1218
1219
1220 sppp_input(ifp, m);
1221 } while (cur_rx != start_rx);
1222
1223 mg->mg_dma_d[channel].rx_prod = cur_rx;
1224
1225 if ((cur_rx == start_rx && consumed) || forcekick) {
1226
1227 ACCOOM_PRINTF(1, ("%s: rx kick, consumed %d pkts\n",
1228 mg->mg_channels[channel]->cc_ifp->if_xname, consumed));
1229 mg->mg_group->rx_headp[channel] = htole32(
1230 mg->mg_listmap->dm_segs[0].ds_addr +
1231 (caddr_t)cur_rx - mg->mg_listkva);
1232 musycc_sreq(mg, channel, MUSYCC_SREQ_SET(8),
1233 MUSYCC_SREQ_RX, EV_NULL);
1234 }
1235 }
1236
1237
1238
1239
1240
1241 void
1242 musycc_txeom(struct musycc_group *mg, int channel, int forcekick)
1243 {
1244 struct dma_desc *dd, *dd_pend;
1245 struct ifnet *ifp;
1246
1247 ACCOOM_PRINTF(3, ("musycc_txeom\n"));
1248
1249 ifp = mg->mg_channels[channel]->cc_ifp;
1250
1251 ifp->if_timer = 0;
1252
1253
1254
1255
1256
1257 for (dd = mg->mg_dma_d[channel].tx_pend;
1258 dd != mg->mg_dma_d[channel].tx_cur;
1259 dd = dd->nextdesc) {
1260 bus_dmamap_sync(mg->mg_dmat, mg->mg_listmap,
1261 ((caddr_t)dd - mg->mg_listkva), sizeof(struct dma_desc),
1262 BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
1263
1264 if (letoh32(dd->status) & MUSYCC_STATUS_OWNER)
1265
1266 break;
1267
1268 mg->mg_dma_d[channel].tx_use--;
1269
1270 dd->status = 0;
1271
1272
1273 if (dd->map->dm_nsegs != 0) {
1274 bus_dmamap_sync(mg->mg_dmat, dd->map, 0,
1275 dd->map->dm_mapsize, BUS_DMASYNC_POSTWRITE);
1276 bus_dmamap_unload(mg->mg_dmat, dd->map);
1277 }
1278 if (dd->mbuf != NULL) {
1279 m_freem(dd->mbuf);
1280 dd->mbuf = NULL;
1281 mg->mg_dma_d[channel].tx_pkts--;
1282 ifp->if_opackets++;
1283 }
1284 }
1285
1286 dd_pend = mg->mg_dma_d[channel].tx_pend;
1287 mg->mg_dma_d[channel].tx_pend = dd;
1288
1289 if (ifp->if_flags & IFF_OACTIVE && dd_pend != dd) {
1290 ifp->if_flags &= ~IFF_OACTIVE;
1291 musycc_start(ifp);
1292 }
1293
1294 if (forcekick) {
1295
1296 ACCOOM_PRINTF(1, ("%s: tx kick forced\n",
1297 mg->mg_channels[channel]->cc_ifp->if_xname));
1298 mg->mg_group->tx_headp[channel] =
1299 htole32(mg->mg_listmap->dm_segs[0].ds_addr +
1300 (caddr_t)mg->mg_dma_d[channel].tx_pend - mg->mg_listkva);
1301
1302 musycc_sreq(mg, channel, MUSYCC_SREQ_SET(8), MUSYCC_SREQ_TX,
1303 EV_NULL);
1304 }
1305 }
1306
1307 int
1308 musycc_intr(void *arg)
1309 {
1310 struct musycc_softc *mc = arg;
1311 struct musycc_group *mg;
1312 struct ifnet *ifp;
1313 u_int32_t intstatus, id;
1314 int i, n, chan;
1315
1316 intstatus = bus_space_read_4(mc->mc_st, mc->mc_sh, MUSYCC_INTRSTATUS);
1317
1318 if (intstatus & MUSYCC_INTCNT_MASK) {
1319 bus_dmamap_sync(mc->mc_dmat, mc->mc_intrmap,
1320 offsetof(struct musycc_intdesc, md_intrq[0]),
1321 MUSYCC_INTLEN * sizeof(u_int32_t), BUS_DMASYNC_POSTREAD);
1322
1323 ACCOOM_PRINTF(4, ("%s: interrupt status %08x\n",
1324 mc->mc_dev.dv_xname, intstatus));
1325
1326 n = MUSYCC_NEXTINT_GET(intstatus);
1327 for (i = 0; i < (intstatus & MUSYCC_INTCNT_MASK); i++) {
1328 id = letoh32(mc->mc_intrd->md_intrq[(n + i) %
1329 MUSYCC_INTLEN]);
1330 chan = MUSYCC_INTD_CHAN(id);
1331 mg = &mc->mc_groups[MUSYCC_INTD_GRP(id)];
1332
1333 ACCOOM_PRINTF(4, ("%s: interrupt %s\n",
1334 mc->mc_dev.dv_xname, musycc_intr_print(id)));
1335
1336 if (id & MUSYCC_INTD_ILOST)
1337 ACCOOM_PRINTF(0, ("%s: interrupt lost\n",
1338 mc->mc_dev.dv_xname));
1339
1340 switch (MUSYCC_INTD_EVENT(id)) {
1341 case MUSYCC_INTEV_NONE:
1342 break;
1343 case MUSYCC_INTEV_SACK:
1344 musycc_state_engine(mg, chan,
1345 mg->mg_sreq[mg->mg_sreqpend].event);
1346 mg->mg_sreqpend =
1347 (mg->mg_sreqpend + 1) & MUSYCC_SREQMASK;
1348 if (mg->mg_sreqpend != mg->mg_sreqprod)
1349 musycc_kick(mg);
1350 break;
1351 case MUSYCC_INTEV_EOM:
1352 case MUSYCC_INTEV_EOB:
1353 if (id & MUSYCC_INTD_DIR)
1354 musycc_txeom(mg, chan, 0);
1355 else
1356 musycc_rxeom(mg, chan, 0);
1357 break;
1358 default:
1359 ACCOOM_PRINTF(0, ("%s: unhandled event: %s\n",
1360 mc->mc_dev.dv_xname,
1361 musycc_intr_print(id)));
1362 break;
1363 }
1364 switch (MUSYCC_INTD_ERROR(id)) {
1365 case MUSYCC_INTERR_NONE:
1366 break;
1367 case MUSYCC_INTERR_COFA:
1368 if ((id & MUSYCC_INTD_DIR) == 0)
1369
1370 break;
1371 if (mg->mg_channels[chan]->cc_state !=
1372 CHAN_RUNNING) {
1373
1374
1375
1376
1377 break;
1378 }
1379 ACCOOM_PRINTF(0, ("%s: error: %s\n",
1380 mc->mc_dev.dv_xname,
1381 musycc_intr_print(id)));
1382 #if 0
1383
1384 musycc_txeom(mg, chan);
1385
1386
1387 musycc_dump_dma(mg);
1388 mg->mg_group->tx_headp[chan] =
1389 htole32(mg->mg_listmap->dm_segs[0].ds_addr +
1390 (caddr_t)mg->mg_dma_d[chan].tx_pend -
1391 mg->mg_listkva);
1392 musycc_dump_dma(mg);
1393
1394 musycc_sreq(mg, chan, MUSYCC_SREQ_SET(8),
1395 MUSYCC_SREQ_TX, CHAN_RUNNING);
1396 #endif
1397 break;
1398 case MUSYCC_INTERR_BUFF:
1399
1400
1401
1402
1403 log(LOG_ERR, "%s: internal FIFO %s\n",
1404 mg->mg_channels[chan]->cc_ifp->if_xname,
1405 id & MUSYCC_INTD_DIR ? "underflow" :
1406 "overflow");
1407
1408
1409 ifp = mg->mg_channels[chan]->cc_ifp;
1410 if (id & MUSYCC_INTD_DIR) {
1411 ifp->if_oerrors++;
1412 musycc_txeom(mg, chan, 1);
1413 } else {
1414 ifp->if_ierrors++;
1415 musycc_rxeom(mg, chan, 1);
1416 }
1417 break;
1418 case MUSYCC_INTERR_ONR:
1419 ACCOOM_PRINTF(0, ("%s: error: %s\n",
1420 mc->mc_dev.dv_xname,
1421 musycc_intr_print(id)));
1422
1423
1424 ifp = mg->mg_channels[chan]->cc_ifp;
1425 if (id & MUSYCC_INTD_DIR) {
1426 ifp->if_oerrors++;
1427 musycc_txeom(mg, chan, 1);
1428 } else {
1429 ifp->if_ierrors++;
1430 musycc_rxeom(mg, chan, 1);
1431 }
1432 break;
1433 case MUSYCC_INTERR_OOF:
1434
1435 break;
1436 default:
1437 ACCOOM_PRINTF(0, ("%s: unhandled error: %s\n",
1438 mc->mc_dev.dv_xname,
1439 musycc_intr_print(id)));
1440 break;
1441 }
1442 }
1443 bus_space_write_4(mc->mc_st, mc->mc_sh, MUSYCC_INTRSTATUS,
1444 MUSYCC_NEXTINT_SET((n + i) % MUSYCC_INTLEN));
1445 bus_space_barrier(mc->mc_st, mc->mc_sh, MUSYCC_INTRSTATUS,
1446 sizeof(u_int32_t), BUS_SPACE_BARRIER_WRITE);
1447 return (1);
1448 } else
1449 return (0);
1450 }
1451
1452 void
1453 musycc_kick(struct musycc_group *mg)
1454 {
1455
1456 bus_dmamap_sync(mg->mg_dmat, mg->mg_hdlc->mc_cfgmap,
1457 MUSYCC_GROUPBASE(mg->mg_gnum), sizeof(struct musycc_grpdesc),
1458 BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
1459
1460 ACCOOM_PRINTF(4, ("musycc_kick: group %d sreq[%d] req %08x\n",
1461 mg->mg_gnum, mg->mg_sreqpend, mg->mg_sreq[mg->mg_sreqpend].sreq));
1462
1463 bus_space_write_4(mg->mg_hdlc->mc_st, mg->mg_hdlc->mc_sh,
1464 MUSYCC_SERREQ(mg->mg_gnum), mg->mg_sreq[mg->mg_sreqpend].sreq);
1465 bus_space_barrier(mg->mg_hdlc->mc_st, mg->mg_hdlc->mc_sh,
1466 MUSYCC_SERREQ(mg->mg_gnum), sizeof(u_int32_t),
1467 BUS_SPACE_BARRIER_WRITE);
1468 }
1469
1470 void
1471 musycc_sreq(struct musycc_group *mg, int channel, u_int32_t req, int dir,
1472 enum musycc_event event)
1473 {
1474 #define MUSYCC_SREQINC(x, y) \
1475 do { \
1476 (x) = ((x) + 1) & MUSYCC_SREQMASK; \
1477 if (x == y) \
1478 panic("%s: sreq queue overflow", \
1479 mg->mg_hdlc->mc_dev.dv_xname); \
1480 } while (0)
1481
1482 struct timeval tv;
1483 int needskick;
1484
1485 needskick = (mg->mg_sreqpend == mg->mg_sreqprod);
1486 getmicrouptime(&tv);
1487
1488 ACCOOM_PRINTF(4, ("musycc_sreq: g# %d c# %d req %x dir %x\n",
1489 mg->mg_gnum, channel, req, dir));
1490
1491 if (dir & MUSYCC_SREQ_RX) {
1492 req &= ~MUSYCC_SREQ_TXDIR & ~MUSYCC_SREQ_MASK;
1493 req |= MUSYCC_SREQ_CHSET(channel);
1494 mg->mg_sreq[mg->mg_sreqprod].sreq = req;
1495 mg->mg_sreq[mg->mg_sreqprod].timeout = tv.tv_sec +
1496 MUSYCC_SREQTIMEOUT;
1497 if (dir == MUSYCC_SREQ_RX)
1498 mg->mg_sreq[mg->mg_sreqprod].event = event;
1499 else
1500 mg->mg_sreq[mg->mg_sreqprod].event = EV_NULL;
1501 MUSYCC_SREQINC(mg->mg_sreqprod, mg->mg_sreqpend);
1502 }
1503 if (dir & MUSYCC_SREQ_TX) {
1504 req &= ~MUSYCC_SREQ_MASK;
1505 req |= MUSYCC_SREQ_TXDIR;
1506 req |= MUSYCC_SREQ_CHSET(channel);
1507 mg->mg_sreq[mg->mg_sreqprod].timeout = tv.tv_sec +
1508 MUSYCC_SREQTIMEOUT;
1509 mg->mg_sreq[mg->mg_sreqprod].sreq = req;
1510 mg->mg_sreq[mg->mg_sreqprod].event = event;
1511 MUSYCC_SREQINC(mg->mg_sreqprod, mg->mg_sreqpend);
1512 }
1513
1514 if (needskick)
1515 musycc_kick(mg);
1516
1517 #undef MUSYCC_SREQINC
1518 }
1519
1520 void
1521 musycc_tick(struct channel_softc *cc)
1522 {
1523 struct musycc_group *mg = cc->cc_group;
1524 struct timeval tv;
1525
1526 if (mg->mg_sreqpend == mg->mg_sreqprod)
1527 return;
1528
1529 getmicrouptime(&tv);
1530 if (mg->mg_sreq[mg->mg_sreqpend].timeout < tv.tv_sec) {
1531 log(LOG_ERR, "%s: service request timeout\n",
1532 cc->cc_ifp->if_xname);
1533 mg->mg_sreqpend++;
1534
1535 while (mg->mg_sreq[mg->mg_sreqpend].timeout < tv.tv_sec &&
1536 mg->mg_sreqpend != mg->mg_sreqprod)
1537 mg->mg_sreqpend++;
1538
1539 if (mg->mg_sreqpend != mg->mg_sreqprod)
1540 musycc_kick(mg);
1541 }
1542 }
1543
1544
1545
1546
1547 int
1548 ebus_intr(void *arg)
1549 {
1550 struct musycc_softc *sc = arg;
1551
1552 printf("%s: interrupt\n", sc->mc_dev.dv_xname);
1553 return (1);
1554 }
1555
1556 int
1557 ebus_attach_device(struct ebus_dev *e, struct musycc_softc *mc,
1558 bus_size_t offset, bus_size_t size)
1559 {
1560 struct musycc_softc *ec = mc->mc_other;
1561
1562 e->base = offset << 2;
1563 e->size = size;
1564 e->st = ec->mc_st;
1565 return (bus_space_subregion(ec->mc_st, ec->mc_sh, offset << 2,
1566 size, &e->sh));
1567 }
1568
1569 u_int8_t
1570 ebus_read(struct ebus_dev *e, bus_size_t offset)
1571 {
1572 u_int8_t value;
1573
1574 value = bus_space_read_1(e->st, e->sh, offset << 2);
1575 bus_space_barrier(e->st, e->sh, 0, e->size,
1576 BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
1577 return (value);
1578 }
1579
1580 void
1581 ebus_write(struct ebus_dev *e, bus_size_t offset, u_int8_t value)
1582 {
1583 bus_space_write_1(e->st, e->sh, offset << 2, value);
1584 bus_space_barrier(e->st, e->sh, 0, e->size,
1585 BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
1586 }
1587
1588 void
1589 ebus_read_buf(struct ebus_dev *rom, bus_size_t offset, void *buf, size_t size)
1590 {
1591 u_int8_t *b = buf;
1592 size_t i;
1593
1594 for (i = 0; i < size; i++)
1595 b[i] = ebus_read(rom, offset + i);
1596 }
1597
1598 void
1599 ebus_set_led(struct channel_softc *cc, int on, u_int8_t value)
1600 {
1601 struct musycc_softc *sc = cc->cc_group->mg_hdlc->mc_other;
1602
1603 value &= MUSYCC_LED_MASK;
1604 value <<= cc->cc_group->mg_gnum * 2;
1605
1606 if (on)
1607 sc->mc_ledstate |= value;
1608 else
1609 sc->mc_ledstate &= ~value;
1610
1611 bus_space_write_1(sc->mc_st, sc->mc_sh, sc->mc_ledbase,
1612 sc->mc_ledstate);
1613 bus_space_barrier(sc->mc_st, sc->mc_sh, sc->mc_ledbase, 1,
1614 BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
1615 }
1616
1617
1618
1619
1620
1621 void
1622 musycc_attach_sppp(struct channel_softc *cc,
1623 int (*if_ioctl)(struct ifnet *, u_long, caddr_t))
1624 {
1625 struct ifnet *ifp;
1626
1627 ifp = &cc->cc_ppp.pp_if;
1628 cc->cc_ifp = ifp;
1629
1630 IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
1631 IFQ_SET_READY(&ifp->if_snd);
1632 ifp->if_mtu = PP_MTU;
1633 ifp->if_flags = IFF_POINTOPOINT | IFF_MULTICAST ;
1634 cc->cc_ppp.pp_flags |= PP_CISCO;
1635 cc->cc_ppp.pp_flags |= PP_KEEPALIVE;
1636 cc->cc_ppp.pp_framebytes = 3;
1637
1638 ifp->if_ioctl = if_ioctl;
1639 ifp->if_start = musycc_start;
1640 ifp->if_watchdog = musycc_watchdog;
1641
1642 if_attach(ifp);
1643 if_alloc_sadl(ifp);
1644 sppp_attach(ifp);
1645 #if NBPFILTER > 0
1646 bpfattach(&ifp->if_bpf, ifp, DLT_PPP, PPP_HEADER_LEN);
1647 #endif
1648
1649 }
1650
1651 struct channel_softc *
1652 musycc_channel_create(const char *name, u_int8_t locked)
1653 {
1654 struct channel_softc *cc;
1655
1656 cc = malloc(sizeof(*cc), M_DEVBUF, M_NOWAIT);
1657 if (!cc)
1658 return (NULL);
1659 bzero(cc, sizeof(*cc));
1660
1661 cc->cc_state = CHAN_FLOAT;
1662 cc->cc_locked = locked;
1663
1664
1665 cc->cc_tslots = 0xfffffffe;
1666 strlcpy(cc->cc_ppp.pp_if.if_xname, name,
1667 sizeof(cc->cc_ppp.pp_if.if_xname));
1668
1669 cc->cc_ppp.pp_if.if_softc = cc;
1670
1671 return (cc);
1672 }
1673
1674 int
1675 musycc_channel_attach(struct musycc_softc *mc, struct channel_softc *cc,
1676 struct device *dev, u_int8_t gnum)
1677 {
1678 struct musycc_group *mg;
1679 int i;
1680
1681 if (cc->cc_state != CHAN_FLOAT)
1682 return (-1);
1683
1684 if (gnum >= mc->mc_ngroups) {
1685 ACCOOM_PRINTF(0, ("%s: %s tries to attach to nonexistent group",
1686 mc->mc_dev.dv_xname, cc->cc_ifp->if_xname));
1687 return (-1);
1688 }
1689
1690 mg = &mc->mc_groups[gnum];
1691 for (i = 0; i < MUSYCC_NUMCHAN; i++)
1692 if (mg->mg_channels[i] == NULL) {
1693 mg->mg_channels[i] = cc;
1694 cc->cc_state = CHAN_IDLE;
1695 cc->cc_group = mg;
1696 cc->cc_channel = i;
1697 cc->cc_parent = dev;
1698 return (i);
1699 }
1700 return (-1);
1701 }
1702
1703 void
1704 musycc_channel_detach(struct ifnet *ifp)
1705 {
1706 struct channel_softc *cc = ifp->if_softc;
1707
1708 if (cc->cc_state != CHAN_FLOAT) {
1709 musycc_free_channel(cc->cc_group, cc->cc_channel);
1710 cc->cc_group->mg_channels[cc->cc_channel] = NULL;
1711 }
1712
1713 if_detach(ifp);
1714 }
1715
1716 #ifdef ACCOOM_DEBUG
1717 const char *musycc_events[] = {
1718 "NONE", "SACK", "EOB", "EOM", "EOP", "CHABT", "CHIC", "FREC",
1719 "SINC", "SDEC", "SFILT", "RFU", "RFU", "RFU", "RFU", "RFU"
1720 };
1721 const char *musycc_errors[] = {
1722 "NONE", "BUFF", "COFA", "ONR", "PROT", "RFU", "RFU", "RFU",
1723 "OOF", "FCS", "ALIGN", "ABT", "LNG", "SHT", "SUERR", "PERR"
1724 };
1725 const char *mu_proto[] = {
1726 "trans", "ss7", "hdlc16", "hdlc32", "rsvd4", "rsvd5", "rsvd6", "rsvd7"
1727 };
1728 const char *mu_mode[] = {
1729 "t1", "e1", "2*e1", "4*e1", "n64", "rsvd5", "rsvd6", "rsvd7"
1730 };
1731
1732 char musycc_intrbuf[48];
1733
1734 char *
1735 musycc_intr_print(u_int32_t id)
1736 {
1737 snprintf(musycc_intrbuf, sizeof(musycc_intrbuf),
1738 "ev %s er %s grp %d chan %d dir %s",
1739 musycc_events[MUSYCC_INTD_EVENT(id)],
1740 musycc_errors[MUSYCC_INTD_ERROR(id)],
1741 MUSYCC_INTD_GRP(id), MUSYCC_INTD_CHAN(id),
1742 id & MUSYCC_INTD_DIR ? "T" : "R");
1743 return (musycc_intrbuf);
1744 }
1745
1746 void
1747 musycc_dump_group(int level, struct musycc_group *mg)
1748 {
1749 struct musycc_grpdesc *md = mg->mg_group;
1750 u_int32_t d;
1751 int i;
1752
1753 if (level > accoom_debug)
1754 return;
1755
1756 printf("%s: dumping group %d\n",
1757 mg->mg_hdlc->mc_dev.dv_xname, mg->mg_gnum);
1758 printf("===========================================================\n");
1759 printf("global conf: %08x\n", letoh32(md->global_conf));
1760 d = letoh32(md->group_conf);
1761 printf("group conf: [%08x] %s %s %s int %s%s inhib BSD %s%s poll %d\n",
1762 d,
1763 d & MUSYCC_GRCFG_TXENBL ? "TX" : "",
1764 d & MUSYCC_GRCFG_RXENBL ? "RX" : "",
1765 d & MUSYCC_GRCFG_SUBDSBL ? "" : "SUB",
1766 d & MUSYCC_GRCFG_MSKOOF ? "" : "O",
1767 d & MUSYCC_GRCFG_MSKCOFA ? "" : "C",
1768 d & MUSYCC_GRCFG_INHTBSD ? "TX" : "",
1769 d & MUSYCC_GRCFG_INHRBSD ? "RX" : "",
1770 (d & MUSYCC_GRCFG_POLL64) == MUSYCC_GRCFG_POLL64 ? 64 :
1771 d & MUSYCC_GRCFG_POLL32 ? 32 :
1772 d & MUSYCC_GRCFG_POLL16 ? 16 : 1);
1773 d = letoh32(md->port_conf);
1774 printf("port conf: [%08x] %s %s %s %s %s %s %s\n", d,
1775 mu_mode[d & MUSYCC_PORT_MODEMASK],
1776 d & MUSYCC_PORT_TDAT_EDGE ? "TXE" : "!TXE",
1777 d & MUSYCC_PORT_TSYNC_EDGE ? "TXS" : "!TXS",
1778 d & MUSYCC_PORT_RDAT_EDGE ? "RXE" : "!RXE",
1779 d & MUSYCC_PORT_RSYNC_EDGE ? "RXS" : "!RXS",
1780 d & MUSYCC_PORT_ROOF_EDGE ? "ROOF" : "!ROOF",
1781 d & MUSYCC_PORT_TRITX ? "!tri-state" : "tri-state");
1782 printf("message len 1: %d 2: %d\n",
1783 letoh32(md->msglen_conf) & MUSYCC_MAXFRM_MASK,
1784 (letoh32(md->msglen_conf) >> MUSYCC_MAXFRM2_SHIFT) &
1785 MUSYCC_MAXFRM_MASK);
1786 printf("interrupt queue %x len %d\n", letoh32(md->int_queuep),
1787 letoh32(md->int_queuelen));
1788 printf("memory protection %x\n", letoh32(md->memprot));
1789 printf("===========================================================\n");
1790 printf("Timeslot Map:TX\t\tRX\n");
1791 for (i = 0; i < 128; i++) {
1792 if (md->tx_tsmap[i] & MUSYCC_TSLOT_ENABLED)
1793 printf("%d: %s%s%s[%02d]\t\t", i,
1794 md->tx_tsmap[i] & MUSYCC_TSLOT_ENABLED ? "C" : " ",
1795 md->tx_tsmap[i] & MUSYCC_TSLOT_SUB ? "S" : " ",
1796 md->tx_tsmap[i] & MUSYCC_TSLOT_56K ? "*" : " ",
1797 MUSYCC_TSLOT_CHAN(md->tx_tsmap[i]));
1798 else if (md->rx_tsmap[i] & MUSYCC_TSLOT_ENABLED)
1799 printf("%d: \t\t", i);
1800 if (md->rx_tsmap[i] & MUSYCC_TSLOT_ENABLED)
1801 printf("%s%s%s[%02d]\n",
1802 md->rx_tsmap[i] & MUSYCC_TSLOT_ENABLED ? "C" : " ",
1803 md->rx_tsmap[i] & MUSYCC_TSLOT_SUB ? "S" : " ",
1804 md->rx_tsmap[i] & MUSYCC_TSLOT_56K ? "*" : " ",
1805 MUSYCC_TSLOT_CHAN(md->rx_tsmap[i]));
1806 else
1807 printf("\n");
1808 }
1809 printf("===========================================================\n");
1810 printf("Channel config:\nTX\t\t\tRX\n");
1811 for (i = 0; i < 32; i++)
1812 if (md->tx_cconf[i] != 0) {
1813 d = letoh32(md->tx_cconf[i]);
1814 printf("%s%s%s%s%s%s%s %s [%x]\t",
1815 d & MUSYCC_CHAN_MSKBUFF ? "B" : " ",
1816 d & MUSYCC_CHAN_MSKEOM ? "E" : " ",
1817 d & MUSYCC_CHAN_MSKMSG ? "M" : " ",
1818 d & MUSYCC_CHAN_MSKIDLE ? "I" : " ",
1819 d & MUSYCC_CHAN_FCS ? "F" : "",
1820 d & MUSYCC_CHAN_MAXLEN1 ? "1" : "",
1821 d & MUSYCC_CHAN_MAXLEN2 ? "2" : "",
1822 mu_proto[MUSYCC_CHAN_PROTO_GET(d)],
1823 d);
1824 d = letoh32(md->rx_cconf[i]);
1825 printf("%s%s%s%s%s%s%s %s [%x]\n",
1826 d & MUSYCC_CHAN_MSKBUFF ? "B" : " ",
1827 d & MUSYCC_CHAN_MSKEOM ? "E" : " ",
1828 d & MUSYCC_CHAN_MSKMSG ? "M" : " ",
1829 d & MUSYCC_CHAN_MSKIDLE ? "I" : " ",
1830 d & MUSYCC_CHAN_FCS ? "F" : "",
1831 d & MUSYCC_CHAN_MAXLEN1 ? "1" : "",
1832 d & MUSYCC_CHAN_MAXLEN2 ? "2" : "",
1833 mu_proto[MUSYCC_CHAN_PROTO_GET(d)],
1834 d);
1835 }
1836 printf("===========================================================\n");
1837 musycc_dump_dma(level, mg, 0);
1838 }
1839
1840 void
1841 musycc_dump_desc(int level, struct musycc_group *mg)
1842 {
1843 #define READ4(x) \
1844 bus_space_read_4(mg->mg_hdlc->mc_st, mg->mg_hdlc->mc_sh, \
1845 MUSYCC_GROUPBASE(mg->mg_gnum) + (x))
1846 u_int32_t w;
1847 u_int8_t c1, c2;
1848 int i;
1849
1850 if (level > accoom_debug)
1851 return;
1852
1853 printf("%s: dumping descriptor %d at %p kva %08x + %x dma %08x\n",
1854 mg->mg_hdlc->mc_dev.dv_xname, mg->mg_gnum, mg->mg_group,
1855 mg->mg_hdlc->mc_cfgmap->dm_segs[0].ds_addr,
1856 MUSYCC_GROUPBASE(mg->mg_gnum), READ4(0));
1857 printf("===========================================================\n");
1858 printf("global conf: %08x\n", READ4(MUSYCC_GLOBALCONF));
1859 w = READ4(0x060c);
1860 printf("group conf: [%08x] %s %s %s int %s%s inhib BSD %s%s poll %d\n",
1861 w, w & MUSYCC_GRCFG_TXENBL ? "TX" : "",
1862 w & MUSYCC_GRCFG_RXENBL ? "RX" : "",
1863 w & MUSYCC_GRCFG_SUBDSBL ? "" : "SUB",
1864 w & MUSYCC_GRCFG_MSKOOF ? "" : "O",
1865 w & MUSYCC_GRCFG_MSKCOFA ? "" : "C",
1866 w & MUSYCC_GRCFG_INHTBSD ? "TX" : "",
1867 w & MUSYCC_GRCFG_INHRBSD ? "RX" : "",
1868 (w & MUSYCC_GRCFG_POLL64) == MUSYCC_GRCFG_POLL64 ? 64 :
1869 w & MUSYCC_GRCFG_POLL32 ? 32 :
1870 w & MUSYCC_GRCFG_POLL16 ? 16 : 1);
1871 w = READ4(0x0618);
1872 printf("port conf: [%08x] %s %s %s %s %s %s %s\n", w,
1873 mu_mode[w & MUSYCC_PORT_MODEMASK],
1874 w & MUSYCC_PORT_TDAT_EDGE ? "TXE" : "!TXE",
1875 w & MUSYCC_PORT_TSYNC_EDGE ? "TXS" : "!TXS",
1876 w & MUSYCC_PORT_RDAT_EDGE ? "RXE" : "!RXE",
1877 w & MUSYCC_PORT_RSYNC_EDGE ? "RXS" : "!RXS",
1878 w & MUSYCC_PORT_ROOF_EDGE ? "ROOF" : "!ROOF",
1879 w & MUSYCC_PORT_TRITX ? "!tri-state" : "tri-state");
1880 w = READ4(0x0614);
1881 printf("message len 1: %d 2: %d\n",
1882 w & MUSYCC_MAXFRM_MASK,
1883 (w >> MUSYCC_MAXFRM2_SHIFT) & MUSYCC_MAXFRM_MASK);
1884 printf("interrupt queue %x len %d\n", READ4(0x0604), READ4(0x0608));
1885 printf("memory protection %x\n", READ4(0x0610));
1886 printf("===========================================================\n");
1887 printf("Timeslot Map:TX\t\tRX\n");
1888 for (i = 0; i < 128; i++) {
1889 c1 = bus_space_read_1(mg->mg_hdlc->mc_st, mg->mg_hdlc->mc_sh,
1890 MUSYCC_GROUPBASE(mg->mg_gnum) + 0x0200 + i);
1891 c2 = bus_space_read_1(mg->mg_hdlc->mc_st, mg->mg_hdlc->mc_sh,
1892 MUSYCC_GROUPBASE(mg->mg_gnum) + 0x0400 + i);
1893 if (c1 & MUSYCC_TSLOT_ENABLED)
1894 printf("%d: %s%s%s[%02d]\t\t", i,
1895 c1 & MUSYCC_TSLOT_ENABLED ? "C" : " ",
1896 c1 & MUSYCC_TSLOT_SUB ? "S" : " ",
1897 c1 & MUSYCC_TSLOT_56K ? "*" : " ",
1898 MUSYCC_TSLOT_CHAN(c1));
1899 else if (c2 & MUSYCC_TSLOT_ENABLED)
1900 printf("%d: \t\t", i);
1901 if (c2 & MUSYCC_TSLOT_ENABLED)
1902 printf("%s%s%s[%02d]\n",
1903 c2 & MUSYCC_TSLOT_ENABLED ? "C" : " ",
1904 c2 & MUSYCC_TSLOT_SUB ? "S" : " ",
1905 c2 & MUSYCC_TSLOT_56K ? "*" : " ",
1906 MUSYCC_TSLOT_CHAN(c2));
1907 else
1908 printf("\n");
1909 }
1910 printf("===========================================================\n");
1911 printf("Channel config:\nTX\t\t\t\tRX\n");
1912 for (i = 0; i < 32; i++) {
1913 w = READ4(0x0380 + i * 4);
1914 if (w != 0) {
1915 printf("%s%s%s%s%s%s%s %s [%08x]\t",
1916 w & MUSYCC_CHAN_MSKBUFF ? "B" : " ",
1917 w & MUSYCC_CHAN_MSKEOM ? "E" : " ",
1918 w & MUSYCC_CHAN_MSKMSG ? "M" : " ",
1919 w & MUSYCC_CHAN_MSKIDLE ? "I" : " ",
1920 w & MUSYCC_CHAN_FCS ? "F" : "",
1921 w & MUSYCC_CHAN_MAXLEN1 ? "1" : "",
1922 w & MUSYCC_CHAN_MAXLEN2 ? "2" : "",
1923 mu_proto[MUSYCC_CHAN_PROTO_GET(w)],
1924 w);
1925 w = READ4(0x0580 + i * 4);
1926 printf("%s%s%s%s%s%s%s %s [%08x]\n",
1927 w & MUSYCC_CHAN_MSKBUFF ? "B" : " ",
1928 w & MUSYCC_CHAN_MSKEOM ? "E" : " ",
1929 w & MUSYCC_CHAN_MSKMSG ? "M" : " ",
1930 w & MUSYCC_CHAN_MSKIDLE ? "I" : " ",
1931 w & MUSYCC_CHAN_FCS ? "F" : "",
1932 w & MUSYCC_CHAN_MAXLEN1 ? "1" : "",
1933 w & MUSYCC_CHAN_MAXLEN2 ? "2" : "",
1934 mu_proto[MUSYCC_CHAN_PROTO_GET(w)],
1935 w);
1936 }
1937 }
1938 printf("===========================================================\n");
1939 musycc_dump_dma(level, mg, 0);
1940
1941 }
1942
1943 void
1944 musycc_dump_dma(int level, struct musycc_group *mg, int dir)
1945 {
1946 struct musycc_grpdesc *md = mg->mg_group;
1947 struct dma_desc *dd;
1948 bus_addr_t base, addr;
1949 int i;
1950
1951 if (level > accoom_debug)
1952 return;
1953
1954 printf("DMA Pointers:\n%8s %8s %8s %8s\n",
1955 "tx head", "tx msg", "rx head", "rx msg");
1956 for (i = 0; i < 32; i++) {
1957 if (md->tx_headp[i] == 0 && md->rx_headp[i] == 0)
1958 continue;
1959 printf("%08x %08x %08x %08x\n",
1960 md->tx_headp[i], md->tx_msgp[i],
1961 md->rx_headp[i], md->rx_msgp[i]);
1962 }
1963
1964 base = mg->mg_listmap->dm_segs[0].ds_addr;
1965 for (i = 0; dir & MUSYCC_SREQ_TX && i < 32; i++) {
1966 if (md->tx_headp[i] == 0)
1967 continue;
1968
1969 printf("==================================================\n");
1970 printf("TX DMA Ring for channel %d\n", i);
1971 printf("pend: %p cur: %p cnt: %d use: %d pkgs: %d\n",
1972 mg->mg_dma_d[i].tx_pend, mg->mg_dma_d[i].tx_cur,
1973 mg->mg_dma_d[i].tx_cnt, mg->mg_dma_d[i].tx_use,
1974 mg->mg_dma_d[i].tx_pkts);
1975 printf(" %10s %8s %8s %8s %8s %10s\n",
1976 "addr", "paddr", "next", "status", "data", "mbuf");
1977 dd = mg->mg_dma_d[i].tx_pend;
1978 do {
1979 addr = htole32(base + ((caddr_t)dd - mg->mg_listkva));
1980 printf("%s %p %08x %08x %08x %08x %p\n",
1981 dd == mg->mg_dma_d[i].tx_pend ? ">" :
1982 dd == mg->mg_dma_d[i].tx_cur ? "*" : " ",
1983 dd, addr, dd->next, dd->status,
1984 dd->data, dd->mbuf);
1985 dd = dd->nextdesc;
1986 } while (dd != mg->mg_dma_d[i].tx_pend);
1987 }
1988 for (i = 0; dir & MUSYCC_SREQ_RX && i < 32; i++) {
1989 if (md->rx_headp[i] == 0)
1990 continue;
1991
1992 printf("==================================================\n");
1993 printf("RX DMA Ring for channel %d\n", i);
1994 printf("prod: %p cnt: %d\n",
1995 mg->mg_dma_d[i].rx_prod, mg->mg_dma_d[i].rx_cnt);
1996 printf(" %8s %8s %8s %8s %10s\n",
1997 "addr", "paddr", "next", "status", "data", "mbuf");
1998 dd = mg->mg_dma_d[i].rx_prod;
1999 do {
2000 addr = htole32(base + ((caddr_t)dd - mg->mg_listkva));
2001 printf("%p %08x %08x %08x %08x %p\n", dd, addr,
2002 dd->next, dd->status, dd->data, dd->mbuf);
2003 dd = dd->nextdesc;
2004 } while (dd != mg->mg_dma_d[i].rx_prod);
2005 }
2006 }
2007 #endif