summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>2002-03-16 09:24:19 +0000
committerphk <phk@FreeBSD.org>2002-03-16 09:24:19 +0000
commit688687434f7b4bf689cb76a2bfdbcbc2b34bf03d (patch)
treedc23039ef707ddc22810bca9a45c7b8e4a21d815 /sys
parent160859d70870af6d64ca201c85b7a15c6a0a0e46 (diff)
downloadFreeBSD-src-688687434f7b4bf689cb76a2bfdbcbc2b34bf03d.zip
FreeBSD-src-688687434f7b4bf689cb76a2bfdbcbc2b34bf03d.tar.gz
Add a generic and general ioctl pass-through mechanism.
It should now be posible to issue ioctls to SCSI CD drives.
Diffstat (limited to 'sys')
-rw-r--r--sys/geom/geom.h8
-rw-r--r--sys/geom/geom_bsd.c24
-rw-r--r--sys/geom/geom_dev.c60
-rw-r--r--sys/geom/geom_disk.c42
4 files changed, 84 insertions, 50 deletions
diff --git a/sys/geom/geom.h b/sys/geom/geom.h
index 0a3f4807..1249776 100644
--- a/sys/geom/geom.h
+++ b/sys/geom/geom.h
@@ -247,6 +247,12 @@ void * g_read_data(struct g_consumer *cp, off_t offset, off_t length, int *error
/* geom_kern.c / geom_kernsim.c */
void g_init(void);
+struct g_ioctl {
+ u_long cmd;
+ void *data;
+ int fflag;
+ struct thread *td;
+};
#ifdef _KERNEL
@@ -272,7 +278,7 @@ g_free(void *ptr)
}
extern struct sx topology_lock;
-#define g_topology_lock() sx_xlock(&topology_lock)
+#define g_topology_lock() do { mtx_assert(&Giant, MA_NOTOWNED); sx_xlock(&topology_lock); } while (0)
#define g_topology_unlock() sx_xunlock(&topology_lock)
#define g_topology_assert() sx_assert(&topology_lock, SX_XLOCKED)
diff --git a/sys/geom/geom_bsd.c b/sys/geom/geom_bsd.c
index 47e601d..2688be1 100644
--- a/sys/geom/geom_bsd.c
+++ b/sys/geom/geom_bsd.c
@@ -89,20 +89,42 @@ g_bsd_start(struct bio *bp)
struct g_bsd_softc *ms;
struct g_slicer *gsp;
struct partinfo pi;
+ struct g_ioctl *gio;
gp = bp->bio_to->geom;
gsp = gp->softc;
ms = gsp->softc;
+#if 0
if (g_haveattr(bp, "IOCTL::DIOCGDINFO",
&ms->inram,
sizeof ms->inram))
return (1);
- if (!strcmp(bp->bio_attribute, "IOCTL::DIOCGPART")) {
+ else if (!strcmp(bp->bio_attribute, "IOCTL::DIOCGPART")) {
pi.disklab = &ms->inram;
pi.part = &ms->inram.d_partitions[bp->bio_to->index];
if (g_haveattr(bp, "IOCTL::DIOCGPART", &pi, sizeof pi))
return (1);
}
+#endif
+ if (strcmp(bp->bio_attribute, "GEOM::ioctl"))
+ return(0);
+ else if (bp->bio_length != sizeof *gio)
+ return(0);
+ gio = (struct g_ioctl *)bp->bio_data;
+ if (gio->cmd == DIOCGDINFO) {
+ bcopy(&ms->inram, gio->data, sizeof ms->inram);
+ bp->bio_error = 0;
+ g_io_deliver(bp);
+ return (1);
+ }
+ if (gio->cmd == DIOCGPART) {
+ pi.disklab = &ms->inram;
+ pi.part = &ms->inram.d_partitions[bp->bio_to->index];
+ bcopy(&pi, gio->data, sizeof pi);
+ bp->bio_error = 0;
+ g_io_deliver(bp);
+ return (1);
+ }
return (0);
}
diff --git a/sys/geom/geom_dev.c b/sys/geom/geom_dev.c
index 16f4ad5..1a94f18 100644
--- a/sys/geom/geom_dev.c
+++ b/sys/geom/geom_dev.c
@@ -35,7 +35,6 @@
* $FreeBSD$
*/
-
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
@@ -50,7 +49,6 @@
#include <sys/fcntl.h>
#include <geom/geom.h>
-
#define CDEV_MAJOR 4
static d_open_t g_dev_open;
@@ -131,11 +129,9 @@ g_dev_taste(struct g_method *mp, struct g_provider *pp, struct thread *tp __unus
struct g_geom *gp;
struct g_consumer *cp;
static int unit;
-#if 1
u_int secsize;
off_t mediasize;
int error, j;
-#endif
dev_t dev;
g_trace(G_T_TOPOLOGY, "dev_taste(%s,%s)", mp->name, pp->name);
@@ -146,7 +142,6 @@ g_dev_taste(struct g_method *mp, struct g_provider *pp, struct thread *tp __unus
gp = g_new_geomf(mp, pp->name);
cp = g_new_consumer(gp);
g_attach(cp, pp);
-#if 1
error = g_access_rel(cp, 1, 0, 0);
g_topology_unlock();
if (!error) {
@@ -171,17 +166,12 @@ g_dev_taste(struct g_method *mp, struct g_provider *pp, struct thread *tp __unus
secsize = 512;
mediasize = 0;
}
-#else
- g_topology_unlock();
-#endif
mtx_lock(&Giant);
-#if 1
if (mediasize != 0)
printf("GEOM: \"%s\" %lld bytes in %lld sectors of %u bytes\n",
pp->name, mediasize, mediasize / secsize, secsize);
else
printf("GEOM: \"%s\" (size unavailable)\n", pp->name);
-#endif
dev = make_dev(&g_dev_cdevsw, unit++,
UID_ROOT, GID_WHEEL, 0600, gp->name);
gp->softc = dev;
@@ -249,22 +239,38 @@ g_dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
{
struct g_geom *gp;
struct g_consumer *cp;
- char *nm;
int i, error;
+ struct g_ioctl *gio;
gp = dev->si_drv1;
cp = dev->si_drv2;
error = 0;
mtx_unlock(&Giant);
- switch (cmd) {
- case DIOCGDINFO: nm = "IOCTL::DIOCGDINFO"; break;
- case DIOCGDVIRGIN: nm = "IOCTL::DIOCGDVIRGIN"; break;
- case DIOCGPART: nm = "IOCTL::DIOCGPART"; break;
- default: nm = "?"; break;
+
+ gio = g_malloc(sizeof *gio, M_WAITOK);
+ gio->cmd = cmd;
+ gio->data = data;
+ gio->fflag = fflag;
+ gio->td = td;
+ i = sizeof *gio;
+ if (cmd & IOC_IN)
+ error = g_io_setattr("GEOM::ioctl", cp, i, gio, td);
+ else
+ error = g_io_getattr("GEOM::ioctl", cp, &i, gio, td);
+ g_free(gio);
+
+ if (error == 0) {
+ if (error != 0 && cmd == DIOCGDVIRGIN) {
+ g_topology_lock();
+ gp = g_create_geomf("BSD-method", cp->provider, NULL);
+ g_topology_unlock();
+ }
}
- i = IOCGROUP(cmd);
- if (*nm == '?') {
+ mtx_lock(&Giant);
+ g_rattle();
+ if (error == ENOIOCTL) {
+ i = IOCGROUP(cmd);
printf("IOCTL(0x%lx) \"%s\"", cmd, gp->name);
if (i > ' ' && i <= '~')
printf(" '%c'", (int)IOCGROUP(cmd));
@@ -275,23 +281,9 @@ g_dev_ioctl(dev_t dev, u_long cmd, caddr_t data, int fflag, struct thread *td)
printf("I");
if (cmd & IOC_OUT)
printf("O");
- printf("(%ld)", IOCPARM_LEN(cmd));
- printf(" \"%s\"\n", nm);
- error = ENOIOCTL;
- }
- if (error == 0) {
- i = IOCPARM_LEN(cmd);
- error = g_io_getattr(nm, cp, &i, data, td);
- if (error != 0 && cmd == DIOCGDVIRGIN) {
- g_topology_lock();
- gp = g_create_geomf("BSD-method", cp->provider, NULL);
- g_topology_unlock();
- }
- }
- mtx_lock(&Giant);
- g_rattle();
- if (error == ENOIOCTL)
+ printf("(%ld) = ENOIOCTL\n", IOCPARM_LEN(cmd));
error = ENOTTY;
+ }
return (error);
}
diff --git a/sys/geom/geom_disk.c b/sys/geom/geom_disk.c
index 62da840..ed0b8be 100644
--- a/sys/geom/geom_disk.c
+++ b/sys/geom/geom_disk.c
@@ -115,9 +115,12 @@ g_disk_start(struct bio *bp)
struct bio *bp2;
dev_t dev;
struct disk *dp;
+ struct g_ioctl *gio;
+ int error;
dp = bp->bio_to->geom->softc;
dev = dp->d_dev;
+ error = 0;
switch(bp->bio_cmd) {
case BIO_READ:
case BIO_WRITE:
@@ -134,27 +137,38 @@ g_disk_start(struct bio *bp)
case BIO_GETATTR:
if (g_haveattr_int(bp, "GEOM::sectorsize",
dp->d_label.d_secsize))
- return;
- if (g_haveattr_int(bp, "GEOM::fwsectors",
+ break;
+ else if (g_haveattr_int(bp, "GEOM::fwsectors",
dp->d_label.d_nsectors))
- return;
- if (g_haveattr_int(bp, "GEOM::fwheads",
+ break;
+ else if (g_haveattr_int(bp, "GEOM::fwheads",
dp->d_label.d_ntracks))
- return;
- if (g_haveattr_int(bp, "GEOM::fwcylinders",
+ break;
+ else if (g_haveattr_int(bp, "GEOM::fwcylinders",
dp->d_label.d_ncylinders))
- return;
- if (g_haveattr_off_t(bp, "GEOM::mediasize",
+ break;
+ else if (g_haveattr_off_t(bp, "GEOM::mediasize",
dp->d_label.d_secsize * (off_t)dp->d_label.d_secperunit))
- return;
- bp->bio_error = ENOIOCTL;
- g_io_deliver(bp);
- return;
+ break;
+ else if (!strcmp(bp->bio_attribute, "GEOM::ioctl") &&
+ bp->bio_length == sizeof *gio) {
+ gio = (struct g_ioctl *)bp->bio_data;
+ mtx_lock(&Giant);
+ error = devsw(dev)->d_ioctl(dev, gio->cmd,
+ gio->data, gio->fflag, gio->td);
+ mtx_unlock(&Giant);
+ } else
+ error = ENOIOCTL;
+ break;
default:
- bp->bio_error = EOPNOTSUPP;
+ error = EOPNOTSUPP;
+ break;
+ }
+ if (error) {
+ bp->bio_error = error;
g_io_deliver(bp);
- return;
}
+ return;
}
dev_t
OpenPOWER on IntegriCloud