diff options
author | Helge Deller <deller@gmx.de> | 2013-11-06 17:38:59 -0500 |
---|---|---|
committer | Helge Deller <deller@gmx.de> | 2013-11-07 16:46:20 -0500 |
commit | 0219132fe7c26574371232b50db085573f6fbd3f (patch) | |
tree | 48e186aff406365fe45922b9b0bc06e7ef4cc7f9 | |
parent | 1f2048fd8bc4219db821611da305a74f4b72b3c3 (diff) |
parisc: sticon - unbreak on 64bit kernel
STI text console (sticon) was broken on 64bit machines with more than
4GB RAM and this lead in some cases to a kernel crash.
Since sticon uses the 32bit STI API it needs to keep pointers to memory
below 4GB. But on a 64bit kernel some memory regions (e.g. the kernel
stack) might be above 4GB which then may crash the kernel in the STI
functions.
Additionally sticon didn't selected the built-in framebuffer fonts by
default. This is now fixed.
On a side-note: Theoretically we could enhance the sticon driver to
use the 64bit STI API. But - beside the fact that some machines don't
provide a 64bit STI ROM - this would just add complexity.
Signed-off-by: Helge Deller <deller@gmx.de>
Cc: stable@vger.kernel.org # 3.8+
-rw-r--r-- | drivers/video/console/sticore.c | 166 | ||||
-rw-r--r-- | drivers/video/sticore.h | 62 | ||||
-rw-r--r-- | drivers/video/stifb.c | 10 |
3 files changed, 158 insertions, 80 deletions
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c index 35687fd56456..4ad24f2c6472 100644 --- a/drivers/video/console/sticore.c +++ b/drivers/video/console/sticore.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * core code for console driver using HP's STI firmware | 3 | * core code for console driver using HP's STI firmware |
4 | * | 4 | * |
5 | * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> | 5 | * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> |
6 | * Copyright (C) 2001-2003 Helge Deller <deller@gmx.de> | 6 | * Copyright (C) 2001-2013 Helge Deller <deller@gmx.de> |
7 | * Copyright (C) 2001-2002 Thomas Bogendoerfer <tsbogend@alpha.franken.de> | 7 | * Copyright (C) 2001-2002 Thomas Bogendoerfer <tsbogend@alpha.franken.de> |
8 | * | 8 | * |
9 | * TODO: | 9 | * TODO: |
@@ -30,7 +30,7 @@ | |||
30 | 30 | ||
31 | #include "../sticore.h" | 31 | #include "../sticore.h" |
32 | 32 | ||
33 | #define STI_DRIVERVERSION "Version 0.9a" | 33 | #define STI_DRIVERVERSION "Version 0.9b" |
34 | 34 | ||
35 | static struct sti_struct *default_sti __read_mostly; | 35 | static struct sti_struct *default_sti __read_mostly; |
36 | 36 | ||
@@ -73,28 +73,34 @@ static const struct sti_init_flags default_init_flags = { | |||
73 | 73 | ||
74 | static int sti_init_graph(struct sti_struct *sti) | 74 | static int sti_init_graph(struct sti_struct *sti) |
75 | { | 75 | { |
76 | struct sti_init_inptr_ext inptr_ext = { 0, }; | 76 | struct sti_init_inptr *inptr = &sti->sti_data->init_inptr; |
77 | struct sti_init_inptr inptr = { | 77 | struct sti_init_inptr_ext *inptr_ext = &sti->sti_data->init_inptr_ext; |
78 | .text_planes = 3, /* # of text planes (max 3 for STI) */ | 78 | struct sti_init_outptr *outptr = &sti->sti_data->init_outptr; |
79 | .ext_ptr = STI_PTR(&inptr_ext) | ||
80 | }; | ||
81 | struct sti_init_outptr outptr = { 0, }; | ||
82 | unsigned long flags; | 79 | unsigned long flags; |
83 | int ret; | 80 | int ret, err; |
84 | 81 | ||
85 | spin_lock_irqsave(&sti->lock, flags); | 82 | spin_lock_irqsave(&sti->lock, flags); |
86 | 83 | ||
87 | ret = STI_CALL(sti->init_graph, &default_init_flags, &inptr, | 84 | memset(inptr, 0, sizeof(*inptr)); |
88 | &outptr, sti->glob_cfg); | 85 | inptr->text_planes = 3; /* # of text planes (max 3 for STI) */ |
86 | memset(inptr_ext, 0, sizeof(*inptr_ext)); | ||
87 | inptr->ext_ptr = STI_PTR(inptr_ext); | ||
88 | outptr->errno = 0; | ||
89 | |||
90 | ret = sti_call(sti, sti->init_graph, &default_init_flags, inptr, | ||
91 | outptr, sti->glob_cfg); | ||
92 | |||
93 | if (ret >= 0) | ||
94 | sti->text_planes = outptr->text_planes; | ||
95 | err = outptr->errno; | ||
89 | 96 | ||
90 | spin_unlock_irqrestore(&sti->lock, flags); | 97 | spin_unlock_irqrestore(&sti->lock, flags); |
91 | 98 | ||
92 | if (ret < 0) { | 99 | if (ret < 0) { |
93 | printk(KERN_ERR "STI init_graph failed (ret %d, errno %d)\n",ret,outptr.errno); | 100 | pr_err("STI init_graph failed (ret %d, errno %d)\n", ret, err); |
94 | return -1; | 101 | return -1; |
95 | } | 102 | } |
96 | 103 | ||
97 | sti->text_planes = outptr.text_planes; | ||
98 | return 0; | 104 | return 0; |
99 | } | 105 | } |
100 | 106 | ||
@@ -104,16 +110,18 @@ static const struct sti_conf_flags default_conf_flags = { | |||
104 | 110 | ||
105 | static void sti_inq_conf(struct sti_struct *sti) | 111 | static void sti_inq_conf(struct sti_struct *sti) |
106 | { | 112 | { |
107 | struct sti_conf_inptr inptr = { 0, }; | 113 | struct sti_conf_inptr *inptr = &sti->sti_data->inq_inptr; |
114 | struct sti_conf_outptr *outptr = &sti->sti_data->inq_outptr; | ||
108 | unsigned long flags; | 115 | unsigned long flags; |
109 | s32 ret; | 116 | s32 ret; |
110 | 117 | ||
111 | sti->outptr.ext_ptr = STI_PTR(&sti->outptr_ext); | 118 | outptr->ext_ptr = STI_PTR(&sti->sti_data->inq_outptr_ext); |
112 | 119 | ||
113 | do { | 120 | do { |
114 | spin_lock_irqsave(&sti->lock, flags); | 121 | spin_lock_irqsave(&sti->lock, flags); |
115 | ret = STI_CALL(sti->inq_conf, &default_conf_flags, | 122 | memset(inptr, 0, sizeof(*inptr)); |
116 | &inptr, &sti->outptr, sti->glob_cfg); | 123 | ret = sti_call(sti, sti->inq_conf, &default_conf_flags, |
124 | inptr, outptr, sti->glob_cfg); | ||
117 | spin_unlock_irqrestore(&sti->lock, flags); | 125 | spin_unlock_irqrestore(&sti->lock, flags); |
118 | } while (ret == 1); | 126 | } while (ret == 1); |
119 | } | 127 | } |
@@ -126,7 +134,8 @@ static const struct sti_font_flags default_font_flags = { | |||
126 | void | 134 | void |
127 | sti_putc(struct sti_struct *sti, int c, int y, int x) | 135 | sti_putc(struct sti_struct *sti, int c, int y, int x) |
128 | { | 136 | { |
129 | struct sti_font_inptr inptr = { | 137 | struct sti_font_inptr *inptr = &sti->sti_data->font_inptr; |
138 | struct sti_font_inptr inptr_default = { | ||
130 | .font_start_addr= STI_PTR(sti->font->raw), | 139 | .font_start_addr= STI_PTR(sti->font->raw), |
131 | .index = c_index(sti, c), | 140 | .index = c_index(sti, c), |
132 | .fg_color = c_fg(sti, c), | 141 | .fg_color = c_fg(sti, c), |
@@ -134,14 +143,15 @@ sti_putc(struct sti_struct *sti, int c, int y, int x) | |||
134 | .dest_x = x * sti->font_width, | 143 | .dest_x = x * sti->font_width, |
135 | .dest_y = y * sti->font_height, | 144 | .dest_y = y * sti->font_height, |
136 | }; | 145 | }; |
137 | struct sti_font_outptr outptr = { 0, }; | 146 | struct sti_font_outptr *outptr = &sti->sti_data->font_outptr; |
138 | s32 ret; | 147 | s32 ret; |
139 | unsigned long flags; | 148 | unsigned long flags; |
140 | 149 | ||
141 | do { | 150 | do { |
142 | spin_lock_irqsave(&sti->lock, flags); | 151 | spin_lock_irqsave(&sti->lock, flags); |
143 | ret = STI_CALL(sti->font_unpmv, &default_font_flags, | 152 | *inptr = inptr_default; |
144 | &inptr, &outptr, sti->glob_cfg); | 153 | ret = sti_call(sti, sti->font_unpmv, &default_font_flags, |
154 | inptr, outptr, sti->glob_cfg); | ||
145 | spin_unlock_irqrestore(&sti->lock, flags); | 155 | spin_unlock_irqrestore(&sti->lock, flags); |
146 | } while (ret == 1); | 156 | } while (ret == 1); |
147 | } | 157 | } |
@@ -156,7 +166,8 @@ void | |||
156 | sti_set(struct sti_struct *sti, int src_y, int src_x, | 166 | sti_set(struct sti_struct *sti, int src_y, int src_x, |
157 | int height, int width, u8 color) | 167 | int height, int width, u8 color) |
158 | { | 168 | { |
159 | struct sti_blkmv_inptr inptr = { | 169 | struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr; |
170 | struct sti_blkmv_inptr inptr_default = { | ||
160 | .fg_color = color, | 171 | .fg_color = color, |
161 | .bg_color = color, | 172 | .bg_color = color, |
162 | .src_x = src_x, | 173 | .src_x = src_x, |
@@ -166,14 +177,15 @@ sti_set(struct sti_struct *sti, int src_y, int src_x, | |||
166 | .width = width, | 177 | .width = width, |
167 | .height = height, | 178 | .height = height, |
168 | }; | 179 | }; |
169 | struct sti_blkmv_outptr outptr = { 0, }; | 180 | struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr; |
170 | s32 ret; | 181 | s32 ret; |
171 | unsigned long flags; | 182 | unsigned long flags; |
172 | 183 | ||
173 | do { | 184 | do { |
174 | spin_lock_irqsave(&sti->lock, flags); | 185 | spin_lock_irqsave(&sti->lock, flags); |
175 | ret = STI_CALL(sti->block_move, &clear_blkmv_flags, | 186 | *inptr = inptr_default; |
176 | &inptr, &outptr, sti->glob_cfg); | 187 | ret = sti_call(sti, sti->block_move, &clear_blkmv_flags, |
188 | inptr, outptr, sti->glob_cfg); | ||
177 | spin_unlock_irqrestore(&sti->lock, flags); | 189 | spin_unlock_irqrestore(&sti->lock, flags); |
178 | } while (ret == 1); | 190 | } while (ret == 1); |
179 | } | 191 | } |
@@ -182,7 +194,8 @@ void | |||
182 | sti_clear(struct sti_struct *sti, int src_y, int src_x, | 194 | sti_clear(struct sti_struct *sti, int src_y, int src_x, |
183 | int height, int width, int c) | 195 | int height, int width, int c) |
184 | { | 196 | { |
185 | struct sti_blkmv_inptr inptr = { | 197 | struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr; |
198 | struct sti_blkmv_inptr inptr_default = { | ||
186 | .fg_color = c_fg(sti, c), | 199 | .fg_color = c_fg(sti, c), |
187 | .bg_color = c_bg(sti, c), | 200 | .bg_color = c_bg(sti, c), |
188 | .src_x = src_x * sti->font_width, | 201 | .src_x = src_x * sti->font_width, |
@@ -192,14 +205,15 @@ sti_clear(struct sti_struct *sti, int src_y, int src_x, | |||
192 | .width = width * sti->font_width, | 205 | .width = width * sti->font_width, |
193 | .height = height* sti->font_height, | 206 | .height = height* sti->font_height, |
194 | }; | 207 | }; |
195 | struct sti_blkmv_outptr outptr = { 0, }; | 208 | struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr; |
196 | s32 ret; | 209 | s32 ret; |
197 | unsigned long flags; | 210 | unsigned long flags; |
198 | 211 | ||
199 | do { | 212 | do { |
200 | spin_lock_irqsave(&sti->lock, flags); | 213 | spin_lock_irqsave(&sti->lock, flags); |
201 | ret = STI_CALL(sti->block_move, &clear_blkmv_flags, | 214 | *inptr = inptr_default; |
202 | &inptr, &outptr, sti->glob_cfg); | 215 | ret = sti_call(sti, sti->block_move, &clear_blkmv_flags, |
216 | inptr, outptr, sti->glob_cfg); | ||
203 | spin_unlock_irqrestore(&sti->lock, flags); | 217 | spin_unlock_irqrestore(&sti->lock, flags); |
204 | } while (ret == 1); | 218 | } while (ret == 1); |
205 | } | 219 | } |
@@ -212,7 +226,8 @@ void | |||
212 | sti_bmove(struct sti_struct *sti, int src_y, int src_x, | 226 | sti_bmove(struct sti_struct *sti, int src_y, int src_x, |
213 | int dst_y, int dst_x, int height, int width) | 227 | int dst_y, int dst_x, int height, int width) |
214 | { | 228 | { |
215 | struct sti_blkmv_inptr inptr = { | 229 | struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr; |
230 | struct sti_blkmv_inptr inptr_default = { | ||
216 | .src_x = src_x * sti->font_width, | 231 | .src_x = src_x * sti->font_width, |
217 | .src_y = src_y * sti->font_height, | 232 | .src_y = src_y * sti->font_height, |
218 | .dest_x = dst_x * sti->font_width, | 233 | .dest_x = dst_x * sti->font_width, |
@@ -220,14 +235,15 @@ sti_bmove(struct sti_struct *sti, int src_y, int src_x, | |||
220 | .width = width * sti->font_width, | 235 | .width = width * sti->font_width, |
221 | .height = height* sti->font_height, | 236 | .height = height* sti->font_height, |
222 | }; | 237 | }; |
223 | struct sti_blkmv_outptr outptr = { 0, }; | 238 | struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr; |
224 | s32 ret; | 239 | s32 ret; |
225 | unsigned long flags; | 240 | unsigned long flags; |
226 | 241 | ||
227 | do { | 242 | do { |
228 | spin_lock_irqsave(&sti->lock, flags); | 243 | spin_lock_irqsave(&sti->lock, flags); |
229 | ret = STI_CALL(sti->block_move, &default_blkmv_flags, | 244 | *inptr = inptr_default; |
230 | &inptr, &outptr, sti->glob_cfg); | 245 | ret = sti_call(sti, sti->block_move, &default_blkmv_flags, |
246 | inptr, outptr, sti->glob_cfg); | ||
231 | spin_unlock_irqrestore(&sti->lock, flags); | 247 | spin_unlock_irqrestore(&sti->lock, flags); |
232 | } while (ret == 1); | 248 | } while (ret == 1); |
233 | } | 249 | } |
@@ -284,7 +300,7 @@ __setup("sti=", sti_setup); | |||
284 | 300 | ||
285 | 301 | ||
286 | 302 | ||
287 | static char *font_name[MAX_STI_ROMS] = { "VGA8x16", }; | 303 | static char *font_name[MAX_STI_ROMS]; |
288 | static int font_index[MAX_STI_ROMS], | 304 | static int font_index[MAX_STI_ROMS], |
289 | font_height[MAX_STI_ROMS], | 305 | font_height[MAX_STI_ROMS], |
290 | font_width[MAX_STI_ROMS]; | 306 | font_width[MAX_STI_ROMS]; |
@@ -389,10 +405,10 @@ static void sti_dump_outptr(struct sti_struct *sti) | |||
389 | "%d used bits\n" | 405 | "%d used bits\n" |
390 | "%d planes\n" | 406 | "%d planes\n" |
391 | "attributes %08x\n", | 407 | "attributes %08x\n", |
392 | sti->outptr.bits_per_pixel, | 408 | sti->sti_data->inq_outptr.bits_per_pixel, |
393 | sti->outptr.bits_used, | 409 | sti->sti_data->inq_outptr.bits_used, |
394 | sti->outptr.planes, | 410 | sti->sti_data->inq_outptr.planes, |
395 | sti->outptr.attributes)); | 411 | sti->sti_data->inq_outptr.attributes)); |
396 | } | 412 | } |
397 | 413 | ||
398 | static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, | 414 | static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, |
@@ -402,24 +418,21 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, | |||
402 | struct sti_glob_cfg_ext *glob_cfg_ext; | 418 | struct sti_glob_cfg_ext *glob_cfg_ext; |
403 | void *save_addr; | 419 | void *save_addr; |
404 | void *sti_mem_addr; | 420 | void *sti_mem_addr; |
405 | const int save_addr_size = 1024; /* XXX */ | 421 | int i, size; |
406 | int i; | ||
407 | 422 | ||
408 | if (!sti->sti_mem_request) | 423 | if (sti->sti_mem_request < 256) |
409 | sti->sti_mem_request = 256; /* STI default */ | 424 | sti->sti_mem_request = 256; /* STI default */ |
410 | 425 | ||
411 | glob_cfg = kzalloc(sizeof(*sti->glob_cfg), GFP_KERNEL); | 426 | size = sizeof(struct sti_all_data) + sti->sti_mem_request - 256; |
412 | glob_cfg_ext = kzalloc(sizeof(*glob_cfg_ext), GFP_KERNEL); | ||
413 | save_addr = kzalloc(save_addr_size, GFP_KERNEL); | ||
414 | sti_mem_addr = kzalloc(sti->sti_mem_request, GFP_KERNEL); | ||
415 | 427 | ||
416 | if (!(glob_cfg && glob_cfg_ext && save_addr && sti_mem_addr)) { | 428 | sti->sti_data = kzalloc(size, STI_LOWMEM); |
417 | kfree(glob_cfg); | 429 | if (!sti->sti_data) |
418 | kfree(glob_cfg_ext); | ||
419 | kfree(save_addr); | ||
420 | kfree(sti_mem_addr); | ||
421 | return -ENOMEM; | 430 | return -ENOMEM; |
422 | } | 431 | |
432 | glob_cfg = &sti->sti_data->glob_cfg; | ||
433 | glob_cfg_ext = &sti->sti_data->glob_cfg_ext; | ||
434 | save_addr = &sti->sti_data->save_addr; | ||
435 | sti_mem_addr = &sti->sti_data->sti_mem_addr; | ||
423 | 436 | ||
424 | glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext); | 437 | glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext); |
425 | glob_cfg->save_addr = STI_PTR(save_addr); | 438 | glob_cfg->save_addr = STI_PTR(save_addr); |
@@ -475,32 +488,31 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, | |||
475 | return 0; | 488 | return 0; |
476 | } | 489 | } |
477 | 490 | ||
478 | #ifdef CONFIG_FB | 491 | #ifdef CONFIG_FONTS |
479 | static struct sti_cooked_font * | 492 | static struct sti_cooked_font * |
480 | sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) | 493 | sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) |
481 | { | 494 | { |
482 | const struct font_desc *fbfont; | 495 | const struct font_desc *fbfont = NULL; |
483 | unsigned int size, bpc; | 496 | unsigned int size, bpc; |
484 | void *dest; | 497 | void *dest; |
485 | struct sti_rom_font *nf; | 498 | struct sti_rom_font *nf; |
486 | struct sti_cooked_font *cooked_font; | 499 | struct sti_cooked_font *cooked_font; |
487 | 500 | ||
488 | if (!fbfont_name || !strlen(fbfont_name)) | 501 | if (fbfont_name && strlen(fbfont_name)) |
489 | return NULL; | 502 | fbfont = find_font(fbfont_name); |
490 | fbfont = find_font(fbfont_name); | ||
491 | if (!fbfont) | 503 | if (!fbfont) |
492 | fbfont = get_default_font(1024,768, ~(u32)0, ~(u32)0); | 504 | fbfont = get_default_font(1024,768, ~(u32)0, ~(u32)0); |
493 | if (!fbfont) | 505 | if (!fbfont) |
494 | return NULL; | 506 | return NULL; |
495 | 507 | ||
496 | DPRINTK((KERN_DEBUG "selected %dx%d fb-font %s\n", | 508 | pr_info("STI selected %dx%d framebuffer font %s for sticon\n", |
497 | fbfont->width, fbfont->height, fbfont->name)); | 509 | fbfont->width, fbfont->height, fbfont->name); |
498 | 510 | ||
499 | bpc = ((fbfont->width+7)/8) * fbfont->height; | 511 | bpc = ((fbfont->width+7)/8) * fbfont->height; |
500 | size = bpc * 256; | 512 | size = bpc * 256; |
501 | size += sizeof(struct sti_rom_font); | 513 | size += sizeof(struct sti_rom_font); |
502 | 514 | ||
503 | nf = kzalloc(size, GFP_KERNEL); | 515 | nf = kzalloc(size, STI_LOWMEM); |
504 | if (!nf) | 516 | if (!nf) |
505 | return NULL; | 517 | return NULL; |
506 | 518 | ||
@@ -637,7 +649,7 @@ static void *sti_bmode_font_raw(struct sti_cooked_font *f) | |||
637 | unsigned char *n, *p, *q; | 649 | unsigned char *n, *p, *q; |
638 | int size = f->raw->bytes_per_char*256+sizeof(struct sti_rom_font); | 650 | int size = f->raw->bytes_per_char*256+sizeof(struct sti_rom_font); |
639 | 651 | ||
640 | n = kzalloc (4*size, GFP_KERNEL); | 652 | n = kzalloc(4*size, STI_LOWMEM); |
641 | if (!n) | 653 | if (!n) |
642 | return NULL; | 654 | return NULL; |
643 | p = n + 3; | 655 | p = n + 3; |
@@ -673,7 +685,7 @@ static struct sti_rom *sti_get_bmode_rom (unsigned long address) | |||
673 | sti_bmode_rom_copy(address + BMODE_LAST_ADDR_OFFS, sizeof(size), &size); | 685 | sti_bmode_rom_copy(address + BMODE_LAST_ADDR_OFFS, sizeof(size), &size); |
674 | 686 | ||
675 | size = (size+3) / 4; | 687 | size = (size+3) / 4; |
676 | raw = kmalloc(size, GFP_KERNEL); | 688 | raw = kmalloc(size, STI_LOWMEM); |
677 | if (raw) { | 689 | if (raw) { |
678 | sti_bmode_rom_copy(address, size, raw); | 690 | sti_bmode_rom_copy(address, size, raw); |
679 | memmove (&raw->res004, &raw->type[0], 0x3c); | 691 | memmove (&raw->res004, &raw->type[0], 0x3c); |
@@ -707,7 +719,7 @@ static struct sti_rom *sti_get_wmode_rom(unsigned long address) | |||
707 | /* read the ROM size directly from the struct in ROM */ | 719 | /* read the ROM size directly from the struct in ROM */ |
708 | size = gsc_readl(address + offsetof(struct sti_rom,last_addr)); | 720 | size = gsc_readl(address + offsetof(struct sti_rom,last_addr)); |
709 | 721 | ||
710 | raw = kmalloc(size, GFP_KERNEL); | 722 | raw = kmalloc(size, STI_LOWMEM); |
711 | if (raw) | 723 | if (raw) |
712 | sti_rom_copy(address, size, raw); | 724 | sti_rom_copy(address, size, raw); |
713 | 725 | ||
@@ -743,6 +755,10 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti, | |||
743 | 755 | ||
744 | address = (unsigned long) STI_PTR(raw); | 756 | address = (unsigned long) STI_PTR(raw); |
745 | 757 | ||
758 | pr_info("STI ROM supports 32 %sbit firmware functions.\n", | ||
759 | raw->alt_code_type == ALT_CODE_TYPE_PA_RISC_64 | ||
760 | ? "and 64 " : ""); | ||
761 | |||
746 | sti->font_unpmv = address + (raw->font_unpmv & 0x03ffffff); | 762 | sti->font_unpmv = address + (raw->font_unpmv & 0x03ffffff); |
747 | sti->block_move = address + (raw->block_move & 0x03ffffff); | 763 | sti->block_move = address + (raw->block_move & 0x03ffffff); |
748 | sti->init_graph = address + (raw->init_graph & 0x03ffffff); | 764 | sti->init_graph = address + (raw->init_graph & 0x03ffffff); |
@@ -901,7 +917,8 @@ test_rom: | |||
901 | sti_dump_globcfg(sti->glob_cfg, sti->sti_mem_request); | 917 | sti_dump_globcfg(sti->glob_cfg, sti->sti_mem_request); |
902 | sti_dump_outptr(sti); | 918 | sti_dump_outptr(sti); |
903 | 919 | ||
904 | printk(KERN_INFO " graphics card name: %s\n", sti->outptr.dev_name ); | 920 | pr_info(" graphics card name: %s\n", |
921 | sti->sti_data->inq_outptr.dev_name); | ||
905 | 922 | ||
906 | sti_roms[num_sti_roms] = sti; | 923 | sti_roms[num_sti_roms] = sti; |
907 | num_sti_roms++; | 924 | num_sti_roms++; |
@@ -1073,6 +1090,29 @@ struct sti_struct * sti_get_rom(unsigned int index) | |||
1073 | } | 1090 | } |
1074 | EXPORT_SYMBOL(sti_get_rom); | 1091 | EXPORT_SYMBOL(sti_get_rom); |
1075 | 1092 | ||
1093 | |||
1094 | int sti_call(const struct sti_struct *sti, unsigned long func, | ||
1095 | const void *flags, void *inptr, void *outptr, | ||
1096 | struct sti_glob_cfg *glob_cfg) | ||
1097 | { | ||
1098 | unsigned long _flags = STI_PTR(flags); | ||
1099 | unsigned long _inptr = STI_PTR(inptr); | ||
1100 | unsigned long _outptr = STI_PTR(outptr); | ||
1101 | unsigned long _glob_cfg = STI_PTR(glob_cfg); | ||
1102 | int ret; | ||
1103 | |||
1104 | #ifdef CONFIG_64BIT | ||
1105 | /* Check for overflow when using 32bit STI on 64bit kernel. */ | ||
1106 | if (WARN_ONCE(_flags>>32 || _inptr>>32 || _outptr>>32 || _glob_cfg>>32, | ||
1107 | "Out of 32bit-range pointers!")) | ||
1108 | return -1; | ||
1109 | #endif | ||
1110 | |||
1111 | ret = pdc_sti_call(func, _flags, _inptr, _outptr, _glob_cfg); | ||
1112 | |||
1113 | return ret; | ||
1114 | } | ||
1115 | |||
1076 | MODULE_AUTHOR("Philipp Rumpf, Helge Deller, Thomas Bogendoerfer"); | 1116 | MODULE_AUTHOR("Philipp Rumpf, Helge Deller, Thomas Bogendoerfer"); |
1077 | MODULE_DESCRIPTION("Core STI driver for HP's NGLE series graphics cards in HP PARISC machines"); | 1117 | MODULE_DESCRIPTION("Core STI driver for HP's NGLE series graphics cards in HP PARISC machines"); |
1078 | MODULE_LICENSE("GPL v2"); | 1118 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/video/sticore.h b/drivers/video/sticore.h index addf7b615ef8..af1619536ac8 100644 --- a/drivers/video/sticore.h +++ b/drivers/video/sticore.h | |||
@@ -18,6 +18,9 @@ | |||
18 | #define STI_FONT_HPROMAN8 1 | 18 | #define STI_FONT_HPROMAN8 1 |
19 | #define STI_FONT_KANA8 2 | 19 | #define STI_FONT_KANA8 2 |
20 | 20 | ||
21 | #define ALT_CODE_TYPE_UNKNOWN 0x00 /* alt code type values */ | ||
22 | #define ALT_CODE_TYPE_PA_RISC_64 0x01 | ||
23 | |||
21 | /* The latency of the STI functions cannot really be reduced by setting | 24 | /* The latency of the STI functions cannot really be reduced by setting |
22 | * this to 0; STI doesn't seem to be designed to allow calling a different | 25 | * this to 0; STI doesn't seem to be designed to allow calling a different |
23 | * function (or the same function with different arguments) after a | 26 | * function (or the same function with different arguments) after a |
@@ -40,14 +43,6 @@ | |||
40 | 43 | ||
41 | #define STI_PTR(p) ( virt_to_phys(p) ) | 44 | #define STI_PTR(p) ( virt_to_phys(p) ) |
42 | #define PTR_STI(p) ( phys_to_virt((unsigned long)p) ) | 45 | #define PTR_STI(p) ( phys_to_virt((unsigned long)p) ) |
43 | #define STI_CALL(func, flags, inptr, outptr, glob_cfg) \ | ||
44 | ({ \ | ||
45 | pdc_sti_call( func, STI_PTR(flags), \ | ||
46 | STI_PTR(inptr), \ | ||
47 | STI_PTR(outptr), \ | ||
48 | STI_PTR(glob_cfg)); \ | ||
49 | }) | ||
50 | |||
51 | 46 | ||
52 | #define sti_onscreen_x(sti) (sti->glob_cfg->onscreen_x) | 47 | #define sti_onscreen_x(sti) (sti->glob_cfg->onscreen_x) |
53 | #define sti_onscreen_y(sti) (sti->glob_cfg->onscreen_y) | 48 | #define sti_onscreen_y(sti) (sti->glob_cfg->onscreen_y) |
@@ -56,6 +51,12 @@ | |||
56 | #define sti_font_x(sti) (PTR_STI(sti->font)->width) | 51 | #define sti_font_x(sti) (PTR_STI(sti->font)->width) |
57 | #define sti_font_y(sti) (PTR_STI(sti->font)->height) | 52 | #define sti_font_y(sti) (PTR_STI(sti->font)->height) |
58 | 53 | ||
54 | #ifdef CONFIG_64BIT | ||
55 | #define STI_LOWMEM (GFP_KERNEL | GFP_DMA) | ||
56 | #else | ||
57 | #define STI_LOWMEM (GFP_KERNEL) | ||
58 | #endif | ||
59 | |||
59 | 60 | ||
60 | /* STI function configuration structs */ | 61 | /* STI function configuration structs */ |
61 | 62 | ||
@@ -306,6 +307,34 @@ struct sti_blkmv_outptr { | |||
306 | }; | 307 | }; |
307 | 308 | ||
308 | 309 | ||
310 | /* sti_all_data is an internal struct which needs to be allocated in | ||
311 | * low memory (< 4GB) if STI is used with 32bit STI on a 64bit kernel */ | ||
312 | |||
313 | struct sti_all_data { | ||
314 | struct sti_glob_cfg glob_cfg; | ||
315 | struct sti_glob_cfg_ext glob_cfg_ext; | ||
316 | |||
317 | struct sti_conf_inptr inq_inptr; | ||
318 | struct sti_conf_outptr inq_outptr; /* configuration */ | ||
319 | struct sti_conf_outptr_ext inq_outptr_ext; | ||
320 | |||
321 | struct sti_init_inptr_ext init_inptr_ext; | ||
322 | struct sti_init_inptr init_inptr; | ||
323 | struct sti_init_outptr init_outptr; | ||
324 | |||
325 | struct sti_blkmv_inptr blkmv_inptr; | ||
326 | struct sti_blkmv_outptr blkmv_outptr; | ||
327 | |||
328 | struct sti_font_inptr font_inptr; | ||
329 | struct sti_font_outptr font_outptr; | ||
330 | |||
331 | /* leave as last entries */ | ||
332 | unsigned long save_addr[1024 / sizeof(unsigned long)]; | ||
333 | /* min 256 bytes which is STI default, max sti->sti_mem_request */ | ||
334 | unsigned long sti_mem_addr[256 / sizeof(unsigned long)]; | ||
335 | /* do not add something below here ! */ | ||
336 | }; | ||
337 | |||
309 | /* internal generic STI struct */ | 338 | /* internal generic STI struct */ |
310 | 339 | ||
311 | struct sti_struct { | 340 | struct sti_struct { |
@@ -330,11 +359,9 @@ struct sti_struct { | |||
330 | region_t regions[STI_REGION_MAX]; | 359 | region_t regions[STI_REGION_MAX]; |
331 | unsigned long regions_phys[STI_REGION_MAX]; | 360 | unsigned long regions_phys[STI_REGION_MAX]; |
332 | 361 | ||
333 | struct sti_glob_cfg *glob_cfg; | 362 | struct sti_glob_cfg *glob_cfg; /* points into sti_all_data */ |
334 | struct sti_cooked_font *font; /* ptr to selected font (cooked) */ | ||
335 | 363 | ||
336 | struct sti_conf_outptr outptr; /* configuration */ | 364 | struct sti_cooked_font *font; /* ptr to selected font (cooked) */ |
337 | struct sti_conf_outptr_ext outptr_ext; | ||
338 | 365 | ||
339 | struct pci_dev *pd; | 366 | struct pci_dev *pd; |
340 | 367 | ||
@@ -343,6 +370,9 @@ struct sti_struct { | |||
343 | 370 | ||
344 | /* pointer to the fb_info where this STI device is used */ | 371 | /* pointer to the fb_info where this STI device is used */ |
345 | struct fb_info *info; | 372 | struct fb_info *info; |
373 | |||
374 | /* pointer to all internal data */ | ||
375 | struct sti_all_data *sti_data; | ||
346 | }; | 376 | }; |
347 | 377 | ||
348 | 378 | ||
@@ -350,6 +380,14 @@ struct sti_struct { | |||
350 | 380 | ||
351 | struct sti_struct *sti_get_rom(unsigned int index); /* 0: default sti */ | 381 | struct sti_struct *sti_get_rom(unsigned int index); /* 0: default sti */ |
352 | 382 | ||
383 | |||
384 | /* sticore main function to call STI firmware */ | ||
385 | |||
386 | int sti_call(const struct sti_struct *sti, unsigned long func, | ||
387 | const void *flags, void *inptr, void *outptr, | ||
388 | struct sti_glob_cfg *glob_cfg); | ||
389 | |||
390 | |||
353 | /* functions to call the STI ROM directly */ | 391 | /* functions to call the STI ROM directly */ |
354 | 392 | ||
355 | void sti_putc(struct sti_struct *sti, int c, int y, int x); | 393 | void sti_putc(struct sti_struct *sti, int c, int y, int x); |
diff --git a/drivers/video/stifb.c b/drivers/video/stifb.c index 876648e15e9d..019a1feef995 100644 --- a/drivers/video/stifb.c +++ b/drivers/video/stifb.c | |||
@@ -1101,6 +1101,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) | |||
1101 | var = &info->var; | 1101 | var = &info->var; |
1102 | 1102 | ||
1103 | fb->sti = sti; | 1103 | fb->sti = sti; |
1104 | dev_name = sti->sti_data->inq_outptr.dev_name; | ||
1104 | /* store upper 32bits of the graphics id */ | 1105 | /* store upper 32bits of the graphics id */ |
1105 | fb->id = fb->sti->graphics_id[0]; | 1106 | fb->id = fb->sti->graphics_id[0]; |
1106 | 1107 | ||
@@ -1114,11 +1115,11 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) | |||
1114 | Since this driver only supports standard mode, we check | 1115 | Since this driver only supports standard mode, we check |
1115 | if the device name contains the string "DX" and tell the | 1116 | if the device name contains the string "DX" and tell the |
1116 | user how to reconfigure the card. */ | 1117 | user how to reconfigure the card. */ |
1117 | if (strstr(sti->outptr.dev_name, "DX")) { | 1118 | if (strstr(dev_name, "DX")) { |
1118 | printk(KERN_WARNING | 1119 | printk(KERN_WARNING |
1119 | "WARNING: stifb framebuffer driver does not support '%s' in double-buffer mode.\n" | 1120 | "WARNING: stifb framebuffer driver does not support '%s' in double-buffer mode.\n" |
1120 | "WARNING: Please disable the double-buffer mode in IPL menu (the PARISC-BIOS).\n", | 1121 | "WARNING: Please disable the double-buffer mode in IPL menu (the PARISC-BIOS).\n", |
1121 | sti->outptr.dev_name); | 1122 | dev_name); |
1122 | goto out_err0; | 1123 | goto out_err0; |
1123 | } | 1124 | } |
1124 | /* fall though */ | 1125 | /* fall though */ |
@@ -1130,7 +1131,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) | |||
1130 | break; | 1131 | break; |
1131 | default: | 1132 | default: |
1132 | printk(KERN_WARNING "stifb: '%s' (id: 0x%08x) not supported.\n", | 1133 | printk(KERN_WARNING "stifb: '%s' (id: 0x%08x) not supported.\n", |
1133 | sti->outptr.dev_name, fb->id); | 1134 | dev_name, fb->id); |
1134 | goto out_err0; | 1135 | goto out_err0; |
1135 | } | 1136 | } |
1136 | 1137 | ||
@@ -1154,7 +1155,6 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) | |||
1154 | fb->id = S9000_ID_A1659A; | 1155 | fb->id = S9000_ID_A1659A; |
1155 | break; | 1156 | break; |
1156 | case S9000_ID_TIMBER: /* HP9000/710 Any (may be a grayscale device) */ | 1157 | case S9000_ID_TIMBER: /* HP9000/710 Any (may be a grayscale device) */ |
1157 | dev_name = fb->sti->outptr.dev_name; | ||
1158 | if (strstr(dev_name, "GRAYSCALE") || | 1158 | if (strstr(dev_name, "GRAYSCALE") || |
1159 | strstr(dev_name, "Grayscale") || | 1159 | strstr(dev_name, "Grayscale") || |
1160 | strstr(dev_name, "grayscale")) | 1160 | strstr(dev_name, "grayscale")) |
@@ -1290,7 +1290,7 @@ static int __init stifb_init_fb(struct sti_struct *sti, int bpp_pref) | |||
1290 | var->xres, | 1290 | var->xres, |
1291 | var->yres, | 1291 | var->yres, |
1292 | var->bits_per_pixel, | 1292 | var->bits_per_pixel, |
1293 | sti->outptr.dev_name, | 1293 | dev_name, |
1294 | fb->id, | 1294 | fb->id, |
1295 | fix->mmio_start); | 1295 | fix->mmio_start); |
1296 | 1296 | ||