if_mcf5272.c
来自「开放源码实时操作系统源码.」· C语言 代码 · 共 1,887 行 · 第 1/5 页
C
1,887 行
put_reg(MCF5272_SIM->enet.rdar, MCF5272_FEC_RDAR_DESTACT);
/* Set the flag to indicate that the device is up and running. */
PMCF5272_FEC_DATA(sc)->operational = ETH_DEV_UP;
}
/* A routine to halt the FEC. */
static void
MCF5272_fec_stop(struct eth_drv_sc *sc)
{
/* Stop the packet transmission gracefully. */
/* Set the Graceful Transmit Stop bit. */
put_reg(MCF5272_SIM->enet.tcr, get_reg(MCF5272_SIM->enet.tcr)
| MCF5272_FEC_TCR_GTS);
/* Wait for the current transmission to complete. */
while( !(get_reg(MCF5272_SIM->enet.eir) & MCF5272_FEC_EIR_GRA));
/* Clear the GRA event. */
put_reg(MCF5272_SIM->enet.eir, MCF5272_FEC_EIR_GRA);
/* Disable all FEC interrupts by clearing the IMR register. */
put_reg(MCF5272_SIM->enet.eimr, 0);
/* Clear the GTS bit so frames can be tranmitted when restarted */
put_reg(MCF5272_SIM->enet.tcr, get_reg(MCF5272_SIM->enet.tcr) &
~MCF5272_FEC_TCR_GTS);
/* Set the Ethernet control register to zero to disable the FEC. */
put_reg(MCF5272_SIM->enet.ecr, 0);
/* Deliver any pending frames and acknowledge any transmitted frames. */
MCF5272_fec_deliver(sc);
/* Set the flag to indicate that the device is down. */
PMCF5272_FEC_DATA(sc)->operational = ETH_DEV_DOWN;
}
/* This routine is called to perform special "control" opertions. */
static int
MCF5272_fec_control(struct eth_drv_sc *sc, unsigned long key,
void *data, int data_length)
{
switch (key)
{
case ETH_DRV_SET_MAC_ADDRESS:
{
/* Set the hardware address of the Ethernet controller. */
struct ifreq* p_ifreq = data;
/* If the length of the strcutre is not equal to the size of */
/* ifreq, then exit with an error. */
if (data_length != sizeof(*p_ifreq))
{
return 0;
}
/* Set the lower 4-byte address. */
put_reg(MCF5272_SIM->enet.malr,0
| (p_ifreq->ifr_ifru.ifru_hwaddr.sa_data[0] <<24)
| (p_ifreq->ifr_ifru.ifru_hwaddr.sa_data[1] <<16)
| (p_ifreq->ifr_ifru.ifru_hwaddr.sa_data[2] <<8)
| (p_ifreq->ifr_ifru.ifru_hwaddr.sa_data[3] <<0));
/* Set the upper 2-byte address. */
put_reg(MCF5272_SIM->enet.maur,
0
| (p_ifreq->ifr_ifru.ifru_hwaddr.sa_data[4] <<24)
| (p_ifreq->ifr_ifru.ifru_hwaddr.sa_data[5] <<16));
/* Return 1 to indicate that programming of the new MAC */
/* address is successful. */
return 1;
}
break;
#ifdef CYGPKG_NET
case ETH_DRV_GET_IF_STATS:
case ETH_DRV_GET_IF_STATS_UD:
#if 0
{
struct ether_drv_stats* pstats = (struct ether_drv_stats*)
data;
MCF5272_FEC_DIAG diag;
/* Retrieve the driver defined diagnostic structure. */
MCF5272_get_stats(sc, &diag);
strcpy(pstats->description, ether_device_name);
pstats->duplex = ETH_MODE_UNKNWON;
pstats->operational = (unsigned char )PMCF5272_FEC_DATA(sc)->operational;
pstats->speed = 0;
/* Translate the device specific diagnostic values to the */
/* generic ether_drv_stats values. */
/* Get the receive bytes count. */
pstats->rx_count = diag.rx_bytes_cnt;
/* Get the number of successful packet received. */
pstats->rx_good = diag.rx_pk_cnt;
/* Get the receive CRC error count. */
pstats->rx_crc_errors = diag.rx_crc_err_cnt;
/* Get the receive overrun error count. */
pstats->rx_overrun_errors = diag.rx_overrun_err_cnt;
/* Get the received short frame error count. */
pstats->rx_short_frames = diag.rx_short_frm_err_cnt;
/* Get the received long frame error count. */
pstats->rx_too_long_frames = diag.rx_long_frm_err_cnt;
/* Get the number of transmitted bytes. */
pstats->tx_count = diag.tx_bytes_cnt;
/* Get the number of defered packets. */
pstats->tx_deferred = diag.tx_def_cnt;
/* The number of successfully transmitted packets. */
pstats->tx_good = diag.tx_pk_cnt;
/* Get the transmit late collision count. */
pstats->tx_late_collisions = diag.tx_late_col_cnt;
/* Get the transmit underrun count. */
pstats->tx_underrun = diag.tx_underrun_cnt;
/* Get the transmit late collision count. */
pstats->tx_total_collisions = diag.tx_late_col_cnt;
return 1;
}
#else
{
/* Copy the ethernet name device over. */
strcpy(((struct mcf5272_ether_drv_stats*)data)->description,
ether_device_name);
/* Get the stats. */
MCF5272_get_stats(sc,
&((struct mcf5272_ether_drv_stats*)data)->stats);
/* Copy the mode over. */
((struct mcf5272_ether_drv_stats*)data)->duplex =
PMCF5272_FEC_DATA(sc)->duplex;
/* The ethernet driver is operational. */
((struct mcf5272_ether_drv_stats*)data)->operational =
PMCF5272_FEC_DATA(sc)->operational;
/* Copy the speed over. */
((struct mcf5272_ether_drv_stats*)data)->speed =
PMCF5272_FEC_DATA(sc)->speed;
return 1;
}
#endif
break;
#endif /* CYGPKG_NET */
default:
return 1;
break;
}
}
/* This routine is called to see if it is possible to send another */
/* packet. It will return non-zero if a transmit is possible, zero */
/* otherwise. */
static int
MCF5272_fec_can_send(struct eth_drv_sc *sc)
{
const int buffer_window = 5; /* Specifies the minimum empty buffer descrpitors */
if ((NUM_TXBDS - PBUF_INFO(sc)->num_busy_bd) > buffer_window)
{
return 1;
}
else
{
PMCF5272_FEC_DATA(sc)->diag_counters.tx_full_cnt++;
return 0;
}
}
/* This routine is called by eCos to send a frame to the ethernet */
/* controller. */
static void
MCF5272_fec_send(struct eth_drv_sc *sc,
struct eth_drv_sg *sg_list,
int sg_len,
int total_len,
unsigned long key)
{
/* Call eth_tx_check() routine for any packet transmitted by eCos. */
eth_tx_check(sg_list, sg_len);
/* If we do have enough buffer to send we call */
/* MCF5272_fec_common_send routine to send the packet. Otherwise, we */
/* throw away the packet and call eCos's tx_done rutine to notify that */
/* the packet has been sent. */
if (NUM_TXBDS - PBUF_INFO(sc)->num_busy_bd > sg_len)
{
MCF5272_fec_common_send(sc, sg_list, sg_len, total_len, key, TX_KEY_ECOS);
}
else
{
CYG_ASSERT(false, "ETH: Send buffer full");
/* Inform the upper layer of a completion of the packet. */
(sc->funs->eth_drv->tx_done)(sc,
key,
0);
}
}
/* This routine is called to send a frame to the ethernet controller. */
/* This is a generic send routine. */
/*
INPUT:
sc - Ethernet driver sc.
sg_glist - scatter gather list.
sg_len - The number of scattter gather entries in the list.
total_len - The total length of the frame.
*/
static void
MCF5272_fec_common_send(struct eth_drv_sc *sc,
struct eth_drv_sg *sg_list,
int sg_len,
int total_len,
unsigned long key,
tx_key_type_t key_type)
{
int i = 0;
NBUF *pBD = NULL;
NBUF *first_bd;
buf_info_t* p_buf = PBUF_INFO(sc);
CYG_ASSERT(sg_len > 0, "ETH: sg_len cannot be zero");
/* Update the number of used transmitted buffer desciptors. */
p_buf->num_busy_bd += sg_len;
/* Keep track of the maximum number of busy transmit buffer */
/* descriptors. */
if (p_buf->num_busy_bd > p_buf->max_num_busy_bd)
{
p_buf->max_num_busy_bd = p_buf->num_busy_bd;
}
/* Enqueue the key, the index to first and last buffer desriptor, the */
/* number of buffer descriptors, the packet length and the type of */
/* packet to the transmit queue. */
nbuf_enq_tx_key(p_buf, (p_buf->iTxbd + sg_len - 1) % NUM_TXBDS,
key,
p_buf->iTxbd,
sg_len,
total_len,
key_type);
/* Get the pointer to the first buffer descriptor of the packet. We */
/* don't set the R bit for the first packet until we have allocated and */
/* initialized all the buffer descriptors. */
first_bd = pBD = nbuf_tx_allocate(p_buf);
do
{
CYG_ASSERT(pBD != NULL, "ETH: nbuf_tx_allocate() returned NULL");
/* Copy the address of the buffer and the length to the allocated */
/* buffer descriptor. Note that buf_index indexes to the buffer */
/* descriptor it returns. */
pBD->data = (uint8*)sg_list[i].buf;
pBD->length = sg_list[i].len;
if (i == sg_len - 1)
{
/* Set the the L, TC and R bit to indicate that the buffer */
/* descriptor is the last buffer descriptor, the CRC is */
/* appended by the FEC and the buffer descriptor is ready for */
/* transmission. */
pBD->status |= TX_BD_L | TX_BD_TC | TX_BD_R;
/* When we have reached the last buffer scatther list, we */
/* break from the loop. */
break;
}
else
{
if (i)
{
/* If the buffer descriptor is not the first buffer */
/* descriptor, then set the R bit to notify the FEC that */
/* the buffer descriptor is read for transmission. FEC */
/* must reset R bit after transmitted for buffer. */
pBD->status |= TX_BD_R;
}
/* Allocate the next buffer descriptor. */
pBD = nbuf_tx_allocate(p_buf);
}
/* Advance to the next index. */
i++;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?