]>
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 | ||
0e826a06 AJ |
211 | static void pmac_dma_trim(BlockBackend *blk, |
212 | int64_t offset, int bytes, | |
213 | void (*cb)(void *opaque, int ret), void *opaque) | |
214 | { | |
215 | DBDMA_io *io = opaque; | |
216 | MACIOIDEState *m = io->opaque; | |
217 | IDEState *s = idebus_active_if(&m->bus); | |
218 | dma_addr_t dma_addr, dma_len; | |
219 | void *mem; | |
220 | ||
221 | qemu_iovec_destroy(&io->iov); | |
222 | qemu_iovec_init(&io->iov, io->len / MACIO_PAGE_SIZE + 1); | |
223 | ||
224 | dma_addr = io->addr; | |
225 | dma_len = io->len; | |
226 | mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len, | |
227 | DMA_DIRECTION_TO_DEVICE); | |
228 | ||
229 | qemu_iovec_add(&io->iov, mem, io->len); | |
230 | s->io_buffer_size -= io->len; | |
231 | s->io_buffer_index += io->len; | |
232 | io->len = 0; | |
233 | ||
234 | m->aiocb = ide_issue_trim(blk, (offset >> 9), &io->iov, (bytes >> 9), | |
235 | cb, io); | |
236 | } | |
237 | ||
4827ac1e MCA |
238 | static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) |
239 | { | |
240 | DBDMA_io *io = opaque; | |
241 | MACIOIDEState *m = io->opaque; | |
242 | IDEState *s = idebus_active_if(&m->bus); | |
0389b8f8 | 243 | int64_t offset; |
4827ac1e | 244 | |
b01d44cd | 245 | MACIO_DPRINTF("pmac_ide_atapi_transfer_cb\n"); |
4827ac1e MCA |
246 | |
247 | if (ret < 0) { | |
b01d44cd | 248 | MACIO_DPRINTF("DMA error: %d\n", ret); |
4827ac1e MCA |
249 | ide_atapi_io_error(s, ret); |
250 | goto done; | |
251 | } | |
252 | ||
253 | if (!m->dma_active) { | |
254 | MACIO_DPRINTF("waiting for data (%#x - %#x - %x)\n", | |
255 | s->nsector, io->len, s->status); | |
256 | /* data not ready yet, wait for the channel to get restarted */ | |
257 | io->processing = false; | |
80fc95d8 AG |
258 | return; |
259 | } | |
260 | ||
4827ac1e | 261 | if (s->io_buffer_size <= 0) { |
b01d44cd | 262 | MACIO_DPRINTF("End of IDE transfer\n"); |
b8842209 | 263 | ide_atapi_cmd_ok(s); |
cae32357 | 264 | m->dma_active = false; |
4827ac1e | 265 | goto done; |
33ce36bb | 266 | } |
b8842209 GH |
267 | |
268 | if (io->len == 0) { | |
4827ac1e | 269 | MACIO_DPRINTF("End of DMA transfer\n"); |
a597e79c | 270 | goto done; |
b8842209 GH |
271 | } |
272 | ||
4827ac1e MCA |
273 | if (s->lba == -1) { |
274 | /* Non-block ATAPI transfer - just copy to RAM */ | |
275 | s->io_buffer_size = MIN(s->io_buffer_size, io->len); | |
276 | cpu_physical_memory_write(io->addr, s->io_buffer, s->io_buffer_size); | |
277 | ide_atapi_cmd_ok(s); | |
278 | m->dma_active = false; | |
279 | goto done; | |
80fc95d8 AG |
280 | } |
281 | ||
0389b8f8 MCA |
282 | /* Calculate current offset */ |
283 | offset = (int64_t)(s->lba << 11) + s->io_buffer_index; | |
284 | ||
0389b8f8 | 285 | pmac_dma_read(s->blk, offset, io->len, pmac_ide_atapi_transfer_cb, io); |
a597e79c CH |
286 | return; |
287 | ||
288 | done: | |
b88b3c8b AG |
289 | if (ret < 0) { |
290 | block_acct_failed(blk_get_stats(s->blk), &s->acct); | |
291 | } else { | |
292 | block_acct_done(blk_get_stats(s->blk), &s->acct); | |
293 | } | |
a597e79c | 294 | io->dma_end(opaque); |
4827ac1e MCA |
295 | |
296 | return; | |
b8842209 GH |
297 | } |
298 | ||
299 | static void pmac_ide_transfer_cb(void *opaque, int ret) | |
300 | { | |
301 | DBDMA_io *io = opaque; | |
302 | MACIOIDEState *m = io->opaque; | |
303 | IDEState *s = idebus_active_if(&m->bus); | |
0389b8f8 | 304 | int64_t offset; |
bd4214fc MCA |
305 | |
306 | MACIO_DPRINTF("pmac_ide_transfer_cb\n"); | |
b8842209 GH |
307 | |
308 | if (ret < 0) { | |
b01d44cd | 309 | MACIO_DPRINTF("DMA error: %d\n", ret); |
b8842209 | 310 | m->aiocb = NULL; |
8aef291f | 311 | ide_dma_error(s); |
a597e79c | 312 | goto done; |
b8842209 GH |
313 | } |
314 | ||
cae32357 AG |
315 | if (!m->dma_active) { |
316 | MACIO_DPRINTF("waiting for data (%#x - %#x - %x)\n", | |
317 | s->nsector, io->len, s->status); | |
318 | /* data not ready yet, wait for the channel to get restarted */ | |
319 | io->processing = false; | |
320 | return; | |
321 | } | |
322 | ||
bd4214fc | 323 | if (s->io_buffer_size <= 0) { |
b01d44cd | 324 | MACIO_DPRINTF("End of IDE transfer\n"); |
b8842209 | 325 | s->status = READY_STAT | SEEK_STAT; |
9cdd03a7 | 326 | ide_set_irq(s->bus); |
cae32357 | 327 | m->dma_active = false; |
bd4214fc | 328 | goto done; |
b8842209 GH |
329 | } |
330 | ||
b8842209 | 331 | if (io->len == 0) { |
bd4214fc | 332 | MACIO_DPRINTF("End of DMA transfer\n"); |
a597e79c | 333 | goto done; |
b8842209 GH |
334 | } |
335 | ||
bd4214fc | 336 | /* Calculate number of sectors */ |
0389b8f8 | 337 | offset = (ide_get_sector(s) << 9) + s->io_buffer_index; |
33ce36bb | 338 | |
4e1e0051 CH |
339 | switch (s->dma_cmd) { |
340 | case IDE_DMA_READ: | |
0389b8f8 | 341 | pmac_dma_read(s->blk, offset, io->len, pmac_ide_transfer_cb, io); |
4e1e0051 CH |
342 | break; |
343 | case IDE_DMA_WRITE: | |
ac58fe7b | 344 | pmac_dma_write(s->blk, offset, io->len, pmac_ide_transfer_cb, io); |
4e1e0051 | 345 | break; |
d353fb72 | 346 | case IDE_DMA_TRIM: |
0e826a06 | 347 | pmac_dma_trim(s->blk, offset, io->len, pmac_ide_transfer_cb, io); |
d353fb72 | 348 | break; |
4e1e0051 | 349 | } |
3e300fa6 | 350 | |
a597e79c | 351 | return; |
b9b2008b | 352 | |
a597e79c CH |
353 | done: |
354 | if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) { | |
b88b3c8b AG |
355 | if (ret < 0) { |
356 | block_acct_failed(blk_get_stats(s->blk), &s->acct); | |
357 | } else { | |
358 | block_acct_done(blk_get_stats(s->blk), &s->acct); | |
359 | } | |
a597e79c | 360 | } |
bd4214fc | 361 | io->dma_end(opaque); |
b8842209 GH |
362 | } |
363 | ||
364 | static void pmac_ide_transfer(DBDMA_io *io) | |
365 | { | |
366 | MACIOIDEState *m = io->opaque; | |
367 | IDEState *s = idebus_active_if(&m->bus); | |
368 | ||
33ce36bb AG |
369 | MACIO_DPRINTF("\n"); |
370 | ||
cd8722bb | 371 | if (s->drive_kind == IDE_CD) { |
4be74634 | 372 | block_acct_start(blk_get_stats(s->blk), &s->acct, io->len, |
5366d0c8 | 373 | BLOCK_ACCT_READ); |
4827ac1e | 374 | |
b8842209 GH |
375 | pmac_ide_atapi_transfer_cb(io, 0); |
376 | return; | |
377 | } | |
378 | ||
a597e79c CH |
379 | switch (s->dma_cmd) { |
380 | case IDE_DMA_READ: | |
4be74634 | 381 | block_acct_start(blk_get_stats(s->blk), &s->acct, io->len, |
5366d0c8 | 382 | BLOCK_ACCT_READ); |
a597e79c CH |
383 | break; |
384 | case IDE_DMA_WRITE: | |
4be74634 | 385 | block_acct_start(blk_get_stats(s->blk), &s->acct, io->len, |
5366d0c8 | 386 | BLOCK_ACCT_WRITE); |
a597e79c CH |
387 | break; |
388 | default: | |
389 | break; | |
390 | } | |
391 | ||
b8842209 GH |
392 | pmac_ide_transfer_cb(io, 0); |
393 | } | |
394 | ||
395 | static void pmac_ide_flush(DBDMA_io *io) | |
396 | { | |
397 | MACIOIDEState *m = io->opaque; | |
398 | ||
922453bc | 399 | if (m->aiocb) { |
4be74634 | 400 | blk_drain_all(); |
922453bc | 401 | } |
b8842209 GH |
402 | } |
403 | ||
404 | /* PowerMac IDE memory IO */ | |
405 | static void pmac_ide_writeb (void *opaque, | |
a8170e5e | 406 | hwaddr addr, uint32_t val) |
b8842209 GH |
407 | { |
408 | MACIOIDEState *d = opaque; | |
409 | ||
410 | addr = (addr & 0xFFF) >> 4; | |
411 | switch (addr) { | |
412 | case 1 ... 7: | |
413 | ide_ioport_write(&d->bus, addr, val); | |
414 | break; | |
415 | case 8: | |
416 | case 22: | |
417 | ide_cmd_write(&d->bus, 0, val); | |
418 | break; | |
419 | default: | |
420 | break; | |
421 | } | |
422 | } | |
423 | ||
a8170e5e | 424 | static uint32_t pmac_ide_readb (void *opaque,hwaddr addr) |
b8842209 GH |
425 | { |
426 | uint8_t retval; | |
427 | MACIOIDEState *d = opaque; | |
428 | ||
429 | addr = (addr & 0xFFF) >> 4; | |
430 | switch (addr) { | |
431 | case 1 ... 7: | |
432 | retval = ide_ioport_read(&d->bus, addr); | |
433 | break; | |
434 | case 8: | |
435 | case 22: | |
436 | retval = ide_status_read(&d->bus, 0); | |
437 | break; | |
438 | default: | |
439 | retval = 0xFF; | |
440 | break; | |
441 | } | |
442 | return retval; | |
443 | } | |
444 | ||
445 | static void pmac_ide_writew (void *opaque, | |
a8170e5e | 446 | hwaddr addr, uint32_t val) |
b8842209 GH |
447 | { |
448 | MACIOIDEState *d = opaque; | |
449 | ||
450 | addr = (addr & 0xFFF) >> 4; | |
b8842209 | 451 | val = bswap16(val); |
b8842209 GH |
452 | if (addr == 0) { |
453 | ide_data_writew(&d->bus, 0, val); | |
454 | } | |
455 | } | |
456 | ||
a8170e5e | 457 | static uint32_t pmac_ide_readw (void *opaque,hwaddr addr) |
b8842209 GH |
458 | { |
459 | uint16_t retval; | |
460 | MACIOIDEState *d = opaque; | |
461 | ||
462 | addr = (addr & 0xFFF) >> 4; | |
463 | if (addr == 0) { | |
464 | retval = ide_data_readw(&d->bus, 0); | |
465 | } else { | |
466 | retval = 0xFFFF; | |
467 | } | |
b8842209 | 468 | retval = bswap16(retval); |
b8842209 GH |
469 | return retval; |
470 | } | |
471 | ||
472 | static void pmac_ide_writel (void *opaque, | |
a8170e5e | 473 | hwaddr addr, uint32_t val) |
b8842209 GH |
474 | { |
475 | MACIOIDEState *d = opaque; | |
476 | ||
477 | addr = (addr & 0xFFF) >> 4; | |
b8842209 | 478 | val = bswap32(val); |
b8842209 GH |
479 | if (addr == 0) { |
480 | ide_data_writel(&d->bus, 0, val); | |
481 | } | |
482 | } | |
483 | ||
a8170e5e | 484 | static uint32_t pmac_ide_readl (void *opaque,hwaddr addr) |
b8842209 GH |
485 | { |
486 | uint32_t retval; | |
487 | MACIOIDEState *d = opaque; | |
488 | ||
489 | addr = (addr & 0xFFF) >> 4; | |
490 | if (addr == 0) { | |
491 | retval = ide_data_readl(&d->bus, 0); | |
492 | } else { | |
493 | retval = 0xFFFFFFFF; | |
494 | } | |
b8842209 | 495 | retval = bswap32(retval); |
b8842209 GH |
496 | return retval; |
497 | } | |
498 | ||
a348f108 | 499 | static const MemoryRegionOps pmac_ide_ops = { |
23c5e4ca AK |
500 | .old_mmio = { |
501 | .write = { | |
502 | pmac_ide_writeb, | |
503 | pmac_ide_writew, | |
504 | pmac_ide_writel, | |
505 | }, | |
506 | .read = { | |
507 | pmac_ide_readb, | |
508 | pmac_ide_readw, | |
509 | pmac_ide_readl, | |
510 | }, | |
511 | }, | |
512 | .endianness = DEVICE_NATIVE_ENDIAN, | |
b8842209 GH |
513 | }; |
514 | ||
44bfa332 JQ |
515 | static const VMStateDescription vmstate_pmac = { |
516 | .name = "ide", | |
517 | .version_id = 3, | |
518 | .minimum_version_id = 0, | |
35d08458 | 519 | .fields = (VMStateField[]) { |
44bfa332 JQ |
520 | VMSTATE_IDE_BUS(bus, MACIOIDEState), |
521 | VMSTATE_IDE_DRIVES(bus.ifs, MACIOIDEState), | |
522 | VMSTATE_END_OF_LIST() | |
b8842209 | 523 | } |
44bfa332 | 524 | }; |
b8842209 | 525 | |
07a7484e | 526 | static void macio_ide_reset(DeviceState *dev) |
b8842209 | 527 | { |
07a7484e | 528 | MACIOIDEState *d = MACIO_IDE(dev); |
b8842209 | 529 | |
4a643563 | 530 | ide_bus_reset(&d->bus); |
b8842209 GH |
531 | } |
532 | ||
4aa3510f AG |
533 | static int ide_nop_int(IDEDMA *dma, int x) |
534 | { | |
535 | return 0; | |
536 | } | |
537 | ||
a718978e | 538 | static int32_t ide_nop_int32(IDEDMA *dma, int32_t l) |
3251bdcf JS |
539 | { |
540 | return 0; | |
541 | } | |
542 | ||
4aa3510f | 543 | static void ide_dbdma_start(IDEDMA *dma, IDEState *s, |
097310b5 | 544 | BlockCompletionFunc *cb) |
4aa3510f AG |
545 | { |
546 | MACIOIDEState *m = container_of(dma, MACIOIDEState, dma); | |
4827ac1e | 547 | |
bd4214fc | 548 | s->io_buffer_index = 0; |
4827ac1e | 549 | if (s->drive_kind == IDE_CD) { |
4827ac1e | 550 | s->io_buffer_size = s->packet_transfer_size; |
bd4214fc | 551 | } else { |
b01d44cd | 552 | s->io_buffer_size = s->nsector * BDRV_SECTOR_SIZE; |
bd4214fc | 553 | } |
4827ac1e | 554 | |
bd4214fc MCA |
555 | MACIO_DPRINTF("\n\n------------ IDE transfer\n"); |
556 | MACIO_DPRINTF("buffer_size: %x buffer_index: %x\n", | |
557 | s->io_buffer_size, s->io_buffer_index); | |
558 | MACIO_DPRINTF("lba: %x size: %x\n", s->lba, s->io_buffer_size); | |
559 | MACIO_DPRINTF("-------------------------\n"); | |
4827ac1e | 560 | |
cae32357 | 561 | m->dma_active = true; |
4aa3510f AG |
562 | DBDMA_kick(m->dbdma); |
563 | } | |
564 | ||
565 | static const IDEDMAOps dbdma_ops = { | |
566 | .start_dma = ide_dbdma_start, | |
3251bdcf | 567 | .prepare_buf = ide_nop_int32, |
4aa3510f | 568 | .rw_buf = ide_nop_int, |
4aa3510f AG |
569 | }; |
570 | ||
07a7484e | 571 | static void macio_ide_realizefn(DeviceState *dev, Error **errp) |
b8842209 | 572 | { |
07a7484e AF |
573 | MACIOIDEState *s = MACIO_IDE(dev); |
574 | ||
575 | ide_init2(&s->bus, s->irq); | |
4aa3510f AG |
576 | |
577 | /* Register DMA callbacks */ | |
578 | s->dma.ops = &dbdma_ops; | |
579 | s->bus.dma = &s->dma; | |
07a7484e AF |
580 | } |
581 | ||
582 | static void macio_ide_initfn(Object *obj) | |
583 | { | |
584 | SysBusDevice *d = SYS_BUS_DEVICE(obj); | |
585 | MACIOIDEState *s = MACIO_IDE(obj); | |
586 | ||
c6baf942 | 587 | ide_bus_new(&s->bus, sizeof(s->bus), DEVICE(obj), 0, 2); |
1437c94b | 588 | memory_region_init_io(&s->mem, obj, &pmac_ide_ops, s, "pmac-ide", 0x1000); |
07a7484e AF |
589 | sysbus_init_mmio(d, &s->mem); |
590 | sysbus_init_irq(d, &s->irq); | |
591 | sysbus_init_irq(d, &s->dma_irq); | |
592 | } | |
593 | ||
594 | static void macio_ide_class_init(ObjectClass *oc, void *data) | |
595 | { | |
596 | DeviceClass *dc = DEVICE_CLASS(oc); | |
597 | ||
598 | dc->realize = macio_ide_realizefn; | |
599 | dc->reset = macio_ide_reset; | |
600 | dc->vmsd = &vmstate_pmac; | |
3469d9bc | 601 | set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); |
07a7484e | 602 | } |
b8842209 | 603 | |
07a7484e AF |
604 | static const TypeInfo macio_ide_type_info = { |
605 | .name = TYPE_MACIO_IDE, | |
606 | .parent = TYPE_SYS_BUS_DEVICE, | |
607 | .instance_size = sizeof(MACIOIDEState), | |
608 | .instance_init = macio_ide_initfn, | |
609 | .class_init = macio_ide_class_init, | |
610 | }; | |
b8842209 | 611 | |
07a7484e AF |
612 | static void macio_ide_register_types(void) |
613 | { | |
614 | type_register_static(&macio_ide_type_info); | |
615 | } | |
b8842209 | 616 | |
14eefd0e | 617 | /* hd_table must contain 2 block drivers */ |
07a7484e AF |
618 | void macio_ide_init_drives(MACIOIDEState *s, DriveInfo **hd_table) |
619 | { | |
620 | int i; | |
b8842209 | 621 | |
07a7484e AF |
622 | for (i = 0; i < 2; i++) { |
623 | if (hd_table[i]) { | |
624 | ide_create_drive(&s->bus, i, hd_table[i]); | |
625 | } | |
626 | } | |
b8842209 | 627 | } |
07a7484e AF |
628 | |
629 | void macio_ide_register_dma(MACIOIDEState *s, void *dbdma, int channel) | |
630 | { | |
4aa3510f | 631 | s->dbdma = dbdma; |
07a7484e AF |
632 | DBDMA_register_channel(dbdma, channel, s->dma_irq, |
633 | pmac_ide_transfer, pmac_ide_flush, s); | |
634 | } | |
635 | ||
636 | type_init(macio_ide_register_types) |