2 * linux/drivers/video/console/sticon.c - console driver using HP's STI firmware
4 * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
5 * Copyright (C) 2002-2020 Helge Deller <deller@gmx.de>
7 * Based on linux/drivers/video/vgacon.c and linux/drivers/video/fbcon.c,
10 * Created 28 Sep 1997 by Geert Uytterhoeven
11 * Rewritten by Martin Mares <mj@ucw.cz>, July 1998
12 * Copyright (C) 1991, 1992 Linus Torvalds
14 * Copyright (C) 1995 Geert Uytterhoeven
15 * Copyright (C) 1993 Bjoern Brauel
17 * Copyright (C) 1993 Hamish Macdonald
19 * Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
21 * with work by William Rucklidge (wjr@cs.cornell.edu)
23 * Jes Sorensen (jds@kom.auc.dk)
25 * with work by Guenther Kelleter
28 * Emmanuel Marty (core@ggi-project.org)
29 * Jakub Jelinek (jj@ultra.linux.cz)
30 * Martin Mares <mj@ucw.cz>
32 * This file is subject to the terms and conditions of the GNU General Public
33 * License. See the file COPYING in the main directory of this archive for
38 #include <linux/init.h>
39 #include <linux/kernel.h>
40 #include <linux/console.h>
41 #include <linux/errno.h>
42 #include <linux/vt_kern.h>
44 #include <linux/selection.h>
45 #include <linux/module.h>
46 #include <linux/slab.h>
47 #include <linux/font.h>
48 #include <linux/crc32.h>
52 #include "../fbdev/sticore.h"
54 /* switching to graphics mode */
56 static int vga_is_gfx
;
58 #define STI_DEF_FONT sticon_sti->font
60 /* borrowed from fbcon.c */
61 #define FNTREFCOUNT(fd) (fd->refcount)
62 #define FNTCRC(fd) (fd->crc)
63 static struct sti_cooked_font
*font_data
[MAX_NR_CONSOLES
];
65 /* this is the sti_struct used for this console */
66 static struct sti_struct
*sticon_sti
;
68 static const char *sticon_startup(void)
73 static void sticon_putc(struct vc_data
*conp
, int c
, int ypos
, int xpos
)
75 if (vga_is_gfx
|| console_blanked
)
78 if (conp
->vc_mode
!= KD_TEXT
)
81 sti_putc(sticon_sti
, c
, ypos
, xpos
, font_data
[conp
->vc_num
]);
84 static void sticon_putcs(struct vc_data
*conp
, const unsigned short *s
,
85 int count
, int ypos
, int xpos
)
87 if (vga_is_gfx
|| console_blanked
)
90 if (conp
->vc_mode
!= KD_TEXT
)
94 sti_putc(sticon_sti
, scr_readw(s
++), ypos
, xpos
++,
95 font_data
[conp
->vc_num
]);
99 static void sticon_cursor(struct vc_data
*conp
, int mode
)
103 /* no cursor update if screen is blanked */
104 if (vga_is_gfx
|| console_blanked
)
107 car1
= conp
->vc_screenbuf
[conp
->state
.x
+ conp
->state
.y
* conp
->vc_cols
];
110 sti_putc(sticon_sti
, car1
, conp
->state
.y
, conp
->state
.x
,
111 font_data
[conp
->vc_num
]);
115 switch (CUR_SIZE(conp
->vc_cursor_type
)) {
117 case CUR_LOWER_THIRD
:
121 sti_putc(sticon_sti
, (car1
& 255) + (0 << 8) + (7 << 11),
122 conp
->state
.y
, conp
->state
.x
, font_data
[conp
->vc_num
]);
129 static bool sticon_scroll(struct vc_data
*conp
, unsigned int t
,
130 unsigned int b
, enum con_scroll dir
, unsigned int count
)
132 struct sti_struct
*sti
= sticon_sti
;
137 sticon_cursor(conp
, CM_ERASE
);
141 sti_bmove(sti
, t
+ count
, 0, t
, 0, b
- t
- count
, conp
->vc_cols
,
142 font_data
[conp
->vc_num
]);
143 sti_clear(sti
, b
- count
, 0, count
, conp
->vc_cols
,
144 conp
->vc_video_erase_char
, font_data
[conp
->vc_num
]);
148 sti_bmove(sti
, t
, 0, t
+ count
, 0, b
- t
- count
, conp
->vc_cols
,
149 font_data
[conp
->vc_num
]);
150 sti_clear(sti
, t
, 0, count
, conp
->vc_cols
,
151 conp
->vc_video_erase_char
, font_data
[conp
->vc_num
]);
158 static int sticon_set_def_font(int unit
, struct console_font
*op
)
160 if (font_data
[unit
] != STI_DEF_FONT
) {
161 if (--FNTREFCOUNT(font_data
[unit
]) == 0) {
162 kfree(font_data
[unit
]->raw_ptr
);
163 kfree(font_data
[unit
]);
165 font_data
[unit
] = STI_DEF_FONT
;
171 static int sticon_set_font(struct vc_data
*vc
, struct console_font
*op
)
173 struct sti_struct
*sti
= sticon_sti
;
174 int vc_cols
, vc_rows
, vc_old_cols
, vc_old_rows
;
175 int unit
= vc
->vc_num
;
178 int size
, i
, bpc
, pitch
;
179 struct sti_rom_font
*new_font
;
180 struct sti_cooked_font
*cooked_font
;
181 unsigned char *data
= op
->data
, *p
;
183 if ((w
< 6) || (h
< 6) || (w
> 32) || (h
> 32)
184 || (op
->charcount
!= 256 && op
->charcount
!= 512))
186 pitch
= ALIGN(w
, 8) / 8;
188 size
= bpc
* op
->charcount
;
190 new_font
= kmalloc(sizeof(*new_font
) + size
, STI_LOWMEM
);
194 new_font
->first_char
= 0;
195 new_font
->last_char
= op
->charcount
- 1;
197 new_font
->height
= h
;
198 new_font
->font_type
= STI_FONT_HPROMAN8
;
199 new_font
->bytes_per_char
= bpc
;
200 new_font
->underline_height
= 0;
201 new_font
->underline_pos
= 0;
203 cooked_font
= kzalloc(sizeof(*cooked_font
), GFP_KERNEL
);
208 cooked_font
->raw
= new_font
;
209 cooked_font
->raw_ptr
= new_font
;
210 cooked_font
->width
= w
;
211 cooked_font
->height
= h
;
212 FNTREFCOUNT(cooked_font
) = 0; /* usage counter */
214 p
= (unsigned char *) new_font
;
215 p
+= sizeof(*new_font
);
216 for (i
= 0; i
< op
->charcount
; i
++) {
217 memcpy(p
, data
, bpc
);
221 FNTCRC(cooked_font
) = crc32(0, new_font
, size
+ sizeof(*new_font
));
222 sti_font_convert_bytemode(sti
, cooked_font
);
223 new_font
= cooked_font
->raw_ptr
;
225 /* check if font is already used by other console */
226 for (i
= 0; i
< MAX_NR_CONSOLES
; i
++) {
227 if (font_data
[i
] != STI_DEF_FONT
228 && (FNTCRC(font_data
[i
]) == FNTCRC(cooked_font
))) {
231 /* current font is the same as the new one */
234 cooked_font
= font_data
[i
];
235 new_font
= cooked_font
->raw_ptr
;
240 /* clear screen with old font: we now may have less rows */
241 vc_old_rows
= vc
->vc_rows
;
242 vc_old_cols
= vc
->vc_cols
;
243 sti_clear(sticon_sti
, 0, 0, vc_old_rows
, vc_old_cols
,
244 vc
->vc_video_erase_char
, font_data
[vc
->vc_num
]);
246 /* delete old font in case it is a user font */
247 sticon_set_def_font(unit
, NULL
);
249 FNTREFCOUNT(cooked_font
)++;
250 font_data
[unit
] = cooked_font
;
252 vc_cols
= sti_onscreen_x(sti
) / cooked_font
->width
;
253 vc_rows
= sti_onscreen_y(sti
) / cooked_font
->height
;
254 vc_resize(vc
, vc_cols
, vc_rows
);
256 /* need to repaint screen if cols & rows are same as old font */
257 if (vc_cols
== vc_old_cols
&& vc_rows
== vc_old_rows
)
263 static int sticon_font_default(struct vc_data
*vc
, struct console_font
*op
, char *name
)
265 return sticon_set_def_font(vc
->vc_num
, op
);
268 static int sticon_font_set(struct vc_data
*vc
, struct console_font
*font
,
271 return sticon_set_font(vc
, font
);
274 static void sticon_init(struct vc_data
*c
, int init
)
276 struct sti_struct
*sti
= sticon_sti
;
277 int vc_cols
, vc_rows
;
279 sti_set(sti
, 0, 0, sti_onscreen_y(sti
), sti_onscreen_x(sti
), 0);
280 vc_cols
= sti_onscreen_x(sti
) / sti
->font
->width
;
281 vc_rows
= sti_onscreen_y(sti
) / sti
->font
->height
;
282 c
->vc_can_do_color
= 1;
285 c
->vc_cols
= vc_cols
;
286 c
->vc_rows
= vc_rows
;
288 vc_resize(c
, vc_cols
, vc_rows
);
292 static void sticon_deinit(struct vc_data
*c
)
296 /* free memory used by user font */
297 for (i
= 0; i
< MAX_NR_CONSOLES
; i
++)
298 sticon_set_def_font(i
, NULL
);
301 static void sticon_clear(struct vc_data
*conp
, int sy
, int sx
, int height
,
304 if (!height
|| !width
)
307 sti_clear(sticon_sti
, sy
, sx
, height
, width
,
308 conp
->vc_video_erase_char
, font_data
[conp
->vc_num
]);
311 static int sticon_switch(struct vc_data
*conp
)
313 return 1; /* needs refreshing */
316 static int sticon_blank(struct vc_data
*c
, int blank
, int mode_switch
)
323 sti_clear(sticon_sti
, 0, 0, c
->vc_rows
, c
->vc_cols
, BLANK
,
324 font_data
[c
->vc_num
]);
330 static u8
sticon_build_attr(struct vc_data
*conp
, u8 color
,
331 enum vc_intensity intens
,
332 bool blink
, bool underline
, bool reverse
,
335 u8 attr
= ((color
& 0x70) >> 1) | ((color
& 7));
338 color
= ((color
>> 3) & 0x7) | ((color
& 0x7) << 3);
344 static void sticon_invert_region(struct vc_data
*conp
, u16
*p
, int count
)
346 int col
= 1; /* vga_can_do_color; */
349 u16 a
= scr_readw(p
);
352 a
= ((a
) & 0x88ff) | (((a
) & 0x7000) >> 4) | (((a
) & 0x0700) << 4);
354 a
= ((a
& 0x0700) == 0x0100) ? 0x7000 : 0x7700;
360 static const struct consw sti_con
= {
361 .owner
= THIS_MODULE
,
362 .con_startup
= sticon_startup
,
363 .con_init
= sticon_init
,
364 .con_deinit
= sticon_deinit
,
365 .con_clear
= sticon_clear
,
366 .con_putc
= sticon_putc
,
367 .con_putcs
= sticon_putcs
,
368 .con_cursor
= sticon_cursor
,
369 .con_scroll
= sticon_scroll
,
370 .con_switch
= sticon_switch
,
371 .con_blank
= sticon_blank
,
372 .con_font_set
= sticon_font_set
,
373 .con_font_default
= sticon_font_default
,
374 .con_build_attr
= sticon_build_attr
,
375 .con_invert_region
= sticon_invert_region
,
380 static int __init
sticonsole_init(void)
384 /* already initialized ? */
388 sticon_sti
= sti_get_rom(0);
392 for (i
= 0; i
< MAX_NR_CONSOLES
; i
++)
393 font_data
[i
] = STI_DEF_FONT
;
395 pr_info("sticon: Initializing STI text console.\n");
397 err
= do_take_over_console(&sti_con
, 0, MAX_NR_CONSOLES
- 1,
398 PAGE0
->mem_cons
.cl_class
!= CL_DUPLEX
);
404 module_init(sticonsole_init
);
405 MODULE_LICENSE("GPL");