ixp2400_tx.uc 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. /*
  2. * TX 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 TBUF partition 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 TBUF uses 64-byte mpackets.
  17. * - TX descriptors reside in SRAM, and have the following format:
  18. * struct tx_desc
  19. * {
  20. * // to uengine
  21. * u32 buf_phys_addr;
  22. * u32 pkt_length;
  23. * u32 channel;
  24. * };
  25. * - Packet data resides in DRAM.
  26. * - Packet buffer addresses are 8-byte aligned.
  27. * - Scratch ring 2 is tx_pending.
  28. * - Scratch ring 3 is tx_done, and has status condition 'full'.
  29. * - This code is run on all eight threads of the microengine it runs on.
  30. */
  31. #define TX_SEQUENCE_0 0x0060
  32. #define TBUF_CTRL 0x1800
  33. #define PARTITION_SIZE 128
  34. #define PARTITION_THRESH 96
  35. .sig volatile sig1
  36. .sig volatile sig2
  37. .sig volatile sig3
  38. .reg @old_tx_seq_0
  39. .reg @mpkts_in_flight
  40. .reg @next_tbuf_mpacket
  41. .reg @buffer_handle
  42. .reg @buffer_start
  43. .reg @packet_length
  44. .reg @channel
  45. .reg @packet_offset
  46. .reg zero
  47. immed[zero, 0]
  48. /*
  49. * Skip context 0 initialisation?
  50. */
  51. .begin
  52. br!=ctx[0, mpacket_tx_loop#]
  53. .end
  54. /*
  55. * Wait until all pending TBUF elements have been transmitted.
  56. */
  57. .begin
  58. .reg read $tx
  59. .sig zzz
  60. loop_empty#:
  61. msf[read, $tx, zero, TX_SEQUENCE_0, 1], ctx_swap[zzz]
  62. alu_shf[--, --, b, $tx, >>31]
  63. beq[loop_empty#]
  64. alu[@old_tx_seq_0, --, b, $tx]
  65. .end
  66. immed[@mpkts_in_flight, 0]
  67. alu[@next_tbuf_mpacket, @old_tx_seq_0, and, (PARTITION_SIZE - 1)]
  68. immed[@buffer_handle, 0]
  69. /*
  70. * Initialise signal pipeline.
  71. */
  72. .begin
  73. local_csr_wr[SAME_ME_SIGNAL, (&sig1 << 3)]
  74. .set_sig sig1
  75. local_csr_wr[SAME_ME_SIGNAL, (&sig2 << 3)]
  76. .set_sig sig2
  77. local_csr_wr[SAME_ME_SIGNAL, (&sig3 << 3)]
  78. .set_sig sig3
  79. .end
  80. mpacket_tx_loop#:
  81. .begin
  82. .reg tbuf_element_index
  83. .reg buffer_handle
  84. .reg sop_eop
  85. .reg packet_data
  86. .reg channel
  87. .reg mpacket_size
  88. /*
  89. * If there is no packet currently being transmitted,
  90. * dequeue the next TX descriptor, and fetch the buffer
  91. * address, packet length and destination channel number.
  92. */
  93. .begin
  94. .reg read $stemp $stemp2 $stemp3
  95. .xfer_order $stemp $stemp2 $stemp3
  96. .sig zzz
  97. ctx_arb[sig1]
  98. alu[--, --, b, @buffer_handle]
  99. bne[already_got_packet#]
  100. tx_nobufs#:
  101. scratch[get, $stemp, zero, 8, 1], ctx_swap[zzz]
  102. alu[@buffer_handle, --, b, $stemp]
  103. beq[tx_nobufs#]
  104. sram[read, $stemp, $stemp, 0, 3], ctx_swap[zzz]
  105. alu[@buffer_start, --, b, $stemp]
  106. alu[@packet_length, --, b, $stemp2]
  107. beq[zero_byte_packet#]
  108. alu[@channel, --, b, $stemp3]
  109. immed[@packet_offset, 0]
  110. already_got_packet#:
  111. local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig1 << 3))]
  112. .end
  113. /*
  114. * Determine tbuf element index, SOP/EOP flags, mpacket
  115. * offset and mpacket size and cache buffer_handle and
  116. * channel number.
  117. */
  118. .begin
  119. alu[tbuf_element_index, --, b, @next_tbuf_mpacket]
  120. alu[@next_tbuf_mpacket, @next_tbuf_mpacket, +, 1]
  121. alu[@next_tbuf_mpacket, @next_tbuf_mpacket, and,
  122. (PARTITION_SIZE - 1)]
  123. alu[buffer_handle, --, b, @buffer_handle]
  124. immed[@buffer_handle, 0]
  125. immed[sop_eop, 1]
  126. alu[packet_data, --, b, @packet_offset]
  127. bne[no_sop#]
  128. alu[sop_eop, sop_eop, or, 2]
  129. no_sop#:
  130. alu[packet_data, packet_data, +, @buffer_start]
  131. alu[channel, --, b, @channel]
  132. alu[mpacket_size, @packet_length, -, @packet_offset]
  133. alu[--, 64, -, mpacket_size]
  134. bhs[eop#]
  135. alu[@buffer_handle, --, b, buffer_handle]
  136. immed[mpacket_size, 64]
  137. alu[sop_eop, sop_eop, and, 2]
  138. eop#:
  139. alu[@packet_offset, @packet_offset, +, mpacket_size]
  140. .end
  141. /*
  142. * Wait until there's enough space in the TBUF.
  143. */
  144. .begin
  145. .reg read $tx
  146. .reg temp
  147. .sig zzz
  148. ctx_arb[sig2]
  149. br[test_space#]
  150. loop_space#:
  151. msf[read, $tx, zero, TX_SEQUENCE_0, 1], ctx_swap[zzz]
  152. alu[temp, $tx, -, @old_tx_seq_0]
  153. alu[temp, temp, and, 0xff]
  154. alu[@mpkts_in_flight, @mpkts_in_flight, -, temp]
  155. alu[@old_tx_seq_0, --, b, $tx]
  156. test_space#:
  157. alu[--, PARTITION_THRESH, -, @mpkts_in_flight]
  158. blo[loop_space#]
  159. alu[@mpkts_in_flight, @mpkts_in_flight, +, 1]
  160. local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig2 << 3))]
  161. .end
  162. /*
  163. * Copy the packet data to the TBUF.
  164. */
  165. .begin
  166. .reg temp
  167. .sig copy_sig
  168. alu[temp, mpacket_size, -, 1]
  169. alu_shf[temp, 0x10, or, temp, >>3]
  170. alu_shf[temp, 0x10, or, temp, <<21]
  171. alu_shf[temp, temp, or, tbuf_element_index, <<11]
  172. alu_shf[--, temp, or, 1, <<18]
  173. dram[tbuf_wr, --, packet_data, 0, max_8],
  174. indirect_ref, sig_done[copy_sig]
  175. ctx_arb[copy_sig]
  176. .end
  177. /*
  178. * Mark TBUF element as ready-to-be-transmitted.
  179. */
  180. .begin
  181. .reg write $tsw $tsw2
  182. .xfer_order $tsw $tsw2
  183. .reg temp
  184. .sig zzz
  185. alu_shf[temp, channel, or, mpacket_size, <<24]
  186. alu_shf[$tsw, temp, or, sop_eop, <<8]
  187. immed[$tsw2, 0]
  188. immed[temp, TBUF_CTRL]
  189. alu_shf[temp, temp, or, tbuf_element_index, <<3]
  190. msf[write, $tsw, temp, 0, 2], ctx_swap[zzz]
  191. .end
  192. /*
  193. * Resynchronise.
  194. */
  195. .begin
  196. ctx_arb[sig3]
  197. local_csr_wr[SAME_ME_SIGNAL, (0x80 | (&sig3 << 3))]
  198. .end
  199. /*
  200. * If this was an EOP mpacket, recycle the TX buffer
  201. * and signal the host.
  202. */
  203. .begin
  204. .reg write $stemp
  205. .sig zzz
  206. alu[--, sop_eop, and, 1]
  207. beq[mpacket_tx_loop#]
  208. tx_done_ring_full#:
  209. br_inp_state[SCR_Ring3_Status, tx_done_ring_full#]
  210. alu[$stemp, --, b, buffer_handle]
  211. scratch[put, $stemp, zero, 12, 1], ctx_swap[zzz]
  212. cap[fast_wr, 0, XSCALE_INT_A]
  213. br[mpacket_tx_loop#]
  214. .end
  215. .end
  216. zero_byte_packet#:
  217. halt