Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 17 Mar 2012 03:23:13 +0000 (UTC)
From:      Grzegorz Bernacki <gber@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r233073 - projects/nand/sys/geom
Message-ID:  <201203170323.q2H3NDCs048073@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: gber
Date: Sat Mar 17 03:23:13 2012
New Revision: 233073
URL: http://svn.freebsd.org/changeset/base/233073

Log:
  Add changes required for proper working of NAND chip geom devices.
  
  Obtained from: Semihalf
  Supported by:  FreeBSD Foundation, Juniper Networks

Modified:
  projects/nand/sys/geom/geom.h
  projects/nand/sys/geom/geom_dev.c
  projects/nand/sys/geom/geom_disk.c
  projects/nand/sys/geom/geom_disk.h
  projects/nand/sys/geom/geom_io.c
  projects/nand/sys/geom/geom_slice.c

Modified: projects/nand/sys/geom/geom.h
==============================================================================
--- projects/nand/sys/geom/geom.h	Sat Mar 17 03:18:28 2012	(r233072)
+++ projects/nand/sys/geom/geom.h	Sat Mar 17 03:23:13 2012	(r233073)
@@ -309,6 +309,8 @@ struct bio *g_alloc_bio(void);
 void * g_read_data(struct g_consumer *cp, off_t offset, off_t length, int *error);
 int g_write_data(struct g_consumer *cp, off_t offset, void *ptr, off_t length);
 int g_delete_data(struct g_consumer *cp, off_t offset, off_t length);
+void *g_read_oob(struct g_consumer *cp, off_t offset, off_t length, int *error);
+int g_write_oob(struct g_consumer *cp, off_t offset, void *ptr, off_t length);
 void g_print_bio(struct bio *bp);
 
 /* geom_kern.c / geom_kernsim.c */

Modified: projects/nand/sys/geom/geom_dev.c
==============================================================================
--- projects/nand/sys/geom/geom_dev.c	Sat Mar 17 03:18:28 2012	(r233072)
+++ projects/nand/sys/geom/geom_dev.c	Sat Mar 17 03:23:13 2012	(r233073)
@@ -311,8 +311,10 @@ g_dev_ioctl(struct cdev *dev, u_long cmd
 	struct g_consumer *cp;
 	struct g_provider *pp;
 	struct g_kerneldump kd;
+	struct nand_oob_request *nand_req;
 	off_t offset, length, chunk;
 	int i, error;
+	void *buf;
 	u_int u;
 
 	gp = dev->si_drv1;
@@ -345,6 +347,16 @@ g_dev_ioctl(struct cdev *dev, u_long cmd
 		if (error == 0 && *(u_int *)data == 0)
 			error = ENOENT;
 		break;
+	case DIOCNOOBSIZE:
+		error = g_io_getattr("NAND::oobsize", cp, &i, data);
+		if (error == 0 && *(u_int *)data == 0)
+			error = ENOENT;
+		break;
+	case DIOCNBLKSIZE:
+		error = g_io_getattr("NAND::blocksize", cp, &i, data);
+		if (error == 0 && *(u_int *)data == 0)
+			error = ENOENT;
+		break;
 	case DIOCGFRONTSTUFF:
 		error = g_io_getattr("GEOM::frontstuff", cp, &i, data);
 		break;
@@ -396,6 +408,28 @@ g_dev_ioctl(struct cdev *dev, u_long cmd
 				break;
 		}
 		break;
+	case DIOCNREADOOB:
+		nand_req = (struct nand_oob_request *)data;
+
+		buf = g_read_oob(cp, nand_req->offset, nand_req->length,
+		    &error);
+		if (error)
+			break;
+
+		error = copyout(buf, nand_req->ubuf, nand_req->length);
+		break;
+	case DIOCNWRITEOOB:
+		nand_req = (struct nand_oob_request *)data;
+
+		buf = g_malloc(nand_req->length, M_WAITOK);
+		error = copyin(nand_req->ubuf, buf, nand_req->length);
+
+		if (error)
+			break;
+
+		error = g_write_oob(cp, nand_req->offset, buf,
+		    nand_req->length);
+		break;
 	case DIOCGIDENT:
 		error = g_io_getattr("GEOM::ident", cp, &i, data);
 		break;

Modified: projects/nand/sys/geom/geom_disk.c
==============================================================================
--- projects/nand/sys/geom/geom_disk.c	Sat Mar 17 03:18:28 2012	(r233072)
+++ projects/nand/sys/geom/geom_disk.c	Sat Mar 17 03:23:13 2012	(r233073)
@@ -368,6 +368,10 @@ g_disk_start(struct bio *bp)
 			break;
 		else if (g_handleattr_int(bp, "GEOM::fwheads", dp->d_fwheads))
 			break;
+		else if (g_handleattr_int(bp, "NAND::oobsize", dp->n_oobsize))
+			break;
+		else if (g_handleattr_int(bp, "NAND::pagesize", dp->n_pagesize))
+			break;
 		else if (g_handleattr_off_t(bp, "GEOM::frontstuff", 0))
 			break;
 		else if (g_handleattr_str(bp, "GEOM::ident", dp->d_ident))

Modified: projects/nand/sys/geom/geom_disk.h
==============================================================================
--- projects/nand/sys/geom/geom_disk.h	Sat Mar 17 03:18:28 2012	(r233072)
+++ projects/nand/sys/geom/geom_disk.h	Sat Mar 17 03:23:13 2012	(r233073)
@@ -86,6 +86,8 @@ struct disk {
 	u_int			d_maxsize;
 	u_int			d_stripeoffset;
 	u_int			d_stripesize;
+	u_int			n_oobsize;
+	u_int			n_pagesize;
 	char			d_ident[DISK_IDENT_SIZE];
 	char			d_descr[DISK_IDENT_SIZE];
 	uint16_t		d_hba_vendor;

Modified: projects/nand/sys/geom/geom_io.c
==============================================================================
--- projects/nand/sys/geom/geom_io.c	Sat Mar 17 03:18:28 2012	(r233072)
+++ projects/nand/sys/geom/geom_io.c	Sat Mar 17 03:23:13 2012	(r233073)
@@ -289,11 +289,13 @@ g_io_check(struct bio *bp)
 	/* Fail if access counters dont allow the operation */
 	switch(bp->bio_cmd) {
 	case BIO_READ:
+	case BIO_READOOB:
 	case BIO_GETATTR:
 		if (cp->acr == 0)
 			return (EPERM);
 		break;
 	case BIO_WRITE:
+	case BIO_WRITEOOB:
 	case BIO_DELETE:
 	case BIO_FLUSH:
 		if (cp->acw == 0)
@@ -759,6 +761,52 @@ g_delete_data(struct g_consumer *cp, off
 	return (error);
 }
 
+void *
+g_read_oob(struct g_consumer *cp, off_t offset, off_t length, int *error)
+{
+	struct bio *bp;
+	void *ptr;
+	int errorc;
+
+	bp = g_alloc_bio();
+	bp->bio_cmd = BIO_READOOB;
+	bp->bio_done = NULL;
+	bp->bio_offset = offset;
+	bp->bio_length = length;
+	ptr = g_malloc(length, M_WAITOK);
+	bp->bio_data = ptr;
+	g_io_request(bp, cp);
+	errorc = biowait(bp, "groob");
+	if (error != NULL)
+		*error = errorc;
+
+	g_destroy_bio(bp);
+	if (errorc) {
+		g_free(ptr);
+		ptr = NULL;
+	}
+
+	return (ptr);
+}
+
+int
+g_write_oob(struct g_consumer *cp, off_t offset, void *ptr, off_t length)
+{
+	struct bio *bp;
+	int error;
+
+	bp = g_alloc_bio();
+	bp->bio_cmd = BIO_WRITEOOB;
+	bp->bio_done = NULL;
+	bp->bio_offset = offset;
+	bp->bio_length = length;
+	bp->bio_data = ptr;
+	g_io_request(bp, cp);
+	error = biowait(bp, "gwoob");
+	g_destroy_bio(bp);
+	return (error);
+}
+
 void
 g_print_bio(struct bio *bp)
 {

Modified: projects/nand/sys/geom/geom_slice.c
==============================================================================
--- projects/nand/sys/geom/geom_slice.c	Sat Mar 17 03:18:28 2012	(r233072)
+++ projects/nand/sys/geom/geom_slice.c	Sat Mar 17 03:23:13 2012	(r233073)
@@ -215,7 +215,9 @@ g_slice_start(struct bio *bp)
 	gsl = &gsp->slices[idx];
 	switch(bp->bio_cmd) {
 	case BIO_READ:
+	case BIO_READOOB:
 	case BIO_WRITE:
+	case BIO_WRITEOOB:
 	case BIO_DELETE:
 		if (bp->bio_offset > gsl->length) {
 			g_io_deliver(bp, EINVAL); /* XXX: EWHAT ? */
@@ -233,8 +235,10 @@ g_slice_start(struct bio *bp)
 			if (t + bp->bio_length <= ghp->offset)
 				continue;
 			switch(bp->bio_cmd) {
-			case BIO_READ:		idx = ghp->ract; break;
-			case BIO_WRITE:		idx = ghp->wact; break;
+			case BIO_READ:
+			case BIO_READOOB:	idx = ghp->ract; break;
+			case BIO_WRITE:
+			case BIO_WRITEOOB:	idx = ghp->wact; break;
 			case BIO_DELETE:	idx = ghp->dact; break;
 			}
 			switch(idx) {



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