xref: /inferno-os/os/boot/mpc/uartboot.c (revision d0e1d143ef6f03c75c008c7ec648859dd260cbab)
1 #include "boot.h"
2 
3 /*
4  * this doesn't yet use the crc
5  */
6 
7 typedef struct Uboot Uboot;
8 struct Uboot {
9 	Queue*	iq;
10 	Block*	partial;
11 	ulong	csum;
12 	long	bno;
13 	uchar	buf[64];
14 	int	nleft;
15 	int	ntimeout;
16 };
17 
18 static	Uboot	uboot;
19 ulong	crc32(void *buf, int n, ulong crc);
20 
21 static void
22 uartbrecv(uchar *p, int n)
23 {
24 	Uboot *ub;
25 	Block *b;
26 
27 	ub = &uboot;
28 	if(n > 0 && ub->iq != nil){
29 		b = iallocb(n);
30 		memmove(b->wp, p, n);
31 		b->wp += n;
32 		qbwrite(ub->iq, b);
33 	}
34 }
35 
36 int
37 uartinit(void)
38 {
39 	return 1<<0;
40 }
41 
42 Partition*
43 setuartpart(int, char *s)
44 {
45 	static Partition pp[1];
46 
47 	if(strcmp(s, "boot") != 0 && strcmp(s, "disk") != 0)
48 		return 0;
49 	pp[0].start = 0;
50 	pp[0].end = 2*1024*1024;
51 	strcpy(pp[0].name, "boot");
52 	return pp;
53 }
54 
55 long
56 uartseek(int, long)
57 {
58 	/* start the boot */
59 	if(uboot.iq == nil)
60 		uboot.iq = qopen(64*1024, 0, 0, 0);
61 	if(uboot.partial){
62 		freeb(uboot.partial);
63 		uboot.partial = 0;
64 	}
65 	print("uart: start transmission\n");
66 	uartsetboot(uartbrecv);
67 	uboot.csum = ~0;
68 	uboot.bno = 0;
69 	uboot.nleft = 0;
70 	uboot.ntimeout = 0;
71 	return 0;
72 }
73 
74 static long
75 uartreadn(void *buf, int nb)
76 {
77 	ulong start;
78 	Uboot *ub;
79 	int l;
80 	Block *b;
81 	uchar *p;
82 
83 	p = buf;
84 	ub = &uboot;
85 	start = m->ticks;
86 	while(nb > 0){
87 		b = ub->partial;
88 		ub->partial = nil;
89 		if(b == nil){
90 			ub->ntimeout = 0;
91 			while((b = qget(ub->iq)) == 0){
92 				if(TK2MS(m->ticks - start) >= 15*1000){
93 					if(++ub->ntimeout >= 3){
94 						print("uart: timeout\n");
95 						return 0;
96 					}
97 					uartputs("n", 1);
98 				}
99 			}
100 		}
101 		l = BLEN(b);
102 		if(l > nb)
103 			l = nb;
104 		memmove(p, b->rp, l);
105 		b->rp += l;
106 		if(b->rp >= b->wp)
107 			freeb(b);
108 		else
109 			ub->partial = b;
110 		nb -= l;
111 		p += l;
112 	}
113 	return p-(uchar*)buf;
114 }
115 
116 long
117 uartread(int, void *buf, long n)
118 {
119 	uchar *p;
120 	int l;
121 	static uchar lbuf[64];
122 
123 	p = buf;
124 	if((l = uboot.nleft) > 0){
125 		if(l > n)
126 			l = n;
127 		uboot.nleft -= l;
128 		memmove(p, uboot.buf, l);
129 		p += l;
130 		n -= l;
131 	}
132 	while(n > 0){
133 		l = uartreadn(lbuf, sizeof(lbuf));
134 		if(l < sizeof(lbuf))
135 			return 0;
136 		if(l > n){
137 			uboot.nleft = l-n;
138 			memmove(uboot.buf, lbuf+n, uboot.nleft);
139 			l = n;
140 		}
141 		memmove(p, lbuf, l);
142 		n -= l;
143 		p += l;
144 		uboot.bno++;
145 		uartputs("y", 1);
146 	}
147 	return p-(uchar*)buf;
148 }
149 
150 /*
151  * from Rob Warnock
152  */
153 static	ulong	crc32tab[256];	/* initialised on first call to crc32 */
154 
155 enum {
156 	CRC32POLY = 0x04c11db7     /* AUTODIN II, Ethernet, & FDDI */
157 };
158 
159 /*
160  * Build auxiliary table for parallel byte-at-a-time CRC-32.
161  */
162 static void
163 initcrc32(void)
164 {
165 	int i, j;
166 	ulong c;
167 
168 	for(i = 0; i < 256; i++) {
169 		for(c = i << 24, j = 8; j > 0; j--)
170 			if(c & (1<<31))
171 				c = (c<<1) ^ CRC32POLY;
172 			else
173 				c <<= 1;
174 		crc32tab[i] = c;
175 	}
176 }
177 
178 ulong
179 crc32(void *buf, int n, ulong crc)
180 {
181 	uchar *p;
182 
183 	if(crc32tab[1] == 0)
184 		initcrc32();
185 	crc = ~crc;
186 	for(p = buf; --n >= 0;)
187 		crc = (crc << 8) ^ crc32tab[(crc >> 24) ^ *p++];
188 	return ~crc;
189 }
190