2
0

xilinx_ethlite.c 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /*
  2. * QEMU model of the Xilinx Ethernet Lite MAC.
  3. *
  4. * Copyright (c) 2009 Edgar E. Iglesias.
  5. *
  6. * Permission is hereby granted, free of charge, to any person obtaining a copy
  7. * of this software and associated documentation files (the "Software"), to deal
  8. * in the Software without restriction, including without limitation the rights
  9. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. * copies of the Software, and to permit persons to whom the Software is
  11. * furnished to do so, subject to the following conditions:
  12. *
  13. * The above copyright notice and this permission notice shall be included in
  14. * all copies or substantial portions of the Software.
  15. *
  16. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. * THE SOFTWARE.
  23. */
  24. #include "sysbus.h"
  25. #include "hw.h"
  26. #include "net.h"
  27. #define D(x)
  28. #define R_TX_BUF0 0
  29. #define R_TX_LEN0 (0x07f4 / 4)
  30. #define R_TX_GIE0 (0x07f8 / 4)
  31. #define R_TX_CTRL0 (0x07fc / 4)
  32. #define R_TX_BUF1 (0x0800 / 4)
  33. #define R_TX_LEN1 (0x0ff4 / 4)
  34. #define R_TX_CTRL1 (0x0ffc / 4)
  35. #define R_RX_BUF0 (0x1000 / 4)
  36. #define R_RX_CTRL0 (0x17fc / 4)
  37. #define R_RX_BUF1 (0x1800 / 4)
  38. #define R_RX_CTRL1 (0x1ffc / 4)
  39. #define R_MAX (0x2000 / 4)
  40. #define GIE_GIE 0x80000000
  41. #define CTRL_I 0x8
  42. #define CTRL_P 0x2
  43. #define CTRL_S 0x1
  44. struct xlx_ethlite
  45. {
  46. SysBusDevice busdev;
  47. qemu_irq irq;
  48. NICState *nic;
  49. NICConf conf;
  50. uint32_t c_tx_pingpong;
  51. uint32_t c_rx_pingpong;
  52. unsigned int txbuf;
  53. unsigned int rxbuf;
  54. uint32_t regs[R_MAX];
  55. };
  56. static inline void eth_pulse_irq(struct xlx_ethlite *s)
  57. {
  58. /* Only the first gie reg is active. */
  59. if (s->regs[R_TX_GIE0] & GIE_GIE) {
  60. qemu_irq_pulse(s->irq);
  61. }
  62. }
  63. static uint32_t eth_readl (void *opaque, target_phys_addr_t addr)
  64. {
  65. struct xlx_ethlite *s = opaque;
  66. uint32_t r = 0;
  67. addr >>= 2;
  68. switch (addr)
  69. {
  70. case R_TX_GIE0:
  71. case R_TX_LEN0:
  72. case R_TX_LEN1:
  73. case R_TX_CTRL1:
  74. case R_TX_CTRL0:
  75. case R_RX_CTRL1:
  76. case R_RX_CTRL0:
  77. r = s->regs[addr];
  78. D(qemu_log("%s %x=%x\n", __func__, addr * 4, r));
  79. break;
  80. default:
  81. r = tswap32(s->regs[addr]);
  82. break;
  83. }
  84. return r;
  85. }
  86. static void
  87. eth_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
  88. {
  89. struct xlx_ethlite *s = opaque;
  90. unsigned int base = 0;
  91. addr >>= 2;
  92. switch (addr)
  93. {
  94. case R_TX_CTRL0:
  95. case R_TX_CTRL1:
  96. if (addr == R_TX_CTRL1)
  97. base = 0x800 / 4;
  98. D(qemu_log("%s addr=%x val=%x\n", __func__, addr * 4, value));
  99. if ((value & (CTRL_P | CTRL_S)) == CTRL_S) {
  100. qemu_send_packet(&s->nic->nc,
  101. (void *) &s->regs[base],
  102. s->regs[base + R_TX_LEN0]);
  103. D(qemu_log("eth_tx %d\n", s->regs[base + R_TX_LEN0]));
  104. if (s->regs[base + R_TX_CTRL0] & CTRL_I)
  105. eth_pulse_irq(s);
  106. } else if ((value & (CTRL_P | CTRL_S)) == (CTRL_P | CTRL_S)) {
  107. memcpy(&s->conf.macaddr.a[0], &s->regs[base], 6);
  108. if (s->regs[base + R_TX_CTRL0] & CTRL_I)
  109. eth_pulse_irq(s);
  110. }
  111. /* We are fast and get ready pretty much immediately so
  112. we actually never flip the S nor P bits to one. */
  113. s->regs[addr] = value & ~(CTRL_P | CTRL_S);
  114. break;
  115. /* Keep these native. */
  116. case R_TX_LEN0:
  117. case R_TX_LEN1:
  118. case R_TX_GIE0:
  119. case R_RX_CTRL0:
  120. case R_RX_CTRL1:
  121. D(qemu_log("%s addr=%x val=%x\n", __func__, addr * 4, value));
  122. s->regs[addr] = value;
  123. break;
  124. default:
  125. s->regs[addr] = tswap32(value);
  126. break;
  127. }
  128. }
  129. static CPUReadMemoryFunc * const eth_read[] = {
  130. NULL, NULL, &eth_readl,
  131. };
  132. static CPUWriteMemoryFunc * const eth_write[] = {
  133. NULL, NULL, &eth_writel,
  134. };
  135. static int eth_can_rx(VLANClientState *nc)
  136. {
  137. struct xlx_ethlite *s = DO_UPCAST(NICState, nc, nc)->opaque;
  138. int r;
  139. r = !(s->regs[R_RX_CTRL0] & CTRL_S);
  140. return r;
  141. }
  142. static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
  143. {
  144. struct xlx_ethlite *s = DO_UPCAST(NICState, nc, nc)->opaque;
  145. unsigned int rxbase = s->rxbuf * (0x800 / 4);
  146. /* DA filter. */
  147. if (!(buf[0] & 0x80) && memcmp(&s->conf.macaddr.a[0], buf, 6))
  148. return size;
  149. if (s->regs[rxbase + R_RX_CTRL0] & CTRL_S) {
  150. D(qemu_log("ethlite lost packet %x\n", s->regs[R_RX_CTRL0]));
  151. return -1;
  152. }
  153. D(qemu_log("%s %d rxbase=%x\n", __func__, size, rxbase));
  154. memcpy(&s->regs[rxbase + R_RX_BUF0], buf, size);
  155. s->regs[rxbase + R_RX_CTRL0] |= CTRL_S;
  156. if (s->regs[rxbase + R_RX_CTRL0] & CTRL_I)
  157. eth_pulse_irq(s);
  158. /* If c_rx_pingpong was set flip buffers. */
  159. s->rxbuf ^= s->c_rx_pingpong;
  160. return size;
  161. }
  162. static void eth_cleanup(VLANClientState *nc)
  163. {
  164. struct xlx_ethlite *s = DO_UPCAST(NICState, nc, nc)->opaque;
  165. s->nic = NULL;
  166. }
  167. static NetClientInfo net_xilinx_ethlite_info = {
  168. .type = NET_CLIENT_TYPE_NIC,
  169. .size = sizeof(NICState),
  170. .can_receive = eth_can_rx,
  171. .receive = eth_rx,
  172. .cleanup = eth_cleanup,
  173. };
  174. static int xilinx_ethlite_init(SysBusDevice *dev)
  175. {
  176. struct xlx_ethlite *s = FROM_SYSBUS(typeof (*s), dev);
  177. int regs;
  178. sysbus_init_irq(dev, &s->irq);
  179. s->rxbuf = 0;
  180. regs = cpu_register_io_memory(eth_read, eth_write, s, DEVICE_NATIVE_ENDIAN);
  181. sysbus_init_mmio(dev, R_MAX * 4, regs);
  182. qemu_macaddr_default_if_unset(&s->conf.macaddr);
  183. s->nic = qemu_new_nic(&net_xilinx_ethlite_info, &s->conf,
  184. dev->qdev.info->name, dev->qdev.id, s);
  185. qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
  186. return 0;
  187. }
  188. static SysBusDeviceInfo xilinx_ethlite_info = {
  189. .init = xilinx_ethlite_init,
  190. .qdev.name = "xilinx,ethlite",
  191. .qdev.size = sizeof(struct xlx_ethlite),
  192. .qdev.props = (Property[]) {
  193. DEFINE_PROP_UINT32("txpingpong", struct xlx_ethlite, c_tx_pingpong, 1),
  194. DEFINE_PROP_UINT32("rxpingpong", struct xlx_ethlite, c_rx_pingpong, 1),
  195. DEFINE_NIC_PROPERTIES(struct xlx_ethlite, conf),
  196. DEFINE_PROP_END_OF_LIST(),
  197. }
  198. };
  199. static void xilinx_ethlite_register(void)
  200. {
  201. sysbus_register_withprop(&xilinx_ethlite_info);
  202. }
  203. device_init(xilinx_ethlite_register)