]>
Commit | Line | Data |
---|---|---|
b8842209 GH |
1 | /* |
2 | * QEMU IDE Emulation: MacIO 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 | */ | |
baec1910 AF |
25 | #include "hw/hw.h" |
26 | #include "hw/ppc/mac.h" | |
0d09e41a | 27 | #include "hw/ppc/mac_dbdma.h" |
4be74634 | 28 | #include "sysemu/block-backend.h" |
9c17d615 | 29 | #include "sysemu/dma.h" |
59f2a787 GH |
30 | |
31 | #include <hw/ide/internal.h> | |
b8842209 | 32 | |
33ce36bb AG |
33 | /* debug MACIO */ |
34 | // #define DEBUG_MACIO | |
35 | ||
36 | #ifdef DEBUG_MACIO | |
37 | static const int debug_macio = 1; | |
38 | #else | |
39 | static const int debug_macio = 0; | |
40 | #endif | |
41 | ||
42 | #define MACIO_DPRINTF(fmt, ...) do { \ | |
43 | if (debug_macio) { \ | |
44 | printf(fmt , ## __VA_ARGS__); \ | |
45 | } \ | |
46 | } while (0) | |
47 | ||
48 | ||
b8842209 GH |
49 | /***********************************************************/ |
50 | /* MacIO based PowerPC IDE */ | |
51 | ||
02c7c992 BS |
52 | #define MACIO_PAGE_SIZE 4096 |
53 | ||
b01d44cd MCA |
54 | /* |
55 | * Unaligned DMA read/write access functions required for OS X/Darwin which | |
56 | * don't perform DMA transactions on sector boundaries. These functions are | |
57 | * modelled on bdrv_co_do_preadv()/bdrv_co_do_pwritev() and so should be | |
58 | * easy to remove if the unaligned block APIs are ever exposed. | |
59 | */ | |
60 | ||
4827ac1e | 61 | static void pmac_dma_read(BlockBackend *blk, |
0389b8f8 | 62 | int64_t offset, unsigned int bytes, |
4827ac1e | 63 | void (*cb)(void *opaque, int ret), void *opaque) |
b8842209 GH |
64 | { |
65 | DBDMA_io *io = opaque; | |
66 | MACIOIDEState *m = io->opaque; | |
67 | IDEState *s = idebus_active_if(&m->bus); | |
4827ac1e MCA |
68 | dma_addr_t dma_addr, dma_len; |
69 | void *mem; | |
0389b8f8 MCA |
70 | int64_t sector_num; |
71 | int nsector; | |
72 | uint64_t align = BDRV_SECTOR_SIZE; | |
73 | size_t head_bytes, tail_bytes; | |
b8842209 | 74 | |
4827ac1e MCA |
75 | qemu_iovec_destroy(&io->iov); |
76 | qemu_iovec_init(&io->iov, io->len / MACIO_PAGE_SIZE + 1); | |
77 | ||
0389b8f8 MCA |
78 | sector_num = (offset >> 9); |
79 | nsector = (io->len >> 9); | |
4827ac1e | 80 | |
0389b8f8 MCA |
81 | MACIO_DPRINTF("--- DMA read transfer (0x%" HWADDR_PRIx ",0x%x): " |
82 | "sector_num: %" PRId64 ", nsector: %d\n", io->addr, io->len, | |
83 | sector_num, nsector); | |
4827ac1e | 84 | |
0389b8f8 MCA |
85 | dma_addr = io->addr; |
86 | dma_len = io->len; | |
87 | mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len, | |
88 | DMA_DIRECTION_FROM_DEVICE); | |
4827ac1e | 89 | |
0389b8f8 MCA |
90 | if (offset & (align - 1)) { |
91 | head_bytes = offset & (align - 1); | |
4827ac1e | 92 | |
0389b8f8 MCA |
93 | MACIO_DPRINTF("--- DMA unaligned head: sector %" PRId64 ", " |
94 | "discarding %zu bytes\n", sector_num, head_bytes); | |
4827ac1e | 95 | |
ac58fe7b | 96 | qemu_iovec_add(&io->iov, &io->head_remainder, head_bytes); |
4827ac1e | 97 | |
0389b8f8 MCA |
98 | bytes += offset & (align - 1); |
99 | offset = offset & ~(align - 1); | |
b8842209 GH |
100 | } |
101 | ||
0389b8f8 | 102 | qemu_iovec_add(&io->iov, mem, io->len); |
cae32357 | 103 | |
0389b8f8 MCA |
104 | if ((offset + bytes) & (align - 1)) { |
105 | tail_bytes = (offset + bytes) & (align - 1); | |
33ce36bb | 106 | |
0389b8f8 MCA |
107 | MACIO_DPRINTF("--- DMA unaligned tail: sector %" PRId64 ", " |
108 | "discarding bytes %zu\n", sector_num, tail_bytes); | |
4827ac1e | 109 | |
ac58fe7b | 110 | qemu_iovec_add(&io->iov, &io->tail_remainder, align - tail_bytes); |
0389b8f8 | 111 | bytes = ROUND_UP(bytes, align); |
b8842209 GH |
112 | } |
113 | ||
4827ac1e MCA |
114 | s->io_buffer_size -= io->len; |
115 | s->io_buffer_index += io->len; | |
80fc95d8 | 116 | |
4827ac1e | 117 | io->len = 0; |
80fc95d8 | 118 | |
0389b8f8 MCA |
119 | MACIO_DPRINTF("--- Block read transfer - sector_num: %" PRIx64 " " |
120 | "nsector: %x\n", (offset >> 9), (bytes >> 9)); | |
80fc95d8 | 121 | |
0389b8f8 MCA |
122 | m->aiocb = blk_aio_readv(blk, (offset >> 9), &io->iov, (bytes >> 9), |
123 | cb, io); | |
4827ac1e | 124 | } |
80fc95d8 | 125 | |
bd4214fc | 126 | static void pmac_dma_write(BlockBackend *blk, |
ac58fe7b | 127 | int64_t offset, int bytes, |
bd4214fc MCA |
128 | void (*cb)(void *opaque, int ret), void *opaque) |
129 | { | |
130 | DBDMA_io *io = opaque; | |
131 | MACIOIDEState *m = io->opaque; | |
132 | IDEState *s = idebus_active_if(&m->bus); | |
133 | dma_addr_t dma_addr, dma_len; | |
134 | void *mem; | |
ac58fe7b MCA |
135 | int64_t sector_num; |
136 | int nsector; | |
137 | uint64_t align = BDRV_SECTOR_SIZE; | |
138 | size_t head_bytes, tail_bytes; | |
139 | bool unaligned_head = false, unaligned_tail = false; | |
bd4214fc MCA |
140 | |
141 | qemu_iovec_destroy(&io->iov); | |
142 | qemu_iovec_init(&io->iov, io->len / MACIO_PAGE_SIZE + 1); | |
143 | ||
ac58fe7b MCA |
144 | sector_num = (offset >> 9); |
145 | nsector = (io->len >> 9); | |
bd4214fc | 146 | |
ac58fe7b MCA |
147 | MACIO_DPRINTF("--- DMA write transfer (0x%" HWADDR_PRIx ",0x%x): " |
148 | "sector_num: %" PRId64 ", nsector: %d\n", io->addr, io->len, | |
149 | sector_num, nsector); | |
bd4214fc | 150 | |
ac58fe7b MCA |
151 | dma_addr = io->addr; |
152 | dma_len = io->len; | |
153 | mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len, | |
154 | DMA_DIRECTION_TO_DEVICE); | |
bd4214fc | 155 | |
ac58fe7b MCA |
156 | if (offset & (align - 1)) { |
157 | head_bytes = offset & (align - 1); | |
158 | sector_num = ((offset & ~(align - 1)) >> 9); | |
bd4214fc | 159 | |
ac58fe7b MCA |
160 | MACIO_DPRINTF("--- DMA unaligned head: pre-reading head sector %" |
161 | PRId64 "\n", sector_num); | |
bd4214fc | 162 | |
ac58fe7b | 163 | blk_pread(s->blk, (sector_num << 9), &io->head_remainder, align); |
bd4214fc | 164 | |
ac58fe7b MCA |
165 | qemu_iovec_add(&io->iov, &io->head_remainder, head_bytes); |
166 | qemu_iovec_add(&io->iov, mem, io->len); | |
bd4214fc | 167 | |
ac58fe7b MCA |
168 | bytes += offset & (align - 1); |
169 | offset = offset & ~(align - 1); | |
170 | ||
171 | unaligned_head = true; | |
bd4214fc MCA |
172 | } |
173 | ||
ac58fe7b MCA |
174 | if ((offset + bytes) & (align - 1)) { |
175 | tail_bytes = (offset + bytes) & (align - 1); | |
176 | sector_num = (((offset + bytes) & ~(align - 1)) >> 9); | |
bd4214fc | 177 | |
ac58fe7b MCA |
178 | MACIO_DPRINTF("--- DMA unaligned tail: pre-reading tail sector %" |
179 | PRId64 "\n", sector_num); | |
bd4214fc | 180 | |
ac58fe7b | 181 | blk_pread(s->blk, (sector_num << 9), &io->tail_remainder, align); |
bd4214fc | 182 | |
ac58fe7b MCA |
183 | if (!unaligned_head) { |
184 | qemu_iovec_add(&io->iov, mem, io->len); | |
185 | } | |
bd4214fc | 186 | |
ac58fe7b MCA |
187 | qemu_iovec_add(&io->iov, &io->tail_remainder + tail_bytes, |
188 | align - tail_bytes); | |
bd4214fc | 189 | |
ac58fe7b | 190 | bytes = ROUND_UP(bytes, align); |
bd4214fc | 191 | |
ac58fe7b | 192 | unaligned_tail = true; |
bd4214fc MCA |
193 | } |
194 | ||
ac58fe7b MCA |
195 | if (!unaligned_head && !unaligned_tail) { |
196 | qemu_iovec_add(&io->iov, mem, io->len); | |
197 | } | |
198 | ||
199 | s->io_buffer_size -= io->len; | |
200 | s->io_buffer_index += io->len; | |
bd4214fc MCA |
201 | |
202 | io->len = 0; | |
203 | ||
ac58fe7b MCA |
204 | MACIO_DPRINTF("--- Block write transfer - sector_num: %" PRIx64 " " |
205 | "nsector: %x\n", (offset >> 9), (bytes >> 9)); | |
bd4214fc | 206 | |
ac58fe7b MCA |
207 | m->aiocb = blk_aio_writev(blk, (offset >> 9), &io->iov, (bytes >> 9), |
208 | cb, io); | |
bd4214fc MCA |
209 | } |
210 | ||
4827ac1e MCA |
211 | static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) |
212 | { | |
213 | DBDMA_io *io = opaque; | |
214 | MACIOIDEState *m = io->opaque; | |
215 | IDEState *s = idebus_active_if(&m->bus); | |
0389b8f8 | 216 | int64_t offset; |
4827ac1e | 217 | |
b01d44cd | 218 | MACIO_DPRINTF("pmac_ide_atapi_transfer_cb\n"); |
4827ac1e MCA |
219 | |
220 | if (ret < 0) { | |
b01d44cd | 221 | MACIO_DPRINTF("DMA error: %d\n", ret); |
4827ac1e MCA |
222 | ide_atapi_io_error(s, ret); |
223 | goto done; | |
224 | } | |
225 | ||
226 | if (!m->dma_active) { | |
227 | MACIO_DPRINTF("waiting for data (%#x - %#x - %x)\n", | |
228 | s->nsector, io->len, s->status); | |
229 | /* data not ready yet, wait for the channel to get restarted */ | |
230 | io->processing = false; | |
80fc95d8 AG |
231 | return; |
232 | } | |
233 | ||
4827ac1e | 234 | if (s->io_buffer_size <= 0) { |
b01d44cd | 235 | MACIO_DPRINTF("End of IDE transfer\n"); |
b8842209 | 236 | ide_atapi_cmd_ok(s); |
cae32357 | 237 | m->dma_active = false; |
4827ac1e | 238 | goto done; |
33ce36bb | 239 | } |
b8842209 GH |
240 | |
241 | if (io->len == 0) { | |
4827ac1e | 242 | MACIO_DPRINTF("End of DMA transfer\n"); |
a597e79c | 243 | goto done; |
b8842209 GH |
244 | } |
245 | ||
4827ac1e MCA |
246 | if (s->lba == -1) { |
247 | /* Non-block ATAPI transfer - just copy to RAM */ | |
248 | s->io_buffer_size = MIN(s->io_buffer_size, io->len); | |
249 | cpu_physical_memory_write(io->addr, s->io_buffer, s->io_buffer_size); | |
250 | ide_atapi_cmd_ok(s); | |
251 | m->dma_active = false; | |
252 | goto done; | |
80fc95d8 AG |
253 | } |
254 | ||
0389b8f8 MCA |
255 | /* Calculate current offset */ |
256 | offset = (int64_t)(s->lba << 11) + s->io_buffer_index; | |
257 | ||
0389b8f8 | 258 | pmac_dma_read(s->blk, offset, io->len, pmac_ide_atapi_transfer_cb, io); |
a597e79c CH |
259 | return; |
260 | ||
261 | done: | |
4be74634 | 262 | block_acct_done(blk_get_stats(s->blk), &s->acct); |
a597e79c | 263 | io->dma_end(opaque); |
4827ac1e MCA |
264 | |
265 | return; | |
b8842209 GH |
266 | } |
267 | ||
268 | static void pmac_ide_transfer_cb(void *opaque, int ret) | |
269 | { | |
270 | DBDMA_io *io = opaque; | |
271 | MACIOIDEState *m = io->opaque; | |
272 | IDEState *s = idebus_active_if(&m->bus); | |
0389b8f8 | 273 | int64_t offset; |
bd4214fc MCA |
274 | |
275 | MACIO_DPRINTF("pmac_ide_transfer_cb\n"); | |
b8842209 GH |
276 | |
277 | if (ret < 0) { | |
b01d44cd | 278 | MACIO_DPRINTF("DMA error: %d\n", ret); |
b8842209 | 279 | m->aiocb = NULL; |
8aef291f | 280 | ide_dma_error(s); |
a597e79c | 281 | goto done; |
b8842209 GH |
282 | } |
283 | ||
cae32357 AG |
284 | if (!m->dma_active) { |
285 | MACIO_DPRINTF("waiting for data (%#x - %#x - %x)\n", | |
286 | s->nsector, io->len, s->status); | |
287 | /* data not ready yet, wait for the channel to get restarted */ | |
288 | io->processing = false; | |
289 | return; | |
290 | } | |
291 | ||
bd4214fc | 292 | if (s->io_buffer_size <= 0) { |
b01d44cd | 293 | MACIO_DPRINTF("End of IDE transfer\n"); |
b8842209 | 294 | s->status = READY_STAT | SEEK_STAT; |
9cdd03a7 | 295 | ide_set_irq(s->bus); |
cae32357 | 296 | m->dma_active = false; |
bd4214fc | 297 | goto done; |
b8842209 GH |
298 | } |
299 | ||
b8842209 | 300 | if (io->len == 0) { |
bd4214fc | 301 | MACIO_DPRINTF("End of DMA transfer\n"); |
a597e79c | 302 | goto done; |
b8842209 GH |
303 | } |
304 | ||
bd4214fc | 305 | /* Calculate number of sectors */ |
0389b8f8 | 306 | offset = (ide_get_sector(s) << 9) + s->io_buffer_index; |
33ce36bb | 307 | |
4e1e0051 CH |
308 | switch (s->dma_cmd) { |
309 | case IDE_DMA_READ: | |
0389b8f8 | 310 | pmac_dma_read(s->blk, offset, io->len, pmac_ide_transfer_cb, io); |
4e1e0051 CH |
311 | break; |
312 | case IDE_DMA_WRITE: | |
ac58fe7b | 313 | pmac_dma_write(s->blk, offset, io->len, pmac_ide_transfer_cb, io); |
4e1e0051 | 314 | break; |
d353fb72 | 315 | case IDE_DMA_TRIM: |
d353fb72 | 316 | break; |
4e1e0051 | 317 | } |
3e300fa6 | 318 | |
a597e79c | 319 | return; |
b9b2008b | 320 | |
a597e79c CH |
321 | done: |
322 | if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) { | |
4be74634 | 323 | block_acct_done(blk_get_stats(s->blk), &s->acct); |
a597e79c | 324 | } |
bd4214fc | 325 | io->dma_end(opaque); |
b8842209 GH |
326 | } |
327 | ||
328 | static void pmac_ide_transfer(DBDMA_io *io) | |
329 | { | |
330 | MACIOIDEState *m = io->opaque; | |
331 | IDEState *s = idebus_active_if(&m->bus); | |
332 | ||
33ce36bb AG |
333 | MACIO_DPRINTF("\n"); |
334 | ||
cd8722bb | 335 | if (s->drive_kind == IDE_CD) { |
4be74634 | 336 | block_acct_start(blk_get_stats(s->blk), &s->acct, io->len, |
5366d0c8 | 337 | BLOCK_ACCT_READ); |
4827ac1e | 338 | |
b8842209 GH |
339 | pmac_ide_atapi_transfer_cb(io, 0); |
340 | return; | |
341 | } | |
342 | ||
a597e79c CH |
343 | switch (s->dma_cmd) { |
344 | case IDE_DMA_READ: | |
4be74634 | 345 | block_acct_start(blk_get_stats(s->blk), &s->acct, io->len, |
5366d0c8 | 346 | BLOCK_ACCT_READ); |
a597e79c CH |
347 | break; |
348 | case IDE_DMA_WRITE: | |
4be74634 | 349 | block_acct_start(blk_get_stats(s->blk), &s->acct, io->len, |
5366d0c8 | 350 | BLOCK_ACCT_WRITE); |
a597e79c CH |
351 | break; |
352 | default: | |
353 | break; | |
354 | } | |
355 | ||
b8842209 GH |
356 | pmac_ide_transfer_cb(io, 0); |
357 | } | |
358 | ||
359 | static void pmac_ide_flush(DBDMA_io *io) | |
360 | { | |
361 | MACIOIDEState *m = io->opaque; | |
362 | ||
922453bc | 363 | if (m->aiocb) { |
4be74634 | 364 | blk_drain_all(); |
922453bc | 365 | } |
b8842209 GH |
366 | } |
367 | ||
368 | /* PowerMac IDE memory IO */ | |
369 | static void pmac_ide_writeb (void *opaque, | |
a8170e5e | 370 | hwaddr addr, uint32_t val) |
b8842209 GH |
371 | { |
372 | MACIOIDEState *d = opaque; | |
373 | ||
374 | addr = (addr & 0xFFF) >> 4; | |
375 | switch (addr) { | |
376 | case 1 ... 7: | |
377 | ide_ioport_write(&d->bus, addr, val); | |
378 | break; | |
379 | case 8: | |
380 | case 22: | |
381 | ide_cmd_write(&d->bus, 0, val); | |
382 | break; | |
383 | default: | |
384 | break; | |
385 | } | |
386 | } | |
387 | ||
a8170e5e | 388 | static uint32_t pmac_ide_readb (void *opaque,hwaddr addr) |
b8842209 GH |
389 | { |
390 | uint8_t retval; | |
391 | MACIOIDEState *d = opaque; | |
392 | ||
393 | addr = (addr & 0xFFF) >> 4; | |
394 | switch (addr) { | |
395 | case 1 ... 7: | |
396 | retval = ide_ioport_read(&d->bus, addr); | |
397 | break; | |
398 | case 8: | |
399 | case 22: | |
400 | retval = ide_status_read(&d->bus, 0); | |
401 | break; | |
402 | default: | |
403 | retval = 0xFF; | |
404 | break; | |
405 | } | |
406 | return retval; | |
407 | } | |
408 | ||
409 | static void pmac_ide_writew (void *opaque, | |
a8170e5e | 410 | hwaddr addr, uint32_t val) |
b8842209 GH |
411 | { |
412 | MACIOIDEState *d = opaque; | |
413 | ||
414 | addr = (addr & 0xFFF) >> 4; | |
b8842209 | 415 | val = bswap16(val); |
b8842209 GH |
416 | if (addr == 0) { |
417 | ide_data_writew(&d->bus, 0, val); | |
418 | } | |
419 | } | |
420 | ||
a8170e5e | 421 | static uint32_t pmac_ide_readw (void *opaque,hwaddr addr) |
b8842209 GH |
422 | { |
423 | uint16_t retval; | |
424 | MACIOIDEState *d = opaque; | |
425 | ||
426 | addr = (addr & 0xFFF) >> 4; | |
427 | if (addr == 0) { | |
428 | retval = ide_data_readw(&d->bus, 0); | |
429 | } else { | |
430 | retval = 0xFFFF; | |
431 | } | |
b8842209 | 432 | retval = bswap16(retval); |
b8842209 GH |
433 | return retval; |
434 | } | |
435 | ||
436 | static void pmac_ide_writel (void *opaque, | |
a8170e5e | 437 | hwaddr addr, uint32_t val) |
b8842209 GH |
438 | { |
439 | MACIOIDEState *d = opaque; | |
440 | ||
441 | addr = (addr & 0xFFF) >> 4; | |
b8842209 | 442 | val = bswap32(val); |
b8842209 GH |
443 | if (addr == 0) { |
444 | ide_data_writel(&d->bus, 0, val); | |
445 | } | |
446 | } | |
447 | ||
a8170e5e | 448 | static uint32_t pmac_ide_readl (void *opaque,hwaddr addr) |
b8842209 GH |
449 | { |
450 | uint32_t retval; | |
451 | MACIOIDEState *d = opaque; | |
452 | ||
453 | addr = (addr & 0xFFF) >> 4; | |
454 | if (addr == 0) { | |
455 | retval = ide_data_readl(&d->bus, 0); | |
456 | } else { | |
457 | retval = 0xFFFFFFFF; | |
458 | } | |
b8842209 | 459 | retval = bswap32(retval); |
b8842209 GH |
460 | return retval; |
461 | } | |
462 | ||
a348f108 | 463 | static const MemoryRegionOps pmac_ide_ops = { |
23c5e4ca AK |
464 | .old_mmio = { |
465 | .write = { | |
466 | pmac_ide_writeb, | |
467 | pmac_ide_writew, | |
468 | pmac_ide_writel, | |
469 | }, | |
470 | .read = { | |
471 | pmac_ide_readb, | |
472 | pmac_ide_readw, | |
473 | pmac_ide_readl, | |
474 | }, | |
475 | }, | |
476 | .endianness = DEVICE_NATIVE_ENDIAN, | |
b8842209 GH |
477 | }; |
478 | ||
44bfa332 JQ |
479 | static const VMStateDescription vmstate_pmac = { |
480 | .name = "ide", | |
481 | .version_id = 3, | |
482 | .minimum_version_id = 0, | |
35d08458 | 483 | .fields = (VMStateField[]) { |
44bfa332 JQ |
484 | VMSTATE_IDE_BUS(bus, MACIOIDEState), |
485 | VMSTATE_IDE_DRIVES(bus.ifs, MACIOIDEState), | |
486 | VMSTATE_END_OF_LIST() | |
b8842209 | 487 | } |
44bfa332 | 488 | }; |
b8842209 | 489 | |
07a7484e | 490 | static void macio_ide_reset(DeviceState *dev) |
b8842209 | 491 | { |
07a7484e | 492 | MACIOIDEState *d = MACIO_IDE(dev); |
b8842209 | 493 | |
4a643563 | 494 | ide_bus_reset(&d->bus); |
b8842209 GH |
495 | } |
496 | ||
4aa3510f AG |
497 | static int ide_nop_int(IDEDMA *dma, int x) |
498 | { | |
499 | return 0; | |
500 | } | |
501 | ||
3251bdcf JS |
502 | static int32_t ide_nop_int32(IDEDMA *dma, int x) |
503 | { | |
504 | return 0; | |
505 | } | |
506 | ||
4aa3510f | 507 | static void ide_dbdma_start(IDEDMA *dma, IDEState *s, |
097310b5 | 508 | BlockCompletionFunc *cb) |
4aa3510f AG |
509 | { |
510 | MACIOIDEState *m = container_of(dma, MACIOIDEState, dma); | |
4827ac1e | 511 | |
bd4214fc | 512 | s->io_buffer_index = 0; |
4827ac1e | 513 | if (s->drive_kind == IDE_CD) { |
4827ac1e | 514 | s->io_buffer_size = s->packet_transfer_size; |
bd4214fc | 515 | } else { |
b01d44cd | 516 | s->io_buffer_size = s->nsector * BDRV_SECTOR_SIZE; |
bd4214fc | 517 | } |
4827ac1e | 518 | |
bd4214fc MCA |
519 | MACIO_DPRINTF("\n\n------------ IDE transfer\n"); |
520 | MACIO_DPRINTF("buffer_size: %x buffer_index: %x\n", | |
521 | s->io_buffer_size, s->io_buffer_index); | |
522 | MACIO_DPRINTF("lba: %x size: %x\n", s->lba, s->io_buffer_size); | |
523 | MACIO_DPRINTF("-------------------------\n"); | |
4827ac1e | 524 | |
cae32357 | 525 | m->dma_active = true; |
4aa3510f AG |
526 | DBDMA_kick(m->dbdma); |
527 | } | |
528 | ||
529 | static const IDEDMAOps dbdma_ops = { | |
530 | .start_dma = ide_dbdma_start, | |
3251bdcf | 531 | .prepare_buf = ide_nop_int32, |
4aa3510f | 532 | .rw_buf = ide_nop_int, |
4aa3510f AG |
533 | }; |
534 | ||
07a7484e | 535 | static void macio_ide_realizefn(DeviceState *dev, Error **errp) |
b8842209 | 536 | { |
07a7484e AF |
537 | MACIOIDEState *s = MACIO_IDE(dev); |
538 | ||
539 | ide_init2(&s->bus, s->irq); | |
4aa3510f AG |
540 | |
541 | /* Register DMA callbacks */ | |
542 | s->dma.ops = &dbdma_ops; | |
543 | s->bus.dma = &s->dma; | |
07a7484e AF |
544 | } |
545 | ||
546 | static void macio_ide_initfn(Object *obj) | |
547 | { | |
548 | SysBusDevice *d = SYS_BUS_DEVICE(obj); | |
549 | MACIOIDEState *s = MACIO_IDE(obj); | |
550 | ||
c6baf942 | 551 | ide_bus_new(&s->bus, sizeof(s->bus), DEVICE(obj), 0, 2); |
1437c94b | 552 | memory_region_init_io(&s->mem, obj, &pmac_ide_ops, s, "pmac-ide", 0x1000); |
07a7484e AF |
553 | sysbus_init_mmio(d, &s->mem); |
554 | sysbus_init_irq(d, &s->irq); | |
555 | sysbus_init_irq(d, &s->dma_irq); | |
556 | } | |
557 | ||
558 | static void macio_ide_class_init(ObjectClass *oc, void *data) | |
559 | { | |
560 | DeviceClass *dc = DEVICE_CLASS(oc); | |
561 | ||
562 | dc->realize = macio_ide_realizefn; | |
563 | dc->reset = macio_ide_reset; | |
564 | dc->vmsd = &vmstate_pmac; | |
565 | } | |
b8842209 | 566 | |
07a7484e AF |
567 | static const TypeInfo macio_ide_type_info = { |
568 | .name = TYPE_MACIO_IDE, | |
569 | .parent = TYPE_SYS_BUS_DEVICE, | |
570 | .instance_size = sizeof(MACIOIDEState), | |
571 | .instance_init = macio_ide_initfn, | |
572 | .class_init = macio_ide_class_init, | |
573 | }; | |
b8842209 | 574 | |
07a7484e AF |
575 | static void macio_ide_register_types(void) |
576 | { | |
577 | type_register_static(&macio_ide_type_info); | |
578 | } | |
b8842209 | 579 | |
14eefd0e | 580 | /* hd_table must contain 2 block drivers */ |
07a7484e AF |
581 | void macio_ide_init_drives(MACIOIDEState *s, DriveInfo **hd_table) |
582 | { | |
583 | int i; | |
b8842209 | 584 | |
07a7484e AF |
585 | for (i = 0; i < 2; i++) { |
586 | if (hd_table[i]) { | |
587 | ide_create_drive(&s->bus, i, hd_table[i]); | |
588 | } | |
589 | } | |
b8842209 | 590 | } |
07a7484e AF |
591 | |
592 | void macio_ide_register_dma(MACIOIDEState *s, void *dbdma, int channel) | |
593 | { | |
4aa3510f | 594 | s->dbdma = dbdma; |
07a7484e AF |
595 | DBDMA_register_channel(dbdma, channel, s->dma_irq, |
596 | pmac_ide_transfer, pmac_ide_flush, s); | |
597 | } | |
598 | ||
599 | type_init(macio_ide_register_types) |