]>
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 | ||
407a4f30 JQ |
124 | static const VMStateDescription vmstate_bmdma = { |
125 | .name = "ide bmdma", | |
126 | .version_id = 3, | |
127 | .minimum_version_id = 0, | |
128 | .minimum_version_id_old = 0, | |
129 | .fields = (VMStateField []) { | |
130 | VMSTATE_UINT8(cmd, BMDMAState), | |
131 | VMSTATE_UINT8(status, BMDMAState), | |
132 | VMSTATE_UINT32(addr, BMDMAState), | |
133 | VMSTATE_INT64(sector_num, BMDMAState), | |
134 | VMSTATE_UINT32(nsector, BMDMAState), | |
135 | VMSTATE_UINT8(unit, BMDMAState), | |
136 | VMSTATE_END_OF_LIST() | |
977e1244 | 137 | } |
407a4f30 | 138 | }; |
977e1244 | 139 | |
407a4f30 | 140 | static int ide_pci_post_load(void *opaque, int version_id) |
977e1244 GH |
141 | { |
142 | PCIIDEState *d = opaque; | |
407a4f30 | 143 | int i; |
977e1244 | 144 | |
977e1244 | 145 | for(i = 0; i < 2; i++) { |
407a4f30 JQ |
146 | /* current versions always store 0/1, but older version |
147 | stored bigger values. We only need last bit */ | |
148 | d->bmdma[i].unit &= 1; | |
977e1244 GH |
149 | } |
150 | return 0; | |
151 | } | |
152 | ||
407a4f30 JQ |
153 | const VMStateDescription vmstate_ide_pci = { |
154 | .name = "ide", | |
155 | .version_id = 3, | |
156 | .minimum_version_id = 0, | |
157 | .minimum_version_id_old = 0, | |
158 | .post_load = ide_pci_post_load, | |
159 | .fields = (VMStateField []) { | |
160 | VMSTATE_PCI_DEVICE(dev, PCIIDEState), | |
161 | VMSTATE_STRUCT_ARRAY(bmdma, PCIIDEState, 2, 0, | |
162 | vmstate_bmdma, BMDMAState), | |
163 | VMSTATE_IDE_BUS_ARRAY(bus, PCIIDEState, 2), | |
164 | VMSTATE_IDE_DRIVES(bus[0].ifs, PCIIDEState), | |
165 | VMSTATE_IDE_DRIVES(bus[1].ifs, PCIIDEState), | |
166 | VMSTATE_END_OF_LIST() | |
167 | } | |
168 | }; | |
169 | ||
3e7e1558 | 170 | void pci_ide_create_devs(PCIDevice *dev, DriveInfo **hd_table) |
feef3102 GH |
171 | { |
172 | PCIIDEState *d = DO_UPCAST(PCIIDEState, dev, dev); | |
173 | static const int bus[4] = { 0, 0, 1, 1 }; | |
174 | static const int unit[4] = { 0, 1, 0, 1 }; | |
175 | int i; | |
176 | ||
177 | for (i = 0; i < 4; i++) { | |
178 | if (hd_table[i] == NULL) | |
179 | continue; | |
1f850f10 | 180 | ide_create_drive(d->bus+bus[i], unit[i], hd_table[i]); |
feef3102 GH |
181 | } |
182 | } |