📄 baycom_epp.c
字号:
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 void receive(struct 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 ch; numbits = bc->hdlcrx.numbits; state = bc->hdlcrx.state; bitstream = bc->hdlcrx.bitstream; bitbuf = bc->hdlcrx.bitbuf; for (; cnt > 0; cnt--) { ch = parport_epp_read_data(pp); bitstream >>= 8; bitstream |= ch << 8; bitbuf >>= 8; bitbuf |= ch << 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;}/* --------------------------------------------------------------------- */#ifdef __i386__#define GETTICK(x) \({ \ if (current_cpu_data.x86_capability & X86_FEATURE_TSC) \ __asm__ __volatile__("rdtsc" : "=a" (x) : : "dx");\})#else /* __i386__ */#define GETTICK(x)#endif /* __i386__ */static void epp_bh(struct device *dev){ struct baycom_state *bc; struct parport *pp; unsigned char stat; 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 */ bc->stat = stat = parport_epp_read_addr(pp); bc->debug_vals.last_pllcorr = stat; GETTICK(time1); if (bc->modem == EPP_FPGAEXTSTATUS) { /* get input count */ parport_epp_write_addr(pp, EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE|1); cnt = parport_epp_read_addr(pp); cnt |= parport_epp_read_addr(pp) << 8; cnt &= 0x7fff; /* get output count */ parport_epp_write_addr(pp, EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE|2); cnt2 = parport_epp_read_addr(pp); cnt2 |= parport_epp_read_addr(pp) << 8; cnt2 = 16384 - (cnt2 & 0x7fff); /* return to normal */ parport_epp_write_addr(pp, EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE); transmit(bc, cnt2, stat); GETTICK(time2); receive(dev, cnt); bc->stat = stat = parport_epp_read_addr(pp); } 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; } transmit(bc, cnt, stat); 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; } receive(dev, cnt); stat = parport_epp_read_addr(pp); if (parport_epp_check_timeout(pp)) goto epptimeout; } cnt = 0; if (bc->bitrate < 50000) cnt = 256; else if (bc->bitrate < 100000) cnt = 128; while (cnt > 0 && stat & EPP_NREF) { receive(dev, 1); cnt--; stat = parport_epp_read_addr(pp); } } GETTICK(time3);#ifdef BAYCOM_DEBUG bc->debug_vals.mod_cycles = time2 - time1; bc->debug_vals.demod_cycles = time3 - time2;#endif /* BAYCOM_DEBUG */ if (parport_epp_check_timeout(pp)) goto epptimeout; queue_task(&bc->run_bh, &tq_timer); return; epptimeout: printk(KERN_ERR "%s: EPP timeout!\n", bc_drvname);}/* ---------------------------------------------------------------------- *//* * ===================== network driver interface ========================= */static int baycom_send_packet(struct sk_buff *skb, struct device *dev){ struct baycom_state *bc; baycom_paranoia_check(dev, "baycom_send_packet", 0); bc = (struct baycom_state *)dev->priv; skb_queue_tail(&bc->send_queue, skb); dev->trans_start = jiffies; return 0;}/* --------------------------------------------------------------------- */static int baycom_set_mac_address(struct 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 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 device *dev = (struct 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 device *dev){ struct baycom_state *bc; struct parport *pp; const struct tq_struct run_bh = { 0, 0, (void *)(void *)epp_bh, dev }; unsigned int i, j; unsigned char stat; unsigned long tstart; baycom_paranoia_check(dev, "epp_open", -ENXIO); bc = (struct baycom_state *)dev->priv; if (dev->start) return 0; pp = parport_enumerate(); while (pp && pp->base != dev->base_addr) pp = pp->next; 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); return -ENXIO; }#endif memset(&bc->modem, 0, sizeof(bc->modem)); if (!(bc->pdev = parport_register_device(pp, dev->name, NULL, epp_wakeup, epp_interrupt, PARPORT_DEV_EXCL, dev))) { printk(KERN_ERR "%s: cannot register parport at 0x%lx\n", bc_drvname, pp->base); return -ENXIO; } if (parport_claim(bc->pdev)) { printk(KERN_ERR "%s: parport at 0x%lx busy\n", bc_drvname, pp->base); parport_unregister_device(bc->pdev); return -EBUSY; } if (!(pp->modes & (PARPORT_MODE_PCECPEPP|PARPORT_MODE_PCEPP))) { printk(KERN_ERR "%s: parport at 0x%lx does not support any EPP mode\n", bc_drvname, pp->base); parport_release(bc->pdev); parport_unregister_device(bc->pdev); return -EIO; } dev->irq = /*pp->irq*/ 0; bc->run_bh = run_bh; bc->bh_running = 1; if (pp->modes & PARPORT_MODE_PCECPEPP) { printk(KERN_INFO "%s: trying to enable EPP mode\n", bc_drvname); parport_frob_econtrol(pp, 0xe0, 0x80); } /* bc->pdev->port->ops->change_mode(bc->pdev->port, PARPORT_MODE_PCEPP); not yet implemented */ bc->modem = EPP_CONVENTIONAL; if (eppconfig(bc)) printk(KERN_INFO "%s: no FPGA detected, assuming conventional EPP modem\n", bc_drvname); else bc->modem = /*EPP_FPGA*/ EPP_FPGAEXTSTATUS; parport_write_control(pp, LPTCTRL_PROGRAM); /* prepare EPP mode; we aren't using interrupts */ /* reset the modem */ parport_epp_write_addr(pp, 0); parport_epp_write_addr(pp, EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE); /* autoprobe baud rate */ tstart = jiffies; i = 0; while ((signed)(jiffies-tstart-HZ/3) < 0) { stat = parport_epp_read_addr(pp); if ((stat & (EPP_NRAEF|EPP_NRHF)) == EPP_NRHF) { schedule(); continue; } for (j = 0; j < 256; j++) parport_epp_read_data(pp); i += 256; } for (j = 0; j < 256; j++) { stat = parport_epp_read_addr(pp); if (!(stat & EPP_NREF)) break; parport_epp_read_data(pp); i++; } tstart = jiffies - tstart; bc->bitrate = i * (8 * HZ) / tstart; j = 1; i = bc->bitrate >> 3; while (j < 7 && i > 150) { j++; i >>= 1; } printk(KERN_INFO "%s: autoprobed bitrate: %d int divider: %d int rate: %d\n", bc_drvname, bc->bitrate, j, bc->bitrate >> (j+2)); parport_epp_write_addr(pp, EPP_TX_FIFO_ENABLE|EPP_RX_FIFO_ENABLE|EPP_MODEM_ENABLE/*|j*/); /* * initialise hdlc variables */ bc->hdlcrx.state = 0; bc->hdlcrx.numbits = 0; bc->hdlctx.state = tx_idle; bc->hdlctx.bufcnt = 0; bc->hdlctx.slotcnt = bc->ch_params.slottime; bc->hdlctx.calibrate = 0; dev->start = 1; dev->tbusy = 0; dev->interrupt = 0; /* start the bottom half stuff */ queue_task(&bc->run_bh, &tq_timer); MOD_INC_USE_COUNT; return 0;#if 0 errreturn: parport_release(bc->pdev); parport_unregister_device(bc->pdev); return -EIO;#endif}/* --------------------------------------------------------------------- */static int epp_close(struct device *dev){ struct baycom_state *bc; struct parport *pp; struct sk_buff *skb; baycom_paranoia_check(dev, "epp_close", -EINVAL); if (!dev->start) return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -