1139749Simp/*- 2126177Srik * DDK library for Cronyx-Tau adapters. 3126177Srik * 4126177Srik * Copyright (C) 1998-1999 Cronyx Engineering. 5126177Srik * Author: Alexander Kvitchenko, <aak@cronyx.ru> 6126177Srik * 7126177Srik * Copyright (C) 1999-2003 Cronyx Engineering. 8126177Srik * Author: Roman Kurakin, <rik@cronyx.ru> 9126177Srik * 10126177Srik * This source is derived from 11126177Srik * Diagnose utility for Cronyx-Tau adapter: 12126177Srik * by Serge Vakulenko, <vak@cronyx.ru> 13126177Srik * 14126177Srik * This software is distributed with NO WARRANTIES, not even the implied 15126177Srik * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 16126177Srik * 17126177Srik * Authors grant any other persons or organisations permission to use 18126177Srik * or modify this software as long as this message is kept with the software, 19126177Srik * all derivative works or modified versions. 20126177Srik * 21126177Srik * Cronyx Id: ctddk.c,v 1.1.2.3 2003/11/14 16:55:36 rik Exp $ 22126177Srik */ 23126177Srik#include <sys/cdefs.h> 24126177Srik__FBSDID("$FreeBSD$"); 25126177Srik 26126177Srik#include <dev/cx/machdep.h> 27126177Srik#include <dev/ctau/ctddk.h> 28126177Srik#include <dev/ctau/ctaureg.h> 29126177Srik#include <dev/ctau/hdc64570.h> 30126177Srik#include <dev/ctau/ds2153.h> 31126177Srik#include <dev/ctau/am8530.h> 32126177Srik#include <dev/ctau/lxt318.h> 33126177Srik#include <dev/cx/cronyxfw.h> 34126177Srik#include <dev/ctau/ctaufw.h> 35126177Srik#include <dev/ctau/ctau2fw.h> 36126177Srik 37126177Srik#ifndef CT_DDK_NO_G703 38126177Srik#include <dev/ctau/ctaug7fw.h> 39126177Srik#endif 40126177Srik 41126177Srik#ifndef CT_DDK_NO_E1 42126177Srik#include <dev/ctau/ctaue1fw.h> 43126177Srik#endif 44126177Srik 45126177Srikstatic void ct_hdlc_interrupt (ct_chan_t *c, int imvr); 46126177Srikstatic void ct_e1_interrupt (ct_board_t *b); 47126177Srikstatic void ct_scc_interrupt (ct_board_t *b); 48126177Srikstatic void ct_e1timer_interrupt (ct_chan_t *c); 49126177Srik 50126177Srikstatic short porttab [] = { /* standard base port set */ 51126177Srik 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 52126177Srik 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0 53126177Srik}; 54126177Srik 55126177Srikint ct_find (port_t *board_ports) 56126177Srik{ 57126177Srik int i, n; 58126177Srik 59126177Srik for (i=0, n=0; porttab[i] && n<NBRD; i++) 60126177Srik if (ct_probe_board (porttab[i], -1, -1)) 61126177Srik board_ports[n++] = porttab[i]; 62126177Srik return n; 63126177Srik} 64126177Srik 65126177Srikint ct_open_board (ct_board_t *b, int num, port_t port, int irq, int dma) 66126177Srik{ 67126177Srik ct_chan_t *c; 68126177Srik const unsigned char *fw; 69126177Srik const cr_dat_tst_t *ft; 70126177Srik long flen; 71126177Srik 72126177Srik if (num >= NBRD || ! ct_probe_board (port, irq, dma)) 73126177Srik return 0; 74126177Srik 75126177Srik /* init callback pointers */ 76126177Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 77126177Srik c->call_on_tx = 0; 78126177Srik c->call_on_rx = 0; 79126177Srik c->call_on_msig = 0; 80126177Srik c->call_on_scc = 0; 81126177Srik c->call_on_err = 0; 82126177Srik } 83126177Srik 84126177Srik /* init DDK channel variables */ 85126177Srik for (c=b->chan; c<b->chan+NCHAN; ++c) { 86126177Srik c->sccrx_empty = c->scctx_empty = 1; 87126177Srik c->sccrx_b = c->sccrx_e = 0; 88126177Srik c->scctx_b = c->scctx_e = 0; 89126177Srik c->e1_first_int = 1; 90126177Srik } 91126177Srik 92126177Srik /* init board structure */ 93126177Srik ct_init (b, num, port, irq, dma, ctau_fw_data, 94126177Srik ctau_fw_len, ctau_fw_tvec, ctau2_fw_data); 95126177Srik 96126177Srik /* determine which firmware should be loaded */ 97126177Srik fw = ctau_fw_data; 98126177Srik flen = ctau_fw_len; 99126177Srik ft = ctau_fw_tvec; 100126177Srik switch (b->type) { 101126177Srik case B_TAU2: 102126177Srik case B_TAU2_G703: 103126177Srik case B_TAU2_E1: 104126177Srik case B_TAU2_E1D: 105126177Srik fw = ctau2_fw_data; 106126177Srik flen = 0; 107126177Srik ft = 0; 108126177Srik break; 109126177Srik#ifndef CT_DDK_NO_G703 110126177Srik case B_TAU_G703: 111126177Srik fw = ctaug703_fw_data; 112126177Srik flen = ctaug703_fw_len; 113126177Srik ft = ctaug703_fw_tvec; 114126177Srik break; 115126177Srik#endif 116126177Srik#ifndef CT_DDK_NO_E1 117126177Srik case B_TAU_E1: 118126177Srik fw = ctaue1_fw_data; 119126177Srik flen = ctaue1_fw_len; 120126177Srik ft = ctaue1_fw_tvec; 121126177Srik break; 122126177Srik#endif 123126177Srik } 124126177Srik /* Load firmware and set up board */ 125126177Srik return ct_setup_board (b, fw, flen, ft); 126126177Srik} 127126177Srik 128126177Srik/* 129126177Srik * must be called on the exit 130126177Srik */ 131126177Srikvoid ct_close_board (ct_board_t *b) 132126177Srik{ 133126177Srik ct_setup_board (b, 0, 0, 0); 134126177Srik 135126177Srik /* Reset the controller. */ 136126177Srik outb (BCR0(b->port), 0); 137126177Srik 138126177Srik /* Disable DMA channel. */ 139126177Srik ct_disable_dma (b); 140126177Srik 141126177Srik ct_led (b, 0); 142126177Srik} 143126177Srik 144126177Srikstatic void ct_g703_rate (ct_chan_t *c, unsigned long rate) 145126177Srik{ 146126177Srik c->gopt.rate = rate; 147126177Srik ct_setup_g703 (c->board); 148126177Srik} 149126177Srik 150126177Srik/* 151126177Srik * Set up baud rate. 152126177Srik */ 153126177Srikstatic void ct_chan_baud (ct_chan_t *c, unsigned long baud) 154126177Srik{ 155126177Srik c->baud = baud; 156126177Srik if (baud) { 157126177Srik c->hopt.txs = CLK_INT; 158126177Srik } else { 159126177Srik ct_set_dpll (c, 0); 160126177Srik c->hopt.txs = CLK_LINE; 161126177Srik } 162126177Srik ct_update_chan (c); 163126177Srik} 164126177Srik 165126177Srikvoid ct_set_baud (ct_chan_t *c, unsigned long baud) 166126177Srik{ 167126177Srik unsigned long r; 168126177Srik 169126177Srik if (c->mode == M_E1) 170126177Srik return; 171126177Srik if (c->mode == M_G703) { 172126177Srik if (baud >= 2048000) r = 2048; 173126177Srik else if (baud >= 1024000) r = 1024; 174126177Srik else if (baud >= 512000) r = 512; 175126177Srik else if (baud >= 256000) r = 256; 176126177Srik else if (baud >= 128000) r = 128; 177126177Srik else r = 64; 178126177Srik ct_g703_rate (c, r); 179126177Srik } else 180126177Srik ct_chan_baud (c, baud); 181126177Srik} 182126177Srik 183126177Srik/* 184126177Srik * Configure Tau/E1 board. 185126177Srik */ 186126177Srikstatic void ct_e1_config (ct_board_t *b, unsigned char cfg) 187126177Srik{ 188126177Srik if (cfg == b->opt.cfg) 189126177Srik return; 190126177Srik 191126177Srik if (cfg == CFG_B) 192126177Srik b->chan[1].mode = M_HDLC; 193126177Srik else 194126177Srik b->chan[1].mode = M_E1; 195126177Srik 196126177Srik /* Recovering synchronization */ 197126177Srik if (b->opt.cfg == CFG_B) { 198126177Srik ct_chan_baud (b->chan+1, 0); 199126177Srik ct_set_invtxc (b->chan+1, 0); 200126177Srik ct_set_invrxc (b->chan+1, 0); 201126177Srik ct_set_nrzi (b->chan+1, 0); 202126177Srik } 203126177Srik b->opt.cfg = cfg; 204126177Srik ct_setup_e1 (b); 205126177Srik} 206126177Srik 207126177Srik/* 208126177Srik * Config Tau/G.703 board 209126177Srik */ 210126177Srikstatic void ct_g703_config (ct_board_t *b, unsigned char cfg) 211126177Srik{ 212126177Srik if (cfg == b->opt.cfg) 213126177Srik return; 214126177Srik 215126177Srik if (cfg == CFG_B) 216126177Srik b->chan[1].mode = M_HDLC; 217126177Srik else 218126177Srik b->chan[1].mode = M_G703; 219126177Srik 220126177Srik /* Recovering synchronization */ 221126177Srik if (b->opt.cfg == CFG_B) { 222126177Srik ct_chan_baud (b->chan+1, 0); 223126177Srik ct_set_invtxc (b->chan+1, 0); 224126177Srik ct_set_invrxc (b->chan+1, 0); 225126177Srik ct_set_nrzi (b->chan+1, 0); 226126177Srik } 227126177Srik b->opt.cfg = cfg; 228126177Srik ct_setup_g703 (b); 229126177Srik} 230126177Srik 231126177Srikint ct_set_clk (ct_chan_t *c, int clk) 232126177Srik{ 233126177Srik if (c->num) 234126177Srik c->board->opt.clk1 = clk; 235126177Srik else 236126177Srik c->board->opt.clk0 = clk; 237126177Srik if (c->mode == M_E1) { 238126177Srik ct_setup_e1 (c->board); 239126177Srik return 0; 240126177Srik } if (c->mode == M_G703) { 241126177Srik ct_setup_g703 (c->board); 242126177Srik return 0; 243126177Srik } else 244126177Srik return -1; 245126177Srik} 246126177Srik 247126177Srikint ct_get_clk (ct_chan_t *c) 248126177Srik{ 249126177Srik return c->num ? c->board->opt.clk1 : c->board->opt.clk0; 250126177Srik} 251126177Srik 252126177Srikint ct_set_ts (ct_chan_t *c, unsigned long ts) 253126177Srik{ 254126177Srik if (! (c->mode == M_E1)) 255126177Srik return -1; 256126177Srik if (c->num) 257126177Srik c->board->opt.s1 = ts; 258126177Srik else 259126177Srik c->board->opt.s0 = ts; 260126177Srik ct_setup_e1 (c->board); 261126177Srik return 0; 262126177Srik} 263126177Srik 264126177Srikint ct_set_subchan (ct_board_t *b, unsigned long ts) 265126177Srik{ 266126177Srik if (b->chan[0].mode != M_E1) 267126177Srik return -1; 268126177Srik b->opt.s2 = ts; 269126177Srik ct_setup_e1 (b); 270126177Srik return 0; 271126177Srik} 272126177Srik 273126177Srikint ct_set_higain (ct_chan_t *c, int on) 274126177Srik{ 275126177Srik if (! (c->mode == M_E1)) 276126177Srik return -1; 277126177Srik c->gopt.higain = on ? 1 : 0; 278126177Srik ct_setup_e1 (c->board); 279126177Srik return 0; 280126177Srik} 281126177Srik 282126177Srik/* 283126177Srik * Start service channel. 284126177Srik */ 285126177Srikvoid ct_start_scc (ct_chan_t *c, char *rxbuf, char *txbuf) 286126177Srik{ 287126177Srik c->sccrx = rxbuf; 288126177Srik c->scctx = txbuf; 289126177Srik 290126177Srik /* Enable interrupts from service channel. */ 291126177Srik if (c->board->type != B_TAU_E1 && c->board->type != B_TAU_E1C && 292126177Srik c->board->type != B_TAU2_E1) 293126177Srik return; 294126177Srik 295126177Srik cte_out2 (c->board->port, c->num ? AM_IMR : AM_IMR | AM_A, 296126177Srik IMR_TX | IMR_RX_ALL); 297126177Srik cte_out2 (c->board->port, AM_MICR, MICR_MIE); 298126177Srik} 299126177Srik 300126177Srik/* 301126177Srik * Start HDLC channel. 302126177Srik */ 303126177Srikvoid ct_start_chan (ct_chan_t *c, ct_buf_t *cb, unsigned long phys) 304126177Srik{ 305126177Srik int i, ier0; 306126177Srik unsigned long bound; 307126177Srik 308126177Srik if (cb) { 309126177Srik /* Set up descriptors, align to 64k boundary. 310126177Srik * If 64k boundary is inside buffers 311126177Srik * buffers will begin on this boundary 312126177Srik * (there were allocated additional space for this) */ 313126177Srik c->tdesc = cb->descbuf; 314126177Srik c->tdphys[0] = phys + ((char*)c->tdesc - (char*)cb); 315126177Srik bound = ((c->tdphys[0] + 0xffff) & ~(0xffffUL)); 316126177Srik if (bound < c->tdphys[0] + 2*NBUF*sizeof(ct_desc_t)) { 317126177Srik c->tdesc = (ct_desc_t*) ((char*) c->tdesc + 318126177Srik (bound - c->tdphys[0])); 319126177Srik c->tdphys[0] = bound; 320126177Srik } 321126177Srik c->rdesc = c->tdesc + NBUF; 322126177Srik 323126177Srik /* Set buffers. */ 324126177Srik for (i=0; i<NBUF; ++i) { 325126177Srik c->rbuf[i] = cb->rbuffer[i]; 326126177Srik c->tbuf[i] = cb->tbuffer[i]; 327126177Srik } 328126177Srik 329126177Srik /* Set buffer physical addresses */ 330126177Srik for (i=0; i<NBUF; ++i) { 331126177Srik c->rphys[i] = phys + ((char*)c->rbuf[i] - (char*)cb); 332126177Srik c->tphys[i] = phys + ((char*)c->tbuf[i] - (char*)cb); 333126177Srik c->rdphys[i] = phys + ((char*)(c->rdesc+i) - (char*)cb); 334126177Srik c->tdphys[i] = phys + ((char*)(c->tdesc+i) - (char*)cb); 335126177Srik } 336126177Srik } 337126177Srik /* Set up block chains. */ 338126177Srik /* receive buffers */ 339126177Srik for (i=0; i<NBUF; ++i) { 340126177Srik B_NEXT (c->rdesc[i]) = c->rdphys[(i+1) % NBUF] & 0xffff; 341126177Srik B_PTR (c->rdesc[i]) = c->rphys[i]; 342126177Srik B_LEN (c->rdesc[i]) = DMABUFSZ; 343126177Srik B_STATUS (c->rdesc[i]) = 0; 344126177Srik } 345126177Srik /* transmit buffers */ 346126177Srik for (i=0; i<NBUF; ++i) { 347126177Srik B_NEXT (c->tdesc[i]) = c->tdphys[(i+1) % NBUF] & 0xffff; 348126177Srik B_PTR (c->tdesc[i]) = c->tphys[i]; 349126177Srik B_LEN (c->tdesc[i]) = DMABUFSZ; 350126177Srik B_STATUS (c->tdesc[i]) = FST_EOM; 351126177Srik c->attach[i] = 0; 352126177Srik } 353126177Srik 354126177Srik if (c->type & T_E1) { 355126177Srik c->mode = M_E1; 356126177Srik if (c->num && c->board->opt.cfg == CFG_B) 357126177Srik c->mode = M_HDLC; 358126177Srik } 359126177Srik if (c->type & T_G703) { 360126177Srik c->mode = M_G703; 361126177Srik if (c->num && c->board->opt.cfg == CFG_B) 362126177Srik c->mode = M_HDLC; 363126177Srik } 364126177Srik ct_update_chan (c); 365126177Srik 366126177Srik /* enable receiver */ 367126177Srik c->rn = 0; 368126177Srik ct_start_receiver (c, 1 , c->rphys[0], DMABUFSZ, c->rdphys[0], 369126177Srik c->rdphys[NBUF-1]); 370126177Srik outb (c->IE1, inb (c->IE1) | IE1_CDCDE); 371126177Srik outb (c->IE0, inb (c->IE0) | IE0_RX_INTE); 372126177Srik ier0 = inb (IER0(c->board->port)); 373126177Srik ier0 |= c->num ? IER0_RX_INTE_1 : IER0_RX_INTE_0; 374126177Srik outb (IER0(c->board->port), ier0); 375126177Srik 376126177Srik /* Enable transmitter */ 377126177Srik c->tn = 0; 378126177Srik c->te = 0; 379126177Srik ct_start_transmitter (c, 1 , c->tphys[0], DMABUFSZ, c->tdphys[0], 380126177Srik c->tdphys[0]); 381126177Srik outb (c->TX.DIR, DIR_CHAIN_EOME | DIR_CHAIN_BOFE | DIR_CHAIN_COFE); 382126177Srik 383126177Srik /* Clear DTR and RTS */ 384126177Srik ct_set_dtr (c, 0); 385126177Srik ct_set_rts (c, 0); 386126177Srik} 387126177Srik 388126177Srik/* 389126177Srik * Turn receiver on/off 390126177Srik */ 391126177Srikvoid ct_enable_receive (ct_chan_t *c, int on) 392126177Srik{ 393126177Srik unsigned char st3, ier0, ier1; 394126177Srik 395126177Srik st3 = inb (c->ST3); 396126177Srik /* enable or disable receiver */ 397126177Srik if (on && ! (st3 & ST3_RX_ENABLED)) { 398126177Srik c->rn = 0; 399126177Srik ct_start_receiver (c, 1 , c->rphys[0], DMABUFSZ, c->rdphys[0], 400126177Srik c->rdphys[NBUF-1]); 401126177Srik /* enable status interrupt */ 402126177Srik outb (c->IE1, inb (c->IE1) | IE1_CDCDE); 403126177Srik outb (c->IE0, inb (c->IE0) | IE0_RX_INTE); 404126177Srik ier0 = inb (IER0(c->board->port)); 405126177Srik ier0 |= c->num ? IER0_RX_INTE_1 : IER0_RX_INTE_0; 406126177Srik outb (IER0(c->board->port), ier0); 407126177Srik ct_set_rts (c, 1); 408126177Srik } else if (! on && (st3 & ST3_RX_ENABLED)) { 409126177Srik ct_set_rts (c, 0); 410126177Srik outb (c->CMD, CMD_RX_DISABLE); 411126177Srik 412126177Srik ier0 = inb (IER0(c->board->port)); 413126177Srik ier0 &= c->num ? ~(IER0_RX_INTE_1 | IER0_RX_RDYE_1) : 414126177Srik ~(IER0_RX_INTE_0 | IER0_RX_RDYE_0); 415126177Srik outb (IER0(c->board->port), ier0); 416126177Srik 417126177Srik ier1 = inb (IER1(c->board->port)); 418126177Srik ier1 &= c->num ? ~(IER1_RX_DMERE_1 | IER1_RX_DME_1) : 419126177Srik ~(IER1_RX_DMERE_0 | IER1_RX_DME_0); 420126177Srik outb (IER1(c->board->port), ier1); 421126177Srik } 422126177Srik 423126177Srik} 424126177Srik 425126177Srik/* 426126177Srik * Turn transmitter on/off 427126177Srik */ 428126177Srikvoid ct_enable_transmit (ct_chan_t *c, int on) 429126177Srik{ 430126177Srik unsigned char st3, ier0, ier1; 431126177Srik 432126177Srik st3 = inb (c->ST3); 433126177Srik /* enable or disable receiver */ 434126177Srik if (on && ! (st3 & ST3_TX_ENABLED)) { 435126177Srik c->tn = 0; 436126177Srik c->te = 0; 437126177Srik ct_start_transmitter (c, 1 , c->tphys[0], DMABUFSZ, 438126177Srik c->tdphys[0], c->tdphys[0]); 439126177Srik outb (c->TX.DIR, 440126177Srik DIR_CHAIN_EOME | DIR_CHAIN_BOFE | DIR_CHAIN_COFE); 441126177Srik } else if (! on && (st3 & ST3_TX_ENABLED)) { 442126177Srik outb (c->CMD, CMD_TX_DISABLE); 443126177Srik 444126177Srik ier0 = inb (IER0(c->board->port)); 445126177Srik ier0 &= c->num ? ~(IER0_TX_INTE_1 | IER0_TX_RDYE_1) : 446126177Srik ~(IER0_TX_INTE_0 | IER0_TX_RDYE_0); 447126177Srik outb (IER0(c->board->port), ier0); 448126177Srik 449126177Srik ier1 = inb (IER1(c->board->port)); 450126177Srik ier1 &= c->num ? ~(IER1_TX_DMERE_1 | IER1_TX_DME_1) : 451126177Srik ~(IER1_TX_DMERE_0 | IER1_TX_DME_0); 452126177Srik outb (IER1(c->board->port), ier1); 453126177Srik } 454126177Srik 455126177Srik} 456126177Srik 457126177Srikint ct_set_config (ct_board_t *b, int cfg) 458126177Srik{ 459126177Srik if (b->opt.cfg == cfg) 460126177Srik return 0; 461126177Srik switch (b->type) { 462126177Srik case B_TAU_G703: 463126177Srik case B_TAU_G703C: 464126177Srik case B_TAU2_G703: 465126177Srik if (cfg == CFG_C) 466126177Srik return -1; 467126177Srik ct_g703_config (b, cfg); 468126177Srik return 0; 469126177Srik case B_TAU_E1: 470126177Srik case B_TAU_E1C: 471126177Srik case B_TAU_E1D: 472126177Srik case B_TAU2_E1: 473126177Srik case B_TAU2_E1D: 474126177Srik ct_e1_config (b, cfg); 475126177Srik return 0; 476126177Srik default: 477126177Srik return cfg == CFG_A ? 0 : -1; 478126177Srik } 479126177Srik} 480126177Srik 481126177Srikint ct_get_dpll (ct_chan_t *c) 482126177Srik{ 483126177Srik return (c->hopt.rxs == CLK_RXS_DPLL_INT); 484126177Srik} 485126177Srik 486126177Srikvoid ct_set_dpll (ct_chan_t *c, int on) 487126177Srik{ 488126177Srik if (on && ct_get_baud (c)) 489126177Srik c->hopt.rxs = CLK_RXS_DPLL_INT; 490126177Srik else 491126177Srik c->hopt.rxs = CLK_LINE; 492126177Srik ct_update_chan (c); 493126177Srik} 494126177Srik 495126177Srikint ct_get_nrzi (ct_chan_t *c) 496126177Srik{ 497126177Srik return (c->opt.md2.encod == MD2_ENCOD_NRZI); 498126177Srik} 499126177Srik 500126177Srik/* 501126177Srik * Change line encoding to NRZI, default is NRZ 502126177Srik */ 503126177Srikvoid ct_set_nrzi (ct_chan_t *c, int on) 504126177Srik{ 505126177Srik c->opt.md2.encod = on ? MD2_ENCOD_NRZI : MD2_ENCOD_NRZ; 506126177Srik outb (c->MD2, *(unsigned char*)&c->opt.md2); 507126177Srik} 508126177Srik 509126177Srik/* 510126177Srik * Transmit clock inversion 511126177Srik */ 512126177Srikvoid ct_set_invtxc (ct_chan_t *c, int on) 513126177Srik{ 514126177Srik if (on) c->board->bcr2 |= (c->num ? BCR2_INVTXC1 : BCR2_INVTXC0); 515126177Srik else c->board->bcr2 &= ~(c->num ? BCR2_INVTXC1 : BCR2_INVTXC0); 516126177Srik outb (BCR2(c->board->port), c->board->bcr2); 517126177Srik} 518126177Srik 519126177Srikint ct_get_invtxc (ct_chan_t *c) 520126177Srik{ 521126177Srik return (c->board->bcr2 & (c->num ? BCR2_INVTXC1 : BCR2_INVTXC0)) != 0; 522126177Srik} 523126177Srik 524126177Srik/* 525126177Srik * Receive clock inversion 526126177Srik */ 527126177Srikvoid ct_set_invrxc (ct_chan_t *c, int on) 528126177Srik{ 529126177Srik if (on) c->board->bcr2 |= (c->num ? BCR2_INVRXC1 : BCR2_INVRXC0); 530126177Srik else c->board->bcr2 &= ~(c->num ? BCR2_INVRXC1 : BCR2_INVRXC0); 531126177Srik outb (BCR2(c->board->port), c->board->bcr2); 532126177Srik} 533126177Srik 534126177Srikint ct_get_invrxc (ct_chan_t *c) 535126177Srik{ 536126177Srik return (c->board->bcr2 & (c->num ? BCR2_INVRXC1 : BCR2_INVRXC0)) != 0; 537126177Srik} 538126177Srik 539126177Srik/* 540126177Srik * Main interrupt handler 541126177Srik */ 542126177Srikvoid ct_int_handler (ct_board_t *b) 543126177Srik{ 544126177Srik unsigned char bsr0, imvr; 545126177Srik ct_chan_t *c; 546126177Srik 547126177Srik while ((bsr0 = inb (BSR0(b->port))) & BSR0_INTR) { 548126177Srik if (bsr0 & BSR0_RDYERR) { 549126177Srik outb (BCR1(b->port), b->bcr1); 550126177Srik } else if (bsr0 & BSR0_GINT) { 551126177Srik if (b->type == B_TAU_E1 || b->type == B_TAU_E1C || 552126177Srik b->type == B_TAU_E1D || b->type == B_TAU2_E1 || 553126177Srik b->type == B_TAU2_E1D) 554126177Srik ct_e1_interrupt (b); 555126177Srik } else if (bsr0 & BSR0_HDINT) { 556126177Srik /* Read the interrupt modified vector register. */ 557126177Srik imvr = inb (IACK(b->port)); 558126177Srik c = b->chan + (imvr & IMVR_CHAN1 ? 1 : 0); 559126177Srik ct_hdlc_interrupt (c, imvr); 560126177Srik } 561126177Srik } 562126177Srik} 563126177Srik 564126177Srikstatic void ct_e1_interrupt (ct_board_t *b) 565126177Srik{ 566126177Srik unsigned char sr; 567126177Srik 568126177Srik sr = inb (E1SR(b->port)); 569126177Srik 570126177Srik if (sr & E1SR_SCC_IRQ) ct_scc_interrupt (b); 571126177Srik if (sr & E1SR_E0_IRQ1) ct_e1timer_interrupt (b->chan + 0); 572126177Srik if (sr & E1SR_E1_IRQ1) ct_e1timer_interrupt (b->chan + 1); 573126177Srik} 574126177Srik 575126177Srikstatic void ct_scc_interrupt (ct_board_t *b) 576126177Srik{ 577126177Srik unsigned char rsr; 578126177Srik unsigned char ivr, a = AM_A; /* assume channel A */ 579126177Srik ct_chan_t *c = b->chan; 580126177Srik 581126177Srik ivr = cte_in2 (b->port, AM_IVR); 582126177Srik if (! (ivr & IVR_A)) 583126177Srik ++c, a = 0; /* really channel B */ 584126177Srik 585126177Srik switch (ivr & IVR_REASON) { 586126177Srik case IVR_TXRDY: /* transmitter empty */ 587126177Srik c->scctx_b = (c->scctx_b + 1) % SCCBUFSZ; 588126177Srik if (c->scctx_b == c->scctx_e) { 589126177Srik c->scctx_empty = 1; 590126177Srik cte_out2c (c, AM_CR | CR_RST_TXINT); 591126177Srik } else 592126177Srik cte_out2d (c, c->scctx[c->scctx_b]); 593126177Srik break; 594126177Srik 595126177Srik case IVR_RXERR: /* receive error */ 596126177Srik case IVR_RX: /* receive character available */ 597126177Srik rsr = cte_in2 (b->port, a|AM_RSR); 598126177Srik 599126177Srik if (rsr & RSR_RXOVRN) { /* rx overrun */ 600126177Srik if (c->call_on_err) 601126177Srik c->call_on_err (c, CT_SCC_OVERRUN); 602126177Srik } else if (rsr & RSR_FRME) { /* frame error */ 603126177Srik if (c->call_on_err) 604126177Srik c->call_on_err (c, CT_SCC_FRAME); 605126177Srik } else { 606126177Srik c->sccrx[c->sccrx_e] = cte_in2d (c); 607126177Srik c->sccrx_e = (c->sccrx_e + 1) % SCCBUFSZ; 608126177Srik c->sccrx_empty &= 0; 609126177Srik if (c->call_on_scc) 610126177Srik c->call_on_scc (c); 611126177Srik if (c->sccrx_e == c->sccrx_b && ! c->sccrx_empty) 612126177Srik if (c->call_on_err) 613126177Srik c->call_on_err (c, CT_SCC_OVERFLOW); 614126177Srik } 615126177Srik if (rsr) 616126177Srik cte_out2c (c, CR_RST_ERROR); 617126177Srik break; 618126177Srik 619126177Srik case IVR_STATUS: /* external status interrupt */ 620126177Srik /* Unexpected SCC status interrupt. */ 621126177Srik cte_out2c (c, CR_RST_EXTINT); 622126177Srik break; 623126177Srik } 624126177Srik} 625126177Srik 626126177Srik/* 627126177Srik * G.703 mode channel: process 1-second timer interrupts. 628126177Srik * Read error and request registers, and fill the status field. 629126177Srik */ 630126177Srikvoid ct_g703_timer (ct_chan_t *c) 631126177Srik{ 632126177Srik int bpv, cd, tsterr, tstreq; 633126177Srik 634126177Srik /* Count seconds. 635126177Srik * During the first second after the channel startup 636126177Srik * the status registers are not stable yet, 637126177Srik * we will so skip the first second. */ 638126177Srik ++c->cursec; 639126177Srik if (c->mode != M_G703) 640126177Srik return; 641126177Srik if (c->totsec + c->cursec <= 1) 642126177Srik return; 643126177Srik c->status = 0; 644126177Srik 645126177Srik cd = ct_get_cd (c); 646126177Srik 647126177Srik bpv = inb (GERR (c->board->port)) & (c->num ? GERR_BPV1 : GERR_BPV0); 648126177Srik outb (GERR (c->board->port), bpv); 649126177Srik 650126177Srik tsterr = inb (GERR (c->board->port)) & (c->num ? GERR_ERR1 : GERR_ERR0); 651126177Srik outb (GERR (c->board->port), tsterr); 652126177Srik 653126177Srik tstreq = inb (GLDR (c->board->port)) & 654126177Srik (c->num ? GLDR_LREQ1 : GLDR_LREQ0); 655126177Srik outb (GLDR (c->board->port), tstreq); 656126177Srik 657126177Srik /* Compute the SNMP-compatible channel status. */ 658126177Srik if (bpv) 659126177Srik ++c->currnt.bpv; /* bipolar violation */ 660126177Srik if (! cd) 661126177Srik c->status |= ESTS_LOS; /* loss of signal */ 662126177Srik if (tsterr) 663126177Srik c->status |= ESTS_TSTERR; /* test error */ 664126177Srik if (tstreq) 665126177Srik c->status |= ESTS_TSTREQ; /* test code detected */ 666126177Srik 667126177Srik if (! c->status) 668126177Srik c->status = ESTS_NOALARM; 669126177Srik 670126177Srik /* Unavaiable second -- loss of carrier, or receiving test code. */ 671126177Srik if ((! cd) || tstreq) 672126177Srik /* Unavailable second -- no other counters. */ 673126177Srik ++c->currnt.uas; 674126177Srik else { 675126177Srik /* Line errored second -- any BPV. */ 676126177Srik if (bpv) 677126177Srik ++c->currnt.les; 678126177Srik 679126177Srik /* Collect data for computing 680126177Srik * degraded minutes. */ 681126177Srik ++c->degsec; 682126177Srik if (cd && bpv) 683126177Srik ++c->degerr; 684126177Srik } 685126177Srik 686126177Srik /* Degraded minutes -- having more than 50% error intervals. */ 687126177Srik if (c->cursec / 60 == 0) { 688126177Srik if (c->degerr*2 > c->degsec) 689126177Srik ++c->currnt.dm; 690126177Srik c->degsec = 0; 691126177Srik c->degerr = 0; 692126177Srik } 693126177Srik 694126177Srik /* Rotate statistics every 15 minutes. */ 695126177Srik if (c->cursec > 15*60) { 696126177Srik int i; 697126177Srik 698126177Srik for (i=47; i>0; --i) 699126177Srik c->interval[i] = c->interval[i-1]; 700126177Srik c->interval[0] = c->currnt; 701126177Srik 702126177Srik /* Accumulate total statistics. */ 703126177Srik c->total.bpv += c->currnt.bpv; 704126177Srik c->total.fse += c->currnt.fse; 705126177Srik c->total.crce += c->currnt.crce; 706126177Srik c->total.rcrce += c->currnt.rcrce; 707126177Srik c->total.uas += c->currnt.uas; 708126177Srik c->total.les += c->currnt.les; 709126177Srik c->total.es += c->currnt.es; 710126177Srik c->total.bes += c->currnt.bes; 711126177Srik c->total.ses += c->currnt.ses; 712126177Srik c->total.oofs += c->currnt.oofs; 713126177Srik c->total.css += c->currnt.css; 714126177Srik c->total.dm += c->currnt.dm; 715126177Srik memset (&c->currnt, 0, sizeof (c->currnt)); 716126177Srik 717126177Srik c->totsec += c->cursec; 718126177Srik c->cursec = 0; 719126177Srik } 720126177Srik} 721126177Srik 722126177Srikstatic void ct_e1timer_interrupt (ct_chan_t *c) 723126177Srik{ 724126177Srik unsigned short port; 725126177Srik unsigned char sr1, sr2, ssr; 726126177Srik unsigned long bpv, fas, crc4, ebit, pcv, oof; 727126177Srik 728126177Srik port = c->num ? E1CS1(c->board->port) : E1CS0(c->board->port); 729126177Srik 730126177Srik sr2 = cte_ins (port, DS_SR2, 0xff); 731126177Srik /* is it timer interrupt ? */ 732126177Srik if (! (sr2 & SR2_SEC)) 733126177Srik return; 734126177Srik 735126177Srik /* first interrupts should be ignored */ 736126177Srik if (c->e1_first_int > 0) { 737126177Srik c->e1_first_int --; 738126177Srik return; 739126177Srik } 740126177Srik 741126177Srik ++c->cursec; 742126177Srik c->status = 0; 743126177Srik 744126177Srik /* Compute the SNMP-compatible channel status. */ 745126177Srik sr1 = cte_ins (port, DS_SR1, 0xff); 746126177Srik ssr = cte_in (port, DS_SSR); 747126177Srik oof = 0; 748126177Srik 749126177Srik if (sr1 & (SR1_RCL | SR1_RLOS)) 750126177Srik c->status |= ESTS_LOS; /* loss of signal */ 751126177Srik if (sr1 & SR1_RUA1) 752126177Srik c->status |= ESTS_AIS; /* receiving all ones */ 753126177Srik if (c->gopt.cas && (sr1 & SR1_RSA1)) 754126177Srik c->status |= ESTS_AIS16; /* signaling all ones */ 755126177Srik if (c->gopt.cas && (sr1 & SR1_RDMA)) 756126177Srik c->status |= ESTS_FARLOMF; /* alarm in timeslot 16 */ 757126177Srik if (sr1 & SR1_RRA) 758126177Srik c->status |= ESTS_FARLOF; /* far loss of framing */ 759126177Srik 760126177Srik /* Controlled slip second -- any slip event. */ 761126177Srik if (sr1 & SR1_RSLIP) { 762126177Srik ++c->currnt.css; 763126177Srik } 764126177Srik 765126177Srik if (ssr & SSR_SYNC) { 766126177Srik c->status |= ESTS_LOF; /* loss of framing */ 767126177Srik ++oof; /* out of framing */ 768126177Srik } 769126177Srik if ((c->gopt.cas && (ssr & SSR_SYNC_CAS)) || 770126177Srik (c->gopt.crc4 && (ssr & SSR_SYNC_CRC4))) { 771126177Srik c->status |= ESTS_LOMF; /* loss of multiframing */ 772126177Srik ++oof; /* out of framing */ 773126177Srik } 774126177Srik 775126177Srik if (! c->status) 776126177Srik c->status = ESTS_NOALARM; 777126177Srik 778126177Srik /* Get error counters. */ 779126177Srik bpv = VCR (cte_in (port, DS_VCR1), cte_in (port, DS_VCR2)); 780126177Srik fas = FASCR (cte_in (port, DS_FASCR1), cte_in (port, DS_FASCR2)); 781126177Srik crc4 = CRCCR (cte_in (port, DS_CRCCR1), cte_in (port, DS_CRCCR2)); 782126177Srik ebit = EBCR (cte_in (port, DS_EBCR1), cte_in (port, DS_EBCR2)); 783126177Srik 784126177Srik c->currnt.bpv += bpv; 785126177Srik c->currnt.fse += fas; 786126177Srik if (c->gopt.crc4) { 787126177Srik c->currnt.crce += crc4; 788126177Srik c->currnt.rcrce += ebit; 789126177Srik } 790126177Srik 791126177Srik /* Path code violation is frame sync error if CRC4 disabled, 792126177Srik * or CRC error if CRC4 enabled. */ 793126177Srik pcv = fas; 794126177Srik if (c->gopt.crc4) 795126177Srik pcv += crc4; 796126177Srik 797126177Srik /* Unavaiable second -- receiving all ones, or 798126177Srik * loss of carrier, or loss of signal. */ 799126177Srik if (sr1 & (SR1_RUA1 | SR1_RCL | SR1_RLOS)) 800126177Srik /* Unavailable second -- no other counters. */ 801126177Srik ++c->currnt.uas; 802126177Srik else { 803126177Srik /* Line errored second -- any BPV. */ 804126177Srik if (bpv) 805126177Srik ++c->currnt.les; 806126177Srik 807126177Srik /* Errored second -- any PCV, or out of frame sync, 808126177Srik * or any slip events. */ 809126177Srik if (pcv || oof || (sr1 & SR1_RSLIP)) 810126177Srik ++c->currnt.es; 811126177Srik 812126177Srik /* Severely errored framing second -- out of frame sync. */ 813126177Srik if (oof) 814126177Srik ++c->currnt.oofs; 815126177Srik 816126177Srik /* Severely errored seconds -- 817126177Srik * 832 or more PCVs, or 2048 or more BPVs. */ 818126177Srik if (bpv >= 2048 || pcv >= 832) 819126177Srik ++c->currnt.ses; 820126177Srik else { 821126177Srik /* Bursty errored seconds -- 822126177Srik * no SES and more than 1 PCV. */ 823126177Srik if (pcv > 1) 824126177Srik ++c->currnt.bes; 825126177Srik 826126177Srik /* Collect data for computing 827126177Srik * degraded minutes. */ 828126177Srik ++c->degsec; 829126177Srik c->degerr += bpv + pcv; 830126177Srik } 831126177Srik } 832126177Srik 833126177Srik /* Degraded minutes -- having error rate more than 10e-6, 834126177Srik * not counting unavailable and severely errored seconds. */ 835126177Srik if (c->cursec / 60 == 0) { 836126177Srik if (c->degerr > c->degsec * 2048 / 1000) 837126177Srik ++c->currnt.dm; 838126177Srik c->degsec = 0; 839126177Srik c->degerr = 0; 840126177Srik } 841126177Srik 842126177Srik /* Rotate statistics every 15 minutes. */ 843126177Srik if (c->cursec > 15*60) { 844126177Srik int i; 845126177Srik 846126177Srik for (i=47; i>0; --i) 847126177Srik c->interval[i] = c->interval[i-1]; 848126177Srik c->interval[0] = c->currnt; 849126177Srik 850126177Srik /* Accumulate total statistics. */ 851126177Srik c->total.bpv += c->currnt.bpv; 852126177Srik c->total.fse += c->currnt.fse; 853126177Srik c->total.crce += c->currnt.crce; 854126177Srik c->total.rcrce += c->currnt.rcrce; 855126177Srik c->total.uas += c->currnt.uas; 856126177Srik c->total.les += c->currnt.les; 857126177Srik c->total.es += c->currnt.es; 858126177Srik c->total.bes += c->currnt.bes; 859126177Srik c->total.ses += c->currnt.ses; 860126177Srik c->total.oofs += c->currnt.oofs; 861126177Srik c->total.css += c->currnt.css; 862126177Srik c->total.dm += c->currnt.dm; 863126177Srik for (i=0; i<sizeof (c->currnt); ++i) 864126177Srik *(((char *)(&c->currnt))+i)=0; 865126177Srik 866126177Srik c->totsec += c->cursec; 867126177Srik c->cursec = 0; 868126177Srik } 869126177Srik} 870126177Srik 871126177Srikstatic void ct_hdlc_interrupt (ct_chan_t *c, int imvr) 872126177Srik{ 873126177Srik int i, dsr, st1, st2, cda; 874126177Srik 875126177Srik switch (imvr & IMVR_VECT_MASK) { 876126177Srik case IMVR_RX_DMOK: /* receive DMA normal end */ 877126177Srik dsr = inb (c->RX.DSR); 878126177Srik cda = inw (c->RX.CDA); 879126177Srik for (i=0; i<NBUF; ++i) 880126177Srik if (cda == (unsigned short) c->rdphys[i]) 881126177Srik break; 882126177Srik if (i >= NBUF) 883126177Srik i = c->rn; /* cannot happen */ 884126177Srik while (c->rn != i) { 885126177Srik int cst = B_STATUS (c->rdesc[c->rn]); 886126177Srik if (cst == FST_EOM) { 887126177Srik /* process data */ 888126177Srik if (c->call_on_rx) 889126177Srik c->call_on_rx (c, c->rbuf[c->rn], 890126177Srik B_LEN(c->rdesc[c->rn])); 891126177Srik ++c->ipkts; 892126177Srik c->ibytes += B_LEN(c->rdesc[c->rn]); 893126177Srik } else if (cst & ST2_OVRN) { 894126177Srik /* Receive overrun error */ 895126177Srik if (c->call_on_err) 896126177Srik c->call_on_err (c, CT_OVERRUN); 897126177Srik ++c->ierrs; 898126177Srik } else if (cst & (ST2_HDLC_RBIT | 899126177Srik ST2_HDLC_ABT | ST2_HDLC_SHRT)) { 900126177Srik /* Receive frame error */ 901126177Srik if (c->call_on_err) 902126177Srik c->call_on_err (c, CT_FRAME); 903126177Srik ++c->ierrs; 904126177Srik } else if ((cst & ST2_HDLC_EOM) 905126177Srik && (cst & ST2_HDLC_CRCE)) { 906126177Srik /* Receive CRC error */ 907126177Srik if (c->call_on_err) 908126177Srik c->call_on_err (c, CT_CRC); 909126177Srik ++c->ierrs; 910126177Srik } else if (! (cst & ST2_HDLC_EOM)) { 911126177Srik /* Frame dose not fit in the buffer.*/ 912126177Srik if (c->call_on_err) 913126177Srik c->call_on_err (c, CT_OVERFLOW); 914126177Srik ++c->ierrs; 915126177Srik } 916126177Srik 917126177Srik B_NEXT (c->rdesc[c->rn]) = 918126177Srik c->rdphys[(c->rn+1) % NBUF] & 0xffff; 919126177Srik B_PTR (c->rdesc[c->rn]) = c->rphys[c->rn]; 920126177Srik B_LEN (c->rdesc[c->rn]) = DMABUFSZ; 921126177Srik B_STATUS (c->rdesc[c->rn]) = 0; 922126177Srik c->rn = (c->rn + 1) % NBUF; 923126177Srik } 924126177Srik outw (c->RX.EDA, (unsigned short) c->rdphys[(i+NBUF-1)%NBUF]); 925126177Srik /* Clear DMA interrupt. */ 926126177Srik if (inb (c->RX.DSR) & DSR_DMA_ENABLE) { 927126177Srik outb (c->RX.DSR, dsr); 928126177Srik } else { 929126177Srik outb (c->RX.DSR, (dsr & 0xfc) | DSR_DMA_ENABLE); 930126177Srik } 931126177Srik ++c->rintr; 932126177Srik break; 933126177Srik 934126177Srik case IMVR_RX_INT: /* receive status */ 935126177Srik st1 = inb (c->ST1); 936126177Srik st2 = inb (c->ST2); 937126177Srik if (st1 & ST1_CDCD){ 938126177Srik if (c->call_on_msig) 939126177Srik c->call_on_msig (c); 940126177Srik ++c->mintr; 941126177Srik } 942126177Srik /* Clear interrupt. */ 943126177Srik outb (c->ST1, st1); 944126177Srik outb (c->ST2, st2); 945126177Srik ++c->rintr; 946126177Srik break; 947126177Srik 948126177Srik case IMVR_RX_DMERR: /* receive DMA error */ 949126177Srik dsr = inb (c->RX.DSR); 950126177Srik if (dsr & (DSR_CHAIN_BOF | DSR_CHAIN_COF)) { 951126177Srik if (c->call_on_err) 952126177Srik c->call_on_err (c, CT_OVERFLOW); 953126177Srik ++c->ierrs; 954126177Srik for (i=0; i<NBUF; ++i) { 955126177Srik B_LEN (c->rdesc[i]) = DMABUFSZ; 956126177Srik B_STATUS (c->rdesc[i]) = 0; 957126177Srik } 958126177Srik ct_start_receiver (c, 1, c->rphys[0], DMABUFSZ, 959126177Srik c->rdphys[0], c->rdphys[NBUF-1]); 960126177Srik c->rn = 0; 961126177Srik } 962126177Srik /* Clear DMA interrupt. */ 963126177Srik outb (c->RX.DSR, dsr); 964126177Srik ++c->rintr; 965126177Srik break; 966126177Srik 967126177Srik case IMVR_TX_DMOK: /* transmit DMA normal end */ 968126177Srik case IMVR_TX_DMERR: /* transmit DMA error */ 969126177Srik dsr = inb (c->TX.DSR); 970126177Srik cda = inw (c->TX.CDA); 971126177Srik 972126177Srik for (i=0; i<NBUF && cda != (unsigned short)c->tdphys[i]; ++i) 973126177Srik continue; 974126177Srik if (i >= NBUF) 975126177Srik i = 1; /* cannot happen */ 976126177Srik if (dsr & DSR_CHAIN_COF) { 977126177Srik if (c->call_on_err) 978126177Srik c->call_on_err (c, CT_UNDERRUN); 979126177Srik ++c->oerrs; 980126177Srik } 981126177Srik while (c->tn != i) { 982126177Srik if (c->call_on_tx) 983126177Srik c->call_on_tx (c, c->attach[c->tn], 984126177Srik B_LEN(c->tdesc[c->tn])); 985126177Srik ++c->opkts; 986126177Srik c->obytes += B_LEN(c->tdesc[c->tn]); 987126177Srik 988126177Srik c->tn = (c->tn + 1) % NBUF; 989126177Srik /* Clear DMA interrupt. */ 990126177Srik outb (c->TX.DSR, DSR_CHAIN_EOM | DSR_DMA_CONTINUE); 991126177Srik } 992126177Srik outb (c->TX.DSR, dsr & ~DSR_CHAIN_EOM); 993126177Srik ++c->tintr; 994126177Srik break; 995126177Srik 996126177Srik case IMVR_TX_INT: /* transmit error, HDLC only */ 997126177Srik st1 = inb (c->ST1); 998126177Srik if (st1 & ST1_HDLC_UDRN) { 999126177Srik if (c->call_on_err) 1000126177Srik c->call_on_err (c, CT_UNDERRUN); 1001126177Srik ++c->oerrs; 1002126177Srik } 1003126177Srik outb (c->ST1, st1); 1004126177Srik ++c->tintr; 1005126177Srik break; 1006126177Srik 1007126177Srik default: 1008126177Srik /* Unknown interrupt - cannot happen. */ 1009126177Srik break; 1010126177Srik } 1011126177Srik} 1012126177Srik 1013126177Srikint ct_receive_enabled (ct_chan_t *c) 1014126177Srik{ 1015126177Srik int st3; 1016126177Srik 1017126177Srik st3 = inb (c->ST3); 1018126177Srik return (st3 & ST3_RX_ENABLED) ? 1 : 0; 1019126177Srik} 1020126177Srik 1021126177Srikint ct_transmit_enabled (ct_chan_t *c) 1022126177Srik{ 1023126177Srik int st3; 1024126177Srik 1025126177Srik st3 = inb (c->ST3); 1026126177Srik return (st3 & ST3_TX_ENABLED) ? 1 : 0; 1027126177Srik} 1028126177Srik 1029126177Srikint ct_buf_free (ct_chan_t *c) 1030126177Srik{ 1031126177Srik return (NBUF + c->tn - c->te - 1) % NBUF; 1032126177Srik} 1033126177Srik 1034126177Srikint ct_send_packet (ct_chan_t *c, unsigned char *data, int len, 1035126177Srik void *attachment) 1036126177Srik{ 1037126177Srik int dsr, ne; 1038126177Srik 1039126177Srik if (len > DMABUFSZ) 1040126177Srik return -2; 1041126177Srik 1042126177Srik /* Is it really free? */ 1043126177Srik ne = (c->te+1) % NBUF; 1044126177Srik if (ne == c->tn) 1045126177Srik return -1; 1046126177Srik 1047126177Srik /* Set up the tx descriptor. */ 1048126177Srik B_LEN (c->tdesc[c->te]) = len; 1049126177Srik B_STATUS (c->tdesc[c->te]) = FST_EOM; 1050126177Srik c->attach[c->te] = attachment; 1051126177Srik if (c->tbuf[c->te] != data) 1052126177Srik memcpy (c->tbuf[c->te], data, len); 1053126177Srik 1054126177Srik /* Start the transmitter. */ 1055126177Srik c->te = ne; 1056126177Srik outw (c->TX.EDA, (unsigned short) c->tdphys[ne]); 1057126177Srik dsr = inb (c->TX.DSR); 1058126177Srik if (! (dsr & DSR_DMA_ENABLE)) 1059126177Srik outb (c->TX.DSR, DSR_DMA_ENABLE); 1060126177Srik return 0; 1061126177Srik} 1062126177Srik 1063126177Srikint scc_write (ct_chan_t *c, unsigned char *d, int len) 1064126177Srik{ 1065126177Srik int i, free; 1066126177Srik 1067126177Srik /* determining free place in buffer */ 1068126177Srik if (c->scctx_empty) 1069126177Srik free = SCCBUFSZ; 1070126177Srik else 1071126177Srik free = (SCCBUFSZ + c->scctx_b - c->scctx_e) % SCCBUFSZ; 1072126177Srik 1073126177Srik if (len > free) 1074126177Srik return -1; 1075126177Srik 1076126177Srik for (i=0; i<len; i++){ 1077126177Srik c->scctx[c->scctx_e] = d[i]; 1078126177Srik c->scctx_e = (c->scctx_e+1) % SCCBUFSZ; 1079126177Srik } 1080126177Srik if (c->scctx_empty && len) { 1081126177Srik cte_out2d (c, c->scctx[c->scctx_b]); 1082126177Srik c->scctx_empty = 0; 1083126177Srik } 1084126177Srik return 0; 1085126177Srik} 1086126177Srik 1087126177Srikint scc_read (ct_chan_t *c, unsigned char *d, int len) 1088126177Srik{ 1089126177Srik int i, bytes; 1090126177Srik 1091126177Srik if (c->sccrx_empty) 1092126177Srik bytes = 0; 1093126177Srik else 1094126177Srik bytes = (SCCBUFSZ + c->sccrx_e - 1 - c->sccrx_b) % 1095126177Srik SCCBUFSZ + 1; 1096126177Srik if (len > bytes) 1097126177Srik return -1; 1098126177Srik 1099126177Srik for (i=0; i<len; i++){ 1100126177Srik d[i] = c->sccrx[c->sccrx_b]; 1101126177Srik c->sccrx_b = (c->sccrx_b+1) % SCCBUFSZ; 1102126177Srik } 1103126177Srik if (c->sccrx_b==c->sccrx_e) 1104126177Srik c->sccrx_empty = 1; 1105126177Srik return 0; 1106126177Srik} 1107126177Srik 1108126177Srikint sccrx_check (ct_chan_t *c) 1109126177Srik{ 1110126177Srik int bytes; 1111126177Srik 1112126177Srik if (c->sccrx_empty) 1113126177Srik bytes = 0; 1114126177Srik else 1115126177Srik bytes = (SCCBUFSZ + c->sccrx_e - 1 - c->sccrx_b) % 1116126177Srik SCCBUFSZ + 1; 1117126177Srik return bytes; 1118126177Srik} 1119126177Srik 1120126177Srikint scc_read_byte (ct_chan_t *c) 1121126177Srik{ 1122126177Srik unsigned char a; 1123126177Srik 1124126177Srik if (scc_read (c, &a, 1) < 0) 1125126177Srik return -1; 1126126177Srik return a; 1127126177Srik} 1128126177Srik 1129126177Srikint scc_write_byte (ct_chan_t *c, unsigned char b) 1130126177Srik{ 1131126177Srik if (scc_write (c, &b, 1) < 0) 1132126177Srik return -1; 1133126177Srik return b; 1134126177Srik} 1135126177Srik 1136126177Srik/* 1137126177Srik * Register event processing functions 1138126177Srik */ 1139126177Srikvoid ct_register_transmit (ct_chan_t *c, void (*func) (ct_chan_t*, void*, int)) 1140126177Srik{ 1141126177Srik c->call_on_tx = func; 1142126177Srik} 1143126177Srik 1144126177Srikvoid ct_register_receive (ct_chan_t *c, void (*func) (ct_chan_t*, char*, int)) 1145126177Srik{ 1146126177Srik c->call_on_rx = func; 1147126177Srik} 1148126177Srik 1149126177Srikvoid ct_register_error (ct_chan_t *c, void (*func) (ct_chan_t*, int)) 1150126177Srik{ 1151126177Srik c->call_on_err = func; 1152126177Srik} 1153126177Srik 1154126177Srikvoid ct_register_scc (ct_chan_t *c, void (*func) (ct_chan_t*)) 1155126177Srik{ 1156126177Srik c->call_on_scc = func; 1157126177Srik} 1158126177Srik 1159126177Srikvoid ct_register_modem (ct_chan_t *c, void (*func) (ct_chan_t*)) 1160126177Srik{ 1161126177Srik c->call_on_msig = func; 1162126177Srik} 1163