open-src/app/gfx-utils/sun-src/vts/efb/tools.c
changeset 1117 629ac4b133bc
child 1368 475ce9398539
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/open-src/app/gfx-utils/sun-src/vts/efb/tools.c	Mon Apr 25 14:22:03 2011 -0700
@@ -0,0 +1,339 @@
+
+/*
+ * Copyright (c) 2006, 2009, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <sys/mman.h>
+
+#include "gfx_common.h"		/* GFX Common definitions */
+#include "graphicstest.h"
+#include "libvtsSUNWefb.h"	/* Common VTS library definitions */
+
+#include "X11/Xlib.h"
+#include "gfx_vts.h"		/* VTS Graphics Test common routines */
+#include "efb.h"
+
+
+int
+efb_get_pci_info(int fd, struct pci_info *pciInfo)
+{
+	struct gfx_pci_cfg pciCfg;
+	int i;
+	unsigned int bar;
+
+	if (ioctl(fd, GFX_IOCTL_GET_PCI_CONFIG, &pciCfg) == -1) {
+		return -1;
+	}
+
+        pciInfo->deviceID = pciCfg.DeviceID;
+
+	for (i = 0; i < 6; i++) {
+	    bar = pciCfg.bar[i];
+	    if (bar != 0) {
+		if (bar & PCI_MAP_IO) {
+		    pciInfo->ioBase[i] = PCIGETIO(bar);
+		    pciInfo->type[i] = bar & PCI_MAP_IO_ATTR_MASK;
+		} else {
+		    pciInfo->type[i] = bar & PCI_MAP_MEMORY_ATTR_MASK;
+		    pciInfo->memBase[i] = PCIGETMEMORY(bar);
+		    if (PCI_MAP_IS64BITMEM(bar)) {
+			if (i == 5) {
+			    pciInfo->memBase[i] = 0;
+			} else {
+			    int bar_hi = pciCfg.bar[i+1];
+			    pciInfo->memBase[i] |= (bar_hi << 32);
+			    ++i;
+			}
+		    }
+		    pciInfo->size[i] = EFB_REG_SIZE_LOG2;
+		}
+	    }
+	}
+
+	return 0;
+}
+
+int
+efb_get_mem_info(struct pci_info *pci_info, struct efb_info *pEFB) 
+{
+	unsigned char reg;
+
+	pEFB->FBPhysAddr = pci_info->memBase[0] & 0xfff00000;
+	pEFB->FBMapSize = 0;
+
+	pEFB->MMIOPhysAddr = pci_info->memBase[2] & 0xffff0000;
+	pEFB->MMIOMapSize =  1 << pci_info->size[2];
+
+	pEFB->RelocateIO = pci_info->ioBase[1];
+
+	pEFB->ChipSet = pci_info->deviceID;
+
+#ifdef DEBUG
+	printf("FBPhysAddr=0x%x FBMapSize=0x%x\n", pEFB->FBPhysAddr, pEFB->FBMapSize);
+	printf("MMIOPhysAddr=0x%x MMIOMapSize=0x%x\n", pEFB->MMIOPhysAddr, pEFB->MMIOMapSize);
+	printf("RelocateIO=0x%x\n", pEFB->RelocateIO);
+#endif
+
+	return 0;
+}
+
+
+int
+efb_init_info(struct efb_info *pEFB)
+{
+	unsigned int v, v2;
+	unsigned int status = 0;
+
+        
+#if 0
+	/* 
+	 * first check if the hardware is already initialized.
+	 * If not, abort
+	 */
+	ioctl(pEFB->fd, EFB_GET_STATUS_FLAGS, &status);
+	if (!(status & EFB_STATUS_HW_INITIALIZED))
+		return -1;
+#endif
+
+
+        v = REGR(CRTC_GEN_CNTL);
+	v2 = (v & CRTC_GEN_CNTL__CRTC_PIX_WIDTH_MASK) >> CRTC_GEN_CNTL__CRTC_PIX_WIDTH__SHIFT;
+	if (v2 <= 2)
+        	pEFB->bitsPerPixel = 8;
+	else if (v2 <= 4)
+		pEFB->bitsPerPixel = 16;
+	else 
+		pEFB->bitsPerPixel = 32;
+
+
+        v = REGR(CRTC_H_TOTAL_DISP);
+	v2 = (v & CRTC_H_TOTAL_DISP__CRTC_H_DISP_MASK) >> CRTC_H_TOTAL_DISP__CRTC_H_DISP__SHIFT;
+	pEFB->screenWidth = (v2 + 1) * 8;
+
+        v = REGR(CRTC_V_TOTAL_DISP);
+	v2 = (v & CRTC_V_TOTAL_DISP__CRTC_V_DISP_MASK) >> CRTC_V_TOTAL_DISP__CRTC_V_DISP__SHIFT;
+	pEFB->screenHeight = (v2 + 1);
+	pEFB->screenPitch = pEFB->screenWidth * pEFB->bitsPerPixel / 8;
+
+
+	pEFB->fbLocation = REGR(RADEON_MC_FB_LOCATION);
+
+#ifdef DEBUG
+	printf("bpp=%d width=%d height=%d pitch=%d fbLoc=0x%x\n", 
+		pEFB->bitsPerPixel, pEFB->screenWidth, pEFB->screenHeight, pEFB->screenPitch, 
+		pEFB->fbLocation);
+#endif
+	return 0;
+}
+
+int
+efb_map_mem(struct efb_info *pEFB, return_packet *rp, int test)
+{
+        struct pci_info  pci_info;
+        int              pageSize, size;
+	int		 fd = pEFB->fd;
+
+        if (efb_get_pci_info(fd, &pci_info) == -1) {
+            TraceMessage(VTS_DEBUG, __func__, "get pci info failed\n");
+            gfx_vts_set_message(rp, 1, test, "get pci info failed");
+            return -1;
+        }
+
+
+        if (efb_get_mem_info(&pci_info, pEFB) == -1) {
+            TraceMessage(VTS_DEBUG, __func__, "get mem info failed\n");
+            gfx_vts_set_message(rp, 1, test, "get mem info failed");
+            return -1;
+        }
+
+        /*
+         * Map MMIO
+         */
+        pageSize = getpagesize();
+        size = pEFB->MMIOMapSize + (pageSize - 1) & (~(pageSize - 1));
+
+        pEFB->MMIOvaddr = (unsigned char *)mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED,
+                                        fd, pEFB->MMIOPhysAddr);
+
+        if (pEFB->MMIOvaddr == MAP_FAILED) {
+            TraceMessage(VTS_DEBUG, __func__, "map MMIO failed\n");
+            gfx_vts_set_message(rp, 1, test, "map MMIO failed");
+            return -1;
+        }
+
+
+
+	switch (pEFB->ChipSet) {
+	case 20825:
+	case 20830:
+	case 23396:
+		pEFB->FBMapSize = REGR(RADEON_CONFIG_MEMSIZE);
+		break;
+	default:
+		pEFB->FBMapSize = REGR(R600_CONFIG_MEMSIZE);
+		break;
+	}
+	
+
+        /*
+         * Map framebuffer
+         */
+        pageSize = getpagesize();
+        size = pEFB->FBMapSize + (pageSize - 1) & (~(pageSize - 1));
+
+        pEFB->FBvaddr = (unsigned char *)mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED,
+                                        fd, pEFB->FBPhysAddr);
+
+        if (pEFB->FBvaddr == MAP_FAILED) {
+            TraceMessage(VTS_DEBUG, __func__, "map framebuffer failed\n");
+            gfx_vts_set_message(rp, 1, test, "map framebuffer failed");
+            return -1;
+        }
+
+
+	return 0;
+}
+
+int
+efb_unmap_mem(struct efb_info *pEFB, return_packet *rp, int test)
+{
+        /*
+         * Unmap Frame Buffer
+         */
+
+        if (munmap((void *)pEFB->FBvaddr, pEFB->FBMapSize) == -1) {
+            TraceMessage(VTS_DEBUG, __func__, "unmap framebuffer failed\n");
+            gfx_vts_set_message(rp, 1, test, "unmap framebuffer failed");
+            return -1;
+        }
+
+        if (munmap((void *)pEFB->MMIOvaddr, pEFB->MMIOMapSize) == -1) {
+            TraceMessage(VTS_DEBUG, __func__, "unmap MMIO failed\n");
+            gfx_vts_set_message(rp, 1, test, "unmap MMIO failed");
+            return -1;
+        }
+
+	return 0;
+}
+
+
+#define MASK    RBBM_STATUS__CMDFIFO_AVAIL_MASK
+
+uint32_t
+getBPPValue (int bpp)
+{
+	switch (bpp) {
+            case 8:     return (DST_8BPP);
+            case 15:    return (DST_15BPP);
+            case 16:    return (DST_16BPP);
+            case 32:    return (DST_32BPP);
+            default:    return (0);
+    	}
+}
+
+void 
+efb_flush_pixel_cache(struct efb_info *pEFB)
+{
+	int i ;
+
+	// initiate flush
+	REGW(RADEON_RB2D_DSTCACHE_CTLSTAT, REGR(RADEON_RB2D_DSTCACHE_CTLSTAT) | 0xf);
+
+	// check for completion but limit looping to 16384 reads
+	i = 16384;
+	while((REGR(RADEON_RB2D_DSTCACHE_CTLSTAT) & RADEON_RB2D_DC_BUSY) == RADEON_RB2D_DC_BUSY &&
+                --i >= 0 ) ;
+}
+
+void 
+efb_reset_engine (struct efb_info *pEFB)
+{
+	uint32_t save_genresetcntl, save_clockcntlindex, save_mclkcntl;
+	long term_count;
+
+	efb_flush_pixel_cache(pEFB) ;
+
+	save_clockcntlindex = REGR(RADEON_CLOCK_CNTL_INDEX);
+
+	// save GEN_RESET_CNTL register
+	save_genresetcntl = REGR(RADEON_DISP_MISC_CNTL);
+
+	// reset by setting bit, add read delay, then clear bit, 
+	// add read delay
+	REGW(RADEON_DISP_MISC_CNTL, save_genresetcntl |
+      	     RADEON_DISP_MISC_CNTL__SOFT_RESET_GRPH_PP);
+	REGR(RADEON_DISP_MISC_CNTL);
+	REGW(RADEON_DISP_MISC_CNTL, save_genresetcntl &
+             ~(RADEON_DISP_MISC_CNTL__SOFT_RESET_GRPH_PP));
+	REGR(RADEON_DISP_MISC_CNTL);
+
+	// restore the two registers we changed
+	REGW(RADEON_CLOCK_CNTL_INDEX, save_clockcntlindex);
+	REGW(RADEON_DISP_MISC_CNTL, save_genresetcntl);
+
+	term_count++;     // for monitoring engine hangs
+}
+
+void 
+efb_wait_for_fifo(struct efb_info *pEFB, int c)
+{
+	uint32_t i;
+	long limit;
+
+	/* First a short loop, just in case fifo clears out quickly */
+	for(limit=100; (REGR(RBBM_STATUS) & MASK) < c && --limit > 0; ) ;
+
+	if((REGR(RBBM_STATUS) & MASK) < c ) {
+    		hrtime_t timeout = gethrtime() + (hrtime_t)3000000000;
+            	while((REGR(RBBM_STATUS) & MASK) < c && 
+					gethrtime() < timeout )
+        	    yield();
+
+       	    	if((REGR(RBBM_STATUS) & MASK) < c )
+      	    	    efb_reset_engine(pEFB) ;
+	}
+}
+
+void 
+efb_wait_for_idle(struct efb_info *pEFB)
+{
+	uint32_t i;
+	long limit;
+
+	efb_wait_for_fifo(pEFB, 64) ;
+
+	for(limit=10000; (REGR(RBBM_STATUS) & GUI_ACTIVE) && --limit > 0; ) ;
+
+	if( REGR(RBBM_STATUS) & GUI_ACTIVE ) {
+    	    hrtime_t timeout = gethrtime() + (hrtime_t)3000000000;
+    	    while( (REGR(RBBM_STATUS) & GUI_ACTIVE) && 
+				gethrtime() < timeout )
+        	yield();
+
+            if( (REGR(RBBM_STATUS) & GUI_ACTIVE) != 0 )
+      		efb_reset_engine(pEFB) ;
+	}
+}
+
+