xref: /plan9-contrib/sys/src/cmd/jtagfs/icert.c (revision dedb130315e7b691e306ee069395ee1f0b18e4d4)
1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include "chain.h"
5 #include "debug.h"
6 #include "tap.h"
7 #include "lebo.h"
8 #include "bebo.h"
9 #include "jtag.h"
10 #include "icert.h"
11 #include "mpsse.h"
12 #include "/sys/src/9/kw/arm.h"
13 #include "mmu.h"
14 
15 /*
16  *	Read, paying special atention to anything called
17  *	embedded-ice/debug of the arm core, normally
18  *	there is a chapter called Debug or Debugging and some
19  *	details sprinkled around.
20  *	- ARM9E-S "Technical Reference Manual"
21  *	- ARM7TDMI-S "Core Technical Reference Manual"
22  *	- Open On-Chip Debugger thesis
23  *	"Design and Implementation of an On-Chip Debug for Embedded
24  *	Target Systems"
25  *	- Application note 205 "Writing JTAG Sequences for Arm 9 Processors"
26  *	The bit ordering on the last one is confusing/wrong, but the
27  *	procedures for doing things clarify a lot.
28  */
29 
30 
31 /*
32  *	BUG: print pack and unpack could be generated automatically
33  *	except for the wild endianness of the instr. Minilanguage?
34  */
35 
36 static char *
printech1(EiceChain1 * ec1,char * s,int ssz)37 printech1(EiceChain1 *ec1, char *s, int ssz)
38 {
39 	char *e, *te;
40 
41 	te = s + ssz -1;
42 
43 	e = seprint(s, te, "rwdata: %#8.8ux\n", ec1->rwdata);
44 	e = seprint(e, te, "wptandbkpt: %1.1d\n", ec1->wptandbkpt);
45 	e = seprint(e, te, "sysspeed: %1.1d\n", ec1->sysspeed);
46 	e = seprint(e, te, "instr: %#8.8ux\n", ec1->instr);
47 	return e;
48 }
49 
50 static int
packech1(Chain * ch,EiceChain1 * ec1)51 packech1(Chain *ch, EiceChain1 *ec1)
52 {
53 	EiceChain1	lec;
54 	uchar unused;
55 
56 	unused = 0;
57 
58 	lec.instr = hmsbputl(&ec1->instr);
59 	hbeputl(&lec.rwdata, ec1->rwdata);
60 
61 	putbits(ch, &lec.rwdata, RWDataSz);
62 	putbits(ch, &unused, 1);
63 	putbits(ch, &lec.wptandbkpt, WpTanDBKptSz);
64 
65 	putbits(ch, &ec1->sysspeed, SysSpeedSz);
66 	putbits(ch, &lec.instr, InstrSz);
67 
68 	return 0;
69 }
70 
71 static int
unpackech1(EiceChain1 * ec1,Chain * ch)72 unpackech1(EiceChain1 *ec1, Chain *ch)
73 {
74 	uchar unused;
75 
76 	unused = 0;
77 
78 
79 	getbits(&ec1->rwdata, ch, RWDataSz);
80 	getbits(&unused, ch, 1);
81 	getbits(&ec1->wptandbkpt, ch, WpTanDBKptSz);
82 	getbits(&ec1->sysspeed, ch, SysSpeedSz);
83 	getbits(&ec1->instr, ch, InstrSz);
84 
85 	ec1->instr = msbhgetl(&ec1->instr);
86 	ec1->rwdata = lehgetl(&ec1->rwdata);
87 
88 	return 0;
89 }
90 
91 
92 static char *
printech2(EiceChain2 * ec2,char * s,int ssz)93 printech2(EiceChain2 *ec2, char *s, int ssz)
94 {
95 	char *e, *te;
96 
97 	te = s + ssz -1;
98 
99 	e = seprint(s, te, "data: %#8.8ux\n", ec2->data);
100 	e = seprint(e, te, "addr: %#2.2ux\n", ec2->addr);
101 	e = seprint(e, te, "rw: %1.1d\n", ec2->rw);
102 	return e;
103 }
104 
105 static int
valregaddr(uchar addr)106 valregaddr(uchar addr)
107 {
108 	if(addr <= CtlMskReg)
109 		return 1;
110 	if( (addr&Wp0)  <= CtlMskReg ||  (addr&Wp1)  <= CtlMskReg)
111 		return 1;
112 	return 0;
113 }
114 
115 static int
packech2(Chain * ch,EiceChain2 * ec2)116 packech2(Chain *ch, EiceChain2 *ec2)
117 {
118 	EiceChain2	lec;
119 
120 	if(!valregaddr(ec2->addr))
121 		return -1;
122 
123 	hleputl(&lec.data, ec2->data);
124 
125 	putbits(ch, &lec.data, DataSz);
126 	putbits(ch, &ec2->addr, AddrSz);
127 	putbits(ch, &ec2->rw, RWSz);
128 	return 0;
129 }
130 
131 static int
unpackech2(EiceChain2 * ec2,Chain * ch)132 unpackech2(EiceChain2 *ec2, Chain *ch)
133 {
134 
135 	getbits(&ec2->data, ch, DataSz);
136 	getbits(&ec2->addr, ch, AddrSz);
137 	getbits(&ec2->rw, ch, RWSz);
138 
139 	if(!valregaddr(ec2->addr))
140 		return -1;
141 
142 	ec2->data = lehgetl(&ec2->data);
143 
144 	return 0;
145 }
146 
147 
148 static char *
printwp(EiceWp * wp,char * s,int ssz)149 printwp(EiceWp *wp, char *s, int ssz)
150 {
151 	char *e, *te;
152 
153 	te = s + ssz -1;
154 
155 	e = seprint(s, te, "addrval: %#8.8ux\n", wp->addrval);
156 	e = seprint(e, te, "addmsk: %#8.8ux\n", wp->addrmsk);
157 	e = seprint(e, te, "dataval: %#8.8ux\n", wp->dataval);
158 	e = seprint(e, te, "datamsk: %#8.8ux\n", wp->datamsk);
159 
160 	e = seprint(e, te, "ctlval: %#4.4ux\n", wp->ctlval);
161 	e = seprint(e, te, "ctlmsk: %#2.2ux\n", wp->ctlmsk);
162 	return e;
163 }
164 
165 static char *
printregs(EiceRegs * regs,char * s,int ssz)166 printregs(EiceRegs *regs, char *s, int ssz)
167 {
168 	char *e, *te, i;
169 
170 	te = s + ssz -1;
171 
172 	e = seprint(s, te, "debug: %#2.2ux\n", regs->debug);
173 	e = seprint(e, te, "debsts: %#2.2ux\n", regs->debsts);
174 	e = seprint(e, te, "veccat: %#2.2ux\n", regs->veccat);
175 	e = seprint(e, te, "debcomctl: %#2.2ux\n", regs->debcomctl);
176 	e = seprint(e, te, "debcomdata: %#8.8ux\n", regs->debcomdata);
177 
178 	for(i = 0; i<nelem(regs->wp); i++)
179 		e = printwp(regs->wp + i, e, ssz+(s-e));
180 	return e;
181 }
182 
183 static u32int
unpackcpuid(uchar * v)184 unpackcpuid(uchar *v)
185 {
186 	u32int id;
187 
188 	id = lehgetl(v);
189 	return id;
190 }
191 
192 static void
prcpuid(u32int id)193 prcpuid(u32int id)
194 {
195 
196 	fprint(2, "ID: %#8.8ux\n", id);
197 	fprint(2, "Must be 1: %d\n", id&1);
198 	fprint(2, "Manufacturer id: %#lux\n", MANID(id));
199 	fprint(2, "Part no: %#lux\n", PARTNO(id));
200 	fprint(2, "Version: %#lux\n", VERS(id));
201 	return;
202 }
203 
204 
205 
206 int
setinst(JMedium * jmed,uchar inst,int nocommit)207 setinst(JMedium *jmed, uchar inst, int nocommit)
208 {
209 	int res, com;
210 	ShiftTDesc req;
211 	uchar buf[1+ShiftMarg];
212 
213 	memset(buf, 0, 5);
214 	buf[0] = inst;
215 	com = 0;
216 
217 	dprint(Djtag, "Setting jtag instr: %#2.2ux, commit: %d\n",
218 			inst, !nocommit);
219 	if(nocommit)
220 		com = ShiftNoCommit;
221 	req.reg = TapIR;
222 	req.buf = buf;
223 	req.nbits = InLen;
224 	req.op = ShiftOut|com;
225 
226 	res = tapshift(jmed, &req, nil, jmed->tapcpu);
227 	if(res < 0){
228 		werrstr("setinst: shifting instruction %#2.2ux for jtag", inst);
229 		return -1;
230 	}
231 	return res;
232 }
233 
234 int
icesetreg(JMedium * jmed,int regaddr,u32int val)235 icesetreg(JMedium *jmed, int regaddr, u32int val)
236 {
237 	Chain ch;
238 	ShiftTDesc req;
239 	EiceChain2 ec2;
240 	char debugstr[128];
241 	int res;
242 
243 	dprint(Dice, "Set eice 2 reg[%#2.2ux] to %#8.8ux\n", regaddr, val);
244 	ec2.data = val;
245 	ec2.addr = regaddr;
246 	ec2.rw = 1;
247 	memset(&ch, 0, sizeof ch);
248 
249 
250 	res = packech2(&ch, &ec2);
251 	if(res < 0)
252 		return -1;
253 	if(debug[Dchain] || debug[DAll]){
254 		printech2(&ec2, debugstr, sizeof debugstr);
255 		fprint(2, "%s", debugstr);
256 		printchain(&ch);
257 	}
258 	req.reg = TapDR;
259 	req.buf = ch.buf;
260 	req.nbits = EiceCh2Len;
261 	req.op = ShiftOut;
262 	res = tapshift(jmed, &req, nil, jmed->tapcpu);
263 	if(res < 0)
264 		return -1;
265 
266 	return 0;
267 }
268 
269 
270 u32int
icegetreg(JMedium * jmed,int regaddr)271 icegetreg(JMedium *jmed, int regaddr)
272 {
273 	Chain ch;
274 	ShiftTDesc req;
275 	int res;
276 	EiceChain2 ec2;
277 	char debugstr[128];
278 
279 	ec2.data = 0;
280 	ec2.addr = regaddr;
281 	ec2.rw = 0;
282 	memset(&ch, 0, sizeof ch);
283 
284 	res = packech2(&ch, &ec2);
285 	if(res < 0)
286 		return -1;
287 	if(debug[Dchain] || debug[DAll]){
288 		printech2(&ec2, debugstr, sizeof debugstr);
289 		fprint(2, "%s", debugstr);
290 		printchain(&ch);
291 	}
292 	req.reg = TapDR;
293 	req.buf = ch.buf;
294 	req.nbits = EiceCh2Len;
295 	req.op = ShiftOut;
296 	res = tapshift(jmed, &req, nil, jmed->tapcpu);
297 	if(res < 0)
298 		return -1;
299 	req.reg = TapDR;
300 	req.buf = ch.buf;
301 	req.nbits = EiceCh2Len;
302 	req.op = ShiftOut|ShiftIn;
303 	res = tapshift(jmed, &req, nil, jmed->tapcpu);
304 	if(res < 0)
305 		return -1;
306 	ch.b = 0;
307 	ch.e = EiceCh2Len;
308 	res = unpackech2(&ec2, &ch);
309 	if(res < 0)
310 		return -1;
311 	if(debug[Dice] || debug[DAll]){
312 		printchain(&ch);
313 		printech2(&ec2, debugstr, sizeof debugstr);
314 		fprint(2, "Get eice 2 reg[%#2.2ux] to %#8.8ux\n", regaddr, ec2.data);
315 	}
316 	return ec2.data;
317 }
318 
319 int
setchain(JMedium * jmed,int commit,uchar chain)320 setchain(JMedium *jmed, int commit, uchar chain)
321 {
322 	ShiftTDesc req;
323 	uchar data[1+ShiftMarg];
324 	int res, com;
325 
326 	dprint(Dice, "Set chain %d, chain before %d\n", chain, jmed->currentch);
327 	if(jmed->currentch == chain)
328 		return 0;
329 	res = setinst(jmed, InScanN, 1);
330 	if(res < 0)
331 		return -1;
332 	data[0] = chain;
333 	com = 0;
334 	if(!commit)
335 		com = ShiftNoCommit;
336 	req.reg = TapDR;
337 	req.buf = data;
338 	req.nbits = 5;
339 	req.op = ShiftPauseIn|ShiftOut|com;
340 	res = tapshift(jmed, &req, nil, jmed->tapcpu);
341 	if(res < 0)
342 		return -1;
343 	res = setinst(jmed, InTest, 1);
344 	if(res < 0)
345 		return -1;
346 	jmed->currentch = chain;
347 	return 0;
348 }
349 
350 
351 int
armgofetch(JMedium * jmed,u32int instr,int sysspeed)352 armgofetch(JMedium *jmed, u32int instr, int sysspeed)
353 {
354 	char debugstr[128];
355 	ShiftTDesc req;
356 	EiceChain1 ec1;
357 	Chain ch;
358 	int res;
359 
360 	ec1.instr = instr;
361 	ec1.sysspeed = sysspeed;
362 	ec1.wptandbkpt = 0;
363 	ec1.rwdata = 0;
364 	memset(&ch, 0, sizeof (Chain));
365 	res = packech1(&ch, &ec1);
366 	if(res < 0)
367 		return -1;
368 	if(debug[Dchain] || debug[DAll]){
369 		printech1(&ec1, debugstr, sizeof debugstr);
370 		fprint(2, "%s", debugstr);
371 		printchain(&ch);
372 	}
373 	req.reg = TapDR;
374 	req.buf = ch.buf;
375 	req.nbits = ch.e-ch.b;
376 	req.op = ShiftOut|ShiftPauseOut|ShiftPauseIn;
377 	res = tapshift(jmed, &req, nil, jmed->tapcpu);
378 	if(res < 0)
379 		return -1;
380 	return 0;
381 
382 }
383 
384 int
armgetexec(JMedium * jmed,int nregs,u32int * regs,u32int inst)385 armgetexec(JMedium *jmed, int nregs, u32int *regs, u32int inst)
386 {
387 	ShiftTDesc req;
388 	int i, res, flags;
389 	uchar *buf;
390 	ShiftRDesc *replies;
391 
392 	dprint(Darm, "Exec: %#8.8ux\n", inst);
393 	replies = mallocz(nregs*sizeof(ShiftRDesc), 1);
394 	if(replies == nil)
395 		sysfatal("read, no mem %r");
396 	buf = mallocz(EiceCh1Len+ShiftMarg, 1);
397 	if(buf == nil)
398 		sysfatal("read, no mem %r");
399 	armgofetch(jmed, inst, 0);
400 	/* INST in decode stage */
401 	armgofetch(jmed, ARMNOP, 0);
402 	/* INST in execute stage */
403 	armgofetch(jmed, ARMNOP, 0);
404 	/* INST in access stage */
405 	flags = ShiftAsync|ShiftIn|ShiftPauseIn|ShiftPauseOut;
406 	for(i = 0; i < nregs; i++){
407 		req.reg = TapDR;
408 		req.buf = buf;
409 		req.nbits = EiceCh1Len;
410 		req.op = flags;
411 		res = tapshift(jmed, &req,  &replies[i], jmed->tapcpu);
412 		if(res < 0)
413 			return -1;
414 	}
415 	for(i = 0; i < nregs; i++){
416 		res = jmed->rdshiftrep(jmed, buf, &replies[i]);
417 		if(res < 0)
418 			return -1;
419 		regs[i] = *(u32int *)buf;
420 		dprint(Darm, "Read [%d]: %#8.8ux\n", i, regs[i]);
421 	}
422 	armgofetch(jmed, ARMNOP, 0);
423 	/* INST in writeback stage */
424 	armgofetch(jmed, ARMNOP, 0);
425 	/* INST end, pipeline full of NOPs */
426 
427 	free(buf);
428 	free(replies);
429 	return 0;
430 }
431 
432 int
armsetexec(JMedium * jmed,int nregs,u32int * regs,u32int inst)433 armsetexec(JMedium *jmed, int nregs, u32int *regs, u32int inst)
434 {
435 	ShiftTDesc req;
436 	int i, res, flags;
437 	uchar *buf;
438 
439 	ShiftRDesc *replies;
440 
441 	dprint(Darm, "Exec: %#8.8ux\n", inst);
442 	replies = mallocz(nregs*sizeof(ShiftRDesc), 1);
443 	if(replies == nil)
444 		sysfatal("read, no mem %r");
445 	buf = mallocz(EiceCh1Len+ShiftMarg, 1);
446 	if(buf == nil)
447 		sysfatal("readregs, no mem %r");
448 	armgofetch(jmed, inst, 0);
449 	/* STMIA in decode stage */
450 	armgofetch(jmed, ARMNOP, 0);
451 	/* STMIA in execute stage */
452 	armgofetch(jmed, ARMNOP, 0);
453 	/* STMIA in memory acess stage */
454 	flags = ShiftOut|ShiftPauseIn|ShiftPauseOut;
455 	for(i = 0; i < nregs; i++){
456 		*(u32int *)buf = regs[i];
457 		dprint(Darm, "Set [%d]: %#8.8ux\n", i, regs[i]);
458 		req.reg = TapDR;
459 		req.buf = buf;
460 		req.nbits = EiceCh1Len;
461 		req.op = flags;
462 		res = tapshift(jmed, &req,  nil, jmed->tapcpu);
463 		if(res < 0)
464 			return -1;
465 	}
466 	armgofetch(jmed, ARMNOP, 0);
467 	/* STMIA in writeback stage */
468 	armgofetch(jmed, ARMNOP, 0);
469 	/* STMIA end, pipeline full of NOPs */
470 
471 	free(buf);
472 	free(replies);
473 	return 0;
474 }
475 
476 /* reads r0-r15 to regs if bits of mask are 1 */
477 static int
armgetregs(JMedium * jmed,u32int mask,u32int * regs)478 armgetregs(JMedium *jmed, u32int mask, u32int *regs)
479 {
480 	int ireps, nregs, r, i;
481 	u32int *regrd;
482 
483 	nregs = 0;
484 	ireps = 0;
485 	for(i = 0; i < 16; i++){
486 		if( (1 << i) & mask)
487 			nregs++;
488 	}
489 	regrd = mallocz(nregs*sizeof(u32int), 1);
490 	if(regrd == nil)
491 		sysfatal("read, no mem %r");
492 
493 	r = armgetexec(jmed, nregs, regrd, ARMSTMIA|mask);
494 	if(r < 0)
495 		return -1;
496 
497 	for(i = 0; i < 16; i++){
498 		if( (1 << i) & mask){
499 			regs[i] = regrd[ireps++];
500 			dprint(Darm, "rd register r%d: %#8.8ux\n", i, regs[i]);
501 		}
502 	}
503 	free(regrd);
504 	return 0;
505 }
506 /* sets r0-r15 to regs if bits of mask are 1 */
507 int
armsetregs(JMedium * jmed,int mask,u32int * regs)508 armsetregs(JMedium *jmed, int mask, u32int *regs)
509 {
510 	int ireps, nregs, r, i;
511 	u32int *regrw;
512 
513 	nregs = 0;
514 	ireps = 0;
515 	for(i = 0; i < 16; i++){
516 		if( (1 << i) & mask)
517 			nregs++;
518 	}
519 	regrw = mallocz(nregs*sizeof(u32int), 1);
520 	if(regrw == nil)
521 		sysfatal("read, no mem %r");
522 	for(i = 0; i < 16; i++){
523 		if( (1 << i) & mask){
524 			regrw[ireps++] = regs[i];
525 			dprint(Darm, "wr register r%d: %#8.8ux\n", i, regs[i]);
526 		}
527 	}
528 	r = armsetexec(jmed, nregs, regrw, ARMLDMIA|mask);
529 	if(r < 0)
530 		return -1;
531 
532 	free(regrw);
533 	return 0;
534 }
535 
536 static void
armprctxt(ArmCtxt * ctxt)537 armprctxt(ArmCtxt *ctxt)
538 {
539 	int i;
540 
541 	fprint(2, "Arm is in debug: %d\nregs\n", ctxt->debug);
542 	for(i = 0; i < 16; i++)
543 		fprint(2, "r%d: %#8.8ux\n", i, ctxt->r[i]);
544 	fprint(2, "cpsr: %#8.8ux\n", ctxt->cpsr);
545 	fprint(2, "spsr: %#8.8ux\n", ctxt->spsr);
546 }
547 
548 char *
armsprctxt(ArmCtxt * ctxt,char * s,int ssz)549 armsprctxt(ArmCtxt *ctxt, char *s, int ssz)
550 {
551 	char *e, *te;
552 	int i;
553 
554 	te = s + ssz -1;
555 
556 	e = seprint(s, te, "Arm is in debug: %d\nregs\n", ctxt->debug);
557 	for(i = 0; i < 16; i++)
558 		e = seprint(e, te, "r%d: %#8.8ux\n", i, ctxt->r[i]);
559 	e = seprint(e, te, "cpsr: %#8.8ux\n", ctxt->cpsr);
560 	e = seprint(e, te, "spsr: %#8.8ux\n", ctxt->spsr);
561 	return e;
562 }
563 
564 static char dbgstr[4*1024];
565 
566 int
armsavectxt(JMedium * jmed,ArmCtxt * ctxt)567 armsavectxt(JMedium *jmed, ArmCtxt *ctxt)
568 {
569 	int res;
570 
571 	res = setchain(jmed, 0, 1);
572 	if(res < 0)
573 		goto Error;
574 
575 	res = armgetregs(jmed, 0xffff, ctxt->r);
576 	if(res < 0)
577 		goto Error;
578 	res = armgofetch(jmed, ARMMRSr0CPSR, 0);
579 	if(res < 0)
580 		goto Error;
581 	res = armgetexec(jmed, 1, &ctxt->cpsr, ARMSTMIA|0x0001);
582 	if(res < 0)
583 		goto Error;
584 	res = armgofetch(jmed, ARMMRSr0SPSR, 0);
585 	if(res < 0)
586 		goto Error;
587 	res = armgetexec(jmed, 1, &ctxt->spsr, ARMSTMIA|0x0001);
588 	if(res < 0)
589 		goto Error;
590 	res = mmurdregs(jmed, ctxt);
591 	if(res < 0){
592 		werrstr("mmurdregs %r");
593 		return -1;
594 	}
595 	if(debug[Dmmu] || debug[DAll]){
596 		printmmuregs(ctxt, dbgstr, sizeof dbgstr);
597 		dprint(Dfs, "MMU state:\n%s\n", dbgstr);
598 	}
599 	if(debug[Dctxt] || debug[DAll]){
600 		fprint(2, "Arm save ctxt\n");
601 		armprctxt(ctxt);
602 	}
603 	return 0;
604 Error:
605 	return -1;
606 }
607 
608 static int
armjmpctxt(JMedium * jmed,ArmCtxt * ctxt)609 armjmpctxt(JMedium *jmed, ArmCtxt *ctxt)
610 {
611 	int res;
612 
613 	if(debug[Dctxt] || debug[DAll]){
614 		fprint(2, "Arm jmp ctxt\n");
615 		armprctxt(ctxt);
616 	}
617 	res = armsetexec(jmed, 1, &ctxt->cpsr, ARMLDMIA|0x0001);
618 	if(res < 0)
619 		return -1;
620 	res = armgofetch(jmed, ARMMSRr0CPSR, 0);
621 	if(res < 0)
622 		return -1;
623 	 /*	it is quite important this is the last instr for PC calculations */
624 	ctxt->r[15] += ctxt->pcadjust;
625 	res = armsetregs(jmed, 0xffff, ctxt->r);
626 	if(res < 0)
627 		return -1;
628 
629 	return 0;
630 }
631 
632 
633 int
armfastexec(JMedium * jmed,u32int inst)634 armfastexec(JMedium *jmed, u32int inst)
635 {
636 	int res;
637 
638 	dprint(Darm, "Exec: %#8.8ux\n", inst);
639 	res = armgofetch(jmed, ARMNOP, 0);
640 	if(res < 0)
641 		return -1;
642 
643 	res = armgofetch(jmed, ARMNOP, 0);
644 	if(res < 0)
645 		return -1;
646 	res = armgofetch(jmed, ARMNOP, 0);
647 	if(res < 0)
648 		return -1;
649 	res = armgofetch(jmed, inst, 0);
650 	if(res < 0)
651 		return -1;
652 	res = armgofetch(jmed, ARMNOP, 1);
653 	if(res < 0)
654 		return -1;
655 	return 0;
656 }
657 
658 int
icedebugstate(JMedium * jmed)659 icedebugstate(JMedium *jmed)
660 {
661 	int res;
662 
663 	res = setchain(jmed, ChCommit, 2);
664 	if(res < 0)
665 		return 0;
666 	return icegetreg(jmed, DebStsReg) & DBGACK;
667 }
668 
669 int
icewaitdebug(JMedium * jmed)670 icewaitdebug(JMedium *jmed)
671 {
672 	int i, res;
673 
674 	res = setchain(jmed, ChCommit, 2);
675 	if(res < 0)
676 		return -1;
677 
678 	for(i = 0; i < 20; i ++){
679 		if(icedebugstate(jmed))
680 			break;
681 		sleep(100);
682 	}
683 	if( i == 20)
684 		return -1;
685 
686 	icesetreg(jmed, DebugCtlReg, INTDIS|DBGACK); /* clear RQ */
687 	return 0;
688 }
689 
690 int
armrdmemwd(JMedium * jmed,u32int addr,u32int * data,int sz)691 armrdmemwd(JMedium *jmed, u32int addr, u32int *data, int sz)
692 {
693 	int res;
694 	u32int d, byte;
695 
696 	res = setchain(jmed, ChCommit, 1);
697 	if(res < 0)
698 		sysfatal("setchain %r");
699 	byte = 0;
700 	if(sz == 1)
701 		byte = BYTEWDTH;
702 	/* load address in r0 */
703 	res = armsetexec(jmed, 1, &addr, ARMLDMIA|0x0001);
704 	if(res < 0)
705 		return -1;
706 
707 	/* LDR r1, [r0] place data in r1 */
708 	res = armfastexec(jmed, byte|ARMLDRindr1xr0);
709 	if(res < 0)
710 		return -1;
711 
712 	setinst(jmed, InRestart, 0);
713 	res = icewaitdebug(jmed);
714 	if(res < 0)
715 		return -1;
716 	res = setchain(jmed, ChCommit, 1);
717 	if(res < 0)
718 		sysfatal("setchain %r");
719 	armgetexec(jmed, 1, &d, byte|ARMSTMIA|0x0002);
720 
721 	*data = d;
722 	dprint(Dmem, "Read data %#8.8ux addr %#8.8ux \n",
723 				d, addr);
724 	return sz;
725 }
726 
727 int
armwrmemwd(JMedium * jmed,u32int addr,u32int data,int sz)728 armwrmemwd(JMedium *jmed, u32int addr, u32int data, int sz)
729 {
730 	int res;
731 	u32int byte;
732 
733 	dprint(Dmem, "Write data %#8.8ux addr %#8.8ux \n",
734 				data, addr);
735 	res = setchain(jmed, ChCommit, 1);
736 	if(res < 0)
737 		sysfatal("setchain %r");
738 	byte = 0;
739 	if(sz == 1)
740 		byte = BYTEWDTH;
741 	/* load address in r0 */
742 	res = armsetexec(jmed, 1, &addr, ARMLDMIA|0x0001);
743 	if(res < 0)
744 		return -1;
745 	/* load data in r1 */
746 	res = armsetexec(jmed, 1, &data, byte|ARMLDMIA|0x0002);
747 	if(res < 0)
748 		return -1;
749 
750 	/* STR [r0], r1 place data in [r0] */
751 	res = armfastexec(jmed, ARMSTRindxr0r1);
752 	if(res < 0)
753 		return -1;
754 
755 	setinst(jmed, InRestart, 0);
756 	res = icewaitdebug(jmed);
757 	if(res < 0)
758 		return -1;
759 	return sz;
760 }
761 
762 
763 u32int
armidentify(JMedium * jmed)764 armidentify(JMedium *jmed)
765 {
766 	uchar *buf;
767 	ShiftTDesc req;
768 	u32int cpuid;
769 	int res, i;
770 
771 	//if(jmed->motherb == Sheeva)
772 	//	jmed->resets(jmed->mdata, 0, 1);
773 	buf = malloc(sizeof(u32int)*0x100+	ShiftMarg);
774 	if(buf == nil)
775 		sysfatal("memory");
776 
777 	for(i = 0; i < sizeof(u32int)*0x100; i++)
778 		buf[i] = i;	/* just a pattern to see in debugging */
779 
780 	req.reg = TapDR;
781 	req.buf = buf;
782 	req.nbits = sizeof(u32int)*0x100;	/* Bug by 8? */
783 	req.op = ShiftOut|ShiftIn;
784 	res = tapshift(jmed, &req, nil, jmed->tapcpu);
785 	if(res < 0){
786 		free(buf);
787 		return ~0;
788 	}
789 	//if(jmed->motherb == Sheeva)
790 	//	jmed->resets(jmed->mdata, 0, 0);
791 	cpuid = unpackcpuid(buf);
792 	if(cpuid != jmed->taps[jmed->tapcpu].hwid){
793 		fprint(2, "cpuid: %#8.8ux != %#8.8ux\n", cpuid, jmed->taps[jmed->tapcpu].hwid);
794 		free(buf);
795 		return ~0;
796 	}
797 	prcpuid(cpuid);
798 	free(buf);
799 	return cpuid;
800 }
801 
802 /* see if the fixed bypass value is ok */
803 int
armbpasstest(JMedium * jmed)804 armbpasstest(JMedium *jmed)
805 {
806 	ShiftTDesc req;
807 	uchar buf[2+ShiftMarg];
808 	int res;
809 
810 	memset(buf, 0xff, sizeof(buf));
811 	req.reg = TapIR;
812 	req.buf = buf;
813 	req.nbits = 2+InLen;
814 	req.op = ShiftOut|ShiftIn;
815 	res = tapshift(jmed, &req, nil, jmed->tapcpu);
816 	if(res < 0)
817 		sysfatal("jmed->regshift %r");
818 	if((buf[0] & 0xf) !=  0x1){
819 		fprint(2, "bad bypass: %#2.2ux\n", buf[0]);
820 		return -1;
821 	}
822 
823 	return 0;
824 }
825 
826 /* BUG: werrstr in the inner functions to indicate error, warnings... */
827 
828 
829 int
icewaitentry(JMedium * jmed,ArmCtxt * ctxt)830 icewaitentry(JMedium *jmed, ArmCtxt *ctxt)
831 {
832 	int res;
833 
834 	if(ctxt->debugreas == NoReas){
835 		werrstr("No debug activated");
836 		return -1;
837 	}
838 	res = setchain(jmed, ChCommit, 2);
839 	if(res < 0)
840 		return -1;
841 	res = icewaitdebug(jmed);
842 	if(res < 0)
843 		return -1;
844 
845 	res = setchain(jmed, ChNoCommit, 1);
846 	if(res < 0)
847 		return -1;
848 
849 	/*	BUG: should change to Arm from Thumb or Jazelle, adjust, keep PC.
850 	 *	If I ever come down to doing this, Remember to repeat Thumb inst
851 	 *	to be endian independant...
852 	  */
853 	res = armsavectxt(jmed, ctxt);
854 	if(res < 0)
855 		return -1;
856 	ctxt->debug = 1;
857 
858 	ctxt->pcadjust = 0;	/* BUG: Thumb not impl */
859 	ctxt->r[15] -= 6*ArmInstSz;
860 	switch(ctxt->debugreas){
861 		case BreakReas:
862 		case VeccatReas:
863 			ctxt->pcadjust = -2*ArmInstSz;
864 		break;
865 		case DebugReas:
866 		break;
867 	}
868 	return 0;
869 }
870 
871 int
iceenterdebug(JMedium * jmed,ArmCtxt * ctxt)872 iceenterdebug(JMedium *jmed, ArmCtxt *ctxt)
873 {
874 	int res;
875 
876 	res = setchain(jmed, ChCommit, 2);
877 	if(res < 0)
878 		return -1;
879 
880 	//if(jmed->motherb == Sheeva)
881 	//	jmed->resets(jmed->mdata, 0, 1);
882 	if(!(icegetreg(jmed, DebStsReg) & DBGACK)){
883 			icesetreg(jmed, DebugCtlReg, DBGRQ);	/* freeze */
884 	}
885 
886 	//if(jmed->motherb == Sheeva)
887 	//	jmed->resets(jmed->mdata, 0, 0);
888 	ctxt->debugreas = DebugReas;
889 	res = icewaitentry(jmed, ctxt);
890 	if(res < 0)
891 		return -1;
892 	ctxt->exitreas = NoReas;
893 	return 0;
894 }
895 
896 
897 /*
898  *	The branch is the way to exit debug permanently
899  * 	no branch and you fall back to debug
900  *	The context needs to be restored (some register needs
901  *	to be written), don't know why
902  *	but you will fall back to debug if not, no matter what doc says.
903  *	The bypass is not mentioned to be necessary anywhere, but
904  *	the feroceon will not restart without it.
905  */
906 
907 int
iceexitdebug(JMedium * jmed,ArmCtxt * ctxt)908 iceexitdebug(JMedium *jmed, ArmCtxt *ctxt)
909 {
910 	int res, i;
911 	uchar wctl;
912 	u32int sts;
913 
914 	res = setchain(jmed, ChCommit, 1);
915 	if(res < 0)
916 		return -1;
917 
918 	res = armjmpctxt(jmed, ctxt);
919 	if(res < 0)
920 		return -1;
921 
922 	/* 4 entry to debug,  Store(does not count)  3 NOPS, Branch = -8 */
923 	res = armfastexec(jmed, ARMBRIMM|0xfffffb);
924 	if(res < 0)
925 		return -1;
926 
927 	res = setchain(jmed, ChCommit, 2);
928 	if(res < 0)
929 		return -1;
930 
931 	wctl = icegetreg(jmed, Wp0|CtlValReg);
932 	if(ctxt->exitreas != BreakReqReas)
933 		icesetreg(jmed, Wp0|CtlValReg, wctl&~EnableWPCtl);
934 
935 	if(ctxt->exitreas != VeccatReqReas)
936 		icesetreg(jmed, VecCatReg, 0);
937 	icesetreg(jmed, DebugCtlReg, 0); /* clear all,*/
938 	setinst(jmed, InBypass, 0);
939 	setinst(jmed, InRestart, 0);
940 	sleep(100);
941 	res = setchain(jmed, ChCommit, 2);
942 	if(res < 0)
943 		return -1;
944 
945 	for(i = 0; i < 10; i ++){
946 		sts = icegetreg(jmed, DebStsReg);
947 		if((sts&DBGACK) == 0)
948 			break;
949 		sleep(100);
950 	}
951 	if( i == 10)
952 		return -1;
953 
954 	switch(ctxt->exitreas){
955 		case NoReas:
956 			ctxt->debugreas = NoReas;
957 		break;
958 		case VeccatReqReas:
959 			ctxt->debugreas = VeccatReas;
960 		break;
961 		case BreakReqReas:
962 			ctxt->debugreas = BreakReas;
963 		break;
964 		default:
965 			ctxt->debugreas = NoReas;
966 		break;
967 	}
968 	ctxt->debug = 0;
969 	return 0;
970 }
971