18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * linux/drivers/video/console/sticon.c - console driver using HP's STI firmware 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> 58c2ecf20Sopenharmony_ci * Copyright (C) 2002-2020 Helge Deller <deller@gmx.de> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Based on linux/drivers/video/vgacon.c and linux/drivers/video/fbcon.c, 88c2ecf20Sopenharmony_ci * which were 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Created 28 Sep 1997 by Geert Uytterhoeven 118c2ecf20Sopenharmony_ci * Rewritten by Martin Mares <mj@ucw.cz>, July 1998 128c2ecf20Sopenharmony_ci * Copyright (C) 1991, 1992 Linus Torvalds 138c2ecf20Sopenharmony_ci * 1995 Jay Estabrook 148c2ecf20Sopenharmony_ci * Copyright (C) 1995 Geert Uytterhoeven 158c2ecf20Sopenharmony_ci * Copyright (C) 1993 Bjoern Brauel 168c2ecf20Sopenharmony_ci * Roman Hodek 178c2ecf20Sopenharmony_ci * Copyright (C) 1993 Hamish Macdonald 188c2ecf20Sopenharmony_ci * Greg Harp 198c2ecf20Sopenharmony_ci * Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk] 208c2ecf20Sopenharmony_ci * 218c2ecf20Sopenharmony_ci * with work by William Rucklidge (wjr@cs.cornell.edu) 228c2ecf20Sopenharmony_ci * Geert Uytterhoeven 238c2ecf20Sopenharmony_ci * Jes Sorensen (jds@kom.auc.dk) 248c2ecf20Sopenharmony_ci * Martin Apel 258c2ecf20Sopenharmony_ci * with work by Guenther Kelleter 268c2ecf20Sopenharmony_ci * Martin Schaller 278c2ecf20Sopenharmony_ci * Andreas Schwab 288c2ecf20Sopenharmony_ci * Emmanuel Marty (core@ggi-project.org) 298c2ecf20Sopenharmony_ci * Jakub Jelinek (jj@ultra.linux.cz) 308c2ecf20Sopenharmony_ci * Martin Mares <mj@ucw.cz> 318c2ecf20Sopenharmony_ci * 328c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 338c2ecf20Sopenharmony_ci * License. See the file COPYING in the main directory of this archive for 348c2ecf20Sopenharmony_ci * more details. 358c2ecf20Sopenharmony_ci * 368c2ecf20Sopenharmony_ci */ 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#include <linux/init.h> 398c2ecf20Sopenharmony_ci#include <linux/kernel.h> 408c2ecf20Sopenharmony_ci#include <linux/console.h> 418c2ecf20Sopenharmony_ci#include <linux/errno.h> 428c2ecf20Sopenharmony_ci#include <linux/vt_kern.h> 438c2ecf20Sopenharmony_ci#include <linux/kd.h> 448c2ecf20Sopenharmony_ci#include <linux/selection.h> 458c2ecf20Sopenharmony_ci#include <linux/module.h> 468c2ecf20Sopenharmony_ci#include <linux/slab.h> 478c2ecf20Sopenharmony_ci#include <linux/font.h> 488c2ecf20Sopenharmony_ci#include <linux/crc32.h> 498c2ecf20Sopenharmony_ci#include <linux/fb.h> 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci#include <asm/io.h> 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci#include "../fbdev/sticore.h" 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci/* switching to graphics mode */ 568c2ecf20Sopenharmony_ci#define BLANK 0 578c2ecf20Sopenharmony_cistatic int vga_is_gfx; 588c2ecf20Sopenharmony_ci 598c2ecf20Sopenharmony_ci#define STI_DEF_FONT sticon_sti->font 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci/* borrowed from fbcon.c */ 628c2ecf20Sopenharmony_ci#define FNTREFCOUNT(fd) (fd->refcount) 638c2ecf20Sopenharmony_ci#define FNTCRC(fd) (fd->crc) 648c2ecf20Sopenharmony_cistatic struct sti_cooked_font *font_data[MAX_NR_CONSOLES]; 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci/* this is the sti_struct used for this console */ 678c2ecf20Sopenharmony_cistatic struct sti_struct *sticon_sti; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_cistatic const char *sticon_startup(void) 708c2ecf20Sopenharmony_ci{ 718c2ecf20Sopenharmony_ci return "STI console"; 728c2ecf20Sopenharmony_ci} 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_cistatic void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos) 758c2ecf20Sopenharmony_ci{ 768c2ecf20Sopenharmony_ci if (vga_is_gfx || console_blanked) 778c2ecf20Sopenharmony_ci return; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci if (conp->vc_mode != KD_TEXT) 808c2ecf20Sopenharmony_ci return; 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci sti_putc(sticon_sti, c, ypos, xpos, font_data[conp->vc_num]); 838c2ecf20Sopenharmony_ci} 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistatic void sticon_putcs(struct vc_data *conp, const unsigned short *s, 868c2ecf20Sopenharmony_ci int count, int ypos, int xpos) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci if (vga_is_gfx || console_blanked) 898c2ecf20Sopenharmony_ci return; 908c2ecf20Sopenharmony_ci 918c2ecf20Sopenharmony_ci if (conp->vc_mode != KD_TEXT) 928c2ecf20Sopenharmony_ci return; 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci while (count--) { 958c2ecf20Sopenharmony_ci sti_putc(sticon_sti, scr_readw(s++), ypos, xpos++, 968c2ecf20Sopenharmony_ci font_data[conp->vc_num]); 978c2ecf20Sopenharmony_ci } 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_cistatic void sticon_cursor(struct vc_data *conp, int mode) 1018c2ecf20Sopenharmony_ci{ 1028c2ecf20Sopenharmony_ci unsigned short car1; 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci /* no cursor update if screen is blanked */ 1058c2ecf20Sopenharmony_ci if (vga_is_gfx || console_blanked) 1068c2ecf20Sopenharmony_ci return; 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci car1 = conp->vc_screenbuf[conp->state.x + conp->state.y * conp->vc_cols]; 1098c2ecf20Sopenharmony_ci switch (mode) { 1108c2ecf20Sopenharmony_ci case CM_ERASE: 1118c2ecf20Sopenharmony_ci sti_putc(sticon_sti, car1, conp->state.y, conp->state.x, 1128c2ecf20Sopenharmony_ci font_data[conp->vc_num]); 1138c2ecf20Sopenharmony_ci break; 1148c2ecf20Sopenharmony_ci case CM_MOVE: 1158c2ecf20Sopenharmony_ci case CM_DRAW: 1168c2ecf20Sopenharmony_ci switch (CUR_SIZE(conp->vc_cursor_type)) { 1178c2ecf20Sopenharmony_ci case CUR_UNDERLINE: 1188c2ecf20Sopenharmony_ci case CUR_LOWER_THIRD: 1198c2ecf20Sopenharmony_ci case CUR_LOWER_HALF: 1208c2ecf20Sopenharmony_ci case CUR_TWO_THIRDS: 1218c2ecf20Sopenharmony_ci case CUR_BLOCK: 1228c2ecf20Sopenharmony_ci sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11), 1238c2ecf20Sopenharmony_ci conp->state.y, conp->state.x, font_data[conp->vc_num]); 1248c2ecf20Sopenharmony_ci break; 1258c2ecf20Sopenharmony_ci } 1268c2ecf20Sopenharmony_ci break; 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci} 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_cistatic bool sticon_scroll(struct vc_data *conp, unsigned int t, 1318c2ecf20Sopenharmony_ci unsigned int b, enum con_scroll dir, unsigned int count) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci struct sti_struct *sti = sticon_sti; 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci if (vga_is_gfx) 1368c2ecf20Sopenharmony_ci return false; 1378c2ecf20Sopenharmony_ci 1388c2ecf20Sopenharmony_ci sticon_cursor(conp, CM_ERASE); 1398c2ecf20Sopenharmony_ci 1408c2ecf20Sopenharmony_ci switch (dir) { 1418c2ecf20Sopenharmony_ci case SM_UP: 1428c2ecf20Sopenharmony_ci sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols, 1438c2ecf20Sopenharmony_ci font_data[conp->vc_num]); 1448c2ecf20Sopenharmony_ci sti_clear(sti, b - count, 0, count, conp->vc_cols, 1458c2ecf20Sopenharmony_ci conp->vc_video_erase_char, font_data[conp->vc_num]); 1468c2ecf20Sopenharmony_ci break; 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci case SM_DOWN: 1498c2ecf20Sopenharmony_ci sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols, 1508c2ecf20Sopenharmony_ci font_data[conp->vc_num]); 1518c2ecf20Sopenharmony_ci sti_clear(sti, t, 0, count, conp->vc_cols, 1528c2ecf20Sopenharmony_ci conp->vc_video_erase_char, font_data[conp->vc_num]); 1538c2ecf20Sopenharmony_ci break; 1548c2ecf20Sopenharmony_ci } 1558c2ecf20Sopenharmony_ci 1568c2ecf20Sopenharmony_ci return false; 1578c2ecf20Sopenharmony_ci} 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_cistatic int sticon_set_def_font(int unit, struct console_font *op) 1608c2ecf20Sopenharmony_ci{ 1618c2ecf20Sopenharmony_ci if (font_data[unit] != STI_DEF_FONT) { 1628c2ecf20Sopenharmony_ci if (--FNTREFCOUNT(font_data[unit]) == 0) { 1638c2ecf20Sopenharmony_ci kfree(font_data[unit]->raw_ptr); 1648c2ecf20Sopenharmony_ci kfree(font_data[unit]); 1658c2ecf20Sopenharmony_ci } 1668c2ecf20Sopenharmony_ci font_data[unit] = STI_DEF_FONT; 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci return 0; 1708c2ecf20Sopenharmony_ci} 1718c2ecf20Sopenharmony_ci 1728c2ecf20Sopenharmony_cistatic int sticon_set_font(struct vc_data *vc, struct console_font *op) 1738c2ecf20Sopenharmony_ci{ 1748c2ecf20Sopenharmony_ci struct sti_struct *sti = sticon_sti; 1758c2ecf20Sopenharmony_ci int vc_cols, vc_rows, vc_old_cols, vc_old_rows; 1768c2ecf20Sopenharmony_ci int unit = vc->vc_num; 1778c2ecf20Sopenharmony_ci int w = op->width; 1788c2ecf20Sopenharmony_ci int h = op->height; 1798c2ecf20Sopenharmony_ci int size, i, bpc, pitch; 1808c2ecf20Sopenharmony_ci struct sti_rom_font *new_font; 1818c2ecf20Sopenharmony_ci struct sti_cooked_font *cooked_font; 1828c2ecf20Sopenharmony_ci unsigned char *data = op->data, *p; 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci if ((w < 6) || (h < 6) || (w > 32) || (h > 32) 1858c2ecf20Sopenharmony_ci || (op->charcount != 256 && op->charcount != 512)) 1868c2ecf20Sopenharmony_ci return -EINVAL; 1878c2ecf20Sopenharmony_ci pitch = ALIGN(w, 8) / 8; 1888c2ecf20Sopenharmony_ci bpc = pitch * h; 1898c2ecf20Sopenharmony_ci size = bpc * op->charcount; 1908c2ecf20Sopenharmony_ci 1918c2ecf20Sopenharmony_ci new_font = kmalloc(sizeof(*new_font) + size, STI_LOWMEM); 1928c2ecf20Sopenharmony_ci if (!new_font) 1938c2ecf20Sopenharmony_ci return -ENOMEM; 1948c2ecf20Sopenharmony_ci 1958c2ecf20Sopenharmony_ci new_font->first_char = 0; 1968c2ecf20Sopenharmony_ci new_font->last_char = op->charcount - 1; 1978c2ecf20Sopenharmony_ci new_font->width = w; 1988c2ecf20Sopenharmony_ci new_font->height = h; 1998c2ecf20Sopenharmony_ci new_font->font_type = STI_FONT_HPROMAN8; 2008c2ecf20Sopenharmony_ci new_font->bytes_per_char = bpc; 2018c2ecf20Sopenharmony_ci new_font->underline_height = 0; 2028c2ecf20Sopenharmony_ci new_font->underline_pos = 0; 2038c2ecf20Sopenharmony_ci 2048c2ecf20Sopenharmony_ci cooked_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL); 2058c2ecf20Sopenharmony_ci if (!cooked_font) { 2068c2ecf20Sopenharmony_ci kfree(new_font); 2078c2ecf20Sopenharmony_ci return -ENOMEM; 2088c2ecf20Sopenharmony_ci } 2098c2ecf20Sopenharmony_ci cooked_font->raw = new_font; 2108c2ecf20Sopenharmony_ci cooked_font->raw_ptr = new_font; 2118c2ecf20Sopenharmony_ci cooked_font->width = w; 2128c2ecf20Sopenharmony_ci cooked_font->height = h; 2138c2ecf20Sopenharmony_ci FNTREFCOUNT(cooked_font) = 0; /* usage counter */ 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_ci p = (unsigned char *) new_font; 2168c2ecf20Sopenharmony_ci p += sizeof(*new_font); 2178c2ecf20Sopenharmony_ci for (i = 0; i < op->charcount; i++) { 2188c2ecf20Sopenharmony_ci memcpy(p, data, bpc); 2198c2ecf20Sopenharmony_ci data += pitch*32; 2208c2ecf20Sopenharmony_ci p += bpc; 2218c2ecf20Sopenharmony_ci } 2228c2ecf20Sopenharmony_ci FNTCRC(cooked_font) = crc32(0, new_font, size + sizeof(*new_font)); 2238c2ecf20Sopenharmony_ci sti_font_convert_bytemode(sti, cooked_font); 2248c2ecf20Sopenharmony_ci new_font = cooked_font->raw_ptr; 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci /* check if font is already used by other console */ 2278c2ecf20Sopenharmony_ci for (i = 0; i < MAX_NR_CONSOLES; i++) { 2288c2ecf20Sopenharmony_ci if (font_data[i] != STI_DEF_FONT 2298c2ecf20Sopenharmony_ci && (FNTCRC(font_data[i]) == FNTCRC(cooked_font))) { 2308c2ecf20Sopenharmony_ci kfree(new_font); 2318c2ecf20Sopenharmony_ci kfree(cooked_font); 2328c2ecf20Sopenharmony_ci /* current font is the same as the new one */ 2338c2ecf20Sopenharmony_ci if (i == unit) 2348c2ecf20Sopenharmony_ci return 0; 2358c2ecf20Sopenharmony_ci cooked_font = font_data[i]; 2368c2ecf20Sopenharmony_ci new_font = cooked_font->raw_ptr; 2378c2ecf20Sopenharmony_ci break; 2388c2ecf20Sopenharmony_ci } 2398c2ecf20Sopenharmony_ci } 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci /* clear screen with old font: we now may have less rows */ 2428c2ecf20Sopenharmony_ci vc_old_rows = vc->vc_rows; 2438c2ecf20Sopenharmony_ci vc_old_cols = vc->vc_cols; 2448c2ecf20Sopenharmony_ci sti_clear(sticon_sti, 0, 0, vc_old_rows, vc_old_cols, 2458c2ecf20Sopenharmony_ci vc->vc_video_erase_char, font_data[vc->vc_num]); 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci /* delete old font in case it is a user font */ 2488c2ecf20Sopenharmony_ci sticon_set_def_font(unit, NULL); 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_ci FNTREFCOUNT(cooked_font)++; 2518c2ecf20Sopenharmony_ci font_data[unit] = cooked_font; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci vc_cols = sti_onscreen_x(sti) / cooked_font->width; 2548c2ecf20Sopenharmony_ci vc_rows = sti_onscreen_y(sti) / cooked_font->height; 2558c2ecf20Sopenharmony_ci vc_resize(vc, vc_cols, vc_rows); 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci /* need to repaint screen if cols & rows are same as old font */ 2588c2ecf20Sopenharmony_ci if (vc_cols == vc_old_cols && vc_rows == vc_old_rows) 2598c2ecf20Sopenharmony_ci update_screen(vc); 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci return 0; 2628c2ecf20Sopenharmony_ci} 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_cistatic int sticon_font_default(struct vc_data *vc, struct console_font *op, char *name) 2658c2ecf20Sopenharmony_ci{ 2668c2ecf20Sopenharmony_ci return sticon_set_def_font(vc->vc_num, op); 2678c2ecf20Sopenharmony_ci} 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_cistatic int sticon_font_set(struct vc_data *vc, struct console_font *font, 2708c2ecf20Sopenharmony_ci unsigned int flags) 2718c2ecf20Sopenharmony_ci{ 2728c2ecf20Sopenharmony_ci return sticon_set_font(vc, font); 2738c2ecf20Sopenharmony_ci} 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_cistatic void sticon_init(struct vc_data *c, int init) 2768c2ecf20Sopenharmony_ci{ 2778c2ecf20Sopenharmony_ci struct sti_struct *sti = sticon_sti; 2788c2ecf20Sopenharmony_ci int vc_cols, vc_rows; 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci sti_set(sti, 0, 0, sti_onscreen_y(sti), sti_onscreen_x(sti), 0); 2818c2ecf20Sopenharmony_ci vc_cols = sti_onscreen_x(sti) / sti->font->width; 2828c2ecf20Sopenharmony_ci vc_rows = sti_onscreen_y(sti) / sti->font->height; 2838c2ecf20Sopenharmony_ci c->vc_can_do_color = 1; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci if (init) { 2868c2ecf20Sopenharmony_ci c->vc_cols = vc_cols; 2878c2ecf20Sopenharmony_ci c->vc_rows = vc_rows; 2888c2ecf20Sopenharmony_ci } else { 2898c2ecf20Sopenharmony_ci vc_resize(c, vc_cols, vc_rows); 2908c2ecf20Sopenharmony_ci } 2918c2ecf20Sopenharmony_ci} 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_cistatic void sticon_deinit(struct vc_data *c) 2948c2ecf20Sopenharmony_ci{ 2958c2ecf20Sopenharmony_ci int i; 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci /* free memory used by user font */ 2988c2ecf20Sopenharmony_ci for (i = 0; i < MAX_NR_CONSOLES; i++) 2998c2ecf20Sopenharmony_ci sticon_set_def_font(i, NULL); 3008c2ecf20Sopenharmony_ci} 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_cistatic void sticon_clear(struct vc_data *conp, int sy, int sx, int height, 3038c2ecf20Sopenharmony_ci int width) 3048c2ecf20Sopenharmony_ci{ 3058c2ecf20Sopenharmony_ci if (!height || !width) 3068c2ecf20Sopenharmony_ci return; 3078c2ecf20Sopenharmony_ci 3088c2ecf20Sopenharmony_ci sti_clear(sticon_sti, sy, sx, height, width, 3098c2ecf20Sopenharmony_ci conp->vc_video_erase_char, font_data[conp->vc_num]); 3108c2ecf20Sopenharmony_ci} 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_cistatic int sticon_switch(struct vc_data *conp) 3138c2ecf20Sopenharmony_ci{ 3148c2ecf20Sopenharmony_ci return 1; /* needs refreshing */ 3158c2ecf20Sopenharmony_ci} 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_cistatic int sticon_blank(struct vc_data *c, int blank, int mode_switch) 3188c2ecf20Sopenharmony_ci{ 3198c2ecf20Sopenharmony_ci if (blank == 0) { 3208c2ecf20Sopenharmony_ci if (mode_switch) 3218c2ecf20Sopenharmony_ci vga_is_gfx = 0; 3228c2ecf20Sopenharmony_ci return 1; 3238c2ecf20Sopenharmony_ci } 3248c2ecf20Sopenharmony_ci sti_clear(sticon_sti, 0, 0, c->vc_rows, c->vc_cols, BLANK, 3258c2ecf20Sopenharmony_ci font_data[c->vc_num]); 3268c2ecf20Sopenharmony_ci if (mode_switch) 3278c2ecf20Sopenharmony_ci vga_is_gfx = 1; 3288c2ecf20Sopenharmony_ci return 1; 3298c2ecf20Sopenharmony_ci} 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_cistatic u8 sticon_build_attr(struct vc_data *conp, u8 color, 3328c2ecf20Sopenharmony_ci enum vc_intensity intens, 3338c2ecf20Sopenharmony_ci bool blink, bool underline, bool reverse, 3348c2ecf20Sopenharmony_ci bool italic) 3358c2ecf20Sopenharmony_ci{ 3368c2ecf20Sopenharmony_ci u8 fg = color & 7; 3378c2ecf20Sopenharmony_ci u8 bg = (color & 0x70) >> 4; 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci if (reverse) 3408c2ecf20Sopenharmony_ci return (fg << 3) | bg; 3418c2ecf20Sopenharmony_ci else 3428c2ecf20Sopenharmony_ci return (bg << 3) | fg; 3438c2ecf20Sopenharmony_ci} 3448c2ecf20Sopenharmony_ci 3458c2ecf20Sopenharmony_cistatic void sticon_invert_region(struct vc_data *conp, u16 *p, int count) 3468c2ecf20Sopenharmony_ci{ 3478c2ecf20Sopenharmony_ci int col = 1; /* vga_can_do_color; */ 3488c2ecf20Sopenharmony_ci 3498c2ecf20Sopenharmony_ci while (count--) { 3508c2ecf20Sopenharmony_ci u16 a = scr_readw(p); 3518c2ecf20Sopenharmony_ci 3528c2ecf20Sopenharmony_ci if (col) 3538c2ecf20Sopenharmony_ci a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4); 3548c2ecf20Sopenharmony_ci else 3558c2ecf20Sopenharmony_ci a = ((a & 0x0700) == 0x0100) ? 0x7000 : 0x7700; 3568c2ecf20Sopenharmony_ci 3578c2ecf20Sopenharmony_ci scr_writew(a, p++); 3588c2ecf20Sopenharmony_ci } 3598c2ecf20Sopenharmony_ci} 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_cistatic const struct consw sti_con = { 3628c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 3638c2ecf20Sopenharmony_ci .con_startup = sticon_startup, 3648c2ecf20Sopenharmony_ci .con_init = sticon_init, 3658c2ecf20Sopenharmony_ci .con_deinit = sticon_deinit, 3668c2ecf20Sopenharmony_ci .con_clear = sticon_clear, 3678c2ecf20Sopenharmony_ci .con_putc = sticon_putc, 3688c2ecf20Sopenharmony_ci .con_putcs = sticon_putcs, 3698c2ecf20Sopenharmony_ci .con_cursor = sticon_cursor, 3708c2ecf20Sopenharmony_ci .con_scroll = sticon_scroll, 3718c2ecf20Sopenharmony_ci .con_switch = sticon_switch, 3728c2ecf20Sopenharmony_ci .con_blank = sticon_blank, 3738c2ecf20Sopenharmony_ci .con_font_set = sticon_font_set, 3748c2ecf20Sopenharmony_ci .con_font_default = sticon_font_default, 3758c2ecf20Sopenharmony_ci .con_build_attr = sticon_build_attr, 3768c2ecf20Sopenharmony_ci .con_invert_region = sticon_invert_region, 3778c2ecf20Sopenharmony_ci}; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_cistatic int __init sticonsole_init(void) 3828c2ecf20Sopenharmony_ci{ 3838c2ecf20Sopenharmony_ci int err, i; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci /* already initialized ? */ 3868c2ecf20Sopenharmony_ci if (sticon_sti) 3878c2ecf20Sopenharmony_ci return 0; 3888c2ecf20Sopenharmony_ci 3898c2ecf20Sopenharmony_ci sticon_sti = sti_get_rom(0); 3908c2ecf20Sopenharmony_ci if (!sticon_sti) 3918c2ecf20Sopenharmony_ci return -ENODEV; 3928c2ecf20Sopenharmony_ci 3938c2ecf20Sopenharmony_ci for (i = 0; i < MAX_NR_CONSOLES; i++) 3948c2ecf20Sopenharmony_ci font_data[i] = STI_DEF_FONT; 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci pr_info("sticon: Initializing STI text console on %s at [%s]\n", 3978c2ecf20Sopenharmony_ci sticon_sti->sti_data->inq_outptr.dev_name, 3988c2ecf20Sopenharmony_ci sticon_sti->pa_path); 3998c2ecf20Sopenharmony_ci console_lock(); 4008c2ecf20Sopenharmony_ci err = do_take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1, 4018c2ecf20Sopenharmony_ci PAGE0->mem_cons.cl_class != CL_DUPLEX); 4028c2ecf20Sopenharmony_ci console_unlock(); 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci return err; 4058c2ecf20Sopenharmony_ci} 4068c2ecf20Sopenharmony_ci 4078c2ecf20Sopenharmony_cimodule_init(sticonsole_init); 4088c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 409