📄 lan9118.c
字号:
/* check chip id. */ temp_u32 = lan9118_reg_read(LAN9118_REG_OFFSET_ID_REV); if ((temp_u32 & LAN9118_REG_ID_REV_ID_MASK) != LAN9118_REG_ID_REV_VALUE) { printf("Failed to read the ID of the lan9118 when open it!!!!\n"); return -1; } /* check chip power mode, wait for chip ready. */ temp_u32 = lan9118_reg_read(LAN9118_REG_OFFSET_PMT_CTRL); if ((temp_u32&0x00003000) != 0) { lan9118_reg_write(LAN9118_REG_OFFSET_BYTE_TEST, (U32)0); /* wake up. */ lan9118_local_delay(click/100); /* delay 10ms. */ temp_int = LAN9118_PHY_TIMEOUT; temp_u32 = lan9118_reg_read(LAN9118_REG_OFFSET_PMT_CTRL); while (temp_int--) { temp_u32 = lan9118_reg_read(LAN9118_REG_OFFSET_PMT_CTRL); if (temp_u32 & 1) { /* ready. */ break; } lan9118_local_delay(click/1000); /* delay 1ms. */ temp_int--; } temp_u32 = lan9118_reg_read(LAN9118_REG_OFFSET_PMT_CTRL); if ((temp_u32&1) == 0) { printf("lan9118 PHY not ready!!\n"); return -1; } } temp_u32 = lan9118_reg_read(LAN9118_REG_OFFSET_PMT_CTRL); if ((temp_u32&1) == 0) { printf("lan9118 PHY not ready!!\n"); return -1; } /* initialize the tx/rx buffer */ /* set the TX FIFO size. */ /*lan9118_reg_write(LAN9118_REG_OFFSET_HW_CFG, 0x00040000);*/ /* 4Kbytes. */ /* setup automatic flow control. */ lan9118_reg_write(LAN9118_REG_OFFSET_AFC_CFG, 0x8c4601); /* enable LED. */ lan9118_reg_write(LAN9118_REG_OFFSET_GPIO_CFG, 0x70000000); /* disable interrupt. */ lan9118_reg_write(LAN9118_REG_OFFSET_INT_EN, 0); lan9118_reg_write(LAN9118_REG_OFFSET_INT_STS, 0xffffffff); /* enable flow control. */ lan9118_mac_reg_write(LAN9118_REG_SUBOFFSET_FLOW, 0xffff0002); /* setup mac address. 00-40-45-1b-d2-0d */ lan9118_mac_reg_write(LAN9118_REG_SUBOFFSET_ADDRH, 0x00000dd2); lan9118_mac_reg_write(LAN9118_REG_SUBOFFSET_ADDRL, 0x1b454000); /* dump t/rx data. */ lan9118_reg_write(LAN9118_REG_OFFSET_TX_CFG, 0x0000c000); lan9118_reg_write(LAN9118_REG_OFFSET_RX_CFG, 0x00008000); /* setup parameters. */ /* TX: */ temp_u32 = lan9118_reg_read(LAN9118_REG_OFFSET_HW_CFG); temp_u32 &= 0x000f0000; temp_u32 |= 0x00100000; lan9118_reg_write(LAN9118_REG_OFFSET_HW_CFG, temp_u32); temp_u32 = lan9118_reg_read(LAN9118_REG_OFFSET_INT_EN); temp_u32 |= 0x00002000; lan9118_reg_write(LAN9118_REG_OFFSET_INT_EN, temp_u32); temp_u32 = lan9118_mac_reg_read(LAN9118_REG_SUBOFFSET_MAC_CR); temp_u32 = 0x80000008; /* temp_u32 |= 0x00000800; reject broadcast frame. */ lan9118_mac_reg_write(LAN9118_REG_SUBOFFSET_MAC_CR, temp_u32); /* RX: */ lan9118_reg_write(LAN9118_REG_OFFSET_RX_CFG, 0); temp_u32 = lan9118_mac_reg_read(LAN9118_REG_SUBOFFSET_MAC_CR); temp_u32 |= 0x00000004; lan9118_mac_reg_write(LAN9118_REG_SUBOFFSET_MAC_CR, temp_u32); temp_u32 = lan9118_reg_read(LAN9118_REG_OFFSET_FIFO_INT); temp_u32 &= 0xffff0000; lan9118_reg_write(LAN9118_REG_OFFSET_FIFO_INT, temp_u32); temp_u32 = lan9118_reg_read(LAN9118_REG_OFFSET_INT_EN); temp_u32 |= 0x00004008; lan9118_reg_write(LAN9118_REG_OFFSET_INT_EN, temp_u32); /* PHY: */ temp_u32 = ((((U32)(lan9118_phy_reg_read(LAN9118_REG_SUBOFFSET_PHY_Identifier2)))<<16)&0xffff0000); temp_u32 |= (((U32)(lan9118_phy_reg_read(LAN9118_REG_SUBOFFSET_PHY_Identifier1)))&0x0000ffff); if (temp_u32 == 0xc0d10007) { /* reset physical. */ lan9118_phy_reg_write(LAN9118_REG_SUBOFFSET_Basic_Control_Register, 0x8000); lan9118_local_delay(click/10); /* wait 100ms. */ temp_int = LAN9118_PHY_TIMEOUT; while (temp_int) { if (lan9118_phy_reg_read(LAN9118_REG_SUBOFFSET_Basic_Control_Register) & 0x8000) { temp_int -= 1; } else { break; } } if (temp_int == 0) { return -1; /* reset incomplete with timeout. */ } /* setup&start automatic negotiation. */ temp_u16 = lan9118_phy_reg_read(LAN9118_REG_SUBOFFSET_Auto_Negotiation_Advertisement_Register); temp_u16 &= ~0x0c00; /* no pause. */ temp_u16 |= 0x0c00; /* both symmetric and asymmetric pause. */ temp_u16 |= 0x01e0; /* 10/100M and Half/Full duplex. */ lan9118_phy_reg_write(LAN9118_REG_SUBOFFSET_Auto_Negotiation_Advertisement_Register, temp_u16); lan9118_local_delay(click/100); /* delay 10ms. */ temp_u16 = lan9118_phy_reg_read(LAN9118_REG_SUBOFFSET_Basic_Control_Register); temp_u16 |= 0x2100; /* 2:100M, 1:full-duplex. */ lan9118_phy_reg_write(LAN9118_REG_SUBOFFSET_Basic_Control_Register, temp_u16); lan9118_local_delay(click/100); /* delay 10ms. */ temp_u16 = lan9118_phy_reg_read(LAN9118_REG_SUBOFFSET_Basic_Control_Register); temp_u16 |= 0x1200; /* 1:enable auto negotiation, 2:restart negotiation. */ lan9118_phy_reg_write(LAN9118_REG_SUBOFFSET_Basic_Control_Register, temp_u16); lan9118_local_delay(click/100); /* delay 10ms. */ temp_int = 10*3; /* 3s */ while (temp_int) { /* whether the negotiation complete? */ temp_int -= 1; lan9118_local_delay(click/10); temp_u16 = lan9118_phy_reg_read(LAN9118_REG_SUBOFFSET_Basic_Status_Register); if (temp_u16 & 0x0020) { break; /* complete. */ } } temp_u16 = lan9118_phy_reg_read(LAN9118_REG_SUBOFFSET_Basic_Status_Register); if ((temp_u16 & 0x0020) == 0) { printf("Negotiation timeout!!!\n"); return -1; } temp_u16 = lan9118_phy_reg_read(LAN9118_REG_SUBOFFSET_Basic_Status_Register); if ((temp_u16 & 0x0004) == 0) { printf("Warning, link down!!!\nPlease plug."); } else { temp_u16 = lan9118_phy_reg_read(LAN9118_REG_SUBOFFSET_PHY_Special_Control_Status_Register); temp_u16 = temp_u16 >> 2; temp_u16 &= 0x0007; switch (temp_u16) { case 0x01: printf("Auto-negotiation complete, 10Base-T, half duplex.\n"); break; case 0x02: printf("Auto-negotiation complete, 100Base-TX, half duplex.\n"); break; case 0x05: printf("Auto-negotiation complete, 10Base-T, full duplex.\n"); break; case 0x06: printf("Auto-negotiation complete, 100Base-TX, full duplex.\n"); break; default: printf("Auto-negotiation complete, unknown!!\n");; } } /* If full duplex, the enable full duplex in MAC. */ temp_u16 = lan9118_phy_reg_read(LAN9118_REG_SUBOFFSET_Auto_Negotiation_Advertisement_Register); temp_u16 &= lan9118_phy_reg_read(LAN9118_REG_SUBOFFSET_Auto_Negotiation_Link_Partner_Ability_Register); if (temp_u16 & 0x0140) { temp_u32 = lan9118_mac_reg_read(LAN9118_REG_SUBOFFSET_MAC_CR); temp_u32 |= 0x00100000; lan9118_mac_reg_write(LAN9118_REG_SUBOFFSET_MAC_CR, temp_u32); } } else { printf("Unknown PHY-ID: 0x%x", temp_u32); return -1; } return 0;}/* lan9118_send - send array via lan9118 with interrupt. */int tx_package_tag = 0;int transmit_busy_wait_time = 2000;int lan9118_send(U32 * p_src, int length){ int i; union_tx_command_a tx_command_a; union_tx_command_b tx_command_b; union_tx_status tx_status; U32 temp_u32; tx_status.data = lan9118_reg_read(LAN9118_REG_OFFSET_TX_STATUS); if (dt) { if (tx_status.bits.error_status) { printf("tx error: \n"); if (tx_status.bits.loss_of_carrier) { printf("\tloss of carrier!!!\n"); } if (tx_status.bits.no_carrier) { printf("\tno carrier!!!\n"); } if (tx_status.bits.late_collision) { printf("\tlate_collision!!!\n"); } if (tx_status.bits.excessive_collision) { printf("\texcessive collision!!!\n"); } if (tx_status.bits.excessive_deferral) { printf("\texcessive deferral!!!\n"); } if (tx_status.bits.underrun_error) { printf("\tunderrun error!!!\n"); } } } temp_u32 = lan9118_reg_read(LAN9118_REG_OFFSET_TX_FIFO_INF); i = transmit_busy_wait_time; while ((temp_u32 & 0x0000ffff) < (length + 16)) { if (i == 0) { printf("LAN9118 TX buffer: %d\n", temp_u32 & 0x0000ffff); printf("vxWorks want: %d", length + 16); return 0; } i--; temp_u32 = lan9118_reg_read(LAN9118_REG_OFFSET_TX_FIFO_INF); } tx_command_a.data = 0; tx_command_b.data = 0; if (length > END_BUFSIZ) { length = END_BUFSIZ; } tx_package_tag += 1; tx_command_a.bits.interrupt_on_completion = 0; tx_command_a.bits.buffer_size = length; tx_command_a.bits.first_segment = 1; tx_command_a.bits.last_segment = 1; tx_command_a.bits.data_start_offset = ((U32)p_src)&0x3; /* align, 0,1,2,3 */ tx_command_b.bits.package_tag = tx_package_tag; tx_command_b.bits.package_length = length; lan9118_reg_write(LAN9118_REG_OFFSET_TX_DATA, tx_command_a.data); lan9118_reg_write(LAN9118_REG_OFFSET_TX_DATA, tx_command_b.data); for(i = (length+3)/4; i > 0; i--) { lan9118_reg_write(LAN9118_REG_OFFSET_TX_DATA, *p_src); p_src++; } /* set the TX_ON of TX_CFG. */ lan9118_reg_write(LAN9118_REG_OFFSET_TX_CFG, 0x00000002); if (dt) { printf("tx %d.", length); } return length;}/* lan9118_receive - get any package from buffer. */int lan_recv_garbage = 4;int miss_rx_overflow_count = 0;int get_rx = 0;int lan9118_receive(END_DEVICE * pDrvCtrl){ U32 rx_fifo_inf = 0; U8 rxsused = 0; union_rx_status rx_status; int i, length, temp_int; U32 * p_u32; U16 * p_u16; U8 p_char[END_BUFSIZ]; STATUS temp_status; pDrvCtrl->do_rx = 0; while(1) { /* get receive fifo information. */ rx_fifo_inf = lan9118_reg_read(LAN9118_REG_OFFSET_RX_FIFO_INF); rxsused = (U8)((rx_fifo_inf>>16)&0x000000ff); if (rxsused) { /* there're any package in the buffer. */ rx_status.data = lan9118_reg_read(LAN9118_REG_OFFSET_RX_STATUS); length = (int)(rx_status.bits.package_length); if (length > END_BUFSIZ) { printf("Error, package large than 1520!!!\n Reset the net.\n"); lan9118Reset(pDrvCtrl); return -1; } /* receive data from lan9118 rx fifo. */ temp_int = end_rx_frame_put(length); if (temp_int == -1) { printf("Error, netLibBuf overflow!!!\n"); return -1; } else { pDrvCtrl->do_rx += 1; get_rx += 1; } /* display. */ if (drcc) { display_rx_frame = 1; } else { display_rx_frame = 0; } if (drc) { if ((p_u32[0] == 0x1b454000) && ((p_u32[1]&0xffff) == 0xdd2)) { display_rx_frame = 1; } else { display_rx_frame = 0; } } if (display_rx_frame) { p_u16 = (U16 *)p_u32; printf("\n"); for (i = 1; i <= length; i++) { printf("0x%02x ", p_char[i-1]); if (!(i%16)) printf("\n"); } printf("\n"); } if (dr) { printf("rx %d\n", length); } /* error info. */ if (rx_status.bits.filtering_fail) { printf("Error: net-rx filtering fail!!!\n"); } if (rx_status.bits.error_status) { if (rx_status.bits.runt_frame) { printf("Error: net-rx runt frame!!!\n"); } if (rx_status.bits.frame_too_long) { printf("Error: net-rx frame too long!!!\n"); } if (rx_status.bits.collision_seen) { printf("Error: net-rx collision seen!!!\n"); } if (rx_status.bits.crc_error) { printf("Error: net-rx crc error!!!\n"); } } if (rx_status.bits.broadcast_frame) { /* printf("Info: receive broadcast frame.\n"); */ } if (rx_status.bits.length_error) { printf("Error: net-rx length error!!!\n"); } if (rx_status.bits.multicast_frame) { /*printf("Info: receive multicast frame.\n"); */ } if (rx_status.bits.frame_type) { /* printf("Info: receive ethernet frame.\n"); */ } else { /* printf("Info: receive 802.3 frame.\n"); */ } if (rx_status.bits.receive_watchdog_time_out) { printf("Error: net-rx receive watchdog time out!!!\n"); } if (rx_status.bits.mii_error) { printf("Error: net-rx mii error!!!\n"); } if (rx_status.bits.dribbling_bit) { printf("Error: net-rx dribbling bit!!!\n"); } /* printf("Receive %d bytes.\n\n", rx_status.bits.package_length); */ } else { /* There's nothing in the buffer. */ break; } } if (pDrvCtrl->do_rx) { netJobAdd ((FUNCPTR)lan9118RecvInt, (int)pDrvCtrl, pDrvCtrl->do_rx, 0,0,0); } return length;}/* * lan9118Load - initialize the driver and device * * This routine initializes the driver and the device to the operational state. * All of the device specific parameters are passed in the initString. * * The string contains the target specific parameters like this: * * "register addr:int vector:int level:shmem addr:shmem size:shmem width" * * This routine can be called in two modes. If it is called with an empty but * allocated string, it places the name of this device into the <initString> * and returns 0. * * If the string is allocated and not empty, the routine attempts to load * the driver using the values specified in the string. * * RETURNS: An END object pointer, or NULL on error, or 0 and the name of the * device if the <initString> was empty. */END_OBJ * lan9118Load ( char* initString, /* String to be parsed by the driver. */ void* p_v ){ END_DEVICE * pDrvCtrl; if(initString == NULL) { return NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -