/*
- * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
+ * Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
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;
atlock_t refall_lock;
-static void gref_wput(gref, m)
+caddr_t atp_free_cluster_list = 0;
+
+void gref_wput(gref, m)
gref_t *gref;
gbuf_t *m;
{
if ((*err = atalk_getref(0, fd, &gref, proc)) == 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
if ((*err = atalk_getref(0, fd, &gref, proc)) == 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;
}
int err;
gref_t *gref;
-
-
if ((err = atalk_closeref(fp, &gref)) == 0) {
thread_funnel_switch(KERNEL_FUNNEL, NETWORK_FUNNEL);
(void)gref_close(gref);
return 0;
} /* _ATrw */
-int _ATread(fp, uio, cred)
+int _ATread(fp, uio, cred, flags, p)
void *fp;
struct uio *uio;
void *cred;
+ int flags;
+ struct proc *p;
{
int stat;
return stat;
}
-int _ATwrite(fp, uio, cred)
+int _ATwrite(fp, uio, cred, flags, p)
void *fp;
struct uio *uio;
void *cred;
+ int flags;
+ struct proc *p;
{
int 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;
+ 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;
+ /* error if not for us */
+ if ((cmd & 0xffff) != 0xff99)
+ return EOPNOTSUPP;
- /* copy in ioc command info */
+ /* 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);
+ 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) {
+ if (fromKernel)
+ bcopy (arg, &ioccmd, sizeof (ioccmd_t));
+ else {
+ if ((err = copyin((caddr_t)arg, (caddr_t)&ioccmd, sizeof(ioccmd_t))) != 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(%x, %x, %d)\n", err,
+ (caddr_t)arg, (caddr_t)&ioccmd, sizeof(ioccmd_t));
#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 (ioccmd.ic_len) {
+ if ((gbuf_cont(m) = gbuf_alloc(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), ioccmd.ic_len); /* mbuf->m_len */
+ if (fromKernel)
+ bcopy (ioccmd.ic_dp, gbuf_rptr(gbuf_cont(m)), ioccmd.ic_len);
+ else {
+ 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 */
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 */
+ ATDISABLE(s, gref->lock);
+ while ((m = gref->ichead) == 0) {
+ gref->sevents |= POLLPRI;
#ifdef APPLETALK_DEBUG
kprintf("sleep gref = 0x%x\n", (unsigned)gref);
#endif
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) {
+ 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 (fromKernel)
+ bcopy (gbuf_rptr(mdata), &ioccmd.ic_dp[len], gbuf_len(mdata));
+ else {
+ if ((err = copyout((caddr_t)gbuf_rptr(mdata), (caddr_t)&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)&ioccmd.ic_dp[len], gbuf_len(mdata));
#endif
- goto l_done;
- }
- len += gbuf_len(mdata);
- }
- }
- if ((err = copyout((caddr_t)&ioccmd,
- (caddr_t)arg, sizeof(ioccmd_t))) != 0) {
+ goto l_done;
+ }
+ }
+ len += gbuf_len(mdata);
+ }
+ }
+
+ if (fromKernel)
+ bcopy (&ioccmd, arg, sizeof(ioccmd_t));
+ else {
+ 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));
+ kprintf("at_ioctl: error copyout2=%d from=%x to=%x len=%d\n",
+ err, &ioccmd, arg, sizeof(ioccmd_t));
#endif
- goto l_done;
- }
- }
+ goto l_done;
+ }
+ }
+ }
l_done:
gbuf_freem(m);
#endif
}
else
- err = at_ioctl(gref, cmd, arg);
+ err = at_ioctl(gref, cmd, arg, 0);
thread_funnel_switch(NETWORK_FUNNEL, KERNEL_FUNNEL);
return err;
}
-int _ATselect(fp, which, proc)
+int _ATselect(fp, which, wql, proc)
struct file *fp;
int which;
+ void * wql;
struct proc *proc;
{
int s, err, rc = 0;
rc = 1;
else {
gref->sevents |= POLLIN;
- selrecord(proc, &gref->si);
+ selrecord(proc, &gref->si, wql);
}
}
else if (which == POLLOUT) {
rc = 1;
else {
gref->sevents |= POLLOUT;
- selrecord(proc, &gref->si);
+ selrecord(proc, &gref->si, wql);
}
} else
rc = 1;
#ifdef APPLETALK_DEBUG
kprintf("wakeup gref = 0x%x\n", (unsigned)gref);
#endif
- thread_wakeup(&gref->iocevent);
+ wakeup(&gref->iocevent);
}
}
break;
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;
}
gref_t *gref;
{
if (gref->sevents & POLLSYNC)
- thread_wakeup(&gref->event);
+ wakeup(&gref->event);
}
void atalk_flush(gref)
/* 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);
}
}
}
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);
}
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;
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() */
{
- 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));
+ }
}
/*
{
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) {