diff options
| author | thorpej <thorpej@NetBSD.org> | 1998-01-29 00:59:33 +0000 |
|---|---|---|
| committer | thorpej <thorpej@NetBSD.org> | 1998-01-29 00:59:33 +0000 |
| commit | a7bc6bd92c7cbb6506665cd93aee45ca5d3597ef (patch) | |
| tree | bca009720a8d745bf28049a095dc838673aa20bb /sys | |
| parent | 99139bc35a23b9724f1bb2c1d8e8cc9d199860c3 (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')
| -rw-r--r-- | sys/dev/ic/ne2000.c | 25 |
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) { |
