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

📄 smc91c92_cs.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
    /* Pause 200ms... */    mdelay(200);        /* Now read and write the COR... */    tmp = readb(smc->base + link->conf.ConfigBase + CISREG_COR);    udelay(5);    writeb(tmp, smc->base + link->conf.ConfigBase + CISREG_COR);    return 0;}static int mhz_mfc_config(dev_link_t *link){    struct smc_private *smc = link->priv;    struct net_device *dev = &smc->dev;    tuple_t tuple;    cisparse_t parse;    u_char buf[255];    cistpl_cftable_entry_t *cf = &parse.cftable_entry;    win_req_t req;    memreq_t mem;    int i, k;    link->conf.Attributes |= CONF_ENABLE_SPKR;    link->conf.Status = CCSR_AUDIO_ENA;    link->irq.Attributes =	IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED|IRQ_HANDLE_PRESENT;    link->io.IOAddrLines = 16;    link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;    link->io.NumPorts2 = 8;    tuple.Attributes = tuple.TupleOffset = 0;    tuple.TupleData = (cisdata_t *)buf;    tuple.TupleDataMax = sizeof(buf);    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;    i = first_tuple(link->handle, &tuple, &parse);    /* The Megahertz combo cards have modem-like CIS entries, so       we have to explicitly try a bunch of port combinations. */    while (i == CS_SUCCESS) {	link->conf.ConfigIndex = cf->index;	link->io.BasePort2 = cf->io.win[0].base;	for (k = 0; k < 0x400; k += 0x10) {	    if (k & 0x80) continue;	    link->io.BasePort1 = k ^ 0x300;	    i = CardServices(RequestIO, link->handle, &link->io);	    if (i == CS_SUCCESS) break;	}	if (i == CS_SUCCESS) break;	i = next_tuple(link->handle, &tuple, &parse);    }    if (i != CS_SUCCESS)	return i;    dev->base_addr = link->io.BasePort1;        /* Allocate a memory window, for accessing the ISR */    req.Attributes = WIN_DATA_WIDTH_8|WIN_MEMORY_TYPE_AM|WIN_ENABLE;    req.Base = req.Size = 0;    req.AccessSpeed = 0;    link->win = (window_handle_t)link->handle;    i = CardServices(RequestWindow, &link->win, &req);    if (i != CS_SUCCESS)	return i;    smc->base = ioremap(req.Base, req.Size);    mem.CardOffset = mem.Page = 0;    if (smc->manfid == MANFID_MOTOROLA)	mem.CardOffset = link->conf.ConfigBase;    i = CardServices(MapMemPage, link->win, &mem);        if ((i == CS_SUCCESS)	&& (smc->manfid == MANFID_MEGAHERTZ)	&& (smc->cardid == PRODID_MEGAHERTZ_EM3288))	mhz_3288_power(link);        return i;}static int mhz_setup(dev_link_t *link){    client_handle_t handle = link->handle;    struct smc_private *smc = link->priv;    struct net_device *dev = &smc->dev;    tuple_t tuple;    cisparse_t parse;    u_char buf[255], *station_addr;    tuple.Attributes = tuple.TupleOffset = 0;    tuple.TupleData = buf;    tuple.TupleDataMax = sizeof(buf);    /* Read the station address from the CIS.  It is stored as the last       (fourth) string in the Version 1 Version/ID tuple. */    tuple.DesiredTuple = CISTPL_VERS_1;    if (first_tuple(handle, &tuple, &parse) != CS_SUCCESS)	return -1;    /* Ugh -- the EM1144 card has two VERS_1 tuples!?! */    if (next_tuple(handle, &tuple, &parse) != CS_SUCCESS)	first_tuple(handle, &tuple, &parse);    if (parse.version_1.ns > 3) {	station_addr = parse.version_1.str + parse.version_1.ofs[3];	if (cvt_ascii_address(dev, station_addr) == 0)	    return 0;    }    /* Another possibility: for the EM3288, in a special tuple */    tuple.DesiredTuple = 0x81;    if (CardServices(GetFirstTuple, handle, &tuple) != CS_SUCCESS)	return -1;    if (CardServices(GetTupleData, handle, &tuple) != CS_SUCCESS)	return -1;    buf[12] = '\0';    if (cvt_ascii_address(dev, buf) == 0)	return 0;        return -1;}/*======================================================================    Configuration stuff for the Motorola Mariner    mot_config() writes directly to the Mariner configuration    registers because the CIS is just bogus.    ======================================================================*/static void mot_config(dev_link_t *link){    struct smc_private *smc = link->priv;    struct net_device *dev = &smc->dev;    ioaddr_t ioaddr = dev->base_addr;    ioaddr_t iouart = link->io.BasePort2;        /* Set UART base address and force map with COR bit 1 */    writeb(iouart & 0xff,        smc->base + MOT_UART + CISREG_IOBASE_0);    writeb((iouart >> 8) & 0xff, smc->base + MOT_UART + CISREG_IOBASE_1);    writeb(MOT_NORMAL,           smc->base + MOT_UART + CISREG_COR);        /* Set SMC base address and force map with COR bit 1 */    writeb(ioaddr & 0xff,        smc->base + MOT_LAN + CISREG_IOBASE_0);    writeb((ioaddr >> 8) & 0xff, smc->base + MOT_LAN + CISREG_IOBASE_1);    writeb(MOT_NORMAL,           smc->base + MOT_LAN + CISREG_COR);    /* Wait for things to settle down */    mdelay(100);}static int mot_setup(dev_link_t *link){    struct smc_private *smc = link->priv;    struct net_device *dev = &smc->dev;    ioaddr_t ioaddr = dev->base_addr;    int i, wait, loop;    u_int addr;    /* Read Ethernet address from Serial EEPROM */        for (i = 0; i < 3; i++) {	SMC_SELECT_BANK(2);	outw(MOT_EEPROM + i, ioaddr + POINTER);	SMC_SELECT_BANK(1);	outw((CTL_RELOAD | CTL_EE_SELECT), ioaddr + CONTROL);	for (loop = wait = 0; loop < 200; loop++) {	    udelay(10);	    wait = ((CTL_RELOAD | CTL_STORE) & inw(ioaddr + CONTROL));	    if (wait == 0) break;	}		if (wait)	    return -1;		addr = inw(ioaddr + GENERAL);	dev->dev_addr[2*i]   = addr & 0xff;	dev->dev_addr[2*i+1] = (addr >> 8) & 0xff;    }        return 0;}/*====================================================================*/static int smc_config(dev_link_t *link){    struct smc_private *smc = link->priv;    struct net_device *dev = &smc->dev;    tuple_t tuple;    cisparse_t parse;    u_char buf[255];    cistpl_cftable_entry_t *cf = &parse.cftable_entry;    int i;    tuple.Attributes = tuple.TupleOffset = 0;    tuple.TupleData = (cisdata_t *)buf;    tuple.TupleDataMax = sizeof(buf);    tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY;    link->io.NumPorts1 = 16;    i = first_tuple(link->handle, &tuple, &parse);    while (i != CS_NO_MORE_ITEMS) {	if (i == CS_SUCCESS) {	    link->conf.ConfigIndex = cf->index;	    link->io.BasePort1 = cf->io.win[0].base;	    link->io.IOAddrLines = cf->io.flags & CISTPL_IO_LINES_MASK;	    i = CardServices(RequestIO, link->handle, &link->io);	    if (i == CS_SUCCESS) break;	}	i = next_tuple(link->handle, &tuple, &parse);    }    if (i == CS_SUCCESS)	dev->base_addr = link->io.BasePort1;    return i;}static int smc_setup(dev_link_t *link){    client_handle_t handle = link->handle;    struct smc_private *smc = link->priv;    struct net_device *dev = &smc->dev;    tuple_t tuple;    cisparse_t parse;    cistpl_lan_node_id_t *node_id;    u_char buf[255], *station_addr;    int i;    tuple.Attributes = tuple.TupleOffset = 0;    tuple.TupleData = buf;    tuple.TupleDataMax = sizeof(buf);        /* Check for a LAN function extension tuple */    tuple.DesiredTuple = CISTPL_FUNCE;    i = first_tuple(handle, &tuple, &parse);    while (i == CS_SUCCESS) {	if (parse.funce.type == CISTPL_FUNCE_LAN_NODE_ID)	    break;	i = next_tuple(handle, &tuple, &parse);    }    if (i == CS_SUCCESS) {	node_id = (cistpl_lan_node_id_t *)parse.funce.data;	if (node_id->nb == 6) {	    for (i = 0; i < 6; i++)		dev->dev_addr[i] = node_id->id[i];	    return 0;	}    }        /* Try the third string in the Version 1 Version/ID tuple. */    tuple.DesiredTuple = CISTPL_VERS_1;    if (first_tuple(handle, &tuple, &parse) != CS_SUCCESS)	return -1;    station_addr = parse.version_1.str + parse.version_1.ofs[2];    if (cvt_ascii_address(dev, station_addr) == 0)	return 0;    return -1;}/*====================================================================*/static int osi_config(dev_link_t *link){    struct smc_private *smc = link->priv;    struct net_device *dev = &smc->dev;    static ioaddr_t com[4] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };    int i, j;        link->conf.Attributes |= CONF_ENABLE_SPKR;    link->conf.Status = CCSR_AUDIO_ENA;    link->irq.Attributes =	IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED|IRQ_HANDLE_PRESENT;    link->io.NumPorts1 = 64;    link->io.Attributes2 = IO_DATA_PATH_WIDTH_8;    link->io.NumPorts2 = 8;    link->io.IOAddrLines = 16;        /* Enable Hard Decode, LAN, Modem */    link->conf.ConfigIndex = 0x23;        for (i = j = 0; j < 4; j++) {	link->io.BasePort2 = com[j];	i = CardServices(RequestIO, link->handle, &link->io);	if (i == CS_SUCCESS) break;    }    if (i != CS_SUCCESS) {	/* Fallback: turn off hard decode */	link->conf.ConfigIndex = 0x03;	link->io.NumPorts2 = 0;	i = CardServices(RequestIO, link->handle, &link->io);    }    dev->base_addr = link->io.BasePort1 + 0x10;    return i;}static int osi_setup(dev_link_t *link, u_short manfid, u_short cardid){    client_handle_t handle = link->handle;    struct smc_private *smc = link->priv;    struct net_device *dev = &smc->dev;    tuple_t tuple;    u_char buf[255];    int i;        tuple.Attributes = TUPLE_RETURN_COMMON;    tuple.TupleData = buf;    tuple.TupleDataMax = sizeof(buf);    tuple.TupleOffset = 0;        /* Read the station address from tuple 0x90, subtuple 0x04 */    tuple.DesiredTuple = 0x90;    i = CardServices(GetFirstTuple, handle, &tuple);    while (i == CS_SUCCESS) {	i = CardServices(GetTupleData, handle, &tuple);	if ((i != CS_SUCCESS) || (buf[0] == 0x04))	    break;	i = CardServices(GetNextTuple, handle, &tuple);    }    if (i != CS_SUCCESS)	return -1;    for (i = 0; i < 6; i++)	dev->dev_addr[i] = buf[i+2];    if (((manfid == MANFID_OSITECH) &&	 (cardid == PRODID_OSITECH_SEVEN)) ||	((manfid == MANFID_PSION) &&	 (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);	}    } else if (manfid == MANFID_OSITECH) {	/* Make sure both functions are powered up */	set_bits(0x300, link->io.BasePort1 + OSITECH_AUI_PWR);	/* Now, turn on the interrupt for both card functions */	set_bits(0x300, link->io.BasePort1 + OSITECH_RESET_ISR);	DEBUG(2, "AUI/PWR: %4.4x RESET/ISR: %4.4x\n",	      inw(link->io.BasePort1 + OSITECH_AUI_PWR),	      inw(link->io.BasePort1 + OSITECH_RESET_ISR));    }    return 0;}/*======================================================================    This verifies that the chip is some SMC91cXX variant, and returns    the revision code if successful.  Otherwise, it returns -ENODEV.    ======================================================================*/static int check_sig(dev_link_t *link){    struct smc_private *smc = link->priv;    struct net_device *dev = &smc->dev;    ioaddr_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);	CardServices(ReleaseIO, link->handle, &link->io);	link->io.Attributes1 = IO_DATA_PATH_WIDTH_8;	CardServices(RequestIO, 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 smc_private *smc = link->priv;    struct net_device *dev = &smc->dev;    tuple_t tuple;    cisparse_t parse;    u_short buf[32];    char *name;    int i, rev;    DEBUG(0, "smc91c92_config(0x%p)\n", link);        tuple.Attributes = tuple.TupleOffset = 0;    tuple.TupleData = (cisdata_t *)buf;    tuple.TupleDataMax = sizeof(buf);    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 = CardServices(RequestIRQ, link->handle, &link->irq);    CS_EXIT_TEST(i, RequestIRQ, config_failed);    i = CardServices(RequestConfiguration, 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");        if (register_netdev(dev) != 0) {	printk(KERN_ERR "smc91c92_cs: register_netdev() failed\n");	goto config_undo;    }    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) {

⌨️ 快捷键说明

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