162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * linux/drivers/video/console/sticon.c - console driver using HP's STI firmware 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> 562306a36Sopenharmony_ci * Copyright (C) 2002-2020 Helge Deller <deller@gmx.de> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Based on linux/drivers/video/vgacon.c and linux/drivers/video/fbcon.c, 862306a36Sopenharmony_ci * which were 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Created 28 Sep 1997 by Geert Uytterhoeven 1162306a36Sopenharmony_ci * Rewritten by Martin Mares <mj@ucw.cz>, July 1998 1262306a36Sopenharmony_ci * Copyright (C) 1991, 1992 Linus Torvalds 1362306a36Sopenharmony_ci * 1995 Jay Estabrook 1462306a36Sopenharmony_ci * Copyright (C) 1995 Geert Uytterhoeven 1562306a36Sopenharmony_ci * Copyright (C) 1993 Bjoern Brauel 1662306a36Sopenharmony_ci * Roman Hodek 1762306a36Sopenharmony_ci * Copyright (C) 1993 Hamish Macdonald 1862306a36Sopenharmony_ci * Greg Harp 1962306a36Sopenharmony_ci * Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk] 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * with work by William Rucklidge (wjr@cs.cornell.edu) 2262306a36Sopenharmony_ci * Geert Uytterhoeven 2362306a36Sopenharmony_ci * Jes Sorensen (jds@kom.auc.dk) 2462306a36Sopenharmony_ci * Martin Apel 2562306a36Sopenharmony_ci * with work by Guenther Kelleter 2662306a36Sopenharmony_ci * Martin Schaller 2762306a36Sopenharmony_ci * Andreas Schwab 2862306a36Sopenharmony_ci * Emmanuel Marty (core@ggi-project.org) 2962306a36Sopenharmony_ci * Jakub Jelinek (jj@ultra.linux.cz) 3062306a36Sopenharmony_ci * Martin Mares <mj@ucw.cz> 3162306a36Sopenharmony_ci * 3262306a36Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 3362306a36Sopenharmony_ci * License. See the file COPYING in the main directory of this archive for 3462306a36Sopenharmony_ci * more details. 3562306a36Sopenharmony_ci * 3662306a36Sopenharmony_ci */ 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#include <linux/init.h> 3962306a36Sopenharmony_ci#include <linux/kernel.h> 4062306a36Sopenharmony_ci#include <linux/console.h> 4162306a36Sopenharmony_ci#include <linux/errno.h> 4262306a36Sopenharmony_ci#include <linux/vt_kern.h> 4362306a36Sopenharmony_ci#include <linux/kd.h> 4462306a36Sopenharmony_ci#include <linux/selection.h> 4562306a36Sopenharmony_ci#include <linux/module.h> 4662306a36Sopenharmony_ci#include <linux/slab.h> 4762306a36Sopenharmony_ci#include <linux/font.h> 4862306a36Sopenharmony_ci#include <linux/crc32.h> 4962306a36Sopenharmony_ci#include <linux/fb.h> 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci#include <asm/io.h> 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci#include <video/sticore.h> 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci/* switching to graphics mode */ 5662306a36Sopenharmony_ci#define BLANK 0 5762306a36Sopenharmony_cistatic int vga_is_gfx; 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ci#define STI_DEF_FONT sticon_sti->font 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci/* borrowed from fbcon.c */ 6262306a36Sopenharmony_ci#define FNTREFCOUNT(fd) (fd->refcount) 6362306a36Sopenharmony_ci#define FNTCRC(fd) (fd->crc) 6462306a36Sopenharmony_cistatic struct sti_cooked_font *font_data[MAX_NR_CONSOLES]; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci/* this is the sti_struct used for this console */ 6762306a36Sopenharmony_cistatic struct sti_struct *sticon_sti; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic const char *sticon_startup(void) 7062306a36Sopenharmony_ci{ 7162306a36Sopenharmony_ci return "STI console"; 7262306a36Sopenharmony_ci} 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_cistatic void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos) 7562306a36Sopenharmony_ci{ 7662306a36Sopenharmony_ci if (vga_is_gfx || console_blanked) 7762306a36Sopenharmony_ci return; 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci if (conp->vc_mode != KD_TEXT) 8062306a36Sopenharmony_ci return; 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci sti_putc(sticon_sti, c, ypos, xpos, font_data[conp->vc_num]); 8362306a36Sopenharmony_ci} 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_cistatic void sticon_putcs(struct vc_data *conp, const unsigned short *s, 8662306a36Sopenharmony_ci int count, int ypos, int xpos) 8762306a36Sopenharmony_ci{ 8862306a36Sopenharmony_ci if (vga_is_gfx || console_blanked) 8962306a36Sopenharmony_ci return; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci if (conp->vc_mode != KD_TEXT) 9262306a36Sopenharmony_ci return; 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci while (count--) { 9562306a36Sopenharmony_ci sti_putc(sticon_sti, scr_readw(s++), ypos, xpos++, 9662306a36Sopenharmony_ci font_data[conp->vc_num]); 9762306a36Sopenharmony_ci } 9862306a36Sopenharmony_ci} 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_cistatic void sticon_cursor(struct vc_data *conp, int mode) 10162306a36Sopenharmony_ci{ 10262306a36Sopenharmony_ci unsigned short car1; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_ci /* no cursor update if screen is blanked */ 10562306a36Sopenharmony_ci if (vga_is_gfx || console_blanked) 10662306a36Sopenharmony_ci return; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_ci car1 = conp->vc_screenbuf[conp->state.x + conp->state.y * conp->vc_cols]; 10962306a36Sopenharmony_ci switch (mode) { 11062306a36Sopenharmony_ci case CM_ERASE: 11162306a36Sopenharmony_ci sti_putc(sticon_sti, car1, conp->state.y, conp->state.x, 11262306a36Sopenharmony_ci font_data[conp->vc_num]); 11362306a36Sopenharmony_ci break; 11462306a36Sopenharmony_ci case CM_MOVE: 11562306a36Sopenharmony_ci case CM_DRAW: 11662306a36Sopenharmony_ci switch (CUR_SIZE(conp->vc_cursor_type)) { 11762306a36Sopenharmony_ci case CUR_UNDERLINE: 11862306a36Sopenharmony_ci case CUR_LOWER_THIRD: 11962306a36Sopenharmony_ci case CUR_LOWER_HALF: 12062306a36Sopenharmony_ci case CUR_TWO_THIRDS: 12162306a36Sopenharmony_ci case CUR_BLOCK: 12262306a36Sopenharmony_ci sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11), 12362306a36Sopenharmony_ci conp->state.y, conp->state.x, font_data[conp->vc_num]); 12462306a36Sopenharmony_ci break; 12562306a36Sopenharmony_ci } 12662306a36Sopenharmony_ci break; 12762306a36Sopenharmony_ci } 12862306a36Sopenharmony_ci} 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_cistatic bool sticon_scroll(struct vc_data *conp, unsigned int t, 13162306a36Sopenharmony_ci unsigned int b, enum con_scroll dir, unsigned int count) 13262306a36Sopenharmony_ci{ 13362306a36Sopenharmony_ci struct sti_struct *sti = sticon_sti; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_ci if (vga_is_gfx) 13662306a36Sopenharmony_ci return false; 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci sticon_cursor(conp, CM_ERASE); 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci switch (dir) { 14162306a36Sopenharmony_ci case SM_UP: 14262306a36Sopenharmony_ci sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols, 14362306a36Sopenharmony_ci font_data[conp->vc_num]); 14462306a36Sopenharmony_ci sti_clear(sti, b - count, 0, count, conp->vc_cols, 14562306a36Sopenharmony_ci conp->vc_video_erase_char, font_data[conp->vc_num]); 14662306a36Sopenharmony_ci break; 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci case SM_DOWN: 14962306a36Sopenharmony_ci sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols, 15062306a36Sopenharmony_ci font_data[conp->vc_num]); 15162306a36Sopenharmony_ci sti_clear(sti, t, 0, count, conp->vc_cols, 15262306a36Sopenharmony_ci conp->vc_video_erase_char, font_data[conp->vc_num]); 15362306a36Sopenharmony_ci break; 15462306a36Sopenharmony_ci } 15562306a36Sopenharmony_ci 15662306a36Sopenharmony_ci return false; 15762306a36Sopenharmony_ci} 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_cistatic void sticon_set_def_font(int unit) 16062306a36Sopenharmony_ci{ 16162306a36Sopenharmony_ci if (font_data[unit] != STI_DEF_FONT) { 16262306a36Sopenharmony_ci if (--FNTREFCOUNT(font_data[unit]) == 0) { 16362306a36Sopenharmony_ci kfree(font_data[unit]->raw_ptr); 16462306a36Sopenharmony_ci kfree(font_data[unit]); 16562306a36Sopenharmony_ci } 16662306a36Sopenharmony_ci font_data[unit] = STI_DEF_FONT; 16762306a36Sopenharmony_ci } 16862306a36Sopenharmony_ci} 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic int sticon_set_font(struct vc_data *vc, struct console_font *op, 17162306a36Sopenharmony_ci unsigned int vpitch) 17262306a36Sopenharmony_ci{ 17362306a36Sopenharmony_ci struct sti_struct *sti = sticon_sti; 17462306a36Sopenharmony_ci int vc_cols, vc_rows, vc_old_cols, vc_old_rows; 17562306a36Sopenharmony_ci int unit = vc->vc_num; 17662306a36Sopenharmony_ci int w = op->width; 17762306a36Sopenharmony_ci int h = op->height; 17862306a36Sopenharmony_ci int size, i, bpc, pitch; 17962306a36Sopenharmony_ci struct sti_rom_font *new_font; 18062306a36Sopenharmony_ci struct sti_cooked_font *cooked_font; 18162306a36Sopenharmony_ci unsigned char *data = op->data, *p; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci if ((w < 6) || (h < 6) || (w > 32) || (h > 32) || (vpitch != 32) 18462306a36Sopenharmony_ci || (op->charcount != 256 && op->charcount != 512)) 18562306a36Sopenharmony_ci return -EINVAL; 18662306a36Sopenharmony_ci pitch = ALIGN(w, 8) / 8; 18762306a36Sopenharmony_ci bpc = pitch * h; 18862306a36Sopenharmony_ci size = bpc * op->charcount; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci new_font = kmalloc(sizeof(*new_font) + size, STI_LOWMEM); 19162306a36Sopenharmony_ci if (!new_font) 19262306a36Sopenharmony_ci return -ENOMEM; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci new_font->first_char = 0; 19562306a36Sopenharmony_ci new_font->last_char = op->charcount - 1; 19662306a36Sopenharmony_ci new_font->width = w; 19762306a36Sopenharmony_ci new_font->height = h; 19862306a36Sopenharmony_ci new_font->font_type = STI_FONT_HPROMAN8; 19962306a36Sopenharmony_ci new_font->bytes_per_char = bpc; 20062306a36Sopenharmony_ci new_font->underline_height = 0; 20162306a36Sopenharmony_ci new_font->underline_pos = 0; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci cooked_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL); 20462306a36Sopenharmony_ci if (!cooked_font) { 20562306a36Sopenharmony_ci kfree(new_font); 20662306a36Sopenharmony_ci return -ENOMEM; 20762306a36Sopenharmony_ci } 20862306a36Sopenharmony_ci cooked_font->raw = new_font; 20962306a36Sopenharmony_ci cooked_font->raw_ptr = new_font; 21062306a36Sopenharmony_ci cooked_font->width = w; 21162306a36Sopenharmony_ci cooked_font->height = h; 21262306a36Sopenharmony_ci FNTREFCOUNT(cooked_font) = 0; /* usage counter */ 21362306a36Sopenharmony_ci 21462306a36Sopenharmony_ci p = (unsigned char *) new_font; 21562306a36Sopenharmony_ci p += sizeof(*new_font); 21662306a36Sopenharmony_ci for (i = 0; i < op->charcount; i++) { 21762306a36Sopenharmony_ci memcpy(p, data, bpc); 21862306a36Sopenharmony_ci data += pitch*32; 21962306a36Sopenharmony_ci p += bpc; 22062306a36Sopenharmony_ci } 22162306a36Sopenharmony_ci FNTCRC(cooked_font) = crc32(0, new_font, size + sizeof(*new_font)); 22262306a36Sopenharmony_ci sti_font_convert_bytemode(sti, cooked_font); 22362306a36Sopenharmony_ci new_font = cooked_font->raw_ptr; 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci /* check if font is already used by other console */ 22662306a36Sopenharmony_ci for (i = 0; i < MAX_NR_CONSOLES; i++) { 22762306a36Sopenharmony_ci if (font_data[i] != STI_DEF_FONT 22862306a36Sopenharmony_ci && (FNTCRC(font_data[i]) == FNTCRC(cooked_font))) { 22962306a36Sopenharmony_ci kfree(new_font); 23062306a36Sopenharmony_ci kfree(cooked_font); 23162306a36Sopenharmony_ci /* current font is the same as the new one */ 23262306a36Sopenharmony_ci if (i == unit) 23362306a36Sopenharmony_ci return 0; 23462306a36Sopenharmony_ci cooked_font = font_data[i]; 23562306a36Sopenharmony_ci new_font = cooked_font->raw_ptr; 23662306a36Sopenharmony_ci break; 23762306a36Sopenharmony_ci } 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci /* clear screen with old font: we now may have less rows */ 24162306a36Sopenharmony_ci vc_old_rows = vc->vc_rows; 24262306a36Sopenharmony_ci vc_old_cols = vc->vc_cols; 24362306a36Sopenharmony_ci sti_clear(sticon_sti, 0, 0, vc_old_rows, vc_old_cols, 24462306a36Sopenharmony_ci vc->vc_video_erase_char, font_data[vc->vc_num]); 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci /* delete old font in case it is a user font */ 24762306a36Sopenharmony_ci sticon_set_def_font(unit); 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci FNTREFCOUNT(cooked_font)++; 25062306a36Sopenharmony_ci font_data[unit] = cooked_font; 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci vc_cols = sti_onscreen_x(sti) / cooked_font->width; 25362306a36Sopenharmony_ci vc_rows = sti_onscreen_y(sti) / cooked_font->height; 25462306a36Sopenharmony_ci vc_resize(vc, vc_cols, vc_rows); 25562306a36Sopenharmony_ci 25662306a36Sopenharmony_ci /* need to repaint screen if cols & rows are same as old font */ 25762306a36Sopenharmony_ci if (vc_cols == vc_old_cols && vc_rows == vc_old_rows) 25862306a36Sopenharmony_ci update_screen(vc); 25962306a36Sopenharmony_ci 26062306a36Sopenharmony_ci return 0; 26162306a36Sopenharmony_ci} 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_cistatic int sticon_font_default(struct vc_data *vc, struct console_font *op, char *name) 26462306a36Sopenharmony_ci{ 26562306a36Sopenharmony_ci sticon_set_def_font(vc->vc_num); 26662306a36Sopenharmony_ci 26762306a36Sopenharmony_ci return 0; 26862306a36Sopenharmony_ci} 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistatic int sticon_font_set(struct vc_data *vc, struct console_font *font, 27162306a36Sopenharmony_ci unsigned int vpitch, unsigned int flags) 27262306a36Sopenharmony_ci{ 27362306a36Sopenharmony_ci return sticon_set_font(vc, font, vpitch); 27462306a36Sopenharmony_ci} 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_cistatic void sticon_init(struct vc_data *c, int init) 27762306a36Sopenharmony_ci{ 27862306a36Sopenharmony_ci struct sti_struct *sti = sticon_sti; 27962306a36Sopenharmony_ci int vc_cols, vc_rows; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci sti_set(sti, 0, 0, sti_onscreen_y(sti), sti_onscreen_x(sti), 0); 28262306a36Sopenharmony_ci vc_cols = sti_onscreen_x(sti) / sti->font->width; 28362306a36Sopenharmony_ci vc_rows = sti_onscreen_y(sti) / sti->font->height; 28462306a36Sopenharmony_ci c->vc_can_do_color = 1; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci if (init) { 28762306a36Sopenharmony_ci c->vc_cols = vc_cols; 28862306a36Sopenharmony_ci c->vc_rows = vc_rows; 28962306a36Sopenharmony_ci } else { 29062306a36Sopenharmony_ci vc_resize(c, vc_cols, vc_rows); 29162306a36Sopenharmony_ci } 29262306a36Sopenharmony_ci} 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_cistatic void sticon_deinit(struct vc_data *c) 29562306a36Sopenharmony_ci{ 29662306a36Sopenharmony_ci int i; 29762306a36Sopenharmony_ci 29862306a36Sopenharmony_ci /* free memory used by user font */ 29962306a36Sopenharmony_ci for (i = 0; i < MAX_NR_CONSOLES; i++) 30062306a36Sopenharmony_ci sticon_set_def_font(i); 30162306a36Sopenharmony_ci} 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_cistatic void sticon_clear(struct vc_data *conp, int sy, int sx, int height, 30462306a36Sopenharmony_ci int width) 30562306a36Sopenharmony_ci{ 30662306a36Sopenharmony_ci if (!height || !width) 30762306a36Sopenharmony_ci return; 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci sti_clear(sticon_sti, sy, sx, height, width, 31062306a36Sopenharmony_ci conp->vc_video_erase_char, font_data[conp->vc_num]); 31162306a36Sopenharmony_ci} 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_cistatic int sticon_switch(struct vc_data *conp) 31462306a36Sopenharmony_ci{ 31562306a36Sopenharmony_ci return 1; /* needs refreshing */ 31662306a36Sopenharmony_ci} 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_cistatic int sticon_blank(struct vc_data *c, int blank, int mode_switch) 31962306a36Sopenharmony_ci{ 32062306a36Sopenharmony_ci if (blank == 0) { 32162306a36Sopenharmony_ci if (mode_switch) 32262306a36Sopenharmony_ci vga_is_gfx = 0; 32362306a36Sopenharmony_ci return 1; 32462306a36Sopenharmony_ci } 32562306a36Sopenharmony_ci sti_clear(sticon_sti, 0, 0, c->vc_rows, c->vc_cols, BLANK, 32662306a36Sopenharmony_ci font_data[c->vc_num]); 32762306a36Sopenharmony_ci if (mode_switch) 32862306a36Sopenharmony_ci vga_is_gfx = 1; 32962306a36Sopenharmony_ci return 1; 33062306a36Sopenharmony_ci} 33162306a36Sopenharmony_ci 33262306a36Sopenharmony_cistatic u8 sticon_build_attr(struct vc_data *conp, u8 color, 33362306a36Sopenharmony_ci enum vc_intensity intens, 33462306a36Sopenharmony_ci bool blink, bool underline, bool reverse, 33562306a36Sopenharmony_ci bool italic) 33662306a36Sopenharmony_ci{ 33762306a36Sopenharmony_ci u8 fg = color & 7; 33862306a36Sopenharmony_ci u8 bg = (color & 0x70) >> 4; 33962306a36Sopenharmony_ci 34062306a36Sopenharmony_ci if (reverse) 34162306a36Sopenharmony_ci return (fg << 3) | bg; 34262306a36Sopenharmony_ci else 34362306a36Sopenharmony_ci return (bg << 3) | fg; 34462306a36Sopenharmony_ci} 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_cistatic void sticon_invert_region(struct vc_data *conp, u16 *p, int count) 34762306a36Sopenharmony_ci{ 34862306a36Sopenharmony_ci int col = 1; /* vga_can_do_color; */ 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci while (count--) { 35162306a36Sopenharmony_ci u16 a = scr_readw(p); 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci if (col) 35462306a36Sopenharmony_ci a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4); 35562306a36Sopenharmony_ci else 35662306a36Sopenharmony_ci a = ((a & 0x0700) == 0x0100) ? 0x7000 : 0x7700; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci scr_writew(a, p++); 35962306a36Sopenharmony_ci } 36062306a36Sopenharmony_ci} 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_cistatic const struct consw sti_con = { 36362306a36Sopenharmony_ci .owner = THIS_MODULE, 36462306a36Sopenharmony_ci .con_startup = sticon_startup, 36562306a36Sopenharmony_ci .con_init = sticon_init, 36662306a36Sopenharmony_ci .con_deinit = sticon_deinit, 36762306a36Sopenharmony_ci .con_clear = sticon_clear, 36862306a36Sopenharmony_ci .con_putc = sticon_putc, 36962306a36Sopenharmony_ci .con_putcs = sticon_putcs, 37062306a36Sopenharmony_ci .con_cursor = sticon_cursor, 37162306a36Sopenharmony_ci .con_scroll = sticon_scroll, 37262306a36Sopenharmony_ci .con_switch = sticon_switch, 37362306a36Sopenharmony_ci .con_blank = sticon_blank, 37462306a36Sopenharmony_ci .con_font_set = sticon_font_set, 37562306a36Sopenharmony_ci .con_font_default = sticon_font_default, 37662306a36Sopenharmony_ci .con_build_attr = sticon_build_attr, 37762306a36Sopenharmony_ci .con_invert_region = sticon_invert_region, 37862306a36Sopenharmony_ci}; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_cistatic int __init sticonsole_init(void) 38362306a36Sopenharmony_ci{ 38462306a36Sopenharmony_ci int err, i; 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_ci /* already initialized ? */ 38762306a36Sopenharmony_ci if (sticon_sti) 38862306a36Sopenharmony_ci return 0; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci sticon_sti = sti_get_rom(0); 39162306a36Sopenharmony_ci if (!sticon_sti) 39262306a36Sopenharmony_ci return -ENODEV; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci for (i = 0; i < MAX_NR_CONSOLES; i++) 39562306a36Sopenharmony_ci font_data[i] = STI_DEF_FONT; 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci pr_info("sticon: Initializing STI text console on %s at [%s]\n", 39862306a36Sopenharmony_ci sticon_sti->sti_data->inq_outptr.dev_name, 39962306a36Sopenharmony_ci sticon_sti->pa_path); 40062306a36Sopenharmony_ci console_lock(); 40162306a36Sopenharmony_ci err = do_take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1, 40262306a36Sopenharmony_ci PAGE0->mem_cons.cl_class != CL_DUPLEX); 40362306a36Sopenharmony_ci console_unlock(); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci return err; 40662306a36Sopenharmony_ci} 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_cimodule_init(sticonsole_init); 40962306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 410