From owner-svn-src-all@FreeBSD.ORG Sun Jan 31 21:18:23 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 34F4C1065679; Sun, 31 Jan 2010 21:18:23 +0000 (UTC) (envelope-from weongyo@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 2263F8FC21; Sun, 31 Jan 2010 21:18:23 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o0VLINeW041838; Sun, 31 Jan 2010 21:18:23 GMT (envelope-from weongyo@svn.freebsd.org) Received: (from weongyo@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o0VLINKJ041832; Sun, 31 Jan 2010 21:18:23 GMT (envelope-from weongyo@svn.freebsd.org) Message-Id: <201001312118.o0VLINKJ041832@svn.freebsd.org> From: Weongyo Jeong Date: Sun, 31 Jan 2010 21:18:23 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r203319 - in head/sys: dev/siba modules/siba_bwn X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 31 Jan 2010 21:18:23 -0000 Author: weongyo Date: Sun Jan 31 21:18:22 2010 New Revision: 203319 URL: http://svn.freebsd.org/changeset/base/203319 Log: Adds siba_bwn module which is used with bwn(4). Main purpose of this module is to distinguish parts of Silicon Backplane and of Broadcom Wireless. Added: head/sys/dev/siba/siba_bwn.c (contents, props changed) head/sys/dev/siba/siba_core.c (contents, props changed) head/sys/modules/siba_bwn/ head/sys/modules/siba_bwn/Makefile (contents, props changed) Modified: head/sys/dev/siba/siba.c head/sys/dev/siba/siba_cc.c head/sys/dev/siba/siba_ids.h head/sys/dev/siba/siba_pcib.c head/sys/dev/siba/sibareg.h head/sys/dev/siba/sibavar.h Modified: head/sys/dev/siba/siba.c ============================================================================== --- head/sys/dev/siba/siba.c Sun Jan 31 20:02:42 2010 (r203318) +++ head/sys/dev/siba/siba.c Sun Jan 31 21:18:22 2010 (r203319) @@ -37,9 +37,9 @@ __FBSDID("$FreeBSD$"); #include -#include -#include #include +#include +#include /* * TODO: De-mipsify this code. @@ -77,7 +77,7 @@ static struct siba_devid siba_devids[] = "MIPS core" }, { SIBA_VID_BROADCOM, SIBA_DEVID_ETHERNET, SIBA_REV_ANY, "Ethernet core" }, - { SIBA_VID_BROADCOM, SIBA_DEVID_USB, SIBA_REV_ANY, + { SIBA_VID_BROADCOM, SIBA_DEVID_USB11_HOSTDEV, SIBA_REV_ANY, "USB host controller" }, { SIBA_VID_BROADCOM, SIBA_DEVID_IPSEC, SIBA_REV_ANY, "IPSEC accelerator" }, @@ -103,7 +103,6 @@ static struct siba_devid * static struct resource_list * siba_get_reslist(device_t, device_t); static uint8_t siba_getirq(uint16_t); -static uint8_t siba_getncores(uint16_t); static int siba_print_all_resources(device_t dev); static int siba_print_child(device_t, device_t); static int siba_probe(device_t); @@ -112,30 +111,7 @@ int siba_read_ivar(device_t, device_t, static struct siba_devinfo * siba_setup_devinfo(device_t, uint8_t); int siba_write_ivar(device_t, device_t, int, uintptr_t); - -/* - * Earlier ChipCommon revisions have hardcoded number of cores - * present dependent on the ChipCommon ID. - */ -static uint8_t -siba_getncores(uint16_t ccid) -{ - uint8_t ncores; - - switch (ccid) { - case SIBA_CCID_SENTRY5: - ncores = 7; - break; - case SIBA_CCID_BCM4710: - case SIBA_CCID_BCM4704: - ncores = 9; - break; - default: - ncores = 0; - } - - return (ncores); -} +uint8_t siba_getncores(device_t, uint16_t); /* * On the Sentry5, the system bus IRQs are the same as the @@ -156,7 +132,7 @@ siba_getirq(uint16_t devid) case SIBA_DEVID_IPSEC: irq = 2; break; - case SIBA_DEVID_USB: + case SIBA_DEVID_USB11_HOSTDEV: irq = 3; break; case SIBA_DEVID_PCI: @@ -188,7 +164,7 @@ siba_probe(device_t dev) uint16_t ccid; int rid; - sc->sc_dev = dev; + sc->siba_dev = dev; //rman_debug = 1; /* XXX */ @@ -197,24 +173,24 @@ siba_probe(device_t dev) * was compiled with. */ rid = MIPS_MEM_RID; - sc->sc_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + sc->siba_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); - if (sc->sc_mem == NULL) { + if (sc->siba_mem_res == NULL) { device_printf(dev, "unable to allocate probe aperture\n"); return (ENXIO); } - sc->sc_bt = rman_get_bustag(sc->sc_mem); - sc->sc_bh = rman_get_bushandle(sc->sc_mem); - sc->sc_maddr = rman_get_start(sc->sc_mem); - sc->sc_msize = rman_get_size(sc->sc_mem); + sc->siba_mem_bt = rman_get_bustag(sc->siba_mem_res); + sc->siba_mem_bh = rman_get_bushandle(sc->siba_mem_res); + sc->siba_maddr = rman_get_start(sc->siba_mem_res); + sc->siba_msize = rman_get_size(sc->siba_mem_res); if (siba_debug) { device_printf(dev, "start %08x len %08x\n", - sc->sc_maddr, sc->sc_msize); + sc->siba_maddr, sc->siba_msize); } - idlo = siba_read_4(sc, 0, SIBA_CORE_IDLO); - idhi = siba_read_4(sc, 0, SIBA_CORE_IDHI); + idlo = siba_mips_read_4(sc, 0, SIBA_IDLOW); + idhi = siba_mips_read_4(sc, 0, SIBA_IDHIGH); ccid = ((idhi & 0x8ff0) >> 4); if (siba_debug) { device_printf(dev, "idlo = %08x\n", idlo); @@ -256,7 +232,7 @@ siba_probe(device_t dev) uint16_t cc_id; uint16_t cc_rev; - ccidreg = siba_read_4(sc, 0, SIBA_CC_CCID); + ccidreg = siba_mips_read_4(sc, 0, SIBA_CC_CHIPID); cc_id = (ccidreg & SIBA_CC_IDMASK); cc_rev = (ccidreg & SIBA_CC_REVMASK) >> SIBA_CC_REVSHIFT; if (siba_debug) { @@ -264,9 +240,9 @@ siba_probe(device_t dev) ccidreg, cc_id, cc_rev); } - sc->sc_ncores = siba_getncores(cc_id); + sc->siba_ncores = siba_getncores(dev, cc_id); if (siba_debug) { - device_printf(dev, "%d cores detected.\n", sc->sc_ncores); + device_printf(dev, "%d cores detected.\n", sc->siba_ncores); } /* @@ -275,36 +251,38 @@ siba_probe(device_t dev) */ rid = MIPS_MEM_RID; int result; - result = bus_release_resource(dev, SYS_RES_MEMORY, rid, sc->sc_mem); + result = bus_release_resource(dev, SYS_RES_MEMORY, rid, + sc->siba_mem_res); if (result != 0) { device_printf(dev, "error %d releasing resource\n", result); return (ENXIO); } uint32_t total; - total = sc->sc_ncores * SIBA_CORE_LEN; + total = sc->siba_ncores * SIBA_CORE_LEN; /* XXX Don't allocate the entire window until we * enumerate the bus. Once the bus has been enumerated, * and instance variables/children instantiated + populated, * release the resource so children may attach. */ - sc->sc_mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, - sc->sc_maddr, sc->sc_maddr + total - 1, total, RF_ACTIVE); - if (sc->sc_mem == NULL) { + sc->siba_mem_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, + sc->siba_maddr, sc->siba_maddr + total - 1, total, RF_ACTIVE); + if (sc->siba_mem_res == NULL) { device_printf(dev, "unable to allocate entire aperture\n"); return (ENXIO); } - sc->sc_bt = rman_get_bustag(sc->sc_mem); - sc->sc_bh = rman_get_bushandle(sc->sc_mem); - sc->sc_maddr = rman_get_start(sc->sc_mem); - sc->sc_msize = rman_get_size(sc->sc_mem); + sc->siba_mem_bt = rman_get_bustag(sc->siba_mem_res); + sc->siba_mem_bh = rman_get_bushandle(sc->siba_mem_res); + sc->siba_maddr = rman_get_start(sc->siba_mem_res); + sc->siba_msize = rman_get_size(sc->siba_mem_res); if (siba_debug) { device_printf(dev, "after remapping: start %08x len %08x\n", - sc->sc_maddr, sc->sc_msize); + sc->siba_maddr, sc->siba_msize); } - bus_set_resource(dev, SYS_RES_MEMORY, rid, sc->sc_maddr, sc->sc_msize); + bus_set_resource(dev, SYS_RES_MEMORY, rid, sc->siba_maddr, + sc->siba_msize); /* * We need a manager for the space we claim on nexus to @@ -313,12 +291,13 @@ siba_probe(device_t dev) * otherwise it may be claimed elsewhere. * XXX move to softc */ - mem_rman.rm_start = sc->sc_maddr; - mem_rman.rm_end = sc->sc_maddr + sc->sc_msize - 1; + mem_rman.rm_start = sc->siba_maddr; + mem_rman.rm_end = sc->siba_maddr + sc->siba_msize - 1; mem_rman.rm_type = RMAN_ARRAY; mem_rman.rm_descr = "SiBa I/O memory addresses"; if (rman_init(&mem_rman) != 0 || - rman_manage_region(&mem_rman, mem_rman.rm_start, mem_rman.rm_end) != 0) { + rman_manage_region(&mem_rman, mem_rman.rm_start, + mem_rman.rm_end) != 0) { panic("%s: mem_rman", __func__); } @@ -344,7 +323,7 @@ siba_attach(device_t dev) * NB: only one core may be mapped at any time if the siba bus * is the child of a PCI or PCMCIA bus. */ - for (idx = 0; idx < sc->sc_ncores; idx++) { + for (idx = 0; idx < sc->siba_ncores; idx++) { sdi = siba_setup_devinfo(dev, idx); child = device_add_child(dev, NULL, -1); if (child == NULL) @@ -483,13 +462,14 @@ siba_setup_devinfo(device_t dev, uint8_t sdi = malloc(sizeof(*sdi), M_DEVBUF, M_WAITOK | M_ZERO); resource_list_init(&sdi->sdi_rl); - idlo = siba_read_4(sc, idx, SIBA_CORE_IDLO); - idhi = siba_read_4(sc, idx, SIBA_CORE_IDHI); + idlo = siba_mips_read_4(sc, idx, SIBA_IDLOW); + idhi = siba_mips_read_4(sc, idx, SIBA_IDHIGH); - vendorid = (idhi & SIBA_IDHIGH_VC) >> SIBA_IDHIGH_VC_SHIFT; + vendorid = (idhi & SIBA_IDHIGH_VENDORMASK) >> + SIBA_IDHIGH_VENDOR_SHIFT; devid = ((idhi & 0x8ff0) >> 4); - rev = (idhi & SIBA_IDHIGH_RCLO); - rev |= (idhi & SIBA_IDHIGH_RCHI) >> SIBA_IDHIGH_RCHI_SHIFT; + rev = (idhi & SIBA_IDHIGH_REVLO); + rev |= (idhi & SIBA_IDHIGH_REVHI) >> SIBA_IDHIGH_REVHI_SHIFT; sdi->sdi_vid = vendorid; sdi->sdi_devid = devid; @@ -500,7 +480,7 @@ siba_setup_devinfo(device_t dev, uint8_t /* * Determine memory window on bus and irq if one is needed. */ - baseaddr = sc->sc_maddr + (idx * SIBA_CORE_LEN); + baseaddr = sc->siba_maddr + (idx * SIBA_CORE_LEN); resource_list_add(&sdi->sdi_rl, SYS_RES_MEMORY, MIPS_MEM_RID, /* XXX */ baseaddr, baseaddr + SIBA_CORE_LEN - 1, SIBA_CORE_LEN); Added: head/sys/dev/siba/siba_bwn.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/dev/siba/siba_bwn.c Sun Jan 31 21:18:22 2010 (r203319) @@ -0,0 +1,366 @@ +/*- + * Copyright (c) 2009-2010 Weongyo Jeong + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * Sonics Silicon Backplane front-end for bwn(4). + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +/* + * PCI glue. + */ + +struct siba_bwn_softc { + /* Child driver using MSI. */ + device_t ssc_msi_child; + struct siba_softc ssc_siba; +}; + +#define BS_BAR 0x10 +#define PCI_VENDOR_BROADCOM 0x14e4 +#define N(a) (sizeof(a) / sizeof(a[0])) + +static const struct siba_dev { + uint16_t vid; + uint16_t did; + const char *desc; +} siba_devices[] = { + { PCI_VENDOR_BROADCOM, 0x4301, "Broadcom BCM4301 802.11b Wireless" }, + { PCI_VENDOR_BROADCOM, 0x4306, "Unknown" }, + { PCI_VENDOR_BROADCOM, 0x4307, "Broadcom BCM4307 802.11b Wireless" }, + { PCI_VENDOR_BROADCOM, 0x4311, "Broadcom BCM4311 802.11b/g Wireless" }, + { PCI_VENDOR_BROADCOM, 0x4312, + "Broadcom BCM4312 802.11a/b/g Wireless" }, + { PCI_VENDOR_BROADCOM, 0x4315, "Broadcom BCM4312 802.11b/g Wireless" }, + { PCI_VENDOR_BROADCOM, 0x4318, "Broadcom BCM4318 802.11b/g Wireless" }, + { PCI_VENDOR_BROADCOM, 0x4319, + "Broadcom BCM4318 802.11a/b/g Wireless" }, + { PCI_VENDOR_BROADCOM, 0x4320, "Broadcom BCM4306 802.11b/g Wireless" }, + { PCI_VENDOR_BROADCOM, 0x4321, "Broadcom BCM4306 802.11a Wireless" }, + { PCI_VENDOR_BROADCOM, 0x4324, + "Broadcom BCM4309 802.11a/b/g Wireless" }, + { PCI_VENDOR_BROADCOM, 0x4325, "Broadcom BCM4306 802.11b/g Wireless" }, + { PCI_VENDOR_BROADCOM, 0x4328, "Unknown" }, + { PCI_VENDOR_BROADCOM, 0x4329, "Unknown" }, + { PCI_VENDOR_BROADCOM, 0x432b, "Unknown" } +}; + +device_t siba_add_child(device_t, struct siba_softc *, int, const char *, + int); +int siba_core_attach(struct siba_softc *); +int siba_core_detach(struct siba_softc *); +int siba_core_suspend(struct siba_softc *); +int siba_core_resume(struct siba_softc *); + +static int +siba_bwn_probe(device_t dev) +{ + int i; + uint16_t did, vid; + + did = pci_get_device(dev); + vid = pci_get_vendor(dev); + + for (i = 0; i < N(siba_devices); i++) { + if (siba_devices[i].did == did && siba_devices[i].vid == vid) { + device_set_desc(dev, siba_devices[i].desc); + return (BUS_PROBE_DEFAULT); + } + } + return (ENXIO); +} + +static int +siba_bwn_attach(device_t dev) +{ + struct siba_bwn_softc *ssc = device_get_softc(dev); + struct siba_softc *siba = &ssc->ssc_siba; + + siba->siba_dev = dev; + siba->siba_type = SIBA_TYPE_PCI; + + /* + * Enable bus mastering. + */ + pci_enable_busmaster(dev); + + /* + * Setup memory-mapping of PCI registers. + */ + siba->siba_mem_rid = SIBA_PCIR_BAR; + siba->siba_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &siba->siba_mem_rid, RF_ACTIVE); + if (siba->siba_mem_res == NULL) { + device_printf(dev, "cannot map register space\n"); + return (ENXIO); + } + siba->siba_mem_bt = rman_get_bustag(siba->siba_mem_res); + siba->siba_mem_bh = rman_get_bushandle(siba->siba_mem_res); + + /* Get more PCI information */ + siba->siba_pci_did = pci_get_device(dev); + siba->siba_pci_vid = pci_get_vendor(dev); + siba->siba_pci_subvid = pci_get_subvendor(dev); + siba->siba_pci_subdid = pci_get_subdevice(dev); + + return (siba_core_attach(siba)); +} + +static int +siba_bwn_detach(device_t dev) +{ + struct siba_bwn_softc *ssc = device_get_softc(dev); + struct siba_softc *siba = &ssc->ssc_siba; + + /* check if device was removed */ + siba->siba_invalid = !bus_child_present(dev); + + pci_disable_busmaster(dev); + bus_generic_detach(dev); + siba_core_detach(siba); + + bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR, siba->siba_mem_res); + + return (0); +} + +static int +siba_bwn_shutdown(device_t dev) +{ + device_t *devlistp; + int devcnt, error = 0, i; + + error = device_get_children(dev, &devlistp, &devcnt); + if (error != 0) + return (error); + + for (i = 0 ; i < devcnt ; i++) + device_shutdown(devlistp[i]); + free(devlistp, M_TEMP); + return (0); +} + +static int +siba_bwn_suspend(device_t dev) +{ + struct siba_bwn_softc *ssc = device_get_softc(dev); + struct siba_softc *siba = &ssc->ssc_siba; + device_t *devlistp; + int devcnt, error = 0, i, j; + + error = device_get_children(dev, &devlistp, &devcnt); + if (error != 0) + return (error); + + for (i = 0 ; i < devcnt ; i++) { + error = DEVICE_SUSPEND(devlistp[i]); + if (error) { + for (j = 0; j < i; i++) + DEVICE_RESUME(devlistp[j]); + return (error); + } + } + free(devlistp, M_TEMP); + return (siba_core_suspend(siba)); +} + +static int +siba_bwn_resume(device_t dev) +{ + struct siba_bwn_softc *ssc = device_get_softc(dev); + struct siba_softc *siba = &ssc->ssc_siba; + device_t *devlistp; + int devcnt, error = 0, i; + + error = siba_core_resume(siba); + if (error != 0) + return (error); + + error = device_get_children(dev, &devlistp, &devcnt); + if (error != 0) + return (error); + + for (i = 0 ; i < devcnt ; i++) + DEVICE_RESUME(devlistp[i]); + free(devlistp, M_TEMP); + return (0); +} + +static device_t +siba_bwn_add_child(device_t dev, int order, const char *name, int unit) +{ + struct siba_bwn_softc *ssc = device_get_softc(dev); + struct siba_softc *siba = &ssc->ssc_siba; + + return (siba_add_child(dev, siba, order, name, unit)); +} + +/* proxying to the parent */ +static struct resource * +siba_bwn_alloc_resource(device_t dev, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + + return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev, + type, rid, start, end, count, flags)); +} + +/* proxying to the parent */ +static int +siba_bwn_release_resource(device_t dev, device_t child, int type, + int rid, struct resource *r) +{ + + return (BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, type, + rid, r)); +} + +/* proxying to the parent */ +static int +siba_bwn_setup_intr(device_t dev, device_t child, struct resource *irq, + int flags, driver_filter_t *filter, driver_intr_t *intr, void *arg, + void **cookiep) +{ + + return (BUS_SETUP_INTR(device_get_parent(dev), dev, irq, flags, + filter, intr, arg, cookiep)); +} + +/* proxying to the parent */ +static int +siba_bwn_teardown_intr(device_t dev, device_t child, struct resource *irq, + void *cookie) +{ + + return (BUS_TEARDOWN_INTR(device_get_parent(dev), dev, irq, cookie)); +} + +static int +siba_bwn_find_extcap(device_t dev, device_t child, int capability, + int *capreg) +{ + + return (pci_find_extcap(dev, capability, capreg)); +} + +static int +siba_bwn_alloc_msi(device_t dev, device_t child, int *count) +{ + struct siba_bwn_softc *ssc; + int error; + + ssc = device_get_softc(dev); + if (ssc->ssc_msi_child != NULL) + return (EBUSY); + error = pci_alloc_msi(dev, count); + if (error == 0) + ssc->ssc_msi_child = child; + return (error); +} + +static int +siba_bwn_release_msi(device_t dev, device_t child) +{ + struct siba_bwn_softc *ssc; + int error; + + ssc = device_get_softc(dev); + if (ssc->ssc_msi_child != child) + return (ENXIO); + error = pci_release_msi(dev); + if (error == 0) + ssc->ssc_msi_child = NULL; + return (error); +} + +static int +siba_bwn_msi_count(device_t dev, device_t child) +{ + + return (pci_msi_count(dev)); +} + +static device_method_t siba_bwn_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, siba_bwn_probe), + DEVMETHOD(device_attach, siba_bwn_attach), + DEVMETHOD(device_detach, siba_bwn_detach), + DEVMETHOD(device_shutdown, siba_bwn_shutdown), + DEVMETHOD(device_suspend, siba_bwn_suspend), + DEVMETHOD(device_resume, siba_bwn_resume), + + /* Bus interface */ + DEVMETHOD(bus_add_child, siba_bwn_add_child), + DEVMETHOD(bus_alloc_resource, siba_bwn_alloc_resource), + DEVMETHOD(bus_release_resource, siba_bwn_release_resource), + DEVMETHOD(bus_setup_intr, siba_bwn_setup_intr), + DEVMETHOD(bus_teardown_intr, siba_bwn_teardown_intr), + + /* PCI interface */ + DEVMETHOD(pci_find_extcap, siba_bwn_find_extcap), + DEVMETHOD(pci_alloc_msi, siba_bwn_alloc_msi), + DEVMETHOD(pci_release_msi, siba_bwn_release_msi), + DEVMETHOD(pci_msi_count, siba_bwn_msi_count), + + { 0,0 } +}; +static driver_t siba_bwn_driver = { + "siba_bwn", + siba_bwn_methods, + sizeof(struct siba_bwn_softc) +}; +static devclass_t siba_bwn_devclass; +DRIVER_MODULE(siba_bwn, pci, siba_bwn_driver, siba_bwn_devclass, 0, 0); +MODULE_VERSION(siba_bwn, 1); Modified: head/sys/dev/siba/siba_cc.c ============================================================================== --- head/sys/dev/siba/siba_cc.c Sun Jan 31 20:02:42 2010 (r203318) +++ head/sys/dev/siba/siba_cc.c Sun Jan 31 21:18:22 2010 (r203319) @@ -55,9 +55,9 @@ __FBSDID("$FreeBSD$"); #include -#include -#include #include +#include +#include static int siba_cc_attach(device_t); static int siba_cc_probe(device_t); Added: head/sys/dev/siba/siba_core.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/dev/siba/siba_core.c Sun Jan 31 21:18:22 2010 (r203319) @@ -0,0 +1,2007 @@ +/*- + * Copyright (c) 2009-2010 Weongyo Jeong + * 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, + * without modification. + * 2. Redistributions in binary form must reproduce at minimum a disclaimer + * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any + * redistribution must be conditioned upon including a substantially + * similar Disclaimer requirement for further binary redistribution. + * + * NO WARRANTY + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES. + */ + +#include +__FBSDID("$FreeBSD$"); + +/* + * the Sonics Silicon Backplane driver. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include +#include +#include + +#ifdef SIBA_DEBUG +enum { + SIBA_DEBUG_SCAN = 0x00000001, /* scan */ + SIBA_DEBUG_PMU = 0x00000002, /* PMU */ + SIBA_DEBUG_PLL = 0x00000004, /* PLL */ + SIBA_DEBUG_SWITCHCORE = 0x00000008, /* switching core */ + SIBA_DEBUG_SPROM = 0x00000010, /* SPROM */ + SIBA_DEBUG_CORE = 0x00000020, /* handling cores */ + SIBA_DEBUG_ANY = 0xffffffff +}; +#define DPRINTF(siba, m, fmt, ...) do { \ + if (siba->siba_debug & (m)) \ + printf(fmt, __VA_ARGS__); \ +} while (0) +#else +#define DPRINTF(siba, m, fmt, ...) do { (void) siba; } while (0) +#endif +#define N(a) (sizeof(a) / sizeof(a[0])) + +static void siba_pci_gpio(struct siba_softc *, uint32_t, int); +static void siba_scan(struct siba_softc *); +static int siba_switchcore(struct siba_softc *, uint8_t); +static int siba_pci_switchcore_sub(struct siba_softc *, uint8_t); +static uint32_t siba_scan_read_4(struct siba_softc *, uint8_t, uint16_t); +static uint16_t siba_dev2chipid(struct siba_softc *); +static uint16_t siba_pci_read_2(struct siba_dev_softc *, uint16_t); +static uint32_t siba_pci_read_4(struct siba_dev_softc *, uint16_t); +static void siba_pci_write_2(struct siba_dev_softc *, uint16_t, uint16_t); +static void siba_pci_write_4(struct siba_dev_softc *, uint16_t, uint32_t); +static void siba_cc_clock(struct siba_cc *, + enum siba_clock); +static void siba_cc_pmu_init(struct siba_cc *); +static void siba_cc_power_init(struct siba_cc *); +static void siba_cc_powerup_delay(struct siba_cc *); +static int siba_cc_clockfreq(struct siba_cc *, int); +static void siba_cc_pmu1_pll0_init(struct siba_cc *, uint32_t); +static void siba_cc_pmu0_pll0_init(struct siba_cc *, uint32_t); +static enum siba_clksrc siba_cc_clksrc(struct siba_cc *); +static const struct siba_cc_pmu1_plltab *siba_cc_pmu1_plltab_find(uint32_t); +static uint32_t siba_cc_pll_read(struct siba_cc *, uint32_t); +static void siba_cc_pll_write(struct siba_cc *, uint32_t, + uint32_t); +static const struct siba_cc_pmu0_plltab * + siba_cc_pmu0_plltab_findentry(uint32_t); +static int siba_pci_sprom(struct siba_softc *, struct siba_sprom *); +static int siba_sprom_read(struct siba_softc *, uint16_t *, uint16_t); +static int sprom_check_crc(const uint16_t *, size_t); +static uint8_t siba_crc8(uint8_t, uint8_t); +static void siba_sprom_r123(struct siba_sprom *, const uint16_t *); +static void siba_sprom_r45(struct siba_sprom *, const uint16_t *); +static void siba_sprom_r8(struct siba_sprom *, const uint16_t *); +static int8_t siba_sprom_r123_antgain(uint8_t, const uint16_t *, uint16_t, + uint16_t); +static uint32_t siba_tmslow_reject_bitmask(struct siba_dev_softc *); +static uint32_t siba_pcicore_read_4(struct siba_pci *, uint16_t); +static void siba_pcicore_write_4(struct siba_pci *, uint16_t, uint32_t); +static uint32_t siba_pcie_read(struct siba_pci *, uint32_t); +static void siba_pcie_write(struct siba_pci *, uint32_t, uint32_t); +static void siba_pcie_mdio_write(struct siba_pci *, uint8_t, uint8_t, + uint16_t); +static void siba_pci_read_multi_1(struct siba_dev_softc *, void *, size_t, + uint16_t); +static void siba_pci_read_multi_2(struct siba_dev_softc *, void *, size_t, + uint16_t); +static void siba_pci_read_multi_4(struct siba_dev_softc *, void *, size_t, + uint16_t); +static void siba_pci_write_multi_1(struct siba_dev_softc *, const void *, + size_t, uint16_t); +static void siba_pci_write_multi_2(struct siba_dev_softc *, const void *, + size_t, uint16_t); +static void siba_pci_write_multi_4(struct siba_dev_softc *, const void *, + size_t, uint16_t); +static const char *siba_core_name(uint16_t); +static void siba_pcicore_init(struct siba_pci *); +device_t siba_add_child(device_t, struct siba_softc *, int, const char *, + int); +int siba_core_attach(struct siba_softc *); +int siba_core_detach(struct siba_softc *); +int siba_core_suspend(struct siba_softc *); +int siba_core_resume(struct siba_softc *); +uint8_t siba_getncores(device_t, uint16_t); + +static const struct siba_bus_ops siba_pci_ops = { + .read_2 = siba_pci_read_2, + .read_4 = siba_pci_read_4, + .write_2 = siba_pci_write_2, + .write_4 = siba_pci_write_4, + .read_multi_1 = siba_pci_read_multi_1, + .read_multi_2 = siba_pci_read_multi_2, + .read_multi_4 = siba_pci_read_multi_4, + .write_multi_1 = siba_pci_write_multi_1, + .write_multi_2 = siba_pci_write_multi_2, + .write_multi_4 = siba_pci_write_multi_4, +}; + +static const struct siba_cc_pmu_res_updown siba_cc_pmu_4325_updown[] = + SIBA_CC_PMU_4325_RES_UPDOWN; +static const struct siba_cc_pmu_res_depend siba_cc_pmu_4325_depend[] = + SIBA_CC_PMU_4325_RES_DEPEND; +static const struct siba_cc_pmu_res_updown siba_cc_pmu_4328_updown[] = + SIBA_CC_PMU_4328_RES_UPDOWN; +static const struct siba_cc_pmu_res_depend siba_cc_pmu_4328_depend[] = + SIBA_CC_PMU_4328_RES_DEPEND; +static const struct siba_cc_pmu0_plltab siba_cc_pmu0_plltab[] = + SIBA_CC_PMU0_PLLTAB_ENTRY; +static const struct siba_cc_pmu1_plltab siba_cc_pmu1_plltab[] = + SIBA_CC_PMU1_PLLTAB_ENTRY; + +int +siba_core_attach(struct siba_softc *siba) +{ + struct siba_cc *scc; + int error; + + KASSERT(siba->siba_type == SIBA_TYPE_PCI, + ("unsupported BUS type (%#x)", siba->siba_type)); + + siba->siba_ops = &siba_pci_ops; + + siba_pci_gpio(siba, SIBA_GPIO_CRYSTAL | SIBA_GPIO_PLL, 1); + siba_scan(siba); + + /* XXX init PCI or PCMCIA host devices */ + + siba_powerup(siba, 0); + + /* init ChipCommon */ + scc = &siba->siba_cc; + if (scc->scc_dev != NULL) { + siba_cc_pmu_init(scc); + siba_cc_power_init(scc); + siba_cc_clock(scc, SIBA_CLOCK_FAST); + siba_cc_powerup_delay(scc); + } + + /* fetch various internal informations for PCI */ + siba->siba_board_vendor = pci_read_config(siba->siba_dev, + PCIR_SUBVEND_0, 2); + siba->siba_board_type = pci_read_config(siba->siba_dev, PCIR_SUBDEV_0, + 2); + siba->siba_board_rev = pci_read_config(siba->siba_dev, PCIR_REVID, 2); + error = siba_pci_sprom(siba, &siba->siba_sprom); + if (error) { + siba_powerdown(siba); + return (error); + } + + siba_powerdown(siba); + return (0); +} + +int +siba_core_detach(struct siba_softc *siba) +{ + device_t *devlistp; + int devcnt, error = 0, i; + + error = device_get_children(siba->siba_dev, &devlistp, &devcnt); + if (error != 0) + return (0); + + for ( i = 0 ; i < devcnt ; i++) + device_delete_child(siba->siba_dev, devlistp[i]); + free(devlistp, M_TEMP); + return (0); +} + +static void +siba_pci_gpio(struct siba_softc *siba, uint32_t what, int on) +{ + uint32_t in, out; + uint16_t status; + + if (siba->siba_type != SIBA_TYPE_PCI) + return; + + out = pci_read_config(siba->siba_dev, SIBA_GPIO_OUT, 4); + if (on == 0) { + if (what & SIBA_GPIO_PLL) + out |= SIBA_GPIO_PLL; + if (what & SIBA_GPIO_CRYSTAL) + out &= ~SIBA_GPIO_CRYSTAL; + pci_write_config(siba->siba_dev, SIBA_GPIO_OUT, out, 4); + pci_write_config(siba->siba_dev, SIBA_GPIO_OUT_EN, + pci_read_config(siba->siba_dev, + SIBA_GPIO_OUT_EN, 4) | what, 4); + return; + } + + in = pci_read_config(siba->siba_dev, SIBA_GPIO_IN, 4); + if ((in & SIBA_GPIO_CRYSTAL) != SIBA_GPIO_CRYSTAL) { + if (what & SIBA_GPIO_CRYSTAL) { + out |= SIBA_GPIO_CRYSTAL; + if (what & SIBA_GPIO_PLL) + out |= SIBA_GPIO_PLL; + pci_write_config(siba->siba_dev, SIBA_GPIO_OUT, out, 4); + pci_write_config(siba->siba_dev, + SIBA_GPIO_OUT_EN, pci_read_config(siba->siba_dev, + SIBA_GPIO_OUT_EN, 4) | what, 4); + DELAY(1000); + } + if (what & SIBA_GPIO_PLL) { + out &= ~SIBA_GPIO_PLL; + pci_write_config(siba->siba_dev, SIBA_GPIO_OUT, out, 4); + DELAY(5000); + } + } + + status = pci_read_config(siba->siba_dev, PCIR_STATUS, 2); + status &= ~PCIM_STATUS_STABORT; + pci_write_config(siba->siba_dev, PCIR_STATUS, status, 2); +} + +static void +siba_scan(struct siba_softc *siba) +{ + struct siba_dev_softc *sd; + uint32_t idhi, tmp; + int base, dev_i = 0, error, i, is_pcie, n_80211 = 0, n_cc = 0, + n_pci = 0; + + KASSERT(siba->siba_type == SIBA_TYPE_PCI, + ("unsupported BUS type (%#x)", siba->siba_type)); + + siba->siba_ndevs = 0; + error = siba_switchcore(siba, 0); /* need the first core */ + if (error) + return; + + idhi = siba_scan_read_4(siba, 0, SIBA_IDHIGH); + if (SIBA_IDHIGH_CORECODE(idhi) == SIBA_DEVID_CHIPCOMMON) { + tmp = siba_scan_read_4(siba, 0, SIBA_CC_CHIPID); + siba->siba_chipid = SIBA_CC_ID(tmp); + siba->siba_chiprev = SIBA_CC_REV(tmp); + siba->siba_chippkg = SIBA_CC_PKG(tmp); + if (SIBA_IDHIGH_REV(idhi) >= 4) + siba->siba_ndevs = SIBA_CC_NCORES(tmp); + siba->siba_cc.scc_caps = siba_scan_read_4(siba, 0, + SIBA_CC_CAPS); + } else { + if (siba->siba_type == SIBA_TYPE_PCI) { + siba->siba_chipid = siba_dev2chipid(siba); + siba->siba_chiprev = pci_read_config(siba->siba_dev, + PCIR_REVID, 2); + siba->siba_chippkg = 0; + } else { + siba->siba_chipid = 0x4710; + siba->siba_chiprev = 0; + siba->siba_chippkg = 0; + } + } + if (siba->siba_ndevs == 0) + siba->siba_ndevs = siba_getncores(siba->siba_dev, + siba->siba_chipid); + if (siba->siba_ndevs > SIBA_MAX_CORES) { + device_printf(siba->siba_dev, + "too many siba cores (max %d %d)\n", + SIBA_MAX_CORES, siba->siba_ndevs); + return; + } + + /* looking basic information about each cores/devices */ + for (i = 0; i < siba->siba_ndevs; i++) { + error = siba_switchcore(siba, i); + if (error) + return; + sd = &(siba->siba_devs[dev_i]); + idhi = siba_scan_read_4(siba, i, SIBA_IDHIGH); + sd->sd_bus = siba; + sd->sd_id.sd_device = SIBA_IDHIGH_CORECODE(idhi); + sd->sd_id.sd_rev = SIBA_IDHIGH_REV(idhi); + sd->sd_id.sd_vendor = SIBA_IDHIGH_VENDOR(idhi); + sd->sd_ops = siba->siba_ops; + sd->sd_coreidx = i; + + DPRINTF(siba, SIBA_DEBUG_SCAN, + "core %d (%s) found (cc %#xrev %#x vendor %#x)\n", + i, siba_core_name(sd->sd_id.sd_device), + sd->sd_id.sd_device, sd->sd_id.sd_rev, sd->sd_id.vendor); + + switch (sd->sd_id.sd_device) { + case SIBA_DEVID_CHIPCOMMON: + n_cc++; + if (n_cc > 1) { + device_printf(siba->siba_dev, + "warn: multiple ChipCommon\n"); + break; + } + siba->siba_cc.scc_dev = sd; + break; + case SIBA_DEVID_80211: + n_80211++; + if (n_80211 > 1) { + device_printf(siba->siba_dev, + "warn: multiple 802.11 core\n"); + continue; + } + break; + case SIBA_DEVID_PCI: + case SIBA_DEVID_PCIE: + n_pci++; + error = pci_find_extcap(siba->siba_dev, PCIY_EXPRESS, + &base); + is_pcie = (error == 0) ? 1 : 0; + + if (n_pci > 1) { + device_printf(siba->siba_dev, + "warn: multiple PCI(E) cores\n"); + break; + } + if (sd->sd_id.sd_device == SIBA_DEVID_PCI && + is_pcie == 1) *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***