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