darwin-xnu/bsd/netat/adsp.c
<<
>>
Prefs
   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 * Change log:
  24 *   06/29/95 - Modified to handle flow control for writing (Tuyen Nguyen)
  25 *    Modified for MP, 1996 by Tuyen Nguyen
  26 *   Modified, April 9, 1997 by Tuyen Nguyen for MacOSX.
  27 */
  28#define RESOLVE_DBG
  29#include <sys/errno.h>
  30#include <sys/types.h>
  31#include <sys/param.h>
  32#include <machine/spl.h>
  33#include <sys/systm.h>
  34#include <sys/kernel.h>
  35#include <sys/proc.h>
  36#include <sys/filedesc.h>
  37#include <sys/fcntl.h>
  38#include <sys/mbuf.h>
  39#include <sys/socket.h>
  40
  41#include <netat/sysglue.h>
  42#include <netat/appletalk.h>
  43#include <netat/at_pcb.h>
  44#include <netat/ddp.h>
  45#include <netat/adsp.h>
  46#include <netat/adsp_internal.h>
  47
  48#ifdef notdefn
  49struct adsp_debug adsp_dtable[1025];
  50int ad_entry = 0;
  51#endif
  52
  53extern atlock_t adspgen_lock;
  54
  55adspAllocateCCB(gref)
  56    register gref_t *gref;      /* READ queue */
  57{
  58    gbuf_t *ccb_mp;
  59    register CCBPtr sp;
  60
  61    if (!(ccb_mp = gbuf_alloc(sizeof(CCB), PRI_LO))) {
  62        return (0);
  63    }
  64    bzero((caddr_t) gbuf_rptr(ccb_mp), sizeof(CCB));
  65    gbuf_wset(ccb_mp,sizeof(CCB));
  66    gref->info = (caddr_t) ccb_mp;
  67    sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info));
  68
  69    sp->pid = gref->pid; /* save the caller process pointer */
  70    sp->gref = gref;            /* save a back pointer to the WRITE queue */
  71    sp->sp_mp = ccb_mp;         /* and its message block */
  72    ATLOCKINIT(sp->lock);
  73    ATLOCKINIT(sp->lockClose);
  74    ATLOCKINIT(sp->lockRemove);
  75    return 1;
  76}
  77
  78adspRelease(gref)
  79    register gref_t *gref;      /* READ queue */
  80{
  81    register CCBPtr sp;
  82    int s, l;
  83
  84    ATDISABLE(l, adspgen_lock);
  85    if (gref->info) {
  86        sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info));
  87        ATDISABLE(s, sp->lock);
  88        ATENABLE(s, adspgen_lock);
  89                                /* Tells completion routine of close */
  90                                /* packet to remove us. */
  91
  92        if (sp->state == sPassive || sp->state == sClosed || 
  93            sp->state == sOpening || sp->state == sListening) {
  94            ATENABLE(l, sp->lock);
  95            if (sp->state == sListening)
  96                CompleteQueue(&sp->opb, errAborted);
  97            sp->removing = 1;   /* Prevent allowing another dspClose. */
  98            DoClose(sp, errAborted, 0); /* will remove CCB */
  99            return 0;
 100        } else {                        /* sClosing & sOpen */
 101            sp->state = sClosing;
 102        }
 103        ATENABLE(l, sp->lock);
 104
 105        if (CheckOkToClose(sp)) { /* going to close */
 106            sp->sendCtl = B_CTL_CLOSE; /* Send close advice */
 107        } else {
 108                CheckSend(sp);  /* try one more time to send out data */
 109                if (sp->state != sClosed)
 110                    sp->sendCtl = B_CTL_CLOSE; /* Setup to send close advice */
 111        }
 112        CheckSend(sp);          /* and force out the close */
 113        ATDISABLE(s, sp->lock);
 114            sp->removing = 1;   /* Prevent allowing another dspClose. */
 115            sp->state = sClosed;
 116        ATENABLE(s, sp->lock);
 117            DoClose(sp, errAborted, 0);  /* to closed and remove CCB */
 118    } else
 119        ATENABLE(l, adspgen_lock);
 120}
 121
 122
 123
 124
 125adspWriteHandler(gref, mp)
 126    gref_t *gref;                       /* WRITE queue */
 127    gbuf_t *mp;
 128{
 129
 130    register ioc_t *iocbp;
 131    register struct adspcmd *ap;
 132    int error, flag;
 133        void *sp;
 134
 135    switch(gbuf_type(mp)) {
 136                case MSG_DATA:
 137                if (gref->info == 0) {
 138                        gbuf_freem(mp);
 139                        return(STR_IGNORE);
 140                        }
 141                /*
 142                 * Fill in the global stuff
 143                 */
 144                ap = (struct adspcmd *)gbuf_rptr(mp);
 145                ap->gref = gref;
 146                ap->ioc = 0;
 147                ap->mp = mp;
 148                sp = (void *)gbuf_rptr(((gbuf_t *)gref->info));
 149                switch(ap->csCode) {
 150                        case dspWrite:
 151                                if ((error = adspWrite(sp, ap)))
 152                                gbuf_freem(mp);
 153                                return(STR_IGNORE);
 154                        case dspAttention:
 155                                if ((error = adspAttention(sp, ap)))
 156                                gbuf_freem(mp);
 157                                return(STR_IGNORE);
 158                }
 159                case MSG_IOCTL:
 160                if (gref->info == 0) {
 161                        adspioc_ack(EPROTOTYPE, mp, gref);
 162                        return(STR_IGNORE);
 163                        }
 164                iocbp = (ioc_t *) gbuf_rptr(mp);
 165                if (ADSP_IOCTL(iocbp->ioc_cmd)) {
 166                        iocbp->ioc_count = sizeof(*ap) - 1;
 167                        if (gbuf_cont(mp) == 0) {
 168                        adspioc_ack(EINVAL, mp, gref);
 169                        return(STR_IGNORE);
 170                        }
 171                        ap = (struct adspcmd *) gbuf_rptr(gbuf_cont(mp));
 172                        ap->gref = gref;
 173                        ap->ioc = (caddr_t) mp;
 174                        ap->mp = gbuf_cont(mp); /* request head */
 175                        ap->ioResult = 0;
 176        
 177                        if ((gref->info == 0) && ((iocbp->ioc_cmd != ADSPOPEN) &&
 178                                                        (iocbp->ioc_cmd != ADSPCLLISTEN))) {
 179                                ap->ioResult = errState;
 180        
 181                        adspioc_ack(EINVAL, mp, gref);
 182                        return(STR_IGNORE);
 183                        }
 184                } else
 185                        return(STR_PUTNEXT);    /* pass it on down */   
 186                sp = (void *)gbuf_rptr(((gbuf_t *)gref->info));
 187                switch(iocbp->ioc_cmd) {
 188                        case ADSPOPEN:
 189                        case ADSPCLLISTEN:
 190                                ap->socket = ((CCBPtr)sp)->localSocket;
 191                                flag = (adspMode(ap) == ocAccept) ? 1 : 0;
 192                                if (flag && ap->socket) {
 193                                        if (adspDeassignSocket((CCBPtr)sp) >= 0)
 194                                                ap->socket = 0;
 195                                }
 196                                if ((ap->socket == 0) &&
 197                                        ((ap->socket = 
 198                                          (at_socket)adspAssignSocket(gref, flag)) == 0)) {
 199                                        adspioc_ack(EADDRNOTAVAIL, mp, gref);
 200                                        return(STR_IGNORE);
 201                                }
 202                                ap->csCode = iocbp->ioc_cmd == ADSPOPEN ? dspInit : dspCLInit;
 203                                if ((error = adspInit(sp, ap)) == 0) {
 204                                switch(ap->csCode) {
 205                                case dspInit:
 206                                        /* and open the connection */
 207                                        ap->csCode = dspOpen;
 208                                        error = adspOpen(sp, ap);
 209                                        break;
 210                                case dspCLInit:
 211                                        /* ADSPCLLISTEN */
 212                                        ap->csCode = dspCLListen;
 213                                        error = adspCLListen(sp, ap);
 214                                        break;
 215                                }
 216                                }
 217                                if (error) 
 218                                adspioc_ack(error, mp, gref); /* if this failed req complete */
 219                                return(STR_IGNORE);
 220                        case ADSPCLOSE:
 221                                ap->csCode = dspClose;
 222                                if ((error = adspClose(sp, ap))) {
 223                                adspioc_ack(error, mp, gref);
 224                                break;
 225                                }
 226                                break;
 227                        case ADSPCLREMOVE:
 228                                ap->csCode = dspCLRemove;
 229                                error = adspClose(sp, ap);
 230                                adspioc_ack(error, mp, gref);
 231                                return(STR_IGNORE);
 232                        case ADSPCLDENY:
 233                                ap->csCode = dspCLDeny;
 234                                if ((error = adspCLDeny(sp, ap))) {
 235                                adspioc_ack(error, mp, gref);
 236                                }
 237                                return(STR_IGNORE);
 238                        case ADSPSTATUS:
 239                                ap->csCode = dspStatus;
 240                                if ((error = adspStatus(sp, ap))) {
 241                                adspioc_ack(error, mp, gref);
 242                                }
 243                                return(STR_IGNORE);
 244                        case ADSPREAD:
 245                                ap->csCode = dspRead;
 246                                if ((error = adspRead(sp, ap))) {
 247                                adspioc_ack(error, mp, gref);
 248                                }
 249                                return(STR_IGNORE);
 250                        case ADSPATTENTION:
 251                                ap->csCode = dspAttention;
 252                                if ((error = adspReadAttention(sp, ap))) {
 253                                adspioc_ack(error, mp, gref);
 254                                }
 255                                return(STR_IGNORE);
 256                        case ADSPOPTIONS:
 257                                ap->csCode = dspOptions;
 258                                if ((error = adspOptions(sp, ap))) {
 259                                adspioc_ack(error, mp, gref);
 260                                }
 261                                return(STR_IGNORE);
 262                        case ADSPRESET:
 263                                ap->csCode = dspReset;
 264                                if ((error = adspReset(sp, ap))) {
 265                                adspioc_ack(error, mp, gref);
 266                                }
 267                                return(STR_IGNORE);
 268                        case ADSPNEWCID:
 269                                ap->csCode = dspNewCID;
 270                                if ((error = adspNewCID(sp, ap))) {
 271                                adspioc_ack(error, mp, gref);
 272                                }
 273                                return(STR_IGNORE);
 274                        default:
 275                                return(STR_PUTNEXT);    /* pass it on down */
 276                }
 277                return(STR_IGNORE);
 278                case MSG_PROTO:
 279                default:
 280                gbuf_freem(mp);
 281    }
 282}
 283
 284
 285adspReadHandler(gref, mp)
 286    gref_t *gref;
 287    gbuf_t *mp;
 288{
 289    int error;
 290
 291    switch(gbuf_type(mp)) {
 292    case MSG_DATA:
 293        if ((error = adspPacket(gref, mp))) {
 294            gbuf_freem(mp);
 295        }
 296        break;
 297        
 298    case MSG_IOCTL:
 299    default:
 300        return(STR_PUTNEXT);
 301        break;
 302    }
 303    return(STR_IGNORE);
 304}
 305
 306/*
 307 * adsp_sendddp()
 308 *
 309 * Description:
 310 *      This procedure a formats a DDP datagram header and calls the
 311 *      DDP module to queue it for routing and transmission according to
 312 *      the DDP parameters.  We always take control of the datagram;
 313 *      if there is an error we free it, otherwise we pass it to the next
 314 *      layer.  We don't need to set the src address fileds because the
 315 *      DDP layer fills these in for us.
 316 *
 317 * Calling Sequence:
 318 *      ret_status = adsp_sendddp(q, sp, mp, length, dstnetaddr, ddptype);
 319 *
 320 * Formal Parameters:
 321 *      sp              Caller stream pointer
 322 *      mp              gbuf_t chain containing the datagram to transmit
 323 *                      The first mblk contains the ADSP header and space
 324 *                      for the DDP header.
 325 *      length          size of data portion of datagram
 326 *      dstnetaddr      address of 4-byte destination internet address
 327 *      ddptype         DDP protocol to assign to the datagram
 328 *
 329 * Completion Status:
 330 *      0               Procedure successful completed.
 331 *      EMSGSIZE        Specified datagram length is too big.
 332 *
 333 * Side Effects:
 334 *      NONE
 335 */
 336
 337adsp_sendddp(sp, mp, length, dstnetaddr, ddptype)
 338   CCBPtr sp;
 339   gbuf_t *mp;
 340   int length;
 341   AddrUnion *dstnetaddr;
 342   int ddptype;
 343{
 344   DDPX_FRAME   *ddp;
 345   gbuf_t *mlist = mp;
 346
 347   if (mp == 0)
 348       return EINVAL;
 349
 350   if (length > DDP_DATA_SIZE) {
 351       gbuf_freel(mlist);
 352       return EMSGSIZE;
 353   }
 354
 355  while (mp) {
 356
 357   if (length == 0)
 358       length = gbuf_msgsize(mp) - DDPL_FRAME_LEN;
 359   /* Set up the DDP header */
 360
 361   ddp = (DDPX_FRAME *) gbuf_rptr(mp);
 362   UAS_ASSIGN(ddp->ddpx_length, (length + DDPL_FRAME_LEN));
 363   UAS_ASSIGN(ddp->ddpx_cksm, 0);
 364   if (sp) {
 365        if (sp->useCheckSum)
 366           UAS_ASSIGN(ddp->ddpx_cksm, 1);
 367   }
 368
 369   NET_ASSIGN(ddp->ddpx_dnet, dstnetaddr->a.net);
 370   ddp->ddpx_dnode = dstnetaddr->a.node;
 371   ddp->ddpx_source = sp ? sp->localSocket : ddp->ddpx_dest;
 372   ddp->ddpx_dest = dstnetaddr->a.socket;
 373
 374   ddp->ddpx_type = ddptype;
 375   length = 0;
 376   mp = gbuf_next(mp);
 377
 378  }
 379           
 380   DDP_OUTPUT(mlist);
 381   return 0;
 382}
 383
 384void NotifyUser(sp)
 385    register CCBPtr sp;
 386
 387{
 388/*
 389    pidsig(sp->pid, SIGIO);
 390*/
 391}
 392
 393void UrgentUser(sp)
 394    register CCBPtr sp;
 395{
 396/*
 397    pidsig(sp->pid, SIGURG);
 398*/
 399}
 400
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.