- 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]
This commit is contained in:
parent
b348c714fa
commit
5807aa9312
@ -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 bio *bp)
|
||||
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, int w, int e)
|
||||
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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user