From a2642c4d671663ccebc3574cebde8efbfa324ba1 Mon Sep 17 00:00:00 2001 From: Joerg Wunsch Date: Tue, 14 May 2002 21:28:45 +0000 Subject: [PATCH] After some comments from bde, rewrite the loops to avoid turning the previously used "micro-optimization" (count-down loop) into a pessimization. Now the loops are written in the more natural count-up form. Also, while being there, i made the logic in out_fdc() similar to the logic in in_fdc(). The old implementation was a bit bogus anyway since it first tested the DIO bit and only afterwards the RQM bit. However, according to the description of the i82077, the DIO bit is only guaranteed to be valid once the RQM bit is set. Thus, the old implementatoin would have had the chance to misbehave on a controller that is implemented in accordance with the i82077 description (but is not bug-for-bug compatible). MFC after: 3 days --- sys/dev/fdc/fdc.c | 70 +++++++++++++++++++---------------------------- sys/isa/fd.c | 70 +++++++++++++++++++---------------------------- 2 files changed, 56 insertions(+), 84 deletions(-) diff --git a/sys/dev/fdc/fdc.c b/sys/dev/fdc/fdc.c index 60fff67f0e9a..5edc407b337f 100644 --- a/sys/dev/fdc/fdc.c +++ b/sys/dev/fdc/fdc.c @@ -1482,26 +1482,29 @@ fdc_reset(fdc_p fdc) /* * FDC IO functions, take care of the main status register, timeout * in case the desired status bits are never set. + * + * These PIO loops initially start out with short delays between + * each iteration in the expectation that the required condition + * is usually met quickly, so it can be handled immediately. After + * about 1 ms, stepping is increased to achieve a better timing + * accuracy in the calls to DELAY(). */ static int fd_in(struct fdc_data *fdc, int *ptr) { - int i, j = FDSTS_TIMEOUT; - while ((i = fdsts_rd(fdc) & (NE7_DIO|NE7_RQM)) - != (NE7_DIO|NE7_RQM) && j-- > 0) { + int i, j, step; + + for (j = 0, step = 1; + (i = fdsts_rd(fdc) & (NE7_DIO|NE7_RQM)) != (NE7_DIO|NE7_RQM) && + j < FDSTS_TIMEOUT; + j += step) { if (i == NE7_RQM) return (fdc_err(fdc, "ready for output in input\n")); - /* - * After (maybe) 1 msec of waiting, back off to larger - * stepping to get the timing more accurate. - */ - if (FDSTS_TIMEOUT - j > 1000) { - DELAY(1000); - j -= 999; - } else - DELAY(1); + if (j == 1000) + step = 1000; + DELAY(step); } - if (j <= 0) + if (j >= FDSTS_TIMEOUT) return (fdc_err(fdc, bootverbose? "input ready timeout\n": 0)); #ifdef FDC_DEBUG i = fddata_rd(fdc); @@ -1519,36 +1522,19 @@ fd_in(struct fdc_data *fdc, int *ptr) int out_fdc(struct fdc_data *fdc, int x) { - int i; + int i, j, step; - /* Check that the direction bit is set */ - i = FDSTS_TIMEOUT; - while ((fdsts_rd(fdc) & NE7_DIO) && i-- > 0) - /* - * After (maybe) 1 msec of waiting, back off to larger - * stepping to get the timing more accurate. - */ - if (FDSTS_TIMEOUT - i > 1000) { - DELAY(1000); - i -= 999; - } else - 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 = FDSTS_TIMEOUT; - while ((fdsts_rd(fdc) & NE7_RQM) == 0 && i-- > 0) - /* - * After (maybe) 1 msec of waiting, back off to larger - * stepping to get the timing more accurate. - */ - if (FDSTS_TIMEOUT - i > 1000) { - DELAY(1000); - i -= 999; - } else - DELAY(1); - if (i <= 0) + for (j = 0, step = 1; + (i = fdsts_rd(fdc) & (NE7_DIO|NE7_RQM)) != NE7_RQM && + j < FDSTS_TIMEOUT; + j += step) { + if (i == (NE7_DIO|NE7_RQM)) + return (fdc_err(fdc, "ready for input in output\n")); + if (j == 1000) + step = 1000; + DELAY(step); + } + if (j >= FDSTS_TIMEOUT) return (fdc_err(fdc, bootverbose? "output ready timeout\n": 0)); /* Send the command and return */ diff --git a/sys/isa/fd.c b/sys/isa/fd.c index 60fff67f0e9a..5edc407b337f 100644 --- a/sys/isa/fd.c +++ b/sys/isa/fd.c @@ -1482,26 +1482,29 @@ fdc_reset(fdc_p fdc) /* * FDC IO functions, take care of the main status register, timeout * in case the desired status bits are never set. + * + * These PIO loops initially start out with short delays between + * each iteration in the expectation that the required condition + * is usually met quickly, so it can be handled immediately. After + * about 1 ms, stepping is increased to achieve a better timing + * accuracy in the calls to DELAY(). */ static int fd_in(struct fdc_data *fdc, int *ptr) { - int i, j = FDSTS_TIMEOUT; - while ((i = fdsts_rd(fdc) & (NE7_DIO|NE7_RQM)) - != (NE7_DIO|NE7_RQM) && j-- > 0) { + int i, j, step; + + for (j = 0, step = 1; + (i = fdsts_rd(fdc) & (NE7_DIO|NE7_RQM)) != (NE7_DIO|NE7_RQM) && + j < FDSTS_TIMEOUT; + j += step) { if (i == NE7_RQM) return (fdc_err(fdc, "ready for output in input\n")); - /* - * After (maybe) 1 msec of waiting, back off to larger - * stepping to get the timing more accurate. - */ - if (FDSTS_TIMEOUT - j > 1000) { - DELAY(1000); - j -= 999; - } else - DELAY(1); + if (j == 1000) + step = 1000; + DELAY(step); } - if (j <= 0) + if (j >= FDSTS_TIMEOUT) return (fdc_err(fdc, bootverbose? "input ready timeout\n": 0)); #ifdef FDC_DEBUG i = fddata_rd(fdc); @@ -1519,36 +1522,19 @@ fd_in(struct fdc_data *fdc, int *ptr) int out_fdc(struct fdc_data *fdc, int x) { - int i; + int i, j, step; - /* Check that the direction bit is set */ - i = FDSTS_TIMEOUT; - while ((fdsts_rd(fdc) & NE7_DIO) && i-- > 0) - /* - * After (maybe) 1 msec of waiting, back off to larger - * stepping to get the timing more accurate. - */ - if (FDSTS_TIMEOUT - i > 1000) { - DELAY(1000); - i -= 999; - } else - 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 = FDSTS_TIMEOUT; - while ((fdsts_rd(fdc) & NE7_RQM) == 0 && i-- > 0) - /* - * After (maybe) 1 msec of waiting, back off to larger - * stepping to get the timing more accurate. - */ - if (FDSTS_TIMEOUT - i > 1000) { - DELAY(1000); - i -= 999; - } else - DELAY(1); - if (i <= 0) + for (j = 0, step = 1; + (i = fdsts_rd(fdc) & (NE7_DIO|NE7_RQM)) != NE7_RQM && + j < FDSTS_TIMEOUT; + j += step) { + if (i == (NE7_DIO|NE7_RQM)) + return (fdc_err(fdc, "ready for input in output\n")); + if (j == 1000) + step = 1000; + DELAY(step); + } + if (j >= FDSTS_TIMEOUT) return (fdc_err(fdc, bootverbose? "output ready timeout\n": 0)); /* Send the command and return */