xref: /minix3/minix/lib/libhgfs/channel.c (revision 433d6423c39e34ec4b79c950597bb2d236f886be)
1*433d6423SLionel Sambuc /* Part of libhgfs - (c) 2009, D.C. van Moolenbroek */
2*433d6423SLionel Sambuc 
3*433d6423SLionel Sambuc #include "inc.h"
4*433d6423SLionel Sambuc 
5*433d6423SLionel Sambuc #define CMD_XFER	0x1E		/* vmware backdoor transfer command */
6*433d6423SLionel Sambuc 
7*433d6423SLionel Sambuc enum {
8*433d6423SLionel Sambuc   XFER_OPEN,				/* open transfer channel */
9*433d6423SLionel Sambuc   XFER_SENDLEN,				/* specify length of data to send */
10*433d6423SLionel Sambuc   XFER_SEND,				/* send data */
11*433d6423SLionel Sambuc   XFER_RECVLEN,				/* get length of data to receive */
12*433d6423SLionel Sambuc   XFER_RECV,				/* receive data */
13*433d6423SLionel Sambuc   XFER_RECVACK,				/* acknowledge receipt of data */
14*433d6423SLionel Sambuc   XFER_CLOSE				/* close transfer channel */
15*433d6423SLionel Sambuc };
16*433d6423SLionel Sambuc 
17*433d6423SLionel Sambuc #define STATUS(p) (HIWORD((p)[2]) & 0xff)
18*433d6423SLionel Sambuc 
19*433d6423SLionel Sambuc /*===========================================================================*
20*433d6423SLionel Sambuc  *				channel_open				     *
21*433d6423SLionel Sambuc  *===========================================================================*/
channel_open(struct channel * ch,u32_t type)22*433d6423SLionel Sambuc int channel_open(
23*433d6423SLionel Sambuc 	struct channel *ch,	/* struct describing the new channel */
24*433d6423SLionel Sambuc 	u32_t type         	/* channel type: CH_IN or CH_OUT */
25*433d6423SLionel Sambuc )
26*433d6423SLionel Sambuc {
27*433d6423SLionel Sambuc /* Open a new backdoor channel. Upon success, the given channel structure will
28*433d6423SLionel Sambuc  * be filled with information and can be used in subsequent channel calls.
29*433d6423SLionel Sambuc  * Return OK on success, or a negative error code on error.
30*433d6423SLionel Sambuc  */
31*433d6423SLionel Sambuc   u32_t ptr[6];
32*433d6423SLionel Sambuc 
33*433d6423SLionel Sambuc   ptr[1] = type | 0x80000000;
34*433d6423SLionel Sambuc   ptr[2] = MAKELONG(CMD_XFER, XFER_OPEN);
35*433d6423SLionel Sambuc 
36*433d6423SLionel Sambuc   backdoor(ptr);
37*433d6423SLionel Sambuc 
38*433d6423SLionel Sambuc   if ((STATUS(ptr) & 1) == 0) return EIO;
39*433d6423SLionel Sambuc 
40*433d6423SLionel Sambuc   ch->id = HIWORD(ptr[3]);
41*433d6423SLionel Sambuc   ch->cookie1 = ptr[4];
42*433d6423SLionel Sambuc   ch->cookie2 = ptr[5];
43*433d6423SLionel Sambuc 
44*433d6423SLionel Sambuc   return OK;
45*433d6423SLionel Sambuc }
46*433d6423SLionel Sambuc 
47*433d6423SLionel Sambuc /*===========================================================================*
48*433d6423SLionel Sambuc  *				channel_close				     *
49*433d6423SLionel Sambuc  *===========================================================================*/
channel_close(struct channel * ch)50*433d6423SLionel Sambuc void channel_close(
51*433d6423SLionel Sambuc 	struct channel *ch	/* backdoor channel to close */
52*433d6423SLionel Sambuc )
53*433d6423SLionel Sambuc {
54*433d6423SLionel Sambuc /* Close a previously opened backdoor channel.
55*433d6423SLionel Sambuc  */
56*433d6423SLionel Sambuc   u32_t ptr[6];
57*433d6423SLionel Sambuc 
58*433d6423SLionel Sambuc   ptr[2] = MAKELONG(CMD_XFER, XFER_CLOSE);
59*433d6423SLionel Sambuc   ptr[3] = MAKELONG(0, ch->id);
60*433d6423SLionel Sambuc   ptr[4] = ch->cookie1;
61*433d6423SLionel Sambuc   ptr[5] = ch->cookie2;
62*433d6423SLionel Sambuc 
63*433d6423SLionel Sambuc   backdoor(ptr);
64*433d6423SLionel Sambuc }
65*433d6423SLionel Sambuc 
66*433d6423SLionel Sambuc /*===========================================================================*
67*433d6423SLionel Sambuc  *				channel_send				     *
68*433d6423SLionel Sambuc  *===========================================================================*/
channel_send(struct channel * ch,char * buf,int len)69*433d6423SLionel Sambuc int channel_send(
70*433d6423SLionel Sambuc 	struct channel *ch,	/* backdoor channel to send to */
71*433d6423SLionel Sambuc 	char *buf,         	/* buffer to send data from */
72*433d6423SLionel Sambuc 	int len            	/* size of the data to send */
73*433d6423SLionel Sambuc )
74*433d6423SLionel Sambuc {
75*433d6423SLionel Sambuc /* Receive data over a backdoor channel. Return OK on success, or a negative
76*433d6423SLionel Sambuc  * error code on error.
77*433d6423SLionel Sambuc  */
78*433d6423SLionel Sambuc   u32_t ptr[7];
79*433d6423SLionel Sambuc 
80*433d6423SLionel Sambuc   ptr[1] = len;
81*433d6423SLionel Sambuc   ptr[2] = MAKELONG(CMD_XFER, XFER_SENDLEN);
82*433d6423SLionel Sambuc   ptr[3] = MAKELONG(0, ch->id);
83*433d6423SLionel Sambuc   ptr[4] = ch->cookie1;
84*433d6423SLionel Sambuc   ptr[5] = ch->cookie2;
85*433d6423SLionel Sambuc 
86*433d6423SLionel Sambuc   backdoor(ptr);
87*433d6423SLionel Sambuc 
88*433d6423SLionel Sambuc   if ((STATUS(ptr) & 1) == 0) return EIO;
89*433d6423SLionel Sambuc 
90*433d6423SLionel Sambuc   if (len == 0) return OK;
91*433d6423SLionel Sambuc 
92*433d6423SLionel Sambuc   ptr[1] = MAKELONG(0, 1);
93*433d6423SLionel Sambuc   ptr[2] = len;
94*433d6423SLionel Sambuc   ptr[3] = MAKELONG(0, ch->id);
95*433d6423SLionel Sambuc   ptr[4] = (u32_t)buf;
96*433d6423SLionel Sambuc   ptr[5] = ch->cookie2;
97*433d6423SLionel Sambuc   ptr[6] = ch->cookie1;
98*433d6423SLionel Sambuc 
99*433d6423SLionel Sambuc   backdoor_out(ptr);
100*433d6423SLionel Sambuc 
101*433d6423SLionel Sambuc   return OK;
102*433d6423SLionel Sambuc }
103*433d6423SLionel Sambuc 
104*433d6423SLionel Sambuc /*===========================================================================*
105*433d6423SLionel Sambuc  *				channel_recv				     *
106*433d6423SLionel Sambuc  *===========================================================================*/
channel_recv(struct channel * ch,char * buf,int max)107*433d6423SLionel Sambuc int channel_recv(
108*433d6423SLionel Sambuc 	struct channel *ch,	/* backdoor channel to receive from */
109*433d6423SLionel Sambuc 	char *buf,         	/* buffer to receive data into */
110*433d6423SLionel Sambuc 	int max            	/* size of the buffer */
111*433d6423SLionel Sambuc )
112*433d6423SLionel Sambuc {
113*433d6423SLionel Sambuc /* Receive data on a backdoor channel. Return the number of bytes received, or
114*433d6423SLionel Sambuc  * a negative error code on error.
115*433d6423SLionel Sambuc  */
116*433d6423SLionel Sambuc   u32_t ptr[7];
117*433d6423SLionel Sambuc   int len;
118*433d6423SLionel Sambuc 
119*433d6423SLionel Sambuc   ptr[2] = MAKELONG(CMD_XFER, XFER_RECVLEN);
120*433d6423SLionel Sambuc   ptr[3] = MAKELONG(0, ch->id);
121*433d6423SLionel Sambuc   ptr[4] = ch->cookie1;
122*433d6423SLionel Sambuc   ptr[5] = ch->cookie2;
123*433d6423SLionel Sambuc 
124*433d6423SLionel Sambuc   backdoor(ptr);
125*433d6423SLionel Sambuc 
126*433d6423SLionel Sambuc   if ((STATUS(ptr) & 0x81) == 0) return EIO;
127*433d6423SLionel Sambuc 
128*433d6423SLionel Sambuc   if ((len = ptr[1]) == 0 || (STATUS(ptr) & 3) == 1) return 0;
129*433d6423SLionel Sambuc 
130*433d6423SLionel Sambuc   if (len > max) return E2BIG;
131*433d6423SLionel Sambuc 
132*433d6423SLionel Sambuc   ptr[1] = MAKELONG(0, 1);
133*433d6423SLionel Sambuc   ptr[2] = len;
134*433d6423SLionel Sambuc   ptr[3] = MAKELONG(0, ch->id);
135*433d6423SLionel Sambuc   ptr[4] = ch->cookie1;
136*433d6423SLionel Sambuc   ptr[5] = (u32_t)buf;
137*433d6423SLionel Sambuc   ptr[6] = ch->cookie2;
138*433d6423SLionel Sambuc 
139*433d6423SLionel Sambuc   backdoor_in(ptr);
140*433d6423SLionel Sambuc 
141*433d6423SLionel Sambuc   ptr[1] = 1;
142*433d6423SLionel Sambuc   ptr[2] = MAKELONG(CMD_XFER, XFER_RECVACK);
143*433d6423SLionel Sambuc   ptr[3] = MAKELONG(0, ch->id);
144*433d6423SLionel Sambuc   ptr[4] = ch->cookie1;
145*433d6423SLionel Sambuc   ptr[5] = ch->cookie2;
146*433d6423SLionel Sambuc 
147*433d6423SLionel Sambuc   backdoor(ptr);
148*433d6423SLionel Sambuc 
149*433d6423SLionel Sambuc   return len;
150*433d6423SLionel Sambuc }
151