xref: /minix3/minix/servers/vfs/device.c (revision e3b8d4bb58a799dc7fd563ac39bf3015762af03b)
189a4204bSDavid van Moolenbroek /*
289a4204bSDavid van Moolenbroek  * This file contains a number of device-type independent device routines.
3433d6423SLionel Sambuc  *
4433d6423SLionel Sambuc  * The entry points in this file are:
5433d6423SLionel Sambuc  *   do_ioctl:          perform the IOCTL system call
689a4204bSDavid van Moolenbroek  *   make_ioctl_grant:  make a grant for an IOCTL request to a device
7433d6423SLionel Sambuc  */
8433d6423SLionel Sambuc 
9433d6423SLionel Sambuc #include "fs.h"
10433d6423SLionel Sambuc #include "vnode.h"
1189a4204bSDavid van Moolenbroek #include "file.h"
1289a4204bSDavid van Moolenbroek #include <sys/ioctl.h>
13433d6423SLionel Sambuc 
14232819ddSDavid van Moolenbroek /*
1589a4204bSDavid van Moolenbroek  * Perform the ioctl(2) system call.
16232819ddSDavid van Moolenbroek  */
1789a4204bSDavid van Moolenbroek int
do_ioctl(void)1889a4204bSDavid van Moolenbroek do_ioctl(void)
19433d6423SLionel Sambuc {
2089a4204bSDavid van Moolenbroek 	unsigned long request;
21433d6423SLionel Sambuc 	struct filp *f;
22433d6423SLionel Sambuc 	register struct vnode *vp;
2389a4204bSDavid van Moolenbroek 	vir_bytes arg;
2489a4204bSDavid van Moolenbroek 	int r, fd;
25433d6423SLionel Sambuc 
26232819ddSDavid van Moolenbroek 	fd = job_m_in.m_lc_vfs_ioctl.fd;
2789a4204bSDavid van Moolenbroek 	request = job_m_in.m_lc_vfs_ioctl.req;
2889a4204bSDavid van Moolenbroek 	arg = (vir_bytes)job_m_in.m_lc_vfs_ioctl.arg;
29433d6423SLionel Sambuc 
30232819ddSDavid van Moolenbroek 	if ((f = get_filp(fd, VNODE_READ)) == NULL)
31433d6423SLionel Sambuc 		return(err_code);
32433d6423SLionel Sambuc 	vp = f->filp_vno;		/* get vnode pointer */
33433d6423SLionel Sambuc 
3489a4204bSDavid van Moolenbroek 	switch (vp->v_mode & S_IFMT) {
3589a4204bSDavid van Moolenbroek 	case S_IFBLK:
36433d6423SLionel Sambuc 		f->filp_ioctl_fp = fp;
37433d6423SLionel Sambuc 
3889a4204bSDavid van Moolenbroek 		r = bdev_ioctl(vp->v_sdev, who_e, request, arg);
39433d6423SLionel Sambuc 
40433d6423SLionel Sambuc 		f->filp_ioctl_fp = NULL;
4189a4204bSDavid van Moolenbroek 		break;
4289a4204bSDavid van Moolenbroek 
4389a4204bSDavid van Moolenbroek 	case S_IFCHR:
4489a4204bSDavid van Moolenbroek 		r = cdev_io(CDEV_IOCTL, vp->v_sdev, who_e, arg, 0, request,
45433d6423SLionel Sambuc 		    f->filp_flags);
4689a4204bSDavid van Moolenbroek 		break;
4789a4204bSDavid van Moolenbroek 
48*e3b8d4bbSDavid van Moolenbroek 	case S_IFSOCK:
49*e3b8d4bbSDavid van Moolenbroek 		r = sdev_ioctl(vp->v_sdev, request, arg, f->filp_flags);
50*e3b8d4bbSDavid van Moolenbroek 		break;
51*e3b8d4bbSDavid van Moolenbroek 
5289a4204bSDavid van Moolenbroek 	default:
5389a4204bSDavid van Moolenbroek 		r = ENOTTY;
54433d6423SLionel Sambuc 	}
55433d6423SLionel Sambuc 
56433d6423SLionel Sambuc 	unlock_filp(f);
57433d6423SLionel Sambuc 
58433d6423SLionel Sambuc 	return r;
59433d6423SLionel Sambuc }
60433d6423SLionel Sambuc 
6189a4204bSDavid van Moolenbroek /*
6289a4204bSDavid van Moolenbroek  * Create a magic grant for the given IOCTL request.
6389a4204bSDavid van Moolenbroek  */
6489a4204bSDavid van Moolenbroek cp_grant_id_t
make_ioctl_grant(endpoint_t driver_e,endpoint_t user_e,vir_bytes buf,unsigned long request)6589a4204bSDavid van Moolenbroek make_ioctl_grant(endpoint_t driver_e, endpoint_t user_e, vir_bytes buf,
6689a4204bSDavid van Moolenbroek 	unsigned long request)
67433d6423SLionel Sambuc {
6889a4204bSDavid van Moolenbroek 	cp_grant_id_t grant;
6989a4204bSDavid van Moolenbroek 	int access;
7089a4204bSDavid van Moolenbroek 	size_t size;
7189a4204bSDavid van Moolenbroek 
7289a4204bSDavid van Moolenbroek 	/*
7389a4204bSDavid van Moolenbroek 	 * For IOCTLs, the bytes parameter contains the IOCTL request.
7489a4204bSDavid van Moolenbroek 	 * This request encodes the requested access method and buffer size.
75433d6423SLionel Sambuc 	 */
7689a4204bSDavid van Moolenbroek 	access = 0;
7789a4204bSDavid van Moolenbroek 	if (_MINIX_IOCTL_IOR(request)) access |= CPF_WRITE;
7889a4204bSDavid van Moolenbroek 	if (_MINIX_IOCTL_IOW(request)) access |= CPF_READ;
7989a4204bSDavid van Moolenbroek 	if (_MINIX_IOCTL_BIG(request))
8089a4204bSDavid van Moolenbroek 		size = _MINIX_IOCTL_SIZE_BIG(request);
8189a4204bSDavid van Moolenbroek 	else
8289a4204bSDavid van Moolenbroek 		size = _MINIX_IOCTL_SIZE(request);
83433d6423SLionel Sambuc 
8489a4204bSDavid van Moolenbroek 	/*
8589a4204bSDavid van Moolenbroek 	 * Grant access to the buffer even if no I/O happens with the ioctl,
8689a4204bSDavid van Moolenbroek 	 * although now that we no longer identify responses based on grants,
8789a4204bSDavid van Moolenbroek 	 * this is not strictly necessary.
88433d6423SLionel Sambuc 	 */
8989a4204bSDavid van Moolenbroek 	grant = cpf_grant_magic(driver_e, user_e, buf, size, access);
90433d6423SLionel Sambuc 
9189a4204bSDavid van Moolenbroek 	if (!GRANT_VALID(grant))
9289a4204bSDavid van Moolenbroek 		panic("VFS: cpf_grant_magic failed");
93433d6423SLionel Sambuc 
9489a4204bSDavid van Moolenbroek 	return grant;
95433d6423SLionel Sambuc }
96