vreset.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805
  1. /*
  2. * vreset.c
  3. *
  4. * Initialize the VGA control registers to 80x25 text mode.
  5. *
  6. * Adapted from a program by:
  7. * Steve Sellgren
  8. * San Francisco Indigo Company
  9. * sfindigo!sellgren@uunet.uu.net
  10. *
  11. * Original concept by:
  12. * Gary Thomas <gdt@linuxppc.org>
  13. * Adapted for Moto boxes by:
  14. * Pat Kane & Mark Scott, 1996
  15. * Adapted for IBM portables by:
  16. * Takeshi Ishimoto
  17. * Multi-console support:
  18. * Terje Malmedal <terje.malmedal@usit.uio.no>
  19. */
  20. #include "iso_font.h"
  21. #include "nonstdio.h"
  22. extern char *vidmem;
  23. extern int lines, cols;
  24. struct VaRegs;
  25. /*
  26. * VGA Register
  27. */
  28. struct VgaRegs
  29. {
  30. unsigned short io_port;
  31. unsigned char io_index;
  32. unsigned char io_value;
  33. };
  34. void unlockVideo(int slot);
  35. void setTextRegs(struct VgaRegs *svp);
  36. void setTextCLUT(int shift);
  37. void clearVideoMemory(void);
  38. void loadFont(unsigned char *ISA_mem);
  39. static void mdelay(int ms)
  40. {
  41. for (; ms > 0; --ms)
  42. udelay(1000);
  43. }
  44. /*
  45. * Default console text mode registers used to reset
  46. * graphics adapter.
  47. */
  48. #define NREGS 54
  49. #define ENDMK 0xFFFF /* End marker */
  50. #define S3Vendor 0x5333
  51. #define CirrusVendor 0x1013
  52. #define DiamondVendor 0x100E
  53. #define MatroxVendor 0x102B
  54. #define ParadiseVendor 0x101C
  55. struct VgaRegs GenVgaTextRegs[NREGS+1] = {
  56. /* port index value */
  57. /* SR Regs */
  58. { 0x3c4, 0x1, 0x0 },
  59. { 0x3c4, 0x2, 0x3 },
  60. { 0x3c4, 0x3, 0x0 },
  61. { 0x3c4, 0x4, 0x2 },
  62. /* CR Regs */
  63. { 0x3d4, 0x0, 0x5f },
  64. { 0x3d4, 0x1, 0x4f },
  65. { 0x3d4, 0x2, 0x50 },
  66. { 0x3d4, 0x3, 0x82 },
  67. { 0x3d4, 0x4, 0x55 },
  68. { 0x3d4, 0x5, 0x81 },
  69. { 0x3d4, 0x6, 0xbf },
  70. { 0x3d4, 0x7, 0x1f },
  71. { 0x3d4, 0x8, 0x00 },
  72. { 0x3d4, 0x9, 0x4f },
  73. { 0x3d4, 0xa, 0x0d },
  74. { 0x3d4, 0xb, 0x0e },
  75. { 0x3d4, 0xc, 0x00 },
  76. { 0x3d4, 0xd, 0x00 },
  77. { 0x3d4, 0xe, 0x00 },
  78. { 0x3d4, 0xf, 0x00 },
  79. { 0x3d4, 0x10, 0x9c },
  80. { 0x3d4, 0x11, 0x8e },
  81. { 0x3d4, 0x12, 0x8f },
  82. { 0x3d4, 0x13, 0x28 },
  83. { 0x3d4, 0x14, 0x1f },
  84. { 0x3d4, 0x15, 0x96 },
  85. { 0x3d4, 0x16, 0xb9 },
  86. { 0x3d4, 0x17, 0xa3 },
  87. /* GR Regs */
  88. { 0x3ce, 0x0, 0x0 },
  89. { 0x3ce, 0x1, 0x0 },
  90. { 0x3ce, 0x2, 0x0 },
  91. { 0x3ce, 0x3, 0x0 },
  92. { 0x3ce, 0x4, 0x0 },
  93. { 0x3ce, 0x5, 0x10 },
  94. { 0x3ce, 0x6, 0xe },
  95. { 0x3ce, 0x7, 0x0 },
  96. { 0x3ce, 0x8, 0xff },
  97. { ENDMK }
  98. };
  99. struct RGBColors
  100. {
  101. unsigned char r, g, b;
  102. };
  103. /*
  104. * Default console text mode color table.
  105. * These values were obtained by booting Linux with
  106. * text mode firmware & then dumping the registers.
  107. */
  108. struct RGBColors TextCLUT[256] =
  109. {
  110. /* red green blue */
  111. { 0x0, 0x0, 0x0 },
  112. { 0x0, 0x0, 0x2a },
  113. { 0x0, 0x2a, 0x0 },
  114. { 0x0, 0x2a, 0x2a },
  115. { 0x2a, 0x0, 0x0 },
  116. { 0x2a, 0x0, 0x2a },
  117. { 0x2a, 0x2a, 0x0 },
  118. { 0x2a, 0x2a, 0x2a },
  119. { 0x0, 0x0, 0x15 },
  120. { 0x0, 0x0, 0x3f },
  121. { 0x0, 0x2a, 0x15 },
  122. { 0x0, 0x2a, 0x3f },
  123. { 0x2a, 0x0, 0x15 },
  124. { 0x2a, 0x0, 0x3f },
  125. { 0x2a, 0x2a, 0x15 },
  126. { 0x2a, 0x2a, 0x3f },
  127. { 0x0, 0x15, 0x0 },
  128. { 0x0, 0x15, 0x2a },
  129. { 0x0, 0x3f, 0x0 },
  130. { 0x0, 0x3f, 0x2a },
  131. { 0x2a, 0x15, 0x0 },
  132. { 0x2a, 0x15, 0x2a },
  133. { 0x2a, 0x3f, 0x0 },
  134. { 0x2a, 0x3f, 0x2a },
  135. { 0x0, 0x15, 0x15 },
  136. { 0x0, 0x15, 0x3f },
  137. { 0x0, 0x3f, 0x15 },
  138. { 0x0, 0x3f, 0x3f },
  139. { 0x2a, 0x15, 0x15 },
  140. { 0x2a, 0x15, 0x3f },
  141. { 0x2a, 0x3f, 0x15 },
  142. { 0x2a, 0x3f, 0x3f },
  143. { 0x15, 0x0, 0x0 },
  144. { 0x15, 0x0, 0x2a },
  145. { 0x15, 0x2a, 0x0 },
  146. { 0x15, 0x2a, 0x2a },
  147. { 0x3f, 0x0, 0x0 },
  148. { 0x3f, 0x0, 0x2a },
  149. { 0x3f, 0x2a, 0x0 },
  150. { 0x3f, 0x2a, 0x2a },
  151. { 0x15, 0x0, 0x15 },
  152. { 0x15, 0x0, 0x3f },
  153. { 0x15, 0x2a, 0x15 },
  154. { 0x15, 0x2a, 0x3f },
  155. { 0x3f, 0x0, 0x15 },
  156. { 0x3f, 0x0, 0x3f },
  157. { 0x3f, 0x2a, 0x15 },
  158. { 0x3f, 0x2a, 0x3f },
  159. { 0x15, 0x15, 0x0 },
  160. { 0x15, 0x15, 0x2a },
  161. { 0x15, 0x3f, 0x0 },
  162. { 0x15, 0x3f, 0x2a },
  163. { 0x3f, 0x15, 0x0 },
  164. { 0x3f, 0x15, 0x2a },
  165. { 0x3f, 0x3f, 0x0 },
  166. { 0x3f, 0x3f, 0x2a },
  167. { 0x15, 0x15, 0x15 },
  168. { 0x15, 0x15, 0x3f },
  169. { 0x15, 0x3f, 0x15 },
  170. { 0x15, 0x3f, 0x3f },
  171. { 0x3f, 0x15, 0x15 },
  172. { 0x3f, 0x15, 0x3f },
  173. { 0x3f, 0x3f, 0x15 },
  174. { 0x3f, 0x3f, 0x3f },
  175. { 0x39, 0xc, 0x5 },
  176. { 0x15, 0x2c, 0xf },
  177. { 0x26, 0x10, 0x3d },
  178. { 0x29, 0x29, 0x38 },
  179. { 0x4, 0x1a, 0xe },
  180. { 0x2, 0x1e, 0x3a },
  181. { 0x3c, 0x25, 0x33 },
  182. { 0x3c, 0xc, 0x2c },
  183. { 0x3f, 0x3, 0x2b },
  184. { 0x1c, 0x9, 0x13 },
  185. { 0x25, 0x2a, 0x35 },
  186. { 0x1e, 0xa, 0x38 },
  187. { 0x24, 0x8, 0x3 },
  188. { 0x3, 0xe, 0x36 },
  189. { 0xc, 0x6, 0x2a },
  190. { 0x26, 0x3, 0x32 },
  191. { 0x5, 0x2f, 0x33 },
  192. { 0x3c, 0x35, 0x2f },
  193. { 0x2d, 0x26, 0x3e },
  194. { 0xd, 0xa, 0x10 },
  195. { 0x25, 0x3c, 0x11 },
  196. { 0xd, 0x4, 0x2e },
  197. { 0x5, 0x19, 0x3e },
  198. { 0xc, 0x13, 0x34 },
  199. { 0x2b, 0x6, 0x24 },
  200. { 0x4, 0x3, 0xd },
  201. { 0x2f, 0x3c, 0xc },
  202. { 0x2a, 0x37, 0x1f },
  203. { 0xf, 0x12, 0x38 },
  204. { 0x38, 0xe, 0x2a },
  205. { 0x12, 0x2f, 0x19 },
  206. { 0x29, 0x2e, 0x31 },
  207. { 0x25, 0x13, 0x3e },
  208. { 0x33, 0x3e, 0x33 },
  209. { 0x1d, 0x2c, 0x25 },
  210. { 0x15, 0x15, 0x5 },
  211. { 0x32, 0x25, 0x39 },
  212. { 0x1a, 0x7, 0x1f },
  213. { 0x13, 0xe, 0x1d },
  214. { 0x36, 0x17, 0x34 },
  215. { 0xf, 0x15, 0x23 },
  216. { 0x2, 0x35, 0xd },
  217. { 0x15, 0x3f, 0xc },
  218. { 0x14, 0x2f, 0xf },
  219. { 0x19, 0x21, 0x3e },
  220. { 0x27, 0x11, 0x2f },
  221. { 0x38, 0x3f, 0x3c },
  222. { 0x36, 0x2d, 0x15 },
  223. { 0x16, 0x17, 0x2 },
  224. { 0x1, 0xa, 0x3d },
  225. { 0x1b, 0x11, 0x3f },
  226. { 0x21, 0x3c, 0xd },
  227. { 0x1a, 0x39, 0x3d },
  228. { 0x8, 0xe, 0xe },
  229. { 0x22, 0x21, 0x23 },
  230. { 0x1e, 0x30, 0x5 },
  231. { 0x1f, 0x22, 0x3d },
  232. { 0x1e, 0x2f, 0xa },
  233. { 0x0, 0x1c, 0xe },
  234. { 0x0, 0x1c, 0x15 },
  235. { 0x0, 0x1c, 0x1c },
  236. { 0x0, 0x15, 0x1c },
  237. { 0x0, 0xe, 0x1c },
  238. { 0x0, 0x7, 0x1c },
  239. { 0xe, 0xe, 0x1c },
  240. { 0x11, 0xe, 0x1c },
  241. { 0x15, 0xe, 0x1c },
  242. { 0x18, 0xe, 0x1c },
  243. { 0x1c, 0xe, 0x1c },
  244. { 0x1c, 0xe, 0x18 },
  245. { 0x1c, 0xe, 0x15 },
  246. { 0x1c, 0xe, 0x11 },
  247. { 0x1c, 0xe, 0xe },
  248. { 0x1c, 0x11, 0xe },
  249. { 0x1c, 0x15, 0xe },
  250. { 0x1c, 0x18, 0xe },
  251. { 0x1c, 0x1c, 0xe },
  252. { 0x18, 0x1c, 0xe },
  253. { 0x15, 0x1c, 0xe },
  254. { 0x11, 0x1c, 0xe },
  255. { 0xe, 0x1c, 0xe },
  256. { 0xe, 0x1c, 0x11 },
  257. { 0xe, 0x1c, 0x15 },
  258. { 0xe, 0x1c, 0x18 },
  259. { 0xe, 0x1c, 0x1c },
  260. { 0xe, 0x18, 0x1c },
  261. { 0xe, 0x15, 0x1c },
  262. { 0xe, 0x11, 0x1c },
  263. { 0x14, 0x14, 0x1c },
  264. { 0x16, 0x14, 0x1c },
  265. { 0x18, 0x14, 0x1c },
  266. { 0x1a, 0x14, 0x1c },
  267. { 0x1c, 0x14, 0x1c },
  268. { 0x1c, 0x14, 0x1a },
  269. { 0x1c, 0x14, 0x18 },
  270. { 0x1c, 0x14, 0x16 },
  271. { 0x1c, 0x14, 0x14 },
  272. { 0x1c, 0x16, 0x14 },
  273. { 0x1c, 0x18, 0x14 },
  274. { 0x1c, 0x1a, 0x14 },
  275. { 0x1c, 0x1c, 0x14 },
  276. { 0x1a, 0x1c, 0x14 },
  277. { 0x18, 0x1c, 0x14 },
  278. { 0x16, 0x1c, 0x14 },
  279. { 0x14, 0x1c, 0x14 },
  280. { 0x14, 0x1c, 0x16 },
  281. { 0x14, 0x1c, 0x18 },
  282. { 0x14, 0x1c, 0x1a },
  283. { 0x14, 0x1c, 0x1c },
  284. { 0x14, 0x1a, 0x1c },
  285. { 0x14, 0x18, 0x1c },
  286. { 0x14, 0x16, 0x1c },
  287. { 0x0, 0x0, 0x10 },
  288. { 0x4, 0x0, 0x10 },
  289. { 0x8, 0x0, 0x10 },
  290. { 0xc, 0x0, 0x10 },
  291. { 0x10, 0x0, 0x10 },
  292. { 0x10, 0x0, 0xc },
  293. { 0x10, 0x0, 0x8 },
  294. { 0x10, 0x0, 0x4 },
  295. { 0x10, 0x0, 0x0 },
  296. { 0x10, 0x4, 0x0 },
  297. { 0x10, 0x8, 0x0 },
  298. { 0x10, 0xc, 0x0 },
  299. { 0x10, 0x10, 0x0 },
  300. { 0xc, 0x10, 0x0 },
  301. { 0x8, 0x10, 0x0 },
  302. { 0x4, 0x10, 0x0 },
  303. { 0x0, 0x10, 0x0 },
  304. { 0x0, 0x10, 0x4 },
  305. { 0x0, 0x10, 0x8 },
  306. { 0x0, 0x10, 0xc },
  307. { 0x0, 0x10, 0x10 },
  308. { 0x0, 0xc, 0x10 },
  309. { 0x0, 0x8, 0x10 },
  310. { 0x0, 0x4, 0x10 },
  311. { 0x8, 0x8, 0x10 },
  312. { 0xa, 0x8, 0x10 },
  313. { 0xc, 0x8, 0x10 },
  314. { 0xe, 0x8, 0x10 },
  315. { 0x10, 0x8, 0x10 },
  316. { 0x10, 0x8, 0xe },
  317. { 0x10, 0x8, 0xc },
  318. { 0x10, 0x8, 0xa },
  319. { 0x10, 0x8, 0x8 },
  320. { 0x10, 0xa, 0x8 },
  321. { 0x10, 0xc, 0x8 },
  322. { 0x10, 0xe, 0x8 },
  323. { 0x10, 0x10, 0x8 },
  324. { 0xe, 0x10, 0x8 },
  325. { 0xc, 0x10, 0x8 },
  326. { 0xa, 0x10, 0x8 },
  327. { 0x8, 0x10, 0x8 },
  328. { 0x8, 0x10, 0xa },
  329. { 0x8, 0x10, 0xc },
  330. { 0x8, 0x10, 0xe },
  331. { 0x8, 0x10, 0x10 },
  332. { 0x8, 0xe, 0x10 },
  333. { 0x8, 0xc, 0x10 },
  334. { 0x8, 0xa, 0x10 },
  335. { 0xb, 0xb, 0x10 },
  336. { 0xc, 0xb, 0x10 },
  337. { 0xd, 0xb, 0x10 },
  338. { 0xf, 0xb, 0x10 },
  339. { 0x10, 0xb, 0x10 },
  340. { 0x10, 0xb, 0xf },
  341. { 0x10, 0xb, 0xd },
  342. { 0x10, 0xb, 0xc },
  343. { 0x10, 0xb, 0xb },
  344. { 0x10, 0xc, 0xb },
  345. { 0x10, 0xd, 0xb },
  346. { 0x10, 0xf, 0xb },
  347. { 0x10, 0x10, 0xb },
  348. { 0xf, 0x10, 0xb },
  349. { 0xd, 0x10, 0xb },
  350. { 0xc, 0x10, 0xb },
  351. { 0xb, 0x10, 0xb },
  352. { 0xb, 0x10, 0xc },
  353. { 0xb, 0x10, 0xd },
  354. { 0xb, 0x10, 0xf },
  355. { 0xb, 0x10, 0x10 },
  356. { 0xb, 0xf, 0x10 },
  357. { 0xb, 0xd, 0x10 },
  358. { 0xb, 0xc, 0x10 },
  359. { 0x0, 0x0, 0x0 },
  360. { 0x0, 0x0, 0x0 },
  361. { 0x0, 0x0, 0x0 },
  362. { 0x0, 0x0, 0x0 },
  363. { 0x0, 0x0, 0x0 },
  364. { 0x0, 0x0, 0x0 },
  365. { 0x0, 0x0, 0x0 }
  366. };
  367. unsigned char AC[21] = {
  368. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07,
  369. 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
  370. 0x0C, 0x00, 0x0F, 0x08, 0x00};
  371. static int scanPCI(int start_slt);
  372. static int PCIVendor(int);
  373. #ifdef DEBUG
  374. static void printslots(void);
  375. #endif
  376. extern void puthex(unsigned long);
  377. extern void puts(const char *);
  378. static void unlockS3(void);
  379. static inline void
  380. outw(int port, unsigned short val)
  381. {
  382. outb(port, val >> 8);
  383. outb(port+1, val);
  384. }
  385. int
  386. vga_init(unsigned char *ISA_mem)
  387. {
  388. int slot;
  389. struct VgaRegs *VgaTextRegs;
  390. /* See if VGA already in TEXT mode - exit if so! */
  391. outb(0x3CE, 0x06);
  392. if ((inb(0x3CF) & 0x01) == 0){
  393. puts("VGA already in text mode\n");
  394. return 0;
  395. }
  396. /* If no VGA responding in text mode, then we have some work to do...
  397. */
  398. slot = -1;
  399. while((slot = scanPCI(slot)) > -1) { /* find video card in use */
  400. unlockVideo(slot); /* enable I/O to card */
  401. VgaTextRegs = GenVgaTextRegs;
  402. switch (PCIVendor(slot)) {
  403. default:
  404. break;
  405. case(S3Vendor):
  406. unlockS3();
  407. break;
  408. case(CirrusVendor):
  409. outw(0x3C4, 0x0612); /* unlock ext regs */
  410. outw(0x3C4, 0x0700); /* reset ext sequence mode */
  411. break;
  412. case(ParadiseVendor): /* IBM Portable 850 */
  413. outw(0x3ce, 0x0f05); /* unlock pardise registers */
  414. outw(0x3c4, 0x0648);
  415. outw(0x3d4, 0x2985);
  416. outw(0x3d4, 0x34a6);
  417. outb(0x3ce, 0x0b); /* disable linear addressing */
  418. outb(0x3cf, inb(0x3cf) & ~0x30);
  419. outw(0x3c4, 0x1400);
  420. outb(0x3ce, 0x0e); /* disable 256 color mode */
  421. outb(0x3cf, inb(0x3cf) & ~0x01);
  422. outb(0xd00, 0xff); /* enable auto-centering */
  423. if (!(inb(0xd01) & 0x03)) {
  424. outb(0x3d4, 0x33);
  425. outb(0x3d5, inb(0x3d5) & ~0x90);
  426. outb(0x3d4, 0x32);
  427. outb(0x3d5, inb(0x3d5) | 0x04);
  428. outw(0x3d4, 0x0250);
  429. outw(0x3d4, 0x07ba);
  430. outw(0x3d4, 0x0900);
  431. outw(0x3d4, 0x15e7);
  432. outw(0x3d4, 0x2a95);
  433. }
  434. outw(0x3d4, 0x34a0);
  435. break;
  436. #if 0 /* Untested - probably doesn't work */
  437. case(MatroxVendor):
  438. case(DiamondVendor):
  439. puts("VGA Chip Vendor ID: ");
  440. puthex(PCIVendor(slot));
  441. puts("\n");
  442. mdelay(1000);
  443. #endif
  444. };
  445. outw(0x3C4, 0x0120); /* disable video */
  446. setTextRegs(VgaTextRegs); /* initial register setup */
  447. setTextCLUT(0); /* load color lookup table */
  448. loadFont(ISA_mem); /* load font */
  449. setTextRegs(VgaTextRegs); /* reload registers */
  450. outw(0x3C4, 0x0100); /* re-enable video */
  451. clearVideoMemory();
  452. if (PCIVendor(slot) == S3Vendor) {
  453. outb(0x3c2, 0x63); /* MISC */
  454. } /* endif */
  455. #ifdef DEBUG
  456. printslots();
  457. mdelay(5000);
  458. #endif
  459. mdelay(1000); /* give time for the video monitor to come up */
  460. }
  461. return (1); /* 'CRT' I/O supported */
  462. }
  463. /*
  464. * Write to VGA Attribute registers.
  465. */
  466. void
  467. writeAttr(unsigned char index, unsigned char data, unsigned char videoOn)
  468. {
  469. unsigned char v;
  470. v = inb(0x3da); /* reset attr. address toggle */
  471. if (videoOn)
  472. outb(0x3c0, (index & 0x1F) | 0x20);
  473. else
  474. outb(0x3c0, (index & 0x1F));
  475. outb(0x3c0, data);
  476. }
  477. void
  478. setTextRegs(struct VgaRegs *svp)
  479. {
  480. int i;
  481. /*
  482. * saved settings
  483. */
  484. while( svp->io_port != ENDMK ) {
  485. outb(svp->io_port, svp->io_index);
  486. outb(svp->io_port+1, svp->io_value);
  487. svp++;
  488. }
  489. outb(0x3c2, 0x67); /* MISC */
  490. outb(0x3c6, 0xff); /* MASK */
  491. for ( i = 0; i < 0x10; i++)
  492. writeAttr(i, AC[i], 0); /* pallete */
  493. writeAttr(0x10, 0x0c, 0); /* text mode */
  494. writeAttr(0x11, 0x00, 0); /* overscan color (border) */
  495. writeAttr(0x12, 0x0f, 0); /* plane enable */
  496. writeAttr(0x13, 0x08, 0); /* pixel panning */
  497. writeAttr(0x14, 0x00, 1); /* color select; video on */
  498. }
  499. void
  500. setTextCLUT(int shift)
  501. {
  502. int i;
  503. outb(0x3C6, 0xFF);
  504. i = inb(0x3C7);
  505. outb(0x3C8, 0);
  506. i = inb(0x3C7);
  507. for ( i = 0; i < 256; i++) {
  508. outb(0x3C9, TextCLUT[i].r << shift);
  509. outb(0x3C9, TextCLUT[i].g << shift);
  510. outb(0x3C9, TextCLUT[i].b << shift);
  511. }
  512. }
  513. void
  514. loadFont(unsigned char *ISA_mem)
  515. {
  516. int i, j;
  517. unsigned char *font_page = (unsigned char *) &ISA_mem[0xA0000];
  518. outb(0x3C2, 0x67);
  519. /*
  520. * Load font
  521. */
  522. i = inb(0x3DA); /* Reset Attr toggle */
  523. outb(0x3C0,0x30);
  524. outb(0x3C0, 0x01); /* graphics mode */
  525. outw(0x3C4, 0x0001); /* reset sequencer */
  526. outw(0x3C4, 0x0204); /* write to plane 2 */
  527. outw(0x3C4, 0x0406); /* enable plane graphics */
  528. outw(0x3C4, 0x0003); /* reset sequencer */
  529. outw(0x3CE, 0x0402); /* read plane 2 */
  530. outw(0x3CE, 0x0500); /* write mode 0, read mode 0 */
  531. outw(0x3CE, 0x0605); /* set graphics mode */
  532. for (i = 0; i < sizeof(font); i += 16) {
  533. for (j = 0; j < 16; j++) {
  534. __asm__ volatile("eieio");
  535. font_page[(2*i)+j] = font[i+j];
  536. }
  537. }
  538. }
  539. static void
  540. unlockS3(void)
  541. {
  542. int s3_device_id;
  543. outw(0x3d4, 0x3848);
  544. outw(0x3d4, 0x39a5);
  545. outb(0x3d4, 0x2d);
  546. s3_device_id = inb(0x3d5) << 8;
  547. outb(0x3d4, 0x2e);
  548. s3_device_id |= inb(0x3d5);
  549. if (s3_device_id != 0x8812) {
  550. /* From the S3 manual */
  551. outb(0x46E8, 0x10); /* Put into setup mode */
  552. outb(0x3C3, 0x10);
  553. outb(0x102, 0x01); /* Enable registers */
  554. outb(0x46E8, 0x08); /* Enable video */
  555. outb(0x3C3, 0x08);
  556. outb(0x4AE8, 0x00);
  557. #if 0
  558. outb(0x42E8, 0x80); /* Reset graphics engine? */
  559. #endif
  560. outb(0x3D4, 0x38); /* Unlock all registers */
  561. outb(0x3D5, 0x48);
  562. outb(0x3D4, 0x39);
  563. outb(0x3D5, 0xA5);
  564. outb(0x3D4, 0x40);
  565. outb(0x3D5, inb(0x3D5)|0x01);
  566. outb(0x3D4, 0x33);
  567. outb(0x3D5, inb(0x3D5)&~0x52);
  568. outb(0x3D4, 0x35);
  569. outb(0x3D5, inb(0x3D5)&~0x30);
  570. outb(0x3D4, 0x3A);
  571. outb(0x3D5, 0x00);
  572. outb(0x3D4, 0x53);
  573. outb(0x3D5, 0x00);
  574. outb(0x3D4, 0x31);
  575. outb(0x3D5, inb(0x3D5)&~0x4B);
  576. outb(0x3D4, 0x58);
  577. outb(0x3D5, 0);
  578. outb(0x3D4, 0x54);
  579. outb(0x3D5, 0x38);
  580. outb(0x3D4, 0x60);
  581. outb(0x3D5, 0x07);
  582. outb(0x3D4, 0x61);
  583. outb(0x3D5, 0x80);
  584. outb(0x3D4, 0x62);
  585. outb(0x3D5, 0xA1);
  586. outb(0x3D4, 0x69); /* High order bits for cursor address */
  587. outb(0x3D5, 0);
  588. outb(0x3D4, 0x32);
  589. outb(0x3D5, inb(0x3D5)&~0x10);
  590. } else {
  591. outw(0x3c4, 0x0806); /* IBM Portable 860 */
  592. outw(0x3c4, 0x1041);
  593. outw(0x3c4, 0x1128);
  594. outw(0x3d4, 0x4000);
  595. outw(0x3d4, 0x3100);
  596. outw(0x3d4, 0x3a05);
  597. outw(0x3d4, 0x6688);
  598. outw(0x3d4, 0x5800); /* disable linear addressing */
  599. outw(0x3d4, 0x4500); /* disable H/W cursor */
  600. outw(0x3c4, 0x5410); /* enable auto-centering */
  601. outw(0x3c4, 0x561f);
  602. outw(0x3c4, 0x1b80); /* lock DCLK selection */
  603. outw(0x3d4, 0x3900); /* lock S3 registers */
  604. outw(0x3d4, 0x3800);
  605. } /* endif */
  606. }
  607. /*
  608. * cursor() sets an offset (0-1999) into the 80x25 text area.
  609. */
  610. void
  611. cursor(int x, int y)
  612. {
  613. int pos = (y*cols)+x;
  614. outb(0x3D4, 14);
  615. outb(0x3D5, pos >> 8);
  616. outb(0x3D4, 15);
  617. outb(0x3D5, pos);
  618. }
  619. void
  620. clearVideoMemory(void)
  621. {
  622. int i, j;
  623. for (i = 0; i < lines; i++) {
  624. for (j = 0; j < cols; j++) {
  625. vidmem[((i*cols)+j)*2] = 0x20; /* fill with space character */
  626. vidmem[((i*cols)+j)*2+1] = 0x07; /* set bg & fg attributes */
  627. }
  628. }
  629. }
  630. /* ============ */
  631. #define NSLOTS 8
  632. #define NPCIREGS 5
  633. /*
  634. should use devfunc number/indirect method to be totally safe on
  635. all machines, this works for now on 3 slot Moto boxes
  636. */
  637. struct PCI_ConfigInfo {
  638. unsigned long * config_addr;
  639. unsigned long regs[NPCIREGS];
  640. } PCI_slots [NSLOTS] = {
  641. { (unsigned long *)0x80808000, {0xDEADBEEF,} }, /* onboard */
  642. { (unsigned long *)0x80800800, {0xDEADBEEF,} }, /* onboard */
  643. { (unsigned long *)0x80801000, {0xDEADBEEF,} }, /* onboard */
  644. { (unsigned long *)0x80802000, {0xDEADBEEF,} }, /* onboard */
  645. { (unsigned long *)0x80804000, {0xDEADBEEF,} }, /* onboard */
  646. { (unsigned long *)0x80810000, {0xDEADBEEF,} }, /* slot A/1 */
  647. { (unsigned long *)0x80820000, {0xDEADBEEF,} }, /* slot B/2 */
  648. { (unsigned long *)0x80840000, {0xDEADBEEF,} } /* slot C/3 */
  649. };
  650. /*
  651. * The following code modifies the PCI Command register
  652. * to enable memory and I/O accesses.
  653. */
  654. void
  655. unlockVideo(int slot)
  656. {
  657. volatile unsigned char * ppci;
  658. ppci = (unsigned char * )PCI_slots[slot].config_addr;
  659. ppci[4] = 0x0003; /* enable memory and I/O accesses */
  660. ppci[0x10] = 0x00000; /* turn off memory mapping */
  661. ppci[0x11] = 0x00000; /* mem_base = 0 */
  662. ppci[0x12] = 0x00000;
  663. ppci[0x13] = 0x00000;
  664. __asm__ volatile("eieio");
  665. outb(0x3d4, 0x11);
  666. outb(0x3d5, 0x0e); /* unlock CR0-CR7 */
  667. }
  668. long
  669. SwapBytes(long lv) /* turn little endian into big indian long */
  670. {
  671. long t;
  672. t = (lv&0x000000FF) << 24;
  673. t |= (lv&0x0000FF00) << 8;
  674. t |= (lv&0x00FF0000) >> 8;
  675. t |= (lv&0xFF000000) >> 24;
  676. return(t);
  677. }
  678. #define DEVID 0
  679. #define CMD 1
  680. #define CLASS 2
  681. #define MEMBASE 4
  682. int
  683. scanPCI(int start_slt)
  684. {
  685. int slt, r;
  686. struct PCI_ConfigInfo *pslot;
  687. int theSlot = -1;
  688. int highVgaSlot = 0;
  689. for ( slt = start_slt + 1; slt < NSLOTS; slt++) {
  690. pslot = &PCI_slots[slt];
  691. for ( r = 0; r < NPCIREGS; r++) {
  692. pslot->regs[r] = SwapBytes ( pslot->config_addr[r] );
  693. }
  694. /* card in slot ? */
  695. if ( pslot->regs[DEVID] != 0xFFFFFFFF ) {
  696. /* VGA ? */
  697. if ( ((pslot->regs[CLASS] & 0xFFFFFF00) == 0x03000000) ||
  698. ((pslot->regs[CLASS] & 0xFFFFFF00) == 0x00010000)) {
  699. highVgaSlot = slt;
  700. /* did firmware enable it ? */
  701. if ( (pslot->regs[CMD] & 0x03) ) {
  702. theSlot = slt;
  703. break;
  704. }
  705. }
  706. }
  707. }
  708. return ( theSlot );
  709. }
  710. /* return Vendor ID of card in the slot */
  711. static
  712. int PCIVendor(int slotnum) {
  713. struct PCI_ConfigInfo *pslot;
  714. pslot = &PCI_slots[slotnum];
  715. return (pslot->regs[DEVID] & 0xFFFF);
  716. }
  717. #ifdef DEBUG
  718. static
  719. void printslots(void)
  720. {
  721. int i;
  722. #if 0
  723. struct PCI_ConfigInfo *pslot;
  724. #endif
  725. for(i=0; i < NSLOTS; i++) {
  726. #if 0
  727. pslot = &PCI_slots[i];
  728. printf("Slot: %d, Addr: %x, Vendor: %08x, Class: %08x\n",
  729. i, pslot->config_addr, pslot->regs[0], pslot->regs[2]);
  730. #else
  731. puts("PCI Slot number: "); puthex(i);
  732. puts(" Vendor ID: ");
  733. puthex(PCIVendor(i)); puts("\n");
  734. #endif
  735. }
  736. }
  737. #endif /* DEBUG */