1 #include <linux/config.h>
2 #include <linux/module.h>
3 #include <linux/types.h>
4 #include <linux/kernel.h>
5 #include <linux/malloc.h>
6 #include <linux/init.h>
8 #include <asm/uaccess.h>
9 #include <asm/pgalloc.h>
14 struct sti_struct default_sti
= {
18 static struct sti_font_flags default_font_flags
= {
22 /* The colour indices used by STI are
32 * So we have the same colours as VGA (basically one bit each for R, G, B),
33 * but have to translate them, anyway. */
35 static u8 col_trans
[8] = {
40 #define c_fg(sti, c) col_trans[((c>> 8) & 7)]
41 #define c_bg(sti, c) col_trans[((c>>11) & 7)]
42 #define c_index(sti, c) (c&0xff)
44 static struct sti_init_flags default_init_flags
= {
45 STI_WAIT
, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, NULL
49 sti_init_graph(struct sti_struct
*sti
)
51 struct sti_init_inptr_ext inptr_ext
= {
54 struct sti_init_inptr inptr
= {
55 3, STI_PTR(&inptr_ext
)
57 struct sti_init_outptr outptr
= { 0 };
61 spin_lock_irqsave(&sti
->lock
, flags
);
63 ret
= STI_CALL(sti
->init_graph
, &default_init_flags
, &inptr
,
64 &outptr
, sti
->glob_cfg
);
66 spin_unlock_irqrestore(&sti
->lock
, flags
);
68 sti
->text_planes
= outptr
.text_planes
;
71 static struct sti_conf_flags default_conf_flags
= {
76 sti_inq_conf(struct sti_struct
*sti
)
78 struct sti_conf_inptr inptr
= { NULL
};
79 struct sti_conf_outptr_ext outptr_ext
= { future_ptr
: NULL
};
80 struct sti_conf_outptr outptr
= {
81 ext_ptr
: STI_PTR(&outptr_ext
)
87 spin_lock_irqsave(&sti
->lock
, flags
);
88 ret
= STI_CALL(sti
->inq_conf
, &default_conf_flags
,
89 &inptr
, &outptr
, sti
->glob_cfg
);
90 spin_unlock_irqrestore(&sti
->lock
, flags
);
95 sti_putc(struct sti_struct
*sti
, int c
, int y
, int x
)
97 struct sti_font_inptr inptr
= {
98 (u32
) sti
->font
, c_index(sti
, c
), c_fg(sti
, c
), c_bg(sti
, c
),
99 x
* sti_font_x(sti
), y
* sti_font_y(sti
), NULL
101 struct sti_font_outptr outptr
= {
108 spin_lock_irqsave(&sti
->lock
, flags
);
109 ret
= STI_CALL(sti
->font_unpmv
, &default_font_flags
,
110 &inptr
, &outptr
, sti
->glob_cfg
);
111 spin_unlock_irqrestore(&sti
->lock
, flags
);
115 static struct sti_blkmv_flags clear_blkmv_flags
= {
116 STI_WAIT
, 1, 1, 0, 0, NULL
120 sti_set(struct sti_struct
*sti
, int src_y
, int src_x
,
121 int height
, int width
, u8 color
)
123 struct sti_blkmv_inptr inptr
= {
130 struct sti_blkmv_outptr outptr
= { 0, NULL
};
135 spin_lock_irqsave(&sti
->lock
, flags
);
136 ret
= STI_CALL(sti
->block_move
, &clear_blkmv_flags
,
137 &inptr
, &outptr
, sti
->glob_cfg
);
138 spin_unlock_irqrestore(&sti
->lock
, flags
);
143 sti_clear(struct sti_struct
*sti
, int src_y
, int src_x
,
144 int height
, int width
)
146 struct sti_blkmv_inptr inptr
= {
148 src_x
* sti_font_x(sti
), src_y
* sti_font_y(sti
),
149 src_x
* sti_font_x(sti
), src_y
* sti_font_y(sti
),
150 width
* sti_font_x(sti
), height
* sti_font_y(sti
),
153 struct sti_blkmv_outptr outptr
= { 0, NULL
};
158 spin_lock_irqsave(&sti
->lock
, flags
);
159 ret
= STI_CALL(sti
->block_move
, &clear_blkmv_flags
,
160 &inptr
, &outptr
, sti
->glob_cfg
);
161 spin_unlock_irqrestore(&sti
->lock
, flags
);
165 static struct sti_blkmv_flags default_blkmv_flags
= {
166 STI_WAIT
, 0, 0, 0, 0, NULL
170 sti_bmove(struct sti_struct
*sti
, int src_y
, int src_x
,
171 int dst_y
, int dst_x
, int height
, int width
)
173 struct sti_blkmv_inptr inptr
= {
175 src_x
* sti_font_x(sti
), src_y
* sti_font_y(sti
),
176 dst_x
* sti_font_x(sti
), dst_y
* sti_font_y(sti
),
177 width
* sti_font_x(sti
), height
* sti_font_y(sti
),
180 struct sti_blkmv_outptr outptr
= { 0, NULL
};
185 spin_lock_irqsave(&sti
->lock
, flags
);
186 ret
= STI_CALL(sti
->block_move
, &default_blkmv_flags
,
187 &inptr
, &outptr
, sti
->glob_cfg
);
188 spin_unlock_irqrestore(&sti
->lock
, flags
);
194 sti_rom_copy(unsigned long base
, unsigned long offset
,
195 unsigned long count
, void *dest
)
197 void *savedest
= dest
;
198 int savecount
= count
;
202 *(u32
*)dest
= gsc_readl(base
+ offset
);
208 *(u8
*)dest
= gsc_readb(base
+ offset
);
212 __flush_dcache_range((unsigned long) dest
, count
);
213 __flush_icache_range((unsigned long) dest
, count
);
216 static void dump_sti_rom(struct sti_rom
*rom
)
218 printk("STI word mode ROM type %d\n", rom
->type
[3]);
219 printk(" supports %d monitors\n", rom
->num_mons
);
220 printk(" conforms to STI ROM spec revision %d.%02x\n",
221 rom
->revno
[0] >> 4, rom
->revno
[0] & 0x0f);
222 printk(" graphics id %02x%02x%02x%02x%02x%02x%02x%02x\n",
230 rom
->graphics_id
[7]);
231 printk(" font start %08x\n", rom
->font_start
);
232 printk(" region list %08x\n", rom
->region_list
);
233 printk(" init_graph %08x\n", rom
->init_graph
);
234 printk(" alternate code type %d\n", rom
->alt_code_type
);
237 static void __init
sti_cook_fonts(struct sti_cooked_rom
*cooked_rom
,
238 struct sti_rom
*raw_rom
)
240 struct sti_rom_font
*raw_font
;
241 struct sti_cooked_font
*cooked_font
;
242 struct sti_rom_font
*font_start
;
245 kmalloc(sizeof *cooked_font
, GFP_KERNEL
);
249 cooked_rom
->font_start
= cooked_font
;
251 raw_font
= ((void *)raw_rom
) + (raw_rom
->font_start
);
253 font_start
= raw_font
;
254 cooked_font
->raw
= raw_font
;
256 while(raw_font
->next_font
) {
257 raw_font
= ((void *)font_start
) + (raw_font
->next_font
);
259 cooked_font
->next_font
=
260 kmalloc(sizeof *cooked_font
, GFP_KERNEL
);
261 if(!cooked_font
->next_font
)
264 cooked_font
= cooked_font
->next_font
;
266 cooked_font
->raw
= raw_font
;
269 cooked_font
->next_font
= NULL
;
272 static int font_index
, font_height
, font_width
;
274 static int __init
sti_font_setup(char *str
)
278 /* we accept sti_font=10x20, sti_font=10*20 or sti_font=7 style
281 if((x
= strchr(str
, 'x')) || (x
= strchr(str
, '*'))) {
282 font_height
= simple_strtoul(str
, NULL
, 0);
283 font_width
= simple_strtoul(x
+1, NULL
, 0);
285 font_index
= simple_strtoul(str
, NULL
, 0);
291 __setup("sti_font=", sti_font_setup
);
293 static int __init
sti_search_font(struct sti_cooked_rom
*rom
,
294 int height
, int width
)
296 struct sti_cooked_font
*font
;
299 for(font
= rom
->font_start
; font
; font
= font
->next_font
, i
++) {
300 if((font
->raw
->width
== width
) && (font
->raw
->height
== height
))
307 static struct sti_cooked_font
* __init
308 sti_select_font(struct sti_cooked_rom
*rom
)
310 struct sti_cooked_font
*font
;
313 if(font_width
&& font_height
)
314 font_index
= sti_search_font(rom
, font_height
, font_width
);
316 for(font
= rom
->font_start
, i
= font_index
;
318 font
= font
->next_font
, i
--);
323 return rom
->font_start
;
327 sti_dump_globcfg_ext(struct sti_glob_cfg_ext
*cfg
)
329 printk( "monitor %d\n"
330 "in friendly mode: %d\n"
331 "power consumption %d watts\n"
342 sti_dump_globcfg(struct sti_glob_cfg
*glob_cfg
)
344 printk( "%d text planes\n"
345 "%4d x %4d screen resolution\n"
346 "%4d x %4d offscreen\n"
348 "regions at %08x %08x %08x %08x\n"
349 "regions at %08x %08x %08x %08x\n"
352 glob_cfg
->text_planes
,
353 glob_cfg
->onscreen_x
, glob_cfg
->onscreen_y
,
354 glob_cfg
->offscreen_x
, glob_cfg
->offscreen_y
,
355 glob_cfg
->total_x
, glob_cfg
->total_y
,
356 glob_cfg
->region_ptrs
[0], glob_cfg
->region_ptrs
[1],
357 glob_cfg
->region_ptrs
[2], glob_cfg
->region_ptrs
[3],
358 glob_cfg
->region_ptrs
[4], glob_cfg
->region_ptrs
[5],
359 glob_cfg
->region_ptrs
[6], glob_cfg
->region_ptrs
[7],
361 glob_cfg
->save_addr
);
362 sti_dump_globcfg_ext(PTR_STI(glob_cfg
->ext_ptr
));
366 sti_init_glob_cfg(struct sti_struct
*sti
, unsigned long hpa
,
367 unsigned long rom_address
)
369 struct sti_glob_cfg
*glob_cfg
;
370 struct sti_glob_cfg_ext
*glob_cfg_ext
;
374 glob_cfg
= kmalloc(sizeof *sti
->glob_cfg
, GFP_KERNEL
);
375 glob_cfg_ext
= kmalloc(sizeof *glob_cfg_ext
, GFP_KERNEL
);
376 save_addr
= kmalloc(1024 /*XXX*/, GFP_KERNEL
);
377 sti_mem_addr
= kmalloc(1024, GFP_KERNEL
);
379 if((!glob_cfg
) || (!glob_cfg_ext
) || (!save_addr
) || (!sti_mem_addr
))
382 memset(glob_cfg
, 0, sizeof *glob_cfg
);
383 memset(glob_cfg_ext
, 0, sizeof *glob_cfg_ext
);
384 memset(save_addr
, 0, 1024);
385 memset(sti_mem_addr
, 0, 1024);
387 glob_cfg
->ext_ptr
= STI_PTR(glob_cfg_ext
);
388 glob_cfg
->save_addr
= STI_PTR(save_addr
);
389 glob_cfg
->region_ptrs
[0] = ((sti
->regions
[0]>>18)<<12) + rom_address
;
390 glob_cfg
->region_ptrs
[1] = ((sti
->regions
[1]>>18)<<12) + hpa
;
391 glob_cfg
->region_ptrs
[2] = ((sti
->regions
[2]>>18)<<12) + hpa
;
392 glob_cfg
->region_ptrs
[3] = ((sti
->regions
[3]>>18)<<12) + hpa
;
393 glob_cfg
->region_ptrs
[4] = ((sti
->regions
[4]>>18)<<12) + hpa
;
394 glob_cfg
->region_ptrs
[5] = ((sti
->regions
[5]>>18)<<12) + hpa
;
395 glob_cfg
->region_ptrs
[6] = ((sti
->regions
[6]>>18)<<12) + hpa
;
396 glob_cfg
->region_ptrs
[7] = ((sti
->regions
[7]>>18)<<12) + hpa
;
398 glob_cfg_ext
->sti_mem_addr
= STI_PTR(sti_mem_addr
);
400 sti
->glob_cfg
= STI_PTR(glob_cfg
);
403 /* address is a pointer to a word mode or pci rom */
404 static struct sti_struct
* __init
405 sti_read_rom(unsigned long address
)
407 struct sti_struct
*ret
= NULL
;
408 struct sti_cooked_rom
*cooked
= NULL
;
409 struct sti_rom
*raw
= NULL
;
417 cooked
= kmalloc(sizeof *cooked
, GFP_KERNEL
);
418 raw
= kmalloc(sizeof *raw
, GFP_KERNEL
);
424 sti_rom_copy(address
, 0, sizeof *raw
, raw
);
428 size
= raw
->last_addr
;
430 raw
= kmalloc(size
, GFP_KERNEL
);
433 sti_rom_copy(address
, 0, size
, raw
);
435 sti_cook_fonts(cooked
, raw
);
437 sti_cook_regions(cooked
, raw
);
438 sti_cook_functions(cooked
, raw
);
441 if(raw
->region_list
) {
442 ret
->regions
= kmalloc(32, GFP_KERNEL
); /* FIXME */
444 memcpy(ret
->regions
, ((void *)raw
)+raw
->region_list
, 32);
447 address
= virt_to_phys(raw
);
449 ret
->font_unpmv
= address
+(raw
->font_unpmv
& 0x03ffffff);
450 ret
->block_move
= address
+(raw
->block_move
& 0x03ffffff);
451 ret
->init_graph
= address
+(raw
->init_graph
& 0x03ffffff);
452 ret
->inq_conf
= address
+(raw
->inq_conf
& 0x03ffffff);
457 ret
->font
= (struct sti_rom_font
*) virt_to_phys(sti_select_font(ret
->rom
)->raw
);
470 static struct sti_struct
* __init
471 sti_try_rom(unsigned long address
, unsigned long hpa
)
473 struct sti_struct
*sti
= NULL
;
477 /* if we can't read the ROM, bail out early. Not being able
478 * to read the hpa is okay, for romless sti */
479 if(pdc_add_valid((void*)address
))
482 printk("found potential STI ROM at %08lx\n", address
);
484 sig
= le16_to_cpu(gsc_readw(address
));
486 if((sig
==0x55aa) || (sig
==0xaa55)) {
487 address
+= le32_to_cpu(gsc_readl(address
+8));
488 printk("sig %04x, PCI STI ROM at %08lx\n",
494 if((sig
&0xff) == 0x01) {
495 printk("STI byte mode ROM at %08lx, ignored\n",
502 printk("STI word mode ROM at %08lx\n",
505 sti
= sti_read_rom(address
);
511 /* this is hacked. We need a better way to find out the HPA for
512 * romless STI (eg search for the graphics devices we know about
514 if (!pdc_add_valid((void *)0xf5000000)) printk("f4000000 g\n");
515 if (!pdc_add_valid((void *)0xf7000000)) printk("f6000000 g\n");
516 if (!pdc_add_valid((void *)0xf9000000)) printk("f8000000 g\n");
517 if (!pdc_add_valid((void *)0xfb000000)) printk("fa000000 g\n");
518 sti_init_glob_cfg(sti
, hpa
, address
);
523 sti_dump_globcfg(PTR_STI(sti
->glob_cfg
));
528 static unsigned long sti_address
;
529 static unsigned long sti_hpa
;
531 /* XXX: should build a list of STI ROMs */
532 struct sti_struct
* __init
535 struct sti_struct
*tmp
= NULL
, *sti
= NULL
;
537 /* handle the command line */
538 if (sti_address
&& sti_hpa
) {
539 return sti_try_rom(sti_address
, sti_hpa
);
542 /* 712, 715, some other boxes don't have a separate STI ROM,
543 * but use part of the regular flash */
544 if (PAGE0
->proc_sti
) {
545 printk("STI ROM from PDC at %08x\n", PAGE0
->proc_sti
);
546 if (!pdc_add_valid((void *)0xf9000000))
547 sti
= sti_try_rom(PAGE0
->proc_sti
, 0xf8000000);
548 else if (!pdc_add_valid((void *)0xf5000000))
549 sti
= sti_try_rom(PAGE0
->proc_sti
, 0xf4000000);
550 else if (!pdc_add_valid((void *)0xf7000000))
551 sti
= sti_try_rom(PAGE0
->proc_sti
, 0xf6000000);
552 else if (!pdc_add_valid((void *)0xfb000000))
553 sti
= sti_try_rom(PAGE0
->proc_sti
, 0xfa000000);
557 /* standard locations for GSC graphic devices */
558 if (!pdc_add_valid((void *)0xf4000000))
559 tmp
= sti_try_rom(0xf4000000, 0xf4000000);
560 sti
= tmp
? tmp
: sti
;
561 if (!pdc_add_valid((void *)0xf6000000))
562 tmp
= sti_try_rom(0xf6000000, 0xf6000000);
563 sti
= tmp
? tmp
: sti
;
564 if (!pdc_add_valid((void *)0xf8000000))
565 tmp
= sti_try_rom(0xf8000000, 0xf8000000);
566 sti
= tmp
? tmp
: sti
;
567 if (!pdc_add_valid((void *)0xfa000000))
568 tmp
= sti_try_rom(0xfa000000, 0xfa000000);
569 sti
= tmp
? tmp
: sti
;
579 if(strcmp(str
, "pdc") == 0) {
580 sti_address
= PAGE0
->proc_sti
;
584 sti_address
= simple_strtoul(str
, &end
, 16);
586 if((end
== str
) || (sti_address
< 0xf0000000)) {
591 sti_hpa
= sti_address
;
599 __setup("sti=", sti_setup
);