/*
*/
#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;
}