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

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

unix.superglobalmegacorp.com

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