Subject: kern/17193: mb86960 driver supports word more only
To: None <gnats-bugs@gnats.netbsd.org>
From: Christian Groessler <cpg@aladdin.de>
List: netbsd-bugs
Date: 06/08/2002 15:59:52
>Number: 17193
>Category: kern
>Synopsis: mb86960 driver supports word more only
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Sat Jun 08 07:01:01 PDT 2002
>Closed-Date:
>Last-Modified:
>Originator: Christian Groessler
>Release: NetBSD 1.6_BETA1
>Organization:
at home
>Environment:
System: NetBSD power.cnet.aladdin.de 1.6_BETA1 NetBSD 1.6_BETA1 (POWER) #0: Fri May 31 20:10:13 CEST 2002 chris@power.cnet.aladdin.de:/local/netbsdsrc-1.6/src/sys/arch/macppc/compile/POWER macppc
Architecture: powerpc
Machine: macppc
>Description:
The mb86960 driver supports only the word (16 bit) mode bus
interface of the chip. The upcoming Dreamcast LAN adapter driver needs
byte mode. I've attached a patch which implements this support.
There is still one unniceness in the mb86960_attach() function - it
always sets word size, maybe this should become a parameter to the
function. Currently it's no real problem, since there are only 2 byte
sized i/os made afterwards in this function.
>How-To-Repeat:
look at mb86960.c source code.
>Fix:
--- old/sys/dev/ic/mb86960.c Tue Nov 13 14:14:41 2001
+++ new/sys/dev/ic/mb86960.c Sat Jun 8 15:43:25 2002
@@ -222,7 +222,7 @@ mb86960_config(sc, media, nmedia, defmed
#if FE_SINGLE_TRANSMISSION
/* Override txb config to allocate minimum. */
- sc->proto_dlcr6 &= ~FE_D6_TXBSIZ
+ sc->proto_dlcr6 &= ~FE_D6_TXBSIZ;
sc->proto_dlcr6 |= FE_D6_TXBSIZ_2x2KB;
#endif
@@ -988,11 +988,15 @@ mb86960_rint(sc, rstat)
sc->sc_dev.dv_xname, sbuf);
#endif
ifp->if_ierrors++;
+#if FE_DEBUG >= 2
+ printf("rint: error (%02X)\n", rstat);
+#endif
+ return;
}
/*
* MB86960 has a flag indicating "receive queue empty."
- * We just loop cheking the flag to pull out all received
+ * We just loop checking the flag to pull out all received
* packets.
*
* We limit the number of iterrations to avoid infinite loop.
@@ -1011,7 +1015,14 @@ mb86960_rint(sc, rstat)
* use inw() to get the status byte. The significant
* value is returned in lower 8 bits.
*/
- status = (u_char)bus_space_read_2(bst, bsh, FE_BMPR8);
+
+ if ((sc->proto_dlcr6 & FE_D6_SBW) == FE_D6_SBW_BYTE) {
+ status = bus_space_read_1(bst, bsh, FE_BMPR8);
+ (void) bus_space_read_1(bst, bsh, FE_BMPR8);
+ }
+ else {
+ status = (u_char)bus_space_read_2(bst, bsh, FE_BMPR8);
+ }
#if FE_DEBUG >= 4
log(LOG_INFO, "%s: receive status = %02x\n",
sc->sc_dev.dv_xname, status);
@@ -1035,7 +1046,13 @@ mb86960_rint(sc, rstat)
* It is a sum of a header (14 bytes) and a payload.
* CRC has been stripped off by the 86960.
*/
- len = bus_space_read_2(bst, bsh, FE_BMPR8);
+ if ((sc->proto_dlcr6 & FE_D6_SBW) == FE_D6_SBW_BYTE) {
+ len = bus_space_read_1(bst, bsh, FE_BMPR8);
+ len |= bus_space_read_1(bst, bsh, FE_BMPR8) << 8;
+ }
+ else {
+ len = (u_char)bus_space_read_2(bst, bsh, FE_BMPR8);
+ }
/*
* MB86965 checks the packet length and drop big packet
@@ -1126,8 +1143,6 @@ mb86960_intr(arg)
*/
tstat = bus_space_read_1(bst, bsh, FE_DLCR0) & FE_TMASK;
rstat = bus_space_read_1(bst, bsh, FE_DLCR1) & FE_RMASK;
- if (tstat == 0 && rstat == 0)
- return (0);
/*
* Loop until there are no more new interrupt conditions.
@@ -1374,8 +1389,13 @@ mb86960_get_packet(sc, len)
m->m_len = len;
/* Get a packet. */
- bus_space_read_multi_stream_2(bst, bsh, FE_BMPR8, mtod(m, u_int16_t *),
- (len + 1) >> 1);
+ if ((sc->proto_dlcr6 & FE_D6_SBW) == FE_D6_SBW_BYTE) {
+ bus_space_read_multi_stream_1(bst, bsh, FE_BMPR8, mtod(m, u_int8_t *), len);
+ }
+ else {
+ bus_space_read_multi_stream_2(bst, bsh, FE_BMPR8, mtod(m, u_int16_t *),
+ (len + 1) >> 1);
+ }
#if NBPFILTER > 0
/*
@@ -1426,11 +1446,21 @@ mb86960_write_mbufs(sc, m)
#if FE_DELAYED_PADDING
/* Do the "delayed padding." */
- len = sc->txb_padding >> 1;
- if (len > 0) {
- while (--len >= 0)
- bus_space_write_2(bst, bsh, FE_BMPR8, 0);
- sc->txb_padding = 0;
+ if ((sc->proto_dlcr6 & FE_D6_SBW) == FE_D6_SBW_BYTE) {
+ len = sc->txb_padding;
+ if (len > 0) {
+ while (--len >= 0)
+ bus_space_write_1(bst, bsh, FE_BMPR8, 0);
+ sc->txb_padding = 0;
+ }
+ }
+ else {
+ len = sc->txb_padding >> 1;
+ if (len > 0) {
+ while (--len >= 0)
+ bus_space_write_2(bst, bsh, FE_BMPR8, 0);
+ sc->txb_padding = 0;
+ }
}
#endif
@@ -1475,8 +1505,16 @@ mb86960_write_mbufs(sc, m)
* packet in the transmission buffer, we can skip the
* padding process. It may gain performance slightly. FIXME.
*/
- bus_space_write_2(bst, bsh, FE_BMPR8,
- max(totlen, (ETHER_MIN_LEN - ETHER_CRC_LEN)));
+ if ((sc->proto_dlcr6 & FE_D6_SBW) == FE_D6_SBW_BYTE) {
+ bus_space_write_1(bst, bsh, FE_BMPR8,
+ max(totlen, (ETHER_MIN_LEN - ETHER_CRC_LEN)));
+ bus_space_write_1(bst, bsh, FE_BMPR8,
+ max(totlen, (ETHER_MIN_LEN - ETHER_CRC_LEN)) >> 8);
+ }
+ else {
+ bus_space_write_2(bst, bsh, FE_BMPR8,
+ max(totlen, (ETHER_MIN_LEN - ETHER_CRC_LEN)));
+ }
/*
* Update buffer status now.
@@ -1495,9 +1533,9 @@ mb86960_write_mbufs(sc, m)
/*
* Transfer the data from mbuf chain to the transmission buffer.
- * MB86960 seems to require that data be transferred as words, and
- * only words. So that we require some extra code to patch
- * over odd-length mbufs.
+ * If the MB86960 is configured in word mode, data needs to be
+ * transferred as words, and only words. So that we require some
+ * extra code to patch over odd-length mbufs.
*/
wantbyte = 0;
for (; m != 0; m = m->m_next) {
@@ -1509,25 +1547,33 @@ mb86960_write_mbufs(sc, m)
/* Find the actual data to send. */
data = mtod(m, caddr_t);
- /* Finish the last byte. */
- if (wantbyte) {
- bus_space_write_2(bst, bsh, FE_BMPR8,
- savebyte | (*data << 8));
- data++;
- len--;
- wantbyte = 0;
- }
-
- /* Output contiguous words. */
- if (len > 1)
- bus_space_write_multi_stream_2(bst, bsh, FE_BMPR8,
- (u_int16_t *)data, len >> 1);
-
- /* Save remaining byte, if there is one. */
- if (len & 1) {
- data += len & ~1;
- savebyte = *data;
- wantbyte = 1;
+ if ((sc->proto_dlcr6 & FE_D6_SBW) == FE_D6_SBW_BYTE) {
+ bus_space_write_multi_stream_1(bst, bsh, FE_BMPR8,
+ (u_int8_t *)data, len);
+ if (len & 1)
+ bus_space_write_1(bst, bsh, FE_BMPR8, 0);
+ }
+ else {
+ /* Finish the last byte. */
+ if (wantbyte) {
+ bus_space_write_2(bst, bsh, FE_BMPR8,
+ savebyte | (*data << 8));
+ data++;
+ len--;
+ wantbyte = 0;
+ }
+
+ /* Output contiguous words. */
+ if (len > 1)
+ bus_space_write_multi_stream_2(bst, bsh, FE_BMPR8,
+ (u_int16_t *)data, len >> 1);
+
+ /* Save remaining byte, if there is one. */
+ if (len & 1) {
+ data += len & ~1;
+ savebyte = *data;
+ wantbyte = 1;
+ }
}
}
@@ -1539,9 +1585,16 @@ mb86960_write_mbufs(sc, m)
/*
* Pad the packet to the minimum length if necessary.
*/
- len = ((ETHER_MIN_LEN - ETHER_CRC_LEN) >> 1) - (totlen >> 1);
- while (--len >= 0)
- bus_space_write_2(bst, bsh, FE_BMPR8, 0);
+ if ((sc->proto_dlcr6 & FE_D6_SBW) == FE_D6_SBW_BYTE) {
+ len = (ETHER_MIN_LEN - ETHER_CRC_LEN) - totlen;
+ while (--len >= 0)
+ bus_space_write_1(bst, bsh, FE_BMPR8, 0);
+ }
+ else {
+ len = ((ETHER_MIN_LEN - ETHER_CRC_LEN) >> 1) - (totlen >> 1);
+ while (--len >= 0)
+ bus_space_write_2(bst, bsh, FE_BMPR8, 0);
+ }
#endif
}
@@ -1677,7 +1730,7 @@ mb86960_setmode(sc)
*
* Note that the DLC (Data Linc Control unit, i.e. transmitter
* and receiver) must be stopped when feeding the filter, and
- * DLC trushes all packets in both transmission and receive
+ * DLC trashes all packets in both transmission and receive
* buffers when stopped.
*
* ... Are the above sentenses correct? I have to check the
>Release-Note:
>Audit-Trail:
>Unformatted: