From b983bae23bf7341b9bf5daaef53789d401773b79 Mon Sep 17 00:00:00 2001 From: joerg Date: Fri, 29 Jun 2001 15:30:48 +0000 Subject: Use the new-born BIO_CMD1 instead of fudging a bio_flag value for reading the sector ID. Based on numerous comments made by Bruce, rewrite a good part of the old fdformat() function, and merge it with fdreadid() into a single unified fdmisccmd() function. Various style and a couple of more serious bugs fixed there. While i was at it, i also fixed the long-standing "TODO: don't allocate buffer on stack." in fdcioctl(), fixed a number of style bugs there, and finally implemented the FD_DEBUG ioctl command that has been advertised in (formerly ) for almost seven years now. ;-) Submitted by: bde (a lot of fixes for fdformat()) --- sys/isa/fd.c | 188 +++++++++++++++++++++++------------------------------------ 1 file changed, 72 insertions(+), 116 deletions(-) (limited to 'sys/isa') diff --git a/sys/isa/fd.c b/sys/isa/fd.c index 206097d..5e95d0c 100644 --- a/sys/isa/fd.c +++ b/sys/isa/fd.c @@ -121,7 +121,7 @@ #define FD_360in5_25 16 #define FD_640in5_25 17 -#define BIO_RDSECTID BIO_FLAG1 +#define BIO_RDSECTID BIO_CMD1 static struct fd_type fd_types[NUMTYPES] = { @@ -215,8 +215,7 @@ static timeout_t fd_iotimeout; static timeout_t fd_pseudointr; static int fdstate(struct fdc_data *); static int retrier(struct fdc_data *); -static int fdformat(dev_t, struct fd_formb *, struct proc *); -static int fdreadid(dev_t, struct fdc_readid *); +static int fdmisccmd(dev_t, u_int, void *); static int enable_fifo(fdc_p fdc); static void fd_clone (void *arg, char *name, int namelen, dev_t *dev); @@ -1497,7 +1496,7 @@ fdstrategy(struct bio *bp) goto bad; } fdblk = 128 << (fd->ft->secsize); - if (bp->bio_cmd != BIO_FORMAT && (bp->bio_flags & BIO_RDSECTID) == 0) { + if (bp->bio_cmd != BIO_FORMAT && bp->bio_cmd != BIO_RDSECTID) { if (bp->bio_blkno < 0) { printf( "fd%d: fdstrat: bad request blkno = %lu, bcount = %ld\n", @@ -1712,7 +1711,7 @@ fdstate(fdc_p fdc) else idf = ISADMA_WRITE; format = bp->bio_cmd == BIO_FORMAT; - rdsectid = bp->bio_flags & BIO_RDSECTID; + rdsectid = bp->bio_cmd == BIO_RDSECTID; if (format) { finfo = (struct fd_formb *)bp->bio_data; fd->skip = (char *)&(finfo->fd_formb_cylno(0)) @@ -2253,147 +2252,90 @@ fdbiodone(struct bio *bp) } static int -fdformat(dev_t dev, struct fd_formb *finfo, struct proc *p) +fdmisccmd(dev_t dev, u_int cmd, void *data) { - fdu_t fdu; - fd_p fd; - + fdu_t fdu; + fd_p fd; struct bio *bp; - int rv = 0, s; + struct fd_formb *finfo; + struct fdc_readid *idfield; size_t fdblk; - fdu = FDUNIT(minor(dev)); - fd = devclass_get_softc(fd_devclass, fdu); + fdu = FDUNIT(minor(dev)); + fd = devclass_get_softc(fd_devclass, fdu); fdblk = 128 << fd->ft->secsize; + finfo = (struct fd_formb *)data; + idfield = (struct fdc_readid *)data; - /* set up a buffer header for fdstrategy() */ - bp = (struct bio *)malloc(sizeof(struct bio), M_TEMP, M_NOWAIT); - if(bp == 0) - return ENOMEM; - /* - * keep the process from being swapped - */ - PHOLD(p); - bzero((void *)bp, sizeof(*bp)); - bp->bio_cmd = BIO_FORMAT; + bp = malloc(sizeof(struct bio), M_TEMP, M_ZERO | M_NOWAIT); + if (bp == 0) + return (ENOMEM); /* - * calculate a fake blkno, so fdstrategy() would initiate a - * seek to the requested cylinder + * Set up a bio request for fdstrategy(). bio_blkno is faked + * so that fdstrategy() will seek to the the requested + * cylinder, and use the desired head. Since we are not + * interested in bioqdisksort() munging with our faked bio + * request, we mark it as being an ordered request. */ - bp->bio_blkno = (finfo->cyl * (fd->ft->sectrac * fd->ft->heads) - + finfo->head * fd->ft->sectrac) * fdblk / DEV_BSIZE; - - bp->bio_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs; - bp->bio_data = (caddr_t)finfo; - - /* now do the format */ + bp->bio_cmd = cmd; + if (cmd == BIO_FORMAT) { + bp->bio_blkno = + (finfo->cyl * (fd->ft->sectrac * fd->ft->heads) + + finfo->head * fd->ft->sectrac) * + fdblk / DEV_BSIZE; + bp->bio_bcount = sizeof(struct fd_idfield_data) * + finfo->fd_formb_nsecs; + } else if (cmd == BIO_RDSECTID) { + bp->bio_blkno = + (idfield->cyl * (fd->ft->sectrac * fd->ft->heads) + + idfield->head * fd->ft->sectrac) * + fdblk / DEV_BSIZE; + bp->bio_bcount = sizeof(struct fdc_readid); + } else + panic("wrong cmd in fdmisccmd()"); + bp->bio_data = data; bp->bio_dev = dev; bp->bio_done = fdbiodone; - fdstrategy(bp); - - /* ...and wait for it to complete */ - s = splbio(); - while(!(bp->bio_flags & BIO_DONE)) { - rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz); - if (rv == EWOULDBLOCK) - break; - } - splx(s); - - if (rv == EWOULDBLOCK) { - /* timed out */ - rv = EIO; - device_unbusy(fd->dev); - } - if (bp->bio_flags & BIO_ERROR) - rv = bp->bio_error; - /* - * allow the process to be swapped - */ - PRELE(p); - free(bp, M_TEMP); - return rv; -} - -static int -fdreadid(dev_t dev, struct fdc_readid *idfield) -{ - fdu_t fdu; - fd_p fd; - - struct bio *bp; - int rv = 0, s; - size_t fdblk; - - fdu = FDUNIT(minor(dev)); - fd = devclass_get_softc(fd_devclass, fdu); - fdblk = 128 << fd->ft->secsize; - - /* set up a buffer header for fdstrategy() */ - bp = (struct bio *)malloc(sizeof(struct bio), M_TEMP, M_NOWAIT); - if(bp == 0) - return ENOMEM; - - bzero((void *)bp, sizeof(*bp)); - bp->bio_cmd = BIO_READ; - bp->bio_flags |= BIO_RDSECTID; + bp->bio_flags = BIO_ORDERED; /* - * calculate a fake blkno, so fdstrategy() would initiate a - * seek to the requested cylinder + * Now run the cmd. The wait loop is a version of bufwait() + * adapted for struct bio instead of struct buf and + * specialized for the current context. */ - bp->bio_blkno = (idfield->cyl * (fd->ft->sectrac * fd->ft->heads) - + idfield->head * fd->ft->sectrac) * fdblk / DEV_BSIZE; - bp->bio_bcount = sizeof(struct fdc_readid); - bp->bio_data = (caddr_t)idfield; - bp->bio_dev = dev; - bp->bio_done = fdbiodone; fdstrategy(bp); + while((bp->bio_flags & BIO_DONE) == 0) + tsleep(bp, PRIBIO, "fdcmd", 0); - /* ...and wait for it to complete */ - s = splbio(); - while(!(bp->bio_flags & BIO_DONE)) { - rv = tsleep((caddr_t)bp, PRIBIO, "fdrdid", 10 * hz); - if (rv == EWOULDBLOCK) - break; - } - splx(s); - - if (rv == EWOULDBLOCK) { - /* timed out */ - rv = EIO; - device_unbusy(fd->dev); - } - if (bp->bio_flags & BIO_ERROR) - rv = bp->bio_error; free(bp, M_TEMP); - return rv; + return (bp->bio_flags & BIO_ERROR ? bp->bio_error : 0); } -/* - * TODO: don't allocate buffer on stack. - */ - static int fdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) { - fdu_t fdu = FDUNIT(minor(dev)); - fd_p fd = devclass_get_softc(fd_devclass, fdu); - size_t fdblk; - + fdu_t fdu; + fd_p fd; struct fd_type *fdt; struct disklabel *dl; struct fdc_status *fsp; struct fdc_readid *rid; - char buffer[DEV_BSIZE]; + char *buffer; + size_t fdblk; int error = 0; + fdu = FDUNIT(minor(dev)); + fd = devclass_get_softc(fd_devclass, fdu); fdblk = 128 << fd->ft->secsize; switch (cmd) { case DIOCGDINFO: - bzero(buffer, sizeof (buffer)); + buffer = malloc(DEV_BSIZE, M_TEMP, M_ZERO | M_NOWAIT); + if (buffer == 0) { + error = ENOMEM; + break; + } dl = (struct disklabel *)buffer; dl->d_secsize = fdblk; fdt = fd->ft; @@ -2407,6 +2349,7 @@ fdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) error = EINVAL; *(struct disklabel *)addr = *dl; + free(buffer, M_TEMP); break; case DIOCSDINFO: @@ -2427,12 +2370,19 @@ fdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) dl = (struct disklabel *)addr; + buffer = malloc(DEV_BSIZE, M_TEMP, M_ZERO | M_NOWAIT); + if (buffer == 0) { + error = ENOMEM; + break; + } if ((error = setdisklabel((struct disklabel *)buffer, dl, (u_long)0)) != 0) break; error = writedisklabel(dev, (struct disklabel *)buffer); + free(buffer, M_TEMP); break; + case FD_FORM: if ((flag & FWRITE) == 0) error = EBADF; /* must be opened for writing */ @@ -2440,7 +2390,7 @@ fdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) FD_FORMAT_VERSION) error = EINVAL; /* wrong version of formatting prog */ else - error = fdformat(dev, (struct fd_formb *)addr, p); + error = fdmisccmd(dev, BIO_FORMAT, addr); break; case FD_GTYPE: /* get drive type */ @@ -2462,6 +2412,12 @@ fdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) fd->options = *(int *)addr; break; +#ifdef FDC_DEBUG + case FD_DEBUG: + fd_debug = *(int *)addr; + break; +#endif + case FD_CLRERR: if (suser(p) != 0) return EPERM; @@ -2479,7 +2435,7 @@ fdioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) rid = (struct fdc_readid *)addr; if (rid->cyl > MAX_CYLINDER || rid->head > MAX_HEAD) return EINVAL; - error = fdreadid(dev, rid); + error = fdmisccmd(dev, BIO_RDSECTID, addr); break; default: -- cgit v1.1