📄 dm9000.c
字号:
}int dmfe_send_packet(struct sk_buff *skb, struct net_device *dev){ board_info_t *db = (board_info_t *) dev->priv; unsigned char *data_ptr; int i, tmplen; /* Disable all interrupt */ iow(db, 0xff, 0x80); /* Move data to DM9000 TX RAM */ data_ptr = (char *)skb->data; dmfe_outb(0xf8, db->ioaddr); if (db->io_mode == 2) { /* Byte mode */ for (i = 0; i < skb->len; i++) dmfe_outb((data_ptr[i] & 0xff), db->io_data); } else { /* Word mode */ tmplen = (skb->len + 1) / 2; dmfe_outsw((u16 *) data_ptr, tmplen, db->io_data); } /* Set TX length to DM9000 */ iow(db, 0xfc, skb->len & 0xff); iow(db, 0xfd, (skb->len >> 8) & 0xff); /* Issue TX polling command */ iow(db, 0x2, 0x1); /* Cleared after TX complete */ /* Re-enable interrupt mask */ iow(db, 0xff, 0x83); /* wait for completion */ while ((dmfe_irq_pending(dev) | ETHIRQ_TX) == 0) ; dmfe_irq_clear(ETHIRQ_TX, dev); return 0;}int dmfe_receive_packet(struct net_device *dev){ board_info_t *db = (board_info_t *) dev->priv; struct sk_buff *skb; u8 rxbyte; u8 *rdptr; u16 i, RxStatus, RxLen, GoodPacket, tmplen; int npacket = 0;#if DM9000_RXDMA int reloc, last_lo = 0, last_hi = 0;#endif // while ((dmfe_irq_pending(dev) | ETHIRQ_RX) == 0) // ; dmfe_irq_clear(ETHIRQ_RX, dev); /* Check packet ready or not */ do { rxbyte = ior(db, 0xf0); /* Dummy read */ rxbyte = ior(db, 0xf0); /* Got most updated data */ /* Status check: this byte must be 0 or 1 */ if (rxbyte > DM9000_PKT_RDY) { PrintUart("<DM9000> STOP\r\n", -1); iow(db, 0x05, 0x00); /* Stop Device */ iow(db, 0xfe, 0x80); /* Stop INT request */ db->device_wait_reset = 1; } /* packet ready to receive check */ if (rxbyte == DM9000_PKT_RDY) { /* A packet ready now & Get status/length */ GoodPacket = 1; if (db->io_mode == 2) { /* Byte mode */ RxStatus = ior(db, 0xf2) + (ior(db, 0xf2) << 8); RxLen = ior(db, 0xf2) + (ior(db, 0xf2) << 8); } else { /* Word mode */ dmfe_outb(0xf2, db->ioaddr); RxStatus = dmfe_inw(db->io_data); RxLen = dmfe_inw(db->io_data); } /* Packet Status check */ if (RxLen < 0x40) { GoodPacket = 0; } if (RxLen > DM9000_PKT_MAX) { PrintUart("<DM9000> RST : Overflow\r\n", -1); db->device_wait_reset = 1; } if (RxStatus & 0xbf00) GoodPacket = 0; /* Move data from DM9000 */ if (!db->device_wait_reset) { if ((skb = skb_alloc(RxLen + 8)) == NULL) PrintUart("<DM9000> SKB allocation fail.\r\n", -1); if (GoodPacket && skb) { skb->len = RxLen; rdptr = (u8 *) skb->data; /* Read received packet from RX SARM */ if (db->io_mode == 2) { /* Byte mode */ for (i = 0; i < RxLen; i++) rdptr[i] = dmfe_inb(db->io_data); } else { /* Word mode */ tmplen = (RxLen + 1) / 2;#if DM9000_RXDMA if ((tmplen & 0x03) != 0) { reloc = 1; last_lo = ior(db, 0xf4); last_hi = ior(db, 0xf5); dmfe_outb(0xf2, db->ioaddr); } else reloc = 0; dmfe_start_rxdma((u16 *) rdptr, tmplen, db->io_data); dmfe_cleanup_rxdma(); if (reloc) { // DMA transfers by 8 bytes. so it needs validating RXMEM ptr last_lo += (tmplen << 1); while (last_lo >= 0x100) { if (++last_hi == 0x40) last_hi = 0x0c; last_lo -= 0x100; } iow(db, 0xf4, last_lo); iow(db, 0xf5, last_hi); }#else dmfe_insw((u16 *) rdptr, tmplen, db->io_data);#endif } /* Pass to upper layer */ skb_put(skb); ++npacket; } else { PrintUart("<DM9000> : Bad Packet\r\n", -1); /* Without buffer or error packet */ if (db->io_mode == 2) { /* Byte mode */ for (i = 0; i < RxLen; i++) dmfe_inb(db->io_data); } else { /* Word mode */ tmplen = (RxLen + 1) / 2; for (i = 0; i < tmplen; i++) dmfe_inw(db->io_data); } } } } } while (rxbyte && !db->device_wait_reset); return npacket;}void dmfe_print_status(struct net_device *dev){ static struct { int addr; int len; } s_reg_list[] = { { 0x00, 1 }, { 0x01, 1 }, { 0x02, 1 }, { 0x03, 1 }, { 0x04, 1 }, { 0x05, 1 }, { 0x06, 1 }, { 0x07, 1 }, { 0x08, 1 }, { 0x09, 1 }, { 0x0a, 1 }, { 0x0b, 1 }, { 0x0c, 1 }, { 0x0d, 2 }, { 0x0f, 1 }, { 0x10, 6 }, { 0x16, 8 }, { 0x1e, 1 }, { 0x1f, 1 }, { 0x22, 2 }, { 0x24, 2 }, { 0x28, 2 }, { 0x2a, 2 }, { 0x2c, 1 }, { 0x2f, 1 }, { 0xf4, 2 }, { 0xfa, 2 }, { 0xfc, 2 }, { 0xfe, 1 }, { 0xff, 1 }, { -1, 0 }, }; board_info_t *db = (board_info_t *) dev->priv; int i, j; for (i = 0; s_reg_list[i].addr >= 0; ++i) { PrintFormat("%02X : ", s_reg_list[i].addr); for (j = 0; j < s_reg_list[i].len; ++j) PrintFormat("%02X ", ior(db, s_reg_list[i].addr + j)); PrintFormat("\n"); }}//// Miscellaneous///* Identify NIC type*/void identify_nic(board_info_t *db){ u16 phy_reg3; iow(db, 0, DM9000_EXT_MII); phy_reg3 = phy_read(db, 3); switch (phy_reg3 & 0xfff0) { case 0xb900: if (phy_read(db, 31) == 0x4404) { db->nic_type = HOMERUN_NIC; program_dm9801(db, phy_reg3); } else { db->nic_type = LONGRUN_NIC; program_dm9802(db); } break; default: db->nic_type = FASTETHER_NIC; break; } iow(db, 0, DM9000_INT_MII); }static int g_nfloor = 0;void program_dm9801(board_info_t *db, u16 HPNA_rev){ u16 reg16, reg17, reg24, reg25; if (!g_nfloor) g_nfloor = DM9801_NOISE_FLOOR; reg16 = phy_read(db, 16); reg17 = phy_read(db, 17); reg24 = phy_read(db, 24); reg25 = phy_read(db, 25); switch (HPNA_rev) { case 0xb900: /* DM9801 E3 */ reg16 |= 0x1000; reg25 = ((reg24 + g_nfloor) & 0x00ff) | 0xf000; break; case 0xb901: /* DM9801 E4 */ reg25 = ((reg24 + g_nfloor) & 0x00ff) | 0xc200; reg17 = (reg17 & 0xfff0) + g_nfloor + 3; break; case 0xb902: /* DM9801 E5 */ case 0xb903: /* DM9801 E6 */ default: reg16 |= 0x1000; reg25 = ((reg24 + g_nfloor - 3) & 0x00ff) | 0xc200; reg17 = (reg17 & 0xfff0) + g_nfloor; break; } phy_write(db, 16, reg16); phy_write(db, 17, reg17); phy_write(db, 25, reg25);}/* Init LongRun DM9802*/void program_dm9802(board_info_t *db){ u16 reg25; if (!g_nfloor) g_nfloor = DM9802_NOISE_FLOOR; reg25 = phy_read(db, 25); reg25 = (reg25 & 0xff00) + g_nfloor; phy_write(db, 25, reg25);}/* Set PHY operationg mode*/void set_PHY_mode(board_info_t *db){ u16 phy_reg4 = 0x01e1, phy_reg0=0x1000; if (!(db->op_mode & DM9000_AUTO)) { switch (db->op_mode) { case DM9000_10MHD: phy_reg4 = 0x21; phy_reg0 = 0x0000; break; case DM9000_10MFD: phy_reg4 = 0x41; phy_reg0 = 0x1100; break; case DM9000_100MHD: phy_reg4 = 0x81; phy_reg0 = 0x2000; break; case DM9000_100MFD: phy_reg4 = 0x101; phy_reg0 =0x3100; break; } phy_write(db, 4, phy_reg4); /* Set PHY media mode */ phy_write(db, 0, phy_reg0); /* Tmp */ } iow(db, 0x1e, 0x01); /* Let GPIO0 output */ iow(db, 0x1f, 0x00); /* Enable PHY */}/* Read a word from phyxcer*/u16 phy_read(board_info_t *db, int reg){ /* Fill the phyxcer register into REG_0C */ iow(db, 0xc, DM9000_PHY | reg); iow(db, 0xb, 0xc); /* Issue phyxcer read command */ udelay(100); /* Wait read complete */ iow(db, 0xb, 0x0); /* Clear phyxcer read command */ /* The read data keeps on REG_0D & REG_0E */ return (ior(db, 0xe) << 8) | ior(db, 0xd);}/* Write a word to phyxcer*/void phy_write(board_info_t *db, int reg, u16 value){ /* Fill the phyxcer register into REG_0C */ iow(db, 0xc, DM9000_PHY | reg); /* Fill the written data into REG_0D & REG_0E */ iow(db, 0xd, (value & 0xff)); iow(db, 0xe, ((value >> 8) & 0xff)); iow(db, 0xb, 0xa); /* Issue phyxcer write command */ udelay(500); /* Wait write complete */ iow(db, 0xb, 0x0); /* Clear phyxcer write command */}/* * EEPROM interface * * chipset : HOLTEK HT93LC46 * size : 1K bit = 128 bytes = 64 words * * DM9000 registers * 0xb : EEPROM control register * 0xc : EEPROM address register * 0xd : EEPROM data register low byte * 0xe : EEPROM data register high byte */// reg : index of register // now it workks as 64 words * 16 bits// so the reg is between [0..63]unsigned short dmfe_eeprom_readw(struct net_device *dev, int reg){ board_info_t *db = (board_info_t *) dev->priv; iow(db, 0xc, reg); // Address iow(db, 0xb, 0x4); // READ Register udelay(200); // delay iow(db, 0xb, 0x0); // end READ command return (unsigned short) (ior(db, 0xd) + (ior(db, 0xe) << 8));}void dmfe_eeprom_writew(struct net_device *dev, int reg, int data){ board_info_t *db = (board_info_t *) dev->priv; iow(db, 0xc, reg); // Address iow(db, 0xd, (data & 0xff)); // Data Low iow(db, 0xe, (data >> 8) & 0xff); // Data High iow(db, 0xb, 0x12); // WRITE Register with Write EEPROM Enable udelay(200); // delay iow(db, 0xb, 0x0); // end WRITE command}#endif // SUPPORT_NET
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -