1: 2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
14:
15: 16: 17: 18: 19:
20:
21: #include "cmdsvc.h"
22:
23: LOCAL UW s_addr;
24: LOCAL UW e_addr;
25: LOCAL UW offset;
26: LOCAL UW loaddr;
27: LOCAL UW hiaddr;
28: LOCAL W blkno;
29: LOCAL W blkptr;
30: #define XBLK_SZ 1024
31: #define BLK_SZ 128
32: #define blkbuf wrkBuf
33: LOCAL W blksz;
34:
35: LOCAL FUNCP readFn;
36:
37: #define inputByte(tmo) getSIO(tmo)
38: #define outputByte(c) putSIO(c)
39:
40:
41: #define SOH (0x01)
42: #define STX (0x02)
43: #define EOT (0x04)
44: #define ACK (0x06)
45: #define NAK (0x15)
46: #define CAN (0x18)
47: #define CTLC ('C' - '@')
48: #define CTLZ ('Z' - '@')
49:
50: 51: 52: 53: 54: 55: 56: 57: 58:
59: #define IDLE_TMO ( 1 * 1000)
60: #define RECV_TMO ( 1 * 1000)
61: #define SOH_TMO (10 * 1000)
62: #define SOH1_TMO ( 3 * 1000)
63: #define MAX_RETRY 10
64:
65: 66: 67:
68: LOCAL void purgeInput(void)
69: {
70: while (inputByte(IDLE_TMO) >= 0);
71: }
72: 73: 74:
75: LOCAL W textRead(void)
76: {
77: W c;
78:
79: while ((c = inputByte(0)) < 0);
80: return (c == CTLC || c == CAN) ? E_CANCEL : c;
81: }
82: 83: 84:
85: LOCAL W xmodemRead(void)
86: {
87: W i, c, ctlch;
88: UB cksum;
89:
90: if (blkptr < blksz) return blkbuf[blkptr++];
91:
92: c = 0;
93: ctlch = ACK;
94: if (blkno++ == 0) {
95:
96: outputByte(NAK);
97: c = inputByte(SOH1_TMO);
98: ctlch = -1;
99: }
100:
101: for (;;) {
102:
103: for (i = 0;;) {
104: if (ctlch >= 0) {
105:
106: outputByte(ctlch);
107:
108:
109: c = inputByte(SOH_TMO);
110: }
111: ctlch = NAK;
112: if (c == SOH) {blksz = BLK_SZ; break;}
113: if (c == STX) {blksz = XBLK_SZ; break;}
114: if (c == CAN || c == CTLC) {
115:
116: c = inputByte(IDLE_TMO);
117: if (c < 0 || c == CAN || c == CTLC)
118: return E_CANCEL;
119: } else if (c == EOT) {
120: outputByte(ACK);
121: return E_END;
122: }
123: purgeInput();
124: if (++i >= MAX_RETRY) return E_XMODEM;
125: }
126:
127:
128: if ((i = inputByte(RECV_TMO)) < 0) continue;
129: if ((c = inputByte(RECV_TMO)) < 0) continue;
130: if (i + c != 0xff) continue;
131:
132: if (i != (blkno & 0xff)) {
133: if (i != ((blkno - 1) & 0xff)) return E_XMODEM;
134:
135: ctlch = ACK;
136: }
137:
138:
139: for (cksum = 0, i = 0; i < blksz; i++) {
140: if ((c = inputByte(RECV_TMO)) < 0) break;
141: cksum += (blkbuf[i] = c);
142: }
143: if (c < 0) continue;
144:
145:
146: if (inputByte(RECV_TMO) == cksum && ctlch != ACK) break;
147: }
148: blkptr = 0;
149: return blkbuf[blkptr++];
150: }
151: 152: 153:
154: LOCAL void xmodemEnd(W er)
155: {
156:
157: while (er >= 0) er = xmodemRead();
158:
159: if (er != E_END && er != E_CANCEL) {
160: purgeInput();
161: outputByte(CAN);
162: outputByte(CAN);
163: outputByte(CAN);
164: }
165: }
166: 167: 168:
169: LOCAL W loadImage(void)
170: {
171: W i, c;
172: UB buf[512];
173:
174: for (i = 0;;) {
175: if ((c = (*readFn)()) >= 0) buf[i++] = c;
176: if (i < sizeof(buf) && c >= 0) continue;
177: if (i > 0) {
178: if (e_addr < loaddr ||
179: e_addr - 1 > hiaddr - i) return E_RANGE;
180: if (writeMem(e_addr, buf, i, 1) != i) return E_MACV;
181: e_addr += i;
182: i = 0;
183: }
184: if (c < 0) return c;
185: }
186: }
187: 188: 189:
190: LOCAL W readHex(void)
191: {
192: W c;
193:
194: if ((c = (*readFn)()) < 0) return c;
195: if (c >= '0' && c <= '9') return c - '0';
196: if (c >= 'A' && c <= 'F') return c - 'A' + 10;
197: if (c >= 'a' && c <= 'f') return c - 'a' + 10;
198: return E_LOAD;
199: }
200: 201: 202:
203: LOCAL W loadSform(void)
204: {
205: W i, c, bcnt, v, v1, dcnt, rtype;
206: UW addr, a_addr;
207: UB cksum, buf[512];
208:
209: a_addr = s_addr;
210: s_addr = 0xffffffff;
211: e_addr = 0;
212:
213: for (;;) {
214: if ((c = (*readFn)()) < 0) return c;
215:
216: if (c != 'S') {
217: if (c == CTLZ) break;
218: continue;
219: }
220:
221: if ((c = (*readFn)()) < 0) return c;
222: switch(c) {
223: case '0':
224: rtype = 0; break;
225: case '1':
226: case '2':
227: case '3':
228: rtype = c - '0' + 2; break;
229: case '7':
230: case '8':
231: case '9':
232: rtype = -1; break;
233: default: return E_LOADFMT;
234: }
235:
236: for (cksum = bcnt = addr = dcnt = i = 0;; i++) {
237: if ((v1 = readHex()) < 0) return v1;
238: if ((v = readHex()) < 0) return v;
239: cksum += (v += (v1 << 4));
240:
241: if (i == 0) {
242: if ((bcnt = v - 1) < 0) return E_LOAD;
243: addr = 0;
244: continue;
245: }
246: if (i > bcnt) {
247: if (cksum != 0xff) return E_LOAD;
248: break;
249: }
250: if (rtype <= 0) continue;
251:
252: if (i < rtype) {
253: addr = (addr << 8) + v;
254: } else {
255: buf[dcnt++] = (UB)v;
256: }
257: }
258: if (dcnt > 0) {
259:
260:
261: if (a_addr != 0) {
262: offset = a_addr - addr;
263: a_addr = 0;
264: }
265: addr += offset;
266: if (addr < loaddr || addr - 1 > hiaddr - dcnt)
267: return E_RANGE;
268: if (writeMem(addr, buf, dcnt, 1) != dcnt)
269: return E_MACV;
270: if (addr < s_addr) s_addr = addr;
271: if ((addr += dcnt) > e_addr) e_addr = addr;
272: }
273: if (rtype < 0) break;
274: }
275: return E_OK;
276: }
277: 278: 279:
280: EXPORT ER doLoading(W proto, UW addr, UW *range)
281: {
282: ER er;
283:
284: e_addr = s_addr = addr;
285:
286: if (range) {
287: loaddr = range[0];
288: hiaddr = range[1];
289: offset = range[2];
290: } else {
291: loaddr = 0;
292: hiaddr = 0xFFFFFFFF;
293: offset = 0;
294: }
295:
296: if (proto & P_XMODEM) {
297: readFn = (FUNCP)xmodemRead;
298: blkptr = blkno = blksz = 0;
299: } else {
300: readFn = (FUNCP)textRead;
301: }
302:
303: if (proto & P_SFORM) {
304: er = loadSform();
305: if (er == E_END) er = E_LOAD;
306: } else {
307: er = loadImage();
308: }
309:
310:
311: if (proto & P_XMODEM) xmodemEnd(er);
312:
313:
314: purgeInput();
315:
316: if (er == E_END) er = E_OK;
317: DSP_LF;
318: if (er == E_OK) {
319: e_addr--;
320: if (range) {
321: range[0] = s_addr;
322: range[1] = e_addr;
323: s_addr -= offset;
324: e_addr -= offset;
325: }
326: DSP_F5(S,"Loaded: ", 08X,s_addr, S," -> ", 08X,e_addr, CH,'\n');
327: }
328: return er;
329: }