From 7728d9f88b787fcc77633927a90abdf41ba89497 Mon Sep 17 00:00:00 2001 From: miod Date: Sun, 11 Jan 2015 18:10:33 +0000 Subject: [PATCH] When using sun4 PROM I/O routines, make sure we never attempt to transfer more than the maximum DMA transfer size the PROM reports. Crank version to 2.9. --- sys/arch/sparc/stand/common/promdev.c | 61 ++++++++++++++++++++------- sys/arch/sparc/stand/common/version.c | 5 ++- 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/sys/arch/sparc/stand/common/promdev.c b/sys/arch/sparc/stand/common/promdev.c index 34bbda28e4a..afe89c90356 100644 --- a/sys/arch/sparc/stand/common/promdev.c +++ b/sys/arch/sparc/stand/common/promdev.c @@ -1,4 +1,4 @@ -/* $OpenBSD: promdev.c,v 1.16 2015/01/11 15:29:03 miod Exp $ */ +/* $OpenBSD: promdev.c,v 1.17 2015/01/11 18:10:33 miod Exp $ */ /* $NetBSD: promdev.c,v 1.16 1995/11/14 15:04:01 pk Exp $ */ /* @@ -221,12 +221,15 @@ prom0_strategy(devdata, flag, dblk, size, buf, rsize) struct promdata *pd = devdata; struct saioreq *si; struct om_boottable *ops; - char *dmabuf; - int si_flag; - size_t xcnt; + struct devinfo *dip; + char *dmabuf; + int si_flag; + size_t xcnt, total, chunk; + int rc = 0; si = pd->si; ops = si->si_boottab; + dip = ops->b_devinfo; #ifdef DEBUG_PROM printf("prom_strategy: size=%d dblk=%d\n", size, dblk); @@ -234,23 +237,51 @@ prom0_strategy(devdata, flag, dblk, size, buf, rsize) dmabuf = dvma_mapin(buf, size); - si->si_bn = dblk; - si->si_ma = dmabuf; - si->si_cc = size; + /* + * Clamp I/O to the maximum DMA transfer size supported by the PROM, + * if necessary. Note that we need to round down to a block boundary + * as the value is not necessarily a power of two (8216 has been + * seen with PROM rev 1.3.) + */ + if (dip->d_dmabytes != 0) + chunk = dbtob(btodb(dip->d_dmabytes)); + else + chunk = size; + + total = 0; + while (size != 0) { + if (size < chunk) + chunk = size; - si_flag = (flag == F_READ) ? SAIO_F_READ : SAIO_F_WRITE; - xcnt = (*ops->b_strategy)(si, si_flag); - dvma_mapout(dmabuf, size); + si->si_bn = dblk; + si->si_ma = dmabuf; + si->si_cc = chunk; + + si_flag = (flag == F_READ) ? SAIO_F_READ : SAIO_F_WRITE; + xcnt = (*ops->b_strategy)(si, si_flag); #ifdef DEBUG_PROM - printf("disk_strategy: xcnt = %x\n", xcnt); + printf("disk_strategy: xcnt = %x\n", xcnt); #endif - if (xcnt <= 0) - return (EIO); + if (xcnt <= 0) { + rc = EIO; + break; + } - *rsize = xcnt; - return (0); + total += xcnt; + if (xcnt != chunk) + break; + + size -= chunk; + dmabuf += chunk; + dblk += btodb(chunk); + } + + dvma_mapout(dmabuf, size); + + *rsize = total; + return rc; } int diff --git a/sys/arch/sparc/stand/common/version.c b/sys/arch/sparc/stand/common/version.c index 565b5789bc3..177a2d3c4a9 100644 --- a/sys/arch/sparc/stand/common/version.c +++ b/sys/arch/sparc/stand/common/version.c @@ -1,4 +1,4 @@ -/* $OpenBSD: version.c,v 1.9 2014/03/30 19:48:04 miod Exp $ */ +/* $OpenBSD: version.c,v 1.10 2015/01/11 18:10:33 miod Exp $ */ /* $NetBSD: version.c,v 1.4 1995/09/16 23:20:39 pk Exp $ */ /* @@ -49,6 +49,7 @@ * stomping on PROM data below 4MB on sun4c * 2.7 /etc/random.seed support * 2.8 Fix network boot broken on some PROM by the 2.7 changes + * 2.9 Cope with DMA transfer size limits of old sun4 PROMs */ -char *version = "2.8"; +char *version = "2.9"; -- 2.20.1