FreeBSD/Linux Kernel Cross Reference
sys/dev/ofw/ofw_disk.c
1 /*-
2 * Copyright (C) 2002 Benno Rice <benno@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY Benno Rice ``AS IS'' AND ANY EXPRESS OR
15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17 * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
18 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
20 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
21 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
22 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include <sys/cdefs.h>
27 __FBSDID("$FreeBSD: releng/9.0/sys/dev/ofw/ofw_disk.c 194139 2009-06-14 00:15:26Z marius $");
28
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/bio.h>
32 #include <sys/kernel.h>
33 #include <sys/kthread.h>
34 #include <sys/linker.h>
35 #include <sys/lock.h>
36 #include <sys/malloc.h>
37 #include <sys/mutex.h>
38 #include <sys/proc.h>
39
40 #include <geom/geom.h>
41
42 #include <dev/ofw/openfirm.h>
43
44 #define OFWD_BLOCKSIZE 512
45
46 struct ofwd_softc
47 {
48 struct bio_queue_head ofwd_bio_queue;
49 struct mtx ofwd_queue_mtx;
50 ihandle_t ofwd_instance;
51 off_t ofwd_mediasize;
52 unsigned ofwd_sectorsize;
53 unsigned ofwd_fwheads;
54 unsigned ofwd_fwsectors;
55 struct proc *ofwd_procp;
56 struct g_geom *ofwd_gp;
57 struct g_provider *ofwd_pp;
58 } ofwd_softc;
59
60 static g_init_t g_ofwd_init;
61 static g_start_t g_ofwd_start;
62 static g_access_t g_ofwd_access;
63
64 struct g_class g_ofwd_class = {
65 .name = "OFWD",
66 .version = G_VERSION,
67 .init = g_ofwd_init,
68 .start = g_ofwd_start,
69 .access = g_ofwd_access,
70 };
71
72 DECLARE_GEOM_CLASS(g_ofwd_class, g_ofwd);
73
74 static int ofwd_enable = 0;
75 TUNABLE_INT("kern.ofw.disk", &ofwd_enable);
76
77 static int
78 ofwd_startio(struct ofwd_softc *sc, struct bio *bp)
79 {
80 u_int r;
81
82 r = OF_seek(sc->ofwd_instance, bp->bio_offset);
83
84 switch (bp->bio_cmd) {
85 case BIO_READ:
86 r = OF_read(sc->ofwd_instance, (void *)bp->bio_data,
87 bp->bio_length);
88 break;
89 case BIO_WRITE:
90 r = OF_write(sc->ofwd_instance, (void *)bp->bio_data,
91 bp->bio_length);
92 break;
93 }
94 if (r != bp->bio_length)
95 panic("ofwd: incorrect i/o count");
96
97 bp->bio_resid = 0;
98 return (0);
99 }
100
101 static void
102 ofwd_kthread(void *arg)
103 {
104 struct ofwd_softc *sc;
105 struct bio *bp;
106 int error;
107
108 sc = arg;
109 curthread->td_base_pri = PRIBIO;
110
111 for (;;) {
112 mtx_lock(&sc->ofwd_queue_mtx);
113 bp = bioq_takefirst(&sc->ofwd_bio_queue);
114 if (!bp) {
115 msleep(sc, &sc->ofwd_queue_mtx, PRIBIO | PDROP,
116 "ofwdwait", 0);
117 continue;
118 }
119 mtx_unlock(&sc->ofwd_queue_mtx);
120 if (bp->bio_cmd == BIO_GETATTR) {
121 error = EOPNOTSUPP;
122 } else
123 error = ofwd_startio(sc, bp);
124
125 if (error != -1) {
126 bp->bio_completed = bp->bio_length;
127 g_io_deliver(bp, error);
128 }
129 }
130 }
131
132 static void
133 g_ofwd_init(struct g_class *mp __unused)
134 {
135 char path[128];
136 char fname[32];
137 phandle_t ofd;
138 struct ofwd_softc *sc;
139 struct g_geom *gp;
140 struct g_provider *pp;
141 ihandle_t ifd;
142 int error;
143
144 if (ofwd_enable == 0)
145 return;
146
147 ofd = OF_finddevice("ofwdisk");
148 if (ofd == -1)
149 return;
150
151 bzero(path, 128);
152 OF_package_to_path(ofd, path, 128);
153 OF_getprop(ofd, "file", fname, sizeof(fname));
154 printf("ofw_disk located at %s, file %s\n", path, fname);
155 ifd = OF_open(path);
156 if (ifd == -1) {
157 printf("ofw_disk: could not create instance\n");
158 return;
159 }
160
161 sc = (struct ofwd_softc *)malloc(sizeof *sc, M_DEVBUF,
162 M_WAITOK | M_ZERO);
163 bioq_init(&sc->ofwd_bio_queue);
164 mtx_init(&sc->ofwd_queue_mtx, "ofwd bio queue", NULL, MTX_DEF);
165 sc->ofwd_instance = ifd;
166 sc->ofwd_mediasize = (off_t)2 * 33554432;
167 sc->ofwd_sectorsize = OFWD_BLOCKSIZE;
168 sc->ofwd_fwsectors = 0;
169 sc->ofwd_fwheads = 0;
170 error = kproc_create(ofwd_kthread, sc, &sc->ofwd_procp, 0, 0,
171 "ofwd0");
172 if (error != 0) {
173 free(sc, M_DEVBUF);
174 return;
175 }
176
177 gp = g_new_geomf(&g_ofwd_class, "ofwd0");
178 gp->softc = sc;
179 pp = g_new_providerf(gp, "ofwd0");
180 pp->mediasize = sc->ofwd_mediasize;
181 pp->sectorsize = sc->ofwd_sectorsize;
182 sc->ofwd_gp = gp;
183 sc->ofwd_pp = pp;
184 g_error_provider(pp, 0);
185 }
186
187 static void
188 g_ofwd_start(struct bio *bp)
189 {
190 struct ofwd_softc *sc;
191
192 sc = bp->bio_to->geom->softc;
193 mtx_lock(&sc->ofwd_queue_mtx);
194 bioq_disksort(&sc->ofwd_bio_queue, bp);
195 mtx_unlock(&sc->ofwd_queue_mtx);
196 wakeup(sc);
197 }
198
199 static int
200 g_ofwd_access(struct g_provider *pp, int r, int w, int e)
201 {
202
203 if (pp->geom->softc == NULL)
204 return (ENXIO);
205 return (0);
206 }
Cache object: adcbcd7b31e538832fbb6087277d3dd2
|