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

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

unix.superglobalmegacorp.com

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