2 * QEMU IDE Emulation: MacIO support.
4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2006 Openedhand Ltd.
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:
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
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
26 #include "hw/ppc/mac.h"
27 #include "hw/ppc/mac_dbdma.h"
28 #include "block/block.h"
29 #include "sysemu/dma.h"
31 #include <hw/ide/internal.h>
33 /***********************************************************/
34 /* MacIO based PowerPC IDE */
36 #define MACIO_PAGE_SIZE 4096
38 static void pmac_ide_atapi_transfer_cb(void *opaque
, int ret
)
40 DBDMA_io
*io
= opaque
;
41 MACIOIDEState
*m
= io
->opaque
;
42 IDEState
*s
= idebus_active_if(&m
->bus
);
46 qemu_sglist_destroy(&s
->sg
);
47 ide_atapi_io_error(s
, ret
);
51 if (s
->io_buffer_size
> 0) {
53 qemu_sglist_destroy(&s
->sg
);
55 s
->packet_transfer_size
-= s
->io_buffer_size
;
57 s
->io_buffer_index
+= s
->io_buffer_size
;
58 s
->lba
+= s
->io_buffer_index
>> 11;
59 s
->io_buffer_index
&= 0x7ff;
62 if (s
->packet_transfer_size
<= 0)
69 /* launch next transfer */
71 s
->io_buffer_size
= io
->len
;
73 qemu_sglist_init(&s
->sg
, io
->len
/ MACIO_PAGE_SIZE
+ 1,
75 qemu_sglist_add(&s
->sg
, io
->addr
, io
->len
);
79 m
->aiocb
= dma_bdrv_read(s
->bs
, &s
->sg
,
80 (int64_t)(s
->lba
<< 2) + (s
->io_buffer_index
>> 9),
81 pmac_ide_atapi_transfer_cb
, io
);
85 bdrv_acct_done(s
->bs
, &s
->acct
);
89 static void pmac_ide_transfer_cb(void *opaque
, int ret
)
91 DBDMA_io
*io
= opaque
;
92 MACIOIDEState
*m
= io
->opaque
;
93 IDEState
*s
= idebus_active_if(&m
->bus
);
99 qemu_sglist_destroy(&s
->sg
);
104 sector_num
= ide_get_sector(s
);
105 if (s
->io_buffer_size
> 0) {
107 qemu_sglist_destroy(&s
->sg
);
108 n
= (s
->io_buffer_size
+ 0x1ff) >> 9;
110 ide_set_sector(s
, sector_num
);
114 /* end of transfer ? */
115 if (s
->nsector
== 0) {
116 s
->status
= READY_STAT
| SEEK_STAT
;
125 /* launch next transfer */
127 s
->io_buffer_index
= 0;
128 s
->io_buffer_size
= io
->len
;
130 qemu_sglist_init(&s
->sg
, io
->len
/ MACIO_PAGE_SIZE
+ 1,
131 &dma_context_memory
);
132 qemu_sglist_add(&s
->sg
, io
->addr
, io
->len
);
136 switch (s
->dma_cmd
) {
138 m
->aiocb
= dma_bdrv_read(s
->bs
, &s
->sg
, sector_num
,
139 pmac_ide_transfer_cb
, io
);
142 m
->aiocb
= dma_bdrv_write(s
->bs
, &s
->sg
, sector_num
,
143 pmac_ide_transfer_cb
, io
);
146 m
->aiocb
= dma_bdrv_io(s
->bs
, &s
->sg
, sector_num
,
147 ide_issue_trim
, pmac_ide_transfer_cb
, s
,
148 DMA_DIRECTION_TO_DEVICE
);
154 if (s
->dma_cmd
== IDE_DMA_READ
|| s
->dma_cmd
== IDE_DMA_WRITE
) {
155 bdrv_acct_done(s
->bs
, &s
->acct
);
160 static void pmac_ide_transfer(DBDMA_io
*io
)
162 MACIOIDEState
*m
= io
->opaque
;
163 IDEState
*s
= idebus_active_if(&m
->bus
);
165 s
->io_buffer_size
= 0;
166 if (s
->drive_kind
== IDE_CD
) {
167 bdrv_acct_start(s
->bs
, &s
->acct
, io
->len
, BDRV_ACCT_READ
);
168 pmac_ide_atapi_transfer_cb(io
, 0);
172 switch (s
->dma_cmd
) {
174 bdrv_acct_start(s
->bs
, &s
->acct
, io
->len
, BDRV_ACCT_READ
);
177 bdrv_acct_start(s
->bs
, &s
->acct
, io
->len
, BDRV_ACCT_WRITE
);
183 pmac_ide_transfer_cb(io
, 0);
186 static void pmac_ide_flush(DBDMA_io
*io
)
188 MACIOIDEState
*m
= io
->opaque
;
195 /* PowerMac IDE memory IO */
196 static void pmac_ide_writeb (void *opaque
,
197 hwaddr addr
, uint32_t val
)
199 MACIOIDEState
*d
= opaque
;
201 addr
= (addr
& 0xFFF) >> 4;
204 ide_ioport_write(&d
->bus
, addr
, val
);
208 ide_cmd_write(&d
->bus
, 0, val
);
215 static uint32_t pmac_ide_readb (void *opaque
,hwaddr addr
)
218 MACIOIDEState
*d
= opaque
;
220 addr
= (addr
& 0xFFF) >> 4;
223 retval
= ide_ioport_read(&d
->bus
, addr
);
227 retval
= ide_status_read(&d
->bus
, 0);
236 static void pmac_ide_writew (void *opaque
,
237 hwaddr addr
, uint32_t val
)
239 MACIOIDEState
*d
= opaque
;
241 addr
= (addr
& 0xFFF) >> 4;
244 ide_data_writew(&d
->bus
, 0, val
);
248 static uint32_t pmac_ide_readw (void *opaque
,hwaddr addr
)
251 MACIOIDEState
*d
= opaque
;
253 addr
= (addr
& 0xFFF) >> 4;
255 retval
= ide_data_readw(&d
->bus
, 0);
259 retval
= bswap16(retval
);
263 static void pmac_ide_writel (void *opaque
,
264 hwaddr addr
, uint32_t val
)
266 MACIOIDEState
*d
= opaque
;
268 addr
= (addr
& 0xFFF) >> 4;
271 ide_data_writel(&d
->bus
, 0, val
);
275 static uint32_t pmac_ide_readl (void *opaque
,hwaddr addr
)
278 MACIOIDEState
*d
= opaque
;
280 addr
= (addr
& 0xFFF) >> 4;
282 retval
= ide_data_readl(&d
->bus
, 0);
286 retval
= bswap32(retval
);
290 static const MemoryRegionOps pmac_ide_ops
= {
303 .endianness
= DEVICE_NATIVE_ENDIAN
,
306 static const VMStateDescription vmstate_pmac
= {
309 .minimum_version_id
= 0,
310 .minimum_version_id_old
= 0,
311 .fields
= (VMStateField
[]) {
312 VMSTATE_IDE_BUS(bus
, MACIOIDEState
),
313 VMSTATE_IDE_DRIVES(bus
.ifs
, MACIOIDEState
),
314 VMSTATE_END_OF_LIST()
318 static void macio_ide_reset(DeviceState
*dev
)
320 MACIOIDEState
*d
= MACIO_IDE(dev
);
322 ide_bus_reset(&d
->bus
);
325 static void macio_ide_realizefn(DeviceState
*dev
, Error
**errp
)
327 MACIOIDEState
*s
= MACIO_IDE(dev
);
329 ide_init2(&s
->bus
, s
->irq
);
332 static void macio_ide_initfn(Object
*obj
)
334 SysBusDevice
*d
= SYS_BUS_DEVICE(obj
);
335 MACIOIDEState
*s
= MACIO_IDE(obj
);
337 ide_bus_new(&s
->bus
, DEVICE(obj
), 0);
338 memory_region_init_io(&s
->mem
, &pmac_ide_ops
, s
, "pmac-ide", 0x1000);
339 sysbus_init_mmio(d
, &s
->mem
);
340 sysbus_init_irq(d
, &s
->irq
);
341 sysbus_init_irq(d
, &s
->dma_irq
);
344 static void macio_ide_class_init(ObjectClass
*oc
, void *data
)
346 DeviceClass
*dc
= DEVICE_CLASS(oc
);
348 dc
->realize
= macio_ide_realizefn
;
349 dc
->reset
= macio_ide_reset
;
350 dc
->vmsd
= &vmstate_pmac
;
353 static const TypeInfo macio_ide_type_info
= {
354 .name
= TYPE_MACIO_IDE
,
355 .parent
= TYPE_SYS_BUS_DEVICE
,
356 .instance_size
= sizeof(MACIOIDEState
),
357 .instance_init
= macio_ide_initfn
,
358 .class_init
= macio_ide_class_init
,
361 static void macio_ide_register_types(void)
363 type_register_static(&macio_ide_type_info
);
366 /* hd_table must contain 4 block drivers */
367 void macio_ide_init_drives(MACIOIDEState
*s
, DriveInfo
**hd_table
)
371 for (i
= 0; i
< 2; i
++) {
373 ide_create_drive(&s
->bus
, i
, hd_table
[i
]);
378 void macio_ide_register_dma(MACIOIDEState
*s
, void *dbdma
, int channel
)
380 DBDMA_register_channel(dbdma
, channel
, s
->dma_irq
,
381 pmac_ide_transfer
, pmac_ide_flush
, s
);
384 type_init(macio_ide_register_types
)