svn commit: r233073 - projects/nand/sys/geom
Grzegorz Bernacki
gber at FreeBSD.org
Sat Mar 17 03:23:15 UTC 2012
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) {
More information about the svn-src-projects
mailing list