* linux/drivers/video/console/sticon.c - console driver using HP's STI firmware
*
* 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,
* which were
#include <linux/kd.h>
#include <linux/selection.h>
#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/font.h>
+#include <linux/crc32.h>
#include <asm/io.h>
#define BLANK 0
static int vga_is_gfx;
-/* this is the sti_struct used for this console */
-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)
+#define STI_DEF_FONT sticon_sti->font
-static int vbl_cursor_cnt;
+/* borrowed from fbcon.c */
+#define FNTREFCOUNT(fd) (fd->refcount)
+#define FNTCRC(fd) (fd->crc)
+static struct sti_cooked_font *font_data[MAX_NR_CONSOLES];
-static inline void cursor_undrawn(void)
-{
- vbl_cursor_cnt = 0;
- cursor_drawn = 0;
-}
+/* this is the sti_struct used for this console */
+static struct sti_struct *sticon_sti;
static const char *sticon_startup(void)
{
static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos)
{
- int redraw_cursor = 0;
-
if (vga_is_gfx || console_blanked)
return;
if (conp->vc_mode != KD_TEXT)
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);
- if (redraw_cursor)
- vbl_cursor_cnt = CURSOR_DRAW_DELAY;
+ sti_putc(sticon_sti, c, ypos, xpos, font_data[conp->vc_num]);
}
static void sticon_putcs(struct vc_data *conp, const unsigned short *s,
int count, int ypos, int xpos)
{
- int redraw_cursor = 0;
-
if (vga_is_gfx || console_blanked)
return;
if (conp->vc_mode != KD_TEXT)
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--) {
- 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)
{
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];
switch (mode) {
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;
case CM_MOVE:
case CM_DRAW:
case CUR_TWO_THIRDS:
case CUR_BLOCK:
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;
switch (dir) {
case SM_UP:
- 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);
+ sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols,
+ 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;
case SM_DOWN:
- 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);
+ sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols,
+ 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;
}
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)
{
struct sti_struct *sti = sticon_sti;
int vc_cols, vc_rows;
sti_set(sti, 0, 0, sti_onscreen_y(sti), sti_onscreen_x(sti), 0);
- vc_cols = sti_onscreen_x(sti) / sti->font_width;
- vc_rows = sti_onscreen_y(sti) / sti->font_height;
+ vc_cols = sti_onscreen_x(sti) / sti->font->width;
+ vc_rows = sti_onscreen_y(sti) / sti->font->height;
c->vc_can_do_color = 1;
if (init) {
c->vc_cols = vc_cols;
c->vc_rows = vc_rows;
} 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_con(vc_rows, vc_cols, c->vc_num); */
}
}
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,
if (!height || !width)
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)
vga_is_gfx = 0;
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)
vga_is_gfx = 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,
enum vc_intensity intens,
bool blink, bool underline, bool reverse,
}
}
-static void sticon_save_screen(struct vc_data *conp)
-{
-}
-
static const struct consw sti_con = {
.owner = THIS_MODULE,
.con_startup = sticon_startup,
.con_scroll = sticon_scroll,
.con_switch = sticon_switch,
.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_invert_region = sticon_invert_region,
- .con_screen_pos = sticon_screen_pos,
- .con_getxy = sticon_getxy,
};
static int __init sticonsole_init(void)
{
- int err;
+ int err, i;
+
/* already initialized ? */
if (sticon_sti)
return 0;
if (!sticon_sti)
return -ENODEV;
+ for (i = 0; i < MAX_NR_CONSOLES; i++)
+ font_data[i] = STI_DEF_FONT;
+
pr_info("sticon: Initializing STI text console.\n");
console_lock();
err = do_take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1,
* core code for console driver using HP's STI firmware
*
* 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>
*
* TODO:
*
*/
+#define pr_fmt(fmt) "%s: " fmt, KBUILD_MODNAME
+
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
};
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_default = {
- .font_start_addr= STI_PTR(sti->font->raw),
+ .font_start_addr = STI_PTR(font->raw),
.index = c_index(sti, c),
.fg_color = c_fg(sti, c),
.bg_color = c_bg(sti, c),
- .dest_x = x * sti->font_width,
- .dest_y = y * sti->font_height,
+ .dest_x = x * font->width,
+ .dest_y = y * font->height,
};
struct sti_font_outptr *outptr = &sti->sti_data->font_outptr;
s32 ret;
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)
{
struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr;
struct sti_blkmv_inptr inptr_default = {
.fg_color = c_fg(sti, c),
.bg_color = c_bg(sti, c),
- .src_x = src_x * sti->font_width,
- .src_y = src_y * sti->font_height,
- .dest_x = src_x * sti->font_width,
- .dest_y = src_y * sti->font_height,
- .width = width * sti->font_width,
- .height = height* sti->font_height,
+ .src_x = src_x * font->width,
+ .src_y = src_y * font->height,
+ .dest_x = src_x * font->width,
+ .dest_y = src_y * font->height,
+ .width = width * font->width,
+ .height = height * font->height,
};
struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr;
s32 ret;
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)
{
struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr;
struct sti_blkmv_inptr inptr_default = {
- .src_x = src_x * sti->font_width,
- .src_y = src_y * sti->font_height,
- .dest_x = dst_x * sti->font_width,
- .dest_y = dst_y * sti->font_height,
- .width = width * sti->font_width,
- .height = height* sti->font_height,
+ .src_x = src_x * font->width,
+ .src_y = src_y * font->height,
+ .dest_x = dst_x * font->width,
+ .dest_y = dst_y * font->height,
+ .width = width * font->width,
+ .height = height * font->height,
};
struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr;
s32 ret;
-static char *font_name[MAX_STI_ROMS];
-static int font_index[MAX_STI_ROMS],
- font_height[MAX_STI_ROMS],
- font_width[MAX_STI_ROMS];
+static char *font_name;
+static int font_index,
+ font_height,
+ font_width;
#ifndef MODULE
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
- * or sti_font=7 style command lines. */
+ if (*str >= '0' && *str <= '9') {
+ char *x;
- while (i<MAX_STI_ROMS && str && *str) {
- if (*str>='0' && *str<='9') {
- if ((x = strchr(str, 'x')) || (x = strchr(str, '*'))) {
- 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);
- }
+ if ((x = strchr(str, 'x')) || (x = strchr(str, '*'))) {
+ font_height = simple_strtoul(str, NULL, 0);
+ font_width = simple_strtoul(x+1, NULL, 0);
} else {
- font_name[i] = str; /* fb font name */
+ font_index = simple_strtoul(str, NULL, 0);
}
-
- if ((x = strchr(str, ',')))
- *x++ = 0;
- str = x;
-
- i++;
+ } else {
+ font_name = str; /* fb font name */
}
return 1;
* framebuffer font names (e.g. VGA8x16, SUN22x18).
* This is only available if the fonts have been statically compiled
* 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
* by giving the desired number to the sticon driver.
* NOTE: This number is machine and STI ROM dependend.
{
struct sti_glob_cfg_ext *cfg;
- DPRINTK((KERN_INFO
- "%d text planes\n"
+ pr_debug("%d text planes\n"
"%4d x %4d screen resolution\n"
"%4d x %4d offscreen\n"
"%4d x %4d layout\n"
glob_cfg->region_ptrs[4], glob_cfg->region_ptrs[5],
glob_cfg->region_ptrs[6], glob_cfg->region_ptrs[7],
glob_cfg->reent_lvl,
- glob_cfg->save_addr));
+ glob_cfg->save_addr);
/* dump extended cfg */
cfg = PTR_STI((unsigned long)glob_cfg->ext_ptr);
- DPRINTK(( KERN_INFO
- "monitor %d\n"
+ pr_debug("monitor %d\n"
"in friendly mode: %d\n"
"power consumption %d watts\n"
"freq ref %d\n"
cfg->friendly_boot,
cfg->power,
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)
{
- DPRINTK((KERN_INFO
- "%d bits per pixel\n"
+ pr_debug("%d bits per pixel\n"
"%d used bits\n"
"%d planes\n"
"attributes %08x\n",
sti->sti_data->inq_outptr.bits_per_pixel,
sti->sti_data->inq_outptr.bits_used,
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,
if (offs != PCI_ROM_ADDRESS &&
(offs < PCI_BASE_ADDRESS_0 ||
offs > PCI_BASE_ADDRESS_5)) {
- printk (KERN_WARNING
- "STI pci region mapping for region %d (%02x) can't be mapped\n",
+ pr_warn("STI pci region mapping for region %d (%02x) can't be mapped\n",
i,sti->rm_entry[i]);
continue;
}
if (len)
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",
i, sti->regions_phys[i], glob_cfg->region_ptrs[i],
len/1024,
sti->regions[i].region_desc.btlb,
sti->regions[i].region_desc.sys_only,
sti->regions[i].region_desc.cache,
- sti->regions[i].region_desc.last));
+ sti->regions[i].region_desc.last);
/* last entry reached ? */
if (sti->regions[i].region_desc.last)
}
if (++i<8 && sti->regions[i].region)
- printk(KERN_WARNING "%s: *future ptr (0x%8x) not yet supported !\n",
- __FILE__, sti->regions[i].region);
+ pr_warn("future ptr (0x%8x) not yet supported !\n",
+ sti->regions[i].region);
glob_cfg_ext->sti_mem_addr = STI_PTR(sti_mem_addr);
}
cooked_font->raw = nf;
+ cooked_font->raw_ptr = nf;
cooked_font->next_font = NULL;
cooked_rom->font_start = cooked_font;
}
#endif
-static struct sti_cooked_font *sti_select_font(struct sti_cooked_rom *rom,
- int (*search_font_fnc)(struct sti_cooked_rom *, int, int))
+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;
+}
+
+static struct sti_cooked_font *sti_select_font(struct sti_cooked_rom *rom)
{
struct sti_cooked_font *font;
int i;
- int index = num_sti_roms;
/* check for framebuffer-font first */
- if ((font = sti_select_fbfont(rom, font_name[index])))
- return font;
+ if (!font_index) {
+ font = sti_select_fbfont(rom, font_name);
+ if (font)
+ return font;
+ }
- if (font_width[index] && font_height[index])
- font_index[index] = search_font_fnc(rom,
- font_height[index], font_width[index]);
+ if (font_width && font_height)
+ font_index = sti_search_font(rom,
+ font_height, font_width);
- for (font = rom->font_start, i = font_index[index];
- font && (i > 0);
- font = font->next_font, i--);
+ for (font = rom->font_start, i = font_index - 1;
+ font && (i > 0);
+ font = font->next_font, i--);
if (font)
return font;
}
-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[1],
rom->revno[0] >> 4,
rom->revno[0] & 0x0f);
- DPRINTK((" supports %d monitors\n", rom->num_mons));
- DPRINTK((" font start %08x\n", rom->font_start));
- DPRINTK((" region list %08x\n", rom->region_list));
- DPRINTK((" init_graph %08x\n", rom->init_graph));
- DPRINTK((" bus support %02x\n", rom->bus_support));
- DPRINTK((" ext bus support %02x\n", rom->ext_bus_support));
- DPRINTK((" alternate code type %d\n", rom->alt_code_type));
+ pr_debug(" supports %d monitors\n", rom->num_mons);
+ pr_debug(" font start %08x\n", rom->font_start);
+ pr_debug(" region list %08x\n", rom->region_list);
+ pr_debug(" init_graph %08x\n", rom->init_graph);
+ pr_debug(" bus support %02x\n", rom->bus_support);
+ pr_debug(" ext bus support %02x\n", rom->ext_bus_support);
+ 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;
+ }
}
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_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;
- 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);
+ f->raw_ptr = n;
if (!n)
- return NULL;
+ return;
p = n + 3;
- q = (unsigned char *)f->raw;
+ q = (unsigned char *) f->raw;
while (size--) {
*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,
void *dest)
goto out_err;
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;
}
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
? "and 64 " : "");
sti->rom = cooked;
sti->rom->raw = raw;
-
- sti->font = sti_select_font(sti->rom, sti_search_font);
- sti->font_width = sti->font->raw->width;
- sti->font_height = sti->font->raw->height;
- if (!wordmode)
- sti->font->raw = sti_bmode_font_raw(sti->font);
+ sti_dump_rom(sti);
+
+ sti->wordmode = wordmode;
+ sti->font = sti_select_font(sti->rom);
+ sti->font->width = sti->font->raw->width;
+ sti->font->height = sti->font->raw->height;
+ sti_font_convert_bytemode(sti, sti->font);
sti->sti_mem_request = raw->sti_mem_req;
sti->graphics_id[0] = raw->graphics_id[0];
sti->graphics_id[1] = raw->graphics_id[1];
-
- sti_dump_rom(raw);
/* check if the ROM routines in this card are compatible */
if (wordmode || sti->graphics_id[1] != 0x09A02587)
return 1;
msg_not_supported:
- printk(KERN_ERR "Sorry, this GSC/STI card is not yet supported.\n");
- printk(KERN_ERR "Please see http://parisc-linux.org/faq/"
- "graphics-howto.html for more info.\n");
+ pr_warn("Sorry, this GSC/STI card is not yet supported.\n");
+ pr_warn("Please see https://parisc.wiki.kernel.org/"
+ "index.php/Graphics_howto for more info.\n");
/* fall through */
out_err:
kfree(raw);
u32 sig;
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;
}
if (i != 1) {
/* The ROM could have multiple architecture
* dependent images (e.g. i386, parisc,...) */
- printk(KERN_WARNING
- "PCI ROM is not a STI ROM type image (0x%8x)\n", i);
+ pr_warn("PCI ROM is not a STI ROM type image (0x%8x)\n", i);
goto out_err;
}
sti->pd = pd;
i = gsc_readl(address+0x0c);
- DPRINTK(("PCI ROM size (from header) = %d kB\n",
- le16_to_cpu(i>>16)*512/1024));
+ pr_debug("PCI ROM size (from header) = %d kB\n",
+ le16_to_cpu(i>>16)*512/1024);
rm_offset = le16_to_cpu(i & 0xffff);
if (rm_offset) {
/* read 16 bytes from the pci region mapper array */
*rm++ = gsc_readl(address+rm_offset+0x04);
*rm++ = gsc_readl(address+rm_offset+0x08);
*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));
- 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;
}
ok = 0;
if ((sig & 0xff) == 0x01) {
- DPRINTK((" byte mode ROM at %08lx, hpa at %08lx\n",
- address, hpa));
+ pr_debug(" byte mode ROM at %08lx, hpa at %08lx\n",
+ address, hpa);
ok = sti_read_rom(0, sti, address);
}
if ((sig & 0xffff) == 0x0303) {
- DPRINTK((" word mode ROM at %08lx, hpa at %08lx\n",
- address, hpa));
+ pr_debug(" word mode ROM at %08lx, hpa at %08lx\n",
+ address, hpa);
ok = sti_read_rom(1, sti, address);
}
unsigned long rom_base;
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);
- DPRINTK((KERN_DEBUG "STI PCI ROM disabled\n"));
+ pr_debug("STI PCI ROM disabled\n");
}
if (sti_init_graph(sti))
rom_len = pci_resource_len(pd, PCI_ROM_RESOURCE);
if (rom_base) {
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);
- DPRINTK((KERN_DEBUG "Trying PCI STI ROM at %08lx, PCI hpa at %08lx\n",
- rom_base, fb_base));
+ pr_debug("Trying PCI STI ROM at %08lx, PCI hpa at %08lx\n",
+ rom_base, fb_base);
sti = sti_try_rom_generic(rom_base, fb_base, pd);
if (sti) {
}
if (!sti) {
- printk(KERN_WARNING "Unable to handle STI device '%s'\n",
- pci_name(pd));
+ pr_warn("Unable to handle STI device '%s'\n", pci_name(pd));
return -ENODEV;
}
#endif /* CONFIG_PCI */
sticore_initialized = 1;
- printk(KERN_INFO "STI GSC/PCI core graphics driver "
+ pr_info("STI GSC/PCI core graphics driver "
STI_DRIVERVERSION "\n");
/* Register drivers for native & PCI cards */