source: soft/giet_vm/libs/stdio.c @ 232

Last change on this file since 232 was 232, checked in by meunier, 11 years ago

Ajout du malloc dans le Giet.

File size: 30.8 KB
Line 
1//////////////////////////////////////////////////////////////////////////////////
2// File     : stdio.c         
3// Date     : 01/04/2010
4// Author   : alain greiner & Joel Porquet
5// Copyright (c) UPMC-LIP6
6///////////////////////////////////////////////////////////////////////////////////
7// The stdio.c and stdio.h files are part of the GIET_VM nano-kernel.
8// This library contains all user-level functions that contain a system call
9// to access protected or shared ressources.
10///////////////////////////////////////////////////////////////////////////////////
11
12#include <stdarg.h>
13#include <stdio.h>
14
15#define SYSCALL_PROCID          0x00
16#define SYSCALL_PROCTIME        0x01
17#define SYSCALL_TTY_WRITE       0x02
18#define SYSCALL_TTY_READ        0x03
19#define SYSCALL_TIMER_START     0x04
20#define SYSCALL_TIMER_STOP      0x05
21#define SYSCALL_GCD_WRITE       0x06
22#define SYSCALL_GCD_READ        0x07
23#define SYSCALL_HEAP_INFO       0x08
24#define SYSCALL_PROC_TASK_ID    0x09
25#define SYSCALL_GLOBAL_TASK_ID  0x0A
26#define SYSCALL_CTX_SWITCH      0x0D
27#define SYSCALL_EXIT            0x0E
28#define SYSCALL_PROC_NUMBER     0x0F
29#define SYSCALL_FB_SYNC_WRITE   0x10
30#define SYSCALL_FB_SYNC_READ    0x11
31#define SYSCALL_FB_WRITE        0x12
32#define SYSCALL_FB_READ         0x13
33#define SYSCALL_FB_COMPLETED    0x14
34#define SYSCALL_IOC_WRITE       0x15
35#define SYSCALL_IOC_READ        0x16
36#define SYSCALL_IOC_COMPLETED   0x17
37#define SYSCALL_VOBJ_GET_VBASE  0x1A
38#define SYSCALL_NIC_WRITE       0x1B
39#define SYSCALL_NIC_READ        0x1C
40#define SYSCALL_NIC_COMPLETED   0x1D
41
42//////////////////////////////////////////////////////////////////////////////////
43// sys_call()
44// This generic C function is used to implement all system calls.
45// It writes the system call arguments in the proper registers,
46// and tells GCC what has been modified by system call execution.
47//////////////////////////////////////////////////////////////////////////////////
48static inline unsigned int sys_call(unsigned int call_no,
49        unsigned int arg_0, 
50        unsigned int arg_1, 
51        unsigned int arg_2, 
52        unsigned int arg_3) {
53    register unsigned int reg_no_and_output asm("v0") = call_no;
54    register unsigned int reg_a0 asm("a0") = arg_0;
55    register unsigned int reg_a1 asm("a1") = arg_1;
56    register unsigned int reg_a2 asm("a2") = arg_2;
57    register unsigned int reg_a3 asm("a3") = arg_3;
58
59    asm volatile(
60            "syscall"
61            : "=r" (reg_no_and_output)  /* output argument */
62            : "r" (reg_a0),             /* input arguments */
63            "r" (reg_a1),
64            "r" (reg_a2),
65            "r" (reg_a3),
66            "r" (reg_no_and_output)
67            : "memory",
68            /* These persistant registers will be saved on the stack by the
69             * compiler only if they contain relevant data. */
70            "at",
71            "v1",
72            "ra",
73            "t0",
74            "t1",
75            "t2",
76            "t3",
77            "t4",
78            "t5",
79            "t6",
80            "t7",
81            "t8",
82            "t9"
83               );
84    return reg_no_and_output;
85}
86
87/////      MIPS32 related system calls  /////
88
89////////////////////////////////////////////////////////////////////////////////////
90// giet_procid()
91////////////////////////////////////////////////////////////////////////////////////
92// This function returns the processor identifier.
93////////////////////////////////////////////////////////////////////////////////////
94unsigned int giet_procid() {
95    return sys_call(SYSCALL_PROCID, 0, 0, 0, 0);
96}
97
98
99////////////////////////////////////////////////////////////////////////////////////
100// giet_proctime()
101////////////////////////////////////////////////////////////////////////////////////
102// This function returns the local processor time (clock cycles since boot)
103////////////////////////////////////////////////////////////////////////////////////
104unsigned int giet_proctime() {
105    return sys_call(SYSCALL_PROCTIME, 0, 0, 0, 0);
106}
107
108
109//////     TTY device related system calls /////
110
111////////////////////////////////////////////////////////////////////////////////////
112// giet_tty_putc()
113////////////////////////////////////////////////////////////////////////////////////
114// This function displays a single ascii character on a terminal.
115// The terminal index must be defined in the task context in the boot phase.
116// It doesn't use the TTY_PUT_IRQ interrupt, and the associated kernel buffer.
117// - Returns 1 if the character has been written, 0 otherwise.
118////////////////////////////////////////////////////////////////////////////////////
119unsigned int giet_tty_putc(char byte) {
120    return sys_call(SYSCALL_TTY_WRITE, (unsigned int) (&byte), 1, 0, 0);
121}
122
123
124////////////////////////////////////////////////////////////////////////////////////
125// giet_tty_puts()
126////////////////////////////////////////////////////////////////////////////////////
127// This function displays a string on a terminal.
128// The terminal index must be defined in the task context in the boot phase.
129// The string must be terminated by a NUL character.
130// It doesn't use the TTY_PUT_IRQ interrupt, and the associated kernel buffer.
131// - Returns the number of written characters.
132////////////////////////////////////////////////////////////////////////////////////
133unsigned int giet_tty_puts(char * buf) {
134    unsigned int length = 0;
135    while (buf[length] != 0) {
136        length++;
137    }
138    return sys_call(SYSCALL_TTY_WRITE, (unsigned int) buf, length, 0, 0);
139}
140
141
142////////////////////////////////////////////////////////////////////////////////////
143// giet_tty_putw()
144////////////////////////////////////////////////////////////////////////////////////
145// This function displays the value of a 32-bit word with decimal characters.
146// The terminal index must be defined in the task context in the boot phase.
147// It doesn't use the TTY_PUT_IRQ interrupt, and the associated kernel buffer.
148// Returns the number of written characters (should be equal to ten).
149////////////////////////////////////////////////////////////////////////////////////
150unsigned int giet_tty_putw(unsigned int val) {
151    char buf[10];
152    unsigned int i;
153    for (i = 0; i < 10; i++) {
154        buf[9 - i] = (val % 10) + 0x30;
155        val = val / 10;
156    }
157    return sys_call(SYSCALL_TTY_WRITE, (unsigned int) buf, 10, 0, 0);
158}
159
160
161////////////////////////////////////////////////////////////////////////////////////
162// giet_tty_getc()
163////////////////////////////////////////////////////////////////////////////////////
164// This blocking function fetches a single ascii character from a terminal.
165// The terminal index must be defined in the task context in the boot phase.
166// It uses the IRQ_GET interrupt, and the associated kernel buffer.
167// - Returns 0 when completed.
168////////////////////////////////////////////////////////////////////////////////////
169unsigned int giet_tty_getc(char * byte) {
170    unsigned int ret = 0;
171    while (ret == 0) {
172        ret = sys_call(SYSCALL_TTY_READ, (unsigned int)byte, 1, 0, 0);
173    }
174    return 0;
175}
176
177
178////////////////////////////////////////////////////////////////////////////////////
179// giet_tty_gets()
180////////////////////////////////////////////////////////////////////////////////////
181// This blocking function fetches a string from a terminal to a fixed length buffer.
182// The terminal index must be defined in the task context in the boot phase.
183// It uses the TTY_GET_IRQ interrupt, anf the associated kernel buffer.
184// - Returns 0 when completed.
185// - Up to (bufsize - 1) characters (including the non printable characters)
186//   will be copied into buffer, and the string is always completed by a NUL
187//   character.
188// - The <LF> character is interpreted, as the function close the string with a
189//   NUL character if <LF> is read.
190// - The <DEL> character is interpreted, and the corresponding character(s) are
191//   removed from the target buffer.
192////////////////////////////////////////////////////////////////////////////////////
193unsigned int giet_tty_gets(char * buf, unsigned int bufsize) {
194    unsigned int ret;
195    unsigned char byte;
196    unsigned int index = 0;
197
198    while (index < (bufsize - 1)) {
199        do {
200            ret = sys_call(SYSCALL_TTY_READ, (unsigned int) (&byte), 1, 0, 0);
201        } while (ret != 1);
202
203        if (byte == 0x0A) {
204            break; /* LF */
205        }
206        else if ((byte == 0x7F) && (index > 0)) {
207            index--; /* DEL */
208        }
209        else {
210            buf[index] = byte;
211            index++;
212        }
213    }
214    buf[index] = 0;
215    return 0;
216}
217
218
219////////////////////////////////////////////////////////////////////////////////////
220// giet_tty_getw()
221////////////////////////////////////////////////////////////////////////////////////
222// This blocking function fetches a string of decimal characters (most
223// significant digit first) to build a 32-bit unsigned integer.
224// The terminal index must be defined in the task context in the boot phase.
225// It uses the TTY_GET_IRQ interrupt, anf the associated kernel buffer.
226// - Returns necessarily 0 when completed.
227//
228// - The non-blocking system function _tty_read_irq is called several times,
229//   and the decimal characters are written in a 32 characters buffer until a
230//   <LF> character is read.
231// - The <DEL> character is interpreted, and previous characters can be
232//   cancelled. All others characters are ignored.
233// - When the <LF> character is received, the string is converted to an
234//   unsigned int value. If the number of decimal digit is too large for the 32
235//   bits range, the zero value is returned.
236////////////////////////////////////////////////////////////////////////////////////
237unsigned int giet_tty_getw(unsigned int * val) {
238    unsigned char buf[32];
239    unsigned char byte;
240    unsigned int save = 0;
241    unsigned int dec = 0;
242    unsigned int done = 0;
243    unsigned int overflow = 0;
244    unsigned int max = 0;
245    unsigned int i;
246    unsigned int ret;
247
248    while (done == 0) {
249        do {
250            ret = sys_call(SYSCALL_TTY_READ, (unsigned int) (&byte), 1, 0, 0);
251        } while (ret != 1);
252
253        if ((byte > 0x2F) && (byte < 0x3A)) {
254            /* decimal character */
255            buf[max] = byte;
256            max++;
257            giet_tty_putc(byte);
258        }
259        else if ((byte == 0x0A) || (byte == 0x0D)) {
260            /* LF or CR character */
261            done = 1;
262        }
263        else if (byte == 0x7F) {
264            /* DEL character */
265            if (max > 0) {
266                max--; /* cancel the character */
267                giet_tty_putc(0x08);
268                giet_tty_putc(0x20);
269                giet_tty_putc(0x08);
270            }
271        }
272        if (max == 32) {
273            /* decimal string overflow */
274            for (i = 0; i < max; i++) {
275                /* cancel the string */
276                giet_tty_putc(0x08);
277                giet_tty_putc(0x20);
278                giet_tty_putc(0x08);
279            }
280            giet_tty_putc(0x30);
281            *val = 0; /* return 0 value */
282            return 0;
283        }
284    }
285
286    /* string conversion */
287    for (i = 0; i < max; i++) {
288        dec = dec * 10 + (buf[i] - 0x30);
289        if (dec < save) {
290            overflow = 1;
291        }
292        save = dec;
293    }
294
295    /* check overflow */
296    if (overflow == 0) {
297        *val = dec; /* return decimal value */
298    }
299    else {
300        for (i = 0; i < max; i++) {
301            /* cancel the string */
302            giet_tty_putc(0x08);
303            giet_tty_putc(0x20);
304            giet_tty_putc(0x08);
305        }
306        giet_tty_putc(0x30);
307        *val = 0; /* return 0 value */
308    }
309    return 0;
310}
311
312
313////////////////////////////////////////////////////////////////////////////////////
314// giet_tty_printf()
315////////////////////////////////////////////////////////////////////////////////////
316// This function is a simplified version of the mutek_printf() function.
317// The terminal index must be defined in the calling task context.
318// It doesn't use the IRQ_PUT interrupt, and the associated kernel buffer.
319// Only a limited number of formats are supported:
320//   - %d : signed decimal
321//   - %u : unsigned decimal
322//   - %x : hexadecimal
323//   - %c : char
324//   - %s : string
325// - Returns 0 if success, > 0 if error.
326////////////////////////////////////////////////////////////////////////////////////
327unsigned int giet_tty_printf(char * format, ...) {
328    va_list ap;
329    va_start(ap, format);
330    unsigned int ret;
331
332printf_text:
333
334    while (*format) {
335        unsigned int i;
336        for (i = 0; format[i] && format[i] != '%'; i++);
337        if (i) {
338            ret = sys_call(SYSCALL_TTY_WRITE, (unsigned int) format, i, 0, 0);
339            if (ret != i) {
340                return 1; /* return error */
341            }
342            format += i;
343        }
344        if (*format == '%') {
345            format++;
346            goto printf_arguments;
347        }
348    }
349
350    va_end(ap);
351    return 0;
352
353printf_arguments:
354
355    {
356        int val = va_arg(ap, long);
357        char buf[20];
358        char * pbuf;
359        unsigned int len = 0;
360        static const char HexaTab[] = "0123456789ABCDEF";
361        unsigned int i;
362
363        switch (*format++) {
364            case ('c'):             /* char conversion */
365                len = 1;
366                buf[0] = val;
367                pbuf = buf;
368                break;
369            case ('d'):             /* decimal signed integer */
370                if (val < 0) {
371                    val = -val;
372                    ret = sys_call(SYSCALL_TTY_WRITE, (unsigned int)"-", 1, 0, 0);
373                    if (ret != 1) {
374                        return 1; /* return error */
375                    }
376                }
377            case ('u'):             /* decimal unsigned integer */
378                for(i = 0; i < 10; i++) {
379                    buf[9 - i] = HexaTab[val % 10];
380                    if (!(val /= 10)) {
381                        break;
382                    }
383                }
384                len =  i + 1;
385                pbuf = &buf[9 - i];
386                break;
387            case ('x'):             /* hexadecimal integer */
388                ret = sys_call(SYSCALL_TTY_WRITE, (unsigned int) "0x", 2, 0, 0);
389                if (ret != 2) {
390                    return 1; /* return error */
391                }
392                for(i = 0; i < 8; i++) {
393                    buf[7 - i] = HexaTab[val % 16U];
394                    if (!(val /= 16U)) {
395                        break;
396                    }
397                }
398                len =  i + 1;
399                pbuf = &buf[7 - i];
400                break;
401            case ('s'):             /* string */
402                {
403                    char * str = (char *) val;
404                    while (str[len]) {
405                        len++;
406                    }
407                    pbuf = (char *) val;
408                }
409                break;
410            default:
411                goto printf_text;
412        }
413
414        ret = sys_call(SYSCALL_TTY_WRITE, (unsigned int) pbuf, len, 0, 0);
415        if (ret != len) {
416            return 1;
417        }
418        goto printf_text;
419    }
420}
421
422
423/////  TIMER related system calls //////
424
425//////////////////////////////////////////////////////////////////////////////////
426// giet_timer_start()
427//////////////////////////////////////////////////////////////////////////////////
428// This function activates the private user timer allocated to the calling task
429// in the boot phase.
430// - Returns 0 if success, > 0 if error.
431//////////////////////////////////////////////////////////////////////////////////
432unsigned int giet_timer_start() {
433    return sys_call(SYSCALL_TIMER_START, 0, 0, 0, 0);
434}
435
436
437//////////////////////////////////////////////////////////////////////////////////
438// giet_timer_stop()
439//////////////////////////////////////////////////////////////////////////////////
440// This function activates the user timer allocated to the calling task.
441// - Returns 0 if success, > 0 if error.
442//////////////////////////////////////////////////////////////////////////////////
443unsigned int giet_timer_stop() {
444    return sys_call(SYSCALL_TIMER_STOP, 0, 0, 0, 0);
445}
446
447
448/////  GCD (Greatest Common Divider) related system calls
449
450#define GCD_OPA     0
451#define GCD_OPB     1
452#define GCD_START   2
453#define GCD_STATUS  3
454
455//////////////////////////////////////////////////////////////////////////////////
456// giet_gcd_set_opa()
457//////////////////////////////////////////////////////////////////////////////////
458// This function sets the operand A in the GCD coprocessor.
459// - Returns 0 if success, > 0 if error.
460//////////////////////////////////////////////////////////////////////////////////
461unsigned int giet_gcd_set_opa(unsigned int val) {
462    return sys_call(SYSCALL_GCD_WRITE, GCD_OPA, val, 0, 0);
463}
464
465
466//////////////////////////////////////////////////////////////////////////////////
467//     giet_gcd_set_opb()
468//////////////////////////////////////////////////////////////////////////////////
469// This function sets operand B in the GCD coprocessor.
470// - Returns 0 if success, > 0 if error.
471//////////////////////////////////////////////////////////////////////////////////
472unsigned int giet_gcd_set_opb(unsigned int val) {
473    return sys_call(SYSCALL_GCD_WRITE, GCD_OPB, val, 0, 0);
474}
475
476
477//////////////////////////////////////////////////////////////////////////////////
478//     giet_gcd_start()
479//////////////////////////////////////////////////////////////////////////////////
480// This function starts the computation in the GCD coprocessor.
481// - Returns 0 if success, > 0 if error.
482//////////////////////////////////////////////////////////////////////////////////
483unsigned int giet_gcd_start() {
484    return sys_call(SYSCALL_GCD_WRITE, GCD_START, 0, 0, 0);
485}
486
487
488//////////////////////////////////////////////////////////////////////////////////
489//     giet_gcd_get_status()
490//////////////////////////////////////////////////////////////////////////////////
491// This function gets the status fromn the GCD coprocessor.
492// - The value is 0 when the coprocessor is idle (computation completed).
493//////////////////////////////////////////////////////////////////////////////////
494unsigned int giet_gcd_get_status(unsigned int * val) {
495    return sys_call(SYSCALL_GCD_READ, GCD_STATUS, (unsigned int) val, 0, 0);
496}
497
498
499//////////////////////////////////////////////////////////////////////////////////
500//     giet_gcd_get_result()
501//////////////////////////////////////////////////////////////////////////////////
502// This function gets the result of the computation from the GCD coprocessor.
503//////////////////////////////////////////////////////////////////////////////////
504unsigned int giet_gcd_get_result(unsigned int * val) {
505    return sys_call(SYSCALL_GCD_READ, GCD_OPA, (unsigned int) val, 0, 0);
506}
507
508
509///// Block device related system calls  /////
510
511//////////////////////////////////////////////////////////////////////////////////
512//     giet_ioc_write()
513//////////////////////////////////////////////////////////////////////////////////
514// Transfer data from a memory buffer to a file on the block_device.
515//     lba    : Logical Block Address (first block index)
516//     buffer : base address of the memory buffer
517//     count  : number of blocks to be transfered
518// - Returns 0 if success, > 0 if error (e.g. memory buffer not in user space).
519//////////////////////////////////////////////////////////////////////////////////
520unsigned int giet_ioc_write( unsigned int lba, void * buffer, unsigned int count) {
521    return sys_call(SYSCALL_IOC_WRITE, lba, (unsigned int) buffer, count, 0);
522}
523
524
525//////////////////////////////////////////////////////////////////////////////////
526// giet_ioc_read()
527//////////////////////////////////////////////////////////////////////////////////
528// Transfer data from a file on the block_device to a memory buffer.
529//     lba    : Logical Block Address (first block index)
530//     buffer : base address of the memory buffer
531//     count  : number of blocks to be transfered
532// - Returns 0 if success, > 0 if error (e.g. memory buffer not in user space).
533//////////////////////////////////////////////////////////////////////////////////
534unsigned int giet_ioc_read(unsigned int lba, void * buffer, unsigned int count) {
535    return sys_call(SYSCALL_IOC_READ, lba, (unsigned int) buffer, count, 0);
536}
537
538
539//////////////////////////////////////////////////////////////////////////////////
540// giet_ioc_completed()
541//////////////////////////////////////////////////////////////////////////////////
542// This blocking function returns 0 when the I/O transfer is
543// successfully completed, and returns 1 if an address error has been detected.
544//////////////////////////////////////////////////////////////////////////////////
545unsigned int giet_ioc_completed() {
546    return sys_call(SYSCALL_IOC_COMPLETED, 0, 0, 0, 0);
547}
548
549
550/////  Frame buffer device related system calls  /////
551
552//////////////////////////////////////////////////////////////////////////////////
553// giet_fb_sync_write()
554//////////////////////////////////////////////////////////////////////////////////
555// This blocking function use a memory copy strategy to transfer data from a
556// user buffer to the frame buffer device in kernel space.
557//     offset : offset (in bytes) in the frame buffer
558//     buffer : base address of the memory buffer
559//     length : number of bytes to be transfered
560// - Returns 0 if success, > 0 if error (e.g. memory buffer not in user space).
561//////////////////////////////////////////////////////////////////////////////////
562unsigned int giet_fb_sync_write(unsigned int offset, void * buffer, unsigned int length) {
563    return sys_call(SYSCALL_FB_SYNC_WRITE, offset, (unsigned int) buffer, length, 0);
564}
565
566
567//////////////////////////////////////////////////////////////////////////////////
568// giet_fb_sync_read()
569//////////////////////////////////////////////////////////////////////////////////
570// This blocking function use a memory copy strategy to transfer data from the
571// frame buffer device in kernel space to an user buffer.
572//     offset : offset (in bytes) in the frame buffer
573//     buffer : base address of the user buffer
574//     length : number of bytes to be transfered
575// - Returns 0 if success, > 0 if error (e.g. memory buffer not in user space).
576//////////////////////////////////////////////////////////////////////////////////
577unsigned int giet_fb_sync_read(unsigned int offset, void * buffer, unsigned int length) {
578    return sys_call(SYSCALL_FB_SYNC_READ, offset, (unsigned int) buffer, length, 0);
579}
580
581
582//////////////////////////////////////////////////////////////////////////////////
583// giet_fb_write()
584//////////////////////////////////////////////////////////////////////////////////
585// This non-blocking function use the DMA coprocessor to transfer data from a
586// user buffer to the frame buffer device in kernel space.
587// - offset : offset (in bytes) in the frame buffer
588// - buffer : base address of the user buffer
589// - length : number of bytes to be transfered
590// The transfer completion is signaled by an IRQ, and must be tested by the
591// fb_completed() function.
592// - Returns 0 if success, > 0 if error (e.g. memory buffer not in user space).
593//////////////////////////////////////////////////////////////////////////////////
594unsigned int giet_fb_write(unsigned int offset, void * buffer, unsigned int length) {
595    return sys_call(SYSCALL_FB_WRITE, offset, (unsigned int) buffer, length, 0);
596}
597
598
599//////////////////////////////////////////////////////////////////////////////////
600// giet_fb_read()
601//////////////////////////////////////////////////////////////////////////////////
602// This non-blocking function use the DMA coprocessor to transfer data from the
603// frame buffer device in kernel space to an user buffer.
604// - offset : offset (in bytes) in the frame buffer
605// - buffer : base address of the memory buffer
606// - length : number of bytes to be transfered
607// The transfer completion is signaled by an IRQ, and must be tested by the
608// fb_completed() function.
609// - Returns 0 if success, > 0 if error (e.g. memory buffer not in user space).
610//////////////////////////////////////////////////////////////////////////////////
611unsigned int giet_fb_read(unsigned int offset, void * buffer, unsigned int length) {
612    return sys_call(SYSCALL_FB_READ, offset, (unsigned int) buffer, length, 0);
613}
614
615
616//////////////////////////////////////////////////////////////////////////////////
617// giet_fb_completed()
618//////////////////////////////////////////////////////////////////////////////////
619// This blocking function returns when the transfer is completed.
620// - Returns 0 if success, > 0 if error.
621//////////////////////////////////////////////////////////////////////////////////
622unsigned int giet_fb_completed() {
623    return sys_call(SYSCALL_FB_COMPLETED, 0, 0, 0, 0);
624}
625
626
627//////////////////////////////////////////////////////////////////////////////////
628// giet_nic_write()
629//////////////////////////////////////////////////////////////////////////////////
630// This non-blocking function use the DMA coprocessor to transfer data from the
631// NIC device to an user buffer.
632// - offset : offset (in bytes) in the NIC
633// - buffer : base address of the memory buffer
634// - length : number of bytes to be transfered
635// The transfer completion is signaled by an IRQ, and must be tested by the
636// nic_completed() function.
637// - Returns 0 if success, > 0 if error (e.g. memory buffer not in user space).
638//////////////////////////////////////////////////////////////////////////////////
639
640unsigned int giet_nic_write(unsigned int offset, void * buffer, unsigned int length) {
641    return sys_call(SYSCALL_NIC_WRITE, offset, (unsigned int) buffer, length, 0);
642}
643
644
645//////////////////////////////////////////////////////////////////////////////////
646// giet_nic_read()
647//////////////////////////////////////////////////////////////////////////////////
648// This non-blocking function use the DMA coprocessor to transfer data from the
649// NIC device to an user buffer.
650// - offset : offset (in bytes) in the NIC
651// - buffer : base address of the memory buffer
652// - length : number of bytes to be transfered
653// The transfer completion is signaled by an IRQ, and must be tested by the
654// nic_completed() function.
655// - Returns 0 if success, > 0 if error (e.g. memory buffer not in user space).
656//////////////////////////////////////////////////////////////////////////////////
657
658unsigned int giet_nic_read(unsigned int offset, void * buffer, unsigned int length) {
659    return sys_call(SYSCALL_NIC_READ, offset, (unsigned int) buffer, length, 0);
660}
661
662
663//////////////////////////////////////////////////////////////////////////////////
664// giet_nic_completed()
665//////////////////////////////////////////////////////////////////////////////////
666// This blocking function returns when the transfer is completed.
667// - Returns 0 if success, > 0 if error.
668//////////////////////////////////////////////////////////////////////////////////
669unsigned int giet_nic_completed() {
670    return sys_call(SYSCALL_NIC_COMPLETED, 0, 0, 0, 0);
671}
672
673
674///// Miscellaneous related system calls /////
675
676//////////////////////////////////////////////////////////////////////////////////
677// giet_vobj_get_vbase()
678//////////////////////////////////////////////////////////////////////////////////
679// This function writes in argument (vobj_vaddr) the virtual base address
680// of a vobj (defined in the mapping_info data structure), identified by
681// the two arguments (vspace_name and vobj_name).
682// The (vobj_type) argument is redundant, and used for coherence checking.
683// - Returns the address if success,  0 if error ( not defined or wrong type )
684//////////////////////////////////////////////////////////////////////////////////
685unsigned int giet_vobj_get_vbase(char * vspace_name, char * vobj_name, unsigned int vobj_type, unsigned int * vobj_vaddr) {
686    return sys_call(SYSCALL_VOBJ_GET_VBASE, 
687            (unsigned int) vspace_name,
688            (unsigned int) vobj_name,
689            (unsigned int) vobj_type,
690            (unsigned int) vobj_vaddr);
691}
692
693
694////////////////////////////////////////////////////////////////////////////////////
695// giet_proc_number()
696////////////////////////////////////////////////////////////////////////////////////
697// This function returns in the buffer argument the number of processors
698// in the cluster specified by the cluster_id argument.
699// - Returns 0 if success, > 0 if error ( cluster index too large )
700////////////////////////////////////////////////////////////////////////////////////
701unsigned int giet_proc_number(unsigned int cluster_id, unsigned int * buffer) {
702    return sys_call(SYSCALL_PROC_NUMBER, cluster_id, (unsigned int) buffer, 0, 0);
703}
704
705
706/////  Miscellaneous system calls /////
707
708//////////////////////////////////////////////////////////////////////////////////
709// giet_task_exit()
710//////////////////////////////////////////////////////////////////////////////////
711// This function stops execution of the calling task with a TTY message,
712// and enter an infinite loop.
713// The task is blocked, but it still consume processor cycles ...
714//////////////////////////////////////////////////////////////////////////////////
715void giet_exit() {
716    sys_call(SYSCALL_EXIT, 0, 0, 0, 0);
717}
718
719
720///////////////////////////////////////////////////////////////////////////////////
721// giet_rand()
722// This function returns a pseudo-random value derived from the processor cycle
723// count. This value is comprised between 0 & 65535.
724///////////////////////////////////////////////////////////////////////////////////
725unsigned int giet_rand() {
726    unsigned int x = sys_call(SYSCALL_PROCTIME, 0, 0, 0, 0);
727    if ((x & 0xF) > 7) {
728        return (x*x & 0xFFFF);
729    }
730    else {
731        return (x*x*x & 0xFFFF);
732    }
733}
734
735
736//////////////////////////////////////////////////////////////////////////////////
737// giet_context_switch()
738// The user task calling this function is descheduled and
739// the processor is allocated to another task.
740//////////////////////////////////////////////////////////////////////////////////
741unsigned int giet_context_switch() {
742    return sys_call(SYSCALL_CTX_SWITCH, 0, 0, 0, 0);
743}
744
745//////////////////////////////////////////////////////////////////////////////////
746// giet_proc_task_id()
747// This functions returns the local task id, i.e. the processor task id (ranging
748// from 0 to n-1(p) for each processor if p has n tasks)
749//////////////////////////////////////////////////////////////////////////////////
750unsigned int giet_proc_task_id() {
751    return sys_call(SYSCALL_PROC_TASK_ID, 0, 0, 0, 0);
752}
753
754//////////////////////////////////////////////////////////////////////////////////
755// giet_heap_info()
756// This function returns the base address and size of the current task's heap
757//////////////////////////////////////////////////////////////////////////////////
758unsigned int giet_heap_info(unsigned int * vaddr, unsigned int * length) {
759    return sys_call(SYSCALL_HEAP_INFO, (unsigned int) vaddr, (unsigned int) length, 0, 0);
760}
761
762
763//////////////////////////////////////////////////////////////////////////////////
764// giet_global_task_id()
765// This functions returns the global task id, which is unique in all the giet
766//////////////////////////////////////////////////////////////////////////////////
767unsigned int giet_global_task_id() {
768    return sys_call(SYSCALL_GLOBAL_TASK_ID, 0, 0, 0, 0);
769}
770
771// Local Variables:
772// tab-width: 4
773// c-basic-offset: 4
774// c-file-offsets:((innamespace . 0)(inline-open . 0))
775// indent-tabs-mode: nil
776// End:
777// vim: filetype=c:expandtab:shiftwidth=4:tabstop=4:softtabstop=4
778
Note: See TracBrowser for help on using the repository browser.