From owner-svn-src-all@FreeBSD.ORG Thu Mar 19 15:46:34 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 0225110656E9; Thu, 19 Mar 2009 15:46:34 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id D93588FC16; Thu, 19 Mar 2009 15:46:33 +0000 (UTC) (envelope-from jhb@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n2JFkXm7067441; Thu, 19 Mar 2009 15:46:33 GMT (envelope-from jhb@svn.freebsd.org) Received: (from jhb@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n2JFkXBa067438; Thu, 19 Mar 2009 15:46:33 GMT (envelope-from jhb@svn.freebsd.org) Message-Id: <200903191546.n2JFkXBa067438@svn.freebsd.org> From: John Baldwin Date: Thu, 19 Mar 2009 15:46:33 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-6@freebsd.org X-SVN-Group: stable-6 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r190073 - in stable/6/sys: . boot/i386/libi386 contrib/pf dev/cxgb X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 19 Mar 2009 15:46:35 -0000 Author: jhb Date: Thu Mar 19 15:46:33 2009 New Revision: 190073 URL: http://svn.freebsd.org/changeset/base/190073 Log: MFC: 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/i386/libi386/bioscd.c stable/6/sys/boot/i386/libi386/biosdisk.c stable/6/sys/boot/i386/libi386/libi386.h stable/6/sys/contrib/pf/ (props changed) stable/6/sys/dev/cxgb/ (props changed) Modified: stable/6/sys/boot/i386/libi386/bioscd.c ============================================================================== --- stable/6/sys/boot/i386/libi386/bioscd.c Thu Mar 19 15:45:43 2009 (r190072) +++ stable/6/sys/boot/i386/libi386/bioscd.c Thu Mar 19 15:46:33 2009 (r190073) @@ -173,9 +173,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); @@ -235,7 +235,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; @@ -244,9 +244,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); } @@ -257,11 +257,15 @@ 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; + static struct edd_packet packet; int biosdev; #ifdef DISK_DEBUG int error; @@ -275,47 +279,77 @@ 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 = 0x13; + v86.eax = 0; + v86.edx = biosdev; + v86int(); + } + + packet.len = 0x10; + packet.count = x; + packet.offset = VTOPOFF(xp); + packet.seg = VTOPSEG(xp); + packet.lba = dblk; v86.ctl = V86_FLAGS; v86.addr = 0x13; - v86.eax = 0; + v86.eax = 0x4200; v86.edx = biosdev; + v86.ds = VTOPSEG(&packet); + v86.esi = VTOPOFF(&packet); v86int(); + result = (v86.efl & PSL_C); + if (result == 0) + break; } - - packet[0] = 0x10; - packet[1] = blks; - packet[2] = VTOPOFF(dest); - packet[3] = VTOPSEG(dest); - packet[4] = dblk & 0xffff; - packet[5] = dblk >> 16; - packet[6] = 0; - packet[7] = 0; - v86.ctl = V86_FLAGS; - v86.addr = 0x13; - v86.eax = 0x4200; - v86.edx = biosdev; - v86.ds = VTOPSEG(packet); - v86.esi = VTOPOFF(packet); - 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); Modified: stable/6/sys/boot/i386/libi386/biosdisk.c ============================================================================== --- stable/6/sys/boot/i386/libi386/biosdisk.c Thu Mar 19 15:45:43 2009 (r190072) +++ stable/6/sys/boot/i386/libi386/biosdisk.c Thu Mar 19 15:46:33 2009 (r190073) @@ -1105,14 +1105,6 @@ bd_realstrategy(void *devdata, int rw, d /* Max number of sectors to bounce-buffer if the request crosses a 64k boundary */ #define FLOPPY_BOUNCEBUF 18 -struct edd_packet { - uint16_t len; - uint16_t count; - uint16_t offset; - uint16_t seg; - uint64_t lba; -}; - static int bd_edd_io(struct open_disk *od, daddr_t dblk, int blks, caddr_t dest, int write) { Modified: stable/6/sys/boot/i386/libi386/libi386.h ============================================================================== --- stable/6/sys/boot/i386/libi386/libi386.h Thu Mar 19 15:45:43 2009 (r190072) +++ stable/6/sys/boot/i386/libi386/libi386.h Thu Mar 19 15:46:33 2009 (r190073) @@ -57,6 +57,14 @@ struct i386_devdesc } d_kind; }; +struct edd_packet { + uint16_t len; + uint16_t count; + uint16_t offset; + uint16_t seg; + uint64_t lba; +}; + int i386_getdev(void **vdev, const char *devspec, const char **path); char *i386_fmtdev(void *vdev); int i386_setcurrdev(struct env_var *ev, int flags, const void *value);