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