summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorthorpej <thorpej@NetBSD.org>1998-01-29 00:59:33 +0000
committerthorpej <thorpej@NetBSD.org>1998-01-29 00:59:33 +0000
commita7bc6bd92c7cbb6506665cd93aee45ca5d3597ef (patch)
treebca009720a8d745bf28049a095dc838673aa20bb /sys/dev
parent99139bc35a23b9724f1bb2c1d8e8cc9d199860c3 (diff)
In the NE2000 case, if we encounter an unaligned mbuf, copy it to an
aligned buffer so that we can do 16-bit PIO to the device without causing an unaligned access fault.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/ne2000.c25
1 files changed, 23 insertions, 2 deletions
diff --git a/sys/dev/ic/ne2000.c b/sys/dev/ic/ne2000.c
index 30f8b63bb1c..791c8a5290d 100644
--- a/sys/dev/ic/ne2000.c
+++ b/sys/dev/ic/ne2000.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ne2000.c,v 1.8 1998/01/26 20:30:09 thorpej Exp $ */
+/* $NetBSD: ne2000.c,v 1.9 1998/01/29 00:59:33 thorpej Exp $ */
/*-
* Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
@@ -449,7 +449,7 @@ ne2000_write_mbuf(sc, m, buf)
}
} else {
/* NE2000s are a bit trickier. */
- u_int8_t *data, savebyte[2];
+ u_int8_t *data, *aligndata, savebyte[2];
int l, wantbyte;
wantbyte = 0;
@@ -458,6 +458,8 @@ ne2000_write_mbuf(sc, m, buf)
if (l == 0)
continue;
data = mtod(m, u_int8_t *);
+ aligndata = NULL;
+
/* Finish the last word. */
if (wantbyte) {
savebyte[1] = *data;
@@ -467,6 +469,22 @@ ne2000_write_mbuf(sc, m, buf)
l--;
wantbyte = 0;
}
+
+ /*
+ * If the previous mbuf was odd length, the
+ * above check will have misaligned the rest
+ * of the current mbuf. If this is the case,
+ * we need to use a temporary buffer.
+ */
+ if (ALIGNED_POINTER(data, u_int16_t) == 0) {
+ aligndata = malloc(l, M_DEVBUF, M_NOWAIT);
+ if (aligndata == NULL)
+ panic("ne2000_write_mbuf: can't get "
+ "temporary buffer"); /* XXX */
+ bcopy(data, aligndata, l);
+ data = aligndata;
+ }
+
/* Output contiguous words. */
if (l > 1) {
bus_space_write_multi_2(asict, asich,
@@ -479,6 +497,9 @@ ne2000_write_mbuf(sc, m, buf)
savebyte[0] = *data;
wantbyte = 1;
}
+
+ if (aligndata != NULL)
+ free(aligndata, M_DEVBUF);
}
if (wantbyte) {