1*96c646f7Sandvar /* $NetBSD: pud_dev.c,v 1.8 2024/02/04 18:52:36 andvar Exp $ */
2001b8e98Spooka
3001b8e98Spooka /*
4001b8e98Spooka * Copyright (c) 2007 Antti Kantee. All Rights Reserved.
5001b8e98Spooka *
6001b8e98Spooka * Development of this software was supported by the
7001b8e98Spooka * Research Foundation of Helsinki University of Technology
8001b8e98Spooka *
9001b8e98Spooka * Redistribution and use in source and binary forms, with or without
10001b8e98Spooka * modification, are permitted provided that the following conditions
11001b8e98Spooka * are met:
12001b8e98Spooka * 1. Redistributions of source code must retain the above copyright
13001b8e98Spooka * notice, this list of conditions and the following disclaimer.
14001b8e98Spooka * 2. Redistributions in binary form must reproduce the above copyright
15001b8e98Spooka * notice, this list of conditions and the following disclaimer in the
16001b8e98Spooka * documentation and/or other materials provided with the distribution.
17001b8e98Spooka *
18001b8e98Spooka * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
19001b8e98Spooka * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20001b8e98Spooka * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21001b8e98Spooka * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22001b8e98Spooka * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23001b8e98Spooka * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24001b8e98Spooka * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25001b8e98Spooka * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26001b8e98Spooka * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27001b8e98Spooka * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28001b8e98Spooka * SUCH DAMAGE.
29001b8e98Spooka */
30001b8e98Spooka
31001b8e98Spooka #include <sys/cdefs.h>
32*96c646f7Sandvar __KERNEL_RCSID(0, "$NetBSD: pud_dev.c,v 1.8 2024/02/04 18:52:36 andvar Exp $");
33001b8e98Spooka
34001b8e98Spooka #include <sys/param.h>
35001b8e98Spooka #include <sys/buf.h>
36001b8e98Spooka #include <sys/conf.h>
37001b8e98Spooka #include <sys/event.h>
382bde3fa6Spooka #include <sys/ioccom.h>
39001b8e98Spooka #include <sys/kmem.h>
40001b8e98Spooka #include <sys/poll.h>
41001b8e98Spooka #include <sys/socketvar.h>
42001b8e98Spooka
43001b8e98Spooka #include <dev/pud/pud_sys.h>
44001b8e98Spooka
452bde3fa6Spooka /*
462bde3fa6Spooka * b/c independent helpers
472bde3fa6Spooka */
482bde3fa6Spooka
49750d6339Spooka static int
doopenclose(dev_t dev,int flags,int fmt,int class,int type)502bde3fa6Spooka doopenclose(dev_t dev, int flags, int fmt, int class, int type)
51750d6339Spooka {
52750d6339Spooka struct pud_req_openclose pc_oc; /* XXX: stack = stupid */
53750d6339Spooka
54750d6339Spooka pc_oc.pm_flags = flags;
55750d6339Spooka pc_oc.pm_fmt = fmt;
56750d6339Spooka
57750d6339Spooka return pud_request(dev, &pc_oc, sizeof(pc_oc), class, type);
58750d6339Spooka }
59750d6339Spooka
6078932903Spooka #include <sys/disklabel.h>
612bde3fa6Spooka static int
doioctl(dev_t dev,u_long cmd,void * data,int flag,int class,int type)622bde3fa6Spooka doioctl(dev_t dev, u_long cmd, void *data, int flag, int class, int type)
632bde3fa6Spooka {
642bde3fa6Spooka struct pud_req_ioctl *pc_ioctl;
652bde3fa6Spooka size_t dlen, allocsize;
662bde3fa6Spooka int error;
672bde3fa6Spooka
682bde3fa6Spooka dlen = IOCPARM_LEN(cmd);
692bde3fa6Spooka allocsize = sizeof(struct pud_req_ioctl) + dlen;
702bde3fa6Spooka pc_ioctl = kmem_zalloc(allocsize, KM_SLEEP);
712bde3fa6Spooka
722bde3fa6Spooka pc_ioctl->pm_iocmd = cmd;
732bde3fa6Spooka pc_ioctl->pm_flag = flag;
742bde3fa6Spooka
752bde3fa6Spooka if (cmd & IOC_IN)
762bde3fa6Spooka memcpy(pc_ioctl->pm_data, data, dlen);
772bde3fa6Spooka error = pud_request(dev, pc_ioctl, allocsize, class, type);
782bde3fa6Spooka if (error)
792bde3fa6Spooka goto out;
802bde3fa6Spooka if (cmd & IOC_OUT)
812bde3fa6Spooka memcpy(data, pc_ioctl->pm_data, dlen);
822bde3fa6Spooka
832bde3fa6Spooka out:
842bde3fa6Spooka kmem_free(pc_ioctl, allocsize);
852bde3fa6Spooka return error;
862bde3fa6Spooka }
872bde3fa6Spooka
88001b8e98Spooka /*
89001b8e98Spooka * Block de-vices
90001b8e98Spooka */
91001b8e98Spooka
92001b8e98Spooka static dev_type_open(pud_bdev_open);
93001b8e98Spooka static dev_type_close(pud_bdev_close);
94001b8e98Spooka static dev_type_strategy(pud_bdev_strategy);
95001b8e98Spooka static dev_type_ioctl(pud_bdev_ioctl);
96001b8e98Spooka #if 0
97001b8e98Spooka static dev_type_dump(pud_bdev_dump);
98001b8e98Spooka static dev_type_size(pud_bdev_size);
99001b8e98Spooka #endif
100001b8e98Spooka
101001b8e98Spooka struct bdevsw pud_bdevsw = {
102001b8e98Spooka .d_open = pud_bdev_open,
103001b8e98Spooka .d_close = pud_bdev_close,
104001b8e98Spooka .d_strategy = pud_bdev_strategy,
105001b8e98Spooka .d_ioctl = pud_bdev_ioctl,
106001b8e98Spooka #if 0
107001b8e98Spooka .d_dump = pud_bdev_dump,
108001b8e98Spooka .d_psize = pud_bdev_size,
109001b8e98Spooka #endif
110001b8e98Spooka };
111001b8e98Spooka
112001b8e98Spooka static int
pud_bdev_open(dev_t dev,int flags,int fmt,lwp_t * l)113001b8e98Spooka pud_bdev_open(dev_t dev, int flags, int fmt, lwp_t *l)
114001b8e98Spooka {
115001b8e98Spooka
1162bde3fa6Spooka return doopenclose(dev, flags, fmt, PUD_REQ_BDEV, PUD_BDEV_OPEN);
117001b8e98Spooka }
118001b8e98Spooka
119001b8e98Spooka static int
pud_bdev_close(dev_t dev,int flags,int fmt,lwp_t * l)120001b8e98Spooka pud_bdev_close(dev_t dev, int flags, int fmt, lwp_t *l)
121001b8e98Spooka {
122001b8e98Spooka
1232bde3fa6Spooka return doopenclose(dev, flags, fmt, PUD_REQ_BDEV, PUD_BDEV_CLOSE);
124001b8e98Spooka }
125001b8e98Spooka
126001b8e98Spooka static void
pud_bdev_strategy(struct buf * bp)127001b8e98Spooka pud_bdev_strategy(struct buf *bp)
128001b8e98Spooka {
129750d6339Spooka struct pud_req_readwrite *pc_rw;
130750d6339Spooka size_t allocsize;
131750d6339Spooka int error;
132001b8e98Spooka
133750d6339Spooka allocsize = sizeof(struct pud_req_readwrite) + bp->b_bcount;
134750d6339Spooka pc_rw = kmem_zalloc(allocsize, KM_SLEEP);
135750d6339Spooka
136750d6339Spooka pc_rw->pm_offset = bp->b_blkno << DEV_BSHIFT;
137750d6339Spooka pc_rw->pm_resid = bp->b_bcount;
138750d6339Spooka
139750d6339Spooka if (BUF_ISWRITE(bp))
140750d6339Spooka memcpy(pc_rw->pm_data, bp->b_data, bp->b_bcount);
141750d6339Spooka
142750d6339Spooka error = pud_request(bp->b_dev, pc_rw, allocsize, PUD_REQ_BDEV,
143750d6339Spooka BUF_ISREAD(bp) ? PUD_BDEV_STRATREAD : PUD_BDEV_STRATWRITE);
144750d6339Spooka if (error)
145750d6339Spooka goto out;
146750d6339Spooka
147750d6339Spooka if (pc_rw->pm_resid > bp->b_bcount) {
148750d6339Spooka error = EINVAL;
149750d6339Spooka goto out;
150750d6339Spooka }
151750d6339Spooka
152750d6339Spooka if (BUF_ISREAD(bp))
153750d6339Spooka memcpy(bp->b_data,pc_rw->pm_data,bp->b_bcount-pc_rw->pm_resid);
154750d6339Spooka
155750d6339Spooka bp->b_resid = pc_rw->pm_resid;
156750d6339Spooka
157750d6339Spooka out:
158750d6339Spooka kmem_free(pc_rw, allocsize);
159750d6339Spooka bp->b_error = error;
160001b8e98Spooka biodone(bp);
161001b8e98Spooka }
162001b8e98Spooka
163001b8e98Spooka int
pud_bdev_ioctl(dev_t dev,u_long cmd,void * data,int flag,lwp_t * l)1642bde3fa6Spooka pud_bdev_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l)
165001b8e98Spooka {
166001b8e98Spooka
1672bde3fa6Spooka return doioctl(dev, cmd, data, flag, PUD_REQ_BDEV, PUD_BDEV_IOCTL);
168001b8e98Spooka }
169001b8e98Spooka
170001b8e98Spooka /* hnmmm */
171001b8e98Spooka #if 0
172001b8e98Spooka int
173001b8e98Spooka pud_bdev_dump(dev_t dev, daddr_t addr, void *data, size_t sz)
174001b8e98Spooka {
175001b8e98Spooka
176001b8e98Spooka return EOPNOTSUPP;
177001b8e98Spooka }
178001b8e98Spooka
179001b8e98Spooka int
180001b8e98Spooka pud_bdev_size(dev_t dev)
181001b8e98Spooka {
182001b8e98Spooka
183001b8e98Spooka return 0;
184001b8e98Spooka }
185001b8e98Spooka #endif
186001b8e98Spooka
187001b8e98Spooka /*
188*96c646f7Sandvar * Char devices
189001b8e98Spooka */
190001b8e98Spooka
191001b8e98Spooka static dev_type_open(pud_cdev_open);
192001b8e98Spooka static dev_type_close(pud_cdev_close);
193001b8e98Spooka static dev_type_read(pud_cdev_read);
194001b8e98Spooka static dev_type_write(pud_cdev_write);
195001b8e98Spooka static dev_type_ioctl(pud_cdev_ioctl);
196001b8e98Spooka static dev_type_poll(pud_cdev_poll);
197001b8e98Spooka static dev_type_mmap(pud_cdev_mmap);
198001b8e98Spooka static dev_type_kqfilter(pud_cdev_kqfilter);
199001b8e98Spooka
200001b8e98Spooka struct cdevsw pud_cdevsw = {
201001b8e98Spooka .d_open = pud_cdev_open,
202001b8e98Spooka .d_close = pud_cdev_close,
203001b8e98Spooka .d_read = pud_cdev_read,
204001b8e98Spooka .d_write = pud_cdev_write,
205001b8e98Spooka .d_ioctl = pud_cdev_ioctl,
206001b8e98Spooka #if 0
207001b8e98Spooka .d_stop = pud_cdev_stop,
208001b8e98Spooka .d_tty = pud_cdev_tty,
209001b8e98Spooka #endif
210001b8e98Spooka .d_poll = pud_cdev_poll,
211001b8e98Spooka .d_mmap = pud_cdev_mmap,
212001b8e98Spooka .d_kqfilter = pud_cdev_kqfilter,
213001b8e98Spooka .d_flag = D_OTHER,
214001b8e98Spooka };
215001b8e98Spooka
216001b8e98Spooka static int
pud_cdev_open(dev_t dev,int flags,int fmt,lwp_t * l)217001b8e98Spooka pud_cdev_open(dev_t dev, int flags, int fmt, lwp_t *l)
218001b8e98Spooka {
219001b8e98Spooka
2202bde3fa6Spooka return doopenclose(dev, flags, fmt, PUD_REQ_CDEV, PUD_CDEV_OPEN);
221001b8e98Spooka }
222001b8e98Spooka
223001b8e98Spooka static int
pud_cdev_close(dev_t dev,int flags,int fmt,lwp_t * l)224001b8e98Spooka pud_cdev_close(dev_t dev, int flags, int fmt, lwp_t *l)
225001b8e98Spooka {
226001b8e98Spooka
2276c9d0b51Spooka return doopenclose(dev, flags, fmt, PUD_REQ_CDEV, PUD_CDEV_CLOSE);
228001b8e98Spooka }
229001b8e98Spooka
230001b8e98Spooka static int
pud_cdev_read(dev_t dev,struct uio * uio,int flag)231001b8e98Spooka pud_cdev_read(dev_t dev, struct uio *uio, int flag)
232001b8e98Spooka {
233001b8e98Spooka struct pud_creq_read *pc_read;
234001b8e98Spooka size_t allocsize;
235001b8e98Spooka int error;
236001b8e98Spooka
237001b8e98Spooka allocsize = sizeof(struct pud_creq_read) + uio->uio_resid;
238001b8e98Spooka pc_read = kmem_zalloc(allocsize, KM_SLEEP);
239001b8e98Spooka
240001b8e98Spooka pc_read->pm_offset = uio->uio_offset;
241001b8e98Spooka pc_read->pm_resid = uio->uio_resid;
242001b8e98Spooka
243001b8e98Spooka error = pud_request(dev, pc_read, allocsize,
244001b8e98Spooka PUD_REQ_CDEV, PUD_CDEV_READ);
245001b8e98Spooka if (error)
246001b8e98Spooka goto out;
247001b8e98Spooka
248001b8e98Spooka if (pc_read->pm_resid > uio->uio_resid) {
249001b8e98Spooka error = EINVAL;
250001b8e98Spooka goto out;
251001b8e98Spooka }
252001b8e98Spooka
253750d6339Spooka error = uiomove(pc_read->pm_data,
254750d6339Spooka uio->uio_resid - pc_read->pm_resid, uio);
255001b8e98Spooka
256001b8e98Spooka out:
257001b8e98Spooka kmem_free(pc_read, allocsize);
258001b8e98Spooka return error;
259001b8e98Spooka }
260001b8e98Spooka
261001b8e98Spooka static int
pud_cdev_write(dev_t dev,struct uio * uio,int flag)262001b8e98Spooka pud_cdev_write(dev_t dev, struct uio *uio, int flag)
263001b8e98Spooka {
264001b8e98Spooka struct pud_creq_write *pc_write;
265001b8e98Spooka size_t allocsize;
266001b8e98Spooka int error;
267001b8e98Spooka
268001b8e98Spooka allocsize = sizeof(struct pud_creq_write) + uio->uio_resid;
269001b8e98Spooka pc_write = kmem_zalloc(allocsize, KM_SLEEP);
270001b8e98Spooka
271001b8e98Spooka pc_write->pm_offset = uio->uio_offset;
272001b8e98Spooka pc_write->pm_resid = uio->uio_resid;
273001b8e98Spooka
274001b8e98Spooka error = uiomove(pc_write->pm_data, uio->uio_resid, uio);
275001b8e98Spooka if (error)
276001b8e98Spooka goto out;
277001b8e98Spooka
278001b8e98Spooka error = pud_request(dev, pc_write, allocsize,
279001b8e98Spooka PUD_REQ_CDEV, PUD_CDEV_WRITE);
280001b8e98Spooka if (error)
281001b8e98Spooka goto out;
282001b8e98Spooka
283001b8e98Spooka if (pc_write->pm_resid)
284001b8e98Spooka error = EIO;
285001b8e98Spooka
286001b8e98Spooka out:
287001b8e98Spooka kmem_free(pc_write, allocsize);
288001b8e98Spooka return error;
289001b8e98Spooka }
290001b8e98Spooka
291001b8e98Spooka static int
pud_cdev_ioctl(dev_t dev,u_long cmd,void * data,int flag,lwp_t * l)292001b8e98Spooka pud_cdev_ioctl(dev_t dev, u_long cmd, void *data, int flag, lwp_t *l)
293001b8e98Spooka {
294001b8e98Spooka
2952bde3fa6Spooka return doioctl(dev, cmd, data, flag, PUD_REQ_CDEV, PUD_CDEV_IOCTL);
296001b8e98Spooka }
297001b8e98Spooka
298001b8e98Spooka static paddr_t
pud_cdev_mmap(dev_t dev,off_t off,int flag)299001b8e98Spooka pud_cdev_mmap(dev_t dev, off_t off, int flag)
300001b8e98Spooka {
301001b8e98Spooka
3022f06310fSpooka return (paddr_t)-1;
3032f06310fSpooka }
3042f06310fSpooka
3052f06310fSpooka static int
pud_cdev_poll(dev_t dev,int flag,lwp_t * l)3062f06310fSpooka pud_cdev_poll(dev_t dev, int flag, lwp_t *l)
3072f06310fSpooka {
3082f06310fSpooka
309001b8e98Spooka return EOPNOTSUPP;
310001b8e98Spooka }
311001b8e98Spooka
312001b8e98Spooka static int
pud_cdev_kqfilter(dev_t dev,struct knote * kn)313001b8e98Spooka pud_cdev_kqfilter(dev_t dev, struct knote *kn)
314001b8e98Spooka {
315001b8e98Spooka
316001b8e98Spooka return EOPNOTSUPP;
317001b8e98Spooka }
318