📄 vgacon.c
字号:
int beg; unsigned short video_port_status = vga_video_port_reg + 6; int font_select = 0x00; if (vga_video_type != VIDEO_TYPE_EGAM) { charmap = (char *)VGA_MAP_MEM(colourmap); beg = 0x0e;#ifdef VGA_CAN_DO_64KB if (vga_video_type == VIDEO_TYPE_VGAC) beg = 0x06;#endif } else { charmap = (char *)VGA_MAP_MEM(blackwmap); beg = 0x0a; } #ifdef BROKEN_GRAPHICS_PROGRAMS /* * All fonts are loaded in slot 0 (0:1 for 512 ch) */ if (!arg) return -EINVAL; /* Return to default font not supported */ vga_font_is_default = 0; font_select = ch512 ? 0x04 : 0x00;#else /* * The default font is kept in slot 0 and is never touched. * A custom font is loaded in slot 2 (256 ch) or 2:3 (512 ch) */ if (set) { vga_font_is_default = !arg; if (!arg) ch512 = 0; /* Default font is always 256 */ font_select = arg ? (ch512 ? 0x0e : 0x0a) : 0x00; } if ( !vga_font_is_default ) charmap += 4*cmapsz;#endif spin_lock_irq(&vga_lock); outb_p( 0x00, seq_port_reg ); /* First, the sequencer */ outb_p( 0x01, seq_port_val ); /* Synchronous reset */ outb_p( 0x02, seq_port_reg ); outb_p( 0x04, seq_port_val ); /* CPU writes only to map 2 */ outb_p( 0x04, seq_port_reg ); outb_p( 0x07, seq_port_val ); /* Sequential addressing */ outb_p( 0x00, seq_port_reg ); outb_p( 0x03, seq_port_val ); /* Clear synchronous reset */ outb_p( 0x04, gr_port_reg ); /* Now, the graphics controller */ outb_p( 0x02, gr_port_val ); /* select map 2 */ outb_p( 0x05, gr_port_reg ); outb_p( 0x00, gr_port_val ); /* disable odd-even addressing */ outb_p( 0x06, gr_port_reg ); outb_p( 0x00, gr_port_val ); /* map start at A000:0000 */ spin_unlock_irq(&vga_lock); if (arg) { if (set) for (i=0; i<cmapsz ; i++) vga_writeb(arg[i], charmap + i); else for (i=0; i<cmapsz ; i++) arg[i] = vga_readb(charmap + i); /* * In 512-character mode, the character map is not contiguous if * we want to remain EGA compatible -- which we do */ if (ch512) { charmap += 2*cmapsz; arg += cmapsz; if (set) for (i=0; i<cmapsz ; i++) vga_writeb(arg[i], charmap+i); else for (i=0; i<cmapsz ; i++) arg[i] = vga_readb(charmap+i); } } spin_lock_irq(&vga_lock); outb_p( 0x00, seq_port_reg ); /* First, the sequencer */ outb_p( 0x01, seq_port_val ); /* Synchronous reset */ outb_p( 0x02, seq_port_reg ); outb_p( 0x03, seq_port_val ); /* CPU writes to maps 0 and 1 */ outb_p( 0x04, seq_port_reg ); outb_p( 0x03, seq_port_val ); /* odd-even addressing */ if (set) { outb_p( 0x03, seq_port_reg ); /* Character Map Select */ outb_p( font_select, seq_port_val ); } outb_p( 0x00, seq_port_reg ); outb_p( 0x03, seq_port_val ); /* clear synchronous reset */ outb_p( 0x04, gr_port_reg ); /* Now, the graphics controller */ outb_p( 0x00, gr_port_val ); /* select map 0 for CPU */ outb_p( 0x05, gr_port_reg ); outb_p( 0x10, gr_port_val ); /* enable even-odd addressing */ outb_p( 0x06, gr_port_reg ); outb_p( beg, gr_port_val ); /* map starts at b800:0 or b000:0 */ /* if 512 char mode is already enabled don't re-enable it. */ if ((set)&&(ch512!=vga_512_chars)) { /* attribute controller */ int i; for(i=0; i<MAX_NR_CONSOLES; i++) { struct vc_data *c = vc_cons[i].d; if (c && c->vc_sw == &vga_con) c->vc_hi_font_mask = ch512 ? 0x0800 : 0; } vga_512_chars=ch512; /* 256-char: enable intensity bit 512-char: disable intensity bit */ inb_p( video_port_status ); /* clear address flip-flop */ outb_p ( 0x12, attrib_port ); /* color plane enable register */ outb_p ( ch512 ? 0x07 : 0x0f, attrib_port ); /* Wilton (1987) mentions the following; I don't know what it means, but it works, and it appears necessary */ inb_p( video_port_status ); outb_p ( 0x20, attrib_port ); } spin_unlock_irq(&vga_lock); return 0;}/* * Adjust the screen to fit a font of a certain height */static intvgacon_adjust_height(unsigned fontheight){ int rows, maxscan; unsigned char ovr, vde, fsr; if (fontheight == vga_video_font_height) return 0; vga_video_font_height = video_font_height = fontheight; rows = video_scan_lines/fontheight; /* Number of video rows we end up with */ maxscan = rows*fontheight - 1; /* Scan lines to actually display-1 */ /* Reprogram the CRTC for the new font size Note: the attempt to read the overflow register will fail on an EGA, but using 0xff for the previous value appears to be OK for EGA text modes in the range 257-512 scan lines, so I guess we don't need to worry about it. The same applies for the spill bits in the font size and cursor registers; they are write-only on EGA, but it appears that they are all don't care bits on EGA, so I guess it doesn't matter. */ spin_lock_irq(&vga_lock); outb_p( 0x07, vga_video_port_reg ); /* CRTC overflow register */ ovr = inb_p(vga_video_port_val); outb_p( 0x09, vga_video_port_reg ); /* Font size register */ fsr = inb_p(vga_video_port_val); spin_unlock_irq(&vga_lock); vde = maxscan & 0xff; /* Vertical display end reg */ ovr = (ovr & 0xbd) + /* Overflow register */ ((maxscan & 0x100) >> 7) + ((maxscan & 0x200) >> 3); fsr = (fsr & 0xe0) + (fontheight-1); /* Font size register */ spin_lock_irq(&vga_lock); outb_p( 0x07, vga_video_port_reg ); /* CRTC overflow register */ outb_p( ovr, vga_video_port_val ); outb_p( 0x09, vga_video_port_reg ); /* Font size */ outb_p( fsr, vga_video_port_val ); outb_p( 0x12, vga_video_port_reg ); /* Vertical display limit */ outb_p( vde, vga_video_port_val ); spin_unlock_irq(&vga_lock); vc_resize_all(rows, 0); /* Adjust console size */ return 0;}static int vgacon_font_op(struct vc_data *c, struct console_font_op *op){ int rc; if (vga_video_type < VIDEO_TYPE_EGAM) return -EINVAL; if (op->op == KD_FONT_OP_SET) { if (op->width != 8 || (op->charcount != 256 && op->charcount != 512)) return -EINVAL; rc = vgacon_do_font_op(op->data, 1, op->charcount == 512); if (!rc && !(op->flags & KD_FONT_FLAG_DONT_RECALC)) rc = vgacon_adjust_height(op->height); } else if (op->op == KD_FONT_OP_GET) { op->width = 8; op->height = vga_video_font_height; op->charcount = vga_512_chars ? 512 : 256; if (!op->data) return 0; rc = vgacon_do_font_op(op->data, 0, 0); } else rc = -ENOSYS; return rc;}#elsestatic int vgacon_font_op(struct vc_data *c, struct console_font_op *op){ return -ENOSYS;}#endifstatic int vgacon_scrolldelta(struct vc_data *c, int lines){ if (!lines) /* Turn scrollback off */ c->vc_visible_origin = c->vc_origin; else { int vram_size = vga_vram_end - vga_vram_base; int margin = c->vc_size_row * 4; int ul, we, p, st; if (vga_rolled_over > (c->vc_scr_end - vga_vram_base) + margin) { ul = c->vc_scr_end - vga_vram_base; we = vga_rolled_over + c->vc_size_row; } else { ul = 0; we = vram_size; } p = (c->vc_visible_origin - vga_vram_base - ul + we) % we + lines * c->vc_size_row; st = (c->vc_origin - vga_vram_base - ul + we) % we; if (p < margin) p = 0; if (p > st - margin) p = st; c->vc_visible_origin = vga_vram_base + (p + ul) % we; } vga_set_mem_top(c); return 1;}static int vgacon_set_origin(struct vc_data *c){ if (vga_is_gfx || /* We don't play origin tricks in graphic modes */ (console_blanked && !vga_palette_blanked)) /* Nor we write to blanked screens */ return 0; c->vc_origin = c->vc_visible_origin = vga_vram_base; vga_set_mem_top(c); vga_rolled_over = 0; return 1;}static void vgacon_save_screen(struct vc_data *c){ static int vga_bootup_console = 0; if (!vga_bootup_console) { /* This is a gross hack, but here is the only place we can * set bootup console parameters without messing up generic * console initialization routines. */ vga_bootup_console = 1; c->vc_x = ORIG_X; c->vc_y = ORIG_Y; } if (!vga_is_gfx) scr_memcpyw((u16 *) c->vc_screenbuf, (u16 *) c->vc_origin, c->vc_screenbuf_size);}static int vgacon_scroll(struct vc_data *c, int t, int b, int dir, int lines){ unsigned long oldo; unsigned int delta; if (t || b != c->vc_rows || vga_is_gfx) return 0; if (c->vc_origin != c->vc_visible_origin) vgacon_scrolldelta(c, 0); if (!vga_hardscroll_enabled || lines >= c->vc_rows/2) return 0; oldo = c->vc_origin; delta = lines * c->vc_size_row; if (dir == SM_UP) { if (c->vc_scr_end + delta >= vga_vram_end) { scr_memcpyw((u16 *)vga_vram_base, (u16 *)(oldo + delta), c->vc_screenbuf_size - delta); c->vc_origin = vga_vram_base; vga_rolled_over = oldo - vga_vram_base; } else c->vc_origin += delta; scr_memsetw((u16 *)(c->vc_origin + c->vc_screenbuf_size - delta), c->vc_video_erase_char, delta); } else { if (oldo - delta < vga_vram_base) { scr_memmovew((u16 *)(vga_vram_end - c->vc_screenbuf_size + delta), (u16 *)oldo, c->vc_screenbuf_size - delta); c->vc_origin = vga_vram_end - c->vc_screenbuf_size; vga_rolled_over = 0; } else c->vc_origin -= delta; c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size; scr_memsetw((u16 *)(c->vc_origin), c->vc_video_erase_char, delta); } c->vc_scr_end = c->vc_origin + c->vc_screenbuf_size; c->vc_visible_origin = c->vc_origin; vga_set_mem_top(c); c->vc_pos = (c->vc_pos - oldo) + c->vc_origin; return 1;}/* * The console `switch' structure for the VGA based console */static int vgacon_dummy(struct vc_data *c){ return 0;}#define DUMMY (void *) vgacon_dummyconst struct consw vga_con = { con_startup: vgacon_startup, con_init: vgacon_init, con_deinit: vgacon_deinit, con_clear: DUMMY, con_putc: DUMMY, con_putcs: DUMMY, con_cursor: vgacon_cursor, con_scroll: vgacon_scroll, con_bmove: DUMMY, con_switch: vgacon_switch, con_blank: vgacon_blank, con_font_op: vgacon_font_op, con_set_palette: vgacon_set_palette, con_scrolldelta: vgacon_scrolldelta, con_set_origin: vgacon_set_origin, con_save_screen: vgacon_save_screen, con_build_attr: vgacon_build_attr, con_invert_region: vgacon_invert_region,};MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -