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