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

📄 3c589_cs.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 3 页
字号:
    dev->base_addr = link->io.BasePort1;    if (register_netdev(dev) != 0) {	printk(KERN_NOTICE "3c589_cs: register_netdev() failed\n");	goto failed;    }        ioaddr = dev->base_addr;    EL3WINDOW(0);    /* The 3c589 has an extra EEPROM for configuration info, including       the hardware address.  The 3c562 puts the address in the CIS. */    tuple.DesiredTuple = 0x88;    if (CardServices(GetFirstTuple, handle, &tuple) == CS_SUCCESS) {	CardServices(GetTupleData, handle, &tuple);	for (i = 0; i < 3; i++)	    phys_addr[i] = htons(buf[i]);    } else {	for (i = 0; i < 3; i++)	    phys_addr[i] = htons(read_eeprom(ioaddr, i));	if (phys_addr[0] == 0x6060) {	    printk(KERN_NOTICE "3c589_cs: IO port conflict at 0x%03lx"		   "-0x%03lx\n", dev->base_addr, dev->base_addr+15);	    goto failed;	}    }    strcpy(lp->node.dev_name, dev->name);    link->dev = &lp->node;    link->state &= ~DEV_CONFIG_PENDING;        /* The address and resource configuration register aren't loaded from       the EEPROM and *must* be set to 0 and IRQ3 for the PCMCIA version. */    outw(0x3f00, ioaddr + 8);    /* The if_port symbol can be set when the module is loaded */    if ((if_port >= 0) && (if_port <= 3))	dev->if_port = if_port;    else	printk(KERN_NOTICE "3c589_cs: invalid if_port requested\n");        printk(KERN_INFO "%s: 3Com 3c%s, io %#3lx, irq %d, hw_addr ",	   dev->name, (multi ? "562" : "589"), dev->base_addr,	   dev->irq);    for (i = 0; i < 6; i++)	printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));    i = inl(ioaddr);    printk(KERN_INFO "  %dK FIFO split %s Rx:Tx, %s xcvr\n",	   (i & 7) ? 32 : 8, ram_split[(i >> 16) & 3],	   if_names[dev->if_port]);    return;cs_failed:    cs_error(link->handle, last_fn, last_ret);failed:    tc589_release((u_long)link);    return;    } /* tc589_config *//*======================================================================    After a card is removed, tc589_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 void tc589_release(u_long arg){    dev_link_t *link = (dev_link_t *)arg;    DEBUG(0, "3c589_release(0x%p)\n", link);        if (link->open) {	DEBUG(1, "3c589_cs: release postponed, '%s' still open\n",	      link->dev->dev_name);	link->state |= DEV_STALE_CONFIG;	return;    }        CardServices(ReleaseConfiguration, link->handle);    CardServices(ReleaseIO, link->handle, &link->io);    CardServices(ReleaseIRQ, link->handle, &link->irq);        link->state &= ~DEV_CONFIG;    } /* tc589_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.    ======================================================================*/static int tc589_event(event_t event, int priority,		       event_callback_args_t *args){    dev_link_t *link = args->client_data;    struct el3_private *lp = link->priv;    struct net_device *dev = &lp->dev;        DEBUG(1, "3c589_event(0x%06x)\n", event);        switch (event) {    case CS_EVENT_CARD_REMOVAL:	link->state &= ~DEV_PRESENT;	if (link->state & DEV_CONFIG) {	    netif_device_detach(dev);	    mod_timer(&link->release, jiffies + HZ/20);	}	break;    case CS_EVENT_CARD_INSERTION:	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;	tc589_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);	    CardServices(ReleaseConfiguration, link->handle);	}	break;    case CS_EVENT_PM_RESUME:	link->state &= ~DEV_SUSPEND;	/* Fall through... */    case CS_EVENT_CARD_RESET:	if (link->state & DEV_CONFIG) {	    CardServices(RequestConfiguration, link->handle, &link->conf);	    if (link->open) {		tc589_reset(dev);		netif_device_attach(dev);	    }	}	break;    }    return 0;} /* tc589_event *//*====================================================================*//*  Use this for commands that may take time to finish*/static void tc589_wait_for_completion(struct net_device *dev, int cmd){    int i = 100;    outw(cmd, dev->base_addr + EL3_CMD);    while (--i > 0)	if (!(inw(dev->base_addr + EL3_STATUS) & 0x1000)) break;    if (i == 0)	printk(KERN_NOTICE "%s: command 0x%04x did not complete!\n",	       dev->name, cmd);}/*  Read a word from the EEPROM using the regular EEPROM access register.  Assume that we are in register window zero.*/static u_short read_eeprom(ioaddr_t ioaddr, int index){    int i;    outw(EEPROM_READ + index, ioaddr + 10);    /* Reading the eeprom takes 162 us */    for (i = 1620; i >= 0; i--)	if ((inw(ioaddr + 10) & EEPROM_BUSY) == 0)	    break;    return inw(ioaddr + 12);}/*  Set transceiver type, perhaps to something other than what the user  specified in dev->if_port.*/static void tc589_set_xcvr(struct net_device *dev, int if_port){    struct el3_private *lp = (struct el3_private *)dev->priv;    ioaddr_t ioaddr = dev->base_addr;        EL3WINDOW(0);    switch (if_port) {    case 0: case 1: outw(0, ioaddr + 6); break;    case 2: outw(3<<14, ioaddr + 6); break;    case 3: outw(1<<14, ioaddr + 6); break;    }    /* On PCMCIA, this just turns on the LED */    outw((if_port == 2) ? StartCoax : StopCoax, ioaddr + EL3_CMD);    /* 10baseT interface, enable link beat and jabber check. */    EL3WINDOW(4);    outw(MEDIA_LED | ((if_port < 2) ? MEDIA_TP : 0), ioaddr + WN4_MEDIA);    EL3WINDOW(1);    if (if_port == 2)	lp->media_status = ((dev->if_port == 0) ? 0x8000 : 0x4000);    else	lp->media_status = ((dev->if_port == 0) ? 0x4010 : 0x8800);}static void dump_status(struct net_device *dev){    ioaddr_t ioaddr = dev->base_addr;    EL3WINDOW(1);    printk(KERN_INFO "  irq status %04x, rx status %04x, tx status "	   "%02x  tx free %04x\n", inw(ioaddr+EL3_STATUS),	   inw(ioaddr+RX_STATUS), inb(ioaddr+TX_STATUS),	   inw(ioaddr+TX_FREE));    EL3WINDOW(4);    printk(KERN_INFO "  diagnostics: fifo %04x net %04x ethernet %04x"	   " media %04x\n", inw(ioaddr+0x04), inw(ioaddr+0x06),	   inw(ioaddr+0x08), inw(ioaddr+0x0a));    EL3WINDOW(1);}/* Reset and restore all of the 3c589 registers. */static void tc589_reset(struct net_device *dev){    ioaddr_t ioaddr = dev->base_addr;    int i;        EL3WINDOW(0);    outw(0x0001, ioaddr + 4);			/* Activate board. */     outw(0x3f00, ioaddr + 8);			/* Set the IRQ line. */        /* Set the station address in window 2. */    EL3WINDOW(2);    for (i = 0; i < 6; i++)	outb(dev->dev_addr[i], ioaddr + i);    tc589_set_xcvr(dev, dev->if_port);        /* Switch to the stats window, and clear all stats by reading. */    outw(StatsDisable, ioaddr + EL3_CMD);    EL3WINDOW(6);    for (i = 0; i < 9; i++)	inb(ioaddr+i);    inw(ioaddr + 10);    inw(ioaddr + 12);        /* Switch to register set 1 for normal use. */    EL3WINDOW(1);    /* Accept b-cast and phys addr only. */    outw(SetRxFilter | RxStation | RxBroadcast, ioaddr + EL3_CMD);    outw(StatsEnable, ioaddr + EL3_CMD); /* Turn on statistics. */    outw(RxEnable, ioaddr + EL3_CMD); /* Enable the receiver. */    outw(TxEnable, ioaddr + EL3_CMD); /* Enable transmitter. */    /* Allow status bits to be seen. */    outw(SetStatusEnb | 0xff, ioaddr + EL3_CMD);    /* Ack all pending events, and set active indicator mask. */    outw(AckIntr | IntLatch | TxAvailable | RxEarly | IntReq,	 ioaddr + EL3_CMD);    outw(SetIntrEnb | IntLatch | TxAvailable | RxComplete | StatsFull	 | AdapterFailure, ioaddr + EL3_CMD);}static int netdev_ethtool_ioctl (struct net_device *dev, void *useraddr){	u32 ethcmd;	/* dev_ioctl() in ../../net/core/dev.c has already checked	   capable(CAP_NET_ADMIN), so don't bother with that here.  */	if (get_user(ethcmd, (u32 *)useraddr))		return -EFAULT;	switch (ethcmd) {	case ETHTOOL_GDRVINFO: {		struct ethtool_drvinfo info = { ETHTOOL_GDRVINFO };		strcpy (info.driver, DRV_NAME);		strcpy (info.version, DRV_VERSION);		sprintf(info.bus_info, "PCMCIA 0x%lx", dev->base_addr);		if (copy_to_user (useraddr, &info, sizeof (info)))			return -EFAULT;		return 0;	}#ifdef PCMCIA_DEBUG	/* get message-level */	case ETHTOOL_GMSGLVL: {		struct ethtool_value edata = {ETHTOOL_GMSGLVL};		edata.data = pc_debug;		if (copy_to_user(useraddr, &edata, sizeof(edata)))			return -EFAULT;		return 0;	}	/* set message-level */	case ETHTOOL_SMSGLVL: {		struct ethtool_value edata;		if (copy_from_user(&edata, useraddr, sizeof(edata)))			return -EFAULT;		pc_debug = edata.data;		return 0;	}#endif	default:		break;	}	return -EOPNOTSUPP;}static int netdev_ioctl (struct net_device *dev, struct ifreq *rq, int cmd){	int rc;	switch (cmd) {	case SIOCETHTOOL:		rc = netdev_ethtool_ioctl(dev, (void *) rq->ifr_data);		break;	default:		rc = -EOPNOTSUPP;		break;	}	return rc;}static int el3_config(struct net_device *dev, struct ifmap *map){    if ((map->port != (u_char)(-1)) && (map->port != dev->if_port)) {	if (map->port <= 3) {	    dev->if_port = map->port;	    printk(KERN_INFO "%s: switched to %s port\n",		   dev->name, if_names[dev->if_port]);	    tc589_set_xcvr(dev, dev->if_port);	} else	    return -EINVAL;    }    return 0;}static int el3_open(struct net_device *dev){    struct el3_private *lp = (struct el3_private *)dev->priv;    dev_link_t *link = &lp->link;        if (!DEV_OK(link))	return -ENODEV;    link->open++;    MOD_INC_USE_COUNT;    netif_start_queue(dev);        tc589_reset(dev);    lp->media.function = &media_check;    lp->media.data = (u_long)lp;    lp->media.expires = jiffies + HZ;    add_timer(&lp->media);    DEBUG(1, "%s: opened, status %4.4x.\n",	  dev->name, inw(dev->base_addr + EL3_STATUS));        return 0;}static void el3_tx_timeout(struct net_device *dev){    struct el3_private *lp = (struct el3_private *)dev->priv;    ioaddr_t ioaddr = dev->base_addr;        printk(KERN_NOTICE "%s: Transmit timed out!\n", dev->name);    dump_status(dev);    lp->stats.tx_errors++;    dev->trans_start = jiffies;    /* Issue TX_RESET and TX_START commands. */    tc589_wait_for_completion(dev, TxReset);    outw(TxEnable, ioaddr + EL3_CMD);    netif_wake_queue(dev);}static void pop_tx_status(struct net_device *dev){    struct el3_private *lp = (struct el3_private *)dev->priv;    ioaddr_t ioaddr = dev->base_addr;    int i;        /* Clear the Tx status stack. */    for (i = 32; i > 0; i--) {	u_char tx_status = inb(ioaddr + TX_STATUS);	if (!(tx_status & 0x84)) break;	/* reset transmitter on jabber error or underrun */	if (tx_status & 0x30)	    tc589_wait_for_completion(dev, TxReset);	if (tx_status & 0x38) {

⌨️ 快捷键说明

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