3 #include "ins_eth_ocm.h"
6 * Function for obtaining MAC address. Located externally in application code.
8 * @param net NET interface (Interniche typedef)
9 * @param mac_addr Character array into which MAC address should be written.
11 * @return zero on success, nonzero otherwise.
13 extern int get_mac_addr(NET net
, unsigned char mac_addr
[6]);
16 * Performs PHY initialization and determines link duplex.
17 * This is fully vendor specific depending on the PHY you are using.
19 * @param dev Pointer to eth_ocm_dev struct which contains needed base address
20 * @return 1 if Link is established in Full duplex.
21 * 0 if Link is established in Half duplex.
23 extern int eth_ocm_phy_init(eth_ocm_dev
*dev
);
25 static void eth_ocm_isr(void *context
, alt_u32 id
);
26 static int eth_ocm_read_init(eth_ocm_dev
*dev
);
27 #ifndef ETH_OCM_SYNC_TX
28 static int eth_ocm_pkt_send(PACKET pkt
);
29 static int eth_ocm_low_send(NET net
, char *data
, unsigned data_bytes
);
30 static void eth_ocm_tx_isr(eth_ocm_dev
*dev
);
32 static int eth_ocm_raw_send(NET net
, char *data
, unsigned data_bytes
);
33 #endif // else ifndef ETH_OCM_SYNC_TX
34 static int eth_ocm_rx_isr(eth_ocm_dev
*dev
);
37 * Prepare ethernet MAC.
39 * @param ins_dev Pointer to associated alt_iniche_dev struct
42 error_t
eth_ocm_prep(alt_iniche_dev
*ins_dev
){
47 index
= ins_dev
->if_num
;
48 dev
= (eth_ocm_dev
*)ins_dev
;
50 #if (ETH_OCM_DBG_LVL >= 1)
52 dprintf("eth_ocm_prep\n");
53 #endif // if ETH_OCM_DBG_LVL
55 //create eth_ocm_info struct
56 dev
->info
= (eth_ocm_info
*)malloc(sizeof(eth_ocm_info
));
57 dev
->info
->sem
= 0; //initialize semaphore
58 dev
->info
->rx_pkts
= (PACKET
*)(malloc(sizeof(PACKET
) * ETH_OCM_RX_DESC_COUNT
));
62 ifp
->n_mib
->ifAdminStatus
= ETH_OCM_STATUS_DOWN
;
63 ifp
->n_mib
->ifOperStatus
= ETH_OCM_STATUS_DOWN
;
64 ifp
->n_mib
->ifLastChange
= cticks
* (100/TPS
); //timestamp
65 ifp
->n_mib
->ifPhysAddress
= (u_char
*)dev
->info
->mac_addr
;
66 ifp
->n_mib
->ifDescr
= (u_char
*)"Opencores 10/100 ethernet MAC";
67 ifp
->n_lnh
= ETHHDR_SIZE
; /* ethernet header size. */
68 ifp
->n_hal
= ETH_OCM_MAC_ADDR_LEN
; /* MAC address length */
69 ifp
->n_mib
->ifType
= ETHERNET
; /* device type */
70 ifp
->n_mtu
= ETH_OCM_MAX_MTU
; /* max frame size */
72 /* install our hardware driver routines */
73 ifp
->n_init
= eth_ocm_init
;
74 #ifndef ETH_OCM_SYNC_TX
75 ifp
->pkt_send
= eth_ocm_pkt_send
;
79 ifp
->raw_send
= eth_ocm_raw_send
;
80 #endif // ifndef ETH_OCM_SYNC_TX
81 ifp
->n_close
= eth_ocm_close
;
82 ifp
->n_stats
= eth_ocm_stats
;
85 ifp
->n_flags
|= (NF_NBPROT
| NF_IPV6
);
87 ifp
->n_flags
|= NF_NBPROT
;
90 /* set cross-pointers between iface and eth_ocm structs */
91 dev
->info
->netp
= ifp
;
92 ifp
->n_local
= (void*)(dev
);
94 /* get the MAC address. */
95 get_mac_addr(ifp
, dev
->info
->mac_addr
);
100 //End of function eth_ocm_prep
103 * Initializes the Opencores ethernet MAC. Called by InterNiche stack
107 int eth_ocm_init(int iface
){
108 int status
= SUCCESS
;
116 #if (ETH_OCM_DBG_LVL >= 1)
117 dprintf("[eth_ocm_init]\n");
121 //now get the info pointer
122 dev
= (eth_ocm_dev
*)ifp
->n_local
;
126 //Reset Descriptors (supposedly this can be done while in reset)
127 for(temp
=ETH_OCM_DESC_START
;temp
<ETH_OCM_DESC_END
;temp
++)
128 IOWR(dev
->base
, temp
, 0);
130 //Let's disable the MAC until everything else is set up
133 //Determine the number of RX descriptors
134 regs
->tx_bd_num
= ETH_OCM_TX_DESC_COUNT
; //Set TX descriptor count in MAC
135 info
->cur_tx_desc
= 0;
136 info
->cur_rx_desc
= 0;
137 #ifndef ETH_OCM_SYNC_TX
138 info
->next_tx_desc
= 0;
139 info
->next_tx_desc_rdy
= 1;
141 dev
->info
->tosend
.q_head
= dev
->info
->tosend
.q_tail
= NULL
;
142 dev
->info
->tosend
.q_max
= dev
->info
->tosend
.q_min
= dev
->info
->tosend
.q_len
= 0;
143 dev
->info
->sending
.q_head
= dev
->info
->sending
.q_tail
= NULL
;
144 dev
->info
->sending
.q_max
= dev
->info
->sending
.q_min
= dev
->info
->sending
.q_len
= 0;
147 /* perform any necessary PHY setup */
148 //Let's set the MDIO interface up to run at 4MHz.
149 temp
= (ALT_CPU_FREQ
/ 1000000);
151 temp
&= 0xFFFFFFFE; //only even numbers allowed)
152 regs
->miimoder
= temp
;
153 regs
->miicommand
= 0;
154 //Find out if we should run in duplex or not
155 duplex
= eth_ocm_phy_init(dev
);
158 duplex
= ETH_OCM_MODER_FULLD_MSK
;
160 // Configure MAC options
162 regs
->int_mask
= ETH_OCM_DEFAULT_INTERRUPT_MASK
; //Interrupt on receive
163 // Clear any existing interrupts
164 regs
->int_source
= 0xFFFFFFFF;
168 regs
->ipgt
= ETH_OCM_FULL_DUPLEX_IPGT
;
170 regs
->ipgt
= ETH_OCM_HALF_DUPLEX_IPGT
;
172 //Let's set the defaults just because they've bitten us before
173 regs
->ipgr2
= 0x0000000C;
174 regs
->ipgr2
= 0x00000012;
175 regs
->packetlen
= 0x00400600; //Min and Max frame sizes
176 regs
->collconf
= 0x000F003F;
177 regs
->ctrlmoder
= 0x00000000;
179 #if (ETH_OCM_DBG_LVL >= 1)
180 dprintf("[eth_ocm_init] Configuring MAC address "
181 "%02x:%02x:%02x:%02x:%02x:%02x\n",
182 info
->mac_addr
[0],info
->mac_addr
[1],info
->mac_addr
[2],
183 info
->mac_addr
[3],info
->mac_addr
[4],info
->mac_addr
[5]);
184 #endif // if ETH_OCM_DBG_LVL
185 //Configure the MAC address
187 ( ((int)info
->mac_addr
[5]) |
188 (((int)info
->mac_addr
[4]) << 8) |
189 (((int)info
->mac_addr
[3]) << 16) |
190 (((int)info
->mac_addr
[2]) << 24) );
193 ( ((int)((unsigned char)info
->mac_addr
[1])) |
194 (((int)((unsigned char)info
->mac_addr
[0])) << 8) );
199 ETH_OCM_MODER_PAD_MSK
| //Enable padding of small packets
200 ETH_OCM_MODER_CRCEN_MSK
| //Append CRC to TX packets
201 ETH_OCM_MODER_RXEN_MSK
| //Enable receive
202 ETH_OCM_MODER_TXEN_MSK
| //Enable transmit
203 duplex
//Discovered duplex
206 #if (ETH_OCM_DBG_LVL >= 1)
207 dprintf("\nOpencores MAC post-init: MODER = 0x%08x\n", (int)regs
->moder
);
208 #endif // if ETH_OCM_DBG
211 nets
[iface
]->n_mib
->ifAdminStatus
= ETH_OCM_STATUS_UP
;
212 nets
[iface
]->n_mib
->ifOperStatus
= ETH_OCM_STATUS_UP
;
214 //register ISR interrupt handler
215 temp
= alt_irq_register(dev
->irq
, dev
, eth_ocm_isr
);
217 dprintf("[eth_ocm_init] Failed to register RX ISR\n");
218 //Setup the first read transfer
219 eth_ocm_read_init(dev
);
221 return status
; //MAC is ready to rock and roll
223 //End of eth_ocm_init function
226 #ifndef ETH_OCM_SYNC_TX
227 int eth_ocm_pkt_send(PACKET pkt
){
236 dev
= (eth_ocm_dev
*)pkt
->net
->n_local
;
241 OS_ENTER_CRITICAL(); //disable interrupts
243 putq(&info
->tosend
, (qp
)pkt
);
246 //If there is an available descriptor, and it's not busy
247 if(info->next_tx_desc_rdy && (info->sending.q_len < ETH_OCM_TX_DESC_COUNT)){//!(regs->txdescs[info->next_tx_desc].ctrl & ETH_OCM_TXDESC_READY_MSK)){
248 result = eth_ocm_low_send(pkt->net, pkt->nb_prot, pkt->nb_plen);
249 //If setup failed, free the packet and move on.
250 if(result != SUCCESS){
251 pkt->net->n_mib->ifOutDiscards++; //increment TX discard counter
255 else{ //Transfer was successfully setup
256 info->next_tx_desc++;
257 if(info->next_tx_desc == ETH_OCM_TX_DESC_COUNT)
258 info->next_tx_desc = 0;
259 //See if all descriptor are in use
260 if(info->next_tx_desc == info->cur_tx_desc)
261 info->next_tx_desc_rdy = 0;
262 //Put the packet in the sending queue
263 putq(&info->sending, (qp)pkt);
266 else{ //Unable to send packet right now so queue it
267 putq(&info->tosend, (qp)pkt);
271 OS_EXIT_CRITICAL(); //reenable interrupts
275 /** This is the asynchronous raw send function. It sets up a transfer
276 * but does not wait for it to conclude. It sets the MAC to interrupt
277 * when the transfer has finished. This is not threadsafe.
283 * @return 0 if Successful, negative otherwise
285 int eth_ocm_low_send(NET net
, char *data
, unsigned data_bytes
){
293 dev
= (eth_ocm_dev
*)net
->n_local
;
296 len
= data_bytes
- ETHHDR_BIAS
;
299 //Check to see if someone is nesting send calls (BAD!)
301 dprintf("[eth_ocm_low_send] ERROR: Nested low send call\n");
306 // clear bit-31 before passing it to SGDMA Driver
307 buf
= (alt_u8
*)alt_remap_cached( (volatile void *)data
, 4);
308 //advance the pointer beyond the header bias
309 buf
= (alt_u8
*)((unsigned int)buf
+ ETHHDR_BIAS
);
311 //Some error checks first
312 if(len
< ETH_OCM_MIN_MTU
)
313 result
= -1; //packet too small
314 if(len
> ETH_OCM_MAX_MTU
)
315 result
= -EFBIG
; //packet too big
316 if(regs
->txdescs
[info
->next_tx_desc
].ctrl
& ETH_OCM_TXDESC_READY_MSK
)
317 result
= -EBUSY
; //DMA not available
319 if(result
== SUCCESS
){
320 //Write pointer to descriptor
321 regs
->txdescs
[info
->next_tx_desc
].ptr
= (unsigned int)buf
;
322 //Write length and setup transfer
323 result
= ((len
<< ETH_OCM_TXDESC_LEN_OFST
) |
324 ETH_OCM_TXDESC_READY_MSK
|
325 ETH_OCM_TXDESC_IRQ_MSK
|
326 ETH_OCM_TXDESC_PAD_MSK
|
327 ETH_OCM_TXDESC_CRC_MSK
);
328 //See if wrap flag should be set
329 if(info
->next_tx_desc
== (ETH_OCM_TX_DESC_COUNT
- 1))
330 result
|= ETH_OCM_TXDESC_WRAP_MSK
;
332 regs
->txdescs
[info
->next_tx_desc
].ctrl
= result
;
340 void eth_ocm_tx_isr(eth_ocm_dev
*dev
){
349 //First we need to process all finished descriptors
350 while( info
->sending
.q_len
>0
351 && ((info
->cur_tx_desc
!= info
->next_tx_desc
) || !info
->next_tx_desc_rdy
)
352 && !(regs
->txdescs
[info
->cur_tx_desc
].ctrl
& ETH_OCM_TXDESC_READY_MSK
)){
355 pkt
= (PACKET
)getq(&info
->sending
);
357 //Get transmit result from descriptor
358 result
= regs
->txdescs
[info
->cur_tx_desc
].ctrl
;
362 (ETH_OCM_TXDESC_UR_MSK
|
363 ETH_OCM_TXDESC_RL_MSK
|
364 ETH_OCM_TXDESC_LC_MSK
|
365 ETH_OCM_TXDESC_CS_MSK
)){
366 #if (ETH_OCM_DBG_LVL >= 2)
367 dprintf("[eth_ocm_tx_isr] Transmit error 0x%x\n", result
);
368 #endif // if ETH_OCM_DBG_LVL
369 pkt
->net
->n_mib
->ifOutDiscards
++; //increment TX discard counter
372 #if (ETH_OCM_DBG_LVL >= 5)
373 if(result
& ETH_OCM_TXDESC_RTRY_MSK
)
374 dprintf("[eth_ocm_tx_isr] Transmit retries: %d\n", (result
& ETH_OCM_TXDESC_RTRY_MSK
)>>ETH_OCM_TXDESC_RTRY_OFST
);
376 pkt
->net
->n_mib
->ifOutOctets
+= pkt
->nb_plen
;
377 pkt
->net
->n_mib
->ifOutUcastPkts
++;
384 //Increment the current descriptor pointer
386 if(info
->cur_tx_desc
== ETH_OCM_TX_DESC_COUNT
)
387 info
->cur_tx_desc
= 0;
388 //Whatever the next descriptor is it's ready now
389 info
->next_tx_desc_rdy
= 1;
392 //Now we can send any queued packets
393 while( info
->next_tx_desc_rdy
394 && info
->tosend
.q_len
>0
395 && !(regs
->txdescs
[info
->next_tx_desc
].ctrl
& ETH_OCM_TXDESC_READY_MSK
) ){
397 //Get the packet to be send
398 pkt
= (PACKET
)getq(&info
->tosend
);
400 result
= eth_ocm_low_send(pkt
->net
, pkt
->nb_prot
, pkt
->nb_plen
);
401 //If setup failed, free the packet and move on.
402 if(result
!= SUCCESS
){
403 pkt
->net
->n_mib
->ifOutDiscards
++;
406 else{ //Transfer was successfully setup
407 info
->next_tx_desc
++;
408 if(info
->next_tx_desc
== ETH_OCM_TX_DESC_COUNT
)
409 info
->next_tx_desc
= 0;
410 //See if all descriptor are in use
411 if(info
->next_tx_desc
== info
->cur_tx_desc
)
412 info
->next_tx_desc_rdy
= 0;
413 //Put the packet in the sending queue
414 putq(&info
->sending
, (qp
)pkt
);
419 #endif // ifndef ETH_OCM_SYNC_TX
422 #ifdef ETH_OCM_SYNC_TX
424 * Raw send function to initiate a transfer to the mac
426 * @param net - NET structure associated with the Opencores MAC instance
427 * @param data - pointer to the data payload
429 * @return SUCCESS if success, else a negative value
431 int eth_ocm_raw_send(NET net
, char * data
, unsigned data_bytes
){
443 OS_ENTER_CRITICAL(); //disable interrupts
445 dev
= (eth_ocm_dev
*)net
->n_local
;
448 len
= data_bytes
- ETHHDR_BIAS
;
451 //Check to see if someone is nesting send calls (BAD!)
453 dprintf("[eth_ocm_raw_send] ERROR: Nested raw send call\n");
460 // clear bit-31 before passing it to SGDMA Driver
461 buf
= (alt_u8
*)alt_remap_cached( (volatile void *)data
, 4);
462 //advance the pointer beyond the header bias
463 buf
= (alt_u8
*)((unsigned int)buf
+ ETHHDR_BIAS
);
465 //Some error checks first
466 if(len
< ETH_OCM_MIN_MTU
)
467 result
= -1; //packet too small
468 if(len
> ETH_OCM_MAX_MTU
)
469 result
= -EFBIG
; //packet too big
470 if(regs
->txdescs
[0].ctrl
& ETH_OCM_TXDESC_READY_MSK
)
471 result
= -EBUSY
; //DMA not available
474 //Write pointer to descriptor
475 regs
->txdescs
[0].ptr
= (unsigned int)buf
;
476 //Write length and setup transfer
477 regs
->txdescs
[0].ctrl
=
478 ((len
<< ETH_OCM_TXDESC_LEN_OFST
) |
479 ETH_OCM_TXDESC_READY_MSK
|
480 ETH_OCM_TXDESC_WRAP_MSK
|
481 ETH_OCM_TXDESC_PAD_MSK
|
482 ETH_OCM_TXDESC_CRC_MSK
);
483 //Wait for transfer to complete
486 result
= regs
->txdescs
[0].ctrl
;
488 }while((result
& ETH_OCM_TXDESC_READY_MSK
) && i
<ETH_OCM_TRANSMIT_TIMEOUT
);
489 //Make sure no timeout occurred
490 if(i
<ETH_OCM_TRANSMIT_TIMEOUT
){
492 (ETH_OCM_TXDESC_UR_MSK
|
493 ETH_OCM_TXDESC_RL_MSK
|
494 ETH_OCM_TXDESC_LC_MSK
|
495 ETH_OCM_TXDESC_CS_MSK
)){
496 #if (ETH_OCM_DBG_LVL >= 2)
497 dprintf("[eth_ocm_raw_send] Transmit error 0x%x\n", result
);
498 #endif // if ETH_OCM_DBG_LVL
499 result
= -EIO
; //Some error occured
502 #if (ETH_OCM_DBG_LVL >= 5)
503 if(result
& ETH_OCM_TXDESC_RTRY_MSK
)
504 dprintf("[eth_ocm_raw_send] Transmit retries: %d\n", (result
& ETH_OCM_TXDESC_RTRY_MSK
)>>ETH_OCM_TXDESC_RTRY_OFST
);
512 } //End of if(!result) Transmit branch
515 if(!result
){ //Successfull transfer
516 net
->n_mib
->ifOutOctets
+= data_bytes
; //Increment TX data counter
517 // we dont know whether it was unicast or not, we count both in <ifOutUcastPkts>
518 net
->n_mib
->ifOutUcastPkts
++;
521 else{ //Failed transfer
522 #if (ETH_OCM_DBG_LVL >= 2)
523 dprintf("[eth_ocm_raw_send] Transmit failed, "
527 #endif // if ETH_OCM_DBG_LVL
528 net
->n_mib
->ifOutDiscards
++; //increment TX discard counter
529 result
= SEND_DROPPED
; // ENP_RESOURCE and SEND_DROPPED have the same value!
532 info
->sem
= 0; //release semaphore
533 OS_EXIT_CRITICAL(); //reenable interrupts
534 return result
; //success
536 //End of function eth_ocm_raw_send
537 #endif // ifdef ETH_OCM_SYNC_TX
541 * Receive ISR (interrupt service routine)
543 * @param context - context of the Opencores MAC instance
544 * @param id - IRQ number
546 void eth_ocm_isr(void *context
, alt_u32 id
){
551 dev
= (eth_ocm_dev
*)context
;
554 //Read the interrupt source
555 result
= regs
->int_source
;
557 //Clear interrupt flags immediately. Only clear the ones that
558 //have been set. We do this in case another one has occured since
560 regs
->int_source
= result
; //clear interrupts
562 //Check for receive flags
563 if(result
& (ETH_OCM_INT_MASK_RXB_MSK
| ETH_OCM_INT_MASK_RXE_MSK
)){
564 //Call the receive function. This will set up a new transfer
566 //Check to see if there is something in the stack's received queue
567 if ((rcvdq
.q_len
) > 0){
572 //Check for busy flag
573 if(result
& ETH_OCM_INT_MASK_BUSY_MSK
){
574 #if (ETH_OCM_DBG_LVL >= 3)
575 dprintf("Frame dropped: too busy to receive\n");
577 dev
->info
->netp
->n_mib
->ifInDiscards
++;
580 #ifndef ETH_OCM_SYNC_TX
581 //Check for transmit flags
582 if(result
& (ETH_OCM_INT_MASK_TXE_MSK
| ETH_OCM_INT_MASK_TXB_MSK
)){
585 #endif //ifndef ETH_OCM_SYNC_TX
588 //See if any interrupts have been set
589 result
= regs
->int_source
;
595 * Set up the first receive transfer
597 static int eth_ocm_read_init(eth_ocm_dev
*dev
){
607 pkts
= info
->rx_pkts
;
610 //allocate a packet for every descriptor
611 for(i
=0;i
<ETH_OCM_RX_DESC_COUNT
;i
++){
612 pkts
[i
] = pk_alloc(ETH_OCM_BUF_ALLOC_SIZE
);
613 if (!pkts
[i
]){ // couldn't get a free buffer for rx
614 dprintf("[eth_ocm_read_init] Fatal error: Unable to allocte ETH_OCM_RX_DESC_COUNT buffers\n");
618 // ensure bit-31 of pkt_array[i]->nb_buff is clear before passing
619 buf_ptr
= (alt_u8
*)alt_remap_cached ((volatile void*) pkts
[i
]->nb_buff
, 4);
620 //shift the actual write location over by ETHHDR_BIAS (see ipport.h)
621 buf_ptr
= (alt_u8
*)(((unsigned int)buf_ptr
) + ETHHDR_BIAS
);
623 if(!(regs
->rxdescs
[i
].ctrl
& ETH_OCM_RXDESC_EMPTY_MSK
)){
625 regs
->rxdescs
[i
].ptr
= (alt_u32
)buf_ptr
;
626 //Write the control register to start the transfer
627 temp
= ETH_OCM_RXDESC_EMPTY_MSK
| ETH_OCM_RXDESC_IRQ_MSK
;
628 if(i
== (ETH_OCM_RX_DESC_COUNT
- 1))
629 temp
|= ETH_OCM_RXDESC_WRAP_MSK
;
630 regs
->rxdescs
[i
].ctrl
= temp
;
633 dprintf("[eth_ocm_read_init] Fatal error: RX descriptor unavailable.\n");
634 dprintf("[eth_ocm_read_init] Descriptor %u = 0x%08x\n", i
, (int)regs
->rxdescs
[i
].ctrl
);
641 //End of function eth_ocm_read_init
645 * Receive operation. Checks the status of the received frame.
646 * Attempt to obtain a new buffer from the InterNiche stack.
647 * Schedules another RX transfer
649 * @return SUCCESS on success
651 static int eth_ocm_rx_isr(eth_ocm_dev
*dev
)
665 pkts
= info
->rx_pkts
;
666 cur
= info
->cur_rx_desc
;
668 stat
= regs
->rxdescs
[cur
].ctrl
;
670 //We'll process as many descriptors as are ready
671 while(!(stat
& ETH_OCM_RXDESC_EMPTY_MSK
)){
672 pklen
= stat
& ETH_OCM_RXDESC_LEN_MSK
;
673 pklen
= pklen
>> ETH_OCM_RXDESC_LEN_OFST
;
675 //Increment received byte count
676 info
->netp
->n_mib
->ifInOctets
+= (u_long
)pklen
;
678 pkts
[cur
]->nb_prot
= pkts
[cur
]->nb_buff
+ ETHHDR_SIZE
;
679 pkts
[cur
]->nb_plen
= pklen
- (14 + 4); //Packet length minus (header + CRC)
680 pkts
[cur
]->nb_tstamp
= cticks
;
681 pkts
[cur
]->net
= info
->netp
;
683 // set packet type for demux routine
684 eth
= (struct ethhdr
*)(pkts
[cur
]->nb_buff
+ ETHHDR_BIAS
);
685 pkts
[cur
]->type
= eth
->e_type
;
687 if (!(stat
& ETH_OCM_RXDESC_ERROR_MSK
)){
688 pkt
= pk_alloc(ETH_OCM_BUF_ALLOC_SIZE
);
689 if (!pkt
){ // couldn't get a free buffer for rx
690 #if (ETH_OCM_DBG_LVL >= 4)
691 dprintf("[eth_ocm_rx_isr] No free RX buffers (Swamping the NicheStack)\n");
692 #endif // if ETH_OCM_DBG_LVL
693 info
->netp
->n_mib
->ifInDiscards
++;
696 putq(&rcvdq
, pkts
[cur
]);
701 #if (ETH_OCM_DBG_LVL >= 3)
702 dprintf("[eth_ocm_rx_isr] Frame discarded due to errors: 0x%08x!\n", (unsigned)stat
);
703 #endif // if ETH_OCM_DBG_LVL
704 info
->netp
->n_mib
->ifInDiscards
++;
707 // ensure bit-31 of pkt_array[]->nb_buff is clear before passing
709 buf_ptr
= (alt_u8
*)alt_remap_cached ((volatile void*) pkts
[cur
]->nb_buff
, 4);
710 //shift the actual write location over by ETHHDR_BIAS (see ipport.h)
711 buf_ptr
= (alt_u8
*)((unsigned int)buf_ptr
+ ETHHDR_BIAS
);
714 regs
->rxdescs
[cur
].ptr
= (unsigned int)buf_ptr
;
715 //Write the control register to start the transfer
716 stat
= ETH_OCM_RXDESC_EMPTY_MSK
| ETH_OCM_RXDESC_IRQ_MSK
;
717 if(cur
== (ETH_OCM_RX_DESC_COUNT
- 1))
718 stat
|= ETH_OCM_RXDESC_WRAP_MSK
;
719 regs
->rxdescs
[cur
].ctrl
= stat
;
721 //increment current descriptor counter
723 if(cur
== ETH_OCM_RX_DESC_COUNT
)
725 //get new descriptors status
726 stat
= regs
->rxdescs
[cur
].ctrl
;
728 info
->cur_rx_desc
= cur
;
733 void eth_ocm_stats(void *pio
, int iface
) {
741 dev
= (eth_ocm_dev
*)ifp
->n_local
;
744 #ifndef ETH_OCM_SYNC_TX
745 ns_printf(pio
, "ToSend queue: max:%d, current:%d\n",
746 dev
->info
->tosend
.q_max
,
747 dev
->info
->tosend
.q_len
);
749 ns_printf(pio
, "Sendng queue: max:%d, current:%d\n",
750 dev
->info
->sending
.q_max
,
751 dev
->info
->sending
.q_len
);
752 #endif //ifndef ETH_OCM_SYNC_TX
754 ns_printf(pio
, "TX Descriptor status:\n");
755 for(i
=0;i
<ETH_OCM_TX_DESC_COUNT
;i
++){
756 ns_printf(pio
," %3d: 0x%08x\n", i
, regs
->txdescs
[i
].ctrl
);
759 ns_printf(pio
, "RX Descriptor status:\n");
760 for(i
=0;i
<ETH_OCM_RX_DESC_COUNT
;i
++){
761 ns_printf(pio
," %3d: 0x%08x\n", i
, regs
->rxdescs
[i
].ctrl
);
768 * Closes the opencores mac interface
770 * @param iface index of the NET interface associated with the Opencores MAC.
773 int eth_ocm_close(int iface
)
781 dev
= (eth_ocm_dev
*)ifp
->n_local
;
783 ifp
->n_mib
->ifAdminStatus
= ETH_OCM_STATUS_DOWN
;
785 /* disable the interrupt in the OS*/
786 err
= alt_irq_register (dev
->irq
, 0, NULL
);
788 dprintf("[eth_ocm_close] Could not unregister interrupt, error = %d\n",err
);
793 IOWR_ETH_OCM_MODER(dev
->base
, 0);
796 ifp
->n_mib
->ifOperStatus
= ETH_OCM_STATUS_DOWN
;
797 //deallocate memory for the eth_ocm_info struct allocated in eth_ocm_prep
798 free(dev
->info
->rx_pkts
);
804 #endif // ifdef ALT_INICHE
805 //End of file ins_eth_ocm.h