1 /*
2 * Copyright 2005-2015 The Openchrome Project
3 * [https://www.freedesktop.org/wiki/Openchrome]
4 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
5 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sub license,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 */
26
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include "xf86.h"
32 #include "xf86_OSproc.h"
33 #include "xf86Priv.h"
34
35 #include "xf86Pci.h"
36
37 #define _XF86DRI_SERVER_
38 #include "GL/glxtokens.h"
39 #include "sarea.h"
40
41 #include "via_driver.h"
42 #include "via_drm.h"
43 #include "via_dri.h"
44 #include "xf86drm.h"
45
46 #ifndef DRIINFO_MAJOR_VERSION
47 #define DRIINFO_MAJOR_VERSION 4
48 #endif
49 #ifndef DRIINFO_MINOR_VERSION
50 #define DRIINFO_MINOR_VERSION 0
51 #endif
52
53 #define VIDEO 0
54 #define AGP 1
55 #define AGP_CMDBUF_PAGES 512
56 #define AGP_CMDBUF_SIZE (AGP_PAGE_SIZE * AGP_CMDBUF_PAGES)
57 #define VIA_AGP_MODE_MASK 0x17
58 #define VIA_AGPv3_MODE 0x08
59 #define VIA_AGPv3_8X_MODE 0x02
60 #define VIA_AGPv3_4X_MODE 0x01
61 #define VIA_AGP_4X_MODE 0x04
62 #define VIA_AGP_2X_MODE 0x02
63 #define VIA_AGP_1X_MODE 0x01
64 #define VIA_AGP_FW_MODE 0x10
65
66 extern void GlxSetVisualConfigs(int nconfigs,
67 __GLXvisualConfig * configs,
68 void **configprivs);
69
70 typedef struct
71 {
72 int major;
73 int minor;
74 int patchlevel;
75 } ViaDRMVersion;
76
77 static char VIAKernelDriverName[] = "via";
78 static char VIAClientDriverName[] = "unichrome";
79 static const ViaDRMVersion drmExpected = { 1, 3, 0 };
80 static const ViaDRMVersion drmCompat = { 2, 0, 0 };
81
82 static Bool VIAInitVisualConfigs(ScreenPtr pScreen);
83 static Bool VIADRIMapInit(ScreenPtr pScreen, VIAPtr pVia);
84
85 static Bool VIACreateContext(ScreenPtr pScreen, VisualPtr visual,
86 drm_context_t hwContext, void *pVisualConfigPriv,
87 DRIContextType contextStore);
88 static void VIADestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
89 DRIContextType contextStore);
90 static void VIADRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
91 DRIContextType readContextType,
92 void *readContextStore,
93 DRIContextType writeContextType,
94 void *writeContextStore);
95 static void VIADRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index);
96 static void VIADRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
97 RegionPtr prgnSrc, CARD32 index);
98
99 void
kickVblank(ScrnInfoPtr pScrn)100 kickVblank(ScrnInfoPtr pScrn)
101 {
102 /*
103 * Switching mode will clear registers that make vblank
104 * interrupts happen. If the driver thinks interrupts
105 * are enabled, make sure vblank interrupts go through.
106 * registers are not documented in VIA docs.
107 */
108 VIAPtr pVia = VIAPTR(pScrn);
109 vgaHWPtr hwp = VGAHWPTR(pScrn);
110 VIADRIPtr pVIADRI = pVia->pDRIInfo->devPrivate;
111
112 if (pVIADRI->irqEnabled)
113 hwp->writeCrtc(hwp, 0x11, hwp->readCrtc(hwp, 0x11) | 0x30);
114 }
115
116 static void
VIADRIIrqInit(ScrnInfoPtr pScrn,VIADRIPtr pVIADRI)117 VIADRIIrqInit(ScrnInfoPtr pScrn, VIADRIPtr pVIADRI)
118 {
119 VIAPtr pVia = VIAPTR(pScrn);
120
121 pVIADRI->irqEnabled = drmGetInterruptFromBusID
122 (pVia->drmmode.fd,
123 #ifdef HAVE_PCIACCESS
124 ((pVia->PciInfo->domain << 8) | pVia->PciInfo->bus),
125 pVia->PciInfo->dev, pVia->PciInfo->func
126 #else
127 ((pciConfigPtr)pVia->PciInfo->thisCard)->busnum,
128 ((pciConfigPtr)pVia->PciInfo->thisCard)->devnum,
129 ((pciConfigPtr)pVia->PciInfo->thisCard)->funcnum
130 #endif
131 );
132 if ((drmCtlInstHandler(pVia->drmmode.fd, pVIADRI->irqEnabled))) {
133 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
134 "[drm] Failure adding IRQ handler. "
135 "Falling back to IRQ-free operation.\n");
136 pVIADRI->irqEnabled = 0;
137 }
138
139 if (pVIADRI->irqEnabled)
140 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
141 "[drm] IRQ handler installed, using IRQ %d.\n",
142 pVIADRI->irqEnabled);
143 }
144
145 static void
VIADRIIrqExit(ScrnInfoPtr pScrn,VIADRIPtr pVIADRI)146 VIADRIIrqExit(ScrnInfoPtr pScrn, VIADRIPtr pVIADRI)
147 {
148 VIAPtr pVia = VIAPTR(pScrn);
149
150 if (pVIADRI->irqEnabled) {
151 if (drmCtlUninstHandler(pVia->drmmode.fd)) {
152 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
153 "[drm] IRQ handler uninstalled.\n");
154 } else {
155 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
156 "[drm] Could not uninstall IRQ handler.\n");
157 }
158 }
159 }
160
161 void
VIADRIRingBufferCleanup(ScrnInfoPtr pScrn)162 VIADRIRingBufferCleanup(ScrnInfoPtr pScrn)
163 {
164 VIAPtr pVia = VIAPTR(pScrn);
165 VIADRIPtr pVIADRI = pVia->pDRIInfo->devPrivate;
166
167 if (pVIADRI->ringBufActive) {
168 drm_via_dma_init_t ringBufInit;
169
170 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
171 "[drm] Cleaning up DMA ring-buffer.\n");
172 ringBufInit.func = VIA_CLEANUP_DMA;
173 if (drmCommandWrite(pVia->drmmode.fd, DRM_VIA_DMA_INIT, &ringBufInit,
174 sizeof(ringBufInit))) {
175 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
176 "[drm] Failed to clean up DMA ring-buffer: %d\n", errno);
177 }
178 pVIADRI->ringBufActive = 0;
179 }
180 }
181
182 Bool
VIADRIRingBufferInit(ScrnInfoPtr pScrn)183 VIADRIRingBufferInit(ScrnInfoPtr pScrn)
184 {
185 VIAPtr pVia = VIAPTR(pScrn);
186 VIADRIPtr pVIADRI = pVia->pDRIInfo->devPrivate;
187
188 if (pVIADRI->ringBufActive)
189 return TRUE;
190
191 if (pVia->agpEnable) {
192 drm_via_dma_init_t ringBufInit;
193
194 if ((pVia->drmVerMajor == 1) && (pVia->drmVerMinor <= 3))
195 return FALSE;
196
197 /*
198 * Info from code-snippet on DRI-DEVEL list; Erdi Chen.
199 */
200
201 switch (pVia->ChipId) {
202 case PCI_CHIP_VT3314:
203 case PCI_CHIP_VT3259:
204 pVIADRI->reg_pause_addr = 0x40c;
205 break;
206 default:
207 pVIADRI->reg_pause_addr = 0x418;
208 break;
209 }
210
211 ringBufInit.offset = pVia->agpSize;
212 ringBufInit.size = AGP_CMDBUF_SIZE;
213 ringBufInit.reg_pause_addr = pVIADRI->reg_pause_addr;
214 ringBufInit.func = VIA_INIT_DMA;
215
216 if (drmCommandWrite(pVia->drmmode.fd, DRM_VIA_DMA_INIT, &ringBufInit,
217 sizeof(ringBufInit))) {
218 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
219 "[drm] Failed to initialize DMA ring-buffer: %d\n",
220 errno);
221 return FALSE;
222 }
223
224 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
225 "[drm] Initialized AGP ring-buffer, size 0x%lx at AGP "
226 "offset 0x%lx.\n", ringBufInit.size, ringBufInit.offset);
227 pVIADRI->ringBufActive = 1;
228 }
229 return TRUE;
230 }
231
232 static Bool
VIASetAgpMode(ScrnInfoPtr pScrn)233 VIASetAgpMode(ScrnInfoPtr pScrn)
234 {
235 VIAPtr pVia = VIAPTR(pScrn);
236 CARD32 mode = drmAgpGetMode(pVia->drmmode.fd);
237 unsigned int vendor = drmAgpVendorId(pVia->drmmode.fd);
238 unsigned int device = drmAgpDeviceId(pVia->drmmode.fd);
239
240 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Detected AGP "
241 "vendor 0x%04x, device 0x%04x\n", vendor, device);
242
243 mode &= ~VIA_AGP_MODE_MASK;
244 if (mode & VIA_AGPv3_MODE) {
245 mode |= VIA_AGPv3_8X_MODE;
246 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Found AGP v3 "
247 "compatible device. Trying AGP 8X mode.\n");
248 } else {
249 mode |= VIA_AGP_4X_MODE;
250 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Didn't find any AGP v3 "
251 "compatible device. Trying AGP 4X mode.\n");
252 }
253
254 mode |= VIA_AGP_FW_MODE;
255 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
256 "[drm] Trying to enable AGP fast writes.\n");
257
258 if (drmAgpEnable(pVia->drmmode.fd, mode) < 0)
259 return FALSE;
260 return TRUE;
261 }
262
263 static Bool
VIADRIAgpInit(ScrnInfoPtr pScrn)264 VIADRIAgpInit(ScrnInfoPtr pScrn)
265 {
266 unsigned long agpCmdSize, agp_phys;
267 VIAPtr pVia = VIAPTR(pScrn);
268 drm_handle_t handle;
269 drmAddress agpaddr;
270 drm_via_agp_t agp;
271 int agpPages;
272
273 pVia->agpSize = 0;
274 if (drmAgpAcquire(pVia->drmmode.fd) < 0) {
275 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] drmAgpAcquire failed %d\n",
276 errno);
277 return FALSE;
278 }
279
280 if (!VIASetAgpMode(pScrn)) {
281 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] VIASetAgpMode failed\n");
282 drmAgpRelease(pVia->drmmode.fd);
283 return FALSE;
284 }
285
286 agpCmdSize = (pVia->agpEnable) ? AGP_CMDBUF_SIZE : 0;
287 if (pVia->agpMem * 1024 < agpCmdSize + AGP_PAGE_SIZE) {
288 pVia->agpMem = (agpCmdSize + AGP_PAGE_SIZE) / 1024;
289 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
290 "[drm] Forcing AGP size to %d kB\n", pVia->agpMem);
291 }
292
293 agpPages = (pVia->agpMem * 1024 + AGP_PAGE_SIZE - 1) / AGP_PAGE_SIZE;
294 if (drmAgpAlloc(pVia->drmmode.fd, agpPages * AGP_PAGE_SIZE,
295 0, &agp_phys, &pVia->agpHandle) < 0) {
296 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] drmAgpAlloc failed\n");
297 drmAgpRelease(pVia->drmmode.fd);
298 return FALSE;
299 }
300
301 if (drmAgpBind(pVia->drmmode.fd, pVia->agpHandle, 0) < 0) {
302 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[drm] drmAgpBind failed\n");
303 drmAgpFree(pVia->drmmode.fd, pVia->agpHandle);
304 drmAgpRelease(pVia->drmmode.fd);
305 return FALSE;
306 }
307
308 /*
309 * Place the ring-buffer last in the AGP region, and restrict the
310 * public map not to include the buffer for security reasons.
311 */
312 pVia->agpSize = agpPages * AGP_PAGE_SIZE - agpCmdSize;
313 pVia->agpAddr = drmAgpBase(pVia->drmmode.fd);
314 agp.offset = 0;
315 agp.size = pVia->agpSize;
316 if (drmCommandWrite(pVia->drmmode.fd, DRM_VIA_AGP_INIT, &agp,
317 sizeof(drm_via_agp_t)) < 0) {
318 drmAgpUnbind(pVia->drmmode.fd, pVia->agpHandle);
319 drmAgpFree(pVia->drmmode.fd, pVia->agpHandle);
320 drmAgpRelease(pVia->drmmode.fd);
321 return FALSE;
322 }
323
324 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] drmAgpEnabled succeeded\n");
325
326 /* Allocate all of AGP memory */
327 if (drmAddMap(pVia->drmmode.fd, 0, pVia->agpSize,
328 DRM_AGP, 0, &handle) < 0) {
329 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
330 "[drm] Failed to map public agp area.\n");
331 pVia->agpSize = 0;
332 drmAgpUnbind(pVia->drmmode.fd, pVia->agpHandle);
333 drmAgpFree(pVia->drmmode.fd, pVia->agpHandle);
334 drmAgpRelease(pVia->drmmode.fd);
335 return FALSE;
336 }
337 drmMap(pVia->drmmode.fd, handle, pVia->agpSize, &agpaddr);
338 pVia->agpMappedAddr = agpaddr;
339
340 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
341 "[drm] agpAddr = 0x%08lx\n", pVia->agpAddr);
342 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
343 "[drm] agpSize = 0x%08x\n", pVia->agpSize);
344 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
345 "[drm] agp physical addr = %p\n", pVia->agpMappedAddr);
346 return TRUE;
347 }
348
349 static Bool
VIADRIFBInit(ScrnInfoPtr pScrn)350 VIADRIFBInit(ScrnInfoPtr pScrn)
351 {
352 VIAPtr pVia = VIAPTR(pScrn);
353 drm_via_fb_t fb;
354
355 fb.offset = pVia->FBFreeStart;
356 fb.size = pVia->FBFreeEnd;
357 if (drmCommandWrite(pVia->drmmode.fd, DRM_VIA_FB_INIT, &fb,
358 sizeof(drm_via_fb_t)) < 0) {
359 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
360 "[drm] Failed to initialize frame buffer area.\n");
361 return FALSE;
362 } else {
363 xf86DrvMsg(pScrn->scrnIndex, X_INFO,
364 "[drm] Using %d KB for DRM memory heap.\n", fb.size >> 10);
365 return TRUE;
366 }
367 }
368
369 static Bool
VIAInitVisualConfigs(ScreenPtr pScreen)370 VIAInitVisualConfigs(ScreenPtr pScreen)
371 {
372 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
373 VIAPtr pVia = VIAPTR(pScrn);
374 int numConfigs = 0;
375 __GLXvisualConfig *pConfigs = 0;
376 VIAConfigPrivPtr pVIAConfigs = 0;
377 VIAConfigPrivPtr *pVIAConfigPtrs = 0;
378 int i, db, stencil, accum;
379
380 if (pScrn->bitsPerPixel == 16 || pScrn->bitsPerPixel == 32) {
381 numConfigs = 12;
382 if (!(pConfigs = (__GLXvisualConfig *)
383 calloc(sizeof(__GLXvisualConfig), numConfigs)))
384 return FALSE;
385 if (!(pVIAConfigs = (VIAConfigPrivPtr)
386 calloc(sizeof(VIAConfigPrivRec), numConfigs))) {
387 free(pConfigs);
388 return FALSE;
389 }
390 if (!(pVIAConfigPtrs = (VIAConfigPrivPtr *)
391 calloc(sizeof(VIAConfigPrivPtr), numConfigs))) {
392 free(pConfigs);
393 free(pVIAConfigs);
394 return FALSE;
395 }
396 for (i = 0; i < numConfigs; i++)
397 pVIAConfigPtrs[i] = &pVIAConfigs[i];
398
399 i = 0;
400 for (accum = 0; accum <= 1; accum++) {
401 /* 32bpp depth buffer disabled, as Mesa has limitations */
402 for (stencil = 0; stencil <= 2; stencil++) {
403 for (db = 0; db <= 1; db++) {
404 pConfigs[i].vid = -1;
405 pConfigs[i].class = -1;
406 pConfigs[i].rgba = TRUE;
407 pConfigs[i].redSize = -1;
408 pConfigs[i].greenSize = -1;
409 pConfigs[i].blueSize = -1;
410 pConfigs[i].redMask = -1;
411 pConfigs[i].greenMask = -1;
412 pConfigs[i].blueMask = -1;
413 if (pScrn->bitsPerPixel == 32) {
414 pConfigs[i].alphaSize = 8;
415 pConfigs[i].alphaMask = 0xFF000000;
416 } else {
417 pConfigs[i].alphaSize = 0;
418 pConfigs[i].alphaMask = 0;
419 }
420
421 if (accum) {
422 pConfigs[i].accumRedSize = 16;
423 pConfigs[i].accumGreenSize = 16;
424 pConfigs[i].accumBlueSize = 16;
425 if (pScrn->bitsPerPixel == 32)
426 pConfigs[i].accumAlphaSize = 16;
427 else
428 pConfigs[i].accumAlphaSize = 0;
429 } else {
430 pConfigs[i].accumRedSize = 0;
431 pConfigs[i].accumGreenSize = 0;
432 pConfigs[i].accumBlueSize = 0;
433 pConfigs[i].accumAlphaSize = 0;
434 }
435 if (!db)
436 pConfigs[i].doubleBuffer = TRUE;
437 else
438 pConfigs[i].doubleBuffer = FALSE;
439
440 pConfigs[i].stereo = FALSE;
441 pConfigs[i].bufferSize = -1;
442
443 switch (stencil) {
444 case 0:
445 pConfigs[i].depthSize = 24;
446 pConfigs[i].stencilSize = 8;
447 break;
448 case 1:
449 pConfigs[i].depthSize = 16;
450 pConfigs[i].stencilSize = 0;
451 break;
452 case 2:
453 pConfigs[i].depthSize = 0;
454 pConfigs[i].stencilSize = 0;
455 break;
456 case 3:
457 pConfigs[i].depthSize = 32;
458 pConfigs[i].stencilSize = 0;
459 break;
460 }
461
462 pConfigs[i].auxBuffers = 0;
463 pConfigs[i].level = 0;
464 if (accum)
465 pConfigs[i].visualRating = GLX_SLOW_VISUAL_EXT;
466 else
467 pConfigs[i].visualRating = GLX_NONE_EXT;
468 pConfigs[i].transparentPixel = GLX_NONE_EXT;
469 pConfigs[i].transparentRed = 0;
470 pConfigs[i].transparentGreen = 0;
471 pConfigs[i].transparentBlue = 0;
472 pConfigs[i].transparentAlpha = 0;
473 pConfigs[i].transparentIndex = 0;
474 i++;
475 }
476 }
477 }
478
479 if (i != numConfigs) {
480 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "[dri] Incorrect "
481 "initialization of visuals. Disabling DRI.\n");
482
483 if (pConfigs)
484 free(pConfigs);
485 if (pVIAConfigs)
486 free(pVIAConfigs);
487 if (pVIAConfigPtrs)
488 free(pVIAConfigPtrs);
489
490 return FALSE;
491 }
492 }
493
494 pVia->numVisualConfigs = numConfigs;
495 pVia->pVisualConfigs = pConfigs;
496 pVia->pVisualConfigsPriv = pVIAConfigs;
497 GlxSetVisualConfigs(numConfigs, pConfigs, (void **)pVIAConfigPtrs);
498
499 return TRUE;
500 }
501
502 Bool
VIADRI1ScreenInit(ScreenPtr pScreen)503 VIADRI1ScreenInit(ScreenPtr pScreen)
504 {
505 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
506 VIAPtr pVia = VIAPTR(pScrn);
507 int major, minor, patch;
508 DRIInfoPtr pDRIInfo;
509 VIADRIPtr pVIADRI;
510
511 /* If symbols or version check fails, we still want this to be NULL. */
512 pVia->pDRIInfo = NULL;
513 drmClose(pVia->drmmode.fd);
514
515 /* Check that the GLX, DRI, and DRM modules have been loaded by testing
516 * for canonical symbols in each module. */
517 if (!xf86LoaderCheckSymbol("GlxSetVisualConfigs"))
518 return FALSE;
519 if (!xf86LoaderCheckSymbol("drmAvailable"))
520 return FALSE;
521 if (!xf86LoaderCheckSymbol("DRIQueryVersion")) {
522 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
523 "[dri] VIADRI1ScreenInit failed (libdri.a is too old).\n");
524 return FALSE;
525 }
526
527 /* Check the DRI version. */
528 DRIQueryVersion(&major, &minor, &patch);
529 if (major != DRIINFO_MAJOR_VERSION || minor < DRIINFO_MINOR_VERSION) {
530 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
531 "[dri] VIADRI1ScreenInit failed -- FALSE mismatch.\n"
532 "[dri] libdri is %d.%d.%d, but %d.%d.x is needed.\n"
533 "[dri] Disabling DRI.\n",
534 major, minor, patch,
535 DRIINFO_MAJOR_VERSION, DRIINFO_MINOR_VERSION);
536 return FALSE;
537 }
538
539 pVia->pDRIInfo = DRICreateInfoRec();
540 if (!pVia->pDRIInfo)
541 return FALSE;
542
543 pDRIInfo = pVia->pDRIInfo;
544 pDRIInfo->drmDriverName = VIAKernelDriverName;
545 switch (pVia->Chipset) {
546 case VIA_K8M890:
547 case VIA_P4M900:
548 case VIA_VX800:
549 case VIA_VX855:
550 case VIA_VX900:
551 pDRIInfo->clientDriverName = "swrast";
552 break;
553 default:
554 pDRIInfo->clientDriverName = VIAClientDriverName;
555 break;
556 }
557 pDRIInfo->busIdString = DRICreatePCIBusID(pVia->PciInfo);
558 pDRIInfo->ddxDriverMajorVersion = VIA_DRIDDX_VERSION_MAJOR;
559 pDRIInfo->ddxDriverMinorVersion = VIA_DRIDDX_VERSION_MINOR;
560 pDRIInfo->ddxDriverPatchVersion = VIA_DRIDDX_VERSION_PATCH;
561 #if (DRIINFO_MAJOR_VERSION == 5)
562 pDRIInfo->frameBufferPhysicalAddress = (pointer) pVia->FrameBufferBase;
563 #else
564 pDRIInfo->frameBufferPhysicalAddress = pVia->FrameBufferBase;
565 #endif
566 pDRIInfo->frameBufferSize = pVia->videoRambytes;
567
568 pDRIInfo->frameBufferStride = (pScrn->displayWidth *
569 pScrn->bitsPerPixel / 8);
570 pDRIInfo->ddxDrawableTableEntry = VIA_MAX_DRAWABLES;
571
572 if (SAREA_MAX_DRAWABLES < VIA_MAX_DRAWABLES)
573 pDRIInfo->maxDrawableTableEntry = SAREA_MAX_DRAWABLES;
574 else
575 pDRIInfo->maxDrawableTableEntry = VIA_MAX_DRAWABLES;
576
577 #ifdef NOT_DONE
578 /* FIXME: need to extend DRI protocol to pass this size back to client
579 * for SAREA mapping that includes a device private record. */
580 pDRIInfo->SAREASize = ((sizeof(XF86DRISAREARec) + 0xfff) & 0x1000); /* round to page */
581 /* + shared memory device private rec */
582 #else
583 /* For now the mapping works by using a fixed size defined
584 * in the SAREA header. */
585 if (sizeof(XF86DRISAREARec) + sizeof(drm_via_sarea_t) > SAREA_MAX) {
586 xf86DrvMsg(pScrn->scrnIndex, X_ERROR, "Data does not fit in SAREA\n");
587 DRIDestroyInfoRec(pVia->pDRIInfo);
588 pVia->pDRIInfo = NULL;
589 return FALSE;
590 }
591 pDRIInfo->SAREASize = SAREA_MAX;
592 #endif
593
594 if (!(pVIADRI = (VIADRIPtr) calloc(sizeof(VIADRIRec), 1))) {
595 DRIDestroyInfoRec(pVia->pDRIInfo);
596 pVia->pDRIInfo = NULL;
597 return FALSE;
598 }
599 pDRIInfo->devPrivate = pVIADRI;
600 pDRIInfo->devPrivateSize = sizeof(VIADRIRec);
601 pDRIInfo->contextSize = sizeof(VIADRIContextRec);
602
603 pDRIInfo->CreateContext = VIACreateContext;
604 pDRIInfo->DestroyContext = VIADestroyContext;
605 pDRIInfo->SwapContext = VIADRISwapContext;
606 pDRIInfo->InitBuffers = VIADRIInitBuffers;
607 pDRIInfo->MoveBuffers = VIADRIMoveBuffers;
608 pDRIInfo->bufferRequests = DRI_ALL_WINDOWS;
609
610 if (!DRIScreenInit(pScreen, pDRIInfo, &pVia->drmmode.fd)) {
611 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
612 "[dri] DRIScreenInit failed. Disabling DRI.\n");
613 free(pDRIInfo->devPrivate);
614 pDRIInfo->devPrivate = NULL;
615 DRIDestroyInfoRec(pVia->pDRIInfo);
616 pVia->pDRIInfo = NULL;
617 pVia->drmmode.fd = -1;
618 return FALSE;
619 }
620
621 if (!(VIAInitVisualConfigs(pScreen))) {
622 VIADRICloseScreen(pScreen);
623 return FALSE;
624 }
625 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] visual configs initialized.\n");
626
627 /* DRIScreenInit doesn't add all the common mappings.
628 * Add additional mappings here. */
629 if (!VIADRIMapInit(pScreen, pVia)) {
630 VIADRICloseScreen(pScreen);
631 return FALSE;
632 }
633 pVIADRI->regs.size = VIA_MMIO_REGSIZE;
634 pVIADRI->regs.handle = pVia->registerHandle;
635 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] mmio Registers = 0x%08lx\n",
636 (unsigned long)pVIADRI->regs.handle);
637
638 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] mmio mapped.\n");
639 return TRUE;
640 }
641
642 void
VIADRICloseScreen(ScreenPtr pScreen)643 VIADRICloseScreen(ScreenPtr pScreen)
644 {
645 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
646 VIAPtr pVia = VIAPTR(pScrn);
647 VIADRIPtr pVIADRI;
648
649 VIADRIRingBufferCleanup(pScrn);
650 if (pVia->agpSize) {
651 drmUnmap(pVia->agpMappedAddr, pVia->agpSize);
652 drmRmMap(pVia->drmmode.fd, pVia->agpHandle);
653 drmAgpUnbind(pVia->drmmode.fd, pVia->agpHandle);
654 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Freeing agp memory\n");
655 drmAgpFree(pVia->drmmode.fd, pVia->agpHandle);
656 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] Releasing agp module\n");
657 drmAgpRelease(pVia->drmmode.fd);
658 }
659
660 DRICloseScreen(pScreen);
661 drm_bo_free(pScrn, pVia->driOffScreenMem);
662
663 if (pVia->pDRIInfo) {
664 if ((pVIADRI = (VIADRIPtr) pVia->pDRIInfo->devPrivate)) {
665 VIADRIIrqExit(pScrn, pVIADRI);
666 free(pVIADRI);
667 pVia->pDRIInfo->devPrivate = NULL;
668 }
669 DRIDestroyInfoRec(pVia->pDRIInfo);
670 pVia->pDRIInfo = NULL;
671 }
672
673 if (pVia->pVisualConfigs) {
674 free(pVia->pVisualConfigs);
675 pVia->pVisualConfigs = NULL;
676 }
677 if (pVia->pVisualConfigsPriv) {
678 free(pVia->pVisualConfigsPriv);
679 pVia->pVisualConfigsPriv = NULL;
680 }
681 }
682
683 /* TODO: xserver receives driver's swapping event and does something
684 * according the data initialized in this function.
685 */
686 static Bool
VIACreateContext(ScreenPtr pScreen,VisualPtr visual,drm_context_t hwContext,void * pVisualConfigPriv,DRIContextType contextStore)687 VIACreateContext(ScreenPtr pScreen, VisualPtr visual,
688 drm_context_t hwContext, void *pVisualConfigPriv,
689 DRIContextType contextStore)
690 {
691 return TRUE;
692 }
693
694 static void
VIADestroyContext(ScreenPtr pScreen,drm_context_t hwContext,DRIContextType contextStore)695 VIADestroyContext(ScreenPtr pScreen, drm_context_t hwContext,
696 DRIContextType contextStore)
697 {
698 }
699
700 Bool
VIADRIFinishScreenInit(ScreenPtr pScreen)701 VIADRIFinishScreenInit(ScreenPtr pScreen)
702 {
703 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
704 VIAPtr pVia = VIAPTR(pScrn);
705 VIADRIPtr pVIADRI;
706
707 pVia->pDRIInfo->driverSwapMethod = DRI_HIDE_X_CONTEXT;
708 pVia->agpDMA = FALSE;
709
710 pVIADRI = (VIADRIPtr) pVia->pDRIInfo->devPrivate;
711 pVIADRI->drixinerama = FALSE;
712
713 if (pVia->driSize < pVia->Bpl) {
714 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
715 "[drm] No DRM framebuffer heap available.\n"
716 "[drm] Please increase the frame buffer\n"
717 "[drm] memory area in the BIOS. Disabling DRI.\n");
718 return FALSE;
719 }
720 if (pVia->driSize < 3 * (pScrn->virtualY * pVia->Bpl)) {
721 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
722 "[drm] The DRM heap and pixmap cache memory may be too\n"
723 "[drm] small for optimal performance. Please increase\n"
724 "[drm] the frame buffer memory area in the BIOS.\n");
725 }
726
727 pVia->driOffScreenMem = drm_bo_alloc(pScrn, pVia->driSize, 16, TTM_PL_FLAG_VRAM);
728
729 DRIFinishScreenInit(pScreen);
730
731 /* Set SAREA value. */
732 {
733 drm_via_sarea_t *saPriv;
734
735 saPriv = (drm_via_sarea_t *) DRIGetSAREAPrivate(pScreen);
736 assert(saPriv);
737 memset(saPriv, 0, sizeof(*saPriv));
738 saPriv->ctxOwner = -1;
739 }
740 pVIADRI->deviceID = pVia->Chipset;
741 pVIADRI->width = pScrn->virtualX;
742 pVIADRI->height = pScrn->virtualY;
743 pVIADRI->mem = pScrn->videoRam * 1024;
744 pVIADRI->bytesPerPixel = (pScrn->bitsPerPixel + 7) / 8;
745 pVIADRI->sarea_priv_offset = sizeof(XF86DRISAREARec);
746 /* TODO */
747 pVIADRI->scrnX = pVIADRI->width;
748 pVIADRI->scrnY = pVIADRI->height;
749
750 /* Initialize IRQ. */
751 if (pVia->DRIIrqEnable)
752 VIADRIIrqInit(pScrn, pVIADRI);
753
754 pVIADRI->ringBufActive = 0;
755 VIADRIRingBufferInit(pScrn);
756 pVia->agpDMA = pVia->dma2d && pVIADRI->ringBufActive;
757 return TRUE;
758 }
759
760 static void
VIADRISwapContext(ScreenPtr pScreen,DRISyncType syncType,DRIContextType oldContextType,void * oldContext,DRIContextType newContextType,void * newContext)761 VIADRISwapContext(ScreenPtr pScreen, DRISyncType syncType,
762 DRIContextType oldContextType, void *oldContext,
763 DRIContextType newContextType, void *newContext)
764 {
765 #if 0
766 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
767 VIAPtr pVia = VIAPTR(pScrn);
768 #endif
769 return;
770 }
771
772 static void
VIADRIInitBuffers(WindowPtr pWin,RegionPtr prgn,CARD32 index)773 VIADRIInitBuffers(WindowPtr pWin, RegionPtr prgn, CARD32 index)
774 {
775 #if 0
776 ScreenPtr pScreen = pWin->drawable.pScreen;
777 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
778 VIAPtr pVia = VIAPTR(pScrn);
779 #endif
780 return;
781 }
782
783 static void
VIADRIMoveBuffers(WindowPtr pParent,DDXPointRec ptOldOrg,RegionPtr prgnSrc,CARD32 index)784 VIADRIMoveBuffers(WindowPtr pParent, DDXPointRec ptOldOrg,
785 RegionPtr prgnSrc, CARD32 index)
786 {
787 #if 0
788 ScreenPtr pScreen = pParent->drawable.pScreen;
789 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
790 VIAPtr pVia = VIAPTR(pScrn);
791 #endif
792 return;
793 }
794
795 /* Initialize the kernel data structures. */
796 Bool
VIADRIKernelInit(ScrnInfoPtr pScrn)797 VIADRIKernelInit(ScrnInfoPtr pScrn)
798 {
799 VIAPtr pVia = VIAPTR(pScrn);
800 drm_via_init_t drmInfo;
801
802 pVia->IsPCI = !VIADRIAgpInit(pScrn);
803 if (pVia->IsPCI)
804 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Using PCI.\n");
805 else
806 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Using AGP.\n");
807
808 if (!(VIADRIFBInit(pScrn))) {
809 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
810 "[dri] Frame buffer initialization failed.\n");
811 return FALSE;
812 }
813 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Frame buffer initialized.\n");
814
815 memset(&drmInfo, 0, sizeof(drm_via_init_t));
816 drmInfo.func = VIA_INIT_MAP;
817 drmInfo.sarea_priv_offset = sizeof(XF86DRISAREARec);
818 drmInfo.fb_offset = pVia->frameBufferHandle;
819 drmInfo.mmio_offset = pVia->registerHandle;
820
821 if (pVia->IsPCI) {
822 drmInfo.agpAddr = 0;
823 } else {
824 /*For AMD64*/
825 #ifndef __x86_64__
826 drmInfo.agpAddr = (CARD32)pVia->agpAddr;
827 #else
828 drmInfo.agpAddr = (CARD64)pVia->agpAddr;
829 #endif
830 }
831
832 if ((drmCommandWrite(pVia->drmmode.fd, DRM_VIA_MAP_INIT, &drmInfo,
833 sizeof(drm_via_init_t))) < 0)
834 return FALSE;
835
836 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[dri] Kernel data initialized.\n");
837 return TRUE;
838 }
839
840 /* Add a map for the MMIO registers. */
841 static Bool
VIADRIMapInit(ScreenPtr pScreen,VIAPtr pVia)842 VIADRIMapInit(ScreenPtr pScreen, VIAPtr pVia)
843 {
844 ScrnInfoPtr pScrn = xf86ScreenToScrn(pScreen);
845 int flags = DRM_READ_ONLY;
846
847 if (drmAddMap(pVia->drmmode.fd, pVia->MmioBase, VIA_MMIO_REGSIZE,
848 DRM_REGISTERS, flags, &pVia->registerHandle) < 0) {
849 return FALSE;
850 }
851 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] register handle = 0x%08lx\n",
852 (unsigned long)pVia->registerHandle);
853 if (drmAddMap(pVia->drmmode.fd, pVia->FrameBufferBase, pVia->videoRambytes,
854 DRM_FRAME_BUFFER, 0, &pVia->frameBufferHandle) < 0) {
855 return FALSE;
856 }
857 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "[drm] framebuffer handle = 0x%08lx\n",
858 (unsigned long)pVia->frameBufferHandle);
859
860 return TRUE;
861 }
862
863 #define DRM_VIA_BLIT_MAX_SIZE (2048*2048*4)
864
865 static int
viaDRIFBMemcpy(int fd,struct buffer_object * vram,unsigned char * addr,Bool toFB)866 viaDRIFBMemcpy(int fd, struct buffer_object *vram, unsigned char *addr,
867 Bool toFB)
868 {
869 unsigned long fbOffset = vram->offset, size = vram->size, curSize;
870 drm_via_dmablit_t blit;
871 int err;
872
873 do {
874 curSize = (size > DRM_VIA_BLIT_MAX_SIZE) ? DRM_VIA_BLIT_MAX_SIZE : size;
875
876 blit.num_lines = 1;
877 blit.line_length = curSize;
878 blit.fb_addr = fbOffset;
879 blit.fb_stride = ALIGN_TO(curSize, 16);
880 blit.mem_addr = addr;
881 blit.mem_stride = blit.fb_stride;
882 blit.to_fb = (toFB) ? 1 : 0;
883
884 do {
885 err = drmCommandWriteRead(fd, DRM_VIA_DMA_BLIT,
886 &blit, sizeof(blit));
887 } while (-EAGAIN == err);
888 if (err)
889 return err;
890
891 do {
892 err = drmCommandWriteRead(fd, DRM_VIA_BLIT_SYNC,
893 &blit.sync, sizeof(blit.sync));
894 } while (-EAGAIN == err);
895 if (err)
896 return err;
897
898 fbOffset += curSize;
899 addr += curSize;
900 size -= curSize;
901
902 } while (size > 0);
903 return 0;
904 }
905
906 void
viaDRIOffscreenSave(ScrnInfoPtr pScrn)907 viaDRIOffscreenSave(ScrnInfoPtr pScrn)
908 {
909 VIAPtr pVia = VIAPTR(pScrn);
910 unsigned long srcSize = pVia->driOffScreenMem->size;
911 int err;
912
913 if (pVia->driOffScreenSave)
914 free(pVia->driOffScreenSave);
915
916 pVia->driOffScreenSave = malloc(srcSize + 16);
917 if (pVia->driOffScreenSave) {
918 void *dst, *src = drm_bo_map(pScrn, pVia->driOffScreenMem);
919
920 dst = (void *) ALIGN_TO((unsigned long) pVia->driOffScreenSave, 16);
921 if ((pVia->drmVerMajor == 2) && (pVia->drmVerMinor >= 8)) {
922 err = viaDRIFBMemcpy(pVia->drmmode.fd, pVia->driOffScreenMem, dst, FALSE);
923 if (!err)
924 return;
925
926 xf86DrvMsg(pScrn->scrnIndex, X_WARNING,
927 "Hardware backup of DRI offscreen memory failed: %s.\n"
928 "\tUsing slow software backup instead.\n",
929 strerror(-err));
930 }
931 memcpy(dst, src, srcSize);
932 drm_bo_unmap(pScrn, pVia->driOffScreenMem);
933 } else {
934 xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
935 "Out of memory trying to backup DRI offscreen memory.\n");
936 }
937 return;
938 }
939
940 void
viaDRIOffscreenRestore(ScrnInfoPtr pScrn)941 viaDRIOffscreenRestore(ScrnInfoPtr pScrn)
942 {
943 VIAPtr pVia = VIAPTR(pScrn);
944
945 if (pVia->driOffScreenSave) {
946 void *src, *dst = drm_bo_map(pScrn, pVia->driOffScreenMem);
947
948 src = pVia->driOffScreenSave;
949 memcpy(dst, src, pVia->driOffScreenMem->size);
950 free(pVia->driOffScreenSave);
951 pVia->driOffScreenSave = NULL;
952
953 drm_bo_unmap(pScrn, pVia->driOffScreenMem);
954 } else {
955 }
956 }
957