]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netat/adsp_Close.c
xnu-2422.1.72.tar.gz
[apple/xnu.git] / bsd / netat / adsp_Close.c
diff --git a/bsd/netat/adsp_Close.c b/bsd/netat/adsp_Close.c
deleted file mode 100644 (file)
index d769015..0000000
+++ /dev/null
@@ -1,513 +0,0 @@
-/*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
- *
- * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. The rights granted to you under the License
- * may not be used to create, or enable the creation or redistribution of,
- * unlawful or unlicensed copies of an Apple operating system, or to
- * circumvent, violate, or enable the circumvention or violation of, any
- * terms of an Apple operating system software license agreement.
- * 
- * Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
- */
-/*
- *     Copyright (c) 1990, 1995-1998 Apple Computer, Inc.
- *     All Rights Reserved.
- */
-
-/* dspClose.c 
- * From Mike Shoemaker v01.16 06/29/90 mbs
- */
-/*
- * Change log:
- *   06/29/95 - Modified to handle flow control for writing (Tuyen Nguyen)
- *    Modified for MP, 1996 by Tuyen Nguyen
- *    Modified, April 9, 1997 by Tuyen Nguyen for MacOSX.
- */
-
-#include <sys/errno.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <machine/spl.h>
-#include <sys/systm.h>
-#include <sys/kernel.h>
-#include <sys/proc.h>
-#include <sys/filedesc.h>
-#include <sys/fcntl.h>
-#include <sys/mbuf.h>
-#include <sys/socket.h>
-#include <sys/socketvar.h>
-#include <sys/time.h>
-
-#include <netat/sysglue.h>
-#include <netat/appletalk.h>
-#include <netat/ddp.h>
-#include <netat/at_pcb.h>
-#include <netat/debug.h>
-#include <netat/adsp.h>
-#include <netat/adsp_internal.h>
-
-
-static void qRemove(CCBPtr, CCBPtr);
-
-
-/*
- * CheckOkToClose
- * 
- * Check to see if it is OK to close this connection cleanly.
- *
- * INPUTS:
- *             Stream pointer
- * OUTPUTS:
- *             True if no outstanding transactions and we can close cleanly
- */
-int CheckOkToClose(sp)         /* (CCBPtr sp) */
-    CCBPtr sp;
-{
-    
-    if (sp->sData)             /* Outstanding data ? */
-       return 0;
-
-    if (sp->sapb)              /* Outstanding send attention ? */
-       return 0;
-
-    if (sp->frpb)              /* Outstanding forward reset ? */
-       return 0;
-               
-    if (sp->sendAttnAck)
-       return 0;
-               
-    if (sp->sendDataAck)
-       return 0;
-       
-    /*
-     * Must be OK to close
-     */
-    sp->sendCtl        |= B_CTL_CLOSE; /* So, need to send close advice */
-    sp->callSend = 1;
-
-    return 1;                  /* It's OK to close */
-}
-
-
-/*
- * CompleteQueue
- * 
- * Given the address of the head of a queue of DSP parameter blocks, zero 
- * the queue, and complete each item on the queue with the given result 
- * code.
- *
- * INPUTS:
- *             qhead           Address of ptr to first queue element
- *             code            The result code
- * OUTPUTS:
- *             none
- */
-int  CompleteQueue(qhead, code)        /* (DSPPBPtr FPTR qhead, OSErr code) */
-    struct adspcmd **qhead;
-    int code;
-{
-    register struct adspcmd *p;
-    register struct adspcmd *n;
-    register gref_t *gref;
-    register int    _total = 0;
-    CCBPtr sp = 0;
-
-    n = *qhead;                        /* Get first item */
-    *qhead = 0;                        /* Zero out the queue */
-    if (n) {
-       gref = n->gref;
-       if (gref->info) {
-           sp = (CCBPtr)gbuf_rptr(((gbuf_t *)gref->info));
-           atalk_flush(sp->gref);
-           }
-    }
-
-    while ((p = n)) {          /* while items left */
-       n = (struct adspcmd *)(p->qLink); /* Save next guy */
-       p->ioResult = code;
-       if (sp) {
-           completepb(sp, p);  /* complete the copy of the request */
-           _total++;
-       } else
-           gbuf_freem(p->mp);
-    }                          /* while */
-    return(_total);
-}
-
-/*
- * RemoveCCB
- * 
- * Called from do close to free up the user's CCB.  So, we remove the 
- * CCB from the list of CCB's.
- *
- * INPUTS:
- *             sp      pointer to ccb
- *             pb      a remove param block to complete when done
- * OUTPUTS:
- *             none
- */
-void RemoveCCB(CCBPtr, struct adspcmd *);
-
-void RemoveCCB(sp, pb)         /* (CCBPtr sp, DSPPBPtr pb) */
-    CCBPtr sp;
-    struct adspcmd *pb;
-{
-       gref_t *gref;
-       
-       if (sp->gref == 0)
-               return;
-    /*
-     * Unlink CCB from list
-     */
-    qRemove((CCB *)AT_ADSP_STREAMS, sp); /* remove sp from active streams queue */
-
-    if (pb) {
-       pb->ioResult = 0;
-       if (pb->ioc)            /* is this a current or queued request */
-           adspioc_ack(0, (gbuf_t *)pb->ioc, pb->gref);        /* current */
-       else {
-           completepb(sp, pb); /* queued */
-       }
-       
-       if (sp->opb && (pb != sp->opb)) { /* if the pb requested is not the */
-           pb = sp->opb;               /* waiting open pb, complete it too */
-           sp->opb = 0;
-           pb->ioResult = 0;
-           completepb(sp, pb);
-       } else {
-           sp->opb = 0;
-        }
-    }
-    gref = sp->gref;
-    sp->gref = 0;
-    if (gref->info == (char *)sp->sp_mp) { /* queue head is still valid */
-           unsigned char skt;
-
-           if ((skt = sp->localSocket) != 0) {
-             if (adspDeassignSocket(sp) == 0)
-                 ddp_notify_nbp(skt, sp->pid, DDP_ADSP);
-           }
-
-         if (gref->info) {
-           gbuf_freem((gbuf_t *)gref->info);   /* free the CCB */
-           gref->info = 0;
-         }
-    } else
-       gbuf_freem(sp->sp_mp);  /* our head is already gone, be sure
-                                * to release our resources too */
-}
-
-int  AbortIO(CCBPtr, short);
-
-int  AbortIO(sp, err)
-    CCBPtr sp;
-    short err;
-{
-    register int    _total;
-
-       if (sp->gref == 0)
-               return 0;
-    /*
-     * Complete all outstanding transactions.  
-     */
-    _total = CompleteQueue(&sp->sapb, err); /* Abort outstanding send attentions */
-    CompleteQueue(&sp->frpb, err); /* Abort outstanding forward resets */
-
-    if (sp->sbuf_mb) { /* clear the send queue */
-       gbuf_freel(sp->sbuf_mb);
-       sp->sbuf_mb = 0;
-    }
-
-    if (sp->csbuf_mb) {
-       gbuf_freem(sp->csbuf_mb);
-       sp->csbuf_mb = 0;
-    }
-    sp->sData = 0;
-    
-    return(_total);
-}
-
-/*
- * DoClose
- * 
- * Called from several places (probe timeout, recv close advice, 
- * dspRemove, etc.) to change state of connection to closed and 
- * complete all outstanding I/O.
- *
- * Will also remove the CCB if there is a dsp remove pending.
- *
- * INPUTS:
- *             sp              An ADSP stream
- * OUTPUTS:
- *             none
- */
-void DoClose(sp, err, force_abort)     /* (CCBPtr sp, OSErr err) */
-    register CCBPtr sp;
-    int err;
-       int force_abort;
-{
-    register struct adspcmd *pb, *np;
-    register gbuf_t *mp;
-    int      aborted_count;
-       
-    dPrintf(D_M_ADSP, D_L_TRACE, ("DoClose: pid=%d,e=%d,a=%d,s=%d,r=%d\n",
-               sp->pid, err, force_abort, sp->localSocket, sp->removing));
-    sp->userFlags |= eClosed; /* Set flag */
-    sp->state = sClosed;
-    sp->openState = O_STATE_NOTHING;
-
-    /*
-     * Clean up any timer elements
-     */
-    RemoveTimerElem(&adspGlobal.slowTimers, &sp->ProbeTimer);
-    RemoveTimerElem(&adspGlobal.fastTimers, &sp->FlushTimer);
-    RemoveTimerElem(&adspGlobal.fastTimers, &sp->RetryTimer);
-    RemoveTimerElem(&adspGlobal.fastTimers, &sp->AttnTimer);
-    RemoveTimerElem(&adspGlobal.fastTimers, &sp->ResetTimer);
-
-    aborted_count = AbortIO(sp, err);
-    np = sp->opb;              /* Get list of close/removes to complete */
-    sp->opb = 0;               /* set this list null */
-       
-    while ((pb = np)) {                /* Handle all of the close/remove param blks */
-       np = (struct adspcmd *)pb->qLink; /* Get next guy (if any) */
-       pb->qLink = 0;
-       pb->ioResult = err;
-       completepb(sp, pb);
-    }
-    if (sp->removing && (force_abort >= 0)) {        /* Abort outstanding receives */
-       aborted_count += CompleteQueue(&sp->rpb, err);
-
-       if (sp->deferred_mb) {
-               gbuf_freel(sp->deferred_mb);
-               sp->deferred_mb = 0;
-       }
-       if (sp->attn_mb) {
-               gbuf_freem(sp->attn_mb);
-               sp->attn_mb = 0;
-       }
-       if (sp->rbuf_mb) { /* clear the rcv queue */
-               gbuf_freem(sp->rbuf_mb);
-               sp->rbuf_mb = 0;
-       }
-       if (sp->crbuf_mb) {
-               gbuf_freem(sp->crbuf_mb);
-               sp->crbuf_mb = 0;
-       }
-       sp->rData = 0;
-
-       /* if our connection has been timed out */
-       /* and the user wasn't notified of the TearDown */
-       /* because of pending requests on this socket */
-       /* then fake a read completion to force the notification */
-
-       if (force_abort && aborted_count == 0) {
-           if ((mp = gbuf_alloc(sizeof(struct adspcmd), PRI_HI))) {
-               pb = (struct adspcmd *)gbuf_rptr(mp);
-               gbuf_wset(mp,sizeof(struct adspcmd));
-
-               bzero((caddr_t) pb, sizeof(struct adspcmd));
-               pb->mp = mp;
-               pb->csCode = dspRead;
-               pb->ioResult = errAborted;
-               completepb(sp, pb);             /* send fake read completion */
-           }
-       }
-       sp->removing = 0;
-       RemoveCCB(sp, 0); /* Will call completion routine */
-    }
-    sp->userFlags &= ~eClosed;
-}
-
-
-/*
- * dspClose
- * 
- * Also called for dspRemove and dspCLRemove.
- * Must handle case of multiple close calls being issued (without 
- * abort bit set) Can only allow one pending remove though.
- *
- * INPUTS:
- *     -->     ccbRefNum               refnum of connection end
- *     -->     abort                   abort the connection
- *
- * OUTPUTS:
- *     none
- *
- * ERRORS:
- *             errRefNum               Bad connection Refnum
- */
-int adspClose(sp, pb)          /* (DSPPBPtr pb) */
-    register CCBPtr sp;
-    register struct adspcmd *pb;
-{
-    register gbuf_t *mp;
-       
-    /* Must execute nearly all of this with ints off because user could 
-     * be issuing a second dspRemove while the first is pending.  Until 
-     * we can detect this, we must not allow interrupts.
-     * Also, we can't handle the case where a close was issued earlier, 
-     * and now this is the remove.  If the write completion for the 
-     * close advice packet occurs in the middle of this, we might
-     * foul up.
-     */
-
-    if (sp == 0) {
-       pb->ioResult = errRefNum;
-       return EINVAL;
-    }
-
-    /*
-     * Handle dspCLRemove
-     */
-    if (pb->csCode == (short)dspCLRemove) { /* Remove connection listener */
-       if (sp->state != (short)sListening) { /* But it's not a listener! */
-           pb->ioResult = errState;
-           return EINVAL;
-       }
-       CompleteQueue(&sp->opb, errAborted); /* Complete all dspListens */
-       RemoveCCB(sp, pb);      /* Will call completion routine */
-       return 0;
-    }
-
-
-    /*
-     * Either dspClose or dspRemove
-     */
-
-    if (sp->removing) {                /* Don't allow dspRemove or dspClose */
-                               /* after one dspRemove has been issued. */
-       pb->ioResult = errState;
-       return EINVAL;
-    }
-
-
-    /*
-     * The previous Macintosh ADSP allowed you to call close on a 
-     * connection that was in the process of opening or passively 
-     * waiting for an open request. It is also legal to close a 
-     * connection that is already closed.  No error will be generated.
-     *
-     * It is also legal to issue a second close call while the first 
-     * is still pending.
-     */
-    if (pb->csCode == (short)dspClose) {
-       if ((sp->state == (short)sPassive) || (sp->state == (short)sOpening)) {
-           sp->state = sClosed;
-           DoClose(sp, errAborted, 0);
-           pb->ioResult = 0;
-           adspioc_ack(0, (gbuf_t *)pb->ioc, pb->gref);
-           return 0;
-       }
-               
-       if (sp->state == (word)sClosed) { /* Ok to close a closed connection */
-           pb->ioResult = 0;
-           adspioc_ack(0, (gbuf_t *)pb->ioc, pb->gref);
-           return 0;
-       }
-       if ((sp->state != (word)sOpen) && (sp->state != (word)sClosing)) {
-           pb->ioResult = errState;
-           return EINVAL;
-       }
-               
-       sp->state = sClosing;   /* No matter what, we're closing */
-    }                          /* dspClose */
-    
-    else {                     /* dspRemove */
-       sp->removing = 1;       /* Prevent allowing another dspClose. */
-                               /* Tells completion routine of close */
-                               /* packet to remove us. */
-
-       if (sp->state == sPassive || sp->state == sClosed || 
-           sp->state == sOpening) {
-           sp->state = sClosed;
-           DoClose(sp, errAborted, 0); /* Will remove CCB! */
-           return 0;
-       } else                  /* sClosing & sOpen */
-           sp->state = sClosing;
-       
-    }                          /* dspRemove */
-
-    if (pb->u.closeParams.abort || CheckOkToClose(sp)) /* going to close */
-    {
-       AbortIO(sp, errAborted);
-       sp->sendCtl = B_CTL_CLOSE; /* Send close advice */
-    }
-
-    pb->ioResult = 1;
-    if ( (mp = gbuf_copym(pb->mp)) ) { /* duplicate user request */
-           adspioc_ack(0, (gbuf_t *)pb->ioc, pb->gref); /* release user */
-           pb = (struct adspcmd *)gbuf_rptr(mp); /* get new parameter block */
-           pb->ioc = 0;
-           pb->mp = mp;
-           qAddToEnd((struct qlink **)&sp->opb, (struct qlink *)pb);   /* and save it */
-    } else {
-           pb->ioResult = 0;
-           adspioc_ack(0, (gbuf_t *)pb->ioc, pb->gref); /* release user, and keep no copy
-                                            * for kernel bookkeeping, yetch!
-                                            */
-    }
-    CheckSend(sp);
-
-    return 0;
-}
-
-static void qRemove(qptr, elem)
-    register CCBPtr qptr;
-    register CCBPtr elem;
-{
-
-    while(qptr->ccbLink) {
-       if ((DSPPBPtr)(qptr->ccbLink) == (DSPPBPtr)elem) {
-           qptr->ccbLink = elem->ccbLink;
-           elem->ccbLink = 0;
-           return;
-       }
-       qptr = qptr->ccbLink;
-    }
-}
-
-int RxClose(sp)
-    register CCBPtr sp;
-{
-    register gbuf_t *mp;
-    register struct adspcmd *pb;
-
-       if ((sp->state == sClosing) || (sp->state == sClosed))
-               return 0;
-       
-    sp->state = sClosed;
-    CheckReadQueue(sp);                /* try to deliver all remaining data */
-
-    if ( (mp = gbuf_alloc(sizeof(struct adspcmd), PRI_HI)) ) {
-        pb = (struct adspcmd *)gbuf_rptr(mp);
-       gbuf_wset(mp,sizeof(struct adspcmd));
-       pb->ioc = 0;
-       pb->mp = mp;
-
-       pb->csCode = dspClose;
-       pb->ioResult = 0;
-       completepb(sp, pb);             /* send close completion */
-    }
-
-if ((sp->userFlags & eClosed) == 0)
-    DoClose(sp, errAborted, -1);       /* abort send requests and timers */
-
-    return 0;
-}