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

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: 
                    183:        /* Controll registers.  */
                    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: 
                    404:        if (ctrl->channels[c].eol)
                    405:                return 0;
                    406: 
                    407:        do {
1.1.1.2   root      408:                D(printf("ch=%d buf=%x after=%x\n",
1.1       root      409:                         c,
                    410:                         (uint32_t)ctrl->channels[c].current_d.buf,
1.1.1.2   root      411:                         (uint32_t)ctrl->channels[c].current_d.after));
1.1       root      412: 
                    413:                channel_load_d(ctrl, c);
                    414:                saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF);
                    415:                len = (uint32_t)(unsigned long)
                    416:                        ctrl->channels[c].current_d.after;
                    417:                len -= saved_data_buf;
                    418: 
                    419:                if (len > sizeof buf)
                    420:                        len = sizeof buf;
                    421:                cpu_physical_memory_read (saved_data_buf, buf, len);
                    422: 
                    423:                D(printf("channel %d pushes %x %u bytes\n", c, 
                    424:                         saved_data_buf, len));
                    425: 
                    426:                if (ctrl->channels[c].client->client.push)
                    427:                        ctrl->channels[c].client->client.push(
                    428:                                ctrl->channels[c].client->client.opaque,
                    429:                                buf, len);
                    430:                else
                    431:                        printf("WARNING: DMA ch%d dataloss,"
                    432:                               " no attached client.\n", c);
                    433: 
                    434:                saved_data_buf += len;
                    435: 
                    436:                if (saved_data_buf == (uint32_t)(unsigned long)
                    437:                                ctrl->channels[c].current_d.after) {
                    438:                        /* Done. Step to next.  */
                    439:                        if (ctrl->channels[c].current_d.out_eop) {
                    440:                                /* TODO: signal eop to the client.  */
                    441:                                D(printf("signal eop\n"));
                    442:                        }
                    443:                        if (ctrl->channels[c].current_d.intr) {
                    444:                                /* TODO: signal eop to the client.  */
                    445:                                /* data intr.  */
                    446:                                D(printf("signal intr %d eol=%d\n",
                    447:                                        len, ctrl->channels[c].current_d.eol));
                    448:                                ctrl->channels[c].regs[R_INTR] |= (1 << 2);
                    449:                                channel_update_irq(ctrl, c);
                    450:                        }
                    451:                        channel_store_d(ctrl, c);
                    452:                        if (ctrl->channels[c].current_d.eol) {
                    453:                                D(printf("channel %d EOL\n", c));
                    454:                                ctrl->channels[c].eol = 1;
                    455: 
                    456:                                /* Mark the context as disabled.  */
                    457:                                ctrl->channels[c].current_c.dis = 1;
                    458:                                channel_store_c(ctrl, c);
                    459: 
                    460:                                channel_stop(ctrl, c);
                    461:                        } else {
                    462:                                ctrl->channels[c].regs[RW_SAVED_DATA] =
                    463:                                        (uint32_t)(unsigned long)ctrl->
                    464:                                                channels[c].current_d.next;
                    465:                                /* Load new descriptor.  */
                    466:                                channel_load_d(ctrl, c);
                    467:                                saved_data_buf = (uint32_t)(unsigned long)
                    468:                                        ctrl->channels[c].current_d.buf;
                    469:                        }
                    470: 
                    471:                        ctrl->channels[c].regs[RW_SAVED_DATA_BUF] =
                    472:                                                        saved_data_buf;
                    473:                        D(dump_d(c, &ctrl->channels[c].current_d));
                    474:                }
                    475:                ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf;
                    476:        } while (!ctrl->channels[c].eol);
                    477:        return 1;
                    478: }
                    479: 
                    480: static int channel_in_process(struct fs_dma_ctrl *ctrl, int c, 
                    481:                              unsigned char *buf, int buflen, int eop)
                    482: {
                    483:        uint32_t len;
                    484:        uint32_t saved_data_buf;
                    485: 
                    486:        if (ctrl->channels[c].eol == 1)
                    487:                return 0;
                    488: 
                    489:        channel_load_d(ctrl, c);
                    490:        saved_data_buf = channel_reg(ctrl, c, RW_SAVED_DATA_BUF);
                    491:        len = (uint32_t)(unsigned long)ctrl->channels[c].current_d.after;
                    492:        len -= saved_data_buf;
                    493:        
                    494:        if (len > buflen)
                    495:                len = buflen;
                    496: 
                    497:        cpu_physical_memory_write (saved_data_buf, buf, len);
                    498:        saved_data_buf += len;
                    499: 
                    500:        if (saved_data_buf ==
                    501:            (uint32_t)(unsigned long)ctrl->channels[c].current_d.after
                    502:            || eop) {
                    503:                uint32_t r_intr = ctrl->channels[c].regs[R_INTR];
                    504: 
                    505:                D(printf("in dscr end len=%d\n", 
                    506:                         ctrl->channels[c].current_d.after
                    507:                         - ctrl->channels[c].current_d.buf));
1.1.1.2   root      508:                ctrl->channels[c].current_d.after = saved_data_buf;
1.1       root      509: 
                    510:                /* Done. Step to next.  */
                    511:                if (ctrl->channels[c].current_d.intr) {
                    512:                        /* TODO: signal eop to the client.  */
                    513:                        /* data intr.  */
                    514:                        ctrl->channels[c].regs[R_INTR] |= 3;
                    515:                }
                    516:                if (eop) {
                    517:                        ctrl->channels[c].current_d.in_eop = 1;
                    518:                        ctrl->channels[c].regs[R_INTR] |= 8;
                    519:                }
                    520:                if (r_intr != ctrl->channels[c].regs[R_INTR])
                    521:                        channel_update_irq(ctrl, c);
                    522: 
                    523:                channel_store_d(ctrl, c);
                    524:                D(dump_d(c, &ctrl->channels[c].current_d));
                    525: 
                    526:                if (ctrl->channels[c].current_d.eol) {
                    527:                        D(printf("channel %d EOL\n", c));
                    528:                        ctrl->channels[c].eol = 1;
                    529: 
                    530:                        /* Mark the context as disabled.  */
                    531:                        ctrl->channels[c].current_c.dis = 1;
                    532:                        channel_store_c(ctrl, c);
                    533: 
                    534:                        channel_stop(ctrl, c);
                    535:                } else {
                    536:                        ctrl->channels[c].regs[RW_SAVED_DATA] =
                    537:                                (uint32_t)(unsigned long)ctrl->
                    538:                                        channels[c].current_d.next;
                    539:                        /* Load new descriptor.  */
                    540:                        channel_load_d(ctrl, c);
                    541:                        saved_data_buf = (uint32_t)(unsigned long)
                    542:                                ctrl->channels[c].current_d.buf;
                    543:                }
                    544:        }
                    545: 
                    546:        ctrl->channels[c].regs[RW_SAVED_DATA_BUF] = saved_data_buf;
                    547:        return len;
                    548: }
                    549: 
                    550: static inline int channel_in_run(struct fs_dma_ctrl *ctrl, int c)
                    551: {
                    552:        if (ctrl->channels[c].client->client.pull) {
                    553:                ctrl->channels[c].client->client.pull(
                    554:                        ctrl->channels[c].client->client.opaque);
                    555:                return 1;
                    556:        } else
                    557:                return 0;
                    558: }
                    559: 
                    560: static uint32_t dma_rinvalid (void *opaque, target_phys_addr_t addr)
                    561: {
1.1.1.2   root      562:         hw_error("Unsupported short raccess. reg=" TARGET_FMT_plx "\n", addr);
1.1       root      563:         return 0;
                    564: }
                    565: 
1.1.1.5 ! root      566: static uint64_t
        !           567: dma_read(void *opaque, target_phys_addr_t addr, unsigned int size)
1.1       root      568: {
                    569:         struct fs_dma_ctrl *ctrl = opaque;
                    570:        int c;
                    571:        uint32_t r = 0;
                    572: 
1.1.1.5 ! root      573:        if (size != 4) {
        !           574:                dma_rinvalid(opaque, addr);
        !           575:        }
        !           576: 
1.1       root      577:        /* Make addr relative to this channel and bounded to nr regs.  */
                    578:        c = fs_channel(addr);
                    579:        addr &= 0xff;
                    580:        addr >>= 2;
                    581:        switch (addr)
                    582:        {
                    583:                case RW_STAT:
                    584:                        r = ctrl->channels[c].state & 7;
                    585:                        r |= ctrl->channels[c].eol << 5;
                    586:                        r |= ctrl->channels[c].stream_cmd_src << 8;
                    587:                        break;
                    588: 
                    589:                default:
                    590:                        r = ctrl->channels[c].regs[addr];
1.1.1.2   root      591:                        D(printf ("%s c=%d addr=" TARGET_FMT_plx "\n",
1.1       root      592:                                  __func__, c, addr));
                    593:                        break;
                    594:        }
                    595:        return r;
                    596: }
                    597: 
                    598: static void
                    599: dma_winvalid (void *opaque, target_phys_addr_t addr, uint32_t value)
                    600: {
1.1.1.2   root      601:         hw_error("Unsupported short waccess. reg=" TARGET_FMT_plx "\n", addr);
1.1       root      602: }
                    603: 
                    604: static void
                    605: dma_update_state(struct fs_dma_ctrl *ctrl, int c)
                    606: {
1.1.1.5 ! root      607:        if (ctrl->channels[c].regs[RW_CFG] & 2)
        !           608:                ctrl->channels[c].state = STOPPED;
        !           609:        if (!(ctrl->channels[c].regs[RW_CFG] & 1))
        !           610:                ctrl->channels[c].state = RST;
1.1       root      611: }
                    612: 
                    613: static void
1.1.1.5 ! root      614: dma_write(void *opaque, target_phys_addr_t addr,
        !           615:          uint64_t val64, unsigned int size)
1.1       root      616: {
                    617:         struct fs_dma_ctrl *ctrl = opaque;
1.1.1.5 ! root      618:        uint32_t value = val64;
1.1       root      619:        int c;
                    620: 
1.1.1.5 ! root      621:        if (size != 4) {
        !           622:                dma_winvalid(opaque, addr, value);
        !           623:        }
        !           624: 
1.1       root      625:         /* Make addr relative to this channel and bounded to nr regs.  */
                    626:        c = fs_channel(addr);
                    627:         addr &= 0xff;
                    628:         addr >>= 2;
                    629:         switch (addr)
                    630:        {
                    631:                case RW_DATA:
                    632:                        ctrl->channels[c].regs[addr] = value;
                    633:                        break;
                    634: 
                    635:                case RW_CFG:
                    636:                        ctrl->channels[c].regs[addr] = value;
                    637:                        dma_update_state(ctrl, c);
                    638:                        break;
                    639:                case RW_CMD:
                    640:                        /* continue.  */
                    641:                        if (value & ~1)
                    642:                                printf("Invalid store to ch=%d RW_CMD %x\n",
                    643:                                       c, value);
                    644:                        ctrl->channels[c].regs[addr] = value;
                    645:                        channel_continue(ctrl, c);
                    646:                        break;
                    647: 
                    648:                case RW_SAVED_DATA:
                    649:                case RW_SAVED_DATA_BUF:
                    650:                case RW_GROUP:
                    651:                case RW_GROUP_DOWN:
                    652:                        ctrl->channels[c].regs[addr] = value;
                    653:                        break;
                    654: 
                    655:                case RW_ACK_INTR:
                    656:                case RW_INTR_MASK:
                    657:                        ctrl->channels[c].regs[addr] = value;
                    658:                        channel_update_irq(ctrl, c);
                    659:                        if (addr == RW_ACK_INTR)
                    660:                                ctrl->channels[c].regs[RW_ACK_INTR] = 0;
                    661:                        break;
                    662: 
                    663:                case RW_STREAM_CMD:
                    664:                        if (value & ~1023)
                    665:                                printf("Invalid store to ch=%d "
                    666:                                       "RW_STREAMCMD %x\n",
                    667:                                       c, value);
                    668:                        ctrl->channels[c].regs[addr] = value;
                    669:                        D(printf("stream_cmd ch=%d\n", c));
                    670:                        channel_stream_cmd(ctrl, c, value);
                    671:                        break;
                    672: 
                    673:                default:
1.1.1.2   root      674:                        D(printf ("%s c=%d " TARGET_FMT_plx "\n",
                    675:                                __func__, c, addr));
1.1       root      676:                        break;
                    677:         }
                    678: }
                    679: 
1.1.1.5 ! root      680: static const MemoryRegionOps dma_ops = {
        !           681:        .read = dma_read,
        !           682:        .write = dma_write,
        !           683:        .endianness = DEVICE_NATIVE_ENDIAN,
        !           684:        .valid = {
        !           685:                .min_access_size = 1,
        !           686:                .max_access_size = 4
        !           687:        }
1.1       root      688: };
                    689: 
                    690: static int etraxfs_dmac_run(void *opaque)
                    691: {
                    692:        struct fs_dma_ctrl *ctrl = opaque;
                    693:        int i;
                    694:        int p = 0;
                    695: 
                    696:        for (i = 0; 
                    697:             i < ctrl->nr_channels;
                    698:             i++)
                    699:        {
                    700:                if (ctrl->channels[i].state == RUNNING)
                    701:                {
                    702:                        if (ctrl->channels[i].input) {
                    703:                                p += channel_in_run(ctrl, i);
                    704:                        } else {
                    705:                                p += channel_out_run(ctrl, i);
                    706:                        }
                    707:                }
                    708:        }
                    709:        return p;
                    710: }
                    711: 
                    712: int etraxfs_dmac_input(struct etraxfs_dma_client *client, 
                    713:                       void *buf, int len, int eop)
                    714: {
                    715:        return channel_in_process(client->ctrl, client->channel, 
                    716:                                  buf, len, eop);
                    717: }
                    718: 
                    719: /* Connect an IRQ line with a channel.  */
                    720: void etraxfs_dmac_connect(void *opaque, int c, qemu_irq *line, int input)
                    721: {
                    722:        struct fs_dma_ctrl *ctrl = opaque;
1.1.1.2   root      723:        ctrl->channels[c].irq = *line;
1.1       root      724:        ctrl->channels[c].input = input;
                    725: }
                    726: 
                    727: void etraxfs_dmac_connect_client(void *opaque, int c, 
                    728:                                 struct etraxfs_dma_client *cl)
                    729: {
                    730:        struct fs_dma_ctrl *ctrl = opaque;
                    731:        cl->ctrl = ctrl;
                    732:        cl->channel = c;
                    733:        ctrl->channels[c].client = cl;
                    734: }
                    735: 
                    736: 
                    737: static void DMA_run(void *opaque)
                    738: {
                    739:     struct fs_dma_ctrl *etraxfs_dmac = opaque;
                    740:     int p = 1;
                    741: 
1.1.1.5 ! root      742:     if (runstate_is_running())
1.1       root      743:         p = etraxfs_dmac_run(etraxfs_dmac);
                    744: 
                    745:     if (p)
                    746:         qemu_bh_schedule_idle(etraxfs_dmac->bh);
                    747: }
                    748: 
1.1.1.2   root      749: void *etraxfs_dmac_init(target_phys_addr_t base, int nr_channels)
1.1       root      750: {
                    751:        struct fs_dma_ctrl *ctrl = NULL;
                    752: 
1.1.1.5 ! root      753:        ctrl = g_malloc0(sizeof *ctrl);
1.1       root      754: 
                    755:         ctrl->bh = qemu_bh_new(DMA_run, ctrl);
                    756: 
                    757:        ctrl->nr_channels = nr_channels;
1.1.1.5 ! root      758:        ctrl->channels = g_malloc0(sizeof ctrl->channels[0] * nr_channels);
        !           759: 
        !           760:        memory_region_init_io(&ctrl->mmio, &dma_ops, ctrl, "etraxfs-dma",
        !           761:                              nr_channels * 0x2000);
        !           762:        memory_region_add_subregion(get_system_memory(), base, &ctrl->mmio);
1.1       root      763: 
                    764:        return ctrl;
                    765: }

unix.superglobalmegacorp.com

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