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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2. TPG CVS users: please don't commit changes to this file directly, send
  3. them to prumpf@tux.org and wait for a new version instead.  Otherwise,
  4. your changes will get lost when prumpf releases the next version, as
  5. this file *will* be replaced with it.  You have been warned.
  6. 2000-05-30, <deller@gmx.de>
  7. */
  8. #if 1
  9. #define DPRINTK(x) printk x
  10. #else
  11. #define DPRINTK(x)
  12. #endif
  13. /*
  14.  *  linux/drivers/video/sticon.c  - console driver using HP's STI firmware
  15.  *
  16.  * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
  17.  *
  18.  *  Based on linux/drivers/video/vgacon.c and linux/drivers/video/fbcon.c,
  19.  *  which were
  20.  *
  21.  * Created 28 Sep 1997 by Geert Uytterhoeven
  22.  * Rewritten by Martin Mares <mj@ucw.cz>, July 1998
  23.  * Copyright (C) 1991, 1992  Linus Torvalds
  24.  *     1995  Jay Estabrook
  25.  * Copyright (C) 1995 Geert Uytterhoeven
  26.  * Copyright (C) 1993 Bjoern Brauel
  27.  *    Roman Hodek
  28.  * Copyright (C) 1993 Hamish Macdonald
  29.  *    Greg Harp
  30.  * Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
  31.  *
  32.  *       with work by William Rucklidge (wjr@cs.cornell.edu)
  33.  *    Geert Uytterhoeven
  34.  *    Jes Sorensen (jds@kom.auc.dk)
  35.  *    Martin Apel
  36.  *       with work by Guenther Kelleter
  37.  *    Martin Schaller
  38.  *    Andreas Schwab
  39.  *    Emmanuel Marty (core@ggi-project.org)
  40.  *    Jakub Jelinek (jj@ultra.linux.cz)
  41.  *    Martin Mares <mj@ucw.cz>
  42.  *
  43.  *  This file is subject to the terms and conditions of the GNU General Public
  44.  *  License.  See the file COPYING in the main directory of this archive for
  45.  *  more details.
  46.  */
  47. /*
  48.  *  TODO:
  49.  *   - call STI in virtual mode rather than in real mode
  50.  *   - support for PCI-only STI ROMs (which don't have a traditional region
  51.  *     list)
  52.  *   - safe detection (i.e. verify there is a graphics device at a given
  53.  *     address first, not just read a random device's io space)
  54.  *   - support for multiple STI devices in one machine
  55.  *   - support for byte-mode STI ROMs
  56.  *   - support for just using STI to switch to a colour fb (stifb ?)
  57.  *   - try to make it work on m68k hp workstations ;)
  58.  */
  59. #include <linux/types.h>
  60. #include <linux/sched.h>
  61. #include <linux/fs.h>
  62. #include <linux/kernel.h>
  63. #include <linux/tty.h>
  64. #include <linux/console.h>
  65. #include <linux/string.h>
  66. #include <linux/kd.h>
  67. #include <linux/slab.h>
  68. #include <linux/vt_kern.h>
  69. #include <linux/selection.h>
  70. #include <linux/ioport.h>
  71. #include <linux/init.h>
  72. #include <linux/delay.h>
  73. #include <asm/io.h>
  74. #include <asm/real.h>
  75. #include <linux/module.h>
  76. #include <linux/fb.h>
  77. #include <linux/smp.h>
  78. #include <asm/irq.h>
  79. #include <asm/system.h>
  80. #include <asm/uaccess.h>
  81. #include <video/fbcon.h>
  82. #include <video/font.h>
  83. #include "sti-bmode.h"
  84. /* The latency of the STI functions cannot really be reduced by setting
  85.  * this to 0;  STI doesn't seem to be designed to allow calling a different
  86.  * function (or the same function with different arguments) after a
  87.  * function exited with 1 as return value.
  88.  *
  89.  * As all of the functions below could be called from interrupt context,
  90.  * we have to spin_lock_irqsave around the do { ret = bla(); } while(ret==1)
  91.  * block.  Really bad latency there.
  92.  *
  93.  * Probably the best solution to all this is have the generic code manage
  94.  * the screen buffer and a kernel thread to call STI occasionally.
  95.  * 
  96.  * Luckily, the frame buffer guys have the same problem so we can just wait
  97.  * for them to fix it and steal their solution.   prumpf
  98.  *
  99.  * Actually, another long-term viable solution is to completely do STI
  100.  * support in userspace - that way we avoid the potential license issues
  101.  * of using proprietary fonts, too. */
  102.  
  103. #define STI_WAIT 1
  104. #define STI_PTR(p) ( (typeof(p)) virt_to_phys(p))
  105. #define PTR_STI(p) ( (typeof(p)) phys_to_virt((unsigned long)p) )
  106. static struct sti_struct default_sti = {
  107. SPIN_LOCK_UNLOCKED,
  108. };
  109. static struct sti_font_flags default_font_flags = {
  110. STI_WAIT, 0, 0, NULL
  111. };
  112. /* The colour indices used by STI are
  113.  *   0 - Black
  114.  *   1 - White
  115.  *   2 - Red
  116.  *   3 - Yellow/Brown
  117.  *   4 - Green
  118.  *   5 - Cyan
  119.  *   6 - Blue
  120.  *   7 - Magenta
  121.  *
  122.  * So we have the same colours as VGA (basically one bit each for R, G, B),
  123.  * but have to translate them, anyway. */
  124. static u8 col_trans[8] = {
  125.         0, 6, 4, 5,
  126.         2, 7, 3, 1
  127. };
  128. #define c_fg(sti, c) col_trans[((c>> 8) & 7)]
  129. #define c_bg(sti, c) col_trans[((c>>11) & 7)]
  130. #define c_index(sti, c) (c&0xff)
  131. #define sti_onscreen_x(sti) (PTR_STI(sti->glob_cfg)->onscreen_x)
  132. #define sti_onscreen_y(sti) (PTR_STI(sti->glob_cfg)->onscreen_y)
  133. #define sti_font_x(sti) (STI_U8(PTR_STI(sti->font)->width))
  134. #define sti_font_y(sti) (STI_U8(PTR_STI(sti->font)->height))
  135. static struct sti_init_flags default_init_flags = {
  136. STI_WAIT, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, NULL
  137. };
  138. static void sti_init_graph(struct sti_struct *sti) 
  139. {
  140. struct sti_init_inptr_ext inptr_ext = {
  141. 0, { 0 }, 0, NULL
  142. };
  143. struct sti_init_inptr inptr = {
  144. 3, STI_PTR(&inptr_ext)
  145. };
  146. struct sti_init_outptr outptr = { 0 };
  147. unsigned long flags;
  148. s32 ret;
  149. spin_lock_irqsave(&sti->lock, flags);
  150. ret = STI_CALL(sti->init_graph, &default_init_flags, &inptr,
  151. &outptr, sti->glob_cfg);
  152. spin_unlock_irqrestore(&sti->lock, flags);
  153. sti->text_planes = outptr.text_planes;
  154. }
  155. #if 0
  156. static struct sti_conf_flags default_conf_flags = {
  157. STI_WAIT, 0, NULL
  158. };
  159. static void sti_inq_conf(struct sti_struct *sti)
  160. {
  161. struct sti_conf_inptr inptr = { NULL };
  162. struct sti_conf_outptr_ext outptr_ext = { future_ptr: NULL };
  163. struct sti_conf_outptr outptr = {
  164. ext_ptr: STI_PTR(&outptr_ext)
  165. };
  166. unsigned long flags;
  167. s32 ret;
  168. do {
  169. spin_lock_irqsave(&sti->lock, flags);
  170. ret = STI_CALL(sti->inq_conf, &default_conf_flags,
  171. &inptr, &outptr, sti->glob_cfg);
  172. spin_unlock_irqrestore(&sti->lock, flags);
  173. } while(ret == 1);
  174. }
  175. #endif
  176. static void sti_putc(struct sti_struct *sti, int c, int y, int x)
  177. {
  178. struct sti_font_inptr inptr = {
  179. (u32) sti->font, c_index(sti, c), c_fg(sti, c), c_bg(sti, c),
  180. x * sti_font_x(sti), y * sti_font_y(sti), NULL
  181. };
  182. struct sti_font_outptr outptr = {
  183. 0, NULL
  184. };
  185. s32 ret;
  186. unsigned long flags;
  187. do {
  188. spin_lock_irqsave(&sti->lock, flags);
  189. ret = STI_CALL(sti->font_unpmv, &default_font_flags,
  190. &inptr, &outptr, sti->glob_cfg);
  191. spin_unlock_irqrestore(&sti->lock, flags);
  192. } while(ret == 1);
  193. }
  194. static struct sti_blkmv_flags clear_blkmv_flags = {
  195. STI_WAIT, 1, 1, 0, 0, NULL
  196. };
  197. static void sti_set(struct sti_struct *sti, int src_y, int src_x,
  198. int height, int width, u8 color)
  199. {
  200. struct sti_blkmv_inptr inptr = {
  201. color, color,
  202. src_x, src_y ,
  203. src_x, src_y ,
  204. width, height,
  205. NULL
  206. };
  207. struct sti_blkmv_outptr outptr = { 0, NULL };
  208. s32 ret = 0;
  209. unsigned long flags;
  210. do {
  211. spin_lock_irqsave(&sti->lock, flags);
  212. ret = STI_CALL(sti->block_move, &clear_blkmv_flags,
  213. &inptr, &outptr, sti->glob_cfg);
  214. spin_unlock_irqrestore(&sti->lock, flags);
  215. } while(ret == 1);
  216. }
  217. static void sti_clear(struct sti_struct *sti, int src_y, int src_x,
  218. int height, int width)
  219. {
  220. struct sti_blkmv_inptr inptr = {
  221. 0, 0,
  222. src_x * sti_font_x(sti), src_y * sti_font_y(sti),
  223. src_x * sti_font_x(sti), src_y * sti_font_y(sti),
  224. width * sti_font_x(sti), height* sti_font_y(sti),
  225. NULL
  226. };
  227. struct sti_blkmv_outptr outptr = { 0, NULL };
  228. s32 ret = 0;
  229. unsigned long flags;
  230. do {
  231. spin_lock_irqsave(&sti->lock, flags);
  232. ret = STI_CALL(sti->block_move, &clear_blkmv_flags,
  233. &inptr, &outptr, sti->glob_cfg);
  234. spin_unlock_irqrestore(&sti->lock, flags);
  235. } while(ret == 1);
  236. }
  237. static struct sti_blkmv_flags default_blkmv_flags = {
  238. STI_WAIT, 0, 0, 0, 0, NULL
  239. };
  240. static void sti_bmove(struct sti_struct *sti, int src_y, int src_x,
  241. int dst_y, int dst_x, int height, int width)
  242. {
  243. struct sti_blkmv_inptr inptr = {
  244. 0, 0,
  245. src_x * sti_font_x(sti), src_y * sti_font_y(sti),
  246. dst_x * sti_font_x(sti), dst_y * sti_font_y(sti),
  247. width * sti_font_x(sti), height* sti_font_y(sti),
  248. NULL
  249. };
  250. struct sti_blkmv_outptr outptr = { 0, NULL };
  251. s32 ret = 0;
  252. unsigned long flags;
  253. do {
  254. spin_lock_irqsave(&sti->lock, flags);
  255. ret = STI_CALL(sti->block_move, &default_blkmv_flags,
  256. &inptr, &outptr, sti->glob_cfg);
  257. spin_unlock_irqrestore(&sti->lock, flags);
  258. } while(ret == 1);
  259. }
  260. /* STICON */
  261. static const char __init *sticon_startup(void)
  262. {
  263. return "STI console";
  264. }
  265. static int sticon_set_palette(struct vc_data *c, unsigned char *table)
  266. {
  267. return -EINVAL;
  268. }
  269. static int sticon_font_op(struct vc_data *c, struct console_font_op *op)
  270. {
  271. return -ENOSYS;
  272. }
  273. static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos)
  274. {
  275. sti_putc(&default_sti, c, ypos, xpos);
  276. }
  277. static void sticon_putcs(struct vc_data *conp, const unsigned short *s,
  278. int count, int ypos, int xpos)
  279. {
  280. while(count--) {
  281. sti_putc(&default_sti, scr_readw(s++), ypos, xpos++);
  282. }
  283. }
  284. static void sticon_cursor(struct vc_data *conp, int mode)
  285. {
  286. }
  287. static int sticon_scroll(struct vc_data *conp, int t, int b, int dir,
  288. int count)
  289. {
  290. struct sti_struct *sti = &default_sti;
  291. if(console_blanked)
  292. return 0;
  293. sticon_cursor(conp, CM_ERASE);
  294. switch(dir) {
  295. case SM_UP:
  296. sti_bmove(sti, t+count, 0, t, 0, b-t-count, conp->vc_cols);
  297. sti_clear(sti, b-count, 0, count, conp->vc_cols);
  298. break;
  299. case SM_DOWN:
  300. sti_bmove(sti, t, 0, t+count, 0, b-t-count, conp->vc_cols);
  301. sti_clear(sti, t, 0, count, conp->vc_cols);
  302. break;
  303. }
  304. return 0;
  305. }
  306. static void sticon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
  307. int height, int width)
  308. {
  309. sti_bmove(&default_sti, sy, sx, dy, dx, height, width);
  310. }
  311. static void sticon_init(struct vc_data *c, int init)
  312. {
  313. struct sti_struct *sti = &default_sti;
  314. int vc_cols, vc_rows;
  315. sti_set(sti, 0, 0, sti_onscreen_y(sti), sti_onscreen_x(sti), 0);
  316. c->vc_can_do_color = 1;
  317. vc_cols = PTR_STI(sti->glob_cfg)->onscreen_x / sti_font_x(sti);
  318. vc_rows = PTR_STI(sti->glob_cfg)->onscreen_y / sti_font_y(sti);
  319. vc_resize_con(vc_rows, vc_cols, c->vc_num);
  320. }
  321. static void sticon_deinit(struct vc_data *c)
  322. {
  323. }
  324. static void sticon_clear(struct vc_data *conp, int sy, int sx, int height,
  325. int width)
  326. {
  327. sti_clear(&default_sti, sy, sx, height, width);
  328. }
  329. static int sticon_switch(struct vc_data *conp)
  330. {
  331. return 0;
  332. }
  333. static int sticon_blank(struct vc_data *conp, int blank)
  334. {
  335. return 0;
  336. }
  337. static int sticon_scrolldelta(struct vc_data *conp, int lines)
  338. {
  339. return 0;
  340. }
  341. static int sticon_set_origin(struct vc_data *conp)
  342. {
  343. return 0;
  344. }
  345. static u8 sticon_build_attr(struct vc_data *conp, u8 color, u8 intens, u8 blink, u8 underline, u8 reverse)
  346. {
  347. u8 attr = ((color & 0x70) >> 1) | ((color & 7));
  348. if(reverse) {
  349. color = ((color>>3)&0x7) | ((color &0x7)<<3);
  350. }
  351. return attr;
  352. }
  353. static struct consw sti_con = {
  354. con_startup:  sticon_startup, 
  355. con_init:  sticon_init,
  356. con_deinit:  sticon_deinit,
  357. con_clear:  sticon_clear,
  358. con_putc:  sticon_putc,
  359. con_putcs:  sticon_putcs,
  360. con_cursor:  sticon_cursor,
  361. con_scroll:  sticon_scroll,
  362. con_bmove:  sticon_bmove,
  363. con_switch:  sticon_switch,
  364. con_blank:  sticon_blank,
  365. con_font_op: sticon_font_op,
  366. con_set_palette: sticon_set_palette,
  367. con_scrolldelta: sticon_scrolldelta,
  368. con_set_origin:  sticon_set_origin,
  369. con_build_attr: sticon_build_attr,
  370. };
  371. #include <asm/pgalloc.h> /* need cache flush routines */
  372. static void __init sti_rom_copy(unsigned long base, unsigned long offset,
  373. unsigned long count, void *dest)
  374. {
  375. void *savedest = dest;
  376. int savecount = count;
  377. while(count >= 4) {
  378. count -= 4;
  379. *(u32 *)dest = gsc_readl(base + offset);
  380. #if 0
  381. DPRINTK(("%08xn", *(u32 *)dest));
  382. if(*(u32 *)dest == 0x64646464) {
  383.   DPRINTK(("!!!!n"));
  384.   { u32 foo = 0; while(foo += 0x100); }
  385. }
  386. #endif
  387. offset += 4;
  388. dest += 4;
  389. }
  390. while(count) {
  391. count--;
  392. *(u8 *)dest = gsc_readb(base + offset);
  393. offset++;
  394. dest++;
  395. }
  396. flush_kernel_dcache_range((unsigned long)dest, count);
  397. flush_icache_range((unsigned long)dest, dest + count);
  398. }
  399. static void dump_sti_rom(struct sti_rom *rom)
  400. {
  401. printk("STI byte mode ROM type %dn", STI_U8(rom->type));
  402. printk(" supports %d monitorsn", STI_U8(rom->num_mons));
  403. printk(" conforms to STI ROM spec revision %d.%02xn",
  404. STI_U8(rom->revno[0]) >> 4, STI_U8(rom->revno[0]) & 0x0f);
  405. printk(__FUNCTION__ ": %dn", __LINE__);
  406. printk(" graphics id %02x%02x%02x%02x%02x%02x%02x%02xn",
  407. (unsigned int) STI_U8(rom->graphics_id[0]), 
  408. (unsigned int) STI_U8(rom->graphics_id[1]), 
  409. (unsigned int) STI_U8(rom->graphics_id[2]), 
  410. (unsigned int) STI_U8(rom->graphics_id[3]), 
  411. (unsigned int) STI_U8(rom->graphics_id[4]), 
  412. (unsigned int) STI_U8(rom->graphics_id[5]), 
  413. (unsigned int) STI_U8(rom->graphics_id[6]), 
  414. (unsigned int) STI_U8(rom->graphics_id[7]));
  415. printk(__FUNCTION__ ": %dn", __LINE__);
  416. printk(" font start %08xn",  STI_U32(rom->font_start));
  417. printk(__FUNCTION__ ": %dn", __LINE__);
  418. printk(" region list %08xn", STI_U32(rom->region_list));
  419. printk(__FUNCTION__ ": %dn", __LINE__);
  420. printk(" init_graph %08xn",  STI_U32(rom->init_graph));
  421. printk(__FUNCTION__ ": %dn", __LINE__);
  422. printk(" alternate code type %dn", STI_U8(rom->alt_code_type));
  423. printk(__FUNCTION__ ": %dn", __LINE__);
  424. }
  425. static void __init sti_cook_fonts(struct sti_cooked_rom *cooked_rom,
  426.   struct sti_rom *raw_rom)
  427. {
  428. struct sti_rom_font *raw_font;
  429. struct sti_cooked_font *cooked_font;
  430. struct sti_rom_font *font_start;
  431. cooked_font =
  432. kmalloc(sizeof *cooked_font, GFP_KERNEL);
  433. if(!cooked_font)
  434. return;
  435. cooked_rom->font_start = cooked_font;
  436. #if 0
  437. DPRINTK(("%p = %p + %08xn",
  438.        ((void *)raw_rom) + (STI_U32(raw_rom->font_start)),
  439.        ((void *)raw_rom), (STI_U32(raw_rom->font_start))));
  440. #endif
  441. raw_font = ((void *)raw_rom) + STI_U32(raw_rom->font_start) - 3;
  442. font_start = raw_font;
  443. cooked_font->raw = raw_font;
  444. DPRINTK(("next font %08xn", STI_U32(raw_font->next_font)));
  445. while(0 && STI_U32(raw_font->next_font)) {
  446. raw_font = ((void *)font_start) + STI_U32(raw_font->next_font);
  447. cooked_font->next_font =
  448. kmalloc(sizeof *cooked_font, GFP_KERNEL);
  449. if(!cooked_font->next_font)
  450. return;
  451. cooked_font = cooked_font->next_font;
  452. // cooked_font->raw = raw_font;
  453. DPRINTK(("raw_font %pn",
  454.        raw_font));
  455. DPRINTK(("next_font %08x %pn",
  456.        STI_U32(raw_font->next_font),
  457.        ((void *)font_start) + STI_U32(raw_font->next_font)));
  458. }
  459. cooked_font->next_font = NULL;
  460. }
  461. static unsigned long __init sti_cook_function(void *function,
  462.       u32 size)
  463. {
  464. sti_u32 *func = (sti_u32 *)function;
  465. u32 *ret;
  466. int i;
  467. ret = kmalloc(size, GFP_KERNEL);
  468. if(!ret) {
  469. printk(KERN_ERR __FILE__ ": could not get memory.n");
  470. return 0;
  471. }
  472. for(i=0; i<(size/4); i++)
  473.     ret[i] = STI_U32(func[i]);
  474. flush_all_caches();
  475. return virt_to_phys(ret);
  476. }
  477. static int font_index, font_height, font_width;
  478. static int __init sti_search_font(struct sti_cooked_rom *rom,
  479.   int height, int width)
  480. {
  481. struct sti_cooked_font *font;
  482. int i = 0;
  483. for(font = rom->font_start; font; font = font->next_font, i++) {
  484. if((STI_U8(font->raw->width) == width) &&
  485.    (STI_U8(font->raw->height) == height))
  486. return i;
  487. }
  488. return 0;
  489. }
  490. static struct sti_cooked_font * __init
  491. sti_select_font(struct sti_cooked_rom *rom)
  492. {
  493. struct sti_cooked_font *font;
  494. int i;
  495. if(font_width && font_height)
  496. font_index = sti_search_font(rom, font_height, font_width);
  497. for(font = rom->font_start, i = font_index;
  498.     font && (i > 0);
  499.     font = font->next_font, i--);
  500. if(font)
  501. return font;
  502. else
  503. return rom->font_start;
  504. }
  505. /* address is a pointer to a word mode or pci rom */
  506. static struct sti_struct * __init sti_read_rom(unsigned long address)
  507. {
  508. struct sti_struct *ret = NULL;
  509. struct sti_cooked_rom *cooked = NULL;
  510. struct sti_rom *raw = NULL;
  511. unsigned long size;
  512. ret = &default_sti;
  513. if(!ret)
  514. goto out_err;
  515. cooked = kmalloc(sizeof *cooked, GFP_KERNEL);
  516. raw = kmalloc(sizeof *raw, GFP_KERNEL);
  517. if(!(raw && cooked))
  518. goto out_err;
  519. /* reallocate raw */
  520. sti_rom_copy(address, 0, sizeof *raw, raw);
  521. dump_sti_rom(raw);
  522. size = STI_U32(raw->last_addr) + 1;
  523. size = 128*1024;
  524. // DPRINTK(("size %08lxn", size));
  525. // DPRINTK(("font_start %08xn", STI_U32(raw->font_start)));
  526. // kfree(raw);
  527. raw = kmalloc(size, GFP_KERNEL);
  528. if(!raw)
  529. goto out_err;
  530. sti_rom_copy(address, 0, size-1, raw);
  531. sti_cook_fonts(cooked, raw);
  532. // sti_cook_regions(cooked, raw);
  533. // sti_cook_functions(cooked, raw);
  534. if(STI_U32(raw->region_list)) {
  535. struct sti_rom_region *region =
  536. ((void *)raw) + STI_U32(raw->region_list) - 3;
  537. // DPRINTK(("region_list %08xn", STI_U32(raw->region_list)));
  538. ret->regions = kmalloc(32, GFP_KERNEL); /* FIXME!! */
  539. ret->regions[0] = STI_U32(region[0].region);
  540. ret->regions[1] = STI_U32(region[1].region);
  541. ret->regions[2] = STI_U32(region[2].region);
  542. ret->regions[3] = STI_U32(region[3].region);
  543. ret->regions[4] = STI_U32(region[4].region);
  544. ret->regions[5] = STI_U32(region[5].region);
  545. ret->regions[6] = STI_U32(region[6].region);
  546. ret->regions[7] = STI_U32(region[7].region);
  547. }
  548. address = virt_to_phys(raw);
  549. #if 0
  550. DPRINTK(("init_graph %08x %08xn"
  551.        "state_mgmt %08x %08xn"
  552.        "font_unpmv %08x %08xn"
  553.        "block_move %08x %08xn"
  554.        "self_test  %08x %08xn"
  555.        "excep_hdlr %08x %08xn"
  556.        "irq_conf   %08x %08xn"
  557.        "set_cm_e   %08x %08xn"
  558.        "dma_ctrl   %08x %08xn"
  559.        "flow_ctrl  %08x %08xn"
  560.        "user_timin %08x %08xn"
  561.        "process_m  %08x %08xn"
  562.        "sti_util   %08x %08xn"
  563.        "end_addr   %08x %08xn",
  564.        STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
  565.        STI_U32(raw->state_mgmt), STI_U32(raw->state_mgmt_m68k),
  566.        STI_U32(raw->font_unpmv), STI_U32(raw->font_unpmv_m68k),
  567.        STI_U32(raw->block_move), STI_U32(raw->block_move_m68k),
  568.        STI_U32(raw->self_test), STI_U32(raw->self_test_m68k),
  569.        STI_U32(raw->excep_hdlr), STI_U32(raw->excep_hdlr_m68k),
  570.        STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
  571.        STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
  572.        STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
  573.        STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
  574.        STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
  575.        STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
  576.        STI_U32(raw->init_graph), STI_U32(raw->init_graph_m68k),
  577.        STI_U32(raw->end_addr), STI_U32(raw->end_addr_m68k) ) );
  578. #endif
  579. ret->init_graph = sti_cook_function(((void *)raw)+STI_U32(raw->init_graph)-3,
  580.     (STI_U32(raw->state_mgmt) -
  581.      STI_U32(raw->init_graph))/4);
  582. ret->font_unpmv = sti_cook_function(((void *)raw)+STI_U32(raw->font_unpmv)-3,
  583.     (STI_U32(raw->block_move) -
  584.      STI_U32(raw->font_unpmv))/4);
  585. ret->block_move = sti_cook_function(((void *)raw)+STI_U32(raw->block_move)-3,
  586.     (STI_U32(raw->self_test) -
  587.      STI_U32(raw->block_move))/4);
  588. ret->inq_conf = sti_cook_function(((void *)raw)+STI_U32(raw->inq_conf),
  589.   STI_U32(raw->set_cm_entry) -
  590.   STI_U32(raw->inq_conf));
  591. ret->rom = cooked;
  592. ret->rom->raw = raw;
  593. ret->font = (struct sti_rom_font *) virt_to_phys(sti_select_font(ret->rom)->raw);
  594. return ret;
  595. out_err:
  596. if(raw)
  597. kfree(raw);
  598. if(cooked)
  599. kfree(cooked);
  600. return NULL;
  601. }
  602. #if 0
  603. static void dump_globcfg_ext(struct sti_glob_cfg_ext *cfg)
  604. {
  605. DPRINTK(("monitor %dn"
  606. "in friendly mode: %dn"
  607. "power consumption %d wattsn"
  608. "freq ref %dn"
  609. "sti_mem_addr %pn",
  610. cfg->curr_mon,
  611. cfg->friendly_boot,
  612. cfg->power,
  613. cfg->freq_ref,
  614. cfg->sti_mem_addr));
  615. }
  616. static void dump_globcfg(struct sti_glob_cfg *glob_cfg)
  617. {
  618. DPRINTK(("%d text planesn"
  619. "%4d x %4d screen resolutionn"
  620. "%4d x %4d offscreenn"
  621. "%4d x %4d layoutn"
  622. "regions at %08x %08x %08x %08xn"
  623. "regions at %08x %08x %08x %08xn"
  624. "reent_lvl %dn"
  625. "save_addr %pn",
  626. glob_cfg->text_planes,
  627. glob_cfg->onscreen_x, glob_cfg->onscreen_y,
  628. glob_cfg->offscreen_x, glob_cfg->offscreen_y,
  629. glob_cfg->total_x, glob_cfg->total_y,
  630. glob_cfg->region_ptrs[0], glob_cfg->region_ptrs[1],
  631. glob_cfg->region_ptrs[2], glob_cfg->region_ptrs[3],
  632. glob_cfg->region_ptrs[4], glob_cfg->region_ptrs[5],
  633. glob_cfg->region_ptrs[6], glob_cfg->region_ptrs[7],
  634. glob_cfg->reent_lvl,
  635. glob_cfg->save_addr));
  636. dump_globcfg_ext(PTR_STI(glob_cfg->ext_ptr));
  637. }
  638. #endif
  639. static void __init sti_init_glob_cfg(struct sti_struct *sti, unsigned long hpa,
  640.      unsigned long rom_address)
  641. {
  642. struct sti_glob_cfg *glob_cfg;
  643. struct sti_glob_cfg_ext *glob_cfg_ext;
  644. void *save_addr;
  645. void *sti_mem_addr;
  646. glob_cfg = kmalloc(sizeof *sti->glob_cfg, GFP_KERNEL);
  647. glob_cfg_ext = kmalloc(sizeof *glob_cfg_ext, GFP_KERNEL);
  648. save_addr = kmalloc(1024 /*XXX*/, GFP_KERNEL);
  649. sti_mem_addr = kmalloc(1024, GFP_KERNEL);
  650. if((!glob_cfg) || (!glob_cfg_ext) || (!save_addr) || (!sti_mem_addr))
  651. return;
  652. memset(glob_cfg, 0, sizeof *glob_cfg);
  653. memset(glob_cfg_ext, 0, sizeof *glob_cfg_ext);
  654. memset(save_addr, 0, 1024);
  655. memset(sti_mem_addr, 0, 1024);
  656. glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext);
  657. glob_cfg->save_addr = STI_PTR(save_addr);
  658. glob_cfg->region_ptrs[0] = ((sti->regions[0]>>18)<<12) + rom_address;
  659. glob_cfg->region_ptrs[1] = ((sti->regions[1]>>18)<<12) + hpa;
  660. glob_cfg->region_ptrs[2] = ((sti->regions[2]>>18)<<12) + hpa;
  661. glob_cfg->region_ptrs[3] = ((sti->regions[3]>>18)<<12) + hpa;
  662. glob_cfg->region_ptrs[4] = ((sti->regions[4]>>18)<<12) + hpa;
  663. glob_cfg->region_ptrs[5] = ((sti->regions[5]>>18)<<12) + hpa;
  664. glob_cfg->region_ptrs[6] = ((sti->regions[6]>>18)<<12) + hpa;
  665. glob_cfg->region_ptrs[7] = ((sti->regions[7]>>18)<<12) + hpa;
  666. glob_cfg_ext->sti_mem_addr = STI_PTR(sti_mem_addr);
  667. sti->glob_cfg = STI_PTR(glob_cfg);
  668. }
  669. static void __init sti_try_rom(unsigned long address, unsigned long hpa)
  670. {
  671. struct sti_struct *sti = NULL;
  672. u16 sig;
  673. /* if we can't read the ROM, bail out early.  Not being able
  674.  * to read the hpa is okay, for romless sti */
  675. if(pdc_add_valid((void*)address))
  676. return;
  677. printk("found potential STI ROM at %08lxn", address);
  678. sig = le16_to_cpu(gsc_readw(address));
  679. if((sig&0xff) == 0x01) {
  680. sti = sti_read_rom(address);
  681. }
  682. if(sig == 0x0303) {
  683. printk("STI word mode ROM at %08lx, ignoredn",
  684.        address);
  685. sti = NULL;
  686. }
  687. if(!sti)
  688. return;
  689. /* this is hacked.  We need a better way to find out the HPA for
  690.  * romless STI (eg search for the graphics devices we know about
  691.  * by sversion) */
  692. if (!pdc_add_valid((void *)0xf5000000)) DPRINTK(("f4000000 bn"));
  693. if (!pdc_add_valid((void *)0xf7000000)) DPRINTK(("f6000000 bn"));
  694. if (!pdc_add_valid((void *)0xf9000000)) DPRINTK(("f8000000 bn"));
  695. if (!pdc_add_valid((void *)0xfb000000)) DPRINTK(("fa000000 bn"));
  696. sti_init_glob_cfg(sti, hpa, address);
  697. sti_init_graph(sti);
  698. //sti_inq_conf(sti);
  699. #if !defined(SERIAL_CONSOLE)
  700.     extern void pdc_console_die(void);  
  701.     pdc_console_die(); 
  702. }
  703. #endif
  704. take_over_console(&sti_con, 0, MAX_NR_CONSOLES-1, 1);
  705. /* sti_inq_conf(sti); */
  706. }
  707. static unsigned long sti_address;
  708. static unsigned long sti_hpa;
  709. static void __init sti_init_roms(void)
  710. {
  711. /* handle the command line */
  712. if(sti_address && sti_hpa) {
  713. sti_try_rom(sti_address, sti_hpa);
  714. return;
  715. }
  716. /* 712, 715, some other boxes don't have a separate STI ROM,
  717.  * but use part of the regular flash */
  718. if(PAGE0->proc_sti) {
  719. printk("STI ROM from PDC at %08xn", PAGE0->proc_sti);
  720. if(!pdc_add_valid((void *)0xf9000000))
  721. sti_try_rom(PAGE0->proc_sti, 0xf8000000);
  722. else if(!pdc_add_valid((void *)0xf5000000))
  723. sti_try_rom(PAGE0->proc_sti, 0xf4000000);
  724. else if(!pdc_add_valid((void *)0xf7000000))
  725. sti_try_rom(PAGE0->proc_sti, 0xf6000000);
  726. else if(!pdc_add_valid((void *)0xfb000000))
  727. sti_try_rom(PAGE0->proc_sti, 0xfa000000);
  728. }
  729. /* standard locations for GSC graphic devices */
  730. if(!pdc_add_valid((void *)0xf4000000))
  731. sti_try_rom(0xf4000000, 0xf4000000);
  732. if(!pdc_add_valid((void *)0xf6000000))
  733. sti_try_rom(0xf6000000, 0xf6000000);
  734. if(!pdc_add_valid((void *)0xf8000000))
  735. sti_try_rom(0xf8000000, 0xf8000000);
  736. if(!pdc_add_valid((void *)0xfa000000))
  737. sti_try_rom(0xfa000000, 0xfa000000);
  738. }
  739. static int __init sti_init(void)
  740. {
  741. printk("searching for byte mode STI ROMsn");
  742. sti_init_roms();
  743. return 0;
  744. }
  745. module_init(sti_init)
  746. MODULE_LICENSE("GPL");