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