📄 ethernet_cs8900a.c
字号:
return 0; } //if there are no errors, assume everything is ok return 1;}////////////////////////////////////////////////////////////////////////////////// rx_packet_ethernet// PURPOSE: Receives a packet.// PARAMS: (IN) u8 * data - buffer for received packet.// (IN) u16 * size - size of buffer.// (OUT) u16 * size - actual size of received packet. If unchanged// packet may be truncated.// RETURNS: 1 for success, 0 for failure.////////////////////////////////////////////////////////////////////////////////intrx_packet_ethernet(u8 *data, u16 *size, char bcast_enable){ u16 rx_size = 1; int i; u16 oddword; u16 temp; //see if the chip has a packet waiting to be copied out temp = readcs(RX_EVENT); if((temp & RX_PACKET_RECEIVED_OK) == 0) { return 0; } rx_size = readcs(RX_LENGTH); //tell the chip to automatically increment it's internal address register //each time we read from it. (*(volatile u16 *)(BASE_ADDR + ADDRESS_PORT)) = (RX_FRAME | AUTOINCREMENT); //copy the packet out of the chips buffer //if our destination address is u16 aligned, we can do 16 bit transfers if((u32)data % sizeof(u16)) { for(i = 0;i < (rx_size / sizeof(u16));i++) { oddword = *(volatile u16 *)(BASE_ADDR + DATA_PORT); *(u8 *)data++ = (u8)oddword & 0xFF; *(u8 *)data++ = (u8)(oddword >> 8) & 0xFF; } } else { for(i = 0;i < (rx_size / 2);i++) { *(u16 *)data = *(volatile u16 *)(BASE_ADDR + DATA_PORT); data += 2; } } //If the rxed packet is of uneven size, we will need to get the last byte if(rx_size % sizeof(u16)) { *data = (u8)(*(volatile u16 *)(BASE_ADDR + DATA_PORT) & 0xFF); } //For some reason, the CS8900 reports the size as one dword larger than it //actually is. Perhaps it is including the values of RX_EVENT and RX_LENGTH //in the size. *size = (int)rx_size - sizeof(u32); return 1;}#if DEBUG_LEVEL >= 4////////////////////////////////////////////////////////////////////////////////// dump_eeprom// PURPOSE: Dumps the raw contents of the interesting portion of the EEPROM// PARAMS: Nothing.// RETURNS: Nothing.////////////////////////////////////////////////////////////////////////////////static inline voiddump_eeprom(void){ int addr; for (addr=0; addr < (EEPROM_ADDR_IA_W2+1); ++addr) { u16 data; read_eeprom_ethernet(addr, &data); itc_printf("%x: %x\r\n", addr, data); }}#endif////////////////////////////////////////////////////////////////////////////////// read_mac_ethernet// PURPOSE: Reads the MAC address.// PARAMS: (OUT) u16 * macaddr - An array to return the MAC address.// RETURNS: 1 for success, 0 for failure.////////////////////////////////////////////////////////////////////////////////intread_mac_ethernet(u16 *macaddr, unsigned short num){#if defined (TAGGED_EEPROM) && defined(CONFIG_EEPROM_24LC64) u16 mac_size=sizeof(short) * 3; char tag[7]; // Try to read the tagged format MAC address. if (check_eeprom_header()) { itc_strcpy(tag, "MACADx"); tag[5] = num + '0'; if (eeprom_get_item(tag, sizeof(tag)-1, (u8 *)macaddr, &mac_size) <= 0) { DEBUG_3("Could not find EEPROM tag %s\r\n", tag); return 0; } return 1; } //no fallback! return 0;#endif if (num != 0) { // This driver supports only a single Ethernet chip return 0; } if (!probe_cs8900a((char *)BASE_ADDR)) { // We don't seem to have a CS8900 to read return 0; }#if DEBUG_LEVEL >= 4 dump_eeprom();#endif // If the reset configuration block of the EEPROM was read correctly // at reset time, then SSR_EEPROM_OK will be set. Get the MAC address // from the CS8900 Individual Address Register in that case. if (readcs(SSR) & SSR_EEPROM_OK) { macaddr[0] = readcs(IAR+0); macaddr[1] = readcs(IAR+2); macaddr[2] = readcs(IAR+4); DEBUG_4("Got MAC from chip\r\n"); return 1; } // The chip indicates that no reset configuration block was found. This // means either that the MAC address is not set on this device, or was set // on an older version of I-Boot using our own nonstandard format. DEBUG_4("Got MAC from EEPROM\r\n"); return (read_eeprom_ethernet(EEPROM_ADDR_IA_W0, &macaddr[0]) && read_eeprom_ethernet(EEPROM_ADDR_IA_W1, &macaddr[1]) && read_eeprom_ethernet(EEPROM_ADDR_IA_W2, &macaddr[2]));}////////////////////////////////////////////////////////////////////////////////// write_mac_ethernet// PURPOSE: Writes a new MAC address.// PARAMS: (IN) u16 * macaddr - An array containing the new MAC address.// RETURNS: 1 for success, 0 for failure.////////////////////////////////////////////////////////////////////////////////intwrite_mac_ethernet(u16 *macaddr, unsigned short num){ // See section 3.4.4 in the data sheet for the meaning of this structure static u16 data[]= { // Magic header 0xa10a, // Block 1 (reg 0x158 (IAR), len 2+1) (2 << 12) | IAR, 0x0000, /* MAC ADDR */ 0x0000, 0x0000, }; int result = 1; u16 sum = 0; int i;#if defined (TAGGED_EEPROM) && defined(CONFIG_EEPROM_24LC64) u16 mac_size=sizeof(short) * 3; char tag[7]; itc_strcpy(tag, "MACADx"); tag[5] = num + '0'; if (eeprom_write_item(tag, sizeof(tag)-1, (u8 *)macaddr, mac_size) < 0) { itc_printf("ERROR: Could not write to EEPROM\r\n"); return 0; } return 1;#endif /* insert MAC ADDR into block 1 */ data[2] = macaddr[0]; data[3] = macaddr[1]; data[4] = macaddr[2]; /* write configuration block */ for(i=0; i < countof(data); i++) { sum += (data[i]&0xff) + (data[i]>>8); result &= write_eeprom_ethernet(i, data[i]); } /* write the checksum */ result &= write_eeprom_ethernet(i, ((0x100 - (sum & 0xff)) & 0xff) << 8); /* * Write a copy of the MAC address here for backwards compatibility with * old bootloaders. * Note that this could overwrite data stored in tagged EEPROM format, * but that will be caught by the CRC check. */ result &= write_eeprom_ethernet(EEPROM_ADDR_IA_W0, macaddr[0]); result &= write_eeprom_ethernet(EEPROM_ADDR_IA_W1, macaddr[1]); result &= write_eeprom_ethernet(EEPROM_ADDR_IA_W2, macaddr[2]); return result;}////////////////////////////////////////////////////////////////////////////////// read_eeprom_ethernet// PURPOSE: Reads from the attached EEPROM.// PARAMS: (IN) u16 offset - Offset from which to read.// PARAMS: (OUT) u16 * value - Value read.// RETURNS: 1 for success, 0 for failure.////////////////////////////////////////////////////////////////////////////////intread_eeprom_ethernet(u16 offset, u16 *value){ //wait for EEPROM to be free notbusy(); writecs(ECR, (offset | EEPROM_READ_CMD)); //wait for it to finish notbusy(); *value = readcs(EEPROM_DATA); return 1;}////////////////////////////////////////////////////////////////////////////////// write_eeprom_ethernet// PURPOSE: Writes to the attached EEPROM.// PARAMS: (IN) u16 offset - Offset from which to write.// (IN) u16 value - Value to write.// RETURNS: 1 for success, 0 for failure.////////////////////////////////////////////////////////////////////////////////intwrite_eeprom_ethernet(u16 offset, u16 value){ //wait for EEPROM to be free notbusy(); writecs(ECR, EEPROM_ERASE_ENABLE); notbusy(); writecs(EEPROM_DATA, value); notbusy(); writecs(ECR, (offset | EEPROM_WRITE_CMD)); notbusy(); writecs(ECR, EEPROM_ERASE_DISABLE); notbusy(); return 1;}// Not strictly necessary on the Crystalint rx_ethernet_off (void){ return 1;}// Not strictly necessary on the Crystalint rx_ethernet_on (void){ return 1;}// Not strictly necessary on the Crystalint flush_ethernet (void){ return 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -