| [158] | 1 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 2 | // File     : stdio.c | 
|---|
|  | 3 | // Date     : 01/04/2010 | 
|---|
|  | 4 | // Author   : alain greiner & Joel Porquet | 
|---|
|  | 5 | // Copyright (c) UPMC-LIP6 | 
|---|
|  | 6 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [203] | 7 | // The stdio.c and stdio.h files are part of the GIET_VM nano-kernel. | 
|---|
| [158] | 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 | 
|---|
| [203] | 19 | #define SYSCALL_TIMER_START     0x04 | 
|---|
|  | 20 | #define SYSCALL_TIMER_STOP      0x05 | 
|---|
| [158] | 21 | #define SYSCALL_GCD_WRITE       0x06 | 
|---|
|  | 22 | #define SYSCALL_GCD_READ        0x07 | 
|---|
| [232] | 23 | #define SYSCALL_HEAP_INFO       0x08 | 
|---|
|  | 24 | #define SYSCALL_PROC_TASK_ID    0x09 | 
|---|
|  | 25 | #define SYSCALL_GLOBAL_TASK_ID  0x0A | 
|---|
| [158] | 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 | 
|---|
| [237] | 37 | #define SYSCALL_IOC_BLOCK_SIZE  0x18 | 
|---|
| [228] | 38 | #define SYSCALL_VOBJ_GET_VBASE  0x1A | 
|---|
| [218] | 39 | #define SYSCALL_NIC_WRITE       0x1B | 
|---|
|  | 40 | #define SYSCALL_NIC_READ        0x1C | 
|---|
|  | 41 | #define SYSCALL_NIC_COMPLETED   0x1D | 
|---|
| [158] | 42 |  | 
|---|
|  | 43 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 44 | // sys_call() | 
|---|
| [158] | 45 | // This generic C function is used to implement all system calls. | 
|---|
| [165] | 46 | // It writes the system call arguments in the proper registers, | 
|---|
|  | 47 | // and tells GCC what has been modified by system call execution. | 
|---|
| [158] | 48 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 49 | static 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) { | 
|---|
| [158] | 54 | register unsigned int reg_no_and_output asm("v0") = call_no; | 
|---|
| [228] | 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; | 
|---|
| [158] | 59 |  | 
|---|
|  | 60 | asm volatile( | 
|---|
|  | 61 | "syscall" | 
|---|
|  | 62 | : "=r" (reg_no_and_output)  /* output argument */ | 
|---|
|  | 63 | : "r" (reg_a0),             /* input arguments */ | 
|---|
| [228] | 64 | "r" (reg_a1), | 
|---|
|  | 65 | "r" (reg_a2), | 
|---|
|  | 66 | "r" (reg_a3), | 
|---|
|  | 67 | "r" (reg_no_and_output) | 
|---|
| [158] | 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 |  | 
|---|
| [228] | 88 | /////      MIPS32 related system calls  ///// | 
|---|
| [158] | 89 |  | 
|---|
|  | 90 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 91 | // giet_procid() | 
|---|
|  | 92 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 93 | // This function returns the processor identifier. | 
|---|
|  | 94 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 95 | unsigned int giet_procid() { | 
|---|
|  | 96 | return sys_call(SYSCALL_PROCID, 0, 0, 0, 0); | 
|---|
| [158] | 97 | } | 
|---|
| [228] | 98 |  | 
|---|
|  | 99 |  | 
|---|
| [158] | 100 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 101 | // giet_proctime() | 
|---|
|  | 102 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 103 | // This function returns the local processor time (clock cycles since boot) | 
|---|
|  | 104 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [238] | 105 | unsigned int giet_proctime() | 
|---|
|  | 106 | { | 
|---|
| [228] | 107 | return sys_call(SYSCALL_PROCTIME, 0, 0, 0, 0); | 
|---|
| [158] | 108 | } | 
|---|
|  | 109 |  | 
|---|
|  | 110 |  | 
|---|
| [228] | 111 | //////     TTY device related system calls ///// | 
|---|
|  | 112 |  | 
|---|
| [158] | 113 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 114 | // giet_tty_putc() | 
|---|
|  | 115 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 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 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [238] | 121 | unsigned int giet_tty_putc(char byte) | 
|---|
|  | 122 | { | 
|---|
| [228] | 123 | return sys_call(SYSCALL_TTY_WRITE, (unsigned int) (&byte), 1, 0, 0); | 
|---|
| [158] | 124 | } | 
|---|
| [228] | 125 |  | 
|---|
|  | 126 |  | 
|---|
| [158] | 127 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 128 | // giet_tty_puts() | 
|---|
|  | 129 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 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 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [238] | 136 | unsigned int giet_tty_puts(char * buf) | 
|---|
|  | 137 | { | 
|---|
| [158] | 138 | unsigned int length = 0; | 
|---|
| [238] | 139 | while (buf[length] != 0) { length++; } | 
|---|
| [228] | 140 | return sys_call(SYSCALL_TTY_WRITE, (unsigned int) buf, length, 0, 0); | 
|---|
| [158] | 141 | } | 
|---|
| [228] | 142 |  | 
|---|
|  | 143 |  | 
|---|
| [158] | 144 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 145 | // giet_tty_putw() | 
|---|
|  | 146 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 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 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [238] | 152 | unsigned int giet_tty_putw(unsigned int val) | 
|---|
|  | 153 | { | 
|---|
| [158] | 154 | char buf[10]; | 
|---|
|  | 155 | unsigned int i; | 
|---|
| [238] | 156 | for (i = 0; i < 10; i++) | 
|---|
|  | 157 | { | 
|---|
| [228] | 158 | buf[9 - i] = (val % 10) + 0x30; | 
|---|
| [158] | 159 | val = val / 10; | 
|---|
|  | 160 | } | 
|---|
| [228] | 161 | return sys_call(SYSCALL_TTY_WRITE, (unsigned int) buf, 10, 0, 0); | 
|---|
| [158] | 162 | } | 
|---|
| [228] | 163 |  | 
|---|
|  | 164 |  | 
|---|
| [158] | 165 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 166 | // giet_tty_getc() | 
|---|
|  | 167 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 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 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [238] | 173 | unsigned int giet_tty_getc(char * byte) | 
|---|
|  | 174 | { | 
|---|
| [158] | 175 | unsigned int ret = 0; | 
|---|
| [238] | 176 | while (ret == 0) | 
|---|
|  | 177 | { | 
|---|
| [228] | 178 | ret = sys_call(SYSCALL_TTY_READ, (unsigned int)byte, 1, 0, 0); | 
|---|
| [158] | 179 | } | 
|---|
|  | 180 | return 0; | 
|---|
|  | 181 | } | 
|---|
| [228] | 182 |  | 
|---|
|  | 183 |  | 
|---|
| [158] | 184 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 185 | // giet_tty_gets() | 
|---|
|  | 186 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 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. | 
|---|
| [238] | 194 | // - The <LF> character is interpreted, and the function close the string with a | 
|---|
| [158] | 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 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [238] | 199 | unsigned int giet_tty_gets( char*        buf, | 
|---|
|  | 200 | unsigned int bufsize) | 
|---|
|  | 201 | { | 
|---|
| [158] | 202 | unsigned int ret; | 
|---|
|  | 203 | unsigned char byte; | 
|---|
|  | 204 | unsigned int index = 0; | 
|---|
|  | 205 |  | 
|---|
| [238] | 206 | while (index < (bufsize - 1)) | 
|---|
|  | 207 | { | 
|---|
|  | 208 | do { ret = sys_call(SYSCALL_TTY_READ, (unsigned int) (&byte), 1, 0, 0); } | 
|---|
|  | 209 | while (ret != 1); | 
|---|
| [158] | 210 |  | 
|---|
| [238] | 211 | if (byte == 0x0A)  /* LF */ | 
|---|
|  | 212 | { | 
|---|
|  | 213 | break; | 
|---|
| [228] | 214 | } | 
|---|
| [238] | 215 | else if ((byte == 0x7F) && (index > 0))  /* DEL */ | 
|---|
|  | 216 | { | 
|---|
|  | 217 | index--; | 
|---|
| [228] | 218 | } | 
|---|
| [238] | 219 | else | 
|---|
|  | 220 | { | 
|---|
| [158] | 221 | buf[index] = byte; | 
|---|
|  | 222 | index++; | 
|---|
|  | 223 | } | 
|---|
|  | 224 | } | 
|---|
|  | 225 | buf[index] = 0; | 
|---|
|  | 226 | return 0; | 
|---|
|  | 227 | } | 
|---|
| [228] | 228 |  | 
|---|
|  | 229 |  | 
|---|
| [158] | 230 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 231 | // giet_tty_getw() | 
|---|
|  | 232 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 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 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [238] | 248 | unsigned int giet_tty_getw(unsigned int * val) | 
|---|
|  | 249 | { | 
|---|
| [158] | 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 |  | 
|---|
| [238] | 260 | while (done == 0) | 
|---|
|  | 261 | { | 
|---|
|  | 262 | do { ret = sys_call(SYSCALL_TTY_READ, (unsigned int) (&byte), 1, 0, 0); } | 
|---|
|  | 263 | while (ret != 1); | 
|---|
| [158] | 264 |  | 
|---|
| [238] | 265 | if ((byte > 0x2F) && (byte < 0x3A))  /* decimal character */ | 
|---|
|  | 266 | { | 
|---|
| [158] | 267 | buf[max] = byte; | 
|---|
|  | 268 | max++; | 
|---|
| [165] | 269 | giet_tty_putc(byte); | 
|---|
| [158] | 270 | } | 
|---|
| [238] | 271 | else if ((byte == 0x0A))   /* LF */ | 
|---|
|  | 272 | { | 
|---|
| [158] | 273 | done = 1; | 
|---|
|  | 274 | } | 
|---|
| [238] | 275 | else if (byte == 0x7F)   /* DEL */ | 
|---|
|  | 276 | { | 
|---|
|  | 277 | if (max > 0) | 
|---|
|  | 278 | { | 
|---|
|  | 279 | max--;      /* cancel the character */ | 
|---|
| [165] | 280 | giet_tty_putc(0x08); | 
|---|
|  | 281 | giet_tty_putc(0x20); | 
|---|
|  | 282 | giet_tty_putc(0x08); | 
|---|
| [158] | 283 | } | 
|---|
|  | 284 | } | 
|---|
| [238] | 285 | if (max == 32)  /* decimal string overflow */ | 
|---|
|  | 286 | { | 
|---|
|  | 287 | for (i = 0; i < max; i++) | 
|---|
|  | 288 | { | 
|---|
| [228] | 289 | /* cancel the string */ | 
|---|
| [165] | 290 | giet_tty_putc(0x08); | 
|---|
|  | 291 | giet_tty_putc(0x20); | 
|---|
|  | 292 | giet_tty_putc(0x08); | 
|---|
| [158] | 293 | } | 
|---|
| [165] | 294 | giet_tty_putc(0x30); | 
|---|
| [238] | 295 | *val = 0;      /* return 0 value */ | 
|---|
| [158] | 296 | return 0; | 
|---|
|  | 297 | } | 
|---|
|  | 298 | } | 
|---|
|  | 299 |  | 
|---|
|  | 300 | /* string conversion */ | 
|---|
| [238] | 301 | for (i = 0; i < max; i++) | 
|---|
|  | 302 | { | 
|---|
| [158] | 303 | dec = dec * 10 + (buf[i] - 0x30); | 
|---|
| [238] | 304 | if (dec < save)  overflow = 1; | 
|---|
| [158] | 305 | save = dec; | 
|---|
|  | 306 | } | 
|---|
|  | 307 |  | 
|---|
|  | 308 | /* check overflow */ | 
|---|
| [238] | 309 | if (overflow == 0) | 
|---|
|  | 310 | { | 
|---|
| [158] | 311 | *val = dec; /* return decimal value */ | 
|---|
|  | 312 | } | 
|---|
| [238] | 313 | else | 
|---|
|  | 314 | { | 
|---|
|  | 315 | for (i = 0; i < max; i++) | 
|---|
|  | 316 | { | 
|---|
| [228] | 317 | /* cancel the string */ | 
|---|
| [165] | 318 | giet_tty_putc(0x08); | 
|---|
|  | 319 | giet_tty_putc(0x20); | 
|---|
|  | 320 | giet_tty_putc(0x08); | 
|---|
| [158] | 321 | } | 
|---|
| [165] | 322 | giet_tty_putc(0x30); | 
|---|
| [238] | 323 | *val = 0;         /* return 0 value */ | 
|---|
| [158] | 324 | } | 
|---|
|  | 325 | return 0; | 
|---|
|  | 326 | } | 
|---|
| [228] | 327 |  | 
|---|
|  | 328 |  | 
|---|
| [158] | 329 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 330 | // giet_tty_printf() | 
|---|
|  | 331 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 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 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [238] | 343 | unsigned int giet_tty_printf(char * format, ...) | 
|---|
|  | 344 | { | 
|---|
| [158] | 345 | va_list ap; | 
|---|
|  | 346 | va_start(ap, format); | 
|---|
|  | 347 | unsigned int ret; | 
|---|
|  | 348 |  | 
|---|
|  | 349 | printf_text: | 
|---|
|  | 350 |  | 
|---|
| [238] | 351 | while (*format) | 
|---|
|  | 352 | { | 
|---|
| [158] | 353 | unsigned int i; | 
|---|
| [228] | 354 | for (i = 0; format[i] && format[i] != '%'; i++); | 
|---|
| [238] | 355 | if (i) | 
|---|
|  | 356 | { | 
|---|
| [228] | 357 | ret = sys_call(SYSCALL_TTY_WRITE, (unsigned int) format, i, 0, 0); | 
|---|
| [238] | 358 | if (ret != i)  return 1; /* return error */ | 
|---|
| [158] | 359 | format += i; | 
|---|
|  | 360 | } | 
|---|
| [238] | 361 | if (*format == '%') | 
|---|
|  | 362 | { | 
|---|
| [158] | 363 | format++; | 
|---|
|  | 364 | goto printf_arguments; | 
|---|
|  | 365 | } | 
|---|
|  | 366 | } | 
|---|
|  | 367 |  | 
|---|
|  | 368 | va_end(ap); | 
|---|
|  | 369 | return 0; | 
|---|
|  | 370 |  | 
|---|
|  | 371 | printf_arguments: | 
|---|
|  | 372 |  | 
|---|
|  | 373 | { | 
|---|
| [228] | 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; | 
|---|
| [158] | 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; | 
|---|
| [228] | 390 | ret = sys_call(SYSCALL_TTY_WRITE, (unsigned int)"-", 1, 0, 0); | 
|---|
|  | 391 | if (ret != 1) { | 
|---|
| [158] | 392 | return 1; /* return error */ | 
|---|
| [228] | 393 | } | 
|---|
| [158] | 394 | } | 
|---|
|  | 395 | case ('u'):             /* decimal unsigned integer */ | 
|---|
| [228] | 396 | for(i = 0; i < 10; i++) { | 
|---|
|  | 397 | buf[9 - i] = HexaTab[val % 10]; | 
|---|
|  | 398 | if (!(val /= 10)) { | 
|---|
|  | 399 | break; | 
|---|
|  | 400 | } | 
|---|
| [158] | 401 | } | 
|---|
| [228] | 402 | len =  i + 1; | 
|---|
|  | 403 | pbuf = &buf[9 - i]; | 
|---|
| [158] | 404 | break; | 
|---|
|  | 405 | case ('x'):             /* hexadecimal integer */ | 
|---|
| [228] | 406 | ret = sys_call(SYSCALL_TTY_WRITE, (unsigned int) "0x", 2, 0, 0); | 
|---|
|  | 407 | if (ret != 2) { | 
|---|
| [158] | 408 | return 1; /* return error */ | 
|---|
|  | 409 | } | 
|---|
| [228] | 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]; | 
|---|
| [158] | 418 | break; | 
|---|
|  | 419 | case ('s'):             /* string */ | 
|---|
|  | 420 | { | 
|---|
| [228] | 421 | char * str = (char *) val; | 
|---|
|  | 422 | while (str[len]) { | 
|---|
|  | 423 | len++; | 
|---|
|  | 424 | } | 
|---|
|  | 425 | pbuf = (char *) val; | 
|---|
| [158] | 426 | } | 
|---|
|  | 427 | break; | 
|---|
|  | 428 | default: | 
|---|
|  | 429 | goto printf_text; | 
|---|
|  | 430 | } | 
|---|
|  | 431 |  | 
|---|
| [228] | 432 | ret = sys_call(SYSCALL_TTY_WRITE, (unsigned int) pbuf, len, 0, 0); | 
|---|
|  | 433 | if (ret != len) { | 
|---|
| [158] | 434 | return 1; | 
|---|
| [228] | 435 | } | 
|---|
| [158] | 436 | goto printf_text; | 
|---|
|  | 437 | } | 
|---|
|  | 438 | } | 
|---|
|  | 439 |  | 
|---|
| [203] | 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 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 450 | unsigned int giet_timer_start() { | 
|---|
|  | 451 | return sys_call(SYSCALL_TIMER_START, 0, 0, 0, 0); | 
|---|
| [203] | 452 | } | 
|---|
| [228] | 453 |  | 
|---|
|  | 454 |  | 
|---|
| [203] | 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 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 461 | unsigned int giet_timer_stop() { | 
|---|
|  | 462 | return sys_call(SYSCALL_TIMER_STOP, 0, 0, 0, 0); | 
|---|
| [203] | 463 | } | 
|---|
|  | 464 |  | 
|---|
| [228] | 465 |  | 
|---|
| [165] | 466 | /////  GCD (Greatest Common Divider) related system calls | 
|---|
| [158] | 467 |  | 
|---|
|  | 468 | #define GCD_OPA     0 | 
|---|
|  | 469 | #define GCD_OPB     1 | 
|---|
|  | 470 | #define GCD_START   2 | 
|---|
|  | 471 | #define GCD_STATUS  3 | 
|---|
|  | 472 |  | 
|---|
|  | 473 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 474 | // giet_gcd_set_opa() | 
|---|
|  | 475 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 476 | // This function sets the operand A in the GCD coprocessor. | 
|---|
|  | 477 | // - Returns 0 if success, > 0 if error. | 
|---|
|  | 478 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 479 | unsigned int giet_gcd_set_opa(unsigned int val) { | 
|---|
|  | 480 | return sys_call(SYSCALL_GCD_WRITE, GCD_OPA, val, 0, 0); | 
|---|
| [158] | 481 | } | 
|---|
| [228] | 482 |  | 
|---|
|  | 483 |  | 
|---|
| [158] | 484 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 485 | //     giet_gcd_set_opb() | 
|---|
| [165] | 486 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 487 | // This function sets operand B in the GCD coprocessor. | 
|---|
|  | 488 | // - Returns 0 if success, > 0 if error. | 
|---|
|  | 489 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 490 | unsigned int giet_gcd_set_opb(unsigned int val) { | 
|---|
|  | 491 | return sys_call(SYSCALL_GCD_WRITE, GCD_OPB, val, 0, 0); | 
|---|
| [158] | 492 | } | 
|---|
| [228] | 493 |  | 
|---|
|  | 494 |  | 
|---|
| [158] | 495 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 496 | //     giet_gcd_start() | 
|---|
| [165] | 497 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 498 | // This function starts the computation in the GCD coprocessor. | 
|---|
|  | 499 | // - Returns 0 if success, > 0 if error. | 
|---|
|  | 500 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 501 | unsigned int giet_gcd_start() { | 
|---|
|  | 502 | return sys_call(SYSCALL_GCD_WRITE, GCD_START, 0, 0, 0); | 
|---|
| [158] | 503 | } | 
|---|
| [228] | 504 |  | 
|---|
|  | 505 |  | 
|---|
| [158] | 506 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 507 | //     giet_gcd_get_status() | 
|---|
| [165] | 508 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 509 | // This function gets the status fromn the GCD coprocessor. | 
|---|
|  | 510 | // - The value is 0 when the coprocessor is idle (computation completed). | 
|---|
|  | 511 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 512 | unsigned int giet_gcd_get_status(unsigned int * val) { | 
|---|
|  | 513 | return sys_call(SYSCALL_GCD_READ, GCD_STATUS, (unsigned int) val, 0, 0); | 
|---|
| [158] | 514 | } | 
|---|
| [228] | 515 |  | 
|---|
|  | 516 |  | 
|---|
| [158] | 517 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 518 | //     giet_gcd_get_result() | 
|---|
| [165] | 519 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 520 | // This function gets the result of the computation from the GCD coprocessor. | 
|---|
|  | 521 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 522 | unsigned int giet_gcd_get_result(unsigned int * val) { | 
|---|
|  | 523 | return sys_call(SYSCALL_GCD_READ, GCD_OPA, (unsigned int) val, 0, 0); | 
|---|
| [158] | 524 | } | 
|---|
|  | 525 |  | 
|---|
| [228] | 526 |  | 
|---|
| [158] | 527 | ///// Block device related system calls  ///// | 
|---|
|  | 528 |  | 
|---|
|  | 529 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 530 | //     giet_ioc_write() | 
|---|
| [165] | 531 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 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 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 538 | unsigned 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); | 
|---|
| [158] | 540 | } | 
|---|
| [228] | 541 |  | 
|---|
|  | 542 |  | 
|---|
| [158] | 543 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 544 | // giet_ioc_read() | 
|---|
|  | 545 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 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 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 552 | unsigned 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); | 
|---|
| [158] | 554 | } | 
|---|
| [228] | 555 |  | 
|---|
|  | 556 |  | 
|---|
| [158] | 557 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 558 | // giet_ioc_completed() | 
|---|
|  | 559 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 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 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 563 | unsigned int giet_ioc_completed() { | 
|---|
|  | 564 | return sys_call(SYSCALL_IOC_COMPLETED, 0, 0, 0, 0); | 
|---|
| [158] | 565 | } | 
|---|
|  | 566 |  | 
|---|
| [228] | 567 |  | 
|---|
| [237] | 568 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 569 | // giet_ioc_block_size() | 
|---|
|  | 570 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 571 | // This blocking function returns the block_size (in bytes) of the block device | 
|---|
|  | 572 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 573 | unsigned int giet_ioc_block_size() { | 
|---|
|  | 574 | return sys_call(SYSCALL_IOC_BLOCK_SIZE, 0, 0, 0, 0); | 
|---|
|  | 575 | } | 
|---|
|  | 576 |  | 
|---|
|  | 577 |  | 
|---|
| [158] | 578 | /////  Frame buffer device related system calls  ///// | 
|---|
|  | 579 |  | 
|---|
|  | 580 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 581 | // giet_fb_sync_write() | 
|---|
|  | 582 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 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 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 590 | unsigned 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); | 
|---|
| [158] | 592 | } | 
|---|
| [228] | 593 |  | 
|---|
|  | 594 |  | 
|---|
| [158] | 595 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 596 | // giet_fb_sync_read() | 
|---|
|  | 597 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 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 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 605 | unsigned 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); | 
|---|
| [158] | 607 | } | 
|---|
| [228] | 608 |  | 
|---|
|  | 609 |  | 
|---|
| [158] | 610 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 611 | // giet_fb_write() | 
|---|
|  | 612 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 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 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 622 | unsigned 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); | 
|---|
| [158] | 624 | } | 
|---|
| [228] | 625 |  | 
|---|
|  | 626 |  | 
|---|
| [158] | 627 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 628 | // giet_fb_read() | 
|---|
|  | 629 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 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 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 639 | unsigned 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); | 
|---|
| [158] | 641 | } | 
|---|
| [228] | 642 |  | 
|---|
|  | 643 |  | 
|---|
| [158] | 644 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 645 | // giet_fb_completed() | 
|---|
|  | 646 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 647 | // This blocking function returns when the transfer is completed. | 
|---|
|  | 648 | // - Returns 0 if success, > 0 if error. | 
|---|
|  | 649 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 650 | unsigned int giet_fb_completed() { | 
|---|
|  | 651 | return sys_call(SYSCALL_FB_COMPLETED, 0, 0, 0, 0); | 
|---|
| [158] | 652 | } | 
|---|
|  | 653 |  | 
|---|
| [228] | 654 |  | 
|---|
| [218] | 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 |  | 
|---|
| [228] | 668 | unsigned 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); | 
|---|
| [218] | 670 | } | 
|---|
|  | 671 |  | 
|---|
| [228] | 672 |  | 
|---|
| [218] | 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 |  | 
|---|
| [228] | 686 | unsigned 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); | 
|---|
| [218] | 688 | } | 
|---|
|  | 689 |  | 
|---|
| [228] | 690 |  | 
|---|
| [218] | 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 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 697 | unsigned int giet_nic_completed() { | 
|---|
|  | 698 | return sys_call(SYSCALL_NIC_COMPLETED, 0, 0, 0, 0); | 
|---|
| [218] | 699 | } | 
|---|
|  | 700 |  | 
|---|
| [228] | 701 |  | 
|---|
| [165] | 702 | ///// Miscellaneous related system calls ///// | 
|---|
| [158] | 703 |  | 
|---|
|  | 704 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 705 | // giet_vobj_get_vbase() | 
|---|
| [158] | 706 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 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 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 713 | unsigned int giet_vobj_get_vbase(char * vspace_name, char * vobj_name, unsigned int vobj_type, unsigned int * vobj_vaddr) { | 
|---|
| [160] | 714 | return sys_call(SYSCALL_VOBJ_GET_VBASE, | 
|---|
| [228] | 715 | (unsigned int) vspace_name, | 
|---|
|  | 716 | (unsigned int) vobj_name, | 
|---|
|  | 717 | (unsigned int) vobj_type, | 
|---|
|  | 718 | (unsigned int) vobj_vaddr); | 
|---|
| [158] | 719 | } | 
|---|
| [165] | 720 |  | 
|---|
| [228] | 721 |  | 
|---|
| [158] | 722 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 723 | // giet_proc_number() | 
|---|
|  | 724 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 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 | //////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 729 | unsigned 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); | 
|---|
| [158] | 731 | } | 
|---|
|  | 732 |  | 
|---|
| [228] | 733 |  | 
|---|
| [158] | 734 | /////  Miscellaneous system calls ///// | 
|---|
|  | 735 |  | 
|---|
|  | 736 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 737 | // giet_task_exit() | 
|---|
|  | 738 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [158] | 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 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 743 | void giet_exit() { | 
|---|
|  | 744 | sys_call(SYSCALL_EXIT, 0, 0, 0, 0); | 
|---|
| [158] | 745 | } | 
|---|
| [228] | 746 |  | 
|---|
|  | 747 |  | 
|---|
| [158] | 748 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [165] | 749 | // giet_rand() | 
|---|
| [158] | 750 | // This function returns a pseudo-random value derived from the processor cycle | 
|---|
|  | 751 | // count. This value is comprised between 0 & 65535. | 
|---|
|  | 752 | /////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 753 | unsigned int giet_rand() { | 
|---|
|  | 754 | unsigned int x = sys_call(SYSCALL_PROCTIME, 0, 0, 0, 0); | 
|---|
|  | 755 | if ((x & 0xF) > 7) { | 
|---|
| [158] | 756 | return (x*x & 0xFFFF); | 
|---|
| [228] | 757 | } | 
|---|
|  | 758 | else { | 
|---|
| [158] | 759 | return (x*x*x & 0xFFFF); | 
|---|
| [228] | 760 | } | 
|---|
| [158] | 761 | } | 
|---|
| [228] | 762 |  | 
|---|
|  | 763 |  | 
|---|
| [158] | 764 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 765 | // giet_context_switch() | 
|---|
| [158] | 766 | // The user task calling this function is descheduled and | 
|---|
|  | 767 | // the processor is allocated to another task. | 
|---|
|  | 768 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [228] | 769 | unsigned int giet_context_switch() { | 
|---|
|  | 770 | return sys_call(SYSCALL_CTX_SWITCH, 0, 0, 0, 0); | 
|---|
| [158] | 771 | } | 
|---|
|  | 772 |  | 
|---|
| [228] | 773 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [232] | 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) | 
|---|
| [228] | 777 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
| [232] | 778 | unsigned int giet_proc_task_id() { | 
|---|
|  | 779 | return sys_call(SYSCALL_PROC_TASK_ID, 0, 0, 0, 0); | 
|---|
| [228] | 780 | } | 
|---|
| [158] | 781 |  | 
|---|
| [232] | 782 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 783 | // giet_heap_info() | 
|---|
|  | 784 | // This function returns the base address and size of the current task's heap | 
|---|
|  | 785 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 786 | unsigned 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 | } | 
|---|
| [228] | 789 |  | 
|---|
| [232] | 790 |  | 
|---|
|  | 791 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 792 | // giet_global_task_id() | 
|---|
|  | 793 | // This functions returns the global task id, which is unique in all the giet | 
|---|
|  | 794 | ////////////////////////////////////////////////////////////////////////////////// | 
|---|
|  | 795 | unsigned int giet_global_task_id() { | 
|---|
|  | 796 | return sys_call(SYSCALL_GLOBAL_TASK_ID, 0, 0, 0, 0); | 
|---|
|  | 797 | } | 
|---|
|  | 798 |  | 
|---|
| [228] | 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 |  | 
|---|