2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (C) 2002 Benno Rice <benno@FreeBSD.org>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 #include <sys/cdefs.h>
29 __FBSDID("$FreeBSD$");
31 #include <sys/param.h>
32 #include <sys/systm.h>
34 #include <sys/kernel.h>
35 #include <sys/kthread.h>
36 #include <sys/linker.h>
38 #include <sys/malloc.h>
39 #include <sys/mutex.h>
42 #include <geom/geom.h>
44 #include <dev/ofw/openfirm.h>
46 #define OFWD_BLOCKSIZE 512
50 struct bio_queue_head ofwd_bio_queue;
51 struct mtx ofwd_queue_mtx;
52 ihandle_t ofwd_instance;
54 unsigned ofwd_sectorsize;
55 unsigned ofwd_fwheads;
56 unsigned ofwd_fwsectors;
57 struct proc *ofwd_procp;
58 struct g_geom *ofwd_gp;
59 struct g_provider *ofwd_pp;
62 static g_init_t g_ofwd_init;
63 static g_start_t g_ofwd_start;
64 static g_access_t g_ofwd_access;
66 struct g_class g_ofwd_class = {
70 .start = g_ofwd_start,
71 .access = g_ofwd_access,
74 DECLARE_GEOM_CLASS(g_ofwd_class, g_ofwd);
76 static int ofwd_enable = 0;
77 TUNABLE_INT("kern.ofw.disk", &ofwd_enable);
80 ofwd_startio(struct ofwd_softc *sc, struct bio *bp)
84 r = OF_seek(sc->ofwd_instance, bp->bio_offset);
86 switch (bp->bio_cmd) {
88 r = OF_read(sc->ofwd_instance, (void *)bp->bio_data,
92 r = OF_write(sc->ofwd_instance, (void *)bp->bio_data,
96 if (r != bp->bio_length)
97 panic("ofwd: incorrect i/o count");
104 ofwd_kthread(void *arg)
106 struct ofwd_softc *sc;
111 curthread->td_base_pri = PRIBIO;
114 mtx_lock(&sc->ofwd_queue_mtx);
115 bp = bioq_takefirst(&sc->ofwd_bio_queue);
117 msleep(sc, &sc->ofwd_queue_mtx, PRIBIO | PDROP,
121 mtx_unlock(&sc->ofwd_queue_mtx);
122 if (bp->bio_cmd == BIO_GETATTR) {
125 error = ofwd_startio(sc, bp);
128 bp->bio_completed = bp->bio_length;
129 g_io_deliver(bp, error);
135 g_ofwd_init(struct g_class *mp __unused)
140 struct ofwd_softc *sc;
142 struct g_provider *pp;
146 if (ofwd_enable == 0)
149 ofd = OF_finddevice("ofwdisk");
154 OF_package_to_path(ofd, path, 128);
155 OF_getprop(ofd, "file", fname, sizeof(fname));
156 printf("ofw_disk located at %s, file %s\n", path, fname);
159 printf("ofw_disk: could not create instance\n");
163 sc = (struct ofwd_softc *)malloc(sizeof *sc, M_DEVBUF,
165 bioq_init(&sc->ofwd_bio_queue);
166 mtx_init(&sc->ofwd_queue_mtx, "ofwd bio queue", NULL, MTX_DEF);
167 sc->ofwd_instance = ifd;
168 sc->ofwd_mediasize = (off_t)2 * 33554432;
169 sc->ofwd_sectorsize = OFWD_BLOCKSIZE;
170 sc->ofwd_fwsectors = 0;
171 sc->ofwd_fwheads = 0;
172 error = kproc_create(ofwd_kthread, sc, &sc->ofwd_procp, 0, 0,
179 gp = g_new_geomf(&g_ofwd_class, "ofwd0");
181 pp = g_new_providerf(gp, "ofwd0");
182 pp->mediasize = sc->ofwd_mediasize;
183 pp->sectorsize = sc->ofwd_sectorsize;
186 g_error_provider(pp, 0);
190 g_ofwd_start(struct bio *bp)
192 struct ofwd_softc *sc;
194 sc = bp->bio_to->geom->softc;
195 mtx_lock(&sc->ofwd_queue_mtx);
196 bioq_disksort(&sc->ofwd_bio_queue, bp);
197 mtx_unlock(&sc->ofwd_queue_mtx);
202 g_ofwd_access(struct g_provider *pp, int r, int w, int e)
205 if (pp->geom->softc == NULL)