e100lpslave.S
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:11k
源码类别:

Linux/Unix编程

开发平台:

Unix_Linux

  1. ;; $Id: e100lpslave.S,v 1.3 2001/06/21 16:55:26 olof Exp $
  2. ;;
  3. ;; Etrax100 slave network<->parport forwarder
  4. ;;
  5. ;; Copyright (c) 1999 Bjorn Wesen, Axis Communications AB
  6. ;;
  7. ;; We got 784 bytes (par loader size) to do DMA forwarding
  8. ;; between DMA0/1 (ethernet) and DMA3/4 (par port 0 RX/1 TX)
  9. ;;
  10. #include <linux/config.h>
  11. #if 0
  12. #define ASSEMBLER_MACROS_ONLY
  13. #endif
  14. #include <asm/sv_addr_ag.h>
  15. #define BUFSIZE 0x600
  16. ;; R_IRQ_READ2
  17. #define DMA1EOPBIT 3
  18. #define DMA0EOPBIT 1
  19. #define DMA3EOPBIT 7
  20. #define DMA4DESCBIT 8
  21. ;; R_IRQ_READ0
  22. #define PAR0ECPCMDBIT 11
  23. ;; get host CMDs
  24. #include "e100lpslave.h"
  25. start:
  26. ;; disable interrupts. we are not going to use them at all.
  27. di
  28. ;; setup DMA connections and port configuration
  29. movu.w 0x84, r0 ; DMA2/3/4/5 to par ports
  30. move.d r0, [R_GEN_CONFIG]
  31. ;; setup port PA dirs and turn on the LED to show were alive
  32. movu.w 0x0cfb, r0 ; PA2-PA3 out, PA2 inactive
  33. move.d r0, [R_PORT_PA_SET]
  34. ;; enable MDIO output pin
  35. moveq IO_STATE(R_NETWORK_MGM_CTRL, mdoe, enable), r0
  36. move.d r0, [R_NETWORK_MGM_CTRL]
  37. ;; accept broadcast frames, and enable station address 0
  38. moveq IO_STATE(R_NETWORK_REC_CONFIG, broadcast, receive) | 
  39. IO_STATE(R_NETWORK_REC_CONFIG, ma0, enable), r0
  40. move.d r0, [R_NETWORK_REC_CONFIG]
  41. ;; use MII CLK mode, and enable the controller
  42. moveq IO_STATE(R_NETWORK_GEN_CONFIG, phy, mii_clk) | 
  43. IO_STATE(R_NETWORK_GEN_CONFIG, enable, on), r0
  44. move.d r0, [R_NETWORK_GEN_CONFIG]
  45. move.d IO_STATE(R_PAR0_CONFIG, ioe,     noninv)    |  
  46. IO_STATE(R_PAR0_CONFIG, iseli,   noninv)    |  
  47. IO_STATE(R_PAR0_CONFIG, iautofd, noninv)    |  
  48. IO_STATE(R_PAR0_CONFIG, istrb,   noninv)    |  
  49. IO_STATE(R_PAR0_CONFIG, iinit,   noninv)    |  
  50. IO_STATE(R_PAR0_CONFIG, iperr,   noninv)    |  
  51. IO_STATE(R_PAR0_CONFIG, iack,    noninv)    |  
  52. IO_STATE(R_PAR0_CONFIG, ibusy,   noninv)    |  
  53. IO_STATE(R_PAR0_CONFIG, ifault,  noninv)    |  
  54. IO_STATE(R_PAR0_CONFIG, isel,    noninv)    |  
  55. IO_STATE(R_PAR0_CONFIG, dma, enable)        |  
  56. IO_STATE(R_PAR0_CONFIG, rle_in, disable)    |  
  57. IO_STATE(R_PAR0_CONFIG, rle_out, disable)   |  
  58. IO_STATE(R_PAR0_CONFIG, enable, on)         |  
  59. IO_STATE(R_PAR0_CONFIG, force, on)          |  
  60. IO_STATE(R_PAR0_CONFIG, mode, ecp_rev), r0 ; Reverse ECP - PAR0 is RX
  61. move.d r0, [R_PAR0_CONFIG]
  62. move.d IO_STATE(R_PAR1_CONFIG, ioe,     noninv)    |  
  63. IO_STATE(R_PAR1_CONFIG, iseli,   noninv)    |  
  64. IO_STATE(R_PAR1_CONFIG, iautofd, noninv)    |  
  65. IO_STATE(R_PAR1_CONFIG, istrb,   noninv)    |  
  66. IO_STATE(R_PAR1_CONFIG, iinit,   noninv)    |  
  67. IO_STATE(R_PAR1_CONFIG, iperr,   inv)       |  
  68. IO_STATE(R_PAR1_CONFIG, iack,    noninv)    |  
  69. IO_STATE(R_PAR1_CONFIG, ibusy,   noninv)    |  
  70. IO_STATE(R_PAR1_CONFIG, ifault,  noninv)    |  
  71. IO_STATE(R_PAR1_CONFIG, isel,    noninv)    |  
  72. IO_STATE(R_PAR1_CONFIG, dma, enable)        |  
  73. IO_STATE(R_PAR1_CONFIG, rle_in, disable)    |  
  74. IO_STATE(R_PAR1_CONFIG, rle_out, disable)   |  
  75. IO_STATE(R_PAR1_CONFIG, enable, on)         |  
  76. IO_STATE(R_PAR1_CONFIG, force, on)          |  
  77. IO_STATE(R_PAR1_CONFIG, mode, ecp_fwd), r0 ; Forward ECP - PAR1 is TX
  78. move.d r0, [R_PAR1_CONFIG]
  79. moveq IO_FIELD(R_PAR1_DELAY, setup, 0), r0    ; setup time of value * 160 + 20 == 20 ns
  80. move.d r0, [R_PAR1_DELAY]
  81. ;; we got four descriptors, that can be active at the same time:
  82. ;; 1) from network
  83. ;; 2) to parport
  84. ;; 3) from parport
  85. ;; 4) to network
  86. ;;
  87. ;; we got four buffers, each can hold a max packet (we use 1536 bytes)
  88. ;; buffers 1 and 2 are used from network to parport, while
  89. ;; buffers 3 and 4 are used from parport to network.
  90. ;; 
  91. ;; a double buffering scheme is used, so that new data can be read
  92. ;; into a buffer pair while the last data is written out from the
  93. ;; last buffer. if the read buffer is done before the write buffer,
  94. ;; the reading will halt until the writing is done, at which point
  95. ;; writing starts from the newly read and reading can start with
  96. ;; the newly written.
  97. ;; 
  98. move.d R_DMA_CH0_FIRST, r1   ; we use this as base for subsequent DMA ops
  99. moveq IO_STATE(R_DMA_CH1_CMD, cmd, start), r6
  100. move.d FN1desc, r7
  101. move.d R_IRQ_READ0, r9
  102. ;; start receiving from network
  103. jsr startdmaFPTN
  104. jsr startdmaFNTP
  105. ;; ------------------- MAIN LOOP
  106. ;; IRQ bits: parport rcv is par0_ecp_cmd, then dma3_eop
  107. ;;              network rcv is dma1_eop
  108. ;;              parport tx  is dma4_desc
  109. ;;              network tx  is dma0_eop
  110. mainloop:
  111. ;; ------- first handle the parport -> network link
  112. ;; check if we got something from the parport
  113. move.d [r9], r0 ; r0 <- *R_IRQ_READ0
  114. btstq PAR0ECPCMDBIT, r0
  115. bpl noparecp
  116. nop
  117. ;; ack it by reading PAR0_STATUS_DATA
  118. move.d [R_PAR0_STATUS_DATA], r0
  119. ;; trigger EOP on DMA3 (par0 incoming channel)
  120. moveq IO_STATE(R_SET_EOP, ch3_eop, set), r0
  121. move.d r0, [R_SET_EOP]
  122. noparecp:
  123. ;; if we simultaneously have parport rx EOP and
  124. ;; network TX eop, we can swap buffers and start a new RX/TX
  125. move.d [r9 + (R_IRQ_READ2 - R_IRQ_READ0)], r0
  126. btstq DMA3EOPBIT, r0 ; check parport rx
  127. bpl noswap1
  128. btstq DMA0EOPBIT, r0 ; check network tx
  129. bpl noswap1
  130. nop
  131. ;; prepare to swap buffer ptrs (FN3b <-> TN4b)
  132. move.d [r4 = r7 + 56], r0; FP3b
  133. move.d [r3 = r7 + 72], r2; TN4b
  134. ;; but first check if this was a Host Command Packet
  135. move.d [r0], r5 ; r5 <- first 4 bytes in PAR-received packet
  136. bne handle_command ; if non-zero, it was a host command
  137. addq 4, r0 ; skip command (in delay slot - handle_command requires this)
  138. move.d r0, [r3] ; write to To Network descriptor
  139. subq 4, r2 ; undo the skipping done last swap
  140. move.d r2, [r4] ; write to From Parport descriptor
  141. ;; clear the interrupts
  142. moveq IO_STATE(R_DMA_CH0_CLR_INTR, clr_eop, do), r0
  143. move.b r0, [r1 + (R_DMA_CH0_CLR_INTR - R_DMA_CH0_FIRST)]
  144. move.b r0, [r1 + (R_DMA_CH3_CLR_INTR - R_DMA_CH0_FIRST)]
  145. ;; copy received length to outgoing network length
  146. move.w [r7 + 60], r0 ; FPhlen
  147. subq 4, r0 ; skip command
  148. move.w r0, [r7 + 64] ; TN4desc
  149. ;; restart DMAs
  150. jsr startdmaFPTN
  151. #ifdef CONFIG_ETRAX_ETHERNET_LPSLAVE_HAS_LEDS
  152. #if defined(CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK)
  153. ;; Turn off the LED signaling an outgoing network packet
  154. movu.b [LEDOff], r0
  155. #elif defined(CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY)
  156. ;; Light the LED signaling an outgoing network packet
  157. movu.b [LEDAmber], r0
  158. #else
  159. #error "Define either CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK or CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY"
  160. #endif 
  161. move.b r0, [R_PORT_PA_DATA]
  162. move.d 0x00011000, r0
  163. move.d r0,[LEDCount]
  164. #endif
  165. noswap1:
  166. ;; ----- now check the network -> parport link
  167. ;; if we simultaneously have network rx EOP and
  168. ;; parport TX desc, we can swap buffers and start a new RX/TX
  169. move.d [r9 + (R_IRQ_READ2 - R_IRQ_READ0)], r0
  170. btstq DMA1EOPBIT, r0 ; check network rx
  171. bpl noswap2
  172. btstq DMA4DESCBIT, r0 ; check parport tx
  173. bpl noswap2
  174. nop
  175. ;; prepare to swap buffer ptrs (FP1b <-> TP2b)
  176. move.d [r4 = r7 +  8], r0; FN1b
  177. move.d [r3 = r7 + 24], r2; TP2b
  178. move.d r0, [r3] ; write to To Parport descriptor
  179. move.d r2, [r4] ; write to From Network descriptor
  180. ;; clear the interrupts
  181. moveq IO_STATE(R_DMA_CH1_CLR_INTR, clr_eop, do) | 
  182. IO_STATE(R_DMA_CH1_CLR_INTR, clr_descr, do), r0
  183. move.b r0, [r1 + (R_DMA_CH1_CLR_INTR - R_DMA_CH0_FIRST)]
  184. move.b r0, [r1 + (R_DMA_CH4_CLR_INTR - R_DMA_CH0_FIRST)]
  185. ;; copy received network length to outgoing parport length
  186. move.w [r7 + 12], r0 ; FNhlen
  187. move.w r0, [r7 + 16] ; TP2desc
  188. ;; restart DMAs
  189. jsr startdmaFNTP
  190. #if 0
  191. #ifdef CONFIG_ETRAX_ETHERNET_LPSLAVE_HAS_LEDS
  192. ;; Light the LED signaling an incoming networkpacket
  193. movu.b 0xFB, r0
  194. move.b r0, [R_PORT_PA_DATA]
  195. move.d 0x00010000, r0
  196. move.d r0,[LEDCount]
  197. #endif
  198. #endif
  199. noswap2:
  200. #ifdef CONFIG_ETRAX_ETHERNET_LPSLAVE_HAS_LEDS
  201. ;; Count down LED counter, and turn off the network LED if required
  202. move.d [LEDCount], r0
  203. beq mainloop
  204. nop
  205. subq 1, r0
  206. move.d r0, [LEDCount]
  207. bne mainloop
  208. nop
  209. #if defined(CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK)
  210. ;; Light the network LED , and start over the main loop
  211. movu.b [LEDAmber], r0
  212. #elif defined(CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY)
  213. ;; Turn off the network LED, and start over the main loop
  214. movu.b [LEDOff], r0
  215. #else
  216. #error "Define either CONFIG_ETRAX_NETWORK_LED_ON_WHEN_LINK or CONFIG_ETRAX_NETWORK_LED_ON_WHEN_ACTIVITY"
  217. #endif
  218. move.b r0, [R_PORT_PA_DATA]
  219. #endif
  220. ba mainloop
  221. nop
  222. ;; --- some useful subroutines.
  223. handle_command:
  224. ;; handle command. we also need to clear the PAR0 RX EOP IRQ, and 
  225. ;; restart the PAR0 dma. command is in R5, packet after cmd is in R0
  226. moveq IO_STATE(R_DMA_CH3_CLR_INTR, clr_eop, do), r2
  227. move.b r2, [r1 + (R_DMA_CH3_CLR_INTR - R_DMA_CH0_FIRST)]
  228. cmpq HOST_CMD_SETMAC, r5
  229. bne no_setmac
  230. nop
  231. ;; copy station address (6 bytes) from packet to hardware
  232. move.d [r0+], r2
  233. move.d R_NETWORK_SA_0, r3
  234. move.d r2, [r3]
  235. move.w [r0], r2
  236. move.w r2, [r3 + 4] 
  237. no_setmac:
  238. move noswap1, SRP
  239. ba startdmaFP
  240. nop
  241. ;; start DMAs, from parport and to network
  242. startdmaFPTN:
  243. ;; start transmitting to the network (CH0)
  244. move.d TN4desc, r8
  245. move.d r8, [r1] ; TN4desc -> FIRST0
  246. move.b r6, [r1 + (R_DMA_CH0_CMD - R_DMA_CH0_FIRST)] ; start -> CMD0
  247. startdmaFP:
  248. ;; start receiving from parport (CH3)
  249. move.d FP3desc, r8
  250. move.d r8, [r1 + (R_DMA_CH3_FIRST - R_DMA_CH0_FIRST)]  ; FP3desc -> FIRST3
  251. move.b r6, [r1 + (R_DMA_CH3_CMD - R_DMA_CH0_FIRST)] ; start -> CMD3
  252. ret
  253. nop
  254. ;; start DMAs, from network and to parport
  255. startdmaFNTP:
  256. ;; start transmitting to the parport (CH4)
  257. move.d TP2desc, r8
  258. move.d r8, [r1 + (R_DMA_CH4_FIRST - R_DMA_CH0_FIRST)] ; TP2desc -> FIRST4
  259. move.b r6, [r1 + (R_DMA_CH4_CMD - R_DMA_CH0_FIRST)] ; start -> CMD4
  260. ;; start receiving from network (CH1) (r7 already contains FN1desc)
  261. move.d r7, [r1 + (R_DMA_CH1_FIRST - R_DMA_CH0_FIRST)]  ; FN1desc -> FIRST1
  262. move.b r6, [r1 + (R_DMA_CH1_CMD - R_DMA_CH0_FIRST)] ; start -> CMD1
  263. ret
  264. nop
  265. ;; --- DMA descriptors - each descriptor is 4 longwords (16 bytes)
  266. ;; DONT MOVE THESE AROUND. Due to the as/ld "hole-in-the-head",
  267. ;; we cant write stuff like (TP2b - TP2desc) but the offsets
  268. ;; have to be hardcoded.
  269. .data
  270. ;; 0 from network
  271. FN1desc:
  272. .word BUFSIZE ; sw_len
  273. .word 0x0001 ; ctrl, d_eol is only flag we need
  274. .dword 0 ; next
  275. FN1b: .dword buffers ; buffer 1 8
  276. .word 0 ; hw_len
  277. .word 0 ; status
  278. ;; 16 to parport
  279. TP2desc:
  280. .word 2 ; sw_len, filled in by code 
  281. .word 0x0004 ; ctrl, d_wait because ecp cmd in next
  282. .dword TP2desc2 ; next
  283. TP2b: .dword buffers + BUFSIZE ; buffer 2 24
  284. .word 0 ; hw_len
  285. .word 0 ; status
  286. ;; 32 to parport second descriptor, for the ECP command
  287. TP2desc2:
  288. .word 0x0001 ; sw_len, 1 byte (ecp command) 
  289. .word 0x0019 ; ctrl, d_ecp | d_eol | d_int
  290. .dword 0 ; next
  291. .dword TP2desc2 ; buffer, dont care
  292. .word 0 ; hw_len
  293. .word 0 ; status
  294. ;; 48 from parport
  295. FP3desc:
  296. .word BUFSIZE ; sw_len
  297. .word 0x0001 ; ctrl, d_eol is only flag we need
  298. .dword 0 ; next
  299. FP3b: .dword buffers + BUFSIZE * 2 ; 56 buffer 3
  300. FPhlen: .word 0 ; 60 hw_len
  301. .word 0 ; status
  302. ;; 64 to network
  303. TN4desc:
  304. .word 2 ; sw_len, filled in by code 
  305. .word 0x0007 ; ctrl, d_eop | d_eol | d_wait
  306. .dword 0 ; next
  307. TN4b: .dword buffers + BUFSIZE * 3 + 4 ; 72 buffer 4 (the +4 is to offset the anti-skipping)
  308. .word 0 ; hw_len
  309. .word 0 ; status
  310. #ifdef CONFIG_ETRAX_ETHERNET_LPSLAVE_HAS_LEDS
  311. LEDCount:
  312. .dword 0
  313. LEDOff:
  314. .word 0xff
  315. LEDGreen:
  316. .word 0xfb
  317. LEDRed:
  318. .word 0xf7
  319. LEDAmber:
  320. .word 0xf3
  321. LED:
  322. .word 0xf7
  323. #endif
  324. ;; after the prog we put the buffers. not in the asm program, we just use
  325. ;; the address generated
  326. buffers:
  327. ;; END