📄 baycom_epp.c
字号:
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 = netdev_priv(dev); 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; } cp = skb_put(skb, pktlen); *cp++ = 0; /* KISS kludge */ memcpy(cp, bc->hdlcrx.buf, pktlen - 1); skb->protocol = ax25_type_trans(skb, dev); netif_rx(skb); dev->last_rx = jiffies; bc->stats.rx_packets++;}static int receive(struct net_device *dev, int cnt){ struct baycom_state *bc = netdev_priv(dev); struct parport *pp = bc->pdev->port; unsigned int bitbuf, notbitstream, bitstream, numbits, state; unsigned char tmp[128]; unsigned char *cp; int cnt2, ret = 0; int j; 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; for (j = 0; j < 8; j++) { /* flag or abort */ if (unlikely(!(notbitstream & (0x0fc << j)))) { /* abort received */ if (!(notbitstream & (0x1fc << j))) state = 0; /* not flag received */ else if (!(bitstream & (0x1fe << j)) != (0x0fc << j)) { if (state) do_rxpacket(dev); bc->hdlcrx.bufcnt = 0; bc->hdlcrx.bufptr = bc->hdlcrx.buf; state = 1; numbits = 7-j; } } /* stuffed bit */ else if (unlikely((bitstream & (0x1f8 << j)) == (0xf8 << j))) { numbits--; bitbuf = (bitbuf & ((~0xff) << j)) | ((bitbuf & ~((~0xff) << j)) << 1); } } 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__#include <asm/msr.h>#define GETTICK(x) \({ \ if (cpu_has_tsc) \ rdtscl(x); \})#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; bc = netdev_priv(dev); if (!bc->work_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 */ schedule_delayed_work(&bc->run_work, 1); 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 = netdev_priv(dev); 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 = netdev_priv(dev); /* * 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 = netdev_priv(dev); 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){ struct baycom_state *bc = netdev_priv(dev); struct parport *pp = parport_find_base(dev->base_addr); unsigned int i, j; unsigned char tmp[128]; unsigned char stat; unsigned long tstart; if (!pp) { printk(KERN_ERR "%s: parport at 0x%lx unknown\n", bc_drvname, dev->base_addr); return -ENXIO; }#if 0 if (pp->irq < 0) { printk(KERN_ERR "%s: parport at 0x%lx has no irq\n", bc_drvname, pp->base); parport_put_port(pp); return -ENXIO; }#endif if ((~pp->modes) & (PARPORT_MODE_TRISTATE | PARPORT_MODE_PCSPP | PARPORT_MODE_SAFEININT)) { printk(KERN_ERR "%s: parport at 0x%lx cannot be used\n", bc_drvname, pp->base); parport_put_port(pp); return -EIO; } memset(&bc->modem, 0, sizeof(bc->modem));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -