source: soft/giet_vm/giet_common/utils.c @ 456

Last change on this file since 456 was 455, checked in by alain, 10 years ago

Introducing the tty0.c/tty0.h files defining access function to TTY0 (including the _printf().
Introducing the locks.c/locks.h files defining two types of spin-lock (with and without a waiting queue).

File size: 25.8 KB
Line 
1///////////////////////////////////////////////////////////////////////////////////
2// File     : utils.c
3// Date     : 18/10/2013
4// Author   : alain greiner
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The utils.c and utils.h files are part of the GIET-VM nano-kernel.
8///////////////////////////////////////////////////////////////////////////////////
9
10#include <utils.h>
11#include <tty0.h>
12#include <giet_config.h>
13#include <hard_config.h>
14#include <mapping_info.h>
15#include <tty_driver.h>
16#include <ctx_handler.h>
17
18// This global variable is allocated in the boot.c file or in kernel_init.c file
19extern static_scheduler_t* _schedulers[X_SIZE][Y_SIZE][NB_PROCS_MAX];
20
21///////////////////////////////////////////////////////////////////////////////////
22//         CP0 registers access functions
23///////////////////////////////////////////////////////////////////////////////////
24
25/////////////////////////
26unsigned int _get_sched() 
27{
28    unsigned int ret;
29    asm volatile( "mfc0      %0,     $4,2    \n" 
30                  : "=r"(ret) );
31    return ret;
32}
33///////////////////////
34unsigned int _get_epc() 
35{
36    unsigned int ret;
37    asm volatile( "mfc0      %0,    $14     \n"
38                  : "=r"(ret) );
39    return ret;
40}
41////////////////////////
42unsigned int _get_bvar() 
43{
44    unsigned int ret;
45    asm volatile( "mfc0      %0,    $8     \n"
46                  : "=r"(ret));
47    return ret;
48}
49//////////////////////
50unsigned int _get_cr() 
51{
52    unsigned int ret;
53    asm volatile( "mfc0      %0,    $13    \n"
54                  : "=r"(ret));
55    return ret;
56}
57//////////////////////
58unsigned int _get_sr() 
59{
60    unsigned int ret;
61    asm volatile( "mfc0      %0,     $12   \n"
62                  : "=r"(ret));
63    return ret;
64}
65//////////////////////////
66unsigned int _get_procid() 
67{
68    unsigned int ret;
69    asm volatile ( "mfc0     %0,     $15, 1  \n"
70                   :"=r" (ret) );
71    return (ret & 0xFFF);
72}
73////////////////////////////
74unsigned int _get_proctime() 
75{
76    unsigned int ret;
77    asm volatile ( "mfc0     %0,     $9      \n"
78                   :"=r" (ret) );
79    return ret;
80}
81
82/////////////////////////////////////////////
83void _it_disable( unsigned int * save_sr_ptr) 
84{
85    unsigned int sr = 0;
86    asm volatile( "li      $3,        0xFFFFFFFE    \n"
87                  "mfc0    %0,        $12           \n"
88                  "and     $3,        $3,   %0      \n" 
89                  "mtc0    $3,        $12           \n" 
90                  : "+r"(sr)
91                  :
92                  : "$3" );
93    *save_sr_ptr = sr;
94}
95//////////////////////////////////////////////
96void _it_restore( unsigned int * save_sr_ptr ) 
97{
98    unsigned int sr = *save_sr_ptr;
99    asm volatile( "mtc0    %0,        $12           \n" 
100                  :
101                  : "r"(sr)
102                  : "memory" );
103}
104
105/////////////////////////////////
106void _set_sched(unsigned int val) 
107{
108    asm volatile ( "mtc0     %0,     $4, 2          \n"
109                   :
110                   :"r" (val) );
111}
112//////////////////////////////
113void _set_sr(unsigned int val) 
114{
115    asm volatile ( "mtc0     %0,     $12            \n"
116                   :
117                   :"r" (val) );
118}
119
120
121///////////////////////////////////////////////////////////////////////////////////
122//         CP2 registers access functions
123///////////////////////////////////////////////////////////////////////////////////
124
125////////////////////////////
126unsigned int _get_mmu_ptpr() 
127{
128    unsigned int ret;
129    asm volatile( "mfc2      %0,     $0      \n"
130                  : "=r"(ret) );
131    return ret;
132}
133////////////////////////////
134unsigned int _get_mmu_mode() 
135{
136    unsigned int ret;
137    asm volatile( "mfc2      %0,     $1      \n"
138                  : "=r"(ret) );
139    return ret;
140}
141////////////////////////////////////
142void _set_mmu_ptpr(unsigned int val) 
143{
144    asm volatile ( "mtc2     %0,     $0      \n"
145                   :
146                   :"r" (val)
147                   :"memory" );
148}
149////////////////////////////////////
150void _set_mmu_mode(unsigned int val) 
151{
152    asm volatile ( "mtc2     %0,     $1      \n"
153                   :
154                   :"r" (val)
155                   :"memory" );
156}
157////////////////////////////////////////////
158void _set_mmu_dcache_inval(unsigned int val) 
159{
160    asm volatile ( "mtc2     %0,     $7      \n"
161                   :
162                   :"r" (val)
163                   :"memory" );
164}
165
166
167////////////////////////////////////////////////////////////////////////////
168//          Physical addressing related functions
169////////////////////////////////////////////////////////////////////////////
170
171///////////////////////////////////////////////////////
172unsigned int _physical_read( unsigned long long paddr ) 
173{
174    unsigned int value;
175    unsigned int lsb = (unsigned int) paddr;
176    unsigned int msb = (unsigned int) (paddr >> 32);
177    unsigned int sr;
178
179    _it_disable(&sr);
180
181    asm volatile( "mfc2   $2,     $1                 \n"     /* $2 <= MMU_MODE   */
182                  "andi   $3,     $2,        0xb     \n"
183                  "mtc2   $3,     $1                 \n"     /* DTLB off         */   
184
185                  "mtc2   %2,     $24                \n"     /* PADDR_EXT <= msb */   
186                  "lw     %0,     0(%1)              \n"     /* value <= *paddr  */
187                  "mtc2   $0,     $24                \n"     /* PADDR_EXT <= 0   */   
188
189                  "mtc2   $2,     $1                 \n"     /* restore MMU_MODE */
190                  : "=r" (value)
191                  : "r" (lsb), "r" (msb)
192                  : "$2", "$3" );
193
194    _it_restore(&sr);
195    return value;
196}
197////////////////////////////////////////////////
198void _physical_write( unsigned long long paddr, 
199                      unsigned int       value ) 
200{
201    unsigned int lsb = (unsigned int)paddr;
202    unsigned int msb = (unsigned int)(paddr >> 32);
203    unsigned int sr;
204
205   _it_disable(&sr);
206
207    asm volatile( "mfc2   $2,     $1                 \n"     /* $2 <= MMU_MODE   */
208                  "andi   $3,     $2,        0xb     \n"
209                  "mtc2   $3,     $1                 \n"     /* DTLB off         */   
210
211                  "mtc2   %2,     $24                \n"     /* PADDR_EXT <= msb */   
212                  "sw     %0,     0(%1)              \n"     /* *paddr <= value  */
213                  "mtc2   $0,     $24                \n"     /* PADDR_EXT <= 0   */   
214
215                  "mtc2   $2,     $1                 \n"     /* restore MMU_MODE */
216                  "sync                              \n"
217                  :
218                  : "r" (value), "r" (lsb), "r" (msb)
219                  : "$2", "$3" );
220
221    _it_restore(&sr);
222}
223
224/////////////////////////////////////////////////////////////////
225unsigned long long _physical_read_ull( unsigned long long paddr ) 
226{
227    unsigned int data_lsb;
228    unsigned int data_msb;
229    unsigned int addr_lsb = (unsigned int) paddr;
230    unsigned int addr_msb = (unsigned int) (paddr >> 32);
231    unsigned int sr;
232
233    _it_disable(&sr);
234
235    asm volatile( "mfc2   $2,     $1                 \n"     /* $2 <= MMU_MODE       */
236                  "andi   $3,     $2,        0xb     \n"
237                  "mtc2   $3,     $1                 \n"     /* DTLB off             */   
238
239                  "mtc2   %3,     $24                \n"     /* PADDR_EXT <= msb     */   
240                  "lw     %0,     0(%2)              \n"     /* data_lsb <= *paddr   */
241                  "lw     %1,     4(%2)              \n"     /* data_msb <= *paddr+4 */
242                  "mtc2   $0,     $24                \n"     /* PADDR_EXT <= 0       */   
243
244                  "mtc2   $2,     $1                 \n"     /* restore MMU_MODE     */
245                  : "=r" (data_lsb), "=r"(data_msb)
246                  : "r" (addr_lsb), "r" (addr_msb)
247                  : "$2", "$3" );
248
249    _it_restore(&sr);
250
251    return ( (((unsigned long long)data_msb)<<32) +
252             (((unsigned long long)data_lsb)) );
253}
254
255///////////////////////////////////////////////////
256void _physical_write_ull( unsigned long long paddr, 
257                          unsigned long long value ) 
258{
259    unsigned int addr_lsb = (unsigned int)paddr;
260    unsigned int addr_msb = (unsigned int)(paddr >> 32);
261    unsigned int data_lsb = (unsigned int)value;
262    unsigned int data_msb = (unsigned int)(value >> 32);
263    unsigned int sr;
264
265    _it_disable(&sr);
266
267    asm volatile( "mfc2   $2,     $1                 \n"     /* $2 <= MMU_MODE     */
268                  "andi   $3,     $2,        0xb     \n"
269                  "mtc2   $3,     $1                 \n"     /* DTLB off           */   
270
271                  "mtc2   %3,     $24                \n"     /* PADDR_EXT <= msb   */   
272                  "sw     %0,     0(%2)              \n"     /* *paddr <= value    */
273                  "sw     %1,     4(%2)              \n"     /* *paddr+4 <= value  */
274                  "mtc2   $0,     $24                \n"     /* PADDR_EXT <= 0     */   
275
276                  "mtc2   $2,     $1                 \n"     /* restore MMU_MODE   */
277                  "sync                              \n"
278                  :
279                  : "r" (data_lsb), "r" (data_msb), "r" (addr_lsb), "r" (addr_msb)
280                  : "$2", "$3" );
281
282    _it_restore(&sr);
283}
284
285////////////////////////////////////////////////////
286void _physical_memcpy( unsigned long long dst_paddr,  // destination buffer paddr
287                       unsigned long long src_paddr,  // source buffer paddr
288                       unsigned int size )            // bytes
289{
290    // check alignment constraints
291    if ( (dst_paddr & 3) || (src_paddr & 3) || (size & 3) ) 
292    {
293        _puts("\n[GIET ERROR] in _physical_memcpy() : buffer unaligned\n");
294        _exit();
295    }
296
297    unsigned int src_lsb = (unsigned int)src_paddr;
298    unsigned int src_msb = (unsigned int)(src_paddr >> 32);
299    unsigned int dst_lsb = (unsigned int)dst_paddr;
300    unsigned int dst_msb = (unsigned int)(dst_paddr >> 32);
301    unsigned int iter    = size>>2;
302    unsigned int data;
303    unsigned int sr;
304
305    _it_disable(&sr);
306
307    asm volatile( "mfc2   $2,     $1                 \n"     /* $2 <= current MMU_MODE */
308                  "andi   $3,     $2,        0xb     \n"     /* $3 <= new MMU_MODE     */
309                  "mtc2   $3,     $1                 \n"     /* DTLB off               */   
310
311                  "move   $4,     %5                 \n"     /* $4 < iter              */
312                  "move   $5,     %1                 \n"     /* $5 < src_lsb           */
313                  "move   $6,     %3                 \n"     /* $6 < src_lsb           */
314
315                  "ph_memcpy_loop:                   \n"
316                  "mtc2   %2,     $24                \n"     /* PADDR_EXT <= src_msb   */   
317                  "lw     %0,     0($5)              \n"     /* data <= *src_paddr     */
318                  "mtc2   %4,     $24                \n"     /* PADDR_EXT <= dst_msb   */   
319                  "sw     %0,     0($6)              \n"     /* *dst_paddr <= data     */
320
321                  "addi   $4,     $4,       -1       \n"     /* iter = iter - 1        */
322                  "addi   $5,     $5,        4       \n"     /* src_lsb += 4           */
323                  "addi   $6,     $6,        4       \n"     /* dst_lsb += 4           */
324                  "bne    $4,     $0, ph_memcpy_loop \n"
325                  "nop                               \n"
326
327                  "mtc2   $0,     $24                \n"     /* PADDR_EXT <= 0         */   
328                  "mtc2   $2,     $1                 \n"     /* restore MMU_MODE       */
329                  : "=r" (data)
330                  : "r" (src_lsb), "r" (src_msb), "r" (dst_lsb), "r"(dst_msb), "r"(iter)
331                  : "$2", "$3", "$4", "$5", "$6" );
332
333    _it_restore(&sr);
334} // end _physical_memcpy()
335
336////////////////////////////////////////////////
337void _physical_memset( unsigned long long paddr,     // destination buffer paddr
338                       unsigned int       size,      // bytes
339                       unsigned int       data )     // written value
340{
341    // check alignment constraints
342    if ( (paddr & 3) || (size & 7) )
343    {
344        _puts("\n[GIET ERROR] in _physical_memset() : buffer unaligned\n");
345        _exit();
346    }
347
348    unsigned int lsb  = (unsigned int)paddr;
349    unsigned int msb  = (unsigned int)(paddr >> 32);
350    unsigned int sr;
351
352    _it_disable(&sr);
353
354    asm volatile( "mfc2   $8,     $1                 \n"     /* $8 <= current MMU_MODE */
355                  "andi   $9,     $8,        0xb     \n"     /* $9 <= new MMU_MODE     */
356                  "mtc2   $9,     $1                 \n"     /* DTLB off               */
357                  "mtc2   %3,     $24                \n"     /* PADDR_EXT <= msb       */
358
359                  "1:                                \n"     /* set 8 bytes per iter   */
360                  "sw     %2,     0(%0)              \n"     /* *src_paddr     = data  */
361                  "sw     %2,     4(%0)              \n"     /* *(src_paddr+4) = data  */
362                  "addi   %1,     %1,       -8       \n"     /* size -= 8              */
363                  "addi   %0,     %0,        8       \n"     /* src_paddr += 8         */
364                  "bnez   %1,     1b                 \n"     /* loop while size != 0   */
365
366                  "mtc2   $0,     $24                \n"     /* PADDR_EXT <= 0         */
367                  "mtc2   $8,     $1                 \n"     /* restore MMU_MODE       */
368                  : "+r"(lsb), "+r"(size)
369                  : "r"(data), "r" (msb)
370                  : "$8", "$9", "memory" );
371
372    _it_restore(&sr);
373}  // _physical_memset()
374
375///////////////////////////////////////////////
376void _io_extended_write( unsigned int*  vaddr,
377                         unsigned int   value )
378{
379    unsigned long long paddr;
380
381    if ( _get_mmu_mode() & 0x4 )  // MMU activated : use virtual address
382    {
383        *vaddr = value;
384    }
385    else                          // use paddr extension for IO
386    {
387        paddr = (unsigned long long)(unsigned int)vaddr +
388                (((unsigned long long)((X_IO<<Y_WIDTH) + Y_IO))<<32); 
389        _physical_write( paddr, value );
390    }
391    asm volatile("sync" ::: "memory");
392}
393
394//////////////////////////////////////////////////////
395unsigned int _io_extended_read( unsigned int*  vaddr )
396{
397    unsigned long long paddr;
398
399    if ( _get_mmu_mode() & 0x4 )  // MMU activated : use virtual address
400    {
401        return *(volatile unsigned int*)vaddr;
402    }
403    else                          // use paddr extension for IO
404    {
405        paddr = (unsigned long long)(unsigned int)vaddr +
406                (((unsigned long long)((X_IO<<Y_WIDTH) + Y_IO))<<32); 
407        return _physical_read( paddr );
408    }
409}
410
411
412
413////////////////////////////////////////////////////////////////////////////////////
414//           Scheduler and tasks context access functions
415////////////////////////////////////////////////////////////////////////////////////
416
417
418///////////////////////////////////
419unsigned int _get_current_task_id() 
420{
421    static_scheduler_t * psched = (static_scheduler_t *) _get_sched();
422    return (unsigned int) (psched->current);
423}
424
425////////////////////////////////////////////
426unsigned int _get_task_slot( unsigned int x,
427                             unsigned int y,
428                             unsigned int p,
429                             unsigned int ltid,
430                             unsigned int slot )
431{
432    static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
433    return psched->context[ltid][slot];
434}
435
436////////////////////////////////////
437void _set_task_slot( unsigned int x,
438                     unsigned int y,
439                     unsigned int p,
440                     unsigned int ltid,
441                     unsigned int slot,
442                     unsigned int value )
443{
444    static_scheduler_t* psched  = (static_scheduler_t*)_schedulers[x][y][p];
445    psched->context[ltid][slot] = value;
446}
447
448///////////////////////////////////////////////////
449unsigned int _get_context_slot( unsigned int slot )
450{
451    static_scheduler_t* psched  = (static_scheduler_t*)_get_sched();
452    unsigned int        task_id = psched->current;
453    return psched->context[task_id][slot];
454}
455
456///////////////////////////////////////////
457void _set_context_slot( unsigned int slot,
458                       unsigned int value )
459{
460    static_scheduler_t* psched  = (static_scheduler_t*)_get_sched();
461    unsigned int        task_id = psched->current;
462    psched->context[task_id][slot] = value;
463}
464
465/////////////////////////////////////////////////////////////////////////////
466//      Access functions to mapping_info data structure
467/////////////////////////////////////////////////////////////////////////////
468
469////////////////////////////////////////////////////////////////
470mapping_cluster_t * _get_cluster_base(mapping_header_t * header) 
471{
472    return (mapping_cluster_t *) ((char *) header +
473            MAPPING_HEADER_SIZE);
474}
475//////////////////////////////////////////////////////////
476mapping_pseg_t * _get_pseg_base(mapping_header_t * header) 
477{
478    return (mapping_pseg_t *) ((char *) header +
479            MAPPING_HEADER_SIZE +
480            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE);
481}
482//////////////////////////////////////////////////////////////
483mapping_vspace_t * _get_vspace_base(mapping_header_t * header) 
484{
485    return (mapping_vspace_t *)  ((char *) header +
486            MAPPING_HEADER_SIZE +
487            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
488            MAPPING_PSEG_SIZE * header->psegs);
489}
490//////////////////////////////////////////////////////////
491mapping_vseg_t * _get_vseg_base(mapping_header_t * header)
492{
493    return (mapping_vseg_t *) ((char *) header +
494            MAPPING_HEADER_SIZE +
495            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
496            MAPPING_PSEG_SIZE * header->psegs +
497            MAPPING_VSPACE_SIZE * header->vspaces);
498}
499//////////////////////////////////////////////////////////
500mapping_vobj_t * _get_vobj_base(mapping_header_t * header) 
501{
502    return (mapping_vobj_t *) ((char *) header +
503            MAPPING_HEADER_SIZE +
504            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
505            MAPPING_PSEG_SIZE * header->psegs +
506            MAPPING_VSPACE_SIZE * header->vspaces +
507            MAPPING_VSEG_SIZE * header->vsegs );
508}
509//////////////////////////////////////////////////////////
510mapping_task_t * _get_task_base(mapping_header_t * header) 
511{
512    return (mapping_task_t *) ((char *) header +
513            MAPPING_HEADER_SIZE +
514            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
515            MAPPING_PSEG_SIZE * header->psegs +
516            MAPPING_VSPACE_SIZE * header->vspaces +
517            MAPPING_VOBJ_SIZE * header->vobjs +
518            MAPPING_VSEG_SIZE * header->vsegs);
519}
520/////////////////////////////////////////////////////////
521mapping_proc_t *_get_proc_base(mapping_header_t * header) 
522{
523    return (mapping_proc_t *) ((char *) header +
524            MAPPING_HEADER_SIZE +
525            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
526            MAPPING_PSEG_SIZE * header->psegs +
527            MAPPING_VSPACE_SIZE * header->vspaces +
528            MAPPING_VSEG_SIZE * header->vsegs +
529            MAPPING_VOBJ_SIZE * header->vobjs +
530            MAPPING_TASK_SIZE * header->tasks);
531}
532///////////////////////////////////////////////////////
533mapping_irq_t *_get_irq_base(mapping_header_t * header) 
534{
535    return (mapping_irq_t *) ((char *) header +
536            MAPPING_HEADER_SIZE +
537            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
538            MAPPING_PSEG_SIZE * header->psegs +
539            MAPPING_VSPACE_SIZE * header->vspaces +
540            MAPPING_VSEG_SIZE * header->vsegs +
541            MAPPING_VOBJ_SIZE * header->vobjs +
542            MAPPING_TASK_SIZE * header->tasks +
543            MAPPING_PROC_SIZE * header->procs);
544}
545/////////////////////////////////////////////////////////////
546mapping_coproc_t *_get_coproc_base(mapping_header_t * header) 
547{
548    return (mapping_coproc_t *) ((char *) header +
549            MAPPING_HEADER_SIZE +
550            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
551            MAPPING_PSEG_SIZE * header->psegs +
552            MAPPING_VSPACE_SIZE * header->vspaces +
553            MAPPING_VOBJ_SIZE * header->vobjs +
554            MAPPING_VSEG_SIZE * header->vsegs +
555            MAPPING_TASK_SIZE * header->tasks +
556            MAPPING_PROC_SIZE * header->procs +
557            MAPPING_IRQ_SIZE * header->irqs);
558}
559///////////////////////////////////////////////////////////////
560mapping_cp_port_t *_get_cp_port_base(mapping_header_t * header) 
561{
562    return (mapping_cp_port_t *) ((char *) header +
563            MAPPING_HEADER_SIZE +
564            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
565            MAPPING_PSEG_SIZE * header->psegs +
566            MAPPING_VSPACE_SIZE * header->vspaces +
567            MAPPING_VOBJ_SIZE * header->vobjs +
568            MAPPING_VSEG_SIZE * header->vsegs +
569            MAPPING_TASK_SIZE * header->tasks +
570            MAPPING_PROC_SIZE * header->procs +
571            MAPPING_IRQ_SIZE * header->irqs +
572            MAPPING_COPROC_SIZE * header->coprocs);
573}
574/////////////////////////////////////////////////////////////
575mapping_periph_t *_get_periph_base(mapping_header_t * header) 
576{
577    return (mapping_periph_t *) ((char *) header +
578            MAPPING_HEADER_SIZE +
579            MAPPING_CLUSTER_SIZE * X_SIZE * Y_SIZE +
580            MAPPING_PSEG_SIZE * header->psegs +
581            MAPPING_VSPACE_SIZE * header->vspaces +
582            MAPPING_VOBJ_SIZE * header->vobjs +
583            MAPPING_VSEG_SIZE * header->vsegs +
584            MAPPING_TASK_SIZE * header->tasks +
585            MAPPING_PROC_SIZE * header->procs +
586            MAPPING_IRQ_SIZE * header->irqs +
587            MAPPING_COPROC_SIZE * header->coprocs +
588            MAPPING_CP_PORT_SIZE * header->cp_ports);
589}
590
591///////////////////////////////////////////////////////////////////////////////////
592//             Miscelaneous functions
593///////////////////////////////////////////////////////////////////////////////////
594
595//////////////////////////////////////
596__attribute__((noreturn)) void _exit() 
597{
598    unsigned int procid     = _get_procid();
599    unsigned int x          = (procid >> (Y_WIDTH + P_WIDTH)) & ((1<<X_WIDTH)-1);
600    unsigned int y          = (procid >> P_WIDTH) & ((1<<Y_WIDTH)-1);
601    unsigned int lpid       = procid & ((1<<P_WIDTH)-1);
602
603
604    _puts("\n[GIET PANIC] processor[");
605    _putd( x );
606    _puts(",");
607    _putd( y );
608    _puts(",");
609    _putd( lpid );
610    _puts("] exit at cycle ");
611    _putd( _get_proctime() );
612    _puts(" ...\n");
613
614    while (1) { asm volatile ("nop"); }
615}
616
617/////////////////////////////////////
618void _random_wait( unsigned int val )
619{
620    unsigned int mask  = (1<<(val&0x1F))-1;
621    unsigned int delay = (_get_proctime() ^ (_get_procid()<<4)) & mask;
622    asm volatile( "move  $3,   %0                 \n"
623                  "loop_nic_completed:            \n"
624                  "addi  $3,   $3, -1             \n"
625                  "bnez  $3,   loop_nic_completed \n"
626                  "nop                            \n"
627                  :
628                  : "r" (delay)
629                  : "$3" ); 
630}
631
632///////////////////////////
633void _break( char* string ) 
634{
635    char byte;
636
637    _puts("\n[GIET DEBUG] break from ");
638    _puts( string );
639    _puts(" / stoke any key to continue\n");
640    _getc( &byte );
641}
642
643///////////////////////////////////////
644unsigned int _strncmp( const char * s1, 
645                       const char * s2, 
646                       unsigned int n ) 
647{
648    unsigned int i;
649    for (i = 0; i < n; i++) 
650    {
651        if (s1[i] != s2[i])  return 1; 
652        if (s1[i] == 0)      break;
653    }
654    return 0;
655}
656
657/////////////////////////////////////////
658char* _strcpy( char* dest, char* source )
659{
660    if (!dest || !source) return dest;
661
662    while (*source)
663        *(dest++) = *(source++);
664
665    return dest;
666}
667
668/////////////////////////////////////////////////////
669void _dcache_buf_invalidate( unsigned int buf_vbase, 
670                             unsigned int buf_size ) 
671{
672    unsigned int offset;
673    unsigned int tmp;
674    unsigned int line_size;   // bytes
675
676    // compute data cache line size based on config register (bits 12:10)
677    asm volatile(
678                 "mfc0 %0, $16, 1" 
679                 : "=r" (tmp) );
680
681    tmp = ((tmp >> 10) & 0x7);
682    line_size = 2 << tmp;
683
684    // iterate on cache lines
685    for ( offset = 0; offset < buf_size; offset += line_size) 
686    {
687        _set_mmu_dcache_inval( buf_vbase + offset );
688    }
689}
690
691
692
693///////////////////////////////////////////////////////////////////////////////////
694//   Required by GCC
695///////////////////////////////////////////////////////////////////////////////////
696
697////////////////////////////////
698void* memcpy( void*        dest,     // dest buffer vbase
699              const void*  source,   // source buffer vbase
700              unsigned int size )    // bytes
701{
702    unsigned int* idst = (unsigned int*)dest;
703    unsigned int* isrc = (unsigned int*)source;
704
705    // word-by-word copy
706    if (!((unsigned int) idst & 3) && !((unsigned int) isrc & 3)) 
707    {
708        while (size > 3) 
709        {
710            *idst++ = *isrc++;
711            size -= 4;
712        }
713    }
714
715    unsigned char* cdst = (unsigned char*)dest;
716    unsigned char* csrc = (unsigned char*)source;
717
718    /* byte-by-byte copy */
719    while (size--) 
720    {
721        *cdst++ = *csrc++;
722    }
723    return dest;
724}
725
726/////////////////////////////////
727void * memset( void*        dst, 
728               int          value, 
729               unsigned int count ) 
730{
731    // word-by-word copy
732    unsigned int* idst = dst;
733    unsigned int  data = (((unsigned char)value)      ) |
734                         (((unsigned char)value) <<  8) |
735                         (((unsigned char)value) << 16) |
736                         (((unsigned char)value) << 24) ;
737
738    if ( ! ((unsigned int)idst & 3) )
739    {
740        while ( count > 3 )
741        {
742            *idst++ = data;
743            count -= 4;
744        }
745    }
746   
747    // byte-by-byte copy
748    unsigned char* cdst = dst;
749    while (count--) 
750    {
751        *cdst++ = (unsigned char)value;
752    }
753    return dst;
754}
755
756
757// Local Variables:
758// tab-width: 4
759// c-basic-offset: 4
760// c-file-offsets:((innamespace . 0)(inline-open . 0))
761// indent-tabs-mode: nil
762// End:
763// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
764
Note: See TracBrowser for help on using the repository browser.