[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