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

📄 pi2.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
	    restore_flags(flags);	    return;	}	/* NOTE - fall through if more to send */    case ST_TXDELAY:	/* Disable DMA chan */	disable_dma(lp->dmachan);	/* Set up for TX dma */	wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | EXT_INT_ENAB);	/* Get all chars */	/* Strip KISS control byte */	length = lp->sndbuf->len - 1;	memcpy(lp->txdmabuf, &lp->sndbuf->data[1], length);	/* Setup DMA controller for tx */	setup_tx_dma(lp, length);	/* select transmit interrupts to enable */	/* Allow DMA on chan */	enable_dma(lp->dmachan);	/* reset CRC, Txint pend*/	wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC | RES_Tx_P);	/* allow Underrun int only */	wrtscc(lp->cardbase, cmd, R15, TxUIE);	/* Enable TX DMA */	wrtscc(lp->cardbase, cmd, R1, WT_RDY_ENAB | WT_FN_RDYFN | EXT_INT_ENAB);	/* Send CRC on underrun */	wrtscc(lp->cardbase, cmd, R0, RES_EOM_L);	/* packet going out now */	lp->tstate = ACTIVE;	break;    case DEFER:	/* we have deferred prev xmit attempt         * See Intel Microcommunications Handbook, p2-308         */	wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);	wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);	if ((rdscc(lp->cardbase, cmd, R0) & DCD) != 0) {	    lp->tstate = DEFER;	    tdelay(lp, 100);	    /* Defer until dcd transition or 100mS timeout */	    wrtscc(lp->cardbase, CTL + lp->base, R15, CTSIE | DCDIE);	    restore_flags(flags);	    return;	}	if (random() > lp->persist) {	    lp->tstate = DEFER;	    tdelay(lp, lp->slotime);	    restore_flags(flags);	    return;	}	/* Assert RTS early minimize collision window */	wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | Tx8);	rts(lp, ON);		/* Transmitter on */	lp->tstate = ST_TXDELAY;	tdelay(lp, lp->txdelay);	restore_flags(flags);	return;    }				/* switch(lp->tstate) */    restore_flags(flags);}				/* a_exint() *//* Receive interrupt handler for the A channel */static void a_rxint(struct device *dev, struct pi_local *lp){    unsigned long flags;    int cmd;    int bytecount;    char rse;    struct sk_buff *skb;    int sksize, pkt_len;    struct mbuf *cur_buf;    unsigned char *cfix;    save_flags(flags);    cli();			/* disable interrupts */    cmd = lp->base + CTL;    rse = rdscc(lp->cardbase, cmd, R1);	/* Get special condition bits from R1 */    if (rse & Rx_OVR)	lp->rstate = RXERROR;    if (rse & END_FR) {	/* If end of frame */	/* figure length of frame from 8237 */	clear_dma_ff(lp->dmachan);	bytecount = lp->bufsiz - get_dma_residue(lp->dmachan);	if ((rse & CRC_ERR) || (lp->rstate > ACTIVE) || (bytecount < 10)) {	    if ((bytecount >= 10) && (rse & CRC_ERR)) {		lp->stats.rx_crc_errors++;	    }	    if (lp->rstate == RXERROR) {		lp->stats.rx_errors++;		lp->stats.rx_over_errors++;	    }	    /* Reset buffer pointers */	    lp->rstate = ACTIVE;	    setup_rx_dma(lp);	} else {	    /* Here we have a valid frame */	    /* Toss 2 crc bytes , add one for KISS */	    pkt_len = lp->rcvbuf->cnt = bytecount - 2 + 1;	    /* Get buffer for next frame */	    cur_buf = lp->rcvbuf;	    switchbuffers(lp);	    setup_rx_dma(lp);	    /* Malloc up new buffer. */	    sksize = pkt_len;	    skb = dev_alloc_skb(sksize);	    if (skb == NULL) {		printk(KERN_ERR "PI: %s: Memory squeeze, dropping packet.\n", dev->name);		lp->stats.rx_dropped++;		restore_flags(flags);		return;	    }	    skb->dev = dev;	    /* KISS kludge -  prefix with a 0 byte */	    cfix=skb_put(skb,pkt_len);	    *cfix++=0;	    /* 'skb->data' points to the start of sk_buff data area. */	    memcpy(cfix, (char *) cur_buf->data,		   pkt_len - 1);	    skb->protocol=htons(ETH_P_AX25);	    skb->mac.raw=skb->data;	    netif_rx(skb);	    lp->stats.rx_packets++;	}			/* end good frame */    }				/* end EOF check */    wrtscc(lp->cardbase, lp->base + CTL, R0, ERR_RES);	/* error reset */    restore_flags(flags);}static void b_rxint(struct device *dev, struct pi_local *lp){    unsigned long flags;    int cmd;    char rse;    struct sk_buff *skb;    int sksize;    int pkt_len;    unsigned char *cfix;    save_flags(flags);    cli();			/* disable interrupts */    cmd = CTL + lp->base;    rse = rdscc(lp->cardbase, cmd, R1);	/* get status byte from R1 */    if ((rdscc(lp->cardbase, cmd, R0)) & Rx_CH_AV) {	/* there is a char to be stored         * read special condition bits before reading the data char         */	if (rse & Rx_OVR) {	    /* Rx overrun - toss buffer */	    /* reset buffer pointers */	    lp->rcp = lp->rcvbuf->data;	    lp->rcvbuf->cnt = 0;	    lp->rstate = RXERROR;	/* set error flag */	    lp->stats.rx_errors++;	    lp->stats.rx_over_errors++;	} else if (lp->rcvbuf->cnt >= lp->bufsiz) {	    /* Too large -- toss buffer */	    /* reset buffer pointers */	    lp->rcp = lp->rcvbuf->data;	    lp->rcvbuf->cnt = 0;	    lp->rstate = TOOBIG;/* when set, chars are not stored */	}	/* ok, we can store the received character now */	if (lp->rstate == ACTIVE) {	/* If no errors... */	    *lp->rcp++ = rdscc(lp->cardbase, cmd, R8);	/* char to rcv buff */	    lp->rcvbuf->cnt++;	/* bump count */	} else {	    /* got to empty FIFO */	    (void) rdscc(lp->cardbase, cmd, R8);	    wrtscc(lp->cardbase, cmd, R0, ERR_RES);	/* reset err latch */	    lp->rstate = ACTIVE;	}    }    if (rse & END_FR) {	/* END OF FRAME -- Make sure Rx was active */	if (lp->rcvbuf->cnt > 0) {	    if ((rse & CRC_ERR) || (lp->rstate > ACTIVE) || (lp->rcvbuf->cnt < 10)) {		if ((lp->rcvbuf->cnt >= 10) && (rse & CRC_ERR)) {		    lp->stats.rx_crc_errors++;		}		lp->rcp = lp->rcvbuf->data;		lp->rcvbuf->cnt = 0;	    } else {		/* Here we have a valid frame */		pkt_len = lp->rcvbuf->cnt -= 2;	/* Toss 2 crc bytes */		pkt_len += 1;	/* Make room for KISS control byte */		/* Malloc up new buffer. */		sksize = pkt_len;		skb = dev_alloc_skb(sksize);		if (skb == NULL) {		    printk(KERN_ERR "PI: %s: Memory squeeze, dropping packet.\n", dev->name);		    lp->stats.rx_dropped++;		    restore_flags(flags);		    return;		}		skb->dev = dev;		/* KISS kludge -  prefix with a 0 byte */		cfix=skb_put(skb,pkt_len);		*cfix++=0;		/* 'skb->data' points to the start of sk_buff data area. */		memcpy(cfix, lp->rcvbuf->data, pkt_len - 1);		skb->protocol=ntohs(ETH_P_AX25);		skb->mac.raw=skb->data;		netif_rx(skb);		lp->stats.rx_packets++;		/* packet queued - initialize buffer for next frame */		lp->rcp = lp->rcvbuf->data;		lp->rcvbuf->cnt = 0;	    }			/* end good frame queued */	}			/* end check for active receive upon EOF */	lp->rstate = ACTIVE;	/* and clear error status */    }				/* end EOF check */    restore_flags(flags);}static void b_txint(struct pi_local *lp){    unsigned long flags;    int cmd;    unsigned char c;    save_flags(flags);    cli();    cmd = CTL + lp->base;    switch (lp->tstate) {    case CRCOUT:	lp->tstate = FLAGOUT;	tdelay(lp, lp->squeldelay);	restore_flags(flags);	return;    case IDLE:	/* Transmitter idle. Find a frame for transmission */	if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL) {	    /* Nothing to send - return to receive mode             * Tx OFF now - flag should have gone             */	    rts(lp, OFF);	    restore_flags(flags);	    return;	}	lp->txptr = lp->sndbuf->data;	lp->txptr++;		/* Ignore KISS control byte */	lp->txcnt = (int) lp->sndbuf->len - 1;	/* If a buffer to send, we drop thru here */    case DEFER:		/* we may have deferred prev xmit attempt */	/* Check DCD - debounce it */	/* See Intel Microcommunications Handbook, p2-308 */	wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);	wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);	if ((rdscc(lp->cardbase, cmd, R0) & DCD) != 0) {	    lp->tstate = DEFER;	    tdelay(lp, 100);	    /* defer until DCD transition or timeout */	    wrtscc(lp->cardbase, cmd, R15, CTSIE | DCDIE);	    restore_flags(flags);	    return;	}	if (random() > lp->persist) {	    lp->tstate = DEFER;	    tdelay(lp, lp->slotime);	    restore_flags(flags);	    return;	}	rts(lp, ON);		/* Transmitter on */	lp->tstate = ST_TXDELAY;	tdelay(lp, lp->txdelay);	restore_flags(flags);	return;    case ACTIVE:	/* Here we are actively sending a frame */	if (lp->txcnt--) {	    c = *lp->txptr++;	    /* next char is gone */	    wrtscc(lp->cardbase, cmd, R8, c);	    /* stuffing a char satisfies Interrupt condition */	} else {	    /* No more to send */	    kfree_skb(lp->sndbuf);	    lp->sndbuf = NULL;	    if ((rdscc(lp->cardbase, cmd, R0) & 0x40)) {		/* Did we underrun? */		/* unexpected underrun */		lp->stats.tx_errors++;		lp->stats.tx_fifo_errors++;		wrtscc(lp->cardbase, cmd, R0, SEND_ABORT);		lp->tstate = FLAGOUT;		tdelay(lp, lp->squeldelay);		restore_flags(flags);		return;	    }	    lp->tstate = UNDERRUN;	/* Now we expect to underrun */	    /* Send flags on underrun */	    if (lp->speed) {	/* If internally clocked */		wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI);	    } else {		wrtscc(lp->cardbase, cmd, R10, CRCPS);	    }	    wrtscc(lp->cardbase, cmd, R0, RES_Tx_P);	/* reset Tx Int Pend */	}	restore_flags(flags);	return;			/* back to wait for interrupt */    }				/* end switch */    restore_flags(flags);}/* Pi SIO External/Status interrupts (for the B channel) * This can be caused by a receiver abort, or a Tx UNDERRUN/EOM. * Receiver automatically goes to Hunt on an abort. * * If the Tx Underrun interrupt hits, change state and * issue a reset command for it, and return. */static void b_exint(struct pi_local *lp){    unsigned long flags;    char st;    int cmd;    char c;    cmd = CTL + lp->base;    save_flags(flags);    cli();			/* disable interrupts */    st = rdscc(lp->cardbase, cmd, R0);	/* Fetch status */    /* reset external status latch */    wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);    switch (lp->tstate) {    case ACTIVE:		/* Unexpected underrun */	kfree_skb(lp->sndbuf);	lp->sndbuf = NULL;	wrtscc(lp->cardbase, cmd, R0, SEND_ABORT);	lp->tstate = FLAGOUT;	lp->stats.tx_errors++;	lp->stats.tx_fifo_errors++;	tdelay(lp, lp->squeldelay);	restore_flags(flags);	return;    case UNDERRUN:	lp->tstate = CRCOUT;	restore_flags(flags);	return;    case FLAGOUT:	/* Find a frame for transmission */	if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL) {	    /* Nothing to send - return to receive mode             * Tx OFF now - flag should have gone             */	    rts(lp, OFF);	    lp->tstate = IDLE;	    restore_flags(flags);	    return;	}	lp->txptr = lp->sndbuf->data;	lp->txptr++;		/* Ignore KISS control byte */	lp->txcnt = (int) lp->sndbuf->len - 1;	/* Get first char to send */	lp->txcnt--;	c = *lp->txptr++;	wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC);	/* reset for next frame */	/* Send abort on underrun */	if (lp->speed) {	/* If internally clocked */	    wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI | ABUNDER);	} else {	    wrtscc(lp->cardbase, cmd, R10, CRCPS | ABUNDER);	}	wrtscc(lp->cardbase, cmd, R8, c);	/* First char out now */	wrtscc(lp->cardbase, cmd, R0, RES_EOM_L);	/* Reset end of message latch */#ifdef STUFF2        /* stuff an extra one if we can */	if (lp->txcnt) {	    lp->txcnt--;	    c = *lp->txptr++;	    /* Wait for tx buffer empty */	    while((rdscc(lp->cardbase, cmd, R0) & 0x04) == 0)		;	    wrtscc(lp->cardbase, cmd, R8, c);	}#endif	/* select transmit interrupts to enable */	wrtscc(lp->cardbase, cmd, R15, TxUIE);	/* allow Underrun int only */	wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);	wrtscc(lp->cardbase, cmd, R1, TxINT_ENAB | EXT_INT_ENAB);	/* Tx/Ext ints */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -