summaryrefslogtreecommitdiff
path: root/drivers/video/sticore.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/sticore.c')
-rw-r--r--drivers/video/sticore.c159
1 files changed, 104 insertions, 55 deletions
diff --git a/drivers/video/sticore.c b/drivers/video/sticore.c
index 7eb925f2ba9c..c3765ad6eedf 100644
--- a/drivers/video/sticore.c
+++ b/drivers/video/sticore.c
@@ -4,7 +4,7 @@
* core code for console driver using HP's STI firmware
*
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
- * Copyright (C) 2001-2020 Helge Deller <deller@gmx.de>
+ * Copyright (C) 2001-2023 Helge Deller <deller@gmx.de>
* Copyright (C) 2001-2002 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
*
* TODO:
@@ -41,6 +41,26 @@ static struct sti_struct *default_sti __read_mostly;
static int num_sti_roms __read_mostly;
static struct sti_struct *sti_roms[MAX_STI_ROMS] __read_mostly;
+static void *store_sti_val(struct sti_struct *sti, void *ptr, unsigned long val)
+{
+ u32 *ptr32 = ptr;
+
+ if (IS_ENABLED(CONFIG_64BIT) && sti->do_call64) {
+ /* used for 64-bit STI ROM */
+ unsigned long *ptr64 = ptr;
+
+ ptr64 = PTR_ALIGN(ptr64, sizeof(void *));
+ *ptr64++ = val;
+ return ptr64;
+ }
+
+ /* used for 32-bit STI ROM */
+ *ptr32++ = val;
+ return ptr32;
+}
+
+#define store_sti_ptr(sti, dest, ptr) \
+ store_sti_val(sti, dest, STI_PTR(ptr))
/* The colour indices used by STI are
* 0 - Black
@@ -87,7 +107,7 @@ static int sti_init_graph(struct sti_struct *sti)
memset(inptr, 0, sizeof(*inptr));
inptr->text_planes = 3; /* # of text planes (max 3 for STI) */
memset(inptr_ext, 0, sizeof(*inptr_ext));
- inptr->ext_ptr = STI_PTR(inptr_ext);
+ store_sti_ptr(sti, &inptr->ext_ptr, inptr_ext);
outptr->errno = 0;
ret = sti_call(sti, sti->init_graph, &default_init_flags, inptr,
@@ -118,7 +138,7 @@ static void sti_inq_conf(struct sti_struct *sti)
unsigned long flags;
s32 ret;
- outptr->ext_ptr = STI_PTR(&sti->sti_data->inq_outptr_ext);
+ store_sti_ptr(sti, &outptr->ext_ptr, &sti->sti_data->inq_outptr_ext);
do {
spin_lock_irqsave(&sti->lock, flags);
@@ -138,9 +158,9 @@ void
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;
struct sti_font_inptr inptr_default = {
- .font_start_addr = STI_PTR(font->raw),
+ .font_start_addr = (void *)STI_PTR(font->raw),
.index = c_index(sti, c),
.fg_color = c_fg(sti, c),
.bg_color = c_bg(sti, c),
@@ -153,7 +173,14 @@ sti_putc(struct sti_struct *sti, int c, int y, int x,
do {
spin_lock_irqsave(&sti->lock, flags);
- *inptr = inptr_default;
+ inptr = &inptr_default;
+ if (IS_ENABLED(CONFIG_64BIT) && !sti->do_call64) {
+ /* copy below 4G if calling 32-bit on LP64 kernel */
+ inptr = &sti->sti_data->font_inptr;
+ *inptr = inptr_default;
+ /* skip first 4 bytes for 32-bit STI call */
+ inptr = (void *)(((unsigned long)inptr) + sizeof(u32));
+ }
ret = sti_call(sti, sti->font_unpmv, &default_font_flags,
inptr, outptr, sti->glob_cfg);
spin_unlock_irqrestore(&sti->lock, flags);
@@ -170,7 +197,7 @@ void
sti_set(struct sti_struct *sti, int src_y, int src_x,
int height, int width, u8 color)
{
- struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr;
+ struct sti_blkmv_inptr *inptr;
struct sti_blkmv_inptr inptr_default = {
.fg_color = color,
.bg_color = color,
@@ -187,7 +214,12 @@ sti_set(struct sti_struct *sti, int src_y, int src_x,
do {
spin_lock_irqsave(&sti->lock, flags);
- *inptr = inptr_default;
+ inptr = &inptr_default;
+ if (IS_ENABLED(CONFIG_64BIT) && !sti->do_call64) {
+ /* copy below 4G if calling 32-bit on LP64 kernel */
+ inptr = &sti->sti_data->blkmv_inptr;
+ *inptr = inptr_default;
+ }
ret = sti_call(sti, sti->block_move, &clear_blkmv_flags,
inptr, outptr, sti->glob_cfg);
spin_unlock_irqrestore(&sti->lock, flags);
@@ -198,7 +230,7 @@ void
sti_clear(struct sti_struct *sti, int src_y, int src_x,
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;
struct sti_blkmv_inptr inptr_default = {
.fg_color = c_fg(sti, c),
.bg_color = c_bg(sti, c),
@@ -215,7 +247,12 @@ sti_clear(struct sti_struct *sti, int src_y, int src_x,
do {
spin_lock_irqsave(&sti->lock, flags);
- *inptr = inptr_default;
+ inptr = &inptr_default;
+ if (IS_ENABLED(CONFIG_64BIT) && !sti->do_call64) {
+ /* copy below 4G if calling 32-bit on LP64 kernel */
+ inptr = &sti->sti_data->blkmv_inptr;
+ *inptr = inptr_default;
+ }
ret = sti_call(sti, sti->block_move, &clear_blkmv_flags,
inptr, outptr, sti->glob_cfg);
spin_unlock_irqrestore(&sti->lock, flags);
@@ -231,7 +268,7 @@ sti_bmove(struct sti_struct *sti, int src_y, int src_x,
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;
struct sti_blkmv_inptr inptr_default = {
.src_x = src_x * font->width,
.src_y = src_y * font->height,
@@ -246,7 +283,12 @@ sti_bmove(struct sti_struct *sti, int src_y, int src_x,
do {
spin_lock_irqsave(&sti->lock, flags);
- *inptr = inptr_default;
+ inptr = &inptr_default;
+ if (IS_ENABLED(CONFIG_64BIT) && !sti->do_call64) {
+ /* copy below 4G if calling 32-bit on LP64 kernel */
+ inptr = &sti->sti_data->blkmv_inptr;
+ *inptr = inptr_default;
+ }
ret = sti_call(sti, sti->block_move, &default_blkmv_flags,
inptr, outptr, sti->glob_cfg);
spin_unlock_irqrestore(&sti->lock, flags);
@@ -359,42 +401,31 @@ __setup("sti_font=", sti_font_setup);
-static void sti_dump_globcfg(struct sti_glob_cfg *glob_cfg,
- unsigned int sti_mem_request)
+static void sti_dump_globcfg(struct sti_struct *sti)
{
- struct sti_glob_cfg_ext *cfg;
+ struct sti_glob_cfg *glob_cfg = sti->glob_cfg;
+ struct sti_glob_cfg_ext *cfg = &sti->sti_data->glob_cfg_ext;
pr_debug("%d text planes\n"
"%4d x %4d screen resolution\n"
"%4d x %4d offscreen\n"
- "%4d x %4d layout\n"
- "regions at %08x %08x %08x %08x\n"
- "regions at %08x %08x %08x %08x\n"
- "reent_lvl %d\n"
- "save_addr %08x\n",
+ "%4d x %4d layout\n",
glob_cfg->text_planes,
glob_cfg->onscreen_x, glob_cfg->onscreen_y,
glob_cfg->offscreen_x, glob_cfg->offscreen_y,
- glob_cfg->total_x, glob_cfg->total_y,
- glob_cfg->region_ptrs[0], glob_cfg->region_ptrs[1],
- glob_cfg->region_ptrs[2], glob_cfg->region_ptrs[3],
- 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->total_x, glob_cfg->total_y);
/* dump extended cfg */
- cfg = PTR_STI((unsigned long)glob_cfg->ext_ptr);
pr_debug("monitor %d\n"
"in friendly mode: %d\n"
"power consumption %d watts\n"
"freq ref %d\n"
- "sti_mem_addr %08x (size=%d bytes)\n",
+ "sti_mem_addr %px (size=%d bytes)\n",
cfg->curr_mon,
cfg->friendly_boot,
cfg->power,
cfg->freq_ref,
- cfg->sti_mem_addr, sti_mem_request);
+ cfg->sti_mem_addr, sti->sti_mem_request);
}
static void sti_dump_outptr(struct sti_struct *sti)
@@ -414,7 +445,7 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address,
{
struct sti_glob_cfg *glob_cfg;
struct sti_glob_cfg_ext *glob_cfg_ext;
- void *save_addr;
+ void *save_addr, *ptr;
void *sti_mem_addr;
int i, size;
@@ -432,9 +463,7 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address,
save_addr = &sti->sti_data->save_addr;
sti_mem_addr = &sti->sti_data->sti_mem_addr;
- glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext);
- glob_cfg->save_addr = STI_PTR(save_addr);
- for (i=0; i<8; i++) {
+ for (i = 0; i < STI_REGION_MAX; i++) {
unsigned long newhpa, len;
if (sti->pd) {
@@ -457,13 +486,10 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address,
REGION_OFFSET_TO_PHYS(sti->regions[i], newhpa);
len = sti->regions[i].region_desc.length * 4096;
- if (len)
- glob_cfg->region_ptrs[i] = sti->regions_phys[i];
- pr_debug("region #%d: phys %08lx, region_ptr %08x, len=%lukB, "
+ pr_debug("region #%d: phys %08lx, len=%lukB, "
"btlb=%d, sysonly=%d, cache=%d, last=%d\n",
- i, sti->regions_phys[i], glob_cfg->region_ptrs[i],
- len/1024,
+ i, sti->regions_phys[i], len / 1024,
sti->regions[i].region_desc.btlb,
sti->regions[i].region_desc.sys_only,
sti->regions[i].region_desc.cache,
@@ -474,11 +500,16 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address,
break;
}
- if (++i<8 && sti->regions[i].region)
- pr_warn("future ptr (0x%8x) not yet supported !\n",
- sti->regions[i].region);
+ ptr = &glob_cfg->region_ptrs;
+ for (i = 0; i < STI_REGION_MAX; i++)
+ ptr = store_sti_val(sti, ptr, sti->regions_phys[i]);
+
+ *(s32 *)ptr = 0; /* set reent_lvl */
+ ptr += sizeof(s32);
+ ptr = store_sti_ptr(sti, ptr, save_addr);
+ ptr = store_sti_ptr(sti, ptr, glob_cfg_ext);
- glob_cfg_ext->sti_mem_addr = STI_PTR(sti_mem_addr);
+ store_sti_ptr(sti, &glob_cfg_ext->sti_mem_addr, sti_mem_addr);
sti->glob_cfg = glob_cfg;
@@ -802,10 +833,19 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti,
raw->alt_code_type == ALT_CODE_TYPE_PA_RISC_64
? "and 64 " : "");
- sti->font_unpmv = address + (raw->font_unpmv & 0x03ffffff);
- sti->block_move = address + (raw->block_move & 0x03ffffff);
- sti->init_graph = address + (raw->init_graph & 0x03ffffff);
- sti->inq_conf = address + (raw->inq_conf & 0x03ffffff);
+ if (IS_ENABLED(CONFIG_64BIT) &&
+ raw->alt_code_type == ALT_CODE_TYPE_PA_RISC_64) {
+ sti->do_call64 = 1;
+ sti->font_unpmv = address + (raw->font_unp_addr & 0x03ffffff);
+ sti->block_move = address + (raw->block_move_addr & 0x03ffffff);
+ sti->init_graph = address + (raw->init_graph_addr & 0x03ffffff);
+ sti->inq_conf = address + (raw->inq_conf_addr & 0x03ffffff);
+ } else {
+ sti->font_unpmv = address + (raw->font_unpmv & 0x03ffffff);
+ sti->block_move = address + (raw->block_move & 0x03ffffff);
+ sti->init_graph = address + (raw->init_graph & 0x03ffffff);
+ sti->inq_conf = address + (raw->inq_conf & 0x03ffffff);
+ }
sti->rom = cooked;
sti->rom->raw = raw;
@@ -818,7 +858,13 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti,
sti_font_convert_bytemode(sti, sti->font);
sti_dump_font(sti->font);
+ pr_info(" using %d-bit STI ROM functions\n",
+ (IS_ENABLED(CONFIG_64BIT) && sti->do_call64) ? 64 : 32);
+
sti->sti_mem_request = raw->sti_mem_req;
+ pr_debug(" mem_request = %d, reentsize %d\n",
+ sti->sti_mem_request, raw->reentsize);
+
sti->graphics_id[0] = raw->graphics_id[0];
sti->graphics_id[1] = raw->graphics_id[1];
@@ -876,10 +922,12 @@ static struct sti_struct *sti_try_rom_generic(unsigned long address,
spin_lock_init(&sti->lock);
test_rom:
- /* if we can't read the ROM, bail out early. Not being able
- * to read the hpa is okay, for romless sti */
- if (pdc_add_valid(address))
+ /* pdc_add_valid() works only on 32-bit kernels */
+ if ((!IS_ENABLED(CONFIG_64BIT) ||
+ (boot_cpu_data.pdc.capabilities & PDC_MODEL_OS32)) &&
+ pdc_add_valid(address)) {
goto out_err;
+ }
sig = gsc_readl(address);
@@ -949,7 +997,7 @@ test_rom:
goto out_err;
sti_inq_conf(sti);
- sti_dump_globcfg(sti->glob_cfg, sti->sti_mem_request);
+ sti_dump_globcfg(sti);
sti_dump_outptr(sti);
pr_info(" graphics card name: %s\n",
@@ -1135,14 +1183,15 @@ int sti_call(const struct sti_struct *sti, unsigned long func,
unsigned long _glob_cfg = STI_PTR(glob_cfg);
int ret;
-#ifdef CONFIG_64BIT
/* Check for overflow when using 32bit STI on 64bit kernel. */
- if (WARN_ONCE(_flags>>32 || _inptr>>32 || _outptr>>32 || _glob_cfg>>32,
+ if (WARN_ONCE(IS_ENABLED(CONFIG_64BIT) && !sti->do_call64 &&
+ (upper_32_bits(_flags) || upper_32_bits(_inptr) ||
+ upper_32_bits(_outptr) || upper_32_bits(_glob_cfg)),
"Out of 32bit-range pointers!"))
return -1;
-#endif
- ret = pdc_sti_call(func, _flags, _inptr, _outptr, _glob_cfg);
+ ret = pdc_sti_call(func, _flags, _inptr, _outptr, _glob_cfg,
+ sti->do_call64);
return ret;
}