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

📄 xirc2ps_cs.c

📁 pcmcia驱动源代码,直接可以在linux2.6下使用 !
💻 C
📖 第 1 页 / 共 4 页
字号:
	writeb(0x47, local->dingo_ccr + CISREG_COR);	ioaddr = link->io.BasePort1;	writeb(ioaddr & 0xff	  , local->dingo_ccr + CISREG_IOBASE_0);	writeb((ioaddr >> 8)&0xff , local->dingo_ccr + CISREG_IOBASE_1);      #if 0	{	    u_char tmp;	    printk(KERN_INFO "ECOR:");	    for (i=0; i < 7; i++) {		tmp = readb(local->dingo_ccr + i*2);		printk(" %02x", tmp);	    }	    printk("\n");	    printk(KERN_INFO "DCOR:");	    for (i=0; i < 4; i++) {		tmp = readb(local->dingo_ccr + 0x20 + i*2);		printk(" %02x", tmp);	    }	    printk("\n");	    printk(KERN_INFO "SCOR:");	    for (i=0; i < 10; i++) {		tmp = readb(local->dingo_ccr + 0x40 + i*2);		printk(" %02x", tmp);	    }	    printk("\n");	}      #endif	writeb(0x01, local->dingo_ccr + 0x20);	writeb(0x0c, local->dingo_ccr + 0x22);	writeb(0x00, local->dingo_ccr + 0x24);	writeb(0x00, local->dingo_ccr + 0x26);	writeb(0x00, local->dingo_ccr + 0x28);    }    /* The if_port symbol can be set when the module is loaded */    local->probe_port=0;    if (!if_port) {	local->probe_port = dev->if_port = 1;    } else if ((if_port >= 1 && if_port <= 2) ||	       (local->mohawk && if_port==4))	dev->if_port = if_port;    else	printk(KNOT_XIRC "invalid if_port requested\n");    /* we can now register the device with the net subsystem */    dev->irq = link->irq.AssignedIRQ;    dev->base_addr = link->io.BasePort1;    if (local->dingo)	do_reset(dev, 1); /* a kludge to make the cem56 work */    link->dev_node = &local->node;    SET_NETDEV_DEV(dev, &handle_to_dev(link));    if ((err=register_netdev(dev))) {	printk(KNOT_XIRC "register_netdev() failed\n");	link->dev_node = NULL;	goto config_error;    }    strcpy(local->node.dev_name, dev->name);    /* give some infos about the hardware */    printk(KERN_INFO "%s: %s: port %#3lx, irq %d, hwaddr",	 dev->name, local->manf_str,(u_long)dev->base_addr, (int)dev->irq);    for (i = 0; i < 6; i++)	printk("%c%02X", i?':':' ', dev->dev_addr[i]);    printk("\n");    return 0;  config_error:    xirc2ps_release(link);    return -ENODEV;  failure:    return -ENODEV;} /* xirc2ps_config *//**************** * After a card is removed, xirc2ps_release() will unregister the net * device, and release the PCMCIA configuration.  If the device is * still open, this will be postponed until it is closed. */static voidxirc2ps_release(struct pcmcia_device *link){	DEBUG(0, "release(0x%p)\n", link);	if (link->win) {		struct net_device *dev = link->priv;		local_info_t *local = netdev_priv(dev);		if (local->dingo)			iounmap(local->dingo_ccr - 0x0800);	}	pcmcia_disable_device(link);} /* xirc2ps_release *//*====================================================================*/static int xirc2ps_suspend(struct pcmcia_device *link){	struct net_device *dev = link->priv;	if (link->open) {		netif_device_detach(dev);		do_powerdown(dev);	}	return 0;}static int xirc2ps_resume(struct pcmcia_device *link){	struct net_device *dev = link->priv;	if (link->open) {		do_reset(dev,1);		netif_device_attach(dev);	}	return 0;}/*====================================================================*//**************** * This is the Interrupt service route. */static irqreturn_txirc2ps_interrupt(int irq, void *dev_id){    struct net_device *dev = (struct net_device *)dev_id;    local_info_t *lp = netdev_priv(dev);    kio_addr_t ioaddr;    u_char saved_page;    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 voidxirc2ps_tx_timeout_task(struct work_struct *work){	local_info_t *local =		container_of(work, local_info_t, tx_timeout_task);	struct net_device *dev = local->dev;    /* reset the card */    do_reset(dev,1);    dev->trans_start = jiffies;    netif_wake_queue(dev);}static voiddo_tx_timeout(struct net_device *dev){    local_info_t *lp = netdev_priv(dev);    lp->stats.tx_errors++;    printk(KERN_NOTICE "%s: transmit timed out\n", dev->name);    schedule_work(&lp->tx_timeout_task);}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->len;    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)    {        if (skb_padto(skb, ETH_ZLEN))        	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.

⌨️ 快捷键说明

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