-/* $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 $ */
/*
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);
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
-/* $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 $ */
/*
* 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";