GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / cfe / cfe / arch / mips / cpu / sb1250 / src / cfe_dmtest.c
blob8024b1436c0671b06879edb14b84b811bcde34a8
1 /* *********************************************************************
2 * Broadcom Common Firmware Environment (CFE)
3 *
4 * Test commands File: cfe_dmtest.c
5 *
6 * A temporary sandbox for data mover test routines and commands.
7 *
8 *********************************************************************
10 * Copyright 2000,2001,2002,2003
11 * Broadcom Corporation. All rights reserved.
13 * This software is furnished under license and may be used and
14 * copied only in accordance with the following terms and
15 * conditions. Subject to these conditions, you may download,
16 * copy, install, use, modify and distribute modified or unmodified
17 * copies of this software in source and/or binary form. No title
18 * or ownership is transferred hereby.
20 * 1) Any source code used, modified or distributed must reproduce
21 * and retain this copyright notice and list of conditions
22 * as they appear in the source file.
24 * 2) No right is granted to use any trade name, trademark, or
25 * logo of Broadcom Corporation. The "Broadcom Corporation"
26 * name may not be used to endorse or promote products derived
27 * from this software without the prior written permission of
28 * Broadcom Corporation.
30 * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
31 * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
32 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
33 * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
34 * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
35 * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
36 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
37 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
38 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
39 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
40 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
41 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
42 * THE POSSIBILITY OF SUCH DAMAGE.
43 ********************************************************************* */
46 #include "sbmips.h"
47 #include "sb1250_defs.h"
48 #include "sb1250_regs.h"
49 #include "sb1250_int.h"
50 #include "sb1250_dma.h"
51 /* pass 1 holdover */
52 #define M_DM_DSCRA_THROTTLE _SB_MAKEMASK1(43)
53 #ifdef _SENTOSA_
54 #include "sentosa.h"
55 #endif
57 #include "lib_types.h"
58 #include "lib_string.h"
59 #include "lib_malloc.h"
60 #include "lib_printf.h"
62 #include "cfe.h"
63 #include "ui_command.h"
64 #include "cfe_console.h"
65 #include "cfe_timer.h"
66 #include "cfe_iocb.h"
67 #include "cfe_devfuncs.h"
68 #include "cfe_irq.h"
70 #include "lib_hssubr.h"
71 #include "addrspace.h"
73 #ifdef __long64 /* Temporary hack */
75 static long
76 phys_addr(long va)
78 long pa;
80 if (va - K0BASE >= 0 && va - K0BASE < K0SIZE)
81 pa = K0_TO_PHYS(va);
82 else if (va - K1BASE >= 0 && va - K1BASE < K1SIZE)
83 pa = K1_TO_PHYS(va);
84 else
85 pa = XKPHYS_TO_PHYS(va);
87 return pa;
90 /* to be exported */
91 void dm_bzero(void *dest, int cnt);
92 void dm_bsink(void *src, int cnt);
93 void dm_bcopy(void *src, void *dest, int cnt);
94 void dm_multibcopy(void *src, void *dest, int cnt, int blksize);
96 static uint64_t zb_hz;
97 static uint64_t zb_mhz;
99 static int ui_cmd_zero(ui_cmdline_t *cmd, int argc, char *argv[]);
100 static int ui_cmd_sink(ui_cmdline_t *cmd, int argc, char *argv[]);
101 static int ui_cmd_cpy(ui_cmdline_t *cmd, int argc, char *argv[]);
102 static int ui_cmd_mcpy(ui_cmdline_t *cmd, int argc, char *argv[]);
104 /* demo stuff */
105 static int ui_cmd_testdm(ui_cmdline_t *cmd, int argc, char *argv[]);
106 static int ui_cmd_talkdm(ui_cmdline_t *cmd, int argc, char *argv[]);
108 int ui_init_testcmds2(void);
109 int ui_init_testcmds2(void)
111 zb_hz = cfe_cpu_speed/2;
112 zb_mhz = (zb_hz + 500000)/1000000;
114 /* demo commands */
115 cmd_addcmd("test dm",
116 ui_cmd_testdm,
117 NULL,
118 "Loop copying memory using the data mover",
119 "test dm [-v|-p] [-u] [-t] [-off] [dest src len]\n\n"
120 "This command continuously copies from source to destination\n "
121 " using the data mover and displays MB/s (times 10)",
122 "-p;Address is a physical address|"
123 "-v;Address is a (kernel) virtual address|"
124 "-u;Uncachable source and destination|"
125 "-t;Throttle DMA|"
126 "-off;Stop test");
127 cmd_addcmd("talk",
128 ui_cmd_talkdm,
129 NULL,
130 "Text echo",
131 "talk [-l]\n\n"
132 "This command sends to the text demon using the\n "
133 " data mover and mailbox variables",
134 "-l;Use local addresses");
136 /* timing/utility commands */
137 cmd_addcmd("sink",
138 ui_cmd_sink,
139 NULL,
140 "Read memory using the data mover",
141 "sink [-v|-p] [-u|-l2] [addr [len]]\n\n"
142 "This command reads a region of memory using the data\n"
143 "mover and discards the result.",
144 "-p;Address is a physical address|"
145 "-v;Address is a (kernel) virtual address|"
146 "-u;Uncachable source|"
147 "-l2;L2 allocate at source");
148 cmd_addcmd("zero",
149 ui_cmd_zero,
150 NULL,
151 "Zero memory using the data mover",
152 "zero [-v|-p] [-u|-l2] [addr [len]]\n\n"
153 "This command clears a region of memory to zero using the\n"
154 "data mover.",
155 "-p;Address is a physical address|"
156 "-v;Address is a (kernel) virtual address|"
157 "-u;Uncachable destination|"
158 "-l2;L2 allocate at destination");
159 cmd_addcmd("mcpy",
160 ui_cmd_mcpy,
161 NULL,
162 "Copy memory using the data mover with multiple descriptors",
163 "cpy [-v|-p] [-u|-l2] dest src [[len] blksize]\n\n"
164 "This command copies from source to destination using the\n"
165 "data mover with blksize bytes per descriptor.",
166 "-p;Address is a physical address|"
167 "-v;Address is a (kernel) virtual address|"
168 "-u;Uncachable source and destination|"
169 "-l2;L2 allocate at destination");
170 cmd_addcmd("cpy",
171 ui_cmd_cpy,
172 NULL,
173 "Copy memory using the data mover",
174 "cpy [-v|-p] [-u|-l2] dest src [len]\n\n"
175 "This command copies from source to destination using the\n"
176 "data mover.",
177 "-p;Address is a physical address|"
178 "-v;Address is a (kernel) virtual address|"
179 "-u;Uncachable source and destination|"
180 "-l2;L2 allocate at destination");
181 return 0;
185 #define _SBDMA_POLL_
187 #define dm_nextbuf(d,f) ((((d)->f+1) == (d)->dm_dscrring_end) ? \
188 (d)->dm_dscrring : (d)->f+1)
190 /* The following macro won't work with 64-bit virtual addresses. */
191 #define SBDMA_VTOP(x) ((uint64_t) K1_TO_PHYS((uint64_t)((unsigned long)(x))))
194 /* abbreviations for generating descriptors */
196 typedef uint64_t flags_t;
198 #define SRCUNC M_DM_DSCRA_UN_SRC /* Source uncached */
199 #define SRCINC V_DM_DSCRA_DIR_SRC_INCR /* inc src ptr */
200 #define SRCDEC V_DM_DSCRA_DIR_SRC_DECR /* dec src ptr */
201 #define SRCCON V_DM_DSCRA_DIR_SRC_CONST /* src ptr constant */
203 #define DSTUNC M_DM_DSCRA_UN_DEST /* Dest uncached */
204 #define DSTINC V_DM_DSCRA_DIR_DEST_INCR /* inc dest ptr */
205 #define DSTDEC V_DM_DSCRA_DIR_DEST_DECR /* dec dest ptr */
206 #define DSTCON V_DM_DSCRA_DIR_DEST_CONST /* dest ptr constant */
208 #define ZEROMEM M_DM_DSCRA_ZERO_MEM /* just zero dest */
209 #define PREFETCH M_DM_DSCRA_PREFETCH /* don't write dest */
210 #define L2CDEST M_DM_DSCRA_L2C_DEST /* dest l2 cacheable */
211 #define L2CSRC M_DM_DSCRA_L2C_SRC /* src l2 cacheable */
213 /* NB: THROTTLE is defined only for pass 1 parts. */
214 #define THROTTLE M_DM_DSCRA_THROTTLE /* throttle DMA */
216 #ifdef _SBDMA_INTERRUPTS_
217 #define INTER M_DM_DSCRA_INTERRUPT /* int on dscr done */
218 #else
219 #define INTER 0
220 #endif
223 typedef uint32_t sbport_t;
224 typedef uint64_t sbphysaddr_t;
226 typedef struct sbdmadscr_s {
227 uint64_t dscr_a;
228 uint64_t dscr_b;
229 } sbdmadscr_t;
231 typedef struct sbgendma_s {
232 int ch; /* channel number */
234 void *dm_dscrmem; /* Memory for descriptor list */
236 sbport_t dm_dscrbase; /* Descriptor base address */
237 sbport_t dm_dscrcnt; /* Descriptor count register */
238 sbport_t dm_curdscr; /* current descriptor address */
240 sbdmadscr_t *dm_dscrring; /* base of descriptor table */
241 sbdmadscr_t *dm_dscrring_end; /* end of descriptor table */
243 sbphysaddr_t dm_dscrring_phys; /* and also the phys addr */
244 sbdmadscr_t *dm_addptr; /* next dscr for sw to add */
245 sbdmadscr_t *dm_remptr; /* next dscr for sw to remove */
247 /* number of descriptors we have not told the hardware about yet. */
248 int dm_newcnt;
250 int dm_busy;
251 } sbgendma_t;
254 #define DM_READCSR(x) SBREADCSR(x)
255 #define DM_WRITECSR(x,y) SBWRITECSR(x,y)
257 static sbgendma_t sbgendma_ctx[DM_NUM_CHANNELS];
259 /* Channel allocation:
260 0 utility commands that use the data mover (foreground)
261 1 data mover test loop (background)
262 2 talk command (background)
263 3 data mover multicopy (foreground)
266 #define SBDMA_CMD_CH 0
267 #define SBDMA_TEST_CH 1
268 #define SBDMA_TALK_CH 2
269 #define SBDMA_MCMD_CH 3
272 static int sbgendma_initialized = 0;
275 /* For Pass 1, dedicate an SCD peformance counter to use as a counter
276 of ZBbus cycles. */
277 #include "sb1250_scd.h"
278 #define ZCTR_MODULUS 0x10000000000LL
280 /* The counter is a shared resource that must be reset periodically
281 since it doesn't roll over. Furthermore, there is a pass one bug
282 that makes the interrupt unreliable and the final value either all
283 ones or all zeros. We therefore reset the count when it exceeds
284 half the modulus. We also assume that intervals of interest
285 are much less than half the modulus and attempt to adjust for
286 the reset in zclk_elapsed. */
288 static void
289 zclk_init(uint64_t val)
291 *((volatile uint64_t *) UNCADDR(A_SCD_PERF_CNT_0)) = val;
292 *((volatile uint64_t *) UNCADDR(A_SCD_PERF_CNT_CFG)) =
293 V_SPC_CFG_SRC0(1) | M_SPC_CFG_ENABLE;
296 static uint64_t
297 zclk_get(void)
299 uint64_t ticks;
301 ticks = *((volatile uint64_t *) UNCADDR(A_SCD_PERF_CNT_0));
302 if (ticks == 0 || ticks == ZCTR_MODULUS-1) {
303 ticks = 0;
304 zclk_init(ticks);
306 else if (ticks >= ZCTR_MODULUS/2) {
307 ticks -= ZCTR_MODULUS/2;
308 zclk_init(ticks); /* Ignore the fudge and lose a few ticks */
310 return ticks;
313 static uint64_t
314 zclk_elapsed(uint64_t stop, uint64_t start)
316 return ((stop >= start) ? stop : stop + ZCTR_MODULUS/2) - start;
320 /* *********************************************************************
321 * DM_PROCBUFFERS(d)
323 * Process "completed" buffers on the specified DMA channel.
324 * This is normally called within the interrupt service routine.
325 * Note that this isn't really ideal for priority channels, since
326 * it processes all of the packets on a given channel before
327 * returning.
329 * Input parameters:
330 * d - DMA channel context
332 * Return value:
333 * number of packets processed.
334 ********************************************************************* */
335 static int
336 dm_procbuffers(sbgendma_t *d)
338 int curidx;
339 int hwidx;
340 int count = 0;
342 for (;;) {
343 /* Figure out where we are (as an index) and where
344 the hardware is (also as an index)
346 This could be done faster if (for example) the
347 descriptor table was page-aligned and contiguous in
348 both virtual and physical memory -- you could then
349 just compare the low-order bits of the virtual address
350 (dm_remptr) and the physical address (dm_curdscr CSR) */
352 curidx = d->dm_remptr - d->dm_dscrring;
353 hwidx = ((DM_READCSR(d->dm_curdscr) & M_DM_CUR_DSCR_DSCR_ADDR) -
354 d->dm_dscrring_phys) / sizeof(sbdmadscr_t);
356 /* If they're the same, we've processed all of the descriptors
357 owned by us. */
359 if (curidx == hwidx)
360 break;
362 /* Otherwise, issue the upcall, or do whatever we want to do
363 to indicate to the client program that the operation is
364 complete (not used here). */
366 count++;
368 /* .. and advance to the next buffer. */
370 d->dm_remptr = dm_nextbuf(d, dm_remptr);
373 return count;
377 /* *********************************************************************
378 * DM_ADDDESCR(d,newdsc,n)
380 * Add a descriptor to the specified DMA channel.
382 * Input parameters:
383 * d - DMA channel descriptor
384 * newdsc - pointer to descriptor
385 * n - number of descriptors to add
387 * Return value:
388 * number of descriptors actually added
389 ********************************************************************* */
390 static int
391 dm_adddescr(sbgendma_t *d, sbdmadscr_t *newdsc, int n)
393 sbdmadscr_t *dsc;
394 sbdmadscr_t *nextdsc;
395 int cnt = 0;
397 while (n > 0) {
399 dsc = d->dm_addptr;
400 nextdsc = dm_nextbuf(d, dm_addptr);
402 /* Test whether the ring is full (next == remptr) */
404 if (nextdsc == d->dm_remptr) {
405 break;
408 dsc->dscr_a = newdsc->dscr_a;
409 dsc->dscr_b = newdsc->dscr_b;
411 d->dm_addptr = nextdsc;
413 cnt++;
414 n--;
415 newdsc++;
418 d->dm_newcnt += cnt;
420 return cnt;
424 /* *********************************************************************
425 * DM_START(d)
427 * Start DMA on the specified channel, queueing all descriptors
428 * that we have added with dm_adddescr()
430 * Input parameters:
431 * d - DMA context
433 * Return value:
434 * start time (zbclks)
435 ********************************************************************* */
436 static uint64_t
437 dm_start(sbgendma_t *d)
439 uint64_t now;
441 if (d->dm_newcnt) {
442 d->dm_busy = 1;
443 DM_WRITECSR(d->dm_dscrcnt, d->dm_newcnt);
445 now = zclk_get();
446 d->dm_newcnt = 0;
447 return now;
451 #ifdef _SBDMA_INTERRUPTS_
452 /* *********************************************************************
453 * DM_INTERRUPT(ctx)
455 * "interrupt" routine for a given channel
457 * Input parameters:
458 * ctx - DMA channel context
460 * Return value:
461 * nothing
462 ********************************************************************* */
463 static void
464 dm_interrupt(void *ctx)
466 sbgendma_t *d = (sbgendma_t *)ctx;
468 /* Clear the interrupt (better in procbuffers? */
469 (void) DM_READCSR(d->dm_dscrbase);
471 dm_procbuffers(d);
473 if (G_DM_CUR_DSCR_DSCR_COUNT(DM_READCSR(d->dm_curdscr)) == 0)
474 d->dm_busy = 0;
478 /* *********************************************************************
479 * DM_ISDONE(d)
481 * Returns TRUE if all descriptors on the specified channel
482 * are complete.
484 * Input parameters:
485 * d - DMA context
487 * Return value:
488 * 1 if all descriptors are processed (none pending in hw)
489 * 0 if there are still some descriptors in progress
490 ********************************************************************* */
491 static int
492 dm_isdone(sbgendma_t *d)
494 cfe_irq_poll(NULL); /* avoid full bg poll if timing */
496 return (d->dm_busy == 0);
500 /* *********************************************************************
501 * DM_WAIT(d)
503 * Returns elapsed zb clks when an interrupt becomes pending on
504 * the channel and also processes the interrupt.
505 * CAUTION: spins forever if misused.
507 * Input parameters:
508 * none
510 * Return value:
511 * stop time (zbclks)
512 ********************************************************************* */
514 #define IMR_POINTER(cpu,reg) \
515 ((volatile uint64_t *)(PHYS_TO_K1(A_IMR_REGISTER(cpu,reg))))
516 extern int32_t _getcause(void); /* return value of CP0 CAUSE */
518 static uint64_t
519 dm_wait(sbgendma_t *d)
521 uint64_t mask = (1LL << (K_INT_DM_CH_0 + d->ch));
522 volatile uint64_t *status = IMR_POINTER(0, R_IMR_INTERRUPT_SOURCE_STATUS);
523 uint64_t stop;
525 for (;;) {
526 while ((_getcause() & M_CAUSE_IP2) == 0)
527 continue;
528 if ((*status & mask) != 0)
529 break;
530 cfe_irq_poll(NULL);
531 if (d->dm_busy == 0)
532 break;
534 stop = zclk_get();
536 while (!dm_isdone(d))
537 continue;
539 return stop;
541 #else /* !_SBDMA_INTERRUPTS_ */
543 /* *********************************************************************
544 * DM_ISDONE(d)
546 * Returns TRUE if all descriptors on the specified channel
547 * are complete.
549 * Input parameters:
550 * d - DMA context
552 * Return value:
553 * 1 if all descriptors are processed (none pending in hw)
554 * 0 if there are still some descriptors in progress
555 ********************************************************************* */
556 static int
557 dm_isdone(sbgendma_t *d)
559 #ifdef _SBDMA_TEST_PTRS_
560 int curidx, hwidx;
561 #endif
563 /* If polling, now is a good time to process finished descriptors. */
565 dm_procbuffers(d);
567 /* Test for DMA complete. There are two ways to do this, to use
568 the same technique the interrupt routine uses and compare the
569 pointers to the descriptor tables, or we can use the count.
570 Both methods are shown below. */
572 #ifdef _SBDMA_TEST_PTRS_
573 curidx = d->dm_addptr - d->dm_dscrring;
574 hwidx = ((DM_READCSR(d->dm_curdscr) & M_DM_CUR_DSCR_DSCR_ADDR) -
575 d->dm_dscrring_phys) / sizeof(sbdmadscr_t);
576 return (curidx == hwidx);
577 #else
578 return (G_DM_CUR_DSCR_DSCR_COUNT(DM_READCSR(d->dm_curdscr)) == 0);
579 #endif
583 /* *********************************************************************
584 * DM_WAIT(d)
586 * Returns elapsed zb clks when an interrupt becomes pending on
587 * the channel and also processes the interrupt.
588 * CAUTION: spins forever if misused.
590 * Input parameters:
591 * none
593 * Return value:
594 * stop time (zbclks)
595 ********************************************************************* */
597 static uint64_t
598 dm_wait(sbgendma_t *d)
600 uint64_t stop;
602 while (!dm_isdone(d))
603 continue;
604 stop = zclk_get();
606 d->dm_busy = 0;
607 return stop;
609 #endif /* !_SBDMA_INTERRUPTS_ */
612 /* *********************************************************************
613 * DM_BUILDDESCR_P(dsc,dest,src,len,flags)
615 * Builds a descriptor.
617 * Input parameters:
618 * dsc - pointer to descriptor to build
619 * dest - destination address (physical)
620 * src - source address (physical)
621 * len - number of bytes to transfer
622 * flags - flags for transfer
624 * Return value:
625 * nothing
626 ********************************************************************* */
627 static void
628 dm_builddescr_p(sbdmadscr_t *dsc, uint64_t dest, uint64_t src,
629 int len, flags_t flags)
631 dsc->dscr_a = dest | flags;
632 dsc->dscr_b = src | V_DM_DSCRB_SRC_LENGTH(len);
636 #define CACHE_ALIGN(x, t) ((t)(((unsigned long)(x) + 31) & ~31))
638 /* *********************************************************************
639 * DM_ALLOCDSCRS(count)
641 * Allocates dynamic storage for a descriptor ring
643 * Input parameters:
644 * cnt - number of descriptors
646 * Return value:
647 * pointer to the allocated space (use only cache-aligned slots)
648 ********************************************************************* */
649 static void *
650 dm_allocdscrs(int cnt)
652 /* Allocate with enough fudge to cache-align. */
653 return KMALLOC(cnt * sizeof(sbdmadscr_t) + 32, 0);
657 /* *********************************************************************
658 * DM_INITCTX(ch,n,priority)
660 * Initialize a generic DMA context - this structure describes
661 * the hardware and software state for the device driver.
663 * Input parameters:
664 * ch - channel number (0..3)
665 * n - desired number of available descriptors
666 * (ring size is n+1 to distinguish full/empty cases)
667 * priority - priority for this channel (K_DM_DSCR_BASE_PRIORITY_x)
669 * Return value:
670 * nothing
671 ********************************************************************* */
672 static void
673 dm_initctx(int ch, int n, int priority)
675 sbgendma_t *d;
676 uint64_t base;
678 /* Initialize the fields in the DMA controller's context. */
680 d = &sbgendma_ctx[ch];
682 d->ch = ch;
683 d->dm_dscrbase = (sbport_t) A_DM_REGISTER(ch, R_DM_DSCR_BASE);
684 d->dm_dscrcnt = (sbport_t) A_DM_REGISTER(ch, R_DM_DSCR_COUNT);
685 d->dm_curdscr = (sbport_t) A_DM_REGISTER(ch, R_DM_CUR_DSCR_ADDR);
687 /* Initialize the pointers to the DMA descriptor ring. */
689 d->dm_dscrmem = dm_allocdscrs(n+1);
691 d->dm_dscrring = CACHE_ALIGN(d->dm_dscrmem, sbdmadscr_t *);
692 d->dm_dscrring_end = d->dm_dscrring + (n+1);
694 d->dm_addptr = d->dm_dscrring;
695 d->dm_remptr = d->dm_dscrring;
697 d->dm_newcnt = 0;
698 d->dm_busy = 0;
700 /* Calculate the physical address of the start of the descriptor
701 ring. We need this for determining when the pointers wrap. */
703 d->dm_dscrring_phys = (sbphysaddr_t) SBDMA_VTOP(d->dm_dscrring);
705 /* Finally, set up the DMA controller. */
707 base = d->dm_dscrring_phys |
708 V_DM_DSCR_BASE_PRIORITY(priority) |
709 V_DM_DSCR_BASE_RINGSZ(n+1);
710 DM_WRITECSR(d->dm_dscrbase, base);
711 (void)DM_READCSR(d->dm_dscrbase); /* push */
713 base = d->dm_dscrring_phys |
714 V_DM_DSCR_BASE_PRIORITY(priority) |
715 V_DM_DSCR_BASE_RINGSZ(n+1) |
716 M_DM_DSCR_BASE_RESET; /* disable and reset */
717 DM_WRITECSR(d->dm_dscrbase, base);
718 (void)DM_READCSR(d->dm_dscrbase); /* push */
720 base = d->dm_dscrring_phys |
721 V_DM_DSCR_BASE_PRIORITY(priority) |
722 V_DM_DSCR_BASE_RINGSZ(n+1) |
723 M_DM_DSCR_BASE_ENABL; /* enable */
724 DM_WRITECSR(d->dm_dscrbase, base);
728 /* *********************************************************************
729 * DM_UNINITCTX(ch)
731 * Finalize a generic DMA context - this structure describes
732 * the hardware and software state for the device driver.
734 * Input parameters:
735 * ch - channel number (0..3)
737 * Return value:
738 * nothing
739 ********************************************************************* */
740 static void
741 dm_uninitctx(int ch)
743 sbgendma_t *d;
744 uint64_t base;
746 /* Finalize the fields in the DMA controller's context. */
748 d = &sbgendma_ctx[ch];
750 if (d->dm_dscrmem != NULL) {
751 KFREE(d->dm_dscrmem);
753 d->dm_dscrmem = NULL;
755 d->dm_dscrring = NULL;
756 d->dm_dscrring_end = NULL;
758 d->dm_addptr = NULL;
759 d->dm_remptr = NULL;
761 d->dm_newcnt = 0;
762 d->dm_busy = 0;
764 d->dm_dscrring_phys = (sbphysaddr_t) 0;
765 base = d->dm_dscrring_phys;
766 DM_WRITECSR(d->dm_dscrbase, base);
767 (void)DM_READCSR(d->dm_dscrbase); /* push */
769 DM_WRITECSR(d->dm_dscrbase, base | M_DM_DSCR_BASE_RESET);
773 /* *********************************************************************
774 * DM_STARTONE(ch,dscr)
776 * Start a single descriptor
778 * Input parameters:
779 * ch - DMA channel number.
780 * dscr - descriptor to run
782 * Return value:
783 * start time (zbclks)
784 ********************************************************************* */
785 static uint64_t
786 dm_startone(int ch, sbdmadscr_t *dscr)
788 sbgendma_t *d = &sbgendma_ctx[ch];
790 /* Try to put it on the queue. If this doesn't work, call the
791 polling function until we get space. This can happen if the
792 ring is full when we attempt to add a descriptor, which is very
793 unlikely in this test program. */
795 for (;;) {
796 if (dm_adddescr(d, dscr, 1) == 1) {
797 break;
799 #ifdef _SBDMA_POLL_
800 dm_procbuffers(d);
801 #endif
804 return dm_start(d);
807 /* *********************************************************************
808 * DM_RUNONE(ch,dscr)
810 * Run a single descriptor, waiting until it completes before
811 * returning to the calling program.
813 * Input parameters:
814 * ch - DMA channel number.
815 * dscr - descriptor to run
817 * Return value:
818 * elapsed time (zbclks)
819 ********************************************************************* */
820 static uint64_t
821 dm_runone(int ch, sbdmadscr_t *dscr)
823 sbgendma_t *d = &sbgendma_ctx[ch];
824 uint64_t start, stop;
826 start = dm_startone(ch, dscr);
827 stop = dm_wait(d);
829 return zclk_elapsed(stop, start);
833 /* *********************************************************************
834 * DM_RESET()
836 * Reset and initialize global data structures.
838 * Input parameters:
839 * none
841 * Return value:
842 * none
843 ********************************************************************* */
844 static void
845 dm_reset(void)
847 sbport_t dscrbase_p;
848 int ch;
850 for (ch = 0; ch < DM_NUM_CHANNELS; ch++) {
851 dscrbase_p = (sbport_t) A_DM_REGISTER(ch, R_DM_DSCR_BASE);
852 DM_WRITECSR(dscrbase_p, M_DM_DSCR_BASE_RESET);
855 for (ch = 0; ch < DM_NUM_CHANNELS; ch++) {
856 dscrbase_p = (sbport_t) A_DM_REGISTER(ch, R_DM_DSCR_BASE);
857 while (DM_READCSR(dscrbase_p) && M_DM_DSCR_BASE_ACTIVE) {
858 POLL();
865 /* *********************************************************************
866 * DM_INIT()
868 * Initialize global data structures if necessary.
870 * Input parameters:
871 * none
873 * Return value:
874 * none
875 ********************************************************************* */
876 static void
877 dm_init(void)
879 if (!sbgendma_initialized) {
880 dm_reset();
882 zclk_init(0); /* Time origin is arbitrary */
884 dm_initctx(SBDMA_CMD_CH, 1, K_DM_DSCR_BASE_PRIORITY_1);
885 #ifdef _SBDMA_INTERRUPTS_
886 cfe_request_irq(K_INT_DM_CH_0 + SBDMA_CMD_CH,
887 dm_interrupt, &sbgendma_ctx[SBDMA_CMD_CH], 0, 0);
888 #endif /* _SBDMA_INTERRUPTS_ */
890 sbgendma_initialized = 1;
895 /* *********************************************************************
896 * DM_CMD_INIT(flush)
898 * Initialize global data structures, if necessary.
900 * Input parameters:
901 * flush - flush caches first (for timing)
903 * Return value:
904 * none
905 ********************************************************************* */
906 static void
907 dm_cmd_init(int flush)
909 dm_init();
911 if (flush)
916 /* *********************************************************************
917 * DM_BCOPY_P(src,dest,cnt,flags)
919 * This is an example implementation of "bcopy" that uses
920 * the data mover.
922 * Input parameters:
923 * ch - DMA channel number.
924 * src - source physical address
925 * dest - destination physical address
926 * cnt - count of bytes to copy
927 * flags - option flags
929 * Return value:
930 * elapsed time (zbclks)
931 ********************************************************************* */
932 static uint64_t
933 dm_bcopy_p(int ch, long src, long dest, int cnt, flags_t flags)
935 sbdmadscr_t dscr;
937 if ((unsigned long)src < (unsigned long)dest
938 && (unsigned long)(src + cnt) > (unsigned long)dest) {
939 flags |= SRCDEC|DSTDEC;
940 dest += cnt - 1;
941 src += cnt - 1;
943 else {
944 flags |= SRCINC|DSTINC;
947 dm_builddescr_p(&dscr, dest, src, cnt, flags|INTER);
948 return dm_runone(ch, &dscr);
952 /* *********************************************************************
953 * DM_BCOPY(src,dest,cnt)
955 * This is an example implementation of "bcopy" that uses
956 * the data mover.
958 * Input parameters:
959 * src - source virtual address
960 * dest - destination virtual address
961 * cnt - count of bytes to copy
963 * Return value:
964 * nothing
965 ********************************************************************* */
966 void
967 dm_bcopy(void *src, void *dest, int cnt)
969 dm_bcopy_p(SBDMA_CMD_CH, phys_addr((long)src), phys_addr((long)dest), cnt, 0);
973 /* *********************************************************************
974 * DM_MULTIBCOPY_P(ch,src,dest,cnt,flags)
976 * Input parameters:
977 * ch - DMA channel number.
978 * src - source physical address
979 * dest - destination physical address
980 * cnt - count of bytes to copy
981 * step - maximum bytes per descriptor
982 * flags - option flags
984 * Return value:
985 * elapsed time (zbclks)
986 ********************************************************************* */
987 static uint64_t
988 dm_multibcopy_p(int ch, long src, long dest, int cnt, int step, flags_t flags)
990 sbgendma_t *d = &sbgendma_ctx[ch];
991 sbdmadscr_t dscr;
992 int dnum;
993 uint64_t start, stop;
995 dnum = (cnt + (step-1))/step;
996 if (dnum == 0) {
997 return 0;
1000 flags |= SRCINC|DSTINC;
1002 dm_init();
1003 dm_initctx(ch, dnum, K_DM_DSCR_BASE_PRIORITY_1);
1004 #ifdef _SBDMA_INTERRUPTS_
1005 cfe_request_irq(K_INT_DM_CH_0 + ch, dm_interrupt, d, 0, 0);
1006 #endif
1008 while (cnt > 0) {
1009 int n = (cnt < step ? cnt : step);
1011 if (cnt <= n)
1012 flags |= INTER;
1014 dm_builddescr_p(&dscr, dest, src, n, flags);
1015 dm_adddescr(d, &dscr, 1);
1016 src += n;
1017 dest += n;
1018 cnt -= n;
1021 start = dm_start(d);
1022 stop = dm_wait(d);
1024 cfe_free_irq(K_INT_DM_CH_0 + ch, 0);
1025 dm_uninitctx(ch);
1027 return zclk_elapsed(stop, start);
1030 /* *********************************************************************
1031 * DM_MULTIBCOPY(src,dest,cnt)
1033 * This is a variant of BCOPY that queues up several descriptors to
1034 * do the work.
1036 * Input parameters:
1037 * src - source virtual address
1038 * dest - destination virtual address
1039 * len - count of bytes to copy
1040 * blksize - maximum bytes per descriptor
1042 * Return value:
1043 * nothing
1044 ********************************************************************* */
1045 void
1046 dm_multibcopy(void *src, void *dest, int len, int blksize)
1048 dm_multibcopy_p(SBDMA_CMD_CH, phys_addr((long) src), phys_addr((long) dest),
1049 len, blksize, 0);
1053 /* *********************************************************************
1054 * DM_BZERO_P(dest,cnt,flags)
1056 * Input parameters:
1057 * ch - DMA channel number.
1058 * dest - physical address
1059 * cnt - count of bytes to zero
1060 * flags - option flags
1062 * Return value:
1063 * elapsed time (zbclks)
1064 ********************************************************************* */
1065 static uint64_t
1066 dm_bzero_p(int ch, long dest, int cnt, flags_t flags)
1068 sbdmadscr_t dscr;
1070 flags |= SRCCON|ZEROMEM|DSTINC;
1071 dm_builddescr_p(&dscr, dest, 0, cnt, flags|INTER);
1072 return dm_runone(ch, &dscr);
1075 /* *********************************************************************
1076 * DM_BZERO(dest,cnt)
1078 * This is an example implementation of "bzero" that uses
1079 * the data mover.
1081 * Input parameters:
1082 * dest - destination virtual address
1083 * cnt - count of bytes to zero
1085 * Return value:
1086 * nothing
1087 ********************************************************************* */
1088 void
1089 dm_bzero(void *dest, int cnt)
1091 dm_bzero_p(SBDMA_CMD_CH, phys_addr((long) dest), cnt, 0);
1095 /* *********************************************************************
1096 * DM_BSINK_P(ch,src,cnt,flags)
1098 * Input parameters:
1099 * ch - DMA channel number.
1100 * src - physical address
1101 * cnt - count of bytes to read
1102 * flags - option flags
1104 * Return value:
1105 * elapsed time (zbclks)
1106 ********************************************************************* */
1107 static uint64_t
1108 dm_bsink_p(int ch, long src, int cnt, flags_t flags)
1110 sbdmadscr_t dscr;
1112 flags |= SRCINC|PREFETCH|DSTCON;
1113 dm_builddescr_p(&dscr, 0, src, cnt, flags|INTER);
1114 return dm_runone(ch, &dscr);
1117 /* *********************************************************************
1118 * DM_BSINK(src,cnt)
1120 * Input parameters:
1121 * src - physical address
1122 * cnt - count of bytes to read
1124 * Return value:
1125 * nothing
1126 ********************************************************************* */
1127 void
1128 dm_bsink(void *src, int cnt)
1130 dm_bsink_p(SBDMA_CMD_CH, phys_addr((long) src), cnt, 0);
1134 /* Address parsing adapted from ui_examcmds. */
1136 #define ATYPE_TYPE_NONE 0
1137 #define ATYPE_TYPE_PHYS 1
1138 #define ATYPE_TYPE_VIRT 2
1139 #define ATYPE_TYPE_MASK (ATYPE_TYPE_PHYS | ATYPE_TYPE_VIRT)
1141 static int
1142 getaddrarg(ui_cmdline_t *cmd, int arg, long *addr, int *atype)
1144 int res;
1146 res = -1;
1148 if (atype) {
1149 *atype &= ~ATYPE_TYPE_MASK;
1150 *atype |= ATYPE_TYPE_NONE;
1152 if (cmd_sw_isset(cmd, "-p")) {
1153 *atype |= ATYPE_TYPE_PHYS;
1155 else if (cmd_sw_isset(cmd, "-v")) {
1156 *atype |= ATYPE_TYPE_VIRT;
1158 else {
1159 *atype |= ATYPE_TYPE_VIRT; /* best default? */
1163 if (addr) {
1164 char *x = cmd_getarg(cmd, arg);
1166 *addr = 0;
1167 if (x) {
1168 /* Following gdb, we Make 64-bit addresses expressed as
1169 8-digit numbers sign extend automagically. Saves
1170 typing, but is very gross. */
1171 int longaddr;
1172 longaddr = strlen(x);
1173 if (memcmp(x, "0x", 2) == 0) longaddr -= 2;
1175 *addr = (longaddr > 8) ? (long) xtoq(x) : (long) xtoi(x);
1176 res = 0;
1180 return res;
1183 static int
1184 getlenarg(ui_cmdline_t *cmd, int arg, size_t *len)
1186 int res;
1188 res = -1;
1190 if (len) {
1191 char *x = cmd_getarg(cmd, arg);
1193 *len = 0;
1194 if (x) {
1195 *len = (size_t) xtoi(x);
1196 res = 0;
1199 return res;
1202 static void
1203 show_rate(size_t len, uint64_t elapsed)
1205 uint64_t rate;
1206 char digits[4+1];
1208 if (elapsed == 0) elapsed = 1; /* zbclk always 0 in the simulator */
1210 rate = ((uint64_t)len * zb_mhz * 10L)/elapsed;
1211 sprintf(digits, "%04d", rate);
1212 cfe_ledstr(digits);
1213 printf("%3d.%1d MB/s\n", rate/10L, rate%10L);
1217 static int
1218 ui_cmd_zero(ui_cmdline_t *cmd, int argc, char *argv[])
1220 long dest;
1221 int dtype;
1222 size_t len;
1223 flags_t flags = 0;
1224 uint64_t elapsed;
1226 getaddrarg(cmd, 0, &dest, &dtype);
1227 getlenarg(cmd, 1, &len);
1228 if (cmd_sw_isset(cmd, "-u"))
1229 flags |= DSTUNC;
1230 else if (cmd_sw_isset(cmd, "-l2"))
1231 flags |= L2CDEST;
1233 if ((dtype & ATYPE_TYPE_MASK) == ATYPE_TYPE_VIRT)
1234 dest = phys_addr(dest);
1236 if (len > 0x100000) len = 0x100000;
1238 dm_cmd_init((flags & DSTUNC) != DSTUNC);
1240 elapsed = dm_bzero_p(SBDMA_CMD_CH, dest, len, flags);
1242 show_rate(len, elapsed);
1243 return 0;
1247 static int
1248 ui_cmd_sink(ui_cmdline_t *cmd, int argc, char *argv[])
1250 long src;
1251 int stype;
1252 size_t len;
1253 flags_t flags = 0;
1254 uint64_t elapsed;
1256 getaddrarg(cmd, 0, &src, &stype);
1257 getlenarg(cmd, 1, &len);
1258 if (cmd_sw_isset(cmd, "-u"))
1259 flags |= SRCUNC;
1260 else if (cmd_sw_isset(cmd, "-l2"))
1261 flags |= L2CSRC;
1263 if ((stype & ATYPE_TYPE_MASK) == ATYPE_TYPE_VIRT)
1264 src = phys_addr(src);
1266 if (len > 0x100000) len = 0x100000;
1268 dm_cmd_init((flags & SRCUNC) != SRCUNC);
1270 elapsed = dm_bsink_p(SBDMA_CMD_CH, src, len, flags);
1272 show_rate(len, elapsed);
1273 return 0;
1277 static int
1278 ui_cmd_cpy(ui_cmdline_t *cmd, int argc, char *argv[])
1280 long src, dest;
1281 int stype, dtype;
1282 size_t len;
1283 flags_t flags = 0;
1284 uint64_t elapsed;
1286 getaddrarg(cmd, 0, &dest, &dtype);
1287 getaddrarg(cmd, 1, &src, &stype);
1288 getlenarg(cmd, 2, &len);
1289 if (cmd_sw_isset(cmd, "-u"))
1290 flags |= SRCUNC|DSTUNC;
1291 else if (cmd_sw_isset(cmd, "-l2"))
1292 flags |= L2CDEST;
1294 if ((dtype & ATYPE_TYPE_MASK) == ATYPE_TYPE_VIRT)
1295 dest = phys_addr(dest);
1296 if ((stype & ATYPE_TYPE_MASK) == ATYPE_TYPE_VIRT)
1297 src = phys_addr(src);
1299 if (len > 0x100000) len = 0x100000;
1301 dm_cmd_init((flags & (SRCUNC|DSTUNC)) != (SRCUNC|DSTUNC));
1303 elapsed = dm_bcopy_p(SBDMA_CMD_CH, src, dest, len, flags);
1305 show_rate(len, elapsed);
1306 return 0;
1309 static int
1310 ui_cmd_mcpy(ui_cmdline_t *cmd, int argc, char *argv[])
1312 long src, dest;
1313 int stype, dtype;
1314 size_t len, blksize;
1315 flags_t flags = 0;
1316 uint64_t elapsed;
1318 getaddrarg(cmd, 0, &dest, &dtype);
1319 getaddrarg(cmd, 1, &src, &stype);
1320 getlenarg(cmd, 2, &len);
1321 getlenarg(cmd, 3, &blksize);
1322 if (cmd_sw_isset(cmd, "-u"))
1323 flags |= SRCUNC|DSTUNC;
1324 else if (cmd_sw_isset(cmd, "-l2"))
1325 flags |= L2CDEST;
1327 if ((dtype & ATYPE_TYPE_MASK) == ATYPE_TYPE_VIRT)
1328 dest = phys_addr(dest);
1329 if ((stype & ATYPE_TYPE_MASK) == ATYPE_TYPE_VIRT)
1330 src = phys_addr(src);
1332 dm_cmd_init((flags & (SRCUNC|DSTUNC)) != (SRCUNC|DSTUNC));
1334 if (len <= blksize)
1335 elapsed = dm_bcopy_p(SBDMA_CMD_CH, src, dest, len, flags);
1336 else
1337 elapsed = dm_multibcopy_p(SBDMA_MCMD_CH, src, dest, len, blksize, flags);
1339 show_rate(len, elapsed);
1340 return 0;
1344 /* *********************************************************************
1345 * ui_cmd_testdm()
1347 * Test program.
1349 * Input parameters:
1350 * argc,argv
1352 * Return value:
1354 ********************************************************************* */
1356 #ifdef _SBDMA_INTERRUPTS_
1358 #define N_SAMPLES 8
1360 typedef struct sbgendma_args_s {
1361 int ch;
1362 int enabled;
1363 long src, dest;
1364 size_t len;
1365 flags_t flags;
1366 uint64_t start;
1367 uint64_t last;
1368 uint64_t delta[N_SAMPLES];
1369 int index;
1370 int toggle;
1371 uint64_t count;
1372 } sbgendma_args_t;
1374 static void
1375 dm_restart(sbgendma_args_t *args)
1377 sbdmadscr_t dscr;
1379 dm_builddescr_p(&dscr, args->dest, args->src, args->len, args->flags);
1381 args->start = dm_startone(args->ch, &dscr);
1384 static void
1385 dm_interrupt_loop(void *ctx)
1387 sbgendma_args_t *args = (sbgendma_args_t *)ctx;
1388 sbgendma_t *d = &sbgendma_ctx[args->ch];
1390 /* Clear the interrupt (better in procbuffers? */
1391 (void) DM_READCSR(d->dm_dscrbase);
1393 dm_procbuffers(d);
1395 if (G_DM_CUR_DSCR_DSCR_COUNT(DM_READCSR(d->dm_curdscr)) == 0) {
1396 uint64_t start, now;
1397 char digits[4+1];
1399 now = zclk_get();
1400 start = args->start;
1402 d->dm_busy = 0;
1404 if (args->len == 0) {
1405 args->enabled = 0;
1406 cfe_free_irq(K_INT_DM_CH_0 + args->ch, 0);
1407 dm_uninitctx(args->ch);
1408 cfe_ledstr("CFE ");
1410 else {
1411 dm_restart(args);
1413 args->delta[args->index] = zclk_elapsed(now, start);
1414 args->index = (args->index + 1) % N_SAMPLES;
1416 if (zclk_elapsed(now, args->last) > zb_hz/4) {
1417 int i;
1418 uint64_t avg, rate;
1420 args->last = now;
1421 avg = 0;
1422 for (i = 0; i < N_SAMPLES; i++)
1423 avg += args->delta[i];
1424 avg /= N_SAMPLES;
1425 rate = ((uint64_t)(args->len) * zb_mhz * 10L)/avg;
1426 sprintf(digits, "%04d", rate);
1427 #ifdef _SENTOSA_
1428 #define WRITECSR(csr,val) *((volatile uint64_t *) (csr)) = (val)
1429 args->toggle ^= 1;
1430 if (args->toggle)
1431 WRITECSR(PHYS_TO_K1(A_GPIO_PIN_SET), M_GPIO_DEBUG_LED);
1432 else
1433 WRITECSR(PHYS_TO_K1(A_GPIO_PIN_CLR), M_GPIO_DEBUG_LED);
1434 args->count += 1;
1435 if (args->count % (5*60*4) == 0)
1436 xprintf("%ld\n", args->count/(60*4));
1437 #undef WRITECSR
1438 #else
1439 cfe_ledstr(digits);
1440 #endif
1446 static sbgendma_args_t *test_args[DM_NUM_CHANNELS] = {
1447 NULL, NULL, NULL, NULL
1450 static int
1451 ui_cmd_testdm(ui_cmdline_t *cmd, int argc, char *argv[])
1453 long src, dest;
1454 int stype, dtype;
1455 size_t len;
1456 flags_t flags = 0;
1457 sbgendma_args_t *args;
1458 int ch = SBDMA_TEST_CH; /* always single channel for now */
1459 int i;
1461 if (argc == 0) {
1462 /* OK values for demos */
1463 dest = 0xE000120000LL;
1464 src = 0x0000020000LL;
1465 len = 0x100000LL;
1467 else {
1468 getaddrarg(cmd, 0, &dest, &dtype);
1469 getaddrarg(cmd, 1, &src, &stype);
1470 getlenarg(cmd, 2, &len);
1471 if (cmd_sw_isset(cmd, "-u"))
1472 flags |= SRCUNC|DSTUNC;
1473 if (cmd_sw_isset(cmd, "-t"))
1474 flags |= THROTTLE;
1476 if ((dtype & ATYPE_TYPE_MASK) == ATYPE_TYPE_VIRT)
1477 dest = phys_addr(dest);
1478 if ((stype & ATYPE_TYPE_MASK) == ATYPE_TYPE_VIRT)
1479 src = phys_addr(src);
1482 if (cmd_sw_isset(cmd, "-off"))
1483 len = 0;
1485 if ((unsigned long)src < (unsigned long)dest
1486 && (unsigned long)(src + len) > (unsigned long)dest) {
1487 flags |= SRCDEC|DSTDEC;
1488 dest += len - 1;
1489 src += len - 1;
1491 else {
1492 flags |= SRCINC|DSTINC;
1495 args = test_args[ch];
1496 if (args == NULL) {
1497 args = (sbgendma_args_t *)KMALLOC(sizeof(sbgendma_args_t), 0);
1498 if (args == NULL)
1499 return -1;
1500 args->ch = ch;
1501 args->enabled = 0;
1502 args->len = 0;
1503 test_args[ch] = args;
1506 args->src = src;
1507 args->dest = dest;
1508 args->len = len;
1509 args->flags = flags|INTER;
1510 args->index = 0;
1511 for (i = 0; i < N_SAMPLES; i++)
1512 args->delta[i] = 0;
1513 args->toggle = 0;
1514 args->count = 0;
1516 dm_init();
1518 if (!args->enabled && len != 0) {
1519 dm_initctx(args->ch, 1, K_DM_DSCR_BASE_PRIORITY_1);
1520 cfe_request_irq(K_INT_DM_CH_0 + args->ch,
1521 dm_interrupt_loop, args, 0, 0);
1523 args->enabled = 1;
1524 args->last = zclk_get();
1525 dm_restart(args);
1528 return 0;
1530 #else /* !_SBDMA_INTERRUPTS_ */
1532 static int
1533 ui_cmd_testdm(ui_cmdline_t *cmd, int argc, char *argv[])
1535 long src, dest;
1536 int stype, dtype;
1537 size_t len;
1538 flags_t flags = 0;
1539 uint64_t now, elapsed;
1540 uint64_t rate;
1541 char digits[4+1];
1542 uint64_t last;
1544 getaddrarg(cmd, 0, &dest, &dtype);
1545 getaddrarg(cmd, 1, &src, &stype);
1546 getlenarg(cmd, 2, &len);
1547 if (cmd_sw_isset(cmd, "-u"))
1548 flags |= SRCUNC|DSTUNC;
1550 if ((dtype & ATYPE_TYPE_MASK) == ATYPE_TYPE_VIRT)
1551 dest = phys_addr(dest);
1552 if ((stype & ATYPE_TYPE_MASK) == ATYPE_TYPE_VIRT)
1553 src = phys_addr(src);
1555 last = zclk_get();
1557 printf("Press ENTER to stop timing\n");
1559 dm_cmd_init((flags & (SRCUNC|DSTUNC)) != (SRCUNC|DSTUNC));
1560 dm_initctx(SBDMA_TEST_CH, 1, K_DM_DSCR_BASE_PRIORITY_1);
1562 do {
1563 elapsed = dm_bcopy_p(SBDMA_TEST_CH, src, dest, len, flags);
1564 now = zclk_get();
1566 if (zclk_elapsed(now, last) > zb_hz/4) {
1567 last = now;
1568 rate = ((uint64_t)len * zb_mhz * 10L)/elapsed;
1569 sprintf(digits, "%04d", rate);
1570 cfe_ledstr(digits);
1573 } while (!console_status());
1575 dm_uninitctx(SBDMA_TEST_CH);
1576 return 0;
1578 #endif /* !_SBDMA_INTERRUPTS_ */
1581 /* demo stuff */
1583 /* The communication area */
1585 #define SBDMA_REMOTEP(x) ((uint64_t)(x) | 0xe000000000LL)
1587 /* Using physical address 0x10000 as the mailbox base is arbitrary but
1588 compatible with CFE. */
1589 #define MBOX_PADDR 0x10000
1590 #define BUFFER_PADDR (MBOX_PADDR + sizeof(int))
1592 #define BUFFER_SIZE 200
1594 static int listener = 0;
1596 static void
1597 cfe_recvdm(void *arg)
1599 /* always use the local values */
1600 volatile int *mailbox = (volatile int *) PHYS_TO_K1(MBOX_PADDR);
1601 volatile char *rx_buffer = (volatile char *) PHYS_TO_K1(BUFFER_PADDR);
1603 if (*mailbox) {
1604 int len;
1606 for (len = 0; len < BUFFER_SIZE-1 && rx_buffer[len] != '\000'; len++)
1608 rx_buffer[len] = '\000';
1609 console_write("[", 1);
1610 console_write((char *)rx_buffer, len);
1611 console_write("]\r\n", 3);
1612 *mailbox = 0;
1616 static int
1617 ui_cmd_talkdm(ui_cmdline_t *cmd, int argc, char *argv[])
1619 volatile int *mailbox;
1620 char tx_buffer[BUFFER_SIZE];
1621 int tx_len;
1622 uint64_t src, dst;
1623 int local = cmd_sw_isset(cmd, "-l");
1624 static char prompt[] = "Enter text, exit with \"!<ENTER>\"\r\n";
1626 if (!listener) {
1627 *((volatile int *) PHYS_TO_K1(MBOX_PADDR)) = 0;
1628 cfe_bg_add(cfe_recvdm, NULL);
1629 listener = 1;
1632 src = K0_TO_PHYS((uint64_t)tx_buffer);
1633 if (local) {
1634 mailbox = (volatile int *) PHYS_TO_K1 (MBOX_PADDR);
1635 dst = BUFFER_PADDR;
1637 else {
1638 mailbox = (volatile int *)
1639 PHYS_TO_XKSEG_UNCACHED (SBDMA_REMOTEP(MBOX_PADDR));
1640 dst = SBDMA_REMOTEP(BUFFER_PADDR);
1643 dm_init();
1644 dm_initctx(SBDMA_TALK_CH, 1, K_DM_DSCR_BASE_PRIORITY_1);
1645 #ifdef _SBDMA_INTERRUPTS_
1646 cfe_request_irq(K_INT_DM_CH_0 + SBDMA_TALK_CH,
1647 dm_interrupt, &sbgendma_ctx[SBDMA_TALK_CH], 0, 0);
1648 #endif /* _SBDMA_INTERRUPTS_ */
1650 console_write(prompt, strlen(prompt));
1652 for (;;) {
1653 tx_len = console_readline("", tx_buffer, BUFFER_SIZE-1);
1655 if (tx_len == 1 && tx_buffer[0] == '!') {
1656 console_write("bye\r\n", 5);
1657 break;
1660 tx_buffer[tx_len] = '\000';
1662 while (*mailbox == 1)
1663 POLL();
1665 dm_bcopy_p(SBDMA_TALK_CH, src, dst, tx_len+1, 0);
1666 *mailbox = 1;
1668 while (*mailbox == 1)
1669 POLL();
1672 #ifdef _SBDMA_INTERRUPTS_
1673 cfe_free_irq(K_INT_DM_CH_0 + SBDMA_TALK_CH, 0);
1674 #endif
1675 dm_uninitctx(SBDMA_TALK_CH);
1677 return 0;
1680 #else /* ! __long64 */
1681 int ui_init_testcmds2(void);
1682 int ui_init_testcmds2(void)
1684 return 0;
1686 #endif /* __long64 */