Annotation of qemu/hw/mac_dbdma.c, revision 1.1.1.3

1.1       root        1: /*
                      2:  * PowerMac descriptor-based DMA emulation
                      3:  *
                      4:  * Copyright (c) 2005-2007 Fabrice Bellard
                      5:  * Copyright (c) 2007 Jocelyn Mayer
1.1.1.2   root        6:  * Copyright (c) 2009 Laurent Vivier
                      7:  *
                      8:  * some parts from linux-2.6.28, arch/powerpc/include/asm/dbdma.h
                      9:  *
                     10:  *   Definitions for using the Apple Descriptor-Based DMA controller
                     11:  *   in Power Macintosh computers.
                     12:  *
                     13:  *   Copyright (C) 1996 Paul Mackerras.
                     14:  *
                     15:  * some parts from mol 0.9.71
                     16:  *
                     17:  *   Descriptor based DMA emulation
                     18:  *
                     19:  *   Copyright (C) 1998-2004 Samuel Rydh ([email protected])
1.1       root       20:  *
                     21:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                     22:  * of this software and associated documentation files (the "Software"), to deal
                     23:  * in the Software without restriction, including without limitation the rights
                     24:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     25:  * copies of the Software, and to permit persons to whom the Software is
                     26:  * furnished to do so, subject to the following conditions:
                     27:  *
                     28:  * The above copyright notice and this permission notice shall be included in
                     29:  * all copies or substantial portions of the Software.
                     30:  *
                     31:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     32:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     33:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     34:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     35:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     36:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     37:  * THE SOFTWARE.
                     38:  */
                     39: #include "hw.h"
1.1.1.2   root       40: #include "isa.h"
                     41: #include "mac_dbdma.h"
1.1       root       42: 
1.1.1.2   root       43: /* debug DBDMA */
                     44: //#define DEBUG_DBDMA
1.1       root       45: 
1.1.1.2   root       46: #ifdef DEBUG_DBDMA
1.1.1.3 ! root       47: #define DBDMA_DPRINTF(fmt, ...)                                 \
        !            48:     do { printf("DBDMA: " fmt , ## __VA_ARGS__); } while (0)
1.1.1.2   root       49: #else
1.1.1.3 ! root       50: #define DBDMA_DPRINTF(fmt, ...)
1.1.1.2   root       51: #endif
                     52: 
                     53: /*
                     54:  */
                     55: 
                     56: /*
                     57:  * DBDMA control/status registers.  All little-endian.
                     58:  */
                     59: 
                     60: #define DBDMA_CONTROL         0x00
                     61: #define DBDMA_STATUS          0x01
                     62: #define DBDMA_CMDPTR_HI       0x02
                     63: #define DBDMA_CMDPTR_LO       0x03
                     64: #define DBDMA_INTR_SEL        0x04
                     65: #define DBDMA_BRANCH_SEL      0x05
                     66: #define DBDMA_WAIT_SEL        0x06
                     67: #define DBDMA_XFER_MODE       0x07
                     68: #define DBDMA_DATA2PTR_HI     0x08
                     69: #define DBDMA_DATA2PTR_LO     0x09
                     70: #define DBDMA_RES1            0x0A
                     71: #define DBDMA_ADDRESS_HI      0x0B
                     72: #define DBDMA_BRANCH_ADDR_HI  0x0C
                     73: #define DBDMA_RES2            0x0D
                     74: #define DBDMA_RES3            0x0E
                     75: #define DBDMA_RES4            0x0F
                     76: 
                     77: #define DBDMA_REGS            16
                     78: #define DBDMA_SIZE            (DBDMA_REGS * sizeof(uint32_t))
                     79: 
                     80: #define DBDMA_CHANNEL_SHIFT   7
                     81: #define DBDMA_CHANNEL_SIZE    (1 << DBDMA_CHANNEL_SHIFT)
                     82: 
                     83: #define DBDMA_CHANNELS        (0x1000 >> DBDMA_CHANNEL_SHIFT)
                     84: 
                     85: /* Bits in control and status registers */
                     86: 
                     87: #define RUN    0x8000
                     88: #define PAUSE  0x4000
                     89: #define FLUSH  0x2000
                     90: #define WAKE   0x1000
                     91: #define DEAD   0x0800
                     92: #define ACTIVE 0x0400
                     93: #define BT     0x0100
                     94: #define DEVSTAT        0x00ff
                     95: 
                     96: /*
                     97:  * DBDMA command structure.  These fields are all little-endian!
                     98:  */
                     99: 
                    100: typedef struct dbdma_cmd {
                    101:     uint16_t req_count;          /* requested byte transfer count */
                    102:     uint16_t command;    /* command word (has bit-fields) */
                    103:     uint32_t phy_addr;   /* physical data address */
                    104:     uint32_t cmd_dep;    /* command-dependent field */
                    105:     uint16_t res_count;          /* residual count after completion */
                    106:     uint16_t xfer_status; /* transfer status */
                    107: } dbdma_cmd;
                    108: 
                    109: /* DBDMA command values in command field */
                    110: 
                    111: #define COMMAND_MASK    0xf000
                    112: #define OUTPUT_MORE    0x0000  /* transfer memory data to stream */
                    113: #define OUTPUT_LAST    0x1000  /* ditto followed by end marker */
                    114: #define INPUT_MORE     0x2000  /* transfer stream data to memory */
                    115: #define INPUT_LAST     0x3000  /* ditto, expect end marker */
                    116: #define STORE_WORD     0x4000  /* write word (4 bytes) to device reg */
                    117: #define LOAD_WORD      0x5000  /* read word (4 bytes) from device reg */
                    118: #define DBDMA_NOP      0x6000  /* do nothing */
                    119: #define DBDMA_STOP     0x7000  /* suspend processing */
                    120: 
                    121: /* Key values in command field */
                    122: 
                    123: #define KEY_MASK        0x0700
                    124: #define KEY_STREAM0    0x0000  /* usual data stream */
                    125: #define KEY_STREAM1    0x0100  /* control/status stream */
                    126: #define KEY_STREAM2    0x0200  /* device-dependent stream */
                    127: #define KEY_STREAM3    0x0300  /* device-dependent stream */
                    128: #define KEY_STREAM4    0x0400  /* reserved */
                    129: #define KEY_REGS       0x0500  /* device register space */
                    130: #define KEY_SYSTEM     0x0600  /* system memory-mapped space */
                    131: #define KEY_DEVICE     0x0700  /* device memory-mapped space */
                    132: 
                    133: /* Interrupt control values in command field */
                    134: 
                    135: #define INTR_MASK       0x0030
                    136: #define INTR_NEVER     0x0000  /* don't interrupt */
                    137: #define INTR_IFSET     0x0010  /* intr if condition bit is 1 */
                    138: #define INTR_IFCLR     0x0020  /* intr if condition bit is 0 */
                    139: #define INTR_ALWAYS    0x0030  /* always interrupt */
                    140: 
                    141: /* Branch control values in command field */
                    142: 
                    143: #define BR_MASK         0x000c
                    144: #define BR_NEVER       0x0000  /* don't branch */
                    145: #define BR_IFSET       0x0004  /* branch if condition bit is 1 */
                    146: #define BR_IFCLR       0x0008  /* branch if condition bit is 0 */
                    147: #define BR_ALWAYS      0x000c  /* always branch */
                    148: 
                    149: /* Wait control values in command field */
                    150: 
                    151: #define WAIT_MASK       0x0003
                    152: #define WAIT_NEVER     0x0000  /* don't wait */
                    153: #define WAIT_IFSET     0x0001  /* wait if condition bit is 1 */
                    154: #define WAIT_IFCLR     0x0002  /* wait if condition bit is 0 */
                    155: #define WAIT_ALWAYS    0x0003  /* always wait */
                    156: 
                    157: typedef struct DBDMA_channel {
                    158:     int channel;
                    159:     uint32_t regs[DBDMA_REGS];
                    160:     qemu_irq irq;
                    161:     DBDMA_io io;
                    162:     DBDMA_rw rw;
                    163:     DBDMA_flush flush;
                    164:     dbdma_cmd current;
                    165:     int processing;
                    166: } DBDMA_channel;
                    167: 
                    168: #ifdef DEBUG_DBDMA
                    169: static void dump_dbdma_cmd(dbdma_cmd *cmd)
                    170: {
                    171:     printf("dbdma_cmd %p\n", cmd);
                    172:     printf("    req_count 0x%04x\n", le16_to_cpu(cmd->req_count));
                    173:     printf("    command 0x%04x\n", le16_to_cpu(cmd->command));
                    174:     printf("    phy_addr 0x%08x\n", le32_to_cpu(cmd->phy_addr));
                    175:     printf("    cmd_dep 0x%08x\n", le32_to_cpu(cmd->cmd_dep));
                    176:     printf("    res_count 0x%04x\n", le16_to_cpu(cmd->res_count));
                    177:     printf("    xfer_status 0x%04x\n", le16_to_cpu(cmd->xfer_status));
                    178: }
                    179: #else
                    180: static void dump_dbdma_cmd(dbdma_cmd *cmd)
1.1       root      181: {
1.1.1.2   root      182: }
                    183: #endif
                    184: static void dbdma_cmdptr_load(DBDMA_channel *ch)
                    185: {
                    186:     DBDMA_DPRINTF("dbdma_cmdptr_load 0x%08x\n",
                    187:                   be32_to_cpu(ch->regs[DBDMA_CMDPTR_LO]));
                    188:     cpu_physical_memory_read(be32_to_cpu(ch->regs[DBDMA_CMDPTR_LO]),
                    189:                              (uint8_t*)&ch->current, sizeof(dbdma_cmd));
1.1       root      190: }
                    191: 
1.1.1.2   root      192: static void dbdma_cmdptr_save(DBDMA_channel *ch)
1.1       root      193: {
1.1.1.2   root      194:     DBDMA_DPRINTF("dbdma_cmdptr_save 0x%08x\n",
                    195:                   be32_to_cpu(ch->regs[DBDMA_CMDPTR_LO]));
                    196:     DBDMA_DPRINTF("xfer_status 0x%08x res_count 0x%04x\n",
                    197:                   le16_to_cpu(ch->current.xfer_status),
                    198:                   le16_to_cpu(ch->current.res_count));
                    199:     cpu_physical_memory_write(be32_to_cpu(ch->regs[DBDMA_CMDPTR_LO]),
                    200:                               (uint8_t*)&ch->current, sizeof(dbdma_cmd));
1.1       root      201: }
                    202: 
1.1.1.2   root      203: static void kill_channel(DBDMA_channel *ch)
1.1       root      204: {
1.1.1.2   root      205:     DBDMA_DPRINTF("kill_channel\n");
                    206: 
                    207:     ch->regs[DBDMA_STATUS] |= cpu_to_be32(DEAD);
                    208:     ch->regs[DBDMA_STATUS] &= cpu_to_be32(~ACTIVE);
                    209: 
                    210:     qemu_irq_raise(ch->irq);
1.1       root      211: }
                    212: 
1.1.1.2   root      213: static void conditional_interrupt(DBDMA_channel *ch)
1.1       root      214: {
1.1.1.2   root      215:     dbdma_cmd *current = &ch->current;
                    216:     uint16_t intr;
                    217:     uint16_t sel_mask, sel_value;
                    218:     uint32_t status;
                    219:     int cond;
                    220: 
                    221:     DBDMA_DPRINTF("conditional_interrupt\n");
                    222: 
                    223:     intr = le16_to_cpu(current->command) & INTR_MASK;
                    224: 
                    225:     switch(intr) {
                    226:     case INTR_NEVER:  /* don't interrupt */
                    227:         return;
                    228:     case INTR_ALWAYS: /* always interrupt */
                    229:         qemu_irq_raise(ch->irq);
                    230:         return;
                    231:     }
                    232: 
                    233:     status = be32_to_cpu(ch->regs[DBDMA_STATUS]) & DEVSTAT;
                    234: 
                    235:     sel_mask = (be32_to_cpu(ch->regs[DBDMA_INTR_SEL]) >> 16) & 0x0f;
                    236:     sel_value = be32_to_cpu(ch->regs[DBDMA_INTR_SEL]) & 0x0f;
                    237: 
                    238:     cond = (status & sel_mask) == (sel_value & sel_mask);
                    239: 
                    240:     switch(intr) {
                    241:     case INTR_IFSET:  /* intr if condition bit is 1 */
                    242:         if (cond)
                    243:             qemu_irq_raise(ch->irq);
                    244:         return;
                    245:     case INTR_IFCLR:  /* intr if condition bit is 0 */
                    246:         if (!cond)
                    247:             qemu_irq_raise(ch->irq);
                    248:         return;
                    249:     }
                    250: }
1.1       root      251: 
1.1.1.2   root      252: static int conditional_wait(DBDMA_channel *ch)
                    253: {
                    254:     dbdma_cmd *current = &ch->current;
                    255:     uint16_t wait;
                    256:     uint16_t sel_mask, sel_value;
                    257:     uint32_t status;
                    258:     int cond;
                    259: 
                    260:     DBDMA_DPRINTF("conditional_wait\n");
                    261: 
                    262:     wait = le16_to_cpu(current->command) & WAIT_MASK;
                    263: 
                    264:     switch(wait) {
                    265:     case WAIT_NEVER:  /* don't wait */
                    266:         return 0;
                    267:     case WAIT_ALWAYS: /* always wait */
                    268:         return 1;
                    269:     }
                    270: 
                    271:     status = be32_to_cpu(ch->regs[DBDMA_STATUS]) & DEVSTAT;
                    272: 
                    273:     sel_mask = (be32_to_cpu(ch->regs[DBDMA_WAIT_SEL]) >> 16) & 0x0f;
                    274:     sel_value = be32_to_cpu(ch->regs[DBDMA_WAIT_SEL]) & 0x0f;
                    275: 
                    276:     cond = (status & sel_mask) == (sel_value & sel_mask);
                    277: 
                    278:     switch(wait) {
                    279:     case WAIT_IFSET:  /* wait if condition bit is 1 */
                    280:         if (cond)
                    281:             return 1;
                    282:         return 0;
                    283:     case WAIT_IFCLR:  /* wait if condition bit is 0 */
                    284:         if (!cond)
                    285:             return 1;
                    286:         return 0;
                    287:     }
1.1       root      288:     return 0;
                    289: }
                    290: 
1.1.1.2   root      291: static void next(DBDMA_channel *ch)
1.1       root      292: {
1.1.1.2   root      293:     uint32_t cp;
                    294: 
                    295:     ch->regs[DBDMA_STATUS] &= cpu_to_be32(~BT);
                    296: 
                    297:     cp = be32_to_cpu(ch->regs[DBDMA_CMDPTR_LO]);
                    298:     ch->regs[DBDMA_CMDPTR_LO] = cpu_to_be32(cp + sizeof(dbdma_cmd));
                    299:     dbdma_cmdptr_load(ch);
                    300: }
                    301: 
                    302: static void branch(DBDMA_channel *ch)
                    303: {
                    304:     dbdma_cmd *current = &ch->current;
                    305: 
                    306:     ch->regs[DBDMA_CMDPTR_LO] = current->cmd_dep;
                    307:     ch->regs[DBDMA_STATUS] |= cpu_to_be32(BT);
                    308:     dbdma_cmdptr_load(ch);
                    309: }
                    310: 
                    311: static void conditional_branch(DBDMA_channel *ch)
                    312: {
                    313:     dbdma_cmd *current = &ch->current;
                    314:     uint16_t br;
                    315:     uint16_t sel_mask, sel_value;
                    316:     uint32_t status;
                    317:     int cond;
                    318: 
                    319:     DBDMA_DPRINTF("conditional_branch\n");
                    320: 
                    321:     /* check if we must branch */
                    322: 
                    323:     br = le16_to_cpu(current->command) & BR_MASK;
                    324: 
                    325:     switch(br) {
                    326:     case BR_NEVER:  /* don't branch */
                    327:         next(ch);
                    328:         return;
                    329:     case BR_ALWAYS: /* always branch */
                    330:         branch(ch);
                    331:         return;
                    332:     }
                    333: 
                    334:     status = be32_to_cpu(ch->regs[DBDMA_STATUS]) & DEVSTAT;
                    335: 
                    336:     sel_mask = (be32_to_cpu(ch->regs[DBDMA_BRANCH_SEL]) >> 16) & 0x0f;
                    337:     sel_value = be32_to_cpu(ch->regs[DBDMA_BRANCH_SEL]) & 0x0f;
                    338: 
                    339:     cond = (status & sel_mask) == (sel_value & sel_mask);
                    340: 
                    341:     switch(br) {
                    342:     case BR_IFSET:  /* branch if condition bit is 1 */
                    343:         if (cond)
                    344:             branch(ch);
                    345:         else
                    346:             next(ch);
                    347:         return;
                    348:     case BR_IFCLR:  /* branch if condition bit is 0 */
                    349:         if (!cond)
                    350:             branch(ch);
                    351:         else
                    352:             next(ch);
                    353:         return;
                    354:     }
                    355: }
                    356: 
                    357: static QEMUBH *dbdma_bh;
                    358: static void channel_run(DBDMA_channel *ch);
                    359: 
                    360: static void dbdma_end(DBDMA_io *io)
                    361: {
                    362:     DBDMA_channel *ch = io->channel;
                    363:     dbdma_cmd *current = &ch->current;
                    364: 
                    365:     if (conditional_wait(ch))
                    366:         goto wait;
                    367: 
                    368:     current->xfer_status = cpu_to_le16(be32_to_cpu(ch->regs[DBDMA_STATUS]));
                    369:     current->res_count = cpu_to_le16(be32_to_cpu(io->len));
                    370:     dbdma_cmdptr_save(ch);
                    371:     if (io->is_last)
                    372:         ch->regs[DBDMA_STATUS] &= cpu_to_be32(~FLUSH);
                    373: 
                    374:     conditional_interrupt(ch);
                    375:     conditional_branch(ch);
                    376: 
                    377: wait:
                    378:     ch->processing = 0;
                    379:     if ((ch->regs[DBDMA_STATUS] & cpu_to_be32(RUN)) &&
                    380:         (ch->regs[DBDMA_STATUS] & cpu_to_be32(ACTIVE)))
                    381:         channel_run(ch);
                    382: }
                    383: 
                    384: static void start_output(DBDMA_channel *ch, int key, uint32_t addr,
                    385:                         uint16_t req_count, int is_last)
                    386: {
                    387:     DBDMA_DPRINTF("start_output\n");
                    388: 
                    389:     /* KEY_REGS, KEY_DEVICE and KEY_STREAM
                    390:      * are not implemented in the mac-io chip
                    391:      */
                    392: 
                    393:     DBDMA_DPRINTF("addr 0x%x key 0x%x\n", addr, key);
                    394:     if (!addr || key > KEY_STREAM3) {
                    395:         kill_channel(ch);
                    396:         return;
                    397:     }
                    398: 
                    399:     ch->io.addr = addr;
                    400:     ch->io.len = req_count;
                    401:     ch->io.is_last = is_last;
                    402:     ch->io.dma_end = dbdma_end;
                    403:     ch->io.is_dma_out = 1;
                    404:     ch->processing = 1;
                    405:     ch->rw(&ch->io);
                    406: }
                    407: 
                    408: static void start_input(DBDMA_channel *ch, int key, uint32_t addr,
                    409:                        uint16_t req_count, int is_last)
                    410: {
                    411:     DBDMA_DPRINTF("start_input\n");
                    412: 
                    413:     /* KEY_REGS, KEY_DEVICE and KEY_STREAM
                    414:      * are not implemented in the mac-io chip
                    415:      */
                    416: 
                    417:     if (!addr || key > KEY_STREAM3) {
                    418:         kill_channel(ch);
                    419:         return;
                    420:     }
                    421: 
                    422:     ch->io.addr = addr;
                    423:     ch->io.len = req_count;
                    424:     ch->io.is_last = is_last;
                    425:     ch->io.dma_end = dbdma_end;
                    426:     ch->io.is_dma_out = 0;
                    427:     ch->processing = 1;
                    428:     ch->rw(&ch->io);
                    429: }
                    430: 
                    431: static void load_word(DBDMA_channel *ch, int key, uint32_t addr,
                    432:                      uint16_t len)
                    433: {
                    434:     dbdma_cmd *current = &ch->current;
                    435:     uint32_t val;
                    436: 
                    437:     DBDMA_DPRINTF("load_word\n");
                    438: 
                    439:     /* only implements KEY_SYSTEM */
                    440: 
                    441:     if (key != KEY_SYSTEM) {
                    442:         printf("DBDMA: LOAD_WORD, unimplemented key %x\n", key);
                    443:         kill_channel(ch);
                    444:         return;
                    445:     }
                    446: 
                    447:     cpu_physical_memory_read(addr, (uint8_t*)&val, len);
                    448: 
                    449:     if (len == 2)
                    450:         val = (val << 16) | (current->cmd_dep & 0x0000ffff);
                    451:     else if (len == 1)
                    452:         val = (val << 24) | (current->cmd_dep & 0x00ffffff);
                    453: 
                    454:     current->cmd_dep = val;
                    455: 
                    456:     if (conditional_wait(ch))
                    457:         goto wait;
                    458: 
                    459:     current->xfer_status = cpu_to_le16(be32_to_cpu(ch->regs[DBDMA_STATUS]));
                    460:     dbdma_cmdptr_save(ch);
                    461:     ch->regs[DBDMA_STATUS] &= cpu_to_be32(~FLUSH);
                    462: 
                    463:     conditional_interrupt(ch);
                    464:     next(ch);
                    465: 
                    466: wait:
                    467:     qemu_bh_schedule(dbdma_bh);
                    468: }
                    469: 
                    470: static void store_word(DBDMA_channel *ch, int key, uint32_t addr,
                    471:                       uint16_t len)
                    472: {
                    473:     dbdma_cmd *current = &ch->current;
                    474:     uint32_t val;
                    475: 
                    476:     DBDMA_DPRINTF("store_word\n");
                    477: 
                    478:     /* only implements KEY_SYSTEM */
                    479: 
                    480:     if (key != KEY_SYSTEM) {
                    481:         printf("DBDMA: STORE_WORD, unimplemented key %x\n", key);
                    482:         kill_channel(ch);
                    483:         return;
                    484:     }
                    485: 
                    486:     val = current->cmd_dep;
                    487:     if (len == 2)
                    488:         val >>= 16;
                    489:     else if (len == 1)
                    490:         val >>= 24;
                    491: 
                    492:     cpu_physical_memory_write(addr, (uint8_t*)&val, len);
                    493: 
                    494:     if (conditional_wait(ch))
                    495:         goto wait;
                    496: 
                    497:     current->xfer_status = cpu_to_le16(be32_to_cpu(ch->regs[DBDMA_STATUS]));
                    498:     dbdma_cmdptr_save(ch);
                    499:     ch->regs[DBDMA_STATUS] &= cpu_to_be32(~FLUSH);
                    500: 
                    501:     conditional_interrupt(ch);
                    502:     next(ch);
                    503: 
                    504: wait:
                    505:     qemu_bh_schedule(dbdma_bh);
                    506: }
                    507: 
                    508: static void nop(DBDMA_channel *ch)
                    509: {
                    510:     dbdma_cmd *current = &ch->current;
                    511: 
                    512:     if (conditional_wait(ch))
                    513:         goto wait;
                    514: 
                    515:     current->xfer_status = cpu_to_le16(be32_to_cpu(ch->regs[DBDMA_STATUS]));
                    516:     dbdma_cmdptr_save(ch);
                    517: 
                    518:     conditional_interrupt(ch);
                    519:     conditional_branch(ch);
                    520: 
                    521: wait:
                    522:     qemu_bh_schedule(dbdma_bh);
                    523: }
                    524: 
                    525: static void stop(DBDMA_channel *ch)
                    526: {
                    527:     ch->regs[DBDMA_STATUS] &= cpu_to_be32(~(ACTIVE|DEAD|FLUSH));
                    528: 
                    529:     /* the stop command does not increment command pointer */
                    530: }
                    531: 
                    532: static void channel_run(DBDMA_channel *ch)
                    533: {
                    534:     dbdma_cmd *current = &ch->current;
                    535:     uint16_t cmd, key;
                    536:     uint16_t req_count;
                    537:     uint32_t phy_addr;
                    538: 
                    539:     DBDMA_DPRINTF("channel_run\n");
                    540:     dump_dbdma_cmd(current);
                    541: 
                    542:     /* clear WAKE flag at command fetch */
                    543: 
                    544:     ch->regs[DBDMA_STATUS] &= cpu_to_be32(~WAKE);
                    545: 
                    546:     cmd = le16_to_cpu(current->command) & COMMAND_MASK;
                    547: 
                    548:     switch (cmd) {
                    549:     case DBDMA_NOP:
                    550:         nop(ch);
                    551:        return;
                    552: 
                    553:     case DBDMA_STOP:
                    554:         stop(ch);
                    555:        return;
                    556:     }
                    557: 
                    558:     key = le16_to_cpu(current->command) & 0x0700;
                    559:     req_count = le16_to_cpu(current->req_count);
                    560:     phy_addr = le32_to_cpu(current->phy_addr);
                    561: 
                    562:     if (key == KEY_STREAM4) {
                    563:         printf("command %x, invalid key 4\n", cmd);
                    564:         kill_channel(ch);
                    565:         return;
                    566:     }
                    567: 
                    568:     switch (cmd) {
                    569:     case OUTPUT_MORE:
                    570:         start_output(ch, key, phy_addr, req_count, 0);
                    571:        return;
                    572: 
                    573:     case OUTPUT_LAST:
                    574:         start_output(ch, key, phy_addr, req_count, 1);
                    575:        return;
                    576: 
                    577:     case INPUT_MORE:
                    578:         start_input(ch, key, phy_addr, req_count, 0);
                    579:        return;
                    580: 
                    581:     case INPUT_LAST:
                    582:         start_input(ch, key, phy_addr, req_count, 1);
                    583:        return;
                    584:     }
                    585: 
                    586:     if (key < KEY_REGS) {
                    587:         printf("command %x, invalid key %x\n", cmd, key);
                    588:         key = KEY_SYSTEM;
                    589:     }
                    590: 
                    591:     /* for LOAD_WORD and STORE_WORD, req_count is on 3 bits
                    592:      * and BRANCH is invalid
                    593:      */
                    594: 
                    595:     req_count = req_count & 0x0007;
                    596:     if (req_count & 0x4) {
                    597:         req_count = 4;
                    598:         phy_addr &= ~3;
                    599:     } else if (req_count & 0x2) {
                    600:         req_count = 2;
                    601:         phy_addr &= ~1;
                    602:     } else
                    603:         req_count = 1;
                    604: 
                    605:     switch (cmd) {
                    606:     case LOAD_WORD:
                    607:         load_word(ch, key, phy_addr, req_count);
                    608:        return;
                    609: 
                    610:     case STORE_WORD:
                    611:         store_word(ch, key, phy_addr, req_count);
                    612:        return;
                    613:     }
                    614: }
                    615: 
                    616: static void DBDMA_run (DBDMA_channel *ch)
                    617: {
                    618:     int channel;
                    619: 
                    620:     for (channel = 0; channel < DBDMA_CHANNELS; channel++, ch++) {
                    621:             uint32_t status = be32_to_cpu(ch->regs[DBDMA_STATUS]);
                    622:             if (!ch->processing && (status & RUN) && (status & ACTIVE))
                    623:                 channel_run(ch);
                    624:     }
                    625: }
                    626: 
                    627: static void DBDMA_run_bh(void *opaque)
                    628: {
                    629:     DBDMA_channel *ch = opaque;
                    630: 
                    631:     DBDMA_DPRINTF("DBDMA_run_bh\n");
                    632: 
                    633:     DBDMA_run(ch);
                    634: }
                    635: 
                    636: void DBDMA_register_channel(void *dbdma, int nchan, qemu_irq irq,
                    637:                             DBDMA_rw rw, DBDMA_flush flush,
                    638:                             void *opaque)
                    639: {
                    640:     DBDMA_channel *ch = ( DBDMA_channel *)dbdma + nchan;
                    641: 
                    642:     DBDMA_DPRINTF("DBDMA_register_channel 0x%x\n", nchan);
                    643: 
                    644:     ch->irq = irq;
                    645:     ch->channel = nchan;
                    646:     ch->rw = rw;
                    647:     ch->flush = flush;
                    648:     ch->io.opaque = opaque;
                    649:     ch->io.channel = ch;
                    650: }
                    651: 
                    652: void DBDMA_schedule(void)
                    653: {
1.1.1.3 ! root      654:     qemu_notify_event();
1.1.1.2   root      655: }
                    656: 
                    657: static void
                    658: dbdma_control_write(DBDMA_channel *ch)
                    659: {
                    660:     uint16_t mask, value;
                    661:     uint32_t status;
                    662: 
                    663:     mask = (be32_to_cpu(ch->regs[DBDMA_CONTROL]) >> 16) & 0xffff;
                    664:     value = be32_to_cpu(ch->regs[DBDMA_CONTROL]) & 0xffff;
                    665: 
                    666:     value &= (RUN | PAUSE | FLUSH | WAKE | DEVSTAT);
                    667: 
                    668:     status = be32_to_cpu(ch->regs[DBDMA_STATUS]);
                    669: 
                    670:     status = (value & mask) | (status & ~mask);
                    671: 
                    672:     if (status & WAKE)
                    673:         status |= ACTIVE;
                    674:     if (status & RUN) {
                    675:         status |= ACTIVE;
                    676:         status &= ~DEAD;
                    677:     }
                    678:     if (status & PAUSE)
                    679:         status &= ~ACTIVE;
                    680:     if ((be32_to_cpu(ch->regs[DBDMA_STATUS]) & RUN) && !(status & RUN)) {
                    681:         /* RUN is cleared */
                    682:         status &= ~(ACTIVE|DEAD);
                    683:     }
                    684: 
                    685:     DBDMA_DPRINTF("    status 0x%08x\n", status);
                    686: 
                    687:     ch->regs[DBDMA_STATUS] = cpu_to_be32(status);
                    688: 
                    689:     if (status & ACTIVE)
                    690:         qemu_bh_schedule(dbdma_bh);
                    691:     if (status & FLUSH)
                    692:         ch->flush(&ch->io);
                    693: }
                    694: 
                    695: static void dbdma_writel (void *opaque,
                    696:                           target_phys_addr_t addr, uint32_t value)
                    697: {
                    698:     int channel = addr >> DBDMA_CHANNEL_SHIFT;
                    699:     DBDMA_channel *ch = (DBDMA_channel *)opaque + channel;
                    700:     int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;
                    701: 
                    702:     DBDMA_DPRINTF("writel 0x" TARGET_FMT_plx " <= 0x%08x\n", addr, value);
                    703:     DBDMA_DPRINTF("channel 0x%x reg 0x%x\n",
                    704:                   (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
                    705: 
                    706:     /* cmdptr cannot be modified if channel is RUN or ACTIVE */
                    707: 
                    708:     if (reg == DBDMA_CMDPTR_LO &&
                    709:         (ch->regs[DBDMA_STATUS] & cpu_to_be32(RUN | ACTIVE)))
                    710:        return;
                    711: 
                    712:     ch->regs[reg] = value;
                    713: 
                    714:     switch(reg) {
                    715:     case DBDMA_CONTROL:
                    716:         dbdma_control_write(ch);
                    717:         break;
                    718:     case DBDMA_CMDPTR_LO:
                    719:         /* 16-byte aligned */
                    720:         ch->regs[DBDMA_CMDPTR_LO] &= cpu_to_be32(~0xf);
                    721:         dbdma_cmdptr_load(ch);
                    722:         break;
                    723:     case DBDMA_STATUS:
                    724:     case DBDMA_INTR_SEL:
                    725:     case DBDMA_BRANCH_SEL:
                    726:     case DBDMA_WAIT_SEL:
                    727:         /* nothing to do */
                    728:         break;
                    729:     case DBDMA_XFER_MODE:
                    730:     case DBDMA_CMDPTR_HI:
                    731:     case DBDMA_DATA2PTR_HI:
                    732:     case DBDMA_DATA2PTR_LO:
                    733:     case DBDMA_ADDRESS_HI:
                    734:     case DBDMA_BRANCH_ADDR_HI:
                    735:     case DBDMA_RES1:
                    736:     case DBDMA_RES2:
                    737:     case DBDMA_RES3:
                    738:     case DBDMA_RES4:
                    739:         /* unused */
                    740:         break;
                    741:     }
1.1       root      742: }
                    743: 
                    744: static uint32_t dbdma_readl (void *opaque, target_phys_addr_t addr)
                    745: {
1.1.1.2   root      746:     uint32_t value;
                    747:     int channel = addr >> DBDMA_CHANNEL_SHIFT;
                    748:     DBDMA_channel *ch = (DBDMA_channel *)opaque + channel;
                    749:     int reg = (addr - (channel << DBDMA_CHANNEL_SHIFT)) >> 2;
                    750: 
                    751:     value = ch->regs[reg];
                    752: 
                    753:     DBDMA_DPRINTF("readl 0x" TARGET_FMT_plx " => 0x%08x\n", addr, value);
                    754:     DBDMA_DPRINTF("channel 0x%x reg 0x%x\n",
                    755:                   (uint32_t)addr >> DBDMA_CHANNEL_SHIFT, reg);
                    756: 
                    757:     switch(reg) {
                    758:     case DBDMA_CONTROL:
                    759:         value = 0;
                    760:         break;
                    761:     case DBDMA_STATUS:
                    762:     case DBDMA_CMDPTR_LO:
                    763:     case DBDMA_INTR_SEL:
                    764:     case DBDMA_BRANCH_SEL:
                    765:     case DBDMA_WAIT_SEL:
                    766:         /* nothing to do */
                    767:         break;
                    768:     case DBDMA_XFER_MODE:
                    769:     case DBDMA_CMDPTR_HI:
                    770:     case DBDMA_DATA2PTR_HI:
                    771:     case DBDMA_DATA2PTR_LO:
                    772:     case DBDMA_ADDRESS_HI:
                    773:     case DBDMA_BRANCH_ADDR_HI:
                    774:         /* unused */
                    775:         value = 0;
                    776:         break;
                    777:     case DBDMA_RES1:
                    778:     case DBDMA_RES2:
                    779:     case DBDMA_RES3:
                    780:     case DBDMA_RES4:
                    781:         /* reserved */
                    782:         break;
                    783:     }
                    784: 
                    785:     return value;
1.1       root      786: }
                    787: 
                    788: static CPUWriteMemoryFunc *dbdma_write[] = {
1.1.1.2   root      789:     NULL,
                    790:     NULL,
                    791:     dbdma_writel,
1.1       root      792: };
                    793: 
                    794: static CPUReadMemoryFunc *dbdma_read[] = {
1.1.1.2   root      795:     NULL,
                    796:     NULL,
                    797:     dbdma_readl,
1.1       root      798: };
                    799: 
1.1.1.2   root      800: static void dbdma_save(QEMUFile *f, void *opaque)
                    801: {
                    802:     DBDMA_channel *s = opaque;
                    803:     unsigned int i, j;
                    804: 
                    805:     for (i = 0; i < DBDMA_CHANNELS; i++)
                    806:         for (j = 0; j < DBDMA_REGS; j++)
                    807:             qemu_put_be32s(f, &s[i].regs[j]);
                    808: }
                    809: 
                    810: static int dbdma_load(QEMUFile *f, void *opaque, int version_id)
1.1       root      811: {
1.1.1.2   root      812:     DBDMA_channel *s = opaque;
                    813:     unsigned int i, j;
                    814: 
                    815:     if (version_id != 2)
                    816:         return -EINVAL;
                    817: 
                    818:     for (i = 0; i < DBDMA_CHANNELS; i++)
                    819:         for (j = 0; j < DBDMA_REGS; j++)
                    820:             qemu_get_be32s(f, &s[i].regs[j]);
                    821: 
                    822:     return 0;
1.1       root      823: }
                    824: 
1.1.1.2   root      825: static void dbdma_reset(void *opaque)
                    826: {
                    827:     DBDMA_channel *s = opaque;
                    828:     int i;
                    829: 
                    830:     for (i = 0; i < DBDMA_CHANNELS; i++)
                    831:         memset(s[i].regs, 0, DBDMA_SIZE);
                    832: }
                    833: 
                    834: void* DBDMA_init (int *dbdma_mem_index)
                    835: {
                    836:     DBDMA_channel *s;
                    837: 
                    838:     s = qemu_mallocz(sizeof(DBDMA_channel) * DBDMA_CHANNELS);
                    839: 
1.1.1.3 ! root      840:     *dbdma_mem_index = cpu_register_io_memory(dbdma_read, dbdma_write, s);
1.1.1.2   root      841:     register_savevm("dbdma", -1, 1, dbdma_save, dbdma_load, s);
                    842:     qemu_register_reset(dbdma_reset, s);
                    843:     dbdma_reset(s);
                    844: 
                    845:     dbdma_bh = qemu_bh_new(DBDMA_run_bh, s);
                    846: 
                    847:     return s;
                    848: }

unix.superglobalmegacorp.com

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