xref: /plan9-contrib/sys/src/cmd/jtagfs/ma.c (revision dedb130315e7b691e306ee069395ee1f0b18e4d4)
1 #include <u.h>
2 #include <libc.h>
3 #include <ctype.h> /* BUG: yes I know... ascii*/
4 #include <bio.h>
5 #include "debug.h"
6 #include "tap.h"
7 #include "jtag.h"
8 #include "icert.h"	/* BUG: separate medium and ice */
9 #include "mpsse.h"
10 
11 /*
12  *	Mpsse assembler
13  *	Based on AN2232C-01 Command Processor for MPSSE and MCU Host Bus
14  *	and various magical commands from source code all around.
15  */
16 
17 
18 enum{
19 	/* MPSSE  */
20 
21 	/*
22 	 *	This are used only to make opcodes
23 	 *	for Clocking in/out data to TD0 to TDI
24 	 */
25 	OpModOut = 0x10,
26 	OpTmsCs = 0x4a,			/* clock data to TmsCs */
27 
28 	/* Modifiers for both */
29 	OpModShort = 0x02,		/* len only one byte */
30 	OpModOutFalling = 0x01,
31 	OpModInFalling = 0x04,
32 	OpModLSB = 0x08,
33 	OpModIn = 0x20,
34 
35 	OpModBitsH = 0x02,
36 	OpModBitsIn = 0x01,
37 	OpSetBits = 0x80,			/* value(?)/direction on pins*/
38 
39 	OpLoop = 0x84,			/* loop connect TDI/DO with TDO/DI */
40 	OpBreakLoop = 0x85,		/* break loop */
41 	OpTckSkDiv = 0x86,			/* valL valH,  ?? description of reset */
42 
43 	OpDiv5ClkEnab = 0x8b,
44 	OpDiv5ClkDisab = 0x8a,
45 
46 
47 	/* MCU host emulation */
48 	OpModLong = 0x01,			/* addrH addrL */
49 
50 	OpMCURd = 0x90,			/* addr */
51 	OpMCUWr = 0x92,			/* addr Data */
52 
53 	OpBad = 0,				/* made this up */
54 
55 	/* Both modes */
56 	OpSendImm = 0x87,		/* flush buffer back to PC  ??? */
57 	OpWaitIOHigh = 0x88,		/* IO high, GPIOH in MPSSE, I/O1 on MCU */
58 	OpWaitIOLow = 0x89,		/* IO low, GPIOH in MPSSE, I/O1 on MCU */
59 
60 	OpAdaptClkEnab = 0x96,
61 	OpAdaptClkDisab = 0x97,
62 	RBad = 0xFA,				/* followed by the bad command */
63 
64 	MaxDataSz = 0xffff+1,
65 };
66 
67 typedef struct Inst Inst;
68 struct Inst{
69 	int hasresp;
70 	int isshort;
71 	int islsb;	/* bits come/go LSB */
72 	int nedge;
73 	uchar edge[2];
74 	uchar opcode;
75 	int lensz;
76 	uchar len[2];
77 	int immsz;
78 	uchar imm[3];
79 	int datasz;
80 	uchar data[1];
81 };
82 
83 enum{
84 	DataIn,
85 	DataOut,
86 	DataOutIn,
87 	TmsCsOut,
88 	TmsCsOutIn,
89 	SetBitsL,
90 	SetBitsH,
91 	TckSkDiv,
92 	MCURd,	/* from this down, no param */
93 	MCUWr,
94 	SendImm,
95 	WaitIOHigh,
96 	WaitIOLow,
97 	AdaptClkEnab,
98 	AdaptClkDisab,
99 	Div5ClkEnab,
100 	Div5ClkDisab,
101 	GetBitsL,
102 	GetBitsH,
103 	Loop,
104 	BreakLoop,
105 	ILast,
106 };
107 
108 static char *inst[] = {
109 	[DataIn]			"DataIn",
110 	[DataOut]			"DataOut",
111 	[DataOutIn]		"DataOutIn",
112 	[TmsCsOut]		"TmsCsOut",
113 	[TmsCsOutIn]		"TmsCsOutIn",
114 	[SetBitsL]			"SetBitsL",
115 	[SetBitsH]			"SetBitsH",
116 	[TckSkDiv]		"TckSkDiv",
117 	[MCURd]			"MCURd",
118 	[MCUWr]			"MCUWr",
119 	[SendImm]		"SendImm",
120 	[WaitIOHigh]		"WaitIOHigh",
121 	[WaitIOLow]		"WaitIOLow",
122 	[AdaptClkEnab]		"AdaptClkEnab",
123 	[AdaptClkDisab]	"AdaptClkDisab",
124 	[Div5ClkEnab]		"Div5ClkEnab",
125 	[Div5ClkDisab]		"Div5ClkDisab",
126 	[GetBitsL]			"GetBitsL",
127 	[GetBitsH]			"GetBitsH",
128 	[Loop]			"Loop",
129 	[BreakLoop]		"BreakLoop",
130 	[ILast]			nil,
131 
132 };
133 
134 
135 enum{
136 	EdgeNone,
137 	EdgeUp,
138 	EdgeDown,
139 	EdgeBad,
140 };
141 
142 static uchar
dataopcode(Inst * inst,int instid,int issh,int islsb)143 dataopcode(Inst *inst, int instid, int issh, int islsb)
144 {
145 	uchar opcode = 0;
146 
147 	switch(instid){
148 	case DataOutIn:
149 		if(inst->edge[1] == EdgeDown)
150 				opcode = OpModInFalling;
151 		/* fall through */
152 	case DataOut:
153 		opcode |= OpModOut;
154 		if (inst->edge[0] == EdgeDown)
155 			opcode |= OpModOutFalling;
156 		break;
157 	case DataIn:
158 		if (inst->edge[0] == EdgeDown)
159 			opcode |= OpModInFalling;
160 		break;
161 	}
162 
163 	opcode |= inst->hasresp? OpModIn : 0;
164 	opcode |= issh? OpModShort : 0;
165 	opcode |= islsb? OpModLSB : 0;
166 
167 	return opcode;
168 }
169 
170 
171 static uchar
opcode(Inst * inst,int instid)172 opcode(Inst *inst, int instid)
173 {
174 	int issh, islsb;
175 	uchar opcode;
176 
177 	opcode = 0;
178 	issh = inst->isshort;
179 	islsb = inst->islsb;
180 
181 	if(instid != TmsCsOutIn && instid != TmsCsOut&& instid != DataOutIn)
182 		if(inst->edge[1] != EdgeNone){
183 			werrstr("should not have edge");
184 			return OpBad;
185 		}
186 
187 	switch(instid){
188 	case DataOutIn:
189 	case DataOut:
190 	case DataIn:
191 		opcode = dataopcode(inst, instid, issh, islsb);
192 		break;
193 
194 	case TmsCsOutIn:
195 		opcode = OpModIn;
196 		if (inst->edge[1] == EdgeDown)
197 			opcode |= OpModInFalling;
198 	/* fall through */
199 	case TmsCsOut:
200 		opcode |= OpTmsCs;
201 		if(!issh || (inst->len[0] + 1) > 7){
202 			werrstr("len too big: %d, issh:%d",
203 				inst->len[0]+1, issh);
204 			return OpBad;
205 		}
206 		if (inst->edge[0] == EdgeDown)
207 			opcode |= OpModOutFalling;
208 		opcode |= OpModShort;
209 		opcode |= OpModLSB;
210 		break;
211 	case MCURd:
212 		opcode = OpMCURd;
213 		opcode |= !issh? OpModLong : 0;
214 		break;
215 	case MCUWr:
216 		opcode = OpMCUWr;
217 		opcode |= !issh? OpModLong : 0;
218 		break;
219 	case SendImm:
220 		opcode = OpSendImm;
221 		break;
222 	case WaitIOHigh:
223 		opcode = OpWaitIOHigh;
224 		break;
225 	case TckSkDiv:
226 		opcode = OpTckSkDiv;
227 		break;
228 	case WaitIOLow:
229 		opcode = OpWaitIOLow;
230 		break;
231 	case AdaptClkEnab:
232 		opcode = OpAdaptClkEnab;
233 		break;
234 	case AdaptClkDisab:
235 		opcode = OpAdaptClkDisab;
236 		break;
237 	case Div5ClkEnab:
238 		opcode = OpDiv5ClkEnab;
239 		break;
240 	case Div5ClkDisab:
241 		opcode = OpDiv5ClkDisab;
242 		break;
243 	case GetBitsH:
244 	case SetBitsH:
245 		opcode = OpModBitsH;
246 	case GetBitsL:
247 	/* fall through */
248 		if(instid == GetBitsL || instid == GetBitsH)
249 			opcode |= OpModBitsIn;
250 	case SetBitsL:
251 		opcode |= OpSetBits;
252 		break;
253 	case Loop:
254 		opcode = OpLoop;
255 		break;
256 	case BreakLoop:
257 		opcode = OpBreakLoop;
258 		break;
259 	default:
260 		werrstr("unknown instruction");
261 		return OpBad;
262 	}
263 	return opcode;
264 }
265 
266 enum {
267 	ParLen	=	'L',		/* Data len 2 bytes or 1 byte (bit len) */
268 	ParShLen	=	'l', 		/* bit len Bnumber */
269 	ParData	=	'D',		/* data or @ to place data later */
270 	ParShData = 	'd',		/* short data, 1 byte at most */
271 	ParImm 	=	'I',		/* immediate operator, 2/1 bytes */
272 	ParLImm	=	'i',		/* immediate operator, 2 bytes */
273 	ParShImm =	'c',		/* immediate operator, 1 byte */
274 	ParEdge	=	'E',		/* EdgeUp or EdgeDown */
275 	ParEndian	=	'N',		/* LSB or MSB */
276 	ParLsb	=	'n',		/* LSB */
277 };
278 
279 typedef struct InstDesc InstDesc;
280 struct InstDesc
281 {
282 	char *name;
283 	char *desc;
284 	int hasresp;
285 };
286 
287 static InstDesc idesc[] = {
288 	[DataIn]			{"DataIn",	"ENL", 1},
289 	[DataOut]			{"DataOut",	"ENLD", 0},
290 	[DataOutIn]		{"DataOutIn",	"EENLD", 1},
291 	[TmsCsOut]		{"TmsCsOut",	"ENld", 0},
292 	[TmsCsOutIn]		{"TmsCsOutIn",	"EENld", 1},
293 	[MCURd]			{"MCURd",	"I", 1},
294 	[MCUWr]			{"MCUWr",	"Id", 0},
295 	[SendImm]		{"SendImm",	"", 0},
296 	[WaitIOHigh]		{"WaitIOHigh",	"", 0},
297 	[WaitIOLow]		{"WaitIOLow",	"", 0},
298 	[AdaptClkEnab]		{"AdaptClkEnab",	"", 0},
299 	[AdaptClkDisab]	{"AdaptClkDisab",	"", 0},
300 	[Div5ClkEnab]		{"Div5ClkEnab",	"", 0},
301 	[Div5ClkDisab]		{"Div5ClkDisab",	"", 0},
302 	[SetBitsL]			{"SetBitsL",	"cc", 0},
303 	[GetBitsL]			{"GetBitsL",	"c", 0},
304 	[SetBitsH]			{"SetBitsH",	"cc", 0},
305 	[GetBitsH]			{"GetBitsH",	"c", 0},
306 	[TckSkDiv]		{"TckSkDiv",	"i", 0},
307 	[Loop]			{"Loop",	"", 0},
308 	[BreakLoop]		{"BreakLoop",	"", 0},
309 	[ILast]			{nil,		nil, 0},
310 };
311 
312 
313 static int
nametoid(char * name)314 nametoid(char *name)
315 {
316 	int i;
317 	for (i = 0; i < ILast; i++){
318 		if(strcmp(inst[i], name) == 0)
319 			break;
320 	}
321 	if(i == ILast)
322 		return -1;
323 	return i;
324 }
325 
326 static int
edgetoid(char * edgename)327 edgetoid(char *edgename)
328 {
329 	if(strcmp(edgename, "EdgeUp") == 0)
330 		return EdgeUp;
331 	else if(strcmp(edgename, "EdgeDown") == 0)
332 		return EdgeDown;
333 
334 	return EdgeBad;
335 }
336 
337 static int
isendian(char * endianname)338 isendian(char *endianname)
339 {
340 	if(strcmp(endianname, "LSB") == 0)
341 		return 1;
342 	else if(strcmp(endianname, "MSB") == 0)
343 		return 1;
344 
345 	return 0;
346 }
347 
348 
349 static int
datalen(Inst * inst,char * p)350 datalen(Inst *inst, char *p)
351 {
352 	int len;
353 	if(p[0] == 'B'){
354 		inst->isshort++;
355 		p++;
356 	}
357 	else
358 		inst->isshort = 0;
359 	len = atoi(p); //strtol and check
360 	if(inst->isshort && len > 8)
361 		return -1;
362 	if(len > MaxDataSz)
363 		return -1;
364 	return len;
365 }
366 
367 static void
setlen(Inst * inst,int dlen)368 setlen(Inst *inst, int dlen)
369 {
370 	if(dlen != 0){
371 		inst->lensz++;
372 		inst->len[0] = (dlen - 1 ) & 0xff;
373 		if(!inst->isshort){
374 			inst->len[1] = 0xff & ((dlen - 1) >> 8);
375 			inst->lensz++;
376 		}
377 	}
378 }
379 
380 
381 static int
setdata(Inst * inst,char * nm,char * p,char * te,int bdlen)382 setdata(Inst *inst, char *nm, char *p, char *te, int bdlen)
383 {
384 	int i;
385 	char *e;
386 
387 	if(p == nil){
388 		werrstr("%s: should have data", nm);
389 		return -1;
390 	}
391 	if(*p == '@'){
392 		inst->datasz = bdlen;
393 		return 0;
394 	}
395 
396 	if(te != p)
397 		p[strlen(p)] = ' '; /* untokenize */
398 
399 	for (i = 0; i < bdlen; i++){
400 		inst->data[i] = strtol(p, &e, 0);
401 		if(!isspace(*e) && i != bdlen-1)
402 			return -1;
403 		p = e;
404 	}
405 	inst->datasz = i;
406 	return 0;
407 
408 }
409 
410 static int
hasresp(int instid)411 hasresp(int instid)
412 {
413 	return idesc[instid].hasresp;
414 }
415 
416 
417 static int
hasnoparam(int instid)418 hasnoparam(int instid)
419 {
420 	return strlen(idesc[instid].desc) == 0;
421 }
422 
423 static char *
endfield(char * p)424 endfield(char *p)
425 {
426 	char *s;
427 
428 	s = p;
429 	if(*p =='\0')
430 		return nil;
431 	while(*p != '\0'){
432 		if(isspace(*p)){
433 			if(s == p)
434 				return nil;
435 			return p;
436 		}
437 		p++;
438 	}
439 	return p;
440 }
441 
442 enum{
443 	LongSz,
444 	ShortSz,
445 	AnySz,
446 };
447 
448 static int
setimm(Inst * inst,int imm,int kindsz)449 setimm(Inst *inst, int imm, int kindsz)
450 {
451 	int isl, immh, imml;
452 
453 	isl = imm&~0xff;
454 
455 	if(isl && kindsz == ShortSz)
456 		return -1;
457 
458 
459 	if(isl || kindsz == LongSz){
460 		immh = (imm >> 8)&0xff;
461 		inst->imm[inst->immsz++] = immh; /* High, then low */
462 	}
463 	imml = imm&0xff;
464 	inst->imm[inst->immsz++] = imml;
465 	return 0;
466 }
467 
468 static Inst*
parseinst(int instid,char * pars,char * idname)469 parseinst(int instid, char *pars, char *idname)
470 {
471 	char *tok[15], *err, *e;
472 	char tf;
473 	int i, ntok, tnf, dlen, bdlen, imm, ndata;
474 	Inst *inst;
475 
476 	tf = '\0';
477 	dlen = bdlen = 0;
478 	err = "";
479 	inst = mallocz(sizeof(Inst) + 1, 1);
480 	if(inst == nil)
481 		return nil;
482 	tnf = strlen(idesc[instid].desc);
483 	e = pars + strlen(pars) + 1;
484 	ntok = tokenize(pars, tok, tnf);
485 	if(tnf != ntok){
486 		werrstr("%s: bad nr param %d!=%d", idname, tnf, ntok);
487 		return nil;
488 	}
489 
490 	for(i = 0; i < tnf; i++){
491 		tf = idesc[instid].desc[i];
492 		switch(tf){
493 		case ParLen:
494 			dlen = datalen(inst, tok[i]);
495 			if(dlen < 0){
496 				err = "bad len";
497 				goto Err;
498 			}
499 			if(inst->isshort)
500 				bdlen = 1;
501 			else {
502 				bdlen = dlen;
503 				inst = realloc(inst, sizeof(Inst) + bdlen);
504 				if(inst == nil)
505 					return nil;
506 			}
507 			break;
508 		case ParShLen:
509 			dlen = datalen(inst, tok[i]);
510 			if(dlen < 0){
511 				err = "bad len";
512 				goto Err;
513 			}
514 			bdlen = 1;
515 			if(!inst->isshort) {
516 				err = "should be short";
517 				goto Err;
518 			}
519 			break;
520 		case ParData:
521 			if(bdlen != 0){
522 				ndata = setdata(inst, idname, tok[i], e, bdlen);
523 				if(ndata < 0){
524 					err = "short data";
525 					goto Err;
526 				}
527 			}
528 			else {
529 				err = "no data";
530 				goto Err;
531 			}
532 			break;
533 		case ParShData:
534 			if(bdlen != 0){
535 				ndata = setdata(inst, idname, tok[i], e, bdlen);
536 				if(ndata < 0){
537 					err = "short data";
538 					goto Err;
539 				}
540 			}
541 			else {
542 				err = "no data";
543 				goto Err;
544 			}
545 			if(ndata > 1){
546 				err = "more than 1 byte data";
547 				goto Err;
548 			}
549 			break;
550 		case ParImm:
551 			imm = atoi(tok[i]);
552 			if(setimm(inst, imm, AnySz) < 0)
553 				goto Err;
554 			break;
555 		case ParLImm:
556 			imm = atoi(tok[i]);
557 			if(setimm(inst, imm, LongSz) < 0)
558 				goto Err;
559 			break;
560 		case ParShImm:
561 			imm = atoi(tok[i]);
562 			if(setimm(inst, imm, ShortSz) < 0)
563 				goto Err;
564 			break;
565 		case ParEdge:
566 			inst->edge[inst->nedge] = edgetoid(tok[i]);
567 			if(inst->edge[inst->nedge] == EdgeBad)
568 				goto Err;
569 			inst->nedge++;
570 			break;
571 		case ParEndian:
572 			inst->islsb = strcmp(tok[i], "LSB") == 0;
573 			if(!isendian(tok[i])){
574 				err = "bad endianness";
575 				goto Err;
576 			}
577 			break;
578 		case ParLsb:
579 			inst->islsb = strcmp(tok[i], "LSB") == 0;
580 			if(inst->islsb){
581 				err = "bad endianness: not LSB";
582 				goto Err;
583 			}
584 			break;
585 		default:
586 			err = "bad param";
587 			goto Err;
588 		}
589 
590 		if(bdlen > MaxDataSz || (inst->isshort && dlen > 8)){
591 			err = "len too big";
592 			goto Err;
593 		}
594 	}
595 
596 	setlen(inst, dlen);
597 	inst->hasresp = hasresp(instid);
598 	inst->opcode = opcode(inst, instid);
599 	if(inst->opcode == OpBad){
600 		err = "bad opcode";
601 		goto Err;
602 	}
603 	return inst;
604 Err:
605 	werrstr("inst:%s, nf:%d, ftype:%c, fval:%s:%s\n", idname, i, tf, tok[i], err);
606 	free(inst);
607 	return nil;
608 }
609 
610 static Inst *
parseassln(char * assline)611 parseassln(char *assline)
612 {
613 	int instid, lnsz;
614 	Inst *inst;
615 	char *ef, inm[32];
616 
617 	dprint(Dassln, "%s\n", assline);
618 
619 	lnsz = strlen(assline);
620 	if(lnsz == 0){
621 	 	werrstr("%s: line does not match instruction", assline);
622 		return nil;
623 	}
624 
625 	ef = endfield(assline);
626 	if(ef == nil){
627 	 	werrstr("%s: empty inst", assline);
628 		return nil;
629 	}
630 	strncpy(inm, assline, ef-assline);
631 	inm[ef-assline] = '\0';
632 	instid = nametoid(inm);
633 	if(instid < 0){
634 		werrstr("unrecognized instruction %s", inm);
635 		return nil;
636 	}
637 	inst = parseinst(instid, ef, inm);
638 	return inst;
639 }
640 
641 static int
unpacklen(Inst * inst)642 unpacklen(Inst *inst)
643 {
644 	int len;
645 
646 	if (inst->lensz == 0)
647 		return 0;
648 	len =  ((inst->len[1]<<8) | inst->len[0]) + 1;
649 
650 	return len;
651 }
652 
653 static int
instpacksz(Inst * inst)654 instpacksz(Inst *inst)
655 {
656 	return 1 + inst->immsz + inst->lensz + inst->datasz;
657 }
658 
659 static void
sdumpinst(char * s,int ssz,Inst * inst)660 sdumpinst(char *s, int ssz, Inst *inst)
661 {
662 	int i;
663 	char *e, *te;
664 
665 	e = s + ssz - 1;
666 	te = e;
667 
668 	e = seprint(s, te, "op: %#2.2ux\n", inst->opcode);
669 	if(e >= te)
670 		return;
671 	if(inst->hasresp){
672 		e = seprint(e, te, "hasresp: %d\n", inst->hasresp);
673 		if(e >= te)
674 			return;
675 	}
676 	if(inst->isshort){
677 		e = seprint(e, te, "isshort: %d\n", inst->isshort);
678 		if(e >= te)
679 			return;
680 	}
681 	e = seprint(e, te, "islsb: %d\n", inst->islsb);
682 	if(e >= te)
683 		return;
684 
685 	for(i = 0; i < inst->immsz; i++){
686 		e = seprint(e, te, "imm%d: %#2.2ux\n", i, inst->imm[i]);
687 		if(e >= te)
688 			return;
689 	}
690 
691 	if(inst->lensz != 0){
692 		e = seprint(e, te, "lensz: %d\n", inst->lensz);
693 		if(e >= te)
694 			return;
695 		e = seprint(e, te, "len: %d\n", unpacklen(inst));
696 		if(e >= te)
697 			return;
698 		e = seprint(e, te, "datasz: %d\n", inst->datasz);
699 		if(e >= te)
700 			return;
701 		for(i = 0; i < inst->datasz; i++){
702 			e = seprint(e, te, "%#2.2ux ", inst->data[i]);
703 			if(e >= te)
704 				return;
705 		}
706 	}
707 }
708 
709 static void
debpack(Inst * inst)710 debpack(Inst *inst)
711 {
712 	int i;
713 	if(!debug[Dmach] && !debug[DAll])
714 		return;
715 	fprint(2, "%#2.2ux ", inst->opcode);
716 
717 	for(i = 0; i <  inst->immsz; i++)
718 		fprint(2, "%#2.2ux ", inst->imm[i]);
719 	for(i = 0; i <  inst->lensz; i++)
720 		fprint(2, "%#2.2ux ", inst->len[i]);
721 	fprint(2, "\n");
722 	dumpbuf(Dmach, inst->data, inst->datasz);
723 	fprint(2, "\n");
724 }
725 
726 
727 static int
instpack(Mpsse * mpsse,Inst * inst)728 instpack(Mpsse *mpsse, Inst *inst)
729 {
730 	int n;
731 	int sz;
732 	Biobufhdr *bp;
733 
734 	bp = &mpsse->bout;
735 
736 	sz = instpacksz(inst);
737 	if(sz + Bbuffered(bp) > MpsseBufSz){
738 		n = mpsseflush(mpsse);
739 		if(n < 0)
740 			return -1;
741 	}
742 	debpack(inst);
743 	n = Bwrite(bp, &inst->opcode, 1);
744 	if(n < 0)
745 		return -1;
746 	n = Bwrite(bp, inst->imm, inst->immsz);
747 	if(n < 0)
748 		return -1;
749 	n = Bwrite(bp, inst->len, inst->lensz);
750 	if(n < 0)
751 		return -1;
752 	n = Bwrite(bp, inst->data, inst->datasz);
753 	if(n < 0)
754 		return -1;
755 	return 0;
756 }
757 
758 int
pushcmd(Mpsse * mpsse,char * ln)759 pushcmd(Mpsse *mpsse, char *ln)
760 {
761 	Inst *inst;
762 	int res;
763 	char *dmp, *lln;
764 
765 	res = 0;
766 	lln = strdup(ln);
767 	inst = parseassln(lln);
768 	free(lln);
769 
770 	if(inst == nil)
771 		return -1;
772 	if(debug[Dinst]){
773 		dmp = malloc(255);
774 		if(dmp == nil)
775 			return -1;
776 		sdumpinst(dmp, 255, inst);
777 		fprint(2, "%s\n", dmp);
778 		free(dmp);
779 	}
780 
781 	if(instpack(mpsse, inst) < 0)
782 		res = -1;
783 	free(inst);
784 	return res;
785 }
786 
787 int
pushcmdwdata(Mpsse * mpsse,char * ln,uchar * buf,int buflen)788 pushcmdwdata(Mpsse *mpsse, char *ln, uchar *buf, int buflen)
789 {
790 	Inst *inst;
791 	int res;
792 	char *dmp, *lln;
793 
794 	res = 0;
795 	lln = strdup(ln);
796 	inst = parseassln(lln);
797 	free(lln);
798 
799 	if(inst == nil)
800 		return -1;
801 	if(inst->datasz != buflen){
802 		werrstr("wrong data in cmd %d != %d", inst->datasz, buflen);
803 		return -1;
804 	}
805 	memmove(inst->data, buf, inst->datasz);
806 	if(debug[Dinst]){
807 		dmp = malloc(255);
808 		if(dmp == nil)
809 			return -1;
810 		sdumpinst(dmp, 255, inst);
811 		fprint(2, "%s\n", dmp);
812 		free(dmp);
813 	}
814 
815 	if(instpack(mpsse, inst) < 0)
816 		res = -1;
817 	free(inst);
818 	return res;
819 }
820 
821