OpenCores
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 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


Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.