2
0

via.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. /*
  2. * QEMU IDE Emulation: PCI VIA82C686B support.
  3. *
  4. * Copyright (c) 2003 Fabrice Bellard
  5. * Copyright (c) 2006 Openedhand Ltd.
  6. * Copyright (c) 2010 Huacai Chen <zltjiangshi@gmail.com>
  7. *
  8. * Permission is hereby granted, free of charge, to any person obtaining a copy
  9. * of this software and associated documentation files (the "Software"), to deal
  10. * in the Software without restriction, including without limitation the rights
  11. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  12. * copies of the Software, and to permit persons to whom the Software is
  13. * furnished to do so, subject to the following conditions:
  14. *
  15. * The above copyright notice and this permission notice shall be included in
  16. * all copies or substantial portions of the Software.
  17. *
  18. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  19. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  20. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  21. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  22. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  23. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  24. * THE SOFTWARE.
  25. */
  26. #include "qemu/osdep.h"
  27. #include "hw/pci/pci.h"
  28. #include "migration/vmstate.h"
  29. #include "qemu/module.h"
  30. #include "sysemu/dma.h"
  31. #include "hw/ide/pci.h"
  32. #include "trace.h"
  33. static uint64_t bmdma_read(void *opaque, hwaddr addr,
  34. unsigned size)
  35. {
  36. BMDMAState *bm = opaque;
  37. uint32_t val;
  38. if (size != 1) {
  39. return ((uint64_t)1 << (size * 8)) - 1;
  40. }
  41. switch (addr & 3) {
  42. case 0:
  43. val = bm->cmd;
  44. break;
  45. case 2:
  46. val = bm->status;
  47. break;
  48. default:
  49. val = 0xff;
  50. break;
  51. }
  52. trace_bmdma_read_via(addr, val);
  53. return val;
  54. }
  55. static void bmdma_write(void *opaque, hwaddr addr,
  56. uint64_t val, unsigned size)
  57. {
  58. BMDMAState *bm = opaque;
  59. if (size != 1) {
  60. return;
  61. }
  62. trace_bmdma_write_via(addr, val);
  63. switch (addr & 3) {
  64. case 0:
  65. bmdma_cmd_writeb(bm, val);
  66. break;
  67. case 2:
  68. bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06);
  69. break;
  70. default:;
  71. }
  72. }
  73. static const MemoryRegionOps via_bmdma_ops = {
  74. .read = bmdma_read,
  75. .write = bmdma_write,
  76. };
  77. static void bmdma_setup_bar(PCIIDEState *d)
  78. {
  79. int i;
  80. memory_region_init(&d->bmdma_bar, OBJECT(d), "via-bmdma-container", 16);
  81. for(i = 0;i < 2; i++) {
  82. BMDMAState *bm = &d->bmdma[i];
  83. memory_region_init_io(&bm->extra_io, OBJECT(d), &via_bmdma_ops, bm,
  84. "via-bmdma", 4);
  85. memory_region_add_subregion(&d->bmdma_bar, i * 8, &bm->extra_io);
  86. memory_region_init_io(&bm->addr_ioport, OBJECT(d),
  87. &bmdma_addr_ioport_ops, bm, "bmdma", 4);
  88. memory_region_add_subregion(&d->bmdma_bar, i * 8 + 4, &bm->addr_ioport);
  89. }
  90. }
  91. static void via_ide_set_irq(void *opaque, int n, int level)
  92. {
  93. PCIDevice *d = PCI_DEVICE(opaque);
  94. if (level) {
  95. d->config[0x70 + n * 8] |= 0x80;
  96. } else {
  97. d->config[0x70 + n * 8] &= ~0x80;
  98. }
  99. level = (d->config[0x70] & 0x80) || (d->config[0x78] & 0x80);
  100. n = pci_get_byte(d->config + PCI_INTERRUPT_LINE);
  101. if (n) {
  102. qemu_set_irq(isa_get_irq(NULL, n), level);
  103. }
  104. }
  105. static void via_ide_reset(DeviceState *dev)
  106. {
  107. PCIIDEState *d = PCI_IDE(dev);
  108. PCIDevice *pd = PCI_DEVICE(dev);
  109. uint8_t *pci_conf = pd->config;
  110. int i;
  111. for (i = 0; i < 2; i++) {
  112. ide_bus_reset(&d->bus[i]);
  113. }
  114. pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_WAIT);
  115. pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_FAST_BACK |
  116. PCI_STATUS_DEVSEL_MEDIUM);
  117. pci_set_long(pci_conf + PCI_BASE_ADDRESS_0, 0x000001f0);
  118. pci_set_long(pci_conf + PCI_BASE_ADDRESS_1, 0x000003f4);
  119. pci_set_long(pci_conf + PCI_BASE_ADDRESS_2, 0x00000170);
  120. pci_set_long(pci_conf + PCI_BASE_ADDRESS_3, 0x00000374);
  121. pci_set_long(pci_conf + PCI_BASE_ADDRESS_4, 0x0000cc01); /* BMIBA: 20-23h */
  122. pci_set_long(pci_conf + PCI_INTERRUPT_LINE, 0x0000010e);
  123. /* IDE chip enable, IDE configuration 1/2, IDE FIFO Configuration*/
  124. pci_set_long(pci_conf + 0x40, 0x0a090600);
  125. /* IDE misc configuration 1/2/3 */
  126. pci_set_long(pci_conf + 0x44, 0x00c00068);
  127. /* IDE Timing control */
  128. pci_set_long(pci_conf + 0x48, 0xa8a8a8a8);
  129. /* IDE Address Setup Time */
  130. pci_set_long(pci_conf + 0x4c, 0x000000ff);
  131. /* UltraDMA Extended Timing Control*/
  132. pci_set_long(pci_conf + 0x50, 0x07070707);
  133. /* UltraDMA FIFO Control */
  134. pci_set_long(pci_conf + 0x54, 0x00000004);
  135. /* IDE primary sector size */
  136. pci_set_long(pci_conf + 0x60, 0x00000200);
  137. /* IDE secondary sector size */
  138. pci_set_long(pci_conf + 0x68, 0x00000200);
  139. /* PCI PM Block */
  140. pci_set_long(pci_conf + 0xc0, 0x00020001);
  141. }
  142. static void via_ide_realize(PCIDevice *dev, Error **errp)
  143. {
  144. PCIIDEState *d = PCI_IDE(dev);
  145. uint8_t *pci_conf = dev->config;
  146. int i;
  147. pci_config_set_prog_interface(pci_conf, 0x8f); /* native PCI ATA mode */
  148. pci_set_long(pci_conf + PCI_CAPABILITY_LIST, 0x000000c0);
  149. dev->wmask[PCI_INTERRUPT_LINE] = 0xf;
  150. memory_region_init_io(&d->data_bar[0], OBJECT(d), &pci_ide_data_le_ops,
  151. &d->bus[0], "via-ide0-data", 8);
  152. pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &d->data_bar[0]);
  153. memory_region_init_io(&d->cmd_bar[0], OBJECT(d), &pci_ide_cmd_le_ops,
  154. &d->bus[0], "via-ide0-cmd", 4);
  155. pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->cmd_bar[0]);
  156. memory_region_init_io(&d->data_bar[1], OBJECT(d), &pci_ide_data_le_ops,
  157. &d->bus[1], "via-ide1-data", 8);
  158. pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &d->data_bar[1]);
  159. memory_region_init_io(&d->cmd_bar[1], OBJECT(d), &pci_ide_cmd_le_ops,
  160. &d->bus[1], "via-ide1-cmd", 4);
  161. pci_register_bar(dev, 3, PCI_BASE_ADDRESS_SPACE_IO, &d->cmd_bar[1]);
  162. bmdma_setup_bar(d);
  163. pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &d->bmdma_bar);
  164. vmstate_register(DEVICE(dev), 0, &vmstate_ide_pci, d);
  165. for (i = 0; i < 2; i++) {
  166. ide_bus_new(&d->bus[i], sizeof(d->bus[i]), DEVICE(d), i, 2);
  167. ide_init2(&d->bus[i], qemu_allocate_irq(via_ide_set_irq, d, i));
  168. bmdma_init(&d->bus[i], &d->bmdma[i], d);
  169. d->bmdma[i].bus = &d->bus[i];
  170. ide_register_restart_cb(&d->bus[i]);
  171. }
  172. }
  173. static void via_ide_exitfn(PCIDevice *dev)
  174. {
  175. PCIIDEState *d = PCI_IDE(dev);
  176. unsigned i;
  177. for (i = 0; i < 2; ++i) {
  178. memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].extra_io);
  179. memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].addr_ioport);
  180. }
  181. }
  182. void via_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn)
  183. {
  184. PCIDevice *dev;
  185. dev = pci_create_simple(bus, devfn, "via-ide");
  186. pci_ide_create_devs(dev, hd_table);
  187. }
  188. static void via_ide_class_init(ObjectClass *klass, void *data)
  189. {
  190. DeviceClass *dc = DEVICE_CLASS(klass);
  191. PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
  192. dc->reset = via_ide_reset;
  193. k->realize = via_ide_realize;
  194. k->exit = via_ide_exitfn;
  195. k->vendor_id = PCI_VENDOR_ID_VIA;
  196. k->device_id = PCI_DEVICE_ID_VIA_IDE;
  197. k->revision = 0x06;
  198. k->class_id = PCI_CLASS_STORAGE_IDE;
  199. set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
  200. }
  201. static const TypeInfo via_ide_info = {
  202. .name = "via-ide",
  203. .parent = TYPE_PCI_IDE,
  204. .class_init = via_ide_class_init,
  205. };
  206. static void via_ide_register_types(void)
  207. {
  208. type_register_static(&via_ide_info);
  209. }
  210. type_init(via_ide_register_types)