Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 10 Mar 2012 07:06:54 +0000 (UTC)
From:      Grzegorz Bernacki <gber@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r232771 - in projects/nand/sys: geom sys
Message-ID:  <201203100706.q2A76sq0044805@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gber
Date: Sat Mar 10 07:06:54 2012
New Revision: 232771
URL: http://svn.freebsd.org/changeset/base/232771

Log:
  Add geom devices for NAND chips
  
  Obtained from: Semihalf
  Supported by:  FreeBSD Foundation, Juniper Networks

Added:
  projects/nand/sys/geom/geom_nand.c
  projects/nand/sys/geom/geom_nand.h
Modified:
  projects/nand/sys/sys/bio.h

Added: projects/nand/sys/geom/geom_nand.c
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/nand/sys/geom/geom_nand.c	Sat Mar 10 07:06:54 2012	(r232771)
@@ -0,0 +1,490 @@
+/*-
+ * Copyright (c) 2002 Poul-Henning Kamp
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * Copyright (c) 2010 Semihalf
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Poul-Henning Kamp
+ * and NAI Labs, the Security Research Division of Network Associates, Inc.
+ * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
+ * DARPA CHATS research program.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The names of the authors may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * From FreeBSD: src/sys/geom/geom_disk.c,v 1.110.2.2 2009/09/15 11:23:59 pjd
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_geom.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/sysctl.h>
+#include <sys/bio.h>
+#include <sys/conf.h>
+#include <sys/fcntl.h>
+#include <sys/malloc.h>
+#include <sys/sysctl.h>
+#include <sys/devicestat.h>
+#include <sys/sbuf.h>
+#include <machine/md_var.h>
+
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <geom/geom.h>
+#include <geom/geom_nand.h>
+#include <geom/geom_int.h>
+
+static struct mtx g_gnand_done_mtx;
+
+static g_access_t g_gnand_access;
+static g_init_t g_gnand_init;
+static g_fini_t g_gnand_fini;
+static g_start_t g_gnand_start;
+static g_ioctl_t g_gnand_ioctl;
+static g_dumpconf_t g_gnand_dumpconf;
+
+static struct g_class g_gnand_class = {
+	.name = "GNAND",
+	.version = G_VERSION,
+	.init = g_gnand_init,
+	.fini = g_gnand_fini,
+	.start = g_gnand_start,
+	.access = g_gnand_access,
+	.ioctl = g_gnand_ioctl,
+	.dumpconf = g_gnand_dumpconf,
+};
+
+static void
+g_gnand_init(struct g_class *mp __unused)
+{
+
+	mtx_init(&g_gnand_done_mtx, "g_gnand_done", NULL, MTX_DEF);
+}
+
+static void
+g_gnand_fini(struct g_class *mp __unused)
+{
+
+	mtx_destroy(&g_gnand_done_mtx);
+}
+
+DECLARE_GEOM_CLASS(g_gnand_class, g_gnand);
+
+static void __inline
+g_gnand_lock_giant(struct gnand *dp)
+{
+	if (dp->d_flags & DISKFLAG_NEEDSGIANT)
+		mtx_lock(&Giant);
+}
+
+static void __inline
+g_gnand_unlock_giant(struct gnand *dp)
+{
+	if (dp->d_flags & DISKFLAG_NEEDSGIANT)
+		mtx_unlock(&Giant);
+}
+
+static int
+g_gnand_access(struct g_provider *pp, int r, int w, int e)
+{
+	struct gnand *dp;
+	int error;
+
+	g_trace(G_T_ACCESS, "g_gnand_access(%s, %d, %d, %d)",
+	    pp->name, r, w, e);
+	g_topology_assert();
+	dp = pp->geom->softc;
+	if (dp == NULL || dp->d_destroyed) {
+		/*
+		 * Allow decreasing access count even if gnand is not
+		 * avaliable anymore.
+		 */
+		if (r <= 0 && w <= 0 && e <= 0)
+			return (0);
+		return (ENXIO);
+	}
+	r += pp->acr;
+	w += pp->acw;
+	e += pp->ace;
+	error = 0;
+	if ((pp->acr + pp->acw + pp->ace) == 0 && (r + w + e) > 0) {
+		if (dp->d_open != NULL) {
+			g_gnand_lock_giant(dp);
+			error = dp->d_open(dp);
+			if (bootverbose && error != 0)
+				printf("Opened gnand %s -> %d\n",
+				    pp->name, error);
+			g_gnand_unlock_giant(dp);
+		}
+		pp->mediasize = dp->d_mediasize;
+		pp->sectorsize = dp->d_sectorsize;
+		dp->d_flags |= DISKFLAG_OPEN;
+		if (dp->d_maxsize == 0) {
+			printf("WARNING: Disk drive %s%d has no d_maxsize\n",
+			    dp->d_name, dp->d_unit);
+			dp->d_maxsize = DFLTPHYS;
+		}
+	} else if ((pp->acr + pp->acw + pp->ace) > 0 && (r + w + e) == 0) {
+		if (dp->d_close != NULL) {
+			g_gnand_lock_giant(dp);
+			error = dp->d_close(dp);
+			if (error != 0)
+				printf("Closed gnand %s -> %d\n",
+				    pp->name, error);
+			g_gnand_unlock_giant(dp);
+		}
+		dp->d_flags &= ~DISKFLAG_OPEN;
+	}
+	return (error);
+}
+
+static void
+g_gnand_done(struct bio *bp)
+{
+	struct bio *bp2;
+	struct gnand *dp;
+
+	/* See "notes" for why we need a mutex here */
+	/* XXX: will witness accept a mix of Giant/unGiant drivers here ? */
+	mtx_lock(&g_gnand_done_mtx);
+	bp->bio_completed = bp->bio_length - bp->bio_resid;
+
+	bp2 = bp->bio_parent;
+	if (bp2->bio_error == 0)
+		bp2->bio_error = bp->bio_error;
+	bp2->bio_completed += bp->bio_completed;
+	if ((bp->bio_cmd & (BIO_READ|BIO_WRITE|BIO_DELETE)) &&
+	    (dp = bp2->bio_to->geom->softc)) {
+		devstat_end_transaction_bio(dp->d_devstat, bp);
+	}
+	g_destroy_bio(bp);
+	bp2->bio_inbed++;
+	if (bp2->bio_children == bp2->bio_inbed) {
+		bp2->bio_resid = bp2->bio_bcount - bp2->bio_completed;
+		g_io_deliver(bp2, bp2->bio_error);
+	}
+	mtx_unlock(&g_gnand_done_mtx);
+}
+
+static int
+g_gnand_ioctl(struct g_provider *pp, u_long cmd, void * data, int fflag,
+    struct thread *td)
+{
+	struct g_geom *gp;
+	struct gnand *dp;
+	int error;
+
+	gp = pp->geom;
+	dp = gp->softc;
+
+	if (dp->d_ioctl == NULL)
+		return (ENOIOCTL);
+	g_gnand_lock_giant(dp);
+	error = dp->d_ioctl(dp, cmd, data, fflag, td);
+	g_gnand_unlock_giant(dp);
+	return (error);
+}
+
+static void
+g_gnand_start(struct bio *bp)
+{
+	struct bio *bp2, *bp3;
+	struct gnand *dp;
+	int error;
+	off_t off;
+
+	dp = bp->bio_to->geom->softc;
+	if (dp == NULL || dp->d_destroyed) {
+		g_io_deliver(bp, ENXIO);
+		return;
+	}
+	error = EJUSTRETURN;
+	switch(bp->bio_cmd) {
+	case BIO_DELETE:
+	case BIO_READ:
+	case BIO_READOOB:
+	case BIO_WRITE:
+	case BIO_WRITEOOB:
+		g_trace(G_T_BIO,
+		    "g_gnand_start(%p) offset %jd length %jd data %p cmd %d",
+		    bp, (intmax_t)bp->bio_offset, (intmax_t)bp->bio_length,
+		    bp->bio_data, bp->bio_cmd);
+		off = 0;
+		bp3 = NULL;
+		bp2 = g_clone_bio(bp);
+		if (bp2 == NULL) {
+			error = ENOMEM;
+			break;
+		}
+		do {
+			bp2->bio_offset += off;
+			bp2->bio_length -= off;
+			bp2->bio_data += off;
+			if (bp2->bio_length > dp->d_maxsize) {
+				/*
+				 * XXX: If we have a stripesize we should really
+				 * use it here.
+				 */
+				bp2->bio_length = dp->d_maxsize;
+				off += dp->d_maxsize;
+				/*
+				 * To avoid a race, we need to grab the next bio
+				 * before we schedule this one.  See "notes".
+				 */
+				bp3 = g_clone_bio(bp);
+				if (bp3 == NULL)
+					bp->bio_error = ENOMEM;
+			}
+			bp2->bio_done = g_gnand_done;
+			bp2->bio_pblkno = bp2->bio_offset / dp->d_sectorsize;
+			bp2->bio_bcount = bp2->bio_length;
+			bp2->bio_nand = dp;
+			devstat_start_transaction_bio(dp->d_devstat, bp2);
+			g_gnand_lock_giant(dp);
+			dp->d_strategy(bp2);
+			g_gnand_unlock_giant(dp);
+			bp2 = bp3;
+			bp3 = NULL;
+		} while (bp2 != NULL);
+		break;
+	case BIO_GETATTR:
+		if (g_handleattr_int(bp, "NAND::oobsize", dp->d_oobsize))
+			break;
+		else if (g_handleattr(bp, "NAND::device", &(dp->d_dev),
+		    sizeof(device_t)))
+			break;
+		else if (g_handleattr_int(bp, "NAND::pagesize", dp->d_pagesize))
+			break;
+		else if (g_handleattr_int(bp, "NAND::blocksize", dp->d_maxsize))
+			break;
+		else if (g_handleattr_off_t(bp, "GEOM::frontstuff", 0))
+			break;
+		else if (g_handleattr_str(bp, "GEOM::ident", dp->d_ident))
+			break;
+		else
+			error = ENOIOCTL;
+		break;
+	case BIO_FLUSH:
+			g_io_deliver(bp, ENODEV);
+			return;
+	default:
+		error = EOPNOTSUPP;
+		break;
+	}
+	if (error != EJUSTRETURN)
+		g_io_deliver(bp, error);
+	return;
+}
+
+static void
+g_gnand_dumpconf(struct sbuf *sb, const char *indent, struct g_geom *gp,
+    struct g_consumer *cp, struct g_provider *pp)
+{
+	struct gnand *dp;
+
+	dp = gp->softc;
+	if (dp == NULL)
+		return;
+	if (indent == NULL) {
+		sbuf_printf(sb, " page %u", dp->d_pagesize);
+		sbuf_printf(sb, " oob %u", dp->d_oobsize);
+		return;
+	}
+	if (pp != NULL) {
+		sbuf_printf(sb, "%s<pagesize>%u</pagesize>\n",
+		    indent, dp->d_pagesize);
+		sbuf_printf(sb, "%s<oobsize>%u</oobsize>\n",
+		    indent, dp->d_oobsize);
+		sbuf_printf(sb, "%s<blocksize>%u</blocksize>\n",
+		    indent, dp->d_maxsize);
+	}
+}
+
+static void
+g_gnand_create(void *arg, int flag)
+{
+	struct g_geom *gp;
+	struct g_provider *pp;
+	struct gnand *dp;
+
+	if (flag == EV_CANCEL)
+		return;
+	g_topology_assert();
+	dp = arg;
+	gp = g_new_geomf(&g_gnand_class, "%s%d", dp->d_name, dp->d_unit);
+	gp->softc = dp;
+	pp = g_new_providerf(gp, "%s", gp->name);
+	pp->mediasize = dp->d_mediasize;
+	pp->sectorsize = dp->d_sectorsize;
+	if (dp->d_flags & DISKFLAG_CANDELETE)
+		pp->flags |= G_PF_CANDELETE;
+	pp->stripeoffset = dp->d_stripeoffset;
+	pp->stripesize = dp->d_stripesize;
+	if (bootverbose)
+		printf("GEOM: new gnand %s\n", gp->name);
+	dp->d_geom = gp;
+	g_error_provider(pp, 0);
+}
+
+static void
+g_gnand_destroy(void *ptr, int flag)
+{
+	struct gnand *dp;
+	struct g_geom *gp;
+
+	g_topology_assert();
+	dp = ptr;
+	gp = dp->d_geom;
+	if (gp != NULL) {
+		gp->softc = NULL;
+		g_wither_geom(gp, ENXIO);
+	}
+	g_free(dp);
+}
+
+/*
+ * We only allow [a-zA-Z0-9-_@#%.:] characters, the rest is converted to 'x<HH>'.
+ */
+static void
+g_gnand_ident_adjust(char *ident, size_t size)
+{
+	char newid[DISK_IDENT_SIZE], tmp[4];
+	size_t len;
+	char *p;
+
+	bzero(newid, sizeof(newid));
+	len = 0;
+	for (p = ident; *p != '\0' && len < sizeof(newid) - 1; p++) {
+		switch (*p) {
+		default:
+			if ((*p < 'a' || *p > 'z') &&
+			    (*p < 'A' || *p > 'Z') &&
+			    (*p < '0' || *p > '9')) {
+				snprintf(tmp, sizeof(tmp), "x%02hhx", *p);
+				strlcat(newid, tmp, sizeof(newid));
+				len += 3;
+				break;
+			}
+			/* FALLTHROUGH */
+		case '-':
+		case '_':
+		case '@':
+		case '#':
+		case '%':
+		case '.':
+		case ':':
+			newid[len++] = *p;
+			break;
+		}
+	}
+	bzero(ident, size);
+	strlcpy(ident, newid, size);
+}
+
+struct gnand *
+gnand_alloc()
+{
+	struct gnand *dp;
+
+	dp = g_malloc(sizeof *dp, M_WAITOK | M_ZERO);
+	return (dp);
+}
+
+void
+gnand_create(struct gnand *dp)
+{
+
+	KASSERT(dp->d_strategy != NULL, ("gnand_create need d_strategy"));
+	KASSERT(dp->d_name != NULL, ("gnand_create need d_name"));
+	KASSERT(*dp->d_name != 0, ("gnand_create need d_name"));
+	KASSERT(strlen(dp->d_name) < SPECNAMELEN - 4, ("gnand name too long"));
+	if (dp->d_devstat == NULL)
+		dp->d_devstat = devstat_new_entry(dp->d_name, dp->d_unit,
+		    dp->d_sectorsize, DEVSTAT_ALL_SUPPORTED,
+		    DEVSTAT_TYPE_DIRECT, DEVSTAT_PRIORITY_MAX);
+	dp->d_geom = NULL;
+	g_gnand_ident_adjust(dp->d_ident, sizeof(dp->d_ident));
+	g_post_event(g_gnand_create, dp, M_WAITOK, dp, NULL);
+}
+
+void
+gnand_destroy(struct gnand *dp)
+{
+
+	g_cancel_event(dp);
+	dp->d_destroyed = 1;
+	if (dp->d_devstat != NULL)
+		devstat_remove_entry(dp->d_devstat);
+	g_post_event(g_gnand_destroy, dp, M_WAITOK, NULL);
+}
+
+void
+gnand_gone(struct gnand *dp)
+{
+	struct g_geom *gp;
+	struct g_provider *pp;
+
+	gp = dp->d_geom;
+	if (gp != NULL)
+		LIST_FOREACH(pp, &gp->provider, provider)
+			g_wither_provider(pp, ENXIO);
+}
+
+static void
+g_kern_gnands(void *p, int flag __unused)
+{
+	struct sbuf *sb;
+	struct g_geom *gp;
+	char *sp;
+
+	sb = p;
+	sp = "";
+	g_topology_assert();
+	LIST_FOREACH(gp, &g_gnand_class.geom, geom) {
+		sbuf_printf(sb, "%s%s", sp, gp->name);
+		sp = " ";
+	}
+	sbuf_finish(sb);
+}
+
+static int
+sysctl_gnands(SYSCTL_HANDLER_ARGS)
+{
+	int error;
+	struct sbuf *sb;
+
+	sb = sbuf_new_auto();
+	g_waitfor_event(g_kern_gnands, sb, M_WAITOK, NULL);
+	error = SYSCTL_OUT(req, sbuf_data(sb), sbuf_len(sb) + 1);
+	sbuf_delete(sb);
+	return (error);
+}
+
+SYSCTL_PROC(_kern, OID_AUTO, gnands, CTLTYPE_STRING | CTLFLAG_RD |
+    CTLFLAG_MPSAFE, 0, 0, sysctl_gnands, "A", "names of available gnands");

Added: projects/nand/sys/geom/geom_nand.h
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ projects/nand/sys/geom/geom_nand.h	Sat Mar 10 07:06:54 2012	(r232771)
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 2003 Poul-Henning Kamp
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by Poul-Henning Kamp
+ * and NAI Labs, the Security Research Division of Network Associates, Inc.
+ * under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
+ * DARPA CHATS research program.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. The names of the authors may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * From FreeBSD: src/sys/geom/geom_gnand.h,v 1.9 2009/04/10 04:08:34 thompsa
+ */
+
+#ifndef _GEOM_GEOM_NAND_H_
+#define _GEOM_GEOM_NAND_H_
+
+#ifdef _KERNEL 
+
+#include <sys/queue.h>
+#include <sys/_lock.h>
+#include <sys/_mutex.h>
+#include <sys/disk.h>
+
+struct gnand;
+
+typedef	int	gnand_open_t(struct gnand *);
+typedef	int	gnand_close_t(struct gnand *);
+typedef	void	gnand_strategy_t(struct bio *bp);
+typedef	int	gnand_ioctl_t(struct gnand *, u_long cmd, void *data,
+			int fflag, struct thread *td);
+		/* NB: gnand_ioctl_t SHALL be cast'able to d_ioctl_t */
+
+struct g_geom;
+struct devstat;
+
+struct gnand {
+	/* Fields which are private to geom_gnand */
+	struct g_geom		*d_geom;
+	struct devstat		*d_devstat;
+	int			d_destroyed;
+
+	/* Shared fields */
+	u_int			d_flags;
+	const char		*d_name;
+	u_int			d_unit;
+	struct bio_queue_head	*d_queue;
+	struct mtx		*d_lock;
+	device_t		d_dev;
+
+	/* Disk methods  */
+	gnand_open_t		*d_open;
+	gnand_close_t		*d_close;
+	gnand_strategy_t	*d_strategy;
+	gnand_ioctl_t		*d_ioctl;
+	dumper_t		*d_dump;
+
+	/* Info fields from driver to geom_gnand.c. Valid when open */
+	u_int			d_sectorsize;
+	off_t			d_mediasize;
+	u_int			d_maxsize;
+	u_int			d_stripeoffset;
+	u_int			d_stripesize;
+	u_int			d_oobsize;
+	u_int			d_pagesize;
+	char			d_ident[DISK_IDENT_SIZE];
+
+	/* Fields private to the driver */
+	void			*d_drv1;
+};
+
+#define DISKFLAG_NEEDSGIANT	0x1
+#define DISKFLAG_OPEN		0x2
+#define DISKFLAG_CANDELETE	0x4
+#define DISKFLAG_CANFLUSHCACHE	0x8
+
+struct gnand *gnand_alloc(void);
+void gnand_create(struct gnand *gnand);
+void gnand_destroy(struct gnand *gnand);
+void gnand_gone(struct gnand *gnand);
+
+#endif /* _KERNEL */
+#endif /* _GEOM_GEOM_NAND_H_ */

Modified: projects/nand/sys/sys/bio.h
==============================================================================
--- projects/nand/sys/sys/bio.h	Sat Mar 10 06:54:37 2012	(r232770)
+++ projects/nand/sys/sys/bio.h	Sat Mar 10 07:06:54 2012	(r232771)
@@ -46,15 +46,19 @@
 #define BIO_DELETE	0x04
 #define BIO_GETATTR	0x08
 #define BIO_FLUSH	0x10
-#define BIO_CMD0	0x20	/* Available for local hacks */
-#define BIO_CMD1	0x40	/* Available for local hacks */
+#define BIO_CMD0	0x20
+#define BIO_CMD1	0x40
 #define BIO_CMD2	0x80	/* Available for local hacks */
 
+#define	BIO_READOOB	BIO_CMD0
+#define	BIO_WRITEOOB	BIO_CMD1
+
 /* bio_flags */
 #define BIO_ERROR	0x01
 #define BIO_DONE	0x02
 #define BIO_ONQUEUE	0x04
 #define BIO_ORDERED	0x08
+#define	BIO_ECC		0x10
 
 #ifdef _KERNEL
 struct disk;
@@ -65,6 +69,7 @@ struct bio;
 
 typedef void bio_task_t(void *);
 
+
 /*
  * The bio structure describes an I/O operation in the kernel.
  */
@@ -74,7 +79,10 @@ struct bio {
 	uint8_t	bio_cflags;		/* Private use by the consumer. */
 	uint8_t	bio_pflags;		/* Private use by the provider. */
 	struct cdev *bio_dev;		/* Device to do I/O on. */
-	struct disk *bio_disk;		/* Valid below geom_disk.c only */
+	union {
+		struct disk *bio_disk;		/* Valid below geom_disk.c only */
+		struct gnand *bio_nand;		/* Valid below geom_disk.c only */
+	} bio_source;
 	off_t	bio_offset;		/* Offset into file. */
 	long	bio_bcount;		/* Valid bytes in buffer. */
 	caddr_t	bio_data;		/* Memory, superblocks, indirect etc. */
@@ -112,6 +120,24 @@ struct bio {
 	daddr_t bio_pblkno;               /* physical block number */
 };
 
+#define	bio_disk		bio_source.bio_disk
+#define	bio_nand		bio_source.bio_nand
+
+/* bio_cmd */
+#define BIO_READ	0x01
+#define BIO_WRITE	0x02
+#define BIO_DELETE	0x04
+#define BIO_GETATTR	0x08
+#define BIO_FLUSH	0x10
+#define BIO_CMD0	0x20	/* Available for local hacks */
+#define BIO_CMD1	0x40	/* Available for local hacks */
+#define BIO_CMD2	0x80	/* Available for local hacks */
+
+/* bio_flags */
+#define BIO_ERROR	0x01
+#define BIO_DONE	0x02
+#define BIO_ONQUEUE	0x04
+
 struct uio;
 struct devstat;
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201203100706.q2A76sq0044805>