cos2000v2/lib/vga.c

670 lines
15 KiB
C

/*******************************************************************************/
/* COS2000 - Compatible Operating System - LGPL v3 - Hordé Nicolas */
/* */
#include "vga.h"
#include "video.h"
#include "memory.h"
#include "asm.h"
#include "types.h"
#include "VGA/modes.c"
static videoinfos infos;
/*******************************************************************************/
/* Deplace l'adresse virtuelle en mode paginee */
void VGA_remap_memory(u32 vaddr)
{
virtual_range_use_kernel(vaddr, GRPHSCREEN, ENDOFVMEM - GRPHSCREEN,
PAGE_NOFLAG);
}
/*******************************************************************************/
/* Detecte si le hardware est disponible, return NULL ou pointeur sur le type de pilote */
u8 *VGA_detect_hardware(void)
{
return "LEGACY";
}
/*******************************************************************************/
/* Renvoie l'adresse du segment video */
u32 getbase(void)
{
u32 base;
outb(GRAPHICS, 6);
base = inb(GRAPHICS + 1);
base >>= 2;
base &= 3;
switch (base)
{
case 0:
case 1:
base = 0xA0000;
break;
case 2:
base = 0xB0000;
break;
case 3:
base = 0xB8000;
break;
}
return base;
}
/*******************************************************************************/
/* Change le mode video courant */
/* ERR 0 aucune
/* ERR 1 mode non existant */
static u8 realsize;
u8 VGA_setvideo_mode(u8 mode)
{
u32 index = 0;
while (vgacapabilities[index].modenumber != 0xFF)
{
if (vgacapabilities[index].modenumber == mode)
{
infos.currentmode =
vgacapabilities[index].modenumber;
break;
}
index++;
}
if (infos.currentmode != mode)
return 1;
infos.currentwidth = vgacapabilities[index].width;
infos.currentheight = vgacapabilities[index].height;
infos.currentdepth = vgacapabilities[index].depth;
infos.currentactivepage = 0;
infos.currentshowedpage = 0;
infos.currentcursorX = 0;
infos.currentcursorY = 0;
infos.currentfont1 = 0;
infos.currentfont2 = 0;
infos.isgraphic = vgacapabilities[index].graphic;
infos.isblinking = false;
infos.iscursorvisible = false;
if (infos.isgraphic)
{
switch (infos.currentdepth)
{
case 1:
/* mode N&B */
infos.currentpitch = infos.currentwidth;
realsize = 1;
break;
case 2:
/* mode 4 couleurs */
infos.currentpitch =
(infos.currentwidth << 1);
realsize = 2;
break;
case 4:
/* mode 16 couleurs */
infos.currentpitch = infos.currentwidth;
realsize = 4;
break;
case 8:
/* mode 256 couleurs */
if (modes[index].
sequencer.Sequencer_Memory_Mode_Register
== 0x0E)
{
/* mode chainé (plus rapide mais limité en mémoire) */
infos.currentpitch =
infos.currentwidth;
realsize = 8;
}
else
{
/* mode non chainé */
infos.currentpitch =
infos.currentwidth >> 2;
realsize = 9;
}
break;
default:
break;
}
infos.pagesize = infos.currentheight * infos.currentpitch;
}
else
{
infos.currentpitch = infos.currentwidth * 2;
infos.pagesize = infos.currentheight * infos.currentpitch;
realsize = 0;
}
infos.pagesnumber = (PLANESIZE / infos.pagesize);
infos.baseaddress =
(modes[index].ctrc.Cursor_Location_High_Register << 8) +
modes[index].ctrc.Cursor_Location_Low_Register + getbase();
/* Initialise les registre "divers" */
outb(MISC_WRITE, modes[index].misc);
/* Initialise les registre d'etat */
outb(STATE, 0x00);
/* Initialise le séquenceur */
outreg(SEQUENCER, &modes[index].sequencer, 5);
/* Debloque le verouillage des registres controleur CRT */
outb(CCRT, 0x11);
outb(CCRT + 1, 0x0E);
/* Initialise le controleur CRT */
outreg(CCRT, &modes[index].ctrc, 25);
/* Initialise le controleur graphique */
outreg(GRAPHICS, &modes[index].graphic, 9);
inb(STATE);
/* Initialise le controleur d'attributs */
outregsame(ATTRIBS, &modes[index].attribut, 21);
inb(STATE);
outb(ATTRIBS, 0x20);
/* Initialise l'adresse des procedures de gestion graphique et les differentes
variables en fonction de la profondeur et du mode */
return 0;
}
/*******************************************************************************/
/* Renvoie le nom du driver */
u8 *VGA_getvideo_drivername(void)
{
return "VGA";
}
/*******************************************************************************/
/* Renvoie un pointeur sur la structure des capacités graphiques */
u8 *VGA_getvideo_capabilities(void)
{
return vgacapabilities;
}
/*******************************************************************************/
/* Renvoie un pointeur sur l'état courant de la carte */
videoinfos *VGA_getvideo_info(void)
{
return &infos;
}
/*******************************************************************************/
/* Effecture un mouvement de la mémoire centrale vers la mémoire video (linéarisée) */
u32 VGA_mem_to_video(void *src, u32 dst, u32 size, bool increment_src)
{
u32 realdst =
infos.baseaddress +
infos.currentactivepage * infos.pagesize + dst;
switch (realsize)
{
case 0:
if (!increment_src)
{
u8 tmp = (u8) src;
memset(realdst, tmp, size, 2);
}
else
{
memcpy(src, realdst, size, 2);
}
break;
case 1:
break;
case 2:
break;
case 4:
break;
case 8:
if (!increment_src)
{
u8 tmp = (u8) (src);
if (size % 4 == 0)
{
u32 pattern =
tmp + (tmp << 8) +
(tmp << 16) + (tmp << 24);
stosd(pattern, realdst,
(size >> 2));
}
else if (size % 2 == 0)
{
u32 pattern = tmp + (tmp << 8);
stosw(pattern, realdst,
(size >> 1));
}
else
{
u32 pattern = tmp;
stosb(pattern, realdst, size);
}
}
else
{
if (size % 4 == 0)
{
movsd(src, realdst, size >> 2);
}
else if (size % 2 == 0)
{
movsw(src, realdst, size >> 1);
}
else
{
movsb(src, realdst, size);
}
}
break;
case 9:
break;
}
}
/*******************************************************************************/
/* Effecture un mouvement de la mémoire video (linéarisée) vers la mémoire centrale*/
u32 VGA_video_to_mem(u32 src, void *dst, u32 size)
{
u32 realsrc =
infos.baseaddress +
infos.currentactivepage * infos.pagesize + src;
switch (realsize)
{
case 0:
memcpy(realsrc, dst, size, 2);
break;
case 1:
break;
case 2:
break;
case 4:
break;
case 8:
break;
case 9:
break;
}
}
/*******************************************************************************/
/* Effecture un mouvement de la mémoire video (linéarisé) vers la mémoire vidéo (linéarisée) */
u32 VGA_video_to_video(u32 src, u32 dst, u32 size)
{
u32 base =
infos.baseaddress +
infos.currentactivepage * infos.pagesize;
u32 realsrc = base + src;
u32 realdst = base + dst;
switch (realsize)
{
case 8:
case 0:
if (size % 4 == 0)
{
movsd(realsrc, realdst, size >> 2);
}
else if (size % 2 == 0)
{
movsw(realsrc, realdst, size >> 1);
}
else
{
movsb(realsrc, realdst, size);
}
break;
case 1:
break;
case 2:
break;
case 4:
break;
case 9:
break;
}
}
/*******************************************************************************/
/* Fixe la page ecran de travail */
void VGA_page_set(u8 page)
{
if (page < infos.pagesnumber)
infos.currentactivepage = page;
}
/*******************************************************************************/
/* Affiche la page ecran specifié */
void VGA_page_show(u8 page)
{
if (page < infos.pagesnumber)
{
u16 addr;
addr = page * infos.pagesize / 2;
outb(CCRT, 0x0C);
outb(CCRT + 1, (addr >> 8));
outb(CCRT, 0x0D);
outb(CCRT + 1, (addr & 0xFF));
infos.currentshowedpage = page;
}
}
/*******************************************************************************/
/* Sépare l'écran en 2 a partir de la ligne Y */
static splitY = 0;
void VGA_page_split(u16 y)
{
if (y != 0)
{
u16 addr;
if (!infos.isgraphic)
addr = (y << 3);
else
addr = y;
/* line compare pour ligne atteinte */
outb(CCRT, 0x18);
outb(CCRT + 1, (addr & 0xFF));
/* overflow pour le bit 8 */
outb(CCRT, 0x07);
outb(CCRT + 1, (inb(CCRT + 1) & ~16) | ((addr >> 4) & 16));
/* Maximum Scan Line pour le bit 9 */
outb(CCRT, 0x09);
outb(CCRT + 1, (inb(CCRT + 1) & ~64) | ((addr >> 3) & 64));
splitY = y;
}
else
{
/* line compare pour ligne atteinte */
outb(CCRT, 0x18);
outb(CCRT + 1, 0);
/* overflow pour le bit 8 */
outb(CCRT, 0x07);
outb(CCRT + 1, inb(CCRT + 1) & ~16);
/* Maximum Scan Line pour le bit 9 */
outb(CCRT, 0x09);
outb(CCRT + 1, inb(CCRT + 1) & ~64);
splitY = 0;
}
}
/*******************************************************************************/
/* Attend la retrace verticale */
void VGA_wait_vretrace(void)
{
while ((inb(STATE) & 8) == 0);
}
/*******************************************************************************/
/* Attend la retrace horizontale */
void VGA_wait_hretrace(void)
{
while ((inb(STATE) & 1) == 0);
}
/*******************************************************************************/
/* Active l'affichage du curseur de texte */
void VGA_cursor_enable(void)
{
if (!infos.isgraphic)
{
u8 curs;
/* active le curseur hardware */
outb(CCRT, 10);
curs = inb(CCRT + 1) & ~32;
outb(CCRT + 1, curs);
infos.iscursorvisible = true;
}
}
/*******************************************************************************/
/* Desactive l'affichage du curseur de texte */
void VGA_cursor_disable(void)
{
if (!infos.isgraphic)
{
u8 curs;
/* Desactive le curseur hardware */
outb(CCRT, 10);
curs = inb(CCRT + 1) | 32;
outb(CCRT + 1, curs);
infos.iscursorvisible = false;
}
}
/*******************************************************************************/
/* Utilise le plan de bit spécifié */
void useplane(u8 plan)
{
u8 mask;
plan &= 3;
mask = 1 << plan;
/* choisi le plan de lecture */
outb(GRAPHICS, 4);
outb(GRAPHICS + 1, plan);
/* choisi le plan d'ecriture */
outb(SEQUENCER, 2);
outb(SEQUENCER + 1, mask);
}
/*******************************************************************************/
/* fixe la position du curseur texte */
void VGA_cursor_set(u16 x, u16 y)
{
if (!infos.isgraphic)
{
u16 pos;
if (splitY == 0)
pos = (infos.currentshowedpage * infos.pagesize /
2 + x + y * infos.currentwidth);
else
pos = (x + y * infos.currentwidth);
outb(CCRT, 0x0F);
outb(CCRT + 1, (u8) (pos & 0x00FF));
outb(CCRT, 0x0E);
outb(CCRT + 1, (u8) ((pos & 0xFF00) >> 8));
infos.currentcursorX = x;
infos.currentcursorY = y;
}
}
/*******************************************************************************/
/* Charge une nouvelle police de caractère */
/* ERR 1 mode graphique activé*/
u32 VGA_font_load(u8 * def, u8 size, u8 font)
{
if (infos.isgraphic)
return 1;
u8 oldregs[5] = { 0, 0, 0, 0, 0 };
u8 *base;
u16 i;
if (font > 7)
return 1;
if (font < 4)
base = (u8 *) (getbase() + (font << 14));
else
base = (u8 *) (getbase() +
((((font - 4) << 1) + 1) << 13));
/* sauve les anciens registres */
outb(SEQUENCER, 2);
oldregs[0] = inb(SEQUENCER + 1);
outb(SEQUENCER, 4);
oldregs[1] = inb(SEQUENCER + 1);
/* Adressage paire/impair desactivé (lineaire) */
outb(SEQUENCER + 1, oldregs[1] | 0x04);
outb(GRAPHICS, 4);
oldregs[2] = inb(GRAPHICS + 1);
outb(GRAPHICS, 5);
oldregs[3] = inb(GRAPHICS + 1);
/* Adressage paire/impair desactivé (lineaire) */
outb(GRAPHICS + 1, oldregs[3] & ~0x10);
outb(GRAPHICS, 6);
oldregs[4] = inb(GRAPHICS + 1);
/* Adressage paire/impair desactivé (lineaire) */
outb(GRAPHICS + 1, oldregs[4] & ~0x02);
/* utilisation du plan N°2 */
useplane(2);
for (i = 0; i < 256; i++)
{
memcpy(def, base + i * 32, size, 1);
def += size;
}
outb(SEQUENCER, 2);
outb(SEQUENCER + 1, oldregs[0]);
outb(SEQUENCER, 4);
outb(SEQUENCER + 1, oldregs[1]);
outb(GRAPHICS, 4);
outb(GRAPHICS + 1, oldregs[2]);
outb(GRAPHICS, 5);
outb(GRAPHICS + 1, oldregs[3]);
outb(GRAPHICS, 6);
outb(GRAPHICS + 1, oldregs[4]);
return 0;
}
/*******************************************************************************/
/* Fixe le N° de la police de caractère a utiliser */
void VGA_font1_set(u8 num)
{
if (!infos.isgraphic)
{
num &= 0x07;
outb(SEQUENCER, 3);
outb(SEQUENCER + 1,
(inb(SEQUENCER + 1) & 0xEC) | ((num & 0x03) +
((num & 0x04) << 2)));
infos.currentfont1 = num;
}
}
/*******************************************************************************/
/* Fixe le N° de la police de caractère a utiliser */
void VGA_font2_set(u8 num)
{
if (!infos.isgraphic)
{
num &= 0x07;
outb(SEQUENCER, 3);
outb(SEQUENCER + 1,
(inb(SEQUENCER + 1) & 0xD3) | (((num & 0x03) << 2) +
((num & 0x04) << 3)));
infos.currentfont2 = num;
}
}
/*******************************************************************************/
/* Autorise le clignotement */
void VGA_blink_enable(void)
{
if (!infos.isgraphic)
{
outb(CCRT, 0x10);
outb(CCRT + 1, (inb(SEQUENCER + 1) | 0x04));
infos.isblinking = true;
}
}
/*******************************************************************************/
/* Annule le clignotement */
void VGA_blink_disable(void)
{
if (!infos.isgraphic)
{
outb(CCRT, 0x10);
outb(CCRT + 1, (inb(SEQUENCER + 1) & ~0x04));
infos.isblinking = false;
}
}
/*******************************************************************************/
/* Envoie une série d'octet a destination d'une portion de mémoire
vers le registre spécifié */
void outreg(u16 port, u8 * src, u16 num)
{
int i;
for (i = 0; i < num; i++)
{
outb(port, i);
outb(port + 1, *src++);
}
}
/*******************************************************************************/
/* Envoie une série d'octet a destination d'une portion de mémoire
vers le registre spécifié (accés data et index confondu) */
void outregsame(u16 port, u8 * src, u16 num)
{
int i;
for (i = 0; i < num; i++)
{
inb(port);
outb(port, i);
outb(port, *src++);
}
}
/*******************************************************************************/
/* Récupère une série d'octet en provenance d'un registre spécifié
vers portion de mémoire */
void inreg(u16 port, u8 * src, u16 num)
{
int i;
for (i = 0; i < num; i++)
{
outb(port, i);
*src++ = inb(port + 1);
}
}
/*******************************************************************************/
/* Récupère une série d'octet en provenance d'un registre spécifié
vers portion de mémoire (accés data et index confondu) */
void inregsame(u16 port, u8 * src, u16 num)
{
int i;
for (i = 0; i < num; i++)
{
inb(port);
outb(port, i);
*src++ = inb(port);
}
}
/*******************************************************************************/