|
|
1.1 ! root 1: /******************************Module*Header*******************************\ ! 2: * Module Name: bank.c ! 3: * ! 4: * Functions to control VGA banking ! 5: * ! 6: * Copyright (c) 1992 Microsoft Corporation ! 7: \**************************************************************************/ ! 8: ! 9: ! 10: #include "driver.h" // private driver defines ! 11: ! 12: void BankErrorTrap(PDEVSURF, LONG, BANK_JUST); ! 13: void Bank2Window(PDEVSURF, LONG, BANK_JUST, ULONG); ! 14: void Bank2Window2RW(PDEVSURF, LONG, BANK_JUST, ULONG); ! 15: void Bank2Window1RW(PDEVSURF, LONG, BANK_JUST, ULONG); ! 16: void Bank1Window2RW(PDEVSURF, LONG, BANK_JUST); ! 17: void Bank1Window(PDEVSURF, LONG, BANK_JUST); ! 18: ! 19: LPBYTE pPtrWork; ! 20: LPBYTE pPtrSave; ! 21: ! 22: // BUGBUG all routines should get the scan width out of the surface ! 23: ULONG ulNextScan_global; ! 24: ! 25: /******************************Public*Routine******************************\ ! 26: * SetUpBanking ! 27: * ! 28: * Set up banking for the current mode ! 29: * pdsurf and ppdev are the pointers to the current surface and device ! 30: * Relevant fields in the surface are set up for banking ! 31: \**************************************************************************/ ! 32: ! 33: BOOL SetUpBanking(PDEVSURF pdsurf, PPDEV ppdev) ! 34: { ! 35: INT i; ! 36: LONG lTemp; ! 37: LONG lScansPerBank, lScan, lTotalScans, lTotalBanks; ! 38: LONG lScansBetweenBanks; ! 39: ULONG ulOffset; ! 40: PVIDEO_BANK_SELECT BankInfo; ! 41: UINT ReturnedDataLength; ! 42: VIDEO_BANK_SELECT TempBankInfo; ! 43: PBANK_INFO pbiWorking; ! 44: ! 45: // ! 46: // Query the miniport for banking info for this mode. ! 47: // ! 48: // First, figure out how big a buffer we need for the banking info ! 49: // (returned in TempBankInfo->Size). ! 50: // ! 51: ! 52: // ! 53: // BUGBUG The error paths should point to the end of the function where ! 54: // we can deallocate all the buffers that were allocated. ! 55: // ! 56: ! 57: if (!DeviceIoControl(ppdev->hDriver, ! 58: IOCTL_VIDEO_GET_BANK_SELECT_CODE, ! 59: NULL, // input buffer ! 60: 0, ! 61: &TempBankInfo, // output buffer ! 62: sizeof(VIDEO_BANK_SELECT), ! 63: &ReturnedDataLength, ! 64: NULL)) { ! 65: ! 66: // ! 67: // We expect this call to fail, because we didn't allow any room ! 68: // for the code; we just want to get the required output buffer ! 69: // size. Make sure we got the expected error, ERROR_MORE_DATA. ! 70: // ! 71: ! 72: if (GetLastError() != ERROR_MORE_DATA) { ! 73: ! 74: // ! 75: // Should post error and return FALSE ! 76: // ! 77: ! 78: RIP("VGA.DLL: Initialization error-GetBankSelectCode, first call"); ! 79: ! 80: return FALSE; ! 81: } ! 82: ! 83: } ! 84: ! 85: ! 86: // ! 87: // Now, allocate a buffer of the required size and get the banking info. ! 88: // ! 89: ! 90: if ((BankInfo = (PVIDEO_BANK_SELECT) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, ! 91: TempBankInfo.Size)) == NULL) { ! 92: ! 93: // ! 94: // Should post error and return FALSE ! 95: // ! 96: ! 97: RIP("VGA.DLL: Initialization error-couldn't get memory for bank info"); ! 98: return FALSE; ! 99: ! 100: ! 101: } ! 102: ! 103: if (!DeviceIoControl(ppdev->hDriver, ! 104: IOCTL_VIDEO_GET_BANK_SELECT_CODE, ! 105: NULL, ! 106: 0, ! 107: BankInfo, ! 108: TempBankInfo.Size, ! 109: &ReturnedDataLength, ! 110: NULL)) { ! 111: ! 112: // ! 113: // Should post error and return FALSE ! 114: // ! 115: ! 116: RIP("VGA.DLL: Initialization error-GetBankSelectCode, second call"); ! 117: return FALSE; ! 118: ! 119: } ! 120: ! 121: ! 122: // ! 123: // Set up for banking. ! 124: // ! 125: ! 126: // Set up variables that are the same whether the adapter is banked or not ! 127: ! 128: pdsurf->pBankSelectInfo = BankInfo; ! 129: pdsurf->pfnBankSwitchCode = ! 130: (PFN) (((UCHAR *)BankInfo) + BankInfo->CodeOffset); ! 131: pdsurf->vbtBankingType = BankInfo->BankingType; ! 132: pdsurf->ulBitmapSize = BankInfo->BitmapSize; ! 133: pdsurf->lNextScan = BankInfo->BitmapWidthInBytes; ! 134: ! 135: // BUGBUG this should not be static ! 136: ulNextScan_global = BankInfo->BitmapWidthInBytes; ! 137: ! 138: // Set up the pointer off-screen work areas at the very end of display ! 139: // memory (values are relative to bitmap start) ! 140: // BUGBUG should be in PDEV ! 141: pPtrWork = (LPBYTE) pdsurf->ulBitmapSize - POINTER_WORK_AREA_SIZE; ! 142: pPtrSave = pPtrWork - POINTER_SAVE_AREA_SIZE; ! 143: ! 144: // Set up info that depends on whether or not the adapter is banked ! 145: ! 146: if (BankInfo->BankingType == VideoNotBanked) { ! 147: ! 148: lTotalScans = BankInfo->BitmapSize / BankInfo->BitmapWidthInBytes; ! 149: ! 150: // Unbanked; set all clip rects for the full bitmap, so the bank never ! 151: // needs to be changed, and set the banking vectors to error traps, ! 152: // since they should never be called ! 153: ! 154: pdsurf->rcl1WindowClip.left = pdsurf->rcl2WindowClip[0].left = ! 155: pdsurf->rcl2WindowClip[1].left = pdsurf->rcl1WindowClip.top = ! 156: pdsurf->rcl2WindowClip[0].top = pdsurf->rcl2WindowClip[1].top = 0; ! 157: ! 158: pdsurf->rcl1WindowClip.right = pdsurf->rcl2WindowClip[0].right = ! 159: pdsurf->rcl2WindowClip[1].right = ! 160: BankInfo->BitmapWidthInBytes << 8; ! 161: ! 162: pdsurf->rcl1WindowClip.bottom = pdsurf->rcl2WindowClip[0].bottom = ! 163: pdsurf->rcl2WindowClip[1].bottom = lTotalScans; ! 164: ! 165: pdsurf->pfnBankControl = BankErrorTrap; ! 166: pdsurf->pfnBankControl2Window = BankErrorTrap; ! 167: ! 168: pdsurf->ulWindowBank[0] = pdsurf->ulWindowBank[1] = (ULONG)0; ! 169: pdsurf->pvBitmapStart = pdsurf->pvBitmapStart2Window[0] = ! 170: pdsurf->pvBitmapStart2Window[1] = pdsurf->pvStart; ! 171: ! 172: // Scan line to be used with JustifyBottom to map in the bank ! 173: // containing the pointer work and save areas, which are guaranteed not ! 174: // to span banks. Is only used to determine that the bank never needs ! 175: // to be changed to map in the pointer in unbanked case ! 176: pdsurf->ulPtrBankScan = 0; ! 177: ! 178: // Mark that the bank info pointers are unused, so we don't try to ! 179: // deallocate the memory they point to ! 180: pdsurf->pbiBankInfo = pdsurf->pbiBankInfo2RW = NULL; ! 181: ! 182: // Allocate space for the temp buffer. ! 183: ! 184: if ((pdsurf->pvBankBufferPlane0 = ! 185: (PVOID) LocalAlloc(LMEM_FIXED | ! 186: LMEM_ZEROINIT, BANK_BUFFER_SIZE_UNBANKED)) == NULL) { ! 187: ! 188: // ! 189: // Should post error and return FALSE ! 190: // ! 191: ! 192: RIP("VGA.DLL: Couldn't get memory for temp buffer"); ! 193: return FALSE; ! 194: ! 195: } ! 196: ! 197: pdsurf->ulTempBufferSize = BANK_BUFFER_SIZE_UNBANKED; ! 198: ! 199: // These should never be used ! 200: pdsurf->pvBankBufferPlane1 = ! 201: pdsurf->pvBankBufferPlane2 = ! 202: pdsurf->pvBankBufferPlane3 = (PVOID) NULL; ! 203: ! 204: } else { ! 205: ! 206: // Banked, so set up all banking variables and initialize the bank ! 207: // control routines and their data tables ! 208: ! 209: // Reject if there are broken rasters (a broken raster is a scan line ! 210: // that crosses a bank boundary); that's not handled in this driver ! 211: ! 212: if (BankInfo->BankingType != VideoBanked2RW) { ! 213: ! 214: // For the 1 RW window and 1R1W window cases, windows are ! 215: // assumed to be BANK_SIZE_1_WINDOW in size (generally 64K) ! 216: lTemp = BANK_SIZE_1_WINDOW; ! 217: ! 218: } else { ! 219: ! 220: // For the 2 RW window case, windows are assumed to be ! 221: // BANK_SIZE_2RW_WINDOW in size (generally 32K) ! 222: lTemp = BANK_SIZE_2RW_WINDOW; ! 223: ! 224: } ! 225: ! 226: if ((lTemp % BankInfo->BitmapWidthInBytes) != 0) { ! 227: ! 228: // ! 229: // Should post error and return FALSE ! 230: // ! 231: ! 232: RIP("VGA.DLL: Broken rasters not supported"); ! 233: return FALSE; ! 234: ! 235: } ! 236: ! 237: // These will be set properly on first call to bank controller, below, ! 238: // or something's wrong ! 239: pdsurf->ulWindowBank[0] = (ULONG)-1; ! 240: pdsurf->ulWindowBank[1] = (ULONG)-1; ! 241: pdsurf->pvBitmapStart = pdsurf->pvBitmapStart2Window[0] = ! 242: pdsurf->pvBitmapStart2Window[1] = (PVOID) 0; ! 243: ! 244: // Set all clip rects to invalid; they'll be updated when the first ! 245: // bank is mapped in ! 246: ! 247: pdsurf->rcl1WindowClip.left = pdsurf->rcl2WindowClip[0].left = ! 248: pdsurf->rcl2WindowClip[1].left = pdsurf->rcl1WindowClip.top = ! 249: pdsurf->rcl2WindowClip[0].top = pdsurf->rcl2WindowClip[1].top = ! 250: pdsurf->rcl1WindowClip.right = pdsurf->rcl2WindowClip[0].right = ! 251: pdsurf->rcl2WindowClip[1].right = pdsurf->rcl1WindowClip.bottom = ! 252: pdsurf->rcl2WindowClip[0].bottom = ! 253: pdsurf->rcl2WindowClip[1].bottom = -1; ! 254: ! 255: // Set up to call the appropriate banking control routines ! 256: ! 257: switch(BankInfo->BankingType) { ! 258: ! 259: case VideoBanked1RW: ! 260: ! 261: pdsurf->pfnBankControl = Bank1Window; ! 262: pdsurf->pfnBankControl2Window = Bank2Window1RW; ! 263: ! 264: if ((pdsurf->pvBankBufferPlane0 = ! 265: (PVOID) LocalAlloc(LMEM_FIXED | ! 266: LMEM_ZEROINIT, BANK_BUFFER_SIZE_1RW)) == NULL) { ! 267: ! 268: // ! 269: // Should post error and return FALSE ! 270: // ! 271: ! 272: RIP("VGA.DLL: Couldn't get memory for temp buffer"); ! 273: return FALSE; ! 274: ! 275: } ! 276: ! 277: pdsurf->ulTempBufferSize = BANK_BUFFER_SIZE_1RW; ! 278: ! 279: pdsurf->pvBankBufferPlane1 = ! 280: ((LPBYTE)pdsurf->pvBankBufferPlane0) + ! 281: BANK_BUFFER_PLANE_SIZE; ! 282: pdsurf->pvBankBufferPlane2 = ! 283: ((LPBYTE)pdsurf->pvBankBufferPlane1) + ! 284: BANK_BUFFER_PLANE_SIZE; ! 285: pdsurf->pvBankBufferPlane3 = ! 286: ((LPBYTE)pdsurf->pvBankBufferPlane2) + ! 287: BANK_BUFFER_PLANE_SIZE; ! 288: ! 289: break; ! 290: ! 291: ! 292: case VideoBanked1R1W: ! 293: ! 294: pdsurf->pfnBankControl = Bank1Window; ! 295: pdsurf->pfnBankControl2Window = Bank2Window; ! 296: ! 297: if ((pdsurf->pvBankBufferPlane0 = ! 298: (PVOID) LocalAlloc(LMEM_FIXED | ! 299: LMEM_ZEROINIT, BANK_BUFFER_SIZE_1R1W)) == NULL) { ! 300: ! 301: // ! 302: // Should post error and return FALSE ! 303: // ! 304: ! 305: RIP("VGA.DLL: Couldn't get memory for temp buffer"); ! 306: return FALSE; ! 307: ! 308: } ! 309: ! 310: pdsurf->ulTempBufferSize = BANK_BUFFER_SIZE_1R1W; ! 311: ! 312: // These should never be used ! 313: pdsurf->pvBankBufferPlane1 = ! 314: pdsurf->pvBankBufferPlane2 = ! 315: pdsurf->pvBankBufferPlane3 = (PVOID) NULL; ! 316: ! 317: break; ! 318: ! 319: ! 320: case VideoBanked2RW: ! 321: ! 322: pdsurf->pfnBankControl = Bank1Window2RW; ! 323: pdsurf->pfnBankControl2Window = Bank2Window2RW; ! 324: ! 325: if ((pdsurf->pvBankBufferPlane0 = ! 326: (PVOID) LocalAlloc(LMEM_FIXED | ! 327: LMEM_ZEROINIT, BANK_BUFFER_SIZE_2RW)) == NULL) { ! 328: ! 329: // ! 330: // Should post error and return FALSE ! 331: // ! 332: ! 333: RIP("VGA.DLL: Couldn't get memory for temp buffer"); ! 334: return FALSE; ! 335: ! 336: } ! 337: ! 338: pdsurf->ulTempBufferSize = BANK_BUFFER_SIZE_2RW; ! 339: ! 340: // These should never be used ! 341: pdsurf->pvBankBufferPlane1 = ! 342: pdsurf->pvBankBufferPlane2 = ! 343: pdsurf->pvBankBufferPlane3 = (PVOID) NULL; ! 344: ! 345: break; ! 346: ! 347: default: ! 348: ! 349: // ! 350: // Should post error and return FALSE ! 351: // ! 352: ! 353: RIP("VGA.DLL: bad BankingType"); ! 354: return FALSE; ! 355: ! 356: } ! 357: ! 358: // Set up the bank control tables with clip rects for banks ! 359: // Note: lTotalBanks is generally an overestimate when granularity ! 360: // is less than window size, because we ignore any banks after the ! 361: // first one that includes the last scan line of the bitmap. A bit ! 362: // of memory could be saved by sizing lTotalBanks exactly. Note too, ! 363: // though, that the 2 RW window case may require more entries then, ! 364: // because its windows are shorter, so you'd have to make sure there ! 365: // were enough entries for the 2 RW window case, or recalculate ! 366: // lTotalBanks for the 2 RW case ! 367: ! 368: lTotalBanks = BankInfo->BitmapSize / BankInfo->Granularity; ! 369: lTotalScans = BankInfo->BitmapSize / BankInfo->BitmapWidthInBytes; ! 370: lScansBetweenBanks = ! 371: BankInfo->Granularity / BankInfo->BitmapWidthInBytes; ! 372: ! 373: // Allocate memory for bank control info ! 374: ! 375: if ((pdsurf->pbiBankInfo = (PBANK_INFO) LocalAlloc(LMEM_FIXED | ! 376: LMEM_ZEROINIT, lTotalBanks * sizeof(BANK_INFO))) == NULL) { ! 377: ! 378: // ! 379: // Should post error and return FALSE ! 380: // ! 381: ! 382: RIP("VGA.DLL: Couldn't get memory for bank info #2"); ! 383: return FALSE; ! 384: ! 385: } ! 386: ! 387: // Build the list of bank rects & offsets assuming standard window ! 388: // size ! 389: ! 390: lScansPerBank = BANK_SIZE_1_WINDOW / BankInfo->BitmapWidthInBytes; ! 391: ulOffset = 0; ! 392: lScan = -lScansBetweenBanks; // precompensate for 1st time in loop ! 393: i = 0; ! 394: pbiWorking = pdsurf->pbiBankInfo; ! 395: ! 396: do { ! 397: ! 398: lScan += lScansBetweenBanks; ! 399: pbiWorking->rclBankBounds.left = 0; ! 400: pbiWorking->rclBankBounds.right = pdsurf->sizlSurf.cx; ! 401: pbiWorking->rclBankBounds.top = lScan; ! 402: pbiWorking->rclBankBounds.bottom = lScan + lScansPerBank; ! 403: pbiWorking->ulBankOffset = ulOffset; ! 404: ulOffset += BankInfo->Granularity; ! 405: i++; ! 406: pbiWorking++; ! 407: ! 408: } while ((lScan + lScansPerBank) < lTotalScans); ! 409: ! 410: pdsurf->ulBankInfoLength = i; ! 411: ! 412: // If this is a 2RW bank adapter, build a table for that too, with ! 413: // 32K windows ! 414: ! 415: if (BankInfo->BankingType == VideoBanked2RW) { ! 416: ! 417: // Offset from one bank index to next to make two 32K banks ! 418: // appear to be one seamless 64K bank ! 419: pdsurf->ulBank2RWSkip = ! 420: (BANK_SIZE_2RW_WINDOW / BankInfo->Granularity); ! 421: ! 422: // Allocate memory for 2RW case bank control info ! 423: if ((pdsurf->pbiBankInfo2RW = ! 424: (PBANK_INFO) LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, ! 425: lTotalBanks * sizeof(BANK_INFO))) == NULL) { ! 426: ! 427: // ! 428: // Should post error and return FALSE ! 429: // ! 430: ! 431: RIP("VGA.DLL: Couldn't get memory for bank info #3"); ! 432: return FALSE; ! 433: ! 434: } ! 435: ! 436: // Build the list of bank rects & offsets for 2RW case ! 437: lScansPerBank = ! 438: BANK_SIZE_2RW_WINDOW / BankInfo->BitmapWidthInBytes; ! 439: lScan = -lScansBetweenBanks; // precompensate for 1st time ! 440: ulOffset = 0; ! 441: i = 0; ! 442: pbiWorking = pdsurf->pbiBankInfo2RW; ! 443: ! 444: do { ! 445: ! 446: lScan += lScansBetweenBanks; ! 447: pbiWorking->rclBankBounds.left = 0; ! 448: pbiWorking->rclBankBounds.right = pdsurf->sizlSurf.cx; ! 449: pbiWorking->rclBankBounds.top = lScan; ! 450: pbiWorking->rclBankBounds.bottom = lScan + lScansPerBank; ! 451: pbiWorking->ulBankOffset = ulOffset; ! 452: ulOffset += BankInfo->Granularity; ! 453: i++; ! 454: pbiWorking++; ! 455: ! 456: } while ((lScan + lScansPerBank) < lTotalScans); ! 457: ! 458: pdsurf->ulBankInfo2RWLength = i; ! 459: ! 460: } else { ! 461: ! 462: // Not a 2RW bank adapter, just use standard table for 2-window ! 463: // cases ! 464: ! 465: pdsurf->pbiBankInfo2RW = pdsurf->pbiBankInfo; ! 466: pdsurf->ulBankInfo2RWLength = pdsurf->ulBankInfoLength; ! 467: ! 468: } ! 469: ! 470: // Map in scan line 0 for read & write, to put things in a known state ! 471: ! 472: pdsurf->pfnBankControl(pdsurf, 0, JustifyTop); ! 473: ! 474: // Scan line to be used with JustifyBottom to map in the bank ! 475: // containing the pointer work and save areas, which are guaranteed not ! 476: // to span banks ! 477: pdsurf->ulPtrBankScan = (pdsurf->ulBitmapSize/pdsurf->lNextScan) - 1; ! 478: ! 479: } ! 480: ! 481: ! 482: return TRUE; ! 483: } ! 484: ! 485: /******************************Private*Routine******************************\ ! 486: * BankErrorTrap ! 487: * ! 488: * Traps calls to bank control functions in non-banked modes ! 489: * ! 490: \**************************************************************************/ ! 491: ! 492: void BankErrorTrap(PDEVSURF pdsurf, LONG lScan, ! 493: BANK_JUST ulJustification) ! 494: { ! 495: DISPDBG((0, "VGA.DLL: Call to bank manager in unbanked mode\n")); ! 496: } ! 497: ! 498: ! 499: /******************************Private*Routine******************************\ ! 500: * Bank1Window ! 501: * ! 502: * Maps in a single R/W window that allows access to lScan. Applies to both ! 503: * 1 RW window and 1R1W window banking schemes. ! 504: * ! 505: * Note: in the 1 R/W adapter case, this may be called with a fourth parameter ! 506: * (the source/dest selector), which is ignored. This is so that we can use the ! 507: * same routine as the destination for 1 R/W 2-window calls; those calls don't ! 508: * map in separate banks, of course, but they let us get away with common code ! 509: * for 1 R/W and 1R/1W in some cases (such as aligned blits). ! 510: * ! 511: \**************************************************************************/ ! 512: ! 513: void Bank1Window(PDEVSURF pdsurf, LONG lScan, ! 514: BANK_JUST ulJustification) ! 515: { ! 516: ULONG ulBank; ! 517: PBANK_INFO pbiWorking; ! 518: volatile ULONG ulBank0; ! 519: volatile PFN pBankFn; ! 520: ! 521: // ASM routines that call this may have STD in effect, but the C compiler ! 522: // assumes CLD ! 523: ! 524: _asm pushfd ! 525: _asm cld ! 526: ! 527: // Find the bank containing the scan line with the desired justification ! 528: if (ulJustification == JustifyTop) { ! 529: ! 530: // Map scan line in as near as possible to the top of the window ! 531: ulBank = pdsurf->ulBankInfoLength-1; ! 532: pbiWorking = pdsurf->pbiBankInfo + ulBank; ! 533: while (pbiWorking->rclBankBounds.top > lScan) { ! 534: ulBank--; ! 535: pbiWorking--; ! 536: } ! 537: ! 538: } else { ! 539: ! 540: // Map scan line in as near as possible to the bottom of the window ! 541: ulBank = 0; ! 542: pbiWorking = pdsurf->pbiBankInfo; ! 543: while (pbiWorking->rclBankBounds.bottom <= lScan) { ! 544: ulBank++; ! 545: pbiWorking++; ! 546: } ! 547: ! 548: } ! 549: ! 550: // Set the clip rect for this bank; if it's set to -1, that indicates that ! 551: // a double-window set-up is currently active, so invalidate double-window ! 552: // clip rects and display memory pointers (when double-window is active, ! 553: // single-window is inactive, and vice-versa; a full bank set-up has to be ! 554: // performed to switch between the two) ! 555: ! 556: if (pdsurf->rcl1WindowClip.top == -1) { ! 557: ! 558: pdsurf->rcl2WindowClip[0].top = ! 559: pdsurf->rcl2WindowClip[0].bottom = ! 560: pdsurf->rcl2WindowClip[0].right = ! 561: pdsurf->rcl2WindowClip[0].left = ! 562: pdsurf->rcl2WindowClip[1].top = ! 563: pdsurf->rcl2WindowClip[1].bottom = ! 564: pdsurf->rcl2WindowClip[1].right = ! 565: pdsurf->rcl2WindowClip[1].left = -1; ! 566: pdsurf->pvBitmapStart2Window[0] = (PDEVSURF) 0; ! 567: pdsurf->pvBitmapStart2Window[1] = (PDEVSURF) 0; ! 568: ! 569: } else { ! 570: // ASSERT(pdsurf->rcl2WindowClip[0].top == -1, ! 571: // "BANK.C: 2 bank src not mapped out"); ! 572: // ASSERT(pdsurf->rcl2WindowClip[1].top == -1, ! 573: // "BANK.C: 2 bank src not mapped out"); ! 574: } ! 575: ! 576: ! 577: pdsurf->rcl1WindowClip = pbiWorking->rclBankBounds; ! 578: ! 579: // Shift the bitmap start address so that the desired bank aligns with ! 580: // the banking window. The source and destination are set only so 1 R/W ! 581: // aligned blits will work without having to be specifically aware of ! 582: // the adapter type (some of the same code works with 1R/1W adapters too). ! 583: ! 584: pdsurf->pvBitmapStart = ! 585: pdsurf->pvBitmapStart2Window[0] = ! 586: pdsurf->pvBitmapStart2Window[1] = ! 587: (PVOID) ((UCHAR *)pdsurf->pvStart - pbiWorking->ulBankOffset); ! 588: ! 589: // Map in the desired bank for both read and write ! 590: // This is so convoluted to avoid problems with wiping out registers C ! 591: // thinks it's still using; the values are tranferred to volatiles, and ! 592: // then to registers ! 593: ! 594: ulBank0 = ulBank; ! 595: pBankFn = pdsurf->pfnBankSwitchCode; ! 596: _asm mov eax,ulBank0; ! 597: _asm mov edx,eax; ! 598: pBankFn(); // actually switch the banks ! 599: ! 600: _asm popfd ! 601: } ! 602: ! 603: ! 604: /******************************Private*Routine******************************\ ! 605: * Bank1Window2RW ! 606: * ! 607: * Maps in two 32K RW windows so that they form a single 64K R/W window that ! 608: * allows access to lScan. Applies only to 2 RW window schemes. ! 609: * ! 610: \**************************************************************************/ ! 611: ! 612: void Bank1Window2RW(PDEVSURF pdsurf, LONG lScan, ! 613: BANK_JUST ulJustification) ! 614: { ! 615: ULONG ulBank; ! 616: PBANK_INFO pbiWorking; ! 617: volatile ULONG ulBank0; ! 618: volatile ULONG ulBank1; ! 619: volatile PFN pBankFn; ! 620: ! 621: // ASM routines that call this may have STD in effect, but the C compiler ! 622: // assumes CLD ! 623: ! 624: _asm pushfd ! 625: _asm cld ! 626: ! 627: // Find the bank containing the scan line with the desired justification ! 628: if (ulJustification == JustifyTop) { ! 629: ! 630: // Map scan line in as near as possible to the top of the window ! 631: ulBank = pdsurf->ulBankInfoLength-1; ! 632: pbiWorking = pdsurf->pbiBankInfo + ulBank; ! 633: while (pbiWorking->rclBankBounds.top > lScan) { ! 634: ulBank--; ! 635: pbiWorking--; ! 636: } ! 637: ! 638: } else { ! 639: ! 640: // Map scan line in as near as possible to the bottom of the window ! 641: ulBank = 0; ! 642: pbiWorking = pdsurf->pbiBankInfo; ! 643: while (pbiWorking->rclBankBounds.bottom <= lScan) { ! 644: ulBank++; ! 645: pbiWorking++; ! 646: } ! 647: ! 648: } ! 649: ! 650: // Set the clip rect for this bank; if it's set to -1, that indicates that ! 651: // a double-window set-up is currently active, so invalidate double-window ! 652: // clip rects and display memory pointers (when double-window is active, ! 653: // single-window is inactive, and vice-versa; a full bank set-up has to be ! 654: // performed to switch between the two) ! 655: ! 656: if (pdsurf->rcl1WindowClip.top == -1) { ! 657: ! 658: pdsurf->rcl2WindowClip[0].top = ! 659: pdsurf->rcl2WindowClip[0].bottom = ! 660: pdsurf->rcl2WindowClip[0].right = ! 661: pdsurf->rcl2WindowClip[0].left = ! 662: pdsurf->rcl2WindowClip[1].top = ! 663: pdsurf->rcl2WindowClip[1].bottom = ! 664: pdsurf->rcl2WindowClip[1].right = ! 665: pdsurf->rcl2WindowClip[1].left = -1; ! 666: pdsurf->pvBitmapStart2Window[0] = (PDEVSURF) 0; ! 667: pdsurf->pvBitmapStart2Window[1] = (PDEVSURF) 0; ! 668: ! 669: } else { ! 670: // ASSERT(pdsurf->rcl2WindowClip[0].top == -1, ! 671: // "BANK.C: 2 bank src not mapped out"); ! 672: // ASSERT(pdsurf->rcl2WindowClip[1].top == -1, ! 673: // "BANK.C: 2 bank src not mapped out"); ! 674: } ! 675: ! 676: ! 677: pdsurf->rcl1WindowClip = pbiWorking->rclBankBounds; ! 678: ! 679: // Shift the bitmap start address so that the desired bank aligns with ! 680: // the banking window. The source and destination are set only so 1 R/W ! 681: // aligned blits will work without having to be specifically aware of ! 682: // the adapter type (some of the same code works with 1R/1W adapters too). ! 683: ! 684: pdsurf->pvBitmapStart = ! 685: pdsurf->pvBitmapStart2Window[0] = ! 686: pdsurf->pvBitmapStart2Window[1] = ! 687: (PVOID) ((UCHAR *)pdsurf->pvStart - pbiWorking->ulBankOffset); ! 688: ! 689: // Map in the desired bank for both read and write; this is accomplished ! 690: // by mapping in the desired 32K bank, followed by the next 32K bank. ! 691: // This is so convoluted to avoid problems with wiping out registers C ! 692: // thinks it's still using; the values are tranferred to volatiles, and ! 693: // then to registers ! 694: ! 695: ulBank0 = ulBank; ! 696: ulBank1 = ulBank0 + pdsurf->ulBank2RWSkip; ! 697: pBankFn = pdsurf->pfnBankSwitchCode; ! 698: _asm mov eax,ulBank0; ! 699: _asm mov edx,ulBank1; ! 700: pBankFn(); // actually switch the banks ! 701: ! 702: _asm popfd ! 703: } ! 704: ! 705: ! 706: /******************************Private*Routine******************************\ ! 707: * Bank2Window ! 708: * ! 709: * Maps in one of two windows, either the source window (window 0) or the dest ! 710: * window (window 1), to allows access to lScan. Applies to 1R1W window ! 711: * banking scheme; should never be called for 1 RW window schemes, because ! 712: * there's only one window in that case. ! 713: * ! 714: \**************************************************************************/ ! 715: ! 716: void Bank2Window(PDEVSURF pdsurf, LONG lScan, ! 717: BANK_JUST ulJustification, ULONG ulWindowToMap) ! 718: { ! 719: ULONG ulBank; ! 720: PBANK_INFO pbiWorking; ! 721: volatile ULONG ulBank0, ulBank1; ! 722: volatile PFN pBankFn; ! 723: ! 724: // ASM routines that call this may have STD in effect, but the C compiler ! 725: // assumes CLD ! 726: ! 727: _asm pushfd ! 728: _asm cld ! 729: ! 730: // Find the bank containing the scan line with the desired justification ! 731: if (ulJustification == JustifyTop) { ! 732: ! 733: // Map scan line in as near as possible to the top of the window ! 734: ulBank = pdsurf->ulBankInfoLength-1; ! 735: pbiWorking = pdsurf->pbiBankInfo + ulBank; ! 736: while (pbiWorking->rclBankBounds.top > lScan) { ! 737: ulBank--; ! 738: pbiWorking--; ! 739: } ! 740: ! 741: } else { ! 742: ! 743: // Map scan line in as near as possible to the bottom of the window ! 744: ulBank = 0; ! 745: pbiWorking = pdsurf->pbiBankInfo; ! 746: while (pbiWorking->rclBankBounds.bottom <= lScan) { ! 747: ulBank++; ! 748: pbiWorking++; ! 749: } ! 750: ! 751: } ! 752: ! 753: // Set the clip rect for this bank; if it's set to -1, that indicates that ! 754: // a single-window set-up is currently active, so invalidate single-window ! 755: // clip rects and display memory pointers (when double-window is active, ! 756: // single-window is inactive, and vice-versa; a full bank set-up has to be ! 757: // performed to switch between the two) ! 758: ! 759: if (pdsurf->rcl2WindowClip[ulWindowToMap].top == -1) { ! 760: ! 761: pdsurf->rcl1WindowClip.top = ! 762: pdsurf->rcl1WindowClip.bottom = ! 763: pdsurf->rcl1WindowClip.right = ! 764: pdsurf->rcl1WindowClip.left = -1; ! 765: pdsurf->pvBitmapStart = (PDEVSURF) 0; ! 766: ! 767: // Neither of the 2 window windows was active, so we have to set up the ! 768: // variables for the other bank (the one other than the one we were ! 769: // called to set) as well, to make it valid. The other bank is set to ! 770: // the same state as the bank we were called to set ! 771: pdsurf->rcl2WindowClip[ulWindowToMap^1] = pbiWorking->rclBankBounds; ! 772: pdsurf->pvBitmapStart2Window[ulWindowToMap^1] = ! 773: (PVOID) ((UCHAR *)pdsurf->pvStart - pbiWorking->ulBankOffset); ! 774: pdsurf->ulWindowBank[ulWindowToMap^1] = ulBank; ! 775: } else { ! 776: // ASSERT(pdsurf->rcl1WindowClip.top == -1, ! 777: // "BANK.C: 1 bank not mapped out"); ! 778: } ! 779: ! 780: pdsurf->rcl2WindowClip[ulWindowToMap] = pbiWorking->rclBankBounds; ! 781: ! 782: // Shift the bitmap start address so that the desired bank aligns with the ! 783: // banking window ! 784: ! 785: pdsurf->pvBitmapStart2Window[ulWindowToMap] = ! 786: (PVOID) ((UCHAR *)pdsurf->pvStart - pbiWorking->ulBankOffset); ! 787: ! 788: // Map in the desired bank; also map in the other bank to whatever its ! 789: // current state is ! 790: ! 791: pdsurf->ulWindowBank[ulWindowToMap] = ulBank; ! 792: ! 793: // Set both banks at once, because we may have just initialized the other ! 794: // bank, and because this way the bank switch code doesn't have to do a ! 795: // read before write to obtain the state of the other bank. ! 796: // This is so convoluted to avoid problems with wiping out registers C ! 797: // thinks it's still using; the values are tranferred to volatiles, and ! 798: // then to registers ! 799: ! 800: ulBank0 = pdsurf->ulWindowBank[0]; ! 801: ulBank1 = pdsurf->ulWindowBank[1]; ! 802: pBankFn = pdsurf->pfnBankSwitchCode; ! 803: _asm mov eax,ulBank0; ! 804: _asm mov edx,ulBank1; ! 805: pBankFn(); // actually switch the banks ! 806: ! 807: _asm popfd ! 808: } ! 809: ! 810: ! 811: /******************************Private*Routine******************************\ ! 812: * Bank2Window1RW ! 813: * ! 814: * Maps in the one window in 1R/W case. Does exactly the same thing as the ! 815: * one window case, because there's only one window, but has to be a separate ! 816: * entry point because of the extra parameter (because we're using STDCALL). ! 817: \**************************************************************************/ ! 818: ! 819: void Bank2Window1RW(PDEVSURF pdsurf, LONG lScan, ! 820: BANK_JUST ulJustification, ULONG ulWindowToMap) ! 821: { ! 822: Bank1Window(pdsurf, lScan, ulJustification); ! 823: } ! 824: ! 825: ! 826: /******************************Private*Routine******************************\ ! 827: * Bank2Window2RW ! 828: * ! 829: * Maps in one of two windows, either the source window (window 0) or the dest ! 830: * window (window 1), to allows access to lScan. Applies to 2RW window ! 831: * banking scheme; should never be called for 1 RW window schemes, because ! 832: * there's only one window in that case. ! 833: \**************************************************************************/ ! 834: ! 835: void Bank2Window2RW(PDEVSURF pdsurf, LONG lScan, ! 836: BANK_JUST ulJustification, ULONG ulWindowToMap) ! 837: { ! 838: ULONG ulBank; ! 839: PBANK_INFO pbiWorking; ! 840: volatile ULONG ulBank0, ulBank1; ! 841: volatile PFN pBankFn; ! 842: ! 843: // ASM routines that call this may have STD in effect, but the C compiler ! 844: // assumes CLD ! 845: ! 846: _asm pushfd ! 847: _asm cld ! 848: ! 849: // Find the bank containing the scan line with the desired justification ! 850: if (ulJustification == JustifyTop) { ! 851: ! 852: // Map scan line in as near as possible to the top of the window ! 853: ulBank = pdsurf->ulBankInfo2RWLength-1; ! 854: pbiWorking = pdsurf->pbiBankInfo2RW + ulBank; ! 855: while (pbiWorking->rclBankBounds.top > lScan) { ! 856: ulBank--; ! 857: pbiWorking--; ! 858: } ! 859: ! 860: } else { ! 861: ! 862: // Map scan line in as near as possible to the bottom of the window ! 863: ulBank = 0; ! 864: pbiWorking = pdsurf->pbiBankInfo2RW; ! 865: while (pbiWorking->rclBankBounds.bottom <= lScan) { ! 866: ulBank++; ! 867: pbiWorking++; ! 868: } ! 869: ! 870: } ! 871: ! 872: // Set the clip rect for this bank; if it's set to -1, that indicates that ! 873: // a single-window set-up is currently active, so invalidate single-window ! 874: // clip rects and display memory pointers (when double-window is active, ! 875: // single-window is inactive, and vice-versa; a full bank set-up has to be ! 876: // performed to switch between the two) ! 877: ! 878: if (pdsurf->rcl2WindowClip[ulWindowToMap].top == -1) { ! 879: ! 880: pdsurf->rcl1WindowClip.top = ! 881: pdsurf->rcl1WindowClip.bottom = ! 882: pdsurf->rcl1WindowClip.right = ! 883: pdsurf->rcl1WindowClip.left = -1; ! 884: pdsurf->pvBitmapStart = (PDEVSURF) 0; ! 885: ! 886: // Neither of the 2 window windows was active, so we have to set up the ! 887: // variables for the other bank (the one other than the one we were ! 888: // called to set) as well, to make it valid. The other bank is set to ! 889: // the same state as the bank we were called to set ! 890: pdsurf->rcl2WindowClip[ulWindowToMap^1] = pbiWorking->rclBankBounds; ! 891: if (ulWindowToMap == 1) { ! 892: pdsurf->pvBitmapStart2Window[0] = ! 893: (PVOID) ((UCHAR *)pdsurf->pvStart - pbiWorking->ulBankOffset); ! 894: } else { ! 895: pdsurf->pvBitmapStart2Window[1] = ! 896: (PVOID) ((UCHAR *)pdsurf->pvStart - pbiWorking->ulBankOffset + ! 897: BANK_SIZE_2RW_WINDOW); ! 898: } ! 899: pdsurf->ulWindowBank[ulWindowToMap^1] = ulBank; ! 900: } else { ! 901: // ASSERT(pdsurf->rcl1WindowClip.top == -1, ! 902: // "BANK.C: 1 bank not mapped out"); ! 903: } ! 904: ! 905: pdsurf->rcl2WindowClip[ulWindowToMap] = pbiWorking->rclBankBounds; ! 906: ! 907: // Shift the bitmap start address so that the desired bank aligns with the ! 908: // banking window ! 909: ! 910: if (ulWindowToMap == 0) { ! 911: pdsurf->pvBitmapStart2Window[0] = ! 912: (PVOID) ((UCHAR *)pdsurf->pvStart - pbiWorking->ulBankOffset); ! 913: } else { ! 914: pdsurf->pvBitmapStart2Window[1] = ! 915: (PVOID) ((UCHAR *)pdsurf->pvStart - pbiWorking->ulBankOffset + ! 916: BANK_SIZE_2RW_WINDOW); ! 917: } ! 918: ! 919: // Map in the desired bank; also map in the other bank to whatever its ! 920: // current state is ! 921: ! 922: pdsurf->ulWindowBank[ulWindowToMap] = ulBank; ! 923: ! 924: // Set both banks at once, because we may have just initialized the other ! 925: // bank, and because this way the bank switch code doesn't have to do a ! 926: // read before write to obtain the state of the other bank. ! 927: // This is so convoluted to avoid problems with wiping out registers C ! 928: // thinks it's still using; the values are tranferred to volatiles, and ! 929: // then to registers ! 930: ! 931: ulBank0 = pdsurf->ulWindowBank[0]; ! 932: ulBank1 = pdsurf->ulWindowBank[1]; ! 933: pBankFn = pdsurf->pfnBankSwitchCode; ! 934: _asm mov eax,ulBank0; ! 935: _asm mov edx,ulBank1; ! 936: pBankFn(); // actually switch the banks ! 937: ! 938: _asm popfd ! 939: } ! 940: ! 941: ! 942: /************************************************************************\ ! 943: * DrvIntersectRect ! 944: * ! 945: * Calculates the intersection between *prcSrc1 and *prcSrc2, ! 946: * returning the resulting rect in *prcDst. Returns TRUE if ! 947: * *prcSrc1 intersects *prcSrc2, FALSE otherwise. If there is no ! 948: * intersection, an empty rect is returned in *prcDst ! 949: \************************************************************************/ ! 950: static const RECTL rclEmpty = { 0, 0, 0, 0 }; ! 951: ! 952: BOOL DrvIntersectRect( ! 953: PRECTL prcDst, ! 954: PRECTL prcSrc1, ! 955: PRECTL prcSrc2) ! 956: ! 957: { ! 958: prcDst->left = max(prcSrc1->left, prcSrc2->left); ! 959: prcDst->right = min(prcSrc1->right, prcSrc2->right); ! 960: ! 961: /* ! 962: * check for empty rect ! 963: */ ! 964: if (prcDst->left < prcDst->right) { ! 965: ! 966: prcDst->top = max(prcSrc1->top, prcSrc2->top); ! 967: prcDst->bottom = min(prcSrc1->bottom, prcSrc2->bottom); ! 968: ! 969: /* ! 970: * check for empty rect ! 971: */ ! 972: if (prcDst->top < prcDst->bottom) { ! 973: return TRUE; // not empty ! 974: } ! 975: } ! 976: ! 977: /* ! 978: * empty rect ! 979: */ ! 980: *prcDst = rclEmpty; ! 981: ! 982: return FALSE; ! 983: } ! 984: ! 985: /************************************************************************\ ! 986: * vForceBank0 ! 987: * ! 988: * Forces the VGA to map in bank 0 if there's banking. Intended for use ! 989: * when returning from fullscreen, so a known bank is mapped. ! 990: \************************************************************************/ ! 991: VOID vForceBank0( ! 992: PPDEV ppdev) ! 993: { ! 994: PDEVSURF pdsurf = ppdev->pdsurf; ! 995: ! 996: if (pdsurf->vbtBankingType != VideoNotBanked) { ! 997: ! 998: // Set all clip rects to invalid; they'll be updated when we map in ! 999: // bank 0 ! 1000: pdsurf->rcl1WindowClip.left = pdsurf->rcl2WindowClip[0].left = ! 1001: pdsurf->rcl2WindowClip[1].left = pdsurf->rcl1WindowClip.top = ! 1002: pdsurf->rcl2WindowClip[0].top = pdsurf->rcl2WindowClip[1].top = ! 1003: pdsurf->rcl1WindowClip.right = pdsurf->rcl2WindowClip[0].right = ! 1004: pdsurf->rcl2WindowClip[1].right = pdsurf->rcl1WindowClip.bottom = ! 1005: pdsurf->rcl2WindowClip[0].bottom = ! 1006: pdsurf->rcl2WindowClip[1].bottom = -1; ! 1007: ! 1008: // Map in scan line 0 for read & write, to put things in a known state ! 1009: pdsurf->pfnBankControl(pdsurf, 0, JustifyTop); ! 1010: } ! 1011: } ! 1012:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.