📄 mdacon_lcd.c
字号:
u16 i;#ifdef LCD_DEBUG printk(KERN_DEBUG "mdacon.c for lcd: lcd_clear_text_area\n");#endif // clear memory screen buffer for (i=0; i<SCREENSIZE; ++i) { screen[i]=0; } // clear LCD text area write_lcd_command_word(SET_ADDRESS_POINTER,TEXT_BASE); for (i=0; i<SCREENSIZE; ++i) { write_lcd_command_byte(DATA_WRITE_INC,0); } // clear LCD attribute area write_lcd_command_word(SET_ADDRESS_POINTER,ATTRIB_BASE); for (i=0; i<SCREENSIZE; ++i) { write_lcd_command_byte(DATA_WRITE_INC,0); }}#ifdef MODULEstatic void mda_initialize(void)#else__initfunc(static void mda_initialize(void))#endif{ u16 i; // initialize control port CEHI; // disable chip RDHI; // disable reading from LCD WRHI; // disable writing to LCD CDHI; // command/status mode DATAOUT; // make 8-bit parallel port an output port write_lcd_command_word(SET_GRAPHIC_HOME_ADDRESS,ATTRIB_BASE); write_lcd_command_word(SET_GRAPHIC_AREA,LCD_NUM_COLUMNS); write_lcd_command_word(SET_TEXT_HOME_ADDRESS,TEXT_BASE); write_lcd_command_word(SET_TEXT_AREA,LCD_NUM_COLUMNS); write_lcd_command(SET_MODE | ATTRIBUTE_MODE | EXTERNAL_CG); write_lcd_command_2_bytes(SET_OFFSET_REGISTER,CHARGEN_BASE>>11,0); write_lcd_command(SET_CURSOR_PATTERN | 7); // cursor is 8 lines high write_lcd_command_2_bytes(SET_CURSOR_POINTER,0,0); // load 6x8 font with VGA map write_lcd_command_word(SET_ADDRESS_POINTER,CHARGEN_BASE); for (i=0; i<FONTDATAMAX; ++i) { write_lcd_command_byte(DATA_WRITE_INC,fontdata_6x8[i]); } lcd_enable_text(); lcd_enable_graphic(); lcd_enable_cursor(); lcd_enable_blink(); lcd_clear_text_area();}#ifdef MODULEstatic const char *mdacon_startup(void)#else__initfunc(static const char *mdacon_startup(void))#endif{ lcd_num_columns = LCD_NUM_COLUMNS; lcd_num_lines = LCD_NUM_LINES; lcd_ram_len = 0x2000; lcd_data_port = 0x378; lcd_status_port = lcd_data_port+1; lcd_control_port = lcd_data_port+2; lcd_type = TYPE_LCD; lcd_type_name = "generic Toshiba T6963C"; if (! mda_detect()) { printk("mdacon.c for lcd: LCD not detected.\n"); return NULL; } mda_initialize(); printk("mdacon: %s with %ldK of memory detected.\n", lcd_type_name, lcd_ram_len/1024); return "LCD-0";}static void mdacon_init(struct vc_data *c, int init){#ifdef LCD_DEBUG printk(KERN_DEBUG "mdacon.c for lcd: mdacon_init %i\n",init);#endif c->vc_complement_mask = 0x0800; /* reverse video */ c->vc_display_fg = &lcd_display_fg; if (init) { c->vc_cols = lcd_num_columns; c->vc_rows = lcd_num_lines; } else { vc_resize_con(lcd_num_lines, lcd_num_columns, c->vc_num); } /* make the first MDA console visible */ if (lcd_display_fg == NULL) lcd_display_fg = c; MOD_INC_USE_COUNT;}static void mdacon_deinit(struct vc_data *c){#ifdef LCD_DEBUG printk(KERN_DEBUG "mdacon.c for lcd: mdacon_deinit\n");#endif /* con_set_default_unimap(c->vc_num); */ if (lcd_display_fg == c) lcd_display_fg = NULL; MOD_DEC_USE_COUNT;}static inline u16 lcd_convert_attr(u16 ch){ /* only reverse, blinking and reverse+blinking supported */ /* underline simulated by reverse */ u16 attr=0;#ifdef LCD_DEBUG printk(KERN_DEBUG "mdacon.c for lcd: mdacon_convert_attr %i\n",ch);#endif if (ch & 0x8000) { // blink attr |= 0x0800; } if (ch & 0x1000) { // reverse attr |= 0x0500; } if (ch & 0x0800) { // underline, simulate by reverse attr |= 0x0500; } return (ch & 0x00ff) | attr;}static u8 mdacon_build_attr(struct vc_data *c, u8 color, u8 intensity, u8 blink, u8 underline, u8 reverse){#ifdef LCD_DEBUG printk(KERN_DEBUG "mdacon.c for lcd: mdacon_build_attr " "%i,%i,%i,%i,%i\n",color,intensity,blink,underline,reverse);#endif return (intensity & 3) | ((underline & 1) << 2) | ((reverse & 1) << 3) | ((blink & 1) << 7);}static void mdacon_invert_region(struct vc_data *c, u16 *p, int count){ /* u16 i; printk(KERN_DEBUG "mdacon.c for lcd: unimplemented mdacon_invert_region begin" "%p,%i\n",p,count); for (i=0; i<count; ++i) { printk(KERN_DEBUG "mdacon.c for lcd: pos %i=%i\n",i,*(p+i)); } printk(KERN_DEBUG "mdacon.c for lcd: mdacon_invert_region end\n"); */}static void mdacon_putc(struct vc_data *c, int ch, int y, int x){ u16 ch_converted; u16 position;#ifdef LCD_DEBUG printk(KERN_DEBUG "mdacon.c for lcd: mdacon_putc " "%i,%i,%i\n",ch,y,x);#endif position=POSITION(x,y); ch_converted=lcd_convert_attr(ch); // save character to memory buffer screen[position]=ch_converted; // write character code to LCD write_lcd_command_word(SET_ADDRESS_POINTER,TEXT_BASE+position); write_lcd_command_byte(DATA_WRITE,ch_converted & 0x00ff); // write character attribute to LCD write_lcd_command_word(SET_ADDRESS_POINTER,ATTRIB_BASE+position); write_lcd_command_byte(DATA_WRITE,ch_converted>>8); //lcd_enable_text(); //lcd_enable_graphic();}static void mdacon_putcs(struct vc_data *c, const unsigned short *s, int count, int y, int x){ u16 i; u16 position;#ifdef LCD_DEBUG printk(KERN_DEBUG "mdacon.c for lcd: mdacon_putcs begin " "%p,%i,%i,%i\n",s,count,y,x);#endif position=POSITION(x,y); // save characters to memory buffer for (i=0; i<count; ++i) {#ifdef LCD_DEBUG printk(KERN_DEBUG "mdacon.c for lcd: mdacon_putcs char " "%i\n",*(s+i));#endif screen[position+i]=lcd_convert_attr(*(s+i)); } // write character codes to LCD write_lcd_command_word(SET_ADDRESS_POINTER,TEXT_BASE+position); for (i=0; i<count; ++i) { write_lcd_command_byte(DATA_WRITE_INC,screen[position+i] & 0x00ff); } // write character attributes to LCD write_lcd_command_word(SET_ADDRESS_POINTER,ATTRIB_BASE+position); for (i=0; i<count; ++i) { write_lcd_command_byte(DATA_WRITE_INC,screen[position+i]>>8); }#ifdef LCD_DEBUG printk(KERN_DEBUG "mdacon.c for lcd: mdacon_putcs end\n");#endif //lcd_enable_text(); //lcd_enable_graphic();}static void mdacon_clear(struct vc_data *c, int y, int x, int height, int width){ int xx,yy;#ifdef LCD_DEBUG printk(KERN_DEBUG "mdacon.c for lcd: mdacon_clear " "%i,%i,%i,%i\n",y,x,height,width);#endif if (width <= 0 || height <= 0) return; for (yy=0; yy<height; ++yy) { for (xx=0; xx<width; ++xx) { mdacon_putc(c,c->vc_video_erase_char,y+yy,x+xx); } }} static void mdacon_bmove(struct vc_data *c, int sy, int sx, int dy, int dx, int height, int width){ printk("mdacon.c for lcd: unimplemented mdacon_bmove " "%i,%i,%i,%i,%i,%i\n",sy,sx,dy,dx,height,width);}static int mdacon_switch(struct vc_data *c){ return 1; /* redrawing needed */}static int mdacon_set_palette(struct vc_data *c, unsigned char *table){ return -EINVAL;}static int mdacon_blank(struct vc_data *c, int blank){ printk("mdacon.c for lcd: unimplemented mdacon_blank %i\n",blank); return 0;}static int mdacon_font_op(struct vc_data *c, struct console_font_op *op){ return -ENOSYS;}static int mdacon_scrolldelta(struct vc_data *c, int lines){#ifdef LCD_DEBUG printk(KERN_DEBUG "mdacon.c for lcd: mdacon_scrolldelta %i\n",lines);#endif return 0;}static void mdacon_cursor(struct vc_data *c, int mode){#ifdef LCD_DEBUG printk(KERN_DEBUG "mdacon.c for lcd: mdacon_cursor %i\n",mode);#endif if (mode == CM_ERASE) { lcd_disable_cursor(); return; } write_lcd_command_2_bytes(SET_CURSOR_POINTER,c->vc_x,c->vc_y); switch (c->vc_cursor_type & 0x0f) { case CUR_LOWER_THIRD: lcd_set_cursor_size(0, 1); break; case CUR_LOWER_HALF: lcd_set_cursor_size(0, 3); break; case CUR_TWO_THIRDS: lcd_set_cursor_size(0, 5); break; case CUR_BLOCK: lcd_set_cursor_size(0, 7); break; case CUR_NONE: lcd_set_cursor_size(8, 7); break; default: lcd_set_cursor_size(0, 1); break; } lcd_enable_cursor();}static void lcd_memset(u16 d, const unsigned short ch, u16 count){ u16 i; u16 ch_converted; ch_converted=lcd_convert_attr(ch); // memset to memory buffer for (i=0; i<count; ++i) { screen[d+i]=ch_converted; } // memset to LCD text area write_lcd_command_word(SET_ADDRESS_POINTER,TEXT_BASE+d); for (i=0; i<count; ++i) { write_lcd_command_byte(DATA_WRITE_INC,ch_converted & 0x00ff); } // memset to LCD attribute area write_lcd_command_word(SET_ADDRESS_POINTER,ATTRIB_BASE+d); for (i=0; i<count; ++i) { write_lcd_command_byte(DATA_WRITE_INC,ch_converted>>8); }}static void lcd_memmove(u16 d, u16 s, u16 count){ u16 i; if (d<s) { // move memory buffer for (i=0; i<count; ++i) { screen[d+i]=screen[s+i]; } } else { // move memory buffer for (i=0; i<count; ++i) { screen[d+count-1-i]=screen[s+count-1-i]; } } // update LCD text area write_lcd_command_word(SET_ADDRESS_POINTER,TEXT_BASE+d); for (i=0; i<count; ++i) { write_lcd_command_byte(DATA_WRITE_INC,screen[d+i] & 0x00ff); } // update LCD attribute area write_lcd_command_word(SET_ADDRESS_POINTER,ATTRIB_BASE+d); for (i=0; i<count; ++i) { write_lcd_command_byte(DATA_WRITE_INC,screen[d+i]>>8); }}static int mdacon_scroll(struct vc_data *c, int t, int b, int dir, int lines){#ifdef LCD_DEBUG printk(KERN_DEBUG "mdacon.c for lcd: mdacon_scroll " "t=%i,b=%i,dir=%i,lines=%i\n",t,b,dir,lines);#endif if (!lines) return 0; if (lines>c->vc_rows) lines=c->vc_rows; switch (dir) { case SM_UP: lcd_memmove(POSITION(0,t),POSITION(0,t+lines), (b-t-lines)*lcd_num_columns); lcd_memset(POSITION(0,b-lines),c->vc_video_erase_char, lines*lcd_num_columns); break; case SM_DOWN: lcd_memmove(POSITION(0,t+lines),POSITION(0,t), (b-t-lines)*lcd_num_columns); lcd_memset(POSITION(0,t),c->vc_video_erase_char, lines*lcd_num_columns); break; } //lcd_enable_text(); //lcd_enable_graphic();#ifdef LCD_DEBUG printk(KERN_DEBUG "mdacon.c for lcd: mdacon_scroll more " "eattr=%i,lines=%i,lcd_num_columns=%i,c->vc_rows=%i\n", c->vc_video_erase_char,lines,lcd_num_columns,c->vc_rows);#endif return 0;}/* * The console `switch' structure for the MDA based console */struct consw mda_con = { mdacon_startup, /* con_startup */ mdacon_init, /* con_init */ mdacon_deinit, /* con_deinit */ mdacon_clear, /* con_clear */ mdacon_putc, /* con_putc */ mdacon_putcs, /* con_putcs */ mdacon_cursor, /* con_cursor */ mdacon_scroll, /* con_scroll */ mdacon_bmove, /* con_bmove */ mdacon_switch, /* con_switch */ mdacon_blank, /* con_blank */ mdacon_font_op, /* con_font_op */ mdacon_set_palette, /* con_set_palette */ mdacon_scrolldelta, /* con_scrolldelta */ NULL, /* con_set_origin */ NULL, /* con_save_screen */ mdacon_build_attr, /* con_build_attr */ mdacon_invert_region, /* con_invert_region */};#ifdef MODULEvoid mda_console_init(void)#else__initfunc(void mda_console_init(void))#endif{ if (mda_first_vc > mda_last_vc) return; take_over_console(&mda_con, mda_first_vc-1, mda_last_vc-1, 0);}#ifdef MODULEint init_module(void){ mda_console_init(); return 0;}void cleanup_module(void){ give_up_console(&mda_con);}#endif#ifdef STANDALONEint main(void){ unsigned short buffer[80]; struct vc_data c; int i; ioperm(0x378,3,1); ioperm(0x80,1,1); c.vc_rows=16; c.vc_cols=40; c.vc_video_erase_char=32; mdacon_startup(); mdacon_init(&c,1); for (i=0; i<16; ++i) { buffer[0]=i/10+48; buffer[1]=i%10+48; mdacon_putcs(&c,buffer,2,i,0); } mdacon_scroll(&c,0,16,1,1); return 0;}#endif // def STANDALONE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -