⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 yam.c

📁 linux-2.4.29操作系统的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
	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 + -