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

📄 e100lpslave.s

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 S
字号:
	;; $Id: e100lpslave.S,v 1.3 2001/06/21 16:55:26 olof Exp $	;;	;; Etrax100 slave network<->parport forwarder	;;	;; Copyright (c) 1999 Bjorn Wesen, Axis Communications AB	;;	;; We got 784 bytes (par loader size) to do DMA forwarding	;; between DMA0/1 (ethernet) and DMA3/4 (par port 0 RX/1 TX)	;;#include <linux/config.h>#if 0#define ASSEMBLER_MACROS_ONLY#endif#include <asm/sv_addr_ag.h>#define BUFSIZE 0x600	;; R_IRQ_READ2#define DMA1EOPBIT 3#define DMA0EOPBIT 1#define DMA3EOPBIT 7#define DMA4DESCBIT 8	;; R_IRQ_READ0#define PAR0ECPCMDBIT 11	;; get host CMDs#include "e100lpslave.h"start:	;; disable interrupts. we are not going to use them at all.	di	;; setup DMA connections and port configuration	movu.w	0x84, r0	; DMA2/3/4/5 to par ports	move.d	r0, [R_GEN_CONFIG]	;; setup port PA dirs and turn on the LED to show were alive	movu.w	0x0cfb, r0	; PA2-PA3 out, PA2 inactive	move.d	r0, [R_PORT_PA_SET]	;; enable MDIO output pin	moveq IO_STATE(R_NETWORK_MGM_CTRL, mdoe, enable), r0	move.d	r0, [R_NETWORK_MGM_CTRL]	;; accept broadcast frames, and enable station address 0	moveq	IO_STATE(R_NETWORK_REC_CONFIG, broadcast, receive) | \		IO_STATE(R_NETWORK_REC_CONFIG, ma0, enable), r0	move.d	r0, [R_NETWORK_REC_CONFIG]	;; use MII CLK mode, and enable the controller	moveq	IO_STATE(R_NETWORK_GEN_CONFIG, phy, mii_clk) | \		IO_STATE(R_NETWORK_GEN_CONFIG, enable, on), r0	move.d	r0, [R_NETWORK_GEN_CONFIG]	move.d	IO_STATE(R_PAR0_CONFIG, ioe,     noninv)    |  \		IO_STATE(R_PAR0_CONFIG, iseli,   noninv)    |  \		IO_STATE(R_PAR0_CONFIG, iautofd, noninv)    |  \		IO_STATE(R_PAR0_CONFIG, istrb,   noninv)    |  \		IO_STATE(R_PAR0_CONFIG, iinit,   noninv)    |  \		IO_STATE(R_PAR0_CONFIG, iperr,   noninv)    |  \		IO_STATE(R_PAR0_CONFIG, iack,    noninv)    |  \		IO_STATE(R_PAR0_CONFIG, ibusy,   noninv)    |  \		IO_STATE(R_PAR0_CONFIG, ifault,  noninv)    |  \		IO_STATE(R_PAR0_CONFIG, isel,    noninv)    |  \		IO_STATE(R_PAR0_CONFIG, dma, enable)        |  \		IO_STATE(R_PAR0_CONFIG, rle_in, disable)    |  \		IO_STATE(R_PAR0_CONFIG, rle_out, disable)   |  \		IO_STATE(R_PAR0_CONFIG, enable, on)         |  \		IO_STATE(R_PAR0_CONFIG, force, on)          |  \		IO_STATE(R_PAR0_CONFIG, mode, ecp_rev), r0	; Reverse ECP - PAR0 is RX	move.d	r0, [R_PAR0_CONFIG]	move.d	IO_STATE(R_PAR1_CONFIG, ioe,     noninv)    |  \		IO_STATE(R_PAR1_CONFIG, iseli,   noninv)    |  \		IO_STATE(R_PAR1_CONFIG, iautofd, noninv)    |  \		IO_STATE(R_PAR1_CONFIG, istrb,   noninv)    |  \		IO_STATE(R_PAR1_CONFIG, iinit,   noninv)    |  \		IO_STATE(R_PAR1_CONFIG, iperr,   inv)       |  \		IO_STATE(R_PAR1_CONFIG, iack,    noninv)    |  \		IO_STATE(R_PAR1_CONFIG, ibusy,   noninv)    |  \		IO_STATE(R_PAR1_CONFIG, ifault,  noninv)    |  \		IO_STATE(R_PAR1_CONFIG, isel,    noninv)    |  \		IO_STATE(R_PAR1_CONFIG, dma, enable)        |  \		IO_STATE(R_PAR1_CONFIG, rle_in, disable)    |  \		IO_STATE(R_PAR1_CONFIG, rle_out, disable)   |  \		IO_STATE(R_PAR1_CONFIG, enable, on)         |  \		IO_STATE(R_PAR1_CONFIG, force, on)          |  \		IO_STATE(R_PAR1_CONFIG, mode, ecp_fwd), r0	; Forward ECP - PAR1 is TX	move.d	r0, [R_PAR1_CONFIG]	moveq	IO_FIELD(R_PAR1_DELAY, setup, 0), r0    ; setup time of value * 160 + 20 == 20 ns	move.d	r0, [R_PAR1_DELAY]	;; we got four descriptors, that can be active at the same time:	;; 1) from network	;; 2) to parport	;; 3) from parport	;; 4) to network	;;	;; we got four buffers, each can hold a max packet (we use 1536 bytes)	;; buffers 1 and 2 are used from network to parport, while	;; buffers 3 and 4 are used from parport to network.	;; 	;; a double buffering scheme is used, so that new data can be read	;; into a buffer pair while the last data is written out from the	;; last buffer. if the read buffer is done before the write buffer,	;; the reading will halt until the writing is done, at which point	;; writing starts from the newly read and reading can start with	;; the newly written.	;; 	move.d	R_DMA_CH0_FIRST, r1   ; we use this as base for subsequent DMA ops	moveq	IO_STATE(R_DMA_CH1_CMD, cmd, start), r6	move.d	FN1desc, r7	move.d	R_IRQ_READ0, r9	;; start receiving from network	jsr	startdmaFPTN	jsr	startdmaFNTP		;; ------------------- MAIN LOOP	;; IRQ bits:	parport rcv is par0_ecp_cmd, then dma3_eop	;;              network rcv is dma1_eop	;;              parport tx  is dma4_desc	;;              network tx  is dma0_eopmainloop:	;; ------- first handle the parport -> network link	;; check if we got something from the parport	move.d	[r9], r0	; r0 <- *R_IRQ_READ0	btstq	PAR0ECPCMDBIT, r0	bpl	noparecp	nop	;; ack it by reading PAR0_STATUS_DATA	move.d	[R_PAR0_STATUS_DATA], r0	;; trigger EOP on DMA3 (par0 incoming channel)	moveq	IO_STATE(R_SET_EOP, ch3_eop, set), r0	move.d	r0, [R_SET_EOP]noparecp:	;; if we simultaneously have parport rx EOP and	;; network TX eop, we can swap buffers and start a new RX/TX	move.d	[r9 + (R_IRQ_READ2 - R_IRQ_READ0)], r0	btstq	DMA3EOPBIT, r0	; check parport rx	bpl	noswap1	btstq	DMA0EOPBIT, r0	; check network tx	bpl	noswap1	nop	;; prepare to swap buffer ptrs (FN3b <-> TN4b)	move.d	[r4 = r7 + 56], r0; FP3b	move.d	[r3 = r7 + 72], r2; TN4b	;; but first check if this was a Host Command Packet	move.d	[r0], r5	; r5 <- first 4 bytes in PAR-received packet	bne	handle_command	; if non-zero, it was a host command	addq	4, r0		; skip command (in delay slot - handle_command requires this)	move.d	r0, [r3]	; write to To Network descriptor	subq	4, r2		; undo the skipping done last swap	move.d	r2, [r4]	; write to From Parport descriptor	;; clear the interrupts	moveq	IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do), r0	move.b	r0, [r1 + (R_DMA_CH0_CLR_INTR - R_DMA_CH0_FIRST)]	move.b	r0, [r1 + (R_DMA_CH3_CLR_INTR - R_DMA_CH0_FIRST)]	;; copy received length to outgoing network length	move.w	[r7 + 60], r0	; FPhlen	subq	4, r0		; skip command	move.w	r0, [r7 + 64]	; TN4desc	;; restart DMAs	jsr	startdmaFPTN#ifdef CONFIG_ETRAX_ETHERNET_LPSLAVE_HAS_LEDS#if defined(CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK)	;; Turn off the LED signaling an outgoing network packet	movu.b	[LEDOff], r0#elif defined(CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY)	;; Light the LED signaling an outgoing network packet	movu.b	[LEDAmber], r0#else#error "Define either CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK or CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY"	#endif 	move.b	r0, [R_PORT_PA_DATA]	move.d	0x00011000, r0	move.d	r0,[LEDCount]#endifnoswap1:	;; ----- now check the network -> parport link	;; if we simultaneously have network rx EOP and	;; parport TX desc, we can swap buffers and start a new RX/TX	move.d	[r9 + (R_IRQ_READ2 - R_IRQ_READ0)], r0	btstq	DMA1EOPBIT, r0	; check network rx	bpl	noswap2	btstq	DMA4DESCBIT, r0	; check parport tx	bpl	noswap2	nop	;; prepare to swap buffer ptrs (FP1b <-> TP2b)	move.d	[r4 = r7 +  8], r0; FN1b	move.d	[r3 = r7 + 24], r2; TP2b	move.d	r0, [r3]	; write to To Parport descriptor	move.d	r2, [r4]	; write to From Network descriptor	;; clear the interrupts	moveq	IO_STATE(R_DMA_CH1_CLR_INTR, clr_eop, do) | \		IO_STATE(R_DMA_CH1_CLR_INTR, clr_descr, do), r0	move.b	r0, [r1 + (R_DMA_CH1_CLR_INTR - R_DMA_CH0_FIRST)]	move.b	r0, [r1 + (R_DMA_CH4_CLR_INTR - R_DMA_CH0_FIRST)]	;; copy received network length to outgoing parport length	move.w	[r7 + 12], r0	; FNhlen	move.w	r0, [r7 + 16]	; TP2desc	;; restart DMAs	jsr	startdmaFNTP#if 0#ifdef CONFIG_ETRAX_ETHERNET_LPSLAVE_HAS_LEDS	;; Light the LED signaling an incoming networkpacket	movu.b	0xFB, r0	move.b	r0, [R_PORT_PA_DATA]	move.d	0x00010000, r0	move.d	r0,[LEDCount]#endif#endifnoswap2:#ifdef CONFIG_ETRAX_ETHERNET_LPSLAVE_HAS_LEDS	;; Count down LED counter, and turn off the network LED if required	move.d	[LEDCount], r0	beq	mainloop	nop	subq	1, r0	move.d	r0, [LEDCount]		bne	mainloop	nop#if defined(CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK)		;; Light the network LED , and start over the main loop	movu.b	[LEDAmber], r0#elif defined(CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY)			;; Turn off the network LED, and start over the main loop	movu.b	[LEDOff], r0#else#error "Define either CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK or CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY"	#endif	move.b	r0, [R_PORT_PA_DATA]#endif	ba	mainloop	nop	;; --- some useful subroutines.handle_command:	;; handle command. we also need to clear the PAR0 RX EOP IRQ, and 	;; restart the PAR0 dma. command is in R5, packet after cmd is in R0	moveq	IO_STATE(R_DMA_CH3_CLR_INTR, clr_eop, do), r2	move.b	r2, [r1 + (R_DMA_CH3_CLR_INTR - R_DMA_CH0_FIRST)]	cmpq	HOST_CMD_SETMAC, r5	bne	no_setmac	nop	;; copy station address (6 bytes) from packet to hardware	move.d	[r0+], r2	move.d	R_NETWORK_SA_0, r3	move.d	r2, [r3]	move.w	[r0], r2	move.w	r2, [r3 + 4] no_setmac:	move	noswap1, SRP	ba	startdmaFP	nop	;; start DMAs, from parport and to networkstartdmaFPTN:	;; start transmitting to the network (CH0)	move.d	TN4desc, r8	move.d	r8, [r1]					; TN4desc -> FIRST0	move.b	r6, [r1 + (R_DMA_CH0_CMD - R_DMA_CH0_FIRST)]	; start -> CMD0startdmaFP:	;; start receiving from parport (CH3)	move.d	FP3desc, r8	move.d	r8, [r1 + (R_DMA_CH3_FIRST - R_DMA_CH0_FIRST)]  ; FP3desc -> FIRST3	move.b	r6, [r1 + (R_DMA_CH3_CMD - R_DMA_CH0_FIRST)]	; start -> CMD3	ret	nop	;; start DMAs, from network and to parportstartdmaFNTP:	;; start transmitting to the parport (CH4)	move.d	TP2desc, r8	move.d	r8, [r1 + (R_DMA_CH4_FIRST - R_DMA_CH0_FIRST)]	; TP2desc -> FIRST4	move.b	r6, [r1 + (R_DMA_CH4_CMD - R_DMA_CH0_FIRST)]	; start -> CMD4	;; start receiving from network (CH1) (r7 already contains FN1desc)	move.d	r7, [r1 + (R_DMA_CH1_FIRST - R_DMA_CH0_FIRST)]  ; FN1desc -> FIRST1	move.b	r6, [r1 + (R_DMA_CH1_CMD - R_DMA_CH0_FIRST)]	; start -> CMD1	ret	nop	;; --- DMA descriptors - each descriptor is 4 longwords (16 bytes)	;; DONT MOVE THESE AROUND. Due to the as/ld "hole-in-the-head",	;; we cant write stuff like (TP2b - TP2desc) but the offsets	;; have to be hardcoded.	.data	;; 0 from networkFN1desc:	.word	BUFSIZE		; sw_len	.word	0x0001		; ctrl, d_eol is only flag we need	.dword	0		; nextFN1b:	.dword	buffers		; buffer 1 8	.word	0		; hw_len	.word	0		; status	;; 16 to parportTP2desc:	.word	2		; sw_len, filled in by code 	.word	0x0004		; ctrl, d_wait because ecp cmd in next	.dword	TP2desc2	; nextTP2b:	.dword	buffers + BUFSIZE ; buffer 2 24	.word	0		; hw_len	.word	0		; status	;; 32 to parport second descriptor, for the ECP commandTP2desc2:	.word	0x0001		; sw_len, 1 byte (ecp command) 	.word	0x0019		; ctrl, d_ecp | d_eol | d_int	.dword	0		; next	.dword	TP2desc2	; buffer, dont care	.word	0		; hw_len	.word	0		; status	;; 48 from parportFP3desc:	.word	BUFSIZE		; sw_len	.word	0x0001		; ctrl, d_eol is only flag we need	.dword	0		; nextFP3b:	.dword	buffers + BUFSIZE * 2 ; 56 buffer 3FPhlen:	.word	0		; 60 hw_len	.word	0		; status	;; 64 to networkTN4desc:	.word	2		; sw_len, filled in by code 	.word	0x0007		; ctrl, d_eop | d_eol | d_wait	.dword	0		; nextTN4b:	.dword	buffers + BUFSIZE * 3 + 4	; 72 buffer 4 (the +4 is to offset the anti-skipping)	.word	0		; hw_len	.word	0		; status#ifdef CONFIG_ETRAX_ETHERNET_LPSLAVE_HAS_LEDSLEDCount:	.dword	0LEDOff:		.word	0xffLEDGreen:	.word	0xfbLEDRed:	.word	0xf7LEDAmber:	.word	0xf3LED:	.word	0xf7#endif	;; after the prog we put the buffers. not in the asm program, we just use	;; the address generatedbuffers:	;; END

⌨️ 快捷键说明

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