xref: /minix/minix/servers/vfs/device.c (revision fb9c64b2)
1 /*
2  * This file contains a number of device-type independent device routines.
3  *
4  * The entry points in this file are:
5  *   do_ioctl:          perform the IOCTL system call
6  *   make_ioctl_grant:  make a grant for an IOCTL request to a device
7  */
8 
9 #include "fs.h"
10 #include "vnode.h"
11 #include "file.h"
12 #include <sys/ioctl.h>
13 
14 /*
15  * Perform the ioctl(2) system call.
16  */
17 int
18 do_ioctl(void)
19 {
20 	unsigned long request;
21 	struct filp *f;
22 	register struct vnode *vp;
23 	vir_bytes arg;
24 	int r, fd;
25 
26 	fd = job_m_in.m_lc_vfs_ioctl.fd;
27 	request = job_m_in.m_lc_vfs_ioctl.req;
28 	arg = (vir_bytes)job_m_in.m_lc_vfs_ioctl.arg;
29 
30 	if ((f = get_filp(fd, VNODE_READ)) == NULL)
31 		return(err_code);
32 	vp = f->filp_vno;		/* get vnode pointer */
33 
34 	switch (vp->v_mode & S_IFMT) {
35 	case S_IFBLK:
36 		f->filp_ioctl_fp = fp;
37 
38 		r = bdev_ioctl(vp->v_sdev, who_e, request, arg);
39 
40 		f->filp_ioctl_fp = NULL;
41 		break;
42 
43 	case S_IFCHR:
44 		r = cdev_io(CDEV_IOCTL, vp->v_sdev, who_e, arg, 0, request,
45 		    f->filp_flags);
46 		break;
47 
48 	case S_IFSOCK:
49 		r = sdev_ioctl(vp->v_sdev, request, arg, f->filp_flags);
50 		break;
51 
52 	default:
53 		r = ENOTTY;
54 	}
55 
56 	unlock_filp(f);
57 
58 	return r;
59 }
60 
61 /*
62  * Create a magic grant for the given IOCTL request.
63  */
64 cp_grant_id_t
65 make_ioctl_grant(endpoint_t driver_e, endpoint_t user_e, vir_bytes buf,
66 	unsigned long request)
67 {
68 	cp_grant_id_t grant;
69 	int access;
70 	size_t size;
71 
72 	/*
73 	 * For IOCTLs, the bytes parameter contains the IOCTL request.
74 	 * This request encodes the requested access method and buffer size.
75 	 */
76 	access = 0;
77 	if (_MINIX_IOCTL_IOR(request)) access |= CPF_WRITE;
78 	if (_MINIX_IOCTL_IOW(request)) access |= CPF_READ;
79 	if (_MINIX_IOCTL_BIG(request))
80 		size = _MINIX_IOCTL_SIZE_BIG(request);
81 	else
82 		size = _MINIX_IOCTL_SIZE(request);
83 
84 	/*
85 	 * Grant access to the buffer even if no I/O happens with the ioctl,
86 	 * although now that we no longer identify responses based on grants,
87 	 * this is not strictly necessary.
88 	 */
89 	grant = cpf_grant_magic(driver_e, user_e, buf, size, access);
90 
91 	if (!GRANT_VALID(grant))
92 		panic("VFS: cpf_grant_magic failed");
93 
94 	return grant;
95 }
96