Commit | Line | Data |
---|---|---|
805e021f CE |
1 | /* |
2 | * Copyright 2010, Sine Nomine Associates and others. | |
3 | * All Rights Reserved. | |
4 | * | |
5 | * This software has been released under the terms of the IBM Public | |
6 | * License. For details, see the LICENSE file in the top-level source | |
7 | * directory or online at http://www.openafs.org/dl/license10.html | |
8 | */ | |
9 | ||
10 | #include <afsconfig.h> | |
11 | #include "afs/param.h" | |
12 | ||
13 | /* ioctl-based emulation for the AFS syscall, for Solaris 11 and onwards. */ | |
14 | ||
15 | #ifdef AFS_SUN511_ENV | |
16 | ||
17 | #include "afs/sysincludes.h" /* Standard vendor system headers */ | |
18 | #include "afsincludes.h" /* Afs-based standard headers */ | |
19 | ||
20 | #include <sys/types.h> | |
21 | #include <sys/file.h> | |
22 | #include <sys/errno.h> | |
23 | #include <sys/open.h> | |
24 | #include <sys/cred.h> | |
25 | #include <sys/ddi.h> | |
26 | #include <sys/sunddi.h> | |
27 | ||
28 | #define DEVAFS_MINOR 0 | |
29 | ||
30 | static int | |
31 | devafs_open(dev_t *devp, int flag, int otyp, cred_t *cred_p) | |
32 | { | |
33 | if (getminor(*devp) != DEVAFS_MINOR) { | |
34 | return EINVAL; | |
35 | } | |
36 | if (otyp != OTYP_CHR) { | |
37 | return EINVAL; | |
38 | } | |
39 | return 0; | |
40 | } | |
41 | ||
42 | static int | |
43 | devafs_close(dev_t dev, int flag, int otyp, cred_t *cred_p) | |
44 | { | |
45 | if (getminor(dev) != DEVAFS_MINOR) { | |
46 | return EINVAL; | |
47 | } | |
48 | if (otyp != OTYP_CHR) { | |
49 | return EINVAL; | |
50 | } | |
51 | return 0; | |
52 | } | |
53 | ||
54 | static int | |
55 | devafs_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cred_p, | |
56 | int *rval_p) | |
57 | { | |
58 | int error; | |
59 | struct afssysa ua; | |
60 | rval_t rv; | |
61 | ||
62 | if (getminor(dev) != DEVAFS_MINOR) { | |
63 | return EINVAL; | |
64 | } | |
65 | ||
66 | switch (cmd) { | |
67 | case VIOC_SYSCALL: { | |
68 | struct afssysargs sargs; | |
69 | error = ddi_copyin((const void *)arg, &sargs, sizeof(sargs), mode); | |
70 | if (error) { | |
71 | return EFAULT; | |
72 | } | |
73 | ua.syscall = sargs.syscall; | |
74 | ua.parm1 = sargs.param1; | |
75 | ua.parm2 = sargs.param2; | |
76 | ua.parm3 = sargs.param3; | |
77 | ua.parm4 = sargs.param4; | |
78 | ua.parm5 = sargs.param5; | |
79 | ua.parm6 = sargs.param6; | |
80 | ||
81 | break; | |
82 | } | |
83 | case VIOC_SYSCALL32: { | |
84 | struct afssysargs32 sargs32; | |
85 | error = ddi_copyin((const void *)arg, &sargs32, sizeof(sargs32), mode); | |
86 | if (error) { | |
87 | return EFAULT; | |
88 | } | |
89 | ua.syscall = sargs32.syscall; | |
90 | ua.parm1 = sargs32.param1; | |
91 | ua.parm2 = sargs32.param2; | |
92 | ua.parm3 = sargs32.param3; | |
93 | ua.parm4 = sargs32.param4; | |
94 | ua.parm5 = sargs32.param5; | |
95 | ua.parm6 = sargs32.param6; | |
96 | ||
97 | break; | |
98 | } | |
99 | default: | |
100 | return EINVAL; | |
101 | } | |
102 | ||
103 | rv.r_val1 = 0; | |
104 | error = Afs_syscall(&ua, &rv); | |
105 | ||
106 | if (!error) { | |
107 | error = rv.r_val1; | |
108 | } | |
109 | ||
110 | return error; | |
111 | } | |
112 | ||
113 | static struct cb_ops devafs_cb_ops = { | |
114 | /* .cb_open = */ devafs_open, | |
115 | /* .cb_close = */ devafs_close, | |
116 | /* .cb_strategy = */ nodev, | |
117 | /* .cb_print = */ nodev, | |
118 | /* .cb_dump = */ nodev, | |
119 | /* .cb_read = */ nodev, | |
120 | /* .cb_write = */ nodev, | |
121 | /* .cb_ioctl = */ devafs_ioctl, | |
122 | /* .cb_devmap = */ nodev, | |
123 | /* .cb_mmap = */ nodev, | |
124 | /* .cb_segmap = */ nodev, | |
125 | /* .cb_chpoll = */ nochpoll, | |
126 | /* .cb_prop_op = */ ddi_prop_op, | |
127 | /* .cb_str = */ NULL, | |
128 | /* .cb_flag = */ D_NEW | D_MP | D_64BIT, | |
129 | /* .cb_rev = */ CB_REV, | |
130 | /* .cb_aread = */ nodev, | |
131 | /* .cb_awrite = */ nodev, | |
132 | }; | |
133 | ||
134 | static dev_info_t *devafs_dip = NULL; | |
135 | ||
136 | static int | |
137 | devafs_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resultp) | |
138 | { | |
139 | switch (cmd) { | |
140 | case DDI_INFO_DEVT2DEVINFO: | |
141 | *resultp = devafs_dip; | |
142 | return DDI_SUCCESS; | |
143 | case DDI_INFO_DEVT2INSTANCE: | |
144 | *resultp = 0; /* we only have one instance */ | |
145 | return DDI_SUCCESS; | |
146 | default: | |
147 | return DDI_FAILURE; | |
148 | } | |
149 | } | |
150 | ||
151 | static int | |
152 | devafs_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) | |
153 | { | |
154 | int error; | |
155 | switch (cmd) { | |
156 | case DDI_ATTACH: | |
157 | osi_Assert(devafs_dip == NULL); | |
158 | ||
159 | error = ddi_create_minor_node(dip, "afs", S_IFCHR, DEVAFS_MINOR, | |
160 | DDI_PSEUDO, 0); | |
161 | if (error != DDI_SUCCESS) { | |
162 | return DDI_FAILURE; | |
163 | } | |
164 | ||
165 | devafs_dip = dip; | |
166 | ||
167 | ddi_report_dev(dip); | |
168 | ||
169 | return DDI_SUCCESS; | |
170 | case DDI_RESUME: | |
171 | return DDI_FAILURE; | |
172 | default: | |
173 | return DDI_FAILURE; | |
174 | } | |
175 | } | |
176 | ||
177 | static int | |
178 | devafs_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) | |
179 | { | |
180 | switch (cmd) { | |
181 | case DDI_DETACH: | |
182 | osi_Assert(devafs_dip != NULL); | |
183 | ||
184 | devafs_dip = NULL; | |
185 | ||
186 | ddi_prop_remove_all(dip); | |
187 | ddi_remove_minor_node(dip, NULL); | |
188 | ||
189 | return DDI_SUCCESS; | |
190 | case DDI_SUSPEND: | |
191 | return DDI_FAILURE; | |
192 | default: | |
193 | return DDI_FAILURE; | |
194 | } | |
195 | } | |
196 | ||
197 | static struct dev_ops afs_devops = { | |
198 | /* .devo_rev = */ DEVO_REV, | |
199 | /* .devo_refcnt = */ 0, | |
200 | /* .devo_getinfo = */ devafs_getinfo, | |
201 | /* .devo_identify = */ nulldev, | |
202 | /* .devo_probe = */ nulldev, | |
203 | /* .devo_attach = */ devafs_attach, | |
204 | /* .devo_detach = */ devafs_detach, | |
205 | /* .devo_reset = */ nodev, | |
206 | /* .devo_cb_ops = */ &devafs_cb_ops, | |
207 | /* .devo_bus_ops = */ NULL, | |
208 | /* .devo_power = */ NULL, | |
209 | /* .devo_quiesce = */ ddi_quiesce_not_needed, | |
210 | }; | |
211 | ||
212 | extern struct mod_ops mod_driverops; | |
213 | ||
214 | struct modldrv afs_modldrv = { | |
215 | &mod_driverops, | |
216 | "/dev/afs driver", | |
217 | &afs_devops, | |
218 | }; | |
219 | ||
220 | #endif /* AFS_SUN511_ENV */ |