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