2 * Copyright (c) 2002 The NetBSD Foundation, Inc.
5 * This code is derived from software contributed to The NetBSD Foundation
6 * by Martin Husemann <martin@NetBSD.org>.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: daic.c,v 1.28 2009/03/14 15:36:17 dsl Exp $");
35 * daic.c: MI driver for Diehl active ISDN cards (S, SX, SXn, SCOM, QUADRO)
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/kernel.h>
41 #include <sys/errno.h>
42 #include <sys/ioctl.h>
43 #include <sys/device.h>
44 #include <sys/malloc.h>
46 #include <sys/socket.h>
49 #include <netisdn/i4b_ioctl.h>
50 #include <netisdn/i4b_l3l4.h>
51 #include <netisdn/i4b_isdnq931.h>
52 #include <netisdn/i4b_q931.h>
53 #include <netisdn/i4b_l3fsm.h>
54 #include <netisdn/i4b_l4.h>
57 #include <dev/ic/daicvar.h>
58 #include <dev/ic/daicreg.h>
59 #include <dev/microcode/daic/dnload.h>
63 /* the device is MI, only the attach struct is in the bus
64 dependent frontend. And only on old versions... */
65 struct cfdriver daic_cd
= {
71 /* local function prototypes */
72 static const char * cardtypename(int cardtype
);
73 static int daic_download(void *, int portcount
, struct isdn_dr_prot
*data
);
74 static int daic_diagnostic(void *, struct isdn_diagnostic_request
*req
);
75 static void daic_connect_request(struct call_desc
*cd
);
76 static void daic_connect_response(struct call_desc
*cd
, int, int);
77 static void daic_disconnect_request(struct call_desc
*cd
, int);
78 static int daic_reset(bus_space_tag_t bus
, bus_space_handle_t io
, int port
, int *memsize
);
79 static int daic_handle_intr(struct daic_softc
*sc
, int port
);
80 static void daic_register_port(struct daic_softc
*sc
, int port
);
81 static void daic_request(struct daic_softc
*sc
, int port
, u_int req
, u_int id
, bus_size_t parmsize
, const u_int8_t
*parms
);
82 static u_int
daic_assign(struct daic_softc
*sc
, int port
, u_int instance
, bus_size_t parmsize
, const u_int8_t
*parms
);
83 static void daic_indicate_ind(struct daic_softc
*sc
, int port
);
84 static void daic_bch_config(void *, int channel
, int bprot
, int updown
);
85 static void daic_bch_tx_start(void *, int channel
);
86 static void daic_set_link(void *softc
, int channel
,
87 const struct isdn_l4_driver_functions
*l4_driver
, void *l4_inst
);
88 static void daic_mgmt_command(struct isdn_l3_driver
*drv
, int cmd
, void *parm
);
89 static void daic_alert_request(struct call_desc
*cd
);
91 static isdn_link_t
*daic_ret_linktab(void *softc
, int channel
);
94 static void daic_dump_request(struct daic_softc
*sc
, int port
, u_int req
, u_int id
, bus_size_t parmsize
, u_int8_t
*parms
);
98 static const char * const cardnames
[] = {
99 "S", "SX", "SCOM", "QUADRO"
102 static const char * const err_codes
[DAIC_RC_ERRMASK
+1] = {
113 /* fixed parameters */
116 static u_int8_t parm_none
[] = { 0 };
117 #define VOIDREQ(sc,port,req,id) daic_request(sc, port, req, id, sizeof parm_none, parm_none)
119 /* assign request for the global d-channel instance */
120 static u_int8_t parm_global_assign
[] = {
121 /* BC len cap rate A-law */
122 0x04, 0x03, 0x80, 0x90, 0xa3, /* 64k speech */
123 0x04, 0x02, 0x88, 0x90, /* 64k data */
124 0x04, 0x03, 0x89, 0x90, 0xa3, /* restricted digital info */
125 0x04, 0x03, 0x90, 0x90, 0xa3, /* 3.1k speech */
126 /* shift6 SIN len service */
127 0x96, 0x01, 0x02, 0x00, 0x00, /* any service */
132 /*---------------------------------------------------------------------------*
133 * Return the name of a card with given cardtype
134 *---------------------------------------------------------------------------*/
136 cardtypename(int cardtype
)
138 if (cardtype
>= 0 && cardtype
< (sizeof(cardnames
) / sizeof(cardnames
[0])))
139 return cardnames
[cardtype
];
141 return "unknown type";
144 /*---------------------------------------------------------------------------*
145 * Probe for presence of device at given io space.
146 * Return the card type (stupid ISA needs to know this in advance, to
147 * calculate the share memory size).
148 *---------------------------------------------------------------------------*/
150 daic_probe(bus_space_tag_t bus
, bus_space_handle_t io
)
152 return (daic_reset(bus
, io
, 0, NULL
));
155 /*---------------------------------------------------------------------------*
156 * Attach and initialize the card at given io space.
157 *---------------------------------------------------------------------------*/
159 daic_attach(device_t self
, struct daic_softc
*sc
)
161 int i
, num_ports
, memsize
= 0;
164 memset(sc
->sc_port
, 0, sizeof sc
->sc_port
);
165 memset(sc
->sc_con
, 0, sizeof sc
->sc_con
);
166 sc
->sc_cardtype
= -1;
169 sc
->sc_cardtype
= daic_reset(sc
->sc_iot
, sc
->sc_ioh
, 0, &memsize
);
170 if (sc
->sc_cardtype
== 0) {
171 printf(": unknown card, can not attach.\n");
176 printf("%s: EICON.Diehl %s\n", device_xname(&sc
->sc_dev
),
177 cardtypename(sc
->sc_cardtype
));
178 printf("%s: %d kByte on board RAM\n", device_xname(&sc
->sc_dev
), memsize
);
179 num_ports
= sc
->sc_cardtype
== DAIC_TYPE_QUAD
? 4 : 1;
180 for (i
= 0; i
< num_ports
; i
++)
181 sc
->sc_port
[i
].du_state
= DAIC_STATE_DOWNLOAD
;
183 /* register all ports this card has */
184 for (i
= 0; i
< num_ports
; i
++)
185 daic_register_port(sc
, i
);
188 /*---------------------------------------------------------------------------*
189 * handle interrupts for one port of the card
190 *---------------------------------------------------------------------------*/
192 daic_handle_intr(struct daic_softc
*sc
, int port
)
194 struct outcallentry
*assoc
;
195 struct daic_unit
* du
= &sc
->sc_port
[port
];
196 int off
= port
* DAIC_ISA_MEMSIZE
;
201 /* check if we caused the interrupt */
202 if (!bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_IRQ
+off
))
203 return 0; /* nope, exit */
205 /* is the card in running state yet? */
206 if (du
->du_state
== DAIC_STATE_TESTING
) {
207 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_RC
+off
, 0);
208 du
->du_state
= DAIC_STATE_RUNNING
;
213 /* what caused the interrupt? */
214 /* (1) Check for a return code */
215 rc
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_RC
+off
);
216 rcid
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_RCID
+off
);
217 if (!rc
) goto check_ind
;
219 /* maybe an assign answer (positive or negative) */
220 if (rc
== DAIC_RC_ASSIGN_OK
) {
221 du
->du_assign_res
= rcid
;
222 /* assing rc is special, we tell the card it's done */
223 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_REQ
+off
, 0);
224 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_RC
+off
, 0);
225 /* we handle some types of assigns to global dchannel id's automaticaly */
226 if (du
->du_assign
& DAIC_ASSIGN_GLOBAL
) {
227 du
->du_global_dchan
= rcid
;
228 du
->du_assign
&= ~(DAIC_ASSIGN_GLOBAL
|DAIC_ASSIGN_PENDING
);
229 if (du
->du_assign
& DAIC_ASSIGN_SLEEPING
) {
231 wakeup(&du
->du_assign_res
);
234 wakeup(&du
->du_assign
);
237 } else if ((rc
& DAIC_RC_ASSIGN_MASK
) == DAIC_RC_ASSIGN_RC
) {
238 aprint_error_dev(&sc
->sc_dev
, "assign request failed, error 0x%02x: %s\n",
239 rc
& DAIC_RC_ERRMASK
,
240 err_codes
[rc
& DAIC_RC_ERRMASK
]);
241 du
->du_assign_res
= 0;
242 /* assing rc is special, we tell the card it's done */
243 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_REQ
+off
, 0);
244 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_RC
+off
, 0);
246 wakeup(&du
->du_assign
);
249 if (rcid
== du
->du_global_dchan
) {
250 du
->du_request_res
= rc
;
251 wakeup(&du
->du_request_res
);
254 for (chan
= 0; chan
< 2; chan
++) {
255 if (rcid
== sc
->sc_con
[port
*2+chan
].dchan_inst
) {
256 sc
->sc_con
[port
*2+chan
].dchan_rc
= rc
;
257 wakeup(&sc
->sc_con
[port
*2+chan
].dchan_rc
);
259 } else if (rcid
== sc
->sc_con
[port
*2+chan
].bchan_inst
) {
260 sc
->sc_con
[port
*2+chan
].bchan_rc
= rc
;
261 wakeup(&sc
->sc_con
[port
*2+chan
].bchan_rc
);
265 TAILQ_FOREACH(assoc
, &sc
->sc_outcalls
[port
], queue
) {
266 if (rcid
== assoc
->dchan_id
) {
274 printf("%s: unknown id 0x%02x got rc 0x%02x: %s\n",
275 device_xname(&sc
->sc_dev
), rcid
, rc
,
276 err_codes
[rc
& DAIC_RC_ERRMASK
]);
279 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_RC
+off
, 0);
282 /* (2) Check for an indication */
283 ind
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_IND
+off
);
284 indid
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_INDID
+off
);
287 /* incoming call routed to global dchannel task? */
288 if (indid
== du
->du_global_dchan
) {
289 if (ind
== DAIC_IND_INDICATE
) {
290 daic_indicate_ind(sc
, port
);
291 } else if (ind
== DAIC_IND_INFO
) {
294 printf("%s: got info indication\n",
295 device_xname(&sc
->sc_dev
));
297 for (i
= 0; i
< 48; i
++) {
299 printf("\n%02x:", i
);
300 printf(" %02x", bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_RBUFFER
+off
+i
));
303 } else if (ind
== DAIC_IND_HANGUP
) {
304 printf("%s: got global HANGUP indication\n",
305 device_xname(&sc
->sc_dev
));
307 printf("%s: unknown global indication: 0x%02x\n",
308 device_xname(&sc
->sc_dev
), ind
);
313 for (chan
= 0; chan
< 2; chan
++) {
314 if (indid
== sc
->sc_con
[port
*2+chan
].dchan_inst
) {
315 printf("%s: D-Channel indication 0x%02x for channel %d\n",
316 device_xname(&sc
->sc_dev
), ind
, chan
);
318 } else if (indid
== sc
->sc_con
[port
*2+chan
].bchan_inst
) {
319 printf("%s: B-Channel indication 0x%02x for channel %d\n",
320 device_xname(&sc
->sc_dev
), ind
, chan
);
325 TAILQ_FOREACH(assoc
, &sc
->sc_outcalls
[port
], queue
) {
326 if (indid
== assoc
->dchan_id
) {
327 printf("%s: D-Channel indication 0x%02x for outgoing call with cdid %d\n",
328 sc
-device_xname(&>sc_dev
), ind
, assoc
->cdid
);
333 /* not found - something's wrong! */
334 printf("%s: got ind 0x%02x for id 0x%02x\n", device_xname(&sc
->sc_dev
), ind
, indid
);
337 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_IND
+off
, 0);
340 /* tell card we're ready for more... */
341 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_IRQ
+off
, 0);
346 /*---------------------------------------------------------------------------*
348 *---------------------------------------------------------------------------*/
350 daic_intr(struct daic_softc
*sc
)
353 if (sc
->sc_cardtype
== DAIC_TYPE_QUAD
) {
355 for (i
= 0; i
< 4; i
++)
356 handeld
|= daic_handle_intr(sc
, i
);
358 handeld
= daic_handle_intr(sc
, 0);
362 /*---------------------------------------------------------------------------*
363 * Download primary protocol microcode to on-board processor
364 *---------------------------------------------------------------------------*/
366 daic_download(void *token
, int count
, struct isdn_dr_prot
*data
)
368 struct daic_unit
*du
= token
;
369 struct daic_softc
*sc
= du
->du_sc
;
372 if (sc
->sc_cardtype
!= DAIC_TYPE_QUAD
)
373 count
= 1; /* XXX - or signal error ? */
375 for (i
= 0; i
< count
; i
++) {
376 int off
= DAIC_ISA_MEMSIZE
* i
;
377 u_int8_t
*p
= data
[i
].microcode
;
378 size_t s
= data
[i
].bytecount
;
381 for (p
= data
[i
].microcode
+4, cnt
= 0; *p
&& cnt
< 70; p
++, cnt
++)
383 sw_id
= p
[1] | (p
[2] << 8) | (p
[3] << 16) | (p
[4] << 24);
384 if (sc
->sc_cardtype
== DAIC_TYPE_QUAD
)
385 printf("%s port %d: downloading %s\n",
386 device_xname(&sc
->sc_dev
), i
, data
[i
].microcode
+4);
388 printf("%s: downloading %s\n",
389 device_xname(&sc
->sc_dev
), data
[i
].microcode
+4);
391 p
= data
[i
].microcode
;
393 size_t size
= (s
> 256) ? 256 : s
;
394 bus_space_write_region_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_BOOT_BUF
+off
, p
, size
);
397 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_BOOT_CTRL
+off
, 1);
399 for (cnt
= 0; cnt
< 2*hz
; cnt
++) {
401 if (bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_BOOT_CTRL
+off
) == 0)
404 tsleep(sc
, 0, "daic download", 1);
406 if (bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_BOOT_CTRL
+off
) != 0) {
408 aprint_error_dev(&sc
->sc_dev
, "download of microcode failed\n");
413 /* configure microcode - no parameters yet - XXX */
414 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_BOOT_TEI
+off
, 0);
415 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_BOOT_NT2
+off
, 0);
416 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_BOOT_ZERO
+off
, 0);
417 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_BOOT_WATCHDOG
+off
, 0);
418 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_BOOT_PERMANENT
+off
, 0);
419 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_BOOT_XINTERFACE
+off
, 0);
422 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_BOOT_CTRL
+off
, 2);
424 /* wait for signature */
425 for (cnt
= 0; cnt
< 2*hz
; cnt
++) {
427 signature
= bus_space_read_2(sc
->sc_iot
, sc
->sc_ioh
, DAIC_BOOT_SIGNATURE
+off
);
428 if (signature
== DAIC_SIGNATURE_VALUE
)
431 if (signature
!= DAIC_SIGNATURE_VALUE
) {
433 aprint_error_dev(&sc
->sc_dev
, "microcode signature bad: should be %04x, is %04x\n",
434 DAIC_SIGNATURE_VALUE
,signature
);
440 tsleep(&sc
->sc_port
[i
].du_state
, 0, "daic protocol init", hz
/25);
444 /* real check: send an invalid request and wait for an interrupt */
445 sc
->sc_port
[i
].du_state
= DAIC_STATE_TESTING
;
446 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_RC
+off
, 0);
447 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_REQID
+off
, 0xff);
448 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_REQ
+off
, 1);
450 tsleep(&sc
->sc_port
[i
].du_state
, 0, "daic irq test", 2*hz
);
452 if (sc
->sc_port
[i
].du_state
!= DAIC_STATE_RUNNING
) {
454 printf("%s: download interrupt test timeout\n",
455 device_xname(&sc
->sc_dev
));
459 /* finish card configuration */
460 bus_space_write_4(sc
->sc_iot
, sc
->sc_ioh
, DAIC_SWID
+off
, sw_id
);
461 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_SET_CARD
+off
, sc
->sc_cardtype
);
464 /* assign global d-channel id for that port */
465 sc
->sc_port
[i
].du_global_dchan
=
466 daic_assign(sc
, i
, DAIC_GLOBALID_DCHAN
,
467 sizeof parm_global_assign
, parm_global_assign
);
469 /* send an INDICATE request to get incoming calls on this id */
471 VOIDREQ(sc
, i
, DAIC_REQ_INDICATE
, sc
->sc_port
[i
].du_global_dchan
);
473 tsleep(&sc
->sc_port
[i
].du_request_res
, 0, "daic request", 0);
475 if (sc
->sc_port
[i
].du_request_res
!= DAIC_RC_OK
) {
476 aprint_error_dev(&sc
->sc_dev
, "INDICATE request error (0x%02x): %s\n",
477 sc
->sc_port
[i
].du_request_res
,
478 err_codes
[sc
->sc_port
[i
].du_request_res
& DAIC_RC_ERRMASK
]);
487 /*---------------------------------------------------------------------------*
488 * Reset the card, download primary bootstrap, let it check the
489 * card and return the cardtype identified by the microcode
490 * or -1 if no known card is detected.
491 *---------------------------------------------------------------------------*/
493 daic_reset(bus_space_tag_t bus
, bus_space_handle_t io
, int port
, int *memsize
)
495 int i
, off
= port
* DAIC_ISA_MEMSIZE
;
496 int cardtype
, mem
, quiet
= memsize
== NULL
; /* no output if we are only probing */
498 /* clear any pending interrupt */
499 bus_space_read_1(bus
, io
, DAIC_IRQ
+off
);
501 bus_space_write_1(bus
, io
, DAIC_BOOT_SET_RESET
+off
, 0);
503 /* download primary bootstrap */
504 bus_space_set_region_1(bus
, io
, DAIC_BOOT_START
+off
, 0, DAIC_BOOT_CODE
-DAIC_BOOT_START
);
505 bus_space_write_region_1(bus
, io
, DAIC_BOOT_CODE
+off
, dnload
, DAIC_BOOT_END
-DAIC_BOOT_CODE
+1);
506 if (bus_space_read_1(bus
, io
, DAIC_BOOT_CTRL
+off
)
507 || bus_space_read_1(bus
, io
, DAIC_BOOT_EBIT
+off
)) {
508 if (!quiet
) printf(": shared memory test failed!\n");
511 /* let card perform memory test */
512 bus_space_write_1(bus
, io
, DAIC_BOOT_CTRL
+off
, DAIC_TEST_MEM
);
513 /* and off we go... */
514 bus_space_write_1(bus
, io
, DAIC_BOOT_CLR_RESET
+off
, 0);
515 /* wait for response from bootstrap */
516 for (i
= 0; i
< 15000 && bus_space_read_1(bus
, io
, DAIC_BOOT_CTRL
+off
) != DAIC_TEST_RDY
; i
++)
519 if (!quiet
) printf(": on board processor test failed!\n");
522 if (bus_space_read_1(bus
, io
, DAIC_BOOT_EBIT
+off
)) {
523 if (!quiet
) printf(": on board memory test failed at %p\n",
524 (void*)bus_space_read_2(bus
, io
, DAIC_BOOT_ELOC
+off
));
528 /* fetch info from primary bootstrap code */
529 cardtype
= bus_space_read_1(bus
, io
, DAIC_BOOT_CARD
+off
);
530 mem
= bus_space_read_1(bus
, io
, DAIC_BOOT_MSIZE
+off
) << 4;
537 /*---------------------------------------------------------------------------*
538 * Generic diagnostic interface - pass through the microcode data
539 * without knowing too much about it. This passes a lot work to
540 * userland, but hey, this is only a diagnostic tool...
541 *---------------------------------------------------------------------------*/
543 daic_diagnostic(void *token
, struct isdn_diagnostic_request
*req
)
545 struct daic_unit
*du
= token
;
546 struct daic_softc
*sc
= du
->du_sc
;
547 int port
= du
->du_port
;
548 int off
= port
* DAIC_ISA_MEMSIZE
;
552 /* validate parameters */
553 if (req
->cmd
> DAIC_DIAG_MAXCMD
) {
554 aprint_error_dev(&sc
->sc_dev
, "daic_diagnostic: illegal cmd %d\n",
558 if (req
->out_param_len
> (DAIC_DIAG_DATA_SIZE
+1)) {
559 aprint_error_dev(&sc
->sc_dev
, "daic_diagnostic: illegal out_param_len %d\n",
564 /* XXX - only for debug */
565 if (req
->cmd
== 0x05) {
566 /* pass through request from userland */
569 static u_int8_t parms
[] = {
570 IEI_CALLID
, 0x01, 0x81,
571 IEI_CALLINGPN
, 7, NUMBER_TYPEPLAN
, '9', '8', '9', '0', '2', '0',
572 0x96, 0x01, 0x02, 0x01, 0x00,
576 /* create the d-channel task for this call */
577 printf("%s: assigning id for pass-through call\n", device_xname(&sc
->sc_dev
));
578 id
= daic_assign(sc
, port
, DAIC_GLOBALID_DCHAN
, sizeof(parms
), parms
);
579 printf("%s: got id 0x%02x\n", device_xname(&sc
->sc_dev
), id
);
582 daic_dump_request(sc
, port
, DAIC_REQ_CALL
, id
, req
->in_param_len
, req
->in_param
);
584 daic_request(sc
, port
, DAIC_REQ_CALL
, id
, req
->in_param_len
, req
->in_param
);
588 /* all these need an output parameter */
589 if (req
->out_param
== NULL
)
592 /* check state and switch to DIAGNOSTIC */
594 if (sc
->sc_port
[port
].du_state
!= DAIC_STATE_RUNNING
) {
598 sc
->sc_port
[port
].du_state
= DAIC_STATE_DIAGNOSTIC
;
601 /* set new request */
602 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_DIAG_REQ
+off
, req
->cmd
);
604 /* sorry, no interrupt on completition - have to poll */
605 for (cnt
= 0; cnt
< 3*hz
; cnt
++) {
606 if (bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_DIAG_REQ
+off
) == 0
607 && bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_DIAG_RC
+off
) != 0)
609 tsleep(sc
, 0, "daic diagnostic", 1);
611 rc
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_DIAG_RC
+off
);
613 /* stop request and return error */
614 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_DIAG_REQ
+off
, 0);
615 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_DIAG_RC
+off
, 0);
619 /* out param gets rc and all the data */
620 if (req
->out_param_len
>= 2) {
621 ((u_int8_t
*)(req
->out_param
))[0] = (u_int8_t
)rc
;
622 bus_space_read_region_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_DIAG_DATA
+off
, ((u_int8_t
*)req
->out_param
)+1, req
->out_param_len
-1);
624 /* acknowledge data */
625 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_DIAG_RC
+off
, 0);
627 done
: /* back to normal state */
629 sc
->sc_port
[port
].du_state
= DAIC_STATE_RUNNING
;
635 static void daic_stat(void *port
, int channel
, bchan_statistics_t
*bsp
)
639 static const struct isdn_l4_bchannel_functions
646 static const struct isdn_l3_driver_functions
647 daic_l3_functions
= {
650 daic_connect_request
,
651 daic_connect_response
,
652 daic_disconnect_request
,
659 /*---------------------------------------------------------------------------*
660 * Register one port and attach it to the upper layers
661 *---------------------------------------------------------------------------*/
663 daic_register_port(struct daic_softc
*sc
, int port
)
666 char cardname
[80], devname
[80];
667 struct isdn_l3_driver
* l3drv
;
669 sc
->sc_port
[port
].du_port
= port
;
670 sc
->sc_port
[port
].du_sc
= sc
;
672 /* make sure this hardware driver type is known to layer 4 */
673 if (sc
->sc_cardtype
== DAIC_TYPE_QUAD
)
674 snprintf(devname
, sizeof(devname
), "%s port %d",
675 device_xname(&sc
->sc_dev
), port
);
677 strlcpy(devname
, device_xname(&sc
->sc_dev
), sizeof(devname
));
678 snprintf(cardname
, sizeof(cardname
), "EICON.Diehl %s",
679 cardtypename(sc
->sc_cardtype
));
680 l3drv
= isdn_attach_isdnif(
681 devname
, cardname
, &sc
->sc_port
[port
], &daic_l3_functions
,
683 sc
->sc_port
[port
].du_l3
= l3drv
;
685 /* initialize linktabs for this port */
686 for (chan
= 0; chan
< 2; chan
++) {
687 isdn_link_t
*lt
= &sc
->sc_con
[port
*2+chan
].isdn_linktab
;
688 lt
->l1token
= &sc
->sc_port
[port
];
690 lt
->tx_queue
= &sc
->sc_con
[port
*2+chan
].tx_queue
;
691 lt
->rx_queue
= &sc
->sc_con
[port
*2+chan
].rx_queue
;
693 TAILQ_INIT(&sc
->sc_outcalls
[port
]);
695 isdn_isdnif_ready(l3drv
->isdnif
);
698 /*---------------------------------------------------------------------------*
699 * return the address of daic drivers linktab
700 *---------------------------------------------------------------------------*/
702 daic_ret_linktab(void *token
, int channel
)
704 struct daic_unit
*du
= token
;
705 struct daic_softc
*sc
= du
->du_sc
;
706 int port
= du
->du_port
;
707 struct daic_connection
*con
= &sc
->sc_con
[port
*2+channel
];
709 return(&con
->isdn_linktab
);
712 /*---------------------------------------------------------------------------*
713 * set the driver linktab in the b channel softc
714 *---------------------------------------------------------------------------*/
716 daic_set_link(void *token
, int channel
, const struct isdn_l4_driver_functions
*l4_driver
, void *l4_inst
)
718 struct daic_unit
*du
= token
;
719 struct daic_softc
*sc
= du
->du_sc
;
720 int port
= du
->du_port
;
721 struct daic_connection
*con
= &sc
->sc_con
[port
*2+channel
];
723 con
->l4_driver
= l4_driver
;
724 con
->l4_driver_softc
= l4_inst
;
727 /*---------------------------------------------------------------------------*
728 * Send a request to the card.
729 *---------------------------------------------------------------------------*/
732 struct daic_softc
*sc
, /* ourself */
733 int port
, /* and the port on this card */
734 u_int req
, /* the request to send */
735 u_int id
, /* id of communication task */
736 bus_size_t parmsize
, /* size of parms including the terminating zero */
737 const u_int8_t
*parms
) /* pointer to parms to pass */
739 int off
= port
*DAIC_ISA_MEMSIZE
;
741 /* spin while card is yet busy */
742 while (bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_REQ
))
743 ; /* unlikely to happen with this driver */
745 /* output parameters */
746 bus_space_write_region_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_XBUFFER
+off
, parms
, parmsize
);
748 /* output request and id */
749 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_REQID
+off
, id
);
750 bus_space_write_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_REQ
+off
, req
);
753 /*---------------------------------------------------------------------------*
754 * Assign a unique instance id for some communication class
755 * on the card. Only one assign request may be running on a
756 * port at any time, handle this and return the instance id.
757 *---------------------------------------------------------------------------*/
760 struct daic_softc
*sc
, /* our state and port no */
762 u_int classid
, /* Diehl calls this "global instance id" */
763 bus_size_t parmsize
, /* sizeof parameter arra */
764 const u_int8_t
*parms
) /* task instance parameters */
766 static char wchan
[] = "daic assign";
770 /* there only may be one assignment running concurrently */
773 if (!(sc
->sc_port
[port
].du_assign
& DAIC_ASSIGN_PENDING
))
774 break; /* we got it! */
776 /* somebody else is assigning, record state and sleep */
777 sc
->sc_port
[port
].du_assign
|= DAIC_ASSIGN_SLEEPING
;
778 tsleep(&sc
->sc_port
[port
].du_assign_res
, 0, wchan
, 0);
781 /* put parameters and request to card */
782 sc
->sc_port
[port
].du_assign
|= DAIC_ASSIGN_PENDING
;
783 daic_request(sc
, port
, DAIC_REQ_ASSIGN
, classid
, parmsize
, parms
);
785 /* wait for completition of assignment by the card */
786 tsleep(&sc
->sc_port
[port
].du_assign
, 0, wchan
, 0);
787 id
= sc
->sc_port
[port
].du_assign_res
;
789 /* have we lost our global dchannel id in the meantime? */
790 if (sc
->sc_port
[port
].du_assign
& DAIC_ASSIGN_NOGLOBAL
) {
791 /* start an assign request and let the result
792 be handled by the interrupt handler - we don't
793 have to wait for it here. As the assign lock
794 isn't freed, we don't wake up others... */
795 sc
->sc_port
[port
].du_assign
&= ~DAIC_ASSIGN_NOGLOBAL
;
796 sc
->sc_port
[port
].du_assign
|= DAIC_ASSIGN_PENDING
|DAIC_ASSIGN_GLOBAL
;
797 daic_request(sc
, port
, DAIC_REQ_ASSIGN
, DAIC_GLOBALID_DCHAN
,
798 sizeof parm_global_assign
, parm_global_assign
);
803 /* XXX - review this, can't remember why I did it this complicated */
805 /* unlock and wakup others, if any */
806 if (sc
->sc_port
[port
].du_assign
& DAIC_ASSIGN_SLEEPING
) {
807 sc
->sc_port
[port
].du_assign
= 0;
808 wakeup(&sc
->sc_port
[port
].du_assign_res
);
810 sc
->sc_port
[port
].du_assign
= 0;
817 /*---------------------------------------------------------------------------*
818 * Debug output of request parameters
819 *---------------------------------------------------------------------------*/
821 daic_dump_request(struct daic_softc
*sc
, int port
, u_int req
, u_int id
, bus_size_t parmsize
, u_int8_t
*parms
)
824 printf("%s: request 0x%02x to task id 0x%02x:",
825 device_xname(&sc
->sc_dev
), req
, id
);
826 for (i
= 0; i
< parmsize
; i
++) {
828 printf("\n%02x:", i
);
829 printf(" %02x", parms
[i
]);
835 /*---------------------------------------------------------------------------*
836 * Decode parameters of an INDICATE indication from the card
837 * and pass them to layer 4. Called from within an interrupt
839 *---------------------------------------------------------------------------*/
841 daic_indicate_ind(struct daic_softc
*sc
, int port
)
843 int offset
= port
*DAIC_ISA_MEMSIZE
;
848 /* get and init new calldescriptor */
849 cd
= reserve_cd(); /* cdid filled in */
850 cd
->bprot
= BPROT_NONE
;
853 cd
->dst_telno
[0] = '\0';
854 cd
->src_telno
[0] = '\0';
855 cd
->channelid
= CHAN_NO
;
858 cd
->crflag
= CRF_DEST
;
859 cd
->ilt
= NULL
; /* reset link tab ptrs */
863 ie
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_RBUFFER
+offset
+i
);
866 if (ie
& 0x80) continue;
867 ielen
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_RBUFFER
+offset
+i
);
871 ie
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_RBUFFER
+offset
+i
);
872 if (ie
== 0x80 || ie
== 0x89 || ie
== 0x90)
873 cd
->bprot
= BPROT_NONE
;
875 cd
->bprot
= BPROT_RHDLC
;
880 ie
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_RBUFFER
+offset
+i
);
885 bus_space_read_region_1(sc
->sc_iot
, sc
->sc_ioh
,
886 DAIC_COM_RBUFFER
+offset
+i
+off
, cd
->src_telno
,
888 cd
->src_telno
[ielen
-off
+1] = '\0';
892 bus_space_read_region_1(sc
->sc_iot
, sc
->sc_ioh
,
893 DAIC_COM_RBUFFER
+offset
+i
+1,
894 cd
->dst_telno
, ielen
-1);
895 cd
->dst_telno
[ielen
] = '\0';
898 ie
= bus_space_read_1(sc
->sc_iot
, sc
->sc_ioh
, DAIC_COM_RBUFFER
+offset
+i
);
899 if ((ie
& 0xf4) != 0x80)
900 cd
->channelid
= CHAN_NO
;
903 case IE_CHAN_ID_NO
: cd
->channelid
= CHAN_NO
; break;
904 case IE_CHAN_ID_B1
: cd
->channelid
= CHAN_B1
; break;
905 case IE_CHAN_ID_B2
: cd
->channelid
= CHAN_B2
; break;
906 case IE_CHAN_ID_ANY
: cd
->channelid
= CHAN_ANY
; break;
908 cd
->channelexcl
= (ie
& 0x08) >> 3;
913 cd
->event
= EV_SETUP
;
914 /* ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_RSVD; */
916 /* record the dchannel id for this call and the call descriptor */
917 sc
->sc_con
[port
*2+cd
->channelid
].dchan_inst
= sc
->sc_port
[port
].du_global_dchan
;
918 sc
->sc_con
[port
*2+cd
->channelid
].cdid
= cd
->cdid
;
920 /* this task is busy now, we need a new global dchan id */
921 if (sc
->sc_port
[port
].du_assign
& DAIC_ASSIGN_PENDING
) {
922 /* argh - can't assign right now */
923 sc
->sc_port
[port
].du_assign
|= DAIC_ASSIGN_NOGLOBAL
;
925 /* yeah - can request the assign right away, but let the
926 interrupt handler autohandle the result */
927 sc
->sc_port
[port
].du_assign
|= DAIC_ASSIGN_PENDING
|DAIC_ASSIGN_GLOBAL
;
928 daic_request(sc
, port
, DAIC_REQ_ASSIGN
, DAIC_GLOBALID_DCHAN
,
929 sizeof parm_global_assign
, parm_global_assign
);
932 if (cd
->bprot
== BPROT_NONE
)
933 printf("\nincoming voice call from \"%s\" to \"%s\"\n",
934 cd
->src_telno
, cd
->dst_telno
);
936 printf("\nincoming data call from \"%s\" to \"%s\"\n",
937 cd
->src_telno
, cd
->dst_telno
);
939 /* hand up call to layer 4 */
940 i4b_l4_connect_ind(cd
);
943 /*---------------------------------------------------------------------------*
944 * Layer 4 request a call setup
945 *---------------------------------------------------------------------------*/
947 daic_connect_request(struct call_desc
*cd
)
949 u_int8_t id
, cpn
[TELNO_MAX
+4], parms
[TELNO_MAX
+16], *p
;
950 struct daic_unit
*du
= cd
->ilt
->l1token
;
951 struct daic_softc
*sc
= du
->du_sc
;
952 int port
= du
->du_port
;
954 struct outcallentry
*assoc
;
956 /* to associate the cdid with the communication task
957 we are going to create for this outgoing call,
958 we maintain a queue of pending outgoing calls.
959 As soon as a SETUP response is received, we move
960 the association to the allocated b-channel. */
962 /* configure d-channel task parameters */
964 *p
++ = IEI_CALLID
; *p
++ = 0x01;
965 if (cd
->bprot
== BPROT_NONE
) {
967 } else if (cd
->bprot
== BPROT_RHDLC
) {
970 printf("%s: daic_connect_request for unknown bchan protocol 0x%x\n",
971 device_xname(&sc
->sc_dev
), cd
->bprot
);
974 if (cd
->src_telno
[0]) {
975 *p
++ = IEI_CALLINGPN
;
976 *p
++ = strlen(cd
->src_telno
)+1;
977 *p
++ = NUMBER_TYPEPLAN
;
978 strcpy(p
, cd
->src_telno
);
981 if (cd
->channelid
== CHAN_B1
|| cd
->channelid
== CHAN_B2
) {
982 *p
++ = IEI_CHANNELID
;
984 *p
++ = 0x81 + cd
->channelid
;
986 if (cd
->bprot
== BPROT_NONE
) {
987 *p
++ = 0x96; /* shift6 */
988 *p
++ = 0x01; /* SIN */
989 *p
++ = 0x02; /* len */
990 *p
++ = 0x01; /* Telephony */
991 *p
++ = 0x00; /* add.info */
995 /* create the d-channel task for this call */
996 id
= daic_assign(sc
, port
, DAIC_GLOBALID_DCHAN
, p
- parms
, parms
);
998 /* map it to the call descriptor id */
999 assoc
= malloc(sizeof(struct outcallentry
), M_DEVBUF
, 0);
1000 assoc
->cdid
= cd
->cdid
;
1001 assoc
->dchan_id
= id
;
1003 TAILQ_INSERT_TAIL(&sc
->sc_outcalls
[port
], assoc
, queue
);
1005 /* send a call request */
1006 len
= strlen(cd
->dst_telno
);
1007 cpn
[0] = IEI_CALLEDPN
;
1009 cpn
[2] = NUMBER_TYPEPLAN
;
1010 strcpy(cpn
+3, cd
->dst_telno
);
1012 daic_dump_request(sc
, port
, DAIC_REQ_CALL
, id
, len
+4, cpn
);
1014 daic_request(sc
, port
, DAIC_REQ_CALL
, id
, len
+4, cpn
);
1016 tsleep(assoc
, 0, "daic call", 0);
1017 if (assoc
->rc
!= DAIC_RC_OK
) {
1018 aprint_error_dev(&sc
->sc_dev
, "call request failed, error 0x%02x: %s\n",
1019 assoc
->rc
& DAIC_RC_ERRMASK
,
1020 err_codes
[assoc
->rc
& DAIC_RC_ERRMASK
]);
1024 /*---------------------------------------------------------------------------*
1026 *---------------------------------------------------------------------------*/
1027 static void daic_connect_response(struct call_desc
*cd
, int response
, int cause
)
1031 /*---------------------------------------------------------------------------*
1033 *---------------------------------------------------------------------------*/
1034 static void daic_disconnect_request(struct call_desc
*cd
, int cause
)
1038 /*---------------------------------------------------------------------------*
1040 *---------------------------------------------------------------------------*/
1041 static void daic_bch_config(void *token
, int channel
, int bprot
, int updown
)
1043 printf("daic: bch_config\n");
1046 /*---------------------------------------------------------------------------*
1048 *---------------------------------------------------------------------------*/
1049 static void daic_bch_tx_start(void *token
, int channel
)
1051 printf("daic: bch_tx_start\n");
1054 /*---------------------------------------------------------------------------*
1056 *---------------------------------------------------------------------------*/
1058 daic_mgmt_command(struct isdn_l3_driver
*drv
, int cmd
, void *parm
)
1062 /*---------------------------------------------------------------------------*
1064 *---------------------------------------------------------------------------*/
1066 daic_alert_request(struct call_desc
*cd
)