xref: /openbmc/qemu/hw/ide/macio.c (revision 6683d7bc)
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  */
25 #include "hw/hw.h"
26 #include "hw/ppc/mac.h"
27 #include "hw/ppc/mac_dbdma.h"
28 #include "block/block.h"
29 #include "sysemu/dma.h"
30 
31 #include <hw/ide/internal.h>
32 
33 /***********************************************************/
34 /* MacIO based PowerPC IDE */
35 
36 #define MACIO_PAGE_SIZE 4096
37 
38 static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
39 {
40     DBDMA_io *io = opaque;
41     MACIOIDEState *m = io->opaque;
42     IDEState *s = idebus_active_if(&m->bus);
43 
44     if (ret < 0) {
45         m->aiocb = NULL;
46         qemu_sglist_destroy(&s->sg);
47         ide_atapi_io_error(s, ret);
48         goto done;
49     }
50 
51     if (s->io_buffer_size > 0) {
52         m->aiocb = NULL;
53         qemu_sglist_destroy(&s->sg);
54 
55         s->packet_transfer_size -= s->io_buffer_size;
56 
57         s->io_buffer_index += s->io_buffer_size;
58 	s->lba += s->io_buffer_index >> 11;
59         s->io_buffer_index &= 0x7ff;
60     }
61 
62     if (s->packet_transfer_size <= 0)
63         ide_atapi_cmd_ok(s);
64 
65     if (io->len == 0) {
66         goto done;
67     }
68 
69     /* launch next transfer */
70 
71     s->io_buffer_size = io->len;
72 
73     qemu_sglist_init(&s->sg, io->len / MACIO_PAGE_SIZE + 1,
74                      &dma_context_memory);
75     qemu_sglist_add(&s->sg, io->addr, io->len);
76     io->addr += io->len;
77     io->len = 0;
78 
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);
82     return;
83 
84 done:
85     bdrv_acct_done(s->bs, &s->acct);
86     io->dma_end(opaque);
87 }
88 
89 static void pmac_ide_transfer_cb(void *opaque, int ret)
90 {
91     DBDMA_io *io = opaque;
92     MACIOIDEState *m = io->opaque;
93     IDEState *s = idebus_active_if(&m->bus);
94     int n;
95     int64_t sector_num;
96 
97     if (ret < 0) {
98         m->aiocb = NULL;
99         qemu_sglist_destroy(&s->sg);
100 	ide_dma_error(s);
101         goto done;
102     }
103 
104     sector_num = ide_get_sector(s);
105     if (s->io_buffer_size > 0) {
106         m->aiocb = NULL;
107         qemu_sglist_destroy(&s->sg);
108         n = (s->io_buffer_size + 0x1ff) >> 9;
109         sector_num += n;
110         ide_set_sector(s, sector_num);
111         s->nsector -= n;
112     }
113 
114     /* end of transfer ? */
115     if (s->nsector == 0) {
116         s->status = READY_STAT | SEEK_STAT;
117         ide_set_irq(s->bus);
118     }
119 
120     /* end of DMA ? */
121     if (io->len == 0) {
122         goto done;
123     }
124 
125     /* launch next transfer */
126 
127     s->io_buffer_index = 0;
128     s->io_buffer_size = io->len;
129 
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);
133     io->addr += io->len;
134     io->len = 0;
135 
136     switch (s->dma_cmd) {
137     case IDE_DMA_READ:
138         m->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num,
139 		                 pmac_ide_transfer_cb, io);
140         break;
141     case IDE_DMA_WRITE:
142         m->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num,
143 		                  pmac_ide_transfer_cb, io);
144         break;
145     case IDE_DMA_TRIM:
146         m->aiocb = dma_bdrv_io(s->bs, &s->sg, sector_num,
147                                ide_issue_trim, pmac_ide_transfer_cb, io,
148                                DMA_DIRECTION_TO_DEVICE);
149         break;
150     }
151     return;
152 
153 done:
154     if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) {
155         bdrv_acct_done(s->bs, &s->acct);
156     }
157     io->dma_end(io);
158 }
159 
160 static void pmac_ide_transfer(DBDMA_io *io)
161 {
162     MACIOIDEState *m = io->opaque;
163     IDEState *s = idebus_active_if(&m->bus);
164 
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);
169         return;
170     }
171 
172     switch (s->dma_cmd) {
173     case IDE_DMA_READ:
174         bdrv_acct_start(s->bs, &s->acct, io->len, BDRV_ACCT_READ);
175         break;
176     case IDE_DMA_WRITE:
177         bdrv_acct_start(s->bs, &s->acct, io->len, BDRV_ACCT_WRITE);
178         break;
179     default:
180         break;
181     }
182 
183     pmac_ide_transfer_cb(io, 0);
184 }
185 
186 static void pmac_ide_flush(DBDMA_io *io)
187 {
188     MACIOIDEState *m = io->opaque;
189 
190     if (m->aiocb) {
191         bdrv_drain_all();
192     }
193 }
194 
195 /* PowerMac IDE memory IO */
196 static void pmac_ide_writeb (void *opaque,
197                              hwaddr addr, uint32_t val)
198 {
199     MACIOIDEState *d = opaque;
200 
201     addr = (addr & 0xFFF) >> 4;
202     switch (addr) {
203     case 1 ... 7:
204         ide_ioport_write(&d->bus, addr, val);
205         break;
206     case 8:
207     case 22:
208         ide_cmd_write(&d->bus, 0, val);
209         break;
210     default:
211         break;
212     }
213 }
214 
215 static uint32_t pmac_ide_readb (void *opaque,hwaddr addr)
216 {
217     uint8_t retval;
218     MACIOIDEState *d = opaque;
219 
220     addr = (addr & 0xFFF) >> 4;
221     switch (addr) {
222     case 1 ... 7:
223         retval = ide_ioport_read(&d->bus, addr);
224         break;
225     case 8:
226     case 22:
227         retval = ide_status_read(&d->bus, 0);
228         break;
229     default:
230         retval = 0xFF;
231         break;
232     }
233     return retval;
234 }
235 
236 static void pmac_ide_writew (void *opaque,
237                              hwaddr addr, uint32_t val)
238 {
239     MACIOIDEState *d = opaque;
240 
241     addr = (addr & 0xFFF) >> 4;
242     val = bswap16(val);
243     if (addr == 0) {
244         ide_data_writew(&d->bus, 0, val);
245     }
246 }
247 
248 static uint32_t pmac_ide_readw (void *opaque,hwaddr addr)
249 {
250     uint16_t retval;
251     MACIOIDEState *d = opaque;
252 
253     addr = (addr & 0xFFF) >> 4;
254     if (addr == 0) {
255         retval = ide_data_readw(&d->bus, 0);
256     } else {
257         retval = 0xFFFF;
258     }
259     retval = bswap16(retval);
260     return retval;
261 }
262 
263 static void pmac_ide_writel (void *opaque,
264                              hwaddr addr, uint32_t val)
265 {
266     MACIOIDEState *d = opaque;
267 
268     addr = (addr & 0xFFF) >> 4;
269     val = bswap32(val);
270     if (addr == 0) {
271         ide_data_writel(&d->bus, 0, val);
272     }
273 }
274 
275 static uint32_t pmac_ide_readl (void *opaque,hwaddr addr)
276 {
277     uint32_t retval;
278     MACIOIDEState *d = opaque;
279 
280     addr = (addr & 0xFFF) >> 4;
281     if (addr == 0) {
282         retval = ide_data_readl(&d->bus, 0);
283     } else {
284         retval = 0xFFFFFFFF;
285     }
286     retval = bswap32(retval);
287     return retval;
288 }
289 
290 static const MemoryRegionOps pmac_ide_ops = {
291     .old_mmio = {
292         .write = {
293             pmac_ide_writeb,
294             pmac_ide_writew,
295             pmac_ide_writel,
296         },
297         .read = {
298             pmac_ide_readb,
299             pmac_ide_readw,
300             pmac_ide_readl,
301         },
302     },
303     .endianness = DEVICE_NATIVE_ENDIAN,
304 };
305 
306 static const VMStateDescription vmstate_pmac = {
307     .name = "ide",
308     .version_id = 3,
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()
315     }
316 };
317 
318 static void macio_ide_reset(DeviceState *dev)
319 {
320     MACIOIDEState *d = MACIO_IDE(dev);
321 
322     ide_bus_reset(&d->bus);
323 }
324 
325 static void macio_ide_realizefn(DeviceState *dev, Error **errp)
326 {
327     MACIOIDEState *s = MACIO_IDE(dev);
328 
329     ide_init2(&s->bus, s->irq);
330 }
331 
332 static void macio_ide_initfn(Object *obj)
333 {
334     SysBusDevice *d = SYS_BUS_DEVICE(obj);
335     MACIOIDEState *s = MACIO_IDE(obj);
336 
337     ide_bus_new(&s->bus, DEVICE(obj), 0, 2);
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);
342 }
343 
344 static void macio_ide_class_init(ObjectClass *oc, void *data)
345 {
346     DeviceClass *dc = DEVICE_CLASS(oc);
347 
348     dc->realize = macio_ide_realizefn;
349     dc->reset = macio_ide_reset;
350     dc->vmsd = &vmstate_pmac;
351 }
352 
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,
359 };
360 
361 static void macio_ide_register_types(void)
362 {
363     type_register_static(&macio_ide_type_info);
364 }
365 
366 /* hd_table must contain 4 block drivers */
367 void macio_ide_init_drives(MACIOIDEState *s, DriveInfo **hd_table)
368 {
369     int i;
370 
371     for (i = 0; i < 2; i++) {
372         if (hd_table[i]) {
373             ide_create_drive(&s->bus, i, hd_table[i]);
374         }
375     }
376 }
377 
378 void macio_ide_register_dma(MACIOIDEState *s, void *dbdma, int channel)
379 {
380     DBDMA_register_channel(dbdma, channel, s->dma_irq,
381                            pmac_ide_transfer, pmac_ide_flush, s);
382 }
383 
384 type_init(macio_ide_register_types)
385