static void ks8842_rx_frame(struct net_device *netdev, struct ks8842_adapter *adapter) { u32 status = ks8842_read32(adapter, 17, REG_QMU_DATA_LO); int len = (status >> 16) & 0x7ff; status &= 0xffff; dev_dbg(&adapter->pdev->dev, "%s - rx_data: status: %x\n", __func__, status); /* check the status */ if ((status & RXSR_VALID) && !(status & RXSR_ERROR)) { struct sk_buff *skb = netdev_alloc_skb_ip_align(netdev, len); dev_dbg(&adapter->pdev->dev, "%s, got package, len: %d\n", __func__, len); if (skb) { u32 *data; netdev->stats.rx_packets++; netdev->stats.rx_bytes += len; if (status & RXSR_MULTICAST) netdev->stats.multicast++; data = (u32 *)skb_put(skb, len); ks8842_select_bank(adapter, 17); while (len > 0) { *data++ = ioread32(adapter->hw_addr + REG_QMU_DATA_LO); len -= sizeof(u32); } skb->protocol = eth_type_trans(skb, netdev); netif_rx(skb); } else netdev->stats.rx_dropped++; } else { dev_dbg(&adapter->pdev->dev, "RX error, status: %x\n", status); netdev->stats.rx_errors++; if (status & RXSR_TOO_LONG) netdev->stats.rx_length_errors++; if (status & RXSR_CRC_ERROR) netdev->stats.rx_crc_errors++; if (status & RXSR_RUNT) netdev->stats.rx_frame_errors++; } /* set high watermark to 3K */ ks8842_clear_bits(adapter, 0, 1 << 12, REG_QRFCR); /* release the frame */ ks8842_write16(adapter, 17, 0x01, REG_RXQCR); /* set high watermark to 2K */ ks8842_enable_bits(adapter, 0, 1 << 12, REG_QRFCR); }
static void ks8842_reset_hw(struct ks8842_adapter *adapter) { /* reset the HW */ ks8842_reset(adapter); /* Enable QMU Transmit flow control / transmit padding / Transmit CRC */ ks8842_write16(adapter, 16, 0x000E, REG_TXCR); /* enable the receiver, uni + multi + broadcast + flow ctrl + crc strip */ ks8842_write16(adapter, 16, 0x8 | 0x20 | 0x40 | 0x80 | 0x400, REG_RXCR); /* TX frame pointer autoincrement */ ks8842_write16(adapter, 17, 0x4000, REG_TXFDPR); /* RX frame pointer autoincrement */ ks8842_write16(adapter, 17, 0x4000, REG_RXFDPR); /* RX 2 kb high watermark */ ks8842_write16(adapter, 0, 0x1000, REG_QRFCR); /* aggresive back off in half duplex */ ks8842_enable_bits(adapter, 32, 1 << 8, REG_SGCR1); /* enable no excessive collison drop */ ks8842_enable_bits(adapter, 32, 1 << 3, REG_SGCR2); /* Enable port 1 force flow control / back pressure / transmit / recv */ ks8842_write16(adapter, 48, 0x1E07, REG_P1CR2); /* restart port auto-negotiation */ ks8842_enable_bits(adapter, 49, 1 << 13, REG_P1CR4); /* only advertise 10Mbps */ ks8842_clear_bits(adapter, 49, 3 << 2, REG_P1CR4); /* Enable the transmitter */ ks8842_enable_tx(adapter); /* Enable the receiver */ ks8842_enable_rx(adapter); /* clear all interrupts */ ks8842_write16(adapter, 18, 0xffff, REG_ISR); /* enable interrupts */ ks8842_write16(adapter, 18, ENABLED_IRQS, REG_IER); /* enable the switch */ ks8842_write16(adapter, 32, 0x1, REG_SW_ID_AND_ENABLE); }
static void ks8842_disable_rx(struct ks8842_adapter *adapter) { ks8842_clear_bits(adapter, 16, 0x01, REG_RXCR); }