1102714Sphk/*	$NetBSD: puc.c,v 1.7 2000/07/29 17:43:38 jlam Exp $	*/
2102714Sphk
3102714Sphk/*-
4102714Sphk * Copyright (c) 2002 JF Hay.  All rights reserved.
5102714Sphk * Copyright (c) 2000 M. Warner Losh.  All rights reserved.
6102714Sphk *
7102714Sphk * Redistribution and use in source and binary forms, with or without
8102714Sphk * modification, are permitted provided that the following conditions
9102714Sphk * are met:
10102714Sphk * 1. Redistributions of source code must retain the above copyright
11140040Simp *    notice, this list of conditions and the following disclaimer.
12102714Sphk * 2. Redistributions in binary form must reproduce the above copyright
13102714Sphk *    notice, this list of conditions and the following disclaimer in the
14102714Sphk *    documentation and/or other materials provided with the distribution.
15102714Sphk *
16140040Simp * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17140040Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18140040Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19140040Simp * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20140040Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21140040Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22140040Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23140040Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24140040Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25140040Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26140040Simp * SUCH DAMAGE.
27102714Sphk */
28102714Sphk
29139749Simp/*-
30102714Sphk * Copyright (c) 1996, 1998, 1999
31102714Sphk *	Christopher G. Demetriou.  All rights reserved.
32102714Sphk *
33102714Sphk * Redistribution and use in source and binary forms, with or without
34102714Sphk * modification, are permitted provided that the following conditions
35102714Sphk * are met:
36102714Sphk * 1. Redistributions of source code must retain the above copyright
37102714Sphk *    notice, this list of conditions and the following disclaimer.
38102714Sphk * 2. Redistributions in binary form must reproduce the above copyright
39102714Sphk *    notice, this list of conditions and the following disclaimer in the
40102714Sphk *    documentation and/or other materials provided with the distribution.
41102714Sphk * 3. All advertising materials mentioning features or use of this software
42102714Sphk *    must display the following acknowledgement:
43102714Sphk *      This product includes software developed by Christopher G. Demetriou
44102714Sphk *	for the NetBSD Project.
45102714Sphk * 4. The name of the author may not be used to endorse or promote products
46102714Sphk *    derived from this software without specific prior written permission
47102714Sphk *
48102714Sphk * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
49102714Sphk * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
50102714Sphk * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
51102714Sphk * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
52102714Sphk * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
53102714Sphk * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
54102714Sphk * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
55102714Sphk * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
56102714Sphk * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
57102714Sphk * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
58102714Sphk */
59102714Sphk
60102714Sphk#include <sys/cdefs.h>
61102714Sphk__FBSDID("$FreeBSD$");
62102714Sphk
63102714Sphk#include <sys/param.h>
64102714Sphk#include <sys/systm.h>
65102714Sphk#include <sys/kernel.h>
66129879Sphk#include <sys/module.h>
67102714Sphk#include <sys/bus.h>
68102714Sphk#include <sys/conf.h>
69102714Sphk#include <sys/malloc.h>
70263109Srstone#include <sys/sysctl.h>
71102714Sphk
72102714Sphk#include <machine/bus.h>
73102714Sphk#include <machine/resource.h>
74102714Sphk#include <sys/rman.h>
75102714Sphk
76102714Sphk#include <dev/pci/pcireg.h>
77102714Sphk#include <dev/pci/pcivar.h>
78102714Sphk
79160030Sobrien#include <dev/puc/puc_cfg.h>
80158124Smarcel#include <dev/puc/puc_bfe.h>
81102714Sphk
82263109Srstonestatic int puc_msi_disable;
83267992ShselaskySYSCTL_INT(_hw_puc, OID_AUTO, msi_disable, CTLFLAG_RDTUN,
84263109Srstone    &puc_msi_disable, 0, "Disable use of MSI interrupts by puc(9)");
85263109Srstone
86158124Smarcelstatic const struct puc_cfg *
87158124Smarcelpuc_pci_match(device_t dev, const struct puc_cfg *desc)
88119814Smarcel{
89172617Sdes	uint16_t vendor, device;
90172617Sdes	uint16_t subvendor, subdevice;
91119814Smarcel
92158124Smarcel	vendor = pci_get_vendor(dev);
93158124Smarcel	device = pci_get_device(dev);
94172617Sdes	subvendor = pci_get_subvendor(dev);
95172617Sdes	subdevice = pci_get_subdevice(dev);
96172617Sdes
97172617Sdes	while (desc->vendor != 0xffff) {
98172617Sdes		if (desc->vendor == vendor && desc->device == device) {
99172617Sdes			/* exact match */
100172617Sdes			if (desc->subvendor == subvendor &&
101172617Sdes		            desc->subdevice == subdevice)
102172617Sdes				return (desc);
103172617Sdes			/* wildcard match */
104172617Sdes			if (desc->subvendor == 0xffff)
105172617Sdes				return (desc);
106172617Sdes		}
107158124Smarcel		desc++;
108172617Sdes	}
109172617Sdes
110172617Sdes	/* no match */
111172617Sdes	return (NULL);
112119814Smarcel}
113119814Smarcel
114102714Sphkstatic int
115102714Sphkpuc_pci_probe(device_t dev)
116102714Sphk{
117158124Smarcel	const struct puc_cfg *desc;
118102714Sphk
119119539Sjhb	if ((pci_read_config(dev, PCIR_HDRTYPE, 1) & PCIM_HDRTYPE) != 0)
120102714Sphk		return (ENXIO);
121102714Sphk
122158124Smarcel	desc = puc_pci_match(dev, puc_pci_devices);
123102714Sphk	if (desc == NULL)
124102714Sphk		return (ENXIO);
125158124Smarcel	return (puc_bfe_probe(dev, desc));
126102714Sphk}
127102714Sphk
128263109Srstonestatic int
129263109Srstonepuc_pci_attach(device_t dev)
130263109Srstone{
131263109Srstone	struct puc_softc *sc;
132263109Srstone	int error, count;
133263109Srstone
134263109Srstone	sc = device_get_softc(dev);
135263109Srstone
136263109Srstone	if (!puc_msi_disable) {
137263109Srstone		count = 1;
138263109Srstone
139263109Srstone		if (pci_alloc_msi(dev, &count) == 0) {
140263109Srstone			sc->sc_msi = 1;
141263109Srstone			sc->sc_irid = 1;
142263109Srstone		}
143263109Srstone	}
144263109Srstone
145263109Srstone	error = puc_bfe_attach(dev);
146263109Srstone
147263109Srstone	if (error != 0 && sc->sc_msi)
148263109Srstone		pci_release_msi(dev);
149263109Srstone
150263109Srstone	return (error);
151263109Srstone}
152263109Srstone
153263109Srstonestatic int
154263109Srstonepuc_pci_detach(device_t dev)
155263109Srstone{
156263109Srstone	struct puc_softc *sc;
157263109Srstone	int error;
158263109Srstone
159263109Srstone	sc = device_get_softc(dev);
160263109Srstone
161263109Srstone	error = puc_bfe_detach(dev);
162263109Srstone
163263109Srstone	if (error != 0)
164263109Srstone		return (error);
165263109Srstone
166263109Srstone	if (sc->sc_msi)
167263109Srstone		error = pci_release_msi(dev);
168263109Srstone
169263109Srstone	return (error);
170263109Srstone}
171263109Srstone
172263109Srstone
173102714Sphkstatic device_method_t puc_pci_methods[] = {
174102714Sphk    /* Device interface */
175102714Sphk    DEVMETHOD(device_probe,		puc_pci_probe),
176263109Srstone    DEVMETHOD(device_attach,		puc_pci_attach),
177263109Srstone    DEVMETHOD(device_detach,		puc_pci_detach),
178102714Sphk
179158124Smarcel    DEVMETHOD(bus_alloc_resource,	puc_bus_alloc_resource),
180158124Smarcel    DEVMETHOD(bus_release_resource,	puc_bus_release_resource),
181158124Smarcel    DEVMETHOD(bus_get_resource,		puc_bus_get_resource),
182158124Smarcel    DEVMETHOD(bus_read_ivar,		puc_bus_read_ivar),
183158124Smarcel    DEVMETHOD(bus_setup_intr,		puc_bus_setup_intr),
184158124Smarcel    DEVMETHOD(bus_teardown_intr,	puc_bus_teardown_intr),
185223091Sjhb    DEVMETHOD(bus_print_child,		puc_bus_print_child),
186223091Sjhb    DEVMETHOD(bus_child_pnpinfo_str,	puc_bus_child_pnpinfo_str),
187223091Sjhb    DEVMETHOD(bus_child_location_str,	puc_bus_child_location_str),
188227843Smarius
189227843Smarius    DEVMETHOD_END
190102714Sphk};
191102714Sphk
192102714Sphkstatic driver_t puc_pci_driver = {
193158124Smarcel	puc_driver_name,
194102714Sphk	puc_pci_methods,
195102714Sphk	sizeof(struct puc_softc),
196102714Sphk};
197102714Sphk
198102714SphkDRIVER_MODULE(puc, pci, puc_pci_driver, puc_devclass, 0, 0);
199