The Lenovo Ideacentre Stick 300 I recently acquired has a Realtek
RTL8723BS wireless chip which uses an SDIO interface.  This made me
look at our SDIO support code again.  I noticed that reading the
per-function CIS wasn't implemented, so I wrote the missing code.

The diff below fixes a couple of issues with the code.  The most
important thing as the we need to read from function 0 to gather all
the information.  I also noticed that the current code mistakenly
identified the SDIO card function code as "wireless network".  Last but
not least, the bus width was being set to a reserved value.  I removed
that setting, as it is obviously wrong and bus width 1 is supposed to
be the default anyway.

As far as I know we don't actually have any SDIO device drivers in our
tree anymore, so this should all be very low risk.

ok?


Index: sdmmc_cis.c
===================================================================
RCS file: /cvs/src/sys/dev/sdmmc/sdmmc_cis.c,v
retrieving revision 1.6
diff -u -p -r1.6 sdmmc_cis.c
--- sdmmc_cis.c 11 Jan 2016 07:32:38 -0000      1.6
+++ sdmmc_cis.c 19 Apr 2016 21:20:47 -0000
@@ -37,18 +37,16 @@ u_int32_t sdmmc_cisptr(struct sdmmc_func
 u_int32_t
 sdmmc_cisptr(struct sdmmc_function *sf)
 {
+       struct sdmmc_function *sf0 = sf->sc->sc_fn0;
        u_int32_t cisptr = 0;
+       int reg;
 
        rw_assert_wrlock(&sf->sc->sc_lock);
 
-       /* XXX where is the per-function CIS pointer register? */
-       if (sf->number != 0)
-               return SD_IO_CIS_START;
-
-       /* XXX is the CIS pointer stored in little-endian format? */
-       cisptr |= sdmmc_io_read_1(sf, SD_IO_CCCR_CISPTR+0) << 0;
-       cisptr |= sdmmc_io_read_1(sf, SD_IO_CCCR_CISPTR+1) << 8;
-       cisptr |= sdmmc_io_read_1(sf, SD_IO_CCCR_CISPTR+2) << 16;
+       reg = SD_IO_CCCR_CISPTR + (sf->number * SD_IO_CCCR_SIZE);
+       cisptr |= sdmmc_io_read_1(sf0, reg + 0) << 0;
+       cisptr |= sdmmc_io_read_1(sf0, reg + 1) << 8;
+       cisptr |= sdmmc_io_read_1(sf0, reg + 2) << 16;
 
        return cisptr;
 }
@@ -56,18 +54,13 @@ sdmmc_cisptr(struct sdmmc_function *sf)
 int
 sdmmc_read_cis(struct sdmmc_function *sf, struct sdmmc_cis *cis)
 {
+       struct sdmmc_function *sf0 = sf->sc->sc_fn0;
        int reg;
        u_int8_t tplcode;
        u_int8_t tpllen;
 
        rw_assert_wrlock(&sf->sc->sc_lock);
 
-       bzero(cis, sizeof *cis);
-
-       /* XXX read per-function CIS */
-       if (sf->number != 0)
-               return 1;
-
        reg = (int)sdmmc_cisptr(sf);
        if (reg < SD_IO_CIS_START ||
            reg >= (SD_IO_CIS_START+SD_IO_CIS_SIZE-16)) {
@@ -76,13 +69,13 @@ sdmmc_read_cis(struct sdmmc_function *sf
        }
 
        for (;;) {
-               tplcode = sdmmc_io_read_1(sf, reg++);
+               tplcode = sdmmc_io_read_1(sf0, reg++);
                if (tplcode == SD_IO_CISTPL_END)
                        break;
                if (tplcode == SD_IO_CISTPL_NULL)
                        continue;
 
-               tpllen = sdmmc_io_read_1(sf, reg++);
+               tpllen = sdmmc_io_read_1(sf0, reg++);
                if (tpllen == 0) {
                        printf("%s: CIS parse error at %d, "
                            "tuple code %#x, length %d\n",
@@ -98,7 +91,7 @@ sdmmc_read_cis(struct sdmmc_function *sf
                                reg += tpllen;
                                break;
                        }
-                       cis->function = sdmmc_io_read_1(sf, reg);
+                       cis->function = sdmmc_io_read_1(sf0, reg);
                        reg += tpllen;
                        break;
                case SD_IO_CISTPL_MANFID:
@@ -108,10 +101,10 @@ sdmmc_read_cis(struct sdmmc_function *sf
                                reg += tpllen;
                                break;
                        }
-                       cis->manufacturer = sdmmc_io_read_1(sf, reg++);
-                       cis->manufacturer |= sdmmc_io_read_1(sf, reg++) << 8;
-                       cis->product = sdmmc_io_read_1(sf, reg++);
-                       cis->product |= sdmmc_io_read_1(sf, reg++) << 8;
+                       cis->manufacturer = sdmmc_io_read_1(sf0, reg++);
+                       cis->manufacturer |= sdmmc_io_read_1(sf0, reg++) << 8;
+                       cis->product = sdmmc_io_read_1(sf0, reg++);
+                       cis->product |= sdmmc_io_read_1(sf0, reg++) << 8;
                        break;
                case SD_IO_CISTPL_VERS_1:
                        if (tpllen < 2) {
@@ -123,12 +116,12 @@ sdmmc_read_cis(struct sdmmc_function *sf
                        {
                                int start, i, ch, count;
 
-                               cis->cis1_major = sdmmc_io_read_1(sf, reg++);
-                               cis->cis1_minor = sdmmc_io_read_1(sf, reg++);
+                               cis->cis1_major = sdmmc_io_read_1(sf0, reg++);
+                               cis->cis1_minor = sdmmc_io_read_1(sf0, reg++);
 
                                for (count = 0, start = 0, i = 0;
                                     (count < 4) && ((i + 4) < 256); i++) {
-                                       ch = sdmmc_io_read_1(sf, reg + i);
+                                       ch = sdmmc_io_read_1(sf0, reg + i);
                                        if (ch == 0xff)
                                                break;
                                        cis->cis1_info_buf[i] = ch;
@@ -178,8 +171,8 @@ sdmmc_print_cis(struct sdmmc_function *s
 
        printf("%s: function %d: ", DEVNAME(sf->sc), sf->number);
        switch (sf->cis.function) {
-       case SDMMC_FUNCTION_WLAN:
-               printf("wireless network adapter");
+       case TPLFID_FUNCTION_SDIO:
+               printf("SDIO");
                break;
        default:
                printf("unknown (%d)", sf->cis.function);
Index: sdmmc_io.c
===================================================================
RCS file: /cvs/src/sys/dev/sdmmc/sdmmc_io.c,v
retrieving revision 1.22
diff -u -p -r1.22 sdmmc_io.c
--- sdmmc_io.c  14 Mar 2015 03:38:49 -0000      1.22
+++ sdmmc_io.c  19 Apr 2016 21:20:47 -0000
@@ -171,21 +171,17 @@ sdmmc_io_init(struct sdmmc_softc *sc, st
 {
        rw_assert_wrlock(&sc->sc_lock);
 
-       if (sf->number == 0) {
-               sdmmc_io_write_1(sf, SD_IO_CCCR_BUS_WIDTH,
-                   CCCR_BUS_WIDTH_1);
+       if (sdmmc_read_cis(sf, &sf->cis) != 0) {
+               printf("%s: can't read CIS\n", DEVNAME(sc));
+               SET(sf->flags, SFF_ERROR);
+               return 1;
+       }
 
-               if (sdmmc_read_cis(sf, &sf->cis) != 0) {
-                       printf("%s: can't read CIS\n", DEVNAME(sc));
-                       SET(sf->flags, SFF_ERROR);
-                       return 1;
-               }
+       sdmmc_check_cis_quirks(sf);
 
-               sdmmc_check_cis_quirks(sf);
+       if (sdmmc_verbose)
+               sdmmc_print_cis(sf);
 
-               if (sdmmc_verbose)
-                       sdmmc_print_cis(sf);
-       }
        return 0;
 }
 
Index: sdmmc_ioreg.h
===================================================================
RCS file: /cvs/src/sys/dev/sdmmc/sdmmc_ioreg.h,v
retrieving revision 1.5
diff -u -p -r1.5 sdmmc_ioreg.h
--- sdmmc_ioreg.h       11 Jan 2016 07:32:38 -0000      1.5
+++ sdmmc_ioreg.h       19 Apr 2016 21:20:47 -0000
@@ -69,8 +69,9 @@
 #define SD_IO_CCCR_CTL                 0x06
 #define  CCCR_CTL_RES                  (1<<3)
 #define SD_IO_CCCR_BUS_WIDTH           0x07
-#define  CCCR_BUS_WIDTH_4              (1<<1)
-#define  CCCR_BUS_WIDTH_1              (1<<0)
+#define  CCCR_BUS_WIDTH_1              (0<<0)
+#define  CCCR_BUS_WIDTH_4              (2<<0)
+#define  CCCR_BUS_WIDTH_8              (3<<0)
 #define SD_IO_CCCR_CISPTR              0x09 /* XXX 9-10, 10-11, or 9-12 */
 
 /* Function Basic Registers (FBR) */
@@ -90,6 +91,6 @@
 #define SD_IO_CISTPL_END               0xff
 
 /* CISTPL_FUNCID codes */
-#define SDMMC_FUNCTION_WLAN            0x0c
+#define TPLFID_FUNCTION_SDIO           0x0c
 
 #endif

Reply via email to