parisc/sticon: Add user font support
This is a major rework of the sticon (parisc text console) driver in order to support user font support. Usually one want to use the stifb (parisc framebuffer driver) which is based on fbcon and does support fonts and colors, but some old machines (e.g. HP 730 workstations) don't provide a supported stifb graphic card, and for those user fonts are preferred. This patch drops unused code for software cursor and scrollback, enhances the debug output and adds better documentation. The code was tested on various machines with byte-mode and word-mode graphic cards on GSC- and PCI-busses. Signed-off-by: Helge Deller <deller@gmx.de>
This commit is contained in:
parent
58a5c67aad
commit
7ff3f14ddc
|
@ -119,6 +119,7 @@ config STI_CONSOLE
|
||||||
bool "STI text console"
|
bool "STI text console"
|
||||||
depends on PARISC && HAS_IOMEM
|
depends on PARISC && HAS_IOMEM
|
||||||
select FONT_SUPPORT
|
select FONT_SUPPORT
|
||||||
|
select CRC32
|
||||||
default y
|
default y
|
||||||
help
|
help
|
||||||
The STI console is the builtin display/keyboard on HP-PARISC
|
The STI console is the builtin display/keyboard on HP-PARISC
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* linux/drivers/video/console/sticon.c - console driver using HP's STI firmware
|
* linux/drivers/video/console/sticon.c - console driver using HP's STI firmware
|
||||||
*
|
*
|
||||||
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
|
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
|
||||||
* Copyright (C) 2002 Helge Deller <deller@gmx.de>
|
* Copyright (C) 2002-2020 Helge Deller <deller@gmx.de>
|
||||||
*
|
*
|
||||||
* Based on linux/drivers/video/vgacon.c and linux/drivers/video/fbcon.c,
|
* Based on linux/drivers/video/vgacon.c and linux/drivers/video/fbcon.c,
|
||||||
* which were
|
* which were
|
||||||
|
@ -43,6 +43,9 @@
|
||||||
#include <linux/kd.h>
|
#include <linux/kd.h>
|
||||||
#include <linux/selection.h>
|
#include <linux/selection.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/font.h>
|
||||||
|
#include <linux/crc32.h>
|
||||||
|
|
||||||
#include <asm/io.h>
|
#include <asm/io.h>
|
||||||
|
|
||||||
|
@ -52,28 +55,16 @@
|
||||||
#define BLANK 0
|
#define BLANK 0
|
||||||
static int vga_is_gfx;
|
static int vga_is_gfx;
|
||||||
|
|
||||||
|
#define STI_DEF_FONT sticon_sti->font
|
||||||
|
|
||||||
|
/* borrowed from fbcon.c */
|
||||||
|
#define FNTREFCOUNT(fd) (fd->refcount)
|
||||||
|
#define FNTCRC(fd) (fd->crc)
|
||||||
|
static struct sti_cooked_font *font_data[MAX_NR_CONSOLES];
|
||||||
|
|
||||||
/* this is the sti_struct used for this console */
|
/* this is the sti_struct used for this console */
|
||||||
static struct sti_struct *sticon_sti;
|
static struct sti_struct *sticon_sti;
|
||||||
|
|
||||||
/* Software scrollback */
|
|
||||||
static unsigned long softback_buf, softback_curr;
|
|
||||||
static unsigned long softback_in;
|
|
||||||
static unsigned long /* softback_top, */ softback_end;
|
|
||||||
static int softback_lines;
|
|
||||||
|
|
||||||
/* software cursor */
|
|
||||||
static int cursor_drawn;
|
|
||||||
#define CURSOR_DRAW_DELAY (1)
|
|
||||||
#define DEFAULT_CURSOR_BLINK_RATE (20)
|
|
||||||
|
|
||||||
static int vbl_cursor_cnt;
|
|
||||||
|
|
||||||
static inline void cursor_undrawn(void)
|
|
||||||
{
|
|
||||||
vbl_cursor_cnt = 0;
|
|
||||||
cursor_drawn = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static const char *sticon_startup(void)
|
static const char *sticon_startup(void)
|
||||||
{
|
{
|
||||||
return "STI console";
|
return "STI console";
|
||||||
|
@ -81,61 +72,43 @@ static const char *sticon_startup(void)
|
||||||
|
|
||||||
static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos)
|
static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos)
|
||||||
{
|
{
|
||||||
int redraw_cursor = 0;
|
|
||||||
|
|
||||||
if (vga_is_gfx || console_blanked)
|
if (vga_is_gfx || console_blanked)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (conp->vc_mode != KD_TEXT)
|
if (conp->vc_mode != KD_TEXT)
|
||||||
return;
|
return;
|
||||||
#if 0
|
|
||||||
if ((p->cursor_x == xpos) && (p->cursor_y == ypos)) {
|
|
||||||
cursor_undrawn();
|
|
||||||
redraw_cursor = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
sti_putc(sticon_sti, c, ypos, xpos);
|
sti_putc(sticon_sti, c, ypos, xpos, font_data[conp->vc_num]);
|
||||||
|
|
||||||
if (redraw_cursor)
|
|
||||||
vbl_cursor_cnt = CURSOR_DRAW_DELAY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sticon_putcs(struct vc_data *conp, const unsigned short *s,
|
static void sticon_putcs(struct vc_data *conp, const unsigned short *s,
|
||||||
int count, int ypos, int xpos)
|
int count, int ypos, int xpos)
|
||||||
{
|
{
|
||||||
int redraw_cursor = 0;
|
|
||||||
|
|
||||||
if (vga_is_gfx || console_blanked)
|
if (vga_is_gfx || console_blanked)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (conp->vc_mode != KD_TEXT)
|
if (conp->vc_mode != KD_TEXT)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if 0
|
|
||||||
if ((p->cursor_y == ypos) && (xpos <= p->cursor_x) &&
|
|
||||||
(p->cursor_x < (xpos + count))) {
|
|
||||||
cursor_undrawn();
|
|
||||||
redraw_cursor = 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
while (count--) {
|
while (count--) {
|
||||||
sti_putc(sticon_sti, scr_readw(s++), ypos, xpos++);
|
sti_putc(sticon_sti, scr_readw(s++), ypos, xpos++,
|
||||||
|
font_data[conp->vc_num]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (redraw_cursor)
|
|
||||||
vbl_cursor_cnt = CURSOR_DRAW_DELAY;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sticon_cursor(struct vc_data *conp, int mode)
|
static void sticon_cursor(struct vc_data *conp, int mode)
|
||||||
{
|
{
|
||||||
unsigned short car1;
|
unsigned short car1;
|
||||||
|
|
||||||
|
/* no cursor update if screen is blanked */
|
||||||
|
if (vga_is_gfx || console_blanked)
|
||||||
|
return;
|
||||||
|
|
||||||
car1 = conp->vc_screenbuf[conp->state.x + conp->state.y * conp->vc_cols];
|
car1 = conp->vc_screenbuf[conp->state.x + conp->state.y * conp->vc_cols];
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
case CM_ERASE:
|
case CM_ERASE:
|
||||||
sti_putc(sticon_sti, car1, conp->state.y, conp->state.x);
|
sti_putc(sticon_sti, car1, conp->state.y, conp->state.x,
|
||||||
|
font_data[conp->vc_num]);
|
||||||
break;
|
break;
|
||||||
case CM_MOVE:
|
case CM_MOVE:
|
||||||
case CM_DRAW:
|
case CM_DRAW:
|
||||||
|
@ -146,7 +119,7 @@ static void sticon_cursor(struct vc_data *conp, int mode)
|
||||||
case CUR_TWO_THIRDS:
|
case CUR_TWO_THIRDS:
|
||||||
case CUR_BLOCK:
|
case CUR_BLOCK:
|
||||||
sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11),
|
sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11),
|
||||||
conp->state.y, conp->state.x);
|
conp->state.y, conp->state.x, font_data[conp->vc_num]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -165,42 +138,164 @@ static bool sticon_scroll(struct vc_data *conp, unsigned int t,
|
||||||
|
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
case SM_UP:
|
case SM_UP:
|
||||||
sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols);
|
sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols,
|
||||||
sti_clear(sti, b - count, 0, count, conp->vc_cols, conp->vc_video_erase_char);
|
font_data[conp->vc_num]);
|
||||||
|
sti_clear(sti, b - count, 0, count, conp->vc_cols,
|
||||||
|
conp->vc_video_erase_char, font_data[conp->vc_num]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SM_DOWN:
|
case SM_DOWN:
|
||||||
sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols);
|
sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols,
|
||||||
sti_clear(sti, t, 0, count, conp->vc_cols, conp->vc_video_erase_char);
|
font_data[conp->vc_num]);
|
||||||
|
sti_clear(sti, t, 0, count, conp->vc_cols,
|
||||||
|
conp->vc_video_erase_char, font_data[conp->vc_num]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int sticon_set_def_font(int unit, struct console_font *op)
|
||||||
|
{
|
||||||
|
if (font_data[unit] != STI_DEF_FONT) {
|
||||||
|
if (--FNTREFCOUNT(font_data[unit]) == 0) {
|
||||||
|
kfree(font_data[unit]->raw_ptr);
|
||||||
|
kfree(font_data[unit]);
|
||||||
|
}
|
||||||
|
font_data[unit] = STI_DEF_FONT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sticon_set_font(struct vc_data *vc, struct console_font *op)
|
||||||
|
{
|
||||||
|
struct sti_struct *sti = sticon_sti;
|
||||||
|
int vc_cols, vc_rows, vc_old_cols, vc_old_rows;
|
||||||
|
int unit = vc->vc_num;
|
||||||
|
int w = op->width;
|
||||||
|
int h = op->height;
|
||||||
|
int size, i, bpc, pitch;
|
||||||
|
struct sti_rom_font *new_font;
|
||||||
|
struct sti_cooked_font *cooked_font;
|
||||||
|
unsigned char *data = op->data, *p;
|
||||||
|
|
||||||
|
if ((w < 6) || (h < 6) || (w > 32) || (h > 32)
|
||||||
|
|| (op->charcount != 256 && op->charcount != 512))
|
||||||
|
return -EINVAL;
|
||||||
|
pitch = ALIGN(w, 8) / 8;
|
||||||
|
bpc = pitch * h;
|
||||||
|
size = bpc * op->charcount;
|
||||||
|
|
||||||
|
new_font = kmalloc(sizeof(*new_font) + size, STI_LOWMEM);
|
||||||
|
if (!new_font)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
new_font->first_char = 0;
|
||||||
|
new_font->last_char = op->charcount - 1;
|
||||||
|
new_font->width = w;
|
||||||
|
new_font->height = h;
|
||||||
|
new_font->font_type = STI_FONT_HPROMAN8;
|
||||||
|
new_font->bytes_per_char = bpc;
|
||||||
|
new_font->underline_height = 0;
|
||||||
|
new_font->underline_pos = 0;
|
||||||
|
|
||||||
|
cooked_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL);
|
||||||
|
if (!cooked_font) {
|
||||||
|
kfree(new_font);
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
cooked_font->raw = new_font;
|
||||||
|
cooked_font->raw_ptr = new_font;
|
||||||
|
cooked_font->width = w;
|
||||||
|
cooked_font->height = h;
|
||||||
|
FNTREFCOUNT(cooked_font) = 0; /* usage counter */
|
||||||
|
|
||||||
|
p = (unsigned char *) new_font;
|
||||||
|
p += sizeof(*new_font);
|
||||||
|
for (i = 0; i < op->charcount; i++) {
|
||||||
|
memcpy(p, data, bpc);
|
||||||
|
data += pitch*32;
|
||||||
|
p += bpc;
|
||||||
|
}
|
||||||
|
FNTCRC(cooked_font) = crc32(0, new_font, size + sizeof(*new_font));
|
||||||
|
sti_font_convert_bytemode(sti, cooked_font);
|
||||||
|
new_font = cooked_font->raw_ptr;
|
||||||
|
|
||||||
|
/* check if font is already used by other console */
|
||||||
|
for (i = 0; i < MAX_NR_CONSOLES; i++) {
|
||||||
|
if (font_data[i] != STI_DEF_FONT
|
||||||
|
&& (FNTCRC(font_data[i]) == FNTCRC(cooked_font))) {
|
||||||
|
kfree(new_font);
|
||||||
|
kfree(cooked_font);
|
||||||
|
/* current font is the same as the new one */
|
||||||
|
if (i == unit)
|
||||||
|
return 0;
|
||||||
|
cooked_font = font_data[i];
|
||||||
|
new_font = cooked_font->raw_ptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clear screen with old font: we now may have less rows */
|
||||||
|
vc_old_rows = vc->vc_rows;
|
||||||
|
vc_old_cols = vc->vc_cols;
|
||||||
|
sti_clear(sticon_sti, 0, 0, vc_old_rows, vc_old_cols,
|
||||||
|
vc->vc_video_erase_char, font_data[vc->vc_num]);
|
||||||
|
|
||||||
|
/* delete old font in case it is a user font */
|
||||||
|
sticon_set_def_font(unit, NULL);
|
||||||
|
|
||||||
|
FNTREFCOUNT(cooked_font)++;
|
||||||
|
font_data[unit] = cooked_font;
|
||||||
|
|
||||||
|
vc_cols = sti_onscreen_x(sti) / cooked_font->width;
|
||||||
|
vc_rows = sti_onscreen_y(sti) / cooked_font->height;
|
||||||
|
vc_resize(vc, vc_cols, vc_rows);
|
||||||
|
|
||||||
|
/* need to repaint screen if cols & rows are same as old font */
|
||||||
|
if (vc_cols == vc_old_cols && vc_rows == vc_old_rows)
|
||||||
|
update_screen(vc);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sticon_font_default(struct vc_data *vc, struct console_font *op, char *name)
|
||||||
|
{
|
||||||
|
return sticon_set_def_font(vc->vc_num, op);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int sticon_font_set(struct vc_data *vc, struct console_font *font,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
return sticon_set_font(vc, font);
|
||||||
|
}
|
||||||
|
|
||||||
static void sticon_init(struct vc_data *c, int init)
|
static void sticon_init(struct vc_data *c, int init)
|
||||||
{
|
{
|
||||||
struct sti_struct *sti = sticon_sti;
|
struct sti_struct *sti = sticon_sti;
|
||||||
int vc_cols, vc_rows;
|
int vc_cols, vc_rows;
|
||||||
|
|
||||||
sti_set(sti, 0, 0, sti_onscreen_y(sti), sti_onscreen_x(sti), 0);
|
sti_set(sti, 0, 0, sti_onscreen_y(sti), sti_onscreen_x(sti), 0);
|
||||||
vc_cols = sti_onscreen_x(sti) / sti->font_width;
|
vc_cols = sti_onscreen_x(sti) / sti->font->width;
|
||||||
vc_rows = sti_onscreen_y(sti) / sti->font_height;
|
vc_rows = sti_onscreen_y(sti) / sti->font->height;
|
||||||
c->vc_can_do_color = 1;
|
c->vc_can_do_color = 1;
|
||||||
|
|
||||||
if (init) {
|
if (init) {
|
||||||
c->vc_cols = vc_cols;
|
c->vc_cols = vc_cols;
|
||||||
c->vc_rows = vc_rows;
|
c->vc_rows = vc_rows;
|
||||||
} else {
|
} else {
|
||||||
/* vc_rows = (c->vc_rows > vc_rows) ? vc_rows : c->vc_rows; */
|
|
||||||
/* vc_cols = (c->vc_cols > vc_cols) ? vc_cols : c->vc_cols; */
|
|
||||||
vc_resize(c, vc_cols, vc_rows);
|
vc_resize(c, vc_cols, vc_rows);
|
||||||
/* vc_resize_con(vc_rows, vc_cols, c->vc_num); */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sticon_deinit(struct vc_data *c)
|
static void sticon_deinit(struct vc_data *c)
|
||||||
{
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* free memory used by user font */
|
||||||
|
for (i = 0; i < MAX_NR_CONSOLES; i++)
|
||||||
|
sticon_set_def_font(i, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sticon_clear(struct vc_data *conp, int sy, int sx, int height,
|
static void sticon_clear(struct vc_data *conp, int sy, int sx, int height,
|
||||||
|
@ -209,7 +304,8 @@ static void sticon_clear(struct vc_data *conp, int sy, int sx, int height,
|
||||||
if (!height || !width)
|
if (!height || !width)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sti_clear(sticon_sti, sy, sx, height, width, conp->vc_video_erase_char);
|
sti_clear(sticon_sti, sy, sx, height, width,
|
||||||
|
conp->vc_video_erase_char, font_data[conp->vc_num]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sticon_switch(struct vc_data *conp)
|
static int sticon_switch(struct vc_data *conp)
|
||||||
|
@ -224,64 +320,13 @@ static int sticon_blank(struct vc_data *c, int blank, int mode_switch)
|
||||||
vga_is_gfx = 0;
|
vga_is_gfx = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
sti_clear(sticon_sti, 0,0, c->vc_rows, c->vc_cols, BLANK);
|
sti_clear(sticon_sti, 0, 0, c->vc_rows, c->vc_cols, BLANK,
|
||||||
|
font_data[c->vc_num]);
|
||||||
if (mode_switch)
|
if (mode_switch)
|
||||||
vga_is_gfx = 1;
|
vga_is_gfx = 1;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static u16 *sticon_screen_pos(const struct vc_data *conp, int offset)
|
|
||||||
{
|
|
||||||
int line;
|
|
||||||
unsigned long p;
|
|
||||||
|
|
||||||
if (conp->vc_num != fg_console || !softback_lines)
|
|
||||||
return (u16 *)(conp->vc_origin + offset);
|
|
||||||
line = offset / conp->vc_size_row;
|
|
||||||
if (line >= softback_lines)
|
|
||||||
return (u16 *)(conp->vc_origin + offset - softback_lines * conp->vc_size_row);
|
|
||||||
p = softback_curr + offset;
|
|
||||||
if (p >= softback_end)
|
|
||||||
p += softback_buf - softback_end;
|
|
||||||
return (u16 *)p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static unsigned long sticon_getxy(struct vc_data *conp, unsigned long pos,
|
|
||||||
int *px, int *py)
|
|
||||||
{
|
|
||||||
int x, y;
|
|
||||||
unsigned long ret;
|
|
||||||
if (pos >= conp->vc_origin && pos < conp->vc_scr_end) {
|
|
||||||
unsigned long offset = (pos - conp->vc_origin) / 2;
|
|
||||||
|
|
||||||
x = offset % conp->vc_cols;
|
|
||||||
y = offset / conp->vc_cols;
|
|
||||||
if (conp->vc_num == fg_console)
|
|
||||||
y += softback_lines;
|
|
||||||
ret = pos + (conp->vc_cols - x) * 2;
|
|
||||||
} else if (conp->vc_num == fg_console && softback_lines) {
|
|
||||||
unsigned long offset = pos - softback_curr;
|
|
||||||
|
|
||||||
if (pos < softback_curr)
|
|
||||||
offset += softback_end - softback_buf;
|
|
||||||
offset /= 2;
|
|
||||||
x = offset % conp->vc_cols;
|
|
||||||
y = offset / conp->vc_cols;
|
|
||||||
ret = pos + (conp->vc_cols - x) * 2;
|
|
||||||
if (ret == softback_end)
|
|
||||||
ret = softback_buf;
|
|
||||||
if (ret == softback_in)
|
|
||||||
ret = conp->vc_origin;
|
|
||||||
} else {
|
|
||||||
/* Should not happen */
|
|
||||||
x = y = 0;
|
|
||||||
ret = conp->vc_origin;
|
|
||||||
}
|
|
||||||
if (px) *px = x;
|
|
||||||
if (py) *py = y;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static u8 sticon_build_attr(struct vc_data *conp, u8 color,
|
static u8 sticon_build_attr(struct vc_data *conp, u8 color,
|
||||||
enum vc_intensity intens,
|
enum vc_intensity intens,
|
||||||
bool blink, bool underline, bool reverse,
|
bool blink, bool underline, bool reverse,
|
||||||
|
@ -312,10 +357,6 @@ static void sticon_invert_region(struct vc_data *conp, u16 *p, int count)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sticon_save_screen(struct vc_data *conp)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
static const struct consw sti_con = {
|
static const struct consw sti_con = {
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.con_startup = sticon_startup,
|
.con_startup = sticon_startup,
|
||||||
|
@ -328,18 +369,18 @@ static const struct consw sti_con = {
|
||||||
.con_scroll = sticon_scroll,
|
.con_scroll = sticon_scroll,
|
||||||
.con_switch = sticon_switch,
|
.con_switch = sticon_switch,
|
||||||
.con_blank = sticon_blank,
|
.con_blank = sticon_blank,
|
||||||
.con_save_screen = sticon_save_screen,
|
.con_font_set = sticon_font_set,
|
||||||
|
.con_font_default = sticon_font_default,
|
||||||
.con_build_attr = sticon_build_attr,
|
.con_build_attr = sticon_build_attr,
|
||||||
.con_invert_region = sticon_invert_region,
|
.con_invert_region = sticon_invert_region,
|
||||||
.con_screen_pos = sticon_screen_pos,
|
|
||||||
.con_getxy = sticon_getxy,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static int __init sticonsole_init(void)
|
static int __init sticonsole_init(void)
|
||||||
{
|
{
|
||||||
int err;
|
int err, i;
|
||||||
|
|
||||||
/* already initialized ? */
|
/* already initialized ? */
|
||||||
if (sticon_sti)
|
if (sticon_sti)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -348,6 +389,9 @@ static int __init sticonsole_init(void)
|
||||||
if (!sticon_sti)
|
if (!sticon_sti)
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_NR_CONSOLES; i++)
|
||||||
|
font_data[i] = STI_DEF_FONT;
|
||||||
|
|
||||||
pr_info("sticon: Initializing STI text console.\n");
|
pr_info("sticon: Initializing STI text console.\n");
|
||||||
console_lock();
|
console_lock();
|
||||||
err = do_take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1,
|
err = do_take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1,
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
* core code for console driver using HP's STI firmware
|
* core code for console driver using HP's STI firmware
|
||||||
*
|
*
|
||||||
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
|
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
|
||||||
* Copyright (C) 2001-2013 Helge Deller <deller@gmx.de>
|
* Copyright (C) 2001-2020 Helge Deller <deller@gmx.de>
|
||||||
* Copyright (C) 2001-2002 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
|
* Copyright (C) 2001-2002 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
|
||||||
*
|
*
|
||||||
* TODO:
|
* TODO:
|
||||||
|
@ -14,6 +14,8 @@
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#define pr_fmt(fmt) "%s: " fmt, KBUILD_MODNAME
|
||||||
|
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
|
@ -133,16 +135,17 @@ static const struct sti_font_flags default_font_flags = {
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
sti_putc(struct sti_struct *sti, int c, int y, int x)
|
sti_putc(struct sti_struct *sti, int c, int y, int x,
|
||||||
|
struct sti_cooked_font *font)
|
||||||
{
|
{
|
||||||
struct sti_font_inptr *inptr = &sti->sti_data->font_inptr;
|
struct sti_font_inptr *inptr = &sti->sti_data->font_inptr;
|
||||||
struct sti_font_inptr inptr_default = {
|
struct sti_font_inptr inptr_default = {
|
||||||
.font_start_addr= STI_PTR(sti->font->raw),
|
.font_start_addr = STI_PTR(font->raw),
|
||||||
.index = c_index(sti, c),
|
.index = c_index(sti, c),
|
||||||
.fg_color = c_fg(sti, c),
|
.fg_color = c_fg(sti, c),
|
||||||
.bg_color = c_bg(sti, c),
|
.bg_color = c_bg(sti, c),
|
||||||
.dest_x = x * sti->font_width,
|
.dest_x = x * font->width,
|
||||||
.dest_y = y * sti->font_height,
|
.dest_y = y * font->height,
|
||||||
};
|
};
|
||||||
struct sti_font_outptr *outptr = &sti->sti_data->font_outptr;
|
struct sti_font_outptr *outptr = &sti->sti_data->font_outptr;
|
||||||
s32 ret;
|
s32 ret;
|
||||||
|
@ -193,18 +196,18 @@ sti_set(struct sti_struct *sti, int src_y, int src_x,
|
||||||
|
|
||||||
void
|
void
|
||||||
sti_clear(struct sti_struct *sti, int src_y, int src_x,
|
sti_clear(struct sti_struct *sti, int src_y, int src_x,
|
||||||
int height, int width, int c)
|
int height, int width, int c, struct sti_cooked_font *font)
|
||||||
{
|
{
|
||||||
struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr;
|
struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr;
|
||||||
struct sti_blkmv_inptr inptr_default = {
|
struct sti_blkmv_inptr inptr_default = {
|
||||||
.fg_color = c_fg(sti, c),
|
.fg_color = c_fg(sti, c),
|
||||||
.bg_color = c_bg(sti, c),
|
.bg_color = c_bg(sti, c),
|
||||||
.src_x = src_x * sti->font_width,
|
.src_x = src_x * font->width,
|
||||||
.src_y = src_y * sti->font_height,
|
.src_y = src_y * font->height,
|
||||||
.dest_x = src_x * sti->font_width,
|
.dest_x = src_x * font->width,
|
||||||
.dest_y = src_y * sti->font_height,
|
.dest_y = src_y * font->height,
|
||||||
.width = width * sti->font_width,
|
.width = width * font->width,
|
||||||
.height = height* sti->font_height,
|
.height = height * font->height,
|
||||||
};
|
};
|
||||||
struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr;
|
struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr;
|
||||||
s32 ret;
|
s32 ret;
|
||||||
|
@ -225,16 +228,17 @@ static const struct sti_blkmv_flags default_blkmv_flags = {
|
||||||
|
|
||||||
void
|
void
|
||||||
sti_bmove(struct sti_struct *sti, int src_y, int src_x,
|
sti_bmove(struct sti_struct *sti, int src_y, int src_x,
|
||||||
int dst_y, int dst_x, int height, int width)
|
int dst_y, int dst_x, int height, int width,
|
||||||
|
struct sti_cooked_font *font)
|
||||||
{
|
{
|
||||||
struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr;
|
struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr;
|
||||||
struct sti_blkmv_inptr inptr_default = {
|
struct sti_blkmv_inptr inptr_default = {
|
||||||
.src_x = src_x * sti->font_width,
|
.src_x = src_x * font->width,
|
||||||
.src_y = src_y * sti->font_height,
|
.src_y = src_y * font->height,
|
||||||
.dest_x = dst_x * sti->font_width,
|
.dest_x = dst_x * font->width,
|
||||||
.dest_y = dst_y * sti->font_height,
|
.dest_y = dst_y * font->height,
|
||||||
.width = width * sti->font_width,
|
.width = width * font->width,
|
||||||
.height = height* sti->font_height,
|
.height = height * font->height,
|
||||||
};
|
};
|
||||||
struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr;
|
struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr;
|
||||||
s32 ret;
|
s32 ret;
|
||||||
|
@ -301,36 +305,32 @@ __setup("sti=", sti_setup);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static char *font_name[MAX_STI_ROMS];
|
static char *font_name;
|
||||||
static int font_index[MAX_STI_ROMS],
|
static int font_index,
|
||||||
font_height[MAX_STI_ROMS],
|
font_height,
|
||||||
font_width[MAX_STI_ROMS];
|
font_width;
|
||||||
#ifndef MODULE
|
#ifndef MODULE
|
||||||
static int sti_font_setup(char *str)
|
static int sti_font_setup(char *str)
|
||||||
{
|
{
|
||||||
char *x;
|
/*
|
||||||
int i = 0;
|
* The default font can be selected in various ways.
|
||||||
|
* a) sti_font=VGA8x16, sti_font=10x20, sti_font=10*20 selects
|
||||||
|
* an built-in Linux framebuffer font.
|
||||||
|
* b) sti_font=<index>, where index is (1..x) with 1 selecting
|
||||||
|
* the first HP STI ROM built-in font..
|
||||||
|
*/
|
||||||
|
|
||||||
/* we accept sti_font=VGA8x16, sti_font=10x20, sti_font=10*20
|
if (*str >= '0' && *str <= '9') {
|
||||||
* or sti_font=7 style command lines. */
|
char *x;
|
||||||
|
|
||||||
while (i<MAX_STI_ROMS && str && *str) {
|
if ((x = strchr(str, 'x')) || (x = strchr(str, '*'))) {
|
||||||
if (*str>='0' && *str<='9') {
|
font_height = simple_strtoul(str, NULL, 0);
|
||||||
if ((x = strchr(str, 'x')) || (x = strchr(str, '*'))) {
|
font_width = simple_strtoul(x+1, NULL, 0);
|
||||||
font_height[i] = simple_strtoul(str, NULL, 0);
|
|
||||||
font_width[i] = simple_strtoul(x+1, NULL, 0);
|
|
||||||
} else {
|
|
||||||
font_index[i] = simple_strtoul(str, NULL, 0);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
font_name[i] = str; /* fb font name */
|
font_index = simple_strtoul(str, NULL, 0);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
if ((x = strchr(str, ',')))
|
font_name = str; /* fb font name */
|
||||||
*x++ = 0;
|
|
||||||
str = x;
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -344,7 +344,7 @@ static int sti_font_setup(char *str)
|
||||||
* framebuffer font names (e.g. VGA8x16, SUN22x18).
|
* framebuffer font names (e.g. VGA8x16, SUN22x18).
|
||||||
* This is only available if the fonts have been statically compiled
|
* This is only available if the fonts have been statically compiled
|
||||||
* in with e.g. the CONFIG_FONT_8x16 or CONFIG_FONT_SUN12x22 options.
|
* in with e.g. the CONFIG_FONT_8x16 or CONFIG_FONT_SUN12x22 options.
|
||||||
* - sti_font=<number>
|
* - sti_font=<number> (<number> = 1,2,3,...)
|
||||||
* most STI ROMs have built-in HP specific fonts, which can be selected
|
* most STI ROMs have built-in HP specific fonts, which can be selected
|
||||||
* by giving the desired number to the sticon driver.
|
* by giving the desired number to the sticon driver.
|
||||||
* NOTE: This number is machine and STI ROM dependend.
|
* NOTE: This number is machine and STI ROM dependend.
|
||||||
|
@ -364,8 +364,7 @@ static void sti_dump_globcfg(struct sti_glob_cfg *glob_cfg,
|
||||||
{
|
{
|
||||||
struct sti_glob_cfg_ext *cfg;
|
struct sti_glob_cfg_ext *cfg;
|
||||||
|
|
||||||
DPRINTK((KERN_INFO
|
pr_debug("%d text planes\n"
|
||||||
"%d text planes\n"
|
|
||||||
"%4d x %4d screen resolution\n"
|
"%4d x %4d screen resolution\n"
|
||||||
"%4d x %4d offscreen\n"
|
"%4d x %4d offscreen\n"
|
||||||
"%4d x %4d layout\n"
|
"%4d x %4d layout\n"
|
||||||
|
@ -382,12 +381,11 @@ static void sti_dump_globcfg(struct sti_glob_cfg *glob_cfg,
|
||||||
glob_cfg->region_ptrs[4], glob_cfg->region_ptrs[5],
|
glob_cfg->region_ptrs[4], glob_cfg->region_ptrs[5],
|
||||||
glob_cfg->region_ptrs[6], glob_cfg->region_ptrs[7],
|
glob_cfg->region_ptrs[6], glob_cfg->region_ptrs[7],
|
||||||
glob_cfg->reent_lvl,
|
glob_cfg->reent_lvl,
|
||||||
glob_cfg->save_addr));
|
glob_cfg->save_addr);
|
||||||
|
|
||||||
/* dump extended cfg */
|
/* dump extended cfg */
|
||||||
cfg = PTR_STI((unsigned long)glob_cfg->ext_ptr);
|
cfg = PTR_STI((unsigned long)glob_cfg->ext_ptr);
|
||||||
DPRINTK(( KERN_INFO
|
pr_debug("monitor %d\n"
|
||||||
"monitor %d\n"
|
|
||||||
"in friendly mode: %d\n"
|
"in friendly mode: %d\n"
|
||||||
"power consumption %d watts\n"
|
"power consumption %d watts\n"
|
||||||
"freq ref %d\n"
|
"freq ref %d\n"
|
||||||
|
@ -396,20 +394,19 @@ static void sti_dump_globcfg(struct sti_glob_cfg *glob_cfg,
|
||||||
cfg->friendly_boot,
|
cfg->friendly_boot,
|
||||||
cfg->power,
|
cfg->power,
|
||||||
cfg->freq_ref,
|
cfg->freq_ref,
|
||||||
cfg->sti_mem_addr, sti_mem_request));
|
cfg->sti_mem_addr, sti_mem_request);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sti_dump_outptr(struct sti_struct *sti)
|
static void sti_dump_outptr(struct sti_struct *sti)
|
||||||
{
|
{
|
||||||
DPRINTK((KERN_INFO
|
pr_debug("%d bits per pixel\n"
|
||||||
"%d bits per pixel\n"
|
|
||||||
"%d used bits\n"
|
"%d used bits\n"
|
||||||
"%d planes\n"
|
"%d planes\n"
|
||||||
"attributes %08x\n",
|
"attributes %08x\n",
|
||||||
sti->sti_data->inq_outptr.bits_per_pixel,
|
sti->sti_data->inq_outptr.bits_per_pixel,
|
||||||
sti->sti_data->inq_outptr.bits_used,
|
sti->sti_data->inq_outptr.bits_used,
|
||||||
sti->sti_data->inq_outptr.planes,
|
sti->sti_data->inq_outptr.planes,
|
||||||
sti->sti_data->inq_outptr.attributes));
|
sti->sti_data->inq_outptr.attributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address,
|
static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address,
|
||||||
|
@ -448,8 +445,7 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address,
|
||||||
if (offs != PCI_ROM_ADDRESS &&
|
if (offs != PCI_ROM_ADDRESS &&
|
||||||
(offs < PCI_BASE_ADDRESS_0 ||
|
(offs < PCI_BASE_ADDRESS_0 ||
|
||||||
offs > PCI_BASE_ADDRESS_5)) {
|
offs > PCI_BASE_ADDRESS_5)) {
|
||||||
printk (KERN_WARNING
|
pr_warn("STI pci region mapping for region %d (%02x) can't be mapped\n",
|
||||||
"STI pci region mapping for region %d (%02x) can't be mapped\n",
|
|
||||||
i,sti->rm_entry[i]);
|
i,sti->rm_entry[i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -464,14 +460,14 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address,
|
||||||
if (len)
|
if (len)
|
||||||
glob_cfg->region_ptrs[i] = sti->regions_phys[i];
|
glob_cfg->region_ptrs[i] = sti->regions_phys[i];
|
||||||
|
|
||||||
DPRINTK(("region #%d: phys %08lx, region_ptr %08x, len=%lukB, "
|
pr_debug("region #%d: phys %08lx, region_ptr %08x, len=%lukB, "
|
||||||
"btlb=%d, sysonly=%d, cache=%d, last=%d\n",
|
"btlb=%d, sysonly=%d, cache=%d, last=%d\n",
|
||||||
i, sti->regions_phys[i], glob_cfg->region_ptrs[i],
|
i, sti->regions_phys[i], glob_cfg->region_ptrs[i],
|
||||||
len/1024,
|
len/1024,
|
||||||
sti->regions[i].region_desc.btlb,
|
sti->regions[i].region_desc.btlb,
|
||||||
sti->regions[i].region_desc.sys_only,
|
sti->regions[i].region_desc.sys_only,
|
||||||
sti->regions[i].region_desc.cache,
|
sti->regions[i].region_desc.cache,
|
||||||
sti->regions[i].region_desc.last));
|
sti->regions[i].region_desc.last);
|
||||||
|
|
||||||
/* last entry reached ? */
|
/* last entry reached ? */
|
||||||
if (sti->regions[i].region_desc.last)
|
if (sti->regions[i].region_desc.last)
|
||||||
|
@ -479,8 +475,8 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (++i<8 && sti->regions[i].region)
|
if (++i<8 && sti->regions[i].region)
|
||||||
printk(KERN_WARNING "%s: *future ptr (0x%8x) not yet supported !\n",
|
pr_warn("future ptr (0x%8x) not yet supported !\n",
|
||||||
__FILE__, sti->regions[i].region);
|
sti->regions[i].region);
|
||||||
|
|
||||||
glob_cfg_ext->sti_mem_addr = STI_PTR(sti_mem_addr);
|
glob_cfg_ext->sti_mem_addr = STI_PTR(sti_mem_addr);
|
||||||
|
|
||||||
|
@ -538,6 +534,7 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
cooked_font->raw = nf;
|
cooked_font->raw = nf;
|
||||||
|
cooked_font->raw_ptr = nf;
|
||||||
cooked_font->next_font = NULL;
|
cooked_font->next_font = NULL;
|
||||||
|
|
||||||
cooked_rom->font_start = cooked_font;
|
cooked_rom->font_start = cooked_font;
|
||||||
|
@ -552,24 +549,38 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct sti_cooked_font *sti_select_font(struct sti_cooked_rom *rom,
|
static int sti_search_font(struct sti_cooked_rom *rom, int height, int width)
|
||||||
int (*search_font_fnc)(struct sti_cooked_rom *, int, int))
|
{
|
||||||
|
struct sti_cooked_font *font;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
|
for (font = rom->font_start; font; font = font->next_font, i++) {
|
||||||
|
if ((font->raw->width == width) &&
|
||||||
|
(font->raw->height == height))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct sti_cooked_font *sti_select_font(struct sti_cooked_rom *rom)
|
||||||
{
|
{
|
||||||
struct sti_cooked_font *font;
|
struct sti_cooked_font *font;
|
||||||
int i;
|
int i;
|
||||||
int index = num_sti_roms;
|
|
||||||
|
|
||||||
/* check for framebuffer-font first */
|
/* check for framebuffer-font first */
|
||||||
if ((font = sti_select_fbfont(rom, font_name[index])))
|
if (!font_index) {
|
||||||
return font;
|
font = sti_select_fbfont(rom, font_name);
|
||||||
|
if (font)
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
if (font_width[index] && font_height[index])
|
if (font_width && font_height)
|
||||||
font_index[index] = search_font_fnc(rom,
|
font_index = sti_search_font(rom,
|
||||||
font_height[index], font_width[index]);
|
font_height, font_width);
|
||||||
|
|
||||||
for (font = rom->font_start, i = font_index[index];
|
for (font = rom->font_start, i = font_index - 1;
|
||||||
font && (i > 0);
|
font && (i > 0);
|
||||||
font = font->next_font, i--);
|
font = font->next_font, i--);
|
||||||
|
|
||||||
if (font)
|
if (font)
|
||||||
return font;
|
return font;
|
||||||
|
@ -578,20 +589,35 @@ static struct sti_cooked_font *sti_select_font(struct sti_cooked_rom *rom,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void sti_dump_rom(struct sti_rom *rom)
|
static void sti_dump_rom(struct sti_struct *sti)
|
||||||
{
|
{
|
||||||
printk(KERN_INFO " id %04x-%04x, conforms to spec rev. %d.%02x\n",
|
struct sti_rom *rom = sti->rom->raw;
|
||||||
|
struct sti_cooked_font *font_start;
|
||||||
|
int nr;
|
||||||
|
|
||||||
|
pr_info(" id %04x-%04x, conforms to spec rev. %d.%02x\n",
|
||||||
rom->graphics_id[0],
|
rom->graphics_id[0],
|
||||||
rom->graphics_id[1],
|
rom->graphics_id[1],
|
||||||
rom->revno[0] >> 4,
|
rom->revno[0] >> 4,
|
||||||
rom->revno[0] & 0x0f);
|
rom->revno[0] & 0x0f);
|
||||||
DPRINTK((" supports %d monitors\n", rom->num_mons));
|
pr_debug(" supports %d monitors\n", rom->num_mons);
|
||||||
DPRINTK((" font start %08x\n", rom->font_start));
|
pr_debug(" font start %08x\n", rom->font_start);
|
||||||
DPRINTK((" region list %08x\n", rom->region_list));
|
pr_debug(" region list %08x\n", rom->region_list);
|
||||||
DPRINTK((" init_graph %08x\n", rom->init_graph));
|
pr_debug(" init_graph %08x\n", rom->init_graph);
|
||||||
DPRINTK((" bus support %02x\n", rom->bus_support));
|
pr_debug(" bus support %02x\n", rom->bus_support);
|
||||||
DPRINTK((" ext bus support %02x\n", rom->ext_bus_support));
|
pr_debug(" ext bus support %02x\n", rom->ext_bus_support);
|
||||||
DPRINTK((" alternate code type %d\n", rom->alt_code_type));
|
pr_debug(" alternate code type %d\n", rom->alt_code_type);
|
||||||
|
|
||||||
|
font_start = sti->rom->font_start;
|
||||||
|
nr = 0;
|
||||||
|
while (font_start) {
|
||||||
|
struct sti_rom_font *f = font_start->raw;
|
||||||
|
|
||||||
|
pr_info(" built-in font #%d: size %dx%d, chars %d-%d, bpc %d\n", ++nr,
|
||||||
|
f->width, f->height,
|
||||||
|
f->first_char, f->last_char, f->bytes_per_char);
|
||||||
|
font_start = font_start->next_font;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -628,39 +654,34 @@ static int sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int sti_search_font(struct sti_cooked_rom *rom, int height, int width)
|
|
||||||
{
|
|
||||||
struct sti_cooked_font *font;
|
|
||||||
int i = 0;
|
|
||||||
|
|
||||||
for (font = rom->font_start; font; font = font->next_font, i++) {
|
|
||||||
if ((font->raw->width == width) &&
|
|
||||||
(font->raw->height == height))
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define BMODE_RELOCATE(offset) offset = (offset) / 4;
|
#define BMODE_RELOCATE(offset) offset = (offset) / 4;
|
||||||
#define BMODE_LAST_ADDR_OFFS 0x50
|
#define BMODE_LAST_ADDR_OFFS 0x50
|
||||||
|
|
||||||
static void *sti_bmode_font_raw(struct sti_cooked_font *f)
|
void sti_font_convert_bytemode(struct sti_struct *sti, struct sti_cooked_font *f)
|
||||||
{
|
{
|
||||||
unsigned char *n, *p, *q;
|
unsigned char *n, *p, *q;
|
||||||
int size = f->raw->bytes_per_char*256+sizeof(struct sti_rom_font);
|
int size = f->raw->bytes_per_char * 256 + sizeof(struct sti_rom_font);
|
||||||
|
struct sti_rom_font *old_font;
|
||||||
|
|
||||||
|
if (sti->wordmode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
old_font = f->raw_ptr;
|
||||||
n = kcalloc(4, size, STI_LOWMEM);
|
n = kcalloc(4, size, STI_LOWMEM);
|
||||||
|
f->raw_ptr = n;
|
||||||
if (!n)
|
if (!n)
|
||||||
return NULL;
|
return;
|
||||||
p = n + 3;
|
p = n + 3;
|
||||||
q = (unsigned char *)f->raw;
|
q = (unsigned char *) f->raw;
|
||||||
while (size--) {
|
while (size--) {
|
||||||
*p = *q++;
|
*p = *q++;
|
||||||
p+=4;
|
p += 4;
|
||||||
}
|
}
|
||||||
return n + 3;
|
/* store new ptr to byte-mode font and delete old font */
|
||||||
|
f->raw = (struct sti_rom_font *) (n + 3);
|
||||||
|
kfree(old_font);
|
||||||
}
|
}
|
||||||
|
EXPORT_SYMBOL(sti_font_convert_bytemode);
|
||||||
|
|
||||||
static void sti_bmode_rom_copy(unsigned long base, unsigned long count,
|
static void sti_bmode_rom_copy(unsigned long base, unsigned long count,
|
||||||
void *dest)
|
void *dest)
|
||||||
|
@ -747,7 +768,7 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti,
|
||||||
goto out_err;
|
goto out_err;
|
||||||
|
|
||||||
if (!sti_cook_fonts(cooked, raw)) {
|
if (!sti_cook_fonts(cooked, raw)) {
|
||||||
printk(KERN_ERR "No font found for STI at %08lx\n", address);
|
pr_warn("No font found for STI at %08lx\n", address);
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,7 +777,8 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti,
|
||||||
|
|
||||||
address = (unsigned long) STI_PTR(raw);
|
address = (unsigned long) STI_PTR(raw);
|
||||||
|
|
||||||
pr_info("STI ROM supports 32 %sbit firmware functions.\n",
|
pr_info("STI %s ROM supports 32 %sbit firmware functions.\n",
|
||||||
|
wordmode ? "word mode" : "byte mode",
|
||||||
raw->alt_code_type == ALT_CODE_TYPE_PA_RISC_64
|
raw->alt_code_type == ALT_CODE_TYPE_PA_RISC_64
|
||||||
? "and 64 " : "");
|
? "and 64 " : "");
|
||||||
|
|
||||||
|
@ -767,18 +789,17 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti,
|
||||||
|
|
||||||
sti->rom = cooked;
|
sti->rom = cooked;
|
||||||
sti->rom->raw = raw;
|
sti->rom->raw = raw;
|
||||||
|
sti_dump_rom(sti);
|
||||||
sti->font = sti_select_font(sti->rom, sti_search_font);
|
|
||||||
sti->font_width = sti->font->raw->width;
|
sti->wordmode = wordmode;
|
||||||
sti->font_height = sti->font->raw->height;
|
sti->font = sti_select_font(sti->rom);
|
||||||
if (!wordmode)
|
sti->font->width = sti->font->raw->width;
|
||||||
sti->font->raw = sti_bmode_font_raw(sti->font);
|
sti->font->height = sti->font->raw->height;
|
||||||
|
sti_font_convert_bytemode(sti, sti->font);
|
||||||
|
|
||||||
sti->sti_mem_request = raw->sti_mem_req;
|
sti->sti_mem_request = raw->sti_mem_req;
|
||||||
sti->graphics_id[0] = raw->graphics_id[0];
|
sti->graphics_id[0] = raw->graphics_id[0];
|
||||||
sti->graphics_id[1] = raw->graphics_id[1];
|
sti->graphics_id[1] = raw->graphics_id[1];
|
||||||
|
|
||||||
sti_dump_rom(raw);
|
|
||||||
|
|
||||||
/* check if the ROM routines in this card are compatible */
|
/* check if the ROM routines in this card are compatible */
|
||||||
if (wordmode || sti->graphics_id[1] != 0x09A02587)
|
if (wordmode || sti->graphics_id[1] != 0x09A02587)
|
||||||
|
@ -804,9 +825,9 @@ ok:
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
msg_not_supported:
|
msg_not_supported:
|
||||||
printk(KERN_ERR "Sorry, this GSC/STI card is not yet supported.\n");
|
pr_warn("Sorry, this GSC/STI card is not yet supported.\n");
|
||||||
printk(KERN_ERR "Please see http://parisc-linux.org/faq/"
|
pr_warn("Please see https://parisc.wiki.kernel.org/"
|
||||||
"graphics-howto.html for more info.\n");
|
"index.php/Graphics_howto for more info.\n");
|
||||||
/* fall through */
|
/* fall through */
|
||||||
out_err:
|
out_err:
|
||||||
kfree(raw);
|
kfree(raw);
|
||||||
|
@ -823,7 +844,7 @@ static struct sti_struct *sti_try_rom_generic(unsigned long address,
|
||||||
u32 sig;
|
u32 sig;
|
||||||
|
|
||||||
if (num_sti_roms >= MAX_STI_ROMS) {
|
if (num_sti_roms >= MAX_STI_ROMS) {
|
||||||
printk(KERN_WARNING "maximum number of STI ROMS reached !\n");
|
pr_warn("maximum number of STI ROMS reached !\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -849,16 +870,15 @@ test_rom:
|
||||||
if (i != 1) {
|
if (i != 1) {
|
||||||
/* The ROM could have multiple architecture
|
/* The ROM could have multiple architecture
|
||||||
* dependent images (e.g. i386, parisc,...) */
|
* dependent images (e.g. i386, parisc,...) */
|
||||||
printk(KERN_WARNING
|
pr_warn("PCI ROM is not a STI ROM type image (0x%8x)\n", i);
|
||||||
"PCI ROM is not a STI ROM type image (0x%8x)\n", i);
|
|
||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
sti->pd = pd;
|
sti->pd = pd;
|
||||||
|
|
||||||
i = gsc_readl(address+0x0c);
|
i = gsc_readl(address+0x0c);
|
||||||
DPRINTK(("PCI ROM size (from header) = %d kB\n",
|
pr_debug("PCI ROM size (from header) = %d kB\n",
|
||||||
le16_to_cpu(i>>16)*512/1024));
|
le16_to_cpu(i>>16)*512/1024);
|
||||||
rm_offset = le16_to_cpu(i & 0xffff);
|
rm_offset = le16_to_cpu(i & 0xffff);
|
||||||
if (rm_offset) {
|
if (rm_offset) {
|
||||||
/* read 16 bytes from the pci region mapper array */
|
/* read 16 bytes from the pci region mapper array */
|
||||||
|
@ -867,29 +887,24 @@ test_rom:
|
||||||
*rm++ = gsc_readl(address+rm_offset+0x04);
|
*rm++ = gsc_readl(address+rm_offset+0x04);
|
||||||
*rm++ = gsc_readl(address+rm_offset+0x08);
|
*rm++ = gsc_readl(address+rm_offset+0x08);
|
||||||
*rm++ = gsc_readl(address+rm_offset+0x0c);
|
*rm++ = gsc_readl(address+rm_offset+0x0c);
|
||||||
DPRINTK(("PCI region Mapper offset = %08x: ",
|
|
||||||
rm_offset));
|
|
||||||
for (i=0; i<16; i++)
|
|
||||||
DPRINTK(("%02x ", sti->rm_entry[i]));
|
|
||||||
DPRINTK(("\n"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
address += le32_to_cpu(gsc_readl(address+8));
|
address += le32_to_cpu(gsc_readl(address+8));
|
||||||
DPRINTK(("sig %04x, PCI STI ROM at %08lx\n", sig, address));
|
pr_debug("sig %04x, PCI STI ROM at %08lx\n", sig, address);
|
||||||
goto test_rom;
|
goto test_rom;
|
||||||
}
|
}
|
||||||
|
|
||||||
ok = 0;
|
ok = 0;
|
||||||
|
|
||||||
if ((sig & 0xff) == 0x01) {
|
if ((sig & 0xff) == 0x01) {
|
||||||
DPRINTK((" byte mode ROM at %08lx, hpa at %08lx\n",
|
pr_debug(" byte mode ROM at %08lx, hpa at %08lx\n",
|
||||||
address, hpa));
|
address, hpa);
|
||||||
ok = sti_read_rom(0, sti, address);
|
ok = sti_read_rom(0, sti, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((sig & 0xffff) == 0x0303) {
|
if ((sig & 0xffff) == 0x0303) {
|
||||||
DPRINTK((" word mode ROM at %08lx, hpa at %08lx\n",
|
pr_debug(" word mode ROM at %08lx, hpa at %08lx\n",
|
||||||
address, hpa));
|
address, hpa);
|
||||||
ok = sti_read_rom(1, sti, address);
|
ok = sti_read_rom(1, sti, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -906,7 +921,7 @@ test_rom:
|
||||||
unsigned long rom_base;
|
unsigned long rom_base;
|
||||||
rom_base = pci_resource_start(sti->pd, PCI_ROM_RESOURCE);
|
rom_base = pci_resource_start(sti->pd, PCI_ROM_RESOURCE);
|
||||||
pci_write_config_dword(sti->pd, PCI_ROM_ADDRESS, rom_base & ~PCI_ROM_ADDRESS_ENABLE);
|
pci_write_config_dword(sti->pd, PCI_ROM_ADDRESS, rom_base & ~PCI_ROM_ADDRESS_ENABLE);
|
||||||
DPRINTK((KERN_DEBUG "STI PCI ROM disabled\n"));
|
pr_debug("STI PCI ROM disabled\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sti_init_graph(sti))
|
if (sti_init_graph(sti))
|
||||||
|
@ -981,14 +996,14 @@ static int sticore_pci_init(struct pci_dev *pd, const struct pci_device_id *ent)
|
||||||
rom_len = pci_resource_len(pd, PCI_ROM_RESOURCE);
|
rom_len = pci_resource_len(pd, PCI_ROM_RESOURCE);
|
||||||
if (rom_base) {
|
if (rom_base) {
|
||||||
pci_write_config_dword(pd, PCI_ROM_ADDRESS, rom_base | PCI_ROM_ADDRESS_ENABLE);
|
pci_write_config_dword(pd, PCI_ROM_ADDRESS, rom_base | PCI_ROM_ADDRESS_ENABLE);
|
||||||
DPRINTK((KERN_DEBUG "STI PCI ROM enabled at 0x%08lx\n", rom_base));
|
pr_debug("STI PCI ROM enabled at 0x%08lx\n", rom_base);
|
||||||
}
|
}
|
||||||
|
|
||||||
printk(KERN_INFO "STI PCI graphic ROM found at %08lx (%u kB), fb at %08lx (%u MB)\n",
|
pr_info("STI PCI graphic ROM found at %08lx (%u kB), fb at %08lx (%u MB)\n",
|
||||||
rom_base, rom_len/1024, fb_base, fb_len/1024/1024);
|
rom_base, rom_len/1024, fb_base, fb_len/1024/1024);
|
||||||
|
|
||||||
DPRINTK((KERN_DEBUG "Trying PCI STI ROM at %08lx, PCI hpa at %08lx\n",
|
pr_debug("Trying PCI STI ROM at %08lx, PCI hpa at %08lx\n",
|
||||||
rom_base, fb_base));
|
rom_base, fb_base);
|
||||||
|
|
||||||
sti = sti_try_rom_generic(rom_base, fb_base, pd);
|
sti = sti_try_rom_generic(rom_base, fb_base, pd);
|
||||||
if (sti) {
|
if (sti) {
|
||||||
|
@ -998,8 +1013,7 @@ static int sticore_pci_init(struct pci_dev *pd, const struct pci_device_id *ent)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sti) {
|
if (!sti) {
|
||||||
printk(KERN_WARNING "Unable to handle STI device '%s'\n",
|
pr_warn("Unable to handle STI device '%s'\n", pci_name(pd));
|
||||||
pci_name(pd));
|
|
||||||
return -ENODEV;
|
return -ENODEV;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_PCI */
|
#endif /* CONFIG_PCI */
|
||||||
|
@ -1058,7 +1072,7 @@ static void sti_init_roms(void)
|
||||||
|
|
||||||
sticore_initialized = 1;
|
sticore_initialized = 1;
|
||||||
|
|
||||||
printk(KERN_INFO "STI GSC/PCI core graphics driver "
|
pr_info("STI GSC/PCI core graphics driver "
|
||||||
STI_DRIVERVERSION "\n");
|
STI_DRIVERVERSION "\n");
|
||||||
|
|
||||||
/* Register drivers for native & PCI cards */
|
/* Register drivers for native & PCI cards */
|
||||||
|
|
|
@ -4,12 +4,6 @@
|
||||||
|
|
||||||
/* generic STI structures & functions */
|
/* generic STI structures & functions */
|
||||||
|
|
||||||
#if 0
|
|
||||||
#define DPRINTK(x) printk x
|
|
||||||
#else
|
|
||||||
#define DPRINTK(x)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define MAX_STI_ROMS 4 /* max no. of ROMs which this driver handles */
|
#define MAX_STI_ROMS 4 /* max no. of ROMs which this driver handles */
|
||||||
|
|
||||||
#define STI_REGION_MAX 8 /* hardcoded STI constants */
|
#define STI_REGION_MAX 8 /* hardcoded STI constants */
|
||||||
|
@ -246,8 +240,12 @@ struct sti_rom_font {
|
||||||
/* sticore internal font handling */
|
/* sticore internal font handling */
|
||||||
|
|
||||||
struct sti_cooked_font {
|
struct sti_cooked_font {
|
||||||
struct sti_rom_font *raw;
|
struct sti_rom_font *raw; /* native ptr for STI functions */
|
||||||
|
void *raw_ptr; /* kmalloc'ed font data */
|
||||||
struct sti_cooked_font *next_font;
|
struct sti_cooked_font *next_font;
|
||||||
|
int height, width;
|
||||||
|
int refcount;
|
||||||
|
u32 crc;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct sti_cooked_rom {
|
struct sti_cooked_rom {
|
||||||
|
@ -341,9 +339,6 @@ struct sti_all_data {
|
||||||
struct sti_struct {
|
struct sti_struct {
|
||||||
spinlock_t lock;
|
spinlock_t lock;
|
||||||
|
|
||||||
/* the following fields needs to be filled in by the word/byte routines */
|
|
||||||
int font_width;
|
|
||||||
int font_height;
|
|
||||||
/* char **mon_strings; */
|
/* char **mon_strings; */
|
||||||
int sti_mem_request;
|
int sti_mem_request;
|
||||||
u32 graphics_id[2];
|
u32 graphics_id[2];
|
||||||
|
@ -362,6 +357,7 @@ struct sti_struct {
|
||||||
|
|
||||||
struct sti_glob_cfg *glob_cfg; /* points into sti_all_data */
|
struct sti_glob_cfg *glob_cfg; /* points into sti_all_data */
|
||||||
|
|
||||||
|
int wordmode;
|
||||||
struct sti_cooked_font *font; /* ptr to selected font (cooked) */
|
struct sti_cooked_font *font; /* ptr to selected font (cooked) */
|
||||||
|
|
||||||
struct pci_dev *pd;
|
struct pci_dev *pd;
|
||||||
|
@ -380,6 +376,7 @@ struct sti_struct {
|
||||||
/* sticore interface functions */
|
/* sticore interface functions */
|
||||||
|
|
||||||
struct sti_struct *sti_get_rom(unsigned int index); /* 0: default sti */
|
struct sti_struct *sti_get_rom(unsigned int index); /* 0: default sti */
|
||||||
|
void sti_font_convert_bytemode(struct sti_struct *sti, struct sti_cooked_font *f);
|
||||||
|
|
||||||
|
|
||||||
/* sticore main function to call STI firmware */
|
/* sticore main function to call STI firmware */
|
||||||
|
@ -391,12 +388,14 @@ int sti_call(const struct sti_struct *sti, unsigned long func,
|
||||||
|
|
||||||
/* functions to call the STI ROM directly */
|
/* functions to call the STI ROM directly */
|
||||||
|
|
||||||
void sti_putc(struct sti_struct *sti, int c, int y, int x);
|
void sti_putc(struct sti_struct *sti, int c, int y, int x,
|
||||||
|
struct sti_cooked_font *font);
|
||||||
void sti_set(struct sti_struct *sti, int src_y, int src_x,
|
void sti_set(struct sti_struct *sti, int src_y, int src_x,
|
||||||
int height, int width, u8 color);
|
int height, int width, u8 color);
|
||||||
void sti_clear(struct sti_struct *sti, int src_y, int src_x,
|
void sti_clear(struct sti_struct *sti, int src_y, int src_x,
|
||||||
int height, int width, int c);
|
int height, int width, int c, struct sti_cooked_font *font);
|
||||||
void sti_bmove(struct sti_struct *sti, int src_y, int src_x,
|
void sti_bmove(struct sti_struct *sti, int src_y, int src_x,
|
||||||
int dst_y, int dst_x, int height, int width);
|
int dst_y, int dst_x, int height, int width,
|
||||||
|
struct sti_cooked_font *font);
|
||||||
|
|
||||||
#endif /* STICORE_H */
|
#endif /* STICORE_H */
|
||||||
|
|
Loading…
Reference in New Issue