milkymist-minimac2.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548
  1. /*
  2. * QEMU model of the Milkymist minimac2 block.
  3. *
  4. * Copyright (c) 2011 Michael Walle <michael@walle.cc>
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18. *
  19. *
  20. * Specification available at:
  21. * not available yet
  22. *
  23. */
  24. #include "qemu/osdep.h"
  25. #include "qapi/error.h"
  26. #include "cpu.h" /* FIXME: why does this use TARGET_PAGE_ALIGN? */
  27. #include "hw/irq.h"
  28. #include "hw/qdev-properties.h"
  29. #include "hw/sysbus.h"
  30. #include "migration/vmstate.h"
  31. #include "trace.h"
  32. #include "net/net.h"
  33. #include "qemu/log.h"
  34. #include "qemu/module.h"
  35. #include "qemu/error-report.h"
  36. #include <zlib.h>
  37. enum {
  38. R_SETUP = 0,
  39. R_MDIO,
  40. R_STATE0,
  41. R_COUNT0,
  42. R_STATE1,
  43. R_COUNT1,
  44. R_TXCOUNT,
  45. R_MAX
  46. };
  47. enum {
  48. SETUP_PHY_RST = (1<<0),
  49. };
  50. enum {
  51. MDIO_DO = (1<<0),
  52. MDIO_DI = (1<<1),
  53. MDIO_OE = (1<<2),
  54. MDIO_CLK = (1<<3),
  55. };
  56. enum {
  57. STATE_EMPTY = 0,
  58. STATE_LOADED = 1,
  59. STATE_PENDING = 2,
  60. };
  61. enum {
  62. MDIO_OP_WRITE = 1,
  63. MDIO_OP_READ = 2,
  64. };
  65. enum mdio_state {
  66. MDIO_STATE_IDLE,
  67. MDIO_STATE_READING,
  68. MDIO_STATE_WRITING,
  69. };
  70. enum {
  71. R_PHY_ID1 = 2,
  72. R_PHY_ID2 = 3,
  73. R_PHY_MAX = 32
  74. };
  75. #define MINIMAC2_MTU 1530
  76. #define MINIMAC2_BUFFER_SIZE 2048
  77. struct MilkymistMinimac2MdioState {
  78. int last_clk;
  79. int count;
  80. uint32_t data;
  81. uint16_t data_out;
  82. int state;
  83. uint8_t phy_addr;
  84. uint8_t reg_addr;
  85. };
  86. typedef struct MilkymistMinimac2MdioState MilkymistMinimac2MdioState;
  87. #define TYPE_MILKYMIST_MINIMAC2 "milkymist-minimac2"
  88. #define MILKYMIST_MINIMAC2(obj) \
  89. OBJECT_CHECK(MilkymistMinimac2State, (obj), TYPE_MILKYMIST_MINIMAC2)
  90. struct MilkymistMinimac2State {
  91. SysBusDevice parent_obj;
  92. NICState *nic;
  93. NICConf conf;
  94. char *phy_model;
  95. MemoryRegion buffers;
  96. MemoryRegion regs_region;
  97. qemu_irq rx_irq;
  98. qemu_irq tx_irq;
  99. uint32_t regs[R_MAX];
  100. MilkymistMinimac2MdioState mdio;
  101. uint16_t phy_regs[R_PHY_MAX];
  102. uint8_t *rx0_buf;
  103. uint8_t *rx1_buf;
  104. uint8_t *tx_buf;
  105. };
  106. typedef struct MilkymistMinimac2State MilkymistMinimac2State;
  107. static const uint8_t preamble_sfd[] = {
  108. 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5
  109. };
  110. static void minimac2_mdio_write_reg(MilkymistMinimac2State *s,
  111. uint8_t phy_addr, uint8_t reg_addr, uint16_t value)
  112. {
  113. trace_milkymist_minimac2_mdio_write(phy_addr, reg_addr, value);
  114. /* nop */
  115. }
  116. static uint16_t minimac2_mdio_read_reg(MilkymistMinimac2State *s,
  117. uint8_t phy_addr, uint8_t reg_addr)
  118. {
  119. uint16_t r = s->phy_regs[reg_addr];
  120. trace_milkymist_minimac2_mdio_read(phy_addr, reg_addr, r);
  121. return r;
  122. }
  123. static void minimac2_update_mdio(MilkymistMinimac2State *s)
  124. {
  125. MilkymistMinimac2MdioState *m = &s->mdio;
  126. /* detect rising clk edge */
  127. if (m->last_clk == 0 && (s->regs[R_MDIO] & MDIO_CLK)) {
  128. /* shift data in */
  129. int bit = ((s->regs[R_MDIO] & MDIO_DO)
  130. && (s->regs[R_MDIO] & MDIO_OE)) ? 1 : 0;
  131. m->data = (m->data << 1) | bit;
  132. /* check for sync */
  133. if (m->data == 0xffffffff) {
  134. m->count = 32;
  135. }
  136. if (m->count == 16) {
  137. uint8_t start = (m->data >> 14) & 0x3;
  138. uint8_t op = (m->data >> 12) & 0x3;
  139. uint8_t ta = (m->data) & 0x3;
  140. if (start == 1 && op == MDIO_OP_WRITE && ta == 2) {
  141. m->state = MDIO_STATE_WRITING;
  142. } else if (start == 1 && op == MDIO_OP_READ && (ta & 1) == 0) {
  143. m->state = MDIO_STATE_READING;
  144. } else {
  145. m->state = MDIO_STATE_IDLE;
  146. }
  147. if (m->state != MDIO_STATE_IDLE) {
  148. m->phy_addr = (m->data >> 7) & 0x1f;
  149. m->reg_addr = (m->data >> 2) & 0x1f;
  150. }
  151. if (m->state == MDIO_STATE_READING) {
  152. m->data_out = minimac2_mdio_read_reg(s, m->phy_addr,
  153. m->reg_addr);
  154. }
  155. }
  156. if (m->count < 16 && m->state == MDIO_STATE_READING) {
  157. int bit = (m->data_out & 0x8000) ? 1 : 0;
  158. m->data_out <<= 1;
  159. if (bit) {
  160. s->regs[R_MDIO] |= MDIO_DI;
  161. } else {
  162. s->regs[R_MDIO] &= ~MDIO_DI;
  163. }
  164. }
  165. if (m->count == 0 && m->state) {
  166. if (m->state == MDIO_STATE_WRITING) {
  167. uint16_t data = m->data & 0xffff;
  168. minimac2_mdio_write_reg(s, m->phy_addr, m->reg_addr, data);
  169. }
  170. m->state = MDIO_STATE_IDLE;
  171. }
  172. m->count--;
  173. }
  174. m->last_clk = (s->regs[R_MDIO] & MDIO_CLK) ? 1 : 0;
  175. }
  176. static size_t assemble_frame(uint8_t *buf, size_t size,
  177. const uint8_t *payload, size_t payload_size)
  178. {
  179. uint32_t crc;
  180. if (size < payload_size + 12) {
  181. qemu_log_mask(LOG_GUEST_ERROR, "milkymist_minimac2: frame too big "
  182. "(%zd bytes)\n", payload_size);
  183. return 0;
  184. }
  185. /* prepend preamble and sfd */
  186. memcpy(buf, preamble_sfd, 8);
  187. /* now copy the payload */
  188. memcpy(buf + 8, payload, payload_size);
  189. /* pad frame if needed */
  190. if (payload_size < 60) {
  191. memset(buf + payload_size + 8, 0, 60 - payload_size);
  192. payload_size = 60;
  193. }
  194. /* append fcs */
  195. crc = cpu_to_le32(crc32(0, buf + 8, payload_size));
  196. memcpy(buf + payload_size + 8, &crc, 4);
  197. return payload_size + 12;
  198. }
  199. static void minimac2_tx(MilkymistMinimac2State *s)
  200. {
  201. uint32_t txcount = s->regs[R_TXCOUNT];
  202. uint8_t *buf = s->tx_buf;
  203. if (txcount < 64) {
  204. error_report("milkymist_minimac2: ethernet frame too small (%u < %u)",
  205. txcount, 64);
  206. goto err;
  207. }
  208. if (txcount > MINIMAC2_MTU) {
  209. error_report("milkymist_minimac2: MTU exceeded (%u > %u)",
  210. txcount, MINIMAC2_MTU);
  211. goto err;
  212. }
  213. if (memcmp(buf, preamble_sfd, 8) != 0) {
  214. error_report("milkymist_minimac2: frame doesn't contain the preamble "
  215. "and/or the SFD (%02x %02x %02x %02x %02x %02x %02x %02x)",
  216. buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
  217. goto err;
  218. }
  219. trace_milkymist_minimac2_tx_frame(txcount - 12);
  220. /* send packet, skipping preamble and sfd */
  221. qemu_send_packet_raw(qemu_get_queue(s->nic), buf + 8, txcount - 12);
  222. s->regs[R_TXCOUNT] = 0;
  223. err:
  224. trace_milkymist_minimac2_pulse_irq_tx();
  225. qemu_irq_pulse(s->tx_irq);
  226. }
  227. static void update_rx_interrupt(MilkymistMinimac2State *s)
  228. {
  229. if (s->regs[R_STATE0] == STATE_PENDING
  230. || s->regs[R_STATE1] == STATE_PENDING) {
  231. trace_milkymist_minimac2_raise_irq_rx();
  232. qemu_irq_raise(s->rx_irq);
  233. } else {
  234. trace_milkymist_minimac2_lower_irq_rx();
  235. qemu_irq_lower(s->rx_irq);
  236. }
  237. }
  238. static ssize_t minimac2_rx(NetClientState *nc, const uint8_t *buf, size_t size)
  239. {
  240. MilkymistMinimac2State *s = qemu_get_nic_opaque(nc);
  241. uint32_t r_count;
  242. uint32_t r_state;
  243. uint8_t *rx_buf;
  244. size_t frame_size;
  245. trace_milkymist_minimac2_rx_frame(buf, size);
  246. /* choose appropriate slot */
  247. if (s->regs[R_STATE0] == STATE_LOADED) {
  248. r_count = R_COUNT0;
  249. r_state = R_STATE0;
  250. rx_buf = s->rx0_buf;
  251. } else if (s->regs[R_STATE1] == STATE_LOADED) {
  252. r_count = R_COUNT1;
  253. r_state = R_STATE1;
  254. rx_buf = s->rx1_buf;
  255. } else {
  256. return 0;
  257. }
  258. /* assemble frame */
  259. frame_size = assemble_frame(rx_buf, MINIMAC2_BUFFER_SIZE, buf, size);
  260. if (frame_size == 0) {
  261. return size;
  262. }
  263. trace_milkymist_minimac2_rx_transfer(rx_buf, frame_size);
  264. /* update slot */
  265. s->regs[r_count] = frame_size;
  266. s->regs[r_state] = STATE_PENDING;
  267. update_rx_interrupt(s);
  268. return size;
  269. }
  270. static uint64_t
  271. minimac2_read(void *opaque, hwaddr addr, unsigned size)
  272. {
  273. MilkymistMinimac2State *s = opaque;
  274. uint32_t r = 0;
  275. addr >>= 2;
  276. switch (addr) {
  277. case R_SETUP:
  278. case R_MDIO:
  279. case R_STATE0:
  280. case R_COUNT0:
  281. case R_STATE1:
  282. case R_COUNT1:
  283. case R_TXCOUNT:
  284. r = s->regs[addr];
  285. break;
  286. default:
  287. qemu_log_mask(LOG_GUEST_ERROR,
  288. "milkymist_minimac2_rd%d: 0x%" HWADDR_PRIx "\n",
  289. size, addr << 2);
  290. break;
  291. }
  292. trace_milkymist_minimac2_memory_read(addr << 2, r);
  293. return r;
  294. }
  295. static int minimac2_can_rx(MilkymistMinimac2State *s)
  296. {
  297. if (s->regs[R_STATE0] == STATE_LOADED) {
  298. return 1;
  299. }
  300. if (s->regs[R_STATE1] == STATE_LOADED) {
  301. return 1;
  302. }
  303. return 0;
  304. }
  305. static void
  306. minimac2_write(void *opaque, hwaddr addr, uint64_t value,
  307. unsigned size)
  308. {
  309. MilkymistMinimac2State *s = opaque;
  310. trace_milkymist_minimac2_memory_write(addr, value);
  311. addr >>= 2;
  312. switch (addr) {
  313. case R_MDIO:
  314. {
  315. /* MDIO_DI is read only */
  316. int mdio_di = (s->regs[R_MDIO] & MDIO_DI);
  317. s->regs[R_MDIO] = value;
  318. if (mdio_di) {
  319. s->regs[R_MDIO] |= mdio_di;
  320. } else {
  321. s->regs[R_MDIO] &= ~mdio_di;
  322. }
  323. minimac2_update_mdio(s);
  324. } break;
  325. case R_TXCOUNT:
  326. s->regs[addr] = value;
  327. if (value > 0) {
  328. minimac2_tx(s);
  329. }
  330. break;
  331. case R_STATE0:
  332. case R_STATE1:
  333. s->regs[addr] = value;
  334. update_rx_interrupt(s);
  335. if (minimac2_can_rx(s)) {
  336. qemu_flush_queued_packets(qemu_get_queue(s->nic));
  337. }
  338. break;
  339. case R_SETUP:
  340. case R_COUNT0:
  341. case R_COUNT1:
  342. s->regs[addr] = value;
  343. break;
  344. default:
  345. qemu_log_mask(LOG_GUEST_ERROR,
  346. "milkymist_minimac2_wr%d: 0x%" HWADDR_PRIx
  347. " = 0x%" PRIx64 "\n",
  348. size, addr << 2, value);
  349. break;
  350. }
  351. }
  352. static const MemoryRegionOps minimac2_ops = {
  353. .read = minimac2_read,
  354. .write = minimac2_write,
  355. .valid = {
  356. .min_access_size = 4,
  357. .max_access_size = 4,
  358. },
  359. .endianness = DEVICE_NATIVE_ENDIAN,
  360. };
  361. static void milkymist_minimac2_reset(DeviceState *d)
  362. {
  363. MilkymistMinimac2State *s = MILKYMIST_MINIMAC2(d);
  364. int i;
  365. for (i = 0; i < R_MAX; i++) {
  366. s->regs[i] = 0;
  367. }
  368. for (i = 0; i < R_PHY_MAX; i++) {
  369. s->phy_regs[i] = 0;
  370. }
  371. /* defaults */
  372. s->phy_regs[R_PHY_ID1] = 0x0022; /* Micrel KSZ8001L */
  373. s->phy_regs[R_PHY_ID2] = 0x161a;
  374. }
  375. static NetClientInfo net_milkymist_minimac2_info = {
  376. .type = NET_CLIENT_DRIVER_NIC,
  377. .size = sizeof(NICState),
  378. .receive = minimac2_rx,
  379. };
  380. static void milkymist_minimac2_realize(DeviceState *dev, Error **errp)
  381. {
  382. SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
  383. MilkymistMinimac2State *s = MILKYMIST_MINIMAC2(dev);
  384. size_t buffers_size = TARGET_PAGE_ALIGN(3 * MINIMAC2_BUFFER_SIZE);
  385. sysbus_init_irq(sbd, &s->rx_irq);
  386. sysbus_init_irq(sbd, &s->tx_irq);
  387. memory_region_init_io(&s->regs_region, OBJECT(dev), &minimac2_ops, s,
  388. "milkymist-minimac2", R_MAX * 4);
  389. sysbus_init_mmio(sbd, &s->regs_region);
  390. /* register buffers memory */
  391. memory_region_init_ram_nomigrate(&s->buffers, OBJECT(dev), "milkymist-minimac2.buffers",
  392. buffers_size, &error_fatal);
  393. vmstate_register_ram_global(&s->buffers);
  394. s->rx0_buf = memory_region_get_ram_ptr(&s->buffers);
  395. s->rx1_buf = s->rx0_buf + MINIMAC2_BUFFER_SIZE;
  396. s->tx_buf = s->rx1_buf + MINIMAC2_BUFFER_SIZE;
  397. sysbus_init_mmio(sbd, &s->buffers);
  398. qemu_macaddr_default_if_unset(&s->conf.macaddr);
  399. s->nic = qemu_new_nic(&net_milkymist_minimac2_info, &s->conf,
  400. object_get_typename(OBJECT(dev)), dev->id, s);
  401. qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
  402. }
  403. static const VMStateDescription vmstate_milkymist_minimac2_mdio = {
  404. .name = "milkymist-minimac2-mdio",
  405. .version_id = 1,
  406. .minimum_version_id = 1,
  407. .fields = (VMStateField[]) {
  408. VMSTATE_INT32(last_clk, MilkymistMinimac2MdioState),
  409. VMSTATE_INT32(count, MilkymistMinimac2MdioState),
  410. VMSTATE_UINT32(data, MilkymistMinimac2MdioState),
  411. VMSTATE_UINT16(data_out, MilkymistMinimac2MdioState),
  412. VMSTATE_INT32(state, MilkymistMinimac2MdioState),
  413. VMSTATE_UINT8(phy_addr, MilkymistMinimac2MdioState),
  414. VMSTATE_UINT8(reg_addr, MilkymistMinimac2MdioState),
  415. VMSTATE_END_OF_LIST()
  416. }
  417. };
  418. static const VMStateDescription vmstate_milkymist_minimac2 = {
  419. .name = "milkymist-minimac2",
  420. .version_id = 1,
  421. .minimum_version_id = 1,
  422. .fields = (VMStateField[]) {
  423. VMSTATE_UINT32_ARRAY(regs, MilkymistMinimac2State, R_MAX),
  424. VMSTATE_UINT16_ARRAY(phy_regs, MilkymistMinimac2State, R_PHY_MAX),
  425. VMSTATE_STRUCT(mdio, MilkymistMinimac2State, 0,
  426. vmstate_milkymist_minimac2_mdio, MilkymistMinimac2MdioState),
  427. VMSTATE_END_OF_LIST()
  428. }
  429. };
  430. static Property milkymist_minimac2_properties[] = {
  431. DEFINE_NIC_PROPERTIES(MilkymistMinimac2State, conf),
  432. DEFINE_PROP_STRING("phy_model", MilkymistMinimac2State, phy_model),
  433. DEFINE_PROP_END_OF_LIST(),
  434. };
  435. static void milkymist_minimac2_class_init(ObjectClass *klass, void *data)
  436. {
  437. DeviceClass *dc = DEVICE_CLASS(klass);
  438. dc->realize = milkymist_minimac2_realize;
  439. dc->reset = milkymist_minimac2_reset;
  440. dc->vmsd = &vmstate_milkymist_minimac2;
  441. dc->props = milkymist_minimac2_properties;
  442. }
  443. static const TypeInfo milkymist_minimac2_info = {
  444. .name = TYPE_MILKYMIST_MINIMAC2,
  445. .parent = TYPE_SYS_BUS_DEVICE,
  446. .instance_size = sizeof(MilkymistMinimac2State),
  447. .class_init = milkymist_minimac2_class_init,
  448. };
  449. static void milkymist_minimac2_register_types(void)
  450. {
  451. type_register_static(&milkymist_minimac2_info);
  452. }
  453. type_init(milkymist_minimac2_register_types)