Date: Wed, 21 Jan 2009 17:32:26 +0000 (UTC) From: Jung-uk Kim <jkim@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-7@freebsd.org Subject: svn commit: r187544 - in stable/7/sys: . contrib/pf dev/ath/ath_hal dev/cxgb dev/fdc Message-ID: <200901211732.n0LHWQoE084920@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: jkim Date: Wed Jan 21 17:32:26 2009 New Revision: 187544 URL: http://svn.freebsd.org/changeset/base/187544 Log: MFC: r184976 - Revive fdc(4) per-device flag 0x10, which was removed in r1.284[1]. - If the flag is set and auto-select fails, assume disk is not present. - Set disk empty flag only when the floppy controller reset is needed. It fixes regression introduced in r1.311, which prevented it from ignoring errors. Now fdformat(1) and dd(1) with conv=noerror option can continue when read/write errors occur as they should. - Do not retry disk probing as it is extremely slow and pointless. - Move the disk probing code into a separate function. - Do not reset disk empty flag if write-protect check fails somehow. PR: kern/116538[1] Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/dev/fdc/fdc.c Modified: stable/7/sys/dev/fdc/fdc.c ============================================================================== --- stable/7/sys/dev/fdc/fdc.c Wed Jan 21 17:28:24 2009 (r187543) +++ stable/7/sys/dev/fdc/fdc.c Wed Jan 21 17:32:26 2009 (r187544) @@ -97,6 +97,8 @@ __FBSDID("$FreeBSD$"); * fd_drivetype; on i386 machines, if * given as 0, use RTC type for fd0 * and fd1 */ +#define FD_NO_CHLINE 0x10 /* drive does not support changeline + * aka. unit attention */ #define FD_NO_PROBE 0x20 /* don't probe drive (seek test), just * assume it is there */ @@ -263,6 +265,7 @@ struct fd_data { static driver_intr_t fdc_intr; static driver_filter_t fdc_intr_fast; static void fdc_reset(struct fdc_data *); +static int fd_probe_disk(struct fd_data *, int *); SYSCTL_NODE(_debug, OID_AUTO, fdc, CTLFLAG_RW, 0, "fdc driver"); @@ -768,9 +771,11 @@ fdc_worker(struct fdc_data *fdc) (fdc->retry >= retries || (fd->options & FDOPT_NORETRY))) { if ((debugflags & 4)) printf("Too many retries (EIO)\n"); - mtx_lock(&fdc->fdc_mtx); - fd->flags |= FD_EMPTY; - mtx_unlock(&fdc->fdc_mtx); + if (fdc->flags & FDC_NEEDS_RESET) { + mtx_lock(&fdc->fdc_mtx); + fd->flags |= FD_EMPTY; + mtx_unlock(&fdc->fdc_mtx); + } return (fdc_biodone(fdc, EIO)); } @@ -836,65 +841,12 @@ fdc_worker(struct fdc_data *fdc) fdctl_wr(fdc, fd->ft->trans); if (bp->bio_cmd & BIO_PROBE) { - - if (!(fdin_rd(fdc) & FDI_DCHG) && !(fd->flags & FD_EMPTY)) + if ((!(device_get_flags(fd->dev) & FD_NO_CHLINE) && + !(fdin_rd(fdc) & FDI_DCHG) && + !(fd->flags & FD_EMPTY)) || + fd_probe_disk(fd, &need_recal) == 0) return (fdc_biodone(fdc, 0)); - - /* - * Try to find out if we have a disk in the drive - * - * First recal, then seek to cyl#1, this clears the - * old condition on the disk change line so we can - * examine it for current status - */ - if (debugflags & 0x40) - printf("New disk in probe\n"); - mtx_lock(&fdc->fdc_mtx); - fd->flags |= FD_NEWDISK; - mtx_unlock(&fdc->fdc_mtx); - retry_line = __LINE__; - if (fdc_cmd(fdc, 2, NE7CMD_RECAL, fd->fdsu, 0)) - return (1); - tsleep(fdc, PRIBIO, "fdrecal", hz); - retry_line = __LINE__; - if (fdc_sense_int(fdc, &st0, &cyl) == FD_NOT_VALID) - return (1); /* XXX */ - retry_line = __LINE__; - if ((st0 & 0xc0) || cyl != 0) - return (1); - - /* Seek to track 1 */ - retry_line = __LINE__; - if (fdc_cmd(fdc, 3, NE7CMD_SEEK, fd->fdsu, 1, 0)) - return (1); - tsleep(fdc, PRIBIO, "fdseek", hz); - retry_line = __LINE__; - if (fdc_sense_int(fdc, &st0, &cyl) == FD_NOT_VALID) - return (1); /* XXX */ - need_recal |= (1 << fd->fdsu); - if (fdin_rd(fdc) & FDI_DCHG) { - if (debugflags & 0x40) - printf("Empty in probe\n"); - mtx_lock(&fdc->fdc_mtx); - fd->flags |= FD_EMPTY; - mtx_unlock(&fdc->fdc_mtx); - } else { - if (debugflags & 0x40) - printf("Got disk in probe\n"); - mtx_lock(&fdc->fdc_mtx); - fd->flags &= ~FD_EMPTY; - mtx_unlock(&fdc->fdc_mtx); - retry_line = __LINE__; - if(fdc_sense_drive(fdc, &st3) != 0) - return (1); - mtx_lock(&fdc->fdc_mtx); - if(st3 & NE7_ST3_WP) - fd->flags |= FD_WP; - else - fd->flags &= ~FD_WP; - mtx_unlock(&fdc->fdc_mtx); - } - return (fdc_biodone(fdc, 0)); + return (1); } /* @@ -1238,6 +1190,71 @@ fd_enqueue(struct fd_data *fd, struct bi mtx_unlock(&fdc->fdc_mtx); } +/* + * Try to find out if we have a disk in the drive. + */ +static int +fd_probe_disk(struct fd_data *fd, int *recal) +{ + struct fdc_data *fdc; + int st0, st3, cyl; + int oopts, ret; + + fdc = fd->fdc; + oopts = fd->options; + fd->options |= FDOPT_NOERRLOG | FDOPT_NORETRY; + ret = 1; + + /* + * First recal, then seek to cyl#1, this clears the old condition on + * the disk change line so we can examine it for current status. + */ + if (debugflags & 0x40) + printf("New disk in probe\n"); + mtx_lock(&fdc->fdc_mtx); + fd->flags |= FD_NEWDISK; + mtx_unlock(&fdc->fdc_mtx); + if (fdc_cmd(fdc, 2, NE7CMD_RECAL, fd->fdsu, 0)) + goto done; + tsleep(fdc, PRIBIO, "fdrecal", hz); + if (fdc_sense_int(fdc, &st0, &cyl) == FD_NOT_VALID) + goto done; /* XXX */ + if ((st0 & 0xc0) || cyl != 0) + goto done; + + /* Seek to track 1 */ + if (fdc_cmd(fdc, 3, NE7CMD_SEEK, fd->fdsu, 1, 0)) + goto done; + tsleep(fdc, PRIBIO, "fdseek", hz); + if (fdc_sense_int(fdc, &st0, &cyl) == FD_NOT_VALID) + goto done; /* XXX */ + *recal |= (1 << fd->fdsu); + if (fdin_rd(fdc) & FDI_DCHG) { + if (debugflags & 0x40) + printf("Empty in probe\n"); + mtx_lock(&fdc->fdc_mtx); + fd->flags |= FD_EMPTY; + mtx_unlock(&fdc->fdc_mtx); + } else { + if (fdc_sense_drive(fdc, &st3) != 0) + goto done; + if (debugflags & 0x40) + printf("Got disk in probe\n"); + mtx_lock(&fdc->fdc_mtx); + fd->flags &= ~FD_EMPTY; + if (st3 & NE7_ST3_WP) + fd->flags |= FD_WP; + else + fd->flags &= ~FD_WP; + mtx_unlock(&fdc->fdc_mtx); + } + ret = 0; + +done: + fd->options = oopts; + return (ret); +} + static int fdmisccmd(struct fd_data *fd, u_int cmd, void *data) { @@ -1350,7 +1367,7 @@ fdautoselect(struct fd_data *fd) if (debugflags & 0x40) device_printf(fd->dev, "autoselection failed\n"); fdsettype(fd, fd_native_types[fd->type]); - return (0); + return (-1); } else { if (debugflags & 0x40) { device_printf(fd->dev, @@ -1411,7 +1428,13 @@ fd_access(struct g_provider *pp, int r, if (fd->flags & FD_EMPTY) return (ENXIO); if (fd->flags & FD_NEWDISK) { - fdautoselect(fd); + if (fdautoselect(fd) != 0 && + (device_get_flags(fd->dev) & FD_NO_CHLINE)) { + mtx_lock(&fdc->fdc_mtx); + fd->flags |= FD_EMPTY; + mtx_unlock(&fdc->fdc_mtx); + return (ENXIO); + } mtx_lock(&fdc->fdc_mtx); fd->flags &= ~FD_NEWDISK; mtx_unlock(&fdc->fdc_mtx);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200901211732.n0LHWQoE084920>