Three distinct changes:

- Better disklabel handling.  While a disklabel isn't used
	  in the driver, some versions of the OpenPROM insist on
	  one being present in order to boot from floppy.  These
	  changes provide a default label (in a way similar to how
	  the SCSI disk driver provides a default) so that a user
	  can more easily place the label on the disk.

	- Fix semi-bug in bootpath handling.  It appears as if the
	  bootpath can appear in a couple of formats: "/fd@0,0", which
	  is what bootpath_fake() creates on v0 proms and may be
	  passed by some v2 proms, and "/fd0" which is what the
	  v2 prom on my SS2 passes.  We now handle both formats.

	- Use a mountroot hook to eject the floppy and wait for
	  the user to insert a filesystem floppy if we're the boot/root
	  device.
This commit is contained in:
thorpej 1996-01-15 00:14:42 +00:00
parent 3f8e0d27a6
commit 8a5504241e

View File

@ -1,4 +1,4 @@
/* $NetBSD: fd.c,v 1.18 1996/01/12 00:19:47 thorpej Exp $ */
/* $NetBSD: fd.c,v 1.19 1996/01/15 00:14:42 thorpej Exp $ */
/*-
* Copyright (c) 1993, 1994, 1995 Charles Hannum.
@ -52,6 +52,7 @@
#include <sys/disk.h>
#include <sys/buf.h>
#include <sys/uio.h>
#include <sys/stat.h>
#include <sys/syslog.h>
#include <sys/queue.h>
@ -196,7 +197,7 @@ struct cfdriver fdcd = {
NULL, "fd", fdmatch, fdattach, DV_DISK, sizeof(struct fd_softc)
};
void fdgetdisklabel __P((struct fd_softc *));
void fdgetdisklabel __P((dev_t));
int fd_get_parms __P((struct fd_softc *));
void fdstrategy __P((struct buf *));
void fdstart __P((struct fd_softc *));
@ -222,6 +223,8 @@ void fdchwintr __P((void));
int fdcswintr __P((struct fdc_softc *));
void fdcretry __P((struct fdc_softc *fdc));
void fdfinish __P((struct fd_softc *fd, struct buf *bp));
void fd_do_eject __P((void));
void fd_mountroot_hook __P((struct device *));
#if PIL_FDSOFT == 4
#define IE_FDSOFT IE_L4
@ -398,12 +401,23 @@ fdcattach(parent, self, aux)
* Openprom node, so we can as well check for the floppy boots here.
*/
if (ca->ca_ra.ra_bp &&
strcmp(ca->ca_ra.ra_bp->name, OBP_FDNAME) == 0 &&
ca->ca_ra.ra_bp->val[0] == 0 &&
ca->ca_ra.ra_bp->val[1] == 0)
fa.fa_bootdev = 1;
else
fa.fa_bootdev = 0;
strcmp(ca->ca_ra.ra_bp->name, OBP_FDNAME) == 0) {
/*
* WOAH THERE! It looks like we can get the bootpath
* in a couple of different formats!! The faked
* bootpath (and some v2?) looks like /fd@0,0
* but the real bootpath on some v2 OpenPROM
* systems looks like /fd0. We deal with that
* bere by looking for either case. --thorpej
*/
if (((ca->ca_ra.ra_bp->val[0] == 0) && /* /fd@0,0 */
(ca->ca_ra.ra_bp->val[1] == 0)) ||
((ca->ca_ra.ra_bp->val[0] == -1) && /* /fd0 */
(ca->ca_ra.ra_bp->val[1] == 0)))
fa.fa_bootdev = 1;
else
fa.fa_bootdev = 0;
}
/* physical limit: four drives per controller. */
for (fa.fa_drive = 0; fa.fa_drive < 4; fa.fa_drive++) {
@ -522,6 +536,12 @@ fdattach(parent, self, aux)
if (fa->fa_bootdev)
bootdv = &fd->sc_dv;
/*
* Establish a mountroot_hook anyway in case we booted
* with RB_ASKNAME and get selected as the boot device.
*/
mountroot_hook_establish(fd_mountroot_hook, &fd->sc_dv);
/* XXX Need to do some more fiddling with sc_dk. */
dk_establish(&fd->sc_dk, &fd->sc_dv);
}
@ -774,11 +794,12 @@ out_fdc(fdc, x)
}
int
Fdopen(dev, flags)
Fdopen(dev, flags, fmt, p)
dev_t dev;
int flags;
int flags, fmt;
struct proc *p;
{
int unit;
int unit, pmask;
struct fd_softc *fd;
struct fd_type *type;
@ -800,17 +821,52 @@ Fdopen(dev, flags)
fd->sc_cylin = -1;
fd->sc_flags |= FD_OPEN;
/*
* Only update the disklabel if we're not open anywhere else.
*/
if (fd->sc_dk.dk_openmask == 0)
fdgetdisklabel(dev);
pmask = (1 << DISKPART(dev));
switch (fmt) {
case S_IFCHR:
fd->sc_dk.dk_copenmask |= pmask;
break;
case S_IFBLK:
fd->sc_dk.dk_bopenmask |= pmask;
break;
}
fd->sc_dk.dk_openmask =
fd->sc_dk.dk_copenmask | fd->sc_dk.dk_bopenmask;
return 0;
}
int
fdclose(dev, flags)
fdclose(dev, flags, fmt, p)
dev_t dev;
int flags;
int flags, fmt;
struct proc *p;
{
struct fd_softc *fd = fdcd.cd_devs[FDUNIT(dev)];
int pmask = (1 << DISKPART(dev));
fd->sc_flags &= ~FD_OPEN;
switch (fmt) {
case S_IFCHR:
fd->sc_dk.dk_copenmask &= ~pmask;
break;
case S_IFBLK:
fd->sc_dk.dk_bopenmask &= ~pmask;
break;
}
fd->sc_dk.dk_openmask =
fd->sc_dk.dk_copenmask | fd->sc_dk.dk_bopenmask;
return 0;
}
@ -1424,17 +1480,6 @@ fdioctl(dev, cmd, addr, flag)
switch (cmd) {
case DIOCGDINFO:
bzero(fd->sc_dk.dk_label, sizeof(struct disklabel));
fd->sc_dk.dk_label->d_secpercyl = fd->sc_type->seccyl;
fd->sc_dk.dk_label->d_type = DTYPE_FLOPPY;
fd->sc_dk.dk_label->d_secsize = FDC_BSIZE;
if (readdisklabel(dev, fdstrategy,
fd->sc_dk.dk_label,
fd->sc_dk.dk_cpulabel) != NULL)
return EINVAL;
*(struct disklabel *)addr = *(fd->sc_dk.dk_label);
return 0;
@ -1460,9 +1505,7 @@ fdioctl(dev, cmd, addr, flag)
return error;
case DIOCEJECT:
auxregbisc(AUXIO_FDS, AUXIO_FEJ);
delay(10);
auxregbisc(AUXIO_FEJ, AUXIO_FDS);
fd_do_eject();
return 0;
#ifdef DEBUG
@ -1510,3 +1553,92 @@ fdioctl(dev, cmd, addr, flag)
panic("fdioctl: impossible");
#endif
}
void
fdgetdisklabel(dev)
dev_t dev;
{
int unit = FDUNIT(dev), i;
struct fd_softc *fd = fdcd.cd_devs[unit];
struct disklabel *lp = fd->sc_dk.dk_label;
struct cpu_disklabel *clp = fd->sc_dk.dk_cpulabel;
bzero(lp, sizeof(struct disklabel));
bzero(lp, sizeof(struct cpu_disklabel));
lp->d_type = DTYPE_FLOPPY;
lp->d_secsize = FDC_BSIZE;
lp->d_secpercyl = fd->sc_type->seccyl;
lp->d_nsectors = fd->sc_type->sectrac;
lp->d_ncylinders = fd->sc_type->tracks;
lp->d_ntracks = fd->sc_type->heads; /* Go figure... */
lp->d_rpm = 3600; /* XXX like it matters... */
strncpy(lp->d_typename, "floppy", sizeof(lp->d_typename));
strncpy(lp->d_packname, "fictitious", sizeof(lp->d_packname));
lp->d_interleave = 1;
lp->d_partitions[RAW_PART].p_offset = 0;
lp->d_partitions[RAW_PART].p_size = lp->d_secpercyl * lp->d_ncylinders;
lp->d_partitions[RAW_PART].p_fstype = FS_UNUSED;
lp->d_npartitions = RAW_PART + 1;
lp->d_magic = DISKMAGIC;
lp->d_magic2 = DISKMAGIC;
lp->d_checksum = dkcksum(lp);
/*
* Call the generic disklabel extraction routine. If there's
* not a label there, fake it.
*/
if (readdisklabel(dev, fdstrategy, lp, clp) != NULL) {
strncpy(lp->d_packname, "default label",
sizeof(lp->d_packname));
/*
* Reset the partition info; it might have gotten
* trashed in readdisklabel().
*
* XXX Why do we have to do this? readdisklabel()
* should be safe...
*/
for (i = 0; i < MAXPARTITIONS; ++i) {
lp->d_partitions[i].p_offset = 0;
if (i == RAW_PART) {
lp->d_partitions[i].p_size =
lp->d_secpercyl * lp->d_ncylinders;
lp->d_partitions[i].p_fstype = FS_BSDFFS;
} else {
lp->d_partitions[i].p_size = 0;
lp->d_partitions[i].p_fstype = FS_UNUSED;
}
}
lp->d_npartitions = RAW_PART + 1;
}
}
void
fd_do_eject()
{
auxregbisc(AUXIO_FDS, AUXIO_FEJ);
delay(10);
auxregbisc(AUXIO_FEJ, AUXIO_FDS);
}
/* ARGSUSED */
void
fd_mountroot_hook(dev)
struct device *dev;
{
int c;
fd_do_eject();
printf("Insert filesystem floppy and press return.");
for (;;) {
c = cngetc();
if ((c == '\r') || (c == '\n')) {
printf("\n");
return;
}
}
}