eeprom93xx.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  1. /*
  2. * QEMU EEPROM 93xx emulation
  3. *
  4. * Copyright (c) 2006-2007 Stefan Weil
  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. * This program 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
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, see <http://www.gnu.org/licenses/>.
  18. */
  19. /* Emulation for serial EEPROMs:
  20. * NMC93C06 256-Bit (16 x 16)
  21. * NMC93C46 1024-Bit (64 x 16)
  22. * NMC93C56 2028 Bit (128 x 16)
  23. * NMC93C66 4096 Bit (256 x 16)
  24. * Compatible devices include FM93C46 and others.
  25. *
  26. * Other drivers use these interface functions:
  27. * eeprom93xx_new - add a new EEPROM (with 16, 64 or 256 words)
  28. * eeprom93xx_free - destroy EEPROM
  29. * eeprom93xx_read - read data from the EEPROM
  30. * eeprom93xx_write - write data to the EEPROM
  31. * eeprom93xx_data - get EEPROM data array for external manipulation
  32. *
  33. * Todo list:
  34. * - No emulation of EEPROM timings.
  35. */
  36. #include "qemu/osdep.h"
  37. #include "hw/nvram/eeprom93xx.h"
  38. #include "migration/qemu-file-types.h"
  39. #include "migration/vmstate.h"
  40. /* Debug EEPROM emulation. */
  41. //~ #define DEBUG_EEPROM
  42. #ifdef DEBUG_EEPROM
  43. #define logout(fmt, ...) fprintf(stderr, "EEPROM\t%-24s" fmt, __func__, ## __VA_ARGS__)
  44. #else
  45. #define logout(fmt, ...) ((void)0)
  46. #endif
  47. #define EEPROM_INSTANCE 0
  48. #define OLD_EEPROM_VERSION 20061112
  49. #define EEPROM_VERSION (OLD_EEPROM_VERSION + 1)
  50. #if 0
  51. typedef enum {
  52. eeprom_read = 0x80, /* read register xx */
  53. eeprom_write = 0x40, /* write register xx */
  54. eeprom_erase = 0xc0, /* erase register xx */
  55. eeprom_ewen = 0x30, /* erase / write enable */
  56. eeprom_ewds = 0x00, /* erase / write disable */
  57. eeprom_eral = 0x20, /* erase all registers */
  58. eeprom_wral = 0x10, /* write all registers */
  59. eeprom_amask = 0x0f,
  60. eeprom_imask = 0xf0
  61. } eeprom_instruction_t;
  62. #endif
  63. #ifdef DEBUG_EEPROM
  64. static const char *opstring[] = {
  65. "extended", "write", "read", "erase"
  66. };
  67. #endif
  68. struct _eeprom_t {
  69. uint8_t tick;
  70. uint8_t address;
  71. uint8_t command;
  72. uint8_t writable;
  73. uint8_t eecs;
  74. uint8_t eesk;
  75. uint8_t eedo;
  76. uint8_t addrbits;
  77. uint16_t size;
  78. uint16_t data;
  79. uint16_t contents[];
  80. };
  81. /* Code for saving and restoring of EEPROM state. */
  82. /* Restore an uint16_t from an uint8_t
  83. This is a Big hack, but it is how the old state did it.
  84. */
  85. static int get_uint16_from_uint8(QEMUFile *f, void *pv, size_t size,
  86. const VMStateField *field)
  87. {
  88. uint16_t *v = pv;
  89. *v = qemu_get_ubyte(f);
  90. return 0;
  91. }
  92. static int put_unused(QEMUFile *f, void *pv, size_t size,
  93. const VMStateField *field, JSONWriter *vmdesc)
  94. {
  95. fprintf(stderr, "uint16_from_uint8 is used only for backwards compatibility.\n");
  96. fprintf(stderr, "Never should be used to write a new state.\n");
  97. exit(0);
  98. return 0;
  99. }
  100. static const VMStateInfo vmstate_hack_uint16_from_uint8 = {
  101. .name = "uint16_from_uint8",
  102. .get = get_uint16_from_uint8,
  103. .put = put_unused,
  104. };
  105. #define VMSTATE_UINT16_HACK_TEST(_f, _s, _t) \
  106. VMSTATE_SINGLE_TEST(_f, _s, _t, 0, vmstate_hack_uint16_from_uint8, uint16_t)
  107. static bool is_old_eeprom_version(void *opaque, int version_id)
  108. {
  109. return version_id == OLD_EEPROM_VERSION;
  110. }
  111. static const VMStateDescription vmstate_eeprom = {
  112. .name = "eeprom",
  113. .version_id = EEPROM_VERSION,
  114. .minimum_version_id = OLD_EEPROM_VERSION,
  115. .fields = (VMStateField[]) {
  116. VMSTATE_UINT8(tick, eeprom_t),
  117. VMSTATE_UINT8(address, eeprom_t),
  118. VMSTATE_UINT8(command, eeprom_t),
  119. VMSTATE_UINT8(writable, eeprom_t),
  120. VMSTATE_UINT8(eecs, eeprom_t),
  121. VMSTATE_UINT8(eesk, eeprom_t),
  122. VMSTATE_UINT8(eedo, eeprom_t),
  123. VMSTATE_UINT8(addrbits, eeprom_t),
  124. VMSTATE_UINT16_HACK_TEST(size, eeprom_t, is_old_eeprom_version),
  125. VMSTATE_UNUSED_TEST(is_old_eeprom_version, 1),
  126. VMSTATE_UINT16_EQUAL_V(size, eeprom_t, EEPROM_VERSION, NULL),
  127. VMSTATE_UINT16(data, eeprom_t),
  128. VMSTATE_VARRAY_UINT16_UNSAFE(contents, eeprom_t, size, 0,
  129. vmstate_info_uint16, uint16_t),
  130. VMSTATE_END_OF_LIST()
  131. }
  132. };
  133. void eeprom93xx_write(eeprom_t *eeprom, int eecs, int eesk, int eedi)
  134. {
  135. uint8_t tick = eeprom->tick;
  136. uint8_t eedo = eeprom->eedo;
  137. uint16_t address = eeprom->address;
  138. uint8_t command = eeprom->command;
  139. logout("CS=%u SK=%u DI=%u DO=%u, tick = %u\n",
  140. eecs, eesk, eedi, eedo, tick);
  141. if (!eeprom->eecs && eecs) {
  142. /* Start chip select cycle. */
  143. logout("Cycle start, waiting for 1st start bit (0)\n");
  144. tick = 0;
  145. command = 0x0;
  146. address = 0x0;
  147. } else if (eeprom->eecs && !eecs) {
  148. /* End chip select cycle. This triggers write / erase. */
  149. if (eeprom->writable) {
  150. uint8_t subcommand = address >> (eeprom->addrbits - 2);
  151. if (command == 0 && subcommand == 2) {
  152. /* Erase all. */
  153. for (address = 0; address < eeprom->size; address++) {
  154. eeprom->contents[address] = 0xffff;
  155. }
  156. } else if (command == 3) {
  157. /* Erase word. */
  158. eeprom->contents[address] = 0xffff;
  159. } else if (tick >= 2 + 2 + eeprom->addrbits + 16) {
  160. if (command == 1) {
  161. /* Write word. */
  162. eeprom->contents[address] &= eeprom->data;
  163. } else if (command == 0 && subcommand == 1) {
  164. /* Write all. */
  165. for (address = 0; address < eeprom->size; address++) {
  166. eeprom->contents[address] &= eeprom->data;
  167. }
  168. }
  169. }
  170. }
  171. /* Output DO is tristate, read results in 1. */
  172. eedo = 1;
  173. } else if (eecs && !eeprom->eesk && eesk) {
  174. /* Raising edge of clock shifts data in. */
  175. if (tick == 0) {
  176. /* Wait for 1st start bit. */
  177. if (eedi == 0) {
  178. logout("Got correct 1st start bit, waiting for 2nd start bit (1)\n");
  179. tick++;
  180. } else {
  181. logout("wrong 1st start bit (is 1, should be 0)\n");
  182. tick = 2;
  183. //~ assert(!"wrong start bit");
  184. }
  185. } else if (tick == 1) {
  186. /* Wait for 2nd start bit. */
  187. if (eedi != 0) {
  188. logout("Got correct 2nd start bit, getting command + address\n");
  189. tick++;
  190. } else {
  191. logout("1st start bit is longer than needed\n");
  192. }
  193. } else if (tick < 2 + 2) {
  194. /* Got 2 start bits, transfer 2 opcode bits. */
  195. tick++;
  196. command <<= 1;
  197. if (eedi) {
  198. command += 1;
  199. }
  200. } else if (tick < 2 + 2 + eeprom->addrbits) {
  201. /* Got 2 start bits and 2 opcode bits, transfer all address bits. */
  202. tick++;
  203. address = ((address << 1) | eedi);
  204. if (tick == 2 + 2 + eeprom->addrbits) {
  205. logout("%s command, address = 0x%02x (value 0x%04x)\n",
  206. opstring[command], address, eeprom->contents[address]);
  207. if (command == 2) {
  208. eedo = 0;
  209. }
  210. address = address % eeprom->size;
  211. if (command == 0) {
  212. /* Command code in upper 2 bits of address. */
  213. switch (address >> (eeprom->addrbits - 2)) {
  214. case 0:
  215. logout("write disable command\n");
  216. eeprom->writable = 0;
  217. break;
  218. case 1:
  219. logout("write all command\n");
  220. break;
  221. case 2:
  222. logout("erase all command\n");
  223. break;
  224. case 3:
  225. logout("write enable command\n");
  226. eeprom->writable = 1;
  227. break;
  228. }
  229. } else {
  230. /* Read, write or erase word. */
  231. eeprom->data = eeprom->contents[address];
  232. }
  233. }
  234. } else if (tick < 2 + 2 + eeprom->addrbits + 16) {
  235. /* Transfer 16 data bits. */
  236. tick++;
  237. if (command == 2) {
  238. /* Read word. */
  239. eedo = ((eeprom->data & 0x8000) != 0);
  240. }
  241. eeprom->data <<= 1;
  242. eeprom->data += eedi;
  243. } else {
  244. logout("additional unneeded tick, not processed\n");
  245. }
  246. }
  247. /* Save status of EEPROM. */
  248. eeprom->tick = tick;
  249. eeprom->eecs = eecs;
  250. eeprom->eesk = eesk;
  251. eeprom->eedo = eedo;
  252. eeprom->address = address;
  253. eeprom->command = command;
  254. }
  255. uint16_t eeprom93xx_read(eeprom_t *eeprom)
  256. {
  257. /* Return status of pin DO (0 or 1). */
  258. logout("CS=%u DO=%u\n", eeprom->eecs, eeprom->eedo);
  259. return eeprom->eedo;
  260. }
  261. #if 0
  262. void eeprom93xx_reset(eeprom_t *eeprom)
  263. {
  264. /* prepare eeprom */
  265. logout("eeprom = 0x%p\n", eeprom);
  266. eeprom->tick = 0;
  267. eeprom->command = 0;
  268. }
  269. #endif
  270. eeprom_t *eeprom93xx_new(DeviceState *dev, uint16_t nwords)
  271. {
  272. /* Add a new EEPROM (with 16, 64 or 256 words). */
  273. eeprom_t *eeprom;
  274. uint8_t addrbits;
  275. switch (nwords) {
  276. case 16:
  277. case 64:
  278. addrbits = 6;
  279. break;
  280. case 128:
  281. case 256:
  282. addrbits = 8;
  283. break;
  284. default:
  285. assert(!"Unsupported EEPROM size, fallback to 64 words!");
  286. nwords = 64;
  287. addrbits = 6;
  288. }
  289. eeprom = g_malloc0(sizeof(*eeprom) + nwords * 2);
  290. eeprom->size = nwords;
  291. eeprom->addrbits = addrbits;
  292. /* Output DO is tristate, read results in 1. */
  293. eeprom->eedo = 1;
  294. logout("eeprom = 0x%p, nwords = %u\n", eeprom, nwords);
  295. vmstate_register(VMSTATE_IF(dev), 0, &vmstate_eeprom, eeprom);
  296. return eeprom;
  297. }
  298. void eeprom93xx_free(DeviceState *dev, eeprom_t *eeprom)
  299. {
  300. /* Destroy EEPROM. */
  301. logout("eeprom = 0x%p\n", eeprom);
  302. vmstate_unregister(VMSTATE_IF(dev), &vmstate_eeprom, eeprom);
  303. g_free(eeprom);
  304. }
  305. uint16_t *eeprom93xx_data(eeprom_t *eeprom)
  306. {
  307. /* Get EEPROM data array. */
  308. return &eeprom->contents[0];
  309. }
  310. /* eof */