Files
Arquivotheca.SunOS-4.1.4/sys/sun/swapgeneric.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

2107 lines
49 KiB
C

#ifndef lint
static char sccsid[] = "@(#)swapgeneric.c 1.1 94/10/31 SMI";
#endif
/*
* Copyright (c) 1987-1990 by Sun Microsystems, Inc.
*
* XXX - This stuff is no longer generic or swap related
* and should probably be moved to autoconf.c.
*/
/* XXX: These must be kept in sync with scsi config flags. */
#define DISK 0 /* Scsi disk */
#define TAPE 1 /* Scsi tape */
#define CDROM 2 /* Scsi cdrom */
#include <sys/param.h>
#include <sys/conf.h>
#include <sys/buf.h>
#include <sys/vm.h>
#include <sys/systm.h>
#include <sys/reboot.h>
#include <sys/file.h>
#include <sys/vfs.h>
#include <sys/mtio.h>
#undef NFSCLIENT
#include <sys/mount.h>
#include <sys/socket.h>
#include <net/if.h>
#include <machine/pte.h>
#include <sundev/mbvar.h>
#ifdef OPENPROMS
#include <mon/obpdefs.h>
#else OPENPROMS
#include <mon/sunromvec.h>
#endif OPENPROMS
#include <sun/autoconf.h>
#ifdef sun4c
#include <machine/auxio.h>
#define Auxio (*(u_char *)AUXIO_REG)
#endif sun4c
#ifdef OPENPROMS
/*
* Undefine DPRINTF to remove compiled code.
* #define DPRINTF if (bootpath_debug) printf
*/
#ifdef DPRINTF
static int bootpath_debug = 1; /* Non-zero for debug messages */
#endif DPRINTF
#endif
/*
* Generic configuration; all in one
*/
dev_t rootdev;
struct vnode *rootvp;
/*
* Flags in bdevlist/cdevlist.
* This stuff moved outside the "ifdef OPENPROM" for building
* VME dev_info structs, and booting from VME.
*/
#define SG_EXISTS 1 /* device exists */
#define SG_HEXUNIT 2 /* unit number is hex */
#define SG_TAPE 4 /* tape minor number */
#define SG_NHEX 3 /* number of hex digits required & allowed */
static int sg_parse_name();
static dev_t sg_form_dev();
#ifndef OPENPROMS
#include "id.h"
#if NID > 0
extern struct mb_driver idcdriver;
#endif
#include "xd.h"
#if NXD > 0
extern struct mb_driver xdcdriver;
#endif
#include "xy.h"
#if NXY > 0
extern struct mb_driver xycdriver;
#endif
# include "xt.h"
#if NXT > 0
extern struct mb_driver xtcdriver;
#endif
# include "mt.h"
#if NMT > 0
extern struct mb_driver tmdriver;
#endif
#ifdef OLDSCSI
#include "sc.h"
#if NSC > 0
extern struct mb_driver scdriver;
#endif
#include "si.h"
#if NSI > 0
extern struct mb_driver sidriver;
#endif
#include "se.h"
#if NSE > 0
extern struct mb_driver sedriver;
#endif
#include "sw.h"
#if NSW > 0
extern struct mb_driver swdriver;
#endif
#include "sm.h"
#if NSM > 0
extern struct mb_driver smdriver;
#endif
#include "wds.h"
#if NWDS > 0
extern struct mb_driver wdsdriver;
#endif
#else OLDSCSI
#include "sd.h"
#if NSD > 0
extern struct mb_driver sddriver;
#endif
#endif OLDSCSI
#include "ns.h"
#if NNS > 0
extern struct mb_driver nsdriver;
#endif
#include "rd.h"
#if NRD > 0
extern struct mb_driver rddriver;
#endif
#include "fd.h"
#if NFD > 0
extern struct mb_driver fdcdriver;
#endif
#include "hd.h"
#if NHD > 0
extern struct mb_driver hdcdriver;
#endif
#include "ft.h"
#if NFT > 0
extern struct mb_driver ftdriver;
#endif
/*
* Flags in bdevlist/cdevlist.
*/
#define SG_EXISTS 1 /* device exists */
#define SG_HEXUNIT 2 /* unit number is hex */
#define SG_TAPE 4 /* tape minor number */
#define SG_NHEX 3 /* number of hex digits required & allowed */
struct bdevlist {
char *bl_name;
struct mb_driver *bl_driver;
dev_t bl_root;
int bl_flags;
} bdevlist[] = {
#if NID > 0
{"id", &idcdriver, makedev(22, 0), SG_HEXUNIT},
#endif
#if NXD > 0
{"xd", &xdcdriver, makedev(10, 0)},
#endif
#if NXY > 0
{"xy", &xycdriver, makedev(3, 0)},
#endif
#if NSC > 0
{"sd", &scdriver, makedev(7, 0)},
#endif
#ifdef OLDSCSI
#if NSI > 0
{"sd", &sidriver, makedev(7, 0)},
#endif
#if NSE > 0
{"sd", &sedriver, makedev(7, 0)},
#endif
#if NSW > 0
{"sd", &swdriver, makedev(7, 0)},
#endif
#if NSM > 0
{"sd", &smdriver, makedev(7, 0)},
#endif
#if NWDS > 0
{"sd", &wdsdriver, makedev(7, 0)},
#endif
#else OLDSCSI
#if NSD > 0
{"sd", &sddriver, makedev(7, 0)},
#endif
#endif OLDSCSI
#if NRD > 0
{"rd", &rddriver, makedev(13, 0)},
#endif
#if NNS > 0
{"ns", &nsdriver, makedev(12, 0)},
#endif
#if NHD > 0
{"hd", &hdcdriver, makedev(15, 0)},
#endif
#ifdef ROOT_ON_FLOPPY
#if NFD > 0
{"fd", &fdcdriver, makedev(16, 0)},
#endif
#endif ROOT_ON_FLOPPY
#ifdef ROOT_ON_TAPE
#include "st.h"
#ifdef OLDSCSI
#if NST > 0
# if NSC > 0
{"st", &scdriver, makedev(11, MT_NOREWIND)},
# endif
# if NSI > 0
{"st", &sidriver, makedev(11, MT_NOREWIND)},
# endif
# if NSE > 0
{"st", &sedriver, makedev(11, MT_NOREWIND)},
# endif
# if NSW > 0
{"st", &swdriver, makedev(11, MT_NOREWIND)},
# endif
# if NSM > 0
{"st", &smdriver, makedev(11, MT_NOREWIND)},
# endif
# if NWDS > 0
{"st", &wdsdriver, makedev(11, MT_NOREWIND)},
# endif
#endif NST > 0
#else OLDSCSI
#if NST > 0
{"st", &stdriver, makedev(11, MT_NOREWIND)},
#endif
#endif OLDSCSI
#if NXT > 0
{"xt", &xtcdriver, makedev(8, MT_NOREWIND)},
#endif
#if NMT > 0
{"mt", &tmdriver, makedev(1, MT_NOREWIND)},
#endif
#endif ROOT_ON_TAPE
{0}
};
#include "rd.h"
#if NRD > 0
/*
* If the ram disk is intialized from tape, it needs to
* use the character device to skip to the right file.
*/
struct cdevlist {
char *cl_name;
struct mb_driver *cl_driver;
dev_t cl_croot;
dev_t cl_broot;
int cl_flags;
} cdevlist[] = {
#include "st.h"
#ifdef OLDSCSI
#if NST > 0
# if NSC > 0
{"st", &scdriver, makedev(18, MT_NOREWIND), makedev(11, MT_NOREWIND)},
# endif
# if NSI > 0
{"st", &sidriver, makedev(18, MT_NOREWIND), makedev(11, MT_NOREWIND)},
# endif
# if NSE > 0
{"st", &sedriver, makedev(18, MT_NOREWIND), makedev(11, MT_NOREWIND)},
# endif
# if NSM > 0
{"st", &smdriver, makedev(18, MT_NOREWIND), makedev(11, MT_NOREWIND)},
# endif
# if NSW > 0
{"st", &swdriver, makedev(18, MT_NOREWIND), makedev(11, MT_NOREWIND)},
# endif
# if NWDS > 0
{"st", &wdsdriver, makedev(18, MT_NOREWIND), makedev(11, MT_NOREWIND)},
# endif
#endif NST > 0
#else OLDSCSI
#if NST > 0
{"st", &stdriver, makedev(18, MT_NOREWIND), makedev(11, MT_NOREWIND)},
#endif
#endif OLDSCSI
#include "sr.h"
#ifdef OLDSCSI
#if NSR > 0
# if NSC > 0
{"sr", &scdriver, makedev(58, 0), makedev(18, 0)},
# endif
# if NSI > 0
{"sr", &sidriver, makedev(58, 0), makedev(18, 0)},
# endif
# if NSE > 0
{"sr", &sedriver, makedev(58, 0), makedev(18, 0)},
# endif
# if NSM > 0
{"sr", &smdriver, makedev(58, 0), makedev(18, 0)},
# endif
# if NSW > 0
{"sr", &swdriver, makedev(58, 0), makedev(18, 0)},
# endif
# if NWDS > 0
{"sr", &wdsdriver, makedev(58, 0), makedev(18, 0)},
# endif
#endif NSR > 0
#else OLDSCSI
#if NSR > 0
{"sr", &srdriver, makedev(58, 0), makedev(18, 0)},
#endif
#endif OLDSCSI
#if NXT > 0
{"xt", &xtcdriver, makedev(30, MT_NOREWIND), makedev(8, MT_NOREWIND)},
#endif
#if NMT > 0
{"mt", &tmdriver, makedev(5, MT_NOREWIND), makedev(1, MT_NOREWIND)},
#endif
#if NID > 0
{"id", &idcdriver, makedev(72, 0), makedev(22, 0), SG_HEXUNIT},
#endif
#if NXD > 0
{"xd", &xdcdriver, makedev(42, 0), makedev(10, 0)},
#endif
#if NXY > 0
{"xy", &xycdriver, makedev(9, 0), makedev(3, 0)},
#endif
#ifdef OLDSCSI
#if NSC > 0
{"sd", &scdriver, makedev(17, 0), makedev(7, 0)},
#endif
#if NSI > 0
{"sd", &sidriver, makedev(17, 0), makedev(7, 0)},
#endif
#if NSE > 0
{"sd", &sedriver, makedev(17, 0), makedev(7, 0)},
#endif
#if NSW > 0
{"sd", &swdriver, makedev(17, 0), makedev(7, 0)},
#endif
#if NSM > 0
{"sd", &smdriver, makedev(17, 0), makedev(7, 0)},
#endif
#if NWDS > 0
{"sd", &wdsdriver, makedev(17, 0), makedev(7, 0)},
#endif
#else OLDSCSI
#if NSD > 0
{"sd", &sddriver, makedev(17, 0), makedev(7, 0)},
#endif
#endif OLDSCSI
#if NFT > 0
{"ft", &ftdriver, -1, makedev(14, 0)},
#endif
{0}
};
#endif NRD > 0
static int sg_parse_name();
static dev_t sg_form_dev();
#else !OPENPROMS
/*
* slightly nonportable C- bdevlist will point to a kmem_alloc'ed
* area of memory which will then be an array of bdevlist structures.
* The terminator for this list will be signalled by a null bl_dev pointer
*
* There will only be one entry per device kind- that is, the bl_dev
* will point to the devinfo structure for the first valid and attached
* device found.
*/
static struct bdevlist {
struct dev_info *bl_dev;
dev_t bl_root;
int bl_exists; /*
* bl_exists contains a bit pattern
* for valid units for this device.
*/
struct bdevlist *bl_next; /* successor */
int bl_flags; /* flags for IPI from psra/pie */
} *bdevlist = NULL;
#include "rd.h"
#if NRD > 0
static struct dev_ops pseudo_ops = { 0 };
/*
* slightly nonportable C- cdevlist will point to a kmem_alloc'ed
* area of memory which will then be an array of cdevlist structures.
* The terminator for this list will be signalled by a null cl_dev pointer
*
*/
static struct cdevlist {
struct dev_info *cl_dev;
dev_t cl_croot;
dev_t cl_broot;
int cl_exists; /* bit pattern of attached units */
struct cdevlist *cl_next; /* successor */
} *cdevlist = NULL;
#endif NRD
/*
* XXX FIX ME FIX ME FIX ME
* XXX THIS IS GROSS
* XXX THERE MUST BE A BETTER WAY TO DO THIS
* XXX PERHAPS SOMETHING IN sun/conf.c THAT TIES NAMESPACE TO {b, c}devsw
* XXX ENTRIES. THIS COULD ALSO REDUCE THE LOAD IN sun/wscons.c
*
* XXX Also, shouldn't the [bc]maptabs be in REVERSE order of preference,
* XXX as the [bc]devlists are built in LIFO order?
*/
static struct bmaptab {
char *m_name; /* device name */
dev_t m_bmajor; /* major device number */
} bmaptab[] = {
#ifdef sun4m
#include "id.h"
#include "xd.h" /* keeping xd included for now, just in case */
#else
#define NID 0
#define NXD 0
#endif
#if NID > 0
{ "id", makedev(22, 0) },
#endif NID > 0
#if NXD > 0
{ "xd", makedev(10, 0) },
#endif NXD > 0
#include "sd.h"
#if NSD > 0
{ "sd", makedev(7, 0) },
#endif NSD > 0
#include "fd.h"
#if NFD > 0
{ "fd", makedev(16, 0) },
#endif NFD
/* rd.h included above */
#if NRD > 0
{ "rd", makedev(13, 0) },
#endif NRD
#include "ns.h"
#if NNS > 0
{ "ns", makedev(12, 0) },
#endif NNS
#ifdef ROOT_ON_TAPE
#include "st.h"
#if NST > 0
{ "st", makedev(11, MT_NOREWIND) },
#endif NST > 0
#endif ROOT_ON_TAPE
#include "sr.h"
#if NSR > 0
{ "sr", makedev(18, 0) },
#endif NSR > 0
{ 0 },
};
#if NRD > 0
static struct cmaptab
{
char *m_name; /* device name */
dev_t m_bmajor; /* major device number - block */
dev_t m_cmajor; /* major device number - char */
} cmaptab[] = {
#if NSD > 0
{ "sd", makedev(7, 0), makedev(17, 0) },
#endif NSD > 0
#if NFD > 0
{ "fd", makedev(16, 0), makedev(54, 0) },
#endif NFD
#if NST > 0
{ "st", makedev(11, MT_NOREWIND), makedev(18, MT_NOREWIND) },
#endif NST > 0
#include "ft.h"
#if NFT > 0
{ "ft", makedev(14, 0), -1 },
#endif NFT
#if NSR > 0
{ "sr", makedev(18, 0), makedev(58, 0) },
#endif NSR > 0
#if NID > 0
{ "id", makedev(22, 0), makedev(72, 0) },
#endif
{ 0 },
};
#endif NRD
#endif !OPENPROMS
struct vfssw *
getfstype(askfor, fsname)
char *askfor;
char *fsname;
{
int fstype;
#ifdef OPENPROMS
char devname[OBP_MAXDEVNAME];
#else OPENPROMS
struct bootparam *bp;
char devname[32];
#endif OPENPROMS
short unit;
extern char *strcpy(), *strncpy();
if (boothowto & RB_ASKNAME) {
for (fsname[0] = '\0'; fsname[0] == '\0'; /* empty */) {
printf("%s filesystem type (", askfor);
for (fstype = 0; fstype < MOUNT_MAXTYPE; fstype++) {
if (!vfssw[fstype].vsw_name)
continue;
if (!strcmp("swap", askfor) &&
!strcmp("4.2", vfssw[fstype].vsw_name))
continue; /* "swap" can't be on "4.2" */
if (!strcmp("root", askfor) &&
!strcmp("spec", vfssw[fstype].vsw_name))
continue; /* "root" can't be on "spec" */
printf("%s ", vfssw[fstype].vsw_name);
}
printf("): ");
gets(fsname);
for (fstype = 0; fstype < MOUNT_MAXTYPE; fstype++) {
if (vfssw[fstype].vsw_name == 0)
continue; /* ignore fstypes without names */
if (!strcmp("swap", askfor) &&
!strcmp("4.2", vfssw[fstype].vsw_name))
continue; /* "swap" can't be on "4.2" */
if (!strcmp("root", askfor) &&
!strcmp("spec", vfssw[fstype].vsw_name))
continue; /* "root" can't be on "spec" */
if (*fsname == '\0') {
/* default, grab the first */
(void) strcpy(fsname,
vfssw[fstype].vsw_name);
return (&vfssw[fstype]);
}
if (strcmp(vfssw[fstype].vsw_name, fsname)==0) {
return (&vfssw[fstype]);
}
}
printf("Unknown filesystem type '%s'\n", fsname);
*fsname = '\0';
}
} else if (*fsname) {
for (fstype = 0; fstype < MOUNT_MAXTYPE; fstype++) {
if (vfssw[fstype].vsw_name == 0) {
continue;
}
if (strcmp(vfssw[fstype].vsw_name, fsname) == 0) {
return (&vfssw[fstype]);
}
}
} else { /* last try before giving up */
/*
* See if the device specified on the boot line
* is an initialized network interface.
* If so, then select "nfs".
*/
#ifdef OPENPROMS
#ifdef DPRINTF
char *path;
#endif
extern char *prom_bootpath();
#ifdef DPRINTF
path = prom_bootpath();
#else
(void) prom_bootpath();
#endif
#ifdef DPRINTF
DPRINTF("getfstype: path <%s> --> ", path ? path : "NONE!");
#endif DPRINTF
devname[0] = (char)0; /* In case of error getting devname */
if (prom_get_boot_dev_name(devname, sizeof devname) != 0) {
#ifdef DPRINTF
DPRINTF("getfstype: Error getting devname");
#endif DPRINTF
return ((struct vfssw *)0);
}
unit = (short)prom_get_boot_dev_unit();
#ifdef DPRINTF
DPRINTF("device <%s>, unit <%x>\n",
devname, (int)unit);
#endif DPRINTF
#else OPENPROMS
bp = *romp->v_bootparam;
if (bp) {
devname[0] = bp->bp_dev[0];
devname[1] = bp->bp_dev[1];
devname[2] = '\0';
unit = bp->bp_ctlr;
}
#endif OPENPROMS
if (ifname(devname, unit)) { /* interface found */
for (fstype = 0; fstype < MOUNT_MAXTYPE; fstype++) {
if (vfssw[fstype].vsw_name == 0)
continue;
if (strcmp(vfssw[fstype].vsw_name, "nfs") == 0)
return (&vfssw[fstype]);
}
}
}
return ((struct vfssw *)0);
}
/*
* If booted with ASKNAME, prompt on the console for a filesystem
* name and return it.
*/
getfsname(askfor, name)
char *askfor;
char *name;
{
if (boothowto & RB_ASKNAME) {
printf("%s name: ", askfor);
gets(name);
}
}
#ifndef OPENPROMS
/*
* Return the device number and name of the first
* block device in the bdevlist that can be opened.
* If booted with the -a flag, ask user for device name.
* Name must be at least 128 bytes long.
* askfor is one of "root" or "swap".
*/
dev_t
getblockdev(askfor, name)
char *askfor;
char *name;
{
register struct bdevlist *bl;
struct bdevlist lbl;
int ctlr, unit, part, i, def_part;
static int first_time = 0;
dev_t dev;
if (strcmp(askfor, "swap") == 0)
part = def_part = 1; /* default swap partition is 'b' */
else
part = def_part = 0; /* default root partition is 'a' */
if (boothowto & RB_ASKNAME) {
for (bl = bdevlist; bl->bl_name; bl++) {
if (first_time)
break;
if (chkroot(bl) > 0) {
bl->bl_flags |= SG_EXISTS;
continue;
}
/* We don't check for extra tape units. */
if ((bdevsw[major(bl->bl_root)].d_flags & B_TAPE))
continue;
/*
* Controller present; unit 0 is not. Check for
* additional units 1-6.
*/
for (i = 1; i <= 6; i++) {
register int root;
root = bl->bl_root;
bl->bl_root = makedev(major(bl->bl_root), i<<3);
if (chkroot(bl) > 0)
bl->bl_flags |= SG_EXISTS;
bl->bl_root = root;
if (bl->bl_flags & SG_EXISTS)
break;
}
}
first_time = 1;
for (unit = -1; unit == -1; /* empty */) {
/*
* SCSI makes things complicated since disks, tapes,
* and other devices are hung off the same controller.
* Thus, we have to use the bdev table name.
*/
printf("%s device ( ", askfor);
for (bl = bdevlist; bl->bl_name; bl++) {
if (bl->bl_flags & SG_EXISTS)
if (bl->bl_flags & SG_HEXUNIT)
printf("%s%%3x[a-h] ",
bl->bl_name);
else
printf("%s%%d[a-h] ",
bl->bl_name);
}
printf("): ");
gets(name);
if (*name == '\0') {
bl = bdevlist;
unit = 0;
part = def_part;
break;
}
for (bl = bdevlist; bl->bl_name; bl++) {
if (bl->bl_name[0] == name[0] &&
bl->bl_name[1] == name[1])
break;
}
if (!bl->bl_name) {
printf("unknown device name %c%c\n",
name[0], name[1]);
continue;
}
sdloop:
unit = 0; /* default unit number */
part = def_part; /* default partition */
/*
* Parse name to get unit number and partition.
*/
if (sg_parse_name(name, &unit, &part, bl->bl_flags)) {
/*
* See if we can open it. If not, reprompt.
*/
dev = sg_form_dev(bl->bl_root, &name[2],
unit, part, bl->bl_flags);
lbl = *bl; /* local struct copy */
lbl.bl_root = dev;
if (chkroot(&lbl) > 0)
return (dev);
/*
* does scsi make things complicated !!!.
* There are different
* kinds of scsis. look through all of them.
*/
if (name[0] == 's' && name[1] == 'd' &&
(++bl)) {
for (; bl->bl_name; bl++) {
if (bl->bl_name[0] == name[0] &&
bl->bl_name[1] == name[1])
goto sdloop;
}
}
printf("cannot open %s - re-enter.\n", name);
unit = -1; /* stay in loop */
}
}
} else {
unit = 0;
/*
* If a name was given, find that block device and use it.
*/
if (*name != '\0') {
for (bl = bdevlist; bl->bl_name; bl++) {
if (bl->bl_name[0] == name[0] &&
bl->bl_name[1] == name[1]) {
if (chkroot(bl) >= 0 &&
sg_parse_name(name, &unit,
&part, bl->bl_flags))
goto found;
}
}
return ((dev_t)0);
}
/*
* Look for device we booted from and use it if found.
*/
for (bl = bdevlist; bl->bl_name; bl++) {
register struct bootparam *bp = (*romp->v_bootparam);
if (!((*bl->bl_name == bp->bp_dev[0]) &&
(*(bl->bl_name+1) == bp->bp_dev[1])))
continue;
name[0] = bp->bp_dev[0];
name[1] = bp->bp_dev[1];
ctlr = bp->bp_ctlr;
part = bp->bp_part;
unit = bp->bp_unit;
/* If scsi disk (or CDROM), get logical unit. */
if (name[0] == 's' && name[1] == 'd') {
register struct bdevlist *bbl;
if ((unit = lkupbdev(bl, ctlr, unit, DISK)) == -1) {
/* maybe it's a CDROM */
bbl = bl;
for (bl = bdevlist; bl->bl_name; bl++) {
if (!((*bl->bl_name == 's') &&
(*(bl->bl_name+1) == 'r') &&
(bl->bl_flags & SG_EXISTS)))
continue;
/*
* Note, use bp_unit as unit is
* modified.
*/
if ((unit = lkupbdev(bl, ctlr,
bp->bp_unit, CDROM)) != -1)
break;
}
if (unit == -1) {
bl = bbl;
continue;
}
}
/* If scsi CDROM, get logical unit. */
} else if (name[0] == 's' && name[1] == 'r') {
if ((unit = lkupbdev(bl, ctlr, unit, CDROM)) == -1)
continue;
/* IPI device, get logical unit. */
} else if (bl->bl_flags & SG_HEXUNIT) {
unit = (ctlr << 4) | unit;
}
/* Got unit, now let's open it and see if it's there */
lbl = *bl; /* copy struct */
lbl.bl_root = sg_form_dev(bl->bl_root, &name[2],
unit, part, bl->bl_flags);
if (chkroot(&lbl) > 0)
return (lbl.bl_root);
}
/*
* Last chance, use the first device that can be opened.
*/
unit = 0;
part = def_part;
for (bl = bdevlist; bl->bl_name; bl++) {
if (chkroot(bl) > 0)
goto found;
}
return ((dev_t)0);
}
found:
name[0] = bl->bl_name[0];
name[1] = bl->bl_name[1];
return (sg_form_dev(bl->bl_root, &name[2], unit, part, bl->bl_flags));
}
#else !OPENPROMS
/*
* Return the device number and name of the first
* block device in the bdevlist that can be opened.
* If booted with the -a flag, ask user for device name.
* Name must be at least 128 bytes long.
* askfor is one of "root" or "swap".
*/
dev_t
getblockdev(askfor, name)
char *askfor;
char *name;
{
register struct bdevlist *bl;
struct bdevlist lbl;
int unit, part, def_part, askme = (boothowto & RB_ASKNAME);
dev_t dev, chk;
char devname[OBP_MAXDEVNAME];
#ifdef DPRINTF
char *path;
#endif
extern char *prom_bootpath();
if (strcmp(askfor, "swap") == 0)
part = def_part = 1; /* default swap partition is 'b' */
else
part = def_part = 0; /* default root partition is 'a' */
if (!bdevlist) {
if (build_bdevlist() == 0) {
panic("getblockdev: No Devices to boot off of?");
/*NOTREACHED*/
}
}
tryagain:
if (askme) {
for (unit = -1; unit == -1; /* empty */) {
printf("%s device (", askfor);
for (bl = bdevlist; bl != NULL; bl = bl->bl_next) {
if (bl->bl_exists) {
if (bl->bl_flags & SG_HEXUNIT)
printf("%s%%3x[a-h] ",
bl->bl_dev->devi_name);
else
printf("%s%%d[a-h] ",
bl->bl_dev->devi_name);
}
}
printf("): ");
gets(name);
if (*name == '\0') {
bl = bdevlist;
unit = 0;
part = def_part;
break;
}
for (bl = bdevlist; bl->bl_next; bl = bl->bl_next) {
if (strncmp(
bl->bl_dev->devi_name, name, 2) == 0)
break;
}
if (!bl) {
printf("Unknown device name '%c%c'\n",
name[0], name[1]);
continue;
}
unit = 0; /* default unit number */
part = def_part; /* default partition */
/*
* Parse name to get unit number and partition.
*/
if (sg_parse_name(name, &unit, &part, bl->bl_flags)) {
/*
* See if we can open it. If not, reprompt.
*/
dev = sg_form_dev(bl->bl_root, &name[2],
unit, part, bl->bl_flags);
lbl = *bl; /* local struct copy */
lbl.bl_root = dev;
if (lbl.bl_exists)
return (dev);
}
}
} else {
unit = 0;
/*
* If we are looking for swap, assume
* that the second partition is needed.
*/
if (strcmp (askfor, "swap") == 0)
part = 1;
else
part = 0;
/*
* If a name was given, find that block device
*/
if (*name != '\0') {
for (bl = bdevlist; bl != NULL; bl = bl->bl_next) {
if (strncmp(bl->bl_dev->devi_name, name, 2))
continue;
if ((bl->bl_exists) &&
sg_parse_name(name, &unit,
&part, bl->bl_flags))
goto found;
}
return ((dev_t)0);
}
/*
* Look for device we booted from
*/
#ifdef DPRINTF
path = prom_bootpath();
DPRINTF("getblockdev: path <%s> --> ", path ? path : "NONE!");
#else
(void) prom_bootpath();
#endif DPRINTF
if (prom_get_boot_dev_name(devname, sizeof devname) != 0) {
#ifdef DPRINTF
DPRINTF("getblockdev: Error getting devname (usefirst)\n");
#endif DPRINTF
goto usefirst;
}
unit = prom_get_boot_dev_unit();
part = prom_get_boot_dev_part();
#ifdef DPRINTF
DPRINTF("device <%s> unit <%x> part <%d>\n",
devname, unit, part);
#endif DPRINTF
for (bl = bdevlist; bl != NULL; bl = bl->bl_next) {
if (strcmp(bl->bl_dev->devi_name, devname) != 0)
continue;
if (bl->bl_exists & (1 << unit))
goto found;
}
/*
* Use the first device that can be opened.
* If we are looking for swap, assume
* that the second partition is needed.
*/
usefirst:
if (strcmp (askfor, "swap") == 0) part = 1;
for (bl = bdevlist; bl != NULL; bl = bl->bl_next) {
if (bl->bl_exists == 0)
continue;
/*
* if some user has a floppy in their drive, and they
* are booting a GENERIC kernel over the net, they
* expect to NOT swap on the floppy. Since there is
* nothing intrinsically "illegal" about it - it is
* just too small for normal operations, we put in
* a special HACK here, to disallow swapping on "fd"
*/
if ((bl->bl_dev->devi_name[0] == 'f') &&
(bl->bl_dev->devi_name[1] == 'd') &&
(strcmp (askfor, "swap") == 0))
continue;
while (unit < 8*sizeof (bl->bl_exists)) {
if (bl->bl_exists&(1<<unit)) {
if (chkopenable(makedev(major(bl->bl_root),
(unit * 8 + part))))
goto found;
}
unit++;
}
}
return ((dev_t)0);
}
found:
name[0] = bl->bl_dev->devi_name[0];
name[1] = bl->bl_dev->devi_name[1];
chk = (sg_form_dev(bl->bl_root, &name[2], unit, part, bl->bl_flags));
/*
* Make sure that you can open the device
* the user ended up specifying (unless it's rd.c)
*/
if (strncmp("rd0", name, 3) != 0) {
if (chkopenable(chk)) {
return (chk);
} else {
printf("Cannot open '%s'\n", name);
askme = 1;
goto tryagain;
}
} else
return (chk);
}
/*
* check if dev is openable, 0 no, 1 yes
*/
static
chkopenable(dev)
dev_t dev;
{
short maj = major(dev);
if ((*bdevsw[maj].d_open)(dev, FREAD) == 0) {
(void)(*bdevsw[maj].d_close)(dev, FREAD);
return (1);
} else
return (0);
}
/*
* Check to see whether name is already in bdevlist
*/
static struct bdevlist *
chkdup_b(name)
register char *name;
{
register struct bdevlist *tp = bdevlist;
while (tp) {
if (strcmp(name, tp->bl_dev->devi_name) == 0)
break;
else
tp = tp->bl_next;
}
return (tp);
}
/*
* If this dev structure refers to this bmaptab entry,
* and an equivalent name (i.e., another unit) is not
* already in the bdevlist, add it in.
*/
static
add_to_blist(dev, op)
register struct dev_info *dev;
char *op;
{
register struct bmaptab *bmp = (struct bmaptab *) op;
if (strcmp(dev->devi_name, bmp->m_name) == 0 && dev->devi_driver) {
register struct bdevlist *tp;
/*
* If there is a devlist entry allready in the list,
* then only add a notation to it that there is another
* unit available.
*/
if (tp = chkdup_b(dev->devi_name)) {
tp->bl_exists |= (1<<dev->devi_unit);
} else {
tp = bdevlist;
bdevlist = (struct bdevlist *)new_kmem_zalloc(
sizeof (*tp), KMEM_NOSLEEP);
if (!bdevlist)
panic("add_to_blist: no memory");
bdevlist->bl_dev = dev;
bdevlist->bl_next = tp;
bdevlist->bl_root = bmp->m_bmajor;
bdevlist->bl_exists |= (1<<dev->devi_unit);
/* have to set the flag for IPI devices */
if (strcmp(bmp->m_name, "id") == 0)
bdevlist->bl_flags = SG_HEXUNIT;
}
}
}
static int
build_bdevlist()
{
extern struct dev_info *top_devinfo;
register struct bmaptab *bmp;
for (bmp = bmaptab; bmp->m_name; bmp++) {
#if NRD > 0
if (strcmp("rd", bmp->m_name) == 0 ||
strcmp("ns", bmp->m_name) == 0 ||
strcmp("ft", bmp->m_name) == 0) {
register struct dev_info *dev =
(struct dev_info *)new_kmem_zalloc(
sizeof (struct dev_info), KMEM_NOSLEEP);
if (!dev)
panic("build_bdevlist: no memory");
dev->devi_name = bmp->m_name;
dev->devi_driver = &pseudo_ops;
add_to_blist(dev, (char *) bmp);
} else
#endif NRD > 0
walk_devs(top_devinfo, add_to_blist, (char *) bmp);
}
{
/* move "sr" devices to the end of the list. */
register struct bdevlist *srl, *otl, *scn, *nxt;
srl = NULL;
otl = NULL;
nxt = bdevlist;
while (scn = nxt) {
nxt = scn->bl_next;
if ((scn->bl_dev->devi_name[0] == 's') &&
(scn->bl_dev->devi_name[1] == 'r')) {
scn->bl_next = srl;
srl = scn;
} else {
scn->bl_next = otl;
otl = scn;
}
scn = nxt;
}
while (srl != NULL) {
nxt = srl->bl_next;
srl->bl_next = scn;
scn = srl;
srl = nxt;
}
while (otl != NULL) {
nxt = otl->bl_next;
otl->bl_next = scn;
scn = otl;
otl = nxt;
}
bdevlist = scn;
}
return (bdevlist != NULL);
}
#if NRD > 0
/*
* Check to see whether name is already in cdevlist
*/
static struct cdevlist *
chkdup_c(name)
register char *name;
{
register struct cdevlist *tp = cdevlist;
while (tp) {
if (strcmp(name, tp->cl_dev->devi_name) == 0)
break;
else
tp = tp->cl_next;
}
return (tp);
}
/*
* If this dev structure refers to this cmaptab entry,
* and an equivalent name (i.e., another unit) is not
* already in the cdevlist, add it in.
*/
static
add_to_clist(dev, op)
register struct dev_info *dev;
char *op;
{
register struct cmaptab *cmp = (struct cmaptab *) op;
if (strcmp(dev->devi_name, cmp->m_name) == 0 && dev->devi_driver) {
register struct cdevlist *tp;
/*
* If there is a devlist entry allready in the list,
* then only add a notation to it that there is another
* unit available.
*/
if (tp = chkdup_c(dev->devi_name)) {
tp->cl_exists |= (1<<dev->devi_unit);
} else {
tp = cdevlist;
cdevlist = (struct cdevlist *)
new_kmem_zalloc(sizeof (*tp), KMEM_NOSLEEP);
if (!cdevlist)
panic("add_to_clist: no memory");
cdevlist->cl_dev = dev;
cdevlist->cl_next = tp;
cdevlist->cl_croot = cmp->m_cmajor;
cdevlist->cl_broot = cmp->m_bmajor;
cdevlist->cl_exists |= (1<<dev->devi_unit);
}
}
}
static
build_cdevlist()
{
extern struct dev_info *top_devinfo;
register struct cmaptab *cmp;
for (cmp = cmaptab; cmp->m_name; cmp++) {
if (strcmp("rd", cmp->m_name) == 0 ||
strcmp("ns", cmp->m_name) == 0 ||
strcmp("ft", cmp->m_name) == 0) {
register struct dev_info *dev =
(struct dev_info *)new_kmem_zalloc(
sizeof (struct dev_info), KMEM_NOSLEEP);
if (!dev)
panic("build_cdevlist: no memory");
dev->devi_driver = &pseudo_ops;
dev->devi_name = cmp->m_name;
add_to_clist(dev, (char *) cmp);
} else
walk_devs(top_devinfo, add_to_clist, (char *) cmp);
}
return (cdevlist != NULL);
}
#endif NRD
#endif !OPENPROMS
#if NRD > 0
/*
* for ease of use - we can patch the kernel with where to get the munixfs.
* yes, I *know* this is a HORRIBLE HACK - the alternative is to build
* 4 different (1/4", 1/2", floppy, net) MUNIX kernels.
* if you make changes here, be so kind as to fixup things in ...src/sundist
* XXX - toss the string by making getchardev smarter and just parse the
* boot args
*/
char loadramdiskfrom[16] = { 0 };
/*
* loadramdiskfile is used for both tape and cdrom; for tape is file
* number, for cdrom is offset in bytes from start of boot partition
* to munixfs image.
* NOTE: this is patched via adb in the various scripts in ...src/sundist
*/
int loadramdiskfile = -1;
#ifndef OPENPROMS
/*
* The ram disk driver is initialized from another device
* that contains the image of a 4.2 file system.
*
* Return the device number and name of the first
* char device in the cdevlist that can be opened.
* Name must be at least 128 bytes long.
*/
int
getchardev(askfor, name, fileno, cdev, bdev)
char *askfor, *name;
int *fileno; /* -1 or file number on tape */
dev_t *cdev, *bdev;
{
register struct cdevlist *cl;
int ctlr, unit, part;
int i;
if (boothowto & RB_ASKNAME) {
for (cl = cdevlist; cl->cl_name; cl++) {
if ((i = chkcdev(cl)) > 0) {
cl->cl_flags |= SG_EXISTS;
continue; /* Found it */
} else if (i < 0) {
continue; /* no contrler found */
}
/*
* If st0 failed, check second host adapter for st4.
* Note, we use the block device so we don't confuse
* the ram disk driver.
*/
if (cl->cl_name[0] == 's' && cl->cl_name[1] == 't') {
register int root;
root = cl->cl_croot;
cl->cl_croot = makedev(major(cl->cl_croot),
MTMINOR(4) + MT_NOREWIND);
if (chkcdev(cl) > 0)
cl->cl_flags |= SG_EXISTS;
cl->cl_croot = root;
}
}
retry:
fubar(); /* XXX sun4 compiler workaround */
for (unit = -1; unit == -1; /* empty */) {
printf("%s device ( ", askfor);
for (cl = cdevlist; cl->cl_name; cl++)
if (cl->cl_flags & SG_EXISTS) {
if (cl->cl_flags & SG_HEXUNIT)
printf("%s%%3x[a-h] ",
cl->cl_name);
else
printf("%s%%d[a-h] ",
cl->cl_name);
}
printf("): ");
gets(name);
if (*name == '\0') {
cl = cdevlist;
unit = 0;
part = 0;
break;
}
for (cl = cdevlist; cl->cl_name; cl++) {
if (cl->cl_name[0] == name[0] &&
cl->cl_name[1] == name[1])
break;
}
if (!cl->cl_name) {
printf("unknown device name %c%c\n",
name[0], name[1]);
continue;
}
unit = part = 0; /* set defaults */
(void) sg_parse_name(name, &unit, &part, cl->cl_flags);
}
} else {
ctlr = unit = part = 0;
for (cl = cdevlist; cl->cl_name; cl++) {
if ((i = chkcdev(cl)) > 0) {
cl->cl_flags |= SG_EXISTS;
continue; /* Found it */
} else if (i < 0) {
continue; /* no controler found */
}
/*
* If st0 failed, check second host adapter for st4.
* Note, we use the block device so we don't confuse
* the ram disk driver.
*/
if (cl->cl_name[0] == 's' && cl->cl_name[1] == 't') {
register int root;
root = cl->cl_croot;
cl->cl_croot = makedev(major(cl->cl_croot),
MTMINOR(4) + MT_NOREWIND);
if (chkcdev(cl) > 0)
cl->cl_flags |= SG_EXISTS;
cl->cl_croot = root;
}
}
/*
* Look for device we booted from and use it if found.
* Note, scsi requires some special processing to get unit.
*/
for (cl = cdevlist; cl->cl_name; cl++) {
register struct bootparam *bp = (*romp->v_bootparam);
if (!((*cl->cl_name == bp->bp_dev[0]) &&
(*(cl->cl_name+1) == bp->bp_dev[1]) &&
(cl->cl_flags & SG_EXISTS)))
continue;
name[0] = cl->cl_name[0];
name[1] = cl->cl_name[1];
ctlr = bp->bp_ctlr;
unit = bp->bp_unit;
part = bp->bp_part;
/* If scsi tape, get logical unit. */
if (name[0] == 's' && name[1] == 't') {
if ((unit = lkupcdev(cl, ctlr, unit, TAPE)) != -1)
goto found;
/* If scsi disk (or CDROM), get logical unit. */
} else if (name[0] == 's' && name[1] == 'd') {
register struct cdevlist *ccl;
if ((unit = lkupcdev(cl, ctlr, unit, DISK)) != -1)
goto found;
/* maybe it's a CDROM */
ccl = cl;
for (cl = cdevlist; cl->cl_name; cl++) {
if (!((*cl->cl_name == 's') &&
(*(cl->cl_name+1) == 'r') &&
(cl->cl_flags & SG_EXISTS)))
continue;
/* Note, use bp_unit as unit is modified */
if ((unit = lkupcdev(cl, ctlr, bp->bp_unit,
CDROM)) != -1)
goto found;
}
cl = ccl;
/* If scsi CDROM, get logical unit. */
} else if ((name[0] == 's') && (name[1] == 'r')) {
if ((unit = lkupcdev(cl, ctlr, unit, CDROM)) != -1)
goto found;
/* Non-scsi device, we're done. */
} else {
goto found;
}
}
goto retry; /* didn't find it: must be an error? */
}
found:
name[0] = cl->cl_name[0];
name[1] = cl->cl_name[1];
*fileno = -1;
/*
* If the device is a tape, prompt for the file number
* If RB_ASKNAME was set prompt the user. Otherwise default
* to the filenumber stamped into the kernel.
*/
if ((bdevsw[major(cl->cl_broot)].d_flags & B_TAPE) != 0) {
char buf[40];
register char *p = buf;
register int num;
cl->cl_flags |= SG_TAPE;
if (!(boothowto & RB_ASKNAME) && (loadramdiskfile != -1)) {
*fileno = loadramdiskfile;
} else {
p = buf;
do {
printf("Tape file number? ");
gets(p);
} while (!*p || *p < '0' || *p > '9');
for (num = 0; *p && *p >= '0' && *p <= '9'; ++p)
num = (num * 10) + *p - '0';
*fileno = num;
}
}
*bdev = sg_form_dev(cl->cl_broot, &name[2], unit, part, cl->cl_flags);
*cdev = sg_form_dev(cl->cl_croot, &name[2], unit, part, cl->cl_flags);
}
/*
* Lookup unit number for scsi. Translates physical unit number
* (really target/lun number) into kernel logical unit number.
* Returns logical unit number. Otherwise, returns -1.
* XXX: There ought to be a way to combine this with lkupbdev and
* save some space.
*/
lkupcdev(cl, ctlr, unit, flags)
register struct cdevlist *cl;
int ctlr, unit, flags;
{
register struct mb_device *md = mbdinit;
int root;
short maj, minr;
/* Find entry in table */
for (md = mbdinit; md->md_driver; md++) {
if (md->md_alive == 0 || md->md_driver != cl->cl_driver ||
md->md_flags != flags || md->md_ctlr != ctlr ||
md->md_slave != unit)
continue;
/* Fix up minor unit number to point to right unit. */
if (flags == TAPE)
minr = MTMINOR(md->md_unit) + MT_NOREWIND;
else
minr = md->md_unit <<3;
/* Open device and see if it's there. */
root = cl->cl_croot;
cl->cl_croot = makedev(major(root), minr);
maj = major(cl->cl_croot);
if ((*cdevsw[maj].d_open)(cl->cl_croot, FREAD) == 0) {
(void)(*cdevsw[maj].d_close)(cl->cl_croot, FREAD);
cl->cl_croot = root;
return (md->md_unit);
}
cl->cl_croot = root;
}
return (-1);
}
chkcdev(cl)
register struct cdevlist *cl;
{
register struct mb_device *md;
register int status = -1;
for (md = mbdinit; md->md_driver; md++) {
short maj;
/* looking for correct driver and unit number */
if (md->md_alive == 0 || md->md_driver != cl->cl_driver)
continue;
#ifdef not
/*
* If want things exact; but slow...
* Then reverse this ifdef.
*/
status = 0;
maj = major(cl->cl_croot);
if ((*cdevsw[maj].d_open)(cl->cl_croot, FREAD) == 0) {
(void)(*cdevsw[maj].d_close)(cl->cl_croot, FREAD);
return (1);
}
#else not
return (1);
#endif not
}
/*
* The device was not in the system maintained list of mainbus devices.
* Check for a pseudo device that is usable as a root or swap device.
*/
if ((cl->cl_driver->mdr_flags & MDR_PSEUDO) != 0)
return (1);
return (status);
}
#else !OPENPROMS
/*
* The ram disk driver is initialized from another device
* that contains the image of a 4.2 file system.
*
* Return the device number and name of the first
* char device in the cdevlist that can be opened.
* Name must be at least 128 bytes long.
*/
int
getchardev(askfor, name, fileno, cdev, bdev)
char *askfor,
*name;
int *fileno; /* -1 or file number on tape */
dev_t *cdev, *bdev;
{
register struct cdevlist *cl;
int unit,
part;
struct dev_info *dip;
char devname[OBP_MAXDEVNAME];
char *path;
extern char *prom_bootpath();
if (!cdevlist) {
if (build_cdevlist() == 0) {
panic("getchardev: No Devices to boot off of?");
/*NOTREACHED*/
}
}
/*
* see if a default is defined or if we can just use the bootargs
*/
if (!(boothowto & RB_ASKNAME)) {
if (loadramdiskfrom[0] == '\0') {
path = prom_bootpath();
#ifdef DPRINTF
DPRINTF("getchardev: path <%s> --> ", path ? path : "NONE!");
#endif DPRINTF
if (prom_get_boot_dev_name( devname, sizeof devname ) != 0) {
#ifdef DPRINTF
DPRINTF("getchardev: Error getting devname (tryagain)");
#endif DPRINTF
goto tryagain;
}
unit = prom_get_boot_dev_unit();
part = prom_get_boot_dev_part();
#ifdef DPRINTF
DPRINTF("device <%s> unit <%x> part <%d>\n",
devname, unit, part);
#endif DPRINTF
loadramdiskfrom[0] = devname[0];
loadramdiskfrom[1] = devname[1];
loadramdiskfrom[2] = (char)0;
/*
* XXX bad cause IPI has lots of units!
*/
loadramdiskfrom[2] = '0' + unit;
loadramdiskfrom[3] = 'a' + part;
loadramdiskfrom[4] = '\0';
}
(void)strncpy(name, loadramdiskfrom, 16);
for (cl = cdevlist; cl != NULL; cl = cl->cl_next) {
if (!(cl->cl_exists & (1 << unit)))
continue;
if (strncmp(cl->cl_dev->devi_name, name, 2) == 0) {
printf("Loading ram disk from %s\n", name);
goto got_name;
}
}
/*
* maybe, if it was "sd" and the unit didn't exist, it
* was really "sr" (we boot "sr" as "sd")
*/
if ((name[0] == 's') && (name[1] == 'd')) {
for (cl = cdevlist; cl != NULL; cl = cl->cl_next) {
if (strncmp(cl->cl_dev->devi_name, "sr", 2))
continue;
/* we found "sr", does it exist? */
/* XXX NOTE: ASSUMES only 1 cdrom! */
if (!(cl->cl_exists))
continue;
/* it lives, so fix things up */
name[1] = 'r';
unit = 0; /* XXX ASSUMES only 1 CDROM */
/*
* we leave partition as is, for rd.c rd_offset
* rd.c will strip out before doing open
*/
printf("Loading ram disk from %s\n", name);
goto got_name;
}
}
}
tryagain:
for (unit = -1; unit == -1; /* empty */) {
printf("%s device (", askfor);
for (cl = cdevlist; cl != NULL; cl = cl->cl_next)
if (cl->cl_exists)
printf("%s%%d[a-h] ", cl->cl_dev->devi_name);
printf("): ");
gets(name);
if (*name == '\0') {
cl = cdevlist;
unit = 0;
part = 0;
break;
}
for (cl = cdevlist; cl != NULL; cl = cl->cl_next) {
if (strncmp(cl->cl_dev->devi_name, name, 2) == 0)
break;
}
if (!cl) {
printf(
"Unknown device name '%c%c'\n", name[0], name[1]);
continue;
}
if (name[2] < '0' || name[2] > '7') {
printf("bad/missing unit number\n");
continue;
}
unit = name[2] - '0';
if (name[3] == '\0') {
part = 0;
} else if (name[3] >= 'a' && name[3] <= 'h') {
part = name[3] - 'a';
} else {
printf("bad partition (use a-h)\n");
unit = -1;
}
}
name[0] = cl->cl_dev->devi_name[0];
name[1] = cl->cl_dev->devi_name[1];
name[2] = '0' + unit;
name[3] = 'a' + part;
name[4] = '\0';
got_name:
/* If the device is a tape, prompt for the file number */
if ((bdevsw[major(cl->cl_broot)].d_flags & B_TAPE) != 0) {
char buf[40];
register char *p = buf;
register int num;
if (!(boothowto & RB_ASKNAME) && (loadramdiskfile != -1)) {
*fileno = loadramdiskfile;
} else {
p = buf;
do {
printf("Tape file number? ");
gets(p);
} while (!*p || *p < '0' || *p > '9');
for (num = 0; *p && *p >= '0' && *p <= '9'; ++p)
num = (num * 10) + *p - '0';
*fileno = num;
}
*bdev = makedev(major(cl->cl_broot),
minor(cl->cl_broot)|unit|part);
*cdev = makedev(major(cl->cl_croot),
minor(cl->cl_croot)|unit|part);
} else {
*fileno = -1;
*bdev = makedev(major(cl->cl_broot), (unit * 8 + part));
*cdev = makedev(major(cl->cl_croot), (unit * 8 + part));
}
/*
* This should be also be pertinent for
* sun3x/80 or other ejectable floppy machines.
*
*
* if an auto ejectable floppy, we must eject the one we booted
* off of so the filesystem can be loaded
* NOTE: we can't open/do ioctls to the device - it isn't mapped in yet.
*/
/*
* FIXME FIX ME XXX should really do either...
* if (cmajor(cdev) == 54 || cmajor(cdev) == Maj#of_sf)
*/
if (name[0] == 'f' && name[1] == 'd') {
/* turn on drive select and (later eject) */
#ifdef sun4c
Auxio |= (AUX_MBO | AUX_EJECT); /* pre-set eject ?proms broke?*/
Auxio |= (AUX_MBO | AUX_DRVSELECT);
DELAY(100);
Auxio = (Auxio | AUX_MBO) & ~AUX_EJECT; /* eject is low true */
DELAY(100);
/* now turn off both eject and select, MBO = Must Be Ones! */
Auxio = (Auxio | AUX_MBO | AUX_EJECT) & ~AUX_DRVSELECT;
printf(
"please insert diskette \"B\", press any key to continue:");
#else sun4c
printf("please insert next diskette, type any key to continue");
#endif sun4c
if (getchar() != '\n')
printf("\n");
}
}
#endif !OPENPROMS
#endif NRD > 0
#ifndef OPENPROMS
/*
* Lookup unit number for scsi. Translates physical unit number
* (really target/lun number) into kernel logical unit number.
* Returns logical unit number. Otherwise, returns -1.
* XXX: There ought to be a way to combine this with lkupcdev and
* save some space.
*/
lkupbdev(bl, ctlr, unit, flags)
register struct bdevlist *bl;
int ctlr, unit, flags;
{
register struct mb_device *md = mbdinit;
int root;
short maj, minr;
/* Find entry in table */
for (md = mbdinit; md->md_driver; md++) {
if (md->md_alive == 0 || md->md_driver != bl->bl_driver ||
md->md_flags != flags || md->md_ctlr != ctlr ||
md->md_slave != unit)
continue;
/* Fix up minor unit number to point to right unit. */
if (flags == TAPE)
minr = MTMINOR(md->md_unit) + MT_NOREWIND;
else
minr = md->md_unit <<3;
/* Open device and see if it's there. */
root = bl->bl_root;
bl->bl_root = makedev(major(root), minr);
maj = major(bl->bl_root);
if ((*bdevsw[maj].d_open)(bl->bl_root, FREAD) == 0) {
(void)(*bdevsw[maj].d_close)(bl->bl_root, FREAD);
bl->bl_root = root;
return (md->md_unit);
}
bl->bl_root = root;
}
return (-1);
}
/*
* Check for block device presence. Returns -1 (no controller),
* 0 (controller present but no unit), or 1 (controller and unit present).
*/
chkroot(bl)
register struct bdevlist *bl;
{
register struct mb_device *md;
register int status = -1;
for (md = mbdinit; md->md_driver; md++) {
short maj;
if (md->md_alive == 0 || md->md_driver != bl->bl_driver)
continue;
status = 0;
maj = major(bl->bl_root);
if ((*bdevsw[maj].d_open)(bl->bl_root, FREAD) == 0) {
(void)(*bdevsw[maj].d_close)(bl->bl_root, FREAD);
return (1);
}
}
/*
* The device was not in the system maintained list of mainbus devices.
* Check for a pseudo device that is usable as a root or swap device.
*/
if ((bl->bl_driver->mdr_flags & MDR_PSEUDO) != 0)
return (1);
return (status);
}
#endif !OPENPROMS
/*
* These routines moved outside the "ifndef OPENPROMS" as they
* are needed for VME disk boot.
*/
/*
* Parse device name into unit and partition number.
* The name is of one of two forms:
* decimal: 2 char name, 1-2 digit unit, 1 char partition.
* hex: 2 char name, 3 hex unit, 1 char partition.
* Returns non-zero if name in good form.
* Sets unit number pointed to by unitp to -1 if badly parsed.
* Leaves unit number and partition at old value if not entered.
*/
static int
sg_parse_name(name, unitp, partp, flags)
char *name;
int *unitp, *partp;
int flags;
{
int i, c, unit;
char *cp;
cp = name + 2;
if (*cp == '\0') /* no unit number specified - OK */
return (1);
if (flags & SG_HEXUNIT) {
unit = 0;
for (i = 0; i < SG_NHEX; i++) {
c = *cp++;
if (c == '\0') {
printf(
"unit number too short. specify 3 hex\n");
*unitp = -1;
return (0);
}
unit <<= 4;
if (c >= '0' && c <= '9') {
unit += c - '0';
} else if (c >= 'a' && c <= 'f') {
unit += c - 'a';
} else if (c >= 'A' && c <= 'F') {
unit += c - 'A';
} else {
printf("bad hex digit '%c'\n", c);
*unitp = -1;
return (0);
}
}
} else {
if ((c = *cp++) < '0' || c > '9') {
printf("bad unit number.\n");
*unitp = -1;
return (0);
}
unit = c - '0';
/*
* handle optional second digit.
*/
if ((c = *cp) >= '0' && c <= '9') {
unit *= 10;
unit += c - '0';
cp++;
}
}
*unitp = unit;
if ((c = *cp) == '\0')
return (1); /* no partition - allow default */
if (c >= 'a' && c <= 'h') {
*partp = c - 'a';
} else {
printf("bad partition (use a-h)\n");
*unitp = -1; /* flag error */
return (0);
}
return (1);
}
/*
* form device number and name for unit, partition, and flags.
*/
static dev_t
sg_form_dev(base_dev, str, unit, part, flags)
dev_t base_dev; /* starting device major/minor number */
char *str; /* place to put ascii unit/partition */
int unit, part; /* unit and partition */
int flags;
{
int majdev = major(base_dev);
int mindev = minor(base_dev);
int i;
if (flags & SG_HEXUNIT) {
/* Process hex unit numbers (e.g. IPI devices) */
for (i = (SG_NHEX-1)*4; i >= 0; i -= 4) /* put 3 hex */
*str++ = "0123456789abcdef"[(unit >> i) & 0xf];
/*
* Bit 7 of the unit number must be zero and isn't used in
* calculating the major/minor number. This is so it fits
* better into a limited number of major numbers. This bit
* corresponds to the high order bit of the slave number, which
* ranges 0-7.
*/
unit = (unit & ~0xff) >> 1 | unit & 0x7f;
unit = unit * 8 + part;
majdev += (unit >> 8) & 0xff;
mindev += unit & 0xff;
} else {
/* Process decimal unit numbers (default) */
if (unit >= 10) {
*str++ = '0' + (unit / 10);
unit %= 10;
}
*str++ = '0' + unit;
if (flags & SG_TAPE) {
/* tape minor number */
mindev = MTMINOR(unit) + MT_NOREWIND;
} else {
/* disk minor number */
mindev |= (unit * 8 + part);
}
}
*str++ = 'a' + part;
*str = '\0';
return (makedev(majdev, mindev));
}
getchar()
{
register c;
c = cngetc();
if (c == '\r')
c = '\n';
#ifdef sun4c
else if (c == 0177)
return (c);
#endif
cnputc(c);
return (c);
}
gets(cp)
char *cp;
{
register char *lp;
register c;
lp = cp;
while (1) {
c = getchar() & 0177;
switch (c) {
case '\n':
*lp++ = '\0';
return;
case 0177:
if (lp > cp) {
cnputc('\b');
}
case '\b':
if (lp > cp) {
cnputc(' ');
cnputc('\b');
}
case '#':
lp--;
if (lp < cp)
lp = cp;
continue;
case '@':
case 'u'&037:
lp = cp;
cnputc('\n');
continue;
default:
*lp++ = c;
}
}
}
static
fubar()
{
/* this is really ugly, but it makes cc -O work */
}