Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/bwn/if_bwn_pci.c
39534 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2015-2016 Landon Fuller <[email protected]>
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
*
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
* SUCH DAMAGE.
27
*/
28
29
#include <sys/cdefs.h>
30
#include "opt_bwn.h"
31
#include "opt_wlan.h"
32
33
#include <sys/param.h>
34
#include <sys/kernel.h>
35
#include <sys/bus.h>
36
#include <sys/module.h>
37
38
#include <dev/pci/pcireg.h>
39
#include <dev/pci/pcivar.h>
40
41
#include <dev/bhnd/bhndb/bhndb_pcivar.h>
42
#include <dev/bhnd/bhndb/bhndb_hwdata.h>
43
#include <dev/bhnd/bhndb/bhndb_pci_hwdata.h>
44
45
#include <dev/bhnd/bhnd_ids.h>
46
47
#include "bhndb_bus_if.h"
48
49
#include "if_bwn_pcivar.h"
50
51
/* If non-zero, enable attachment of BWN_QUIRK_UNTESTED devices */
52
static int attach_untested = 0;
53
TUNABLE_INT("hw.bwn_pci.attach_untested", &attach_untested);
54
55
/* SIBA Devices */
56
static const struct bwn_pci_device siba_devices[] = {
57
BWN_BCM_DEV(BCM4306_D11A, "BCM4306 802.11a",
58
BWN_QUIRK_WLAN_DUALCORE|BWN_QUIRK_SOFTMODEM_UNPOPULATED),
59
BWN_BCM_DEV(BCM4306_D11G, "BCM4306 802.11b/g",
60
BWN_QUIRK_SOFTMODEM_UNPOPULATED),
61
BWN_BCM_DEV(BCM4306_D11G_ID2, "BCM4306 802.11b/g",
62
BWN_QUIRK_SOFTMODEM_UNPOPULATED),
63
BWN_BCM_DEV(BCM4306_D11DUAL, "BCM4306 802.11a/b/g",
64
BWN_QUIRK_SOFTMODEM_UNPOPULATED),
65
BWN_BCM_DEV(BCM4307, "BCM4307 802.11b", 0),
66
67
BWN_BCM_DEV(BCM4311_D11G, "BCM4311 802.11b/g", 0),
68
BWN_BCM_DEV(BCM4311_D11DUAL, "BCM4311 802.11a/b/g", 0),
69
BWN_BCM_DEV(BCM4311_D11A, "BCM4311 802.11a",
70
BWN_QUIRK_UNTESTED|BWN_QUIRK_WLAN_DUALCORE),
71
72
BWN_BCM_DEV(BCM4318_D11G, "BCM4318 802.11b/g", 0),
73
BWN_BCM_DEV(BCM4318_D11DUAL, "BCM4318 802.11a/b/g", 0),
74
BWN_BCM_DEV(BCM4318_D11A, "BCM4318 802.11a",
75
BWN_QUIRK_UNTESTED|BWN_QUIRK_WLAN_DUALCORE),
76
77
BWN_BCM_DEV(BCM4321_D11N, "BCM4321 802.11n Dual-Band",
78
BWN_QUIRK_USBH_UNPOPULATED),
79
BWN_BCM_DEV(BCM4321_D11N2G, "BCM4321 802.11n 2GHz",
80
BWN_QUIRK_USBH_UNPOPULATED),
81
BWN_BCM_DEV(BCM4321_D11N5G, "BCM4321 802.11n 5GHz",
82
BWN_QUIRK_UNTESTED|BWN_QUIRK_USBH_UNPOPULATED),
83
84
BWN_BCM_DEV(BCM4322_D11N, "BCM4322 802.11n Dual-Band", 0),
85
BWN_BCM_DEV(BCM4322_D11N2G, "BCM4322 802.11n 2GHz",
86
BWN_QUIRK_UNTESTED),
87
BWN_BCM_DEV(BCM4322_D11N5G, "BCM4322 802.11n 5GHz",
88
BWN_QUIRK_UNTESTED),
89
90
BWN_BCM_DEV(BCM4328_D11G, "BCM4328/4312 802.11g", 0),
91
{ 0, 0, NULL, 0 }
92
};
93
94
/** BCMA Devices */
95
static const struct bwn_pci_device bcma_devices[] = {
96
BWN_BCM_DEV(BCM4331_D11N, "BCM4331 802.11n Dual-Band", 0),
97
BWN_BCM_DEV(BCM4331_D11N2G, "BCM4331 802.11n 2GHz", 0),
98
BWN_BCM_DEV(BCM4331_D11N5G, "BCM4331 802.11n 5GHz", 0),
99
BWN_BCM_DEV(BCM43224_D11N, "BCM43224 802.11n Dual-Band", 0),
100
BWN_BCM_DEV(BCM43224_D11N_ID_VEN1, "BCM43224 802.11n Dual-Band",0),
101
BWN_BCM_DEV(BCM43225_D11N2G, "BCM43225 802.11n 2GHz", 0),
102
{ 0, 0, NULL, 0}
103
};
104
105
/** Device configuration table */
106
static const struct bwn_pci_devcfg bwn_pci_devcfgs[] = {
107
/* SIBA devices */
108
{
109
.bridge_hwcfg = &bhndb_pci_siba_generic_hwcfg,
110
.bridge_hwtable = bhndb_pci_generic_hw_table,
111
.bridge_hwprio = bhndb_siba_priority_table,
112
.devices = siba_devices
113
},
114
/* BCMA devices */
115
{
116
.bridge_hwcfg = &bhndb_pci_bcma_generic_hwcfg,
117
.bridge_hwtable = bhndb_pci_generic_hw_table,
118
.bridge_hwprio = bhndb_bcma_priority_table,
119
.devices = bcma_devices
120
},
121
{ NULL, NULL, NULL }
122
};
123
124
/** Search the device configuration table for an entry matching @p dev. */
125
static int
126
bwn_pci_find_devcfg(device_t dev, const struct bwn_pci_devcfg **cfg,
127
const struct bwn_pci_device **device)
128
{
129
const struct bwn_pci_devcfg *dvc;
130
const struct bwn_pci_device *dv;
131
132
for (dvc = bwn_pci_devcfgs; dvc->devices != NULL; dvc++) {
133
for (dv = dvc->devices; dv->device != 0; dv++) {
134
if (pci_get_vendor(dev) == dv->vendor &&
135
pci_get_device(dev) == dv->device)
136
{
137
if (cfg != NULL)
138
*cfg = dvc;
139
140
if (device != NULL)
141
*device = dv;
142
143
return (0);
144
}
145
}
146
}
147
148
return (ENOENT);
149
}
150
151
static int
152
bwn_pci_probe(device_t dev)
153
{
154
const struct bwn_pci_device *ident;
155
156
if (bwn_pci_find_devcfg(dev, NULL, &ident))
157
return (ENXIO);
158
159
/* Skip untested devices */
160
if (ident->quirks & BWN_QUIRK_UNTESTED && !attach_untested)
161
return (ENXIO);
162
163
device_set_desc(dev, ident->desc);
164
return (BUS_PROBE_DEFAULT);
165
}
166
167
static int
168
bwn_pci_attach(device_t dev)
169
{
170
struct bwn_pci_softc *sc;
171
const struct bwn_pci_device *ident;
172
int error;
173
174
sc = device_get_softc(dev);
175
sc->dev = dev;
176
177
/* Find our hardware config */
178
if (bwn_pci_find_devcfg(dev, &sc->devcfg, &ident))
179
return (ENXIO);
180
181
/* Save quirk flags */
182
sc->quirks = ident->quirks;
183
184
/* Attach bridge device */
185
if ((error = bhndb_attach_bridge(dev, &sc->bhndb_dev, DEVICE_UNIT_ANY)))
186
return (ENXIO);
187
188
/* Success */
189
return (0);
190
}
191
192
static void
193
bwn_pci_probe_nomatch(device_t dev, device_t child)
194
{
195
const char *name;
196
197
name = device_get_name(child);
198
if (name == NULL)
199
name = "unknown device";
200
201
device_printf(dev, "<%s> (no driver attached)\n", name);
202
}
203
204
static const struct bhndb_hwcfg *
205
bwn_pci_get_generic_hwcfg(device_t dev, device_t child)
206
{
207
struct bwn_pci_softc *sc = device_get_softc(dev);
208
return (sc->devcfg->bridge_hwcfg);
209
}
210
211
static const struct bhndb_hw *
212
bwn_pci_get_bhndb_hwtable(device_t dev, device_t child)
213
{
214
struct bwn_pci_softc *sc = device_get_softc(dev);
215
return (sc->devcfg->bridge_hwtable);
216
}
217
218
static const struct bhndb_hw_priority *
219
bwn_pci_get_bhndb_hwprio(device_t dev, device_t child)
220
{
221
struct bwn_pci_softc *sc = device_get_softc(dev);
222
return (sc->devcfg->bridge_hwprio);
223
}
224
225
static bool
226
bwn_pci_is_core_disabled(device_t dev, device_t child,
227
struct bhnd_core_info *core)
228
{
229
struct bwn_pci_softc *sc;
230
231
sc = device_get_softc(dev);
232
233
switch (bhnd_core_class(core)) {
234
case BHND_DEVCLASS_WLAN:
235
if (core->unit > 0 && !(sc->quirks & BWN_QUIRK_WLAN_DUALCORE))
236
return (true);
237
238
return (false);
239
240
case BHND_DEVCLASS_ENET:
241
case BHND_DEVCLASS_ENET_MAC:
242
case BHND_DEVCLASS_ENET_PHY:
243
return ((sc->quirks & BWN_QUIRK_ENET_HW_UNPOPULATED) != 0);
244
245
case BHND_DEVCLASS_USB_HOST:
246
return ((sc->quirks & BWN_QUIRK_USBH_UNPOPULATED) != 0);
247
248
case BHND_DEVCLASS_SOFTMODEM:
249
return ((sc->quirks & BWN_QUIRK_SOFTMODEM_UNPOPULATED) != 0);
250
251
default:
252
return (false);
253
}
254
}
255
256
static device_method_t bwn_pci_methods[] = {
257
/* Device interface */
258
DEVMETHOD(device_probe, bwn_pci_probe),
259
DEVMETHOD(device_attach, bwn_pci_attach),
260
DEVMETHOD(device_detach, bus_generic_detach),
261
DEVMETHOD(device_shutdown, bus_generic_shutdown),
262
DEVMETHOD(device_suspend, bus_generic_suspend),
263
DEVMETHOD(device_resume, bus_generic_resume),
264
265
/* Bus interface */
266
DEVMETHOD(bus_probe_nomatch, bwn_pci_probe_nomatch),
267
268
/* BHNDB_BUS Interface */
269
DEVMETHOD(bhndb_bus_get_generic_hwcfg, bwn_pci_get_generic_hwcfg),
270
DEVMETHOD(bhndb_bus_get_hardware_table, bwn_pci_get_bhndb_hwtable),
271
DEVMETHOD(bhndb_bus_get_hardware_prio, bwn_pci_get_bhndb_hwprio),
272
DEVMETHOD(bhndb_bus_is_core_disabled, bwn_pci_is_core_disabled),
273
274
DEVMETHOD_END
275
};
276
277
DEFINE_CLASS_0(bwn_pci, bwn_pci_driver, bwn_pci_methods,
278
sizeof(struct bwn_pci_softc));
279
DRIVER_MODULE_ORDERED(bwn_pci, pci, bwn_pci_driver, NULL, NULL, SI_ORDER_ANY);
280
MODULE_PNP_INFO("U16:vendor;U16:device;D:#", pci, bwn_siba,
281
siba_devices, nitems(siba_devices) - 1);
282
MODULE_PNP_INFO("U16:vendor;U16:device;D:#", pci, bwn_bcma,
283
bcma_devices, nitems(bcma_devices) - 1);
284
DRIVER_MODULE(bhndb, bwn_pci, bhndb_pci_driver, NULL, NULL);
285
286
MODULE_DEPEND(bwn_pci, bwn, 1, 1, 1);
287
MODULE_DEPEND(bwn_pci, bhnd, 1, 1, 1);
288
MODULE_DEPEND(bwn_pci, bhndb, 1, 1, 1);
289
MODULE_DEPEND(bwn_pci, bhndb_pci, 1, 1, 1);
290
MODULE_DEPEND(bwn_pci, bcma_bhndb, 1, 1, 1);
291
MODULE_DEPEND(bwn_pci, siba_bhndb, 1, 1, 1);
292
MODULE_VERSION(bwn_pci, 1);
293
294