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

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

Adding a syscall to allow a user to know the block size with which the block device has been configured.

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