via.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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. qemu_set_irq(isa_get_irq(NULL, 14 + n), level);
  100. }
  101. static void via_ide_reset(DeviceState *dev)
  102. {
  103. PCIIDEState *d = PCI_IDE(dev);
  104. PCIDevice *pd = PCI_DEVICE(dev);
  105. uint8_t *pci_conf = pd->config;
  106. int i;
  107. for (i = 0; i < 2; i++) {
  108. ide_bus_reset(&d->bus[i]);
  109. }
  110. pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_IO | PCI_COMMAND_WAIT);
  111. pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_FAST_BACK |
  112. PCI_STATUS_DEVSEL_MEDIUM);
  113. pci_set_long(pci_conf + PCI_BASE_ADDRESS_0, 0x000001f0);
  114. pci_set_long(pci_conf + PCI_BASE_ADDRESS_1, 0x000003f4);
  115. pci_set_long(pci_conf + PCI_BASE_ADDRESS_2, 0x00000170);
  116. pci_set_long(pci_conf + PCI_BASE_ADDRESS_3, 0x00000374);
  117. pci_set_long(pci_conf + PCI_BASE_ADDRESS_4, 0x0000cc01); /* BMIBA: 20-23h */
  118. pci_set_long(pci_conf + PCI_INTERRUPT_LINE, 0x0000010e);
  119. /* IDE chip enable, IDE configuration 1/2, IDE FIFO Configuration*/
  120. pci_set_long(pci_conf + 0x40, 0x0a090600);
  121. /* IDE misc configuration 1/2/3 */
  122. pci_set_long(pci_conf + 0x44, 0x00c00068);
  123. /* IDE Timing control */
  124. pci_set_long(pci_conf + 0x48, 0xa8a8a8a8);
  125. /* IDE Address Setup Time */
  126. pci_set_long(pci_conf + 0x4c, 0x000000ff);
  127. /* UltraDMA Extended Timing Control*/
  128. pci_set_long(pci_conf + 0x50, 0x07070707);
  129. /* UltraDMA FIFO Control */
  130. pci_set_long(pci_conf + 0x54, 0x00000004);
  131. /* IDE primary sector size */
  132. pci_set_long(pci_conf + 0x60, 0x00000200);
  133. /* IDE secondary sector size */
  134. pci_set_long(pci_conf + 0x68, 0x00000200);
  135. /* PCI PM Block */
  136. pci_set_long(pci_conf + 0xc0, 0x00020001);
  137. }
  138. static void via_ide_realize(PCIDevice *dev, Error **errp)
  139. {
  140. PCIIDEState *d = PCI_IDE(dev);
  141. DeviceState *ds = DEVICE(dev);
  142. uint8_t *pci_conf = dev->config;
  143. int i;
  144. pci_config_set_prog_interface(pci_conf, 0x8a); /* legacy mode */
  145. pci_set_long(pci_conf + PCI_CAPABILITY_LIST, 0x000000c0);
  146. dev->wmask[PCI_INTERRUPT_LINE] = 0;
  147. dev->wmask[PCI_CLASS_PROG] = 5;
  148. memory_region_init_io(&d->data_bar[0], OBJECT(d), &pci_ide_data_le_ops,
  149. &d->bus[0], "via-ide0-data", 8);
  150. pci_register_bar(dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &d->data_bar[0]);
  151. memory_region_init_io(&d->cmd_bar[0], OBJECT(d), &pci_ide_cmd_le_ops,
  152. &d->bus[0], "via-ide0-cmd", 4);
  153. pci_register_bar(dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &d->cmd_bar[0]);
  154. memory_region_init_io(&d->data_bar[1], OBJECT(d), &pci_ide_data_le_ops,
  155. &d->bus[1], "via-ide1-data", 8);
  156. pci_register_bar(dev, 2, PCI_BASE_ADDRESS_SPACE_IO, &d->data_bar[1]);
  157. memory_region_init_io(&d->cmd_bar[1], OBJECT(d), &pci_ide_cmd_le_ops,
  158. &d->bus[1], "via-ide1-cmd", 4);
  159. pci_register_bar(dev, 3, PCI_BASE_ADDRESS_SPACE_IO, &d->cmd_bar[1]);
  160. bmdma_setup_bar(d);
  161. pci_register_bar(dev, 4, PCI_BASE_ADDRESS_SPACE_IO, &d->bmdma_bar);
  162. qdev_init_gpio_in(ds, via_ide_set_irq, 2);
  163. for (i = 0; i < 2; i++) {
  164. ide_bus_new(&d->bus[i], sizeof(d->bus[i]), ds, i, 2);
  165. ide_init2(&d->bus[i], qdev_get_gpio_in(ds, i));
  166. bmdma_init(&d->bus[i], &d->bmdma[i], d);
  167. d->bmdma[i].bus = &d->bus[i];
  168. ide_register_restart_cb(&d->bus[i]);
  169. }
  170. }
  171. static void via_ide_exitfn(PCIDevice *dev)
  172. {
  173. PCIIDEState *d = PCI_IDE(dev);
  174. unsigned i;
  175. for (i = 0; i < 2; ++i) {
  176. memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].extra_io);
  177. memory_region_del_subregion(&d->bmdma_bar, &d->bmdma[i].addr_ioport);
  178. }
  179. }
  180. static void via_ide_class_init(ObjectClass *klass, void *data)
  181. {
  182. DeviceClass *dc = DEVICE_CLASS(klass);
  183. PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
  184. dc->reset = via_ide_reset;
  185. dc->vmsd = &vmstate_ide_pci;
  186. k->realize = via_ide_realize;
  187. k->exit = via_ide_exitfn;
  188. k->vendor_id = PCI_VENDOR_ID_VIA;
  189. k->device_id = PCI_DEVICE_ID_VIA_IDE;
  190. k->revision = 0x06;
  191. k->class_id = PCI_CLASS_STORAGE_IDE;
  192. set_bit(DEVICE_CATEGORY_STORAGE, dc->categories);
  193. }
  194. static const TypeInfo via_ide_info = {
  195. .name = "via-ide",
  196. .parent = TYPE_PCI_IDE,
  197. .class_init = via_ide_class_init,
  198. };
  199. static void via_ide_register_types(void)
  200. {
  201. type_register_static(&via_ide_info);
  202. }
  203. type_init(via_ide_register_types)