115177Snate/*- 215284Snate * DDK library for Cronyx-Tau adapters. 315284Snate * 415284Snate * Copyright (C) 1998-1999 Cronyx Engineering. 515284Snate * Author: Alexander Kvitchenko, <aak@cronyx.ru> 615284Snate * 715284Snate * Copyright (C) 1999-2003 Cronyx Engineering. 815284Snate * Author: Roman Kurakin, <rik@cronyx.ru> 915284Snate * 1015284Snate * This source is derived from 1115284Snate * Diagnose utility for Cronyx-Tau adapter: 1215284Snate * by Serge Vakulenko, <vak@cronyx.ru> 1315284Snate * 1415284Snate * This software is distributed with NO WARRANTIES, not even the implied 1515284Snate * warranties for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 1615284Snate * 1715284Snate * Authors grant any other persons or organisations permission to use 1815284Snate * or modify this software as long as this message is kept with the software, 1915284Snate * all derivative works or modified versions. 2015284Snate * 2115284Snate * Cronyx Id: ctddk.c,v 1.1.2.3 2003/11/14 16:55:36 rik Exp $ 2215284Snate */ 2315284Snate#include <sys/cdefs.h> 2415284Snate__FBSDID("$FreeBSD$"); 2510217Sphk 2630171Scharnier#include <dev/cx/machdep.h> 2730171Scharnier#include <dev/ctau/ctddk.h> 2830171Scharnier#include <dev/ctau/ctaureg.h> 2950479Speter#include <dev/ctau/hdc64570.h> 3030171Scharnier#include <dev/ctau/ds2153.h> 3130171Scharnier#include <dev/ctau/am8530.h> 3259656Siwasaki#include <dev/ctau/lxt318.h> 3359656Siwasaki#include <dev/cx/cronyxfw.h> 3459656Siwasaki#include <dev/ctau/ctaufw.h> 3559656Siwasaki#include <dev/ctau/ctau2fw.h> 3659656Siwasaki 3730171Scharnier#ifndef CT_DDK_NO_G703 3810217Sphk#include <dev/ctau/ctaug7fw.h> 3910217Sphk#endif 4010217Sphk 4130171Scharnier#ifndef CT_DDK_NO_E1 4210217Sphk#include <dev/ctau/ctaue1fw.h> 4310217Sphk#endif 4431290Snate 4510217Sphkstatic void ct_hdlc_interrupt (ct_chan_t *c, int imvr); 4610217Sphkstatic void ct_e1_interrupt (ct_board_t *b); 4710217Sphkstatic void ct_scc_interrupt (ct_board_t *b); 4810217Sphkstatic void ct_e1timer_interrupt (ct_chan_t *c); 4959656Siwasaki 5059656Siwasakistatic short porttab [] = { /* standard base port set */ 5159656Siwasaki 0x200, 0x220, 0x240, 0x260, 0x280, 0x2a0, 0x2c0, 0x2e0, 52111507Sgreen 0x300, 0x320, 0x340, 0x360, 0x380, 0x3a0, 0x3c0, 0x3e0, 0 5359656Siwasaki}; 5416487Snate 5516487Snateint ct_find (port_t *board_ports) 5616487Snate{ 5716487Snate int i, n; 5816487Snate 5916487Snate for (i=0, n=0; porttab[i] && n<NBRD; i++) 6090968Sshiba if (ct_probe_board (porttab[i], -1, -1)) 6159053Siwasaki board_ports[n++] = porttab[i]; 6259656Siwasaki return n; 6316487Snate} 6416487Snate 6516487Snateint ct_open_board (ct_board_t *b, int num, port_t port, int irq, int dma) 6616487Snate{ 6710217Sphk ct_chan_t *c; 6816487Snate const unsigned char *fw; 6915177Snate const cr_dat_tst_t *ft; 7015177Snate long flen; 7159656Siwasaki 7259656Siwasaki if (num >= NBRD || ! ct_probe_board (port, irq, dma)) 7359656Siwasaki return 0; 7459656Siwasaki 7559656Siwasaki /* init callback pointers */ 7659656Siwasaki for (c=b->chan; c<b->chan+NCHAN; ++c) { 7715177Snate c->call_on_tx = 0; 7815177Snate c->call_on_rx = 0; 7915177Snate c->call_on_msig = 0; 8015177Snate c->call_on_scc = 0; 8115177Snate c->call_on_err = 0; 8215177Snate } 8315177Snate 8415177Snate /* init DDK channel variables */ 8515177Snate for (c=b->chan; c<b->chan+NCHAN; ++c) { 8615177Snate c->sccrx_empty = c->scctx_empty = 1; 8715177Snate c->sccrx_b = c->sccrx_e = 0; 8815177Snate c->scctx_b = c->scctx_e = 0; 8915177Snate c->e1_first_int = 1; 9015177Snate } 9115177Snate 9215177Snate /* init board structure */ 9315177Snate ct_init (b, num, port, irq, dma, ctau_fw_data, 9459656Siwasaki ctau_fw_len, ctau_fw_tvec, ctau2_fw_data); 9515177Snate 9615177Snate /* determine which firmware should be loaded */ 9715177Snate fw = ctau_fw_data; 9815177Snate flen = ctau_fw_len; 9915177Snate ft = ctau_fw_tvec; 10015177Snate switch (b->type) { 10115177Snate case B_TAU2: 10215177Snate case B_TAU2_G703: 10359656Siwasaki case B_TAU2_E1: 10459656Siwasaki case B_TAU2_E1D: 10515177Snate fw = ctau2_fw_data; 10615177Snate flen = 0; 10710217Sphk ft = 0; 10810217Sphk break; 10910217Sphk#ifndef CT_DDK_NO_G703 11010217Sphk case B_TAU_G703: 11110217Sphk fw = ctaug703_fw_data; 11210217Sphk flen = ctaug703_fw_len; 11310217Sphk ft = ctaug703_fw_tvec; 11415177Snate break; 11515177Snate#endif 11615177Snate#ifndef CT_DDK_NO_E1 11710217Sphk case B_TAU_E1: 11810217Sphk fw = ctaue1_fw_data; 11910217Sphk flen = ctaue1_fw_len; 12010217Sphk ft = ctaue1_fw_tvec; 12115177Snate break; 12210217Sphk#endif 12310217Sphk } 12415177Snate /* Load firmware and set up board */ 12561804Sroberto return ct_setup_board (b, fw, flen, ft); 12615177Snate} 12715177Snate 12810217Sphk/* 12915177Snate * must be called on the exit 13015177Snate */ 13115177Snatevoid ct_close_board (ct_board_t *b) 13215177Snate{ 13315177Snate ct_setup_board (b, 0, 0, 0); 13415177Snate 13515177Snate /* Reset the controller. */ 13615177Snate outb (BCR0(b->port), 0); 13715177Snate 13815177Snate /* Disable DMA channel. */ 13915177Snate ct_disable_dma (b); 14015177Snate 14115177Snate ct_led (b, 0); 14215177Snate} 14315177Snate 14415177Snatestatic void ct_g703_rate (ct_chan_t *c, unsigned long rate) 14590968Sshiba{ 14690968Sshiba c->gopt.rate = rate; 14790968Sshiba ct_setup_g703 (c->board); 14859656Siwasaki} 14959053Siwasaki 15059053Siwasaki/* 15159656Siwasaki * Set up baud rate. 15259656Siwasaki */ 15359656Siwasakistatic void ct_chan_baud (ct_chan_t *c, unsigned long baud) 15459656Siwasaki{ 15510217Sphk c->baud = baud; 15610217Sphk if (baud) { 15715177Snate c->hopt.txs = CLK_INT; 15810217Sphk } else { 15915177Snate ct_set_dpll (c, 0); 16010217Sphk c->hopt.txs = CLK_LINE; 16110217Sphk } 16210217Sphk ct_update_chan (c); 16310217Sphk} 16410217Sphk 16510217Sphkvoid ct_set_baud (ct_chan_t *c, unsigned long baud) 16615177Snate{ 16715177Snate unsigned long r; 16815177Snate 16915177Snate if (c->mode == M_E1) 17015177Snate return; 17110217Sphk if (c->mode == M_G703) { 17215177Snate if (baud >= 2048000) r = 2048; 17310217Sphk else if (baud >= 1024000) r = 1024; 17415177Snate else if (baud >= 512000) r = 512; 17510217Sphk else if (baud >= 256000) r = 256; 17610217Sphk else if (baud >= 128000) r = 128; 17710217Sphk else r = 64; 17810217Sphk ct_g703_rate (c, r); 17915177Snate } else 18010217Sphk ct_chan_baud (c, baud); 18115177Snate} 18210217Sphk 18315177Snate/* 18410217Sphk * Configure Tau/E1 board. 18510217Sphk */ 18615177Snatestatic void ct_e1_config (ct_board_t *b, unsigned char cfg) 18715177Snate{ 18810217Sphk if (cfg == b->opt.cfg) 18910217Sphk return; 19015177Snate 19110217Sphk if (cfg == CFG_B) 19215177Snate b->chan[1].mode = M_HDLC; 19310217Sphk else 19410217Sphk b->chan[1].mode = M_E1; 19515177Snate 19610217Sphk /* Recovering synchronization */ 19710217Sphk if (b->opt.cfg == CFG_B) { 19810217Sphk ct_chan_baud (b->chan+1, 0); 19916487Snate ct_set_invtxc (b->chan+1, 0); 20010217Sphk ct_set_invrxc (b->chan+1, 0); 20110217Sphk ct_set_nrzi (b->chan+1, 0); 20210217Sphk } 20310217Sphk b->opt.cfg = cfg; 20459656Siwasaki ct_setup_e1 (b); 20559656Siwasaki} 20659656Siwasaki 20759656Siwasaki/* 20859656Siwasaki * Config Tau/G.703 board 20959656Siwasaki */ 21059656Siwasakistatic void ct_g703_config (ct_board_t *b, unsigned char cfg) 21188961Simp{ 21288961Simp if (cfg == b->opt.cfg) 21359656Siwasaki return; 21459656Siwasaki 21559656Siwasaki if (cfg == CFG_B) 21659656Siwasaki b->chan[1].mode = M_HDLC; 21759656Siwasaki else 21859656Siwasaki b->chan[1].mode = M_G703; 21959656Siwasaki 22088961Simp /* Recovering synchronization */ 22188961Simp if (b->opt.cfg == CFG_B) { 22259656Siwasaki ct_chan_baud (b->chan+1, 0); 22388961Simp ct_set_invtxc (b->chan+1, 0); 22459656Siwasaki ct_set_invrxc (b->chan+1, 0); 22559656Siwasaki ct_set_nrzi (b->chan+1, 0); 22659656Siwasaki } 22759656Siwasaki b->opt.cfg = cfg; 22859656Siwasaki ct_setup_g703 (b); 22959656Siwasaki} 23059656Siwasaki 23188961Simpint ct_set_clk (ct_chan_t *c, int clk) 23288961Simp{ 23388961Simp if (c->num) 23488961Simp c->board->opt.clk1 = clk; 23559656Siwasaki else 23659656Siwasaki c->board->opt.clk0 = clk; 23759656Siwasaki if (c->mode == M_E1) { 23859656Siwasaki ct_setup_e1 (c->board); 23959656Siwasaki return 0; 24059656Siwasaki } if (c->mode == M_G703) { 24159656Siwasaki ct_setup_g703 (c->board); 24288961Simp return 0; 24388961Simp } else 24410217Sphk return -1; 24559656Siwasaki} 24690968Sshiba 24790968Sshibaint ct_get_clk (ct_chan_t *c) 24890968Sshiba{ 24990968Sshiba return c->num ? c->board->opt.clk1 : c->board->opt.clk0; 25090968Sshiba} 25190968Sshiba 25290968Sshibaint ct_set_ts (ct_chan_t *c, unsigned long ts) 25390968Sshiba{ 25490968Sshiba if (! (c->mode == M_E1)) 25590968Sshiba return -1; 25690968Sshiba if (c->num) 25790968Sshiba c->board->opt.s1 = ts; 25890968Sshiba else 25990968Sshiba c->board->opt.s0 = ts; 26059053Siwasaki ct_setup_e1 (c->board); 26159656Siwasaki return 0; 26259053Siwasaki} 26359053Siwasaki 26459053Siwasakiint ct_set_subchan (ct_board_t *b, unsigned long ts) 26559053Siwasaki{ 26659053Siwasaki if (b->chan[0].mode != M_E1) 26759053Siwasaki return -1; 26859053Siwasaki b->opt.s2 = ts; 26915177Snate ct_setup_e1 (b); 27059656Siwasaki return 0; 27159656Siwasaki} 27259656Siwasaki 27359656Siwasakiint ct_set_higain (ct_chan_t *c, int on) 27459656Siwasaki{ 27559656Siwasaki if (! (c->mode == M_E1)) 27659656Siwasaki return -1; 27759656Siwasaki c->gopt.higain = on ? 1 : 0; 27859656Siwasaki ct_setup_e1 (c->board); 27959656Siwasaki return 0; 28059656Siwasaki} 28159656Siwasaki 28259656Siwasaki/* 28359656Siwasaki * Start service channel. 28459656Siwasaki */ 28559656Siwasakivoid ct_start_scc (ct_chan_t *c, char *rxbuf, char *txbuf) 28659656Siwasaki{ 28759656Siwasaki c->sccrx = rxbuf; 28859656Siwasaki c->scctx = txbuf; 28959656Siwasaki 29010217Sphk /* Enable interrupts from service channel. */ 29159656Siwasaki if (c->board->type != B_TAU_E1 && c->board->type != B_TAU_E1C && 29259656Siwasaki c->board->type != B_TAU2_E1) 29359656Siwasaki return; 29459656Siwasaki 29559656Siwasaki cte_out2 (c->board->port, c->num ? AM_IMR : AM_IMR | AM_A, 29659656Siwasaki IMR_TX | IMR_RX_ALL); 29759656Siwasaki cte_out2 (c->board->port, AM_MICR, MICR_MIE); 29859656Siwasaki} 29959656Siwasaki 30059656Siwasaki/* 30159656Siwasaki * Start HDLC channel. 30259656Siwasaki */ 30359656Siwasakivoid ct_start_chan (ct_chan_t *c, ct_buf_t *cb, unsigned long phys) 30459656Siwasaki{ 30559656Siwasaki int i, ier0; 30659656Siwasaki unsigned long bound; 30759656Siwasaki 30859656Siwasaki if (cb) { 30959656Siwasaki /* Set up descriptors, align to 64k boundary. 31059656Siwasaki * If 64k boundary is inside buffers 31159656Siwasaki * buffers will begin on this boundary 31259656Siwasaki * (there were allocated additional space for this) */ 31359656Siwasaki c->tdesc = cb->descbuf; 31459656Siwasaki c->tdphys[0] = phys + ((char*)c->tdesc - (char*)cb); 31559656Siwasaki bound = ((c->tdphys[0] + 0xffff) & ~(0xffffUL)); 31659656Siwasaki if (bound < c->tdphys[0] + 2*NBUF*sizeof(ct_desc_t)) { 31759656Siwasaki c->tdesc = (ct_desc_t*) ((char*) c->tdesc + 31859656Siwasaki (bound - c->tdphys[0])); 31959656Siwasaki c->tdphys[0] = bound; 32059656Siwasaki } 32159656Siwasaki c->rdesc = c->tdesc + NBUF; 32259656Siwasaki 32359656Siwasaki /* Set buffers. */ 32459656Siwasaki for (i=0; i<NBUF; ++i) { 32559656Siwasaki c->rbuf[i] = cb->rbuffer[i]; 32659656Siwasaki c->tbuf[i] = cb->tbuffer[i]; 32759656Siwasaki } 32859656Siwasaki 32959656Siwasaki /* Set buffer physical addresses */ 33059656Siwasaki for (i=0; i<NBUF; ++i) { 33159656Siwasaki c->rphys[i] = phys + ((char*)c->rbuf[i] - (char*)cb); 33259656Siwasaki c->tphys[i] = phys + ((char*)c->tbuf[i] - (char*)cb); 33359656Siwasaki c->rdphys[i] = phys + ((char*)(c->rdesc+i) - (char*)cb); 33459656Siwasaki c->tdphys[i] = phys + ((char*)(c->tdesc+i) - (char*)cb); 33559656Siwasaki } 33659656Siwasaki } 33759656Siwasaki /* Set up block chains. */ 33859656Siwasaki /* receive buffers */ 33959656Siwasaki for (i=0; i<NBUF; ++i) { 34059656Siwasaki B_NEXT (c->rdesc[i]) = c->rdphys[(i+1) % NBUF] & 0xffff; 34159656Siwasaki B_PTR (c->rdesc[i]) = c->rphys[i]; 34259656Siwasaki B_LEN (c->rdesc[i]) = DMABUFSZ; 34359656Siwasaki B_STATUS (c->rdesc[i]) = 0; 34459656Siwasaki } 34559656Siwasaki /* transmit buffers */ 34659656Siwasaki for (i=0; i<NBUF; ++i) { 34759656Siwasaki B_NEXT (c->tdesc[i]) = c->tdphys[(i+1) % NBUF] & 0xffff; 34859656Siwasaki B_PTR (c->tdesc[i]) = c->tphys[i]; 34959656Siwasaki B_LEN (c->tdesc[i]) = DMABUFSZ; 35059656Siwasaki B_STATUS (c->tdesc[i]) = FST_EOM; 35159656Siwasaki c->attach[i] = 0; 35259656Siwasaki } 35310217Sphk 35410217Sphk if (c->type & T_E1) { 35516487Snate c->mode = M_E1; 35610255Sphk if (c->num && c->board->opt.cfg == CFG_B) 35710217Sphk c->mode = M_HDLC; 35815177Snate } 35910217Sphk if (c->type & T_G703) { 36010217Sphk c->mode = M_G703; 36110217Sphk if (c->num && c->board->opt.cfg == CFG_B) 36210217Sphk c->mode = M_HDLC; 36310217Sphk } 36415177Snate ct_update_chan (c); 36559656Siwasaki 36610217Sphk /* enable receiver */ 36715177Snate c->rn = 0; 36810217Sphk ct_start_receiver (c, 1 , c->rphys[0], DMABUFSZ, c->rdphys[0], 36910217Sphk c->rdphys[NBUF-1]); 37015177Snate outb (c->IE1, inb (c->IE1) | IE1_CDCDE); 37110217Sphk outb (c->IE0, inb (c->IE0) | IE0_RX_INTE); 37215177Snate ier0 = inb (IER0(c->board->port)); 37310217Sphk ier0 |= c->num ? IER0_RX_INTE_1 : IER0_RX_INTE_0; 37410217Sphk outb (IER0(c->board->port), ier0); 37510217Sphk 37616487Snate /* Enable transmitter */ 37710255Sphk c->tn = 0; 37810217Sphk c->te = 0; 37915177Snate ct_start_transmitter (c, 1 , c->tphys[0], DMABUFSZ, c->tdphys[0], 38059656Siwasaki c->tdphys[0]); 38110217Sphk outb (c->TX.DIR, DIR_CHAIN_EOME | DIR_CHAIN_BOFE | DIR_CHAIN_COFE); 38210217Sphk 38310217Sphk /* Clear DTR and RTS */ 38459656Siwasaki ct_set_dtr (c, 0); 38510217Sphk ct_set_rts (c, 0); 38610217Sphk} 38715177Snate 38810217Sphk/* 38959656Siwasaki * Turn receiver on/off 39059656Siwasaki */ 39159656Siwasakivoid ct_enable_receive (ct_chan_t *c, int on) 39259656Siwasaki{ 39359656Siwasaki unsigned char st3, ier0, ier1; 39459656Siwasaki 39559656Siwasaki st3 = inb (c->ST3); 39659656Siwasaki /* enable or disable receiver */ 39759656Siwasaki if (on && ! (st3 & ST3_RX_ENABLED)) { 39859656Siwasaki c->rn = 0; 39959656Siwasaki ct_start_receiver (c, 1 , c->rphys[0], DMABUFSZ, c->rdphys[0], 40059656Siwasaki c->rdphys[NBUF-1]); 40159656Siwasaki /* enable status interrupt */ 40259656Siwasaki outb (c->IE1, inb (c->IE1) | IE1_CDCDE); 40359656Siwasaki outb (c->IE0, inb (c->IE0) | IE0_RX_INTE); 40459656Siwasaki ier0 = inb (IER0(c->board->port)); 40559656Siwasaki ier0 |= c->num ? IER0_RX_INTE_1 : IER0_RX_INTE_0; 40659656Siwasaki outb (IER0(c->board->port), ier0); 40759656Siwasaki ct_set_rts (c, 1); 40859656Siwasaki } else if (! on && (st3 & ST3_RX_ENABLED)) { 40959656Siwasaki ct_set_rts (c, 0); 41059656Siwasaki outb (c->CMD, CMD_RX_DISABLE); 41159656Siwasaki 41259656Siwasaki ier0 = inb (IER0(c->board->port)); 41359656Siwasaki ier0 &= c->num ? ~(IER0_RX_INTE_1 | IER0_RX_RDYE_1) : 41459656Siwasaki ~(IER0_RX_INTE_0 | IER0_RX_RDYE_0); 41559656Siwasaki outb (IER0(c->board->port), ier0); 41659656Siwasaki 41759656Siwasaki ier1 = inb (IER1(c->board->port)); 41859656Siwasaki ier1 &= c->num ? ~(IER1_RX_DMERE_1 | IER1_RX_DME_1) : 41959656Siwasaki ~(IER1_RX_DMERE_0 | IER1_RX_DME_0); 42059656Siwasaki outb (IER1(c->board->port), ier1); 42159656Siwasaki } 42259656Siwasaki 42359656Siwasaki} 42459656Siwasaki 42510217Sphk/* 42610217Sphk * Turn transmitter on/off 42716487Snate */ 42810255Sphkvoid ct_enable_transmit (ct_chan_t *c, int on) 42910217Sphk{ 43015177Snate unsigned char st3, ier0, ier1; 43115177Snate 43215177Snate st3 = inb (c->ST3); 43315177Snate /* enable or disable receiver */ 43410217Sphk if (on && ! (st3 & ST3_TX_ENABLED)) { 43510217Sphk c->tn = 0; 43615177Snate c->te = 0; 43710217Sphk ct_start_transmitter (c, 1 , c->tphys[0], DMABUFSZ, 43810217Sphk c->tdphys[0], c->tdphys[0]); 43910217Sphk outb (c->TX.DIR, 44015177Snate DIR_CHAIN_EOME | DIR_CHAIN_BOFE | DIR_CHAIN_COFE); 44110217Sphk } else if (! on && (st3 & ST3_TX_ENABLED)) { 44259656Siwasaki outb (c->CMD, CMD_TX_DISABLE); 44359656Siwasaki 44459656Siwasaki ier0 = inb (IER0(c->board->port)); 44559656Siwasaki ier0 &= c->num ? ~(IER0_TX_INTE_1 | IER0_TX_RDYE_1) : 44659656Siwasaki ~(IER0_TX_INTE_0 | IER0_TX_RDYE_0); 44759656Siwasaki outb (IER0(c->board->port), ier0); 44810217Sphk 44910217Sphk ier1 = inb (IER1(c->board->port)); 45059656Siwasaki ier1 &= c->num ? ~(IER1_TX_DMERE_1 | IER1_TX_DME_1) : 45159656Siwasaki ~(IER1_TX_DMERE_0 | IER1_TX_DME_0); 45215177Snate outb (IER1(c->board->port), ier1); 45310217Sphk } 45410217Sphk 45510217Sphk} 45610217Sphk 45710217Sphkint ct_set_config (ct_board_t *b, int cfg) 45815177Snate{ 45915177Snate if (b->opt.cfg == cfg) 46015177Snate return 0; 46110217Sphk switch (b->type) { 46210217Sphk case B_TAU_G703: 46310217Sphk case B_TAU_G703C: 46410217Sphk case B_TAU2_G703: 46510217Sphk if (cfg == CFG_C) 46610217Sphk return -1; 46710217Sphk ct_g703_config (b, cfg); 46810217Sphk return 0; 46915177Snate case B_TAU_E1: 47015177Snate case B_TAU_E1C: 47110217Sphk case B_TAU_E1D: 47210217Sphk case B_TAU2_E1: 47315177Snate case B_TAU2_E1D: 47410217Sphk ct_e1_config (b, cfg); 47559656Siwasaki return 0; 47615177Snate default: 47759656Siwasaki return cfg == CFG_A ? 0 : -1; 47859656Siwasaki } 47959656Siwasaki} 48010217Sphk 48110217Sphkint ct_get_dpll (ct_chan_t *c) 48215177Snate{ 48310217Sphk return (c->hopt.rxs == CLK_RXS_DPLL_INT); 48459656Siwasaki} 48559656Siwasaki 48610217Sphkvoid ct_set_dpll (ct_chan_t *c, int on) 48710217Sphk{ 48859656Siwasaki if (on && ct_get_baud (c)) 48959656Siwasaki c->hopt.rxs = CLK_RXS_DPLL_INT; 49059656Siwasaki else 49110217Sphk c->hopt.rxs = CLK_LINE; 49210217Sphk ct_update_chan (c); 49315177Snate} 49415177Snate 49510217Sphkint ct_get_nrzi (ct_chan_t *c) 49610217Sphk{ 49710217Sphk return (c->opt.md2.encod == MD2_ENCOD_NRZI); 49815177Snate} 49959656Siwasaki 50010217Sphk/* 50110217Sphk * Change line encoding to NRZI, default is NRZ 50215177Snate */ 50315177Snatevoid ct_set_nrzi (ct_chan_t *c, int on) 50476343Sdmlb{ 50510217Sphk c->opt.md2.encod = on ? MD2_ENCOD_NRZI : MD2_ENCOD_NRZ; 50676343Sdmlb outb (c->MD2, *(unsigned char*)&c->opt.md2); 50710217Sphk} 50810217Sphk 50959656Siwasaki/* 51010217Sphk * Transmit clock inversion 51176343Sdmlb */ 51210217Sphkvoid ct_set_invtxc (ct_chan_t *c, int on) 51310217Sphk{ 51459656Siwasaki if (on) c->board->bcr2 |= (c->num ? BCR2_INVTXC1 : BCR2_INVTXC0); 51559656Siwasaki else c->board->bcr2 &= ~(c->num ? BCR2_INVTXC1 : BCR2_INVTXC0); 51610217Sphk outb (BCR2(c->board->port), c->board->bcr2); 51776343Sdmlb} 51859656Siwasaki 51959656Siwasakiint ct_get_invtxc (ct_chan_t *c) 52059656Siwasaki{ 52110217Sphk return (c->board->bcr2 & (c->num ? BCR2_INVTXC1 : BCR2_INVTXC0)) != 0; 52210217Sphk} 52310217Sphk 52415177Snate/* 52510217Sphk * Receive clock inversion 52659656Siwasaki */ 52759656Siwasakivoid ct_set_invrxc (ct_chan_t *c, int on) 52859656Siwasaki{ 52910217Sphk if (on) c->board->bcr2 |= (c->num ? BCR2_INVRXC1 : BCR2_INVRXC0); 53059656Siwasaki else c->board->bcr2 &= ~(c->num ? BCR2_INVRXC1 : BCR2_INVRXC0); 53159656Siwasaki outb (BCR2(c->board->port), c->board->bcr2); 53259656Siwasaki} 53315177Snate 53459656Siwasakiint ct_get_invrxc (ct_chan_t *c) 53559656Siwasaki{ 53610217Sphk return (c->board->bcr2 & (c->num ? BCR2_INVRXC1 : BCR2_INVRXC0)) != 0; 53715177Snate} 53810217Sphk 53959656Siwasaki/* 54015177Snate * Main interrupt handler 54159656Siwasaki */ 54210217Sphkvoid ct_int_handler (ct_board_t *b) 54310217Sphk{ 54415177Snate unsigned char bsr0, imvr; 54510217Sphk ct_chan_t *c; 54615177Snate 54710217Sphk while ((bsr0 = inb (BSR0(b->port))) & BSR0_INTR) { 54810217Sphk if (bsr0 & BSR0_RDYERR) { 54910217Sphk outb (BCR1(b->port), b->bcr1); 55010217Sphk } else if (bsr0 & BSR0_GINT) { 55110217Sphk if (b->type == B_TAU_E1 || b->type == B_TAU_E1C || 55210217Sphk b->type == B_TAU_E1D || b->type == B_TAU2_E1 || 55310217Sphk b->type == B_TAU2_E1D) 55410217Sphk ct_e1_interrupt (b); 55510217Sphk } else if (bsr0 & BSR0_HDINT) { 55610217Sphk /* Read the interrupt modified vector register. */ 55710217Sphk imvr = inb (IACK(b->port)); 55810217Sphk c = b->chan + (imvr & IMVR_CHAN1 ? 1 : 0); 55910217Sphk ct_hdlc_interrupt (c, imvr); 56010217Sphk } 56110217Sphk } 56210217Sphk} 56310217Sphk 56410217Sphkstatic void ct_e1_interrupt (ct_board_t *b) 56516487Snate{ 56610217Sphk unsigned char sr; 56710217Sphk 56815177Snate sr = inb (E1SR(b->port)); 56915177Snate 57015177Snate if (sr & E1SR_SCC_IRQ) ct_scc_interrupt (b); 57115177Snate if (sr & E1SR_E0_IRQ1) ct_e1timer_interrupt (b->chan + 0); 57210217Sphk if (sr & E1SR_E1_IRQ1) ct_e1timer_interrupt (b->chan + 1); 57310217Sphk} 57415177Snate 57515177Snatestatic void ct_scc_interrupt (ct_board_t *b) 57615177Snate{ 57715177Snate unsigned char rsr; 57810217Sphk unsigned char ivr, a = AM_A; /* assume channel A */ 57910217Sphk ct_chan_t *c = b->chan; 58015177Snate 58110217Sphk ivr = cte_in2 (b->port, AM_IVR); 58210217Sphk if (! (ivr & IVR_A)) 58315177Snate ++c, a = 0; /* really channel B */ 58415177Snate 58559656Siwasaki switch (ivr & IVR_REASON) { 58610217Sphk case IVR_TXRDY: /* transmitter empty */ 58759656Siwasaki c->scctx_b = (c->scctx_b + 1) % SCCBUFSZ; 58815177Snate if (c->scctx_b == c->scctx_e) { 58910217Sphk c->scctx_empty = 1; 59015177Snate cte_out2c (c, AM_CR | CR_RST_TXINT); 59115177Snate } else 59210217Sphk cte_out2d (c, c->scctx[c->scctx_b]); 59310217Sphk break; 59410217Sphk 59510217Sphk case IVR_RXERR: /* receive error */ 59635310Snate case IVR_RX: /* receive character available */ 59735310Snate rsr = cte_in2 (b->port, a|AM_RSR); 59815177Snate 59915177Snate if (rsr & RSR_RXOVRN) { /* rx overrun */ 60015177Snate if (c->call_on_err) 60115177Snate c->call_on_err (c, CT_SCC_OVERRUN); 60215177Snate } else if (rsr & RSR_FRME) { /* frame error */ 60315177Snate if (c->call_on_err) 60415177Snate c->call_on_err (c, CT_SCC_FRAME); 60515177Snate } else { 60610217Sphk c->sccrx[c->sccrx_e] = cte_in2d (c); 60759656Siwasaki c->sccrx_e = (c->sccrx_e + 1) % SCCBUFSZ; 60815177Snate c->sccrx_empty &= 0; 60910217Sphk if (c->call_on_scc) 61015177Snate c->call_on_scc (c); 61115177Snate if (c->sccrx_e == c->sccrx_b && ! c->sccrx_empty) 61215177Snate if (c->call_on_err) 61310217Sphk c->call_on_err (c, CT_SCC_OVERFLOW); 61415177Snate } 61510217Sphk if (rsr) 61610217Sphk cte_out2c (c, CR_RST_ERROR); 61710217Sphk break; 61816487Snate 61910217Sphk case IVR_STATUS: /* external status interrupt */ 62010217Sphk /* Unexpected SCC status interrupt. */ 62115177Snate cte_out2c (c, CR_RST_EXTINT); 62215177Snate break; 62315177Snate } 62415177Snate} 62515177Snate 62659656Siwasaki/* 62759656Siwasaki * G.703 mode channel: process 1-second timer interrupts. 62859656Siwasaki * Read error and request registers, and fill the status field. 62959656Siwasaki */ 63010217Sphkvoid ct_g703_timer (ct_chan_t *c) 63115177Snate{ 63210217Sphk int bpv, cd, tsterr, tstreq; 63310217Sphk 63415177Snate /* Count seconds. 63510217Sphk * During the first second after the channel startup 63610217Sphk * the status registers are not stable yet, 63710217Sphk * we will so skip the first second. */ 63810217Sphk ++c->cursec; 63910217Sphk if (c->mode != M_G703) 64015177Snate return; 64115177Snate if (c->totsec + c->cursec <= 1) 64230171Scharnier return; 64310217Sphk c->status = 0; 64415177Snate 64510217Sphk cd = ct_get_cd (c); 64610217Sphk 64710217Sphk bpv = inb (GERR (c->board->port)) & (c->num ? GERR_BPV1 : GERR_BPV0); 64810217Sphk outb (GERR (c->board->port), bpv); 64910217Sphk 65059656Siwasaki tsterr = inb (GERR (c->board->port)) & (c->num ? GERR_ERR1 : GERR_ERR0); 65159656Siwasaki outb (GERR (c->board->port), tsterr); 65259656Siwasaki 65359656Siwasaki tstreq = inb (GLDR (c->board->port)) & 65459656Siwasaki (c->num ? GLDR_LREQ1 : GLDR_LREQ0); 65559656Siwasaki outb (GLDR (c->board->port), tstreq); 65659656Siwasaki 65759656Siwasaki /* Compute the SNMP-compatible channel status. */ 65859656Siwasaki if (bpv) 65959656Siwasaki ++c->currnt.bpv; /* bipolar violation */ 66015177Snate if (! cd) 66110217Sphk c->status |= ESTS_LOS; /* loss of signal */ 66210217Sphk if (tsterr) 66321371Snate c->status |= ESTS_TSTERR; /* test error */ 66410217Sphk if (tstreq) 66515177Snate c->status |= ESTS_TSTREQ; /* test code detected */ 66610217Sphk 66710217Sphk if (! c->status) 66815177Snate c->status = ESTS_NOALARM; 66915177Snate 67010217Sphk /* Unavaiable second -- loss of carrier, or receiving test code. */ 67110217Sphk if ((! cd) || tstreq) 67215177Snate /* Unavailable second -- no other counters. */ 67330171Scharnier ++c->currnt.uas; 67410217Sphk else { 67510217Sphk /* Line errored second -- any BPV. */ 67615177Snate if (bpv) 67715177Snate ++c->currnt.les; 67815177Snate 67915177Snate /* Collect data for computing 68015177Snate * degraded minutes. */ 68115177Snate ++c->degsec; 68210217Sphk if (cd && bpv) 68359656Siwasaki ++c->degerr; 68459656Siwasaki } 68559656Siwasaki 68659656Siwasaki /* Degraded minutes -- having more than 50% error intervals. */ 68759656Siwasaki if (c->cursec / 60 == 0) { 68859656Siwasaki if (c->degerr*2 > c->degsec) 68959656Siwasaki ++c->currnt.dm; 69059656Siwasaki c->degsec = 0; 69159656Siwasaki c->degerr = 0; 69259656Siwasaki } 69359656Siwasaki 69459656Siwasaki /* Rotate statistics every 15 minutes. */ 695112233Simp if (c->cursec > 15*60) { 69610217Sphk int i; 69710217Sphk 69815177Snate for (i=47; i>0; --i) 69959656Siwasaki c->interval[i] = c->interval[i-1]; 70010217Sphk c->interval[0] = c->currnt; 70110217Sphk 70210217Sphk /* Accumulate total statistics. */ 70310217Sphk c->total.bpv += c->currnt.bpv; 70415177Snate c->total.fse += c->currnt.fse; 70515177Snate c->total.crce += c->currnt.crce; 70610217Sphk c->total.rcrce += c->currnt.rcrce; 70715177Snate c->total.uas += c->currnt.uas; 70810217Sphk c->total.les += c->currnt.les; 70910217Sphk c->total.es += c->currnt.es; 71010217Sphk c->total.bes += c->currnt.bes; 71116487Snate c->total.ses += c->currnt.ses; 71210217Sphk c->total.oofs += c->currnt.oofs; 71310217Sphk c->total.css += c->currnt.css; 71415177Snate c->total.dm += c->currnt.dm; 71510217Sphk memset (&c->currnt, 0, sizeof (c->currnt)); 71610217Sphk 71710217Sphk c->totsec += c->cursec; 71810217Sphk c->cursec = 0; 71915177Snate } 72010217Sphk} 72110217Sphk 72210217Sphkstatic void ct_e1timer_interrupt (ct_chan_t *c) 72310217Sphk{ 72410217Sphk unsigned short port; 72515177Snate unsigned char sr1, sr2, ssr; 72615177Snate unsigned long bpv, fas, crc4, ebit, pcv, oof; 72710217Sphk 72815177Snate port = c->num ? E1CS1(c->board->port) : E1CS0(c->board->port); 72910217Sphk 73010217Sphk sr2 = cte_ins (port, DS_SR2, 0xff); 73110217Sphk /* is it timer interrupt ? */ 73210217Sphk if (! (sr2 & SR2_SEC)) 73316487Snate return; 73410217Sphk 73510217Sphk /* first interrupts should be ignored */ 73615177Snate if (c->e1_first_int > 0) { 73710217Sphk c->e1_first_int --; 73810217Sphk return; 73910217Sphk } 74010217Sphk 74115177Snate ++c->cursec; 74210217Sphk c->status = 0; 74315177Snate 74410217Sphk /* Compute the SNMP-compatible channel status. */ 74510217Sphk sr1 = cte_ins (port, DS_SR1, 0xff); 74610217Sphk ssr = cte_in (port, DS_SSR); 74715177Snate oof = 0; 74815177Snate 749111507Sgreen if (sr1 & (SR1_RCL | SR1_RLOS)) 750111507Sgreen c->status |= ESTS_LOS; /* loss of signal */ 751111507Sgreen if (sr1 & SR1_RUA1) 75215177Snate c->status |= ESTS_AIS; /* receiving all ones */ 75315177Snate if (c->gopt.cas && (sr1 & SR1_RSA1)) 75415177Snate c->status |= ESTS_AIS16; /* signaling all ones */ 75515177Snate if (c->gopt.cas && (sr1 & SR1_RDMA)) 75615177Snate c->status |= ESTS_FARLOMF; /* alarm in timeslot 16 */ 75715177Snate if (sr1 & SR1_RRA) 75815177Snate c->status |= ESTS_FARLOF; /* far loss of framing */ 75915177Snate 76010217Sphk /* Controlled slip second -- any slip event. */ 76110217Sphk if (sr1 & SR1_RSLIP) { 76210217Sphk ++c->currnt.css; 76315177Snate } 76415177Snate 76510217Sphk if (ssr & SSR_SYNC) { 76615177Snate c->status |= ESTS_LOF; /* loss of framing */ 76710217Sphk ++oof; /* out of framing */ 76810217Sphk } 76910217Sphk if ((c->gopt.cas && (ssr & SSR_SYNC_CAS)) || 77016487Snate (c->gopt.crc4 && (ssr & SSR_SYNC_CRC4))) { 77110217Sphk c->status |= ESTS_LOMF; /* loss of multiframing */ 77210217Sphk ++oof; /* out of framing */ 77315177Snate } 77410217Sphk 77510217Sphk if (! c->status) 77610217Sphk c->status = ESTS_NOALARM; 77715177Snate 77815177Snate /* Get error counters. */ 77910217Sphk bpv = VCR (cte_in (port, DS_VCR1), cte_in (port, DS_VCR2)); 78015177Snate fas = FASCR (cte_in (port, DS_FASCR1), cte_in (port, DS_FASCR2)); 78116487Snate crc4 = CRCCR (cte_in (port, DS_CRCCR1), cte_in (port, DS_CRCCR2)); 78210217Sphk ebit = EBCR (cte_in (port, DS_EBCR1), cte_in (port, DS_EBCR2)); 78310217Sphk 78415177Snate c->currnt.bpv += bpv; 78510217Sphk c->currnt.fse += fas; 78610217Sphk if (c->gopt.crc4) { 78710217Sphk c->currnt.crce += crc4; 78815177Snate c->currnt.rcrce += ebit; 78915177Snate } 79010217Sphk 791 /* Path code violation is frame sync error if CRC4 disabled, 792 * or CRC error if CRC4 enabled. */ 793 pcv = fas; 794 if (c->gopt.crc4) 795 pcv += crc4; 796 797 /* Unavaiable second -- receiving all ones, or 798 * loss of carrier, or loss of signal. */ 799 if (sr1 & (SR1_RUA1 | SR1_RCL | SR1_RLOS)) 800 /* Unavailable second -- no other counters. */ 801 ++c->currnt.uas; 802 else { 803 /* Line errored second -- any BPV. */ 804 if (bpv) 805 ++c->currnt.les; 806 807 /* Errored second -- any PCV, or out of frame sync, 808 * or any slip events. */ 809 if (pcv || oof || (sr1 & SR1_RSLIP)) 810 ++c->currnt.es; 811 812 /* Severely errored framing second -- out of frame sync. */ 813 if (oof) 814 ++c->currnt.oofs; 815 816 /* Severely errored seconds -- 817 * 832 or more PCVs, or 2048 or more BPVs. */ 818 if (bpv >= 2048 || pcv >= 832) 819 ++c->currnt.ses; 820 else { 821 /* Bursty errored seconds -- 822 * no SES and more than 1 PCV. */ 823 if (pcv > 1) 824 ++c->currnt.bes; 825 826 /* Collect data for computing 827 * degraded minutes. */ 828 ++c->degsec; 829 c->degerr += bpv + pcv; 830 } 831 } 832 833 /* Degraded minutes -- having error rate more than 10e-6, 834 * not counting unavailable and severely errored seconds. */ 835 if (c->cursec / 60 == 0) { 836 if (c->degerr > c->degsec * 2048 / 1000) 837 ++c->currnt.dm; 838 c->degsec = 0; 839 c->degerr = 0; 840 } 841 842 /* Rotate statistics every 15 minutes. */ 843 if (c->cursec > 15*60) { 844 int i; 845 846 for (i=47; i>0; --i) 847 c->interval[i] = c->interval[i-1]; 848 c->interval[0] = c->currnt; 849 850 /* Accumulate total statistics. */ 851 c->total.bpv += c->currnt.bpv; 852 c->total.fse += c->currnt.fse; 853 c->total.crce += c->currnt.crce; 854 c->total.rcrce += c->currnt.rcrce; 855 c->total.uas += c->currnt.uas; 856 c->total.les += c->currnt.les; 857 c->total.es += c->currnt.es; 858 c->total.bes += c->currnt.bes; 859 c->total.ses += c->currnt.ses; 860 c->total.oofs += c->currnt.oofs; 861 c->total.css += c->currnt.css; 862 c->total.dm += c->currnt.dm; 863 for (i=0; i<sizeof (c->currnt); ++i) 864 *(((char *)(&c->currnt))+i)=0; 865 866 c->totsec += c->cursec; 867 c->cursec = 0; 868 } 869} 870 871static void ct_hdlc_interrupt (ct_chan_t *c, int imvr) 872{ 873 int i, dsr, st1, st2, cda; 874 875 switch (imvr & IMVR_VECT_MASK) { 876 case IMVR_RX_DMOK: /* receive DMA normal end */ 877 dsr = inb (c->RX.DSR); 878 cda = inw (c->RX.CDA); 879 for (i=0; i<NBUF; ++i) 880 if (cda == (unsigned short) c->rdphys[i]) 881 break; 882 if (i >= NBUF) 883 i = c->rn; /* cannot happen */ 884 while (c->rn != i) { 885 int cst = B_STATUS (c->rdesc[c->rn]); 886 if (cst == FST_EOM) { 887 /* process data */ 888 if (c->call_on_rx) 889 c->call_on_rx (c, c->rbuf[c->rn], 890 B_LEN(c->rdesc[c->rn])); 891 ++c->ipkts; 892 c->ibytes += B_LEN(c->rdesc[c->rn]); 893 } else if (cst & ST2_OVRN) { 894 /* Receive overrun error */ 895 if (c->call_on_err) 896 c->call_on_err (c, CT_OVERRUN); 897 ++c->ierrs; 898 } else if (cst & (ST2_HDLC_RBIT | 899 ST2_HDLC_ABT | ST2_HDLC_SHRT)) { 900 /* Receive frame error */ 901 if (c->call_on_err) 902 c->call_on_err (c, CT_FRAME); 903 ++c->ierrs; 904 } else if ((cst & ST2_HDLC_EOM) 905 && (cst & ST2_HDLC_CRCE)) { 906 /* Receive CRC error */ 907 if (c->call_on_err) 908 c->call_on_err (c, CT_CRC); 909 ++c->ierrs; 910 } else if (! (cst & ST2_HDLC_EOM)) { 911 /* Frame dose not fit in the buffer.*/ 912 if (c->call_on_err) 913 c->call_on_err (c, CT_OVERFLOW); 914 ++c->ierrs; 915 } 916 917 B_NEXT (c->rdesc[c->rn]) = 918 c->rdphys[(c->rn+1) % NBUF] & 0xffff; 919 B_PTR (c->rdesc[c->rn]) = c->rphys[c->rn]; 920 B_LEN (c->rdesc[c->rn]) = DMABUFSZ; 921 B_STATUS (c->rdesc[c->rn]) = 0; 922 c->rn = (c->rn + 1) % NBUF; 923 } 924 outw (c->RX.EDA, (unsigned short) c->rdphys[(i+NBUF-1)%NBUF]); 925 /* Clear DMA interrupt. */ 926 if (inb (c->RX.DSR) & DSR_DMA_ENABLE) { 927 outb (c->RX.DSR, dsr); 928 } else { 929 outb (c->RX.DSR, (dsr & 0xfc) | DSR_DMA_ENABLE); 930 } 931 ++c->rintr; 932 break; 933 934 case IMVR_RX_INT: /* receive status */ 935 st1 = inb (c->ST1); 936 st2 = inb (c->ST2); 937 if (st1 & ST1_CDCD){ 938 if (c->call_on_msig) 939 c->call_on_msig (c); 940 ++c->mintr; 941 } 942 /* Clear interrupt. */ 943 outb (c->ST1, st1); 944 outb (c->ST2, st2); 945 ++c->rintr; 946 break; 947 948 case IMVR_RX_DMERR: /* receive DMA error */ 949 dsr = inb (c->RX.DSR); 950 if (dsr & (DSR_CHAIN_BOF | DSR_CHAIN_COF)) { 951 if (c->call_on_err) 952 c->call_on_err (c, CT_OVERFLOW); 953 ++c->ierrs; 954 for (i=0; i<NBUF; ++i) { 955 B_LEN (c->rdesc[i]) = DMABUFSZ; 956 B_STATUS (c->rdesc[i]) = 0; 957 } 958 ct_start_receiver (c, 1, c->rphys[0], DMABUFSZ, 959 c->rdphys[0], c->rdphys[NBUF-1]); 960 c->rn = 0; 961 } 962 /* Clear DMA interrupt. */ 963 outb (c->RX.DSR, dsr); 964 ++c->rintr; 965 break; 966 967 case IMVR_TX_DMOK: /* transmit DMA normal end */ 968 case IMVR_TX_DMERR: /* transmit DMA error */ 969 dsr = inb (c->TX.DSR); 970 cda = inw (c->TX.CDA); 971 972 for (i=0; i<NBUF && cda != (unsigned short)c->tdphys[i]; ++i) 973 continue; 974 if (i >= NBUF) 975 i = 1; /* cannot happen */ 976 if (dsr & DSR_CHAIN_COF) { 977 if (c->call_on_err) 978 c->call_on_err (c, CT_UNDERRUN); 979 ++c->oerrs; 980 } 981 while (c->tn != i) { 982 if (c->call_on_tx) 983 c->call_on_tx (c, c->attach[c->tn], 984 B_LEN(c->tdesc[c->tn])); 985 ++c->opkts; 986 c->obytes += B_LEN(c->tdesc[c->tn]); 987 988 c->tn = (c->tn + 1) % NBUF; 989 /* Clear DMA interrupt. */ 990 outb (c->TX.DSR, DSR_CHAIN_EOM | DSR_DMA_CONTINUE); 991 } 992 outb (c->TX.DSR, dsr & ~DSR_CHAIN_EOM); 993 ++c->tintr; 994 break; 995 996 case IMVR_TX_INT: /* transmit error, HDLC only */ 997 st1 = inb (c->ST1); 998 if (st1 & ST1_HDLC_UDRN) { 999 if (c->call_on_err) 1000 c->call_on_err (c, CT_UNDERRUN); 1001 ++c->oerrs; 1002 } 1003 outb (c->ST1, st1); 1004 ++c->tintr; 1005 break; 1006 1007 default: 1008 /* Unknown interrupt - cannot happen. */ 1009 break; 1010 } 1011} 1012 1013int ct_receive_enabled (ct_chan_t *c) 1014{ 1015 int st3; 1016 1017 st3 = inb (c->ST3); 1018 return (st3 & ST3_RX_ENABLED) ? 1 : 0; 1019} 1020 1021int ct_transmit_enabled (ct_chan_t *c) 1022{ 1023 int st3; 1024 1025 st3 = inb (c->ST3); 1026 return (st3 & ST3_TX_ENABLED) ? 1 : 0; 1027} 1028 1029int ct_buf_free (ct_chan_t *c) 1030{ 1031 return (NBUF + c->tn - c->te - 1) % NBUF; 1032} 1033 1034int ct_send_packet (ct_chan_t *c, unsigned char *data, int len, 1035 void *attachment) 1036{ 1037 int dsr, ne; 1038 1039 if (len > DMABUFSZ) 1040 return -2; 1041 1042 /* Is it really free? */ 1043 ne = (c->te+1) % NBUF; 1044 if (ne == c->tn) 1045 return -1; 1046 1047 /* Set up the tx descriptor. */ 1048 B_LEN (c->tdesc[c->te]) = len; 1049 B_STATUS (c->tdesc[c->te]) = FST_EOM; 1050 c->attach[c->te] = attachment; 1051 if (c->tbuf[c->te] != data) 1052 memcpy (c->tbuf[c->te], data, len); 1053 1054 /* Start the transmitter. */ 1055 c->te = ne; 1056 outw (c->TX.EDA, (unsigned short) c->tdphys[ne]); 1057 dsr = inb (c->TX.DSR); 1058 if (! (dsr & DSR_DMA_ENABLE)) 1059 outb (c->TX.DSR, DSR_DMA_ENABLE); 1060 return 0; 1061} 1062 1063int scc_write (ct_chan_t *c, unsigned char *d, int len) 1064{ 1065 int i, free; 1066 1067 /* determining free place in buffer */ 1068 if (c->scctx_empty) 1069 free = SCCBUFSZ; 1070 else 1071 free = (SCCBUFSZ + c->scctx_b - c->scctx_e) % SCCBUFSZ; 1072 1073 if (len > free) 1074 return -1; 1075 1076 for (i=0; i<len; i++){ 1077 c->scctx[c->scctx_e] = d[i]; 1078 c->scctx_e = (c->scctx_e+1) % SCCBUFSZ; 1079 } 1080 if (c->scctx_empty && len) { 1081 cte_out2d (c, c->scctx[c->scctx_b]); 1082 c->scctx_empty = 0; 1083 } 1084 return 0; 1085} 1086 1087int scc_read (ct_chan_t *c, unsigned char *d, int len) 1088{ 1089 int i, bytes; 1090 1091 if (c->sccrx_empty) 1092 bytes = 0; 1093 else 1094 bytes = (SCCBUFSZ + c->sccrx_e - 1 - c->sccrx_b) % 1095 SCCBUFSZ + 1; 1096 if (len > bytes) 1097 return -1; 1098 1099 for (i=0; i<len; i++){ 1100 d[i] = c->sccrx[c->sccrx_b]; 1101 c->sccrx_b = (c->sccrx_b+1) % SCCBUFSZ; 1102 } 1103 if (c->sccrx_b==c->sccrx_e) 1104 c->sccrx_empty = 1; 1105 return 0; 1106} 1107 1108int sccrx_check (ct_chan_t *c) 1109{ 1110 int bytes; 1111 1112 if (c->sccrx_empty) 1113 bytes = 0; 1114 else 1115 bytes = (SCCBUFSZ + c->sccrx_e - 1 - c->sccrx_b) % 1116 SCCBUFSZ + 1; 1117 return bytes; 1118} 1119 1120int scc_read_byte (ct_chan_t *c) 1121{ 1122 unsigned char a; 1123 1124 if (scc_read (c, &a, 1) < 0) 1125 return -1; 1126 return a; 1127} 1128 1129int scc_write_byte (ct_chan_t *c, unsigned char b) 1130{ 1131 if (scc_write (c, &b, 1) < 0) 1132 return -1; 1133 return b; 1134} 1135 1136/* 1137 * Register event processing functions 1138 */ 1139void ct_register_transmit (ct_chan_t *c, void (*func) (ct_chan_t*, void*, int)) 1140{ 1141 c->call_on_tx = func; 1142} 1143 1144void ct_register_receive (ct_chan_t *c, void (*func) (ct_chan_t*, char*, int)) 1145{ 1146 c->call_on_rx = func; 1147} 1148 1149void ct_register_error (ct_chan_t *c, void (*func) (ct_chan_t*, int)) 1150{ 1151 c->call_on_err = func; 1152} 1153 1154void ct_register_scc (ct_chan_t *c, void (*func) (ct_chan_t*)) 1155{ 1156 c->call_on_scc = func; 1157} 1158 1159void ct_register_modem (ct_chan_t *c, void (*func) (ct_chan_t*)) 1160{ 1161 c->call_on_msig = func; 1162} 1163