1 /* ISDN4BSD code */
2 /*-
3 * Copyright (c) 2002 The NetBSD Foundation, Inc.
4 * All rights reserved.
5 *
6 * This code is derived from software contributed to The NetBSD Foundation
7 * by Martin Husemann <martin@netbsd.org>.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by the NetBSD
20 * Foundation, Inc. and its contributors.
21 * 4. Neither the name of The NetBSD Foundation nor the names of its
22 * contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 * POSSIBILITY OF SUCH DAMAGE.
36 *
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: daic.c,v 1.14 2003/04/06 18:20:12 wiz Exp $");
41
42 /*
43 * daic.c: MI driver for Diehl active ISDN cards (S, SX, SXn, SCOM, QUADRO)
44 */
45
46 #include <sys/param.h>
47 #include <sys/systm.h>
48 #include <sys/kernel.h>
49 #include <sys/errno.h>
50 #include <sys/ioctl.h>
51 #include <sys/device.h>
52 #include <sys/malloc.h>
53 #include <sys/proc.h>
54 #include <sys/socket.h>
55 #include <net/if.h>
56
57 #include <netisdn/i4b_ioctl.h>
58 #include <netisdn/i4b_l3l4.h>
59 #include <netisdn/i4b_isdnq931.h>
60 #include <netisdn/i4b_q931.h>
61 #include <netisdn/i4b_l3fsm.h>
62 #include <netisdn/i4b_l4.h>
63
64 #include <machine/bus.h>
65 #include <dev/ic/daicvar.h>
66 #include <dev/ic/daicreg.h>
67 #include <dev/microcode/daic/dnload.h>
68
69 #ifdef NetBSD1_3
70 #if NetBSD1_3 < 2
71 /* the device is MI, only the attach struct is in the bus
72 dependend frontend. And only on old versions... */
73 struct cfdriver daic_cd = {
74 NULL, "daic", DV_DULL
75 };
76 #endif
77 #endif
78
79 /* local function prototypes */
80 static char * cardtypename __P((int cardtype));
81 static int daic_download __P((void *, int portcount, struct isdn_dr_prot *data));
82 static int daic_diagnostic __P((void *, struct isdn_diagnostic_request *req));
83 static void daic_connect_request(struct call_desc *cd);
84 static void daic_connect_response(struct call_desc *cd, int, int);
85 static void daic_disconnect_request(struct call_desc *cd, int);
86 static int daic_reset __P((bus_space_tag_t bus, bus_space_handle_t io, int port, int *memsize));
87 static int daic_handle_intr __P((struct daic_softc *sc, int port));
88 static void daic_register_port(struct daic_softc *sc, int port);
89 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);
90 static u_int daic_assign(struct daic_softc *sc, int port, u_int instance, bus_size_t parmsize, const u_int8_t *parms);
91 static void daic_indicate_ind(struct daic_softc *sc, int port);
92 static void daic_bch_config(void *, int channel, int bprot, int updown);
93 static void daic_bch_tx_start(void *, int channel);
94 static void daic_set_link(void *softc, int channel,
95 const struct isdn_l4_driver_functions *l4_driver, void *l4_inst );
96 static void daic_mgmt_command(struct isdn_l3_driver *drv, int cmd, void *parm);
97 static void daic_alert_request(struct call_desc *cd);
98
99 static isdn_link_t *daic_ret_linktab(void *softc, int channel);
100
101 #ifdef DAIC_DEBUG
102 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);
103 #endif
104
105 /* static data */
106 static char *cardnames[] = {
107 "S", "SX", "SCOM", "QUADRO"
108 };
109
110 static char *err_codes[DAIC_RC_ERRMASK+1] = {
111 "NO ERROR",
112 "UNKNOWN COMMAND",
113 "WRONG COMMAND",
114 "WRONG ID",
115 "WRONG CH",
116 "UNKNOWN IE",
117 "WRONG IE",
118 "OUT OF RESOURCES"
119 };
120
121 /* fixed parameters */
122
123 /* no parameters */
124 static u_int8_t parm_none[] = { 0 };
125 #define VOIDREQ(sc,port,req,id) daic_request(sc, port, req, id, sizeof parm_none, parm_none)
126
127 /* assign request for the global d-channel instance */
128 static u_int8_t parm_global_assign[] = {
129 /* BC len cap rate A-law */
130 0x04, 0x03, 0x80, 0x90, 0xa3, /* 64k speech */
131 0x04, 0x02, 0x88, 0x90, /* 64k data */
132 0x04, 0x03, 0x89, 0x90, 0xa3, /* restricted digital info */
133 0x04, 0x03, 0x90, 0x90, 0xa3, /* 3.1k speech */
134 /* shift6 SIN len service */
135 0x96, 0x01, 0x02, 0x00, 0x00, /* any service */
136 /* end of parms */
137 0x00
138 };
139
140 /*---------------------------------------------------------------------------*
141 * Return the name of a card with given cardtype
142 *---------------------------------------------------------------------------*/
143 static char *
cardtypename(cardtype)144 cardtypename(cardtype)
145 int cardtype;
146 {
147 if (cardtype >= 0 && cardtype < (sizeof(cardnames) / sizeof(cardnames[0])))
148 return cardnames[cardtype];
149 else
150 return "unknown type";
151 }
152
153 /*---------------------------------------------------------------------------*
154 * Probe for presence of device at given io space.
155 * Return the card type (stupid ISA needs to know this in advance, to
156 * calculate the share memory size).
157 *---------------------------------------------------------------------------*/
158 int
daic_probe(bus,io)159 daic_probe(bus, io)
160 bus_space_tag_t bus;
161 bus_space_handle_t io;
162 {
163 return (daic_reset(bus, io, 0, NULL));
164 }
165
166 /*---------------------------------------------------------------------------*
167 * Attach and initialize the card at given io space.
168 *---------------------------------------------------------------------------*/
169 void
daic_attach(self,sc)170 daic_attach(self, sc)
171 struct device *self;
172 struct daic_softc *sc;
173 {
174 int i, num_ports, memsize = 0;
175
176 /* init sc */
177 memset(sc->sc_port, 0, sizeof sc->sc_port);
178 memset(sc->sc_con, 0, sizeof sc->sc_con);
179 sc->sc_cardtype = -1;
180
181 /* init card */
182 sc->sc_cardtype = daic_reset(sc->sc_iot, sc->sc_ioh, 0, &memsize);
183 if (sc->sc_cardtype == 0) {
184 printf(": unknown card, can not attach.\n");
185 return;
186 }
187
188 printf("\n");
189 printf("%s: EICON.Diehl %s\n", sc->sc_dev.dv_xname,
190 cardtypename(sc->sc_cardtype));
191 printf("%s: %d kByte on board RAM\n", sc->sc_dev.dv_xname, memsize);
192 num_ports = sc->sc_cardtype == DAIC_TYPE_QUAD ? 4 : 1;
193 for (i = 0; i < num_ports; i++)
194 sc->sc_port[i].du_state = DAIC_STATE_DOWNLOAD;
195
196 /* register all ports this card has */
197 for (i = 0; i < num_ports; i++)
198 daic_register_port(sc, i);
199 }
200
201 /*---------------------------------------------------------------------------*
202 * handle interrupts for one port of the card
203 *---------------------------------------------------------------------------*/
204 static int
daic_handle_intr(sc,port)205 daic_handle_intr(sc, port)
206 struct daic_softc *sc;
207 int port;
208 {
209 struct outcallentry *assoc;
210 struct daic_unit * du = &sc->sc_port[port];
211 int off = port * DAIC_ISA_MEMSIZE;
212 u_int8_t rc, rcid;
213 u_int8_t ind, indid;
214 int chan;
215
216 /* check if we caused the interrupt */
217 if (!bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_IRQ+off))
218 return 0; /* nope, exit */
219
220 /* is the card in running state yet? */
221 if (du->du_state == DAIC_STATE_TESTING) {
222 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RC+off, 0);
223 du->du_state = DAIC_STATE_RUNNING;
224 wakeup(du);
225 goto done;
226 }
227
228 /* what caused the interrupt? */
229 /* (1) Check for a return code */
230 rc = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RC+off);
231 rcid = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RCID+off);
232 if (!rc) goto check_ind;
233
234 /* maybe an assign answer (positive or negative) */
235 if (rc == DAIC_RC_ASSIGN_OK) {
236 du->du_assign_res = rcid;
237 /* assing rc is special, we tell the card it's done */
238 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_REQ+off, 0);
239 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RC+off, 0);
240 /* we handle some types of assigns to global dchannel id's automaticaly */
241 if (du->du_assign & DAIC_ASSIGN_GLOBAL) {
242 du->du_global_dchan = rcid;
243 du->du_assign &= ~(DAIC_ASSIGN_GLOBAL|DAIC_ASSIGN_PENDING);
244 if (du->du_assign & DAIC_ASSIGN_SLEEPING) {
245 du->du_assign = 0;
246 wakeup(&du->du_assign_res);
247 }
248 } else {
249 wakeup(&du->du_assign);
250 }
251 goto check_ind;
252 } else if ((rc & DAIC_RC_ASSIGN_MASK) == DAIC_RC_ASSIGN_RC) {
253 printf("%s: assign request failed, error 0x%02x: %s\n",
254 sc->sc_dev.dv_xname, rc & DAIC_RC_ERRMASK,
255 err_codes[rc & DAIC_RC_ERRMASK]);
256 du->du_assign_res = 0;
257 /* assing rc is special, we tell the card it's done */
258 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_REQ+off, 0);
259 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RC+off, 0);
260 /* that's it */
261 wakeup(&du->du_assign);
262 goto check_ind;
263 }
264 if (rcid == du->du_global_dchan) {
265 du->du_request_res = rc;
266 wakeup(&du->du_request_res);
267 goto req_done;
268 }
269 for (chan = 0; chan < 2; chan++) {
270 if (rcid == sc->sc_con[port*2+chan].dchan_inst) {
271 sc->sc_con[port*2+chan].dchan_rc = rc;
272 wakeup(&sc->sc_con[port*2+chan].dchan_rc);
273 goto req_done;
274 } else if (rcid == sc->sc_con[port*2+chan].bchan_inst) {
275 sc->sc_con[port*2+chan].bchan_rc = rc;
276 wakeup(&sc->sc_con[port*2+chan].bchan_rc);
277 goto req_done;
278 }
279 }
280 TAILQ_FOREACH(assoc, &sc->sc_outcalls[port], queue) {
281 if (rcid == assoc->dchan_id) {
282 assoc->rc = rc;
283 wakeup(assoc);
284 goto req_done;
285 }
286 }
287
288 /* not found? */
289 printf("%s: unknown id 0x%02x got rc 0x%02x: %s\n",
290 sc->sc_dev.dv_xname, rcid, rc,
291 err_codes[rc & DAIC_RC_ERRMASK]);
292
293 req_done:
294 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RC+off, 0);
295
296 check_ind:
297 /* (2) Check for an indication */
298 ind = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_IND+off);
299 indid = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_INDID+off);
300 if (!ind) goto done;
301
302 /* incoming call routed to global dchannel task? */
303 if (indid == du->du_global_dchan) {
304 if (ind == DAIC_IND_INDICATE) {
305 daic_indicate_ind(sc, port);
306 } else if (ind == DAIC_IND_INFO) {
307 int i;
308
309 printf("%s: got info indication\n",
310 sc->sc_dev.dv_xname);
311
312 for (i = 0; i < 48; i++) {
313 if (!(i % 16))
314 printf("\n%02x:", i);
315 printf(" %02x", bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+off+i));
316 }
317 printf("\n");
318 } else if (ind == DAIC_IND_HANGUP) {
319 printf("%s: got global HANGUP indication\n",
320 sc->sc_dev.dv_xname);
321 } else {
322 printf("%s: unknown global indication: 0x%02x\n",
323 sc->sc_dev.dv_xname, ind);
324 }
325 goto ind_done;
326 }
327
328 for (chan = 0; chan < 2; chan++) {
329 if (indid == sc->sc_con[port*2+chan].dchan_inst) {
330 printf("%s: D-Channel indication 0x%02x for channel %d\n",
331 sc->sc_dev.dv_xname, ind, chan);
332 goto ind_done;
333 } else if (indid == sc->sc_con[port*2+chan].bchan_inst) {
334 printf("%s: B-Channel indication 0x%02x for channel %d\n",
335 sc->sc_dev.dv_xname, ind, chan);
336 goto ind_done;
337 }
338 }
339
340 TAILQ_FOREACH(assoc, &sc->sc_outcalls[port], queue) {
341 if (indid == assoc->dchan_id) {
342 printf("%s: D-Channel indication 0x%02x for outgoing call with cdid %d\n",
343 sc->sc_dev.dv_xname, ind, assoc->cdid);
344 goto ind_done;
345 }
346 }
347
348 /* not found - something's wrong! */
349 printf("%s: got ind 0x%02x for id 0x%02x\n", sc->sc_dev.dv_xname, ind, indid);
350
351 ind_done:
352 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_IND+off, 0);
353
354 done:
355 /* tell card we're ready for more... */
356 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_IRQ+off, 0);
357
358 return 1;
359 }
360
361 /*---------------------------------------------------------------------------*
362 * Handle interrupts
363 *---------------------------------------------------------------------------*/
364 int
daic_intr(sc)365 daic_intr(sc)
366 struct daic_softc *sc;
367 {
368 int handeld = 0;
369 if (sc->sc_cardtype == DAIC_TYPE_QUAD) {
370 int i;
371 for (i = 0; i < 4; i++)
372 handeld |= daic_handle_intr(sc, i);
373 } else
374 handeld = daic_handle_intr(sc, 0);
375 return handeld;
376 }
377
378 /*---------------------------------------------------------------------------*
379 * Download primary protocol microcode to on-board processor
380 *---------------------------------------------------------------------------*/
381 static int
daic_download(token,count,data)382 daic_download(token, count, data)
383 void *token;
384 int count;
385 struct isdn_dr_prot *data;
386 {
387 struct daic_unit *du = token;
388 struct daic_softc *sc = du->du_sc;
389 int i;
390
391 if (sc->sc_cardtype != DAIC_TYPE_QUAD)
392 count = 1; /* XXX - or signal error ? */
393
394 for (i = 0; i < count; i++) {
395 int off = DAIC_ISA_MEMSIZE * i;
396 u_int8_t *p = data[i].microcode;
397 size_t s = data[i].bytecount;
398 u_int32_t sw_id;
399 int cnt, x;
400 for (p = data[i].microcode+4, cnt = 0; *p && cnt < 70; p++, cnt++)
401 ;
402 sw_id = p[1] | (p[2] << 8) | (p[3] << 16) | (p[4] << 24);
403 if (sc->sc_cardtype == DAIC_TYPE_QUAD)
404 printf("%s port %d: downloading %s\n",
405 sc->sc_dev.dv_xname, i, data[i].microcode+4);
406 else
407 printf("%s: downloading %s\n",
408 sc->sc_dev.dv_xname, data[i].microcode+4);
409 x = splnet();
410 p = data[i].microcode;
411 while (s > 0) {
412 size_t size = (s > 256) ? 256 : s;
413 bus_space_write_region_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_BUF+off, p, size);
414 p += size;
415 s -= size;
416 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_CTRL+off, 1);
417 splx(x);
418 for (cnt = 0; cnt < 2*hz; cnt++) {
419 x = splnet();
420 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_CTRL+off) == 0)
421 break;
422 splx(x);
423 tsleep(sc, 0, "daic download", 1);
424 }
425 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_CTRL+off) != 0) {
426 splx(x);
427 printf("%s: download of microcode failed\n",
428 sc->sc_dev.dv_xname);
429 return EIO;
430 }
431 }
432
433 /* configure microcode - no parameters yet - XXX */
434 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_TEI+off, 0);
435 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_NT2+off, 0);
436 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_ZERO+off, 0);
437 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_WATCHDOG+off, 0);
438 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_PERMANENT+off, 0);
439 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_XINTERFACE+off, 0);
440
441 /* start protocol */
442 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_CTRL+off, 2);
443
444 /* wait for signature */
445 for (cnt = 0; cnt < 2*hz; cnt++) {
446 u_int16_t signature;
447 signature = bus_space_read_2(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_SIGNATURE+off);
448 if (signature == DAIC_SIGNATURE_VALUE)
449 break;
450 if (signature) {
451 if (signature != DAIC_SIGNATURE_VALUE) {
452 splx(x);
453 printf("%s: microcode signature bad: should be %04x, is %04x\n",
454 sc->sc_dev.dv_xname, DAIC_SIGNATURE_VALUE,signature);
455 return EIO;
456 }
457 break;
458 }
459 splx(x);
460 tsleep(&sc->sc_port[i].du_state, 0, "daic protocol init", hz/25);
461 x = splnet();
462 }
463
464 /* real check: send an invalid request and wait for an interrupt */
465 sc->sc_port[i].du_state = DAIC_STATE_TESTING;
466 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RC+off, 0);
467 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_REQID+off, 0xff);
468 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_REQ+off, 1);
469 splx(x);
470 tsleep(&sc->sc_port[i].du_state, 0, "daic irq test", 2*hz);
471 x = splnet();
472 if (sc->sc_port[i].du_state != DAIC_STATE_RUNNING) {
473 splx(x);
474 printf("%s: download interrupt test timeout\n",
475 sc->sc_dev.dv_xname);
476 return EIO;
477 }
478
479 /* finish card configuration */
480 bus_space_write_4(sc->sc_iot, sc->sc_ioh, DAIC_SWID+off, sw_id);
481 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_SET_CARD+off, sc->sc_cardtype);
482 splx(x);
483
484 /* assign global d-channel id for that port */
485 sc->sc_port[i].du_global_dchan =
486 daic_assign(sc, i, DAIC_GLOBALID_DCHAN,
487 sizeof parm_global_assign, parm_global_assign);
488
489 /* send an INDICATE request to get incoming calls on this id */
490 x = splnet();
491 VOIDREQ(sc, i, DAIC_REQ_INDICATE, sc->sc_port[i].du_global_dchan);
492 splx(x);
493 tsleep(&sc->sc_port[i].du_request_res, 0, "daic request", 0);
494 x = splnet();
495 if (sc->sc_port[i].du_request_res != DAIC_RC_OK) {
496 printf("%s: INDICATE request error (0x%02x): %s\n",
497 sc->sc_dev.dv_xname, sc->sc_port[i].du_request_res,
498 err_codes[sc->sc_port[i].du_request_res & DAIC_RC_ERRMASK]);
499 splx(x);
500 return EIO;
501 }
502 splx(x);
503 }
504 return 0;
505 }
506
507 /*---------------------------------------------------------------------------*
508 * Reset the card, download primary bootstrap, let it check the
509 * card and return the cardtype identified by the microcode
510 * or -1 if no known card is detected.
511 *---------------------------------------------------------------------------*/
512 static int
daic_reset(bus,io,port,memsize)513 daic_reset(bus, io, port, memsize)
514 bus_space_tag_t bus;
515 bus_space_handle_t io;
516 int port;
517 int *memsize;
518 {
519 int i, off = port * DAIC_ISA_MEMSIZE;
520 int cardtype, mem, quiet = memsize == NULL; /* no output if we are only probing */
521
522 /* clear any pending interrupt */
523 bus_space_read_1(bus, io, DAIC_IRQ+off);
524 /* reset card */
525 bus_space_write_1(bus, io, DAIC_BOOT_SET_RESET+off, 0);
526
527 /* download primary bootstrap */
528 bus_space_set_region_1(bus, io, DAIC_BOOT_START+off, 0, DAIC_BOOT_CODE-DAIC_BOOT_START);
529 bus_space_write_region_1(bus, io, DAIC_BOOT_CODE+off, dnload, DAIC_BOOT_END-DAIC_BOOT_CODE+1);
530 if (bus_space_read_1(bus, io, DAIC_BOOT_CTRL+off)
531 || bus_space_read_1(bus, io, DAIC_BOOT_EBIT+off)) {
532 if (!quiet) printf(": shared memory test failed!\n");
533 return -1;
534 }
535 /* let card perform memory test */
536 bus_space_write_1(bus, io, DAIC_BOOT_CTRL+off, DAIC_TEST_MEM);
537 /* and off we go... */
538 bus_space_write_1(bus, io, DAIC_BOOT_CLR_RESET+off, 0);
539 /* wait for response from bootstrap */
540 for (i = 0; i < 15000 && bus_space_read_1(bus, io, DAIC_BOOT_CTRL+off) != DAIC_TEST_RDY; i++)
541 DELAY(100);
542 if (i >= 15000) {
543 if (!quiet) printf(": on board processor test failed!\n");
544 return -1;
545 }
546 if (bus_space_read_1(bus, io, DAIC_BOOT_EBIT+off)) {
547 if (!quiet) printf(": on board memory test failed at %p\n",
548 (void*)bus_space_read_2(bus, io, DAIC_BOOT_ELOC+off));
549 return -1;
550 }
551
552 /* fetch info from primary bootstrap code */
553 cardtype = bus_space_read_1(bus, io, DAIC_BOOT_CARD+off);
554 mem = bus_space_read_1(bus, io, DAIC_BOOT_MSIZE+off) << 4;
555 if (memsize)
556 *memsize = mem;
557
558 return cardtype;
559 }
560
561 /*---------------------------------------------------------------------------*
562 * Generic diagnostic interface - pass through the microcode data
563 * without knowing too much about it. This passes a lot work to
564 * userland, but hey, this is only a diagnostic tool...
565 *---------------------------------------------------------------------------*/
566 static int
daic_diagnostic(token,req)567 daic_diagnostic(token, req)
568 void *token;
569 struct isdn_diagnostic_request *req;
570 {
571 struct daic_unit *du = token;
572 struct daic_softc *sc = du->du_sc;
573 int port = du->du_port;
574 int off = port * DAIC_ISA_MEMSIZE;
575 int rc, cnt;
576 int s, err = 0;
577
578 /* validate parameters */
579 if (req->cmd < 0 || req->cmd > DAIC_DIAG_MAXCMD) {
580 printf("%s: daic_diagnostic: illegal cmd %d\n",
581 sc->sc_dev.dv_xname, req->cmd);
582 return EIO;
583 }
584 if (req->out_param_len > (DAIC_DIAG_DATA_SIZE+1)) {
585 printf("%s: daic_diagnostic: illegal out_param_len %d\n",
586 sc->sc_dev.dv_xname, req->out_param_len);
587 return EIO;
588 }
589
590 /* XXX - only for debug */
591 if (req->cmd == 0x05) {
592 /* pass through request from userland */
593
594 u_int8_t id;
595 static u_int8_t parms[] = {
596 IEI_CALLID, 0x01, 0x81,
597 IEI_CALLINGPN, 7, NUMBER_TYPEPLAN, '9', '8', '9', '0', '2', '0',
598 0x96, 0x01, 0x02, 0x01, 0x00,
599 0x00
600 };
601
602 /* create the d-channel task for this call */
603 printf("%s: assigning id for pass-through call\n", sc->sc_dev.dv_xname);
604 id = daic_assign(sc, port, DAIC_GLOBALID_DCHAN, sizeof(parms), parms);
605 printf("%s: got id 0x%02x\n", sc->sc_dev.dv_xname, id);
606
607 #ifdef DAIC_DEBUG
608 daic_dump_request(sc, port, DAIC_REQ_CALL, id, req->in_param_len, req->in_param);
609 #endif
610 daic_request(sc, port, DAIC_REQ_CALL, id, req->in_param_len, req->in_param);
611 return 0;
612 }
613
614 /* all these need an output parameter */
615 if (req->out_param == NULL)
616 return EIO;
617
618 /* check state and switch to DIAGNOSTIC */
619 s = splnet();
620 if (sc->sc_port[port].du_state != DAIC_STATE_RUNNING) {
621 splx(s);
622 return EWOULDBLOCK;
623 }
624 sc->sc_port[port].du_state = DAIC_STATE_DIAGNOSTIC;
625 splx(s);
626
627 /* set new request */
628 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_REQ+off, req->cmd);
629
630 /* sorry, no interrupt on completition - have to poll */
631 for (cnt = 0; cnt < 3*hz; cnt++) {
632 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_REQ+off) == 0
633 && bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_RC+off) != 0)
634 break;
635 tsleep(sc, 0, "daic diagnostic", 1);
636 }
637 rc = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_RC+off);
638 if (rc == 0) {
639 /* stop request and return error */
640 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_REQ+off, 0);
641 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_RC+off, 0);
642 err = EIO;
643 goto done;
644 }
645 /* out param gets rc and all the data */
646 if (req->out_param_len >= 2) {
647 ((u_int8_t*)(req->out_param))[0] = (u_int8_t)rc;
648 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);
649 }
650 /* acknowledge data */
651 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_RC+off, 0);
652
653 done: /* back to normal state */
654 s = splnet();
655 sc->sc_port[port].du_state = DAIC_STATE_RUNNING;
656 splx(s);
657
658 return err;
659 }
660
daic_stat(void * port,int channel,bchan_statistics_t * bsp)661 static void daic_stat(void *port, int channel, bchan_statistics_t *bsp)
662 {
663 }
664
665 static const struct isdn_l4_bchannel_functions
666 daic_l4_driver = {
667 daic_bch_config,
668 daic_bch_tx_start,
669 daic_stat
670 };
671
672 static const struct isdn_l3_driver_functions
673 daic_l3_functions = {
674 daic_ret_linktab,
675 daic_set_link,
676 daic_connect_request,
677 daic_connect_response,
678 daic_disconnect_request,
679 daic_alert_request,
680 daic_download,
681 daic_diagnostic,
682 daic_mgmt_command
683 };
684
685 /*---------------------------------------------------------------------------*
686 * Register one port and attach it to the upper layers
687 *---------------------------------------------------------------------------*/
688 static void
daic_register_port(struct daic_softc * sc,int port)689 daic_register_port(struct daic_softc *sc, int port)
690 {
691 int chan;
692 char cardname[80], devname[80];
693 struct isdn_l3_driver * l3drv;
694
695 sc->sc_port[port].du_port = port;
696 sc->sc_port[port].du_sc = sc;
697
698 /* make sure this hardware driver type is known to layer 4 */
699 if (sc->sc_cardtype == DAIC_TYPE_QUAD)
700 sprintf(devname, "%s port %d", sc->sc_dev.dv_xname, port);
701 else
702 strlcpy(devname, sc->sc_dev.dv_xname, sizeof (devname));
703 sprintf(cardname, "EICON.Diehl %s", cardtypename(sc->sc_cardtype));
704 l3drv = isdn_attach_bri(
705 devname, cardname, &sc->sc_port[port], &daic_l3_functions);
706 sc->sc_port[port].du_l3 = l3drv;
707
708 /* initialize linktabs for this port */
709 for (chan = 0; chan < 2; chan++) {
710 isdn_link_t *lt = &sc->sc_con[port*2+chan].isdn_linktab;
711 lt->l1token = &sc->sc_port[port];
712 lt->channel = chan;
713 lt->tx_queue = &sc->sc_con[port*2+chan].tx_queue;
714 lt->rx_queue = &sc->sc_con[port*2+chan].rx_queue;
715 }
716 TAILQ_INIT(&sc->sc_outcalls[port]);
717
718 isdn_bri_ready(l3drv->bri);
719 }
720
721 /*---------------------------------------------------------------------------*
722 * return the address of daic drivers linktab
723 *---------------------------------------------------------------------------*/
724 static isdn_link_t *
daic_ret_linktab(void * token,int channel)725 daic_ret_linktab(void *token, int channel)
726 {
727 struct daic_unit *du = token;
728 struct daic_softc *sc = du->du_sc;
729 int port = du->du_port;
730 struct daic_connection *con = &sc->sc_con[port*2+channel];
731
732 return(&con->isdn_linktab);
733 }
734
735 /*---------------------------------------------------------------------------*
736 * set the driver linktab in the b channel softc
737 *---------------------------------------------------------------------------*/
738 static void
daic_set_link(void * token,int channel,const struct isdn_l4_driver_functions * l4_driver,void * l4_inst)739 daic_set_link(void *token, int channel, const struct isdn_l4_driver_functions *l4_driver, void *l4_inst)
740 {
741 struct daic_unit *du = token;
742 struct daic_softc *sc = du->du_sc;
743 int port = du->du_port;
744 struct daic_connection *con = &sc->sc_con[port*2+channel];
745
746 con->l4_driver = l4_driver;
747 con->l4_driver_softc = l4_inst;
748 }
749
750 /*---------------------------------------------------------------------------*
751 * Send a request to the card.
752 *---------------------------------------------------------------------------*/
753 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)754 daic_request(
755 struct daic_softc *sc, /* ourself */
756 int port, /* and the port on this card */
757 u_int req, /* the request to send */
758 u_int id, /* id of communication task */
759 bus_size_t parmsize, /* size of parms including the terminating zero */
760 const u_int8_t *parms) /* pointer to parms to pass */
761 {
762 int off = port*DAIC_ISA_MEMSIZE;
763
764 /* spin while card is yet busy */
765 while (bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_REQ))
766 ; /* unlikely to happen with this driver */
767
768 /* output parameters */
769 bus_space_write_region_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_XBUFFER+off, parms, parmsize);
770
771 /* output request and id */
772 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_REQID+off, id);
773 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_REQ+off, req);
774 }
775
776 /*---------------------------------------------------------------------------*
777 * Assign a unique instance id for some communication class
778 * on the card. Only one assign request may be running on a
779 * port at any time, handle this and return the instance id.
780 *---------------------------------------------------------------------------*/
781 static u_int
daic_assign(struct daic_softc * sc,int port,u_int classid,bus_size_t parmsize,const u_int8_t * parms)782 daic_assign(
783 struct daic_softc *sc, /* our state and port no */
784 int port,
785 u_int classid, /* Diehl calls this "global instance id" */
786 bus_size_t parmsize, /* sizeof paramter arra */
787 const u_int8_t *parms) /* task instance parameters */
788 {
789 static char wchan[] = "daic assign";
790 u_int8_t id;
791 int x;
792
793 /* there only may be one assignment running concurrently */
794 x = splnet();
795 for (;;) {
796 if (!(sc->sc_port[port].du_assign & DAIC_ASSIGN_PENDING))
797 break; /* we got it! */
798
799 /* somebody else is assigning, record state and sleep */
800 sc->sc_port[port].du_assign |= DAIC_ASSIGN_SLEEPING;
801 tsleep(&sc->sc_port[port].du_assign_res, 0, wchan, 0);
802 }
803
804 /* put parameters and request to card */
805 sc->sc_port[port].du_assign |= DAIC_ASSIGN_PENDING;
806 daic_request(sc, port, DAIC_REQ_ASSIGN, classid, parmsize, parms);
807
808 /* wait for completition of assignment by the card */
809 tsleep(&sc->sc_port[port].du_assign, 0, wchan, 0);
810 id = sc->sc_port[port].du_assign_res;
811
812 /* have we lost our global dchannel id in the meantime? */
813 if (sc->sc_port[port].du_assign & DAIC_ASSIGN_NOGLOBAL) {
814 /* start an assign request and let the result
815 be handled by the interrupt handler - we don't
816 have to wait for it here. As the assign lock
817 isn't freed, we don't wake up others... */
818 sc->sc_port[port].du_assign &= ~DAIC_ASSIGN_NOGLOBAL;
819 sc->sc_port[port].du_assign |= DAIC_ASSIGN_PENDING|DAIC_ASSIGN_GLOBAL;
820 daic_request(sc, port, DAIC_REQ_ASSIGN, DAIC_GLOBALID_DCHAN,
821 sizeof parm_global_assign, parm_global_assign);
822 splx(x);
823 return id;
824 }
825
826 /* XXX - review this, can't remember why I did it this complicated */
827
828 /* unlock and wakup others, if any */
829 if (sc->sc_port[port].du_assign & DAIC_ASSIGN_SLEEPING) {
830 sc->sc_port[port].du_assign = 0;
831 wakeup(&sc->sc_port[port].du_assign_res);
832 } else
833 sc->sc_port[port].du_assign = 0;
834 splx(x);
835
836 return id;
837 }
838
839 #ifdef DAIC_DEBUG
840 /*---------------------------------------------------------------------------*
841 * Debug output of request parameters
842 *---------------------------------------------------------------------------*/
843 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)844 daic_dump_request(struct daic_softc *sc, int port, u_int req, u_int id, bus_size_t parmsize, u_int8_t *parms)
845 {
846 int i;
847 printf("%s: request 0x%02x to task id 0x%02x:",
848 sc->sc_dev.dv_xname, req, id);
849 for (i = 0; i < parmsize; i++) {
850 if (i % 16 == 0)
851 printf("\n%02x:", i);
852 printf(" %02x", parms[i]);
853 }
854 printf("\n");
855 }
856 #endif
857
858 /*---------------------------------------------------------------------------*
859 * Decode parameters of an INDICATE indication from the card
860 * and pass them to layer 4. Called from within an interrupt
861 * context.
862 *---------------------------------------------------------------------------*/
863 static void
daic_indicate_ind(struct daic_softc * sc,int port)864 daic_indicate_ind(struct daic_softc *sc, int port)
865 {
866 int offset = port*DAIC_ISA_MEMSIZE;
867 int i;
868 u_int8_t ie, ielen;
869 call_desc_t *cd;
870
871 /* get and init new calldescriptor */
872 cd = reserve_cd(); /* cdid filled in */
873 cd->bprot = BPROT_NONE;
874 cd->cause_in = 0;
875 cd->cause_out = 0;
876 cd->dst_telno[0] = '\0';
877 cd->src_telno[0] = '\0';
878 cd->channelid = CHAN_NO;
879 cd->channelexcl = 0;
880 cd->cr = -1;
881 cd->crflag = CRF_DEST;
882 cd->ilt = NULL; /* reset link tab ptrs */
883
884 i = 0;
885 for (;;) {
886 ie = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+offset+i);
887 if (!ie) break;
888 i++;
889 if (ie & 0x80) continue;
890 ielen = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+offset+i);
891 i++;
892 switch (ie) {
893 case IEI_BEARERCAP:
894 ie = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+offset+i);
895 if (ie == 0x80 || ie == 0x89 || ie == 0x90)
896 cd->bprot = BPROT_NONE;
897 else if (ie == 0x88)
898 cd->bprot = BPROT_RHDLC;
899 break;
900 case IEI_CALLINGPN:
901 {
902 int off;
903 ie = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+offset+i);
904 if (ie & 0x80)
905 off = 1;
906 else
907 off = 2;
908 bus_space_read_region_1(sc->sc_iot, sc->sc_ioh,
909 DAIC_COM_RBUFFER+offset+i+off, cd->src_telno,
910 ielen - off);
911 cd->src_telno[ielen-off+1] = '\0';
912 }
913 break;
914 case IEI_CALLEDPN:
915 bus_space_read_region_1(sc->sc_iot, sc->sc_ioh,
916 DAIC_COM_RBUFFER+offset+i+1,
917 cd->dst_telno, ielen-1);
918 cd->dst_telno[ielen] = '\0';
919 break;
920 case IEI_CHANNELID:
921 ie = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+offset+i);
922 if ((ie & 0xf4) != 0x80)
923 cd->channelid = CHAN_NO;
924 else {
925 switch(ie & 0x03) {
926 case IE_CHAN_ID_NO: cd->channelid = CHAN_NO; break;
927 case IE_CHAN_ID_B1: cd->channelid = CHAN_B1; break;
928 case IE_CHAN_ID_B2: cd->channelid = CHAN_B2; break;
929 case IE_CHAN_ID_ANY: cd->channelid = CHAN_ANY; break;
930 }
931 cd->channelexcl = (ie & 0x08) >> 3;
932 }
933 }
934 i += ielen;
935 }
936 cd->event = EV_SETUP;
937 /* ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_RSVD; */
938
939 /* record the dchannel id for this call and the call descriptor */
940 sc->sc_con[port*2+cd->channelid].dchan_inst = sc->sc_port[port].du_global_dchan;
941 sc->sc_con[port*2+cd->channelid].cdid = cd->cdid;
942
943 /* this task is busy now, we need a new global dchan id */
944 if (sc->sc_port[port].du_assign & DAIC_ASSIGN_PENDING) {
945 /* argh - can't assign right now */
946 sc->sc_port[port].du_assign |= DAIC_ASSIGN_NOGLOBAL;
947 } else {
948 /* yeah - can request the assign right away, but let the
949 interrupt handler autohandle the result */
950 sc->sc_port[port].du_assign |= DAIC_ASSIGN_PENDING|DAIC_ASSIGN_GLOBAL;
951 daic_request(sc, port, DAIC_REQ_ASSIGN, DAIC_GLOBALID_DCHAN,
952 sizeof parm_global_assign, parm_global_assign);
953 }
954
955 if (cd->bprot == BPROT_NONE)
956 printf("\nincoming voice call from \"%s\" to \"%s\"\n",
957 cd->src_telno, cd->dst_telno);
958 else
959 printf("\nincoming data call from \"%s\" to \"%s\"\n",
960 cd->src_telno, cd->dst_telno);
961
962 /* hand up call to layer 4 */
963 i4b_l4_connect_ind(cd);
964 }
965
966 /*---------------------------------------------------------------------------*
967 * Layer 4 request a call setup
968 *---------------------------------------------------------------------------*/
969 static void
daic_connect_request(struct call_desc * cd)970 daic_connect_request(struct call_desc *cd)
971 {
972 u_int8_t id, cpn[TELNO_MAX+4], parms[TELNO_MAX+16], *p;
973 struct daic_unit *du = cd->ilt->l1token;
974 struct daic_softc *sc = du->du_sc;
975 int port = du->du_port;
976 int x, len;
977 struct outcallentry *assoc;
978
979 /* to associate the cdid with the communication task
980 we are going to create for this outgoing call,
981 we maintain a queue of pending outgoing calls.
982 As soon as a SETUP response is received, we move
983 the association to the allocated b-channel. */
984
985 /* configure d-channel task parameters */
986 p = parms;
987 *p++ = IEI_CALLID; *p++ = 0x01;
988 if (cd->bprot == BPROT_NONE) {
989 *p++ = 0x82;
990 } else if (cd->bprot == BPROT_RHDLC) {
991 *p++ = 0x85;
992 } else {
993 printf("%s: daic_connect_request for unknown bchan protocol 0x%x\n",
994 sc->sc_dev.dv_xname, cd->bprot);
995 return;
996 }
997 if (cd->src_telno[0]) {
998 *p++ = IEI_CALLINGPN;
999 *p++ = strlen(cd->src_telno)+1;
1000 *p++ = NUMBER_TYPEPLAN;
1001 strlcpy(p, cd->src_telno, sizeof (parms) - (p - parms));
1002 p += strlen(p);
1003 }
1004 if (cd->channelid == CHAN_B1 || cd->channelid == CHAN_B2) {
1005 *p++ = IEI_CHANNELID;
1006 *p++ = 0x01;
1007 *p++ = 0x81 + cd->channelid;
1008 }
1009 if (cd->bprot == BPROT_NONE) {
1010 *p++ = 0x96; /* shift6 */
1011 *p++ = 0x01; /* SIN */
1012 *p++ = 0x02; /* len */
1013 *p++ = 0x01; /* Telephony */
1014 *p++ = 0x00; /* add.info */
1015 }
1016 *p++ = 0;
1017
1018 /* create the d-channel task for this call */
1019 id = daic_assign(sc, port, DAIC_GLOBALID_DCHAN, p - parms, parms);
1020
1021 /* map it to the call descriptor id */
1022 assoc = malloc(sizeof(struct outcallentry), M_DEVBUF, 0);
1023 assoc->cdid = cd->cdid;
1024 assoc->dchan_id = id;
1025 x = splnet();
1026 TAILQ_INSERT_TAIL(&sc->sc_outcalls[port], assoc, queue);
1027
1028 /* send a call request */
1029 len = strlen(cd->dst_telno);
1030 cpn[0] = IEI_CALLEDPN;
1031 cpn[1] = len+1;
1032 cpn[2] = NUMBER_TYPEPLAN;
1033 strlcpy(cpn + 3, cd->dst_telno, sizeof (cpn) - 3);
1034 #ifdef DAIC_DEBUG
1035 daic_dump_request(sc, port, DAIC_REQ_CALL, id, len+4, cpn);
1036 #endif
1037 daic_request(sc, port, DAIC_REQ_CALL, id, len+4, cpn);
1038 splx(x);
1039 tsleep(assoc, 0, "daic call", 0);
1040 if (assoc->rc != DAIC_RC_OK) {
1041 printf("%s: call request failed, error 0x%02x: %s\n",
1042 sc->sc_dev.dv_xname, assoc->rc & DAIC_RC_ERRMASK,
1043 err_codes[assoc->rc & DAIC_RC_ERRMASK]);
1044 }
1045 }
1046
1047 /*---------------------------------------------------------------------------*
1048 * TODO:
1049 *---------------------------------------------------------------------------*/
daic_connect_response(struct call_desc * cd,int response,int cause)1050 static void daic_connect_response(struct call_desc *cd, int response, int cause)
1051 {
1052 }
1053
1054 /*---------------------------------------------------------------------------*
1055 * TODO:
1056 *---------------------------------------------------------------------------*/
daic_disconnect_request(struct call_desc * cd,int cause)1057 static void daic_disconnect_request(struct call_desc *cd, int cause)
1058 {
1059 }
1060
1061 /*---------------------------------------------------------------------------*
1062 * TODO:
1063 *---------------------------------------------------------------------------*/
daic_bch_config(void * token,int channel,int bprot,int updown)1064 static void daic_bch_config(void *token, int channel, int bprot, int updown)
1065 {
1066 printf("daic: bch_config\n");
1067 }
1068
1069 /*---------------------------------------------------------------------------*
1070 * TODO:
1071 *---------------------------------------------------------------------------*/
daic_bch_tx_start(void * token,int channel)1072 static void daic_bch_tx_start(void *token, int channel)
1073 {
1074 printf("daic: bch_tx_start\n");
1075 }
1076
1077 /*---------------------------------------------------------------------------*
1078 * TODO:
1079 *---------------------------------------------------------------------------*/
1080 static void
daic_mgmt_command(struct isdn_l3_driver * drv,int cmd,void * parm)1081 daic_mgmt_command(struct isdn_l3_driver *drv, int cmd, void *parm)
1082 {
1083 }
1084
1085 /*---------------------------------------------------------------------------*
1086 * TODO:
1087 *---------------------------------------------------------------------------*/
1088 static void
daic_alert_request(struct call_desc * cd)1089 daic_alert_request(struct call_desc *cd)
1090 {
1091 }
1092
1093