Annotation of qemu/hw/etraxfs_dma.c, revision 1.1.1.6

1.1       root        1: /*
                      2:  * QEMU ETRAX DMA Controller.
                      3:  *
                      4:  * Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB.
                      5:  *
                      6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      7:  * of this software and associated documentation files (the "Software"), to deal
                      8:  * in the Software without restriction, including without limitation the rights
                      9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     10:  * copies of the Software, and to permit persons to whom the Software is
                     11:  * furnished to do so, subject to the following conditions:
                     12:  *
                     13:  * The above copyright notice and this permission notice shall be included in
                     14:  * all copies or substantial portions of the Software.
                     15:  *
                     16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     22:  * THE SOFTWARE.
                     23:  */
                     24: #include <stdio.h>
                     25: #include <sys/time.h>
                     26: #include "hw.h"
1.1.1.5   root       27: #include "exec-memory.h"
1.1       root       28: #include "qemu-common.h"
                     29: #include "sysemu.h"
                     30: 
                     31: #include "etraxfs_dma.h"
                     32: 
                     33: #define D(x)
                     34: 
                     35: #define RW_DATA           (0x0 / 4)
                     36: #define RW_SAVED_DATA     (0x58 / 4)
                     37: #define RW_SAVED_DATA_BUF (0x5c / 4)
                     38: #define RW_GROUP          (0x60 / 4)
                     39: #define RW_GROUP_DOWN     (0x7c / 4)
                     40: #define RW_CMD            (0x80 / 4)
                     41: #define RW_CFG            (0x84 / 4)
                     42: #define RW_STAT           (0x88 / 4)
                     43: #define RW_INTR_MASK      (0x8c / 4)
                     44: #define RW_ACK_INTR       (0x90 / 4)
                     45: #define R_INTR            (0x94 / 4)
                     46: #define R_MASKED_INTR     (0x98 / 4)
                     47: #define RW_STREAM_CMD     (0x9c / 4)
                     48: 
                     49: #define DMA_REG_MAX       (0x100 / 4)
                     50: 
                     51: /* descriptors */
                     52: 
                     53: // ------------------------------------------------------------ dma_descr_group
                     54: typedef struct dma_descr_group {
1.1.1.2   root       55:   uint32_t                      next;
1.1       root       56:   unsigned                      eol        : 1;
                     57:   unsigned                      tol        : 1;
                     58:   unsigned                      bol        : 1;
                     59:   unsigned                                 : 1;
                     60:   unsigned                      intr       : 1;
                     61:   unsigned                                 : 2;
                     62:   unsigned                      en         : 1;
                     63:   unsigned                                 : 7;
                     64:   unsigned                      dis        : 1;
                     65:   unsigned                      md         : 16;
                     66:   struct dma_descr_group       *up;
                     67:   union {
                     68:     struct dma_descr_context   *context;
                     69:     struct dma_descr_group     *group;
                     70:   }                             down;
                     71: } dma_descr_group;
                     72: 
                     73: // ---------------------------------------------------------- dma_descr_context
                     74: typedef struct dma_descr_context {
1.1.1.2   root       75:   uint32_t                      next;
1.1       root       76:   unsigned                      eol        : 1;
                     77:   unsigned                                 : 3;
                     78:   unsigned                      intr       : 1;
                     79:   unsigned                                 : 1;
                     80:   unsigned                      store_mode : 1;
                     81:   unsigned                      en         : 1;
                     82:   unsigned                                 : 7;
                     83:   unsigned                      dis        : 1;
                     84:   unsigned                      md0        : 16;
                     85:   unsigned                      md1;
                     86:   unsigned                      md2;
                     87:   unsigned                      md3;
                     88:   unsigned                      md4;
1.1.1.2   root       89:   uint32_t                      saved_data;
                     90:   uint32_t                      saved_data_buf;
1.1       root       91: } dma_descr_context;
                     92: 
                     93: // ------------------------------------------------------------- dma_descr_data
                     94: typedef struct dma_descr_data {
1.1.1.2   root       95:   uint32_t                      next;
                     96:   uint32_t                      buf;
1.1       root       97:   unsigned                      eol        : 1;
                     98:   unsigned                                 : 2;
                     99:   unsigned                      out_eop    : 1;
                    100:   unsigned                      intr       : 1;
                    101:   unsigned                      wait       : 1;
                    102:   unsigned                                 : 2;
                    103:   unsigned                                 : 3;
                    104:   unsigned                      in_eop     : 1;
                    105:   unsigned                                 : 4;
                    106:   unsigned                      md         : 16;
1.1.1.2   root      107:   uint32_t                      after;
1.1       root      108: } dma_descr_data;
                    109: 
                    110: /* Constants */
                    111: enum {
                    112:   regk_dma_ack_pkt                         = 0x00000100,
                    113:   regk_dma_anytime                         = 0x00000001,
                    114:   regk_dma_array                           = 0x00000008,
                    115:   regk_dma_burst                           = 0x00000020,
                    116:   regk_dma_client                          = 0x00000002,
                    117:   regk_dma_copy_next                       = 0x00000010,
                    118:   regk_dma_copy_up                         = 0x00000020,
                    119:   regk_dma_data_at_eol                     = 0x00000001,
                    120:   regk_dma_dis_c                           = 0x00000010,
                    121:   regk_dma_dis_g                           = 0x00000020,
                    122:   regk_dma_idle                            = 0x00000001,
                    123:   regk_dma_intern                          = 0x00000004,
                    124:   regk_dma_load_c                          = 0x00000200,
                    125:   regk_dma_load_c_n                        = 0x00000280,
                    126:   regk_dma_load_c_next                     = 0x00000240,
                    127:   regk_dma_load_d                          = 0x00000140,
                    128:   regk_dma_load_g                          = 0x00000300,
                    129:   regk_dma_load_g_down                     = 0x000003c0,
                    130:   regk_dma_load_g_next                     = 0x00000340,
                    131:   regk_dma_load_g_up                       = 0x00000380,
                    132:   regk_dma_next_en                         = 0x00000010,
                    133:   regk_dma_next_pkt                        = 0x00000010,
                    134:   regk_dma_no                              = 0x00000000,
                    135:   regk_dma_only_at_wait                    = 0x00000000,
                    136:   regk_dma_restore                         = 0x00000020,
                    137:   regk_dma_rst                             = 0x00000001,
                    138:   regk_dma_running                         = 0x00000004,
                    139:   regk_dma_rw_cfg_default                  = 0x00000000,
                    140:   regk_dma_rw_cmd_default                  = 0x00000000,
                    141:   regk_dma_rw_intr_mask_default            = 0x00000000,
                    142:   regk_dma_rw_stat_default                 = 0x00000101,
                    143:   regk_dma_rw_stream_cmd_default           = 0x00000000,
                    144:   regk_dma_save_down                       = 0x00000020,
                    145:   regk_dma_save_up                         = 0x00000020,
                    146:   regk_dma_set_reg                         = 0x00000050,
                    147:   regk_dma_set_w_size1                     = 0x00000190,
                    148:   regk_dma_set_w_size2                     = 0x000001a0,
                    149:   regk_dma_set_w_size4                     = 0x000001c0,
                    150:   regk_dma_stopped                         = 0x00000002,
                    151:   regk_dma_store_c                         = 0x00000002,
                    152:   regk_dma_store_descr                     = 0x00000000,
                    153:   regk_dma_store_g                         = 0x00000004,
                    154:   regk_dma_store_md                        = 0x00000001,
                    155:   regk_dma_sw                              = 0x00000008,
                    156:   regk_dma_update_down                     = 0x00000020,
                    157:   regk_dma_yes                             = 0x00000001
                    158: };
                    159: 
                    160: enum dma_ch_state
                    161: {
                    162:        RST = 1,
                    163:        STOPPED = 2,
                    164:        RUNNING = 4
                    165: };
                    166: 
                    167: struct fs_dma_channel
                    168: {
1.1.1.2   root      169:        qemu_irq irq;
1.1       root      170:        struct etraxfs_dma_client *client;
                    171: 
                    172:        /* Internal status.  */
                    173:        int stream_cmd_src;
                    174:        enum dma_ch_state state;
                    175: 
                    176:        unsigned int input : 1;
                    177:        unsigned int eol : 1;
                    178: 
                    179:        struct dma_descr_group current_g;
                    180:        struct dma_descr_context current_c;
                    181:        struct dma_descr_data current_d;
                    182: 
1.1.1.6 ! root      183:        /* Control registers.  */
1.1       root      184:        uint32_t regs[DMA_REG_MAX];
                    185: };
                    186: 
                    187: struct fs_dma_ctrl
                    188: {
1.1.1.5   root      189:        MemoryRegion mmio;
1.1       root      190:        int nr_channels;
                    191:        struct fs_dma_channel *channels;
                    192: 
                    193:         QEMUBH *bh;
                    194: };
                    195: 
                    196: static void DMA_run(void *opaque);
                    197: static int channel_out_run(struct fs_dma_ctrl *ctrl, int c);
                    198: 
                    199: static inline uint32_t channel_reg(struct fs_dma_ctrl *ctrl, int c, int reg)
                    200: {
                    201:        return ctrl->channels[c].regs[reg];
                    202: }
                    203: 
                    204: static inline int channel_stopped(struct fs_dma_ctrl *ctrl, int c)
                    205: {
                    206:        return channel_reg(ctrl, c, RW_CFG) & 2;
                    207: }
                    208: 
                    209: static inline int channel_en(struct fs_dma_ctrl *ctrl, int c)
                    210: {
                    211:        return (channel_reg(ctrl, c, RW_CFG) & 1)
                    212:                && ctrl->channels[c].client;
                    213: }
                    214: 
                    215: static inline int fs_channel(target_phys_addr_t addr)
                    216: {
                    217:        /* Every channel has a 0x2000 ctrl register map.  */
                    218:        return addr >> 13;
                    219: }
                    220: 
                    221: #ifdef USE_THIS_DEAD_CODE
                    222: static void channel_load_g(struct fs_dma_ctrl *ctrl, int c)
                    223: {
                    224:        target_phys_addr_t addr = channel_reg(ctrl, c, RW_GROUP);
                    225: 
                    226:        /* Load and decode. FIXME: handle endianness.  */
                    227:        cpu_physical_memory_read (addr, 
                    228:                                  (void *) &ctrl->channels[c].current_g, 
                    229:                                  sizeof ctrl->channels[c].current_g);
                    230: }
                    231: 
                    232: static void dump_c(int ch, struct dma_descr_context *c)
                    233: {
                    234:        printf("%s ch=%d\n", __func__, ch);
1.1.1.2   root      235:        printf("next=%x\n", c->next);
                    236:        printf("saved_data=%x\n", c->saved_data);
                    237:        printf("saved_data_buf=%x\n", c->saved_data_buf);
1.1       root      238:        printf("eol=%x\n", (uint32_t) c->eol);
                    239: }
                    240: 
                    241: static void dump_d(int ch, struct dma_descr_data *d)
                    242: {
                    243:        printf("%s ch=%d\n", __func__, ch);
1.1.1.2   root      244:        printf("next=%x\n", d->next);
                    245:        printf("buf=%x\n", d->buf);
                    246:        printf("after=%x\n", d->after);
1.1       root      247:        printf("intr=%x\n", (uint32_t) d->intr);
                    248:        printf("out_eop=%x\n", (uint32_t) d->out_eop);
                    249:        printf("in_eop=%x\n", (uint32_t) d->in_eop);
                    250:        printf("eol=%x\n", (uint32_t) d->eol);
                    251: }
                    252: #endif
                    253: 
                    254: static void channel_load_c(struct fs_dma_ctrl *ctrl, int c)
                    255: {
                    256:        target_phys_addr_t addr = channel_reg(ctrl, c, RW_GROUP_DOWN);
                    257: 
                    258:        /* Load and decode. FIXME: handle endianness.  */
                    259:        cpu_physical_memory_read (addr, 
                    260:                                  (void *) &ctrl->channels[c].current_c, 
                    261:                                  sizeof ctrl->channels[c].current_c);
                    262: 
                    263:        D(dump_c(c, &ctrl->channels[c].current_c));
                    264:        /* I guess this should update the current pos.  */
                    265:        ctrl->channels[c].regs[RW_SAVED_DATA] =
                    266:                (uint32_t)(unsigned long)ctrl->channels[c].current_c.saved_data;
                    267:        ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
                    268:                (uint32_t)(unsigned long)ctrl->channels[c].current_c.saved_data_buf;
                    269: }
                    270: 
                    271: static void channel_load_d(struct fs_dma_ctrl *ctrl, int c)
                    272: {
                    273:        target_phys_addr_t addr = channel_reg(ctrl, c, RW_SAVED_DATA);
                    274: 
                    275:        /* Load and decode. FIXME: handle endianness.  */
1.1.1.2   root      276:        D(printf("%s ch=%d addr=" TARGET_FMT_plx "\n", __func__, c, addr));
1.1       root      277:        cpu_physical_memory_read (addr,
                    278:                                  (void *) &ctrl->channels[c].current_d, 
                    279:                                  sizeof ctrl->channels[c].current_d);
                    280: 
                    281:        D(dump_d(c, &ctrl->channels[c].current_d));
                    282:        ctrl->channels[c].regs[RW_DATA] = addr;
                    283: }
                    284: 
                    285: static void channel_store_c(struct fs_dma_ctrl *ctrl, int c)
                    286: {
                    287:        target_phys_addr_t addr = channel_reg(ctrl, c, RW_GROUP_DOWN);
                    288: 
                    289:        /* Encode and store. FIXME: handle endianness.  */
1.1.1.2   root      290:        D(printf("%s ch=%d addr=" TARGET_FMT_plx "\n", __func__, c, addr));
1.1       root      291:        D(dump_d(c, &ctrl->channels[c].current_d));
                    292:        cpu_physical_memory_write (addr,
                    293:                                  (void *) &ctrl->channels[c].current_c,
                    294:                                  sizeof ctrl->channels[c].current_c);
                    295: }
                    296: 
                    297: static void channel_store_d(struct fs_dma_ctrl *ctrl, int c)
                    298: {
                    299:        target_phys_addr_t addr = channel_reg(ctrl, c, RW_SAVED_DATA);
                    300: 
                    301:        /* Encode and store. FIXME: handle endianness.  */
1.1.1.2   root      302:        D(printf("%s ch=%d addr=" TARGET_FMT_plx "\n", __func__, c, addr));
1.1       root      303:        cpu_physical_memory_write (addr,
                    304:                                  (void *) &ctrl->channels[c].current_d, 
                    305:                                  sizeof ctrl->channels[c].current_d);
                    306: }
                    307: 
                    308: static inline void channel_stop(struct fs_dma_ctrl *ctrl, int c)
                    309: {
                    310:        /* FIXME:  */
                    311: }
                    312: 
                    313: static inline void channel_start(struct fs_dma_ctrl *ctrl, int c)
                    314: {
                    315:        if (ctrl->channels[c].client)
                    316:        {
                    317:                ctrl->channels[c].eol = 0;
                    318:                ctrl->channels[c].state = RUNNING;
                    319:                if (!ctrl->channels[c].input)
                    320:                        channel_out_run(ctrl, c);
                    321:        } else
                    322:                printf("WARNING: starting DMA ch %d with no client\n", c);
                    323: 
                    324:         qemu_bh_schedule_idle(ctrl->bh);
                    325: }
                    326: 
                    327: static void channel_continue(struct fs_dma_ctrl *ctrl, int c)
                    328: {
                    329:        if (!channel_en(ctrl, c) 
                    330:            || channel_stopped(ctrl, c)
                    331:            || ctrl->channels[c].state != RUNNING
                    332:            /* Only reload the current data descriptor if it has eol set.  */
                    333:            || !ctrl->channels[c].current_d.eol) {
                    334:                D(printf("continue failed ch=%d state=%d stopped=%d en=%d eol=%d\n", 
                    335:                         c, ctrl->channels[c].state,
                    336:                         channel_stopped(ctrl, c),
                    337:                         channel_en(ctrl,c),
                    338:                         ctrl->channels[c].eol));
                    339:                D(dump_d(c, &ctrl->channels[c].current_d));
                    340:                return;
                    341:        }
                    342: 
                    343:        /* Reload the current descriptor.  */
                    344:        channel_load_d(ctrl, c);
                    345: 
                    346:        /* If the current descriptor cleared the eol flag and we had already
                    347:           reached eol state, do the continue.  */
                    348:        if (!ctrl->channels[c].current_d.eol && ctrl->channels[c].eol) {
1.1.1.2   root      349:                D(printf("continue %d ok %x\n", c,
1.1       root      350:                         ctrl->channels[c].current_d.next));
                    351:                ctrl->channels[c].regs[RW_SAVED_DATA] =
                    352:                        (uint32_t)(unsigned long)ctrl->channels[c].current_d.next;
                    353:                channel_load_d(ctrl, c);
                    354:                ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
                    355:                        (uint32_t)(unsigned long)ctrl->channels[c].current_d.buf;
                    356: 
                    357:                channel_start(ctrl, c);
                    358:        }
                    359:        ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
                    360:                (uint32_t)(unsigned long)ctrl->channels[c].current_d.buf;
                    361: }
                    362: 
                    363: static void channel_stream_cmd(struct fs_dma_ctrl *ctrl, int c, uint32_t v)
                    364: {
                    365:        unsigned int cmd = v & ((1 << 10) - 1);
                    366: 
                    367:        D(printf("%s ch=%d cmd=%x\n",
                    368:                 __func__, c, cmd));
                    369:        if (cmd & regk_dma_load_d) {
                    370:                channel_load_d(ctrl, c);
                    371:                if (cmd & regk_dma_burst)
                    372:                        channel_start(ctrl, c);
                    373:        }
                    374: 
                    375:        if (cmd & regk_dma_load_c) {
                    376:                channel_load_c(ctrl, c);
                    377:        }
                    378: }
                    379: 
                    380: static void channel_update_irq(struct fs_dma_ctrl *ctrl, int c)
                    381: {
                    382:        D(printf("%s %d\n", __func__, c));
                    383:         ctrl->channels[c].regs[R_INTR] &=
                    384:                ~(ctrl->channels[c].regs[RW_ACK_INTR]);
                    385: 
                    386:         ctrl->channels[c].regs[R_MASKED_INTR] =
                    387:                ctrl->channels[c].regs[R_INTR]
                    388:                & ctrl->channels[c].regs[RW_INTR_MASK];
                    389: 
                    390:        D(printf("%s: chan=%d masked_intr=%x\n", __func__, 
                    391:                 c,
                    392:                 ctrl->channels[c].regs[R_MASKED_INTR]));
                    393: 
1.1.1.2   root      394:         qemu_set_irq(ctrl->channels[c].irq,
                    395:                     !!ctrl->channels[c].regs[R_MASKED_INTR]);
1.1       root      396: }
                    397: 
                    398: static int channel_out_run(struct fs_dma_ctrl *ctrl, int c)
                    399: {
                    400:        uint32_t len;
                    401:        uint32_t saved_data_buf;
                    402:        unsigned char buf[2 * 1024];
                    403: 
1.1.1.6 ! root      404:        struct dma_context_metadata meta;
        !           405:        bool send_context = true;
        !           406: 
1.1       root      407:        if (ctrl->channels[c].eol)
                    408:                return 0;
                    409: 
                    410:        do {
1.1.1.6 ! root      411:                bool out_eop;
1.1.1.2   root      412:                D(printf("ch=%d buf=%x after=%x\n",
1.1       root      413:                         c,
                    414:                         (uint32_t)ctrl->channels[c].current_d.buf,
1.1.1.2   root      415:                         (uint32_t)ctrl->channels[c].current_d.after));
1.1       root      416: 
1.1.1.6 ! root      417:                if (send_context) {
        !           418:                        if (ctrl->channels[c].client->client.metadata_push) {
        !           419:                                meta.metadata = ctrl->channels[c].current_d.md;
        !           420:                                ctrl->channels[c].client->client.metadata_push(
        !           421:                                        ctrl->channels[c].client->client.opaque,
        !           422:                                        &meta);
        !           423:                        }
        !           424:                        send_context = false;
        !           425:                }
        !           426: 
1.1       root      427:                channel_load_d(ctrl, c);
                    428:                saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF);
                    429:                len = (uint32_t)(unsigned long)
                    430:                        ctrl->channels[c].current_d.after;
                    431:                len -= saved_data_buf;
                    432: 
                    433:                if (len > sizeof buf)
                    434:                        len = sizeof buf;
                    435:                cpu_physical_memory_read (saved_data_buf, buf, len);
                    436: 
1.1.1.6 ! root      437:                out_eop = ((saved_data_buf + len) ==
        !           438:                           ctrl->channels[c].current_d.after) &&
        !           439:                        ctrl->channels[c].current_d.out_eop;
        !           440: 
        !           441:                D(printf("channel %d pushes %x %u bytes eop=%u\n", c,
        !           442:                         saved_data_buf, len, out_eop));
1.1       root      443: 
                    444:                if (ctrl->channels[c].client->client.push)
                    445:                        ctrl->channels[c].client->client.push(
                    446:                                ctrl->channels[c].client->client.opaque,
1.1.1.6 ! root      447:                                buf, len, out_eop);
1.1       root      448:                else
                    449:                        printf("WARNING: DMA ch%d dataloss,"
                    450:                               " no attached client.\n", c);
                    451: 
                    452:                saved_data_buf += len;
                    453: 
                    454:                if (saved_data_buf == (uint32_t)(unsigned long)
                    455:                                ctrl->channels[c].current_d.after) {
                    456:                        /* Done. Step to next.  */
                    457:                        if (ctrl->channels[c].current_d.out_eop) {
1.1.1.6 ! root      458:                                send_context = true;
1.1       root      459:                        }
                    460:                        if (ctrl->channels[c].current_d.intr) {
                    461:                                /* data intr.  */
                    462:                                D(printf("signal intr %d eol=%d\n",
                    463:                                        len, ctrl->channels[c].current_d.eol));
                    464:                                ctrl->channels[c].regs[R_INTR] |= (1 << 2);
                    465:                                channel_update_irq(ctrl, c);
                    466:                        }
                    467:                        channel_store_d(ctrl, c);
                    468:                        if (ctrl->channels[c].current_d.eol) {
                    469:                                D(printf("channel %d EOL\n", c));
                    470:                                ctrl->channels[c].eol = 1;
                    471: 
                    472:                                /* Mark the context as disabled.  */
                    473:                                ctrl->channels[c].current_c.dis = 1;
                    474:                                channel_store_c(ctrl, c);
                    475: 
                    476:                                channel_stop(ctrl, c);
                    477:                        } else {
                    478:                                ctrl->channels[c].regs[RW_SAVED_DATA] =
                    479:                                        (uint32_t)(unsigned long)ctrl->
                    480:                                                channels[c].current_d.next;
                    481:                                /* Load new descriptor.  */
                    482:                                channel_load_d(ctrl, c);
                    483:                                saved_data_buf = (uint32_t)(unsigned long)
                    484:                                        ctrl->channels[c].current_d.buf;
                    485:                        }
                    486: 
                    487:                        ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
                    488:                                                        saved_data_buf;
                    489:                        D(dump_d(c, &ctrl->channels[c].current_d));
                    490:                }
                    491:                ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf;
                    492:        } while (!ctrl->channels[c].eol);
                    493:        return 1;
                    494: }
                    495: 
                    496: static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, 
                    497:                              unsigned char *buf, int buflen, int eop)
                    498: {
                    499:        uint32_t len;
                    500:        uint32_t saved_data_buf;
                    501: 
                    502:        if (ctrl->channels[c].eol == 1)
                    503:                return 0;
                    504: 
                    505:        channel_load_d(ctrl, c);
                    506:        saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF);
                    507:        len = (uint32_t)(unsigned long)ctrl->channels[c].current_d.after;
                    508:        len -= saved_data_buf;
                    509:        
                    510:        if (len > buflen)
                    511:                len = buflen;
                    512: 
                    513:        cpu_physical_memory_write (saved_data_buf, buf, len);
                    514:        saved_data_buf += len;
                    515: 
                    516:        if (saved_data_buf ==
                    517:            (uint32_t)(unsigned long)ctrl->channels[c].current_d.after
                    518:            || eop) {
                    519:                uint32_t r_intr = ctrl->channels[c].regs[R_INTR];
                    520: 
                    521:                D(printf("in dscr end len=%d\n", 
                    522:                         ctrl->channels[c].current_d.after
                    523:                         - ctrl->channels[c].current_d.buf));
1.1.1.2   root      524:                ctrl->channels[c].current_d.after = saved_data_buf;
1.1       root      525: 
                    526:                /* Done. Step to next.  */
                    527:                if (ctrl->channels[c].current_d.intr) {
                    528:                        /* TODO: signal eop to the client.  */
                    529:                        /* data intr.  */
                    530:                        ctrl->channels[c].regs[R_INTR] |= 3;
                    531:                }
                    532:                if (eop) {
                    533:                        ctrl->channels[c].current_d.in_eop = 1;
                    534:                        ctrl->channels[c].regs[R_INTR] |= 8;
                    535:                }
                    536:                if (r_intr != ctrl->channels[c].regs[R_INTR])
                    537:                        channel_update_irq(ctrl, c);
                    538: 
                    539:                channel_store_d(ctrl, c);
                    540:                D(dump_d(c, &ctrl->channels[c].current_d));
                    541: 
                    542:                if (ctrl->channels[c].current_d.eol) {
                    543:                        D(printf("channel %d EOL\n", c));
                    544:                        ctrl->channels[c].eol = 1;
                    545: 
                    546:                        /* Mark the context as disabled.  */
                    547:                        ctrl->channels[c].current_c.dis = 1;
                    548:                        channel_store_c(ctrl, c);
                    549: 
                    550:                        channel_stop(ctrl, c);
                    551:                } else {
                    552:                        ctrl->channels[c].regs[RW_SAVED_DATA] =
                    553:                                (uint32_t)(unsigned long)ctrl->
                    554:                                        channels[c].current_d.next;
                    555:                        /* Load new descriptor.  */
                    556:                        channel_load_d(ctrl, c);
                    557:                        saved_data_buf = (uint32_t)(unsigned long)
                    558:                                ctrl->channels[c].current_d.buf;
                    559:                }
                    560:        }
                    561: 
                    562:        ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf;
                    563:        return len;
                    564: }
                    565: 
                    566: static inline int channel_in_run(struct fs_dma_ctrl *ctrl, int c)
                    567: {
                    568:        if (ctrl->channels[c].client->client.pull) {
                    569:                ctrl->channels[c].client->client.pull(
                    570:                        ctrl->channels[c].client->client.opaque);
                    571:                return 1;
                    572:        } else
                    573:                return 0;
                    574: }
                    575: 
                    576: static uint32_t dma_rinvalid (void *opaque, target_phys_addr_t addr)
                    577: {
1.1.1.2   root      578:         hw_error("Unsupported short raccess. reg=" TARGET_FMT_plx "\n", addr);
1.1       root      579:         return 0;
                    580: }
                    581: 
1.1.1.5   root      582: static uint64_t
                    583: dma_read(void *opaque, target_phys_addr_t addr, unsigned int size)
1.1       root      584: {
                    585:         struct fs_dma_ctrl *ctrl = opaque;
                    586:        int c;
                    587:        uint32_t r = 0;
                    588: 
1.1.1.5   root      589:        if (size != 4) {
                    590:                dma_rinvalid(opaque, addr);
                    591:        }
                    592: 
1.1       root      593:        /* Make addr relative to this channel and bounded to nr regs.  */
                    594:        c = fs_channel(addr);
                    595:        addr &= 0xff;
                    596:        addr >>= 2;
                    597:        switch (addr)
                    598:        {
                    599:                case RW_STAT:
                    600:                        r = ctrl->channels[c].state & 7;
                    601:                        r |= ctrl->channels[c].eol << 5;
                    602:                        r |= ctrl->channels[c].stream_cmd_src << 8;
                    603:                        break;
                    604: 
                    605:                default:
                    606:                        r = ctrl->channels[c].regs[addr];
1.1.1.2   root      607:                        D(printf ("%s c=%d addr=" TARGET_FMT_plx "\n",
1.1       root      608:                                  __func__, c, addr));
                    609:                        break;
                    610:        }
                    611:        return r;
                    612: }
                    613: 
                    614: static void
                    615: dma_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value)
                    616: {
1.1.1.2   root      617:         hw_error("Unsupported short waccess. reg=" TARGET_FMT_plx "\n", addr);
1.1       root      618: }
                    619: 
                    620: static void
                    621: dma_update_state(struct fs_dma_ctrl *ctrl, int c)
                    622: {
1.1.1.5   root      623:        if (ctrl->channels[c].regs[RW_CFG] & 2)
                    624:                ctrl->channels[c].state = STOPPED;
                    625:        if (!(ctrl->channels[c].regs[RW_CFG] & 1))
                    626:                ctrl->channels[c].state = RST;
1.1       root      627: }
                    628: 
                    629: static void
1.1.1.5   root      630: dma_write(void *opaque, target_phys_addr_t addr,
                    631:          uint64_t val64, unsigned int size)
1.1       root      632: {
                    633:         struct fs_dma_ctrl *ctrl = opaque;
1.1.1.5   root      634:        uint32_t value = val64;
1.1       root      635:        int c;
                    636: 
1.1.1.5   root      637:        if (size != 4) {
                    638:                dma_winvalid(opaque, addr, value);
                    639:        }
                    640: 
1.1       root      641:         /* Make addr relative to this channel and bounded to nr regs.  */
                    642:        c = fs_channel(addr);
                    643:         addr &= 0xff;
                    644:         addr >>= 2;
                    645:         switch (addr)
                    646:        {
                    647:                case RW_DATA:
                    648:                        ctrl->channels[c].regs[addr] = value;
                    649:                        break;
                    650: 
                    651:                case RW_CFG:
                    652:                        ctrl->channels[c].regs[addr] = value;
                    653:                        dma_update_state(ctrl, c);
                    654:                        break;
                    655:                case RW_CMD:
                    656:                        /* continue.  */
                    657:                        if (value & ~1)
                    658:                                printf("Invalid store to ch=%d RW_CMD %x\n",
                    659:                                       c, value);
                    660:                        ctrl->channels[c].regs[addr] = value;
                    661:                        channel_continue(ctrl, c);
                    662:                        break;
                    663: 
                    664:                case RW_SAVED_DATA:
                    665:                case RW_SAVED_DATA_BUF:
                    666:                case RW_GROUP:
                    667:                case RW_GROUP_DOWN:
                    668:                        ctrl->channels[c].regs[addr] = value;
                    669:                        break;
                    670: 
                    671:                case RW_ACK_INTR:
                    672:                case RW_INTR_MASK:
                    673:                        ctrl->channels[c].regs[addr] = value;
                    674:                        channel_update_irq(ctrl, c);
                    675:                        if (addr == RW_ACK_INTR)
                    676:                                ctrl->channels[c].regs[RW_ACK_INTR] = 0;
                    677:                        break;
                    678: 
                    679:                case RW_STREAM_CMD:
                    680:                        if (value & ~1023)
                    681:                                printf("Invalid store to ch=%d "
                    682:                                       "RW_STREAMCMD %x\n",
                    683:                                       c, value);
                    684:                        ctrl->channels[c].regs[addr] = value;
                    685:                        D(printf("stream_cmd ch=%d\n", c));
                    686:                        channel_stream_cmd(ctrl, c, value);
                    687:                        break;
                    688: 
                    689:                default:
1.1.1.2   root      690:                        D(printf ("%s c=%d " TARGET_FMT_plx "\n",
                    691:                                __func__, c, addr));
1.1       root      692:                        break;
                    693:         }
                    694: }
                    695: 
1.1.1.5   root      696: static const MemoryRegionOps dma_ops = {
                    697:        .read = dma_read,
                    698:        .write = dma_write,
                    699:        .endianness = DEVICE_NATIVE_ENDIAN,
                    700:        .valid = {
                    701:                .min_access_size = 1,
                    702:                .max_access_size = 4
                    703:        }
1.1       root      704: };
                    705: 
                    706: static int etraxfs_dmac_run(void *opaque)
                    707: {
                    708:        struct fs_dma_ctrl *ctrl = opaque;
                    709:        int i;
                    710:        int p = 0;
                    711: 
                    712:        for (i = 0; 
                    713:             i < ctrl->nr_channels;
                    714:             i++)
                    715:        {
                    716:                if (ctrl->channels[i].state == RUNNING)
                    717:                {
                    718:                        if (ctrl->channels[i].input) {
                    719:                                p += channel_in_run(ctrl, i);
                    720:                        } else {
                    721:                                p += channel_out_run(ctrl, i);
                    722:                        }
                    723:                }
                    724:        }
                    725:        return p;
                    726: }
                    727: 
                    728: int etraxfs_dmac_input(struct etraxfs_dma_client *client, 
                    729:                       void *buf, int len, int eop)
                    730: {
                    731:        return channel_in_process(client->ctrl, client->channel, 
                    732:                                  buf, len, eop);
                    733: }
                    734: 
                    735: /* Connect an IRQ line with a channel.  */
                    736: void etraxfs_dmac_connect(void *opaque, int c, qemu_irq *line, int input)
                    737: {
                    738:        struct fs_dma_ctrl *ctrl = opaque;
1.1.1.2   root      739:        ctrl->channels[c].irq = *line;
1.1       root      740:        ctrl->channels[c].input = input;
                    741: }
                    742: 
                    743: void etraxfs_dmac_connect_client(void *opaque, int c, 
                    744:                                 struct etraxfs_dma_client *cl)
                    745: {
                    746:        struct fs_dma_ctrl *ctrl = opaque;
                    747:        cl->ctrl = ctrl;
                    748:        cl->channel = c;
                    749:        ctrl->channels[c].client = cl;
                    750: }
                    751: 
                    752: 
                    753: static void DMA_run(void *opaque)
                    754: {
                    755:     struct fs_dma_ctrl *etraxfs_dmac = opaque;
                    756:     int p = 1;
                    757: 
1.1.1.5   root      758:     if (runstate_is_running())
1.1       root      759:         p = etraxfs_dmac_run(etraxfs_dmac);
                    760: 
                    761:     if (p)
                    762:         qemu_bh_schedule_idle(etraxfs_dmac->bh);
                    763: }
                    764: 
1.1.1.2   root      765: void *etraxfs_dmac_init(target_phys_addr_t base, int nr_channels)
1.1       root      766: {
                    767:        struct fs_dma_ctrl *ctrl = NULL;
                    768: 
1.1.1.5   root      769:        ctrl = g_malloc0(sizeof *ctrl);
1.1       root      770: 
                    771:         ctrl->bh = qemu_bh_new(DMA_run, ctrl);
                    772: 
                    773:        ctrl->nr_channels = nr_channels;
1.1.1.5   root      774:        ctrl->channels = g_malloc0(sizeof ctrl->channels[0] * nr_channels);
                    775: 
                    776:        memory_region_init_io(&ctrl->mmio, &dma_ops, ctrl, "etraxfs-dma",
                    777:                              nr_channels * 0x2000);
                    778:        memory_region_add_subregion(get_system_memory(), base, &ctrl->mmio);
1.1       root      779: 
                    780:        return ctrl;
                    781: }

unix.superglobalmegacorp.com

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