Annotation of ntddk/src/video/displays/vga/bank.c, revision 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.