move pSAREAPriv declaration to be C-compliant
[mesa.git] / src / mesa / drivers / dri / r128 / server / r128_dri.c
1 /* $XFree86: xc/programs/Xserver/hw/xfree86/drivers/ati/r128_dri.c,v 1.28 2003/02/07 20:41:14 martin Exp $ */
2 /*
3 * Copyright 1999, 2000 ATI Technologies Inc., Markham, Ontario,
4 * Precision Insight, Inc., Cedar Park, Texas, and
5 * VA Linux Systems Inc., Fremont, California.
6 *
7 * All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining
10 * a copy of this software and associated documentation files (the
11 * "Software"), to deal in the Software without restriction, including
12 * without limitation on the rights to use, copy, modify, merge,
13 * publish, distribute, sublicense, and/or sell copies of the Software,
14 * and to permit persons to whom the Software is furnished to do so,
15 * subject to the following conditions:
16 *
17 * The above copyright notice and this permission notice (including the
18 * next paragraph) shall be included in all copies or substantial
19 * portions of the Software.
20 *
21 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 * NON-INFRINGEMENT. IN NO EVENT SHALL ATI, PRECISION INSIGHT, VA LINUX
25 * SYSTEMS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
26 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28 * OTHER DEALINGS IN THE SOFTWARE.
29 */
30
31 /*
32 * Authors:
33 * Kevin E. Martin <martin@valinux.com>
34 * Rickard E. Faith <faith@valinux.com>
35 * Daryll Strauss <daryll@valinux.com>
36 * Gareth Hughes <gareth@valinux.com>
37 *
38 */
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <errno.h>
44 #include <unistd.h>
45 // Fix this to use kernel pci_ids.h when all of these IDs make it into the kernel
46 #include "pci_ids.h"
47
48 #include "driver.h"
49 #include "drm.h"
50
51 #include "r128.h"
52 #include "r128_dri.h"
53 #include "r128_macros.h"
54 #include "r128_reg.h"
55 #include "r128_version.h"
56 #include "r128_drm.h"
57
58
59 /* ?? HACK - for now, put this here... */
60 /* ?? Alpha - this may need to be a variable to handle UP1x00 vs TITAN */
61 #if defined(__alpha__)
62 # define DRM_PAGE_SIZE 8192
63 #elif defined(__ia64__)
64 # define DRM_PAGE_SIZE getpagesize()
65 #else
66 # define DRM_PAGE_SIZE 4096
67 #endif
68
69 /**
70 * \brief Establish the set of modes available for the display.
71 *
72 * \param ctx display handle.
73 * \param numModes will receive the number of supported modes.
74 * \param modes will point to the list of supported modes.
75 *
76 * \return one on success, or zero on failure.
77 *
78 * Allocates a single visual and fills it with information according to the
79 * display bit depth. Supports only 16 and 32 bpp bit depths, aborting
80 * otherwise.
81 */
82 const __GLcontextModes __glModes[] = {
83
84 /* 32 bit, RGBA Depth=24 Stencil=8 */
85 {.rgbMode = GL_TRUE, .colorIndexMode = GL_FALSE, .doubleBufferMode = GL_TRUE, .stereoMode = GL_FALSE,
86 .haveAccumBuffer = GL_FALSE, .haveDepthBuffer = GL_TRUE, .haveStencilBuffer = GL_TRUE,
87 .redBits = 8, .greenBits = 8, .blueBits = 8, .alphaBits = 8,
88 .redMask = 0xff0000, .greenMask = 0xff00, .blueMask = 0xff, .alphaMask = 0xff000000,
89 .rgbBits = 32, .indexBits = 0,
90 .accumRedBits = 0, .accumGreenBits = 0, .accumBlueBits = 0, .accumAlphaBits = 0,
91 .depthBits = 24, .stencilBits = 8,
92 .numAuxBuffers= 0, .level = 0, .pixmapMode = GL_FALSE, },
93
94 /* 16 bit, RGB Depth=16 */
95 {.rgbMode = GL_TRUE, .colorIndexMode = GL_FALSE, .doubleBufferMode = GL_TRUE, .stereoMode = GL_FALSE,
96 .haveAccumBuffer = GL_FALSE, .haveDepthBuffer = GL_TRUE, .haveStencilBuffer = GL_FALSE,
97 .redBits = 5, .greenBits = 6, .blueBits = 5, .alphaBits = 0,
98 .redMask = 0xf800, .greenMask = 0x07e0, .blueMask = 0x001f, .alphaMask = 0x0,
99 .rgbBits = 16, .indexBits = 0,
100 .accumRedBits = 0, .accumGreenBits = 0, .accumBlueBits = 0, .accumAlphaBits = 0,
101 .depthBits = 16, .stencilBits = 0,
102 .numAuxBuffers= 0, .level = 0, .pixmapMode = GL_FALSE, },
103 };
104 static int R128InitContextModes( const DRIDriverContext *ctx,
105 int *numModes, const __GLcontextModes **modes)
106 {
107 *numModes = sizeof(__glModes)/sizeof(__GLcontextModes *);
108 *modes = &__glModes[0];
109 return 1;
110 }
111
112 /* Compute log base 2 of val. */
113 static int R128MinBits(int val)
114 {
115 int bits;
116
117 if (!val) return 1;
118 for (bits = 0; val; val >>= 1, ++bits);
119 return bits;
120 }
121
122 /* Initialize the AGP state. Request memory for use in AGP space, and
123 initialize the Rage 128 registers to point to that memory. */
124 static GLboolean R128DRIAgpInit(const DRIDriverContext *ctx)
125 {
126 unsigned char *R128MMIO = ctx->MMIOAddress;
127 R128InfoPtr info = ctx->driverPrivate;
128 unsigned long mode;
129 unsigned int vendor, device;
130 int ret;
131 unsigned long cntl, chunk;
132 int s, l;
133 int flags;
134 unsigned long agpBase;
135
136 if (drmAgpAcquire(ctx->drmFD) < 0) {
137 fprintf(stderr, "[agp] AGP not available\n");
138 return GL_FALSE;
139 }
140
141 /* Modify the mode if the default mode is
142 not appropriate for this particular
143 combination of graphics card and AGP
144 chipset. */
145
146 mode = drmAgpGetMode(ctx->drmFD); /* Default mode */
147 vendor = drmAgpVendorId(ctx->drmFD);
148 device = drmAgpDeviceId(ctx->drmFD);
149
150 mode &= ~R128_AGP_MODE_MASK;
151 switch (info->agpMode) {
152 case 4: mode |= R128_AGP_4X_MODE;
153 case 2: mode |= R128_AGP_2X_MODE;
154 case 1: default: mode |= R128_AGP_1X_MODE;
155 }
156
157 fprintf(stderr,
158 "[agp] Mode 0x%08lx [AGP 0x%04x/0x%04x; Card 0x%04x/0x%04x]\n",
159 mode, vendor, device,
160 0x1002,
161 info->Chipset);
162
163 if (drmAgpEnable(ctx->drmFD, mode) < 0) {
164 fprintf(stderr, "[agp] AGP not enabled\n");
165 drmAgpRelease(ctx->drmFD);
166 return GL_FALSE;
167 }
168
169 info->agpOffset = 0;
170
171 if ((ret = drmAgpAlloc(ctx->drmFD, info->agpSize*1024*1024, 0, NULL,
172 &info->agpMemHandle)) < 0) {
173 fprintf(stderr, "[agp] Out of memory (%d)\n", ret);
174 drmAgpRelease(ctx->drmFD);
175 return GL_FALSE;
176 }
177 fprintf(stderr,
178 "[agp] %d kB allocated with handle 0x%08x\n",
179 info->agpSize*1024, info->agpMemHandle);
180
181 if (drmAgpBind(ctx->drmFD, info->agpMemHandle, info->agpOffset) < 0) {
182 fprintf(stderr, "[agp] Could not bind\n");
183 drmAgpFree(ctx->drmFD, info->agpMemHandle);
184 drmAgpRelease(ctx->drmFD);
185 return GL_FALSE;
186 }
187
188 /* Initialize the CCE ring buffer data */
189 info->ringStart = info->agpOffset;
190 info->ringMapSize = info->ringSize*1024*1024 + DRM_PAGE_SIZE;
191 info->ringSizeLog2QW = R128MinBits(info->ringSize*1024*1024/8) - 1;
192
193 info->ringReadOffset = info->ringStart + info->ringMapSize;
194 info->ringReadMapSize = DRM_PAGE_SIZE;
195
196 /* Reserve space for vertex/indirect buffers */
197 info->bufStart = info->ringReadOffset + info->ringReadMapSize;
198 info->bufMapSize = info->bufSize*1024*1024;
199
200 /* Reserve the rest for AGP textures */
201 info->agpTexStart = info->bufStart + info->bufMapSize;
202 s = (info->agpSize*1024*1024 - info->agpTexStart);
203 l = R128MinBits((s-1) / R128_NR_TEX_REGIONS);
204 if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY;
205 info->agpTexMapSize = (s >> l) << l;
206 info->log2AGPTexGran = l;
207
208 if (info->CCESecure) flags = DRM_READ_ONLY;
209 else flags = 0;
210
211 if (drmAddMap(ctx->drmFD, info->ringStart, info->ringMapSize,
212 DRM_AGP, flags, &info->ringHandle) < 0) {
213 fprintf(stderr,
214 "[agp] Could not add ring mapping\n");
215 return GL_FALSE;
216 }
217 fprintf(stderr,
218 "[agp] ring handle = 0x%08lx\n", info->ringHandle);
219
220 if (drmMap(ctx->drmFD, info->ringHandle, info->ringMapSize,
221 (drmAddressPtr)&info->ring) < 0) {
222 fprintf(stderr, "[agp] Could not map ring\n");
223 return GL_FALSE;
224 }
225 fprintf(stderr,
226 "[agp] Ring mapped at 0x%08lx\n",
227 (unsigned long)info->ring);
228
229 if (drmAddMap(ctx->drmFD, info->ringReadOffset, info->ringReadMapSize,
230 DRM_AGP, flags, &info->ringReadPtrHandle) < 0) {
231 fprintf(stderr,
232 "[agp] Could not add ring read ptr mapping\n");
233 return GL_FALSE;
234 }
235 fprintf(stderr,
236 "[agp] ring read ptr handle = 0x%08lx\n",
237 info->ringReadPtrHandle);
238
239 if (drmMap(ctx->drmFD, info->ringReadPtrHandle, info->ringReadMapSize,
240 (drmAddressPtr)&info->ringReadPtr) < 0) {
241 fprintf(stderr,
242 "[agp] Could not map ring read ptr\n");
243 return GL_FALSE;
244 }
245 fprintf(stderr,
246 "[agp] Ring read ptr mapped at 0x%08lx\n",
247 (unsigned long)info->ringReadPtr);
248
249 if (drmAddMap(ctx->drmFD, info->bufStart, info->bufMapSize,
250 DRM_AGP, 0, &info->bufHandle) < 0) {
251 fprintf(stderr,
252 "[agp] Could not add vertex/indirect buffers mapping\n");
253 return GL_FALSE;
254 }
255 fprintf(stderr,
256 "[agp] vertex/indirect buffers handle = 0x%08lx\n",
257 info->bufHandle);
258
259 if (drmMap(ctx->drmFD, info->bufHandle, info->bufMapSize,
260 (drmAddressPtr)&info->buf) < 0) {
261 fprintf(stderr,
262 "[agp] Could not map vertex/indirect buffers\n");
263 return GL_FALSE;
264 }
265 fprintf(stderr,
266 "[agp] Vertex/indirect buffers mapped at 0x%08lx\n",
267 (unsigned long)info->buf);
268
269 if (drmAddMap(ctx->drmFD, info->agpTexStart, info->agpTexMapSize,
270 DRM_AGP, 0, &info->agpTexHandle) < 0) {
271 fprintf(stderr,
272 "[agp] Could not add AGP texture map mapping\n");
273 return GL_FALSE;
274 }
275 fprintf(stderr,
276 "[agp] AGP texture map handle = 0x%08lx\n",
277 info->agpTexHandle);
278
279 if (drmMap(ctx->drmFD, info->agpTexHandle, info->agpTexMapSize,
280 (drmAddressPtr)&info->agpTex) < 0) {
281 fprintf(stderr,
282 "[agp] Could not map AGP texture map\n");
283 return GL_FALSE;
284 }
285 fprintf(stderr,
286 "[agp] AGP Texture map mapped at 0x%08lx\n",
287 (unsigned long)info->agpTex);
288
289 /* Initialize Rage 128's AGP registers */
290 cntl = INREG(R128_AGP_CNTL);
291 cntl &= ~R128_AGP_APER_SIZE_MASK;
292 switch (info->agpSize) {
293 case 256: cntl |= R128_AGP_APER_SIZE_256MB; break;
294 case 128: cntl |= R128_AGP_APER_SIZE_128MB; break;
295 case 64: cntl |= R128_AGP_APER_SIZE_64MB; break;
296 case 32: cntl |= R128_AGP_APER_SIZE_32MB; break;
297 case 16: cntl |= R128_AGP_APER_SIZE_16MB; break;
298 case 8: cntl |= R128_AGP_APER_SIZE_8MB; break;
299 case 4: cntl |= R128_AGP_APER_SIZE_4MB; break;
300 default:
301 fprintf(stderr,
302 "[agp] Illegal aperture size %d kB\n",
303 info->agpSize*1024);
304 return GL_FALSE;
305 }
306 agpBase = drmAgpBase(ctx->drmFD);
307 OUTREG(R128_AGP_BASE, agpBase);
308 OUTREG(R128_AGP_CNTL, cntl);
309
310 /* Disable Rage 128's PCIGART registers */
311 chunk = INREG(R128_BM_CHUNK_0_VAL);
312 chunk &= ~(R128_BM_PTR_FORCE_TO_PCI |
313 R128_BM_PM4_RD_FORCE_TO_PCI |
314 R128_BM_GLOBAL_FORCE_TO_PCI);
315 OUTREG(R128_BM_CHUNK_0_VAL, chunk);
316
317 OUTREG(R128_PCI_GART_PAGE, 1); /* Ensure AGP GART is used (for now) */
318
319 return GL_TRUE;
320 }
321
322 static GLboolean R128DRIPciInit(const DRIDriverContext *ctx)
323 {
324 R128InfoPtr info = ctx->driverPrivate;
325 unsigned char *R128MMIO = ctx->MMIOAddress;
326 uint32_t chunk;
327 int ret;
328 int flags;
329
330 info->agpOffset = 0;
331
332 ret = drmScatterGatherAlloc(ctx->drmFD, info->agpSize*1024*1024,
333 &info->pciMemHandle);
334 if (ret < 0) {
335 fprintf(stderr, "[pci] Out of memory (%d)\n", ret);
336 return GL_FALSE;
337 }
338 fprintf(stderr,
339 "[pci] %d kB allocated with handle 0x%08x\n",
340 info->agpSize*1024, info->pciMemHandle);
341
342 /* Initialize the CCE ring buffer data */
343 info->ringStart = info->agpOffset;
344 info->ringMapSize = info->ringSize*1024*1024 + DRM_PAGE_SIZE;
345 info->ringSizeLog2QW = R128MinBits(info->ringSize*1024*1024/8) - 1;
346
347 info->ringReadOffset = info->ringStart + info->ringMapSize;
348 info->ringReadMapSize = DRM_PAGE_SIZE;
349
350 /* Reserve space for vertex/indirect buffers */
351 info->bufStart = info->ringReadOffset + info->ringReadMapSize;
352 info->bufMapSize = info->bufSize*1024*1024;
353
354 flags = DRM_READ_ONLY | DRM_LOCKED | DRM_KERNEL;
355
356 if (drmAddMap(ctx->drmFD, info->ringStart, info->ringMapSize,
357 DRM_SCATTER_GATHER, flags, &info->ringHandle) < 0) {
358 fprintf(stderr,
359 "[pci] Could not add ring mapping\n");
360 return GL_FALSE;
361 }
362 fprintf(stderr,
363 "[pci] ring handle = 0x%08lx\n", info->ringHandle);
364
365 if (drmMap(ctx->drmFD, info->ringHandle, info->ringMapSize,
366 (drmAddressPtr)&info->ring) < 0) {
367 fprintf(stderr, "[pci] Could not map ring\n");
368 return GL_FALSE;
369 }
370 fprintf(stderr,
371 "[pci] Ring mapped at 0x%08lx\n",
372 (unsigned long)info->ring);
373 fprintf(stderr,
374 "[pci] Ring contents 0x%08lx\n",
375 *(unsigned long *)info->ring);
376
377 if (drmAddMap(ctx->drmFD, info->ringReadOffset, info->ringReadMapSize,
378 DRM_SCATTER_GATHER, flags, &info->ringReadPtrHandle) < 0) {
379 fprintf(stderr,
380 "[pci] Could not add ring read ptr mapping\n");
381 return GL_FALSE;
382 }
383 fprintf(stderr,
384 "[pci] ring read ptr handle = 0x%08lx\n",
385 info->ringReadPtrHandle);
386
387 if (drmMap(ctx->drmFD, info->ringReadPtrHandle, info->ringReadMapSize,
388 (drmAddressPtr)&info->ringReadPtr) < 0) {
389 fprintf(stderr,
390 "[pci] Could not map ring read ptr\n");
391 return GL_FALSE;
392 }
393 fprintf(stderr,
394 "[pci] Ring read ptr mapped at 0x%08lx\n",
395 (unsigned long)info->ringReadPtr);
396 fprintf(stderr,
397 "[pci] Ring read ptr contents 0x%08lx\n",
398 *(unsigned long *)info->ringReadPtr);
399
400 if (drmAddMap(ctx->drmFD, info->bufStart, info->bufMapSize,
401 DRM_SCATTER_GATHER, 0, &info->bufHandle) < 0) {
402 fprintf(stderr,
403 "[pci] Could not add vertex/indirect buffers mapping\n");
404 return GL_FALSE;
405 }
406 fprintf(stderr,
407 "[pci] vertex/indirect buffers handle = 0x%08lx\n",
408 info->bufHandle);
409
410 if (drmMap(ctx->drmFD, info->bufHandle, info->bufMapSize,
411 (drmAddressPtr)&info->buf) < 0) {
412 fprintf(stderr,
413 "[pci] Could not map vertex/indirect buffers\n");
414 return GL_FALSE;
415 }
416 fprintf(stderr,
417 "[pci] Vertex/indirect buffers mapped at 0x%08lx\n",
418 (unsigned long)info->buf);
419 fprintf(stderr,
420 "[pci] Vertex/indirect buffers contents 0x%08lx\n",
421 *(unsigned long *)info->buf);
422
423 if (!info->IsPCI) {
424 /* This is really an AGP card, force PCI GART mode */
425 chunk = INREG(R128_BM_CHUNK_0_VAL);
426 chunk |= (R128_BM_PTR_FORCE_TO_PCI |
427 R128_BM_PM4_RD_FORCE_TO_PCI |
428 R128_BM_GLOBAL_FORCE_TO_PCI);
429 OUTREG(R128_BM_CHUNK_0_VAL, chunk);
430 OUTREG(R128_PCI_GART_PAGE, 0); /* Ensure PCI GART is used */
431 }
432
433 return GL_TRUE;
434 }
435
436 /* Add a map for the MMIO registers that will be accessed by any
437 DRI-based clients. */
438 static GLboolean R128DRIMapInit(const DRIDriverContext *ctx)
439 {
440 R128InfoPtr info = ctx->driverPrivate;
441 int flags;
442
443 if (info->CCESecure) flags = DRM_READ_ONLY;
444 else flags = 0;
445
446 /* Map registers */
447 if (drmAddMap(ctx->drmFD, ctx->MMIOStart, ctx->MMIOSize,
448 DRM_REGISTERS, flags, &info->registerHandle) < 0) {
449 return GL_FALSE;
450 }
451 fprintf(stderr,
452 "[drm] register handle = 0x%08lx\n", info->registerHandle);
453
454 return GL_TRUE;
455 }
456
457 /* Initialize the kernel data structures. */
458 static int R128DRIKernelInit(const DRIDriverContext *ctx)
459 {
460 R128InfoPtr info = ctx->driverPrivate;
461 drm_r128_init_t drmInfo;
462
463 memset( &drmInfo, 0, sizeof(&drmInfo) );
464
465 drmInfo.func = R128_INIT_CCE;
466 drmInfo.sarea_priv_offset = sizeof(drm_sarea_t);
467 drmInfo.is_pci = info->IsPCI;
468 drmInfo.cce_mode = info->CCEMode;
469 drmInfo.cce_secure = info->CCESecure;
470 drmInfo.ring_size = info->ringSize*1024*1024;
471 drmInfo.usec_timeout = info->CCEusecTimeout;
472
473 drmInfo.fb_bpp = ctx->bpp;
474 drmInfo.depth_bpp = ctx->bpp;
475
476 drmInfo.front_offset = info->frontOffset;
477 drmInfo.front_pitch = info->frontPitch;
478
479 drmInfo.back_offset = info->backOffset;
480 drmInfo.back_pitch = info->backPitch;
481
482 drmInfo.depth_offset = info->depthOffset;
483 drmInfo.depth_pitch = info->depthPitch;
484 drmInfo.span_offset = info->spanOffset;
485
486 drmInfo.fb_offset = info->LinearAddr;
487 drmInfo.mmio_offset = info->registerHandle;
488 drmInfo.ring_offset = info->ringHandle;
489 drmInfo.ring_rptr_offset = info->ringReadPtrHandle;
490 drmInfo.buffers_offset = info->bufHandle;
491 drmInfo.agp_textures_offset = info->agpTexHandle;
492
493 if (drmCommandWrite(ctx->drmFD, DRM_R128_INIT,
494 &drmInfo, sizeof(drmInfo)) < 0)
495 return GL_FALSE;
496
497 return GL_TRUE;
498 }
499
500 /* Add a map for the vertex buffers that will be accessed by any
501 DRI-based clients. */
502 static GLboolean R128DRIBufInit(const DRIDriverContext *ctx)
503 {
504 R128InfoPtr info = ctx->driverPrivate;
505 /* Initialize vertex buffers */
506 if (info->IsPCI) {
507 info->bufNumBufs = drmAddBufs(ctx->drmFD,
508 info->bufMapSize / R128_BUFFER_SIZE,
509 R128_BUFFER_SIZE,
510 DRM_SG_BUFFER,
511 info->bufStart);
512 } else {
513 info->bufNumBufs = drmAddBufs(ctx->drmFD,
514 info->bufMapSize / R128_BUFFER_SIZE,
515 R128_BUFFER_SIZE,
516 DRM_AGP_BUFFER,
517 info->bufStart);
518 }
519 if (info->bufNumBufs <= 0) {
520 fprintf(stderr,
521 "[drm] Could not create vertex/indirect buffers list\n");
522 return GL_FALSE;
523 }
524 fprintf(stderr,
525 "[drm] Added %d %d byte vertex/indirect buffers\n",
526 info->bufNumBufs, R128_BUFFER_SIZE);
527
528 if (!(info->buffers = drmMapBufs(ctx->drmFD))) {
529 fprintf(stderr,
530 "[drm] Failed to map vertex/indirect buffers list\n");
531 return GL_FALSE;
532 }
533 fprintf(stderr,
534 "[drm] Mapped %d vertex/indirect buffers\n",
535 info->buffers->count);
536
537 return GL_TRUE;
538 }
539
540 static void R128DRIIrqInit(const DRIDriverContext *ctx)
541 {
542 R128InfoPtr info = ctx->driverPrivate;
543 unsigned char *R128MMIO = ctx->MMIOAddress;
544
545 if (!info->irq) {
546 info->irq = drmGetInterruptFromBusID(
547 ctx->drmFD,
548 ctx->pciBus,
549 ctx->pciDevice,
550 ctx->pciFunc);
551
552 if((drmCtlInstHandler(ctx->drmFD, info->irq)) != 0) {
553 fprintf(stderr,
554 "[drm] failure adding irq handler, "
555 "there is a device already using that irq\n"
556 "[drm] falling back to irq-free operation\n");
557 info->irq = 0;
558 } else {
559 info->gen_int_cntl = INREG( R128_GEN_INT_CNTL );
560 }
561 }
562
563 if (info->irq)
564 fprintf(stderr,
565 "[drm] dma control initialized, using IRQ %d\n",
566 info->irq);
567 }
568
569 static int R128CCEStop(const DRIDriverContext *ctx)
570 {
571 R128InfoPtr info = ctx->driverPrivate;
572 drm_r128_cce_stop_t stop;
573 int ret, i;
574
575 stop.flush = 1;
576 stop.idle = 1;
577
578 ret = drmCommandWrite( ctx->drmFD, DRM_R128_CCE_STOP,
579 &stop, sizeof(stop) );
580
581 if ( ret == 0 ) {
582 return 0;
583 } else if ( errno != EBUSY ) {
584 return -errno;
585 }
586
587 stop.flush = 0;
588
589 i = 0;
590 do {
591 ret = drmCommandWrite( ctx->drmFD, DRM_R128_CCE_STOP,
592 &stop, sizeof(stop) );
593 } while ( ret && errno == EBUSY && i++ < R128_IDLE_RETRY );
594
595 if ( ret == 0 ) {
596 return 0;
597 } else if ( errno != EBUSY ) {
598 return -errno;
599 }
600
601 stop.idle = 0;
602
603 if ( drmCommandWrite( ctx->drmFD, DRM_R128_CCE_STOP,
604 &stop, sizeof(stop) )) {
605 return -errno;
606 } else {
607 return 0;
608 }
609 }
610
611 /* Initialize the CCE state, and start the CCE (if used by the X server) */
612 static void R128DRICCEInit(const DRIDriverContext *ctx)
613 {
614 R128InfoPtr info = ctx->driverPrivate;
615
616 /* Turn on bus mastering */
617 info->BusCntl &= ~R128_BUS_MASTER_DIS;
618
619 /* CCEMode is initialized in r128_driver.c */
620 switch (info->CCEMode) {
621 case R128_PM4_NONPM4: info->CCEFifoSize = 0; break;
622 case R128_PM4_192PIO: info->CCEFifoSize = 192; break;
623 case R128_PM4_192BM: info->CCEFifoSize = 192; break;
624 case R128_PM4_128PIO_64INDBM: info->CCEFifoSize = 128; break;
625 case R128_PM4_128BM_64INDBM: info->CCEFifoSize = 128; break;
626 case R128_PM4_64PIO_128INDBM: info->CCEFifoSize = 64; break;
627 case R128_PM4_64BM_128INDBM: info->CCEFifoSize = 64; break;
628 case R128_PM4_64PIO_64VCBM_64INDBM: info->CCEFifoSize = 64; break;
629 case R128_PM4_64BM_64VCBM_64INDBM: info->CCEFifoSize = 64; break;
630 case R128_PM4_64PIO_64VCPIO_64INDPIO: info->CCEFifoSize = 64; break;
631 }
632
633 /* Make sure the CCE is on for the X server */
634 R128CCE_START(ctx, info);
635 }
636
637
638 static int R128MemoryInit(const DRIDriverContext *ctx)
639 {
640 R128InfoPtr info = ctx->driverPrivate;
641 int width_bytes = ctx->shared.virtualWidth * ctx->cpp;
642 int cpp = ctx->cpp;
643 int bufferSize = ((ctx->shared.virtualHeight * width_bytes
644 + R128_BUFFER_ALIGN)
645 & ~R128_BUFFER_ALIGN);
646 int depthSize = ((((ctx->shared.virtualHeight+15) & ~15) * width_bytes
647 + R128_BUFFER_ALIGN)
648 & ~R128_BUFFER_ALIGN);
649 int l;
650
651 info->frontOffset = 0;
652 info->frontPitch = ctx->shared.virtualWidth;
653
654 fprintf(stderr,
655 "Using %d MB AGP aperture\n", info->agpSize);
656 fprintf(stderr,
657 "Using %d MB for the ring buffer\n", info->ringSize);
658 fprintf(stderr,
659 "Using %d MB for vertex/indirect buffers\n", info->bufSize);
660 fprintf(stderr,
661 "Using %d MB for AGP textures\n", info->agpTexSize);
662
663 /* Front, back and depth buffers - everything else texture??
664 */
665 info->textureSize = ctx->shared.fbSize - 2 * bufferSize - depthSize;
666
667 if (info->textureSize < 0)
668 return 0;
669
670 l = R128MinBits((info->textureSize-1) / R128_NR_TEX_REGIONS);
671 if (l < R128_LOG_TEX_GRANULARITY) l = R128_LOG_TEX_GRANULARITY;
672
673 /* Round the texture size up to the nearest whole number of
674 * texture regions. Again, be greedy about this, don't
675 * round down.
676 */
677 info->log2TexGran = l;
678 info->textureSize = (info->textureSize >> l) << l;
679
680 /* Set a minimum usable local texture heap size. This will fit
681 * two 256x256x32bpp textures.
682 */
683 if (info->textureSize < 512 * 1024) {
684 info->textureOffset = 0;
685 info->textureSize = 0;
686 }
687
688 /* Reserve space for textures */
689 info->textureOffset = ((ctx->shared.fbSize - info->textureSize +
690 R128_BUFFER_ALIGN) &
691 ~R128_BUFFER_ALIGN);
692
693 /* Reserve space for the shared depth
694 * buffer.
695 */
696 info->depthOffset = ((info->textureOffset - depthSize +
697 R128_BUFFER_ALIGN) &
698 ~R128_BUFFER_ALIGN);
699 info->depthPitch = ctx->shared.virtualWidth;
700
701 info->backOffset = ((info->depthOffset - bufferSize +
702 R128_BUFFER_ALIGN) &
703 ~R128_BUFFER_ALIGN);
704 info->backPitch = ctx->shared.virtualWidth;
705
706
707 fprintf(stderr,
708 "Will use back buffer at offset 0x%x\n",
709 info->backOffset);
710 fprintf(stderr,
711 "Will use depth buffer at offset 0x%x\n",
712 info->depthOffset);
713 fprintf(stderr,
714 "Will use %d kb for textures at offset 0x%x\n",
715 info->textureSize/1024, info->textureOffset);
716
717 return 1;
718 }
719
720
721 /* Initialize the screen-specific data structures for the DRI and the
722 Rage 128. This is the main entry point to the device-specific
723 initialization code. It calls device-independent DRI functions to
724 create the DRI data structures and initialize the DRI state. */
725 static GLboolean R128DRIScreenInit(DRIDriverContext *ctx)
726 {
727 R128InfoPtr info = ctx->driverPrivate;
728 R128DRIPtr pR128DRI;
729 int err, major, minor, patch;
730 drmVersionPtr version;
731 drm_r128_sarea_t *pSAREAPriv;
732
733 switch (ctx->bpp) {
734 case 8:
735 /* These modes are not supported (yet). */
736 case 15:
737 case 24:
738 fprintf(stderr,
739 "[dri] R128DRIScreenInit failed (depth %d not supported). "
740 "[dri] Disabling DRI.\n", ctx->bpp);
741 return GL_FALSE;
742
743 /* Only 16 and 32 color depths are supports currently. */
744 case 16:
745 case 32:
746 break;
747 }
748
749 info->registerSize = ctx->MMIOSize;
750 ctx->shared.SAREASize = DRM_PAGE_SIZE;
751
752 /* Note that drmOpen will try to load the kernel module, if needed. */
753 ctx->drmFD = drmOpen("r128", NULL );
754 if (ctx->drmFD < 0) {
755 fprintf(stderr, "[drm] drmOpen failed\n");
756 return 0;
757 }
758
759 /* Check the r128 DRM version */
760 version = drmGetVersion(ctx->drmFD);
761 if (version) {
762 if (version->version_major != 2 ||
763 version->version_minor < 2) {
764 /* incompatible drm version */
765 fprintf(stderr,
766 "[dri] R128DRIScreenInit failed because of a version mismatch.\n"
767 "[dri] r128.o kernel module version is %d.%d.%d but version 2.2 or greater is needed.\n"
768 "[dri] Disabling the DRI.\n",
769 version->version_major,
770 version->version_minor,
771 version->version_patchlevel);
772 drmFreeVersion(version);
773 return GL_FALSE;
774 }
775 info->drmMinor = version->version_minor;
776 drmFreeVersion(version);
777 }
778
779 if ((err = drmSetBusid(ctx->drmFD, ctx->pciBusID)) < 0) {
780 fprintf(stderr, "[drm] drmSetBusid failed (%d, %s), %s\n",
781 ctx->drmFD, ctx->pciBusID, strerror(-err));
782 return 0;
783 }
784
785 if (drmAddMap( ctx->drmFD,
786 0,
787 ctx->shared.SAREASize,
788 DRM_SHM,
789 DRM_CONTAINS_LOCK,
790 &ctx->shared.hSAREA) < 0)
791 {
792 fprintf(stderr, "[drm] drmAddMap failed\n");
793 return 0;
794 }
795 fprintf(stderr, "[drm] added %d byte SAREA at 0x%08lx\n",
796 ctx->shared.SAREASize, ctx->shared.hSAREA);
797
798 if (drmMap( ctx->drmFD,
799 ctx->shared.hSAREA,
800 ctx->shared.SAREASize,
801 (drmAddressPtr)(&ctx->pSAREA)) < 0)
802 {
803 fprintf(stderr, "[drm] drmMap failed\n");
804 return 0;
805 }
806 memset(ctx->pSAREA, 0, ctx->shared.SAREASize);
807 fprintf(stderr, "[drm] mapped SAREA 0x%08lx to %p, size %d\n",
808 ctx->shared.hSAREA, ctx->pSAREA, ctx->shared.SAREASize);
809
810 /* Need to AddMap the framebuffer and mmio regions here:
811 */
812 if (drmAddMap( ctx->drmFD,
813 (drmHandle)ctx->FBStart,
814 ctx->FBSize,
815 DRM_FRAME_BUFFER,
816 0,
817 &ctx->shared.hFrameBuffer) < 0)
818 {
819 fprintf(stderr, "[drm] drmAddMap framebuffer failed\n");
820 return 0;
821 }
822
823 fprintf(stderr, "[drm] framebuffer handle = 0x%08lx\n",
824 ctx->shared.hFrameBuffer);
825
826 if (!R128MemoryInit(ctx))
827 return GL_FALSE;
828
829 /* Initialize AGP */
830 if (!info->IsPCI && !R128DRIAgpInit(ctx)) {
831 info->IsPCI = GL_TRUE;
832 fprintf(stderr,
833 "[agp] AGP failed to initialize -- falling back to PCI mode.\n");
834 fprintf(stderr,
835 "[agp] Make sure you have the agpgart kernel module loaded.\n");
836 }
837
838 /* Initialize PCIGART */
839 if (info->IsPCI && !R128DRIPciInit(ctx)) {
840 return GL_FALSE;
841 }
842
843 /* DRIScreenInit doesn't add all the
844 common mappings. Add additional
845 mappings here. */
846 if (!R128DRIMapInit(ctx)) {
847 return GL_FALSE;
848 }
849
850 /* Create a 'server' context so we can grab the lock for
851 * initialization ioctls.
852 */
853 if ((err = drmCreateContext(ctx->drmFD, &ctx->serverContext)) != 0) {
854 fprintf(stderr, "%s: drmCreateContext failed %d\n", __FUNCTION__, err);
855 return 0;
856 }
857
858 DRM_LOCK(ctx->drmFD, ctx->pSAREA, ctx->serverContext, 0);
859
860 /* Initialize the kernel data structures */
861 if (!R128DRIKernelInit(ctx)) {
862 return GL_FALSE;
863 }
864
865 /* Initialize the vertex buffers list */
866 if (!R128DRIBufInit(ctx)) {
867 return GL_FALSE;
868 }
869
870 /* Initialize IRQ */
871 R128DRIIrqInit(ctx);
872
873 /* Initialize and start the CCE if required */
874 R128DRICCEInit(ctx);
875
876 /* Quick hack to clear the front & back buffers. Could also use
877 * the clear ioctl to do this, but would need to setup hw state
878 * first.
879 */
880 memset((char *)ctx->FBAddress + info->frontOffset,
881 0,
882 info->frontPitch * ctx->cpp * ctx->shared.virtualHeight );
883
884 memset((char *)ctx->FBAddress + info->backOffset,
885 0,
886 info->backPitch * ctx->cpp * ctx->shared.virtualHeight );
887
888 pSAREAPriv = (drm_r128_sarea_t *)(((char*)ctx->pSAREA) +
889 sizeof(drm_sarea_t));
890 memset(pSAREAPriv, 0, sizeof(*pSAREAPriv));
891
892 /* This is the struct passed to radeon_dri.so for its initialization */
893 ctx->driverClientMsg = malloc(sizeof(R128DRIRec));
894 ctx->driverClientMsgSize = sizeof(R128DRIRec);
895
896 pR128DRI = (R128DRIPtr)ctx->driverClientMsg;
897 pR128DRI->deviceID = info->Chipset;
898 pR128DRI->width = ctx->shared.virtualWidth;
899 pR128DRI->height = ctx->shared.virtualHeight;
900 pR128DRI->depth = ctx->bpp;
901 pR128DRI->bpp = ctx->bpp;
902
903 pR128DRI->IsPCI = info->IsPCI;
904 pR128DRI->AGPMode = info->agpMode;
905
906 pR128DRI->frontOffset = info->frontOffset;
907 pR128DRI->frontPitch = info->frontPitch;
908 pR128DRI->backOffset = info->backOffset;
909 pR128DRI->backPitch = info->backPitch;
910 pR128DRI->depthOffset = info->depthOffset;
911 pR128DRI->depthPitch = info->depthPitch;
912 pR128DRI->spanOffset = info->spanOffset;
913 pR128DRI->textureOffset = info->textureOffset;
914 pR128DRI->textureSize = info->textureSize;
915 pR128DRI->log2TexGran = info->log2TexGran;
916
917 pR128DRI->registerHandle = info->registerHandle;
918 pR128DRI->registerSize = info->registerSize;
919
920 pR128DRI->agpTexHandle = info->agpTexHandle;
921 pR128DRI->agpTexMapSize = info->agpTexMapSize;
922 pR128DRI->log2AGPTexGran = info->log2AGPTexGran;
923 pR128DRI->agpTexOffset = info->agpTexStart;
924 pR128DRI->sarea_priv_offset = sizeof(drm_sarea_t);
925
926 return GL_TRUE;
927 }
928
929 /* The screen is being closed, so clean up any state and free any
930 resources used by the DRI. */
931 void R128DRICloseScreen(const DRIDriverContext *ctx)
932 {
933 R128InfoPtr info = ctx->driverPrivate;
934 drm_r128_init_t drmInfo;
935
936 /* Stop the CCE if it is still in use */
937 R128CCE_STOP(ctx, info);
938
939 if (info->irq) {
940 drmCtlUninstHandler(ctx->drmFD);
941 info->irq = 0;
942 }
943
944 /* De-allocate vertex buffers */
945 if (info->buffers) {
946 drmUnmapBufs(info->buffers);
947 info->buffers = NULL;
948 }
949
950 /* De-allocate all kernel resources */
951 memset(&drmInfo, 0, sizeof(drmInfo));
952 drmInfo.func = R128_CLEANUP_CCE;
953 drmCommandWrite(ctx->drmFD, DRM_R128_INIT,
954 &drmInfo, sizeof(drmInfo));
955
956 /* De-allocate all AGP resources */
957 if (info->agpTex) {
958 drmUnmap(info->agpTex, info->agpTexMapSize);
959 info->agpTex = NULL;
960 }
961 if (info->buf) {
962 drmUnmap(info->buf, info->bufMapSize);
963 info->buf = NULL;
964 }
965 if (info->ringReadPtr) {
966 drmUnmap(info->ringReadPtr, info->ringReadMapSize);
967 info->ringReadPtr = NULL;
968 }
969 if (info->ring) {
970 drmUnmap(info->ring, info->ringMapSize);
971 info->ring = NULL;
972 }
973 if (info->agpMemHandle != DRM_AGP_NO_HANDLE) {
974 drmAgpUnbind(ctx->drmFD, info->agpMemHandle);
975 drmAgpFree(ctx->drmFD, info->agpMemHandle);
976 info->agpMemHandle = 0;
977 drmAgpRelease(ctx->drmFD);
978 }
979 if (info->pciMemHandle) {
980 drmScatterGatherFree(ctx->drmFD, info->pciMemHandle);
981 info->pciMemHandle = 0;
982 }
983 }
984
985 static GLboolean R128PreInitDRI(const DRIDriverContext *ctx)
986 {
987 R128InfoPtr info = ctx->driverPrivate;
988
989 /*info->CCEMode = R128_DEFAULT_CCE_PIO_MODE;*/
990 info->CCEMode = R128_DEFAULT_CCE_BM_MODE;
991 info->CCESecure = GL_TRUE;
992
993 info->agpMode = R128_DEFAULT_AGP_MODE;
994 info->agpSize = R128_DEFAULT_AGP_SIZE;
995 info->ringSize = R128_DEFAULT_RING_SIZE;
996 info->bufSize = R128_DEFAULT_BUFFER_SIZE;
997 info->agpTexSize = R128_DEFAULT_AGP_TEX_SIZE;
998
999 info->CCEusecTimeout = R128_DEFAULT_CCE_TIMEOUT;
1000
1001 return GL_TRUE;
1002 }
1003
1004 /**
1005 * \brief Initialize the framebuffer device mode
1006 *
1007 * \param ctx display handle.
1008 *
1009 * \return one on success, or zero on failure.
1010 *
1011 * Fills in \p info with some default values and some information from \p ctx
1012 * and then calls R128ScreenInit() for the screen initialization.
1013 *
1014 * Before exiting clears the framebuffer memory accessing it directly.
1015 */
1016 static int R128InitFBDev( DRIDriverContext *ctx )
1017 {
1018 R128InfoPtr info = calloc(1, sizeof(*info));
1019
1020 {
1021 int dummy = ctx->shared.virtualWidth;
1022
1023 switch (ctx->bpp / 8) {
1024 case 1: dummy = (ctx->shared.virtualWidth + 127) & ~127; break;
1025 case 2: dummy = (ctx->shared.virtualWidth + 31) & ~31; break;
1026 case 3:
1027 case 4: dummy = (ctx->shared.virtualWidth + 15) & ~15; break;
1028 }
1029
1030 ctx->shared.virtualWidth = dummy;
1031 }
1032
1033 ctx->driverPrivate = (void *)info;
1034
1035 info->Chipset = ctx->chipset;
1036
1037 switch (info->Chipset) {
1038 case PCI_DEVICE_ID_ATI_RAGE128_LE:
1039 case PCI_DEVICE_ID_ATI_RAGE128_RE:
1040 case PCI_DEVICE_ID_ATI_RAGE128_RK:
1041 case PCI_DEVICE_ID_ATI_RAGE128_PD:
1042 case PCI_DEVICE_ID_ATI_RAGE128_PP:
1043 case PCI_DEVICE_ID_ATI_RAGE128_PR:
1044 /* This is a PCI card */
1045 info->IsPCI = GL_TRUE;
1046 break;
1047 default:
1048 /* This is an AGP card */
1049 info->IsPCI = GL_FALSE;
1050 break;
1051 }
1052
1053 info->frontPitch = ctx->shared.virtualWidth;
1054 info->LinearAddr = ctx->FBStart & 0xfc000000;
1055
1056 if (!R128PreInitDRI(ctx))
1057 return 0;
1058
1059 if (!R128DRIScreenInit(ctx))
1060 return 0;
1061
1062 return 1;
1063 }
1064
1065
1066 /**
1067 * \brief The screen is being closed, so clean up any state and free any
1068 * resources used by the DRI.
1069 *
1070 * \param ctx display handle.
1071 *
1072 * Unmaps the SAREA, closes the DRM device file descriptor and frees the driver
1073 * private data.
1074 */
1075 static void R128HaltFBDev( DRIDriverContext *ctx )
1076 {
1077 drmUnmap( ctx->pSAREA, ctx->shared.SAREASize );
1078 drmClose(ctx->drmFD);
1079
1080 if (ctx->driverPrivate) {
1081 free(ctx->driverPrivate);
1082 ctx->driverPrivate = 0;
1083 }
1084 }
1085
1086
1087 /**
1088 * \brief Validate the fbdev mode.
1089 *
1090 * \param ctx display handle.
1091 *
1092 * \return one on success, or zero on failure.
1093 *
1094 * Saves some registers and returns 1.
1095 *
1096 * \sa R128PostValidateMode().
1097 */
1098 static int R128ValidateMode( const DRIDriverContext *ctx )
1099 {
1100 return 1;
1101 }
1102
1103
1104 /**
1105 * \brief Examine mode returned by fbdev.
1106 *
1107 * \param ctx display handle.
1108 *
1109 * \return one on success, or zero on failure.
1110 *
1111 * Restores registers that fbdev has clobbered and returns 1.
1112 *
1113 * \sa R128ValidateMode().
1114 */
1115 static int R128PostValidateMode( const DRIDriverContext *ctx )
1116 {
1117 return 1;
1118 }
1119
1120
1121 /**
1122 * \brief Shutdown the drawing engine.
1123 *
1124 * \param ctx display handle
1125 *
1126 * Turns off the command processor engine & restores the graphics card
1127 * to a state that fbdev understands.
1128 */
1129 static int R128EngineShutdown( const DRIDriverContext *ctx )
1130 {
1131 return 1;
1132 }
1133
1134 /**
1135 * \brief Restore the drawing engine.
1136 *
1137 * \param ctx display handle
1138 *
1139 * Resets the graphics card and sets initial values for several registers of
1140 * the card's drawing engine.
1141 *
1142 * Turns on the R128 command processor engine (i.e., the ringbuffer).
1143 */
1144 static int R128EngineRestore( const DRIDriverContext *ctx )
1145 {
1146 return 1;
1147 }
1148
1149
1150 /**
1151 * \brief Exported driver interface for Mini GLX.
1152 *
1153 * \sa DRIDriverRec.
1154 */
1155 const struct DRIDriverRec __driDriver = {
1156 R128InitContextModes,
1157 R128ValidateMode,
1158 R128PostValidateMode,
1159 R128InitFBDev,
1160 R128HaltFBDev,
1161 R128EngineShutdown,
1162 R128EngineRestore,
1163 0,
1164 };