3 ** Michael Smith, msmith@freebsd.org. All rights reserved.
5 ** This code contains a module marked :
7 * Copyright (c) 1991 Regents of the University of California.
9 * Copyright (c) 1994 Jordan K. Hubbard
10 * All rights reserved.
11 * Copyright (c) 1994 David Greenman
12 * All rights reserved.
14 * Many additional changes by Bruce Evans
16 * This code is derived from software contributed by the
17 * University of California Berkeley, Jordan K. Hubbard,
18 * David Greenman and Bruce Evans.
20 ** As such, it contains code subject to the above copyrights.
21 ** The module and its copyright can be found below.
23 ** Redistribution and use in source and binary forms, with or without
24 ** modification, are permitted provided that the following conditions
26 ** 1. Redistributions of source code must retain the above copyright
27 ** notice, this list of conditions and the following disclaimer as
28 ** the first lines of this file unmodified.
29 ** 2. Redistributions in binary form must reproduce the above copyright
30 ** notice, this list of conditions and the following disclaimer in the
31 ** documentation and/or other materials provided with the distribution.
32 ** 3. All advertising materials mentioning features or use of this software
33 ** must display the following acknowledgment:
34 ** This product includes software developed by Michael Smith.
35 ** 4. The name of the author may not be used to endorse or promote products
36 ** derived from this software without specific prior written permission.
38 ** THIS SOFTWARE IS PROVIDED BY MICHAEL SMITH ``AS IS'' AND ANY EXPRESS OR
39 ** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
40 ** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
41 ** IN NO EVENT SHALL MICHAEL SMITH BE LIABLE FOR ANY DIRECT, INDIRECT,
42 ** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
43 ** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
44 ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
45 ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46 ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
47 ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
55 ** Kernel boot-time configuration manipulation tool for FreeBSD.
57 ** Two modes of operation are supported : the default is the line-editor mode,
58 ** the command "visual" invokes the fullscreen mode.
60 ** The line-editor mode is the old favorite from FreeBSD 2.0/20.05 &c., the
61 ** fullscreen mode requires syscons or a minimal-ansi serial console.
65 ** USERCONFIG, visual mode.
69 ** Look for "EDIT THIS LIST" to add to the list of known devices
72 ** There are a number of assumptions made in this code.
74 ** - That the console supports a minimal set of ANSI escape sequences
75 ** (See the screen manipulation section for a summary)
76 ** and has at least 24 rows.
77 ** - That values less than or equal to zero for any of the device
78 ** parameters indicate that the driver does not use the parameter.
79 ** - That flags are _always_ editable.
81 ** Devices marked as disabled are imported as such.
83 ** For this tool to be useful, the list of devices below _MUST_ be updated
84 ** when a new driver is brought into the kernel. It is not possible to
85 ** extract this information from the drivers in the kernel.
89 ** - Display _what_ a device conflicts with.
90 ** - Implement page up/down (as what?)
91 ** - Wizard mode (no restrictions)
92 ** - Find out how to put syscons back into low-intensity mode so that the
93 ** !b escape is useful on the console. (It seems to be that it actually
94 ** gets low/high intensity backwards. That looks OK.)
96 ** - Only display headings with devices under them. (difficult)
99 #include "opt_userconfig.h"
100 #define COMPAT_OLDISA /* get the definitions */
102 #include <sys/param.h>
103 #include <sys/systm.h>
104 #include <sys/kernel.h>
105 #include <sys/malloc.h>
106 #include <sys/reboot.h>
107 #include <sys/linker.h>
108 #include <sys/sysctl.h>
110 #include <sys/cons.h>
112 #include <machine/md_var.h>
113 #include <machine/limits.h>
115 #define _I386_ISA_ISA_DEVICE_H_
117 static MALLOC_DEFINE(M_DEVL, "uc_devlist", "uc_device lists in userconfig()");
119 #include <machine/uc_device.h>
120 static struct uc_device *uc_devlist; /* list read by kget to extract changes */
121 static struct uc_device *uc_devtab; /* fake uc_device table */
123 static int userconfig_boot_parsing; /* set if we are reading from the boot instructions */
125 #define putchar(x) cnputc(x)
127 static void load_devtab(void);
128 static void free_devtab(void);
129 static void save_resource(struct uc_device *);
132 sysctl_machdep_uc_devlist(SYSCTL_HANDLER_ARGS)
134 struct uc_device *id;
142 error+=sizeof(struct uc_device)+8;
145 return(SYSCTL_OUT(req,0,error));
147 /* Output the data. The buffer is filled with consecutive
148 * struct uc_device and char buf[8], containing the name
149 * (not guaranteed to end with '\0').
153 error=sysctl_handle_opaque(oidp,id,
154 sizeof(struct uc_device),req);
155 if(error) return(error);
156 strncpy(name,id->id_name,8);
157 error=sysctl_handle_opaque(oidp,name,
159 if(error) return(error);
166 SYSCTL_PROC( _machdep, OID_AUTO, uc_devlist, CTLFLAG_RD,
167 0, 0, sysctl_machdep_uc_devlist, "A",
168 "List of ISA devices changed in UserConfig");
171 ** Obtain command input.
173 ** Initially, input is read from a possibly-loaded script.
174 ** At the end of the script, or if no script is supplied,
175 ** behaviour is determined by the RB_CONFIG (-c) flag. If
176 ** the flag is set, user input is read from the console; if
177 ** unset, the 'quit' command is invoked and userconfig
180 ** Note that quit commands encountered in the script will be
181 ** ignored if the RB_CONFIG flag is supplied.
183 static const char *config_script;
184 static int config_script_size; /* use of int for -ve magic value */
186 #define has_config_script() (config_script_size > 0)
189 init_config_script(void)
191 caddr_t autoentry, autoattr;
193 /* Look for loaded userconfig script */
194 autoentry = preload_search_by_type("userconfig_script");
195 if (autoentry != NULL) {
196 /* We have one, get size and data */
197 config_script_size = 0;
198 if ((autoattr = preload_search_info(autoentry, MODINFO_SIZE)) != NULL)
199 config_script_size = (size_t)*(u_int32_t *)autoattr;
200 config_script = NULL;
201 if ((autoattr = preload_search_info(autoentry, MODINFO_ADDR)) != NULL)
202 config_script = *(const char **)autoattr;
204 if ((config_script_size == 0) || (config_script == NULL)) {
205 config_script_size = 0;
206 config_script = NULL;
209 return has_config_script();
216 #ifdef INTRO_USERCONFIG
217 static int intro = 0;
220 if (has_config_script())
222 /* Consume character from loaded userconfig script, display */
223 userconfig_boot_parsing = 1;
226 config_script_size--;
230 #ifdef INTRO_USERCONFIG
231 if (userconfig_boot_parsing) {
232 if (!(boothowto & RB_CONFIG)) {
233 /* userconfig_script, !RB_CONFIG -> quit */
236 config_script = "uit\n";
237 config_script_size = strlen(config_script);
238 /* userconfig_script will be 1 on the next pass */
241 /* userconfig_script, RB_CONFIG -> cngetc() */
244 if (!(boothowto & RB_CONFIG)) {
245 /* no userconfig_script, !RB_CONFIG -> show intro */
249 config_script = "ntro\n";
250 config_script_size = strlen(config_script);
251 /* userconfig_script will be 1 on the next pass */
254 /* no userconfig_script, RB_CONFIG -> cngetc() */
257 #else /* !INTRO_USERCONFIG */
258 /* assert(boothowto & RB_CONFIG) */
259 #endif /* INTRO_USERCONFIG */
260 userconfig_boot_parsing = 0;
269 #define TRUE (!FALSE)
272 #ifdef VISUAL_USERCONFIG
276 char dev[16]; /* device basename */
277 char name[60]; /* long name */
278 int attrib; /* things to do with the device */
279 int class; /* device classification */
282 #define FLG_INVISIBLE (1<<0) /* device should not be shown */
283 #define FLG_MANDATORY (1<<1) /* device can be edited but not disabled */
284 #define FLG_FIXIRQ (1<<2) /* device IRQ cannot be changed */
285 #define FLG_FIXIOBASE (1<<3) /* device iobase cannot be changed */
286 #define FLG_FIXMADDR (1<<4) /* device maddr cannot be changed */
287 #define FLG_FIXMSIZE (1<<5) /* device msize cannot be changed */
288 #define FLG_FIXDRQ (1<<6) /* device DRQ cannot be changed */
289 #define FLG_FIXED (FLG_FIXIRQ|FLG_FIXIOBASE|FLG_FIXMADDR|FLG_FIXMSIZE|FLG_FIXDRQ)
290 #define FLG_IMMUTABLE (FLG_FIXED|FLG_MANDATORY)
292 #define CLS_STORAGE 1 /* storage devices */
293 #define CLS_NETWORK 2 /* network interfaces */
294 #define CLS_COMMS 3 /* serial, parallel ports */
295 #define CLS_INPUT 4 /* user input : mice, keyboards, joysticks etc */
296 #define CLS_MMEDIA 5 /* "multimedia" devices (sound, video, etc) */
297 #define CLS_MISC 255 /* none of the above */
306 static DEVCLASS_INFO devclass_names[] = {
307 { "Storage : ", CLS_STORAGE},
308 { "Network : ", CLS_NETWORK},
309 { "Communications : ", CLS_COMMS},
310 { "Input : ", CLS_INPUT},
311 { "Multimedia : ", CLS_MMEDIA},
312 { "Miscellaneous : ", CLS_MISC},
316 /********************* EDIT THIS LIST **********************/
320 ** - Devices that shouldn't be seen or removed should be marked FLG_INVISIBLE.
321 ** - XXX The list below should be reviewed by the driver authors to verify
322 ** that the correct flags have been set for each driver, and that the
323 ** descriptions are accurate.
326 static DEV_INFO device_info[] = {
327 /*---Name----- ---Description---------------------------------------------- */
328 {"adv", "AdvanSys SCSI narrow controller", 0, CLS_STORAGE},
329 {"bt", "Buslogic SCSI controller", 0, CLS_STORAGE},
330 {"aha", "Adaptec 154x SCSI controller", 0, CLS_STORAGE},
331 {"aic", "Adaptec 152x SCSI and compatible SCSI cards", 0, CLS_STORAGE},
332 {"nca", "ProAudio Spectrum SCSI and compatibles", 0, CLS_STORAGE},
333 {"sea", "Seagate ST01/ST02 SCSI and compatibles", 0, CLS_STORAGE},
334 {"stg", "TMC 18C30/18C50 based SCSI cards", 0, CLS_STORAGE},
335 {"ata", "ATA/ATAPI compatible disk controller", 0, CLS_STORAGE},
336 {"fdc", "Floppy disk controller", FLG_FIXED, CLS_STORAGE},
337 {"mcd", "Mitsumi CD-ROM", 0, CLS_STORAGE},
338 {"scd", "Sony CD-ROM", 0, CLS_STORAGE},
339 {"matcd", "Matsushita/Panasonic/Creative CDROM", 0, CLS_STORAGE},
340 {"wt", "Wangtek/Archive QIC-02 Tape drive", 0, CLS_STORAGE},
341 {"ad", "ATA/ATAPI compatible storage device", FLG_INVISIBLE, CLS_STORAGE},
342 {"fd", "Floppy disk device", FLG_INVISIBLE, CLS_STORAGE},
344 {"cs", "IBM EtherJet, CS89x0-based Ethernet adapters",0, CLS_NETWORK},
345 {"ed", "NE1000,NE2000,3C503,WD/SMC80xx Ethernet adapters",0, CLS_NETWORK},
346 {"el", "3C501 Ethernet adapter", 0, CLS_NETWORK},
347 {"ep", "3C509 Ethernet adapter", 0, CLS_NETWORK},
348 {"ex", "Intel EtherExpress Pro/10 Ethernet adapter", 0, CLS_NETWORK},
349 {"fe", "Fujitsu MB86960A/MB86965A Ethernet adapters", 0, CLS_NETWORK},
350 {"ie", "AT&T Starlan 10 and EN100, 3C507, NI5210 Ethernet adapters",0,CLS_NETWORK},
351 {"le", "DEC Etherworks 2 and 3 Ethernet adapters", 0, CLS_NETWORK},
352 {"lnc", "Isolan, Novell NE2100/NE32-VL Ethernet adapters", 0,CLS_NETWORK},
353 {"sn", "SMC/Megahertz Ethernet adapters", 0,CLS_NETWORK},
354 {"xe", "Xircom PC Card Ethernet adapter", 0, CLS_NETWORK},
355 {"rdp", "RealTek RTL8002 Pocket Ethernet", 0, CLS_NETWORK},
357 {"sio", "8250/16450/16550 Serial port", 0, CLS_COMMS},
358 {"cx", "Cronyx/Sigma multiport sync/async adapter",0, CLS_COMMS},
359 {"rc", "RISCom/8 multiport async adapter", 0, CLS_COMMS},
360 {"cy", "Cyclades multiport async adapter", 0, CLS_COMMS},
361 {"dgb", "Digiboard PC/Xe, PC/Xi async adapter", 0, CLS_COMMS},
362 {"si", "Specialix SI/XIO/SX async adapter", 0, CLS_COMMS},
363 {"stl", "Stallion EasyIO/Easy Connection 8/32 async adapter",0, CLS_COMMS},
364 {"stli", "Stallion intelligent async adapter" ,0, CLS_COMMS},
365 {"ppc", "Parallel Port chipset", 0, CLS_COMMS},
366 {"gp", "National Instruments AT-GPIB/TNT driver", 0, CLS_COMMS},
368 {"atkbdc", "Keyboard controller", FLG_INVISIBLE, CLS_INPUT},
369 {"atkbd", "Keyboard", FLG_FIXED, CLS_INPUT},
370 {"mse", "Microsoft Bus Mouse", 0, CLS_INPUT},
371 {"psm", "PS/2 Mouse", FLG_FIXED, CLS_INPUT},
372 {"joy", "Joystick", FLG_FIXED, CLS_INPUT},
373 {"vt", "PCVT console driver", FLG_IMMUTABLE, CLS_INPUT},
374 {"sc", "Syscons console driver", FLG_IMMUTABLE, CLS_INPUT},
376 {"sbc", "PCM Creative SoundBlaster/ESS/Avance sounce cards", 0,CLS_MMEDIA},
377 {"gusc", "PCM Gravis UltraSound sound cards", 0, CLS_MMEDIA},
378 {"pcm", "PCM Generic soundcard support", 0, CLS_MMEDIA},
379 {"sb", "VOXWARE Soundblaster PCM (SB/Pro/16, ProAudio Spectrum)",0,CLS_MMEDIA},
380 {"sbxvi", "VOXWARE Soundblaster 16", 0, CLS_MMEDIA},
381 {"sbmidi", "VOXWARE Soundblaster MIDI interface", 0, CLS_MMEDIA},
382 {"awe", "VOXWARE AWE32 MIDI", 0, CLS_MMEDIA},
383 {"pas", "VOXWARE ProAudio Spectrum PCM and MIDI", 0, CLS_MMEDIA},
384 {"gus", "VOXWARE Gravis Ultrasound, Ultrasound 16 and Ultrasound MAX",0,CLS_MMEDIA},
385 {"gusxvi", "VOXWARE Gravis Ultrasound 16-bit PCM", 0, CLS_MMEDIA},
386 {"gusmax", "VOXWARE Gravis Ultrasound MAX", 0, CLS_MMEDIA},
387 {"mss", "VOXWARE Microsoft Sound System", 0, CLS_MMEDIA},
388 {"opl", "VOXWARE OPL-2/3 FM, SB/Pro/16, ProAudio Spectrum",0,CLS_MMEDIA},
389 {"mpu", "VOXWARE Roland MPU401 MIDI", 0, CLS_MMEDIA},
390 {"sscape", "VOXWARE Ensoniq Soundscape MIDI interface", 0, CLS_MMEDIA},
391 {"sscape_mss", "VOXWARE Ensoniq Soundscape PCM", 0, CLS_MMEDIA},
392 {"uart", "VOXWARE 6850 MIDI UART", 0, CLS_MMEDIA},
393 {"pca", "PC speaker PCM audio driver", FLG_FIXED, CLS_MMEDIA},
394 {"ctx", "Coretex-I frame grabber", 0, CLS_MMEDIA},
395 {"spigot", "Creative Labs Video Spigot video capture", 0, CLS_MMEDIA},
396 {"scc", "IBM Smart Capture Card", 0, CLS_MMEDIA},
397 {"gsc", "Genius GS-4500 hand scanner", 0, CLS_MMEDIA},
398 {"asc", "AmiScan scanner", 0, CLS_MMEDIA},
400 {"apm", "Advanced Power Management", FLG_FIXED, CLS_MISC},
401 {"pcic", "PC-card controller", 0, CLS_MISC},
402 {"npx", "Math coprocessor", FLG_IMMUTABLE, CLS_MISC},
403 {"vga", "Catchall PCI VGA driver", FLG_INVISIBLE, CLS_MISC},
407 typedef struct _devlist_struct
410 int attrib; /* flag values as per the FLG_* defines above */
411 int class; /* disk, etc as per the CLS_* defines above */
413 int iobase,irq,drq,maddr,msize,unit,flags,id;
414 int comment; /* 0 = device, 1 = comment, 2 = collapsed comment */
415 int conflicts; /* set/reset by findconflict, count of conflicts */
416 int changed; /* nonzero if the device has been edited */
417 struct uc_device *device;
418 struct _devlist_struct *prev,*next;
423 #define DEV_COMMENT 1
426 #define LIST_CURRENT (1<<0)
427 #define LIST_SELECTED (1<<1)
429 #define KEY_EXIT 0 /* return codes from dolist() and friends */
435 #define KEY_UP 5 /* these only returned from editval() */
439 #define KEY_NULL 9 /* this allows us to spin & redraw */
441 #define KEY_ZOOM 10 /* these for zoom all/collapse all */
442 #define KEY_UNZOOM 11
444 #define KEY_HELP 12 /* duh? */
446 static void redraw(void);
447 static void insdev(DEV_LIST *dev, DEV_LIST *list);
448 static int devinfo(DEV_LIST *dev);
449 static int visuserconfig(void);
451 static DEV_LIST *active = NULL,*inactive = NULL; /* driver lists */
452 static DEV_LIST *alist,*ilist; /* visible heads of the driver lists */
453 static DEV_LIST scratch; /* scratch record */
454 static int conflicts; /* total conflict count */
457 static char lines[] = "--------------------------------------------------------------------------------";
458 static char spaces[] = " ";
462 ** Device manipulation stuff : find, describe, configure.
468 ** Sets the device referenced by (*dev) to the parameters in the struct,
469 ** and the enable flag according to (enabled)
472 setdev(DEV_LIST *dev, int enabled)
474 dev->device->id_iobase = dev->iobase; /* copy happy */
475 dev->device->id_irq = (u_short)(dev->irq < 16 ? 1<<dev->irq : 0); /* IRQ is bitfield */
476 dev->device->id_drq = (short)dev->drq;
477 dev->device->id_maddr = (caddr_t)dev->maddr;
478 dev->device->id_msize = dev->msize;
479 dev->device->id_flags = dev->flags;
480 dev->device->id_enabled = enabled;
487 ** Walk the kernel device tables and build the active and inactive lists
493 struct uc_device *ap;
495 ap = uc_devtab; /* pointer to array of devices */
496 for (i = 0; ap[i].id_id; i++) /* for each device in this table */
498 scratch.unit = ap[i].id_unit; /* device parameters */
499 strcpy(scratch.dev,ap[i].id_name);
500 scratch.iobase = ap[i].id_iobase;
501 scratch.irq = ffs(ap[i].id_irq)-1;
502 scratch.drq = ap[i].id_drq;
503 scratch.maddr = (int)ap[i].id_maddr;
504 scratch.msize = ap[i].id_msize;
505 scratch.flags = ap[i].id_flags;
507 scratch.comment = DEV_DEVICE; /* admin stuff */
508 scratch.conflicts = 0;
509 scratch.device = &ap[i]; /* save pointer for later reference */
511 if (!devinfo(&scratch)) /* get more info on the device */
512 insdev(&scratch,ap[i].id_enabled?active:inactive);
520 ** Fill in (dev->name), (dev->attrib) and (dev->type) from the device_info array.
521 ** If the device is unknown, put it in the CLS_MISC class, with no flags.
523 ** If the device is marked "invisible", return nonzero; the caller should
524 ** not insert any such device into either list.
528 devinfo(DEV_LIST *dev)
532 for (i = 0; device_info[i].class; i++)
534 if (!strcmp(dev->dev,device_info[i].dev))
536 if (device_info[i].attrib & FLG_INVISIBLE) /* forget we ever saw this one */
538 strcpy(dev->name,device_info[i].name); /* get the name */
539 dev->attrib = device_info[i].attrib;
540 dev->class = device_info[i].class;
544 strcpy(dev->name,"Unknown device");
546 dev->class = CLS_MISC;
552 ** List manipulation stuff : add, move, initialise, free, traverse
554 ** Note that there are assumptions throughout this code that
555 ** the first entry in a list will never move. (assumed to be
563 ** appends a copy of (dev) to the end of (*list)
566 addev(DEV_LIST *dev, DEV_LIST **list)
571 lp = (DEV_LIST *)malloc(sizeof(DEV_LIST),M_DEVL,M_WAITOK);
572 bcopy(dev,lp,sizeof(DEV_LIST)); /* create copied record */
574 if (*list) /* list exists */
578 ap = ap->next; /* scoot to end of list */
582 }else{ /* list does not yet exist */
584 lp->prev = lp->next = NULL; /* list now exists */
592 ** Finds the 'appropriate' place for (dev) in (list)
594 ** 'Appropriate' means in numeric order with other devices of the same type,
595 ** or in alphabetic order following a comment of the appropriate type.
596 ** or at the end of the list if an appropriate comment is not found. (this should
598 ** (Note that the appropriate point is never the top, but may be the bottom)
601 findspot(DEV_LIST *dev, DEV_LIST *list)
605 /* search for a previous instance of the same device */
606 for (ap = list; ap; ap = ap->next)
608 if (ap->comment != DEV_DEVICE) /* ignore comments */
610 if (!strcmp(dev->dev,ap->dev)) /* same base device */
612 if ((dev->unit <= ap->unit) /* belongs before (equal is bad) */
613 || !ap->next) /* or end of list */
615 ap = ap->prev; /* back up one */
616 break; /* done here */
618 if (ap->next) /* if the next item exists */
620 if (ap->next->comment != DEV_DEVICE) /* next is a comment */
622 if (strcmp(dev->dev,ap->next->dev)) /* next is a different device */
628 if (!ap) /* not sure yet */
630 /* search for a class that the device might belong to */
631 for (ap = list; ap; ap = ap->next)
633 if (ap->comment != DEV_DEVICE) /* look for simlar devices */
635 if (dev->class != ap->class) /* of same class too 8) */
637 if (strcmp(dev->dev,ap->dev) < 0) /* belongs before the current entry */
639 ap = ap->prev; /* back up one */
640 break; /* done here */
642 if (ap->next) /* if the next item exists */
643 if (ap->next->comment != DEV_DEVICE) /* next is a comment, go here */
648 if (!ap) /* didn't find a match */
650 for (ap = list; ap->next; ap = ap->next) /* try for a matching comment */
651 if ((ap->comment != DEV_DEVICE)
652 && (ap->class == dev->class)) /* appropriate place? */
654 } /* or just put up with last */
663 ** Inserts a copy of (dev) at the appropriate point in (list)
666 insdev(DEV_LIST *dev, DEV_LIST *list)
670 lp = (DEV_LIST *)malloc(sizeof(DEV_LIST),M_DEVL,M_WAITOK);
671 bcopy(dev,lp,sizeof(DEV_LIST)); /* create copied record */
673 ap = findspot(lp,list); /* find appropriate spot */
674 lp->next = ap->next; /* point to next */
676 ap->next->prev = lp; /* point next to new */
677 lp->prev = ap; /* point new to current */
678 ap->next = lp; /* and current to new */
685 ** Moves (dev) from its current list to an appropriate place in (list)
686 ** (dev) may not come from the top of a list, but it may from the bottom.
689 movedev(DEV_LIST *dev, DEV_LIST *list)
693 ap = findspot(dev,list);
694 dev->prev->next = dev->next; /* remove from old list */
696 dev->next->prev = dev->prev;
698 dev->next = ap->next; /* insert in new list */
700 ap->next->prev = dev; /* point next to new */
701 dev->prev = ap; /* point new to current */
702 ap->next = dev; /* and current to new */
709 ** Initialises (*list) with the basic headings
712 initlist(DEV_LIST **list)
716 for(i = 0; devclass_names[i].name[0]; i++) /* for each devtype name */
718 strcpy(scratch.name,devclass_names[i].name);
719 scratch.comment = DEV_ZOOMED;
720 scratch.class = devclass_names[i].number;
721 scratch.attrib = FLG_MANDATORY; /* can't be moved */
722 addev(&scratch,list); /* add to the list */
730 ** Walks (list) and saves the settings of any entry marked as changed.
732 ** The device's active field is set according to (active).
734 ** Builds the uc_devlist used by kget to extract the changed device information.
735 ** The code for this was taken almost verbatim from the original module.
738 savelist(DEV_LIST *list, int active)
740 struct uc_device *id_p,*id_pn;
745 if ((list->comment == DEV_DEVICE) && /* is a device */
746 (list->changed) && /* has been changed */
747 (list->device != NULL)) { /* has an uc_device structure */
749 setdev(list,active); /* set the device itself */
752 for (id_p=uc_devlist; id_p; id_p=id_p->id_next)
753 { /* look on the list for it */
754 if (id_p->id_id == list->device->id_id)
756 name = list->device->id_name;
757 id_pn = id_p->id_next;
759 free(id_p->id_name, M_DEVL);
760 bcopy(list->device,id_p,sizeof(struct uc_device));
761 save_resource(list->device);
762 id_p->id_name = malloc(strlen(name) + 1, M_DEVL,M_WAITOK);
763 strcpy(id_p->id_name, name);
764 id_pn->id_next = uc_devlist;
765 id_p->id_next = id_pn;
769 if (!id_pn) /* not already on the list */
771 name = list->device->id_name;
772 id_pn = malloc(sizeof(struct uc_device),M_DEVL,M_WAITOK);
773 bcopy(list->device,id_pn,sizeof(struct uc_device));
774 save_resource(list->device);
775 id_pn->id_name = malloc(strlen(name) + 1, M_DEVL,M_WAITOK);
776 strcpy(id_pn->id_name, name);
777 id_pn->id_next = uc_devlist;
778 uc_devlist = id_pn; /* park at top of list */
789 ** Frees all storage in use by a (list).
792 nukelist(DEV_LIST *list)
798 while(list->prev) /* walk to head of list */
813 ** Returns the previous entry in (list), skipping zoomed regions. Returns NULL
814 ** if there is no previous entry. (Only possible if list->prev == NULL given the
815 ** premise that there is always a comment at the head of the list)
818 prevent(DEV_LIST *list)
824 dp = list->prev; /* start back one */
827 if (dp->comment == DEV_ZOOMED) /* previous section is zoomed */
828 return(dp); /* so skip to comment */
829 if (dp->comment == DEV_COMMENT) /* not zoomed */
830 return(list->prev); /* one back as normal */
831 dp = dp->prev; /* backpedal */
833 return(dp); /* NULL, we can assume */
840 ** Returns the next entry in (list), skipping zoomed regions. Returns NULL
841 ** if there is no next entry. (Possible if the current entry is last, or
842 ** if the current entry is the last heading and it's collapsed)
845 nextent(DEV_LIST *list)
851 if (list->comment != DEV_ZOOMED) /* no reason to skip */
856 if (dp->comment != DEV_DEVICE) /* found another heading */
860 return(dp); /* back we go */
867 ** Returns the (ofs)th entry down from (list), or NULL if it doesn't exist
870 ofsent(int ofs, DEV_LIST *list)
872 while (ofs-- && list)
873 list = nextent(list);
881 ** Scans every element of (list) and sets the conflict tags appropriately
882 ** Returns the number of conflicts found.
885 findconflict(DEV_LIST *list)
887 int count = 0; /* number of conflicts found */
890 for (dp = list; dp; dp = dp->next) /* over the whole list */
892 if (dp->comment != DEV_DEVICE) /* comments don't usually conflict */
895 dp->conflicts = 0; /* assume the best */
896 for (sp = list; sp; sp = sp->next) /* scan the entire list for conflicts */
898 if (sp->comment != DEV_DEVICE) /* likewise */
901 if (sp == dp) /* always conflict with itself */
904 if ((dp->iobase > 0) && /* iobase conflict? */
905 (dp->iobase == sp->iobase))
907 if ((dp->irq > 0) && /* irq conflict? */
908 (dp->irq == sp->irq))
910 if ((dp->drq > 0) && /* drq conflict? */
911 (dp->drq == sp->drq))
913 if ((sp->maddr > 0) && /* maddr/msize conflict? */
915 (sp->maddr + ((sp->msize == 0) ? 1 : sp->msize) > dp->maddr) &&
916 (dp->maddr + ((dp->msize == 0) ? 1 : dp->msize) > sp->maddr))
919 count += dp->conflicts; /* count conflicts */
928 ** Unzooms all headings in (list)
931 expandlist(DEV_LIST *list)
935 if (list->comment == DEV_COMMENT)
936 list->comment = DEV_ZOOMED;
945 ** Zooms all headings in (list)
948 collapselist(DEV_LIST *list)
952 if (list->comment == DEV_ZOOMED)
953 list->comment = DEV_COMMENT;
960 ** Screen-manipulation stuff
962 ** This is the basic screen layout :
964 ** 0 5 10 15 20 25 30 35 40 45 50 55 60 67 70 75
965 ** |....|....|....|....|....|....|....|....|....|....|....|....|....|....|....|....
966 ** +--------------------------------------------------------------------------------+
967 ** 0 -|---Active Drivers----------------------------xx Conflicts------Dev---IRQ--Port--|
968 ** 1 -| ........................ ....... .. 0x....|
969 ** 2 -| ........................ ....... .. 0x....|
970 ** 3 -| ........................ ....... .. 0x....|
971 ** 4 -| ........................ ....... .. 0x....|
972 ** 5 -| ........................ ....... .. 0x....|
973 ** 6 -| ........................ ....... .. 0x....|
974 ** 7 -| ........................ ....... .. 0x....|
975 ** 8 -| ........................ ....... .. 0x....|
976 ** 9 -|---Inactive Drivers--------------------------------------------Dev--------------|
977 ** 10-| ........................ ....... |
978 ** 11-| ........................ ....... |
979 ** 12-| ........................ ....... |
980 ** 13-| ........................ ....... |
981 ** 14-| ........................ ....... |
982 ** 15-| ........................ ....... |
983 ** 16-| ........................ ....... |
984 ** 17-|------------------------------------------------------UP-DOWN-------------------|
985 ** 18-| Relevant parameters for the current device |
988 ** 21-|--------------------------------------------------------------------------------|
989 ** 22-| Help texts go here |
991 ** +--------------------------------------------------------------------------------+
995 ** On a collapsed comment :
997 ** [Enter] Expand device list [z] Expand all lists
998 ** [TAB] Change fields [Q] Save and Exit
1000 ** On an expanded comment :
1002 ** [Enter] Collapse device list [Z] Collapse all lists
1003 ** [TAB] Change fields [Q] Save and Exit
1005 ** On a comment with no followers
1008 ** [TAB] Change fields [Q] Save and Exit
1010 ** On a device in the active list
1012 ** [Enter] Edit device parameters [DEL] Disable device
1013 ** [TAB] Change fields [Q] Save and Exit [?] Help
1015 ** On a device in the inactive list
1017 ** [Enter] Enable device
1018 ** [TAB] Change fields [Q] Save and Exit [?] Help
1020 ** While editing parameters
1022 ** <parameter-specific help here>
1023 ** [TAB] Change fields [Q] Save device parameters
1030 ** The base-level screen primitives :
1032 ** bold() - enter bold mode \E[1m (md)
1033 ** inverse() - enter inverse mode \E[7m (so)
1034 ** normal() - clear bold/inverse mode \E[m (se)
1035 ** clear() - clear the screen \E[H\E[J (ce)
1036 ** move(x,y) - move the cursor to x,y \E[y;xH: (cm)
1061 printf("\033[H\033[J");
1067 printf("\033[%d;%dH",y+1,x+1);
1073 ** High-level screen primitives :
1075 ** putxyl(x,y,str,len) - put (len) bytes of (str) at (x,y), supports embedded formatting
1076 ** putxy(x,y,str) - put (str) at (x,y), supports embedded formatting
1077 ** erase(x,y,w,h) - clear the box (x,y,w,h)
1078 ** txtbox(x,y,w,y,str) - put (str) in a region at (x,y,w,h)
1079 ** putmsg(str) - put (str) in the message area
1080 ** puthelp(str) - put (str) in the upper helpline
1081 ** pad(str,len) - pad (str) to (len) with spaces
1082 ** drawline(row,detail,list,inverse,*dhelp)
1083 ** - draws a line for (*list) at (row) onscreen. If (detail) is
1084 ** nonzero, include port, IRQ and maddr, if (inverse) is nonzero,
1085 ** draw the line in inverse video, and display (*dhelp) on the
1087 ** drawlist(row,num,detail,list)
1088 ** - draw (num) entries from (list) at (row) onscreen, passile (detail)
1089 ** through to drawline().
1090 ** showparams(dev) - displays the relevant parameters for (dev) below the lists onscreen.
1091 ** yesno(str) - displays (str) in the message area, and returns nonzero on 'y' or 'Y'
1092 ** redraw(); - Redraws the entire screen layout, including the
1093 ** - two list panels.
1098 ** writes (str) at x,y onscreen
1100 ** writes up to (len) of (str) at x,y onscreen.
1102 ** Supports embedded formatting :
1103 ** !i - inverse mode.
1105 ** !n - normal mode.
1108 putxyl(int x, int y, char *str, int len)
1113 while((*str) && (len--))
1115 if (*str == '!') /* format escape? */
1117 switch(*(str+1)) /* depending on the next character */
1121 str +=2; /* skip formatting */
1122 len++; /* doesn't count for length */
1127 str +=2; /* skip formatting */
1128 len++; /* doesn't count for length */
1133 str +=2; /* skip formatting */
1134 len++; /* doesn't count for length */
1138 putchar(*str++); /* not an escape */
1141 putchar(*str++); /* emit the character */
1146 #define putxy(x,y,str) putxyl(x,y,str,-1)
1152 ** Erases the region (x,y,w,h)
1155 erase(int x, int y, int w, int h)
1160 for (i = 0; i < h; i++)
1161 putxyl(x,y++,spaces,w);
1168 ** Writes (str) into the region (x,y,w,h), supports embedded formatting using
1169 ** putxy. Lines are not wrapped, newlines must be forced with \n.
1172 txtbox(int x, int y, int w, int h, char *str)
1177 while((str[i]) && h)
1179 if (str[i] == '\n') /* newline */
1181 putxyl(x,y,str,(i<w)?i:w); /* write lesser of i or w */
1182 y++; /* move down */
1183 h--; /* room for one less */
1184 str += (i+1); /* skip first newline */
1185 i = 0; /* zero offset */
1187 i++; /* next character */
1190 if (h) /* end of string, not region */
1198 ** writes (msg) in the helptext area
1203 erase(0,18,80,3); /* clear area */
1204 txtbox(0,18,80,3,msg);
1211 ** Writes (msg) in the helpline area
1224 ** Draws the help message at the bottom of the screen
1227 masterhelp(char *msg)
1237 ** space-pads a (str) to (len) characters
1240 pad(char *str, int len)
1244 for (i = 0; str[i]; i++) /* find the end of the string */
1246 if (i >= len) /* no padding needed */
1248 while(i < len) /* pad */
1257 ** Displays entry (ofs) of (list) in region at (row) onscreen, optionally displaying
1258 ** the port and IRQ fields if (detail) is nonzero. If (inverse), in inverse video.
1260 ** The text (dhelp) is displayed if the item is a normal device, otherwise
1261 ** help is shown for normal or zoomed comments
1264 drawline(int row, int detail, DEV_LIST *list, int inverse, char *dhelp)
1266 char lbuf[90],nb[70],db[20],ib[16],pb[16];
1268 if (list->comment == DEV_DEVICE)
1271 strncpy(nb+1,list->name,57);
1273 strncpy(nb,list->name,58);
1274 if ((list->comment == DEV_ZOOMED) && (list->next))
1275 if (list->next->comment == DEV_DEVICE) /* only mention if there's something hidden */
1276 strcat(nb," (Collapsed)");
1280 if (list->conflicts) /* device in conflict? */
1284 strcpy(nb+54," !nCONF!i "); /* tag conflict, careful of length */
1286 strcpy(nb+54," !iCONF!n "); /* tag conflict, careful of length */
1289 if (list->comment == DEV_DEVICE)
1291 sprintf(db,"%s%d",list->dev,list->unit);
1296 if ((list->irq > 0) && detail && (list->comment == DEV_DEVICE))
1298 sprintf(ib," %d",list->irq);
1303 if ((list->iobase > 0) && detail && (list->comment == DEV_DEVICE))
1305 sprintf(pb,"0x%x",list->iobase);
1311 sprintf(lbuf," %s%s%s%s%s",inverse?"!i":"",nb,db,ib,pb);
1313 putxyl(0,row,lbuf,80);
1316 switch(list->comment)
1318 case DEV_DEVICE: /* ordinary device */
1324 if (list->next->comment == DEV_DEVICE)
1325 puthelp(" [!bEnter!n] Collapse device list [!bC!n] Collapse all lists");
1330 if (list->next->comment == DEV_DEVICE)
1331 puthelp(" [!bEnter!n] Expand device list [!bX!n] Expand all lists");
1334 puthelp(" WARNING: This list entry corrupted!");
1338 move(0,row); /* put the cursor somewhere relevant */
1345 ** Displays (num) lines of the contents of (list) at (row), optionally displaying the
1346 ** port and IRQ fields as well if (detail) is nonzero
1348 ** printf in the kernel is essentially useless, so we do most of the hard work ourselves here.
1351 drawlist(int row, int num, int detail, DEV_LIST *list)
1355 for(ofs = 0; ofs < num; ofs++)
1359 drawline(row+ofs,detail,list,0,NULL); /* NULL -> don't draw empty help string */
1360 list = nextent(list); /* move down visible list */
1362 erase(0,row+ofs,80,1);
1371 ** Redraws the active list
1380 sprintf(cbuf,"!i%d conflict%s-",conflicts,(conflicts>1)?"s":"");
1383 putxyl(45,0,lines,16);
1385 drawlist(1,8,1,alist); /* draw device lists */
1391 ** Redraws the inactive list
1394 redrawinactive(void)
1396 drawlist(10,7,0,ilist); /* draw device lists */
1403 ** Clear the screen and redraw the entire layout
1410 putxy(3,0,"!bActive!n-!bDrivers");
1411 putxy(63,0,"!bDev!n---!bIRQ!n--!bPort");
1413 putxy(3,9,"!bInactive!n-!bDrivers");
1414 putxy(63,9,"!bDev");
1417 masterhelp(" [!bTAB!n] Change fields [!bQ!n] Save and Exit [!b?!n] Help");
1427 ** Put (str) in the message area, and return 1 if the user hits 'y' or 'Y',
1428 ** 2 if they hit 'c' or 'C', or 0 for 'n' or 'N'.
1431 yesnocancel(char *str)
1457 ** Show device parameters in the region below the lists
1459 ** 0 5 10 15 20 25 30 35 40 45 50 55 60 67 70 75
1460 ** |....|....|....|....|....|....|....|....|....|....|....|....|....|....|....|....
1461 ** +--------------------------------------------------------------------------------+
1462 ** 17-|--------------------------------------------------------------------------------|
1463 ** 18-| Port address : 0x0000 Memory address : 0x00000 Conflict allowed |
1464 ** 19-| IRQ number : 00 Memory size : 0x0000 |
1465 ** 20-| Flags : 0x0000 DRQ number : 00 |
1466 ** 21-|--------------------------------------------------------------------------------|
1469 showparams(DEV_LIST *dev)
1473 erase(0,18,80,3); /* clear area */
1476 if (dev->comment != DEV_DEVICE)
1480 if (dev->iobase > 0)
1482 sprintf(buf,"Port address : 0x%x",dev->iobase);
1488 sprintf(buf,"IRQ number : %d",dev->irq);
1491 sprintf(buf,"Flags : 0x%x",dev->flags);
1495 sprintf(buf,"Memory address : 0x%x",dev->maddr);
1500 sprintf(buf,"Memory size : 0x%x",dev->msize);
1506 sprintf(buf,"DRQ number : %d",dev->drq);
1513 ** Editing functions for device parameters
1515 ** editval(x,y,width,hex,min,max,val) - Edit (*val) in a field (width) wide at (x,y)
1516 ** onscreen. Refuse values outsise (min) and (max).
1517 ** editparams(dev) - Edit the parameters for (dev)
1521 #define VetRet(code) \
1523 if ((i >= min) && (i <= max)) /* legit? */ \
1526 sprintf(buf,hex?"0x%x":"%d",i); \
1527 putxy(hex?x-2:x,y,buf); \
1528 return(code); /* all done and exit */ \
1530 i = *val; /* restore original value */ \
1531 delta = 1; /* restore other stuff */ \
1538 ** Edit (*val) at (x,y) in (hex)?hex:decimal mode, allowing values between (min) and (max)
1539 ** in a field (width) wide. (Allow one space)
1540 ** If (ro) is set, we're in "readonly" mode, so disallow edits.
1542 ** Return KEY_TAB on \t, KEY_EXIT on 'q'
1545 editval(int x, int y, int width, int hex, int min, int max, int *val, int ro)
1547 int i = *val; /* work with copy of the value */
1548 char buf[2+11+1],tc[11+1]; /* display buffer, text copy */
1549 int xp = 0; /* cursor offset into text copy */
1550 int delta = 1; /* force redraw first time in */
1552 int extended = 0; /* stage counter for extended key sequences */
1554 if (hex) /* we presume there's a leading 0x onscreen */
1555 putxy(x-2,y,"!i0x"); /* coz there sure is now */
1559 if (delta) /* only update if necessary */
1561 sprintf(tc,hex?"%x":"%d",i); /* make a text copy of the value */
1562 sprintf(buf,"!i%s",tc); /* format for printing */
1563 erase(x,y,width,1); /* clear the area */
1564 putxy(x,y,buf); /* write */
1565 xp = strlen(tc); /* cursor always at end */
1566 move(x+xp,y); /* position the cursor */
1571 switch(extended) /* escape handling */
1574 if (c == 0x1b) /* esc? */
1576 extended = 1; /* flag and spin */
1580 break; /* nope, drop through */
1582 case 1: /* there was an escape prefix */
1583 if (c == '[' || c == 'O') /* second character in sequence */
1589 return(KEY_EXIT); /* double esc exits */
1591 break; /* nup, not a sequence. */
1595 switch(c) /* looks like the real McCoy */
1598 VetRet(KEY_UP); /* leave if OK */
1601 VetRet(KEY_DOWN); /* leave if OK */
1604 VetRet(KEY_RIGHT); /* leave if OK */
1607 VetRet(KEY_LEFT); /* leave if OK */
1617 case '\t': /* trying to tab off */
1618 VetRet(KEY_TAB); /* verify and maybe return */
1628 case '\177': /* BS or DEL */
1629 if (ro) /* readonly? */
1631 puthelp(" !iThis value cannot be edited (Press ESC)");
1632 while(getchar() != 0x1b); /* wait for key */
1633 return(KEY_NULL); /* spin */
1635 if (xp) /* still something left to delete */
1637 i = (hex ? i/0x10u : i/10); /* strip last digit */
1638 delta = 1; /* force update */
1661 if (ro) /* readonly? */
1663 puthelp(" !iThis value cannot be edited (Press ESC)");
1664 while(getchar() != 0x1b); /* wait for key */
1665 return(KEY_NULL); /* spin */
1667 if (xp >= width) /* no room for more characters anyway */
1671 if ((c >= '0') && (c <= '9'))
1673 i = i*0x10 + (c-'0'); /* update value */
1677 if ((c >= 'a') && (c <= 'f'))
1679 i = i*0x10 + (c-'a'+0xa);
1683 if ((c >= 'A') && (c <= 'F'))
1685 i = i*0x10 + (c-'A'+0xa);
1690 if ((c >= '0') && (c <= '9'))
1692 i = i*10 + (c-'0'); /* update value */
1693 delta = 1; /* force redraw */
1706 ** Edit the parameters for (dev)
1708 ** Note that it's _always_ possible to edit the flags, otherwise it might be
1709 ** possible for this to spin in an endless loop...
1710 ** 0 5 10 15 20 25 30 35 40 45 50 55 60 67 70 75
1711 ** |....|....|....|....|....|....|....|....|....|....|....|....|....|....|....|....
1712 ** +--------------------------------------------------------------------------------+
1713 ** 17-|--------------------------------------------------------------------------------|
1714 ** 18-| Port address : 0x0000 Memory address : 0x00000 Conflict allowed |
1715 ** 19-| IRQ number : 00 Memory size : 0x0000 |
1716 ** 20-| Flags : 0x0000 DRQ number : 00 |
1717 ** 21-|--------------------------------------------------------------------------------|
1719 ** The "intelligence" in this function that hops around based on the directional
1720 ** returns from editval isn't very smart, and depends on the layout above.
1723 editparams(DEV_LIST *dev)
1726 char buf[16]; /* needs to fit the device name */
1728 putxy(2,17,"!bParameters!n-!bfor!n-!bdevice!n-");
1729 sprintf(buf,"!b%s",dev->dev);
1736 if (dev->iobase > 0)
1738 puthelp(" IO Port address (Hexadecimal, 0x1-0xffff)");
1739 ret = editval(18,18,5,1,0x1,0xffff,&(dev->iobase),(dev->attrib & FLG_FIXIOBASE));
1759 puthelp(" Interrupt number (Decimal, 1-15)");
1760 ret = editval(16,19,3,0,1,15,&(dev->irq),(dev->attrib & FLG_FIXIRQ));
1772 if (dev->iobase > 0)
1783 puthelp(" Device-specific flag values.");
1784 ret = editval(18,20,8,1,INT_MIN,INT_MAX,&(dev->flags),0);
1798 if (dev->iobase > 0)
1818 puthelp(" Device memory start address (Hexadecimal, 0x1-0xfffff)");
1819 ret = editval(45,18,6,1,0x1,0xfffff,&(dev->maddr),(dev->attrib & FLG_FIXMADDR));
1826 if (dev->iobase > 0)
1848 puthelp(" Device memory size (Hexadecimal, 0x1-0x10000)");
1849 ret = editval(45,19,5,1,0x1,0x10000,&(dev->msize),(dev->attrib & FLG_FIXMSIZE));
1878 puthelp(" Device DMA request number (Decimal, 1-7)");
1879 ret = editval(43,20,2,0,1,7,&(dev->drq),(dev->attrib & FLG_FIXDRQ));
1902 dev->changed = 1; /* mark as changed */
1905 static char *helptext[] =
1907 " Using the UserConfig kernel settings editor",
1908 " -------------------------------------------",
1914 "The screen displays a list of available drivers, divided into two",
1915 "scrolling lists: Active Drivers, and Inactive Drivers. Each list is",
1916 "by default collapsed and can be expanded to show all the drivers",
1917 "available in each category. The parameters for the currently selected",
1918 "driver are shown at the bottom of the screen.",
1920 "- - Moving around -",
1922 "To move in the current list, use the UP and DOWN cursor keys to select",
1923 "an item (the selected item will be highlighted). If the item is a",
1924 "category name, you may alternatively expand or collapse the list of",
1925 "drivers for that category by pressing [!bENTER!n]. Once the category is",
1926 "expanded, you can select each driver in the same manner and either:",
1928 " - change its parameters using [!bENTER!n]",
1929 " - move it to the Inactive list using [!bDEL!n]",
1931 "Use the [!bTAB!n] key to toggle between the Active and Inactive list; if",
1932 "you need to move a driver from the Inactive list back to the Active",
1933 "one, select it in the Inactive list, using [!bTAB!n] to change lists if",
1934 "necessary, and press [!bENTER!n] -- the device will be moved back to",
1935 "its place in the Active list.",
1937 "- - Altering the list/parameters -",
1939 "Any drivers for devices not installed in your system should be moved",
1940 "to the Inactive list, until there are no remaining parameter conflicts",
1941 "between the drivers, as indicated at the top.",
1943 "Once the list of Active drivers only contains entries for the devices",
1944 "present in your system, you can set their parameters (Interrupt, DMA",
1945 "channel, I/O addresses). To do this, select the driver and press",
1946 "[!bENTER!n]: it is now possible to edit the settings at the",
1947 "bottom of the screen. Use [!bTAB!n] to change fields, and when you are",
1948 "finished, use [!bQ!n] to return to the list.",
1950 "- - Saving changes -",
1952 "When all settings seem correct, and you wish to proceed with the",
1953 "kernel device probing and boot, press [!bQ!n] -- you will be asked to",
1954 "confirm your choice.",
1963 ** Displays help text onscreen for people that are confused, using a simple
1969 int topline = 0; /* where we are in the text */
1970 int line = 0; /* last line we displayed */
1974 for (;;) /* loop until user quits */
1976 /* display help text */
1979 clear(); /* remove everything else */
1980 for (line = topline;
1981 (line < (topline + 24)) && (helptext[line]);
1983 putxy(0,line-topline,helptext[line]);
1988 sprintf(prompt,"!i --%s-- [U]p [D]own [Q]uit !n",helptext[line] ? "MORE" : "END");
1991 c = getchar(); /* so what do they say? */
1998 case 'B': /* wired into 'more' users' fingers */
1999 if (topline > 0) /* room to go up? */
2002 if (topline < 0) /* don't go too far */
2010 case ' ': /* expected by most people */
2011 if (helptext[line]) /* maybe more below? */
2020 redraw(); /* restore the screen */
2028 ** High-level control functions
2035 ** Handle user movement within (*list) in the region starting at (row) onscreen with
2036 ** (num) lines, starting at (*ofs) offset from row onscreen.
2037 ** Pass (detail) on to drawing routines.
2039 ** If the user hits a key other than a cursor key, maybe return a code.
2041 ** (*list) points to the device at the top line in the region, (*ofs) is the
2042 ** position of the highlight within the region. All routines below
2043 ** this take only a device and an absolute row : use ofsent() to find the
2044 ** device, and add (*ofs) to (row) to find the absolute row.
2047 dolist(int row, int num, int detail, int *ofs, DEV_LIST **list, char *dhelp)
2058 showparams(ofsent(*ofs,*list)); /* show device parameters */
2059 drawline(row+*ofs,detail,ofsent(*ofs,*list),1,dhelp); /* highlight current line */
2063 c = getchar(); /* get a character */
2064 if ((extended == 2) || (c==588) || (c==596)) /* console gives "alternative" codes */
2066 extended = 0; /* no longer */
2069 case 588: /* syscons' idea of 'up' */
2071 if (*ofs) /* just a move onscreen */
2073 drawline(row+*ofs,detail,ofsent(*ofs,*list),0,dhelp);/* unhighlight current line */
2074 (*ofs)--; /* move up */
2076 lp = prevent(*list); /* can we go up? */
2079 *list = lp; /* yes, move up list */
2080 drawlist(row,num,detail,*list);
2085 case 596: /* dooby-do */
2086 case 'B': /* down */
2087 lp = ofsent(*ofs,*list); /* get current item */
2089 break; /* nothing more to move to */
2090 drawline(row+*ofs,detail,ofsent(*ofs,*list),0,dhelp); /* unhighlight current line */
2091 if (*ofs < (num-1)) /* room to move onscreen? */
2095 *list = nextent(*list); /* scroll region down */
2096 drawlist(row,num,detail,*list);
2108 case '[': /* cheat : always precedes cursor move */
2109 case 'O': /* ANSI application key mode */
2118 return(KEY_EXIT); /* user requests exit */
2122 return(KEY_DO); /* "do" something */
2127 return(KEY_DEL); /* "delete" response */
2131 return(KEY_UNZOOM); /* expand everything */
2135 return(KEY_ZOOM); /* collapse everything */
2138 drawline(row+*ofs,detail,ofsent(*ofs,*list),0,dhelp); /* unhighlight current line */
2139 return(KEY_TAB); /* "move" response */
2141 case '\014': /* ^L, redraw */
2144 case '?': /* helptext */
2156 ** Do the fullscreen config thang
2161 int actofs = 0, inactofs = 0, mode = 0, ret = -1, i;
2165 initlist(&inactive);
2171 conflicts = findconflict(active); /* find conflicts in the active list only */
2179 case 0: /* active devices */
2180 ret = dolist(1,8,1,&actofs,&alist,
2181 " [!bEnter!n] Edit device parameters [!bDEL!n] Disable device");
2185 mode = 1; /* swap lists */
2202 collapselist(active);
2207 dp = ofsent(actofs,alist); /* get current device */
2208 if (dp) /* paranoia... */
2210 if (dp->attrib & FLG_MANDATORY) /* can't be deleted */
2212 if (dp == alist) /* moving top item on list? */
2216 alist = dp->next; /* point list to non-moving item */
2218 alist = dp->prev; /* end of list, go back instead */
2221 if (!dp->next) /* moving last item on list? */
2224 dp->conflicts = 0; /* no conflicts on the inactive list */
2225 movedev(dp,inactive); /* shift to inactive list */
2226 conflicts = findconflict(active); /* update conflict tags */
2228 redrawactive(); /* redraw */
2233 case KEY_DO: /* edit device parameters */
2234 dp = ofsent(actofs,alist); /* get current device */
2235 if (dp) /* paranoia... */
2237 if (dp->comment == DEV_DEVICE) /* can't edit comments, zoom? */
2239 masterhelp(" [!bTAB!n] Change fields [!bQ!n] Save device parameters");
2241 masterhelp(" [!bTAB!n] Change fields [!bQ!n] Save and Exit [!b?!n] Help");
2243 conflicts = findconflict(active); /* update conflict tags */
2244 }else{ /* DO on comment = zoom */
2245 switch(dp->comment) /* Depends on current state */
2247 case DEV_COMMENT: /* not currently zoomed */
2248 dp->comment = DEV_ZOOMED;
2252 dp->comment = DEV_COMMENT;
2262 case 1: /* inactive devices */
2263 ret = dolist(10,7,0,&inactofs,&ilist,
2264 " [!bEnter!n] Enable device ");
2278 expandlist(inactive);
2285 collapselist(inactive);
2290 dp = ofsent(inactofs,ilist); /* get current device */
2291 if (dp) /* paranoia... */
2293 if (dp->comment == DEV_DEVICE) /* can't move comments, zoom? */
2295 if (dp == ilist) /* moving top of list? */
2299 ilist = dp->next; /* point list to non-moving item */
2301 ilist = dp->prev; /* can't go down, go up instead */
2304 if (!dp->next) /* last entry on list? */
2305 inactofs--; /* shift cursor up one */
2308 movedev(dp,active); /* shift to active list */
2309 conflicts = findconflict(active); /* update conflict tags */
2311 alist = dp; /* put at top and current */
2313 while(dp->comment == DEV_DEVICE)
2314 dp = dp->prev; /* forcibly unzoom section */
2315 dp ->comment = DEV_COMMENT;
2316 mode = 0; /* and swap modes to follow it */
2318 }else{ /* DO on comment = zoom */
2319 switch(dp->comment) /* Depends on current state */
2321 case DEV_COMMENT: /* not currently zoomed */
2322 dp->comment = DEV_ZOOMED;
2326 dp->comment = DEV_COMMENT;
2330 redrawactive(); /* redraw */
2335 default: /* nothing else relevant here */
2340 mode = 0; /* shouldn't happen... */
2343 /* handle returns that are the same for both modes */
2350 i = yesnocancel(" Save these parameters before exiting? ([!bY!n]es/[!bN!n]o/[!bC!n]ancel) ");
2353 case 2: /* cancel */
2357 case 1: /* save and exit */
2359 savelist(inactive,0);
2362 nukelist(active); /* clean up after ourselves */
2372 #endif /* VISUAL_USERCONFIG */
2375 * Copyright (c) 1991 Regents of the University of California.
2376 * All rights reserved.
2377 * Copyright (c) 1994 Jordan K. Hubbard
2378 * All rights reserved.
2379 * Copyright (c) 1994 David Greenman
2380 * All rights reserved.
2382 * Many additional changes by Bruce Evans
2384 * This code is derived from software contributed by the
2385 * University of California Berkeley, Jordan K. Hubbard,
2386 * David Greenman and Bruce Evans.
2388 * Redistribution and use in source and binary forms, with or without
2389 * modification, are permitted provided that the following conditions
2391 * 1. Redistributions of source code must retain the above copyright
2392 * notice, this list of conditions and the following disclaimer.
2393 * 2. Redistributions in binary form must reproduce the above copyright
2394 * notice, this list of conditions and the following disclaimer in the
2395 * documentation and/or other materials provided with the distribution.
2396 * 3. All advertising materials mentioning features or use of this software
2397 * must display the following acknowledgement:
2398 * This product includes software developed by the University of
2399 * California, Berkeley and its contributors.
2400 * 4. Neither the name of the University nor the names of its contributors
2401 * may be used to endorse or promote products derived from this software
2402 * without specific prior written permission.
2404 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2405 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2406 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2407 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2408 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2409 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2410 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2411 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2412 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2413 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2419 #define PARM_DEVSPEC 0x1
2420 #define PARM_INT 0x2
2421 #define PARM_ADDR 0x3
2422 #define PARM_STRING 0x4
2424 typedef struct _cmdparm {
2427 struct uc_device *dparm;
2436 typedef int (*CmdFunc)(CmdParm *);
2438 typedef struct _cmd {
2445 static int lsdevtab(struct uc_device *);
2446 static struct uc_device *find_device(char *, int);
2447 static struct uc_device *search_devtable(struct uc_device *, char *, int);
2448 static void cngets(char *, int);
2449 static Cmd *parse_cmd(char *);
2450 static int parse_args(const char *, CmdParm *);
2451 static int save_dev(struct uc_device *);
2453 static int list_devices(CmdParm *);
2454 static int set_device_ioaddr(CmdParm *);
2455 static int set_device_irq(CmdParm *);
2456 static int set_device_drq(CmdParm *);
2457 static int set_device_iosize(CmdParm *);
2458 static int set_device_mem(CmdParm *);
2459 static int set_device_flags(CmdParm *);
2460 static int set_device_enable(CmdParm *);
2461 static int set_device_disable(CmdParm *);
2462 static int quitfunc(CmdParm *);
2463 static int helpfunc(CmdParm *);
2464 #if defined(INTRO_USERCONFIG)
2465 static int introfunc(CmdParm *);
2472 #include <dev/eisa/eisaconf.h>
2474 static int set_num_eisa_slots(CmdParm *);
2478 static CmdParm addr_parms[] = {
2479 { PARM_DEVSPEC, {} },
2484 static CmdParm int_parms[] = {
2485 { PARM_DEVSPEC, {} },
2490 static CmdParm dev_parms[] = {
2491 { PARM_DEVSPEC, {} },
2496 static CmdParm int_arg[] = {
2502 static Cmd CmdList[] = {
2503 { "?", helpfunc, NULL }, /* ? (help) */
2504 { "di", set_device_disable, dev_parms }, /* disable dev */
2505 { "dr", set_device_drq, int_parms }, /* drq dev # */
2507 { "ei", set_num_eisa_slots, int_arg }, /* # EISA slots */
2509 { "en", set_device_enable, dev_parms }, /* enable dev */
2510 { "ex", quitfunc, NULL }, /* exit (quit) */
2511 { "f", set_device_flags, int_parms }, /* flags dev mask */
2512 { "h", helpfunc, NULL }, /* help */
2513 #if defined(INTRO_USERCONFIG)
2514 { "intro", introfunc, NULL }, /* intro screen */
2516 { "iom", set_device_mem, addr_parms }, /* iomem dev addr */
2517 { "ios", set_device_iosize, int_parms }, /* iosize dev size */
2518 { "ir", set_device_irq, int_parms }, /* irq dev # */
2519 { "l", list_devices, NULL }, /* ls, list */
2520 { "po", set_device_ioaddr, int_parms }, /* port dev addr */
2521 { "res", (CmdFunc)cpu_reset, NULL }, /* reset CPU */
2522 { "q", quitfunc, NULL }, /* quit */
2523 #ifdef VISUAL_USERCONFIG
2524 { "v", (CmdFunc)visuserconfig, NULL }, /* visual mode */
2526 { NULL, NULL, NULL },
2532 static char banner = 1;
2538 init_config_script();
2541 /* Only display signon banner if we are about to go interactive */
2542 if (!has_config_script()) {
2543 if (!(boothowto & RB_CONFIG))
2544 #ifdef INTRO_USERCONFIG
2551 printf("FreeBSD Kernel Configuration Utility - Version 1.2\n"
2552 " Type \"help\" for help"
2553 #ifdef VISUAL_USERCONFIG
2554 " or \"visual\" to go to the visual\n"
2555 " configuration interface (requires MGA/VGA display or\n"
2556 " serial terminal capable of displaying ANSI graphics)"
2564 if (input[0] == '\0')
2566 cmd = parse_cmd(input);
2568 printf("Invalid command or syntax. Type `?' for help.\n");
2571 rval = (*cmd->handler)(cmd->parms);
2580 parse_cmd(char *cmd)
2584 for (cp = CmdList; cp->name; cp++) {
2585 int len = strlen(cp->name);
2587 if (!strncmp(cp->name, cmd, len)) {
2588 while (*cmd && *cmd != ' ' && *cmd != '\t')
2590 if (parse_args(cmd, cp->parms))
2600 parse_args(const char *cmd, CmdParm *parms)
2605 if (*cmd == ' ' || *cmd == '\t') {
2609 if (parms == NULL || parms->type == -1) {
2612 printf("Extra arg(s): %s\n", cmd);
2615 if (parms->type == PARM_DEVSPEC) {
2620 while (*cmd && !(*cmd == ' ' || *cmd == '\t' ||
2621 (*cmd >= '0' && *cmd <= '9')))
2622 devname[i++] = *(cmd++);
2624 if (*cmd >= '0' && *cmd <= '9') {
2625 unit = strtoul(cmd, &ptr, 10);
2627 printf("Invalid device number\n");
2628 /* XXX should print invalid token here and elsewhere. */
2631 /* XXX else should require end of token. */
2634 if ((parms->parm.dparm = find_device(devname, unit)) == NULL) {
2635 printf("No such device: %s%d\n", devname, unit);
2641 if (parms->type == PARM_INT) {
2642 parms->parm.iparm = strtoul(cmd, &ptr, 0);
2644 printf("Invalid numeric argument\n");
2651 if (parms->type == PARM_ADDR) {
2652 parms->parm.u.aparm = (void *)(uintptr_t)strtoul(cmd, &ptr, 0);
2654 printf("Invalid address argument\n");
2661 if (parms->type == PARM_STRING) {
2662 parms->parm.u.sparm = cmd;
2670 list_devices(CmdParm *parms)
2673 if (lsdevtab(uc_devtab)) return 0;
2675 printf("\nNumber of EISA slots to probe: %d\n", num_eisa_slots);
2681 set_device_ioaddr(CmdParm *parms)
2683 parms[0].parm.dparm->id_iobase = parms[1].parm.iparm;
2684 save_dev(parms[0].parm.dparm);
2689 set_device_irq(CmdParm *parms)
2693 irq = parms[1].parm.iparm;
2695 printf("Warning: Remapping IRQ 2 to IRQ 9\n");
2698 else if (irq != -1 && irq > 15) {
2699 printf("An IRQ > 15 would be invalid.\n");
2702 parms[0].parm.dparm->id_irq = (irq < 16 ? 1 << irq : 0);
2703 save_dev(parms[0].parm.dparm);
2708 set_device_drq(CmdParm *parms)
2713 * The bounds checking is just to ensure that the value can be printed
2714 * in 5 characters. 32768 gets converted to -32768 and doesn't fit.
2716 drq = parms[1].parm.iparm;
2717 parms[0].parm.dparm->id_drq = (drq < 32768 ? drq : -1);
2718 save_dev(parms[0].parm.dparm);
2723 set_device_iosize(CmdParm *parms)
2725 parms[0].parm.dparm->id_msize = parms[1].parm.iparm;
2726 save_dev(parms[0].parm.dparm);
2731 set_device_mem(CmdParm *parms)
2733 parms[0].parm.dparm->id_maddr = parms[1].parm.u.aparm;
2734 save_dev(parms[0].parm.dparm);
2739 set_device_flags(CmdParm *parms)
2741 parms[0].parm.dparm->id_flags = parms[1].parm.iparm;
2742 save_dev(parms[0].parm.dparm);
2747 set_device_enable(CmdParm *parms)
2749 parms[0].parm.dparm->id_enabled = TRUE;
2750 save_dev(parms[0].parm.dparm);
2755 set_device_disable(CmdParm *parms)
2757 parms[0].parm.dparm->id_enabled = FALSE;
2758 save_dev(parms[0].parm.dparm);
2764 set_num_eisa_slots(CmdParm *parms)
2768 num_slots = parms[0].parm.iparm;
2769 num_eisa_slots = (num_slots <= 16 ? num_slots : 10);
2775 quitfunc(CmdParm *parms)
2778 * If kernel config supplied, and we are parsing it, and -c also supplied,
2779 * ignore a quit command, This provides a safety mechanism to allow
2780 * recovery from a damaged/buggy kernel config.
2782 if ((boothowto & RB_CONFIG) && userconfig_boot_parsing)
2788 helpfunc(CmdParm *parms)
2791 "Command\t\t\tDescription\n"
2792 "-------\t\t\t-----------\n"
2793 "ls\t\t\tList currently configured devices\n"
2794 "port <devname> <addr>\tSet device port (i/o address)\n"
2795 "irq <devname> <number>\tSet device irq\n"
2796 "drq <devname> <number>\tSet device drq\n"
2797 "iomem <devname> <addr>\tSet device maddr (memory address)\n"
2798 "iosize <devname> <size>\tSet device memory size\n"
2799 "flags <devname> <mask>\tSet device flags\n"
2800 "enable <devname>\tEnable device\n"
2801 "disable <devname>\tDisable device (will not be probed)\n");
2803 printf("eisa <number>\t\tSet the number of EISA slots to probe\n");
2806 "quit\t\t\tExit this configuration utility\n"
2807 "reset\t\t\tReset CPU\n");
2808 #ifdef VISUAL_USERCONFIG
2809 printf("visual\t\t\tGo to fullscreen mode.\n");
2812 "help\t\t\tThis message\n\n"
2813 "Commands may be abbreviated to a unique prefix\n");
2817 #if defined(INTRO_USERCONFIG)
2819 #if defined (VISUAL_USERCONFIG)
2821 center(int y, char *str)
2823 putxy((80 - strlen(str)) / 2, y, str);
2828 introfunc(CmdParm *parms)
2830 #if defined (VISUAL_USERCONFIG)
2831 int curr_item, first_time, extended = 0;
2832 static char *choices[] = {
2833 " Skip kernel configuration and continue with installation ",
2834 " Start kernel configuration in full-screen visual mode ",
2835 " Start kernel configuration in CLI mode ",
2839 center(2, "!bKernel Configuration Menu!n");
2848 for (i = 0; i < 3; i++) {
2852 strcat(tmp, choices[i]);
2855 putxy(10, 5 + i, tmp);
2859 putxy(2, 10, "Here you have the chance to go into kernel configuration mode, making");
2860 putxy(2, 11, "any changes which may be necessary to properly adjust the kernel to");
2861 putxy(2, 12, "match your hardware configuration.");
2862 putxy(2, 14, "If you are installing FreeBSD for the first time, select Visual Mode");
2863 putxy(2, 15, "(press Down-Arrow then ENTER).");
2864 putxy(2, 17, "If you need to do more specialized kernel configuration and are an");
2865 putxy(2, 18, "experienced FreeBSD user, select CLI mode.");
2866 putxy(2, 20, "If you are !icertain!n that you do not need to configure your kernel");
2867 putxy(2, 21, "then simply press ENTER or Q now.");
2871 move(0, 0); /* move the cursor out of the way */
2874 if ((extended == 2) || (c == 588) || (c == 596)) { /* console gives "alternative" codes */
2875 extended = 0; /* no longer */
2884 case 'B': /* down */
2896 case '[': /* cheat : always precedes cursor move */
2897 case 'O': /* ANSI application key mode */
2908 return 1; /* user requests exit */
2910 case '1': /* select an item */
2934 case 'D': /* down */
2947 else if (curr_item == 1)
2948 return visuserconfig();
2950 putxy(0, 1, "Type \"help\" for help or \"quit\" to exit.");
2951 /* enable quitfunc */
2952 userconfig_boot_parsing=0;
2954 boothowto |= RB_CONFIG; /* force -c */
2966 lsdevtab(struct uc_device *dt)
2968 for (; dt->id_id != 0; dt++) {
2973 if (!userconfig_boot_parsing) {
2974 if (getchar() == 'q') {
2984 "Device port irq drq iomem iosize unit flags enab\n"
2988 sprintf(dname, "%s%d", dt->id_name, dt->id_unit);
2989 printf("%-9.9s%-#11x%-6d%-6d%-8p%-9d%-6d%-#11x%-5s\n",
2990 dname, /* dt->id_id, dt->id_driver(by name), */ dt->id_iobase,
2991 ffs(dt->id_irq) - 1, dt->id_drq, dt->id_maddr, dt->id_msize,
2992 /* dt->id_intr(by name), */ dt->id_unit, dt->id_flags,
2993 dt->id_enabled ? "Yes" : "No");
3003 int count = resource_count();
3009 uc_devtab = malloc(sizeof(struct uc_device) * (count + 1), M_DEVL,
3012 for (i = 0; i < count; i++) {
3013 name = resource_query_name(i);
3014 unit = resource_query_unit(i);
3016 continue; /* skip wildcards */
3017 uc_devtab[dt].id_id = id++;
3018 resource_int_value(name, unit, "port", &uc_devtab[dt].id_iobase);
3020 resource_int_value(name, unit, "irq", &val);
3021 uc_devtab[dt].id_irq = (1 << val);
3022 resource_int_value(name, unit, "drq", &uc_devtab[dt].id_drq);
3023 resource_int_value(name, unit, "maddr",(int *)&uc_devtab[dt].id_maddr);
3024 resource_int_value(name, unit, "msize", &uc_devtab[dt].id_msize);
3025 uc_devtab[dt].id_unit = unit;
3026 resource_int_value(name, unit, "flags", &uc_devtab[dt].id_flags);
3028 resource_int_value(name, unit, "disabled", &val);
3029 uc_devtab[dt].id_enabled = !val;
3030 uc_devtab[dt].id_name = malloc(strlen(name) + 1, M_DEVL,M_WAITOK);
3031 strcpy(uc_devtab[dt].id_name, name);
3040 int count = resource_count();
3042 for (i = 0; i < count; i++)
3043 if (uc_devtab[i].id_name)
3044 free(uc_devtab[i].id_name, M_DEVL);
3045 free(uc_devtab, M_DEVL);
3048 static struct uc_device *
3049 find_device(char *devname, int unit)
3051 struct uc_device *ret;
3053 if ((ret = search_devtable(uc_devtab, devname, unit)) != NULL)
3058 static struct uc_device *
3059 search_devtable(struct uc_device *dt, char *devname, int unit)
3063 for (i = 0; dt->id_id != 0; dt++)
3064 if (!strcmp(dt->id_name, devname) && dt->id_unit == unit)
3070 cngets(char *input, int maxin)
3076 /* Treat ^H or ^? as backspace */
3077 if ((c == '\010' || c == '\177')) {
3079 printf("\010 \010");
3080 *--input = '\0', --nchars;
3084 /* Treat ^U or ^X as kill line */
3085 else if ((c == '\025' || c == '\030')) {
3087 printf("\010 \010");
3088 *--input = '\0', --nchars;
3093 if ((++nchars == maxin) || (c == '\n') || (c == '\r') || ( c == -1)) {
3097 *input++ = (u_char)c;
3102 save_resource(struct uc_device *idev)
3107 name = idev->id_name;
3108 unit = idev->id_unit;
3109 resource_set_int(name, unit, "port", idev->id_iobase);
3110 resource_set_int(name, unit, "irq", ffs(idev->id_irq) - 1);
3111 resource_set_int(name, unit, "drq", idev->id_drq);
3112 resource_set_int(name, unit, "maddr", (int)idev->id_maddr);
3113 resource_set_int(name, unit, "msize", idev->id_msize);
3114 resource_set_int(name, unit, "flags", idev->id_flags);
3115 resource_set_int(name, unit, "disabled", !idev->id_enabled);
3120 struct uc_device *idev;
3122 struct uc_device *id_p,*id_pn;
3123 char *name = idev->id_name;
3125 for (id_p = uc_devlist; id_p; id_p = id_p->id_next) {
3126 if (id_p->id_id == idev->id_id) {
3127 id_pn = id_p->id_next;
3129 free(id_p->id_name, M_DEVL);
3130 bcopy(idev,id_p,sizeof(struct uc_device));
3131 save_resource(idev);
3132 id_p->id_name = malloc(strlen(name)+1, M_DEVL,M_WAITOK);
3133 strcpy(id_p->id_name, name);
3134 id_p->id_next = id_pn;
3138 id_pn = malloc(sizeof(struct uc_device),M_DEVL,M_WAITOK);
3139 bcopy(idev,id_pn,sizeof(struct uc_device));
3140 save_resource(idev);
3141 id_pn->id_name = malloc(strlen(name) + 1, M_DEVL,M_WAITOK);
3142 strcpy(id_pn->id_name, name);
3143 id_pn->id_next = uc_devlist;