0,0 → 1,518 |
/* |
*/ |
|
#include <stdlib.h> |
#include <stdio.h> /* for printf */ |
#include <string.h> /* for memset */ |
#include <unistd.h> |
//#include <sys/mman.h> /* for mmap */ |
#include "vga.h" |
#include "libvga.h" |
#include "driver.h" |
|
/* New style driver interface. */ |
#include "timing.h" |
#include "vgaregs.h" |
#include "interface.h" |
#include "lrmi.h" |
#include "vbe.h" |
#define VESAREG_SAVE(i) (VGA_TOTAL_REGS+i) |
#define VESA_TOTAL_REGS (VGA_TOTAL_REGS + 4024) |
|
/* #define VESA_savebitmap 0x0e */ |
int __svgalib_VESA_savebitmap=0x0e; |
int __svgalib_VESA_textmode=3; |
|
static int vesa_init(int, int, int); |
static void vesa_unlock(void); |
|
static int vesa_memory,vesa_chiptype; |
static int vesa_is_linear, vesa_logical_width, vesa_bpp, vesa_granularity; |
static int vesa_regs_size, vesa_linear_base, vesa_last_mode_set; |
static struct LRMI_regs vesa_r; |
static int vesa_read_write, vesa_read_window, vesa_write_window; |
static void * LRMI_mem1, * LRMI_mem2; |
|
static CardSpecs *cardspecs; |
static struct |
{ |
struct vbe_info_block *info; |
struct vbe_mode_info_block *mode; |
} vesa_data; |
|
static int SVGALIB_VESA[__GLASTMODE+1]; |
|
char VideoModeNames [96][40] = { |
"100 - 640x400 256 colors", "101 - 640x480 256 colors", "102 - 800x600 16 colors", |
"103 - 800x600 256 colors", "104 - 1024x768 16 colors", "105 - 1024x768 256 colors", |
"106 - 1280x1024 16 colors", "107 - 1280x1024 256 colors", "108 - 80x60 Text Mode", |
"109 - 132x25 Text Mode", "10A - 132x43 Text Mode", "10B - 132x50 Text Mode", |
"10C - 132x60 Text Mode", "10D - 320x200 32,768 colors", "10E - 320x200 65,536 colors", |
"10F - 320x200 16m colors", "110 - 640x480 32,768 colors", "111 - 640x480 65,536 colors", |
"112 - 640x480 16m colors", "113 - 800x600 32,768 colors", "114 - 800x600 65,536 colors", |
"115 - 800x600 16m colors", "116 - 1024x768 32,768 colors", "117 - 1024x768 65,536 colors", |
"118 - 1024x768 16m colors", "119 - 1280x1024 32,768 colors", "11A - 1280x1024 65,536 colors", |
"11B - 1280x1024 16m colors", "11C - 640x350 256 colors", "11D - 640x350 32,768 colors", |
"11E - 640x400 32,768 colors", "11F - 640x350 65,536 colors", "120 - 640x400 65,536 colors", |
"121 - 640x350 16m colors", "122 - 640x400 16m colors", "123 - 1600x1200 16 colors", |
"124 - 1600x1200 256 colors", "125 - 1600x1200 32,768 colors", "126 - 1600x1200 65,536 colors", |
"127 - 1600x1200 16m colors", "128 - 640x480 16m colors(*)", "129 - 800x600 16m colors(*)", |
"12A - 1024x768 16m colors(*)", "12B - 1280x1024 16m colors(*)", "12C - 1600x1200 16m colors(*)", |
"12D - 320x240 32,768 colors", "12E - 320x400 32,768 colors", "12F - 360x200 32,768 colors", |
"130 - 360x240 32,768 colors", "131 - 360x400 32,768 colors", "132 - 320x240 65,536 colors", |
"133 - 320x400 65,536 colors", "134 - 360x200 65,536 colors", "135 - 360x240 65,536 colors", |
"136 - 360x400 65,536 colors", "137 - 320x240 16m colors", "138 - 320x400 16m colors", |
"139 - name n/a", "13A - name n/a", "13B - name n/a", |
"13C - name n/a", "13D - name n/a", "13E - name n/a", |
"13F - name n/a", "140 - name n/a", "141 - name n/a", |
"142 - 640x350 16m colors(*)", "143 - 640x400 16m colors(*)", "144 - name n/a", |
"145 - name n/a", "146 - name n/a", "147 - name n/a", |
"148 - name n/a", "149 - name n/a", "14A - name n/a", |
"14B - name n/a", "14C - name n/a", "14D - name n/a", |
"14E - name n/a", "14F - name n/a", "150 - 640x350 16 colors", |
"151 - 640x400 16 colors", "152 - 640x480 16 colors", "153 - 320x200 256 colors", |
"154 - 320x240 256 colors", "155 - 320x400 256 colors", "156 - 360x200 256 colors", |
"157 - 360x240 256 colors", "158 - 360x400 256 colors", "159 - name n/a", |
"15A - name n/a", "15B - name n/a", "15C - name n/a", |
"15D - name n/a", "15E - name n/a", "15F - name n/a" |
}; |
|
static void vesa_setpage(int page) |
{ |
vesa_r.eax=0x4f05; |
vesa_r.ebx=0; |
vesa_r.edx=page*64/vesa_granularity; |
__svgalib_LRMI_int(0x10,&vesa_r); |
|
if(vesa_read_write){ |
vesa_r.eax=0x4f05; |
vesa_r.ebx=1; |
vesa_r.edx=page*64/vesa_granularity; |
__svgalib_LRMI_int(0x10,&vesa_r); |
}; |
} |
|
|
static int __svgalib_vesa_inlinearmode(void) |
{ |
return vesa_is_linear; |
} |
|
|
/* Fill in chipset specific mode information */ |
|
static void vesa_getmodeinfo(int mode, vga_modeinfo *modeinfo) |
{ |
if (IS_IN_STANDARD_VGA_DRIVER(mode)) |
return __svgalib_vga_driverspecs.getmodeinfo(mode, modeinfo); |
|
if(modeinfo->colors==16)return; |
|
modeinfo->maxpixels = vesa_memory*1024/modeinfo->bytesperpixel; |
modeinfo->maxlogicalwidth = 4088; /* just a guess, */ |
modeinfo->startaddressrange = vesa_memory * 1024 - 1; |
modeinfo->haveblit = 0; |
modeinfo->flags &= ~HAVE_RWPAGE; |
modeinfo->flags |= vesa_read_write; /* sets HAVE_RWPAGE bit */ |
|
/* for linear need VBE2 */ |
if(vesa_chiptype>=1) |
if (modeinfo->bytesperpixel >= 1) { |
modeinfo->flags |= CAPABLE_LINEAR; |
if (__svgalib_vesa_inlinearmode()) |
modeinfo->flags |= IS_LINEAR | LINEAR_MODE; |
} |
|
/* to get the logical scanline width */ |
memset(&vesa_r, 0, sizeof(vesa_r)); |
|
vesa_r.eax = 0x4f01; |
vesa_r.ecx = SVGALIB_VESA[mode]; |
vesa_r.es = (unsigned int)vesa_data.mode >> 4; |
vesa_r.edi = (unsigned int)vesa_data.mode & 0xf; |
|
if (!__svgalib_LRMI_int(0x10, &vesa_r)) { |
printk(KERN_ERR "Can't get mode info (vm86 failure)\n"); |
return; |
} |
modeinfo->linewidth = vesa_data.mode->bytes_per_scanline; |
} |
|
/* Read and save chipset-specific registers */ |
static int vesa_saveregs(uint8_t regs[]) |
{ |
void * buf; |
buf=LRMI_mem1; |
vesa_r.eax=0x4f04; |
vesa_r.ebx=0; |
vesa_r.es=((long)buf)>>4; |
vesa_r.edx=1; |
vesa_r.ecx=__svgalib_VESA_savebitmap; |
__svgalib_LRMI_int(0x10,&vesa_r); |
memcpy(®s[VGA_TOTAL_REGS],buf,vesa_regs_size); |
return vesa_regs_size; |
} |
|
/* Set chipset-specific registers */ |
|
static void vesa_setregs(const uint8_t regs[], int mode) |
{ |
|
void * buf; |
buf=LRMI_mem1; |
memcpy(buf,®s[VGA_TOTAL_REGS],vesa_regs_size); |
vesa_r.eax=0x4f04; |
vesa_r.ebx=0; |
vesa_r.es=((long)buf)>>4; |
vesa_r.edx=2; |
vesa_r.ecx=__svgalib_VESA_savebitmap; |
__svgalib_LRMI_int(0x10,&vesa_r); |
} |
|
|
/* Return nonzero if mode is available */ |
|
static int vesa_modeavailable(int mode) |
{ |
struct info *info; |
ModeTiming *modetiming; |
ModeInfo *modeinfo; |
|
|
if (IS_IN_STANDARD_VGA_DRIVER(mode)) |
return __svgalib_vga_driverspecs.modeavailable(mode); |
|
info = &__svgalib_infotable[mode]; |
|
modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); |
|
modetiming = malloc(sizeof(ModeTiming)); |
if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { |
free(modetiming); |
free(modeinfo); |
return 0; |
} |
free(modetiming); |
free(modeinfo); |
|
return SVGALIB_VESA[mode]; |
} |
|
|
static int vesa_setmode(int mode, int prv_mode) |
{ |
vesa_bpp=1; |
vesa_granularity=1; |
if (IS_IN_STANDARD_VGA_DRIVER(mode)) { |
|
if(__svgalib_vesatext){ |
vesa_r.eax=0x4f02; /* make sure we are in a regular VGA mode before we start */ |
vesa_r.ebx=__svgalib_VESA_textmode; /* without this, if we start in SVGA mode the result might */ |
__svgalib_LRMI_int(0x10,&vesa_r); /* be something weird */ |
}; |
return __svgalib_vga_driverspecs.setmode(mode, prv_mode); |
} |
if (!vesa_modeavailable(mode)) return 1; |
vesa_r.eax=0x4f02; |
vesa_r.ebx=SVGALIB_VESA[mode]|0x8000|(vesa_is_linear*0x4000); |
vesa_last_mode_set=vesa_r.ebx; |
__svgalib_LRMI_int(0x10,&vesa_r); |
|
vesa_data.info = LRMI_mem2 ; |
vesa_data.mode = (struct vbe_mode_info_block *)(vesa_data.info + 1); |
vesa_r.eax = 0x4f01; |
vesa_r.ecx=SVGALIB_VESA[mode]; |
vesa_r.es = (unsigned int)vesa_data.mode >> 4; |
vesa_r.edi = (unsigned int)vesa_data.mode&0xf; |
__svgalib_LRMI_int(0x10, &vesa_r); |
vesa_logical_width=vesa_data.mode->bytes_per_scanline; |
vesa_bpp=(vesa_data.mode->bits_per_pixel+7)/8; |
if(vesa_logical_width==0) vesa_logical_width=vesa_bpp*vesa_data.mode->x_resolution; |
/* if not reported then guess */ |
vesa_granularity=vesa_data.mode->win_granularity; |
if(vesa_granularity==0)vesa_granularity=64; /* if not reported then guess */ |
if(vesa_chiptype>=1)vesa_linear_base=vesa_data.mode->phys_base_ptr; |
vesa_read_write=0; |
vesa_read_window=0; |
vesa_write_window=0; |
if((vesa_data.mode->win_a_attributes&6)!=6){ |
vesa_read_write=1; |
if ((vesa_data.mode->win_b_attributes&2) == 2) vesa_read_window=1; |
if ((vesa_data.mode->win_b_attributes&4) == 4) vesa_write_window=1; |
} |
return 0; |
} |
|
|
/* Unlock chipset-specific registers */ |
|
static void vesa_unlock(void) |
{ |
} |
|
|
/* Relock chipset-specific registers */ |
/* (currently not used) */ |
|
static void vesa_lock(void) |
{ |
} |
|
|
/* Indentify chipset, initialize and return non-zero if detected */ |
|
int vesa_test(void) |
{ |
__svgalib_LRMI_init(); |
LRMI_mem2 = __svgalib_LRMI_alloc_real(sizeof(struct vbe_info_block) |
+ sizeof(struct vbe_mode_info_block)); |
vesa_data.info = LRMI_mem2; |
vesa_data.mode = (struct vbe_mode_info_block *)(vesa_data.info + 1); |
vesa_r.eax = 0x4f00; |
vesa_r.es = (unsigned int)vesa_data.info >> 4; |
vesa_r.ds = (unsigned int)vesa_data.info >> 4; |
vesa_r.edi = 0; |
|
__svgalib_LRMI_free_real(LRMI_mem2,sizeof(struct vbe_info_block) + sizeof(struct vbe_mode_info_block)); |
|
__svgalib_LRMI_int(0x10, &vesa_r); |
|
printk(KERN_INFO "Int 0x10 result ax=%2x\n",vesa_r.eax); |
|
if (vesa_r.eax!=0x4f) return 0; |
return !vesa_init(0,0,0); |
} |
|
|
/* No r/w paging */ |
static void vesa_setrdpage(int page) |
{ |
vesa_r.eax=0x4f05; |
vesa_r.ebx=vesa_read_window; |
vesa_r.edx=page*64/vesa_granularity; |
__svgalib_LRMI_int(0x10,&vesa_r); |
} |
static void vesa_setwrpage(int page) |
{ |
vesa_r.eax=0x4f05; |
vesa_r.ebx=vesa_write_window; |
vesa_r.edx=page*64/vesa_granularity; |
__svgalib_LRMI_int(0x10,&vesa_r); |
} |
|
|
/* Set display start address (not for 16 color modes) */ |
|
static void vesa_setdisplaystart(int address) |
{ |
vesa_r.eax=0x4f07; |
vesa_r.ebx=0; |
vesa_r.ecx=address % vesa_logical_width; |
vesa_r.edx=address / vesa_logical_width; |
|
__svgalib_LRMI_int(0x10,&vesa_r); |
|
} |
|
/* Set logical scanline length (usually multiple of 8) */ |
|
static void vesa_setlogicalwidth(int width) |
{ |
vesa_r.eax=0x4f06; |
vesa_r.ebx=0; |
vesa_r.ecx=width / vesa_bpp ; |
__svgalib_LRMI_int(0x10,&vesa_r); |
vesa_logical_width=vesa_r.ebx; |
|
} |
|
static int vesa_linear(int op, int param) |
{ |
if (op==LINEAR_ENABLE) { |
vesa_r.eax=0x4f02; |
vesa_r.ebx=vesa_last_mode_set|0x4000; |
__svgalib_LRMI_int(0x10,&vesa_r); |
vesa_is_linear=1; |
}; |
|
if (op==LINEAR_DISABLE){ |
vesa_r.eax=0x4f02; |
vesa_r.ebx=vesa_last_mode_set; |
__svgalib_LRMI_int(0x10,&vesa_r); |
vesa_is_linear=0; |
}; |
if (op==LINEAR_QUERY_BASE) {return vesa_linear_base ;} |
if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) return 0; /* No granularity or range. */ |
else return -1; /* Unknown function. */ |
} |
|
static int vesa_match_programmable_clock(int clock) |
{ |
return clock ; |
} |
static int vesa_map_clock(int bpp, int clock) |
{ |
return clock ; |
} |
static int vesa_map_horizontal_crtc(int bpp, int pixelclock, int htiming) |
{ |
return htiming; |
} |
/* Function table (exported) */ |
|
DriverSpecs __svgalib_vesa_driverspecs = |
{ |
vesa_saveregs, |
vesa_setregs, |
vesa_unlock, |
vesa_lock, |
vesa_test, |
vesa_init, |
vesa_setpage, |
vesa_setrdpage, |
vesa_setwrpage, |
vesa_setmode, |
vesa_modeavailable, |
vesa_setdisplaystart, |
vesa_setlogicalwidth, |
vesa_getmodeinfo, |
0, /* old blit funcs */ |
0, |
0, |
0, |
0, |
0, /* ext_set */ |
0, /* accel */ |
vesa_linear, |
0, /* accelspecs, filled in during init. */ |
NULL, /* Emulation */ |
}; |
|
/* Initialize chipset (called after detection) */ |
|
static int vesa_init(int force, int par1, int par2) |
{ |
short int *mode_list; |
int i; |
|
__svgalib_textprog|=1; |
|
/* Get I/O priviledge */ |
|
if (force) { |
vesa_memory = par1; |
vesa_chiptype = par2; |
} else { |
vesa_memory=4096; |
}; |
|
vesa_data.info = __svgalib_LRMI_alloc_real(sizeof(struct vbe_info_block) |
+ sizeof(struct vbe_mode_info_block)); |
vesa_data.mode = (struct vbe_mode_info_block *)(vesa_data.info + 1); |
vesa_r.eax = 0x4f00; |
vesa_r.es = (unsigned int)vesa_data.info >> 4; |
vesa_r.ds = (unsigned int)vesa_data.info >> 4; |
vesa_r.edi = 0; |
|
memcpy(vesa_data.info->vbe_signature, "VBE2", 4); |
|
__svgalib_LRMI_int(0x10, &vesa_r); |
|
if ((vesa_r.eax & 0xffff) != 0x4f || strncmp(vesa_data.info->vbe_signature, "VESA", 4) != 0) { |
printk(KERN_ERR "No VESA bios detected!\n"); |
printk(KERN_ERR "Try running vga_reset.\n"); |
return 1; |
} |
|
if(vesa_data.info->vbe_version>=0x0200)vesa_chiptype=1 ; else vesa_chiptype=0; |
if(vesa_data.info->vbe_version>=0x0300)vesa_chiptype=2 ; |
|
vesa_memory = vesa_data.info->total_memory*64; |
|
for(i=0;i<__GLASTMODE;i++)SVGALIB_VESA[i]=IS_IN_STANDARD_VGA_DRIVER(i); |
|
mode_list = (short int *)(vesa_data.info->video_mode_list_seg * 16 + vesa_data.info->video_mode_list_off); |
|
while (*mode_list != -1) { |
memset(&vesa_r, 0, sizeof(vesa_r)); |
|
vesa_r.eax = 0x4f01; |
vesa_r.ecx = *mode_list; |
vesa_r.es = (unsigned int)vesa_data.mode >> 4; |
vesa_r.ds = (unsigned int)vesa_data.mode >> 4; |
vesa_r.edi = (unsigned int)vesa_data.mode & 0xf; |
|
if((vesa_chiptype>=1)&&(vesa_data.mode->mode_attributes&0x80)) |
vesa_linear_base=vesa_data.mode->phys_base_ptr; |
if (!__svgalib_LRMI_int(0x10, &vesa_r)) { |
printk(KERN_ERR "Can't get mode info (vm86 failure)\n"); |
return 1; |
} |
|
for(i=0;i<=__GLASTMODE;i++) |
if((infotable[i].xdim==vesa_data.mode->x_resolution)&& |
(infotable[i].ydim==vesa_data.mode->y_resolution)&& |
(((vesa_data.mode->rsvd_mask_size==8)&&(infotable[i].bytesperpixel==4))|| |
((vesa_data.mode->bits_per_pixel==32)&&(infotable[i].bytesperpixel==4))|| |
((vesa_data.mode->bits_per_pixel==24)&&(infotable[i].bytesperpixel==3))|| |
((vesa_data.mode->green_mask_size==5)&&(infotable[i].colors==32768))|| |
((vesa_data.mode->green_mask_size==6)&&(infotable[i].colors==65536))|| |
((vesa_data.mode->memory_model==VBE_MODEL_PLANAR)&&(infotable[i].colors==16))|| |
((vesa_data.mode->memory_model==VBE_MODEL_256)&&(infotable[i].colors==256))|| |
((vesa_data.mode->memory_model==VBE_MODEL_PACKED)&& |
(infotable[i].colors==256)&&(vesa_data.mode->bits_per_pixel==8)))){ |
SVGALIB_VESA[i]=*mode_list; |
i=__GLASTMODE+1; |
}; |
|
mode_list++; |
|
}; |
|
vesa_r.eax=0x4f04; |
vesa_r.edx=0; |
vesa_r.ecx=__svgalib_VESA_savebitmap; |
vesa_r.ebx=0; |
__svgalib_LRMI_int(0x10,&vesa_r); |
vesa_regs_size=vesa_r.ebx*64; |
__svgalib_LRMI_free_real(vesa_data.info,sizeof(vesa_data.info)); |
|
SVGALIB_VESA[TEXT]=3; |
|
cardspecs = malloc(sizeof(CardSpecs)); |
cardspecs->videoMemory = vesa_memory; |
cardspecs->maxPixelClock4bpp = 300000; |
cardspecs->maxPixelClock8bpp = 300000; |
cardspecs->maxPixelClock16bpp = 300000; |
cardspecs->maxPixelClock24bpp = 300000; |
cardspecs->maxPixelClock32bpp = 300000; |
cardspecs->flags = CLOCK_PROGRAMMABLE; |
cardspecs->maxHorizontalCrtc = 4088; |
cardspecs->nClocks =1; |
cardspecs->clocks = NULL; |
cardspecs->mapClock = vesa_map_clock; |
cardspecs->mapHorizontalCrtc = vesa_map_horizontal_crtc; |
cardspecs->matchProgrammableClock=vesa_match_programmable_clock; |
__svgalib_driverspecs = &__svgalib_vesa_driverspecs; |
|
LRMI_mem1 = __svgalib_LRMI_alloc_real(vesa_regs_size); |
LRMI_mem2 = __svgalib_LRMI_alloc_real(sizeof(struct vbe_info_block) |
+ sizeof(struct vbe_mode_info_block)); |
|
__svgalib_banked_mem_base=0xa0000; |
__svgalib_banked_mem_size=0x10000; |
if(vesa_chiptype>=1) { |
__svgalib_linear_mem_base=vesa_linear_base; |
__svgalib_linear_mem_size=vesa_memory*0x400; |
}; |
|
if (__svgalib_driver_report) { |
printk(KERN_INFO "Using VESA driver, %iKB. %s\n",vesa_memory, |
(vesa_chiptype==2)?"VBE3":(vesa_chiptype?"VBE2.0":"VBE1.2")); |
} |
|
sleep(4); |
|
return 0; |
|
} |