mipsnet.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. #include "hw/hw.h"
  2. #include "net/net.h"
  3. #include "trace.h"
  4. #include "hw/sysbus.h"
  5. /* MIPSnet register offsets */
  6. #define MIPSNET_DEV_ID 0x00
  7. #define MIPSNET_BUSY 0x08
  8. #define MIPSNET_RX_DATA_COUNT 0x0c
  9. #define MIPSNET_TX_DATA_COUNT 0x10
  10. #define MIPSNET_INT_CTL 0x14
  11. # define MIPSNET_INTCTL_TXDONE 0x00000001
  12. # define MIPSNET_INTCTL_RXDONE 0x00000002
  13. # define MIPSNET_INTCTL_TESTBIT 0x80000000
  14. #define MIPSNET_INTERRUPT_INFO 0x18
  15. #define MIPSNET_RX_DATA_BUFFER 0x1c
  16. #define MIPSNET_TX_DATA_BUFFER 0x20
  17. #define MAX_ETH_FRAME_SIZE 1514
  18. #define TYPE_MIPS_NET "mipsnet"
  19. #define MIPS_NET(obj) OBJECT_CHECK(MIPSnetState, (obj), TYPE_MIPS_NET)
  20. typedef struct MIPSnetState {
  21. SysBusDevice parent_obj;
  22. uint32_t busy;
  23. uint32_t rx_count;
  24. uint32_t rx_read;
  25. uint32_t tx_count;
  26. uint32_t tx_written;
  27. uint32_t intctl;
  28. uint8_t rx_buffer[MAX_ETH_FRAME_SIZE];
  29. uint8_t tx_buffer[MAX_ETH_FRAME_SIZE];
  30. MemoryRegion io;
  31. qemu_irq irq;
  32. NICState *nic;
  33. NICConf conf;
  34. } MIPSnetState;
  35. static void mipsnet_reset(MIPSnetState *s)
  36. {
  37. s->busy = 1;
  38. s->rx_count = 0;
  39. s->rx_read = 0;
  40. s->tx_count = 0;
  41. s->tx_written = 0;
  42. s->intctl = 0;
  43. memset(s->rx_buffer, 0, MAX_ETH_FRAME_SIZE);
  44. memset(s->tx_buffer, 0, MAX_ETH_FRAME_SIZE);
  45. }
  46. static void mipsnet_update_irq(MIPSnetState *s)
  47. {
  48. int isr = !!s->intctl;
  49. trace_mipsnet_irq(isr, s->intctl);
  50. qemu_set_irq(s->irq, isr);
  51. }
  52. static int mipsnet_buffer_full(MIPSnetState *s)
  53. {
  54. if (s->rx_count >= MAX_ETH_FRAME_SIZE)
  55. return 1;
  56. return 0;
  57. }
  58. static int mipsnet_can_receive(NetClientState *nc)
  59. {
  60. MIPSnetState *s = qemu_get_nic_opaque(nc);
  61. if (s->busy)
  62. return 0;
  63. return !mipsnet_buffer_full(s);
  64. }
  65. static ssize_t mipsnet_receive(NetClientState *nc, const uint8_t *buf, size_t size)
  66. {
  67. MIPSnetState *s = qemu_get_nic_opaque(nc);
  68. trace_mipsnet_receive(size);
  69. if (!mipsnet_can_receive(nc))
  70. return -1;
  71. s->busy = 1;
  72. /* Just accept everything. */
  73. /* Write packet data. */
  74. memcpy(s->rx_buffer, buf, size);
  75. s->rx_count = size;
  76. s->rx_read = 0;
  77. /* Now we can signal we have received something. */
  78. s->intctl |= MIPSNET_INTCTL_RXDONE;
  79. mipsnet_update_irq(s);
  80. return size;
  81. }
  82. static uint64_t mipsnet_ioport_read(void *opaque, hwaddr addr,
  83. unsigned int size)
  84. {
  85. MIPSnetState *s = opaque;
  86. int ret = 0;
  87. addr &= 0x3f;
  88. switch (addr) {
  89. case MIPSNET_DEV_ID:
  90. ret = be32_to_cpu(0x4d495053); /* MIPS */
  91. break;
  92. case MIPSNET_DEV_ID + 4:
  93. ret = be32_to_cpu(0x4e455430); /* NET0 */
  94. break;
  95. case MIPSNET_BUSY:
  96. ret = s->busy;
  97. break;
  98. case MIPSNET_RX_DATA_COUNT:
  99. ret = s->rx_count;
  100. break;
  101. case MIPSNET_TX_DATA_COUNT:
  102. ret = s->tx_count;
  103. break;
  104. case MIPSNET_INT_CTL:
  105. ret = s->intctl;
  106. s->intctl &= ~MIPSNET_INTCTL_TESTBIT;
  107. break;
  108. case MIPSNET_INTERRUPT_INFO:
  109. /* XXX: This seems to be a per-VPE interrupt number. */
  110. ret = 0;
  111. break;
  112. case MIPSNET_RX_DATA_BUFFER:
  113. if (s->rx_count) {
  114. s->rx_count--;
  115. ret = s->rx_buffer[s->rx_read++];
  116. }
  117. break;
  118. /* Reads as zero. */
  119. case MIPSNET_TX_DATA_BUFFER:
  120. default:
  121. break;
  122. }
  123. trace_mipsnet_read(addr, ret);
  124. return ret;
  125. }
  126. static void mipsnet_ioport_write(void *opaque, hwaddr addr,
  127. uint64_t val, unsigned int size)
  128. {
  129. MIPSnetState *s = opaque;
  130. addr &= 0x3f;
  131. trace_mipsnet_write(addr, val);
  132. switch (addr) {
  133. case MIPSNET_TX_DATA_COUNT:
  134. s->tx_count = (val <= MAX_ETH_FRAME_SIZE) ? val : 0;
  135. s->tx_written = 0;
  136. break;
  137. case MIPSNET_INT_CTL:
  138. if (val & MIPSNET_INTCTL_TXDONE) {
  139. s->intctl &= ~MIPSNET_INTCTL_TXDONE;
  140. } else if (val & MIPSNET_INTCTL_RXDONE) {
  141. s->intctl &= ~MIPSNET_INTCTL_RXDONE;
  142. } else if (val & MIPSNET_INTCTL_TESTBIT) {
  143. mipsnet_reset(s);
  144. s->intctl |= MIPSNET_INTCTL_TESTBIT;
  145. } else if (!val) {
  146. /* ACK testbit interrupt, flag was cleared on read. */
  147. }
  148. s->busy = !!s->intctl;
  149. mipsnet_update_irq(s);
  150. break;
  151. case MIPSNET_TX_DATA_BUFFER:
  152. s->tx_buffer[s->tx_written++] = val;
  153. if (s->tx_written == s->tx_count) {
  154. /* Send buffer. */
  155. trace_mipsnet_send(s->tx_count);
  156. qemu_send_packet(qemu_get_queue(s->nic), s->tx_buffer, s->tx_count);
  157. s->tx_count = s->tx_written = 0;
  158. s->intctl |= MIPSNET_INTCTL_TXDONE;
  159. s->busy = 1;
  160. mipsnet_update_irq(s);
  161. }
  162. break;
  163. /* Read-only registers */
  164. case MIPSNET_DEV_ID:
  165. case MIPSNET_BUSY:
  166. case MIPSNET_RX_DATA_COUNT:
  167. case MIPSNET_INTERRUPT_INFO:
  168. case MIPSNET_RX_DATA_BUFFER:
  169. default:
  170. break;
  171. }
  172. }
  173. static const VMStateDescription vmstate_mipsnet = {
  174. .name = "mipsnet",
  175. .version_id = 0,
  176. .minimum_version_id = 0,
  177. .minimum_version_id_old = 0,
  178. .fields = (VMStateField[]) {
  179. VMSTATE_UINT32(busy, MIPSnetState),
  180. VMSTATE_UINT32(rx_count, MIPSnetState),
  181. VMSTATE_UINT32(rx_read, MIPSnetState),
  182. VMSTATE_UINT32(tx_count, MIPSnetState),
  183. VMSTATE_UINT32(tx_written, MIPSnetState),
  184. VMSTATE_UINT32(intctl, MIPSnetState),
  185. VMSTATE_BUFFER(rx_buffer, MIPSnetState),
  186. VMSTATE_BUFFER(tx_buffer, MIPSnetState),
  187. VMSTATE_END_OF_LIST()
  188. }
  189. };
  190. static void mipsnet_cleanup(NetClientState *nc)
  191. {
  192. MIPSnetState *s = qemu_get_nic_opaque(nc);
  193. s->nic = NULL;
  194. }
  195. static NetClientInfo net_mipsnet_info = {
  196. .type = NET_CLIENT_OPTIONS_KIND_NIC,
  197. .size = sizeof(NICState),
  198. .can_receive = mipsnet_can_receive,
  199. .receive = mipsnet_receive,
  200. .cleanup = mipsnet_cleanup,
  201. };
  202. static const MemoryRegionOps mipsnet_ioport_ops = {
  203. .read = mipsnet_ioport_read,
  204. .write = mipsnet_ioport_write,
  205. .impl.min_access_size = 1,
  206. .impl.max_access_size = 4,
  207. };
  208. static int mipsnet_sysbus_init(SysBusDevice *sbd)
  209. {
  210. DeviceState *dev = DEVICE(sbd);
  211. MIPSnetState *s = MIPS_NET(dev);
  212. memory_region_init_io(&s->io, OBJECT(dev), &mipsnet_ioport_ops, s,
  213. "mipsnet-io", 36);
  214. sysbus_init_mmio(sbd, &s->io);
  215. sysbus_init_irq(sbd, &s->irq);
  216. s->nic = qemu_new_nic(&net_mipsnet_info, &s->conf,
  217. object_get_typename(OBJECT(dev)), dev->id, s);
  218. qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
  219. return 0;
  220. }
  221. static void mipsnet_sysbus_reset(DeviceState *dev)
  222. {
  223. MIPSnetState *s = MIPS_NET(dev);
  224. mipsnet_reset(s);
  225. }
  226. static Property mipsnet_properties[] = {
  227. DEFINE_NIC_PROPERTIES(MIPSnetState, conf),
  228. DEFINE_PROP_END_OF_LIST(),
  229. };
  230. static void mipsnet_class_init(ObjectClass *klass, void *data)
  231. {
  232. DeviceClass *dc = DEVICE_CLASS(klass);
  233. SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
  234. k->init = mipsnet_sysbus_init;
  235. set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
  236. dc->desc = "MIPS Simulator network device";
  237. dc->reset = mipsnet_sysbus_reset;
  238. dc->vmsd = &vmstate_mipsnet;
  239. dc->props = mipsnet_properties;
  240. }
  241. static const TypeInfo mipsnet_info = {
  242. .name = TYPE_MIPS_NET,
  243. .parent = TYPE_SYS_BUS_DEVICE,
  244. .instance_size = sizeof(MIPSnetState),
  245. .class_init = mipsnet_class_init,
  246. };
  247. static void mipsnet_register_types(void)
  248. {
  249. type_register_static(&mipsnet_info);
  250. }
  251. type_init(mipsnet_register_types)