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);
50extern int	iskmemdev(dev_t dev);
51
52struct bdevsw	bdevsw[] =
53{
54	/*
55	 *	For block devices, every other block of 8 slots is
56	 *	reserved for Apple.  The other slots are available for
57	 *	the user.  This way we can both add new entries without
58	 *	running into each other.  Be sure to fill in Apple's
59	 *	8 reserved slots when you jump over us -- we'll do the
60	 *	same for you.
61	 */
62
63	/* 0 - 7 are reserved for Apple */
64
65	NO_BDEVICE,							/* 0*/
66	NO_BDEVICE,							/* 1*/
67	NO_BDEVICE,							/* 2*/
68	NO_BDEVICE,							/* 3*/
69	NO_BDEVICE,							/* 4*/
70	NO_BDEVICE,							/* 5*/
71	NO_BDEVICE,							/* 6*/
72	NO_BDEVICE,							/* 7*/
73
74	/* 8 - 15 are reserved to the user */
75	NO_BDEVICE,							/* 8*/
76	NO_BDEVICE,							/* 9*/
77	NO_BDEVICE,							/*10*/
78	NO_BDEVICE,							/*11*/
79	NO_BDEVICE,							/*12*/
80	NO_BDEVICE,							/*13*/
81	NO_BDEVICE,							/*14*/
82	NO_BDEVICE,							/*15*/
83
84	/* 16 - 23 are reserved for Apple */
85	NO_BDEVICE,							/*16*/
86	NO_BDEVICE,							/*17*/
87	NO_BDEVICE,							/*18*/
88	NO_BDEVICE,							/*18*/
89	NO_BDEVICE,							/*20*/
90	NO_BDEVICE,							/*21*/
91	NO_BDEVICE,							/*22*/
92	NO_BDEVICE,							/*23*/
93};
94
95int	nblkdev = sizeof (bdevsw) / sizeof (bdevsw[0]);
96
97extern struct tty *km_tty[];
98extern d_open_t		cnopen;
99extern d_close_t	cnclose;
100extern d_read_t		cnread;
101extern d_write_t	cnwrite;
102extern d_ioctl_t	cnioctl;
103extern d_select_t	cnselect;
104extern d_open_t		kmopen;
105extern d_close_t	kmclose;
106extern d_read_t		kmread;
107extern d_write_t	kmwrite;
108extern d_ioctl_t	kmioctl;
109extern d_open_t		sgopen;
110extern d_close_t	sgclose;
111extern d_ioctl_t	sgioctl;
112
113#if NVOL > 0
114extern d_open_t		volopen;
115extern d_close_t	volclose;
116extern d_ioctl_t	volioctl;
117#else
118#define	volopen		eno_opcl
119#define	volclose	eno_opcl
120#define	volioctl	eno_ioctl
121#endif
122
123extern d_open_t		cttyopen;
124extern d_read_t		cttyread;
125extern d_write_t	cttywrite;
126extern d_ioctl_t	cttyioctl;
127extern d_select_t	cttyselect;
128
129extern d_read_t		mmread;
130extern d_write_t	mmwrite;
131extern d_ioctl_t	mmioctl;
132#define	mmselect	(select_fcn_t *)seltrue
133#define mmmmap		eno_mmap
134
135#include <pty.h>
136#if NPTY > 0
137extern struct tty *pt_tty[];
138extern d_open_t		ptsopen;
139extern d_close_t	ptsclose;
140extern d_read_t		ptsread;
141extern d_write_t	ptswrite;
142extern d_stop_t		ptsstop;
143extern d_open_t		ptcopen;
144extern d_close_t	ptcclose;
145extern d_read_t		ptcread;
146extern d_write_t	ptcwrite;
147extern d_select_t	ptcselect;
148extern d_ioctl_t	ptyioctl;
149#else
150#define ptsopen		eno_opcl
151#define ptsclose	eno_opcl
152#define ptsread		eno_rdwrt
153#define ptswrite	eno_rdwrt
154#define	ptsstop		nulldev
155
156#define ptcopen		eno_opcl
157#define ptcclose	eno_opcl
158#define ptcread		eno_rdwrt
159#define ptcwrite	eno_rdwrt
160#define	ptcselect	eno_select
161#define ptyioctl	eno_ioctl
162#endif
163
164extern d_open_t		logopen;
165extern d_close_t	logclose;
166extern d_read_t		logread;
167extern d_ioctl_t	logioctl;
168extern d_select_t	logselect;
169extern d_open_t		fdesc_open;
170extern d_read_t		fdesc_read;
171extern d_write_t	fdesc_write;
172extern d_ioctl_t	fdesc_ioctl;
173extern d_select_t	fdesc_select;
174
175#define nullopen	(d_open_t *)&nulldev
176#define nullclose	(d_close_t *)&nulldev
177#define nullread	(d_read_t *)&nulldev
178#define nullwrite	(d_write_t *)&nulldev
179#define nullioctl	(d_ioctl_t *)&nulldev
180#define nullselect	(d_select_t *)&nulldev
181#define nullstop	(d_stop_t *)&nulldev
182#define nullreset	(d_reset_t *)&nulldev
183
184struct cdevsw	cdevsw[] =
185{
186	/*
187	 *	For character devices, every other block of 16 slots is
188	 *	reserved for Apple.  The other slots are available for
189	 *	the user.  This way we can both add new entries without
190	 *	running into each other.  Be sure to fill in Apple's
191	 *	16 reserved slots when you jump over us -- we'll do the
192	 *	same for you.
193	 */
194
195	/* 0 - 15 are reserved for Apple */
196
197    {
198	cnopen,		cnclose,	cnread,		cnwrite,	/* 0*/
199	cnioctl,	nullstop,	nullreset,	0,		cnselect,
200	eno_mmap,	eno_strat,	eno_getc,	eno_putc, 	D_TTY
201    },
202    NO_CDEVICE,								/* 1*/
203    {
204	cttyopen,	nullclose,	cttyread,	cttywrite,	/* 2*/
205	cttyioctl,	nullstop,	nullreset,	0,		cttyselect,
206	eno_mmap,	eno_strat,	eno_getc,	eno_putc,	D_TTY
207    },
208    {
209	nullopen,	nullclose,	mmread,		mmwrite,	/* 3*/
210	mmioctl,	nullstop,	nullreset,	0,		mmselect,
211	mmmmap,		eno_strat,	eno_getc,	eno_putc,	D_DISK
212    },
213    {
214	ptsopen,	ptsclose,	ptsread,	ptswrite,	/* 4*/
215	ptyioctl,	ptsstop,	nullreset,	pt_tty,		ttselect,
216	eno_mmap,	eno_strat,	eno_getc,	eno_putc,	D_TTY
217    },
218    {
219	ptcopen,	ptcclose,	ptcread,	ptcwrite,	/* 5*/
220	ptyioctl,	nullstop,	nullreset,	0,		ptcselect,
221	eno_mmap,	eno_strat,	eno_getc,	eno_putc,	D_TTY
222    },
223    {
224	logopen,	logclose,	logread,	eno_rdwrt,	/* 6*/
225	logioctl,	eno_stop,	nullreset,	0,		logselect,
226	eno_mmap,	eno_strat,	eno_getc,	eno_putc,	0
227    },
228    NO_CDEVICE,								/* 7*/
229    NO_CDEVICE,								/* 8*/
230    NO_CDEVICE,								/* 9*/
231    NO_CDEVICE,								/*10*/
232    NO_CDEVICE,								/*11*/
233    {
234	kmopen,		kmclose,	kmread,		kmwrite,	/*12*/
235	kmioctl,	nullstop,	nullreset,	km_tty,		ttselect,
236	eno_mmap,	eno_strat,	eno_getc,	eno_putc,	0
237    },
238    NO_CDEVICE,								/*13*/
239    NO_CDEVICE,								/*14*/
240    NO_CDEVICE,								/*15*/
241
242	/* 16 - 31 are reserved to the user */
243    NO_CDEVICE,								/*16*/
244    NO_CDEVICE,								/*17*/
245    NO_CDEVICE,								/*18*/
246    NO_CDEVICE,								/*19*/
247    NO_CDEVICE,								/*20*/
248    NO_CDEVICE,								/*21*/
249    NO_CDEVICE,								/*22*/
250    NO_CDEVICE,								/*23*/
251    NO_CDEVICE,								/*24*/
252    NO_CDEVICE,								/*25*/
253    NO_CDEVICE,								/*26*/
254    NO_CDEVICE,								/*27*/
255    NO_CDEVICE,								/*28*/
256    NO_CDEVICE,								/*29*/
257    NO_CDEVICE,								/*30*/
258    NO_CDEVICE,								/*31*/
259
260	/* 32 - 47 are reserved to NeXT */
261    {
262	fdesc_open,	eno_opcl,	fdesc_read,	fdesc_write,	/*32*/
263	fdesc_ioctl,	eno_stop,	eno_reset,	0,		fdesc_select,
264	eno_mmap,	eno_strat,	eno_getc,	eno_putc,	0
265    },
266#if 1
267   NO_CDEVICE,
268#else
269    {
270	sgopen,		sgclose,	eno_rdwrt,	eno_rdwrt,	/*33*/
271	sgioctl,	eno_stop,	eno_reset,	0,		eno_select,
272	eno_mmap,	eno_strat,	eno_getc,	eno_putc,	D_TAPE
273    },
274#endif
275    NO_CDEVICE,								/*34*/
276    NO_CDEVICE,								/*35*/
277    NO_CDEVICE,								/*36*/
278    NO_CDEVICE,								/*37*/
279    NO_CDEVICE,								/*38*/
280    NO_CDEVICE,								/*39*/
281    NO_CDEVICE,								/*40*/
282    NO_CDEVICE,								/*41*/
283    {
284	volopen,	volclose,	eno_rdwrt,	eno_rdwrt,	/*42*/
285	volioctl,	eno_stop,	eno_reset,	0,		(select_fcn_t *)seltrue,
286	eno_mmap,	eno_strat,	eno_getc,	eno_putc,	0
287    },
288};
289int	nchrdev = sizeof (cdevsw) / sizeof (cdevsw[0]);
290
291uint64_t cdevsw_flags[sizeof (cdevsw) / sizeof (cdevsw[0])];
292
293#include	<sys/vnode.h> /* for VCHR and VBLK */
294/*
295 * return true if a disk
296 */
297int
298isdisk(dev_t dev, int type)
299{
300	dev_t	maj = major(dev);
301
302	switch (type) {
303	case VCHR:
304		maj = chrtoblk(maj);
305		if (maj == NODEV) {
306			break;
307		}
308		/* FALL THROUGH */
309	case VBLK:
310		if (bdevsw[maj].d_type == D_DISK) {
311			return (1);
312		}
313		break;
314	}
315	return(0);
316}
317
318static int chrtoblktab[] = {
319	/* CHR*/	/* BLK*/	/* CHR*/	/* BLK*/
320	/*  0 */	NODEV,		/*  1 */	NODEV,
321	/*  2 */	NODEV,		/*  3 */	NODEV,
322	/*  4 */	NODEV,		/*  5 */	NODEV,
323	/*  6 */	NODEV,		/*  7 */	NODEV,
324	/*  8 */	NODEV,		/*  9 */	NODEV,
325	/* 10 */	NODEV,		/* 11 */	NODEV,
326	/* 12 */	NODEV,		/* 13 */	NODEV,
327	/* 14 */	NODEV,		/* 15 */	NODEV,
328	/* 16 */	NODEV,		/* 17 */	NODEV,
329	/* 18 */	NODEV,		/* 19 */	NODEV,
330	/* 20 */	NODEV,		/* 21 */	NODEV,
331	/* 22 */	NODEV,		/* 23 */	NODEV,
332	/* 24 */	NODEV,		/* 25 */	NODEV,
333	/* 26 */	NODEV,		/* 27 */	NODEV,
334	/* 28 */	NODEV,		/* 29 */	NODEV,
335	/* 30 */	NODEV,		/* 31 */	NODEV,
336	/* 32 */	NODEV,		/* 33 */	NODEV,
337	/* 34 */	NODEV,		/* 35 */	NODEV,
338	/* 36 */	NODEV,		/* 37 */	NODEV,
339	/* 38 */	NODEV,		/* 39 */	NODEV,
340	/* 40 */	NODEV,		/* 41 */	NODEV,
341	/* 42 */	NODEV,		/* 43 */	NODEV,
342	/* 44 */	NODEV,
343};
344
345/*
346 * convert chr dev to blk dev
347 */
348dev_t
349chrtoblk(dev_t dev)
350{
351	int blkmaj;
352
353	if (major(dev) >= nchrdev)
354		return(NODEV);
355	blkmaj = chrtoblktab[major(dev)];
356	if (blkmaj == NODEV)
357		return(NODEV);
358	return(makedev(blkmaj, minor(dev)));
359}
360
361int
362chrtoblk_set(int cdev, int bdev)
363{
364	if (cdev >= nchrdev)
365		return (-1);
366	if (bdev != NODEV && bdev >= nblkdev)
367		return (-1);
368	chrtoblktab[cdev] = bdev;
369	return 0;
370}
371
372/*
373 * Returns true if dev is /dev/mem or /dev/kmem.
374 */
375int iskmemdev(dev_t dev)
376{
377	return (major(dev) == 3 && minor(dev) < 2);
378}
379