?? xirc2ps_cs.c
字號:
static intmii_getbit(kio_addr_t ioaddr){ unsigned d; PutByte(XIRCREG2_GPR2, 4|0); /* drive MDCK low */ udelay(1); d = GetByte(XIRCREG2_GPR2); /* read MDIO */ PutByte(XIRCREG2_GPR2, 4|1); /* drive MDCK high again */ udelay(1); return d & 0x20; /* read MDIO */}static voidmii_wbits(kio_addr_t ioaddr, unsigned data, int len){ unsigned m = 1 << (len-1); for (; m; m >>= 1) mii_putbit(ioaddr, data & m);}static unsignedmii_rd(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg){ int i; unsigned data=0, m; SelectPage(2); for (i=0; i < 32; i++) /* 32 bit preamble */ mii_putbit(ioaddr, 1); mii_wbits(ioaddr, 0x06, 4); /* Start and opcode for read */ mii_wbits(ioaddr, phyaddr, 5); /* PHY address to be accessed */ mii_wbits(ioaddr, phyreg, 5); /* PHY register to read */ mii_idle(ioaddr); /* turn around */ mii_getbit(ioaddr); for (m = 1<<15; m; m >>= 1) if (mii_getbit(ioaddr)) data |= m; mii_idle(ioaddr); return data;}static voidmii_wr(kio_addr_t ioaddr, u_char phyaddr, u_char phyreg, unsigned data, int len){ int i; SelectPage(2); for (i=0; i < 32; i++) /* 32 bit preamble */ mii_putbit(ioaddr, 1); mii_wbits(ioaddr, 0x05, 4); /* Start and opcode for write */ mii_wbits(ioaddr, phyaddr, 5); /* PHY address to be accessed */ mii_wbits(ioaddr, phyreg, 5); /* PHY Register to write */ mii_putbit(ioaddr, 1); /* turn around */ mii_putbit(ioaddr, 0); mii_wbits(ioaddr, data, len); /* And write the data */ mii_idle(ioaddr);}/*============= Main bulk of functions =========================*//**************** * xirc2ps_attach() creates an "instance" of the driver, allocating * local data structures for one device. The device is registered * with Card Services. * * The dev_link structure is initialized, but we don't actually * configure the card at this point -- we wait until we receive a * card insertion event. */static intxirc2ps_probe(struct pcmcia_device *link){ struct net_device *dev; local_info_t *local; DEBUG(0, "attach()\n"); /* Allocate the device structure */ dev = alloc_etherdev(sizeof(local_info_t)); if (!dev) return -ENOMEM; local = netdev_priv(dev); local->dev = dev; local->p_dev = link; link->priv = dev; /* General socket configuration */ link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.ConfigIndex = 1; link->irq.Handler = xirc2ps_interrupt; link->irq.Instance = dev; /* Fill in card specific entries */ SET_MODULE_OWNER(dev); dev->hard_start_xmit = &do_start_xmit; dev->set_config = &do_config; dev->get_stats = &do_get_stats; dev->do_ioctl = &do_ioctl; SET_ETHTOOL_OPS(dev, &netdev_ethtool_ops); dev->set_multicast_list = &set_multicast_list; dev->open = &do_open; dev->stop = &do_stop;#ifdef HAVE_TX_TIMEOUT dev->tx_timeout = do_tx_timeout; dev->watchdog_timeo = TX_TIMEOUT; INIT_WORK(&local->tx_timeout_task, xirc2ps_tx_timeout_task);#endif return xirc2ps_config(link);} /* xirc2ps_attach *//**************** * This deletes a driver "instance". The device is de-registered * with Card Services. If it has been released, all local data * structures are freed. Otherwise, the structures will be freed * when the device is released. */static voidxirc2ps_detach(struct pcmcia_device *link){ struct net_device *dev = link->priv; DEBUG(0, "detach(0x%p)\n", link); if (link->dev_node) unregister_netdev(dev); xirc2ps_release(link); free_netdev(dev);} /* xirc2ps_detach *//**************** * Detect the type of the card. s is the buffer with the data of tuple 0x20 * Returns: 0 := not supported * mediaid=11 and prodid=47 * Media-Id bits: * Ethernet 0x01 * Tokenring 0x02 * Arcnet 0x04 * Wireless 0x08 * Modem 0x10 * GSM only 0x20 * Prod-Id bits: * Pocket 0x10 * External 0x20 * Creditcard 0x40 * Cardbus 0x80 * */static intset_card_type(struct pcmcia_device *link, const void *s){ struct net_device *dev = link->priv; local_info_t *local = netdev_priv(dev); #ifdef PCMCIA_DEBUG unsigned cisrev = ((const unsigned char *)s)[2]; #endif unsigned mediaid= ((const unsigned char *)s)[3]; unsigned prodid = ((const unsigned char *)s)[4]; DEBUG(0, "cisrev=%02x mediaid=%02x prodid=%02x\n", cisrev, mediaid, prodid); local->mohawk = 0; local->dingo = 0; local->modem = 0; local->card_type = XIR_UNKNOWN; if (!(prodid & 0x40)) { printk(KNOT_XIRC "Ooops: Not a creditcard\n"); return 0; } if (!(mediaid & 0x01)) { printk(KNOT_XIRC "Not an Ethernet card\n"); return 0; } if (mediaid & 0x10) { local->modem = 1; switch(prodid & 15) { case 1: local->card_type = XIR_CEM ; break; case 2: local->card_type = XIR_CEM2 ; break; case 3: local->card_type = XIR_CEM3 ; break; case 4: local->card_type = XIR_CEM33 ; break; case 5: local->card_type = XIR_CEM56M; local->mohawk = 1; break; case 6: case 7: /* 7 is the RealPort 10/56 */ local->card_type = XIR_CEM56 ; local->mohawk = 1; local->dingo = 1; break; } } else { switch(prodid & 15) { case 1: local->card_type = has_ce2_string(link)? XIR_CE2 : XIR_CE ; break; case 2: local->card_type = XIR_CE2; break; case 3: local->card_type = XIR_CE3; local->mohawk = 1; break; } } if (local->card_type == XIR_CE || local->card_type == XIR_CEM) { printk(KNOT_XIRC "Sorry, this is an old CE card\n"); return 0; } if (local->card_type == XIR_UNKNOWN) printk(KNOT_XIRC "unknown card (mediaid=%02x prodid=%02x)\n", mediaid, prodid); return 1;}/**************** * There are some CE2 cards out which claim to be a CE card. * This function looks for a "CE2" in the 3rd version field. * Returns: true if this is a CE2 */static inthas_ce2_string(struct pcmcia_device * p_dev){ if (p_dev->prod_id[2] && strstr(p_dev->prod_id[2], "CE2")) return 1; return 0;}/**************** * xirc2ps_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. */static intxirc2ps_config(struct pcmcia_device * link){ struct net_device *dev = link->priv; local_info_t *local = netdev_priv(dev); tuple_t tuple; cisparse_t parse; kio_addr_t ioaddr; int err, i; u_char buf[64]; cistpl_lan_node_id_t *node_id = (cistpl_lan_node_id_t*)parse.funce.data; cistpl_cftable_entry_t *cf = &parse.cftable_entry; local->dingo_ccr = NULL; DEBUG(0, "config(0x%p)\n", link); /* * This reads the card's CONFIG tuple to find its configuration * registers. */ tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = 64; tuple.TupleOffset = 0; /* Is this a valid card */ tuple.DesiredTuple = CISTPL_MANFID; if ((err=first_tuple(link, &tuple, &parse))) { printk(KNOT_XIRC "manfid not found in CIS\n"); goto failure; } switch(parse.manfid.manf) { case MANFID_XIRCOM: local->manf_str = "Xircom"; break; case MANFID_ACCTON: local->manf_str = "Accton"; break; case MANFID_COMPAQ: case MANFID_COMPAQ2: local->manf_str = "Compaq"; break; case MANFID_INTEL: local->manf_str = "Intel"; break; case MANFID_TOSHIBA: local->manf_str = "Toshiba"; break; default: printk(KNOT_XIRC "Unknown Card Manufacturer ID: 0x%04x\n", (unsigned)parse.manfid.manf); goto failure; } DEBUG(0, "found %s card\n", local->manf_str); if (!set_card_type(link, buf)) { printk(KNOT_XIRC "this card is not supported\n"); goto failure; } /* get the ethernet address from the CIS */ tuple.DesiredTuple = CISTPL_FUNCE; for (err = first_tuple(link, &tuple, &parse); !err; err = next_tuple(link, &tuple, &parse)) { /* Once I saw two CISTPL_FUNCE_LAN_NODE_ID entries: * the first one with a length of zero the second correct - * so I skip all entries with length 0 */ if (parse.funce.type == CISTPL_FUNCE_LAN_NODE_ID && ((cistpl_lan_node_id_t *)parse.funce.data)->nb) break; } if (err) { /* not found: try to get the node-id from tuple 0x89 */ tuple.DesiredTuple = 0x89; /* data layout looks like tuple 0x22 */ if ((err = pcmcia_get_first_tuple(link, &tuple)) == 0 && (err = pcmcia_get_tuple_data(link, &tuple)) == 0) { if (tuple.TupleDataLen == 8 && *buf == CISTPL_FUNCE_LAN_NODE_ID) memcpy(&parse, buf, 8); else err = -1; } } if (err) { /* another try (James Lehmer's CE2 version 4.1)*/ tuple.DesiredTuple = CISTPL_FUNCE; for (err = first_tuple(link, &tuple, &parse); !err; err = next_tuple(link, &tuple, &parse)) { if (parse.funce.type == 0x02 && parse.funce.data[0] == 1 && parse.funce.data[1] == 6 && tuple.TupleDataLen == 13) { buf[1] = 4; memcpy(&parse, buf+1, 8); break; } } } if (err) { printk(KNOT_XIRC "node-id not found in CIS\n"); goto failure; } node_id = (cistpl_lan_node_id_t *)parse.funce.data; if (node_id->nb != 6) { printk(KNOT_XIRC "malformed node-id in CIS\n"); goto failure; } for (i=0; i < 6; i++) dev->dev_addr[i] = node_id->id[i]; link->io.IOAddrLines =10; link->io.Attributes1 = IO_DATA_PATH_WIDTH_16; link->irq.Attributes = IRQ_HANDLE_PRESENT; link->irq.IRQInfo1 = IRQ_LEVEL_ID; if (local->modem) { int pass; if (do_sound) { link->conf.Attributes |= CONF_ENABLE_SPKR; link->conf.Status |= CCSR_AUDIO_ENA; } link->irq.Attributes |= IRQ_TYPE_DYNAMIC_SHARING|IRQ_FIRST_SHARED ; link->io.NumPorts2 = 8; link->io.Attributes2 = IO_DATA_PATH_WIDTH_8; if (local->dingo) { /* Take the Modem IO port from the CIS and scan for a free * Ethernet port */ link->io.NumPorts1 = 16; /* no Mako stuff anymore */ tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; for (err = first_tuple(link, &tuple, &parse); !err; err = next_tuple(link, &tuple, &parse)) { if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8) { for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { link->conf.ConfigIndex = cf->index ; link->io.BasePort2 = cf->io.win[0].base; link->io.BasePort1 = ioaddr; if (!(err=pcmcia_request_io(link, &link->io))) goto port_found; } } } } else { link->io.NumPorts1 = 18; /* We do 2 passes here: The first one uses the regular mapping and * the second tries again, thereby considering that the 32 ports are * mirrored every 32 bytes. Actually we use a mirrored port for * the Mako if (on the first pass) the COR bit 5 is set. */ for (pass=0; pass < 2; pass++) { tuple.DesiredTuple = CISTPL_CFTABLE_ENTRY; for (err = first_tuple(link, &tuple, &parse); !err; err = next_tuple(link, &tuple, &parse)){ if (cf->io.nwin > 0 && (cf->io.win[0].base & 0xf) == 8){ link->conf.ConfigIndex = cf->index ; link->io.BasePort2 = cf->io.win[0].base; link->io.BasePort1 = link->io.BasePort2 + (pass ? (cf->index & 0x20 ? -24:8) : (cf->index & 0x20 ? 8:-24)); if (!(err=pcmcia_request_io(link, &link->io))) goto port_found; } } } /* if special option: * try to configure as Ethernet only. * .... */ } printk(KNOT_XIRC "no ports available\n"); } else { link->irq.Attributes |= IRQ_TYPE_EXCLUSIVE; link->io.NumPorts1 = 16; for (ioaddr = 0x300; ioaddr < 0x400; ioaddr += 0x10) { link->io.BasePort1 = ioaddr; if (!(err=pcmcia_request_io(link, &link->io))) goto port_found; } link->io.BasePort1 = 0; /* let CS decide */ if ((err=pcmcia_request_io(link, &link->io))) { cs_error(link, RequestIO, err); goto config_error; } } port_found: if (err) goto config_error; /**************** * Now allocate an interrupt line. Note that this does not * actually assign a handler to the interrupt. */ if ((err=pcmcia_request_irq(link, &link->irq))) { cs_error(link, RequestIRQ, err); goto config_error; } /**************** * This actually configures the PCMCIA socket -- setting up * the I/O windows and the interrupt mapping. */ if ((err=pcmcia_request_configuration(link, &link->conf))) { cs_error(link, RequestConfiguration, err); goto config_error; } if (local->dingo) { conf_reg_t reg; win_req_t req; memreq_t mem; /* Reset the modem's BAR to the correct value * This is necessary because in the RequestConfiguration call, * the base address of the ethernet port (BasePort1) is written * to the BAR registers of the modem. */ reg.Action = CS_WRITE; reg.Offset = CISREG_IOBASE_0; reg.Value = link->io.BasePort2 & 0xff; if ((err = pcmcia_access_configuration_register(link, ®))) { cs_error(link, 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, ®))) { cs_error(link, 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, &req, &link->win))) { cs_error(link, 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, MapMemPage, err); goto config_error; } /* Setup the CCRs; there are no infos in the CIS about the Ethernet * part. */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -