smbus_slave.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /*
  2. * QEMU SMBus device emulation.
  3. *
  4. * This code is a helper for SMBus device emulation. It implements an
  5. * I2C device inteface and runs the SMBus protocol from the device
  6. * point of view and maps those to simple calls to emulate.
  7. *
  8. * Copyright (c) 2007 CodeSourcery.
  9. * Written by Paul Brook
  10. *
  11. * This code is licensed under the LGPL.
  12. */
  13. /* TODO: Implement PEC. */
  14. #include "qemu/osdep.h"
  15. #include "hw/i2c/i2c.h"
  16. #include "hw/i2c/smbus_slave.h"
  17. #include "migration/vmstate.h"
  18. #include "qemu/module.h"
  19. //#define DEBUG_SMBUS 1
  20. #ifdef DEBUG_SMBUS
  21. #define DPRINTF(fmt, ...) \
  22. do { printf("smbus(%02x): " fmt , dev->i2c.address, ## __VA_ARGS__); } while (0)
  23. #define BADF(fmt, ...) \
  24. do { fprintf(stderr, "smbus: error: " fmt , ## __VA_ARGS__); exit(1);} while (0)
  25. #else
  26. #define DPRINTF(fmt, ...) do {} while(0)
  27. #define BADF(fmt, ...) \
  28. do { fprintf(stderr, "smbus: error: " fmt , ## __VA_ARGS__);} while (0)
  29. #endif
  30. enum {
  31. SMBUS_IDLE,
  32. SMBUS_WRITE_DATA,
  33. SMBUS_READ_DATA,
  34. SMBUS_DONE,
  35. SMBUS_CONFUSED = -1
  36. };
  37. static void smbus_do_quick_cmd(SMBusDevice *dev, int recv)
  38. {
  39. SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
  40. DPRINTF("Quick Command %d\n", recv);
  41. if (sc->quick_cmd) {
  42. sc->quick_cmd(dev, recv);
  43. }
  44. }
  45. static void smbus_do_write(SMBusDevice *dev)
  46. {
  47. SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
  48. DPRINTF("Command %d len %d\n", dev->data_buf[0], dev->data_len);
  49. if (sc->write_data) {
  50. sc->write_data(dev, dev->data_buf, dev->data_len);
  51. }
  52. }
  53. static int smbus_i2c_event(I2CSlave *s, enum i2c_event event)
  54. {
  55. SMBusDevice *dev = SMBUS_DEVICE(s);
  56. switch (event) {
  57. case I2C_START_SEND:
  58. switch (dev->mode) {
  59. case SMBUS_IDLE:
  60. DPRINTF("Incoming data\n");
  61. dev->mode = SMBUS_WRITE_DATA;
  62. break;
  63. default:
  64. BADF("Unexpected send start condition in state %d\n", dev->mode);
  65. dev->mode = SMBUS_CONFUSED;
  66. break;
  67. }
  68. break;
  69. case I2C_START_RECV:
  70. switch (dev->mode) {
  71. case SMBUS_IDLE:
  72. DPRINTF("Read mode\n");
  73. dev->mode = SMBUS_READ_DATA;
  74. break;
  75. case SMBUS_WRITE_DATA:
  76. if (dev->data_len == 0) {
  77. BADF("Read after write with no data\n");
  78. dev->mode = SMBUS_CONFUSED;
  79. } else {
  80. smbus_do_write(dev);
  81. DPRINTF("Read mode\n");
  82. dev->mode = SMBUS_READ_DATA;
  83. }
  84. break;
  85. default:
  86. BADF("Unexpected recv start condition in state %d\n", dev->mode);
  87. dev->mode = SMBUS_CONFUSED;
  88. break;
  89. }
  90. break;
  91. case I2C_FINISH:
  92. if (dev->data_len == 0) {
  93. if (dev->mode == SMBUS_WRITE_DATA || dev->mode == SMBUS_READ_DATA) {
  94. smbus_do_quick_cmd(dev, dev->mode == SMBUS_READ_DATA);
  95. }
  96. } else {
  97. switch (dev->mode) {
  98. case SMBUS_WRITE_DATA:
  99. smbus_do_write(dev);
  100. break;
  101. case SMBUS_READ_DATA:
  102. BADF("Unexpected stop during receive\n");
  103. break;
  104. default:
  105. /* Nothing to do. */
  106. break;
  107. }
  108. }
  109. dev->mode = SMBUS_IDLE;
  110. dev->data_len = 0;
  111. break;
  112. case I2C_NACK:
  113. switch (dev->mode) {
  114. case SMBUS_DONE:
  115. /* Nothing to do. */
  116. break;
  117. case SMBUS_READ_DATA:
  118. dev->mode = SMBUS_DONE;
  119. break;
  120. default:
  121. BADF("Unexpected NACK in state %d\n", dev->mode);
  122. dev->mode = SMBUS_CONFUSED;
  123. break;
  124. }
  125. break;
  126. default:
  127. return -1;
  128. }
  129. return 0;
  130. }
  131. static uint8_t smbus_i2c_recv(I2CSlave *s)
  132. {
  133. SMBusDevice *dev = SMBUS_DEVICE(s);
  134. SMBusDeviceClass *sc = SMBUS_DEVICE_GET_CLASS(dev);
  135. uint8_t ret = 0xff;
  136. switch (dev->mode) {
  137. case SMBUS_READ_DATA:
  138. if (sc->receive_byte) {
  139. ret = sc->receive_byte(dev);
  140. }
  141. DPRINTF("Read data %02x\n", ret);
  142. break;
  143. default:
  144. BADF("Unexpected read in state %d\n", dev->mode);
  145. dev->mode = SMBUS_CONFUSED;
  146. break;
  147. }
  148. return ret;
  149. }
  150. static int smbus_i2c_send(I2CSlave *s, uint8_t data)
  151. {
  152. SMBusDevice *dev = SMBUS_DEVICE(s);
  153. switch (dev->mode) {
  154. case SMBUS_WRITE_DATA:
  155. DPRINTF("Write data %02x\n", data);
  156. if (dev->data_len >= sizeof(dev->data_buf)) {
  157. BADF("Too many bytes sent\n");
  158. } else {
  159. dev->data_buf[dev->data_len++] = data;
  160. }
  161. break;
  162. default:
  163. BADF("Unexpected write in state %d\n", dev->mode);
  164. break;
  165. }
  166. return 0;
  167. }
  168. static void smbus_device_class_init(ObjectClass *klass, void *data)
  169. {
  170. I2CSlaveClass *sc = I2C_SLAVE_CLASS(klass);
  171. sc->event = smbus_i2c_event;
  172. sc->recv = smbus_i2c_recv;
  173. sc->send = smbus_i2c_send;
  174. }
  175. bool smbus_vmstate_needed(SMBusDevice *dev)
  176. {
  177. return dev->mode != SMBUS_IDLE;
  178. }
  179. const VMStateDescription vmstate_smbus_device = {
  180. .name = TYPE_SMBUS_DEVICE,
  181. .version_id = 1,
  182. .minimum_version_id = 1,
  183. .fields = (VMStateField[]) {
  184. VMSTATE_I2C_SLAVE(i2c, SMBusDevice),
  185. VMSTATE_INT32(mode, SMBusDevice),
  186. VMSTATE_INT32(data_len, SMBusDevice),
  187. VMSTATE_UINT8_ARRAY(data_buf, SMBusDevice, SMBUS_DATA_MAX_LEN),
  188. VMSTATE_END_OF_LIST()
  189. }
  190. };
  191. static const TypeInfo smbus_device_type_info = {
  192. .name = TYPE_SMBUS_DEVICE,
  193. .parent = TYPE_I2C_SLAVE,
  194. .instance_size = sizeof(SMBusDevice),
  195. .abstract = true,
  196. .class_size = sizeof(SMBusDeviceClass),
  197. .class_init = smbus_device_class_init,
  198. };
  199. static void smbus_device_register_types(void)
  200. {
  201. type_register_static(&smbus_device_type_info);
  202. }
  203. type_init(smbus_device_register_types)