summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorgrehan <grehan@FreeBSD.org>2004-12-21 02:23:35 +0000
committergrehan <grehan@FreeBSD.org>2004-12-21 02:23:35 +0000
commit8a8ad0dddfa253e5daf138f2193095556257d0ce (patch)
tree04eee9fe37a2415076be6d1b0af97c50c487018c /sys
parent2cc4802343782948a044fa6c48d2e49570d35ddc (diff)
downloadFreeBSD-src-8a8ad0dddfa253e5daf138f2193095556257d0ce.zip
FreeBSD-src-8a8ad0dddfa253e5daf138f2193095556257d0ce.tar.gz
GEOMify the OFW disk driver. Code taken unashamedly from
the preload case in dev/md/md.c.
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ofw/ofw_disk.c273
1 files changed, 126 insertions, 147 deletions
diff --git a/sys/dev/ofw/ofw_disk.c b/sys/dev/ofw/ofw_disk.c
index fa6ef22..54a3d2a 100644
--- a/sys/dev/ofw/ofw_disk.c
+++ b/sys/dev/ofw/ofw_disk.c
@@ -31,192 +31,171 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bio.h>
-#include <sys/module.h>
-#include <sys/bus.h>
-#include <sys/conf.h>
#include <sys/kernel.h>
-#include <sys/limits.h>
-#include <geom/geom_disk.h>
+#include <sys/kthread.h>
+#include <sys/linker.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
-#include <dev/ofw/openfirm.h>
+#include <geom/geom.h>
-#include <machine/bus.h>
-#include <machine/md_var.h>
-#include <machine/nexusvar.h>
+#include <dev/ofw/openfirm.h>
#define OFWD_BLOCKSIZE 512
struct ofwd_softc
{
- device_t ofwd_dev;
- struct disk *ofwd_disk;
- phandle_t ofwd_package;
+ struct bio_queue_head ofwd_bio_queue;
+ struct mtx ofwd_queue_mtx;
ihandle_t ofwd_instance;
+ off_t ofwd_mediasize;
+ unsigned ofwd_sectorsize;
+ unsigned ofwd_fwheads;
+ unsigned ofwd_fwsectors;
+ struct proc *ofwd_procp;
+ struct g_geom *ofwd_gp;
+ struct g_provider *ofwd_pp;
+} ofwd_softc;
+
+static g_init_t g_ofwd_init;
+static g_start_t g_ofwd_start;
+static g_access_t g_ofwd_access;
+
+struct g_class g_ofwd_class = {
+ .name = "OFWD",
+ .version = G_VERSION,
+ .init = g_ofwd_init,
+ .start = g_ofwd_start,
+ .access = g_ofwd_access,
};
-/*
- * Disk device bus interface.
- */
-static void ofwd_identify(driver_t *, device_t);
-static int ofwd_probe(device_t);
-static int ofwd_attach(device_t);
-
-static device_method_t ofwd_methods[] = {
- DEVMETHOD(device_identify, ofwd_identify),
- DEVMETHOD(device_probe, ofwd_probe),
- DEVMETHOD(device_attach, ofwd_attach),
- { 0, 0 }
-};
-
-static driver_t ofwd_driver = {
- "ofwd",
- ofwd_methods,
- sizeof(struct ofwd_softc)
-};
-
-static devclass_t ofwd_devclass;
-
-DRIVER_MODULE(ofwd, nexus, ofwd_driver, ofwd_devclass, 0, 0);
+DECLARE_GEOM_CLASS(g_ofwd_class, g_ofwd);
-/*
- * Disk device control interface.
- */
-static disk_strategy_t ofwd_strategy;
-
-/*
- * Handle an I/O request.
- */
-static void
-ofwd_strategy(struct bio *bp)
+static int
+ofwd_startio(struct ofwd_softc *sc, struct bio *bp)
{
- struct ofwd_softc *sc;
- long r;
-
- sc = (struct ofwd_softc *)bp->bio_disk->d_drv1;
-
- if (sc == NULL) {
- printf("ofwd: bio for invalid disk!\n");
- biofinish(bp, NULL, EINVAL);
- return;
- }
-
- bp->bio_resid = bp->bio_bcount;
+ u_int r;
r = OF_seek(sc->ofwd_instance, bp->bio_offset);
- if (r == -1) {
- device_printf(sc->ofwd_dev, "seek failed\n");
- biofinish(bp, NULL, EIO);
- return;
- }
-
- if (bp->bio_cmd == BIO_READ) {
+ switch (bp->bio_cmd) {
+ case BIO_READ:
r = OF_read(sc->ofwd_instance, (void *)bp->bio_data,
- bp->bio_bcount);
- } else {
+ bp->bio_length);
+ break;
+ case BIO_WRITE:
r = OF_write(sc->ofwd_instance, (void *)bp->bio_data,
- bp->bio_bcount);
- }
-
- if (r > bp->bio_bcount)
- panic("ofwd: more bytes read/written than requested");
- if (r == -1) {
- device_printf(sc->ofwd_dev, "r (%ld) < bp->bio_bcount (%ld)\n",
- r, bp->bio_bcount);
- biofinish(bp, NULL, EIO);
- return;
- }
-
- bp->bio_resid -= r;
+ bp->bio_length);
+ break;
+ }
+ if (r != bp->bio_length)
+ panic("ofwd: incorrect i/o count");
+
+ bp->bio_resid = 0;
+ return (0);
+}
- if (r < bp->bio_bcount) {
- device_printf(sc->ofwd_dev, "r (%ld) < bp->bio_bcount (%ld)\n",
- r, bp->bio_bcount);
- biofinish(bp, NULL, EIO); /* XXX: probably not an error */
- return;
+static void
+ofwd_kthread(void *arg)
+{
+ struct ofwd_softc *sc;
+ struct bio *bp;
+ int error;
+
+ sc = arg;
+ curthread->td_base_pri = PRIBIO;
+
+ for (;;) {
+ mtx_lock(&sc->ofwd_queue_mtx);
+ bp = bioq_takefirst(&sc->ofwd_bio_queue);
+ if (!bp) {
+ msleep(sc, &sc->ofwd_queue_mtx, PRIBIO | PDROP,
+ "ofwdwait", 0);
+ continue;
+ }
+ mtx_unlock(&sc->ofwd_queue_mtx);
+ if (bp->bio_cmd == BIO_GETATTR) {
+ error = EOPNOTSUPP;
+ } else
+ error = ofwd_startio(sc, bp);
+
+ if (error != -1) {
+ bp->bio_completed = bp->bio_length;
+ g_io_deliver(bp, error);
+ }
}
- biodone(bp);
- return;
}
-/*
- * Attach the Open Firmware disk to nexus if present.
- */
static void
-ofwd_identify(driver_t *driver, device_t parent)
+g_ofwd_init(struct g_class *mp __unused)
{
- device_t child;
+ struct ofwd_softc *sc;
+ struct g_geom *gp;
+ struct g_provider *pp;
+ char path[128];
+ char fname[32];
phandle_t ofd;
- static char type[8];
+ ihandle_t ifd;
+ int error;
ofd = OF_finddevice("ofwdisk");
if (ofd == -1)
return;
- OF_getprop(ofd, "device_type", type, sizeof(type));
+ bzero(path, 128);
+ OF_package_to_path(ofd, path, 128);
+ OF_getprop(ofd, "file", fname, sizeof(fname));
+ printf("ofw_disk located at %s, file %s\n", path, fname);
+ ifd = OF_open(path);
+ if (ifd == -1) {
+ printf("ofw_disk: could not create instance\n");
+ return;
+ }
- child = BUS_ADD_CHILD(parent, INT_MAX, "ofwd", 0);
- if (child != NULL) {
- nexus_set_device_type(child, type);
- nexus_set_node(child, ofd);
+ sc = (struct ofwd_softc *)malloc(sizeof *sc, M_DEVBUF,
+ M_WAITOK|M_ZERO);
+ bioq_init(&sc->ofwd_bio_queue);
+ mtx_init(&sc->ofwd_queue_mtx, "ofwd bio queue", NULL, MTX_DEF);
+ sc->ofwd_instance = ifd;
+ sc->ofwd_mediasize = (off_t)2*33554432 * OFWD_BLOCKSIZE;
+ sc->ofwd_sectorsize = OFWD_BLOCKSIZE;
+ sc->ofwd_fwsectors = 0;
+ sc->ofwd_fwheads = 0;
+ error = kthread_create(ofwd_kthread, sc, &sc->ofwd_procp, 0, 0,
+ "ofwd0");
+ if (error != 0) {
+ free(sc, M_DEVBUF);
+ return;
}
+
+ gp = g_new_geomf(&g_ofwd_class, "ofwd0");
+ gp->softc = sc;
+ pp = g_new_providerf(gp, "ofwd0");
+ pp->mediasize = sc->ofwd_mediasize;
+ pp->sectorsize = sc->ofwd_sectorsize;
+ sc->ofwd_gp = gp;
+ sc->ofwd_pp = pp;
+ g_error_provider(pp, 0);
}
-/*
- * Probe for an Open Firmware disk.
- */
-static int
-ofwd_probe(device_t dev)
+static void
+g_ofwd_start(struct bio *bp)
{
- char *type;
- char fname[32];
- phandle_t node;
-
- type = nexus_get_device_type(dev);
- node = nexus_get_node(dev);
-
- if (type == NULL ||
- (strcmp(type, "disk") != 0 && strcmp(type, "block") != 0))
- return (ENXIO);
-
- if (OF_getprop(node, "file", fname, sizeof(fname)) == -1)
- return (ENXIO);
+ struct ofwd_softc *sc;
- device_set_desc(dev, "Open Firmware disk");
- return (0);
+ sc = bp->bio_to->geom->softc;
+ mtx_lock(&sc->ofwd_queue_mtx);
+ bioq_disksort(&sc->ofwd_bio_queue, bp);
+ mtx_unlock(&sc->ofwd_queue_mtx);
+ wakeup(sc);
}
static int
-ofwd_attach(device_t dev)
+g_ofwd_access(struct g_provider *pp, int r, int w, int e)
{
- struct ofwd_softc *sc;
- char path[128];
- char fname[32];
-
- sc = device_get_softc(dev);
- sc->ofwd_dev = dev;
- bzero(path, 128);
- OF_package_to_path(nexus_get_node(dev), path, 128);
- OF_getprop(nexus_get_node(dev), "file", fname, sizeof(fname));
- device_printf(dev, "located at %s, file %s\n", path, fname);
- sc->ofwd_instance = OF_open(path);
- if (sc->ofwd_instance == -1) {
- device_printf(dev, "could not create instance\n");
+ if (pp->geom->softc == NULL)
return (ENXIO);
- }
-
- sc->ofwd_disk = disk_alloc();
- sc->ofwd_disk->d_strategy = ofwd_strategy;
- sc->ofwd_disk->d_name = "ofwd";
- sc->ofwd_disk->d_sectorsize = OFWD_BLOCKSIZE;
- sc->ofwd_disk->d_mediasize = (off_t)33554432 * OFWD_BLOCKSIZE;
- sc->ofwd_disk->d_fwsectors = 0;
- sc->ofwd_disk->d_fwheads = 0;
- sc->ofwd_disk->d_drv1 = sc;
- sc->ofwd_disk->d_maxsize = PAGE_SIZE;
- sc->ofwd_disk->d_unit = device_get_unit(dev);
- sc->ofwd_disk->d_flags = DISKFLAG_NEEDSGIANT;
- disk_create(sc->ofwd_disk, DISK_VERSION);
-
- return (0);
+ return (0);
}
OpenPOWER on IntegriCloud