[PATCH 1/2 xf86-video-impact] Cacheflush-enhancement,...

peter fuerst post at pfrst.de
Tue Sep 6 13:45:20 PDT 2011




This patch provides some enhancements for XImpact:

- Check for available cache-flush methods, and use the kernel-driver's
   cache-flush ioctl if possible. (This method is likely to be the only one
   available, when the Impact kernel-driver is finally incorporated into the
   Linux-kernel! Besides, it performs slightly better than lib-cacheflush
   for a majority of window-sizes.)
   If none is available, fall back to PIO-mode automatically.

- Recognize Impact/R4k (with the help of an up to date kernel-driver) and
   handle it appropriately. (Though this could not be tested yet)

- The borders, where to switch between PIO and DMA or between DMA-Methods
   are more accurate now.


Signed-off-by: peter fuerst <post at pfrst.de>

---

  src/impact.h        |    8 ++-
  src/impact_driver.c |   38 ++++++++++-----
  src/impact_regs.h   |   18 +++++--
  src/impact_shadow.c |  134 ++++++++++++++++++++++++++++++++++++++++-----------
  4 files changed, 150 insertions(+), 48 deletions(-)


diff --git a/src/impact.h b/src/impact.h
index 31f69c6..ce6b148 100644
--- a/xorg/driver/xf86-video-impact/src/impact.h	Thu Oct 28 07:32:19 2010 -0400
+++ b/xorg/driver/xf86-video-impact/src/impact.h	Thu Jul 21 03:39:43 2011
@@ -50,7 +50,9 @@

  typedef struct {
  	unsigned busID;
-	unsigned isSR;
+	unsigned IPnr;
+#	define IMPACTSR_IP(i) ((i) > 28)
+#	define IMPACTSR(p) IMPACTSR_IP((p)->IPnr)
  	int devFD;
  	int bitplanes;

@@ -139,7 +141,9 @@ void ImpactBackupPalette(ScrnInfoPtr);
  int ImpactDepth24Flags(void);
  void ImpactI2RefreshArea8(ScrnInfoPtr, int num, BoxPtr pbox);
  void ImpactSRRefreshArea8(ScrnInfoPtr, int num, BoxPtr pbox);
-void ImpactI2RefreshArea32(ScrnInfoPtr, int num, BoxPtr pbox);
+void ImpactIP28RefreshArea32(ScrnInfoPtr, int num, BoxPtr pbox);
+void ImpactIP22RefreshArea32(ScrnInfoPtr, int num, BoxPtr pbox);
  void ImpactSRRefreshArea32(ScrnInfoPtr, int num, BoxPtr pbox);
+void ImpactI2FindCflushmode(ImpactPtr);

  #endif /* __IMPACT_H__ */


diff --git a/src/impact_driver.c b/src/impact_driver.c
index 924db4a..cb16b4a 100644
--- a/xorg/driver/xf86-video-impact/src/impact_driver.c	Thu Oct 28 07:32:19 2010 -0400
+++ b/xorg/driver/xf86-video-impact/src/impact_driver.c	Sun Jul 24 21:37:47 2011
@@ -80,7 +80,7 @@

  struct probed_id {
  	unsigned char id;
-	unsigned char sr;
+	unsigned char ip;
  };


@@ -251,7 +251,7 @@ ImpactProbe(DriverPtr drv, int flags)
  					int entity;
  					ScrnInfoPtr pScrn = 0;
  					entity = xf86ClaimNoSlot(drv, 0, dev, TRUE);
-					if (probedIDs[j].sr) {
+					if (IMPACTSR_IP(probedIDs[j].ip)) {
  						base = (IMPACTSR_BASE_ADDR0 + busID * IMPACTSR_BASE_OFFSET);
  						RANGE(range[0], base,
  							base + sizeof(ImpactSRRegs), ResExcMemBlock);
@@ -271,7 +271,7 @@ ImpactProbe(DriverPtr drv, int flags)
  					pScrn->EnterVT = ImpactEnterVT;
  					pScrn->LeaveVT = ImpactLeaveVT;
  					pScrn->driverPrivate =
-						(void*)(busID | (long)probedIDs[j].sr<<16);
+						(void*)(busID | (long)probedIDs[j].ip<<16);
  					foundScreen = TRUE;
  					break;
  				}
@@ -357,10 +357,10 @@ ImpactPreInit(ScrnInfoPtr pScrn, int flags)
  	/* ...and initialize it. */
  	pImpact = IMPACTPTR(pScrn);
  	pImpact->busID = busID & 0xffff;
-	pImpact->isSR  = busID >> 16;
+	pImpact->IPnr  = busID >> 16;
  	pImpact->FlushBoxCache = 0;

-	if (pImpact->isSR) {
+	if (IMPACTSR(pImpact)) {
  		pImpact->WaitCfifoEmpty = &ImpactSRWaitCfifoEmpty;
  		pImpact->WaitDMAOver = &ImpactSRWaitDMAOver;
  		pImpact->WaitDMAReady = &ImpactSRWaitDMAReady;
@@ -381,7 +381,10 @@ ImpactPreInit(ScrnInfoPtr pScrn, int flags)
  		pImpact->XmapGetModeRegister = &ImpactI2XmapGetModeRegister;
  		pImpact->XmapSetModeRegister = &ImpactI2XmapSetModeRegister;
  		pImpact->RefreshArea8  = &ImpactI2RefreshArea8;
-		pImpact->RefreshArea32 = &ImpactI2RefreshArea32;
+		if (22 == pImpact->IPnr)
+			pImpact->RefreshArea32 = &ImpactIP22RefreshArea32;
+		else
+			pImpact->RefreshArea32 = &ImpactIP28RefreshArea32;
  		pImpact->base_addr0 = IMPACTI2_BASE_ADDR0;
  		pImpact->base_offset = IMPACTI2_BASE_OFFSET;
  	}
@@ -603,6 +606,9 @@ ImpactScreenInit(int index, ScreenPtr pScreen, int argc, char **argv)
  	if (1 == serverGeneration)
  		xf86ShowUnusedOptions(pScrn->scrnIndex, pScrn->options);

+	if (!IMPACTSR(pImpact))
+		ImpactI2FindCflushmode(pImpact);
+
  	return TRUE;

  out_freerec:
@@ -731,7 +737,7 @@ ImpactHWProbe(struct probed_id probedIDs[], int lim)
  	FILE* fb;
  	int hasImpact = 0;

-	probedIDs[0].sr = probedIDs[0].id = 0;
+	probedIDs[0].ip = probedIDs[0].id = 0;
  	if (IMPACT_MAX_BOARDS < lim)
  		lim = IMPACT_MAX_BOARDS;

@@ -741,9 +747,17 @@ ImpactHWProbe(struct probed_id probedIDs[], int lim)
  			char *s;
  			unsigned i = strtoul(line,&s,10);
  			if ( !strncmp(s," Impact",7) ) {
-				probedIDs[hasImpact].sr = ('S' == s[7]);
-				probedIDs[hasImpact].id = i;
-				hasImpact++;
+				switch (s[7]) {
+					case '2':
+						probedIDs[hasImpact].ip = 22 + s[8] - '2';
+						break;
+					case 'S':
+						probedIDs[hasImpact].ip = 30;
+						break;
+					default:
+						probedIDs[hasImpact].ip = 28;
+				}
+				probedIDs[hasImpact++].id = i;
  			}
  		}
  		fclose(fb);
@@ -797,7 +811,7 @@ ImpactMapRegs(ScrnInfoPtr pScrn)
  		ErrorF("ImpactMapRegs: failed to open /dev/fb%d (%s)\n",
  			pImpact->busID , strerror(errno));
  	else {
-		size_t size = pImpact->isSR ? 0x200000:sizeof(ImpactI2Regs);
+		size_t size = IMPACTSR(pImpact) ? 0x200000:sizeof(ImpactI2Regs);
  		pImpact->pImpactRegs =
  			mmap((void*)0, size, PROT_READ|PROT_WRITE,
  				MAP_SHARED, pImpact->devFD, 0);
@@ -839,7 +853,7 @@ static void
  ImpactUnmapRegs(ScrnInfoPtr pScrn)
  {
  	ImpactPtr pImpact = IMPACTPTR(pScrn);
-	size_t size = pImpact->isSR ? 0x200000:sizeof(ImpactI2Regs);
+	size_t size = IMPACTSR(pImpact) ? 0x200000:sizeof(ImpactI2Regs);

  	if (pImpact->pImpactRegs)
  		munmap( pImpact->pImpactRegs, size );


diff --git a/src/impact_regs.h b/src/impact_regs.h
index e29b941..f6b16c9 100644
--- a/xorg/driver/xf86-video-impact/src/impact_regs.h	Thu Oct 28 07:32:19 2010 -0400
+++ b/xorg/driver/xf86-video-impact/src/impact_regs.h	Wed Jul 27 21:51:20 2011
@@ -147,11 +147,19 @@ ImpactFifoCmd64( mgicfifo_t *fifo, unsigned cmd, unsigned reg, unsigned val )
  }

  static __inline__ void
-ImpactFifoCmd32( mgicfifo_t *fifo, unsigned cmd, unsigned reg )
+ImpactFifoCmd32hi( mgicfifo_t *fifo, unsigned cmd, unsigned reg )
+{
+	fifo->w = cmd | reg<<8;
+}
+
+static __inline__ void
+ImpactFifoCmd32lo( mgicfifo_t *fifo, unsigned cmd, unsigned reg )
  {
  	(&fifo->w)[1] = cmd | reg<<8;
  }

+#define ImpactFifoCmd32 ImpactFifoCmd32hi
+
  #define ImpactCmdWriteRss( fifo, reg, val )\
  	ImpactFifoCmd64( fifo, 0x00180004, reg, val )
  #define ImpactCmdExecRss( fifo, reg, val )\
@@ -193,13 +201,11 @@ ImpactFifoCmd32( mgicfifo_t *fifo, unsigned cmd, unsigned reg )
  #define impact_cmd_hq_pg_startaddr(f,v)	ImpactFifoCmd64(f,0x00080604,0,v)
  #define impact_cmd_hq_pg_linecnt(f,v)	ImpactFifoCmd64(f,0x00080704,0,v)
  #define impact_cmd_hq_pg_widtha(f,v)	ImpactFifoCmd64(f,0x00080804,0,v)
-#if 0
+
  #define impact_cmd_hq_dmactrl_1(f)	ImpactFifoCmd32(f,0x00080b04,0)
-#define impact_cmd_hq_dmactrl_2(f)	ImpactFifoCmd64(f,0x000000b7,0,0x000e0400)
-#else
+#define impact_cmd_hq_dmactrl_2(f,p)	ImpactFifoCmd64(f,((p)<<1)|0x000000b1,0,0x000e0400)
  #define impact_cmd_hq_dmactrl_a(f,p)	ImpactFifoCmd64(f,0x00080b04,0,((p)<<1)|0x000000b1)
-#define impact_cmd_hq_dmactrl_b(f)	ImpactFifoCmd32(f,0x000e0400,0)
-#endif
+#define impact_cmd_hq_dmactrl_b(f)	ImpactFifoCmd32lo(f,0x000e0400,0)

  /* Now the Indexed registers of the VC2. */
  #define VC2_IREG_CONFIG    0x1f	/* this is wrong (0x20) in newport_regs.h */


diff --git a/src/impact_shadow.c b/src/impact_shadow.c
index fffd507..6bc711e 100644
--- a/xorg/driver/xf86-video-impact/src/impact_shadow.c	Thu Oct 28 07:32:19 2010 -0400
+++ b/xorg/driver/xf86-video-impact/src/impact_shadow.c	Wed Jul 27 21:59:04 2011
@@ -168,30 +168,81 @@ ImpactSRRefreshArea8(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
   * 32-bit blits are done as DMA operations, which is FAST on SGI machines
   */

+static void (*ImpactCflushBox)(int, char*, BoxPtr, unsigned);
+
  static void
-ImpactCflushBoxPixlines(int fd, char *base, BoxPtr box, unsigned bpitch)
+ImpactCflushLib(int fd, char *base, BoxPtr box, unsigned bpitch)
  {
-	int w = (box->x2 - box->x1) << 2;
+	int w = box->x2 - box->x1;
  	int h = box->y2 - box->y1;
  	int i;

  	base += bpitch*box->y1 + 4*box->x1;
-
-	/* One syscall for each pixel-line. */
-	for (i = 0; i < h; i++, base += bpitch)
-		cacheflush(base, w, DCACHE);
+	/*
+	 * This border was found to be suitable on IP28,
+	 * it may or may not fit IP26's conditions.
+	 */
+	if (w > 865 || 4*w > 5440 - 11*h && 10*w > 8180 - 14*h)
+		/* Whole enclosing mem, although may be mostly unconcerned. */
+		cacheflush(base, (h-1)*bpitch + (w << 2), DCACHE);
+	else
+		/* One syscall for each pixel-line. */
+		for (w <<= 2, i = 0; i < h; i++, base += bpitch)
+			cacheflush(base, w, DCACHE);
  }

  static void
-ImpactCflushBoxEnclosure(int fd, char *base, BoxPtr box, unsigned bpitch)
+ImpactCflushDrv(int fd, char *base, BoxPtr box, unsigned bpitch)
  {
-	int w = (box->x2 - box->x1) << 2;
-	int h = box->y2 - box->y1;
-
-	base += bpitch*box->y1 + 4*box->x1;
+	struct
+	{	struct winsize box;
+		unsigned long long base;
+		unsigned bpitch;
+	} par;
+
+	/* One cacheflush for each pixel-line by a single syscall. */
+	par.box.ws_col = box->x1;
+	par.box.ws_row = box->y1;
+	par.box.ws_xpixel = box->x2 - box->x1;
+	par.box.ws_ypixel = box->y2 - box->y1;
+	par.base = (unsigned long long) base;
+	par.bpitch = bpitch;
+	ioctl(fd, TCFLSH, &par);
+}

-	/* Whole enclosing mem, although may be mostly unconcerned. */
-	cacheflush(base, (h-1)*bpitch + w, DCACHE);
+void
+ImpactI2FindCflushmode(ImpactPtr pImpact)
+{
+	if (pImpact->IPnr != 22) {
+		struct
+		{	struct winsize box;
+			unsigned long long base;
+			unsigned bpitch;
+		} par;
+
+		par.box.ws_col = par.box.ws_row = 0;
+		par.box.ws_xpixel = par.box.ws_ypixel = 1;
+		par.base = (unsigned long long) pImpact->ShadowPtr;
+		par.bpitch = pImpact->ShadowPitch;
+		/*
+		 * Does the Impact kernel-driver provide the special cache
+		 * flush ioctl? If available, use it.
+		 */
+		if (!ioctl(pImpact->devFD, TCFLSH, &par)) {
+			ErrorF("Using kernel driver's cache-flush-ioctl.\n");
+			ImpactCflushBox = ImpactCflushDrv;
+		/*
+		 * Only the extended sys_cacheflush() would check its 3rd
+		 * parameter and return non-zero here. The "standard" version
+		 * simply assumes ICACHE, returning 0.
+		 */
+		} else if (cacheflush(pImpact->ShadowPtr, 4, -1)) {
+			ErrorF("Using cacheflush() system call from libc.\n");
+			ImpactCflushBox = ImpactCflushLib;
+		} else
+			ErrorF("No cache-flush method available, "
+				"falling back to PIO mode.\n");
+	}
  }


@@ -235,9 +286,13 @@ ImpactRefreshBoxDMA(int isSR, mgicfifo_t *cfifo, BoxPtr box, unsigned bpitch)
  	impact_cmd_hq_pg_startaddr(cfifo, bpitch*box->y1+(box->x1<<2));
  	impact_cmd_hq_pg_linecnt(cfifo, h);
  	impact_cmd_hq_pg_widtha(cfifo, w<<2);
-	impact_cmd_hq_dmactrl_a(cfifo,3);
-	impact_cmd_hq_dmactrl_b(cfifo);
-
+	if (isSR) { /* but both (should) do the same  :) */
+		impact_cmd_hq_dmactrl_1(cfifo);
+		impact_cmd_hq_dmactrl_2(cfifo,3);
+	} else {
+		impact_cmd_hq_dmactrl_a(cfifo,3);
+		impact_cmd_hq_dmactrl_b(cfifo);
+	}
  	return 1;
  }

@@ -257,7 +312,7 @@ ImpactRefreshArea32DMA(ImpactPtr pImpact, int num, BoxPtr pbox)
  {
  	ImpactRegsPtr pImpactRegs = pImpact->pImpactRegs;
  	mgicfifo_t *cfifo =
-		pImpact->isSR ? &pImpactRegs->sr.cfifo:&pImpactRegs->i2.cfifo;
+		IMPACTSR(pImpact) ? &pImpactRegs->sr.cfifo:&pImpactRegs->i2.cfifo;
  	unsigned bpitch = pImpact->ShadowPitch;

  	for (; num-- > 0; pbox++) {
@@ -273,7 +328,7 @@ ImpactRefreshArea32DMA(ImpactPtr pImpact, int num, BoxPtr pbox)
  						&sanebox, bpitch);

  		(*pImpact->WaitDMAOver)(pImpactRegs);
-		ImpactRefreshBoxDMA(pImpact->isSR, cfifo, &sanebox, bpitch);
+		ImpactRefreshBoxDMA(IMPACTSR(pImpact), cfifo, &sanebox, bpitch);
  		(*pImpact->WaitDMAOver)(pImpactRegs);
  		ImpactPostRefreshBoxDMA(cfifo);
  	}
@@ -290,7 +345,7 @@ ImpactRefreshArea32PIO(ImpactPtr pImpact, int num, BoxPtr pbox)
  {
  	ImpactRegsPtr pImpactRegs = pImpact->pImpactRegs;
  	mgicfifo_t *cfifo =
-		pImpact->isSR ? &pImpactRegs->sr.cfifo:&pImpactRegs->i2.cfifo;
+		IMPACTSR(pImpact) ? &pImpactRegs->sr.cfifo:&pImpactRegs->i2.cfifo;
  	unsigned bpitch = pImpact->ShadowPitch;

  	for (; num--; pbox++) {
@@ -324,27 +379,50 @@ ImpactRefreshArea32PIO(ImpactPtr pImpact, int num, BoxPtr pbox)
  }


+/*
+ * IP28 and IP26 need the same DMA-refresh strategy.
+ */
  void
-ImpactI2RefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+ImpactIP28RefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
  {
  	ImpactPtr pImpact = IMPACTPTR(pScrn);
+	pImpact->FlushBoxCache = ImpactCflushBox;

  	for (; num--; pbox++) {
  		int w = pbox->x2 - pbox->x1;
  		int h = pbox->y2 - pbox->y1;
-
-		if (w < 16 || w < 24 && h < 16 || w < 40 && h < 4)
+		int pio = !pImpact->FlushBoxCache;
+		/*
+		 * This border was found to be suitable on IP28,
+		 * it may or may not fit IP22's or IP26's conditions.
+		 */
+		if (w < 10)
+			pio = 1;
+		else if (w < 17) {
+			static char lim[] = {52,23,14,11,9,8,7};
+			if (h < lim[w-10]) pio = 1;
+		} else if (/* w < 56 && */ h < 7) {
+			static char lim[] = {0,56,34,26,21,19,17};
+			if (w < lim[h]) pio = 1;
+		}
+		if (pio)
  			ImpactRefreshArea32PIO(pImpact, 1, pbox);
-		else {
-			if (h < 580)
-				pImpact->FlushBoxCache = ImpactCflushBoxPixlines;
-			else
-				pImpact->FlushBoxCache = ImpactCflushBoxEnclosure;
+		else
  			ImpactRefreshArea32DMA(pImpact, 1, pbox);
-		}
  	}
  }

+/*
+ * 1) On IP22 uncached writes are available, so cache-flush is not needed.
+ * 2) Where to switch between PIO and DMA could (yet) be checked on IP28 only.
+ * So solely plain DMA is used for now.
+ */
+void
+ImpactIP22RefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
+{
+	ImpactRefreshArea32DMA(IMPACTPTR(pScrn), num, pbox);
+}
+
  void
  ImpactSRRefreshArea32(ScrnInfoPtr pScrn, int num, BoxPtr pbox)
  {

*** eof ***


More information about the xorg-devel mailing list