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