File:  [Apple Darwin 0.x] / kernel / bsd / netat / sys_dep.c.good
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:26:01 2018 UTC (8 years, 2 months ago) by root
Branches: MAIN, Apple
CVS tags: HEAD, Darwin03, Darwin01
Darwin 0.1 Mach+BSD kernel

/*
 *	Copyright (c) 1995 Apple Computer, Inc. 
 *
 *	The information contained herein is subject to change without
 *	notice and  should not be  construed as a commitment by Apple
 *	Computer, Inc. Apple Computer, Inc. assumes no responsibility
 *	for any errors that may appear.
 *
 *	Confidential and Proprietary to Apple Computer, Inc.
 *
 */
#include <h/sysglue.h>
#include <h/debug.h>
#include <sys/malloc.h>
#ifdef _AIX
	#include <sys/device.h>
#else
#include <sys/file.h>
#endif

int (*sys_ATsocket)() = 0;
int (*sys_ATgetmsg)() = 0;
int (*sys_ATputmsg)() = 0;
int (*sys_ATPsndreq)() = 0;
int (*sys_ATPsndrsp)() = 0;
int (*sys_ATPgetreq)() = 0;
int (*sys_ATPgetrsp)() = 0;

#ifndef _AIX

int ATsocket(proc, uap, retval)
	void *proc;
	struct {
	int proto;
	} *uap;
	int *retval;
{
	int err;

	if (sys_ATsocket)
		*retval = (*sys_ATsocket)(uap->proto, &err, proc);
	else {
		*retval = -1;
		err = ENXIO;
	}
	return err;
}

int ATgetmsg(proc, uap, retval)
	void *proc;
	struct {
	int fd;
	void *ctlptr;
	void *datptr;
	int *flags;
	} *uap;
	int *retval;
{
	int err;

	if (sys_ATgetmsg)
		*retval = (*sys_ATgetmsg)(uap->fd,
			uap->ctlptr, uap->datptr, uap->flags, &err, proc);
	else {
		*retval = -1;
		err = ENXIO;
	}
	return err;
}

int ATputmsg(proc, uap, retval)
	void *proc;
	struct {
	int fd;
	void *ctlptr;
	void *datptr;
	int flags;
	} *uap;
	int *retval;
{
	int err;

	if (sys_ATputmsg)
		*retval = (*sys_ATputmsg)(uap->fd,
			uap->ctlptr, uap->datptr, uap->flags, &err, proc);
	else {
		*retval = -1;
		err = ENXIO;
	}
	return err;
}

int ATPsndreq(proc, uap, retval)
	void *proc;
	struct {
	int fd;
	unsigned char *buf;
	int len;
	int nowait;
	} *uap;
	int *retval;
{
	int err;

	if (sys_ATPsndreq)
		*retval = (*sys_ATPsndreq)(uap->fd,
			uap->buf, uap->len, uap->nowait, &err, proc);
	else {
		*retval = -1;
		err= ENXIO;
	}
	return err;
}

int ATPsndrsp(proc, uap, retval)
	void *proc;
	struct {
	int fd;
	unsigned char *respbuff;
	int resplen;
	int datalen;
	} *uap;
	int *retval;
{
	int err;

	if (sys_ATPsndrsp)
		*retval = (*sys_ATPsndrsp)(uap->fd,
			uap->respbuff, uap->resplen, uap->datalen, &err, proc);
	else {
		*retval = -1;
		err = ENXIO;
	}
	return err;
}

int ATPgetreq(proc, uap, retval)
	void *proc;
	struct {
	int fd;
	unsigned char *buf;
	int buflen;
	} *uap;
	int *retval;
{
	int err;

	if (sys_ATPgetreq)
		*retval = (*sys_ATPgetreq)(uap->fd,
			uap->buf, uap->buflen, &err, proc);
	else {
		*retval = -1;
		err = ENXIO;
	}
	return err;
}

int ATPgetrsp(proc, uap, retval)
	void *proc;
	struct {
	int fd;
	unsigned char *bdsp;
	} *uap;
	int *retval;
{
	int err;

	if (sys_ATPgetrsp)
		*retval = (*sys_ATPgetrsp)(uap->fd, uap->bdsp, &err, proc);
	else {
		*retval = -1;
		err = ENXIO;
	}
	return err;
}

void *atalk_kalloc(size)
	int size;
{
	int *buf;

	buf = (int *)kalloc(sizeof(int)+size);
	*buf++ = size;
	return (void *)buf;
}

void atalk_kfree(buf)
	int *buf;
{
	int size;

	size = *(--buf);
	kfree((void *)buf, sizeof(int)+size);
}

int atalk_closeref(fp, grefp)
	struct file *fp;
	gref_t **grefp;
{
	*grefp = (gref_t *)fp->f_data;
	fp->f_data = 0;
	return 0;
}

int atalk_openref(gref, retfd, proc)
	gref_t *gref;
	int *retfd;
	struct proc *proc;
{
extern int _ATread(), _ATwrite(),_ATioctl(), _ATselect(), _ATclose();
static struct fileops fileops = {_ATread, _ATwrite, _ATioctl, _ATselect, _ATclose};
	int err, fd;
	struct file *fp;

	if ((err = falloc(proc, &fp, &fd)) != 0)
		return err;
	fp->f_flag = FREAD|FWRITE;
/*##### LD 5/7/96 Warning: we don't have a "DTYPE_OTHER" for
 * Rhapsody, so defines DTYPE_ATALK as DTYPE_SOCKET...
 */
	fp->f_type = DTYPE_ATALK+1;
	fp->f_ops = &fileops;
	*retfd = fd;
	fp->f_data = (void *)gref;
	gref->next = (void *)fp;
	return 0;
}

int atalk_getref(fp, fd, grefp, proc)
	struct file *fp;
	int fd;
	gref_t **grefp;
	struct proc *proc;
{
	if (fp == 0) {
		struct filedesc *fdp = proc->p_fd;
		int nfds = fdp->fd_nfiles;
		if ((fd < 0) || (fd > nfds) || ((fp = fdp->fd_ofiles[fd]) == 0)) {
			*grefp = (gref_t *)0;
			return EBADF;
		}
	}
	if ((*grefp = (gref_t *)fp->f_data) == 0)
		return EBADF;
	return 0;
}

gbuf_t *gbuf_alloc(size, pri)
	int size;
	int pri;
{
	gbuf_t *m;
/*
 * ### LD 5/12/97 Allocate only a mbuf if size is ok,
 *     otherwise add a cluster.
 */
	m = (gbuf_t *)m_gethdr(M_DONTWAIT, MSG_DATA);
	if (size > MCLBYTES) {
		kprintf("gbuf_alloc: size=%d larger than cluster size\n", size);
		panic("gbuf_alloc: size bigger than cluster size");
		m_free(m);
		return NULL;
	}	
	if (m && (size > MHLEN))
		MCLGET(m, M_DONTWAIT);
	gbuf_next(m) = 0;
	gbuf_cont(m) = 0;
	gbuf_wset(m,0);
	return m;
}

void gbuf_freeb(m)
	gbuf_t *m;
{
	if (m) {
		m_free(m);
	}
}

/*
 * LD 5/12/97 Added for Rhapsody, defines a m_clattach function that:
 * "Allocates an mbuf structure and attaches an external cluster."
 */

struct mbuf *m_clattach(extbuf, extfree, extsize, extarg, wait)
	caddr_t extbuf;	
	int (*extfree)();
	int extsize;
	int extarg;
	int wait;
{
        register struct mbuf *m;

        MGETHDR(m, wait, MT_DATA);
        if (m == 0)
                return (0);
        m->m_ext.ext_buf = extbuf;
        m->m_ext.ext_free = extfree;
        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_data = extbuf;
        m->m_flags |= M_EXT;
        m->m_pkthdr.len = extsize;
        m->m_len = extsize;

        return (m);

}
void *atalk_timeout(func, arg, ticks)
	void (*func)();
	void *arg;
	int ticks;
{
/*
	dPrintf(D_M_ATP,D_L_VERBOSE,
			"atalk_timeout: func=%x,arg=%x,time=%d\n", func,arg,ticks, 0, 0);
*/
	timeout(func, arg, ticks);
	return arg;
}

void atalk_untimeout(func, arg, trb)
	void (*func)();
	void *arg;
	void *trb;
{
/*
	dPrintf(D_M_ATP,D_L_VERBOSE,
		"atalk_untimeout: func=%x,arg=%x, trb=%d\n", func,arg,trb, 0, 0);
*/
	untimeout(func, arg);
}

void config_atalk()
{
	atalk_load();
	pat_config();
}

#else

int ATsocket(proto)
	int proto;
{
	int err, rc = -1;

	if (sys_ATsocket)
		rc = (*sys_ATsocket)(proto, &err, 0);
	else
		err = ENXIO;
	if (err)
		setuerror(err);
	return rc;
}

int ATgetmsg(fd, ctlptr, datptr, flags)
	int fd;
	void *ctlptr;
	void *datptr;
	int *flags;
{
	int err, rc = -1;

	if (sys_ATgetmsg)
		rc = (*sys_ATgetmsg)(fd, ctlptr, datptr, flags, &err, 0);
	else
		err = ENXIO;
	if (err)
		setuerror(err);
	return rc;
}

int ATputmsg(fd, ctlptr, datptr, flags)
	int fd;
	void *ctlptr;
	void *datptr;
	int flags;
{
	int err, rc = -1;

	if (sys_ATputmsg)
		rc = (*sys_ATputmsg)(fd, ctlptr, datptr, flags, &err, 0);
	else
		err = ENXIO;
	if (err)
		setuerror(err);
	return rc;
}

int ATPsndreq(fd, buf, len, nowait)
	int fd;
	unsigned char *buf;
	int len;
	int nowait;
{
	int err, rc = -1;

	if (sys_ATPsndreq)
		rc = (*sys_ATPsndreq)(fd, buf, len, nowait, &err, 0);
	else
		err = ENXIO;
	if (err)
		setuerror(err);
	return rc;
}

int ATPsndrsp(fd, respbuff, resplen, datalen)
	int fd;
	unsigned char *respbuff;
	int resplen;
	int datalen;
{
	int err, rc = -1;

	if (sys_ATPsndrsp)
		rc = (*sys_ATPsndrsp)(fd, respbuff, resplen, datalen, &err, 0);
	else
		err = ENXIO;
	if (err)
		setuerror(err);
	return rc;
}

int ATPgetreq(fd, buf, buflen)
	int fd;
	unsigned char *buf;
	int buflen;
{
	int err, rc = -1;

	if (sys_ATPgetreq)
		rc = (*sys_ATPgetreq)(fd, buf, buflen, &err, 0);
	else
		err = ENXIO;
	if (err)
		setuerror(err);
	return rc;
}

int ATPgetrsp(fd, bdsp)
	int fd;
	unsigned char *bdsp;
{
	int err, rc = -1;

	if (sys_ATPgetrsp)
		rc = (*sys_ATPgetrsp)(fd, bdsp, &err, 0);
	else
		err = ENXIO;
	if (err)
		setuerror(err);
	return rc;
}

void *atalk_kalloc(size)
	int size;
{
     return (void *)xmalloc(size, 2, pinned_heap);
}

void atalk_kfree(buf)
	void *buf;
{
	xmfree(buf, pinned_heap);
}

int atalk_closeref(fp, grefp)
	struct file *fp;
	gref_t **grefp;
{
	*grefp = (gref_t *)fp->f_data;
	fp->f_data = 0;
	return 0;
}

int atalk_openref(gref, retfd, proc)
	gref_t *gref;
	int *retfd;
	void *proc;
{
extern int _ATrw(), _ATioctl(), _ATselect(), _ATclose(), _ATstat();
static struct fileops fileops = {_ATrw, _ATioctl, _ATselect, _ATclose, _ATstat};
	int err, fd;
	struct file *fp;
	void *crp;

	crp = (void *)crref();
#ifdef _AIX
	if ((err = ufdcreate(FREAD|FWRITE,
			&fileops, 0, DTYPE_OTHER, &fd, crp)) != 0)
#else
	if ((err = ufdcreate(FREAD|FWRITE,
			&fileops, 0, DTYPE_ATALK, &fd, crp)) != 0)
#endif
		return err;
	*retfd = fd;
	fp = U.U_ufd[fd].fp;
	fp->f_data = (void *)gref;
	gref->next = (void *)fp;
	return 0;
}

int atalk_getref(fp, fd, grefp, proc)
	struct file *fp;
	int fd;
	gref_t **grefp;
	struct proc *proc;
{
	if (fp == 0) {
		if ((fd < 0) || (fd > U.U_maxofile) || ((fp = U.U_ufd[fd].fp) == 0)) {
			*grefp = (gref_t *)0;
			return EBADF;
		}
	}
	if ((*grefp = (gref_t *)fp->f_data) == 0)
		return EBADF;
	return 0;
}

gbuf_t *gbuf_alloc(size, pri)
	int size;
	int pri;
{
	gbuf_t *m;

	m = (size > MHLEN) ? (gbuf_t *)m_getclustm(M_DONTWAIT, MSG_DATA, size)
		: (gbuf_t *)m_gethdr(M_DONTWAIT, MSG_DATA);
	gbuf_next(m) = 0;
	gbuf_cont(m) = 0;
	gbuf_wset(m,0);
	return m;
}

void gbuf_freeb(m)
	gbuf_t *m;
{
	if (m)
		m_free(m);
}

static struct trb *trb_freehead = 0;
static struct trb *trb_freetail = 0;
static struct trb *trb_pendhead = 0;
static int trb_cnt = 0;
static atlock_t trb_lock;

static void atalk_rem_timeoutcf()
{
	register int s;
	register struct trb *trb;
	register struct trb *tmp_freehead, *tmp_pendhead;

	ATDISABLE(s, trb_lock);
	tmp_freehead = trb_freehead;
	trb_freehead = 0;
	tmp_pendhead = trb_pendhead;
	trb_pendhead = 0;
	trb_cnt = 0;
	ATENABLE(s, trb_lock);
	while ((trb = tmp_pendhead) != 0) {
		tmp_pendhead = trb->to_next;
		while (tstop(trb));
		tfree(trb);
	}
	while ((trb = tmp_freehead) != 0) {
		tmp_freehead = trb->to_next;
		tfree(trb);
	}
	dPrintf(D_M_ATP,D_L_ERROR, "atalk: timer stopped!\n",0,0,0,0,0);
}

static void atalk_timeoutcf(cnt)
	int cnt;
{
	register int i;
	register struct trb *trb;

	if (trb_freehead == 0) {
		for (i=0; i < cnt-1; i++) {
			trb = (struct trb *)talloc();
			trb->to_next = trb_freehead;
			trb_freehead = trb;
			if (!i) trb_freetail = trb;
			trb_cnt++;
		}
	}
	ATLOCKINIT(trb_lock);
}

static void atalk_clock(trb)
	register struct trb *trb;
{
	register int s;
	register struct trb *next;
	void (*tof)();
	void *arg;

	ATDISABLE(s, trb_lock);
	if (trb_pendhead && trb->func) {
		/*
		 * remove the timeout from the pending queue
		 */
		if (trb_pendhead == trb)
			trb_pendhead = trb->to_next;
		else {
			for (next=trb_pendhead; next->to_next; next=next->to_next) {
				if (next->to_next == trb) {
					next->to_next = trb->to_next;
					trb->func = 0;
					break;
				}
			}
			if (trb->func) {
				dPrintf(D_M_ATP,D_L_WARNING,
					"atalk_clock: %d,%x,%x\n", trb_cnt,trb,trb_pendhead,0,0);
				/*
				 * we have not found the trb in the pending list - something
				 * has gone wrong here. maybe the trb has been returned to
				 * the free list; in which case, we should simply ignore
				 * this timeout event!
				 */
				for (next=trb_freehead; next; next=next->to_next) {
					if (next == trb)
					{
						ATENABLE(s, trb_lock);
						return;
					}
				}
				/*
				 * the trb is not in the free list either - something has
				 * really gone wacky here! all we can do now is put the
				 * trb back into the free list and hope that it will be ok.
				 */
				trb->to_next = 0;
				if (trb_freehead)
					trb_freetail->to_next = trb;
				else
					trb_freehead = trb;
				trb_freetail = trb;
				trb_cnt++;
				ATENABLE(s, trb_lock);
				return;
			}
		}

		/*
		 * process the timeout
		 */
		trb->func = 0;
		trb->to_next = 0;
		tof = trb->tof;
		trb->tof = 0;
		arg = (void *)trb->func_data;
		trb->func_data = 999;
		if (trb_freehead)
			trb_freetail->to_next = trb;
		else
			trb_freehead = trb;
		trb_freetail = trb;
		trb_cnt++;
		ATENABLE(s, trb_lock);
		if (tof) {
			dPrintf(D_M_ATP,D_L_VERBOSE, "atalk_clock: func=%x, arg=%x, %d\n",
				tof,arg,trb_cnt,0,0);
			(*tof)(arg);
		} else {
			dPrintf(D_M_ATP,D_L_ERROR, "atalk_clock: func=%x, arg=%x, %d\n",
				tof,arg,trb_cnt,0,0);
		}
	} else
		ATENABLE(s, trb_lock);
}

void *atalk_timeout(func, arg, ticks)
	void (*func)();
	void *arg;
	int ticks;
{
	register int s;
	register struct trb *trb;

	dPrintf(D_M_ATP,D_L_VERBOSE,
		"atalk_timeout: func=%x,arg=%x,time=%d, %d,%x\n", func,arg,ticks,trb_cnt,trb_pendhead);
	/*
	 * set up the timeout request
	 */
	ATDISABLE(s, trb_lock);
	if ((trb = trb_freehead) == 0) {
		ATENABLE(s, trb_lock);
		dPrintf(D_M_ATP,D_L_WARNING,
			"atalk_timeout: NO TRB! time=%d, %d\n", ticks,trb_cnt,0,0,0);
		return 0;
	}
	trb_freehead = trb->to_next;
	trb->to_next = trb_pendhead;
	trb_pendhead = trb;
	trb_cnt--;
	trb->timeout.it_value.tv_sec  =  ticks / HZ;
	trb->timeout.it_value.tv_nsec = (ticks % HZ) * (NS_PER_SEC / HZ);
	trb->knext     = 0;
	trb->kprev     = 0;
	trb->flags     = 0;
	trb->tof       = func;
	trb->func      = (void (*)())atalk_clock;
	trb->func_data = (ulong)arg;
	trb->ipri      = PL_IMP;
	trb->id        = -1;

	/*
	 * start the timeout
	 */
	ATENABLE(s, trb_lock);
	tstart(trb);
	return (void *)trb;
}

void atalk_untimeout(func, arg, trb)
	void (*func)();
	void *arg;
	register struct trb *trb;
{
	register int s;
	register struct trb *next;

	dPrintf(D_M_ATP,D_L_VERBOSE,
		"atalk_untimeout: func=%x,arg=%x, %d\n", func,arg,trb_cnt,0,0);

	ATDISABLE(s, trb_lock);
	if (trb == 0) {
		for (trb=trb_pendhead; trb; trb=trb->to_next) {
			if ((func == trb->tof) && (arg == (void *)trb->func_data))
				break;
		}
	}
	if (trb && (trb->func == (void (*)())atalk_clock)
			&& (func == trb->tof) && (arg == (void *)trb->func_data)) {
		trb->func_data = 999;
		if (!(trb->flags & T_PENDING))
			{
			trb->tof = 0;
			ATENABLE(s, trb_lock);
			return;
			}
		trb->func = 0;
		while (tstop(trb));
		if (trb_pendhead == trb)
			trb_pendhead = trb->to_next;
		else {
			for (next=trb_pendhead; next->to_next != trb; next=next->to_next) {
				if (next->to_next == 0) {
					ATENABLE(s, trb_lock);
					dPrintf(D_M_ATP,D_L_WARNING,
						"atalk_untimeout: UNKNOWN TRB %x...\n",trb,0,0,0,0);
					return;
				}
			}
			next->to_next = trb->to_next;
		}
		trb->to_next = 0;
		trb_freetail->to_next = trb;
		trb_freetail = trb;
		trb_cnt++;
	}
	ATENABLE(s, trb_lock);
}

int config_atalk(dev, cmd, uiop)
dev_t dev;
int cmd;
void *uiop;
{
	static int loaded = 0;
	int err, nest;

	err = 0;
	nest = lockl(&kernel_lock, LOCK_SHORT);

	if (cmd == CFG_INIT) {
		if (loaded)
			goto out;
		vm_protect(0, 4096, 3);
		atalk_timeoutcf(256);
		atalk_load();
		loaded = 1;

	} else if (cmd == CFG_TERM) {
		if (!loaded)
			goto out;
		atalk_rem_timeoutcf();
		atalk_unload();
		loaded = 0;

	} else
		err =  EINVAL;

out:
	if (nest != LOCK_NEST)
		unlockl(&kernel_lock);
	return(err);
}

#endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.