xref: /plan9-contrib/sys/src/cmd/aux/vmware/msgchan.c (revision 06d2afa6aa61b39f2ff8184391f0458258bcc86a)
1*06d2afa6SDavid du Colombier #include "all.h"
2*06d2afa6SDavid du Colombier #include <fcall.h>
3*06d2afa6SDavid du Colombier #include <thread.h>
4*06d2afa6SDavid du Colombier #include <9p.h>	/* for emalloc9p */
5*06d2afa6SDavid du Colombier 
6*06d2afa6SDavid du Colombier enum
7*06d2afa6SDavid du Colombier {
8*06d2afa6SDavid du Colombier 	/* high bits of u.cx */
9*06d2afa6SDavid du Colombier 	CmdOpen		= 0x00,
10*06d2afa6SDavid du Colombier 	CmdSendsize	= 0x01,
11*06d2afa6SDavid du Colombier 	CmdSenddata	= 0x02,
12*06d2afa6SDavid du Colombier 	CmdRecvsize	= 0x03,
13*06d2afa6SDavid du Colombier 	CmdRecvdata	= 0x04,
14*06d2afa6SDavid du Colombier 	CmdRecvstatus	= 0x05,
15*06d2afa6SDavid du Colombier 	CmdClose		= 0x06,
16*06d2afa6SDavid du Colombier 
17*06d2afa6SDavid du Colombier 	StatSuccess	= 0x0001,		/* request succeeded */
18*06d2afa6SDavid du Colombier 	StatHavedata	= 0x0002,		/* vmware has message available */
19*06d2afa6SDavid du Colombier 	StatClosed	= 0x0004,		/* channel got closed */
20*06d2afa6SDavid du Colombier 	StatUnsent	= 0x0008,		/* vmware removed message before it got delivered */
21*06d2afa6SDavid du Colombier 	StatChkpt		= 0x0010,		/* checkpoint occurred */
22*06d2afa6SDavid du Colombier 	StatPoweroff	= 0x0020,		/* underlying device is powering off */
23*06d2afa6SDavid du Colombier };
24*06d2afa6SDavid du Colombier 
25*06d2afa6SDavid du Colombier 
26*06d2afa6SDavid du Colombier Msgchan*
openmsg(ulong proto)27*06d2afa6SDavid du Colombier openmsg(ulong proto)
28*06d2afa6SDavid du Colombier {
29*06d2afa6SDavid du Colombier 	Msgchan *c;
30*06d2afa6SDavid du Colombier 	Ureg u;
31*06d2afa6SDavid du Colombier 
32*06d2afa6SDavid du Colombier 	memset(&u, 0, sizeof u);
33*06d2afa6SDavid du Colombier 	u.cx = (CmdOpen<<16) | BackMessage;
34*06d2afa6SDavid du Colombier 	u.bx = proto;
35*06d2afa6SDavid du Colombier 
36*06d2afa6SDavid du Colombier 	backdoor(&u, 0);
37*06d2afa6SDavid du Colombier 
38*06d2afa6SDavid du Colombier fprint(2, "msgopen %.8lux\n", u.cx);
39*06d2afa6SDavid du Colombier 	if(!(u.cx & (StatSuccess<<16))){
40*06d2afa6SDavid du Colombier 		fprint(2, "message %.8lux\n", u.cx);
41*06d2afa6SDavid du Colombier 		werrstr("unable to open message channel (%.8lux)", u.cx);
42*06d2afa6SDavid du Colombier 		return nil;
43*06d2afa6SDavid du Colombier 	}
44*06d2afa6SDavid du Colombier 
45*06d2afa6SDavid du Colombier 	c = emalloc9p(sizeof(*c));
46*06d2afa6SDavid du Colombier 	c->id = u.dx>>16;
47*06d2afa6SDavid du Colombier 	return c;
48*06d2afa6SDavid du Colombier }
49*06d2afa6SDavid du Colombier 
50*06d2afa6SDavid du Colombier enum
51*06d2afa6SDavid du Colombier {
52*06d2afa6SDavid du Colombier 	Ok = 0,
53*06d2afa6SDavid du Colombier 	ErrBad = -1,
54*06d2afa6SDavid du Colombier 	ErrChkpt = -2,
55*06d2afa6SDavid du Colombier };
56*06d2afa6SDavid du Colombier 
57*06d2afa6SDavid du Colombier static int
sendpiece(Msgchan * c,int ty,ulong a)58*06d2afa6SDavid du Colombier sendpiece(Msgchan *c, int ty, ulong a)
59*06d2afa6SDavid du Colombier {
60*06d2afa6SDavid du Colombier 	Ureg u;
61*06d2afa6SDavid du Colombier 
62*06d2afa6SDavid du Colombier 	memset(&u, 0, sizeof u);
63*06d2afa6SDavid du Colombier 	u.cx = (ty<<16) | BackMessage;
64*06d2afa6SDavid du Colombier 	u.dx = c->id<<16;
65*06d2afa6SDavid du Colombier 	u.bx = a;
66*06d2afa6SDavid du Colombier 
67*06d2afa6SDavid du Colombier 	backdoor(&u, 0);
68*06d2afa6SDavid du Colombier 
69*06d2afa6SDavid du Colombier 	if(!(u.cx & (StatSuccess<<16))){
70*06d2afa6SDavid du Colombier fprint(2, "cmd %x failed\n", ty);
71*06d2afa6SDavid du Colombier 		if(u.cx & (StatChkpt<<16))
72*06d2afa6SDavid du Colombier 			return ErrChkpt;
73*06d2afa6SDavid du Colombier 		return ErrBad;
74*06d2afa6SDavid du Colombier 	}
75*06d2afa6SDavid du Colombier 	return 0;
76*06d2afa6SDavid du Colombier }
77*06d2afa6SDavid du Colombier 
78*06d2afa6SDavid du Colombier int
sendmsg(Msgchan * c,void * a,int n)79*06d2afa6SDavid du Colombier sendmsg(Msgchan *c, void *a, int n)
80*06d2afa6SDavid du Colombier {
81*06d2afa6SDavid du Colombier 	int i, m, e, left;
82*06d2afa6SDavid du Colombier 	uchar *p;
83*06d2afa6SDavid du Colombier 	ulong v;
84*06d2afa6SDavid du Colombier 
85*06d2afa6SDavid du Colombier Again:
86*06d2afa6SDavid du Colombier 	v = n;
87*06d2afa6SDavid du Colombier 	if(sendpiece(c, CmdSendsize, v) < 0)
88*06d2afa6SDavid du Colombier 		return -1;
89*06d2afa6SDavid du Colombier 
90*06d2afa6SDavid du Colombier 	p = a;
91*06d2afa6SDavid du Colombier 	left = n;
92*06d2afa6SDavid du Colombier 	while(left > 0){
93*06d2afa6SDavid du Colombier 		m = left;
94*06d2afa6SDavid du Colombier 		if(m > 4)
95*06d2afa6SDavid du Colombier 			m = 4;
96*06d2afa6SDavid du Colombier 		v = 0;
97*06d2afa6SDavid du Colombier 		for(i=0; i<m; i++)
98*06d2afa6SDavid du Colombier 			v |= *p++ << (8*i);
99*06d2afa6SDavid du Colombier 		if((e=sendpiece(c, CmdSenddata, v)) < 0){
100*06d2afa6SDavid du Colombier 			if(e == -2)
101*06d2afa6SDavid du Colombier 				goto Again;
102*06d2afa6SDavid du Colombier 			return -1;
103*06d2afa6SDavid du Colombier 		}
104*06d2afa6SDavid du Colombier 		left -= m;
105*06d2afa6SDavid du Colombier 	}
106*06d2afa6SDavid du Colombier 	return 0;
107*06d2afa6SDavid du Colombier }
108*06d2afa6SDavid du Colombier 
109*06d2afa6SDavid du Colombier static int
recvpiece(Msgchan * c,int ty,ulong * stat,ulong * a)110*06d2afa6SDavid du Colombier recvpiece(Msgchan *c, int ty, ulong *stat, ulong *a)
111*06d2afa6SDavid du Colombier {
112*06d2afa6SDavid du Colombier 	Ureg u;
113*06d2afa6SDavid du Colombier 
114*06d2afa6SDavid du Colombier fprint(2, "recvpiece %d %d\n", c->id, ty);
115*06d2afa6SDavid du Colombier 	memset(&u, 0, sizeof u);
116*06d2afa6SDavid du Colombier 	u.cx = (ty<<16) | BackMessage;
117*06d2afa6SDavid du Colombier 	u.bx = StatSuccess;
118*06d2afa6SDavid du Colombier 	u.dx = c->id<<16;
119*06d2afa6SDavid du Colombier 
120*06d2afa6SDavid du Colombier 	backdoor(&u, 0);
121*06d2afa6SDavid du Colombier 
122*06d2afa6SDavid du Colombier 	if(!(u.cx & (StatSuccess<<16))){
123*06d2afa6SDavid du Colombier fprint(2, "no success %lux\n", u.cx);
124*06d2afa6SDavid du Colombier 		if(u.cx & (StatChkpt<<16))
125*06d2afa6SDavid du Colombier 			return ErrChkpt;
126*06d2afa6SDavid du Colombier 		return ErrBad;
127*06d2afa6SDavid du Colombier 	}
128*06d2afa6SDavid du Colombier 	*stat = u.cx;
129*06d2afa6SDavid du Colombier 	if(ty == CmdRecvsize && !(u.cx&(StatHavedata<<16))){
130*06d2afa6SDavid du Colombier fprint(2, "poll got no data\n");
131*06d2afa6SDavid du Colombier 		return 0;
132*06d2afa6SDavid du Colombier 	}
133*06d2afa6SDavid du Colombier 
134*06d2afa6SDavid du Colombier 	if(ty != CmdRecvstatus && (u.dx>>16) != ty-2){
135*06d2afa6SDavid du Colombier fprint(2, "got wrong answer! %lux\n", u.dx);
136*06d2afa6SDavid du Colombier 		werrstr("protocol error");
137*06d2afa6SDavid du Colombier 		return ErrBad;
138*06d2afa6SDavid du Colombier 	}
139*06d2afa6SDavid du Colombier 	*a = u.bx;
140*06d2afa6SDavid du Colombier fprint(2, "got %lux\n", *a);
141*06d2afa6SDavid du Colombier 	return 0;
142*06d2afa6SDavid du Colombier }
143*06d2afa6SDavid du Colombier 
144*06d2afa6SDavid du Colombier static void
signalerror(Msgchan * c,int ty)145*06d2afa6SDavid du Colombier signalerror(Msgchan *c, int ty)
146*06d2afa6SDavid du Colombier {
147*06d2afa6SDavid du Colombier 	Ureg u;
148*06d2afa6SDavid du Colombier 
149*06d2afa6SDavid du Colombier 	memset(&u, 0, sizeof u);
150*06d2afa6SDavid du Colombier 	u.cx = (ty<<16) | BackMessage;
151*06d2afa6SDavid du Colombier 	u.dx = c->id<<16;
152*06d2afa6SDavid du Colombier 	u.bx = 0;
153*06d2afa6SDavid du Colombier 	backdoor(&u, 0);
154*06d2afa6SDavid du Colombier }
155*06d2afa6SDavid du Colombier 
156*06d2afa6SDavid du Colombier int
recvmsg(Msgchan * c,void ** pp)157*06d2afa6SDavid du Colombier recvmsg(Msgchan *c, void **pp)
158*06d2afa6SDavid du Colombier {
159*06d2afa6SDavid du Colombier 	int left;
160*06d2afa6SDavid du Colombier 	ulong v, stat, tot;
161*06d2afa6SDavid du Colombier 	uchar *p;
162*06d2afa6SDavid du Colombier 
163*06d2afa6SDavid du Colombier Top:
164*06d2afa6SDavid du Colombier 	if(recvpiece(c, CmdRecvsize, &stat, &tot) < 0)
165*06d2afa6SDavid du Colombier 		return -1;
166*06d2afa6SDavid du Colombier 
167*06d2afa6SDavid du Colombier 	if(!(stat & (StatHavedata<<16)))
168*06d2afa6SDavid du Colombier 		return 0;
169*06d2afa6SDavid du Colombier 
170*06d2afa6SDavid du Colombier 	free(c->a);
171*06d2afa6SDavid du Colombier 	c->a = emalloc9p(tot+5);
172*06d2afa6SDavid du Colombier 	c->na = tot;
173*06d2afa6SDavid du Colombier 	p = c->a;		/* NUL terminate for callers */
174*06d2afa6SDavid du Colombier 
175*06d2afa6SDavid du Colombier 	left = tot;
176*06d2afa6SDavid du Colombier 	while(left > 0){
177*06d2afa6SDavid du Colombier 		switch(recvpiece(c, CmdRecvdata, &stat, &v)){
178*06d2afa6SDavid du Colombier 		case ErrChkpt:
179*06d2afa6SDavid du Colombier 			goto Top;
180*06d2afa6SDavid du Colombier 		case ErrBad:
181*06d2afa6SDavid du Colombier 			signalerror(c, CmdRecvdata);
182*06d2afa6SDavid du Colombier 			return -1;
183*06d2afa6SDavid du Colombier 		}
184*06d2afa6SDavid du Colombier 		*(uint*)p = v;
185*06d2afa6SDavid du Colombier 		p += 4;
186*06d2afa6SDavid du Colombier 		left -= 4;
187*06d2afa6SDavid du Colombier 	}
188*06d2afa6SDavid du Colombier 	((char*)c->a)[tot] = '\0';
189*06d2afa6SDavid du Colombier 
190*06d2afa6SDavid du Colombier 	switch(recvpiece(c, CmdRecvstatus, &stat, &v)){
191*06d2afa6SDavid du Colombier 	case ErrChkpt:
192*06d2afa6SDavid du Colombier 		goto Top;
193*06d2afa6SDavid du Colombier 	case ErrBad:
194*06d2afa6SDavid du Colombier 		/* BUG: signal receipt of error */
195*06d2afa6SDavid du Colombier 		signalerror(c, CmdRecvstatus);
196*06d2afa6SDavid du Colombier 		return -1;
197*06d2afa6SDavid du Colombier 	}
198*06d2afa6SDavid du Colombier 
199*06d2afa6SDavid du Colombier 	*pp = c->a;
200*06d2afa6SDavid du Colombier 	return tot;
201*06d2afa6SDavid du Colombier }
202*06d2afa6SDavid du Colombier 
203*06d2afa6SDavid du Colombier int
closemsg(Msgchan * c)204*06d2afa6SDavid du Colombier closemsg(Msgchan *c)
205*06d2afa6SDavid du Colombier {
206*06d2afa6SDavid du Colombier 	Ureg u;
207*06d2afa6SDavid du Colombier 
208*06d2afa6SDavid du Colombier 	memset(&u, 0, sizeof u);
209*06d2afa6SDavid du Colombier 
210*06d2afa6SDavid du Colombier 	u.cx = (CmdClose<<16) | BackMessage;
211*06d2afa6SDavid du Colombier 	u.dx = c->id;
212*06d2afa6SDavid du Colombier 
213*06d2afa6SDavid du Colombier 	backdoor(&u, 0);
214*06d2afa6SDavid du Colombier 
215*06d2afa6SDavid du Colombier 	if(!(u.cx & (StatSuccess<<16))){
216*06d2afa6SDavid du Colombier 		werrstr("unable to close message channel");
217*06d2afa6SDavid du Colombier 		return -1;
218*06d2afa6SDavid du Colombier 	}
219*06d2afa6SDavid du Colombier 
220*06d2afa6SDavid du Colombier 	free(c->a);
221*06d2afa6SDavid du Colombier 	c->a = nil;
222*06d2afa6SDavid du Colombier 	free(c);
223*06d2afa6SDavid du Colombier 	return 0;
224*06d2afa6SDavid du Colombier }
225