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

📄 pt.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
                 /* We have a valid frame */                 if (lp->dmachan)                 {                 	pkt_len = lp->rcvbuf->cnt = bytecount - 2 +1;					/* Get buffer for next frame */                 	cur_buf = lp->rcvbuf;                 	switchbuffers(lp);                 	setup_rx_dma(lp);                 } else {	                 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 "PT: %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 area */                 if (lp->dmachan)                 	memcpy(cfix, (char*)cur_buf->data, pkt_len - 1);                 else                    memcpy(cfix, lp->rcvbuf->data, pkt_len - 1);                 skb->protocol = ntohs(ETH_P_AX25);                 skb->mac.raw=skb->data;                 lp->stats.rx_bytes+=skb->len;                 netif_rx(skb);                 lp->stats.rx_packets++;                 if (!lp->dmachan)                 {	                 /* packet queued - wind back buffer for next frame */    	             lp->rcp = lp->rcvbuf->data;	                 lp->rcvbuf->cnt = 0;	             }             } /* good frame */         } /* check active Rx */         /* Clear error status */         lp->rstate = ACTIVE;         /* Reset error latch */     } /* end EOF check */     wrtscc(lp->cardbase, cmd, R0, ERR_RES);     restore_flags(flags);} /* pt_rxisr() *//* * This handles the two timer interrupts. * This is a real bugger, cause you have to rip it out of the pi's * external status code.  They use the CTS line or something. */static void pt_tmrisr(struct pt_local *lp){    unsigned long flags;#ifdef PT_DEBUG	printk(KERN_DEBUG "PT: pt_tmrisr(): tstate = %d (%d).\n", lp->tstate, lp->base & CHANA);#endif    save_flags(flags);    cli();    switch (lp->tstate)    {    /* Most of this stuff is in pt_exisr() */    case FLAGOUT:    case ST_TXDELAY:    case DEFER:/*    case ACTIVE:    case UNDERRUN:*/        pt_exisr(lp);        break;    default:	if (lp->base & CHANA) 	    printk(KERN_ERR "PT: pt_tmrisr(): Invalid tstate %d for Channel A\n", lp->tstate);	else	    printk(KERN_ERR "PT: pt_tmrisr(): Invalid tstate %d for Channel B\n", lp->tstate);	break;    } /* end switch */    restore_flags(flags);} /* pt_tmrisr() *//* * This routine is called by the kernel when there is an interrupt for the * PT. */static void pt_interrupt(int irq, void *dev_id, struct pt_regs *regs){    /* It's a tad dodgy here, but we assume pt0a until proven otherwise */    struct device *dev = &pt0a;    struct pt_local *lp = dev->priv;    unsigned char intreg;    unsigned char st;    register int cbase = dev->base_addr & 0x3f0;    unsigned long flags;    /* Read the PT's interrupt register, this is not the SCC one! */    intreg = inb_p(cbase + INT_REG);    while(( intreg & 0x07) != 0x07) {        /* Read interrupt register pending from Channel A */        while ((st = rdscc(cbase, cbase + CHANA + CTL, R3)) != 0)        {        	/* Read interrupt vector from R2, channel B */#ifdef PT_DEBUG		printk(KERN_DEBUG "PT: pt_interrupt(): R3 = %#3x", st);#endif/*        	st = rdscc(lp->cardbase, cbase + CHANB + CTL, R2) & 0x0e;*/#ifdef PT_DEBUG		printk(KERN_DEBUG "PI: R2 = %#3x.\n", st);#endif			if (st & CHARxIP) {			    /* Channel A Rx */	            lp = (struct pt_local*)pt0a.priv;	            pt_rxisr(&pt0a);	        } else if (st & CHATxIP) {	            /* Channel A Tx */	            lp = (struct pt_local*)pt0a.priv;	            pt_txisr(lp);	        } else if (st & CHAEXT) {	        	/* Channel A External Status */	        	lp = (struct pt_local*)pt0a.priv;	        	pt_exisr(lp);	        } else if (st & CHBRxIP) {	        	/* Channel B Rx */	            lp= (struct pt_local*)pt0b.priv;	            pt_rxisr(&pt0b);	        } else if (st & CHBTxIP) {            	/* Channel B Tx */	            lp = (struct pt_local*)pt0b.priv;	            pt_txisr(lp);			} else if (st & CHBEXT) {	        	/* Channel B External Status */	        	lp = (struct pt_local*)pt0b.priv;	        	pt_exisr(lp);	        }            /* Reset highest interrupt under service */            save_flags(flags);            cli();            wrtscc(lp->cardbase, lp->base + CTL, R0, RES_H_IUS);            restore_flags(flags);        }  /* end of SCC ints */        if (!(intreg & PT_TMR1_MSK))        {            /* Clear timer 1 */            inb_p(cbase + TMR1CLR);            pt_tmrisr( (struct pt_local*)pt0a.priv);        }        if (!(intreg & PT_TMR2_MSK))        {            /* Clear timer 2 */            inb_p(cbase + TMR2CLR);            pt_tmrisr( (struct pt_local*)pt0b.priv);        }        /* Get the next PT interrupt vector */        intreg = inb_p(cbase + INT_REG);    } /* while (intreg) */} /* pt_interrupt() */static void pt_exisr(struct pt_local *lp){    unsigned long flags;    int cmd = lp->base + CTL;    unsigned char st;    char c;    int length;    save_flags(flags);    cli();    /* Get external status */    st = rdscc(lp->cardbase, cmd, R0);#ifdef PT_DEBUG	printk(KERN_DEBUG "PT: exisr(): R0 = %#3x tstate = %d (%d).\n", st, lp->tstate, lp->base & CHANA);#endif    /* Reset external status latch */    wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);    if ((lp->rstate >= ACTIVE) && (st & BRK_ABRT) && lp->dmachan)    {    	setup_rx_dma(lp);    	lp->rstate = ACTIVE;    }    switch (lp->tstate)    {    case ACTIVE:		/* Unexpected underrun */#ifdef PT_DEBUG	printk(KERN_DEBUG "PT: exisr(): unexpected underrun detected.\n");#endif        kfree_skb(lp->sndbuf);        lp->sndbuf = NULL;        if (!lp->dmachan)        {	        wrtscc(lp->cardbase, cmd, R0, SEND_ABORT);	        lp->stats.tx_errors++;	        lp->stats.tx_fifo_errors++;	    }        lp->tstate = FLAGOUT;        tdelay(lp, lp->squeldelay);        restore_flags(flags);        return;    case UNDERRUN:        lp->tstate = CRCOUT;        restore_flags(flags);        return;    case FLAGOUT:        /* squeldelay has timed out */        /* Find a frame for transmission */        if ((lp->sndbuf = skb_dequeue(&lp->sndq)) == NULL)        {            /* Nothing to send - return to Rx mode */            pt_rts(lp, OFF);            lp->tstate = IDLE;            restore_flags(flags);            return;        }        if (!lp->dmachan)        {	        lp->txptr = lp->sndbuf->data;    	    lp->txptr++;		/* Ignore KISS control byte */	        lp->txcnt = (int) lp->sndbuf->len - 1;	    }        /* Fall through if we have a packet */    case ST_TXDELAY:    	if (lp->dmachan)    	{    		/* Disable DMA chan */    		disable_dma(lp->dmachan);    		/* Set up for TX dma */    		wrtscc(lp->cardbase, cmd, R1, WT_FN_RDYFN | EXT_INT_ENAB);    		length = lp->sndbuf->len - 1;    		memcpy(lp->txdmabuf, &lp->sndbuf->data[1], length);    		/* Setup DMA controller for Tx */    		setup_tx_dma(lp, length);    		enable_dma(lp->dmachan);    		/* Reset CRC, Txint pending */    		wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC | RES_Tx_P);    		/* Allow underrun 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);    		lp->tstate = ACTIVE;    		break;    	}        /* Get first char to send */        lp->txcnt--;        c = *lp->txptr++;        /* Reset CRC for next frame */        wrtscc(lp->cardbase, cmd, R0, RES_Tx_CRC);        /* send abort on underrun */        if (lp->nrzi)        {            wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI | ABUNDER);        } else {            wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZ | ABUNDER);        }        /* send first char */        wrtscc(lp->cardbase, cmd, R8, c);        /* Reset end of message latch */        wrtscc(lp->cardbase, cmd, R0, RES_EOM_L);        /* stuff an extra one in *//*        while ((rdscc(lp->cardbase, cmd, R0) & Tx_BUF_EMP) && lp->txcnt)        {            lp->txcnt--;            c = *lp->txptr++;            wrtscc(lp->cardbase, cmd, R8, c);        }*/        /* select Tx interrupts to enable */        /* Allow underrun int only */        wrtscc(lp->cardbase, cmd, R15, TxUIE);        /* Reset external interrupts */        wrtscc(lp->cardbase, cmd, R0, RES_EXT_INT);        /* Tx and Rx ints enabled */        wrtscc(lp->cardbase, cmd, R1, TxINT_ENAB | EXT_INT_ENAB);        lp->tstate = ACTIVE;        restore_flags(flags);        return;        /* slotime has timed out */    case DEFER:        /* 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, DCDIE);            restore_flags(flags);            return;        }        if (random() > lp->persist)        {            lp->tstate = DEFER;            tdelay(lp, lp->slotime);            restore_flags(flags);            return;        }        if (lp->dmachan)        	wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | Tx8);        pt_rts(lp, ON);			/* Tx on */        lp->tstate = ST_TXDELAY;        tdelay(lp, lp->txdelay);        restore_flags(flags);        return; 	/* Only for int driven parts */ 	if (lp->dmachan) 	{ 		restore_flags(flags); 		return; 	}    } /* end switch */    /*     * Rx mode only     * This triggers when hunt mode is entered, & since an ABORT     * automatically enters hunt mode, we use that to clean up     * any waiting garbage     */    if ((lp->rstate == ACTIVE) && (st & BRK_ABRT) )    {#ifdef PT_DEBUG	printk(KERN_DEBUG "PT: exisr(): abort detected.\n");#endif  		/* read and dump all of SCC Rx FIFO */        (void) rdscc(lp->cardbase, cmd, R8);        (void) rdscc(lp->cardbase, cmd, R8);        (void) rdscc(lp->cardbase, cmd, R8);        lp->rcp = lp->rcvbuf->data;        lp->rcvbuf->cnt = 0;		/* Re-sync the SCC */		wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);    }    /* Check for DCD transitions */    if ( (st & DCD) != (lp->saved_RR0 & DCD))    {#ifdef PT_DEBUG        printk(KERN_DEBUG "PT: pt_exisr(): DCD is now %s.\n", (st & DCD)? "ON" : "OFF" );#endif		if (st & DCD)		{			/* Check that we don't already have some data */			if (lp->rcvbuf->cnt > 0)			{#ifdef PT_DEBUG				printk(KERN_DEBUG "PT: pt_exisr() dumping %u bytes from buffer.\n", lp->rcvbuf->cnt);#endif				/* wind back buffers */				lp->rcp = lp->rcvbuf->data;				lp->rcvbuf->cnt = 0;			}		} else {  /* DCD off */			/* read and dump al SCC FIFO */			(void)rdscc(lp->cardbase, cmd, R8);			(void)rdscc(lp->cardbase, cmd, R8);			(void)rdscc(lp->cardbase, cmd, R8);			/* wind back buffers */			lp->rcp = lp->rcvbuf->data;			lp->rcvbuf->cnt = 0;			/* Re-sync the SCC */			wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);		}    }    /* Update the saved version of register RR) */    lp->saved_RR0 = st &~ ZCOUNT;    restore_flags(flags);} /* pt_exisr() */#ifdef MODULEEXPORT_NO_SYMBOLS;MODULE_AUTHOR("Craig Small VK2XLZ <vk2xlz@vk2xlz.ampr.org>");MODULE_DESCRIPTION("AX.25 driver for the Gracillis PacketTwin HDLC card");int init_module(void){	return pt_init();}void cleanup_module(void){	free_irq(pt0a.irq, &pt0a);	/* IRQs and IO Ports are shared */	release_region(pt0a.base_addr & 0x3f0, PT_TOTAL_SIZE);	kfree(pt0a.priv);	pt0a.priv = NULL;	unregister_netdev(&pt0a);	kfree(pt0b.priv);	pt0b.priv = NULL;	unregister_netdev(&pt0b);}#endif

⌨️ 快捷键说明

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