diff options
Diffstat (limited to 'stand/libsa/dev.c')
-rw-r--r-- | stand/libsa/dev.c | 129 |
1 files changed, 124 insertions, 5 deletions
diff --git a/stand/libsa/dev.c b/stand/libsa/dev.c index 1d1dd075580e..1edc843d508c 100644 --- a/stand/libsa/dev.c +++ b/stand/libsa/dev.c @@ -27,13 +27,8 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * @(#)dev.c 8.1 (Berkeley) 6/11/93 */ -#include <sys/cdefs.h> -__FBSDID("$FreeBSD$"); - #include <sys/param.h> #include <sys/reboot.h> @@ -56,3 +51,127 @@ noioctl(struct open_file *f __unused, u_long cmd __unused, void *data __unused) { return (EINVAL); } + +char * +devformat(struct devdesc *d) +{ + static char name[DEV_DEVLEN]; + + if (d->d_dev->dv_fmtdev != NULL) + return (d->d_dev->dv_fmtdev(d)); + snprintf(name, sizeof(name), "%s%d:", d->d_dev->dv_name, d->d_unit); + return (name); +} + +/* NB: devspec points to the remainder of the device name after dv_name */ +static int +default_parsedev(struct devdesc **dev, const char *devspec, + const char **path) +{ + struct devdesc *idev; + int unit, err; + char *cp; + + idev = malloc(sizeof(struct devdesc)); + if (idev == NULL) + return (ENOMEM); + + unit = 0; + cp = (char *)devspec; /* strtol interface, alas */ + + if (*devspec != '\0' && *devspec != ':') { + errno = 0; + unit = strtol(devspec, &cp, 0); + if (errno != 0 || cp == devspec) { + err = EUNIT; + goto fail; + } + } + if (*cp != '\0' && *cp != ':') { + err = EINVAL; + goto fail; + } + + idev->d_unit = unit; + if (path != NULL) + *path = (*cp == 0) ? cp : cp + 1; + *dev = idev; + return (0); +fail: + free(idev); + return (err); +} + +/* NB: devspec points to the whole device spec, and possible trailing path */ +int +devparse(struct devdesc **dev, const char *devspec, const char **path) +{ + struct devdesc *idev; + struct devsw *dv; + int i, err; + const char *np; + + /* minimum length check */ + if (strlen(devspec) < 2) + return (EINVAL); + + /* look for a device that matches */ + for (i = 0; devsw[i] != NULL; i++) { + dv = devsw[i]; + if (dv->dv_match != NULL) { + if (dv->dv_match(dv, devspec) != 0) + break; + } else { + if (!strncmp(devspec, dv->dv_name, strlen(dv->dv_name))) + break; + } + } + if (devsw[i] == NULL) + return (ENOENT); + idev = NULL; + err = 0; + if (dv->dv_parsedev) { + err = dv->dv_parsedev(&idev, devspec, path); + } else { + np = devspec + strlen(dv->dv_name); + err = default_parsedev(&idev, np, path); + } + if (err != 0) + return (err); + + idev->d_dev = dv; + if (dev != NULL) + *dev = idev; + else + free(idev); + return (0); +} + +int +devinit(void) +{ + int err = 0; + + /* + * March through the device switch probing for things. + */ + for (int i = 0; devsw[i] != NULL; i++) { + if (devsw[i]->dv_init != NULL) { + if ((devsw[i]->dv_init)() != 0) { + err++; + } + } + } + return (err); +} + +void +dev_cleanup(void) +{ + int i; + + /* Call cleanup routines */ + for (i = 0; devsw[i] != NULL; ++i) + if (devsw[i]->dv_cleanup != NULL) + (devsw[i]->dv_cleanup)(); +} |