⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vgadrv.c

📁 从网上下载的一个自己编写的简单的操作系统源代码,对底层了解很有好处的
💻 C
字号:
/*
 *   ExpOS
 *   Origin Author:  Larry Li
 *   Modify:        Hyl.linuxfourm.net 2003.4.6
 *   Creation Date: 2003.2.12
 */

/*
 * TODO:
 * 修改为 VGA12h 640x480x16 色模拟 VGA03 模式以显示汉字 GB2312 字符
 * 注意:在 VGA12h 将光标失去光标支持.
 */



#include <arch.h>
#include <string.h>
#include <drv/vga.h>



extern int char_color, back_color,pos, cursor_x, cursor_y; 


unsigned char *pvram;
extern char _graph ;



static unsigned char vga12h[VGA_NUM_REGS] = {
/* MISC */
	0xE3,
/* SEQ */
	0x03, 0x01, 0x08, 0x00, 0x06,
/* CRTC */
	0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E,
	0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
	0xEA, 0x0C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3, 0xFF,
/* GC */
	0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x0F, 0xFF,
/* AC */
	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
	0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
	0x01, 0x00, 0x0F, 0x00, 0x00
};

static void switch_vga_mode(unsigned char *regs)
{
	unsigned i;

	/* write MISCELLANEOUS reg */
	 outb(VGA_MISC_WRITE,*regs );
	 regs++;
	/* write SEQUENCER regs */
	for (i = 0; i < VGA_NUM_SEQ_REGS; i++) {
		outb(VGA_SEQ_INDEX,i );
		outb(VGA_SEQ_DATA,*regs );
		regs++;
	}
	/* unlock CRTC registers */
	outb(VGA_CRTC_INDEX,0x03 );
	outb(VGA_CRTC_DATA,inb(VGA_CRTC_DATA) | 0x80 );
	outb(VGA_CRTC_INDEX,0x11 );
	outb(VGA_CRTC_DATA,inb(VGA_CRTC_DATA) & ~0x80 );
	/* make sure they remain unlocked */
	regs[0x03] |= 0x80;
	regs[0x11] &= ~0x80;
	/* write CRTC regs */
	for (i = 0; i < VGA_NUM_CRTC_REGS; i++) {
		outb(VGA_CRTC_INDEX,i );
		outb(VGA_CRTC_DATA,*regs );
		regs++;
	}
	/* write GRAPHICS CONTROLLER regs */
	for (i = 0; i < VGA_NUM_GC_REGS; i++) {
		outb(VGA_GC_INDEX,i );
		outb(VGA_GC_DATA,*regs );
		regs++;
	}
	/* write ATTRIBUTE CONTROLLER regs */
	for (i = 0; i < VGA_NUM_AC_REGS; i++) {
		(void) inb(VGA_INSTAT_READ);
		outb(VGA_AC_INDEX,i );
		outb(VGA_AC_WRITE,*regs );
		regs++;
	}
	/* lock 16-color palette and unblank display */
	(void) inb(VGA_INSTAT_READ);
	outb(VGA_AC_INDEX,0x20 );

	
}

 

/*------------------------------------------------------------------------
 Procedure:     vga_init ID:1
 Purpose:       显示初始化
 Input:         从启动 7C00h 偏移 510, 511 处读取寄存的 x, y 坐标值
 Output:
 Errors:
------------------------------------------------------------------------*/
void vga_init(void)
{
   
     {
    	switch_vga_mode(vga12h);
    
    	_graph = 1;
    
       
       	clear_vram(); 
        
    	extern char log_buf[];
    	//puts(log_buf);
    
    	kprintf(log_buf);
    
    	/* `~ 逃逸序列,后跟一个十六进制数 0-A 表示颜色。`~ 两个字符共用一个键通常在 Esc 键下面 */
    	//puts("`~AOK`~F! `~C中文`~E GB2312 `~7显示已启动,");
    }
    #if 0
	{
    
    	int x, y;
    	/*	unsigned char val;	*/
    
    	x = *(unsigned char *)(0x7C00 + 510);
    	y = *(unsigned char *)(0x7C00 + 511);
    
    	x = 0;
    	y++;
    	gotoxy(x, y);
    
    
    	clear_vram();
    }
	#endif
	
}



void vga_pixel(unsigned int x, unsigned int y, unsigned int c)
{
	unsigned char *off;
	unsigned int mask, i, pmask;

	x %= WIDTH;
	y %= HEIGHT;
	c %= COLORS;

	off = VRAM + COLS * y + (x >> 3);
	x &= 7;
	mask = 0x80 >> x;
	pmask = 1;
	for (i = 0; i < 4; i++) {
		outb(VGA_GC_INDEX,4 );
		outb(VGA_GC_DATA,i );
		outb(VGA_SEQ_INDEX,2 );
		outb(VGA_SEQ_DATA,(1 << i) );

		if (pmask & c)
			*off |= mask;
		else
			*off &= ~mask;
		pmask <<= 1;
	}
}

void vga_outbyte(unsigned int col, unsigned int y, unsigned char mask, unsigned int c)
{
	unsigned char *off;
	unsigned int i, pmask;

	col %= COLS;
	y %= HEIGHT;
	c %= COLORS;

	off = VRAM + COLS * y + col;
	pmask = 1;
	for (i = 0; i < 4; i++) {
		outb(VGA_GC_INDEX,4 );
		outb(VGA_GC_DATA,i );
		outb(VGA_SEQ_INDEX,2 );
		outb(VGA_SEQ_DATA,(1 << i) );

		if (pmask & c)
			*off |= mask;
		else
			*off &= ~mask;
		pmask <<= 1;
	}
}



/*
 * Procedure:     clear_vram ID:1
 * Purpose:       清屏
 *               循环赋值
 * Input:
 * Output:
 * Errors:
 */
void clear_vram(void)
{

   if(_graph){

#ifdef USE_PUTPIXEL
       	int x, y;
       
       	for (y = 0; y < HEIGHT; y++)
       		for (x = 0; x < WIDTH; x++)
       			vga_pixel(x, y, back_color);
#endif

#ifdef OUTBYTE
        
       int col, y;
        
        for (y = 0; y < TIPS_POS; y++)
        	for (col = 0; col < COLS; col++)
        		vga_outbyte(col, y, 0xFF, back_color);
        for (col = 0; col < COLS; col++)
        		vga_outbyte(col, y, 0xFF, WHITE);
        for (y++; y < HEIGHT; y++)
        		for (col = 0; col < COLS; col++)
        			vga_outbyte(col, y, 0xFF, WHITE);
        
#else

    	/* 使用四个页面分别刷新,减少寄存器操作,加快速度 */
    	/*??? 关闭显示后进行操作,避免花屏现象? */
    	unsigned int i, j;
    	unsigned char *off;
    
    	for (i = 0; i < 4; i++) {
    		outb(VGA_SEQ_INDEX,2 );
    		outb(VGA_SEQ_DATA,(1 << i) );
    
    		off = VRAM;
    		if ((1 << i) & back_color)
    			for (j = 0; j <= COLS * TIPS_POS; j++)
    				*off++ = 0x0;
    		else
    			for (j = 0; j <= COLS * TIPS_POS; j++)
    				*off++ = 0;
    		if ((1 << i) & BLACK)
    			for (; j < COLS * (TIPS_POS + 1); j++)
    				*off++ = 0x0;
    		else
    			for (; j < COLS * (TIPS_POS + 1); j++)
    				*off++ = 0;
    		if ((1 << i) & BLACK)
    			for (; j < COLS * HEIGHT; j++)
    				*off++ = 0x0;
    		else
    			for (; j < COLS * HEIGHT; j++)
    				*off++ = 0;
    	}
#endif


      
     }else{

        	/* it is used to clear the video ram */
        	int i;
        	unsigned char *p = (unsigned char *) 0xc00B8000;
        
        	/* set blank */
        	for (i = 0; i < 80 * 25; i++) {
        		*p = ' ';
        		p = p + 2;
        	}
        
        	p = (unsigned char *) 0xc00B8001;
        
        	/* background black */
        	for (i = 0; i < 80 * 25; i++) {
        		*p = 7;
        		p = p + 2;
         	}
     }       

	return;
}



/*
 Procedure:     gotoxy ID:1
 Purpose:       设置当前光标及显示字符位置
 Input:         x, y 坐标
 Output:
 Errors:        ?光标显示问题
*/
inline void gotoxy(unsigned int x, unsigned int y)
{
	pos = (COLS * y + x) * 2;

	cli();
	outb(VGA_IN,14 );
	outb(VGA_DATA,0xFF & (pos >> 9) );
	outb(15, VGA_IN);
	outb(VGA_DATA, 0xFF & (pos >> 1));
	sti();

	cursor_x = x;
	cursor_y = y;
}


static inline phys_copy(unsigned char *src,unsigned char *dst,
	       unsigned int n)
{
int d0, d1, d2;
#if 0
__asm__ __volatile__(
	"rep\n\t"
	"movsb"
	: "=&c" (d0), "=&S" (d1), "=&D" (d2)
	:"0" (n),"1" (src),"2" (dst)
	: "memory");

//#else

__asm__ __volatile__(
	"std\n\t"
	"rep\n\t"
	"movsb\n\t"
	"cld"
	: "=&c" (d0), "=&S" (d1), "=&D" (d2)
	:"0" (n),
	 "1" (n-1+(const char *)src),
	 "2" (n-1+(char *)dst)
	:"memory");
#endif

  #if 1
  int i;
  for(i = 0;i < n;i++)
    {
      *src = *dst;
      src++;
      dst++;
    }
  return;
  #endif
}


/*
 * Procedure:     scroll_up ID:1
 * Purpose:       向上滚动一行屏幕
 * Input:
 * Output:
 * Errors:        ?直接显存拷贝。
 */
void scroll_up(void)
{
    if(_graph)
    {
       int i, j;
       unsigned char *off;
    
       for (i = 0; i < 4; i++) {
    	  outb(VGA_GC_INDEX,4 );
    	  outb(VGA_GC_DATA,i );
    	  outb(VGA_SEQ_INDEX,2 );
    	  outb(VGA_SEQ_DATA,(1 << i) );
    
    	  phys_copy(VRAM, VRAM + COLS * LINE_HEIGHT, COLS * (ROWS - 1) * LINE_HEIGHT);
            
    	  off = VRAM + COLS * LINE_HEIGHT * (ROWS - 1);
    	  if ((1 << i) & back_color)
    	  	 for (j = 0; j < COLS * LINE_HEIGHT; j++)
    	 	  	 *off++ = 0xFF;
    	  else
    	  	 for (j = 0; j < COLS * LINE_HEIGHT; j++)
    	 		 *off++ = 0;
      }/*end for*/
    }else{

    	unsigned char *p = (unsigned char *)0xB8000;
    	unsigned char *p2 = (unsigned char *)(0xB8000 + COLS * 2);
    	unsigned int count = (ROWS -1) * COLS * 2;
    	int i;
    
    	phys_copy(p, p2,count); /* src ,dst ,count */
    
    	/* then clear the bottom line */
    	p = (unsigned char *)(0xB8000 + (ROWS - 1) * 2 * COLS);
    	for (i = 0; i < COLS * 2; i += 2)
    		p[i] = ' ';
    	

   }

   return;
}


#if 0
#ifdef HAS_PCXBACK
typedef struct {
	char manufacturer;
	char version;
	char encoding;
	char bitsperpixel;
	short xmin, ymin;
	short xmax, ymax;
	short hres, vres;
	char palette[48];
	char reserved;
	char colorplanes;
	short width;
	short palettetype;
	char filler[58];
} PCXHEAD;

extern unsigned char *BACK;

void show_pcxback()
{
	int i, j, k;
	int n, c;
	int w, h, bytes;
	PCXHEAD *ph;
	unsigned char *data, *vga;
	unsigned char buf[COLS];

	ph = (PCXHEAD *)BACK;
	if (ph->manufacturer != 0x0A)
		return;
	w = (ph->xmax - ph->xmin) + 1;
	h = (ph->ymax - ph->ymin) + 1;
	bytes = ph->width;
	data = (unsigned char *)(BACK + sizeof(PCXHEAD));
	for (i = 0; i < h; i++) {
		for (j = 0; j < 4; j++) {
			n = 0;
			do {
				c = *data++;
				if ((c & 0xC0) == 0xC0) {
					k = c & 0x3F;
					c = *data++;
					while (k--)
						buf[n++] = c;
				} else
					buf[n++] = c;
			} while (n < bytes && n < COLS);
			vga = VRAM + i * COLS;
			for (k = 0; k < bytes; k++)
				vga[k] = buf[k];
		}
	}
}
#endif	/* HAS_PCXBACK */
#endif 

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -