Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/dev/agp/agp_via.c
39537 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2000 Doug Rabson
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
* 2. Redistributions in binary form must reproduce the above copyright
13
* notice, this list of conditions and the following disclaimer in the
14
* documentation and/or other materials provided with the distribution.
15
*
16
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26
* SUCH DAMAGE.
27
*/
28
29
#include <sys/param.h>
30
#include <sys/systm.h>
31
#include <sys/malloc.h>
32
#include <sys/kernel.h>
33
#include <sys/module.h>
34
#include <sys/bus.h>
35
#include <sys/lock.h>
36
#include <sys/mutex.h>
37
#include <sys/proc.h>
38
39
#include <dev/agp/agppriv.h>
40
#include <dev/agp/agpreg.h>
41
#include <dev/pci/pcivar.h>
42
#include <dev/pci/pcireg.h>
43
44
#include <vm/vm.h>
45
#include <vm/vm_object.h>
46
#include <vm/pmap.h>
47
48
#define REG_GARTCTRL 0
49
#define REG_APSIZE 1
50
#define REG_ATTBASE 2
51
52
struct agp_via_softc {
53
struct agp_softc agp;
54
u_int32_t initial_aperture; /* aperture size at startup */
55
struct agp_gatt *gatt;
56
int *regs;
57
};
58
59
static int via_v2_regs[] = { AGP_VIA_GARTCTRL, AGP_VIA_APSIZE,
60
AGP_VIA_ATTBASE };
61
static int via_v3_regs[] = { AGP3_VIA_GARTCTRL, AGP3_VIA_APSIZE,
62
AGP3_VIA_ATTBASE };
63
64
static const char*
65
agp_via_match(device_t dev)
66
{
67
if (pci_get_class(dev) != PCIC_BRIDGE
68
|| pci_get_subclass(dev) != PCIS_BRIDGE_HOST)
69
return NULL;
70
71
if (agp_find_caps(dev) == 0)
72
return NULL;
73
74
switch (pci_get_devid(dev)) {
75
case 0x01981106:
76
return ("VIA 8763 (P4X600) host to PCI bridge");
77
case 0x02591106:
78
return ("VIA PM800/PN800/PM880/PN880 host to PCI bridge");
79
case 0x02691106:
80
return ("VIA KT880 host to PCI bridge");
81
case 0x02961106:
82
return ("VIA 3296 (P4M800) host to PCI bridge");
83
case 0x03051106:
84
return ("VIA 82C8363 (Apollo KT133x/KM133) host to PCI bridge");
85
case 0x03141106:
86
return ("VIA 3314 (P4M800CE) host to PCI bridge");
87
case 0x03241106:
88
return ("VIA VT3324 (CX700) host to PCI bridge");
89
case 0x03271106:
90
return ("VIA 3327 (P4M890) host to PCI bridge");
91
case 0x03641106:
92
return ("VIA 3364 (P4M900) host to PCI bridge");
93
case 0x03911106:
94
return ("VIA 8371 (Apollo KX133) host to PCI bridge");
95
case 0x05011106:
96
return ("VIA 8501 (Apollo MVP4) host to PCI bridge");
97
case 0x05971106:
98
return ("VIA 82C597 (Apollo VP3) host to PCI bridge");
99
case 0x05981106:
100
return ("VIA 82C598 (Apollo MVP3) host to PCI bridge");
101
case 0x06011106:
102
return ("VIA 8601 (Apollo ProMedia/PLE133Ta) host to PCI bridge");
103
case 0x06051106:
104
return ("VIA 82C694X (Apollo Pro 133A) host to PCI bridge");
105
case 0x06911106:
106
return ("VIA 82C691 (Apollo Pro) host to PCI bridge");
107
case 0x30911106:
108
return ("VIA 8633 (Pro 266) host to PCI bridge");
109
case 0x30991106:
110
return ("VIA 8367 (KT266/KY266x/KT333) host to PCI bridge");
111
case 0x31011106:
112
return ("VIA 8653 (Pro266T) host to PCI bridge");
113
case 0x31121106:
114
return ("VIA 8361 (KLE133) host to PCI bridge");
115
case 0x31161106:
116
return ("VIA XM266 (PM266/KM266) host to PCI bridge");
117
case 0x31231106:
118
return ("VIA 862x (CLE266) host to PCI bridge");
119
case 0x31281106:
120
return ("VIA 8753 (P4X266) host to PCI bridge");
121
case 0x31481106:
122
return ("VIA 8703 (P4M266x/P4N266) host to PCI bridge");
123
case 0x31561106:
124
return ("VIA XN266 (Apollo Pro266) host to PCI bridge");
125
case 0x31681106:
126
return ("VIA 8754 (PT800) host to PCI bridge");
127
case 0x31891106:
128
return ("VIA 8377 (Apollo KT400/KT400A/KT600) host to PCI bridge");
129
case 0x32051106:
130
return ("VIA 8235/8237 (Apollo KM400/KM400A) host to PCI bridge");
131
case 0x32081106:
132
return ("VIA 8783 (PT890) host to PCI bridge");
133
case 0x32581106:
134
return ("VIA PT880 host to PCI bridge");
135
case 0xb1981106:
136
return ("VIA VT83xx/VT87xx/KTxxx/Px8xx host to PCI bridge");
137
}
138
139
return NULL;
140
}
141
142
static int
143
agp_via_probe(device_t dev)
144
{
145
const char *desc;
146
147
if (resource_disabled("agp", device_get_unit(dev)))
148
return (ENXIO);
149
desc = agp_via_match(dev);
150
if (desc) {
151
device_set_desc(dev, desc);
152
return BUS_PROBE_DEFAULT;
153
}
154
155
return ENXIO;
156
}
157
158
static int
159
agp_via_attach(device_t dev)
160
{
161
struct agp_via_softc *sc = device_get_softc(dev);
162
struct agp_gatt *gatt;
163
int error;
164
u_int32_t agpsel;
165
u_int32_t capid;
166
167
sc->regs = via_v2_regs;
168
169
/* Look at the capability register to see if we handle AGP3 */
170
capid = pci_read_config(dev, agp_find_caps(dev) + AGP_CAPID, 4);
171
if (((capid >> 20) & 0x0f) >= 3) {
172
agpsel = pci_read_config(dev, AGP_VIA_AGPSEL, 1);
173
if ((agpsel & (1 << 1)) == 0)
174
sc->regs = via_v3_regs;
175
}
176
177
error = agp_generic_attach(dev);
178
if (error)
179
return error;
180
181
sc->initial_aperture = AGP_GET_APERTURE(dev);
182
183
for (;;) {
184
gatt = agp_alloc_gatt(dev);
185
if (gatt)
186
break;
187
188
/*
189
* Probably contigmalloc failure. Try reducing the
190
* aperture so that the gatt size reduces.
191
*/
192
if (AGP_SET_APERTURE(dev, AGP_GET_APERTURE(dev) / 2)) {
193
agp_generic_detach(dev);
194
return ENOMEM;
195
}
196
}
197
sc->gatt = gatt;
198
199
if (sc->regs == via_v2_regs) {
200
/* Install the gatt. */
201
pci_write_config(dev, sc->regs[REG_ATTBASE], gatt->ag_physical | 3, 4);
202
203
/* Enable the aperture. */
204
pci_write_config(dev, sc->regs[REG_GARTCTRL], 0x0f, 4);
205
} else {
206
u_int32_t gartctrl;
207
208
/* Install the gatt. */
209
pci_write_config(dev, sc->regs[REG_ATTBASE], gatt->ag_physical, 4);
210
211
/* Enable the aperture. */
212
gartctrl = pci_read_config(dev, sc->regs[REG_GARTCTRL], 4);
213
pci_write_config(dev, sc->regs[REG_GARTCTRL], gartctrl | (3 << 7), 4);
214
}
215
216
device_printf(dev, "aperture size is %dM\n",
217
sc->initial_aperture / 1024 / 1024);
218
219
return 0;
220
}
221
222
static int
223
agp_via_detach(device_t dev)
224
{
225
struct agp_via_softc *sc = device_get_softc(dev);
226
227
agp_free_cdev(dev);
228
229
pci_write_config(dev, sc->regs[REG_GARTCTRL], 0, 4);
230
pci_write_config(dev, sc->regs[REG_ATTBASE], 0, 4);
231
AGP_SET_APERTURE(dev, sc->initial_aperture);
232
agp_free_gatt(sc->gatt);
233
agp_free_res(dev);
234
235
return 0;
236
}
237
238
static u_int32_t
239
agp_via_get_aperture(device_t dev)
240
{
241
struct agp_via_softc *sc = device_get_softc(dev);
242
u_int32_t apsize;
243
244
if (sc->regs == via_v2_regs) {
245
apsize = pci_read_config(dev, sc->regs[REG_APSIZE], 1);
246
247
/*
248
* The size is determined by the number of low bits of
249
* register APBASE which are forced to zero. The low 20 bits
250
* are always forced to zero and each zero bit in the apsize
251
* field just read forces the corresponding bit in the 27:20
252
* to be zero. We calculate the aperture size accordingly.
253
*/
254
return (((apsize ^ 0xff) << 20) | ((1 << 20) - 1)) + 1;
255
} else {
256
apsize = pci_read_config(dev, sc->regs[REG_APSIZE], 2) & 0xfff;
257
switch (apsize) {
258
case 0x800:
259
return 0x80000000;
260
case 0xc00:
261
return 0x40000000;
262
case 0xe00:
263
return 0x20000000;
264
case 0xf00:
265
return 0x10000000;
266
case 0xf20:
267
return 0x08000000;
268
case 0xf30:
269
return 0x04000000;
270
case 0xf38:
271
return 0x02000000;
272
case 0xf3c:
273
return 0x01000000;
274
case 0xf3e:
275
return 0x00800000;
276
case 0xf3f:
277
return 0x00400000;
278
default:
279
device_printf(dev, "Invalid aperture setting 0x%x\n",
280
pci_read_config(dev, sc->regs[REG_APSIZE], 2));
281
return 0;
282
}
283
}
284
}
285
286
static int
287
agp_via_set_aperture(device_t dev, u_int32_t aperture)
288
{
289
struct agp_via_softc *sc = device_get_softc(dev);
290
u_int32_t apsize, key, val;
291
292
if (sc->regs == via_v2_regs) {
293
/*
294
* Reverse the magic from get_aperture.
295
*/
296
apsize = ((aperture - 1) >> 20) ^ 0xff;
297
298
/*
299
* Double check for sanity.
300
*/
301
if ((((apsize ^ 0xff) << 20) | ((1 << 20) - 1)) + 1 != aperture)
302
return EINVAL;
303
304
pci_write_config(dev, sc->regs[REG_APSIZE], apsize, 1);
305
} else {
306
switch (aperture) {
307
case 0x80000000:
308
key = 0x800;
309
break;
310
case 0x40000000:
311
key = 0xc00;
312
break;
313
case 0x20000000:
314
key = 0xe00;
315
break;
316
case 0x10000000:
317
key = 0xf00;
318
break;
319
case 0x08000000:
320
key = 0xf20;
321
break;
322
case 0x04000000:
323
key = 0xf30;
324
break;
325
case 0x02000000:
326
key = 0xf38;
327
break;
328
case 0x01000000:
329
key = 0xf3c;
330
break;
331
case 0x00800000:
332
key = 0xf3e;
333
break;
334
case 0x00400000:
335
key = 0xf3f;
336
break;
337
default:
338
device_printf(dev, "Invalid aperture size (%dMb)\n",
339
aperture / 1024 / 1024);
340
return EINVAL;
341
}
342
val = pci_read_config(dev, sc->regs[REG_APSIZE], 2);
343
pci_write_config(dev, sc->regs[REG_APSIZE],
344
((val & ~0xfff) | key), 2);
345
}
346
return 0;
347
}
348
349
static int
350
agp_via_bind_page(device_t dev, vm_offset_t offset, vm_offset_t physical)
351
{
352
struct agp_via_softc *sc = device_get_softc(dev);
353
354
if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
355
return EINVAL;
356
357
sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = physical;
358
return 0;
359
}
360
361
static int
362
agp_via_unbind_page(device_t dev, vm_offset_t offset)
363
{
364
struct agp_via_softc *sc = device_get_softc(dev);
365
366
if (offset >= (sc->gatt->ag_entries << AGP_PAGE_SHIFT))
367
return EINVAL;
368
369
sc->gatt->ag_virtual[offset >> AGP_PAGE_SHIFT] = 0;
370
return 0;
371
}
372
373
static void
374
agp_via_flush_tlb(device_t dev)
375
{
376
struct agp_via_softc *sc = device_get_softc(dev);
377
u_int32_t gartctrl;
378
379
if (sc->regs == via_v2_regs) {
380
pci_write_config(dev, sc->regs[REG_GARTCTRL], 0x8f, 4);
381
pci_write_config(dev, sc->regs[REG_GARTCTRL], 0x0f, 4);
382
} else {
383
gartctrl = pci_read_config(dev, sc->regs[REG_GARTCTRL], 4);
384
pci_write_config(dev, sc->regs[REG_GARTCTRL], gartctrl &
385
~(1 << 7), 4);
386
pci_write_config(dev, sc->regs[REG_GARTCTRL], gartctrl, 4);
387
}
388
389
}
390
391
static device_method_t agp_via_methods[] = {
392
/* Device interface */
393
DEVMETHOD(device_probe, agp_via_probe),
394
DEVMETHOD(device_attach, agp_via_attach),
395
DEVMETHOD(device_detach, agp_via_detach),
396
DEVMETHOD(device_shutdown, bus_generic_shutdown),
397
DEVMETHOD(device_suspend, bus_generic_suspend),
398
DEVMETHOD(device_resume, bus_generic_resume),
399
400
/* AGP interface */
401
DEVMETHOD(agp_get_aperture, agp_via_get_aperture),
402
DEVMETHOD(agp_set_aperture, agp_via_set_aperture),
403
DEVMETHOD(agp_bind_page, agp_via_bind_page),
404
DEVMETHOD(agp_unbind_page, agp_via_unbind_page),
405
DEVMETHOD(agp_flush_tlb, agp_via_flush_tlb),
406
DEVMETHOD(agp_enable, agp_generic_enable),
407
DEVMETHOD(agp_alloc_memory, agp_generic_alloc_memory),
408
DEVMETHOD(agp_free_memory, agp_generic_free_memory),
409
DEVMETHOD(agp_bind_memory, agp_generic_bind_memory),
410
DEVMETHOD(agp_unbind_memory, agp_generic_unbind_memory),
411
{ 0, 0 }
412
};
413
414
static driver_t agp_via_driver = {
415
"agp",
416
agp_via_methods,
417
sizeof(struct agp_via_softc),
418
};
419
420
DRIVER_MODULE(agp_via, hostb, agp_via_driver, 0, 0);
421
MODULE_DEPEND(agp_via, agp, 1, 1, 1);
422
MODULE_DEPEND(agp_via, pci, 1, 1, 1);
423
424