1*82b8cabaSriastradh /* $NetBSD: altmem.c,v 1.6 2017/10/28 04:53:55 riastradh Exp $ */
2143d1198Sjmcneill
3143d1198Sjmcneill /*-
4143d1198Sjmcneill * Copyright (c) 2009 Jared D. McNeill <jmcneill@invisible.ca>
5143d1198Sjmcneill * All rights reserved.
6143d1198Sjmcneill *
7143d1198Sjmcneill * Redistribution and use in source and binary forms, with or without
8143d1198Sjmcneill * modification, are permitted provided that the following conditions
9143d1198Sjmcneill * are met:
10143d1198Sjmcneill * 1. Redistributions of source code must retain the above copyright
11143d1198Sjmcneill * notice, this list of conditions and the following disclaimer.
12143d1198Sjmcneill * 2. The name of the author may not be used to endorse or promote products
13143d1198Sjmcneill * derived from this software without specific prior written permission.
14143d1198Sjmcneill *
15143d1198Sjmcneill * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16143d1198Sjmcneill * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17143d1198Sjmcneill * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18143d1198Sjmcneill * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19143d1198Sjmcneill * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20143d1198Sjmcneill * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21143d1198Sjmcneill * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
22143d1198Sjmcneill * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23143d1198Sjmcneill * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24143d1198Sjmcneill * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25143d1198Sjmcneill * SUCH DAMAGE.
26143d1198Sjmcneill */
27143d1198Sjmcneill
28143d1198Sjmcneill #include <sys/cdefs.h>
29*82b8cabaSriastradh __KERNEL_RCSID(0, "$NetBSD: altmem.c,v 1.6 2017/10/28 04:53:55 riastradh Exp $");
30143d1198Sjmcneill #include <sys/param.h>
31143d1198Sjmcneill #include <sys/types.h>
32143d1198Sjmcneill #include <sys/device.h>
33143d1198Sjmcneill #include <sys/conf.h>
34143d1198Sjmcneill #include <sys/buf.h>
35143d1198Sjmcneill #include <sys/disklabel.h>
36143d1198Sjmcneill #include <sys/disk.h>
37143d1198Sjmcneill
38143d1198Sjmcneill #include <dev/altmem/altmemvar.h>
39143d1198Sjmcneill
40*82b8cabaSriastradh #include "ioconf.h"
41*82b8cabaSriastradh
42143d1198Sjmcneill struct altmem_softc {
43143d1198Sjmcneill device_t sc_dev;
44143d1198Sjmcneill
45143d1198Sjmcneill struct disk sc_dkdev;
46143d1198Sjmcneill
47143d1198Sjmcneill void *sc_cookie;
48143d1198Sjmcneill const struct altmem_memops *sc_memops;
49143d1198Sjmcneill
50143d1198Sjmcneill size_t sc_size;
51143d1198Sjmcneill };
52143d1198Sjmcneill
53143d1198Sjmcneill static dev_type_open(altmemopen);
54143d1198Sjmcneill static dev_type_close(altmemclose);
55143d1198Sjmcneill static dev_type_read(altmemread);
56143d1198Sjmcneill static dev_type_write(altmemwrite);
57143d1198Sjmcneill static dev_type_ioctl(altmemioctl);
58143d1198Sjmcneill static dev_type_strategy(altmemstrategy);
59143d1198Sjmcneill static dev_type_size(altmemsize);
60143d1198Sjmcneill
61143d1198Sjmcneill static int altmem_match(device_t, cfdata_t, void *);
62143d1198Sjmcneill static void altmem_attach(device_t, device_t, void *);
63143d1198Sjmcneill
64143d1198Sjmcneill const struct bdevsw altmem_bdevsw = {
65a68f9396Sdholland .d_open = altmemopen,
66a68f9396Sdholland .d_close = altmemclose,
67a68f9396Sdholland .d_strategy = altmemstrategy,
68a68f9396Sdholland .d_ioctl = altmemioctl,
69a68f9396Sdholland .d_dump = nodump,
70a68f9396Sdholland .d_psize = altmemsize,
718c70ef39Sdholland .d_discard = nodiscard,
72a68f9396Sdholland .d_flag = D_DISK
73143d1198Sjmcneill };
74143d1198Sjmcneill const struct cdevsw altmem_cdevsw = {
75a68f9396Sdholland .d_open = altmemopen,
76a68f9396Sdholland .d_close = altmemclose,
77a68f9396Sdholland .d_read = altmemread,
78a68f9396Sdholland .d_write = altmemwrite,
79a68f9396Sdholland .d_ioctl = altmemioctl,
80a68f9396Sdholland .d_stop = nostop,
81a68f9396Sdholland .d_tty = notty,
82a68f9396Sdholland .d_poll = nopoll,
83a68f9396Sdholland .d_mmap = nommap,
84a68f9396Sdholland .d_kqfilter = nokqfilter,
85f9228f42Sdholland .d_discard = nodiscard,
86a68f9396Sdholland .d_flag = D_DISK
87143d1198Sjmcneill };
886f00c789Smlelstv static struct dkdriver altmemdkdriver = {
896f00c789Smlelstv .d_strategy = altmemstrategy,
906f00c789Smlelstv .d_minphys = minphys
916f00c789Smlelstv };
92143d1198Sjmcneill
93143d1198Sjmcneill CFATTACH_DECL_NEW(altmem, sizeof(struct altmem_softc), altmem_match,
94143d1198Sjmcneill altmem_attach, NULL, NULL);
95143d1198Sjmcneill
96143d1198Sjmcneill static int
altmem_match(device_t parent,cfdata_t match,void * opaque)97143d1198Sjmcneill altmem_match(device_t parent, cfdata_t match, void *opaque)
98143d1198Sjmcneill {
99143d1198Sjmcneill return 1;
100143d1198Sjmcneill }
101143d1198Sjmcneill
102143d1198Sjmcneill static void
altmem_attach(device_t parent,device_t self,void * opaque)103143d1198Sjmcneill altmem_attach(device_t parent, device_t self, void *opaque)
104143d1198Sjmcneill {
105143d1198Sjmcneill struct altmem_softc *sc = device_private(self);
106143d1198Sjmcneill struct altmem_attach_args *aaa = opaque;
107143d1198Sjmcneill char pbuf[9];
108143d1198Sjmcneill
109143d1198Sjmcneill sc->sc_dev = self;
110143d1198Sjmcneill sc->sc_cookie = aaa->cookie;
111143d1198Sjmcneill sc->sc_memops = aaa->memops;
112143d1198Sjmcneill sc->sc_size = sc->sc_memops->getsize(sc->sc_cookie);
113143d1198Sjmcneill
114143d1198Sjmcneill format_bytes(pbuf, sizeof(pbuf), sc->sc_size);
115143d1198Sjmcneill
116143d1198Sjmcneill aprint_naive("\n");
117143d1198Sjmcneill aprint_normal(": %s\n", pbuf);
118143d1198Sjmcneill
119143d1198Sjmcneill disk_init(&sc->sc_dkdev, device_xname(self), &altmemdkdriver);
120143d1198Sjmcneill disk_attach(&sc->sc_dkdev);
121143d1198Sjmcneill }
122143d1198Sjmcneill
123143d1198Sjmcneill static int
altmemsize(dev_t dev)124143d1198Sjmcneill altmemsize(dev_t dev)
125143d1198Sjmcneill {
126143d1198Sjmcneill struct altmem_softc *sc = device_lookup_private(&altmem_cd, DISKUNIT(dev));
127143d1198Sjmcneill if (sc == NULL)
128143d1198Sjmcneill return 0;
129143d1198Sjmcneill return sc->sc_size >> DEV_BSHIFT;
130143d1198Sjmcneill }
131143d1198Sjmcneill
132143d1198Sjmcneill static int
altmemopen(dev_t dev,int flag,int fmt,struct lwp * l)133143d1198Sjmcneill altmemopen(dev_t dev, int flag, int fmt, struct lwp *l)
134143d1198Sjmcneill {
135143d1198Sjmcneill struct altmem_softc *sc = device_lookup_private(&altmem_cd, DISKUNIT(dev));
136143d1198Sjmcneill if (sc == NULL)
137143d1198Sjmcneill return ENXIO;
138143d1198Sjmcneill return 0;
139143d1198Sjmcneill }
140143d1198Sjmcneill
141143d1198Sjmcneill static int
altmemclose(dev_t dev,int flag,int fmt,struct lwp * l)142143d1198Sjmcneill altmemclose(dev_t dev, int flag, int fmt, struct lwp *l)
143143d1198Sjmcneill {
144143d1198Sjmcneill return 0;
145143d1198Sjmcneill }
146143d1198Sjmcneill
147143d1198Sjmcneill static int
altmemread(dev_t dev,struct uio * uio,int flags)148143d1198Sjmcneill altmemread(dev_t dev, struct uio *uio, int flags)
149143d1198Sjmcneill {
150143d1198Sjmcneill if (device_lookup_private(&altmem_cd, DISKUNIT(dev)) == NULL)
151143d1198Sjmcneill return ENXIO;
152143d1198Sjmcneill return physio(altmemstrategy, NULL, dev, B_READ, minphys, uio);
153143d1198Sjmcneill }
154143d1198Sjmcneill
155143d1198Sjmcneill static int
altmemwrite(dev_t dev,struct uio * uio,int flags)156143d1198Sjmcneill altmemwrite(dev_t dev, struct uio *uio, int flags)
157143d1198Sjmcneill {
158143d1198Sjmcneill if (device_lookup_private(&altmem_cd, DISKUNIT(dev)) == NULL)
159143d1198Sjmcneill return ENXIO;
160143d1198Sjmcneill return physio(altmemstrategy, NULL, dev, B_WRITE, minphys, uio);
161143d1198Sjmcneill }
162143d1198Sjmcneill
163143d1198Sjmcneill static void
altmemstrategy(struct buf * bp)164143d1198Sjmcneill altmemstrategy(struct buf *bp)
165143d1198Sjmcneill {
166143d1198Sjmcneill struct altmem_softc *sc = device_lookup_private(&altmem_cd, DISKUNIT(bp->b_dev));
167143d1198Sjmcneill
168143d1198Sjmcneill if (sc == NULL) {
169143d1198Sjmcneill bp->b_error = ENXIO;
170143d1198Sjmcneill biodone(bp);
171143d1198Sjmcneill return;
172143d1198Sjmcneill }
173143d1198Sjmcneill if (bp->b_bcount == 0) {
174143d1198Sjmcneill biodone(bp);
175143d1198Sjmcneill return;
176143d1198Sjmcneill }
177143d1198Sjmcneill
178143d1198Sjmcneill sc->sc_memops->strategy(sc->sc_cookie, bp);
179143d1198Sjmcneill biodone(bp);
180143d1198Sjmcneill }
181143d1198Sjmcneill
182143d1198Sjmcneill static int
altmemioctl(dev_t dev,u_long cmd,void * data,int flag,struct lwp * l)183143d1198Sjmcneill altmemioctl(dev_t dev, u_long cmd, void *data, int flag, struct lwp *l)
184143d1198Sjmcneill {
185143d1198Sjmcneill struct altmem_softc *sc = device_lookup_private(&altmem_cd, DISKUNIT(dev));
186143d1198Sjmcneill struct dkwedge_info *dkw;
187143d1198Sjmcneill
188143d1198Sjmcneill switch (cmd) {
189143d1198Sjmcneill case DIOCGWEDGEINFO:
190143d1198Sjmcneill dkw = (void *)data;
191143d1198Sjmcneill strlcpy(dkw->dkw_devname, device_xname(sc->sc_dev),
192143d1198Sjmcneill sizeof(dkw->dkw_devname));
193143d1198Sjmcneill strlcpy(dkw->dkw_wname, "altmem", sizeof(dkw->dkw_wname));
194143d1198Sjmcneill dkw->dkw_parent[0] = '\0';
195143d1198Sjmcneill dkw->dkw_offset = 0;
196143d1198Sjmcneill dkw->dkw_size = sc->sc_size >> DEV_BSHIFT;
197143d1198Sjmcneill strcpy(dkw->dkw_ptype, DKW_PTYPE_UNUSED);
198143d1198Sjmcneill break;
199143d1198Sjmcneill default:
200143d1198Sjmcneill return ENOTTY;
201143d1198Sjmcneill }
202143d1198Sjmcneill return 0;
203143d1198Sjmcneill }
204