2 * Copyright (c) 2006 Kip Macy
3 * Copyright (c) 2001 Benno Rice
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
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>
45 #include <geom/geom.h>
47 #include <dev/ofw/ofw_bus.h>
48 #include <dev/ofw/ofw_bus_subr.h>
49 #include <dev/ofw/openfirm.h>
52 #include <machine/hv_api.h>
54 #define HVD_BLOCKSIZE 512
58 struct bio_queue_head hvd_bio_queue;
59 struct mtx hvd_queue_mtx;
61 unsigned hvd_sectorsize;
63 unsigned hvd_fwsectors;
64 struct proc *hvd_procp;
65 struct g_geom *hvd_gp;
66 struct g_provider *hvd_pp;
69 static g_init_t g_hvd_init;
70 static g_start_t g_hvd_start;
71 static g_access_t g_hvd_access;
73 struct g_class g_hvd_class = {
78 .access = g_hvd_access,
81 DECLARE_GEOM_CLASS(g_hvd_class, g_hvd);
86 hvd_startio(struct hvd_softc *sc, struct bio *bp)
95 page_off = bp->bio_offset & PAGE_MASK;
98 switch (bp->bio_cmd) {
100 if (bp->bio_length > (PAGE_SIZE - page_off)) {
101 len = rlen = (PAGE_SIZE - page_off);
102 r = hv_sim_read(bp->bio_offset, vtophys((char *)bp->bio_data), rlen);
104 for (; len < bp->bio_length && r == H_EOK; len += PAGE_SIZE) {
105 rlen = (bp->bio_length - len) > PAGE_SIZE ? PAGE_SIZE : bp->bio_length - len;
106 r = hv_sim_read(bp->bio_offset + len, vtophys((char *)bp->bio_data + len), rlen);
111 if (bp->bio_length > (PAGE_SIZE - page_off)) {
112 len = wlen = (PAGE_SIZE - page_off);
113 r = hv_sim_write(bp->bio_offset, vtophys((char *)bp->bio_data), wlen);
115 for (; len < bp->bio_length && r == H_EOK; len += PAGE_SIZE) {
116 wlen = (bp->bio_length - len) > PAGE_SIZE ? PAGE_SIZE : bp->bio_length - len;
117 r = hv_sim_write(bp->bio_offset + len, vtophys((char *)bp->bio_data + len), wlen);
122 panic("invalid I/O");
129 hvd_kthread(void *arg)
131 struct hvd_softc *sc;
136 curthread->td_base_pri = PRIBIO;
139 mtx_lock(&sc->hvd_queue_mtx);
140 bp = bioq_takefirst(&sc->hvd_bio_queue);
142 msleep(sc, &sc->hvd_queue_mtx, PRIBIO | PDROP,
146 mtx_unlock(&sc->hvd_queue_mtx);
147 if (bp->bio_cmd == BIO_GETATTR) {
150 error = hvd_startio(sc, bp);
153 bp->bio_completed = bp->bio_length;
154 g_io_deliver(bp, error);
160 g_hvd_init(struct g_class *mp __unused)
162 struct hvd_softc *sc;
164 struct g_provider *pp;
166 printf("calling g_hvd_init\n");
168 sc = (struct hvd_softc *)malloc(sizeof *sc, M_DEVBUF,
170 bioq_init(&sc->hvd_bio_queue);
171 mtx_init(&sc->hvd_queue_mtx, "hvd bio queue", NULL, MTX_DEF);
172 sc->hvd_mediasize = (off_t)0x20000000;
173 sc->hvd_sectorsize = HVD_BLOCKSIZE;
174 sc->hvd_fwsectors = 0;
176 error = kproc_create(hvd_kthread, sc, &sc->hvd_procp, 0, 0,
183 gp = g_new_geomf(&g_hvd_class, "hvd0");
185 pp = g_new_providerf(gp, "hvd0");
186 pp->mediasize = sc->hvd_mediasize;
187 pp->sectorsize = sc->hvd_sectorsize;
190 g_error_provider(pp, 0);
194 g_hvd_start(struct bio *bp)
196 struct hvd_softc *sc;
198 printf("in hvd_start\n");
200 sc = bp->bio_to->geom->softc;
201 mtx_lock(&sc->hvd_queue_mtx);
202 bioq_disksort(&sc->hvd_bio_queue, bp);
203 mtx_unlock(&sc->hvd_queue_mtx);
208 g_hvd_access(struct g_provider *pp, int r, int w, int e)
211 if (pp->geom->softc == NULL)
217 hvd_probe(device_t dev)
220 if (strcmp(ofw_bus_get_name(dev), "disk"))
223 device_set_desc(dev, "sun4v virtual disk");
230 hvd_attach(device_t dev)
235 static device_method_t hvd_methods[] = {
236 DEVMETHOD(device_probe, hvd_probe),
237 DEVMETHOD(device_attach, hvd_attach),
242 static driver_t hvd_driver = {
249 static devclass_t hvd_devclass;
251 DRIVER_MODULE(hvd, vnex, hvd_driver, hvd_devclass, 0, 0);