i128accel.c revision 7965d9ac
1 2/* 3 * Copyright 1997-2000 by Robin Cutshaw <robin@XFree86.Org> 4 * 5 * Permission to use, copy, modify, distribute, and sell this software and its 6 * documentation for any purpose is hereby granted without fee, provided that 7 * the above copyright notice appear in all copies and that both that 8 * copyright notice and this permission notice appear in supporting 9 * documentation, and that the name of Robin Cutshaw not be used in 10 * advertising or publicity pertaining to distribution of the software without 11 * specific, written prior permission. Robin Cutshaw makes no representations 12 * about the suitability of this software for any purpose. It is provided 13 * "as is" without express or implied warranty. 14 * 15 * ROBIN CUTSHAW DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO 17 * EVENT SHALL ROBIN CUTSHAW BE LIABLE FOR ANY SPECIAL, INDIRECT OR 18 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 19 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 20 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 21 * PERFORMANCE OF THIS SOFTWARE. 22 * 23 */ 24 25#ifdef HAVE_CONFIG_H 26#include "config.h" 27#endif 28 29#include "xaa.h" 30#include "xaalocal.h" 31#include "xf86fbman.h" 32#include "miline.h" 33#include "servermd.h" 34 35#include "xf86.h" 36#include "xf86_OSproc.h" 37#include "xf86Pci.h" 38#include "xf86PciInfo.h" 39 40#include "i128.h" 41#include "i128reg.h" 42 43static void I128BitBlit(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, 44 int w, int h); 45static void I128SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, 46 int ydir, int rop, unsigned planemask, int transparency_color); 47static void I128SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, 48 int x2, int y2, int w, int h); 49static void I128SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, 50 unsigned planemask); 51static void I128SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, 52 int h); 53static void I128SubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, 54 int x2, int y2, int flags); 55static void I128SetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, 56 int x2, int y2); 57static void I128FillSolidRects(ScrnInfoPtr pScrn, int fg, int rop, 58 unsigned int planemask, int nBox, register BoxPtr pBoxI); 59#if 0 60static void I128ScreenToScreenBitBlt(ScrnInfoPtr pScrn, int nbox, 61 DDXPointPtr pptSrc, BoxPtr pbox, int xdir, int ydir, int alu, 62 unsigned planemask); 63#endif 64 65#define ENG_PIPELINE_READY() { while (pI128->mem.rbase_a[BUSY] & BUSY_BUSY) ; } 66#define ENG_DONE() { while (pI128->mem.rbase_a[FLOW] & (FLOW_DEB | FLOW_MCB | FLOW_PRV)) ;} 67 68 69/* pre-shift rops and just or in as needed */ 70 71static const CARD32 i128alu[16] = 72{ 73 CR_CLEAR<<8, 74 CR_AND<<8, 75 CR_AND_REV<<8, 76 CR_COPY<<8, 77 CR_AND_INV<<8, 78 CR_NOOP<<8, 79 CR_XOR<<8, 80 CR_OR<<8, 81 CR_NOR<<8, 82 CR_EQUIV<<8, 83 CR_INVERT<<8, 84 CR_OR_REV<<8, 85 CR_COPY_INV<<8, 86 CR_OR_INV<<8, 87 CR_NAND<<8, 88 CR_SET<<8 89}; 90 /* 8bpp 16bpp 32bpp unused */ 91static const int min_size[] = { 0x62, 0x32, 0x1A, 0x00 }; 92static const int max_size[] = { 0x80, 0x40, 0x20, 0x00 }; 93static const int split_size[] = { 0x20, 0x10, 0x08, 0x00 }; 94 95 96void 97I128EngineDone(ScrnInfoPtr pScrn) 98{ 99 I128Ptr pI128 = I128PTR(pScrn); 100 ENG_DONE(); 101} 102 103 104static void 105I128BitBlit(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2, int w, int h) 106{ 107 I128Ptr pI128 = I128PTR(pScrn); 108 109#if 0 110 if (pI128->Debug) 111 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "BB %d,%d %d,%d %d,%d 0x%x/0x%x\n", x1, y1, x2, y2, w, h, pI128->cmd); 112#endif 113 114 ENG_PIPELINE_READY(); 115 116 pI128->mem.rbase_a[CMD] = pI128->cmd; 117 /*pI128->mem.rbase_a[XY3_DIR] = pI128->blitdir;*/ 118 119 if (pI128->blitdir & DIR_RL_TB) { 120 x1 += w; x1--; 121 x2 += w; x2--; 122 } 123 if (pI128->blitdir & DIR_LR_BT) { 124 y1 += h; y1--; 125 y2 += h; y2--; 126 } 127 128 129 130 if (pI128->Chipset == PCI_CHIP_I128) { 131 int bppi; 132 133 static int first_time_through = 1; 134 135 /* The I128-1 has a nasty bitblit bug 136 * that occurs when dest is exactly 8 pages wide 137 */ 138 139 bppi = (pI128->mem.rbase_a[BUF_CTRL] & BC_PSIZ_MSK) >> 24; 140 141 if ((w >= min_size[bppi]) && (w <= max_size[bppi])) { 142 if (first_time_through) { 143 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 144 "Using I128-1 workarounds.\n"); 145 first_time_through = 0; 146 } 147 148 bppi = split_size[bppi]; 149#if 1 150 /* split method */ 151 152 pI128->mem.rbase_a[XY2_WH] = (bppi<<16) | h; 153 pI128->mem.rbase_a[XY0_SRC] = (x1<<16) | y1; MB; 154 pI128->mem.rbase_a[XY1_DST] = (x2<<16) | y2; MB; 155 156 ENG_PIPELINE_READY(); 157 158 w -= bppi; 159 160 if (pI128->blitdir & DIR_RL_TB) { 161 /* right to left blit */ 162 x1 -= bppi; 163 x2 -= bppi; 164 } else { 165 /* left to right blit */ 166 x1 += bppi; 167 x2 += bppi; 168 } 169#else 170 /* clip method */ 171 pI128->mem.rbase_a[CLPTL] = (x2<<16) | y2; 172 pI128->mem.rbase_a[CLPBR] = ((x2+w)<<16) | (y2+h); 173 w += bppi; 174#endif 175 } 176 } 177 178 pI128->mem.rbase_a[XY2_WH] = (w<<16) | h; 179 pI128->mem.rbase_a[XY0_SRC] = (x1<<16) | y1; MB; 180 pI128->mem.rbase_a[XY1_DST] = (x2<<16) | y2; MB; 181} 182 183static void 184I128SetupForScreenToScreenCopy(ScrnInfoPtr pScrn, int xdir, int ydir, 185 int rop, unsigned planemask, int transparency_color) 186{ 187 I128Ptr pI128 = I128PTR(pScrn); 188 189#if 0 190 if (pI128->Debug) 191 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SFSSC %d,%d %d 0x%x %d\n", xdir, ydir, rop, planemask, transparency_color); 192#endif 193 194 ENG_PIPELINE_READY(); 195 196 if (planemask == -1) 197 pI128->mem.rbase_a[MASK] = -1; 198 else switch (pI128->bitsPerPixel) { 199 case 8: 200 pI128->mem.rbase_a[MASK] = planemask | 201 (planemask<<8) | 202 (planemask<<16) | 203 (planemask<<24); 204 break; 205 case 16: 206 pI128->mem.rbase_a[MASK] = planemask | (planemask<<16); 207 break; 208 case 24: 209 case 32: 210 default: 211 pI128->mem.rbase_a[MASK] = planemask; 212 break; 213 } 214 215 216 pI128->mem.rbase_a[CLPTL] = 0x00000000; 217 pI128->mem.rbase_a[CLPBR] = (4095<<16) | 2047; 218 219 if (transparency_color != -1) 220 pI128->mem.rbase_a[BACK] = transparency_color; 221 222 223 if (xdir == -1) { 224 if (ydir == -1) pI128->blitdir = DIR_RL_BT; 225 else pI128->blitdir = DIR_RL_TB; 226 } else { 227 if (ydir == -1) pI128->blitdir = DIR_LR_BT; 228 else pI128->blitdir = DIR_LR_TB; 229 } 230 pI128->mem.rbase_a[XY3_DIR] = pI128->blitdir; 231 232 pI128->rop = i128alu[rop]; 233 pI128->cmd = (transparency_color != -1 ? (CS_TRNSP<<16) : 0) | 234 pI128->rop | CO_BITBLT; 235 pI128->mem.rbase_a[CMD] = pI128->cmd; 236} 237 238static void 239I128SubsequentScreenToScreenCopy(ScrnInfoPtr pScrn, int x1, int y1, 240 int x2, int y2, int w, int h) 241{ 242 I128BitBlit(pScrn, x1, y1, x2, y2, w, h); 243} 244 245static void 246I128SetupForSolidFill(ScrnInfoPtr pScrn, int color, int rop, unsigned planemask) 247{ 248 I128Ptr pI128 = I128PTR(pScrn); 249 250#if 0 251 if (pI128->Debug) 252 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SFSF color 0x%x rop 0x%x (I128rop 0x%x) pmask 0x%x\n", color, rop, i128alu[rop]>>8, planemask); 253#endif 254 255 ENG_PIPELINE_READY(); 256 257 if (planemask == -1) 258 pI128->mem.rbase_a[MASK] = -1; 259 else switch (pI128->bitsPerPixel) { 260 case 8: 261 pI128->mem.rbase_a[MASK] = planemask | 262 (planemask<<8) | 263 (planemask<<16) | 264 (planemask<<24); 265 break; 266 case 16: 267 pI128->mem.rbase_a[MASK] = planemask | (planemask<<16); 268 break; 269 case 24: 270 case 32: 271 default: 272 pI128->mem.rbase_a[MASK] = planemask; 273 break; 274 } 275 276 pI128->mem.rbase_a[FORE] = color; 277 278 pI128->clptl = pI128->mem.rbase_a[CLPTL] = 0x00000000; 279 pI128->clpbr = pI128->mem.rbase_a[CLPBR] = (4095<<16) | 2047 ; 280 281 pI128->mem.rbase_a[XY3_DIR] = pI128->blitdir = DIR_LR_TB; 282 283 pI128->rop = i128alu[rop]; 284 pI128->cmd = (CS_SOLID<<16) | pI128->rop | CO_BITBLT; 285 pI128->mem.rbase_a[CMD] = pI128->cmd; 286} 287 288static void 289I128SubsequentSolidFillRect(ScrnInfoPtr pScrn, int x, int y, int w, int h) 290{ 291#if 0 292 I128Ptr pI128 = I128PTR(pScrn); 293 294 if (pI128->Debug) 295 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SSFR %d,%d %d,%d\n", x, y, w, h); 296#endif 297 I128BitBlit(pScrn, 0, 0, x, y, w, h); 298} 299 300static void 301I128SubsequentSolidTwoPointLine(ScrnInfoPtr pScrn, int x1, int y1, int x2, 302 int y2, int flags) 303{ 304 I128Ptr pI128 = I128PTR(pScrn); 305 306#if 0 307 if (pI128->Debug) 308 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "STPL I128rop 0x%x %d,%d %d,%d clip %d,%d %d,%d\n", pI128->rop, x1, y1, x2, y2, pI128->clptl>>16, pI128->clptl&0xffff, (pI128->clpbr>>16)&0xffff, pI128->clpbr&0xffff); 309#endif 310 311 ENG_PIPELINE_READY(); 312 313 pI128->mem.rbase_a[CMD] = 314 ((flags&0x0100) ? (CP_NLST<<24) : 0) | 315 (CC_CLPRECI<<21) | 316 (CS_SOLID<<16) | 317 pI128->rop | 318 CO_LINE; 319 320 pI128->mem.rbase_a[CLPTL] = pI128->clptl; 321 pI128->mem.rbase_a[CLPBR] = pI128->clpbr; 322 323 pI128->mem.rbase_a[XY0_SRC] = (x1<<16) | y1; MB; 324 pI128->mem.rbase_a[XY1_DST] = (x2<<16) | y2; MB; 325} 326 327static void 328I128SetClippingRectangle(ScrnInfoPtr pScrn, int x1, int y1, int x2, int y2) 329{ 330 I128Ptr pI128 = I128PTR(pScrn); 331 int tmp; 332 333#if 0 334 if (pI128->Debug) 335 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "SCR %d,%d %d,%d\n", x1, y1, x2, y2); 336#endif 337 338 if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; } 339 if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; } 340 341 pI128->clptl = (x1<<16) | y1; 342 pI128->clpbr = (x2<<16) | y2; 343} 344 345 346static void 347I128FillSolidRects(ScrnInfoPtr pScrn, int fg, int rop, unsigned int planemask, 348 int nBox, register BoxPtr pBoxI) 349{ 350 I128Ptr pI128 = I128PTR(pScrn); 351 register int w, h; 352 353#if 0 354 if (pI128->Debug) 355 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "FSR color 0x%x rop 0x%x (I128rop 0x%x) pmask 0x%x\n", fg, rop, i128alu[rop]>>8, planemask); 356#endif 357 358 ENG_PIPELINE_READY(); 359 360 if (planemask != -1) { 361 if (pI128->bitsPerPixel == 8) { 362 planemask |= (planemask<<8) | 363 (planemask<<16) | 364 (planemask<<24); 365 } else if (pI128->bitsPerPixel == 16) 366 planemask |= planemask<<16; 367 } 368 369 pI128->mem.rbase_a[MASK] = planemask; 370 pI128->mem.rbase_a[FORE] = fg; 371 pI128->mem.rbase_a[CMD] = (CS_SOLID<<16) | i128alu[rop] | CO_BITBLT; 372 pI128->mem.rbase_a[CLPTL] = 0x00000000; 373 pI128->mem.rbase_a[CLPBR] = (4095<<16) | 2047; 374 375 pI128->mem.rbase_a[XY3_DIR] = DIR_LR_TB; 376 pI128->mem.rbase_a[XY0_SRC] = 0x00000000; 377 378 while (nBox > 0) { 379 w = pBoxI->x2 - pBoxI->x1; 380 h = pBoxI->y2 - pBoxI->y1; 381 if (w > 0 && h > 0) { 382 pI128->mem.rbase_a[XY2_WH] = (w<<16) | h; MB; 383 pI128->mem.rbase_a[XY1_DST] = 384 (pBoxI->x1<<16) | pBoxI->y1; MB; 385 386 ENG_PIPELINE_READY(); 387#if 0 388 if (pI128->Debug) 389 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "FSR x,y %d,%d w,h %d,%d\n", pBoxI->x1, pBoxI->y1, w, h); 390#endif 391 392 } 393 pBoxI++; 394 nBox--; 395 } 396 397 ENG_DONE(); 398 399} 400 401#if 0 402static void 403I128ScreenToScreenBitBlt(ScrnInfoPtr pScrn, int nbox, DDXPointPtr pptSrc, 404 BoxPtr pbox, int xdir, int ydir, int alu, unsigned planemask) 405{ 406 I128Ptr pI128 = I128PTR(pScrn); 407 I128SetupForScreenToScreenCopy(pScrn, xdir, ydir, alu, planemask, -1); 408 for (; nbox; pbox++, pptSrc++, nbox--) 409 I128SubsequentScreenToScreenCopy(pScrn, pptSrc->x, pptSrc->y, 410 pbox->x1, pbox->y1, pbox->x2 - pbox->x1, pbox->y2 - pbox->y1); 411 ENG_DONE(); 412} 413#endif 414 415Bool 416I128XaaInit(ScreenPtr pScreen) 417{ 418 XAAInfoRecPtr infoPtr; 419 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 420 I128Ptr pI128 = I128PTR(pScrn); 421 BoxRec AvailFBArea; 422 CARD32 buf_ctrl; 423 int maxlines; 424 425 pI128->XaaInfoRec = infoPtr = XAACreateInfoRec(); 426 if (!infoPtr) return FALSE; 427 428 infoPtr->Flags = PIXMAP_CACHE | 429 OFFSCREEN_PIXMAPS | 430 LINEAR_FRAMEBUFFER ; 431 432 infoPtr->Sync = I128EngineDone; 433 434 /* screen to screen copy */ 435 infoPtr->ScreenToScreenCopyFlags = NO_TRANSPARENCY; 436 if (pI128->Chipset == PCI_CHIP_I128_T2R) 437 infoPtr->ScreenToScreenCopyFlags |= ONLY_LEFT_TO_RIGHT_BITBLT; 438 439 infoPtr->SetupForScreenToScreenCopy = I128SetupForScreenToScreenCopy; 440 infoPtr->SubsequentScreenToScreenCopy = 441 I128SubsequentScreenToScreenCopy; 442 443#if 0 444 /* screen to screen color expansion */ 445 if (pI128->Chipset == PCI_CHIP_I128_T2R) 446 infoPtr->ScreenToScreenColorExpandFillFlags |= 447 ONLY_LEFT_TO_RIGHT_BITBLT; 448 449 infoPtr->SetupForScreenToScreenColorExpandFill = 450 I128SetupForScreenToScreenColorExpandFill; 451 infoPtr->SubsequentScreenToScreenColorExpandFill = 452 I128SubsequentScreenToScreenColorExpandFill; 453#endif 454 455 /* solid fills */ 456 infoPtr->SetupForSolidFill = I128SetupForSolidFill; 457 infoPtr->SubsequentSolidFillRect = I128SubsequentSolidFillRect; 458 459 infoPtr->FillSolidRects = I128FillSolidRects; 460 461 /* solid lines */ 462 infoPtr->SubsequentSolidTwoPointLine = I128SubsequentSolidTwoPointLine; 463 464 /* clipping */ 465 infoPtr->ClippingFlags = HARDWARE_CLIP_LINE; 466 infoPtr->SetClippingRectangle = I128SetClippingRectangle; 467 468 infoPtr->PolyFillRectSolidFlags = 0; 469 470 maxlines = ((pI128->MemorySize * 1024) - 1024) / 471 (pScrn->displayWidth * pI128->bitsPerPixel / 8); 472 AvailFBArea.x1 = 0; 473 AvailFBArea.x2 = pI128->displayWidth; 474 AvailFBArea.y1 = 0; 475 AvailFBArea.y2 = maxlines; 476 xf86InitFBManager(pScreen, &AvailFBArea); 477 xf86DrvMsg(pScrn->scrnIndex, X_INFO, 478 "Using %d lines for offscreen memory\n", 479 maxlines - pScrn->virtualY); 480 481 switch (pI128->bitsPerPixel) { 482 case 8: buf_ctrl = BC_PSIZ_8B; break; 483 case 16: buf_ctrl = BC_PSIZ_16B; break; 484 case 24: 485 case 32: buf_ctrl = BC_PSIZ_32B; break; 486 default: buf_ctrl = 0; break; /* error */ 487 } 488 if (pI128->Chipset == PCI_CHIP_I128_T2R) { 489 if (pI128->MemoryType == I128_MEMORY_SGRAM) 490 buf_ctrl |= BC_MDM_PLN; 491 else 492 buf_ctrl |= BC_BLK_ENA; 493 } 494 pI128->mem.rbase_a[BUF_CTRL] = buf_ctrl; 495 496 pI128->mem.rbase_a[DE_PGE] = 0x00; 497 pI128->mem.rbase_a[DE_SORG] = pI128->displayOffset; 498 pI128->mem.rbase_a[DE_DORG] = pI128->displayOffset; 499 pI128->mem.rbase_a[DE_MSRC] = 0x00; 500 pI128->mem.rbase_a[DE_WKEY] = 0x00; 501 pI128->mem.rbase_a[DE_SPTCH] = pI128->mem.rbase_g[DB_PTCH]; 502 pI128->mem.rbase_a[DE_DPTCH] = pI128->mem.rbase_g[DB_PTCH]; 503 if (pI128->Chipset == PCI_CHIP_I128_T2R4) 504 pI128->mem.rbase_a[DE_ZPTCH] = pI128->mem.rbase_g[DB_PTCH]; 505 pI128->mem.rbase_a[RMSK] = 0x00000000; 506 pI128->mem.rbase_a[XY4_ZM] = ZOOM_NONE; 507 pI128->mem.rbase_a[LPAT] = 0xffffffff; /* for lines */ 508 pI128->mem.rbase_a[PCTRL] = 0x00000000; /* for lines */ 509 pI128->mem.rbase_a[CLPTL] = 0x00000000; 510 pI128->mem.rbase_a[CLPBR] = (4095<<16) | 2047 ; 511 pI128->mem.rbase_a[ACNTRL] = 0x00000000; 512 pI128->mem.rbase_a[INTM] = 0x03; 513 514 if (pI128->Debug) { 515 xf86DrvMsg(pScrn->scrnIndex, X_INFO, "I128XaaInit done\n"); 516 I128DumpActiveRegisters(pScrn); 517 } 518 519 return(XAAInit(pScreen, infoPtr)); 520} 521