The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/bsd/netat/atp_write.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*
    2  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
    3  *
    4  * @APPLE_LICENSE_HEADER_START@
    5  * 
    6  * The contents of this file constitute Original Code as defined in and
    7  * are subject to the Apple Public Source License Version 1.1 (the
    8  * "License").  You may not use this file except in compliance with the
    9  * License.  Please obtain a copy of the License at
   10  * http://www.apple.com/publicsource and read it before using this file.
   11  * 
   12  * This Original Code and all software distributed under the License are
   13  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
   14  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
   15  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
   16  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
   17  * License for the specific language governing rights and limitations
   18  * under the License.
   19  * 
   20  * @APPLE_LICENSE_HEADER_END@
   21  */
   22 /*
   23  *      Copyright (c) 1996-1998 Apple Computer, Inc.
   24  *      All Rights Reserved.
   25  */
   26 
   27 /*    Modified for MP, 1996 by Tuyen Nguyen
   28  *   Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
   29  */
   30 #define RESOLVE_DBG
   31 
   32 #include <sys/errno.h>
   33 #include <sys/types.h>
   34 #include <sys/param.h>
   35 #include <machine/spl.h>
   36 #include <sys/systm.h>
   37 #include <sys/kernel.h>
   38 #include <sys/proc.h>
   39 #include <sys/filedesc.h>
   40 #include <sys/fcntl.h>
   41 #include <kern/locks.h>
   42 #include <sys/mbuf.h>
   43 #include <sys/ioctl.h>
   44 #include <sys/malloc.h>
   45 #include <sys/socket.h>
   46 #include <sys/socketvar.h>
   47 
   48 #include <net/if.h>
   49 
   50 #include <netat/sysglue.h>
   51 #include <netat/appletalk.h>
   52 #include <netat/ddp.h>
   53 #include <netat/at_pcb.h>
   54 #include <netat/atp.h>
   55 #include <netat/at_var.h>
   56 #include <netat/asp.h>
   57 #include <netat/at_pat.h>
   58 #include <netat/debug.h>
   59 
   60 static int loop_cnt; /* for debugging loops */
   61 #define CHK_LOOP(str) { \
   62   if (loop_cnt++ > 100) { \
   63      kprintf("%s", str); \
   64      break; \
   65   } \
   66 }
   67 
   68 static int atp_pack_bdsp(struct atp_trans *, struct atpBDS *);
   69 static int atp_unpack_bdsp(struct atp_state *, gbuf_t *, struct atp_rcb *, 
   70                            int, int);
   71 void atp_trp_clock(), asp_clock(), asp_clock_locked(), atp_trp_clock_locked();;
   72 
   73 extern struct atp_rcb_qhead atp_need_rel;
   74 extern int atp_inited;
   75 extern struct atp_state *atp_used_list;
   76 extern asp_scb_t *scb_free_list;
   77 extern atlock_t atpgen_lock;
   78 extern atlock_t atpall_lock;
   79 extern atlock_t atptmo_lock;
   80 
   81 extern gbuf_t *scb_resource_m;
   82 extern gbuf_t *atp_resource_m;
   83 extern gref_t *atp_inputQ[];
   84 extern int atp_pidM[];
   85 extern at_ifaddr_t *ifID_home;
   86 extern lck_mtx_t * atalk_mutex;
   87 
   88 static struct atp_trans *trp_tmo_list;
   89 struct atp_trans *trp_tmo_rcb;
   90 
   91 /* first bds entry gives number of bds entries in total (hack) */
   92 #define get_bds_entries(m) \
   93         ((gbuf_len(m) > TOTAL_ATP_HDR_SIZE)? \
   94          (UAS_VALUE(((struct atpBDS *)(AT_ATP_HDR(m)->data))->bdsDataSz)): 0)
   95 
   96 #define atpBDSsize (sizeof(struct atpBDS)*ATP_TRESP_MAX)
   97 
   98 void atp_link()
   99 {
  100         trp_tmo_list = 0;
  101         trp_tmo_rcb = atp_trans_alloc(0);
  102         atp_timout(atp_rcb_timer, trp_tmo_rcb, 10 * HZ);
  103         atp_trp_clock((void *)&atp_inited);
  104         asp_clock((void *)&atp_inited);
  105 }
  106 
  107 void atp_unlink()
  108 {
  109         untimeout(asp_clock_locked, (void *)&atp_inited);
  110         untimeout(atp_trp_clock_locked, (void *)&atp_inited);
  111         atp_untimout(atp_rcb_timer, trp_tmo_rcb); 
  112         trp_tmo_list = 0;
  113 
  114 #ifdef BAD_IDEA
  115         /* allocated in asp_scb_alloc(), which is called 
  116            by asp_open() */
  117         if (scb_resource_m) { 
  118                 gbuf_freem(scb_resource_m);
  119                 scb_resource_m = 0;
  120                 scb_free_list = 0;
  121         }
  122         /* allocated in atp_trans_alloc() */
  123         if (atp_resource_m) {
  124                 gbuf_freem(atp_resource_m);
  125                 atp_resource_m = 0;
  126                 atp_trans_free_list = 0;
  127         }
  128 #endif
  129 }
  130 
  131 /*
  132  *      write queue put routine .... filter out other than IOCTLs
  133  *      Version 1.8 of atp_write.c on 89/02/09 17:53:26
  134  */
  135 
  136 void
  137 atp_wput(gref, m)
  138         register gref_t *gref;
  139         register gbuf_t *m;
  140 {
  141         register ioc_t    *iocbp;
  142         int i, xcnt, s;
  143         struct atp_state *atp;
  144         struct atp_trans *trp;
  145         struct atp_rcb   *rcbp;
  146         at_socket skt;
  147 
  148         atp = (struct atp_state *)gref->info;
  149         if (atp->dflag)
  150                 atp = (struct atp_state *)atp->atp_msgq;
  151 
  152         switch(gbuf_type(m)) {
  153         case MSG_DATA:
  154                 if (atp->atp_msgq) {
  155                         gbuf_freem(m);
  156                         dPrintf(D_M_ATP, D_L_WARNING,
  157                                 ("atp_wput: atp_msgq discarded\n"));
  158                 } else
  159                         atp->atp_msgq = m;
  160                 break;
  161 
  162         case MSG_IOCTL:
  163                 /* Need to ensure that all copyin/copyout calls are made at 
  164                  * put routine time which should be in the user context. (true when
  165                  * we are the stream head). The service routine can be called on an
  166                  * unpredictable context and copyin/copyout calls will get wrong results
  167                  * or even panic the kernel. 
  168                  */
  169                 iocbp = (ioc_t *)gbuf_rptr(m);
  170 
  171                 switch (iocbp->ioc_cmd) {
  172                 case AT_ATP_BIND_REQ:
  173                         if (gbuf_cont(m) == NULL) {
  174                                 iocbp->ioc_rval = -1;
  175                                 atp_iocnak(atp, m, EINVAL);
  176                                 return;
  177                         }
  178                         skt = *(at_socket *)gbuf_rptr(gbuf_cont(m));
  179                         if ((skt = (at_socket)atp_bind(gref, (unsigned int)skt, 0)) == 0)
  180                                 atp_iocnak(atp, m, EINVAL);
  181                         else {
  182                                 *(at_socket *)gbuf_rptr(gbuf_cont(m)) = skt;
  183                                 iocbp->ioc_rval = 0;
  184                                 atp_iocack(atp, m);
  185                                 atp_dequeue_atp(atp);
  186                         }
  187                         return;
  188 
  189                 case AT_ATP_GET_CHANID:
  190                         if (gbuf_cont(m) == NULL) {
  191                                 iocbp->ioc_rval = -1;
  192                                 atp_iocnak(atp, m, EINVAL);
  193                                 return;
  194                         }
  195                         *(gref_t **)gbuf_rptr(gbuf_cont(m)) = gref;
  196                         atp_iocack(atp, m);
  197                         return;
  198 
  199                 /* not the close and not the tickle(?) */
  200                 case AT_ATP_ISSUE_REQUEST_DEF:
  201                 case AT_ATP_ISSUE_REQUEST_DEF_NOTE: {
  202                         gbuf_t *bds, *tmp, *m2;
  203                         struct atp_rcb *rcbp;
  204                         at_ddp_t *ddp;
  205                         at_atp_t *athp;
  206 
  207                         if ((tmp = gbuf_cont(m)) != 0) {
  208                                 if ((bds = gbuf_dupb(tmp)) == NULL) {
  209                                         atp_iocnak(atp, m, ENOBUFS);
  210                                         return;
  211                                 }
  212                                 gbuf_rinc(tmp,atpBDSsize);
  213                                 gbuf_wset(bds,atpBDSsize);
  214                                 iocbp->ioc_count -= atpBDSsize;
  215                                 gbuf_cont(tmp) = bds;
  216                         }
  217 
  218                         /*
  219                          *      send a response to a transaction
  220                          *              first check it out
  221                          */
  222                         if (iocbp->ioc_count < TOTAL_ATP_HDR_SIZE) {
  223                             atp_iocnak(atp, m, EINVAL);
  224                             break;
  225                         }
  226 
  227                         /*
  228                          *      remove the response from the message
  229                          */
  230                         m2 = gbuf_cont(m);
  231                         gbuf_cont(m) = NULL;
  232                         iocbp->ioc_count = 0;
  233                         ddp = AT_DDP_HDR(m2);
  234                         athp = AT_ATP_HDR(m2);
  235                         if (atp->atp_msgq) {
  236                                 gbuf_cont(m2) = atp->atp_msgq;
  237                                 atp->atp_msgq = 0;
  238                         }
  239 
  240                         ATDISABLE(s, atp->atp_lock);
  241                         /*
  242                          *      search for the corresponding rcb
  243                          */
  244                         for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) {
  245                             if (rcbp->rc_tid == UAS_VALUE(athp->tid) &&
  246                                 rcbp->rc_socket.node == ddp->dst_node &&
  247                                 rcbp->rc_socket.net == NET_VALUE(ddp->dst_net) &&
  248                                 rcbp->rc_socket.socket == ddp->dst_socket)
  249                                 break;
  250                         }
  251                         ATENABLE(s, atp->atp_lock);
  252 
  253                         /*
  254                          *      If it has already been sent then return an error
  255                          */
  256                         if ((rcbp && rcbp->rc_state != RCB_NOTIFIED) || 
  257                             (rcbp == NULL && athp->xo)) {
  258                             atp_iocnak(atp, m, ENOENT);
  259                             gbuf_freem(m2);
  260                             return;
  261                         }
  262                         if (rcbp == NULL) { /* a response for an ALO transaction */
  263                             if ((rcbp = atp_rcb_alloc(atp)) == NULL) {
  264                                 atp_iocnak(atp, m, ENOBUFS);
  265                                 gbuf_freem(m2);
  266                                 return;
  267                             }
  268                             rcbp->rc_ioctl = 0;
  269                             rcbp->rc_socket.socket = ddp->dst_socket;
  270                             rcbp->rc_socket.node = ddp->dst_node;
  271                             rcbp->rc_socket.net = NET_VALUE(ddp->dst_net);
  272                             rcbp->rc_tid = UAS_VALUE(athp->tid);
  273                             rcbp->rc_bitmap = 0xff;
  274                             rcbp->rc_xo = 0;
  275                             ATDISABLE(s, atp->atp_lock);
  276                             rcbp->rc_state = RCB_SENDING;
  277                             ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
  278                             ATENABLE(s, atp->atp_lock);
  279                         }
  280                         xcnt = get_bds_entries(m2);
  281                         if ((i = atp_unpack_bdsp(atp, m2, rcbp, xcnt, FALSE))) {
  282                             if ( !rcbp->rc_xo)
  283                                 atp_rcb_free(rcbp);
  284                             atp_iocnak(atp, m, i);
  285                             return;
  286                         }
  287                         atp_send_replies(atp, rcbp);
  288 
  289                         /*
  290                          *      send the ack back to the responder
  291                          */
  292                         atp_iocack(atp, m);
  293                         return;
  294                 }
  295 
  296                 case AT_ATP_GET_POLL: {
  297                         if (gbuf_cont(m)) {
  298                             gbuf_freem(gbuf_cont(m));
  299                             gbuf_cont(m) = NULL;
  300                             iocbp->ioc_count = 0;
  301                         }
  302 
  303                         /*
  304                          *      search for a waiting request
  305                          */
  306                         ATDISABLE(s, atp->atp_lock);
  307                         if ((rcbp = atp->atp_attached.head)) {
  308                             /*
  309                              *  Got one, move it to the active response Q
  310                              */
  311                             gbuf_cont(m) = rcbp->rc_ioctl;
  312                             rcbp->rc_ioctl = NULL;
  313                             if (rcbp->rc_xo) {
  314                                 ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list);
  315                                 rcbp->rc_state = RCB_NOTIFIED;
  316                                 ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
  317                             } else {
  318                                 /* detach rcbp from attached queue,
  319                                  * and free any outstanding resources
  320                                  */
  321                                 atp_rcb_free(rcbp);
  322                             }
  323                             ATENABLE(s, atp->atp_lock);
  324                             atp_iocack(atp, m);
  325                         } else {
  326                                 /*
  327                                  *      None available - can out
  328                                  */
  329                                 ATENABLE(s, atp->atp_lock);
  330                                 atp_iocnak(atp, m, EAGAIN);
  331                         }
  332                         break;
  333                 }
  334 
  335                 case AT_ATP_CANCEL_REQUEST: {
  336                         /*
  337                          *      Cancel a pending request
  338                          */
  339                         if (iocbp->ioc_count != sizeof(int)) {
  340                             atp_iocnak(atp, m, EINVAL);
  341                             break;
  342                         }
  343                         i = *(int *)gbuf_rptr(gbuf_cont(m));
  344                         gbuf_freem(gbuf_cont(m));
  345                         gbuf_cont(m) = NULL;
  346                         ATDISABLE(s, atp->atp_lock);
  347                         for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
  348                           if (trp->tr_tid == i)
  349                                 break;
  350                         }
  351                         if (trp == NULL) {
  352                                 ATENABLE(s, atp->atp_lock);
  353                                 atp_iocnak(atp, m, ENOENT);
  354                         } else {
  355                                 ATENABLE(s, atp->atp_lock);
  356                                 atp_free(trp);
  357                                 atp_iocack(atp, m);
  358                         }
  359                         break;
  360                 }
  361 
  362                 case AT_ATP_PEEK: {
  363                         unsigned char event;
  364                         if (atalk_peek(gref, &event) == -1)
  365                             atp_iocnak(atp, m, EAGAIN);
  366                         else {
  367                                 *gbuf_rptr(gbuf_cont(m)) = event;
  368                                 atp_iocack(atp, m);
  369                         }
  370                         break;
  371                 }
  372 
  373                 case DDP_IOC_GET_CFG:
  374 #ifdef APPLETALK_DEBUG
  375                         kprintf("atp_wput: DDP_IOC_GET_CFG\n");
  376 #endif
  377                         if (gbuf_cont(m) == 0) {
  378                                 atp_iocnak(atp, m, EINVAL);
  379                                 break;
  380                         }
  381                         {
  382                         /* *** was ddp_get_cfg() *** */
  383                           ddp_addr_t *cfgp = 
  384                             (ddp_addr_t *)gbuf_rptr(gbuf_cont(m));
  385                           cfgp->inet.net = ifID_home->ifThisNode.s_net;
  386                           cfgp->inet.node = ifID_home->ifThisNode.s_node;
  387                           cfgp->inet.socket = atp->atp_socket_no;
  388                           cfgp->ddptype = DDP_ATP;
  389 #ifdef NOT_YET
  390                           cfgp->inet.net = atp->atp_gref->laddr.s_net;
  391                           cfgp->inet.node = atp->atp_gref->laddr.s_node;
  392                           cfgp->inet.socket = atp->atp_gref->lport;
  393                           cfgp->ddptype = atp->atp_gref->ddptype;
  394 #endif
  395                         }
  396                         gbuf_wset(gbuf_cont(m), sizeof(ddp_addr_t));
  397                         atp_iocack(atp, m);
  398                         break;
  399                                         
  400                 default:
  401                         /*
  402                          *      Otherwise pass it on, if possible
  403                          */
  404                         iocbp->ioc_private = (void *)gref;
  405                         DDP_OUTPUT(m);
  406                         break;
  407           }
  408                 break;
  409 
  410         default:
  411                 gbuf_freem(m);
  412                 break;
  413         }
  414 } /* atp_wput */
  415 
  416 gbuf_t  *atp_build_release(trp)
  417 register struct atp_trans *trp;
  418 {
  419         register gbuf_t   *m;
  420         register at_ddp_t *ddp;
  421         register at_atp_t   *athp;
  422 
  423         /*
  424          *      Now try and allocate enough space to send the message
  425          *              if none is available the caller will schedule
  426          *              a timeout so we can retry for more space soon
  427          */
  428         if ((m = (gbuf_t *)gbuf_alloc(AT_WR_OFFSET+ATP_HDR_SIZE, PRI_HI)) != NULL) {
  429                 gbuf_rinc(m,AT_WR_OFFSET);
  430                 gbuf_wset(m,TOTAL_ATP_HDR_SIZE);
  431                 ddp = AT_DDP_HDR(m);
  432                 ddp->type = DDP_ATP;
  433                 UAS_ASSIGN(ddp->checksum, 0);
  434                 ddp->dst_socket = trp->tr_socket.socket;
  435                 ddp->dst_node = trp->tr_socket.node;
  436                 NET_ASSIGN(ddp->dst_net, trp->tr_socket.net);
  437                 ddp->src_node = trp->tr_local_node;
  438                 NET_NET(ddp->src_net, trp->tr_local_net);
  439 
  440                 /*
  441                  * clear the cmd/xo/eom/sts/unused fields
  442                  */
  443                 athp = AT_ATP_HDR(m);
  444                 ATP_CLEAR_CONTROL(athp);
  445                 athp->cmd = ATP_CMD_TREL;
  446                 UAS_ASSIGN(athp->tid, trp->tr_tid);
  447         }
  448 
  449         return (m);
  450 }
  451 
  452 void atp_send_replies(atp, rcbp)
  453      register struct atp_state *atp;
  454      register struct atp_rcb   *rcbp;
  455 {       register gbuf_t *m;
  456         register int     i, len;
  457         int              s_gen, s, cnt, err, offset, space;
  458         unsigned char *m0_rptr = NULL, *m0_wptr = NULL;
  459         register at_atp_t *athp;
  460         register struct atpBDS *bdsp;
  461         register gbuf_t *m2, *m1, *m0, *mhdr;
  462         caddr_t lastPage;
  463         gbuf_t *mprev, *mlist = 0;
  464         at_socket src_socket = (at_socket)atp->atp_socket_no;
  465         gbuf_t *rc_xmt[ATP_TRESP_MAX];
  466         struct   ddp_atp {
  467                  char    ddp_atp_hdr[TOTAL_ATP_HDR_SIZE];
  468         };
  469         struct timeval timenow;
  470 
  471         ATDISABLE(s, atp->atp_lock);
  472         if (rcbp->rc_queue != atp) {
  473                 ATENABLE(s, atp->atp_lock);
  474                 return;
  475         }
  476         if (rcbp->rc_not_sent_bitmap == 0)
  477                 goto nothing_to_send;
  478 
  479         dPrintf(D_M_ATP_LOW, D_L_OUTPUT, ("atp_send_replies\n"));
  480         /*
  481          *      Do this for each message that hasn't been sent
  482          */
  483         cnt = rcbp->rc_pktcnt;
  484         for (i = 0; i < cnt; i++) {
  485           rc_xmt[i] = 0;
  486           if (rcbp->rc_snd[i]) {
  487                 if ((rc_xmt[i] = 
  488                      gbuf_alloc(AT_WR_OFFSET+TOTAL_ATP_HDR_SIZE,PRI_MED)) 
  489                     == NULL) {
  490                         for (cnt = 0; cnt < i; cnt++)
  491                                 if (rc_xmt[cnt])
  492                                         gbuf_freeb(rc_xmt[cnt]);
  493                         goto nothing_to_send;
  494                 }
  495           }
  496         }
  497 
  498         m = rcbp->rc_xmt;
  499         m0 = gbuf_cont(m);
  500         if (gbuf_len(m) > TOTAL_ATP_HDR_SIZE)
  501                 bdsp = (struct atpBDS *)(AT_ATP_HDR(m)->data);
  502         else
  503                 bdsp = 0;
  504         offset = 0;
  505         if (m0)
  506                 space = gbuf_msgsize(m0);
  507         else
  508           space = 0;
  509         for (i = 0; i < cnt; i++) {
  510                 if (rcbp->rc_snd[i] == 0) {
  511                         if ((len = UAS_VALUE(bdsp->bdsBuffSz))) {
  512                                 offset += len;
  513                                 space -= len;
  514                         }
  515                 } else {
  516                         mhdr = rc_xmt[i];
  517                         /* setup header fields */
  518                         gbuf_rinc(mhdr,AT_WR_OFFSET);
  519                         gbuf_wset(mhdr,TOTAL_ATP_HDR_SIZE);
  520                         *(struct ddp_atp *)(gbuf_rptr(mhdr))= *(struct ddp_atp *)(gbuf_rptr(m));
  521                         athp = AT_ATP_HDR(mhdr);
  522                         ATP_CLEAR_CONTROL(athp);
  523                         athp->cmd = ATP_CMD_TRESP;
  524                         athp->bitmap = i;
  525                         if (i == (cnt - 1))
  526                                 athp->eom = 1; /* for the last fragment */
  527                         if (bdsp) {
  528                                 UAL_UAL(athp->user_bytes, bdsp->bdsUserData);
  529                                 if ((len = UAS_VALUE(bdsp->bdsBuffSz)) && m0 != 0 && space > 0) {
  530                                         if ((m1 = m_copym(m0, offset, len, M_DONTWAIT)) == 0) {
  531                                                 for (i = 0; i < cnt; i++)
  532                                                         if (rc_xmt[i])
  533                                                                 gbuf_freem(rc_xmt[i]);
  534                                                 goto nothing_to_send;
  535                                         }
  536                                         offset += len;
  537                                         space -= len;
  538                                         gbuf_cont(mhdr) = m1;
  539                                 }
  540                         }       
  541                                 
  542                         AT_DDP_HDR(mhdr)->src_socket = src_socket;
  543                         dPrintf(D_M_ATP_LOW, D_L_OUTPUT,
  544                                 ("atp_send_replies: %d, socket=%d, size=%d\n",
  545                                 i, atp->atp_socket_no, gbuf_msgsize(gbuf_cont(m2))));
  546         
  547                         if (mlist)
  548                                 gbuf_next(mprev) = mhdr;
  549                         else
  550                                 mlist = mhdr;
  551                         mprev = mhdr;
  552         
  553                         rcbp->rc_snd[i] = 0;
  554                         rcbp->rc_not_sent_bitmap &= ~atp_mask[i];
  555                         if (rcbp->rc_not_sent_bitmap == 0)
  556                                 break;
  557                 }
  558                 /*
  559                  * on to the next frag
  560                  */
  561                 bdsp++;
  562         }
  563         if (mlist) {
  564                 ATENABLE(s, atp->atp_lock);
  565                 DDP_OUTPUT(mlist);
  566                 ATDISABLE(s, atp->atp_lock);
  567         }
  568 
  569 nothing_to_send:
  570         /*
  571          *      If all replies from this reply block have been sent then 
  572          *              remove it from the queue and mark it so
  573          */
  574         if (rcbp->rc_queue != atp) {
  575                 ATENABLE(s, atp->atp_lock);
  576                 return;
  577         }
  578         rcbp->rc_rep_waiting = 0;
  579 
  580         /*
  581          *      If we are doing execute once re-set the rcb timeout 
  582          *      each time we send back any part of the response. Note
  583          *      that this timer is started when an initial request is
  584          *      received. Each response reprimes the timer.  Duplicate
  585          *      requests do not reprime the timer.
  586          *     
  587          *      We have sent all of a response so free the 
  588          *      resources.
  589          */
  590         if (rcbp->rc_xo && rcbp->rc_state != RCB_RELEASED) {
  591                 getmicrouptime(&timenow);
  592                 ATDISABLE(s_gen, atpgen_lock);
  593                 if (rcbp->rc_timestamp == 0) {
  594                         rcbp->rc_timestamp = timenow.tv_sec;
  595                         if (rcbp->rc_timestamp == 0)
  596                                 rcbp->rc_timestamp = 1;
  597                         ATP_Q_APPEND(atp_need_rel, rcbp, rc_tlist);
  598                 }
  599                 rcbp->rc_state = RCB_RESPONSE_FULL;
  600                 ATENABLE(s_gen, atpgen_lock);
  601         } else
  602                 atp_rcb_free(rcbp);
  603         ATENABLE(s, atp->atp_lock);
  604 } /* atp_send_replies */
  605 
  606 
  607 static int
  608 atp_pack_bdsp(trp, bdsp)
  609      register struct atp_trans *trp;
  610      register struct atpBDS *bdsp;
  611 {
  612         register gbuf_t *m = NULL;
  613         register int i, datsize = 0;
  614         struct atpBDS *bdsbase = bdsp;
  615         int error = 0;
  616 
  617         dPrintf(D_M_ATP, D_L_INFO, ("atp_pack_bdsp: socket=%d\n",
  618                 trp->tr_queue->atp_socket_no));
  619 
  620         for (i = 0; i < ATP_TRESP_MAX; i++, bdsp++) {
  621                 unsigned short bufsize = UAS_VALUE(bdsp->bdsBuffSz);
  622                 long bufaddr = UAL_VALUE(bdsp->bdsBuffAddr);
  623 
  624                 if ((m = trp->tr_rcv[i]) == NULL)
  625                         break;
  626 
  627                 /* discard ddp hdr on first packet */
  628                 if (i == 0)
  629                         gbuf_rinc(m,DDP_X_HDR_SIZE); 
  630 
  631                 /* this field may contain control information even when 
  632                    no data is present */
  633                 UAL_UAL(bdsp->bdsUserData, 
  634                         (((at_atp_t *)(gbuf_rptr(m)))->user_bytes));
  635                 gbuf_rinc(m, ATP_HDR_SIZE);
  636 
  637                 if ((bufsize != 0) && (bufaddr != 0)) {
  638                         /* user expects data back */
  639                         short tmp = 0;
  640                         register char *buf = (char *)bufaddr;
  641 
  642                         while (m) {
  643                                 unsigned short len = (unsigned short)(gbuf_len(m));
  644                                 if (len) {
  645                                         if (len > bufsize)
  646                                                 len = bufsize;
  647                                         if ((error = copyout((caddr_t)gbuf_rptr(m), 
  648                                                 CAST_USER_ADDR_T(&buf[tmp]),
  649                                                 len)) != 0) {
  650                                                 return error;
  651                                         }
  652                                         bufsize -= len;
  653                                         tmp += len;
  654                                 }
  655                                 m = gbuf_cont(m);
  656                         }
  657 
  658                         UAS_ASSIGN(bdsp->bdsDataSz, tmp);
  659                         datsize += (int)tmp;
  660                 }
  661                 gbuf_freem(trp->tr_rcv[i]);
  662                 trp->tr_rcv[i] = NULL;
  663         }
  664 
  665         /* report the number of packets */
  666         UAS_ASSIGN(((struct atpBDS *)bdsbase)->bdsBuffSz, i);
  667 
  668         dPrintf(D_M_ATP, D_L_INFO, ("             : size=%d\n",
  669                 datsize));
  670         
  671         return 0;
  672 } /* atp_pack_bdsp */
  673 
  674 
  675 /* create an mbuf chain with mbuf packet headers for each ATP response packet
  676  * to be sent.  m contains the DDP hdr, ATP hdr, and and array of atpBDS structs.  
  677  * chained to m is an mbuf that contians the actual data pointed to by the atpBDS
  678  * structs.
  679  */
  680 static int
  681 atp_unpack_bdsp(atp, m, rcbp, cnt, wait)
  682         struct atp_state *atp;
  683         gbuf_t          *m;     /* ddp, atp and bdsp gbuf_t */
  684         register struct atp_rcb *rcbp;
  685     register int    cnt, wait;
  686 {
  687         register struct atpBDS *bdsp;
  688         register         gbuf_t        *m2, *m1, *m0, *mhdr;
  689         caddr_t         lastPage;
  690     at_atp_t    *athp;
  691         int             i, len, s_gen;
  692         at_socket       src_socket;
  693         
  694         struct ddp_atp {
  695                  char    ddp_atp_hdr[TOTAL_ATP_HDR_SIZE];
  696         };
  697         gbuf_t                  *mprev, *mlist = 0;
  698         gbuf_t                  *rc_xmt[ATP_TRESP_MAX];
  699         unsigned char   *m0_rptr, *m0_wptr;
  700         int                             err, offset, space;
  701         struct timeval timenow;
  702 
  703         /*
  704          * get the user data structure pointer
  705          */
  706         bdsp = (struct atpBDS *)(AT_ATP_HDR(m)->data);
  707 
  708         /*
  709          * Guard against bogus count argument.
  710          */
  711         if ((unsigned) cnt > ATP_TRESP_MAX) {
  712                 dPrintf(D_M_ATP, D_L_ERROR,
  713                         ("atp_unpack_bdsp: bad bds count 0x%x\n", cnt));
  714                 gbuf_freem(m);
  715                 return(EINVAL);
  716         }
  717         if ((src_socket = (at_socket)atp->atp_socket_no) == 0xFF) {
  718           /* comparison was to -1, however src_socket is a u_char */
  719                 gbuf_freem(m);
  720                 return EPIPE;
  721         }
  722 
  723         m0 = gbuf_cont(m);
  724         rcbp->rc_xmt = m;
  725         rcbp->rc_pktcnt = cnt;
  726         rcbp->rc_state = RCB_SENDING;
  727         rcbp->rc_not_sent_bitmap = 0;
  728 
  729         if (cnt <= 1) {
  730                 /*
  731                  * special case this to
  732                  * improve AFP write transactions to the server
  733                  */
  734                 rcbp->rc_pktcnt = 1;
  735                 if ((m2 = gbuf_alloc_wait(AT_WR_OFFSET+TOTAL_ATP_HDR_SIZE, 
  736                                           wait)) == NULL)
  737                     return 0;
  738                 gbuf_rinc(m2,AT_WR_OFFSET);
  739                 gbuf_wset(m2,TOTAL_ATP_HDR_SIZE);
  740                 *(struct ddp_atp *)(gbuf_rptr(m2))= *(struct ddp_atp *)(gbuf_rptr(m));
  741                 athp = AT_ATP_HDR(m2);
  742                 ATP_CLEAR_CONTROL(athp);
  743                 athp->cmd = ATP_CMD_TRESP;
  744                 athp->bitmap = 0;
  745                 athp->eom = 1;     /* there's only 1 fragment */
  746 
  747                 /* *** why only if cnt > 0? *** */
  748                 if (cnt > 0)
  749                         UAL_UAL(athp->user_bytes, bdsp->bdsUserData);
  750                 if (m0)
  751                         if (!append_copy((struct mbuf *)m2, 
  752                                          (struct mbuf *)m0, wait)) {
  753                                 gbuf_freeb(m2);
  754                                 return 0;
  755                         }
  756                 /*
  757                  *      send the message and mark it as sent
  758                  */
  759                 AT_DDP_HDR(m2)->src_socket = src_socket;
  760                 dPrintf(D_M_ATP_LOW, D_L_INFO,
  761                         ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
  762                         0,atp->atp_socket_no,gbuf_msgsize(gbuf_cont(m2)),cnt));
  763                 mlist = m2;
  764                 goto l_send;
  765         }
  766 
  767         /* create an array of mbuf packet headers for the packets to be sent
  768          * to contain the atp and ddp headers with room at the front for the
  769          * datalink header.
  770          */
  771         for (i = 0; i < cnt; i++) {
  772                 /* all hdrs, packet data and dst addr storage */
  773                 if ((rc_xmt[i] = 
  774                      gbuf_alloc_wait(AT_WR_OFFSET+TOTAL_ATP_HDR_SIZE, wait)) == NULL) {
  775                                 for (cnt = 0; cnt < i; cnt++)
  776                                         if (rc_xmt[cnt])
  777                                                 gbuf_freeb(rc_xmt[cnt]);
  778                                 return 0;
  779                 }
  780         }
  781 
  782         /* run through the atpBDS structs and create an mbuf for the data
  783          * portion of each packet to be sent.  these get chained to the mbufs
  784          * containing the ATP and DDP headers.  this code assumes that no ATP
  785          * packet is contained in more than 2 mbufs (e.i crosses mbuf boundary
  786          * no more than one time).
  787          */
  788         offset = 0;
  789         if (m0)
  790                 space = gbuf_msgsize(m0);
  791         for (i = 0; i < cnt; i++) {                     /* for each hdr mbuf */
  792             mhdr = rc_xmt[i];
  793             /* setup header fields */
  794                 gbuf_rinc(mhdr,AT_WR_OFFSET);
  795                 gbuf_wset(mhdr,TOTAL_ATP_HDR_SIZE);
  796                 *(struct ddp_atp *)(gbuf_rptr(mhdr))= *(struct ddp_atp *)(gbuf_rptr(m));
  797                 athp = AT_ATP_HDR(mhdr);
  798                 ATP_CLEAR_CONTROL(athp);
  799                 athp->cmd = ATP_CMD_TRESP;
  800                 athp->bitmap = i;
  801                 if (i == (cnt - 1))
  802                         athp->eom = 1; /* for the last fragment */
  803                 UAL_UAL(athp->user_bytes, bdsp->bdsUserData);
  804                 
  805                 if ((len = UAS_VALUE(bdsp->bdsBuffSz)) != 0  && m0 != 0 && space > 0) {         
  806                         if ((m1 = m_copym(m0, offset, len, wait)) == 0) {
  807                                 for (i = 0; i < cnt; i++)
  808                                         if (rc_xmt[i])
  809                                                 gbuf_freem(rc_xmt[i]);
  810                                 return 0;
  811                         }
  812                         gbuf_cont(mhdr) = m1;
  813                         space -= len;
  814                         offset += len;
  815                 }
  816                                 
  817                 AT_DDP_HDR(mhdr)->src_socket = src_socket;
  818                 dPrintf(D_M_ATP_LOW,D_L_INFO,
  819                         ("atp_unpack_bdsp %d, socket=%d, size=%d, cnt=%d\n",
  820                         i,atp->atp_socket_no,gbuf_msgsize(gbuf_cont(mhdr)),cnt));
  821                 if (mlist)
  822                         gbuf_next(mprev) = mhdr;
  823                 else
  824                         mlist = mhdr;
  825                 mprev = mhdr;
  826                 /*
  827                  * on to the next frag
  828                  */
  829                 bdsp++;
  830         }
  831         /*
  832          * send the message
  833          */
  834 l_send:
  835         if (rcbp->rc_xo) {
  836                 getmicrouptime(&timenow);
  837                 ATDISABLE(s_gen, atpgen_lock);
  838                 if (rcbp->rc_timestamp == 0) {
  839                         if ((rcbp->rc_timestamp = timenow.tv_sec) == 0)
  840                                 rcbp->rc_timestamp = 1;
  841                         ATP_Q_APPEND(atp_need_rel, rcbp, rc_tlist);
  842                 }
  843                 ATENABLE(s_gen, atpgen_lock);
  844         }
  845 
  846         DDP_OUTPUT(mlist);
  847         return 0;
  848 
  849 } /* atp_unpack_bdsp */
  850 
  851 #define ATP_SOCKET_LAST  (DDP_SOCKET_LAST-6)
  852 #define ATP_SOCKET_FIRST (DDP_SOCKET_1st_DYNAMIC)
  853 static unsigned int sNext = 0;
  854 
  855 int atp_bind(gref, sVal, flag)
  856         gref_t *gref;
  857         unsigned int sVal;
  858         unsigned char *flag;
  859 {
  860         extern unsigned char asp_inpC[];
  861         extern asp_scb_t *asp_scbQ[];
  862         unsigned char inpC, sNextUsed = 0;
  863         unsigned int sMin, sMax, sSav;
  864         struct atp_state *atp;
  865         int s;
  866 
  867         atp = (struct atp_state *)gref->info;
  868         if (atp->dflag)
  869                 atp = (struct atp_state *)atp->atp_msgq;
  870 
  871         sMax = ATP_SOCKET_LAST;
  872         sMin = ATP_SOCKET_FIRST;
  873         ATDISABLE(s, atpgen_lock);
  874         if (flag && (*flag == 3)) {
  875                 sMin += 40;
  876                 if (sMin < sNext) {
  877                         sMin = sNext;
  878                         sNextUsed = 1;
  879                 }
  880         }
  881 
  882         if ( (sVal != 0) && 
  883              ((sVal > sMax) || (sVal < 2) || (sVal == 6) || 
  884               (ddp_socket_inuse(sVal, DDP_ATP) &&
  885                (atp_inputQ[sVal] != (gref_t *)1)))) {
  886                 ATENABLE(s, atpgen_lock);
  887                 return 0;
  888         }
  889 
  890         if (sVal == 0) {
  891                 inpC = 255;
  892 again:
  893                 for (sVal=sMin; sVal <= sMax; sVal++) {
  894                         if (!ddp_socket_inuse(sVal, DDP_ATP) ||
  895                             atp_inputQ[sVal] == (gref_t *)1)
  896                                 break;
  897                         else if (flag && (*flag == 3) && asp_scbQ[sVal]) {
  898                                 if ((asp_scbQ[sVal]->dflag == *flag)
  899                                     && (asp_inpC[sVal] < inpC) ) {
  900                                   inpC = asp_inpC[sVal];
  901                                   sSav = sVal;
  902                                 }
  903                         }
  904                 }
  905                 if (sVal > sMax) {
  906                         if (flag && (*flag == 3)) {
  907                                 if (sNextUsed) {
  908                                         sNextUsed = 0;
  909                                         sMax = sNext - 1;
  910                                         sMin = ATP_SOCKET_FIRST+40;
  911                                         goto again;
  912                                 }
  913                                 sNext = 0;
  914                                 *flag = (unsigned char)sSav;
  915                         }
  916                         ATENABLE(s, atpgen_lock);
  917                         return 0;
  918                 }
  919         }
  920         atp->atp_socket_no = (short)sVal;
  921         atp_inputQ[sVal] = gref;
  922         if (flag == 0)
  923                 atp_pidM[sVal] = atp->atp_pid;
  924         else if (*flag == 3) {
  925                 sNext = sVal + 1;
  926                 if (sNext > ATP_SOCKET_LAST)
  927                         sNext = 0;
  928         }
  929 
  930         ATENABLE(s, atpgen_lock);
  931         return (int)sVal;
  932 }
  933 
  934 void atp_req_ind(atp, mioc)
  935         register struct atp_state *atp;
  936         register gbuf_t *mioc;
  937 {
  938         register struct atp_rcb *rcbp;
  939         int s;
  940 
  941         if ((rcbp = atp->atp_attached.head) != 0) {
  942                 gbuf_cont(mioc) = rcbp->rc_ioctl;
  943                 rcbp->rc_ioctl = NULL;
  944                 ATDISABLE(s, atp->atp_lock);
  945                 if (rcbp->rc_xo) {
  946                         ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list);
  947                         rcbp->rc_state = RCB_NOTIFIED;
  948                         ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
  949                 } else
  950                         atp_rcb_free(rcbp);
  951                 ATENABLE(s, atp->atp_lock);
  952                 if (gbuf_cont(mioc))
  953                   ((ioc_t *)gbuf_rptr(mioc))->ioc_count = gbuf_msgsize(gbuf_cont(mioc));
  954                 else
  955                   ((ioc_t *)gbuf_rptr(mioc))->ioc_count = 0;
  956                 asp_ack_reply(atp->atp_gref, mioc);
  957         } else
  958                 gbuf_freeb(mioc);
  959 }
  960 
  961 void atp_rsp_ind(trp, mioc)
  962     register struct atp_trans *trp;
  963         register gbuf_t *mioc;
  964 {
  965         register struct atp_state *atp = trp->tr_queue;
  966         register int err;
  967         gbuf_t *xm = 0;
  968 
  969         err = 0;
  970         {
  971             switch (trp->tr_state) {
  972             case TRANS_DONE:
  973                         if (asp_pack_bdsp(trp, &xm) < 0)
  974                             err = EFAULT;
  975                         gbuf_cont(mioc) = trp->tr_xmt;
  976                         trp->tr_xmt = NULL;
  977                         break;
  978 
  979             case TRANS_FAILED:
  980                         err = ETIMEDOUT;
  981                         break;
  982 
  983             default:
  984                         err = ENOENT;
  985                         break;
  986             }
  987             atp_free(trp);
  988 
  989             if (err) {
  990                         dPrintf(D_M_ATP, D_L_ERROR,
  991                                 ("atp_rsp_ind: TRANSACTION error\n"));
  992                         atp_iocnak(atp, mioc, err);
  993             } else {
  994                         gbuf_cont(gbuf_cont(mioc)) = xm;
  995                 atp_iocack(atp, mioc);
  996             }
  997         }
  998 }
  999 
 1000 void atp_cancel_req(gref, tid)
 1001         gref_t *gref;
 1002         unsigned short tid;
 1003 {
 1004         int s;
 1005         struct atp_state *atp;
 1006         struct atp_trans *trp;
 1007 
 1008         atp = (struct atp_state *)gref->info;
 1009         if (atp->dflag)
 1010                 atp = (struct atp_state *)atp->atp_msgq;
 1011 
 1012         ATDISABLE(s, atp->atp_lock);
 1013         for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
 1014             if (trp->tr_tid == tid)
 1015                         break;
 1016         }
 1017         ATENABLE(s, atp->atp_lock);
 1018         if (trp != NULL)
 1019                 atp_free(trp);
 1020 }
 1021 
 1022 /*
 1023  * remove atp from the use list
 1024  */
 1025 void
 1026 atp_dequeue_atp(atp)
 1027         struct atp_state *atp;
 1028 {
 1029         int s;
 1030 
 1031         ATDISABLE(s, atpall_lock);
 1032         if (atp == atp_used_list) {
 1033                 if ((atp_used_list = atp->atp_trans_waiting) != 0)
 1034                         atp->atp_trans_waiting->atp_rcb_waiting = 0;
 1035         } else if (atp->atp_rcb_waiting) {
 1036                 if ((atp->atp_rcb_waiting->atp_trans_waiting
 1037                                 = atp->atp_trans_waiting) != 0)
 1038                         atp->atp_trans_waiting->atp_rcb_waiting = atp->atp_rcb_waiting;
 1039         }
 1040 
 1041         atp->atp_trans_waiting = 0;
 1042         atp->atp_rcb_waiting = 0;
 1043         ATENABLE(s, atpall_lock);
 1044 }
 1045 
 1046 void
 1047 atp_timout(func, trp, ticks)
 1048         void (*func)();
 1049         struct atp_trans *trp;
 1050         int ticks;
 1051 {
 1052         int s;
 1053         unsigned int sum;
 1054         struct atp_trans *curr_trp, *prev_trp;
 1055 
 1056         ATDISABLE(s, atptmo_lock);
 1057         if (trp->tr_tmo_func) {
 1058                 ATENABLE(s, atptmo_lock);
 1059                 return;
 1060         }
 1061 
 1062         trp->tr_tmo_func = func;
 1063         trp->tr_tmo_delta = 1+(ticks>>5);
 1064 
 1065         if (trp_tmo_list == 0) {
 1066                 trp->tr_tmo_next = trp->tr_tmo_prev = 0;
 1067                 trp_tmo_list = trp;
 1068                 ATENABLE(s, atptmo_lock);
 1069                 return;
 1070         }
 1071 
 1072         prev_trp = 0;
 1073         curr_trp = trp_tmo_list;
 1074         sum = 0;
 1075 
 1076         while (1) {
 1077                 sum += curr_trp->tr_tmo_delta;
 1078                 if (sum > trp->tr_tmo_delta) {
 1079                         sum -= curr_trp->tr_tmo_delta;
 1080                         trp->tr_tmo_delta -= sum;
 1081                         curr_trp->tr_tmo_delta -= trp->tr_tmo_delta;
 1082                         break;
 1083                 }
 1084                 prev_trp = curr_trp;
 1085                 if ((curr_trp = curr_trp->tr_tmo_next) == 0) {
 1086                         trp->tr_tmo_delta -= sum;
 1087                         break;
 1088                 }
 1089         }
 1090 
 1091         if (prev_trp) {
 1092                 trp->tr_tmo_prev = prev_trp;
 1093                 if ((trp->tr_tmo_next = prev_trp->tr_tmo_next) != 0)
 1094                         prev_trp->tr_tmo_next->tr_tmo_prev = trp;
 1095                 prev_trp->tr_tmo_next = trp;
 1096         } else {
 1097                 trp->tr_tmo_prev = 0;
 1098                 trp->tr_tmo_next = trp_tmo_list;
 1099                 trp_tmo_list->tr_tmo_prev = trp;
 1100                 trp_tmo_list = trp;
 1101         }
 1102         ATENABLE(s, atptmo_lock);
 1103 }
 1104 
 1105 void
 1106 atp_untimout(func, trp)
 1107         void (*func)();
 1108         struct atp_trans *trp;
 1109 {
 1110         int s;
 1111 
 1112         ATDISABLE(s, atptmo_lock);
 1113         if (trp->tr_tmo_func == 0) {
 1114                 ATENABLE(s, atptmo_lock);
 1115                 return;
 1116         }
 1117 
 1118         if (trp_tmo_list == trp) {
 1119                 if ((trp_tmo_list = trp->tr_tmo_next) != 0) {
 1120                         trp_tmo_list->tr_tmo_prev = 0;
 1121                         trp->tr_tmo_next->tr_tmo_delta += trp->tr_tmo_delta;
 1122                 }
 1123         } else {
 1124                 if ((trp->tr_tmo_prev->tr_tmo_next = trp->tr_tmo_next) != 0) {
 1125                         trp->tr_tmo_next->tr_tmo_prev = trp->tr_tmo_prev;
 1126                         trp->tr_tmo_next->tr_tmo_delta += trp->tr_tmo_delta;
 1127                 }
 1128         }
 1129         trp->tr_tmo_func = 0;
 1130         ATENABLE(s, atptmo_lock);
 1131 }
 1132 
 1133 void
 1134 atp_trp_clock_locked(arg)
 1135         void *arg;
 1136 {
 1137         atalk_lock();
 1138         atp_trp_clock(arg);
 1139         atalk_unlock();
 1140 }
 1141 
 1142 void
 1143 atp_trp_clock(arg)
 1144         void *arg;
 1145 {
 1146         int s;
 1147         struct atp_trans *trp;
 1148         void (*tr_tmo_func)();
 1149 
 1150         ATDISABLE(s, atptmo_lock);
 1151         if (trp_tmo_list)
 1152                 trp_tmo_list->tr_tmo_delta--;
 1153         while (((trp = trp_tmo_list) != 0) && (trp_tmo_list->tr_tmo_delta == 0)) {
 1154                 if ((trp_tmo_list = trp->tr_tmo_next) != 0)
 1155                         trp_tmo_list->tr_tmo_prev = 0;
 1156                 if ((tr_tmo_func = trp->tr_tmo_func) != 0) {
 1157                         trp->tr_tmo_func = 0;
 1158                         ATENABLE(s, atptmo_lock);
 1159                         (*tr_tmo_func)(trp);
 1160                         ATDISABLE(s, atptmo_lock);
 1161                 }
 1162         }
 1163         ATENABLE(s, atptmo_lock);
 1164 
 1165         timeout(atp_trp_clock_locked, (void *)arg, (1<<5));
 1166 }
 1167 
 1168 void
 1169 atp_send_req(gref, mioc)
 1170         gref_t *gref;
 1171         gbuf_t *mioc;
 1172 {
 1173         register struct atp_state *atp;
 1174         register struct atp_trans *trp;
 1175         register ioc_t *iocbp;
 1176         register at_atp_t *athp;
 1177         register at_ddp_t *ddp;
 1178         gbuf_t *m, *m2, *bds;
 1179         struct atp_set_default *sdb;
 1180         int s, old;
 1181         unsigned int timer;
 1182 
 1183         atp = (struct atp_state *)((struct atp_state *)gref->info)->atp_msgq;
 1184         iocbp = (ioc_t *)gbuf_rptr(mioc);
 1185 
 1186         if ((trp = atp_trans_alloc(atp)) == NULL) {
 1187 l_retry:
 1188                 ((asp_scb_t *)gref->info)->stat_msg = mioc;
 1189                 iocbp->ioc_private = (void *)gref;
 1190                 timeout(atp_retry_req, mioc, 10);
 1191                 return;
 1192         }
 1193 
 1194         m2 = gbuf_cont(mioc);
 1195         if ((bds = gbuf_dupb(m2)) == NULL) {
 1196                 atp_trans_free(trp);
 1197                 goto l_retry;
 1198         }
 1199         gbuf_rinc(m2,atpBDSsize);
 1200         gbuf_wset(bds,atpBDSsize);
 1201         iocbp->ioc_count -= atpBDSsize;
 1202         gbuf_cont(m2) = NULL;
 1203 
 1204         old = iocbp->ioc_cmd;
 1205         iocbp->ioc_cmd = AT_ATP_ISSUE_REQUEST;
 1206         sdb = (struct atp_set_default *)gbuf_rptr(m2);
 1207 
 1208         /*
 1209          * The at_snd_req library routine multiplies seconds by 100.
 1210          * We need to divide by 100 in order to obtain the timer.
 1211          */
 1212         if ((timer = (sdb->def_rate * HZ)/100) == 0)
 1213             timer = HZ;
 1214         iocbp->ioc_count -= sizeof(struct atp_set_default);
 1215         gbuf_rinc(m2,sizeof(struct atp_set_default));
 1216 
 1217         trp->tr_retry = sdb->def_retries;
 1218         trp->tr_timeout = timer;
 1219         trp->tr_bdsp = bds;
 1220         trp->tr_tid = atp_tid(atp);
 1221         trp->tr_xmt = mioc;
 1222 
 1223         /*
 1224          *      Now fill in the header (and remember the bits
 1225          *              we need to know)
 1226          */
 1227         athp = AT_ATP_HDR(m2);
 1228         athp->cmd = ATP_CMD_TREQ;
 1229         UAS_ASSIGN(athp->tid, trp->tr_tid);
 1230         athp->eom = 0;
 1231         athp->sts = 0;
 1232         trp->tr_xo = athp->xo;
 1233         trp->tr_bitmap = athp->bitmap;
 1234         ddp = AT_DDP_HDR(m2);
 1235         ddp->type = DDP_ATP;
 1236         ddp->src_socket = (at_socket)atp->atp_socket_no;
 1237         trp->tr_socket.socket = ddp->dst_socket;
 1238         trp->tr_socket.node = ddp->dst_node;
 1239         trp->tr_socket.net = NET_VALUE(ddp->dst_net);
 1240         trp->tr_local_socket = atp->atp_socket_no;
 1241         trp->tr_local_node = ddp->src_node;
 1242         NET_NET(trp->tr_local_net, ddp->src_net);
 1243 
 1244 #ifdef NOT_YET
 1245         /* save the local information in the gref */
 1246         atp->atp_gref->laddr.s_net = NET_VALUE(ddp->src_net);
 1247         atp->atp_gref->laddr.s_node = ddp->src_node;
 1248         atp->atp_gref->lport = ddp->src_node;
 1249         atp->atp_gref->ddptype = DDP_ATP;
 1250 #endif
 1251 
 1252         /*
 1253          *      Put us in the transaction waiting queue
 1254          */
 1255         ATDISABLE(s, atp->atp_lock);
 1256         ATP_Q_APPEND(atp->atp_trans_wait, trp, tr_list);
 1257         ATENABLE(s, atp->atp_lock);
 1258 
 1259         /*
 1260          * Send the message and set the timer   
 1261          */
 1262         m = (gbuf_t *)copy_pkt(m2, sizeof(llc_header_t));
 1263         if (!trp->tr_retry && !trp->tr_bitmap && !trp->tr_xo)
 1264                 atp_x_done(trp); /* no reason to tie up resources */
 1265         else
 1266                 atp_timout(atp_req_timeout, trp, trp->tr_timeout);
 1267         if (m) {
 1268                 trace_mbufs(D_M_ATP_LOW, "  s", m);
 1269                 DDP_OUTPUT(m);
 1270         }
 1271 } /* atp_send_req */
 1272 
 1273 void atp_retry_req(arg)
 1274         void *arg;
 1275 {
 1276         gbuf_t *m = (gbuf_t *)arg;
 1277         gref_t *gref;
 1278 
 1279         atalk_lock();
 1280 
 1281         gref = (gref_t *)((ioc_t *)gbuf_rptr(m))->ioc_private;
 1282         if (gref->info) {
 1283                 ((asp_scb_t *)gref->info)->stat_msg = 0;
 1284                 atp_send_req(gref, m);
 1285         }
 1286         atalk_unlock();
 1287 }
 1288 
 1289 void atp_send_rsp(gref, m, wait)
 1290         gref_t *gref;
 1291         gbuf_t *m;
 1292         int wait;
 1293 {
 1294         register struct atp_state *atp;
 1295         register struct atp_rcb *rcbp;
 1296         register at_atp_t *athp;
 1297         register at_ddp_t *ddp;
 1298         int s, xcnt;
 1299 
 1300         atp = (struct atp_state *)gref->info;
 1301         if (atp->dflag)
 1302                 atp = (struct atp_state *)atp->atp_msgq;
 1303         ddp = AT_DDP_HDR(m);
 1304         athp = AT_ATP_HDR(m);
 1305 
 1306         /*
 1307          *      search for the corresponding rcb
 1308          */
 1309         ATDISABLE(s, atp->atp_lock);
 1310         for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) {
 1311             if ( (rcbp->rc_tid == UAS_VALUE(athp->tid)) &&
 1312                         (rcbp->rc_socket.node == ddp->dst_node) &&
 1313                         (rcbp->rc_socket.net == NET_VALUE(ddp->dst_net)) &&
 1314                         (rcbp->rc_socket.socket == ddp->dst_socket) )
 1315                 break;
 1316         }
 1317 
 1318         /*
 1319          *      If it has already been sent then drop the request
 1320          */
 1321         if ((rcbp && (rcbp->rc_state != RCB_NOTIFIED)) ||
 1322                         (rcbp == NULL && athp->xo) ) {
 1323                 ATENABLE(s, atp->atp_lock);
 1324                 gbuf_freem(m);
 1325                 return;
 1326         }
 1327         ATENABLE(s, atp->atp_lock);
 1328 
 1329         if (rcbp == NULL) { /* a response is being sent for an ALO transaction */
 1330             if ((rcbp = atp_rcb_alloc(atp)) == NULL) {
 1331                         gbuf_freem(m);
 1332                         return;
 1333             }
 1334             rcbp->rc_ioctl = 0;
 1335             rcbp->rc_socket.socket = ddp->dst_socket;
 1336             rcbp->rc_socket.node = ddp->dst_node;
 1337             rcbp->rc_socket.net = NET_VALUE(ddp->dst_net);
 1338             rcbp->rc_tid = UAS_VALUE(athp->tid);
 1339             rcbp->rc_bitmap = 0xff;
 1340             rcbp->rc_xo = 0;
 1341             rcbp->rc_state = RCB_RESPONSE_FULL;
 1342             ATDISABLE(s, atp->atp_lock);
 1343             ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
 1344                 ATENABLE(s, atp->atp_lock);
 1345         }
 1346         else if (ddp->src_node == 0) {
 1347                 NET_NET(ddp->src_net, rcbp->rc_local_net);
 1348                 ddp->src_node = rcbp->rc_local_node;
 1349         }
 1350 
 1351         xcnt = get_bds_entries(m);
 1352         s = atp_unpack_bdsp(atp, m, rcbp, xcnt, wait);
 1353         if (s == 0)
 1354                 atp_send_replies(atp, rcbp);
 1355 } /* atp_send_rsp */
 1356 
 1357 int asp_pack_bdsp(trp, xm)
 1358      register struct  atp_trans     *trp;
 1359      gbuf_t **xm;
 1360 {
 1361         register struct atpBDS *bdsp;
 1362         register gbuf_t        *m, *m2;
 1363         register int           i;
 1364         gbuf_t        *m_prev, *m_head = 0;
 1365 
 1366         dPrintf(D_M_ATP, D_L_INFO, ("asp_pack_bdsp: socket=%d\n",
 1367                 trp->tr_queue->atp_socket_no));
 1368 
 1369         if ((m2 = trp->tr_bdsp) == NULL)
 1370                 return 0;
 1371         trp->tr_bdsp = NULL;
 1372         bdsp = (struct atpBDS *)gbuf_rptr(m2);
 1373 
 1374         for (i = 0; (i < ATP_TRESP_MAX && 
 1375                      bdsp < (struct atpBDS *)(gbuf_wptr(m2))); i++) {
 1376                 if ((m = trp->tr_rcv[i]) == NULL)
 1377                         break;
 1378                 if (i == 0) {
 1379                         /* discard ddp hdr on first packet */
 1380                         gbuf_rinc(m,DDP_X_HDR_SIZE); 
 1381                 }
 1382 
 1383                 UAL_UAL(bdsp->bdsUserData, (((at_atp_t *)(gbuf_rptr(m)))->user_bytes));
 1384                 gbuf_rinc(m, ATP_HDR_SIZE);
 1385 
 1386                 if (UAL_VALUE(bdsp->bdsBuffAddr)) {
 1387                         short tmp = 0;
 1388 
 1389                         /* user expects data back */
 1390                         m = gbuf_strip(m);
 1391                         if (m_head == 0)
 1392                                 m_head = m;
 1393                         else
 1394                                 gbuf_cont(m_prev) = m;
 1395                         if (m) {
 1396                                 tmp = (short)gbuf_len(m);
 1397                                 while (gbuf_cont(m)) {
 1398                                         m = gbuf_cont(m);
 1399                                         tmp += (short)(gbuf_len(m));
 1400                                 }
 1401                                 m_prev = m;
 1402                         }
 1403                         UAS_ASSIGN(bdsp->bdsDataSz, tmp);
 1404                 }
 1405                 trp->tr_rcv[i] = NULL;
 1406                 bdsp++;
 1407 
 1408         }
 1409         /*
 1410          * report the number of packets
 1411          */
 1412         UAS_ASSIGN(((struct atpBDS *)gbuf_rptr(m2))->bdsBuffSz, i);
 1413 
 1414         if (trp->tr_xmt) /* an ioctl block is still held? */
 1415                 gbuf_cont(trp->tr_xmt) = m2;
 1416         else
 1417                 trp->tr_xmt = m2;
 1418 
 1419         if (m_head)
 1420                 *xm = m_head;
 1421         else
 1422                 *xm = 0;
 1423 
 1424         dPrintf(D_M_ATP, D_L_INFO, ("             : size=%d\n",
 1425                 gbuf_msgsize(*xm)));
 1426 
 1427         return 0;
 1428 }
 1429 
 1430 /*
 1431  * The following routines are direct entries from system
 1432  * calls to allow fast sending and recving of ATP data.
 1433  */
 1434 
 1435 int
 1436 _ATPsndreq(fd, buf, len, nowait, err, proc)
 1437         int fd;
 1438         unsigned char *buf;
 1439         int len;
 1440         int nowait;
 1441         int *err;
 1442         void *proc;
 1443 {
 1444         gref_t *gref;
 1445         int s, rc;
 1446         unsigned short tid;
 1447         unsigned int timer;
 1448         register struct atp_state *atp;
 1449         register struct atp_trans *trp;
 1450         register ioc_t *iocbp;
 1451         register at_atp_t *athp;
 1452         register at_ddp_t *ddp;
 1453         struct atp_set_default *sdb;
 1454         gbuf_t *m2, *m, *mioc;
 1455         char bds[atpBDSsize];
 1456 
 1457         if ((*err = atalk_getref(0, fd, &gref, proc, 1)) != 0)
 1458                 return -1;
 1459 
 1460         if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
 1461                         || (atp->atp_flags & ATP_CLOSING)) {
 1462                 dPrintf(D_M_ATP, D_L_ERROR, ("ATPsndreq: stale handle=0x%x, pid=%d\n",
 1463                         (u_int) gref, gref->pid));
 1464                 file_drop(fd);
 1465                 *err = EINVAL;
 1466                 return -1;
 1467         }
 1468 
 1469 
 1470         while ((mioc = gbuf_alloc(sizeof(ioc_t), PRI_MED)) == 0) {
 1471                 struct timespec ts;
 1472                 /* the vaue of 10n terms of hz is 100ms */
 1473                 ts.tv_sec = 0;
 1474                 ts.tv_nsec = 100 *1000 * NSEC_PER_USEC;
 1475 
 1476                 ATDISABLE(s, atp->atp_delay_lock);
 1477                 rc = msleep(&atp->atp_delay_event, atalk_mutex, PSOCK | PCATCH, "atpmioc", &ts);
 1478                 ATENABLE(s, atp->atp_delay_lock);
 1479                 if (rc != 0) {
 1480                         *err = rc;
 1481                         file_drop(fd);
 1482                         return -1;
 1483                 }
 1484                 
 1485         }
 1486         gbuf_wset(mioc,sizeof(ioc_t));
 1487         len -= atpBDSsize;
 1488         while ((m2 = gbuf_alloc(len, PRI_MED)) == 0) {
 1489         struct timespec ts;
 1490         /* the vaue of 10n terms of hz is 100ms */
 1491         ts.tv_sec = 0;
 1492         ts.tv_nsec = 100 *1000 * NSEC_PER_USEC;
 1493 
 1494                 ATDISABLE(s, atp->atp_delay_lock);
 1495                 rc = msleep(&atp->atp_delay_event, atalk_mutex, PSOCK | PCATCH, "atpm2", &ts);
 1496                 ATENABLE(s, atp->atp_delay_lock);
 1497                 if (rc != 0) {
 1498                         gbuf_freeb(mioc);
 1499                         file_drop(fd);
 1500                         *err = rc;
 1501                         return -1;
 1502                 }
 1503         }
 1504         gbuf_wset(m2, len);
 1505         gbuf_cont(mioc) = m2;
 1506         if (((*err = copyin(CAST_USER_ADDR_T(buf), (caddr_t)bds, atpBDSsize)) != 0)
 1507                 || ((*err = copyin(CAST_USER_ADDR_T(&buf[atpBDSsize]),
 1508                         (caddr_t)gbuf_rptr(m2), len)) != 0)) {
 1509                 gbuf_freem(mioc);
 1510                 file_drop(fd);
 1511                 return -1;
 1512         }
 1513         gbuf_set_type(mioc, MSG_IOCTL);
 1514         iocbp = (ioc_t *)gbuf_rptr(mioc);
 1515         iocbp->ioc_count = len;
 1516         iocbp->ioc_cmd = nowait ? AT_ATP_ISSUE_REQUEST_NOTE : AT_ATP_ISSUE_REQUEST;
 1517         sdb = (struct atp_set_default *)gbuf_rptr(m2);
 1518 
 1519         /*
 1520          * The at_snd_req library routine multiplies seconds by 100.
 1521          * We need to divide by 100 in order to obtain the timer.
 1522          */
 1523         if ((timer = (sdb->def_rate * HZ)/100) == 0)
 1524             timer = HZ;
 1525         iocbp->ioc_count -= sizeof(struct atp_set_default);
 1526         gbuf_rinc(m2,sizeof(struct atp_set_default));
 1527 
 1528         /*
 1529          * allocate and set up the transaction record
 1530          */
 1531         while ((trp = atp_trans_alloc(atp)) == 0) {
 1532         struct timespec ts;
 1533         /* the vaue of 10n terms of hz is 100ms */
 1534         ts.tv_sec = 0;
 1535         ts.tv_nsec = 100 *1000 * NSEC_PER_USEC;
 1536 
 1537                 ATDISABLE(s, atp->atp_delay_lock);
 1538                 rc = msleep(&atp->atp_delay_event, atalk_mutex, PSOCK | PCATCH, "atptrp", &ts);
 1539                 ATENABLE(s, atp->atp_delay_lock);
 1540                 if (rc != 0) {
 1541                         gbuf_freem(mioc);
 1542                         file_drop(fd);
 1543                         *err = rc;
 1544                         return -1;
 1545                 }
 1546         }
 1547         trp->tr_retry = sdb->def_retries;
 1548         trp->tr_timeout = timer;
 1549         trp->tr_bdsp = NULL;
 1550         trp->tr_tid = atp_tid(atp);
 1551         tid = trp->tr_tid;
 1552 
 1553         /*
 1554          *      remember the IOCTL packet so we can ack it
 1555          *              later
 1556          */
 1557         trp->tr_xmt = mioc;
 1558 
 1559         /*
 1560          *      Now fill in the header (and remember the bits
 1561          *              we need to know)
 1562          */
 1563         athp = AT_ATP_HDR(m2);
 1564         athp->cmd = ATP_CMD_TREQ;
 1565         UAS_ASSIGN(athp->tid, trp->tr_tid);
 1566         athp->eom = 0;
 1567         athp->sts = 0;
 1568         trp->tr_xo = athp->xo;
 1569         trp->tr_bitmap = athp->bitmap;
 1570         ddp = AT_DDP_HDR(m2);
 1571         ddp->type = DDP_ATP;
 1572         ddp->src_socket = (at_socket)atp->atp_socket_no;
 1573         ddp->src_node = 0;
 1574         trp->tr_socket.socket = ddp->dst_socket;
 1575         trp->tr_socket.node = ddp->dst_node;
 1576         trp->tr_socket.net = NET_VALUE(ddp->dst_net);
 1577         trp->tr_local_socket = atp->atp_socket_no;
 1578 
 1579 #ifdef NOT_YET
 1580         /* save the local information in the gref */
 1581         atp->atp_gref->laddr.s_net = NET_VALUE(ddp->src_net);
 1582         atp->atp_gref->laddr.s_node = ddp->src_node;
 1583         atp->atp_gref->lport = ddp->src_node;
 1584         atp->atp_gref->ddptype = DDP_ATP;
 1585 #endif
 1586 
 1587         /*
 1588          *      Put us in the transaction waiting queue
 1589          */
 1590         ATDISABLE(s, atp->atp_lock);
 1591         ATP_Q_APPEND(atp->atp_trans_wait, trp, tr_list);
 1592         ATENABLE(s, atp->atp_lock);
 1593 
 1594         /*
 1595          * Send the message and set the timer   
 1596          */
 1597         m = (gbuf_t *)copy_pkt(m2, sizeof(llc_header_t));
 1598         if ( !trp->tr_retry && !trp->tr_bitmap && !trp->tr_xo)
 1599                 atp_x_done(trp); /* no reason to tie up resources */
 1600         else
 1601                 atp_timout(atp_req_timeout, trp, trp->tr_timeout);
 1602         if (m)
 1603                 DDP_OUTPUT(m);
 1604 
 1605         if (nowait) {
 1606                 file_drop(fd);
 1607                 return (int)tid;
 1608         }
 1609 
 1610         /*
 1611          * wait for the transaction to complete
 1612          */
 1613         ATDISABLE(s, trp->tr_lock);
 1614         while ((trp->tr_state != TRANS_DONE) && (trp->tr_state != TRANS_FAILED) &&
 1615                                 (trp->tr_state != TRANS_ABORTING)) {
 1616                 trp->tr_rsp_wait = 1;
 1617                 rc = msleep(&trp->tr_event, atalk_mutex, PSOCK | PCATCH, "atpsndreq", 0);
 1618                 if (rc != 0) {
 1619                         trp->tr_rsp_wait = 0;
 1620                         ATENABLE(s, trp->tr_lock);
 1621                         file_drop(fd);
 1622                         *err = rc;
 1623                         return -1;
 1624                 }
 1625         }
 1626         trp->tr_rsp_wait = 0;
 1627         ATENABLE(s, trp->tr_lock);
 1628 
 1629 
 1630         if (trp->tr_state == TRANS_FAILED || trp->tr_state == TRANS_ABORTING) {
 1631                 /*
 1632                  * transaction timed out, return error
 1633                  */
 1634                 atp_free(trp);
 1635                 file_drop(fd);
 1636                 *err = ETIMEDOUT;
 1637                 return -1;
 1638         }
 1639 
 1640         /*
 1641          * copy out the recv data
 1642          */
 1643         if ((*err = atp_pack_bdsp(trp, (struct atpBDS *)bds)) != 0) {
 1644                 atp_free(trp);
 1645                 file_drop(fd);
 1646                 return -1;
 1647         }
 1648 
 1649         /*
 1650          * copyout the result info
 1651          */
 1652         if ((*err = copyout((caddr_t)bds, CAST_USER_ADDR_T(buf), atpBDSsize)) != 0) {
 1653                 atp_free(trp);
 1654                 file_drop(fd);
 1655                 return -1;
 1656         }
 1657 
 1658         atp_free(trp);
 1659         file_drop(fd);
 1660 
 1661         return (int)tid;
 1662 } /* _ATPsndreq */
 1663 
 1664 
 1665 /*      entry point for ATP send response.  respbuf contains a DDP hdr,
 1666  *      ATP hdr, and atpBDS array.  The bdsDataSz field of the first atpBDS
 1667  *      struct contains the number of atpBDS structs in the array. resplen
 1668  *      contains the len of the data in respbuf and datalen contains the
 1669  *      len of the data buffer holding the response packets which the atpBDS
 1670  *      struct entries point to.
 1671  */
 1672 int
 1673 _ATPsndrsp(fd, respbuff, resplen, datalen, err, proc)
 1674         int fd;
 1675         unsigned char *respbuff;
 1676         int resplen;
 1677         int datalen;
 1678         int *err;
 1679         void *proc;
 1680 {
 1681         gref_t          *gref;
 1682         int             s, rc;
 1683         long            bufaddr;
 1684         gbuf_t          *m, *mdata;
 1685         short           space;
 1686         int             size;
 1687         struct atp_state *atp;
 1688         struct atpBDS *bdsp;
 1689         u_int16_t       *bufsz;
 1690         char            *buf;
 1691         int                     bds_cnt, count, len;
 1692         caddr_t         dataptr;
 1693 
 1694         if ((*err = atalk_getref(0, fd, &gref, proc, 1)) != 0)
 1695                 return -1;
 1696 
 1697         if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
 1698                         || (atp->atp_flags & ATP_CLOSING)) {
 1699                 dPrintf(D_M_ATP, D_L_ERROR, ("ATPsndrsp: stale handle=0x%x, pid=%d\n",
 1700                         (u_int) gref, gref->pid));
 1701 
 1702                 file_drop(fd);
 1703                 *err = EINVAL;
 1704                 return -1;
 1705         }
 1706 
 1707         /*
 1708          * allocate buffer and copy in the response info
 1709          */
 1710         if ((m = gbuf_alloc_wait(resplen, TRUE)) == 0) {
 1711                 *err = ENOMEM;
 1712                 file_drop(fd);
 1713                 return -1;
 1714         }
 1715         if ((*err = copyin(CAST_USER_ADDR_T(respbuff), (caddr_t)gbuf_rptr(m), resplen)) != 0) {
 1716                 gbuf_freeb(m);
 1717                 file_drop(fd);
 1718                 return -1;
 1719         }
 1720         gbuf_wset(m,resplen);
 1721         ((at_ddp_t *)gbuf_rptr(m))->src_node = 0;
 1722         bdsp = (struct atpBDS *)(gbuf_rptr(m) + TOTAL_ATP_HDR_SIZE);
 1723 
 1724         /*
 1725          * allocate buffers and copy in the response data.
 1726          * note that only the size field of the atpBDS field
 1727          * is used internally in the kernel.
 1728          */
 1729         bds_cnt = get_bds_entries(m);           /* count of # entries */
 1730         /* check correctness of parameters */
 1731         if (bds_cnt > ATP_TRESP_MAX) {
 1732             gbuf_freem(m);
 1733                 *err = EINVAL;
 1734                 file_drop(fd);
 1735                 return -1;
 1736         }
 1737         
 1738         for (size = 0, count = 0; count < bds_cnt; count++) {
 1739                 size += UAS_VALUE(bdsp[count].bdsBuffSz);
 1740         }
 1741         if (size > datalen) {                           
 1742             gbuf_freem(m);
 1743                 *err = EINVAL;
 1744                 file_drop(fd);
 1745                 return -1;
 1746         }
 1747         
 1748         /* get the first mbuf */
 1749         if ((mdata = gbuf_alloc_wait((space = (size > MCLBYTES ? MCLBYTES : size)), TRUE)) == 0) {
 1750             gbuf_freem(m);
 1751                 file_drop(fd);
 1752                 *err = ENOMEM;
 1753                 return -1;
 1754         }
 1755         gbuf_cont(m) = mdata;
 1756         dataptr = mtod(mdata, caddr_t);
 1757         for (count = 0; count < bds_cnt; bdsp++, count++) {
 1758                 if ((bufaddr = UAL_VALUE(bdsp->bdsBuffAddr)) != 0 && 
 1759                                 (len = UAS_VALUE(bdsp->bdsBuffSz)) != 0) {
 1760                         if (len > space) {                                                                                      /* enough room ? */
 1761                                 gbuf_wset(mdata, dataptr - mtod(mdata, caddr_t));               /* set len of last mbuf */
 1762                                 /* allocate the next mbuf */
 1763                                 if ((gbuf_cont(mdata) = m_get((M_WAIT), MSG_DATA)) == 0) {
 1764                                         gbuf_freem(m);
 1765                                         file_drop(fd);
 1766                                         *err = ENOMEM;
 1767                                         return -1;
 1768                                 }
 1769                                 mdata = gbuf_cont(mdata);       
 1770                                 MCLGET(mdata, M_WAIT);
 1771                                 if (!(mdata->m_flags & M_EXT)) {
 1772                                         m_freem(m);
 1773                                         file_drop(fd);
 1774                                         return(NULL);
 1775                                 }
 1776                                 dataptr = mtod(mdata, caddr_t);
 1777                                 space = MCLBYTES;
 1778                         }
 1779                         /* do the copyin */
 1780                         if ((*err = copyin(CAST_USER_ADDR_T(bufaddr), dataptr, len)) != 0) {
 1781                                 gbuf_freem(m);
 1782                                 file_drop(fd);
 1783                                 return -1;
 1784                         }
 1785                         dataptr += len;
 1786                         space -= len;
 1787                 }
 1788         }
 1789         gbuf_wset(mdata, dataptr - mtod(mdata, caddr_t));               /* set len of last mbuf */
 1790         gbuf_cont(m)->m_pkthdr.len = size;                                              /* set packet hdr len */
 1791 
 1792         atp_send_rsp(gref, m, TRUE);
 1793         file_drop(fd);
 1794         return 0;
 1795 }
 1796 
 1797 int
 1798 _ATPgetreq(fd, buf, buflen, err, proc)
 1799         int fd;
 1800         unsigned char *buf;
 1801         int buflen;
 1802         int *err;
 1803         void *proc;
 1804 {
 1805         gref_t *gref;
 1806         register struct atp_state *atp;
 1807         register struct atp_rcb *rcbp;
 1808         register gbuf_t *m, *m_head;
 1809         int s, size, len;
 1810 
 1811         if ((*err = atalk_getref(0, fd, &gref, proc, 1)) != 0)
 1812                 return -1;
 1813 
 1814         if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
 1815                         || (atp->atp_flags & ATP_CLOSING)) {
 1816                 dPrintf(D_M_ATP, D_L_ERROR, ("ATPgetreq: stale handle=0x%x, pid=%d\n",
 1817                         (u_int) gref, gref->pid));
 1818                 file_drop(fd);
 1819                 *err = EINVAL;
 1820                 return -1;
 1821         }
 1822 
 1823         ATDISABLE(s, atp->atp_lock);
 1824         if ((rcbp = atp->atp_attached.head) != NULL) {
 1825             /*
 1826              * Got one, move it to the active response Q
 1827              */
 1828                 m_head = rcbp->rc_ioctl;
 1829                 rcbp->rc_ioctl = NULL;
 1830 
 1831                 if (rcbp->rc_xo) {
 1832                         ATP_Q_REMOVE(atp->atp_attached, rcbp, rc_list);
 1833                         rcbp->rc_state = RCB_NOTIFIED;
 1834                         ATP_Q_APPEND(atp->atp_rcb, rcbp, rc_list);
 1835                 } else {
 1836                         /* detach rcbp from attached queue,
 1837                          * and free any outstanding resources
 1838                          */
 1839                         atp_rcb_free(rcbp);
 1840                 }
 1841                 ATENABLE(s, atp->atp_lock);
 1842 
 1843                 /*
 1844                  * copyout the request data, including the protocol header
 1845                  */
 1846                 for (size=0, m=m_head; m; m = gbuf_cont(m)) {
 1847                         if ((len = gbuf_len(m)) > buflen)
 1848                                 len = buflen;
 1849                         copyout((caddr_t)gbuf_rptr(m), CAST_USER_ADDR_T(&buf[size]), len);
 1850                         size += len;
 1851                         if ((buflen -= len) == 0)
 1852                                 break;
 1853                 }
 1854                 gbuf_freem(m_head);
 1855 
 1856                 file_drop(fd);
 1857                 return size;
 1858         }
 1859         ATENABLE(s, atp->atp_lock);
 1860 
 1861         file_drop(fd);
 1862         return -1;
 1863 }
 1864 
 1865 int
 1866 _ATPgetrsp(fd, bdsp, err, proc)
 1867         int fd;
 1868         struct atpBDS *bdsp;
 1869         int *err;
 1870         void *proc;
 1871 {
 1872         gref_t *gref;
 1873         register struct atp_state *atp;
 1874         register struct atp_trans *trp;
 1875         int s, tid;
 1876         char bds[atpBDSsize];
 1877 
 1878         if ((*err = atalk_getref(0, fd, &gref, proc, 1)) != 0)
 1879                 return -1;
 1880 
 1881         if ((gref == 0) || ((atp = (struct atp_state *)gref->info) == 0)
 1882                         || (atp->atp_flags & ATP_CLOSING)) {
 1883                 dPrintf(D_M_ATP, D_L_ERROR, ("ATPgetrsp: stale handle=0x%x, pid=%d\n",
 1884                         (u_int) gref, gref->pid));
 1885                 file_drop(fd);
 1886                 *err = EINVAL;
 1887                 return -1;
 1888         }
 1889 
 1890         ATDISABLE(s, atp->atp_lock);
 1891         for (trp = atp->atp_trans_wait.head; trp; trp = trp->tr_list.next) {
 1892                 dPrintf(D_M_ATP, D_L_INFO,
 1893                         ("ATPgetrsp: atp:0x%x, trp:0x%x, state:%d\n",
 1894                         (u_int) atp, (u_int) trp, trp->tr_state));
 1895 
 1896                 switch (trp->tr_state) {
 1897                 case TRANS_DONE:
 1898                 ATENABLE(s, atp->atp_lock);
 1899                         if ((*err = copyin(CAST_USER_ADDR_T(bdsp),
 1900                                         (caddr_t)bds, sizeof(bds))) != 0) {
 1901                                 atp_free(trp);
 1902                                 file_drop(fd);
 1903                                 return -1;
 1904                         }
 1905                         if ((*err = atp_pack_bdsp(trp, (struct atpBDS *)bds)) != 0) {
 1906                                 atp_free(trp);
 1907                                 file_drop(fd);
 1908                                 return -1;
 1909                         }
 1910                         tid = (int)trp->tr_tid;
 1911                         atp_free(trp);
 1912                         if ((*err = copyout((caddr_t)bds, CAST_USER_ADDR_T(bdsp), sizeof(bds))) != 0) {
 1913                                 file_drop(fd);
 1914                                 return -1;
 1915                         }
 1916                         file_drop(fd);
 1917                         return tid;
 1918 
 1919                 case TRANS_FAILED:
 1920                         /*
 1921                          * transaction timed out, return error
 1922                          */
 1923                 ATENABLE(s, atp->atp_lock);
 1924                         atp_free(trp);
 1925                         file_drop(fd);
 1926                         *err = ETIMEDOUT;
 1927                         return -1;
 1928 
 1929                 default:
 1930                         continue;
 1931             }
 1932         }
 1933         ATENABLE(s, atp->atp_lock);
 1934 
 1935         file_drop(fd);
 1936         *err = EINVAL;
 1937         return -1;
 1938 }
 1939 
 1940 void
 1941 atp_drop_req(gref, m)
 1942         gref_t *gref;
 1943         gbuf_t *m;
 1944 {
 1945         int s;
 1946         struct atp_state *atp;
 1947         struct atp_rcb *rcbp;
 1948         at_atp_t *athp;
 1949         at_ddp_t *ddp;
 1950 
 1951         atp = (struct atp_state *)gref->info;
 1952         if (atp->dflag)
 1953                 atp = (struct atp_state *)atp->atp_msgq;
 1954         ddp = AT_DDP_HDR(m);
 1955         athp = AT_ATP_HDR(m);
 1956 
 1957         /*
 1958          *      search for the corresponding rcb
 1959          */
 1960         ATDISABLE(s, atp->atp_lock);
 1961         for (rcbp = atp->atp_rcb.head; rcbp; rcbp = rcbp->rc_list.next) {
 1962             if ( (rcbp->rc_tid == UAS_VALUE(athp->tid)) &&
 1963                         (rcbp->rc_socket.node == ddp->src_node) &&
 1964                         (rcbp->rc_socket.net == NET_VALUE(ddp->src_net)) &&
 1965                         (rcbp->rc_socket.socket == ddp->src_socket) )
 1966                 break;
 1967         }
 1968 
 1969         /*
 1970          *      drop the request
 1971          */
 1972         if (rcbp)
 1973                 atp_rcb_free(rcbp);
 1974         ATENABLE(s, atp->atp_lock);
 1975 
 1976         gbuf_freem(m);
 1977 }

Cache object: fbd91187d53b0b53c72173413aae7f93


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.