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

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

Added support for memspaces and const.
Added an interrupt masking to the "giet_context_switch" syscall
Corrected two bugs in boot/boot_init.c (one minor and one regarding barriers initialization)
Reformatted the code in all files.

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