sii3112.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. /*
  2. * QEMU SiI3112A PCI to Serial ATA Controller Emulation
  3. *
  4. * Copyright (C) 2017 BALATON Zoltan <balaton@eik.bme.hu>
  5. *
  6. * This work is licensed under the terms of the GNU GPL, version 2 or later.
  7. * See the COPYING file in the top-level directory.
  8. *
  9. */
  10. /* For documentation on this and similar cards see:
  11. * http://wiki.osdev.org/User:Quok/Silicon_Image_Datasheets
  12. */
  13. #include "qemu/osdep.h"
  14. #include "hw/ide/pci.h"
  15. #include "qemu/module.h"
  16. #include "trace.h"
  17. #define TYPE_SII3112_PCI "sii3112"
  18. #define SII3112_PCI(obj) OBJECT_CHECK(SiI3112PCIState, (obj), \
  19. TYPE_SII3112_PCI)
  20. typedef struct SiI3112Regs {
  21. uint32_t confstat;
  22. uint32_t scontrol;
  23. uint16_t sien;
  24. uint8_t swdata;
  25. } SiI3112Regs;
  26. typedef struct SiI3112PCIState {
  27. PCIIDEState i;
  28. MemoryRegion mmio;
  29. SiI3112Regs regs[2];
  30. } SiI3112PCIState;
  31. /* The sii3112_reg_read and sii3112_reg_write functions implement the
  32. * Internal Register Space - BAR5 (section 6.7 of the data sheet).
  33. */
  34. static uint64_t sii3112_reg_read(void *opaque, hwaddr addr,
  35. unsigned int size)
  36. {
  37. SiI3112PCIState *d = opaque;
  38. uint64_t val = 0;
  39. switch (addr) {
  40. case 0x00:
  41. val = d->i.bmdma[0].cmd;
  42. break;
  43. case 0x01:
  44. val = d->regs[0].swdata;
  45. break;
  46. case 0x02:
  47. val = d->i.bmdma[0].status;
  48. break;
  49. case 0x03:
  50. val = 0;
  51. break;
  52. case 0x04 ... 0x07:
  53. val = bmdma_addr_ioport_ops.read(&d->i.bmdma[0], addr - 4, size);
  54. break;
  55. case 0x08:
  56. val = d->i.bmdma[1].cmd;
  57. break;
  58. case 0x09:
  59. val = d->regs[1].swdata;
  60. break;
  61. case 0x0a:
  62. val = d->i.bmdma[1].status;
  63. break;
  64. case 0x0b:
  65. val = 0;
  66. break;
  67. case 0x0c ... 0x0f:
  68. val = bmdma_addr_ioport_ops.read(&d->i.bmdma[1], addr - 12, size);
  69. break;
  70. case 0x10:
  71. val = d->i.bmdma[0].cmd;
  72. val |= (d->regs[0].confstat & (1UL << 11) ? (1 << 4) : 0); /*SATAINT0*/
  73. val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 6) : 0); /*SATAINT1*/
  74. val |= (d->i.bmdma[1].status & BM_STATUS_INT ? (1 << 14) : 0);
  75. val |= (uint32_t)d->i.bmdma[0].status << 16;
  76. val |= (uint32_t)d->i.bmdma[1].status << 24;
  77. break;
  78. case 0x18:
  79. val = d->i.bmdma[1].cmd;
  80. val |= (d->regs[1].confstat & (1UL << 11) ? (1 << 4) : 0);
  81. val |= (uint32_t)d->i.bmdma[1].status << 16;
  82. break;
  83. case 0x80 ... 0x87:
  84. val = pci_ide_data_le_ops.read(&d->i.bus[0], addr - 0x80, size);
  85. break;
  86. case 0x8a:
  87. val = pci_ide_cmd_le_ops.read(&d->i.bus[0], 2, size);
  88. break;
  89. case 0xa0:
  90. val = d->regs[0].confstat;
  91. break;
  92. case 0xc0 ... 0xc7:
  93. val = pci_ide_data_le_ops.read(&d->i.bus[1], addr - 0xc0, size);
  94. break;
  95. case 0xca:
  96. val = pci_ide_cmd_le_ops.read(&d->i.bus[1], 2, size);
  97. break;
  98. case 0xe0:
  99. val = d->regs[1].confstat;
  100. break;
  101. case 0x100:
  102. val = d->regs[0].scontrol;
  103. break;
  104. case 0x104:
  105. val = (d->i.bus[0].ifs[0].blk) ? 0x113 : 0;
  106. break;
  107. case 0x148:
  108. val = (uint32_t)d->regs[0].sien << 16;
  109. break;
  110. case 0x180:
  111. val = d->regs[1].scontrol;
  112. break;
  113. case 0x184:
  114. val = (d->i.bus[1].ifs[0].blk) ? 0x113 : 0;
  115. break;
  116. case 0x1c8:
  117. val = (uint32_t)d->regs[1].sien << 16;
  118. break;
  119. default:
  120. val = 0;
  121. }
  122. trace_sii3112_read(size, addr, val);
  123. return val;
  124. }
  125. static void sii3112_reg_write(void *opaque, hwaddr addr,
  126. uint64_t val, unsigned int size)
  127. {
  128. SiI3112PCIState *d = opaque;
  129. trace_sii3112_write(size, addr, val);
  130. switch (addr) {
  131. case 0x00:
  132. case 0x10:
  133. bmdma_cmd_writeb(&d->i.bmdma[0], val);
  134. break;
  135. case 0x01:
  136. case 0x11:
  137. d->regs[0].swdata = val & 0x3f;
  138. break;
  139. case 0x02:
  140. case 0x12:
  141. d->i.bmdma[0].status = (val & 0x60) | (d->i.bmdma[0].status & 1) |
  142. (d->i.bmdma[0].status & ~val & 6);
  143. break;
  144. case 0x04 ... 0x07:
  145. bmdma_addr_ioport_ops.write(&d->i.bmdma[0], addr - 4, val, size);
  146. break;
  147. case 0x08:
  148. case 0x18:
  149. bmdma_cmd_writeb(&d->i.bmdma[1], val);
  150. break;
  151. case 0x09:
  152. case 0x19:
  153. d->regs[1].swdata = val & 0x3f;
  154. break;
  155. case 0x0a:
  156. case 0x1a:
  157. d->i.bmdma[1].status = (val & 0x60) | (d->i.bmdma[1].status & 1) |
  158. (d->i.bmdma[1].status & ~val & 6);
  159. break;
  160. case 0x0c ... 0x0f:
  161. bmdma_addr_ioport_ops.write(&d->i.bmdma[1], addr - 12, val, size);
  162. break;
  163. case 0x80 ... 0x87:
  164. pci_ide_data_le_ops.write(&d->i.bus[0], addr - 0x80, val, size);
  165. break;
  166. case 0x8a:
  167. pci_ide_cmd_le_ops.write(&d->i.bus[0], 2, val, size);
  168. break;
  169. case 0xc0 ... 0xc7:
  170. pci_ide_data_le_ops.write(&d->i.bus[1], addr - 0xc0, val, size);
  171. break;
  172. case 0xca:
  173. pci_ide_cmd_le_ops.write(&d->i.bus[1], 2, val, size);
  174. break;
  175. case 0x100:
  176. d->regs[0].scontrol = val & 0xfff;
  177. if (val & 1) {
  178. ide_bus_reset(&d->i.bus[0]);
  179. }
  180. break;
  181. case 0x148:
  182. d->regs[0].sien = (val >> 16) & 0x3eed;
  183. break;
  184. case 0x180:
  185. d->regs[1].scontrol = val & 0xfff;
  186. if (val & 1) {
  187. ide_bus_reset(&d->i.bus[1]);
  188. }
  189. break;
  190. case 0x1c8:
  191. d->regs[1].sien = (val >> 16) & 0x3eed;
  192. break;
  193. default:
  194. val = 0;
  195. }
  196. }
  197. static const MemoryRegionOps sii3112_reg_ops = {
  198. .read = sii3112_reg_read,
  199. .write = sii3112_reg_write,
  200. .endianness = DEVICE_LITTLE_ENDIAN,
  201. };
  202. /* the PCI irq level is the logical OR of the two channels */
  203. static void sii3112_update_irq(SiI3112PCIState *s)
  204. {
  205. int i, set = 0;
  206. for (i = 0; i < 2; i++) {
  207. set |= s->regs[i].confstat & (1UL << 11);
  208. }
  209. pci_set_irq(PCI_DEVICE(s), (set ? 1 : 0));
  210. }
  211. static void sii3112_set_irq(void *opaque, int channel, int level)
  212. {
  213. SiI3112PCIState *s = opaque;
  214. trace_sii3112_set_irq(channel, level);
  215. if (level) {
  216. s->regs[channel].confstat |= (1UL << 11);
  217. } else {
  218. s->regs[channel].confstat &= ~(1UL << 11);
  219. }
  220. sii3112_update_irq(s);
  221. }
  222. static void sii3112_reset(DeviceState *dev)
  223. {
  224. SiI3112PCIState *s = SII3112_PCI(dev);
  225. int i;
  226. for (i = 0; i < 2; i++) {
  227. s->regs[i].confstat = 0x6515 << 16;
  228. ide_bus_reset(&s->i.bus[i]);
  229. }
  230. }
  231. static void sii3112_pci_realize(PCIDevice *dev, Error **errp)
  232. {
  233. SiI3112PCIState *d = SII3112_PCI(dev);
  234. PCIIDEState *s = PCI_IDE(dev);
  235. MemoryRegion *mr;
  236. qemu_irq *irq;
  237. int i;
  238. pci_config_set_interrupt_pin(dev->config, 1);
  239. pci_set_byte(dev->config + PCI_CACHE_LINE_SIZE, 8);
  240. /* BAR5 is in PCI memory space */
  241. memory_region_init_io(&d->mmio, OBJECT(d), &sii3112_reg_ops, d,
  242. "sii3112.bar5", 0x200);
  243. pci_register_bar(dev, 5, PCI_BASE_ADDRESS_SPACE_MEMORY, &d->mmio);
  244. /* BAR0-BAR4 are PCI I/O space aliases into BAR5 */
  245. mr = g_new(MemoryRegion, 1);
  246. memory_region_init_alias(mr, OBJECT(d), "sii3112.bar0", &d->mmio, 0x80, 8);
  247. pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, mr);
  248. mr = g_new(MemoryRegion, 1);
  249. memory_region_init_alias(mr, OBJECT(d), "sii3112.bar1", &d->mmio, 0x88, 4);
  250. pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, mr);
  251. mr = g_new(MemoryRegion, 1);
  252. memory_region_init_alias(mr, OBJECT(d), "sii3112.bar2", &d->mmio, 0xc0, 8);
  253. pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, mr);
  254. mr = g_new(MemoryRegion, 1);
  255. memory_region_init_alias(mr, OBJECT(d), "sii3112.bar3", &d->mmio, 0xc8, 4);
  256. pci_register_bar(dev, 3, PCI_BASE_ADDRESS_SPACE_IO, mr);
  257. mr = g_new(MemoryRegion, 1);
  258. memory_region_init_alias(mr, OBJECT(d), "sii3112.bar4", &d->mmio, 0, 16);
  259. pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, mr);
  260. irq = qemu_allocate_irqs(sii3112_set_irq, d, 2);
  261. for (i = 0; i < 2; i++) {
  262. ide_bus_new(&s->bus[i], sizeof(s->bus[i]), DEVICE(dev), i, 1);
  263. ide_init2(&s->bus[i], irq[i]);
  264. bmdma_init(&s->bus[i], &s->bmdma[i], s);
  265. s->bmdma[i].bus = &s->bus[i];
  266. ide_register_restart_cb(&s->bus[i]);
  267. }
  268. }
  269. static void sii3112_pci_class_init(ObjectClass *klass, void *data)
  270. {
  271. DeviceClass *dc = DEVICE_CLASS(klass);
  272. PCIDeviceClass *pd = PCI_DEVICE_CLASS(klass);
  273. pd->vendor_id = 0x1095;
  274. pd->device_id = 0x3112;
  275. pd->class_id = PCI_CLASS_STORAGE_RAID;
  276. pd->revision = 1;
  277. pd->realize = sii3112_pci_realize;
  278. dc->reset = sii3112_reset;
  279. dc->desc = "SiI3112A SATA controller";
  280. set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
  281. }
  282. static const TypeInfo sii3112_pci_info = {
  283. .name = TYPE_SII3112_PCI,
  284. .parent = TYPE_PCI_IDE,
  285. .instance_size = sizeof(SiI3112PCIState),
  286. .class_init = sii3112_pci_class_init,
  287. };
  288. static void sii3112_register_types(void)
  289. {
  290. type_register_static(&sii3112_pci_info);
  291. }
  292. type_init(sii3112_register_types)