From f8d79e79a1700fdcf26a1dfcaefad905b1279600 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Tue, 24 Jun 2008 22:16:02 +0100 Subject: [PATCH] DM9000: Cleanup source code - remove forward declerations Cleanup the source code by moving the code around to avoid having to declare the functions before they are used. Signed-off-by: Ben Dooks Signed-off-by: Jeff Garzik --- drivers/net/dm9000.c | 1352 +++++++++++++++++++++--------------------- 1 file changed, 666 insertions(+), 686 deletions(-) diff --git a/drivers/net/dm9000.c b/drivers/net/dm9000.c index 79538ab4ee60..679c291107f5 100644 --- a/drivers/net/dm9000.c +++ b/drivers/net/dm9000.c @@ -152,23 +152,6 @@ static inline board_info_t *to_dm9000_board(struct net_device *dev) return dev->priv; } -/* function declaration ------------------------------------- */ -static int dm9000_open(struct net_device *); -static int dm9000_start_xmit(struct sk_buff *, struct net_device *); -static int dm9000_stop(struct net_device *); - -static void dm9000_init_dm9000(struct net_device *); - -static irqreturn_t dm9000_interrupt(int, void *); - -static int dm9000_phy_read(struct net_device *dev, int phy, int reg); -static void dm9000_phy_write(struct net_device *dev, int phy, int reg, int v); - -static void dm9000_read_eeprom(board_info_t *, int addr, u8 *to); -static void dm9000_write_eeprom(board_info_t *, int addr, u8 *dp); -static void dm9000_rx(struct net_device *); -static void dm9000_hash_table(struct net_device *); - /* DM9000 network board routine ---------------------------- */ static void @@ -315,41 +298,6 @@ static void dm9000_schedule_poll(board_info_t *db) schedule_delayed_work(&db->phy_poll, HZ * 2); } -/* Our watchdog timed out. Called by the networking layer */ -static void dm9000_timeout(struct net_device *dev) -{ - board_info_t *db = (board_info_t *) dev->priv; - u8 reg_save; - unsigned long flags; - - /* Save previous register address */ - reg_save = readb(db->io_addr); - spin_lock_irqsave(&db->lock,flags); - - netif_stop_queue(dev); - dm9000_reset(db); - dm9000_init_dm9000(dev); - /* We can accept TX packets again */ - dev->trans_start = jiffies; - netif_wake_queue(dev); - - /* Restore previous register address */ - writeb(reg_save, db->io_addr); - spin_unlock_irqrestore(&db->lock,flags); -} - -#ifdef CONFIG_NET_POLL_CONTROLLER -/* - *Used by netconsole - */ -static void dm9000_poll_controller(struct net_device *dev) -{ - disable_irq(dev->irq); - dm9000_interrupt(dev->irq,dev); - enable_irq(dev->irq); -} -#endif - static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd) { board_info_t *dm = to_dm9000_board(dev); @@ -360,6 +308,121 @@ static int dm9000_ioctl(struct net_device *dev, struct ifreq *req, int cmd) return generic_mii_ioctl(&dm->mii, if_mii(req), cmd, NULL); } +static unsigned int +dm9000_read_locked(board_info_t *db, int reg) +{ + unsigned long flags; + unsigned int ret; + + spin_lock_irqsave(&db->lock, flags); + ret = ior(db, reg); + spin_unlock_irqrestore(&db->lock, flags); + + return ret; +} + +static int dm9000_wait_eeprom(board_info_t *db) +{ + unsigned int status; + int timeout = 8; /* wait max 8msec */ + + /* The DM9000 data sheets say we should be able to + * poll the ERRE bit in EPCR to wait for the EEPROM + * operation. From testing several chips, this bit + * does not seem to work. + * + * We attempt to use the bit, but fall back to the + * timeout (which is why we do not return an error + * on expiry) to say that the EEPROM operation has + * completed. + */ + + while (1) { + status = dm9000_read_locked(db, DM9000_EPCR); + + if ((status & EPCR_ERRE) == 0) + break; + + if (timeout-- < 0) { + dev_dbg(db->dev, "timeout waiting EEPROM\n"); + break; + } + } + + return 0; +} + +/* + * Read a word data from EEPROM + */ +static void +dm9000_read_eeprom(board_info_t *db, int offset, u8 *to) +{ + unsigned long flags; + + if (db->flags & DM9000_PLATF_NO_EEPROM) { + to[0] = 0xff; + to[1] = 0xff; + return; + } + + mutex_lock(&db->addr_lock); + + spin_lock_irqsave(&db->lock, flags); + + iow(db, DM9000_EPAR, offset); + iow(db, DM9000_EPCR, EPCR_ERPRR); + + spin_unlock_irqrestore(&db->lock, flags); + + dm9000_wait_eeprom(db); + + /* delay for at-least 150uS */ + msleep(1); + + spin_lock_irqsave(&db->lock, flags); + + iow(db, DM9000_EPCR, 0x0); + + to[0] = ior(db, DM9000_EPDRL); + to[1] = ior(db, DM9000_EPDRH); + + spin_unlock_irqrestore(&db->lock, flags); + + mutex_unlock(&db->addr_lock); +} + +/* + * Write a word data to SROM + */ +static void +dm9000_write_eeprom(board_info_t *db, int offset, u8 *data) +{ + unsigned long flags; + + if (db->flags & DM9000_PLATF_NO_EEPROM) + return; + + mutex_lock(&db->addr_lock); + + spin_lock_irqsave(&db->lock, flags); + iow(db, DM9000_EPAR, offset); + iow(db, DM9000_EPDRH, data[1]); + iow(db, DM9000_EPDRL, data[0]); + iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW); + spin_unlock_irqrestore(&db->lock, flags); + + dm9000_wait_eeprom(db); + + mdelay(1); /* wait at least 150uS to clear */ + + spin_lock_irqsave(&db->lock, flags); + iow(db, DM9000_EPCR, 0); + spin_unlock_irqrestore(&db->lock, flags); + + mutex_unlock(&db->addr_lock); +} + /* ethtool ops */ static void dm9000_get_drvinfo(struct net_device *dev, @@ -527,6 +590,553 @@ static unsigned char dm9000_type_to_char(enum dm9000_type type) return '?'; } +/* + * Set DM9000 multicast address + */ +static void +dm9000_hash_table(struct net_device *dev) +{ + board_info_t *db = (board_info_t *) dev->priv; + struct dev_mc_list *mcptr = dev->mc_list; + int mc_cnt = dev->mc_count; + int i, oft; + u32 hash_val; + u16 hash_table[4]; + u8 rcr = RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN; + unsigned long flags; + + dm9000_dbg(db, 1, "entering %s\n", __func__); + + spin_lock_irqsave(&db->lock, flags); + + for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++) + iow(db, oft, dev->dev_addr[i]); + + /* Clear Hash Table */ + for (i = 0; i < 4; i++) + hash_table[i] = 0x0; + + /* broadcast address */ + hash_table[3] = 0x8000; + + if (dev->flags & IFF_PROMISC) + rcr |= RCR_PRMSC; + + if (dev->flags & IFF_ALLMULTI) + rcr |= RCR_ALL; + + /* the multicast address in Hash Table : 64 bits */ + for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) { + hash_val = ether_crc_le(6, mcptr->dmi_addr) & 0x3f; + hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16); + } + + /* Write the hash table to MAC MD table */ + for (i = 0, oft = DM9000_MAR; i < 4; i++) { + iow(db, oft++, hash_table[i]); + iow(db, oft++, hash_table[i] >> 8); + } + + iow(db, DM9000_RCR, rcr); + spin_unlock_irqrestore(&db->lock, flags); +} + +/* + * Initilize dm9000 board + */ +static void +dm9000_init_dm9000(struct net_device *dev) +{ + board_info_t *db = dev->priv; + unsigned int imr; + + dm9000_dbg(db, 1, "entering %s\n", __func__); + + /* I/O mode */ + db->io_mode = ior(db, DM9000_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */ + + /* GPIO0 on pre-activate PHY */ + iow(db, DM9000_GPR, 0); /* REG_1F bit0 activate phyxcer */ + iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */ + iow(db, DM9000_GPR, 0); /* Enable PHY */ + + if (db->flags & DM9000_PLATF_EXT_PHY) + iow(db, DM9000_NCR, NCR_EXT_PHY); + + /* Program operating register */ + iow(db, DM9000_TCR, 0); /* TX Polling clear */ + iow(db, DM9000_BPTR, 0x3f); /* Less 3Kb, 200us */ + iow(db, DM9000_FCR, 0xff); /* Flow Control */ + iow(db, DM9000_SMCR, 0); /* Special Mode */ + /* clear TX status */ + iow(db, DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END); + iow(db, DM9000_ISR, ISR_CLR_STATUS); /* Clear interrupt status */ + + /* Set address filter table */ + dm9000_hash_table(dev); + + imr = IMR_PAR | IMR_PTM | IMR_PRM; + if (db->type != TYPE_DM9000E) + imr |= IMR_LNKCHNG; + + db->imr_all = imr; + + /* Enable TX/RX interrupt mask */ + iow(db, DM9000_IMR, imr); + + /* Init Driver variable */ + db->tx_pkt_cnt = 0; + db->queue_pkt_len = 0; + dev->trans_start = 0; +} + +/* Our watchdog timed out. Called by the networking layer */ +static void dm9000_timeout(struct net_device *dev) +{ + board_info_t *db = (board_info_t *) dev->priv; + u8 reg_save; + unsigned long flags; + + /* Save previous register address */ + reg_save = readb(db->io_addr); + spin_lock_irqsave(&db->lock, flags); + + netif_stop_queue(dev); + dm9000_reset(db); + dm9000_init_dm9000(dev); + /* We can accept TX packets again */ + dev->trans_start = jiffies; + netif_wake_queue(dev); + + /* Restore previous register address */ + writeb(reg_save, db->io_addr); + spin_unlock_irqrestore(&db->lock, flags); +} + +/* + * Hardware start transmission. + * Send a packet to media from the upper layer. + */ +static int +dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev) +{ + unsigned long flags; + board_info_t *db = dev->priv; + + dm9000_dbg(db, 3, "%s:\n", __func__); + + if (db->tx_pkt_cnt > 1) + return 1; + + spin_lock_irqsave(&db->lock, flags); + + /* Move data to DM9000 TX RAM */ + writeb(DM9000_MWCMD, db->io_addr); + + (db->outblk)(db->io_data, skb->data, skb->len); + dev->stats.tx_bytes += skb->len; + + db->tx_pkt_cnt++; + /* TX control: First packet immediately send, second packet queue */ + if (db->tx_pkt_cnt == 1) { + /* Set TX length to DM9000 */ + iow(db, DM9000_TXPLL, skb->len); + iow(db, DM9000_TXPLH, skb->len >> 8); + + /* Issue TX polling command */ + iow(db, DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */ + + dev->trans_start = jiffies; /* save the time stamp */ + } else { + /* Second packet */ + db->queue_pkt_len = skb->len; + netif_stop_queue(dev); + } + + spin_unlock_irqrestore(&db->lock, flags); + + /* free this SKB */ + dev_kfree_skb(skb); + + return 0; +} + +/* + * DM9000 interrupt handler + * receive the packet to upper layer, free the transmitted packet + */ + +static void dm9000_tx_done(struct net_device *dev, board_info_t *db) +{ + int tx_status = ior(db, DM9000_NSR); /* Got TX status */ + + if (tx_status & (NSR_TX2END | NSR_TX1END)) { + /* One packet sent complete */ + db->tx_pkt_cnt--; + dev->stats.tx_packets++; + + if (netif_msg_tx_done(db)) + dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status); + + /* Queue packet check & send */ + if (db->tx_pkt_cnt > 0) { + iow(db, DM9000_TXPLL, db->queue_pkt_len); + iow(db, DM9000_TXPLH, db->queue_pkt_len >> 8); + iow(db, DM9000_TCR, TCR_TXREQ); + dev->trans_start = jiffies; + } + netif_wake_queue(dev); + } +} + +struct dm9000_rxhdr { + u8 RxPktReady; + u8 RxStatus; + __le16 RxLen; +} __attribute__((__packed__)); + +/* + * Received a packet and pass to upper layer + */ +static void +dm9000_rx(struct net_device *dev) +{ + board_info_t *db = (board_info_t *) dev->priv; + struct dm9000_rxhdr rxhdr; + struct sk_buff *skb; + u8 rxbyte, *rdptr; + bool GoodPacket; + int RxLen; + + /* Check packet ready or not */ + do { + ior(db, DM9000_MRCMDX); /* Dummy read */ + + /* Get most updated data */ + rxbyte = readb(db->io_data); + + /* Status check: this byte must be 0 or 1 */ + if (rxbyte > DM9000_PKT_RDY) { + dev_warn(db->dev, "status check fail: %d\n", rxbyte); + iow(db, DM9000_RCR, 0x00); /* Stop Device */ + iow(db, DM9000_ISR, IMR_PAR); /* Stop INT request */ + return; + } + + if (rxbyte != DM9000_PKT_RDY) + return; + + /* A packet ready now & Get status/length */ + GoodPacket = true; + writeb(DM9000_MRCMD, db->io_addr); + + (db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr)); + + RxLen = le16_to_cpu(rxhdr.RxLen); + + if (netif_msg_rx_status(db)) + dev_dbg(db->dev, "RX: status %02x, length %04x\n", + rxhdr.RxStatus, RxLen); + + /* Packet Status check */ + if (RxLen < 0x40) { + GoodPacket = false; + if (netif_msg_rx_err(db)) + dev_dbg(db->dev, "RX: Bad Packet (runt)\n"); + } + + if (RxLen > DM9000_PKT_MAX) { + dev_dbg(db->dev, "RST: RX Len:%x\n", RxLen); + } + + if (rxhdr.RxStatus & 0xbf) { + GoodPacket = false; + if (rxhdr.RxStatus & 0x01) { + if (netif_msg_rx_err(db)) + dev_dbg(db->dev, "fifo error\n"); + dev->stats.rx_fifo_errors++; + } + if (rxhdr.RxStatus & 0x02) { + if (netif_msg_rx_err(db)) + dev_dbg(db->dev, "crc error\n"); + dev->stats.rx_crc_errors++; + } + if (rxhdr.RxStatus & 0x80) { + if (netif_msg_rx_err(db)) + dev_dbg(db->dev, "length error\n"); + dev->stats.rx_length_errors++; + } + } + + /* Move data from DM9000 */ + if (GoodPacket + && ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) { + skb_reserve(skb, 2); + rdptr = (u8 *) skb_put(skb, RxLen - 4); + + /* Read received packet from RX SRAM */ + + (db->inblk)(db->io_data, rdptr, RxLen); + dev->stats.rx_bytes += RxLen; + + /* Pass to upper layer */ + skb->protocol = eth_type_trans(skb, dev); + netif_rx(skb); + dev->stats.rx_packets++; + + } else { + /* need to dump the packet's data */ + + (db->dumpblk)(db->io_data, RxLen); + } + } while (rxbyte == DM9000_PKT_RDY); +} + +static irqreturn_t dm9000_interrupt(int irq, void *dev_id) +{ + struct net_device *dev = dev_id; + board_info_t *db = dev->priv; + int int_status; + u8 reg_save; + + dm9000_dbg(db, 3, "entering %s\n", __func__); + + /* A real interrupt coming */ + + spin_lock(&db->lock); + + /* Save previous register address */ + reg_save = readb(db->io_addr); + + /* Disable all interrupts */ + iow(db, DM9000_IMR, IMR_PAR); + + /* Got DM9000 interrupt status */ + int_status = ior(db, DM9000_ISR); /* Got ISR */ + iow(db, DM9000_ISR, int_status); /* Clear ISR status */ + + if (netif_msg_intr(db)) + dev_dbg(db->dev, "interrupt status %02x\n", int_status); + + /* Received the coming packet */ + if (int_status & ISR_PRS) + dm9000_rx(dev); + + /* Trnasmit Interrupt check */ + if (int_status & ISR_PTS) + dm9000_tx_done(dev, db); + + if (db->type != TYPE_DM9000E) { + if (int_status & ISR_LNKCHNG) { + /* fire a link-change request */ + schedule_delayed_work(&db->phy_poll, 1); + } + } + + /* Re-enable interrupt mask */ + iow(db, DM9000_IMR, db->imr_all); + + /* Restore previous register address */ + writeb(reg_save, db->io_addr); + + spin_unlock(&db->lock); + + return IRQ_HANDLED; +} + +#ifdef CONFIG_NET_POLL_CONTROLLER +/* + *Used by netconsole + */ +static void dm9000_poll_controller(struct net_device *dev) +{ + disable_irq(dev->irq); + dm9000_interrupt(dev->irq, dev); + enable_irq(dev->irq); +} +#endif + +/* + * Open the interface. + * The interface is opened whenever "ifconfig" actives it. + */ +static int +dm9000_open(struct net_device *dev) +{ + board_info_t *db = dev->priv; + unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK; + + if (netif_msg_ifup(db)) + dev_dbg(db->dev, "enabling %s\n", dev->name); + + /* If there is no IRQ type specified, default to something that + * may work, and tell the user that this is a problem */ + + if (irqflags == IRQF_TRIGGER_NONE) { + dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n"); + irqflags = DEFAULT_TRIGGER; + } + + irqflags |= IRQF_SHARED; + + if (request_irq(dev->irq, &dm9000_interrupt, irqflags, dev->name, dev)) + return -EAGAIN; + + /* Initialize DM9000 board */ + dm9000_reset(db); + dm9000_init_dm9000(dev); + + /* Init driver variable */ + db->dbug_cnt = 0; + + mii_check_media(&db->mii, netif_msg_link(db), 1); + netif_start_queue(dev); + + dm9000_schedule_poll(db); + + return 0; +} + +/* + * Sleep, either by using msleep() or if we are suspending, then + * use mdelay() to sleep. + */ +static void dm9000_msleep(board_info_t *db, unsigned int ms) +{ + if (db->in_suspend) + mdelay(ms); + else + msleep(ms); +} + +/* + * Read a word from phyxcer + */ +static int +dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) +{ + board_info_t *db = (board_info_t *) dev->priv; + unsigned long flags; + unsigned int reg_save; + int ret; + + mutex_lock(&db->addr_lock); + + spin_lock_irqsave(&db->lock,flags); + + /* Save previous register address */ + reg_save = readb(db->io_addr); + + /* Fill the phyxcer register into REG_0C */ + iow(db, DM9000_EPAR, DM9000_PHY | reg); + + iow(db, DM9000_EPCR, 0xc); /* Issue phyxcer read command */ + + writeb(reg_save, db->io_addr); + spin_unlock_irqrestore(&db->lock,flags); + + dm9000_msleep(db, 1); /* Wait read complete */ + + spin_lock_irqsave(&db->lock,flags); + reg_save = readb(db->io_addr); + + iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer read command */ + + /* The read data keeps on REG_0D & REG_0E */ + ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL); + + /* restore the previous address */ + writeb(reg_save, db->io_addr); + spin_unlock_irqrestore(&db->lock,flags); + + mutex_unlock(&db->addr_lock); + + dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret); + return ret; +} + +/* + * Write a word to phyxcer + */ +static void +dm9000_phy_write(struct net_device *dev, + int phyaddr_unused, int reg, int value) +{ + board_info_t *db = (board_info_t *) dev->priv; + unsigned long flags; + unsigned long reg_save; + + dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value); + mutex_lock(&db->addr_lock); + + spin_lock_irqsave(&db->lock,flags); + + /* Save previous register address */ + reg_save = readb(db->io_addr); + + /* Fill the phyxcer register into REG_0C */ + iow(db, DM9000_EPAR, DM9000_PHY | reg); + + /* Fill the written data into REG_0D & REG_0E */ + iow(db, DM9000_EPDRL, value); + iow(db, DM9000_EPDRH, value >> 8); + + iow(db, DM9000_EPCR, 0xa); /* Issue phyxcer write command */ + + writeb(reg_save, db->io_addr); + spin_unlock_irqrestore(&db->lock, flags); + + dm9000_msleep(db, 1); /* Wait write complete */ + + spin_lock_irqsave(&db->lock,flags); + reg_save = readb(db->io_addr); + + iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */ + + /* restore the previous address */ + writeb(reg_save, db->io_addr); + + spin_unlock_irqrestore(&db->lock, flags); + mutex_unlock(&db->addr_lock); +} + +static void +dm9000_shutdown(struct net_device *dev) +{ + board_info_t *db = dev->priv; + + /* RESET device */ + dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */ + iow(db, DM9000_GPR, 0x01); /* Power-Down PHY */ + iow(db, DM9000_IMR, IMR_PAR); /* Disable all interrupt */ + iow(db, DM9000_RCR, 0x00); /* Disable RX */ +} + +/* + * Stop the interface. + * The interface is stopped when it is brought. + */ +static int +dm9000_stop(struct net_device *ndev) +{ + board_info_t *db = ndev->priv; + + if (netif_msg_ifdown(db)) + dev_dbg(db->dev, "shutting down %s\n", ndev->name); + + cancel_delayed_work_sync(&db->phy_poll); + + netif_stop_queue(ndev); + netif_carrier_off(ndev); + + /* free interrupt */ + free_irq(ndev->irq, ndev); + + dm9000_shutdown(ndev); + + return 0; +} + #define res_size(_r) (((_r)->end - (_r)->start) + 1) /* @@ -545,7 +1155,7 @@ dm9000_probe(struct platform_device *pdev) u32 id_val; /* Init network device */ - ndev = alloc_etherdev(sizeof (struct board_info)); + ndev = alloc_etherdev(sizeof(struct board_info)); if (!ndev) { dev_err(&pdev->dev, "could not allocate device.\n"); return -ENOMEM; @@ -556,8 +1166,8 @@ dm9000_probe(struct platform_device *pdev) dev_dbg(&pdev->dev, "dm9000_probe()\n"); /* setup board info structure */ - db = (struct board_info *) ndev->priv; - memset(db, 0, sizeof (*db)); + db = ndev->priv; + memset(db, 0, sizeof(*db)); db->dev = &pdev->dev; db->ndev = ndev; @@ -722,7 +1332,7 @@ dm9000_probe(struct platform_device *pdev) if (!is_valid_ether_addr(ndev->dev_addr)) { /* try reading from mac */ - + mac_src = "chip"; for (i = 0; i < 6; i++) ndev->dev_addr[i] = ior(db, i+DM9000_PAR); @@ -753,636 +1363,6 @@ out: return ret; } -/* - * Open the interface. - * The interface is opened whenever "ifconfig" actives it. - */ -static int -dm9000_open(struct net_device *dev) -{ - board_info_t *db = dev->priv; - unsigned long irqflags = db->irq_res->flags & IRQF_TRIGGER_MASK; - - if (netif_msg_ifup(db)) - dev_dbg(db->dev, "enabling %s\n", dev->name); - - /* If there is no IRQ type specified, default to something that - * may work, and tell the user that this is a problem */ - - if (irqflags == IRQF_TRIGGER_NONE) { - dev_warn(db->dev, "WARNING: no IRQ resource flags set.\n"); - irqflags = DEFAULT_TRIGGER; - } - - irqflags |= IRQF_SHARED; - - if (request_irq(dev->irq, &dm9000_interrupt, irqflags, dev->name, dev)) - return -EAGAIN; - - /* Initialize DM9000 board */ - dm9000_reset(db); - dm9000_init_dm9000(dev); - - /* Init driver variable */ - db->dbug_cnt = 0; - - mii_check_media(&db->mii, netif_msg_link(db), 1); - netif_start_queue(dev); - - dm9000_schedule_poll(db); - - return 0; -} - -/* - * Initilize dm9000 board - */ -static void -dm9000_init_dm9000(struct net_device *dev) -{ - board_info_t *db = dev->priv; - unsigned int imr; - - dm9000_dbg(db, 1, "entering %s\n", __func__); - - /* I/O mode */ - db->io_mode = ior(db, DM9000_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */ - - /* GPIO0 on pre-activate PHY */ - iow(db, DM9000_GPR, 0); /* REG_1F bit0 activate phyxcer */ - iow(db, DM9000_GPCR, GPCR_GEP_CNTL); /* Let GPIO0 output */ - iow(db, DM9000_GPR, 0); /* Enable PHY */ - - if (db->flags & DM9000_PLATF_EXT_PHY) - iow(db, DM9000_NCR, NCR_EXT_PHY); - - /* Program operating register */ - iow(db, DM9000_TCR, 0); /* TX Polling clear */ - iow(db, DM9000_BPTR, 0x3f); /* Less 3Kb, 200us */ - iow(db, DM9000_FCR, 0xff); /* Flow Control */ - iow(db, DM9000_SMCR, 0); /* Special Mode */ - /* clear TX status */ - iow(db, DM9000_NSR, NSR_WAKEST | NSR_TX2END | NSR_TX1END); - iow(db, DM9000_ISR, ISR_CLR_STATUS); /* Clear interrupt status */ - - /* Set address filter table */ - dm9000_hash_table(dev); - - imr = IMR_PAR | IMR_PTM | IMR_PRM; - if (db->type != TYPE_DM9000E) - imr |= IMR_LNKCHNG; - - db->imr_all = imr; - - /* Enable TX/RX interrupt mask */ - iow(db, DM9000_IMR, imr); - - /* Init Driver variable */ - db->tx_pkt_cnt = 0; - db->queue_pkt_len = 0; - dev->trans_start = 0; -} - -/* - * Hardware start transmission. - * Send a packet to media from the upper layer. - */ -static int -dm9000_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - unsigned long flags; - board_info_t *db = dev->priv; - - dm9000_dbg(db, 3, "%s:\n", __func__); - - if (db->tx_pkt_cnt > 1) - return 1; - - spin_lock_irqsave(&db->lock, flags); - - /* Move data to DM9000 TX RAM */ - writeb(DM9000_MWCMD, db->io_addr); - - (db->outblk)(db->io_data, skb->data, skb->len); - dev->stats.tx_bytes += skb->len; - - db->tx_pkt_cnt++; - /* TX control: First packet immediately send, second packet queue */ - if (db->tx_pkt_cnt == 1) { - /* Set TX length to DM9000 */ - iow(db, DM9000_TXPLL, skb->len); - iow(db, DM9000_TXPLH, skb->len >> 8); - - /* Issue TX polling command */ - iow(db, DM9000_TCR, TCR_TXREQ); /* Cleared after TX complete */ - - dev->trans_start = jiffies; /* save the time stamp */ - } else { - /* Second packet */ - db->queue_pkt_len = skb->len; - netif_stop_queue(dev); - } - - spin_unlock_irqrestore(&db->lock, flags); - - /* free this SKB */ - dev_kfree_skb(skb); - - return 0; -} - -static void -dm9000_shutdown(struct net_device *dev) -{ - board_info_t *db = dev->priv; - - /* RESET device */ - dm9000_phy_write(dev, 0, MII_BMCR, BMCR_RESET); /* PHY RESET */ - iow(db, DM9000_GPR, 0x01); /* Power-Down PHY */ - iow(db, DM9000_IMR, IMR_PAR); /* Disable all interrupt */ - iow(db, DM9000_RCR, 0x00); /* Disable RX */ -} - -/* - * Stop the interface. - * The interface is stopped when it is brought. - */ -static int -dm9000_stop(struct net_device *ndev) -{ - board_info_t *db = ndev->priv; - - if (netif_msg_ifdown(db)) - dev_dbg(db->dev, "shutting down %s\n", ndev->name); - - cancel_delayed_work_sync(&db->phy_poll); - - netif_stop_queue(ndev); - netif_carrier_off(ndev); - - /* free interrupt */ - free_irq(ndev->irq, ndev); - - dm9000_shutdown(ndev); - - return 0; -} - -/* - * DM9000 interrupt handler - * receive the packet to upper layer, free the transmitted packet - */ - -static void -dm9000_tx_done(struct net_device *dev, board_info_t * db) -{ - int tx_status = ior(db, DM9000_NSR); /* Got TX status */ - - if (tx_status & (NSR_TX2END | NSR_TX1END)) { - /* One packet sent complete */ - db->tx_pkt_cnt--; - dev->stats.tx_packets++; - - if (netif_msg_tx_done(db)) - dev_dbg(db->dev, "tx done, NSR %02x\n", tx_status); - - /* Queue packet check & send */ - if (db->tx_pkt_cnt > 0) { - iow(db, DM9000_TXPLL, db->queue_pkt_len); - iow(db, DM9000_TXPLH, db->queue_pkt_len >> 8); - iow(db, DM9000_TCR, TCR_TXREQ); - dev->trans_start = jiffies; - } - netif_wake_queue(dev); - } -} - -static irqreturn_t -dm9000_interrupt(int irq, void *dev_id) -{ - struct net_device *dev = dev_id; - board_info_t *db = dev->priv; - int int_status; - u8 reg_save; - - dm9000_dbg(db, 3, "entering %s\n", __func__); - - /* A real interrupt coming */ - - spin_lock(&db->lock); - - /* Save previous register address */ - reg_save = readb(db->io_addr); - - /* Disable all interrupts */ - iow(db, DM9000_IMR, IMR_PAR); - - /* Got DM9000 interrupt status */ - int_status = ior(db, DM9000_ISR); /* Got ISR */ - iow(db, DM9000_ISR, int_status); /* Clear ISR status */ - - if (netif_msg_intr(db)) - dev_dbg(db->dev, "interrupt status %02x\n", int_status); - - /* Received the coming packet */ - if (int_status & ISR_PRS) - dm9000_rx(dev); - - /* Trnasmit Interrupt check */ - if (int_status & ISR_PTS) - dm9000_tx_done(dev, db); - - if (db->type != TYPE_DM9000E) { - if (int_status & ISR_LNKCHNG) { - /* fire a link-change request */ - schedule_delayed_work(&db->phy_poll, 1); - } - } - - /* Re-enable interrupt mask */ - iow(db, DM9000_IMR, db->imr_all); - - /* Restore previous register address */ - writeb(reg_save, db->io_addr); - - spin_unlock(&db->lock); - - return IRQ_HANDLED; -} - -struct dm9000_rxhdr { - u8 RxPktReady; - u8 RxStatus; - __le16 RxLen; -} __attribute__((__packed__)); - -/* - * Received a packet and pass to upper layer - */ -static void -dm9000_rx(struct net_device *dev) -{ - board_info_t *db = (board_info_t *) dev->priv; - struct dm9000_rxhdr rxhdr; - struct sk_buff *skb; - u8 rxbyte, *rdptr; - bool GoodPacket; - int RxLen; - - /* Check packet ready or not */ - do { - ior(db, DM9000_MRCMDX); /* Dummy read */ - - /* Get most updated data */ - rxbyte = readb(db->io_data); - - /* Status check: this byte must be 0 or 1 */ - if (rxbyte > DM9000_PKT_RDY) { - dev_warn(db->dev, "status check fail: %d\n", rxbyte); - iow(db, DM9000_RCR, 0x00); /* Stop Device */ - iow(db, DM9000_ISR, IMR_PAR); /* Stop INT request */ - return; - } - - if (rxbyte != DM9000_PKT_RDY) - return; - - /* A packet ready now & Get status/length */ - GoodPacket = true; - writeb(DM9000_MRCMD, db->io_addr); - - (db->inblk)(db->io_data, &rxhdr, sizeof(rxhdr)); - - RxLen = le16_to_cpu(rxhdr.RxLen); - - if (netif_msg_rx_status(db)) - dev_dbg(db->dev, "RX: status %02x, length %04x\n", - rxhdr.RxStatus, RxLen); - - /* Packet Status check */ - if (RxLen < 0x40) { - GoodPacket = false; - if (netif_msg_rx_err(db)) - dev_dbg(db->dev, "RX: Bad Packet (runt)\n"); - } - - if (RxLen > DM9000_PKT_MAX) { - dev_dbg(db->dev, "RST: RX Len:%x\n", RxLen); - } - - if (rxhdr.RxStatus & 0xbf) { - GoodPacket = false; - if (rxhdr.RxStatus & 0x01) { - if (netif_msg_rx_err(db)) - dev_dbg(db->dev, "fifo error\n"); - dev->stats.rx_fifo_errors++; - } - if (rxhdr.RxStatus & 0x02) { - if (netif_msg_rx_err(db)) - dev_dbg(db->dev, "crc error\n"); - dev->stats.rx_crc_errors++; - } - if (rxhdr.RxStatus & 0x80) { - if (netif_msg_rx_err(db)) - dev_dbg(db->dev, "length error\n"); - dev->stats.rx_length_errors++; - } - } - - /* Move data from DM9000 */ - if (GoodPacket - && ((skb = dev_alloc_skb(RxLen + 4)) != NULL)) { - skb_reserve(skb, 2); - rdptr = (u8 *) skb_put(skb, RxLen - 4); - - /* Read received packet from RX SRAM */ - - (db->inblk)(db->io_data, rdptr, RxLen); - dev->stats.rx_bytes += RxLen; - - /* Pass to upper layer */ - skb->protocol = eth_type_trans(skb, dev); - netif_rx(skb); - dev->stats.rx_packets++; - - } else { - /* need to dump the packet's data */ - - (db->dumpblk)(db->io_data, RxLen); - } - } while (rxbyte == DM9000_PKT_RDY); -} - -static unsigned int -dm9000_read_locked(board_info_t *db, int reg) -{ - unsigned long flags; - unsigned int ret; - - spin_lock_irqsave(&db->lock, flags); - ret = ior(db, reg); - spin_unlock_irqrestore(&db->lock, flags); - - return ret; -} - -static int dm9000_wait_eeprom(board_info_t *db) -{ - unsigned int status; - int timeout = 8; /* wait max 8msec */ - - /* The DM9000 data sheets say we should be able to - * poll the ERRE bit in EPCR to wait for the EEPROM - * operation. From testing several chips, this bit - * does not seem to work. - * - * We attempt to use the bit, but fall back to the - * timeout (which is why we do not return an error - * on expiry) to say that the EEPROM operation has - * completed. - */ - - while (1) { - status = dm9000_read_locked(db, DM9000_EPCR); - - if ((status & EPCR_ERRE) == 0) - break; - - if (timeout-- < 0) { - dev_dbg(db->dev, "timeout waiting EEPROM\n"); - break; - } - } - - return 0; -} - -/* - * Read a word data from EEPROM - */ -static void -dm9000_read_eeprom(board_info_t *db, int offset, u8 *to) -{ - unsigned long flags; - - if (db->flags & DM9000_PLATF_NO_EEPROM) { - to[0] = 0xff; - to[1] = 0xff; - return; - } - - mutex_lock(&db->addr_lock); - - spin_lock_irqsave(&db->lock, flags); - - iow(db, DM9000_EPAR, offset); - iow(db, DM9000_EPCR, EPCR_ERPRR); - - spin_unlock_irqrestore(&db->lock, flags); - - dm9000_wait_eeprom(db); - - /* delay for at-least 150uS */ - msleep(1); - - spin_lock_irqsave(&db->lock, flags); - - iow(db, DM9000_EPCR, 0x0); - - to[0] = ior(db, DM9000_EPDRL); - to[1] = ior(db, DM9000_EPDRH); - - spin_unlock_irqrestore(&db->lock, flags); - - mutex_unlock(&db->addr_lock); -} - -/* - * Write a word data to SROM - */ -static void -dm9000_write_eeprom(board_info_t *db, int offset, u8 *data) -{ - unsigned long flags; - - if (db->flags & DM9000_PLATF_NO_EEPROM) - return; - - mutex_lock(&db->addr_lock); - - spin_lock_irqsave(&db->lock, flags); - iow(db, DM9000_EPAR, offset); - iow(db, DM9000_EPDRH, data[1]); - iow(db, DM9000_EPDRL, data[0]); - iow(db, DM9000_EPCR, EPCR_WEP | EPCR_ERPRW); - spin_unlock_irqrestore(&db->lock, flags); - - dm9000_wait_eeprom(db); - - mdelay(1); /* wait at least 150uS to clear */ - - spin_lock_irqsave(&db->lock, flags); - iow(db, DM9000_EPCR, 0); - spin_unlock_irqrestore(&db->lock, flags); - - mutex_unlock(&db->addr_lock); -} - -/* - * Set DM9000 multicast address - */ -static void -dm9000_hash_table(struct net_device *dev) -{ - board_info_t *db = (board_info_t *) dev->priv; - struct dev_mc_list *mcptr = dev->mc_list; - int mc_cnt = dev->mc_count; - int i, oft; - u32 hash_val; - u16 hash_table[4]; - u8 rcr = RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN; - unsigned long flags; - - dm9000_dbg(db, 1, "entering %s\n", __func__); - - spin_lock_irqsave(&db->lock, flags); - - for (i = 0, oft = DM9000_PAR; i < 6; i++, oft++) - iow(db, oft, dev->dev_addr[i]); - - /* Clear Hash Table */ - for (i = 0; i < 4; i++) - hash_table[i] = 0x0; - - /* broadcast address */ - hash_table[3] = 0x8000; - - if (dev->flags & IFF_PROMISC) - rcr |= RCR_PRMSC; - - if (dev->flags & IFF_ALLMULTI) - rcr |= RCR_ALL; - - /* the multicast address in Hash Table : 64 bits */ - for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) { - hash_val = ether_crc_le(6, mcptr->dmi_addr) & 0x3f; - hash_table[hash_val / 16] |= (u16) 1 << (hash_val % 16); - } - - /* Write the hash table to MAC MD table */ - for (i = 0, oft = DM9000_MAR; i < 4; i++) { - iow(db, oft++, hash_table[i]); - iow(db, oft++, hash_table[i] >> 8); - } - - iow(db, DM9000_RCR, rcr); - spin_unlock_irqrestore(&db->lock, flags); -} - - -/* - * Sleep, either by using msleep() or if we are suspending, then - * use mdelay() to sleep. - */ -static void dm9000_msleep(board_info_t *db, unsigned int ms) -{ - if (db->in_suspend) - mdelay(ms); - else - msleep(ms); -} - -/* - * Read a word from phyxcer - */ -static int -dm9000_phy_read(struct net_device *dev, int phy_reg_unused, int reg) -{ - board_info_t *db = (board_info_t *) dev->priv; - unsigned long flags; - unsigned int reg_save; - int ret; - - mutex_lock(&db->addr_lock); - - spin_lock_irqsave(&db->lock,flags); - - /* Save previous register address */ - reg_save = readb(db->io_addr); - - /* Fill the phyxcer register into REG_0C */ - iow(db, DM9000_EPAR, DM9000_PHY | reg); - - iow(db, DM9000_EPCR, 0xc); /* Issue phyxcer read command */ - - writeb(reg_save, db->io_addr); - spin_unlock_irqrestore(&db->lock,flags); - - dm9000_msleep(db, 1); /* Wait read complete */ - - spin_lock_irqsave(&db->lock,flags); - reg_save = readb(db->io_addr); - - iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer read command */ - - /* The read data keeps on REG_0D & REG_0E */ - ret = (ior(db, DM9000_EPDRH) << 8) | ior(db, DM9000_EPDRL); - - /* restore the previous address */ - writeb(reg_save, db->io_addr); - spin_unlock_irqrestore(&db->lock,flags); - - mutex_unlock(&db->addr_lock); - - dm9000_dbg(db, 5, "phy_read[%02x] -> %04x\n", reg, ret); - return ret; -} - -/* - * Write a word to phyxcer - */ -static void -dm9000_phy_write(struct net_device *dev, - int phyaddr_unused, int reg, int value) -{ - board_info_t *db = (board_info_t *) dev->priv; - unsigned long flags; - unsigned long reg_save; - - dm9000_dbg(db, 5, "phy_write[%02x] = %04x\n", reg, value); - mutex_lock(&db->addr_lock); - - spin_lock_irqsave(&db->lock,flags); - - /* Save previous register address */ - reg_save = readb(db->io_addr); - - /* Fill the phyxcer register into REG_0C */ - iow(db, DM9000_EPAR, DM9000_PHY | reg); - - /* Fill the written data into REG_0D & REG_0E */ - iow(db, DM9000_EPDRL, value); - iow(db, DM9000_EPDRH, value >> 8); - - iow(db, DM9000_EPCR, 0xa); /* Issue phyxcer write command */ - - writeb(reg_save, db->io_addr); - spin_unlock_irqrestore(&db->lock, flags); - - dm9000_msleep(db, 1); /* Wait write complete */ - - spin_lock_irqsave(&db->lock,flags); - reg_save = readb(db->io_addr); - - iow(db, DM9000_EPCR, 0x0); /* Clear phyxcer write command */ - - /* restore the previous address */ - writeb(reg_save, db->io_addr); - - spin_unlock_irqrestore(&db->lock, flags); - mutex_unlock(&db->addr_lock); -} - static int dm9000_drv_suspend(struct platform_device *dev, pm_message_t state) {