1 /*****************************************************************************\
2
3 mlc.c - MLC support for multi-point tranport driver
4
5 (c) 2004-2007 Copyright HP Development Company, LP
6
7 Permission is hereby granted, free of charge, to any person obtaining a copy
8 of this software and associated documentation files (the "Software"), to deal
9 in the Software without restriction, including without limitation the rights
10 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
11 of the Software, and to permit persons to whom the Software is furnished to do
12 so, subject to the following conditions:
13
14 The above copyright notice and this permission notice shall be included in all
15 copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
19 FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
20 COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21 IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
24 \*****************************************************************************/
25
26 #include "hpmud.h"
27 #include "hpmudi.h"
28
cut_buf(mud_channel * pc,char * buf,int size)29 int __attribute__ ((visibility ("hidden"))) cut_buf(mud_channel *pc, char *buf, int size)
30 {
31 int len;
32
33 if (pc->rcnt > size)
34 {
35 /* Return part of rbuf. */
36 len = size;
37 memcpy(buf, &pc->rbuf[pc->rindex], len);
38 pc->rindex += len;
39 pc->rcnt -= len;
40 }
41 else
42 {
43 /* Return all of rbuf. */
44 len = pc->rcnt;
45 memcpy(buf, &pc->rbuf[pc->rindex], len);
46 pc->rindex = pc->rcnt = 0;
47 }
48
49 return len;
50 }
51
52 /* Write command reply back to peripheral. */
MlcForwardReply(mud_channel * pc,int fd,unsigned char * buf,int size)53 static int MlcForwardReply(mud_channel *pc, int fd, unsigned char *buf, int size)
54 {
55 mud_device *pd = &msp->device[pc->dindex];
56 int len=0;
57
58 if ((len = (pd->vf.write)(fd, buf, size, HPMUD_EXCEPTION_TIMEOUT)) != size)
59 {
60 BUG("unable to MlcForwarReply: %m\n");
61 }
62 return len;
63 }
64
65 /* Execute command from peripheral. */
MlcExecReverseCmd(mud_channel * pc,int fd,unsigned char * buf)66 static int MlcExecReverseCmd(mud_channel *pc, int fd, unsigned char *buf)
67 {
68 mud_device *pd = &msp->device[pc->dindex];
69 mud_channel *out_of_bound_channel;
70 MLCCmd *pCmd;
71 MLCReply *pReply;
72 MLCCredit *pCredit;
73 MLCCreditReply *pCreditReply;
74 MLCCreditRequest *pCreditReq;
75 MLCCreditRequestReply *pCreditReqReply;
76 MLCError *pError;
77 int len, size;
78 static int cnt;
79
80 pCmd = (MLCCmd *)buf;
81
82 /* See if this packet is a command packet. */
83 if (!(pCmd->h.hsid == 0 && pCmd->h.psid == 0))
84 {
85 if (pCmd->h.hsid == pCmd->h.psid)
86 {
87 /* Got a valid data packet handle it. This can happen when channel_read timeouts and p2hcredit=1. */
88 out_of_bound_channel = &pd->channel[pCmd->h.hsid];
89
90 if (out_of_bound_channel->ta.p2hcredit <= 0)
91 {
92 BUG("invalid data packet credit=%d\n", out_of_bound_channel->ta.p2hcredit);
93 return 0;
94 }
95
96 size = ntohs(pCmd->h.length) - sizeof(MLCHeader);
97 if (size > (HPMUD_BUFFER_SIZE - out_of_bound_channel->rcnt))
98 {
99 BUG("invalid data packet size=%d\n", size);
100 return 0;
101 }
102 memcpy(&out_of_bound_channel->rbuf[out_of_bound_channel->rcnt], buf+sizeof(MLCHeader), size);
103 out_of_bound_channel->rcnt += size;
104 if (pCmd->h.credit)
105 out_of_bound_channel->ta.h2pcredit += pCmd->h.credit; /* note, piggy back credit is 1 byte wide */
106 out_of_bound_channel->ta.p2hcredit--; /* one data packet was read, decrement credit count */
107 }
108 else
109 {
110 len = ntohs(pCmd->h.length);
111 BUG("unsolicited data packet: hsid=%x, psid=%x, length=%d, credit=%d, status=%x\n", pCmd->h.hsid,
112 pCmd->h.psid, len, pCmd->h.credit, pCmd->h.status);
113 DBG_DUMP(buf, len);
114 }
115 return 0;
116 }
117
118 /* Process any command. */
119 switch (pCmd->cmd)
120 {
121 case MLC_CREDIT:
122 pCredit = (MLCCredit *)buf;
123 out_of_bound_channel = &pd->channel[pCredit->hsocket];
124 out_of_bound_channel->ta.h2pcredit += ntohs(pCredit->credit);
125 pCreditReply = (MLCCreditReply *)buf;
126 pCreditReply->h.length = htons(sizeof(MLCCreditReply));
127 pCreditReply->cmd |= 0x80;
128 pCreditReply->result = 0;
129 MlcForwardReply(pc, fd, (unsigned char *)pCreditReply, sizeof(MLCCreditReply));
130 break;
131 case MLC_CREDIT_REQUEST:
132 pCreditReq = (MLCCreditRequest *)buf;
133 if (cnt++ < 5)
134 BUG("unexpected MLCCreditRequest: cmd=%x, hid=%x, pid=%x, credit=%d\n", pCreditReq->cmd,
135 pCreditReq->hsocket, pCreditReq->psocket, ntohs(pCreditReq->credit));
136 pCreditReqReply = (MLCCreditRequestReply *)buf;
137 pCreditReqReply->h.length = htons(sizeof(MLCCreditRequestReply));
138 pCreditReqReply->cmd |= 0x80;
139 pCreditReqReply->result = 0;
140 pCreditReqReply->credit = 0;
141 MlcForwardReply(pc, fd, (unsigned char *)pCreditReqReply, sizeof(MLCCreditRequestReply));
142 break;
143 case MLC_ERROR:
144 pError = (MLCError *)buf;
145 BUG("unexpected MLCError: cmd=%x, result=%x\n", pError->cmd, pError->result);
146 return 1;
147 default:
148 pReply = (MLCReply *)buf;
149 BUG("unexpected command: cmd=%x, result=%x\n", pReply->cmd, pReply->result);
150 pReply->h.length = htons(sizeof(MLCReply));
151 pReply->cmd |= 0x80;
152 pReply->result = 1;
153 MlcForwardReply(pc, fd, (unsigned char *)pReply, sizeof(MLCReply));
154 break;
155 }
156 return 0;
157 }
158
159 /* Get command from peripheral and processes the reverse command. */
MlcReverseCmd(mud_channel * pc,int fd)160 int __attribute__ ((visibility ("hidden"))) MlcReverseCmd(mud_channel *pc, int fd)
161 {
162 mud_device *pd = &msp->device[pc->dindex];
163 unsigned char buf[HPMUD_BUFFER_SIZE];
164 int stat=0, len, size;
165 unsigned int pklen;
166 unsigned char *pBuf;
167 MLCReply *pPk;
168
169 pPk = (MLCReply *)buf;
170
171 pBuf = buf;
172
173 /* Read packet header. */
174 size = sizeof(MLCHeader);
175 while (size > 0)
176 {
177 if ((len = (pd->vf.read)(fd, pBuf, size, HPMUD_EXCEPTION_TIMEOUT)) < 0)
178 {
179 BUG("unable to read MlcReverseCmd header: %m\n");
180 stat = 1;
181 goto bugout;
182 }
183 size-=len;
184 pBuf+=len;
185 }
186
187 /* Determine packet size. */
188 if ((pklen = ntohs(pPk->h.length)) > sizeof(buf))
189 {
190 BUG("invalid MlcReverseCmd packet size: size=%d\n", pklen);
191 stat = 1;
192 goto bugout;
193 }
194
195 /* Read packet data field. */
196 size = pklen - sizeof(MLCHeader);
197 while (size > 0)
198 {
199 if ((len = (pd->vf.read)(fd, pBuf, size, HPMUD_EXCEPTION_TIMEOUT)) < 0)
200 {
201 BUG("unable to read MlcReverseCmd data: %m\n");
202 stat = 1;
203 goto bugout;
204 }
205 size-=len;
206 pBuf+=len;
207 }
208
209 stat = MlcExecReverseCmd(pc, fd, buf);
210
211 bugout:
212 return stat;
213 }
214
215 /*
216 * Get command reply from peripheral. Waits for reply then returns. Processes any reverse commands
217 * while waiting for a reply.
218 */
MlcReverseReply(mud_channel * pc,int fd,unsigned char * buf,int bufsize)219 static int MlcReverseReply(mud_channel *pc, int fd, unsigned char *buf, int bufsize)
220 {
221 mud_device *pd = &msp->device[pc->dindex];
222 int stat=0, len, size, pklen;
223 unsigned char *pBuf;
224 MLCReply *pPk;
225
226 pPk = (MLCReply *)buf;
227
228 while (1)
229 {
230 pBuf = buf;
231
232 /* Read packet header. */
233 size = sizeof(MLCHeader);
234 while (size > 0)
235 {
236 if ((len = (pd->vf.read)(fd, pBuf, size, 4000000)) < 0) /* wait 4 seconds, same as dot4 */
237 {
238 BUG("unable to read MlcReverseReply header: %m bytesRead=%zd\n", sizeof(MLCHeader)-size);
239 stat = 2; /* short timeout */
240 goto bugout;
241 }
242 size-=len;
243 pBuf+=len;
244 }
245
246 /* Determine packet size. */
247 pklen = ntohs(pPk->h.length);
248 if (pklen < 0 || pklen > bufsize)
249 {
250 BUG("invalid MlcReverseReply packet size: size=%d, buf=%d\n", pklen, bufsize);
251 stat = 1;
252 goto bugout;
253 }
254
255 if (pklen == 0)
256 {
257 /* Got invalid MLC header from peripheral, try this "off-by-one" firmware hack (ie: OJ600). */
258 BUG("trying MlcReverseReply firmware hack\n");
259 memcpy(buf, &buf[1], sizeof(MLCHeader)-1);
260 pklen = ntohs(pPk->h.length);
261 if (pklen <= 0 || pklen > bufsize)
262 {
263 BUG("invalid MlcReverseReply packet size: size=%d, buf=%d\n", pklen, bufsize);
264 stat = 1;
265 goto bugout;
266 }
267 if ((len = (pd->vf.read)(fd, --pBuf, 1, 1000000)) < 0) /* wait 1 second */
268 {
269 BUG("unable to read MlcReverseReply header: %m\n");
270 stat = 1;
271 goto bugout;
272 }
273 pBuf++;
274 DBG_DUMP(buf, sizeof(MLCHeader));
275 }
276
277 /* Read packet data field. */
278 size = pklen - sizeof(MLCHeader);
279 while (size > 0)
280 {
281 if ((len = (pd->vf.read)(fd, pBuf, size, HPMUD_EXCEPTION_TIMEOUT)) < 0)
282 {
283 BUG("unable to read MlcReverseReply data: %m exp=%zd act=%zd\n", pklen-sizeof(MLCHeader), pklen-sizeof(MLCHeader)-size);
284 stat = 1;
285 goto bugout;
286 }
287 size-=len;
288 pBuf+=len;
289 }
290
291 /* Check for reply. */
292 if (pPk->cmd & 0x80)
293 break;
294
295 stat = MlcExecReverseCmd(pc, fd, buf);
296
297 if (stat != 0)
298 break;
299
300 } /* while (1) */
301
302 bugout:
303 return stat;
304 }
305
MlcInit(mud_channel * pc,int fd)306 int __attribute__ ((visibility ("hidden"))) MlcInit(mud_channel *pc, int fd)
307 {
308 mud_device *pd = &msp->device[pc->dindex];
309 unsigned char buf[HPMUD_BUFFER_SIZE];
310 int stat=0, len, n, cnt;
311 MLCInit *pCmd;
312 MLCInitReply *pReply;
313
314 memset(buf, 0, sizeof(MLCInit));
315 pCmd = (MLCInit *)buf;
316 n = sizeof(MLCInit);
317 pCmd->h.length = htons(n);
318 pCmd->cmd = MLC_INIT;
319 pCmd->rev = 3;
320
321 if ((len = (pd->vf.write)(fd, pCmd, n, HPMUD_EXCEPTION_TIMEOUT)) != n)
322 {
323 BUG("unable to write MLCInit: %m\n");
324 stat = 1;
325 goto bugout;
326 }
327
328 cnt=0;
329 while(1)
330 {
331 stat = MlcReverseReply(pc, fd, buf, sizeof(buf));
332 pReply = (MLCInitReply *)buf;
333
334 if ((stat != 0) || (pReply->cmd != (0x80 | MLC_INIT)) || (pReply->result != 0))
335 {
336 if (errno == EIO && cnt<1)
337 {
338 /* hack for usblp.c 2.6.5 */
339 BUG("invalid MLCInitReply retrying...\n");
340 sleep(1);
341 cnt++;
342 continue;
343 }
344 if (stat == 2 && cnt<1)
345 {
346 /* hack for Tahoe */
347 BUG("invalid MLCInitReply retrying command...\n");
348 memset(buf, 0, sizeof(MLCInit));
349 n = sizeof(MLCInit);
350 pCmd->h.length = htons(n);
351 pCmd->cmd = MLC_INIT;
352 pCmd->rev = 3;
353 (pd->vf.write)(fd, pCmd, n, HPMUD_EXCEPTION_TIMEOUT);
354 cnt++;
355 continue;
356 }
357 BUG("invalid MLCInitReply: cmd=%x, result=%x\n, revision=%x\n", pReply->cmd, pReply->result, pReply->rev);
358 stat = 1;
359 goto bugout;
360 }
361 break;
362 }
363
364 bugout:
365 return stat;
366 }
367
MlcExit(mud_channel * pc,int fd)368 int __attribute__ ((visibility ("hidden"))) MlcExit(mud_channel *pc, int fd)
369 {
370 mud_device *pd = &msp->device[pc->dindex];
371 unsigned char buf[HPMUD_BUFFER_SIZE];
372 int stat=0, len, n;
373 MLCExit *pCmd;
374 MLCExitReply *pReply;
375
376 memset(buf, 0, sizeof(MLCExit));
377 pCmd = (MLCExit *)buf;
378 n = sizeof(MLCExit);
379 pCmd->h.length = htons(n);
380 pCmd->cmd = MLC_EXIT;
381
382 if ((len = (pd->vf.write)(fd, pCmd, n, HPMUD_EXCEPTION_TIMEOUT)) != n)
383 {
384 BUG("unable to write MLCExit: %m\n");
385 stat = 1;
386 goto bugout;
387 }
388
389 stat = MlcReverseReply(pc, fd, buf, sizeof(buf));
390 pReply = (MLCExitReply *)buf;
391
392 if ((stat != 0) || (pReply->cmd != (0x80 | MLC_EXIT)) || (pReply->result != 0))
393 {
394 BUG("invalid MLCExitReply: cmd=%x, result=%x\n", pReply->cmd, pReply->result);
395 stat = 1;
396 goto bugout;
397 }
398
399 bugout:
400 return stat;
401 }
402
MlcConfigSocket(mud_channel * pc,int fd)403 int __attribute__ ((visibility ("hidden"))) MlcConfigSocket(mud_channel *pc, int fd)
404 {
405 mud_device *pd = &msp->device[pc->dindex];
406 unsigned char buf[HPMUD_BUFFER_SIZE];
407 int stat=0, len, n;
408 MLCConfigSocket *pCmd;
409 MLCConfigSocketReply *pReply;
410
411 if (pc->ta.h2psize > 0)
412 return stat; /* already got host/peripheral packet sizes */
413
414 memset(buf, 0, sizeof(MLCConfigSocket));
415 pCmd = (MLCConfigSocket *)buf;
416 n = sizeof(MLCConfigSocket);
417 pCmd->h.length = htons(n);
418 pCmd->cmd = MLC_CONFIG_SOCKET;
419 pCmd->socket = pc->sockid;
420 pCmd->h2psize = htons(HPMUD_BUFFER_SIZE);
421 pCmd->p2hsize = htons(HPMUD_BUFFER_SIZE);
422 pCmd->status = 0; /* status level?? */
423
424 if ((len = (pd->vf.write)(fd, pCmd, n, HPMUD_EXCEPTION_TIMEOUT)) != n)
425 {
426 BUG("unable to write MLCConfigSocket: %m\n");
427 stat = 1;
428 goto bugout;
429 }
430
431 stat = MlcReverseReply(pc, fd, buf, sizeof(buf));
432 pReply = (MLCConfigSocketReply *)buf;
433
434 if ((stat != 0) || (pReply->cmd != (0x80 | MLC_CONFIG_SOCKET)) || (pReply->result != 0))
435 {
436 BUG("invalid MLCConfigSocketReply: cmd=%x, result=%x\n", pReply->cmd, pReply->result);
437 stat = 1;
438 goto bugout;
439 }
440
441 pc->ta.h2psize = ntohs(pReply->h2psize);
442 pc->ta.p2hsize = ntohs(pReply->p2hsize);
443
444 bugout:
445 return stat;
446 }
447
448 /* Write data to peripheral. */
MlcForwardData(mud_channel * pc,int fd,const void * buf,int size,int usec_timeout)449 int __attribute__ ((visibility ("hidden"))) MlcForwardData(mud_channel *pc, int fd, const void *buf, int size, int usec_timeout)
450 {
451 mud_device *pd = &msp->device[pc->dindex];
452 int stat=0, len, n;
453 MLCHeader h;
454
455 memset(&h, 0, sizeof(h));
456 n = sizeof(MLCHeader) + size;
457 h.length = htons(n);
458 h.hsid = pc->sockid;
459 h.psid = pc->sockid;
460
461 if ((len = (pd->vf.write)(fd, &h, sizeof(MLCHeader), usec_timeout)) != sizeof(MLCHeader))
462 {
463 BUG("unable to write MlcForwardData header: %m\n");
464 stat = 1;
465 goto bugout;
466 }
467
468 if ((len = (pd->vf.write)(fd, buf, size, usec_timeout)) != size)
469 {
470 BUG("unable to write MlcForwardData: %m\n");
471 stat = 1;
472 goto bugout;
473 }
474
475 bugout:
476 return stat;
477 }
478
479 /* Read data from peripheral. */
MlcReverseData(mud_channel * pc,int fd,void * buf,int length,int usec_timeout)480 int __attribute__ ((visibility ("hidden"))) MlcReverseData(mud_channel *pc, int fd, void *buf, int length, int usec_timeout)
481 {
482 mud_device *pd = &msp->device[pc->dindex];
483 mud_channel *out_of_bound_channel;
484 int len, size, total;
485 MLCHeader *pPk;
486
487 pPk = (MLCHeader *)buf;
488
489 while (1)
490 {
491 total = 0;
492
493 /* Read packet header. */
494 size = sizeof(MLCHeader);
495 while (size > 0)
496 {
497 /* Use requested client timeout until we start reading. */
498 if (total == 0)
499 len = (pd->vf.read)(fd, buf+total, size, usec_timeout);
500 else
501 len = (pd->vf.read)(fd, buf+total, size, HPMUD_EXCEPTION_TIMEOUT);
502
503 if (len < 0)
504 {
505 /* Got a timeout, if exception timeout or timeout occured after read started thats an error. */
506 if (usec_timeout >= HPMUD_EXCEPTION_TIMEOUT || total > 0)
507 BUG("unable to read MlcReverseData header: %m %s\n", pd->uri);
508 goto bugout;
509 }
510 size-=len;
511 total+=len;
512 }
513
514 /* Determine data size. */
515 size = ntohs(pPk->length) - sizeof(MLCHeader);
516
517 if (size > length)
518 {
519 BUG("invalid MlcReverseData size: size=%d, buf=%d\n", size, length);
520 goto bugout;
521 }
522
523 /* Make sure data packet is for this channel. */
524 if (pPk->hsid != pc->sockid && pPk->psid != pc->sockid)
525 {
526 if (pPk->hsid == 0 && pPk->psid == 0)
527 {
528 /* Ok, got a command channel packet instead of a data packet, handle it... */
529 while (size > 0)
530 {
531 if ((len = (pd->vf.read)(fd, buf+total, size, HPMUD_EXCEPTION_TIMEOUT)) < 0)
532 {
533 BUG("unable to read MlcReverseData command: %m\n");
534 goto bugout;
535 }
536 size-=len;
537 total=len;
538 }
539 MlcExecReverseCmd(pc, fd, buf);
540 continue; /* try again for data packet */
541 }
542 else if (pPk->hsid == pPk->psid)
543 {
544 /* Got a valid data packet for another channel handle it. This can happen when ReadData timeouts and p2hcredit=1. */
545 out_of_bound_channel = &pd->channel[pPk->hsid];
546 unsigned char *pBuf;
547
548 if (out_of_bound_channel->ta.p2hcredit <= 0)
549 {
550 BUG("invalid data packet credit=%d\n", out_of_bound_channel->ta.p2hcredit);
551 goto bugout;
552 }
553
554 if (size > (HPMUD_BUFFER_SIZE - out_of_bound_channel->rcnt))
555 {
556 BUG("invalid data packet size=%d\n", size);
557 goto bugout;
558 }
559
560 total = 0;
561 pBuf = &out_of_bound_channel->rbuf[out_of_bound_channel->rcnt];
562 while (size > 0)
563 {
564 if ((len = (pd->vf.read)(fd, pBuf+total, size, HPMUD_EXCEPTION_TIMEOUT)) < 0)
565 {
566 BUG("unable to read MlcReverseData: %m\n");
567 goto bugout;
568 }
569 size-=len;
570 total+=len;
571 }
572
573 out_of_bound_channel->rcnt += total;
574 if (pPk->credit)
575 out_of_bound_channel->ta.h2pcredit += pPk->credit; /* note, piggy back credit is 1 byte wide */
576 out_of_bound_channel->ta.p2hcredit--; /* one data packet was read, decrement credit count */
577 continue; /* try again for data packet */
578 }
579 else
580 {
581 MLCCmd *pCmd = (MLCCmd *)buf;
582 BUG("invalid MlcReverseData state: exp hsid=%x, act hsid=%x, psid=%x, length=%d, credit=%d, status=%x, cmd=%x\n", pc->sockid,
583 pPk->hsid, pPk->psid, ntohs(pPk->length), pPk->credit, pPk->status, pCmd->cmd);
584 goto bugout;
585 }
586 }
587
588 if (pPk->credit)
589 {
590 pc->ta.h2pcredit += pPk->credit; /* note, piggy back credit is 1 byte wide */
591 }
592
593 total = 0; /* eat packet header */
594
595 /* Read packet data field with exception_timeout. */
596 while (size > 0)
597 {
598 if ((len = (pd->vf.read)(fd, buf+total, size, HPMUD_EXCEPTION_TIMEOUT)) < 0)
599 {
600 BUG("unable to read MlcReverseData: %m\n");
601 goto bugout;
602 }
603 size-=len;
604 total+=len;
605 }
606 break; /* done reading data packet */
607 } /* while (1) */
608
609 bugout:
610 return total;
611 }
612
MlcOpenChannel(mud_channel * pc,int fd)613 int __attribute__ ((visibility ("hidden"))) MlcOpenChannel(mud_channel *pc, int fd)
614 {
615 mud_device *pd = &msp->device[pc->dindex];
616 unsigned char buf[HPMUD_BUFFER_SIZE];
617 int stat=0, len, n;
618 MLCOpenChannel *pCmd;
619 MLCOpenChannelReply *pReply;
620
621 memset(buf, 0, sizeof(MLCOpenChannel));
622 pCmd = (MLCOpenChannel *)buf;
623 n = sizeof(MLCOpenChannel);
624 pCmd->h.length = htons(n);
625 pCmd->cmd = MLC_OPEN_CHANNEL;
626 pCmd->hsocket = pc->sockid; /* assume static socket ids */
627 pCmd->psocket = pc->sockid;
628 pCmd->credit = htons(0); /* credit sender will accept from receiver (set by MlcDevice::ReadData) */
629 // SetH2PCredit(0); /* initialize sender to receiver credit */
630
631 if ((len = (pd->vf.write)(fd, pCmd, n, HPMUD_EXCEPTION_TIMEOUT)) != n)
632 {
633 BUG("unable to write MlcOpenChannel: %m\n");
634 stat = 1;
635 goto bugout;
636 }
637
638 stat = MlcReverseReply(pc, fd, buf, sizeof(buf));
639 pReply = (MLCOpenChannelReply *)buf;
640
641 if ((stat != 0) || (pReply->cmd != (0x80 | MLC_OPEN_CHANNEL)) || (pReply->result != 0))
642 {
643 BUG("invalid MlcOpenChannelReply: cmd=%x, result=%x\n", pReply->cmd, pReply->result);
644 stat = 1;
645 goto bugout;
646 }
647
648 pc->ta.h2pcredit = ntohs(pReply->credit);
649
650 bugout:
651 return stat;
652 }
653
MlcCloseChannel(mud_channel * pc,int fd)654 int __attribute__ ((visibility ("hidden"))) MlcCloseChannel(mud_channel *pc, int fd)
655 {
656 mud_device *pd = &msp->device[pc->dindex];
657 unsigned char buf[HPMUD_BUFFER_SIZE];
658 int stat=0, len, n;
659 MLCCloseChannel *pCmd;
660 MLCCloseChannelReply *pReply;
661
662 memset(buf, 0, sizeof(MLCCloseChannel));
663 pCmd = (MLCCloseChannel *)buf;
664 n = sizeof(MLCCloseChannel);
665 pCmd->h.length = htons(n);
666 pCmd->cmd = MLC_CLOSE_CHANNEL;
667 pCmd->hsocket = pc->sockid; /* assume static socket ids */
668 pCmd->psocket = pc->sockid;
669
670 if ((len = (pd->vf.write)(fd, pCmd, n, HPMUD_EXCEPTION_TIMEOUT)) != n)
671 {
672 BUG("unable to write MlcCloseChannel: %m\n");
673 stat = 1;
674 goto bugout;
675 }
676
677 stat = MlcReverseReply(pc, fd, buf, sizeof(buf));
678 pReply = (MLCCloseChannelReply *)buf;
679
680 if ((stat != 0) || (pReply->cmd != (0x80 | MLC_CLOSE_CHANNEL)) || (pReply->result != 0))
681 {
682 BUG("invalid MlcCloseChannelReply: cmd=%x, result=%x\n", pReply->cmd, pReply->result);
683 stat = 1;
684 goto bugout;
685 }
686
687 bugout:
688 return stat;
689 }
690
MlcCredit(mud_channel * pc,int fd,unsigned short credit)691 int __attribute__ ((visibility ("hidden"))) MlcCredit(mud_channel *pc, int fd, unsigned short credit)
692 {
693 mud_device *pd = &msp->device[pc->dindex];
694 unsigned char buf[HPMUD_BUFFER_SIZE];
695 int stat=0, len, n;
696 MLCCredit *pCmd;
697 MLCCreditReply *pReply;
698
699 memset(buf, 0, sizeof(MLCCredit));
700 pCmd = (MLCCredit *)buf;
701 n = sizeof(MLCCredit);
702 pCmd->h.length = htons(n);
703 pCmd->cmd = MLC_CREDIT;
704 pCmd->hsocket = pc->sockid; /* assume static socket ids */
705 pCmd->psocket = pc->sockid;
706 pCmd->credit = htons(credit); /* set peripheral to host credit */
707
708 if ((len = (pd->vf.write)(fd, pCmd, n, HPMUD_EXCEPTION_TIMEOUT)) != n)
709 {
710 BUG("unable to write MlcCredit: %m\n");
711 stat = 1;
712 goto bugout;
713 }
714
715 stat = MlcReverseReply(pc, fd, buf, sizeof(buf));
716 pReply = (MLCCreditReply *)buf;
717
718 if ((stat != 0) || (pReply->cmd != (0x80 | MLC_CREDIT)) || (pReply->result != 0))
719 {
720 BUG("invalid MlcCreditReply: cmd=%x, result=%x\n", pReply->cmd, pReply->result);
721 stat = 1;
722 goto bugout;
723 }
724
725 pc->ta.p2hcredit += credit;
726
727 bugout:
728 return stat;
729 }
730
MlcCreditRequest(mud_channel * pc,int fd,unsigned short credit)731 int __attribute__ ((visibility ("hidden"))) MlcCreditRequest(mud_channel *pc, int fd, unsigned short credit)
732 {
733 mud_device *pd = &msp->device[pc->dindex];
734 unsigned char buf[HPMUD_BUFFER_SIZE];
735 int stat=0, len, n;
736 MLCCreditRequest *pCmd;
737 MLCCreditRequestReply *pReply;
738
739 memset(buf, 0, sizeof(MLCCreditRequest));
740 pCmd = (MLCCreditRequest *)buf;
741 n = sizeof(MLCCreditRequest);
742 pCmd->h.length = htons(n);
743 pCmd->cmd = MLC_CREDIT_REQUEST;
744 pCmd->hsocket = pc->sockid; /* assume static socket ids */
745 pCmd->psocket = pc->sockid;
746 pCmd->credit = htons(credit); /* request host to peripheral credit */
747
748 if ((len = (pd->vf.write)(fd, pCmd, n, HPMUD_EXCEPTION_TIMEOUT)) != n)
749 {
750 BUG("unable to write MlcCreditRequest: %m\n");
751 stat = 1;
752 goto bugout;
753 }
754
755 stat = MlcReverseReply(pc, fd, buf, sizeof(buf));
756 pReply = (MLCCreditRequestReply *)buf;
757
758 if ((stat != 0) || (pReply->cmd != (0x80 | MLC_CREDIT_REQUEST)) || (pReply->result != 0))
759 {
760 BUG("invalid MlcCreditRequestReply: cmd=%x, result=%x\n", pReply->cmd, pReply->result);
761 stat = 1;
762 goto bugout;
763 }
764
765 pc->ta.h2pcredit += ntohs(pReply->credit);
766
767 bugout:
768 return stat;
769 }
770
771
772
773