autoconf.c revision 47444
14Srgrimes/*- 24Srgrimes * Copyright (c) 1990 The Regents of the University of California. 34Srgrimes * All rights reserved. 44Srgrimes * 54Srgrimes * This code is derived from software contributed to Berkeley by 64Srgrimes * William Jolitz. 74Srgrimes * 84Srgrimes * Redistribution and use in source and binary forms, with or without 94Srgrimes * modification, are permitted provided that the following conditions 104Srgrimes * are met: 114Srgrimes * 1. Redistributions of source code must retain the above copyright 124Srgrimes * notice, this list of conditions and the following disclaimer. 134Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 144Srgrimes * notice, this list of conditions and the following disclaimer in the 154Srgrimes * documentation and/or other materials provided with the distribution. 164Srgrimes * 3. All advertising materials mentioning features or use of this software 174Srgrimes * must display the following acknowledgement: 184Srgrimes * This product includes software developed by the University of 194Srgrimes * California, Berkeley and its contributors. 204Srgrimes * 4. Neither the name of the University nor the names of its contributors 214Srgrimes * may be used to endorse or promote products derived from this software 224Srgrimes * without specific prior written permission. 234Srgrimes * 244Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 254Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 264Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 274Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 284Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 294Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 304Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 314Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 324Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 334Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 344Srgrimes * SUCH DAMAGE. 354Srgrimes * 36620Srgrimes * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91 3747444Sjb * $Id: autoconf.c,v 1.122 1999/05/12 07:40:50 phk Exp $ 384Srgrimes */ 394Srgrimes 404Srgrimes/* 414Srgrimes * Setup the system to run on the current machine. 424Srgrimes * 438876Srgrimes * Configure() is called at boot time and initializes the vba 444Srgrimes * device tables and the memory controller monitoring. Available 454Srgrimes * devices are determined (from possibilities mentioned in ioconf.c), 464Srgrimes * and the drivers are initialized. 474Srgrimes */ 4832358Seivind#include "opt_bootp.h" 4932726Seivind#include "opt_ffs.h" 5025460Sjoerg#include "opt_cd9660.h" 5137272Sjmg#include "opt_nfsroot.h" 5245720Speter#include "opt_bus.h" 5346806Sphk#include "opt_rootdevname.h" 5425164Speter 552056Swollman#include <sys/param.h> 562056Swollman#include <sys/systm.h> 5745720Speter#include <sys/bus.h> 582056Swollman#include <sys/conf.h> 5931328Speter#include <sys/disklabel.h> 6036809Sbde#include <sys/diskslice.h> 612056Swollman#include <sys/reboot.h> 622056Swollman#include <sys/kernel.h> 6336809Sbde#include <sys/malloc.h> 6412604Sbde#include <sys/mount.h> 6512649Speter#include <sys/sysctl.h> 664Srgrimes 6720641Sbde#include <machine/bootinfo.h> 6810665Sbde#include <machine/cons.h> 6931337Sbde#include <machine/ipl.h> 707090Sbde#include <machine/md_var.h> 7127288Sfsmp#ifdef APIC_IO 7225164Speter#include <machine/smp.h> 7325164Speter#endif /* APIC_IO */ 7427288Sfsmp 7536809Sbde#include <i386/isa/icu.h> 7625164Speter 7729243Sjmg#include "pnp.h" 7829243Sjmg#if NPNP > 0 7946600Speter#include <i386/isa/isa_device.h> 8029243Sjmg#include <i386/isa/pnp.h> 8129243Sjmg#endif 8229243Sjmg 8312604Sbde#include "eisa.h" 8412604Sbde#if NEISA > 0 8512604Sbde#include <i386/eisa/eisaconf.h> 8612604Sbde#endif 8710665Sbde 8812604Sbde#include "pci.h" 8912604Sbde#if NPCI > 0 9012604Sbde#include <pci/pcivar.h> 9112604Sbde#endif 92798Swollman 9346915Speter#include "isa.h" 9446915Speter#if NISA > 0 9546915Speterdevice_t isa_bus_device = 0; 9646915Speter#endif 9746915Speter 9842817Speterstatic void configure_first __P((void *)); 9912604Sbdestatic void configure __P((void *)); 10042817Speterstatic void configure_final __P((void *)); 10112604Sbde 10212848Sbdestatic void configure_finish __P((void)); 10312848Sbdestatic void configure_start __P((void)); 10412848Sbdestatic int setdumpdev __P((dev_t dev)); 10547444Sjb#if defined(FFS) || defined(FFS_ROOT) 10612848Sbdestatic void setroot __P((void)); 10747444Sjb#endif 10846806Sphkstatic int setrootbyname __P((char *name)); 10946806Sphkstatic void gets __P((char *)); 11012848Sbde 11142817SpeterSYSINIT(configure1, SI_SUB_CONFIGURE, SI_ORDER_FIRST, configure_first, NULL); 11242817Speter/* SI_ORDER_SECOND is hookable */ 11342817SpeterSYSINIT(configure2, SI_SUB_CONFIGURE, SI_ORDER_THIRD, configure, NULL); 11442817Speter/* SI_ORDER_MIDDLE is hookable */ 11542817SpeterSYSINIT(configure3, SI_SUB_CONFIGURE, SI_ORDER_ANY, configure_final, NULL); 11642817Speter 11746806Sphkdev_t rootdev = NODEV; 11846806Sphkdev_t dumpdev = NODEV; 11942817Speter 12039982Sobrien#if defined(CD9660) || defined(CD9660_ROOT) 12122521Sdyson 12225460Sjoerg#include <sys/fcntl.h> 12325460Sjoerg#include <sys/proc.h> 12425460Sjoerg#include <sys/stat.h> 12525460Sjoerg#include <machine/clock.h> 12622521Sdyson 12725460Sjoerg/* 12825460Sjoerg * XXX All this CD-ROM root stuff is fairly messy. Ick. 12925460Sjoerg * 13025460Sjoerg * We need to try out all our potential CDROM drives, so we need a table. 13125460Sjoerg */ 1327731Sphkstatic struct { 1337731Sphk char *name; 1347731Sphk int major; 1357731Sphk} try_cdrom[] = { 1367731Sphk { "cd", 6 }, 1377731Sphk { "mcd", 7 }, 1387731Sphk { "scd", 16 }, 1397731Sphk { "matcd", 17 }, 14025460Sjoerg { "wcd", 19 }, 1417731Sphk { 0, 0} 1427731Sphk}; 1437731Sphk 14425460Sjoergstatic int find_cdrom_root __P((void)); 14512604Sbde 14612604Sbdestatic int 14725460Sjoergfind_cdrom_root() 1487731Sphk{ 14925460Sjoerg int i, j, error; 15037389Sjulian struct cdevsw *bd; 15125460Sjoerg dev_t orootdev; 1527731Sphk 15325460Sjoerg#if CD9660_ROOTDELAY > 0 15425460Sjoerg DELAY(CD9660_ROOTDELAY * 1000000); 15525460Sjoerg#endif 15625460Sjoerg orootdev = rootdev; 15725460Sjoerg for (i = 0 ; i < 2; i++) 15825460Sjoerg for (j = 0 ; try_cdrom[j].name ; j++) { 15925460Sjoerg if (try_cdrom[j].major >= nblkdev) 16025460Sjoerg continue; 16125460Sjoerg rootdev = makedev(try_cdrom[j].major, i * 8); 16246676Sphk bd = bdevsw(rootdev); 16325460Sjoerg if (bd == NULL || bd->d_open == NULL) 16425460Sjoerg continue; 16525460Sjoerg if (bootverbose) 16625460Sjoerg printf("trying %s%d as rootdev (0x%x)\n", 16725460Sjoerg try_cdrom[j].name, i, rootdev); 16825460Sjoerg error = (bd->d_open)(rootdev, FREAD, S_IFBLK, curproc); 16925460Sjoerg if (error == 0) { 17025460Sjoerg if (bd->d_close != NULL) 17125460Sjoerg (bd->d_close)(rootdev, FREAD, S_IFBLK, 17225460Sjoerg curproc); 17325460Sjoerg return 0; 17425460Sjoerg } 1757731Sphk } 17625460Sjoerg 17725460Sjoerg rootdev = orootdev; 1787731Sphk return EINVAL; 1797731Sphk} 18039982Sobrien#endif /* CD9660 || CD9660_ROOT */ 1817731Sphk 18212604Sbdestatic void 1837818Sdufaultconfigure_start() 1847818Sdufault{ 1857818Sdufault} 1867818Sdufault 18712604Sbdestatic void 1887818Sdufaultconfigure_finish() 1897818Sdufault{ 1907818Sdufault} 1917818Sdufault 19245720Speterdevice_t nexus_dev; 19345720Speter 1944Srgrimes/* 1954Srgrimes * Determine i/o configuration for a machine. 1964Srgrimes */ 19710665Sbdestatic void 19842817Speterconfigure_first(dummy) 19942817Speter void *dummy; 20042817Speter{ 20142817Speter 20242817Speter configure_start(); /* DDB hook? */ 20342817Speter} 20442817Speter 20542817Speterstatic void 20610665Sbdeconfigure(dummy) 20710653Sdg void *dummy; 2084Srgrimes{ 2094Srgrimes 21012791Sgibbs /* Allow all routines to decide for themselves if they want intrs */ 21129675Sgibbs /* 21229675Sgibbs * XXX Since this cannot be achieved on all architectures, we should 21329675Sgibbs * XXX go back to disabling all interrupts until configuration is 21429675Sgibbs * XXX completed and switch any devices that rely on the current 21529675Sgibbs * XXX behavior to no longer rely on interrupts or to register an 21629675Sgibbs * XXX interrupt_driven_config_hook for the task. 21729675Sgibbs */ 21831336Sbde /* 21931336Sbde * XXX The above is wrong, because we're implicitly at splhigh(), 22031336Sbde * XXX and should stay there, so enabling interrupts in the CPU 22131336Sbde * XXX and the ICU at most gives pending interrupts which just get 22231336Sbde * XXX in the way. 22331336Sbde */ 22427288Sfsmp#ifdef APIC_IO 22527288Sfsmp bsp_apic_configure(); 22625172Speter enable_intr(); 22727288Sfsmp#else 22827288Sfsmp enable_intr(); 22925172Speter INTREN(IRQ_SLAVE); 23027288Sfsmp#endif /* APIC_IO */ 23112791Sgibbs 23229243Sjmg#if NPNP > 0 23329243Sjmg pnp_configure(); 23429243Sjmg#endif 23529243Sjmg 23645720Speter /* nexus0 is the top of the i386 device tree */ 23745720Speter device_add_child(root_bus, "nexus", 0, 0); 23812791Sgibbs 23938779Snsouch /* initialize new bus architecture */ 24038779Snsouch root_bus_configure(); 24138779Snsouch 24245720Speter#if NISA > 0 24345720Speter if (isa_bus_device) 24445720Speter bus_generic_attach(isa_bus_device); 24545720Speter#endif 24645720Speter 24731336Sbde /* 24831336Sbde * Now we're ready to handle (pending) interrupts. 24931336Sbde * XXX this is slightly misplaced. 25031336Sbde */ 25131336Sbde spl0(); 25231336Sbde 25331337Sbde /* 25431337Sbde * Allow lowering of the ipl to the lowest kernel level if we 25531337Sbde * panic (or call tsleep() before clearing `cold'). No level is 25631337Sbde * completely safe (since a panic may occur in a critical region 25731337Sbde * at splhigh()), but we want at least bio interrupts to work. 25831337Sbde */ 25931337Sbde safepri = cpl; 26042817Speter} 26131337Sbde 26242817Speterstatic void 26342817Speterconfigure_final(dummy) 26442817Speter void *dummy; 26542817Speter{ 26642817Speter int i; 26722564Sbde 26842817Speter configure_finish(); /* DDB hook? */ 2697818Sdufault 27010665Sbde cninit_finish(); 27110665Sbde 27220641Sbde if (bootverbose) { 27327561Sfsmp 27427561Sfsmp#ifdef APIC_IO 27527615Sfsmp imen_dump(); 27627561Sfsmp#endif /* APIC_IO */ 27727561Sfsmp 27820641Sbde /* 27920641Sbde * Print out the BIOS's idea of the disk geometries. 28020641Sbde */ 28120641Sbde printf("BIOS Geometries:\n"); 28220641Sbde for (i = 0; i < N_BIOS_GEOM; i++) { 28320641Sbde unsigned long bios_geom; 28420641Sbde int max_cylinder, max_head, max_sector; 28520641Sbde 28620641Sbde bios_geom = bootinfo.bi_bios_geom[i]; 28720641Sbde 28820641Sbde /* 28920641Sbde * XXX the bootstrap punts a 1200K floppy geometry 29020641Sbde * when the get-disk-geometry interrupt fails. Skip 29120641Sbde * drives that have this geometry. 29220641Sbde */ 29320641Sbde if (bios_geom == 0x4f010f) 29420641Sbde continue; 29520641Sbde 29620641Sbde printf(" %x:%08lx ", i, bios_geom); 29720641Sbde max_cylinder = bios_geom >> 16; 29820641Sbde max_head = (bios_geom >> 8) & 0xff; 29920641Sbde max_sector = bios_geom & 0xff; 30020641Sbde printf( 30120641Sbde "0..%d=%d cylinders, 0..%d=%d heads, 1..%d=%d sectors\n", 30220641Sbde max_cylinder, max_cylinder + 1, 30320641Sbde max_head, max_head + 1, 30420641Sbde max_sector, max_sector); 30520641Sbde } 30620641Sbde printf(" %d accounted for\n", bootinfo.bi_n_bios_used); 30720641Sbde 30816075Sjoerg printf("Device configuration finished.\n"); 30920641Sbde } 31029675Sgibbs cold = 0; 31129675Sgibbs} 31216075Sjoerg 31335319Sjulian 31429675Sgibbsvoid 31529675Sgibbscpu_rootconf() 31629675Sgibbs{ 31729675Sgibbs /* 31829675Sgibbs * XXX NetBSD has a much cleaner approach to finding root. 31929675Sgibbs * XXX We should adopt their code. 32029675Sgibbs */ 32139982Sobrien#if defined(CD9660) || defined(CD9660_ROOT) 32222521Sdyson if ((boothowto & RB_CDROM)) { 32316075Sjoerg if (bootverbose) 32416075Sjoerg printf("Considering CD-ROM root f/s.\n"); 32525460Sjoerg /* NB: find_cdrom_root() sets rootdev if successful. */ 32625460Sjoerg if (find_cdrom_root() == 0) 32725460Sjoerg mountrootfsname = "cd9660"; 32825460Sjoerg else if (bootverbose) 32925460Sjoerg printf("No CD-ROM available as root f/s.\n"); 33016075Sjoerg } 3317731Sphk#endif 3328007Sphk 33325723Stegge#ifdef BOOTP_NFSROOT 33425723Stegge if (!mountrootfsname && !nfs_diskless_valid) { 33525723Stegge if (bootverbose) 33625723Stegge printf("Considering BOOTP NFS root f/s.\n"); 33725723Stegge mountrootfsname = "nfs"; 33825723Stegge } 33925723Stegge#endif /* BOOTP_NFSROOT */ 34039982Sobrien#if defined(NFS) || defined(NFS_ROOT) 34122564Sbde if (!mountrootfsname && nfs_diskless_valid) { 34222564Sbde if (bootverbose) 34322564Sbde printf("Considering NFS root f/s.\n"); 34422564Sbde mountrootfsname = "nfs"; 34522564Sbde } 34622564Sbde#endif /* NFS */ 34722564Sbde 34839982Sobrien#if defined(FFS) || defined(FFS_ROOT) 34922521Sdyson if (!mountrootfsname) { 35022521Sdyson mountrootfsname = "ufs"; 35116075Sjoerg if (bootverbose) 35216075Sjoerg printf("Considering FFS root f/s.\n"); 35345703Sbde if (boothowto & RB_ASKNAME) 35445703Sbde setconf(); 35545703Sbde else 3565321Sjkh setroot(); 3573795Sphk } 3584Srgrimes#endif 35922564Sbde 36022521Sdyson if (!mountrootfsname) { 3614370Sphk panic("Nobody wants to mount my root for me"); 3624370Sphk } 36329675Sgibbs} 36417355Sbde 36535319Sjulian 36629675Sgibbsvoid 36729675Sgibbscpu_dumpconf() 36829675Sgibbs{ 36929675Sgibbs if (setdumpdev(dumpdev) != 0) 37029675Sgibbs dumpdev = NODEV; 3714Srgrimes} 3724Srgrimes 37312722Sphkstatic int 3748833Sdgsetdumpdev(dev) 3758833Sdg dev_t dev; 3768481Swollman{ 3778833Sdg int maj, psize; 3788833Sdg long newdumplo; 3798833Sdg 3808833Sdg if (dev == NODEV) { 3818481Swollman dumpdev = dev; 3828833Sdg return (0); 3838481Swollman } 3848833Sdg maj = major(dev); 38546773Sphk if (maj >= nblkdev || bdevsw(dev) == NULL) 38612889Speter return (ENXIO); /* XXX is this right? */ 38746773Sphk if (bdevsw(dev)->d_psize == NULL) 38812889Speter return (ENXIO); /* XXX should be ENODEV ? */ 38946773Sphk psize = bdevsw(dev)->d_psize(dev); 3908833Sdg if (psize == -1) 39112889Speter return (ENXIO); /* XXX should be ENODEV ? */ 39231316Sbde /* 39331316Sbde * XXX should clean up checking in dumpsys() to be more like this, 39431316Sbde * and nuke dodump sysctl (too many knobs), and move this to 39531316Sbde * kern_shutdown.c... 39631316Sbde */ 39715538Sphk newdumplo = psize - Maxmem * PAGE_SIZE / DEV_BSIZE; 3988833Sdg if (newdumplo < 0) 3998833Sdg return (ENOSPC); 4008833Sdg dumpdev = dev; 4018833Sdg dumplo = newdumplo; 4028833Sdg return (0); 4038876Srgrimes} 4048481Swollman 40535319Sjulian 4068833Sdgu_long bootdev = 0; /* not a dev_t - encoding is different */ 4074Srgrimes 4081289Sache#define FDMAJOR 2 4091290Sache#define FDUNITSHIFT 6 4104Srgrimes 41147444Sjb#if defined(FFS) || defined(FFS_ROOT) 4124Srgrimes/* 4134Srgrimes * Attempt to find the device from which we were booted. 4144Srgrimes * If we can do so, and not instructed not to do so, 41536809Sbde * set rootdevs[] and rootdevnames[] to correspond to the 41636809Sbde * boot device(s). 4174Srgrimes */ 418798Swollmanstatic void 4194Srgrimessetroot() 4204Srgrimes{ 42136809Sbde int majdev, mindev, unit, slice, part; 42246773Sphk dev_t newrootdev, dev; 42336809Sbde char partname[2]; 42436809Sbde char *sname; 4254Srgrimes 42646806Sphk if (boothowto & RB_DFLTROOT) { 42746808Sphk#ifdef ROOTDEVNAME 42846806Sphk setrootbyname(ROOTDEVNAME); 42946808Sphk#else 43046808Sphk setconf(); 43146808Sphk#endif 4324Srgrimes return; 43346806Sphk } 43446806Sphk if ((bootdev & B_MAGICMASK) != B_DEVMAGIC) 43546806Sphk return; 43636809Sbde majdev = B_TYPE(bootdev); 43746773Sphk dev = makedev(majdev, 0); 43846773Sphk if (majdev >= nblkdev || bdevsw(dev) == NULL) 43936809Sbde return; 44036809Sbde unit = B_UNIT(bootdev); 44136809Sbde slice = B_SLICE(bootdev); 44236809Sbde if (slice == WHOLE_DISK_SLICE) 44334624Smsmith slice = COMPATIBILITY_SLICE; 44436809Sbde if (slice < 0 || slice >= MAX_SLICES) 4454Srgrimes return; 44636809Sbde 44736809Sbde /* 44836809Sbde * XXX kludge for inconsistent unit numbering and lack of slice 44936809Sbde * support for floppies. 45036809Sbde */ 4511290Sache if (majdev == FDMAJOR) { 45236809Sbde slice = COMPATIBILITY_SLICE; 4532400Sache part = RAW_PART; 4541290Sache mindev = unit << FDUNITSHIFT; 45536809Sbde } else { 45636809Sbde part = B_PARTITION(bootdev); 45734622Smsmith mindev = dkmakeminor(unit, slice, part); 4581290Sache } 45936809Sbde 46036809Sbde newrootdev = makedev(majdev, mindev); 46136809Sbde rootdevs[0] = newrootdev; 46246773Sphk sname = dsname(bdevsw(newrootdev)->d_name, unit, slice, part, partname); 46336809Sbde rootdevnames[0] = malloc(strlen(sname) + 2, M_DEVBUF, M_NOWAIT); 46436809Sbde sprintf(rootdevnames[0], "%s%s", sname, partname); 46536809Sbde 4664Srgrimes /* 46736809Sbde * For properly dangerously dedicated disks (ones with a historical 46836809Sbde * bogus partition table), the boot blocks will give slice = 4, but 46936809Sbde * the kernel will only provide the compatibility slice since it 47036809Sbde * knows that slice 4 is not a real slice. Arrange to try mounting 47136809Sbde * the compatibility slice as root if mounting the slice passed by 47236809Sbde * the boot blocks fails. This handles the dangerously dedicated 47336809Sbde * case and perhaps others. 4744Srgrimes */ 47536809Sbde if (slice == COMPATIBILITY_SLICE) 4764Srgrimes return; 47736809Sbde slice = COMPATIBILITY_SLICE; 47836809Sbde rootdevs[1] = dkmodslice(newrootdev, slice); 47946773Sphk sname = dsname(bdevsw(newrootdev)->d_name, unit, slice, part, partname); 48036809Sbde rootdevnames[1] = malloc(strlen(sname) + 2, M_DEVBUF, M_NOWAIT); 48136809Sbde sprintf(rootdevnames[1], "%s%s", sname, partname); 4824Srgrimes} 48347444Sjb#endif 48412649Speter 48535319Sjulian 48612649Speterstatic int 48712649Spetersysctl_kern_dumpdev SYSCTL_HANDLER_ARGS 48812649Speter{ 48912649Speter int error; 49047048Sphk udev_t ndumpdev; 49112649Speter 49247048Sphk ndumpdev = dev2udev(dumpdev); 49312649Speter error = sysctl_handle_opaque(oidp, &ndumpdev, sizeof ndumpdev, req); 49417355Sbde if (error == 0 && req->newptr != NULL) 49547048Sphk error = setdumpdev(udev2dev(ndumpdev, 1)); 49612649Speter return (error); 49712649Speter} 49812649Speter 49912649SpeterSYSCTL_PROC(_kern, KERN_DUMPDEV, dumpdev, CTLTYPE_OPAQUE|CTLFLAG_RW, 50022564Sbde 0, sizeof dumpdev, sysctl_kern_dumpdev, "T,dev_t", ""); 50146806Sphk 50246806Sphk 50346806Sphk 50446806Sphkstatic int 50546806Sphksetrootbyname(char *name) 50646806Sphk{ 50746806Sphk char *cp; 50846806Sphk int bd, unit, slice, part; 50946806Sphk dev_t dev; 51046806Sphk 51146806Sphk slice = 0; 51246806Sphk part = 0; 51346806Sphk cp = name; 51446806Sphk while (cp != '\0' && (*cp < '0' || *cp > '9')) 51546806Sphk cp++; 51646806Sphk if (cp == name) { 51746806Sphk printf("missing device name\n"); 51846806Sphk return(1); 51946806Sphk } 52046806Sphk if (*cp == '\0') { 52146806Sphk printf("missing unit number\n"); 52246806Sphk return(1); 52346806Sphk } 52446806Sphk unit = *cp - '0'; 52546806Sphk *cp++ = '\0'; 52646806Sphk for (bd = 0; bd < nblkdev; bd++) { 52746806Sphk dev = makedev(bd, 0); 52846806Sphk if (bdevsw(dev) != NULL && 52946806Sphk strcmp(bdevsw(dev)->d_name, name) == 0) 53046806Sphk goto gotit; 53146806Sphk } 53246806Sphk return (2); 53346806Sphkgotit: 53446806Sphk while (*cp >= '0' && *cp <= '9') 53546806Sphk unit += 10 * unit + *cp++ - '0'; 53646806Sphk if (*cp == 's' && cp[1] >= '0' && cp[1] <= '9') { 53746806Sphk slice = cp[1] - '0'; 53846806Sphk cp += 2; 53946806Sphk } 54046806Sphk if (*cp >= 'a' && *cp <= 'h') { 54146806Sphk part = *cp - 'a'; 54246806Sphk cp++; 54346806Sphk } 54446806Sphk if (*cp != '\0') { 54546806Sphk printf("junk after name\n"); 54646806Sphk return (1); 54746806Sphk } 54846806Sphk printf("driver=%s, unit=%d, slice=%d, part=%d\n", 54946806Sphk name, unit, slice, part); 55046806Sphk rootdev = makedev(bd, dkmakeminor(unit, slice, part)); 55146806Sphk return 0; 55246806Sphk} 55346806Sphk 55446806Sphkvoid 55546806Sphksetconf() 55646806Sphk{ 55746806Sphk char name[128]; 55846806Sphk int i; 55946806Sphk dev_t dev; 56046806Sphk 56146806Sphk for(;;) { 56246806Sphk printf("root device? "); 56346806Sphk gets(name); 56446806Sphk i = setrootbyname(name); 56546806Sphk if (!i) 56646806Sphk return; 56746806Sphk 56846806Sphk printf("use one of:\n"); 56946806Sphk for (i = 0; i < nblkdev; i++) { 57046806Sphk dev = makedev(i, 0); 57146806Sphk if (bdevsw(dev) != NULL) 57246806Sphk printf(" %s", bdevsw(dev)->d_name); 57346806Sphk } 57446806Sphk printf(" followed by a unit number...\n"); 57546806Sphk } 57646806Sphk} 57746806Sphk 57846806Sphkstatic void 57946806Sphkgets(cp) 58046806Sphk char *cp; 58146806Sphk{ 58246806Sphk register char *lp; 58346806Sphk register int c; 58446806Sphk 58546806Sphk lp = cp; 58646806Sphk for (;;) { 58746806Sphk printf("%c", c = cngetc() & 0177); 58846806Sphk switch (c) { 58946806Sphk case -1: 59046806Sphk case '\n': 59146806Sphk case '\r': 59246806Sphk *lp++ = '\0'; 59346806Sphk return; 59446806Sphk case '\b': 59546806Sphk case '\177': 59646806Sphk if (lp > cp) { 59746806Sphk printf(" \b"); 59846806Sphk lp--; 59946806Sphk } 60046806Sphk continue; 60146806Sphk case '#': 60246806Sphk lp--; 60346806Sphk if (lp < cp) 60446806Sphk lp = cp; 60546806Sphk continue; 60646806Sphk case '@': 60746806Sphk case 'u' & 037: 60846806Sphk lp = cp; 60946806Sphk printf("%c", '\n'); 61046806Sphk continue; 61146806Sphk default: 61246806Sphk *lp++ = c; 61346806Sphk } 61446806Sphk } 61546806Sphk} 616