]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netat/atp_write.c
xnu-2422.1.72.tar.gz
[apple/xnu.git] / bsd / netat / atp_write.c
diff --git a/bsd/netat/atp_write.c b/bsd/netat/atp_write.c
deleted file mode 100644 (file)
index a46fa47..0000000
+++ /dev/null
@@ -1,1915 +0,0 @@
-/*
- * Copyright (c) 1996-2007 Apple Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- * 
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-
-/*    Modified for MP, 1996 by Tuyen Nguyen
- *   Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
- */
-#define RESOLVE_DBG
-
-#include <sys/errno.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <machine/spl.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/proc.h>
-#include <sys/filedesc.h>
-#include <sys/fcntl.h>
-#include <kern/locks.h>
-#include <sys/mbuf.h>
-#include <sys/ioctl.h>
-#include <sys/malloc.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/file.h>
-
-#include <net/if.h>
-
-#include <netat/sysglue.h>
-#include <netat/appletalk.h>
-#include <netat/ddp.h>
-#include <netat/at_pcb.h>
-#include <netat/atp.h>
-#include <netat/at_var.h>
-#include <netat/asp.h>
-#include <netat/at_pat.h>
-#include <netat/debug.h>
-
-
-int asp_pack_bdsp(struct atp_trans *, gbuf_t **);
-
-static int atp_pack_bdsp(struct atp_trans *, struct atpBDS *);
-static int atp_unpack_bdsp(struct atp_state *, gbuf_t *, struct atp_rcb *, 
-                          int, int);
-void atp_trp_clock(void *arg), atp_trp_clock_locked(void *arg);
-
-extern struct atp_rcb_qhead atp_need_rel;
-extern int atp_inited;
-extern struct atp_state *atp_used_list;
-extern asp_scb_t *scb_free_list;
-
-extern gbuf_t *scb_resource_m;
-extern gbuf_t *atp_resource_m;
-extern gref_t *atp_inputQ[];
-extern int atp_pidM[];
-extern at_ifaddr_t *ifID_home;
-extern lck_mtx_t * atalk_mutex;
-
-static struct atp_trans *trp_tmo_list;
-struct atp_trans *trp_tmo_rcb;
-
-/* first bds entry gives number of bds entries in total (hack) */
-#define get_bds_entries(m) \
-       ((gbuf_len(m) > TOTAL_ATP_HDR_SIZE)? \
-        (UAS_VALUE(((struct atpBDS *)(AT_ATP_HDR(m)->data))->bdsDataSz)): 0)
-
-#define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
-
-void atp_link(void)
-{
-       trp_tmo_list = 0;
-       trp_tmo_rcb = atp_trans_alloc(0);
-       atp_timout(atp_rcb_timer, trp_tmo_rcb, 10 * HZ);
-       atp_trp_clock((void *)&atp_inited);
-       asp_clock((void *)&atp_inited);
-}
-
-void atp_unlink()
-{
-       untimeout(asp_clock_locked, (void *)&atp_inited);
-       untimeout(atp_trp_clock_locked, (void *)&atp_inited);
-       atp_untimout(atp_rcb_timer, trp_tmo_rcb); 
-       trp_tmo_list = 0;
-
-#ifdef BAD_IDEA
-       /* allocated in asp_scb_alloc(), which is called 
-          by asp_open() */
-       if (scb_resource_m) { 
-               gbuf_freem(scb_resource_m);
-               scb_resource_m = 0;
-               scb_free_list = 0;
-       }
-       /* allocated in atp_trans_alloc() */
-       if (atp_resource_m) {
-               gbuf_freem(atp_resource_m);
-               atp_resource_m = 0;
-               atp_trans_free_list = 0;
-       }
-#endif
-}
-
-/*
- *     write queue put routine .... filter out other than IOCTLs
- *     Version 1.8 of atp_write.c on 89/02/09 17:53:26
- */
-
-void
-atp_wput(gref, m)
-       register gref_t *gref;
-       register gbuf_t *m;
-{
-       register ioc_t    *iocbp;
-       int i, xcnt;
-       struct atp_state *atp;
-       struct atp_trans *trp;
-       struct atp_rcb   *rcbp;
-       at_socket skt;
-
-       atp = (struct atp_state *)gref->info;
-       if (atp->dflag)
-               atp = (struct atp_state *)atp->atp_msgq;
-
-       switch(gbuf_type(m)) {
-       case MSG_DATA:
-               if (atp->atp_msgq) {
-                       gbuf_freem(m);
-                       dPrintf(D_M_ATP, D_L_WARNING,
-                               ("atp_wput: atp_msgq discarded\n"));
-               } else
-                       atp->atp_msgq = m;
-               break;
-
-       case MSG_IOCTL:
-               /* Need to ensure that all copyin/copyout calls are made at 
-                * put routine time which should be in the user context. (true when
-                * we are the stream head). The service routine can be called on an
-                * unpredictable context and copyin/copyout calls will get wrong results
-                * or even panic the kernel. 
-                */
-               iocbp = (ioc_t *)gbuf_rptr(m);
-
-               switch (iocbp->ioc_cmd) {
-               case AT_ATP_BIND_REQ:
-                       if (gbuf_cont(m) == NULL) {
-                               iocbp->ioc_rval = -1;
-                               atp_iocnak(atp, m, EINVAL);
-                               return;
-                       }
-                       skt = *(at_socket *)gbuf_rptr(gbuf_cont(m));
-                       if ((skt = (at_socket)atp_bind(gref, (unsigned int)skt, 0)) == 0)
-                               atp_iocnak(atp, m, EINVAL);
-                       else {
-                               *(at_socket *)gbuf_rptr(gbuf_cont(m)) = skt;
-                               iocbp->ioc_rval = 0;
-                               atp_iocack(atp, m);
-                               atp_dequeue_atp(atp);
-                       }
-                       return;
-
-               case AT_ATP_GET_CHANID:
-                       if (gbuf_cont(m) == NULL) {
-                               iocbp->ioc_rval = -1;
-                               atp_iocnak(atp, m, EINVAL);
-                               return;
-                       }
-                       *(gref_t **)gbuf_rptr(gbuf_cont(m)) = gref;
-                       atp_iocack(atp, m);
-                       return;
-
-               /* not the close and not the tickle(?) */
-               case AT_ATP_ISSUE_REQUEST_DEF:
-               case AT_ATP_ISSUE_REQUEST_DEF_NOTE: {
-                       gbuf_t *bds, *tmp, *m2;
-                       at_ddp_t *ddp;
-                       at_atp_t *athp;
-
-                       if ((tmp = gbuf_cont(m)) != 0) {
-                               if ((bds = gbuf_dupb(tmp)) == NULL) {
-                                       atp_iocnak(atp, m, ENOBUFS);
-                                       return;
-                               }
-                               gbuf_rinc(tmp,atpBDSsize);
-                               gbuf_wset(bds,atpBDSsize);
-                               iocbp->ioc_count -= atpBDSsize;
-                               gbuf_cont(tmp) = bds;
-                       }
-
-                       /*
-                        *      send a response to a transaction
-                        *              first check it out
-                        */
-                       if (iocbp->ioc_count < TOTAL_ATP_HDR_SIZE) {
-                           atp_iocnak(atp, m, EINVAL);
-                           break;
-                       }
-
-                       /*
-                        *      remove the response from the message
-                        */
-                       m2 = gbuf_cont(m);
-                       gbuf_cont(m) = NULL;
-                       iocbp->ioc_count = 0;
-                       ddp = AT_DDP_HDR(m2);
-                       athp = AT_ATP_HDR(m2);
-                       if (atp->atp_msgq) {
-                               gbuf_cont(m2) = atp->atp_msgq;
-                               atp->atp_msgq = 0;
-                       }
-
-                       /*
-                        *      search for the corresponding rcb
-                        */
-                       for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) {
-                           if (rcbp->rc_tid == UAS_VALUE_NTOH(athp->tid) &&
-                               rcbp->rc_socket.node == ddp->dst_node &&
-                               rcbp->rc_socket.net == NET_VALUE(ddp->dst_net) &&
-                               rcbp->rc_socket.socket == ddp->dst_socket)
-                               break;
-                       }
-
-                       /*
-                        *      If it has already been sent then return an error
-                        */
-                       if ((rcbp && rcbp->rc_state != RCB_NOTIFIED) || 
-                           (rcbp == NULL && athp->xo)) {
-                           atp_iocnak(atp, m, ENOENT);
-                           gbuf_freem(m2);
-                           return;
-                       }
-                       if (rcbp == NULL) { /* a response for an ALO transaction */
-                           if ((rcbp = atp_rcb_alloc(atp)) == NULL) {
-                               atp_iocnak(atp, m, ENOBUFS);
-                               gbuf_freem(m2);
-                               return;
-                           }
-                           rcbp->rc_ioctl = 0;
-                           rcbp->rc_socket.socket = ddp->dst_socket;
-                           rcbp->rc_socket.node = ddp->dst_node;
-                           rcbp->rc_socket.net = NET_VALUE(ddp->dst_net);
-                           rcbp->rc_tid = UAS_VALUE_NTOH(athp->tid);
-                           rcbp->rc_bitmap = 0xff;
-                           rcbp->rc_xo = 0;
-                           rcbp->rc_state = RCB_SENDING;
-                           ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
-                       }
-                       xcnt = get_bds_entries(m2);
-                       if ((i = atp_unpack_bdsp(atp, m2, rcbp, xcnt, FALSE))) {
-                           if ( !rcbp->rc_xo)
-                               atp_rcb_free(rcbp);
-                           atp_iocnak(atp, m, i);
-                           return;
-                       }
-                       atp_send_replies(atp, rcbp);
-
-                       /*
-                        *      send the ack back to the responder
-                        */
-                       atp_iocack(atp, m);
-                       return;
-               }
-
-               case AT_ATP_GET_POLL: {
-                       if (gbuf_cont(m)) {
-                           gbuf_freem(gbuf_cont(m));
-                           gbuf_cont(m) = NULL;
-                           iocbp->ioc_count = 0;
-                       }
-
-                       /*
-                        *      search for a waiting request
-                        */
-                       if ((rcbp = atp->atp_attached.head)) {
-                           /*
-                            *  Got one, move it to the active response Q
-                            */
-                           gbuf_cont(m) = rcbp->rc_ioctl;
-                           rcbp->rc_ioctl = NULL;
-                           if (rcbp->rc_xo) {
-                               ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list);
-                               rcbp->rc_state = RCB_NOTIFIED;
-                               ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
-                           } else {
-                               /* detach rcbp from attached queue,
-                                * and free any outstanding resources
-                                */
-                               atp_rcb_free(rcbp);
-                           }
-                           atp_iocack(atp, m);
-                       } else {
-                               /*
-                                *      None available - can out
-                                */
-                               atp_iocnak(atp, m, EAGAIN);
-                       }
-                       break;
-               }
-
-               case AT_ATP_CANCEL_REQUEST: {
-                       /*
-                        *      Cancel a pending request
-                        */
-                       if (iocbp->ioc_count != sizeof(int)) {
-                           atp_iocnak(atp, m, EINVAL);
-                           break;
-                       }
-                       i = *(int *)gbuf_rptr(gbuf_cont(m));
-                       gbuf_freem(gbuf_cont(m));
-                       gbuf_cont(m) = NULL;
-                       for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
-                         if (trp->tr_tid == i)
-                               break;
-                       }
-                       if (trp == NULL)
-                               atp_iocnak(atp, m, ENOENT);
-                       else {
-                               atp_free(trp);
-                               atp_iocack(atp, m);
-                       }
-                       break;
-               }
-
-               case AT_ATP_PEEK: {
-                       unsigned char event;
-                       if (atalk_peek(gref, &event) == -1)
-                           atp_iocnak(atp, m, EAGAIN);
-                       else {
-                               *gbuf_rptr(gbuf_cont(m)) = event;
-                               atp_iocack(atp, m);
-                       }
-                       break;
-               }
-
-               case DDP_IOC_GET_CFG:
-#ifdef APPLETALK_DEBUG
-                       kprintf("atp_wput: DDP_IOC_GET_CFG\n");
-#endif
-                       if (gbuf_cont(m) == 0) {
-                               atp_iocnak(atp, m, EINVAL);
-                               break;
-                       }
-                       {
-                       /* *** was ddp_get_cfg() *** */
-                         ddp_addr_t *cfgp = 
-                           (ddp_addr_t *)gbuf_rptr(gbuf_cont(m));
-                         cfgp->inet.net = ifID_home->ifThisNode.s_net;
-                         cfgp->inet.node = ifID_home->ifThisNode.s_node;
-                         cfgp->inet.socket = atp->atp_socket_no;
-                         cfgp->ddptype = DDP_ATP;
-#ifdef NOT_YET
-                         cfgp->inet.net = atp->atp_gref->laddr.s_net;
-                         cfgp->inet.node = atp->atp_gref->laddr.s_node;
-                         cfgp->inet.socket = atp->atp_gref->lport;
-                         cfgp->ddptype = atp->atp_gref->ddptype;
-#endif
-                       }
-                       gbuf_wset(gbuf_cont(m), sizeof(ddp_addr_t));
-                       atp_iocack(atp, m);
-                       break;
-                                       
-               default:
-                       /*
-                        *      Otherwise pass it on, if possible
-                        */
-                       iocbp->ioc_private = (void *)gref;
-                       DDP_OUTPUT(m);
-                       break;
-         }
-               break;
-
-       default:
-               gbuf_freem(m);
-               break;
-       }
-} /* atp_wput */
-
-gbuf_t  *atp_build_release(trp)
-register struct atp_trans *trp;
-{
-       register gbuf_t   *m;
-       register at_ddp_t *ddp;
-       register at_atp_t   *athp;
-
-       /*
-        *      Now try and allocate enough space to send the message
-        *              if none is available the caller will schedule
-        *              a timeout so we can retry for more space soon
-        */
-       if ((m = (gbuf_t *)gbuf_alloc(AT_WR_OFFSET+ATP_HDR_SIZE, PRI_HI)) != NULL) {
-               gbuf_rinc(m,AT_WR_OFFSET);
-               gbuf_wset(m,TOTAL_ATP_HDR_SIZE);
-               ddp = AT_DDP_HDR(m);
-               ddp->type = DDP_ATP;
-               UAS_ASSIGN_HTON(ddp->checksum, 0);
-               ddp->dst_socket = trp->tr_socket.socket;
-               ddp->dst_node = trp->tr_socket.node;
-               NET_ASSIGN(ddp->dst_net, trp->tr_socket.net);
-               ddp->src_node = trp->tr_local_node;
-               NET_NET(ddp->src_net, trp->tr_local_net);
-
-               /*
-                * clear the cmd/xo/eom/sts/unused fields
-                */
-               athp = AT_ATP_HDR(m);
-               ATP_CLEAR_CONTROL(athp);
-               athp->cmd = ATP_CMD_TREL;
-               UAS_ASSIGN_HTON(athp->tid, trp->tr_tid);
-       }
-
-       return (m);
-}
-
-void atp_send_replies(atp, rcbp)
-     register struct atp_state *atp;
-     register struct atp_rcb   *rcbp;
-{       register gbuf_t *m;
-       register int     i, len;
-       int              cnt, offset, space;
-       register at_atp_t *athp;
-       register struct atpBDS *bdsp;
-       register gbuf_t *m1, *m0, *mhdr;
-#if DEBUG
-       gbuf_t *m2 = NULL;
-#endif /* DEBUG */
-       gbuf_t *mprev = 0, *mlist = 0;
-       at_socket src_socket = (at_socket)atp->atp_socket_no;
-       gbuf_t *rc_xmt[ATP_TRESP_MAX];
-       struct   ddp_atp {
-                char    ddp_atp_hdr[TOTAL_ATP_HDR_SIZE];
-       };
-       struct timeval timenow;
-
-       if (rcbp->rc_queue != atp)
-               return;
-       if (rcbp->rc_not_sent_bitmap == 0)
-               goto nothing_to_send;
-
-       dPrintf(D_M_ATP_LOW, D_L_OUTPUT, ("atp_send_replies\n"));
-       /*
-        *      Do this for each message that hasn't been sent
-        */
-       cnt = rcbp->rc_pktcnt;
-       for (i = 0; i < cnt; i++) {
-         rc_xmt[i] = 0;
-         if (rcbp->rc_snd[i]) {
-               if ((rc_xmt[i] = 
-                    gbuf_alloc(AT_WR_OFFSET+TOTAL_ATP_HDR_SIZE,PRI_MED)) 
-                   == NULL) {
-                       for (cnt = 0; cnt < i; cnt++)
-                               if (rc_xmt[cnt])
-                                       gbuf_freeb(rc_xmt[cnt]);
-                       goto nothing_to_send;
-               }
-         }
-       }
-
-       m = rcbp->rc_xmt;
-       m0 = gbuf_cont(m);
-       if (gbuf_len(m) > TOTAL_ATP_HDR_SIZE)
-               bdsp = (struct atpBDS *)(AT_ATP_HDR(m)->data);
-       else
-               bdsp = 0;
-       offset = 0;
-       if (m0)
-               space = gbuf_msgsize(m0);
-       else
-         space = 0;
-       for (i = 0; i < cnt; i++) {
-               if (rcbp->rc_snd[i] == 0) {
-                       if ((len = UAS_VALUE(bdsp->bdsBuffSz))) {
-                               offset += len;
-                               space -= len;
-                       }
-               } else {
-                       mhdr = rc_xmt[i];
-                       /* setup header fields */
-                       gbuf_rinc(mhdr,AT_WR_OFFSET);
-                       gbuf_wset(mhdr,TOTAL_ATP_HDR_SIZE);
-                       *(struct ddp_atp *)(gbuf_rptr(mhdr))= *(struct ddp_atp *)(gbuf_rptr(m));
-                       athp = AT_ATP_HDR(mhdr);
-                       ATP_CLEAR_CONTROL(athp);
-                       athp->cmd = ATP_CMD_TRESP;
-                       athp->bitmap = i;
-                       if (i == (cnt - 1))
-                               athp->eom = 1; /* for the last fragment */
-                       if (bdsp) {
-                               UAL_UAL(athp->user_bytes, bdsp->bdsUserData);
-                               if ((len = UAS_VALUE(bdsp->bdsBuffSz)) && m0 != 0 && space > 0) {
-                                       if ((m1 = m_copym(m0, offset, len, M_DONTWAIT)) == 0) {
-                                               for (i = 0; i < cnt; i++)
-                                                       if (rc_xmt[i])
-                                                               gbuf_freem(rc_xmt[i]);
-                                               goto nothing_to_send;
-                                       }
-                                       offset += len;
-                                       space -= len;
-                                       gbuf_cont(mhdr) = m1;
-                               }
-                       }       
-                               
-                       AT_DDP_HDR(mhdr)->src_socket = src_socket;
-                       dPrintf(D_M_ATP_LOW, D_L_OUTPUT,
-                               ("atp_send_replies: %d, socket=%d, size=%d\n",
-                               i, atp->atp_socket_no, gbuf_msgsize(gbuf_cont(m2))));
-       
-                       if (mlist)
-                               gbuf_next(mprev) = mhdr;
-                       else
-                               mlist = mhdr;
-                       mprev = mhdr;
-       
-                       rcbp->rc_snd[i] = 0;
-                       rcbp->rc_not_sent_bitmap &= ~atp_mask[i];
-                       if (rcbp->rc_not_sent_bitmap == 0)
-                               break;
-               }
-               /*
-                * on to the next frag
-                */
-               bdsp++;
-       }
-       if (mlist)
-               DDP_OUTPUT(mlist);
-       
-
-nothing_to_send:
-       /*
-        *      If all replies from this reply block have been sent then 
-        *              remove it from the queue and mark it so
-        */
-       if (rcbp->rc_queue != atp)
-               return;
-       rcbp->rc_rep_waiting = 0;
-
-       /*
-        *      If we are doing execute once re-set the rcb timeout 
-        *      each time we send back any part of the response. Note
-        *      that this timer is started when an initial request is
-        *      received. Each response reprimes the timer.  Duplicate
-        *      requests do not reprime the timer.
-        *     
-        *      We have sent all of a response so free the 
-        *      resources.
-        */
-       if (rcbp->rc_xo && rcbp->rc_state != RCB_RELEASED) {
-               getmicrouptime(&timenow);
-               if (rcbp->rc_timestamp == 0) {
-                       rcbp->rc_timestamp = timenow.tv_sec;
-                       if (rcbp->rc_timestamp == 0)
-                               rcbp->rc_timestamp = 1;
-                       ATP_Q_APPEND(atp_need_rel, rcbp, rc_tlist);
-               }
-               rcbp->rc_state = RCB_RESPONSE_FULL;
-       } else
-               atp_rcb_free(rcbp);
-} /* atp_send_replies */
-
-
-static int
-atp_pack_bdsp(trp, bdsp)
-     register struct atp_trans *trp;
-     register struct atpBDS *bdsp;
-{
-       register gbuf_t *m = NULL;
-       register int i, datsize = 0;
-       struct atpBDS *bdsbase = bdsp;
-       int error = 0;
-
-       dPrintf(D_M_ATP, D_L_INFO, ("atp_pack_bdsp: socket=%d\n",
-               trp->tr_queue->atp_socket_no));
-
-       for (i = 0; i < ATP_TRESP_MAX; i++, bdsp++) {
-               unsigned short bufsize = UAS_VALUE(bdsp->bdsBuffSz);
-               long bufaddr = UAL_VALUE(bdsp->bdsBuffAddr);
-
-               if ((m = trp->tr_rcv[i]) == NULL)
-                       break;
-
-               /* discard ddp hdr on first packet */
-               if (i == 0)
-                       gbuf_rinc(m,DDP_X_HDR_SIZE); 
-
-               /* this field may contain control information even when 
-                  no data is present */
-               UAL_UAL(bdsp->bdsUserData, 
-                       (((at_atp_t *)(gbuf_rptr(m)))->user_bytes));
-               gbuf_rinc(m, ATP_HDR_SIZE);
-
-               if ((bufsize != 0) && (bufaddr != 0)) {
-                       /* user expects data back */
-                       short tmp = 0;
-                       register char *buf = (char *)bufaddr;
-
-                       while (m) {
-                               unsigned short len = (unsigned short)(gbuf_len(m));
-                               if (len) {
-                                       if (len > bufsize)
-                                               len = bufsize;
-                                       if ((error = copyout((caddr_t)gbuf_rptr(m), 
-                                               CAST_USER_ADDR_T(&buf[tmp]),
-                                               len)) != 0) {
-                                               return error;
-                                       }
-                                       bufsize -= len;
-                                       tmp += len;
-                               }
-                               m = gbuf_cont(m);
-                       }
-
-                       UAS_ASSIGN(bdsp->bdsDataSz, tmp);
-                       datsize += (int)tmp;
-               }
-               gbuf_freem(trp->tr_rcv[i]);
-               trp->tr_rcv[i] = NULL;
-       }
-
-       /* report the number of packets */
-       UAS_ASSIGN(((struct atpBDS *)bdsbase)->bdsBuffSz, i);
-
-       dPrintf(D_M_ATP, D_L_INFO, ("             : size=%d\n",
-               datsize));
-       
-       return 0;
-} /* atp_pack_bdsp */
-
-
-/* create an mbuf chain with mbuf packet headers for each ATP response packet
- * to be sent.  m contains the DDP hdr, ATP hdr, and and array of atpBDS structs.  
- * chained to m is an mbuf that contians the actual data pointed to by the atpBDS
- * structs.
- */
-static int
-atp_unpack_bdsp(atp, m, rcbp, cnt, wait)
-       struct atp_state *atp;
-        gbuf_t          *m;    /* ddp, atp and bdsp gbuf_t */
-       register struct atp_rcb *rcbp;
-    register int    cnt, wait;
-{
-       register struct atpBDS *bdsp;
-       register         gbuf_t        *m2, *m1, *m0, *mhdr;
-    at_atp_t    *athp;
-       int             i, len;
-       at_socket       src_socket;
-       
-       struct ddp_atp {
-                char    ddp_atp_hdr[TOTAL_ATP_HDR_SIZE];
-       };
-       gbuf_t                  *mprev = 0, *mlist = 0;
-       gbuf_t                  *rc_xmt[ATP_TRESP_MAX];
-       int                             offset, space = 0;
-       struct timeval timenow;
-
-       /*
-        * get the user data structure pointer
-        */
-       bdsp = (struct atpBDS *)(AT_ATP_HDR(m)->data);
-
-       /*
-        * Guard against bogus count argument.
-        */
-       if ((unsigned) cnt > ATP_TRESP_MAX) {
-               dPrintf(D_M_ATP, D_L_ERROR,
-                       ("atp_unpack_bdsp: bad bds count 0x%x\n", cnt));
-               gbuf_freem(m);
-               return(EINVAL);
-       }
-       if ((src_socket = (at_socket)atp->atp_socket_no) == 0xFF) {
-         /* comparison was to -1, however src_socket is a u_char */
-               gbuf_freem(m);
-               return EPIPE;
-       }
-
-       m0 = gbuf_cont(m);
-       rcbp->rc_xmt = m;
-       rcbp->rc_pktcnt = cnt;
-       rcbp->rc_state = RCB_SENDING;
-       rcbp->rc_not_sent_bitmap = 0;
-
-       if (cnt <= 1) {
-               /*
-                * special case this to
-                * improve AFP write transactions to the server
-                */
-               rcbp->rc_pktcnt = 1;
-               if ((m2 = gbuf_alloc_wait(AT_WR_OFFSET+TOTAL_ATP_HDR_SIZE, 
-                                         wait)) == NULL)
-                   return 0;
-               gbuf_rinc(m2,AT_WR_OFFSET);
-               gbuf_wset(m2,TOTAL_ATP_HDR_SIZE);
-               *(struct ddp_atp *)(gbuf_rptr(m2))= *(struct ddp_atp *)(gbuf_rptr(m));
-               athp = AT_ATP_HDR(m2);
-               ATP_CLEAR_CONTROL(athp);
-               athp->cmd = ATP_CMD_TRESP;
-               athp->bitmap = 0;
-               athp->eom = 1;     /* there's only 1 fragment */
-
-               /* *** why only if cnt > 0? *** */
-               if (cnt > 0)
-                       UAL_UAL(athp->user_bytes, bdsp->bdsUserData);
-               if (m0)
-                       if (!append_copy((struct mbuf *)m2, 
-                                        (struct mbuf *)m0, wait)) {
-                               gbuf_freeb(m2);
-                               return 0;
-                       }
-               /*
-                *      send the message and mark it as sent
-                */
-               AT_DDP_HDR(m2)->src_socket = src_socket;
-               dPrintf(D_M_ATP_LOW, D_L_INFO,
-                       ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
-                       0,atp->atp_socket_no,gbuf_msgsize(gbuf_cont(m2)),cnt));
-               mlist = m2;
-               goto l_send;
-       }
-
-       /* create an array of mbuf packet headers for the packets to be sent
-        * to contain the atp and ddp headers with room at the front for the
-        * datalink header.
-        */
-       for (i = 0; i < cnt; i++) {
-               /* all hdrs, packet data and dst addr storage */
-               if ((rc_xmt[i] = 
-                    gbuf_alloc_wait(AT_WR_OFFSET+TOTAL_ATP_HDR_SIZE, wait)) == NULL) {
-                               for (cnt = 0; cnt < i; cnt++)
-                                       if (rc_xmt[cnt])
-                                               gbuf_freeb(rc_xmt[cnt]);
-                               return 0;
-               }
-       }
-
-       /* run through the atpBDS structs and create an mbuf for the data
-        * portion of each packet to be sent.  these get chained to the mbufs
-        * containing the ATP and DDP headers.  this code assumes that no ATP
-        * packet is contained in more than 2 mbufs (e.i crosses mbuf boundary
-        * no more than one time).
-        */
-       offset = 0;
-       if (m0)
-               space = gbuf_msgsize(m0);
-       for (i = 0; i < cnt; i++) {                     /* for each hdr mbuf */
-           mhdr = rc_xmt[i];
-           /* setup header fields */
-               gbuf_rinc(mhdr,AT_WR_OFFSET);
-               gbuf_wset(mhdr,TOTAL_ATP_HDR_SIZE);
-               *(struct ddp_atp *)(gbuf_rptr(mhdr))= *(struct ddp_atp *)(gbuf_rptr(m));
-               athp = AT_ATP_HDR(mhdr);
-               ATP_CLEAR_CONTROL(athp);
-               athp->cmd = ATP_CMD_TRESP;
-               athp->bitmap = i;
-               if (i == (cnt - 1))
-                       athp->eom = 1; /* for the last fragment */
-               UAL_UAL(athp->user_bytes, bdsp->bdsUserData);
-               
-               if ((len = UAS_VALUE(bdsp->bdsBuffSz)) != 0  && m0 != 0 && space > 0) {         
-                       if ((m1 = m_copym(m0, offset, len, wait)) == 0) {
-                               for (i = 0; i < cnt; i++)
-                                       if (rc_xmt[i])
-                                               gbuf_freem(rc_xmt[i]);
-                               return 0;
-                       }
-                       gbuf_cont(mhdr) = m1;
-                       space -= len;
-                       offset += len;
-               }
-                               
-               AT_DDP_HDR(mhdr)->src_socket = src_socket;
-               dPrintf(D_M_ATP_LOW,D_L_INFO,
-                       ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
-                       i,atp->atp_socket_no,gbuf_msgsize(gbuf_cont(mhdr)),cnt));
-               if (mlist)
-                       gbuf_next(mprev) = mhdr;
-               else
-                       mlist = mhdr;
-               mprev = mhdr;
-               /*
-                * on to the next frag
-                */
-               bdsp++;
-       }
-       /*
-        * send the message
-        */
-l_send:
-       if (rcbp->rc_xo) {
-               getmicrouptime(&timenow);
-               if (rcbp->rc_timestamp == 0) {
-                       if ((rcbp->rc_timestamp = timenow.tv_sec) == 0)
-                               rcbp->rc_timestamp = 1;
-                       ATP_Q_APPEND(atp_need_rel, rcbp, rc_tlist);
-               }
-       }
-
-       DDP_OUTPUT(mlist);
-       return 0;
-
-} /* atp_unpack_bdsp */
-
-#define ATP_SOCKET_LAST  (DDP_SOCKET_LAST-6)
-#define ATP_SOCKET_FIRST (DDP_SOCKET_1st_DYNAMIC)
-static unsigned int sNext = 0;
-extern unsigned char asp_inpC[];
-extern asp_scb_t *asp_scbQ[];
-
-int atp_bind(gref, sVal, flag)
-       gref_t *gref;
-       unsigned int sVal;
-       unsigned char *flag;
-{
-       unsigned char inpC, sNextUsed = 0;
-       unsigned int sMin, sMax, sSav = 0;
-       struct atp_state *atp;
-
-       atp = (struct atp_state *)gref->info;
-       if (atp->dflag)
-               atp = (struct atp_state *)atp->atp_msgq;
-
-       sMax = ATP_SOCKET_LAST;
-       sMin = ATP_SOCKET_FIRST;
-       if (flag && (*flag == 3)) {
-               sMin += 40;
-               if (sMin < sNext) {
-                       sMin = sNext;
-                       sNextUsed = 1;
-               }
-       }
-
-       if ( (sVal != 0) && 
-            ((sVal > sMax) || (sVal < 2) || (sVal == 6) || 
-             (ddp_socket_inuse(sVal, DDP_ATP) &&
-              (atp_inputQ[sVal] != (gref_t *)1)))) {
-               return 0;
-       }
-
-       if (sVal == 0) {
-               inpC = 255;
-again:
-               for (sVal=sMin; sVal <= sMax; sVal++) {
-                       if (!ddp_socket_inuse(sVal, DDP_ATP) ||
-                           atp_inputQ[sVal] == (gref_t *)1)
-                               break;
-                       else if (flag && (*flag == 3) && asp_scbQ[sVal]) {
-                               if ((asp_scbQ[sVal]->dflag == *flag)
-                                   && (asp_inpC[sVal] < inpC) ) {
-                                 inpC = asp_inpC[sVal];
-                                 sSav = sVal;
-                               }
-                       }
-               }
-               if (sVal > sMax) {
-                       if (flag && (*flag == 3)) {
-                               if (sNextUsed) {
-                                       sNextUsed = 0;
-                                       sMax = sNext - 1;
-                                       sMin = ATP_SOCKET_FIRST+40;
-                                       goto again;
-                               }
-                               sNext = 0;
-                               *flag = (unsigned char)sSav;
-                       }
-                       return 0;
-               }
-       }
-       atp->atp_socket_no = (short)sVal;
-       atp_inputQ[sVal] = gref;
-       if (flag == 0)
-               atp_pidM[sVal] = atp->atp_pid;
-       else if (*flag == 3) {
-               sNext = sVal + 1;
-               if (sNext > ATP_SOCKET_LAST)
-                       sNext = 0;
-       }
-
-       return (int)sVal;
-}
-
-void atp_req_ind(atp, mioc)
-       register struct atp_state *atp;
-       register gbuf_t *mioc;
-{
-       register struct atp_rcb *rcbp;
-
-       if ((rcbp = atp->atp_attached.head) != 0) {
-               gbuf_cont(mioc) = rcbp->rc_ioctl;
-               rcbp->rc_ioctl = NULL;
-               if (rcbp->rc_xo) {
-                       ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list);
-                       rcbp->rc_state = RCB_NOTIFIED;
-                       ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
-               } else
-                       atp_rcb_free(rcbp);
-               if (gbuf_cont(mioc))
-                 ((ioc_t *)gbuf_rptr(mioc))->ioc_count = gbuf_msgsize(gbuf_cont(mioc));
-               else
-                 ((ioc_t *)gbuf_rptr(mioc))->ioc_count = 0;
-               asp_ack_reply(atp->atp_gref, mioc);
-       } else
-               gbuf_freeb(mioc);
-}
-
-void atp_rsp_ind(trp, mioc)
-    register struct atp_trans *trp;
-       register gbuf_t *mioc;
-{
-       register struct atp_state *atp = trp->tr_queue;
-       register int err;
-       gbuf_t *xm = 0;
-
-       err = 0;
-       {
-           switch (trp->tr_state) {
-           case TRANS_DONE:
-                       if (asp_pack_bdsp(trp, &xm) < 0)
-                           err = EFAULT;
-                       gbuf_cont(mioc) = trp->tr_xmt;
-                       trp->tr_xmt = NULL;
-                       break;
-
-           case TRANS_FAILED:
-                       err = ETIMEDOUT;
-                       break;
-
-           default:
-                       err = ENOENT;
-                       break;
-           }
-           atp_free(trp);
-
-           if (err) {
-                       dPrintf(D_M_ATP, D_L_ERROR,
-                               ("atp_rsp_ind: TRANSACTION error\n"));
-                       atp_iocnak(atp, mioc, err);
-           } else {
-                       gbuf_cont(gbuf_cont(mioc)) = xm;
-               atp_iocack(atp, mioc);
-           }
-       }
-}
-
-void atp_cancel_req(gref, tid)
-       gref_t *gref;
-       unsigned short tid;
-{
-       struct atp_state *atp;
-       struct atp_trans *trp;
-
-       atp = (struct atp_state *)gref->info;
-       if (atp->dflag)
-               atp = (struct atp_state *)atp->atp_msgq;
-
-       for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
-           if (trp->tr_tid == tid)
-                       break;
-       }
-       if (trp != NULL)
-               atp_free(trp);
-}
-
-/*
- * remove atp from the use list
- */
-void
-atp_dequeue_atp(atp)
-       struct atp_state *atp;
-{
-
-       if (atp == atp_used_list) {
-               if ((atp_used_list = atp->atp_trans_waiting) != 0)
-                       atp->atp_trans_waiting->atp_rcb_waiting = 0;
-       } else if (atp->atp_rcb_waiting) {
-               if ((atp->atp_rcb_waiting->atp_trans_waiting
-                               = atp->atp_trans_waiting) != 0)
-                       atp->atp_trans_waiting->atp_rcb_waiting = atp->atp_rcb_waiting;
-       }
-
-       atp->atp_trans_waiting = 0;
-       atp->atp_rcb_waiting = 0;
-}
-
-void
-atp_timout(func, trp, ticks)
-       atp_tmo_func func;
-       struct atp_trans *trp;
-       int ticks;
-{
-       unsigned int sum;
-       struct atp_trans *curr_trp, *prev_trp;
-
-       if (trp->tr_tmo_func)
-               return;
-
-       trp->tr_tmo_func = func;
-       trp->tr_tmo_delta = 1+(ticks>>5);
-
-       if (trp_tmo_list == 0) {
-               trp->tr_tmo_next = trp->tr_tmo_prev = 0;
-               trp_tmo_list = trp;
-               return;
-       }
-
-       prev_trp = 0;
-       curr_trp = trp_tmo_list;
-       sum = 0;
-
-       while (1) {
-               sum += curr_trp->tr_tmo_delta;
-               if (sum > trp->tr_tmo_delta) {
-                       sum -= curr_trp->tr_tmo_delta;
-                       trp->tr_tmo_delta -= sum;
-                       curr_trp->tr_tmo_delta -= trp->tr_tmo_delta;
-                       break;
-               }
-               prev_trp = curr_trp;
-               if ((curr_trp = curr_trp->tr_tmo_next) == 0) {
-                       trp->tr_tmo_delta -= sum;
-                       break;
-               }
-       }
-
-       if (prev_trp) {
-               trp->tr_tmo_prev = prev_trp;
-               if ((trp->tr_tmo_next = prev_trp->tr_tmo_next) != 0)
-                       prev_trp->tr_tmo_next->tr_tmo_prev = trp;
-               prev_trp->tr_tmo_next = trp;
-       } else {
-               trp->tr_tmo_prev = 0;
-               trp->tr_tmo_next = trp_tmo_list;
-               trp_tmo_list->tr_tmo_prev = trp;
-               trp_tmo_list = trp;
-       }
-}
-
-void
-atp_untimout(
-       __unused atp_tmo_func func,
-       struct atp_trans *trp)
-{
-
-       if (trp->tr_tmo_func == 0)
-               return;
-
-       if (trp_tmo_list == trp) {
-               if ((trp_tmo_list = trp->tr_tmo_next) != 0) {
-                       trp_tmo_list->tr_tmo_prev = 0;
-                       trp->tr_tmo_next->tr_tmo_delta += trp->tr_tmo_delta;
-               }
-       } else {
-               if ((trp->tr_tmo_prev->tr_tmo_next = trp->tr_tmo_next) != 0) {
-                       trp->tr_tmo_next->tr_tmo_prev = trp->tr_tmo_prev;
-                       trp->tr_tmo_next->tr_tmo_delta += trp->tr_tmo_delta;
-               }
-       }
-       trp->tr_tmo_func = 0;
-}
-
-void
-atp_trp_clock_locked(arg)
-       void *arg;
-{
-       atalk_lock();
-       atp_trp_clock(arg);
-       atalk_unlock();
-}
-
-void
-atp_trp_clock(arg)
-       void *arg;
-{
-       struct atp_trans *trp;
-       atp_tmo_func tr_tmo_func;
-
-       if (trp_tmo_list)
-               trp_tmo_list->tr_tmo_delta--;
-       while (((trp = trp_tmo_list) != 0) && (trp_tmo_list->tr_tmo_delta == 0)) {
-               if ((trp_tmo_list = trp->tr_tmo_next) != 0)
-                       trp_tmo_list->tr_tmo_prev = 0;
-               if ((tr_tmo_func = trp->tr_tmo_func) != 0) {
-                       trp->tr_tmo_func = 0;
-                       (*tr_tmo_func)(trp);
-               }
-       }
-
-       timeout(atp_trp_clock_locked, (void *)arg, (1<<5));
-}
-
-void
-atp_send_req(gref, mioc)
-       gref_t *gref;
-       gbuf_t *mioc;
-{
-       register struct atp_state *atp;
-       register struct atp_trans *trp;
-       register ioc_t *iocbp;
-       register at_atp_t *athp;
-       register at_ddp_t *ddp;
-       gbuf_t *m, *m2, *bds;
-       struct atp_set_default *sdb;
-       int old;
-       unsigned int timer;
-       u_short         temp_net;
-
-       atp = (struct atp_state *)((struct atp_state *)gref->info)->atp_msgq;
-       iocbp = (ioc_t *)gbuf_rptr(mioc);
-
-       if ((trp = atp_trans_alloc(atp)) == NULL) {
-l_retry:
-               ((asp_scb_t *)gref->info)->stat_msg = mioc;
-               iocbp->ioc_private = (void *)gref;
-               timeout(atp_retry_req, mioc, 10);
-               return;
-       }
-
-       m2 = gbuf_cont(mioc);
-       if ((bds = gbuf_dupb(m2)) == NULL) {
-               atp_trans_free(trp);
-               goto l_retry;
-       }
-       gbuf_rinc(m2,atpBDSsize);
-       gbuf_wset(bds,atpBDSsize);
-       iocbp->ioc_count -= atpBDSsize;
-       gbuf_cont(m2) = NULL;
-
-       old = iocbp->ioc_cmd;
-       iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST;
-       sdb = (struct atp_set_default *)gbuf_rptr(m2);
-
-       /*
-        * The at_snd_req library routine multiplies seconds by 100.
-        * We need to divide by 100 in order to obtain the timer.
-        */
-       if ((timer = (sdb->def_rate * HZ)/100) == 0)
-           timer = HZ;
-       iocbp->ioc_count -= sizeof(struct atp_set_default);
-       gbuf_rinc(m2,sizeof(struct atp_set_default));
-
-       trp->tr_retry = sdb->def_retries;
-       trp->tr_timeout = timer;
-       trp->tr_bdsp = bds;
-       trp->tr_tid = atp_tid(atp);
-       trp->tr_xmt = mioc;
-
-       /*
-        *      Now fill in the header (and remember the bits
-        *              we need to know)
-        */
-       athp = AT_ATP_HDR(m2);
-       athp->cmd = ATP_CMD_TREQ;
-       UAS_ASSIGN_HTON(athp->tid, trp->tr_tid);
-       athp->eom = 0;
-       athp->sts = 0;
-       trp->tr_xo = athp->xo;
-       trp->tr_bitmap = athp->bitmap;
-       ddp = AT_DDP_HDR(m2);
-       ddp->type = DDP_ATP;
-       ddp->src_socket = (at_socket)atp->atp_socket_no;
-       trp->tr_socket.socket = ddp->dst_socket;
-       trp->tr_socket.node = ddp->dst_node;
-       trp->tr_socket.net = NET_VALUE(ddp->dst_net);
-       trp->tr_local_socket = atp->atp_socket_no;
-       trp->tr_local_node = ddp->src_node;
-       temp_net = NET_VALUE(ddp->src_net);
-       NET_ASSIGN_NOSWAP(trp->tr_local_net, temp_net);
-
-#ifdef NOT_YET
-       /* save the local information in the gref */
-       atp->atp_gref->laddr.s_net = NET_VALUE(ddp->src_net);
-       atp->atp_gref->laddr.s_node = ddp->src_node;
-       atp->atp_gref->lport = ddp->src_node;
-       atp->atp_gref->ddptype = DDP_ATP;
-#endif
-
-       /*
-        *      Put us in the transaction waiting queue
-        */
-       ATP_Q_APPEND(atp->atp_trans_wait, trp, tr_list);
-
-       /*
-        * Send the message and set the timer   
-        */
-       m = (gbuf_t *)copy_pkt(m2, sizeof(llc_header_t));
-       if (!trp->tr_retry && !trp->tr_bitmap && !trp->tr_xo)
-               atp_x_done(trp); /* no reason to tie up resources */
-       else
-               atp_timout(atp_req_timeout, trp, trp->tr_timeout);
-       if (m) {
-               trace_mbufs(D_M_ATP_LOW, "  s", m);
-               DDP_OUTPUT(m);
-       }
-} /* atp_send_req */
-
-void atp_retry_req(arg)
-       void *arg;
-{
-       gbuf_t *m = (gbuf_t *)arg;
-       gref_t *gref;
-
-       atalk_lock();
-
-       gref = (gref_t *)((ioc_t *)gbuf_rptr(m))->ioc_private;
-       if (gref->info) {
-               ((asp_scb_t *)gref->info)->stat_msg = 0;
-               atp_send_req(gref, m);
-       }
-       atalk_unlock();
-}
-
-void atp_send_rsp(gref, m, wait)
-       gref_t *gref;
-       gbuf_t *m;
-       int wait;
-{
-       register struct atp_state *atp;
-       register struct atp_rcb *rcbp;
-       register at_atp_t *athp;
-       register at_ddp_t *ddp;
-       int s, xcnt;
-       u_short temp_net;
-
-       atp = (struct atp_state *)gref->info;
-       if (atp->dflag)
-               atp = (struct atp_state *)atp->atp_msgq;
-       ddp = AT_DDP_HDR(m);
-       athp = AT_ATP_HDR(m);
-
-       /*
-        *      search for the corresponding rcb
-        */
-       for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) {
-           if ( (rcbp->rc_tid == UAS_VALUE_NTOH(athp->tid)) &&
-                       (rcbp->rc_socket.node == ddp->dst_node) &&
-                       (rcbp->rc_socket.net == NET_VALUE(ddp->dst_net)) &&
-                       (rcbp->rc_socket.socket == ddp->dst_socket) )
-               break;
-       }
-
-       /*
-        *      If it has already been sent then drop the request
-        */
-       if ((rcbp && (rcbp->rc_state != RCB_NOTIFIED)) ||
-                       (rcbp == NULL && athp->xo) ) {
-               gbuf_freem(m);
-               return;
-       }
-
-       if (rcbp == NULL) { /* a response is being sent for an ALO transaction */
-           if ((rcbp = atp_rcb_alloc(atp)) == NULL) {
-                       gbuf_freem(m);
-                       return;
-           }
-           rcbp->rc_ioctl = 0;
-           rcbp->rc_socket.socket = ddp->dst_socket;
-           rcbp->rc_socket.node = ddp->dst_node;
-           rcbp->rc_socket.net = NET_VALUE(ddp->dst_net);
-           rcbp->rc_tid = UAS_VALUE_NTOH(athp->tid);
-           rcbp->rc_bitmap = 0xff;
-           rcbp->rc_xo = 0;
-           rcbp->rc_state = RCB_RESPONSE_FULL;
-           ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
-       }
-       else if (ddp->src_node == 0) {
-               temp_net = NET_VALUE_NOSWAP(rcbp->rc_local_net);
-               NET_ASSIGN(ddp->src_net, temp_net);
-               ddp->src_node = rcbp->rc_local_node;
-       }
-
-       xcnt = get_bds_entries(m);
-       s = atp_unpack_bdsp(atp, m, rcbp, xcnt, wait);
-       if (s == 0)
-               atp_send_replies(atp, rcbp);
-} /* atp_send_rsp */
-
-int asp_pack_bdsp(trp, xm)
-     register struct  atp_trans     *trp;
-     gbuf_t **xm;
-{
-       register struct atpBDS *bdsp;
-       register gbuf_t        *m, *m2;
-       register int           i;
-       gbuf_t        *m_prev = 0, *m_head = 0;
-
-       dPrintf(D_M_ATP, D_L_INFO, ("asp_pack_bdsp: socket=%d\n",
-               trp->tr_queue->atp_socket_no));
-
-       if ((m2 = trp->tr_bdsp) == NULL)
-               return 0;
-       trp->tr_bdsp = NULL;
-       bdsp = (struct atpBDS *)gbuf_rptr(m2);
-
-       for (i = 0; (i < ATP_TRESP_MAX && 
-                    bdsp < (struct atpBDS *)(gbuf_wptr(m2))); i++) {
-               if ((m = trp->tr_rcv[i]) == NULL)
-                       break;
-               if (i == 0) {
-                       /* discard ddp hdr on first packet */
-                       gbuf_rinc(m,DDP_X_HDR_SIZE); 
-               }
-
-               UAL_UAL(bdsp->bdsUserData, (((at_atp_t *)(gbuf_rptr(m)))->user_bytes));
-               gbuf_rinc(m, ATP_HDR_SIZE);
-
-               if (UAL_VALUE(bdsp->bdsBuffAddr)) {
-                       short tmp = 0;
-
-                       /* user expects data back */
-                       m = gbuf_strip(m);
-                       if (m_head == 0)
-                               m_head = m;
-                       else
-                               gbuf_cont(m_prev) = m;
-                       if (m) {
-                               tmp = (short)gbuf_len(m);
-                               while (gbuf_cont(m)) {
-                                       m = gbuf_cont(m);
-                                       tmp += (short)(gbuf_len(m));
-                               }
-                               m_prev = m;
-                       }
-                       UAS_ASSIGN(bdsp->bdsDataSz, tmp);
-               }
-               trp->tr_rcv[i] = NULL;
-               bdsp++;
-
-       }
-       /*
-        * report the number of packets
-        */
-       UAS_ASSIGN(((struct atpBDS *)gbuf_rptr(m2))->bdsBuffSz, i);
-
-       if (trp->tr_xmt) /* an ioctl block is still held? */
-               gbuf_cont(trp->tr_xmt) = m2;
-       else
-               trp->tr_xmt = m2;
-
-       if (m_head)
-               *xm = m_head;
-       else
-               *xm = 0;
-
-       dPrintf(D_M_ATP, D_L_INFO, ("             : size=%d\n",
-               gbuf_msgsize(*xm)));
-
-       return 0;
-}
-
-/*
- * The following routines are direct entries from system
- * calls to allow fast sending and recving of ATP data.
- */
-
-int
-_ATPsndreq(fd, buf, len, nowait, err, proc)
-       int fd;
-       unsigned char *buf;
-       int len;
-       int nowait;
-       int *err;
-       void *proc;
-{
-       gref_t *gref;
-       int rc;
-       unsigned short tid;
-       unsigned int timer;
-       register struct atp_state *atp;
-       register struct atp_trans *trp;
-       register ioc_t *iocbp;
-       register at_atp_t *athp;
-       register at_ddp_t *ddp;
-       struct atp_set_default *sdb;
-       gbuf_t *m2, *m, *mioc;
-       char bds[atpBDSsize];
-
-       if ((*err = atalk_getref(0, fd, &gref, proc, 1)) != 0)
-               return -1;
-
-       if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
-                       || (atp->atp_flags & ATP_CLOSING)) {
-               dPrintf(D_M_ATP, D_L_ERROR, ("ATPsndreq: stale handle=0x%x, pid=%d\n",
-                       (u_int) gref, gref->pid));
-               file_drop(fd);
-               *err = EINVAL;
-               return -1;
-       }
-
-       if (len < atpBDSsize + sizeof(struct atp_set_default) + TOTAL_ATP_HDR_SIZE ||
-               len > atpBDSsize + sizeof(struct atp_set_default) + TOTAL_ATP_HDR_SIZE + 
-               ATP_DATA_SIZE) {
-               file_drop(fd);
-               *err = EINVAL;
-               return -1;
-       }
-
-       while ((mioc = gbuf_alloc(sizeof(ioc_t), PRI_MED)) == 0) {
-               struct timespec ts;
-               /* the vaue of 10n terms of hz is 100ms */
-               ts.tv_sec = 0;
-               ts.tv_nsec = 100 *1000 * NSEC_PER_USEC;
-
-               rc = msleep(&atp->atp_delay_event, atalk_mutex, PSOCK | PCATCH, "atpmioc", &ts);
-               if (rc != 0) {
-                       *err = rc;
-                       file_drop(fd);
-                       return -1;
-               }
-               
-       }
-       gbuf_wset(mioc,sizeof(ioc_t));
-       len -= atpBDSsize;
-       while ((m2 = gbuf_alloc(len, PRI_MED)) == 0) {
-        struct timespec ts;
-        /* the vaue of 10n terms of hz is 100ms */
-        ts.tv_sec = 0;
-        ts.tv_nsec = 100 *1000 * NSEC_PER_USEC;
-
-               rc = msleep(&atp->atp_delay_event, atalk_mutex, PSOCK | PCATCH, "atpm2", &ts);
-               if (rc != 0) {
-                       gbuf_freeb(mioc);
-                       file_drop(fd);
-                       *err = rc;
-                       return -1;
-               }
-       }
-       gbuf_wset(m2, len);
-       gbuf_cont(mioc) = m2;
-       if (((*err = copyin(CAST_USER_ADDR_T(buf), (caddr_t)bds, atpBDSsize)) != 0)
-               || ((*err = copyin(CAST_USER_ADDR_T(&buf[atpBDSsize]),
-                       (caddr_t)gbuf_rptr(m2), len)) != 0)) {
-               gbuf_freem(mioc);
-               file_drop(fd);
-               return -1;
-       }
-       gbuf_set_type(mioc, MSG_IOCTL);
-       iocbp = (ioc_t *)gbuf_rptr(mioc);
-       iocbp->ioc_count = len;
-       iocbp->ioc_cmd = nowait ? AT_ATP_ISSUE_REQUEST_NOTE : AT_ATP_ISSUE_REQUEST;
-       sdb = (struct atp_set_default *)gbuf_rptr(m2);
-
-       /*
-        * The at_snd_req library routine multiplies seconds by 100.
-        * We need to divide by 100 in order to obtain the timer.
-        */
-       if ((timer = (sdb->def_rate * HZ)/100) == 0)
-           timer = HZ;
-       iocbp->ioc_count -= sizeof(struct atp_set_default);
-       gbuf_rinc(m2,sizeof(struct atp_set_default));
-
-       /*
-        * allocate and set up the transaction record
-        */
-       while ((trp = atp_trans_alloc(atp)) == 0) {
-        struct timespec ts;
-        /* the vaue of 10n terms of hz is 100ms */
-        ts.tv_sec = 0;
-        ts.tv_nsec = 100 *1000 * NSEC_PER_USEC;
-
-               rc = msleep(&atp->atp_delay_event, atalk_mutex, PSOCK | PCATCH, "atptrp", &ts);
-               if (rc != 0) {
-                       gbuf_freem(mioc);
-                       file_drop(fd);
-                       *err = rc;
-                       return -1;
-               }
-       }
-       trp->tr_retry = sdb->def_retries;
-       trp->tr_timeout = timer;
-       trp->tr_bdsp = NULL;
-       trp->tr_tid = atp_tid(atp);
-       tid = trp->tr_tid;
-
-       /*
-        *      remember the IOCTL packet so we can ack it
-        *              later
-        */
-       trp->tr_xmt = mioc;
-
-       /*
-        *      Now fill in the header (and remember the bits
-        *              we need to know)
-        */
-       athp = AT_ATP_HDR(m2);
-       athp->cmd = ATP_CMD_TREQ;
-       UAS_ASSIGN_HTON(athp->tid, trp->tr_tid);
-       athp->eom = 0;
-       athp->sts = 0;
-       trp->tr_xo = athp->xo;
-       trp->tr_bitmap = athp->bitmap;
-       ddp = AT_DDP_HDR(m2);
-       ddp->type = DDP_ATP;
-       ddp->src_socket = (at_socket)atp->atp_socket_no;
-       ddp->src_node = 0;
-       trp->tr_socket.socket = ddp->dst_socket;
-       trp->tr_socket.node = ddp->dst_node;
-       trp->tr_socket.net = NET_VALUE(ddp->dst_net);
-       trp->tr_local_socket = atp->atp_socket_no;
-
-#ifdef NOT_YET
-       /* save the local information in the gref */
-       atp->atp_gref->laddr.s_net = NET_VALUE(ddp->src_net);
-       atp->atp_gref->laddr.s_node = ddp->src_node;
-       atp->atp_gref->lport = ddp->src_node;
-       atp->atp_gref->ddptype = DDP_ATP;
-#endif
-
-       /*
-        *      Put us in the transaction waiting queue
-        */
-       ATP_Q_APPEND(atp->atp_trans_wait, trp, tr_list);
-
-       /*
-        * Send the message and set the timer   
-        */
-       m = (gbuf_t *)copy_pkt(m2, sizeof(llc_header_t));
-       if ( !trp->tr_retry && !trp->tr_bitmap && !trp->tr_xo)
-               atp_x_done(trp); /* no reason to tie up resources */
-       else
-               atp_timout(atp_req_timeout, trp, trp->tr_timeout);
-       if (m)
-               DDP_OUTPUT(m);
-
-       if (nowait) {
-               file_drop(fd);
-               return (int)tid;
-       }
-
-       /*
-        * wait for the transaction to complete
-        */
-       while ((trp->tr_state != TRANS_DONE) && (trp->tr_state != TRANS_FAILED) &&
-                               (trp->tr_state != TRANS_ABORTING)) {
-               trp->tr_rsp_wait = 1;
-               rc = msleep(&trp->tr_event, atalk_mutex, PSOCK | PCATCH, "atpsndreq", 0);
-               if (rc != 0) {
-                       trp->tr_rsp_wait = 0;
-                       file_drop(fd);
-                       *err = rc;
-                       return -1;
-               }
-       }
-       trp->tr_rsp_wait = 0;
-
-
-       if (trp->tr_state == TRANS_FAILED || trp->tr_state == TRANS_ABORTING) {
-               /*
-                * transaction timed out, return error
-                */
-               atp_free(trp);
-               file_drop(fd);
-               *err = ETIMEDOUT;
-               return -1;
-       }
-
-       /*
-        * copy out the recv data
-        */
-       if ((*err = atp_pack_bdsp(trp, (struct atpBDS *)bds)) != 0) {
-               atp_free(trp);
-               file_drop(fd);
-               return -1;
-       }
-
-       /*
-        * copyout the result info
-        */
-       if ((*err = copyout((caddr_t)bds, CAST_USER_ADDR_T(buf), atpBDSsize)) != 0) {
-               atp_free(trp);
-               file_drop(fd);
-               return -1;
-       }
-
-       atp_free(trp);
-       file_drop(fd);
-
-       return (int)tid;
-} /* _ATPsndreq */
-
-
-/*     entry point for ATP send response.  respbuf contains a DDP hdr,
- *     ATP hdr, and atpBDS array.  The bdsDataSz field of the first atpBDS
- *     struct contains the number of atpBDS structs in the array. resplen
- *     contains the len of the data in respbuf and datalen contains the
- *     len of the data buffer holding the response packets which the atpBDS
- *     struct entries point to.
- */
-int
-_ATPsndrsp(fd, respbuff, resplen, datalen, err, proc)
-       int fd;
-       unsigned char *respbuff;
-       int resplen;
-       int datalen;
-       int *err;
-       void *proc;
-{
-       gref_t          *gref;
-       long            bufaddr;
-       gbuf_t          *m, *mdata;
-       short           space;
-       int             size;
-       struct atp_state *atp;
-       struct atpBDS *bdsp;
-       int                     bds_cnt, count, len;
-       caddr_t         dataptr;
-
-       if ((*err = atalk_getref(0, fd, &gref, proc, 1)) != 0)
-               return -1;
-
-       if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
-                       || (atp->atp_flags & ATP_CLOSING)) {
-               dPrintf(D_M_ATP, D_L_ERROR, ("ATPsndrsp: stale handle=0x%x, pid=%d\n",
-                       (u_int) gref, gref->pid));
-
-               file_drop(fd);
-               *err = EINVAL;
-               return -1;
-       }
-
-       /*
-        * allocate buffer and copy in the response info
-        */
-       if (resplen < 0 || resplen > TOTAL_ATP_HDR_SIZE + sizeof(struct atpBDS)*ATP_TRESP_MAX) {
-               file_drop(fd);
-               *err = EINVAL;
-               return -1;
-       }
-       if ((m = gbuf_alloc_wait(resplen, TRUE)) == 0) {
-               *err = ENOMEM;
-               file_drop(fd);
-               return -1;
-       }
-       if ((*err = copyin(CAST_USER_ADDR_T(respbuff), (caddr_t)gbuf_rptr(m), resplen)) != 0) {
-               gbuf_freeb(m);
-               file_drop(fd);
-               return -1;
-       }
-       gbuf_wset(m,resplen);
-       ((at_ddp_t *)gbuf_rptr(m))->src_node = 0;
-       bdsp = (struct atpBDS *)(gbuf_rptr(m) + TOTAL_ATP_HDR_SIZE);
-
-       /*
-        * allocate buffers and copy in the response data.
-        * note that only the size field of the atpBDS field
-        * is used internally in the kernel.
-        */
-       bds_cnt = get_bds_entries(m);           /* count of # entries */
-       /* check correctness of parameters */
-       if (bds_cnt > ATP_TRESP_MAX) {
-           gbuf_freem(m);
-               *err = EINVAL;
-               file_drop(fd);
-               return -1;
-       }
-       
-       for (size = 0, count = 0; count < bds_cnt; count++) {
-               if (UAS_VALUE(bdsp[count].bdsBuffSz) > ATP_DATA_SIZE) {
-                       gbuf_freem(m);
-                       *err = EINVAL;
-                       file_drop(fd);
-                       return -1;
-               }
-               size += UAS_VALUE(bdsp[count].bdsBuffSz);
-       }
-       if (size > datalen) {                           
-           gbuf_freem(m);
-               *err = EINVAL;
-               file_drop(fd);
-               return -1;
-       }
-       
-       /* get the first mbuf */
-       if ((mdata = gbuf_alloc_wait((space = (size > MCLBYTES ? MCLBYTES : size)), TRUE)) == 0) {
-           gbuf_freem(m);
-               file_drop(fd);
-               *err = ENOMEM;
-               return -1;
-       }
-       gbuf_cont(m) = mdata;
-       dataptr = mtod(mdata, caddr_t);
-       for (count = 0; count < bds_cnt; bdsp++, count++) {
-               if ((bufaddr = UAL_VALUE(bdsp->bdsBuffAddr)) != 0 && 
-                               (len = UAS_VALUE(bdsp->bdsBuffSz)) != 0) {
-                       if (len > space) {                                                                                      /* enough room ? */
-                               gbuf_wset(mdata, dataptr - mtod(mdata, caddr_t));               /* set len of last mbuf */
-                               /* allocate the next mbuf */
-                               if ((gbuf_cont(mdata) = m_get((M_WAIT), MSG_DATA)) == 0) {
-                                       gbuf_freem(m);
-                                       file_drop(fd);
-                                       *err = ENOMEM;
-                                       return -1;
-                               }
-                               mdata = gbuf_cont(mdata);       
-                               MCLGET(mdata, M_WAIT);
-                               if (!(mdata->m_flags & M_EXT)) {
-                                       m_freem(m);
-                                       file_drop(fd);
-                                       return(0);
-                               }
-                               dataptr = mtod(mdata, caddr_t);
-                               space = MCLBYTES;
-                       }
-                       /* do the copyin */
-                       if ((*err = copyin(CAST_USER_ADDR_T(bufaddr), dataptr, len)) != 0) {
-                               gbuf_freem(m);
-                               file_drop(fd);
-                               return -1;
-                       }
-                       dataptr += len;
-                       space -= len;
-               }
-       }
-       gbuf_wset(mdata, dataptr - mtod(mdata, caddr_t));               /* set len of last mbuf */
-       gbuf_cont(m)->m_pkthdr.len = size;                                              /* set packet hdr len */
-
-       atp_send_rsp(gref, m, TRUE);
-       file_drop(fd);
-       return 0;
-}
-
-int
-_ATPgetreq(fd, buf, buflen, err, proc)
-       int fd;
-       unsigned char *buf;
-       int buflen;
-       int *err;
-       void *proc;
-{
-       gref_t *gref;
-       register struct atp_state *atp;
-       register struct atp_rcb *rcbp;
-       register gbuf_t *m, *m_head;
-       int size, len;
-
-       if ((*err = atalk_getref(0, fd, &gref, proc, 1)) != 0)
-               return -1;
-
-       if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
-                       || (atp->atp_flags & ATP_CLOSING)) {
-               dPrintf(D_M_ATP, D_L_ERROR, ("ATPgetreq: stale handle=0x%x, pid=%d\n",
-                       (u_int) gref, gref->pid));
-               file_drop(fd);
-               *err = EINVAL;
-               return -1;
-       }
-
-       if (buflen < DDP_X_HDR_SIZE + ATP_HDR_SIZE) {
-               file_drop(fd);
-               *err = EINVAL;
-               return -1;
-       }
-
-       if ((rcbp = atp->atp_attached.head) != NULL) {
-           /*
-            * Got one, move it to the active response Q
-            */
-               m_head = rcbp->rc_ioctl;
-               rcbp->rc_ioctl = NULL;
-
-               if (rcbp->rc_xo) {
-                       ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list);
-                       rcbp->rc_state = RCB_NOTIFIED;
-                       ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
-               } else {
-                       /* detach rcbp from attached queue,
-                        * and free any outstanding resources
-                        */
-                       atp_rcb_free(rcbp);
-               }
-
-               /*
-                * copyout the request data, including the protocol header
-                */
-               for (size=0, m=m_head; m; m = gbuf_cont(m)) {
-                       if ((len = gbuf_len(m)) > buflen)
-                               len = buflen;
-                       copyout((caddr_t)gbuf_rptr(m), CAST_USER_ADDR_T(&buf[size]), len);
-                       size += len;
-                       if ((buflen -= len) == 0)
-                               break;
-               }
-               gbuf_freem(m_head);
-
-               file_drop(fd);
-               return size;
-       }
-
-       file_drop(fd);
-       return -1;
-}
-
-int
-_ATPgetrsp(fd, bdsp, err, proc)
-       int fd;
-       struct atpBDS *bdsp;
-       int *err;
-       void *proc;
-{
-       gref_t *gref;
-       register struct atp_state *atp;
-       register struct atp_trans *trp;
-       int tid;
-       char bds[atpBDSsize];
-
-       if ((*err = atalk_getref(0, fd, &gref, proc, 1)) != 0)
-               return -1;
-
-       if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
-                       || (atp->atp_flags & ATP_CLOSING)) {
-               dPrintf(D_M_ATP, D_L_ERROR, ("ATPgetrsp: stale handle=0x%x, pid=%d\n",
-                       (u_int) gref, gref->pid));
-               file_drop(fd);
-               *err = EINVAL;
-               return -1;
-       }
-
-       for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
-               dPrintf(D_M_ATP, D_L_INFO,
-                       ("ATPgetrsp: atp:0x%x, trp:0x%x, state:%d\n",
-                       (u_int) atp, (u_int) trp, trp->tr_state));
-
-               switch (trp->tr_state) {
-               case TRANS_DONE:
-                       if ((*err = copyin(CAST_USER_ADDR_T(bdsp),
-                                       (caddr_t)bds, sizeof(bds))) != 0) {
-                               atp_free(trp);
-                               file_drop(fd);
-                               return -1;
-                       }
-                       if ((*err = atp_pack_bdsp(trp, (struct atpBDS *)bds)) != 0) {
-                               atp_free(trp);
-                               file_drop(fd);
-                               return -1;
-                       }
-                       tid = (int)trp->tr_tid;
-                       atp_free(trp);
-                       if ((*err = copyout((caddr_t)bds, CAST_USER_ADDR_T(bdsp), sizeof(bds))) != 0) {
-                               file_drop(fd);
-                               return -1;
-                       }
-                       file_drop(fd);
-                       return tid;
-
-               case TRANS_FAILED:
-                       /*
-                        * transaction timed out, return error
-                        */
-                       atp_free(trp);
-                       file_drop(fd);
-                       *err = ETIMEDOUT;
-                       return -1;
-
-               default:
-                       continue;
-           }
-       }
-
-       file_drop(fd);
-       *err = EINVAL;
-       return -1;
-}
-
-void
-atp_drop_req(gref, m)
-       gref_t *gref;
-       gbuf_t *m;
-{
-       struct atp_state *atp;
-       struct atp_rcb *rcbp;
-       at_atp_t *athp;
-       at_ddp_t *ddp;
-
-       atp = (struct atp_state *)gref->info;
-       if (atp->dflag)
-               atp = (struct atp_state *)atp->atp_msgq;
-       ddp = AT_DDP_HDR(m);
-       athp = AT_ATP_HDR(m);
-
-       /*
-        *      search for the corresponding rcb
-        */
-       for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) {
-           if ( (rcbp->rc_tid == UAS_VALUE_NTOH(athp->tid)) &&
-                       (rcbp->rc_socket.node == ddp->src_node) &&
-                       (rcbp->rc_socket.net == NET_VALUE(ddp->src_net)) &&
-                       (rcbp->rc_socket.socket == ddp->src_socket) )
-               break;
-       }
-
-       /*
-        *      drop the request
-        */
-       if (rcbp)
-               atp_rcb_free(rcbp);
-
-       gbuf_freem(m);
-}