/** ** VESA.C ---- VESA compatible paging routines ** ** Copyright (C) 1991 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954 ** Copyright (C) 1992 Csaba Biegl, 820 Stirrup Dr, Nashville, TN 37221 ** Copyright (C) 1993 Grzegorz Mazur, gbm@ii.pw.edu.pl ** ** This file is distributed under the terms listed in the document ** "copying.dj", available from DJ Delorie at the address above. ** A copy of "copying.dj" should accompany this file; if not, a copy ** should be available from where this file was obtained. This file ** may not be distributed without a verbatim copy of "copying.dj". ** ** This file is distributed WITHOUT ANY WARRANTY; without even the implied ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. **/ int VESA_win_write = 0; /* VESA window index of the writable page */ int VESA_win_read = (-1); /* VESA window index of the readable page */ void far paging_routine(void) { return; } void far VESA_paging_routine(void) { asm push ds; asm push es; asm mov cl,BYTE PTR cs:[driver_header.page_gran_shift]; asm mov dl,al; asm xor dh,dh; asm shl dx,cl; /* DX: write window (A or B) index */ asm mov al,ah; asm xor ah,ah; asm shl ax,cl; /* AX: read window index */ asm mov bx,WORD PTR cs:[VESA_win_write]; /* index (A or B) of write window */ asm cmp bx,(-1); /* set it ? */ asm je set_read_window; asm push ax; /* save read window */ asm mov ax,0x4f05; asm call DWORD PTR cs:[driver_header.VESA_paging_fnc]; asm pop ax; set_read_window: asm mov bx,WORD PTR cs:[VESA_win_read]; /* index (A or B) of read window */ asm cmp bx,(-1); /* set it ? */ asm je paging_done; asm mov dx,ax; asm mov ax,0x4f05; asm call DWORD PTR cs:[driver_header.VESA_paging_fnc]; paging_done: asm pop es; asm pop ds; asm mov al,8; /* reconfig GR CTRL port for mask writes */ asm mov dx,0x3ce; /* GRX expects it in 16 color modes, and */ asm out dx,al; /* the paging func may have changed it */ return; } int setup_VESA_paging(GrModeEntry *md) { ModeInfoBlock *mb = VESAgetModeInfo(md->mode.vdr.BIOS_mode); int winsize,wingran,Aattr,Battr,Sdiff; if(!mb || !(mb->ModeAttributes & MODE_ISGRAPHICS)) { VESA_win_read = (-1); VESA_win_write = (-1); driver_header.VESA_paging_fnc = 0L; driver_header.paging_routine = FP_OFF(paging_routine); return(GRD_NO_RW); } /* size and granularity must be pwr of 2! */ for(winsize = 0; (1 << winsize) < mb->WinSize; winsize++) ; for(wingran = 0; (1 << wingran) < mb->WinGranularity; wingran++) ; if((1 << winsize) != mb->WinSize) return(-1); if((1 << wingran) != mb->WinGranularity) return(-1); /* check window attributes */ Aattr = mb->WinAAttributes; Battr = mb->WinBAttributes; Sdiff = mb->WinBSegment - mb->WinASegment; Aattr &= (Aattr & WIN_SUPPORTED) ? (WIN_READABLE | WIN_WRITABLE) : 0; Battr &= (Battr & WIN_SUPPORTED) ? (WIN_READABLE | WIN_WRITABLE) : 0; /* cases with two adjacent split R/W pages (ATI) */ if((Aattr == (WIN_READABLE | WIN_WRITABLE)) && (Battr == (WIN_READABLE | WIN_WRITABLE)) && (Sdiff == ((1024 / 16) << winsize))) { driver_header.wr_page_start = mb->WinASegment; driver_header.rd_page_start = mb->WinBSegment; VESA_win_write = 0; VESA_win_read = 1; } else if((Aattr == (WIN_READABLE | WIN_WRITABLE)) && (Battr == (WIN_READABLE | WIN_WRITABLE)) && (Sdiff == ((-1024 / 16) << winsize))) { driver_header.wr_page_start = mb->WinBSegment; driver_header.rd_page_start = mb->WinASegment; VESA_win_write = 1; VESA_win_read = 0; } /* cases with one full R and one full W page (Tseng 4000) */ else if((Aattr & WIN_READABLE) && (Battr & WIN_WRITABLE) && (Sdiff == 0)) { driver_header.wr_page_start = mb->WinBSegment; driver_header.rd_page_start = mb->WinASegment; VESA_win_write = 1; VESA_win_read = 0; } else if((Aattr & WIN_WRITABLE) && (Battr & WIN_READABLE) && (Sdiff == 0)) { driver_header.wr_page_start = mb->WinASegment; driver_header.rd_page_start = mb->WinBSegment; VESA_win_write = 0; VESA_win_read = 1; } /* single page cases (Trident) */ else if(Aattr == (WIN_WRITABLE | WIN_READABLE)) { driver_header.wr_page_start = mb->WinASegment; driver_header.rd_page_start = 0xffff; VESA_win_write = 0; VESA_win_read = (-1); } else if(Battr == (WIN_WRITABLE | WIN_READABLE)) { driver_header.wr_page_start = mb->WinBSegment; driver_header.rd_page_start = 0xffff; VESA_win_write = 1; VESA_win_read = (-1); } /* cannot use the paging scheme of this card */ else return(-1); /* setup header variables */ driver_header.page_size_shift = winsize - 2; /* in 4kByte units */ driver_header.page_gran_shift = winsize - wingran; driver_header.line_offset = mb->BytesPerScanLine; driver_header.VESA_paging_fnc = mb->WinFuncPtr; driver_header.paging_routine = FP_OFF(VESA_paging_routine); return((VESA_win_read == (-1)) ? GRD_NO_RW : GRD_RW_64K); }