Skip to content

Commit 99ef0c6

Browse files
committed
sticon/parisc: Fix STI console on 64-bit only machines
Fix the STI console to be able to execute either the 64-bit STI ROM code or the 32-bit STI ROM code. This is necessary on 64-bit only machines (e.g. C8000 workstation) which otherwise won't show the STI text console with HP graphic cards like Visualize-FX5/FX10/FXe. Note that when calling 32-bit code from a 64-bit kernel one needs to copy contents on the CPU stack from high memory down below the 4GB limit. Tested-by: John David Anglin <dave.anglin@bell.net> Signed-off-by: Helge Deller <deller@gmx.de>
1 parent ededd9d commit 99ef0c6

3 files changed

Lines changed: 127 additions & 78 deletions

File tree

drivers/video/fbdev/stifb.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@
7171

7272
#include <video/sticore.h>
7373

74-
/* REGION_BASE(fb_info, index) returns the virtual address for region <index> */
74+
/* REGION_BASE(fb_info, index) returns the physical address for region <index> */
7575
#define REGION_BASE(fb_info, index) \
76-
F_EXTEND(fb_info->sti->glob_cfg->region_ptrs[index])
76+
F_EXTEND(fb_info->sti->regions_phys[index])
7777

7878
#define NGLEDEVDEPROM_CRT_REGION 1
7979

drivers/video/sticore.c

Lines changed: 104 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* core code for console driver using HP's STI firmware
55
*
66
* Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
7-
* Copyright (C) 2001-2020 Helge Deller <deller@gmx.de>
7+
* Copyright (C) 2001-2023 Helge Deller <deller@gmx.de>
88
* Copyright (C) 2001-2002 Thomas Bogendoerfer <tsbogend@alpha.franken.de>
99
*
1010
* TODO:
@@ -41,6 +41,26 @@ static struct sti_struct *default_sti __read_mostly;
4141
static int num_sti_roms __read_mostly;
4242
static struct sti_struct *sti_roms[MAX_STI_ROMS] __read_mostly;
4343

44+
static void *store_sti_val(struct sti_struct *sti, void *ptr, unsigned long val)
45+
{
46+
u32 *ptr32 = ptr;
47+
48+
if (IS_ENABLED(CONFIG_64BIT) && sti->do_call64) {
49+
/* used for 64-bit STI ROM */
50+
unsigned long *ptr64 = ptr;
51+
52+
ptr64 = PTR_ALIGN(ptr64, sizeof(void *));
53+
*ptr64++ = val;
54+
return ptr64;
55+
}
56+
57+
/* used for 32-bit STI ROM */
58+
*ptr32++ = val;
59+
return ptr32;
60+
}
61+
62+
#define store_sti_ptr(sti, dest, ptr) \
63+
store_sti_val(sti, dest, STI_PTR(ptr))
4464

4565
/* The colour indices used by STI are
4666
* 0 - Black
@@ -87,7 +107,7 @@ static int sti_init_graph(struct sti_struct *sti)
87107
memset(inptr, 0, sizeof(*inptr));
88108
inptr->text_planes = 3; /* # of text planes (max 3 for STI) */
89109
memset(inptr_ext, 0, sizeof(*inptr_ext));
90-
inptr->ext_ptr = STI_PTR(inptr_ext);
110+
store_sti_ptr(sti, &inptr->ext_ptr, inptr_ext);
91111
outptr->errno = 0;
92112

93113
ret = sti_call(sti, sti->init_graph, &default_init_flags, inptr,
@@ -118,7 +138,7 @@ static void sti_inq_conf(struct sti_struct *sti)
118138
unsigned long flags;
119139
s32 ret;
120140

121-
outptr->ext_ptr = STI_PTR(&sti->sti_data->inq_outptr_ext);
141+
store_sti_ptr(sti, &outptr->ext_ptr, &sti->sti_data->inq_outptr_ext);
122142

123143
do {
124144
spin_lock_irqsave(&sti->lock, flags);
@@ -138,9 +158,9 @@ void
138158
sti_putc(struct sti_struct *sti, int c, int y, int x,
139159
struct sti_cooked_font *font)
140160
{
141-
struct sti_font_inptr *inptr = &sti->sti_data->font_inptr;
161+
struct sti_font_inptr *inptr;
142162
struct sti_font_inptr inptr_default = {
143-
.font_start_addr = STI_PTR(font->raw),
163+
.font_start_addr = (void *)STI_PTR(font->raw),
144164
.index = c_index(sti, c),
145165
.fg_color = c_fg(sti, c),
146166
.bg_color = c_bg(sti, c),
@@ -153,7 +173,14 @@ sti_putc(struct sti_struct *sti, int c, int y, int x,
153173

154174
do {
155175
spin_lock_irqsave(&sti->lock, flags);
156-
*inptr = inptr_default;
176+
inptr = &inptr_default;
177+
if (IS_ENABLED(CONFIG_64BIT) && !sti->do_call64) {
178+
/* copy below 4G if calling 32-bit on LP64 kernel */
179+
inptr = &sti->sti_data->font_inptr;
180+
*inptr = inptr_default;
181+
/* skip first 4 bytes for 32-bit STI call */
182+
inptr = (void *)(((unsigned long)inptr) + sizeof(u32));
183+
}
157184
ret = sti_call(sti, sti->font_unpmv, &default_font_flags,
158185
inptr, outptr, sti->glob_cfg);
159186
spin_unlock_irqrestore(&sti->lock, flags);
@@ -170,7 +197,7 @@ void
170197
sti_set(struct sti_struct *sti, int src_y, int src_x,
171198
int height, int width, u8 color)
172199
{
173-
struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr;
200+
struct sti_blkmv_inptr *inptr;
174201
struct sti_blkmv_inptr inptr_default = {
175202
.fg_color = color,
176203
.bg_color = color,
@@ -187,7 +214,12 @@ sti_set(struct sti_struct *sti, int src_y, int src_x,
187214

188215
do {
189216
spin_lock_irqsave(&sti->lock, flags);
190-
*inptr = inptr_default;
217+
inptr = &inptr_default;
218+
if (IS_ENABLED(CONFIG_64BIT) && !sti->do_call64) {
219+
/* copy below 4G if calling 32-bit on LP64 kernel */
220+
inptr = &sti->sti_data->blkmv_inptr;
221+
*inptr = inptr_default;
222+
}
191223
ret = sti_call(sti, sti->block_move, &clear_blkmv_flags,
192224
inptr, outptr, sti->glob_cfg);
193225
spin_unlock_irqrestore(&sti->lock, flags);
@@ -198,7 +230,7 @@ void
198230
sti_clear(struct sti_struct *sti, int src_y, int src_x,
199231
int height, int width, int c, struct sti_cooked_font *font)
200232
{
201-
struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr;
233+
struct sti_blkmv_inptr *inptr;
202234
struct sti_blkmv_inptr inptr_default = {
203235
.fg_color = c_fg(sti, c),
204236
.bg_color = c_bg(sti, c),
@@ -215,7 +247,12 @@ sti_clear(struct sti_struct *sti, int src_y, int src_x,
215247

216248
do {
217249
spin_lock_irqsave(&sti->lock, flags);
218-
*inptr = inptr_default;
250+
inptr = &inptr_default;
251+
if (IS_ENABLED(CONFIG_64BIT) && !sti->do_call64) {
252+
/* copy below 4G if calling 32-bit on LP64 kernel */
253+
inptr = &sti->sti_data->blkmv_inptr;
254+
*inptr = inptr_default;
255+
}
219256
ret = sti_call(sti, sti->block_move, &clear_blkmv_flags,
220257
inptr, outptr, sti->glob_cfg);
221258
spin_unlock_irqrestore(&sti->lock, flags);
@@ -231,7 +268,7 @@ sti_bmove(struct sti_struct *sti, int src_y, int src_x,
231268
int dst_y, int dst_x, int height, int width,
232269
struct sti_cooked_font *font)
233270
{
234-
struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr;
271+
struct sti_blkmv_inptr *inptr;
235272
struct sti_blkmv_inptr inptr_default = {
236273
.src_x = src_x * font->width,
237274
.src_y = src_y * font->height,
@@ -246,7 +283,12 @@ sti_bmove(struct sti_struct *sti, int src_y, int src_x,
246283

247284
do {
248285
spin_lock_irqsave(&sti->lock, flags);
249-
*inptr = inptr_default;
286+
inptr = &inptr_default;
287+
if (IS_ENABLED(CONFIG_64BIT) && !sti->do_call64) {
288+
/* copy below 4G if calling 32-bit on LP64 kernel */
289+
inptr = &sti->sti_data->blkmv_inptr;
290+
*inptr = inptr_default;
291+
}
250292
ret = sti_call(sti, sti->block_move, &default_blkmv_flags,
251293
inptr, outptr, sti->glob_cfg);
252294
spin_unlock_irqrestore(&sti->lock, flags);
@@ -359,42 +401,31 @@ __setup("sti_font=", sti_font_setup);
359401

360402

361403

362-
static void sti_dump_globcfg(struct sti_glob_cfg *glob_cfg,
363-
unsigned int sti_mem_request)
404+
static void sti_dump_globcfg(struct sti_struct *sti)
364405
{
365-
struct sti_glob_cfg_ext *cfg;
406+
struct sti_glob_cfg *glob_cfg = sti->glob_cfg;
407+
struct sti_glob_cfg_ext *cfg = &sti->sti_data->glob_cfg_ext;
366408

367409
pr_debug("%d text planes\n"
368410
"%4d x %4d screen resolution\n"
369411
"%4d x %4d offscreen\n"
370-
"%4d x %4d layout\n"
371-
"regions at %08x %08x %08x %08x\n"
372-
"regions at %08x %08x %08x %08x\n"
373-
"reent_lvl %d\n"
374-
"save_addr %08x\n",
412+
"%4d x %4d layout\n",
375413
glob_cfg->text_planes,
376414
glob_cfg->onscreen_x, glob_cfg->onscreen_y,
377415
glob_cfg->offscreen_x, glob_cfg->offscreen_y,
378-
glob_cfg->total_x, glob_cfg->total_y,
379-
glob_cfg->region_ptrs[0], glob_cfg->region_ptrs[1],
380-
glob_cfg->region_ptrs[2], glob_cfg->region_ptrs[3],
381-
glob_cfg->region_ptrs[4], glob_cfg->region_ptrs[5],
382-
glob_cfg->region_ptrs[6], glob_cfg->region_ptrs[7],
383-
glob_cfg->reent_lvl,
384-
glob_cfg->save_addr);
416+
glob_cfg->total_x, glob_cfg->total_y);
385417

386418
/* dump extended cfg */
387-
cfg = PTR_STI((unsigned long)glob_cfg->ext_ptr);
388419
pr_debug("monitor %d\n"
389420
"in friendly mode: %d\n"
390421
"power consumption %d watts\n"
391422
"freq ref %d\n"
392-
"sti_mem_addr %08x (size=%d bytes)\n",
423+
"sti_mem_addr %px (size=%d bytes)\n",
393424
cfg->curr_mon,
394425
cfg->friendly_boot,
395426
cfg->power,
396427
cfg->freq_ref,
397-
cfg->sti_mem_addr, sti_mem_request);
428+
cfg->sti_mem_addr, sti->sti_mem_request);
398429
}
399430

400431
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,
414445
{
415446
struct sti_glob_cfg *glob_cfg;
416447
struct sti_glob_cfg_ext *glob_cfg_ext;
417-
void *save_addr;
448+
void *save_addr, *ptr;
418449
void *sti_mem_addr;
419450
int i, size;
420451

@@ -432,9 +463,7 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address,
432463
save_addr = &sti->sti_data->save_addr;
433464
sti_mem_addr = &sti->sti_data->sti_mem_addr;
434465

435-
glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext);
436-
glob_cfg->save_addr = STI_PTR(save_addr);
437-
for (i=0; i<8; i++) {
466+
for (i = 0; i < STI_REGION_MAX; i++) {
438467
unsigned long newhpa, len;
439468

440469
if (sti->pd) {
@@ -457,13 +486,10 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address,
457486
REGION_OFFSET_TO_PHYS(sti->regions[i], newhpa);
458487

459488
len = sti->regions[i].region_desc.length * 4096;
460-
if (len)
461-
glob_cfg->region_ptrs[i] = sti->regions_phys[i];
462489

463-
pr_debug("region #%d: phys %08lx, region_ptr %08x, len=%lukB, "
490+
pr_debug("region #%d: phys %08lx, len=%lukB, "
464491
"btlb=%d, sysonly=%d, cache=%d, last=%d\n",
465-
i, sti->regions_phys[i], glob_cfg->region_ptrs[i],
466-
len/1024,
492+
i, sti->regions_phys[i], len / 1024,
467493
sti->regions[i].region_desc.btlb,
468494
sti->regions[i].region_desc.sys_only,
469495
sti->regions[i].region_desc.cache,
@@ -474,11 +500,16 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address,
474500
break;
475501
}
476502

477-
if (++i<8 && sti->regions[i].region)
478-
pr_warn("future ptr (0x%8x) not yet supported !\n",
479-
sti->regions[i].region);
503+
ptr = &glob_cfg->region_ptrs;
504+
for (i = 0; i < STI_REGION_MAX; i++)
505+
ptr = store_sti_val(sti, ptr, sti->regions_phys[i]);
506+
507+
*(s32 *)ptr = 0; /* set reent_lvl */
508+
ptr += sizeof(s32);
509+
ptr = store_sti_ptr(sti, ptr, save_addr);
510+
ptr = store_sti_ptr(sti, ptr, glob_cfg_ext);
480511

481-
glob_cfg_ext->sti_mem_addr = STI_PTR(sti_mem_addr);
512+
store_sti_ptr(sti, &glob_cfg_ext->sti_mem_addr, sti_mem_addr);
482513

483514
sti->glob_cfg = glob_cfg;
484515

@@ -802,10 +833,19 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti,
802833
raw->alt_code_type == ALT_CODE_TYPE_PA_RISC_64
803834
? "and 64 " : "");
804835

805-
sti->font_unpmv = address + (raw->font_unpmv & 0x03ffffff);
806-
sti->block_move = address + (raw->block_move & 0x03ffffff);
807-
sti->init_graph = address + (raw->init_graph & 0x03ffffff);
808-
sti->inq_conf = address + (raw->inq_conf & 0x03ffffff);
836+
if (IS_ENABLED(CONFIG_64BIT) &&
837+
raw->alt_code_type == ALT_CODE_TYPE_PA_RISC_64) {
838+
sti->do_call64 = 1;
839+
sti->font_unpmv = address + (raw->font_unp_addr & 0x03ffffff);
840+
sti->block_move = address + (raw->block_move_addr & 0x03ffffff);
841+
sti->init_graph = address + (raw->init_graph_addr & 0x03ffffff);
842+
sti->inq_conf = address + (raw->inq_conf_addr & 0x03ffffff);
843+
} else {
844+
sti->font_unpmv = address + (raw->font_unpmv & 0x03ffffff);
845+
sti->block_move = address + (raw->block_move & 0x03ffffff);
846+
sti->init_graph = address + (raw->init_graph & 0x03ffffff);
847+
sti->inq_conf = address + (raw->inq_conf & 0x03ffffff);
848+
}
809849

810850
sti->rom = cooked;
811851
sti->rom->raw = raw;
@@ -818,7 +858,13 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti,
818858
sti_font_convert_bytemode(sti, sti->font);
819859
sti_dump_font(sti->font);
820860

861+
pr_info(" using %d-bit STI ROM functions\n",
862+
(IS_ENABLED(CONFIG_64BIT) && sti->do_call64) ? 64 : 32);
863+
821864
sti->sti_mem_request = raw->sti_mem_req;
865+
pr_debug(" mem_request = %d, reentsize %d\n",
866+
sti->sti_mem_request, raw->reentsize);
867+
822868
sti->graphics_id[0] = raw->graphics_id[0];
823869
sti->graphics_id[1] = raw->graphics_id[1];
824870

@@ -876,10 +922,12 @@ static struct sti_struct *sti_try_rom_generic(unsigned long address,
876922
spin_lock_init(&sti->lock);
877923

878924
test_rom:
879-
/* if we can't read the ROM, bail out early. Not being able
880-
* to read the hpa is okay, for romless sti */
881-
if (pdc_add_valid(address))
925+
/* pdc_add_valid() works only on 32-bit kernels */
926+
if ((!IS_ENABLED(CONFIG_64BIT) ||
927+
(boot_cpu_data.pdc.capabilities & PDC_MODEL_OS32)) &&
928+
pdc_add_valid(address)) {
882929
goto out_err;
930+
}
883931

884932
sig = gsc_readl(address);
885933

@@ -949,7 +997,7 @@ static struct sti_struct *sti_try_rom_generic(unsigned long address,
949997
goto out_err;
950998

951999
sti_inq_conf(sti);
952-
sti_dump_globcfg(sti->glob_cfg, sti->sti_mem_request);
1000+
sti_dump_globcfg(sti);
9531001
sti_dump_outptr(sti);
9541002

9551003
pr_info(" graphics card name: %s\n",
@@ -1135,14 +1183,15 @@ int sti_call(const struct sti_struct *sti, unsigned long func,
11351183
unsigned long _glob_cfg = STI_PTR(glob_cfg);
11361184
int ret;
11371185

1138-
#ifdef CONFIG_64BIT
11391186
/* Check for overflow when using 32bit STI on 64bit kernel. */
1140-
if (WARN_ONCE(_flags>>32 || _inptr>>32 || _outptr>>32 || _glob_cfg>>32,
1187+
if (WARN_ONCE(IS_ENABLED(CONFIG_64BIT) && !sti->do_call64 &&
1188+
(upper_32_bits(_flags) || upper_32_bits(_inptr) ||
1189+
upper_32_bits(_outptr) || upper_32_bits(_glob_cfg)),
11411190
"Out of 32bit-range pointers!"))
11421191
return -1;
1143-
#endif
11441192

1145-
ret = pdc_sti_call(func, _flags, _inptr, _outptr, _glob_cfg, 0);
1193+
ret = pdc_sti_call(func, _flags, _inptr, _outptr, _glob_cfg,
1194+
sti->do_call64);
11461195

11471196
return ret;
11481197
}

0 commit comments

Comments
 (0)