sticore.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:14k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. #include <linux/module.h>
  2. #include <linux/types.h>
  3. #include <linux/kernel.h>
  4. #include <linux/slab.h>
  5. #include <linux/init.h>
  6. #include <asm/uaccess.h>
  7. #include <asm/pgalloc.h>
  8. #include <asm/io.h>
  9. #include "sti.h"
  10. struct sti_struct default_sti = {
  11. SPIN_LOCK_UNLOCKED,
  12. };
  13. static struct sti_font_flags default_font_flags = {
  14. STI_WAIT, 0, 0, NULL
  15. };
  16. /* The colour indices used by STI are
  17.  *   0 - Black
  18.  *   1 - White
  19.  *   2 - Red
  20.  *   3 - Yellow/Brown
  21.  *   4 - Green
  22.  *   5 - Cyan
  23.  *   6 - Blue
  24.  *   7 - Magenta
  25.  *
  26.  * So we have the same colours as VGA (basically one bit each for R, G, B),
  27.  * but have to translate them, anyway. */
  28. static u8 col_trans[8] = {
  29.         0, 6, 4, 5,
  30.         2, 7, 3, 1
  31. };
  32. #define c_fg(sti, c) col_trans[((c>> 8) & 7)]
  33. #define c_bg(sti, c) col_trans[((c>>11) & 7)]
  34. #define c_index(sti, c) (c&0xff)
  35. static struct sti_init_flags default_init_flags = {
  36. STI_WAIT, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, NULL
  37. };
  38. void
  39. sti_init_graph(struct sti_struct *sti) 
  40. {
  41. struct sti_init_inptr_ext inptr_ext = {
  42. 0, { 0 }, 0, NULL
  43. };
  44. struct sti_init_inptr inptr = {
  45. 3, STI_PTR(&inptr_ext)
  46. };
  47. struct sti_init_outptr outptr = { 0 };
  48. unsigned long flags;
  49. s32 ret;
  50. spin_lock_irqsave(&sti->lock, flags);
  51. ret = STI_CALL(sti->init_graph, &default_init_flags, &inptr,
  52. &outptr, sti->glob_cfg);
  53. spin_unlock_irqrestore(&sti->lock, flags);
  54. sti->text_planes = outptr.text_planes;
  55. }
  56. static struct sti_conf_flags default_conf_flags = {
  57. STI_WAIT, 0, NULL
  58. };
  59. void
  60. sti_inq_conf(struct sti_struct *sti)
  61. {
  62. struct sti_conf_inptr inptr = { NULL };
  63. struct sti_conf_outptr_ext outptr_ext = { future_ptr: NULL };
  64. struct sti_conf_outptr outptr = {
  65. ext_ptr: STI_PTR(&outptr_ext)
  66. };
  67. unsigned long flags;
  68. s32 ret;
  69. do {
  70. spin_lock_irqsave(&sti->lock, flags);
  71. ret = STI_CALL(sti->inq_conf, &default_conf_flags,
  72. &inptr, &outptr, sti->glob_cfg);
  73. spin_unlock_irqrestore(&sti->lock, flags);
  74. } while(ret == 1);
  75. }
  76. void
  77. sti_putc(struct sti_struct *sti, int c, int y, int x)
  78. {
  79. struct sti_font_inptr inptr = {
  80. (u32) sti->font, c_index(sti, c), c_fg(sti, c), c_bg(sti, c),
  81. x * sti_font_x(sti), y * sti_font_y(sti), NULL
  82. };
  83. struct sti_font_outptr outptr = {
  84. 0, NULL
  85. };
  86. s32 ret;
  87. unsigned long flags;
  88. do {
  89. spin_lock_irqsave(&sti->lock, flags);
  90. ret = STI_CALL(sti->font_unpmv, &default_font_flags,
  91. &inptr, &outptr, sti->glob_cfg);
  92. spin_unlock_irqrestore(&sti->lock, flags);
  93. } while(ret == 1);
  94. }
  95. static struct sti_blkmv_flags clear_blkmv_flags = {
  96. STI_WAIT, 1, 1, 0, 0, NULL
  97. };
  98. void
  99. sti_set(struct sti_struct *sti, int src_y, int src_x,
  100. int height, int width, u8 color)
  101. {
  102. struct sti_blkmv_inptr inptr = {
  103. color, color,
  104. src_x, src_y ,
  105. src_x, src_y ,
  106. width, height,
  107. NULL
  108. };
  109. struct sti_blkmv_outptr outptr = { 0, NULL };
  110. s32 ret = 0;
  111. unsigned long flags;
  112. do {
  113. spin_lock_irqsave(&sti->lock, flags);
  114. ret = STI_CALL(sti->block_move, &clear_blkmv_flags,
  115. &inptr, &outptr, sti->glob_cfg);
  116. spin_unlock_irqrestore(&sti->lock, flags);
  117. } while(ret == 1);
  118. }
  119. void
  120. sti_clear(struct sti_struct *sti, int src_y, int src_x,
  121.   int height, int width)
  122. {
  123. struct sti_blkmv_inptr inptr = {
  124. 0, 0,
  125. src_x * sti_font_x(sti), src_y * sti_font_y(sti),
  126. src_x * sti_font_x(sti), src_y * sti_font_y(sti),
  127. width * sti_font_x(sti), height* sti_font_y(sti),
  128. NULL
  129. };
  130. struct sti_blkmv_outptr outptr = { 0, NULL };
  131. s32 ret = 0;
  132. unsigned long flags;
  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. static struct sti_blkmv_flags default_blkmv_flags = {
  141. STI_WAIT, 0, 0, 0, 0, NULL
  142. };
  143. void
  144. sti_bmove(struct sti_struct *sti, int src_y, int src_x,
  145.   int dst_y, int dst_x, int height, int width)
  146. {
  147. struct sti_blkmv_inptr inptr = {
  148. 0, 0,
  149. src_x * sti_font_x(sti), src_y * sti_font_y(sti),
  150. dst_x * sti_font_x(sti), dst_y * sti_font_y(sti),
  151. width * sti_font_x(sti), height* sti_font_y(sti),
  152. NULL
  153. };
  154. struct sti_blkmv_outptr outptr = { 0, NULL };
  155. s32 ret = 0;
  156. unsigned long flags;
  157. do {
  158. spin_lock_irqsave(&sti->lock, flags);
  159. ret = STI_CALL(sti->block_move, &default_blkmv_flags,
  160. &inptr, &outptr, sti->glob_cfg);
  161. spin_unlock_irqrestore(&sti->lock, flags);
  162. } while(ret == 1);
  163. }
  164. static void __init
  165. sti_rom_copy(unsigned long base, unsigned long offset,
  166.      unsigned long count, void *dest)
  167. {
  168. void *savedest = dest;
  169. int savecount = count;
  170. while(count >= 4) {
  171. count -= 4;
  172. *(u32 *)dest = gsc_readl(base + offset);
  173. offset += 4;
  174. dest += 4;
  175. }
  176. while(count) {
  177. count--;
  178. *(u8 *)dest = gsc_readb(base + offset);
  179. offset++;
  180. dest++;
  181. }
  182. flush_kernel_dcache_range((unsigned long)dest, count);
  183. flush_icache_range((unsigned long)dest, dest + count);
  184. }
  185. static void dump_sti_rom(struct sti_rom *rom)
  186. {
  187. printk("STI word mode ROM type %dn", rom->type[3]);
  188. printk(" supports %d monitorsn", rom->num_mons);
  189. printk(" conforms to STI ROM spec revision %d.%02xn",
  190. rom->revno[0] >> 4, rom->revno[0] & 0x0f);
  191. printk(" graphics id %02x%02x%02x%02x%02x%02x%02x%02xn",
  192. rom->graphics_id[0], 
  193. rom->graphics_id[1], 
  194. rom->graphics_id[2], 
  195. rom->graphics_id[3], 
  196. rom->graphics_id[4], 
  197. rom->graphics_id[5], 
  198. rom->graphics_id[6], 
  199. rom->graphics_id[7]);
  200. printk(" font start %08xn", rom->font_start);
  201. printk(" region list %08xn", rom->region_list);
  202. printk(" init_graph %08xn", rom->init_graph);
  203. printk(" alternate code type %dn", rom->alt_code_type);
  204. }
  205. static void __init sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
  206.   struct sti_rom *raw_rom)
  207. {
  208. struct sti_rom_font *raw_font;
  209. struct sti_cooked_font *cooked_font;
  210. struct sti_rom_font *font_start;
  211. cooked_font =
  212. kmalloc(sizeof *cooked_font, GFP_KERNEL);
  213. if(!cooked_font)
  214. return;
  215. cooked_rom->font_start = cooked_font;
  216. raw_font = ((void *)raw_rom) + (raw_rom->font_start);
  217. font_start = raw_font;
  218. cooked_font->raw = raw_font;
  219. while(raw_font->next_font) {
  220. raw_font = ((void *)font_start) + (raw_font->next_font);
  221. cooked_font->next_font =
  222. kmalloc(sizeof *cooked_font, GFP_KERNEL);
  223. if(!cooked_font->next_font)
  224. return;
  225. cooked_font = cooked_font->next_font;
  226. cooked_font->raw = raw_font;
  227. }
  228. cooked_font->next_font = NULL;
  229. }
  230. static int font_index, font_height, font_width;
  231. static int __init sti_font_setup(char *str)
  232. {
  233. char *x;
  234. /* we accept sti_font=10x20, sti_font=10*20 or sti_font=7 style
  235.  * command lines. */
  236. if((x = strchr(str, 'x')) || (x = strchr(str, '*'))) {
  237. font_height = simple_strtoul(str, NULL, 0);
  238. font_width = simple_strtoul(x+1, NULL, 0);
  239. } else {
  240. font_index = simple_strtoul(str, NULL, 0);
  241. }
  242. return 0;
  243. }
  244. __setup("sti_font=", sti_font_setup);
  245. static int __init sti_search_font(struct sti_cooked_rom *rom,
  246.   int height, int width)
  247. {
  248. struct sti_cooked_font *font;
  249. int i = 0;
  250. for(font = rom->font_start; font; font = font->next_font, i++) {
  251. if((font->raw->width == width) && (font->raw->height == height))
  252. return i;
  253. }
  254. return 0;
  255. }
  256. static struct sti_cooked_font * __init
  257. sti_select_font(struct sti_cooked_rom *rom)
  258. {
  259. struct sti_cooked_font *font;
  260. int i;
  261. if(font_width && font_height)
  262. font_index = sti_search_font(rom, font_height, font_width);
  263. for(font = rom->font_start, i = font_index;
  264.     font && (i > 0);
  265.     font = font->next_font, i--);
  266. if(font)
  267. return font;
  268. else
  269. return rom->font_start;
  270. }
  271. static void __init
  272. sti_dump_globcfg_ext(struct sti_glob_cfg_ext *cfg)
  273. {
  274. printk( "monitor %dn"
  275. "in friendly mode: %dn"
  276. "power consumption %d wattsn"
  277. "freq ref %dn"
  278. "sti_mem_addr %pn",
  279. cfg->curr_mon,
  280. cfg->friendly_boot,
  281. cfg->power,
  282. cfg->freq_ref,
  283. cfg->sti_mem_addr);
  284. }
  285. void __init
  286. sti_dump_globcfg(struct sti_glob_cfg *glob_cfg)
  287. {
  288. printk( "%d text planesn"
  289. "%4d x %4d screen resolutionn"
  290. "%4d x %4d offscreenn"
  291. "%4d x %4d layoutn"
  292. "regions at %08x %08x %08x %08xn"
  293. "regions at %08x %08x %08x %08xn"
  294. "reent_lvl %dn"
  295. "save_addr %pn",
  296. glob_cfg->text_planes,
  297. glob_cfg->onscreen_x, glob_cfg->onscreen_y,
  298. glob_cfg->offscreen_x, glob_cfg->offscreen_y,
  299. glob_cfg->total_x, glob_cfg->total_y,
  300. glob_cfg->region_ptrs[0], glob_cfg->region_ptrs[1],
  301. glob_cfg->region_ptrs[2], glob_cfg->region_ptrs[3],
  302. glob_cfg->region_ptrs[4], glob_cfg->region_ptrs[5],
  303. glob_cfg->region_ptrs[6], glob_cfg->region_ptrs[7],
  304. glob_cfg->reent_lvl,
  305. glob_cfg->save_addr);
  306. sti_dump_globcfg_ext(PTR_STI(glob_cfg->ext_ptr));
  307. }
  308. static void __init
  309. sti_init_glob_cfg(struct sti_struct *sti, unsigned long hpa,
  310.   unsigned long rom_address)
  311. {
  312. struct sti_glob_cfg *glob_cfg;
  313. struct sti_glob_cfg_ext *glob_cfg_ext;
  314. void *save_addr;
  315. void *sti_mem_addr;
  316. glob_cfg = kmalloc(sizeof *sti->glob_cfg, GFP_KERNEL);
  317. glob_cfg_ext = kmalloc(sizeof *glob_cfg_ext, GFP_KERNEL);
  318. save_addr = kmalloc(1024 /*XXX*/, GFP_KERNEL);
  319. sti_mem_addr = kmalloc(1024, GFP_KERNEL);
  320. if((!glob_cfg) || (!glob_cfg_ext) || (!save_addr) || (!sti_mem_addr))
  321. return;
  322. memset(glob_cfg, 0, sizeof *glob_cfg);
  323. memset(glob_cfg_ext, 0, sizeof *glob_cfg_ext);
  324. memset(save_addr, 0, 1024);
  325. memset(sti_mem_addr, 0, 1024);
  326. glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext);
  327. glob_cfg->save_addr = STI_PTR(save_addr);
  328. glob_cfg->region_ptrs[0] = ((sti->regions[0]>>18)<<12) + rom_address;
  329. glob_cfg->region_ptrs[1] = ((sti->regions[1]>>18)<<12) + hpa;
  330. glob_cfg->region_ptrs[2] = ((sti->regions[2]>>18)<<12) + hpa;
  331. glob_cfg->region_ptrs[3] = ((sti->regions[3]>>18)<<12) + hpa;
  332. glob_cfg->region_ptrs[4] = ((sti->regions[4]>>18)<<12) + hpa;
  333. glob_cfg->region_ptrs[5] = ((sti->regions[5]>>18)<<12) + hpa;
  334. glob_cfg->region_ptrs[6] = ((sti->regions[6]>>18)<<12) + hpa;
  335. glob_cfg->region_ptrs[7] = ((sti->regions[7]>>18)<<12) + hpa;
  336. glob_cfg_ext->sti_mem_addr = STI_PTR(sti_mem_addr);
  337. sti->glob_cfg = STI_PTR(glob_cfg);
  338. }
  339. /* address is a pointer to a word mode or pci rom */
  340. static struct sti_struct * __init
  341. sti_read_rom(unsigned long address)
  342. {
  343. struct sti_struct *ret = NULL;
  344. struct sti_cooked_rom *cooked = NULL;
  345. struct sti_rom *raw = NULL;
  346. unsigned long size;
  347. ret = &default_sti;
  348. if(!ret)
  349. goto out_err;
  350. cooked = kmalloc(sizeof *cooked, GFP_KERNEL);
  351. raw = kmalloc(sizeof *raw, GFP_KERNEL);
  352. if(!(raw && cooked))
  353. goto out_err;
  354. /* reallocate raw */
  355. sti_rom_copy(address, 0, sizeof *raw, raw);
  356. dump_sti_rom(raw);
  357. size = raw->last_addr;
  358. /* kfree(raw); */
  359. raw = kmalloc(size, GFP_KERNEL);
  360. if(!raw)
  361. goto out_err;
  362. sti_rom_copy(address, 0, size, raw);
  363. sti_cook_fonts(cooked, raw);
  364. #if 0
  365. sti_cook_regions(cooked, raw);
  366. sti_cook_functions(cooked, raw);
  367. #endif
  368. if(raw->region_list) {
  369. ret->regions = kmalloc(32, GFP_KERNEL); /* FIXME */
  370. memcpy(ret->regions, ((void *)raw)+raw->region_list, 32);
  371. }
  372. address = virt_to_phys(raw);
  373. ret->font_unpmv = address+(raw->font_unpmv & 0x03ffffff);
  374. ret->block_move = address+(raw->block_move & 0x03ffffff);
  375. ret->init_graph = address+(raw->init_graph & 0x03ffffff);
  376. ret->inq_conf = address+(raw->inq_conf     & 0x03ffffff);
  377. ret->rom = cooked;
  378. ret->rom->raw = raw;
  379. ret->font = (struct sti_rom_font *) virt_to_phys(sti_select_font(ret->rom)->raw);
  380. return ret;
  381. out_err:
  382. if(raw)
  383. kfree(raw);
  384. if(cooked)
  385. kfree(cooked);
  386. return NULL;
  387. }
  388. static struct sti_struct * __init
  389. sti_try_rom(unsigned long address, unsigned long hpa)
  390. {
  391. struct sti_struct *sti = NULL;
  392. u16 sig;
  393. test_rom:
  394. /* if we can't read the ROM, bail out early.  Not being able
  395.  * to read the hpa is okay, for romless sti */
  396. if(pdc_add_valid((void*)address))
  397. return NULL;
  398. printk("found potential STI ROM at %08lxn", address);
  399. sig = le16_to_cpu(gsc_readw(address));
  400. if((sig==0x55aa) || (sig==0xaa55)) {
  401. address += le32_to_cpu(gsc_readl(address+8));
  402. printk("sig %04x, PCI STI ROM at %08lxn",
  403.        sig, address);
  404. goto test_rom;
  405. }
  406. if((sig&0xff) == 0x01) {
  407. printk("STI byte mode ROM at %08lx, ignoredn",
  408.        address);
  409. sti = NULL;
  410. }
  411. if(sig == 0x0303) {
  412. printk("STI word mode ROM at %08lxn",
  413.        address);
  414. sti = sti_read_rom(address);
  415. }
  416. if (!sti)
  417. return NULL;
  418. /* this is hacked.  We need a better way to find out the HPA for
  419.  * romless STI (eg search for the graphics devices we know about
  420.  * by sversion) */
  421. if (!pdc_add_valid((void *)0xf5000000)) printk("f4000000 gn");
  422. if (!pdc_add_valid((void *)0xf7000000)) printk("f6000000 gn");
  423. if (!pdc_add_valid((void *)0xf9000000)) printk("f8000000 gn");
  424. if (!pdc_add_valid((void *)0xfb000000)) printk("fa000000 gn");
  425. sti_init_glob_cfg(sti, hpa, address);
  426. sti_init_graph(sti);
  427. sti_inq_conf(sti);
  428. sti_dump_globcfg(PTR_STI(sti->glob_cfg));
  429. return sti;
  430. }
  431. static unsigned long sti_address;
  432. static unsigned long sti_hpa;
  433. /* XXX: should build a list of STI ROMs */
  434. struct sti_struct * __init
  435. sti_init_roms(void)
  436. {
  437. struct sti_struct *tmp = NULL, *sti = NULL;
  438. /* handle the command line */
  439. if (sti_address && sti_hpa) {
  440. return sti_try_rom(sti_address, sti_hpa);
  441. }
  442. /* 712, 715, some other boxes don't have a separate STI ROM,
  443.  * but use part of the regular flash */
  444. if (PAGE0->proc_sti) {
  445. printk("STI ROM from PDC at %08xn", PAGE0->proc_sti);
  446. if (!pdc_add_valid((void *)0xf9000000))
  447. sti = sti_try_rom(PAGE0->proc_sti, 0xf8000000);
  448. else if (!pdc_add_valid((void *)0xf5000000))
  449. sti = sti_try_rom(PAGE0->proc_sti, 0xf4000000);
  450. else if (!pdc_add_valid((void *)0xf7000000))
  451. sti = sti_try_rom(PAGE0->proc_sti, 0xf6000000);
  452. else if (!pdc_add_valid((void *)0xfb000000))
  453. sti = sti_try_rom(PAGE0->proc_sti, 0xfa000000);
  454. }
  455. /* standard locations for GSC graphic devices */
  456. if (!pdc_add_valid((void *)0xf4000000))
  457. tmp = sti_try_rom(0xf4000000, 0xf4000000);
  458. sti = tmp ? tmp : sti;
  459. if (!pdc_add_valid((void *)0xf6000000))
  460. tmp = sti_try_rom(0xf6000000, 0xf6000000);
  461. sti = tmp ? tmp : sti;
  462. if (!pdc_add_valid((void *)0xf8000000))
  463. tmp = sti_try_rom(0xf8000000, 0xf8000000);
  464. sti = tmp ? tmp : sti;
  465. if (!pdc_add_valid((void *)0xfa000000))
  466. tmp = sti_try_rom(0xfa000000, 0xfa000000);
  467. sti = tmp ? tmp : sti;
  468. return sti;
  469. }
  470. static int __init
  471. sti_setup(char *str)
  472. {
  473. char *end;
  474. if(strcmp(str, "pdc") == 0) {
  475. sti_address = PAGE0->proc_sti;
  476. return 1;
  477. } else {
  478. sti_address = simple_strtoul(str, &end, 16);
  479. if((end == str) || (sti_address < 0xf0000000)) {
  480. sti_address = 0;
  481. return 0;
  482. }
  483. sti_hpa = sti_address;
  484. return 1;
  485. }
  486. return 0;
  487. }
  488. __setup("sti=", sti_setup);
  489. MODULE_LICENSE("GPL");