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