📄 vgacon.c
字号:
int col = vga_can_do_color; while (count--) { u16 a = scr_readw(p); if (col) a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4); else a ^= ((a & 0x0700) == 0x0100) ? 0x7000 : 0x7700; scr_writew(a, p++); }}static void vgacon_set_cursor_size(int xpos, int from, int to){ unsigned long flags; int curs, cure;#ifdef TRIDENT_GLITCH if (xpos < 16) from--, to--;#endif if ((from == cursor_size_lastfrom) && (to == cursor_size_lastto)) return; cursor_size_lastfrom = from; cursor_size_lastto = to; spin_lock_irqsave(&vga_lock, flags); outb_p(0x0a, vga_video_port_reg); /* Cursor start */ curs = inb_p(vga_video_port_val); outb_p(0x0b, vga_video_port_reg); /* Cursor end */ cure = inb_p(vga_video_port_val); curs = (curs & 0xc0) | from; cure = (cure & 0xe0) | to; outb_p(0x0a, vga_video_port_reg); /* Cursor start */ outb_p(curs, vga_video_port_val); outb_p(0x0b, vga_video_port_reg); /* Cursor end */ outb_p(cure, vga_video_port_val); spin_unlock_irqrestore(&vga_lock, flags);}static void vgacon_cursor(struct vc_data *c, int mode){ if (c->vc_origin != c->vc_visible_origin) vgacon_scrolldelta(c, 0); switch (mode) { case CM_ERASE: write_vga(14, (c->vc_pos - vga_vram_base) / 2); vgacon_set_cursor_size(c->vc_x, 31, 30); break; case CM_MOVE: case CM_DRAW: write_vga(14, (c->vc_pos - vga_vram_base) / 2); switch (c->vc_cursor_type & 0x0f) { case CUR_UNDERLINE: vgacon_set_cursor_size(c->vc_x, c->vc_font.height - (c->vc_font.height < 10 ? 2 : 3), c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2)); break; case CUR_TWO_THIRDS: vgacon_set_cursor_size(c->vc_x, c->vc_font.height / 3, c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2)); break; case CUR_LOWER_THIRD: vgacon_set_cursor_size(c->vc_x, (c->vc_font.height * 2) / 3, c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2)); break; case CUR_LOWER_HALF: vgacon_set_cursor_size(c->vc_x, c->vc_font.height / 2, c->vc_font.height - (c->vc_font.height < 10 ? 1 : 2)); break; case CUR_NONE: vgacon_set_cursor_size(c->vc_x, 31, 30); break; default: vgacon_set_cursor_size(c->vc_x, 1, c->vc_font.height); break; } break; }}static int vgacon_doresize(struct vc_data *c, unsigned int width, unsigned int height){ unsigned long flags; unsigned int scanlines = height * c->vc_font.height; u8 scanlines_lo, r7, vsync_end, mode, max_scan; spin_lock_irqsave(&vga_lock, flags); outb_p(VGA_CRTC_MAX_SCAN, vga_video_port_reg); max_scan = inb_p(vga_video_port_val); if (max_scan & 0x80) scanlines <<= 1; outb_p(VGA_CRTC_MODE, vga_video_port_reg); mode = inb_p(vga_video_port_val); if (mode & 0x04) scanlines >>= 1; scanlines -= 1; scanlines_lo = scanlines & 0xff; outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg); r7 = inb_p(vga_video_port_val) & ~0x42; if (scanlines & 0x100) r7 |= 0x02; if (scanlines & 0x200) r7 |= 0x40; /* deprotect registers */ outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg); vsync_end = inb_p(vga_video_port_val); outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg); outb_p(vsync_end & ~0x80, vga_video_port_val); outb_p(VGA_CRTC_H_DISP, vga_video_port_reg); outb_p(width - 1, vga_video_port_val); outb_p(VGA_CRTC_OFFSET, vga_video_port_reg); outb_p(width >> 1, vga_video_port_val); outb_p(VGA_CRTC_V_DISP_END, vga_video_port_reg); outb_p(scanlines_lo, vga_video_port_val); outb_p(VGA_CRTC_OVERFLOW, vga_video_port_reg); outb_p(r7,vga_video_port_val); /* reprotect registers */ outb_p(VGA_CRTC_V_SYNC_END, vga_video_port_reg); outb_p(vsync_end, vga_video_port_val); spin_unlock_irqrestore(&vga_lock, flags); return 0;}static int vgacon_switch(struct vc_data *c){ /* * We need to save screen size here as it's the only way * we can spot the screen has been resized and we need to * set size of freshly allocated screens ourselves. */ vga_video_num_columns = c->vc_cols; vga_video_num_lines = c->vc_rows; /* We can only copy out the size of the video buffer here, * otherwise we get into VGA BIOS */ if (!vga_is_gfx) { scr_memcpyw((u16 *) c->vc_origin, (u16 *) c->vc_screenbuf, c->vc_screenbuf_size > vga_vram_size ? vga_vram_size : c->vc_screenbuf_size); if (!(vga_video_num_columns % 2) && vga_video_num_columns <= ORIG_VIDEO_COLS && vga_video_num_lines <= (ORIG_VIDEO_LINES * vga_default_font_height) / c->vc_font.height) vgacon_doresize(c, c->vc_cols, c->vc_rows); } return 0; /* Redrawing not needed */}static void vga_set_palette(struct vc_data *vc, unsigned char *table){ int i, j; vga_w(state.vgabase, VGA_PEL_MSK, 0xff); for (i = j = 0; i < 16; i++) { vga_w(state.vgabase, VGA_PEL_IW, table[i]); vga_w(state.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2); vga_w(state.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2); vga_w(state.vgabase, VGA_PEL_D, vc->vc_palette[j++] >> 2); }}static int vgacon_set_palette(struct vc_data *vc, unsigned char *table){#ifdef CAN_LOAD_PALETTE if (vga_video_type != VIDEO_TYPE_VGAC || vga_palette_blanked || !CON_IS_VISIBLE(vc)) return -EINVAL; vga_set_palette(vc, table); return 0;#else return -EINVAL;#endif}/* structure holding original VGA register settings */static struct { unsigned char SeqCtrlIndex; /* Sequencer Index reg. */ unsigned char CrtCtrlIndex; /* CRT-Contr. Index reg. */ unsigned char CrtMiscIO; /* Miscellaneous register */ unsigned char HorizontalTotal; /* CRT-Controller:00h */ unsigned char HorizDisplayEnd; /* CRT-Controller:01h */ unsigned char StartHorizRetrace; /* CRT-Controller:04h */ unsigned char EndHorizRetrace; /* CRT-Controller:05h */ unsigned char Overflow; /* CRT-Controller:07h */ unsigned char StartVertRetrace; /* CRT-Controller:10h */ unsigned char EndVertRetrace; /* CRT-Controller:11h */ unsigned char ModeControl; /* CRT-Controller:17h */ unsigned char ClockingMode; /* Seq-Controller:01h */} vga_state;static void vga_vesa_blank(struct vgastate *state, int mode){ /* save original values of VGA controller registers */ if (!vga_vesa_blanked) { spin_lock_irq(&vga_lock); vga_state.SeqCtrlIndex = vga_r(state->vgabase, VGA_SEQ_I); vga_state.CrtCtrlIndex = inb_p(vga_video_port_reg); vga_state.CrtMiscIO = vga_r(state->vgabase, VGA_MIS_R); spin_unlock_irq(&vga_lock); outb_p(0x00, vga_video_port_reg); /* HorizontalTotal */ vga_state.HorizontalTotal = inb_p(vga_video_port_val); outb_p(0x01, vga_video_port_reg); /* HorizDisplayEnd */ vga_state.HorizDisplayEnd = inb_p(vga_video_port_val); outb_p(0x04, vga_video_port_reg); /* StartHorizRetrace */ vga_state.StartHorizRetrace = inb_p(vga_video_port_val); outb_p(0x05, vga_video_port_reg); /* EndHorizRetrace */ vga_state.EndHorizRetrace = inb_p(vga_video_port_val); outb_p(0x07, vga_video_port_reg); /* Overflow */ vga_state.Overflow = inb_p(vga_video_port_val); outb_p(0x10, vga_video_port_reg); /* StartVertRetrace */ vga_state.StartVertRetrace = inb_p(vga_video_port_val); outb_p(0x11, vga_video_port_reg); /* EndVertRetrace */ vga_state.EndVertRetrace = inb_p(vga_video_port_val); outb_p(0x17, vga_video_port_reg); /* ModeControl */ vga_state.ModeControl = inb_p(vga_video_port_val); vga_state.ClockingMode = vga_rseq(state->vgabase, VGA_SEQ_CLOCK_MODE); } /* assure that video is enabled */ /* "0x20" is VIDEO_ENABLE_bit in register 01 of sequencer */ spin_lock_irq(&vga_lock); vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode | 0x20); /* test for vertical retrace in process.... */ if ((vga_state.CrtMiscIO & 0x80) == 0x80) vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO & 0xEF); /* * Set <End of vertical retrace> to minimum (0) and * <Start of vertical Retrace> to maximum (incl. overflow) * Result: turn off vertical sync (VSync) pulse. */ if (mode & VESA_VSYNC_SUSPEND) { outb_p(0x10, vga_video_port_reg); /* StartVertRetrace */ outb_p(0xff, vga_video_port_val); /* maximum value */ outb_p(0x11, vga_video_port_reg); /* EndVertRetrace */ outb_p(0x40, vga_video_port_val); /* minimum (bits 0..3) */ outb_p(0x07, vga_video_port_reg); /* Overflow */ outb_p(vga_state.Overflow | 0x84, vga_video_port_val); /* bits 9,10 of vert. retrace */ } if (mode & VESA_HSYNC_SUSPEND) { /* * Set <End of horizontal retrace> to minimum (0) and * <Start of horizontal Retrace> to maximum * Result: turn off horizontal sync (HSync) pulse. */ outb_p(0x04, vga_video_port_reg); /* StartHorizRetrace */ outb_p(0xff, vga_video_port_val); /* maximum */ outb_p(0x05, vga_video_port_reg); /* EndHorizRetrace */ outb_p(0x00, vga_video_port_val); /* minimum (0) */ } /* restore both index registers */ vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex); outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg); spin_unlock_irq(&vga_lock);}static void vga_vesa_unblank(struct vgastate *state){ /* restore original values of VGA controller registers */ spin_lock_irq(&vga_lock); vga_w(state->vgabase, VGA_MIS_W, vga_state.CrtMiscIO); outb_p(0x00, vga_video_port_reg); /* HorizontalTotal */ outb_p(vga_state.HorizontalTotal, vga_video_port_val); outb_p(0x01, vga_video_port_reg); /* HorizDisplayEnd */ outb_p(vga_state.HorizDisplayEnd, vga_video_port_val); outb_p(0x04, vga_video_port_reg); /* StartHorizRetrace */ outb_p(vga_state.StartHorizRetrace, vga_video_port_val); outb_p(0x05, vga_video_port_reg); /* EndHorizRetrace */ outb_p(vga_state.EndHorizRetrace, vga_video_port_val); outb_p(0x07, vga_video_port_reg); /* Overflow */ outb_p(vga_state.Overflow, vga_video_port_val); outb_p(0x10, vga_video_port_reg); /* StartVertRetrace */ outb_p(vga_state.StartVertRetrace, vga_video_port_val); outb_p(0x11, vga_video_port_reg); /* EndVertRetrace */ outb_p(vga_state.EndVertRetrace, vga_video_port_val); outb_p(0x17, vga_video_port_reg); /* ModeControl */ outb_p(vga_state.ModeControl, vga_video_port_val); /* ClockingMode */ vga_wseq(state->vgabase, VGA_SEQ_CLOCK_MODE, vga_state.ClockingMode); /* restore index/control registers */ vga_w(state->vgabase, VGA_SEQ_I, vga_state.SeqCtrlIndex); outb_p(vga_state.CrtCtrlIndex, vga_video_port_reg); spin_unlock_irq(&vga_lock);}static void vga_pal_blank(struct vgastate *state){ int i; vga_w(state->vgabase, VGA_PEL_MSK, 0xff); for (i = 0; i < 16; i++) { vga_w(state->vgabase, VGA_PEL_IW, i); vga_w(state->vgabase, VGA_PEL_D, 0); vga_w(state->vgabase, VGA_PEL_D, 0); vga_w(state->vgabase, VGA_PEL_D, 0); }}static int vgacon_blank(struct vc_data *c, int blank, int mode_switch){ switch (blank) { case 0: /* Unblank */ if (vga_vesa_blanked) { vga_vesa_unblank(&state); vga_vesa_blanked = 0; } if (vga_palette_blanked) { vga_set_palette(c, color_table); vga_palette_blanked = 0; return 0; } vga_is_gfx = 0; /* Tell console.c that it has to restore the screen itself */ return 1; case 1: /* Normal blanking */ case -1: /* Obsolete */ if (!mode_switch && vga_video_type == VIDEO_TYPE_VGAC) { vga_pal_blank(&state); vga_palette_blanked = 1; return 0; } vgacon_set_origin(c); scr_memsetw((void *) vga_vram_base, BLANK, c->vc_screenbuf_size); if (mode_switch) vga_is_gfx = 1; return 1; default: /* VESA blanking */ if (vga_video_type == VIDEO_TYPE_VGAC) { vga_vesa_blank(&state, blank - 1); vga_vesa_blanked = blank; } return 0; }}/* * PIO_FONT support. * * The font loading code goes back to the codepage package by * Joel Hoffman (joel@wam.umd.edu). (He reports that the original * reference is: "From: p. 307 of _Programmer's Guide to PC & PS/2 * Video Systems_ by Richard Wilton. 1987. Microsoft Press".) * * Change for certain monochrome monitors by Yury Shevchuck * (sizif@botik.yaroslavl.su). */#ifdef CAN_LOAD_EGA_FONTS#define colourmap 0xa0000/* Pauline Middelink <middelin@polyware.iaf.nl> reports that we should use 0xA0000 for the bwmap as well.. */#define blackwmap 0xa0000#define cmapsz 8192static int vgacon_do_font_op(struct vgastate *state,char *arg,int set,int ch512){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -