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

📄 sk_g16.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
/*- * Function       : SK_lance_init * Author         : Patrick J.D. Weichmann * Date Created   : 94/05/26 * * Description    : Reset LANCE chip, fill RMD, TMD structures with *                  start values and Start LANCE. * * Parameters     : I : struct net_device *dev - SK_G16 device structure *                  I : int mode - put LANCE into "mode" see data-sheet for *                                 more info. * Return Value   : 0  - Init done * Errors         : -1 - Init failed * Update History : *     YY/MM/DD  uid  Description-*/static int SK_lance_init(struct net_device *dev, unsigned short mode){    int i;    unsigned long flags;    struct priv *p = (struct priv *) dev->priv;     struct tmd  *tmdp;    struct rmd  *rmdp;    PRINTK(("## %s: At beginning of LANCE init. CSR0: %#06x\n",            SK_NAME, SK_read_reg(CSR0)));    /* Reset LANCE */    SK_reset_board();    /* Initialize TMD's with start values */    p->tmdnum = 0;                   /* First descriptor for transmitting */     p->tmdlast = 0;                  /* First descriptor for reading stats */    for (i = 0; i < TMDNUM; i++)     /* Init all TMD's */    {	tmdp = p->tmdhead + i;    	writel((unsigned long) p->tmdbufs[i], tmdp->u.buffer); /* assign buffer */		/* Mark TMD as start and end of packet */	writeb(TX_STP | TX_ENP, &tmdp->u.s.status);    }    /* Initialize RMD's with start values */    p->rmdnum = 0;                   /* First RMD which will be used */     for (i = 0; i < RMDNUM; i++)     /* Init all RMD's */    {	rmdp = p->rmdhead + i;		writel((unsigned long) p->rmdbufs[i], rmdp->u.buffer); /* assign buffer */		/*          * LANCE must be owner at beginning so that he can fill in 	 * receiving packets, set status and release RMD 	 */	writeb(RX_OWN, &rmdp->u.s.status);	writew(-PKT_BUF_SZ, &rmdp->blen); /* Buffer Size (two's complement) */	writeb(0, &rmdp->mlen);           /* init message length */       	    }    /* Fill LANCE Initialize Block */    writew(mode, (&((p->ram)->ib.mode))); /* Set operation mode */    for (i = 0; i < ETH_ALEN; i++)   /* Set physical address */    {	writeb(dev->dev_addr[i], (&((p->ram)->ib.paddr[i])));     }    for (i = 0; i < 8; i++)          /* Set multicast, logical address */    {	writeb(0, (&((p->ram)->ib.laddr[i]))); /* We do not use logical addressing */    }     /* Set ring descriptor pointers and set number of descriptors */    writel((int)p->rmdhead | RMDNUMMASK, (&((p->ram)->ib.rdrp)));    writel((int)p->tmdhead | TMDNUMMASK, (&((p->ram)->ib.tdrp)));    /* Prepare LANCE Control and Status Registers */    spin_lock_irqsave(&SK_lock, flags);    SK_write_reg(CSR3, CSR3_ACON);   /* Ale Control !!!THIS MUST BE SET!!!! */     /*      * LANCE addresses the RAM from 0x0000 to 0x3fbf and has no access to     * PC Memory locations.     *     * In structure SK_ram is defined that the first thing in ram     * is the initialization block. So his address is for LANCE always     * 0x0000     *     * CSR1 contains low order bits 15:0 of initialization block address     * CSR2 is built of:      *    7:0  High order bits 23:16 of initialization block address     *   15:8  reserved, must be 0     */        /* Set initialization block address (must be on word boundary) */    SK_write_reg(CSR1, 0);          /* Set low order bits 15:0 */    SK_write_reg(CSR2, 0);          /* Set high order bits 23:16 */         PRINTK(("## %s: After setting CSR1-3. CSR0: %#06x\n",            SK_NAME, SK_read_reg(CSR0)));    /* Initialize LANCE */    /*      * INIT = Initialize, when set, causes the LANCE to begin the     * initialization procedure and access the Init Block.     */    SK_write_reg(CSR0, CSR0_INIT);     spin_unlock_irqrestore(&SK_lock, flags);    /* Wait until LANCE finished initialization */        SK_set_RAP(CSR0);              /* Register Address Pointer to CSR0 */    for (i = 0; (i < 100) && !(SK_rread_reg() & CSR0_IDON); i++) 	; /* Wait until init done or go ahead if problems (i>=100) */    if (i >= 100) /* Something is wrong ! */    {	printk("%s: can't init am7990, status: %04x "	       "init_block: %#08x\n", 		dev->name, (int) SK_read_reg(CSR0), 		(unsigned int) &(p->ram)->ib);#ifdef SK_DEBUG	SK_print_pos(dev, "LANCE INIT failed");	SK_print_dev(dev,"Device Structure:");#endif	return -1;                 /* LANCE init failed */    }    PRINTK(("## %s: init done after %d ticks\n", SK_NAME, i));    /* Clear Initialize done, enable Interrupts, start LANCE */    SK_write_reg(CSR0, CSR0_IDON | CSR0_INEA | CSR0_STRT);    PRINTK(("## %s: LANCE started. CSR0: %#06x\n", SK_NAME,             SK_read_reg(CSR0)));    return 0;                      /* LANCE is up and running */} /* End of SK_lance_init() *//*- * Function       : SK_send_packet * Author         : Patrick J.D. Weichmann * Date Created   : 94/05/27 * * Description    : Writes an socket buffer into a transmit descriptor *                  and starts transmission. * * Parameters     : I : struct sk_buff *skb - packet to transfer *                  I : struct net_device *dev  - SK_G16 device structure * Return Value   : 0 - OK *                  1 - Could not transmit (dev_queue_xmit will queue it) *                      and try to sent it later * Globals        : None * Side Effects   : None * Update History : *     YY/MM/DD  uid  Description-*/static void SK_timeout(struct net_device *dev){	printk(KERN_WARNING "%s: xmitter timed out, try to restart!\n", dev->name);	SK_lance_init(dev, MODE_NORMAL); /* Reinit LANCE */	netif_wake_queue(dev);		 /* Clear Transmitter flag */	dev->trans_start = jiffies;      /* Mark Start of transmission */}static int SK_send_packet(struct sk_buff *skb, struct net_device *dev){    struct priv *p = (struct priv *) dev->priv;    struct tmd *tmdp;    PRINTK2(("## %s: SK_send_packet() called, CSR0 %#04x.\n", 	    SK_NAME, SK_read_reg(CSR0)));    /*      * Block a timer-based transmit from overlapping.      * This means check if we are already in.      */    netif_stop_queue (dev);    {	/* Evaluate Packet length */	short len = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;        	tmdp = p->tmdhead + p->tmdnum; /* Which descriptor for transmitting */	/* Fill in Transmit Message Descriptor */	/* Copy data into dual ported ram */	memcpy_toio((tmdp->u.buffer & 0x00ffffff), skb->data, skb->len);	writew(-len, &tmdp->blen);            /* set length to transmit */	/* 	 * Packet start and end is always set because we use the maximum	 * packet length as buffer length.	 * Relinquish ownership to LANCE	 */	writeb(TX_OWN | TX_STP | TX_ENP, &tmdp->u.s.status);		/* Start Demand Transmission */	SK_write_reg(CSR0, CSR0_TDMD | CSR0_INEA);	dev->trans_start = jiffies;   /* Mark start of transmission */	/* Set pointer to next transmit buffer */	p->tmdnum++; 	p->tmdnum &= TMDNUM-1; 	/* Do we own the next transmit buffer ? */	if (! (readb(&((p->tmdhead + p->tmdnum)->u.s.status)) & TX_OWN) )	{	   /* 	    * We own next buffer and are ready to transmit, so	    * clear busy flag	    */	   netif_start_queue(dev);	}	p->stats.tx_bytes += skb->len;    }    dev_kfree_skb(skb);    return 0;  } /* End of SK_send_packet *//*- * Function       : SK_interrupt * Author         : Patrick J.D. Weichmann * Date Created   : 94/05/27 * * Description    : SK_G16 interrupt handler which checks for LANCE *                  Errors, handles transmit and receive interrupts * * Parameters     : I : int irq, void *dev_id, struct pt_regs * regs - * Return Value   : None * Errors         : None * Globals        : None * Side Effects   : None * Update History : *     YY/MM/DD  uid  Description-*/static void SK_interrupt(int irq, void *dev_id, struct pt_regs * regs){    int csr0;    struct net_device *dev = dev_id;    struct priv *p = (struct priv *) dev->priv;    PRINTK2(("## %s: SK_interrupt(). status: %#06x\n",             SK_NAME, SK_read_reg(CSR0)));    if (dev == NULL)    {	printk("SK_interrupt(): IRQ %d for unknown device.\n", irq);    }        spin_lock (&SK_lock);    csr0 = SK_read_reg(CSR0);      /* store register for checking */    /*      * Acknowledge all of the current interrupt sources, disable           * Interrupts (INEA = 0)      */    SK_write_reg(CSR0, csr0 & CSR0_CLRALL);     if (csr0 & CSR0_ERR) /* LANCE Error */    {	printk("%s: error: %04x\n", dev->name, csr0);              if (csr0 & CSR0_MISS)      /* No place to store packet ? */        {             p->stats.rx_dropped++;        }    }    if (csr0 & CSR0_RINT)          /* Receive Interrupt (packet arrived) */     {	SK_rxintr(dev);     }    if (csr0 & CSR0_TINT)          /* Transmit interrupt (packet sent) */    {	SK_txintr(dev);    }    SK_write_reg(CSR0, CSR0_INEA); /* Enable Interrupts */    spin_unlock (&SK_lock);} /* End of SK_interrupt() */ /*- * Function       : SK_txintr * Author         : Patrick J.D. Weichmann * Date Created   : 94/05/27 * * Description    : After sending a packet we check status, update *                  statistics and relinquish ownership of transmit  *                  descriptor ring. * * Parameters     : I : struct net_device *dev - SK_G16 device structure * Return Value   : None * Errors         : None * Globals        : None * Update History : *     YY/MM/DD  uid  Description-*/static void SK_txintr(struct net_device *dev){    int tmdstat;    struct tmd *tmdp;    struct priv *p = (struct priv *) dev->priv;    PRINTK2(("## %s: SK_txintr() status: %#06x\n",             SK_NAME, SK_read_reg(CSR0)));    tmdp = p->tmdhead + p->tmdlast;     /* Which buffer we sent at last ? */    /* Set next buffer */    p->tmdlast++;    p->tmdlast &= TMDNUM-1;    tmdstat = readb(&tmdp->u.s.status);    /*      * We check status of transmitted packet.     * see LANCE data-sheet for error explanation     */    if (tmdstat & TX_ERR) /* Error occurred */    {	int stat2 = readw(&tmdp->status2);	printk("%s: TX error: %04x %04x\n", dev->name, tmdstat, stat2);	if (stat2 & TX_TDR)    /* TDR problems? */	{	    printk("%s: tdr-problems \n", dev->name);	}	if (stat2 & TX_RTRY)   /* Failed in 16 attempts to transmit ? */            p->stats.tx_aborted_errors++;           if (stat2 & TX_LCOL)   /* Late collision ? */            p->stats.tx_window_errors++; 	if (stat2 & TX_LCAR)   /* Loss of Carrier ? */              p->stats.tx_carrier_errors++;        if (stat2 & TX_UFLO)   /* Underflow error ? */        {            p->stats.tx_fifo_errors++;            /*              * If UFLO error occurs it will turn transmitter of.             * So we must reinit LANCE             */            SK_lance_init(dev, MODE_NORMAL);        }		p->stats.tx_errors++;	writew(0, &tmdp->status2);             /* Clear error flags */    }    else if (tmdstat & TX_MORE)        /* Collisions occurred ? */    {        /*          * Here I have a problem.         * I only know that there must be one or up to 15 collisions.         * That's why TX_MORE is set, because after 16 attempts TX_RTRY         * will be set which means couldn't send packet aborted transfer.         *         * First I did not have this in but then I thought at minimum         * we see that something was not ok.         * If anyone knows something better than this to handle this         * please report it.         */         p->stats.collisions++;     }    else   /* Packet sent without any problems */    {        p->stats.tx_packets++;     }    /*      * We mark transmitter not busy anymore, because now we have a free     * transmit descriptor which can be filled by SK_send_packet and     * afterwards sent by the LANCE     *      * The function which do handle slow IRQ parts is do_bottom_half()     * which runs at normal kernel priority, that means all interrupt are     * enabled. (see kernel/irq.c)     *       * net_bh does something like this:     *  - check if already in net_bh     *  - try to transmit something from the send queue     *  - if something is in the receive queue send it up to higher      *    levels if it is a known protocol     *  - try to transmit something from the send queue     */    netif_wake_queue(dev);} /* End of SK_txintr() *//*- * Function       : SK_rxintr * Author         : Patrick J.D. Weichmann * Date Created   : 94/05/27 * * Description    : Buffer sent, check for errors, relinquish ownership *                  of the receive message descriptor.  * * Parameters     : I : SK_G16 device structure * Return Value   : None * Globals        : None * Update History : *     YY/MM/DD  uid  Description-*/static void SK_rxintr(struct net_device *dev){    struct rmd *rmdp;    int rmdstat;    struct priv *p = (struct priv *) dev->priv;    PRINTK2(("## %s: SK_rxintr(). CSR0: %#06x\n",             SK_NAME, SK_read_reg(CSR0)));    rmdp = p->rmdhead + p->rmdnum;    /* As long as we own the next entry, check status and send     * it up to higher layer      */    while (!( (rmdstat = readb(&rmdp->u.s.status)) & RX_OWN))    {	/*          * Start and end of packet must be set, because we use 	 * the ethernet maximum packet length (1518) as buffer size.	 * 	 * Because our buffers are at maximum OFLO and BUFF errors are	 * not to be concerned (see Data sheet)	 */	if ((rmdstat & (RX_STP | RX_ENP)) != (RX_STP | RX_ENP))	{	    /* Start of a frame > 1518 Bytes ? */	    if (rmdstat & RX_STP) 	    {		p->stats.rx_errors++;        /* bad packet received */		p->stats.rx_length_errors++; /* packet too long */		printk("%s: packet too long\n", dev->name);	    }	    	    /*              * All other packets will be ignored until a new frame with	     * start (RX_STP) set follows.	     * 	     * What we do is just give descriptor free for new incoming	     * packets. 	     */	    writeb(RX_OWN, &rmdp->u.s.status); /* Relinquish ownership to LANCE */ 	}	else if (rmdstat & RX_ERR)          /* Receive Error ? */	{	    printk("%s: RX error: %04x\n", dev->name, (int) rmdstat);	    	    p->stats.rx_errors++;	    if (rmdstat & RX_FRAM) p->stats.rx_frame_errors++;	    if (rmdstat & RX_CRC)  p->stats.rx_crc_errors++;	    writeb(RX_OWN, &rmdp->u.s.status); /* Relinquish ownership to LANCE */	}	else /* We have a packet which can be queued for the upper layers */	{	    int len = readw(&rmdp->mlen) & 0x0fff;  /* extract message length from receive buffer */	    struct sk_buff *skb;	    skb = dev_alloc_skb(len+2); /* allocate socket buffer */ 	    if (skb == NULL)                /* Could not get mem ? */	    {    		/* 

⌨️ 快捷键说明

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