ct_cursor.c revision 9f4658d1
1 2/* 3 * Copyright 1994 The XFree86 Project 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * DAVID WEXELBLAT BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 19 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 20 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 * SOFTWARE. 22 * 23 * Hardware Cursor for Trident utilizing XAA Cursor code. 24 * Written by Alan Hourihane <alanh@fairlite.demon.co.uk> 25 * Modified for Chips and Technologies by David Bateman <dbateman@eng.uts.edu.au> 26 */ 27 28#ifdef HAVE_CONFIG_H 29#include "config.h" 30#endif 31 32/* All drivers should typically include these */ 33#include "xf86.h" 34#include "xf86_OSproc.h" 35 36/* Everything using inb/outb, etc needs "compiler.h" */ 37#include "compiler.h" 38 39/* Drivers for PCI hardware need this */ 40#include "xf86PciInfo.h" 41 42/* Drivers that need to access the PCI config space directly need this */ 43#include "xf86Pci.h" 44 45#include "xf86Cursor.h" 46 47/* Driver specific headers */ 48#include "ct_driver.h" 49 50/* Sync function, maybe this should check infoRec->NeedToSync before syncing */ 51#define CURSOR_SYNC(pScrn) \ 52 if (IS_HiQV(cPtr)) { \ 53 CHIPSHiQVSync(pScrn); \ 54 } else { \ 55 if(!cPtr->UseMMIO) { \ 56 CHIPSSync(pScrn); \ 57 } else { \ 58 CHIPSMMIOSync(pScrn); \ 59 } \ 60 } 61 62/* Swing your cursor bytes round and round... yeehaw! */ 63#if X_BYTE_ORDER == X_BIG_ENDIAN 64#define P_SWAP32( a , b ) \ 65 ((char *)a)[0] = ((char *)b)[3]; \ 66 ((char *)a)[1] = ((char *)b)[2]; \ 67 ((char *)a)[2] = ((char *)b)[1]; \ 68 ((char *)a)[3] = ((char *)b)[0] 69 70#define P_SWAP16( a , b ) \ 71 ((char *)a)[0] = ((char *)b)[1]; \ 72 ((char *)a)[1] = ((char *)b)[0]; \ 73 ((char *)a)[2] = ((char *)b)[3]; \ 74 ((char *)a)[3] = ((char *)b)[2] 75#endif 76 77static void 78CHIPSShowCursor(ScrnInfoPtr pScrn) 79{ 80 CHIPSPtr cPtr = CHIPSPTR(pScrn); 81 unsigned char tmp; 82 83 CURSOR_SYNC(pScrn); 84 85 /* turn the cursor on */ 86 if (IS_HiQV(cPtr)) { 87 tmp = cPtr->readXR(cPtr, 0xA0); 88 cPtr->writeXR(cPtr, 0xA0, (tmp & 0xF8) | 5); 89 if (cPtr->UseDualChannel && 90 (! xf86IsEntityShared(pScrn->entityList[0]))) { 91 unsigned int IOSS, MSS; 92 IOSS = cPtr->readIOSS(cPtr); 93 MSS = cPtr->readMSS(cPtr); 94 cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | 95 IOSS_PIPE_B)); 96 cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS & 97 MSS_MASK) | MSS_PIPE_B)); 98 tmp = cPtr->readXR(cPtr, 0xA0); 99 cPtr->writeXR(cPtr, 0xA0, (tmp & 0xF8) | 5); 100 cPtr->writeIOSS(cPtr, IOSS); 101 cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), MSS); 102 } 103 } else { 104 if(!cPtr->UseMMIO) { 105 HW_DEBUG(0x8); 106 outw(cPtr->PIOBase+DR(0x8), 0x21); 107 } else { 108 HW_DEBUG(DR(8)); 109 /* Used to be: MMIOmemw(MR(8)) = 0x21; */ 110 MMIOmeml(MR(8)) = 0x21; 111 } 112 } 113 cPtr->HWCursorShown = TRUE; 114} 115 116static void 117CHIPSHideCursor(ScrnInfoPtr pScrn) 118{ 119 CHIPSPtr cPtr = CHIPSPTR(pScrn); 120 unsigned char tmp; 121 122 CURSOR_SYNC(pScrn); 123 124 /* turn the cursor off */ 125 if (IS_HiQV(cPtr)) { 126 tmp = cPtr->readXR(cPtr, 0xA0); 127 cPtr->writeXR(cPtr, 0xA0, tmp & 0xF8); 128 if (cPtr->UseDualChannel && 129 (! xf86IsEntityShared(pScrn->entityList[0]))) { 130 unsigned int IOSS, MSS; 131 IOSS = cPtr->readIOSS(cPtr); 132 MSS = cPtr->readMSS(cPtr); 133 cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | 134 IOSS_PIPE_B)); 135 cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS & 136 MSS_MASK) | MSS_PIPE_B)); 137 tmp = cPtr->readXR(cPtr, 0xA0); 138 cPtr->writeXR(cPtr, 0xA0, tmp & 0xF8); 139 cPtr->writeIOSS(cPtr, IOSS); 140 cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), MSS); 141 } 142 } else { 143 if(!cPtr->UseMMIO) { 144 HW_DEBUG(0x8); 145 outw(cPtr->PIOBase+DR(0x8), 0x20); 146 } else { 147 HW_DEBUG(DR(0x8)); 148 /* Used to be: MMIOmemw(DR(0x8)) = 0x20; */ 149 MMIOmeml(DR(0x8)) = 0x20; 150 } 151 } 152 cPtr->HWCursorShown = FALSE; 153} 154 155static void 156CHIPSSetCursorPosition(ScrnInfoPtr pScrn, int x, int y) 157{ 158 CHIPSPtr cPtr = CHIPSPTR(pScrn); 159 160 CURSOR_SYNC(pScrn); 161 162 if (x < 0) 163 x = ~(x-1) | 0x8000; 164 if (y < 0) 165 y = ~(y-1) | 0x8000; 166 167 /* Program the cursor origin (offset into the cursor bitmap). */ 168 if (IS_HiQV(cPtr)) { 169 cPtr->writeXR(cPtr, 0xA4, x & 0xFF); 170 cPtr->writeXR(cPtr, 0xA5, (x >> 8) & 0x87); 171 cPtr->writeXR(cPtr, 0xA6, y & 0xFF); 172 cPtr->writeXR(cPtr, 0xA7, (y >> 8) & 0x87); 173 if (cPtr->UseDualChannel && 174 (! xf86IsEntityShared(pScrn->entityList[0]))) { 175 unsigned int IOSS, MSS; 176 IOSS = cPtr->readIOSS(cPtr); 177 MSS = cPtr->readMSS(cPtr); 178 cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | 179 IOSS_PIPE_B)); 180 cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS & 181 MSS_MASK) | MSS_PIPE_B)); 182 cPtr->writeXR(cPtr, 0xA4, x & 0xFF); 183 cPtr->writeXR(cPtr, 0xA5, (x >> 8) & 0x87); 184 cPtr->writeXR(cPtr, 0xA6, y & 0xFF); 185 cPtr->writeXR(cPtr, 0xA7, (y >> 8) & 0x87); 186 cPtr->writeIOSS(cPtr, IOSS); 187 cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), MSS); 188 } 189 } else { 190 CARD32 xy; 191 192 xy = y; 193 xy = (xy << 16) | x; 194 if(!cPtr->UseMMIO) { 195 HW_DEBUG(0xB); 196 outl(cPtr->PIOBase+DR(0xB), xy); 197 } else { 198 HW_DEBUG(MR(0xB)); 199 MMIOmeml(MR(0xB)) = xy; 200 } 201 } 202} 203 204static void 205CHIPSSetCursorColors(ScrnInfoPtr pScrn, int bg, int fg) 206{ 207 CHIPSPtr cPtr = CHIPSPTR(pScrn); 208 vgaHWPtr hwp = VGAHWPTR(pScrn); 209 CARD32 packedcolfg, packedcolbg; 210 211 CURSOR_SYNC(pScrn); 212 213 if (IS_HiQV(cPtr)) { 214 unsigned char xr80; 215 216 /* Enable extended palette addressing */ 217 xr80 = cPtr->readXR(cPtr, 0x80); 218 cPtr->writeXR(cPtr, 0x80, xr80 | 0x1); 219 220 /* Write the new colours to the extended VGA palette. Palette 221 * index is incremented after each write, so only write index 222 * once 223 */ 224 hwp->writeDacWriteAddr(hwp, 0x04); 225 if (xr80 & 0x80) { 226 /* 8bit DAC */ 227 hwp->writeDacData(hwp, (bg >> 16) & 0xFF); 228 hwp->writeDacData(hwp, (bg >> 8) & 0xFF); 229 hwp->writeDacData(hwp, bg & 0xFF); 230 hwp->writeDacData(hwp, (fg >> 16) & 0xFF); 231 hwp->writeDacData(hwp, (fg >> 8) & 0xFF); 232 hwp->writeDacData(hwp, fg & 0xFF); 233 } else { 234 /* 6bit DAC */ 235 hwp->writeDacData(hwp, (bg >> 18) & 0xFF); 236 hwp->writeDacData(hwp, (bg >> 10) & 0xFF); 237 hwp->writeDacData(hwp, (bg >> 2) & 0xFF); 238 hwp->writeDacData(hwp, (fg >> 18) & 0xFF); 239 hwp->writeDacData(hwp, (fg >> 10) & 0xFF); 240 hwp->writeDacData(hwp, (fg >> 2) & 0xFF); 241 } 242 /* Enable normal palette addressing */ 243 cPtr->writeXR(cPtr, 0x80, xr80); 244 245 if (cPtr->UseDualChannel && 246 (! xf86IsEntityShared(pScrn->entityList[0]))) { 247 unsigned int IOSS, MSS; 248 IOSS = cPtr->readIOSS(cPtr); 249 MSS = cPtr->readMSS(cPtr); 250 cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | 251 IOSS_PIPE_B)); 252 cPtr->writeMSS(cPtr, hwp, ((cPtr->storeMSS & MSS_MASK) | 253 MSS_PIPE_B)); 254 /* Enable extended palette addressing */ 255 xr80 = cPtr->readXR(cPtr, 0x80); 256 cPtr->writeXR(cPtr, 0x80, xr80 | 0x1); 257 258 /* Write the new colours to the extended VGA palette. Palette 259 * index is incremented after each write, so only write index 260 * once 261 */ 262 hwp->writeDacWriteAddr(hwp, 0x04); 263 if (xr80 & 0x80) { 264 /* 8bit DAC */ 265 hwp->writeDacData(hwp, (bg >> 16) & 0xFF); 266 hwp->writeDacData(hwp, (bg >> 8) & 0xFF); 267 hwp->writeDacData(hwp, bg & 0xFF); 268 hwp->writeDacData(hwp, (fg >> 16) & 0xFF); 269 hwp->writeDacData(hwp, (fg >> 8) & 0xFF); 270 hwp->writeDacData(hwp, fg & 0xFF); 271 } else { 272 /* 6bit DAC */ 273 hwp->writeDacData(hwp, (bg >> 18) & 0xFF); 274 hwp->writeDacData(hwp, (bg >> 10) & 0xFF); 275 hwp->writeDacData(hwp, (bg >> 2) & 0xFF); 276 hwp->writeDacData(hwp, (fg >> 18) & 0xFF); 277 hwp->writeDacData(hwp, (fg >> 10) & 0xFF); 278 hwp->writeDacData(hwp, (fg >> 2) & 0xFF); 279 } 280 /* Enable normal palette addressing */ 281 cPtr->writeXR(cPtr, 0x80, xr80); 282 cPtr->writeIOSS(cPtr, IOSS); 283 cPtr->writeMSS(cPtr, hwp, MSS); 284 } 285 } else if (IS_Wingine(cPtr)) { 286 outl(cPtr->PIOBase+DR(0xA), (bg & 0xFFFFFF)); 287 outl(cPtr->PIOBase+DR(0x9), (fg & 0xFFFFFF)); 288 } else { 289 packedcolfg = ((fg & 0xF80000) >> 8) | ((fg & 0xFC00) >> 5) 290 | ((fg & 0xF8) >> 3); 291 packedcolbg = ((bg & 0xF80000) >> 8) | ((bg & 0xFC00) >> 5) 292 | ((bg & 0xF8) >> 3); 293 packedcolfg = (packedcolfg << 16) | packedcolbg; 294 if(!cPtr->UseMMIO) { 295 HW_DEBUG(0x9); 296 outl(cPtr->PIOBase+DR(0x9), packedcolfg); 297 } else { 298 MMIOmeml(MR(0x9)) = packedcolfg; 299 HW_DEBUG(MR(0x9)); 300 } 301 } 302} 303 304static void 305CHIPSLoadCursorImage(ScrnInfoPtr pScrn, unsigned char *src) 306{ 307 CHIPSPtr cPtr = CHIPSPTR(pScrn); 308 CHIPSACLPtr cAcl = CHIPSACLPTR(pScrn); 309#if X_BYTE_ORDER == X_BIG_ENDIAN 310 CARD32 *s = (pointer)src; 311 CARD32 *d = (pointer)(cPtr->FbBase + cAcl->CursorAddress); 312 int y; 313#endif 314 315 CURSOR_SYNC(pScrn); 316 317 if (cPtr->cursorDelay) { 318 usleep(200000); 319 cPtr->cursorDelay = FALSE; 320 } 321 322 if (IS_Wingine(cPtr)) { 323 int i; 324 CARD32 *tmp = (CARD32 *)src; 325 326 outl(cPtr->PIOBase+DR(0x8),0x20); 327 for (i=0; i<64; i++) { 328 outl(cPtr->PIOBase+DR(0xC),*(CARD32 *)tmp); 329 tmp++; 330 } 331 } else { 332 if (cPtr->Flags & ChipsLinearSupport) { 333#if X_BYTE_ORDER == X_BIG_ENDIAN 334 /* On big endian machines we must flip our cursor image around. */ 335 switch(pScrn->bitsPerPixel >> 3) { 336 case 4: 337 case 3: 338#if 1 339 memcpy((unsigned char *)cPtr->FbBase + cAcl->CursorAddress, 340 src, cPtr->CursorInfoRec->MaxWidth * 341 cPtr->CursorInfoRec->MaxHeight / 4); 342#else 343 for (y = 0; y < 64; y++) { 344 P_SWAP32(d,s); 345 d++; s++; 346 P_SWAP32(d,s); 347 d++; s++; 348 P_SWAP32(d,s); 349 d++; s++; 350 P_SWAP32(d,s); 351 d++; s++; 352 } 353#endif 354 break; 355 case 2: 356 for (y = 0; y < 64; y++) { 357 P_SWAP16(d,s); 358 d++; s++; 359 P_SWAP16(d,s); 360 d++; s++; 361 P_SWAP16(d,s); 362 d++; s++; 363 P_SWAP16(d,s); 364 d++; s++; 365 } 366 break; 367 default: 368 for (y = 0; y < 64; y++) { 369 *d++ = *s++; 370 *d++ = *s++; 371 *d++ = *s++; 372 *d++ = *s++; 373 } 374 } 375#else 376 memcpy((unsigned char *)cPtr->FbBase + cAcl->CursorAddress, 377 src, cPtr->CursorInfoRec->MaxWidth * 378 cPtr->CursorInfoRec->MaxHeight / 4); 379#endif 380 } else { 381 /* 382 * The cursor can only be in the last 16K of video memory, 383 * which fits in the last banking window. 384 */ 385 if (IS_HiQV(cPtr)) 386 if (pScrn->bitsPerPixel < 8) 387 CHIPSHiQVSetReadWritePlanar(pScrn->pScreen, 388 (int)(cAcl->CursorAddress >> 16)); 389 else 390 CHIPSHiQVSetReadWrite(pScrn->pScreen, 391 (int)(cAcl->CursorAddress >> 16)); 392 else 393 if (pScrn->bitsPerPixel < 8) 394 CHIPSSetWritePlanar(pScrn->pScreen, 395 (int)(cAcl->CursorAddress >> 16)); 396 else 397 CHIPSSetWrite(pScrn->pScreen, 398 (int)(cAcl->CursorAddress >> 16)); 399 memcpy((unsigned char *)cPtr->FbBase + (cAcl->CursorAddress & 400 0xFFFF), src, cPtr->CursorInfoRec->MaxWidth * 401 cPtr->CursorInfoRec->MaxHeight / 4); 402 } 403 } 404 405 /* set cursor address here or we loose the cursor on video mode change */ 406 if (IS_HiQV(cPtr)) { 407 cPtr->writeXR(cPtr, 0xA2, (cAcl->CursorAddress >> 8) & 0xFF); 408 cPtr->writeXR(cPtr, 0xA3, (cAcl->CursorAddress >> 16) & 0x3F); 409 if (cPtr->UseDualChannel && 410 (! xf86IsEntityShared(pScrn->entityList[0]))) { 411 unsigned int IOSS, MSS; 412 IOSS = cPtr->readIOSS(cPtr); 413 MSS = cPtr->readMSS(cPtr); 414 cPtr->writeIOSS(cPtr, ((cPtr->storeIOSS & IOSS_MASK) | 415 IOSS_PIPE_B)); 416 cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), ((cPtr->storeMSS & 417 MSS_MASK) | MSS_PIPE_B)); 418 cPtr->writeXR(cPtr, 0xA2, (cAcl->CursorAddress >> 8) & 0xFF); 419 cPtr->writeXR(cPtr, 0xA3, (cAcl->CursorAddress >> 16) & 0x3F); 420 cPtr->writeIOSS(cPtr, IOSS); 421 cPtr->writeMSS(cPtr, VGAHWPTR(pScrn), MSS); 422 } 423 } else if (!IS_Wingine(cPtr)) { 424 if (!cPtr->UseMMIO) { 425 HW_DEBUG(0xC); 426 outl(cPtr->PIOBase+DR(0xC), cAcl->CursorAddress); 427 } else { 428 HW_DEBUG(MR(0xC)); 429 MMIOmeml(MR(0xC)) = cAcl->CursorAddress; 430 } 431 } 432} 433 434static Bool 435CHIPSUseHWCursor(ScreenPtr pScreen, CursorPtr pCurs) 436{ 437 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 438 CHIPSPtr cPtr = CHIPSPTR(pScrn); 439 440 return (((cPtr->Flags & ChipsHWCursor) != 0) 441 && !(pScrn->currentMode->Flags & V_DBLSCAN)); 442} 443 444Bool 445CHIPSCursorInit(ScreenPtr pScreen) 446{ 447 ScrnInfoPtr pScrn = xf86Screens[pScreen->myNum]; 448 CHIPSPtr cPtr = CHIPSPTR(pScrn); 449 xf86CursorInfoPtr infoPtr; 450 451 infoPtr = xf86CreateCursorInfoRec(); 452 if(!infoPtr) return FALSE; 453 454 cPtr->CursorInfoRec = infoPtr; 455 456 infoPtr->Flags = 457#if X_BYTE_ORDER == X_LITTLE_ENDIAN 458 HARDWARE_CURSOR_BIT_ORDER_MSBFIRST | 459#endif 460 HARDWARE_CURSOR_INVERT_MASK | 461 HARDWARE_CURSOR_SWAP_SOURCE_AND_MASK | 462 HARDWARE_CURSOR_TRUECOLOR_AT_8BPP; 463 464 if (IS_HiQV(cPtr)) { 465 infoPtr->Flags |= HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_64; 466 infoPtr->MaxHeight = 64; 467 infoPtr->MaxWidth = 64; 468 } else if (IS_Wingine(cPtr)) { 469 infoPtr->Flags |= HARDWARE_CURSOR_SOURCE_MASK_NOT_INTERLEAVED; 470 infoPtr->MaxHeight = 32; 471 infoPtr->MaxWidth = 32; 472 } else { 473 infoPtr->Flags |= HARDWARE_CURSOR_SOURCE_MASK_INTERLEAVE_8; 474 infoPtr->MaxHeight = 32; 475 infoPtr->MaxWidth = 32; 476 } 477 478 infoPtr->SetCursorColors = CHIPSSetCursorColors; 479 infoPtr->SetCursorPosition = CHIPSSetCursorPosition; 480 infoPtr->LoadCursorImage = CHIPSLoadCursorImage; 481 infoPtr->HideCursor = CHIPSHideCursor; 482 infoPtr->ShowCursor = CHIPSShowCursor; 483 infoPtr->UseHWCursor = CHIPSUseHWCursor; 484 485 return(xf86InitCursor(pScreen, infoPtr)); 486} 487 488