|
|
1.1 ! root 1: /******************************Module*Header*******************************\ ! 2: * Module Name: bank.c ! 3: * ! 4: * Functions to control 256 colour VGA banking. ! 5: * ! 6: * Copyright (c) 1992 Microsoft Corporation ! 7: \**************************************************************************/ ! 8: ! 9: #include "driver.h" ! 10: #include "limits.h" ! 11: ! 12: VOID vBankErrorTrap(PPDEV, LONG, BANK_JUST); ! 13: VOID vBank2Window(PPDEV, LONG, BANK_JUST, ULONG); ! 14: VOID vBank2Window2RW(PPDEV, LONG, BANK_JUST, ULONG); ! 15: VOID vBank2Window1RW(PPDEV, LONG, BANK_JUST, ULONG); ! 16: VOID vBank1Window2RW(PPDEV, LONG, BANK_JUST); ! 17: VOID vBank1Window(PPDEV, LONG, BANK_JUST); ! 18: VOID vPlanar2Window(PPDEV, LONG, BANK_JUST, ULONG); ! 19: VOID vPlanar2Window2RW(PPDEV, LONG, BANK_JUST, ULONG); ! 20: VOID vPlanar2Window1RW(PPDEV, LONG, BANK_JUST, ULONG); ! 21: VOID vPlanar1Window2RW(PPDEV, LONG, BANK_JUST); ! 22: VOID vPlanar1Window(PPDEV, LONG, BANK_JUST); ! 23: ! 24: /******************************Public*Routine******************************\ ! 25: * bInitializeNonPlanar(ppdev, pBankInfo) ! 26: * ! 27: * Initialize for non-planar mode banking. ! 28: * ! 29: * NOTE: Allocates ppdev->pbiBankInfo and ppdev->pjJustifyTopBank buffers! ! 30: \**************************************************************************/ ! 31: ! 32: BOOL bInitializeNonPlanar(PPDEV ppdev, VIDEO_BANK_SELECT* pBankInfo) ! 33: { ! 34: LONG lTotalScans; ! 35: LONG lTotalBanks; ! 36: ULONG cjBankSize; ! 37: ! 38: ULONG cjGranularity = pBankInfo->Granularity; ! 39: LONG lDelta = pBankInfo->BitmapWidthInBytes; ! 40: ULONG cjBitmapSize = pBankInfo->BitmapSize; ! 41: ! 42: ASSERTVGA(cjBitmapSize >= ppdev->cyScreen * lDelta, "Not enough vram"); ! 43: ! 44: // Set up for non-planar banking: ! 45: ! 46: ppdev->lNextScan = lDelta; ! 47: ppdev->vbtBankingType = pBankInfo->BankingType; ! 48: ! 49: ppdev->pfnBankSwitchCode = ! 50: (PFN) (((BYTE*)pBankInfo) + pBankInfo->CodeOffset); ! 51: ! 52: // Set all clip rects to invalid; they'll be updated when the first ! 53: // bank is mapped in ! 54: ! 55: ppdev->rcl1WindowClip.bottom = -1; ! 56: ppdev->rcl2WindowClip[0].bottom = -1; ! 57: ppdev->rcl2WindowClip[1].bottom = -1; ! 58: ! 59: // Set up to call the appropriate banking control routines ! 60: ! 61: switch(pBankInfo->BankingType) ! 62: { ! 63: case VideoBanked1RW: ! 64: ppdev->pfnBankControl = vBank1Window; ! 65: ppdev->pfnBankControl2Window = vBank2Window1RW; ! 66: break; ! 67: ! 68: case VideoBanked1R1W: ! 69: ppdev->pfnBankControl = vBank1Window; ! 70: ppdev->pfnBankControl2Window = vBank2Window; ! 71: break; ! 72: ! 73: case VideoBanked2RW: ! 74: ppdev->pfnBankControl = vBank1Window2RW; ! 75: ppdev->pfnBankControl2Window = vBank2Window2RW; ! 76: ! 77: // Offset from one bank index to next to make two 32k banks ! 78: // appear to be one seamless 64k bank: ! 79: ! 80: ppdev->ulBank2RWSkip = BANK_SIZE_2RW_WINDOW / cjGranularity; ! 81: break; ! 82: ! 83: default: ! 84: RIP("Bad BankingType"); ! 85: return(FALSE); ! 86: } ! 87: ! 88: // Set up the bank control tables with clip rects for banks ! 89: // Note: lTotalBanks is generally an overestimate when granularity ! 90: // is less than window size, because we ignore any banks after the ! 91: // first one that includes the last scan line of the bitmap. A bit ! 92: // of memory could be saved by sizing lTotalBanks exactly. Note too, ! 93: // though, that the 2 RW window case may require more entries then, ! 94: // because its windows are shorter, so you'd have to make sure there ! 95: // were enough entries for the 2 RW window case, or recalculate ! 96: // lTotalBanks for the 2 RW case ! 97: ! 98: lTotalBanks = cjBitmapSize / cjGranularity; ! 99: lTotalScans = cjBitmapSize / lDelta; ! 100: ! 101: ppdev->cTotalScans = lTotalScans; ! 102: ppdev->pbiBankInfo = (PBANK_INFO) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, ! 103: lTotalBanks * sizeof(BANK_INFO)); ! 104: if (ppdev->pbiBankInfo == NULL) ! 105: { ! 106: RIP("Couldn't get memory for bank info"); ! 107: return(FALSE); ! 108: } ! 109: ! 110: ppdev->pjJustifyTopBank = (BYTE*) LocalAlloc(LMEM_FIXED, lTotalScans); ! 111: if (ppdev->pjJustifyTopBank == NULL) ! 112: { ! 113: RIP("Couldn't get memory for JustifyTopBank table"); ! 114: return(FALSE); ! 115: } ! 116: ! 117: // For 2 RW windows, windows are assumed to be 32k in size, otherwise ! 118: // assumed to be 64k: ! 119: ! 120: if (pBankInfo->BankingType == VideoBanked2RW) ! 121: cjBankSize = BANK_SIZE_2RW_WINDOW; ! 122: else ! 123: cjBankSize = BANK_SIZE_1_WINDOW; ! 124: ! 125: if ((cjGranularity + lDelta) >= cjBankSize && ! 126: (cjGranularity % lDelta) != 0) ! 127: { ! 128: // Oh no, we've got broken rasters (where a scan line crosses ! 129: // a bank boundary): ! 130: ! 131: RIP("Oops, broken rasters not yet handled"); ! 132: return(FALSE); ! 133: } ! 134: else ! 135: { ! 136: // We now fill in the scan-to-bank look-up and bank tables: ! 137: ! 138: LONG iScan = 0; ! 139: ULONG iBank = 0; ! 140: ULONG cjScan = 0; ! 141: ULONG cjNextBank = cjGranularity; ! 142: ULONG cjEndOfBank = cjBankSize; ! 143: PBANK_INFO pbiWorking = ppdev->pbiBankInfo; ! 144: ! 145: while (TRUE) ! 146: { ! 147: pbiWorking->ulBankOffset = cjNextBank - cjGranularity; ! 148: ! 149: // There are no broken rasters, so don't worry about left and right ! 150: // edges: ! 151: ! 152: pbiWorking->rclBankBounds.left = LONG_MIN + 1; // +1 to avoid ! 153: // compiler warn ! 154: pbiWorking->rclBankBounds.right = LONG_MAX; ! 155: pbiWorking->rclBankBounds.top = iScan; ! 156: pbiWorking->rclBankBounds.bottom = iScan + ! 157: (cjEndOfBank - cjScan) / lDelta; ! 158: ! 159: // We don't need any more banks if we can see to the end ! 160: // of the bitmap with the current bank: ! 161: ! 162: if (cjScan + cjBankSize >= cjBitmapSize) ! 163: break; ! 164: ! 165: while (cjScan < cjNextBank) ! 166: { ! 167: ppdev->pjJustifyTopBank[iScan++] = (BYTE) iBank; ! 168: cjScan += lDelta; ! 169: } ! 170: ! 171: // Get ready for next bank: ! 172: ! 173: cjNextBank += cjGranularity; ! 174: cjEndOfBank += cjGranularity; ! 175: pbiWorking++; ! 176: iBank++; ! 177: } ! 178: ! 179: // Clean up the last scans: ! 180: ! 181: ppdev->iLastBank = iBank; ! 182: pbiWorking->rclBankBounds.bottom = lTotalScans; ! 183: while (iScan < lTotalScans) ! 184: { ! 185: ppdev->pjJustifyTopBank[iScan++] = (BYTE) iBank; ! 186: } ! 187: ! 188: // We've just computed the precise table for JustifyTop; we now ! 189: // compute the scan offset for determining JustifyBottom: ! 190: ! 191: ASSERTVGA(cjBankSize >= cjGranularity, ! 192: "Device says granularity more than bank size?"); ! 193: ! 194: ppdev->ulJustifyBottomOffset = (cjBankSize - cjGranularity) / lDelta; ! 195: ! 196: // ulJustifyBottomOffset must be less than the number of scans ! 197: // that fit entirely in any bank less the granularity size; if ! 198: // our width doesn't divide evenly into the granularity, we'll ! 199: // have to adjust the value to account for the first scan not ! 200: // starting at offset 0 in any bank: ! 201: ! 202: if ((cjGranularity % lDelta) != 0 && ppdev->ulJustifyBottomOffset > 0) ! 203: ppdev->ulJustifyBottomOffset--; ! 204: } ! 205: ! 206: return(TRUE); ! 207: } ! 208: ! 209: /******************************Public*Routine******************************\ ! 210: * bInitializePlanar(ppdev, pBankInfo) ! 211: * ! 212: * Initialize for non-planar mode banking. ! 213: * ! 214: * NOTE: Allocates ppdev->pbiPlanarInfo and ppdev->pjJustifyTopPlanar buffers! ! 215: \**************************************************************************/ ! 216: ! 217: BOOL bInitializePlanar(PPDEV ppdev, VIDEO_BANK_SELECT* pBankInfo) ! 218: { ! 219: LONG lTotalScans; ! 220: LONG lTotalBanks; ! 221: ULONG cjBankSize; ! 222: ULONG cjGranularity = pBankInfo->PlanarHCGranularity; ! 223: ! 224: // Since we're in planar mode, every byte we see actually represents ! 225: // four bytes of video memory: ! 226: ! 227: LONG lDelta = pBankInfo->BitmapWidthInBytes / 4; ! 228: ULONG cjBitmapSize = pBankInfo->BitmapSize / 4; ! 229: ! 230: ppdev->fl |= DRIVER_PLANAR_CAPABLE; ! 231: ! 232: // Set all clip rects to invalid; they'll be updated when the first ! 233: // bank is mapped in ! 234: ! 235: ppdev->rcl1PlanarClip.bottom = -1; ! 236: ppdev->rcl2PlanarClip[0].bottom = -1; ! 237: ppdev->rcl2PlanarClip[1].bottom = -1; ! 238: ! 239: // Set up for planar banking: ! 240: ! 241: ppdev->pfnPlanarSwitchCode = ! 242: (PFN) (((BYTE*)pBankInfo) + pBankInfo->PlanarHCBankCodeOffset); ! 243: ppdev->pfnPlanarEnable = ! 244: (PFN) (((BYTE*)pBankInfo) + pBankInfo->PlanarHCEnableCodeOffset); ! 245: ppdev->pfnPlanarDisable = ! 246: (PFN) (((BYTE*)pBankInfo) + pBankInfo->PlanarHCDisableCodeOffset); ! 247: ! 248: ppdev->lPlanarNextScan = lDelta; ! 249: ppdev->vbtPlanarType = pBankInfo->PlanarHCBankingType; ! 250: ! 251: // Set up to call the appropriate banking control routines ! 252: ! 253: switch(ppdev->vbtPlanarType) ! 254: { ! 255: case VideoBanked1RW: ! 256: ppdev->pfnPlanarControl = vPlanar1Window; ! 257: ppdev->pfnPlanarControl2 = vPlanar2Window1RW; ! 258: break; ! 259: ! 260: case VideoBanked1R1W: ! 261: ppdev->pfnPlanarControl = vPlanar1Window; ! 262: ppdev->pfnPlanarControl2 = vPlanar2Window; ! 263: break; ! 264: ! 265: case VideoBanked2RW: ! 266: ppdev->pfnPlanarControl = vPlanar1Window2RW; ! 267: ppdev->pfnPlanarControl2 = vPlanar2Window2RW; ! 268: ! 269: // Offset from one bank index to next to make two 32k banks ! 270: // appear to be one seamless 64k bank: ! 271: ! 272: ppdev->ulPlanar2RWSkip = BANK_SIZE_2RW_WINDOW / cjGranularity; ! 273: break; ! 274: ! 275: default: ! 276: RIP("Bad BankingType"); ! 277: return(FALSE); ! 278: } ! 279: ! 280: lTotalBanks = cjBitmapSize / cjGranularity; ! 281: lTotalScans = cjBitmapSize / lDelta; ! 282: ! 283: ppdev->pbiPlanarInfo = (PBANK_INFO) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, ! 284: lTotalBanks * sizeof(BANK_INFO)); ! 285: if (ppdev->pbiPlanarInfo == NULL) ! 286: { ! 287: RIP("Couldn't get memory for bank info"); ! 288: return(FALSE); ! 289: } ! 290: ! 291: ppdev->pjJustifyTopPlanar = (BYTE*) LocalAlloc(LMEM_FIXED, lTotalScans); ! 292: if (ppdev->pjJustifyTopPlanar == NULL) ! 293: { ! 294: RIP("Couldn't get memory for JustifyTopBank table"); ! 295: return(FALSE); ! 296: } ! 297: ! 298: // For 2 RW windows, windows are assumed to be 32k in size, otherwise ! 299: // assumed to be 64k: ! 300: ! 301: if (pBankInfo->BankingType == VideoBanked2RW) ! 302: cjBankSize = BANK_SIZE_2RW_WINDOW; ! 303: else ! 304: cjBankSize = BANK_SIZE_1_WINDOW; ! 305: ! 306: if ((cjGranularity + lDelta) >= cjBankSize && ! 307: (cjGranularity % lDelta) != 0) ! 308: { ! 309: // Oh no, we've got broken rasters (where a scan line crosses ! 310: // a bank boundary): ! 311: ! 312: DISPDBG((0, "Can't handle broken planar rasters")); ! 313: ! 314: ppdev->fl &= ~DRIVER_PLANAR_CAPABLE;// !!! Temporary, until we handle ! 315: return(TRUE); // broken rasters in planar copy ! 316: } ! 317: else ! 318: { ! 319: // We now fill in the scan-to-bank look-up and bank tables: ! 320: ! 321: LONG iScan = 0; ! 322: ULONG iBank = 0; ! 323: ULONG cjScan = 0; ! 324: ULONG cjNextBank = cjGranularity; ! 325: ULONG cjEndOfBank = cjBankSize; ! 326: PBANK_INFO pbiWorking = ppdev->pbiPlanarInfo; ! 327: ! 328: while (TRUE) ! 329: { ! 330: pbiWorking->ulBankOffset = cjNextBank - cjGranularity; ! 331: ! 332: // There are no broken rasters, so don't worry about left and right ! 333: // edges: ! 334: ! 335: pbiWorking->rclBankBounds.left = LONG_MIN + 1; // +1 to avoid ! 336: // compiler warn ! 337: pbiWorking->rclBankBounds.right = LONG_MAX; ! 338: pbiWorking->rclBankBounds.top = iScan; ! 339: pbiWorking->rclBankBounds.bottom = iScan + ! 340: (cjEndOfBank - cjScan) / lDelta; ! 341: ! 342: // We don't need any more banks if we can see to the end ! 343: // of the bitmap with the current bank: ! 344: ! 345: if (cjScan + cjBankSize >= cjBitmapSize) ! 346: break; ! 347: ! 348: while (cjScan < cjNextBank) ! 349: { ! 350: ppdev->pjJustifyTopPlanar[iScan++] = (BYTE) iBank; ! 351: cjScan += lDelta; ! 352: } ! 353: ! 354: // Get ready for next bank: ! 355: ! 356: cjNextBank += cjGranularity; ! 357: cjEndOfBank += cjGranularity; ! 358: pbiWorking++; ! 359: iBank++; ! 360: } ! 361: ! 362: // Clean up the last scans: ! 363: ! 364: ppdev->iLastPlanar = iBank; ! 365: pbiWorking->rclBankBounds.bottom = lTotalScans; ! 366: while (iScan < lTotalScans) ! 367: { ! 368: ppdev->pjJustifyTopPlanar[iScan++] = (BYTE) iBank; ! 369: } ! 370: ! 371: // We've just computed the precise table for JustifyTop; we now ! 372: // compute the scan offset for determining JustifyBottom: ! 373: ! 374: ASSERTVGA(cjBankSize >= cjGranularity, ! 375: "Device says granularity more than bank size?"); ! 376: ! 377: ppdev->ulPlanarBottomOffset = (cjBankSize - cjGranularity) / lDelta; ! 378: ! 379: // ulPlanarBottomOffset must be less than the number of scans ! 380: // that fit entirely in any bank less the granularity size; if ! 381: // our width doesn't divide evenly into the granularity, we'll ! 382: // have to adjust the value to account for the first scan not ! 383: // starting at offset 0 in any bank: ! 384: ! 385: if ((cjGranularity % lDelta) != 0 && ppdev->ulPlanarBottomOffset > 0) ! 386: ppdev->ulPlanarBottomOffset--; ! 387: } ! 388: ! 389: return(TRUE); ! 390: } ! 391: ! 392: /******************************Public*Routine******************************\ ! 393: * bEnableBanking(ppdev) ! 394: * ! 395: * Set up banking for the current mode ! 396: * pdsurf and ppdev are the pointers to the current surface and device ! 397: * Relevant fields in the surface are set up for banking ! 398: \**************************************************************************/ ! 399: ! 400: BOOL bEnableBanking(PPDEV ppdev) ! 401: { ! 402: PVIDEO_BANK_SELECT pBankInfo; ! 403: UINT ReturnedDataLength; ! 404: VIDEO_BANK_SELECT TempBankInfo; ! 405: ! 406: // Make sure we've set to NULL any pointers to buffers that we allocate, ! 407: // so that we can free them in our error path: ! 408: ! 409: ppdev->pBankInfo = NULL; ! 410: ppdev->pjJustifyTopBank = NULL; ! 411: ppdev->pbiBankInfo = NULL; ! 412: ppdev->pjJustifyTopPlanar = NULL; ! 413: ppdev->pbiPlanarInfo = NULL; ! 414: ! 415: // Query the miniport for banking info for this mode. ! 416: // ! 417: // First, figure out how big a buffer we need for the banking info ! 418: // (returned in TempBankInfo->Size). ! 419: ! 420: if (!DeviceIoControl(ppdev->hDriver, ! 421: IOCTL_VIDEO_GET_BANK_SELECT_CODE, ! 422: NULL, // input buffer ! 423: 0, ! 424: (LPVOID) &TempBankInfo, // output buffer ! 425: sizeof(VIDEO_BANK_SELECT), ! 426: &ReturnedDataLength, ! 427: NULL)) ! 428: { ! 429: // We expect this call to fail, because we didn't allow any room ! 430: // for the code; we just want to get the required output buffer ! 431: // size. Make sure we got the expected error, ERROR_MORE_DATA. ! 432: ! 433: if (GetLastError() != ERROR_MORE_DATA) ! 434: { ! 435: RIP("Initialization error-GetBankSelectCode, first call"); ! 436: goto error; ! 437: } ! 438: } ! 439: ! 440: // Now, allocate a buffer of the required size and get the banking info. ! 441: ! 442: pBankInfo = (PVIDEO_BANK_SELECT) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, ! 443: TempBankInfo.Size); ! 444: if (pBankInfo == NULL) ! 445: { ! 446: RIP("Initialization error-couldn't get memory for bank info"); ! 447: goto error; ! 448: } ! 449: ! 450: // Remember it so we can free it later: ! 451: ! 452: ppdev->pBankInfo = pBankInfo; ! 453: ! 454: if (!DeviceIoControl(ppdev->hDriver, ! 455: IOCTL_VIDEO_GET_BANK_SELECT_CODE, ! 456: NULL, ! 457: 0, ! 458: (LPVOID) pBankInfo, ! 459: TempBankInfo.Size, ! 460: &ReturnedDataLength, ! 461: NULL)) ! 462: { ! 463: RIP("Initialization error-GetBankSelectCode, second call"); ! 464: goto error; ! 465: } ! 466: ! 467: // Set up for banking: ! 468: ! 469: ppdev->ulBitmapSize = pBankInfo->BitmapSize; ! 470: ! 471: if (!bInitializeNonPlanar(ppdev, pBankInfo)) ! 472: goto error; ! 473: ! 474: if (pBankInfo->BankingFlags & PLANAR_HC) ! 475: { ! 476: ppdev->fl |= DRIVER_PLANAR_CAPABLE; ! 477: if (!bInitializePlanar(ppdev, pBankInfo)) ! 478: goto error; ! 479: } ! 480: ! 481: // Map in scan line 0 for read & write, to put things in a known state: ! 482: ! 483: ppdev->pfnBankControl(ppdev, 0, JustifyTop); ! 484: ! 485: return(TRUE); ! 486: ! 487: // Error path: ! 488: ! 489: error: ! 490: vDisableBanking(ppdev); ! 491: ! 492: return(FALSE); ! 493: } ! 494: ! 495: /******************************Public*Routine******************************\ ! 496: * vDisableBanking(ppdev) ! 497: * ! 498: * Disable banking for the current mode ! 499: \**************************************************************************/ ! 500: ! 501: VOID vDisableBanking(PPDEV ppdev) ! 502: { ! 503: LocalFree((LPVOID) ppdev->pBankInfo); ! 504: LocalFree((LPVOID) ppdev->pjJustifyTopBank); ! 505: LocalFree((LPVOID) ppdev->pbiBankInfo); ! 506: LocalFree((LPVOID) ppdev->pjJustifyTopPlanar); ! 507: LocalFree((LPVOID) ppdev->pbiPlanarInfo); ! 508: } ! 509: ! 510: /******************************Private*Routine******************************\ ! 511: * vBankErrorTrap ! 512: * ! 513: * Traps calls to bank control functions in non-banked modes ! 514: * ! 515: \**************************************************************************/ ! 516: ! 517: VOID vBankErrorTrap(PPDEV ppdev, LONG lScan, BANK_JUST ulJustification) ! 518: { ! 519: DISPDBG((0,"Call to bank manager in unbanked mode")); ! 520: } ! 521: ! 522: /******************************Private*Routine******************************\ ! 523: * vBank1Window ! 524: * ! 525: * Maps in a single R/W window that allows access to lScan. Applies to both ! 526: * 1 RW window and 1R1W window banking schemes. ! 527: * ! 528: \**************************************************************************/ ! 529: ! 530: VOID vBank1Window(PPDEV ppdev, LONG lScan, BANK_JUST ulJustification) ! 531: { ! 532: ULONG ulBank; ! 533: PBANK_INFO pbiWorking; ! 534: volatile ULONG ulBank0; ! 535: volatile PFN pBankFn; ! 536: ! 537: // ASM routines that call this may have STD in effect, but the C compiler ! 538: // assumes CLD ! 539: ! 540: _asm pushfd ! 541: _asm cld ! 542: ! 543: // Set the clip rect for this bank; if it's set to -1, that indicates that ! 544: // a double-window set-up is currently active, so invalidate double-window ! 545: // clip rects and display memory pointers (when double-window is active, ! 546: // single-window is inactive, and vice-versa; a full bank set-up has to be ! 547: // performed to switch between the two) ! 548: ! 549: if (ppdev->rcl1WindowClip.bottom == -1) ! 550: { ! 551: if (ppdev->flBank & BANK_PLANAR) ! 552: { ! 553: ppdev->flBank &= ~BANK_PLANAR; ! 554: ppdev->pfnPlanarDisable(); ! 555: } ! 556: ! 557: ppdev->rcl2WindowClip[0].bottom = -1; ! 558: ppdev->rcl2WindowClip[1].bottom = -1; ! 559: ppdev->rcl1PlanarClip.bottom = -1; ! 560: ppdev->rcl2PlanarClip[0].bottom = -1; ! 561: ppdev->rcl2PlanarClip[1].bottom = -1; ! 562: } ! 563: ! 564: ASSERTVGA(!(ppdev->flBank & BANK_PLANAR), "Shouldn't be in planar mode"); ! 565: ! 566: // Find the bank containing the scan line with the desired justification: ! 567: ! 568: { ! 569: register LONG lSearchScan = lScan; ! 570: if (ulJustification == JustifyBottom) ! 571: { ! 572: lSearchScan -= ppdev->ulJustifyBottomOffset; ! 573: if (lSearchScan <= 0) ! 574: lSearchScan = 0; ! 575: } ! 576: ! 577: ulBank = (ULONG) ppdev->pjJustifyTopBank[lSearchScan]; ! 578: pbiWorking = &ppdev->pbiBankInfo[ulBank]; ! 579: } ! 580: ! 581: ASSERTVGA(pbiWorking->rclBankBounds.top <= lScan && ! 582: pbiWorking->rclBankBounds.bottom > lScan, ! 583: "Oops, scan not in bank"); ! 584: ! 585: ppdev->rcl1WindowClip = pbiWorking->rclBankBounds; ! 586: ! 587: // Shift the bitmap start address so that the desired bank aligns with ! 588: // the banking window. The source and destination are set only so 1 R/W ! 589: // aligned blits will work without having to be specifically aware of ! 590: // the adapter type (some of the same code works with 1R/1W adapters too). ! 591: ! 592: ppdev->pvBitmapStart = (PVOID) (ppdev->pjScreen - pbiWorking->ulBankOffset); ! 593: ppdev->pvBitmapStart2Window[0] = ppdev->pvBitmapStart; ! 594: ppdev->pvBitmapStart2Window[1] = ppdev->pvBitmapStart; ! 595: ! 596: ppdev->flBank &= ~BANK_BROKEN_RASTERS; // No broken rasters ! 597: ! 598: // Map in the desired bank for both read and write ! 599: // This is so convoluted to avoid problems with wiping out registers C ! 600: // thinks it's still using; the values are tranferred to volatiles, and ! 601: // then to registers ! 602: ! 603: ulBank0 = ulBank; ! 604: pBankFn = ppdev->pfnBankSwitchCode; ! 605: ! 606: _asm mov eax,ulBank0; ! 607: _asm mov edx,eax; ! 608: pBankFn(); // actually switch the banks ! 609: ! 610: _asm popfd ! 611: } ! 612: ! 613: /******************************Private*Routine******************************\ ! 614: * vBank1Window2RW ! 615: * ! 616: * Maps in two 32K RW windows so that they form a single 64K R/W window that ! 617: * allows access to lScan. Applies only to 2 RW window schemes. ! 618: * ! 619: \**************************************************************************/ ! 620: ! 621: VOID vBank1Window2RW(PPDEV ppdev, LONG lScan, BANK_JUST ulJustification) ! 622: { ! 623: ULONG ulBank0; ! 624: ULONG ulBank1; ! 625: volatile PFN pBankFn; ! 626: ! 627: // ASM routines that call this may have STD in effect, but the C compiler ! 628: // assumes CLD ! 629: ! 630: _asm pushfd ! 631: _asm cld ! 632: ! 633: // Set the clip rect for this bank; if it's set to -1, that indicates that ! 634: // a double-window set-up is currently active, so invalidate double-window ! 635: // clip rects and display memory pointers (when double-window is active, ! 636: // single-window is inactive, and vice-versa; a full bank set-up has to be ! 637: // performed to switch between the two) ! 638: ! 639: if (ppdev->rcl1WindowClip.bottom == -1) ! 640: { ! 641: if (ppdev->flBank & BANK_PLANAR) ! 642: { ! 643: ppdev->flBank &= ~BANK_PLANAR; ! 644: ppdev->pfnPlanarDisable(); ! 645: } ! 646: ! 647: ppdev->rcl2WindowClip[0].bottom = -1; ! 648: ppdev->rcl2WindowClip[1].bottom = -1; ! 649: ppdev->rcl1PlanarClip.bottom = -1; ! 650: ppdev->rcl2PlanarClip[0].bottom = -1; ! 651: ppdev->rcl2PlanarClip[1].bottom = -1; ! 652: } ! 653: ! 654: ASSERTVGA(!(ppdev->flBank & BANK_PLANAR), "Shouldn't be in planar mode"); ! 655: ! 656: // Find the bank containing the scan line with the desired justification: ! 657: ! 658: if (ulJustification == JustifyTop) ! 659: { ! 660: ulBank0 = ppdev->pjJustifyTopBank[lScan]; ! 661: ulBank1 = ulBank0 + ppdev->ulBank2RWSkip; ! 662: if (ulBank1 >= ppdev->iLastBank) ! 663: { ! 664: ulBank1 = ppdev->iLastBank; ! 665: ulBank0 = ulBank1 - ppdev->ulBank2RWSkip; ! 666: } ! 667: } ! 668: else ! 669: { ! 670: lScan -= ppdev->ulJustifyBottomOffset; ! 671: if (lScan <= 0) ! 672: lScan = 0; ! 673: ! 674: ulBank1 = ppdev->pjJustifyTopBank[lScan]; ! 675: ulBank0 = ulBank1 - ppdev->ulBank2RWSkip; ! 676: if ((LONG) ulBank0 < 0) ! 677: { ! 678: ulBank0 = 0; ! 679: ulBank1 = ppdev->ulBank2RWSkip; ! 680: } ! 681: } ! 682: ! 683: ppdev->rcl1WindowClip.left = ppdev->pbiBankInfo[ulBank0].rclBankBounds.left; ! 684: ppdev->rcl1WindowClip.top = ppdev->pbiBankInfo[ulBank0].rclBankBounds.top; ! 685: ppdev->rcl1WindowClip.bottom = ppdev->pbiBankInfo[ulBank1].rclBankBounds.bottom; ! 686: ppdev->rcl1WindowClip.right = ppdev->pbiBankInfo[ulBank1].rclBankBounds.right; ! 687: ! 688: // Shift the bitmap start address so that the desired bank aligns with ! 689: // the banking window. The source and destination are set only so 1 R/W ! 690: // aligned blits will work without having to be specifically aware of ! 691: // the adapter type (some of the same code works with 1R/1W adapters too). ! 692: ! 693: ppdev->pvBitmapStart = (PVOID) ((BYTE*)ppdev->pjScreen ! 694: - ppdev->pbiBankInfo[ulBank0].ulBankOffset); ! 695: ! 696: ppdev->pvBitmapStart2Window[0] = ppdev->pvBitmapStart; ! 697: ppdev->pvBitmapStart2Window[1] = ppdev->pvBitmapStart; ! 698: ! 699: ppdev->flBank &= ~BANK_BROKEN_RASTERS; // No broken rasters ! 700: ! 701: // Map in the desired bank for both read and write; this is accomplished ! 702: // by mapping in the desired 32K bank, followed by the next 32K bank. ! 703: // This is so convoluted to avoid problems with wiping out registers C ! 704: // thinks it's still using; the values are tranferred to volatiles, and ! 705: // then to registers ! 706: ! 707: pBankFn = ppdev->pfnBankSwitchCode; ! 708: ! 709: _asm mov eax,ulBank0; ! 710: _asm mov edx,ulBank1; ! 711: pBankFn(); // actually switch the banks ! 712: ! 713: _asm popfd; ! 714: } ! 715: ! 716: /******************************Private*Routine******************************\ ! 717: * vBank2Window ! 718: * ! 719: * Maps in one of two windows, either the source window (window 0) or the dest ! 720: * window (window 1), to allows access to lScan. Applies to 1R1W window ! 721: * banking scheme; should never be called for 1 RW window schemes, because ! 722: * there's only one window in that case. ! 723: * ! 724: \**************************************************************************/ ! 725: ! 726: VOID vBank2Window( ! 727: PPDEV ppdev, ! 728: LONG lScan, ! 729: BANK_JUST ulJustification, ! 730: ULONG ulWindowToMap) ! 731: { ! 732: ULONG ulBank; ! 733: PBANK_INFO pbiWorking; ! 734: volatile ULONG ulBank0; ! 735: volatile ULONG ulBank1; ! 736: volatile PFN pBankFn; ! 737: ! 738: // ASM routines that call this may have STD in effect, but the C compiler ! 739: // assumes CLD ! 740: ! 741: _asm pushfd ! 742: _asm cld ! 743: ! 744: // Find the bank containing the scan line with the desired justification: ! 745: ! 746: if (ulJustification == JustifyBottom) ! 747: { ! 748: lScan -= ppdev->ulJustifyBottomOffset; ! 749: if (lScan <= 0) ! 750: lScan = 0; ! 751: } ! 752: ! 753: ulBank = (ULONG) ppdev->pjJustifyTopBank[lScan]; ! 754: pbiWorking = &ppdev->pbiBankInfo[ulBank]; ! 755: ! 756: // Set the clip rect for this bank; if it's set to -1, that indicates that ! 757: // a single-window set-up is currently active, so invalidate single-window ! 758: // clip rects and display memory pointers (when double-window is active, ! 759: // single-window is inactive, and vice-versa; a full bank set-up has to be ! 760: // performed to switch between the two) ! 761: ! 762: if (ppdev->rcl2WindowClip[ulWindowToMap].bottom == -1) ! 763: { ! 764: ULONG ulOtherWindow = ulWindowToMap ^ 1; ! 765: ! 766: if (ppdev->flBank & BANK_PLANAR) ! 767: { ! 768: ppdev->flBank &= ~BANK_PLANAR; ! 769: ppdev->pfnPlanarDisable(); ! 770: } ! 771: ! 772: ppdev->rcl1WindowClip.bottom = -1; ! 773: ppdev->rcl1PlanarClip.bottom = -1; ! 774: ppdev->rcl2PlanarClip[0].bottom = -1; ! 775: ppdev->rcl2PlanarClip[1].bottom = -1; ! 776: ! 777: // Neither of the 2 window windows was active, so we have to set up the ! 778: // variables for the other bank (the one other than the one we were ! 779: // called to set) as well, to make it valid. The other bank is set to ! 780: // the same state as the bank we were called to set ! 781: ! 782: ppdev->rcl2WindowClip[ulOtherWindow] = pbiWorking->rclBankBounds; ! 783: ppdev->ulWindowBank[ulOtherWindow] = ulBank; ! 784: ppdev->pvBitmapStart2Window[ulOtherWindow] = ! 785: (PVOID) ((BYTE*)ppdev->pjScreen - pbiWorking->ulBankOffset); ! 786: } ! 787: ! 788: ASSERTVGA(!(ppdev->flBank & BANK_PLANAR), "Shouldn't be in planar mode"); ! 789: ! 790: ppdev->rcl2WindowClip[ulWindowToMap] = pbiWorking->rclBankBounds; ! 791: ! 792: // Shift the bitmap start address so that the desired bank aligns with the ! 793: // banking window ! 794: ! 795: ppdev->pvBitmapStart2Window[ulWindowToMap] = ! 796: (PVOID) ((UCHAR *)ppdev->pjScreen - pbiWorking->ulBankOffset); ! 797: ! 798: // Map in the desired bank; also map in the other bank to whatever its ! 799: // current state is ! 800: ! 801: ppdev->ulWindowBank[ulWindowToMap] = ulBank; ! 802: ! 803: ppdev->flBank &= ~BANK_BROKEN_RASTERS; // No broken rasters ! 804: ! 805: // Set both banks at once, because we may have just initialized the other ! 806: // bank, and because this way the bank switch code doesn't have to do a ! 807: // read before write to obtain the state of the other bank. ! 808: // This is so convoluted to avoid problems with wiping out registers C ! 809: // thinks it's still using; the values are tranferred to volatiles, and ! 810: // then to registers ! 811: ! 812: ! 813: ulBank0 = ppdev->ulWindowBank[0]; ! 814: ulBank1 = ppdev->ulWindowBank[1]; ! 815: pBankFn = ppdev->pfnBankSwitchCode; ! 816: ! 817: _asm mov eax,ulBank0; ! 818: _asm mov edx,ulBank1; ! 819: pBankFn(); // actually switch the banks ! 820: ! 821: _asm popfd; ! 822: } ! 823: ! 824: /******************************Private*Routine******************************\ ! 825: * vBank2Window1RW ! 826: * ! 827: * Maps in the one window in 1R/W case. Does exactly the same thing as the ! 828: * one window case, because there's only one window, but has to be a separate ! 829: * entry point because of the extra parameter (because we're using STDCALL). ! 830: \**************************************************************************/ ! 831: ! 832: VOID vBank2Window1RW(PPDEV ppdev, LONG lScan, ! 833: BANK_JUST ulJustification, ULONG ulWindowToMap) ! 834: { ! 835: vBank1Window(ppdev, lScan, ulJustification); ! 836: } ! 837: ! 838: /******************************Private*Routine******************************\ ! 839: * vBank2Window2RW ! 840: * ! 841: * Maps in one of two windows, either the source window (window 0) or the dest ! 842: * window (window 1), to allows access to lScan. Applies to 2RW window ! 843: * banking scheme; should never be called for 1 RW window schemes, because ! 844: * there's only one window in that case. ! 845: \**************************************************************************/ ! 846: ! 847: VOID vBank2Window2RW( ! 848: PPDEV ppdev, ! 849: LONG lScan, ! 850: BANK_JUST ulJustification, ! 851: ULONG ulWindowToMap) ! 852: { ! 853: ULONG ulBank; ! 854: PBANK_INFO pbiWorking; ! 855: volatile ULONG ulBank0; ! 856: volatile ULONG ulBank1; ! 857: volatile PFN pBankFn; ! 858: ! 859: // ASM routines that call this may have STD in effect, but the C compiler ! 860: // assumes CLD ! 861: ! 862: _asm pushfd ! 863: _asm cld ! 864: ! 865: // Find the bank containing the scan line with the desired justification: ! 866: ! 867: if (ulJustification == JustifyBottom) ! 868: { ! 869: lScan -= ppdev->ulJustifyBottomOffset; ! 870: if (lScan <= 0) ! 871: lScan = 0; ! 872: } ! 873: ! 874: ulBank = (ULONG) ppdev->pjJustifyTopBank[lScan]; ! 875: pbiWorking = &ppdev->pbiBankInfo[ulBank]; ! 876: ! 877: // Set the clip rect for this bank; if it's set to -1, that indicates that ! 878: // a single-window set-up is currently active, so invalidate single-window ! 879: // clip rects and display memory pointers (when double-window is active, ! 880: // single-window is inactive, and vice-versa; a full bank set-up has to be ! 881: // performed to switch between the two) ! 882: ! 883: if (ppdev->rcl2WindowClip[ulWindowToMap].bottom == -1) ! 884: { ! 885: if (ppdev->flBank & BANK_PLANAR) ! 886: { ! 887: ppdev->flBank &= ~BANK_PLANAR; ! 888: ppdev->pfnPlanarDisable(); ! 889: } ! 890: ! 891: ppdev->rcl1WindowClip.bottom = -1; ! 892: ppdev->rcl1PlanarClip.bottom = -1; ! 893: ppdev->rcl2PlanarClip[0].bottom = -1; ! 894: ppdev->rcl2PlanarClip[1].bottom = -1; ! 895: ! 896: // Neither of the 2 window windows was active, so we have to set up the ! 897: // variables for the other bank (the one other than the one we were ! 898: // called to set) as well, to make it valid. The other bank is set to ! 899: // the same state as the bank we were called to set ! 900: ! 901: ppdev->rcl2WindowClip[ulWindowToMap^1] = pbiWorking->rclBankBounds; ! 902: if (ulWindowToMap == 1) ! 903: { ! 904: ppdev->pvBitmapStart2Window[0] = ! 905: (PVOID) ((BYTE*)ppdev->pjScreen - pbiWorking->ulBankOffset); ! 906: } ! 907: else ! 908: { ! 909: ppdev->pvBitmapStart2Window[1] = ! 910: (PVOID) ((UCHAR *)ppdev->pjScreen - pbiWorking->ulBankOffset + ! 911: BANK_SIZE_2RW_WINDOW); ! 912: } ! 913: ppdev->ulWindowBank[ulWindowToMap^1] = ulBank; ! 914: } ! 915: ! 916: ASSERTVGA(!(ppdev->flBank & BANK_PLANAR), "Shouldn't be in planar mode"); ! 917: ! 918: ppdev->rcl2WindowClip[ulWindowToMap] = pbiWorking->rclBankBounds; ! 919: ! 920: // Shift the bitmap start address so that the desired bank aligns with the ! 921: // banking window ! 922: ! 923: if (ulWindowToMap == 0) ! 924: { ! 925: ppdev->pvBitmapStart2Window[0] = ! 926: (PVOID) ((UCHAR *)ppdev->pjScreen - pbiWorking->ulBankOffset); ! 927: } ! 928: else ! 929: { ! 930: ppdev->pvBitmapStart2Window[1] = ! 931: (PVOID) ((UCHAR *)ppdev->pjScreen - pbiWorking->ulBankOffset + ! 932: BANK_SIZE_2RW_WINDOW); ! 933: } ! 934: ! 935: ppdev->flBank &= ~BANK_BROKEN_RASTERS; // No broken rasters ! 936: ! 937: // Map in the desired bank; also map in the other bank to whatever its ! 938: // current state is ! 939: ! 940: ppdev->ulWindowBank[ulWindowToMap] = ulBank; ! 941: ! 942: // Set both banks at once, because we may have just initialized the other ! 943: // bank, and because this way the bank switch code doesn't have to do a ! 944: // read before write to obtain the state of the other bank. ! 945: // This is so convoluted to avoid problems with wiping out registers C ! 946: // thinks it's still using; the values are tranferred to volatiles, and ! 947: // then to registers ! 948: ! 949: ulBank0 = ppdev->ulWindowBank[0]; ! 950: ulBank1 = ppdev->ulWindowBank[1]; ! 951: pBankFn = ppdev->pfnBankSwitchCode; ! 952: _asm mov eax,ulBank0; ! 953: _asm mov edx,ulBank1; ! 954: pBankFn(); // actually switch the banks ! 955: ! 956: _asm popfd; ! 957: } ! 958: ! 959: /******************************Private*Routine******************************\ ! 960: * vPlanar1Window ! 961: * ! 962: * Maps in a single R/W window that allows access to lScan. Applies to both ! 963: * 1 RW window and 1R1W window banking schemes. ! 964: \**************************************************************************/ ! 965: ! 966: VOID vPlanar1Window(PPDEV ppdev, LONG lScan, BANK_JUST ulJustification) ! 967: { ! 968: ULONG ulBank; ! 969: PBANK_INFO pbiWorking; ! 970: volatile ULONG ulBank0; ! 971: volatile PFN pBankFn; ! 972: ! 973: // ASM routines that call this may have STD in effect, but the C compiler ! 974: // assumes CLD ! 975: ! 976: _asm pushfd ! 977: _asm cld ! 978: ! 979: // Set the clip rect for this bank; if it's set to -1, that indicates that ! 980: // a double-window set-up is currently active, so invalidate double-window ! 981: // clip rects and display memory pointers (when double-window is active, ! 982: // single-window is inactive, and vice-versa; a full bank set-up has to be ! 983: // performed to switch between the two) ! 984: ! 985: if (ppdev->rcl1PlanarClip.bottom == -1) ! 986: { ! 987: if (!(ppdev->flBank & BANK_PLANAR)) ! 988: { ! 989: ppdev->flBank |= BANK_PLANAR; ! 990: ppdev->pfnPlanarEnable(); ! 991: } ! 992: ! 993: ppdev->rcl1WindowClip.bottom = -1; ! 994: ppdev->rcl2WindowClip[0].bottom = -1; ! 995: ppdev->rcl2WindowClip[1].bottom = -1; ! 996: ppdev->rcl2PlanarClip[0].bottom = -1; ! 997: ppdev->rcl2PlanarClip[1].bottom = -1; ! 998: } ! 999: ! 1000: ASSERTVGA(ppdev->flBank & BANK_PLANAR, "Should be in planar mode"); ! 1001: ! 1002: // Find the bank containing the scan line with the desired justification: ! 1003: ! 1004: if (ulJustification == JustifyBottom) ! 1005: { ! 1006: lScan -= ppdev->ulPlanarBottomOffset; ! 1007: if (lScan <= 0) ! 1008: lScan = 0; ! 1009: } ! 1010: ! 1011: ulBank = (ULONG) ppdev->pjJustifyTopPlanar[lScan]; ! 1012: pbiWorking = &ppdev->pbiPlanarInfo[ulBank]; ! 1013: ! 1014: ppdev->rcl1PlanarClip = pbiWorking->rclBankBounds; ! 1015: ! 1016: // Shift the bitmap start address so that the desired bank aligns with ! 1017: // the banking window. The source and destination are set only so 1 R/W ! 1018: // aligned blits will work without having to be specifically aware of ! 1019: // the adapter type (some of the same code works with 1R/1W adapters too). ! 1020: ! 1021: ppdev->pvBitmapStart = (PVOID) (ppdev->pjScreen - pbiWorking->ulBankOffset); ! 1022: ppdev->pvBitmapStart2Window[0] = ppdev->pvBitmapStart; ! 1023: ppdev->pvBitmapStart2Window[1] = ppdev->pvBitmapStart; ! 1024: ! 1025: ppdev->flBank &= ~BANK_BROKEN_RASTERS; // No broken rasters ! 1026: ! 1027: // Map in the desired bank for both read and write ! 1028: // This is so convoluted to avoid problems with wiping out registers C ! 1029: // thinks it's still using; the values are tranferred to volatiles, and ! 1030: // then to registers ! 1031: ! 1032: ulBank0 = ulBank; ! 1033: pBankFn = ppdev->pfnPlanarSwitchCode; ! 1034: ! 1035: _asm mov eax,ulBank0; ! 1036: _asm mov edx,eax; ! 1037: pBankFn(); // actually switch the banks ! 1038: ! 1039: _asm popfd ! 1040: } ! 1041: ! 1042: /******************************Private*Routine******************************\ ! 1043: * vPlanar1Window2RW ! 1044: * ! 1045: * Maps in two 32K RW windows so that they form a single 64K R/W window that ! 1046: * allows access to lScan. Applies only to 2 RW window schemes. ! 1047: * ! 1048: \**************************************************************************/ ! 1049: ! 1050: VOID vPlanar1Window2RW(PPDEV ppdev, LONG lScan, BANK_JUST ulJustification) ! 1051: { ! 1052: ULONG ulBank0; ! 1053: ULONG ulBank1; ! 1054: volatile PFN pBankFn; ! 1055: ! 1056: // ASM routines that call this may have STD in effect, but the C compiler ! 1057: // assumes CLD ! 1058: ! 1059: _asm pushfd ! 1060: _asm cld ! 1061: ! 1062: // Set the clip rect for this bank; if it's set to -1, that indicates that ! 1063: // a double-window set-up is currently active, so invalidate double-window ! 1064: // clip rects and display memory pointers (when double-window is active, ! 1065: // single-window is inactive, and vice-versa; a full bank set-up has to be ! 1066: // performed to switch between the two) ! 1067: ! 1068: ! 1069: if (ppdev->rcl1PlanarClip.bottom == -1) ! 1070: { ! 1071: if (!(ppdev->flBank & BANK_PLANAR)) ! 1072: { ! 1073: ppdev->flBank |= BANK_PLANAR; ! 1074: ppdev->pfnPlanarEnable(); ! 1075: } ! 1076: ! 1077: ppdev->rcl1WindowClip.bottom = -1; ! 1078: ppdev->rcl2WindowClip[0].bottom = -1; ! 1079: ppdev->rcl2WindowClip[1].bottom = -1; ! 1080: ppdev->rcl2PlanarClip[0].bottom = -1; ! 1081: ppdev->rcl2PlanarClip[1].bottom = -1; ! 1082: } ! 1083: ! 1084: ASSERTVGA(ppdev->flBank & BANK_PLANAR, "Should be in planar mode"); ! 1085: ! 1086: // Find the bank containing the scan line with the desired justification: ! 1087: ! 1088: if (ulJustification == JustifyTop) ! 1089: { ! 1090: ulBank0 = ppdev->pjJustifyTopPlanar[lScan]; ! 1091: ulBank1 = ulBank0 + ppdev->ulPlanar2RWSkip; ! 1092: if (ulBank1 >= ppdev->iLastPlanar) ! 1093: ulBank1 = ppdev->iLastPlanar; ! 1094: } ! 1095: else ! 1096: { ! 1097: lScan -= ppdev->ulPlanarBottomOffset; ! 1098: if (lScan <= 0) ! 1099: lScan = 0; ! 1100: ! 1101: ulBank1 = ppdev->pjJustifyTopPlanar[lScan]; ! 1102: ulBank0 = ulBank1 - ppdev->ulPlanar2RWSkip; ! 1103: if ((LONG) ulBank0 < 0) ! 1104: ulBank0 = 0; ! 1105: } ! 1106: ! 1107: ppdev->rcl1PlanarClip.left = ppdev->pbiPlanarInfo[ulBank0].rclBankBounds.left; ! 1108: ppdev->rcl1PlanarClip.top = ppdev->pbiPlanarInfo[ulBank0].rclBankBounds.top; ! 1109: ppdev->rcl1PlanarClip.bottom = ppdev->pbiPlanarInfo[ulBank1].rclBankBounds.bottom; ! 1110: ppdev->rcl1PlanarClip.right = ppdev->pbiPlanarInfo[ulBank1].rclBankBounds.right; ! 1111: ! 1112: // Shift the bitmap start address so that the desired bank aligns with ! 1113: // the banking window. The source and destination are set only so 1 R/W ! 1114: // aligned blits will work without having to be specifically aware of ! 1115: // the adapter type (some of the same code works with 1R/1W adapters too). ! 1116: ! 1117: ppdev->pvBitmapStart = (PVOID) ((BYTE*)ppdev->pjScreen ! 1118: - ppdev->pbiPlanarInfo[ulBank0].ulBankOffset); ! 1119: ! 1120: ppdev->pvBitmapStart2Window[0] = ppdev->pvBitmapStart; ! 1121: ppdev->pvBitmapStart2Window[1] = ppdev->pvBitmapStart; ! 1122: ! 1123: ppdev->flBank &= ~BANK_BROKEN_RASTERS; // No broken rasters ! 1124: ! 1125: // Map in the desired bank for both read and write; this is accomplished ! 1126: // by mapping in the desired 32K bank, followed by the next 32K bank. ! 1127: // This is so convoluted to avoid problems with wiping out registers C ! 1128: // thinks it's still using; the values are tranferred to volatiles, and ! 1129: // then to registers ! 1130: ! 1131: pBankFn = ppdev->pfnPlanarSwitchCode; ! 1132: ! 1133: _asm mov eax,ulBank0; ! 1134: _asm mov edx,ulBank1; ! 1135: pBankFn(); // actually switch the banks ! 1136: ! 1137: _asm popfd; ! 1138: } ! 1139: ! 1140: /******************************Private*Routine******************************\ ! 1141: * vPlanar2Window ! 1142: * ! 1143: * Maps in one of two windows, either the source window (window 0) or the dest ! 1144: * window (window 1), to allows access to lScan. Applies to 1R1W window ! 1145: * banking scheme; should never be called for 1 RW window schemes, because ! 1146: * there's only one window in that case. ! 1147: * ! 1148: \**************************************************************************/ ! 1149: ! 1150: VOID vPlanar2Window( ! 1151: PPDEV ppdev, ! 1152: LONG lScan, ! 1153: BANK_JUST ulJustification, ! 1154: ULONG ulWindowToMap) ! 1155: { ! 1156: ULONG ulBank; ! 1157: PBANK_INFO pbiWorking; ! 1158: volatile ULONG ulBank0; ! 1159: volatile ULONG ulBank1; ! 1160: volatile PFN pBankFn; ! 1161: ! 1162: // ASM routines that call this may have STD in effect, but the C compiler ! 1163: // assumes CLD ! 1164: ! 1165: _asm pushfd ! 1166: _asm cld ! 1167: ! 1168: // Find the bank containing the scan line with the desired justification: ! 1169: ! 1170: if (ulJustification == JustifyBottom) ! 1171: { ! 1172: lScan -= ppdev->ulPlanarBottomOffset; ! 1173: if (lScan <= 0) ! 1174: lScan = 0; ! 1175: } ! 1176: ! 1177: ulBank = (ULONG) ppdev->pjJustifyTopPlanar[lScan]; ! 1178: pbiWorking = &ppdev->pbiPlanarInfo[ulBank]; ! 1179: ! 1180: // Set the clip rect for this bank; if it's set to -1, that indicates that ! 1181: // a single-window set-up is currently active, so invalidate single-window ! 1182: // clip rects and display memory pointers (when double-window is active, ! 1183: // single-window is inactive, and vice-versa; a full bank set-up has to be ! 1184: // performed to switch between the two) ! 1185: ! 1186: if (ppdev->rcl2PlanarClip[ulWindowToMap].bottom == -1) ! 1187: { ! 1188: ULONG ulOtherWindow = ulWindowToMap ^ 1; ! 1189: ! 1190: if (!(ppdev->flBank & BANK_PLANAR)) ! 1191: { ! 1192: ppdev->flBank |= BANK_PLANAR; ! 1193: ppdev->pfnPlanarEnable(); ! 1194: } ! 1195: ! 1196: ppdev->rcl1WindowClip.bottom = -1; ! 1197: ppdev->rcl2WindowClip[0].bottom = -1; ! 1198: ppdev->rcl2WindowClip[1].bottom = -1; ! 1199: ppdev->rcl1PlanarClip.bottom = -1; ! 1200: ! 1201: // Neither of the 2 window windows was active, so we have to set up the ! 1202: // variables for the other bank (the one other than the one we were ! 1203: // called to set) as well, to make it valid. The other bank is set to ! 1204: // the same state as the bank we were called to set ! 1205: ! 1206: ppdev->rcl2PlanarClip[ulOtherWindow] = pbiWorking->rclBankBounds; ! 1207: ppdev->ulWindowBank[ulOtherWindow] = ulBank; ! 1208: ppdev->pvBitmapStart2Window[ulOtherWindow] = ! 1209: (PVOID) ((BYTE*)ppdev->pjScreen - pbiWorking->ulBankOffset); ! 1210: } ! 1211: ! 1212: ASSERTVGA(ppdev->flBank & BANK_PLANAR, "Should be in planar mode"); ! 1213: ! 1214: ppdev->rcl2PlanarClip[ulWindowToMap] = pbiWorking->rclBankBounds; ! 1215: ! 1216: // Shift the bitmap start address so that the desired bank aligns with the ! 1217: // banking window ! 1218: ! 1219: ppdev->pvBitmapStart2Window[ulWindowToMap] = ! 1220: (PVOID) ((UCHAR *)ppdev->pjScreen - pbiWorking->ulBankOffset); ! 1221: ! 1222: // Map in the desired bank; also map in the other bank to whatever its ! 1223: // current state is ! 1224: ! 1225: ppdev->ulWindowBank[ulWindowToMap] = ulBank; ! 1226: ! 1227: ppdev->flBank &= ~BANK_BROKEN_RASTERS; // No broken rasters ! 1228: ! 1229: // Set both banks at once, because we may have just initialized the other ! 1230: // bank, and because this way the bank switch code doesn't have to do a ! 1231: // read before write to obtain the state of the other bank. ! 1232: // This is so convoluted to avoid problems with wiping out registers C ! 1233: // thinks it's still using; the values are tranferred to volatiles, and ! 1234: // then to registers ! 1235: ! 1236: ! 1237: ulBank0 = ppdev->ulWindowBank[0]; ! 1238: ulBank1 = ppdev->ulWindowBank[1]; ! 1239: pBankFn = ppdev->pfnPlanarSwitchCode; ! 1240: ! 1241: _asm mov eax,ulBank0; ! 1242: _asm mov edx,ulBank1; ! 1243: pBankFn(); // actually switch the banks ! 1244: ! 1245: _asm popfd; ! 1246: } ! 1247: ! 1248: /******************************Private*Routine******************************\ ! 1249: * vPlanar2Window1RW ! 1250: * ! 1251: * Maps in the one window in 1R/W case. Does exactly the same thing as the ! 1252: * one window case, because there's only one window, but has to be a separate ! 1253: * entry point because of the extra parameter (because we're using STDCALL). ! 1254: \**************************************************************************/ ! 1255: ! 1256: VOID vPlanar2Window1RW(PPDEV ppdev, LONG lScan, ! 1257: BANK_JUST ulJustification, ULONG ulWindowToMap) ! 1258: { ! 1259: vPlanar1Window(ppdev, lScan, ulJustification); ! 1260: } ! 1261: ! 1262: /******************************Private*Routine******************************\ ! 1263: * vPlanar2Window2RW ! 1264: * ! 1265: * Maps in one of two windows, either the source window (window 0) or the dest ! 1266: * window (window 1), to allows access to lScan. Applies to 2RW window ! 1267: * banking scheme; should never be called for 1 RW window schemes, because ! 1268: * there's only one window in that case. ! 1269: \**************************************************************************/ ! 1270: ! 1271: VOID vPlanar2Window2RW( ! 1272: PPDEV ppdev, ! 1273: LONG lScan, ! 1274: BANK_JUST ulJustification, ! 1275: ULONG ulWindowToMap) ! 1276: { ! 1277: ULONG ulBank; ! 1278: PBANK_INFO pbiWorking; ! 1279: volatile ULONG ulBank0; ! 1280: volatile ULONG ulBank1; ! 1281: volatile PFN pBankFn; ! 1282: ! 1283: // ASM routines that call this may have STD in effect, but the C compiler ! 1284: // assumes CLD ! 1285: ! 1286: _asm pushfd ! 1287: _asm cld ! 1288: ! 1289: // Find the bank containing the scan line with the desired justification: ! 1290: ! 1291: if (ulJustification == JustifyBottom) ! 1292: { ! 1293: lScan -= ppdev->ulPlanarBottomOffset; ! 1294: if (lScan <= 0) ! 1295: lScan = 0; ! 1296: } ! 1297: ! 1298: ulBank = (ULONG) ppdev->pjJustifyTopPlanar[lScan]; ! 1299: pbiWorking = &ppdev->pbiPlanarInfo[ulBank]; ! 1300: ! 1301: // Set the clip rect for this bank; if it's set to -1, that indicates that ! 1302: // a single-window set-up is currently active, so invalidate single-window ! 1303: // clip rects and display memory pointers (when double-window is active, ! 1304: // single-window is inactive, and vice-versa; a full bank set-up has to be ! 1305: // performed to switch between the two) ! 1306: ! 1307: if (ppdev->rcl2PlanarClip[ulWindowToMap].bottom == -1) ! 1308: { ! 1309: if (!(ppdev->flBank & BANK_PLANAR)) ! 1310: { ! 1311: ppdev->flBank |= BANK_PLANAR; ! 1312: ppdev->pfnPlanarEnable(); ! 1313: } ! 1314: ! 1315: ppdev->rcl1WindowClip.bottom = -1; ! 1316: ppdev->rcl2WindowClip[0].bottom = -1; ! 1317: ppdev->rcl2WindowClip[1].bottom = -1; ! 1318: ppdev->rcl1PlanarClip.bottom = -1; ! 1319: ! 1320: // Neither of the 2 window windows was active, so we have to set up the ! 1321: // variables for the other bank (the one other than the one we were ! 1322: // called to set) as well, to make it valid. The other bank is set to ! 1323: // the same state as the bank we were called to set ! 1324: ! 1325: ppdev->rcl2PlanarClip[ulWindowToMap^1] = pbiWorking->rclBankBounds; ! 1326: if (ulWindowToMap == 1) ! 1327: { ! 1328: ppdev->pvBitmapStart2Window[0] = ! 1329: (PVOID) ((BYTE*)ppdev->pjScreen - pbiWorking->ulBankOffset); ! 1330: } ! 1331: else ! 1332: { ! 1333: ppdev->pvBitmapStart2Window[1] = ! 1334: (PVOID) ((UCHAR *)ppdev->pjScreen - pbiWorking->ulBankOffset + ! 1335: BANK_SIZE_2RW_WINDOW); ! 1336: } ! 1337: ppdev->ulWindowBank[ulWindowToMap^1] = ulBank; ! 1338: } ! 1339: ! 1340: ASSERTVGA(ppdev->flBank & BANK_PLANAR, "Should be in planar mode"); ! 1341: ! 1342: ppdev->rcl2PlanarClip[ulWindowToMap] = pbiWorking->rclBankBounds; ! 1343: ! 1344: // Shift the bitmap start address so that the desired bank aligns with the ! 1345: // banking window ! 1346: ! 1347: if (ulWindowToMap == 0) ! 1348: { ! 1349: ppdev->pvBitmapStart2Window[0] = ! 1350: (PVOID) ((UCHAR *)ppdev->pjScreen - pbiWorking->ulBankOffset); ! 1351: } ! 1352: else ! 1353: { ! 1354: ppdev->pvBitmapStart2Window[1] = ! 1355: (PVOID) ((UCHAR *)ppdev->pjScreen - pbiWorking->ulBankOffset + ! 1356: BANK_SIZE_2RW_WINDOW); ! 1357: } ! 1358: ! 1359: ppdev->flBank &= ~BANK_BROKEN_RASTERS; // No broken rasters ! 1360: ! 1361: // Map in the desired bank; also map in the other bank to whatever its ! 1362: // current state is ! 1363: ! 1364: ppdev->ulWindowBank[ulWindowToMap] = ulBank; ! 1365: ! 1366: // Set both banks at once, because we may have just initialized the other ! 1367: // bank, and because this way the bank switch code doesn't have to do a ! 1368: // read before write to obtain the state of the other bank. ! 1369: // This is so convoluted to avoid problems with wiping out registers C ! 1370: // thinks it's still using; the values are tranferred to volatiles, and ! 1371: // then to registers ! 1372: ! 1373: ulBank0 = ppdev->ulWindowBank[0]; ! 1374: ulBank1 = ppdev->ulWindowBank[1]; ! 1375: pBankFn = ppdev->pfnPlanarSwitchCode; ! 1376: _asm mov eax,ulBank0; ! 1377: _asm mov edx,ulBank1; ! 1378: pBankFn(); // actually switch the banks ! 1379: ! 1380: _asm popfd; ! 1381: } ! 1382: ! 1383: ! 1384: /******************************Private*Routine******************************\ ! 1385: * vPlanarDouble ! 1386: * ! 1387: * Maps in two windows simultaneously, both the source window (window 0) ! 1388: * and the dest window (window 1), to allows access to the scans. ! 1389: * Applies to 1R1W and 2R/w window banking schemes; should never be called ! 1390: * for 1 RW window schemes, because there's only one window in that case. ! 1391: * ! 1392: \**************************************************************************/ ! 1393: ! 1394: VOID vPlanarDouble( ! 1395: PPDEV ppdev, ! 1396: LONG lScan0, // Source bank ! 1397: BANK_JUST ulJustification0,// Source justification ! 1398: LONG lScan1, // Destination bank ! 1399: BANK_JUST ulJustification1)// Destination justification ! 1400: { ! 1401: PBANK_INFO pbi0; ! 1402: PBANK_INFO pbi1; ! 1403: ULONG ulBank0; ! 1404: ULONG ulBank1; ! 1405: volatile ULONG ulBank0_vol; ! 1406: volatile ULONG ulBank1_vol; ! 1407: volatile PFN pBankFn; ! 1408: ! 1409: // ASM routines that call this may have STD in effect, but the C compiler ! 1410: // assumes CLD ! 1411: ! 1412: _asm pushfd ! 1413: _asm cld ! 1414: ! 1415: // Find the banks containing the scan lines with the desired justification: ! 1416: ! 1417: if (ulJustification0 == JustifyBottom) ! 1418: { ! 1419: lScan0 -= ppdev->ulPlanarBottomOffset; ! 1420: if (lScan0 <= 0) ! 1421: lScan0 = 0; ! 1422: } ! 1423: if (ulJustification1 == JustifyBottom) ! 1424: { ! 1425: lScan1 -= ppdev->ulPlanarBottomOffset; ! 1426: if (lScan1 <= 0) ! 1427: lScan1 = 0; ! 1428: } ! 1429: ! 1430: ulBank0 = (ULONG) ppdev->pjJustifyTopPlanar[lScan0]; ! 1431: ulBank1 = (ULONG) ppdev->pjJustifyTopPlanar[lScan1]; ! 1432: pbi0 = &ppdev->pbiPlanarInfo[ulBank0]; ! 1433: pbi1 = &ppdev->pbiPlanarInfo[ulBank1]; ! 1434: ! 1435: // Set the clip rect for this bank; if it's set to -1, that indicates that ! 1436: // a single-window set-up is currently active, so invalidate single-window ! 1437: // clip rects and display memory pointers (when double-window is active, ! 1438: // single-window is inactive, and vice-versa; a full bank set-up has to be ! 1439: // performed to switch between the two) ! 1440: ! 1441: if (ppdev->rcl2PlanarClip[0].bottom == -1) ! 1442: { ! 1443: if (!(ppdev->flBank & BANK_PLANAR)) ! 1444: { ! 1445: ppdev->flBank |= BANK_PLANAR; ! 1446: ppdev->pfnPlanarEnable(); ! 1447: } ! 1448: ! 1449: ppdev->rcl1WindowClip.bottom = -1; ! 1450: ppdev->rcl2WindowClip[0].bottom = -1; ! 1451: ppdev->rcl2WindowClip[1].bottom = -1; ! 1452: ppdev->rcl1PlanarClip.bottom = -1; ! 1453: } ! 1454: ! 1455: ASSERTVGA(ppdev->flBank & BANK_PLANAR, "Should be in planar mode"); ! 1456: ! 1457: ppdev->rcl2PlanarClip[0] = pbi0->rclBankBounds; ! 1458: ppdev->rcl2PlanarClip[1] = pbi1->rclBankBounds; ! 1459: ! 1460: // Shift the bitmap start address so that the desired bank aligns with the ! 1461: // banking window ! 1462: ! 1463: ppdev->pvBitmapStart2Window[0] = ! 1464: (PVOID) ((UCHAR *)ppdev->pjScreen - pbi0->ulBankOffset); ! 1465: ppdev->pvBitmapStart2Window[1] = ! 1466: (PVOID) ((UCHAR *)ppdev->pjScreen - pbi1->ulBankOffset); ! 1467: ! 1468: if (ppdev->vbtPlanarType == VideoBanked2RW) ! 1469: { ! 1470: ppdev->pvBitmapStart2Window[1] = (PVOID) ((BYTE*) ! 1471: ppdev->pvBitmapStart2Window[1] + BANK_SIZE_2RW_WINDOW); ! 1472: } ! 1473: ! 1474: // Map in the desired banks. ! 1475: ! 1476: ppdev->ulWindowBank[0] = ulBank0; ! 1477: ppdev->ulWindowBank[1] = ulBank1; ! 1478: ! 1479: ppdev->flBank &= ~BANK_BROKEN_RASTERS; // No broken rasters ! 1480: ! 1481: // Set both banks at once. ! 1482: // This is so convoluted to avoid problems with wiping out registers C ! 1483: // thinks it's still using; the values are tranferred to volatiles, and ! 1484: // then to registers ! 1485: ! 1486: ulBank0_vol = ulBank0; ! 1487: ulBank1_vol = ulBank1; ! 1488: pBankFn = ppdev->pfnPlanarSwitchCode; ! 1489: ! 1490: _asm mov eax,ulBank0_vol; ! 1491: _asm mov edx,ulBank1_vol; ! 1492: pBankFn(); // actually switch the banks ! 1493: ! 1494: _asm popfd; ! 1495: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.