root / hw / ide / via.c @ 6bcb1a79
History | View | Annotate | Download (6.1 kB)
1 | 016512f3 | Huacai Chen | /*
|
---|---|---|---|
2 | 016512f3 | Huacai Chen | * QEMU IDE Emulation: PCI VIA82C686B support.
|
3 | 016512f3 | Huacai Chen | *
|
4 | 016512f3 | Huacai Chen | * Copyright (c) 2003 Fabrice Bellard
|
5 | 016512f3 | Huacai Chen | * Copyright (c) 2006 Openedhand Ltd.
|
6 | 016512f3 | Huacai Chen | * Copyright (c) 2010 Huacai Chen <zltjiangshi@gmail.com>
|
7 | 016512f3 | Huacai Chen | *
|
8 | 016512f3 | Huacai Chen | * Permission is hereby granted, free of charge, to any person obtaining a copy
|
9 | 016512f3 | Huacai Chen | * of this software and associated documentation files (the "Software"), to deal
|
10 | 016512f3 | Huacai Chen | * in the Software without restriction, including without limitation the rights
|
11 | 016512f3 | Huacai Chen | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
12 | 016512f3 | Huacai Chen | * copies of the Software, and to permit persons to whom the Software is
|
13 | 016512f3 | Huacai Chen | * furnished to do so, subject to the following conditions:
|
14 | 016512f3 | Huacai Chen | *
|
15 | 016512f3 | Huacai Chen | * The above copyright notice and this permission notice shall be included in
|
16 | 016512f3 | Huacai Chen | * all copies or substantial portions of the Software.
|
17 | 016512f3 | Huacai Chen | *
|
18 | 016512f3 | Huacai Chen | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
19 | 016512f3 | Huacai Chen | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
20 | 016512f3 | Huacai Chen | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
21 | 016512f3 | Huacai Chen | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
22 | 016512f3 | Huacai Chen | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
23 | 016512f3 | Huacai Chen | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
24 | 016512f3 | Huacai Chen | * THE SOFTWARE.
|
25 | 016512f3 | Huacai Chen | */
|
26 | 016512f3 | Huacai Chen | #include <hw/hw.h> |
27 | 016512f3 | Huacai Chen | #include <hw/pc.h> |
28 | 016512f3 | Huacai Chen | #include <hw/pci.h> |
29 | 016512f3 | Huacai Chen | #include <hw/isa.h> |
30 | 016512f3 | Huacai Chen | #include "block.h" |
31 | 016512f3 | Huacai Chen | #include "block_int.h" |
32 | 016512f3 | Huacai Chen | #include "sysemu.h" |
33 | 016512f3 | Huacai Chen | #include "dma.h" |
34 | 016512f3 | Huacai Chen | |
35 | 016512f3 | Huacai Chen | #include <hw/ide/pci.h> |
36 | 016512f3 | Huacai Chen | |
37 | 016512f3 | Huacai Chen | static uint32_t bmdma_readb(void *opaque, uint32_t addr) |
38 | 016512f3 | Huacai Chen | { |
39 | 016512f3 | Huacai Chen | BMDMAState *bm = opaque; |
40 | 016512f3 | Huacai Chen | uint32_t val; |
41 | 016512f3 | Huacai Chen | |
42 | 016512f3 | Huacai Chen | switch (addr & 3) { |
43 | 016512f3 | Huacai Chen | case 0: |
44 | 016512f3 | Huacai Chen | val = bm->cmd; |
45 | 016512f3 | Huacai Chen | break;
|
46 | 016512f3 | Huacai Chen | case 2: |
47 | 016512f3 | Huacai Chen | val = bm->status; |
48 | 016512f3 | Huacai Chen | break;
|
49 | 016512f3 | Huacai Chen | default:
|
50 | 016512f3 | Huacai Chen | val = 0xff;
|
51 | 016512f3 | Huacai Chen | break;
|
52 | 016512f3 | Huacai Chen | } |
53 | 016512f3 | Huacai Chen | #ifdef DEBUG_IDE
|
54 | 016512f3 | Huacai Chen | printf("bmdma: readb 0x%02x : 0x%02x\n", addr, val);
|
55 | 016512f3 | Huacai Chen | #endif
|
56 | 016512f3 | Huacai Chen | return val;
|
57 | 016512f3 | Huacai Chen | } |
58 | 016512f3 | Huacai Chen | |
59 | 016512f3 | Huacai Chen | static void bmdma_writeb(void *opaque, uint32_t addr, uint32_t val) |
60 | 016512f3 | Huacai Chen | { |
61 | 016512f3 | Huacai Chen | BMDMAState *bm = opaque; |
62 | 016512f3 | Huacai Chen | #ifdef DEBUG_IDE
|
63 | 016512f3 | Huacai Chen | printf("bmdma: writeb 0x%02x : 0x%02x\n", addr, val);
|
64 | 016512f3 | Huacai Chen | #endif
|
65 | 016512f3 | Huacai Chen | switch (addr & 3) { |
66 | 016512f3 | Huacai Chen | case 2: |
67 | 016512f3 | Huacai Chen | bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06); |
68 | 016512f3 | Huacai Chen | break;
|
69 | 016512f3 | Huacai Chen | default:;
|
70 | 016512f3 | Huacai Chen | } |
71 | 016512f3 | Huacai Chen | } |
72 | 016512f3 | Huacai Chen | |
73 | 016512f3 | Huacai Chen | static void bmdma_map(PCIDevice *pci_dev, int region_num, |
74 | 016512f3 | Huacai Chen | pcibus_t addr, pcibus_t size, int type)
|
75 | 016512f3 | Huacai Chen | { |
76 | 016512f3 | Huacai Chen | PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, pci_dev); |
77 | 016512f3 | Huacai Chen | int i;
|
78 | 016512f3 | Huacai Chen | |
79 | 016512f3 | Huacai Chen | for(i = 0;i < 2; i++) { |
80 | 016512f3 | Huacai Chen | BMDMAState *bm = &d->bmdma[i]; |
81 | 016512f3 | Huacai Chen | d->bus[i].bmdma = bm; |
82 | 016512f3 | Huacai Chen | bm->bus = d->bus+i; |
83 | 016512f3 | Huacai Chen | qemu_add_vm_change_state_handler(ide_dma_restart_cb, bm); |
84 | 016512f3 | Huacai Chen | |
85 | 016512f3 | Huacai Chen | register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm); |
86 | 016512f3 | Huacai Chen | |
87 | 016512f3 | Huacai Chen | register_ioport_write(addr + 1, 3, 1, bmdma_writeb, bm); |
88 | 016512f3 | Huacai Chen | register_ioport_read(addr, 4, 1, bmdma_readb, bm); |
89 | 016512f3 | Huacai Chen | |
90 | 016512f3 | Huacai Chen | register_ioport_write(addr + 4, 4, 1, bmdma_addr_writeb, bm); |
91 | 016512f3 | Huacai Chen | register_ioport_read(addr + 4, 4, 1, bmdma_addr_readb, bm); |
92 | 016512f3 | Huacai Chen | register_ioport_write(addr + 4, 4, 2, bmdma_addr_writew, bm); |
93 | 016512f3 | Huacai Chen | register_ioport_read(addr + 4, 4, 2, bmdma_addr_readw, bm); |
94 | 016512f3 | Huacai Chen | register_ioport_write(addr + 4, 4, 4, bmdma_addr_writel, bm); |
95 | 016512f3 | Huacai Chen | register_ioport_read(addr + 4, 4, 4, bmdma_addr_readl, bm); |
96 | 016512f3 | Huacai Chen | addr += 8;
|
97 | 016512f3 | Huacai Chen | } |
98 | 016512f3 | Huacai Chen | } |
99 | 016512f3 | Huacai Chen | |
100 | 016512f3 | Huacai Chen | static void via_reset(void *opaque) |
101 | 016512f3 | Huacai Chen | { |
102 | 016512f3 | Huacai Chen | PCIIDEState *d = opaque; |
103 | 016512f3 | Huacai Chen | uint8_t *pci_conf = d->dev.config; |
104 | 016512f3 | Huacai Chen | int i;
|
105 | 016512f3 | Huacai Chen | |
106 | 016512f3 | Huacai Chen | for (i = 0; i < 2; i++) { |
107 | 016512f3 | Huacai Chen | ide_bus_reset(&d->bus[i]); |
108 | 016512f3 | Huacai Chen | ide_dma_reset(&d->bmdma[i]); |
109 | 016512f3 | Huacai Chen | } |
110 | 016512f3 | Huacai Chen | |
111 | 016512f3 | Huacai Chen | pci_set_word(pci_conf + PCI_COMMAND, PCI_COMMAND_WAIT); |
112 | 016512f3 | Huacai Chen | pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_FAST_BACK | |
113 | 016512f3 | Huacai Chen | PCI_STATUS_DEVSEL_MEDIUM); |
114 | 016512f3 | Huacai Chen | |
115 | 016512f3 | Huacai Chen | pci_set_long(pci_conf + PCI_BASE_ADDRESS_0, 0x000001f0);
|
116 | 016512f3 | Huacai Chen | pci_set_long(pci_conf + PCI_BASE_ADDRESS_1, 0x000003f4);
|
117 | 016512f3 | Huacai Chen | pci_set_long(pci_conf + PCI_BASE_ADDRESS_2, 0x00000170);
|
118 | 016512f3 | Huacai Chen | pci_set_long(pci_conf + PCI_BASE_ADDRESS_3, 0x00000374);
|
119 | 016512f3 | Huacai Chen | pci_set_long(pci_conf + PCI_BASE_ADDRESS_4, 0x0000cc01); /* BMIBA: 20-23h */ |
120 | 016512f3 | Huacai Chen | pci_set_long(pci_conf + PCI_INTERRUPT_LINE, 0x0000010e);
|
121 | 016512f3 | Huacai Chen | |
122 | 016512f3 | Huacai Chen | /* IDE chip enable, IDE configuration 1/2, IDE FIFO Configuration*/
|
123 | 016512f3 | Huacai Chen | pci_set_long(pci_conf + 0x40, 0x0a090600); |
124 | 016512f3 | Huacai Chen | /* IDE misc configuration 1/2/3 */
|
125 | 016512f3 | Huacai Chen | pci_set_long(pci_conf + 0x44, 0x00c00068); |
126 | 016512f3 | Huacai Chen | /* IDE Timing control */
|
127 | 016512f3 | Huacai Chen | pci_set_long(pci_conf + 0x48, 0xa8a8a8a8); |
128 | 016512f3 | Huacai Chen | /* IDE Address Setup Time */
|
129 | 016512f3 | Huacai Chen | pci_set_long(pci_conf + 0x4c, 0x000000ff); |
130 | 016512f3 | Huacai Chen | /* UltraDMA Extended Timing Control*/
|
131 | 016512f3 | Huacai Chen | pci_set_long(pci_conf + 0x50, 0x07070707); |
132 | 016512f3 | Huacai Chen | /* UltraDMA FIFO Control */
|
133 | 016512f3 | Huacai Chen | pci_set_long(pci_conf + 0x54, 0x00000004); |
134 | 016512f3 | Huacai Chen | /* IDE primary sector size */
|
135 | 016512f3 | Huacai Chen | pci_set_long(pci_conf + 0x60, 0x00000200); |
136 | 016512f3 | Huacai Chen | /* IDE secondary sector size */
|
137 | 016512f3 | Huacai Chen | pci_set_long(pci_conf + 0x68, 0x00000200); |
138 | 016512f3 | Huacai Chen | /* PCI PM Block */
|
139 | 016512f3 | Huacai Chen | pci_set_long(pci_conf + 0xc0, 0x00020001); |
140 | 016512f3 | Huacai Chen | } |
141 | 016512f3 | Huacai Chen | |
142 | 016512f3 | Huacai Chen | /* via ide func */
|
143 | 016512f3 | Huacai Chen | static int vt82c686b_ide_initfn(PCIDevice *dev) |
144 | 016512f3 | Huacai Chen | { |
145 | 016512f3 | Huacai Chen | PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev);; |
146 | 016512f3 | Huacai Chen | uint8_t *pci_conf = d->dev.config; |
147 | 016512f3 | Huacai Chen | |
148 | 016512f3 | Huacai Chen | pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_VIA); |
149 | 016512f3 | Huacai Chen | pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_VIA_IDE); |
150 | 016512f3 | Huacai Chen | pci_config_set_class(pci_conf, PCI_CLASS_STORAGE_IDE); |
151 | 016512f3 | Huacai Chen | pci_config_set_prog_interface(pci_conf, 0x8a); /* legacy ATA mode */ |
152 | 016512f3 | Huacai Chen | pci_config_set_revision(pci_conf,0x06); /* Revision 0.6 */ |
153 | 016512f3 | Huacai Chen | pci_set_long(pci_conf + PCI_CAPABILITY_LIST, 0x000000c0);
|
154 | 016512f3 | Huacai Chen | |
155 | 016512f3 | Huacai Chen | qemu_register_reset(via_reset, d); |
156 | 016512f3 | Huacai Chen | pci_register_bar((PCIDevice *)d, 4, 0x10, |
157 | 016512f3 | Huacai Chen | PCI_BASE_ADDRESS_SPACE_IO, bmdma_map); |
158 | 016512f3 | Huacai Chen | |
159 | 1724f049 | Alex Williamson | vmstate_register(&dev->qdev, 0, &vmstate_ide_pci, d);
|
160 | 016512f3 | Huacai Chen | |
161 | 016512f3 | Huacai Chen | ide_bus_new(&d->bus[0], &d->dev.qdev);
|
162 | 016512f3 | Huacai Chen | ide_bus_new(&d->bus[1], &d->dev.qdev);
|
163 | 016512f3 | Huacai Chen | ide_init2(&d->bus[0], isa_reserve_irq(14)); |
164 | 016512f3 | Huacai Chen | ide_init2(&d->bus[1], isa_reserve_irq(15)); |
165 | 016512f3 | Huacai Chen | ide_init_ioport(&d->bus[0], 0x1f0, 0x3f6); |
166 | 016512f3 | Huacai Chen | ide_init_ioport(&d->bus[1], 0x170, 0x376); |
167 | 016512f3 | Huacai Chen | |
168 | 016512f3 | Huacai Chen | return 0; |
169 | 016512f3 | Huacai Chen | } |
170 | 016512f3 | Huacai Chen | |
171 | 016512f3 | Huacai Chen | void vt82c686b_ide_init(PCIBus *bus, DriveInfo **hd_table, int devfn) |
172 | 016512f3 | Huacai Chen | { |
173 | 016512f3 | Huacai Chen | PCIDevice *dev; |
174 | 016512f3 | Huacai Chen | |
175 | 016512f3 | Huacai Chen | dev = pci_create_simple(bus, devfn, "via-ide");
|
176 | 016512f3 | Huacai Chen | pci_ide_create_devs(dev, hd_table); |
177 | 016512f3 | Huacai Chen | } |
178 | 016512f3 | Huacai Chen | |
179 | 016512f3 | Huacai Chen | static PCIDeviceInfo via_ide_info = {
|
180 | 016512f3 | Huacai Chen | .qdev.name = "via-ide",
|
181 | 016512f3 | Huacai Chen | .qdev.size = sizeof(PCIIDEState),
|
182 | 016512f3 | Huacai Chen | .qdev.no_user = 1,
|
183 | 016512f3 | Huacai Chen | .init = vt82c686b_ide_initfn, |
184 | 016512f3 | Huacai Chen | }; |
185 | 016512f3 | Huacai Chen | |
186 | 016512f3 | Huacai Chen | static void via_ide_register(void) |
187 | 016512f3 | Huacai Chen | { |
188 | 016512f3 | Huacai Chen | pci_qdev_register(&via_ide_info); |
189 | 016512f3 | Huacai Chen | } |
190 | 016512f3 | Huacai Chen | device_init(via_ide_register); |