home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <ctype.h>
- #include <dos.h>
- #include <stdlib.h>
- #include <conio.h>
-
- /* vgapos.c - version 1.0 Copyright (c) May 8, 1991 by
- Robert W. Babcock and WSS Division of DDC
- 4 Reeves Road
- Bedford, MA 01730
- USA
- 617-275-1183
-
- Display screens in various modes and accept input to change VGA CRTC
- registers which control centering and other aspects of the display.
- Print a table of values to be stuffed into the VGA registers by a
- memory resident routine such as the accompanying VGAMOVE.ASM. This
- program was specifically written for the ATI VGA Wonder card, but it
- should be portable to other VGA cards with minor modifications.
-
- Warning: playing with VGA CRTC registers changes the timing signals sent
- to your monitor. Such changes could make your monitor very unhappy,
- possibly even to the point of causing permanant hardware damage. This
- routine is supplied in source code form so that you can see exactly what
- it does and make modifications to adapt it to your video board. The
- author specifically disclaims any responsibility for any harmful
- consequences which may arise out of your use of this code.
- */
-
- /* Prototypes for local routines
- */
- int add_reg(int incr, struct vga_regs *bios_value, struct vga_regs *old_value,
- int crt_reg);
- void bios_mode(int mode);
- void border_set(void);
- void enable_regs(void);
- void fill_screen(unsigned int segment);
- void help_print(int mode, struct vga_regs *bios_regs,
- struct vga_regs *current_regs);
- void poke_vga(int crt_reg, int data);
- int range_check(int old_value, int increment, int max_value);
- void set_mode(int mode, int mono, struct vga_regs *bios_value,
- struct vga_regs *new_value);
-
- #define INPUT_STATUS_1 0x3da
- #define INPUT_STATUS_1_MONO 0x3ba
- #define ATTR_ADDRESS_WRITE 0x3c0
- #define ATTR_ADDRESS_READ 0x3c1
- #define INDEX_ATTR_PALBASE 0 /* palette registers 0-f */
- #define INDEX_ATTR_MCR 0x10 /* mode control register */
- #define INDEX_ATTR_OCR 0x11 /* overscan color register */
- #define INDEX_ATTR_CPE 0x12 /* color plane enable register */
- #define INDEX_ATTR_HPP 0x13 /* horizontal pixel panning register */
- #define INDEX_ATTR_CS 0x14 /* color select register */
-
- #define SEQ_ADDRESS 0x3c4
- #define SEQ_DATA 0x3c5
- #define INDEX_SEQ_RR 0 /* reset register */
- #define INDEX_SEQ_CM 1 /* clocking mode register */
- #define INDEX_SEQ_MAP 2 /* map mask register */
- #define INDEX_SEQ_CMS 3 /* character map select register */
- #define INDEX_SEQ_MEM 4 /* memory mode register */
-
- #define CRTC_ADDRESS 0x3d4
- #define CRTC_ADDRESS_MONO 0x3b4
- #define CRTC_DATA 0x3d5
- #define CRTC_DATA_MONO 0x3b5
- #define INDEX_CRTC_HT 0 /* horizontal total register */
- #define INDEX_CRTC_HDE 1 /* horizontal display end register */
- #define INDEX_CRTC_SHB 2 /* start horizontal blanking register */
- #define INDEX_CRTC_EHB 3 /* end horizontal blanking register */
- #define INDEX_CRTC_SHR 4 /* start horizontal retrace register */
- #define INDEX_CRTC_EHR 5 /* end horizontal retrace register */
- #define INDEX_CRTC_VT 6 /* vertical total register */
- #define INDEX_CRTC_OF 7 /* overflow register */
- #define INDEX_CRTC_PRS 8 /* preset row scan register */
- #define INDEX_CRTC_MSL 9 /* maximum scan line register */
- #define INDEX_CRTC_CS 0xa /* cursor start register */
- #define INDEX_CRTC_CE 0xb /* cursor end register */
- #define INDEX_CRTC_SAH 0xc /* start address high register */
- #define INDEX_CRTC_SAL 0xd /* start address low register */
- #define INDEX_CRTC_CLH 0xe /* cursor location high register */
- #define INDEX_CRTC_CLL 0xf /* cursor location low register */
- #define INDEX_CRTC_VRS 0x10 /* vertical retrace start register */
- #define INDEX_CRTC_EVR 0x11 /* vertical retrace end register */
- #define INDEX_CRTC_VDE 0x12 /* vertical display end register */
- #define INDEX_CRTC_OFF 0x13 /* offset register */
- #define INDEX_CRTC_UL 0x14 /* underline location register */
- #define INDEX_CRTC_VBS 0x15 /* start vertical blank register */
- #define INDEX_CRTC_VBE 0x16 /* end vertical blank register */
- #define INDEX_CRTC_MCR 0x17 /* mode control register */
- #define INDEX_CRTC_LCR 0x18 /* line compare register */
-
- #define GCR_ADDRESS 0x3ce
- #define GCR_DATA 0x3cf
- #define INDEX_GCR_SR 0 /* set/reset register */
- #define INDEX_GCR_ESR 1 /* enable set/reset register */
- #define INDEX_GCR_CC 2 /* color compare register */
- #define INDEX_GCR_DR 3 /* data rotate register */
- #define INDEX_GCR_RMS 4 /* read map select register */
- #define INDEX_GCR_MODE 5 /* mode register */
- #define INDEX_GCR_MR 6 /* miscellaneous register */
- #define INDEX_GCR_CDC 7 /* color don't care register */
- #define INDEX_GCR_BM 8 /* bit map register */
-
- #define NMODES 25
-
- int Crtc_address, Crtc_data, Input_status_1;
- struct vga_regs
- {
- int ht; /* horizontal total */
- int hde; /* horizontal display end */
- int shb; /* start horizontal blanking */
- int ehb; /* end horizontal blanking, low 5 bits plus overflow to
- high bit of EHR, also display enable skew and
- compatible read */
- int shr; /* start horizontal retrace */
- int ehr; /* end horizontal retrace low 5 bits, also horizontal
- retrace delay and EHB overflow */
- int vt; /* vertical total, 2 additional bits in overflow
- register */
- int overflow; /* overflow of vrs, vde, vt, lc, vbs, vt */
- int msl; /* maximum scan line, also vbs overflow, lc overflow
- and 2T4 */
- int vrs; /* vertical retrace start */
- int evr; /* vertical retrace end low 4 bits, also protect registers
- 0-7, and bandwidth */
- int vde; /* vertical display end, 2 high bits in overflow reg */
- int vbs; /* start vertical blank, 2 bits in overflow register and
- maximum scan line register */
- int vbe; /* end vertical blank */
- };
-
- void main(int argc, char **argv)
- {
- /* These are the modes which the VGA board recognizes. Non-standard modes
- must be changed for different boards. These are for the ATI VGA Wonder.
- */
- int modes[NMODES]={
- 0, 1, 2, 3, 4, 5, 6, 7,
- 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x23,
- 0x27, 0x33, 0x37, 0x54, 0x61, 0x62, 0x63, 0x65,
- 0x67};
- /* These are the segments used by the various modes. These need to be known
- so that the program can stuff something into video memory to be displayed
- on the sample screen
- */
- unsigned int segs[NMODES]={
- 0xb800, 0xb800, 0xb800, 0xb800, 0xb800, 0xb800, 0xb800, 0xb000,
- 0xa000, 0xa000, 0xa000, 0xa000, 0xa000, 0xa000, 0xa000, 0xb800,
- 0xb000, 0xb800, 0xb000, 0xa000, 0xa000, 0xa000, 0xa000, 0xa000,
- 0xa000};
- /* These are 0 for color modes, 1 for mono modes. Some of the VGA registers
- have different addresses for mono and color modes.
- */
- int mono_mode[NMODES]={
- 0, 0, 0, 0, 0, 0, 0, 1,
- 0, 0, 1, 0, 0, 0, 0, 0,
- 1, 0, 1, 0, 0, 0, 0, 0,
- 0};
-
- struct vga_regs bios_value[NMODES],new_value[NMODES];
-
- int crt_reg,i;
- char *filename;
- FILE *fpout;
-
- if(argc == 1)
- filename = "REG.VGA";
- else
- filename=argv[1];
-
- if(NULL != (fpout = fopen(filename,"r")))
- {
- fclose(fpout);
- printf("\n\nFile %s for register printout already exists, "
- "ok to overwrite? ",filename);
- /* don't want a macro version of toupper which might call getchar twice
- */
- #ifdef toupper
- #undef toupper
- #endif
- if('Y' != toupper(getchar()))
- exit(1);
- }
-
- if(NULL == (fpout = fopen(filename,"w")))
- {
- printf("\n\nUnable to open %s for register printout\n", filename);
- exit(1);
- }
-
- printf("This routine will display a screen in various modes (resolutions).\n"
- "For each resolution, adjust the horizontal centering with the + and -\n"
- "keys, or hit h to see what VGA registers you can select to fiddle with\n"
- "by hitting a CAPITAL letter. When done with a mode, hit enter. The\n"
- "actual screen contents may appear as garbage for graphics modes. When\n"
- "all modes have been displayed, 80x25 text mode is selected and a table\n"
- "of results is printed to REG.VGA or to the first command line arg.\n\n"
- "Warning: monitors can get very unhappy, even to the point of self\n"
- "destruction, if you feed them strange sync signals. Hitting the space\n"
- "bar restores the BIOS defaults for the current mode, which is probably\n"
- "the safest thing to do if you lose sync while fiddling with registers.\n\n"
- "Hit ENTER to start...");
-
- getch();
-
- for(i=0; i<NMODES; i++)
- {
- set_mode(modes[i], mono_mode[i], &bios_value[i], &new_value[i]);
- fill_screen(segs[i]);
- enable_regs();
-
- /* select start horizontal retrace register in CRT controller */
- crt_reg=INDEX_CRTC_SHR;
-
- for(;;)
- {
- switch(getch())
- {
- case 'A': /* horizontal total register */
- crt_reg=INDEX_CRTC_HT;
- continue;
-
- case 'B': /* horizontal display end register */
- crt_reg=INDEX_CRTC_HDE;
- continue;
-
- case 'C': /* start horizontal blanking register */
- crt_reg=INDEX_CRTC_SHB;
- continue;
-
- case 'D': /* end horizontal blanking register */
- crt_reg=INDEX_CRTC_EHB;
- continue;
-
- case 'E': /* start horizontal retrace register */
- crt_reg=INDEX_CRTC_SHR;
- continue;
-
- case 'F': /* end horizontal retrace register */
- crt_reg=INDEX_CRTC_EHR;
- continue;
-
- case 'G': /* vertical total register */
- crt_reg=INDEX_CRTC_VT;
- continue;
-
- case 'H': /* vertical retrace start register */
- crt_reg=INDEX_CRTC_VRS;
- continue;
-
- case 'I': /* vertical retrace end register */
- crt_reg=INDEX_CRTC_EVR;
- continue;
-
- case 'J': /* vertical display end register */
- crt_reg=INDEX_CRTC_VDE;
- continue;
-
- case 'K': /* start vertical blank register */
- crt_reg=INDEX_CRTC_VBS;
- continue;
-
- case 'L': /* end vertical blank register */
- crt_reg=INDEX_CRTC_VBE;
- continue;
-
- case 'h':
- help_print(modes[i], &bios_value[i], &new_value[i]);
- fill_screen(segs[i]);
- continue;
-
- case ' ':
- set_mode(modes[i], mono_mode[i], &bios_value[i], &new_value[i]);
- enable_regs();
- fill_screen(segs[i]);
- break;
-
- case 'q':
- goto all_done;
-
- case '+':
- add_reg(1, &bios_value[i], &new_value[i], crt_reg);
- break;
-
- case '-':
- add_reg(-1, &bios_value[i], &new_value[i], crt_reg);
- break;
-
- case '\r':
- goto mode_done;
-
- default:
- printf("\a");
- break;
- }
- }
- mode_done: ;
- }
- all_done:
- bios_mode(3); /* select 80x25 color mode */
-
- for(i=0; i<NMODES; i++)
- {
- new_value[i].ehr = (new_value[i].ehr & 0x1f) | (bios_value[i].ehr & 0x60)
- | ((new_value[i].ehb & 0x20) << 2);
- new_value[i].ehb = (new_value[i].ehb & 0x1f) | (bios_value[i].ehb & 0xe0);
- new_value[i].vt &= 0xff;
- new_value[i].msl = ((new_value[i].vbs & 0x200) >> 4)
- | (bios_value[i].msl & 0xdf);
- new_value[i].vrs &= 0xff;
- new_value[i].evr = (new_value[i].evr & 0xf) | (bios_value[i].evr & 0xf0);
- new_value[i].vde &= 0xff;
- new_value[i].vbs &= 0xff;
-
- fprintf(fpout, "Mode %xh\n\nRegister old new change (decimal)\n",
- modes[i]);
- fprintf(fpout, "Horizontal total %7x%7x%6d\n", bios_value[i].ht,
- new_value[i].ht, new_value[i].ht - bios_value[i].ht);
- fprintf(fpout, "Horiz display end %7x%7x%6d\n", bios_value[i].hde,
- new_value[i].hde, new_value[i].hde - bios_value[i].hde);
- fprintf(fpout, "Start horiz blanking %7x%7x%6d\n", bios_value[i].shb,
- new_value[i].shb, new_value[i].shb - bios_value[i].shb);
- fprintf(fpout, "End horiz blanking %7x%7x%6d\n", bios_value[i].ehb,
- new_value[i].ehb, new_value[i].ehb - bios_value[i].ehb);
- fprintf(fpout, "Start horiz retrace %7x%7x%6d\n", bios_value[i].shr,
- new_value[i].shr, new_value[i].shr - bios_value[i].shr);
- fprintf(fpout, "End horiz retrace %7x%7x%6d\n", bios_value[i].ehr,
- new_value[i].ehr, new_value[i].ehr - bios_value[i].ehr);
- fprintf(fpout, "Vertical total %7x%7x%6d\n", bios_value[i].vt,
- new_value[i].vt, new_value[i].vt - bios_value[i].vt);
- fprintf(fpout, "Overflow %7x%7x%6d\n", bios_value[i].overflow,
- new_value[i].overflow, new_value[i].overflow - bios_value[i].overflow);
- fprintf(fpout, "Maximum scan line %7x%7x%6d\n", bios_value[i].msl,
- new_value[i].msl, new_value[i].msl - bios_value[i].msl);
- fprintf(fpout, "Vert retrace start %7x%7x%6d\n", bios_value[i].vrs,
- new_value[i].vrs, new_value[i].vrs - bios_value[i].vrs);
- fprintf(fpout, "Vert retrace end %7x%7x%6d\n", bios_value[i].evr,
- new_value[i].evr, new_value[i].evr - bios_value[i].evr);
- fprintf(fpout, "Vert display end %7x%7x%6d\n", bios_value[i].vde,
- new_value[i].vde, new_value[i].vde - bios_value[i].vde);
- fprintf(fpout, "Vert blank start %7x%7x%6d\n", bios_value[i].vbs,
- new_value[i].vbs, new_value[i].vbs - bios_value[i].vbs);
- fprintf(fpout, "Vert blank end %7x%7x%6d\n\n\n", bios_value[i].vbe,
- new_value[i].vbe, new_value[i].vbe - bios_value[i].vbe);
- }
- return;
- }
-
- /* add_reg - add an incr to a crtc register, checking for overflow.
- return the new register value.
- */
- int add_reg(int incr, struct vga_regs *bios_value, struct vga_regs *old_value,
- int crt_reg)
- {
- int new_value;
-
- switch(crt_reg)
- {
- case INDEX_CRTC_HT: /* horizontal total register */
- new_value = old_value->ht = range_check(old_value->ht, incr, 0xff);
- poke_vga(crt_reg, new_value);
- break;
-
- case INDEX_CRTC_HDE: /* horizontal display end register */
- new_value = old_value->hde = range_check(old_value->hde, incr, 0xff);
- poke_vga(crt_reg, new_value);
- break;
-
- case INDEX_CRTC_SHB: /* start horizontal blanking register */
- new_value = old_value->shb = range_check(old_value->shb, incr, 0xff);
- poke_vga(crt_reg, new_value);
- break;
-
- case INDEX_CRTC_EHB: /* end horizontal blanking register */
- new_value = old_value->ehb = range_check(old_value->ehb, incr, 0x3f);
- poke_vga(crt_reg,
- (new_value & 0x1f) | (bios_value->ehb & 0x60) | 0x80);
- new_value = ((new_value & 0x20) << 2) | (bios_value->ehr & 0x60)
- | old_value->ehr;
- poke_vga(INDEX_CRTC_EHR, new_value);
- break;
-
- case INDEX_CRTC_SHR: /* start horizontal retrace register */
- new_value = old_value->shr = range_check(old_value->shr, incr, 0xff);
- poke_vga(crt_reg, new_value);
- break;
-
- case INDEX_CRTC_EHR: /* end horizontal retrace register */
- new_value = old_value->ehr = range_check(old_value->ehr, incr, 0x1f);
- poke_vga(crt_reg, new_value | (bios_value->ehr & 0x60)
- | ((old_value->ehb & 0x20) << 2));
- break;
-
- case INDEX_CRTC_VT: /* vertical total register */
- new_value = old_value->vt = range_check(old_value->vt, incr, 0x3ff);
- poke_vga(crt_reg, new_value & 0xff);
- new_value = (((new_value & 0x100) >> 8) | ((new_value & 0x200) >> 4)
- | (old_value->overflow & 0xde));
- poke_vga(INDEX_CRTC_OF, new_value);
- old_value->overflow = new_value;
- break;
-
- case INDEX_CRTC_OF:
- poke_vga(INDEX_CRTC_OF, old_value->overflow);
- break;
-
- case INDEX_CRTC_MSL:
- poke_vga(INDEX_CRTC_MSL,
- ((old_value->vbs & 0x200) >> 4) | (bios_value->msl & 0xdf));
- break;
-
- case INDEX_CRTC_VRS: /* vertical retrace start register */
- new_value = old_value->vrs = range_check(old_value->vrs, incr, 0x3ff);
- poke_vga(crt_reg,new_value & 0xff);
- new_value = (((new_value & 0x100) >> 6) | ((new_value & 0x200) >> 2)
- | (old_value->overflow & 0x7b));
- poke_vga(INDEX_CRTC_OF, new_value);
- old_value->overflow = new_value;
- break;
-
- case INDEX_CRTC_EVR: /* vertical retrace end register */
- new_value = old_value->evr = range_check(old_value->evr, incr, 0xf);
- poke_vga(crt_reg, new_value | (bios_value->evr & 0x70));
- break;
-
- case INDEX_CRTC_VDE: /* vertical display end register */
- new_value = old_value->vde = range_check(old_value->vde, incr, 0x3ff);
- poke_vga(crt_reg, new_value & 0xff);
- new_value = (((new_value & 0x100) >> 7) | ((new_value & 0x200) >> 3)
- | (old_value->overflow & 0xbd));
- poke_vga(INDEX_CRTC_OF, new_value);
- old_value->overflow = new_value;
- break;
-
- case INDEX_CRTC_VBS: /* start vertical blank register */
- new_value = old_value->vbs = range_check(old_value->vbs, incr, 0x3ff);
- poke_vga(crt_reg, new_value);
- new_value = (((new_value & 0x100) >> 5) | (old_value->overflow & 0xf7));
- poke_vga(INDEX_CRTC_OF, new_value);
- old_value->overflow = new_value;
- new_value = (((old_value->vbs & 0x200) >> 4) | (bios_value->msl & 0xdf));
- poke_vga(INDEX_CRTC_MSL, new_value);
- old_value->msl = new_value;
- break;
-
- case INDEX_CRTC_VBE: /* end vertical blank register */
- new_value = old_value->vbe = range_check(old_value->vbe, incr, 0xff);
- poke_vga(crt_reg, new_value);
- break;
- }
- return(new_value);
- }
-
- /* bios_mode - call bios to select a video mode. For many cards, this is done
- by putting the mode in AL, setting AH=0 and issuing INT 10h. Some boards,
- such as the Vega VGA do it differently
- */
- void bios_mode(int mode)
- {
- union REGS regs;
-
- regs.x.ax=mode; /* select mode */
- int86(0x10,®s,®s);
- return;
- }
-
- /* border_set - set border color
- */
- void border_set(void)
- {
- inportb(INPUT_STATUS_1);
- outportb(ATTR_ADDRESS_WRITE, 0x31);
- outportb(ATTR_ADDRESS_WRITE, 9);
-
- return;
- }
-
- /* enable_regs
- */
- void enable_regs(void)
- {
- int temp;
-
- /* enable access to lower 7 CRTC registers
- */
- outportb(Crtc_address, INDEX_CRTC_EVR);
- temp=inportb(Crtc_data);
- temp &= 0x7f;
- outportb(Crtc_data, temp);
-
- /* enable access to vertical retrace start/end registers
- */
- outportb(Crtc_address, INDEX_CRTC_EHB);
- temp=inportb(Crtc_data);
- temp |= 0x80;
- outportb(Crtc_data, temp);
-
- return;
- }
-
- /* fill_screen - make sure something is displayed, also set border color
- */
- void fill_screen(unsigned int segment)
- {
- long l,nfill;
- char far *video_memory;
-
- video_memory=MK_FP(segment,0); /* make sure something is displayed */
- switch(segment)
- {
- case 0xa000:
- case 0xb000:
- nfill = 64L * 1024L;
- break;
-
- default:
- case 0xb800:
- nfill = 32L * 1024L;
- break;
- }
- for(l=0; l<nfill; l++)
- *(video_memory++)='A' + (l % 26);
-
- border_set();
-
- return;
- }
-
- /* help_print - switch to test mode, print a help screen, switch back
- to mode being set
- */
- void help_print(int mode, struct vga_regs *bios_regs, struct vga_regs *current_regs)
- {
- int i;
-
- bios_mode(3); /* select 80x25 color mode */
- border_set();
-
- fprintf(stderr,"To select a register, hit a CAPITAL letter:\n\n"
- "A - horizontal total register (left/right centering within overscan)\n"
- "B - horizontal display end register (# chars in line, don't change)\n"
- "C - start horizontal blanking register (right side overscan size)\n"
- "D - end horizontal blanking register (left side overscan size)\n"
- "E - start horizontal retrace register (left/right centering)\n"
- "F - end horizontal retrace register\n"
- "G - vertical total register (height inside overscan region)\n"
- "H - vertical retrace start register (up/down centering)\n"
- "I - vertical retrace end register\n"
- "J - vertical display end register (# scan lines, don't change)\n"
- "K - start vertical blank register (bottom overscan, retrace blanking)\n"
- "L - end vertical blank register (top overscan, retrace blanking)\n\n"
- "+/- adjust value up/down, SPACE restores BIOS values\n"
- "Return advances to the next mode\n\n"
- "Current mode is %xh\n\n"
- "Hit any key to return to sample screen...", mode);
- getch();
-
- bios_mode(mode); /* select mode */
-
- enable_regs();
-
- /* restore any changes already made for this mode
- */
- for(i=INDEX_CRTC_HT; i<=INDEX_CRTC_VBE; i++)
- add_reg(0, bios_regs, current_regs, i);
-
- return;
- }
-
- /* poke_vga - change a value in a VGA CRTC register
- */
- void poke_vga(int crt_reg, int data)
- {
- outportb(Crtc_address, crt_reg);
- outportb(Crtc_data, data);
- return;
- }
-
- /* range_check - return old_value + increment if this is within the range
- 0 to max_value, otherwise beep and return unchanged old_value
- */
- int range_check(int old_value, int increment, int max_value)
- {
- int new_value;
-
- new_value = old_value + increment;
- if(new_value < 0 || new_value > max_value)
- return(old_value);
- else
- return(new_value);
- }
-
- /* set a VGA mode, read out register values into bios_value and new_value
- */
- void set_mode(int mode, int mono, struct vga_regs *bios_value,
- struct vga_regs *new_value)
- {
-
- Crtc_address=mono ? CRTC_ADDRESS_MONO : CRTC_ADDRESS;
- Crtc_data=mono ? CRTC_DATA_MONO : CRTC_DATA;
- Input_status_1=mono ? INPUT_STATUS_1_MONO : INPUT_STATUS_1;
-
- bios_mode(mode);
-
- /* read out needed VGA registers
- */
-
- outportb(Crtc_address,INDEX_CRTC_HT);
- bios_value->ht = new_value->ht = inportb(Crtc_data);
-
- outportb(Crtc_address,INDEX_CRTC_HDE);
- bios_value->hde = new_value->hde = inportb(Crtc_data);
-
- outportb(Crtc_address,INDEX_CRTC_SHB);
- bios_value->shb = new_value->shb = inportb(Crtc_data);
-
- outportb(Crtc_address,INDEX_CRTC_EHB);
- bios_value->ehb = new_value->ehb = inportb(Crtc_data);
-
- outportb(Crtc_address,INDEX_CRTC_SHR);
- bios_value->shr = new_value->shr = inportb(Crtc_data);
-
- outportb(Crtc_address,INDEX_CRTC_EHR);
- bios_value->ehr = new_value->ehr = inportb(Crtc_data);
-
- outportb(Crtc_address,INDEX_CRTC_VT);
- bios_value->vt = new_value->vt = inportb(Crtc_data);
-
- outportb(Crtc_address,INDEX_CRTC_OF);
- bios_value->overflow = new_value->overflow = inportb(Crtc_data);
-
- outportb(Crtc_address,INDEX_CRTC_MSL);
- bios_value->msl = new_value->msl = inportb(Crtc_data);
-
- outportb(Crtc_address,INDEX_CRTC_VRS);
- bios_value->vrs = new_value->vrs = inportb(Crtc_data);
-
- outportb(Crtc_address,INDEX_CRTC_EVR);
- bios_value->evr = new_value->evr = inportb(Crtc_data);
-
- outportb(Crtc_address,INDEX_CRTC_VDE);
- bios_value->vde = new_value->vde = inportb(Crtc_data);
-
- outportb(Crtc_address,INDEX_CRTC_VBS);
- bios_value->vbs = new_value->vbs = inportb(Crtc_data);
-
- outportb(Crtc_address,INDEX_CRTC_VBE);
- bios_value->vbe = new_value->vbe = inportb(Crtc_data);
-
- /* Generate actual values for things which use the overflow or other register
- */
-
- new_value->ehb = ((bios_value->ehr & 0x80) >> 2) | (0x1f & bios_value->ehb);
- new_value->ehr &= 0x1f;
- new_value->vt = ((bios_value->overflow & 0x20) << 4)
- | ((bios_value->overflow & 1) << 8) | bios_value->vt;
- new_value->vrs = ((bios_value->overflow & 0x80) << 2)
- | ((bios_value->overflow & 4) << 6) | bios_value->vrs;
- new_value->evr &= 0xf;
- new_value->vde = ((bios_value->overflow & 0x40) << 3)
- | ((bios_value->overflow & 2) << 7) | bios_value->vde;
- new_value->vbs = ((bios_value->msl & 0x20) << 4)
- | ((bios_value->overflow & 8) << 5) | bios_value->vbs;
-
- return;
- }
-