~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/video/sticore.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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>
  6 
  7 #include <asm/uaccess.h>
  8 #include <asm/pgalloc.h>
  9 #include <asm/io.h>
 10 
 11 #include "sti.h"
 12 
 13 struct sti_struct default_sti = {
 14         SPIN_LOCK_UNLOCKED,
 15 };
 16 
 17 static struct sti_font_flags default_font_flags = {
 18         STI_WAIT, 0, 0, NULL
 19 };
 20 
 21 /* The colour indices used by STI are
 22  *   0 - Black
 23  *   1 - White
 24  *   2 - Red
 25  *   3 - Yellow/Brown
 26  *   4 - Green
 27  *   5 - Cyan
 28  *   6 - Blue
 29  *   7 - Magenta
 30  *
 31  * So we have the same colours as VGA (basically one bit each for R, G, B),
 32  * but have to translate them, anyway. */
 33 
 34 static u8 col_trans[8] = {
 35         0, 6, 4, 5,
 36         2, 7, 3, 1
 37 };
 38 
 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)
 42 
 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
 45 };
 46 
 47 void
 48 sti_init_graph(struct sti_struct *sti) 
 49 {
 50         struct sti_init_inptr_ext inptr_ext = {
 51                 0, { 0 }, 0, NULL
 52         };
 53         struct sti_init_inptr inptr = {
 54                 3, STI_PTR(&inptr_ext)
 55         };
 56         struct sti_init_outptr outptr = { 0 };
 57         unsigned long flags;
 58         s32 ret;
 59 
 60         spin_lock_irqsave(&sti->lock, flags);
 61 
 62         ret = STI_CALL(sti->init_graph, &default_init_flags, &inptr,
 63                 &outptr, sti->glob_cfg);
 64 
 65         spin_unlock_irqrestore(&sti->lock, flags);
 66 
 67         sti->text_planes = outptr.text_planes;
 68 }
 69 
 70 static struct sti_conf_flags default_conf_flags = {
 71         STI_WAIT, 0, NULL
 72 };
 73 
 74 void
 75 sti_inq_conf(struct sti_struct *sti)
 76 {
 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)
 81         };
 82         unsigned long flags;
 83         s32 ret;
 84         
 85         do {
 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);
 90         } while(ret == 1);
 91 }
 92 
 93 void
 94 sti_putc(struct sti_struct *sti, int c, int y, int x)
 95 {
 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
 99         };
100         struct sti_font_outptr outptr = {
101                 0, NULL
102         };
103         s32 ret;
104         unsigned long flags;
105 
106         do {
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);
111         } while(ret == 1);
112 }
113 
114 static struct sti_blkmv_flags clear_blkmv_flags = {
115         STI_WAIT, 1, 1, 0, 0, NULL
116 };
117 
118 void
119 sti_set(struct sti_struct *sti, int src_y, int src_x,
120         int height, int width, u8 color)
121 {
122         struct sti_blkmv_inptr inptr = {
123                 color, color,
124                 src_x, src_y ,
125                 src_x, src_y ,
126                 width, height,
127                 NULL
128         };
129         struct sti_blkmv_outptr outptr = { 0, NULL };
130         s32 ret = 0;
131         unsigned long flags;
132         
133         do {
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);
138         } while(ret == 1);
139 }
140 
141 void
142 sti_clear(struct sti_struct *sti, int src_y, int src_x,
143           int height, int width)
144 {
145         struct sti_blkmv_inptr inptr = {
146                 0, 0,
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),
150                 NULL
151         };
152         struct sti_blkmv_outptr outptr = { 0, NULL };
153         s32 ret = 0;
154         unsigned long flags;
155 
156         do {
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);
161         } while(ret == 1);
162 }
163 
164 static struct sti_blkmv_flags default_blkmv_flags = {
165         STI_WAIT, 0, 0, 0, 0, NULL
166 };
167 
168 void
169 sti_bmove(struct sti_struct *sti, int src_y, int src_x,
170           int dst_y, int dst_x, int height, int width)
171 {
172         struct sti_blkmv_inptr inptr = {
173                 0, 0,
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),
177                 NULL
178         };
179         struct sti_blkmv_outptr outptr = { 0, NULL };
180         s32 ret = 0;
181         unsigned long flags;
182 
183         do {
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);
188         } while(ret == 1);
189 }
190 
191 
192 static void __init
193 sti_rom_copy(unsigned long base, unsigned long offset,
194              unsigned long count, void *dest)
195 {
196         void *savedest = dest;
197         int savecount = count;
198 
199         while(count >= 4) {
200                 count -= 4;
201                 *(u32 *)dest = gsc_readl(base + offset);
202                 offset += 4;
203                 dest += 4;
204         }
205         while(count) {
206                 count--;
207                 *(u8 *)dest = gsc_readb(base + offset);
208                 offset++;
209                 dest++;
210         }
211         __flush_dcache_range((unsigned long) dest, count);
212         __flush_icache_range((unsigned long) dest, count);
213 }
214 
215 static void dump_sti_rom(struct sti_rom *rom)
216 {
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",
222                 rom->graphics_id[0], 
223                 rom->graphics_id[1], 
224                 rom->graphics_id[2], 
225                 rom->graphics_id[3], 
226                 rom->graphics_id[4], 
227                 rom->graphics_id[5], 
228                 rom->graphics_id[6], 
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);
234 }
235 
236 static void __init sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
237                                   struct sti_rom *raw_rom)
238 {
239         struct sti_rom_font *raw_font;
240         struct sti_cooked_font *cooked_font;
241         struct sti_rom_font *font_start;
242         
243         cooked_font =
244                 kmalloc(sizeof *cooked_font, GFP_KERNEL);
245         if(!cooked_font)
246                 return;
247 
248         cooked_rom->font_start = cooked_font;
249 
250         raw_font = ((void *)raw_rom) + (raw_rom->font_start);
251 
252         font_start = raw_font;
253         cooked_font->raw = raw_font;
254 
255         while(raw_font->next_font) {
256                 raw_font = ((void *)font_start) + (raw_font->next_font);
257                 
258                 cooked_font->next_font =
259                         kmalloc(sizeof *cooked_font, GFP_KERNEL);
260                 if(!cooked_font->next_font)
261                         return;
262 
263                 cooked_font = cooked_font->next_font;
264 
265                 cooked_font->raw = raw_font;
266         }
267 
268         cooked_font->next_font = NULL;
269 }
270 
271 static int font_index, font_height, font_width;
272 
273 static int __init sti_font_setup(char *str)
274 {
275         char *x;
276 
277         /* we accept sti_font=10x20, sti_font=10*20 or sti_font=7 style
278          * command lines. */
279 
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);
283         } else {
284                 font_index = simple_strtoul(str, NULL, 0);
285         }
286 
287         return 0;
288 }
289 
290 __setup("sti_font=", sti_font_setup);
291 
292 static int __init sti_search_font(struct sti_cooked_rom *rom,
293                                   int height, int width)
294 {
295         struct sti_cooked_font *font;
296         int i = 0;
297         
298         for(font = rom->font_start; font; font = font->next_font, i++) {
299                 if((font->raw->width == width) && (font->raw->height == height))
300                         return i;
301         }
302 
303         return 0;
304 }
305 
306 static struct sti_cooked_font * __init
307 sti_select_font(struct sti_cooked_rom *rom)
308 {
309         struct sti_cooked_font *font;
310         int i;
311 
312         if(font_width && font_height)
313                 font_index = sti_search_font(rom, font_height, font_width);
314 
315         for(font = rom->font_start, i = font_index;
316             font && (i > 0);
317             font = font->next_font, i--);
318 
319         if(font)
320                 return font;
321         else
322                 return rom->font_start;
323 }
324         
325 static void __init
326 sti_dump_globcfg_ext(struct sti_glob_cfg_ext *cfg)
327 {
328         printk( "monitor %d\n"
329                 "in friendly mode: %d\n"
330                 "power consumption %d watts\n"
331                 "freq ref %d\n"
332                 "sti_mem_addr %p\n",
333                 cfg->curr_mon,
334                 cfg->friendly_boot,
335                 cfg->power,
336                 cfg->freq_ref,
337                 cfg->sti_mem_addr);
338 }
339 
340 void __init
341 sti_dump_globcfg(struct sti_glob_cfg *glob_cfg)
342 {
343         printk( "%d text planes\n"
344                 "%4d x %4d screen resolution\n"
345                 "%4d x %4d offscreen\n"
346                 "%4d x %4d layout\n"
347                 "regions at %08x %08x %08x %08x\n"
348                 "regions at %08x %08x %08x %08x\n"
349                 "reent_lvl %d\n"
350                 "save_addr %p\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],
359                 glob_cfg->reent_lvl,
360                 glob_cfg->save_addr);
361         sti_dump_globcfg_ext(PTR_STI(glob_cfg->ext_ptr));
362 }
363                 
364 static void __init
365 sti_init_glob_cfg(struct sti_struct *sti, unsigned long hpa,
366                   unsigned long rom_address)
367 {
368         struct sti_glob_cfg *glob_cfg;
369         struct sti_glob_cfg_ext *glob_cfg_ext;
370         void *save_addr;
371         void *sti_mem_addr;
372 
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);
377 
378         if((!glob_cfg) || (!glob_cfg_ext) || (!save_addr) || (!sti_mem_addr))
379                 return;
380 
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);
385 
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;
396         
397         glob_cfg_ext->sti_mem_addr = STI_PTR(sti_mem_addr);
398 
399         sti->glob_cfg = STI_PTR(glob_cfg);
400 }
401 
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)
405 {
406         struct sti_struct *ret = NULL;
407         struct sti_cooked_rom *cooked = NULL;
408         struct sti_rom *raw = NULL;
409         unsigned long size;
410 
411         ret = &default_sti;
412 
413         if(!ret)
414                 goto out_err;
415 
416         cooked = kmalloc(sizeof *cooked, GFP_KERNEL);
417         raw = kmalloc(sizeof *raw, GFP_KERNEL);
418         
419         if(!(raw && cooked))
420                 goto out_err;
421 
422         /* reallocate raw */
423         sti_rom_copy(address, 0, sizeof *raw, raw);
424 
425         dump_sti_rom(raw);
426 
427         size = raw->last_addr;
428         /* kfree(raw); */
429         raw = kmalloc(size, GFP_KERNEL);
430         if(!raw)
431                 goto out_err;
432         sti_rom_copy(address, 0, size, raw);
433 
434         sti_cook_fonts(cooked, raw);
435 #if 0
436         sti_cook_regions(cooked, raw);
437         sti_cook_functions(cooked, raw);
438 #endif
439 
440         if(raw->region_list) {
441                 ret->regions = kmalloc(32, GFP_KERNEL); /* FIXME */
442 
443                 memcpy(ret->regions, ((void *)raw)+raw->region_list, 32);
444         }
445 
446         address = virt_to_phys(raw);
447 
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);
452 
453         ret->rom = cooked;
454         ret->rom->raw = raw;
455 
456         ret->font = (struct sti_rom_font *) virt_to_phys(sti_select_font(ret->rom)->raw);
457 
458         return ret;
459 
460 out_err:
461         if(raw)
462                 kfree(raw);
463         if(cooked)
464                 kfree(cooked);
465 
466         return NULL;
467 }
468 
469 static struct sti_struct * __init
470 sti_try_rom(unsigned long address, unsigned long hpa)
471 {
472         struct sti_struct *sti = NULL;
473         u16 sig;
474         
475 test_rom:
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))
479                 return NULL;
480 
481         printk("found potential STI ROM at %08lx\n", address);
482 
483         sig = le16_to_cpu(gsc_readw(address));
484 
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",
488                        sig, address);
489 
490                 goto test_rom;
491         }
492 
493         if((sig&0xff) == 0x01) {
494                 printk("STI byte mode ROM at %08lx, ignored\n",
495                        address);
496 
497                 sti = NULL;
498         }
499 
500         if(sig == 0x0303) {
501                 printk("STI word mode ROM at %08lx\n",
502                        address);
503 
504                 sti = sti_read_rom(address);
505         }
506 
507         if (!sti)
508                 return NULL;
509 
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
512          * by sversion) */
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);
518 
519         sti_init_graph(sti);
520 
521         sti_inq_conf(sti);
522         sti_dump_globcfg(PTR_STI(sti->glob_cfg));
523 
524         return sti;
525 }
526 
527 static unsigned long sti_address;
528 static unsigned long sti_hpa;
529 
530 /* XXX: should build a list of STI ROMs */
531 struct sti_struct * __init
532 sti_init_roms(void)
533 {
534         struct sti_struct *tmp = NULL, *sti = NULL;
535 
536         /* handle the command line */
537         if (sti_address && sti_hpa) {
538                 return sti_try_rom(sti_address, sti_hpa);
539         }
540 
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);
553 
554         }
555 
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;
569 
570         return sti;
571 }
572 
573 static int __init
574 sti_setup(char *str)
575 {
576         char *end;
577 
578         if(strcmp(str, "pdc") == 0) {
579                 sti_address = PAGE0->proc_sti;
580 
581                 return 1;
582         } else {
583                 sti_address = simple_strtoul(str, &end, 16);
584 
585                 if((end == str) || (sti_address < 0xf0000000)) {
586                         sti_address = 0;
587                         return 0;
588                 }
589 
590                 sti_hpa = sti_address;
591 
592                 return 1;
593         }
594 
595         return 0;
596 }
597 
598 __setup("sti=", sti_setup);
599 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.