[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

please review the diff against SMC 91Cxx driver



こんばんは。

smc91c92を使っているmac68k用のNuBus NICのドライバーを書いた
のですが、fragmented packetをうまく組み立てることができない
ため、NFSが使えない状態です(netbsd,04650)。rloginなどは動き
ます。

私は上のカード以外にSMC 91Cxxのカードを持っていないため、原
因を切り分けることができません。どなたかMegahertzなどのカー
ドをお持ちの方、-currentに以下のパッチを当てて動くかどうか試
していただけないでしょうか。もちろん「ここが変だ」というので
も結構です。

やっていることは以下の通りです。

○NuBus NICではSMC91C92のレジスターが不連続なアドレスに割り
当てられているため、dp8390.cを参考にreg_map[]を通してアクセ
スするようにした

○mac68kはbig endianなので、レジスターのアクセスにle16toh()、
htole16()を使うようにした

○起動時にNICのROMからMAC addressを読み込んでレジスターに書
き込む機能を追加した

よろしくお願いします。

--
SUNAGAWA Keiki <kei_sun@ba2.so-net.ne.jp>
Hack on NetBSD, and your code runs on over 20 architectures!

Index: dev/ic/smc91cxx.c
===================================================================
RCS file: /a/rsync/netbsd.org/syssrc/sys/dev/ic/smc91cxx.c,v
retrieving revision 1.24
diff -u -r1.24 smc91cxx.c
--- smc91cxx.c	2000/02/04 04:05:50	1.24
+++ smc91cxx.c	2000/02/04 16:10:57
@@ -84,6 +84,7 @@
 #include "bpfilter.h"
 #include "rnd.h"
 
+#include <sys/endian.h>
 #include <sys/param.h> 
 #include <sys/systm.h>
 #include <sys/mbuf.h>
@@ -190,23 +191,22 @@
 }
 
 void
-smc91cxx_attach(sc, myea)
+smc91cxx_attach(sc)
 	struct smc91cxx_softc *sc;
-	u_int8_t *myea;
 {
 	struct ifnet *ifp = &sc->sc_ec.ec_if;
 	bus_space_tag_t bst = sc->sc_bst;
 	bus_space_handle_t bsh = sc->sc_bsh;
 	const char *idstr;
 	u_int16_t tmp;
-	u_int8_t enaddr[ETHER_ADDR_LEN];
 	int i, aui;
 
 	/* Make sure the chip is stopped. */
 	smc91cxx_stop(sc);
 
 	SMC_SELECT_BANK(sc, 3);
-	tmp = bus_space_read_2(bst, bsh, REVISION_REG_W);
+	tmp = le16toh(bus_space_read_2(bst, bsh,
+	    sc->sc_reg_map[REVISION_REG_W]));
 	/* check magic number */
 	if ((tmp & BSR_DETECT_MASK) != BSR_DETECT_VALUE) {
 		idstr = NULL;
@@ -220,21 +220,32 @@
 		printf("unknown chip id %d, ", RR_ID(tmp));
 	printf("revision %d\n", RR_REV(tmp));
 
-	/* Read the station address from the chip. */
+	/* setup MAC address */
 	SMC_SELECT_BANK(sc, 1);
-	if (myea == NULL) {
-		myea = enaddr;
+	if (sc->sc_enaddr_from_rom) {
+		/* Write the MAC address got from ROM to chip. */
+		for (i = 0; i < ETHER_ADDR_LEN; i+= 2) {
+			/* Might this be little endian? */
+			tmp = sc->sc_enaddr[i] << 8 | sc->sc_enaddr[i + 1];
+			bus_space_write_2(bst, bsh,
+			    sc->sc_reg_map[IAR_ADDR0_REG_W + i], tmp);
+		}
+	} else {
+		/* Read the MAC address from the chip. */
 		for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
-			tmp = bus_space_read_2(bst, bsh, IAR_ADDR0_REG_W + i);
-			myea[i + 1] = (tmp >> 8) & 0xff;
-			myea[i] = tmp & 0xff;
+			tmp = le16toh(bus_space_read_2(bst, bsh,
+			    sc->sc_reg_map[IAR_ADDR0_REG_W + i]));
+			sc->sc_enaddr[i] = (htons(tmp) >> 8) & 0xff;
+			sc->sc_enaddr[i + 1] = htons(tmp) & 0xff;
 		}
 	}
+
 	printf("%s: MAC address %s, ", sc->sc_dev.dv_xname,
-	    ether_sprintf(myea));
+	    ether_sprintf(sc->sc_enaddr));
 
 	/* ..and default media. */
-	tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W);
+	tmp = le16toh(bus_space_read_2(bst, bsh,
+	    sc->sc_reg_map[CONFIG_REG_W]));
 	printf("default media %s\n", (aui = (tmp & CR_AUI_SELECT)) ?
 	    "AUI" : "UTP");
 
@@ -249,7 +260,7 @@
 
 	/* Attach the interface. */
 	if_attach(ifp);
-	ether_ifattach(ifp, myea);
+	ether_ifattach(ifp, sc->sc_enaddr);
 
 	/* Initialize the media structures. */
 	ifmedia_init(&sc->sc_media, 0, smc91cxx_mediachange,
@@ -304,12 +315,14 @@
 	case IFM_10_T:
 	case IFM_10_5:
 		SMC_SELECT_BANK(sc, 1);
-		tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W);
+		tmp = le16toh(bus_space_read_2(bst, bsh,
+		    sc->sc_reg_map[CONFIG_REG_W]));
 		if (IFM_SUBTYPE(media) == IFM_10_5)
 			tmp |= CR_AUI_SELECT;
 		else
 			tmp &= ~CR_AUI_SELECT;
-		bus_space_write_2(bst, bsh, CONFIG_REG_W, tmp);
+		bus_space_write_2(bst, bsh, sc->sc_reg_map[CONFIG_REG_W],
+		    htole16(tmp));
 		delay(20000);	/* XXX is this needed? */
 		break;
 
@@ -340,7 +353,8 @@
 	}
 
 	SMC_SELECT_BANK(sc, 1);
-	tmp = bus_space_read_2(bst, bsh, CONFIG_REG_W);
+	tmp = le16toh(bus_space_read_2(bst, bsh,
+	    sc->sc_reg_map[CONFIG_REG_W]));
 	ifmr->ifm_active =
 	    IFM_ETHER | ((tmp & CR_AUI_SELECT) ? IFM_10_5 : IFM_10_T);
 }
@@ -356,7 +370,6 @@
 	bus_space_tag_t bst = sc->sc_bst;
 	bus_space_handle_t bsh = sc->sc_bsh;
 	u_int16_t tmp;
-	u_int8_t *enaddr;
 	int s, i;
 
 	s = splnet();
@@ -369,19 +382,21 @@
 	 * XXX how long are we really supposed to delay?  --thorpej
 	 */
 	SMC_SELECT_BANK(sc, 0);
-	bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, RCR_SOFTRESET);
+	bus_space_write_2(bst, bsh, sc->sc_reg_map[RECV_CONTROL_REG_W],
+	    htole16(RCR_SOFTRESET));
 	delay(100);
-	bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, 0);
+	bus_space_write_2(bst, bsh, sc->sc_reg_map[RECV_CONTROL_REG_W], 0);
 	delay(200);
 
-	bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, 0);
+	bus_space_write_2(bst, bsh, sc->sc_reg_map[TXMIT_CONTROL_REG_W], 0);
 
 	/* Set the Ethernet address. */
 	SMC_SELECT_BANK(sc, 1);
-	enaddr = (u_int8_t *)LLADDR(ifp->if_sadl);
 	for (i = 0; i < ETHER_ADDR_LEN; i += 2) {
-		tmp = enaddr[i + 1] << 8 | enaddr[i];
-		bus_space_write_2(bst, bsh, IAR_ADDR0_REG_W + i, tmp);
+		/* Might it be little endian? */
+		tmp = sc->sc_enaddr[i] << 8 | sc->sc_enaddr[i + 1];
+		bus_space_write_2(bst, bsh,
+		    sc->sc_reg_map[IAR_ADDR0_REG_W + i], tmp);
 	}
 
 	/*
@@ -389,21 +404,24 @@
 	 * transmitted packets (making the best use of our limited memory)
 	 * and enable the EPH interrupt on certain TX errors.
 	 */
-	bus_space_write_2(bst, bsh, CONTROL_REG_W, (CTR_AUTO_RELEASE |
-	    CTR_TE_ENABLE | CTR_CR_ENABLE | CTR_LE_ENABLE));
+	bus_space_write_2(bst, bsh, sc->sc_reg_map[CONTROL_REG_W],
+	    htole16(CTR_AUTO_RELEASE | CTR_TE_ENABLE | CTR_CR_ENABLE
+	    | CTR_LE_ENABLE));
 
 	/*
 	 * Reset the MMU and wait for it to be un-busy.
 	 */
 	SMC_SELECT_BANK(sc, 2);
-	bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_RESET);
-	while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
+	bus_space_write_2(bst, bsh, sc->sc_reg_map[MMU_CMD_REG_W],
+	    htole16(MMUCR_RESET));
+	while (le16toh(bus_space_read_2(bst, bsh,
+	    sc->sc_reg_map[MMU_CMD_REG_W])) & MMUCR_BUSY)
 		/* XXX bound this loop! */ ;
 
 	/*
 	 * Disable all interrupts.
 	 */
-	bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
+	bus_space_write_1(bst, bsh, sc->sc_reg_map[INTR_MASK_REG_B], 0);
 
 	/*
 	 * Set current media.
@@ -424,7 +442,8 @@
 	if (ifp->if_flags & IFF_PROMISC)
 		tmp |= RCR_PROMISC;
 
-	bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, tmp);
+	bus_space_write_2(bst, bsh, sc->sc_reg_map[RECV_CONTROL_REG_W],
+	    htole16(tmp));
 
 	/*
 	 * Set transmitter control to "enabled".
@@ -439,14 +458,15 @@
 	tmp |= TCR_PAD_ENABLE;
 #endif
 
-	bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, tmp);
+	bus_space_write_2(bst, bsh, sc->sc_reg_map[TXMIT_CONTROL_REG_W],
+	    htole16(tmp));
 
 	/*
 	 * Now, enable interrupts.
 	 */
 	SMC_SELECT_BANK(sc, 2);
 
-	bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
+	bus_space_write_1(bst, bsh, sc->sc_reg_map[INTR_MASK_REG_B],
 	    IM_EPH_INT | IM_RX_OVRN_INT | IM_RCV_INT | IM_TX_INT);
 
 	/* Interface is now running, with no output active. */
@@ -530,16 +550,19 @@
 	 * Now allocate the memory.
 	 */
 	SMC_SELECT_BANK(sc, 2);
-	bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_ALLOC | npages);
+	bus_space_write_2(bst, bsh, sc->sc_reg_map[MMU_CMD_REG_W],
+	    htole16(MMUCR_ALLOC | npages));
 
 	timo = MEMORY_WAIT_TIME;
 	do {
-		if (bus_space_read_1(bst, bsh, INTR_STAT_REG_B) & IM_ALLOC_INT)
+		if (bus_space_read_1(bst, bsh, sc->sc_reg_map[INTR_STAT_REG_B])
+		    & IM_ALLOC_INT)
 			break;
 		delay(1);
 	} while (--timo);
 
-	packetno = bus_space_read_1(bst, bsh, ALLOC_RESULT_REG_B);
+	packetno = bus_space_read_1(bst, bsh,
+	    sc->sc_reg_map[ALLOC_RESULT_REG_B]);
 
 	if (packetno & ARR_FAILED || timo == 0) {
 		/*
@@ -550,8 +573,9 @@
 		 * no one else attempts to transmit while we're allocating
 		 * memory.
 		 */
-		bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
-		    bus_space_read_1(bst, bsh, INTR_MASK_REG_B) | IM_ALLOC_INT);
+		bus_space_write_1(bst, bsh, sc->sc_reg_map[INTR_MASK_REG_B],
+		    bus_space_read_1(bst, bsh, sc->sc_reg_map[INTR_MASK_REG_B])
+		    | IM_ALLOC_INT);
 
 		ifp->if_timer = 5;
 		ifp->if_flags |= IFF_OACTIVE;
@@ -562,20 +586,24 @@
 	/*
 	 * We have a packet number - set the data window.
 	 */
-	bus_space_write_1(bst, bsh, PACKET_NUM_REG_B, packetno);
+	bus_space_write_1(bst, bsh, sc->sc_reg_map[PACKET_NUM_REG_B],
+	    packetno);
 
 	/*
 	 * Point to the beginning of the packet.
 	 */
-	bus_space_write_2(bst, bsh, POINTER_REG_W, PTR_AUTOINC /* | 0x0000 */);
+	bus_space_write_2(bst, bsh, sc->sc_reg_map[POINTER_REG_W],
+	    htole16(PTR_AUTOINC /* | 0x0000 */));
 
 	/*
 	 * Send the packet length (+6 for stats, length, and control bytes)
 	 * and the status word (set to zeros).
 	 */
-	bus_space_write_2(bst, bsh, DATA_REG_W, 0);
-	bus_space_write_1(bst, bsh, DATA_REG_B, (length + 6) & 0xff);
-	bus_space_write_1(bst, bsh, DATA_REG_B, ((length + 6) >> 8) & 0xff);
+	bus_space_write_2(bst, bsh, sc->sc_reg_map[DATA_REG_W], 0);
+	bus_space_write_1(bst, bsh, sc->sc_reg_map[DATA_REG_B],
+	    (length + 6) & 0xff);
+	bus_space_write_1(bst, bsh, sc->sc_reg_map[DATA_REG_B],
+	    ((length + 6) >> 8) & 0xff);
 
 	/*
 	 * Get the packet from the kernel.  This will include the Ethernet
@@ -587,14 +615,19 @@
 	 * Push the packet out to the card.
 	 */
 	for (top = m; m != NULL; m = m->m_next) {
+#if !defined(mac68k)
 		/* Words... */
-		bus_space_write_multi_2(bst, bsh, DATA_REG_W,
+		bus_space_write_multi_2(bst, bsh, sc->sc_reg_map[DATA_REG_W],
 		    mtod(m, u_int16_t *), m->m_len >> 1);
 
 		/* ...and the remaining byte, if any. */
 		if (m->m_len & 1)
-			bus_space_write_1(bst, bsh, DATA_REG_B,
+			bus_space_write_1(bst, bsh, sc->sc_reg_map[DATA_REG_B],
 			  *(u_int8_t *)(mtod(m, u_int8_t *) + (m->m_len - 1)));
+#else /* XXX */
+		bus_space_write_multi_1(bst, bsh, sc->sc_reg_map[DATA_REG_B],
+		    mtod(m, u_int8_t *), m->m_len);
+#endif
 	}
 
 #ifdef SMC91CXX_SW_PAD
@@ -602,11 +635,11 @@
 	 * Push out padding.
 	 */
 	while (pad > 1) {
-		bus_space_write_2(bst, bsh, DATA_REG_W, 0);
+		bus_space_write_2(bst, bsh, sc->sc_reg_map[DATA_REG_W], 0);
 		pad -= 2;
 	}
 	if (pad)
-		bus_space_write_1(bst, bsh, DATA_REG_B, 0);
+		bus_space_write_1(bst, bsh, sc->sc_reg_map[DATA_REG_B], 0);
 #endif
 
 	/*
@@ -614,17 +647,18 @@
 	 * is 0, meaning the packet is even lengthed and no special
 	 * CRC handling is necessary.
 	 */
-	bus_space_write_2(bst, bsh, DATA_REG_W, 0);
+	bus_space_write_2(bst, bsh, sc->sc_reg_map[DATA_REG_W], 0);
 
 	/*
 	 * Enable transmit interrupts and let the chip go.  Set a watchdog
 	 * in case we miss the interrupt.
 	 */
-	bus_space_write_1(bst, bsh, INTR_MASK_REG_B,
-	    bus_space_read_1(bst, bsh, INTR_MASK_REG_B) |
-	    IM_TX_INT | IM_TX_EMPTY_INT);
+	bus_space_write_1(bst, bsh, sc->sc_reg_map[INTR_MASK_REG_B],
+	    bus_space_read_1(bst, bsh, sc->sc_reg_map[INTR_MASK_REG_B])
+	    | IM_TX_INT | IM_TX_EMPTY_INT);
 
-	bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_ENQUEUE);
+	bus_space_write_2(bst, bsh, sc->sc_reg_map[MMU_CMD_REG_W],
+	    htole16(MMUCR_ENQUEUE));
 
 	ifp->if_timer = 5;
 
@@ -643,7 +677,8 @@
 	 * RX FIFO.  If nothing has arrived, attempt to queue another
 	 * transmit packet.
 	 */
-	if (bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W) & FIFO_REMPTY)
+	if (bus_space_read_2(bst, bsh,
+	    sc->sc_reg_map[FIFO_PORTS_REG_W]) & le16toh(FIFO_REMPTY))
 		goto again;
 }
 
@@ -670,13 +705,14 @@
 	/*
 	 * Obtain the current interrupt mask.
 	 */
-	mask = bus_space_read_1(bst, bsh, INTR_MASK_REG_B);
+	mask = bus_space_read_1(bst, bsh, sc->sc_reg_map[INTR_MASK_REG_B]);
 
 	/*
 	 * Get the set of interrupt which occurred and eliminate any
 	 * which are not enabled.
 	 */
-	interrupts = bus_space_read_1(bst, bsh, INTR_STAT_REG_B);
+	interrupts = bus_space_read_1(bst, bsh,
+	    sc->sc_reg_map[INTR_STAT_REG_B]);
 	status = interrupts & mask;
 
 	/* Ours? */
@@ -686,13 +722,14 @@
 	/*
 	 * It's ours; disable all interrupts while we process them.
 	 */
-	bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
+	bus_space_write_1(bst, bsh, sc->sc_reg_map[INTR_MASK_REG_B], 0);
 
 	/*
 	 * Receive overrun interrupts.
 	 */
 	if (status & IM_RX_OVRN_INT) {
-		bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_RX_OVRN_INT);
+		bus_space_write_1(bst, bsh, sc->sc_reg_map[INTR_ACK_REG_B],
+		    IM_RX_OVRN_INT);
 		ifp->if_ierrors++;
 	}
 
@@ -701,7 +738,8 @@
 	 */
 	if (status & IM_RCV_INT) {
 #if 1 /* DIAGNOSTIC */
-		packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W);
+		packetno = le16toh(bus_space_read_2(bst, bsh,
+		    sc->sc_reg_map[FIFO_PORTS_REG_W]));
 		if (packetno & FIFO_REMPTY)
 			printf("%s: receive interrupt on empty fifo\n",
 			    sc->sc_dev.dv_xname);
@@ -721,9 +759,11 @@
 		 * Release the just-allocated memory.  We will reallocate
 		 * it through the normal start logic.
 		 */
-		while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
+		while (bus_space_read_2(bst, bsh,
+		    sc->sc_reg_map[MMU_CMD_REG_W]) & le16toh(MMUCR_BUSY))
 			/* XXX bound this loop! */ ;
-		bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_FREEPKT);
+		bus_space_write_2(bst, bsh, sc->sc_reg_map[MMU_CMD_REG_W],
+		    htole16(MMUCR_FREEPKT));
 
 		ifp->if_flags &= ~IFF_OACTIVE;
 		ifp->if_timer = 0;
@@ -735,28 +775,31 @@
 	 * mode.
 	 */
 	if (status & IM_TX_INT) {
-		bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_TX_INT);
+		bus_space_write_1(bst, bsh, sc->sc_reg_map[INTR_ACK_REG_B],
+		    IM_TX_INT);
 
-		packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W) &
-		    FIFO_TX_MASK;
+		packetno = le16toh(bus_space_read_2(bst, bsh,
+		    sc->sc_reg_map[FIFO_PORTS_REG_W])) & FIFO_TX_MASK;
 
 		/*
 		 * Select this as the packet to read from.
 		 */
-		bus_space_write_1(bst, bsh, PACKET_NUM_REG_B, packetno);
+		bus_space_write_1(bst, bsh, sc->sc_reg_map[PACKET_NUM_REG_B],
+		    packetno);
 
 		/*
 		 * Position the pointer to the beginning of the packet.
 		 */
-		bus_space_write_2(bst, bsh, POINTER_REG_W,
-		    PTR_AUTOINC | PTR_READ /* | 0x0000 */);
+		bus_space_write_2(bst, bsh, sc->sc_reg_map[POINTER_REG_W],
+		    htole16(PTR_AUTOINC | PTR_READ /* | 0x0000 */));
 
 		/*
 		 * Fetch the TX status word.  This will be a copy of
 		 * the EPH_STATUS_REG_W at the time of the transmission
 		 * failure.
 		 */
-		tx_status = bus_space_read_2(bst, bsh, DATA_REG_W);
+		tx_status = le16toh(bus_space_read_2(bst, bsh,
+		    sc->sc_reg_map[DATA_REG_W]));
 
 		if (tx_status & EPHSR_TX_SUC)
 			printf("%s: successful packet caused TX interrupt?!\n",
@@ -772,19 +815,23 @@
 		 */
 		SMC_SELECT_BANK(sc, 0);
 #ifdef SMC91CXX_SW_PAD
-		bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, TCR_ENABLE);
+		bus_space_write_2(bst, bsh,
+		    sc->sc_reg_map[TXMIT_CONTROL_REG_W], htole16(TCR_ENABLE));
 #else
-		bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W,
-		    TCR_ENABLE | TCR_PAD_ENABLE);
+		bus_space_write_2(bst, bsh,
+		    sc->sc_reg_map[TXMIT_CONTROL_REG_W],
+		    htole16(TCR_ENABLE | TCR_PAD_ENABLE));
 #endif
 
 		/*
 		 * Kill the failed packet and wait for the MMU to unbusy.
 		 */
 		SMC_SELECT_BANK(sc, 2);
-		while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
+		while (bus_space_read_2(bst, bsh,
+		    sc->sc_reg_map[MMU_CMD_REG_W]) & le16toh(MMUCR_BUSY))
 			/* XXX bound this loop! */ ;
-		bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_FREEPKT);
+		bus_space_write_2(bst, bsh, sc->sc_reg_map[MMU_CMD_REG_W],
+		    htole16(MMUCR_FREEPKT));
 
 		ifp->if_timer = 0;
 	}
@@ -794,13 +841,15 @@
 	 * update transmit statistics from the card.
 	 */
 	if (status & IM_TX_EMPTY_INT) {
-		bus_space_write_1(bst, bsh, INTR_ACK_REG_B, IM_TX_EMPTY_INT);
+		bus_space_write_1(bst, bsh, sc->sc_reg_map[INTR_ACK_REG_B],
+		    IM_TX_EMPTY_INT);
 
 		/* Disable this interrupt. */
 		mask &= ~IM_TX_EMPTY_INT;
 
 		SMC_SELECT_BANK(sc, 0);
-		card_stats = bus_space_read_2(bst, bsh, COUNTER_REG_W);
+		card_stats = le16toh(bus_space_read_2(bst, bsh,
+		    sc->sc_reg_map[COUNTER_REG_W]));
 
 		/* Single collisions. */
 		ifp->if_collisions += card_stats & ECR_COLN_MASK;
@@ -830,8 +879,8 @@
 	 * Reenable the interrupts we wish to receive now that processing
 	 * is complete.
 	 */
-	mask |= bus_space_read_1(bst, bsh, INTR_MASK_REG_B);
-	bus_space_write_1(bst, bsh, INTR_MASK_REG_B, mask);
+	mask |= bus_space_read_1(bst, bsh, sc->sc_reg_map[INTR_MASK_REG_B]);
+	bus_space_write_1(bst, bsh, sc->sc_reg_map[INTR_MASK_REG_B], mask);
 
 #if NRND > 0
 	if (status)
@@ -863,14 +912,16 @@
 	 * PTR_RCV is set, the packet number will be found automatically
 	 * in FIFO_PORTS_REG_W, FIFO_RX_MASK.
 	 */
-	bus_space_write_2(bst, bsh, POINTER_REG_W,
-	    PTR_READ | PTR_RCV | PTR_AUTOINC /* | 0x0000 */);
+	bus_space_write_2(bst, bsh, sc->sc_reg_map[POINTER_REG_W],
+	    htole16(PTR_READ | PTR_RCV | PTR_AUTOINC /* | 0x0000 */));
 
 	/*
 	 * First two words are status and packet length.
 	 */
-	status = bus_space_read_2(bst, bsh, DATA_REG_W);
-	packetlen = bus_space_read_2(bst, bsh, DATA_REG_W);
+	status = le16toh(bus_space_read_2(bst, bsh,
+	    sc->sc_reg_map[DATA_REG_W]));
+	packetlen = le16toh(bus_space_read_2(bst, bsh,
+	    sc->sc_reg_map[DATA_REG_W]));
 
 	/*
 	 * The packet length includes 3 extra words: status, length,
@@ -896,8 +947,9 @@
 	 * Allocate a header mbuf.
 	 */
 	MGETHDR(m, M_DONTWAIT, MT_DATA);
-	if (m == NULL)
+	if (m == NULL) {
 		goto out;
+	}
 
 	m->m_pkthdr.rcvif = ifp;
 	m->m_pkthdr.len = m->m_len = packetlen;
@@ -920,12 +972,17 @@
 	 */
 	eh = mtod(m, struct ether_header *);
 	data = mtod(m, u_int8_t *);
-	bus_space_read_multi_2(bst, bsh, DATA_REG_W, (u_int16_t *)data,
-	    packetlen >> 1);
+#if !defined(mac68k)
+	bus_space_read_multi_2(bst, bsh, sc->sc_reg_map[DATA_REG_W],
+	    (u_int16_t *)data, packetlen >> 1);
 	if (packetlen & 1) {
 		data += packetlen & ~1;
-		*data = bus_space_read_1(bst, bsh, DATA_REG_B);
+		*data = bus_space_read_1(bst, bsh, sc->sc_reg_map[DATA_REG_B]);
 	}
+#else /* XXX */
+	bus_space_read_multi_1(bst, bsh, sc->sc_reg_map[DATA_REG_B], data,
+	    packetlen);
+#endif
 
 	ifp->if_ipackets++;
 
@@ -969,14 +1026,17 @@
 	/*
 	 * Tell the card to free the memory occupied by this packet.
 	 */
-	while (bus_space_read_2(bst, bsh, MMU_CMD_REG_W) & MMUCR_BUSY)
+	while (bus_space_read_2(bst, bsh,
+	    sc->sc_reg_map[MMU_CMD_REG_W]) & le16toh(MMUCR_BUSY))
 		/* XXX bound this loop! */ ;
-	bus_space_write_2(bst, bsh, MMU_CMD_REG_W, MMUCR_RELEASE);
+	bus_space_write_2(bst, bsh, sc->sc_reg_map[MMU_CMD_REG_W],
+	    htole16(MMUCR_RELEASE));
 
 	/*
 	 * Check for another packet.
 	 */
-	packetno = bus_space_read_2(bst, bsh, FIFO_PORTS_REG_W);
+	packetno = le16toh(bus_space_read_2(bst, bsh,
+	    sc->sc_reg_map[FIFO_PORTS_REG_W]));
 	if (packetno & FIFO_REMPTY)
 		return;
 	goto again;
@@ -1155,14 +1215,14 @@
 	 * Clear interrupt mask; disable all interrupts.
 	 */
 	SMC_SELECT_BANK(sc, 2);
-	bus_space_write_1(bst, bsh, INTR_MASK_REG_B, 0);
+	bus_space_write_1(bst, bsh, sc->sc_reg_map[INTR_MASK_REG_B], 0);
 
 	/*
 	 * Disable transmitter and receiver.
 	 */
 	SMC_SELECT_BANK(sc, 0);
-	bus_space_write_2(bst, bsh, RECV_CONTROL_REG_W, 0);
-	bus_space_write_2(bst, bsh, TXMIT_CONTROL_REG_W, 0);
+	bus_space_write_2(bst, bsh, sc->sc_reg_map[RECV_CONTROL_REG_W], 0);
+	bus_space_write_2(bst, bsh, sc->sc_reg_map[TXMIT_CONTROL_REG_W], 0);
 
 	/*
 	 * Cancel watchdog timer.
Index: dev/ic/smc91cxxvar.h
===================================================================
RCS file: /a/rsync/netbsd.org/syssrc/sys/dev/ic/smc91cxxvar.h,v
retrieving revision 1.7
diff -u -r1.7 smc91cxxvar.h
--- smc91cxxvar.h	2000/02/02 16:04:42	1.7
+++ smc91cxxvar.h	2000/02/03 18:18:07
@@ -37,6 +37,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <sys/endian.h>
 #include "rnd.h"
 
 #if NRND > 0
@@ -52,6 +53,11 @@
 
 	struct	ifmedia sc_media;	/* our media info */
 
+	u_int8_t sc_reg_map[SMC_IOSIZE]; /* register map (offsets) */
+
+	u_int8_t sc_enaddr[ETHER_ADDR_LEN]; /* MAC address */
+	int	sc_enaddr_from_rom;	/* MAC address can be taken from ROM */
+
 	/* Power management hooks and state. */
 	int	(*sc_enable) __P((struct smc91cxx_softc *));
 	void	(*sc_disable) __P((struct smc91cxx_softc *));
@@ -62,11 +68,16 @@
 #endif
 };
 
-#define	SMC_SELECT_BANK(sc, x)						\
+#define SMC_SELECT_BANK(sc, x)						\
 	bus_space_write_2((sc)->sc_bst, (sc)->sc_bsh,			\
-	    BANK_SELECT_REG_W, (x))
+	    (sc)->sc_reg_map[BANK_SELECT_REG_W], htole16(x))
+/*
+ * Vendor types
+ */
+#define SMC91CXX_VENDOR_UNKNOWN		0xff	/* unknown */
+#define SMC91CXX_VENDOR_API		0x00	/* API Engineering, Newer Technology */
 
-void	smc91cxx_attach __P((struct smc91cxx_softc *, u_int8_t *));
+void	smc91cxx_attach __P((struct smc91cxx_softc *));
 int	smc91cxx_intr __P((void *));
 int	smc91cxx_enable __P((struct smc91cxx_softc *));
 void	smc91cxx_disable __P((struct smc91cxx_softc *));
Index: dev/isa/if_sm_isa.c
===================================================================
RCS file: /a/rsync/netbsd.org/syssrc/sys/dev/isa/if_sm_isa.c,v
retrieving revision 1.4
diff -u -r1.4 if_sm_isa.c
--- if_sm_isa.c	1998/07/05 06:49:14	1.4
+++ if_sm_isa.c	1999/11/06 09:11:17
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_sm_isa.c,v 1.3 1998/07/05 00:51:22 jonathan Exp $	*/
+/*	$NetBSD: if_sm_isa.c,v 1.4 1998/07/05 06:49:14 jonathan Exp $	*/
 
 /*-
  * Copyright (c) 1997 The NetBSD Foundation, Inc.
@@ -182,13 +182,19 @@
 	sc->sc_bst = iot;
 	sc->sc_bsh = ioh;
 
+	/* registers are linear. */
+	for (i = 0; i < SMC_IOSIZE; i++) {
+		sc->sc_reg_map[i] = i;
+	}
+
 	/* should always be enabled */
 	sc->sc_enabled = 1;
 
 	/* XXX Should get Ethernet address from EEPROM!! */
+	sc->sc_enaddr_from_rom = 0;
 
 	/* Perform generic intialization. */
-	smc91cxx_attach(sc, NULL);
+	smc91cxx_attach(sc);
 
 	/* Establish the interrupt handler. */
 	isc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
Index: dev/pcmcia/if_sm_pcmcia.c
===================================================================
RCS file: /a/rsync/netbsd.org/syssrc/sys/dev/pcmcia/if_sm_pcmcia.c,v
retrieving revision 1.21
diff -u -r1.21 if_sm_pcmcia.c
--- if_sm_pcmcia.c	2000/02/09 13:40:42	1.21
+++ if_sm_pcmcia.c	2000/02/12 01:43:19
@@ -155,6 +155,11 @@
 	psc->sc_pf = pa->pf;
 	cfe = pa->pf->cfe_head.sqh_first;
 
+	/* registers are linear. */
+	for (i = 0; i < SMC_IOSIZE; i++) {
+		sc->sc_reg_map[i] = i;
+	}
+
 	/* Enable the card. */
 	pcmcia_function_init(pa->pf, cfe);
 	if (pcmcia_function_enable(pa->pf)) {
@@ -190,6 +195,7 @@
 		panic("sm_pcmcia_attach: impossible");
 
 	printf(": %s\n", pp->pp_name);
+	sc->sc_enaddr_from_rom = 0;
 
 	/*
 	 * First try to get the Ethernet address from FUNCE/LANNID tuple.
@@ -218,12 +224,18 @@
 			enaddr = myla;
 	}
 
-	if (enaddr == NULL)
+	if (enaddr) {
+		for (i = 0; i < ETHER_ADDL_LEN; i++) {
+			sc->sc_enaddr[i] = *(enaddr + i);
+		}
+		sc->sc_enaddr_from_rom = 1;
+	} else {
 		printf("%s: unable to get Ethernet address\n",
 		    sc->sc_dev.dv_xname);
+	}
 
 	/* Perform generic intialization. */
-	smc91cxx_attach(sc, enaddr);
+	smc91cxx_attach(sc);
 
 	pcmcia_function_disable(pa->pf);
 	return;
Index: dev/pcmcia/mhzc.c
===================================================================
RCS file: /a/rsync/netbsd.org/syssrc/sys/dev/pcmcia/mhzc.c,v
retrieving revision 1.5
diff -u -r1.5 mhzc.c
--- mhzc.c	2000/02/05 04:44:00	1.5
+++ mhzc.c	2000/02/16 10:39:26
@@ -202,6 +202,10 @@
 
 	sc->sc_pf = pa->pf;
 
+	/* registers are linear. */
+	for (i = 0; i < SMC_IOSIZE; i++) {
+		sc->sc_reg_map[i] = i;
+	}
 	sc->sc_product = (const struct mhzc_product *)pcmcia_product_lookup(pa,
             (const struct pcmcia_product *)mhzc_products,
             sizeof mhzc_products[0], NULL);
@@ -515,17 +519,16 @@
  *****************************************************************************/
 
 int	mhzc_em3336_lannid_ciscallback __P((struct pcmcia_tuple *, void *));
-int	mhzc_em3336_ascii_enaddr __P((const char *cisstr, u_int8_t *));
+int	mhzc_em3336_ascii_enaddr __P((const char *cisstr));
 
 int
-mhzc_em3336_enaddr(sc, myla)
+mhzc_em3336_enaddr(sc)
 	struct mhzc_softc *sc;
-	u_int8_t *myla;
 {
 
 	/* Get the station address from CIS tuple 0x81. */
 	if (pcmcia_scan_cis(sc->sc_dev.dv_parent,
-	    mhzc_em3336_lannid_ciscallback, myla) != 1) {
+	    mhzc_em3336_lannid_ciscallback, sc->sc_enaddr) != 1) {
 		printf("%s: unable to get Ethernet address from CIS\n",
 		    sc->sc_dev.dv_xname);
 		return (0);
@@ -591,11 +594,10 @@
 }
 
 int
-mhzc_em3336_lannid_ciscallback(tuple, arg)
+mhzc_em3336_lannid_ciscallback(tuple)
 	struct pcmcia_tuple *tuple;
-	void *arg;
 {
-	u_int8_t *myla = arg, addr_str[ETHER_ADDR_LEN * 2];
+	u_int8_t *addr_str[ETHER_ADDR_LEN * 2];
 	int i;
 
 	if (tuple->code == 0x81) {
@@ -610,9 +612,9 @@
 			addr_str[i] = pcmcia_tuple_read_1(tuple, i);
 
 		/*
-		 * Decode the string into `myla'.
+		 * Decode the string into sc->sc_enaddr.
 		 */
-		return (mhzc_em3336_ascii_enaddr(addr_str, myla));
+		return (mhzc_em3336_ascii_enaddr(addr_str, sc->sc_enaddr));
 	}
 	return (0);
 }
@@ -775,7 +777,6 @@
 {
 	struct smc91cxx_softc *sc = (void *)self;
 	struct mhzc_softc *msc = (void *)parent;
-	u_int8_t myla[ETHER_ADDR_LEN];
 
 	printf(":");
 	if (pcmcia_io_map(msc->sc_pf, PCMCIA_WIDTH_IO16, 0,
@@ -794,11 +795,13 @@
 	sc->sc_enable = sm_mhzc_enable;
 	sc->sc_disable = sm_mhzc_disable;
 
-	if ((*msc->sc_product->mp_enaddr)(msc, myla) != 1)
+	if ((*msc->sc_product->mp_enaddr)(msc, sc->sc_enaddr) != 1)
 		return;
 
+	sc->sc_enaddr_from_rom = 1;
+
 	/* Perform generic initialization. */
-	smc91cxx_attach(sc, myla);
+	smc91cxx_attach(sc);
 }
 
 int