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

📄 xirc2ps_cs.c

📁 h内核
💻 C
📖 第 1 页 / 共 4 页
字号:
	 */	reg.Action = CS_WRITE;	reg.Offset = CISREG_IOBASE_0;	reg.Value = link->io.BasePort2 & 0xff;	if ((err = pcmcia_access_configuration_register(link->handle, &reg))) {	    cs_error(link->handle, AccessConfigurationRegister, err);	    goto config_error;	}	reg.Action = CS_WRITE;	reg.Offset = CISREG_IOBASE_1;	reg.Value = (link->io.BasePort2 >> 8) & 0xff;	if ((err = pcmcia_access_configuration_register(link->handle, &reg))) {	    cs_error(link->handle, AccessConfigurationRegister, err);	    goto config_error;	}	/* There is no config entry for the Ethernet part which	 * is at 0x0800. So we allocate a window into the attribute	 * memory and write direct to the CIS registers	 */	req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;	req.Base = req.Size = 0;	req.AccessSpeed = 0;	if ((err = pcmcia_request_window(&link->handle, &req, &link->win))) {	    cs_error(link->handle, RequestWindow, err);	    goto config_error;	}	local->dingo_ccr = ioremap(req.Base,0x1000) + 0x0800;	mem.CardOffset = 0x0;	mem.Page = 0;	if ((err = pcmcia_map_mem_page(link->win, &mem))) {	    cs_error(link->handle, MapMemPage, err);	    goto config_error;	}	/* Setup the CCRs; there are no infos in the CIS about the Ethernet	 * part.	 */	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 = &local->node;    link->state &= ~DEV_CONFIG_PENDING;    SET_NETDEV_DEV(dev, &handle_to_dev(handle));    if ((err=register_netdev(dev))) {	printk(KNOT_XIRC "register_netdev() failed\n");	link->dev = 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;  config_error:    link->state &= ~DEV_CONFIG_PENDING;    xirc2ps_release(link);    return;  cis_error:    printk(KNOT_XIRC "unable to parse CIS\n");  failure:    link->state &= ~DEV_CONFIG_PENDING;} /* 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(dev_link_t *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_release_window(link->win);    }    pcmcia_release_configuration(link->handle);    pcmcia_release_io(link->handle, &link->io);    pcmcia_release_irq(link->handle, &link->irq);    link->state &= ~DEV_CONFIG;} /* xirc2ps_release *//*====================================================================*//**************** * The card status event handler.  Mostly, this schedules other * stuff to run after an event is received.  A CARD_REMOVAL event * also sets some flags to discourage the net drivers from trying * to talk to the card any more. * * When a CARD_REMOVAL event is received, we immediately set a flag * to block future accesses to this device.  All the functions that * actually access the device should check this flag to make sure * the card is still present. */static intxirc2ps_event(event_t event, int priority,	      event_callback_args_t * args){    dev_link_t *link = args->client_data;    struct net_device *dev = link->priv;    DEBUG(0, "event(%d)\n", (int)event);    switch (event) {    case CS_EVENT_REGISTRATION_COMPLETE:	DEBUG(0, "registration complete\n");	break;    case CS_EVENT_CARD_REMOVAL:	link->state &= ~DEV_PRESENT;	if (link->state & DEV_CONFIG)	    netif_device_detach(dev);	break;    case CS_EVENT_CARD_INSERTION:	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;	xirc2ps_config(link);	break;    case CS_EVENT_PM_SUSPEND:	link->state |= DEV_SUSPEND;	/* Fall through... */    case CS_EVENT_RESET_PHYSICAL:	if (link->state & DEV_CONFIG) {	    if (link->open) {		netif_device_detach(dev);		do_powerdown(dev);	    }	    pcmcia_release_configuration(link->handle);	}	break;    case CS_EVENT_PM_RESUME:	link->state &= ~DEV_SUSPEND;	/* Fall through... */    case CS_EVENT_CARD_RESET:	if (link->state & DEV_CONFIG) {	    pcmcia_request_configuration(link->handle, &link->conf);	    if (link->open) {		do_reset(dev,1);		netif_device_attach(dev);	    }	}	break;    }    return 0;} /* xirc2ps_event *//*====================================================================*//**************** * This is the Interrupt service route. */static irqreturn_txirc2ps_interrupt(int irq, void *dev_id, struct pt_regs *regs){    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 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 *

⌨️ 快捷键说明

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