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