static void ks8842_update_link_status(struct net_device *netdev, struct ks8842_adapter *adapter) { /* */ if (ks8842_read16(adapter, 45, REG_P1MBSR) & 0x4) { netif_carrier_on(netdev); netif_wake_queue(netdev); } else { netif_stop_queue(netdev); netif_carrier_off(netdev); } }
static void ks8842_read_mac_addr(struct ks8842_adapter *adapter, u8 *dest) { int i; u16 mac; for (i = 0; i < ETH_ALEN; i++) dest[ETH_ALEN - i - 1] = ks8842_read8(adapter, 2, REG_MARL + i); if (adapter->conf_flags & MICREL_KS884X) { /* the sequence of saving mac addr between MAC and Switch is different. */ mac = ks8842_read16(adapter, 2, REG_MARL); ks8842_write16(adapter, 39, mac, REG_MACAR3); mac = ks8842_read16(adapter, 2, REG_MARM); ks8842_write16(adapter, 39, mac, REG_MACAR2); mac = ks8842_read16(adapter, 2, REG_MARH); ks8842_write16(adapter, 39, mac, REG_MACAR1); } else { /* make sure the switch port uses the same MAC as the QMU */ mac = ks8842_read16(adapter, 2, REG_MARL); ks8842_write16(adapter, 39, mac, REG_MACAR1); mac = ks8842_read16(adapter, 2, REG_MARM); ks8842_write16(adapter, 39, mac, REG_MACAR2); mac = ks8842_read16(adapter, 2, REG_MARH); ks8842_write16(adapter, 39, mac, REG_MACAR3); } }
static void ks8842_read_mac_addr(struct ks8842_adapter *adapter, u8 *dest) { int i; u16 mac; for (i = 0; i < ETH_ALEN; i++) dest[ETH_ALEN - i - 1] = ks8842_read8(adapter, 2, REG_MARL + i); if (adapter->conf_flags & MICREL_KS884X) { /* */ mac = ks8842_read16(adapter, 2, REG_MARL); ks8842_write16(adapter, 39, mac, REG_MACAR3); mac = ks8842_read16(adapter, 2, REG_MARM); ks8842_write16(adapter, 39, mac, REG_MACAR2); mac = ks8842_read16(adapter, 2, REG_MARH); ks8842_write16(adapter, 39, mac, REG_MACAR1); } else { /* */ mac = ks8842_read16(adapter, 2, REG_MARL); ks8842_write16(adapter, 39, mac, REG_MACAR1); mac = ks8842_read16(adapter, 2, REG_MARM); ks8842_write16(adapter, 39, mac, REG_MACAR2); mac = ks8842_read16(adapter, 2, REG_MARH); ks8842_write16(adapter, 39, mac, REG_MACAR3); } }
void ks8842_tasklet(unsigned long arg) { struct net_device *netdev = (struct net_device *)arg; struct ks8842_adapter *adapter = netdev_priv(netdev); u16 isr; unsigned long flags; u16 entry_bank; /* read current bank to be able to set it back */ spin_lock_irqsave(&adapter->lock, flags); entry_bank = ioread16(adapter->hw_addr + REG_SELECT_BANK); spin_unlock_irqrestore(&adapter->lock, flags); isr = ks8842_read16(adapter, 18, REG_ISR); dev_dbg(&adapter->pdev->dev, "%s - ISR: 0x%x\n", __func__, isr); /* Ack */ ks8842_write16(adapter, 18, isr, REG_ISR); if (!netif_running(netdev)) return; if (isr & IRQ_LINK_CHANGE) ks8842_update_link_status(netdev, adapter); if (isr & (IRQ_RX | IRQ_RX_ERROR)) ks8842_handle_rx(netdev, adapter); if (isr & IRQ_TX) ks8842_handle_tx(netdev, adapter); if (isr & IRQ_RX_OVERRUN) ks8842_handle_rx_overrun(netdev, adapter); if (isr & IRQ_TX_STOPPED) { ks8842_disable_tx(adapter); ks8842_enable_tx(adapter); } if (isr & IRQ_RX_STOPPED) { ks8842_disable_rx(adapter); ks8842_enable_rx(adapter); } /* re-enable interrupts, put back the bank selection register */ spin_lock_irqsave(&adapter->lock, flags); ks8842_write16(adapter, 18, ENABLED_IRQS, REG_IER); iowrite16(entry_bank, adapter->hw_addr + REG_SELECT_BANK); spin_unlock_irqrestore(&adapter->lock, flags); }
static irqreturn_t ks8842_irq(int irq, void *devid) { struct ks8842_adapter *adapter = devid; u16 isr; u16 entry_bank = ioread16(adapter->hw_addr + REG_SELECT_BANK); irqreturn_t ret = IRQ_NONE; isr = ks8842_read16(adapter, 18, REG_ISR); dev_dbg(&adapter->pdev->dev, "%s - ISR: 0x%x\n", __func__, isr); if (isr) { /* disable IRQ */ ks8842_write16(adapter, 18, 0x00, REG_IER); /* schedule tasklet */ tasklet_schedule(&adapter->tasklet); ret = IRQ_HANDLED; } iowrite16(entry_bank, adapter->hw_addr + REG_SELECT_BANK); return ret; }
static inline u16 ks8842_tx_fifo_space(struct ks8842_adapter *adapter) { return ks8842_read16(adapter, 16, REG_TXMIR) & 0x1fff; }
static int __devinit ks8842_probe(struct platform_device *pdev) { int err = -ENOMEM; struct resource *iomem; struct net_device *netdev; struct ks8842_adapter *adapter; u16 id; iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!request_mem_region(iomem->start, resource_size(iomem), DRV_NAME)) goto err_mem_region; netdev = alloc_etherdev(sizeof(struct ks8842_adapter)); if (!netdev) goto err_alloc_etherdev; SET_NETDEV_DEV(netdev, &pdev->dev); adapter = netdev_priv(netdev); adapter->hw_addr = ioremap(iomem->start, resource_size(iomem)); if (!adapter->hw_addr) goto err_ioremap; adapter->irq = platform_get_irq(pdev, 0); if (adapter->irq < 0) { err = adapter->irq; goto err_get_irq; } adapter->pdev = pdev; tasklet_init(&adapter->tasklet, ks8842_tasklet, (unsigned long)netdev); spin_lock_init(&adapter->lock); netdev->netdev_ops = &ks8842_netdev_ops; netdev->ethtool_ops = &ks8842_ethtool_ops; ks8842_read_mac_addr(adapter, netdev->dev_addr); id = ks8842_read16(adapter, 32, REG_SW_ID_AND_ENABLE); strcpy(netdev->name, "eth%d"); err = register_netdev(netdev); if (err) goto err_register; platform_set_drvdata(pdev, netdev); printk(KERN_INFO DRV_NAME " Found chip, family: 0x%x, id: 0x%x, rev: 0x%x\n", (id >> 8) & 0xff, (id >> 4) & 0xf, (id >> 1) & 0x7); return 0; err_register: err_get_irq: iounmap(adapter->hw_addr); err_ioremap: free_netdev(netdev); err_alloc_etherdev: release_mem_region(iomem->start, resource_size(iomem)); err_mem_region: return err; }