1/* $NetBSD: ifpci2.c,v 1.18 2009/11/26 15:17:10 njoly Exp $ */ 2/* 3 * Copyright (c) 1999 Gary Jennejohn. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of the author nor the names of any co-contributors 15 * may be used to endorse or promote products derived from this software 16 * without specific prior written permission. 17 * 4. Altered versions must be plainly marked as such, and must not be 18 * misrepresented as being the original software and/or documentation. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30 * SUCH DAMAGE. 31 * 32 *--------------------------------------------------------------------------- 33 * a lot of code was borrowed from i4b_bchan.c and i4b_hscx.c 34 *--------------------------------------------------------------------------- 35 * 36 * Fritz!Card PCI driver 37 * ------------------------------------------------ 38 * 39 * $Id: ifpci2.c,v 1.19 2009/12/06 23:14:05 dyoung Exp $ 40 * 41 * last edit-date: [Fri Jan 5 11:38:58 2001] 42 * 43 *---------------------------------------------------------------------------*/ 44 45#include <sys/cdefs.h> 46__KERNEL_RCSID(0, "$NetBSD: ifpci2.c,v 1.18 2009/11/26 15:17:10 njoly Exp $"); 47 48 49#include <sys/param.h> 50#include <sys/ioctl.h> 51#include <sys/kernel.h> 52#include <sys/systm.h> 53#include <sys/mbuf.h> 54 55#include <sys/bus.h> 56#include <sys/device.h> 57 58#include <sys/socket.h> 59#include <net/if.h> 60 61#include <sys/callout.h> 62 63#include <dev/pci/pcireg.h> 64#include <dev/pci/pcivar.h> 65#include <dev/pci/pcidevs.h> 66#include <netisdn/i4b_debug.h> 67#include <netisdn/i4b_ioctl.h> 68 69#include <netisdn/i4b_global.h> 70#include <netisdn/i4b_l2.h> 71#include <netisdn/i4b_l1l2.h> 72#include <netisdn/i4b_trace.h> 73#include <netisdn/i4b_mbuf.h> 74 75#include <dev/ic/isic_l1.h> 76#include <dev/ic/isacsx.h> 77#include <dev/ic/hscx.h> 78 79#include <dev/pci/isic_pci.h> 80 81/* PCI config map to use (only one in this driver) */ 82#define FRITZPCI_PORT0_IO_MAPOFF PCI_MAPREG_START+4 83#define FRITZPCI_PORT0_MEM_MAPOFF PCI_MAPREG_START 84 85static isdn_link_t *avma1pp2_ret_linktab(void *token, int channel); 86static void avma1pp2_set_link(void *token, int channel, const struct isdn_l4_driver_functions *l4_driver, void *l4_driver_softc); 87 88void n_connect_request(struct call_desc *cd); 89void n_connect_response(struct call_desc *cd, int response, int cause); 90void n_disconnect_request(struct call_desc *cd, int cause); 91void n_alert_request(struct call_desc *cd); 92void n_mgmt_command(struct isdn_l3_driver *drv, int cmd, void *parm); 93 94extern const struct isdn_layer1_isdnif_driver isic_std_driver; 95 96const struct isdn_l3_driver_functions 97ifpci2_l3_driver = { 98 avma1pp2_ret_linktab, 99 avma1pp2_set_link, 100 n_connect_request, 101 n_connect_response, 102 n_disconnect_request, 103 n_alert_request, 104 NULL, 105 NULL, 106 n_mgmt_command 107}; 108 109struct ifpci_softc { 110 struct isic_softc sc_isic; /* parent class */ 111 112 /* PCI-specific goo */ 113 void *sc_ih; /* interrupt handler */ 114 bus_addr_t sc_base; 115 bus_size_t sc_size; 116 pci_chipset_tag_t sc_pc; 117}; 118 119/* prototypes */ 120static void avma1pp2_disable(struct isic_softc *); 121static int isic_hscx_fifo(l1_bchan_state_t *chan, struct isic_softc *sc); 122 123static int avma1pp2_intr(void*); 124static void avma1pp2_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size); 125static void avma1pp2_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size); 126static void avma1pp2_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data); 127static u_int8_t avma1pp2_read_reg(struct isic_softc *sc, int what, bus_size_t offs); 128static void hscx_write_fifo(int chan, const void *buf, size_t len, struct isic_softc *sc); 129static void hscx_read_fifo(int chan, void *buf, size_t len, struct isic_softc *sc); 130static void hscx_write_reg(int chan, u_int val, struct isic_softc *sc); 131static u_char hscx_read_reg(int chan, struct isic_softc *sc); 132static u_int hscx_read_reg_int(int chan, struct isic_softc *sc); 133static void avma1pp2_bchannel_stat(isdn_layer1token, int h_chan, bchan_statistics_t *bsp); 134static void avma1pp2_map_int(struct ifpci_softc *sc, struct pci_attach_args *pa); 135static void avma1pp2_bchannel_setup(isdn_layer1token, int h_chan, int bprot, int activate); 136static void avma1pp2_init_linktab(struct isic_softc *); 137static int ifpci2_match(device_t parent, cfdata_t match, void *aux); 138static void ifpci2_attach(device_t parent, device_t self, void *aux); 139static int ifpci2_detach(device_t self, int flags); 140static int ifpci2_activate(device_t self, enum devact act); 141 142CFATTACH_DECL(ifritz, sizeof(struct ifpci_softc), 143 ifpci2_match, ifpci2_attach, ifpci2_detach, ifpci2_activate); 144 145/*---------------------------------------------------------------------------* 146 * AVM PCI Fritz!Card V. 2 special registers 147 *---------------------------------------------------------------------------*/ 148 149/* 150 * AVM PCI Status Latch 0 read only bits 151 */ 152#define ASL_IRQ_ISAC 0x01 /* ISAC interrupt, active high */ 153#define ASL_IRQ_HSCX 0x02 /* HSX interrupt, active high */ 154#define ASL_IRQ_TIMER 0x04 /* Timer interrupt, active high */ 155#define ASL_IRQ_BCHAN ASL_IRQ_HSCX 156/* actually active high */ 157#define ASL_IRQ_Pending (ASL_IRQ_ISAC | ASL_IRQ_HSCX | ASL_IRQ_TIMER) 158 159/* 160 * AVM PCI Status Latch 0 read only bits 161 */ 162#define ASL_RESET 0x01 163#define ASL_TIMERRESET 0x04 164#define ASL_ENABLE_INT 0x08 165 166/* 167 * "HSCX" status bits 168 */ 169#define HSCX_STAT_RME 0x01 170#define HSCX_STAT_RDO 0x10 171#define HSCX_STAT_CRCVFRRAB 0x0E 172#define HSCX_STAT_CRCVFR 0x06 173#define HSCX_STAT_RML_MASK 0x3f00 174 175/* 176 * "HSCX" interrupt bits 177 */ 178#define HSCX_INT_XPR 0x80 179#define HSCX_INT_XDU 0x40 180#define HSCX_INT_RPR 0x20 181#define HSCX_INT_MASK 0xE0 182 183/* 184 * "HSCX" command bits 185 */ 186#define HSCX_CMD_XRS 0x80 187#define HSCX_CMD_XME 0x01 188#define HSCX_CMD_RRS 0x20 189#define HSCX_CMD_XML_MASK 0x3f00 190 191/* "HSCX" mode bits */ 192#define HSCX_MODE_ITF_FLG 0x01 193#define HSCX_MODE_TRANS 0x02 194 195/* offsets to various registers in the ASIC, evidently */ 196#define STAT0_OFFSET 0x02 197 198#define HSCX_FIFO1 0x10 199#define HSCX_FIFO2 0x18 200 201#define HSCX_STAT1 0x14 202#define HSCX_STAT2 0x1c 203 204#define ISACSX_INDEX 0x04 205#define ISACSX_DATA 0x08 206 207/* 208 * Commands and parameters are sent to the "HSCX" as a long, but the 209 * fields are handled as bytes. 210 * 211 * The long contains: 212 * (prot << 16)|(txl << 8)|cmd 213 * 214 * where: 215 * prot = protocol to use 216 * txl = transmit length 217 * cmd = the command to be executed 218 * 219 * The fields are defined as u_char in struct l1_softc. 220 * 221 * Macro to coalesce the byte fields into a u_int 222 */ 223#define AVMA1PPSETCMDLONG(f) (f) = ((sc->avma1pp_cmd) | (sc->avma1pp_txl << 8) \ 224 | (sc->avma1pp_prot << 16)) 225 226/* 227 * to prevent deactivating the "HSCX" when both channels are active we 228 * define an HSCX_ACTIVE flag which is or'd into the channel's state 229 * flag in avma1pp2_bchannel_setup upon active and cleared upon deactivation. 230 * It is set high to allow room for new flags. 231 */ 232#define HSCX_AVMA1PP_ACTIVE 0x1000 233 234static int 235ifpci2_match(device_t parent, cfdata_t match, void *aux) 236{ 237 struct pci_attach_args *pa = aux; 238 239 if (PCI_VENDOR(pa->pa_id) == PCI_VENDOR_AVM && 240 PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_AVM_FRITZ_PCI_V2_ISDN) 241 return 1; 242 return 0; 243} 244 245static void 246ifpci2_attach(device_t parent, device_t self, void *aux) 247{ 248 struct ifpci_softc *psc = device_private(self); 249 struct pci_attach_args *pa = aux; 250 struct isic_softc *sc = &psc->sc_isic; 251 struct isdn_l3_driver *drv; 252 u_int v; 253 254 /* announce */ 255 printf(": Fritz!PCI V2 card\n"); 256 257 /* initialize sc */ 258 callout_init(&sc->sc_T3_callout, 0); 259 callout_init(&sc->sc_T4_callout, 0); 260 261 /* setup io mappings */ 262 sc->sc_num_mappings = 1; 263 MALLOC_MAPS(sc); 264 sc->sc_maps[0].size = 0; 265 if (pci_mapreg_map(pa, FRITZPCI_PORT0_IO_MAPOFF, PCI_MAPREG_TYPE_IO, 0, 266 &sc->sc_maps[0].t, &sc->sc_maps[0].h, &psc->sc_base, &psc->sc_size) != 0) { 267 aprint_error_dev(&sc->sc_dev, "can't map card\n"); 268 return; 269 } 270 271 /* setup access routines */ 272 273 sc->clearirq = NULL; 274 sc->readreg = avma1pp2_read_reg; 275 sc->writereg = avma1pp2_write_reg; 276 277 sc->readfifo = avma1pp2_read_fifo; 278 sc->writefifo = avma1pp2_write_fifo; 279 280 281 /* setup card type */ 282 283 sc->sc_cardtyp = CARD_TYPEP_AVMA1PCIV2; 284 285 /* setup IOM bus type */ 286 287 sc->sc_bustyp = BUS_TYPE_IOM2; 288 289 /* this is no IPAC based card */ 290 sc->sc_ipac = 0; 291 sc->sc_bfifolen = HSCX_FIFO_LEN; 292 293 /* setup interrupt mapping */ 294 avma1pp2_map_int(psc, pa); 295 296 /* init the card */ 297 298 v = bus_space_read_4(sc->sc_maps[0].t, sc->sc_maps[0].h, 0); 299 bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, STAT0_OFFSET, 0); 300 DELAY(SEC_DELAY/20); /* 50 ms */ 301 bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, STAT0_OFFSET, ASL_RESET); 302 DELAY(SEC_DELAY/20); /* 50 ms */ 303 bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, STAT0_OFFSET, 0); 304 DELAY(SEC_DELAY/20); /* 50 ms */ 305 306 bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, STAT0_OFFSET, ASL_TIMERRESET); 307 DELAY(SEC_DELAY/100); /* 10 ms */ 308 bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, STAT0_OFFSET, ASL_ENABLE_INT); 309 DELAY(SEC_DELAY/100); /* 10 ms */ 310 311 /* setup i4b infrastructure (have to roll our own here) */ 312 313 /* sc->sc_isac_version = ((ISAC_READ(I_RBCH)) >> 5) & 0x03; */ 314 printf("%s: ISACSX %s\n", device_xname(&sc->sc_dev), "PSB3186"); 315 316 /* init the ISAC */ 317 isic_isacsx_init(sc); 318 319 v = ISAC_READ(I_CIR0); /* Leo: reset generates status change */ 320 321 /* init the "HSCX" */ 322 avma1pp2_bchannel_setup(sc, HSCX_CH_A, BPROT_NONE, 0); 323 324 avma1pp2_bchannel_setup(sc, HSCX_CH_B, BPROT_NONE, 0); 325 326 /* can't use the normal B-Channel stuff */ 327 avma1pp2_init_linktab(sc); 328 329 /* set trace level */ 330 331 sc->sc_trace = TRACE_OFF; 332 333 sc->sc_state = ISAC_IDLE; 334 335 sc->sc_ibuf = NULL; 336 sc->sc_ib = NULL; 337 sc->sc_ilen = 0; 338 339 sc->sc_obuf = NULL; 340 sc->sc_op = NULL; 341 sc->sc_ol = 0; 342 sc->sc_freeflag = 0; 343 344 sc->sc_obuf2 = NULL; 345 sc->sc_freeflag2 = 0; 346 347 /* init higher protocol layers */ 348 drv = isdn_attach_isdnif(device_xname(&sc->sc_dev), 349 "AVM Fritz!PCI V2", &sc->sc_l2, &ifpci2_l3_driver, NBCH_BRI); 350 sc->sc_l3token = drv; 351 sc->sc_l2.driver = &isic_std_driver; 352 sc->sc_l2.l1_token = sc; 353 sc->sc_l2.drv = drv; 354 isdn_layer2_status_ind(&sc->sc_l2, drv, STI_ATTACH, 1); 355 isdn_isdnif_ready(drv->isdnif); 356} 357 358static int 359ifpci2_detach(device_t self, int flags) 360{ 361 struct ifpci_softc *psc = device_private(self); 362 363 bus_space_unmap(psc->sc_isic.sc_maps[0].t, psc->sc_isic.sc_maps[0].h, psc->sc_size); 364 bus_space_free(psc->sc_isic.sc_maps[0].t, psc->sc_isic.sc_maps[0].h, psc->sc_size); 365 pci_intr_disestablish(psc->sc_pc, psc->sc_ih); 366 367 return (0); 368} 369 370int 371ifpci2_activate(device_t self, enum devact act) 372{ 373 struct ifpci_softc *psc = device_private(self); 374 375 switch (act) { 376 case DVACT_DEACTIVATE: 377 psc->sc_isic.sc_intr_valid = ISIC_INTR_DYING; 378 isdn_layer2_status_ind(&psc->sc_isic.sc_l2, psc->sc_isic.sc_l3token, STI_ATTACH, 0); 379 isdn_detach_isdnif(psc->sc_isic.sc_l3token); 380 psc->sc_isic.sc_l3token = NULL; 381 return 0; 382 default: 383 return EOPNOTSUPP; 384 } 385} 386 387/*---------------------------------------------------------------------------* 388 * AVM read fifo routines 389 *---------------------------------------------------------------------------*/ 390 391static void 392avma1pp2_read_fifo(struct isic_softc *sc, int what, void *buf, size_t size) 393{ 394 int i; 395 396 switch (what) { 397 case ISIC_WHAT_ISAC: 398 bus_space_write_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ISACSX_INDEX, 0); 399 /* evidently each byte must be read as a long */ 400 for (i = 0; i < size; i++) 401 ((u_int8_t *)buf)[i] = (u_int8_t)bus_space_read_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ISACSX_DATA); 402 break; 403 case ISIC_WHAT_HSCXA: 404 hscx_read_fifo(0, buf, size, sc); 405 break; 406 case ISIC_WHAT_HSCXB: 407 hscx_read_fifo(1, buf, size, sc); 408 break; 409 } 410} 411 412static void 413hscx_read_fifo(int chan, void *buf, size_t len, struct isic_softc *sc) 414{ 415 int dataoff; 416 417 dataoff = chan ? HSCX_FIFO2 : HSCX_FIFO1; 418 bus_space_read_multi_stream_4(sc->sc_maps[0].t, sc->sc_maps[0].h, 419 dataoff, buf, len/4); 420 if (__predict_false((len&3)>0)) { 421 uint32_t tmp; 422 423 buf = ((unsigned char*)buf) + (len & ~3u); 424 len &= 3u; 425 tmp = bus_space_read_stream_4(sc->sc_maps[0].t, 426 sc->sc_maps[0].h, dataoff); 427 memcpy(buf, &tmp, len); 428 } 429} 430 431/*---------------------------------------------------------------------------* 432 * AVM write fifo routines 433 *---------------------------------------------------------------------------*/ 434 435static void 436avma1pp2_write_fifo(struct isic_softc *sc, int what, const void *buf, size_t size) 437{ 438 int i; 439 440 switch (what) { 441 case ISIC_WHAT_ISAC: 442 bus_space_write_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ISACSX_INDEX, 0); 443 /* evidently each byte must be written as a long */ 444 for (i = 0; i < size; i++) 445 bus_space_write_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ISACSX_DATA, ((const unsigned char *)buf)[i]); 446 break; 447 case ISIC_WHAT_HSCXA: 448 hscx_write_fifo(0, buf, size, sc); 449 break; 450 case ISIC_WHAT_HSCXB: 451 hscx_write_fifo(1, buf, size, sc); 452 break; 453 } 454} 455 456static void 457hscx_write_fifo(int chan, const void *buf, size_t len, struct isic_softc *sc) 458{ 459 size_t cnt; 460 int dataoff; 461 l1_bchan_state_t *Bchan = &sc->sc_chan[chan]; 462 463 dataoff = chan ? HSCX_FIFO2 : HSCX_FIFO1; 464 465 sc->avma1pp_cmd &= ~HSCX_CMD_XME; 466 sc->avma1pp_txl = 0; 467 if (Bchan->out_mbuf_cur == NULL) 468 { 469 if (Bchan->bprot != BPROT_NONE) 470 sc->avma1pp_cmd |= HSCX_CMD_XME; 471 } 472 if (len != sc->sc_bfifolen) 473 sc->avma1pp_txl = len; 474 475 cnt = 0; /* borrow cnt */ 476 AVMA1PPSETCMDLONG(cnt); 477 hscx_write_reg(chan, cnt, sc); 478 479 bus_space_write_multi_stream_4(sc->sc_maps[0].t, sc->sc_maps[0].h, 480 dataoff, buf, (len+3)/4); 481 if (__predict_false((len&3)>0)) { 482 uint32_t tmp; 483 484 buf = (const unsigned char*)buf + (len & ~3u); 485 len &= 3u; 486 memset(&tmp, 0, sizeof(tmp)); 487 memcpy(&tmp, buf, len); 488 bus_space_write_stream_4(sc->sc_maps[0].t, sc->sc_maps[0].h, 489 dataoff, tmp); 490 } 491} 492 493/*---------------------------------------------------------------------------* 494 * AVM write register routines 495 *---------------------------------------------------------------------------*/ 496 497static void 498avma1pp2_write_reg(struct isic_softc *sc, int what, bus_size_t offs, u_int8_t data) 499{ 500 switch (what) { 501 case ISIC_WHAT_ISAC: 502 bus_space_write_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ISACSX_INDEX, offs); 503 bus_space_write_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ISACSX_DATA, data); 504 break; 505 case ISIC_WHAT_HSCXA: 506 hscx_write_reg(0, data, sc); 507 break; 508 case ISIC_WHAT_HSCXB: 509 hscx_write_reg(1, data, sc); 510 break; 511 } 512} 513 514static void 515hscx_write_reg(int chan, u_int val, struct isic_softc *sc) 516{ 517 u_int off; 518 519 off = (chan == 0 ? HSCX_STAT1 : HSCX_STAT2); 520 bus_space_write_4(sc->sc_maps[0].t, sc->sc_maps[0].h, off, val); 521} 522 523/*---------------------------------------------------------------------------* 524 * AVM read register routines 525 *---------------------------------------------------------------------------*/ 526 527static u_int8_t 528avma1pp2_read_reg(struct isic_softc *sc, int what, bus_size_t offs) 529{ 530 u_int8_t val; 531 532 switch (what) { 533 case ISIC_WHAT_ISAC: 534 bus_space_write_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ISACSX_INDEX, offs); 535 val = (u_int8_t)bus_space_read_4(sc->sc_maps[0].t, sc->sc_maps[0].h, ISACSX_DATA); 536 return(val); 537 case ISIC_WHAT_HSCXA: 538 return hscx_read_reg(0, sc); 539 case ISIC_WHAT_HSCXB: 540 return hscx_read_reg(1, sc); 541 } 542 return 0; 543} 544 545static u_char 546hscx_read_reg(int chan, struct isic_softc *sc) 547{ 548 return(hscx_read_reg_int(chan, sc) & 0xff); 549} 550 551/* 552 * need to be able to return an int because the RBCH is in the 2nd 553 * byte. 554 */ 555static u_int 556hscx_read_reg_int(int chan, struct isic_softc *sc) 557{ 558 u_int off; 559 560 off = (chan == 0 ? HSCX_STAT1 : HSCX_STAT2); 561 return(bus_space_read_4(sc->sc_maps[0].t, sc->sc_maps[0].h, off)); 562} 563 564/* 565 * this is the real interrupt routine 566 */ 567static void 568avma1pp2_hscx_intr(int h_chan, u_int stat, struct isic_softc *sc) 569{ 570 register l1_bchan_state_t *chan = &sc->sc_chan[h_chan]; 571 int activity = -1; 572 u_int param = 0; 573 574 NDBGL1(L1_H_IRQ, "%#x", stat); 575 576 if((stat & HSCX_INT_XDU) && (chan->bprot != BPROT_NONE))/* xmit data underrun */ 577 { 578 chan->stat_XDU++; 579 NDBGL1(L1_H_XFRERR, "xmit data underrun"); 580 /* abort the transmission */ 581 sc->avma1pp_txl = 0; 582 sc->avma1pp_cmd |= HSCX_CMD_XRS; 583 AVMA1PPSETCMDLONG(param); 584 hscx_write_reg(h_chan, param, sc); 585 sc->avma1pp_cmd &= ~HSCX_CMD_XRS; 586 AVMA1PPSETCMDLONG(param); 587 hscx_write_reg(h_chan, param, sc); 588 589 if (chan->out_mbuf_head != NULL) /* don't continue to transmit this buffer */ 590 { 591 i4b_Bfreembuf(chan->out_mbuf_head); 592 chan->out_mbuf_cur = chan->out_mbuf_head = NULL; 593 } 594 } 595 596 /* 597 * The following is based on examination of the Linux driver. 598 * 599 * The logic here is different than with a "real" HSCX; all kinds 600 * of information (interrupt/status bits) are in stat. 601 * HSCX_INT_RPR indicates a receive interrupt 602 * HSCX_STAT_RDO indicates an overrun condition, abort - 603 * otherwise read the bytes ((stat & HSCX_STZT_RML_MASK) >> 8) 604 * HSCX_STAT_RME indicates end-of-frame and apparently any 605 * CRC/framing errors are only reported in this state. 606 * if ((stat & HSCX_STAT_CRCVFRRAB) != HSCX_STAT_CRCVFR) 607 * CRC/framing error 608 */ 609 610 if(stat & HSCX_INT_RPR) 611 { 612 register int fifo_data_len; 613 int error = 0; 614 /* always have to read the FIFO, so use a scratch buffer */ 615 u_char scrbuf[HSCX_FIFO_LEN]; 616 617 if(stat & HSCX_STAT_RDO) 618 { 619 chan->stat_RDO++; 620 NDBGL1(L1_H_XFRERR, "receive data overflow"); 621 error++; 622 } 623 624 /* 625 * check whether we're receiving data for an inactive B-channel 626 * and discard it. This appears to happen for telephony when 627 * both B-channels are active and one is deactivated. Since 628 * it is not really possible to deactivate the channel in that 629 * case (the ASIC seems to deactivate _both_ channels), the 630 * "deactivated" channel keeps receiving data which can lead 631 * to exhaustion of mbufs and a kernel panic. 632 * 633 * This is a hack, but it's the only solution I can think of 634 * without having the documentation for the ASIC. 635 * GJ - 28 Nov 1999 636 */ 637 if (chan->state == HSCX_IDLE) 638 { 639 NDBGL1(L1_H_XFRERR, "toss data from %d", h_chan); 640 error++; 641 } 642 643 fifo_data_len = ((stat & HSCX_STAT_RML_MASK) >> 8); 644 645 if(fifo_data_len == 0) 646 fifo_data_len = sc->sc_bfifolen; 647 648 /* ALWAYS read data from HSCX fifo */ 649 650 HSCX_RDFIFO(h_chan, scrbuf, fifo_data_len); 651 chan->rxcount += fifo_data_len; 652 653 /* all error conditions checked, now decide and take action */ 654 655 if(error == 0) 656 { 657 if(chan->in_mbuf == NULL) 658 { 659 if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL) 660 panic("L1 avma1pp2_hscx_intr: RME, cannot allocate mbuf!"); 661 chan->in_cbptr = chan->in_mbuf->m_data; 662 chan->in_len = 0; 663 } 664 665 if((chan->in_len + fifo_data_len) <= BCH_MAX_DATALEN) 666 { 667 /* OK to copy the data */ 668 memcpy(chan->in_cbptr, scrbuf, fifo_data_len); 669 chan->in_cbptr += fifo_data_len; 670 chan->in_len += fifo_data_len; 671 672 /* setup mbuf data length */ 673 674 chan->in_mbuf->m_len = chan->in_len; 675 chan->in_mbuf->m_pkthdr.len = chan->in_len; 676 677 if(sc->sc_trace & TRACE_B_RX) 678 { 679 struct i4b_trace_hdr hdr; 680 hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2); 681 hdr.dir = FROM_NT; 682 hdr.count = ++sc->sc_trace_bcount; 683 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data); 684 } 685 686 if (stat & HSCX_STAT_RME) 687 { 688 if((stat & HSCX_STAT_CRCVFRRAB) == HSCX_STAT_CRCVFR) 689 { 690 (*chan->l4_driver->bch_rx_data_ready)(chan->l4_driver_softc); 691 activity = ACT_RX; 692 693 /* mark buffer ptr as unused */ 694 695 chan->in_mbuf = NULL; 696 chan->in_cbptr = NULL; 697 chan->in_len = 0; 698 } 699 else 700 { 701 chan->stat_CRC++; 702 NDBGL1(L1_H_XFRERR, "CRC/RAB"); 703 if (chan->in_mbuf != NULL) 704 { 705 i4b_Bfreembuf(chan->in_mbuf); 706 chan->in_mbuf = NULL; 707 chan->in_cbptr = NULL; 708 chan->in_len = 0; 709 } 710 } 711 } 712 } /* END enough space in mbuf */ 713 else 714 { 715 if(chan->bprot == BPROT_NONE) 716 { 717 /* setup mbuf data length */ 718 719 chan->in_mbuf->m_len = chan->in_len; 720 chan->in_mbuf->m_pkthdr.len = chan->in_len; 721 722 if(sc->sc_trace & TRACE_B_RX) 723 { 724 struct i4b_trace_hdr hdr; 725 hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2); 726 hdr.dir = FROM_NT; 727 hdr.count = ++sc->sc_trace_bcount; 728 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, chan->in_mbuf->m_len, chan->in_mbuf->m_data); 729 } 730 731 if(!(isdn_bchan_silence(chan->in_mbuf->m_data, chan->in_mbuf->m_len))) 732 activity = ACT_RX; 733 734 /* move rx'd data to rx queue */ 735 736 if (!(IF_QFULL(&chan->rx_queue))) 737 { 738 IF_ENQUEUE(&chan->rx_queue, chan->in_mbuf); 739 } 740 else 741 { 742 i4b_Bfreembuf(chan->in_mbuf); 743 } 744 745 /* signal upper layer that data are available */ 746 (*chan->l4_driver->bch_rx_data_ready)(chan->l4_driver_softc); 747 748 /* alloc new buffer */ 749 750 if((chan->in_mbuf = i4b_Bgetmbuf(BCH_MAX_DATALEN)) == NULL) 751 panic("L1 avma1pp2_hscx_intr: RPF, cannot allocate new mbuf!"); 752 753 /* setup new data ptr */ 754 755 chan->in_cbptr = chan->in_mbuf->m_data; 756 757 /* OK to copy the data */ 758 memcpy(chan->in_cbptr, scrbuf, fifo_data_len); 759 760 chan->in_cbptr += fifo_data_len; 761 chan->in_len = fifo_data_len; 762 763 chan->rxcount += fifo_data_len; 764 } 765 else 766 { 767 NDBGL1(L1_H_XFRERR, "RAWHDLC rx buffer overflow in RPF, in_len=%d", chan->in_len); 768 chan->in_cbptr = chan->in_mbuf->m_data; 769 chan->in_len = 0; 770 } 771 } 772 } /* if(error == 0) */ 773 else 774 { 775 /* land here for RDO */ 776 if (chan->in_mbuf != NULL) 777 { 778 i4b_Bfreembuf(chan->in_mbuf); 779 chan->in_mbuf = NULL; 780 chan->in_cbptr = NULL; 781 chan->in_len = 0; 782 } 783 sc->avma1pp_txl = 0; 784 sc->avma1pp_cmd |= HSCX_CMD_RRS; 785 AVMA1PPSETCMDLONG(param); 786 hscx_write_reg(h_chan, param, sc); 787 sc->avma1pp_cmd &= ~HSCX_CMD_RRS; 788 AVMA1PPSETCMDLONG(param); 789 hscx_write_reg(h_chan, param, sc); 790 } 791 } 792 793 794 /* transmit fifo empty, new data can be written to fifo */ 795 796 if(stat & HSCX_INT_XPR) 797 { 798 /* 799 * for a description what is going on here, please have 800 * a look at isic_bchannel_start() in i4b_bchan.c ! 801 */ 802 803 NDBGL1(L1_H_IRQ, "%s: chan %d - XPR, Tx Fifo Empty!", device_xname(&sc->sc_dev), h_chan); 804 805 if(chan->out_mbuf_cur == NULL) /* last frame is transmitted */ 806 { 807 IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head); 808 809 if(chan->out_mbuf_head == NULL) 810 { 811 chan->state &= ~HSCX_TX_ACTIVE; 812 (*chan->l4_driver->bch_tx_queue_empty)(chan->l4_driver_softc); 813 } 814 else 815 { 816 chan->state |= HSCX_TX_ACTIVE; 817 chan->out_mbuf_cur = chan->out_mbuf_head; 818 chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data; 819 chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len; 820 821 if(sc->sc_trace & TRACE_B_TX) 822 { 823 struct i4b_trace_hdr hdr; 824 hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2); 825 hdr.dir = FROM_TE; 826 hdr.count = ++sc->sc_trace_bcount; 827 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data); 828 } 829 830 if(chan->bprot == BPROT_NONE) 831 { 832 if(!(isdn_bchan_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len))) 833 activity = ACT_TX; 834 } 835 else 836 { 837 activity = ACT_TX; 838 } 839 } 840 } 841 842 isic_hscx_fifo(chan, sc); 843 } 844 845 /* call timeout handling routine */ 846 847 if(activity == ACT_RX || activity == ACT_TX) 848 (*chan->l4_driver->bch_activity)(chan->l4_driver_softc, activity); 849} 850 851/* 852 * this is the main routine which checks each channel and then calls 853 * the real interrupt routine as appropriate 854 */ 855static void 856avma1pp2_hscx_int_handler(struct isic_softc *sc) 857{ 858 u_int stat; 859 860 /* has to be a u_int because the byte count is in the 2nd byte */ 861 stat = hscx_read_reg_int(0, sc); 862 if (stat & HSCX_INT_MASK) 863 avma1pp2_hscx_intr(0, stat, sc); 864 stat = hscx_read_reg_int(1, sc); 865 if (stat & HSCX_INT_MASK) 866 avma1pp2_hscx_intr(1, stat, sc); 867} 868 869static void 870avma1pp2_disable(struct isic_softc *sc) 871{ 872 /* could be still be wrong, but seems to prevent hangs */ 873 bus_space_write_1(sc->sc_maps[0].t, sc->sc_maps[0].h, STAT0_OFFSET, 0x00); 874} 875 876static int 877avma1pp2_intr(void *parm) 878{ 879 struct isic_softc *sc = parm; 880 int ret = 0; 881#define OURS ret = 1 882 u_char stat; 883 884 if (sc->sc_intr_valid != ISIC_INTR_VALID) 885 return 0; 886 887 stat = bus_space_read_1(sc->sc_maps[0].t, sc->sc_maps[0].h, STAT0_OFFSET); 888 NDBGL1(L1_H_IRQ, "stat %x", stat); 889 /* was there an interrupt from this card ? */ 890 if ((stat & ASL_IRQ_Pending) == 0) 891 return 0; /* no */ 892 /* For slow machines loop as long as an interrupt is active */ 893 for (; ((stat & ASL_IRQ_Pending) != 0) ;) 894 { 895 /* interrupts are high active */ 896 if (stat & ASL_IRQ_TIMER) 897 NDBGL1(L1_H_IRQ, "timer interrupt ???"); 898 if (stat & ASL_IRQ_HSCX) 899 { 900 NDBGL1(L1_H_IRQ, "HSCX"); 901 avma1pp2_hscx_int_handler(sc); 902 } 903 if (stat & ASL_IRQ_ISAC) 904 { 905 u_char isacsx_irq_stat; 906 907 NDBGL1(L1_H_IRQ, "ISAC"); 908 for(;;) 909 { 910 /* ISTA tells us whether it was a C/I or HDLC int. */ 911 isacsx_irq_stat = ISAC_READ(I_ISTA); 912 913 if(isacsx_irq_stat) 914 isic_isacsx_irq(sc, isacsx_irq_stat); /* isac handler */ 915 else 916 break; 917 } 918 919 /* 920 * XXX: Leo: Note that Linux doesn't do this mask 921 * frobbing... 922 */ 923 ISAC_WRITE(I_MASKD, 0xff); 924 ISAC_WRITE(I_MASK, 0xff); 925 926 DELAY(100); 927 928 ISAC_WRITE(I_MASKD, isacsx_imaskd); 929 ISAC_WRITE(I_MASK, isacsx_imask); 930 931 } 932 stat = bus_space_read_1(sc->sc_maps[0].t, sc->sc_maps[0].h, STAT0_OFFSET); 933 NDBGL1(L1_H_IRQ, "stat %x", stat); 934 OURS; 935 } 936 return ret; 937} 938 939static void 940avma1pp2_map_int(struct ifpci_softc *psc, struct pci_attach_args *pa) 941{ 942 struct isic_softc *sc = &psc->sc_isic; 943 pci_chipset_tag_t pc = pa->pa_pc; 944 pci_intr_handle_t ih; 945 const char *intrstr; 946 947 /* Map and establish the interrupt. */ 948 if (pci_intr_map(pa, &ih)) { 949 aprint_error_dev(&sc->sc_dev, "couldn't map interrupt\n"); 950 avma1pp2_disable(sc); 951 return; 952 } 953 psc->sc_pc = pc; 954 intrstr = pci_intr_string(pc, ih); 955 psc->sc_ih = pci_intr_establish(pc, ih, IPL_NET, avma1pp2_intr, sc); 956 if (psc->sc_ih == NULL) { 957 aprint_error_dev(&sc->sc_dev, "couldn't establish interrupt"); 958 if (intrstr != NULL) 959 aprint_error(" at %s", intrstr); 960 aprint_error("\n"); 961 avma1pp2_disable(sc); 962 return; 963 } 964 aprint_normal_dev(&sc->sc_dev, "interrupting at %s\n", intrstr); 965} 966 967static void 968avma1pp2_hscx_init(struct isic_softc *sc, int h_chan, int activate) 969{ 970 l1_bchan_state_t *chan = &sc->sc_chan[h_chan]; 971 u_int param = 0; 972 973 NDBGL1(L1_BCHAN, "%s: channel=%d, %s", 974 device_xname(&sc->sc_dev), h_chan, activate ? "activate" : "deactivate"); 975 sc->avma1pp_cmd = sc->avma1pp_prot = sc->avma1pp_txl = 0; 976 977 if (activate == 0) 978 { 979 /* only deactivate if both channels are idle */ 980 if (sc->sc_chan[HSCX_CH_A].state != HSCX_IDLE || 981 sc->sc_chan[HSCX_CH_B].state != HSCX_IDLE) 982 { 983 return; 984 } 985 sc->avma1pp_cmd = HSCX_CMD_XRS|HSCX_CMD_RRS; 986 sc->avma1pp_prot = HSCX_MODE_TRANS; 987 AVMA1PPSETCMDLONG(param); 988 hscx_write_reg(h_chan, param, sc); 989 return; 990 } 991 if(chan->bprot == BPROT_RHDLC) 992 { 993 NDBGL1(L1_BCHAN, "BPROT_RHDLC"); 994 995 /* HDLC Frames, transparent mode 0 */ 996 sc->avma1pp_cmd = HSCX_CMD_XRS|HSCX_CMD_RRS; 997 sc->avma1pp_prot = HSCX_MODE_ITF_FLG; 998 AVMA1PPSETCMDLONG(param); 999 hscx_write_reg(h_chan, param, sc); 1000 sc->avma1pp_cmd = HSCX_CMD_XRS; 1001 AVMA1PPSETCMDLONG(param); 1002 hscx_write_reg(h_chan, param, sc); 1003 sc->avma1pp_cmd = 0; 1004 } 1005 else 1006 { 1007 NDBGL1(L1_BCHAN, "BPROT_NONE??"); 1008 1009 /* Raw Telephony, extended transparent mode 1 */ 1010 sc->avma1pp_cmd = HSCX_CMD_XRS|HSCX_CMD_RRS; 1011 sc->avma1pp_prot = HSCX_MODE_TRANS; 1012 AVMA1PPSETCMDLONG(param); 1013 hscx_write_reg(h_chan, param, sc); 1014 sc->avma1pp_cmd = HSCX_CMD_XRS; 1015 AVMA1PPSETCMDLONG(param); 1016 hscx_write_reg(h_chan, param, sc); 1017 sc->avma1pp_cmd = 0; 1018 } 1019} 1020 1021static void 1022avma1pp2_bchannel_setup(isdn_layer1token t, int h_chan, int bprot, int activate) 1023{ 1024 struct isic_softc *sc = (struct isic_softc*)t; 1025 l1_bchan_state_t *chan = &sc->sc_chan[h_chan]; 1026 1027 int s = splnet(); 1028 1029 if(activate == 0) 1030 { 1031 /* deactivation */ 1032 chan->state = HSCX_IDLE; 1033 avma1pp2_hscx_init(sc, h_chan, activate); 1034 } 1035 1036 NDBGL1(L1_BCHAN, "%s: channel=%d, %s", 1037 device_xname(&sc->sc_dev), h_chan, activate ? "activate" : "deactivate"); 1038 1039 /* general part */ 1040 1041 chan->channel = h_chan; /* B channel */ 1042 chan->bprot = bprot; /* B channel protocol */ 1043 chan->state = HSCX_IDLE; /* B channel state */ 1044 1045 /* receiver part */ 1046 1047 i4b_Bcleanifq(&chan->rx_queue); /* clean rx queue */ 1048 1049 chan->rx_queue.ifq_maxlen = IFQ_MAXLEN; 1050 1051 chan->rxcount = 0; /* reset rx counter */ 1052 1053 i4b_Bfreembuf(chan->in_mbuf); /* clean rx mbuf */ 1054 1055 chan->in_mbuf = NULL; /* reset mbuf ptr */ 1056 chan->in_cbptr = NULL; /* reset mbuf curr ptr */ 1057 chan->in_len = 0; /* reset mbuf data len */ 1058 1059 /* transmitter part */ 1060 1061 i4b_Bcleanifq(&chan->tx_queue); /* clean tx queue */ 1062 1063 chan->tx_queue.ifq_maxlen = IFQ_MAXLEN; 1064 1065 chan->txcount = 0; /* reset tx counter */ 1066 1067 i4b_Bfreembuf(chan->out_mbuf_head); /* clean tx mbuf */ 1068 1069 chan->out_mbuf_head = NULL; /* reset head mbuf ptr */ 1070 chan->out_mbuf_cur = NULL; /* reset current mbuf ptr */ 1071 chan->out_mbuf_cur_ptr = NULL; /* reset current mbuf data ptr */ 1072 chan->out_mbuf_cur_len = 0; /* reset current mbuf data cnt */ 1073 1074 if(activate != 0) 1075 { 1076 /* activation */ 1077 avma1pp2_hscx_init(sc, h_chan, activate); 1078 chan->state |= HSCX_AVMA1PP_ACTIVE; 1079 } 1080 1081 splx(s); 1082} 1083 1084static void 1085avma1pp2_bchannel_start(isdn_layer1token t, int h_chan) 1086{ 1087 struct isic_softc *sc = (struct isic_softc*)t; 1088 register l1_bchan_state_t *chan = &sc->sc_chan[h_chan]; 1089 int s; 1090 int activity = -1; 1091 1092 s = splnet(); /* enter critical section */ 1093 if(chan->state & HSCX_TX_ACTIVE) /* already running ? */ 1094 { 1095 splx(s); 1096 return; /* yes, leave */ 1097 } 1098 1099 /* get next mbuf from queue */ 1100 1101 IF_DEQUEUE(&chan->tx_queue, chan->out_mbuf_head); 1102 1103 if(chan->out_mbuf_head == NULL) /* queue empty ? */ 1104 { 1105 splx(s); /* leave critical section */ 1106 return; /* yes, exit */ 1107 } 1108 1109 /* init current mbuf values */ 1110 1111 chan->out_mbuf_cur = chan->out_mbuf_head; 1112 chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len; 1113 chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data; 1114 1115 /* activity indicator for timeout handling */ 1116 1117 if(chan->bprot == BPROT_NONE) 1118 { 1119 if(!(isdn_bchan_silence(chan->out_mbuf_cur->m_data, chan->out_mbuf_cur->m_len))) 1120 activity = ACT_TX; 1121 } 1122 else 1123 { 1124 activity = ACT_TX; 1125 } 1126 1127 chan->state |= HSCX_TX_ACTIVE; /* we start transmitting */ 1128 1129 if(sc->sc_trace & TRACE_B_TX) /* if trace, send mbuf to trace dev */ 1130 { 1131 struct i4b_trace_hdr hdr; 1132 hdr.type = (h_chan == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2); 1133 hdr.dir = FROM_TE; 1134 hdr.count = ++sc->sc_trace_bcount; 1135 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data); 1136 } 1137 1138 isic_hscx_fifo(chan, sc); 1139 1140 /* call timeout handling routine */ 1141 1142 if(activity == ACT_RX || activity == ACT_TX) 1143 (*chan->l4_driver->bch_activity)(chan->l4_driver_softc, activity); 1144 1145 splx(s); 1146} 1147 1148/*---------------------------------------------------------------------------* 1149 * return the address of isic drivers linktab 1150 *---------------------------------------------------------------------------*/ 1151static isdn_link_t * 1152avma1pp2_ret_linktab(void *token, int channel) 1153{ 1154 struct l2_softc *l2sc = token; 1155 struct isic_softc *sc = l2sc->l1_token; 1156 1157 l1_bchan_state_t *chan = &sc->sc_chan[channel]; 1158 1159 return(&chan->isdn_linktab); 1160} 1161 1162/*---------------------------------------------------------------------------* 1163 * set the driver linktab in the b channel softc 1164 *---------------------------------------------------------------------------*/ 1165static void 1166avma1pp2_set_link(void *token, int channel, const struct isdn_l4_driver_functions *l4_driver, void *l4_driver_softc) 1167{ 1168 struct l2_softc *l2sc = token; 1169 struct isic_softc *sc = l2sc->l1_token; 1170 l1_bchan_state_t *chan = &sc->sc_chan[channel]; 1171 1172 chan->l4_driver = l4_driver; 1173 chan->l4_driver_softc = l4_driver_softc; 1174} 1175 1176static const struct isdn_l4_bchannel_functions 1177avma1pp2_l4_bchannel_functions = { 1178 avma1pp2_bchannel_setup, 1179 avma1pp2_bchannel_start, 1180 avma1pp2_bchannel_stat 1181}; 1182 1183/*---------------------------------------------------------------------------* 1184 * initialize our local linktab 1185 *---------------------------------------------------------------------------*/ 1186static void 1187avma1pp2_init_linktab(struct isic_softc *sc) 1188{ 1189 l1_bchan_state_t *chan = &sc->sc_chan[HSCX_CH_A]; 1190 isdn_link_t *lt = &chan->isdn_linktab; 1191 1192 /* local setup */ 1193 lt->l1token = sc; 1194 lt->channel = HSCX_CH_A; 1195 lt->bchannel_driver = &avma1pp2_l4_bchannel_functions; 1196 lt->tx_queue = &chan->tx_queue; 1197 1198 /* used by non-HDLC data transfers, i.e. telephony drivers */ 1199 lt->rx_queue = &chan->rx_queue; 1200 1201 /* used by HDLC data transfers, i.e. ipr and isp drivers */ 1202 lt->rx_mbuf = &chan->in_mbuf; 1203 1204 chan = &sc->sc_chan[HSCX_CH_B]; 1205 lt = &chan->isdn_linktab; 1206 1207 lt->l1token = sc; 1208 lt->channel = HSCX_CH_B; 1209 lt->bchannel_driver = &avma1pp2_l4_bchannel_functions; 1210 lt->tx_queue = &chan->tx_queue; 1211 1212 /* used by non-HDLC data transfers, i.e. telephony drivers */ 1213 lt->rx_queue = &chan->rx_queue; 1214 1215 /* used by HDLC data transfers, i.e. ipr and isp drivers */ 1216 lt->rx_mbuf = &chan->in_mbuf; 1217} 1218 1219/* 1220 * use this instead of isic_bchannel_stat in i4b_bchan.c because it's static 1221 */ 1222static void 1223avma1pp2_bchannel_stat(isdn_layer1token t, int h_chan, bchan_statistics_t *bsp) 1224{ 1225 struct isic_softc *sc = (struct isic_softc*)t; 1226 l1_bchan_state_t *chan = &sc->sc_chan[h_chan]; 1227 int s; 1228 1229 s = splnet(); 1230 1231 bsp->outbytes = chan->txcount; 1232 bsp->inbytes = chan->rxcount; 1233 1234 chan->txcount = 0; 1235 chan->rxcount = 0; 1236 1237 splx(s); 1238} 1239 1240/*---------------------------------------------------------------------------* 1241 * fill HSCX fifo with data from the current mbuf 1242 * Put this here until it can go into i4b_hscx.c 1243 *---------------------------------------------------------------------------*/ 1244static int 1245isic_hscx_fifo(l1_bchan_state_t *chan, struct isic_softc *sc) 1246{ 1247 int len; 1248 int nextlen; 1249 int i; 1250 int cmd; 1251 /* using a scratch buffer simplifies writing to the FIFO */ 1252 u_char scrbuf[HSCX_FIFO_LEN]; 1253 1254 len = 0; 1255 cmd = 0; 1256 1257 /* 1258 * fill the HSCX tx fifo with data from the current mbuf. if 1259 * current mbuf holds less data than HSCX fifo length, try to 1260 * get the next mbuf from (a possible) mbuf chain. if there is 1261 * not enough data in a single mbuf or in a chain, then this 1262 * is the last mbuf and we tell the HSCX that it has to send 1263 * CRC and closing flag 1264 */ 1265 1266 while(chan->out_mbuf_cur && len != sc->sc_bfifolen) 1267 { 1268 nextlen = min(chan->out_mbuf_cur_len, sc->sc_bfifolen - len); 1269 1270#ifdef NOTDEF 1271 printf("i:mh=%p, mc=%p, mcp=%p, mcl=%d l=%d nl=%d # ", 1272 chan->out_mbuf_head, 1273 chan->out_mbuf_cur, 1274 chan->out_mbuf_cur_ptr, 1275 chan->out_mbuf_cur_len, 1276 len, 1277 nextlen); 1278#endif 1279 1280 cmd |= HSCX_CMDR_XTF; 1281 /* collect the data in the scratch buffer */ 1282 for (i = 0; i < nextlen; i++) 1283 scrbuf[i + len] = chan->out_mbuf_cur_ptr[i]; 1284 1285 len += nextlen; 1286 chan->txcount += nextlen; 1287 1288 chan->out_mbuf_cur_ptr += nextlen; 1289 chan->out_mbuf_cur_len -= nextlen; 1290 1291 if(chan->out_mbuf_cur_len == 0) 1292 { 1293 if((chan->out_mbuf_cur = chan->out_mbuf_cur->m_next) != NULL) 1294 { 1295 chan->out_mbuf_cur_ptr = chan->out_mbuf_cur->m_data; 1296 chan->out_mbuf_cur_len = chan->out_mbuf_cur->m_len; 1297 1298 if(sc->sc_trace & TRACE_B_TX) 1299 { 1300 struct i4b_trace_hdr hdr; 1301 hdr.type = (chan->channel == HSCX_CH_A ? TRC_CH_B1 : TRC_CH_B2); 1302 hdr.dir = FROM_TE; 1303 hdr.count = ++sc->sc_trace_bcount; 1304 isdn_layer2_trace_ind(&sc->sc_l2, sc->sc_l3token, &hdr, chan->out_mbuf_cur->m_len, chan->out_mbuf_cur->m_data); 1305 } 1306 } 1307 else 1308 { 1309 if (chan->bprot != BPROT_NONE) 1310 cmd |= HSCX_CMDR_XME; 1311 i4b_Bfreembuf(chan->out_mbuf_head); 1312 chan->out_mbuf_head = NULL; 1313 } 1314 } 1315 } 1316 /* write what we have from the scratch buf to the HSCX fifo */ 1317 if (len != 0) 1318 HSCX_WRFIFO(chan->channel, scrbuf, len); 1319 return(cmd); 1320} 1321