/** * PROM Library for Cisco Systems 7200 Series Routers * (C) 2008 Philippe Vachon * ----------------------------------------------------------- */ /** * Calling convention: * a0 - syscall number * a1 - arg1 ... etc * v0 - returned value from syscall */ #include /* putc - Syscall 1 * output character c to console * @param c ASCII number for character */ void c_putc(const char c) { asm ( ".set noreorder\n " "li $a0, %[syscall]\n" "lb $a1, (%[character])\n" "syscall\n" "nop\n" ".set reorder\n" : /* no output */ : [character] "r"(&c), [syscall] "g"(PUTC) : "a0", "a1" ); } /* puts - wrapper for putc * output the string pointed to by s * @param s String to be written to the console */ void c_puts(const char *s) { while(*s != '\0') { c_putc(*(s++)); } } /* putsn - put a string of length n on the console * @param s string to be written * @param n length */ void c_putsn(const char *s, int n) { int i = 0; while (*s != '\0' && i != n) { c_putc(*(s++)); i++; } } /* getc - Syscall n * get one character of input from the console * @return ASCII code for character read from console */ char c_getc(void) { char c; asm ( ".set noreorder\n " "li $a0, %[syscall]\n" "syscall\n" "nop\n" "move %[charout], $v0 \n" ".set reorder\n" : [charout] "=r" (c) : [syscall] "g" (GETC) : "a0","v0" ); return c; } /* gets - wrapper for getc * reads up to n characters into buffer b * @param b Buffer to read characters into * @param n size of buffer * @return the number of characters read into b */ int c_gets(char *b, int n) { int i = 0; do { b[i] = c_getc(); c_putc(b[i]); i++; if (b[i - 1] == '\n' || b[i-1] == '\r') { break; } else if (b[i - 1] == 0x8) { i--; } } while (i < n); b[i - 1] = '\0'; return i; } /* c_version - get version string * @return pointer to version string */ char *c_verstr(void) { char *c; asm ( ".set noreorder\n" "li $a0, %[syscall]\n" "syscall\n" "nop\n" "move %[result], $v0\n" ".set reorder\n" : [result] "=r" (c) : [syscall] "g" (VERSION) : "a0", "v0" ); return c; } /* memsz - get total memory size (in bytes) * @return the size of the memory installed in the router, in bytes */ int c_memsz(void) { int r = 0; asm ( " .set noreorder \n" "li $a0, %[syscall]\n" "syscall\n" "nop\n" "move %[result], $v0\n" ".set reorder\n" : [result] "=r" (r) : [syscall] "g" (MEMSIZE) : "a0","v0" ); return r; } /* timer - get number of ticks from timer * @return the value in the timer */ long c_timer(void) { long t = 0; asm (" .set noreorder\n" "li $a0, %[syscall]\n" "syscall\n" "nop\n" "move %[result], $a0\n" ".set reorder\n" : [result]"=r"(t) : [syscall]"g"(TIMER) : "a0","v0" ); return t; } /* String length with a maximum length allowed * @param s pointer to string * @param maxlen maximum length */ int c_strnlen(const char *s, int maxlen) { int i = 0; if (!s) return 0; while (*(s++) != '\0' && i != maxlen) { i++; } return i; } /* baud - get console baud rate * @return boot console baud rate */ int c_baud(void) { int b = 0; asm volatile (".set noreorder\n" "li $a0, %[syscall]\n" "syscall\n" "nop\n" "move %[result], $a0\n" ".set reorder\n" : [result]"=r"(b) : [syscall]"g"(GETBAUD) : "a0", "v0" ); return b; }