diff --git a/sys/i386/i386/userconfig.c b/sys/i386/i386/userconfig.c index bd971cbb896a..31c456f4b685 100644 --- a/sys/i386/i386/userconfig.c +++ b/sys/i386/i386/userconfig.c @@ -38,7 +38,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: userconfig.c,v 1.13 1994/11/13 00:57:06 jkh Exp $ + * $Id: userconfig.c,v 1.14 1994/11/13 01:55:33 jkh Exp $ */ #include <sys/param.h> @@ -80,48 +80,52 @@ static struct isa_device *search_devtable(struct isa_device *, char *, int); static void cngets(char *, int); static Cmd *parse_cmd(char *); static int parse_args(char *, CmdParm *); -long strtol(const char *, char **, int); int strncmp(const char *, const char *, size_t); +unsigned long strtoul(const char *, char **, int); static int list_devices(CmdParm *); static int set_device_ioaddr(CmdParm *); static int set_device_irq(CmdParm *); static int set_device_drq(CmdParm *); static int set_device_mem(CmdParm *); +static int set_device_flags(CmdParm *); static int set_device_enable(CmdParm *); static int set_device_disable(CmdParm *); static int quitfunc(CmdParm *); static int helpfunc(CmdParm *); -CmdParm addr_parms[] = { +static int lineno; + +static CmdParm addr_parms[] = { { PARM_DEVSPEC, {} }, { PARM_ADDR, {} }, { -1, {} }, }; -CmdParm int_parms[] = { +static CmdParm int_parms[] = { { PARM_DEVSPEC, {} }, { PARM_INT, {} }, { -1, {} }, }; -CmdParm dev_parms[] = { +static CmdParm dev_parms[] = { { PARM_DEVSPEC, {} }, { -1, {} }, }; -Cmd CmdList[] = { - { "?", helpfunc, NULL }, /* "" */ +static Cmd CmdList[] = { + { "?", helpfunc, NULL }, /* ? (help) */ { "di", set_device_disable, dev_parms }, /* disable dev */ { "dr", set_device_drq, int_parms }, /* drq dev # */ { "en", set_device_enable, dev_parms }, /* enable dev */ - { "ex", quitfunc, NULL }, /* "" */ + { "ex", quitfunc, NULL }, /* exit (quit) */ + { "f", set_device_flags, int_parms }, /* flags dev mask */ { "h", helpfunc, NULL }, /* help */ - { "io", set_device_ioaddr, addr_parms }, /* io dev addr */ + { "io", set_device_mem, addr_parms }, /* iomem dev addr */ { "ir", set_device_irq, int_parms }, /* irq dev # */ - { "l", list_devices, NULL }, /* ls */ - { "m", set_device_mem, addr_parms }, /* mem dev addr */ - { "q", quitfunc, NULL }, /* "" */ + { "l", list_devices, NULL }, /* ls, list */ + { "p", set_device_ioaddr, int_parms }, /* port dev addr */ + { "q", quitfunc, NULL }, /* quit */ { NULL, NULL, NULL }, }; @@ -137,7 +141,7 @@ userconfig(void) while (1) { printf("config> "); cngets(input, 80); - if (input[0] == NULL) + if (input[0] == '\0') continue; cmd = parse_cmd(input); if (!cmd) { @@ -194,9 +198,9 @@ parse_args(char *cmd, CmdParm *parms) while (*cmd && !(*cmd == ' ' || *cmd == '\t' || (*cmd >= '0' && *cmd <= '9'))) devname[i++] = *(cmd++); - devname[i] = NULL; + devname[i] = '\0'; if (*cmd >= '0' && *cmd <= '9') { - unit = strtol(cmd, &ptr, 10); + unit = strtoul(cmd, &ptr, 10); if (cmd == ptr) { printf("Invalid device number\n"); /* XXX should print invalid token here and elsewhere. */ @@ -213,7 +217,7 @@ parse_args(char *cmd, CmdParm *parms) continue; } if (parms->type == PARM_INT) { - parms->parm.iparm = strtol(cmd, &ptr, 10); + parms->parm.iparm = strtoul(cmd, &ptr, 0); if (cmd == ptr) { printf("Invalid numeric argument\n"); return 1; @@ -223,7 +227,7 @@ parse_args(char *cmd, CmdParm *parms) continue; } if (parms->type == PARM_ADDR) { - parms->parm.aparm = (void *)strtol(cmd, &ptr, 16); + parms->parm.aparm = (void *)strtoul(cmd, &ptr, 0); if (cmd == ptr) { printf("Invalid address argument\n"); return 1; @@ -239,7 +243,7 @@ parse_args(char *cmd, CmdParm *parms) static int list_devices(CmdParm *parms) { - printf("Device IOaddr IRQ DRQ MemAddr Flags Enabled\n"); + lineno = 0; lsdevtab(&isa_devtab_bio[0]); lsdevtab(&isa_devtab_tty[0]); lsdevtab(&isa_devtab_net[0]); @@ -250,21 +254,31 @@ list_devices(CmdParm *parms) static int set_device_ioaddr(CmdParm *parms) { - parms[0].parm.dparm->id_iobase = (int) parms[1].parm.aparm; + parms[0].parm.dparm->id_iobase = parms[1].parm.iparm; return 0; } static int set_device_irq(CmdParm *parms) { - parms[0].parm.dparm->id_irq = 1 << parms[1].parm.iparm; + unsigned irq; + + irq = parms[1].parm.iparm; + parms[0].parm.dparm->id_irq = (irq < 16 ? 1 << irq : 0); return 0; } static int set_device_drq(CmdParm *parms) { - parms[0].parm.dparm->id_drq = parms[1].parm.iparm; + unsigned drq; + + /* + * The bounds checking is just to ensure that the value can be printed + * in 5 characters. 32768 gets converted to -32768 and doesn't fit. + */ + drq = parms[1].parm.iparm; + parms[0].parm.dparm->id_drq = (drq < 32768 ? drq : -1); return 0; } @@ -275,6 +289,13 @@ set_device_mem(CmdParm *parms) return 0; } +static int +set_device_flags(CmdParm *parms) +{ + parms[0].parm.dparm->id_flags = parms[1].parm.iparm; + return 0; +} + static int set_device_enable(CmdParm *parms) { @@ -301,35 +322,61 @@ helpfunc(CmdParm *parms) printf("Command\t\t\tDescription\n"); printf("-------\t\t\t-----------\n"); printf("ls\t\t\tList currently configured devices\n"); - printf("io <devname> <addr>\tSet device io address\n"); - printf("irq <devname> <irq>\tSet device IRQ\n"); - printf("drq <devname> <drq>\tSet device DRQ\n"); - printf("mem <devname> <addr>\tSet device memory address\n"); + printf("port <devname> <addr>\tSet device port (i/o address)\n"); + printf("irq <devname> <number>\tSet device irq\n"); + printf("drq <devname> <number>\tSet device drq\n"); + printf("iomem <devname> <addr>\tSet device maddr (memory address)\n"); + printf("flags <devname> <mask>\tSet device flags\n"); printf("enable <devname>\tEnable device\n"); printf("disable <devname>\tDisable device (will not be probed)\n"); printf("quit\t\t\tExit this configuration utility\n"); printf("help\t\t\tThis message\n\n"); - printf("Commands may also be abbreviated to a unique number of characters\n"); + printf("Commands may be abbreviated to a unique prefix\n"); return 0; } static void lsdevtab(struct isa_device *dt) { - int i; - int lineno = 0; + for (; dt->id_id != 0; dt++) { + int i; + char line[80]; - for (i = 0; dt->id_id != 0; dt++) { - if (lineno++ > 22) { - lineno = 0; + if (lineno >= 23) { printf("<More> "); (void)cngetc(); printf("\n"); + lineno = 0; } - printf("%s%d 0x%x %d %d 0x%x 0x%x %s\n", - dt->id_driver->name, dt->id_unit, dt->id_iobase, - ffs(dt->id_irq) - 1, dt->id_drq, dt->id_maddr, - dt->id_flags, dt->id_enabled ? "Yes" : "No"); + if (lineno == 0) { + printf( +"Device port irq drq iomem unit flags enabled\n"); + ++lineno; + } + /* + * printf() doesn't support %#, %- or even field widths for strings, + * so formatting is not straightforward. + */ + bzero(line, sizeof line); + sprintf(line, "%s%d", dt->id_driver->name, dt->id_unit); + /* Missing: id_id (don't need it). */ + /* Missing: id_driver (useful if we could show it by name). */ + sprintf(line + 9, "0x%x", dt->id_iobase); + sprintf(line + 20, "%d", ffs(dt->id_irq) - 1); + sprintf(line + 26, "%d", dt->id_drq); + sprintf(line + 32, "0x%x", dt->id_maddr); + /* Missing: id_msize (0 at start, useful if we can get here later). */ + /* Missing: id_intr (useful if we could show it by name). */ + /* Display only: id_unit. */ + sprintf(line + 43, "%d", dt->id_unit); + sprintf(line + 49, "0x%x", dt->id_flags); + /* Missing: id_scsiid, id_alive, id_ri_flags, id_reconfig (0 now...) */ + sprintf(line + 60, "%s", dt->id_enabled ? "Yes" : "No"); + for (i = 0; i < 60; ++i) + if (line[i] == '\0') + line[i] = ' '; + printf("%s\n", line); + ++lineno; } } @@ -371,7 +418,7 @@ cngets(char *input, int maxin) if ((c == '\010' || c == '\177')) { if (nchars) { printf("\010 \010"); - *--input = NULL, --nchars; + *--input = '\0', --nchars; } continue; } @@ -379,13 +426,13 @@ cngets(char *input, int maxin) else if ((c == '\025' || c == '\030')) { while (nchars) { printf("\010 \010"); - *--input = NULL, --nchars; + *--input = '\0', --nchars; } continue; } printf("%c", c); if ((++nchars == maxin) || (c == '\n')) { - *input = NULL; + *input = '\0'; break; } *input++ = (u_char)c; @@ -408,86 +455,83 @@ strncmp(const char *s1, const char *s2, size_t n) } /* - * Convert a string to a long integer. + * Kludges to get the library sources of strtoul.c to work in our + * environment. isdigit() and isspace() could be used above too. + */ +#define isalpha(c) (((c) >= 'A' && (c) <= 'Z') \ + || ((c) >= 'a' && (c) <= 'z')) /* unsafe */ +#define isdigit(c) ((unsigned)((c) - '0') <= '9' - '0') +#define isspace(c) ((c) == ' ' || (c) == '\t') /* unsafe */ +#define isupper(c) ((unsigned)((c) - 'A') <= 'Z' - 'A') + +static int errno; + +/* + * The following should be identical with the library sources for strtoul.c. + */ + +/* + * Convert a string to an unsigned long integer. * * Ignores `locale' stuff. Assumes that the upper and lower case * alphabets and digits are each contiguous. - * - * Slightly lobotomized for inclusion here. */ -long -strtol(const char *nptr, char **endptr, int base) +unsigned long +strtoul(nptr, endptr, base) + const char *nptr; + char **endptr; + register int base; { - register const char *s = nptr; - register unsigned long acc; - register int c; - register unsigned long cutoff; - register int neg = 0, any, cutlim; + register const char *s = nptr; + register unsigned long acc; + register int c; + register unsigned long cutoff; + register int neg = 0, any, cutlim; - /* - * Skip white space and pick up leading +/- sign if any. - * If base is 0, allow 0x for hex and 0 for octal, else - * assume decimal; if base is already 16, allow 0x. - */ - do { - c = *s++; - } while (c == ' ' || c == '\t'); - if (c == '-') { - neg = 1; - c = *s++; - } else if (c == '+') - c = *s++; - if ((base == 0 || base == 16) && - c == '0' && (*s == 'x' || *s == 'X')) { - c = s[1]; - s += 2; - base = 16; - } - if (base == 0) - base = c == '0' ? 8 : 10; - - /* - * Compute the cutoff value between legal numbers and illegal - * numbers. That is the largest legal value, divided by the - * base. An input number that is greater than this value, if - * followed by a legal input character, is too big. One that - * is equal to this value may be valid or not; the limit - * between valid and invalid numbers is then based on the last - * digit. For instance, if the range for longs is - * [-2147483648..2147483647] and the input base is 10, - * cutoff will be set to 214748364 and cutlim to either - * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated - * a value > 214748364, or equal but the next digit is > 7 (or 8), - * the number is too big, and we will return a range error. - * - * Set any if any `digits' consumed; make it negative to indicate - * overflow. - */ - cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX; - cutlim = cutoff % (unsigned long)base; - cutoff /= (unsigned long)base; - for (acc = 0, any = 0;; c = *s++) { - if (c >= '0' && c <= '9') - c -= '0'; - else if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z')) - c -= (c >= 'A' && c <= 'Z') ? 'A' - 10 : 'a' - 10; - else - break; - if (c >= base) - break; - if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) - any = -1; - else { - any = 1; - acc *= base; - acc += c; + /* + * See strtol for comments as to the logic used. + */ + do { + c = *s++; + } while (isspace(c)); + if (c == '-') { + neg = 1; + c = *s++; + } else if (c == '+') + c = *s++; + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X')) { + c = s[1]; + s += 2; + base = 16; } - } - if (any < 0) { - acc = neg ? LONG_MIN : LONG_MAX; - } else if (neg) - acc = -acc; - if (endptr != NULL) - *endptr = (char *)(any ? s - 1 : nptr); - return (acc); + if (base == 0) + base = c == '0' ? 8 : 10; + cutoff = (unsigned long)ULONG_MAX / (unsigned long)base; + cutlim = (unsigned long)ULONG_MAX % (unsigned long)base; + for (acc = 0, any = 0;; c = *s++) { + if (isdigit(c)) + c -= '0'; + else if (isalpha(c)) + c -= isupper(c) ? 'A' - 10 : 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULONG_MAX; + errno = ERANGE; + } else if (neg) + acc = -acc; + if (endptr != 0) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); }