Page MenuHomeFreeBSD

D19749.diff
No OneTemporary

D19749.diff

Index: head/sys/conf/files
===================================================================
--- head/sys/conf/files
+++ head/sys/conf/files
@@ -68,6 +68,16 @@
compile-with "${AWK} -f $S/tools/usbdevs2h.awk $S/dev/usb/usbdevs -d" \
no-obj no-implicit-rule before-depend \
clean "usbdevs_data.h"
+sdiodevs.h optional mmccam \
+ dependency "$S/tools/sdiodevs2h.awk $S/dev/sdio/sdiodevs" \
+ compile-with "${AWK} -f $S/tools/sdiodevs2h.awk $S/dev/sdio/sdiodevs -h" \
+ no-obj no-implicit-rule before-depend \
+ clean "sdiodevs.h"
+sdiodevs_data.h optional mmccam \
+ dependency "$S/tools/sdiodevs2h.awk $S/dev/sdio/sdiodevs" \
+ compile-with "${AWK} -f $S/tools/sdiodevs2h.awk $S/dev/sdio/sdiodevs -d" \
+ no-obj no-implicit-rule before-depend \
+ clean "sdiodevs_data.h"
cam/cam.c optional scbus
cam/cam_compat.c optional scbus
cam/cam_iosched.c optional scbus
@@ -3009,6 +3019,9 @@
dev/sdhci/sdhci_if.m optional sdhci
dev/sdhci/sdhci_acpi.c optional sdhci acpi
dev/sdhci/sdhci_pci.c optional sdhci pci
++dev/sdio/sdio_if.m optional mmccam
++dev/sdio/sdio_subr.c optional mmccam
++dev/sdio/sdiob.c optional mmccam
dev/sge/if_sge.c optional sge pci
dev/siis/siis.c optional siis pci
dev/sis/if_sis.c optional sis pci
Index: head/sys/conf/kmod.mk
===================================================================
--- head/sys/conf/kmod.mk
+++ head/sys/conf/kmod.mk
@@ -475,6 +475,18 @@
${AWK} -f ${SYSDIR}/tools/usbdevs2h.awk ${SYSDIR}/dev/usb/usbdevs -d
.endif
+.if !empty(SRCS:Msdiodevs.h)
+CLEANFILES+= sdiodevs.h
+sdiodevs.h: ${SYSDIR}/tools/sdiodevs2h.awk ${SYSDIR}/dev/sdio/sdiodevs
+ ${AWK} -f ${SYSDIR}/tools/sdiodevs2h.awk ${SYSDIR}/dev/sdio/sdiodevs -h
+.endif
+
+.if !empty(SRCS:Msdiodevs_data.h)
+CLEANFILES+= sdiodevs_data.h
+sdiodevs_data.h: ${SYSDIR}/tools/sdiodevs2h.awk ${SYSDIR}/dev/sdio/sdiodevs
+ ${AWK} -f ${SYSDIR}/tools/sdiodevs2h.awk ${SYSDIR}/dev/sdio/sdiodevs -d
+.endif
+
.if !empty(SRCS:Macpi_quirks.h)
CLEANFILES+= acpi_quirks.h
acpi_quirks.h: ${SYSDIR}/tools/acpi_quirks2h.awk ${SYSDIR}/dev/acpica/acpi_quirks
Index: head/sys/dev/sdio/sdio_if.m
===================================================================
--- head/sys/dev/sdio/sdio_if.m
+++ head/sys/dev/sdio/sdio_if.m
@@ -0,0 +1,79 @@
+#-
+# Copyright (c) 2019 The FreeBSD Foundation
+#
+# Portions of this software were developed by Björn Zeeb
+# under sponsorship from the FreeBSD Foundation.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+# $FreeBSD$
+#
+
+#include <sys/bus.h>
+#include <machine/bus.h>
+
+INTERFACE sdio;
+
+#
+# READ DIRECT (1byte)
+#
+METHOD int read_direct {
+ device_t dev;
+ uint8_t fn;
+ uint32_t addr;
+ uint8_t *val;
+};
+
+#
+# WRITE DIRECT (1byte)
+#
+METHOD int write_direct {
+ device_t dev;
+ uint8_t fn;
+ uint32_t addr;
+ uint8_t val;
+};
+
+#
+# READ EXTENDED
+#
+METHOD int read_extended {
+ device_t dev;
+ uint8_t fn;
+ uint32_t addr;
+ uint32_t size;
+ uint8_t *buffer;
+ bool incaddr;
+};
+
+#
+# WRITE EXTENDED
+#
+METHOD int write_extended {
+ device_t dev;
+ uint8_t fn;
+ uint32_t addr;
+ uint32_t size;
+ uint8_t *buffer;
+ bool incaddr;
+};
+
+# end
Index: head/sys/dev/sdio/sdio_subr.h
===================================================================
--- head/sys/dev/sdio/sdio_subr.h
+++ head/sys/dev/sdio/sdio_subr.h
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 2017 Ilya Bakulin. All rights reserved.
+ * Copyright (c) 2018-2019 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Björn Zeeb
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Portions of this software may have been developed with reference to
+ * the SD Simplified Specification. The following disclaimer may apply:
+ *
+ * The following conditions apply to the release of the simplified
+ * specification ("Simplified Specification") by the SD Card Association and
+ * the SD Group. The Simplified Specification is a subset of the complete SD
+ * Specification which is owned by the SD Card Association and the SD
+ * Group. This Simplified Specification is provided on a non-confidential
+ * basis subject to the disclaimers below. Any implementation of the
+ * Simplified Specification may require a license from the SD Card
+ * Association, SD Group, SD-3C LLC or other third parties.
+ *
+ * Disclaimers:
+ *
+ * The information contained in the Simplified Specification is presented only
+ * as a standard specification for SD Cards and SD Host/Ancillary products and
+ * is provided "AS-IS" without any representations or warranties of any
+ * kind. No responsibility is assumed by the SD Group, SD-3C LLC or the SD
+ * Card Association for any damages, any infringements of patents or other
+ * right of the SD Group, SD-3C LLC, the SD Card Association or any third
+ * parties, which may result from its use. No license is granted by
+ * implication, estoppel or otherwise under any patent or other rights of the
+ * SD Group, SD-3C LLC, the SD Card Association or any third party. Nothing
+ * herein shall be construed as an obligation by the SD Group, the SD-3C LLC
+ * or the SD Card Association to disclose or distribute any technical
+ * information, know-how or other confidential information to any third party.
+ *
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SDIO_SUBR_H_
+#define _SDIO_SUBR_H_
+
+/*
+ * This file contains structures and functions to work with SDIO cards.
+ */
+
+struct sdio_func {
+ device_t dev; /* The device to talk to CAM. */
+ uintptr_t drvdata; /* Driver specific data. */
+
+ uint8_t fn; /* Function number. */
+
+ uint8_t class; /* Class of function. */
+ uint16_t vendor; /* Manufacturer ID. */
+ uint16_t device; /* Card ID. */
+
+ uint16_t max_blksize; /* Maximum block size of function. */
+ uint16_t cur_blksize; /* Current block size of function. */
+
+ uint16_t retries; /* Retires for CAM operations. */
+ uint32_t timeout; /* Timeout. */
+};
+
+struct card_info {
+ struct sdio_func f[8];
+
+ /* Compared to R4 Number of I/O Functions we DO count F0 here. */
+ uint8_t num_funcs;
+
+ bool support_multiblk; /* Support Multiple Block Transfer */
+};
+
+#ifdef _KERNEL
+int sdio_enable_func(struct sdio_func *);
+int sdio_disable_func(struct sdio_func *);
+int sdio_set_block_size(struct sdio_func *, uint16_t);
+
+uint8_t sdio_readb(struct sdio_func *, uint32_t, int *);
+void sdio_writeb(struct sdio_func *, uint8_t, uint32_t, int *);
+uint32_t sdio_readl(struct sdio_func *, uint32_t, int *);
+void sdio_writel(struct sdio_func *, uint32_t, uint32_t, int *);
+
+uint8_t sdio_f0_readb(struct sdio_func *, uint32_t, int *);
+void sdio_f0_writeb(struct sdio_func *, uint8_t, uint32_t, int *);
+#endif /* _KERNEL */
+
+#endif /* _SDIO_SUBR_H_ */
Index: head/sys/dev/sdio/sdio_subr.c
===================================================================
--- head/sys/dev/sdio/sdio_subr.c
+++ head/sys/dev/sdio/sdio_subr.c
@@ -0,0 +1,227 @@
+/*-
+ * Copyright (c) 2017 Ilya Bakulin. All rights reserved.
+ * Copyright (c) 2018-2019 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Björn Zeeb
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Portions of this software may have been developed with reference to
+ * the SD Simplified Specification. The following disclaimer may apply:
+ *
+ * The following conditions apply to the release of the simplified
+ * specification ("Simplified Specification") by the SD Card Association and
+ * the SD Group. The Simplified Specification is a subset of the complete SD
+ * Specification which is owned by the SD Card Association and the SD
+ * Group. This Simplified Specification is provided on a non-confidential
+ * basis subject to the disclaimers below. Any implementation of the
+ * Simplified Specification may require a license from the SD Card
+ * Association, SD Group, SD-3C LLC or other third parties.
+ *
+ * Disclaimers:
+ *
+ * The information contained in the Simplified Specification is presented only
+ * as a standard specification for SD Cards and SD Host/Ancillary products and
+ * is provided "AS-IS" without any representations or warranties of any
+ * kind. No responsibility is assumed by the SD Group, SD-3C LLC or the SD
+ * Card Association for any damages, any infringements of patents or other
+ * right of the SD Group, SD-3C LLC, the SD Card Association or any third
+ * parties, which may result from its use. No license is granted by
+ * implication, estoppel or otherwise under any patent or other rights of the
+ * SD Group, SD-3C LLC, the SD Card Association or any third party. Nothing
+ * herein shall be construed as an obligation by the SD Group, the SD-3C LLC
+ * or the SD Card Association to disclose or distribute any technical
+ * information, know-how or other confidential information to any third party.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/kernel.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+
+#include <dev/mmc/mmcreg.h>
+
+#include <dev/sdio/sdiob.h>
+#include <dev/sdio/sdio_subr.h>
+
+#include "sdio_if.h"
+
+/* Works on F0. */
+static int
+sdio_set_bool_for_func(device_t dev, uint32_t addr, uint8_t fn, bool enable)
+{
+ device_t pdev;
+ int error;
+ uint8_t val;
+ bool enabled;
+
+ pdev = device_get_parent(dev);
+ error = SDIO_READ_DIRECT(pdev, 0, addr, &val);
+ if (error != 0)
+ return (error);
+
+ enabled = (val & (1 << fn)) ? true : false;
+ if (enabled == enable)
+ return (0);
+
+ if (enable)
+ val |= (1 << fn);
+ else
+ val &= ~(1 << fn);
+ error = SDIO_WRITE_DIRECT(pdev, 0, addr, val);
+ return (error);
+}
+
+int
+sdio_enable_func(struct sdio_func *f)
+{
+
+ return (sdio_set_bool_for_func(f->dev, SD_IO_CCCR_FN_ENABLE,
+ f->fn, true));
+}
+
+int
+sdio_disable_func(struct sdio_func *f)
+{
+
+ return (sdio_set_bool_for_func(f->dev, SD_IO_CCCR_FN_ENABLE,
+ f->fn, false));
+}
+
+int
+sdio_set_block_size(struct sdio_func *f, uint16_t bs)
+{
+ device_t pdev;
+ int error;
+ uint32_t addr;
+ uint16_t v;
+
+ if (!sdio_get_support_multiblk(f->dev))
+ return (EOPNOTSUPP);
+
+ pdev = device_get_parent(f->dev);
+ addr = SD_IO_FBR_START * f->fn + SD_IO_FBR_IOBLKSZ;
+ v = htole16(bs);
+ /* Always write through F0. */
+ error = SDIO_WRITE_DIRECT(pdev, 0, addr, v & 0xff);
+ if (error == 0)
+ error = SDIO_WRITE_DIRECT(pdev, 0, addr + 1,
+ (v >> 8) & 0xff);
+ if (error == 0)
+ f->cur_blksize = bs;
+
+ return (error);
+}
+
+uint8_t
+sdio_readb(struct sdio_func *f, uint32_t addr, int *err)
+{
+ int error;
+ uint8_t v;
+
+ error = SDIO_READ_DIRECT(device_get_parent(f->dev), f->fn, addr, &v);
+ if (error) {
+ if (err != NULL)
+ *err = error;
+ return (0xff);
+ } else {
+ if (err != NULL)
+ *err = 0;
+ return (v);
+ }
+}
+
+void
+sdio_writeb(struct sdio_func *f, uint8_t val, uint32_t addr, int *err)
+{
+ int error;
+
+ error = SDIO_WRITE_DIRECT(device_get_parent(f->dev), f->fn, addr, val);
+ if (err != NULL)
+ *err = error;
+}
+
+uint32_t
+sdio_readl(struct sdio_func *f, uint32_t addr, int *err)
+{
+ int error;
+ uint32_t v;
+
+ error = SDIO_READ_EXTENDED(device_get_parent(f->dev), f->fn, addr,
+ sizeof(v), (uint8_t *)&v, false);
+ if (error) {
+ if (err != NULL)
+ *err = error;
+ return (0xffffffff);
+ } else {
+ if (err != NULL)
+ *err = 0;
+ return (le32toh(v));
+ }
+}
+
+void
+sdio_writel(struct sdio_func *f, uint32_t val, uint32_t addr, int *err)
+{
+ int error;
+
+ error = SDIO_WRITE_EXTENDED(device_get_parent(f->dev), f->fn, addr,
+ sizeof(val), (uint8_t *)&val, false);
+ if (err != NULL)
+ *err = error;
+}
+
+uint8_t
+sdio_f0_readb(struct sdio_func *f, uint32_t addr, int *err)
+{
+ int error;
+ uint8_t v;
+
+ error = SDIO_READ_DIRECT(device_get_parent(f->dev), 0, addr, &v);
+ if (error) {
+ if (err != NULL)
+ *err = error;
+ return (0xff);
+ } else {
+ if (err != NULL)
+ *err = 0;
+ return (v);
+ }
+}
+
+void
+sdio_f0_writeb(struct sdio_func *f, uint8_t val, uint32_t addr, int *err)
+{
+ int error;
+
+ error = SDIO_WRITE_DIRECT(device_get_parent(f->dev), 0, addr, val);
+ if (err != NULL)
+ *err = error;
+}
+
+/* end */
Index: head/sys/dev/sdio/sdiob.h
===================================================================
--- head/sys/dev/sdio/sdiob.h
+++ head/sys/dev/sdio/sdiob.h
@@ -0,0 +1,92 @@
+/*-
+ * Copyright (c) 2019 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Björn Zeeb
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Portions of this software may have been developed with reference to
+ * the SD Simplified Specification. The following disclaimer may apply:
+ *
+ * The following conditions apply to the release of the simplified
+ * specification ("Simplified Specification") by the SD Card Association and
+ * the SD Group. The Simplified Specification is a subset of the complete SD
+ * Specification which is owned by the SD Card Association and the SD
+ * Group. This Simplified Specification is provided on a non-confidential
+ * basis subject to the disclaimers below. Any implementation of the
+ * Simplified Specification may require a license from the SD Card
+ * Association, SD Group, SD-3C LLC or other third parties.
+ *
+ * Disclaimers:
+ *
+ * The information contained in the Simplified Specification is presented only
+ * as a standard specification for SD Cards and SD Host/Ancillary products and
+ * is provided "AS-IS" without any representations or warranties of any
+ * kind. No responsibility is assumed by the SD Group, SD-3C LLC or the SD
+ * Card Association for any damages, any infringements of patents or other
+ * right of the SD Group, SD-3C LLC, the SD Card Association or any third
+ * parties, which may result from its use. No license is granted by
+ * implication, estoppel or otherwise under any patent or other rights of the
+ * SD Group, SD-3C LLC, the SD Card Association or any third party. Nothing
+ * herein shall be construed as an obligation by the SD Group, the SD-3C LLC
+ * or the SD Card Association to disclose or distribute any technical
+ * information, know-how or other confidential information to any third party.
+ *
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SDIOB_H
+#define _SDIOB_H
+
+#define SDIOB_NAME sdiob
+#define _SDIOB_NAME_S(x) __STRING(x)
+#define SDIOB_NAME_S _SDIOB_NAME_S(SDIOB_NAME)
+
+#ifdef _SYS_BUS_H_
+/* Ivars for sdiob. */
+enum sdiob_dev_enum {
+ SDIOB_IVAR_SUPPORT_MULTIBLK,
+ SDIOB_IVAR_FUNCTION,
+ SDIOB_IVAR_FUNCNUM,
+ SDIOB_IVAR_CLASS,
+ SDIOB_IVAR_VENDOR,
+ SDIOB_IVAR_DEVICE,
+ SDIOB_IVAR_DRVDATA,
+};
+
+#define SDIOB_ACCESSOR(var, ivar, type) \
+ __BUS_ACCESSOR(sdio, var, SDIOB, ivar, type)
+
+SDIOB_ACCESSOR(support_multiblk,SUPPORT_MULTIBLK, bool)
+SDIOB_ACCESSOR(function, FUNCTION, struct sdio_func *)
+SDIOB_ACCESSOR(funcnum, FUNCNUM, uint8_t)
+SDIOB_ACCESSOR(class, CLASS, uint8_t)
+SDIOB_ACCESSOR(vendor, VENDOR, uint16_t)
+SDIOB_ACCESSOR(device, DEVICE, uint16_t)
+SDIOB_ACCESSOR(drvdata, DRVDATA, void *)
+
+#undef SDIOB_ACCESSOR
+#endif /* _SYS_BUS_H_ */
+
+#endif /* _SDIOB_H */
Index: head/sys/dev/sdio/sdiob.c
===================================================================
--- head/sys/dev/sdio/sdiob.c
+++ head/sys/dev/sdio/sdiob.c
@@ -0,0 +1,1188 @@
+/*-
+ * Copyright (c) 2017 Ilya Bakulin. All rights reserved.
+ * Copyright (c) 2018-2019 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Björn Zeeb
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *
+ * Portions of this software may have been developed with reference to
+ * the SD Simplified Specification. The following disclaimer may apply:
+ *
+ * The following conditions apply to the release of the simplified
+ * specification ("Simplified Specification") by the SD Card Association and
+ * the SD Group. The Simplified Specification is a subset of the complete SD
+ * Specification which is owned by the SD Card Association and the SD
+ * Group. This Simplified Specification is provided on a non-confidential
+ * basis subject to the disclaimers below. Any implementation of the
+ * Simplified Specification may require a license from the SD Card
+ * Association, SD Group, SD-3C LLC or other third parties.
+ *
+ * Disclaimers:
+ *
+ * The information contained in the Simplified Specification is presented only
+ * as a standard specification for SD Cards and SD Host/Ancillary products and
+ * is provided "AS-IS" without any representations or warranties of any
+ * kind. No responsibility is assumed by the SD Group, SD-3C LLC or the SD
+ * Card Association for any damages, any infringements of patents or other
+ * right of the SD Group, SD-3C LLC, the SD Card Association or any third
+ * parties, which may result from its use. No license is granted by
+ * implication, estoppel or otherwise under any patent or other rights of the
+ * SD Group, SD-3C LLC, the SD Card Association or any third party. Nothing
+ * herein shall be construed as an obligation by the SD Group, the SD-3C LLC
+ * or the SD Card Association to disclose or distribute any technical
+ * information, know-how or other confidential information to any third party.
+ */
+/*
+ * Implements the (kernel specific) SDIO parts.
+ * This will hide all cam(4) functionality from the SDIO driver implementations
+ * which will just be newbus/device(9) and hence look like any other driver for,
+ * e.g., PCI.
+ * The sdiob(4) parts effetively "translate" between the two worlds "bridging"
+ * messages from MMCCAM to newbus and back.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "opt_cam.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/endian.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+
+#include <cam/cam.h>
+#include <cam/cam_ccb.h>
+#include <cam/cam_queue.h>
+#include <cam/cam_periph.h>
+#include <cam/cam_xpt.h>
+#include <cam/cam_xpt_periph.h>
+#include <cam/cam_xpt_internal.h> /* for cam_path */
+#include <cam/cam_debug.h>
+
+#include <dev/mmc/mmcreg.h>
+
+#include <dev/sdio/sdiob.h>
+#include <dev/sdio/sdio_subr.h>
+
+#include "sdio_if.h"
+
+#ifdef DEBUG
+#define DPRINTF(...) printf(__VA_ARGS__)
+#define DPRINTFDEV(_dev, ...) device_printf((_dev), __VA_ARGS__)
+#else
+#define DPRINTF(...)
+#define DPRINTFDEV(_dev, ...)
+#endif
+
+struct sdiob_softc {
+ uint32_t sdio_state;
+#define SDIO_STATE_DEAD 0x0001
+#define SDIO_STATE_INITIALIZING 0x0002
+#define SDIO_STATE_READY 0x0004
+ uint32_t nb_state;
+#define NB_STATE_DEAD 0x0001
+#define NB_STATE_SIM_ADDED 0x0002
+#define NB_STATE_READY 0x0004
+
+ /* CAM side (including sim_dev). */
+ struct card_info cardinfo;
+ struct cam_periph *periph;
+ union ccb *ccb;
+ struct task discover_task;
+
+ /* Newbus side. */
+ device_t dev; /* Ourselves. */
+ device_t child[8];
+};
+
+/* -------------------------------------------------------------------------- */
+/*
+ * SDIO CMD52 and CM53 implementations along with wrapper functions for
+ * read/write and a CAM periph helper function.
+ * These are the backend implementations of the sdio_if.m framework talking
+ * through CAM to sdhci.
+ * Note: these functions are also called during early discovery stage when
+ * we are not a device(9) yet. Hence they cannot always use device_printf()
+ * to log errors and have to call CAM_DEBUG() during these early stages.
+ */
+
+static int
+sdioerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
+{
+
+ return (cam_periph_error(ccb, cam_flags, sense_flags));
+}
+
+/* CMD52: direct byte access. */
+static int
+sdiob_rw_direct_sc(struct sdiob_softc *sc, uint8_t fn, uint32_t addr, bool wr,
+ uint8_t *val)
+{
+ uint32_t arg, flags;
+ int error;
+
+ KASSERT((val != NULL), ("%s val passed as NULL\n", __func__));
+
+ if (sc->ccb == NULL)
+ sc->ccb = xpt_alloc_ccb();
+ else
+ memset(sc->ccb, 0, sizeof(*sc->ccb));
+ xpt_setup_ccb(&sc->ccb->ccb_h, sc->periph->path, CAM_PRIORITY_NONE);
+ CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_TRACE,
+ ("%s(fn=%d, addr=%#02x, wr=%d, *val=%#02x)\n", __func__,
+ fn, addr, wr, *val));
+
+ flags = MMC_RSP_R5 | MMC_CMD_AC;
+ arg = SD_IO_RW_FUNC(fn) | SD_IO_RW_ADR(addr);
+ if (wr)
+ arg |= SD_IO_RW_WR | SD_IO_RW_RAW | SD_IO_RW_DAT(*val);
+
+ cam_fill_mmcio(&sc->ccb->mmcio,
+ /*retries*/ 0,
+ /*cbfcnp*/ NULL,
+ /*flags*/ CAM_DIR_NONE,
+ /*mmc_opcode*/ SD_IO_RW_DIRECT,
+ /*mmc_arg*/ arg,
+ /*mmc_flags*/ flags,
+ /*mmc_data*/ 0,
+ /*timeout*/ sc->cardinfo.f[fn].timeout);
+ error = cam_periph_runccb(sc->ccb, sdioerror, CAM_FLAG_NONE, 0, NULL);
+ if (error != 0) {
+ if (sc->dev != NULL)
+ device_printf(sc->dev,
+ "%s: Failed to %s address %#10x error=%d\n",
+ __func__, (wr) ? "write" : "read", addr, error);
+ else
+ CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_INFO,
+ ("%s: Failed to %s address: %#10x error=%d\n",
+ __func__, (wr) ? "write" : "read", addr, error));
+ return (error);
+ }
+
+ /* TODO: Add handling of MMC errors */
+ /* ccb->mmcio.cmd.error ? */
+ if (wr == false)
+ *val = sc->ccb->mmcio.cmd.resp[0] & 0xff;
+
+ return (0);
+}
+
+static int
+sdio_rw_direct(device_t dev, uint8_t fn, uint32_t addr, bool wr,
+ uint8_t *val)
+{
+ struct sdiob_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+ cam_periph_lock(sc->periph);
+ error = sdiob_rw_direct_sc(sc, fn, addr, wr, val);
+ cam_periph_unlock(sc->periph);
+ return (error);
+}
+
+static int
+sdiob_read_direct(device_t dev, uint8_t fn, uint32_t addr, uint8_t *val)
+{
+ int error;
+ uint8_t v;
+
+ error = sdio_rw_direct(dev, fn, addr, false, &v);
+ /* Be polite and do not touch the value on read error. */
+ if (error == 0 && val != NULL)
+ *val = v;
+ return (error);
+}
+
+static int
+sdiob_write_direct(device_t dev, uint8_t fn, uint32_t addr, uint8_t val)
+{
+
+ return (sdio_rw_direct(dev, fn, addr, true, &val));
+}
+
+/*
+ * CMD53: IO_RW_EXTENDED, read and write multiple I/O registers.
+ * Increment false gets FIFO mode (single register address).
+ */
+/*
+ * A b_count of 0 means byte mode, b_count > 0 gets block mode.
+ * A b_count of >= 512 would mean infinitive block transfer, which would become
+ * b_count = 0, is not yet supported.
+ * For b_count == 0, blksz is the len of bytes, otherwise it is the amount of
+ * full sized blocks (you must not round the blocks up and leave the last one
+ * partial!)
+ * For byte mode, the maximum of blksz is the functions cur_blksize.
+ * This function should ever only be called by sdio_rw_extended_sc()!
+ */
+static int
+sdiob_rw_extended_cam(struct sdiob_softc *sc, uint8_t fn, uint32_t addr,
+ bool wr, uint8_t *buffer, bool incaddr, uint32_t b_count, uint16_t blksz)
+{
+ struct mmc_data mmcd;
+ uint32_t arg, cam_flags, flags, len;
+ int error;
+
+ if (sc->ccb == NULL)
+ sc->ccb = xpt_alloc_ccb();
+ else
+ memset(sc->ccb, 0, sizeof(*sc->ccb));
+ xpt_setup_ccb(&sc->ccb->ccb_h, sc->periph->path, CAM_PRIORITY_NONE);
+ CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_TRACE,
+ ("%s(fn=%d addr=%#0x wr=%d b_count=%u blksz=%u buf=%p incr=%d)\n",
+ __func__, fn, addr, wr, b_count, blksz, buffer, incaddr));
+
+ KASSERT((b_count <= 511), ("%s: infinitive block transfer not yet "
+ "supported: b_count %u blksz %u, sc %p, fn %u, addr %#10x, %s, "
+ "buffer %p, %s\n", __func__, b_count, blksz, sc, fn, addr,
+ wr ? "wr" : "rd", buffer, incaddr ? "incaddr" : "fifo"));
+ /* Blksz needs to be within bounds for both byte and block mode! */
+ KASSERT((blksz <= sc->cardinfo.f[fn].cur_blksize), ("%s: blksz "
+ "%u > bur_blksize %u, sc %p, fn %u, addr %#10x, %s, "
+ "buffer %p, %s, b_count %u\n", __func__, blksz,
+ sc->cardinfo.f[fn].cur_blksize, sc, fn, addr,
+ wr ? "wr" : "rd", buffer, incaddr ? "incaddr" : "fifo",
+ b_count));
+ if (b_count == 0) {
+ /* Byte mode */
+ len = blksz;
+ if (blksz == 512)
+ blksz = 0;
+ arg = SD_IOE_RW_LEN(blksz);
+ } else {
+ /* Block mode. */
+#ifdef __notyet__
+ if (b_count > 511) {
+ /* Infinitive block transfer. */
+ b_count = 0;
+ }
+#endif
+ len = b_count * blksz;
+ arg = SD_IOE_RW_BLK | SD_IOE_RW_LEN(b_count);
+ }
+
+ flags = MMC_RSP_R5 | MMC_CMD_ADTC;
+ arg |= SD_IOE_RW_FUNC(fn) | SD_IOE_RW_ADR(addr);
+ if (incaddr)
+ arg |= SD_IOE_RW_INCR;
+
+ memset(&mmcd, 0, sizeof(mmcd));
+ mmcd.data = buffer;
+ mmcd.len = len;
+ if (arg & SD_IOE_RW_BLK) {
+ /* XXX both should be known from elsewhere, aren't they? */
+ mmcd.block_size = blksz;
+ mmcd.block_count = b_count;
+ }
+
+ if (wr) {
+ arg |= SD_IOE_RW_WR;
+ cam_flags = CAM_DIR_OUT;
+ mmcd.flags = MMC_DATA_WRITE;
+ } else {
+ cam_flags = CAM_DIR_IN;
+ mmcd.flags = MMC_DATA_READ;
+ }
+#ifdef __notyet__
+ if (b_count == 0) {
+ /* XXX-BZ TODO FIXME. Cancel I/O: CCCR -> ASx */
+ /* Stop cmd. */
+ }
+#endif
+ cam_fill_mmcio(&sc->ccb->mmcio,
+ /*retries*/ 0,
+ /*cbfcnp*/ NULL,
+ /*flags*/ cam_flags,
+ /*mmc_opcode*/ SD_IO_RW_EXTENDED,
+ /*mmc_arg*/ arg,
+ /*mmc_flags*/ flags,
+ /*mmc_data*/ &mmcd,
+ /*timeout*/ sc->cardinfo.f[fn].timeout);
+ if (arg & SD_IOE_RW_BLK) {
+ mmcd.flags |= MMC_DATA_BLOCK_SIZE;
+ if (b_count != 1)
+ sc->ccb->mmcio.cmd.data->flags |= MMC_DATA_MULTI;
+ }
+
+ /* Execute. */
+ error = cam_periph_runccb(sc->ccb, sdioerror, CAM_FLAG_NONE, 0, NULL);
+ if (error != 0) {
+ if (sc->dev != NULL)
+ device_printf(sc->dev,
+ "%s: Failed to %s address %#10x buffer %p size %u "
+ "%s b_count %u blksz %u error=%d\n",
+ __func__, (wr) ? "write to" : "read from", addr,
+ buffer, len, (incaddr) ? "incr" : "fifo",
+ b_count, blksz, error);
+ else
+ CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_INFO,
+ ("%s: Failed to %s address %#10x buffer %p size %u "
+ "%s b_count %u blksz %u error=%d\n",
+ __func__, (wr) ? "write to" : "read from", addr,
+ buffer, len, (incaddr) ? "incr" : "fifo",
+ b_count, blksz, error));
+ return (error);
+ }
+
+ /* TODO: Add handling of MMC errors */
+ /* ccb->mmcio.cmd.error ? */
+ error = sc->ccb->mmcio.cmd.resp[0] & 0xff;
+ if (error != 0) {
+ if (sc->dev != NULL)
+ device_printf(sc->dev,
+ "%s: Failed to %s address %#10x buffer %p size %u "
+ "%s b_count %u blksz %u mmcio resp error=%d\n",
+ __func__, (wr) ? "write to" : "read from", addr,
+ buffer, len, (incaddr) ? "incr" : "fifo",
+ b_count, blksz, error);
+ else
+ CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_INFO,
+ ("%s: Failed to %s address %#10x buffer %p size %u "
+ "%s b_count %u blksz %u mmcio resp error=%d\n",
+ __func__, (wr) ? "write to" : "read from", addr,
+ buffer, len, (incaddr) ? "incr" : "fifo",
+ b_count, blksz, error));
+ }
+ return (error);
+}
+
+static int
+sdiob_rw_extended_sc(struct sdiob_softc *sc, uint8_t fn, uint32_t addr,
+ bool wr, uint32_t size, uint8_t *buffer, bool incaddr)
+{
+ int error;
+ uint32_t len;
+ uint32_t b_count;
+
+ /*
+ * If block mode is supported and we have at least 4 bytes to write and
+ * the size is at least one block, then start doing blk transfers.
+ */
+ while (sc->cardinfo.support_multiblk &&
+ size > 4 && size >= sc->cardinfo.f[fn].cur_blksize) {
+
+ b_count = size / sc->cardinfo.f[fn].cur_blksize;
+ KASSERT(b_count >= 1, ("%s: block count too small %u size %u "
+ "cur_blksize %u\n", __func__, b_count, size,
+ sc->cardinfo.f[fn].cur_blksize));
+
+#ifdef __notyet__
+ /* XXX support inifinite transfer with b_count = 0. */
+#else
+ if (b_count > 511)
+ b_count = 511;
+#endif
+ len = b_count * sc->cardinfo.f[fn].cur_blksize;
+ error = sdiob_rw_extended_cam(sc, fn, addr, wr, buffer, incaddr,
+ b_count, sc->cardinfo.f[fn].cur_blksize);
+ if (error != 0)
+ return (error);
+
+ size -= len;
+ buffer += len;
+ if (incaddr)
+ addr += len;
+ }
+
+ while (size > 0) {
+ len = MIN(size, sc->cardinfo.f[fn].cur_blksize);
+
+ error = sdiob_rw_extended_cam(sc, fn, addr, wr, buffer, incaddr,
+ 0, len);
+ if (error != 0)
+ return (error);
+
+ /* Prepare for next iteration. */
+ size -= len;
+ buffer += len;
+ if (incaddr)
+ addr += len;
+ }
+
+ return (0);
+}
+
+static int
+sdiob_rw_extended(device_t dev, uint8_t fn, uint32_t addr, bool wr,
+ uint32_t size, uint8_t *buffer, bool incaddr)
+{
+ struct sdiob_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+ cam_periph_lock(sc->periph);
+ error = sdiob_rw_extended_sc(sc, fn, addr, wr, size, buffer, incaddr);
+ cam_periph_unlock(sc->periph);
+ return (error);
+}
+
+static int
+sdiob_read_extended(device_t dev, uint8_t fn, uint32_t addr, uint32_t size,
+ uint8_t *buffer, bool incaddr)
+{
+
+ return (sdiob_rw_extended(dev, fn, addr, false, size, buffer, incaddr));
+}
+
+static int
+sdiob_write_extended(device_t dev, uint8_t fn, uint32_t addr, uint32_t size,
+ uint8_t *buffer, bool incaddr)
+{
+
+ return (sdiob_rw_extended(dev, fn, addr, true, size, buffer, incaddr));
+}
+
+/* -------------------------------------------------------------------------- */
+/* Bus interface, ivars handling. */
+
+static int
+sdiob_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
+{
+ struct sdiob_softc *sc;
+ struct sdio_func *f;
+
+ f = device_get_ivars(child);
+ KASSERT(f != NULL, ("%s: dev %p child %p which %d, child ivars NULL\n",
+ __func__, dev, child, which));
+
+ switch (which) {
+ case SDIOB_IVAR_SUPPORT_MULTIBLK:
+ sc = device_get_softc(dev);
+ KASSERT(sc != NULL, ("%s: dev %p child %p which %d, sc NULL\n",
+ __func__, dev, child, which));
+ *result = sc->cardinfo.support_multiblk;
+ break;
+ case SDIOB_IVAR_FUNCTION:
+ *result = (uintptr_t)f;
+ break;
+ case SDIOB_IVAR_FUNCNUM:
+ *result = f->fn;
+ break;
+ case SDIOB_IVAR_CLASS:
+ *result = f->class;
+ break;
+ case SDIOB_IVAR_VENDOR:
+ *result = f->vendor;
+ break;
+ case SDIOB_IVAR_DEVICE:
+ *result = f->device;
+ break;
+ case SDIOB_IVAR_DRVDATA:
+ *result = f->drvdata;
+ break;
+ default:
+ return (ENOENT);
+ }
+ return (0);
+}
+
+static int
+sdiob_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
+{
+ struct sdio_func *f;
+
+ f = device_get_ivars(child);
+ KASSERT(f != NULL, ("%s: dev %p child %p which %d, child ivars NULL\n",
+ __func__, dev, child, which));
+
+ switch (which) {
+ case SDIOB_IVAR_SUPPORT_MULTIBLK:
+ case SDIOB_IVAR_FUNCTION:
+ case SDIOB_IVAR_FUNCNUM:
+ case SDIOB_IVAR_CLASS:
+ case SDIOB_IVAR_VENDOR:
+ case SDIOB_IVAR_DEVICE:
+ return (EINVAL); /* Disallowed. */
+ case SDIOB_IVAR_DRVDATA:
+ f->drvdata = value;
+ break;
+ default:
+ return (ENOENT);
+ }
+
+ return (0);
+}
+
+
+/* -------------------------------------------------------------------------- */
+/*
+ * Newbus functions for ourselves to probe/attach/detach and become a proper
+ * device(9). Attach will also probe for child devices (another driver
+ * implementing SDIO).
+ */
+
+static int
+sdiob_probe(device_t dev)
+{
+
+ device_set_desc(dev, "SDIO CAM-Newbus bridge");
+ return (BUS_PROBE_DEFAULT);
+}
+
+static int
+sdiob_attach(device_t dev)
+{
+ struct sdiob_softc *sc;
+ int error, i;
+
+ sc = device_get_softc(dev);
+ if (sc == NULL)
+ return (ENXIO);
+
+ /*
+ * Now that we are a dev, create one child device per function,
+ * initialize the backpointer, so we can pass them around and
+ * call CAM operations on the parent, and also set the function
+ * itself as ivars, so that we can query/update them.
+ * Do this before any child gets a chance to attach.
+ */
+ for (i = 0; i < sc->cardinfo.num_funcs; i++) {
+
+ sc->child[i] = device_add_child(dev, NULL, -1);
+ if (sc->child[i] == NULL) {
+ device_printf(dev, "%s: failed to add child\n", __func__);
+ return (ENXIO);
+ }
+ sc->cardinfo.f[i].dev = sc->child[i];
+
+ /* Set the function as ivar to the child device. */
+ device_set_ivars(sc->child[i], &sc->cardinfo.f[i]);
+ }
+
+ /*
+ * No one will ever attach to F0; we do the above to have a "device"
+ * to talk to in a general way in the code.
+ * Also do the probe/attach in a 2nd loop, so that all devices are
+ * present as we do have drivers consuming more than one device/func
+ * and might play "tricks" in order to do that assuming devices and
+ * ivars are available for all.
+ */
+ for (i = 1; i < sc->cardinfo.num_funcs; i++) {
+ error = device_probe_and_attach(sc->child[i]);
+ if (error != 0 && bootverbose)
+ device_printf(dev, "%s: device_probe_and_attach(%p %s) "
+ "failed %d for function %d, no child yet\n",
+ __func__,
+ sc->child, device_get_nameunit(sc->child[i]),
+ error, i);
+ }
+
+ sc->nb_state = NB_STATE_READY;
+
+ cam_periph_lock(sc->periph);
+ xpt_announce_periph(sc->periph, NULL);
+ cam_periph_unlock(sc->periph);
+
+ return (0);
+}
+
+static int
+sdiob_detach(device_t dev)
+{
+
+ /* XXX TODO? */
+ return (EOPNOTSUPP);
+}
+
+
+/* -------------------------------------------------------------------------- */
+/*
+ * driver(9) and device(9) "control plane".
+ * This is what we use when we are making ourselves a device(9) in order to
+ * provide a newbus interface again, as well as the implementation of the
+ * SDIO interface.
+ */
+
+static device_method_t sdiob_methods[] = {
+
+ /* Device interface. */
+ DEVMETHOD(device_probe, sdiob_probe),
+ DEVMETHOD(device_attach, sdiob_attach),
+ DEVMETHOD(device_detach, sdiob_detach),
+
+ /* Bus interface. */
+ DEVMETHOD(bus_add_child, bus_generic_add_child),
+ DEVMETHOD(bus_driver_added, bus_generic_driver_added),
+ DEVMETHOD(bus_read_ivar, sdiob_read_ivar),
+ DEVMETHOD(bus_write_ivar, sdiob_write_ivar),
+
+ /* SDIO interface. */
+ DEVMETHOD(sdio_read_direct, sdiob_read_direct),
+ DEVMETHOD(sdio_write_direct, sdiob_write_direct),
+ DEVMETHOD(sdio_read_extended, sdiob_read_extended),
+ DEVMETHOD(sdio_write_extended, sdiob_write_extended),
+
+ DEVMETHOD_END
+};
+
+static devclass_t sdiob_devclass;
+static driver_t sdiob_driver = {
+ SDIOB_NAME_S,
+ sdiob_methods,
+ 0
+};
+
+
+/* -------------------------------------------------------------------------- */
+/*
+ * CIS related.
+ * Read card and function information and populate the cardinfo structure.
+ */
+
+static int
+sdio_read_direct_sc(struct sdiob_softc *sc, uint8_t fn, uint32_t addr,
+ uint8_t *val)
+{
+ int error;
+ uint8_t v;
+
+ error = sdiob_rw_direct_sc(sc, fn, addr, false, &v);
+ if (error == 0 && val != NULL)
+ *val = v;
+ return (error);
+}
+
+static int
+sdio_func_read_cis(struct sdiob_softc *sc, uint8_t fn, uint32_t cis_addr)
+{
+ char cis1_info_buf[256];
+ char *cis1_info[4];
+ int start, i, count, ret;
+ uint32_t addr;
+ uint8_t ch, tuple_id, tuple_len, tuple_count, v;
+
+ /* If we encounter any read errors, abort and return. */
+#define ERR_OUT(ret) \
+ if (ret != 0) \
+ goto err;
+ ret = 0;
+ /* Use to prevent infinite loop in case of parse errors. */
+ tuple_count = 0;
+ memset(cis1_info_buf, 0, 256);
+ do {
+ addr = cis_addr;
+ ret = sdio_read_direct_sc(sc, 0, addr++, &tuple_id);
+ ERR_OUT(ret);
+ if (tuple_id == SD_IO_CISTPL_END)
+ break;
+ if (tuple_id == 0) {
+ cis_addr++;
+ continue;
+ }
+ ret = sdio_read_direct_sc(sc, 0, addr++, &tuple_len);
+ ERR_OUT(ret);
+ if (tuple_len == 0) {
+ CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_PERIPH,
+ ("%s: parse error: 0-length tuple %#02x\n",
+ __func__, tuple_id));
+ return (EIO);
+ }
+
+ switch (tuple_id) {
+ case SD_IO_CISTPL_VERS_1:
+ addr += 2;
+ for (count = 0, start = 0, i = 0;
+ (count < 4) && ((i + 4) < 256); i++) {
+ ret = sdio_read_direct_sc(sc, 0, addr + i, &ch);
+ ERR_OUT(ret);
+ DPRINTF("%s: count=%d, start=%d, i=%d, got "
+ "(%#02x)\n", __func__, count, start, i, ch);
+ if (ch == 0xff)
+ break;
+ cis1_info_buf[i] = ch;
+ if (ch == 0) {
+ cis1_info[count] =
+ cis1_info_buf + start;
+ start = i + 1;
+ count++;
+ }
+ }
+ DPRINTF("Card info: ");
+ for (i=0; i < 4; i++)
+ if (cis1_info[i])
+ DPRINTF(" %s", cis1_info[i]);
+ DPRINTF("\n");
+ break;
+ case SD_IO_CISTPL_MANFID:
+ /* TPLMID_MANF */
+ ret = sdio_read_direct_sc(sc, 0, addr++, &v);
+ ERR_OUT(ret);
+ sc->cardinfo.f[fn].vendor = v;
+ ret = sdio_read_direct_sc(sc, 0, addr++, &v);
+ ERR_OUT(ret);
+ sc->cardinfo.f[fn].vendor |= (v << 8);
+ /* TPLMID_CARD */
+ ret = sdio_read_direct_sc(sc, 0, addr++, &v);
+ ERR_OUT(ret);
+ sc->cardinfo.f[fn].device = v;
+ ret = sdio_read_direct_sc(sc, 0, addr, &v);
+ ERR_OUT(ret);
+ sc->cardinfo.f[fn].device |= (v << 8);
+ break;
+ case SD_IO_CISTPL_FUNCID:
+ /* Not sure if we need to parse it? */
+ break;
+ case SD_IO_CISTPL_FUNCE:
+ if (tuple_len < 4) {
+ printf("%s: FUNCE is too short: %d\n",
+ __func__, tuple_len);
+ break;
+ }
+ /* TPLFE_TYPE (Extended Data) */
+ ret = sdio_read_direct_sc(sc, 0, addr++, &v);
+ ERR_OUT(ret);
+ if (fn == 0) {
+ if (v != 0x00)
+ break;
+ } else {
+ if (v != 0x01)
+ break;
+ addr += 0x0b;
+ }
+ ret = sdio_read_direct_sc(sc, 0, addr, &v);
+ ERR_OUT(ret);
+ sc->cardinfo.f[fn].max_blksize = v;
+ ret = sdio_read_direct_sc(sc, 0, addr+1, &v);
+ ERR_OUT(ret);
+ sc->cardinfo.f[fn].max_blksize |= (v << 8);
+ break;
+ default:
+ CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_PERIPH,
+ ("%s: Skipping fn %d tuple %d ID %#02x "
+ "len %#02x\n", __func__, fn, tuple_count,
+ tuple_id, tuple_len));
+ }
+ if (tuple_len == 0xff) {
+ /* Also marks the end of a tuple chain (E1 16.2) */
+ /* The tuple is valid, hence this going at the end. */
+ break;
+ }
+ cis_addr += 2 + tuple_len;
+ tuple_count++;
+ } while (tuple_count < 20);
+err:
+#undef ERR_OUT
+ return (ret);
+}
+
+static int
+sdio_get_common_cis_addr(struct sdiob_softc *sc, uint32_t *addr)
+{
+ int error;
+ uint32_t a;
+ uint8_t val;
+
+ error = sdio_read_direct_sc(sc, 0, SD_IO_CCCR_CISPTR + 0, &val);
+ if (error != 0)
+ goto err;
+ a = val;
+ error = sdio_read_direct_sc(sc, 0, SD_IO_CCCR_CISPTR + 1, &val);
+ if (error != 0)
+ goto err;
+ a |= (val << 8);
+ error = sdio_read_direct_sc(sc, 0, SD_IO_CCCR_CISPTR + 2, &val);
+ if (error != 0)
+ goto err;
+ a |= (val << 16);
+
+ if (a < SD_IO_CIS_START || a > SD_IO_CIS_START + SD_IO_CIS_SIZE) {
+err:
+ CAM_DEBUG(sc->ccb->ccb_h.path, CAM_DEBUG_PERIPH,
+ ("%s: bad CIS address: %#04x, error %d\n", __func__, a,
+ error));
+ } else if (error == 0 && addr != NULL)
+ *addr = a;
+
+ return (error);
+}
+
+static int
+sdiob_get_card_info(struct sdiob_softc *sc)
+{
+ struct mmc_params *mmcp;
+ uint32_t cis_addr, fbr_addr;
+ int fn, error;
+ uint8_t fn_max, val;
+
+ error = sdio_get_common_cis_addr(sc, &cis_addr);
+ if (error != 0)
+ return (-1);
+
+ memset(&sc->cardinfo, 0, sizeof(sc->cardinfo));
+
+ /* F0 must always be present. */
+ fn = 0;
+ error = sdio_func_read_cis(sc, fn, cis_addr);
+ if (error != 0)
+ return (error);
+ sc->cardinfo.num_funcs++;
+ /* Read CCCR Card Capability. */
+ error = sdio_read_direct_sc(sc, 0, SD_IO_CCCR_CARDCAP, &val);
+ if (error != 0)
+ return (error);
+ sc->cardinfo.support_multiblk = (val & CCCR_CC_SMB) ? true : false;
+ DPRINTF("%s: F%d: Vendor %#04x product %#04x max block size %d bytes "
+ "support_multiblk %s\n",
+ __func__, fn, sc->cardinfo.f[fn].vendor, sc->cardinfo.f[fn].device,
+ sc->cardinfo.f[fn].max_blksize,
+ sc->cardinfo.support_multiblk ? "yes" : "no");
+
+ /* mmcp->sdio_func_count contains the number of functions w/o F0. */
+ mmcp = &sc->ccb->ccb_h.path->device->mmc_ident_data;
+ fn_max = MIN(mmcp->sdio_func_count + 1, nitems(sc->cardinfo.f));
+ for (fn = 1; fn < fn_max; fn++) {
+
+ fbr_addr = SD_IO_FBR_START * fn + SD_IO_FBR_CIS_OFFSET;
+
+ error = sdio_read_direct_sc(sc, 0, fbr_addr++, &val);
+ if (error != 0)
+ break;
+ cis_addr = val;
+ error = sdio_read_direct_sc(sc, 0, fbr_addr++, &val);
+ if (error != 0)
+ break;
+ cis_addr |= (val << 8);
+ error = sdio_read_direct_sc(sc, 0, fbr_addr++, &val);
+ if (error != 0)
+ break;
+ cis_addr |= (val << 16);
+
+ error = sdio_func_read_cis(sc, fn, cis_addr);
+ if (error != 0)
+ break;
+
+ /* Read the Standard SDIO Function Interface Code. */
+ fbr_addr = SD_IO_FBR_START * fn;
+ error = sdio_read_direct_sc(sc, 0, fbr_addr++, &val);
+ if (error != 0)
+ break;
+ sc->cardinfo.f[fn].class = (val & 0x0f);
+ if (sc->cardinfo.f[fn].class == 0x0f) {
+ error = sdio_read_direct_sc(sc, 0, fbr_addr, &val);
+ if (error != 0)
+ break;
+ sc->cardinfo.f[fn].class = val;
+ }
+
+ sc->cardinfo.f[fn].fn = fn;
+ sc->cardinfo.f[fn].cur_blksize = sc->cardinfo.f[fn].max_blksize;
+ sc->cardinfo.f[fn].retries = 0;
+ sc->cardinfo.f[fn].timeout = 5000;
+
+ DPRINTF("%s: F%d: Class %d Vendor %#04x product %#04x "
+ "max_blksize %d bytes\n", __func__, fn,
+ sc->cardinfo.f[fn].class,
+ sc->cardinfo.f[fn].vendor, sc->cardinfo.f[fn].device,
+ sc->cardinfo.f[fn].max_blksize);
+ if (sc->cardinfo.f[fn].vendor == 0) {
+ DPRINTF("%s: F%d doesn't exist\n", __func__, fn);
+ break;
+ }
+ sc->cardinfo.num_funcs++;
+ }
+ return (error);
+}
+
+
+/* -------------------------------------------------------------------------- */
+/*
+ * CAM periph registration, allocation, and detached from that a discovery
+ * task, which goes off reads cardinfo, and then adds ourselves to our SIM's
+ * device adding the devclass and registering the driver. This keeps the
+ * newbus chain connected though we will talk CAM in the middle (until one
+ * day CAM might be newbusyfied).
+ */
+
+static int
+sdio_newbus_sim_add(struct sdiob_softc *sc)
+{
+ device_t pdev;
+ devclass_t bus_devclass;
+ int error;
+
+ /* Add ourselves to our parent (SIM) device. */
+
+ /* Add ourselves to our parent. That way we can become a parent. */
+ KASSERT(sc->periph->sim->sim_dev != NULL, ("%s: sim_dev is NULL, sc %p "
+ "periph %p sim %p\n", __func__, sc, sc->periph, sc->periph->sim));
+
+ if (sc->dev == NULL)
+ sc->dev = BUS_ADD_CHILD(sc->periph->sim->sim_dev, 0,
+ SDIOB_NAME_S, -1);
+ if (sc->dev == NULL)
+ return (ENXIO);
+ device_set_softc(sc->dev, sc);
+ /*
+ * Don't set description here; devclass_add_driver() ->
+ * device_probe_child() -> device_set_driver() will nuke it again.
+ */
+
+ pdev = device_get_parent(sc->dev);
+ KASSERT(pdev != NULL, ("%s: sc %p dev %p (%s) parent is NULL\n",
+ __func__, sc, sc->dev, device_get_nameunit(sc->dev)));
+ bus_devclass = device_get_devclass(pdev);
+ if (bus_devclass == NULL) {
+ printf("%s: Failed to get devclass from %s.\n", __func__,
+ device_get_nameunit(pdev));
+ return (ENXIO);
+ }
+
+ mtx_lock(&Giant);
+ error = devclass_add_driver(bus_devclass, &sdiob_driver,
+ BUS_PASS_DEFAULT, &sdiob_devclass);
+ mtx_unlock(&Giant);
+ if (error != 0) {
+ printf("%s: Failed to add driver to devclass: %d.\n",
+ __func__, error);
+ return (error);
+ }
+
+ /* Done. */
+ sc->nb_state = NB_STATE_SIM_ADDED;
+
+ return (0);
+}
+
+static void
+sdiobdiscover(void *context, int pending)
+{
+ struct cam_periph *periph;
+ struct sdiob_softc *sc;
+ int error;
+
+ KASSERT(context != NULL, ("%s: context is NULL\n", __func__));
+ periph = (struct cam_periph *)context;
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("%s\n", __func__));
+
+ /* Periph was held for us when this task was enqueued. */
+ if ((periph->flags & CAM_PERIPH_INVALID) != 0) {
+ cam_periph_release(periph);
+ return;
+ }
+
+ sc = periph->softc;
+ sc->sdio_state = SDIO_STATE_INITIALIZING;
+
+ if (sc->ccb == NULL)
+ sc->ccb = xpt_alloc_ccb();
+ else
+ memset(sc->ccb, 0, sizeof(*sc->ccb));
+ xpt_setup_ccb(&sc->ccb->ccb_h, periph->path, CAM_PRIORITY_NONE);
+
+ /*
+ * Read CCCR and FBR of each function, get manufacturer and device IDs,
+ * max block size, and whatever else we deem necessary.
+ */
+ cam_periph_lock(periph);
+ error = sdiob_get_card_info(sc);
+ if (error == 0)
+ sc->sdio_state = SDIO_STATE_READY;
+ else
+ sc->sdio_state = SDIO_STATE_DEAD;
+ cam_periph_unlock(periph);
+
+ if (error)
+ return;
+
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("%s: num_func %d\n",
+ __func__, sc->cardinfo.num_funcs));
+
+ /*
+ * Now CAM portion of the driver has been initialized and
+ * we know VID/PID of all the functions on the card.
+ * Time to hook into the newbus.
+ */
+ error = sdio_newbus_sim_add(sc);
+ if (error != 0)
+ sc->nb_state = NB_STATE_DEAD;
+
+ return;
+}
+
+/* Called at the end of cam_periph_alloc() for us to finish allocation. */
+static cam_status
+sdiobregister(struct cam_periph *periph, void *arg)
+{
+ struct sdiob_softc *sc;
+ int error;
+
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("%s: arg %p\n", __func__, arg));
+ if (arg == NULL) {
+ printf("%s: no getdev CCB, can't register device pariph %p\n",
+ __func__, periph);
+ return(CAM_REQ_CMP_ERR);
+ }
+ if (periph->sim == NULL || periph->sim->sim_dev == NULL) {
+ printf("%s: no sim %p or sim_dev %p\n", __func__, periph->sim,
+ (periph->sim != NULL) ? periph->sim->sim_dev : NULL);
+ return(CAM_REQ_CMP_ERR);
+ }
+
+ sc = (struct sdiob_softc *) malloc(sizeof(*sc), M_DEVBUF,
+ M_NOWAIT|M_ZERO);
+ if (sc == NULL) {
+ printf("%s: unable to allocate sc\n", __func__);
+ return (CAM_REQ_CMP_ERR);
+ }
+ sc->sdio_state = SDIO_STATE_DEAD;
+ sc->nb_state = NB_STATE_DEAD;
+ TASK_INIT(&sc->discover_task, 0, sdiobdiscover, periph);
+
+ /* Refcount until we are setup. Can't block. */
+ error = cam_periph_hold(periph, PRIBIO);
+ if (error != 0) {
+ printf("%s: lost periph during registration!\n", __func__);
+ free(sc, M_DEVBUF);
+ return(CAM_REQ_CMP_ERR);
+ }
+ periph->softc = sc;
+ sc->periph = periph;
+ cam_periph_unlock(periph);
+
+ error = taskqueue_enqueue(taskqueue_thread, &sc->discover_task);
+
+ cam_periph_lock(periph);
+ /* We will continue to hold a refcount for discover_task. */
+ /* cam_periph_unhold(periph); */
+
+ xpt_schedule(periph, CAM_PRIORITY_XPT);
+
+ return (CAM_REQ_CMP);
+}
+
+static void
+sdioboninvalidate(struct cam_periph *periph)
+{
+
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("%s:\n", __func__));
+
+ return;
+}
+
+static void
+sdiobcleanup(struct cam_periph *periph)
+{
+
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("%s:\n", __func__));
+
+ return;
+}
+
+static void
+sdiobstart(struct cam_periph *periph, union ccb *ccb)
+{
+
+ CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("%s: ccb %p\n", __func__, ccb));
+
+ return;
+}
+
+static void
+sdiobasync(void *softc, uint32_t code, struct cam_path *path, void *arg)
+{
+ struct cam_periph *periph;
+ struct ccb_getdev *cgd;
+ cam_status status;
+
+ periph = (struct cam_periph *)softc;
+
+ CAM_DEBUG(path, CAM_DEBUG_TRACE, ("%s(code=%d)\n", __func__, code));
+ switch (code) {
+ case AC_FOUND_DEVICE:
+ if (arg == NULL)
+ break;
+ cgd = (struct ccb_getdev *)arg;
+ if (cgd->protocol != PROTO_MMCSD)
+ break;
+
+ /* We do not support SD memory (Combo) Cards. */
+ if ((path->device->mmc_ident_data.card_features &
+ CARD_FEATURE_MEMORY)) {
+ CAM_DEBUG(path, CAM_DEBUG_TRACE,
+ ("Memory card, not interested\n"));
+ break;
+ }
+
+ /*
+ * Allocate a peripheral instance for this device which starts
+ * the probe process.
+ */
+ status = cam_periph_alloc(sdiobregister, sdioboninvalidate,
+ sdiobcleanup, sdiobstart, SDIOB_NAME_S, CAM_PERIPH_BIO, path,
+ sdiobasync, AC_FOUND_DEVICE, cgd);
+ if (status != CAM_REQ_CMP && status != CAM_REQ_INPROG)
+ CAM_DEBUG(path, CAM_DEBUG_PERIPH,
+ ("%s: Unable to attach to new device due to "
+ "status %#02x\n", __func__, status));
+ break;
+ default:
+ CAM_DEBUG(path, CAM_DEBUG_PERIPH,
+ ("%s: cannot handle async code %#02x\n", __func__, code));
+ cam_periph_async(periph, code, path, arg);
+ break;
+ }
+}
+
+static void
+sdiobinit(void)
+{
+ cam_status status;
+
+ /*
+ * Register for new device notification. We will be notified for all
+ * already existing ones.
+ */
+ status = xpt_register_async(AC_FOUND_DEVICE, sdiobasync, NULL, NULL);
+ if (status != CAM_REQ_CMP)
+ printf("%s: Failed to attach async callback, statux %#02x",
+ __func__, status);
+}
+
+/* This function will allow unloading the KLD. */
+static int
+sdiobdeinit(void)
+{
+
+ return (EOPNOTSUPP);
+}
+
+static struct periph_driver sdiobdriver =
+{
+ .init = sdiobinit,
+ .driver_name = SDIOB_NAME_S,
+ .units = TAILQ_HEAD_INITIALIZER(sdiobdriver.units),
+ .generation = 0,
+ .flags = 0,
+ .deinit = sdiobdeinit,
+};
+
+PERIPHDRIVER_DECLARE(SDIOB_NAME, sdiobdriver);
+MODULE_VERSION(SDIOB_NAME, 1);
Index: head/sys/dev/sdio/sdiodevs
===================================================================
--- head/sys/dev/sdio/sdiodevs
+++ head/sys/dev/sdio/sdiodevs
@@ -0,0 +1,74 @@
+$FreeBSD$
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2019 The FreeBSD Foundation
+ *
+ * Portions of this software were developed by Björn Zeeb
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Take SDIO CIS, CISTPL_MANFID, TPLMID_MANF and TPLMID_CARD information and
+ * present them as vendor and device IDs (a terminology we understand for
+ * other parts) and run them through the usbdevs2h.awk script to generate
+ * a header file with #defines for them in sdiodevs.h and sdiodevs_data.h
+ * which provides a structure with a description as well.
+ * The format of this file is modelled after sys/dev/usb/usbdevs.
+ * For more details see there.
+ */
+
+/*
+ * --------------------------------------------------------------------------
+ * List of TPLMID_MANF "vendor ID"s.
+ * Please sort by vendor ID ascending.
+ */
+vendor BROADCOM 0x02d0 Broadcom
+vendor CYPRESS 0x02d0 Cypress/Broadcom
+
+/*
+ * --------------------------------------------------------------------------
+ * List of TPLMID_CARD "product ID"s.
+ * Please group by vendor in same order as above.
+ */
+
+/* Broadcom products */
+product BROADCOM 43241 0x4324 BCM43241 fullmac SDIO WiFi
+product BROADCOM 4329 0x4329 BCM4329 fullmac SDIO WiFi
+product BROADCOM 4330 0x4330 BCM4330 fullmac SDIO WiFi
+product BROADCOM 4334 0x4334 BCM4334 fullmac SDIO WiFi
+product BROADCOM 4335_4339 0x4335 BCM4335_4339 fullmac SDIO WiFi
+product BROADCOM 4339 0x4339 BCM4339 fullmac SDIO WiFi
+product BROADCOM 4345 0x4345 BCM4345 fullmac SDIO WiFi
+product BROADCOM 4354 0x4354 BCM4354 fullmac SDIO WiFi
+product BROADCOM 4356 0x4356 BCM4356 fullmac SDIO WiFi
+product BROADCOM 43143 0xa887 BCM43143 fullmac SDIO WiFi
+product BROADCOM 43340 0xa94c BCM43340 fullmac SDIO WiFi
+product BROADCOM 43341 0xa94d BCM43341 fullmac SDIO WiFi
+product BROADCOM 43362 0xa962 BCM43362 fullmac SDIO WiFi
+product BROADCOM 43364 0xa9a4 BCM43364 fullmac SDIO WiFi
+product BROADCOM 43430 0xa9a6 BCM43430 fullmac SDIO WiFi
+product BROADCOM 43455 0xa9bf BCM43455 fullmac SDIO WiFi
+product CYPRESS 4373 0x4373 CY4373 fullmac SDIO WiFi
+
+/* end */
Index: head/sys/modules/Makefile
===================================================================
--- head/sys/modules/Makefile
+++ head/sys/modules/Makefile
@@ -324,6 +324,7 @@
sdhci \
${_sdhci_acpi} \
sdhci_pci \
+ sdio \
sem \
send \
${_sfxge} \
Index: head/sys/modules/sdio/Makefile
===================================================================
--- head/sys/modules/sdio/Makefile
+++ head/sys/modules/sdio/Makefile
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../dev/sdio
+
+KMOD= sdio
+SRCS= sdiob.c sdio_subr.c
+SRCS+= sdio_if.c
+SRCS+= device_if.h bus_if.h sdio_if.h
+
+.include <bsd.kmod.mk>
Index: head/sys/tools/sdiodevs2h.awk
===================================================================
--- head/sys/tools/sdiodevs2h.awk
+++ head/sys/tools/sdiodevs2h.awk
@@ -0,0 +1,265 @@
+#! /usr/bin/awk -f
+#-
+# $NetBSD: usb/devlist2h.awk,v 1.9 2001/01/18 20:28:22 jdolecek Exp $
+# $FreeBSD$
+#
+# SPDX-License-Identifier: BSD-4-Clause
+#
+# Copyright (c) 1995, 1996 Christopher G. Demetriou
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in the
+# documentation and/or other materials provided with the distribution.
+# 3. All advertising materials mentioning features or use of this software
+# must display the following acknowledgement:
+# This product includes software developed by Christopher G. Demetriou.
+# 4. The name of the author may not be used to endorse or promote products
+# derived from this software without specific prior written permission
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+#
+
+function usage()
+{
+ print "usage: sdiodevs2h.awk <srcfile> [-d|-h]";
+ exit 1;
+}
+
+function header(file)
+{
+ printf("/*\n") > file
+ printf(" * THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT.\n") \
+ > file
+ printf(" *\n") > file
+ printf(" * generated from:\n") > file
+ printf(" *\t%s\n", VERSION) > file
+ printf(" */\n") > file
+}
+
+function vendor(hfile)
+{
+ nvendors++
+
+ vendorindex[$2] = nvendors; # record index for this name, for later.
+ vendors[nvendors, 1] = $2; # name
+ vendors[nvendors, 2] = $3; # id
+ if (hfile)
+ printf("#define\tSDIO_VENDOR_%s\t%s\t", vendors[nvendors, 1],
+ vendors[nvendors, 2]) > hfile
+ i = 3; f = 4;
+
+ # comments
+ ocomment = oparen = 0
+ if (f <= NF) {
+ if (hfile)
+ printf("\t/* ") > hfile
+ ocomment = 1;
+ }
+ while (f <= NF) {
+ if ($f == "#") {
+ if (hfile)
+ printf("(") > hfile
+ oparen = 1
+ f++
+ continue
+ }
+ if (oparen) {
+ if (hfile)
+ printf("%s", $f) > hfile
+ if (f < NF && hfile)
+ printf(" ") > hfile
+ f++
+ continue
+ }
+ vendors[nvendors, i] = $f
+ if (hfile)
+ printf("%s", vendors[nvendors, i]) > hfile
+ if (f < NF && hfile)
+ printf(" ") > hfile
+ i++; f++;
+ }
+ if (oparen && hfile)
+ printf(")") > hfile
+ if (ocomment && hfile)
+ printf(" */") > hfile
+ if (hfile)
+ printf("\n") > hfile
+}
+
+function product(hfile)
+{
+ nproducts++
+
+ products[nproducts, 1] = $2; # vendor name
+ products[nproducts, 2] = $3; # product id
+ products[nproducts, 3] = $4; # id
+ if (hfile)
+ printf("#define\tSDIO_PRODUCT_%s_%s\t%s\t", \
+ products[nproducts, 1], products[nproducts, 2], \
+ products[nproducts, 3]) > hfile
+
+ i=4; f = 5;
+
+ # comments
+ ocomment = oparen = 0
+ if (f <= NF) {
+ if (hfile)
+ printf("\t/* ") > hfile
+ ocomment = 1;
+ }
+ while (f <= NF) {
+ if ($f == "#") {
+ if (hfile)
+ printf("(") > hfile
+ oparen = 1
+ f++
+ continue
+ }
+ if (oparen) {
+ if (hfile)
+ printf("%s", $f) > hfile
+ if (f < NF && hfile)
+ printf(" ") > hfile
+ f++
+ continue
+ }
+ products[nproducts, i] = $f
+ if (hfile)
+ printf("%s", products[nproducts, i]) > hfile
+ if (f < NF && hfile)
+ printf(" ") > hfile
+ i++; f++;
+ }
+ if (oparen && hfile)
+ printf(")") > hfile
+ if (ocomment && hfile)
+ printf(" */") > hfile
+ if (hfile)
+ printf("\n") > hfile
+}
+
+function dump_dfile(dfile)
+{
+ printf("\n") > dfile
+ printf("const struct sdio_knowndev sdio_knowndevs[] = {\n") > dfile
+ for (i = 1; i <= nproducts; i++) {
+ printf("\t{\n") > dfile
+ printf("\t SDIO_VENDOR_%s, SDIO_PRODUCT_%s_%s,\n",
+ products[i, 1], products[i, 1], products[i, 2]) > dfile
+ printf("\t ") > dfile
+ printf("0") > dfile
+ printf(",\n") > dfile
+
+ vendi = vendorindex[products[i, 1]];
+ printf("\t \"") > dfile
+ j = 3;
+ needspace = 0;
+ while (vendors[vendi, j] != "") {
+ if (needspace)
+ printf(" ") > dfile
+ printf("%s", vendors[vendi, j]) > dfile
+ needspace = 1
+ j++
+ }
+ printf("\",\n") > dfile
+
+ printf("\t \"") > dfile
+ j = 4;
+ needspace = 0;
+ while (products[i, j] != "") {
+ if (needspace)
+ printf(" ") > dfile
+ printf("%s", products[i, j]) > dfile
+ needspace = 1
+ j++
+ }
+ printf("\",\n") > dfile
+ printf("\t},\n") > dfile
+ }
+ for (i = 1; i <= nvendors; i++) {
+ printf("\t{\n") > dfile
+ printf("\t SDIO_VENDOR_%s, 0,\n", vendors[i, 1]) > dfile
+ printf("\t SDIO_KNOWNDEV_NOPROD,\n") > dfile
+ printf("\t \"") > dfile
+ j = 3;
+ needspace = 0;
+ while (vendors[i, j] != "") {
+ if (needspace)
+ printf(" ") > dfile
+ printf("%s", vendors[i, j]) > dfile
+ needspace = 1
+ j++
+ }
+ printf("\",\n") > dfile
+ printf("\t NULL,\n") > dfile
+ printf("\t},\n") > dfile
+ }
+ printf("\t{ 0, 0, 0, NULL, NULL, }\n") > dfile
+ printf("};\n") > dfile
+}
+
+BEGIN {
+
+nproducts = nvendors = 0
+# Process the command line
+for (i = 1; i < ARGC; i++) {
+ arg = ARGV[i];
+ if (arg !~ /^-[dh]+$/ && arg !~ /devs$/)
+ usage();
+ if (arg ~ /^-.*d/)
+ dfile="sdiodevs_data.h"
+ if (arg ~ /^-.*h/)
+ hfile="sdiodevs.h"
+ if (arg ~ /devs$/)
+ srcfile = arg;
+}
+ARGC = 1;
+line=0;
+
+while ((getline < srcfile) > 0) {
+ line++;
+ if (line == 1) {
+ VERSION = $0
+ gsub("\\$", "", VERSION)
+ if (dfile)
+ header(dfile)
+ if (hfile)
+ header(hfile)
+ continue;
+ }
+ if ($1 == "vendor") {
+ vendor(hfile)
+ continue
+ }
+ if ($1 == "product") {
+ product(hfile)
+ continue
+ }
+ if ($0 == "")
+ blanklines++
+ if (hfile)
+ print $0 > hfile
+ if (blanklines < 2 && dfile)
+ print $0 > dfile
+}
+
+# print out the match tables
+
+if (dfile)
+ dump_dfile(dfile)
+}

File Metadata

Mime Type
text/plain
Expires
Sat, Feb 22, 12:55 PM (1 h, 17 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16771832
Default Alt Text
D19749.diff (64 KB)

Event Timeline