Annotation of ntddk/src/video/displays/vga/bank.c, revision 1.1.1.1

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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.