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

📄 xirc2ps_cs.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
    unsigned bytes_rcvd;    unsigned int_status, eth_status, rx_status, tx_status;    unsigned rsr, pktlen;    ulong start_ticks = jiffies; /* fixme: jiffies rollover every 497 days				  * is this something to worry about?				  * -- on a laptop?				  */    if (!netif_device_present(dev))	return IRQ_HANDLED;    ioaddr = dev->base_addr;    if (lp->mohawk) { /* must disable the interrupt */	PutByte(XIRCREG_CR, 0);    }    DEBUG(6, "%s: interrupt %d at %#x.\n", dev->name, irq, ioaddr);    saved_page = GetByte(XIRCREG_PR);    /* Read the ISR to see whats the cause for the interrupt.     * This also clears the interrupt flags on CE2 cards     */    int_status = GetByte(XIRCREG_ISR);    bytes_rcvd = 0;  loop_entry:    if (int_status == 0xff) { /* card may be ejected */	DEBUG(3, "%s: interrupt %d for dead card\n", dev->name, irq);	goto leave;    }    eth_status = GetByte(XIRCREG_ESR);    SelectPage(0x40);    rx_status  = GetByte(XIRCREG40_RXST0);    PutByte(XIRCREG40_RXST0, (~rx_status & 0xff));    tx_status = GetByte(XIRCREG40_TXST0);    tx_status |= GetByte(XIRCREG40_TXST1) << 8;    PutByte(XIRCREG40_TXST0, 0);    PutByte(XIRCREG40_TXST1, 0);    DEBUG(3, "%s: ISR=%#2.2x ESR=%#2.2x RSR=%#2.2x TSR=%#4.4x\n",	  dev->name, int_status, eth_status, rx_status, tx_status);    /***** receive section ******/    SelectPage(0);    while (eth_status & FullPktRcvd) {	rsr = GetByte(XIRCREG0_RSR);	if (bytes_rcvd > maxrx_bytes && (rsr & PktRxOk)) {	    /* too many bytes received during this int, drop the rest of the	     * packets */	    lp->stats.rx_dropped++;	    DEBUG(2, "%s: RX drop, too much done\n", dev->name);	} else if (rsr & PktRxOk) {	    struct sk_buff *skb;	    pktlen = GetWord(XIRCREG0_RBC);	    bytes_rcvd += pktlen;	    DEBUG(5, "rsr=%#02x packet_length=%u\n", rsr, pktlen);	    skb = dev_alloc_skb(pktlen+3); /* 1 extra so we can use insw */	    if (!skb) {		printk(KNOT_XIRC "low memory, packet dropped (size=%u)\n",		       pktlen);		lp->stats.rx_dropped++;	    } else { /* okay get the packet */		skb_reserve(skb, 2);		if (lp->silicon == 0 ) { /* work around a hardware bug */		    unsigned rhsa; /* receive start address */		    SelectPage(5);		    rhsa = GetWord(XIRCREG5_RHSA0);		    SelectPage(0);		    rhsa += 3; /* skip control infos */		    if (rhsa >= 0x8000)			rhsa = 0;		    if (rhsa + pktlen > 0x8000) {			unsigned i;			u_char *buf = skb_put(skb, pktlen);			for (i=0; i < pktlen ; i++, rhsa++) {			    buf[i] = GetByte(XIRCREG_EDP);			    if (rhsa == 0x8000) {				rhsa = 0;				i--;			    }			}		    } else {			insw(ioaddr+XIRCREG_EDP,				skb_put(skb, pktlen), (pktlen+1)>>1);		    }		}	      #if 0		else if (lp->mohawk) {		    /* To use this 32 bit access we should use		     * a manual optimized loop		     * Also the words are swapped, we can get more		     * performance by using 32 bit access and swapping		     * the words in a register. Will need this for cardbus		     *		     * Note: don't forget to change the ALLOC_SKB to .. +3		     */		    unsigned i;		    u_long *p = skb_put(skb, pktlen);		    register u_long a;		    kio_addr_t edpreg = ioaddr+XIRCREG_EDP-2;		    for (i=0; i < len ; i += 4, p++) {			a = inl(edpreg);			__asm__("rorl $16,%0\n\t"				:"=q" (a)				: "0" (a));			*p = a;		    }		}	      #endif		else {		    insw(ioaddr+XIRCREG_EDP, skb_put(skb, pktlen),			    (pktlen+1)>>1);		}		skb->protocol = eth_type_trans(skb, dev);		skb->dev = dev;		netif_rx(skb);		dev->last_rx = jiffies;		lp->stats.rx_packets++;		lp->stats.rx_bytes += pktlen;		if (!(rsr & PhyPkt))		    lp->stats.multicast++;	    }	} else { /* bad packet */	    DEBUG(5, "rsr=%#02x\n", rsr);	}	if (rsr & PktTooLong) {	    lp->stats.rx_frame_errors++;	    DEBUG(3, "%s: Packet too long\n", dev->name);	}	if (rsr & CRCErr) {	    lp->stats.rx_crc_errors++;	    DEBUG(3, "%s: CRC error\n", dev->name);	}	if (rsr & AlignErr) {	    lp->stats.rx_fifo_errors++; /* okay ? */	    DEBUG(3, "%s: Alignment error\n", dev->name);	}	/* clear the received/dropped/error packet */	PutWord(XIRCREG0_DO, 0x8000); /* issue cmd: skip_rx_packet */	/* get the new ethernet status */	eth_status = GetByte(XIRCREG_ESR);    }    if (rx_status & 0x10) { /* Receive overrun */	lp->stats.rx_over_errors++;	PutByte(XIRCREG_CR, ClearRxOvrun);	DEBUG(3, "receive overrun cleared\n");    }    /***** transmit section ******/    if (int_status & PktTxed) {	unsigned n, nn;	n = lp->last_ptr_value;	nn = GetByte(XIRCREG0_PTR);	lp->last_ptr_value = nn;	if (nn < n) /* rollover */	    lp->stats.tx_packets += 256 - n;	else if (n == nn) { /* happens sometimes - don't know why */	    DEBUG(0, "PTR not changed?\n");	} else	    lp->stats.tx_packets += lp->last_ptr_value - n;	netif_wake_queue(dev);    }    if (tx_status & 0x0002) {	/* Execessive collissions */	DEBUG(0, "tx restarted due to execssive collissions\n");	PutByte(XIRCREG_CR, RestartTx);  /* restart transmitter process */    }    if (tx_status & 0x0040)	lp->stats.tx_aborted_errors++;    /* recalculate our work chunk so that we limit the duration of this     * ISR to about 1/10 of a second.     * Calculate only if we received a reasonable amount of bytes.     */    if (bytes_rcvd > 1000) {	u_long duration = jiffies - start_ticks;	if (duration >= HZ/10) { /* if more than about 1/10 second */	    maxrx_bytes = (bytes_rcvd * (HZ/10)) / duration;	    if (maxrx_bytes < 2000)		maxrx_bytes = 2000;	    else if (maxrx_bytes > 22000)		maxrx_bytes = 22000;	    DEBUG(1, "set maxrx=%u (rcvd=%u ticks=%lu)\n",		  maxrx_bytes, bytes_rcvd, duration);	} else if (!duration && maxrx_bytes < 22000) {	    /* now much faster */	    maxrx_bytes += 2000;	    if (maxrx_bytes > 22000)		maxrx_bytes = 22000;	    DEBUG(1, "set maxrx=%u\n", maxrx_bytes);	}    }  leave:    if (lockup_hack) {	if (int_status != 0xff && (int_status = GetByte(XIRCREG_ISR)) != 0)	    goto loop_entry;    }    SelectPage(saved_page);    PutByte(XIRCREG_CR, EnableIntr);  /* re-enable interrupts */    /* Instead of dropping packets during a receive, we could     * force an interrupt with this command:     *	  PutByte(XIRCREG_CR, EnableIntr|ForceIntr);     */    return IRQ_HANDLED;} /* xirc2ps_interrupt *//*====================================================================*/static voiddo_tx_timeout(struct net_device *dev){    local_info_t *lp = netdev_priv(dev);    printk(KERN_NOTICE "%s: transmit timed out\n", dev->name);    lp->stats.tx_errors++;    /* reset the card */    do_reset(dev,1);    dev->trans_start = jiffies;    netif_wake_queue(dev);}static intdo_start_xmit(struct sk_buff *skb, struct net_device *dev){    local_info_t *lp = netdev_priv(dev);    kio_addr_t ioaddr = dev->base_addr;    int okay;    unsigned freespace;    unsigned pktlen = skb? skb->len : 0;    DEBUG(1, "do_start_xmit(skb=%p, dev=%p) len=%u\n",	  skb, dev, pktlen);    /* adjust the packet length to min. required     * and hope that the buffer is large enough     * to provide some random data.     * fixme: For Mohawk we can change this by sending     * a larger packetlen than we actually have; the chip will     * pad this in his buffer with random bytes     */    if (pktlen < ETH_ZLEN)    {        skb = skb_padto(skb, ETH_ZLEN);        if (skb == NULL)        	return 0;	pktlen = ETH_ZLEN;    }    netif_stop_queue(dev);    SelectPage(0);    PutWord(XIRCREG0_TRS, (u_short)pktlen+2);    freespace = GetWord(XIRCREG0_TSO);    okay = freespace & 0x8000;    freespace &= 0x7fff;    /* TRS doesn't work - (indeed it is eliminated with sil-rev 1) */    okay = pktlen +2 < freespace;    DEBUG(2 + (okay ? 2 : 0), "%s: avail. tx space=%u%s\n",	  dev->name, freespace, okay ? " (okay)":" (not enough)");    if (!okay) { /* not enough space */	return 1;  /* upper layer may decide to requeue this packet */    }    /* send the packet */    PutWord(XIRCREG_EDP, (u_short)pktlen);    outsw(ioaddr+XIRCREG_EDP, skb->data, pktlen>>1);    if (pktlen & 1)	PutByte(XIRCREG_EDP, skb->data[pktlen-1]);    if (lp->mohawk)	PutByte(XIRCREG_CR, TransmitPacket|EnableIntr);    dev_kfree_skb (skb);    dev->trans_start = jiffies;    lp->stats.tx_bytes += pktlen;    netif_start_queue(dev);    return 0;}static struct net_device_stats *do_get_stats(struct net_device *dev){    local_info_t *lp = netdev_priv(dev);    /*	lp->stats.rx_missed_errors = GetByte(?) */    return &lp->stats;}/**************** * Set all addresses: This first one is the individual address, * the next 9 addresses are taken from the multicast list and * the rest is filled with the individual address. */static voidset_addresses(struct net_device *dev){    kio_addr_t ioaddr = dev->base_addr;    local_info_t *lp = netdev_priv(dev);    struct dev_mc_list *dmi = dev->mc_list;    char *addr;    int i,j,k,n;    SelectPage(k=0x50);    for (i=0,j=8,n=0; ; i++, j++) {	if (i > 5) {	    if (++n > 9)		break;	    i = 0;	}	if (j > 15) {	    j = 8;	    k++;	    SelectPage(k);	}	if (n && n <= dev->mc_count && dmi) {	    addr = dmi->dmi_addr;	    dmi = dmi->next;	} else	    addr = dev->dev_addr;	if (lp->mohawk)	    PutByte(j, addr[5-i]);	else	    PutByte(j, addr[i]);    }    SelectPage(0);}/**************** * Set or clear the multicast filter for this adaptor. * We can filter up to 9 addresses, if more are requested we set * multicast promiscuous mode. */static voidset_multicast_list(struct net_device *dev){    kio_addr_t ioaddr = dev->base_addr;    SelectPage(0x42);    if (dev->flags & IFF_PROMISC) { /* snoop */	PutByte(XIRCREG42_SWC1, 0x06); /* set MPE and PME */    } else if (dev->mc_count > 9 || (dev->flags & IFF_ALLMULTI)) {	PutByte(XIRCREG42_SWC1, 0x06); /* set MPE */    } else if (dev->mc_count) {	/* the chip can filter 9 addresses perfectly */	PutByte(XIRCREG42_SWC1, 0x00);	SelectPage(0x40);	PutByte(XIRCREG40_CMD0, Offline);	set_addresses(dev);	SelectPage(0x40);	PutByte(XIRCREG40_CMD0, EnableRecv | Online);    } else { /* standard usage */	PutByte(XIRCREG42_SWC1, 0x00);    }    SelectPage(0);}static intdo_config(struct net_device *dev, struct ifmap *map){    local_info_t *local = netdev_priv(dev);    DEBUG(0, "do_config(%p)\n", dev);    if (map->port != 255 && map->port != dev->if_port) {	if (map->port > 4)	    return -EINVAL;	if (!map->port) {	    local->probe_port = 1;	    dev->if_port = 1;	} else {	    local->probe_port = 0;	    dev->if_port = map->port;	}	printk(KERN_INFO "%s: switching to %s port\n",	       dev->name, if_names[dev->if_port]);	do_reset(dev,1);  /* not the fine way :-) */    }    return 0;}/**************** * Open the driver */static intdo_open(struct net_device *dev){    local_info_t *lp = netdev_priv(dev);    dev_link_t *link = &lp->link;    DEBUG(0, "do_open(%p)\n", dev);    /* Check that the PCMCIA card is still here. */    /* Physical device present signature. */    if (!DEV_OK(link))	return -ENODEV;    /* okay */    link->open++;    netif_start_queue(dev);    do_reset(dev,1);    return 0;

⌨️ 快捷键说明

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