xref: /openbsd/sys/dev/pci/agp_intel.c (revision 891d7ab6)
1 /*	$OpenBSD: agp_intel.c,v 1.18 2010/08/07 20:47:24 deraadt Exp $	*/
2 /*	$NetBSD: agp_intel.c,v 1.3 2001/09/15 00:25:00 thorpej Exp $	*/
3 
4 /*-
5  * Copyright (c) 2000 Doug Rabson
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  *	$FreeBSD: src/sys/pci/agp_intel.c,v 1.4 2001/07/05 21:28:47 jhb Exp $
30  */
31 
32 #include <sys/param.h>
33 #include <sys/systm.h>
34 #include <sys/malloc.h>
35 #include <sys/kernel.h>
36 #include <sys/lock.h>
37 #include <sys/agpio.h>
38 #include <sys/device.h>
39 #include <sys/agpio.h>
40 
41 #include <dev/pci/pcivar.h>
42 #include <dev/pci/pcireg.h>
43 #include <dev/pci/pcidevs.h>
44 #include <dev/pci/agpvar.h>
45 #include <dev/pci/agpreg.h>
46 
47 #include <machine/bus.h>
48 
49 struct agp_intel_softc {
50 	struct device		 dev;
51 	struct agp_softc	*agpdev;
52 	struct agp_gatt 	*gatt;
53 	pci_chipset_tag_t	 isc_pc;
54 	pcitag_t		 isc_tag;
55 	bus_addr_t		 isc_apaddr;
56 	bus_size_t		 isc_apsize;
57 	u_int			 aperture_mask;
58 	enum {
59 		CHIP_INTEL,
60 		CHIP_I443,
61 		CHIP_I840,
62 		CHIP_I845,
63 		CHIP_I850,
64 		CHIP_I865
65 	}			 chiptype;
66 	/* registers saved during a suspend/resume cycle. */
67 	pcireg_t		 savectrl;
68 	pcireg_t		 savecmd;
69 	pcireg_t		 savecfg;
70 };
71 
72 
73 void	agp_intel_attach(struct device *, struct device *, void *);
74 int	agp_intel_activate(struct device *, int);
75 void	agp_intel_save(struct agp_intel_softc *);
76 void	agp_intel_restore(struct agp_intel_softc *);
77 int	agp_intel_probe(struct device *, void *, void *);
78 bus_size_t agp_intel_get_aperture(void *);
79 int	agp_intel_set_aperture(void *, bus_size_t);
80 void	agp_intel_bind_page(void *, bus_addr_t, paddr_t, int);
81 void	agp_intel_unbind_page(void *, bus_addr_t);
82 void	agp_intel_flush_tlb(void *);
83 
84 struct cfattach intelagp_ca = {
85 	sizeof(struct agp_intel_softc), agp_intel_probe, agp_intel_attach,
86 	NULL, agp_intel_activate
87 };
88 
89 struct cfdriver intelagp_cd = {
90 	NULL, "intelagp", DV_DULL
91 };
92 
93 const struct agp_methods agp_intel_methods = {
94 	agp_intel_bind_page,
95 	agp_intel_unbind_page,
96 	agp_intel_flush_tlb,
97 	/* default enable and memory routines */
98 };
99 
100 int
101 agp_intel_probe(struct device *parent, void *match, void *aux)
102 {
103 	struct agp_attach_args	*aa = aux;
104 	struct pci_attach_args	*pa = aa->aa_pa;
105 
106 	/* Must be a pchb */
107 	if (agpbus_probe(aa) == 0)
108 		return (0);
109 
110 	switch (PCI_PRODUCT(pa->pa_id)) {
111 	case PCI_PRODUCT_INTEL_82443LX:
112 	case PCI_PRODUCT_INTEL_82443BX:
113 	case PCI_PRODUCT_INTEL_82440BX:
114 	case PCI_PRODUCT_INTEL_82440BX_AGP:
115 	case PCI_PRODUCT_INTEL_82815_HB:
116 	case PCI_PRODUCT_INTEL_82820_HB:
117 	case PCI_PRODUCT_INTEL_82830M_HB:
118 	case PCI_PRODUCT_INTEL_82840_HB:
119 	case PCI_PRODUCT_INTEL_82845_HB:
120 	case PCI_PRODUCT_INTEL_82845G_HB:
121 	case PCI_PRODUCT_INTEL_82850_HB:
122 	case PCI_PRODUCT_INTEL_82855PM_HB:
123 	case PCI_PRODUCT_INTEL_82855GM_HB:
124 	case PCI_PRODUCT_INTEL_82860_HB:
125 	case PCI_PRODUCT_INTEL_82865G_HB:
126 	case PCI_PRODUCT_INTEL_82875P_HB:
127 		return (1);
128 	}
129 
130 	return (0);
131 }
132 
133 void
134 agp_intel_attach(struct device *parent, struct device *self, void *aux)
135 {
136 	struct agp_intel_softc	*isc = (struct agp_intel_softc *)self;
137 	struct agp_attach_args	*aa = aux;
138 	struct pci_attach_args	*pa = aa->aa_pa;
139 	struct agp_gatt		*gatt;
140 	pcireg_t		 reg;
141 	u_int32_t		 value;
142 
143 	isc->isc_pc = pa->pa_pc;
144 	isc->isc_tag = pa->pa_tag;
145 
146 	switch (PCI_PRODUCT(pa->pa_id)) {
147 	case PCI_PRODUCT_INTEL_82443LX:
148 	case PCI_PRODUCT_INTEL_82443BX:
149 	case PCI_PRODUCT_INTEL_82440BX:
150 	case PCI_PRODUCT_INTEL_82440BX_AGP:
151 		isc->chiptype = CHIP_I443;
152 		break;
153 	case PCI_PRODUCT_INTEL_82830M_HB:
154 	case PCI_PRODUCT_INTEL_82840_HB:
155 		isc->chiptype = CHIP_I840;
156 		break;
157 	case PCI_PRODUCT_INTEL_82845_HB:
158 	case PCI_PRODUCT_INTEL_82845G_HB:
159 	case PCI_PRODUCT_INTEL_82855PM_HB:
160 		isc->chiptype = CHIP_I845;
161 		break;
162 	case PCI_PRODUCT_INTEL_82850_HB:
163 		isc->chiptype = CHIP_I850;
164 		break;
165 	case PCI_PRODUCT_INTEL_82865G_HB:
166 	case PCI_PRODUCT_INTEL_82875P_HB:
167 		isc->chiptype = CHIP_I865;
168 		break;
169 	default:
170 		isc->chiptype = CHIP_INTEL;
171 		break;
172 	}
173 
174 	if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, AGP_APBASE,
175 	    PCI_MAPREG_TYPE_MEM, &isc->isc_apaddr, NULL, NULL) != 0) {
176 		printf(": can't get aperture info\n");
177 		return;
178 	}
179 
180 	/* Determine maximum supported aperture size. */
181 	value = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_INTEL_APSIZE);
182 	pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_APSIZE, APSIZE_MASK);
183 	isc->aperture_mask = pci_conf_read(pa->pa_pc, pa->pa_tag,
184 		AGP_INTEL_APSIZE) & APSIZE_MASK;
185 	pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_APSIZE, value);
186 	isc->isc_apsize = agp_intel_get_aperture(isc);
187 
188 	for (;;) {
189 		gatt = agp_alloc_gatt(pa->pa_dmat, isc->isc_apsize);
190 		if (gatt != NULL)
191 			break;
192 
193 		/*
194 		 * almost certainly error allocating contigious dma memory
195 		 * so reduce aperture so that the gatt size reduces.
196 		 */
197 		isc->isc_apsize /= 2;
198 		if (agp_intel_set_aperture(isc, isc->isc_apsize)) {
199 			printf(": failed to set aperture\n");
200 			return;
201 		}
202 	}
203 	isc->gatt = gatt;
204 
205 	/* Install the gatt. */
206 	pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_ATTBASE,
207 	    gatt->ag_physical);
208 
209 	/* Enable the GLTB and setup the control register. */
210 	switch (isc->chiptype) {
211 	case CHIP_I443:
212 		pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL,
213 		    AGPCTRL_AGPRSE | AGPCTRL_GTLB);
214 		break;
215 	default:
216 		pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL,
217 		    pci_conf_read(isc->isc_pc, isc->isc_tag,
218 		    AGP_INTEL_AGPCTRL) | AGPCTRL_GTLB);
219 		break;
220 	}
221 
222 	/* Enable things, clear errors etc. */
223 	switch (isc->chiptype) {
224 	case CHIP_I845:
225 	case CHIP_I865:
226 		reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_I840_MCHCFG);
227 		reg |= MCHCFG_AAGN;
228 		pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_I840_MCHCFG, reg);
229 		break;
230 	case CHIP_I840:
231 	case CHIP_I850:
232 		reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_INTEL_AGPCMD);
233 		reg |= AGPCMD_AGPEN;
234 		pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_AGPCMD,
235 		    reg);
236 		reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_I840_MCHCFG);
237 		reg |= MCHCFG_AAGN;
238 		pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_I840_MCHCFG,
239 		    reg);
240 		break;
241 	default:
242 		reg = pci_conf_read(pa->pa_pc, pa->pa_tag, AGP_INTEL_NBXCFG);
243 		reg &= ~NBXCFG_APAE;
244 		reg |=  NBXCFG_AAGN;
245 		pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_NBXCFG, reg);
246 		break;
247 	}
248 
249 	/* Clear Error status */
250 	switch (isc->chiptype) {
251 	case CHIP_I840:
252 		pci_conf_write(pa->pa_pc, pa->pa_tag,
253 		    AGP_INTEL_I8XX_ERRSTS, 0xc000);
254 		break;
255 	case CHIP_I845:
256 	case CHIP_I850:
257 	case CHIP_I865:
258 		pci_conf_write(isc->isc_pc, isc->isc_tag,
259 		    AGP_INTEL_I8XX_ERRSTS, 0x00ff);
260 		break;
261 
262 	default:
263 		pci_conf_write(pa->pa_pc, pa->pa_tag, AGP_INTEL_ERRSTS, 0x70);
264 	}
265 
266 	isc->agpdev = (struct agp_softc *)agp_attach_bus(pa, &agp_intel_methods,
267 	    isc->isc_apaddr, isc->isc_apsize, &isc->dev);
268 	return;
269 }
270 
271 int
272 agp_intel_activate(struct device *arg, int act)
273 {
274 	struct agp_intel_softc *isc = (struct agp_intel_softc *)arg;
275 
276 	switch (act) {
277 	case DVACT_SUSPEND:
278 		agp_intel_save(isc);
279 		break;
280 	case DVACT_RESUME:
281 		agp_intel_restore(isc);
282 		break;
283 	}
284 
285 	return (0);
286 }
287 
288 void
289 agp_intel_save(struct agp_intel_softc *isc)
290 {
291 
292 	if (isc->chiptype != CHIP_I443) {
293 		isc->savectrl = pci_conf_read(isc->isc_pc, isc->isc_tag,
294 		    AGP_INTEL_AGPCTRL);
295 	}
296 
297 	switch (isc->chiptype) {
298 	case CHIP_I845:
299 	case CHIP_I865:
300 		isc->savecmd = pci_conf_read(isc->isc_pc, isc->isc_tag,
301 		    AGP_I840_MCHCFG);
302 
303 		break;
304 	case CHIP_I840:
305 	case CHIP_I850:
306 		isc->savecmd = pci_conf_read(isc->isc_pc, isc->isc_tag,
307 		    AGP_INTEL_AGPCMD);
308 		isc->savecfg = pci_conf_read(isc->isc_pc, isc->isc_tag,
309 		    AGP_I840_MCHCFG);
310 
311 		break;
312 	default:
313 		isc->savecfg = pci_conf_read(isc->isc_pc, isc->isc_tag,
314 		    AGP_INTEL_NBXCFG);
315 		break;
316 	}
317 }
318 
319 void
320 agp_intel_restore(struct agp_intel_softc *isc)
321 {
322 	/*
323 	 * reset size now just in case, if it worked before then sanity
324 	 * checking will not fail
325 	 */
326 	(void)agp_intel_set_aperture(isc, isc->isc_apsize);
327 
328 	/* Install the gatt. */
329 	pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_ATTBASE,
330 	    isc->gatt->ag_physical);
331 
332 	/* Enable the GLTB and setup the control register. */
333 	switch (isc->chiptype) {
334 	case CHIP_I443:
335 		pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL,
336 		    AGPCTRL_AGPRSE | AGPCTRL_GTLB);
337 		break;
338 	default:
339 		pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL,
340 		    isc->savectrl);
341 		break;
342 	}
343 
344 	/* Enable things, clear errors etc. */
345 	switch (isc->chiptype) {
346 	case CHIP_I845:
347 	case CHIP_I865:
348 		pci_conf_write(isc->isc_pc, isc->isc_tag,
349 		    AGP_I840_MCHCFG, isc->savecmd);
350 		break;
351 	case CHIP_I840:
352 	case CHIP_I850:
353 		pci_conf_write(isc->isc_pc, isc->isc_tag,
354 		    AGP_INTEL_AGPCMD, isc->savecmd);
355 		pci_conf_write(isc->isc_pc, isc->isc_tag,
356 		    AGP_I840_MCHCFG, isc->savecfg);
357 		break;
358 	default:
359 		pci_conf_write(isc->isc_pc, isc->isc_tag,
360 		    AGP_INTEL_NBXCFG, isc->savecfg);
361 		break;
362 	}
363 
364 	/* Clear Error status */
365 	switch (isc->chiptype) {
366 	case CHIP_I840:
367 		pci_conf_write(isc->isc_pc, isc->isc_tag,
368 		    AGP_INTEL_I8XX_ERRSTS, 0xc000);
369 		break;
370 	case CHIP_I845:
371 	case CHIP_I850:
372 	case CHIP_I865:
373 		pci_conf_write(isc->isc_pc, isc->isc_tag,
374 		    AGP_INTEL_I8XX_ERRSTS, 0x00ff);
375 		break;
376 	default:
377 		pci_conf_write(isc->isc_pc, isc->isc_tag,
378 		    AGP_INTEL_ERRSTS, 0x70);
379 		break;
380 	}
381 }
382 
383 #if 0
384 int
385 agp_intel_detach(struct agp_softc *sc)
386 {
387 	int error;
388 	pcireg_t reg;
389 	struct agp_intel_softc *isc = sc->sc_chipc;
390 
391 	error = agp_generic_detach(sc);
392 	if (error)
393 		return (error);
394 
395 	/* XXX i845/i855PM/i840/i850E */
396 	reg = pci_conf_read(sc->sc_pc, sc->sc_tag, AGP_INTEL_NBXCFG);
397 	reg &= ~(1 << 9);
398 	printf("%s: set NBXCFG to %x\n", __FUNCTION__, reg);
399 	pci_conf_write(sc->sc_pc, sc->sc_tag, AGP_INTEL_NBXCFG, reg);
400 	pci_conf_write(sc->sc_pc, sc->sc_tag, AGP_INTEL_ATTBASE, 0);
401 	AGP_SET_APERTURE(sc, isc->initial_aperture);
402 	agp_free_gatt(sc, isc->gatt);
403 
404 	return (0);
405 }
406 #endif
407 
408 bus_size_t
409 agp_intel_get_aperture(void *sc)
410 {
411 	struct agp_intel_softc *isc = sc;
412 	bus_size_t apsize;
413 
414 	apsize = pci_conf_read(isc->isc_pc, isc->isc_tag,
415 	    AGP_INTEL_APSIZE) & isc->aperture_mask;
416 
417 	/*
418 	 * The size is determined by the number of low bits of
419 	 * register APBASE which are forced to zero. The low 22 bits
420 	 * are always forced to zero and each zero bit in the apsize
421 	 * field just read forces the corresponding bit in the 27:22
422 	 * to be zero. We calculate the aperture size accordingly.
423 	 */
424 	return ((((apsize ^ isc->aperture_mask) << 22) | ((1 << 22) - 1)) + 1);
425 }
426 
427 int
428 agp_intel_set_aperture(void *sc, bus_size_t aperture)
429 {
430 	struct agp_intel_softc *isc = sc;
431 	bus_size_t apsize;
432 
433 	/*
434 	 * Reverse the magic from get_aperture.
435 	 */
436 	apsize = ((aperture - 1) >> 22) ^ isc->aperture_mask;
437 
438 	/*
439 	 * Double check for sanity.
440 	 */
441 	if ((((apsize ^ isc->aperture_mask) << 22) |
442 	    ((1 << 22) - 1)) + 1 != aperture)
443 		return (EINVAL);
444 
445 	pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_APSIZE, apsize);
446 
447 	return (0);
448 }
449 
450 void
451 agp_intel_bind_page(void *sc, bus_addr_t offset, paddr_t physical, int flags)
452 {
453 	struct agp_intel_softc *isc = sc;
454 
455 	isc->gatt->ag_virtual[(offset - isc->isc_apaddr) >> AGP_PAGE_SHIFT] =
456 	    physical | 0x17;
457 }
458 
459 void
460 agp_intel_unbind_page(void *sc, bus_size_t offset)
461 {
462 	struct agp_intel_softc *isc = sc;
463 
464 	isc->gatt->ag_virtual[(offset - isc->isc_apaddr) >> AGP_PAGE_SHIFT] = 0;
465 }
466 
467 void
468 agp_intel_flush_tlb(void *sc)
469 {
470 	struct agp_intel_softc *isc = sc;
471 	pcireg_t reg;
472 
473 	switch (isc->chiptype) {
474 	case CHIP_I865:
475 	case CHIP_I850:
476 	case CHIP_I845:
477 	case CHIP_I840:
478 	case CHIP_I443:
479 		reg = pci_conf_read(isc->isc_pc, isc->isc_tag,
480 		    AGP_INTEL_AGPCTRL);
481 		reg &= ~AGPCTRL_GTLB;
482 		pci_conf_write(isc->isc_pc, isc->isc_tag,
483 		    AGP_INTEL_AGPCTRL, reg);
484 		pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL,
485 		    reg | AGPCTRL_GTLB);
486 		break;
487 	default: /* XXX */
488 		pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL,
489 		    0x2200);
490 		pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL,
491 		    0x2280);
492 		break;
493 	}
494 }
495