Subject: if_cnw correction (PR 10139)
To: None <port-i386@netbsd.org>
From: None <itojun@iijlab.net>
List: port-i386
Date: 07/06/2000 03:30:07
------- =_aaaaaaaaaa0
Content-Type: text/plain; charset="us-ascii"
Content-ID: <10582.962821789.1@coconut.itojun.org>
Content-Transfer-Encoding: 7bit

	for cnw users: please test it if your cnw does not work right due to
	I/O address range changes.

itojun

------- =_aaaaaaaaaa0
Content-Type: message/rfc822

To: bugs@netbsd.org
cc: feico@dillema.net
Subject: Re: port-i386/10139
From: itojun@iijlab.net
Date: Thu, 06 Jul 2000 03:29:01 +0900
Message-ID: <10534.962821741@coconut.itojun.org>
Sender: itojun@coconut.itojun.org

	The patch tries to use memory mapped access, instead of I/O space
	access, for control registers.  as cnw chokes if I/O address range
	goes >= 0x400 (and CIS tuple does not talk about this), it would 
	be a good option.  I tested it with ThinkPad T20, however, it
	has some issue in receiving large (like >1400) datagram in
		ether -> basestation -> note PC
	direction.  please test it if interested.

itojun


---
Index: if_cnw.c
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pcmcia/if_cnw.c,v
retrieving revision 1.11
diff -u -r1.11 if_cnw.c
--- if_cnw.c	2000/06/05 23:06:31	1.11
+++ if_cnw.c	2000/07/05 18:23:06
@@ -172,8 +172,15 @@
  * We can que a second packet if there are transmit buffers available,
  * but we do not actually send the packet until the last packet has
  * been written.
+ */
 #define	ONE_AT_A_TIME
+
+/*
+ * Netwave cards choke if we try to use io memory address >= 0x400.
+ * Even though, CIS tuple does not talk about this.
+ * Use memory mapped access.
  */
+#define MEMORY_MAPPED
 
 int	cnw_match __P((struct device *, struct cfdata *, void *));
 void	cnw_attach __P((struct device *, struct device *, void *));
@@ -190,10 +197,12 @@
 
 	/* PCMCIA-specific stuff */
 	struct pcmcia_function *sc_pf;	    /* PCMCIA function */
+#ifndef MEMORY_MAPPED
 	struct pcmcia_io_handle sc_pcioh;   /* PCMCIA I/O space handle */
 	int sc_iowin;			    /*   ...window */
 	bus_space_tag_t sc_iot;		    /*   ...bus_space tag */
 	bus_space_handle_t sc_ioh;	    /*   ...bus_space handle */
+#endif
 	struct pcmcia_mem_handle sc_pcmemh; /* PCMCIA memory handle */
 	bus_addr_t sc_memoff;		    /*   ...offset */
 	int sc_memwin;			    /*   ...window */
@@ -250,7 +259,12 @@
 	int i, asr;
 
 	for (i = 0; i < 5000; i++) {
+#ifndef MEMORY_MAPPED
 		asr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CNW_REG_ASR);
+#else
+		asr = bus_space_read_1(sc->sc_memt, sc->sc_memh,
+		    sc->sc_memoff + CNW_IOM_OFF + CNW_REG_ASR);
+#endif
 		if (asr & CNW_ASR_WOC)
 			return (0);
 		DELAY(100);
@@ -337,10 +351,20 @@
 		printf("%s: resetting\n", sc->sc_dev.dv_xname);
 #endif
 	wait_WOC(sc, 0);
+#ifndef MEMORY_MAPPED
 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, CNW_REG_PMR, CNW_PMR_RESET);
+#eles
+	bus_space_write_1(sc->sc_memt, sc->sc_meh,
+	    sc->sc_memoff + CNW_IOM_OFF + CNW_REG_PMR, CNW_PMR_RESET);
+#endif
 	bus_space_write_1(sc->sc_memt, sc->sc_memh,
 	    sc->sc_memoff + CNW_EREG_ASCC, CNW_ASR_WOC);
+#ifndef MEMORY_MAPPED
 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, CNW_REG_PMR, 0);
+#else
+	bus_space_write_1(sc->sc_memt, sc->sc_memh,
+	    sc->sc_memoff + CNW_IOM_OFF + CNW_REG_PMR, 0);
+#endif
 }
 
 
@@ -376,16 +400,28 @@
 
 	/* Enable interrupts */
 	WAIT_WOC(sc);
+#ifndef MEMORY_MAPPED
 	bus_space_write_1(sc->sc_iot, sc->sc_ioh,
 	    CNW_REG_IMR, CNW_IMR_IENA | CNW_IMR_RFU1);
+#else
+	bus_space_write_1(sc->sc_memt, sc->sc_memh,
+	    sc->sc_memoff + CNW_IOM_OFF + CNW_REG_IMR,
+	    CNW_IMR_IENA | CNW_IMR_RFU1);
+#endif
 
 	/* Enable receiver */
 	CNW_CMD0(sc, CNW_CMD_ER);
 
 	/* "Set the IENA bit in COR" */
 	WAIT_WOC(sc);
+#ifndef MEMORY_MAPPED
 	bus_space_write_1(sc->sc_iot, sc->sc_ioh, CNW_REG_COR,
 	    CNW_COR_IENA | CNW_COR_LVLREQ);
+#else
+	bus_space_write_1(sc->sc_memt, sc->sc_memh,
+	    sc->sc_memoff + CNW_IOM_OFF + CNW_REG_COR,
+	    CNW_COR_IENA | CNW_COR_LVLREQ);
+#endif
 }
 
 
@@ -473,6 +509,7 @@
 	struct ifnet *ifp = &sc->sc_ethercom.ec_if;
 	u_int8_t macaddr[ETHER_ADDR_LEN];
 	int i;
+	bus_size_t memsize;
 
 	sc->sc_resource = 0;
 
@@ -486,11 +523,13 @@
 	sc->sc_resource |= CNW_RES_PCIC;
 
 	/* Map I/O register and "memory" */
+#ifndef MEMORY_MAPPED
 	if (pcmcia_io_alloc(sc->sc_pf, 0, CNW_IO_SIZE, CNW_IO_SIZE,
 	    &sc->sc_pcioh) != 0) {
 		printf(": can't allocate i/o space\n");
 		goto fail;
 	}
+
 	if (pcmcia_io_map(sc->sc_pf, PCMCIA_WIDTH_IO16, 0,
 	    CNW_IO_SIZE, &sc->sc_pcioh, &sc->sc_iowin) != 0) {
 		printf(": can't map i/o space\n");
@@ -500,12 +539,18 @@
 	sc->sc_iot = sc->sc_pcioh.iot;
 	sc->sc_ioh = sc->sc_pcioh.ioh;
 	sc->sc_resource |= CNW_RES_IO;
+#endif
 	if (pcmcia_mem_alloc(sc->sc_pf, CNW_MEM_SIZE, &sc->sc_pcmemh) != 0) {
 		printf(": can't allocate memory\n");
 		goto fail;
 	}
+#ifndef MEMORY_MAPPED
+	memsize = CNW_MEM_SIZE;
+#else
+	memsize = CNW_MEM_SIZE + CNW_IOM_SIZE;
+#endif
 	if (pcmcia_mem_map(sc->sc_pf, PCMCIA_WIDTH_MEM8|PCMCIA_MEM_COMMON,
-	    CNW_MEM_ADDR, CNW_MEM_SIZE, &sc->sc_pcmemh, &sc->sc_memoff,
+	    CNW_MEM_ADDR, memsize, &sc->sc_pcmemh, &sc->sc_memoff,
 	    &sc->sc_memwin) != 0) {
 		printf(": can't map memory\n");
 		pcmcia_mem_free(sc->sc_pf, &sc->sc_pcmemh);
@@ -561,11 +606,13 @@
 	return;
 
 fail:
+#ifndef MEMORY_MAPPED
 	if ((sc->sc_resource & CNW_RES_IO) != 0) {
 		pcmcia_io_unmap(sc->sc_pf, sc->sc_iowin);
 		pcmcia_io_free(sc->sc_pf, &sc->sc_pcioh);
 		sc->sc_resource &= ~CNW_RES_IO;
 	}
+#endif
 	if ((sc->sc_resource & CNW_RES_PCIC) != 0) {
 		pcmcia_function_disable(sc->sc_pf);
 		sc->sc_resource &= ~CNW_RES_PCIC;
@@ -638,7 +685,12 @@
 
 		/* Is there any buffer space available on the card? */
 		WAIT_WOC(sc);
+#ifndef MEMORY_MAPPED
 		asr = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CNW_REG_ASR);
+#else
+		asr = bus_space_read_1(sc->sc_memt, sc->sc_memh,
+		    sc->sc_memoff + CNW_IOM_OFF + CNW_REG_ASR);
+#endif
 		if (!(asr & CNW_ASR_TXBA)) {
 #ifdef CNW_DEBUG
 			if (sc->sc_ethercom.ec_if.if_flags & IFF_DEBUG)
@@ -889,15 +941,26 @@
 	ret = 0;
 	for (;;) {
 		WAIT_WOC(sc);
-		if (!(bus_space_read_1(sc->sc_iot, sc->sc_ioh,
-		    CNW_REG_CCSR) & 0x02)) {
+#ifndef MEMORY_MAPPED
+		status = bus_space_read_1(sc->sc_iot, sc->sc_ioh,
+		    CNW_REG_CCSR);
+#else
+		status = bus_space_read_1(sc->sc_memt, sc->sc_memh,
+		    sc->sc_memoff + CNW_IOM_OFF + CNW_REG_CCSR);
+#endif
+		if (!(status & 0x02)) {
 			if (ret == 0)
 				printf("%s: spurious interrupt\n",
 				    sc->sc_dev.dv_xname);
 			return (ret);
 		}
 		ret = 1;
+#ifndef MEMORY_MAPPED
 		status = bus_space_read_1(sc->sc_iot, sc->sc_ioh, CNW_REG_ASR);
+#else
+		status = bus_space_read_1(sc->sc_memt, sc->sc_memh,
+		    sc->sc_memoff + CNW_IOM_OFF + CNW_REG_ASR);
+#endif
 
 		/* Anything to receive? */
 		if (status & CNW_ASR_RXRDY) {
@@ -1191,11 +1254,13 @@
 		if_detach(ifp);
 	}
 
+#ifndef MEMORY_MAPPED
 	/* unmap and free our i/o windows */
 	if ((sc->sc_resource & CNW_RES_IO) != 0) {
 		pcmcia_io_unmap(sc->sc_pf, sc->sc_iowin);
 		pcmcia_io_free(sc->sc_pf, &sc->sc_pcioh);
 	}
+#endif
 
 	/* unmap and free our memory windows */
 	if ((sc->sc_resource & CNW_RES_MEM) != 0) {
Index: if_cnwreg.h
===================================================================
RCS file: /cvsroot/syssrc/sys/dev/pcmcia/if_cnwreg.h,v
retrieving revision 1.2
diff -u -r1.2 if_cnwreg.h
--- if_cnwreg.h	1999/11/29 12:54:00	1.2
+++ if_cnwreg.h	2000/07/05 18:23:08
@@ -39,6 +39,10 @@
 
 /* I/O area */
 #define CNW_IO_SIZE		0x10
+/* I/O area can be accessed via mapped memory too */
+#define CNW_IOM_ADDR		0x28000
+#define CNW_IOM_SIZE		CNW_IO_SIZE
+#define CNW_IOM_OFF		(CNW_IOM_ADDR - CNW_MEM_ADDR)
 
 /* I/O registers */
 #define CNW_REG_COR		0x0

------- =_aaaaaaaaaa0--