📄 xirc2ps_cs.c
字号:
}static void netdev_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info){ strcpy(info->driver, "xirc2ps_cs"); sprintf(info->bus_info, "PCMCIA 0x%lx", dev->base_addr);}static struct ethtool_ops netdev_ethtool_ops = { .get_drvinfo = netdev_get_drvinfo,};static intdo_ioctl(struct net_device *dev, struct ifreq *rq, int cmd){ local_info_t *local = netdev_priv(dev); kio_addr_t ioaddr = dev->base_addr; u16 *data = (u16 *)&rq->ifr_ifru; DEBUG(1, "%s: ioctl(%-.6s, %#04x) %04x %04x %04x %04x\n", dev->name, rq->ifr_ifrn.ifrn_name, cmd, data[0], data[1], data[2], data[3]); if (!local->mohawk) return -EOPNOTSUPP; switch(cmd) { case SIOCGMIIPHY: /* Get the address of the PHY in use. */ data[0] = 0; /* we have only this address */ /* fall trough */ case SIOCGMIIREG: /* Read the specified MII register. */ data[3] = mii_rd(ioaddr, data[0] & 0x1f, data[1] & 0x1f); break; case SIOCSMIIREG: /* Write the specified MII register */ if (!capable(CAP_NET_ADMIN)) return -EPERM; mii_wr(ioaddr, data[0] & 0x1f, data[1] & 0x1f, data[2], 16); break; default: return -EOPNOTSUPP; } return 0;}static voidhardreset(struct net_device *dev){ local_info_t *local = netdev_priv(dev); kio_addr_t ioaddr = dev->base_addr; SelectPage(4); udelay(1); PutByte(XIRCREG4_GPR1, 0); /* clear bit 0: power down */ msleep(40); /* wait 40 msec */ if (local->mohawk) PutByte(XIRCREG4_GPR1, 1); /* set bit 0: power up */ else PutByte(XIRCREG4_GPR1, 1 | 4); /* set bit 0: power up, bit 2: AIC */ msleep(20); /* wait 20 msec */}static voiddo_reset(struct net_device *dev, int full){ local_info_t *local = netdev_priv(dev); kio_addr_t ioaddr = dev->base_addr; unsigned value; DEBUG(0, "%s: do_reset(%p,%d)\n", dev? dev->name:"eth?", dev, full); hardreset(dev); PutByte(XIRCREG_CR, SoftReset); /* set */ msleep(20); /* wait 20 msec */ PutByte(XIRCREG_CR, 0); /* clear */ msleep(40); /* wait 40 msec */ if (local->mohawk) { SelectPage(4); /* set pin GP1 and GP2 to output (0x0c) * set GP1 to low to power up the ML6692 (0x00) * set GP2 to high to power up the 10Mhz chip (0x02) */ PutByte(XIRCREG4_GPR0, 0x0e); } /* give the circuits some time to power up */ msleep(500); /* about 500ms */ local->last_ptr_value = 0; local->silicon = local->mohawk ? (GetByte(XIRCREG4_BOV) & 0x70) >> 4 : (GetByte(XIRCREG4_BOV) & 0x30) >> 4; if (local->probe_port) { if (!local->mohawk) { SelectPage(4); PutByte(XIRCREG4_GPR0, 4); local->probe_port = 0; } } else if (dev->if_port == 2) { /* enable 10Base2 */ SelectPage(0x42); PutByte(XIRCREG42_SWC1, 0xC0); } else { /* enable 10BaseT */ SelectPage(0x42); PutByte(XIRCREG42_SWC1, 0x80); } msleep(40); /* wait 40 msec to let it complete */ #ifdef PCMCIA_DEBUG if (pc_debug) { SelectPage(0); value = GetByte(XIRCREG_ESR); /* read the ESR */ printk(KERN_DEBUG "%s: ESR is: %#02x\n", dev->name, value); } #endif /* setup the ECR */ SelectPage(1); PutByte(XIRCREG1_IMR0, 0xff); /* allow all ints */ PutByte(XIRCREG1_IMR1, 1 ); /* and Set TxUnderrunDetect */ value = GetByte(XIRCREG1_ECR); #if 0 if (local->mohawk) value |= DisableLinkPulse; PutByte(XIRCREG1_ECR, value); #endif DEBUG(0, "%s: ECR is: %#02x\n", dev->name, value); SelectPage(0x42); PutByte(XIRCREG42_SWC0, 0x20); /* disable source insertion */ if (local->silicon != 1) { /* set the local memory dividing line. * The comments in the sample code say that this is only * settable with the scipper version 2 which is revision 0. * Always for CE3 cards */ SelectPage(2); PutWord(XIRCREG2_RBS, 0x2000); } if (full) set_addresses(dev); /* Hardware workaround: * The receive byte pointer after reset is off by 1 so we need * to move the offset pointer back to 0. */ SelectPage(0); PutWord(XIRCREG0_DO, 0x2000); /* change offset command, off=0 */ /* setup MAC IMRs and clear status registers */ SelectPage(0x40); /* Bit 7 ... bit 0 */ PutByte(XIRCREG40_RMASK0, 0xff); /* ROK, RAB, rsv, RO, CRC, AE, PTL, MP */ PutByte(XIRCREG40_TMASK0, 0xff); /* TOK, TAB, SQE, LL, TU, JAB, EXC, CRS */ PutByte(XIRCREG40_TMASK1, 0xb0); /* rsv, rsv, PTD, EXT, rsv,rsv,rsv, rsv*/ PutByte(XIRCREG40_RXST0, 0x00); /* ROK, RAB, REN, RO, CRC, AE, PTL, MP */ PutByte(XIRCREG40_TXST0, 0x00); /* TOK, TAB, SQE, LL, TU, JAB, EXC, CRS */ PutByte(XIRCREG40_TXST1, 0x00); /* TEN, rsv, PTD, EXT, retry_counter:4 */ if (full && local->mohawk && init_mii(dev)) { if (dev->if_port == 4 || local->dingo || local->new_mii) { printk(KERN_INFO "%s: MII selected\n", dev->name); SelectPage(2); PutByte(XIRCREG2_MSR, GetByte(XIRCREG2_MSR) | 0x08); msleep(20); } else { printk(KERN_INFO "%s: MII detected; using 10mbs\n", dev->name); SelectPage(0x42); if (dev->if_port == 2) /* enable 10Base2 */ PutByte(XIRCREG42_SWC1, 0xC0); else /* enable 10BaseT */ PutByte(XIRCREG42_SWC1, 0x80); msleep(40); /* wait 40 msec to let it complete */ } if (full_duplex) PutByte(XIRCREG1_ECR, GetByte(XIRCREG1_ECR | FullDuplex)); } else { /* No MII */ SelectPage(0); value = GetByte(XIRCREG_ESR); /* read the ESR */ dev->if_port = (value & MediaSelect) ? 1 : 2; } /* configure the LEDs */ SelectPage(2); if (dev->if_port == 1 || dev->if_port == 4) /* TP: Link and Activity */ PutByte(XIRCREG2_LED, 0x3b); else /* Coax: Not-Collision and Activity */ PutByte(XIRCREG2_LED, 0x3a); if (local->dingo) PutByte(0x0b, 0x04); /* 100 Mbit LED */ /* enable receiver and put the mac online */ if (full) { SelectPage(0x40); PutByte(XIRCREG40_CMD0, EnableRecv | Online); } /* setup Ethernet IMR and enable interrupts */ SelectPage(1); PutByte(XIRCREG1_IMR0, 0xff); udelay(1); SelectPage(0); PutByte(XIRCREG_CR, EnableIntr); if (local->modem && !local->dingo) { /* do some magic */ if (!(GetByte(0x10) & 0x01)) PutByte(0x10, 0x11); /* unmask master-int bit */ } if (full) printk(KERN_INFO "%s: media %s, silicon revision %d\n", dev->name, if_names[dev->if_port], local->silicon); /* We should switch back to page 0 to avoid a bug in revision 0 * where regs with offset below 8 can't be read after an access * to the MAC registers */ SelectPage(0);}/**************** * Initialize the Media-Independent-Interface * Returns: True if we have a good MII */static intinit_mii(struct net_device *dev){ local_info_t *local = netdev_priv(dev); kio_addr_t ioaddr = dev->base_addr; unsigned control, status, linkpartner; int i; if (if_port == 4 || if_port == 1) { /* force 100BaseT or 10BaseT */ dev->if_port = if_port; local->probe_port = 0; return 1; } status = mii_rd(ioaddr, 0, 1); if ((status & 0xff00) != 0x7800) return 0; /* No MII */ local->new_mii = (mii_rd(ioaddr, 0, 2) != 0xffff); if (local->probe_port) control = 0x1000; /* auto neg */ else if (dev->if_port == 4) control = 0x2000; /* no auto neg, 100mbs mode */ else control = 0x0000; /* no auto neg, 10mbs mode */ mii_wr(ioaddr, 0, 0, control, 16); udelay(100); control = mii_rd(ioaddr, 0, 0); if (control & 0x0400) { printk(KERN_NOTICE "%s can't take PHY out of isolation mode\n", dev->name); local->probe_port = 0; return 0; } if (local->probe_port) { /* according to the DP83840A specs the auto negotiation process * may take up to 3.5 sec, so we use this also for our ML6692 * Fixme: Better to use a timer here! */ for (i=0; i < 35; i++) { msleep(100); /* wait 100 msec */ status = mii_rd(ioaddr, 0, 1); if ((status & 0x0020) && (status & 0x0004)) break; } if (!(status & 0x0020)) { printk(KERN_INFO "%s: autonegotiation failed;" " using 10mbs\n", dev->name); if (!local->new_mii) { control = 0x0000; mii_wr(ioaddr, 0, 0, control, 16); udelay(100); SelectPage(0); dev->if_port = (GetByte(XIRCREG_ESR) & MediaSelect) ? 1 : 2; } } else { linkpartner = mii_rd(ioaddr, 0, 5); printk(KERN_INFO "%s: MII link partner: %04x\n", dev->name, linkpartner); if (linkpartner & 0x0080) { dev->if_port = 4; } else dev->if_port = 1; } } return 1;}static voiddo_powerdown(struct net_device *dev){ kio_addr_t ioaddr = dev->base_addr; DEBUG(0, "do_powerdown(%p)\n", dev); SelectPage(4); PutByte(XIRCREG4_GPR1, 0); /* clear bit 0: power down */ SelectPage(0);}static intdo_stop(struct net_device *dev){ kio_addr_t ioaddr = dev->base_addr; local_info_t *lp = netdev_priv(dev); dev_link_t *link = &lp->link; DEBUG(0, "do_stop(%p)\n", dev); if (!link) return -ENODEV; netif_stop_queue(dev); SelectPage(0); PutByte(XIRCREG_CR, 0); /* disable interrupts */ SelectPage(0x01); PutByte(XIRCREG1_IMR0, 0x00); /* forbid all ints */ SelectPage(4); PutByte(XIRCREG4_GPR1, 0); /* clear bit 0: power down */ SelectPage(0); link->open--; return 0;}static struct pcmcia_device_id xirc2ps_ids[] = { PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0089, 0x110a), PCMCIA_PFC_DEVICE_MANF_CARD(0, 0x0138, 0x110a), PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM28", 0x2e3ee845, 0x0ea978ea), PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM33", 0x2e3ee845, 0x80609023), PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "CEM56", 0x2e3ee845, 0xa650c32a), PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "REM10", 0x2e3ee845, 0x76df1d29), PCMCIA_PFC_DEVICE_PROD_ID13(0, "Xircom", "XEM5600", 0x2e3ee845, 0xf1403719), PCMCIA_PFC_DEVICE_PROD_ID12(0, "Xircom", "CreditCard Ethernet+Modem II", 0x2e3ee845, 0xeca401bf), PCMCIA_DEVICE_MANF_CARD(0x01bf, 0x010a), PCMCIA_DEVICE_PROD_ID13("Toshiba Information Systems", "TPCENET", 0x1b3b94fe, 0xf381c1a2), PCMCIA_DEVICE_PROD_ID13("Xircom", "CE3-10/100", 0x2e3ee845, 0x0ec0ac37), PCMCIA_DEVICE_PROD_ID13("Xircom", "PS-CE2-10", 0x2e3ee845, 0x947d9073), PCMCIA_DEVICE_PROD_ID13("Xircom", "R2E-100BTX", 0x2e3ee845, 0x2464a6e3), PCMCIA_DEVICE_PROD_ID13("Xircom", "RE-10", 0x2e3ee845, 0x3e08d609), PCMCIA_DEVICE_PROD_ID13("Xircom", "XE2000", 0x2e3ee845, 0xf7188e46), PCMCIA_DEVICE_PROD_ID12("Compaq", "Ethernet LAN Card", 0x54f7c49c, 0x9fd2f0a2), PCMCIA_DEVICE_PROD_ID12("Compaq", "Netelligent 10/100 PC Card", 0x54f7c49c, 0xefe96769), PCMCIA_DEVICE_PROD_ID12("Intel", "EtherExpress(TM) PRO/100 PC Card Mobile Adapter16", 0x816cc815, 0x174397db), PCMCIA_DEVICE_PROD_ID12("Toshiba", "10/100 Ethernet PC Card", 0x44a09d9c, 0xb44deecf), /* also matches CFE-10 cards! */ /* PCMCIA_DEVICE_MANF_CARD(0x0105, 0x010a), */ PCMCIA_DEVICE_NULL,};MODULE_DEVICE_TABLE(pcmcia, xirc2ps_ids);static struct pcmcia_driver xirc2ps_cs_driver = { .owner = THIS_MODULE, .drv = { .name = "xirc2ps_cs", }, .attach = xirc2ps_attach, .event = xirc2ps_event, .detach = xirc2ps_detach, .id_table = xirc2ps_ids,};static int __initinit_xirc2ps_cs(void){ return pcmcia_register_driver(&xirc2ps_cs_driver);}static void __exitexit_xirc2ps_cs(void){ pcmcia_unregister_driver(&xirc2ps_cs_driver); BUG_ON(dev_list != NULL);}module_init(init_xirc2ps_cs);module_exit(exit_xirc2ps_cs);#ifndef MODULEstatic int __init setup_xirc2ps_cs(char *str){ /* if_port, full_duplex, do_sound, lockup_hack */ int ints[10] = { -1 }; str = get_options(str, 9, ints);#define MAYBE_SET(X,Y) if (ints[0] >= Y && ints[Y] != -1) { X = ints[Y]; } MAYBE_SET(if_port, 3); MAYBE_SET(full_duplex, 4); MAYBE_SET(do_sound, 5); MAYBE_SET(lockup_hack, 6);#undef MAYBE_SET return 0;}__setup("xirc2ps_cs=", setup_xirc2ps_cs);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -