|
|
1.1 root 1: /*
2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3: *
4: * @APPLE_LICENSE_HEADER_START@
5: *
6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7: * Reserved. This file contains Original Code and/or Modifications of
8: * Original Code as defined in and that are subject to the Apple Public
9: * Source License Version 1.1 (the "License"). You may not use this file
10: * except in compliance with the License. Please obtain a copy of the
11: * License at http://www.apple.com/publicsource and read it before using
12: * this file.
13: *
14: * The Original Code and all software distributed under the License are
15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19: * License for the specific language governing rights and limitations
20: * under the License.
21: *
22: * @APPLE_LICENSE_HEADER_END@
23: */
24:
25: /*
26: * Copyright (c) 1995 Apple Computer, Inc.
27: *
28: * The information contained herein is subject to change without
29: * notice and should not be construed as a commitment by Apple
30: * Computer, Inc. Apple Computer, Inc. assumes no responsibility
31: * for any errors that may appear.
32: *
33: * Confidential and Proprietary to Apple Computer, Inc.
34: *
35: */
36: #ifdef _AIX
37: #include <sys/sleep.h>
38: #include <sys/poll.h>
39: #endif
40: #include <sys/ioccom.h>
41: #include <h/sysglue.h>
42: #include <at/appletalk.h>
43: #include <at/elap.h>
44: #include <at/ddp.h>
45: #include <at/at_lap.h>
46: #include <at_elap.h>
47: #include <h/at_ddp.h>
48: #undef e_sleep_thread
49:
50: /*definition of dbgBits moved here to avoid multiple redefinition */
51: dbgBits_t dbgBits;
52:
53: int _ATsocket(proto, err, proc)
54: int proto;
55: int *err;
56: void *proc;
57: {
58: int fd;
59: gref_t *gref;
60:
61: /* make sure the specified protocol id is valid */
62: switch (proto) {
63: case ATPROTO_DDP:
64: case ATPROTO_LAP:
65: case ATPROTO_ATP:
66: case ATPROTO_ASP:
67: case ATPROTO_AURP:
68: case ATPROTO_ADSP:
69: break;
70: default:
71: *err = EPROTOTYPE;
72: #ifdef APPLETALK_DEBUG
73: kprintf("_ATsocket: error EPROTOTYPE =%d\n", *err);
74: #endif
75: return -1;
76: }
77:
78: /* allocate a protocol channel */
79: if ((*err = gref_open(&gref)) != 0) {
80: #ifdef APPLETALK_DEBUG
81: kprintf("_ATsocket: error gref_open =%d\n", *err);
82: #endif
83: return -1;
84: }
85: gref->proto = proto;
86: #ifdef NEXT
87: gref->pid = ((struct proc *)proc)->p_pid;
88: #endif
89:
90: /* open the specified protocol */
91: switch (gref->proto) {
92: case ATPROTO_DDP:
93: *err = ddp_open(gref); break;
94: case ATPROTO_LAP:
95: *err = lap_open(gref); break;
96: case ATPROTO_ATP:
97: *err = atp_open(gref, 1); break;
98: case ATPROTO_ASP:
99: *err = asp_open(gref); break;
100: #ifdef AURP_SUPPORT
101: case ATPROTO_AURP:
102: *err = aurp_open(gref); break;
103: #endif
104: case ATPROTO_ADSP:
105: *err = adsp_open(gref); break;
106: }
107:
108: /* create the descriptor for the channel */
109: if (*err)
110: gref->proto = ATPROTO_NONE;
111: if (*err || (*err = atalk_openref(gref, &fd, proc))) {
112: #ifdef APPLETALK_DEBUG
113: kprintf("_ATsocket: error atalk_openref =%d\n", *err);
114: #endif
115: gref_close(gref);
116: return -1;
117: }
118: /*
119: kprintf("_ATsocket: proto=%d return=%d fd=%d\n", proto, *err, fd);
120: */
121: return fd;
122: }
123:
124: int _ATgetmsg(fd, ctlptr, datptr, flags, err, proc)
125: int fd;
126: strbuf_t *ctlptr;
127: strbuf_t *datptr;
128: int *flags;
129: int *err;
130: void *proc;
131: {
132: int rc = -1;
133: gref_t *gref;
134:
135: if ((*err = atalk_getref(0, fd, &gref, proc)) == 0) {
136: switch (gref->proto) {
137: case ATPROTO_ASP:
138: rc = ASPgetmsg(gref, ctlptr, datptr, flags, err); break;
139: case ATPROTO_AURP:
140: #ifdef AURP_SUPPORT
141: rc = AURPgetmsg(err); break;
142: #endif
143: default:
144: *err = EPROTONOSUPPORT; break;
145: }
146: }
147:
148:
149: /* kprintf("_ATgetmsg: return=%d\n", *err);*/
150: return rc;
151: }
152:
153: int _ATputmsg(fd, ctlptr, datptr, flags, err, proc)
154: int fd;
155: strbuf_t *ctlptr;
156: strbuf_t *datptr;
157: int flags;
158: int *err;
159: void *proc;
160: {
161: int rc = -1;
162: gref_t *gref;
163:
164: if ((*err = atalk_getref(0, fd, &gref, proc)) == 0) {
165: switch (gref->proto) {
166: case ATPROTO_ASP:
167: rc = ASPputmsg(gref, ctlptr, datptr, flags, err); break;
168: default:
169: *err = EPROTONOSUPPORT; break;
170: }
171: }
172:
173: /* kprintf("_ATputmsg: return=%d\n", *err); */
174: return rc;
175: }
176:
177: int _ATclose(fp, proc)
178: void *fp;
179: void *proc;
180: {
181: int err;
182: gref_t *gref;
183:
184: if ((err = atalk_closeref(fp, &gref)) != 0)
185: return err;
186:
187: gref_close(gref);
188: return 0;
189: }
190:
191: int _ATrw(fp, rw, uio, ext)
192: void *fp;
193: enum uio_rw rw;
194: struct uio *uio;
195: int ext;
196: {
197: void gref_wput();
198: int s, err, len, rlen, clen, res;
199: gref_t *gref;
200: gbuf_t *m, *mhead, *mprev;
201:
202: if ((err = atalk_getref(fp, 0, &gref, 0)) != 0)
203: return err;
204:
205: if ((len = uio->uio_resid) == 0)
206: return 0;
207:
208: ATDISABLE(s, gref->lock);
209: if (gref->errno) {
210: ATENABLE(s, gref->lock);
211: return (int)gref->errno;
212: }
213:
214: if (rw == UIO_READ) {
215: while ((gref->errno == 0) && ((mhead = gref->rdhead) == 0)) {
216: gref->sevents |= POLLMSG;
217: err = tsleep(&gref->event, PSOCK | PCATCH, "AT read", 0);
218: gref->sevents &= ~POLLMSG;
219: if (err != 0) {
220: ATENABLE(s, gref->lock);
221: return err;
222: }
223: }
224:
225: if (gref->errno) {
226: ATENABLE(s, gref->lock);
227: return EPIPE;
228: }
229: if ((gref->rdhead = gbuf_next(mhead)) == 0)
230: gref->rdtail = 0;
231:
232: ATENABLE(s, gref->lock);
233:
234: gbuf_next(mhead) = 0;
235:
236: for (mprev=0, m=mhead, rlen=0; m && len; rlen+=clen, len-=clen) {
237: if ((clen = gbuf_len(m)) > 0) {
238: if (clen > len)
239: clen = len;
240: #ifdef _AIX
241: if (uiomove((caddr_t)gbuf_rptr(m), clen, UIO_READ, uio) == -1)
242: break;
243: #else
244: uio->uio_rw = UIO_READ;
245: res= uiomove((caddr_t)gbuf_rptr(m), clen, uio);
246: /* kprintf("_ATrw: UIO_READ: res=%d\n", res); */
247: if (res == -1)
248: break;
249: #endif
250: if (gbuf_len(m) > len) {
251: gbuf_rinc(m,clen);
252: break;
253: }
254: }
255: mprev = m;
256: m = gbuf_cont(m);
257: }
258: if (m) {
259: if (mprev)
260: gbuf_cont(mprev) = 0;
261: else
262: mhead = 0;
263: ATDISABLE(s, gref->lock);
264: if (gref->rdhead == 0)
265: gref->rdtail = m;
266: gbuf_next(m) = gref->rdhead;
267: gref->rdhead = m;
268: ATENABLE(s, gref->lock);
269: }
270: if (mhead)
271: gbuf_freem(mhead);
272:
273: } else {
274: if (gref->writeable) {
275: while (!(*gref->writeable)(gref)) {
276: /* flow control on, wait to be enabled to write */
277: gref->sevents |= POLLSYNC;
278: err = tsleep(&gref->event, PSOCK | PCATCH, "AT write", 0);
279: gref->sevents &= ~POLLSYNC;
280: if (err != 0) {
281: ATENABLE(s, gref->lock);
282: return err;
283: }
284: }
285: }
286:
287: ATENABLE(s, gref->lock);
288:
289: /* allocate a buffer to copy in the write data */
290: if ((m = gbuf_alloc(AT_WR_OFFSET+len, PRI_MED)) == 0)
291: return ENOBUFS;
292: gbuf_rinc(m,AT_WR_OFFSET);
293: gbuf_wset(m,len);
294:
295: /* copy in the write data */
296: #ifdef _AIX
297: if (uiomove((caddr_t)gbuf_rptr(m), len, UIO_WRITE, uio) == -1) {
298: #else
299: uio->uio_rw = UIO_WRITE;
300: res= uiomove((caddr_t)gbuf_rptr(m), len, uio);
301: /* kprintf("_ATrw: UIO_WRITE: res=%d\n", res); */
302: if (res == -1) {
303: #endif
304: gbuf_freeb(m);
305: return EIO;
306: }
307:
308: /* forward the write data to the appropriate protocol module */
309: gref_wput(gref, m);
310: }
311:
312: return 0;
313: }
314:
315: int _ATread(fp, uio, cred)
316: void *fp;
317: struct uio *uio;
318: void *cred;
319: {
320: return _ATrw(fp, UIO_READ, uio, 0);
321: }
322:
323: int _ATwrite(fp, uio, cred)
324: void *fp;
325: struct uio *uio;
326: void *cred;
327: {
328: return _ATrw(fp, UIO_WRITE, uio, 0);
329: }
330: /*
331: struct at_ioctl_args {
332: int fdes;
333: u_long cmd;
334: caddr_t arg;
335: };
336: int _ATioctl(p, uap, retval)
337: struct proc *p;
338: register struct at_ioctl_args *uap;
339: register_t *retval;
340: */
341: int _ATioctl(fp, cmd, arg, proc)
342: void *fp;
343: u_long cmd;
344: register caddr_t arg;
345: void *proc;
346: {
347: void gref_wput();
348: int s, err, len;
349: gref_t *gref;
350: gbuf_t *m, *mdata;
351: ioc_t *ioc;
352: ioccmd_t ioccmd;
353:
354:
355: if ((err = atalk_getref(fp, 0, &gref, 0)) != 0) {
356: #ifdef APPLETALK_DEBUG
357: kprintf("_ATioctl: atalk_getref=%d\n", err);
358: #endif
359: return err;
360: }
361:
362: /* error if not for us */
363: if ((cmd & 0xffff) != 0xff99)
364: return EOPNOTSUPP;
365:
366: /* copy in ioc command info */
367: /*
368: kprintf("_ATioctl: arg ioccmd.ic_cmd=%x ic_len=%x gref->lock=%x, gref->event=%x\n",
369: ((ioccmd_t *)arg)->ic_cmd, ((ioccmd_t *)arg)->ic_len, gref->lock, gref->event);
370: */
371: if ((err = copyin((caddr_t)arg,
372: (caddr_t)&ioccmd, sizeof(ioccmd_t))) != 0) {
373: #ifdef APPLETALK_DEBUG
374: kprintf("_ATioctl: err = %d, copyin(%x, %x, %d)\n", err, (caddr_t)arg,
375: (caddr_t)&ioccmd, sizeof(ioccmd_t));
376: #endif
377: return err;
378: }
379:
380: /* allocate a buffer to create an ioc command */
381: if ((m = gbuf_alloc(sizeof(ioc_t), PRI_HI)) == 0)
382: return ENOBUFS;
383: gbuf_wset(m,sizeof(ioc_t));
384: gbuf_set_type(m, MSG_IOCTL);
385:
386: /* create the ioc command */
387: if (ioccmd.ic_len) {
388: if ((gbuf_cont(m) = gbuf_alloc(ioccmd.ic_len, PRI_HI)) == 0) {
389: gbuf_freem(m);
390: #ifdef APPLETALK_DEBUG
391: kprintf("_ATioctl: gbuf_alloc err=%d\n",ENOBUFS);
392: #endif
393: return ENOBUFS;
394: }
395: gbuf_wset(gbuf_cont(m),ioccmd.ic_len);
396: if ((err = copyin((caddr_t)ioccmd.ic_dp,
397: (caddr_t)gbuf_rptr(gbuf_cont(m)), ioccmd.ic_len)) != 0) {
398: gbuf_freem(m);
399: return err;
400: }
401: }
402: ioc = (ioc_t *)gbuf_rptr(m);
403: ioc->ioc_cmd = ioccmd.ic_cmd;
404: ioc->ioc_count = ioccmd.ic_len;
405: ioc->ioc_error = 0;
406: ioc->ioc_rval = 0;
407:
408: /* send the ioc command to the appropriate recipient */
409: gref_wput(gref, m);
410:
411: /* wait for the ioc ack */
412: ATDISABLE(s, gref->lock);
413: while ((m = gref->ichead) == 0) {
414: gref->sevents |= POLLPRI;
415: err = tsleep(&gref->iocevent, PSOCK | PCATCH, "AT ioctl", 0);
416: gref->sevents &= ~POLLPRI;
417: if (err != 0) {
418: ATENABLE(s, gref->lock);
419: #ifdef APPLETALK_DEBUG
420: kprintf("_ATioctl: EINTR\n");
421: #endif
422: return err;
423: }
424: }
425:
426: /* PR-2224797 */
427: if (gbuf_next(m) == m) /* error case */
428: gbuf_next(m) = 0;
429:
430: gref->ichead = gbuf_next(m);
431:
432: ATENABLE(s, gref->lock);
433:
434:
435: /* kprintf("_ATioctl: woke up from tread sleep\n"); */
436: /* process the ioc response */
437: ioc = (ioc_t *)gbuf_rptr(m);
438: if ((err = ioc->ioc_error) == 0) {
439: ioccmd.ic_timout = ioc->ioc_rval;
440: ioccmd.ic_len = 0;
441: mdata = gbuf_cont(m);
442: if (mdata && ioccmd.ic_dp) {
443: ioccmd.ic_len = gbuf_msgsize(mdata);
444: for (len=0; mdata; mdata=gbuf_cont(mdata)) {
445: if ((err = copyout((caddr_t)gbuf_rptr(mdata),
446: (caddr_t)&ioccmd.ic_dp[len], gbuf_len(mdata))) < 0) {
447: #ifdef APPLETALK_DEBUG
448: kprintf("_ATioctl: len=%d error copyout=%d from=%x to=%x gbuf_len=%x\n",
449: len, err, (caddr_t)gbuf_rptr(mdata),
450: (caddr_t)&ioccmd.ic_dp[len], gbuf_len(mdata));
451: #endif
452: goto l_done;
453: }
454: len += gbuf_len(mdata);
455: }
456: }
457: if ((err = copyout((caddr_t)&ioccmd,
458: (caddr_t)arg, sizeof(ioccmd_t))) != 0) {
459: #ifdef APPLETALK_DEBUG
460: kprintf("_ATioctl: error copyout2=%d from=%x to=%x len=%d\n",
461: err, &ioccmd, arg, sizeof(ioccmd_t));
462: #endif
463: goto l_done;
464: }
465: }
466:
467: l_done:
468: gbuf_freem(m);
469: /*kprintf("_ATioctl: I_done=%d\n", err);*/
470: return err;
471: }
472:
473: #ifndef _AIX
474: int _ATselect(fp, which, proc)
475: void *fp;
476: int which;
477: void *proc;
478: {
479: int s, err, rc = 0;
480: gref_t *gref;
481:
482: if ((err = atalk_getref(fp, 0, &gref, 0)) != 0)
483: return err;
484:
485: ATDISABLE(s, gref->lock);
486: if (which == FREAD) {
487: if (gref->rdhead || (gref->readable && (*gref->readable)(gref)))
488: rc = 1;
489: else {
490: gref->sevents |= POLLIN;
491: selrecord(proc, &gref->si);
492: }
493: }
494:
495: else if (which == POLLOUT) {
496: if (gref->writeable) {
497: if ((*gref->writeable)(gref))
498: rc = 1;
499: else {
500: gref->sevents |= POLLOUT;
501: selrecord(proc, &gref->si);
502: }
503: } else
504: rc = 1;
505: }
506: ATENABLE(s, gref->lock);
507:
508: return rc;
509: }
510:
511: #else /* AIX code is no longer supported. */
512:
513: int _ATselect(fp, corl, reqevents, retevents, notify)
514: void *fp;
515: int corl;
516: unsigned short reqevents;
517: unsigned short *retevents;
518: void (*notify)();
519: {
520: int s, err, rc = 0;
521: gref_t *gref;
522: unsigned short sevents = 0;
523:
524: if ((err = atalk_getref(fp, 0, &gref, 0)) != 0)
525: return err;
526:
527: ATDISABLE(s, gref->lock);
528: if (reqevents & POLLIN) {
529: if (gref->rdhead || (gref->readable && (*gref->readable)(gref)))
530: sevents |= POLLIN;
531: }
532:
533: if (reqevents & POLLOUT) {
534: if (gref->writeable) {
535: if ((*gref->writeable)(gref))
536: sevents |= POLLOUT;
537: } else
538: sevents |= POLLOUT;
539: }
540:
541: if ((sevents == 0) && ((reqevents & POLLSYNC) == 0)) {
542: if (rc = selreg(corl, 99, gref, reqevents, notify)) {
543: ATENABLE(s, gref->lock);
544: goto l_done;
545: }
546:
547: if (reqevents & POLLIN) {
548: if (gref->rdhead || (gref->readable && (*gref->readable)(gref)))
549: sevents |= POLLIN;
550: else
551: gref->sevents |= POLLIN;
552: }
553:
554: if (reqevents & POLLOUT) {
555: if (gref->writeable) {
556: if ((*gref->writeable)(gref))
557: sevents |= POLLOUT;
558: else
559: gref->sevents |= POLLOUT;
560: } else
561: sevents |= POLLOUT;
562: }
563: }
564: ATENABLE(s, gref->lock);
565: *retevents = sevents;
566:
567: l_done:
568: return rc;
569: }
570:
571: int _ATstat()
572: {
573: return 0;
574: }
575: #endif /* end AIX section */
576:
577: void atalk_putnext(gref, m)
578: gref_t *gref;
579: gbuf_t *m;
580: {
581: int s;
582:
583: ATDISABLE(s, gref->lock);
584:
585: gbuf_next(m) = 0;
586:
587: if ((gbuf_type(m) == MSG_IOCACK) || (gbuf_type(m) == MSG_IOCNAK)) {
588: if (gref->ichead)
589: gbuf_next(gref->ichead) = m;
590: else {
591: gref->ichead = m;
592: if (gref->sevents & POLLPRI) {
593: /*kprintf("atalk_putnext: wake up gref->event=%x\n", &gref->event);*/
594: thread_wakeup(&gref->iocevent);
595: }
596: atalk_notify_sel(gref);
597: }
598:
599: } else {
600: if (gref->errno == 0) {
601: if (gbuf_type(m) == MSG_ERROR) {
602: gref->errno = *gbuf_rptr(m);
603: if (gref->rdhead) {
604: gbuf_freel(gref->rdhead);
605: gref->rdhead = 0;
606: }
607: if (gref->sevents & POLLMSG) {
608: gref->sevents &= ~POLLMSG;
609: /*kprintf("atalk_putnext: wake up gref->event=%x\n", &gref->event);*/
610: thread_wakeup(&gref->event);
611: }
612: if (gref->sevents & POLLIN) {
613: gref->sevents &= ~POLLIN;
614: /*kprintf("atalk_putnext: selwakeup gref->si=%x\n", &gref->si); */
615: selwakeup(&gref->si);
616: }
617: } else if (gref->rdhead) {
618: gbuf_next(gref->rdtail) = m;
619: gref->rdtail = m;
620: } else {
621: gref->rdhead = m;
622: if (gref->sevents & POLLMSG) {
623: gref->sevents &= ~POLLMSG;
624: /*kprintf("atalk_putnext: wake up2 gref->event=%x\n", &gref->event);*/
625: thread_wakeup(&gref->event);
626: }
627: if (gref->sevents & POLLIN) {
628: gref->sevents &= ~POLLIN;
629: /*kprintf("atalk_putnext: selwakeup2 gref->si=%x\n", &gref->si);*/
630: selwakeup(&gref->si);
631: }
632: gref->rdtail = m;
633: }
634: }
635: }
636:
637: ATENABLE(s, gref->lock);
638: }
639:
640: void atalk_enablew(gref)
641: gref_t *gref;
642: {
643: if (gref->sevents & POLLSYNC)
644: #ifdef _AIX
645: e_wakeup(&gref->event);
646: #else
647: thread_wakeup(&gref->event);
648: #endif
649: }
650:
651: void atalk_flush(gref)
652: gref_t *gref;
653: {
654: int s;
655:
656: ATDISABLE(s, gref->lock);
657: if (gref->rdhead) {
658: gbuf_freel(gref->rdhead);
659: gref->rdhead = 0;
660: }
661: if (gref->ichead) {
662: gbuf_freel(gref->ichead);
663: gref->ichead = 0;
664: }
665: ATENABLE(s, gref->lock);
666: }
667:
668: void atalk_notify_sel(gref)
669: gref_t *gref;
670: {
671: int s;
672:
673: ATDISABLE(s, gref->lock);
674: if (gref->sevents & POLLIN) {
675: gref->sevents &= ~POLLIN;
676: selwakeup(&gref->si);
677: }
678: ATENABLE(s, gref->lock);
679: }
680:
681: int atalk_peek(gref, event)
682: gref_t *gref;
683: unsigned char *event;
684: {
685: int s, rc;
686:
687: ATDISABLE(s, gref->lock);
688: if (gref->rdhead) {
689: *event = *gbuf_rptr(gref->rdhead);
690: rc = 0;
691: } else
692: rc = -1;
693: ATENABLE(s, gref->lock);
694:
695: return rc;
696: }
697:
698: static gbuf_t *trace_msg;
699:
700: void atalk_settrace(str, p1, p2, p3, p4, p5)
701: char *str;
702: {
703: int len;
704: gbuf_t *m, *nextm;
705: char trace_buf[256];
706:
707: sprintf(trace_buf, str, p1, p2, p3, p4, p5);
708: len = strlen(trace_buf);
709: #ifdef APPLETALK_DEBUG
710: kprintf("atalk_settrace: gbufalloc size=%d\n", len+1);
711: #endif
712: if ((m = gbuf_alloc(len+1, PRI_MED)) == 0)
713: return;
714: gbuf_wset(m,len);
715: strcpy(gbuf_rptr(m), trace_buf);
716: if (trace_msg) {
717: for (nextm=trace_msg; gbuf_cont(nextm); nextm=gbuf_cont(nextm)) ;
718: gbuf_cont(nextm) = m;
719: } else
720: trace_msg = m;
721: }
722:
723: void atalk_gettrace(m)
724: gbuf_t *m;
725: {
726: if (trace_msg) {
727: gbuf_cont(m) = trace_msg;
728: trace_msg = 0;
729: }
730: }
731:
732: #define GREF_PER_BLK 32
733: static gref_t *gref_free_list = 0;
734: atlock_t refall_lock;
735:
736: void gref_init()
737: {
738: ATLOCKINIT(refall_lock);
739: }
740:
741: gref_t *gref_alloc()
742: {
743: extern gbuf_t *atp_resource_m;
744: int i, s;
745: gbuf_t *m;
746: gref_t *gref, *gref_array;
747:
748: ATDISABLE(s, refall_lock);
749: if (gref_free_list == 0) {
750: ATENABLE(s, refall_lock);
751: #ifdef APPLETALK_DEBUG
752: kprintf("gref_alloc: gbufalloc size=%d\n", GREF_PER_BLK*sizeof(gref_t));
753: #endif
754: if ((m = gbuf_alloc(GREF_PER_BLK*sizeof(gref_t),PRI_HI)) == 0)
755: return (gref_t *)0;
756: bzero(gbuf_rptr(m), GREF_PER_BLK*sizeof(gref_t));
757: gref_array = (gref_t *)gbuf_rptr(m);
758: for (i=0; i < GREF_PER_BLK-1; i++)
759: gref_array[i].next = (gref_t *)&gref_array[i+1];
760: ATDISABLE(s, refall_lock);
761: gbuf_cont(m) = atp_resource_m;
762: atp_resource_m = m;
763: gref_array[i].next = gref_free_list;
764: gref_free_list = (gref_t *)&gref_array[0];
765: }
766:
767: gref = gref_free_list;
768: gref_free_list = gref->next;
769: ATENABLE(s, refall_lock);
770: ATLOCKINIT(gref->lock);
771: ATEVENTINIT(gref->event);
772: ATEVENTINIT(gref->iocevent);
773:
774: return gref;
775: }
776:
777: void gref_free(gref)
778: gref_t *gref;
779: {
780: int s;
781:
782: ATDISABLE(s, refall_lock);
783: bzero((char *)gref, sizeof(gref_t));
784: gref->next = gref_free_list;
785: gref_free_list = gref;
786: ATENABLE(s, refall_lock);
787: }
788:
789: int gref_open(grefp)
790: gref_t **grefp;
791: {
792: gref_t *gref;
793:
794: /*
795: * if no gref structure available, return failure
796: */
797: if ((gref = (gref_t *)gref_alloc()) == 0)
798: return ENOBUFS;
799: #ifndef NEXT
800: gref->pid = getpid();
801: #endif
802: *grefp = gref;
803:
804: return 0;
805: }
806:
807: int gref_close(gref)
808: gref_t *gref;
809: {
810: int rc;
811:
812: switch (gref->proto) {
813: case ATPROTO_DDP:
814: rc = ddp_close(gref); break;
815: case ATPROTO_LAP:
816: rc = lap_close(gref); break;
817: case ATPROTO_ATP:
818: rc = atp_close(gref, 1); break;
819: case ATPROTO_ASP:
820: rc = asp_close(gref); break;
821: #ifdef AURP_SUPPORT
822: case ATPROTO_AURP:
823: rc = aurp_close(gref); break;
824: break;
825: #endif
826: case ATPROTO_ADSP:
827: rc = adsp_close(gref); break;
828: default:
829: rc = 0;
830: break;
831: }
832:
833: if (rc == 0) {
834: atalk_flush(gref);
835: selthreadclear(&gref->si);
836: gref_free(gref);
837: }
838:
839: return rc;
840: }
841:
842: void gref_wput(gref, m)
843: gref_t *gref;
844: gbuf_t *m;
845: {
846:
847: switch (gref->proto) {
848: case ATPROTO_DDP:
849: ddp_putmsg(gref, m); break;
850: case ATPROTO_LAP:
851: elap_wput(gref, m); break;
852: case ATPROTO_ATP:
853: atp_wput(gref, m); break;
854: case ATPROTO_ASP:
855: asp_wput(gref, m); break;
856: #ifdef AURP_SUPPORT
857: case ATPROTO_AURP:
858: aurp_wput(gref, m); break;
859: #endif
860: case ATPROTO_ADSP:
861: adsp_wput(gref, m); break;
862: case ATPROTO_NONE:
863: if (gbuf_type(m) == MSG_IOCTL) {
864: gbuf_freem(gbuf_cont(m));
865: gbuf_cont(m) = 0;
866: ((ioc_t *)gbuf_rptr(m))->ioc_rval = -1;
867: ((ioc_t *)gbuf_rptr(m))->ioc_error = EPROTO;
868: gbuf_set_type(m, MSG_IOCNAK);
869: atalk_putnext(gref, m);
870: } else
871: gbuf_freem(m);
872: break;
873: default:
874: gbuf_freem(m);
875: break;
876: }
877: }
878:
879: int gbuf_msgsize(m)
880: gbuf_t *m;
881: {
882: int size;
883:
884: for (size=0; m; m=gbuf_cont(m))
885: size += gbuf_len(m);
886: return size;
887: }
888:
889: /* Duplicate a single mbuf, attaching existing external storage. */
890: gbuf_t *gbuf_dupb(m)
891: gbuf_t *m;
892: {
893: return((gbuf_t *)m_copym(m, 0, gbuf_len(m), M_DONTWAIT));
894: }
895:
896: gbuf_t *gbuf_dupb_wait(m, wait)
897: gbuf_t *m;
898: int wait;
899: {
900: return((gbuf_t *)m_copym(m, 0, gbuf_len(m), (wait)? M_WAIT: M_DONTWAIT));
901: }
902:
903: /* Duplicate an mbuf chain, attaching existing external storage. */
904: gbuf_t *gbuf_dupm(mlist)
905: gbuf_t *mlist;
906: {
907: return((gbuf_t *)m_copym(mlist, 0, M_COPYALL, M_DONTWAIT));
908: }
909:
910: gbuf_t *gbuf_copym(mlist)
911: gbuf_t *mlist;
912: {
913: int len, offset;
914: gbuf_t *m, *mcurr, *mprev, *mhead;
915:
916: offset = AT_WR_OFFSET;
917: for (mhead = 0, m = mlist; m; m = gbuf_cont(m)) {
918: if ((len = gbuf_len(m)) == 0)
919: continue;
920: if ((mcurr = gbuf_alloc(offset+len, PRI_MED)) == 0) {
921: if (mhead)
922: gbuf_freem(mhead);
923: return (gbuf_t *)0;
924: }
925: gbuf_rinc(mcurr,offset);
926: gbuf_wset(mcurr,len);
927: gbuf_set_type(mcurr, gbuf_type(m));
928: bcopy(gbuf_rptr(m), gbuf_rptr(mcurr), len);
929: if (mhead)
930: gbuf_cont(mprev) = mcurr;
931: else {
932: mhead = mcurr;
933: offset = 0;
934: }
935: mprev = mcurr;
936: }
937:
938: return (gbuf_t *)mhead;
939: }
940:
941: void gbuf_freem(mlist)
942: gbuf_t *mlist;
943: {
944: m_freem((struct mbuf *)mlist);
945: }
946:
947: void gbuf_linkb(m1, m2)
948: gbuf_t *m1;
949: gbuf_t *m2;
950: {
951: while (gbuf_cont(m1) != 0)
952: m1 = gbuf_cont(m1);
953: gbuf_cont(m1) = m2;
954: }
955:
956: /**************************************/
957:
958: int ddp_adjmsg(m, len)
959: gbuf_t *m;
960: int len;
961: {
962: int buf_len;
963: gbuf_t *curr_m, *prev_m;
964:
965: if (m == (gbuf_t *)0)
966: return 0;
967:
968: if (len > 0) {
969: for (curr_m=m; curr_m;) {
970: buf_len = gbuf_len(curr_m);
971: if (len < buf_len) {
972: gbuf_rinc(curr_m,len);
973: return 1;
974: }
975: len -= buf_len;
976: gbuf_rinc(curr_m,buf_len);
977: if ((curr_m = gbuf_cont(curr_m)) == 0) {
978: gbuf_freem(m);
979: return 0;
980: }
981: }
982:
983: } else if (len < 0) {
984: len = -len;
985: l_cont: prev_m = 0;
986: for (curr_m=m; gbuf_cont(curr_m);
987: prev_m=curr_m, curr_m=gbuf_cont(curr_m)) ;
988: buf_len = gbuf_len(curr_m);
989: if (len < buf_len) {
990: gbuf_wdec(curr_m,len);
991: return 1;
992: }
993: if (prev_m == 0)
994: return 0;
995: gbuf_cont(prev_m) = 0;
996: gbuf_freeb(curr_m);
997: len -= buf_len;
998: goto l_cont;
999:
1000: } else
1001: return 1;
1002: }
1003:
1004: /*
1005: * The message chain, m is grown in size by len contiguous bytes.
1006: * If len is non-negative, len bytes are added to the
1007: * end of the gbuf_t chain. If len is negative, the
1008: * bytes are added to the front. ddp_growmsg only adds bytes to
1009: * message blocks of the same type.
1010: * It returns a pointer to the new gbuf_t on sucess, 0 on failure.
1011: */
1012:
1013: gbuf_t *ddp_growmsg(mp, len)
1014: gbuf_t *mp;
1015: int len;
1016: {
1017: gbuf_t *m, *d;
1018:
1019: if ((m = mp) == (gbuf_t *) 0)
1020: return ((gbuf_t *) 0);
1021:
1022: if (len <= 0) {
1023: len = -len;
1024: if ((d = gbuf_alloc(len, PRI_MED)) == 0)
1025: return ((gbuf_t *) 0);
1026: gbuf_set_type(d, gbuf_type(m));
1027: gbuf_wset(d,len);
1028: /* link in new gbuf_t */
1029: gbuf_cont(d) = m;
1030: return (d);
1031:
1032: } else {
1033: register int count;
1034: /*
1035: * Add to tail.
1036: */
1037: if ((count = gbuf_msgsize(m)) < 0)
1038: return ((gbuf_t *) 0);
1039: /* find end of chain */
1040: for ( ; m; m = gbuf_cont(m)) {
1041: if (gbuf_len(m) >= count)
1042: break;
1043: count -= gbuf_len(m);
1044: }
1045: /* m now points to gbuf_t to add to */
1046: if ((d = gbuf_alloc(len, PRI_MED)) == 0)
1047: return ((gbuf_t *) 0);
1048: gbuf_set_type(d, gbuf_type(m));
1049: /* link in new gbuf_t */
1050: gbuf_cont(d) = gbuf_cont(m);
1051: gbuf_cont(m) = d;
1052: gbuf_wset(d,len);
1053: return (d);
1054: }
1055: }
1056:
1057:
1058:
1059: /*
1060: * return an MSG_ERROR on the read stream. Note that the same message
1061: * block that caused the problem is used as the vehicle. So chained
1062: * blocks to this message will be free'd; i.e. ASSUMES no multiple
1063: * references.
1064: * Used by other appletalk modules, so it is not static!
1065: */
1066:
1067: void data_error(errno,mp,gref)
1068: int errno;
1069: register gbuf_t *mp;
1070: register gref_t *gref;
1071: {
1072:
1073: gbuf_set_type(mp, MSG_ERROR);
1074:
1075: *gbuf_rptr(mp) = (unsigned char)errno;
1076: gbuf_wset(mp,1);
1077: if (gbuf_cont(mp)) {
1078: gbuf_freem(gbuf_cont(mp));
1079: gbuf_cont(mp) = 0;
1080: }
1081:
1082: atalk_putnext(gref, mp);
1083: }
1084:
1085: /*
1086: * return the MSG_IOCACK/MSG_IOCNAK. Note that the same message
1087: * block is used as the vehicle, and that if there is an error return,
1088: * then linked blocks are lopped off. BEWARE of multiple references.
1089: * Used by other appletalk modules, so it is not static!
1090: */
1091:
1092: void ioc_ack(errno, m, gref)
1093: int errno;
1094: register gbuf_t *m;
1095: register gref_t *gref;
1096:
1097: {
1098: ioc_t *iocbp = (ioc_t *)gbuf_rptr(m);
1099:
1100: /*kprintf("ioc_ack: m=%x gref=%x errno=%d\n", m, gref, errno);*/
1101:
1102: if (gref->info == NULL) {
1103: gbuf_freem(m);
1104: #ifdef APPLETALK_DEBUG
1105: kprintf("ioc_ack: gref->info == NULL: free m\n");
1106: #endif
1107: return;
1108: }
1109: if ((iocbp->ioc_error = errno) != 0)
1110: { /* errno != 0, then there is an error, get rid of linked blocks! */
1111:
1112: if (gbuf_cont(m)) {
1113: gbuf_freem(gbuf_cont(m));
1114: gbuf_cont(m) = 0;
1115: }
1116: gbuf_set_type(m, MSG_IOCNAK);
1117: iocbp->ioc_count = 0; /* only make zero length if error */
1118: iocbp->ioc_rval = -1;
1119: } else
1120: gbuf_set_type(m, MSG_IOCACK);
1121:
1122: atalk_putnext(gref, m);
1123: }
1124:
1125: /* Queue management functions */
1126:
1127: void
1128: ddp_remque(elem)
1129: register LIB_QELEM_T *elem;
1130: {
1131: elem->q_back->q_forw = elem->q_forw;
1132: elem->q_forw->q_back = elem->q_back;
1133: }
1134:
1135: void
1136: ddp_insque(elem, prev)
1137: register LIB_QELEM_T *elem, *prev;
1138: {
1139: elem->q_back = prev;
1140: elem->q_forw = prev->q_forw;
1141: prev->q_forw->q_back = elem;
1142: prev->q_forw = elem;
1143: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.