]> git.saurik.com Git - apple/xnu.git/blobdiff - bsd/netat/sys_glue.c
xnu-792.22.5.tar.gz
[apple/xnu.git] / bsd / netat / sys_glue.c
index 9d0e956205b89039b43cc653003be0f0d262dbed..597835330f282f5182dd58efe77016428f40cf9e 100644 (file)
@@ -1,23 +1,29 @@
 /*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
  *
- * @APPLE_LICENSE_HEADER_START@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
- * The contents of this file constitute Original Code as defined in and
- * are subject to the Apple Public Source License Version 1.1 (the
- * "License").  You may not use this file except in compliance with the
- * License.  Please obtain a copy of the License at
- * http://www.apple.com/publicsource and read it before using this file.
+ * 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.
  * 
- * This Original Code and all software distributed under the License are
- * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * 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 OR NON-INFRINGEMENT.  Please see the
- * License for the specific language governing rights and limitations
- * under the License.
+ * 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_LICENSE_HEADER_END@
+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 /*
  *     Copyright (c) 1995 Apple Computer, Inc. 
 #include <sys/proc.h>
 #include <sys/filedesc.h>
 #include <sys/fcntl.h>
+#include <sys/file_internal.h>
 #include <sys/mbuf.h>
 #include <sys/ioctl.h>
 #include <sys/malloc.h>
+#include <kern/locks.h>
 #include <sys/socket.h>
 #include <sys/socketvar.h>
 #include <sys/ioccom.h>
+#include <sys/uio_internal.h>
 
 #include <sys/sysctl.h>
 
@@ -55,6 +64,7 @@
 #include <netat/debug.h>
 
 extern struct atpcb ddp_head;
+extern lck_mtx_t * atalk_mutex;
 
 extern void 
   ddp_putmsg(gref_t *gref, gbuf_t *m),
@@ -65,9 +75,13 @@ extern void
   aurp_wput(gref_t *gref, gbuf_t *m),
 #endif
   adsp_wput(gref_t *gref, gbuf_t *m);
+  
+int atp_free_cluster_timeout_set = 0;
+
 
 void atalk_putnext(gref_t *gref, gbuf_t *m);
-static int gref_close(gref_t *gref);
+/* bms:  make gref_close non static so its callable from kernel */
+int gref_close(gref_t *gref);
 
 SYSCTL_DECL(_net_appletalk);
 dbgBits_t dbgBits;
@@ -75,14 +89,18 @@ SYSCTL_STRUCT(_net_appletalk, OID_AUTO, debug, CTLFLAG_WR,
              &dbgBits, dbgBits, "AppleTalk Debug Flags");
 volatile int RouterMix = RT_MIX_DEFAULT; /* default for nbr of ppsec */
 SYSCTL_INT(_net_appletalk, OID_AUTO, routermix, CTLFLAG_WR, 
-          &RouterMix, 0, "Appletalk RouterMix");
+          (int *)&RouterMix, 0, "Appletalk RouterMix");
 at_ddp_stats_t at_ddp_stats;           /* DDP statistics */
 SYSCTL_STRUCT(_net_appletalk, OID_AUTO, ddpstats, CTLFLAG_RD,
              &at_ddp_stats, at_ddp_stats, "AppleTalk DDP Stats");
 
-atlock_t refall_lock;
+static void ioccmd_t_32_to_64( ioccmd_t *from_p, user_ioccmd_t *to_p );
+static void ioccmd_t_64_to_32( user_ioccmd_t *from_p, ioccmd_t *to_p );
+
 
-static void gref_wput(gref, m)
+caddr_t        atp_free_cluster_list = 0;
+
+void gref_wput(gref, m)
        gref_t *gref;
        gbuf_t *m;
 {
@@ -106,7 +124,7 @@ static void gref_wput(gref, m)
                        gbuf_freem(gbuf_cont(m));
                        gbuf_cont(m) = 0;
                        ((ioc_t *)gbuf_rptr(m))->ioc_rval = -1;
-                       ((ioc_t *)gbuf_rptr(m))->ioc_error = EPROTO;
+                       ((ioc_t *)gbuf_rptr(m))->ioc_error = EPROTOTYPE;
                        gbuf_set_type(m, MSG_IOCNAK);
                        atalk_putnext(gref, m);
                } else
@@ -134,7 +152,9 @@ int _ATsocket(proto, err, proc)
 
        case ATPROTO_ATP:
        case ATPROTO_ASP:
+#ifdef AURP_SUPPORT
        case ATPROTO_AURP:
+#endif
        case ATPROTO_ADSP:
                break;
        default:
@@ -153,7 +173,7 @@ int _ATsocket(proto, err, proc)
                return -1;
        }
        gref->proto = proto;
-       gref->pid = ((struct proc *)proc)->p_pid;
+       gref->pid = proc_pid((struct proc *)proc);
 
        /* open the specified protocol */
        switch (gref->proto) {
@@ -205,10 +225,10 @@ int _ATgetmsg(fd, ctlptr, datptr, flags, err, proc)
        int rc = -1;
        gref_t *gref;
 
-       if ((*err = atalk_getref(0, fd, &gref, proc)) == 0) {
+       if ((*err = atalk_getref(0, fd, &gref, proc, 1)) == 0) {
                switch (gref->proto) {
                case ATPROTO_ASP:
-                       rc = ASPgetmsg(gref, ctlptr, datptr, flags, err); 
+                       rc = ASPgetmsg(gref, ctlptr, datptr, NULL, flags, err); 
                        break;
                case ATPROTO_AURP:
 #ifdef AURP_SUPPORT
@@ -219,6 +239,7 @@ int _ATgetmsg(fd, ctlptr, datptr, flags, err, proc)
                        *err = EPROTONOSUPPORT; 
                        break;
                }
+               file_drop(fd);
        }
 
 /*     kprintf("_ATgetmsg: return=%d\n", *err);*/
@@ -236,78 +257,73 @@ int _ATputmsg(fd, ctlptr, datptr, flags, err, proc)
        int rc = -1;
        gref_t *gref;
 
-       if ((*err = atalk_getref(0, fd, &gref, proc)) == 0) {
+       if ((*err = atalk_getref(0, fd, &gref, proc, 1)) == 0) {
                switch (gref->proto) {
                case ATPROTO_ASP:
-                       rc = ASPputmsg(gref, ctlptr, datptr, flags, err); break;
+                       rc = ASPputmsg(gref, ctlptr, datptr, NULL, flags, err); break;
                default:
                        *err = EPROTONOSUPPORT; break;
                }
+               file_drop(fd);
        }
 
 /*     kprintf("_ATputmsg: return=%d\n", *err); */
        return rc;
 }
 
-int _ATclose(fp, proc)
-       struct file *fp;
+int _ATclose(fg, proc)
+       struct fileglob *fg;
        struct proc *proc;
 {
        int err;
        gref_t *gref;
 
-
-
-       if ((err = atalk_closeref(fp, &gref)) == 0) {
-            thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
+       if ((err = atalk_closeref(fg, &gref)) == 0) {
+               atalk_lock();
             (void)gref_close(gref);
-            thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
+               atalk_unlock();
        }
 
        return err;
 }
 
-int _ATrw(fp, rw, uio, ext)
+int _ATrw(fp, rw, uio, p)
      void *fp;
      enum uio_rw rw;
      struct uio *uio;
-     int ext;
+     struct proc *p;
 {
-    int s, err, len, clen = 0, res;
+    int err, len, clen = 0, res;
     gref_t *gref;
     gbuf_t *m, *mhead, *mprev;
 
-    if ((err = atalk_getref(fp, 0, &gref, 0)) != 0)
+       /* no need to get/drop iocount as the fp already has one */
+    if ((err = atalk_getref_locked(fp, 0, &gref, p, 1)) != 0)
        return err;
 
-    if ((len = uio->uio_resid) == 0)
+       // LP64todo - fix this!
+    if ((len = uio_resid(uio)) == 0)
        return 0;
 
-    ATDISABLE(s, gref->lock);
 
     if (rw == UIO_READ) {
        KERNEL_DEBUG(DBG_ADSP_ATRW, 0, gref, len, gref->rdhead, 0);
        while ((gref->errno == 0) && ((mhead = gref->rdhead) == 0)) {
                gref->sevents |= POLLMSG;
-               err = tsleep(&gref->event, PSOCK | PCATCH, "AT read", 0);
+               err = msleep(&gref->event, atalk_mutex, PSOCK | PCATCH, "AT read", 0);
                gref->sevents &= ~POLLMSG;
-               if (err != 0) {
-                       ATENABLE(s, gref->lock);
+               if (err != 0)
                        return err;
-               }
                KERNEL_DEBUG(DBG_ADSP_ATRW, 1, gref, gref->rdhead, mhead, gbuf_next(mhead));
        }
 
-       if (gref->errno) {
-               ATENABLE(s, gref->lock);
+       if (gref->errno)
                return EPIPE;
-       }
        if ((gref->rdhead = gbuf_next(mhead)) == 0)
                gref->rdtail = 0;
 
        KERNEL_DEBUG(DBG_ADSP_ATRW, 2, gref, gref->rdhead, mhead, gbuf_next(mhead));
 
-       ATENABLE(s, gref->lock);
 
 //##### LD TEST 08/05
 //     simple_lock(&gref->lock);
@@ -339,12 +355,10 @@ int _ATrw(fp, rw, uio, ext)
                        gbuf_cont(mprev) = 0;
                else
                        mhead = 0;
-               ATDISABLE(s, gref->lock);
                if (gref->rdhead == 0)
                        gref->rdtail = m;
                gbuf_next(m) = gref->rdhead;
                gref->rdhead = m;
-               ATENABLE(s, gref->lock);
        }
        if (mhead)
                gbuf_freem(mhead);
@@ -355,16 +369,13 @@ int _ATrw(fp, rw, uio, ext)
                while (!(*gref->writeable)(gref)) {
                        /* flow control on, wait to be enabled to write */ 
                        gref->sevents |= POLLSYNC;
-                       err = tsleep(&gref->event, PSOCK | PCATCH, "AT write", 0);
+                       err = msleep(&gref->event, atalk_mutex, PSOCK | PCATCH, "AT write", 0);
                        gref->sevents &= ~POLLSYNC;
-                       if (err != 0) {
-                               ATENABLE(s, gref->lock);
+                       if (err != 0)
                                return err;
-                       }
                }
        }
 
-       ATENABLE(s, gref->lock);
 
        /* allocate a buffer to copy in the write data */
        if ((m = gbuf_alloc(AT_WR_OFFSET+len, PRI_MED)) == 0)
@@ -389,106 +400,130 @@ int _ATrw(fp, rw, uio, ext)
   return 0;
 } /* _ATrw */
 
-int _ATread(fp, uio, cred)
-       void *fp;
+int _ATread(fp, uio, cred, flags, p)
+       struct fileproc *fp;
        struct uio *uio;
        void *cred;
+       int flags;
+       struct proc *p;
 {
      int stat;
 
-       thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
-       stat = _ATrw(fp, UIO_READ, uio, 0);
-       thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
+       atalk_lock();
+       stat = _ATrw(fp, UIO_READ, uio, p);
+       atalk_unlock();
        return stat;
 }
 
-int _ATwrite(fp, uio, cred)
-       void *fp;
+int _ATwrite(fp, uio, cred, flags, p)
+       struct fileproc *fp;
        struct uio *uio;
        void *cred;
+       int flags;
+       struct proc *p;
 {
      int stat;
 
-
-       thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
-       stat = _ATrw(fp, UIO_WRITE, uio, 0);
-       thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
+       atalk_lock();
+       stat = _ATrw(fp, UIO_WRITE, uio, p);
+       atalk_unlock();
 
        return stat;
 }
 
 /* Most of the processing from _ATioctl, so that it can be called
    from the new ioctl code */
-int at_ioctl(gref, cmd, arg)
-     gref_t *gref;
-     register caddr_t arg;
+/* bms:  update to be callable from kernel */
+int at_ioctl(gref_t *gref, u_long cmd, caddr_t arg, int fromKernel)
 {
-       int s, err = 0, len;
-       gbuf_t *m, *mdata;
-       ioc_t *ioc;
-       ioccmd_t ioccmd;
-
-       /* error if not for us */
-       if ((cmd  & 0xffff) != 0xff99)
-               return EOPNOTSUPP;
-
-       /* copy in ioc command info */
-/*
-       kprintf("at_ioctl: arg ioccmd.ic_cmd=%x ic_len=%x gref->lock=%x, gref->event=%x\n",
-               ((ioccmd_t *)arg)->ic_cmd, ((ioccmd_t *)arg)->ic_len, 
-               gref->lock, gref->event);
-*/
-       if ((err = copyin((caddr_t)arg,
-                       (caddr_t)&ioccmd, sizeof(ioccmd_t))) != 0) { 
+    int err = 0, len;
+    u_int size;
+    gbuf_t *m, *mdata;
+    ioc_t *ioc;
+    user_addr_t user_arg;
+    user_ioccmd_t user_ioccmd;
+       boolean_t is64bit;
+
+    /* error if not for us */
+    if ((cmd  & 0xffff) != 0xff99)
+        return EOPNOTSUPP;
+
+       size = IOCPARM_LEN(cmd);
+       if (size != sizeof(user_addr_t))
+               return EINVAL;
+               
+       user_arg = *((user_addr_t *)arg);
+
+    /* copy in ioc command info */
+    is64bit = proc_is64bit(current_proc());
+    if (fromKernel) {
+       ioccmd_t        tmp;
+        bcopy (CAST_DOWN(caddr_t, user_arg), &tmp, sizeof (tmp));
+        ioccmd_t_32_to_64(&tmp, &user_ioccmd);
+    }
+    else {
+               if (is64bit) {
+                       err = copyin(user_arg, (caddr_t)&user_ioccmd, sizeof(user_ioccmd));
+       }
+       else {
+               ioccmd_t        tmp;
+                       err = copyin(user_arg, (caddr_t)&tmp, sizeof(tmp));
+               ioccmd_t_32_to_64(&tmp, &user_ioccmd);
+       }
+       if (err != 0) { 
 #ifdef APPLETALK_DEBUG
-         kprintf("at_ioctl: err = %d, copyin(%x, %x, %d)\n", err, 
-                 (caddr_t)arg, (caddr_t)&ioccmd, sizeof(ioccmd_t));
+                       kprintf("at_ioctl: err = %d, copyin(%llx, %x, %d)\n", err, 
+                       user_arg, (caddr_t)&user_ioccmd, sizeof(user_ioccmd));
 #endif
-               return err;
-       } 
-
-       /* allocate a buffer to create an ioc command */
-       if ((m = gbuf_alloc(sizeof(ioc_t), PRI_HI)) == 0)
-               return ENOBUFS;
-       gbuf_wset(m,sizeof(ioc_t));
-       gbuf_set_type(m, MSG_IOCTL);
-
-       /* create the ioc command */
-       if (ioccmd.ic_len) {
-               if ((gbuf_cont(m) = gbuf_alloc(ioccmd.ic_len, PRI_HI)) == 0) {
-                       gbuf_freem(m);
+            return err;
+        } 
+    }
+
+    /* allocate a buffer to create an ioc command
+       first mbuf contains ioc command */
+    if ((m = gbuf_alloc(sizeof(ioc_t), PRI_HI)) == 0)
+        return ENOBUFS;
+    gbuf_wset(m, sizeof(ioc_t));    /* mbuf->m_len */
+    gbuf_set_type(m, MSG_IOCTL);    /* mbuf->m_type */
+
+    /* create the ioc command 
+       second mbuf contains the actual ASP command */
+    if (user_ioccmd.ic_len) {
+        if ((gbuf_cont(m) = gbuf_alloc(user_ioccmd.ic_len, PRI_HI)) == 0) {
+            gbuf_freem(m);
 #ifdef APPLETALK_DEBUG
                        kprintf("at_ioctl: gbuf_alloc err=%d\n",ENOBUFS);
 #endif
-                       return ENOBUFS;
-               }
-               gbuf_wset(gbuf_cont(m),ioccmd.ic_len);
-               if ((err = copyin((caddr_t)ioccmd.ic_dp,
-                               (caddr_t)gbuf_rptr(gbuf_cont(m)), ioccmd.ic_len)) != 0) { 
-                       gbuf_freem(m);
-                       return err;
-               }
-       }
-       ioc = (ioc_t *)gbuf_rptr(m);
-       ioc->ioc_cmd = ioccmd.ic_cmd;
-       ioc->ioc_count = ioccmd.ic_len;
-       ioc->ioc_error = 0;
-       ioc->ioc_rval = 0;
-
-       /* send the ioc command to the appropriate recipient */
+            return ENOBUFS;
+        }
+        gbuf_wset(gbuf_cont(m), user_ioccmd.ic_len);     /* mbuf->m_len */
+        if (fromKernel)
+            bcopy (CAST_DOWN(caddr_t, user_ioccmd.ic_dp), gbuf_rptr(gbuf_cont(m)), user_ioccmd.ic_len);
+        else {
+            if ((err = copyin(user_ioccmd.ic_dp, (caddr_t)gbuf_rptr(gbuf_cont(m)), user_ioccmd.ic_len)) != 0) { 
+                gbuf_freem(m);
+                return err;
+            }
+        }
+    }
+    ioc = (ioc_t *) gbuf_rptr(m);
+    ioc->ioc_cmd = user_ioccmd.ic_cmd;
+    ioc->ioc_count = user_ioccmd.ic_len;
+    ioc->ioc_error = 0;
+    ioc->ioc_rval = 0;
+
+    /* send the ioc command to the appropriate recipient */
        gref_wput(gref, m);
 
-       /* wait for the ioc ack */
-       ATDISABLE(s, gref->lock);
-       while ((m = gref->ichead) == 0) {
-               gref->sevents |= POLLPRI;
+    /* wait for the ioc ack */
+    while ((m = gref->ichead) == 0) {
+        gref->sevents |= POLLPRI;
 #ifdef APPLETALK_DEBUG
                kprintf("sleep gref = 0x%x\n", (unsigned)gref);
 #endif
-               err = tsleep(&gref->iocevent, PSOCK | PCATCH, "AT ioctl", 0);
+               err = msleep(&gref->iocevent, atalk_mutex, PSOCK | PCATCH, "AT ioctl", 0);
                gref->sevents &= ~POLLPRI;
                if (err != 0) {
-                       ATENABLE(s, gref->lock);
 #ifdef APPLETALK_DEBUG
                        kprintf("at_ioctl: EINTR\n");
 #endif
@@ -502,42 +537,55 @@ int at_ioctl(gref, cmd, arg)
 
        gref->ichead = gbuf_next(m);
 
-       ATENABLE(s, gref->lock);
 
 #ifdef APPLETALK_DEBUG
        kprintf("at_ioctl: woke up from ioc sleep gref = 0x%x\n", 
                (unsigned)gref);
 #endif
-       /* process the ioc response */
-       ioc = (ioc_t *)gbuf_rptr(m);
-       if ((err = ioc->ioc_error) == 0) {
-               ioccmd.ic_timout = ioc->ioc_rval;
-               ioccmd.ic_len = 0;
-               mdata = gbuf_cont(m);
-               if (mdata && ioccmd.ic_dp) {
-                       ioccmd.ic_len = gbuf_msgsize(mdata);
-                 for (len=0; mdata; mdata=gbuf_cont(mdata)) {
-                       if ((err = copyout((caddr_t)gbuf_rptr(mdata),
-                                       (caddr_t)&ioccmd.ic_dp[len], gbuf_len(mdata))) < 0) {
+
+    /* process the ioc response */
+    ioc = (ioc_t *) gbuf_rptr(m);
+    if ((err = ioc->ioc_error) == 0) {
+        user_ioccmd.ic_timout = ioc->ioc_rval;
+        user_ioccmd.ic_len = 0;
+        mdata = gbuf_cont(m);
+        if (mdata && user_ioccmd.ic_dp) {
+            user_ioccmd.ic_len = gbuf_msgsize(mdata);
+            for (len = 0; mdata; mdata = gbuf_cont(mdata)) {
+                if (fromKernel)
+                    bcopy (gbuf_rptr(mdata), CAST_DOWN(caddr_t, (user_ioccmd.ic_dp + len)), gbuf_len(mdata));
+                else {
+                    if ((err = copyout((caddr_t)gbuf_rptr(mdata), (user_ioccmd.ic_dp + len), gbuf_len(mdata))) < 0) {
 #ifdef APPLETALK_DEBUG
-                               kprintf("at_ioctl: len=%d error copyout=%d from=%x to=%x gbuf_len=%x\n",
-                                        len, err, (caddr_t)gbuf_rptr(mdata), 
-                                        (caddr_t)&ioccmd.ic_dp[len], gbuf_len(mdata));
+                                               kprintf("at_ioctl: len=%d error copyout=%d from=%x to=%x gbuf_len=%x\n",
+                                                               len, err, (caddr_t)gbuf_rptr(mdata), (caddr_t)&user_ioccmd.ic_dp[len], gbuf_len(mdata));
 #endif
-                               goto l_done;
+                        goto l_done;
+                    }
+                }
+                len += gbuf_len(mdata);
+            }
+        }
+        
+        if (fromKernel) {
+                       ioccmd_t        tmp;
+                       ioccmd_t_64_to_32(&user_ioccmd, &tmp);
+                       bcopy (&tmp, CAST_DOWN(caddr_t, user_arg), sizeof(tmp));
+        }
+        else {
+                       if (is64bit) {
+                               err = copyout((caddr_t)&user_ioccmd, user_arg, sizeof(user_ioccmd));
                        }
-                       len += gbuf_len(mdata);
-                 }
-               }
-               if ((err = copyout((caddr_t)&ioccmd,
-                               (caddr_t)arg, sizeof(ioccmd_t))) != 0) {
-#ifdef APPLETALK_DEBUG
-                               kprintf("at_ioctl: error copyout2=%d from=%x to=%x len=%d\n",
-                                        err, &ioccmd, arg, sizeof(ioccmd_t));
-#endif
-                       goto l_done;
-               }
-       }
+                       else {
+                               ioccmd_t        tmp;
+                               ioccmd_t_64_to_32(&user_ioccmd, &tmp);
+                               err = copyout((caddr_t)&tmp, user_arg, sizeof(tmp));
+                       }
+            if (err != 0) {
+                goto l_done;
+            }
+        }
+    }
 
 l_done:
        gbuf_freem(m);
@@ -554,42 +602,51 @@ int _ATioctl(fp, cmd, arg, proc)
        int err;
        gref_t *gref;
 
-       thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
-       if ((err = atalk_getref(fp, 0, &gref, 0)) != 0) {
+       atalk_lock();
+       /* No need to get a reference on fp as it already has one */
+       if ((err = atalk_getref_locked(fp, 0, &gref, 0, 0)) != 0) {
 #ifdef APPLETALK_DEBUG
                kprintf("_ATioctl: atalk_getref err = %d\n", err);
 #endif
        }
        else
-            err = at_ioctl(gref, cmd, arg);
+            err = at_ioctl(gref, cmd, arg, 0);
 
-       thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
+       atalk_unlock();
 
        return err;
 }
 
-int _ATselect(fp, which, proc)
-       struct file *fp;
+int _ATselect(fp, which, wql, proc)
+       struct fileproc *fp;
        int which;
+       void * wql;
        struct proc *proc;
 {
-       int s, err, rc = 0;
+       int err, rc = 0;
        gref_t *gref;
 
-       thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
-       err = atalk_getref(fp, 0, &gref, 0);
-       thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
+       /* Radar 4128949: Drop the proc_fd lock here to avoid lock inversion issues with the other AT calls
+      * select() is already holding a reference on the fd, so it won't go away during the time it is unlocked.
+      */
+       proc_fdunlock(proc);
+
+       atalk_lock();
+       /* no need to drop the iocount as select covers that */
+       err = atalk_getref_locked(fp, 0, &gref, 0, 0);
+       atalk_unlock();
 
+       /* Safe to re-grab the proc_fdlock at that point */
+       proc_fdlock(proc);
        if (err != 0)
                rc = 1;
        else {
-            ATDISABLE(s, gref->lock);
             if (which == FREAD) {
                  if (gref->rdhead || (gref->readable && (*gref->readable)(gref)))
                       rc = 1;
                  else {
                       gref->sevents |= POLLIN;
-                      selrecord(proc, &gref->si);
+                      selrecord(proc, &gref->si, wql);
                  }
             }
             else if (which == POLLOUT) {
@@ -598,24 +655,29 @@ int _ATselect(fp, which, proc)
                            rc = 1;
                       else {
                            gref->sevents |= POLLOUT;
-                           selrecord(proc, &gref->si);
+                           selrecord(proc, &gref->si, wql);
                       }
                  } else
                       rc = 1;
             }
-            ATENABLE(s, gref->lock);
        }
 
        return rc;
 }
 
+int _ATkqfilter(fp, kn, p)
+       struct fileproc *fp;
+       struct knote *kn;
+       struct proc *p;
+{
+       return (EOPNOTSUPP);
+}
+
 void atalk_putnext(gref, m)
        gref_t *gref;
        gbuf_t *m;
 {
-       int s;
 
-       ATDISABLE(s, gref->lock);
 
        /* *** potential leak? *** */
        gbuf_next(m) = 0;
@@ -631,7 +693,7 @@ void atalk_putnext(gref, m)
 #ifdef APPLETALK_DEBUG
                                kprintf("wakeup gref = 0x%x\n", (unsigned)gref);
 #endif
-                               thread_wakeup(&gref->iocevent);
+                               wakeup(&gref->iocevent);
                        }
                }
                break;
@@ -650,34 +712,29 @@ void atalk_putnext(gref, m)
                        gref->rdhead = m;
                        if (gref->sevents & POLLMSG) {
                                gref->sevents &= ~POLLMSG;
-                               thread_wakeup(&gref->event);
+                               wakeup(&gref->event);
                        }
                        if (gref->sevents & POLLIN) {
                                gref->sevents &= ~POLLIN;
-                               thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
                                selwakeup(&gref->si);
-                               thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
                        }
                        gref->rdtail = m;
                    }
        } /* switch gbuf_type(m) */
 
-       ATENABLE(s, gref->lock);
 } /* atalk_putnext */
 
 void atalk_enablew(gref)
        gref_t *gref;
 {
        if (gref->sevents & POLLSYNC)
-               thread_wakeup(&gref->event);
+               wakeup(&gref->event);
 }
 
 void atalk_flush(gref)
        gref_t *gref;
 {
-       int s;
 
-       ATDISABLE(s, gref->lock);
        if (gref->rdhead) {
                gbuf_freel(gref->rdhead);
                gref->rdhead = 0;
@@ -686,7 +743,6 @@ void atalk_flush(gref)
                gbuf_freel(gref->ichead);
                gref->ichead = 0;
        }
-       ATENABLE(s, gref->lock);
 }
 
 /*
@@ -697,8 +753,6 @@ void atalk_notify(gref, errno)
        register gref_t *gref;
        int errno;
 {
-       int s;
-       ATDISABLE(s, gref->lock);
 
        if (gref->atpcb_socket) {
            /* For DDP --
@@ -720,48 +774,38 @@ void atalk_notify(gref, errno)
                /* blocked read */
                if (gref->sevents & POLLMSG) {
                        gref->sevents &= ~POLLMSG;
-                       thread_wakeup(&gref->event);
+                       wakeup(&gref->event);
                }
                /* select */
                if (gref->sevents & POLLIN) {
                        gref->sevents &= ~POLLIN;
-                       thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
                        selwakeup(&gref->si);
-                       thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
                }
            }
        }
-       ATENABLE(s, gref->lock);
 } /* atalk_notify */
 
 void atalk_notify_sel(gref)
        gref_t *gref;
 {
-       int s;
 
-       ATDISABLE(s, gref->lock);
        if (gref->sevents & POLLIN) {
                gref->sevents &= ~POLLIN;
-               thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
                selwakeup(&gref->si);
-               thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
        }
-       ATENABLE(s, gref->lock);
 }
 
 int atalk_peek(gref, event)
        gref_t *gref;
        unsigned char *event;
 {
-       int s, rc;
+       int rc;
 
-       ATDISABLE(s, gref->lock);
        if (gref->rdhead) {
                *event = *gbuf_rptr(gref->rdhead);
                rc = 0;
        } else
                rc = -1;
-       ATENABLE(s, gref->lock);
 
        return rc;
 }
@@ -807,15 +851,13 @@ int gref_alloc(grefp)
        gref_t **grefp;
 {
        extern gbuf_t *atp_resource_m;
-       int i, s;
+       int i;
        gbuf_t *m;
        gref_t *gref, *gref_array;
 
        *grefp = (gref_t *)NULL;
 
-       ATDISABLE(s, refall_lock);
        if (gref_free_list == 0) {
-               ATENABLE(s, refall_lock);
 #ifdef APPLETALK_DEBUG
                kprintf("gref_alloc: gbufalloc size=%d\n", GREF_PER_BLK*sizeof(gref_t));
 #endif
@@ -825,7 +867,6 @@ int gref_alloc(grefp)
                gref_array = (gref_t *)gbuf_rptr(m);
                for (i=0; i < GREF_PER_BLK-1; i++)
                        gref_array[i].atpcb_next = (gref_t *)&gref_array[i+1];
-               ATDISABLE(s, refall_lock);
                gbuf_cont(m) = atp_resource_m;
                atp_resource_m = m;
                gref_array[i].atpcb_next = gref_free_list;
@@ -834,10 +875,6 @@ int gref_alloc(grefp)
 
        gref = gref_free_list;
        gref_free_list = gref->atpcb_next;
-       ATENABLE(s, refall_lock);
-       ATLOCKINIT(gref->lock);
-//### LD Test 08/05/98
-//     simple_lock_init(&gref->lock);
        ATEVENTINIT(gref->event);
        ATEVENTINIT(gref->iocevent);
 
@@ -848,10 +885,10 @@ int gref_alloc(grefp)
        return 0;
 } /* gref_alloc */
 
-static int gref_close(gref)
-       gref_t *gref;
+/* bms:  make gref_close callable from kernel */
+int gref_close(gref_t *gref)
 {
-       int s, rc;
+       int rc;
 
        switch (gref->proto) {
 
@@ -879,11 +916,9 @@ static int gref_close(gref)
                selthreadclear(&gref->si);
 
                /* from original gref_free() */
-               ATDISABLE(s, refall_lock);
                bzero((char *)gref, sizeof(gref_t));
                gref->atpcb_next = gref_free_list;
                gref_free_list = gref;
-               ATENABLE(s, refall_lock);
        }
 
        return rc;
@@ -905,9 +940,9 @@ static int gref_close(gref)
 
 struct mbuf *m_clattach(extbuf, extfree, extsize, extarg, wait)
        caddr_t extbuf; 
-       int (*extfree)();
-       int extsize;
-       int extarg;
+       void (*extfree)(caddr_t , u_int, caddr_t);
+       u_int extsize;
+       caddr_t extarg;
        int wait;
 {
         struct mbuf *m;
@@ -920,23 +955,70 @@ struct mbuf *m_clattach(extbuf, extfree, extsize, extarg, wait)
         m->m_ext.ext_size = extsize;
         m->m_ext.ext_arg = extarg;
         m->m_ext.ext_refs.forward = 
-         m->m_ext.ext_refs.backward = &m->m_ext.ext_refs;
+               m->m_ext.ext_refs.backward = &m->m_ext.ext_refs;
         m->m_data = extbuf;
         m->m_flags |= M_EXT;
 
         return (m);
 }
 
+
+
+/*
+       temp fix for bug 2731148  - until this code is re-written to use standard clusters
+       Deletes any free clusters on the free list.
+*/
+void atp_delete_free_clusters()
+{
+       caddr_t cluster;
+       caddr_t cluster_list;
+       
+       
+       /* check for free clusters on the free_cluster_list to be deleted */
+       MBUF_LOCK();    /* lock used by mbuf routines */
+
+               untimeout(&atp_delete_free_clusters, NULL);
+               atp_free_cluster_timeout_set = 0;
+
+               cluster_list = atp_free_cluster_list;
+               atp_free_cluster_list = 0;
+               
+       MBUF_UNLOCK();
+       
+       while (cluster = cluster_list)
+       {
+               cluster_list = *((caddr_t*)cluster);
+               FREE(cluster, M_MCLUST);
+       }
+       
+}
+
+
 /* 
    Used as the "free" routine for over-size clusters allocated using
-   m_lgbuf_alloc(). 
+   m_lgbuf_alloc(). Called by m_free while under MBUF_LOCK.
 */
 
 void m_lgbuf_free(buf, size, arg)
-     void *buf;
-     int size, arg; /* not needed, but they're in m_free() */
+     caddr_t buf;
+     u_int size;
+     caddr_t arg; /* not needed, but they're in m_free() */
 {
-       FREE(buf, M_MCLUST);
+       /* FREE(buf, M_MCLUST); - can't free here - called from m_free while under lock */
+       
+       /* move to free_cluster_list to be deleted later */
+       caddr_t cluster = (caddr_t)buf;
+       
+       /* don't need a lock because this is only called called from m_free which */
+       /* is under MBUF_LOCK */
+       *((caddr_t*)cluster) = atp_free_cluster_list;
+       atp_free_cluster_list = cluster;
+       
+       if (atp_free_cluster_timeout_set == 0)
+       {
+               atp_free_cluster_timeout_set = 1;
+               timeout(&atp_delete_free_clusters, NULL, (1 * HZ));
+       }
 }
 
 /*
@@ -949,6 +1031,9 @@ struct mbuf *m_lgbuf_alloc(size, wait)
 {
        struct mbuf *m;
 
+       if (atp_free_cluster_list)
+               atp_delete_free_clusters();     /* delete any free clusters on the free list */
+       
        /* If size is too large, allocate a cluster, otherwise, use the
           standard mbuf allocation routines.*/
        if (size > MCLBYTES) {
@@ -961,7 +1046,7 @@ struct mbuf *m_lgbuf_alloc(size, wait)
                if (NULL == 
                    (m = m_clattach(buf, m_lgbuf_free, size, 0, 
                                    (wait)? M_WAIT: M_DONTWAIT))) {
-                       m_lgbuf_free(buf);
+                       m_lgbuf_free(buf, 0, 0);
                        return(NULL);
                }
        } else {
@@ -1242,3 +1327,20 @@ void ioc_ack(errno, m, gref)
        atalk_putnext(gref, m);
 }
 
+
+static void ioccmd_t_32_to_64( ioccmd_t *from_p, user_ioccmd_t *to_p )
+{
+       to_p->ic_cmd = from_p->ic_cmd;
+       to_p->ic_timout = from_p->ic_timout;
+       to_p->ic_len = from_p->ic_len;
+       to_p->ic_dp = CAST_USER_ADDR_T(from_p->ic_dp);
+}
+
+
+static void ioccmd_t_64_to_32( user_ioccmd_t *from_p, ioccmd_t *to_p )
+{
+       to_p->ic_cmd = from_p->ic_cmd;
+       to_p->ic_timout = from_p->ic_timout;
+       to_p->ic_len = from_p->ic_len;
+       to_p->ic_dp = CAST_DOWN(caddr_t, from_p->ic_dp);
+}