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