📄 vgacon_lcd.c
字号:
/* * vgacon_lcd.c -- console driver for LCDs with a Toshiba T6963C controller * * Version 0.1, 11 Apr 2000, for Linux kernel 2.2.10 * * (c) 1999-2000 Alexander Frink <Alexander.Frink@Uni-Mainz.DE> * * Replace linux/drivers/video/vgacon.c with this file to use the * display as the primary "video card". * * Adjust LCD_NUM_COLUMNS and LCD_NUM_LINES to the size of your display. * * This file is based on the original console drivers for VGA and MDA * cards (linux/drivers/video/vgacon.c and linux/drivers/video/mdacon.c) * mainly written by Linus Torvalds, Jay Estabrook, Geert Uytterhoeven, * Martin Mares, Patrick Caulfield and Andrew Apted 1991-1998. * The logic to access the T6963C is taken from a program written * by John P. Beale 1997. * * This file is subject to the terms and conditions of the GNU General Public * License. See the file LICENSE in the main directory of this archive for * more details. *///#define STANDALONE//#define LCD_DEBUG#ifndef STANDALONE#include <linux/types.h>#include <linux/sched.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/module.h>#include <linux/tty.h>#include <linux/console.h>#include <linux/console_struct.h>#include <linux/string.h>#include <linux/kd.h>#include <linux/malloc.h>#include <linux/vt_kern.h>#include <linux/vt_buffer.h>#include <linux/selection.h>#include <linux/ioport.h>#include <linux/delay.h>#include <linux/init.h>#include <asm/io.h>#include <asm/vga.h>#else // ndef STANDALONE#include <asm/io.h>#include <unistd.h>typedef unsigned short u16;typedef unsigned char u8;void cli(void) {}void save_flags(unsigned long f) {}void restore_flags(unsigned long f) {}void vc_resize_con(unsigned int l, unsigned int c, unsigned short n) {}struct vc_data { unsigned int vc_rows; unsigned short vc_complement_mask; struct vc_data **vc_display_fg; unsigned int vc_cols; unsigned short vc_num; unsigned int vc_x; unsigned int vc_y; unsigned short vc_video_erase_char; unsigned int vc_cursor_type;};struct console_font_op {};struct consw { const char *(*con_startup)(void); void (*con_init)(struct vc_data *, int); void (*con_deinit)(struct vc_data *); void (*con_clear)(struct vc_data *, int, int, int, int); void (*con_putc)(struct vc_data *, int, int, int); void (*con_putcs)(struct vc_data *, const unsigned short *, int, int, int); void (*con_cursor)(struct vc_data *, int); int (*con_scroll)(struct vc_data *, int, int, int, int); void (*con_bmove)(struct vc_data *, int, int, int, int, int, int); int (*con_switch)(struct vc_data *); int (*con_blank)(struct vc_data *, int); int (*con_font_op)(struct vc_data *, struct console_font_op *); int (*con_set_palette)(struct vc_data *, unsigned char *); int (*con_scrolldelta)(struct vc_data *, int); int (*con_set_origin)(struct vc_data *); void (*con_save_screen)(struct vc_data *); u8 (*con_build_attr)(struct vc_data *, u8, u8, u8, u8, u8); void (*con_invert_region)(struct vc_data *, u16 *, int); u16 *(*con_screen_pos)(struct vc_data *, int); unsigned long (*con_getxy)(struct vc_data *, unsigned long, int *, int *);};void take_over_console(struct consw *con, int f, int l, int dummy) {}#define printk printf#define KERN_DEBUG ""//#define NULL 0#define __initfunc(X) X#define MAX_NR_CONSOLES 64#define SM_UP (1)#define SM_DOWN (2)#define MOD_INC_USE_COUNT#define MOD_DEC_USE_COUNT#define EINVAL 0#define ENOSYS 0#define CM_ERASE (2)#define CUR_LOWER_THIRD 3#define CUR_LOWER_HALF 4#define CUR_TWO_THIRDS 5#define CUR_BLOCK 6#define CUR_NONE 1#endif // ndef STANDALONE/* * Interface used by the world */static const char *lcdcon_startup(void);static void lcdcon_init(struct vc_data *c, int init);static void lcdcon_deinit(struct vc_data *c);static void lcdcon_cursor(struct vc_data *c, int mode);static int lcdcon_switch(struct vc_data *c);static int lcdcon_blank(struct vc_data *c, int blank);static int lcdcon_font_op(struct vc_data *c, struct console_font_op *op);static int lcdcon_set_palette(struct vc_data *c, unsigned char *table);static int lcdcon_scrolldelta(struct vc_data *c, int lines);static int lcdcon_set_origin(struct vc_data *c);static void lcdcon_save_screen(struct vc_data *c);static int lcdcon_scroll(struct vc_data *c, int t, int b, int dir, int lines);static u8 lcdcon_build_attr(struct vc_data *c, u8 color, u8 intensity, u8 blink, u8 underline, u8 reverse);static void lcdcon_invert_region(struct vc_data *c, u16 *p, int count);static unsigned long lcdcon_uni_pagedir[2];/* description of the hardware layout */static unsigned long lcd_vram_base; /* Base of video memory */static unsigned long lcd_vram_len; /* Size of video memory */static unsigned int lcd_num_columns; /* Number of text columns */static unsigned int lcd_num_lines; /* Number of text lines */static unsigned int lcd_data_port;static unsigned int lcd_status_port;static unsigned int lcd_control_port;/* current hardware state */static int lcd_origin_loc=-1;static int lcd_cursor_size_from=-1;static int lcd_cursor_size_to=-1;static u8 lcd_display_mode=0;static enum { TYPE_LCD } lcd_type;static char *lcd_type_name;static struct vc_data *lcd_display_fg = NULL;// take PC 1 HI#define CEHI outb_p(inb_p(lcd_control_port) & 0xfe, lcd_control_port)// take PC 1 LO#define CELO outb_p(inb_p(lcd_control_port) | 0x01, lcd_control_port)// take PC 14 HI#define RDHI outb_p(inb_p(lcd_control_port) & 0xfd, lcd_control_port)// take PC 14 LO#define RDLO outb_p(inb_p(lcd_control_port) | 0x02, lcd_control_port)// take PC 16 HI#define WRHI outb_p(inb_p(lcd_control_port) | 0x04, lcd_control_port)// take PC 16 LO#define WRLO outb_p(inb_p(lcd_control_port) & 0xfb, lcd_control_port)// take PC 17 HI#define CDHI outb_p(inb_p(lcd_control_port) & 0xf7, lcd_control_port)// take PC 17 LO#define CDLO outb_p(inb_p(lcd_control_port) | 0x08, lcd_control_port)// 8bit Data input#define DATAIN outb_p(inb_p(lcd_control_port) | 0x20, lcd_control_port)// 8bit Data output#define DATAOUT outb_p(inb_p(lcd_control_port) & 0xdf, lcd_control_port)// get LCD display status bytestatic inline u8 read_lcd_status(void){ unsigned long flags; u8 lcd_status; save_flags(flags); cli(); DATAIN; // make 8-bit parallel port an input CDHI; // bring LCD C/D line high (read status byte) RDLO; // bring LCD /RD line low (read active) CELO; // bring LCD /CE line low (chip-enable active) lcd_status = inb_p(lcd_data_port); // read LCD status byte CEHI; // bring LCD /CE line high, disabling it RDHI; // deactivate LCD read mode DATAOUT; // make 8-bit parallel port an output port // printk(KERN_DEBUG "lcdcon: status=%i\n",lcd_status); restore_flags(flags); return(lcd_status);}static inline void lcd_wait_until_ready(void){ do { } while ((0x03 & read_lcd_status()) != 0x03);}// write data byte to LCD module over par. port// assume PC port in data OUTPUT modestatic inline void write_lcd_data(u8 byte){ unsigned long flags; save_flags(flags); cli(); lcd_wait_until_ready(); CDLO; WRLO; // activate LCD's write mode outb_p(byte,lcd_data_port); // write value to data port CELO; // pulse enable LOW > 80 ns (hah!) CEHI; // return enable HIGH WRHI; // restore Write mode to inactive // using my P5/75 MHz PC with ISA bus, CE stays low for 2 microseconds restore_flags(flags);} // get data byte from LCD modulestatic inline u8 read_lcd_data(void){ unsigned long flags; u8 lcd_byte; save_flags(flags); cli(); lcd_wait_until_ready(); DATAIN; // make PC's port an input port WRHI; // make sure WRITE mode is inactive CDLO; // data mode RDLO; // activate READ mode CELO; // enable chip, which outputs data lcd_byte = inb_p(lcd_data_port); // read data from LCD CEHI; // disable chip RDHI; // turn off READ mode DATAOUT; // make 8-bit parallel port an output port restore_flags(flags); return(lcd_byte);}// write command byte to LCD module// assumes port is in data OUTPUT modestatic inline void write_lcd_command(u8 byte){ unsigned long flags; save_flags(flags); cli(); lcd_wait_until_ready(); outb_p(byte,lcd_data_port); // present data to LCD on PC's port pins CDHI; // control/status mode RDHI; // make sure LCD read mode is off WRLO; // activate LCD write mode CELO; // pulse ChipEnable LOW, > 80 ns, enables LCD I/O CEHI; // disable LCD I/O WRHI; // deactivate write mode restore_flags(flags);}#define LCD_NUM_COLUMNS 40#define LCD_NUM_LINES 16#define SCREENSIZE (LCD_NUM_COLUMNS*LCD_NUM_LINES)#define CHARGEN_BASE 0x0000#define TEXT_BASE 0x0800#define ATTRIB_BASE 0x1000#define SET_CURSOR_POINTER 0x21#define SET_OFFSET_REGISTER 0x22#define SET_ADDRESS_POINTER 0x24#define SET_TEXT_HOME_ADDRESS 0x40#define SET_TEXT_AREA 0x41#define SET_GRAPHIC_HOME_ADDRESS 0x42#define SET_GRAPHIC_AREA 0x43#define SET_MODE 0x80#define OR_MODE 0x00#define EXOR_MODE 0x01#define AND_MODE 0x03#define ATTRIBUTE_MODE 0x04#define INTERNAL_CG 0x00#define EXTERNAL_CG 0x08#define SET_DISPLAY_MODE 0x90#define BLINK_ON 0x01#define CURSOR_ON 0x02#define TEXT_ON 0x04#define GRAPHIC_ON 0x08#define SET_CURSOR_PATTERN 0xa0#define DATA_WRITE_INC 0xc0#define DATA_READ_INC 0xc1#define DATA_WRITE_DEC 0xc2#define DATA_READ_DEC 0xc3#define DATA_WRITE 0xc4#define DATA_READ 0xc5#define AUTO_WRITE 0xb0#define AUTO_READ 0xb1#define AUTO_RESET 0xb2#include "font_6x8.c"#define POSITION(x,y) ((y)*lcd_num_columns + (x))static u16 screen[SCREENSIZE];static u16 vram[SCREENSIZE];static inline void write_lcd_command_word(u8 cmd, u16 word){ write_lcd_data(word%256); write_lcd_data(word>>8); write_lcd_command(cmd);}static inline void write_lcd_command_2_bytes(u8 cmd, u8 byte1, u8 byte2){ write_lcd_data(byte1); write_lcd_data(byte2); write_lcd_command(cmd);}static inline void write_lcd_command_byte(u8 cmd, u8 byte){ write_lcd_data(byte); write_lcd_command(cmd);}static void init_auto_read(u16 addr){ write_lcd_command_word(SET_ADDRESS_POINTER,addr); write_lcd_command(AUTO_READ); DATAIN; // make PC's port an input port WRHI; // make sure WRITE mode is inactive RDHI; // make sure READ mode is inactive}static void status_check_2(void){ u8 lcd_byte; CDHI; // command mode WRHI; do { RDLO; // activate READ mode CELO; lcd_byte = inb_p(lcd_data_port); // read data from LCD#ifdef LCD_DEBUG printk(KERN_DEBUG "lcdcon: status_check_2 %i\n",lcd_byte);#endif CEHI; RDHI; } while ((lcd_byte & 0x4) == 0);}static u8 next_auto_read(void){ u8 lcd_byte; status_check_2(); WRHI; CDLO; RDLO; CELO; lcd_byte=inb_p(lcd_data_port); CEHI; RDHI; return lcd_byte;}static void end_auto_read(void){ status_check_2(); RDHI; WRHI; DATAOUT; write_lcd_command(AUTO_RESET);}static void lcd_enable_cursor(void){ lcd_display_mode |= CURSOR_ON; write_lcd_command(SET_DISPLAY_MODE | lcd_display_mode);}static void lcd_disable_cursor(void){ lcd_display_mode &= ~CURSOR_ON; write_lcd_command(SET_DISPLAY_MODE | lcd_display_mode);}static void lcd_enable_blink(void){ lcd_display_mode |= BLINK_ON; write_lcd_command(SET_DISPLAY_MODE | lcd_display_mode);}static void lcd_disable_blink(void){ lcd_display_mode &= ~BLINK_ON; write_lcd_command(SET_DISPLAY_MODE | lcd_display_mode);}static void lcd_enable_text(void){ lcd_display_mode |= TEXT_ON; write_lcd_command(SET_DISPLAY_MODE | lcd_display_mode);}static void lcd_disable_text(void){ lcd_display_mode &= ~TEXT_ON; write_lcd_command(SET_DISPLAY_MODE | lcd_display_mode);}static void lcd_enable_graphic(void){ lcd_display_mode |= GRAPHIC_ON; write_lcd_command(SET_DISPLAY_MODE | lcd_display_mode);}static void lcd_disable_graphic(void){ lcd_display_mode &= ~GRAPHIC_ON; write_lcd_command(SET_DISPLAY_MODE | lcd_display_mode);}static inline void lcd_set_cursor_size(u8 from, u8 to){#ifdef LCD_DEBUG printk(KERN_DEBUG "lcdcon: lcd_set_cursor_size %i,%i\n", from,to);#endif if (lcd_cursor_size_from==from && lcd_cursor_size_to==to) return; if (from > to) { lcd_disable_cursor(); } else { if (to>7) to=7; write_lcd_command(SET_CURSOR_PATTERN | to); lcd_enable_cursor(); } lcd_cursor_size_from = from; lcd_cursor_size_to = to;}static void lcd_clear_text_area(void){ u16 i;#ifdef LCD_DEBUG printk(KERN_DEBUG "lcdcon: 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); }}void no_scroll(char *str, int *ints){}__initfunc(static const char *lcdcon_startup(void))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -