⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ixp2400_tx.uc

📁 linux2.6.16版本
💻 UC
字号:
/* * 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 zero	immed[zero, 0]	/*	 * Skip context 0 initialisation?	 */	.begin		br!=ctx[0, mpacket_tx_loop#]	.end	/*	 * Wait until all pending TBUF elements have been transmitted.	 */	.begin		.reg read $tx		.sig zzz	loop_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]	.end	immed[@mpkts_in_flight, 0]	alu[@next_tbuf_mpacket, @old_tx_seq_0, and, (PARTITION_SIZE - 1)]	immed[@buffer_handle, 0]	/*	 * 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	.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 zzz			ctx_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.		 */		.begin			alu[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 zzz			ctx_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_sig			alu[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 zzz			alu_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.		 */		.begin			ctx_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 zzz			alu[--, 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

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -