]>
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 | */ | |
0b8fa32f | 25 | |
53239262 | 26 | #include "qemu/osdep.h" |
0d09e41a | 27 | #include "hw/ppc/mac_dbdma.h" |
a27bd6c7 | 28 | #include "hw/qdev-properties.h" |
d6454270 | 29 | #include "migration/vmstate.h" |
0b8fa32f | 30 | #include "qemu/module.h" |
9b164a46 | 31 | #include "hw/misc/macio/macio.h" |
4be74634 | 32 | #include "sysemu/block-backend.h" |
9c17d615 | 33 | #include "sysemu/dma.h" |
59f2a787 | 34 | |
a9c94277 | 35 | #include "hw/ide/internal.h" |
b8842209 | 36 | |
33ce36bb AG |
37 | /* debug MACIO */ |
38 | // #define DEBUG_MACIO | |
39 | ||
40 | #ifdef DEBUG_MACIO | |
41 | static const int debug_macio = 1; | |
42 | #else | |
43 | static const int debug_macio = 0; | |
44 | #endif | |
45 | ||
46 | #define MACIO_DPRINTF(fmt, ...) do { \ | |
47 | if (debug_macio) { \ | |
48 | printf(fmt , ## __VA_ARGS__); \ | |
49 | } \ | |
50 | } while (0) | |
51 | ||
52 | ||
b8842209 GH |
53 | /***********************************************************/ |
54 | /* MacIO based PowerPC IDE */ | |
55 | ||
02c7c992 BS |
56 | #define MACIO_PAGE_SIZE 4096 |
57 | ||
4827ac1e MCA |
58 | static void pmac_ide_atapi_transfer_cb(void *opaque, int ret) |
59 | { | |
60 | DBDMA_io *io = opaque; | |
61 | MACIOIDEState *m = io->opaque; | |
62 | IDEState *s = idebus_active_if(&m->bus); | |
0389b8f8 | 63 | int64_t offset; |
4827ac1e | 64 | |
b01d44cd | 65 | MACIO_DPRINTF("pmac_ide_atapi_transfer_cb\n"); |
4827ac1e MCA |
66 | |
67 | if (ret < 0) { | |
b01d44cd | 68 | MACIO_DPRINTF("DMA error: %d\n", ret); |
be1e3439 | 69 | qemu_sglist_destroy(&s->sg); |
4827ac1e MCA |
70 | ide_atapi_io_error(s, ret); |
71 | goto done; | |
72 | } | |
73 | ||
74 | if (!m->dma_active) { | |
75 | MACIO_DPRINTF("waiting for data (%#x - %#x - %x)\n", | |
76 | s->nsector, io->len, s->status); | |
77 | /* data not ready yet, wait for the channel to get restarted */ | |
78 | io->processing = false; | |
80fc95d8 AG |
79 | return; |
80 | } | |
81 | ||
4827ac1e | 82 | if (s->io_buffer_size <= 0) { |
b01d44cd | 83 | MACIO_DPRINTF("End of IDE transfer\n"); |
be1e3439 | 84 | qemu_sglist_destroy(&s->sg); |
b8842209 | 85 | ide_atapi_cmd_ok(s); |
cae32357 | 86 | m->dma_active = false; |
4827ac1e | 87 | goto done; |
33ce36bb | 88 | } |
b8842209 GH |
89 | |
90 | if (io->len == 0) { | |
4827ac1e | 91 | MACIO_DPRINTF("End of DMA transfer\n"); |
a597e79c | 92 | goto done; |
b8842209 GH |
93 | } |
94 | ||
4827ac1e MCA |
95 | if (s->lba == -1) { |
96 | /* Non-block ATAPI transfer - just copy to RAM */ | |
97 | s->io_buffer_size = MIN(s->io_buffer_size, io->len); | |
ddd495e5 | 98 | dma_memory_write(&address_space_memory, io->addr, s->io_buffer, |
ba06fe8a | 99 | s->io_buffer_size, MEMTXATTRS_UNSPECIFIED); |
16275edb | 100 | io->len = 0; |
4827ac1e MCA |
101 | ide_atapi_cmd_ok(s); |
102 | m->dma_active = false; | |
103 | goto done; | |
80fc95d8 AG |
104 | } |
105 | ||
0389b8f8 | 106 | /* Calculate current offset */ |
97225170 | 107 | offset = ((int64_t)s->lba << 11) + s->io_buffer_index; |
0389b8f8 | 108 | |
be1e3439 MCA |
109 | qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1, |
110 | &address_space_memory); | |
111 | qemu_sglist_add(&s->sg, io->addr, io->len); | |
112 | s->io_buffer_size -= io->len; | |
113 | s->io_buffer_index += io->len; | |
114 | io->len = 0; | |
115 | ||
116 | s->bus->dma->aiocb = dma_blk_read(s->blk, &s->sg, offset, 0x1, | |
117 | pmac_ide_atapi_transfer_cb, io); | |
a597e79c CH |
118 | return; |
119 | ||
120 | done: | |
bc9ca595 MCA |
121 | dma_memory_unmap(&address_space_memory, io->dma_mem, io->dma_len, |
122 | io->dir, io->dma_len); | |
123 | ||
b88b3c8b AG |
124 | if (ret < 0) { |
125 | block_acct_failed(blk_get_stats(s->blk), &s->acct); | |
126 | } else { | |
127 | block_acct_done(blk_get_stats(s->blk), &s->acct); | |
128 | } | |
03c1280b MCA |
129 | |
130 | ide_set_inactive(s, false); | |
a597e79c | 131 | io->dma_end(opaque); |
b8842209 GH |
132 | } |
133 | ||
134 | static void pmac_ide_transfer_cb(void *opaque, int ret) | |
135 | { | |
136 | DBDMA_io *io = opaque; | |
137 | MACIOIDEState *m = io->opaque; | |
138 | IDEState *s = idebus_active_if(&m->bus); | |
0389b8f8 | 139 | int64_t offset; |
bd4214fc MCA |
140 | |
141 | MACIO_DPRINTF("pmac_ide_transfer_cb\n"); | |
b8842209 GH |
142 | |
143 | if (ret < 0) { | |
b01d44cd | 144 | MACIO_DPRINTF("DMA error: %d\n", ret); |
be1e3439 | 145 | qemu_sglist_destroy(&s->sg); |
8aef291f | 146 | ide_dma_error(s); |
a597e79c | 147 | goto done; |
b8842209 GH |
148 | } |
149 | ||
cae32357 AG |
150 | if (!m->dma_active) { |
151 | MACIO_DPRINTF("waiting for data (%#x - %#x - %x)\n", | |
152 | s->nsector, io->len, s->status); | |
153 | /* data not ready yet, wait for the channel to get restarted */ | |
154 | io->processing = false; | |
155 | return; | |
156 | } | |
157 | ||
bd4214fc | 158 | if (s->io_buffer_size <= 0) { |
b01d44cd | 159 | MACIO_DPRINTF("End of IDE transfer\n"); |
be1e3439 | 160 | qemu_sglist_destroy(&s->sg); |
b8842209 | 161 | s->status = READY_STAT | SEEK_STAT; |
9cdd03a7 | 162 | ide_set_irq(s->bus); |
cae32357 | 163 | m->dma_active = false; |
bd4214fc | 164 | goto done; |
b8842209 GH |
165 | } |
166 | ||
b8842209 | 167 | if (io->len == 0) { |
bd4214fc | 168 | MACIO_DPRINTF("End of DMA transfer\n"); |
a597e79c | 169 | goto done; |
b8842209 GH |
170 | } |
171 | ||
bd4214fc | 172 | /* Calculate number of sectors */ |
0389b8f8 | 173 | offset = (ide_get_sector(s) << 9) + s->io_buffer_index; |
33ce36bb | 174 | |
be1e3439 MCA |
175 | qemu_sglist_init(&s->sg, DEVICE(m), io->len / MACIO_PAGE_SIZE + 1, |
176 | &address_space_memory); | |
177 | qemu_sglist_add(&s->sg, io->addr, io->len); | |
178 | s->io_buffer_size -= io->len; | |
179 | s->io_buffer_index += io->len; | |
180 | io->len = 0; | |
181 | ||
4e1e0051 CH |
182 | switch (s->dma_cmd) { |
183 | case IDE_DMA_READ: | |
be1e3439 MCA |
184 | s->bus->dma->aiocb = dma_blk_read(s->blk, &s->sg, offset, 0x1, |
185 | pmac_ide_atapi_transfer_cb, io); | |
4e1e0051 CH |
186 | break; |
187 | case IDE_DMA_WRITE: | |
be1e3439 MCA |
188 | s->bus->dma->aiocb = dma_blk_write(s->blk, &s->sg, offset, 0x1, |
189 | pmac_ide_transfer_cb, io); | |
4e1e0051 | 190 | break; |
d353fb72 | 191 | case IDE_DMA_TRIM: |
be1e3439 | 192 | s->bus->dma->aiocb = dma_blk_io(blk_get_aio_context(s->blk), &s->sg, |
eb69953e | 193 | offset, 0x1, ide_issue_trim, s, |
be1e3439 MCA |
194 | pmac_ide_transfer_cb, io, |
195 | DMA_DIRECTION_TO_DEVICE); | |
d353fb72 | 196 | break; |
502356ee PB |
197 | default: |
198 | abort(); | |
4e1e0051 | 199 | } |
3e300fa6 | 200 | |
a597e79c | 201 | return; |
b9b2008b | 202 | |
a597e79c | 203 | done: |
bc9ca595 MCA |
204 | dma_memory_unmap(&address_space_memory, io->dma_mem, io->dma_len, |
205 | io->dir, io->dma_len); | |
206 | ||
a597e79c | 207 | if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) { |
b88b3c8b AG |
208 | if (ret < 0) { |
209 | block_acct_failed(blk_get_stats(s->blk), &s->acct); | |
210 | } else { | |
211 | block_acct_done(blk_get_stats(s->blk), &s->acct); | |
212 | } | |
a597e79c | 213 | } |
03c1280b MCA |
214 | |
215 | ide_set_inactive(s, false); | |
bd4214fc | 216 | io->dma_end(opaque); |
b8842209 GH |
217 | } |
218 | ||
219 | static void pmac_ide_transfer(DBDMA_io *io) | |
220 | { | |
221 | MACIOIDEState *m = io->opaque; | |
222 | IDEState *s = idebus_active_if(&m->bus); | |
223 | ||
33ce36bb AG |
224 | MACIO_DPRINTF("\n"); |
225 | ||
cd8722bb | 226 | if (s->drive_kind == IDE_CD) { |
4be74634 | 227 | block_acct_start(blk_get_stats(s->blk), &s->acct, io->len, |
5366d0c8 | 228 | BLOCK_ACCT_READ); |
4827ac1e | 229 | |
b8842209 GH |
230 | pmac_ide_atapi_transfer_cb(io, 0); |
231 | return; | |
232 | } | |
233 | ||
a597e79c CH |
234 | switch (s->dma_cmd) { |
235 | case IDE_DMA_READ: | |
4be74634 | 236 | block_acct_start(blk_get_stats(s->blk), &s->acct, io->len, |
5366d0c8 | 237 | BLOCK_ACCT_READ); |
a597e79c CH |
238 | break; |
239 | case IDE_DMA_WRITE: | |
4be74634 | 240 | block_acct_start(blk_get_stats(s->blk), &s->acct, io->len, |
5366d0c8 | 241 | BLOCK_ACCT_WRITE); |
a597e79c CH |
242 | break; |
243 | default: | |
244 | break; | |
245 | } | |
246 | ||
b8842209 GH |
247 | pmac_ide_transfer_cb(io, 0); |
248 | } | |
249 | ||
250 | static void pmac_ide_flush(DBDMA_io *io) | |
251 | { | |
252 | MACIOIDEState *m = io->opaque; | |
03c1280b | 253 | IDEState *s = idebus_active_if(&m->bus); |
b8842209 | 254 | |
03c1280b | 255 | if (s->bus->dma->aiocb) { |
0d0437aa | 256 | blk_drain(s->blk); |
922453bc | 257 | } |
b8842209 GH |
258 | } |
259 | ||
260 | /* PowerMac IDE memory IO */ | |
5abdf670 | 261 | static uint64_t pmac_ide_read(void *opaque, hwaddr addr, unsigned size) |
b8842209 GH |
262 | { |
263 | MACIOIDEState *d = opaque; | |
5abdf670 MCA |
264 | uint64_t retval = 0xffffffff; |
265 | int reg = addr >> 4; | |
266 | ||
267 | switch (reg) { | |
268 | case 0x0: | |
758c925e LK |
269 | if (size == 1) { |
270 | retval = ide_data_readw(&d->bus, 0) & 0xFF; | |
271 | } else if (size == 2) { | |
5abdf670 MCA |
272 | retval = ide_data_readw(&d->bus, 0); |
273 | } else if (size == 4) { | |
274 | retval = ide_data_readl(&d->bus, 0); | |
275 | } | |
b8842209 | 276 | break; |
5abdf670 MCA |
277 | case 0x1 ... 0x7: |
278 | if (size == 1) { | |
279 | retval = ide_ioport_read(&d->bus, reg); | |
280 | } | |
b8842209 | 281 | break; |
5abdf670 MCA |
282 | case 0x8: |
283 | case 0x16: | |
284 | if (size == 1) { | |
285 | retval = ide_status_read(&d->bus, 0); | |
286 | } | |
b8842209 | 287 | break; |
5abdf670 MCA |
288 | case 0x20: |
289 | if (size == 4) { | |
290 | retval = d->timing_reg; | |
291 | } | |
b8842209 | 292 | break; |
5abdf670 MCA |
293 | case 0x30: |
294 | /* This is an interrupt state register that only exists | |
295 | * in the KeyLargo and later variants. Bit 0x8000_0000 | |
296 | * latches the DMA interrupt and has to be written to | |
297 | * clear. Bit 0x4000_0000 is an image of the disk | |
298 | * interrupt. MacOS X relies on this and will hang if | |
299 | * we don't provide at least the disk interrupt | |
300 | */ | |
301 | if (size == 4) { | |
302 | retval = d->irq_reg; | |
303 | } | |
b8842209 GH |
304 | break; |
305 | } | |
b8842209 | 306 | |
b8842209 GH |
307 | return retval; |
308 | } | |
309 | ||
b8842209 | 310 | |
5abdf670 MCA |
311 | static void pmac_ide_write(void *opaque, hwaddr addr, uint64_t val, |
312 | unsigned size) | |
b8842209 | 313 | { |
b8842209 | 314 | MACIOIDEState *d = opaque; |
5abdf670 MCA |
315 | int reg = addr >> 4; |
316 | ||
317 | switch (reg) { | |
318 | case 0x0: | |
319 | if (size == 2) { | |
320 | ide_data_writew(&d->bus, 0, val); | |
321 | } else if (size == 4) { | |
322 | ide_data_writel(&d->bus, 0, val); | |
323 | } | |
324 | break; | |
325 | case 0x1 ... 0x7: | |
326 | if (size == 1) { | |
327 | ide_ioport_write(&d->bus, reg, val); | |
328 | } | |
329 | break; | |
330 | case 0x8: | |
331 | case 0x16: | |
332 | if (size == 1) { | |
98d98912 | 333 | ide_ctrl_write(&d->bus, 0, val); |
5abdf670 MCA |
334 | } |
335 | break; | |
336 | case 0x20: | |
337 | if (size == 4) { | |
338 | d->timing_reg = val; | |
339 | } | |
340 | break; | |
341 | case 0x30: | |
342 | if (size == 4) { | |
343 | if (val & 0x80000000u) { | |
344 | d->irq_reg &= 0x7fffffff; | |
345 | } | |
346 | } | |
347 | break; | |
b8842209 | 348 | } |
b8842209 GH |
349 | } |
350 | ||
a348f108 | 351 | static const MemoryRegionOps pmac_ide_ops = { |
5abdf670 MCA |
352 | .read = pmac_ide_read, |
353 | .write = pmac_ide_write, | |
354 | .valid.min_access_size = 1, | |
355 | .valid.max_access_size = 4, | |
356 | .endianness = DEVICE_LITTLE_ENDIAN, | |
b8842209 GH |
357 | }; |
358 | ||
44bfa332 JQ |
359 | static const VMStateDescription vmstate_pmac = { |
360 | .name = "ide", | |
c2a0125a | 361 | .version_id = 5, |
44bfa332 | 362 | .minimum_version_id = 0, |
35d08458 | 363 | .fields = (VMStateField[]) { |
44bfa332 JQ |
364 | VMSTATE_IDE_BUS(bus, MACIOIDEState), |
365 | VMSTATE_IDE_DRIVES(bus.ifs, MACIOIDEState), | |
bb37a8e8 | 366 | VMSTATE_BOOL(dma_active, MACIOIDEState), |
c2a0125a MCA |
367 | VMSTATE_UINT32(timing_reg, MACIOIDEState), |
368 | VMSTATE_UINT32(irq_reg, MACIOIDEState), | |
44bfa332 | 369 | VMSTATE_END_OF_LIST() |
b8842209 | 370 | } |
44bfa332 | 371 | }; |
b8842209 | 372 | |
07a7484e | 373 | static void macio_ide_reset(DeviceState *dev) |
b8842209 | 374 | { |
07a7484e | 375 | MACIOIDEState *d = MACIO_IDE(dev); |
b8842209 | 376 | |
4a643563 | 377 | ide_bus_reset(&d->bus); |
b8842209 GH |
378 | } |
379 | ||
ae0cebd7 | 380 | static int ide_nop_int(const IDEDMA *dma, bool is_write) |
4aa3510f AG |
381 | { |
382 | return 0; | |
383 | } | |
384 | ||
ae0cebd7 | 385 | static int32_t ide_nop_int32(const IDEDMA *dma, int32_t l) |
3251bdcf JS |
386 | { |
387 | return 0; | |
388 | } | |
389 | ||
ae0cebd7 | 390 | static void ide_dbdma_start(const IDEDMA *dma, IDEState *s, |
097310b5 | 391 | BlockCompletionFunc *cb) |
4aa3510f AG |
392 | { |
393 | MACIOIDEState *m = container_of(dma, MACIOIDEState, dma); | |
4827ac1e | 394 | |
bd4214fc | 395 | s->io_buffer_index = 0; |
4827ac1e | 396 | if (s->drive_kind == IDE_CD) { |
4827ac1e | 397 | s->io_buffer_size = s->packet_transfer_size; |
bd4214fc | 398 | } else { |
b01d44cd | 399 | s->io_buffer_size = s->nsector * BDRV_SECTOR_SIZE; |
bd4214fc | 400 | } |
4827ac1e | 401 | |
bd4214fc MCA |
402 | MACIO_DPRINTF("\n\n------------ IDE transfer\n"); |
403 | MACIO_DPRINTF("buffer_size: %x buffer_index: %x\n", | |
404 | s->io_buffer_size, s->io_buffer_index); | |
405 | MACIO_DPRINTF("lba: %x size: %x\n", s->lba, s->io_buffer_size); | |
406 | MACIO_DPRINTF("-------------------------\n"); | |
4827ac1e | 407 | |
cae32357 | 408 | m->dma_active = true; |
4aa3510f AG |
409 | DBDMA_kick(m->dbdma); |
410 | } | |
411 | ||
412 | static const IDEDMAOps dbdma_ops = { | |
413 | .start_dma = ide_dbdma_start, | |
3251bdcf | 414 | .prepare_buf = ide_nop_int32, |
4aa3510f | 415 | .rw_buf = ide_nop_int, |
4aa3510f AG |
416 | }; |
417 | ||
07a7484e | 418 | static void macio_ide_realizefn(DeviceState *dev, Error **errp) |
b8842209 | 419 | { |
07a7484e AF |
420 | MACIOIDEState *s = MACIO_IDE(dev); |
421 | ||
4f7265ff | 422 | ide_init2(&s->bus, s->ide_irq); |
4aa3510f AG |
423 | |
424 | /* Register DMA callbacks */ | |
425 | s->dma.ops = &dbdma_ops; | |
426 | s->bus.dma = &s->dma; | |
07a7484e AF |
427 | } |
428 | ||
4f7265ff BH |
429 | static void pmac_ide_irq(void *opaque, int n, int level) |
430 | { | |
431 | MACIOIDEState *s = opaque; | |
432 | uint32_t mask = 0x80000000u >> n; | |
433 | ||
434 | /* We need to reflect the IRQ state in the irq register */ | |
435 | if (level) { | |
436 | s->irq_reg |= mask; | |
437 | } else { | |
438 | s->irq_reg &= ~mask; | |
439 | } | |
440 | ||
441 | if (n) { | |
442 | qemu_set_irq(s->real_ide_irq, level); | |
443 | } else { | |
444 | qemu_set_irq(s->real_dma_irq, level); | |
445 | } | |
446 | } | |
447 | ||
07a7484e AF |
448 | static void macio_ide_initfn(Object *obj) |
449 | { | |
450 | SysBusDevice *d = SYS_BUS_DEVICE(obj); | |
451 | MACIOIDEState *s = MACIO_IDE(obj); | |
452 | ||
82c74ac4 | 453 | ide_bus_init(&s->bus, sizeof(s->bus), DEVICE(obj), 0, 2); |
1437c94b | 454 | memory_region_init_io(&s->mem, obj, &pmac_ide_ops, s, "pmac-ide", 0x1000); |
07a7484e | 455 | sysbus_init_mmio(d, &s->mem); |
4f7265ff BH |
456 | sysbus_init_irq(d, &s->real_ide_irq); |
457 | sysbus_init_irq(d, &s->real_dma_irq); | |
458 | s->dma_irq = qemu_allocate_irq(pmac_ide_irq, s, 0); | |
459 | s->ide_irq = qemu_allocate_irq(pmac_ide_irq, s, 1); | |
e451b85f MCA |
460 | |
461 | object_property_add_link(obj, "dbdma", TYPE_MAC_DBDMA, | |
462 | (Object **) &s->dbdma, | |
d2623129 | 463 | qdev_prop_allow_set_link_before_realize, 0); |
07a7484e AF |
464 | } |
465 | ||
0fc84331 MCA |
466 | static Property macio_ide_properties[] = { |
467 | DEFINE_PROP_UINT32("channel", MACIOIDEState, channel, 0), | |
5c8e3d17 | 468 | DEFINE_PROP_UINT32("addr", MACIOIDEState, addr, -1), |
0fc84331 MCA |
469 | DEFINE_PROP_END_OF_LIST(), |
470 | }; | |
471 | ||
07a7484e AF |
472 | static void macio_ide_class_init(ObjectClass *oc, void *data) |
473 | { | |
474 | DeviceClass *dc = DEVICE_CLASS(oc); | |
475 | ||
476 | dc->realize = macio_ide_realizefn; | |
477 | dc->reset = macio_ide_reset; | |
4f67d30b | 478 | device_class_set_props(dc, macio_ide_properties); |
07a7484e | 479 | dc->vmsd = &vmstate_pmac; |
3469d9bc | 480 | set_bit(DEVICE_CATEGORY_STORAGE, dc->categories); |
07a7484e | 481 | } |
b8842209 | 482 | |
07a7484e AF |
483 | static const TypeInfo macio_ide_type_info = { |
484 | .name = TYPE_MACIO_IDE, | |
485 | .parent = TYPE_SYS_BUS_DEVICE, | |
486 | .instance_size = sizeof(MACIOIDEState), | |
487 | .instance_init = macio_ide_initfn, | |
488 | .class_init = macio_ide_class_init, | |
489 | }; | |
b8842209 | 490 | |
07a7484e AF |
491 | static void macio_ide_register_types(void) |
492 | { | |
493 | type_register_static(&macio_ide_type_info); | |
494 | } | |
b8842209 | 495 | |
14eefd0e | 496 | /* hd_table must contain 2 block drivers */ |
07a7484e AF |
497 | void macio_ide_init_drives(MACIOIDEState *s, DriveInfo **hd_table) |
498 | { | |
499 | int i; | |
b8842209 | 500 | |
07a7484e AF |
501 | for (i = 0; i < 2; i++) { |
502 | if (hd_table[i]) { | |
503 | ide_create_drive(&s->bus, i, hd_table[i]); | |
504 | } | |
505 | } | |
b8842209 | 506 | } |
07a7484e | 507 | |
e451b85f | 508 | void macio_ide_register_dma(MACIOIDEState *s) |
07a7484e | 509 | { |
e451b85f | 510 | DBDMA_register_channel(s->dbdma, s->channel, s->dma_irq, |
07a7484e AF |
511 | pmac_ide_transfer, pmac_ide_flush, s); |
512 | } | |
513 | ||
514 | type_init(macio_ide_register_types) |