diff options
| -rw-r--r-- | sys/boot/i386/libi386/Makefile | 4 | ||||
| -rw-r--r-- | sys/boot/i386/libi386/biosdisk.c | 90 | ||||
| -rw-r--r-- | sys/boot/i386/libi386/devicename.c | 4 |
3 files changed, 76 insertions, 22 deletions
diff --git a/sys/boot/i386/libi386/Makefile b/sys/boot/i386/libi386/Makefile index 4a4d0a22b0f3..ba104c93b12d 100644 --- a/sys/boot/i386/libi386/Makefile +++ b/sys/boot/i386/libi386/Makefile @@ -1,4 +1,4 @@ -# $Id: Makefile,v 1.3 1998/09/17 23:52:07 msmith Exp $ +# $Id: Makefile,v 1.4 1998/09/18 02:02:33 msmith Exp $ # LIB= i386 NOPIC= @@ -10,6 +10,6 @@ SRCS= aout_freebsd.c biosdisk.c biosmem.c bootinfo.c comconsole.c \ CFLAGS+= -I${.CURDIR}/../../common -I${.CURDIR}/../btx/lib # Make the disk code more talkative -CFLAGS+= -DDISK_DEBUG +#CFLAGS+= -DDISK_DEBUG .include <bsd.lib.mk> diff --git a/sys/boot/i386/libi386/biosdisk.c b/sys/boot/i386/libi386/biosdisk.c index 35d62fe8cc8c..e840506b8f8c 100644 --- a/sys/boot/i386/libi386/biosdisk.c +++ b/sys/boot/i386/libi386/biosdisk.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: biosdisk.c,v 1.4 1998/09/18 02:02:33 msmith Exp $ + * $Id: biosdisk.c,v 1.5 1998/09/19 01:33:29 msmith Exp $ */ /* @@ -397,16 +397,42 @@ bd_strategy(void *devdata, int rw, daddr_t dblk, size_t size, void *buf, size_t return (0); } +/* Max number of sectors to bounce-buffer if the request crosses a 64k boundary */ +#define FLOPPY_BOUNCEBUF 18 + static int bd_read(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest) { - int x, bpc, cyl, hd, sec, result, resid, cnt; - caddr_t p; + int x, bpc, cyl, hd, sec, result, resid, cnt, retry, maxfer; + caddr_t p, xp, bbuf, breg; bpc = (od->od_sec * od->od_hds); /* blocks per cylinder */ resid = blks; p = dest; + /* Decide whether we have to bounce */ + if ((od->od_unit < 0x80) && + ((VTOP(dest) >> 16) != (VTOP(dest + blks * BIOSDISK_SECSIZE) >> 16))) { + + /* + * There is a 64k physical boundary somewhere in the destination buffer, so we have + * to arrange a suitable bounce buffer. Allocate a buffer twice as large as we + * need to. Use the bottom half unless there is a break there, in which case we + * use the top half. + */ + x = min(FLOPPY_BOUNCEBUF, blks); + bbuf = malloc(x * 2 * BIOSDISK_SECSIZE); + if (((u_int32_t)VTOP(bbuf) & 0xffff0000) == ((u_int32_t)VTOP(dest + x * BIOSDISK_SECSIZE) & 0xffff0000)) { + breg = bbuf; + } else { + breg = bbuf + x * BIOSDISK_SECSIZE; + } + maxfer = x; /* limit transfers to bounce region size */ + } else { + bbuf = NULL; + maxfer = 0; + } + while (resid > 0) { x = dblk; cyl = x / bpc; /* block # / blocks per cylinder */ @@ -414,32 +440,60 @@ bd_read(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest) hd = x / od->od_sec; /* offset / blocks per track */ sec = x % od->od_sec; /* offset into track */ - /* play it safe and don't cross track boundaries */ - x = min (od->od_sec - sec, resid); + /* play it safe and don't cross track boundaries (XXX this is probably unnecessary) */ + x = min(od->od_sec - sec, resid); + if (maxfer > 0) + x = min(x, maxfer); /* fit bounce buffer */ + + /* where do we transfer to? */ + xp = bbuf == NULL ? p : breg; /* correct sector number for 1-based BIOS numbering */ sec++; - /* build request XXX support EDD requests too */ - v86.ctl = V86_FLAGS; - v86.addr = 0x13; - v86.eax = 0x200 | x; - v86.ecx = ((cyl & 0xff) << 8) | ((cyl & 0x300) >> 2) | sec; - v86.edx = (hd << 8) | od->od_unit; - v86.es = VTOPSEG(p); - v86.ebx = VTOPOFF(p); - v86int(); - result = (v86.efl & 0x1); - DEBUG("%d sectors from %d/%d/%d %s", x, cyl, hd, sec - 1, result ? "failed" : "ok"); - if (result) - return(-1); + /* Loop retrying the operation a couple of times. The BIOS may also retry. */ + for (retry = 0; retry < 3; retry++) { + /* if retrying, reset the drive */ + if (retry > 0) { + v86.ctl = V86_FLAGS; + v86.addr = 0x13; + v86.eax = 0; + v86.edx = od->od_unit; + v86int(); + } + + /* build request XXX support EDD requests too */ + v86.ctl = V86_FLAGS; + v86.addr = 0x13; + v86.eax = 0x200 | x; + v86.ecx = ((cyl & 0xff) << 8) | ((cyl & 0x300) >> 2) | sec; + v86.edx = (hd << 8) | od->od_unit; + v86.es = VTOPSEG(xp); + v86.ebx = VTOPOFF(xp); + v86int(); + result = (v86.efl & 0x1); + if (result == 0) + break; + } + DEBUG("%d sectors from %d/%d/%d to %p (0x%x) %s", x, cyl, hd, sec - 1, p, VTOP(p), result ? "failed" : "ok"); + DEBUG("ax = 0x%04x cx = 0x%04x dx = 0x%04x status 0x%x\n", + 0x200 | x, ((cyl & 0xff) << 8) | ((cyl & 0x300) >> 2) | sec, (hd << 8) | od->od_unit, (v86.eax >> 8) & 0xff); + if (result) { + if (bbuf != NULL) + free(bbuf); + return(-1); + } + if (bbuf != NULL) + bcopy(breg, p, x * BIOSDISK_SECSIZE); p += (x * BIOSDISK_SECSIZE); dblk += x; resid -= x; } /* hexdump(dest, (blks * BIOSDISK_SECSIZE)); */ + if (bbuf != NULL) + free(bbuf); return(0); } diff --git a/sys/boot/i386/libi386/devicename.c b/sys/boot/i386/libi386/devicename.c index 043589fca153..c0ef279169f3 100644 --- a/sys/boot/i386/libi386/devicename.c +++ b/sys/boot/i386/libi386/devicename.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: devicename.c,v 1.1.1.1 1998/08/21 03:17:41 msmith Exp $ */ #include <stand.h> @@ -224,7 +224,7 @@ i386_setcurrdev(struct env_var *ev, int flags, void *value) { struct i386_devdesc *ncurr; int rv; - + if ((rv = i386_parsedev(&ncurr, value, NULL)) != 0) return(rv); free(ncurr); |
