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

📄 smc91c92_cs.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
    the revision code if successful.  Otherwise, it returns -ENODEV.======================================================================*/static int check_sig(dev_link_t *link){    struct net_device *dev = link->priv;    kio_addr_t ioaddr = dev->base_addr;    int width;    u_short s;    SMC_SELECT_BANK(1);    if (inw(ioaddr + BANK_SELECT) >> 8 != 0x33) {	/* Try powering up the chip */	outw(0, ioaddr + CONTROL);	mdelay(55);    }    /* Try setting bus width */    width = (link->io.Attributes1 == IO_DATA_PATH_WIDTH_AUTO);    s = inb(ioaddr + CONFIG);    if (width)	s |= CFG_16BIT;    else	s &= ~CFG_16BIT;    outb(s, ioaddr + CONFIG);    /* Check Base Address Register to make sure bus width is OK */    s = inw(ioaddr + BASE_ADDR);    if ((inw(ioaddr + BANK_SELECT) >> 8 == 0x33) &&	((s >> 8) != (s & 0xff))) {	SMC_SELECT_BANK(3);	s = inw(ioaddr + REVISION);	return (s & 0xff);    }    if (width) {	event_callback_args_t args;	printk(KERN_INFO "smc91c92_cs: using 8-bit IO window.\n");	args.client_data = link;	smc91c92_event(CS_EVENT_RESET_PHYSICAL, 0, &args);	pcmcia_release_io(link->handle, &link->io);	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;	pcmcia_request_io(link->handle, &link->io);	smc91c92_event(CS_EVENT_CARD_RESET, 0, &args);	return check_sig(link);    }    return -ENODEV;}/*======================================================================    smc91c92_config() is scheduled to run after a CARD_INSERTION event    is received, to configure the PCMCIA socket, and to make the    ethernet device available to the system.======================================================================*/#define CS_EXIT_TEST(ret, svc, label) \if (ret != CS_SUCCESS) { cs_error(link->handle, svc, ret); goto label; }static void smc91c92_config(dev_link_t *link){    client_handle_t handle = link->handle;    struct net_device *dev = link->priv;    struct smc_private *smc = netdev_priv(dev);    struct smc_cfg_mem *cfg_mem;    tuple_t *tuple;    cisparse_t *parse;    u_char *buf;    char *name;    int i, j, rev;    kio_addr_t ioaddr;    u_long mir;    DEBUG(0, "smc91c92_config(0x%p)\n", link);    cfg_mem = kmalloc(sizeof(struct smc_cfg_mem), GFP_KERNEL);    if (!cfg_mem)	goto config_failed;    tuple = &cfg_mem->tuple;    parse = &cfg_mem->parse;    buf = cfg_mem->buf;    tuple->Attributes = tuple->TupleOffset = 0;    tuple->TupleData = (cisdata_t *)buf;    tuple->TupleDataMax = 64;    tuple->DesiredTuple = CISTPL_CONFIG;    i = first_tuple(handle, tuple, parse);    CS_EXIT_TEST(i, ParseTuple, config_failed);    link->conf.ConfigBase = parse->config.base;    link->conf.Present = parse->config.rmask[0];    tuple->DesiredTuple = CISTPL_MANFID;    tuple->Attributes = TUPLE_RETURN_COMMON;    if (first_tuple(handle, tuple, parse) == CS_SUCCESS) {	smc->manfid = parse->manfid.manf;	smc->cardid = parse->manfid.card;    }    /* Configure card */    link->state |= DEV_CONFIG;    if ((smc->manfid == MANFID_OSITECH) &&	(smc->cardid != PRODID_OSITECH_SEVEN)) {	i = osi_config(link);    } else if ((smc->manfid == MANFID_MOTOROLA) ||	       ((smc->manfid == MANFID_MEGAHERTZ) &&		((smc->cardid == PRODID_MEGAHERTZ_VARIOUS) ||		 (smc->cardid == PRODID_MEGAHERTZ_EM3288)))) {	i = mhz_mfc_config(link);    } else {	i = smc_config(link);    }    CS_EXIT_TEST(i, RequestIO, config_failed);    i = pcmcia_request_irq(link->handle, &link->irq);    CS_EXIT_TEST(i, RequestIRQ, config_failed);    i = pcmcia_request_configuration(link->handle, &link->conf);    CS_EXIT_TEST(i, RequestConfiguration, config_failed);    if (smc->manfid == MANFID_MOTOROLA)	mot_config(link);    dev->irq = link->irq.AssignedIRQ;    if ((if_port >= 0) && (if_port <= 2))	dev->if_port = if_port;    else	printk(KERN_NOTICE "smc91c92_cs: invalid if_port requested\n");    switch (smc->manfid) {    case MANFID_OSITECH:    case MANFID_PSION:	i = osi_setup(link, smc->manfid, smc->cardid); break;    case MANFID_SMC:    case MANFID_NEW_MEDIA:	i = smc_setup(link); break;    case 0x128: /* For broken Megahertz cards */    case MANFID_MEGAHERTZ:	i = mhz_setup(link); break;    case MANFID_MOTOROLA:    default: /* get the hw address from EEPROM */	i = mot_setup(link); break;    }    if (i != 0) {	printk(KERN_NOTICE "smc91c92_cs: Unable to find hardware address.\n");	goto config_undo;    }    smc->duplex = 0;    smc->rx_ovrn = 0;    rev = check_sig(link);    name = "???";    if (rev > 0)	switch (rev >> 4) {	case 3: name = "92"; break;	case 4: name = ((rev & 15) >= 6) ? "96" : "94"; break;	case 5: name = "95"; break;	case 7: name = "100"; break;	case 8: name = "100-FD"; break;	case 9: name = "110"; break;	}    ioaddr = dev->base_addr;    if (rev > 0) {	u_long mcr;	SMC_SELECT_BANK(0);	mir = inw(ioaddr + MEMINFO) & 0xff;	if (mir == 0xff) mir++;	/* Get scale factor for memory size */	mcr = ((rev >> 4) > 3) ? inw(ioaddr + MEMCFG) : 0x0200;	mir *= 128 * (1<<((mcr >> 9) & 7));	SMC_SELECT_BANK(1);	smc->cfg = inw(ioaddr + CONFIG) & ~CFG_AUI_SELECT;	smc->cfg |= CFG_NO_WAIT | CFG_16BIT | CFG_STATIC;	if (smc->manfid == MANFID_OSITECH)	    smc->cfg |= CFG_IRQ_SEL_1 | CFG_IRQ_SEL_0;	if ((rev >> 4) >= 7)	    smc->cfg |= CFG_MII_SELECT;    } else	mir = 0;    if (smc->cfg & CFG_MII_SELECT) {	SMC_SELECT_BANK(3);	for (i = 0; i < 32; i++) {	    j = mdio_read(dev, i, 1);	    if ((j != 0) && (j != 0xffff)) break;	}	smc->mii_if.phy_id = (i < 32) ? i : -1;	SMC_SELECT_BANK(0);    }    link->dev = &smc->node;    link->state &= ~DEV_CONFIG_PENDING;    SET_NETDEV_DEV(dev, &handle_to_dev(handle));    if (register_netdev(dev) != 0) {	printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");	link->dev = NULL;	goto config_undo;    }    strcpy(smc->node.dev_name, dev->name);    printk(KERN_INFO "%s: smc91c%s rev %d: io %#3lx, irq %d, "	   "hw_addr ", dev->name, name, (rev & 0x0f), dev->base_addr,	   dev->irq);    for (i = 0; i < 6; i++)	printk("%02X%s", dev->dev_addr[i], ((i<5) ? ":" : "\n"));    if (rev > 0) {	if (mir & 0x3ff)	    printk(KERN_INFO "  %lu byte", mir);	else	    printk(KERN_INFO "  %lu kb", mir>>10);	printk(" buffer, %s xcvr\n", (smc->cfg & CFG_MII_SELECT) ?	       "MII" : if_names[dev->if_port]);    }    if (smc->cfg & CFG_MII_SELECT) {	if (smc->mii_if.phy_id != -1) {	    DEBUG(0, "  MII transceiver at index %d, status %x.\n",		  smc->mii_if.phy_id, j);	} else {    	    printk(KERN_NOTICE "  No MII transceivers found!\n");	}    }    kfree(cfg_mem);    return;config_undo:    unregister_netdev(dev);config_failed:			/* CS_EXIT_TEST() calls jump to here... */    smc91c92_release(link);    link->state &= ~DEV_CONFIG_PENDING;    kfree(cfg_mem);} /* smc91c92_config *//*======================================================================    After a card is removed, smc91c92_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 smc91c92_release(dev_link_t *link){    DEBUG(0, "smc91c92_release(0x%p)\n", link);    pcmcia_release_configuration(link->handle);    pcmcia_release_io(link->handle, &link->io);    pcmcia_release_irq(link->handle, &link->irq);    if (link->win) {	struct net_device *dev = link->priv;	struct smc_private *smc = netdev_priv(dev);	iounmap(smc->base);	pcmcia_release_window(link->win);    }    link->state &= ~DEV_CONFIG;}/*======================================================================    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 smc91c92_event(event_t event, int priority,			  event_callback_args_t *args){    dev_link_t *link = args->client_data;    struct net_device *dev = link->priv;    struct smc_private *smc = netdev_priv(dev);    int i;    DEBUG(1, "smc91c92_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);	break;    case CS_EVENT_CARD_INSERTION:	link->state |= DEV_PRESENT | DEV_CONFIG_PENDING;	smc91c92_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);	    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) {	    if ((smc->manfid == MANFID_MEGAHERTZ) &&		(smc->cardid == PRODID_MEGAHERTZ_EM3288))		mhz_3288_power(link);	    pcmcia_request_configuration(link->handle, &link->conf);	    if (smc->manfid == MANFID_MOTOROLA)		mot_config(link);	    if ((smc->manfid == MANFID_OSITECH) &&		(smc->cardid != PRODID_OSITECH_SEVEN)) {		/* Power up the card and enable interrupts */		set_bits(0x0300, dev->base_addr-0x10+OSITECH_AUI_PWR);		set_bits(0x0300, dev->base_addr-0x10+OSITECH_RESET_ISR);	    }	    if (((smc->manfid == MANFID_OSITECH) &&	 	(smc->cardid == PRODID_OSITECH_SEVEN)) ||		((smc->manfid == MANFID_PSION) &&	 	(smc->cardid == PRODID_PSION_NET100))) {		/* Download the Seven of Diamonds firmware */		for (i = 0; i < sizeof(__Xilinx7OD); i++) {	    	    outb(__Xilinx7OD[i], link->io.BasePort1+2);	   	    udelay(50);		}	    }	    if (link->open) {		smc_reset(dev);		netif_device_attach(dev);	    }	}	break;    }    return 0;} /* smc91c92_event *//*======================================================================    MII interface support for SMC91cXX based cards======================================================================*/#define MDIO_SHIFT_CLK		0x04#define MDIO_DATA_OUT		0x01#define MDIO_DIR_WRITE		0x08#define MDIO_DATA_WRITE0	(MDIO_DIR_WRITE)#define MDIO_DATA_WRITE1	(MDIO_DIR_WRITE | MDIO_DATA_OUT)#define MDIO_DATA_READ		0x02static void mdio_sync(kio_addr_t addr){    int bits;    for (bits = 0; bits < 32; bits++) {	outb(MDIO_DATA_WRITE1, addr);	outb(MDIO_DATA_WRITE1 | MDIO_SHIFT_CLK, addr);    }}static int mdio_read(struct net_device *dev, int phy_id, int loc){    kio_addr_t addr = dev->base_addr + MGMT;    u_int cmd = (0x06<<10)|(phy_id<<5)|loc;    int i, retval = 0;    mdio_sync(addr);    for (i = 13; i >= 0; i--) {	int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;	outb(dat, addr);	outb(dat | MDIO_SHIFT_CLK, addr);    }    for (i = 19; i > 0; i--) {	outb(0, addr);	retval = (retval << 1) | ((inb(addr) & MDIO_DATA_READ) != 0);	outb(MDIO_SHIFT_CLK, addr);    }    return (retval>>1) & 0xffff;}static void mdio_write(struct net_device *dev, int phy_id, int loc, int value){    kio_addr_t addr = dev->base_addr + MGMT;    u_int cmd = (0x05<<28)|(phy_id<<23)|(loc<<18)|(1<<17)|value;    int i;    mdio_sync(addr);    for (i = 31; i >= 0; i--) {	int dat = (cmd&(1<<i)) ? MDIO_DATA_WRITE1 : MDIO_DATA_WRITE0;	outb(dat, addr);	outb(dat | MDIO_SHIFT_CLK, addr);    }    for (i = 1; i >= 0; i--) {	outb(0, addr);	outb(MDIO_SHIFT_CLK, addr);    }}/*======================================================================    The driver core code, most of which should be common with a    non-PCMCIA implementation.======================================================================*/#ifdef PCMCIA_DEBUGstatic void smc_dump(struct net_device *dev){    kio_addr_t ioaddr = dev->base_addr;    u_short i, w, save;    save = inw(ioaddr + BANK_SELECT);    for (w = 0; w < 4; w++) {	SMC_SELECT_BANK(w);	printk(KERN_DEBUG "bank %d: ", w);	for (i = 0; i < 14; i += 2)	    printk(" %04x", inw(ioaddr + i));	printk("\n");    }    outw(save, ioaddr + BANK_SELECT);}#endifstatic int smc_open(struct net_device *dev){    struct smc_private *smc = netdev_priv(dev);    dev_link_t *link = &smc->link;#ifdef PCMCIA_DEBUG    DEBUG(0, "%s: smc_open(%p), ID/Window %4.4x.\n",	  dev->name, dev, inw(dev->base_addr + BANK_SELECT));    if (pc_debug > 1) smc_dump(dev);#endif    /* Check that the PCMCIA card is still here. */    if (!DEV_OK(link))	return -ENODEV;    /* Physical device present signature. */    if (check_sig(link) < 0) {	printk("smc91c92_cs: Yikes!  Bad chip signature!\n");	return -ENODEV;    }

⌨️ 快捷键说明

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