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

Last change on this file since 247 was 238, checked in by alain, 12 years ago

Major evolution to support physical addresses larger than 32 bits.
The map.xml format has been modified: the vsegs associated to schedulers
are now explicitely defined and mapped in the page tables.

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