409 lines
		
	
	
	
		
			8.5 KiB
			
		
	
	
	
		
			Ucode
		
	
	
	
	
	
		
		
			
		
	
	
			409 lines
		
	
	
	
		
			8.5 KiB
			
		
	
	
	
		
			Ucode
		
	
	
	
	
	
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								 * RX ucode for the Intel IXP2400 in POS-PHY mode.
							 | 
						||
| 
								 | 
							
								 * Copyright (C) 2004, 2005 Lennert Buytenhek
							 | 
						||
| 
								 | 
							
								 * Dedicated to Marija Kulikova.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * This program is free software; you can redistribute it and/or modify
							 | 
						||
| 
								 | 
							
								 * it under the terms of the GNU General Public License as published by
							 | 
						||
| 
								 | 
							
								 * the Free Software Foundation; either version 2 of the License, or
							 | 
						||
| 
								 | 
							
								 * (at your option) any later version.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Assumptions made in this code:
							 | 
						||
| 
								 | 
							
								 * - The IXP2400 MSF is configured for POS-PHY mode, in a mode where
							 | 
						||
| 
								 | 
							
								 *   only one full element list is used.  This includes, for example,
							 | 
						||
| 
								 | 
							
								 *   1x32 SPHY and 1x32 MPHY32, but not 4x8 SPHY or 1x32 MPHY4.  (This
							 | 
						||
| 
								 | 
							
								 *   is not an exhaustive list.)
							 | 
						||
| 
								 | 
							
								 * - The RBUF uses 64-byte mpackets.
							 | 
						||
| 
								 | 
							
								 * - RX descriptors reside in SRAM, and have the following format:
							 | 
						||
| 
								 | 
							
								 *	struct rx_desc
							 | 
						||
| 
								 | 
							
								 *	{
							 | 
						||
| 
								 | 
							
								 *	// to uengine
							 | 
						||
| 
								 | 
							
								 *		u32	buf_phys_addr;
							 | 
						||
| 
								 | 
							
								 *		u32	buf_length;
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 *	// from uengine
							 | 
						||
| 
								 | 
							
								 *		u32	channel;
							 | 
						||
| 
								 | 
							
								 *		u32	pkt_length;
							 | 
						||
| 
								 | 
							
								 *	};
							 | 
						||
| 
								 | 
							
								 * - Packet data resides in DRAM.
							 | 
						||
| 
								 | 
							
								 * - Packet buffer addresses are 8-byte aligned.
							 | 
						||
| 
								 | 
							
								 * - Scratch ring 0 is rx_pending.
							 | 
						||
| 
								 | 
							
								 * - Scratch ring 1 is rx_done, and has status condition 'full'.
							 | 
						||
| 
								 | 
							
								 * - The host triggers rx_done flush and rx_pending refill on seeing INTA.
							 | 
						||
| 
								 | 
							
								 * - This code is run on all eight threads of the microengine it runs on.
							 | 
						||
| 
								 | 
							
								 *
							 | 
						||
| 
								 | 
							
								 * Local memory is used for per-channel RX state.
							 | 
						||
| 
								 | 
							
								 */
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define RX_THREAD_FREELIST_0		0x0030
							 | 
						||
| 
								 | 
							
								#define RBUF_ELEMENT_DONE		0x0044
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define CHANNEL_FLAGS			*l$index0[0]
							 | 
						||
| 
								 | 
							
								#define CHANNEL_FLAG_RECEIVING		1
							 | 
						||
| 
								 | 
							
								#define PACKET_LENGTH			*l$index0[1]
							 | 
						||
| 
								 | 
							
								#define PACKET_CHECKSUM			*l$index0[2]
							 | 
						||
| 
								 | 
							
								#define BUFFER_HANDLE			*l$index0[3]
							 | 
						||
| 
								 | 
							
								#define BUFFER_START			*l$index0[4]
							 | 
						||
| 
								 | 
							
								#define BUFFER_LENGTH			*l$index0[5]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#define CHANNEL_STATE_SIZE		24	// in bytes
							 | 
						||
| 
								 | 
							
								#define CHANNEL_STATE_SHIFT		5	// ceil(log2(state size))
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									.sig volatile sig1
							 | 
						||
| 
								 | 
							
									.sig volatile sig2
							 | 
						||
| 
								 | 
							
									.sig volatile sig3
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									.sig mpacket_arrived
							 | 
						||
| 
								 | 
							
									.reg add_to_rx_freelist
							 | 
						||
| 
								 | 
							
									.reg read $rsw0, $rsw1
							 | 
						||
| 
								 | 
							
									.xfer_order $rsw0 $rsw1
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									.reg zero
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/*
							 | 
						||
| 
								 | 
							
									 * Initialise add_to_rx_freelist.
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									.begin
							 | 
						||
| 
								 | 
							
										.reg temp
							 | 
						||
| 
								 | 
							
										.reg temp2
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										immed[add_to_rx_freelist, RX_THREAD_FREELIST_0]
							 | 
						||
| 
								 | 
							
										immed_w1[add_to_rx_freelist, (&$rsw0 | (&mpacket_arrived << 12))]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										local_csr_rd[ACTIVE_CTX_STS]
							 | 
						||
| 
								 | 
							
										immed[temp, 0]
							 | 
						||
| 
								 | 
							
										alu[temp2, temp, and, 0x1f]
							 | 
						||
| 
								 | 
							
										alu_shf[add_to_rx_freelist, add_to_rx_freelist, or, temp2, <<20]
							 | 
						||
| 
								 | 
							
										alu[temp2, temp, and, 0x80]
							 | 
						||
| 
								 | 
							
										alu_shf[add_to_rx_freelist, add_to_rx_freelist, or, temp2, <<18]
							 | 
						||
| 
								 | 
							
									.end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									immed[zero, 0]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/*
							 | 
						||
| 
								 | 
							
									 * Skip context 0 initialisation?
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									.begin
							 | 
						||
| 
								 | 
							
										br!=ctx[0, mpacket_receive_loop#]
							 | 
						||
| 
								 | 
							
									.end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/*
							 | 
						||
| 
								 | 
							
									 * Initialise local memory.
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									.begin
							 | 
						||
| 
								 | 
							
										.reg addr
							 | 
						||
| 
								 | 
							
										.reg temp
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										immed[temp, 0]
							 | 
						||
| 
								 | 
							
									init_local_mem_loop#:
							 | 
						||
| 
								 | 
							
										alu_shf[addr, --, b, temp, <<CHANNEL_STATE_SHIFT]
							 | 
						||
| 
								 | 
							
										local_csr_wr[ACTIVE_LM_ADDR_0, addr]
							 | 
						||
| 
								 | 
							
										nop
							 | 
						||
| 
								 | 
							
										nop
							 | 
						||
| 
								 | 
							
										nop
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										immed[CHANNEL_FLAGS, 0]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										alu[temp, temp, +, 1]
							 | 
						||
| 
								 | 
							
										alu[--, temp, and, 0x20]
							 | 
						||
| 
								 | 
							
										beq[init_local_mem_loop#]
							 | 
						||
| 
								 | 
							
									.end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/*
							 | 
						||
| 
								 | 
							
									 * Initialise signal pipeline.
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									.begin
							 | 
						||
| 
								 | 
							
										local_csr_wr[SAME_ME_SIGNAL, (&sig1 << 3)]
							 | 
						||
| 
								 | 
							
										.set_sig sig1
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										local_csr_wr[SAME_ME_SIGNAL, (&sig2 << 3)]
							 | 
						||
| 
								 | 
							
										.set_sig sig2
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										local_csr_wr[SAME_ME_SIGNAL, (&sig3 << 3)]
							 | 
						||
| 
								 | 
							
										.set_sig sig3
							 | 
						||
| 
								 | 
							
									.end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								mpacket_receive_loop#:
							 | 
						||
| 
								 | 
							
									/*
							 | 
						||
| 
								 | 
							
									 * Synchronise and wait for mpacket.
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									.begin
							 | 
						||
| 
								 | 
							
										ctx_arb[sig1]
							 | 
						||
| 
								 | 
							
										local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig1 << 3))]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										msf[fast_wr, --, add_to_rx_freelist, 0]
							 | 
						||
| 
								 | 
							
										.set_sig mpacket_arrived
							 | 
						||
| 
								 | 
							
										ctx_arb[mpacket_arrived]
							 | 
						||
| 
								 | 
							
										.set $rsw0 $rsw1
							 | 
						||
| 
								 | 
							
									.end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/*
							 | 
						||
| 
								 | 
							
									 * We halt if we see {inbparerr,parerr,null,soperror}.
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									.begin
							 | 
						||
| 
								 | 
							
										alu_shf[--, 0x1b, and, $rsw0, >>8]
							 | 
						||
| 
								 | 
							
										bne[abort_rswerr#]
							 | 
						||
| 
								 | 
							
									.end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/*
							 | 
						||
| 
								 | 
							
									 * Point local memory pointer to this channel's state area.
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									.begin
							 | 
						||
| 
								 | 
							
										.reg chanaddr
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										alu[chanaddr, $rsw0, and, 0x1f]
							 | 
						||
| 
								 | 
							
										alu_shf[chanaddr, --, b, chanaddr, <<CHANNEL_STATE_SHIFT]
							 | 
						||
| 
								 | 
							
										local_csr_wr[ACTIVE_LM_ADDR_0, chanaddr]
							 | 
						||
| 
								 | 
							
										nop
							 | 
						||
| 
								 | 
							
										nop
							 | 
						||
| 
								 | 
							
										nop
							 | 
						||
| 
								 | 
							
									.end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/*
							 | 
						||
| 
								 | 
							
									 * Check whether we received a SOP mpacket while we were already
							 | 
						||
| 
								 | 
							
									 * working on a packet, or a non-SOP mpacket while there was no
							 | 
						||
| 
								 | 
							
									 * packet pending.  (SOP == RECEIVING -> abort)  If everything's
							 | 
						||
| 
								 | 
							
									 * okay, update the RECEIVING flag to reflect our new state.
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									.begin
							 | 
						||
| 
								 | 
							
										.reg temp
							 | 
						||
| 
								 | 
							
										.reg eop
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										#if CHANNEL_FLAG_RECEIVING != 1
							 | 
						||
| 
								 | 
							
										#error CHANNEL_FLAG_RECEIVING is not 1
							 | 
						||
| 
								 | 
							
										#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										alu_shf[temp, 1, and, $rsw0, >>15]
							 | 
						||
| 
								 | 
							
										alu[temp, temp, xor, CHANNEL_FLAGS]
							 | 
						||
| 
								 | 
							
										alu[--, temp, and, CHANNEL_FLAG_RECEIVING]
							 | 
						||
| 
								 | 
							
										beq[abort_proterr#]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										alu_shf[eop, 1, and, $rsw0, >>14]
							 | 
						||
| 
								 | 
							
										alu[CHANNEL_FLAGS, temp, xor, eop]
							 | 
						||
| 
								 | 
							
									.end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
									/*
							 | 
						||
| 
								 | 
							
									 * Copy the mpacket into the right spot, and in case of EOP,
							 | 
						||
| 
								 | 
							
									 * write back the descriptor and pass the packet on.
							 | 
						||
| 
								 | 
							
									 */
							 | 
						||
| 
								 | 
							
									.begin
							 | 
						||
| 
								 | 
							
										.reg buffer_offset
							 | 
						||
| 
								 | 
							
										.reg _packet_length
							 | 
						||
| 
								 | 
							
										.reg _packet_checksum
							 | 
						||
| 
								 | 
							
										.reg _buffer_handle
							 | 
						||
| 
								 | 
							
										.reg _buffer_start
							 | 
						||
| 
								 | 
							
										.reg _buffer_length
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/*
							 | 
						||
| 
								 | 
							
										 * Determine buffer_offset, _packet_length and
							 | 
						||
| 
								 | 
							
										 * _packet_checksum.
							 | 
						||
| 
								 | 
							
										 */
							 | 
						||
| 
								 | 
							
										.begin
							 | 
						||
| 
								 | 
							
											.reg temp
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											alu[--, 1, and, $rsw0, >>15]
							 | 
						||
| 
								 | 
							
											beq[not_sop#]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											immed[PACKET_LENGTH, 0]
							 | 
						||
| 
								 | 
							
											immed[PACKET_CHECKSUM, 0]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										not_sop#:
							 | 
						||
| 
								 | 
							
											alu[buffer_offset, --, b, PACKET_LENGTH]
							 | 
						||
| 
								 | 
							
											alu_shf[temp, 0xff, and, $rsw0, >>16]
							 | 
						||
| 
								 | 
							
											alu[_packet_length, buffer_offset, +, temp]
							 | 
						||
| 
								 | 
							
											alu[PACKET_LENGTH, --, b, _packet_length]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											immed[temp, 0xffff]
							 | 
						||
| 
								 | 
							
											alu[temp, $rsw1, and, temp]
							 | 
						||
| 
								 | 
							
											alu[_packet_checksum, PACKET_CHECKSUM, +, temp]
							 | 
						||
| 
								 | 
							
											alu[PACKET_CHECKSUM, --, b, _packet_checksum]
							 | 
						||
| 
								 | 
							
										.end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/*
							 | 
						||
| 
								 | 
							
										 * Allocate buffer in case of SOP.
							 | 
						||
| 
								 | 
							
										 */
							 | 
						||
| 
								 | 
							
										.begin
							 | 
						||
| 
								 | 
							
											.reg temp
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											alu[temp, 1, and, $rsw0, >>15]
							 | 
						||
| 
								 | 
							
											beq[skip_buffer_alloc#]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											.begin
							 | 
						||
| 
								 | 
							
												.sig zzz
							 | 
						||
| 
								 | 
							
												.reg read $stemp $stemp2
							 | 
						||
| 
								 | 
							
												.xfer_order $stemp $stemp2
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											rx_nobufs#:
							 | 
						||
| 
								 | 
							
												scratch[get, $stemp, zero, 0, 1], ctx_swap[zzz]
							 | 
						||
| 
								 | 
							
												alu[_buffer_handle, --, b, $stemp]
							 | 
						||
| 
								 | 
							
												beq[rx_nobufs#]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
												sram[read, $stemp, _buffer_handle, 0, 2],
							 | 
						||
| 
								 | 
							
																ctx_swap[zzz]
							 | 
						||
| 
								 | 
							
												alu[_buffer_start, --, b, $stemp]
							 | 
						||
| 
								 | 
							
												alu[_buffer_length, --, b, $stemp2]
							 | 
						||
| 
								 | 
							
											.end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										skip_buffer_alloc#:
							 | 
						||
| 
								 | 
							
										.end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/*
							 | 
						||
| 
								 | 
							
										 * Resynchronise.
							 | 
						||
| 
								 | 
							
										 */
							 | 
						||
| 
								 | 
							
										.begin
							 | 
						||
| 
								 | 
							
											ctx_arb[sig2]
							 | 
						||
| 
								 | 
							
											local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig2 << 3))]
							 | 
						||
| 
								 | 
							
										.end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/*
							 | 
						||
| 
								 | 
							
										 * Synchronise buffer state.
							 | 
						||
| 
								 | 
							
										 */
							 | 
						||
| 
								 | 
							
										.begin
							 | 
						||
| 
								 | 
							
											.reg temp
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											alu[temp, 1, and, $rsw0, >>15]
							 | 
						||
| 
								 | 
							
											beq[copy_from_local_mem#]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											alu[BUFFER_HANDLE, --, b, _buffer_handle]
							 | 
						||
| 
								 | 
							
											alu[BUFFER_START, --, b, _buffer_start]
							 | 
						||
| 
								 | 
							
											alu[BUFFER_LENGTH, --, b, _buffer_length]
							 | 
						||
| 
								 | 
							
											br[sync_state_done#]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										copy_from_local_mem#:
							 | 
						||
| 
								 | 
							
											alu[_buffer_handle, --, b, BUFFER_HANDLE]
							 | 
						||
| 
								 | 
							
											alu[_buffer_start, --, b, BUFFER_START]
							 | 
						||
| 
								 | 
							
											alu[_buffer_length, --, b, BUFFER_LENGTH]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										sync_state_done#:
							 | 
						||
| 
								 | 
							
										.end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								#if 0
							 | 
						||
| 
								 | 
							
										/*
							 | 
						||
| 
								 | 
							
										 * Debug buffer state management.
							 | 
						||
| 
								 | 
							
										 */
							 | 
						||
| 
								 | 
							
										.begin
							 | 
						||
| 
								 | 
							
											.reg temp
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											alu[temp, 1, and, $rsw0, >>14]
							 | 
						||
| 
								 | 
							
											beq[no_poison#]
							 | 
						||
| 
								 | 
							
											immed[BUFFER_HANDLE, 0xdead]
							 | 
						||
| 
								 | 
							
											immed[BUFFER_START, 0xdead]
							 | 
						||
| 
								 | 
							
											immed[BUFFER_LENGTH, 0xdead]
							 | 
						||
| 
								 | 
							
										no_poison#:
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											immed[temp, 0xdead]
							 | 
						||
| 
								 | 
							
											alu[--, _buffer_handle, -, temp]
							 | 
						||
| 
								 | 
							
											beq[state_corrupted#]
							 | 
						||
| 
								 | 
							
											alu[--, _buffer_start, -, temp]
							 | 
						||
| 
								 | 
							
											beq[state_corrupted#]
							 | 
						||
| 
								 | 
							
											alu[--, _buffer_length, -, temp]
							 | 
						||
| 
								 | 
							
											beq[state_corrupted#]
							 | 
						||
| 
								 | 
							
										.end
							 | 
						||
| 
								 | 
							
								#endif
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/*
							 | 
						||
| 
								 | 
							
										 * Check buffer length.
							 | 
						||
| 
								 | 
							
										 */
							 | 
						||
| 
								 | 
							
										.begin
							 | 
						||
| 
								 | 
							
											alu[--, _buffer_length, -, _packet_length]
							 | 
						||
| 
								 | 
							
											blo[buffer_overflow#]
							 | 
						||
| 
								 | 
							
										.end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/*
							 | 
						||
| 
								 | 
							
										 * Copy the mpacket and give back the RBUF element.
							 | 
						||
| 
								 | 
							
										 */
							 | 
						||
| 
								 | 
							
										.begin
							 | 
						||
| 
								 | 
							
											.reg element
							 | 
						||
| 
								 | 
							
											.reg xfer_size
							 | 
						||
| 
								 | 
							
											.reg temp
							 | 
						||
| 
								 | 
							
											.sig copy_sig
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											alu_shf[element, 0x7f, and, $rsw0, >>24]
							 | 
						||
| 
								 | 
							
											alu_shf[xfer_size, 0xff, and, $rsw0, >>16]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											alu[xfer_size, xfer_size, -, 1]
							 | 
						||
| 
								 | 
							
											alu_shf[xfer_size, 0x10, or, xfer_size, >>3]
							 | 
						||
| 
								 | 
							
											alu_shf[temp, 0x10, or, xfer_size, <<21]
							 | 
						||
| 
								 | 
							
											alu_shf[temp, temp, or, element, <<11]
							 | 
						||
| 
								 | 
							
											alu_shf[--, temp, or, 1, <<18]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											dram[rbuf_rd, --, _buffer_start, buffer_offset, max_8],
							 | 
						||
| 
								 | 
							
														indirect_ref, sig_done[copy_sig]
							 | 
						||
| 
								 | 
							
											ctx_arb[copy_sig]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											alu[temp, RBUF_ELEMENT_DONE, or, element, <<16]
							 | 
						||
| 
								 | 
							
											msf[fast_wr, --, temp, 0]
							 | 
						||
| 
								 | 
							
										.end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/*
							 | 
						||
| 
								 | 
							
										 * If EOP, write back the packet descriptor.
							 | 
						||
| 
								 | 
							
										 */
							 | 
						||
| 
								 | 
							
										.begin
							 | 
						||
| 
								 | 
							
											.reg write $stemp $stemp2
							 | 
						||
| 
								 | 
							
											.xfer_order $stemp $stemp2
							 | 
						||
| 
								 | 
							
											.sig zzz
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											alu_shf[--, 1, and, $rsw0, >>14]
							 | 
						||
| 
								 | 
							
											beq[no_writeback#]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											alu[$stemp, $rsw0, and, 0x1f]
							 | 
						||
| 
								 | 
							
											alu[$stemp2, --, b, _packet_length]
							 | 
						||
| 
								 | 
							
											sram[write, $stemp, _buffer_handle, 8, 2], ctx_swap[zzz]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										no_writeback#:
							 | 
						||
| 
								 | 
							
										.end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/*
							 | 
						||
| 
								 | 
							
										 * Resynchronise.
							 | 
						||
| 
								 | 
							
										 */
							 | 
						||
| 
								 | 
							
										.begin
							 | 
						||
| 
								 | 
							
											ctx_arb[sig3]
							 | 
						||
| 
								 | 
							
											local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig3 << 3))]
							 | 
						||
| 
								 | 
							
										.end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										/*
							 | 
						||
| 
								 | 
							
										 * If EOP, put the buffer back onto the scratch ring.
							 | 
						||
| 
								 | 
							
										 */
							 | 
						||
| 
								 | 
							
										.begin
							 | 
						||
| 
								 | 
							
											.reg write $stemp
							 | 
						||
| 
								 | 
							
											.sig zzz
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											br_inp_state[SCR_Ring1_Status, rx_done_ring_overflow#]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											alu_shf[--, 1, and, $rsw0, >>14]
							 | 
						||
| 
								 | 
							
											beq[mpacket_receive_loop#]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											alu[--, 1, and, $rsw0, >>10]
							 | 
						||
| 
								 | 
							
											bne[rxerr#]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
											alu[$stemp, --, b, _buffer_handle]
							 | 
						||
| 
								 | 
							
											scratch[put, $stemp, zero, 4, 1], ctx_swap[zzz]
							 | 
						||
| 
								 | 
							
											cap[fast_wr, 0, XSCALE_INT_A]
							 | 
						||
| 
								 | 
							
											br[mpacket_receive_loop#]
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
										rxerr#:
							 | 
						||
| 
								 | 
							
											alu[$stemp, --, b, _buffer_handle]
							 | 
						||
| 
								 | 
							
											scratch[put, $stemp, zero, 0, 1], ctx_swap[zzz]
							 | 
						||
| 
								 | 
							
											br[mpacket_receive_loop#]
							 | 
						||
| 
								 | 
							
										.end
							 | 
						||
| 
								 | 
							
									.end
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								abort_rswerr#:
							 | 
						||
| 
								 | 
							
									halt
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								abort_proterr#:
							 | 
						||
| 
								 | 
							
									halt
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								state_corrupted#:
							 | 
						||
| 
								 | 
							
									halt
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								buffer_overflow#:
							 | 
						||
| 
								 | 
							
									halt
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								rx_done_ring_overflow#:
							 | 
						||
| 
								 | 
							
									halt
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 |