📄 xirc2ps_cs.c
字号:
#define GetByte(reg) ((unsigned)inb(ioaddr + (reg)))#define GetWord(reg) ((unsigned)inw(ioaddr + (reg)))#define PutByte(reg,value) outb((value), ioaddr+(reg))#define PutWord(reg,value) outw((value), ioaddr+(reg))/*====== Functions used for debugging =================================*/#if defined(PCMCIA_DEBUG) && 0 /* reading regs may change system status */static voidPrintRegisters(struct net_device *dev){ kio_addr_t ioaddr = dev->base_addr; if (pc_debug > 1) { int i, page; printk(KDBG_XIRC "Register common: "); for (i = 0; i < 8; i++) printk(" %2.2x", GetByte(i)); printk("\n"); for (page = 0; page <= 8; page++) { printk(KDBG_XIRC "Register page %2x: ", page); SelectPage(page); for (i = 8; i < 16; i++) printk(" %2.2x", GetByte(i)); printk("\n"); } for (page=0x40 ; page <= 0x5f; page++) { if (page == 0x43 || (page >= 0x46 && page <= 0x4f) || (page >= 0x51 && page <=0x5e)) continue; printk(KDBG_XIRC "Register page %2x: ", page); SelectPage(page); for (i = 8; i < 16; i++) printk(" %2.2x", GetByte(i)); printk("\n"); } }}#endif /* PCMCIA_DEBUG *//*============== MII Management functions ===============*//**************** * Turn around for read */static voidmii_idle(kio_addr_t ioaddr){ PutByte(XIRCREG2_GPR2, 0x04|0); /* drive MDCK low */ udelay(1); PutByte(XIRCREG2_GPR2, 0x04|1); /* and drive MDCK high */ udelay(1);}/**************** * Write a bit to MDI/O */static voidmii_putbit(kio_addr_t ioaddr, unsigned data){ #if 1 if (data) { PutByte(XIRCREG2_GPR2, 0x0c|2|0); /* set MDIO */ udelay(1); PutByte(XIRCREG2_GPR2, 0x0c|2|1); /* and drive MDCK high */ udelay(1); } else { PutByte(XIRCREG2_GPR2, 0x0c|0|0); /* clear MDIO */ udelay(1); PutByte(XIRCREG2_GPR2, 0x0c|0|1); /* and drive MDCK high */ udelay(1); } #else if (data) { PutWord(XIRCREG2_GPR2-1, 0x0e0e); udelay(1); PutWord(XIRCREG2_GPR2-1, 0x0f0f); udelay(1); } else { PutWord(XIRCREG2_GPR2-1, 0x0c0c); udelay(1); PutWord(XIRCREG2_GPR2-1, 0x0d0d); udelay(1); } #endif}/**************** * Get a bit from MDI/O */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 dev_link_t *xirc2ps_attach(void){ client_reg_t client_reg; dev_link_t *link; struct net_device *dev; local_info_t *local; int err; DEBUG(0, "attach()\n"); /* Allocate the device structure */ dev = alloc_etherdev(sizeof(local_info_t)); if (!dev) return NULL; local = netdev_priv(dev); link = &local->link; link->priv = dev; /* General socket configuration */ link->conf.Attributes = CONF_ENABLE_IRQ; link->conf.Vcc = 50; link->conf.IntType = INT_MEMORY_AND_IO; link->conf.ConfigIndex = 1; link->conf.Present = PRESENT_OPTION; 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;#endif /* Register with Card Services */ link->next = dev_list; dev_list = link; client_reg.dev_info = &dev_info; client_reg.Version = 0x0210; client_reg.event_callback_args.client_data = link; if ((err = pcmcia_register_client(&link->handle, &client_reg))) { cs_error(link->handle, RegisterClient, err); xirc2ps_detach(link); return NULL; } return 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(dev_link_t * link){ struct net_device *dev = link->priv; dev_link_t **linkp; DEBUG(0, "detach(0x%p)\n", link); /* Locate device structure */ for (linkp = &dev_list; *linkp; linkp = &(*linkp)->next) if (*linkp == link) break; if (!*linkp) { DEBUG(0, "detach(0x%p): dev_link lost\n", link); return; } if (link->dev) unregister_netdev(dev); /* * If the device is currently configured and active, we won't * actually delete it yet. Instead, it is marked so that when * the release() function is called, that will trigger a proper * detach(). */ if (link->state & DEV_CONFIG) xirc2ps_release(link); /* Break the link with Card Services */ if (link->handle) pcmcia_deregister_client(link->handle); /* Unlink device structure, free it */ *linkp = link->next; 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(dev_link_t *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(dev_link_t * link){ client_handle_t handle = link->handle; tuple_t tuple; cisparse_t parse; u_char buf[256]; tuple.Attributes = 0; tuple.TupleData = buf; tuple.TupleDataMax = 254; tuple.TupleOffset = 0; tuple.DesiredTuple = CISTPL_VERS_1; if (!first_tuple(handle, &tuple, &parse) && parse.version_1.ns > 2) { if (strstr(parse.version_1.str + parse.version_1.ofs[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 voidxirc2ps_config(dev_link_t * link){ client_handle_t handle = link->handle; 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(handle, &tuple, &parse))) { printk(KNOT_XIRC "manfid not found in CIS\n"); goto failure; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -