1 #include <linux/module.h>
2 #include <linux/types.h>
3 #include <linux/kernel.h>
4 #include <linux/malloc.h>
5 #include <linux/init.h>
7 #include <asm/uaccess.h>
8 #include <asm/pgalloc.h>
13 struct sti_struct default_sti
= {
17 static struct sti_font_flags default_font_flags
= {
21 /* The colour indices used by STI are
31 * So we have the same colours as VGA (basically one bit each for R, G, B),
32 * but have to translate them, anyway. */
34 static u8 col_trans
[8] = {
39 #define c_fg(sti, c) col_trans[((c>> 8) & 7)]
40 #define c_bg(sti, c) col_trans[((c>>11) & 7)]
41 #define c_index(sti, c) (c&0xff)
43 static struct sti_init_flags default_init_flags
= {
44 STI_WAIT
, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, NULL
48 sti_init_graph(struct sti_struct
*sti
)
50 struct sti_init_inptr_ext inptr_ext
= {
53 struct sti_init_inptr inptr
= {
54 3, STI_PTR(&inptr_ext
)
56 struct sti_init_outptr outptr
= { 0 };
60 spin_lock_irqsave(&sti
->lock
, flags
);
62 ret
= STI_CALL(sti
->init_graph
, &default_init_flags
, &inptr
,
63 &outptr
, sti
->glob_cfg
);
65 spin_unlock_irqrestore(&sti
->lock
, flags
);
67 sti
->text_planes
= outptr
.text_planes
;
70 static struct sti_conf_flags default_conf_flags
= {
75 sti_inq_conf(struct sti_struct
*sti
)
77 struct sti_conf_inptr inptr
= { NULL
};
78 struct sti_conf_outptr_ext outptr_ext
= { future_ptr
: NULL
};
79 struct sti_conf_outptr outptr
= {
80 ext_ptr
: STI_PTR(&outptr_ext
)
86 spin_lock_irqsave(&sti
->lock
, flags
);
87 ret
= STI_CALL(sti
->inq_conf
, &default_conf_flags
,
88 &inptr
, &outptr
, sti
->glob_cfg
);
89 spin_unlock_irqrestore(&sti
->lock
, flags
);
94 sti_putc(struct sti_struct
*sti
, int c
, int y
, int x
)
96 struct sti_font_inptr inptr
= {
97 (u32
) sti
->font
, c_index(sti
, c
), c_fg(sti
, c
), c_bg(sti
, c
),
98 x
* sti_font_x(sti
), y
* sti_font_y(sti
), NULL
100 struct sti_font_outptr outptr
= {
107 spin_lock_irqsave(&sti
->lock
, flags
);
108 ret
= STI_CALL(sti
->font_unpmv
, &default_font_flags
,
109 &inptr
, &outptr
, sti
->glob_cfg
);
110 spin_unlock_irqrestore(&sti
->lock
, flags
);
114 static struct sti_blkmv_flags clear_blkmv_flags
= {
115 STI_WAIT
, 1, 1, 0, 0, NULL
119 sti_set(struct sti_struct
*sti
, int src_y
, int src_x
,
120 int height
, int width
, u8 color
)
122 struct sti_blkmv_inptr inptr
= {
129 struct sti_blkmv_outptr outptr
= { 0, NULL
};
134 spin_lock_irqsave(&sti
->lock
, flags
);
135 ret
= STI_CALL(sti
->block_move
, &clear_blkmv_flags
,
136 &inptr
, &outptr
, sti
->glob_cfg
);
137 spin_unlock_irqrestore(&sti
->lock
, flags
);
142 sti_clear(struct sti_struct
*sti
, int src_y
, int src_x
,
143 int height
, int width
)
145 struct sti_blkmv_inptr inptr
= {
147 src_x
* sti_font_x(sti
), src_y
* sti_font_y(sti
),
148 src_x
* sti_font_x(sti
), src_y
* sti_font_y(sti
),
149 width
* sti_font_x(sti
), height
* sti_font_y(sti
),
152 struct sti_blkmv_outptr outptr
= { 0, NULL
};
157 spin_lock_irqsave(&sti
->lock
, flags
);
158 ret
= STI_CALL(sti
->block_move
, &clear_blkmv_flags
,
159 &inptr
, &outptr
, sti
->glob_cfg
);
160 spin_unlock_irqrestore(&sti
->lock
, flags
);
164 static struct sti_blkmv_flags default_blkmv_flags
= {
165 STI_WAIT
, 0, 0, 0, 0, NULL
169 sti_bmove(struct sti_struct
*sti
, int src_y
, int src_x
,
170 int dst_y
, int dst_x
, int height
, int width
)
172 struct sti_blkmv_inptr inptr
= {
174 src_x
* sti_font_x(sti
), src_y
* sti_font_y(sti
),
175 dst_x
* sti_font_x(sti
), dst_y
* sti_font_y(sti
),
176 width
* sti_font_x(sti
), height
* sti_font_y(sti
),
179 struct sti_blkmv_outptr outptr
= { 0, NULL
};
184 spin_lock_irqsave(&sti
->lock
, flags
);
185 ret
= STI_CALL(sti
->block_move
, &default_blkmv_flags
,
186 &inptr
, &outptr
, sti
->glob_cfg
);
187 spin_unlock_irqrestore(&sti
->lock
, flags
);
193 sti_rom_copy(unsigned long base
, unsigned long offset
,
194 unsigned long count
, void *dest
)
196 void *savedest
= dest
;
197 int savecount
= count
;
201 *(u32
*)dest
= gsc_readl(base
+ offset
);
207 *(u8
*)dest
= gsc_readb(base
+ offset
);
211 __flush_dcache_range((unsigned long) dest
, count
);
212 __flush_icache_range((unsigned long) dest
, count
);
215 static void dump_sti_rom(struct sti_rom
*rom
)
217 printk("STI word mode ROM type %d\n", rom
->type
[3]);
218 printk(" supports %d monitors\n", rom
->num_mons
);
219 printk(" conforms to STI ROM spec revision %d.%02x\n",
220 rom
->revno
[0] >> 4, rom
->revno
[0] & 0x0f);
221 printk(" graphics id %02x%02x%02x%02x%02x%02x%02x%02x\n",
229 rom
->graphics_id
[7]);
230 printk(" font start %08x\n", rom
->font_start
);
231 printk(" region list %08x\n", rom
->region_list
);
232 printk(" init_graph %08x\n", rom
->init_graph
);
233 printk(" alternate code type %d\n", rom
->alt_code_type
);
236 static void __init
sti_cook_fonts(struct sti_cooked_rom
*cooked_rom
,
237 struct sti_rom
*raw_rom
)
239 struct sti_rom_font
*raw_font
;
240 struct sti_cooked_font
*cooked_font
;
241 struct sti_rom_font
*font_start
;
244 kmalloc(sizeof *cooked_font
, GFP_KERNEL
);
248 cooked_rom
->font_start
= cooked_font
;
250 raw_font
= ((void *)raw_rom
) + (raw_rom
->font_start
);
252 font_start
= raw_font
;
253 cooked_font
->raw
= raw_font
;
255 while(raw_font
->next_font
) {
256 raw_font
= ((void *)font_start
) + (raw_font
->next_font
);
258 cooked_font
->next_font
=
259 kmalloc(sizeof *cooked_font
, GFP_KERNEL
);
260 if(!cooked_font
->next_font
)
263 cooked_font
= cooked_font
->next_font
;
265 cooked_font
->raw
= raw_font
;
268 cooked_font
->next_font
= NULL
;
271 static int font_index
, font_height
, font_width
;
273 static int __init
sti_font_setup(char *str
)
277 /* we accept sti_font=10x20, sti_font=10*20 or sti_font=7 style
280 if((x
= strchr(str
, 'x')) || (x
= strchr(str
, '*'))) {
281 font_height
= simple_strtoul(str
, NULL
, 0);
282 font_width
= simple_strtoul(x
+1, NULL
, 0);
284 font_index
= simple_strtoul(str
, NULL
, 0);
290 __setup("sti_font=", sti_font_setup
);
292 static int __init
sti_search_font(struct sti_cooked_rom
*rom
,
293 int height
, int width
)
295 struct sti_cooked_font
*font
;
298 for(font
= rom
->font_start
; font
; font
= font
->next_font
, i
++) {
299 if((font
->raw
->width
== width
) && (font
->raw
->height
== height
))
306 static struct sti_cooked_font
* __init
307 sti_select_font(struct sti_cooked_rom
*rom
)
309 struct sti_cooked_font
*font
;
312 if(font_width
&& font_height
)
313 font_index
= sti_search_font(rom
, font_height
, font_width
);
315 for(font
= rom
->font_start
, i
= font_index
;
317 font
= font
->next_font
, i
--);
322 return rom
->font_start
;
326 sti_dump_globcfg_ext(struct sti_glob_cfg_ext
*cfg
)
328 printk( "monitor %d\n"
329 "in friendly mode: %d\n"
330 "power consumption %d watts\n"
341 sti_dump_globcfg(struct sti_glob_cfg
*glob_cfg
)
343 printk( "%d text planes\n"
344 "%4d x %4d screen resolution\n"
345 "%4d x %4d offscreen\n"
347 "regions at %08x %08x %08x %08x\n"
348 "regions at %08x %08x %08x %08x\n"
351 glob_cfg
->text_planes
,
352 glob_cfg
->onscreen_x
, glob_cfg
->onscreen_y
,
353 glob_cfg
->offscreen_x
, glob_cfg
->offscreen_y
,
354 glob_cfg
->total_x
, glob_cfg
->total_y
,
355 glob_cfg
->region_ptrs
[0], glob_cfg
->region_ptrs
[1],
356 glob_cfg
->region_ptrs
[2], glob_cfg
->region_ptrs
[3],
357 glob_cfg
->region_ptrs
[4], glob_cfg
->region_ptrs
[5],
358 glob_cfg
->region_ptrs
[6], glob_cfg
->region_ptrs
[7],
360 glob_cfg
->save_addr
);
361 sti_dump_globcfg_ext(PTR_STI(glob_cfg
->ext_ptr
));
365 sti_init_glob_cfg(struct sti_struct
*sti
, unsigned long hpa
,
366 unsigned long rom_address
)
368 struct sti_glob_cfg
*glob_cfg
;
369 struct sti_glob_cfg_ext
*glob_cfg_ext
;
373 glob_cfg
= kmalloc(sizeof *sti
->glob_cfg
, GFP_KERNEL
);
374 glob_cfg_ext
= kmalloc(sizeof *glob_cfg_ext
, GFP_KERNEL
);
375 save_addr
= kmalloc(1024 /*XXX*/, GFP_KERNEL
);
376 sti_mem_addr
= kmalloc(1024, GFP_KERNEL
);
378 if((!glob_cfg
) || (!glob_cfg_ext
) || (!save_addr
) || (!sti_mem_addr
))
381 memset(glob_cfg
, 0, sizeof *glob_cfg
);
382 memset(glob_cfg_ext
, 0, sizeof *glob_cfg_ext
);
383 memset(save_addr
, 0, 1024);
384 memset(sti_mem_addr
, 0, 1024);
386 glob_cfg
->ext_ptr
= STI_PTR(glob_cfg_ext
);
387 glob_cfg
->save_addr
= STI_PTR(save_addr
);
388 glob_cfg
->region_ptrs
[0] = ((sti
->regions
[0]>>18)<<12) + rom_address
;
389 glob_cfg
->region_ptrs
[1] = ((sti
->regions
[1]>>18)<<12) + hpa
;
390 glob_cfg
->region_ptrs
[2] = ((sti
->regions
[2]>>18)<<12) + hpa
;
391 glob_cfg
->region_ptrs
[3] = ((sti
->regions
[3]>>18)<<12) + hpa
;
392 glob_cfg
->region_ptrs
[4] = ((sti
->regions
[4]>>18)<<12) + hpa
;
393 glob_cfg
->region_ptrs
[5] = ((sti
->regions
[5]>>18)<<12) + hpa
;
394 glob_cfg
->region_ptrs
[6] = ((sti
->regions
[6]>>18)<<12) + hpa
;
395 glob_cfg
->region_ptrs
[7] = ((sti
->regions
[7]>>18)<<12) + hpa
;
397 glob_cfg_ext
->sti_mem_addr
= STI_PTR(sti_mem_addr
);
399 sti
->glob_cfg
= STI_PTR(glob_cfg
);
402 /* address is a pointer to a word mode or pci rom */
403 static struct sti_struct
* __init
404 sti_read_rom(unsigned long address
)
406 struct sti_struct
*ret
= NULL
;
407 struct sti_cooked_rom
*cooked
= NULL
;
408 struct sti_rom
*raw
= NULL
;
416 cooked
= kmalloc(sizeof *cooked
, GFP_KERNEL
);
417 raw
= kmalloc(sizeof *raw
, GFP_KERNEL
);
423 sti_rom_copy(address
, 0, sizeof *raw
, raw
);
427 size
= raw
->last_addr
;
429 raw
= kmalloc(size
, GFP_KERNEL
);
432 sti_rom_copy(address
, 0, size
, raw
);
434 sti_cook_fonts(cooked
, raw
);
436 sti_cook_regions(cooked
, raw
);
437 sti_cook_functions(cooked
, raw
);
440 if(raw
->region_list
) {
441 ret
->regions
= kmalloc(32, GFP_KERNEL
); /* FIXME */
443 memcpy(ret
->regions
, ((void *)raw
)+raw
->region_list
, 32);
446 address
= virt_to_phys(raw
);
448 ret
->font_unpmv
= address
+(raw
->font_unpmv
& 0x03ffffff);
449 ret
->block_move
= address
+(raw
->block_move
& 0x03ffffff);
450 ret
->init_graph
= address
+(raw
->init_graph
& 0x03ffffff);
451 ret
->inq_conf
= address
+(raw
->inq_conf
& 0x03ffffff);
456 ret
->font
= (struct sti_rom_font
*) virt_to_phys(sti_select_font(ret
->rom
)->raw
);
469 static struct sti_struct
* __init
470 sti_try_rom(unsigned long address
, unsigned long hpa
)
472 struct sti_struct
*sti
= NULL
;
476 /* if we can't read the ROM, bail out early. Not being able
477 * to read the hpa is okay, for romless sti */
478 if(pdc_add_valid((void*)address
))
481 printk("found potential STI ROM at %08lx\n", address
);
483 sig
= le16_to_cpu(gsc_readw(address
));
485 if((sig
==0x55aa) || (sig
==0xaa55)) {
486 address
+= le32_to_cpu(gsc_readl(address
+8));
487 printk("sig %04x, PCI STI ROM at %08lx\n",
493 if((sig
&0xff) == 0x01) {
494 printk("STI byte mode ROM at %08lx, ignored\n",
501 printk("STI word mode ROM at %08lx\n",
504 sti
= sti_read_rom(address
);
510 /* this is hacked. We need a better way to find out the HPA for
511 * romless STI (eg search for the graphics devices we know about
513 if (!pdc_add_valid((void *)0xf5000000)) printk("f4000000 g\n");
514 if (!pdc_add_valid((void *)0xf7000000)) printk("f6000000 g\n");
515 if (!pdc_add_valid((void *)0xf9000000)) printk("f8000000 g\n");
516 if (!pdc_add_valid((void *)0xfb000000)) printk("fa000000 g\n");
517 sti_init_glob_cfg(sti
, hpa
, address
);
522 sti_dump_globcfg(PTR_STI(sti
->glob_cfg
));
527 static unsigned long sti_address
;
528 static unsigned long sti_hpa
;
530 /* XXX: should build a list of STI ROMs */
531 struct sti_struct
* __init
534 struct sti_struct
*tmp
= NULL
, *sti
= NULL
;
536 /* handle the command line */
537 if (sti_address
&& sti_hpa
) {
538 return sti_try_rom(sti_address
, sti_hpa
);
541 /* 712, 715, some other boxes don't have a separate STI ROM,
542 * but use part of the regular flash */
543 if (PAGE0
->proc_sti
) {
544 printk("STI ROM from PDC at %08x\n", PAGE0
->proc_sti
);
545 if (!pdc_add_valid((void *)0xf9000000))
546 sti
= sti_try_rom(PAGE0
->proc_sti
, 0xf8000000);
547 else if (!pdc_add_valid((void *)0xf5000000))
548 sti
= sti_try_rom(PAGE0
->proc_sti
, 0xf4000000);
549 else if (!pdc_add_valid((void *)0xf7000000))
550 sti
= sti_try_rom(PAGE0
->proc_sti
, 0xf6000000);
551 else if (!pdc_add_valid((void *)0xfb000000))
552 sti
= sti_try_rom(PAGE0
->proc_sti
, 0xfa000000);
556 /* standard locations for GSC graphic devices */
557 if (!pdc_add_valid((void *)0xf4000000))
558 tmp
= sti_try_rom(0xf4000000, 0xf4000000);
559 sti
= tmp
? tmp
: sti
;
560 if (!pdc_add_valid((void *)0xf6000000))
561 tmp
= sti_try_rom(0xf6000000, 0xf6000000);
562 sti
= tmp
? tmp
: sti
;
563 if (!pdc_add_valid((void *)0xf8000000))
564 tmp
= sti_try_rom(0xf8000000, 0xf8000000);
565 sti
= tmp
? tmp
: sti
;
566 if (!pdc_add_valid((void *)0xfa000000))
567 tmp
= sti_try_rom(0xfa000000, 0xfa000000);
568 sti
= tmp
? tmp
: sti
;
578 if(strcmp(str
, "pdc") == 0) {
579 sti_address
= PAGE0
->proc_sti
;
583 sti_address
= simple_strtoul(str
, &end
, 16);
585 if((end
== str
) || (sti_address
< 0xf0000000)) {
590 sti_hpa
= sti_address
;
598 __setup("sti=", sti_setup
);