1/*
2 * Copyright (c) 1997-2012 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * Copyright (c) 1993 NeXT Computer, Inc.
30 *
31 * UNIX Device switch tables.
32 *
33 * HISTORY
34 *
35 * 30 July 1997 Umesh Vaishampayan (umeshv@apple.com)
36 * 	enabled file descriptor pseudo-device.
37 * 18 June 1993 ? at NeXT
38 *	Cleaned up a lot of stuff in this file.
39 */
40
41#include <sys/param.h>
42#include <sys/systm.h>
43#include <sys/ioctl.h>
44#include <sys/tty.h>
45#include <sys/conf.h>
46
47/* Prototypes that should be elsewhere: */
48extern dev_t	chrtoblk(dev_t dev);
49extern int	chrtoblk_set(int cdev, int bdev);
50
51struct bdevsw	bdevsw[] =
52{
53	/*
54	 *	For block devices, every other block of 8 slots is
55	 *	reserved for Apple.  The other slots are available for
56	 *	the user.  This way we can both add new entries without
57	 *	running into each other.  Be sure to fill in Apple's
58	 *	8 reserved slots when you jump over us -- we'll do the
59	 *	same for you.
60	 */
61
62	/* 0 - 7 are reserved for Apple */
63
64	NO_BDEVICE,							/* 0*/
65	NO_BDEVICE,							/* 1*/
66	NO_BDEVICE,							/* 2*/
67	NO_BDEVICE,							/* 3*/
68	NO_BDEVICE,							/* 4*/
69	NO_BDEVICE,							/* 5*/
70	NO_BDEVICE,							/* 6*/
71	NO_BDEVICE,							/* 7*/
72
73	/* 8 - 15 are reserved to the user */
74	NO_BDEVICE,							/* 8*/
75	NO_BDEVICE,							/* 9*/
76	NO_BDEVICE,							/*10*/
77	NO_BDEVICE,							/*11*/
78	NO_BDEVICE,							/*12*/
79	NO_BDEVICE,							/*13*/
80	NO_BDEVICE,							/*14*/
81	NO_BDEVICE,							/*15*/
82
83	/* 16 - 23 are reserved for Apple */
84	NO_BDEVICE,							/*16*/
85	NO_BDEVICE,							/*17*/
86	NO_BDEVICE,							/*18*/
87	NO_BDEVICE,							/*18*/
88	NO_BDEVICE,							/*20*/
89	NO_BDEVICE,							/*21*/
90	NO_BDEVICE,							/*22*/
91	NO_BDEVICE,							/*23*/
92};
93
94int	nblkdev = sizeof (bdevsw) / sizeof (bdevsw[0]);
95
96extern struct tty *km_tty[];
97extern d_open_t		cnopen;
98extern d_close_t	cnclose;
99extern d_read_t		cnread;
100extern d_write_t	cnwrite;
101extern d_ioctl_t	cnioctl;
102extern d_select_t	cnselect;
103extern d_open_t		kmopen;
104extern d_close_t	kmclose;
105extern d_read_t		kmread;
106extern d_write_t	kmwrite;
107extern d_ioctl_t	kmioctl;
108extern d_open_t		sgopen;
109extern d_close_t	sgclose;
110extern d_ioctl_t	sgioctl;
111
112#if NVOL > 0
113extern d_open_t		volopen;
114extern d_close_t	volclose;
115extern d_ioctl_t	volioctl;
116#else
117#define	volopen		eno_opcl
118#define	volclose	eno_opcl
119#define	volioctl	eno_ioctl
120#endif
121
122extern d_open_t		cttyopen;
123extern d_read_t		cttyread;
124extern d_write_t	cttywrite;
125extern d_ioctl_t	cttyioctl;
126extern d_select_t	cttyselect;
127
128extern d_read_t		mmread;
129extern d_write_t	mmwrite;
130extern d_ioctl_t	mmioctl;
131#define	mmselect	(select_fcn_t *)seltrue
132#define mmmmap		eno_mmap
133
134#include <pty.h>
135#if NPTY > 0
136extern d_open_t		ptsopen;
137extern d_close_t	ptsclose;
138extern d_read_t		ptsread;
139extern d_write_t	ptswrite;
140extern d_stop_t		ptsstop;
141extern d_select_t	ptsselect;
142extern d_open_t		ptcopen;
143extern d_close_t	ptcclose;
144extern d_read_t		ptcread;
145extern d_write_t	ptcwrite;
146extern d_select_t	ptcselect;
147extern d_ioctl_t	ptyioctl;
148#else
149#define ptsopen		eno_opcl
150#define ptsclose	eno_opcl
151#define ptsread		eno_rdwrt
152#define ptswrite	eno_rdwrt
153#define	ptsstop		nulldev
154
155#define ptcopen		eno_opcl
156#define ptcclose	eno_opcl
157#define ptcread		eno_rdwrt
158#define ptcwrite	eno_rdwrt
159#define	ptcselect	eno_select
160#define ptyioctl	eno_ioctl
161#endif
162
163extern d_open_t		logopen;
164extern d_close_t	logclose;
165extern d_read_t		logread;
166extern d_ioctl_t	logioctl;
167extern d_select_t	logselect;
168extern d_open_t		fdesc_open;
169extern d_read_t		fdesc_read;
170extern d_write_t	fdesc_write;
171extern d_ioctl_t	fdesc_ioctl;
172extern d_select_t	fdesc_select;
173
174#define nullopen	(d_open_t *)&nulldev
175#define nullclose	(d_close_t *)&nulldev
176#define nullread	(d_read_t *)&nulldev
177#define nullwrite	(d_write_t *)&nulldev
178#define nullioctl	(d_ioctl_t *)&nulldev
179#define nullselect	(d_select_t *)&nulldev
180#define nullstop	(d_stop_t *)&nulldev
181#define nullreset	(d_reset_t *)&nulldev
182
183struct cdevsw	cdevsw[] =
184{
185	/*
186	 *	For character devices, every other block of 16 slots is
187	 *	reserved for Apple.  The other slots are available for
188	 *	the user.  This way we can both add new entries without
189	 *	running into each other.  Be sure to fill in Apple's
190	 *	16 reserved slots when you jump over us -- we'll do the
191	 *	same for you.
192	 */
193
194	/* 0 - 15 are reserved for Apple */
195
196    {
197	cnopen,		cnclose,	cnread,		cnwrite,	/* 0*/
198	cnioctl,	nullstop,	nullreset,	0,		cnselect,
199	eno_mmap,	eno_strat,	eno_getc,	eno_putc, 	D_TTY
200    },
201    NO_CDEVICE,								/* 1*/
202    {
203	cttyopen,	nullclose,	cttyread,	cttywrite,	/* 2*/
204	cttyioctl,	nullstop,	nullreset,	0,		cttyselect,
205	eno_mmap,	eno_strat,	eno_getc,	eno_putc,	D_TTY
206    },
207    {
208	nullopen,	nullclose,	mmread,		mmwrite,	/* 3*/
209	mmioctl,	nullstop,	nullreset,	0,		mmselect,
210	mmmmap,		eno_strat,	eno_getc,	eno_putc,	D_DISK
211    },
212    {
213	ptsopen,	ptsclose,	ptsread,	ptswrite,	/* 4*/
214	ptyioctl,	ptsstop,	nullreset,	0,		ptsselect,
215	eno_mmap,	eno_strat,	eno_getc,	eno_putc,	D_TTY
216    },
217    {
218	ptcopen,	ptcclose,	ptcread,	ptcwrite,	/* 5*/
219	ptyioctl,	nullstop,	nullreset,	0,		ptcselect,
220	eno_mmap,	eno_strat,	eno_getc,	eno_putc,	D_TTY
221    },
222    {
223	logopen,	logclose,	logread,	eno_rdwrt,	/* 6*/
224	logioctl,	eno_stop,	nullreset,	0,		logselect,
225	eno_mmap,	eno_strat,	eno_getc,	eno_putc,	0
226    },
227    NO_CDEVICE,								/* 7*/
228    NO_CDEVICE,								/* 8*/
229    NO_CDEVICE,								/* 9*/
230    NO_CDEVICE,								/*10*/
231    NO_CDEVICE,								/*11*/
232    {
233	kmopen,		kmclose,	kmread,		kmwrite,	/*12*/
234	kmioctl,	nullstop,	nullreset,	km_tty,		ttselect,
235	eno_mmap,	eno_strat,	eno_getc,	eno_putc,	0
236    },
237    NO_CDEVICE,								/*13*/
238    NO_CDEVICE,								/*14*/
239    NO_CDEVICE,								/*15*/
240
241	/* 16 - 31 are reserved to the user */
242    NO_CDEVICE,								/*16*/
243    NO_CDEVICE,								/*17*/
244    NO_CDEVICE,								/*18*/
245    NO_CDEVICE,								/*19*/
246    NO_CDEVICE,								/*20*/
247    NO_CDEVICE,								/*21*/
248    NO_CDEVICE,								/*22*/
249    NO_CDEVICE,								/*23*/
250    NO_CDEVICE,								/*24*/
251    NO_CDEVICE,								/*25*/
252    NO_CDEVICE,								/*26*/
253    NO_CDEVICE,								/*27*/
254    NO_CDEVICE,								/*28*/
255    NO_CDEVICE,								/*29*/
256    NO_CDEVICE,								/*30*/
257    NO_CDEVICE,								/*31*/
258
259	/* 32 - 47 are reserved to NeXT */
260    {
261	fdesc_open,	eno_opcl,	fdesc_read,	fdesc_write,	/*32*/
262	fdesc_ioctl,	eno_stop,	eno_reset,	0,		fdesc_select,
263	eno_mmap,	eno_strat,	eno_getc,	eno_putc,	0
264    },
265#if 1
266   NO_CDEVICE,
267#else
268    {
269	sgopen,		sgclose,	eno_rdwrt,	eno_rdwrt,	/*33*/
270	sgioctl,	eno_stop,	eno_reset,	0,		eno_select,
271	eno_mmap,	eno_strat,	eno_getc,	eno_putc,	D_TAPE
272    },
273#endif
274    NO_CDEVICE,								/*34*/
275    NO_CDEVICE,								/*35*/
276    NO_CDEVICE,								/*36*/
277    NO_CDEVICE,								/*37*/
278    NO_CDEVICE,								/*38*/
279    NO_CDEVICE,								/*39*/
280    NO_CDEVICE,								/*40*/
281    NO_CDEVICE,								/*41*/
282    {
283	volopen,	volclose,	eno_rdwrt,	eno_rdwrt,	/*42*/
284	volioctl,	eno_stop,	eno_reset,	0,		(select_fcn_t *)seltrue,
285	eno_mmap,	eno_strat,	eno_getc,	eno_putc,	0
286    },
287};
288int	nchrdev = sizeof (cdevsw) / sizeof (cdevsw[0]);
289
290uint64_t cdevsw_flags[sizeof (cdevsw) / sizeof (cdevsw[0])];
291
292#include	<sys/vnode.h> /* for VCHR and VBLK */
293/*
294 * return true if a disk
295 */
296int
297isdisk(dev_t dev, int type)
298{
299	dev_t	maj = major(dev);
300
301	switch (type) {
302	case VCHR:
303		maj = chrtoblk(maj);
304		if (maj == NODEV) {
305			break;
306		}
307		/* FALL THROUGH */
308	case VBLK:
309		if (bdevsw[maj].d_type == D_DISK) {
310			return (1);
311		}
312		break;
313	}
314	return(0);
315}
316
317static int chrtoblktab[] = {
318	/* CHR*/	/* BLK*/	/* CHR*/	/* BLK*/
319	/*  0 */	NODEV,		/*  1 */	NODEV,
320	/*  2 */	NODEV,		/*  3 */	NODEV,
321	/*  4 */	NODEV,		/*  5 */	NODEV,
322	/*  6 */	NODEV,		/*  7 */	NODEV,
323	/*  8 */	NODEV,		/*  9 */	NODEV,
324	/* 10 */	NODEV,		/* 11 */	NODEV,
325	/* 12 */	NODEV,		/* 13 */	NODEV,
326	/* 14 */	NODEV,		/* 15 */	NODEV,
327	/* 16 */	NODEV,		/* 17 */	NODEV,
328	/* 18 */	NODEV,		/* 19 */	NODEV,
329	/* 20 */	NODEV,		/* 21 */	NODEV,
330	/* 22 */	NODEV,		/* 23 */	NODEV,
331	/* 24 */	NODEV,		/* 25 */	NODEV,
332	/* 26 */	NODEV,		/* 27 */	NODEV,
333	/* 28 */	NODEV,		/* 29 */	NODEV,
334	/* 30 */	NODEV,		/* 31 */	NODEV,
335	/* 32 */	NODEV,		/* 33 */	NODEV,
336	/* 34 */	NODEV,		/* 35 */	NODEV,
337	/* 36 */	NODEV,		/* 37 */	NODEV,
338	/* 38 */	NODEV,		/* 39 */	NODEV,
339	/* 40 */	NODEV,		/* 41 */	NODEV,
340	/* 42 */	NODEV,		/* 43 */	NODEV,
341	/* 44 */	NODEV,
342};
343
344/*
345 * convert chr dev to blk dev
346 */
347dev_t
348chrtoblk(dev_t dev)
349{
350	int blkmaj;
351
352	if (major(dev) >= nchrdev)
353		return(NODEV);
354	blkmaj = chrtoblktab[major(dev)];
355	if (blkmaj == NODEV)
356		return(NODEV);
357	return(makedev(blkmaj, minor(dev)));
358}
359
360int
361chrtoblk_set(int cdev, int bdev)
362{
363	if (cdev >= nchrdev)
364		return (-1);
365	if (bdev != NODEV && bdev >= nblkdev)
366		return (-1);
367	chrtoblktab[cdev] = bdev;
368	return 0;
369}
370
371