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;
4141static int num_sti_roms __read_mostly ;
4242static 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 );
138158sti_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 );
170197sti_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 );
198230sti_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
400431static 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
878924test_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