Annotation of qemu/hw/ide/macio.c, revision 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.