summaryrefslogtreecommitdiff
path: root/sys/arch
diff options
context:
space:
mode:
authorMiod Vallat <miod@cvs.openbsd.org>2015-01-11 18:10:34 +0000
committerMiod Vallat <miod@cvs.openbsd.org>2015-01-11 18:10:34 +0000
commitf3167e09033f8074df4ab7b56643b3336681f54d (patch)
treee4d72ea08e018cec987e2273d68fd6738b221fa7 /sys/arch
parentdcb4f5f22ee0a34c139e1ad86ccb949d15e56214 (diff)
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.
Diffstat (limited to 'sys/arch')
-rw-r--r--sys/arch/sparc/stand/common/promdev.c61
-rw-r--r--sys/arch/sparc/stand/common/version.c5
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";