📄 dc2114x.c
字号:
static int dc21x4x_send(struct eth_device* dev, volatile void *packet, int length){ int status = -1; int i; if (length <= 0) { printf("%s: bad packet size: %d\n", dev->name, length); goto Done; } for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { if (i >= TOUT_LOOP) { printf("%s: tx error buffer not ready\n", dev->name); goto Done; } } tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32) packet)); tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_LS | TD_FS | length); tx_ring[tx_new].status = cpu_to_le32(T_OWN); OUTL(dev, POLL_DEMAND, DE4X5_TPD); for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { if (i >= TOUT_LOOP) { printf(".%s: tx buffer not ready\n", dev->name); goto Done; } } if (le32_to_cpu(tx_ring[tx_new].status) & TD_ES) {#if 0 /* test-only */ printf("TX error status = 0x%08X\n", le32_to_cpu(tx_ring[tx_new].status));#endif tx_ring[tx_new].status = 0x0; goto Done; } status = length; Done: tx_new = (tx_new+1) % NUM_TX_DESC; return status;}static int dc21x4x_recv(struct eth_device* dev){ s32 status; int length = 0; for ( ; ; ) { status = (s32)le32_to_cpu(rx_ring[rx_new].status); if (status & R_OWN) { break; } if (status & RD_LS) { /* Valid frame status. */ if (status & RD_ES) { /* There was an error. */ printf("RX error status = 0x%08X\n", status); } else { /* A valid frame received. */ length = (le32_to_cpu(rx_ring[rx_new].status) >> 16); /* Pass the packet up to the protocol * layers. */ NetReceive(NetRxPackets[rx_new], length - 4); } /* Change buffer ownership for this frame, back * to the adapter. */ rx_ring[rx_new].status = cpu_to_le32(R_OWN); } /* Update entry information. */ rx_new = (rx_new + 1) % rxRingSize; } return length;}static void dc21x4x_halt(struct eth_device* dev){ int devbusfn = (int) dev->priv; STOP_DE4X5(dev); OUTL(dev, 0, DE4X5_SICR); pci_write_config_byte(devbusfn, PCI_CFDA_PSM, SLEEP);}static void send_setup_frame(struct eth_device* dev, bd_t *bis){ int i; char setup_frame[SETUP_FRAME_LEN]; char *pa = &setup_frame[0]; memset(pa, 0xff, SETUP_FRAME_LEN); for (i = 0; i < ETH_ALEN; i++) { *(pa + (i & 1)) = dev->enetaddr[i]; if (i & 0x01) { pa += 4; } } for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { if (i >= TOUT_LOOP) { printf("%s: tx error buffer not ready\n", dev->name); goto Done; } } tx_ring[tx_new].buf = cpu_to_le32(phys_to_bus((u32) &setup_frame[0])); tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_SET| SETUP_FRAME_LEN); tx_ring[tx_new].status = cpu_to_le32(T_OWN); OUTL(dev, POLL_DEMAND, DE4X5_TPD); for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++) { if (i >= TOUT_LOOP) { printf("%s: tx buffer not ready\n", dev->name); goto Done; } } if (le32_to_cpu(tx_ring[tx_new].status) != 0x7FFFFFFF) { printf("TX error status2 = 0x%08X\n", le32_to_cpu(tx_ring[tx_new].status)); } tx_new = (tx_new+1) % NUM_TX_DESC;Done: return;}#if defined(UPDATE_SROM) || !defined(CONFIG_TULIP_FIX_DAVICOM)/* SROM Read and write routines. */static voidsendto_srom(struct eth_device* dev, u_int command, u_long addr){ OUTL(dev, command, addr); udelay(1);}static intgetfrom_srom(struct eth_device* dev, u_long addr){ s32 tmp; tmp = INL(dev, addr); udelay(1); return tmp;}/* Note: this routine returns extra data bits for size detection. */static int do_read_eeprom(struct eth_device *dev, u_long ioaddr, int location, int addr_len){ int i; unsigned retval = 0; int read_cmd = location | (SROM_READ_CMD << addr_len); sendto_srom(dev, SROM_RD | SROM_SR, ioaddr); sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);#ifdef DEBUG_SROM printf(" EEPROM read at %d ", location);#endif /* Shift the read command bits out. */ for (i = 4 + addr_len; i >= 0; i--) { short dataval = (read_cmd & (1 << i)) ? EE_DATA_WRITE : 0; sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval, ioaddr); udelay(10); sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | dataval | DT_CLK, ioaddr); udelay(10);#ifdef DEBUG_SROM2 printf("%X", getfrom_srom(dev, ioaddr) & 15);#endif retval = (retval << 1) | ((getfrom_srom(dev, ioaddr) & EE_DATA_READ) ? 1 : 0); } sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr);#ifdef DEBUG_SROM2 printf(" :%X:", getfrom_srom(dev, ioaddr) & 15);#endif for (i = 16; i > 0; i--) { sendto_srom(dev, SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr); udelay(10);#ifdef DEBUG_SROM2 printf("%X", getfrom_srom(dev, ioaddr) & 15);#endif retval = (retval << 1) | ((getfrom_srom(dev, ioaddr) & EE_DATA_READ) ? 1 : 0); sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); udelay(10); } /* Terminate the EEPROM access. */ sendto_srom(dev, SROM_RD | SROM_SR, ioaddr);#ifdef DEBUG_SROM2 printf(" EEPROM value at %d is %5.5x.\n", location, retval);#endif return retval;}#endif /* UPDATE_SROM || !CONFIG_TULIP_FIX_DAVICOM *//* This executes a generic EEPROM command, typically a write or write * enable. It returns the data output from the EEPROM, and thus may * also be used for reads. */#if defined(UPDATE_SROM) || !defined(CONFIG_TULIP_FIX_DAVICOM)static int do_eeprom_cmd(struct eth_device *dev, u_long ioaddr, int cmd, int cmd_len){ unsigned retval = 0;#ifdef DEBUG_SROM printf(" EEPROM op 0x%x: ", cmd);#endif sendto_srom(dev,SROM_RD | SROM_SR | DT_CS | DT_CLK, ioaddr); /* Shift the command bits out. */ do { short dataval = (cmd & (1 << cmd_len)) ? EE_WRITE_1 : EE_WRITE_0; sendto_srom(dev,dataval, ioaddr); udelay(10);#ifdef DEBUG_SROM2 printf("%X", getfrom_srom(dev,ioaddr) & 15);#endif sendto_srom(dev,dataval | DT_CLK, ioaddr); udelay(10); retval = (retval << 1) | ((getfrom_srom(dev,ioaddr) & EE_DATA_READ) ? 1 : 0); } while (--cmd_len >= 0); sendto_srom(dev,SROM_RD | SROM_SR | DT_CS, ioaddr); /* Terminate the EEPROM access. */ sendto_srom(dev,SROM_RD | SROM_SR, ioaddr);#ifdef DEBUG_SROM printf(" EEPROM result is 0x%5.5x.\n", retval);#endif return retval;}#endif /* UPDATE_SROM || !CONFIG_TULIP_FIX_DAVICOM */#ifndef CONFIG_TULIP_FIX_DAVICOMstatic int read_srom(struct eth_device *dev, u_long ioaddr, int index){ int ee_addr_size = do_read_eeprom(dev, ioaddr, 0xff, 8) & 0x40000 ? 8 : 6; return do_eeprom_cmd(dev, ioaddr, (((SROM_READ_CMD << ee_addr_size) | index) << 16) | 0xffff, 3 + ee_addr_size + 16);}#endif /* CONFIG_TULIP_FIX_DAVICOM */#ifdef UPDATE_SROMstatic int write_srom(struct eth_device *dev, u_long ioaddr, int index, int new_value){ int ee_addr_size = do_read_eeprom(dev, ioaddr, 0xff, 8) & 0x40000 ? 8 : 6; int i; unsigned short newval; udelay(10*1000); /* test-only */#ifdef DEBUG_SROM printf("ee_addr_size=%d.\n", ee_addr_size); printf("Writing new entry 0x%4.4x to offset %d.\n", new_value, index);#endif /* Enable programming modes. */ do_eeprom_cmd(dev, ioaddr, (0x4f << (ee_addr_size-4)), 3+ee_addr_size); /* Do the actual write. */ do_eeprom_cmd(dev, ioaddr, (((SROM_WRITE_CMD<<ee_addr_size)|index) << 16) | new_value, 3 + ee_addr_size + 16); /* Poll for write finished. */ sendto_srom(dev, SROM_RD | SROM_SR | DT_CS, ioaddr); for (i = 0; i < 10000; i++) /* Typical 2000 ticks */ if (getfrom_srom(dev, ioaddr) & EE_DATA_READ) break;#ifdef DEBUG_SROM printf(" Write finished after %d ticks.\n", i);#endif /* Disable programming. */ do_eeprom_cmd(dev, ioaddr, (0x40 << (ee_addr_size-4)), 3 + ee_addr_size); /* And read the result. */ newval = do_eeprom_cmd(dev, ioaddr, (((SROM_READ_CMD<<ee_addr_size)|index) << 16) | 0xffff, 3 + ee_addr_size + 16);#ifdef DEBUG_SROM printf(" New value at offset %d is %4.4x.\n", index, newval);#endif return 1;}#endif#ifndef CONFIG_TULIP_FIX_DAVICOMstatic void read_hw_addr(struct eth_device *dev, bd_t *bis){ u_short tmp, *p = (short *)(&dev->enetaddr[0]); int i, j = 0; for (i = 0; i < (ETH_ALEN >> 1); i++) { tmp = read_srom(dev, DE4X5_APROM, ((SROM_HWADD >> 1) + i)); *p = le16_to_cpu(tmp); j += *p++; } if ((j == 0) || (j == 0x2fffd)) { memset (dev->enetaddr, 0, ETH_ALEN); debug ("Warning: can't read HW address from SROM.\n"); goto Done; } return;Done:#ifdef UPDATE_SROM update_srom(dev, bis);#endif return;}#endif /* CONFIG_TULIP_FIX_DAVICOM */#ifdef UPDATE_SROMstatic void update_srom(struct eth_device *dev, bd_t *bis){ int i; static unsigned short eeprom[0x40] = { 0x140b, 0x6610, 0x0000, 0x0000, /* 00 */ 0x0000, 0x0000, 0x0000, 0x0000, /* 04 */ 0x00a3, 0x0103, 0x0000, 0x0000, /* 08 */ 0x0000, 0x1f00, 0x0000, 0x0000, /* 0c */ 0x0108, 0x038d, 0x0000, 0x0000, /* 10 */ 0xe078, 0x0001, 0x0040, 0x0018, /* 14 */ 0x0000, 0x0000, 0x0000, 0x0000, /* 18 */ 0x0000, 0x0000, 0x0000, 0x0000, /* 1c */ 0x0000, 0x0000, 0x0000, 0x0000, /* 20 */ 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */ 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */ 0x0000, 0x0000, 0x0000, 0x0000, /* 2c */ 0x0000, 0x0000, 0x0000, 0x0000, /* 30 */ 0x0000, 0x0000, 0x0000, 0x0000, /* 34 */ 0x0000, 0x0000, 0x0000, 0x0000, /* 38 */ 0x0000, 0x0000, 0x0000, 0x4e07, /* 3c */ }; /* Ethernet Addr... */ eeprom[0x0a] = ((bis->bi_enetaddr[1] & 0xff) << 8) | (bis->bi_enetaddr[0] & 0xff); eeprom[0x0b] = ((bis->bi_enetaddr[3] & 0xff) << 8) | (bis->bi_enetaddr[2] & 0xff); eeprom[0x0c] = ((bis->bi_enetaddr[5] & 0xff) << 8) | (bis->bi_enetaddr[4] & 0xff); for (i=0; i<0x40; i++) { write_srom(dev, DE4X5_APROM, i, eeprom[i]); }}#endif /* UPDATE_SROM */#endif /* CFG_CMD_NET && CONFIG_NET_MULTI && CONFIG_TULIP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -