URL
https://opencores.org/ocsvn/test_project/test_project/trunk
Subversion Repositories test_project
[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [net/] [ixp2000/] [ixp2400_rx.uc] - Rev 62
Compare with Previous | Blame | View Log
/** 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 temp2immed[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].endimmed[zero, 0]/** Skip context 0 initialisation?*/.beginbr!=ctx[0, mpacket_receive_loop#].end/** Initialise local memory.*/.begin.reg addr.reg tempimmed[temp, 0]init_local_mem_loop#:alu_shf[addr, --, b, temp, <<CHANNEL_STATE_SHIFT]local_csr_wr[ACTIVE_LM_ADDR_0, addr]nopnopnopimmed[CHANNEL_FLAGS, 0]alu[temp, temp, +, 1]alu[--, temp, and, 0x20]beq[init_local_mem_loop#].end/** Initialise signal pipeline.*/.beginlocal_csr_wr[SAME_ME_SIGNAL, (&sig1 << 3)].set_sig sig1local_csr_wr[SAME_ME_SIGNAL, (&sig2 << 3)].set_sig sig2local_csr_wr[SAME_ME_SIGNAL, (&sig3 << 3)].set_sig sig3.endmpacket_receive_loop#:/** Synchronise and wait for mpacket.*/.beginctx_arb[sig1]local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig1 << 3))]msf[fast_wr, --, add_to_rx_freelist, 0].set_sig mpacket_arrivedctx_arb[mpacket_arrived].set $rsw0 $rsw1.end/** We halt if we see {inbparerr,parerr,null,soperror}.*/.beginalu_shf[--, 0x1b, and, $rsw0, >>8]bne[abort_rswerr#].end/** Point local memory pointer to this channel's state area.*/.begin.reg chanaddralu[chanaddr, $rsw0, and, 0x1f]alu_shf[chanaddr, --, b, chanaddr, <<CHANNEL_STATE_SHIFT]local_csr_wr[ACTIVE_LM_ADDR_0, chanaddr]nopnopnop.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#endifalu_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 tempalu[--, 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 tempalu[temp, 1, and, $rsw0, >>15]beq[skip_buffer_alloc#].begin.sig zzz.reg read $stemp $stemp2.xfer_order $stemp $stemp2rx_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].endskip_buffer_alloc#:.end/** Resynchronise.*/.beginctx_arb[sig2]local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig2 << 3))].end/** Synchronise buffer state.*/.begin.reg tempalu[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 tempalu[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.*/.beginalu[--, _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_sigalu_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 zzzalu_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.*/.beginctx_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 zzzbr_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.endabort_rswerr#:haltabort_proterr#:haltstate_corrupted#:haltbuffer_overflow#:haltrx_done_ring_overflow#:halt
