Date: Sun, 22 Mar 2009 11:07:13 +0000 (UTC) From: Takahashi Yoshihiro <nyan@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-6@freebsd.org Subject: svn commit: r190262 - in stable/6/sys: . boot/pc98/libpc98 contrib/pf dev/cxgb Message-ID: <200903221107.n2MB7DpS067146@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: nyan Date: Sun Mar 22 11:07:13 2009 New Revision: 190262 URL: http://svn.freebsd.org/changeset/base/190262 Log: MFC: r190146, r190147 Teach the BIOS CD driver to use bounce buffers when the destination address is > 1 MB. Modified: stable/6/sys/ (props changed) stable/6/sys/boot/pc98/libpc98/bioscd.c stable/6/sys/contrib/pf/ (props changed) stable/6/sys/dev/cxgb/ (props changed) Modified: stable/6/sys/boot/pc98/libpc98/bioscd.c ============================================================================== --- stable/6/sys/boot/pc98/libpc98/bioscd.c Sun Mar 22 11:03:24 2009 (r190261) +++ stable/6/sys/boot/pc98/libpc98/bioscd.c Sun Mar 22 11:07:13 2009 (r190262) @@ -170,9 +170,9 @@ bc_add(int biosdev) static void bc_print(int verbose) { - int i; char line[80]; - + int i; + for (i = 0; i < nbcinfo; i++) { sprintf(line, " cd%d: Device 0x%x\n", i, bcinfo[i].bc_sp.sp_devicespec); @@ -232,7 +232,7 @@ bc_strategy(void *devdata, int rw, daddr if (dblk % (BIOSCD_SECSIZE / DEV_BSIZE) != 0) return (EINVAL); dblk /= (BIOSCD_SECSIZE / DEV_BSIZE); - DEBUG("read %d from %d to %p", blks, dblk, buf); + DEBUG("read %d from %lld to %p", blks, dblk, buf); if (rsize) *rsize = 0; @@ -241,9 +241,9 @@ bc_strategy(void *devdata, int rw, daddr return (EIO); } #ifdef BD_SUPPORT_FRAGS - DEBUG("bc_strategy: frag read %d from %d+%d to %p", + DEBUG("frag read %d from %lld+%d to %p", fragsize, dblk, blks, buf + (blks * BIOSCD_SECSIZE)); - if (fragsize && bc_read(unit, dblk + blks, 1, fragsize)) { + if (fragsize && bc_read(unit, dblk + blks, 1, fragbuf)) { DEBUG("frag read error"); return(EIO); } @@ -254,11 +254,14 @@ bc_strategy(void *devdata, int rw, daddr return (0); } +/* Max number of sectors to bounce-buffer at a time. */ +#define CD_BOUNCEBUF 8 + static int bc_read(int unit, daddr_t dblk, int blks, caddr_t dest) { - u_int result, retry; - static unsigned short packet[8]; + u_int maxfer, resid, result, retry, x; + caddr_t bbuf, p, xp; int biosdev; #ifdef DISK_DEBUG int error; @@ -272,40 +275,73 @@ bc_read(int unit, daddr_t dblk, int blks if (blks == 0) return (0); + /* Decide whether we have to bounce */ + if (VTOP(dest) >> 20 != 0) { + /* + * The destination buffer is above first 1MB of + * physical memory so we have to arrange a suitable + * bounce buffer. + */ + x = min(CD_BOUNCEBUF, (unsigned)blks); + bbuf = alloca(x * BIOSCD_SECSIZE); + maxfer = x; + } else { + bbuf = NULL; + maxfer = 0; + } + biosdev = bc_unit2bios(unit); - /* - * 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) { + resid = blks; + p = dest; + + while (resid > 0) { + if (bbuf) + xp = bbuf; + else + xp = p; + x = resid; + if (maxfer > 0) + x = min(x, maxfer); + + /* + * 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 = 0x1b; + v86.eax = 0x0300 | biosdev; + v86int(); + } + v86.ctl = V86_FLAGS; v86.addr = 0x1b; - v86.eax = 0x0300 | biosdev; + v86.eax = 0x0600 | (biosdev & 0x7f); + v86.ebx = x * BIOSCD_SECSIZE; + v86.ecx = dblk & 0xffff; + v86.edx = (dblk >> 16) & 0xffff; + v86.ebp = VTOPOFF(xp); + v86.es = VTOPSEG(xp); v86int(); + result = (v86.efl & PSL_C); + if (result == 0) + break; } - - v86.ctl = V86_FLAGS; - v86.addr = 0x1b; - v86.eax = 0x0600 | (biosdev & 0x7f); - v86.ebx = blks * BIOSCD_SECSIZE; - v86.ecx = dblk & 0xffff; - v86.edx = (dblk >> 16) & 0xffff; - v86.ebp = VTOPOFF(dest); - v86.es = VTOPSEG(dest); - v86int(); - result = (v86.efl & PSL_C); - if (result == 0) - break; - } #ifdef DISK_DEBUG - error = (v86.eax >> 8) & 0xff; + error = (v86.eax >> 8) & 0xff; #endif - DEBUG("%d sectors from %ld to %p (0x%x) %s", blks, dblk, dest, - VTOP(dest), result ? "failed" : "ok"); - DEBUG("unit %d status 0x%x", unit, error); + DEBUG("%d sectors from %lld to %p (0x%x) %s", x, dblk, p, + VTOP(p), result ? "failed" : "ok"); + DEBUG("unit %d status 0x%x", unit, error); + if (bbuf != NULL) + bcopy(bbuf, p, x * BIOSCD_SECSIZE); + p += (x * BIOSCD_SECSIZE); + dblk += x; + resid -= x; + } /* hexdump(dest, (blks * BIOSCD_SECSIZE)); */ return(0);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200903221107.n2MB7DpS067146>