summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/fdc/fdc.c58
-rw-r--r--sys/isa/fd.c58
2 files changed, 82 insertions, 34 deletions
diff --git a/sys/dev/fdc/fdc.c b/sys/dev/fdc/fdc.c
index 5e95d0c..da45cb2 100644
--- a/sys/dev/fdc/fdc.c
+++ b/sys/dev/fdc/fdc.c
@@ -181,6 +181,8 @@ struct fd_data {
struct devstat device_stats;
eventhandler_tag clonetag;
dev_t masterdev;
+#define NCLONEDEVS 10 /* must match the table below */
+ dev_t clonedevs[NCLONEDEVS];
device_t dev;
fdu_t fdu;
};
@@ -832,8 +834,9 @@ static int
fdc_attach(device_t dev)
{
struct fdc_data *fdc;
- int i, error, dunit;
const char *name, *dname;
+ device_t *children;
+ int i, error, dunit, nchildren;
fdc = device_get_softc(dev);
error = fdc_alloc_resources(fdc);
@@ -875,7 +878,17 @@ fdc_attach(device_t dev)
while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0)
fdc_add_child(dev, dname, dunit);
- return (bus_generic_attach(dev));
+ if ((error = bus_generic_attach(dev)) != 0)
+ return (error);
+
+ /* Now remove all children not successfully probed (if any). */
+ if ((error = device_get_children(dev, &children, &nchildren)) != 0)
+ return (error);
+ for (i = 0; i < nchildren; i++)
+ if (!device_is_alive(children[i]))
+ device_delete_child(dev, children[i]);
+
+ return (0);
}
static int
@@ -949,14 +962,10 @@ static struct {
int minor;
int link;
} fd_suffix[] = {
- { "a", 0, 1 },
- { "b", 0, 1 },
- { "c", 0, 1 },
- { "d", 0, 1 },
- { "e", 0, 1 },
- { "f", 0, 1 },
- { "g", 0, 1 },
- { "h", 0, 1 },
+ /*
+ * Genuine clone devices must come first, and their number must
+ * match NCLONEDEVS above.
+ */
{ ".1720", 1, 0 },
{ ".1480", 2, 0 },
{ ".1440", 3, 0 },
@@ -967,15 +976,24 @@ static struct {
{ ".360", 8, 0 },
{ ".640", 9, 0 },
{ ".1232", 10, 0 },
+ { "a", 0, 1 },
+ { "b", 0, 1 },
+ { "c", 0, 1 },
+ { "d", 0, 1 },
+ { "e", 0, 1 },
+ { "f", 0, 1 },
+ { "g", 0, 1 },
+ { "h", 0, 1 },
{ 0, 0 }
};
static void
-fd_clone (void *arg, char *name, int namelen, dev_t *dev)
+fd_clone(void *arg, char *name, int namelen, dev_t *dev)
{
+ struct fd_data *fd;
int u, d, i;
char *n;
- dev_t pdev;
+ fd = (struct fd_data *)arg;
if (*dev != NODEV)
return;
if (dev_stdclone(name, &n, "fd", &u) != 2)
@@ -991,9 +1009,9 @@ fd_clone (void *arg, char *name, int namelen, dev_t *dev)
if (fd_suffix[i].link == 0) {
*dev = make_dev(&fd_cdevsw, (u << 6) + d,
UID_ROOT, GID_OPERATOR, 0640, name);
+ fd->clonedevs[i] = *dev;
} else {
- pdev = makedev(fd_cdevsw.d_maj, (u << 6) + d);
- *dev = make_dev_alias(pdev, name);
+ *dev = make_dev_alias(fd->masterdev, name);
}
}
@@ -1148,15 +1166,18 @@ fd_attach(device_t dev)
{
struct fd_data *fd;
static int cdevsw_add_done;
+ int i;
if (!cdevsw_add_done) {
cdevsw_add(&fd_cdevsw); /* XXX */
cdevsw_add_done = 1;
}
fd = device_get_softc(dev);
- fd->clonetag = EVENTHANDLER_REGISTER(dev_clone, fd_clone, 0, 1000);
+ fd->clonetag = EVENTHANDLER_REGISTER(dev_clone, fd_clone, fd, 1000);
fd->masterdev = make_dev(&fd_cdevsw, fd->fdu << 6,
UID_ROOT, GID_OPERATOR, 0640, "fd%d", fd->fdu);
+ for (i = 0; i < NCLONEDEVS; i++)
+ fd->clonedevs[i] = NODEV;
devstat_add_entry(&fd->device_stats, device_get_name(dev),
device_get_unit(dev), 0, DEVSTAT_NO_ORDERED_TAGS,
DEVSTAT_TYPE_FLOPPY | DEVSTAT_TYPE_IF_OTHER,
@@ -1168,14 +1189,17 @@ static int
fd_detach(device_t dev)
{
struct fd_data *fd;
+ int i;
fd = device_get_softc(dev);
+ untimeout(fd_turnoff, fd, fd->toffhandle);
devstat_remove_entry(&fd->device_stats);
destroy_dev(fd->masterdev);
+ for (i = 0; i < NCLONEDEVS; i++)
+ if (fd->clonedevs[i] != NODEV)
+ destroy_dev(fd->clonedevs[i]);
cdevsw_remove(&fd_cdevsw);
- /* XXX need to destroy cloned devs as well */
EVENTHANDLER_DEREGISTER(dev_clone, fd->clonetag);
- untimeout(fd_turnoff, fd, fd->toffhandle);
return (0);
}
diff --git a/sys/isa/fd.c b/sys/isa/fd.c
index 5e95d0c..da45cb2 100644
--- a/sys/isa/fd.c
+++ b/sys/isa/fd.c
@@ -181,6 +181,8 @@ struct fd_data {
struct devstat device_stats;
eventhandler_tag clonetag;
dev_t masterdev;
+#define NCLONEDEVS 10 /* must match the table below */
+ dev_t clonedevs[NCLONEDEVS];
device_t dev;
fdu_t fdu;
};
@@ -832,8 +834,9 @@ static int
fdc_attach(device_t dev)
{
struct fdc_data *fdc;
- int i, error, dunit;
const char *name, *dname;
+ device_t *children;
+ int i, error, dunit, nchildren;
fdc = device_get_softc(dev);
error = fdc_alloc_resources(fdc);
@@ -875,7 +878,17 @@ fdc_attach(device_t dev)
while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0)
fdc_add_child(dev, dname, dunit);
- return (bus_generic_attach(dev));
+ if ((error = bus_generic_attach(dev)) != 0)
+ return (error);
+
+ /* Now remove all children not successfully probed (if any). */
+ if ((error = device_get_children(dev, &children, &nchildren)) != 0)
+ return (error);
+ for (i = 0; i < nchildren; i++)
+ if (!device_is_alive(children[i]))
+ device_delete_child(dev, children[i]);
+
+ return (0);
}
static int
@@ -949,14 +962,10 @@ static struct {
int minor;
int link;
} fd_suffix[] = {
- { "a", 0, 1 },
- { "b", 0, 1 },
- { "c", 0, 1 },
- { "d", 0, 1 },
- { "e", 0, 1 },
- { "f", 0, 1 },
- { "g", 0, 1 },
- { "h", 0, 1 },
+ /*
+ * Genuine clone devices must come first, and their number must
+ * match NCLONEDEVS above.
+ */
{ ".1720", 1, 0 },
{ ".1480", 2, 0 },
{ ".1440", 3, 0 },
@@ -967,15 +976,24 @@ static struct {
{ ".360", 8, 0 },
{ ".640", 9, 0 },
{ ".1232", 10, 0 },
+ { "a", 0, 1 },
+ { "b", 0, 1 },
+ { "c", 0, 1 },
+ { "d", 0, 1 },
+ { "e", 0, 1 },
+ { "f", 0, 1 },
+ { "g", 0, 1 },
+ { "h", 0, 1 },
{ 0, 0 }
};
static void
-fd_clone (void *arg, char *name, int namelen, dev_t *dev)
+fd_clone(void *arg, char *name, int namelen, dev_t *dev)
{
+ struct fd_data *fd;
int u, d, i;
char *n;
- dev_t pdev;
+ fd = (struct fd_data *)arg;
if (*dev != NODEV)
return;
if (dev_stdclone(name, &n, "fd", &u) != 2)
@@ -991,9 +1009,9 @@ fd_clone (void *arg, char *name, int namelen, dev_t *dev)
if (fd_suffix[i].link == 0) {
*dev = make_dev(&fd_cdevsw, (u << 6) + d,
UID_ROOT, GID_OPERATOR, 0640, name);
+ fd->clonedevs[i] = *dev;
} else {
- pdev = makedev(fd_cdevsw.d_maj, (u << 6) + d);
- *dev = make_dev_alias(pdev, name);
+ *dev = make_dev_alias(fd->masterdev, name);
}
}
@@ -1148,15 +1166,18 @@ fd_attach(device_t dev)
{
struct fd_data *fd;
static int cdevsw_add_done;
+ int i;
if (!cdevsw_add_done) {
cdevsw_add(&fd_cdevsw); /* XXX */
cdevsw_add_done = 1;
}
fd = device_get_softc(dev);
- fd->clonetag = EVENTHANDLER_REGISTER(dev_clone, fd_clone, 0, 1000);
+ fd->clonetag = EVENTHANDLER_REGISTER(dev_clone, fd_clone, fd, 1000);
fd->masterdev = make_dev(&fd_cdevsw, fd->fdu << 6,
UID_ROOT, GID_OPERATOR, 0640, "fd%d", fd->fdu);
+ for (i = 0; i < NCLONEDEVS; i++)
+ fd->clonedevs[i] = NODEV;
devstat_add_entry(&fd->device_stats, device_get_name(dev),
device_get_unit(dev), 0, DEVSTAT_NO_ORDERED_TAGS,
DEVSTAT_TYPE_FLOPPY | DEVSTAT_TYPE_IF_OTHER,
@@ -1168,14 +1189,17 @@ static int
fd_detach(device_t dev)
{
struct fd_data *fd;
+ int i;
fd = device_get_softc(dev);
+ untimeout(fd_turnoff, fd, fd->toffhandle);
devstat_remove_entry(&fd->device_stats);
destroy_dev(fd->masterdev);
+ for (i = 0; i < NCLONEDEVS; i++)
+ if (fd->clonedevs[i] != NODEV)
+ destroy_dev(fd->clonedevs[i]);
cdevsw_remove(&fd_cdevsw);
- /* XXX need to destroy cloned devs as well */
EVENTHANDLER_DEREGISTER(dev_clone, fd->clonetag);
- untimeout(fd_turnoff, fd, fd->toffhandle);
return (0);
}
OpenPOWER on IntegriCloud