📄 ins_eth_ocm.old
字号:
#include "ins_eth_ocm.h"
/**
* Function for obtaining MAC address.
* @param name Name of this MAC
* @param net NET interface (Interniche typedef)
* @param mac_addr Character array into which MAC address should be written.
*
* @return zero on success, nonzero otherwise.
*/
extern int get_mac_addr(char name[], NET net, unsigned char mac_addr[6]);
/**
* Determine whether PHY is full duplex or not.
* This is fully vendor specific depending on the PHY you are using.
* For this reason, this function is declared as external (so you can
* write your own).
*
* @param pmac MAC register map.
* @return 0x11 if Gigabit link is established and full duplex,
* 0x01 if not Gigabit link is established and full duplex,
* 0x00 if not Gigabit link is established and half duplex, * If the link speed cannot be determined, it is fall back to 10/100.
*/
extern int getPHYSpeed(eth_ocm_dev *dev);
static void eth_ocm_rx_isr(void *context, alt_u32 id);
static int eth_ocm_read_init(eth_ocm_dev *dev);
static int eth_ocm_rcv(eth_ocm_dev *dev);
/**
* Prepare ethernet MAC.
*
* @param ins_dev Pointer to associated alt_iniche_dev struct
* @return
*/
error_t eth_ocm_prep(alt_iniche_dev *ins_dev){
NET ifp;
int index;
eth_ocm_dev *dev;
index = ins_dev->if_num;
dev = (eth_ocm_dev *)ins_dev;
//Status message
dprintf("eth_ocm_prep\n");
//create eth_ocm_info struct
dev->info = (eth_ocm_info *)malloc(sizeof(eth_ocm_info));
dev->info->sem = 0; //initialize semaphore
ifp = nets[index];
ifp->n_mib->ifAdminStatus = ETH_OCM_STATUS_DOWN;
ifp->n_mib->ifOperStatus = ETH_OCM_STATUS_DOWN;
ifp->n_mib->ifLastChange = cticks * (100/TPS); //timestamp
ifp->n_mib->ifPhysAddress = (u_char*)dev->info->mac_addr;
ifp->n_mib->ifDescr = (u_char*)"Opencores 10/100 ethernet MAC";
ifp->n_lnh = ETHHDR_SIZE; /* ethernet header size. */
ifp->n_hal = ETH_OCM_MAC_ADDR_LEN; /* MAC address length */
ifp->n_mib->ifType = ETHERNET; /* device type */
ifp->n_mtu = ETH_OCM_MAX_MTU; /* max frame size */
/* install our hardware driver routines */
ifp->n_init = eth_ocm_init;
ifp->pkt_send = NULL;
ifp->raw_send = eth_ocm_raw_send;
ifp->n_close = eth_ocm_close;
ifp->n_stats = eth_ocm_stats;
#ifdef IP_V6
ifp->n_flags |= (NF_NBPROT | NF_IPV6);
#else
ifp->n_flags |= NF_NBPROT;
#endif
/* get the MAC address. */
get_mac_addr(dev->name, ifp, dev->info->mac_addr);
/* set cross-pointers between iface and eth_ocm structs */
dev->info->netp = ifp;
ifp->n_local = (void*)(dev);
index++;
return index;
}
//End of function eth_ocm_prep
/**
* Initializes the Opencores ethernet MAC. Called by InterNiche stack
*
* @param
*/
int eth_ocm_init(int iface){
int status = SUCCESS;
int duplex;
int temp;
NET ifp;
eth_ocm_dev *dev;
eth_ocm_info *info;
dprintf("[eth_ocm_init]\n");
//get the ifp first
ifp = nets[iface];
//now get the info pointer
dev = (eth_ocm_dev *)ifp->n_local;
info = dev->info;
// reset the mac (this is self clearing)
IOWR_ETH_OCM_SW_RESET(dev->base);
//Reset Descriptors (supposedly this can be done while in reset)
for(temp=ETH_OCM_DESC_START;temp<ETH_OCM_DESC_END;temp++)
IOWR(dev->base, temp, 0);
//Let's disable the MAC until everything else is set up
IOWR_ETH_OCM_MODER(dev->base,0);
//Set number of TX descriptors (RX descriptors is 128 minus this number)
IOWR_ETH_OCM_TX_BD_NUM(dev->base, 64);
/* perform any necessary PHY setup */
//Let's set the MDIO interface up to run at 4MHz.
temp = (ALT_CPU_FREQ / 1000000);
temp += 2;
temp &= 0xFFFFFFFE; //only even numbers allowed)
IOWR_ETH_OCM_MIIMODER(dev->base, temp);
IOWR_ETH_OCM_MIICOMMAND(dev->base, 0);
//Find out if we should run in duplex or not
duplex = getPHYSpeed(dev);
if(duplex)
duplex = ETH_OCM_MODER_FULLD_MSK;
// Configure MAC options
// Interrupt sources
IOWR_ETH_OCM_INT_MASK(dev->base,
ETH_OCM_DEFAULT_INTERRUPT_MASK);//Interrupt on receive
// Clear any existing interrupts
IOWR_ETH_OCM_INT_SOURCE(dev->base, 0xFFFFFFFF);
// Inter-packet gap
if(duplex)
IOWR_ETH_OCM_IPGT(dev->base, ETH_OCM_FULL_DUPLEX_IPGT);
else
IOWR_ETH_OCM_IPGT(dev->base, ETH_OCM_HALF_DUPLEX_IPGT);
//Let's set the defaults just because they've bitten us before
IOWR_ETH_OCM_IPGR1(dev->base, 0x0000000C);
IOWR_ETH_OCM_IPGR2(dev->base, 0x00000012);
IOWR_ETH_OCM_PACKETLEN(dev->base, 0x00400600); //Min and Max frame sizes
IOWR_ETH_OCM_COLLCONF(dev->base, 0x000F003F);
IOWR_ETH_OCM_CTRLMODER(dev->base, 0x00000000);
dprintf("[eth_ocm_init] Configuring MAC address "
"%02x:%02x:%02x:%02x:%02x:%02x\n",
info->mac_addr[0],info->mac_addr[1],info->mac_addr[2],
info->mac_addr[3],info->mac_addr[4],info->mac_addr[5]);
//Configure the MAC address
IOWR_ETH_OCM_MAC_ADDR0(dev->base,
( ((int)info->mac_addr[5]) |
(((int)info->mac_addr[4]) << 8) |
(((int)info->mac_addr[3]) << 16) |
(((int)info->mac_addr[2]) << 24) )
);
IOWR_ETH_OCM_MAC_ADDR1(dev->base,
( ((int)((unsigned char)info->mac_addr[1])) |
(((int)((unsigned char)info->mac_addr[0])) << 8) )
);
//Enable MAC
IOWR_ETH_OCM_MODER(dev->base,
ETH_OCM_MODER_PAD_MSK | //Enable padding of small packets
ETH_OCM_MODER_CRCEN_MSK | //Append CRC to TX packets
ETH_OCM_MODER_RXEN_MSK | //Enable receive
ETH_OCM_MODER_TXEN_MSK | //Enable transmit
duplex //Discovered duplex
);
dprintf("\nOpencores MAC post-init: MODER = 0x%08x\n",
IORD_ETH_OCM_MODER(dev->base));
/* status = UP */
nets[iface]->n_mib->ifAdminStatus = ETH_OCM_STATUS_UP;
nets[iface]->n_mib->ifOperStatus = ETH_OCM_STATUS_UP;
//register ISR interrupt handler
temp = alt_irq_register(dev->irq, dev, eth_ocm_rx_isr);
if(temp)
dprintf("[eth_ocm_init] Failed to register RX ISR\n");
//Setup the first read transfer
eth_ocm_read_init(dev);
return status; //MAC is ready to rock and roll
}
//End of eth_ocm_init function
/**
* Raw send function to initiate a transfer to the mac
*
* @param net - NET structure associated with the Opencores MAC instance
* @param data - pointer to the data payload
G
* @return SUCCESS if success, else a negative value
*/
int eth_ocm_raw_send(NET net, char * data, unsigned data_bytes){
int result;
int i;
unsigned len;
eth_ocm_dev *dev;
eth_ocm_info *info;
alt_u8 *buf;
OS_ENTER_CRITICAL(); //disable interrupts
dev = (eth_ocm_dev *)net->n_local;
info = dev->info;
len = data_bytes;
result = 0;
//Check to see if someone is nesting send calls (BAD!)
if(info->sem){
dprintf("Nested eth_ocm_raw_send\n");
OS_EXIT_CRITICAL();
return ENP_RESOURCE;
}
//Grab the semaphore
info->sem = 1;
// clear bit-31 before passing it to SGDMA Driver
buf = (alt_u8 *)alt_remap_cached( (volatile void *)data, 4);
//advance the pointer beyond the header bias
buf = (alt_u8 *)((unsigned int)buf + ETHHDR_BIAS);
//Some error checks first
if(len < ETH_OCM_MIN_MTU)
result = -1; //packet too small
if(len > ETH_OCM_MAX_MTU)
result = -EFBIG; //packet too big
if((IORD_ETH_OCM_DESC_CTRL(dev->base, ETH_OCM_FIRST_TX_DESC) & ETH_OCM_TXDESC_READY_MSK))
result = -EBUSY; //DMA not available
if(!result){
//Write pointer to descriptor
IOWR_ETH_OCM_DESC_PTR(dev->base, ETH_OCM_FIRST_TX_DESC, (unsigned int)buf);
//Write length and setup transfer
IOWR_ETH_OCM_DESC_CTRL(dev->base, ETH_OCM_FIRST_TX_DESC,
((len << ETH_OCM_TXDESC_LEN_OFST) |
ETH_OCM_TXDESC_READY_MSK |
ETH_OCM_TXDESC_WRAP_MSK |
ETH_OCM_TXDESC_PAD_MSK |
ETH_OCM_TXDESC_CRC_MSK)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -