Fix for the issue. PINDSW-4577. Storm prevention done for all paths
[processor-sdk/pdk.git] / packages / ti / drv / icss_emac / firmware / icss_dualemac / src / emac_MII_Rcv.asm
1 ;
2 ;  TEXAS INSTRUMENTS TEXT FILE LICENSE
3
4 ;   Copyright (c) 2017-2019 Texas Instruments Incorporated
5
6 ;  All rights reserved not granted herein.
7 ;  
8 ;  Limited License.  
9
10 ;  Texas Instruments Incorporated grants a world-wide, royalty-free, non-exclusive 
11 ;  license under copyrights and patents it now or hereafter owns or controls to 
12 ;  make, have made, use, import, offer to sell and sell ("Utilize") this software 
13 ;  subject to the terms herein.  With respect to the foregoing patent license, 
14 ;  such license is granted  solely to the extent that any such patent is necessary 
15 ;  to Utilize the software alone.  The patent license shall not apply to any 
16 ;  combinations which include this software, other than combinations with devices 
17 ;  manufactured by or for TI (“TI Devices”).  No hardware patent is licensed hereunder.
18
19 ;  Redistributions must preserve existing copyright notices and reproduce this license 
20 ;  (including the above copyright notice and the disclaimer and (if applicable) source 
21 ;  code license limitations below) in the documentation and/or other materials provided 
22 ;  with the distribution.
23 ;  
24 ;  Redistribution and use in binary form, without modification, are permitted provided 
25 ;  that the following conditions are met:
26 ;       No reverse engineering, decompilation, or disassembly of this software is 
27 ;   permitted with respect to any software provided in binary form.
28 ;       Any redistribution and use are licensed by TI for use only with TI Devices.
29 ;       Nothing shall obligate TI to provide you with source code for the software 
30 ;   licensed and provided to you in object code.
31 ;  
32 ;  If software source code is provided to you, modification and redistribution of the 
33 ;  source code are permitted provided that the following conditions are met:
34 ;       Any redistribution and use of the source code, including any resulting derivative 
35 ;   works, are licensed by TI for use only with TI Devices.
36 ;       Any redistribution and use of any object code compiled from the source code
37 ;   and any resulting derivative works, are licensed by TI for use only with TI Devices.
38
39 ;  Neither the name of Texas Instruments Incorporated nor the names of its suppliers 
40 ;  may be used to endorse or promote products derived from this software without 
41 ;  specific prior written permission.
42
43 ;  DISCLAIMER.
44
45 ;  THIS SOFTWARE IS PROVIDED BY TI AND TI’S LICENSORS "AS IS" AND ANY EXPRESS OR IMPLIED 
46 ;  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
47 ;  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TI AND TI’S 
48 ;  LICENSORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
49 ;  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 
50 ;  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
51 ;  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
52 ;  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 
53 ;  EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
54
55 ; file:   emac_MII_Rcv.asm
56 ;
57 ; brief:  Receive Task
58 ;
59 ;
60 ;  (C) Copyright 2017-2019, Texas Instruments, Inc
61 ;
62 ;
63     
64     .if !$defined("__mii_rcv_p")        
65 __mii_rcv_p     .set    1       
66     
67 ;;///////////////////////////////////////////////////////
68 ; Includes Section
69 ;;///////////////////////////////////////////////////////
70     .include "emac_MII_Rcv.h"
71     .include "icss_macros.h"
72 ;       .include "icss_regs.h"
73     .if $defined("ICSS_SWITCH_BUILD")
74     .include "icss_switch_macros.h"
76     .if $defined("ICSS_STP_SWITCH")
77     .include "icss_stp_switch_macros.h"
78     .cdecls C,NOLIST
79 %{
80 #include "icss_stp_switch.h"
81 %}
82     .endif ; ICSS_STP_SWITCH
83     
84     .endif
85     .include "micro_scheduler.h"
86     .include "emac_MII_Xmt.h"
87     .include "icss_miirt_regs.h"
89     .if $defined(PTP)
90     .include "icss_ptp.h"
91     .include "icss_ptp_macro.h"
92     .cdecls C,NOLIST
93 %{
94 #include "icss_timeSync_memory_map.h"
95 %}
96     .endif ;PTP
98         .global  FN_RCV_FB
99         .global  FN_RCV_NB
100         .global  FN_RCV_LB
101         .global  XMT_QUEUE
102         .global  TASK_EXECUTION_FINISHED
103         .global  FN_TIMESTAMP_GPTP_PACKET
104         .global  FN_CHECK_AND_CLR_PTP_FWD_FLAG
105         .global  FN_CHECK_AND_CLR_PTP_FWD_FLAG_L2
106         .global  FN_COMPARE_DELAY_RESP_ID
108     
109 ;****************************************************************************
111 ;     NAME              : FN_RCV_FB
112 ;     DESCRIPTION       : receives the first block of data from new frame (out of RX L2)
113 ;     RETURNS           : 
114 ;     ARGS              : 
115 ;     USES              : 
116 ;     INVOKES           : 
118 ;****************************************************************************
119 FN_RCV_FB:
120     ; Data is already present in the registers. So, no need to read it again.
121     
122     ZERO        &MII_RCV, $sizeof(MII_RCV)      ; init MII_RCV parameter
123     ; OPT: Possible to make them both context next to each other
124     .if    $defined("TWO_PORT_CFG")    
125     ZERO    &MII_RCV_PORT, $sizeof(MII_RCV_PORT)    ; init MII_RCV parameter  (R14....R17)
126     .endif
127     ; Check if RX port is enabled (information provided by host)
128     LDI R10.w0 , PORT_CONTROL_ADDR
129     LBCO        &R10, PRU_DMEM_ADDR, R10.w0, 10 ; 4 + 6 bytes of Interface MAC Addr
130     
131     ; OPT: Port can be disabled directly in the MII Hardware
132     ; Is port enabled?
133     QBBC        EXIT_FB, R10, 0
135     .if $defined("ICSS_STP_SWITCH")
136 CHECK_STP_DISABLE:
137     ; Prepare STP State register address
138     .if $defined("PRU0")
139     ; Read Port 1 STP state
140     LDI32 RCV_TEMP_REG_3, ICSS_EMAC_FW_FDB__STP_P1_STP_STATE_ADDR    
141     .else    
142     ; Read Port 2 STP state
143     LDI32 RCV_TEMP_REG_3, ICSS_EMAC_FW_FDB__STP_P2_STP_STATE_ADDR
144     .endif ; $defined("PRU0")
145     LBBO  &RCV_TEMP_REG_1.b0, RCV_TEMP_REG_3, 0, 1 ; read state from memory
146     AND   STP_STATE__R22_BYTE, STP_STATE__R22_BYTE, STP_STATE__R22_INV_MASK ; clear relevant bits in R22
147     OR    STP_STATE__R22_BYTE, STP_STATE__R22_BYTE, RCV_TEMP_REG_1.b0 ; set the relevant bits in R22
149     ; If Port disabled, disable directly in MII Hardware
150     AND   RCV_TEMP_REG_1.b0, STP_STATE__R22_BYTE, STP_STATE__R22_MASK ; read STP state in R22
151     QBEQ  EXIT_FB, RCV_TEMP_REG_1.b0, STP_STATE_DISABLED
153     ; If STP state is invalid, log error statistics and drop packet
154     QBGE  CONTINUE_PROCESSING, RCV_TEMP_REG_1.b0, STP_STATE_BLOCKING
155     LDI   RCV_TEMP_REG_3 , STP_INVALID_STATE_OFFSET       ; else drop frame and increase the stats
156     QBA   COUNT_RX_STATS
157     .endif ; ICSS_STP_SWITCH
158         
159 CONTINUE_PROCESSING:
160     .if $defined("ICSS_STP_SWITCH")
161     .if $defined("ICSS_SWITCH_BUILD")
162     ; We are in a valid STP state, thus there is a chance packets get to the host
163     ; By default, both of these flags should be cleared
164     CLR   R22, R22, FDB_LOOKUP_SUCCESS__R22_BIT
165     CLR   R22, R22, PKT_FLOODED__R22_BIT
166     .endif
167     .endif ; ICSS_STP_SWITCH
168     
169     ; set Rcv_active flag to indicate an ongoing reception
170     SET R23 , R23 , Rcv_active 
171     
172 ;*********************************Check for Errors*****************************************
173 ;******************************************************************************************     
174     .if $defined("ICSS_DUAL_EMAC_BUILD")
175 ;check for SFD Errors    
176     .if $defined("HALF_DUPLEX_ENABLED") 
177 ; below code not needed for Full Duple
178     .if $defined("PRU0")        
179     LBCO        &RCV_TEMP_REG_3.b0, MII_RT_CFG_CONST, ICSS_MIIRT_RXERR0, 1      ;read the PRUSS_MII_RT_RX_ERR0 register 
180     QBBC        CHECK_FOR_SHORT_SFD, RCV_TEMP_REG_3, 1      ; check for any error if not then jump else continue
181     ;clear error and writeback
182     SET RCV_TEMP_REG_3 , RCV_TEMP_REG_3 , 1
183     SBCO        &RCV_TEMP_REG_3.b0, MII_RT_CFG_CONST, ICSS_MIIRT_RXERR0, 1
184     QBA     COUNT_SFD_ERROR
185 CHECK_FOR_SHORT_SFD:            
186     QBBC        CONTINUE_PROCESSING_PKT, RCV_TEMP_REG_3, 0      ; check for any error if not then jump else continue
187     ;clear error and writeback
188     SET RCV_TEMP_REG_3 , RCV_TEMP_REG_3 , 0 
189     SBCO        &RCV_TEMP_REG_3.b0, MII_RT_CFG_CONST, ICSS_MIIRT_RXERR0, 1      
190     QBA     COUNT_SFD_ERROR
191     .else
192     LBCO        &RCV_TEMP_REG_3.b0, MII_RT_CFG_CONST, ICSS_MIIRT_RXERR1, 1      ;read the PRUSS_MII_RT_RX_ERR0 register 
193     QBBC        CHECK_FOR_SHORT_SFD, RCV_TEMP_REG_3, 1      ; check for any error if not then jump else continue
194     ;clear error and writeback
195     SET RCV_TEMP_REG_3 , RCV_TEMP_REG_3 , 1 
196     SBCO        &RCV_TEMP_REG_3.b0, MII_RT_CFG_CONST, ICSS_MIIRT_RXERR1, 1      
197     QBA     COUNT_SFD_ERROR
198 CHECK_FOR_SHORT_SFD:            
199     QBBC        CONTINUE_PROCESSING_PKT, RCV_TEMP_REG_3, 0      ; check for any error if not then jump else continue
200     ;clear error and writeback
201     SET RCV_TEMP_REG_3 , RCV_TEMP_REG_3 , 0 
202     SBCO        &RCV_TEMP_REG_3.b0, MII_RT_CFG_CONST, ICSS_MIIRT_RXERR1, 1      
203     QBA     COUNT_SFD_ERROR
204     .endif
205     
206     ;check R31 bit 19 for error
207     QBBC        CONTINUE_PROCESSING_PKT, R31, 19
208     ;clear the error
209     M_CMD16 D_RX_ERROR_CLEAR
210     
211     ;set error flag
212     LDI RCV_TEMP_REG_3 , RX_ERROR_OFFSET
213     QBA     COUNT_RX_STATS
214     ; Check if SA matches with Slave's Interface MAC addr
215     .endif  ;HALF_DUPLEX_ENABLED
216     .endif  ;ICSS_DUAL_EMAC_BUILD
217 CONTINUE_PROCESSING_PKT:
219     .if $defined("ICSS_STP_SWITCH")
220 CHECK_STP_DISCARDING:
221     ; Listening and Blocking states all resolve to the same action:
222     ; .. only allow BPDU frames to pass. Aka DISCARDING in RSTP.
224     ; STP State for current port is stored in R22
225     AND   RCV_TEMP_REG_1.b0, STP_STATE__R22_BYTE, STP_STATE__R22_MASK ; read STP state in R22
226     QBEQ  STP_DISCARD, RCV_TEMP_REG_1.b0, STP_STATE_BLOCKING
227     QBEQ  STP_DISCARD, RCV_TEMP_REG_1.b0, STP_STATE_LISTENING
229     ; Not discarding, continue processing
230     QBA CHECK_RSVD_ADDR
232 STP_DISCARD:
233     ; Only allow BPDU packets
234 CHECK_MC_BPDU:  
235     ; Check Multicast BPDU Address (allow all 01:80:c2:xx:xx:xx traffic)
236     LDI   RCV_TEMP_REG_3.w0, 0x8001
237     QBNE  CHECK_VLAN_BPDU, EthWord.DstWord_01, RCV_TEMP_REG_3.w0
238     LDI   RCV_TEMP_REG_3.b0, 0xC2
239     MOV   RCV_TEMP_REG_3.b2, EthByte.DstByte_2
240     QBNE  CHECK_VLAN_BPDU, RCV_TEMP_REG_3.b0, RCV_TEMP_REG_3.b2
242     ; Address is Multicast BPDU
243     QBA   CHECK_RSVD_ADDR
245 CHECK_VLAN_BPDU:
246     ; Check VLAN BPDU Address
247     LDI   RCV_TEMP_REG_3.w0, 0x0001
248     LDI   RCV_TEMP_REG_3.w2, 0xCC0C
249     QBNE  DROP_PKT, Ethernet.DstAddr_0123, RCV_TEMP_REG_3
250     LDI   RCV_TEMP_REG_3.w0, 0xCDCC
251     QBNE  DROP_PKT, Ethernet.DstAddr_45, RCV_TEMP_REG_3.w0
253 CHECK_RSVD_ADDR:
254     ; Reserved addresses are 01:80:c2:00:00:00 - 01:80:c2:00:00:10
255     LDI   RCV_TEMP_REG_3.w0, 0x8001
256     LDI   RCV_TEMP_REG_3.w2, 0x00C2
257     QBNE  CHECK_PKT_SOURCE, Ethernet.DstAddr_0123, RCV_TEMP_REG_3
258     MOV   RCV_TEMP_REG_3.w2, Ethernet.DstAddr_45
259     QBNE  CHECK_PKT_SOURCE, RCV_TEMP_REG_3.b2, 0x00
260     QBLT  CHECK_PKT_SOURCE, RCV_TEMP_REG_3.b3, 0x10
262     ; Packets for reserved addresses are not to be forwarded
263     ; .. so set the local STP state to "Learning"
264     AND   STP_STATE__R22_BYTE, STP_STATE__R22_BYTE, STP_STATE__R22_INV_MASK ; clr STP state in R22
265     OR    STP_STATE__R22_BYTE, STP_STATE__R22_BYTE, STP_STATE_LEARNING
267     ; Address is VLAN BPDU, continue
268     .endif ; ICSS_STP_SWITCH
269         
270 CHECK_PKT_SOURCE:             
271     QBNE        FB_SA_NO_MATCH_INTERFACE_MAC, Ethernet.SrcAddr_01, R11.w0       ;Check if Source Address matches with own address
272     QBNE        FB_SA_NO_MATCH_INTERFACE_MAC, Ethernet.SrcAddr_23, R11.w2       ;Source Address is stored into 3 words (16 bits)
273     QBNE        FB_SA_NO_MATCH_INTERFACE_MAC, Ethernet.SrcAddr_45, R12.w0       
275     .if $defined("ICSS_STP_SWITCH")
276 DROP_PKT:
277     .endif ; ICSS_STP_SWITCH
278     LDI RCV_TEMP_REG_3 , RX_DROPPED_FRAMES_OFFSET       ; else drop frame and increase the stats
279     QBA     COUNT_RX_STATS
280     ;QBA     EXIT_FB
281     .if $defined("HALF_DUPLEX_ENABLED") 
282 COUNT_SFD_ERROR:
283     LDI RCV_TEMP_REG_3 , SFD_ERROR_OFFSET
284     .endif      ;HALF_DUPLEX_ENABLED
285     
286 COUNT_RX_STATS:
287 ;count statistics based on offset set in RCV_TEMP_REG_3
288     LBCO        &RCV_TEMP_REG_2, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4       
289     ADD RCV_TEMP_REG_2, RCV_TEMP_REG_2, 1       
290     SBCO        &RCV_TEMP_REG_2, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4       
291 EXIT_FB:
292     SET MII_RCV.rx_flags , MII_RCV.rx_flags , rx_frame_error_shift
293     QBA FB_DONE
294     
295 FB_SA_NO_MATCH_INTERFACE_MAC:
296     .if $defined(PTP)
297     M_GPTP_CHECK_AND_SET_FLAGS 
298     .endif ;PTP
299     ; optimize the program memory by loading the promiscuous mode offset
300     ; before jumping to multicast or broadcast packet check
301     ; this would save loading the same when needed to check to bypass 
302     ; the storm prevention later when promiscuous mode is enabled
303     .if $defined("ICSS_DUAL_EMAC_BUILD")
304         LDI     RCV_TEMP_REG_3.w0 , ICSS_EMAC_FIRMWARE_PROMISCUOUS_MODE_OFFSET
305         LBCO    &RCV_TEMP_REG_2, ICSS_SHARED_CONST, RCV_TEMP_REG_3.w0, 4
306     .endif
307     ; check for multi-cast
308     .if $defined("ICSS_STP_SWITCH")
309     QBBS        SKIP_SELF_CHECK, EthByte.DstByte_0, 0 ; if packet is destined for multi/broadcast, skip the self-reference check and DST FDB lookup
310     .else
311     QBBS        FB_MULTI_OR_BROADCAST, EthByte.DstByte_0, 0         ; check if packet is Multi/Broad cast type
312     .endif ; ICSS_STP_SWITCH
313     
314 ;*********************************
315 ; uni-cast handling
316 ;*********************************
317 FB_UNICAST:
318     
319 FB_UNICAST_SA_NO_MATCH:
320     .if $defined("ICSS_DUAL_EMAC_BUILD")
321         QBBS    FB_PROMISCUOUS_MODE_ENABLE, RCV_TEMP_REG_2, ICSS_EMAC_PROMISCOUS_BIT
322     .endif
323     ; check if DA matches with our Interface MAC address
324     QBNE        FB_UNICAST_DA_NO_MATCH, Ethernet.DstAddr_0123, R11      ;Check if Destination Address matches with own address
325     QBNE        FB_UNICAST_DA_NO_MATCH, Ethernet.DstAddr_45, R12.w0     
327 FB_PROMISCUOUS_MODE_ENABLE:
328     ; the frame DST address matches with our own address
329     SET MII_RCV.rx_flags , MII_RCV.rx_flags , host_rcv_flag_shift ; set flag that host queue will receive data
330     .if    $defined("TWO_PORT_CFG")
331     .if    !$defined("ICSS_STP_SWITCH") ; STP needs to do an FDB lookup
332     QBA         FB_LT_VT
333     .endif
334     .else
335     QBA         FB_UNICAST_CHECK_CT
336     .endif
337     
338 FB_UNICAST_DA_NO_MATCH:
339     .if $defined("ICSS_STP_SWITCH")
340     ;; Linux needs to also check if the packet is destined for the other port MAC
341     LDI    RCV_TEMP_REG_1.w0, PORT_MAC_ADDR ; Read from other port DMEM
342     LBCO   &RCV_TEMP_REG_1, PRU_CROSS_DMEM, RCV_TEMP_REG_1.w0, 6 ; 6 bytes of MAC
344     ; check if DA matches with other port MAC address
345     QBNE   FB_UNICAST_DA_NO_MATCH_OTHER_PORT, Ethernet.DstAddr_0123, RCV_TEMP_REG_1
346     QBNE   FB_UNICAST_DA_NO_MATCH_OTHER_PORT, Ethernet.DstAddr_45, RCV_TEMP_REG_2.w0
348     ; the frame DST address matches with other port addr
349     SET MII_RCV.rx_flags , MII_RCV.rx_flags , host_rcv_flag_shift ; set flag that host queue will receive data
351 FB_UNICAST_DA_NO_MATCH_OTHER_PORT:
352     .endif
353     
354     .if    $defined("TWO_PORT_CFG")
356     .if $defined("ICSS_STP_SWITCH")
357 SKIP_SELF_CHECK:      
358 FDB_LOCK: 
359     ; Take the lock and check for timeout
360     LDI RCV_TEMP_REG_1.w0, 0x8F
361     M_SPIN_LOCK RCV_TEMP_REG_4.b2, RCV_TEMP_REG_1.w0    
362     QBNE  FDB_CHECK_DST, RCV_TEMP_REG_4.b2, 0 ; continue if no timeout
363     
364     ; Flood/insert upon timeout
365     SET   MII_RCV.rx_flags , MII_RCV.rx_flags , host_rcv_flag_shift
366     SET   R22, R22, PKT_FLOODED__R22_BIT
367     QBA   FDB_UNLOCK
369 FDB_CHECK_DST:
370     ; If the packet is multi/broadcast, then skip DST lookup
371     QBBS  FDB_SRC_LOOKUP, EthByte.DstByte_0, 0
373     ; If the packet is not destined for the Host, continue with DST lookup
374     QBBC  FDB_DST_LOOKUP, MII_RCV.rx_flags, host_rcv_flag_shift
375     
376     ; Set the local STP state to "Learning" as a way to ensure we can check the
377     ; .. SRC address but not forward the packet. This will not affect the global
378     ; .. STP state.
379     AND   STP_STATE__R22_BYTE, STP_STATE__R22_BYTE, STP_STATE__R22_INV_MASK ; clr STP state in R22
380     OR    STP_STATE__R22_BYTE, STP_STATE__R22_BYTE, STP_STATE_LEARNING
382     QBA   FDB_SRC_LOOKUP ; skip DST lookup
383     
384 FDB_DST_LOOKUP:
385     ; Look up the destination in the FDB to determine if it needs to be flooded or directly forwarded
386     M_UNICAST_FDB_HASH_LOOKUP     EthWord.DstWord_01, EthWord.DstWord_23, Ethernet.DstAddr_45, RCV_TEMP_REG_1.b2
388     ; Check lookup success
389     QBEQ  FDB_DST_LOOKUP_SUCCESS, RCV_TEMP_REG_1.b2, 1
391     ; Not found in FDB, flood the packet
392 FLOOD_UNICAST_PACKET:
393     ; Unicast address not found in FDB, flood it by forwarding the packet
394     ; to the host as well as the other port
395     SET   MII_RCV.rx_flags , MII_RCV.rx_flags , host_rcv_flag_shift
396     SET   R22, R22, PKT_FLOODED__R22_BIT
397     QBA   FDB_DST_LOOKUP_END
399 FDB_DST_LOOKUP_SUCCESS:
400     ; Check destination port is not current port
401     LBBO  &RCV_TEMP_REG_1.b0, RCV_TEMP_REG_3, FDB_MAC_INFO__PORT_NO__OFFSET, FDB_MAC_INFO__PORT_NO__SIZE ; TEMP_REG_3 still has the table pointer from lookup
403     ; If the destination port is the current port, set the local STP state
404     ; .. to "Learning" so we don't forward the packet
405     .if $defined("PRU0")        
406     QBNE  FDB_DST_LOOKUP_END, RCV_TEMP_REG_1.b0, 0x0 ; Port 1
407     .else
408     QBNE  FDB_DST_LOOKUP_END, RCV_TEMP_REG_1.b0, 0x1 ; Port 2
409     .endif
411     ; Set the local STP state to "Learning" as a way to ensure we can learn the
412     ; .. SRC address but not forward the packet. This will not affect the global
413     ; .. STP state.
414     AND   STP_STATE__R22_BYTE, STP_STATE__R22_BYTE, STP_STATE__R22_INV_MASK ; clr STP state in R22
415     OR    STP_STATE__R22_BYTE, STP_STATE__R22_BYTE, STP_STATE_LEARNING
416     
417 FDB_DST_LOOKUP_END:   
418 FDB_SRC_LOOKUP:
419     ; If the src addr is multi/broadcast, then skip the SRC lookup
420     QBBS  FDB_SRC_LOOKUP_END, EthByte.SrcByte_0, 0
421     
422     ; Now we must look up the source address in the FDB for learning purposes
423     M_UNICAST_FDB_HASH_LOOKUP     Ethernet.SrcAddr_01, Ethernet.SrcAddr_23, Ethernet.SrcAddr_45, RCV_TEMP_REG_1.b3
425     ; Check lookup success
426     QBEQ  FDB_SRC_LOOKUP_FAIL, RCV_TEMP_REG_1.b3, 0
428 FDB_SRC_LOOKUP_SUCCESS:
429     ; The source address was found in the FDB, alert the host and proceed to reset the ageing timer
430     SET   R22, R22, FDB_LOOKUP_SUCCESS__R22_BIT
431     
432 FDB_TOUCH_ENTRY:
433     ; Reset FDB entry age and update port number information
435     ; Reset ageing timer
436     LDI   RCV_TEMP_REG_1.w0, 0x0000
438     ; Set port information
439     .if $defined("PRU0")        
440     LDI   RCV_TEMP_REG_1.b2, 0x0 ; Port 1
441     .else
442     LDI   RCV_TEMP_REG_1.b2, 0x1 ; Port 2
443     .endif
444     
445     SBBO  &RCV_TEMP_REG_1, RCV_TEMP_REG_3, FDB_MAC_INFO__AGE__OFFSET, (FDB_MAC_INFO__AGE__SIZE + FDB_MAC_INFO__PORT_NO__SIZE) ; TEMP_REG_3 still has the table pointer from lookup
446     QBA   FDB_SRC_LOOKUP_END
448 FDB_SRC_LOOKUP_FAIL:
449     ; The source MAC isn't found in the FDB, send to the host for insertion
450     SET   MII_RCV.rx_flags , MII_RCV.rx_flags , host_rcv_flag_shift
452 FDB_SRC_LOOKUP_END:
453 FDB_UNLOCK:
454     ; Release the lock
455     M_SPIN_UNLOCK
457     ; If the packet is multi/broadcast, process it as such
458     QBBS  FB_MULTI_OR_BROADCAST, EthByte.DstByte_0, 0    
459     .endif ; ICSS_STP_SWITCH
460     ; Begin process of forwarding unicast packet, cut-through if possible
461     QBA   FB_UNICAST_CHECK_CT
462     
463     .else
464     LDI RCV_TEMP_REG_3 , RX_DROPPED_FRAMES_OFFSET
465     QBA     COUNT_RX_STATS
466     .endif
467 ;*********************************
468 ; multicast/broadcast handling
469 ;*********************************
470 FB_MULTI_OR_BROADCAST:
471 FB_CONTINUE:
472     ; Check if destination is broadcast
473     FILL        &RCV_TEMP_REG_1, 4   ; Fill with 0xffffffff
474     QBNE        FB_MULTICAST, Ethernet.DstAddr_0123, RCV_TEMP_REG_1
475     QBNE        FB_MULTICAST, Ethernet.DstAddr_45, RCV_TEMP_REG_1.w0    
476     
477 FB_BROADCAST:
478     SET R22 , R22 , RX_BC_FRAME      ; set broad-cast bit to indicate the broadcast frame 
479     SET MII_RCV.rx_flags , MII_RCV.rx_flags , host_rcv_flag_shift
480     QBA FB_BROADCAST_CHECK_CT
481     
482 FB_MULTICAST:
483     SET MII_RCV.rx_flags , MII_RCV.rx_flags , host_rcv_flag_shift
484     SET R22 , R22 , RX_MC_FRAME      ; set multi-cast bit to indicate the multicast frame 
486     .if $defined("ICSS_DUAL_EMAC_BUILD") | $defined("ICSS_STP_SWITCH")
487         ; check if multicast filtering is enabled or not i.e. check MULTICAST_CONTROL_BIT in PRU1 data memory
488         LDI     RCV_TEMP_REG_3.w0, ICSS_EMAC_FW_MULTICAST_FILTER_CTRL_OFFSET
489         LBCO    &RCV_TEMP_REG_3.b0, PRU_DMEM_ADDR, RCV_TEMP_REG_3.w0, 1
490         QBEQ    FB_MULTICAST_CONTINUE, RCV_TEMP_REG_3.b0, ICSS_EMAC_FW_MULTICAST_FILTER_CTRL_DISABLED    ; one byte field : 0 -> multicast filtering disabled | 1 -> multicast filtering enabled
492         ; search in multicast table to determine if host receive is to be enabled or not for the incoming multicast frame
493         M_MULTICAST_TABLE_SEARCH_OP
494         ; QBA     FB_MULTICAST_CONTINUE
495     .endif
496     
497 FB_MULTICAST_CONTINUE:
498 FB_UNICAST_CHECK_CT:
499 FB_BROADCAST_CHECK_CT:
500     .if $defined("ICSS_DUAL_EMAC_BUILD") | $defined("ICSS_STP_SWITCH")
501         ; check if VLAN filtering is enabled or not i.e. check VLAN_FLTR_CTRL_SHIFT in VLAN_FLTR_CTRL_BYTE stored in data memory
502         LDI     RCV_TEMP_REG_3.w0, ICSS_EMAC_FW_VLAN_FILTER_CTRL_BITMAP_OFFSET
503         LBCO    &RCV_TEMP_REG_3.b0, PRU_DMEM_ADDR, RCV_TEMP_REG_3.w0, 1
504     ;-----------------------------------------------------------
505     ;   VLAN_FLTR_CTRL_BYTE  |          |          |           | R13 | RCV_TEMP_REG_3
506     ;-----------------------------------------------------------
507         QBBC    FB_SKIP_VLAN_FLTR, RCV_TEMP_REG_3.b0, ICSS_EMAC_FW_VLAN_FILTER_CTRL_ENABLE_BIT   ; one bit field | 0 : VLAN filter disabled | 1 : VLAN filter enabled
509         ; search in VLAN table to determine if host receive is to be enabled or not for the incoming frame
510         M_VLAN_FLTR_SRCH_OP
512 FB_SKIP_VLAN_FLTR:
513     .endif
515     ;PINDSW-4577: Fix to avoid cut-through packets from going via Storm Prevention
516     ;Storm prevention is done only if host receive flag is set
517     QBBC    FB_CONT_CT_CHECK, MII_RCV.rx_flags , host_rcv_flag_shift
518     
519     ; Storm Prevention
520     QBBC    FB_STORM_NOT_MC, R22, RX_MC_FRAME
521     LDI     RCV_TEMP_REG_3 , STORM_PREVENTION_OFFSET_MC
522     ;Do storm prevention here
523     LBCO  &RCV_TEMP_REG_2, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4   ; load the current storm prevent count 
524     QBBC  FB_CONT_CT_CHECK, RCV_TEMP_REG_2, 0
525     LSR   RCV_TEMP_REG_2, RCV_TEMP_REG_2, 8   
526     QBGT  FB_DISCARD_MC, RCV_TEMP_REG_2.w0, 1    ; check if the counter is less than zero and discard packet
527     SUB   RCV_TEMP_REG_2, RCV_TEMP_REG_2, 1   
528     LSL   RCV_TEMP_REG_2, RCV_TEMP_REG_2, 8   
529     SET   RCV_TEMP_REG_2 , RCV_TEMP_REG_2 , 0 
530     SBCO  &RCV_TEMP_REG_2, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4 
532     QBA     FB_CONT_CT_CHECK
533 FB_STORM_NOT_MC:
534     QBBC    FB_STORM_NOT_BC, R22, RX_BC_FRAME
535     LDI     RCV_TEMP_REG_3 , STORM_PREVENTION_OFFSET_BC
536     ;Do storm prevention here
537     LBCO  &RCV_TEMP_REG_2, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4   ; load the current storm prevent count 
538     QBBC  FB_CONT_CT_CHECK, RCV_TEMP_REG_2, 0
539     LSR   RCV_TEMP_REG_2, RCV_TEMP_REG_2, 8   
540     QBGT  FB_DISCARD_BC, RCV_TEMP_REG_2.w0, 1    ; check if the counter is less than zero and discard packet
541     SUB   RCV_TEMP_REG_2, RCV_TEMP_REG_2, 1   
542     LSL   RCV_TEMP_REG_2, RCV_TEMP_REG_2, 8   
543     SET   RCV_TEMP_REG_2 , RCV_TEMP_REG_2 , 0 
544     SBCO  &RCV_TEMP_REG_2, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4 
546     QBA     FB_CONT_CT_CHECK
547 FB_STORM_NOT_BC:
548     LDI     RCV_TEMP_REG_3 , STORM_PREVENTION_OFFSET_UC
549     ;Do storm prevention here
550     LBCO  &RCV_TEMP_REG_2, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4   ; load the current storm prevent count 
551     QBBC  FB_CONT_CT_CHECK, RCV_TEMP_REG_2, 0
552     LSR   RCV_TEMP_REG_2, RCV_TEMP_REG_2, 8   
553     QBGT  FB_DISCARD_UC, RCV_TEMP_REG_2.w0, 1    ; check if the counter is less than zero and discard packet
554     SUB   RCV_TEMP_REG_2, RCV_TEMP_REG_2, 1   
555     LSL   RCV_TEMP_REG_2, RCV_TEMP_REG_2, 8   
556     SET   RCV_TEMP_REG_2 , RCV_TEMP_REG_2 , 0 
557     SBCO  &RCV_TEMP_REG_2, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4 
559     QBA     FB_CONT_CT_CHECK 
561 FB_DISCARD_MC:
562     LDI RCV_TEMP_REG_3 , STORM_PREVENTION_COUNTER_MC
563     QBA COUNT_RX_STATS
564 FB_DISCARD_BC:
565     LDI RCV_TEMP_REG_3 , STORM_PREVENTION_COUNTER_BC
566     QBA COUNT_RX_STATS 
567 FB_DISCARD_UC:
568     LDI RCV_TEMP_REG_3 , STORM_PREVENTION_COUNTER_UC
569     QBA COUNT_RX_STATS 
571 FB_CONT_CT_CHECK:
572     .if    $defined("TWO_PORT_CFG")
574     .if $defined("ICSS_STP_SWITCH")
575 CHECK_STP_LEARNING:
576     ; Only forward packet if STP state is FORWARDING
577     AND   RCV_TEMP_REG_1.b0, STP_STATE__R22_BYTE, STP_STATE__R22_MASK ; read STP state in R22
578     QBNE  SKIP_FORWARDING, RCV_TEMP_REG_1.b0, STP_STATE_FORWARDING ; STP State for current port is stored in R22
580     ; Only forward packet if the OTHER port state is FORWARDING    
581     .if $defined("PRU0")
582     ; Read Port 2 STP state
583     LDI32 RCV_TEMP_REG_3, ICSS_EMAC_FW_FDB__STP_P2_STP_STATE_ADDR    
584     .else    
585     ; Read Port 1 STP state
586     LDI32 RCV_TEMP_REG_3, ICSS_EMAC_FW_FDB__STP_P1_STP_STATE_ADDR    
587     .endif ; $defined("PRU0")
588     LBBO  &RCV_TEMP_REG_1.b0, RCV_TEMP_REG_3, 0, 1
589     
590     QBNE  SKIP_FORWARDING, RCV_TEMP_REG_1.b0, STP_STATE_FORWARDING
592 SET_FORWARDING:
593     .endif ; ICSS_STP_SWITCH
594     QBBS    FB_NO_CT, R23, 0 ;Xmt_active            ; check if we can set cut-through
595     QBBC    FB_NO_CT, R22, 31 ;PACKET_TX_ALLOWED
596     QBA        FB_CT_HANDLING
597     
598 FB_NO_CT:
599     SET        MII_RCV.rx_flags, MII_RCV.rx_flags, fwd_flag_shift    ;MII_RCV.rx_flags.fwd_flag
600     JMP        FB_LT_VT
601 FB_CT_HANDLING:
602   SET        MII_RCV.tx_flags, MII_RCV.tx_flags, cut_through_flag_shift    ;MII_RCV.tx_flags.cut_through_flag
604     .if $defined("ICSS_STP_SWITCH")
605 SKIP_FORWARDING:
606     .endif ; ICSS_STP_SWITCH
607 FB_LT_VT:
608     
609 ;check link on other port
610     QBBS        FB_EGRESS_LINK_UP, R22, 10       ;replaced: QBBS    FB_EGRESS_LINK_UP, OPPOSITE_PORT_LINK_UP 
611         
612 ; OPT: See whether they can be moved next to each other
613     CLR        MII_RCV.rx_flags, MII_RCV.rx_flags, fwd_flag_shift
614     CLR        MII_RCV.tx_flags, MII_RCV.tx_flags, cut_through_flag_shift
615     
616     ;If host receive flag is not set then increment statistics for dropped frames
617     QBBS        FB_EGRESS_LINK_UP, MII_RCV.rx_flags, host_rcv_flag_shift
618     LDI         RCV_TEMP_REG_3, RX_DROPPED_FRAMES_OFFSET
619     CLR         R22, R22, RX_BC_FRAME
620     CLR         R22, R22, RX_MC_FRAME
621     LBCO    &RCV_TEMP_REG_2, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4
622     ADD     RCV_TEMP_REG_2, RCV_TEMP_REG_2, 1
623     SBCO    &RCV_TEMP_REG_2, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4
624     
625     
626 FB_EGRESS_LINK_UP:
627   
628     QBBC    FB_LT_VT_2, MII_RCV.tx_flags, cut_through_flag_shift
629     
630     LDI        CUT_THROUGH_BYTE_CNT, 0x0000
632     ; Insert first 12 bytes in the TX FIFO of opposit
633     .if $defined("ICSS_REV1")
634     LDI TX_DATA_WORD_MASK , 0xffff
635     AND TX_DATA_BYTE , BUFFER.b0 , BUFFER.b0
636     M_PUSH_BYTE
637     AND TX_DATA_BYTE , BUFFER.b1 , BUFFER.b1
638     M_PUSH_BYTE
640     ;MOV                loop_cnt, 2
641     LDI TX_DATA_POINTER, buffer_ptr + 2 
642     loop        FB_RCV_EndLoop_1, 2
643     MVIW        TX_DATA_WORD, *TX_DATA_POINTER  
644     M_PUSH_WORD_CMD
645     ADD TX_DATA_POINTER, TX_DATA_POINTER, 2     
646 FB_RCV_EndLoop_1:
647     .endif
648     .if $defined("ICSS_REV2")
649     LDI        TX_DATA_POINTER, buffer_ptr
650     loop    FB_RCV_EndLoop_1, 3
651     MVID    TX_DATA_DOUBLE_WORD, *TX_DATA_POINTER
652     ADD        TX_DATA_POINTER, TX_DATA_POINTER, 4
653 FB_RCV_EndLoop_1:
654     .endif
655     .endif ;TWO_PORT_CFG
656 FB_LT_VT_2: ; Quality of service --> select RX queue priority based on Ethernet frame tags
657     
658     XIN RX_L2_BANK0_ID, &R18, RANGE_R18_b0      ; XIN RX L2 bank 0 R18 value
659     XIN RX_L2_BANK0_ID, &R2, RANGE_R2_R13       ; XIN RX L2 bank 0 R2 - R13 value    
661     .if $defined(PTP)
662     M_GPTP_ASSIGN_QOS 
663     .endif ;PTP
664     
665     .if    $defined("TWO_PORT_CFG")    
666 ; The naming of the QoS queue goes from 1..4, but we need to count from 0..3
667     LDI        MII_RCV.qos_queue, 4-1    ; default (lowest priority) queue is 4
669 FB_QOS_APPLY_RULES:
670     LDI        RCV_TEMP_REG_1.w0, 0x0081        ; 0x8100 --> indicates QOS tagged frame
671     QBNE    FB_QOS_DONE, Ethernet.TPID, RCV_TEMP_REG_1.w0
672     LSR        RCV_TEMP_REG_1.b0, R5.b2, 5        ; extract PCP info. FIXME: clpru : Ethernet.TCI.b0 -> R5.b2
673     QBGT    FB_QOS_CHECK_FOR_PRIO2, RCV_TEMP_REG_1.b0, 6    ; PCP == 7/6
674     LDI        MII_RCV.qos_queue, 1-1    ; highest priority is 1, select queue 1
675   
676   QBA        FB_QOS_DONE
677 FB_QOS_CHECK_FOR_PRIO2:
678     QBGT    FB_QOS_CHECK_FOR_PRIO3, RCV_TEMP_REG_1.b0, 4    ; PCP == 5/4
679     LDI        MII_RCV.qos_queue, 2-1    ; priority is 2, select queue 2
680     QBA        FB_QOS_DONE
681 FB_QOS_CHECK_FOR_PRIO3:
682     QBGT    FB_QOS_DONE, RCV_TEMP_REG_1.b0, 2    ; PCP == 3/2
683     LDI        MII_RCV.qos_queue, 3-1    ; priority is 3, select queue 3
684   QBA        FB_QOS_DONE
685 ; if PCP == 1/0, this priority 4, default queue already selected
686 FB_QOS_LOADED:
687 FB_QOS_DONE:
688 FB_DONE:
689     .else
690     .if $defined("PRU0")        
691 ; The naming of the QoS queue goes from 1..4, but we need to count from 0..3
692     LDI MII_RCV.qos_queue, 2-1  ; default (lowest priority) queue is 2 for PRU0 
693     .else
694     LDI MII_RCV.qos_queue, 4-1  ; default (lowest priority) queue is 4  for PRU1
695     .endif
696     
697 FB_QOS_APPLY_RULES:
698     LDI RCV_TEMP_REG_1.w0, 0x0081       ; 0x8100 --> indicates QOS tagged frame
699     QBNE        FB_QOS_DONE, Ethernet.TPID, RCV_TEMP_REG_1.w0
700         LSR     RCV_TEMP_REG_1.b0, Ethernet.TCI.x_b.b0, 5       ; extract PCP info
702     .if $defined("PRU0")        
703     QBGT        FB_QOS_DONE, RCV_TEMP_REG_1.b0, 4       ; PCP == 7/6
704     LDI MII_RCV.qos_queue, 1-1  ; highest priority is 1, select queue 1
705     .else
706     QBGT        FB_QOS_DONE, RCV_TEMP_REG_1.b0, 4       ; PCP == 7/6
707     LDI MII_RCV.qos_queue, 3-1  ; highest priority is 3, select queue 3
708     .endif
709     QBA         FB_QOS_DONE
710     
711 ; if PCP == 1/0, this priority 4, default queue already selected
712 FB_QOS_LOADED:
713 FB_QOS_DONE:
714 FB_DONE:
715     .endif ;TWO_PORT_CFG
716     
717     .if    $defined("TWO_PORT_CFG")
718     ;Check if cut-through bit is set ..if yes then push 10 more bytes in Tx_fifo and remain in Rx_Task itself
719     ; OPT : Below bytes can be pushed early in the Profinet
720     QBBC    FB_DONE_NORMAL, MII_RCV.tx_flags, cut_through_flag_shift    ; is cut-through flag set?
721   ; We enter the task with 14 bytes but here we always have 16 bytes even for non HSR frames
722     .if $defined("ICSS_REV1")
723     loop        FB_RCV_EndLoop_2, 5
724     MVIW        TX_DATA_WORD, *TX_DATA_POINTER  
725     M_PUSH_WORD_CMD
726     ADD TX_DATA_POINTER, TX_DATA_POINTER, 2     
727 FB_RCV_EndLoop_2:
728     .endif
729     .if $defined("ICSS_REV2")
730     MVID    TX_DATA_DOUBLE_WORD, *TX_DATA_POINTER
731     ADD        TX_DATA_POINTER, TX_DATA_POINTER, 4
732     .endif
733     
734     LDI        PREVIOUS_R18_RCV_BYTECOUNT, 16
735     ADD        CUT_THROUGH_BYTE_CNT, CUT_THROUGH_BYTE_CNT, 16
737 FB_DONE_NORMAL:    
738     .endif
739 ; Fill the rcv context with host/port queue base pointer, rd_ptr and wrk_pointer
740     QBNE        FB_CHECK_QUEUE_2, MII_RCV.qos_queue,  0
741     .if    $defined("TWO_PORT_CFG")
742     LDI        RX_CONTEXT_OFFSET, P0_Q1_RX_CONTEXT_OFFSET
744         .if    $defined("PRU0")    
745         LDI        RX_PORT_CONTEXT_OFFSET, P2_Q1_RX_CONTEXT_OFFSET
746         .else
747         LDI        RX_PORT_CONTEXT_OFFSET, P1_Q1_RX_CONTEXT_OFFSET
748         .endif    
749     .else
750     LDI RX_CONTEXT_OFFSET , HOST_Q1_RX_CONTEXT_OFFSET       ; Select queue based on QOS
751     .endif
752     QBA Initialize_rcv_context
753     
754     ;end_buffer_desc_offset
755 FB_CHECK_QUEUE_2:
756     QBNE        FB_CHECK_QUEUE_3, MII_RCV.qos_queue,  1
757     .if    $defined("TWO_PORT_CFG")
758     LDI        RX_CONTEXT_OFFSET, P0_Q2_RX_CONTEXT_OFFSET
759         .if    $defined("PRU0")    
760         LDI        RX_PORT_CONTEXT_OFFSET, P2_Q2_RX_CONTEXT_OFFSET
761         .else
762         LDI        RX_PORT_CONTEXT_OFFSET, P1_Q2_RX_CONTEXT_OFFSET
763         .endif
765     .else
766     LDI RX_CONTEXT_OFFSET , HOST_Q2_RX_CONTEXT_OFFSET       ; Select queue based on QOS
767     .endif
768     QBA Initialize_rcv_context
769     
770 FB_CHECK_QUEUE_3:
771     QBNE        FB_CHECK_QUEUE_4, MII_RCV.qos_queue,  2
772     .if    $defined("TWO_PORT_CFG")
774     LDI        RX_CONTEXT_OFFSET, P0_Q3_RX_CONTEXT_OFFSET
776         .if    $defined("PRU0")    
777         LDI        RX_PORT_CONTEXT_OFFSET, P2_Q3_RX_CONTEXT_OFFSET
778         .else
779         LDI        RX_PORT_CONTEXT_OFFSET, P1_Q3_RX_CONTEXT_OFFSET
780         .endif    
782     .else
783     LDI RX_CONTEXT_OFFSET , HOST_Q3_RX_CONTEXT_OFFSET       ; Select queue based on QOS
784     .endif
785     QBA Initialize_rcv_context
786     
787 FB_CHECK_QUEUE_4:
788     .if    $defined("TWO_PORT_CFG")
790     LDI        RX_CONTEXT_OFFSET, P0_Q4_RX_CONTEXT_OFFSET
791         .if    $defined("PRU0")    
792         LDI        RX_PORT_CONTEXT_OFFSET, P2_Q4_RX_CONTEXT_OFFSET
793         .else
794         LDI        RX_PORT_CONTEXT_OFFSET, P1_Q4_RX_CONTEXT_OFFSET
795         .endif    
796     .else
797     LDI RX_CONTEXT_OFFSET , HOST_Q4_RX_CONTEXT_OFFSET       ; Select queue based on QOS
798     .endif
799     
800 Initialize_rcv_context:
801     QBBC        FB_FILL_RCV_CONTEXT_PORT_QUEUE, MII_RCV.rx_flags, host_rcv_flag_shift
802     ; Read the RX Context of Host Port of 8 bytes
803     .if    $defined("TWO_PORT_CFG")
804     LBCO     &MII_RCV.base_buffer_index, PRU1_DMEM_CONST, RX_CONTEXT_OFFSET, 8
805     .else
806     LBCO        &MII_RCV.base_buffer_index, ICSS_SHARED_CONST, RX_CONTEXT_OFFSET, 8     
807     .endif
808     
809 FB_FILL_RCV_CONTEXT_PORT_QUEUE:
810     .if    $defined("TWO_PORT_CFG")
812     QBBC    FB_PKT_NOT_FORWARDED, MII_RCV.rx_flags, fwd_flag_shift
813     ; Read the RX Context of Port of 8 bytes
814     LBCO     &MII_RCV_PORT.base_buffer_index, PRU1_DMEM_CONST, RX_PORT_CONTEXT_OFFSET, 8
815 FB_PKT_NOT_FORWARDED:
816     .endif ;TWO_PORT_CFG
817     ; OPT: If R0.b0 is not changed then remove below instruction. it is to make sure at R0.b0 is 0
818     LDI R0.b0, SHIFT_NONE       
819     .if $defined("PRU0")        
820     XOUT        BANK1, &MII_RCV, $sizeof(MII_RCV)       ; store task parameters in parameter bank
821     .else
822     XOUT        BANK2, &MII_RCV, $sizeof(MII_RCV)       ; store task parameters in parameter bank
823     .endif
824     .if    $defined("TWO_PORT_CFG")
825     .if    $defined("PRU0")    
826     LDI        R0.b0, SHIFT_R14_TO_R0
827     XOUT    BANK0, &MII_RCV_PORT, $sizeof(MII_RCV_PORT)        ; store task parameters in parameter bank
828     .else
829     LDI        R0.b0, SHIFT_R14_TO_R4
830     XOUT    BANK0, &MII_RCV_PORT, $sizeof(MII_RCV_PORT)        ; store task parameters in parameter bank
831     .endif
834     QBBS    FN_RCV_NB, MII_RCV.tx_flags, cut_through_flag_shift
835     .endif ;TWO_PORT_CFG
836     
837     .if $defined("ICSS_DUAL_EMAC_BUILD")
838     ;The following check is required in case of firmware lag
839     ;when the firmware runs late compared to RX L2 FIFO.
840     ;This was being experienced in Profinet Switch and the same is possible here.
841     ;Haven't been able to reproduce this in EMAC.
842     XIN RX_L2_BANK0_ID, &R18, RANGE_R18_b0      
843     QBGT        FB_RCV_EXIT, R18.b0, 32 
844     LDI CURRENT_TASK_POINTER, TX_TASK_POINTER   
845     JMP FN_RCV_NB
846     .endif
847     
848 FB_RCV_EXIT:
849     JMP CALL_REG        
850     
851     
852 ;****************************************************************************
854 ;     NAME              : FN_RCV_NB
855 ;     DESCRIPTION       : receives the next 32Byte block of RX L2
856 ;     RETURNS           : 
857 ;     ARGS              : 
858 ;     USES              : 
859 ;     INVOKES           : 
861 ;****************************************************************************
862 FN_RCV_NB:
863     
864     ; for XIN, make sure that shift is set to 0
865     LDI R0.b0, SHIFT_NONE       
866     ; restore task parameters in parameter bank
867     .if $defined("PRU0")        
868     XIN BANK1, &MII_RCV, $sizeof(MII_RCV)       
869     .else
870     XIN BANK2, &MII_RCV, $sizeof(MII_RCV)       
871     .endif
872     .if    $defined("TWO_PORT_CFG")
873     ;parameters for Port Receive
874     ; OPT: Move it after the XIN of data
875     .if    $defined("PRU0")
876     LDI        R0.b0, SHIFT_R14_TO_R0
877     XIN        BANK0, &MII_RCV_PORT, $sizeof(MII_RCV_PORT)
878     .else
879     LDI        R0.b0, SHIFT_R14_TO_R4
880     XIN        BANK0, &MII_RCV_PORT, $sizeof(MII_RCV_PORT)
881     .endif    
882     .endif
883     ; this task is getting called by MS, first check is to see if we are currently receiving
884     QBBC        NB_DONE_NO_PARAM_STORE, R23, Rcv_active
885     QBBS        NB_DONE_NO_PARAM_STORE, MII_RCV.rx_flags, rx_frame_error_shift
886     
887 FN_RCV_NB_CT_NO_RxEOF:          ; If Rx EOF has not come yet then directly return here ..saves 6 cycles and that helps in finding faster
888                                 ;     that L2 fifo has received 32 or 64 bytes ..which helps in calling NB_PROCESS_32BYTES early
889     ; depending on the bank index, we load bank 0 or bank 1
890     QBBS        NB_XIN_UPPER_BANK, MII_RCV.rx_flags, rx_bank_index_shift
891     
892 NB_XIN_LOWER_BANK:
893     ; OPT: Just one XIN is needed
894     XIN RX_L2_BANK0_ID, &R18, RANGE_R18_b0      
895     XIN RX_L2_BANK0_ID, &R2, RANGE_R2_R13       ; XIN RX L2 bank 0
896     QBA NB_CHECK_AMOUNT_OF_BYTES
897 NB_XIN_UPPER_BANK:
898     ; OPT: Just one XIN is needed
899     XIN RX_L2_BANK1_ID, &R18, RANGE_R18_b0      
900     XIN RX_L2_BANK1_ID, &R2, RANGE_R2_R13       ; XIN RX L2 bank 1
901     
902 NB_CHECK_AMOUNT_OF_BYTES:
903     .if $defined("ICSS_SWITCH_BUILD")
904     QBBC    check_for_32bytes, MII_RCV.tx_flags, cut_through_flag_shift    ;MII_RCV.tx_flags.cut_through_flag
905     SUB        RCV_TEMP_REG_1, R18_RCV_BYTECOUNT, PREVIOUS_R18_RCV_BYTECOUNT
906     .if $defined("ICSS_REV1")
907     QBGT        NB_DONE, RCV_TEMP_REG_1, 2      
908     
909 NB_PUSH_NEXT_WORD_TO_FIFO:
910     QBEQ        check_for_32bytes, R1.b3, 0x28  
911     ADD PREVIOUS_R18_RCV_BYTECOUNT, PREVIOUS_R18_RCV_BYTECOUNT, 2       
912     MVIW        TX_DATA_WORD, *R1.b3    
913     M_PUSH_WORD_CMD
914     ADD CUT_THROUGH_BYTE_CNT, CUT_THROUGH_BYTE_CNT, 2   
915     ADD R1.b3, R1.b3, 2 
916     SUB RCV_TEMP_REG_1, RCV_TEMP_REG_1, 2       
917     QBLE        NB_PUSH_NEXT_WORD_TO_FIFO, RCV_TEMP_REG_1, 2    
918     .endif
919     .if $defined("ICSS_REV2")
920     QBGT    NB_DONE, RCV_TEMP_REG_1, 4
921     
922 NB_PUSH_NEXT_DOUBLE_WORD_TO_FIFO:
923     QBEQ    check_for_32bytes, R1.b3, 0x28
924     ADD        PREVIOUS_R18_RCV_BYTECOUNT, PREVIOUS_R18_RCV_BYTECOUNT, 4
925     MVID    TX_DATA_DOUBLE_WORD, *R1.b3
926     ADD        CUT_THROUGH_BYTE_CNT, CUT_THROUGH_BYTE_CNT, 4
927     ADD        R1.b3, R1.b3, 4
928     SUB        RCV_TEMP_REG_1, RCV_TEMP_REG_1, 4
929     QBLE    NB_PUSH_NEXT_DOUBLE_WORD_TO_FIFO,     RCV_TEMP_REG_1, 4
930     .endif
931 check_for_32bytes:    
932     .endif
933     QBBS        NB_CHECK_AMOUNT_OF_BYTES_BIGGER_32_BANK1, MII_RCV.rx_flags, rx_bank_index_shift   ; check which bank to read
934     
935     ; for bank 0, R18.b0 >=32 bytes
936     QBGT        NB_DONE, R18_RCV_BYTECOUNT, 32  
937     ;LDI        R1.b3, buffer_ptr
938     QBA NB_PROCESS_32BYTES
939     
940 NB_CHECK_AMOUNT_OF_BYTES_BIGGER_32_BANK1:
941     
942     ; for bank 1, R18.b0 <32 bytes
943     QBLE        NB_DONE, R18_RCV_BYTECOUNT, 32
944     
945     .if $defined("ICSS_SWITCH_BUILD")
946     QBBC    NB_PROCESS_32BYTES_CT, MII_RCV.tx_flags, cut_through_flag_shift    ;MII_RCV.tx_flags.cut_through_flag
947     QBEQ    NB_PROCESS_32BYTES_CT, R1.b3, 0x28
948     .if $defined("ICSS_REV1")
949     MVIW        TX_DATA_WORD, *R1.b3    
950     M_PUSH_WORD_CMD
951     ADD CUT_THROUGH_BYTE_CNT, CUT_THROUGH_BYTE_CNT, 2   
952     .endif
953     .if $defined("ICSS_REV2")
954     MVID    TX_DATA_DOUBLE_WORD, *R1.b3
955     ADD        CUT_THROUGH_BYTE_CNT, CUT_THROUGH_BYTE_CNT, 4
956     .endif
957 NB_PROCESS_32BYTES_CT:
958     .endif
959     LDI PREVIOUS_R18_RCV_BYTECOUNT, 0x00        
960     
961 ;***********************************
962 ; 32 bytes handling, no cut through
963 ;***********************************
964 NB_PROCESS_32BYTES:     ; 32 Bytes of new data are in the buffer
965     
966     LDI R1.b3, buffer_ptr       ; load the buffer pointer       
967     
968 NB_PROCESS_CHECK_BYTE_CNTR:
969     ; if this is the first 32 bytes of data, need to init the buffer queues
970     QBNE        NB_PROCESS_32BYTES_CHECK_FLAGS, MII_RCV.byte_cntr, 0
971     
972     .if $defined("ICSS_SWITCH_BUILD")
973     .if    $defined("TWO_PORT_CFG")
974     QBNE    NB_PROCESS_32BYTES_CHECK_FLAGS, MII_RCV_PORT.byte_cntr, 0
975     .endif ;TWO_PORT_CFG    
976  
977   QBBC    NB_PROCESS_32BYTES_INIT_PORT_QUEUE, MII_RCV.rx_flags, host_rcv_flag_shift    ;MII_RCV.rx_flags.host_rcv_flag
978   
979 NB_PROCESS_32BYTES_INIT_HOST_QUEUE:
980     .if    $defined("TWO_PORT_CFG")
981     LDI        RCV_TEMP_REG_3.w0, P0_QUEUE_DESC_OFFSET
982     LDI        RCV_TEMP_REG_3.w2, P0_COL_QUEUE_DESC_OFFSET
983     ; Calling for host queue
984     LDI        RCV_TEMP_REG_1.b1, 0
985     ; get queue
986     JAL CALL_REG, FN_QUEUE_ARBITRATION  
987     ;RCV_TEMP_REG_1.b0 --> OUTPUT: returns information if the queue has been 
988     ;aquired successful ((0-failed to aquire; 1-queue; 2-collision)
989     QBNE    NB_PROCESS_32BYTES_INIT_HOST_QUEUE_OK, RCV_TEMP_REG_1.b0, 0 
990     ; OPT: Can't fail
991 NB_PROCESS_32BYTES_INIT_HOST_QUEUE_FAILED:
992     ; clear host receive flag
993     CLR        MII_RCV.rx_flags, MII_RCV.rx_flags, host_rcv_flag_shift
994   
995     ; ToDo: Do we need to add code for statistics? We should never fail to aquire the queue or the coll-queue
996     QBA        NB_PROCESS_32BYTES_INIT_PORT_QUEUE
997 NB_PROCESS_32BYTES_INIT_HOST_QUEUE_OK:
998     ;CLR        MII_RCV.rx_flags.host_collision_queue_selected         ; ToDo: this could be removed when parameter are init with 0 at b/o frame
999     ; 2-collision selected?
1000     QBNE    NB_PROCESS_32BYTES_INIT_HOST_QUEUE_NO_COLL_SELECTED, RCV_TEMP_REG_1.b0, COLLISION_AQUIRED
1001      
1002     ; Initialize the RCV CONTEXT with the data of Host Collision Queue
1003     SET        MII_RCV.rx_flags, MII_RCV.rx_flags, host_collision_queue_selected_shift
1004     LDI        RCV_TEMP_REG_1.w0, COL_RX_CONTEXT_P0_OFFSET_ADDR
1005     LBCO    &MII_RCV.buffer_index, PRU1_DMEM_CONST, RCV_TEMP_REG_1.w0, 10
1006     .endif ;TWO_PORT_CFG
1007 NB_PROCESS_32BYTES_INIT_HOST_QUEUE_NO_COLL_SELECTED:
1008     .endif
1009     ;Initialize the wrkng_wr_ptr and rd_ptr here as the other PRU might have changed them between Now and RCV_FB
1010     LBCO        &RCV_QUEUE_DESC_REG, QUEUE_DESP_BASE, MII_RCV.rcv_queue_pointer, 4      
1011     AND MII_RCV.rd_ptr , RCV_QUEUE_DESC_REG.rd_ptr , RCV_QUEUE_DESC_REG.rd_ptr
1012     AND MII_RCV.wrkng_wr_ptr , RCV_QUEUE_DESC_REG.wr_ptr , RCV_QUEUE_DESC_REG.wr_ptr
1014     ; Rx interrupt pacing
1015     ; If the rd_ptr & wr_ptr are equal => queue is empty => SET HOST_QUEUE_EMPTY_STATUS 
1016     QBNE    HOST_QUEUE_NOT_EMPTY, RCV_QUEUE_DESC_REG.rd_ptr, RCV_QUEUE_DESC_REG.wr_ptr
1017     SET     R22, R22, HOST_QUEUE_EMPTY_STATUS
1019 HOST_QUEUE_NOT_EMPTY:
1020     .if    $defined("TWO_PORT_CFG")
1021     QBBS    NB_RCV_CONTEXT_INITIALIZED_WITH_COLLISION, MII_RCV.rx_flags, host_collision_queue_selected_shift
1022     .endif ;TWO_PORT_CFG
1023     ; Compute the adress in L3 RAM where the packet is received
1024     SUB RCV_BUFFER_DESC_OFFSET, MII_RCV.wrkng_wr_ptr, MII_RCV.base_buffer_desc_offset   
1025     LSL RCV_BUFFER_DESC_OFFSET, RCV_BUFFER_DESC_OFFSET, 3       
1026     ADD MII_RCV.buffer_index, MII_RCV.base_buffer_index, RCV_BUFFER_DESC_OFFSET 
1027     
1028     .if $defined("ICSS_SWITCH_BUILD")
1029 NB_RCV_CONTEXT_INITIALIZED_WITH_COLLISION:    
1031 NB_PROCESS_32BYTES_INIT_PORT_QUEUE:
1032     ; check if selected    
1033     .if    $defined("TWO_PORT_CFG")
1035   QBBC    NB_PROCESS_32BYTES_CHECK_FLAGS, MII_RCV.rx_flags, fwd_flag_shift
1036   
1037     .if    $defined("PRU0")    
1038     LDI        RCV_TEMP_REG_3.w0, P2_QUEUE_DESC_OFFSET
1039     LDI        RCV_TEMP_REG_3.w2, P2_COL_QUEUE_DESC_OFFSET
1040     .else
1041     LDI        RCV_TEMP_REG_3.w0, P1_QUEUE_DESC_OFFSET
1042     LDI        RCV_TEMP_REG_3.w2, P1_COL_QUEUE_DESC_OFFSET
1043     .endif    
1044     ; get queue
1045     ;CALL    FN_QUEUE_ARBITRATION_PORT_RCV
1046     ; Calling for port queue
1047     LDI        RCV_TEMP_REG_1.b1, 1
1048     JAL CALL_REG, FN_QUEUE_ARBITRATION  
1049     ;RCV_TEMP_REG_1.b0 --> OUTPUT: returns information if the queue has 
1050     ;been acquired successful ((0-failed to acquire; 1-queue; 2-collision)
1051     QBNE    NB_PROCESS_32BYTES_INIT_PORT_QUEUE_OK, RCV_TEMP_REG_1.b0, 0 
1052     ; OPT: Can't fail
1053 NB_PROCESS_32BYTES_INIT_PORT_QUEUE_FAILED:
1054   
1055   
1056   ; clear port receive flag
1057     CLR        MII_RCV.rx_flags, MII_RCV.rx_flags, fwd_flag_shift
1058     ; ToDo: Do we need to add code for statistics? We should never fail to aquire the queue or the coll-queue
1059     QBA        NB_PROCESS_32BYTES_CHECK_FLAGS
1060 NB_PROCESS_32BYTES_INIT_PORT_QUEUE_OK:
1061     ;CLR        MII_RCV.rx_flags.port_collision_queue_selected         ; ToDo: this could be removed when parameter are init with 0 at b/o frame
1062     ; 2-collision selected?
1063     QBNE    NB_PROCESS_32BYTES_INIT_PORT_QUEUE_NO_COLL_SELECTED, RCV_TEMP_REG_1.b0, 2
1064     
1065     ; Initialize the RCV CONTEXT with the data of Port Collision Queue
1066     SET        MII_RCV.rx_flags, MII_RCV.rx_flags, port_collision_queue_selected_shift
1067     .if    $defined("PRU0")
1068     LDI        RCV_TEMP_REG_1.w0, COL_RX_CONTEXT_P2_OFFSET_ADDR
1069     .else
1070     LDI        RCV_TEMP_REG_1.w0, COL_RX_CONTEXT_P1_OFFSET_ADDR
1071     .endif    
1072     LBCO    &MII_RCV_PORT.buffer_index, PRU1_DMEM_CONST, RCV_TEMP_REG_1.w0, 10
1073     
1074 NB_PROCESS_32BYTES_INIT_PORT_QUEUE_NO_COLL_SELECTED:
1075     ;Initialize the wrkng_wr_ptr and rd_ptr here as the other PRU might have changed them between Now and RCV_FB
1076     LBCO    &RCV_QUEUE_DESC_REG, QUEUE_DESP_BASE, MII_RCV_PORT.rcv_queue_pointer, 4
1077     AND MII_RCV_PORT.rd_ptr , RCV_QUEUE_DESC_REG.rd_ptr , RCV_QUEUE_DESC_REG.rd_ptr     ;Warning: converted from MOV
1078     AND MII_RCV_PORT.wrkng_wr_ptr , RCV_QUEUE_DESC_REG.wr_ptr , RCV_QUEUE_DESC_REG.wr_ptr       ;Warning: converted from MOV
1079     QBBS    NB_RCV_PORT_CONTEXT_INITIALIZED_WITH_COLLISION, MII_RCV.rx_flags, port_collision_queue_selected_shift
1080     ; Compute the adress in L3 RAM where the packet is received
1081     SUB        RCV_BUFFER_DESC_OFFSET, MII_RCV_PORT.wrkng_wr_ptr, MII_RCV_PORT.base_buffer_desc_offset
1082     LSL        RCV_BUFFER_DESC_OFFSET, RCV_BUFFER_DESC_OFFSET, 3
1083     ADD        MII_RCV_PORT.buffer_index, MII_RCV_PORT.base_buffer_index, RCV_BUFFER_DESC_OFFSET
1084     
1085 NB_RCV_PORT_CONTEXT_INITIALIZED_WITH_COLLISION:
1086     .endif ;TWO_PORT_CFG
1087     .endif ;ICSS_SWITCH_BUILD
1088     
1089 NB_PROCESS_32BYTES_CHECK_FLAGS:
1090     
1091     .if $defined("ICSS_SWITCH_BUILD")
1092     QBBC    NB_PROCESS_32BYTES_CHECK_FWD_FLAG, MII_RCV.rx_flags, host_rcv_flag_shift     ; MII_RCV.rx_flags.host_rcv_flag
1093     .endif
1095     QBGE    LESS_THAN_64_BYTES_RCVD, MII_RCV.byte_cntr,  32
1096     QBA        EXIT_PREPROCESSING_NB
1097     
1098 LESS_THAN_64_BYTES_RCVD:
1099     ;between 32 and 64 bytes
1100     QBGE    LESS_THAN_32_BYTES_RCVD, MII_RCV.byte_cntr,  0
1101     
1102     .if $defined(PTP)
1103     LDI    RCV_TEMP_REG_3.w2, PTP_IPV4_UDP_E2E_ENABLE
1104     LBCO   &RCV_TEMP_REG_3.b2, ICSS_SHARED_CONST, RCV_TEMP_REG_3.w2, 1
1105     QBEQ   PTP_NOT_ENABLED_RX_B2, RCV_TEMP_REG_3.b2, 0
1106     QBBC   PTP_NOT_ENABLED_RX_B2, R22, RX_IS_UDP_PTP_BIT
1107     CLR    R22, R22, RX_IS_UDP_PTP_BIT
1108     JAL    RCV_TEMP_REG_3.w2, FN_TIMESTAMP_GPTP_PACKET
1109     JAL    RCV_TEMP_REG_3.w2, FN_CHECK_AND_CLR_PTP_FWD_FLAG
1110 PTP_NOT_ENABLED_RX_B2:
1111     .endif    ; "PTP"
1112     QBA       EXIT_PREPROCESSING_NB
1113     
1114 LESS_THAN_32_BYTES_RCVD:
1116     .if $defined(PTP)
1117     ;we don't want to execute this for UDP frames, since this will be executed again later
1118     QBBS    PTP_SKIP_EARLY_TS_FOR_UDP_1, R22, RX_IS_UDP_PTP_BIT
1119     JAL     RCV_TEMP_REG_3.w2, FN_CHECK_AND_CLR_PTP_FWD_FLAG_L2
1120     JAL     RCV_TEMP_REG_3.w2, FN_TIMESTAMP_GPTP_PACKET
1121 PTP_SKIP_EARLY_TS_FOR_UDP_1:
1122     .endif    ;PTP 
1124 EXIT_PREPROCESSING_NB:
1125     SBCO    &Ethernet, L3_OCMC_RAM_CONST, MII_RCV.buffer_index, 32  
1126     ADD MII_RCV.byte_cntr , MII_RCV.byte_cntr ,  32     ; increment byte count by 32
1128     ; Compare current wrk pointer to top_most queue desc pointer ..check for wrap around
1129     QBNE        RCV_NB_NO_QUEUE_WRAP, MII_RCV.wrkng_wr_ptr, MII_RCV.top_most_buffer_desc_offset
1130     AND MII_RCV.wrkng_wr_ptr , MII_RCV.base_buffer_desc_offset , MII_RCV.base_buffer_desc_offset
1131     AND MII_RCV.buffer_index , MII_RCV.base_buffer_index , MII_RCV.base_buffer_index
1132     QBA RCV_NB_QUEUE_WRAPPED
1133 RCV_NB_NO_QUEUE_WRAP:
1134     ADD MII_RCV.buffer_index, MII_RCV.buffer_index,  32
1135     ADD MII_RCV.wrkng_wr_ptr,  MII_RCV.wrkng_wr_ptr,  4
1136     
1137 RCV_NB_QUEUE_WRAPPED:
1138     
1139     ; Prepare for next call of RCV_NB ..whether next 32 bytes can be received or not
1140     QBNE        NB_PROCESS_32BYTES_CHECK_FLAGS_QUEUE_NOT_FULL, MII_RCV.wrkng_wr_ptr, MII_RCV.rd_ptr
1141     
1142     CLR MII_RCV.rx_flags , MII_RCV.rx_flags , host_rcv_flag_shift
1143     SET MII_RCV.rx_flags_extended , MII_RCV.rx_flags_extended , host_queue_overflow_shift
1144     .if $defined("ICSS_DUAL_EMAC_BUILD")
1145     ;For EMAC mode, set rx_frame_error bit. This saves cycles in FN_RCV_LB.
1146     SET MII_RCV.rx_flags , MII_RCV.rx_flags , 4 
1147     .endif
1148     
1149 NB_PROCESS_32BYTES_CHECK_FLAGS_QUEUE_NOT_FULL:
1150     .if $defined("ICSS_SWITCH_BUILD")
1151 NB_PROCESS_32BYTES_CHECK_FWD_FLAG:
1152     .if    $defined("TWO_PORT_CFG")
1154     QBBC    NB_PROCESS_32BYTES_CHECK_FLAG_DONE, MII_RCV.rx_flags, 1    ;MII_RCV.rx_flags.fwd_flag
1155     SBCO    &Ethernet, L3_OCMC_RAM_CONST, MII_RCV_PORT.buffer_index, 32
1156     ADD        MII_RCV_PORT.byte_cntr, MII_RCV_PORT.byte_cntr, 32
1158     ; Compare current wrk pointer to top_most queue desc pointer ..check for wrap around
1159     QBNE    RCV_NB_PORT_NO_QUEUE_WRAP, MII_RCV_PORT.wrkng_wr_ptr, MII_RCV_PORT.top_most_buffer_desc_offset
1160     AND MII_RCV_PORT.wrkng_wr_ptr , MII_RCV_PORT.base_buffer_desc_offset , MII_RCV_PORT.base_buffer_desc_offset ;Warning: converted from MOV
1161     AND MII_RCV_PORT.buffer_index , MII_RCV_PORT.base_buffer_index , MII_RCV_PORT.base_buffer_index     ;Warning: converted from MOV
1162     QBA        RCV_NB_PORT_QUEUE_WRAPPED
1163 RCV_NB_PORT_NO_QUEUE_WRAP:
1164     ADD        MII_RCV_PORT.buffer_index,     MII_RCV_PORT.buffer_index, 32
1165     ADD        MII_RCV_PORT.wrkng_wr_ptr,  MII_RCV_PORT.wrkng_wr_ptr, 4
1166 RCV_NB_PORT_QUEUE_WRAPPED:
1168     ; Prepare for next call of RCV_NB ..whether next 32 bytes can be received or not
1169     QBNE    NB_PROCESS_32BYTES_CHECK_FWD_FLAG_NOT_FULL, MII_RCV_PORT.wrkng_wr_ptr, MII_RCV_PORT.rd_ptr
1170     CLR        MII_RCV.rx_flags, MII_RCV.rx_flags, fwd_flag_shift
1171     SET        MII_RCV.rx_flags_extended, MII_RCV.rx_flags_extended, port_queue_overflow_shift
1172     
1173 NB_PROCESS_32BYTES_CHECK_FWD_FLAG_NOT_FULL:
1175 NB_PROCESS_32BYTES_CHECK_FLAG_DONE:
1176     .endif ;TWO_PORT_CFG
1177     
1178 NB_PROCESS_DONE:
1179     .endif
1180     XOR         MII_RCV.rx_flags, MII_RCV.rx_flags, (1<<rx_bank_index_shift)    ; toggle rx_bank_index flag
1181     
1182 NB_DONE:
1183     
1184     ; restore call register pointer
1185     AND CALL_REG , L1_CALL_REG , L1_CALL_REG
1186     
1187     ; store task parameters from parameter bank
1188 NB_STORE_CONTEXT:
1189     LDI R0.b0, SHIFT_NONE       
1190     .if $defined("PRU0")        
1191     XOUT        BANK1, &MII_RCV, $sizeof(MII_RCV)       
1192     .else
1193     XOUT        BANK2, &MII_RCV, $sizeof(MII_RCV)       
1194     .endif
1195     
1196     .if $defined("ICSS_SWITCH_BUILD")
1197     .if $defined("TWO_PORT_CFG")
1198     .if $defined("PRU0")
1199     LDI        R0.b0, SHIFT_R14_TO_R0
1200     XOUT    BANK0, &MII_RCV_PORT, $sizeof(MII_RCV_PORT)
1201     .else
1202     LDI        R0.b0, SHIFT_R14_TO_R4
1203     XOUT    BANK0, &MII_RCV_PORT, $sizeof(MII_RCV_PORT)
1204     .endif
1205     QBBS    NB_PROCESS_CUT_THROUGH, MII_RCV.tx_flags, cut_through_flag_shift    ;MII_RCV.tx_flags.cut_through_flag
1206     .endif ;TWO_PORT_CFG
1207     .endif
1208     
1209     .if $defined("ICSS_REV1")   
1210     M_RCV_RX_EOF_CHECK_ICSS_REV1        ; check for EOF for REV1
1211     .endif
1212     .if $defined("ICSS_REV2")   
1213     M_RCV_RX_EOF_CHECK_ICSS_REV2        ; check for EOF for REV2
1214     .endif
1216 NB_DONE_NO_PARAM_STORE:
1217     JMP         TASK_EXECUTION_FINISHED
1218     
1219 process_rx_eof_rx_nb:
1220     JMP         FN_RCV_LB
1221     
1222     .if $defined("ICSS_SWITCH_BUILD")
1223     .if    $defined("TWO_PORT_CFG")
1224 NB_PROCESS_CUT_THROUGH:    
1225     ; check for RX EOF condition
1226     .if $defined("ICSS_REV1")
1227     .if $defined("PRU0")        
1228     QBBC        FN_RCV_NB_CT_NO_RxEOF, R31, 30   ;replaced: QBBC        FN_RCV_NB_CT_NO_RxEOF, R31.t30 
1229     .else
1230     QBBC        FN_RCV_NB_CT_NO_RxEOF, R31, 31   ;replaced: QBBC        FN_RCV_NB_CT_NO_RxEOF, R31.t31 
1231     .endif
1232     .endif
1233     .if $defined("ICSS_REV2")
1234     QBBC    FN_RCV_NB_CT_NO_RxEOF, R31, 20        ; Port0 Rx EOF
1235     .endif
1237 FN_RCV_NB_CT_RxEOF:
1238     QBBS    CT_NB_XIN_UPPER_BANK, MII_RCV.rx_flags, rx_bank_index_shift    ;MII_RCV.rx_flags.rx_bank_index
1240 CT_NB_XIN_LOWER_BANK:
1241     
1242     XIN        RX_L2_BANK0_ID, &R18, RANGE_R18_b0
1243     XIN        RX_L2_BANK0_ID, &R2, RANGE_R2_R13                ; XIN RX L2 bank 0
1244     
1245     QBA        CT_NB_CHECK_AMOUNT_OF_BYTES
1246 CT_NB_XIN_UPPER_BANK:    
1247     
1248     XIN        RX_L2_BANK1_ID, &R18, RANGE_R18_b0
1249     XIN        RX_L2_BANK1_ID, &R2, RANGE_R2_R13                ; XIN RX L2 bank 1
1250     
1251 CT_NB_CHECK_AMOUNT_OF_BYTES:    
1252     ; Put the remaining bytes in Tx_FIFO at this point of time itself
1253     AND        RCV_TEMP_REG_1.b0, CUT_THROUGH_BYTE_CNT, 0x003f
1254     ; Below code added to fix a bug when for a 65 byte packet R18 has 1 but cut_through_byte_cnt is 62.
1255     ; Check whether cut_through_byte_cnt is more than R18 count
1256     QBGE    CT_R18_IS_GREATER_OR_EQUAL, RCV_TEMP_REG_1.b0, R18_RCV_BYTECOUNT
1257     LDI        RCV_TEMP_REG_2.b0, 64   ; Subtract from 64 bytes
1258     SUB        RCV_TEMP_REG_1.b0, RCV_TEMP_REG_2.b0, RCV_TEMP_REG_1.b0
1259     ; L2 FIFO wrapped around but few bytes of upper bank didn't get pushed in fifo. It is possible that RX EOF is detected before pushing
1260     ; the last two bytes and R18 gets wrapped around by the time we reach here
1261     ADD        RCV_TEMP_REG_1.b0, RCV_TEMP_REG_1.b0, R18_RCV_BYTECOUNT
1262     QBA        CT_R18_IS_LESS
1263 CT_R18_IS_GREATER_OR_EQUAL:    
1264     
1265     SUB        RCV_TEMP_REG_1.b0, R18_RCV_BYTECOUNT, RCV_TEMP_REG_1.b0
1267 CT_R18_IS_LESS:
1268     .if $defined("ICSS_REV1")
1269     ;QBEQ       CT_PUSH_LB_LASTBYTE_nb, RCV_TEMP_REG_1.b0,  1
1270     LSR loop_cnt, RCV_TEMP_REG_1.b0, 1  
1271     ; OPT: Use function for the loop below
1272     ;QBEQ       ct_assert_eof_nb, loop_cnt, 0x0000
1273     LOOP        CT_NB_ENDLOOP, loop_cnt 
1274     MVIW        TX_DATA_WORD, *TX_DATA_POINTER  
1275     M_PUSH_WORD_CMD
1276     ADD TX_DATA_POINTER, TX_DATA_POINTER, 2     
1277 CT_NB_ENDLOOP:
1278     QBBC        ct_assert_eof_nb, RCV_TEMP_REG_1.b0, 0  
1279 CT_PUSH_LB_LASTBYTE_nb:
1280     MVIB        TX_DATA_BYTE, *R1.b3    
1281     M_PUSH_BYTE
1282 ct_assert_eof_nb:
1283     ;M_PUSH_TX_EOF
1284     .endif
1285     .if $defined("ICSS_REV2")
1286     LSR        loop_cnt, RCV_TEMP_REG_1.b0, 2
1288     loop    CT_NB_ENDLOOP, loop_cnt
1289     MVID    TX_DATA_DOUBLE_WORD, *TX_DATA_POINTER
1290     ADD        TX_DATA_POINTER, TX_DATA_POINTER, 4
1291 CT_NB_ENDLOOP:
1293     AND        RCV_TEMP_REG_2.b0, RCV_TEMP_REG_1.b0, 0x03
1294     QBEQ    ct_assert_eof_nb, RCV_TEMP_REG_2.b0, 0
1295     QBEQ    CT_PUSH_LB_LASTBYTE_nb, RCV_TEMP_REG_2.b0, 1
1296     MVIW    TX_DATA_WORD, *TX_DATA_POINTER
1297     ADD        TX_DATA_POINTER, TX_DATA_POINTER, 2
1298     QBEQ    ct_assert_eof_nb, RCV_TEMP_REG_2.b0, 2
1299 CT_PUSH_LB_LASTBYTE_nb:
1300     MVIB    TX_DATA_BYTE, *R1.b3
1302 ct_assert_eof_nb:    
1303     ; Insert the TX_EOF for outgoing frame
1304     LDI        R31.w2, 0x2000
1305     .endif
1306     ADD        CUT_THROUGH_BYTE_CNT, CUT_THROUGH_BYTE_CNT, RCV_TEMP_REG_1.b0
1307 ct_deassert_ct:    
1308 SKIP_CRC_PUSH:    
1310     LDI        R0.b0, SHIFT_NONE
1311     .if    $defined("PRU0")
1312     XOUT    BANK1, &MII_RCV, $sizeof(MII_RCV)
1313     .else
1314     XOUT    BANK2, &MII_RCV, $sizeof(MII_RCV)
1315     .endif
1316     CLR     R22, R22, PACKET_TX_ALLOWED
1317 ;Check for CRC
1318     LDI RCV_TEMP_REG_2.w0, 0x0204       
1319     LBCO        &RCV_TEMP_REG_1, ICSS_INTC_CONST, RCV_TEMP_REG_2.w0, 4  
1320     .if $defined("PRU0")        
1321     QBBC        NO_CRC_ERROR_CT, RCV_TEMP_REG_1, 4       ;replaced: QBBC    NO_CRC_ERROR_CT, RCV_TEMP_REG_1.t4 
1322     .else
1323     QBBC        NO_CRC_ERROR_CT, RCV_TEMP_REG_1, 16      ;replaced: QBBC    NO_CRC_ERROR_CT, RCV_TEMP_REG_1.t16 
1324     .endif
1325     LDI RCV_TEMP_REG_3 , RX_CRC_COUNT_OFFSET
1326     
1327     ;Add to statistics counter
1328     LBCO        &RCV_TEMP_REG_1, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4       
1329     ADD RCV_TEMP_REG_1, RCV_TEMP_REG_1, 1       
1330     SBCO        &RCV_TEMP_REG_1, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4       
1331 NO_CRC_ERROR_CT:
1332     .endif ;TWO_PORT_CFG
1333     .endif ;ICSS_SWITCH_BUILD
1334     
1335 ;****************************************************************************
1337 ;     NAME                      : FN_RCV_LB
1338 ;     DESCRIPTION       : receives the last block(s) of RX L2
1339 ;     RETURNS           : 
1340 ;     ARGS                      : 
1341 ;     USES              : 
1342 ;     INVOKES           : 
1344 ;****************************************************************************
1345 FN_RCV_LB:
1346     
1347     ; Check if RCV_Active is set. If not drop the frame. It handles the case of undersize errors
1348     QBBS        RCV_LB_PROCESS_NORMAL, R23, Rcv_active
1349     
1350 LB_CHECK_ERRORS:
1351     ;Short frame received then increment the error offset statistics
1352     LDI RCV_TEMP_REG_3 , RX_ERROR_OFFSET
1353     LBCO        &RCV_TEMP_REG_2, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4       
1354     ADD RCV_TEMP_REG_2, RCV_TEMP_REG_2, 1       
1355     SBCO        &RCV_TEMP_REG_2, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4       
1356     .if $defined("ICSS_DUAL_EMAC_BUILD")
1357     .if $defined("HALF_DUPLEX_ENABLED") 
1358     ;check R31 error
1359     QBBC        NO_R31_ERROR, R31, 19       ; if cleared so no error and continue normal operation
1360     ;else clear the error
1361     M_CMD16 D_RX_ERROR_CLEAR        ; else clear error flag
1362     
1363 NO_R31_ERROR:
1364     ;check for SFD Errors
1365     .if $defined("PRU0")        
1366     LBCO        &RCV_TEMP_REG_3.b0, MII_RT_CFG_CONST, ICSS_MIIRT_RXERR0, 1     ;read the PRUSS_MII_RT_RX_ERR0 register          
1367     QBBC        CHECK_FOR_SHORT_SFD1, RCV_TEMP_REG_3, 1         ; check if not error then jump else count stats
1368     ;clear error and writeback
1369     SET RCV_TEMP_REG_3 , RCV_TEMP_REG_3 , 1 
1370     SBCO        &RCV_TEMP_REG_3.b0, MII_RT_CFG_CONST, ICSS_MIIRT_RXERR0, 1      
1371     QBA     COUNT_SFD_ERROR1
1372 CHECK_FOR_SHORT_SFD1:            
1373     QBBC        NO_PREAMBLE_ERROR, RCV_TEMP_REG_3, 0       ; check if not error then jump else count stats 
1374     ;clear error and writeback
1375     SET RCV_TEMP_REG_3 , RCV_TEMP_REG_3 , 0 
1376     SBCO        &RCV_TEMP_REG_3.b0, MII_RT_CFG_CONST, ICSS_MIIRT_RXERR0, 1      
1377     .else
1378     LBCO        &RCV_TEMP_REG_3.b0, MII_RT_CFG_CONST, ICSS_MIIRT_RXERR1, 1     ;read the PRUSS_MII_RT_RX_ERR0 register
1379     QBBC        CHECK_FOR_SHORT_SFD1, RCV_TEMP_REG_3, 1         ; check if not error then jump else count stats
1380     ;clear error and writeback
1381     SET RCV_TEMP_REG_3 , RCV_TEMP_REG_3 , 1 
1382     SBCO        &RCV_TEMP_REG_3.b0, MII_RT_CFG_CONST, ICSS_MIIRT_RXERR1, 1      
1383     QBA     COUNT_SFD_ERROR1
1384 CHECK_FOR_SHORT_SFD1:            
1385     QBBC        NO_PREAMBLE_ERROR, RCV_TEMP_REG_3, 0        ; check if not error then jump else count stats
1386     ;clear error and writeback
1387     SET RCV_TEMP_REG_3 , RCV_TEMP_REG_3 , 0 
1388     SBCO        &RCV_TEMP_REG_3.b0, MII_RT_CFG_CONST, ICSS_MIIRT_RXERR1, 1      
1389     .endif
1390     
1391 COUNT_SFD_ERROR1:
1392         ;increment and store the count
1393     LDI RCV_TEMP_REG_3 , SFD_ERROR_OFFSET
1394     LBCO        &RCV_TEMP_REG_2, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4       
1395     ADD RCV_TEMP_REG_2, RCV_TEMP_REG_2, 1       
1396     SBCO        &RCV_TEMP_REG_2, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4       
1397     .endif ;HALF_DUPLEX_ENABLED
1398     .endif ;ICSS_DUAL_EMAC_BUILD
1399 NO_PREAMBLE_ERROR:
1400     
1401     ; RCV_CONTEXT is not initialized for this error frame.
1402     ; reset RX FIFO, this places the R18 counter back to position 0
1403     CLR R23 , R23 , Rcv_active
1404     M_SET_CMD   D_RESET_RXFIFO
1405     QBA         LB_NO_RX_STAT
1406 RCV_LB_PROCESS_NORMAL:
1407     
1408     ; for XIN, make sure that shift is set to 0
1409     LDI R0.b0, SHIFT_NONE       
1410     ; restore task parameters from parameter bank
1411     .if $defined("PRU0")        
1412     XIN BANK1, &MII_RCV, $sizeof(MII_RCV)       
1413     .else
1414     XIN BANK2, &MII_RCV, $sizeof(MII_RCV)       
1415     .endif
1416     
1417     .if    $defined("TWO_PORT_CFG")
1418      ; OPT: MOve the port context read after the XIN of data
1419     ; for port receive 
1420     .if    $defined("PRU0")
1421     LDI        R0.b0, SHIFT_R14_TO_R0
1422     XIN        BANK0, &MII_RCV_PORT, $sizeof(MII_RCV_PORT)
1423     .else
1424     LDI        R0.b0, SHIFT_R14_TO_R4
1425     XIN        BANK0, &MII_RCV_PORT, $sizeof(MII_RCV_PORT)
1426     .endif    
1427     .endif ;TWO_PORT_CFG
1428     QBBS        LB_RESET_RX_FIFO, MII_RCV.rx_flags, rx_frame_error_shift
1429     ; depending on the bank index, we load bank 0 or bank 1
1430     QBBS        LB_XIN_UPPER_BANK, MII_RCV.rx_flags, rx_bank_index_shift
1431     
1432 LB_XIN_LOWER_BANK:
1433     XIN RX_L2_BANK0_ID, &R18, RANGE_R18_b0      
1434     XIN RX_L2_BANK0_ID, &R2, RANGE_R2_R13       ; XIN RX L2 bank 0
1435     
1436     ; have we received more than 32 bytes?
1437     QBGE        LB_XIN_STORE_LESS_THAN_32_FROM_LOWER_BANK, R18_RCV_BYTECOUNT, 32        
1438     QBA         LB_STORE_FIRST_32_BYTES
1439     
1440 LB_XIN_UPPER_BANK:
1441     XIN RX_L2_BANK1_ID, &R18, RANGE_R18_b0      
1442     XIN RX_L2_BANK1_ID, &R2, RANGE_R2_R13       ; XIN RX L2 bank 1
1444     ;For PTP frames if flow comes here it
1445     ; can only mean that 32-64 bytes have been received
1446     .if $defined("PTP")   
1447     LDI    RCV_TEMP_REG_1.w0, PTP_IPV4_UDP_E2E_ENABLE
1448     LBCO   &RCV_TEMP_REG_1.b0, ICSS_SHARED_CONST, RCV_TEMP_REG_1.w0, 1
1449     QBEQ   PTP_NOT_ENABLED_RX_LB, RCV_TEMP_REG_1.b0, 0
1450     QBBC   PTP_NOT_ENABLED_RX_LB, R22, RX_IS_UDP_PTP_BIT
1451     CLR    R22, R22, RX_IS_UDP_PTP_BIT
1452     JAL    RCV_TEMP_REG_3.w2, FN_TIMESTAMP_GPTP_PACKET
1453     JAL    RCV_TEMP_REG_3.w2, FN_CHECK_AND_CLR_PTP_FWD_FLAG
1454 PTP_NOT_ENABLED_RX_LB:
1455     .endif    ; "PTP"
1456     
1457     ; have we received more than 32 bytes?
1458     QBLE        LB_XIN_STORE_LESS_THAN_32_FROM_UPPER_BANK, R18_RCV_BYTECOUNT, 32        
1459     
1460 LB_STORE_FIRST_32_BYTES:
1461     .if $defined("ICSS_SWITCH_BUILD")
1462     QBBC    LB_PROCESS_32BYTES_CHECK_FWD_FLAG, MII_RCV.rx_flags, host_rcv_flag_shift    ;MII_RCV.rx_flags.host_rcv_flag
1463     .endif
1464     .if $defined(PTP)
1465     ADD     RCV_TEMP_REG_3.w2, MII_RCV.byte_cntr, 32
1466     QBLT    MORE_THAN_32_BYTES_RCVD, RCV_TEMP_REG_3.w2, 32
1468     ;we don't want to execute this for UDP frames, since this will be executed again later
1469     QBBS    MORE_THAN_32_BYTES_RCVD, R22, RX_IS_UDP_PTP_BIT
1470     JAL     RCV_TEMP_REG_3.w2, FN_CHECK_AND_CLR_PTP_FWD_FLAG_L2
1471     JAL     RCV_TEMP_REG_3.w2, FN_TIMESTAMP_GPTP_PACKET
1473 MORE_THAN_32_BYTES_RCVD:
1474     .endif ;PTP
1475     SBCO        &Ethernet, L3_OCMC_RAM_CONST, MII_RCV.buffer_index, 32  
1476     ADD         MII_RCV.byte_cntr, MII_RCV.byte_cntr,  32
1477     
1478     ; Update the buffer descriptor for the received packet
1479     ; Compare current wrk pointer to top_most queue desc pointer ..check for wrap around
1480     QBNE        RCV_LB_NO_QUEUE_WRAP_LOWER, MII_RCV.wrkng_wr_ptr, MII_RCV.top_most_buffer_desc_offset
1481     AND MII_RCV.wrkng_wr_ptr , MII_RCV.base_buffer_desc_offset , MII_RCV.base_buffer_desc_offset
1482     AND MII_RCV.buffer_index , MII_RCV.base_buffer_index , MII_RCV.base_buffer_index
1483     QBA         RCV_LB_QUEUE_WRAPPED_LOWER
1484 RCV_LB_NO_QUEUE_WRAP_LOWER:
1485     ADD         MII_RCV.buffer_index, MII_RCV.buffer_index,  32
1486     ADD         MII_RCV.wrkng_wr_ptr,  MII_RCV.wrkng_wr_ptr,  4
1487     
1488 RCV_LB_QUEUE_WRAPPED_LOWER:
1489     ; Check if the queue got completely filled with the last few bytes and the remaining bytes cannot be added.
1490     ;This scenario of queue overflow has been verified by dry run.
1491     QBNE        LB_PROCESS_32BYTES_CHECK_FLAGS_QUEUE_NOT_FULL_1, MII_RCV.wrkng_wr_ptr, MII_RCV.rd_ptr
1492     CLR MII_RCV.rx_flags , MII_RCV.rx_flags , host_rcv_flag_shift
1493     SET MII_RCV.rx_flags_extended , MII_RCV.rx_flags_extended , host_queue_overflow_shift 
1494     .if $defined("ICSS_DUAL_EMAC_BUILD")
1495     ;For EMAC mode, set rx_frame_error bit.
1496     SET MII_RCV.rx_flags , MII_RCV.rx_flags , 4 
1497     .endif
1498 LB_PROCESS_32BYTES_CHECK_FLAGS_QUEUE_NOT_FULL_1:
1499     .if $defined("ICSS_SWITCH_BUILD")
1500 LB_PROCESS_32BYTES_CHECK_FWD_FLAG:
1501     .if    $defined("TWO_PORT_CFG")
1502     QBBC    LB_PROCESS_32BYTES_CHECK_FLAG_DONE, MII_RCV.rx_flags, fwd_flag_shift    ;MII_RCV.rx_flags.fwd_flag
1503     
1504     SBCO    &Ethernet, L3_OCMC_RAM_CONST, MII_RCV_PORT.buffer_index, 32
1505     ADD        MII_RCV_PORT.byte_cntr, MII_RCV_PORT.byte_cntr, 32
1507     ; Update the buffer descriptor for the received packet
1508     ; Compare current wrk pointer to top_most queue desc pointer ..check for wrap around
1509     QBNE    RCV_LB_NO_PORT_QUEUE_WRAP_LOWER, MII_RCV_PORT.wrkng_wr_ptr, MII_RCV_PORT.top_most_buffer_desc_offset
1510     AND MII_RCV_PORT.wrkng_wr_ptr , MII_RCV_PORT.base_buffer_desc_offset , MII_RCV_PORT.base_buffer_desc_offset ;Warning: converted from MOV
1511     AND MII_RCV_PORT.buffer_index , MII_RCV_PORT.base_buffer_index , MII_RCV_PORT.base_buffer_index     ;Warning: converted from MOV
1512     QBA        RCV_LB_PORT_QUEUE_WRAPPED_LOWER    
1513 RCV_LB_NO_PORT_QUEUE_WRAP_LOWER:
1514     ADD        MII_RCV_PORT.buffer_index, MII_RCV_PORT.buffer_index, 32
1515     ADD        MII_RCV_PORT.wrkng_wr_ptr,  MII_RCV_PORT.wrkng_wr_ptr, 4
1517 RCV_LB_PORT_QUEUE_WRAPPED_LOWER:    
1518     ; Prepare for next call of RCV_LB ..whether next 32 bytes can be received or not
1519     QBNE    LB_PROCESS_32BYTES_CHECK_FLAGS_PORT_QUEUE_NOT_FULL_1, MII_RCV_PORT.wrkng_wr_ptr, MII_RCV_PORT.rd_ptr
1520     CLR        MII_RCV.rx_flags, MII_RCV.rx_flags, fwd_flag_shift    ;MII_RCV.rx_flags.fwd_flag
1521     SET        MII_RCV.rx_flags_extended, MII_RCV.rx_flags_extended, port_queue_overflow_shift    ;MII_RCV.rx_flags_extended.port_queue_overflow
1522     
1523 LB_PROCESS_32BYTES_CHECK_FLAGS_PORT_QUEUE_NOT_FULL_1:
1525 LB_PROCESS_32BYTES_CHECK_FLAG_DONE:    
1526     .endif ;TWO_PORT_CFG
1527     .endif ;ICSS_SWITCH_BUILD
1528     QBBC        LB_STORE_UPPER_DATA, MII_RCV.rx_flags, rx_bank_index_shift
1529     
1530     ; get and store lower data
1531     XIN RX_L2_BANK0_ID, &R2, RANGE_R2_R9        ; recieve the remaining data
1532     QBA LB_XIN_STORE_LESS_THAN_32_FROM_LOWER_BANK
1533 LB_STORE_UPPER_DATA:
1534     ; get and store upper data
1535     XIN RX_L2_BANK1_ID, &R2, RANGE_R2_R13       ; recieve the remaining data    
1536     
1537 LB_XIN_STORE_LESS_THAN_32_FROM_UPPER_BANK:
1538     SUB R0.b1, R18, 32          ; count remaining data  
1539     QBA LB_STORE_FROM_UPPER_BUFFER
1540 LB_XIN_STORE_LESS_THAN_32_FROM_LOWER_BANK:
1541     AND R0.b1 , R18 , R18
1542 LB_STORE_FROM_UPPER_BUFFER:
1544     QBBS    RCV_LB_APPEND_TS, R22, 14    ;check PTP flag
1545     ; Check if 0 bytes are there to store
1546     QBEQ        LB_PROCESS_CHECK_FWD_FLAG, R0.b1, 0     
1547     
1548     ; Receive for Host Queue
1549     .if $defined("ICSS_SWITCH_BUILD")
1550     QBBC    LB_PROCESS_CHECK_FWD_FLAG, MII_RCV.rx_flags, host_rcv_flag_shift    ;MII_RCV.rx_flags.host_rcv_flag
1551     .endif
1552     SBCO        &Ethernet, L3_OCMC_RAM_CONST, MII_RCV.buffer_index, b1  
1553     
1554     ADD     MII_RCV.byte_cntr, MII_RCV.byte_cntr, R0.b1     ; increment the count by R1 bytes   
1555     QBGE        LB_PROCESS_CHECK_FWD_FLAG, R0.b1, 4                 ;If only CRC is left to store then skip
1556     QBNE        RCV_LB_NO_QUEUE_WRAP_2, MII_RCV.wrkng_wr_ptr, MII_RCV.top_most_buffer_desc_offset
1557     AND     MII_RCV.wrkng_wr_ptr , MII_RCV.base_buffer_desc_offset , MII_RCV.base_buffer_desc_offset
1558     QBA         RCV_LB_QUEUE_WRAPPED_2
1559 RCV_LB_NO_QUEUE_WRAP_2:
1560     ADD         MII_RCV.wrkng_wr_ptr,  MII_RCV.wrkng_wr_ptr,  4
1561 RCV_LB_QUEUE_WRAPPED_2:
1562     QBA     RCV_LB_CHECK_OVERFLOW
1563 RCV_LB_APPEND_TS:
1564     ;--------------Logic to append 10 bytes timestamp to the end of packet----------
1565     .if $defined("ICSS_SWITCH_BUILD")
1566         QBBC    LB_PROCESS_CHECK_FWD_FLAG, MII_RCV.rx_flags, host_rcv_flag_shift    ;MII_RCV.rx_flags.host_rcv_flag
1567     .endif
1569     ;If there are 0 bytes to store then append timestamp in new block
1570     QBEQ    LB_TS_STORE_TS, R0.b1, 0
1571     ADD     MII_RCV.byte_cntr, MII_RCV.byte_cntr, R0.b1     ; increment the count by b1 bytes
1572     QBGE        LB_TS_STORE_TS, R0.b1, 4                            ;If only CRC is left to store then skip and append TS
1574     SBCO        &Ethernet, L3_OCMC_RAM_CONST, MII_RCV.buffer_index, b1  ;Store the data   
1576     ;Compare current wrk pointer to top_most queue desc pointer ..check for wrap around
1577     QBNE        LB_TS_NO_WRAP_1, MII_RCV.wrkng_wr_ptr, MII_RCV.top_most_buffer_desc_offset
1578     AND     MII_RCV.wrkng_wr_ptr , MII_RCV.base_buffer_desc_offset , MII_RCV.base_buffer_desc_offset
1579     AND     MII_RCV.buffer_index , MII_RCV.base_buffer_index , MII_RCV.base_buffer_index
1580     QBA         LB_TS_STORE_TS
1581 LB_TS_NO_WRAP_1:
1582     ADD         MII_RCV.buffer_index, MII_RCV.buffer_index,  32
1583     ADD         MII_RCV.wrkng_wr_ptr,  MII_RCV.wrkng_wr_ptr,  4
1585 LB_TS_STORE_TS:   ;store timestamp in new 32B block
1587     ;Load offset
1588     .if $defined(PTP)
1589         M_GPTP_LOAD_TS_OFFSET
1590     .endif
1592     ;Load the TS from Shared RAM
1593     LBCO    &R10, ICSS_SHARED_CONST, RCV_TEMP_REG_1.w0, 10
1594     ;Store into L3 OCMC
1595     SBCO        &R10, L3_OCMC_RAM_CONST, MII_RCV.buffer_index, 10
1596     
1597     ;check wraparound
1598     QBNE        LB_TS_NO_WRAP_2, MII_RCV.wrkng_wr_ptr, MII_RCV.top_most_buffer_desc_offset
1599     AND     MII_RCV.wrkng_wr_ptr , MII_RCV.base_buffer_desc_offset , MII_RCV.base_buffer_desc_offset
1600     QBA         RCV_LB_CHECK_OVERFLOW
1601 LB_TS_NO_WRAP_2:
1602     ADD         MII_RCV.wrkng_wr_ptr,  MII_RCV.wrkng_wr_ptr,  4
1604 RCV_LB_CHECK_OVERFLOW:
1605     .if $defined("ICSS_DUAL_EMAC_BUILD")
1606     ; Check if the queue got completely filled with the last few bytes.
1607     ;If yes, the wr_ptr and rd_prt might become equal and there could be
1608     ;possible data overwrite when the next packet arrives.
1609     ;This has been verfied by dry run.
1610     QBNE        LB_PROCESS_CHECK_FLAGS_QUEUE_NOT_FULL, MII_RCV.wrkng_wr_ptr, MII_RCV.rd_ptr
1611     CLR MII_RCV.rx_flags , MII_RCV.rx_flags , 0 
1612     SET MII_RCV.rx_flags_extended , MII_RCV.rx_flags_extended , 6 
1613     ;For EMAC mode, set rx_frame_error bit
1614     SET MII_RCV.rx_flags , MII_RCV.rx_flags , 4 
1615     
1616 LB_PROCESS_CHECK_FLAGS_QUEUE_NOT_FULL:
1617     .endif ;ICSS_DUAL_EMAC_BUILD
1618 LB_PROCESS_CHECK_FWD_FLAG:
1619     .if $defined("ICSS_SWITCH_BUILD")   
1620     ; Receive for Port Queue
1621     .if    $defined("TWO_PORT_CFG")
1622     QBBC    LB_CLEAR_RX_FIFO, MII_RCV.rx_flags, fwd_flag_shift    ;MII_RCV.rx_flags.fwd_flag
1623     SBCO    &Ethernet, L3_OCMC_RAM_CONST, MII_RCV_PORT.buffer_index, b1
1624     ADD        MII_RCV_PORT.byte_cntr, MII_RCV_PORT.byte_cntr, R0.b1
1625     QBGE    LB_CLEAR_RX_FIFO, R0.b1, 4
1626     QBNE    RCV_LB_NO_PORT_QUEUE_WRAP_2, MII_RCV_PORT.wrkng_wr_ptr, MII_RCV_PORT.top_most_buffer_desc_offset
1627     AND MII_RCV_PORT.wrkng_wr_ptr , MII_RCV_PORT.base_buffer_desc_offset , MII_RCV_PORT.base_buffer_desc_offset ;Warning: converted from MOV
1628     QBA        RCV_LB_PORT_QUEUE_WRAPPED_2    
1629 RCV_LB_NO_PORT_QUEUE_WRAP_2:
1630     ADD        MII_RCV_PORT.wrkng_wr_ptr,  MII_RCV_PORT.wrkng_wr_ptr, 4
1631 RCV_LB_PORT_QUEUE_WRAPPED_2:
1632     .endif ;TWO_PORT_CFG
1633     
1634 LB_CLEAR_RX_FIFO:
1636     QBBS    LB_CHECK_RX_ERRORS, MII_RCV.rx_flags, host_rcv_flag_shift    ;MII_RCV.rx_flags.host_rcv_flag
1637     QBBC    LB_RESET_RX_FIFO, MII_RCV.rx_flags, fwd_flag_shift    ;MII_RCV.rx_flags.fwd_flag
1638     
1639 LB_CHECK_RX_ERRORS: 
1640     .endif  ;ICSS_SWITCH_BUILD
1641     ; Check for CRC Error in the received frame
1642     LDI RCV_TEMP_REG_1.w0, 0x0204       
1643     LBCO        &RCV_TEMP_REG_2, ICSS_INTC_CONST, RCV_TEMP_REG_1.w0, 4      ;load value of INTC_SRSR1   
1644     
1645 ;check odd nibble error 
1646 CHECK_MISALIGNMENT_ERROR:
1647     .if $defined("PRU0")        
1648     QBBC        CHECK_CRC_ERROR, RCV_TEMP_REG_2, 5      ; if interrupt line is clear check for CRC error else continue
1649     .else
1650     QBBC        CHECK_CRC_ERROR, RCV_TEMP_REG_2, 17     ; if interrupt line is clear check for CRC error else continue
1651     .endif
1652     LDI RCV_TEMP_REG_3 , RX_MISALIGNMENT_COUNT_OFFSET
1653     
1654 ;Add to statistics counter
1655     LBCO        &RCV_TEMP_REG_1, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4       
1656     ADD RCV_TEMP_REG_1, RCV_TEMP_REG_1, 1       
1657     SBCO        &RCV_TEMP_REG_1, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4
1658     .if $defined("ICSS_DUAL_EMAC_BUILD")
1659     SET MII_RCV.rx_flags , MII_RCV.rx_flags , 4 
1660     .endif
1661     
1662 CHECK_CRC_ERROR:
1663     .if $defined("PRU0")        
1664     QBBC        LB_CHECK_MIN_FRM_ERR, RCV_TEMP_REG_2, 4
1665     .else
1666     QBBC        LB_CHECK_MIN_FRM_ERR, RCV_TEMP_REG_2, 16
1667     .endif
1668     LDI RCV_TEMP_REG_3 , RX_CRC_COUNT_OFFSET
1669     
1670 ;Add to statistics counter
1671     LBCO        &RCV_TEMP_REG_1, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4       
1672     ADD RCV_TEMP_REG_1, RCV_TEMP_REG_1, 1       
1673     SBCO        &RCV_TEMP_REG_1, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4       
1674     SET MII_RCV.rx_flags , MII_RCV.rx_flags , rx_frame_error_shift
1675     
1676     ;Check whether received frame length is less then defined min value
1677 LB_CHECK_MIN_FRM_ERR:
1678     .if $defined("PRU0")        
1679     LBCO        &RCV_TEMP_REG_2.b0, MII_RT_CFG_CONST, ICSS_MIIRT_RXERR0, 1      
1680     .else
1681     LBCO        &RCV_TEMP_REG_2.b0, MII_RT_CFG_CONST, ICSS_MIIRT_RXERR1, 1      
1682     .endif
1683     QBBC        LB_CHECK_MAX_FRM_ERR, RCV_TEMP_REG_2, 2         ; check if undersize error exist
1684     LDI RCV_TEMP_REG_3 , RX_UNDERSIZED_FRAME_OFFSET
1685     QBA LB_CLR_RX_ERROR_REG
1686     
1687     ;Check whether received frame length is more then defined max value
1688 LB_CHECK_MAX_FRM_ERR:
1689     QBBC        LB_RESET_RX_FIFO, RCV_TEMP_REG_2, 3         ; check for oversize error
1690     LDI RCV_TEMP_REG_3 , RX_OVERSIZED_FRAME_OFFSET
1691     
1692 LB_CLR_RX_ERROR_REG:
1693     
1694 ;Add to statistics counter
1695     LBCO        &RCV_TEMP_REG_1, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4       
1696     ADD RCV_TEMP_REG_1, RCV_TEMP_REG_1, 1       
1697     SBCO        &RCV_TEMP_REG_1, PRU_DMEM_ADDR, RCV_TEMP_REG_3, 4       
1698     
1699     ; Clear the RX MIN or RX MAX ERROR
1700     LDI RCV_TEMP_REG_2.b1, 0x0c 
1701     .if $defined("PRU0")        
1702     SBCO        &RCV_TEMP_REG_2.b1, MII_RT_CFG_CONST, ICSS_MIIRT_RXERR0, 1      
1703     .else
1704     SBCO        &RCV_TEMP_REG_2.b1, MII_RT_CFG_CONST, ICSS_MIIRT_RXERR1, 1      
1705     .endif
1706     SET MII_RCV.rx_flags , MII_RCV.rx_flags , rx_frame_error_shift 
1707     
1708 LB_RESET_RX_FIFO:
1709     ; reset RX fifo, this places the R18 counter back to position 0
1710     M_SET_CMD   D_RESET_RXFIFO
1711     
1712     
1713     QBBC        LB_NO_RX_FRAME_ERROR, MII_RCV.rx_flags, rx_frame_error_shift     ;replaced: QBBC        LB_NO_RX_FRAME_ERROR, MII_RCV.rx_flags.rx_frame_error 
1714     ;clear RX_BC_FRAME & RX_MC_FRAME flags
1715     CLR R22 , R22 , RX_BC_FRAME 
1716     CLR R22 , R22 , RX_MC_FRAME 
1717     JMP LB_RELEASE_QUEUE   ; Clear the EOF and other possible error flags.
1718     
1719 LB_NO_RX_FRAME_ERROR:
1721     .if $defined("ICSS_SWITCH_BUILD")
1722     .if $defined(PTP)
1723     ;This code is used to control PTP packet forwarding from driver, if mem location
1724     ;is set to 1 then FW skips the flow. By default (0) flow is taken
1725     LBCO    &RCV_TEMP_REG_2.b0, ICSS_SHARED_CONST, DISABLE_PTP_FRAME_FORWARDING_CTRL_OFFSET, 1
1726     QBEQ    PTP_PORT_QUEUE_RELEASE_DONE, RCV_TEMP_REG_2.b0, 1        
1727     QBBS    LB_RELEASE_PORT_QUEUE, R22, PTP_RELEASE_PORT_QUEUE_BIT
1729 PTP_PORT_QUEUE_RELEASE_DONE:
1731     .endif ;PTP
1732     .endif ;ICSS_SWITCH_BUILD
1734     LDI R0.b0, 0        
1735     .if $defined("PRU0")        
1736     XOUT        BANK1, &MII_RCV, $sizeof(MII_RCV)       ; store task parameters from parameter bank
1737     .else
1738     XOUT        BANK2, &MII_RCV, $sizeof(MII_RCV)       ; store task parameters from parameter bank
1739     .endif
1740     
1741     .if    $defined("TWO_PORT_CFG")
1743     .if    $defined("PRU0")
1744     LDI        R0.b0, SHIFT_R14_TO_R0
1745     XOUT    BANK0, &MII_RCV_PORT, $sizeof(MII_RCV_PORT)        ; store task parameters from parameter bank
1746     .else
1747     LDI        R0.b0, SHIFT_R14_TO_R4
1748     XOUT    BANK0, &MII_RCV_PORT, $sizeof(MII_RCV_PORT)
1749     .endif
1750     ; For Host Receive
1751     QBBC    LB_UPDATE_CHECK_FWD_FLAG, MII_RCV.rx_flags, host_rcv_flag_shift    ;MII_RCV.rx_flags.host_rcv_flag
1752     .endif ;TWO_PORT_CFG
1753     LDI R0.b0, SHIFT_R2_TO_R26  
1754     .if $defined("PRU0")        
1755     XIN BANK1, &RCV_CONTEXT, $sizeof(MII_RCV_PORT)      ; store task parameters from parameter bank
1756     .else
1757     XIN BANK2, &RCV_CONTEXT, $sizeof(MII_RCV_PORT)      ; store task parameters from parameter bank
1758     .endif
1759     .if    $defined("TWO_PORT_CFG")
1760     CLR R6 , R6 , 0 
1761     QBA        LB_UPDATE_FOR_HOST_RECEIVE
1762 LB_UPDATE_CHECK_FWD_FLAG:
1764     QBBC    LB_UPDATE_CHECK_DONE, MII_RCV.rx_flags, fwd_flag_shift    ;MII_RCV.rx_flags.fwd_flag
1765     .if    $defined("PRU0")    
1766     LDI        R0.b0, SHIFT_R2_TO_R0
1767     XIN        BANK0, &RCV_CONTEXT, $sizeof(MII_RCV_PORT)        ; store task parameters from parameter bank
1768     .else
1769     LDI        R0.b0, SHIFT_R2_TO_R4
1770     XIN        BANK0, &RCV_CONTEXT, $sizeof(MII_RCV_PORT)        ; store task parameters from parameter bank
1771     .endif    
1772     SET R6 , R6 , 0 
1773     .else
1774     ;store the length of the packet for statistics
1775     LDI RCV_TEMP_REG_2 , RX_PKT_SIZE_OFFSET
1776     SBCO        &RCV_CONTEXT.byte_cntr, PRU_DMEM_ADDR, RCV_TEMP_REG_2, 2        ; load the byte count in working register       
1777     
1778     .endif ;TWO_PORT_CFG
1779 LB_UPDATE_FOR_HOST_RECEIVE:
1780     ; Update the Receive Buffer Descriptor
1781     ; Read the wr_ptr of first buffer descriptor
1782     .if    $defined("TWO_PORT_CFG")
1783     LBCO    &RCV_TEMP_REG_1, PRU1_DMEM_CONST, RCV_CONTEXT.rcv_queue_pointer, 4
1784     .else
1785     LBCO        &RCV_TEMP_REG_1, ICSS_SHARED_CONST, RCV_CONTEXT.rcv_queue_pointer, 4    
1786     .endif ;TWO_PORT_CFG
1787     ; clear length field (18..28) and update length with current received frame
1788     LDI RCV_TEMP_REG_2.w0, 0
1789     SUB    RCV_TEMP_REG_2.w2, RCV_CONTEXT.byte_cntr, 4      ;4 byte of FCS   
1790     LSL RCV_TEMP_REG_2.w2, RCV_TEMP_REG_2.w2, 2 
1791     
1792         ;Set the Port number on which packet was received
1793     .if $defined("PRU0")        
1794     SET RCV_TEMP_REG_2 , RCV_TEMP_REG_2 , 16 ; Port 1
1795     .else
1796     SET RCV_TEMP_REG_2 , RCV_TEMP_REG_2 , 17 ;Port 2    
1797     .endif
1798     
1799     CLR     RCV_TEMP_REG_2, RCV_TEMP_REG_2, 15       ;Clear PTP descriptor bit
1801     .if $defined(PTP)  ;check if bit 15 needs to be set
1802         QBBC   LB_SKIP_PTP_DESC_BIT_SET, R22, RX_IS_PTP_BIT
1803         CLR    R22, R22, RX_IS_PTP_BIT
1804         SET        RCV_TEMP_REG_2 , RCV_TEMP_REG_2 , 15  ;Indicate to the driver that this is a PTP frame
1805 LB_SKIP_PTP_DESC_BIT_SET:
1806     .endif ;PTP
1808     .if $defined("ICSS_STP_SWITCH")
1809     ; Set FDB Lookup Success bit if the FDB lookup was successful
1810     QBBC  FDB_LOOKUP_FAIL, R22, FDB_LOOKUP_SUCCESS__R22_BIT
1811     SET   RCV_TEMP_REG_2, RCV_TEMP_REG_2, FDB_LOOKUP_SUCCESS__BD_BIT
1812 FDB_LOOKUP_FAIL:
1814     ; Set Packet Flooded bit if the packet was indeed flooded
1815     QBBC  PKT_NOT_FLOODED, R22, PKT_FLOODED__R22_BIT
1816     SET   RCV_TEMP_REG_2, RCV_TEMP_REG_2, PKT_FLOODED__BD_BIT
1817 PKT_NOT_FLOODED:
1818     .endif ; ICSS_STP_SWITCH
1819         
1820     ; the first buffer descriptor of the frame has been updated with length and port information
1821     SBCO        &RCV_TEMP_REG_2, ICSS_SHARED_CONST, RCV_TEMP_REG_1.w2, 4        
1823     ;Update the queue max fill level
1824     QBGT        LB_RCV_QUEUE_WRAP, RCV_CONTEXT.wrkng_wr_ptr, RCV_CONTEXT.rd_ptr
1825     SUB RCV_TEMP_REG_2.w0, RCV_CONTEXT.wrkng_wr_ptr, RCV_CONTEXT.rd_ptr 
1826     JMP     SKIP_LB_RCV_QUEUE_WRAP
1827     
1828 LB_RCV_QUEUE_WRAP:
1829     ; add queue size to rd_ptr and then subtract wr_ptr
1830     SUB RCV_TEMP_REG_2.w0, RCV_CONTEXT.top_most_buffer_desc_offset, RCV_CONTEXT.rd_ptr  
1831     ADD RCV_TEMP_REG_2.w0, RCV_TEMP_REG_2.w0, 4 
1832     SUB RCV_TEMP_REG_2.w2, RCV_CONTEXT.wrkng_wr_ptr, RCV_CONTEXT.base_buffer_desc_offset        
1833     ADD RCV_TEMP_REG_2.w0, RCV_TEMP_REG_2.w0, RCV_TEMP_REG_2.w2 
1834     
1835 SKIP_LB_RCV_QUEUE_WRAP:
1836     ;divide the queue fill level by 4
1837     LSR RCV_TEMP_REG_2.w0, RCV_TEMP_REG_2.w0, 2 
1838     ;Read the queue max fill level
1839     ADD RCV_TEMP_REG_1.w0, RCV_CONTEXT.rcv_queue_pointer, Q_MAX_FILL_LEVEL_OFFSET       
1840     .if    $defined("TWO_PORT_CFG")
1841     LBCO    &RCV_TEMP_REG_2.b2, PRU1_DMEM_CONST, RCV_TEMP_REG_1.w0, 1    ;RCV_TEMP_REG_2.w2.b0
1842     .else
1843     LBCO        &RCV_TEMP_REG_2.b2, ICSS_SHARED_CONST, RCV_TEMP_REG_1.w0, 1     
1844     
1845     .endif ;TWO_PORT_CFG
1846     ;compare the new queue fill level with max fill level
1847     QBGE        LB_SKIP_NEW_FILL_LEVEL, RCV_TEMP_REG_2.b0, RCV_TEMP_REG_2.b2    
1848     AND RCV_TEMP_REG_2.b2 , RCV_TEMP_REG_2.b0 , RCV_TEMP_REG_2.b0
1849     ; store the new max fill level
1850     .if    $defined("TWO_PORT_CFG")
1851     SBCO    &RCV_TEMP_REG_2.b2, PRU1_DMEM_CONST, RCV_TEMP_REG_1.w0, 1     ;RCV_TEMP_REG_2.w2.b0
1852     .else
1853     SBCO        &RCV_TEMP_REG_2.b2, ICSS_SHARED_CONST, RCV_TEMP_REG_1.w0, 1     
1854     
1855     .endif ;TWO_PORT_CFG
1856 LB_SKIP_NEW_FILL_LEVEL:
1857 LB_HOST_PORT_QUEUE_OVERFLOW_CHECK:
1858 LB_HOST_QUEUE_OVERFLOW:
1859     
1860     ADD RCV_TEMP_REG_1.w0, RCV_CONTEXT.rcv_queue_pointer, Q_OVERFLOW_CNT_OFFSET 
1861     QBBS        LB_PORT_QUEUE_OVERFLOW_CHECK, R6, 0      ;replaced: QBBS        LB_PORT_QUEUE_OVERFLOW_CHECK, CODE_EXECUTING_FOR_PORT_RECEIVE ; 0 -> host recieve | 1 -> port recieve
1862     QBBC        LB_HOST_PORT_QUEUE_OVERFLOW_CHECK_DONE, MII_RCV.rx_flags_extended, 6     ;replaced: QBBC        LB_HOST_PORT_QUEUE_OVERFLOW_CHECK_DONE, MII_RCV.rx_flags_extended.host_queue_overflow 
1863     QBA         HOST_QUEUE_OVERFLOW_STATS
1864     
1865 LB_PORT_QUEUE_OVERFLOW_CHECK:
1866     QBBC        LB_HOST_PORT_QUEUE_OVERFLOW_CHECK_DONE, MII_RCV.rx_flags_extended, 7     ;replaced: QBBC        LB_HOST_PORT_QUEUE_OVERFLOW_CHECK_DONE, MII_RCV.rx_flags_extended.port_queue_overflow 
1867     
1868 HOST_QUEUE_OVERFLOW_STATS:
1869 PORT_QUEUE_OVERFLOW_STATS:
1870     
1871     .if    $defined("TWO_PORT_CFG")
1872     LBCO        &RCV_TEMP_REG_2.b2, PRU1_DMEM_CONST, RCV_TEMP_REG_1.w0, 1       
1873     .else
1874     LBCO        &RCV_TEMP_REG_2.b2, ICSS_SHARED_CONST, RCV_TEMP_REG_1.w0, 1     
1875     .endif
1876     ADD RCV_TEMP_REG_2.b2, RCV_TEMP_REG_2.b2, 1 
1877     .if    $defined("TWO_PORT_CFG")
1878     SBCO        &RCV_TEMP_REG_2.b2, PRU1_DMEM_CONST, RCV_TEMP_REG_1.w0, 1       
1879     .else
1880     SBCO        &RCV_TEMP_REG_2.b2, ICSS_SHARED_CONST, RCV_TEMP_REG_1.w0, 1     
1881     .endif
1882 LB_HOST_PORT_QUEUE_OVERFLOW_CHECK_DONE:
1883     ; Update the Queue Descriptor with the new wr_ptr
1884     ADD RCV_TEMP_REG_1.w0, RCV_CONTEXT.rcv_queue_pointer, Q_RD_PTR_SIZE 
1885     .if    $defined("TWO_PORT_CFG")
1886     SBCO    &RCV_CONTEXT.wrkng_wr_ptr, PRU1_DMEM_CONST, RCV_TEMP_REG_1.w0, Q_WR_PTR_SIZE
1887     .else
1888     SBCO        &RCV_CONTEXT.wrkng_wr_ptr, ICSS_SHARED_CONST, RCV_TEMP_REG_1.w0, Q_WR_PTR_SIZE  
1889     .endif ;TWO_PORT_CFG
1890     .if $defined("ICSS_SWITCH_BUILD")   
1891     .if    $defined("TWO_PORT_CFG")
1892     QBBS    LB_CHECK_COLLISION_FOR_PORT, R6, 0    ;CODE_EXECUTING_FOR_PORT_RECEIVE
1893     ; Update the collision status register with info required by the collision task.
1894     QBBC    LB_UPDATE_CHECK_FWD_FLAG, MII_RCV.rx_flags, host_collision_queue_selected_shift    ;MII_RCV.rx_flags.host_collision_queue_selected
1895     QBA        LB_UPDATE_COLLISION_STATUS
1896     .endif ;TWO_PORT_CFG
1897 LB_CHECK_COLLISION_FOR_PORT:    
1898     .if    $defined("TWO_PORT_CFG")
1899     ; Update the collision status register with info required by the collision task.
1900     QBBC    LB_NO_COLLISIION_OCCURED, MII_RCV.rx_flags, port_collision_queue_selected_shift    ;MII_RCV.rx_flags.port_collision_queue_selected
1901 LB_UPDATE_COLLISION_STATUS:    
1902     LDI     RCV_TEMP_REG_1.w0, COLLISION_STATUS_ADDR
1903     AND COLLISION_STATUS_REG.b2 , MII_RCV.qos_queue , MII_RCV.qos_queue ;Warning: converted from MOV
1904     LSL        COLLISION_STATUS_REG.b2, COLLISION_STATUS_REG.b2, 1
1905     OR        COLLISION_STATUS_REG.b2, COLLISION_STATUS_REG.b2, 0x01
1906     QBBC    LB_COLLISION_SATUS_FOR_HOST_QUEUE, R6, 0    ;CODE_EXECUTING_FOR_PORT_RECEIVE
1907     .if    $defined("PRU0")
1908     ADD        RCV_TEMP_REG_1.w0, RCV_TEMP_REG_1.w0, 2
1909     .else
1910     ADD        RCV_TEMP_REG_1.w0, RCV_TEMP_REG_1.w0, 1
1911     .endif
1912     
1913     CLR        MII_RCV.rx_flags, MII_RCV.rx_flags, port_collision_queue_selected_shift   ; Clear the collision bit for port
1914 LB_COLLISION_SATUS_FOR_HOST_QUEUE:    
1915     SBCO     &COLLISION_STATUS_REG.b2, PRU1_DMEM_CONST, RCV_TEMP_REG_1.w0, 1
1916     
1917     QBBC    LB_UPDATE_CHECK_FWD_FLAG, R6, 0    ;CODE_EXECUTING_FOR_PORT_RECEIVE
1918     .endif ;TWO_PORT_CFG
1919 LB_NO_COLLISIION_OCCURED:
1920 LB_UPDATE_CHECK_DONE:    
1921     .endif  ;ICSS_SWITCH_BUILD
1922 LB_RELEASE_QUEUE:
1923     .if $defined("ICSS_SWITCH_BUILD")
1924     QBBS    LB_RELEASE_HOST_QUEUE, MII_RCV.rx_flags_extended, host_queue_overflow_shift    ;MII_RCV.rx_flags_extended.host_queue_overflow
1925     QBBC    LB_RELEASE_QUEUE_CHECK_FWD_FLAG, MII_RCV.rx_flags, host_rcv_flag_shift    ;MII_RCV.rx_flags.host_rcv_flag
1926     .endif  ;ICSS_SWITCH_BUILD
1927 LB_RELEASE_HOST_QUEUE:  
1928     ;Release the Receive Queue. De-assert the Queue busy bit
1929     ; PRU0 is master so it clear's only "busy_m" bit
1930     .if $defined("PRU0")        
1931     ADD RCV_TEMP_REG_1.w0, MII_RCV.rcv_queue_pointer, Q_STATUS_OFFSET   
1932     .if    $defined("TWO_PORT_CFG")
1933     LBCO    &RCV_TEMP_REG_2, PRU1_DMEM_CONST, RCV_TEMP_REG_1.w0, 3
1934     .else
1935     LBCO        &RCV_TEMP_REG_2, ICSS_SHARED_CONST, RCV_TEMP_REG_1.w0, 3        
1936     
1937     .endif ;TWO_PORT_CFG
1938     AND RCV_TEMP_REG_2.b0, RCV_TEMP_REG_2.b0, 0xFC      ; !(1<<Q_BUSY_M_BIT | 1<<Q_COLLISION_BIT)
1939     QBBC        LB_NO_HOST_QUEUE_OVERFLOW_OCCURED, MII_RCV.rx_flags_extended, host_queue_overflow_shift  ;replaced: QBBC        LB_NO_HOST_QUEUE_OVERFLOW_OCCURED, MII_RCV.rx_flags_extended.host_queue_overflow 
1940     OR  RCV_TEMP_REG_2.b0, RCV_TEMP_REG_2.b0, 0x04      ; set the overflow bit
1941     ADD RCV_TEMP_REG_2.b2, RCV_TEMP_REG_2.b2, 1 ; increment the overflow count by 1 
1942 LB_NO_HOST_QUEUE_OVERFLOW_OCCURED:      
1943     .if    $defined("TWO_PORT_CFG")
1944     SBCO    &RCV_TEMP_REG_2.b0, PRU1_DMEM_CONST, RCV_TEMP_REG_1.w0, 3
1945     .else
1946     SBCO        &RCV_TEMP_REG_2.b0, ICSS_SHARED_CONST, RCV_TEMP_REG_1.w0, 3     
1947     .endif ;TWO_PORT_CFG
1948     
1949     .else
1950     ; PRU1 is slave so it clear's only "busy_s" bit
1951     ADD RCV_TEMP_REG_1.w0, MII_RCV.rcv_queue_pointer, Q_BUSY_S_OFFSET   
1952     .if    $defined("TWO_PORT_CFG")
1953     LBCO    &RCV_TEMP_REG_2, PRU1_DMEM_CONST, RCV_TEMP_REG_1.w0, 4
1954     .else
1955     LBCO        &RCV_TEMP_REG_2, ICSS_SHARED_CONST, RCV_TEMP_REG_1.w0, 4        
1956     .endif ;TWO_PORT_CFG
1957     LDI RCV_TEMP_REG_2.b0, 0    
1958     QBBC        LB_NO_HOST_QUEUE_OVERFLOW_OCCURED_SLAVE, MII_RCV.rx_flags_extended, host_queue_overflow_shift    ;replaced: QBBC        LB_NO_HOST_QUEUE_OVERFLOW_OCCURED_SLAVE, MII_RCV.rx_flags_extended.host_queue_overflow 
1959     OR  RCV_TEMP_REG_2.b1, RCV_TEMP_REG_2.b1, 0x04      ; set the overflow bit
1960     ADD RCV_TEMP_REG_2.b3, RCV_TEMP_REG_2.b3, 1 ; increment the overflow count by 1 
1961 LB_NO_HOST_QUEUE_OVERFLOW_OCCURED_SLAVE:        
1962     .if    $defined("TWO_PORT_CFG")
1963     SBCO    &RCV_TEMP_REG_2, PRU1_DMEM_CONST, RCV_TEMP_REG_1.w0, 4
1964     .else
1965     SBCO        &RCV_TEMP_REG_2, ICSS_SHARED_CONST, RCV_TEMP_REG_1.w0, 4        
1966     .endif ;TWO_PORT_CFG
1967     .endif
1968     
1969 LB_RELEASE_QUEUE_CHECK_FWD_FLAG:
1970     .if $defined("ICSS_SWITCH_BUILD")
1971     QBBS    LB_RELEASE_PORT_QUEUE, MII_RCV.rx_flags_extended, port_queue_overflow_shift    ;MII_RCV.rx_flags_extended.port_queue_overflow
1972     QBBC    LB_RELEASE_QUEUE_CHECK_DONE, MII_RCV.rx_flags, fwd_flag_shift    ;MII_RCV.rx_flags.fwd_flag
1974 LB_RELEASE_PORT_QUEUE:    
1975     ;Release the Port Receive Queue. clear busy_m bit in status as PRU is master
1976     
1977     ADD        RCV_TEMP_REG_1.w0, MII_RCV_PORT.rcv_queue_pointer, Q_STATUS_OFFSET
1978     .if    $defined("TWO_PORT_CFG")
1979     LBCO    &RCV_TEMP_REG_2, PRU1_DMEM_CONST, RCV_TEMP_REG_1.w0, 3
1980     .else
1981     LBCO    &RCV_TEMP_REG_2, ICSS_SHARED_CONST, RCV_TEMP_REG_1.w0, 3
1982     .endif ;TWO_PORT_CFG
1983     AND        RCV_TEMP_REG_2.b0, RCV_TEMP_REG_2.b0, 0xFC  ; !(1<<Q_BUSY_M_BIT | 1<<Q_COLLISION_BIT)
1984     QBBC    LB_NO_PORT_QUEUE_OVERFLOW_OCCURED, MII_RCV.rx_flags_extended, port_queue_overflow_shift    ;MII_RCV.rx_flags_extended.port_queue_overflow
1985     OR        RCV_TEMP_REG_2.b0, RCV_TEMP_REG_2.b0, 0x04   ; set the overflow bit
1986     ADD        RCV_TEMP_REG_2.b2, RCV_TEMP_REG_2.b2, 1     ; increment the overflow count by 1
1987 LB_NO_PORT_QUEUE_OVERFLOW_OCCURED:    
1988     .if    $defined("TWO_PORT_CFG")
1989     SBCO    &RCV_TEMP_REG_2.b0, PRU1_DMEM_CONST, RCV_TEMP_REG_1.w0, 3
1990     .else
1991     SBCO    &RCV_TEMP_REG_2.b0, ICSS_SHARED_CONST, RCV_TEMP_REG_1.w0, 3
1992     .endif ;TWO_PORT_CFG
1993     .if $defined(PTP)
1994     QBBC    LB_RELEASE_QUEUE_CHECK_DONE, R22, PTP_RELEASE_PORT_QUEUE_BIT
1995     CLR     R22, R22, PTP_RELEASE_PORT_QUEUE_BIT
1996     CLR     MII_RCV.rx_flags, MII_RCV.rx_flags, fwd_flag_shift
1997     QBA     PTP_PORT_QUEUE_RELEASE_DONE
1998     .endif
1999 LB_RELEASE_QUEUE_CHECK_DONE: 
2000 LB_MAINTENANCE:
2001     .endif ;ICSS_SWITCH_BUILD
2002     
2003     CLR R23 , R23 , Rcv_active ; indicate that rcv has been completed  
2004     QBBS        LB_NO_RX_STAT, MII_RCV.rx_flags, rx_frame_error_shift    ;replaced: QBBS        LB_NO_RX_STAT, MII_RCV.rx_flags.rx_frame_error 
2005     SET R23 , R23 , RX_STAT_PEND 
2006     
2007     .if $defined("ICSS_SWITCH_BUILD")
2008     QBBC    LB_DONE, MII_RCV.rx_flags, host_rcv_flag_shift    ;MII_RCV.rx_flags.host_rcv_flag
2009     .if    $defined("TWO_PORT_CFG")
2010     QBBS    LB_DONE, MII_RCV.rx_flags, host_collision_queue_selected_shift        ;MII_RCV.rx_flags.host_collision_queue_selected
2011     .endif ;TWO_PORT_CFG
2012     .endif ;ICSS_SWITCH_BUILD
2014     M_RCV_RX_EOF_INTERRUPT_RAISE_INTC           ; raise RX interrupt on intc controller.
2015     
2016     .if $defined("ICSS_SWITCH_BUILD")
2017 LB_DONE:
2018     .if    $defined("TWO_PORT_CFG")
2019     CLR        MII_RCV.rx_flags, MII_RCV.rx_flags,  host_collision_queue_selected_shift    ;MII_RCV.rx_flags.host_collision_queue_selected
2020     .endif ;TWO_PORT_CFG
2021     QBBC    DO_NOT_SET_RX_FWD, MII_RCV.rx_flags, fwd_flag_shift    ;MII_RCV.rx_flags.fwd_flag
2022     .if    $defined("TWO_PORT_CFG")
2023     SET     R22, R22, RX_FWD_FLAG
2024     .endif ;TWO_PORT_CFG
2025     
2026 DO_NOT_SET_RX_FWD:    
2027     .endif ;ICSS_SWITCH_BUILD
2028     
2029 LB_NO_RX_STAT:
2030     
2031     .if $defined("ICSS_REV1")   
2032     M_RCV_RX_EOF_CLEAR_INTC_ICSS_REV1
2033     .endif      ;ICSS_REV1
2034     
2035     .if $defined("ICSS_REV2")   
2036     M_RCV_RX_EOF_CLEAR_INTC_ICSS_REV2
2037     .endif      ;ICSS_REV2
2038     
2039     ; Execute the TX Task as next task
2040     QBBC        TASK_EXECUTION_FINISHED_inter, R23, 0    ;replaced: QBBC        TASK_EXECUTION_FINISHED_inter, Xmt_active 
2041     LDI CURRENT_TASK_POINTER, BG_TASK_POINTER   
2042     JMP         XMT_QUEUE
2043     
2044 TASK_EXECUTION_FINISHED_inter:
2045     JMP TASK_EXECUTION_FINISHED
2046     
2047     .if    $defined("TWO_PORT_CFG")
2048 ;/////////////////////////////// Experimenting Start /////////////////////////////////////////////////////
2050 ;-------------------------------------------------------------------------------------------
2051 ; Function:             F_QUEUE_ARBITRATION
2052 ; Description:         Function will aquire token for either queue or collision buffer
2053 ; Input:    MII_RCV.qos_queue - contains the Qos queue number as been determined by the RX_FB function
2054 ; Input:     RCV_TEMP_REG_3.w0 - contains the base address of host/port queue
2055 ; Input:     RCV_TEMP_REG_3.w2 - contains the base address of the collision queue
2056 ; Input:   RCV_TEMP_REG_1.b1 - contains information about whether called for host or port queue arbitration 
2057 ; Output:    RCV_TEMP_REG_1.b0 - returns value for caller, to indicate that the queue has been aquired 
2058 ;                                successful ((0-failed to aquire; 1-queue; 2-collision)
2059 ; Output:    RCV_TEMP_REG_2.w0 - returns the queue pointer after aquiring the queue
2060 ; Output:    RCV_TEMP_REG_2.w2 - returns the current write pointer of the queue that has been aquired
2061 ;                                is used as wrkng_wr_ptr during the following packet processing
2062 ;            RCV_TEMP_REG_1.w2 - temporayr use 
2063 ;-------------------------------------------------------------------------------------------
2065 FN_QUEUE_ARBITRATION:
2066     LDI        RCV_TEMP_REG_1.b0, 0x00
2067 QAM_CHECK:
2068     LSL        RCV_TEMP_REG_1.w2, MII_RCV.qos_queue, 3        ; adjust queue-number offset to 8byte boundaries
2069     QBNE    PICK_NORMAL_QUEUE, RCV_TEMP_REG_1.b0, COLLISION_AQUIRED
2070     LDI        RCV_TEMP_REG_1.w2, 0x0
2071 PICK_NORMAL_QUEUE:    
2072     ADD        RCV_TEMP_REG_1.w2, RCV_TEMP_REG_3.w0, RCV_TEMP_REG_1.w2    ; adjust for queue base address
2073     ADD        RCV_TEMP_REG_3.w0, RCV_TEMP_REG_1.w2, Q_BUSY_S_OFFSET    ; .w2 points to Q_BUSY_S_OFFSET
2074     ADD        RCV_TEMP_REG_1.w2, RCV_TEMP_REG_1.w2, Q_STATUS_OFFSET    ; .w0 points to Q_STATUS_OFFSET
2075     LBCO    &RCV_TEMP_REG_2.w2, PRU1_DMEM_CONST, RCV_TEMP_REG_3.w0, Q_BUSY_S_SIZE + Q_STATUS_SIZE ; load busy_s + status of this queue
2076     ; Check if it is called for the Port Arbitration
2077     QBBS    PORT_QUEUE_ARBITRATION, RCV_TEMP_REG_1.b1, 0    ;RCV_TEMP_REG_1.b1.t0
2078     .if    $defined("PRU0")      
2079     QBBS    QAM_BUSY, RCV_TEMP_REG_2.b2, Q_BUSY_S_BIT    ; is queue already busy?  PRU0 is master    ;RCV_TEMP_REG_2.w2.b0
2080     SET        RCV_TEMP_REG_2.b3, RCV_TEMP_REG_2.b3, Q_BUSY_M_BIT    ;RCV_TEMP_REG_2.w2.b1
2081     SBCO    &RCV_TEMP_REG_2.b3, PRU1_DMEM_CONST, RCV_TEMP_REG_1.w2, Q_STATUS_SIZE    ; set busy_m into memory
2082     QBA        QAM_CALC_QUEUE_POINTER
2083     .else
2084     QBBS    QAM_BUSY, RCV_TEMP_REG_2.b3, Q_BUSY_M_BIT    ; is queue already busy? PRU1 is slave    ;RCV_TEMP_REG_2.w2.b1
2085     SET        RCV_TEMP_REG_2.b2, RCV_TEMP_REG_2.b2, Q_BUSY_S_BIT    ;RCV_TEMP_REG_2.w2.b0
2086     SBCO    &RCV_TEMP_REG_2.b2, PRU1_DMEM_CONST, RCV_TEMP_REG_3.w0, Q_BUSY_S_SIZE     ; set busy_s into memory
2087     ; load again busy_m ..only for Slave because it needs to check that master has not acquired the queue inbetween
2088     LBCO    &RCV_TEMP_REG_2.b3, PRU1_DMEM_CONST, RCV_TEMP_REG_1.w2, Q_STATUS_SIZE    ;RCV_TEMP_REG_2.w2.b1
2089     QBBC    QAM_CALC_QUEUE_POINTER, RCV_TEMP_REG_2.b3, Q_BUSY_M_BIT    ; is queue already busy?
2090     ; Clear busy_s bit because busy_m bit is set
2091     CLR        RCV_TEMP_REG_2.b2, RCV_TEMP_REG_2.b2, Q_BUSY_S_BIT    ;RCV_TEMP_REG_2.w2.b0
2092     SBCO    &RCV_TEMP_REG_2.b2, PRU1_DMEM_CONST, RCV_TEMP_REG_3.w0, Q_BUSY_S_SIZE     ; clear busy_s into memory    ;RCV_TEMP_REG_2.w2.b0
2093     QBA        QAM_BUSY
2094     .endif
2096 PORT_QUEUE_ARBITRATION:
2097     QBBS    QAM_BUSY, RCV_TEMP_REG_2.b2, Q_BUSY_S_BIT    ; is queue already busy?  PRU0 is master    ;RCV_TEMP_REG_2.w2.b0
2098     SET        RCV_TEMP_REG_2.b3, RCV_TEMP_REG_2.b3, Q_BUSY_M_BIT    ;RCV_TEMP_REG_2.w2.b1
2099     SBCO    &RCV_TEMP_REG_2.b3, PRU1_DMEM_CONST, RCV_TEMP_REG_1.w2, Q_STATUS_SIZE    ; set busy_m into memory
2100     QBA        QAM_CALC_QUEUE_POINTER
2101     
2102 QAM_BUSY: ; failed to aquire the queue, now try the colission
2103     QBEQ    QAM_FAILED, RCV_TEMP_REG_1.b0, COLLISION_AQUIRED
2104     AND RCV_TEMP_REG_3.w0 , RCV_TEMP_REG_3.w2 , RCV_TEMP_REG_3.w2
2105     LDI        RCV_TEMP_REG_1.b0, COLLISION_AQUIRED        ; failed to aquire the queue, indicate this to macro caller by returing 0
2106     ;check that host has emptied the queue before acquiring it
2107     LDI      RCV_TEMP_REG_1.w2, COLLISION_STATUS_ADDR
2108     ADD      RCV_TEMP_REG_1.w2, RCV_TEMP_REG_1.w2, 3 
2109     LBCO     &RCV_TEMP_REG_1.b3, PRU1_DMEM_CONST, RCV_TEMP_REG_1.w2, 1
2110         QBBC    QAM_CHECK, RCV_TEMP_REG_1, 3     ;replaced: QBBC    QAM_CHECK, RCV_TEMP_REG_1.HOST_COLLISION_READ_PENDING 
2111         
2112 QAM_FAILED:
2113     LDI        RCV_TEMP_REG_1.b0, QUEUE_FAILED    ; failed to aquire queue & collision 
2114     LDI        RCV_TEMP_REG_2.w2, 0
2115     QBA        QAM_DONE
2116 QAM_CALC_QUEUE_POINTER:
2117     QBEQ    PICK_COL_QUEUE, RCV_TEMP_REG_1.b0, COLLISION_AQUIRED
2118     ; return value that queue had been aquired OK.
2119     LDI        RCV_TEMP_REG_1.b0, QUEUE_AQUIRED
2120 PICK_COL_QUEUE:    
2121     ; adjust the pointer to the wr_ptr offset
2122     SUB        RCV_TEMP_REG_2.w0, RCV_TEMP_REG_1.w2, Q_STATUS_OFFSET - Q_WR_PTR_OFFSET
2123     ; load wr_ptr from memory, and us it to init the wrkng_wr_ptr
2124     LBCO    &RCV_TEMP_REG_2.w2, PRU1_DMEM_CONST, RCV_TEMP_REG_2.w0, Q_WR_PTR_SIZE
2125     ; ToDo: this can be optimized!
2126     SUB        RCV_TEMP_REG_2.w0, RCV_TEMP_REG_2.w0, Q_WR_PTR_OFFSET
2127 QAM_DONE:
2128     JMP CALL_REG        
2129   
2130 ;////////////////////////////// Experimenting End ////////////////////////////////////////////////////////////////////    
2131     .endif ;TWO_PORT_CFG
2132     .endif  ; e/o MII_Rcv_p