Change the PIO loops from a hard counter into a loop that calls DELAY()

in each cycle, with a tunable max cycle count defined in fdreg.h.

This is said to fix the problem on some Compaq hardware (and perhaps
on other machines using the Natsemi PC87317 chip) where the fdc(4)
driver failed to operate at all.

PR:		kern/21397
Submitted by:	Jung-uk Kim <jkim@niksun.com>
MFC after:	3 days
This commit is contained in:
Joerg Wunsch 2002-05-10 17:56:39 +00:00
parent d147c3da04
commit d0900d6bc0
4 changed files with 52 additions and 16 deletions

@ -563,13 +563,15 @@ enable_fifo(fdc_p fdc)
return fdc_err(fdc, "Enable FIFO failed\n");
/* If command is invalid, return */
j = 100000;
j = FDSTS_TIMEOUT;
while ((i = fdsts_rd(fdc) & (NE7_DIO | NE7_RQM))
!= NE7_RQM && j-- > 0)
!= NE7_RQM && j-- > 0) {
if (i == (NE7_DIO | NE7_RQM)) {
fdc_reset(fdc);
return FD_FAILED;
}
DELAY(1);
}
if (j<0 ||
fd_cmd(fdc, 3,
0, (fifo_threshold - 1) & 0xf, 0, 0) < 0) {
@ -1473,11 +1475,13 @@ fdc_reset(fdc_p fdc)
static int
fd_in(struct fdc_data *fdc, int *ptr)
{
int i, j = 100000;
int i, j = FDSTS_TIMEOUT;
while ((i = fdsts_rd(fdc) & (NE7_DIO|NE7_RQM))
!= (NE7_DIO|NE7_RQM) && j-- > 0)
!= (NE7_DIO|NE7_RQM) && j-- > 0) {
if (i == NE7_RQM)
return fdc_err(fdc, "ready for output in input\n");
DELAY(1);
}
if (j <= 0)
return fdc_err(fdc, bootverbose? "input ready timeout\n": 0);
#ifdef FDC_DEBUG
@ -1499,13 +1503,15 @@ out_fdc(struct fdc_data *fdc, int x)
int i;
/* Check that the direction bit is set */
i = 100000;
while ((fdsts_rd(fdc) & NE7_DIO) && i-- > 0);
i = FDSTS_TIMEOUT;
while ((fdsts_rd(fdc) & NE7_DIO) && i-- > 0)
DELAY(1);
if (i <= 0) return fdc_err(fdc, "direction bit not set\n");
/* Check that the floppy controller is ready for a command */
i = 100000;
while ((fdsts_rd(fdc) & NE7_RQM) == 0 && i-- > 0);
i = FDSTS_TIMEOUT;
while ((fdsts_rd(fdc) & NE7_RQM) == 0 && i-- > 0)
DELAY(1);
if (i <= 0)
return fdc_err(fdc, bootverbose? "output ready timeout\n": 0);

@ -69,3 +69,15 @@
#define FDI_DCHG 0x80 /* diskette has been changed */
/* requires drive and motor being selected */
/* is cleared by any step pulse to drive */
/*
* Timeout value for the PIO loops to wait until the FDC main status
* register matches our expextations (request for master, direction
* bit). This is the number of cycles to loop while waiting, with a
* 1-microsecond (in theory) DELAY() in each cycle. In particular on
* slower hardware, it could take a fair amount more to execute. Of
* course, as soon as the FDC main status register indicates the correct
* bits are set, the loop will terminate, so this is merely a safety
* measure to avoid looping forever in case of broken hardware.
*/
#define FDSTS_TIMEOUT 200

@ -563,13 +563,15 @@ enable_fifo(fdc_p fdc)
return fdc_err(fdc, "Enable FIFO failed\n");
/* If command is invalid, return */
j = 100000;
j = FDSTS_TIMEOUT;
while ((i = fdsts_rd(fdc) & (NE7_DIO | NE7_RQM))
!= NE7_RQM && j-- > 0)
!= NE7_RQM && j-- > 0) {
if (i == (NE7_DIO | NE7_RQM)) {
fdc_reset(fdc);
return FD_FAILED;
}
DELAY(1);
}
if (j<0 ||
fd_cmd(fdc, 3,
0, (fifo_threshold - 1) & 0xf, 0, 0) < 0) {
@ -1473,11 +1475,13 @@ fdc_reset(fdc_p fdc)
static int
fd_in(struct fdc_data *fdc, int *ptr)
{
int i, j = 100000;
int i, j = FDSTS_TIMEOUT;
while ((i = fdsts_rd(fdc) & (NE7_DIO|NE7_RQM))
!= (NE7_DIO|NE7_RQM) && j-- > 0)
!= (NE7_DIO|NE7_RQM) && j-- > 0) {
if (i == NE7_RQM)
return fdc_err(fdc, "ready for output in input\n");
DELAY(1);
}
if (j <= 0)
return fdc_err(fdc, bootverbose? "input ready timeout\n": 0);
#ifdef FDC_DEBUG
@ -1499,13 +1503,15 @@ out_fdc(struct fdc_data *fdc, int x)
int i;
/* Check that the direction bit is set */
i = 100000;
while ((fdsts_rd(fdc) & NE7_DIO) && i-- > 0);
i = FDSTS_TIMEOUT;
while ((fdsts_rd(fdc) & NE7_DIO) && i-- > 0)
DELAY(1);
if (i <= 0) return fdc_err(fdc, "direction bit not set\n");
/* Check that the floppy controller is ready for a command */
i = 100000;
while ((fdsts_rd(fdc) & NE7_RQM) == 0 && i-- > 0);
i = FDSTS_TIMEOUT;
while ((fdsts_rd(fdc) & NE7_RQM) == 0 && i-- > 0)
DELAY(1);
if (i <= 0)
return fdc_err(fdc, bootverbose? "output ready timeout\n": 0);

@ -69,3 +69,15 @@
#define FDI_DCHG 0x80 /* diskette has been changed */
/* requires drive and motor being selected */
/* is cleared by any step pulse to drive */
/*
* Timeout value for the PIO loops to wait until the FDC main status
* register matches our expextations (request for master, direction
* bit). This is the number of cycles to loop while waiting, with a
* 1-microsecond (in theory) DELAY() in each cycle. In particular on
* slower hardware, it could take a fair amount more to execute. Of
* course, as soon as the FDC main status register indicates the correct
* bits are set, the loop will terminate, so this is merely a safety
* measure to avoid looping forever in case of broken hardware.
*/
#define FDSTS_TIMEOUT 200