xref: /dflybsd-src/sys/dev/netif/bwn/siba/siba_bwn.c (revision df052c2a9588fe12c7a2df4e61e2bfa3f3e16ce0)
1cab56aceSImre Vadasz /*-
2cab56aceSImre Vadasz  * Copyright (c) 2009-2010 Weongyo Jeong <weongyo@freebsd.org>
3cab56aceSImre Vadasz  * All rights reserved.
4cab56aceSImre Vadasz  *
5cab56aceSImre Vadasz  * Redistribution and use in source and binary forms, with or without
6cab56aceSImre Vadasz  * modification, are permitted provided that the following conditions
7cab56aceSImre Vadasz  * are met:
8cab56aceSImre Vadasz  * 1. Redistributions of source code must retain the above copyright
9cab56aceSImre Vadasz  *    notice, this list of conditions and the following disclaimer,
10cab56aceSImre Vadasz  *    without modification.
11cab56aceSImre Vadasz  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
12cab56aceSImre Vadasz  *    similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
13cab56aceSImre Vadasz  *    redistribution must be conditioned upon including a substantially
14cab56aceSImre Vadasz  *    similar Disclaimer requirement for further binary redistribution.
15cab56aceSImre Vadasz  *
16cab56aceSImre Vadasz  * NO WARRANTY
17cab56aceSImre Vadasz  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18cab56aceSImre Vadasz  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*df052c2aSSascha Wildner  * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTABILITY
20cab56aceSImre Vadasz  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
21cab56aceSImre Vadasz  * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
22cab56aceSImre Vadasz  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23cab56aceSImre Vadasz  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24cab56aceSImre Vadasz  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
25cab56aceSImre Vadasz  * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26cab56aceSImre Vadasz  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
27cab56aceSImre Vadasz  * THE POSSIBILITY OF SUCH DAMAGES.
28cab56aceSImre Vadasz  */
29cab56aceSImre Vadasz 
30cab56aceSImre Vadasz #include <sys/cdefs.h>
317872accfSImre Vadász __FBSDID("$FreeBSD: head/sys/dev/siba/siba_bwn.c 299409 2016-05-11 06:27:46Z adrian $");
32cab56aceSImre Vadasz 
33cab56aceSImre Vadasz /*
34cab56aceSImre Vadasz  * Sonics Silicon Backplane front-end for bwn(4).
35cab56aceSImre Vadasz  */
36cab56aceSImre Vadasz 
377872accfSImre Vadász #if defined(__DragonFly__)
38a0ab8429SImre Vadasz #include <opt_siba.h>
397872accfSImre Vadász #endif
40a0ab8429SImre Vadasz 
41cab56aceSImre Vadasz #include <sys/param.h>
42cab56aceSImre Vadasz #include <sys/systm.h>
43cab56aceSImre Vadasz #include <sys/malloc.h>
44cab56aceSImre Vadasz #include <sys/module.h>
45cab56aceSImre Vadasz #include <sys/kernel.h>
467872accfSImre Vadász #include <sys/lock.h>
47cab56aceSImre Vadasz #include <sys/errno.h>
487872accfSImre Vadász #if !defined(__DragonFly__)
497872accfSImre Vadász #include <machine/bus.h>
507872accfSImre Vadász #include <machine/resource.h>
517872accfSImre Vadász #endif
52cab56aceSImre Vadasz #include <sys/bus.h>
53cab56aceSImre Vadasz #include <sys/rman.h>
54cab56aceSImre Vadasz #include <sys/socket.h>
55cab56aceSImre Vadasz 
567872accfSImre Vadász #include <net/if.h>
577872accfSImre Vadász #include <net/if_media.h>
587872accfSImre Vadász #include <net/if_arp.h>
597872accfSImre Vadász 
607872accfSImre Vadász #if defined(__DragonFly__)
61a0ab8429SImre Vadasz #include <bus/pci/pcivar.h>
62a0ab8429SImre Vadasz #include <bus/pci/pcireg.h>
637872accfSImre Vadász #else
647872accfSImre Vadász #include <dev/pci/pcivar.h>
657872accfSImre Vadász #include <dev/pci/pcireg.h>
667872accfSImre Vadász #endif
67cab56aceSImre Vadasz 
687872accfSImre Vadász #if defined(__DragonFly__)
69296bc678SImre Vadasz #include "siba_ids.h"
70296bc678SImre Vadasz #include "sibareg.h"
71296bc678SImre Vadasz #include "sibavar.h"
727872accfSImre Vadász #else
737872accfSImre Vadász #include <dev/siba/siba_ids.h>
747872accfSImre Vadász #include <dev/siba/sibareg.h>
757872accfSImre Vadász #include <dev/siba/sibavar.h>
767872accfSImre Vadász #endif
77cab56aceSImre Vadasz 
78cab56aceSImre Vadasz /*
79cab56aceSImre Vadasz  * PCI glue.
80cab56aceSImre Vadasz  */
81cab56aceSImre Vadasz 
82cab56aceSImre Vadasz struct siba_bwn_softc {
83cab56aceSImre Vadasz 	/* Child driver using MSI. */
84cab56aceSImre Vadasz 	device_t			ssc_msi_child;
85cab56aceSImre Vadasz 	struct siba_softc		ssc_siba;
86cab56aceSImre Vadasz };
87cab56aceSImre Vadasz 
88cab56aceSImre Vadasz #define	BS_BAR				0x10
89cab56aceSImre Vadasz #define	PCI_VENDOR_BROADCOM		0x14e4
90cab56aceSImre Vadasz 
91cab56aceSImre Vadasz static const struct siba_dev {
92cab56aceSImre Vadasz 	uint16_t	vid;
93cab56aceSImre Vadasz 	uint16_t	did;
94cab56aceSImre Vadasz 	const char	*desc;
95cab56aceSImre Vadasz } siba_devices[] = {
96cab56aceSImre Vadasz 	{ PCI_VENDOR_BROADCOM, 0x4301, "Broadcom BCM4301 802.11b Wireless" },
97cab56aceSImre Vadasz 	{ PCI_VENDOR_BROADCOM, 0x4306, "Unknown" },
98cab56aceSImre Vadasz 	{ PCI_VENDOR_BROADCOM, 0x4307, "Broadcom BCM4307 802.11b Wireless" },
99cab56aceSImre Vadasz 	{ PCI_VENDOR_BROADCOM, 0x4311, "Broadcom BCM4311 802.11b/g Wireless" },
100cab56aceSImre Vadasz 	{ PCI_VENDOR_BROADCOM, 0x4312,
101cab56aceSImre Vadasz 	  "Broadcom BCM4312 802.11a/b/g Wireless" },
102cab56aceSImre Vadasz 	{ PCI_VENDOR_BROADCOM, 0x4315, "Broadcom BCM4312 802.11b/g Wireless" },
103cab56aceSImre Vadasz 	{ PCI_VENDOR_BROADCOM, 0x4318, "Broadcom BCM4318 802.11b/g Wireless" },
104cab56aceSImre Vadasz 	{ PCI_VENDOR_BROADCOM, 0x4319,
105cab56aceSImre Vadasz 	  "Broadcom BCM4318 802.11a/b/g Wireless" },
106cab56aceSImre Vadasz 	{ PCI_VENDOR_BROADCOM, 0x4320, "Broadcom BCM4306 802.11b/g Wireless" },
107cab56aceSImre Vadasz 	{ PCI_VENDOR_BROADCOM, 0x4321, "Broadcom BCM4306 802.11a Wireless" },
108cab56aceSImre Vadasz 	{ PCI_VENDOR_BROADCOM, 0x4324,
109cab56aceSImre Vadasz 	  "Broadcom BCM4309 802.11a/b/g Wireless" },
110cab56aceSImre Vadasz 	{ PCI_VENDOR_BROADCOM, 0x4325, "Broadcom BCM4306 802.11b/g Wireless" },
1117872accfSImre Vadász 	{ PCI_VENDOR_BROADCOM, 0x4328, "Broadcom BCM4321 802.11a/b/g Wireless" },
112cab56aceSImre Vadasz 	{ PCI_VENDOR_BROADCOM, 0x4329, "Unknown" },
113cab56aceSImre Vadasz 	{ PCI_VENDOR_BROADCOM, 0x432b, "Unknown" }
114cab56aceSImre Vadasz };
115cab56aceSImre Vadasz 
116cab56aceSImre Vadasz int		siba_core_attach(struct siba_softc *);
117cab56aceSImre Vadasz int		siba_core_detach(struct siba_softc *);
118cab56aceSImre Vadasz int		siba_core_suspend(struct siba_softc *);
119cab56aceSImre Vadasz int		siba_core_resume(struct siba_softc *);
120cab56aceSImre Vadasz 
121cab56aceSImre Vadasz static int
siba_bwn_probe(device_t dev)122cab56aceSImre Vadasz siba_bwn_probe(device_t dev)
123cab56aceSImre Vadasz {
124cab56aceSImre Vadasz 	int i;
125cab56aceSImre Vadasz 	uint16_t did, vid;
126cab56aceSImre Vadasz 
127cab56aceSImre Vadasz 	did = pci_get_device(dev);
128cab56aceSImre Vadasz 	vid = pci_get_vendor(dev);
129cab56aceSImre Vadasz 
130249483dfSAaron LI 	for (i = 0; i < nitems(siba_devices); i++) {
131cab56aceSImre Vadasz 		if (siba_devices[i].did == did && siba_devices[i].vid == vid) {
132cab56aceSImre Vadasz 			device_set_desc(dev, siba_devices[i].desc);
133cab56aceSImre Vadasz 			return (BUS_PROBE_DEFAULT);
134cab56aceSImre Vadasz 		}
135cab56aceSImre Vadasz 	}
136cab56aceSImre Vadasz 	return (ENXIO);
137cab56aceSImre Vadasz }
138cab56aceSImre Vadasz 
139cab56aceSImre Vadasz static int
siba_bwn_attach(device_t dev)140cab56aceSImre Vadasz siba_bwn_attach(device_t dev)
141cab56aceSImre Vadasz {
142cab56aceSImre Vadasz 	struct siba_bwn_softc *ssc = device_get_softc(dev);
143cab56aceSImre Vadasz 	struct siba_softc *siba = &ssc->ssc_siba;
144cab56aceSImre Vadasz 
145cab56aceSImre Vadasz 	siba->siba_dev = dev;
146cab56aceSImre Vadasz 	siba->siba_type = SIBA_TYPE_PCI;
147cab56aceSImre Vadasz 
148cab56aceSImre Vadasz 	/*
149cab56aceSImre Vadasz 	 * Enable bus mastering.
150cab56aceSImre Vadasz 	 */
151cab56aceSImre Vadasz 	pci_enable_busmaster(dev);
152cab56aceSImre Vadasz 
153cab56aceSImre Vadasz 	/*
154cab56aceSImre Vadasz 	 * Setup memory-mapping of PCI registers.
155cab56aceSImre Vadasz 	 */
156cab56aceSImre Vadasz 	siba->siba_mem_rid = SIBA_PCIR_BAR;
157cab56aceSImre Vadasz 	siba->siba_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
158cab56aceSImre Vadasz 		&siba->siba_mem_rid, RF_ACTIVE);
159cab56aceSImre Vadasz 	if (siba->siba_mem_res == NULL) {
160cab56aceSImre Vadasz 		device_printf(dev, "cannot map register space\n");
161cab56aceSImre Vadasz 		return (ENXIO);
162cab56aceSImre Vadasz 	}
163cab56aceSImre Vadasz 	siba->siba_mem_bt = rman_get_bustag(siba->siba_mem_res);
164cab56aceSImre Vadasz 	siba->siba_mem_bh = rman_get_bushandle(siba->siba_mem_res);
165cab56aceSImre Vadasz 
166cab56aceSImre Vadasz 	/* Get more PCI information */
167cab56aceSImre Vadasz 	siba->siba_pci_did = pci_get_device(dev);
168cab56aceSImre Vadasz 	siba->siba_pci_vid = pci_get_vendor(dev);
169cab56aceSImre Vadasz 	siba->siba_pci_subvid = pci_get_subvendor(dev);
170cab56aceSImre Vadasz 	siba->siba_pci_subdid = pci_get_subdevice(dev);
171cab56aceSImre Vadasz 	siba->siba_pci_revid = pci_get_revid(dev);
172cab56aceSImre Vadasz 
173cab56aceSImre Vadasz 	return (siba_core_attach(siba));
174cab56aceSImre Vadasz }
175cab56aceSImre Vadasz 
176cab56aceSImre Vadasz static int
siba_bwn_detach(device_t dev)177cab56aceSImre Vadasz siba_bwn_detach(device_t dev)
178cab56aceSImre Vadasz {
179cab56aceSImre Vadasz 	struct siba_bwn_softc *ssc = device_get_softc(dev);
180cab56aceSImre Vadasz 	struct siba_softc *siba = &ssc->ssc_siba;
181cab56aceSImre Vadasz 
182cab56aceSImre Vadasz 	/* check if device was removed */
183cab56aceSImre Vadasz 	siba->siba_invalid = !bus_child_present(dev);
184cab56aceSImre Vadasz 
185cab56aceSImre Vadasz 	pci_disable_busmaster(dev);
186cab56aceSImre Vadasz 	bus_generic_detach(dev);
187cab56aceSImre Vadasz 	siba_core_detach(siba);
188cab56aceSImre Vadasz 
189cab56aceSImre Vadasz 	bus_release_resource(dev, SYS_RES_MEMORY, BS_BAR, siba->siba_mem_res);
190cab56aceSImre Vadasz 
191cab56aceSImre Vadasz 	return (0);
192cab56aceSImre Vadasz }
193cab56aceSImre Vadasz 
194cab56aceSImre Vadasz static int
siba_bwn_shutdown(device_t dev)195cab56aceSImre Vadasz siba_bwn_shutdown(device_t dev)
196cab56aceSImre Vadasz {
197cab56aceSImre Vadasz 	device_t *devlistp;
198cab56aceSImre Vadasz 	int devcnt, error = 0, i;
199cab56aceSImre Vadasz 
200cab56aceSImre Vadasz 	error = device_get_children(dev, &devlistp, &devcnt);
201cab56aceSImre Vadasz 	if (error != 0)
202cab56aceSImre Vadasz 		return (error);
203cab56aceSImre Vadasz 
204cab56aceSImre Vadasz 	for (i = 0 ; i < devcnt ; i++)
205cab56aceSImre Vadasz 		device_shutdown(devlistp[i]);
206a0ab8429SImre Vadasz 	kfree(devlistp, M_TEMP);
207cab56aceSImre Vadasz 	return (0);
208cab56aceSImre Vadasz }
209cab56aceSImre Vadasz 
210cab56aceSImre Vadasz static int
siba_bwn_suspend(device_t dev)211cab56aceSImre Vadasz siba_bwn_suspend(device_t dev)
212cab56aceSImre Vadasz {
213cab56aceSImre Vadasz 	struct siba_bwn_softc *ssc = device_get_softc(dev);
214cab56aceSImre Vadasz 	struct siba_softc *siba = &ssc->ssc_siba;
215cab56aceSImre Vadasz 	device_t *devlistp;
216cab56aceSImre Vadasz 	int devcnt, error = 0, i, j;
217cab56aceSImre Vadasz 
218cab56aceSImre Vadasz 	error = device_get_children(dev, &devlistp, &devcnt);
219cab56aceSImre Vadasz 	if (error != 0)
220cab56aceSImre Vadasz 		return (error);
221cab56aceSImre Vadasz 
222cab56aceSImre Vadasz 	for (i = 0 ; i < devcnt ; i++) {
223cab56aceSImre Vadasz 		error = DEVICE_SUSPEND(devlistp[i]);
224cab56aceSImre Vadasz 		if (error) {
225cab56aceSImre Vadasz 			for (j = 0; j < i; j++)
226cab56aceSImre Vadasz 				DEVICE_RESUME(devlistp[j]);
227a0ab8429SImre Vadasz 			kfree(devlistp, M_TEMP);
228cab56aceSImre Vadasz 			return (error);
229cab56aceSImre Vadasz 		}
230cab56aceSImre Vadasz 	}
231a0ab8429SImre Vadasz 	kfree(devlistp, M_TEMP);
232cab56aceSImre Vadasz 	return (siba_core_suspend(siba));
233cab56aceSImre Vadasz }
234cab56aceSImre Vadasz 
235cab56aceSImre Vadasz static int
siba_bwn_resume(device_t dev)236cab56aceSImre Vadasz siba_bwn_resume(device_t dev)
237cab56aceSImre Vadasz {
238cab56aceSImre Vadasz 	struct siba_bwn_softc *ssc = device_get_softc(dev);
239cab56aceSImre Vadasz 	struct siba_softc *siba = &ssc->ssc_siba;
240cab56aceSImre Vadasz 	device_t *devlistp;
241cab56aceSImre Vadasz 	int devcnt, error = 0, i;
242cab56aceSImre Vadasz 
243cab56aceSImre Vadasz 	error = siba_core_resume(siba);
244cab56aceSImre Vadasz 	if (error != 0)
245cab56aceSImre Vadasz 		return (error);
246cab56aceSImre Vadasz 
247cab56aceSImre Vadasz 	error = device_get_children(dev, &devlistp, &devcnt);
248cab56aceSImre Vadasz 	if (error != 0)
249cab56aceSImre Vadasz 		return (error);
250cab56aceSImre Vadasz 
251cab56aceSImre Vadasz 	for (i = 0 ; i < devcnt ; i++)
252cab56aceSImre Vadasz 		DEVICE_RESUME(devlistp[i]);
253a0ab8429SImre Vadasz 	kfree(devlistp, M_TEMP);
254cab56aceSImre Vadasz 	return (0);
255cab56aceSImre Vadasz }
256cab56aceSImre Vadasz 
257cab56aceSImre Vadasz /* proxying to the parent */
2587872accfSImre Vadász #if defined(__DragonFly__)
259cab56aceSImre Vadasz 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,int cpuid)260cab56aceSImre Vadasz siba_bwn_alloc_resource(device_t dev, device_t child, int type, int *rid,
261a0ab8429SImre Vadasz     u_long start, u_long end, u_long count, u_int flags, int cpuid)
262cab56aceSImre Vadasz {
263cab56aceSImre Vadasz 
264cab56aceSImre Vadasz 	return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
265a0ab8429SImre Vadasz 	    type, rid, start, end, count, flags, cpuid));
266cab56aceSImre Vadasz }
2677872accfSImre Vadász #else
2687872accfSImre Vadász static struct resource *
siba_bwn_alloc_resource(device_t dev,device_t child,int type,int * rid,rman_res_t start,rman_res_t end,rman_res_t count,u_int flags)2697872accfSImre Vadász siba_bwn_alloc_resource(device_t dev, device_t child, int type, int *rid,
2707872accfSImre Vadász     rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
2717872accfSImre Vadász {
2727872accfSImre Vadász 
2737872accfSImre Vadász 	return (BUS_ALLOC_RESOURCE(device_get_parent(dev), dev,
2747872accfSImre Vadász 	    type, rid, start, end, count, flags));
2757872accfSImre Vadász }
2767872accfSImre Vadász #endif
277cab56aceSImre Vadasz 
278cab56aceSImre Vadasz /* proxying to the parent */
279cab56aceSImre Vadasz static int
siba_bwn_release_resource(device_t dev,device_t child,int type,int rid,struct resource * r)280cab56aceSImre Vadasz siba_bwn_release_resource(device_t dev, device_t child, int type,
281cab56aceSImre Vadasz     int rid, struct resource *r)
282cab56aceSImre Vadasz {
283cab56aceSImre Vadasz 
284cab56aceSImre Vadasz 	return (BUS_RELEASE_RESOURCE(device_get_parent(dev), dev, type,
285cab56aceSImre Vadasz 	    rid, r));
286cab56aceSImre Vadasz }
287cab56aceSImre Vadasz 
2887872accfSImre Vadász #if defined(__DragonFly__)
289cab56aceSImre Vadasz /* proxying to the parent */
290cab56aceSImre Vadasz static int
siba_bwn_setup_intr(device_t dev,device_t child,struct resource * irq,int flags,driver_intr_t * intr,void * arg,void ** cookiep,lwkt_serialize_t serializer)291cab56aceSImre Vadasz siba_bwn_setup_intr(device_t dev, device_t child, struct resource *irq,
292a0ab8429SImre Vadasz     int flags, driver_intr_t *intr, void *arg, void **cookiep,
293a0ab8429SImre Vadasz     lwkt_serialize_t serializer)
294cab56aceSImre Vadasz {
295cab56aceSImre Vadasz 
296cab56aceSImre Vadasz 	return (BUS_SETUP_INTR(device_get_parent(dev), dev, irq, flags,
297a0ab8429SImre Vadasz 	    intr, arg, cookiep, serializer, NULL));
298cab56aceSImre Vadasz }
2997872accfSImre Vadász #else
3007872accfSImre Vadász 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)3017872accfSImre Vadász siba_bwn_setup_intr(device_t dev, device_t child, struct resource *irq,
3027872accfSImre Vadász     int flags, driver_filter_t *filter, driver_intr_t *intr, void *arg,
3037872accfSImre Vadász     void **cookiep)
3047872accfSImre Vadász {
3057872accfSImre Vadász 
3067872accfSImre Vadász 	return (BUS_SETUP_INTR(device_get_parent(dev), dev, irq, flags,
3077872accfSImre Vadász 	    filter, intr, arg, cookiep));
3087872accfSImre Vadász }
3097872accfSImre Vadász #endif
310cab56aceSImre Vadasz 
311cab56aceSImre Vadasz /* proxying to the parent */
312cab56aceSImre Vadasz static int
siba_bwn_teardown_intr(device_t dev,device_t child,struct resource * irq,void * cookie)313cab56aceSImre Vadasz siba_bwn_teardown_intr(device_t dev, device_t child, struct resource *irq,
314cab56aceSImre Vadasz     void *cookie)
315cab56aceSImre Vadasz {
316cab56aceSImre Vadasz 
317cab56aceSImre Vadasz 	return (BUS_TEARDOWN_INTR(device_get_parent(dev), dev, irq, cookie));
318cab56aceSImre Vadasz }
319cab56aceSImre Vadasz 
3207872accfSImre Vadász #if !defined(__DragonFly__)
3217872accfSImre Vadász static int
siba_bwn_find_cap(device_t dev,device_t child,int capability,int * capreg)3227872accfSImre Vadász siba_bwn_find_cap(device_t dev, device_t child, int capability,
3237872accfSImre Vadász     int *capreg)
3247872accfSImre Vadász {
3257872accfSImre Vadász 
3267872accfSImre Vadász 	return (pci_find_cap(dev, capability, capreg));
3277872accfSImre Vadász }
3287872accfSImre Vadász #endif
3297872accfSImre Vadász 
330cab56aceSImre Vadasz static int
siba_bwn_find_extcap(device_t dev,device_t child,int capability,int * capreg)331cab56aceSImre Vadasz siba_bwn_find_extcap(device_t dev, device_t child, int capability,
332cab56aceSImre Vadasz     int *capreg)
333cab56aceSImre Vadasz {
334cab56aceSImre Vadasz 
335cab56aceSImre Vadasz 	return (pci_find_extcap(dev, capability, capreg));
336cab56aceSImre Vadasz }
337cab56aceSImre Vadasz 
3387872accfSImre Vadász #if !defined(__DragonFly__)
3397872accfSImre Vadász static int
siba_bwn_find_htcap(device_t dev,device_t child,int capability,int * capreg)3407872accfSImre Vadász siba_bwn_find_htcap(device_t dev, device_t child, int capability,
3417872accfSImre Vadász     int *capreg)
3427872accfSImre Vadász {
3437872accfSImre Vadász 
3447872accfSImre Vadász 	return (pci_find_htcap(dev, capability, capreg));
3457872accfSImre Vadász }
3467872accfSImre Vadász #endif
3477872accfSImre Vadász 
3487872accfSImre Vadász #if defined(__DragonFly__)
349cab56aceSImre Vadasz static int
siba_bwn_alloc_msi(device_t dev,device_t child,int * rid,int count,int cpuid)350a0ab8429SImre Vadasz siba_bwn_alloc_msi(device_t dev, device_t child, int *rid, int count,
351a0ab8429SImre Vadasz     int cpuid)
3527872accfSImre Vadász #else
3537872accfSImre Vadász static int
3547872accfSImre Vadász siba_bwn_alloc_msi(device_t dev, device_t child, int *count)
3557872accfSImre Vadász #endif
356cab56aceSImre Vadasz {
357cab56aceSImre Vadasz 	struct siba_bwn_softc *ssc;
358cab56aceSImre Vadasz 	int error;
359cab56aceSImre Vadasz 
360cab56aceSImre Vadasz 	ssc = device_get_softc(dev);
361cab56aceSImre Vadasz 	if (ssc->ssc_msi_child != NULL)
362cab56aceSImre Vadasz 		return (EBUSY);
3637872accfSImre Vadász #if defined(__DragonFly__)
364a0ab8429SImre Vadasz 	error = pci_alloc_msi(dev, rid, count, cpuid);
3657872accfSImre Vadász #else
3667872accfSImre Vadász 	error = pci_alloc_msi(dev, count);
3677872accfSImre Vadász #endif
368cab56aceSImre Vadasz 	if (error == 0)
369cab56aceSImre Vadasz 		ssc->ssc_msi_child = child;
370cab56aceSImre Vadasz 	return (error);
371cab56aceSImre Vadasz }
372cab56aceSImre Vadasz 
373cab56aceSImre Vadasz static int
siba_bwn_release_msi(device_t dev,device_t child)374cab56aceSImre Vadasz siba_bwn_release_msi(device_t dev, device_t child)
375cab56aceSImre Vadasz {
376cab56aceSImre Vadasz 	struct siba_bwn_softc *ssc;
377cab56aceSImre Vadasz 	int error;
378cab56aceSImre Vadasz 
379cab56aceSImre Vadasz 	ssc = device_get_softc(dev);
380cab56aceSImre Vadasz 	if (ssc->ssc_msi_child != child)
381cab56aceSImre Vadasz 		return (ENXIO);
382cab56aceSImre Vadasz 	error = pci_release_msi(dev);
383cab56aceSImre Vadasz 	if (error == 0)
384cab56aceSImre Vadasz 		ssc->ssc_msi_child = NULL;
385cab56aceSImre Vadasz 	return (error);
386cab56aceSImre Vadasz }
387cab56aceSImre Vadasz 
388cab56aceSImre Vadasz static int
siba_bwn_msi_count(device_t dev,device_t child)389cab56aceSImre Vadasz siba_bwn_msi_count(device_t dev, device_t child)
390cab56aceSImre Vadasz {
391cab56aceSImre Vadasz 
392cab56aceSImre Vadasz 	return (pci_msi_count(dev));
393cab56aceSImre Vadasz }
394cab56aceSImre Vadasz 
395cab56aceSImre Vadasz static int
siba_bwn_read_ivar(device_t dev,device_t child,int which,uintptr_t * result)396cab56aceSImre Vadasz siba_bwn_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
397cab56aceSImre Vadasz {
398cab56aceSImre Vadasz 	struct siba_dev_softc *sd;
399cab56aceSImre Vadasz 	struct siba_softc *siba;
400cab56aceSImre Vadasz 
401cab56aceSImre Vadasz 	sd = device_get_ivars(child);
402cab56aceSImre Vadasz 	siba = sd->sd_bus;
403cab56aceSImre Vadasz 
404cab56aceSImre Vadasz 	switch (which) {
405cab56aceSImre Vadasz 	case SIBA_IVAR_VENDOR:
406cab56aceSImre Vadasz 		*result = sd->sd_id.sd_vendor;
407cab56aceSImre Vadasz 		break;
408cab56aceSImre Vadasz 	case SIBA_IVAR_DEVICE:
409cab56aceSImre Vadasz 		*result = sd->sd_id.sd_device;
410cab56aceSImre Vadasz 		break;
411cab56aceSImre Vadasz 	case SIBA_IVAR_REVID:
412cab56aceSImre Vadasz 		*result = sd->sd_id.sd_rev;
413cab56aceSImre Vadasz 		break;
414cab56aceSImre Vadasz 	case SIBA_IVAR_PCI_VENDOR:
415cab56aceSImre Vadasz 		*result = siba->siba_pci_vid;
416cab56aceSImre Vadasz 		break;
417cab56aceSImre Vadasz 	case SIBA_IVAR_PCI_DEVICE:
418cab56aceSImre Vadasz 		*result = siba->siba_pci_did;
419cab56aceSImre Vadasz 		break;
420cab56aceSImre Vadasz 	case SIBA_IVAR_PCI_SUBVENDOR:
421cab56aceSImre Vadasz 		*result = siba->siba_pci_subvid;
422cab56aceSImre Vadasz 		break;
423cab56aceSImre Vadasz 	case SIBA_IVAR_PCI_SUBDEVICE:
424cab56aceSImre Vadasz 		*result = siba->siba_pci_subdid;
425cab56aceSImre Vadasz 		break;
426cab56aceSImre Vadasz 	case SIBA_IVAR_PCI_REVID:
427cab56aceSImre Vadasz 		*result = siba->siba_pci_revid;
428cab56aceSImre Vadasz 		break;
429cab56aceSImre Vadasz 	case SIBA_IVAR_CHIPID:
430cab56aceSImre Vadasz 		*result = siba->siba_chipid;
431cab56aceSImre Vadasz 		break;
432cab56aceSImre Vadasz 	case SIBA_IVAR_CHIPREV:
433cab56aceSImre Vadasz 		*result = siba->siba_chiprev;
434cab56aceSImre Vadasz 		break;
435cab56aceSImre Vadasz 	case SIBA_IVAR_CHIPPKG:
436cab56aceSImre Vadasz 		*result = siba->siba_chippkg;
437cab56aceSImre Vadasz 		break;
438cab56aceSImre Vadasz 	case SIBA_IVAR_TYPE:
439cab56aceSImre Vadasz 		*result = siba->siba_type;
440cab56aceSImre Vadasz 		break;
441cab56aceSImre Vadasz 	case SIBA_IVAR_CC_PMUFREQ:
442cab56aceSImre Vadasz 		*result = siba->siba_cc.scc_pmu.freq;
443cab56aceSImre Vadasz 		break;
444cab56aceSImre Vadasz 	case SIBA_IVAR_CC_CAPS:
445cab56aceSImre Vadasz 		*result = siba->siba_cc.scc_caps;
446cab56aceSImre Vadasz 		break;
447cab56aceSImre Vadasz 	case SIBA_IVAR_CC_POWERDELAY:
448cab56aceSImre Vadasz 		*result = siba->siba_cc.scc_powerup_delay;
449cab56aceSImre Vadasz 		break;
450cab56aceSImre Vadasz 	case SIBA_IVAR_PCICORE_REVID:
451cab56aceSImre Vadasz 		*result = siba->siba_pci.spc_dev->sd_id.sd_rev;
452cab56aceSImre Vadasz 		break;
453cab56aceSImre Vadasz 	default:
454cab56aceSImre Vadasz 		return (ENOENT);
455cab56aceSImre Vadasz 	}
456cab56aceSImre Vadasz 
457cab56aceSImre Vadasz 	return (0);
458cab56aceSImre Vadasz }
459cab56aceSImre Vadasz 
460cab56aceSImre Vadasz static device_method_t siba_bwn_methods[] = {
461cab56aceSImre Vadasz 	/* Device interface */
462cab56aceSImre Vadasz 	DEVMETHOD(device_probe,		siba_bwn_probe),
463cab56aceSImre Vadasz 	DEVMETHOD(device_attach,	siba_bwn_attach),
464cab56aceSImre Vadasz 	DEVMETHOD(device_detach,	siba_bwn_detach),
465cab56aceSImre Vadasz 	DEVMETHOD(device_shutdown,	siba_bwn_shutdown),
466cab56aceSImre Vadasz 	DEVMETHOD(device_suspend,	siba_bwn_suspend),
467cab56aceSImre Vadasz 	DEVMETHOD(device_resume,	siba_bwn_resume),
468cab56aceSImre Vadasz 
469cab56aceSImre Vadasz 	/* Bus interface */
470cab56aceSImre Vadasz 	DEVMETHOD(bus_alloc_resource,   siba_bwn_alloc_resource),
471cab56aceSImre Vadasz 	DEVMETHOD(bus_release_resource, siba_bwn_release_resource),
472cab56aceSImre Vadasz 	DEVMETHOD(bus_read_ivar,	siba_bwn_read_ivar),
473cab56aceSImre Vadasz 	DEVMETHOD(bus_setup_intr,       siba_bwn_setup_intr),
474cab56aceSImre Vadasz 	DEVMETHOD(bus_teardown_intr,    siba_bwn_teardown_intr),
475cab56aceSImre Vadasz 
476cab56aceSImre Vadasz 	/* PCI interface */
4777872accfSImre Vadász #if !defined(__DragonFly__)
4787872accfSImre Vadász 	DEVMETHOD(pci_find_cap,		siba_bwn_find_cap),
4797872accfSImre Vadász #endif
480cab56aceSImre Vadasz 	DEVMETHOD(pci_find_extcap,	siba_bwn_find_extcap),
4817872accfSImre Vadász #if !defined(__DragonFly__)
4827872accfSImre Vadász 	DEVMETHOD(pci_find_htcap,	siba_bwn_find_htcap),
4837872accfSImre Vadász #endif
484cab56aceSImre Vadasz 	DEVMETHOD(pci_alloc_msi,	siba_bwn_alloc_msi),
485cab56aceSImre Vadasz 	DEVMETHOD(pci_release_msi,	siba_bwn_release_msi),
486cab56aceSImre Vadasz 	DEVMETHOD(pci_msi_count,	siba_bwn_msi_count),
487cab56aceSImre Vadasz 
488cab56aceSImre Vadasz 	DEVMETHOD_END
489cab56aceSImre Vadasz };
490cab56aceSImre Vadasz static driver_t siba_bwn_driver = {
491cab56aceSImre Vadasz 	"siba_bwn",
492cab56aceSImre Vadasz 	siba_bwn_methods,
493cab56aceSImre Vadasz 	sizeof(struct siba_bwn_softc)
494cab56aceSImre Vadasz };
495cab56aceSImre Vadasz static devclass_t siba_bwn_devclass;
4963a25be87SSascha Wildner DRIVER_MODULE(siba_bwn, pci, siba_bwn_driver, siba_bwn_devclass, NULL, NULL);
497cab56aceSImre Vadasz MODULE_VERSION(siba_bwn, 1);
498