📄 baycom_epp.c
字号:
skb = bc->skb; if (!skb) return; bc->skb = NULL; pkt_len = skb->len-1; /* strip KISS byte */ wp = bc->hdlctx.buf; bp = skb->data+1; crc = calc_crc_ccitt(bp, pkt_len); crcarr[0] = crc; crcarr[1] = crc >> 8; *wp++ = 0x7e; bitstream = bitbuf = numbit = 0; while (pkt_len > -2) { bitstream >>= 8; bitstream |= ((unsigned int)*bp) << 8; bitbuf |= ((unsigned int)*bp) << numbit; notbitstream = ~bitstream; bp++; pkt_len--; if (!pkt_len) bp = crcarr; ENCODEITERA(0); ENCODEITERA(1); ENCODEITERA(2); ENCODEITERA(3); ENCODEITERA(4); ENCODEITERA(5); ENCODEITERA(6); ENCODEITERA(7); goto enditer; ENCODEITERB(0); ENCODEITERB(1); ENCODEITERB(2); ENCODEITERB(3); ENCODEITERB(4); ENCODEITERB(5); ENCODEITERB(6); ENCODEITERB(7); enditer: numbit += 8; while (numbit >= 8) { *wp++ = bitbuf; bitbuf >>= 8; numbit -= 8; } } bitbuf |= 0x7e7e << numbit; numbit += 16; while (numbit >= 8) { *wp++ = bitbuf; bitbuf >>= 8; numbit -= 8; } bc->hdlctx.bufptr = bc->hdlctx.buf; bc->hdlctx.bufcnt = wp - bc->hdlctx.buf; dev_kfree_skb(skb); bc->stats.tx_packets++;}/* ---------------------------------------------------------------------- */static unsigned short random_seed;static inline unsigned short random_num(void){ random_seed = 28629 * random_seed + 157; return random_seed;}/* ---------------------------------------------------------------------- */static int transmit(struct baycom_state *bc, int cnt, unsigned char stat){ struct parport *pp = bc->pdev->port; unsigned char tmp[128]; int i, j; if (bc->hdlctx.state == tx_tail && !(stat & EPP_PTTBIT)) bc->hdlctx.state = tx_idle; if (bc->hdlctx.state == tx_idle && bc->hdlctx.calibrate <= 0) { if (bc->hdlctx.bufcnt <= 0) encode_hdlc(bc); if (bc->hdlctx.bufcnt <= 0) return 0; if (!bc->ch_params.fulldup) { if (!(stat & EPP_DCDBIT)) { bc->hdlctx.slotcnt = bc->ch_params.slottime; return 0; } if ((--bc->hdlctx.slotcnt) > 0) return 0; bc->hdlctx.slotcnt = bc->ch_params.slottime; if ((random_num() % 256) > bc->ch_params.ppersist) return 0; } } if (bc->hdlctx.state == tx_idle && bc->hdlctx.bufcnt > 0) { bc->hdlctx.state = tx_keyup; bc->hdlctx.flags = tenms_to_flags(bc, bc->ch_params.tx_delay); bc->ptt_keyed++; } while (cnt > 0) { switch (bc->hdlctx.state) { case tx_keyup: i = min_t(int, cnt, bc->hdlctx.flags); cnt -= i; bc->hdlctx.flags -= i; if (bc->hdlctx.flags <= 0) bc->hdlctx.state = tx_data; memset(tmp, 0x7e, sizeof(tmp)); while (i > 0) { j = (i > sizeof(tmp)) ? sizeof(tmp) : i; if (j != pp->ops->epp_write_data(pp, tmp, j, 0)) return -1; i -= j; } break; case tx_data: if (bc->hdlctx.bufcnt <= 0) { encode_hdlc(bc); if (bc->hdlctx.bufcnt <= 0) { bc->hdlctx.state = tx_tail; bc->hdlctx.flags = tenms_to_flags(bc, bc->ch_params.tx_tail); break; } } i = min_t(int, cnt, bc->hdlctx.bufcnt); bc->hdlctx.bufcnt -= i; cnt -= i; if (i != pp->ops->epp_write_data(pp, bc->hdlctx.bufptr, i, 0)) return -1; bc->hdlctx.bufptr += i; break; case tx_tail: encode_hdlc(bc); if (bc->hdlctx.bufcnt > 0) { bc->hdlctx.state = tx_data; break; } i = min_t(int, cnt, bc->hdlctx.flags); if (i) { cnt -= i; bc->hdlctx.flags -= i; memset(tmp, 0x7e, sizeof(tmp)); while (i > 0) { j = (i > sizeof(tmp)) ? sizeof(tmp) : i; if (j != pp->ops->epp_write_data(pp, tmp, j, 0)) return -1; i -= j; } break; } default: /* fall through */ if (bc->hdlctx.calibrate <= 0) return 0; i = min_t(int, cnt, bc->hdlctx.calibrate); cnt -= i; bc->hdlctx.calibrate -= i; memset(tmp, 0, sizeof(tmp)); while (i > 0) { j = (i > sizeof(tmp)) ? sizeof(tmp) : i; if (j != pp->ops->epp_write_data(pp, tmp, j, 0)) return -1; i -= j; } break; } } return 0;}/* ---------------------------------------------------------------------- */static void do_rxpacket(struct net_device *dev){ struct baycom_state *bc = (struct baycom_state *)dev->priv; struct sk_buff *skb; unsigned char *cp; unsigned pktlen; if (bc->hdlcrx.bufcnt < 4) return; if (!check_crc_ccitt(bc->hdlcrx.buf, bc->hdlcrx.bufcnt)) return; pktlen = bc->hdlcrx.bufcnt-2+1; /* KISS kludge */ if (!(skb = dev_alloc_skb(pktlen))) { printk("%s: memory squeeze, dropping packet\n", dev->name); bc->stats.rx_dropped++; return; } skb->dev = dev; cp = skb_put(skb, pktlen); *cp++ = 0; /* KISS kludge */ memcpy(cp, bc->hdlcrx.buf, pktlen - 1); skb->protocol = htons(ETH_P_AX25); skb->mac.raw = skb->data; netif_rx(skb); bc->stats.rx_packets++;}#define DECODEITERA(j) \({ \ if (!(notbitstream & (0x0fc << j))) /* flag or abort */ \ goto flgabrt##j; \ if ((bitstream & (0x1f8 << j)) == (0xf8 << j)) /* stuffed bit */ \ goto stuff##j; \ enditer##j: ; \})#define DECODEITERB(j) \({ \ flgabrt##j: \ if (!(notbitstream & (0x1fc << j))) { /* abort received */ \ state = 0; \ goto enditer##j; \ } \ if ((bitstream & (0x1fe << j)) != (0x0fc << j)) /* flag received */ \ goto enditer##j; \ if (state) \ do_rxpacket(dev); \ bc->hdlcrx.bufcnt = 0; \ bc->hdlcrx.bufptr = bc->hdlcrx.buf; \ state = 1; \ numbits = 7-j; \ goto enditer##j; \ stuff##j: \ numbits--; \ bitbuf = (bitbuf & ((~0xff) << j)) | ((bitbuf & ~((~0xff) << j)) << 1); \ goto enditer##j; \}) static int receive(struct net_device *dev, int cnt){ struct baycom_state *bc = (struct baycom_state *)dev->priv; struct parport *pp = bc->pdev->port; unsigned int bitbuf, notbitstream, bitstream, numbits, state; unsigned char tmp[128]; unsigned char *cp; int cnt2, ret = 0; numbits = bc->hdlcrx.numbits; state = bc->hdlcrx.state; bitstream = bc->hdlcrx.bitstream; bitbuf = bc->hdlcrx.bitbuf; while (cnt > 0) { cnt2 = (cnt > sizeof(tmp)) ? sizeof(tmp) : cnt; cnt -= cnt2; if (cnt2 != pp->ops->epp_read_data(pp, tmp, cnt2, 0)) { ret = -1; break; } cp = tmp; for (; cnt2 > 0; cnt2--, cp++) { bitstream >>= 8; bitstream |= (*cp) << 8; bitbuf >>= 8; bitbuf |= (*cp) << 8; numbits += 8; notbitstream = ~bitstream; DECODEITERA(0); DECODEITERA(1); DECODEITERA(2); DECODEITERA(3); DECODEITERA(4); DECODEITERA(5); DECODEITERA(6); DECODEITERA(7); goto enddec; DECODEITERB(0); DECODEITERB(1); DECODEITERB(2); DECODEITERB(3); DECODEITERB(4); DECODEITERB(5); DECODEITERB(6); DECODEITERB(7); enddec: while (state && numbits >= 8) { if (bc->hdlcrx.bufcnt >= TXBUFFER_SIZE) { state = 0; } else { *(bc->hdlcrx.bufptr)++ = bitbuf >> (16-numbits); bc->hdlcrx.bufcnt++; numbits -= 8; } } } } bc->hdlcrx.numbits = numbits; bc->hdlcrx.state = state; bc->hdlcrx.bitstream = bitstream; bc->hdlcrx.bitbuf = bitbuf; return ret;}/* --------------------------------------------------------------------- */#ifdef __i386__#define GETTICK(x) \({ \ if (cpu_has_tsc) \ __asm__ __volatile__("rdtsc" : "=a" (x) : : "dx");\})#else /* __i386__ */#define GETTICK(x)#endif /* __i386__ */static void epp_bh(struct net_device *dev){ struct baycom_state *bc; struct parport *pp; unsigned char stat; unsigned char tmp[2]; unsigned int time1 = 0, time2 = 0, time3 = 0; int cnt, cnt2; baycom_paranoia_check_void(dev, "epp_bh"); bc = (struct baycom_state *)dev->priv; if (!bc->bh_running) return; baycom_int_freq(bc); pp = bc->pdev->port; /* update status */ if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1) goto epptimeout; bc->stat = stat; bc->debug_vals.last_pllcorr = stat; GETTICK(time1); if (bc->modem == EPP_FPGAEXTSTATUS) { /* get input count */ tmp[0] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE|1; if (pp->ops->epp_write_addr(pp, tmp, 1, 0) != 1) goto epptimeout; if (pp->ops->epp_read_addr(pp, tmp, 2, 0) != 2) goto epptimeout; cnt = tmp[0] | (tmp[1] << 8); cnt &= 0x7fff; /* get output count */ tmp[0] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE|2; if (pp->ops->epp_write_addr(pp, tmp, 1, 0) != 1) goto epptimeout; if (pp->ops->epp_read_addr(pp, tmp, 2, 0) != 2) goto epptimeout; cnt2 = tmp[0] | (tmp[1] << 8); cnt2 = 16384 - (cnt2 & 0x7fff); /* return to normal */ tmp[0] = EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE; if (pp->ops->epp_write_addr(pp, tmp, 1, 0) != 1) goto epptimeout; if (transmit(bc, cnt2, stat)) goto epptimeout; GETTICK(time2); if (receive(dev, cnt)) goto epptimeout; if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1) goto epptimeout; bc->stat = stat; } else { /* try to tx */ switch (stat & (EPP_NTAEF|EPP_NTHF)) { case EPP_NTHF: cnt = 2048 - 256; break; case EPP_NTAEF: cnt = 2048 - 1793; break; case 0: cnt = 0; break; default: cnt = 2048 - 1025; break; } if (transmit(bc, cnt, stat)) goto epptimeout; GETTICK(time2); /* do receiver */ while ((stat & (EPP_NRAEF|EPP_NRHF)) != EPP_NRHF) { switch (stat & (EPP_NRAEF|EPP_NRHF)) { case EPP_NRAEF: cnt = 1025; break; case 0: cnt = 1793; break; default: cnt = 256; break; } if (receive(dev, cnt)) goto epptimeout; if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1) goto epptimeout; } cnt = 0; if (bc->bitrate < 50000) cnt = 256; else if (bc->bitrate < 100000) cnt = 128; while (cnt > 0 && stat & EPP_NREF) { if (receive(dev, 1)) goto epptimeout; cnt--; if (pp->ops->epp_read_addr(pp, &stat, 1, 0) != 1) goto epptimeout; } } GETTICK(time3);#ifdef BAYCOM_DEBUG bc->debug_vals.mod_cycles = time2 - time1; bc->debug_vals.demod_cycles = time3 - time2;#endif /* BAYCOM_DEBUG */ queue_task(&bc->run_bh, &tq_timer); if (!bc->skb) netif_wake_queue(dev); return; epptimeout: printk(KERN_ERR "%s: EPP timeout!\n", bc_drvname);}/* ---------------------------------------------------------------------- *//* * ===================== network driver interface ========================= */static int baycom_send_packet(struct sk_buff *skb, struct net_device *dev){ struct baycom_state *bc; baycom_paranoia_check(dev, "baycom_send_packet", 0); bc = (struct baycom_state *)dev->priv; if (skb->data[0] != 0) { do_kiss_params(bc, skb->data, skb->len); dev_kfree_skb(skb); return 0; } if (bc->skb) return -1; /* strip KISS byte */ if (skb->len >= HDLCDRV_MAXFLEN+1 || skb->len < 3) { dev_kfree_skb(skb); return 0; } netif_stop_queue(dev); bc->skb = skb; return 0;}/* --------------------------------------------------------------------- */static int baycom_set_mac_address(struct net_device *dev, void *addr){ struct sockaddr *sa = (struct sockaddr *)addr; /* addr is an AX.25 shifted ASCII mac address */ memcpy(dev->dev_addr, sa->sa_data, dev->addr_len); return 0; }/* --------------------------------------------------------------------- */static struct net_device_stats *baycom_get_stats(struct net_device *dev){ struct baycom_state *bc; baycom_paranoia_check(dev, "baycom_get_stats", NULL); bc = (struct baycom_state *)dev->priv; /* * Get the current statistics. This may be called with the * card open or closed. */ return &bc->stats;}/* --------------------------------------------------------------------- */static void epp_wakeup(void *handle){ struct net_device *dev = (struct net_device *)handle; struct baycom_state *bc; baycom_paranoia_check_void(dev, "epp_wakeup"); bc = (struct baycom_state *)dev->priv; printk(KERN_DEBUG "baycom_epp: %s: why am I being woken up?\n", dev->name); if (!parport_claim(bc->pdev)) printk(KERN_DEBUG "baycom_epp: %s: I'm broken.\n", dev->name);}/* --------------------------------------------------------------------- *//* * Open/initialize the board. This is called (in the current kernel) * sometime after booting when the 'ifconfig' program is run. * * This routine should set everything up anew at each open, even * registers that "should" only need to be set once at boot, so that * there is non-reboot way to recover if something goes wrong. */static int epp_open(struct net_device *dev)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -