summaryrefslogtreecommitdiff
path: root/os/boot/rpcg/uartboot.c
diff options
context:
space:
mode:
authorCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
committerCharles.Forsyth <devnull@localhost>2006-12-22 21:39:35 +0000
commit74a4d8c26dd3c1e9febcb717cfd6cb6512991a7a (patch)
treec6e220ba61db3a6ea4052e6841296d829654e664 /os/boot/rpcg/uartboot.c
parent46439007cf417cbd9ac8049bb4122c890097a0fa (diff)
20060303
Diffstat (limited to 'os/boot/rpcg/uartboot.c')
-rw-r--r--os/boot/rpcg/uartboot.c189
1 files changed, 189 insertions, 0 deletions
diff --git a/os/boot/rpcg/uartboot.c b/os/boot/rpcg/uartboot.c
new file mode 100644
index 00000000..0b11b5d5
--- /dev/null
+++ b/os/boot/rpcg/uartboot.c
@@ -0,0 +1,189 @@
+#include "boot.h"
+
+/*
+ * this doesn't yet use the crc
+ */
+
+typedef struct Uboot Uboot;
+struct Uboot {
+ Queue* iq;
+ Block* partial;
+ ulong csum;
+ long bno;
+ uchar buf[64];
+ int nleft;
+ int ntimeout;
+};
+
+static Uboot uboot;
+ulong crc32(void *buf, int n, ulong crc);
+
+static void
+uartbrecv(uchar *p, int n)
+{
+ Uboot *ub;
+ Block *b;
+
+ ub = &uboot;
+ if(n > 0 && ub->iq != nil){
+ b = iallocb(n);
+ memmove(b->wp, p, n);
+ b->wp += n;
+ qbwrite(ub->iq, b);
+ }
+}
+
+int
+uartinit(void)
+{
+ return 1<<0;
+}
+
+Partition*
+setuartpart(int, char *s)
+{
+ static Partition pp[1];
+
+ if(strcmp(s, "boot") != 0 && strcmp(s, "disk") != 0)
+ return 0;
+ pp[0].start = 0;
+ pp[0].end = 2*1024*1024;
+ strcpy(pp[0].name, "boot");
+ return pp;
+}
+
+long
+uartseek(int, long)
+{
+ /* start the boot */
+ if(uboot.iq == nil)
+ uboot.iq = qopen(64*1024, 0, 0, 0);
+ if(uboot.partial){
+ freeb(uboot.partial);
+ uboot.partial = 0;
+ }
+ print("uart: start transmission\n");
+ uartsetboot(uartbrecv);
+ uboot.csum = ~0;
+ uboot.bno = 0;
+ uboot.nleft = 0;
+ uboot.ntimeout = 0;
+ return 0;
+}
+
+static long
+uartreadn(void *buf, int nb)
+{
+ ulong start;
+ Uboot *ub;
+ int l;
+ Block *b;
+ uchar *p;
+
+ p = buf;
+ ub = &uboot;
+ start = m->ticks;
+ while(nb > 0){
+ b = ub->partial;
+ ub->partial = nil;
+ if(b == nil){
+ ub->ntimeout = 0;
+ while((b = qget(ub->iq)) == 0){
+ if(TK2MS(m->ticks - start) >= 15*1000){
+ if(++ub->ntimeout >= 3){
+ print("uart: timeout\n");
+ return 0;
+ }
+ uartputs("n", 1);
+ }
+ }
+ }
+ l = BLEN(b);
+ if(l > nb)
+ l = nb;
+ memmove(p, b->rp, l);
+ b->rp += l;
+ if(b->rp >= b->wp)
+ freeb(b);
+ else
+ ub->partial = b;
+ nb -= l;
+ p += l;
+ }
+ return p-(uchar*)buf;
+}
+
+long
+uartread(int, void *buf, long n)
+{
+ uchar *p;
+ int l;
+ static uchar lbuf[64];
+
+ p = buf;
+ if((l = uboot.nleft) > 0){
+ if(l > n)
+ l = n;
+ uboot.nleft -= l;
+ memmove(p, uboot.buf, l);
+ p += l;
+ n -= l;
+ }
+ while(n > 0){
+ l = uartreadn(lbuf, sizeof(lbuf));
+ if(l < sizeof(lbuf))
+ return 0;
+ if(l > n){
+ uboot.nleft = l-n;
+ memmove(uboot.buf, lbuf+n, uboot.nleft);
+ l = n;
+ }
+ memmove(p, lbuf, l);
+ n -= l;
+ p += l;
+ uboot.bno++;
+ uartputs("y", 1);
+ }
+ return p-(uchar*)buf;
+}
+
+/*
+ * from Rob Warnock
+ */
+static ulong crc32tab[256]; /* initialised on first call to crc32 */
+
+enum {
+ CRC32POLY = 0x04c11db7 /* AUTODIN II, Ethernet, & FDDI */
+};
+
+/*
+ * Build auxiliary table for parallel byte-at-a-time CRC-32.
+ */
+static void
+initcrc32(void)
+{
+ int i, j;
+ ulong c;
+
+ for(i = 0; i < 256; i++) {
+ for(c = i << 24, j = 8; j > 0; j--)
+ if(c & (1<<31))
+ c = (c<<1) ^ CRC32POLY;
+ else
+ c <<= 1;
+ crc32tab[i] = c;
+ }
+}
+
+ulong
+crc32(void *buf, int n, ulong crc)
+{
+ uchar *p;
+
+ if(crc32tab[1] == 0)
+ initcrc32();
+ crc = ~crc;
+ for(p = buf; --n >= 0;)
+ crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
+ return ~crc;
+}