]>
Commit | Line | Data |
---|---|---|
977e1244 GH |
1 | /* |
2 | * QEMU IDE Emulation: PCI Bus support. | |
3 | * | |
4 | * Copyright (c) 2003 Fabrice Bellard | |
5 | * Copyright (c) 2006 Openedhand Ltd. | |
6 | * | |
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
8 | * of this software and associated documentation files (the "Software"), to deal | |
9 | * in the Software without restriction, including without limitation the rights | |
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
11 | * copies of the Software, and to permit persons to whom the Software is | |
12 | * furnished to do so, subject to the following conditions: | |
13 | * | |
14 | * The above copyright notice and this permission notice shall be included in | |
15 | * all copies or substantial portions of the Software. | |
16 | * | |
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
23 | * THE SOFTWARE. | |
24 | */ | |
59f2a787 GH |
25 | #include <hw/hw.h> |
26 | #include <hw/pc.h> | |
27 | #include <hw/pci.h> | |
feef3102 | 28 | #include <hw/isa.h> |
977e1244 GH |
29 | #include "block.h" |
30 | #include "block_int.h" | |
31 | #include "sysemu.h" | |
32 | #include "dma.h" | |
59f2a787 | 33 | |
65c0f135 | 34 | #include <hw/ide/pci.h> |
977e1244 | 35 | |
3e7e1558 | 36 | void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val) |
977e1244 GH |
37 | { |
38 | BMDMAState *bm = opaque; | |
39 | #ifdef DEBUG_IDE | |
40 | printf("%s: 0x%08x\n", __func__, val); | |
41 | #endif | |
42 | if (!(val & BM_CMD_START)) { | |
43 | /* XXX: do it better */ | |
44 | ide_dma_cancel(bm); | |
45 | bm->cmd = val & 0x09; | |
46 | } else { | |
47 | if (!(bm->status & BM_STATUS_DMAING)) { | |
48 | bm->status |= BM_STATUS_DMAING; | |
49 | /* start dma transfer if possible */ | |
50 | if (bm->dma_cb) | |
51 | bm->dma_cb(bm, 0); | |
52 | } | |
53 | bm->cmd = val & 0x09; | |
54 | } | |
55 | } | |
56 | ||
3e7e1558 | 57 | uint32_t bmdma_addr_readb(void *opaque, uint32_t addr) |
977e1244 GH |
58 | { |
59 | BMDMAState *bm = opaque; | |
60 | uint32_t val; | |
61 | val = (bm->addr >> ((addr & 3) * 8)) & 0xff; | |
62 | #ifdef DEBUG_IDE | |
63 | printf("%s: 0x%08x\n", __func__, val); | |
64 | #endif | |
65 | return val; | |
66 | } | |
67 | ||
3e7e1558 | 68 | void bmdma_addr_writeb(void *opaque, uint32_t addr, uint32_t val) |
977e1244 GH |
69 | { |
70 | BMDMAState *bm = opaque; | |
71 | int shift = (addr & 3) * 8; | |
72 | #ifdef DEBUG_IDE | |
73 | printf("%s: 0x%08x\n", __func__, val); | |
74 | #endif | |
75 | bm->addr &= ~(0xFF << shift); | |
76 | bm->addr |= ((val & 0xFF) << shift) & ~3; | |
77 | bm->cur_addr = bm->addr; | |
78 | } | |
79 | ||
3e7e1558 | 80 | uint32_t bmdma_addr_readw(void *opaque, uint32_t addr) |
977e1244 GH |
81 | { |
82 | BMDMAState *bm = opaque; | |
83 | uint32_t val; | |
84 | val = (bm->addr >> ((addr & 3) * 8)) & 0xffff; | |
85 | #ifdef DEBUG_IDE | |
86 | printf("%s: 0x%08x\n", __func__, val); | |
87 | #endif | |
88 | return val; | |
89 | } | |
90 | ||
3e7e1558 | 91 | void bmdma_addr_writew(void *opaque, uint32_t addr, uint32_t val) |
977e1244 GH |
92 | { |
93 | BMDMAState *bm = opaque; | |
94 | int shift = (addr & 3) * 8; | |
95 | #ifdef DEBUG_IDE | |
96 | printf("%s: 0x%08x\n", __func__, val); | |
97 | #endif | |
98 | bm->addr &= ~(0xFFFF << shift); | |
99 | bm->addr |= ((val & 0xFFFF) << shift) & ~3; | |
100 | bm->cur_addr = bm->addr; | |
101 | } | |
102 | ||
3e7e1558 | 103 | uint32_t bmdma_addr_readl(void *opaque, uint32_t addr) |
977e1244 GH |
104 | { |
105 | BMDMAState *bm = opaque; | |
106 | uint32_t val; | |
107 | val = bm->addr; | |
108 | #ifdef DEBUG_IDE | |
109 | printf("%s: 0x%08x\n", __func__, val); | |
110 | #endif | |
111 | return val; | |
112 | } | |
113 | ||
3e7e1558 | 114 | void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val) |
977e1244 GH |
115 | { |
116 | BMDMAState *bm = opaque; | |
117 | #ifdef DEBUG_IDE | |
118 | printf("%s: 0x%08x\n", __func__, val); | |
119 | #endif | |
120 | bm->addr = val & ~3; | |
121 | bm->cur_addr = bm->addr; | |
122 | } | |
123 | ||
5ee84c33 JQ |
124 | static bool ide_bmdma_current_needed(void *opaque) |
125 | { | |
126 | BMDMAState *bm = opaque; | |
127 | ||
128 | return (bm->cur_prd_len != 0); | |
129 | } | |
130 | ||
131 | static const VMStateDescription vmstate_bmdma_current = { | |
132 | .name = "ide bmdma_current", | |
133 | .version_id = 1, | |
134 | .minimum_version_id = 1, | |
135 | .minimum_version_id_old = 1, | |
136 | .fields = (VMStateField []) { | |
137 | VMSTATE_UINT32(cur_addr, BMDMAState), | |
138 | VMSTATE_UINT32(cur_prd_last, BMDMAState), | |
139 | VMSTATE_UINT32(cur_prd_addr, BMDMAState), | |
140 | VMSTATE_UINT32(cur_prd_len, BMDMAState), | |
141 | VMSTATE_END_OF_LIST() | |
142 | } | |
143 | }; | |
144 | ||
145 | ||
407a4f30 JQ |
146 | static const VMStateDescription vmstate_bmdma = { |
147 | .name = "ide bmdma", | |
57338424 | 148 | .version_id = 3, |
407a4f30 JQ |
149 | .minimum_version_id = 0, |
150 | .minimum_version_id_old = 0, | |
151 | .fields = (VMStateField []) { | |
152 | VMSTATE_UINT8(cmd, BMDMAState), | |
153 | VMSTATE_UINT8(status, BMDMAState), | |
154 | VMSTATE_UINT32(addr, BMDMAState), | |
155 | VMSTATE_INT64(sector_num, BMDMAState), | |
156 | VMSTATE_UINT32(nsector, BMDMAState), | |
157 | VMSTATE_UINT8(unit, BMDMAState), | |
158 | VMSTATE_END_OF_LIST() | |
5ee84c33 JQ |
159 | }, |
160 | .subsections = (VMStateSubsection []) { | |
161 | { | |
162 | .vmsd = &vmstate_bmdma_current, | |
163 | .needed = ide_bmdma_current_needed, | |
164 | }, { | |
165 | /* empty */ | |
166 | } | |
977e1244 | 167 | } |
407a4f30 | 168 | }; |
977e1244 | 169 | |
407a4f30 | 170 | static int ide_pci_post_load(void *opaque, int version_id) |
977e1244 GH |
171 | { |
172 | PCIIDEState *d = opaque; | |
407a4f30 | 173 | int i; |
977e1244 | 174 | |
977e1244 | 175 | for(i = 0; i < 2; i++) { |
407a4f30 JQ |
176 | /* current versions always store 0/1, but older version |
177 | stored bigger values. We only need last bit */ | |
178 | d->bmdma[i].unit &= 1; | |
977e1244 GH |
179 | } |
180 | return 0; | |
181 | } | |
182 | ||
407a4f30 JQ |
183 | const VMStateDescription vmstate_ide_pci = { |
184 | .name = "ide", | |
57338424 | 185 | .version_id = 3, |
407a4f30 JQ |
186 | .minimum_version_id = 0, |
187 | .minimum_version_id_old = 0, | |
188 | .post_load = ide_pci_post_load, | |
189 | .fields = (VMStateField []) { | |
190 | VMSTATE_PCI_DEVICE(dev, PCIIDEState), | |
191 | VMSTATE_STRUCT_ARRAY(bmdma, PCIIDEState, 2, 0, | |
192 | vmstate_bmdma, BMDMAState), | |
193 | VMSTATE_IDE_BUS_ARRAY(bus, PCIIDEState, 2), | |
194 | VMSTATE_IDE_DRIVES(bus[0].ifs, PCIIDEState), | |
195 | VMSTATE_IDE_DRIVES(bus[1].ifs, PCIIDEState), | |
196 | VMSTATE_END_OF_LIST() | |
197 | } | |
198 | }; | |
199 | ||
3e7e1558 | 200 | void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table) |
feef3102 GH |
201 | { |
202 | PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev); | |
203 | static const int bus[4] = { 0, 0, 1, 1 }; | |
204 | static const int unit[4] = { 0, 1, 0, 1 }; | |
205 | int i; | |
206 | ||
207 | for (i = 0; i < 4; i++) { | |
208 | if (hd_table[i] == NULL) | |
209 | continue; | |
1f850f10 | 210 | ide_create_drive(d->bus+bus[i], unit[i], hd_table[i]); |
feef3102 GH |
211 | } |
212 | } |