📄 mac.c
字号:
#include "types.h"#include "bios.h"#include "bioscall.h"#include "eth.h"#include "board.h"#include "mac.h"#include "utils.h"static struct frame_desc_struct rx_fd[RX_FRAME_SIZE];static struct frame_desc_struct tx_fd[TX_FRAME_SIZE];static struct frame_buf_struct rx_buf[RX_FRAME_SIZE];static struct frame_buf_struct tx_buf[TX_FRAME_SIZE];static unsigned long gtx_ptr;static unsigned long grx_ptr;static void s3c4510_eth_fd_init(void){ struct frame_desc_struct *fd_ptr; struct frame_desc_struct *fd_start_ptr; struct frame_desc_struct *fd_last_ptr = NULL; unsigned long fb_base; unsigned long i; // TxfdInitialize() in diag code // Get Frame descriptor's base address // +0x4000000 is for setting this area to non-cacheable area. outl((unsigned long)tx_fd | NOCACHE_BIT, BDMATXPTR); gtx_ptr = inl(BDMATXPTR); // Get Transmit buffer base address. fb_base = (unsigned long)tx_buf | NOCACHE_BIT; // Generate linked list. fd_start_ptr = fd_ptr = (struct frame_desc_struct *)gtx_ptr; fd_last_ptr = NULL; for(i = 0; i < TX_FRAME_SIZE; i++) { fd_ptr->frame_data_ptr = (unsigned long)(fb_base & CPU_owner); fd_ptr->reserved = 0; fd_ptr->status_and_frame_lenght = (unsigned long)0x0; if(fd_last_ptr != NULL) fd_last_ptr->next_frame_desc = (unsigned long)fd_ptr; fd_last_ptr = fd_ptr; fd_ptr++; fb_base += sizeof(struct frame_buf_struct); } //Make Frame descriptor to ring buffer type. fd_last_ptr->next_frame_desc = (unsigned long)fd_start_ptr; // RxFDInitialize() in diag code // Get Frame descriptor's base address outl((unsigned long)rx_fd | NOCACHE_BIT, BDMARXPTR); grx_ptr = inl(BDMARXPTR); // Get recieve buffer base address fb_base = (unsigned long)rx_buf | NOCACHE_BIT; // Generate linked list fd_start_ptr = fd_ptr = (struct frame_desc_struct *)grx_ptr; fd_last_ptr = NULL; for(i = 0; i < RX_FRAME_SIZE; i++) { fd_ptr->frame_data_ptr = (unsigned long)(fb_base | BDMA_owner); fd_ptr->reserved = 0; fd_ptr->status_and_frame_lenght = (unsigned long)0x0; if(fd_last_ptr != NULL ) fd_last_ptr->next_frame_desc = (unsigned long)fd_ptr; fd_last_ptr = fd_ptr; fd_ptr++; fb_base += sizeof(struct frame_buf_struct); } // Make Frame descriptor to ring buffer type. fd_last_ptr->next_frame_desc = (unsigned long)fd_start_ptr;}int s3c4510_eth_init(unsigned char *mac_addr){ int i; // reset BDMA and MAC outl(BRxRS, BDMARXCON); outl(BTxRS, BDMATXCON); outl(MaxRxFrameSize, BDMARXLSZ); outl(Reset, MACON); outl(gMACCON, MACON); s3c4510_eth_fd_init(); for(i = 0; i < 4; i++) CAM_Reg(0) = (CAM_Reg(0) << 8) | mac_addr[i]; for(i = 4; i < 6; i++) CAM_Reg(1) = (CAM_Reg(1) << 8) | mac_addr[i]; CAM_Reg(1) = (CAM_Reg(1) << 16); outl(0x0001, CAMEN); outl(gCAMCON, CAMCON); outl(gBDMATXCON, BDMATXCON); outl(gMACTXCON, MACTXCON); outl(gBDMARXCON, BDMARXCON); outl(gMACRXCON, MACRXCON); return 0;}int s3c4510_eth_send(unsigned char *data, int len){ struct frame_desc_struct *fd_ptr; volatile unsigned long *fb_ptr; unsigned char *fb_data; int i; // 1. Get Tx frame descriptor & data pointer fd_ptr = (struct frame_desc_struct *)gtx_ptr; fb_ptr = (unsigned long *)&fd_ptr->frame_data_ptr; fb_data = (unsigned char *)fd_ptr->frame_data_ptr; // 2. Check BDMA ownership if(*fb_ptr & BDMA_owner) return -1; // 3. Prepare Tx Frame data to Frame buffer memcpy(fb_data, data, len); if (len < 60) { for (i = len; i < 60; i++) fb_data[i] = 0x00; len = 60; } // 4. Set Tx Frame flag & Length Field fd_ptr->reserved = (Padding | CRCMode | FrameDataPtrInc | LittleEndian | WA00 | MACTxIntEn); fd_ptr->status_and_frame_lenght = (len & 0xFFFF); // 5. Change ownership to BDMA fd_ptr->frame_data_ptr |= BDMA_owner; // 6. Enable MAC and BDMA Tx control register outl(gBDMATXCON, BDMATXCON); outl(gMACTXCON, MACTXCON); // 7. Change the Tx frame descriptor for next use gtx_ptr = (unsigned long)(fd_ptr->next_frame_desc); return 0;}int s3c4510_eth_rcv(unsigned char *data, int *len){ struct frame_desc_struct *fd_ptr; unsigned long rx_status; unsigned long bdma_status; unsigned char *tmp; // 1. Get Rx Frame Descriptor fd_ptr = (struct frame_desc_struct *)grx_ptr; if (fd_ptr->frame_data_ptr & BDMA_owner) return -1; rx_status = (fd_ptr->status_and_frame_lenght >> 16) & 0xffff; // 2. Get current frame descriptor and status bdma_status = inl(BDMASTAT); // 3. Clear BDMA status register bit by write 1 outl(bdma_status | S_BRxRDF, BDMASTAT); // 4. If Rx frame is good, then process received frame *len = 0; if (rx_status & Good) { *len = (fd_ptr->status_and_frame_lenght & 0xffff) - 4; tmp = (unsigned char *)fd_ptr->frame_data_ptr + 2; // 6. Get received frame to memory buffer memcpy(data, tmp, *len); } // 5. Change ownership to BDMA for next use fd_ptr->frame_data_ptr |= BDMA_owner; // Save Current Status and Frame Length field, and clear fd_ptr->status_and_frame_lenght = 0x0; // 6. Get Next Frame Descriptor pointer to process grx_ptr = (unsigned long)(fd_ptr->next_frame_desc); // 7. Check Notowner status if (inl(BDMASTAT) & S_BRxNO) { outl(S_BRxNO, BDMASTAT); } if ((inl(MACRXSTAT) & 0x400) == 0x400) { outl(gBDMARXCON, BDMARXCON); outl(gMACRXCON, MACRXCON); } return 0;}int s3c4510_eth_exit(void){ outl(0, BDMATXCON); outl(0, BDMARXCON); outl(0, BDMATXPTR); outl(0, BDMARXPTR); outl(0, BDMASTAT); outl(0, MACON); outl(0, CAMCON); outl(0, MACTXCON); outl(0, MACTXSTAT); outl(0, MACRXCON); outl(0, MACRXSTAT); outl(0, STADATA); outl(0x00006000, STACON); outl(0, CAMEN); outl(0, EMISSCNT); outl(0, EPZCNT); outl(0, ERMPZCNT);// outl(0, ETXSTAT); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -