cleanup
authorJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 12 Nov 2020 04:52:42 +0000 (06:52 +0200)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Thu, 12 Nov 2020 04:52:42 +0000 (06:52 +0200)
34 files changed:
Makefile
src/asm.h
src/contty.c [new file with mode: 0644]
src/contty.h [new file with mode: 0644]
src/libc/alloca.h [new file with mode: 0644]
src/libc/assert.h [new file with mode: 0644]
src/libc/ctype.c
src/libc/ctype.h
src/libc/errno.h [new file with mode: 0644]
src/libc/float.h [new file with mode: 0644]
src/libc/inttypes.h [new file with mode: 0644]
src/libc/limits.h [new file with mode: 0644]
src/libc/math.c [new file with mode: 0644]
src/libc/math.h [new file with mode: 0644]
src/libc/rand.c [new file with mode: 0644]
src/libc/setjmp.c [new file with mode: 0644]
src/libc/setjmp.h [new file with mode: 0644]
src/libc/stdarg.h [new file with mode: 0644]
src/libc/stddef.h [new file with mode: 0644]
src/libc/stdint.h
src/libc/stdio.c [new file with mode: 0644]
src/libc/stdio.h [new file with mode: 0644]
src/libc/stdlib.c [new file with mode: 0644]
src/libc/stdlib.h [new file with mode: 0644]
src/libc/string.c
src/libc/string.h
src/main.c
src/panic.c [new file with mode: 0644]
src/panic.h [new file with mode: 0644]
src/rpi.c [new file with mode: 0644]
src/rpi.h [new file with mode: 0644]
src/serial.c
src/timer.h [deleted file]
src/video.c

index ac7afa8..24a3fb6 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -17,8 +17,8 @@ endif
 
 warn = -pedantic -Wall
 dbg = -g
-inc = -Isrc/libc
-gccopt = -marm -fpic -ffreestanding -nostdinc
+inc = -Isrc -Isrc/libc
+gccopt = -marm -fpic -ffreestanding -nostdinc -ffast-math -fno-math-errno
 #arch = -mcpu=arm1176jzf-s
 arch = -mcpu=cortex-a7
 
index 61d29ac..425a8ee 100644 (file)
--- a/src/asm.h
+++ b/src/asm.h
@@ -10,4 +10,6 @@
                "bne 0b\n\t" \
                :: "r"(x) : "cc")
 
+#define halt_cpu() asm volatile("wfe");
+
 #endif /* ASM_H_ */
diff --git a/src/contty.c b/src/contty.c
new file mode 100644 (file)
index 0000000..581d2c8
--- /dev/null
@@ -0,0 +1,17 @@
+#include "contty.h"
+#include "serial.h"
+
+int con_init(void)
+{
+       return 0;
+}
+
+void con_putchar(int c)
+{
+       ser_putchar(c);
+}
+
+int con_getchar(void)
+{
+       return ser_getchar();
+}
diff --git a/src/contty.h b/src/contty.h
new file mode 100644 (file)
index 0000000..b71e836
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef CONTTY_H_
+#define CONTTY_H_
+
+int con_init(void);
+
+void con_putchar(int c);
+int con_getchar(void);
+
+#endif /* CONTTY_H_ */
diff --git a/src/libc/alloca.h b/src/libc/alloca.h
new file mode 100644 (file)
index 0000000..2c86643
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef ALLOCA_H_
+#define ALLOCA_H_
+
+#define alloca(x)      __builtin_alloca(x)
+
+#endif /* ALLOCA_H_ */
diff --git a/src/libc/assert.h b/src/libc/assert.h
new file mode 100644 (file)
index 0000000..4ac0d15
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef ASSERT_H_
+#define ASSERT_H_
+
+#include "panic.h"
+
+#define assert(x) \
+       if(!(x)) { \
+               panic("Kernel assertion failed at " __FILE__ ":%d: " #x "\n", __LINE__); \
+       }
+
+#endif /* ASSERT_H_ */
index 9676441..f720566 100644 (file)
@@ -52,5 +52,5 @@ int toupper(int c)
 
 int tolower(int c)
 {
-       return isupper(c) ? (c + ('A' - 'a')) : c;
+       return isupper(c) ? (c - ('A' - 'a')) : c;
 }
index a36c694..5b010d4 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef CTYPES_H_
-#define CTYPES_H_
+#ifndef CTYPE_H_
+#define CTYPE_H_
 
 int isalnum(int c);
 int isalpha(int c);
@@ -14,5 +14,4 @@ int isspace(int c);
 int toupper(int c);
 int tolower(int c);
 
-
-#endif /* CTYPES_H_ */
+#endif /* CTYPE_H_ */
diff --git a/src/libc/errno.h b/src/libc/errno.h
new file mode 100644 (file)
index 0000000..4bc9f6a
--- /dev/null
@@ -0,0 +1,24 @@
+#ifndef ERRNO_H_
+#define ERRNO_H_
+
+#define EFOO                   1
+#define EAGAIN                 2
+#define EINVAL                 3
+#define ECHILD                 4
+#define EBUSY                  5
+#define ENOMEM                 6
+#define EIO                            7
+#define ENOENT                 8
+#define ENAMETOOLONG   9
+#define ENOSPC                 10
+#define EPERM                  11
+#define ENOTDIR                        12
+#define EISDIR                 13
+#define EEXIST                 14
+#define ERANGE                 34
+
+#define EBUG                   127     /* for missing features and known bugs */
+
+int errno;
+
+#endif /* ERRNO_H_ */
diff --git a/src/libc/float.h b/src/libc/float.h
new file mode 100644 (file)
index 0000000..974e00e
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef FLOAT_H_
+#define FLOAT_H_
+
+#define FLT_MIN        __FLT_MIN__
+#define FLT_MAX        __FLT_MAX__
+
+#endif /* FLOAT_H_ */
diff --git a/src/libc/inttypes.h b/src/libc/inttypes.h
new file mode 100644 (file)
index 0000000..1f10b06
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef INTTYPES_H_
+#define INTTYPES_H_
+
+typedef char int8_t;
+typedef short int16_t;
+typedef int int32_t;
+typedef long long int64_t;
+
+typedef unsigned char uint8_t;
+typedef unsigned short uint16_t;
+typedef unsigned int uint32_t;
+typedef unsigned long long uint64_t;
+
+#endif /* INTTYPES_H_ */
diff --git a/src/libc/limits.h b/src/libc/limits.h
new file mode 100644 (file)
index 0000000..7a09d92
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef LIMITS_H_
+#define LIMITS_H_
+
+#define CHAR_BIT       8
+
+#define SHRT_MIN       (-32768)
+#define SHRT_MAX       32767
+#define INT_MIN                (-2147483648)
+#define INT_MAX                2147483647
+#define LONG_MIN       (-2147483648)
+#define LONG_MAX       2147483647
+
+#define USHRT_MAX      65535
+#define UINT_MAX       0xffffffff
+#define ULONG_MAX      0xffffffff
+
+#define PATH_MAX       256
+
+#endif /* LIMITS_H_ */
diff --git a/src/libc/math.c b/src/libc/math.c
new file mode 100644 (file)
index 0000000..8da9a15
--- /dev/null
@@ -0,0 +1,38 @@
+#include "math.h"
+
+static double calc_pow(double x, double y, double precision);
+
+double pow(double x, double y)
+{
+       if(y == 0.0 || y == -0.0) {
+               return 1.0;
+       }
+       if(y == 1.0) {
+               return x;
+       }
+       if(y == -INFINITY) {
+               return fabs(x) < 1.0 ? INFINITY : 0.0;
+       }
+       if(y == INFINITY) {
+               return fabs(x) < 1.0 ? 0.0 : INFINITY;
+       }
+       return calc_pow(x, y, 1e-6);
+}
+
+static double calc_pow(double x, double y, double precision)
+{
+       if(y < 0.0) {
+               return 1.0 / calc_pow(x, -y, precision);
+       }
+       if(y >= 10.0) {
+               double p = calc_pow(x, y / 2.0, precision / 2.0);
+               return p * p;
+       }
+       if(y >= 1.0) {
+               return x * calc_pow(x, y - 1.0, precision);
+       }
+       if(precision >= 1) {
+               return __builtin_sqrt(x);
+       }
+       return __builtin_sqrt(calc_pow(x, y * 2.0, precision * 2.0));
+}
diff --git a/src/libc/math.h b/src/libc/math.h
new file mode 100644 (file)
index 0000000..6e6b2e9
--- /dev/null
@@ -0,0 +1,19 @@
+#ifndef MATH_H_
+#define MATH_H_
+
+#define INFINITY       __builtin_inff()
+#define NAN                    __builtin_nanf
+
+#define M_PI           3.141592653589793
+
+#define sin(x)         __builtin_sin(x)
+#define cos(x)         __builtin_cos(x)
+#define tan(x)         __builtin_tan(x)
+#define fabs(x)                __builtin_fabs(x)
+#define fmod(x, y)     __builtin_fmod(x, y)
+#define sqrt(x)                __builtin_sqrt(x)
+#define atan2(y, x)    __builtin_atan2(y, x)
+
+double pow(double x, double y);
+
+#endif /* MATH_H_ */
diff --git a/src/libc/rand.c b/src/libc/rand.c
new file mode 100644 (file)
index 0000000..6ea2624
--- /dev/null
@@ -0,0 +1,48 @@
+/* random number generator, based on this description of the algorithm
+ * used by the GNU libc: https://www.mathstat.dal.ca/~selinger/random
+ */
+#include <stdlib.h>
+#include <inttypes.h>
+
+static int init_done;
+static int32_t rng[34];
+static int32_t *ptr0, *ptr1;
+
+int rand(void)
+{
+       int res;
+
+       if(!init_done) {
+               srand(1);
+       }
+
+       *ptr1 += *ptr0;
+       res = (uint32_t)*ptr1 >> 1;
+       if(++ptr0 >= rng + 34) ptr0 = rng;
+       if(++ptr1 >= rng + 34) ptr1 = rng;
+
+       return res;
+}
+
+void srand(unsigned int seed)
+{
+       int i;
+
+       init_done = 1;
+       if(seed == 0) seed = 1;
+
+       rng[0] = seed;
+       for(i=1; i<31; i++) {
+               rng[i] = (16807 * rng[i - 1]) % RAND_MAX;
+               if(rng[i] < 0) rng[i] += RAND_MAX;
+       }
+       for(i=31; i<34; i++) {
+               rng[i] = rng[i - 31];
+       }
+       ptr0 = rng + 3;
+       ptr1 = rng + 31;
+
+       for(i=34; i<344; i++) {
+               rand();
+       }
+}
diff --git a/src/libc/setjmp.c b/src/libc/setjmp.c
new file mode 100644 (file)
index 0000000..5cadbde
--- /dev/null
@@ -0,0 +1,11 @@
+#include <setjmp.h>
+
+int setjmp(jmp_buf buf)
+{
+       return __builtin_setjmp(buf);
+}
+
+void longjmp(jmp_buf buf, int val)
+{
+       __builtin_longjmp(buf, 1);
+}
diff --git a/src/libc/setjmp.h b/src/libc/setjmp.h
new file mode 100644 (file)
index 0000000..6712313
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef SETJMP_H_
+#define SETJMP_H_
+
+typedef unsigned long jmp_buf[5];
+
+int setjmp(jmp_buf buf);
+void longjmp(jmp_buf buf, int val);
+
+#endif /* SETJMP_H_ */
diff --git a/src/libc/stdarg.h b/src/libc/stdarg.h
new file mode 100644 (file)
index 0000000..696aab2
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef STDARG_H_
+#define STDARG_H_
+
+typedef __builtin_va_list va_list;
+
+#define va_start(v,l) __builtin_va_start(v,l)
+#define va_end(v) __builtin_va_end(v)
+#define va_arg(v,l) __builtin_va_arg(v,l)
+
+#endif /* STDARG_H_ */
diff --git a/src/libc/stddef.h b/src/libc/stddef.h
new file mode 100644 (file)
index 0000000..b22543f
--- /dev/null
@@ -0,0 +1,15 @@
+#ifndef STDDEF_H_
+#define STDDEF_H_
+
+#include <inttypes.h>
+
+typedef int32_t ssize_t;
+typedef uint32_t size_t;
+typedef int wchar_t;
+
+typedef int32_t ptrdiff_t;
+typedef uint32_t intptr_t;
+
+#define NULL   0
+
+#endif /* STDDEF_H_ */
index 7050344..c9f87e4 100644 (file)
@@ -1,12 +1,6 @@
 #ifndef LIBC_STDINT_H_
 #define LIBC_STDINT_H_
 
-typedef char int8_t;
-typedef short int16_t;
-typedef long int32_t;
-
-typedef unsigned char uint8_t;
-typedef unsigned short uint16_t;
-typedef unsigned long uint32_t;
+#include "inttypes.h"
 
 #endif /* LIBC_STDINT_H_ */
diff --git a/src/libc/stdio.c b/src/libc/stdio.c
new file mode 100644 (file)
index 0000000..4c72114
--- /dev/null
@@ -0,0 +1,393 @@
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include "contty.h"
+#include "serial.h"
+#include "panic.h"
+
+enum {
+       OUT_DEF,
+       OUT_BUF,
+       OUT_SCR,
+       OUT_SER
+};
+
+static int intern_printf(int out, char *buf, size_t sz, const char *fmt, va_list ap);
+static int intern_scanf(const char *instr, FILE *infile, const char *fmt, va_list ap);
+static void bwrite(int out, char *buf, size_t buf_sz, char *str, int sz);
+/*static int readchar(const char *str, FILE *fp);*/
+
+int putchar(int c)
+{
+       con_putchar(c);
+       return c;
+}
+
+int puts(const char *s)
+{
+       while(*s) {
+               putchar(*s++);
+       }
+       putchar('\n');
+       return 0;
+}
+
+/* -- printf and friends -- */
+
+int printf(const char *fmt, ...)
+{
+       int res;
+       va_list ap;
+
+       va_start(ap, fmt);
+       res = intern_printf(OUT_DEF, 0, 0, fmt, ap);
+       va_end(ap);
+       return res;
+}
+
+int vprintf(const char *fmt, va_list ap)
+{
+       return intern_printf(OUT_DEF, 0, 0, fmt, ap);
+}
+
+int sprintf(char *buf, const char *fmt, ...)
+{
+       int res;
+       va_list ap;
+
+       va_start(ap, fmt);
+       res = intern_printf(OUT_BUF, buf, 0, fmt, ap);
+       va_end(ap);
+       return res;
+}
+
+int vsprintf(char *buf, const char *fmt, va_list ap)
+{
+       return intern_printf(OUT_BUF, buf, 0, fmt, ap);
+}
+
+int snprintf(char *buf, size_t sz, const char *fmt, ...)
+{
+       int res;
+       va_list ap;
+
+       va_start(ap, fmt);
+       res = intern_printf(OUT_BUF, buf, sz, fmt, ap);
+       va_end(ap);
+       return res;
+}
+
+int vsnprintf(char *buf, size_t sz, const char *fmt, va_list ap)
+{
+       return intern_printf(OUT_BUF, buf, sz, fmt, ap);
+}
+
+int fprintf(FILE *fp, const char *fmt, ...)
+{
+       int res;
+       va_list ap;
+
+       va_start(ap, fmt);
+       res = vfprintf(fp, fmt, ap);
+       va_end(ap);
+       return res;
+}
+
+int vfprintf(FILE *fp, const char *fmt, va_list ap)
+{
+       if(fp == stdout || fp == stderr) {
+               return vprintf(fmt, ap);
+       }
+
+       panic("*fprintf for anything other than stdout/stderr, not implemented yet\n");
+       return 0;
+}
+
+int ser_printf(const char *fmt, ...)
+{
+       int res;
+       va_list ap;
+
+       va_start(ap, fmt);
+       res = intern_printf(OUT_SER, 0, 0, fmt, ap);
+       va_end(ap);
+       return res;
+}
+
+int ser_vprintf(const char *fmt, va_list ap)
+{
+       return intern_printf(OUT_SER, 0, 0, fmt, ap);
+}
+
+void perror(const char *s)
+{
+       printf("%s: %s\n", s, strerror(errno));
+}
+
+int getchar(void)
+{
+       return con_getchar();
+}
+
+/* intern_printf provides all the functionality needed by all the printf
+ * variants.
+ * - buf: optional buffer onto which the formatted results are written. If null
+ *   then the output goes to the terminal through putchar calls. This is used
+ *   by the (v)sprintf variants which write to an array of char.
+ * - sz: optional maximum size of the output, 0 means unlimited. This is used
+ *   by the (v)snprintf variants to avoid buffer overflows.
+ * The rest are obvious, format string and variable argument list.
+ */
+static char *convc = "dioxXucsfeEgGpn%";
+
+#define IS_CONV(c)     strchr(convc, c)
+
+#define BUF(x) ((x) ? (x) + cnum : (x))
+#define SZ(x)  ((x) ? (x) - cnum : (x))
+
+static int intern_printf(int out, char *buf, size_t sz, const char *fmt, va_list ap)
+{
+       char conv_buf[32];
+       char *str;
+       int i, slen;
+       const char *fstart = 0;
+
+       /* state */
+       int cnum = 0;
+       int base = 10;
+       int alt = 0;
+       int fwidth = 0;
+       int padc = ' ';
+       int sign = 0;
+       int left_align = 0;
+       int hex_caps = 0;
+       int unsig = 0;
+       int num, unum;
+
+       while(*fmt) {
+               if(*fmt == '%') {
+                       fstart = fmt++;
+                       continue;
+               }
+
+               if(fstart) {
+                       if(IS_CONV(*fmt)) {
+                               switch(*fmt) {
+                               case 'X':
+                                       hex_caps = 1;
+
+                               case 'x':
+                               case 'p':
+                                       base = 16;
+
+                                       if(alt) {
+                                               bwrite(out, BUF(buf), SZ(sz), "0x", 2);
+                                               cnum += 2;
+                                       }
+
+                               case 'u':
+                                       unsig = 1;
+
+                                       if(0) {
+                               case 'o':
+                                               base = 8;
+
+                                               if(alt) {
+                                                       bwrite(out, BUF(buf), SZ(sz), "0", 1);
+                                                       cnum++;
+                                               }
+                                       }
+
+                               case 'd':
+                               case 'i':
+                                       if(unsig) {
+                                               unum = va_arg(ap, unsigned int);
+                                               utoa(unum, conv_buf, base);
+                                       } else {
+                                               num = va_arg(ap, int);
+                                               itoa(num, conv_buf, base);
+                                       }
+                                       if(hex_caps) {
+                                               for(i=0; conv_buf[i]; i++) {
+                                                       conv_buf[i] = toupper(conv_buf[i]);
+                                               }
+                                       }
+
+                                       slen = strlen(conv_buf);
+
+                                       if(left_align) {
+                                               if(!unsig && sign && num >= 0) {
+                                                       bwrite(out, BUF(buf), SZ(sz), "+", 1);
+                                                       cnum++;
+                                               }
+                                               bwrite(out, BUF(buf), SZ(sz), conv_buf, slen);
+                                               cnum += slen;
+                                               padc = ' ';
+                                       }
+                                       for(i=slen; i<fwidth; i++) {
+                                               bwrite(out, BUF(buf), SZ(sz), (char*)&padc, 1);
+                                               cnum++;
+                                       }
+                                       if(!left_align) {
+                                               if(!unsig && sign && num >= 0) {
+                                                       bwrite(out, BUF(buf), SZ(sz), "+", 1);
+                                                       cnum++;
+                                               }
+                                               bwrite(out, BUF(buf), SZ(sz), conv_buf, slen);
+                                               cnum += slen;
+                                       }
+                                       break;
+
+                               case 'c':
+                                       {
+                                               char c = va_arg(ap, int);
+                                               bwrite(out, BUF(buf), SZ(sz), &c, 1);
+                                               cnum++;
+                                       }
+                                       break;
+
+                               case 's':
+                                       str = va_arg(ap, char*);
+                                       slen = strlen(str);
+
+                                       if(left_align) {
+                                               bwrite(out, BUF(buf), SZ(sz), str, slen);
+                                               cnum += slen;
+                                               padc = ' ';
+                                       }
+                                       for(i=slen; i<fwidth; i++) {
+                                               bwrite(out, BUF(buf), SZ(sz), (char*)&padc, 1);
+                                               cnum++;
+                                       }
+                                       if(!left_align) {
+                                               bwrite(out, BUF(buf), SZ(sz), str, slen);
+                                               cnum += slen;
+                                       }
+                                       break;
+
+                               case 'n':
+                                       *va_arg(ap, int*) = cnum;
+                                       break;
+
+                               default:
+                                       break;
+                               }
+
+                               /* restore default conversion state */
+                               base = 10;
+                               alt = 0;
+                               fwidth = 0;
+                               padc = ' ';
+                               hex_caps = 0;
+
+                               fstart = 0;
+                               fmt++;
+                       } else {
+                               switch(*fmt) {
+                               case '#':
+                                       alt = 1;
+                                       break;
+
+                               case '+':
+                                       sign = 1;
+                                       break;
+
+                               case '-':
+                                       left_align = 1;
+                                       break;
+
+                               case 'l':
+                               case 'L':
+                                       break;
+
+                               case '0':
+                                       padc = '0';
+                                       break;
+
+                               default:
+                                       if(isdigit(*fmt)) {
+                                               const char *fw = fmt;
+                                               while(*fmt && isdigit(*fmt)) fmt++;
+
+                                               fwidth = atoi(fw);
+                                               continue;
+                                       }
+                               }
+                               fmt++;
+                       }
+               } else {
+                       bwrite(out, BUF(buf), SZ(sz), (char*)fmt++, 1);
+                       cnum++;
+               }
+       }
+
+       return cnum;
+}
+
+
+#if 0
+static char *sconvc = "diouxcsefg%";
+
+#define IS_SCONV(c)    strchr(sconvc, c)
+
+static int intern_scanf(const char *instr, FILE *infile, const char *fmt, va_list ap)
+{
+       return -1;      /* TODO */
+}
+#endif
+
+
+/* bwrite is called by intern_printf to transparently handle writing into a
+ * buffer or to the terminal
+ */
+static void bwrite(int out, char *buf, size_t buf_sz, char *str, int sz)
+{
+       int i;
+
+       if(out == OUT_BUF) {
+               if(buf_sz && buf_sz <= sz) sz = buf_sz;
+               buf[sz] = 0;
+               memcpy(buf, str, sz);
+       } else {
+               switch(out) {
+               case OUT_DEF:
+                       for(i=0; i<sz; i++) {
+                               putchar(*str++);
+                       }
+                       break;
+
+               case OUT_SER:
+                       for(i=0; i<sz; i++) {
+                               ser_putchar(*str++);
+                       }
+                       break;
+
+               default:
+                       /* TODO: OUT_SCR */
+                       break;
+               }
+       }
+}
+
+/*
+static int readchar(const char *str, FILE *fp)
+{
+       static const char *orig_str;
+       static const char *sptr;
+
+       if(str) {
+               if(str == orig_str) {
+                       if(!*sptr) return -1;
+                       return *sptr++;
+               } else {
+                       orig_str = sptr = str;
+                       return readchar(str, fp);
+               }
+       } else {
+               return fgetc(fp);
+       }
+
+       return -1;
+}
+*/
diff --git a/src/libc/stdio.h b/src/libc/stdio.h
new file mode 100644 (file)
index 0000000..9096886
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef STDIO_H_
+#define STDIO_H_
+
+#include <stdlib.h>
+#include <stdarg.h>
+
+typedef struct FILE FILE;
+
+#define SEEK_SET       0
+#define SEEK_CUR       1
+#define SEEK_END       2
+
+#define EOF    (-1)
+
+#define stdin  ((FILE*)0)
+#define stdout ((FILE*)1)
+#define stderr ((FILE*)2)
+
+int putchar(int c);
+int puts(const char *s);
+
+int printf(const char *fmt, ...);
+int vprintf(const char *fmt, va_list ap);
+
+int sprintf(char *buf, const char *fmt, ...);
+int vsprintf(char *buf, const char *fmt, va_list ap);
+
+int snprintf(char *buf, size_t sz, const char *fmt, ...);
+int vsnprintf(char *buf, size_t sz, const char *fmt, va_list ap);
+
+/* TODO */
+int fprintf(FILE *fp, const char *fmt, ...);
+int vfprintf(FILE *fp, const char *fmt, va_list ap);
+
+/* TODO
+int fscanf(FILE *fp, const char *fmt, ...);
+int vfscanf(FILE *fp, const char *fmt, va_list ap);
+
+int sscanf(const char *str, const char *fmt, ...);
+int vsscanf(const char *ptr, const char *fmt, va_list ap);
+*/
+
+/* printf to the serial port */
+int ser_printf(const char *fmt, ...);
+int ser_vprintf(const char *fmt, va_list ap);
+
+void perror(const char *s);
+
+int getchar(void);
+
+#endif /* STDIO_H_ */
diff --git a/src/libc/stdlib.c b/src/libc/stdlib.c
new file mode 100644 (file)
index 0000000..386cae7
--- /dev/null
@@ -0,0 +1,249 @@
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#include <assert.h>
+#include <alloca.h>
+
+int atoi(const char *str)
+{
+       return strtol(str, 0, 10);
+}
+
+long atol(const char *str)
+{
+       return strtol(str, 0, 10);
+}
+
+long strtol(const char *str, char **endp, int base)
+{
+       long acc = 0;
+       int sign = 1;
+       int valid = 0;
+       const char *start = str;
+
+       while(isspace(*str)) str++;
+
+       if(base == 0) {
+               if(str[0] == '0') {
+                       if(str[1] == 'x' || str[1] == 'X') {
+                               base = 16;
+                       } else {
+                               base = 8;
+                       }
+               } else {
+                       base = 10;
+               }
+       }
+
+       if(*str == '+') {
+               str++;
+       } else if(*str == '-') {
+               sign = -1;
+               str++;
+       }
+
+       while(*str) {
+               long val = LONG_MAX;
+               char c = tolower(*str);
+
+               if(isdigit(c)) {
+                       val = *str - '0';
+               } else if(c >= 'a' && c <= 'f') {
+                       val = 10 + c - 'a';
+               } else {
+                       break;
+               }
+               if(val >= base) {
+                       break;
+               }
+               valid = 1;
+
+               acc = acc * base + val;
+               str++;
+       }
+
+       if(endp) {
+               *endp = (char*)(valid ? str : start);
+       }
+
+       return sign > 0 ? acc : -acc;
+}
+
+void itoa(int val, char *buf, int base)
+{
+       static char rbuf[16];
+       char *ptr = rbuf;
+       int neg = 0;
+
+       if(val < 0) {
+               neg = 1;
+               val = -val;
+       }
+
+       if(val == 0) {
+               *ptr++ = '0';
+       }
+
+       while(val) {
+               int digit = val % base;
+               *ptr++ = digit < 10 ? (digit + '0') : (digit - 10 + 'a');
+               val /= base;
+       }
+
+       if(neg) {
+               *ptr++ = '-';
+       }
+
+       ptr--;
+
+       while(ptr >= rbuf) {
+               *buf++ = *ptr--;
+       }
+       *buf = 0;
+}
+
+void utoa(unsigned int val, char *buf, int base)
+{
+       static char rbuf[16];
+       char *ptr = rbuf;
+
+       if(val == 0) {
+               *ptr++ = '0';
+       }
+
+       while(val) {
+               unsigned int digit = val % base;
+               *ptr++ = digit < 10 ? (digit + '0') : (digit - 10 + 'a');
+               val /= base;
+       }
+
+       ptr--;
+
+       while(ptr >= rbuf) {
+               *buf++ = *ptr--;
+       }
+       *buf = 0;
+}
+
+double atof(const char *str)
+{
+       return strtod(str, 0);
+}
+
+
+double strtod(const char *str, char **endp)
+{
+       char *ep;
+       const char *start = str;
+       int valid = 0;
+       long ival = 0, dval = 0;
+       int ddig = 0;
+       double res;
+
+       /* integer part */
+       ival = strtol(str, &ep, 10);
+       if(ep == str && *str != '.') {
+               if(endp) *endp = (char*)str;
+               return 0.0;
+       }
+       if(ep != str) valid = 1;
+       str = *ep == '.' ? ep + 1 : ep;
+       if(!isdigit(*str)) {
+               goto done;
+       }
+       valid = 1;
+
+       dval = strtol(str, &ep, 10);
+       assert(dval >= 0);
+       ddig = ep - str;
+       str = ep;
+
+done:
+       if(*endp) {
+               *endp = (char*)(valid ? str : start);
+       }
+
+       res = (double)ival;
+       if(ddig) {
+               double d = (double)dval;
+               while(ddig-- > 0) {
+                       d /= 10.0;
+               }
+               res += d;
+       }
+       return res;
+}
+
+void abort(void)
+{
+       panic("Aborted\n");
+}
+
+#define QSORT_THRESHOLD        4
+#define ITEM(idx)      ((char*)arr + (idx) * itemsz)
+
+#define SWAP(p, q) \
+       do { \
+               int nn = itemsz; \
+               char *pp = (p); \
+               char *qq = (q); \
+               do { \
+                       char tmp = *pp; \
+                       *pp++ = *qq; \
+                       *qq++ = tmp; \
+               } while(--nn > 0); \
+       } while(0)
+
+static void ins_sort(void *arr, size_t count, size_t itemsz, int (*cmp)(const void*, const void*))
+{
+       int i;
+       char *it, *a, *b;
+
+       if(count <= 1) return;
+
+       it = (char*)arr + itemsz;
+       for(i=1; i<count; i++) {
+               a = it;
+               it += itemsz;
+               while(a > (char*)arr && cmp(a, (b = a - itemsz)) < 0) {
+                       SWAP(a, b);
+                       a -= itemsz;
+               }
+       }
+}
+
+void qsort(void *arr, size_t count, size_t itemsz, int (*cmp)(const void*, const void*))
+{
+       char *ma, *mb, *mc, *left, *right;
+       size_t sepidx, nleft, nright;
+
+       if(count <= 1) return;
+
+       if(count < QSORT_THRESHOLD) {
+               ins_sort(arr, count, itemsz, cmp);
+               return;
+       }
+
+       ma = arr;
+       mb = ITEM(count / 2);
+       mc = ITEM(count - 1);
+       if(cmp(ma, mb) < 0) SWAP(ma, mb);
+       if(cmp(mc, ma) < 0) SWAP(mc, ma);
+
+       left = ma + itemsz;
+       right = mc - itemsz;
+       for(;;) {
+               while(cmp(left, ma) < 0) left += itemsz;
+               while(cmp(ma, right) < 0) right -= itemsz;
+               if(left >= right) break;
+               SWAP(left, right);
+       }
+       SWAP(ma, right);
+       sepidx = (right - (char*)arr) / itemsz;
+       nleft = sepidx;
+       nright = count - nleft - 1;
+
+       qsort(ma, nleft, itemsz, cmp);
+       qsort(right + itemsz, nright, itemsz, cmp);
+}
diff --git a/src/libc/stdlib.h b/src/libc/stdlib.h
new file mode 100644 (file)
index 0000000..6368187
--- /dev/null
@@ -0,0 +1,29 @@
+#ifndef STDLIB_H_
+#define STDLIB_H_
+
+#include <stddef.h>
+
+#define RAND_MAX       2147483647
+
+#define abs(x) __builtin_abs(x)
+
+int atoi(const char *str);
+long atol(const char *str);
+long strtol(const char *str, char **endp, int base);
+
+void itoa(int val, char *buf, int base);
+void utoa(unsigned int val, char *buf, int base);
+
+double atof(const char *str);
+double strtod(const char *str, char **endp);
+
+void exit(int x) __attribute__((noreturn));    /* defined in startup.s */
+void abort(void);
+
+void qsort(void *arr, size_t count, size_t size, int (*cmp)(const void*, const void*));
+
+int rand(void);
+int rand_r(unsigned int *seedp);
+void srand(unsigned int seed);
+
+#endif /* STDLIB_H_ */
index 9ffb5ec..36b964e 100644 (file)
@@ -1,6 +1,8 @@
-#include "string.h"
+#include <string.h>
+#include <ctype.h>
+#include <stddef.h>
 
-void *memset(void *ptr, int val, int size)
+void *memset(void *ptr, int val, size_t size)
 {
        unsigned char *p = ptr;
        while(size--) {
@@ -9,26 +11,249 @@ void *memset(void *ptr, int val, int size)
        return ptr;
 }
 
-void *memcpy(void *dest, void *src, int size)
+void *memcpy(void *dest, const void *src, size_t n)
 {
        unsigned char *d = dest;
-       unsigned char *s = src;
-       while(size--) {
+       const unsigned char *s = src;
+       while(n--) {
                *d++ = *s++;
        }
        return dest;
 }
 
-int strcmp(const char *a, const char *b)
+void *memmove(void *dest, const void *src, size_t n)
 {
-       while(*a && *a == *b) {
-               a++;
-               b++;
+       int i;
+       char *dptr;
+       const char *sptr;
+
+       if(dest <= src) {
+               /* forward copy */
+               dptr = dest;
+               sptr = src;
+               for(i=0; i<n; i++) {
+                       *dptr++ = *sptr++;
+               }
+       } else {
+               /* backwards copy */
+               dptr = (char*)dest + n - 1;
+               sptr = (const char*)src + n - 1;
+               for(i=0; i<n; i++) {
+                       *dptr-- = *sptr--;
+               }
        }
 
-       if(!*a && !*b) return 0;
+       return dest;
+}
+
+int memcmp(void *aptr, void *bptr, size_t n)
+{
+       int i, startoffs, diff;
+       uint32_t *a32, *b32;
+       unsigned char *a = aptr;
+       unsigned char *b = bptr;
+
+       a32 = (uint32_t*)((intptr_t)(a + 3) & 0xfffffffc);
+       b32 = (uint32_t*)((intptr_t)(b + 3) & 0xfffffffc);
+
+       /* if both are aligned the same way... */
+       if((startoffs = (unsigned char*)a32 - a) == (unsigned char*)b32 - b) {
+               /* catch-up to the 32bit alignment */
+               for(i=0; i<startoffs; i++) {
+                       if((diff = *a++ - *b++) != 0 || --n <= 0) {
+                               return diff;
+                       }
+               }
+
+               /* compare 32bit at once */
+               while(n >= 4) {
+                       if(*a32 != *b32) break;
+                       a32++;
+                       b32++;
+                       n -= 4;
+               }
+
+               /* update byte pointers to contine with the tail */
+               a = (unsigned char*)a32;
+               b = (unsigned char*)b32;
+       }
+
+       /* we're here both for the tail-end of same-alignment buffers, or for the
+        * whole length of mis-aligned buffers.
+        */
+       while(n-- > 0) {
+               if((diff = *a++ - *b++) != 0) {
+                       return diff;
+               }
+       }
+       return 0;
+}
+
+size_t strlen(const char *s)
+{
+       size_t len = 0;
+       while(*s++) len++;
+       return len;
+}
+
+char *strchr(const char *s, int c)
+{
+       while(*s) {
+               if(*s == c) {
+                       return (char*)s;
+               }
+               s++;
+       }
+       return 0;
+}
+
+char *strrchr(const char *s, int c)
+{
+       const char *ptr = s;
+
+       /* find the end */
+       while(*ptr) ptr++;
+
+       /* go back checking for c */
+       while(--ptr >= s) {
+               if(*ptr == c) {
+                       return (char*)ptr;
+               }
+       }
+       return 0;
+}
+
+char *strstr(const char *str, const char *substr)
+{
+       while(*str) {
+               const char *s1 = str;
+               const char *s2 = substr;
+
+               while(*s1 && *s1 == *s2) {
+                       s1++;
+                       s2++;
+               }
+               if(!*s2) {
+                       return (char*)str;
+               }
+               str++;
+       }
+       return 0;
+}
+
+char *strcasestr(const char *str, const char *substr)
+{
+       while(*str) {
+               const char *s1 = str;
+               const char *s2 = substr;
+
+               while(*s1 && tolower(*s1) == tolower(*s2)) {
+                       s1++;
+                       s2++;
+               }
+               if(!*s2) {
+                       return (char*)str;
+               }
+               str++;
+       }
+       return 0;
+}
 
-       if(!*a) return -1;
-       if(!*b) return 1;
-       return *a - *b > 0 ? 1 : -1;
+int strcmp(const char *s1, const char *s2)
+{
+       while(*s1 && *s1 == *s2) {
+               s1++;
+               s2++;
+       }
+       return *s1 - *s2;
+}
+
+int strcasecmp(const char *s1, const char *s2)
+{
+       while(*s1 && tolower(*s1) == tolower(*s2)) {
+               s1++;
+               s2++;
+       }
+       return tolower(*s1) - tolower(*s2);
+}
+
+int strncmp(const char *s1, const char *s2, int n)
+{
+       if(n <= 0) return 0;
+
+       while(n-- > 0 && *s1 && *s2 && *s1 == *s2) {
+               s1++;
+               s2++;
+       }
+
+       if(n <= 0) return 0;
+       return *s1 - *s2;
+}
+
+int strncasecmp(const char *s1, const char *s2, int n)
+{
+       if(n <= 0) return 0;
+
+       while(n-- > 0 && *s1 && *s2 && tolower(*s1) == tolower(*s2)) {
+               s1++;
+               s2++;
+       }
+
+       if(n <= 0) return 0;
+       return tolower(*s1) - tolower(*s2);
+}
+
+char *strcpy(char *dest, const char *src)
+{
+       char *dptr = dest;
+       while((*dptr++ = *src++));
+       return dest;
+}
+
+char *strcat(char *dest, const char *src)
+{
+       strcpy(dest + strlen(dest), src);
+       return dest;
+}
+
+char *strncpy(char *dest, const char *src, int n)
+{
+       char *dptr = dest;
+       while(n-- > 0 && (*dptr++ = *src++));
+       return dest;
+}
+
+
+static const char *errstr[] = {
+       "Success",
+       "Foo",
+       "Interrupted",
+       "Invalid",
+       "Child",
+       "Timeout",
+       "Out of memory",
+       "I/O error",
+       "Not found",
+       "Name too long",
+       "No space left on device",
+       "Permission denied",
+       "Not a directory",
+       "Is a directory",
+       "Does not exist",
+       0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,
+       0,0,0,0,0,0,0,
+       "Bug"
+};
+
+char *strerror(int err)
+{
+       if(err < 0 || err > sizeof errstr / sizeof *errstr || !errstr[err]) {
+               return "Unknown";
+       }
+       return (char*)errstr[err];
 }
index 4a1812f..09f7020 100644 (file)
@@ -1,9 +1,34 @@
-#ifndef LIBC_STRING_H_
-#define LIBC_STRING_H_
+#ifndef STRING_H_
+#define STRING_H_
 
-void *memset(void *ptr, int val, int size);
-void *memcpy(void *dest, void *src, int size);
+#include <stdlib.h>
 
-int strcmp(const char *a, const char *b);
+void *memset(void *s, int c, size_t n);
 
-#endif /* LIBC_STRING_H_ */
+void *memcpy(void *dest, const void *src, size_t n);
+void *memmove(void *dest, const void *src, size_t n);
+
+int memcmp(void *aptr, void *bptr, size_t n);
+
+size_t strlen(const char *s);
+
+char *strchr(const char *s, int c);
+char *strrchr(const char *s, int c);
+
+char *strstr(const char *str, const char *substr);
+char *strcasestr(const char *str, const char *substr);
+
+int strcmp(const char *s1, const char *s2);
+int strcasecmp(const char *s1, const char *s2);
+
+int strncmp(const char *s1, const char *s2, int n);
+int strncasecmp(const char *s1, const char *s2, int n);
+
+char *strcpy(char *dest, const char *src);
+char *strcat(char *dest, const char *src);
+
+char *strncpy(char *dest, const char *src, int n);
+
+char *strerror(int err);
+
+#endif /* STRING_H_ */
index 0c8bdf5..db2ab86 100644 (file)
@@ -1,14 +1,16 @@
 #include "config.h"
 
+#include <stdio.h>
 #include <string.h>
 #include <stdint.h>
 #include <ctype.h>
 #include "asm.h"
+#include "rpi.h"
+#include "contty.h"
 #include "serial.h"
 #include "video.h"
 
 void dbgled(int x);
-void exit(int x);
 
 static void cmdrun(char *cmd);
 
@@ -18,14 +20,17 @@ int main(void)
        static char cmdbuf[256];
        static int cmdend;
 
+       rpi_init();
        init_serial(115200);
-       ser_printstr("Starting rpikern\n");
+       con_init();
+
+       printf("Detected raspberry pi %d, I/O base: %x\n", rpi_model, rpi_iobase);
 
        video_init();
 
-       ser_printstr("Going interactive\n");
+       printf("Going interactive\n");
        for(;;) {
-               int c = ser_getchar();
+               int c = getchar();
 
                switch(c) {
                case '\r':
@@ -41,7 +46,7 @@ int main(void)
 
                case -1:
                        lastnl = 0;
-                       ser_printstr("error!\n");
+                       printf("error!\n");
                        break;
 
                default:
@@ -56,12 +61,6 @@ int main(void)
        return 0;
 }
 
-void panic(void)
-{
-       ser_printstr("PANIC!\n");
-       exit(0);
-}
-
 static void cmdrun(char *cmd)
 {
        char *ptr, *args;
@@ -73,12 +72,10 @@ static void cmdrun(char *cmd)
        args = ptr + 1;
 
        if(strcmp(cmd, "help") == 0) {
-               ser_printstr("help not implemented yet\n");
+               printf("help not implemented yet\n");
        } else if(strcmp(cmd, "ver") == 0) {
-               ser_printstr("rpikern version 0.0\n");
+               printf("rpikern version 0.0\n");
        } else {
-               ser_printstr("Unknown command: ");
-               ser_printstr(cmd);
-               ser_printstr("\n");
+               printf("Unknown command: %s\n", cmd);
        }
 }
diff --git a/src/panic.c b/src/panic.c
new file mode 100644 (file)
index 0000000..34cda75
--- /dev/null
@@ -0,0 +1,12 @@
+#include <stdio.h>
+#include "asm.h"
+
+void panic(const char *fmt, ...)
+{
+       disable_intr();
+
+       printf("~~~~~ rpikern panic ~~~~~\n");
+       printf("TODO: reg dump\n");
+
+       for(;;) halt_cpu();
+}
diff --git a/src/panic.h b/src/panic.h
new file mode 100644 (file)
index 0000000..1b29a63
--- /dev/null
@@ -0,0 +1,6 @@
+#ifndef PANIC_H_
+#define PANIC_H_
+
+void panic(const char *fmt, ...) __attribute__((noreturn));
+
+#endif /* PANIC_H_ */
diff --git a/src/rpi.c b/src/rpi.c
new file mode 100644 (file)
index 0000000..ba39596
--- /dev/null
+++ b/src/rpi.c
@@ -0,0 +1,111 @@
+#include "rpi.h"
+#include "asm.h"
+
+#define IOREG(offs)            (*(volatile uint32_t*)(rpi_iobase | offs))
+
+/* System timer */
+#define STM_CTL_REG            IOREG(0x3000)
+#define STM_STAT_REG   STM_CTL_REG
+#define STM_LCNT_REG   IOREG(0x3004)
+#define STM_HCNT_REG   IOREG(0x3008)
+#define STM_CMP0_REG   IOREG(0x300c)
+#define STM_CMP1_REG   IOREG(0x3010)
+#define STM_CMP2_REG   IOREG(0x3014)
+#define STM_CMP3_REG   IOREG(0x3018)
+
+#define STMCTL_M0              1
+#define STMCTL_M1              2
+#define STMCTL_M2              4
+#define STMCTL_M3              8
+
+/* TIMER */
+#define TM_LOAD_REG            IOREG(0xb400)
+#define TM_VALUE_REG   IOREG(0xb404)
+#define TM_CTL_REG             IOREG(0xb408)
+#define TM_ICLR_REG            IOREG(0xb40c)
+#define TM_IRAW_REG            IOREG(0xb410)
+#define TM_IMSK_REG            IOREG(0xb414)
+#define TM_RELOAD_REG  IOREG(0xb418)
+#define TM_PREDIV_REG  IOREG(0xb41c)
+#define TM_COUNT_REG   IOREG(0xb420)
+
+#define TMCTL_23BIT            0x000002
+#define TMCTL_DIV16            0x000004
+#define TMCTL_DIV256   0x000008
+#define TMCTL_DIV1             0x00000c
+#define TMCTL_IEN              0x000020
+#define TMCTL_EN               0x000080
+#define TMCTL_DBGHALT  0x000100
+#define TMCTL_CNTEN            0x000200
+
+#define TMCTL_PRESCALER(x)     (((uint32_t)(x) & 0xff) << 16)
+
+
+/* MAILBOX */
+#define MBOX_READ_REG  IOREG(0xb880)
+#define MBOX_POLL_REG  IOREG(0xb890)
+#define MBOX_SENDER_REG        IOREG(0xb894)
+#define MBOX_STATUS_REG        IOREG(0xb898)
+#define MBOX_CFG_REG   IOREG(0xb89c)
+#define MBOX_WRITE_REG IOREG(0xb8a0)
+
+/* the full bit is set when there's no space to append messages */
+#define MBOX_STAT_FULL 0x80000000
+/* the empty bit is set when there are no pending messages to be read */
+#define MBOX_STAT_EMPTY        0x40000000
+
+static int detect(void);
+
+int rpi_model;
+uint32_t rpi_iobase;
+uint32_t rpi_memsize, rpi_vc_memsize;
+
+void rpi_init(void)
+{
+       if((rpi_model = detect()) == -1) {
+               for(;;) halt_cpu();
+       }
+
+       /* TODO */
+}
+
+static int detect(void)
+{
+       int i, j;
+       uint32_t tm0, tm1;
+       static uint32_t base[] = {0x20000000, 0x3f000000, 0xfe000000};
+
+       for(i=0; i<3; i++) {
+               rpi_iobase = base[i];
+               tm0 = STM_LCNT_REG;
+               for(j=0; j<256; j++) {
+                       tm1 = STM_LCNT_REG;
+               }
+               if(tm0 != tm1) {
+                       return i + 1;
+               }
+       }
+       return -1;
+}
+
+
+void rpi_mbox_send(int chan, uint32_t msg)
+{
+       while(MBOX_STATUS_REG & MBOX_STAT_FULL);
+       MBOX_WRITE_REG = (msg & 0xfffffff0) | chan;
+}
+
+uint32_t rpi_mbox_recv(int chan)
+{
+       uint32_t msg;
+       do {
+               while(MBOX_STATUS_REG & MBOX_STAT_EMPTY);
+               msg = MBOX_READ_REG;
+       } while((msg & 0xf) != chan);
+       return msg & 0xfffffff0;
+}
+
+int rpi_mbox_pending(int chan)
+{
+       return (MBOX_STATUS_REG & MBOX_STAT_EMPTY) == 0;
+}
diff --git a/src/rpi.h b/src/rpi.h
new file mode 100644 (file)
index 0000000..36f8ac4
--- /dev/null
+++ b/src/rpi.h
@@ -0,0 +1,50 @@
+#ifndef RPI_H_
+#define RPI_H_
+
+#include <stdint.h>
+
+#define RPI_MBOX_FRAMEBUF      1
+#define RPI_MBOX_PROP          8
+
+#define RPI_TAG_GETMODEL       0x010001
+#define RPI_TAG_GETRAM         0x010005
+#define RPI_TAG_GETVRAM                0x010006
+#define RPI_TAG_SETCLOCK       0x038002
+
+#define RPI_TAG_ALLOCFB                0x040001
+#define RPI_TAG_RELEASEFB      0x048001
+#define RPI_TAG_SETFBPHYS      0x048003
+#define RPI_TAG_SETFBVIRT      0x048004
+#define RPI_TAG_SETFBDEPTH     0x048005
+
+struct rpi_tag_getmodel {
+       uint32_t id, size, res;
+       uint32_t model;
+};
+
+struct rpi_tag_getram {
+       uint32_t id, size, res;
+       uint32_t membase, memsize;
+};
+
+struct rpi_tag_setclock {
+       uint32_t id, size, res;
+       uint32_t clock_id, rate, skip_turbo;
+};
+
+struct rpi_prop_header {
+       uint32_t size;
+       uint32_t res;
+};
+
+extern int rpi_model;
+extern uint32_t rpi_iobase;
+extern uint32_t rpi_memsize, rpi_vc_memsize;
+
+void rpi_init(void);
+
+void rpi_mbox_send(int chan, uint32_t msg);
+uint32_t rpi_mbox_recv(int chan);
+int rpi_mbox_pending(int chan);
+
+#endif /* RPI_H_ */
index 9d1b2be..1bc13fe 100644 (file)
@@ -36,6 +36,8 @@ void init_serial(int baud)
 
 void ser_putchar(int c)
 {
+       if(c == '\n') ser_putchar('\r');
+
        while(REG_FR & FR_TXFF);
        REG_DR = c & 0xff;
 }
@@ -49,9 +51,6 @@ int ser_getchar(void)
 void ser_printstr(const char *s)
 {
        while(*s) {
-               if(*s == '\n') {
-                       ser_putchar('\r');
-               }
                ser_putchar(*s++);
        }
 }
diff --git a/src/timer.h b/src/timer.h
deleted file mode 100644 (file)
index 065fdcf..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-#ifndef TIMER_H_
-#define TIMER_H_
-
-#include "config.h"
-
-#define TM_BASE        (IO_BASE | 0xb000)
-
-#define TM_REG(x)      (*(volatile uint32_t*)(TIMER_BASE | (x)))
-#define TM_LOAD                TM_REG(0x400)
-#define TM_VALUE       TM_REG(0x404)
-#define TM_CTL         TM_REG(0x408)
-#define TM_ICLR                TM_REG(0x40c)
-#define TM_IRAW                TM_REG(0x410)
-#define TM_IMSK                TM_REG(0x414)
-#define TM_RELOAD      TM_REG(0x418)
-#define TM_PREDIV      TM_REG(0x41c)
-#define TM_COUNT       TM_REG(0x420)
-
-#define TMCTL_23BIT            0x000002
-#define TMCTL_DIV16            0x000004
-#define TMCTL_DIV256   0x000008
-#define TMCTL_DIV1             0x00000c
-#define TMCTL_IEN              0x000020
-#define TMCTL_EN               0x000080
-#define TMCTL_DBGHALT  0x000100
-#define TMCTL_CNTEN            0x000200
-
-#define TMCTL_PRESCALER(x)     (((uint32_t)(x) & 0xff) << 16)
-
-#endif /* TIMER_H_ */
index 33b740f..9b552dc 100644 (file)
@@ -1,68 +1,18 @@
 #include "config.h"
+#include <stdio.h>
 #include <string.h>
 #include <stdint.h>
+#include "rpi.h"
 #include "video.h"
-#include "serial.h"
 #include "mem.h"
 
-#define MBOX_READ_REG  (*(volatile uint32_t*)(IO_BASE | 0xb880))
-#define MBOX_POLL_REG  (*(volatile uint32_t*)(IO_BASE | 0xb890))
-#define MBOX_SENDER_REG        (*(volatile uint32_t*)(IO_BASE | 0xb894))
-#define MBOX_STATUS_REG        (*(volatile uint32_t*)(IO_BASE | 0xb898))
-#define MBOX_CFG_REG   (*(volatile uint32_t*)(IO_BASE | 0xb89c))
-#define MBOX_WRITE_REG (*(volatile uint32_t*)(IO_BASE | 0xb8a0))
-
-#define MBOX_STAT_WRBUSY       0x80000000
-#define MBOX_STAT_RDBUSY       0x40000000
-
-struct vc_fbinfo {
-       uint32_t phys_width, phys_height;
-       uint32_t virt_width, virt_height;
-       uint32_t pitch;                 /* filled by videocore */
-       uint32_t depth;
-       uint32_t x, y;
-       void *addr;             /* filled by videocore */
-       uint32_t size;  /* filled by videocore */
-};
-
-void mbox_write(int mbox, uint32_t msg);
-uint32_t mbox_read(int mbox);
-
-static struct vc_fbinfo fbinf __attribute__((aligned(16)));
+/* needs to by 16-byte aligned, because the address we send over the mailbox
+ * interface, will have its 4 least significant bits masked off and taken over
+ * by the mailbox id
+ */
+static uint8_t propbuf[64] __attribute__((aligned(16)));
 
 int video_init(void)
 {
-       memset(&fbinf, 0, sizeof fbinf);
-       fbinf.phys_width = fbinf.virt_width = 1024;
-       fbinf.phys_height = fbinf.virt_height = 600;
-       fbinf.depth = 32;
-       fbinf.x = fbinf.y = 0;
-
-       mbox_write(1, MEM_BUS_COHERENT(&fbinf));
-       if(mbox_read(1) != 0) {
-               ser_printstr("Failed to initialize display\n");
-               return -1;
-       }
-
-       ser_printstr("Video init successful\n");
-       memset(fbinf.addr, 0, fbinf.size);
        return 0;
 }
-
-void mbox_write(int mbox, uint32_t msg)
-{
-       while(MBOX_STATUS_REG & MBOX_STAT_WRBUSY);
-       MBOX_WRITE_REG = (msg & 0xfffffff0) | mbox;
-}
-
-uint32_t mbox_read(int mbox)
-{
-       uint32_t msg;
-
-       do {
-               while(MBOX_STATUS_REG & MBOX_STAT_RDBUSY);
-               msg = MBOX_READ_REG;
-       } while((msg & 0xf) != mbox);
-
-       return msg & 0xfffffff0;
-}