📄 yam.c
字号:
case 1200: return add_mcs(bits_1200, bitrate); default: return add_mcs(bits_9600, bitrate); }}/* * download bitstream to FPGA * data is contained in bits[] array in yam1200.h resp. yam9600.h */static int fpga_download(int iobase, int bitrate){ int i, rc; unsigned char *pbits; pbits = get_mcs(bitrate); if (pbits == NULL) return -1; fpga_reset(iobase); for (i = 0; i < YAM_FPGA_SIZE; i++) { if (fpga_write(iobase, pbits[i])) { printk(KERN_ERR "yam: error in write cycle\n"); return -1; /* write... */ } } fpga_write(iobase, 0xFF); rc = inb(MSR(iobase)); /* check DONE signal */ /* Needed for some hardwares */ delay(50); return (rc & MSR_DSR) ? 0 : -1;}/************************************************************************* Serial port init ************************************************************************/static void yam_set_uart(struct net_device *dev){ struct yam_port *yp = (struct yam_port *) dev->priv; int divisor = 115200 / yp->baudrate; outb(0, IER(dev->base_addr)); outb(LCR_DLAB | LCR_BIT8, LCR(dev->base_addr)); outb(divisor, DLL(dev->base_addr)); outb(0, DLM(dev->base_addr)); outb(LCR_BIT8, LCR(dev->base_addr)); outb(PTT_OFF, MCR(dev->base_addr)); outb(0x00, FCR(dev->base_addr)); /* Flush pending irq */ inb(RBR(dev->base_addr)); inb(MSR(dev->base_addr)); /* Enable rx irq */ outb(ENABLE_RTXINT, IER(dev->base_addr));}/* --------------------------------------------------------------------- */enum uart { c_uart_unknown, c_uart_8250, c_uart_16450, c_uart_16550, c_uart_16550A};static const char *uart_str[] ={"unknown", "8250", "16450", "16550", "16550A"};static enum uart yam_check_uart(unsigned int iobase){ unsigned char b1, b2, b3; enum uart u; enum uart uart_tab[] = {c_uart_16450, c_uart_unknown, c_uart_16550, c_uart_16550A}; b1 = inb(MCR(iobase)); outb(b1 | 0x10, MCR(iobase)); /* loopback mode */ b2 = inb(MSR(iobase)); outb(0x1a, MCR(iobase)); b3 = inb(MSR(iobase)) & 0xf0; outb(b1, MCR(iobase)); /* restore old values */ outb(b2, MSR(iobase)); if (b3 != 0x90) return c_uart_unknown; inb(RBR(iobase)); inb(RBR(iobase)); outb(0x01, FCR(iobase)); /* enable FIFOs */ u = uart_tab[(inb(IIR(iobase)) >> 6) & 3]; if (u == c_uart_16450) { outb(0x5a, SCR(iobase)); b1 = inb(SCR(iobase)); outb(0xa5, SCR(iobase)); b2 = inb(SCR(iobase)); if ((b1 != 0x5a) || (b2 != 0xa5)) u = c_uart_8250; } return u;}/******************************************************************************* Rx Section******************************************************************************/static inline void yam_rx_flag(struct net_device *dev, struct yam_port *yp){ if (yp->dcd && yp->rx_len >= 3 && yp->rx_len < YAM_MAX_FRAME) { int pkt_len = yp->rx_len - 2 + 1; /* -CRC + kiss */ struct sk_buff *skb; if ((yp->rx_crch & yp->rx_crcl) != 0xFF) { /* Bad crc */ } else { if (!(skb = dev_alloc_skb(pkt_len))) { printk(KERN_WARNING "%s: memory squeeze, dropping packet\n", dev->name); ++yp->stats.rx_dropped; } else { unsigned char *cp; skb->dev = dev; cp = skb_put(skb, pkt_len); *cp++ = 0; /* KISS kludge */ memcpy(cp, yp->rx_buf, pkt_len - 1); skb->protocol = htons(ETH_P_AX25); skb->mac.raw = skb->data; netif_rx(skb); ++yp->stats.rx_packets; } } } yp->rx_len = 0; yp->rx_crcl = 0x21; yp->rx_crch = 0xf3;}static inline void yam_rx_byte(struct net_device *dev, struct yam_port *yp, unsigned char rxb){ if (yp->rx_len < YAM_MAX_FRAME) { unsigned char c = yp->rx_crcl; yp->rx_crcl = (chktabl[c] ^ yp->rx_crch); yp->rx_crch = (chktabh[c] ^ rxb); yp->rx_buf[yp->rx_len++] = rxb; }}/********************************************************************************* TX Section********************************************************************************/static void ptt_on(struct net_device *dev){ outb(PTT_ON, MCR(dev->base_addr));}static void ptt_off(struct net_device *dev){ outb(PTT_OFF, MCR(dev->base_addr));}static int yam_send_packet(struct sk_buff *skb, struct net_device *dev){ struct yam_port *yp = dev->priv; skb_queue_tail(&yp->send_queue, skb); dev->trans_start = jiffies; return 0;}static void yam_start_tx(struct net_device *dev, struct yam_port *yp){ if ((yp->tx_state == TX_TAIL) || (yp->txd == 0)) yp->tx_count = 1; else yp->tx_count = (yp->bitrate * yp->txd) / 8000; yp->tx_state = TX_HEAD; ptt_on(dev);}static unsigned short random_seed;static inline unsigned short random_num(void){ random_seed = 28629 * random_seed + 157; return random_seed;}static void yam_arbitrate(struct net_device *dev){ struct yam_port *yp = dev->priv; if (!yp || yp->magic != YAM_MAGIC || yp->tx_state != TX_OFF || skb_queue_empty(&yp->send_queue)) { return; } /* tx_state is TX_OFF and there is data to send */ if (yp->dupmode) { /* Full duplex mode, don't wait */ yam_start_tx(dev, yp); return; } if (yp->dcd) { /* DCD on, wait slotime ... */ yp->slotcnt = yp->slot / 10; return; } /* Is slottime passed ? */ if ((--yp->slotcnt) > 0) return; yp->slotcnt = yp->slot / 10; /* is random > persist ? */ if ((random_num() % 256) > yp->pers) return; yam_start_tx(dev, yp);}static void yam_dotimer(unsigned long dummy){ int i; for (i = 0; i < NR_PORTS; i++) { struct net_device *dev = &yam_ports[i].dev; if (netif_running(dev)) yam_arbitrate(dev); } yam_timer.expires = jiffies + HZ / 100; add_timer(&yam_timer);}static void yam_tx_byte(struct net_device *dev, struct yam_port *yp){ struct sk_buff *skb; unsigned char b, temp; switch (yp->tx_state) { case TX_OFF: break; case TX_HEAD: if (--yp->tx_count <= 0) { if (!(skb = skb_dequeue(&yp->send_queue))) { ptt_off(dev); yp->tx_state = TX_OFF; break; } yp->tx_state = TX_DATA; if (skb->data[0] != 0) {/* do_kiss_params(s, skb->data, skb->len); */ dev_kfree_skb_any(skb); break; } yp->tx_len = skb->len - 1; /* strip KISS byte */ if (yp->tx_len >= YAM_MAX_FRAME || yp->tx_len < 2) { dev_kfree_skb_any(skb); break; } memcpy(yp->tx_buf, skb->data + 1, yp->tx_len); dev_kfree_skb_any(skb); yp->tx_count = 0; yp->tx_crcl = 0x21; yp->tx_crch = 0xf3; yp->tx_state = TX_DATA; } break; case TX_DATA: b = yp->tx_buf[yp->tx_count++]; outb(b, THR(dev->base_addr)); temp = yp->tx_crcl; yp->tx_crcl = chktabl[temp] ^ yp->tx_crch; yp->tx_crch = chktabh[temp] ^ b; if (yp->tx_count >= yp->tx_len) { yp->tx_state = TX_CRC1; } break; case TX_CRC1: yp->tx_crch = chktabl[yp->tx_crcl] ^ yp->tx_crch; yp->tx_crcl = chktabh[yp->tx_crcl] ^ chktabl[yp->tx_crch] ^ 0xff; outb(yp->tx_crcl, THR(dev->base_addr)); yp->tx_state = TX_CRC2; break; case TX_CRC2: outb(chktabh[yp->tx_crch] ^ 0xFF, THR(dev->base_addr)); if (skb_queue_empty(&yp->send_queue)) { yp->tx_count = (yp->bitrate * yp->txtail) / 8000; if (yp->dupmode == 2) yp->tx_count += (yp->bitrate * yp->holdd) / 8; if (yp->tx_count == 0) yp->tx_count = 1; yp->tx_state = TX_TAIL; } else { yp->tx_count = 1; yp->tx_state = TX_HEAD; } ++yp->stats.tx_packets; break; case TX_TAIL: if (--yp->tx_count <= 0) { yp->tx_state = TX_OFF; ptt_off(dev); } break; }}/************************************************************************************ ISR routine************************************************************************************/static void yam_interrupt(int irq, void *dev_id, struct pt_regs *regs){ struct net_device *dev; struct yam_port *yp; unsigned char iir; int counter = 100; int i; sti(); for (i = 0; i < NR_PORTS; i++) { yp = &yam_ports[i]; dev = &yp->dev; if (!netif_running(dev)) continue; while ((iir = IIR_MASK & inb(IIR(dev->base_addr))) != IIR_NOPEND) { unsigned char msr = inb(MSR(dev->base_addr)); unsigned char lsr = inb(LSR(dev->base_addr)); unsigned char rxb; if (lsr & LSR_OE) ++yp->stats.rx_fifo_errors; yp->dcd = (msr & RX_DCD) ? 1 : 0; if (--counter <= 0) { printk(KERN_ERR "%s: too many irq iir=%d\n", dev->name, iir); return; } if (msr & TX_RDY) { ++yp->nb_mdint; yam_tx_byte(dev, yp); } if (lsr & LSR_RXC) { ++yp->nb_rxint; rxb = inb(RBR(dev->base_addr)); if (msr & RX_FLAG) yam_rx_flag(dev, yp); else yam_rx_byte(dev, yp, rxb); } } }}static int yam_net_get_info(char *buffer, char **start, off_t offset, int length){ int len = 0; int i; off_t pos = 0; off_t begin = 0; cli(); for (i = 0; i < NR_PORTS; i++) { if (yam_ports[i].iobase == 0 || yam_ports[i].irq == 0) continue; len += sprintf(buffer + len, "Device yam%d\n", i); len += sprintf(buffer + len, " Up %d\n", netif_running(&yam_ports[i].dev)); len += sprintf(buffer + len, " Speed %u\n", yam_ports[i].bitrate); len += sprintf(buffer + len, " IoBase 0x%x\n", yam_ports[i].iobase); len += sprintf(buffer + len, " BaudRate %u\n", yam_ports[i].baudrate); len += sprintf(buffer + len, " IRQ %u\n", yam_ports[i].irq); len += sprintf(buffer + len, " TxState %u\n", yam_ports[i].tx_state); len += sprintf(buffer + len, " Duplex %u\n", yam_ports[i].dupmode); len += sprintf(buffer + len, " HoldDly %u\n", yam_ports[i].holdd); len += sprintf(buffer + len, " TxDelay %u\n", yam_ports[i].txd); len += sprintf(buffer + len, " TxTail %u\n", yam_ports[i].txtail); len += sprintf(buffer + len, " SlotTime %u\n", yam_ports[i].slot); len += sprintf(buffer + len, " Persist %u\n", yam_ports[i].pers); len += sprintf(buffer + len, " TxFrames %lu\n", yam_ports[i].stats.tx_packets); len += sprintf(buffer + len, " RxFrames %lu\n", yam_ports[i].stats.rx_packets); len += sprintf(buffer + len, " TxInt %u\n", yam_ports[i].nb_mdint); len += sprintf(buffer + len, " RxInt %u\n", yam_ports[i].nb_rxint); len += sprintf(buffer + len, " RxOver %lu\n", yam_ports[i].stats.rx_fifo_errors); len += sprintf(buffer + len, "\n"); pos = begin + len; if (pos < offset) { len = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -