Annotation of qemu/hw/ide/macio.c, revision 1.1.1.1

1.1       root        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/mac_dbdma.h>
                     28: #include "block.h"
                     29: #include "block_int.h"
                     30: #include "sysemu.h"
                     31: #include "dma.h"
                     32: 
                     33: #include <hw/ide/internal.h>
                     34: 
                     35: /***********************************************************/
                     36: /* MacIO based PowerPC IDE */
                     37: 
                     38: typedef struct MACIOIDEState {
                     39:     IDEBus bus;
                     40:     BlockDriverAIOCB *aiocb;
                     41: } MACIOIDEState;
                     42: 
                     43: static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
                     44: {
                     45:     DBDMA_io *io = opaque;
                     46:     MACIOIDEState *m = io->opaque;
                     47:     IDEState *s = idebus_active_if(&m->bus);
                     48: 
                     49:     if (ret < 0) {
                     50:         m->aiocb = NULL;
                     51:         qemu_sglist_destroy(&s->sg);
                     52:         ide_atapi_io_error(s, ret);
                     53:         io->dma_end(opaque);
                     54:         return;
                     55:     }
                     56: 
                     57:     if (s->io_buffer_size > 0) {
                     58:         m->aiocb = NULL;
                     59:         qemu_sglist_destroy(&s->sg);
                     60: 
                     61:         s->packet_transfer_size -= s->io_buffer_size;
                     62: 
                     63:         s->io_buffer_index += s->io_buffer_size;
                     64:        s->lba += s->io_buffer_index >> 11;
                     65:         s->io_buffer_index &= 0x7ff;
                     66:     }
                     67: 
                     68:     if (s->packet_transfer_size <= 0)
                     69:         ide_atapi_cmd_ok(s);
                     70: 
                     71:     if (io->len == 0) {
                     72:         io->dma_end(opaque);
                     73:         return;
                     74:     }
                     75: 
                     76:     /* launch next transfer */
                     77: 
                     78:     s->io_buffer_size = io->len;
                     79: 
                     80:     qemu_sglist_init(&s->sg, io->len / TARGET_PAGE_SIZE + 1);
                     81:     qemu_sglist_add(&s->sg, io->addr, io->len);
                     82:     io->addr += io->len;
                     83:     io->len = 0;
                     84: 
                     85:     m->aiocb = dma_bdrv_read(s->bs, &s->sg,
                     86:                              (int64_t)(s->lba << 2) + (s->io_buffer_index >> 9),
                     87:                              pmac_ide_atapi_transfer_cb, io);
                     88:     if (!m->aiocb) {
                     89:         qemu_sglist_destroy(&s->sg);
                     90:         /* Note: media not present is the most likely case */
                     91:         ide_atapi_cmd_error(s, SENSE_NOT_READY,
                     92:                             ASC_MEDIUM_NOT_PRESENT);
                     93:         io->dma_end(opaque);
                     94:         return;
                     95:     }
                     96: }
                     97: 
                     98: static void pmac_ide_transfer_cb(void *opaque, int ret)
                     99: {
                    100:     DBDMA_io *io = opaque;
                    101:     MACIOIDEState *m = io->opaque;
                    102:     IDEState *s = idebus_active_if(&m->bus);
                    103:     int n;
                    104:     int64_t sector_num;
                    105: 
                    106:     if (ret < 0) {
                    107:         m->aiocb = NULL;
                    108:         qemu_sglist_destroy(&s->sg);
                    109:        ide_dma_error(s);
                    110:         io->dma_end(io);
                    111:         return;
                    112:     }
                    113: 
                    114:     sector_num = ide_get_sector(s);
                    115:     if (s->io_buffer_size > 0) {
                    116:         m->aiocb = NULL;
                    117:         qemu_sglist_destroy(&s->sg);
                    118:         n = (s->io_buffer_size + 0x1ff) >> 9;
                    119:         sector_num += n;
                    120:         ide_set_sector(s, sector_num);
                    121:         s->nsector -= n;
                    122:     }
                    123: 
                    124:     /* end of transfer ? */
                    125:     if (s->nsector == 0) {
                    126:         s->status = READY_STAT | SEEK_STAT;
                    127:         ide_set_irq(s->bus);
                    128:     }
                    129: 
                    130:     /* end of DMA ? */
                    131: 
                    132:     if (io->len == 0) {
                    133:         io->dma_end(io);
                    134:        return;
                    135:     }
                    136: 
                    137:     /* launch next transfer */
                    138: 
                    139:     s->io_buffer_index = 0;
                    140:     s->io_buffer_size = io->len;
                    141: 
                    142:     qemu_sglist_init(&s->sg, io->len / TARGET_PAGE_SIZE + 1);
                    143:     qemu_sglist_add(&s->sg, io->addr, io->len);
                    144:     io->addr += io->len;
                    145:     io->len = 0;
                    146: 
                    147:     if (s->is_read)
                    148:         m->aiocb = dma_bdrv_read(s->bs, &s->sg, sector_num,
                    149:                                 pmac_ide_transfer_cb, io);
                    150:     else
                    151:         m->aiocb = dma_bdrv_write(s->bs, &s->sg, sector_num,
                    152:                                  pmac_ide_transfer_cb, io);
                    153:     if (!m->aiocb)
                    154:         pmac_ide_transfer_cb(io, -1);
                    155: }
                    156: 
                    157: static void pmac_ide_transfer(DBDMA_io *io)
                    158: {
                    159:     MACIOIDEState *m = io->opaque;
                    160:     IDEState *s = idebus_active_if(&m->bus);
                    161: 
                    162:     s->io_buffer_size = 0;
                    163:     if (s->is_cdrom) {
                    164:         pmac_ide_atapi_transfer_cb(io, 0);
                    165:         return;
                    166:     }
                    167: 
                    168:     pmac_ide_transfer_cb(io, 0);
                    169: }
                    170: 
                    171: static void pmac_ide_flush(DBDMA_io *io)
                    172: {
                    173:     MACIOIDEState *m = io->opaque;
                    174: 
                    175:     if (m->aiocb)
                    176:         qemu_aio_flush();
                    177: }
                    178: 
                    179: /* PowerMac IDE memory IO */
                    180: static void pmac_ide_writeb (void *opaque,
                    181:                              target_phys_addr_t addr, uint32_t val)
                    182: {
                    183:     MACIOIDEState *d = opaque;
                    184: 
                    185:     addr = (addr & 0xFFF) >> 4;
                    186:     switch (addr) {
                    187:     case 1 ... 7:
                    188:         ide_ioport_write(&d->bus, addr, val);
                    189:         break;
                    190:     case 8:
                    191:     case 22:
                    192:         ide_cmd_write(&d->bus, 0, val);
                    193:         break;
                    194:     default:
                    195:         break;
                    196:     }
                    197: }
                    198: 
                    199: static uint32_t pmac_ide_readb (void *opaque,target_phys_addr_t addr)
                    200: {
                    201:     uint8_t retval;
                    202:     MACIOIDEState *d = opaque;
                    203: 
                    204:     addr = (addr & 0xFFF) >> 4;
                    205:     switch (addr) {
                    206:     case 1 ... 7:
                    207:         retval = ide_ioport_read(&d->bus, addr);
                    208:         break;
                    209:     case 8:
                    210:     case 22:
                    211:         retval = ide_status_read(&d->bus, 0);
                    212:         break;
                    213:     default:
                    214:         retval = 0xFF;
                    215:         break;
                    216:     }
                    217:     return retval;
                    218: }
                    219: 
                    220: static void pmac_ide_writew (void *opaque,
                    221:                              target_phys_addr_t addr, uint32_t val)
                    222: {
                    223:     MACIOIDEState *d = opaque;
                    224: 
                    225:     addr = (addr & 0xFFF) >> 4;
                    226: #ifdef TARGET_WORDS_BIGENDIAN
                    227:     val = bswap16(val);
                    228: #endif
                    229:     if (addr == 0) {
                    230:         ide_data_writew(&d->bus, 0, val);
                    231:     }
                    232: }
                    233: 
                    234: static uint32_t pmac_ide_readw (void *opaque,target_phys_addr_t addr)
                    235: {
                    236:     uint16_t retval;
                    237:     MACIOIDEState *d = opaque;
                    238: 
                    239:     addr = (addr & 0xFFF) >> 4;
                    240:     if (addr == 0) {
                    241:         retval = ide_data_readw(&d->bus, 0);
                    242:     } else {
                    243:         retval = 0xFFFF;
                    244:     }
                    245: #ifdef TARGET_WORDS_BIGENDIAN
                    246:     retval = bswap16(retval);
                    247: #endif
                    248:     return retval;
                    249: }
                    250: 
                    251: static void pmac_ide_writel (void *opaque,
                    252:                              target_phys_addr_t addr, uint32_t val)
                    253: {
                    254:     MACIOIDEState *d = opaque;
                    255: 
                    256:     addr = (addr & 0xFFF) >> 4;
                    257: #ifdef TARGET_WORDS_BIGENDIAN
                    258:     val = bswap32(val);
                    259: #endif
                    260:     if (addr == 0) {
                    261:         ide_data_writel(&d->bus, 0, val);
                    262:     }
                    263: }
                    264: 
                    265: static uint32_t pmac_ide_readl (void *opaque,target_phys_addr_t addr)
                    266: {
                    267:     uint32_t retval;
                    268:     MACIOIDEState *d = opaque;
                    269: 
                    270:     addr = (addr & 0xFFF) >> 4;
                    271:     if (addr == 0) {
                    272:         retval = ide_data_readl(&d->bus, 0);
                    273:     } else {
                    274:         retval = 0xFFFFFFFF;
                    275:     }
                    276: #ifdef TARGET_WORDS_BIGENDIAN
                    277:     retval = bswap32(retval);
                    278: #endif
                    279:     return retval;
                    280: }
                    281: 
                    282: static CPUWriteMemoryFunc * const pmac_ide_write[] = {
                    283:     pmac_ide_writeb,
                    284:     pmac_ide_writew,
                    285:     pmac_ide_writel,
                    286: };
                    287: 
                    288: static CPUReadMemoryFunc * const pmac_ide_read[] = {
                    289:     pmac_ide_readb,
                    290:     pmac_ide_readw,
                    291:     pmac_ide_readl,
                    292: };
                    293: 
                    294: static const VMStateDescription vmstate_pmac = {
                    295:     .name = "ide",
                    296:     .version_id = 3,
                    297:     .minimum_version_id = 0,
                    298:     .minimum_version_id_old = 0,
                    299:     .fields      = (VMStateField []) {
                    300:         VMSTATE_IDE_BUS(bus, MACIOIDEState),
                    301:         VMSTATE_IDE_DRIVES(bus.ifs, MACIOIDEState),
                    302:         VMSTATE_END_OF_LIST()
                    303:     }
                    304: };
                    305: 
                    306: static void pmac_ide_reset(void *opaque)
                    307: {
                    308:     MACIOIDEState *d = opaque;
                    309: 
                    310:     ide_bus_reset(&d->bus);
                    311: }
                    312: 
                    313: /* hd_table must contain 4 block drivers */
                    314: /* PowerMac uses memory mapped registers, not I/O. Return the memory
                    315:    I/O index to access the ide. */
                    316: int pmac_ide_init (DriveInfo **hd_table, qemu_irq irq,
                    317:                   void *dbdma, int channel, qemu_irq dma_irq)
                    318: {
                    319:     MACIOIDEState *d;
                    320:     int pmac_ide_memory;
                    321: 
                    322:     d = qemu_mallocz(sizeof(MACIOIDEState));
                    323:     ide_init2(&d->bus, hd_table[0], hd_table[1], irq);
                    324: 
                    325:     if (dbdma)
                    326:         DBDMA_register_channel(dbdma, channel, dma_irq, pmac_ide_transfer, pmac_ide_flush, d);
                    327: 
                    328:     pmac_ide_memory = cpu_register_io_memory(pmac_ide_read,
                    329:                                              pmac_ide_write, d);
                    330:     vmstate_register(0, &vmstate_pmac, d);
                    331:     qemu_register_reset(pmac_ide_reset, d);
                    332: 
                    333:     return pmac_ide_memory;
                    334: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.