xref: /netbsd-src/sys/dev/pud/pud_dev.c (revision 96c646f762cb6f483f3c55939207c109ca9fc03b)
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