📄 netjet.c
字号:
/* $Id: netjet.c,v 1.29.2.4 2004/02/11 13:21:34 keil Exp $ * * low level stuff for Traverse Technologie NETJet ISDN cards * * Author Karsten Keil * Copyright by Karsten Keil <keil@isdn4linux.de> * * This software may be used and distributed according to the terms * of the GNU General Public License, incorporated herein by reference. * * Thanks to Traverse Technologies Australia for documents and information * * 16-Apr-2002 - led code added - Guy Ellis (guy@traverse.com.au) * */#include <linux/init.h>#include "hisax.h"#include "isac.h"#include "hscx.h"#include "isdnl1.h"#include <linux/interrupt.h>#include <linux/ppp_defs.h>#include <asm/io.h>#include "netjet.h"/* Interface functions */u_charNETjet_ReadIC(struct IsdnCardState *cs, u_char offset){ u_char ret; cs->hw.njet.auxd &= 0xfc; cs->hw.njet.auxd |= (offset>>4) & 3; byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); ret = bytein(cs->hw.njet.isac + ((offset & 0xf)<<2)); return(ret);}voidNETjet_WriteIC(struct IsdnCardState *cs, u_char offset, u_char value){ cs->hw.njet.auxd &= 0xfc; cs->hw.njet.auxd |= (offset>>4) & 3; byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); byteout(cs->hw.njet.isac + ((offset & 0xf)<<2), value);}voidNETjet_ReadICfifo(struct IsdnCardState *cs, u_char *data, int size){ cs->hw.njet.auxd &= 0xfc; byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); insb(cs->hw.njet.isac, data, size);}void NETjet_WriteICfifo(struct IsdnCardState *cs, u_char *data, int size){ cs->hw.njet.auxd &= 0xfc; byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); outsb(cs->hw.njet.isac, data, size);}static void fill_mem(struct BCState *bcs, u_int *pos, u_int cnt, int chan, u_char fill){ u_int mask=0x000000ff, val = 0, *p=pos; u_int i; val |= fill; if (chan) { val <<= 8; mask <<= 8; } mask ^= 0xffffffff; for (i=0; i<cnt; i++) { *p &= mask; *p++ |= val; if (p > bcs->hw.tiger.s_end) p = bcs->hw.tiger.send; }}static voidmode_tiger(struct BCState *bcs, int mode, int bc){ struct IsdnCardState *cs = bcs->cs; u_char led; if (cs->debug & L1_DEB_HSCX) debugl1(cs, "Tiger mode %d bchan %d/%d", mode, bc, bcs->channel); bcs->mode = mode; bcs->channel = bc; switch (mode) { case (L1_MODE_NULL): fill_mem(bcs, bcs->hw.tiger.send, NETJET_DMA_TXSIZE, bc, 0xff); if (cs->debug & L1_DEB_HSCX) debugl1(cs, "Tiger stat rec %d/%d send %d", bcs->hw.tiger.r_tot, bcs->hw.tiger.r_err, bcs->hw.tiger.s_tot); if ((cs->bcs[0].mode == L1_MODE_NULL) && (cs->bcs[1].mode == L1_MODE_NULL)) { cs->hw.njet.dmactrl = 0; byteout(cs->hw.njet.base + NETJET_DMACTRL, cs->hw.njet.dmactrl); byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0); } if (cs->typ == ISDN_CTYPE_NETJET_S) { // led off led = bc & 0x01; led = 0x01 << (6 + led); // convert to mask led = ~led; cs->hw.njet.auxd &= led; byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); } break; case (L1_MODE_TRANS): break; case (L1_MODE_HDLC_56K): case (L1_MODE_HDLC): fill_mem(bcs, bcs->hw.tiger.send, NETJET_DMA_TXSIZE, bc, 0xff); bcs->hw.tiger.r_state = HDLC_ZERO_SEARCH; bcs->hw.tiger.r_tot = 0; bcs->hw.tiger.r_bitcnt = 0; bcs->hw.tiger.r_one = 0; bcs->hw.tiger.r_err = 0; bcs->hw.tiger.s_tot = 0; if (! cs->hw.njet.dmactrl) { fill_mem(bcs, bcs->hw.tiger.send, NETJET_DMA_TXSIZE, !bc, 0xff); cs->hw.njet.dmactrl = 1; byteout(cs->hw.njet.base + NETJET_DMACTRL, cs->hw.njet.dmactrl); byteout(cs->hw.njet.base + NETJET_IRQMASK0, 0x0f); /* was 0x3f now 0x0f for TJ300 and TJ320 GE 13/07/00 */ } bcs->hw.tiger.sendp = bcs->hw.tiger.send; bcs->hw.tiger.free = NETJET_DMA_TXSIZE; test_and_set_bit(BC_FLG_EMPTY, &bcs->Flag); if (cs->typ == ISDN_CTYPE_NETJET_S) { // led on led = bc & 0x01; led = 0x01 << (6 + led); // convert to mask cs->hw.njet.auxd |= led; byteout(cs->hw.njet.auxa, cs->hw.njet.auxd); } break; } if (cs->debug & L1_DEB_HSCX) debugl1(cs, "tiger: set %x %x %x %x/%x pulse=%d", bytein(cs->hw.njet.base + NETJET_DMACTRL), bytein(cs->hw.njet.base + NETJET_IRQMASK0), bytein(cs->hw.njet.base + NETJET_IRQSTAT0), inl(cs->hw.njet.base + NETJET_DMA_READ_ADR), inl(cs->hw.njet.base + NETJET_DMA_WRITE_ADR), bytein(cs->hw.njet.base + NETJET_PULSE_CNT));}static void printframe(struct IsdnCardState *cs, u_char *buf, int count, char *s) { char tmp[128]; char *t = tmp; int i=count,j; u_char *p = buf; t += sprintf(t, "tiger %s(%4d)", s, count); while (i>0) { if (i>16) j=16; else j=i; QuickHex(t, p, j); debugl1(cs, tmp); p += j; i -= j; t = tmp; t += sprintf(t, "tiger %s ", s); }}// macro for 64k#define MAKE_RAW_BYTE for (j=0; j<8; j++) { \ bitcnt++;\ s_val >>= 1;\ if (val & 1) {\ s_one++;\ s_val |= 0x80;\ } else {\ s_one = 0;\ s_val &= 0x7f;\ }\ if (bitcnt==8) {\ bcs->hw.tiger.sendbuf[s_cnt++] = s_val;\ bitcnt = 0;\ }\ if (s_one == 5) {\ s_val >>= 1;\ s_val &= 0x7f;\ bitcnt++;\ s_one = 0;\ }\ if (bitcnt==8) {\ bcs->hw.tiger.sendbuf[s_cnt++] = s_val;\ bitcnt = 0;\ }\ val >>= 1;\ }static int make_raw_data(struct BCState *bcs) {// this make_raw is for 64k register u_int i,s_cnt=0; register u_char j; register u_char val; register u_char s_one = 0; register u_char s_val = 0; register u_char bitcnt = 0; u_int fcs; if (!bcs->tx_skb) { debugl1(bcs->cs, "tiger make_raw: NULL skb"); return(1); } bcs->hw.tiger.sendbuf[s_cnt++] = HDLC_FLAG_VALUE; fcs = PPP_INITFCS; for (i=0; i<bcs->tx_skb->len; i++) { val = bcs->tx_skb->data[i]; fcs = PPP_FCS (fcs, val); MAKE_RAW_BYTE; } fcs ^= 0xffff; val = fcs & 0xff; MAKE_RAW_BYTE; val = (fcs>>8) & 0xff; MAKE_RAW_BYTE; val = HDLC_FLAG_VALUE; for (j=0; j<8; j++) { bitcnt++; s_val >>= 1; if (val & 1) s_val |= 0x80; else s_val &= 0x7f; if (bitcnt==8) { bcs->hw.tiger.sendbuf[s_cnt++] = s_val; bitcnt = 0; } val >>= 1; } if (bcs->cs->debug & L1_DEB_HSCX) debugl1(bcs->cs,"tiger make_raw: in %ld out %d.%d", bcs->tx_skb->len, s_cnt, bitcnt); if (bitcnt) { while (8>bitcnt++) { s_val >>= 1; s_val |= 0x80; } bcs->hw.tiger.sendbuf[s_cnt++] = s_val; bcs->hw.tiger.sendbuf[s_cnt++] = 0xff; // NJ<->NJ thoughput bug fix } bcs->hw.tiger.sendcnt = s_cnt; bcs->tx_cnt -= bcs->tx_skb->len; bcs->hw.tiger.sp = bcs->hw.tiger.sendbuf; return(0);}// macro for 56k#define MAKE_RAW_BYTE_56K for (j=0; j<8; j++) { \ bitcnt++;\ s_val >>= 1;\ if (val & 1) {\ s_one++;\ s_val |= 0x80;\ } else {\ s_one = 0;\ s_val &= 0x7f;\ }\ if (bitcnt==7) {\ s_val >>= 1;\ s_val |= 0x80;\ bcs->hw.tiger.sendbuf[s_cnt++] = s_val;\ bitcnt = 0;\ }\ if (s_one == 5) {\ s_val >>= 1;\ s_val &= 0x7f;\ bitcnt++;\ s_one = 0;\ }\ if (bitcnt==7) {\ s_val >>= 1;\ s_val |= 0x80;\ bcs->hw.tiger.sendbuf[s_cnt++] = s_val;\ bitcnt = 0;\ }\ val >>= 1;\ }static int make_raw_data_56k(struct BCState *bcs) {// this make_raw is for 56k register u_int i,s_cnt=0; register u_char j; register u_char val; register u_char s_one = 0; register u_char s_val = 0; register u_char bitcnt = 0; u_int fcs; if (!bcs->tx_skb) { debugl1(bcs->cs, "tiger make_raw_56k: NULL skb"); return(1); } val = HDLC_FLAG_VALUE; for (j=0; j<8; j++) { bitcnt++; s_val >>= 1; if (val & 1) s_val |= 0x80; else s_val &= 0x7f; if (bitcnt==7) { s_val >>= 1; s_val |= 0x80; bcs->hw.tiger.sendbuf[s_cnt++] = s_val; bitcnt = 0; } val >>= 1; }; fcs = PPP_INITFCS; for (i=0; i<bcs->tx_skb->len; i++) { val = bcs->tx_skb->data[i]; fcs = PPP_FCS (fcs, val); MAKE_RAW_BYTE_56K; } fcs ^= 0xffff; val = fcs & 0xff; MAKE_RAW_BYTE_56K; val = (fcs>>8) & 0xff; MAKE_RAW_BYTE_56K; val = HDLC_FLAG_VALUE; for (j=0; j<8; j++) { bitcnt++; s_val >>= 1; if (val & 1) s_val |= 0x80; else s_val &= 0x7f; if (bitcnt==7) { s_val >>= 1; s_val |= 0x80; bcs->hw.tiger.sendbuf[s_cnt++] = s_val; bitcnt = 0; } val >>= 1; } if (bcs->cs->debug & L1_DEB_HSCX) debugl1(bcs->cs,"tiger make_raw_56k: in %ld out %d.%d", bcs->tx_skb->len, s_cnt, bitcnt); if (bitcnt) { while (8>bitcnt++) { s_val >>= 1; s_val |= 0x80; } bcs->hw.tiger.sendbuf[s_cnt++] = s_val; bcs->hw.tiger.sendbuf[s_cnt++] = 0xff; // NJ<->NJ thoughput bug fix } bcs->hw.tiger.sendcnt = s_cnt; bcs->tx_cnt -= bcs->tx_skb->len; bcs->hw.tiger.sp = bcs->hw.tiger.sendbuf; return(0);}static void got_frame(struct BCState *bcs, int count) { struct sk_buff *skb; if (!(skb = dev_alloc_skb(count))) printk(KERN_WARNING "TIGER: receive out of memory\n"); else { memcpy(skb_put(skb, count), bcs->hw.tiger.rcvbuf, count); skb_queue_tail(&bcs->rqueue, skb); } test_and_set_bit(B_RCVBUFREADY, &bcs->event); schedule_work(&bcs->tqueue); if (bcs->cs->debug & L1_DEB_RECEIVE_FRAME) printframe(bcs->cs, bcs->hw.tiger.rcvbuf, count, "rec");}static void read_raw(struct BCState *bcs, u_int *buf, int cnt){ int i; register u_char j; register u_char val; u_int *pend = bcs->hw.tiger.rec +NETJET_DMA_RXSIZE -1; register u_char state = bcs->hw.tiger.r_state; register u_char r_one = bcs->hw.tiger.r_one; register u_char r_val = bcs->hw.tiger.r_val; register u_int bitcnt = bcs->hw.tiger.r_bitcnt; u_int *p = buf; int bits; u_char mask; if (bcs->mode == L1_MODE_HDLC) { // it's 64k mask = 0xff; bits = 8; } else { // it's 56K mask = 0x7f; bits = 7; }; for (i=0;i<cnt;i++) { val = bcs->channel ? ((*p>>8) & 0xff) : (*p & 0xff); p++; if (p > pend) p = bcs->hw.tiger.rec; if ((val & mask) == mask) { state = HDLC_ZERO_SEARCH; bcs->hw.tiger.r_tot++; bitcnt = 0; r_one = 0; continue; } for (j=0;j<bits;j++) { if (state == HDLC_ZERO_SEARCH) { if (val & 1) { r_one++; } else { r_one=0; state= HDLC_FLAG_SEARCH; if (bcs->cs->debug & L1_DEB_HSCX) debugl1(bcs->cs,"tiger read_raw: zBit(%d,%d,%d) %x", bcs->hw.tiger.r_tot,i,j,val); } } else if (state == HDLC_FLAG_SEARCH) { if (val & 1) { r_one++; if (r_one>6) { state=HDLC_ZERO_SEARCH; } } else { if (r_one==6) { bitcnt=0; r_val=0; state=HDLC_FLAG_FOUND; if (bcs->cs->debug & L1_DEB_HSCX) debugl1(bcs->cs,"tiger read_raw: flag(%d,%d,%d) %x", bcs->hw.tiger.r_tot,i,j,val); } r_one=0; } } else if (state == HDLC_FLAG_FOUND) { if (val & 1) { r_one++; if (r_one>6) { state=HDLC_ZERO_SEARCH; } else { r_val >>= 1; r_val |= 0x80; bitcnt++; } } else { if (r_one==6) { bitcnt=0; r_val=0; r_one=0; val >>= 1; continue; } else if (r_one!=5) { r_val >>= 1; r_val &= 0x7f; bitcnt++; } r_one=0; } if ((state != HDLC_ZERO_SEARCH) && !(bitcnt & 7)) { state=HDLC_FRAME_FOUND; bcs->hw.tiger.r_fcs = PPP_INITFCS; bcs->hw.tiger.rcvbuf[0] = r_val; bcs->hw.tiger.r_fcs = PPP_FCS (bcs->hw.tiger.r_fcs, r_val); if (bcs->cs->debug & L1_DEB_HSCX) debugl1(bcs->cs,"tiger read_raw: byte1(%d,%d,%d) rval %x val %x i %x", bcs->hw.tiger.r_tot,i,j,r_val,val, bcs->cs->hw.njet.irqstat0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -