xref: /openbsd/sys/dev/pci/agp_intel.c (revision 898184e3)
1 /*	$OpenBSD: agp_intel.c,v 1.20 2012/11/13 23:36:17 kettenis 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 		reg = pci_conf_read(isc->isc_pc, isc->isc_tag,
264 		    AGP_INTEL_ERRCMD);
265 		pci_conf_write(isc->isc_pc, isc->isc_tag,
266 		    AGP_INTEL_ERRCMD, reg);
267 	}
268 
269 	isc->agpdev = (struct agp_softc *)agp_attach_bus(pa, &agp_intel_methods,
270 	    isc->isc_apaddr, isc->isc_apsize, &isc->dev);
271 	return;
272 }
273 
274 int
275 agp_intel_activate(struct device *arg, int act)
276 {
277 	struct agp_intel_softc *isc = (struct agp_intel_softc *)arg;
278 
279 	switch (act) {
280 	case DVACT_SUSPEND:
281 		agp_intel_save(isc);
282 		break;
283 	case DVACT_RESUME:
284 		agp_intel_restore(isc);
285 		break;
286 	}
287 
288 	return (0);
289 }
290 
291 void
292 agp_intel_save(struct agp_intel_softc *isc)
293 {
294 
295 	if (isc->chiptype != CHIP_I443) {
296 		isc->savectrl = pci_conf_read(isc->isc_pc, isc->isc_tag,
297 		    AGP_INTEL_AGPCTRL);
298 	}
299 
300 	switch (isc->chiptype) {
301 	case CHIP_I845:
302 	case CHIP_I865:
303 		isc->savecmd = pci_conf_read(isc->isc_pc, isc->isc_tag,
304 		    AGP_I840_MCHCFG);
305 
306 		break;
307 	case CHIP_I840:
308 	case CHIP_I850:
309 		isc->savecmd = pci_conf_read(isc->isc_pc, isc->isc_tag,
310 		    AGP_INTEL_AGPCMD);
311 		isc->savecfg = pci_conf_read(isc->isc_pc, isc->isc_tag,
312 		    AGP_I840_MCHCFG);
313 
314 		break;
315 	default:
316 		isc->savecfg = pci_conf_read(isc->isc_pc, isc->isc_tag,
317 		    AGP_INTEL_NBXCFG);
318 		break;
319 	}
320 }
321 
322 void
323 agp_intel_restore(struct agp_intel_softc *isc)
324 {
325 	pcireg_t	tmp;
326 	/*
327 	 * reset size now just in case, if it worked before then sanity
328 	 * checking will not fail
329 	 */
330 	(void)agp_intel_set_aperture(isc, isc->isc_apsize);
331 
332 	/* Install the gatt. */
333 	pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_ATTBASE,
334 	    isc->gatt->ag_physical);
335 
336 	/* Enable the GLTB and setup the control register. */
337 	switch (isc->chiptype) {
338 	case CHIP_I443:
339 		pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL,
340 		    AGPCTRL_AGPRSE | AGPCTRL_GTLB);
341 		break;
342 	default:
343 		pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL,
344 		    isc->savectrl);
345 		break;
346 	}
347 
348 	/* Enable things, clear errors etc. */
349 	switch (isc->chiptype) {
350 	case CHIP_I845:
351 	case CHIP_I865:
352 		pci_conf_write(isc->isc_pc, isc->isc_tag,
353 		    AGP_I840_MCHCFG, isc->savecmd);
354 		break;
355 	case CHIP_I840:
356 	case CHIP_I850:
357 		pci_conf_write(isc->isc_pc, isc->isc_tag,
358 		    AGP_INTEL_AGPCMD, isc->savecmd);
359 		pci_conf_write(isc->isc_pc, isc->isc_tag,
360 		    AGP_I840_MCHCFG, isc->savecfg);
361 		break;
362 	default:
363 		pci_conf_write(isc->isc_pc, isc->isc_tag,
364 		    AGP_INTEL_NBXCFG, isc->savecfg);
365 		break;
366 	}
367 
368 	/* Clear Error status */
369 	switch (isc->chiptype) {
370 	case CHIP_I840:
371 		pci_conf_write(isc->isc_pc, isc->isc_tag,
372 		    AGP_INTEL_I8XX_ERRSTS, 0xc000);
373 		break;
374 	case CHIP_I845:
375 	case CHIP_I850:
376 	case CHIP_I865:
377 		pci_conf_write(isc->isc_pc, isc->isc_tag,
378 		    AGP_INTEL_I8XX_ERRSTS, 0x00ff);
379 		break;
380 	default:
381 		tmp = pci_conf_read(isc->isc_pc, isc->isc_tag,
382 		    AGP_INTEL_ERRCMD);
383 		pci_conf_write(isc->isc_pc, isc->isc_tag,
384 		    AGP_INTEL_ERRCMD, tmp);
385 		break;
386 	}
387 }
388 
389 #if 0
390 int
391 agp_intel_detach(struct agp_softc *sc)
392 {
393 	int error;
394 	pcireg_t reg;
395 	struct agp_intel_softc *isc = sc->sc_chipc;
396 
397 	error = agp_generic_detach(sc);
398 	if (error)
399 		return (error);
400 
401 	/* XXX i845/i855PM/i840/i850E */
402 	reg = pci_conf_read(sc->sc_pc, sc->sc_tag, AGP_INTEL_NBXCFG);
403 	reg &= ~(1 << 9);
404 	printf("%s: set NBXCFG to %x\n", __FUNCTION__, reg);
405 	pci_conf_write(sc->sc_pc, sc->sc_tag, AGP_INTEL_NBXCFG, reg);
406 	pci_conf_write(sc->sc_pc, sc->sc_tag, AGP_INTEL_ATTBASE, 0);
407 	AGP_SET_APERTURE(sc, isc->initial_aperture);
408 	agp_free_gatt(sc, isc->gatt);
409 
410 	return (0);
411 }
412 #endif
413 
414 bus_size_t
415 agp_intel_get_aperture(void *sc)
416 {
417 	struct agp_intel_softc *isc = sc;
418 	bus_size_t apsize;
419 
420 	apsize = pci_conf_read(isc->isc_pc, isc->isc_tag,
421 	    AGP_INTEL_APSIZE) & isc->aperture_mask;
422 
423 	/*
424 	 * The size is determined by the number of low bits of
425 	 * register APBASE which are forced to zero. The low 22 bits
426 	 * are always forced to zero and each zero bit in the apsize
427 	 * field just read forces the corresponding bit in the 27:22
428 	 * to be zero. We calculate the aperture size accordingly.
429 	 */
430 	return ((((apsize ^ isc->aperture_mask) << 22) | ((1 << 22) - 1)) + 1);
431 }
432 
433 int
434 agp_intel_set_aperture(void *sc, bus_size_t aperture)
435 {
436 	struct agp_intel_softc *isc = sc;
437 	bus_size_t apsize;
438 
439 	/*
440 	 * Reverse the magic from get_aperture.
441 	 */
442 	apsize = ((aperture - 1) >> 22) ^ isc->aperture_mask;
443 
444 	/*
445 	 * Double check for sanity.
446 	 */
447 	if ((((apsize ^ isc->aperture_mask) << 22) |
448 	    ((1 << 22) - 1)) + 1 != aperture)
449 		return (EINVAL);
450 
451 	pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_APSIZE, apsize);
452 
453 	return (0);
454 }
455 
456 void
457 agp_intel_bind_page(void *sc, bus_addr_t offset, paddr_t physical, int flags)
458 {
459 	struct agp_intel_softc *isc = sc;
460 
461 	isc->gatt->ag_virtual[(offset - isc->isc_apaddr) >> AGP_PAGE_SHIFT] =
462 	    physical | 0x17;
463 }
464 
465 void
466 agp_intel_unbind_page(void *sc, bus_size_t offset)
467 {
468 	struct agp_intel_softc *isc = sc;
469 
470 	isc->gatt->ag_virtual[(offset - isc->isc_apaddr) >> AGP_PAGE_SHIFT] = 0;
471 }
472 
473 void
474 agp_intel_flush_tlb(void *sc)
475 {
476 	struct agp_intel_softc *isc = sc;
477 	pcireg_t reg;
478 
479 	switch (isc->chiptype) {
480 	case CHIP_I865:
481 	case CHIP_I850:
482 	case CHIP_I845:
483 	case CHIP_I840:
484 	case CHIP_I443:
485 		reg = pci_conf_read(isc->isc_pc, isc->isc_tag,
486 		    AGP_INTEL_AGPCTRL);
487 		reg &= ~AGPCTRL_GTLB;
488 		pci_conf_write(isc->isc_pc, isc->isc_tag,
489 		    AGP_INTEL_AGPCTRL, reg);
490 		pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL,
491 		    reg | AGPCTRL_GTLB);
492 		break;
493 	default: /* XXX */
494 		pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL,
495 		    0x2200);
496 		pci_conf_write(isc->isc_pc, isc->isc_tag, AGP_INTEL_AGPCTRL,
497 		    0x2280);
498 		break;
499 	}
500 }
501