OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [tags/] [rel-0-3-0-rc3/] [or1ksim/] [peripheral/] [dma.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 212 erez
/* dma.c -- Simulation of DMA
2 1748 jeremybenn
 
3 503 erez
   Copyright (C) 2001 by Erez Volk, erez@opencores.org
4 1748 jeremybenn
   Copyright (C) 2008 Embecosm Limited
5 212 erez
 
6 1748 jeremybenn
   Contributor Jeremy Bennett <jeremy.bennett@embecosm.com>
7 212 erez
 
8 1748 jeremybenn
   This file is part of Or1ksim, the OpenRISC 1000 Architectural Simulator.
9 212 erez
 
10 1748 jeremybenn
   This program is free software; you can redistribute it and/or modify it
11
   under the terms of the GNU General Public License as published by the Free
12
   Software Foundation; either version 3 of the License, or (at your option)
13
   any later version.
14 212 erez
 
15 1748 jeremybenn
   This program is distributed in the hope that it will be useful, but WITHOUT
16
   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17
   FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
18
   more details.
19 1308 phoenix
 
20 1748 jeremybenn
   You should have received a copy of the GNU General Public License along
21
   with this program.  If not, see <http://www.gnu.org/licenses/>.  */
22
 
23
/* This program is commented throughout in a fashion suitable for processing
24
   with Doxygen. */
25
 
26
/* This simulation of the DMA core is not meant to be full.  It is written
27
   only to allow simulating the Ethernet core.  Of course, if anyone feels
28
   like perfecting it, feel free...  */
29
 
30
 
31
/* Autoconf and/or portability configuration */
32 1350 nogj
#include "config.h"
33 1748 jeremybenn
#include "port.h"
34 1350 nogj
 
35 1748 jeremybenn
/* System includes */
36
#include <stdlib.h>
37 1350 nogj
 
38 1748 jeremybenn
/* Package includes */
39 212 erez
#include "dma.h"
40 1748 jeremybenn
#include "fields.h"
41 235 erez
#include "abstract.h"
42 1370 nogj
#include "sched.h"
43 1748 jeremybenn
#include "pic.h"
44
#include "toplevel-support.h"
45
#include "sim-cmd.h"
46 212 erez
 
47 1491 nogj
 
48 1370 nogj
/* We keep a copy of all our controllers because we have to export an interface
49
 * to other peripherals eg. ethernet */
50
static struct dma_controller *dmas = NULL;
51 212 erez
 
52 1748 jeremybenn
static unsigned long dma_read_ch_csr (struct dma_channel *channel);
53
static void dma_write_ch_csr (struct dma_channel *channel,
54
                              unsigned long value);
55
static void dma_load_descriptor (struct dma_channel *channel);
56
static void dma_init_transfer (struct dma_channel *channel);
57
static void dma_channel_terminate_transfer (struct dma_channel *channel,
58
                                            int generate_interrupt);
59 212 erez
 
60 1748 jeremybenn
static void dma_channel_clock (void *dat);
61 212 erez
 
62 1748 jeremybenn
static void masked_increase (oraddr_t * value, unsigned long mask);
63 1370 nogj
 
64 212 erez
#define CHANNEL_ND_I(ch) (TEST_FLAG(ch->regs.csr,DMA_CH_CSR,MODE) && TEST_FLAG(ch->regs.csr,DMA_CH_CSR,USE_ED) && ch->dma_nd_i)
65
 
66
 
67
/* Reset. Initializes all registers to default and places devices in memory address space. */
68 1748 jeremybenn
static void
69
dma_reset (void *dat)
70 212 erez
{
71 1370 nogj
  struct dma_controller *dma = dat;
72
  unsigned channel_number;
73 212 erez
 
74 1748 jeremybenn
  memset (dma->ch, 0, sizeof (dma->ch));
75 1370 nogj
 
76
  dma->regs.csr = 0;
77
  dma->regs.int_msk_a = 0;
78
  dma->regs.int_msk_b = 0;
79
  dma->regs.int_src_a = 0;
80
  dma->regs.int_src_b = 0;
81 1748 jeremybenn
 
82
  for (channel_number = 0; channel_number < DMA_NUM_CHANNELS;
83
       ++channel_number)
84
    {
85
      dma->ch[channel_number].controller = dma;
86
      dma->ch[channel_number].channel_number = channel_number;
87
      dma->ch[channel_number].channel_mask = 1LU << channel_number;
88
      dma->ch[channel_number].regs.am0 = dma->ch[channel_number].regs.am1 =
89
        0xFFFFFFFC;
90
    }
91 212 erez
}
92
 
93
/* Print register values on stdout */
94 1748 jeremybenn
static void
95
dma_status (void *dat)
96 212 erez
{
97 1465 nogj
  unsigned j;
98 1370 nogj
  struct dma_controller *dma = dat;
99 212 erez
 
100 1748 jeremybenn
  if (dma->baseaddr == 0)
101 1370 nogj
    return;
102 212 erez
 
103 1748 jeremybenn
  PRINTF ("\nDMA controller at 0x%" PRIxADDR ":\n", dma->baseaddr);
104
  PRINTF ("CSR       : 0x%08lX\n", dma->regs.csr);
105
  PRINTF ("INT_MSK_A : 0x%08lX\n", dma->regs.int_msk_a);
106
  PRINTF ("INT_MSK_B : 0x%08lX\n", dma->regs.int_msk_b);
107
  PRINTF ("INT_SRC_A : 0x%08lX\n", dma->regs.int_src_a);
108
  PRINTF ("INT_SRC_B : 0x%08lX\n", dma->regs.int_src_b);
109 212 erez
 
110 1748 jeremybenn
  for (j = 0; j < DMA_NUM_CHANNELS; ++j)
111
    {
112
      struct dma_channel *channel = &(dma->ch[j]);
113
      if (!channel->referenced)
114
        continue;
115
      PRINTF ("CH%u_CSR   : 0x%08lX\n", j, channel->regs.csr);
116
      PRINTF ("CH%u_SZ    : 0x%08lX\n", j, channel->regs.sz);
117
      PRINTF ("CH%u_A0    : 0x%08lX\n", j, channel->regs.a0);
118
      PRINTF ("CH%u_AM0   : 0x%08lX\n", j, channel->regs.am0);
119
      PRINTF ("CH%u_A1    : 0x%08lX\n", j, channel->regs.a1);
120
      PRINTF ("CH%u_AM1   : 0x%08lX\n", j, channel->regs.am1);
121
      PRINTF ("CH%u_DESC  : 0x%08lX\n", j, channel->regs.desc);
122
      PRINTF ("CH%u_SWPTR : 0x%08lX\n", j, channel->regs.swptr);
123
    }
124 212 erez
}
125
 
126 1370 nogj
 
127 212 erez
/* Read a register */
128 1748 jeremybenn
static uint32_t
129
dma_read32 (oraddr_t addr, void *dat)
130 212 erez
{
131 1370 nogj
  struct dma_controller *dma = dat;
132 1715 nogj
  uint32_t ret;
133 212 erez
 
134 1748 jeremybenn
  if (addr < DMA_CH_BASE)
135
    {
136
      /* case of global (not per-channel) registers */
137
      switch (addr)
138
        {
139
        case DMA_CSR:
140
          return dma->regs.csr;
141
        case DMA_INT_MSK_A:
142
          return dma->regs.int_msk_a;
143
        case DMA_INT_MSK_B:
144
          return dma->regs.int_msk_b;
145
        case DMA_INT_SRC_A:
146
          if (dma->regs.int_src_a)
147
            clear_interrupt (dma->irq);
148
          ret = dma->regs.int_src_a;
149
          dma->regs.int_src_a = 0;
150
          return ret;
151
        case DMA_INT_SRC_B:
152
          return dma->regs.int_src_b;
153
        default:
154
          fprintf (stderr,
155
                   "dma_read32( 0x%" PRIxADDR " ): Illegal register\n",
156
                   addr + dma->baseaddr);
157
          return 0;
158
        }
159 503 erez
    }
160 1748 jeremybenn
  else
161
    {
162
      /* case of per-channel registers */
163
      unsigned chno = (addr - DMA_CH_BASE) / DMA_CH_SIZE;
164
      addr = (addr - DMA_CH_BASE) % DMA_CH_SIZE;
165
      switch (addr)
166
        {
167
        case DMA_CH_CSR:
168
          return dma_read_ch_csr (&(dma->ch[chno]));
169
        case DMA_CH_SZ:
170
          return dma->ch[chno].regs.sz;
171
        case DMA_CH_A0:
172
          return dma->ch[chno].regs.a0;
173
        case DMA_CH_AM0:
174
          return dma->ch[chno].regs.am0;
175
        case DMA_CH_A1:
176
          return dma->ch[chno].regs.a1;
177
        case DMA_CH_AM1:
178
          return dma->ch[chno].regs.am1;
179
        case DMA_CH_DESC:
180
          return dma->ch[chno].regs.desc;
181
        case DMA_CH_SWPTR:
182
          return dma->ch[chno].regs.swptr;
183
        }
184 503 erez
    }
185 1370 nogj
  return 0;
186 212 erez
}
187
 
188
 
189
/* Handle read from a channel CSR */
190 1748 jeremybenn
static unsigned long
191
dma_read_ch_csr (struct dma_channel *channel)
192 212 erez
{
193 503 erez
  unsigned long result = channel->regs.csr;
194 212 erez
 
195 503 erez
  /* before returning, clear all relevant bits */
196 1748 jeremybenn
  CLEAR_FLAG (channel->regs.csr, DMA_CH_CSR, INT_CHUNK_DONE);
197
  CLEAR_FLAG (channel->regs.csr, DMA_CH_CSR, INT_DONE);
198
  CLEAR_FLAG (channel->regs.csr, DMA_CH_CSR, INT_ERR);
199
  CLEAR_FLAG (channel->regs.csr, DMA_CH_CSR, ERR);
200 212 erez
 
201 503 erez
  return result;
202 212 erez
}
203
 
204
 
205
 
206
/* Write a register */
207 1748 jeremybenn
static void
208
dma_write32 (oraddr_t addr, uint32_t value, void *dat)
209 212 erez
{
210 1370 nogj
  struct dma_controller *dma = dat;
211 212 erez
 
212 503 erez
  /* case of global (not per-channel) registers */
213 1748 jeremybenn
  if (addr < DMA_CH_BASE)
214
    {
215
      switch (addr)
216
        {
217
        case DMA_CSR:
218
          if (TEST_FLAG (value, DMA_CSR, PAUSE))
219
            fprintf (stderr, "dma: PAUSE not implemented\n");
220
          break;
221 212 erez
 
222 1748 jeremybenn
        case DMA_INT_MSK_A:
223
          dma->regs.int_msk_a = value;
224
          break;
225
        case DMA_INT_MSK_B:
226
          dma->regs.int_msk_b = value;
227
          break;
228
        case DMA_INT_SRC_A:
229
          dma->regs.int_src_a = value;
230
          break;
231
        case DMA_INT_SRC_B:
232
          dma->regs.int_src_b = value;
233
          break;
234
        default:
235
          fprintf (stderr,
236
                   "dma_write32( 0x%" PRIxADDR " ): Illegal register\n",
237
                   addr + dma->baseaddr);
238
          return;
239
        }
240 503 erez
    }
241 1748 jeremybenn
  else
242
    {
243
      /* case of per-channel registers */
244
      unsigned chno = (addr - DMA_CH_BASE) / DMA_CH_SIZE;
245
      struct dma_channel *channel = &(dma->ch[chno]);
246
      channel->referenced = 1;
247
      addr = (addr - DMA_CH_BASE) % DMA_CH_SIZE;
248
      switch (addr)
249
        {
250
        case DMA_CSR:
251
          dma_write_ch_csr (&(dma->ch[chno]), value);
252
          break;
253
        case DMA_CH_SZ:
254
          channel->regs.sz = value;
255
          break;
256
        case DMA_CH_A0:
257
          channel->regs.a0 = value;
258
          break;
259
        case DMA_CH_AM0:
260
          channel->regs.am0 = value;
261
          break;
262
        case DMA_CH_A1:
263
          channel->regs.a1 = value;
264
          break;
265
        case DMA_CH_AM1:
266
          channel->regs.am1 = value;
267
          break;
268
        case DMA_CH_DESC:
269
          channel->regs.desc = value;
270
          break;
271
        case DMA_CH_SWPTR:
272
          channel->regs.swptr = value;
273
          break;
274
        }
275 503 erez
    }
276 212 erez
}
277
 
278
 
279
/* Write a channel CSR
280
 * This ensures only the writable bits are modified.
281
 */
282 1748 jeremybenn
static void
283
dma_write_ch_csr (struct dma_channel *channel, unsigned long value)
284 212 erez
{
285 1370 nogj
  /* Check if we should *start* a transfer */
286 1748 jeremybenn
  if (!TEST_FLAG (channel->regs.csr, DMA_CH_CSR, CH_EN) &&
287
      TEST_FLAG (value, DMA_CH_CSR, CH_EN))
288
    SCHED_ADD (dma_channel_clock, channel, 1);
289
  else if (!TEST_FLAG (value, DMA_CH_CSR, CH_EN))
290 1370 nogj
    /* The CH_EN flag is clear, check if we have a transfer in progress and
291
     * clear it */
292 1748 jeremybenn
    SCHED_FIND_REMOVE (dma_channel_clock, channel);
293 1370 nogj
 
294 503 erez
  /* Copy the writable bits to the channel CSR */
295
  channel->regs.csr &= ~DMA_CH_CSR_WRITE_MASK;
296
  channel->regs.csr |= value & DMA_CH_CSR_WRITE_MASK;
297 212 erez
}
298
 
299
 
300
 
301 1370 nogj
/* Clock tick for one channel on one DMA controller.
302 212 erez
 * This does the actual "DMA" operation.
303
 * One chunk is transferred per clock.
304
 */
305 1748 jeremybenn
static void
306
dma_channel_clock (void *dat)
307 212 erez
{
308 1370 nogj
  struct dma_channel *channel = dat;
309 1748 jeremybenn
 
310 1370 nogj
  /* Do we need to abort? */
311 1748 jeremybenn
  if (TEST_FLAG (channel->regs.csr, DMA_CH_CSR, STOP))
312
    {
313
      CLEAR_FLAG (channel->regs.csr, DMA_CH_CSR, CH_EN);
314
      CLEAR_FLAG (channel->regs.csr, DMA_CH_CSR, BUSY);
315
      SET_FLAG (channel->regs.csr, DMA_CH_CSR, ERR);
316 256 erez
 
317 1748 jeremybenn
      if (TEST_FLAG (channel->regs.csr, DMA_CH_CSR, INE_ERR) &&
318
          (channel->controller->regs.int_msk_a & channel->channel_mask))
319
        {
320
          SET_FLAG (channel->regs.csr, DMA_CH_CSR, INT_ERR);
321
          channel->controller->regs.int_src_a = channel->channel_mask;
322
          report_interrupt (channel->controller->irq);
323
        }
324
 
325
      return;
326 503 erez
    }
327 212 erez
 
328 1370 nogj
  /* In HW Handshake mode, only work when dma_req_i asserted */
329 1748 jeremybenn
  if (TEST_FLAG (channel->regs.csr, DMA_CH_CSR, MODE) && !channel->dma_req_i)
330
    {
331
      /* Reschedule */
332
      SCHED_ADD (dma_channel_clock, dat, 1);
333
      return;
334
    }
335 212 erez
 
336 1370 nogj
  /* If this is the first cycle of the transfer, initialize our state */
337 1748 jeremybenn
  if (!TEST_FLAG (channel->regs.csr, DMA_CH_CSR, BUSY))
338
    {
339
      CLEAR_FLAG (channel->regs.csr, DMA_CH_CSR, DONE);
340
      CLEAR_FLAG (channel->regs.csr, DMA_CH_CSR, ERR);
341
      SET_FLAG (channel->regs.csr, DMA_CH_CSR, BUSY);
342 212 erez
 
343 1748 jeremybenn
      /* If using linked lists, copy the appropriate fields to our registers */
344
      if (TEST_FLAG (channel->regs.csr, DMA_CH_CSR, USE_ED))
345
        dma_load_descriptor (channel);
346
      else
347
        channel->load_next_descriptor_when_done = 0;
348 212 erez
 
349 1748 jeremybenn
      /* Set our internal status */
350
      dma_init_transfer (channel);
351 212 erez
 
352 1748 jeremybenn
      /* Might need to skip descriptor */
353
      if (CHANNEL_ND_I (channel))
354
        {
355
          dma_channel_terminate_transfer (channel, 0);
356
          return;
357
        }
358 503 erez
    }
359 235 erez
 
360 1370 nogj
  /* Transfer one word */
361 1748 jeremybenn
  set_direct32 (channel->destination, eval_direct32 (channel->source, 0, 0),
362
                0, 0);
363 1370 nogj
 
364
  /* Advance the source and destionation pointers */
365 1748 jeremybenn
  masked_increase (&(channel->source), channel->source_mask);
366
  masked_increase (&(channel->destination), channel->destination_mask);
367
  ++channel->words_transferred;
368 1370 nogj
 
369
  /* Have we finished a whole chunk? */
370 1748 jeremybenn
  channel->dma_ack_o =
371
    (channel->words_transferred % channel->chunk_size == 0);
372 1370 nogj
 
373
  /* When done with a chunk, check for dma_nd_i */
374 1748 jeremybenn
  if (CHANNEL_ND_I (channel))
375
    {
376
      dma_channel_terminate_transfer (channel, 0);
377
      return;
378
    }
379 1370 nogj
 
380
  /* Are we done? */
381 1748 jeremybenn
  if (channel->words_transferred >= channel->total_size)
382
    {
383
      dma_channel_terminate_transfer (channel, 1);
384
      return;
385
    }
386 1370 nogj
 
387
  /* Reschedule to transfer the next chunk */
388 1748 jeremybenn
  SCHED_ADD (dma_channel_clock, dat, 1);
389 212 erez
}
390
 
391
 
392
/* Copy relevant valued from linked list descriptor to channel registers */
393 1748 jeremybenn
static void
394
dma_load_descriptor (struct dma_channel *channel)
395 212 erez
{
396 1748 jeremybenn
  unsigned long desc_csr =
397
    eval_direct32 (channel->regs.desc + DMA_DESC_CSR, 0, 0);
398 212 erez
 
399 1748 jeremybenn
  channel->load_next_descriptor_when_done =
400
    !TEST_FLAG (desc_csr, DMA_DESC_CSR, EOL);
401 212 erez
 
402 1748 jeremybenn
  ASSIGN_FLAG (channel->regs.csr, DMA_CH_CSR, INC_SRC,
403
               TEST_FLAG (desc_csr, DMA_DESC_CSR, INC_SRC));
404
  ASSIGN_FLAG (channel->regs.csr, DMA_CH_CSR, INC_DST,
405
               TEST_FLAG (desc_csr, DMA_DESC_CSR, INC_DST));
406
  ASSIGN_FLAG (channel->regs.csr, DMA_CH_CSR, SRC_SEL,
407
               TEST_FLAG (desc_csr, DMA_DESC_CSR, SRC_SEL));
408
  ASSIGN_FLAG (channel->regs.csr, DMA_CH_CSR, DST_SEL,
409
               TEST_FLAG (desc_csr, DMA_DESC_CSR, DST_SEL));
410 212 erez
 
411 1748 jeremybenn
  SET_FIELD (channel->regs.sz, DMA_CH_SZ, TOT_SZ,
412
             GET_FIELD (desc_csr, DMA_DESC_CSR, TOT_SZ));
413
 
414
  channel->regs.a0 = eval_direct32 (channel->regs.desc + DMA_DESC_ADR0, 0, 0);
415
  channel->regs.a1 = eval_direct32 (channel->regs.desc + DMA_DESC_ADR1, 0, 0);
416
 
417 503 erez
  channel->current_descriptor = channel->regs.desc;
418 1748 jeremybenn
  channel->regs.desc =
419
    eval_direct32 (channel->regs.desc + DMA_DESC_NEXT, 0, 0);
420 212 erez
}
421
 
422
 
423
/* Initialize internal parameters used to implement transfers */
424 1748 jeremybenn
static void
425
dma_init_transfer (struct dma_channel *channel)
426 212 erez
{
427 503 erez
  channel->source = channel->regs.a0;
428
  channel->destination = channel->regs.a1;
429 1748 jeremybenn
  channel->source_mask =
430
    TEST_FLAG (channel->regs.csr, DMA_CH_CSR,
431
               INC_SRC) ? channel->regs.am0 : 0;
432
  channel->destination_mask =
433
    TEST_FLAG (channel->regs.csr, DMA_CH_CSR,
434
               INC_DST) ? channel->regs.am1 : 0;
435
  channel->total_size = GET_FIELD (channel->regs.sz, DMA_CH_SZ, TOT_SZ);
436
  channel->chunk_size = GET_FIELD (channel->regs.sz, DMA_CH_SZ, CHK_SZ);
437
  if (!channel->chunk_size || (channel->chunk_size > channel->total_size))
438 503 erez
    channel->chunk_size = channel->total_size;
439
  channel->words_transferred = 0;
440 212 erez
}
441
 
442
 
443
/* Take care of transfer termination */
444 1748 jeremybenn
static void
445
dma_channel_terminate_transfer (struct dma_channel *channel,
446
                                int generate_interrupt)
447 212 erez
{
448 503 erez
  /* Might be working in a linked list */
449 1748 jeremybenn
  if (channel->load_next_descriptor_when_done)
450
    {
451
      dma_load_descriptor (channel);
452
      dma_init_transfer (channel);
453
      /* Reschedule */
454
      SCHED_ADD (dma_channel_clock, channel, 1);
455
      return;
456
    }
457 212 erez
 
458 503 erez
  /* Might be in auto-restart mode */
459 1748 jeremybenn
  if (TEST_FLAG (channel->regs.csr, DMA_CH_CSR, ARS))
460
    {
461
      dma_init_transfer (channel);
462
      return;
463
    }
464 212 erez
 
465 503 erez
  /* If needed, write amount of data transferred back to memory */
466 1748 jeremybenn
  if (TEST_FLAG (channel->regs.csr, DMA_CH_CSR, SZ_WB) &&
467
      TEST_FLAG (channel->regs.csr, DMA_CH_CSR, USE_ED))
468
    {
469
      /* TODO: What should we write back? Doc says "total number of remaining bytes" !? */
470
      unsigned long remaining_words =
471
        channel->total_size - channel->words_transferred;
472
      SET_FIELD (channel->regs.sz, DMA_DESC_CSR, TOT_SZ, remaining_words);
473
    }
474 212 erez
 
475 503 erez
  /* Mark end of transfer */
476 1748 jeremybenn
  CLEAR_FLAG (channel->regs.csr, DMA_CH_CSR, CH_EN);
477
  SET_FLAG (channel->regs.csr, DMA_CH_CSR, DONE);
478
  CLEAR_FLAG (channel->regs.csr, DMA_CH_CSR, ERR);
479
  CLEAR_FLAG (channel->regs.csr, DMA_CH_CSR, BUSY);
480
 
481 503 erez
  /* If needed, generate interrupt */
482 1748 jeremybenn
  if (generate_interrupt)
483
    {
484
      /* TODO: Which channel should we interrupt? */
485
      if (TEST_FLAG (channel->regs.csr, DMA_CH_CSR, INE_DONE) &&
486
          (channel->controller->regs.int_msk_a & channel->channel_mask))
487
        {
488
          SET_FLAG (channel->regs.csr, DMA_CH_CSR, INT_DONE);
489
          channel->controller->regs.int_src_a = channel->channel_mask;
490
          report_interrupt (channel->controller->irq);
491
        }
492 503 erez
    }
493 212 erez
}
494
 
495
/* Utility function: Add 4 to a value with a mask */
496 1748 jeremybenn
static void
497
masked_increase (oraddr_t * value, unsigned long mask)
498 212 erez
{
499 503 erez
  *value = (*value & ~mask) | ((*value + 4) & mask);
500 212 erez
}
501 1358 nogj
 
502 1370 nogj
/*-------------------------------------------[ DMA<->Peripheral interface ]---*/
503
/*
504
 * Simulation of control signals
505
 * To be used by simulations for other devices, e.g. ethernet
506
 */
507
 
508 1748 jeremybenn
void
509
set_dma_req_i (struct dma_channel *channel)
510 1358 nogj
{
511 1370 nogj
  channel->dma_req_i = 1;
512 1358 nogj
}
513
 
514 1748 jeremybenn
void
515
clear_dma_req_i (struct dma_channel *channel)
516 1370 nogj
{
517
  channel->dma_req_i = 0;
518
}
519
 
520 1748 jeremybenn
void
521
set_dma_nd_i (struct dma_channel *channel)
522 1370 nogj
{
523
  channel->dma_nd_i = 1;
524
}
525
 
526 1748 jeremybenn
void
527
clear_dma_nd_i (struct dma_channel *channel)
528 1370 nogj
{
529
  channel->dma_nd_i = 0;
530
}
531
 
532 1748 jeremybenn
unsigned
533
check_dma_ack_o (struct dma_channel *channel)
534 1370 nogj
{
535
  return channel->dma_ack_o;
536
}
537
 
538 1748 jeremybenn
struct dma_channel *
539
find_dma_controller_ch (unsigned controller, unsigned channel)
540 1370 nogj
{
541
  struct dma_controller *cur = dmas;
542
 
543 1748 jeremybenn
  while (cur && controller)
544
    {
545
      cur = cur->next;
546
      controller--;
547
    }
548 1370 nogj
 
549 1748 jeremybenn
  if (!cur)
550 1370 nogj
    return NULL;
551
 
552
  return &(cur->ch[channel]);
553
}
554
 
555
 
556
/*----------------------------------------------------[ DMA configuration ]---*/
557 1748 jeremybenn
static void
558
dma_baseaddr (union param_val val, void *dat)
559 1358 nogj
{
560 1370 nogj
  struct dma_controller *dma = dat;
561
  dma->baseaddr = val.addr_val;
562 1358 nogj
}
563
 
564 1748 jeremybenn
static void
565
dma_irq (union param_val val, void *dat)
566 1358 nogj
{
567 1370 nogj
  struct dma_controller *dma = dat;
568
  dma->irq = val.int_val;
569 1358 nogj
}
570
 
571 1748 jeremybenn
static void
572
dma_vapi_id (union param_val val, void *dat)
573 1358 nogj
{
574 1370 nogj
  struct dma_controller *dma = dat;
575
  dma->vapi_id = val.int_val;
576 1358 nogj
}
577
 
578 1748 jeremybenn
static void
579
dma_enabled (union param_val val, void *dat)
580 1461 nogj
{
581
  struct dma_controller *dma = dat;
582
  dma->enabled = val.int_val;
583
}
584
 
585 1748 jeremybenn
 
586
/*---------------------------------------------------------------------------*/
587
/*!Initialize a new DMA configuration
588
 
589
   ALL parameters are set explicitly to default values.                      */
590
/*---------------------------------------------------------------------------*/
591
static void *
592
dma_sec_start ()
593 1370 nogj
{
594 1748 jeremybenn
  struct dma_controller *new = malloc (sizeof (struct dma_controller));
595 1370 nogj
 
596 1748 jeremybenn
  if (!new)
597
    {
598
      fprintf (stderr, "Peripheral DMA: Run out of memory\n");
599
      exit (-1);
600
    }
601 1370 nogj
 
602
  new->next = NULL;
603 1748 jeremybenn
  new->enabled  = 1;
604
  new->baseaddr = 0;
605
  new->irq      = 0;
606
  new->vapi_id  = 0;
607 1370 nogj
 
608
  return new;
609
 
610 1748 jeremybenn
}       /* dma_sec_start() */
611
 
612
static void
613
dma_sec_end (void *dat)
614 1370 nogj
{
615
  struct dma_controller *dma = dat;
616
  struct dma_controller *cur;
617 1486 nogj
  struct mem_ops ops;
618 1370 nogj
 
619 1748 jeremybenn
  if (!dma->enabled)
620
    {
621
      free (dat);
622
      return;
623
    }
624 1461 nogj
 
625 1748 jeremybenn
  memset (&ops, 0, sizeof (struct mem_ops));
626 1486 nogj
 
627
  ops.readfunc32 = dma_read32;
628
  ops.writefunc32 = dma_write32;
629
  ops.read_dat32 = dat;
630
  ops.write_dat32 = dat;
631
 
632
  /* FIXME: Correct delay?? */
633
  ops.delayr = 2;
634
  ops.delayw = 2;
635
 
636 1748 jeremybenn
  reg_mem_area (dma->baseaddr, DMA_ADDR_SPACE, 0, &ops);
637
  reg_sim_reset (dma_reset, dat);
638
  reg_sim_stat (dma_status, dat);
639 1370 nogj
 
640 1748 jeremybenn
  if (dmas)
641
    {
642
      for (cur = dmas; cur->next; cur = cur->next);
643
      cur->next = dma;
644
    }
645
  else
646 1370 nogj
    dmas = dma;
647
}
648
 
649 1748 jeremybenn
void
650
reg_dma_sec (void)
651 1358 nogj
{
652 1748 jeremybenn
  struct config_section *sec =
653
    reg_config_sec ("dma", dma_sec_start, dma_sec_end);
654 1358 nogj
 
655 1748 jeremybenn
  reg_config_param (sec, "enabled", paramt_int, dma_enabled);
656
  reg_config_param (sec, "baseaddr", paramt_addr, dma_baseaddr);
657
  reg_config_param (sec, "irq", paramt_int, dma_irq);
658
  reg_config_param (sec, "vapi_id", paramt_addr, dma_vapi_id);
659 1358 nogj
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.