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

📄 pt.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
        {            if (request_dma(dev->dma, "pt"))            {                free_irq(dev->irq, dev);                return -EAGAIN;            }        }         /* Reset hardware */         chipset_init(dev);     }     lp->tstate = IDLE;     if (dev->base_addr & CHANA)     {         scc_init(dev);         scc_init(dev->next);     }     /* Save a copy of register RR0 for comparing with later on */     /* We always put 0 in zero count */     lp->saved_RR0 = rdscc(lp->cardbase, lp->base + CTL, R0) & ~ZCOUNT;    /* master interrupt enable */    save_flags(flags);    cli();    wrtscc(lp->cardbase, lp->base + CTL, R9, MIE | NV);    outb_p( pt_sercfg |= PT_EI, lp->cardbase + INT_CFG);    restore_flags(flags);    lp->open_time = jiffies;    dev->tbusy = 0;    dev->interrupt = 0;    dev->start = 1;    first_time = 0;    MOD_INC_USE_COUNT;    return 0;} /* pt_open() */static int pt_send_packet(struct sk_buff *skb, struct device *dev){	struct pt_local *lp = (struct pt_local *) dev->priv;#ifdef PT_DEBUG	printk(KERN_DEBUG "PT: pt_send_packet(): (%d)\n", lp->base & CHANA);#endif	hardware_send_packet(lp, skb);	dev->trans_start = jiffies;	return 0;}/* The inverse routine to pt_open() */static int pt_close(struct device *dev){	unsigned long flags;	struct pt_local *lp = dev->priv;	struct sk_buff *ptr = NULL;	int cmd;	cmd = lp->base + CTL;	save_flags(flags);	cli();	/* Reset SCC or channel */	chipset_init(dev);	disable_dma(lp->dmachan);	lp->open_time = 0;	dev->tbusy = 1;	dev->start = 0;	/* Free any buffers left in the hardware transmit queue */	while ((ptr = skb_dequeue(&lp->sndq)) != NULL)		kfree_skb(ptr);	restore_flags(flags);#ifdef PT_DEBUG	printk(KERN_DEBUG "PT: pt_close(): Closing down channel (%d).\n", lp->base & CHANA);#endif	MOD_DEC_USE_COUNT;	return 0;} /* pt_close() */static int pt_ioctl(struct device *dev, struct ifreq *ifr, int cmd){    unsigned long flags;    struct pt_req rq;    struct pt_local *lp = (struct pt_local *) dev->priv;    int ret = verify_area(VERIFY_WRITE, ifr->ifr_data, sizeof(struct pt_req));    if (ret)	return ret;    if (cmd != SIOCDEVPRIVATE)        return -EINVAL;    copy_from_user(&rq, ifr->ifr_data, sizeof(struct pt_req));    switch (rq.cmd) {    case SIOCSPIPARAM:	if (!suser())	    return -EPERM;	save_flags(flags);	cli();	lp->txdelay = rq.txdelay;	lp->persist = rq.persist;	lp->slotime = rq.slotime;	lp->squeldelay = rq.squeldelay;	lp->clockmode = rq.clockmode;	lp->speed = rq.speed;	pt_open(&pt0a);	restore_flags(flags);	ret = 0;	break;    case SIOCSPIDMA:	if (!suser())	    return -EPERM;	ret = 0;	if (dev->base_addr & CHANA) {   /* if A channel */	   if (rq.dmachan < 1 || rq.dmachan > 3)		return -EINVAL;	   save_flags(flags);	   cli();	   pt_close(dev);	   free_dma(lp->dmachan);	   dev->dma = lp->dmachan = rq.dmachan;	   if (request_dma(lp->dmachan,"pt"))		ret = -EAGAIN;	   pt_open(dev);	   restore_flags(flags);	}	break;    case SIOCSPIIRQ:	ret = -EINVAL;      /* add this later */	break;    case SIOCGPIPARAM:    case SIOCGPIDMA:    case SIOCGPIIRQ:	rq.speed = lp->speed;	rq.txdelay = lp->txdelay;	rq.persist = lp->persist;	rq.slotime = lp->slotime;	rq.squeldelay = lp->squeldelay;	rq.clockmode = lp->clockmode;	rq.dmachan = lp->dmachan;	rq.irq = dev->irq;	copy_to_user(ifr->ifr_data, &rq, sizeof(struct pt_req));	ret = 0;	break;    default:	ret = -EINVAL;    }    return ret;}/* *	Get the current statistics. *	This may be called with the card open or closed.  */ static struct net_device_stats *pt_get_stats(struct device *dev){	struct pt_local *lp = (struct pt_local *) dev->priv;	return &lp->stats;}/* * Local variables: *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c skeleton.c" *  version-control: t *  kept-new-versions: 5 *  tab-width: 4 * End: */static void tdelay(struct pt_local *lp, int time){	/* For some reason, we turn off the Tx interrupts here! */	if (!lp->dmachan)		wrtscc(lp->cardbase, lp->base + CTL, R1, INT_ALL_Rx | EXT_INT_ENAB);	if (lp->base & CHANA) 	{		outb_p(time & 0xff, lp->cardbase + TMR1);		outb_p((time >> 8)&0xff, lp->cardbase + TMR1);	}	else	{		outb_p(time & 0xff, lp->cardbase + TMR2);		outb_p((time >> 8)&0xff, lp->cardbase + TMR2);	}} /* tdelay */static void pt_txisr(struct pt_local *lp){	unsigned long flags;	int cmd;	unsigned char c;	save_flags(flags);	cli();	cmd = lp->base + CTL;#ifdef PT_DEBUG	printk(KERN_DEBUG "PT: pt_txisr(): tstate = %d (%d).\n", lp->tstate, lp->base & CHANA);#endif	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	         */	        pt_rts(lp, OFF);	        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;		}	    /* If a buffer to send, drop though here */	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;	    }	    pt_rts(lp, ON);		/* Tx on */	    if (lp->dmachan)	    	wrtscc(lp->cardbase, cmd, R5, TxCRC_ENAB | RTS | Tx8);	    lp->tstate = ST_TXDELAY;	    tdelay(lp, lp->txdelay);	    restore_flags(flags);	    return;	case ACTIVE:	    /* Here we are actively sending a frame */	    if (lp->txcnt--)	    {	        /* XLZ - checkout Gracilis PT code to see if the while	         * loop is better or not.	         */	        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) & TxEOM))	        {	            /* Did we 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;	        /* Send flags on underrun */	       if (lp->nrzi)	       {	           wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZI);	       } else {	           wrtscc(lp->cardbase, cmd, R10, CRCPS | NRZ);	       }	       /* Reset Tx interrupt pending */	       wrtscc(lp->cardbase, cmd, R0, RES_Tx_P);	   }	   restore_flags(flags);	   return;	default:		printk(KERN_ERR "PT: pt_txisr(): Invalid tstate (%d) for chan %s.\n", lp->tstate, (cmd & CHANA? "A": "B") );		pt_rts(lp, OFF);		lp->tstate = IDLE;		break;    } 				/*switch */    restore_flags(flags);}static void pt_rxisr(struct device *dev){    struct pt_local *lp = (struct pt_local*) dev->priv;    int cmd = lp->base + CTL;    int bytecount;    unsigned long flags;    char rse;    struct sk_buff *skb;    int sksize, pkt_len;    struct mbuf *cur_buf = NULL;    unsigned char *cfix;    save_flags(flags);    cli();    /* Get status byte from R1 */    rse = rdscc(lp->cardbase, cmd, R1);#ifdef PT_DEBUG    printk(KERN_DEBUG "PT: pt_rxisr(): R1 = %#3x. (%d)\n", rse, lp->base & CHANA);#endif	if (lp->dmachan && (rse & Rx_OVR))		lp->rstate = RXERROR;    if (rdscc(lp->cardbase, cmd, R0) & Rx_CH_AV && !lp->dmachan)    {        /* There is a char to be stored         * Read special condition bits before reading the data char         */        if (rse & Rx_OVR)        {             /* Rx overrun - toss buffer */             /* wind back the pointers */             lp->rcp = lp->rcvbuf->data;             lp->rcvbuf->cnt = 0;             lp->rstate = RXERROR;             lp->stats.rx_errors++;             lp->stats.rx_fifo_errors++;         } else if (lp->rcvbuf->cnt >= lp->bufsiz)             {                 /* Too large packet                  * wind back Rx buffer pointers                  */                 lp->rcp = lp->rcvbuf->data;                 lp->rcvbuf->cnt = 0;                 lp->rstate = TOOBIG;             }         /* ok, we can store the Rx char if no errors */         if (lp->rstate == ACTIVE)         {             *lp->rcp++ = rdscc(lp->cardbase, cmd, R8);             lp->rcvbuf->cnt++;         } else {             /* we got an error, dump the FIFO */             (void) rdscc(lp->cardbase, cmd, R8);             (void) rdscc(lp->cardbase, cmd, R8);             (void) rdscc(lp->cardbase, cmd, R8);             /* Reset error latch */             wrtscc(lp->cardbase, cmd, R0, ERR_RES);             lp->rstate = ACTIVE;             /* Resync the SCC */             wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);         }     }     if (rse & END_FR)     {#ifdef PT_DEBUG	printk(KERN_DEBUG "PT: pt_rxisr() Got end of a %u byte frame.\n", lp->rcvbuf->cnt);#endif		if (lp->dmachan)		{			clear_dma_ff(lp->dmachan);			bytecount = lp->bufsiz - get_dma_residue(lp->dmachan);		} else {			bytecount = lp->rcvbuf->cnt;		}         /* END OF FRAME - Make sure Rx was active */         if (lp->rcvbuf->cnt > 0 || lp->dmachan)         {             if ((rse & CRC_ERR) || (lp->rstate > ACTIVE) || (bytecount < 10))             {                 if ((bytecount >= 10) && (rse & CRC_ERR))                 {                     lp->stats.rx_crc_errors++;                 }                 if (lp->dmachan)                 {                 	if (lp->rstate == RXERROR)                 	{                 		lp->stats.rx_errors++;                 		lp->stats.rx_over_errors++;                 	}                 	lp->rstate = ACTIVE;                 	setup_rx_dma(lp);                 } else {	                 /* wind back Rx buffer pointers */    	             lp->rcp = lp->rcvbuf->data;        	         lp->rcvbuf->cnt = 0;					/* Re-sync the SCC */					wrtscc(lp->cardbase, cmd, R3, RxENABLE | ENT_HM | AUTO_ENAB | Rx8);        	     }#ifdef PT_DEBUG	printk(KERN_DEBUG "PT: pt_rxisr() %s error.\n", (rse & CRC_ERR)? "CRC" : "state");#endif             } else {

⌨️ 快捷键说明

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