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--