dist/ipf/ml_ipl.c
author yamt <yamt@NetBSD.org>
Tue, 17 Apr 2012 00:01:34 +0000
branchyamt-pagecache
changeset 280360 e98874280705
parent 170082 29e3973a0c0b
permissions -rw-r--r--
sync with head

/*	$NetBSD: ml_ipl.c,v 1.6.2.1 2012/04/17 00:02:24 yamt Exp $	*/

/*
 * Copyright (C) 1993-2001 by Darren Reed.
 *
 * See the IPFILTER.LICENCE file for details on licencing.
 */
/*
 * 29/12/94 Added code from Marc Huber <huber@fzi.de> to allow it to allocate
 * its own major char number! Way cool patch!
 */
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/file.h>
#include <sys/conf.h>
#include <sys/syslog.h>
#include <sys/buf.h>
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/uio.h>
#include <sys/vnode.h>
#include <sundev/mbvar.h>
#include <sun/autoconf.h>
#include <sun/vddrv.h>
#if defined(sun4c) || defined(sun4m)
#include <sun/openprom.h>
#endif

#ifndef	IPL_NAME
#define	IPL_NAME	"/dev/ipl"
#endif

extern	int	ipfattach(), iplopen(), iplclose(), iplioctl(), iplread();
extern	int	nulldev(), iplidentify(), errno;

struct	cdevsw	ipldevsw =
{
	iplopen, iplclose, iplread, nulldev,
	iplioctl, nulldev, nulldev, nulldev,
	0, nulldev,
};


struct	dev_ops	ipl_ops =
{
	1,
	iplidentify,
	ipfattach,
	iplopen,
	iplclose,
	iplread,
	NULL,		/* write */
	NULL,		/* strategy */
	NULL,		/* dump */
	0,		/* psize */
        iplioctl,
	NULL,		/* reset */
	NULL		/* mmap */
};

int	ipl_major = 0;

#ifdef sun4m
struct	vdldrv	vd =
{
	VDMAGIC_PSEUDO,
	"ipl",
	&ipl_ops,
	NULL,
	&ipldevsw,
	0,
	0,
	NULL,
	NULL,
	NULL,
	0,
	1,
};
#else /* sun4m */
struct vdldrv vd =
{
	VDMAGIC_PSEUDO,	/* magic */
	"ipl",		/* name */
#ifdef sun4c
	&ipl_ops,	/* dev_ops */
#else
	NULL,		/* struct mb_ctlr *mb_ctlr */
	NULL,		/* struct mb_driver *mb_driver */
	NULL,		/* struct mb_device *mb_device */
	0,		/* num ctlrs */
	1,		/* numdevs */
#endif /* sun4c */
	NULL,		/* bdevsw */
	&ipldevsw,	/* cdevsw */
	0,		/* block major */
	0,		/* char major */
};
#endif /* sun4m */

extern int vd_unuseddev();
extern struct cdevsw cdevsw[];
extern int nchrdev;

xxxinit(u_int fc, struct vddrv *vdp, caddr_t vdi, struct vdstat *vds)
{
	struct	vdlinkage *v;
	int	i;

	switch (fc)
	{
	case VDLOAD:
		while (ipl_major < nchrdev &&
		       cdevsw[ipl_major].d_open != vd_unuseddev)
			ipl_major++;
		if (ipl_major == nchrdev)
			return ENODEV;
		vd.Drv_charmajor = ipl_major;
		vdp->vdd_vdtab = (struct vdlinkage *)&vd;
		return ipl_attach(vdi);
	case VDUNLOAD:
		return unload(vdp, vdi);

	case VDSTAT:
		return 0;

	default:
		return EIO;
	}
}

static
unload(struct vddrv *vdp, struct vdioctl_unload *vdi)
{
	int	i;

	(void) vn_remove(IPL_NAME, UIO_SYSSPACE, FILE);
	return ipfdetach();
}


static	int	ipl_attach(vdi)
struct	vdioctl_load	*vdi;
{
	struct	vnode	*vp;
	struct	vattr	vattr;
	int		error = 0, fmode = S_IFCHR|0600;

	(void) vn_remove(IPL_NAME, UIO_SYSSPACE, FILE);
	vattr_null(&vattr);
	vattr.va_type = MFTOVT(fmode);
	vattr.va_mode = (fmode & 07777);
	vattr.va_rdev = ipl_major<<8;

	error = vn_create(IPL_NAME, UIO_SYSSPACE, &vattr, EXCL, 0, &vp);
	if (error == 0)
		VN_RELE(vp);
	return ipfattach(0);
}