mirror of
https://github.com/opnsense/src.git
synced 2026-06-11 09:41:03 -04:00
Add a generic and general ioctl pass-through mechanism.
It should now be posible to issue ioctls to SCSI CD drives.
This commit is contained in:
parent
a681ab0abe
commit
a5b2e75d32
4 changed files with 85 additions and 51 deletions
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
g_io_deliver(bp);
|
||||
return;
|
||||
error = EOPNOTSUPP;
|
||||
break;
|
||||
}
|
||||
if (error) {
|
||||
bp->bio_error = error;
|
||||
g_io_deliver(bp);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
dev_t
|
||||
|
|
|
|||
Loading…
Reference in a new issue