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