ixp2400_rx.uc 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  1. /*
  2. * RX ucode for the Intel IXP2400 in POS-PHY mode.
  3. * Copyright (C) 2004, 2005 Lennert Buytenhek
  4. * Dedicated to Marija Kulikova.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Assumptions made in this code:
  12. * - The IXP2400 MSF is configured for POS-PHY mode, in a mode where
  13. * only one full element list is used. This includes, for example,
  14. * 1x32 SPHY and 1x32 MPHY32, but not 4x8 SPHY or 1x32 MPHY4. (This
  15. * is not an exhaustive list.)
  16. * - The RBUF uses 64-byte mpackets.
  17. * - RX descriptors reside in SRAM, and have the following format:
  18. * struct rx_desc
  19. * {
  20. * // to uengine
  21. * u32 buf_phys_addr;
  22. * u32 buf_length;
  23. *
  24. * // from uengine
  25. * u32 channel;
  26. * u32 pkt_length;
  27. * };
  28. * - Packet data resides in DRAM.
  29. * - Packet buffer addresses are 8-byte aligned.
  30. * - Scratch ring 0 is rx_pending.
  31. * - Scratch ring 1 is rx_done, and has status condition 'full'.
  32. * - The host triggers rx_done flush and rx_pending refill on seeing INTA.
  33. * - This code is run on all eight threads of the microengine it runs on.
  34. *
  35. * Local memory is used for per-channel RX state.
  36. */
  37. #define RX_THREAD_FREELIST_0 0x0030
  38. #define RBUF_ELEMENT_DONE 0x0044
  39. #define CHANNEL_FLAGS *l$index0[0]
  40. #define CHANNEL_FLAG_RECEIVING 1
  41. #define PACKET_LENGTH *l$index0[1]
  42. #define PACKET_CHECKSUM *l$index0[2]
  43. #define BUFFER_HANDLE *l$index0[3]
  44. #define BUFFER_START *l$index0[4]
  45. #define BUFFER_LENGTH *l$index0[5]
  46. #define CHANNEL_STATE_SIZE 24 // in bytes
  47. #define CHANNEL_STATE_SHIFT 5 // ceil(log2(state size))
  48. .sig volatile sig1
  49. .sig volatile sig2
  50. .sig volatile sig3
  51. .sig mpacket_arrived
  52. .reg add_to_rx_freelist
  53. .reg read $rsw0, $rsw1
  54. .xfer_order $rsw0 $rsw1
  55. .reg zero
  56. /*
  57. * Initialise add_to_rx_freelist.
  58. */
  59. .begin
  60. .reg temp
  61. .reg temp2
  62. immed[add_to_rx_freelist, RX_THREAD_FREELIST_0]
  63. immed_w1[add_to_rx_freelist, (&$rsw0 | (&mpacket_arrived << 12))]
  64. local_csr_rd[ACTIVE_CTX_STS]
  65. immed[temp, 0]
  66. alu[temp2, temp, and, 0x1f]
  67. alu_shf[add_to_rx_freelist, add_to_rx_freelist, or, temp2, <<20]
  68. alu[temp2, temp, and, 0x80]
  69. alu_shf[add_to_rx_freelist, add_to_rx_freelist, or, temp2, <<18]
  70. .end
  71. immed[zero, 0]
  72. /*
  73. * Skip context 0 initialisation?
  74. */
  75. .begin
  76. br!=ctx[0, mpacket_receive_loop#]
  77. .end
  78. /*
  79. * Initialise local memory.
  80. */
  81. .begin
  82. .reg addr
  83. .reg temp
  84. immed[temp, 0]
  85. init_local_mem_loop#:
  86. alu_shf[addr, --, b, temp, <<CHANNEL_STATE_SHIFT]
  87. local_csr_wr[ACTIVE_LM_ADDR_0, addr]
  88. nop
  89. nop
  90. nop
  91. immed[CHANNEL_FLAGS, 0]
  92. alu[temp, temp, +, 1]
  93. alu[--, temp, and, 0x20]
  94. beq[init_local_mem_loop#]
  95. .end
  96. /*
  97. * Initialise signal pipeline.
  98. */
  99. .begin
  100. local_csr_wr[SAME_ME_SIGNAL, (&sig1 << 3)]
  101. .set_sig sig1
  102. local_csr_wr[SAME_ME_SIGNAL, (&sig2 << 3)]
  103. .set_sig sig2
  104. local_csr_wr[SAME_ME_SIGNAL, (&sig3 << 3)]
  105. .set_sig sig3
  106. .end
  107. mpacket_receive_loop#:
  108. /*
  109. * Synchronise and wait for mpacket.
  110. */
  111. .begin
  112. ctx_arb[sig1]
  113. local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig1 << 3))]
  114. msf[fast_wr, --, add_to_rx_freelist, 0]
  115. .set_sig mpacket_arrived
  116. ctx_arb[mpacket_arrived]
  117. .set $rsw0 $rsw1
  118. .end
  119. /*
  120. * We halt if we see {inbparerr,parerr,null,soperror}.
  121. */
  122. .begin
  123. alu_shf[--, 0x1b, and, $rsw0, >>8]
  124. bne[abort_rswerr#]
  125. .end
  126. /*
  127. * Point local memory pointer to this channel's state area.
  128. */
  129. .begin
  130. .reg chanaddr
  131. alu[chanaddr, $rsw0, and, 0x1f]
  132. alu_shf[chanaddr, --, b, chanaddr, <<CHANNEL_STATE_SHIFT]
  133. local_csr_wr[ACTIVE_LM_ADDR_0, chanaddr]
  134. nop
  135. nop
  136. nop
  137. .end
  138. /*
  139. * Check whether we received a SOP mpacket while we were already
  140. * working on a packet, or a non-SOP mpacket while there was no
  141. * packet pending. (SOP == RECEIVING -> abort) If everything's
  142. * okay, update the RECEIVING flag to reflect our new state.
  143. */
  144. .begin
  145. .reg temp
  146. .reg eop
  147. #if CHANNEL_FLAG_RECEIVING != 1
  148. #error CHANNEL_FLAG_RECEIVING is not 1
  149. #endif
  150. alu_shf[temp, 1, and, $rsw0, >>15]
  151. alu[temp, temp, xor, CHANNEL_FLAGS]
  152. alu[--, temp, and, CHANNEL_FLAG_RECEIVING]
  153. beq[abort_proterr#]
  154. alu_shf[eop, 1, and, $rsw0, >>14]
  155. alu[CHANNEL_FLAGS, temp, xor, eop]
  156. .end
  157. /*
  158. * Copy the mpacket into the right spot, and in case of EOP,
  159. * write back the descriptor and pass the packet on.
  160. */
  161. .begin
  162. .reg buffer_offset
  163. .reg _packet_length
  164. .reg _packet_checksum
  165. .reg _buffer_handle
  166. .reg _buffer_start
  167. .reg _buffer_length
  168. /*
  169. * Determine buffer_offset, _packet_length and
  170. * _packet_checksum.
  171. */
  172. .begin
  173. .reg temp
  174. alu[--, 1, and, $rsw0, >>15]
  175. beq[not_sop#]
  176. immed[PACKET_LENGTH, 0]
  177. immed[PACKET_CHECKSUM, 0]
  178. not_sop#:
  179. alu[buffer_offset, --, b, PACKET_LENGTH]
  180. alu_shf[temp, 0xff, and, $rsw0, >>16]
  181. alu[_packet_length, buffer_offset, +, temp]
  182. alu[PACKET_LENGTH, --, b, _packet_length]
  183. immed[temp, 0xffff]
  184. alu[temp, $rsw1, and, temp]
  185. alu[_packet_checksum, PACKET_CHECKSUM, +, temp]
  186. alu[PACKET_CHECKSUM, --, b, _packet_checksum]
  187. .end
  188. /*
  189. * Allocate buffer in case of SOP.
  190. */
  191. .begin
  192. .reg temp
  193. alu[temp, 1, and, $rsw0, >>15]
  194. beq[skip_buffer_alloc#]
  195. .begin
  196. .sig zzz
  197. .reg read $stemp $stemp2
  198. .xfer_order $stemp $stemp2
  199. rx_nobufs#:
  200. scratch[get, $stemp, zero, 0, 1], ctx_swap[zzz]
  201. alu[_buffer_handle, --, b, $stemp]
  202. beq[rx_nobufs#]
  203. sram[read, $stemp, _buffer_handle, 0, 2],
  204. ctx_swap[zzz]
  205. alu[_buffer_start, --, b, $stemp]
  206. alu[_buffer_length, --, b, $stemp2]
  207. .end
  208. skip_buffer_alloc#:
  209. .end
  210. /*
  211. * Resynchronise.
  212. */
  213. .begin
  214. ctx_arb[sig2]
  215. local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig2 << 3))]
  216. .end
  217. /*
  218. * Synchronise buffer state.
  219. */
  220. .begin
  221. .reg temp
  222. alu[temp, 1, and, $rsw0, >>15]
  223. beq[copy_from_local_mem#]
  224. alu[BUFFER_HANDLE, --, b, _buffer_handle]
  225. alu[BUFFER_START, --, b, _buffer_start]
  226. alu[BUFFER_LENGTH, --, b, _buffer_length]
  227. br[sync_state_done#]
  228. copy_from_local_mem#:
  229. alu[_buffer_handle, --, b, BUFFER_HANDLE]
  230. alu[_buffer_start, --, b, BUFFER_START]
  231. alu[_buffer_length, --, b, BUFFER_LENGTH]
  232. sync_state_done#:
  233. .end
  234. #if 0
  235. /*
  236. * Debug buffer state management.
  237. */
  238. .begin
  239. .reg temp
  240. alu[temp, 1, and, $rsw0, >>14]
  241. beq[no_poison#]
  242. immed[BUFFER_HANDLE, 0xdead]
  243. immed[BUFFER_START, 0xdead]
  244. immed[BUFFER_LENGTH, 0xdead]
  245. no_poison#:
  246. immed[temp, 0xdead]
  247. alu[--, _buffer_handle, -, temp]
  248. beq[state_corrupted#]
  249. alu[--, _buffer_start, -, temp]
  250. beq[state_corrupted#]
  251. alu[--, _buffer_length, -, temp]
  252. beq[state_corrupted#]
  253. .end
  254. #endif
  255. /*
  256. * Check buffer length.
  257. */
  258. .begin
  259. alu[--, _buffer_length, -, _packet_length]
  260. blo[buffer_overflow#]
  261. .end
  262. /*
  263. * Copy the mpacket and give back the RBUF element.
  264. */
  265. .begin
  266. .reg element
  267. .reg xfer_size
  268. .reg temp
  269. .sig copy_sig
  270. alu_shf[element, 0x7f, and, $rsw0, >>24]
  271. alu_shf[xfer_size, 0xff, and, $rsw0, >>16]
  272. alu[xfer_size, xfer_size, -, 1]
  273. alu_shf[xfer_size, 0x10, or, xfer_size, >>3]
  274. alu_shf[temp, 0x10, or, xfer_size, <<21]
  275. alu_shf[temp, temp, or, element, <<11]
  276. alu_shf[--, temp, or, 1, <<18]
  277. dram[rbuf_rd, --, _buffer_start, buffer_offset, max_8],
  278. indirect_ref, sig_done[copy_sig]
  279. ctx_arb[copy_sig]
  280. alu[temp, RBUF_ELEMENT_DONE, or, element, <<16]
  281. msf[fast_wr, --, temp, 0]
  282. .end
  283. /*
  284. * If EOP, write back the packet descriptor.
  285. */
  286. .begin
  287. .reg write $stemp $stemp2
  288. .xfer_order $stemp $stemp2
  289. .sig zzz
  290. alu_shf[--, 1, and, $rsw0, >>14]
  291. beq[no_writeback#]
  292. alu[$stemp, $rsw0, and, 0x1f]
  293. alu[$stemp2, --, b, _packet_length]
  294. sram[write, $stemp, _buffer_handle, 8, 2], ctx_swap[zzz]
  295. no_writeback#:
  296. .end
  297. /*
  298. * Resynchronise.
  299. */
  300. .begin
  301. ctx_arb[sig3]
  302. local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig3 << 3))]
  303. .end
  304. /*
  305. * If EOP, put the buffer back onto the scratch ring.
  306. */
  307. .begin
  308. .reg write $stemp
  309. .sig zzz
  310. br_inp_state[SCR_Ring1_Status, rx_done_ring_overflow#]
  311. alu_shf[--, 1, and, $rsw0, >>14]
  312. beq[mpacket_receive_loop#]
  313. alu[--, 1, and, $rsw0, >>10]
  314. bne[rxerr#]
  315. alu[$stemp, --, b, _buffer_handle]
  316. scratch[put, $stemp, zero, 4, 1], ctx_swap[zzz]
  317. cap[fast_wr, 0, XSCALE_INT_A]
  318. br[mpacket_receive_loop#]
  319. rxerr#:
  320. alu[$stemp, --, b, _buffer_handle]
  321. scratch[put, $stemp, zero, 0, 1], ctx_swap[zzz]
  322. br[mpacket_receive_loop#]
  323. .end
  324. .end
  325. abort_rswerr#:
  326. halt
  327. abort_proterr#:
  328. halt
  329. state_corrupted#:
  330. halt
  331. buffer_overflow#:
  332. halt
  333. rx_done_ring_overflow#:
  334. halt