FreeBSD/Linux Kernel Cross Reference
sys/dev/ic/iavc.c
1 /* $NetBSD: iavc.c,v 1.7.14.1 2010/12/02 23:42:37 snj Exp $ */
2
3 /*
4 * Copyright (c) 2001-2003 Cubical Solutions Ltd. All rights reserved.
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 AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY 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 * The AVM ISDN controllers' card specific support routines.
28 *
29 * $FreeBSD: src/sys/i4b/capi/iavc/iavc_card.c,v 1.1.2.1 2001/08/10 14:08:34 obrien Exp $
30 */
31
32 #include <sys/cdefs.h>
33 __KERNEL_RCSID(0, "$NetBSD: iavc.c,v 1.7.14.1 2010/12/02 23:42:37 snj Exp $");
34
35 #include <sys/param.h>
36 #include <sys/kernel.h>
37 #include <sys/systm.h>
38 #include <sys/mbuf.h>
39 #include <sys/socket.h>
40 #include <sys/device.h>
41 #include <sys/callout.h>
42 #include <sys/reboot.h>
43 #include <net/if.h>
44
45 #include <sys/bus.h>
46
47 #include <netisdn/i4b_debug.h>
48 #include <netisdn/i4b_ioctl.h>
49 #include <netisdn/i4b_trace.h>
50 #include <netisdn/i4b_global.h>
51 #include <netisdn/i4b_l3l4.h>
52 #include <netisdn/i4b_mbuf.h>
53 #include <netisdn/i4b_capi.h>
54 #include <netisdn/i4b_capi_msgs.h>
55
56 #include <dev/ic/iavcvar.h>
57 #include <dev/ic/iavcreg.h>
58
59 /*
60 // AVM B1 (active BRI, PIO mode)
61 */
62
63 int
64 iavc_b1_detect(iavc_softc_t *sc)
65 {
66 if ((iavc_read_port(sc, B1_INSTAT) & 0xfc) ||
67 (iavc_read_port(sc, B1_OUTSTAT) & 0xfc))
68 return (1);
69
70 b1io_outp(sc, B1_INSTAT, 0x02);
71 b1io_outp(sc, B1_OUTSTAT, 0x02);
72 if ((iavc_read_port(sc, B1_INSTAT) & 0xfe) != 2 ||
73 (iavc_read_port(sc, B1_OUTSTAT) & 0xfe) != 2)
74 return (2);
75
76 b1io_outp(sc, B1_INSTAT, 0x00);
77 b1io_outp(sc, B1_OUTSTAT, 0x00);
78 if ((iavc_read_port(sc, B1_INSTAT) & 0xfe) ||
79 (iavc_read_port(sc, B1_OUTSTAT) & 0xfe))
80 return (3);
81
82 return (0); /* found */
83 }
84
85 void
86 iavc_b1_disable_irq(iavc_softc_t *sc)
87 {
88 b1io_outp(sc, B1_INSTAT, 0x00);
89 }
90
91 void
92 iavc_b1_reset(iavc_softc_t *sc)
93 {
94 b1io_outp(sc, B1_RESET, 0);
95 DELAY(55*2*1000);
96
97 b1io_outp(sc, B1_RESET, 1);
98 DELAY(55*2*1000);
99
100 b1io_outp(sc, B1_RESET, 0);
101 DELAY(55*2*1000);
102 }
103
104 /*
105 // Newer PCI-based B1's, and T1's, supports DMA
106 */
107
108 int
109 iavc_b1dma_detect(iavc_softc_t *sc)
110 {
111 AMCC_WRITE(sc, AMCC_MCSR, 0);
112 DELAY(10*1000);
113 AMCC_WRITE(sc, AMCC_MCSR, 0x0f000000);
114 DELAY(10*1000);
115 AMCC_WRITE(sc, AMCC_MCSR, 0);
116 DELAY(42*1000);
117
118 AMCC_WRITE(sc, AMCC_RXLEN, 0);
119 AMCC_WRITE(sc, AMCC_TXLEN, 0);
120 sc->sc_csr = 0;
121 AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
122
123 if (AMCC_READ(sc, AMCC_INTCSR) != 0)
124 return 1;
125
126 AMCC_WRITE(sc, AMCC_RXPTR, 0xffffffff);
127 AMCC_WRITE(sc, AMCC_TXPTR, 0xffffffff);
128 if ((AMCC_READ(sc, AMCC_RXPTR) != 0xfffffffc) ||
129 (AMCC_READ(sc, AMCC_TXPTR) != 0xfffffffc))
130 return 2;
131
132 AMCC_WRITE(sc, AMCC_RXPTR, 0);
133 AMCC_WRITE(sc, AMCC_TXPTR, 0);
134 if ((AMCC_READ(sc, AMCC_RXPTR) != 0) ||
135 (AMCC_READ(sc, AMCC_TXPTR) != 0))
136 return 3;
137
138 iavc_write_port(sc, 0x10, 0x00);
139 iavc_write_port(sc, 0x07, 0x00);
140
141 iavc_write_port(sc, 0x02, 0x02);
142 iavc_write_port(sc, 0x03, 0x02);
143
144 if (((iavc_read_port(sc, 0x02) & 0xfe) != 0x02) ||
145 (iavc_read_port(sc, 0x03) != 0x03))
146 return 4;
147
148 iavc_write_port(sc, 0x02, 0x00);
149 iavc_write_port(sc, 0x03, 0x00);
150
151 if (((iavc_read_port(sc, 0x02) & 0xfe) != 0x00) ||
152 (iavc_read_port(sc, 0x03) != 0x01))
153 return 5;
154
155 return (0); /* found */
156 }
157
158 void
159 iavc_b1dma_reset(iavc_softc_t *sc)
160 {
161 int s = splnet();
162
163 sc->sc_csr = 0;
164 AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
165 AMCC_WRITE(sc, AMCC_MCSR, 0);
166 AMCC_WRITE(sc, AMCC_RXLEN, 0);
167 AMCC_WRITE(sc, AMCC_TXLEN, 0);
168
169 iavc_write_port(sc, 0x10, 0x00); /* XXX magic numbers from */
170 iavc_write_port(sc, 0x07, 0x00); /* XXX the linux driver */
171
172 splx(s);
173
174 AMCC_WRITE(sc, AMCC_MCSR, 0);
175 DELAY(10 * 1000);
176 AMCC_WRITE(sc, AMCC_MCSR, 0x0f000000);
177 DELAY(10 * 1000);
178 AMCC_WRITE(sc, AMCC_MCSR, 0);
179 DELAY(42 * 1000);
180 }
181
182 /*
183 // AVM T1 (active PRI)
184 */
185
186 #define b1dma_tx_empty(sc) (b1io_read_reg((sc), T1_OUTSTAT) & 1)
187 #define b1dma_rx_full(sc) (b1io_read_reg((sc), T1_INSTAT) & 1)
188
189 static int b1dma_tolink(iavc_softc_t *sc, void *buf, int len)
190 {
191 volatile int spin;
192 char *s = (char*) buf;
193 while (len--) {
194 spin = 0;
195 while (!b1dma_tx_empty(sc) && spin < 100000)
196 spin++;
197 if (!b1dma_tx_empty(sc))
198 return -1;
199 t1io_outp(sc, 1, *s++);
200 }
201 return 0;
202 }
203
204 static int b1dma_fromlink(iavc_softc_t *sc, void *buf, int len)
205 {
206 volatile int spin;
207 char *s = (char*) buf;
208 while (len--) {
209 spin = 0;
210 while (!b1dma_rx_full(sc) && spin < 100000)
211 spin++;
212 if (!b1dma_rx_full(sc))
213 return -1;
214 *s++ = t1io_inp(sc, 0);
215 }
216 return 0;
217 }
218
219 static int WriteReg(iavc_softc_t *sc, u_int32_t reg, u_int8_t val)
220 {
221 u_int8_t cmd = 0;
222 if (b1dma_tolink(sc, &cmd, 1) == 0 &&
223 b1dma_tolink(sc, ®, 4) == 0) {
224 u_int32_t tmp = val;
225 return b1dma_tolink(sc, &tmp, 4);
226 }
227 return -1;
228 }
229
230 static u_int8_t ReadReg(iavc_softc_t *sc, u_int32_t reg)
231 {
232 u_int8_t cmd = 1;
233 if (b1dma_tolink(sc, &cmd, 1) == 0 &&
234 b1dma_tolink(sc, ®, 4) == 0) {
235 u_int32_t tmp;
236 if (b1dma_fromlink(sc, &tmp, 4) == 0)
237 return (u_int8_t) tmp;
238 }
239 return 0xff;
240 }
241
242 int
243 iavc_t1_detect(iavc_softc_t *sc)
244 {
245 int ret = iavc_b1dma_detect(sc);
246 if (ret) return ret;
247
248 if ((WriteReg(sc, 0x80001000, 0x11) != 0) ||
249 (WriteReg(sc, 0x80101000, 0x22) != 0) ||
250 (WriteReg(sc, 0x80201000, 0x33) != 0) ||
251 (WriteReg(sc, 0x80301000, 0x44) != 0))
252 return 6;
253
254 if ((ReadReg(sc, 0x80001000) != 0x11) ||
255 (ReadReg(sc, 0x80101000) != 0x22) ||
256 (ReadReg(sc, 0x80201000) != 0x33) ||
257 (ReadReg(sc, 0x80301000) != 0x44))
258 return 7;
259
260 if ((WriteReg(sc, 0x80001000, 0x55) != 0) ||
261 (WriteReg(sc, 0x80101000, 0x66) != 0) ||
262 (WriteReg(sc, 0x80201000, 0x77) != 0) ||
263 (WriteReg(sc, 0x80301000, 0x88) != 0))
264 return 8;
265
266 if ((ReadReg(sc, 0x80001000) != 0x55) ||
267 (ReadReg(sc, 0x80101000) != 0x66) ||
268 (ReadReg(sc, 0x80201000) != 0x77) ||
269 (ReadReg(sc, 0x80301000) != 0x88))
270 return 9;
271
272 return 0; /* found */
273 }
274
275 void
276 iavc_t1_disable_irq(iavc_softc_t *sc)
277 {
278 iavc_write_port(sc, T1_IRQMASTER, 0x00);
279 }
280
281 void
282 iavc_t1_reset(iavc_softc_t *sc)
283 {
284 iavc_b1_reset(sc);
285 iavc_write_port(sc, B1_INSTAT, 0x00);
286 iavc_write_port(sc, B1_OUTSTAT, 0x00);
287 iavc_write_port(sc, T1_IRQMASTER, 0x00);
288 iavc_write_port(sc, T1_RESETBOARD, 0x0f);
289 }
290
291 /* Forward declarations of local subroutines... */
292
293 static int iavc_send_init(iavc_softc_t *);
294
295 static void iavc_handle_rx(iavc_softc_t *);
296 static void iavc_start_tx(iavc_softc_t *);
297
298 static uint32_t iavc_tx_capimsg(iavc_softc_t *, struct mbuf *);
299 static uint32_t iavc_tx_ctrlmsg(iavc_softc_t *, struct mbuf *);
300
301 /*
302 // Callbacks from the upper (capi) layer:
303 // --------------------------------------
304 //
305 // iavc_load
306 // Resets the board and loads the firmware, then initiates
307 // board startup.
308 //
309 // iavc_register
310 // Registers a CAPI application id.
311 //
312 // iavc_release
313 // Releases a CAPI application id.
314 //
315 // iavc_send
316 // Sends a capi message.
317 */
318
319 int iavc_load(capi_softc_t *capi_sc, int len, u_int8_t *cp)
320 {
321 iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx;
322 u_int8_t val;
323
324 aprint_debug_dev(&sc->sc_dev, "reset card ....\n");
325
326 if (sc->sc_dma)
327 iavc_b1dma_reset(sc); /* PCI cards */
328 else if (sc->sc_t1)
329 iavc_t1_reset(sc); /* ISA attachment T1 */
330 else
331 iavc_b1_reset(sc); /* ISA attachment B1 */
332
333 DELAY(1000);
334
335 aprint_debug_dev(&sc->sc_dev, "start loading %d bytes firmware\n", len);
336
337 while (len && b1io_save_put_byte(sc, *cp++) == 0)
338 len--;
339
340 if (len) {
341 aprint_error_dev(&sc->sc_dev, "loading failed, can't write to card, len = %d\n", len);
342 return (EIO);
343 }
344
345 aprint_debug_dev(&sc->sc_dev, "firmware loaded, wait for ACK\n");
346
347 if(sc->sc_capi.card_type == CARD_TYPEC_AVM_B1_ISA)
348 iavc_put_byte(sc, SEND_POLL);
349 else
350 iavc_put_byte(sc, SEND_POLLACK);
351
352 for (len = 0; len < 1000 && !iavc_rx_full(sc); len++)
353 DELAY(100);
354
355 if (!iavc_rx_full(sc)) {
356 aprint_error_dev(&sc->sc_dev, "loading failed, no ack\n");
357 return (EIO);
358 }
359
360 val = iavc_get_byte(sc);
361
362 if ((sc->sc_dma && val != RECEIVE_POLLDWORD) ||
363 (!sc->sc_dma && val != RECEIVE_POLL)) {
364 aprint_error_dev(&sc->sc_dev, "loading failed, bad ack = %02x\n", val);
365 return (EIO);
366 }
367
368 aprint_debug_dev(&sc->sc_dev, "got ACK = 0x%02x\n", val);
369
370 /* Start the DMA engine */
371 if (sc->sc_dma) {
372 int s;
373
374 s = splnet();
375
376 sc->sc_csr = AVM_FLAG;
377 AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
378 AMCC_WRITE(sc, AMCC_MCSR, (EN_A2P_TRANSFERS|EN_P2A_TRANSFERS|
379 A2P_HI_PRIORITY|P2A_HI_PRIORITY|
380 RESET_A2P_FLAGS|RESET_P2A_FLAGS));
381
382 iavc_write_port(sc, 0x07, 0x30); /* XXX magic numbers from */
383 iavc_write_port(sc, 0x10, 0xf0); /* XXX the linux driver */
384
385 bus_dmamap_sync(sc->dmat, sc->rx_map, 0, sc->rx_map->dm_mapsize,
386 BUS_DMASYNC_PREREAD);
387
388 sc->sc_recv1 = 0;
389 AMCC_WRITE(sc, AMCC_RXPTR, sc->rx_map->dm_segs[0].ds_addr);
390 AMCC_WRITE(sc, AMCC_RXLEN, 4);
391 sc->sc_csr |= EN_RX_TC_INT|EN_TX_TC_INT;
392 AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
393
394 splx(s);
395 }
396
397 #ifdef notyet
398 /* good happy place */
399 if(sc->sc_capi.card_type == CARD_TYPEC_AVM_B1_ISA)
400 b1isa_setup_irq(sc);
401 #endif
402
403 iavc_send_init(sc);
404
405 return 0;
406 }
407
408 int iavc_register(capi_softc_t *capi_sc, int applid, int nchan)
409 {
410 iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx;
411 struct mbuf *m = i4b_Dgetmbuf(23);
412 u_int8_t *p;
413
414 if (!m) {
415 aprint_error("iavc%d: can't get memory\n", sc->sc_unit);
416 return (ENOMEM);
417 }
418
419 /*
420 * byte 0x12 = SEND_REGISTER
421 * dword ApplId
422 * dword NumMessages
423 * dword NumB3Connections 0..nbch
424 * dword NumB3Blocks
425 * dword B3Size
426 */
427
428 p = amcc_put_byte(mtod(m, u_int8_t*), 0);
429 p = amcc_put_byte(p, 0);
430 p = amcc_put_byte(p, SEND_REGISTER);
431 p = amcc_put_word(p, applid);
432 #if 0
433 p = amcc_put_word(p, 1024 + (nchan + 1));
434 #else
435 p = amcc_put_word(p, 1024 * (nchan + 1));
436 #endif
437 p = amcc_put_word(p, nchan);
438 p = amcc_put_word(p, 8);
439 p = amcc_put_word(p, 2048);
440
441 IF_ENQUEUE(&sc->sc_txq, m);
442
443 iavc_start_tx(sc);
444
445 return 0;
446 }
447
448 int iavc_release(capi_softc_t *capi_sc, int applid)
449 {
450 iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx;
451 struct mbuf *m = i4b_Dgetmbuf(7);
452 u_int8_t *p;
453
454 if (!m) {
455 aprint_error_dev(&sc->sc_dev, "can't get memory\n");
456 return (ENOMEM);
457 }
458
459 /*
460 * byte 0x14 = SEND_RELEASE
461 * dword ApplId
462 */
463
464 p = amcc_put_byte(mtod(m, u_int8_t*), 0);
465 p = amcc_put_byte(p, 0);
466 p = amcc_put_byte(p, SEND_RELEASE);
467 p = amcc_put_word(p, applid);
468
469 IF_ENQUEUE(&sc->sc_txq, m);
470
471 iavc_start_tx(sc);
472 return 0;
473 }
474
475 int iavc_send(capi_softc_t *capi_sc, struct mbuf *m)
476 {
477 iavc_softc_t *sc = (iavc_softc_t*) capi_sc->ctx;
478
479 if (sc->sc_state != IAVC_UP) {
480 aprint_error_dev(&sc->sc_dev, "attempt to send before device up\n");
481
482 if (m->m_next) i4b_Bfreembuf(m->m_next);
483 i4b_Dfreembuf(m);
484
485 return (ENXIO);
486 }
487
488 if (IF_QFULL(&sc->sc_txq)) {
489 IF_DROP(&sc->sc_txq);
490
491 aprint_error_dev(&sc->sc_dev, "tx overflow, message dropped\n");
492
493 if (m->m_next) i4b_Bfreembuf(m->m_next);
494 i4b_Dfreembuf(m);
495
496 } else {
497 IF_ENQUEUE(&sc->sc_txq, m);
498
499 iavc_start_tx(sc);
500 }
501
502 return 0;
503 }
504
505 /*
506 // Functions called by ourself during the initialization sequence:
507 // ---------------------------------------------------------------
508 //
509 // iavc_send_init
510 // Sends the system initialization message to a newly loaded
511 // board, and sets state to INIT.
512 */
513
514 static int iavc_send_init(iavc_softc_t *sc)
515 {
516 struct mbuf *m = i4b_Dgetmbuf(15);
517 u_int8_t *p;
518 int s;
519
520 if (!m) {
521 aprint_error_dev(&sc->sc_dev, "can't get memory\n");
522 return (ENOMEM);
523 }
524
525 /*
526 * byte 0x11 = SEND_INIT
527 * dword NumApplications
528 * dword NumNCCIs
529 * dword BoardNumber
530 */
531
532 p = amcc_put_byte(mtod(m, u_int8_t*), 0);
533 p = amcc_put_byte(p, 0);
534 p = amcc_put_byte(p, SEND_INIT);
535 p = amcc_put_word(p, 1); /* XXX MaxAppl XXX */
536 p = amcc_put_word(p, sc->sc_capi.sc_nbch);
537 p = amcc_put_word(p, sc->sc_unit);
538
539 s = splnet();
540 IF_ENQUEUE(&sc->sc_txq, m);
541
542 iavc_start_tx(sc);
543
544 sc->sc_state = IAVC_INIT;
545 splx(s);
546 return 0;
547 }
548
549 /*
550 // Functions called during normal operation:
551 // -----------------------------------------
552 //
553 // iavc_receive_init
554 // Reads the initialization reply and calls capi_ll_control().
555 //
556 // iavc_receive_new_ncci
557 // Reads a new NCCI notification and calls capi_ll_control().
558 //
559 // iavc_receive_free_ncci
560 // Reads a freed NCCI notification and calls capi_ll_control().
561 //
562 // iavc_receive_task_ready
563 // Reads a task ready message -- which should not occur XXX.
564 //
565 // iavc_receive_debugmsg
566 // Reads a debug message -- which should not occur XXX.
567 //
568 // iavc_receive_start
569 // Reads a START TRANSMIT message and unblocks device.
570 //
571 // iavc_receive_stop
572 // Reads a STOP TRANSMIT message and blocks device.
573 //
574 // iavc_receive
575 // Reads an incoming message and calls capi_ll_receive().
576 */
577
578 static int iavc_receive_init(iavc_softc_t *sc, u_int8_t *dmabuf)
579 {
580 u_int32_t Length;
581 u_int8_t *p;
582 u_int8_t *cardtype, *serial, *profile, *vers, *caps, *prot;
583
584 if (sc->sc_dma) {
585 p = amcc_get_word(dmabuf, &Length);
586 } else {
587 Length = iavc_get_slice(sc, sc->sc_recvbuf);
588 p = sc->sc_recvbuf;
589 }
590
591 #if 0
592 {
593 int len = 0;
594 printf("%s: rx_init: ", device_xname(&sc->sc_dev));
595 while (len < Length) {
596 printf(" %02x", p[len]);
597 if (len && (len % 16) == 0) printf("\n");
598 len++;
599 }
600 if (len % 16) printf("\n");
601 }
602 #endif
603
604 vers = (p + 1);
605 p += (*p + 1); /* driver version */
606 cardtype = (p + 1);
607 p += (*p + 1); /* card type */
608 p += (*p + 1); /* hardware ID */
609 serial = (p + 1);
610 p += (*p + 1); /* serial number */
611 caps = (p + 1);
612 p += (*p + 1); /* supported options */
613 prot = (p + 1);
614 p += (*p + 1); /* supported protocols */
615 profile = (p + 1);
616
617 if (cardtype && serial && profile) {
618 int nbch = ((profile[3]<<8) | profile[2]);
619
620 aprint_normal_dev(&sc->sc_dev, "AVM %s, s/n %s, %d chans, f/w rev %s, prot %s\n",
621 cardtype, serial, nbch, vers, prot);
622 aprint_verbose_dev(&sc->sc_dev, "%s\n", caps);
623
624 capi_ll_control(&sc->sc_capi, CAPI_CTRL_PROFILE, (int) profile);
625
626 } else {
627 printf("%s: no profile data in info response?\n", device_xname(&sc->sc_dev));
628 }
629
630 sc->sc_blocked = 1; /* controller will send START when ready */
631 return 0;
632 }
633
634 static int iavc_receive_start(iavc_softc_t *sc)
635 {
636 struct mbuf *m = i4b_Dgetmbuf(3);
637 u_int8_t *p;
638
639 if (sc->sc_blocked && sc->sc_state == IAVC_UP)
640 printf("%s: receive_start\n", device_xname(&sc->sc_dev));
641
642 if (!m) {
643 aprint_error_dev(&sc->sc_dev, "can't get memory\n");
644 return (ENOMEM);
645 }
646
647 /*
648 * byte 0x73 = SEND_POLLACK
649 */
650
651 p = amcc_put_byte(mtod(m, u_int8_t*), 0);
652 p = amcc_put_byte(p, 0);
653 p = amcc_put_byte(p, SEND_POLLACK);
654
655 IF_PREPEND(&sc->sc_txq, m);
656
657 NDBGL4(L4_IAVCDBG, "%s: blocked = %d, state = %d",
658 device_xname(&sc->sc_dev), sc->sc_blocked, sc->sc_state);
659
660 sc->sc_blocked = 0;
661 iavc_start_tx(sc);
662
663 /* If this was our first START, register our readiness */
664 if (sc->sc_state != IAVC_UP) {
665 sc->sc_state = IAVC_UP;
666 capi_ll_control(&sc->sc_capi, CAPI_CTRL_READY, 1);
667 }
668
669 return 0;
670 }
671
672 static int iavc_receive_stop(iavc_softc_t *sc)
673 {
674 printf("%s: receive_stop\n", device_xname(&sc->sc_dev));
675 sc->sc_blocked = 1;
676 return 0;
677 }
678
679 static int iavc_receive_new_ncci(iavc_softc_t *sc, u_int8_t *dmabuf)
680 {
681 u_int32_t ApplId, NCCI, WindowSize;
682
683 if (sc->sc_dma) {
684 dmabuf = amcc_get_word(dmabuf, &ApplId);
685 dmabuf = amcc_get_word(dmabuf, &NCCI);
686 dmabuf = amcc_get_word(dmabuf, &WindowSize);
687 } else {
688 ApplId = iavc_get_word(sc);
689 NCCI = iavc_get_word(sc);
690 WindowSize = iavc_get_word(sc);
691 }
692
693 capi_ll_control(&sc->sc_capi, CAPI_CTRL_NEW_NCCI, NCCI);
694 return 0;
695 }
696
697 static int iavc_receive_free_ncci(iavc_softc_t *sc, u_int8_t *dmabuf)
698 {
699 u_int32_t ApplId, NCCI;
700
701 if (sc->sc_dma) {
702 dmabuf = amcc_get_word(dmabuf, &ApplId);
703 dmabuf = amcc_get_word(dmabuf, &NCCI);
704 } else {
705 ApplId = iavc_get_word(sc);
706 NCCI = iavc_get_word(sc);
707 }
708
709 capi_ll_control(&sc->sc_capi, CAPI_CTRL_FREE_NCCI, NCCI);
710 return 0;
711 }
712
713 static int iavc_receive_task_ready(iavc_softc_t *sc, u_int8_t *dmabuf)
714 {
715 u_int32_t TaskId, Length;
716 u_int8_t *p;
717 printf("%s: receive_task_ready\n", device_xname(&sc->sc_dev));
718
719 if (sc->sc_dma) {
720 p = amcc_get_word(dmabuf, &TaskId);
721 p = amcc_get_word(p, &Length);
722 } else {
723 TaskId = iavc_get_word(sc);
724 Length = iavc_get_slice(sc, sc->sc_recvbuf);
725 p = sc->sc_recvbuf;
726 }
727
728 /* XXX could show the message if trace enabled? XXX */
729 return 0;
730 }
731
732 static int iavc_receive_debugmsg(iavc_softc_t *sc, u_int8_t *dmabuf)
733 {
734 u_int32_t Length;
735 u_int8_t *p;
736 printf("%s: receive_debugmsg\n", device_xname(&sc->sc_dev));
737
738 if (sc->sc_dma) {
739 p = amcc_get_word(dmabuf, &Length);
740 } else {
741 Length = iavc_get_slice(sc, sc->sc_recvbuf);
742 p = sc->sc_recvbuf;
743 }
744
745 /* XXX could show the message if trace enabled? XXX */
746 return 0;
747 }
748
749 static int iavc_receive(iavc_softc_t *sc, u_int8_t *dmabuf, int b3data)
750 {
751 struct mbuf *m;
752 u_int32_t ApplId, Length;
753
754 /*
755 * byte 0x21 = RECEIVE_MESSAGE
756 * dword ApplId
757 * dword length
758 * ... CAPI msg
759 *
760 * --or--
761 *
762 * byte 0x22 = RECEIVE_DATA_B3_IND
763 * dword ApplId
764 * dword length
765 * ... CAPI msg
766 * dword datalen
767 * ... B3 data
768 */
769
770 if (sc->sc_dma) {
771 dmabuf = amcc_get_word(dmabuf, &ApplId);
772 dmabuf = amcc_get_word(dmabuf, &Length);
773 } else {
774 ApplId = iavc_get_word(sc);
775 Length = iavc_get_slice(sc, sc->sc_recvbuf);
776 dmabuf = sc->sc_recvbuf;
777 }
778
779 m = i4b_Dgetmbuf(Length);
780 if (!m) {
781 aprint_error_dev(&sc->sc_dev, "can't get memory for receive\n");
782 return (ENOMEM);
783 }
784
785 memcpy(mtod(m, u_int8_t*), dmabuf, Length);
786
787 #if 0
788 {
789 u_int8_t *p = mtod(m, u_int8_t*);
790 int len = 0;
791 printf("%s: applid=%d, len=%d\n", device_xname(&sc->sc_dev),
792 ApplId, Length);
793 while (len < m->m_len) {
794 printf(" %02x", p[len]);
795 if (len && (len % 16) == 0) printf("\n");
796 len++;
797 }
798 if (len % 16) printf("\n");
799 }
800 #endif
801
802 if (b3data) {
803 if (sc->sc_dma) {
804 dmabuf = amcc_get_word(dmabuf + Length, &Length);
805 } else {
806 Length = iavc_get_slice(sc, sc->sc_recvbuf);
807 dmabuf = sc->sc_recvbuf;
808 }
809
810 m->m_next = i4b_Bgetmbuf(Length);
811 if (!m->m_next) {
812 aprint_error_dev(&sc->sc_dev, "can't get memory for receive\n");
813 i4b_Dfreembuf(m);
814 return (ENOMEM);
815 }
816
817 memcpy(mtod(m->m_next, u_int8_t*), dmabuf, Length);
818 }
819
820 capi_ll_receive(&sc->sc_capi, m);
821 return 0;
822 }
823
824 /*
825 // iavc_handle_intr
826 // Checks device interrupt status and calls iavc_handle_{rx,tx}()
827 // as necessary.
828 //
829 // iavc_handle_rx
830 // Reads in the command byte and calls the subroutines above.
831 //
832 // iavc_start_tx
833 // Initiates DMA on the next queued message if possible.
834 */
835
836 int iavc_handle_intr(iavc_softc_t *sc)
837 {
838 u_int32_t status;
839 u_int32_t newcsr;
840
841 if (!sc->sc_dma) {
842 while (iavc_rx_full(sc))
843 iavc_handle_rx(sc);
844 return 0;
845 }
846
847 status = AMCC_READ(sc, AMCC_INTCSR);
848 if ((status & ANY_S5933_INT) == 0)
849 return 0;
850
851 newcsr = sc->sc_csr | (status & ALL_INT);
852 if (status & TX_TC_INT) newcsr &= ~EN_TX_TC_INT;
853 if (status & RX_TC_INT) newcsr &= ~EN_RX_TC_INT;
854 AMCC_WRITE(sc, AMCC_INTCSR, newcsr);
855 sc->sc_intr = 1;
856
857 if (status & RX_TC_INT) {
858 u_int32_t rxlen;
859
860 bus_dmamap_sync(sc->dmat, sc->rx_map, 0, sc->rx_map->dm_mapsize,
861 BUS_DMASYNC_POSTREAD);
862
863 if (sc->sc_recv1 == 0) {
864 sc->sc_recv1 = *(u_int32_t*)(sc->sc_recvbuf);
865 rxlen = (sc->sc_recv1 + 3) & ~3;
866
867 AMCC_WRITE(sc, AMCC_RXPTR, sc->rx_map->dm_segs[0].ds_addr);
868 AMCC_WRITE(sc, AMCC_RXLEN, rxlen ? rxlen : 4);
869 } else {
870 iavc_handle_rx(sc);
871 sc->sc_recv1 = 0;
872 AMCC_WRITE(sc, AMCC_RXPTR, sc->rx_map->dm_segs[0].ds_addr);
873 AMCC_WRITE(sc, AMCC_RXLEN, 4);
874 }
875 }
876
877 if (status & TX_TC_INT) {
878 bus_dmamap_sync(sc->dmat, sc->tx_map, 0, sc->tx_map->dm_mapsize,
879 BUS_DMASYNC_POSTWRITE);
880 sc->sc_csr &= ~EN_TX_TC_INT;
881 iavc_start_tx(sc);
882 }
883
884 AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
885 sc->sc_intr = 0;
886
887 return 0;
888 }
889
890 static void iavc_handle_rx(iavc_softc_t *sc)
891 {
892 u_int8_t *dmabuf = 0, cmd;
893
894 if (sc->sc_dma) {
895 dmabuf = amcc_get_byte(sc->sc_recvbuf, &cmd);
896 } else {
897 cmd = iavc_get_byte(sc);
898 }
899
900 NDBGL4(L4_IAVCDBG, "iavc%d: command = 0x%02x", sc->sc_unit, cmd);
901
902 switch (cmd) {
903 case RECEIVE_DATA_B3_IND:
904 iavc_receive(sc, dmabuf, 1);
905 break;
906
907 case RECEIVE_MESSAGE:
908 iavc_receive(sc, dmabuf, 0);
909 break;
910
911 case RECEIVE_NEW_NCCI:
912 iavc_receive_new_ncci(sc, dmabuf);
913 break;
914
915 case RECEIVE_FREE_NCCI:
916 iavc_receive_free_ncci(sc, dmabuf);
917 break;
918
919 case RECEIVE_START:
920 iavc_receive_start(sc);
921 break;
922
923 case RECEIVE_STOP:
924 iavc_receive_stop(sc);
925 break;
926
927 case RECEIVE_INIT:
928 iavc_receive_init(sc, dmabuf);
929 break;
930
931 case RECEIVE_TASK_READY:
932 iavc_receive_task_ready(sc, dmabuf);
933 break;
934
935 case RECEIVE_DEBUGMSG:
936 iavc_receive_debugmsg(sc, dmabuf);
937 break;
938
939 default:
940 aprint_error_dev(&sc->sc_dev, "unknown msg %02x\n", cmd);
941 }
942 }
943
944 static void iavc_start_tx(iavc_softc_t *sc)
945 {
946 struct mbuf *m;
947 u_int32_t txlen;
948
949 /* If device has put us on hold, punt. */
950
951 if (sc->sc_blocked) {
952 return;
953 }
954
955 /* If using DMA and transmitter busy, punt. */
956 if (sc->sc_dma && (sc->sc_csr & EN_TX_TC_INT)) {
957 return;
958 }
959
960 /* Else, see if we have messages to send. */
961 IF_DEQUEUE(&sc->sc_txq, m);
962 if (!m) {
963 return;
964 }
965
966 /* Have message, will send. */
967 if (CAPIMSG_LEN(m->m_data)) {
968 /* A proper CAPI message, possibly with B3 data */
969 txlen = iavc_tx_capimsg(sc, m);
970 } else {
971 /* A board control message to be sent as is */
972 txlen = iavc_tx_ctrlmsg(sc, m);
973 }
974
975 if (m->m_next) {
976 i4b_Bfreembuf(m->m_next);
977 m->m_next = NULL;
978 }
979 i4b_Dfreembuf(m);
980
981 /* Kick DMA into motion if applicable */
982 if (sc->sc_dma) {
983 txlen = (txlen + 3) & ~3;
984
985 bus_dmamap_sync(sc->dmat, sc->tx_map, 0, txlen,
986 BUS_DMASYNC_PREWRITE);
987
988 AMCC_WRITE(sc, AMCC_TXPTR, sc->tx_map->dm_segs[0].ds_addr);
989 AMCC_WRITE(sc, AMCC_TXLEN, txlen);
990 sc->sc_csr |= EN_TX_TC_INT;
991
992 if (!sc->sc_intr)
993 AMCC_WRITE(sc, AMCC_INTCSR, sc->sc_csr);
994 }
995 }
996
997 static uint32_t
998 iavc_tx_capimsg(iavc_softc_t *sc, struct mbuf *m)
999 {
1000 uint32_t txlen = 0;
1001 u_int8_t *dmabuf;
1002
1003 if (sc->sc_dma) {
1004 /* Copy message to DMA buffer. */
1005
1006 if (m->m_next)
1007 dmabuf = amcc_put_byte(sc->sc_sendbuf, SEND_DATA_B3_REQ);
1008 else
1009 dmabuf = amcc_put_byte(sc->sc_sendbuf, SEND_MESSAGE);
1010
1011 dmabuf = amcc_put_word(dmabuf, m->m_len);
1012 memcpy(dmabuf, m->m_data, m->m_len);
1013 dmabuf += m->m_len;
1014 txlen = 5 + m->m_len;
1015
1016 if (m->m_next) {
1017 dmabuf = amcc_put_word(dmabuf, m->m_next->m_len);
1018 memcpy(dmabuf, m->m_next->m_data, m->m_next->m_len);
1019 txlen += 4 + m->m_next->m_len;
1020 }
1021
1022 } else {
1023 /* Use PIO. */
1024
1025 if (m->m_next) {
1026 iavc_put_byte(sc, SEND_DATA_B3_REQ);
1027 NDBGL4(L4_IAVCDBG, "iavc%d: tx SDB3R msg, len = %d",
1028 sc->sc_unit, m->m_len);
1029 } else {
1030 iavc_put_byte(sc, SEND_MESSAGE);
1031 NDBGL4(L4_IAVCDBG, "iavc%d: tx SM msg, len = %d",
1032 sc->sc_unit, m->m_len);
1033 }
1034 #if 0
1035 {
1036 u_int8_t *p = mtod(m, u_int8_t*);
1037 int len;
1038 for (len = 0; len < m->m_len; len++) {
1039 printf(" %02x", *p++);
1040 if (len && (len % 16) == 0)
1041 printf("\n");
1042 }
1043 if (len % 16)
1044 printf("\n");
1045 }
1046 #endif
1047
1048 iavc_put_slice(sc, m->m_data, m->m_len);
1049
1050 if (m->m_next)
1051 iavc_put_slice(sc, m->m_next->m_data, m->m_next->m_len);
1052 }
1053
1054 return txlen;
1055 }
1056
1057 static uint32_t
1058 iavc_tx_ctrlmsg(iavc_softc_t *sc, struct mbuf *m)
1059 {
1060 uint32_t txlen = 0;
1061 uint8_t *dmabuf;
1062
1063 if (sc->sc_dma) {
1064 memcpy(sc->sc_sendbuf, m->m_data + 2, m->m_len - 2);
1065 txlen = m->m_len - 2;
1066 } else {
1067
1068 #if 0
1069 {
1070 u_int8_t *p = mtod(m, u_int8_t*) + 2;
1071 int len;
1072
1073 printf("%s: tx BDC msg, len = %d, msg =", device_xname(&sc->sc_dev),
1074 m->m_len-2);
1075 for (len = 0; len < m->m_len-2; len++) {
1076 printf(" %02x", *p++);
1077 if (len && (len % 16) == 0) printf("\n");
1078 }
1079 if (len % 16)
1080 printf("\n");
1081 }
1082 #endif
1083
1084 /* no DMA */
1085 txlen = m->m_len - 2;
1086 dmabuf = mtod(m, char*) + 2;
1087 while(txlen--)
1088 b1io_put_byte(sc, *dmabuf++);
1089 }
1090
1091 return txlen;
1092 }
Cache object: d92b82d8a5f745fa1fa2612ca683a40c
|