de4x5.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:174k
- ** When autonegotiation is working, the ANS part searches the SROM for
- ** the highest common speed (TP) link that both can run and if that can
- ** be full duplex. That infoblock is executed and then the link speed set.
- **
- ** Only _10Mb and _100Mb are tested here.
- */
- static int
- dc2114x_autoconf(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
- s32 cr, anlpa, ana, cap, irqs, irq_mask, imr, omr, slnk, sr, sts;
- int next_tick = DE4X5_AUTOSENSE_MS;
- switch (lp->media) {
- case INIT:
- if (lp->timeout < 0) {
- DISABLE_IRQs;
- lp->tx_enable = FALSE;
- lp->linkOK = 0;
- lp->timeout = -1;
- de4x5_save_skbs(dev); /* Save non transmitted skb's */
- if (lp->params.autosense & ~AUTO) {
- srom_map_media(dev); /* Fixed media requested */
- if (lp->media != lp->params.autosense) {
- lp->tcount++;
- lp->media = INIT;
- return next_tick;
- }
- lp->media = INIT;
- }
- }
- if ((next_tick = de4x5_reset_phy(dev)) < 0) {
- next_tick &= ~TIMER_CB;
- } else {
- if (lp->autosense == _100Mb) {
- lp->media = _100Mb;
- } else if (lp->autosense == _10Mb) {
- lp->media = _10Mb;
- } else if (lp->autosense == TP) {
- lp->media = TP;
- } else if (lp->autosense == BNC) {
- lp->media = BNC;
- } else if (lp->autosense == AUI) {
- lp->media = AUI;
- } else {
- lp->media = SPD_DET;
- if ((lp->infoblock_media == ANS) &&
- ((sr=is_anc_capable(dev)) & MII_SR_ANC)) {
- ana = (((sr >> 6) & MII_ANA_TAF) | MII_ANA_CSMA);
- ana &= (lp->fdx ? ~0 : ~MII_ANA_FDAM);
- mii_wr(ana, MII_ANA, lp->phy[lp->active].addr, DE4X5_MII);
- lp->media = ANS;
- }
- }
- lp->local_state = 0;
- next_tick = dc2114x_autoconf(dev);
- }
- break;
-
- case ANS:
- switch (lp->local_state) {
- case 0:
- if (lp->timeout < 0) {
- mii_wr(MII_CR_ASSE | MII_CR_RAN, MII_CR, lp->phy[lp->active].addr, DE4X5_MII);
- }
- cr = test_mii_reg(dev, MII_CR, MII_CR_RAN, FALSE, 500);
- if (cr < 0) {
- next_tick = cr & ~TIMER_CB;
- } else {
- if (cr) {
- lp->local_state = 0;
- lp->media = SPD_DET;
- } else {
- lp->local_state++;
- }
- next_tick = dc2114x_autoconf(dev);
- }
- break;
-
- case 1:
- if ((sr=test_mii_reg(dev, MII_SR, MII_SR_ASSC, TRUE, 2000)) < 0) {
- next_tick = sr & ~TIMER_CB;
- } else {
- lp->media = SPD_DET;
- lp->local_state = 0;
- if (sr) { /* Success! */
- lp->tmp = MII_SR_ASSC;
- anlpa = mii_rd(MII_ANLPA, lp->phy[lp->active].addr, DE4X5_MII);
- ana = mii_rd(MII_ANA, lp->phy[lp->active].addr, DE4X5_MII);
- if (!(anlpa & MII_ANLPA_RF) &&
- (cap = anlpa & MII_ANLPA_TAF & ana)) {
- if (cap & MII_ANA_100M) {
- lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_100M) ? TRUE : FALSE);
- lp->media = _100Mb;
- } else if (cap & MII_ANA_10M) {
- lp->fdx = ((ana & anlpa & MII_ANA_FDAM & MII_ANA_10M) ? TRUE : FALSE);
- lp->media = _10Mb;
- }
- }
- } /* Auto Negotiation failed to finish */
- next_tick = dc2114x_autoconf(dev);
- } /* Auto Negotiation failed to start */
- break;
- }
- break;
- case AUI:
- if (!lp->tx_enable) {
- if (lp->timeout < 0) {
- omr = inl(DE4X5_OMR); /* Set up half duplex for AUI */
- outl(omr & ~OMR_FDX, DE4X5_OMR);
- }
- irqs = 0;
- irq_mask = 0;
- sts = test_media(dev,irqs, irq_mask, 0, 0, 0, 1000);
- if (sts < 0) {
- next_tick = sts & ~TIMER_CB;
- } else {
- if (!(inl(DE4X5_SISR) & SISR_SRA) && (lp->autosense == AUTO)) {
- lp->media = BNC;
- next_tick = dc2114x_autoconf(dev);
- } else {
- lp->local_state = 1;
- de4x5_init_connection(dev);
- }
- }
- } else if (!lp->linkOK && (lp->autosense == AUTO)) {
- lp->media = AUI_SUSPECT;
- next_tick = 3000;
- }
- break;
-
- case AUI_SUSPECT:
- next_tick = de4x5_suspect_state(dev, 1000, AUI, ping_media, dc2114x_autoconf);
- break;
-
- case BNC:
- switch (lp->local_state) {
- case 0:
- if (lp->timeout < 0) {
- omr = inl(DE4X5_OMR); /* Set up half duplex for BNC */
- outl(omr & ~OMR_FDX, DE4X5_OMR);
- }
- irqs = 0;
- irq_mask = 0;
- sts = test_media(dev,irqs, irq_mask, 0, 0, 0, 1000);
- if (sts < 0) {
- next_tick = sts & ~TIMER_CB;
- } else {
- lp->local_state++; /* Ensure media connected */
- next_tick = dc2114x_autoconf(dev);
- }
- break;
-
- case 1:
- if (!lp->tx_enable) {
- if ((sts = ping_media(dev, 3000)) < 0) {
- next_tick = sts & ~TIMER_CB;
- } else {
- if (sts) {
- lp->local_state = 0;
- lp->tcount++;
- lp->media = INIT;
- } else {
- de4x5_init_connection(dev);
- }
- }
- } else if (!lp->linkOK && (lp->autosense == AUTO)) {
- lp->media = BNC_SUSPECT;
- next_tick = 3000;
- }
- break;
- }
- break;
-
- case BNC_SUSPECT:
- next_tick = de4x5_suspect_state(dev, 1000, BNC, ping_media, dc2114x_autoconf);
- break;
-
- case SPD_DET: /* Choose 10Mb/s or 100Mb/s */
- if (srom_map_media(dev) < 0) {
- lp->tcount++;
- lp->media = INIT;
- return next_tick;
- }
- if (lp->media == _100Mb) {
- if ((slnk = test_for_100Mb(dev, 6500)) < 0) {
- lp->media = SPD_DET;
- return (slnk & ~TIMER_CB);
- }
- } else {
- if (wait_for_link(dev) < 0) {
- lp->media = SPD_DET;
- return PDET_LINK_WAIT;
- }
- }
- if (lp->media == ANS) { /* Do MII parallel detection */
- if (is_spd_100(dev)) {
- lp->media = _100Mb;
- } else {
- lp->media = _10Mb;
- }
- next_tick = dc2114x_autoconf(dev);
- } else if (((lp->media == _100Mb) && is_100_up(dev)) ||
- (((lp->media == _10Mb) || (lp->media == TP) ||
- (lp->media == BNC) || (lp->media == AUI)) &&
- is_10_up(dev))) {
- next_tick = dc2114x_autoconf(dev);
- } else {
- lp->tcount++;
- lp->media = INIT;
- }
- break;
-
- case _10Mb:
- next_tick = 3000;
- if (!lp->tx_enable) {
- SET_10Mb;
- de4x5_init_connection(dev);
- } else {
- if (!lp->linkOK && (lp->autosense == AUTO)) {
- if (!is_10_up(dev) || (!lp->useSROM && is_spd_100(dev))) {
- lp->media = INIT;
- lp->tcount++;
- next_tick = DE4X5_AUTOSENSE_MS;
- }
- }
- }
- break;
- case _100Mb:
- next_tick = 3000;
- if (!lp->tx_enable) {
- SET_100Mb;
- de4x5_init_connection(dev);
- } else {
- if (!lp->linkOK && (lp->autosense == AUTO)) {
- if (!is_100_up(dev) || (!lp->useSROM && !is_spd_100(dev))) {
- lp->media = INIT;
- lp->tcount++;
- next_tick = DE4X5_AUTOSENSE_MS;
- }
- }
- }
- break;
- default:
- lp->tcount++;
- printk("Huh?: media:%02xn", lp->media);
- lp->media = INIT;
- break;
- }
-
- return next_tick;
- }
- static int
- srom_autoconf(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- return lp->infoleaf_fn(dev);
- }
- /*
- ** This mapping keeps the original media codes and FDX flag unchanged.
- ** While it isn't strictly necessary, it helps me for the moment...
- ** The early return avoids a media state / SROM media space clash.
- */
- static int
- srom_map_media(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- lp->fdx = 0;
- if (lp->infoblock_media == lp->media)
- return 0;
- switch(lp->infoblock_media) {
- case SROM_10BASETF:
- if (!lp->params.fdx) return -1;
- lp->fdx = TRUE;
- case SROM_10BASET:
- if (lp->params.fdx && !lp->fdx) return -1;
- if ((lp->chipset == DC21140) || ((lp->chipset & ~0x00ff) == DC2114x)) {
- lp->media = _10Mb;
- } else {
- lp->media = TP;
- }
- break;
- case SROM_10BASE2:
- lp->media = BNC;
- break;
- case SROM_10BASE5:
- lp->media = AUI;
- break;
- case SROM_100BASETF:
- if (!lp->params.fdx) return -1;
- lp->fdx = TRUE;
- case SROM_100BASET:
- if (lp->params.fdx && !lp->fdx) return -1;
- lp->media = _100Mb;
- break;
- case SROM_100BASET4:
- lp->media = _100Mb;
- break;
- case SROM_100BASEFF:
- if (!lp->params.fdx) return -1;
- lp->fdx = TRUE;
- case SROM_100BASEF:
- if (lp->params.fdx && !lp->fdx) return -1;
- lp->media = _100Mb;
- break;
- case ANS:
- lp->media = ANS;
- lp->fdx = lp->params.fdx;
- break;
- default:
- printk("%s: Bad media code [%d] detected in SROM!n", dev->name,
- lp->infoblock_media);
- return -1;
- break;
- }
- return 0;
- }
- static void
- de4x5_init_connection(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
- u_long flags = 0;
- if (lp->media != lp->c_media) {
- de4x5_dbg_media(dev);
- lp->c_media = lp->media; /* Stop scrolling media messages */
- }
- spin_lock_irqsave(&lp->lock, flags);
- de4x5_rst_desc_ring(dev);
- de4x5_setup_intr(dev);
- lp->tx_enable = YES;
- spin_unlock_irqrestore(&lp->lock, flags);
- outl(POLL_DEMAND, DE4X5_TPD);
- netif_wake_queue(dev);
- return;
- }
- /*
- ** General PHY reset function. Some MII devices don't reset correctly
- ** since their MII address pins can float at voltages that are dependent
- ** on the signal pin use. Do a double reset to ensure a reset.
- */
- static int
- de4x5_reset_phy(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
- int next_tick = 0;
- if ((lp->useSROM) || (lp->phy[lp->active].id)) {
- if (lp->timeout < 0) {
- if (lp->useSROM) {
- if (lp->phy[lp->active].rst) {
- srom_exec(dev, lp->phy[lp->active].rst);
- srom_exec(dev, lp->phy[lp->active].rst);
- } else if (lp->rst) { /* Type 5 infoblock reset */
- srom_exec(dev, lp->rst);
- srom_exec(dev, lp->rst);
- }
- } else {
- PHY_HARD_RESET;
- }
- if (lp->useMII) {
- mii_wr(MII_CR_RST, MII_CR, lp->phy[lp->active].addr, DE4X5_MII);
- }
- }
- if (lp->useMII) {
- next_tick = test_mii_reg(dev, MII_CR, MII_CR_RST, FALSE, 500);
- }
- } else if (lp->chipset == DC21140) {
- PHY_HARD_RESET;
- }
- return next_tick;
- }
- static int
- test_media(struct net_device *dev, s32 irqs, s32 irq_mask, s32 csr13, s32 csr14, s32 csr15, s32 msec)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
- s32 sts, csr12;
-
- if (lp->timeout < 0) {
- lp->timeout = msec/100;
- if (!lp->useSROM) { /* Already done if by SROM, else dc2104[01] */
- reset_init_sia(dev, csr13, csr14, csr15);
- }
- /* set up the interrupt mask */
- outl(irq_mask, DE4X5_IMR);
- /* clear all pending interrupts */
- sts = inl(DE4X5_STS);
- outl(sts, DE4X5_STS);
-
- /* clear csr12 NRA and SRA bits */
- if ((lp->chipset == DC21041) || lp->useSROM) {
- csr12 = inl(DE4X5_SISR);
- outl(csr12, DE4X5_SISR);
- }
- }
-
- sts = inl(DE4X5_STS) & ~TIMER_CB;
-
- if (!(sts & irqs) && --lp->timeout) {
- sts = 100 | TIMER_CB;
- } else {
- lp->timeout = -1;
- }
-
- return sts;
- }
- static int
- test_tp(struct net_device *dev, s32 msec)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
- int sisr;
-
- if (lp->timeout < 0) {
- lp->timeout = msec/100;
- }
-
- sisr = (inl(DE4X5_SISR) & ~TIMER_CB) & (SISR_LKF | SISR_NCR);
- if (sisr && --lp->timeout) {
- sisr = 100 | TIMER_CB;
- } else {
- lp->timeout = -1;
- }
-
- return sisr;
- }
- /*
- ** Samples the 100Mb Link State Signal. The sample interval is important
- ** because too fast a rate can give erroneous results and confuse the
- ** speed sense algorithm.
- */
- #define SAMPLE_INTERVAL 500 /* ms */
- #define SAMPLE_DELAY 2000 /* ms */
- static int
- test_for_100Mb(struct net_device *dev, int msec)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- int gep = 0, ret = ((lp->chipset & ~0x00ff)==DC2114x? -1 :GEP_SLNK);
- if (lp->timeout < 0) {
- if ((msec/SAMPLE_INTERVAL) <= 0) return 0;
- if (msec > SAMPLE_DELAY) {
- lp->timeout = (msec - SAMPLE_DELAY)/SAMPLE_INTERVAL;
- gep = SAMPLE_DELAY | TIMER_CB;
- return gep;
- } else {
- lp->timeout = msec/SAMPLE_INTERVAL;
- }
- }
-
- if (lp->phy[lp->active].id || lp->useSROM) {
- gep = is_100_up(dev) | is_spd_100(dev);
- } else {
- gep = (~gep_rd(dev) & (GEP_SLNK | GEP_LNP));
- }
- if (!(gep & ret) && --lp->timeout) {
- gep = SAMPLE_INTERVAL | TIMER_CB;
- } else {
- lp->timeout = -1;
- }
-
- return gep;
- }
- static int
- wait_for_link(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- if (lp->timeout < 0) {
- lp->timeout = 1;
- }
-
- if (lp->timeout--) {
- return TIMER_CB;
- } else {
- lp->timeout = -1;
- }
-
- return 0;
- }
- /*
- **
- **
- */
- static int
- test_mii_reg(struct net_device *dev, int reg, int mask, int pol, long msec)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- int test;
- u_long iobase = dev->base_addr;
-
- if (lp->timeout < 0) {
- lp->timeout = msec/100;
- }
-
- if (pol) pol = ~0;
- reg = mii_rd((u_char)reg, lp->phy[lp->active].addr, DE4X5_MII) & mask;
- test = (reg ^ pol) & mask;
-
- if (test && --lp->timeout) {
- reg = 100 | TIMER_CB;
- } else {
- lp->timeout = -1;
- }
-
- return reg;
- }
- static int
- is_spd_100(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
- int spd;
-
- if (lp->useMII) {
- spd = mii_rd(lp->phy[lp->active].spd.reg, lp->phy[lp->active].addr, DE4X5_MII);
- spd = ~(spd ^ lp->phy[lp->active].spd.value);
- spd &= lp->phy[lp->active].spd.mask;
- } else if (!lp->useSROM) { /* de500-xa */
- spd = ((~gep_rd(dev)) & GEP_SLNK);
- } else {
- if ((lp->ibn == 2) || !lp->asBitValid)
- return ((lp->chipset == DC21143)?(~inl(DE4X5_SISR)&SISR_LS100):0);
- spd = (lp->asBitValid & (lp->asPolarity ^ (gep_rd(dev) & lp->asBit))) |
- (lp->linkOK & ~lp->asBitValid);
- }
-
- return spd;
- }
- static int
- is_100_up(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
-
- if (lp->useMII) {
- /* Double read for sticky bits & temporary drops */
- mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII);
- return (mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII) & MII_SR_LKS);
- } else if (!lp->useSROM) { /* de500-xa */
- return ((~gep_rd(dev)) & GEP_SLNK);
- } else {
- if ((lp->ibn == 2) || !lp->asBitValid)
- return ((lp->chipset == DC21143)?(~inl(DE4X5_SISR)&SISR_LS100):0);
- return ((lp->asBitValid&(lp->asPolarity^(gep_rd(dev)&lp->asBit))) |
- (lp->linkOK & ~lp->asBitValid));
- }
- }
- static int
- is_10_up(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
-
- if (lp->useMII) {
- /* Double read for sticky bits & temporary drops */
- mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII);
- return (mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII) & MII_SR_LKS);
- } else if (!lp->useSROM) { /* de500-xa */
- return ((~gep_rd(dev)) & GEP_LNP);
- } else {
- if ((lp->ibn == 2) || !lp->asBitValid)
- return (((lp->chipset & ~0x00ff) == DC2114x) ?
- (~inl(DE4X5_SISR)&SISR_LS10):
- 0);
- return ((lp->asBitValid&(lp->asPolarity^(gep_rd(dev)&lp->asBit))) |
- (lp->linkOK & ~lp->asBitValid));
- }
- }
- static int
- is_anc_capable(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
-
- if (lp->phy[lp->active].id && (!lp->useSROM || lp->useMII)) {
- return (mii_rd(MII_SR, lp->phy[lp->active].addr, DE4X5_MII));
- } else if ((lp->chipset & ~0x00ff) == DC2114x) {
- return (inl(DE4X5_SISR) & SISR_LPN) >> 12;
- } else {
- return 0;
- }
- }
- /*
- ** Send a packet onto the media and watch for send errors that indicate the
- ** media is bad or unconnected.
- */
- static int
- ping_media(struct net_device *dev, int msec)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
- int sisr;
-
- if (lp->timeout < 0) {
- lp->timeout = msec/100;
-
- lp->tmp = lp->tx_new; /* Remember the ring position */
- load_packet(dev, lp->frame, TD_LS | TD_FS | sizeof(lp->frame), (struct sk_buff *)1);
- lp->tx_new = (++lp->tx_new) % lp->txRingSize;
- outl(POLL_DEMAND, DE4X5_TPD);
- }
-
- sisr = inl(DE4X5_SISR);
- if ((!(sisr & SISR_NCR)) &&
- ((s32)le32_to_cpu(lp->tx_ring[lp->tmp].status) < 0) &&
- (--lp->timeout)) {
- sisr = 100 | TIMER_CB;
- } else {
- if ((!(sisr & SISR_NCR)) &&
- !(le32_to_cpu(lp->tx_ring[lp->tmp].status) & (T_OWN | TD_ES)) &&
- lp->timeout) {
- sisr = 0;
- } else {
- sisr = 1;
- }
- lp->timeout = -1;
- }
-
- return sisr;
- }
- /*
- ** This function does 2 things: on Intels it kmalloc's another buffer to
- ** replace the one about to be passed up. On Alpha's it kmallocs a buffer
- ** into which the packet is copied.
- */
- static struct sk_buff *
- de4x5_alloc_rx_buff(struct net_device *dev, int index, int len)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- struct sk_buff *p;
- #if !defined(__alpha__) && !defined(__powerpc__) && !defined(__sparc_v9__) && !defined(DE4X5_DO_MEMCPY)
- struct sk_buff *ret;
- u_long i=0, tmp;
- p = dev_alloc_skb(IEEE802_3_SZ + DE4X5_ALIGN + 2);
- if (!p) return NULL;
- p->dev = dev;
- tmp = virt_to_bus(p->data);
- i = ((tmp + DE4X5_ALIGN) & ~DE4X5_ALIGN) - tmp;
- skb_reserve(p, i);
- lp->rx_ring[index].buf = cpu_to_le32(tmp + i);
- ret = lp->rx_skb[index];
- lp->rx_skb[index] = p;
- if ((u_long) ret > 1) {
- skb_put(ret, len);
- }
- return ret;
- #else
- if (lp->state != OPEN) return (struct sk_buff *)1; /* Fake out the open */
- p = dev_alloc_skb(len + 2);
- if (!p) return NULL;
- p->dev = dev;
- skb_reserve(p, 2); /* Align */
- if (index < lp->rx_old) { /* Wrapped buffer */
- short tlen = (lp->rxRingSize - lp->rx_old) * RX_BUFF_SZ;
- memcpy(skb_put(p,tlen),lp->rx_bufs + lp->rx_old * RX_BUFF_SZ,tlen);
- memcpy(skb_put(p,len-tlen),lp->rx_bufs,len-tlen);
- } else { /* Linear buffer */
- memcpy(skb_put(p,len),lp->rx_bufs + lp->rx_old * RX_BUFF_SZ,len);
- }
-
- return p;
- #endif
- }
- static void
- de4x5_free_rx_buffs(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- int i;
- for (i=0; i<lp->rxRingSize; i++) {
- if ((u_long) lp->rx_skb[i] > 1) {
- dev_kfree_skb(lp->rx_skb[i]);
- }
- lp->rx_ring[i].status = 0;
- lp->rx_skb[i] = (struct sk_buff *)1; /* Dummy entry */
- }
- return;
- }
- static void
- de4x5_free_tx_buffs(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- int i;
- for (i=0; i<lp->txRingSize; i++) {
- if (lp->tx_skb[i])
- de4x5_free_tx_buff(lp, i);
- lp->tx_ring[i].status = 0;
- }
- /* Unload the locally queued packets */
- while (lp->cache.skb) {
- dev_kfree_skb(de4x5_get_cache(dev));
- }
- return;
- }
- /*
- ** When a user pulls a connection, the DECchip can end up in a
- ** 'running - waiting for end of transmission' state. This means that we
- ** have to perform a chip soft reset to ensure that we can synchronize
- ** the hardware and software and make any media probes using a loopback
- ** packet meaningful.
- */
- static void
- de4x5_save_skbs(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
- s32 omr;
- if (!lp->cache.save_cnt) {
- STOP_DE4X5;
- de4x5_tx(dev); /* Flush any sent skb's */
- de4x5_free_tx_buffs(dev);
- de4x5_cache_state(dev, DE4X5_SAVE_STATE);
- de4x5_sw_reset(dev);
- de4x5_cache_state(dev, DE4X5_RESTORE_STATE);
- lp->cache.save_cnt++;
- START_DE4X5;
- }
- return;
- }
- static void
- de4x5_rst_desc_ring(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
- int i;
- s32 omr;
- if (lp->cache.save_cnt) {
- STOP_DE4X5;
- outl(lp->dma_rings, DE4X5_RRBA);
- outl(lp->dma_rings + NUM_RX_DESC * sizeof(struct de4x5_desc),
- DE4X5_TRBA);
-
- lp->rx_new = lp->rx_old = 0;
- lp->tx_new = lp->tx_old = 0;
-
- for (i = 0; i < lp->rxRingSize; i++) {
- lp->rx_ring[i].status = cpu_to_le32(R_OWN);
- }
-
- for (i = 0; i < lp->txRingSize; i++) {
- lp->tx_ring[i].status = cpu_to_le32(0);
- }
-
- barrier();
- lp->cache.save_cnt--;
- START_DE4X5;
- }
-
- return;
- }
- static void
- de4x5_cache_state(struct net_device *dev, int flag)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
- switch(flag) {
- case DE4X5_SAVE_STATE:
- lp->cache.csr0 = inl(DE4X5_BMR);
- lp->cache.csr6 = (inl(DE4X5_OMR) & ~(OMR_ST | OMR_SR));
- lp->cache.csr7 = inl(DE4X5_IMR);
- break;
- case DE4X5_RESTORE_STATE:
- outl(lp->cache.csr0, DE4X5_BMR);
- outl(lp->cache.csr6, DE4X5_OMR);
- outl(lp->cache.csr7, DE4X5_IMR);
- if (lp->chipset == DC21140) {
- gep_wr(lp->cache.gepc, dev);
- gep_wr(lp->cache.gep, dev);
- } else {
- reset_init_sia(dev, lp->cache.csr13, lp->cache.csr14,
- lp->cache.csr15);
- }
- break;
- }
- return;
- }
- static void
- de4x5_put_cache(struct net_device *dev, struct sk_buff *skb)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- struct sk_buff *p;
- if (lp->cache.skb) {
- for (p=lp->cache.skb; p->next; p=p->next);
- p->next = skb;
- } else {
- lp->cache.skb = skb;
- }
- skb->next = NULL;
- return;
- }
- static void
- de4x5_putb_cache(struct net_device *dev, struct sk_buff *skb)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- struct sk_buff *p = lp->cache.skb;
- lp->cache.skb = skb;
- skb->next = p;
- return;
- }
- static struct sk_buff *
- de4x5_get_cache(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- struct sk_buff *p = lp->cache.skb;
- if (p) {
- lp->cache.skb = p->next;
- p->next = NULL;
- }
- return p;
- }
- /*
- ** Check the Auto Negotiation State. Return OK when a link pass interrupt
- ** is received and the auto-negotiation status is NWAY OK.
- */
- static int
- test_ans(struct net_device *dev, s32 irqs, s32 irq_mask, s32 msec)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
- s32 sts, ans;
-
- if (lp->timeout < 0) {
- lp->timeout = msec/100;
- outl(irq_mask, DE4X5_IMR);
-
- /* clear all pending interrupts */
- sts = inl(DE4X5_STS);
- outl(sts, DE4X5_STS);
- }
-
- ans = inl(DE4X5_SISR) & SISR_ANS;
- sts = inl(DE4X5_STS) & ~TIMER_CB;
-
- if (!(sts & irqs) && (ans ^ ANS_NWOK) && --lp->timeout) {
- sts = 100 | TIMER_CB;
- } else {
- lp->timeout = -1;
- }
-
- return sts;
- }
- static void
- de4x5_setup_intr(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
- s32 imr, sts;
-
- if (inl(DE4X5_OMR) & OMR_SR) { /* Only unmask if TX/RX is enabled */
- imr = 0;
- UNMASK_IRQs;
- sts = inl(DE4X5_STS); /* Reset any pending (stale) interrupts */
- outl(sts, DE4X5_STS);
- ENABLE_IRQs;
- }
-
- return;
- }
- /*
- **
- */
- static void
- reset_init_sia(struct net_device *dev, s32 csr13, s32 csr14, s32 csr15)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
- RESET_SIA;
- if (lp->useSROM) {
- if (lp->ibn == 3) {
- srom_exec(dev, lp->phy[lp->active].rst);
- srom_exec(dev, lp->phy[lp->active].gep);
- outl(1, DE4X5_SICR);
- return;
- } else {
- csr15 = lp->cache.csr15;
- csr14 = lp->cache.csr14;
- csr13 = lp->cache.csr13;
- outl(csr15 | lp->cache.gepc, DE4X5_SIGR);
- outl(csr15 | lp->cache.gep, DE4X5_SIGR);
- }
- } else {
- outl(csr15, DE4X5_SIGR);
- }
- outl(csr14, DE4X5_STRR);
- outl(csr13, DE4X5_SICR);
- mdelay(10);
- return;
- }
- /*
- ** Create a loopback ethernet packet
- */
- static void
- create_packet(struct net_device *dev, char *frame, int len)
- {
- int i;
- char *buf = frame;
-
- for (i=0; i<ETH_ALEN; i++) { /* Use this source address */
- *buf++ = dev->dev_addr[i];
- }
- for (i=0; i<ETH_ALEN; i++) { /* Use this destination address */
- *buf++ = dev->dev_addr[i];
- }
-
- *buf++ = 0; /* Packet length (2 bytes) */
- *buf++ = 1;
-
- return;
- }
- /*
- ** Look for a particular board name in the EISA configuration space
- */
- static int
- EISA_signature(char *name, s32 eisa_id)
- {
- static c_char *signatures[] = DE4X5_SIGNATURE;
- char ManCode[DE4X5_STRLEN];
- union {
- s32 ID;
- char Id[4];
- } Eisa;
- int i, status = 0, siglen = sizeof(signatures)/sizeof(c_char *);
-
- *name = ' ';
- Eisa.ID = inl(eisa_id);
-
- ManCode[0]=(((Eisa.Id[0]>>2)&0x1f)+0x40);
- ManCode[1]=(((Eisa.Id[1]&0xe0)>>5)+((Eisa.Id[0]&0x03)<<3)+0x40);
- ManCode[2]=(((Eisa.Id[2]>>4)&0x0f)+0x30);
- ManCode[3]=((Eisa.Id[2]&0x0f)+0x30);
- ManCode[4]=(((Eisa.Id[3]>>4)&0x0f)+0x30);
- ManCode[5]=' ';
-
- for (i=0;i<siglen;i++) {
- if (strstr(ManCode, signatures[i]) != NULL) {
- strcpy(name,ManCode);
- status = 1;
- break;
- }
- }
-
- return status; /* return the device name string */
- }
- /*
- ** Look for a particular board name in the PCI configuration space
- */
- static int
- PCI_signature(char *name, struct de4x5_bus_type *lp)
- {
- static c_char *de4x5_signatures[] = DE4X5_SIGNATURE;
- int i, status = 0, siglen = sizeof(de4x5_signatures)/sizeof(c_char *);
-
- if (lp->chipset == DC21040) {
- strcpy(name, "DE434/5");
- return status;
- } else { /* Search for a DEC name in the SROM */
- int i = *((char *)&lp->srom + 19) * 3;
- strncpy(name, (char *)&lp->srom + 26 + i, 8);
- }
- name[8] = ' ';
- for (i=0; i<siglen; i++) {
- if (strstr(name,de4x5_signatures[i])!=NULL) break;
- }
- if (i == siglen) {
- if (dec_only) {
- *name = ' ';
- } else { /* Use chip name to avoid confusion */
- strcpy(name, (((lp->chipset == DC21040) ? "DC21040" :
- ((lp->chipset == DC21041) ? "DC21041" :
- ((lp->chipset == DC21140) ? "DC21140" :
- ((lp->chipset == DC21142) ? "DC21142" :
- ((lp->chipset == DC21143) ? "DC21143" : "UNKNOWN"
- )))))));
- }
- if (lp->chipset != DC21041) {
- useSROM = TRUE; /* card is not recognisably DEC */
- }
- } else if ((lp->chipset & ~0x00ff) == DC2114x) {
- useSROM = TRUE;
- }
-
- return status;
- }
- /*
- ** Set up the Ethernet PROM counter to the start of the Ethernet address on
- ** the DC21040, else read the SROM for the other chips.
- ** The SROM may not be present in a multi-MAC card, so first read the
- ** MAC address and check for a bad address. If there is a bad one then exit
- ** immediately with the prior srom contents intact (the h/w address will
- ** be fixed up later).
- */
- static void
- DevicePresent(u_long aprom_addr)
- {
- int i, j=0;
- struct de4x5_bus_type *lp = &bus;
-
- if (lp->chipset == DC21040) {
- if (lp->bus == EISA) {
- enet_addr_rst(aprom_addr); /* Reset Ethernet Address ROM Pointer */
- } else {
- outl(0, aprom_addr); /* Reset Ethernet Address ROM Pointer */
- }
- } else { /* Read new srom */
- u_short tmp, *p = (short *)((char *)&lp->srom + SROM_HWADD);
- for (i=0; i<(ETH_ALEN>>1); i++) {
- tmp = srom_rd(aprom_addr, (SROM_HWADD>>1) + i);
- *p = le16_to_cpu(tmp);
- j += *p++;
- }
- if ((j == 0) || (j == 0x2fffd)) {
- return;
- }
- p=(short *)&lp->srom;
- for (i=0; i<(sizeof(struct de4x5_srom)>>1); i++) {
- tmp = srom_rd(aprom_addr, i);
- *p++ = le16_to_cpu(tmp);
- }
- de4x5_dbg_srom((struct de4x5_srom *)&lp->srom);
- }
-
- return;
- }
- /*
- ** Since the write on the Enet PROM register doesn't seem to reset the PROM
- ** pointer correctly (at least on my DE425 EISA card), this routine should do
- ** it...from depca.c.
- */
- static void
- enet_addr_rst(u_long aprom_addr)
- {
- union {
- struct {
- u32 a;
- u32 b;
- } llsig;
- char Sig[sizeof(u32) << 1];
- } dev;
- short sigLength=0;
- s8 data;
- int i, j;
-
- dev.llsig.a = ETH_PROM_SIG;
- dev.llsig.b = ETH_PROM_SIG;
- sigLength = sizeof(u32) << 1;
-
- for (i=0,j=0;j<sigLength && i<PROBE_LENGTH+sigLength-1;i++) {
- data = inb(aprom_addr);
- if (dev.Sig[j] == data) { /* track signature */
- j++;
- } else { /* lost signature; begin search again */
- if (data == dev.Sig[0]) { /* rare case.... */
- j=1;
- } else {
- j=0;
- }
- }
- }
-
- return;
- }
- /*
- ** For the bad status case and no SROM, then add one to the previous
- ** address. However, need to add one backwards in case we have 0xff
- ** as one or more of the bytes. Only the last 3 bytes should be checked
- ** as the first three are invariant - assigned to an organisation.
- */
- static int
- get_hw_addr(struct net_device *dev)
- {
- u_long iobase = dev->base_addr;
- int broken, i, k, tmp, status = 0;
- u_short j,chksum;
- struct de4x5_bus_type *lp = &bus;
- broken = de4x5_bad_srom(lp);
- for (i=0,k=0,j=0;j<3;j++) {
- k <<= 1;
- if (k > 0xffff) k-=0xffff;
-
- if (lp->bus == PCI) {
- if (lp->chipset == DC21040) {
- while ((tmp = inl(DE4X5_APROM)) < 0);
- k += (u_char) tmp;
- dev->dev_addr[i++] = (u_char) tmp;
- while ((tmp = inl(DE4X5_APROM)) < 0);
- k += (u_short) (tmp << 8);
- dev->dev_addr[i++] = (u_char) tmp;
- } else if (!broken) {
- dev->dev_addr[i] = (u_char) lp->srom.ieee_addr[i]; i++;
- dev->dev_addr[i] = (u_char) lp->srom.ieee_addr[i]; i++;
- } else if ((broken == SMC) || (broken == ACCTON)) {
- dev->dev_addr[i] = *((u_char *)&lp->srom + i); i++;
- dev->dev_addr[i] = *((u_char *)&lp->srom + i); i++;
- }
- } else {
- k += (u_char) (tmp = inb(EISA_APROM));
- dev->dev_addr[i++] = (u_char) tmp;
- k += (u_short) ((tmp = inb(EISA_APROM)) << 8);
- dev->dev_addr[i++] = (u_char) tmp;
- }
-
- if (k > 0xffff) k-=0xffff;
- }
- if (k == 0xffff) k=0;
-
- if (lp->bus == PCI) {
- if (lp->chipset == DC21040) {
- while ((tmp = inl(DE4X5_APROM)) < 0);
- chksum = (u_char) tmp;
- while ((tmp = inl(DE4X5_APROM)) < 0);
- chksum |= (u_short) (tmp << 8);
- if ((k != chksum) && (dec_only)) status = -1;
- }
- } else {
- chksum = (u_char) inb(EISA_APROM);
- chksum |= (u_short) (inb(EISA_APROM) << 8);
- if ((k != chksum) && (dec_only)) status = -1;
- }
- /* If possible, try to fix a broken card - SMC only so far */
- srom_repair(dev, broken);
- #ifdef CONFIG_PPC
- /*
- ** If the address starts with 00 a0, we have to bit-reverse
- ** each byte of the address.
- */
- if ( (ppc_md.ppc_machine & _MACH_Pmac) &&
- (dev->dev_addr[0] == 0) &&
- (dev->dev_addr[1] == 0xa0) )
- {
- for (i = 0; i < ETH_ALEN; ++i)
- {
- int x = dev->dev_addr[i];
- x = ((x & 0xf) << 4) + ((x & 0xf0) >> 4);
- x = ((x & 0x33) << 2) + ((x & 0xcc) >> 2);
- dev->dev_addr[i] = ((x & 0x55) << 1) + ((x & 0xaa) >> 1);
- }
- }
- #endif /* CONFIG_PPC */
- /* Test for a bad enet address */
- status = test_bad_enet(dev, status);
- return status;
- }
- /*
- ** Test for enet addresses in the first 32 bytes. The built-in strncmp
- ** didn't seem to work here...?
- */
- static int
- de4x5_bad_srom(struct de4x5_bus_type *lp)
- {
- int i, status = 0;
- for (i=0; i<sizeof(enet_det)/ETH_ALEN; i++) {
- if (!de4x5_strncmp((char *)&lp->srom, (char *)&enet_det[i], 3) &&
- !de4x5_strncmp((char *)&lp->srom+0x10, (char *)&enet_det[i], 3)) {
- if (i == 0) {
- status = SMC;
- } else if (i == 1) {
- status = ACCTON;
- }
- break;
- }
- }
- return status;
- }
- static int
- de4x5_strncmp(char *a, char *b, int n)
- {
- int ret=0;
- for (;n && !ret;n--) {
- ret = *a++ - *b++;
- }
- return ret;
- }
- static void
- srom_repair(struct net_device *dev, int card)
- {
- struct de4x5_bus_type *lp = &bus;
- switch(card) {
- case SMC:
- memset((char *)&bus.srom, 0, sizeof(struct de4x5_srom));
- memcpy(lp->srom.ieee_addr, (char *)dev->dev_addr, ETH_ALEN);
- memcpy(lp->srom.info, (char *)&srom_repair_info[SMC-1], 100);
- useSROM = TRUE;
- break;
- }
- return;
- }
- /*
- ** Assume that the irq's do not follow the PCI spec - this is seems
- ** to be true so far (2 for 2).
- */
- static int
- test_bad_enet(struct net_device *dev, int status)
- {
- struct de4x5_bus_type *lp = &bus;
- int i, tmp;
- for (tmp=0,i=0; i<ETH_ALEN; i++) tmp += (u_char)dev->dev_addr[i];
- if ((tmp == 0) || (tmp == 0x5fa)) {
- if ((lp->chipset == last.chipset) &&
- (lp->bus_num == last.bus) && (lp->bus_num > 0)) {
- for (i=0; i<ETH_ALEN; i++) dev->dev_addr[i] = last.addr[i];
- for (i=ETH_ALEN-1; i>2; --i) {
- dev->dev_addr[i] += 1;
- if (dev->dev_addr[i] != 0) break;
- }
- for (i=0; i<ETH_ALEN; i++) last.addr[i] = dev->dev_addr[i];
- if (!an_exception(lp)) {
- dev->irq = last.irq;
- }
- status = 0;
- }
- } else if (!status) {
- last.chipset = lp->chipset;
- last.bus = lp->bus_num;
- last.irq = dev->irq;
- for (i=0; i<ETH_ALEN; i++) last.addr[i] = dev->dev_addr[i];
- }
- return status;
- }
- /*
- ** List of board exceptions with correctly wired IRQs
- */
- static int
- an_exception(struct de4x5_bus_type *lp)
- {
- if ((*(u_short *)lp->srom.sub_vendor_id == 0x00c0) &&
- (*(u_short *)lp->srom.sub_system_id == 0x95e0)) {
- return -1;
- }
- return 0;
- }
- /*
- ** SROM Read
- */
- static short
- srom_rd(u_long addr, u_char offset)
- {
- sendto_srom(SROM_RD | SROM_SR, addr);
-
- srom_latch(SROM_RD | SROM_SR | DT_CS, addr);
- srom_command(SROM_RD | SROM_SR | DT_IN | DT_CS, addr);
- srom_address(SROM_RD | SROM_SR | DT_CS, addr, offset);
-
- return srom_data(SROM_RD | SROM_SR | DT_CS, addr);
- }
- static void
- srom_latch(u_int command, u_long addr)
- {
- sendto_srom(command, addr);
- sendto_srom(command | DT_CLK, addr);
- sendto_srom(command, addr);
-
- return;
- }
- static void
- srom_command(u_int command, u_long addr)
- {
- srom_latch(command, addr);
- srom_latch(command, addr);
- srom_latch((command & 0x0000ff00) | DT_CS, addr);
-
- return;
- }
- static void
- srom_address(u_int command, u_long addr, u_char offset)
- {
- int i, a;
-
- a = offset << 2;
- for (i=0; i<6; i++, a <<= 1) {
- srom_latch(command | ((a & 0x80) ? DT_IN : 0), addr);
- }
- udelay(1);
-
- i = (getfrom_srom(addr) >> 3) & 0x01;
-
- return;
- }
- static short
- srom_data(u_int command, u_long addr)
- {
- int i;
- short word = 0;
- s32 tmp;
-
- for (i=0; i<16; i++) {
- sendto_srom(command | DT_CLK, addr);
- tmp = getfrom_srom(addr);
- sendto_srom(command, addr);
-
- word = (word << 1) | ((tmp >> 3) & 0x01);
- }
-
- sendto_srom(command & 0x0000ff00, addr);
-
- return word;
- }
- /*
- static void
- srom_busy(u_int command, u_long addr)
- {
- sendto_srom((command & 0x0000ff00) | DT_CS, addr);
-
- while (!((getfrom_srom(addr) >> 3) & 0x01)) {
- mdelay(1);
- }
-
- sendto_srom(command & 0x0000ff00, addr);
-
- return;
- }
- */
- static void
- sendto_srom(u_int command, u_long addr)
- {
- outl(command, addr);
- udelay(1);
-
- return;
- }
- static int
- getfrom_srom(u_long addr)
- {
- s32 tmp;
-
- tmp = inl(addr);
- udelay(1);
-
- return tmp;
- }
- static int
- srom_infoleaf_info(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- int i, count;
- u_char *p;
- /* Find the infoleaf decoder function that matches this chipset */
- for (i=0; i<INFOLEAF_SIZE; i++) {
- if (lp->chipset == infoleaf_array[i].chipset) break;
- }
- if (i == INFOLEAF_SIZE) {
- lp->useSROM = FALSE;
- printk("%s: Cannot find correct chipset for SROM decoding!n",
- dev->name);
- return -ENXIO;
- }
- lp->infoleaf_fn = infoleaf_array[i].fn;
- /* Find the information offset that this function should use */
- count = *((u_char *)&lp->srom + 19);
- p = (u_char *)&lp->srom + 26;
- if (count > 1) {
- for (i=count; i; --i, p+=3) {
- if (lp->device == *p) break;
- }
- if (i == 0) {
- lp->useSROM = FALSE;
- printk("%s: Cannot find correct PCI device [%d] for SROM decoding!n",
- dev->name, lp->device);
- return -ENXIO;
- }
- }
- lp->infoleaf_offset = TWIDDLE(p+1);
- return 0;
- }
- /*
- ** This routine loads any type 1 or 3 MII info into the mii device
- ** struct and executes any type 5 code to reset PHY devices for this
- ** controller.
- ** The info for the MII devices will be valid since the index used
- ** will follow the discovery process from MII address 1-31 then 0.
- */
- static void
- srom_init(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_char *p = (u_char *)&lp->srom + lp->infoleaf_offset;
- u_char count;
- p+=2;
- if (lp->chipset == DC21140) {
- lp->cache.gepc = (*p++ | GEP_CTRL);
- gep_wr(lp->cache.gepc, dev);
- }
- /* Block count */
- count = *p++;
- /* Jump the infoblocks to find types */
- for (;count; --count) {
- if (*p < 128) {
- p += COMPACT_LEN;
- } else if (*(p+1) == 5) {
- type5_infoblock(dev, 1, p);
- p += ((*p & BLOCK_LEN) + 1);
- } else if (*(p+1) == 4) {
- p += ((*p & BLOCK_LEN) + 1);
- } else if (*(p+1) == 3) {
- type3_infoblock(dev, 1, p);
- p += ((*p & BLOCK_LEN) + 1);
- } else if (*(p+1) == 2) {
- p += ((*p & BLOCK_LEN) + 1);
- } else if (*(p+1) == 1) {
- type1_infoblock(dev, 1, p);
- p += ((*p & BLOCK_LEN) + 1);
- } else {
- p += ((*p & BLOCK_LEN) + 1);
- }
- }
- return;
- }
- /*
- ** A generic routine that writes GEP control, data and reset information
- ** to the GEP register (21140) or csr15 GEP portion (2114[23]).
- */
- static void
- srom_exec(struct net_device *dev, u_char *p)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
- u_char count = (p ? *p++ : 0);
- u_short *w = (u_short *)p;
- if (((lp->ibn != 1) && (lp->ibn != 3) && (lp->ibn != 5)) || !count) return;
- if (lp->chipset != DC21140) RESET_SIA;
-
- while (count--) {
- gep_wr(((lp->chipset==DC21140) && (lp->ibn!=5) ?
- *p++ : TWIDDLE(w++)), dev);
- mdelay(2); /* 2ms per action */
- }
- if (lp->chipset != DC21140) {
- outl(lp->cache.csr14, DE4X5_STRR);
- outl(lp->cache.csr13, DE4X5_SICR);
- }
- return;
- }
- /*
- ** Basically this function is a NOP since it will never be called,
- ** unless I implement the DC21041 SROM functions. There's no need
- ** since the existing code will be satisfactory for all boards.
- */
- static int
- dc21041_infoleaf(struct net_device *dev)
- {
- return DE4X5_AUTOSENSE_MS;
- }
- static int
- dc21140_infoleaf(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_char count = 0;
- u_char *p = (u_char *)&lp->srom + lp->infoleaf_offset;
- int next_tick = DE4X5_AUTOSENSE_MS;
- /* Read the connection type */
- p+=2;
- /* GEP control */
- lp->cache.gepc = (*p++ | GEP_CTRL);
- /* Block count */
- count = *p++;
- /* Recursively figure out the info blocks */
- if (*p < 128) {
- next_tick = dc_infoblock[COMPACT](dev, count, p);
- } else {
- next_tick = dc_infoblock[*(p+1)](dev, count, p);
- }
- if (lp->tcount == count) {
- lp->media = NC;
- if (lp->media != lp->c_media) {
- de4x5_dbg_media(dev);
- lp->c_media = lp->media;
- }
- lp->media = INIT;
- lp->tcount = 0;
- lp->tx_enable = FALSE;
- }
- return next_tick & ~TIMER_CB;
- }
- static int
- dc21142_infoleaf(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_char count = 0;
- u_char *p = (u_char *)&lp->srom + lp->infoleaf_offset;
- int next_tick = DE4X5_AUTOSENSE_MS;
- /* Read the connection type */
- p+=2;
- /* Block count */
- count = *p++;
- /* Recursively figure out the info blocks */
- if (*p < 128) {
- next_tick = dc_infoblock[COMPACT](dev, count, p);
- } else {
- next_tick = dc_infoblock[*(p+1)](dev, count, p);
- }
- if (lp->tcount == count) {
- lp->media = NC;
- if (lp->media != lp->c_media) {
- de4x5_dbg_media(dev);
- lp->c_media = lp->media;
- }
- lp->media = INIT;
- lp->tcount = 0;
- lp->tx_enable = FALSE;
- }
- return next_tick & ~TIMER_CB;
- }
- static int
- dc21143_infoleaf(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_char count = 0;
- u_char *p = (u_char *)&lp->srom + lp->infoleaf_offset;
- int next_tick = DE4X5_AUTOSENSE_MS;
- /* Read the connection type */
- p+=2;
- /* Block count */
- count = *p++;
- /* Recursively figure out the info blocks */
- if (*p < 128) {
- next_tick = dc_infoblock[COMPACT](dev, count, p);
- } else {
- next_tick = dc_infoblock[*(p+1)](dev, count, p);
- }
- if (lp->tcount == count) {
- lp->media = NC;
- if (lp->media != lp->c_media) {
- de4x5_dbg_media(dev);
- lp->c_media = lp->media;
- }
- lp->media = INIT;
- lp->tcount = 0;
- lp->tx_enable = FALSE;
- }
- return next_tick & ~TIMER_CB;
- }
- /*
- ** The compact infoblock is only designed for DC21140[A] chips, so
- ** we'll reuse the dc21140m_autoconf function. Non MII media only.
- */
- static int
- compact_infoblock(struct net_device *dev, u_char count, u_char *p)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_char flags, csr6;
- /* Recursively figure out the info blocks */
- if (--count > lp->tcount) {
- if (*(p+COMPACT_LEN) < 128) {
- return dc_infoblock[COMPACT](dev, count, p+COMPACT_LEN);
- } else {
- return dc_infoblock[*(p+COMPACT_LEN+1)](dev, count, p+COMPACT_LEN);
- }
- }
- if ((lp->media == INIT) && (lp->timeout < 0)) {
- lp->ibn = COMPACT;
- lp->active = 0;
- gep_wr(lp->cache.gepc, dev);
- lp->infoblock_media = (*p++) & COMPACT_MC;
- lp->cache.gep = *p++;
- csr6 = *p++;
- flags = *p++;
- lp->asBitValid = (flags & 0x80) ? 0 : -1;
- lp->defMedium = (flags & 0x40) ? -1 : 0;
- lp->asBit = 1 << ((csr6 >> 1) & 0x07);
- lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
- lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
- lp->useMII = FALSE;
- de4x5_switch_mac_port(dev);
- }
- return dc21140m_autoconf(dev);
- }
- /*
- ** This block describes non MII media for the DC21140[A] only.
- */
- static int
- type0_infoblock(struct net_device *dev, u_char count, u_char *p)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_char flags, csr6, len = (*p & BLOCK_LEN)+1;
- /* Recursively figure out the info blocks */
- if (--count > lp->tcount) {
- if (*(p+len) < 128) {
- return dc_infoblock[COMPACT](dev, count, p+len);
- } else {
- return dc_infoblock[*(p+len+1)](dev, count, p+len);
- }
- }
- if ((lp->media == INIT) && (lp->timeout < 0)) {
- lp->ibn = 0;
- lp->active = 0;
- gep_wr(lp->cache.gepc, dev);
- p+=2;
- lp->infoblock_media = (*p++) & BLOCK0_MC;
- lp->cache.gep = *p++;
- csr6 = *p++;
- flags = *p++;
- lp->asBitValid = (flags & 0x80) ? 0 : -1;
- lp->defMedium = (flags & 0x40) ? -1 : 0;
- lp->asBit = 1 << ((csr6 >> 1) & 0x07);
- lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
- lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
- lp->useMII = FALSE;
- de4x5_switch_mac_port(dev);
- }
- return dc21140m_autoconf(dev);
- }
- /* These functions are under construction! */
- static int
- type1_infoblock(struct net_device *dev, u_char count, u_char *p)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_char len = (*p & BLOCK_LEN)+1;
- /* Recursively figure out the info blocks */
- if (--count > lp->tcount) {
- if (*(p+len) < 128) {
- return dc_infoblock[COMPACT](dev, count, p+len);
- } else {
- return dc_infoblock[*(p+len+1)](dev, count, p+len);
- }
- }
- p += 2;
- if (lp->state == INITIALISED) {
- lp->ibn = 1;
- lp->active = *p++;
- lp->phy[lp->active].gep = (*p ? p : 0); p += (*p + 1);
- lp->phy[lp->active].rst = (*p ? p : 0); p += (*p + 1);
- lp->phy[lp->active].mc = TWIDDLE(p); p += 2;
- lp->phy[lp->active].ana = TWIDDLE(p); p += 2;
- lp->phy[lp->active].fdx = TWIDDLE(p); p += 2;
- lp->phy[lp->active].ttm = TWIDDLE(p);
- return 0;
- } else if ((lp->media == INIT) && (lp->timeout < 0)) {
- lp->ibn = 1;
- lp->active = *p;
- lp->infoblock_csr6 = OMR_MII_100;
- lp->useMII = TRUE;
- lp->infoblock_media = ANS;
- de4x5_switch_mac_port(dev);
- }
- return dc21140m_autoconf(dev);
- }
- static int
- type2_infoblock(struct net_device *dev, u_char count, u_char *p)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_char len = (*p & BLOCK_LEN)+1;
- /* Recursively figure out the info blocks */
- if (--count > lp->tcount) {
- if (*(p+len) < 128) {
- return dc_infoblock[COMPACT](dev, count, p+len);
- } else {
- return dc_infoblock[*(p+len+1)](dev, count, p+len);
- }
- }
- if ((lp->media == INIT) && (lp->timeout < 0)) {
- lp->ibn = 2;
- lp->active = 0;
- p += 2;
- lp->infoblock_media = (*p) & MEDIA_CODE;
- if ((*p++) & EXT_FIELD) {
- lp->cache.csr13 = TWIDDLE(p); p += 2;
- lp->cache.csr14 = TWIDDLE(p); p += 2;
- lp->cache.csr15 = TWIDDLE(p); p += 2;
- } else {
- lp->cache.csr13 = CSR13;
- lp->cache.csr14 = CSR14;
- lp->cache.csr15 = CSR15;
- }
- lp->cache.gepc = ((s32)(TWIDDLE(p)) << 16); p += 2;
- lp->cache.gep = ((s32)(TWIDDLE(p)) << 16);
- lp->infoblock_csr6 = OMR_SIA;
- lp->useMII = FALSE;
- de4x5_switch_mac_port(dev);
- }
- return dc2114x_autoconf(dev);
- }
- static int
- type3_infoblock(struct net_device *dev, u_char count, u_char *p)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_char len = (*p & BLOCK_LEN)+1;
- /* Recursively figure out the info blocks */
- if (--count > lp->tcount) {
- if (*(p+len) < 128) {
- return dc_infoblock[COMPACT](dev, count, p+len);
- } else {
- return dc_infoblock[*(p+len+1)](dev, count, p+len);
- }
- }
- p += 2;
- if (lp->state == INITIALISED) {
- lp->ibn = 3;
- lp->active = *p++;
- if (MOTO_SROM_BUG) lp->active = 0;
- lp->phy[lp->active].gep = (*p ? p : 0); p += (2 * (*p) + 1);
- lp->phy[lp->active].rst = (*p ? p : 0); p += (2 * (*p) + 1);
- lp->phy[lp->active].mc = TWIDDLE(p); p += 2;
- lp->phy[lp->active].ana = TWIDDLE(p); p += 2;
- lp->phy[lp->active].fdx = TWIDDLE(p); p += 2;
- lp->phy[lp->active].ttm = TWIDDLE(p); p += 2;
- lp->phy[lp->active].mci = *p;
- return 0;
- } else if ((lp->media == INIT) && (lp->timeout < 0)) {
- lp->ibn = 3;
- lp->active = *p;
- if (MOTO_SROM_BUG) lp->active = 0;
- lp->infoblock_csr6 = OMR_MII_100;
- lp->useMII = TRUE;
- lp->infoblock_media = ANS;
- de4x5_switch_mac_port(dev);
- }
- return dc2114x_autoconf(dev);
- }
- static int
- type4_infoblock(struct net_device *dev, u_char count, u_char *p)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_char flags, csr6, len = (*p & BLOCK_LEN)+1;
- /* Recursively figure out the info blocks */
- if (--count > lp->tcount) {
- if (*(p+len) < 128) {
- return dc_infoblock[COMPACT](dev, count, p+len);
- } else {
- return dc_infoblock[*(p+len+1)](dev, count, p+len);
- }
- }
- if ((lp->media == INIT) && (lp->timeout < 0)) {
- lp->ibn = 4;
- lp->active = 0;
- p+=2;
- lp->infoblock_media = (*p++) & MEDIA_CODE;
- lp->cache.csr13 = CSR13; /* Hard coded defaults */
- lp->cache.csr14 = CSR14;
- lp->cache.csr15 = CSR15;
- lp->cache.gepc = ((s32)(TWIDDLE(p)) << 16); p += 2;
- lp->cache.gep = ((s32)(TWIDDLE(p)) << 16); p += 2;
- csr6 = *p++;
- flags = *p++;
- lp->asBitValid = (flags & 0x80) ? 0 : -1;
- lp->defMedium = (flags & 0x40) ? -1 : 0;
- lp->asBit = 1 << ((csr6 >> 1) & 0x07);
- lp->asPolarity = ((csr6 & 0x80) ? -1 : 0) & lp->asBit;
- lp->infoblock_csr6 = OMR_DEF | ((csr6 & 0x71) << 18);
- lp->useMII = FALSE;
- de4x5_switch_mac_port(dev);
- }
- return dc2114x_autoconf(dev);
- }
- /*
- ** This block type provides information for resetting external devices
- ** (chips) through the General Purpose Register.
- */
- static int
- type5_infoblock(struct net_device *dev, u_char count, u_char *p)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_char len = (*p & BLOCK_LEN)+1;
- /* Recursively figure out the info blocks */
- if (--count > lp->tcount) {
- if (*(p+len) < 128) {
- return dc_infoblock[COMPACT](dev, count, p+len);
- } else {
- return dc_infoblock[*(p+len+1)](dev, count, p+len);
- }
- }
- /* Must be initializing to run this code */
- if ((lp->state == INITIALISED) || (lp->media == INIT)) {
- p+=2;
- lp->rst = p;
- srom_exec(dev, lp->rst);
- }
- return DE4X5_AUTOSENSE_MS;
- }
- /*
- ** MII Read/Write
- */
- static int
- mii_rd(u_char phyreg, u_char phyaddr, u_long ioaddr)
- {
- mii_wdata(MII_PREAMBLE, 2, ioaddr); /* Start of 34 bit preamble... */
- mii_wdata(MII_PREAMBLE, 32, ioaddr); /* ...continued */
- mii_wdata(MII_STRD, 4, ioaddr); /* SFD and Read operation */
- mii_address(phyaddr, ioaddr); /* PHY address to be accessed */
- mii_address(phyreg, ioaddr); /* PHY Register to read */
- mii_ta(MII_STRD, ioaddr); /* Turn around time - 2 MDC */
-
- return mii_rdata(ioaddr); /* Read data */
- }
- static void
- mii_wr(int data, u_char phyreg, u_char phyaddr, u_long ioaddr)
- {
- mii_wdata(MII_PREAMBLE, 2, ioaddr); /* Start of 34 bit preamble... */
- mii_wdata(MII_PREAMBLE, 32, ioaddr); /* ...continued */
- mii_wdata(MII_STWR, 4, ioaddr); /* SFD and Write operation */
- mii_address(phyaddr, ioaddr); /* PHY address to be accessed */
- mii_address(phyreg, ioaddr); /* PHY Register to write */
- mii_ta(MII_STWR, ioaddr); /* Turn around time - 2 MDC */
- data = mii_swap(data, 16); /* Swap data bit ordering */
- mii_wdata(data, 16, ioaddr); /* Write data */
-
- return;
- }
- static int
- mii_rdata(u_long ioaddr)
- {
- int i;
- s32 tmp = 0;
-
- for (i=0; i<16; i++) {
- tmp <<= 1;
- tmp |= getfrom_mii(MII_MRD | MII_RD, ioaddr);
- }
-
- return tmp;
- }
- static void
- mii_wdata(int data, int len, u_long ioaddr)
- {
- int i;
-
- for (i=0; i<len; i++) {
- sendto_mii(MII_MWR | MII_WR, data, ioaddr);
- data >>= 1;
- }
-
- return;
- }
- static void
- mii_address(u_char addr, u_long ioaddr)
- {
- int i;
-
- addr = mii_swap(addr, 5);
- for (i=0; i<5; i++) {
- sendto_mii(MII_MWR | MII_WR, addr, ioaddr);
- addr >>= 1;
- }
-
- return;
- }
- static void
- mii_ta(u_long rw, u_long ioaddr)
- {
- if (rw == MII_STWR) {
- sendto_mii(MII_MWR | MII_WR, 1, ioaddr);
- sendto_mii(MII_MWR | MII_WR, 0, ioaddr);
- } else {
- getfrom_mii(MII_MRD | MII_RD, ioaddr); /* Tri-state MDIO */
- }
-
- return;
- }
- static int
- mii_swap(int data, int len)
- {
- int i, tmp = 0;
-
- for (i=0; i<len; i++) {
- tmp <<= 1;
- tmp |= (data & 1);
- data >>= 1;
- }
-
- return tmp;
- }
- static void
- sendto_mii(u32 command, int data, u_long ioaddr)
- {
- u32 j;
-
- j = (data & 1) << 17;
- outl(command | j, ioaddr);
- udelay(1);
- outl(command | MII_MDC | j, ioaddr);
- udelay(1);
-
- return;
- }
- static int
- getfrom_mii(u32 command, u_long ioaddr)
- {
- outl(command, ioaddr);
- udelay(1);
- outl(command | MII_MDC, ioaddr);
- udelay(1);
-
- return ((inl(ioaddr) >> 19) & 1);
- }
- /*
- ** Here's 3 ways to calculate the OUI from the ID registers.
- */
- static int
- mii_get_oui(u_char phyaddr, u_long ioaddr)
- {
- /*
- union {
- u_short reg;
- u_char breg[2];
- } a;
- int i, r2, r3, ret=0;*/
- int r2, r3;
- /* Read r2 and r3 */
- r2 = mii_rd(MII_ID0, phyaddr, ioaddr);
- r3 = mii_rd(MII_ID1, phyaddr, ioaddr);
- /* SEEQ and Cypress way * /
- / * Shuffle r2 and r3 * /
- a.reg=0;
- r3 = ((r3>>10)|(r2<<6))&0x0ff;
- r2 = ((r2>>2)&0x3fff);
- / * Bit reverse r3 * /
- for (i=0;i<8;i++) {
- ret<<=1;
- ret |= (r3&1);
- r3>>=1;
- }
- / * Bit reverse r2 * /
- for (i=0;i<16;i++) {
- a.reg<<=1;
- a.reg |= (r2&1);
- r2>>=1;
- }
- / * Swap r2 bytes * /
- i=a.breg[0];
- a.breg[0]=a.breg[1];
- a.breg[1]=i;
- return ((a.reg<<8)|ret); */ /* SEEQ and Cypress way */
- /* return ((r2<<6)|(u_int)(r3>>10)); */ /* NATIONAL and BROADCOM way */
- return r2; /* (I did it) My way */
- }
- /*
- ** The SROM spec forces us to search addresses [1-31 0]. Bummer.
- */
- static int
- mii_get_phy(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
- int i, j, k, n, limit=sizeof(phy_info)/sizeof(struct phy_table);
- int id;
-
- lp->active = 0;
- lp->useMII = TRUE;
- /* Search the MII address space for possible PHY devices */
- for (n=0, lp->mii_cnt=0, i=1; !((i==1) && (n==1)); i=(++i)%DE4X5_MAX_MII) {
- lp->phy[lp->active].addr = i;
- if (i==0) n++; /* Count cycles */
- while (de4x5_reset_phy(dev)<0) udelay(100);/* Wait for reset */
- id = mii_get_oui(i, DE4X5_MII);
- if ((id == 0) || (id == 65535)) continue; /* Valid ID? */
- for (j=0; j<limit; j++) { /* Search PHY table */
- if (id != phy_info[j].id) continue; /* ID match? */
- for (k=0; lp->phy[k].id && (k < DE4X5_MAX_PHY); k++);
- if (k < DE4X5_MAX_PHY) {
- memcpy((char *)&lp->phy[k],
- (char *)&phy_info[j], sizeof(struct phy_table));
- lp->phy[k].addr = i;
- lp->mii_cnt++;
- lp->active++;
- } else {
- goto purgatory; /* Stop the search */
- }
- break;
- }
- if ((j == limit) && (i < DE4X5_MAX_MII)) {
- for (k=0; lp->phy[k].id && (k < DE4X5_MAX_PHY); k++);
- lp->phy[k].addr = i;
- lp->phy[k].id = id;
- lp->phy[k].spd.reg = GENERIC_REG; /* ANLPA register */
- lp->phy[k].spd.mask = GENERIC_MASK; /* 100Mb/s technologies */
- lp->phy[k].spd.value = GENERIC_VALUE; /* TX & T4, H/F Duplex */
- lp->mii_cnt++;
- lp->active++;
- printk("%s: Using generic MII device control. If the board doesn't operate, nplease mail the following dump to the author:n", dev->name);
- j = de4x5_debug;
- de4x5_debug |= DEBUG_MII;
- de4x5_dbg_mii(dev, k);
- de4x5_debug = j;
- printk("n");
- }
- }
- purgatory:
- lp->active = 0;
- if (lp->phy[0].id) { /* Reset the PHY devices */
- for (k=0; lp->phy[k].id && (k < DE4X5_MAX_PHY); k++) { /*For each PHY*/
- mii_wr(MII_CR_RST, MII_CR, lp->phy[k].addr, DE4X5_MII);
- while (mii_rd(MII_CR, lp->phy[k].addr, DE4X5_MII) & MII_CR_RST);
-
- de4x5_dbg_mii(dev, k);
- }
- }
- if (!lp->mii_cnt) lp->useMII = FALSE;
- return lp->mii_cnt;
- }
- static char *
- build_setup_frame(struct net_device *dev, int mode)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- int i;
- char *pa = lp->setup_frame;
-
- /* Initialise the setup frame */
- if (mode == ALL) {
- memset(lp->setup_frame, 0, SETUP_FRAME_LEN);
- }
-
- if (lp->setup_f == HASH_PERF) {
- for (pa=lp->setup_frame+IMPERF_PA_OFFSET, i=0; i<ETH_ALEN; i++) {
- *(pa + i) = dev->dev_addr[i]; /* Host address */
- if (i & 0x01) pa += 2;
- }
- *(lp->setup_frame + (HASH_TABLE_LEN >> 3) - 3) = 0x80;
- } else {
- for (i=0; i<ETH_ALEN; i++) { /* Host address */
- *(pa + (i&1)) = dev->dev_addr[i];
- if (i & 0x01) pa += 4;
- }
- for (i=0; i<ETH_ALEN; i++) { /* Broadcast address */
- *(pa + (i&1)) = (char) 0xff;
- if (i & 0x01) pa += 4;
- }
- }
-
- return pa; /* Points to the next entry */
- }
- static void
- enable_ast(struct net_device *dev, u32 time_out)
- {
- timeout(dev, (void *)&de4x5_ast, (u_long)dev, time_out);
-
- return;
- }
- static void
- disable_ast(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
-
- del_timer(&lp->timer);
-
- return;
- }
- static long
- de4x5_switch_mac_port(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
- s32 omr;
- STOP_DE4X5;
- /* Assert the OMR_PS bit in CSR6 */
- omr = (inl(DE4X5_OMR) & ~(OMR_PS | OMR_HBD | OMR_TTM | OMR_PCS | OMR_SCR |
- OMR_FDX));
- omr |= lp->infoblock_csr6;
- if (omr & OMR_PS) omr |= OMR_HBD;
- outl(omr, DE4X5_OMR);
-
- /* Soft Reset */
- RESET_DE4X5;
-
- /* Restore the GEP - especially for COMPACT and Type 0 Infoblocks */
- if (lp->chipset == DC21140) {
- gep_wr(lp->cache.gepc, dev);
- gep_wr(lp->cache.gep, dev);
- } else if ((lp->chipset & ~0x0ff) == DC2114x) {
- reset_init_sia(dev, lp->cache.csr13, lp->cache.csr14, lp->cache.csr15);
- }
- /* Restore CSR6 */
- outl(omr, DE4X5_OMR);
- /* Reset CSR8 */
- inl(DE4X5_MFC);
- return omr;
- }
- static void
- gep_wr(s32 data, struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
- if (lp->chipset == DC21140) {
- outl(data, DE4X5_GEP);
- } else if ((lp->chipset & ~0x00ff) == DC2114x) {
- outl((data<<16) | lp->cache.csr15, DE4X5_SIGR);
- }
- return;
- }
- static int
- gep_rd(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
- if (lp->chipset == DC21140) {
- return inl(DE4X5_GEP);
- } else if ((lp->chipset & ~0x00ff) == DC2114x) {
- return (inl(DE4X5_SIGR) & 0x000fffff);
- }
- return 0;
- }
- static void
- timeout(struct net_device *dev, void (*fn)(u_long data), u_long data, u_long msec)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- int dt;
-
- /* First, cancel any pending timer events */
- del_timer(&lp->timer);
-
- /* Convert msec to ticks */
- dt = (msec * HZ) / 1000;
- if (dt==0) dt=1;
-
- /* Set up timer */
- lp->timer.expires = jiffies + dt;
- lp->timer.function = fn;
- lp->timer.data = data;
- add_timer(&lp->timer);
-
- return;
- }
- static void
- yawn(struct net_device *dev, int state)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
- if ((lp->chipset == DC21040) || (lp->chipset == DC21140)) return;
- if(lp->bus == EISA) {
- switch(state) {
- case WAKEUP:
- outb(WAKEUP, PCI_CFPM);
- mdelay(10);
- break;
- case SNOOZE:
- outb(SNOOZE, PCI_CFPM);
- break;
- case SLEEP:
- outl(0, DE4X5_SICR);
- outb(SLEEP, PCI_CFPM);
- break;
- }
- } else {
- switch(state) {
- case WAKEUP:
- pcibios_write_config_byte(lp->bus_num, lp->device << 3,
- PCI_CFDA_PSM, WAKEUP);
- mdelay(10);
- break;
- case SNOOZE:
- pcibios_write_config_byte(lp->bus_num, lp->device << 3,
- PCI_CFDA_PSM, SNOOZE);
- break;
- case SLEEP:
- outl(0, DE4X5_SICR);
- pcibios_write_config_byte(lp->bus_num, lp->device << 3,
- PCI_CFDA_PSM, SLEEP);
- break;
- }
- }
- return;
- }
- static void
- de4x5_parse_params(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- char *p, *q, t;
- lp->params.fdx = 0;
- lp->params.autosense = AUTO;
- if (args == NULL) return;
- if ((p = strstr(args, dev->name))) {
- if (!(q = strstr(p+strlen(dev->name), "eth"))) q = p + strlen(p);
- t = *q;
- *q = ' ';
- #if !defined(__sparc_v9__) && !defined(__powerpc__) && !defined(__alpha__)
- if (strstr(p, "force_eisa") || strstr(p, "FORCE_EISA")) forceEISA = 1;
- #endif
- if (strstr(p, "fdx") || strstr(p, "FDX")) lp->params.fdx = 1;
- if (strstr(p, "autosense") || strstr(p, "AUTOSENSE")) {
- if (strstr(p, "TP")) {
- lp->params.autosense = TP;
- } else if (strstr(p, "TP_NW")) {
- lp->params.autosense = TP_NW;
- } else if (strstr(p, "BNC")) {
- lp->params.autosense = BNC;
- } else if (strstr(p, "AUI")) {
- lp->params.autosense = AUI;
- } else if (strstr(p, "BNC_AUI")) {
- lp->params.autosense = BNC;
- } else if (strstr(p, "10Mb")) {
- lp->params.autosense = _10Mb;
- } else if (strstr(p, "100Mb")) {
- lp->params.autosense = _100Mb;
- } else if (strstr(p, "AUTO")) {
- lp->params.autosense = AUTO;
- }
- }
- *q = t;
- }
- return;
- }
- static void
- de4x5_dbg_open(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- int i;
-
- if (de4x5_debug & DEBUG_OPEN) {
- printk("%s: de4x5 opening with irq %dn",dev->name,dev->irq);
- printk("tphysical address: ");
- for (i=0;i<6;i++) {
- printk("%2.2x:",(short)dev->dev_addr[i]);
- }
- printk("n");
- printk("Descriptor head addresses:n");
- printk("t0x%8.8lx 0x%8.8lxn",(u_long)lp->rx_ring,(u_long)lp->tx_ring);
- printk("Descriptor addresses:nRX: ");
- for (i=0;i<lp->rxRingSize-1;i++){
- if (i < 3) {
- printk("0x%8.8lx ",(u_long)&lp->rx_ring[i].status);
- }
- }
- printk("...0x%8.8lxn",(u_long)&lp->rx_ring[i].status);
- printk("TX: ");
- for (i=0;i<lp->txRingSize-1;i++){
- if (i < 3) {
- printk("0x%8.8lx ", (u_long)&lp->tx_ring[i].status);
- }
- }
- printk("...0x%8.8lxn", (u_long)&lp->tx_ring[i].status);
- printk("Descriptor buffers:nRX: ");
- for (i=0;i<lp->rxRingSize-1;i++){
- if (i < 3) {
- printk("0x%8.8x ",le32_to_cpu(lp->rx_ring[i].buf));
- }
- }
- printk("...0x%8.8xn",le32_to_cpu(lp->rx_ring[i].buf));
- printk("TX: ");
- for (i=0;i<lp->txRingSize-1;i++){
- if (i < 3) {
- printk("0x%8.8x ", le32_to_cpu(lp->tx_ring[i].buf));
- }
- }
- printk("...0x%8.8xn", le32_to_cpu(lp->tx_ring[i].buf));
- printk("Ring size: nRX: %dnTX: %dn",
- (short)lp->rxRingSize,
- (short)lp->txRingSize);
- }
-
- return;
- }
- static void
- de4x5_dbg_mii(struct net_device *dev, int k)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- u_long iobase = dev->base_addr;
-
- if (de4x5_debug & DEBUG_MII) {
- printk("nMII device address: %dn", lp->phy[k].addr);
- printk("MII CR: %xn",mii_rd(MII_CR,lp->phy[k].addr,DE4X5_MII));
- printk("MII SR: %xn",mii_rd(MII_SR,lp->phy[k].addr,DE4X5_MII));
- printk("MII ID0: %xn",mii_rd(MII_ID0,lp->phy[k].addr,DE4X5_MII));
- printk("MII ID1: %xn",mii_rd(MII_ID1,lp->phy[k].addr,DE4X5_MII));
- if (lp->phy[k].id != BROADCOM_T4) {
- printk("MII ANA: %xn",mii_rd(0x04,lp->phy[k].addr,DE4X5_MII));
- printk("MII ANC: %xn",mii_rd(0x05,lp->phy[k].addr,DE4X5_MII));
- }
- printk("MII 16: %xn",mii_rd(0x10,lp->phy[k].addr,DE4X5_MII));
- if (lp->phy[k].id != BROADCOM_T4) {
- printk("MII 17: %xn",mii_rd(0x11,lp->phy[k].addr,DE4X5_MII));
- printk("MII 18: %xn",mii_rd(0x12,lp->phy[k].addr,DE4X5_MII));
- } else {
- printk("MII 20: %xn",mii_rd(0x14,lp->phy[k].addr,DE4X5_MII));
- }
- }
-
- return;
- }
- static void
- de4x5_dbg_media(struct net_device *dev)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
-
- if (lp->media != lp->c_media) {
- if (de4x5_debug & DEBUG_MEDIA) {
- printk("%s: media is %s%sn", dev->name,
- (lp->media == NC ? "unconnected, link down or incompatible connection" :
- (lp->media == TP ? "TP" :
- (lp->media == ANS ? "TP/Nway" :
- (lp->media == BNC ? "BNC" :
- (lp->media == AUI ? "AUI" :
- (lp->media == BNC_AUI ? "BNC/AUI" :
- (lp->media == EXT_SIA ? "EXT SIA" :
- (lp->media == _100Mb ? "100Mb/s" :
- (lp->media == _10Mb ? "10Mb/s" :
- "???"
- ))))))))), (lp->fdx?" full duplex.":"."));
- }
- lp->c_media = lp->media;
- }
-
- return;
- }
- static void
- de4x5_dbg_srom(struct de4x5_srom *p)
- {
- int i;
- if (de4x5_debug & DEBUG_SROM) {
- printk("Sub-system Vendor ID: %04xn", *((u_short *)p->sub_vendor_id));
- printk("Sub-system ID: %04xn", *((u_short *)p->sub_system_id));
- printk("ID Block CRC: %02xn", (u_char)(p->id_block_crc));
- printk("SROM version: %02xn", (u_char)(p->version));
- printk("# controllers: %02xn", (u_char)(p->num_controllers));
- printk("Hardware Address: ");
- for (i=0;i<ETH_ALEN-1;i++) {
- printk("%02x:", (u_char)*(p->ieee_addr+i));
- }
- printk("%02xn", (u_char)*(p->ieee_addr+i));
- printk("CRC checksum: %04xn", (u_short)(p->chksum));
- for (i=0; i<64; i++) {
- printk("%3d %04xn", i<<1, (u_short)*((u_short *)p+i));
- }
- }
- return;
- }
- static void
- de4x5_dbg_rx(struct sk_buff *skb, int len)
- {
- int i, j;
- if (de4x5_debug & DEBUG_RX) {
- printk("R: %02x:%02x:%02x:%02x:%02x:%02x <- %02x:%02x:%02x:%02x:%02x:%02x len/SAP:%02x%02x [%d]n",
- (u_char)skb->data[0],
- (u_char)skb->data[1],
- (u_char)skb->data[2],
- (u_char)skb->data[3],
- (u_char)skb->data[4],
- (u_char)skb->data[5],
- (u_char)skb->data[6],
- (u_char)skb->data[7],
- (u_char)skb->data[8],
- (u_char)skb->data[9],
- (u_char)skb->data[10],
- (u_char)skb->data[11],
- (u_char)skb->data[12],
- (u_char)skb->data[13],
- len);
- for (j=0; len>0;j+=16, len-=16) {
- printk(" %03x: ",j);
- for (i=0; i<16 && i<len; i++) {
- printk("%02x ",(u_char)skb->data[i+j]);
- }
- printk("n");
- }
- }
- return;
- }
- /*
- ** Perform IOCTL call functions here. Some are privileged operations and the
- ** effective uid is checked in those cases. In the normal course of events
- ** this function is only used for my testing.
- */
- static int
- de4x5_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
- {
- struct de4x5_private *lp = (struct de4x5_private *)dev->priv;
- struct de4x5_ioctl *ioc = (struct de4x5_ioctl *) &rq->ifr_data;
- u_long iobase = dev->base_addr;
- int i, j, status = 0;
- s32 omr;
- union {
- u8 addr[144];
- u16 sval[72];
- u32 lval[36];
- } tmp;
- u_long flags = 0;
-
- switch(ioc->cmd) {
- case DE4X5_GET_HWADDR: /* Get the hardware address */
- ioc->len = ETH_ALEN;
- for (i=0; i<ETH_ALEN; i++) {
- tmp.addr[i] = dev->dev_addr[i];
- }
- if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
- break;
- case DE4X5_SET_HWADDR: /* Set the hardware address */
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- if (copy_from_user(tmp.addr, ioc->data, ETH_ALEN)) return -EFAULT;
- if (netif_queue_stopped(dev))
- return -EBUSY;
- netif_stop_queue(dev);
- for (i=0; i<ETH_ALEN; i++) {
- dev->dev_addr[i] = tmp.addr[i];
- }
- build_setup_frame(dev, PHYS_ADDR_ONLY);
- /* Set up the descriptor and give ownership to the card */
- load_packet(dev, lp->setup_frame, TD_IC | PERFECT_F | TD_SET |
- SETUP_FRAME_LEN, (struct sk_buff *)1);
- lp->tx_new = (++lp->tx_new) % lp->txRingSize;
- outl(POLL_DEMAND, DE4X5_TPD); /* Start the TX */
- netif_wake_queue(dev); /* Unlock the TX ring */
- break;
- case DE4X5_SET_PROM: /* Set Promiscuous Mode */
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- omr = inl(DE4X5_OMR);
- omr |= OMR_PR;
- outl(omr, DE4X5_OMR);
- dev->flags |= IFF_PROMISC;
- break;
- case DE4X5_CLR_PROM: /* Clear Promiscuous Mode */
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- omr = inl(DE4X5_OMR);
- omr &= ~OMR_PR;
- outl(omr, DE4X5_OMR);
- dev->flags &= ~IFF_PROMISC;
- break;
- case DE4X5_SAY_BOO: /* Say "Boo!" to the kernel log file */
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- printk("%s: Boo!n", dev->name);
- break;
- case DE4X5_MCA_EN: /* Enable pass all multicast addressing */
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- omr = inl(DE4X5_OMR);
- omr |= OMR_PM;
- outl(omr, DE4X5_OMR);
- break;
- case DE4X5_GET_STATS: /* Get the driver statistics */
- {
- struct pkt_stats statbuf;
- ioc->len = sizeof(statbuf);
- spin_lock_irqsave(&lp->lock, flags);
- memcpy(&statbuf, &lp->pktStats, ioc->len);
- spin_unlock_irqrestore(&lp->lock, flags);
- if (copy_to_user(ioc->data, &statbuf, ioc->len))
- return -EFAULT;
- break;
- }
- case DE4X5_CLR_STATS: /* Zero out the driver statistics */
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- spin_lock_irqsave(&lp->lock, flags);
- memset(&lp->pktStats, 0, sizeof(lp->pktStats));
- spin_unlock_irqrestore(&lp->lock, flags);
- break;
- case DE4X5_GET_OMR: /* Get the OMR Register contents */
- tmp.addr[0] = inl(DE4X5_OMR);
- if (copy_to_user(ioc->data, tmp.addr, 1)) return -EFAULT;
- break;
- case DE4X5_SET_OMR: /* Set the OMR Register contents */
- if (!capable(CAP_NET_ADMIN)) return -EPERM;
- if (copy_from_user(tmp.addr, ioc->data, 1)) return -EFAULT;
- outl(tmp.addr[0], DE4X5_OMR);
- break;
- case DE4X5_GET_REG: /* Get the DE4X5 Registers */
- j = 0;
- tmp.lval[0] = inl(DE4X5_STS); j+=4;
- tmp.lval[1] = inl(DE4X5_BMR); j+=4;
- tmp.lval[2] = inl(DE4X5_IMR); j+=4;
- tmp.lval[3] = inl(DE4X5_OMR); j+=4;
- tmp.lval[4] = inl(DE4X5_SISR); j+=4;
- tmp.lval[5] = inl(DE4X5_SICR); j+=4;
- tmp.lval[6] = inl(DE4X5_STRR); j+=4;
- tmp.lval[7] = inl(DE4X5_SIGR); j+=4;
- ioc->len = j;
- if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
- break;
-
- #define DE4X5_DUMP 0x0f /* Dump the DE4X5 Status */
- /*
- case DE4X5_DUMP:
- j = 0;
- tmp.addr[j++] = dev->irq;
- for (i=0; i<ETH_ALEN; i++) {
- tmp.addr[j++] = dev->dev_addr[i];
- }
- tmp.addr[j++] = lp->rxRingSize;
- tmp.lval[j>>2] = (long)lp->rx_ring; j+=4;
- tmp.lval[j>>2] = (long)lp->tx_ring; j+=4;
-
- for (i=0;i<lp->rxRingSize-1;i++){
- if (i < 3) {
- tmp.lval[j>>2] = (long)&lp->rx_ring[i].status; j+=4;
- }
- }
- tmp.lval[j>>2] = (long)&lp->rx_ring[i].status; j+=4;
- for (i=0;i<lp->txRingSize-1;i++){
- if (i < 3) {
- tmp.lval[j>>2] = (long)&lp->tx_ring[i].status; j+=4;
- }
- }
- tmp.lval[j>>2] = (long)&lp->tx_ring[i].status; j+=4;
-
- for (i=0;i<lp->rxRingSize-1;i++){
- if (i < 3) {
- tmp.lval[j>>2] = (s32)le32_to_cpu(lp->rx_ring[i].buf); j+=4;
- }
- }
- tmp.lval[j>>2] = (s32)le32_to_cpu(lp->rx_ring[i].buf); j+=4;
- for (i=0;i<lp->txRingSize-1;i++){
- if (i < 3) {
- tmp.lval[j>>2] = (s32)le32_to_cpu(lp->tx_ring[i].buf); j+=4;
- }
- }
- tmp.lval[j>>2] = (s32)le32_to_cpu(lp->tx_ring[i].buf); j+=4;
-
- for (i=0;i<lp->rxRingSize;i++){
- tmp.lval[j>>2] = le32_to_cpu(lp->rx_ring[i].status); j+=4;
- }
- for (i=0;i<lp->txRingSize;i++){
- tmp.lval[j>>2] = le32_to_cpu(lp->tx_ring[i].status); j+=4;
- }
-
- tmp.lval[j>>2] = inl(DE4X5_BMR); j+=4;
- tmp.lval[j>>2] = inl(DE4X5_TPD); j+=4;
- tmp.lval[j>>2] = inl(DE4X5_RPD); j+=4;
- tmp.lval[j>>2] = inl(DE4X5_RRBA); j+=4;
- tmp.lval[j>>2] = inl(DE4X5_TRBA); j+=4;
- tmp.lval[j>>2] = inl(DE4X5_STS); j+=4;
- tmp.lval[j>>2] = inl(DE4X5_OMR); j+=4;
- tmp.lval[j>>2] = inl(DE4X5_IMR); j+=4;
- tmp.lval[j>>2] = lp->chipset; j+=4;
- if (lp->chipset == DC21140) {
- tmp.lval[j>>2] = gep_rd(dev); j+=4;
- } else {
- tmp.lval[j>>2] = inl(DE4X5_SISR); j+=4;
- tmp.lval[j>>2] = inl(DE4X5_SICR); j+=4;
- tmp.lval[j>>2] = inl(DE4X5_STRR); j+=4;
- tmp.lval[j>>2] = inl(DE4X5_SIGR); j+=4;
- }
- tmp.lval[j>>2] = lp->phy[lp->active].id; j+=4;
- if (lp->phy[lp->active].id && (!lp->useSROM || lp->useMII)) {
- tmp.lval[j>>2] = lp->active; j+=4;
- tmp.lval[j>>2]=mii_rd(MII_CR,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
- tmp.lval[j>>2]=mii_rd(MII_SR,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
- tmp.lval[j>>2]=mii_rd(MII_ID0,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
- tmp.lval[j>>2]=mii_rd(MII_ID1,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
- if (lp->phy[lp->active].id != BROADCOM_T4) {
- tmp.lval[j>>2]=mii_rd(MII_ANA,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
- tmp.lval[j>>2]=mii_rd(MII_ANLPA,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
- }
- tmp.lval[j>>2]=mii_rd(0x10,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
- if (lp->phy[lp->active].id != BROADCOM_T4) {
- tmp.lval[j>>2]=mii_rd(0x11,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
- tmp.lval[j>>2]=mii_rd(0x12,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
- } else {
- tmp.lval[j>>2]=mii_rd(0x14,lp->phy[lp->active].addr,DE4X5_MII); j+=4;
- }
- }
-
- tmp.addr[j++] = lp->txRingSize;
- tmp.addr[j++] = netif_queue_stopped(dev);
-
- ioc->len = j;
- if (copy_to_user(ioc->data, tmp.addr, ioc->len)) return -EFAULT;
- break;
- */
- default:
- return -EOPNOTSUPP;
- }
-
- return status;
- }
- #ifdef MODULE
- /*
- ** Note now that module autoprobing is allowed under EISA and PCI. The
- ** IRQ lines will not be auto-detected; instead I'll rely on the BIOSes
- ** to "do the right thing".
- */
- #define LP(a) ((struct de4x5_private *)(a))
- static struct net_device *mdev = NULL;
- static int io=0x0;/* EDIT THIS LINE FOR YOUR CONFIGURATION IF NEEDED */
- MODULE_PARM(io, "i");
- MODULE_PARM_DESC(io, "de4x5 I/O base address");
- int
- init_module(void)
- {
- int i, num, status = -EIO;
- struct net_device *p;
- num = count_adapters();
- for (i=0; i<num; i++) {
- if ((p = insert_device(NULL, io, de4x5_probe)) == NULL)
- return -ENOMEM;
- if (!mdev) mdev = p;
- if (register_netdev(p) != 0) {
- struct de4x5_private *lp = (struct de4x5_private *)p->priv;
- if (lp) {
- release_region(p->base_addr, (lp->bus == PCI ?
- DE4X5_PCI_TOTAL_SIZE :
- DE4X5_EISA_TOTAL_SIZE));
- if (lp->cache.priv) { /* Private area allocated? */
- kfree(lp->cache.priv); /* Free the private area */
- }
- if (lp->rx_ring) {
- pci_free_consistent(lp->pdev, lp->dma_size, lp->rx_ring,
- lp->dma_rings);
- }
- }
- kfree(p);
- } else {
- status = 0; /* At least one adapter will work */
- lastModule = p;
- }
- }
- return status;
- }
- void
- cleanup_module(void)
- {
- while (mdev != NULL) {
- mdev = unlink_modules(mdev);
- }
- return;
- }
- static struct net_device *
- unlink_modules(struct net_device *p)
- {
- struct net_device *next = NULL;
- if (p->priv) { /* Private areas allocated? */
- struct de4x5_private *lp = (struct de4x5_private *)p->priv;
- next = lp->next_module;
- if (lp->rx_ring) {
- pci_free_consistent(lp->pdev, lp->dma_size, lp->rx_ring,
- lp->dma_rings);
- }
- release_region(p->base_addr, (lp->bus == PCI ?
- DE4X5_PCI_TOTAL_SIZE :
- DE4X5_EISA_TOTAL_SIZE));
- kfree(lp->cache.priv); /* Free the private area */
- }
- unregister_netdev(p);
- kfree(p); /* Free the device structure */
-
- return next;
- }
- static int
- count_adapters(void)
- {
- int i, j=0;
- u_short vendor;
- u_int class = DE4X5_CLASS_CODE;
- u_int device;
- #if !defined(__sparc_v9__) && !defined(__powerpc__) && !defined(__alpha__)
- char name[DE4X5_STRLEN];
- u_long iobase = 0x1000;
- for (i=1; i<MAX_EISA_SLOTS; i++, iobase+=EISA_SLOT_INC) {
- if (EISA_signature(name, EISA_ID)) j++;
- }
- #endif
- if (!pcibios_present()) return j;
- for (i=0; (pdev=pci_find_class(class, pdev))!= NULL; i++) {
- vendor = pdev->vendor;
- device = pdev->device << 8;
- if (is_DC21040 || is_DC21041 || is_DC21140 || is_DC2114x) j++;
- }
- return j;
- }
- /*
- ** If at end of eth device list and can't use current entry, malloc
- ** one up. If memory could not be allocated, print an error message.
- */
- static struct net_device * __init
- insert_device(struct net_device *dev, u_long iobase, int (*init)(struct net_device *))
- {
- struct net_device *new;
- new = (struct net_device *)kmalloc(sizeof(struct net_device), GFP_KERNEL);
- if (new == NULL) {
- printk("de4x5.c: Device not initialised, insufficient memoryn");
- return NULL;
- } else {
- memset((char *)new, 0, sizeof(struct net_device));
- new->base_addr = iobase; /* assign the io address */
- new->init = init; /* initialisation routine */
- }
- return new;
- }
- #endif /* MODULE */
- /*
- * Local variables:
- *
- * Delete -DMODVERSIONS below if you didn't define this in your kernel
- *
- * compile-command: "gcc -D__KERNEL__ -DMODULE -I/linux/include -Wall -Wstrict-prototypes -fomit-frame-pointer -fno-strength-reduce -malign-loops=2 -malign-jumps=2 -malign-functions=2 -O2 -m486 -DMODVERSIONS -include /linux/include/linux/modversions.h -c de4x5.c"
- * End:
- */