1/*- 2 * Copyright (c) 2002 The NetBSD Foundation, Inc. 3 * All rights reserved. 4 * 5 * This code is derived from software contributed to The NetBSD Foundation 6 * by Martin Husemann <martin@NetBSD.org>. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 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. 16 * 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. 28 * 29 */ 30 31#include <sys/cdefs.h> 32__KERNEL_RCSID(0, "$NetBSD: daic.c,v 1.29 2009/05/12 14:25:17 cegger Exp $"); 33 34/* 35 * daic.c: MI driver for Diehl active ISDN cards (S, SX, SXn, SCOM, QUADRO) 36 */ 37 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> 45#include <sys/proc.h> 46#include <sys/socket.h> 47#include <net/if.h> 48 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> 55 56#include <sys/bus.h> 57#include <dev/ic/daicvar.h> 58#include <dev/ic/daicreg.h> 59#include <dev/microcode/daic/dnload.h> 60 61#ifdef NetBSD1_3 62#if NetBSD1_3 < 2 63/* the device is MI, only the attach struct is in the bus 64 dependent frontend. And only on old versions... */ 65struct cfdriver daic_cd = { 66 NULL, "daic", DV_DULL 67}; 68#endif 69#endif 70 71/* local function prototypes */ 72static const char * cardtypename(int cardtype); 73static int daic_download(void *, int portcount, struct isdn_dr_prot *data); 74static int daic_diagnostic(void *, struct isdn_diagnostic_request *req); 75static void daic_connect_request(struct call_desc *cd); 76static void daic_connect_response(struct call_desc *cd, int, int); 77static void daic_disconnect_request(struct call_desc *cd, int); 78static int daic_reset(bus_space_tag_t bus, bus_space_handle_t io, int port, int *memsize); 79static int daic_handle_intr(struct daic_softc *sc, int port); 80static void daic_register_port(struct daic_softc *sc, int port); 81static void daic_request(struct daic_softc *sc, int port, u_int req, u_int id, bus_size_t parmsize, const u_int8_t *parms); 82static u_int daic_assign(struct daic_softc *sc, int port, u_int instance, bus_size_t parmsize, const u_int8_t *parms); 83static void daic_indicate_ind(struct daic_softc *sc, int port); 84static void daic_bch_config(void *, int channel, int bprot, int updown); 85static void daic_bch_tx_start(void *, int channel); 86static void daic_set_link(void *softc, int channel, 87 const struct isdn_l4_driver_functions *l4_driver, void *l4_inst ); 88static void daic_mgmt_command(struct isdn_l3_driver *drv, int cmd, void *parm); 89static void daic_alert_request(struct call_desc *cd); 90 91static isdn_link_t *daic_ret_linktab(void *softc, int channel); 92 93#ifdef DAIC_DEBUG 94static void daic_dump_request(struct daic_softc *sc, int port, u_int req, u_int id, bus_size_t parmsize, u_int8_t *parms); 95#endif 96 97/* static data */ 98static const char * const cardnames[] = { 99 "S", "SX", "SCOM", "QUADRO" 100}; 101 102static const char * const err_codes[DAIC_RC_ERRMASK+1] = { 103 "NO ERROR", 104 "UNKNOWN COMMAND", 105 "WRONG COMMAND", 106 "WRONG ID", 107 "WRONG CH", 108 "UNKNOWN IE", 109 "WRONG IE", 110 "OUT OF RESOURCES" 111}; 112 113/* fixed parameters */ 114 115/* no parameters */ 116static u_int8_t parm_none[] = { 0 }; 117#define VOIDREQ(sc,port,req,id) daic_request(sc, port, req, id, sizeof parm_none, parm_none) 118 119/* assign request for the global d-channel instance */ 120static 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 */ 128/* end of parms */ 129 0x00 130}; 131 132/*---------------------------------------------------------------------------* 133 * Return the name of a card with given cardtype 134 *---------------------------------------------------------------------------*/ 135static const char * 136cardtypename(int cardtype) 137{ 138 if (cardtype >= 0 && cardtype < (sizeof(cardnames) / sizeof(cardnames[0]))) 139 return cardnames[cardtype]; 140 else 141 return "unknown type"; 142} 143 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 *---------------------------------------------------------------------------*/ 149int 150daic_probe(bus_space_tag_t bus, bus_space_handle_t io) 151{ 152 return (daic_reset(bus, io, 0, NULL)); 153} 154 155/*---------------------------------------------------------------------------* 156 * Attach and initialize the card at given io space. 157 *---------------------------------------------------------------------------*/ 158void 159daic_attach(device_t self, struct daic_softc *sc) 160{ 161 int i, num_ports, memsize = 0; 162 163 /* init sc */ 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; 167 168 /* init card */ 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"); 172 return; 173 } 174 175 printf("\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; 182 183 /* register all ports this card has */ 184 for (i = 0; i < num_ports; i++) 185 daic_register_port(sc, i); 186} 187 188/*---------------------------------------------------------------------------* 189 * handle interrupts for one port of the card 190 *---------------------------------------------------------------------------*/ 191static int 192daic_handle_intr(struct daic_softc *sc, int port) 193{ 194 struct outcallentry *assoc; 195 struct daic_unit * du = &sc->sc_port[port]; 196 int off = port * DAIC_ISA_MEMSIZE; 197 u_int8_t rc, rcid; 198 u_int8_t ind, indid; 199 int chan; 200 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 */ 204 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; 209 wakeup(du); 210 goto done; 211 } 212 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; 218 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) { 230 du->du_assign = 0; 231 wakeup(&du->du_assign_res); 232 } 233 } else { 234 wakeup(&du->du_assign); 235 } 236 goto check_ind; 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); 245 /* that's it */ 246 wakeup(&du->du_assign); 247 goto check_ind; 248 } 249 if (rcid == du->du_global_dchan) { 250 du->du_request_res = rc; 251 wakeup(&du->du_request_res); 252 goto req_done; 253 } 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); 258 goto req_done; 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); 262 goto req_done; 263 } 264 } 265 TAILQ_FOREACH(assoc, &sc->sc_outcalls[port], queue) { 266 if (rcid == assoc->dchan_id) { 267 assoc->rc = rc; 268 wakeup(assoc); 269 goto req_done; 270 } 271 } 272 273 /* not found? */ 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]); 277 278req_done: 279 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RC+off, 0); 280 281check_ind: 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); 285 if (!ind) goto done; 286 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) { 292 int i; 293 294 printf("%s: got info indication\n", 295 device_xname(&sc->sc_dev)); 296 297 for (i = 0; i < 48; i++) { 298 if (!(i % 16)) 299 printf("\n%02x:", i); 300 printf(" %02x", bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+off+i)); 301 } 302 printf("\n"); 303 } else if (ind == DAIC_IND_HANGUP) { 304 printf("%s: got global HANGUP indication\n", 305 device_xname(&sc->sc_dev)); 306 } else { 307 printf("%s: unknown global indication: 0x%02x\n", 308 device_xname(&sc->sc_dev), ind); 309 } 310 goto ind_done; 311 } 312 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); 317 goto ind_done; 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); 321 goto ind_done; 322 } 323 } 324 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 device_xname(&sc->sc_dev), ind, assoc->cdid); 329 goto ind_done; 330 } 331 } 332 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); 335 336ind_done: 337 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_IND+off, 0); 338 339done: 340 /* tell card we're ready for more... */ 341 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_IRQ+off, 0); 342 343 return 1; 344} 345 346/*---------------------------------------------------------------------------* 347 * Handle interrupts 348 *---------------------------------------------------------------------------*/ 349int 350daic_intr(struct daic_softc *sc) 351{ 352 int handeld = 0; 353 if (sc->sc_cardtype == DAIC_TYPE_QUAD) { 354 int i; 355 for (i = 0; i < 4; i++) 356 handeld |= daic_handle_intr(sc, i); 357 } else 358 handeld = daic_handle_intr(sc, 0); 359 return handeld; 360} 361 362/*---------------------------------------------------------------------------* 363 * Download primary protocol microcode to on-board processor 364 *---------------------------------------------------------------------------*/ 365static int 366daic_download(void *token, int count, struct isdn_dr_prot *data) 367{ 368 struct daic_unit *du = token; 369 struct daic_softc *sc = du->du_sc; 370 int i; 371 372 if (sc->sc_cardtype != DAIC_TYPE_QUAD) 373 count = 1; /* XXX - or signal error ? */ 374 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; 379 u_int32_t sw_id; 380 int cnt, x; 381 for (p = data[i].microcode+4, cnt = 0; *p && cnt < 70; p++, cnt++) 382 ; 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); 387 else 388 printf("%s: downloading %s\n", 389 device_xname(&sc->sc_dev), data[i].microcode+4); 390 x = splnet(); 391 p = data[i].microcode; 392 while (s > 0) { 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); 395 p += size; 396 s -= size; 397 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_CTRL+off, 1); 398 splx(x); 399 for (cnt = 0; cnt < 2*hz; cnt++) { 400 x = splnet(); 401 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_CTRL+off) == 0) 402 break; 403 splx(x); 404 tsleep(sc, 0, "daic download", 1); 405 } 406 if (bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_CTRL+off) != 0) { 407 splx(x); 408 aprint_error_dev(&sc->sc_dev, "download of microcode failed\n"); 409 return EIO; 410 } 411 } 412 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); 420 421 /* start protocol */ 422 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_CTRL+off, 2); 423 424 /* wait for signature */ 425 for (cnt = 0; cnt < 2*hz; cnt++) { 426 u_int16_t signature; 427 signature = bus_space_read_2(sc->sc_iot, sc->sc_ioh, DAIC_BOOT_SIGNATURE+off); 428 if (signature == DAIC_SIGNATURE_VALUE) 429 break; 430 if (signature) { 431 if (signature != DAIC_SIGNATURE_VALUE) { 432 splx(x); 433 aprint_error_dev(&sc->sc_dev, "microcode signature bad: should be %04x, is %04x\n", 434 DAIC_SIGNATURE_VALUE,signature); 435 return EIO; 436 } 437 break; 438 } 439 splx(x); 440 tsleep(&sc->sc_port[i].du_state, 0, "daic protocol init", hz/25); 441 x = splnet(); 442 } 443 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); 449 splx(x); 450 tsleep(&sc->sc_port[i].du_state, 0, "daic irq test", 2*hz); 451 x = splnet(); 452 if (sc->sc_port[i].du_state != DAIC_STATE_RUNNING) { 453 splx(x); 454 printf("%s: download interrupt test timeout\n", 455 device_xname(&sc->sc_dev)); 456 return EIO; 457 } 458 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); 462 splx(x); 463 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); 468 469 /* send an INDICATE request to get incoming calls on this id */ 470 x = splnet(); 471 VOIDREQ(sc, i, DAIC_REQ_INDICATE, sc->sc_port[i].du_global_dchan); 472 splx(x); 473 tsleep(&sc->sc_port[i].du_request_res, 0, "daic request", 0); 474 x = splnet(); 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]); 479 splx(x); 480 return EIO; 481 } 482 splx(x); 483 } 484 return 0; 485} 486 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 *---------------------------------------------------------------------------*/ 492static int 493daic_reset(bus_space_tag_t bus, bus_space_handle_t io, int port, int *memsize) 494{ 495 int i, off = port * DAIC_ISA_MEMSIZE; 496 int cardtype, mem, quiet = memsize == NULL; /* no output if we are only probing */ 497 498 /* clear any pending interrupt */ 499 bus_space_read_1(bus, io, DAIC_IRQ+off); 500 /* reset card */ 501 bus_space_write_1(bus, io, DAIC_BOOT_SET_RESET+off, 0); 502 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"); 509 return -1; 510 } 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++) 517 DELAY(100); 518 if (i >= 15000) { 519 if (!quiet) printf(": on board processor test failed!\n"); 520 return -1; 521 } 522 if (bus_space_read_1(bus, io, DAIC_BOOT_EBIT+off)) { 523 if (!quiet) printf(": on board memory test failed at %x\n", 524 bus_space_read_2(bus, io, DAIC_BOOT_ELOC+off)); 525 return -1; 526 } 527 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; 531 if (memsize) 532 *memsize = mem; 533 534 return cardtype; 535} 536 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 *---------------------------------------------------------------------------*/ 542static int 543daic_diagnostic(void *token, struct isdn_diagnostic_request *req) 544{ 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; 549 int rc, cnt; 550 int s, err = 0; 551 552 /* validate parameters */ 553 if (req->cmd > DAIC_DIAG_MAXCMD) { 554 aprint_error_dev(&sc->sc_dev, "daic_diagnostic: illegal cmd %d\n", 555 req->cmd); 556 return EIO; 557 } 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", 560 req->out_param_len); 561 return EIO; 562 } 563 564 /* XXX - only for debug */ 565 if (req->cmd == 0x05) { 566 /* pass through request from userland */ 567 568 u_int8_t id; 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, 573 0x00 574 }; 575 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); 580 581#ifdef DAIC_DEBUG 582 daic_dump_request(sc, port, DAIC_REQ_CALL, id, req->in_param_len, req->in_param); 583#endif 584 daic_request(sc, port, DAIC_REQ_CALL, id, req->in_param_len, req->in_param); 585 return 0; 586 } 587 588 /* all these need an output parameter */ 589 if (req->out_param == NULL) 590 return EIO; 591 592 /* check state and switch to DIAGNOSTIC */ 593 s = splnet(); 594 if (sc->sc_port[port].du_state != DAIC_STATE_RUNNING) { 595 splx(s); 596 return EWOULDBLOCK; 597 } 598 sc->sc_port[port].du_state = DAIC_STATE_DIAGNOSTIC; 599 splx(s); 600 601 /* set new request */ 602 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_REQ+off, req->cmd); 603 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) 608 break; 609 tsleep(sc, 0, "daic diagnostic", 1); 610 } 611 rc = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_RC+off); 612 if (rc == 0) { 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); 616 err = EIO; 617 goto done; 618 } 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); 623 } 624 /* acknowledge data */ 625 bus_space_write_1(sc->sc_iot, sc->sc_ioh, DAIC_DIAG_RC+off, 0); 626 627done: /* back to normal state */ 628 s = splnet(); 629 sc->sc_port[port].du_state = DAIC_STATE_RUNNING; 630 splx(s); 631 632 return err; 633} 634 635static void daic_stat(void *port, int channel, bchan_statistics_t *bsp) 636{ 637} 638 639static const struct isdn_l4_bchannel_functions 640daic_l4_driver = { 641 daic_bch_config, 642 daic_bch_tx_start, 643 daic_stat 644}; 645 646static const struct isdn_l3_driver_functions 647daic_l3_functions = { 648 daic_ret_linktab, 649 daic_set_link, 650 daic_connect_request, 651 daic_connect_response, 652 daic_disconnect_request, 653 daic_alert_request, 654 daic_download, 655 daic_diagnostic, 656 daic_mgmt_command 657}; 658 659/*---------------------------------------------------------------------------* 660 * Register one port and attach it to the upper layers 661 *---------------------------------------------------------------------------*/ 662static void 663daic_register_port(struct daic_softc *sc, int port) 664{ 665 int chan; 666 char cardname[80], devname[80]; 667 struct isdn_l3_driver * l3drv; 668 669 sc->sc_port[port].du_port = port; 670 sc->sc_port[port].du_sc = sc; 671 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); 676 else 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, 682 NBCH_BRI); 683 sc->sc_port[port].du_l3 = l3drv; 684 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]; 689 lt->channel = chan; 690 lt->tx_queue = &sc->sc_con[port*2+chan].tx_queue; 691 lt->rx_queue = &sc->sc_con[port*2+chan].rx_queue; 692 } 693 TAILQ_INIT(&sc->sc_outcalls[port]); 694 695 isdn_isdnif_ready(l3drv->isdnif); 696} 697 698/*---------------------------------------------------------------------------* 699 * return the address of daic drivers linktab 700 *---------------------------------------------------------------------------*/ 701static isdn_link_t * 702daic_ret_linktab(void *token, int channel) 703{ 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]; 708 709 return(&con->isdn_linktab); 710} 711 712/*---------------------------------------------------------------------------* 713 * set the driver linktab in the b channel softc 714 *---------------------------------------------------------------------------*/ 715static void 716daic_set_link(void *token, int channel, const struct isdn_l4_driver_functions *l4_driver, void *l4_inst) 717{ 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]; 722 723 con->l4_driver = l4_driver; 724 con->l4_driver_softc = l4_inst; 725} 726 727/*---------------------------------------------------------------------------* 728 * Send a request to the card. 729 *---------------------------------------------------------------------------*/ 730static void 731daic_request( 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 */ 738{ 739 int off = port*DAIC_ISA_MEMSIZE; 740 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 */ 744 745 /* output parameters */ 746 bus_space_write_region_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_XBUFFER+off, parms, parmsize); 747 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); 751} 752 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 *---------------------------------------------------------------------------*/ 758static u_int 759daic_assign( 760 struct daic_softc *sc, /* our state and port no */ 761 int port, 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 */ 765{ 766 static char wchan[] = "daic assign"; 767 u_int8_t id; 768 int x; 769 770 /* there only may be one assignment running concurrently */ 771 x = splnet(); 772 for (;;) { 773 if (!(sc->sc_port[port].du_assign & DAIC_ASSIGN_PENDING)) 774 break; /* we got it! */ 775 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); 779 } 780 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); 784 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; 788 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); 799 splx(x); 800 return id; 801 } 802 803 /* XXX - review this, can't remember why I did it this complicated */ 804 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); 809 } else 810 sc->sc_port[port].du_assign = 0; 811 splx(x); 812 813 return id; 814} 815 816#ifdef DAIC_DEBUG 817/*---------------------------------------------------------------------------* 818 * Debug output of request parameters 819 *---------------------------------------------------------------------------*/ 820static void 821daic_dump_request(struct daic_softc *sc, int port, u_int req, u_int id, bus_size_t parmsize, u_int8_t *parms) 822{ 823 int i; 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++) { 827 if (i % 16 == 0) 828 printf("\n%02x:", i); 829 printf(" %02x", parms[i]); 830 } 831 printf("\n"); 832} 833#endif 834 835/*---------------------------------------------------------------------------* 836 * Decode parameters of an INDICATE indication from the card 837 * and pass them to layer 4. Called from within an interrupt 838 * context. 839 *---------------------------------------------------------------------------*/ 840static void 841daic_indicate_ind(struct daic_softc *sc, int port) 842{ 843 int offset = port*DAIC_ISA_MEMSIZE; 844 int i; 845 u_int8_t ie, ielen; 846 call_desc_t *cd; 847 848 /* get and init new calldescriptor */ 849 cd = reserve_cd(); /* cdid filled in */ 850 cd->bprot = BPROT_NONE; 851 cd->cause_in = 0; 852 cd->cause_out = 0; 853 cd->dst_telno[0] = '\0'; 854 cd->src_telno[0] = '\0'; 855 cd->channelid = CHAN_NO; 856 cd->channelexcl = 0; 857 cd->cr = -1; 858 cd->crflag = CRF_DEST; 859 cd->ilt = NULL; /* reset link tab ptrs */ 860 861 i = 0; 862 for (;;) { 863 ie = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+offset+i); 864 if (!ie) break; 865 i++; 866 if (ie & 0x80) continue; 867 ielen = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+offset+i); 868 i++; 869 switch (ie) { 870 case IEI_BEARERCAP: 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; 874 else if (ie == 0x88) 875 cd->bprot = BPROT_RHDLC; 876 break; 877 case IEI_CALLINGPN: 878 { 879 int off; 880 ie = bus_space_read_1(sc->sc_iot, sc->sc_ioh, DAIC_COM_RBUFFER+offset+i); 881 if (ie & 0x80) 882 off = 1; 883 else 884 off = 2; 885 bus_space_read_region_1(sc->sc_iot, sc->sc_ioh, 886 DAIC_COM_RBUFFER+offset+i+off, cd->src_telno, 887 ielen - off); 888 cd->src_telno[ielen-off+1] = '\0'; 889 } 890 break; 891 case IEI_CALLEDPN: 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'; 896 break; 897 case IEI_CHANNELID: 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; 901 else { 902 switch(ie & 0x03) { 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; 907 } 908 cd->channelexcl = (ie & 0x08) >> 3; 909 } 910 } 911 i += ielen; 912 } 913 cd->event = EV_SETUP; 914 /* ctrl_desc[cd->controller].bch_state[cd->channelid] = BCH_ST_RSVD; */ 915 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; 919 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; 924 } else { 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); 930 } 931 932 if (cd->bprot == BPROT_NONE) 933 printf("\nincoming voice call from \"%s\" to \"%s\"\n", 934 cd->src_telno, cd->dst_telno); 935 else 936 printf("\nincoming data call from \"%s\" to \"%s\"\n", 937 cd->src_telno, cd->dst_telno); 938 939 /* hand up call to layer 4 */ 940 i4b_l4_connect_ind(cd); 941} 942 943/*---------------------------------------------------------------------------* 944 * Layer 4 request a call setup 945 *---------------------------------------------------------------------------*/ 946static void 947daic_connect_request(struct call_desc *cd) 948{ 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; 953 int x, len; 954 struct outcallentry *assoc; 955 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. */ 961 962 /* configure d-channel task parameters */ 963 p = parms; 964 *p++ = IEI_CALLID; *p++ = 0x01; 965 if (cd->bprot == BPROT_NONE) { 966 *p++ = 0x82; 967 } else if (cd->bprot == BPROT_RHDLC) { 968 *p++ = 0x85; 969 } else { 970 printf("%s: daic_connect_request for unknown bchan protocol 0x%x\n", 971 device_xname(&sc->sc_dev), cd->bprot); 972 return; 973 } 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); 979 p += strlen(p); 980 } 981 if (cd->channelid == CHAN_B1 || cd->channelid == CHAN_B2) { 982 *p++ = IEI_CHANNELID; 983 *p++ = 0x01; 984 *p++ = 0x81 + cd->channelid; 985 } 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 */ 992 } 993 *p++ = 0; 994 995 /* create the d-channel task for this call */ 996 id = daic_assign(sc, port, DAIC_GLOBALID_DCHAN, p - parms, parms); 997 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; 1002 x = splnet(); 1003 TAILQ_INSERT_TAIL(&sc->sc_outcalls[port], assoc, queue); 1004 1005 /* send a call request */ 1006 len = strlen(cd->dst_telno); 1007 cpn[0] = IEI_CALLEDPN; 1008 cpn[1] = len+1; 1009 cpn[2] = NUMBER_TYPEPLAN; 1010 strcpy(cpn+3, cd->dst_telno); 1011#ifdef DAIC_DEBUG 1012 daic_dump_request(sc, port, DAIC_REQ_CALL, id, len+4, cpn); 1013#endif 1014 daic_request(sc, port, DAIC_REQ_CALL, id, len+4, cpn); 1015 splx(x); 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]); 1021 } 1022} 1023 1024/*---------------------------------------------------------------------------* 1025 * TODO: 1026 *---------------------------------------------------------------------------*/ 1027static void daic_connect_response(struct call_desc *cd, int response, int cause) 1028{ 1029} 1030 1031/*---------------------------------------------------------------------------* 1032 * TODO: 1033 *---------------------------------------------------------------------------*/ 1034static void daic_disconnect_request(struct call_desc *cd, int cause) 1035{ 1036} 1037 1038/*---------------------------------------------------------------------------* 1039 * TODO: 1040 *---------------------------------------------------------------------------*/ 1041static void daic_bch_config(void *token, int channel, int bprot, int updown) 1042{ 1043 printf("daic: bch_config\n"); 1044} 1045 1046/*---------------------------------------------------------------------------* 1047 * TODO: 1048 *---------------------------------------------------------------------------*/ 1049static void daic_bch_tx_start(void *token, int channel) 1050{ 1051 printf("daic: bch_tx_start\n"); 1052} 1053 1054/*---------------------------------------------------------------------------* 1055 * TODO: 1056 *---------------------------------------------------------------------------*/ 1057static void 1058daic_mgmt_command(struct isdn_l3_driver *drv, int cmd, void *parm) 1059{ 1060} 1061 1062/*---------------------------------------------------------------------------* 1063 * TODO: 1064 *---------------------------------------------------------------------------*/ 1065static void 1066daic_alert_request(struct call_desc *cd) 1067{ 1068} 1069 1070