pcib.c revision 1.1.4.2 1 /* $NetBSD: pcib.c,v 1.1.4.2 2007/10/28 20:11:00 joerg Exp $ */
2
3 /*-
4 * Copyright (c) 1996, 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 __KERNEL_RCSID(0, "$NetBSD: pcib.c,v 1.1.4.2 2007/10/28 20:11:00 joerg Exp $");
41
42 #include <sys/types.h>
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/device.h>
46
47 #include <machine/bus.h>
48
49 #include <dev/isa/isavar.h>
50
51 #include <dev/pci/pcivar.h>
52 #include <dev/pci/pcireg.h>
53
54 #include <dev/pci/pcidevs.h>
55
56 #include "isa.h"
57
58 struct pcib_softc {
59 pci_chipset_tag_t sc_pc;
60 pcitag_t sc_tag;
61 struct pci_conf_state sc_pciconf;
62 };
63
64 int pcibmatch(struct device *, struct cfdata *, void *);
65 void pcibattach(struct device *, struct device *, void *);
66
67 static pnp_status_t pcib_power(device_t, pnp_request_t, void *);
68
69 CFATTACH_DECL_NEW(pcib, sizeof(struct pcib_softc),
70 pcibmatch, pcibattach, NULL, NULL);
71
72 void pcib_callback(struct device *);
73
74 int
75 pcibmatch(struct device *parent, struct cfdata *match, void *aux)
76 {
77 struct pci_attach_args *pa = aux;
78
79 #if 0
80 /*
81 * PCI-ISA bridges are matched on class/subclass.
82 * This list contains only the bridges where correct
83 * (or incorrect) behaviour is not yet confirmed.
84 */
85 switch (PCI_VENDOR(pa->pa_id)) {
86 case PCI_VENDOR_INTEL:
87 switch (PCI_PRODUCT(pa->pa_id)) {
88 case PCI_PRODUCT_INTEL_82426EX:
89 case PCI_PRODUCT_INTEL_82380AB:
90 return (1);
91 }
92 break;
93
94 case PCI_VENDOR_UMC:
95 switch (PCI_PRODUCT(pa->pa_id)) {
96 case PCI_PRODUCT_UMC_UM8886F:
97 case PCI_PRODUCT_UMC_UM82C886:
98 return (1);
99 }
100 break;
101 case PCI_VENDOR_ALI:
102 switch (PCI_PRODUCT(pa->pa_id)) {
103 case PCI_PRODUCT_ALI_M1449:
104 case PCI_PRODUCT_ALI_M1543:
105 return (1);
106 }
107 break;
108 case PCI_VENDOR_COMPAQ:
109 switch (PCI_PRODUCT(pa->pa_id)) {
110 case PCI_PRODUCT_COMPAQ_PCI_ISA_BRIDGE:
111 return (1);
112 }
113 break;
114 case PCI_VENDOR_VIATECH:
115 switch (PCI_PRODUCT(pa->pa_id)) {
116 case PCI_PRODUCT_VIATECH_VT82C570MV:
117 case PCI_PRODUCT_VIATECH_VT82C586_ISA:
118 return (1);
119 }
120 break;
121 }
122 #endif
123
124 /*
125 * some special cases:
126 */
127 switch (PCI_VENDOR(pa->pa_id)) {
128 case PCI_VENDOR_INTEL:
129 switch (PCI_PRODUCT(pa->pa_id)) {
130 case PCI_PRODUCT_INTEL_SIO:
131 /*
132 * The Intel SIO identifies itself as a
133 * miscellaneous prehistoric.
134 */
135 case PCI_PRODUCT_INTEL_82371MX:
136 /*
137 * The Intel 82371MX identifies itself erroneously as a
138 * miscellaneous bridge.
139 */
140 case PCI_PRODUCT_INTEL_82371AB_ISA:
141 /*
142 * Some Intel 82371AB PCI-ISA bridge identifies
143 * itself as miscellaneous bridge.
144 */
145 return (1);
146 }
147 break;
148 case PCI_VENDOR_SIS:
149 switch (PCI_PRODUCT(pa->pa_id)) {
150 case PCI_PRODUCT_SIS_85C503:
151 /*
152 * The SIS 85C503 identifies itself as a
153 * miscellaneous prehistoric.
154 */
155 return (1);
156 }
157 break;
158 case PCI_VENDOR_VIATECH:
159 switch (PCI_PRODUCT(pa->pa_id)) {
160 case PCI_PRODUCT_VIATECH_VT82C686A_SMB:
161 /*
162 * The VIA VT82C686A SMBus Controller itself as
163 * ISA bridge, but it's wrong !
164 */
165 return (0);
166 }
167 /*
168 * The Cyrix cs5530 PCI host bridge does not have a broken
169 * latch on the i8254 clock core, unlike its predecessors
170 * the cs5510 and cs5520. This reverses the setting from
171 * i386/i386/identcpu.c where it arguably should not have
172 * been set in the first place. XXX
173 */
174 case PCI_VENDOR_CYRIX:
175 switch (PCI_PRODUCT(pa->pa_id)) {
176 case PCI_PRODUCT_CYRIX_CX5530_PCIB:
177 {
178 extern int clock_broken_latch;
179
180 clock_broken_latch = 0;
181 }
182 return(1);
183 }
184 break;
185 }
186
187 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
188 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_ISA) {
189 return (1);
190 }
191
192 return (0);
193 }
194
195 void
196 pcibattach(struct device *parent, struct device *self, void *aux)
197 {
198 struct pcib_softc *sc = device_private(self);
199 struct pci_attach_args *pa = aux;
200 pnp_device_t *pnp;
201 char devinfo[256];
202
203 aprint_naive("\n");
204 aprint_normal("\n");
205
206 /*
207 * Just print out a description and defer configuration
208 * until all PCI devices have been attached.
209 */
210 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
211 aprint_normal("%s: %s (rev. 0x%02x)\n", self->dv_xname, devinfo,
212 PCI_REVISION(pa->pa_class));
213
214 sc->sc_pc = pa->pa_pc;
215 sc->sc_tag = pa->pa_tag;
216
217 pnp = device_pnp(self);
218
219 /* If a more specific pcib implementation has already registered a
220 * power handler, don't overwrite it.
221 */
222 if (pnp->pnp_power == NULL) {
223 if (pnp_register(self, pcib_power) != PNP_STATUS_SUCCESS)
224 aprint_error("%s: couldn't establish power handler\n",
225 device_xname(self));
226 }
227
228 config_defer(self, pcib_callback);
229 }
230
231 static pnp_status_t
232 pcib_power(device_t dv, pnp_request_t req, void *opaque)
233 {
234 struct pcib_softc *sc;
235 pnp_capabilities_t *pcaps;
236 pnp_state_t *pstate;
237 pci_chipset_tag_t pc;
238 pcitag_t tag;
239
240 sc = device_private(dv);
241 pc = sc->sc_pc;
242 tag = sc->sc_tag;
243
244 switch (req) {
245 case PNP_REQUEST_GET_CAPABILITIES:
246 pcaps = opaque;
247 pcaps->state = PNP_STATE_D0 | PNP_STATE_D3;
248 break;
249 case PNP_REQUEST_GET_STATE:
250 pstate = opaque;
251 *pstate = PNP_STATE_D0; /* XXX */
252 break;
253 case PNP_REQUEST_SET_STATE:
254 pstate = opaque;
255 switch (*pstate) {
256 case PNP_STATE_D0:
257 pci_conf_restore(pc, tag, &sc->sc_pciconf);
258 break;
259 case PNP_STATE_D3:
260 pci_conf_capture(pc, tag, &sc->sc_pciconf);
261 break;
262 default:
263 return PNP_STATUS_UNSUPPORTED;
264 }
265 break;
266 default:
267 return PNP_STATUS_UNSUPPORTED;
268 }
269
270 return PNP_STATUS_SUCCESS;
271 }
272
273 void
274 pcib_callback(struct device *self)
275 {
276 struct isabus_attach_args iba;
277
278 /*
279 * Attach the ISA bus behind this bridge.
280 */
281 memset(&iba, 0, sizeof(iba));
282 iba.iba_iot = X86_BUS_SPACE_IO;
283 iba.iba_memt = X86_BUS_SPACE_MEM;
284 #if NISA > 0
285 iba.iba_dmat = &isa_bus_dma_tag;
286 #endif
287 config_found_ia(self, "isabus", &iba, isabusprint);
288 }
289