diff options
author | Michael Shalayeff <mickey@cvs.openbsd.org> | 1997-04-15 06:25:19 +0000 |
---|---|---|
committer | Michael Shalayeff <mickey@cvs.openbsd.org> | 1997-04-15 06:25:19 +0000 |
commit | eb2063a11dd96d611a925e45d8e1c06eb1b8e290 (patch) | |
tree | 81d4fc45ad1dd6f0f4cc8a4ee04469b14f60e5ca /sys/arch/i386/stand/libsa/biosdev.c | |
parent | 5424050ea1a8211aec2f6e8859e71771545371c5 (diff) |
do bounce-buffering to avoid DMA overrun
somebody, test it!
Diffstat (limited to 'sys/arch/i386/stand/libsa/biosdev.c')
-rw-r--r-- | sys/arch/i386/stand/libsa/biosdev.c | 51 |
1 files changed, 37 insertions, 14 deletions
diff --git a/sys/arch/i386/stand/libsa/biosdev.c b/sys/arch/i386/stand/libsa/biosdev.c index 3c40b8ef344..a73ffd9ead4 100644 --- a/sys/arch/i386/stand/libsa/biosdev.c +++ b/sys/arch/i386/stand/libsa/biosdev.c @@ -1,4 +1,4 @@ -/* $OpenBSD: biosdev.c,v 1.5 1997/04/09 08:39:15 mickey Exp $ */ +/* $OpenBSD: biosdev.c,v 1.6 1997/04/15 06:25:18 mickey Exp $ */ /* * Copyright (c) 1996 Michael Shalayeff @@ -279,7 +279,8 @@ biosstrategy(void *devdata, int rw, for (i = 0; error == 0 && i < nsect; i += n, blk += n, buf += n * DEV_BSIZE) { - register int cyl, hd, sect; + register int cyl, hd, sect, j; + void *bb; btochs(blk, cyl, hd, sect, BIOSNHEADS(bd->dinfo), BIOSNSECTS(bd->dinfo)); @@ -287,28 +288,50 @@ biosstrategy(void *devdata, int rw, n = BIOSNSECTS(bd->dinfo) - sect; else n = nsect - i; + + /* use a bounce buffer to not to cross 64k DMA boundary */ + if ((((u_int32_t)buf) & ~0xffff) != + (((u_int32_t)buf + n * DEV_BSIZE) & ~0xffff)) { + bb = alloc(n * DEV_BSIZE); + if (rw != F_READ) + bcopy (buf, bb, n * DEV_BSIZE); + } else + bb = buf; #ifdef BIOS_DEBUG if (debug) - printf(" (%d,%d,%d,%d)@%p", cyl, hd, sect, n, buf); + printf(" (%d,%d,%d,%d)@%p", cyl, hd, sect, n, bb); #endif - if (rw == F_READ) - error = biosread (bd->biosdev, cyl, hd, sect, n, buf); - else - error = bioswrite(bd->biosdev, cyl, hd, sect, n, buf); - - if (error != 0) { - for (p = bd_errors; p < &bd_errors[bd_nents] && - p->bd_id != error; p++); - - if (error == 0x11) /* ECC corrected */ + for (error = 1, j = 5; error && j--;) { + error = (rw == F_READ)? + biosread (bd->biosdev, cyl, hd, sect, n, bb) + : bioswrite(bd->biosdev, cyl, hd, sect, n, bb); + + switch (error) { + case 0x06: /* disk changed */ + printf ("disk changed\n"); + default: + continue; + + case 0x11: /* ECC corrected */ error = 0; + break; + } + } + + if (bb != buf) { + if (rw == F_READ) + bcopy (bb, buf, n * DEV_BSIZE); + free (bb, n * DEV_BSIZE); } } #ifdef BIOS_DEBUG if (debug) { - if (error != 0) + if (error != 0) { + for (p = bd_errors; p < &bd_errors[bd_nents] && + p->bd_id != error; p++); printf("=%x(%s)", p->bd_id, p->msg); + } putchar('\n'); } #endif |