xref: /openbsd/sys/dev/pci/mmuagp.c (revision 3cab2bb3)
1 /*-
2  * Copyright (c) 2004, 2005 Jung-uk Kim <jkim@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26 
27 #include <sys/param.h>
28 #include <sys/systm.h>
29 #include <sys/malloc.h>
30 #include <sys/device.h>
31 #include <sys/rwlock.h>
32 
33 #include <dev/pci/pcivar.h>
34 #include <dev/pci/pcireg.h>
35 #include <dev/pci/agpvar.h>
36 #include <dev/pci/agpreg.h>
37 
38 #include <dev/pci/pcidevs.h>
39 
40 #include <machine/bus.h>
41 
42 /*
43  * AMD64 GART registers
44  */
45 #define	AGP_AMD64_APCTRL		0x90
46 #define	AGP_AMD64_APBASE		0x94
47 #define	AGP_AMD64_ATTBASE		0x98
48 #define	AGP_AMD64_CACHECTRL		0x9c
49 #define	AGP_AMD64_APCTRL_GARTEN		0x00000001
50 #define	AGP_AMD64_APCTRL_SIZE_MASK	0x0000000e
51 #define	AGP_AMD64_APCTRL_DISGARTCPU	0x00000010
52 #define	AGP_AMD64_APCTRL_DISGARTIO	0x00000020
53 #define	AGP_AMD64_APCTRL_DISWLKPRB	0x00000040
54 #define	AGP_AMD64_APBASE_MASK		0x00007fff
55 #define	AGP_AMD64_ATTBASE_MASK		0xfffffff0
56 #define	AGP_AMD64_CACHECTRL_INVGART	0x00000001
57 #define	AGP_AMD64_CACHECTRL_PTEERR	0x00000002
58 
59 /*
60  * NVIDIA nForce3 registers
61  */
62 #define AGP_AMD64_NVIDIA_0_APBASE	0x10
63 #define AGP_AMD64_NVIDIA_1_APBASE1	0x50
64 #define AGP_AMD64_NVIDIA_1_APLIMIT1	0x54
65 #define AGP_AMD64_NVIDIA_1_APSIZE	0xa8
66 #define AGP_AMD64_NVIDIA_1_APBASE2	0xd8
67 #define AGP_AMD64_NVIDIA_1_APLIMIT2	0xdc
68 
69 /*
70  * ULi M1689 registers
71  */
72 #define AGP_AMD64_ULI_APBASE		0x10
73 #define AGP_AMD64_ULI_HTT_FEATURE	0x50
74 #define AGP_AMD64_ULI_ENU_SCR		0x54
75 
76 
77 #define	AMD64_MAX_MCTRL		8
78 
79 /* XXX nForce3 requires secondary AGP bridge at 0:11:0. */
80 #define AGP_AMD64_NVIDIA_PCITAG(pc)	pci_make_tag(pc, 0, 11, 0)
81 /* XXX Some VIA bridge requires secondary AGP bridge at 0:1:0. */
82 #define AGP_AMD64_VIA_PCITAG(pc)	pci_make_tag(pc, 0, 1, 0)
83 
84 
85 int	mmuagp_probe(struct device *, void *, void *);
86 void	mmuagp_attach(struct device *, struct device *, void *);
87 bus_size_t mmuagp_get_aperture(void *);
88 int	mmuagp_set_aperture(void *, bus_size_t);
89 void	mmuagp_bind_page(void *, bus_addr_t, paddr_t, int);
90 void	mmuagp_unbind_page(void *, bus_addr_t);
91 void	mmuagp_flush_tlb(void *);
92 
93 void	mmuagp_apbase_fixup(void *);
94 
95 void	mmuagp_uli_init(void *);
96 int	mmuagp_uli_set_aperture(void *, bus_size_t);
97 
98 int	mmuagp_nvidia_match(const struct pci_attach_args *, uint16_t);
99 void	mmuagp_nvidia_init(void *);
100 int	mmuagp_nvidia_set_aperture(void *, bus_size_t);
101 
102 int	mmuagp_via_match(const struct pci_attach_args *);
103 void	mmuagp_via_init(void *);
104 int	mmuagp_via_set_aperture(void *, bus_size_t);
105 
106 struct mmuagp_softc {
107 	struct device		 dev;
108 	struct agp_softc	*agpdev;
109 	struct agp_gatt		*gatt;
110 	bus_addr_t		 msc_apaddr;
111 	bus_size_t		 msc_apsize;
112 	uint32_t		 apbase;
113 	pcitag_t		 ctrl_tag;	/* use NVIDIA and VIA */
114 	pcitag_t		 mctrl_tag[AMD64_MAX_MCTRL];
115 	pci_chipset_tag_t	 msc_pc;
116 	pcitag_t		 msc_tag;
117 	int			 n_mctrl;
118 };
119 
120 struct cfattach mmuagp_ca = {
121         sizeof(struct mmuagp_softc), mmuagp_probe, mmuagp_attach
122 };
123 
124 struct cfdriver mmuagp_cd = {
125 	NULL, "mmuagp", DV_DULL
126 };
127 
128 const struct agp_methods mmuagp_methods = {
129 	mmuagp_bind_page,
130 	mmuagp_unbind_page,
131 	mmuagp_flush_tlb,
132 };
133 
134 int
135 mmuagp_probe(struct device *parent, void *match, void *aux)
136 {
137 	struct agp_attach_args	*aa = aux;
138 	struct pci_attach_args	*pa = aa->aa_pa;
139 
140 	/* Must be a pchb, don't attach to iommu-style agp devs */
141 	if (agpbus_probe(aa) == 0)
142 		return (0);
143 
144 	switch (PCI_VENDOR(pa->pa_id)) {
145 	case PCI_VENDOR_ALI:
146 		switch (PCI_PRODUCT(pa->pa_id)) {
147 		case PCI_PRODUCT_ALI_M1689:
148 			return (1);
149 		}
150 		break;
151 	case PCI_VENDOR_AMD:
152 		switch (PCI_PRODUCT(pa->pa_id)) {
153 		case PCI_PRODUCT_AMD_8151_SC:
154 			return (1);
155 		}
156 		break;
157 	case PCI_VENDOR_NVIDIA:
158 		switch (PCI_PRODUCT(pa->pa_id)) {
159 		case PCI_PRODUCT_NVIDIA_NFORCE3_PCHB:
160 			return (mmuagp_nvidia_match(pa,
161 			    PCI_PRODUCT_NVIDIA_NFORCE3_PPB2));
162 			/* NOTREACHED */
163 		case PCI_PRODUCT_NVIDIA_NFORCE3_250_PCHB:
164 			return (mmuagp_nvidia_match(pa,
165 			    PCI_PRODUCT_NVIDIA_NFORCE3_250_AGP));
166 			/* NOTREACHED */
167 		}
168 		break;
169 	case PCI_VENDOR_SIS:
170 		switch (PCI_PRODUCT(pa->pa_id)) {
171 		case PCI_PRODUCT_SIS_755:
172 		case PCI_PRODUCT_SIS_760:
173 			return (1);
174 		}
175 		break;
176 	case PCI_VENDOR_VIATECH:
177 		switch (PCI_PRODUCT(pa->pa_id)) {
178 		case PCI_PRODUCT_VIATECH_K8M800_0:
179 		case PCI_PRODUCT_VIATECH_K8T890_0:
180 		case PCI_PRODUCT_VIATECH_K8HTB_0:
181 		case PCI_PRODUCT_VIATECH_K8HTB:
182 			return (1);
183 		}
184 		break;
185 	}
186 
187 	return (0);
188 }
189 
190 int
191 mmuagp_nvidia_match(const struct pci_attach_args *pa, uint16_t devid)
192 {
193 	pcitag_t	tag;
194 	pcireg_t	reg;
195 
196 	tag = AGP_AMD64_NVIDIA_PCITAG(pa->pa_pc);
197 
198 	reg = pci_conf_read(pa->pa_pc, tag, PCI_CLASS_REG);
199 	if (PCI_CLASS(reg) != PCI_CLASS_BRIDGE ||
200 	    PCI_SUBCLASS(reg) != PCI_SUBCLASS_BRIDGE_PCI)
201 		return 0;
202 
203 	reg = pci_conf_read(pa->pa_pc, tag, PCI_ID_REG);
204 	if (PCI_VENDOR(reg) != PCI_VENDOR_NVIDIA || PCI_PRODUCT(reg) != devid)
205 		return 0;
206 
207 	return 1;
208 }
209 
210 int
211 mmuagp_via_match(const struct pci_attach_args *pa)
212 {
213 	pcitag_t tag;
214 	pcireg_t reg;
215 
216 	tag = AGP_AMD64_VIA_PCITAG(pa->pa_pc);
217 
218 	reg = pci_conf_read(pa->pa_pc, tag, PCI_CLASS_REG);
219 	if (PCI_CLASS(reg) != PCI_CLASS_BRIDGE ||
220 	    PCI_SUBCLASS(reg) != PCI_SUBCLASS_BRIDGE_PCI)
221 		return 0;
222 
223 	reg = pci_conf_read(pa->pa_pc, tag, PCI_ID_REG);
224 	if (PCI_VENDOR(reg) != PCI_VENDOR_VIATECH ||
225 	    PCI_PRODUCT(reg) != PCI_PRODUCT_VIATECH_K8HTB_AGP)
226 		return 0;
227 
228 	return 1;
229 }
230 
231 void
232 mmuagp_attach(struct device *parent, struct device *self, void *aux)
233 {
234 	struct mmuagp_softc	*msc = (struct mmuagp_softc *)self ;
235 	struct agp_attach_args	*aa = aux;
236 	struct pci_attach_args	*pa = aa->aa_pa;
237 	struct agp_gatt		*gatt;
238 	int			 (*set_aperture)(void *, bus_size_t) = NULL;
239 	pcireg_t		 id, attbase, apctrl;
240 	pcitag_t		 tag;
241 	int			 maxdevs, i, n;
242 
243 	if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, AGP_APBASE,
244 	    PCI_MAPREG_TYPE_MEM, &msc->msc_apaddr, NULL, NULL) != 0) {
245 		printf(": can't get aperture info\n");
246 		return;
247 	}
248 
249 	msc->msc_pc = pa->pa_pc;
250 	msc->msc_tag = pa->pa_tag;
251 
252 	maxdevs = pci_bus_maxdevs(pa->pa_pc, 0);
253 	for (i = 0, n = 0; i < maxdevs && n < AMD64_MAX_MCTRL; i++) {
254 		tag = pci_make_tag(pa->pa_pc, 0, i, 3);
255 		id = pci_conf_read(pa->pa_pc, tag, PCI_ID_REG);
256 		if (PCI_VENDOR(id) == PCI_VENDOR_AMD &&
257 		    PCI_PRODUCT(id) ==  PCI_PRODUCT_AMD_0F_MISC) {
258 			msc->mctrl_tag[n] = tag;
259 			n++;
260 		}
261 	}
262 	if (n == 0) {
263 		printf(": no Miscellaneous Control units found\n");
264 		return;
265 	}
266 	msc->n_mctrl = n;
267 
268 	printf(": %d Miscellaneous Control unit(s) found", msc->n_mctrl);
269 
270 	msc->msc_apsize = mmuagp_get_aperture(msc);
271 
272 	for (;;) {
273 		gatt = agp_alloc_gatt(pa->pa_dmat, msc->msc_apsize);
274 		if (gatt != NULL)
275 			break;
276 
277 		/*
278 		 * Probably failed to alloc contigious memory. Try reducing the
279 		 * aperture so that the gatt size reduces.
280 		 */
281 		msc->msc_apsize /= 2;
282 		if (mmuagp_set_aperture(msc, msc->msc_apsize)) {
283 			printf(" can't set aperture size\n");
284 			return;
285 		}
286 	}
287 	msc->gatt = gatt;
288 
289 	switch (PCI_VENDOR(pa->pa_id)) {
290 	case PCI_VENDOR_ALI:
291 		mmuagp_uli_init(msc);
292 		set_aperture = mmuagp_uli_set_aperture;
293 		break;
294 
295 	case PCI_VENDOR_NVIDIA:
296 		msc->ctrl_tag = AGP_AMD64_NVIDIA_PCITAG(pa->pa_pc);
297 		mmuagp_nvidia_init(msc);
298 		set_aperture = mmuagp_nvidia_set_aperture;
299 		break;
300 
301 	case PCI_VENDOR_VIATECH:
302 		/* do we have to set the extra bridge too? */
303 		if (mmuagp_via_match(pa)) {
304 			msc->ctrl_tag = AGP_AMD64_VIA_PCITAG(pa->pa_pc);
305 			mmuagp_via_init(msc);
306 			set_aperture = mmuagp_via_set_aperture;
307 		}
308 		break;
309 	}
310 
311 	if (set_aperture != NULL) {
312 		if ((*set_aperture)(msc, msc->msc_apsize)) {
313 			printf(", failed aperture set\n");
314 			return;
315 		}
316 	}
317 
318 	/* Install the gatt and enable aperture. */
319 	attbase = (uint32_t)(gatt->ag_physical >> 8) & AGP_AMD64_ATTBASE_MASK;
320 	for (i = 0; i < msc->n_mctrl; i++) {
321 		pci_conf_write(pa->pa_pc, msc->mctrl_tag[i], AGP_AMD64_ATTBASE,
322 		    attbase);
323 		apctrl = pci_conf_read(pa->pa_pc, msc->mctrl_tag[i],
324 		    AGP_AMD64_APCTRL);
325 		apctrl |= AGP_AMD64_APCTRL_GARTEN;
326 		apctrl &=
327 		    ~(AGP_AMD64_APCTRL_DISGARTCPU | AGP_AMD64_APCTRL_DISGARTIO);
328 		pci_conf_write(pa->pa_pc, msc->mctrl_tag[i], AGP_AMD64_APCTRL,
329 		    apctrl);
330 	}
331 
332 	agp_flush_cache();
333 
334 	msc->agpdev = (struct agp_softc *)agp_attach_bus(pa, &mmuagp_methods,
335 	    msc->msc_apaddr, msc->msc_apsize, &msc->dev);
336 	return;
337 }
338 
339 
340 static bus_size_t mmuagp_table[] = {
341 	0x02000000,	/*   32 MB */
342 	0x04000000,	/*   64 MB */
343 	0x08000000,	/*  128 MB */
344 	0x10000000,	/*  256 MB */
345 	0x20000000,	/*  512 MB */
346 	0x40000000,	/* 1024 MB */
347 	0x80000000,	/* 2048 MB */
348 };
349 
350 #define AGP_AMD64_TABLE_SIZE \
351 	(sizeof(mmuagp_table) / sizeof(mmuagp_table[0]))
352 
353 bus_size_t
354 mmuagp_get_aperture(void *sc)
355 {
356 	struct mmuagp_softc *msc = sc;
357 	uint32_t i;
358 
359 	i = (pci_conf_read(msc->msc_pc, msc->mctrl_tag[0], AGP_AMD64_APCTRL) &
360 		AGP_AMD64_APCTRL_SIZE_MASK) >> 1;
361 
362 	if (i >= AGP_AMD64_TABLE_SIZE)
363 		return 0;
364 
365 	return mmuagp_table[i];
366 }
367 
368 int
369 mmuagp_set_aperture(void *sc, bus_size_t aperture)
370 {
371 	struct mmuagp_softc	*msc = sc;
372 	uint32_t		 i;
373 	pcireg_t		 apctrl;
374 	int			 j;
375 
376 	for (i = 0; i < AGP_AMD64_TABLE_SIZE; i++)
377 		if (mmuagp_table[i] == aperture)
378 			break;
379 	if (i >= AGP_AMD64_TABLE_SIZE)
380 		return (EINVAL);
381 
382 	for (j = 0; j < msc->n_mctrl; j++) {
383 		apctrl = pci_conf_read(msc->msc_pc, msc->mctrl_tag[0],
384 		    AGP_AMD64_APCTRL);
385 		pci_conf_write(msc->msc_pc, msc->mctrl_tag[0], AGP_AMD64_APCTRL,
386 		    (apctrl & ~(AGP_AMD64_APCTRL_SIZE_MASK)) | (i << 1));
387 	}
388 
389 	return (0);
390 }
391 
392 void
393 mmuagp_bind_page(void *sc, bus_addr_t offset, paddr_t physical, int flags)
394 {
395 	struct mmuagp_softc	*msc = sc;
396 
397 	msc->gatt->ag_virtual[(offset - msc->msc_apaddr) >> AGP_PAGE_SHIFT] =
398 	    (physical & 0xfffff000) | ((physical >> 28) & 0x00000ff0) | 3;
399 }
400 
401 void
402 mmuagp_unbind_page(void *sc, bus_addr_t offset)
403 {
404 	struct mmuagp_softc *msc = sc;
405 
406 	msc->gatt->ag_virtual[(offset - msc->msc_apaddr) >> AGP_PAGE_SHIFT] = 0;
407 }
408 
409 void
410 mmuagp_flush_tlb(void *sc)
411 {
412 	struct mmuagp_softc	*msc = sc;
413 	pcireg_t		 cachectrl;
414 	int			 i;
415 
416 	for (i = 0; i < msc->n_mctrl; i++) {
417 		cachectrl = pci_conf_read(msc->msc_pc, msc->mctrl_tag[i],
418 		    AGP_AMD64_CACHECTRL);
419 		pci_conf_write(msc->msc_pc, msc->mctrl_tag[i],
420 		    AGP_AMD64_CACHECTRL,
421 		    cachectrl | AGP_AMD64_CACHECTRL_INVGART);
422 	}
423 }
424 
425 void
426 mmuagp_apbase_fixup(void *sc)
427 {
428 	struct mmuagp_softc	*msc = sc;
429 	uint32_t		 apbase;
430 	int			 i;
431 
432 	apbase = pci_conf_read(msc->msc_pc, msc->msc_tag, AGP_APBASE);
433 	msc->apbase = PCI_MAPREG_MEM_ADDR(apbase);
434 	apbase = (msc->apbase >> 25) & AGP_AMD64_APBASE_MASK;
435 	for (i = 0; i < msc->n_mctrl; i++)
436 		pci_conf_write(msc->msc_pc, msc->mctrl_tag[i], AGP_AMD64_APBASE,
437 		    apbase);
438 }
439 
440 void
441 mmuagp_uli_init(void *sc)
442 {
443 	struct mmuagp_softc *msc = sc;
444 	pcireg_t apbase;
445 
446 	mmuagp_apbase_fixup(msc);
447 	apbase = pci_conf_read(msc->msc_pc, msc->msc_tag,
448 	    AGP_AMD64_ULI_APBASE);
449 	pci_conf_write(msc->msc_pc, msc->msc_tag, AGP_AMD64_ULI_APBASE,
450 	    (apbase & 0x0000000f) | msc->apbase);
451 	pci_conf_write(msc->msc_pc, msc->msc_tag, AGP_AMD64_ULI_HTT_FEATURE,
452 	    msc->apbase);
453 }
454 
455 int
456 mmuagp_uli_set_aperture(void *sc, bus_size_t aperture)
457 {
458 	struct mmuagp_softc	*msc = sc;
459 
460 	switch (aperture) {
461 	case 0x02000000:	/*  32 MB */
462 	case 0x04000000:	/*  64 MB */
463 	case 0x08000000:	/* 128 MB */
464 	case 0x10000000:	/* 256 MB */
465 		break;
466 	default:
467 		return EINVAL;
468 	}
469 
470 	pci_conf_write(msc->msc_pc, msc->msc_tag, AGP_AMD64_ULI_ENU_SCR,
471 	    msc->apbase + aperture - 1);
472 
473 	return 0;
474 }
475 
476 void
477 mmuagp_nvidia_init(void *sc)
478 {
479 	struct mmuagp_softc	*msc = sc;
480 	pcireg_t		 apbase;
481 
482 	mmuagp_apbase_fixup(msc);
483 	apbase = pci_conf_read(msc->msc_pc, msc->msc_tag,
484 	    AGP_AMD64_NVIDIA_0_APBASE);
485 	pci_conf_write(msc->msc_pc, msc->msc_tag, AGP_AMD64_NVIDIA_0_APBASE,
486 	    (apbase & 0x0000000f) | msc->apbase);
487 	pci_conf_write(msc->msc_pc, msc->ctrl_tag, AGP_AMD64_NVIDIA_1_APBASE1,
488 	    msc->apbase);
489 	pci_conf_write(msc->msc_pc, msc->ctrl_tag, AGP_AMD64_NVIDIA_1_APBASE2,
490 	    msc->apbase);
491 }
492 
493 int
494 mmuagp_nvidia_set_aperture(void *sc, bus_size_t aperture)
495 {
496 	struct mmuagp_softc	*msc = sc;
497 	bus_size_t		 apsize;
498 
499 	switch (aperture) {
500 	case 0x02000000:	/*  32 MB */
501 		apsize = 0x0f;
502 		break;
503 	case 0x04000000:	/*  64 MB */
504 		apsize = 0x0e;
505 		break;
506 	case 0x08000000:	/* 128 MB */
507 		apsize = 0x0c;
508 		break;
509 	case 0x10000000:	/* 256 MB */
510 		apsize = 0x08;
511 		break;
512 	case 0x20000000:	/* 512 MB */
513 		apsize = 0x00;
514 		break;
515 	default:
516 		return (EINVAL);
517 	}
518 
519 	pci_conf_write(msc->msc_pc, msc->ctrl_tag, AGP_AMD64_NVIDIA_1_APSIZE,
520 	    (pci_conf_read(msc->msc_pc, msc->ctrl_tag,
521 	    AGP_AMD64_NVIDIA_1_APSIZE) & 0xfffffff0) | apsize);
522 	pci_conf_write(msc->msc_pc, msc->ctrl_tag, AGP_AMD64_NVIDIA_1_APLIMIT1,
523 	    msc->apbase + aperture - 1);
524 	pci_conf_write(msc->msc_pc, msc->ctrl_tag, AGP_AMD64_NVIDIA_1_APLIMIT2,
525 	    msc->apbase + aperture - 1);
526 
527 	return (0);
528 }
529 
530 void
531 mmuagp_via_init(void *sc)
532 {
533 	struct mmuagp_softc	*msc = sc;
534 
535 	mmuagp_apbase_fixup(sc);
536 	pci_conf_write(msc->msc_pc, msc->ctrl_tag, AGP3_VIA_ATTBASE,
537 	    msc->gatt->ag_physical);
538 	pci_conf_write(msc->msc_pc, msc->ctrl_tag, AGP3_VIA_GARTCTRL,
539 	    pci_conf_read(msc->msc_pc, msc->ctrl_tag, AGP3_VIA_ATTBASE) |
540 	        0x180);
541 }
542 
543 int
544 mmuagp_via_set_aperture(void *sc, bus_size_t aperture)
545 {
546 	struct mmuagp_softc	*msc = sc;
547 	bus_size_t		 apsize;
548 
549 	apsize = ((aperture - 1) >> 20) ^ 0xff;
550 	if ((((apsize ^ 0xff) << 20) | ((1 << 20) - 1)) + 1 != aperture)
551 		return (EINVAL);
552 	pci_conf_write(msc->msc_pc, msc->ctrl_tag, AGP3_VIA_APSIZE,
553 	    (pci_conf_read(msc->msc_pc, msc->ctrl_tag, AGP3_VIA_APSIZE) &
554 	        ~0xff) | apsize);
555 
556 	return 0;
557 }
558