Sync usage with man page.
[netbsd-mini2440.git] / sys / dev / pud / pud_dev.c
blob5a89339dc6285d9ea6aea8851209f671ce9f0956
1 /* $NetBSD: pud_dev.c,v 1.5 2009/12/22 14:12:40 pooka Exp $ */
3 /*
4 * Copyright (c) 2007 Antti Kantee. All Rights Reserved.
6 * Development of this software was supported by the
7 * Research Foundation of Helsinki University of Technology
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28 * SUCH DAMAGE.
31 #include <sys/cdefs.h>
32 __KERNEL_RCSID(0, "$NetBSD: pud_dev.c,v 1.5 2009/12/22 14:12:40 pooka Exp $");
34 #include <sys/param.h>
35 #include <sys/buf.h>
36 #include <sys/conf.h>
37 #include <sys/event.h>
38 #include <sys/ioccom.h>
39 #include <sys/kmem.h>
40 #include <sys/poll.h>
41 #include <sys/socketvar.h>
43 #include <dev/pud/pud_sys.h>
46 * b/c independent helpers
49 static int
50 doopenclose(dev_t dev, int flags, int fmt, int class, int type)
52 struct pud_req_openclose pc_oc; /* XXX: stack = stupid */
54 pc_oc.pm_flags = flags;
55 pc_oc.pm_fmt = fmt;
57 return pud_request(dev, &pc_oc, sizeof(pc_oc), class, type);
60 #include <sys/disklabel.h>
62 * XXX: this is not "reentrant". But then again, partinfo isn't
63 * exactly safe in any case.
65 static struct disklabel dl_partinfo;
67 static int
68 doioctl(dev_t dev, u_long cmd, void *data, int flag, int class, int type)
70 struct pud_req_ioctl *pc_ioctl;
71 size_t dlen, allocsize;
72 u_long origcmd = cmd;
73 void *origdata = NULL; /* XXXgcc */
74 int error;
77 * XXX: kludge. This is a horrible abstraction violation, but
78 * then again DIOCGPART is a horrible ioctl (even more horrible
79 * than the generic ioctl). We handle it specially here since
80 * the server in userspace has no chance to handle it. And it's
81 * a common operation used by most file systems. But really, it
82 * should be replaced by something a bit more ... transactional.
84 if (cmd == DIOCGPART) {
85 cmd = DIOCGDINFO;
86 origdata = data;
87 flag = 0;
88 data = &dl_partinfo;
91 dlen = IOCPARM_LEN(cmd);
92 allocsize = sizeof(struct pud_req_ioctl) + dlen;
93 pc_ioctl = kmem_zalloc(allocsize, KM_SLEEP);
95 pc_ioctl->pm_iocmd = cmd;
96 pc_ioctl->pm_flag = flag;
98 if (cmd & IOC_IN)
99 memcpy(pc_ioctl->pm_data, data, dlen);
100 error = pud_request(dev, pc_ioctl, allocsize, class, type);
101 if (error)
102 goto out;
103 if (cmd & IOC_OUT)
104 memcpy(data, pc_ioctl->pm_data, dlen);
107 * In case doing the infamous DIOCGPART, issue the real
108 * ioctl and do pointer arithmetic to figure out the right
109 * partition. We could use DISKPART() too, but this seems
110 * "better".
112 if (origcmd == DIOCGPART) {
113 struct partinfo *pi, *pi_user;
114 int labidx;
116 CTASSERT(sizeof(struct partinfo) <= sizeof(struct disklabel));
118 pc_ioctl->pm_iocmd = DIOCGPART;
119 pc_ioctl->pm_flag = 0;
121 error = pud_request(dev, pc_ioctl, allocsize, class, type);
122 if (error)
123 goto out;
125 pi_user = (struct partinfo *)pc_ioctl->pm_data;
126 labidx = pi_user->part - &pi_user->disklab->d_partitions[0];
127 /* userspace error, but punish caller, since we have no infra */
128 if (labidx >= MAXPARTITIONS) {
129 error = E2BIG;
130 goto out;
133 pi = origdata;
134 pi->disklab = &dl_partinfo;
135 pi->part = &dl_partinfo.d_partitions[labidx];
139 out:
140 kmem_free(pc_ioctl, allocsize);
141 return error;
145 * Block de-vices
148 static dev_type_open(pud_bdev_open);
149 static dev_type_close(pud_bdev_close);
150 static dev_type_strategy(pud_bdev_strategy);
151 static dev_type_ioctl(pud_bdev_ioctl);
152 #if 0
153 static dev_type_dump(pud_bdev_dump);
154 static dev_type_size(pud_bdev_size);
155 #endif
157 struct bdevsw pud_bdevsw = {
158 .d_open = pud_bdev_open,
159 .d_close = pud_bdev_close,
160 .d_strategy = pud_bdev_strategy,
161 .d_ioctl = pud_bdev_ioctl,
162 #if 0
163 .d_dump = pud_bdev_dump,
164 .d_psize = pud_bdev_size,
165 #endif
168 static int
169 pud_bdev_open(dev_t dev, int flags, int fmt, lwp_t *l)
172 return doopenclose(dev, flags, fmt, PUD_REQ_BDEV, PUD_BDEV_OPEN);
175 static int
176 pud_bdev_close(dev_t dev, int flags, int fmt, lwp_t *l)
179 return doopenclose(dev, flags, fmt, PUD_REQ_BDEV, PUD_BDEV_CLOSE);
182 static void
183 pud_bdev_strategy(struct buf *bp)
185 struct pud_req_readwrite *pc_rw;
186 size_t allocsize;
187 int error;
189 allocsize = sizeof(struct pud_req_readwrite) + bp->b_bcount;
190 pc_rw = kmem_zalloc(allocsize, KM_SLEEP);
192 pc_rw->pm_offset = bp->b_blkno << DEV_BSHIFT;
193 pc_rw->pm_resid = bp->b_bcount;
195 if (BUF_ISWRITE(bp))
196 memcpy(pc_rw->pm_data, bp->b_data, bp->b_bcount);
198 error = pud_request(bp->b_dev, pc_rw, allocsize, PUD_REQ_BDEV,
199 BUF_ISREAD(bp) ? PUD_BDEV_STRATREAD : PUD_BDEV_STRATWRITE);
200 if (error)
201 goto out;
203 if (pc_rw->pm_resid > bp->b_bcount) {
204 error = EINVAL;
205 goto out;
208 if (BUF_ISREAD(bp))
209 memcpy(bp->b_data,pc_rw->pm_data,bp->b_bcount-pc_rw->pm_resid);
211 bp->b_resid = pc_rw->pm_resid;
213 out:
214 kmem_free(pc_rw, allocsize);
215 bp->b_error = error;
216 biodone(bp);
220 pud_bdev_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l)
223 return doioctl(dev, cmd, data, flag, PUD_REQ_BDEV, PUD_BDEV_IOCTL);
226 /* hnmmm */
227 #if 0
229 pud_bdev_dump(dev_t dev, daddr_t addr, void *data, size_t sz)
232 return EOPNOTSUPP;
236 pud_bdev_size(dev_t dev)
239 return 0;
241 #endif
244 * Charrr devices
247 static dev_type_open(pud_cdev_open);
248 static dev_type_close(pud_cdev_close);
249 static dev_type_read(pud_cdev_read);
250 static dev_type_write(pud_cdev_write);
251 static dev_type_ioctl(pud_cdev_ioctl);
252 static dev_type_poll(pud_cdev_poll);
253 static dev_type_mmap(pud_cdev_mmap);
254 static dev_type_kqfilter(pud_cdev_kqfilter);
256 struct cdevsw pud_cdevsw = {
257 .d_open = pud_cdev_open,
258 .d_close = pud_cdev_close,
259 .d_read = pud_cdev_read,
260 .d_write = pud_cdev_write,
261 .d_ioctl = pud_cdev_ioctl,
262 #if 0
263 .d_stop = pud_cdev_stop,
264 .d_tty = pud_cdev_tty,
265 #endif
266 .d_poll = pud_cdev_poll,
267 .d_mmap = pud_cdev_mmap,
268 .d_kqfilter = pud_cdev_kqfilter,
269 .d_flag = D_OTHER,
272 static int
273 pud_cdev_open(dev_t dev, int flags, int fmt, lwp_t *l)
276 return doopenclose(dev, flags, fmt, PUD_REQ_CDEV, PUD_CDEV_OPEN);
279 static int
280 pud_cdev_close(dev_t dev, int flags, int fmt, lwp_t *l)
283 return doopenclose(dev, flags, fmt, PUD_REQ_CDEV, PUD_CDEV_CLOSE);
286 static int
287 pud_cdev_read(dev_t dev, struct uio *uio, int flag)
289 struct pud_creq_read *pc_read;
290 size_t allocsize;
291 int error;
293 allocsize = sizeof(struct pud_creq_read) + uio->uio_resid;
294 pc_read = kmem_zalloc(allocsize, KM_SLEEP);
296 pc_read->pm_offset = uio->uio_offset;
297 pc_read->pm_resid = uio->uio_resid;
299 error = pud_request(dev, pc_read, allocsize,
300 PUD_REQ_CDEV, PUD_CDEV_READ);
301 if (error)
302 goto out;
304 if (pc_read->pm_resid > uio->uio_resid) {
305 error = EINVAL;
306 goto out;
309 error = uiomove(pc_read->pm_data,
310 uio->uio_resid - pc_read->pm_resid, uio);
312 out:
313 kmem_free(pc_read, allocsize);
314 return error;
317 static int
318 pud_cdev_write(dev_t dev, struct uio *uio, int flag)
320 struct pud_creq_write *pc_write;
321 size_t allocsize;
322 int error;
324 allocsize = sizeof(struct pud_creq_write) + uio->uio_resid;
325 pc_write = kmem_zalloc(allocsize, KM_SLEEP);
327 pc_write->pm_offset = uio->uio_offset;
328 pc_write->pm_resid = uio->uio_resid;
330 error = uiomove(pc_write->pm_data, uio->uio_resid, uio);
331 if (error)
332 goto out;
334 error = pud_request(dev, pc_write, allocsize,
335 PUD_REQ_CDEV, PUD_CDEV_WRITE);
336 if (error)
337 goto out;
339 if (pc_write->pm_resid)
340 error = EIO;
342 out:
343 kmem_free(pc_write, allocsize);
344 return error;
347 static int
348 pud_cdev_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l)
351 return doioctl(dev, cmd, data, flag, PUD_REQ_CDEV, PUD_CDEV_IOCTL);
354 static paddr_t
355 pud_cdev_mmap(dev_t dev, off_t off, int flag)
358 return (paddr_t)-1;
361 static int
362 pud_cdev_poll(dev_t dev, int flag, lwp_t *l)
365 return EOPNOTSUPP;
368 static int
369 pud_cdev_kqfilter(dev_t dev, struct knote *kn)
372 return EOPNOTSUPP;