1/*	$NetBSD: ml_ipl.c,v 1.6 2008/05/20 07:08:06 darrenr Exp $	*/
2
3/*
4 * Copyright (C) 1993-2001 by Darren Reed.
5 *
6 * See the IPFILTER.LICENCE file for details on licencing.
7 */
8/*
9 * 29/12/94 Added code from Marc Huber <huber@fzi.de> to allow it to allocate
10 * its own major char number! Way cool patch!
11 */
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <sys/time.h>
15#include <sys/file.h>
16#include <sys/conf.h>
17#include <sys/syslog.h>
18#include <sys/buf.h>
19#include <sys/param.h>
20#include <sys/errno.h>
21#include <sys/uio.h>
22#include <sys/vnode.h>
23#include <sundev/mbvar.h>
24#include <sun/autoconf.h>
25#include <sun/vddrv.h>
26#if defined(sun4c) || defined(sun4m)
27#include <sun/openprom.h>
28#endif
29
30#ifndef	IPL_NAME
31#define	IPL_NAME	"/dev/ipl"
32#endif
33
34extern	int	ipfattach(), iplopen(), iplclose(), iplioctl(), iplread();
35extern	int	nulldev(), iplidentify(), errno;
36
37struct	cdevsw	ipldevsw =
38{
39	iplopen, iplclose, iplread, nulldev,
40	iplioctl, nulldev, nulldev, nulldev,
41	0, nulldev,
42};
43
44
45struct	dev_ops	ipl_ops =
46{
47	1,
48	iplidentify,
49	ipfattach,
50	iplopen,
51	iplclose,
52	iplread,
53	NULL,		/* write */
54	NULL,		/* strategy */
55	NULL,		/* dump */
56	0,		/* psize */
57        iplioctl,
58	NULL,		/* reset */
59	NULL		/* mmap */
60};
61
62int	ipl_major = 0;
63
64#ifdef sun4m
65struct	vdldrv	vd =
66{
67	VDMAGIC_PSEUDO,
68	"ipl",
69	&ipl_ops,
70	NULL,
71	&ipldevsw,
72	0,
73	0,
74	NULL,
75	NULL,
76	NULL,
77	0,
78	1,
79};
80#else /* sun4m */
81struct vdldrv vd =
82{
83	VDMAGIC_PSEUDO,	/* magic */
84	"ipl",		/* name */
85#ifdef sun4c
86	&ipl_ops,	/* dev_ops */
87#else
88	NULL,		/* struct mb_ctlr *mb_ctlr */
89	NULL,		/* struct mb_driver *mb_driver */
90	NULL,		/* struct mb_device *mb_device */
91	0,		/* num ctlrs */
92	1,		/* numdevs */
93#endif /* sun4c */
94	NULL,		/* bdevsw */
95	&ipldevsw,	/* cdevsw */
96	0,		/* block major */
97	0,		/* char major */
98};
99#endif /* sun4m */
100
101extern int vd_unuseddev();
102extern struct cdevsw cdevsw[];
103extern int nchrdev;
104
105xxxinit(u_int fc, struct vddrv *vdp, caddr_t vdi, struct vdstat *vds)
106{
107	struct	vdlinkage *v;
108	int	i;
109
110	switch (fc)
111	{
112	case VDLOAD:
113		while (ipl_major < nchrdev &&
114		       cdevsw[ipl_major].d_open != vd_unuseddev)
115			ipl_major++;
116		if (ipl_major == nchrdev)
117			return ENODEV;
118		vd.Drv_charmajor = ipl_major;
119		vdp->vdd_vdtab = (struct vdlinkage *)&vd;
120		return ipl_attach(vdi);
121	case VDUNLOAD:
122		return unload(vdp, vdi);
123
124	case VDSTAT:
125		return 0;
126
127	default:
128		return EIO;
129	}
130}
131
132static
133unload(struct vddrv *vdp, struct vdioctl_unload *vdi)
134{
135	int	i;
136
137	(void) vn_remove(IPL_NAME, UIO_SYSSPACE, FILE);
138	return ipfdetach();
139}
140
141
142static	int	ipl_attach(vdi)
143struct	vdioctl_load	*vdi;
144{
145	struct	vnode	*vp;
146	struct	vattr	vattr;
147	int		error = 0, fmode = S_IFCHR|0600;
148
149	(void) vn_remove(IPL_NAME, UIO_SYSSPACE, FILE);
150	vattr_null(&vattr);
151	vattr.va_type = MFTOVT(fmode);
152	vattr.va_mode = (fmode & 07777);
153	vattr.va_rdev = ipl_major<<8;
154
155	error = vn_create(IPL_NAME, UIO_SYSSPACE, &vattr, EXCL, 0, &vp);
156	if (error == 0)
157		VN_RELE(vp);
158	return ipfattach(0);
159}
160