URL
https://opencores.org/ocsvn/test_project/test_project/trunk
Subversion Repositories test_project
[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [net/] [ixp2000/] [ixp2400_tx.uc] - Rev 62
Compare with Previous | Blame | View Log
/** TX 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 TBUF partition 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 TBUF uses 64-byte mpackets.* - TX descriptors reside in SRAM, and have the following format:* struct tx_desc* {* // to uengine* u32 buf_phys_addr;* u32 pkt_length;* u32 channel;* };* - Packet data resides in DRAM.* - Packet buffer addresses are 8-byte aligned.* - Scratch ring 2 is tx_pending.* - Scratch ring 3 is tx_done, and has status condition 'full'.* - This code is run on all eight threads of the microengine it runs on.*/#define TX_SEQUENCE_0 0x0060#define TBUF_CTRL 0x1800#define PARTITION_SIZE 128#define PARTITION_THRESH 96.sig volatile sig1.sig volatile sig2.sig volatile sig3.reg @old_tx_seq_0.reg @mpkts_in_flight.reg @next_tbuf_mpacket.reg @buffer_handle.reg @buffer_start.reg @packet_length.reg @channel.reg @packet_offset.reg zeroimmed[zero, 0]/** Skip context 0 initialisation?*/.beginbr!=ctx[0, mpacket_tx_loop#].end/** Wait until all pending TBUF elements have been transmitted.*/.begin.reg read $tx.sig zzzloop_empty#:msf[read, $tx, zero, TX_SEQUENCE_0, 1], ctx_swap[zzz]alu_shf[--, --, b, $tx, >>31]beq[loop_empty#]alu[@old_tx_seq_0, --, b, $tx].endimmed[@mpkts_in_flight, 0]alu[@next_tbuf_mpacket, @old_tx_seq_0, and, (PARTITION_SIZE - 1)]immed[@buffer_handle, 0]/** 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_tx_loop#:.begin.reg tbuf_element_index.reg buffer_handle.reg sop_eop.reg packet_data.reg channel.reg mpacket_size/** If there is no packet currently being transmitted,* dequeue the next TX descriptor, and fetch the buffer* address, packet length and destination channel number.*/.begin.reg read $stemp $stemp2 $stemp3.xfer_order $stemp $stemp2 $stemp3.sig zzzctx_arb[sig1]alu[--, --, b, @buffer_handle]bne[already_got_packet#]tx_nobufs#:scratch[get, $stemp, zero, 8, 1], ctx_swap[zzz]alu[@buffer_handle, --, b, $stemp]beq[tx_nobufs#]sram[read, $stemp, $stemp, 0, 3], ctx_swap[zzz]alu[@buffer_start, --, b, $stemp]alu[@packet_length, --, b, $stemp2]beq[zero_byte_packet#]alu[@channel, --, b, $stemp3]immed[@packet_offset, 0]already_got_packet#:local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig1 << 3))].end/** Determine tbuf element index, SOP/EOP flags, mpacket* offset and mpacket size and cache buffer_handle and* channel number.*/.beginalu[tbuf_element_index, --, b, @next_tbuf_mpacket]alu[@next_tbuf_mpacket, @next_tbuf_mpacket, +, 1]alu[@next_tbuf_mpacket, @next_tbuf_mpacket, and,(PARTITION_SIZE - 1)]alu[buffer_handle, --, b, @buffer_handle]immed[@buffer_handle, 0]immed[sop_eop, 1]alu[packet_data, --, b, @packet_offset]bne[no_sop#]alu[sop_eop, sop_eop, or, 2]no_sop#:alu[packet_data, packet_data, +, @buffer_start]alu[channel, --, b, @channel]alu[mpacket_size, @packet_length, -, @packet_offset]alu[--, 64, -, mpacket_size]bhs[eop#]alu[@buffer_handle, --, b, buffer_handle]immed[mpacket_size, 64]alu[sop_eop, sop_eop, and, 2]eop#:alu[@packet_offset, @packet_offset, +, mpacket_size].end/** Wait until there's enough space in the TBUF.*/.begin.reg read $tx.reg temp.sig zzzctx_arb[sig2]br[test_space#]loop_space#:msf[read, $tx, zero, TX_SEQUENCE_0, 1], ctx_swap[zzz]alu[temp, $tx, -, @old_tx_seq_0]alu[temp, temp, and, 0xff]alu[@mpkts_in_flight, @mpkts_in_flight, -, temp]alu[@old_tx_seq_0, --, b, $tx]test_space#:alu[--, PARTITION_THRESH, -, @mpkts_in_flight]blo[loop_space#]alu[@mpkts_in_flight, @mpkts_in_flight, +, 1]local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig2 << 3))].end/** Copy the packet data to the TBUF.*/.begin.reg temp.sig copy_sigalu[temp, mpacket_size, -, 1]alu_shf[temp, 0x10, or, temp, >>3]alu_shf[temp, 0x10, or, temp, <<21]alu_shf[temp, temp, or, tbuf_element_index, <<11]alu_shf[--, temp, or, 1, <<18]dram[tbuf_wr, --, packet_data, 0, max_8],indirect_ref, sig_done[copy_sig]ctx_arb[copy_sig].end/** Mark TBUF element as ready-to-be-transmitted.*/.begin.reg write $tsw $tsw2.xfer_order $tsw $tsw2.reg temp.sig zzzalu_shf[temp, channel, or, mpacket_size, <<24]alu_shf[$tsw, temp, or, sop_eop, <<8]immed[$tsw2, 0]immed[temp, TBUF_CTRL]alu_shf[temp, temp, or, tbuf_element_index, <<3]msf[write, $tsw, temp, 0, 2], ctx_swap[zzz].end/** Resynchronise.*/.beginctx_arb[sig3]local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig3 << 3))].end/** If this was an EOP mpacket, recycle the TX buffer* and signal the host.*/.begin.reg write $stemp.sig zzzalu[--, sop_eop, and, 1]beq[mpacket_tx_loop#]tx_done_ring_full#:br_inp_state[SCR_Ring3_Status, tx_done_ring_full#]alu[$stemp, --, b, buffer_handle]scratch[put, $stemp, zero, 12, 1], ctx_swap[zzz]cap[fast_wr, 0, XSCALE_INT_A]br[mpacket_tx_loop#].end.endzero_byte_packet#:halt
