ofw_syscons.c 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086
  1. /*-
  2. * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  3. *
  4. * Copyright (c) 2003 Peter Grehan
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  17. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  20. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  22. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  23. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26. * SUCH DAMAGE.
  27. */
  28. #include <sys/cdefs.h>
  29. __FBSDID("$FreeBSD$");
  30. #include <sys/param.h>
  31. #include <sys/systm.h>
  32. #include <sys/module.h>
  33. #include <sys/bus.h>
  34. #include <sys/kernel.h>
  35. #include <sys/sysctl.h>
  36. #include <sys/limits.h>
  37. #include <sys/conf.h>
  38. #include <sys/cons.h>
  39. #include <sys/proc.h>
  40. #include <sys/fcntl.h>
  41. #include <sys/malloc.h>
  42. #include <sys/fbio.h>
  43. #include <sys/consio.h>
  44. #include <machine/bus.h>
  45. #include <machine/sc_machdep.h>
  46. #include <machine/vm.h>
  47. #include <sys/rman.h>
  48. #include <dev/fb/fbreg.h>
  49. #include <dev/syscons/syscons.h>
  50. #include <dev/ofw/openfirm.h>
  51. #include <dev/ofw/ofw_bus.h>
  52. #include <dev/ofw/ofw_pci.h>
  53. #include <powerpc/ofw/ofw_syscons.h>
  54. static int ofwfb_ignore_mmap_checks = 1;
  55. static int ofwfb_reset_on_switch = 1;
  56. static SYSCTL_NODE(_hw, OID_AUTO, ofwfb, CTLFLAG_RD | CTLFLAG_MPSAFE, 0,
  57. "ofwfb");
  58. SYSCTL_INT(_hw_ofwfb, OID_AUTO, relax_mmap, CTLFLAG_RW,
  59. &ofwfb_ignore_mmap_checks, 0, "relaxed mmap bounds checking");
  60. SYSCTL_INT(_hw_ofwfb, OID_AUTO, reset_on_mode_switch, CTLFLAG_RW,
  61. &ofwfb_reset_on_switch, 0, "reset the framebuffer driver on mode switch");
  62. extern u_char dflt_font_16[];
  63. extern u_char dflt_font_14[];
  64. extern u_char dflt_font_8[];
  65. static int ofwfb_configure(int flags);
  66. static vi_probe_t ofwfb_probe;
  67. static vi_init_t ofwfb_init;
  68. static vi_get_info_t ofwfb_get_info;
  69. static vi_query_mode_t ofwfb_query_mode;
  70. static vi_set_mode_t ofwfb_set_mode;
  71. static vi_save_font_t ofwfb_save_font;
  72. static vi_load_font_t ofwfb_load_font;
  73. static vi_show_font_t ofwfb_show_font;
  74. static vi_save_palette_t ofwfb_save_palette;
  75. static vi_load_palette_t ofwfb_load_palette;
  76. static vi_set_border_t ofwfb_set_border;
  77. static vi_save_state_t ofwfb_save_state;
  78. static vi_load_state_t ofwfb_load_state;
  79. static vi_set_win_org_t ofwfb_set_win_org;
  80. static vi_read_hw_cursor_t ofwfb_read_hw_cursor;
  81. static vi_set_hw_cursor_t ofwfb_set_hw_cursor;
  82. static vi_set_hw_cursor_shape_t ofwfb_set_hw_cursor_shape;
  83. static vi_blank_display_t ofwfb_blank_display;
  84. static vi_mmap_t ofwfb_mmap;
  85. static vi_ioctl_t ofwfb_ioctl;
  86. static vi_clear_t ofwfb_clear;
  87. static vi_fill_rect_t ofwfb_fill_rect;
  88. static vi_bitblt_t ofwfb_bitblt;
  89. static vi_diag_t ofwfb_diag;
  90. static vi_save_cursor_palette_t ofwfb_save_cursor_palette;
  91. static vi_load_cursor_palette_t ofwfb_load_cursor_palette;
  92. static vi_copy_t ofwfb_copy;
  93. static vi_putp_t ofwfb_putp;
  94. static vi_putc_t ofwfb_putc;
  95. static vi_puts_t ofwfb_puts;
  96. static vi_putm_t ofwfb_putm;
  97. static video_switch_t ofwfbvidsw = {
  98. .probe = ofwfb_probe,
  99. .init = ofwfb_init,
  100. .get_info = ofwfb_get_info,
  101. .query_mode = ofwfb_query_mode,
  102. .set_mode = ofwfb_set_mode,
  103. .save_font = ofwfb_save_font,
  104. .load_font = ofwfb_load_font,
  105. .show_font = ofwfb_show_font,
  106. .save_palette = ofwfb_save_palette,
  107. .load_palette = ofwfb_load_palette,
  108. .set_border = ofwfb_set_border,
  109. .save_state = ofwfb_save_state,
  110. .load_state = ofwfb_load_state,
  111. .set_win_org = ofwfb_set_win_org,
  112. .read_hw_cursor = ofwfb_read_hw_cursor,
  113. .set_hw_cursor = ofwfb_set_hw_cursor,
  114. .set_hw_cursor_shape = ofwfb_set_hw_cursor_shape,
  115. .blank_display = ofwfb_blank_display,
  116. .mmap = ofwfb_mmap,
  117. .ioctl = ofwfb_ioctl,
  118. .clear = ofwfb_clear,
  119. .fill_rect = ofwfb_fill_rect,
  120. .bitblt = ofwfb_bitblt,
  121. .diag = ofwfb_diag,
  122. .save_cursor_palette = ofwfb_save_cursor_palette,
  123. .load_cursor_palette = ofwfb_load_cursor_palette,
  124. .copy = ofwfb_copy,
  125. .putp = ofwfb_putp,
  126. .putc = ofwfb_putc,
  127. .puts = ofwfb_puts,
  128. .putm = ofwfb_putm,
  129. };
  130. /*
  131. * bitmap depth-specific routines
  132. */
  133. static vi_blank_display_t ofwfb_blank_display8;
  134. static vi_putc_t ofwfb_putc8;
  135. static vi_putm_t ofwfb_putm8;
  136. static vi_set_border_t ofwfb_set_border8;
  137. static vi_blank_display_t ofwfb_blank_display32;
  138. static vi_putc_t ofwfb_putc32;
  139. static vi_putm_t ofwfb_putm32;
  140. static vi_set_border_t ofwfb_set_border32;
  141. VIDEO_DRIVER(ofwfb, ofwfbvidsw, ofwfb_configure);
  142. extern sc_rndr_sw_t txtrndrsw;
  143. RENDERER(ofwfb, 0, txtrndrsw, gfb_set);
  144. RENDERER_MODULE(ofwfb, gfb_set);
  145. /*
  146. * Define the iso6429-1983 colormap
  147. */
  148. static struct {
  149. uint8_t red;
  150. uint8_t green;
  151. uint8_t blue;
  152. } ofwfb_cmap[16] = { /* # R G B Color */
  153. /* - - - - ----- */
  154. { 0x00, 0x00, 0x00 }, /* 0 0 0 0 Black */
  155. { 0x00, 0x00, 0xaa }, /* 1 0 0 2/3 Blue */
  156. { 0x00, 0xaa, 0x00 }, /* 2 0 2/3 0 Green */
  157. { 0x00, 0xaa, 0xaa }, /* 3 0 2/3 2/3 Cyan */
  158. { 0xaa, 0x00, 0x00 }, /* 4 2/3 0 0 Red */
  159. { 0xaa, 0x00, 0xaa }, /* 5 2/3 0 2/3 Magenta */
  160. { 0xaa, 0x55, 0x00 }, /* 6 2/3 1/3 0 Brown */
  161. { 0xaa, 0xaa, 0xaa }, /* 7 2/3 2/3 2/3 White */
  162. { 0x55, 0x55, 0x55 }, /* 8 1/3 1/3 1/3 Gray */
  163. { 0x55, 0x55, 0xff }, /* 9 1/3 1/3 1 Bright Blue */
  164. { 0x55, 0xff, 0x55 }, /* 10 1/3 1 1/3 Bright Green */
  165. { 0x55, 0xff, 0xff }, /* 11 1/3 1 1 Bright Cyan */
  166. { 0xff, 0x55, 0x55 }, /* 12 1 1/3 1/3 Bright Red */
  167. { 0xff, 0x55, 0xff }, /* 13 1 1/3 1 Bright Magenta */
  168. { 0xff, 0xff, 0x80 }, /* 14 1 1 1/3 Bright Yellow */
  169. { 0xff, 0xff, 0xff } /* 15 1 1 1 Bright White */
  170. };
  171. #define TODO printf("%s: unimplemented\n", __func__)
  172. static u_int16_t ofwfb_static_window[ROW*COL];
  173. static struct ofwfb_softc ofwfb_softc;
  174. static __inline int
  175. ofwfb_background(uint8_t attr)
  176. {
  177. return (attr >> 4);
  178. }
  179. static __inline int
  180. ofwfb_foreground(uint8_t attr)
  181. {
  182. return (attr & 0x0f);
  183. }
  184. static u_int
  185. ofwfb_pix32(struct ofwfb_softc *sc, int attr)
  186. {
  187. u_int retval;
  188. if (sc->sc_tag == &bs_le_tag)
  189. retval = (ofwfb_cmap[attr].red << 16) |
  190. (ofwfb_cmap[attr].green << 8) |
  191. ofwfb_cmap[attr].blue;
  192. else
  193. retval = (ofwfb_cmap[attr].blue << 16) |
  194. (ofwfb_cmap[attr].green << 8) |
  195. ofwfb_cmap[attr].red;
  196. return (retval);
  197. }
  198. static int
  199. ofwfb_configure(int flags)
  200. {
  201. struct ofwfb_softc *sc;
  202. phandle_t chosen;
  203. ihandle_t stdout;
  204. phandle_t node;
  205. uint32_t fb_phys;
  206. int depth;
  207. int disable;
  208. int len;
  209. int i;
  210. char type[16];
  211. static int done = 0;
  212. disable = 0;
  213. TUNABLE_INT_FETCH("hw.syscons.disable", &disable);
  214. if (disable != 0)
  215. return (0);
  216. if (done != 0)
  217. return (0);
  218. done = 1;
  219. sc = &ofwfb_softc;
  220. chosen = OF_finddevice("/chosen");
  221. OF_getprop(chosen, "stdout", &stdout, sizeof(stdout));
  222. node = OF_instance_to_package(stdout);
  223. if (node == -1) {
  224. /*
  225. * The "/chosen/stdout" does not exist try
  226. * using "screen" directly.
  227. */
  228. node = OF_finddevice("screen");
  229. }
  230. OF_getprop(node, "device_type", type, sizeof(type));
  231. if (strcmp(type, "display") != 0)
  232. return (0);
  233. /* Only support 8 and 32-bit framebuffers */
  234. OF_getprop(node, "depth", &depth, sizeof(depth));
  235. if (depth == 8) {
  236. sc->sc_blank = ofwfb_blank_display8;
  237. sc->sc_putc = ofwfb_putc8;
  238. sc->sc_putm = ofwfb_putm8;
  239. sc->sc_set_border = ofwfb_set_border8;
  240. } else if (depth == 32) {
  241. sc->sc_blank = ofwfb_blank_display32;
  242. sc->sc_putc = ofwfb_putc32;
  243. sc->sc_putm = ofwfb_putm32;
  244. sc->sc_set_border = ofwfb_set_border32;
  245. } else
  246. return (0);
  247. if (OF_getproplen(node, "height") != sizeof(sc->sc_height) ||
  248. OF_getproplen(node, "width") != sizeof(sc->sc_width) ||
  249. OF_getproplen(node, "linebytes") != sizeof(sc->sc_stride))
  250. return (0);
  251. sc->sc_depth = depth;
  252. sc->sc_node = node;
  253. sc->sc_console = 1;
  254. OF_getprop(node, "height", &sc->sc_height, sizeof(sc->sc_height));
  255. OF_getprop(node, "width", &sc->sc_width, sizeof(sc->sc_width));
  256. OF_getprop(node, "linebytes", &sc->sc_stride, sizeof(sc->sc_stride));
  257. /*
  258. * Get the PCI addresses of the adapter. The node may be the
  259. * child of the PCI device: in that case, try the parent for
  260. * the assigned-addresses property.
  261. */
  262. len = OF_getprop(node, "assigned-addresses", sc->sc_pciaddrs,
  263. sizeof(sc->sc_pciaddrs));
  264. if (len == -1) {
  265. len = OF_getprop(OF_parent(node), "assigned-addresses",
  266. sc->sc_pciaddrs, sizeof(sc->sc_pciaddrs));
  267. }
  268. if (len == -1)
  269. len = 0;
  270. sc->sc_num_pciaddrs = len / sizeof(struct ofw_pci_register);
  271. /*
  272. * Grab the physical address of the framebuffer, and then map it
  273. * into our memory space. If the MMU is not yet up, it will be
  274. * remapped for us when relocation turns on.
  275. *
  276. * XXX We assume #address-cells is 1 at this point.
  277. */
  278. if (OF_getproplen(node, "address") == sizeof(fb_phys)) {
  279. OF_getprop(node, "address", &fb_phys, sizeof(fb_phys));
  280. sc->sc_tag = &bs_be_tag;
  281. bus_space_map(sc->sc_tag, fb_phys, sc->sc_height *
  282. sc->sc_stride, BUS_SPACE_MAP_PREFETCHABLE, &sc->sc_addr);
  283. } else {
  284. /*
  285. * Some IBM systems don't have an address property. Try to
  286. * guess the framebuffer region from the assigned addresses.
  287. * This is ugly, but there doesn't seem to be an alternative.
  288. * Linux does the same thing.
  289. */
  290. fb_phys = sc->sc_num_pciaddrs;
  291. for (i = 0; i < sc->sc_num_pciaddrs; i++) {
  292. /* If it is too small, not the framebuffer */
  293. if (sc->sc_pciaddrs[i].size_lo <
  294. sc->sc_stride*sc->sc_height)
  295. continue;
  296. /* If it is not memory, it isn't either */
  297. if (!(sc->sc_pciaddrs[i].phys_hi &
  298. OFW_PCI_PHYS_HI_SPACE_MEM32))
  299. continue;
  300. /* This could be the framebuffer */
  301. fb_phys = i;
  302. /* If it is prefetchable, it certainly is */
  303. if (sc->sc_pciaddrs[i].phys_hi &
  304. OFW_PCI_PHYS_HI_PREFETCHABLE)
  305. break;
  306. }
  307. if (fb_phys == sc->sc_num_pciaddrs)
  308. return (0);
  309. OF_decode_addr(node, fb_phys, &sc->sc_tag, &sc->sc_addr, NULL);
  310. }
  311. ofwfb_init(0, &sc->sc_va, 0);
  312. return (0);
  313. }
  314. static int
  315. ofwfb_probe(int unit, video_adapter_t **adp, void *arg, int flags)
  316. {
  317. TODO;
  318. return (0);
  319. }
  320. static int
  321. ofwfb_init(int unit, video_adapter_t *adp, int flags)
  322. {
  323. struct ofwfb_softc *sc;
  324. video_info_t *vi;
  325. int cborder;
  326. int font_height;
  327. sc = (struct ofwfb_softc *)adp;
  328. vi = &adp->va_info;
  329. vid_init_struct(adp, "ofwfb", -1, unit);
  330. /* The default font size can be overridden by loader */
  331. font_height = 16;
  332. TUNABLE_INT_FETCH("hw.syscons.fsize", &font_height);
  333. if (font_height == 8) {
  334. sc->sc_font = dflt_font_8;
  335. sc->sc_font_height = 8;
  336. } else if (font_height == 14) {
  337. sc->sc_font = dflt_font_14;
  338. sc->sc_font_height = 14;
  339. } else {
  340. /* default is 8x16 */
  341. sc->sc_font = dflt_font_16;
  342. sc->sc_font_height = 16;
  343. }
  344. /* The user can set a border in chars - default is 1 char width */
  345. cborder = 1;
  346. TUNABLE_INT_FETCH("hw.syscons.border", &cborder);
  347. vi->vi_cheight = sc->sc_font_height;
  348. vi->vi_width = sc->sc_width/8 - 2*cborder;
  349. vi->vi_height = sc->sc_height/sc->sc_font_height - 2*cborder;
  350. vi->vi_cwidth = 8;
  351. /*
  352. * Clamp width/height to syscons maximums
  353. */
  354. if (vi->vi_width > COL)
  355. vi->vi_width = COL;
  356. if (vi->vi_height > ROW)
  357. vi->vi_height = ROW;
  358. sc->sc_xmargin = (sc->sc_width - (vi->vi_width * vi->vi_cwidth)) / 2;
  359. sc->sc_ymargin = (sc->sc_height - (vi->vi_height * vi->vi_cheight))/2;
  360. /*
  361. * Avoid huge amounts of conditional code in syscons by
  362. * defining a dummy h/w text display buffer.
  363. */
  364. adp->va_window = (vm_offset_t) ofwfb_static_window;
  365. /*
  366. * Enable future font-loading and flag color support, as well as
  367. * adding V_ADP_MODECHANGE so that we ofwfb_set_mode() gets called
  368. * when the X server shuts down. This enables us to get the console
  369. * back when X disappears.
  370. */
  371. adp->va_flags |= V_ADP_FONT | V_ADP_COLOR | V_ADP_MODECHANGE;
  372. ofwfb_set_mode(&sc->sc_va, 0);
  373. vid_register(&sc->sc_va);
  374. return (0);
  375. }
  376. static int
  377. ofwfb_get_info(video_adapter_t *adp, int mode, video_info_t *info)
  378. {
  379. bcopy(&adp->va_info, info, sizeof(*info));
  380. return (0);
  381. }
  382. static int
  383. ofwfb_query_mode(video_adapter_t *adp, video_info_t *info)
  384. {
  385. TODO;
  386. return (0);
  387. }
  388. static int
  389. ofwfb_set_mode(video_adapter_t *adp, int mode)
  390. {
  391. struct ofwfb_softc *sc;
  392. char name[64];
  393. ihandle_t ih;
  394. int i, retval;
  395. sc = (struct ofwfb_softc *)adp;
  396. if (ofwfb_reset_on_switch) {
  397. /*
  398. * Open the display device, which will initialize it.
  399. */
  400. memset(name, 0, sizeof(name));
  401. OF_package_to_path(sc->sc_node, name, sizeof(name));
  402. ih = OF_open(name);
  403. if (sc->sc_depth == 8) {
  404. /*
  405. * Install the ISO6429 colormap - older OFW systems
  406. * don't do this by default
  407. */
  408. for (i = 0; i < 16; i++) {
  409. OF_call_method("color!", ih, 4, 1,
  410. ofwfb_cmap[i].red,
  411. ofwfb_cmap[i].green,
  412. ofwfb_cmap[i].blue,
  413. i,
  414. &retval);
  415. }
  416. }
  417. }
  418. ofwfb_blank_display(&sc->sc_va, V_DISPLAY_ON);
  419. return (0);
  420. }
  421. static int
  422. ofwfb_save_font(video_adapter_t *adp, int page, int size, int width,
  423. u_char *data, int c, int count)
  424. {
  425. TODO;
  426. return (0);
  427. }
  428. static int
  429. ofwfb_load_font(video_adapter_t *adp, int page, int size, int width,
  430. u_char *data, int c, int count)
  431. {
  432. struct ofwfb_softc *sc;
  433. sc = (struct ofwfb_softc *)adp;
  434. /*
  435. * syscons code has already determined that current width/height
  436. * are unchanged for this new font
  437. */
  438. sc->sc_font = data;
  439. return (0);
  440. }
  441. static int
  442. ofwfb_show_font(video_adapter_t *adp, int page)
  443. {
  444. return (0);
  445. }
  446. static int
  447. ofwfb_save_palette(video_adapter_t *adp, u_char *palette)
  448. {
  449. /* TODO; */
  450. return (0);
  451. }
  452. static int
  453. ofwfb_load_palette(video_adapter_t *adp, u_char *palette)
  454. {
  455. /* TODO; */
  456. return (0);
  457. }
  458. static int
  459. ofwfb_set_border8(video_adapter_t *adp, int border)
  460. {
  461. struct ofwfb_softc *sc;
  462. int i, j;
  463. uint8_t *addr;
  464. uint8_t bground;
  465. sc = (struct ofwfb_softc *)adp;
  466. bground = ofwfb_background(border);
  467. /* Set top margin */
  468. addr = (uint8_t *) sc->sc_addr;
  469. for (i = 0; i < sc->sc_ymargin; i++) {
  470. for (j = 0; j < sc->sc_width; j++) {
  471. *(addr + j) = bground;
  472. }
  473. addr += sc->sc_stride;
  474. }
  475. /* bottom margin */
  476. addr = (uint8_t *) sc->sc_addr + (sc->sc_height - sc->sc_ymargin)*sc->sc_stride;
  477. for (i = 0; i < sc->sc_ymargin; i++) {
  478. for (j = 0; j < sc->sc_width; j++) {
  479. *(addr + j) = bground;
  480. }
  481. addr += sc->sc_stride;
  482. }
  483. /* remaining left and right borders */
  484. addr = (uint8_t *) sc->sc_addr + sc->sc_ymargin*sc->sc_stride;
  485. for (i = 0; i < sc->sc_height - 2*sc->sc_xmargin; i++) {
  486. for (j = 0; j < sc->sc_xmargin; j++) {
  487. *(addr + j) = bground;
  488. *(addr + j + sc->sc_width - sc->sc_xmargin) = bground;
  489. }
  490. addr += sc->sc_stride;
  491. }
  492. return (0);
  493. }
  494. static int
  495. ofwfb_set_border32(video_adapter_t *adp, int border)
  496. {
  497. /* XXX Be lazy for now and blank entire screen */
  498. return (ofwfb_blank_display32(adp, border));
  499. }
  500. static int
  501. ofwfb_set_border(video_adapter_t *adp, int border)
  502. {
  503. struct ofwfb_softc *sc;
  504. sc = (struct ofwfb_softc *)adp;
  505. return ((*sc->sc_set_border)(adp, border));
  506. }
  507. static int
  508. ofwfb_save_state(video_adapter_t *adp, void *p, size_t size)
  509. {
  510. TODO;
  511. return (0);
  512. }
  513. static int
  514. ofwfb_load_state(video_adapter_t *adp, void *p)
  515. {
  516. TODO;
  517. return (0);
  518. }
  519. static int
  520. ofwfb_set_win_org(video_adapter_t *adp, off_t offset)
  521. {
  522. TODO;
  523. return (0);
  524. }
  525. static int
  526. ofwfb_read_hw_cursor(video_adapter_t *adp, int *col, int *row)
  527. {
  528. *col = 0;
  529. *row = 0;
  530. return (0);
  531. }
  532. static int
  533. ofwfb_set_hw_cursor(video_adapter_t *adp, int col, int row)
  534. {
  535. return (0);
  536. }
  537. static int
  538. ofwfb_set_hw_cursor_shape(video_adapter_t *adp, int base, int height,
  539. int celsize, int blink)
  540. {
  541. return (0);
  542. }
  543. static int
  544. ofwfb_blank_display8(video_adapter_t *adp, int mode)
  545. {
  546. struct ofwfb_softc *sc;
  547. int i;
  548. uint32_t *addr;
  549. uint32_t color;
  550. uint32_t end;
  551. sc = (struct ofwfb_softc *)adp;
  552. addr = (uint32_t *) sc->sc_addr;
  553. end = (sc->sc_stride/4) * sc->sc_height;
  554. /* Splat 4 pixels at once. */
  555. color = (ofwfb_background(SC_NORM_ATTR) << 24) |
  556. (ofwfb_background(SC_NORM_ATTR) << 16) |
  557. (ofwfb_background(SC_NORM_ATTR) << 8) |
  558. (ofwfb_background(SC_NORM_ATTR));
  559. for (i = 0; i < end; i++)
  560. *(addr + i) = color;
  561. return (0);
  562. }
  563. static int
  564. ofwfb_blank_display32(video_adapter_t *adp, int mode)
  565. {
  566. struct ofwfb_softc *sc;
  567. int i;
  568. uint32_t *addr, blank;
  569. sc = (struct ofwfb_softc *)adp;
  570. addr = (uint32_t *) sc->sc_addr;
  571. blank = ofwfb_pix32(sc, ofwfb_background(SC_NORM_ATTR));
  572. for (i = 0; i < (sc->sc_stride/4)*sc->sc_height; i++)
  573. *(addr + i) = blank;
  574. return (0);
  575. }
  576. static int
  577. ofwfb_blank_display(video_adapter_t *adp, int mode)
  578. {
  579. struct ofwfb_softc *sc;
  580. sc = (struct ofwfb_softc *)adp;
  581. return ((*sc->sc_blank)(adp, mode));
  582. }
  583. static int
  584. ofwfb_mmap(video_adapter_t *adp, vm_ooffset_t offset, vm_paddr_t *paddr,
  585. int prot, vm_memattr_t *memattr)
  586. {
  587. struct ofwfb_softc *sc;
  588. int i;
  589. sc = (struct ofwfb_softc *)adp;
  590. /*
  591. * Make sure the requested address lies within the PCI device's
  592. * assigned addrs
  593. */
  594. for (i = 0; i < sc->sc_num_pciaddrs; i++)
  595. if (offset >= sc->sc_pciaddrs[i].phys_lo &&
  596. offset < (sc->sc_pciaddrs[i].phys_lo + sc->sc_pciaddrs[i].size_lo))
  597. {
  598. /*
  599. * If this is a prefetchable BAR, we can (and should)
  600. * enable write-combining.
  601. */
  602. if (sc->sc_pciaddrs[i].phys_hi &
  603. OFW_PCI_PHYS_HI_PREFETCHABLE)
  604. *memattr = VM_MEMATTR_WRITE_COMBINING;
  605. *paddr = offset;
  606. return (0);
  607. }
  608. /*
  609. * Hack for Radeon...
  610. */
  611. if (ofwfb_ignore_mmap_checks) {
  612. *paddr = offset;
  613. return (0);
  614. }
  615. /*
  616. * This might be a legacy VGA mem request: if so, just point it at the
  617. * framebuffer, since it shouldn't be touched
  618. */
  619. if (offset < sc->sc_stride*sc->sc_height) {
  620. *paddr = sc->sc_addr + offset;
  621. return (0);
  622. }
  623. /*
  624. * Error if we didn't have a better idea.
  625. */
  626. if (sc->sc_num_pciaddrs == 0)
  627. return (ENOMEM);
  628. return (EINVAL);
  629. }
  630. static int
  631. ofwfb_ioctl(video_adapter_t *adp, u_long cmd, caddr_t data)
  632. {
  633. return (0);
  634. }
  635. static int
  636. ofwfb_clear(video_adapter_t *adp)
  637. {
  638. TODO;
  639. return (0);
  640. }
  641. static int
  642. ofwfb_fill_rect(video_adapter_t *adp, int val, int x, int y, int cx, int cy)
  643. {
  644. TODO;
  645. return (0);
  646. }
  647. static int
  648. ofwfb_bitblt(video_adapter_t *adp, ...)
  649. {
  650. TODO;
  651. return (0);
  652. }
  653. static int
  654. ofwfb_diag(video_adapter_t *adp, int level)
  655. {
  656. TODO;
  657. return (0);
  658. }
  659. static int
  660. ofwfb_save_cursor_palette(video_adapter_t *adp, u_char *palette)
  661. {
  662. TODO;
  663. return (0);
  664. }
  665. static int
  666. ofwfb_load_cursor_palette(video_adapter_t *adp, u_char *palette)
  667. {
  668. TODO;
  669. return (0);
  670. }
  671. static int
  672. ofwfb_copy(video_adapter_t *adp, vm_offset_t src, vm_offset_t dst, int n)
  673. {
  674. TODO;
  675. return (0);
  676. }
  677. static int
  678. ofwfb_putp(video_adapter_t *adp, vm_offset_t off, uint32_t p, uint32_t a,
  679. int size, int bpp, int bit_ltor, int byte_ltor)
  680. {
  681. TODO;
  682. return (0);
  683. }
  684. static int
  685. ofwfb_putc8(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
  686. {
  687. struct ofwfb_softc *sc;
  688. int row;
  689. int col;
  690. int i;
  691. uint32_t *addr;
  692. u_char *p, fg, bg;
  693. union {
  694. uint32_t l;
  695. uint8_t c[4];
  696. } ch1, ch2;
  697. sc = (struct ofwfb_softc *)adp;
  698. row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight;
  699. col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth;
  700. p = sc->sc_font + c*sc->sc_font_height;
  701. addr = (u_int32_t *)((uintptr_t)sc->sc_addr
  702. + (row + sc->sc_ymargin)*sc->sc_stride
  703. + col + sc->sc_xmargin);
  704. fg = ofwfb_foreground(a);
  705. bg = ofwfb_background(a);
  706. for (i = 0; i < sc->sc_font_height; i++) {
  707. u_char fline = p[i];
  708. /*
  709. * Assume that there is more background than foreground
  710. * in characters and init accordingly
  711. */
  712. ch1.l = ch2.l = (bg << 24) | (bg << 16) | (bg << 8) | bg;
  713. /*
  714. * Calculate 2 x 4-chars at a time, and then
  715. * write these out.
  716. */
  717. if (fline & 0x80) ch1.c[0] = fg;
  718. if (fline & 0x40) ch1.c[1] = fg;
  719. if (fline & 0x20) ch1.c[2] = fg;
  720. if (fline & 0x10) ch1.c[3] = fg;
  721. if (fline & 0x08) ch2.c[0] = fg;
  722. if (fline & 0x04) ch2.c[1] = fg;
  723. if (fline & 0x02) ch2.c[2] = fg;
  724. if (fline & 0x01) ch2.c[3] = fg;
  725. addr[0] = ch1.l;
  726. addr[1] = ch2.l;
  727. addr += (sc->sc_stride / sizeof(u_int32_t));
  728. }
  729. return (0);
  730. }
  731. static int
  732. ofwfb_putc32(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
  733. {
  734. struct ofwfb_softc *sc;
  735. int row;
  736. int col;
  737. int i, j, k;
  738. uint32_t *addr, fg, bg;
  739. u_char *p;
  740. sc = (struct ofwfb_softc *)adp;
  741. row = (off / adp->va_info.vi_width) * adp->va_info.vi_cheight;
  742. col = (off % adp->va_info.vi_width) * adp->va_info.vi_cwidth;
  743. p = sc->sc_font + c*sc->sc_font_height;
  744. addr = (uint32_t *)sc->sc_addr
  745. + (row + sc->sc_ymargin)*(sc->sc_stride/4)
  746. + col + sc->sc_xmargin;
  747. fg = ofwfb_pix32(sc, ofwfb_foreground(a));
  748. bg = ofwfb_pix32(sc, ofwfb_background(a));
  749. for (i = 0; i < sc->sc_font_height; i++) {
  750. for (j = 0, k = 7; j < 8; j++, k--) {
  751. if ((p[i] & (1 << k)) == 0)
  752. *(addr + j) = bg;
  753. else
  754. *(addr + j) = fg;
  755. }
  756. addr += (sc->sc_stride/4);
  757. }
  758. return (0);
  759. }
  760. static int
  761. ofwfb_putc(video_adapter_t *adp, vm_offset_t off, uint8_t c, uint8_t a)
  762. {
  763. struct ofwfb_softc *sc;
  764. sc = (struct ofwfb_softc *)adp;
  765. return ((*sc->sc_putc)(adp, off, c, a));
  766. }
  767. static int
  768. ofwfb_puts(video_adapter_t *adp, vm_offset_t off, u_int16_t *s, int len)
  769. {
  770. int i;
  771. for (i = 0; i < len; i++) {
  772. ofwfb_putc(adp, off + i, s[i] & 0xff, (s[i] & 0xff00) >> 8);
  773. }
  774. return (0);
  775. }
  776. static int
  777. ofwfb_putm(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
  778. uint32_t pixel_mask, int size, int width)
  779. {
  780. struct ofwfb_softc *sc;
  781. sc = (struct ofwfb_softc *)adp;
  782. return ((*sc->sc_putm)(adp, x, y, pixel_image, pixel_mask, size,
  783. width));
  784. }
  785. static int
  786. ofwfb_putm8(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
  787. uint32_t pixel_mask, int size, int width)
  788. {
  789. struct ofwfb_softc *sc;
  790. int i, j, k;
  791. uint8_t *addr;
  792. u_char fg, bg;
  793. sc = (struct ofwfb_softc *)adp;
  794. addr = (u_int8_t *)((uintptr_t)sc->sc_addr
  795. + (y + sc->sc_ymargin)*sc->sc_stride
  796. + x + sc->sc_xmargin);
  797. fg = ofwfb_foreground(SC_NORM_ATTR);
  798. bg = ofwfb_background(SC_NORM_ATTR);
  799. for (i = 0; i < size && i+y < sc->sc_height - 2*sc->sc_ymargin; i++) {
  800. /*
  801. * Calculate 2 x 4-chars at a time, and then
  802. * write these out.
  803. */
  804. for (j = 0, k = width; j < 8; j++, k--) {
  805. if (x + j >= sc->sc_width - 2*sc->sc_xmargin)
  806. continue;
  807. if (pixel_image[i] & (1 << k))
  808. addr[j] = (addr[j] == fg) ? bg : fg;
  809. }
  810. addr += (sc->sc_stride / sizeof(u_int8_t));
  811. }
  812. return (0);
  813. }
  814. static int
  815. ofwfb_putm32(video_adapter_t *adp, int x, int y, uint8_t *pixel_image,
  816. uint32_t pixel_mask, int size, int width)
  817. {
  818. struct ofwfb_softc *sc;
  819. int i, j, k;
  820. uint32_t fg, bg;
  821. uint32_t *addr;
  822. sc = (struct ofwfb_softc *)adp;
  823. addr = (uint32_t *)sc->sc_addr
  824. + (y + sc->sc_ymargin)*(sc->sc_stride/4)
  825. + x + sc->sc_xmargin;
  826. fg = ofwfb_pix32(sc, ofwfb_foreground(SC_NORM_ATTR));
  827. bg = ofwfb_pix32(sc, ofwfb_background(SC_NORM_ATTR));
  828. for (i = 0; i < size && i+y < sc->sc_height - 2*sc->sc_ymargin; i++) {
  829. for (j = 0, k = width; j < 8; j++, k--) {
  830. if (x + j >= sc->sc_width - 2*sc->sc_xmargin)
  831. continue;
  832. if (pixel_image[i] & (1 << k))
  833. *(addr + j) = (*(addr + j) == fg) ? bg : fg;
  834. }
  835. addr += (sc->sc_stride/4);
  836. }
  837. return (0);
  838. }
  839. /*
  840. * Define the syscons nexus device attachment
  841. */
  842. static void
  843. ofwfb_scidentify(driver_t *driver, device_t parent)
  844. {
  845. device_t child;
  846. /*
  847. * Add with a priority guaranteed to make it last on
  848. * the device list
  849. */
  850. child = BUS_ADD_CHILD(parent, INT_MAX, SC_DRIVER_NAME, 0);
  851. }
  852. static int
  853. ofwfb_scprobe(device_t dev)
  854. {
  855. int error;
  856. device_set_desc(dev, "System console");
  857. error = sc_probe_unit(device_get_unit(dev),
  858. device_get_flags(dev) | SC_AUTODETECT_KBD);
  859. if (error != 0)
  860. return (error);
  861. /* This is a fake device, so make sure we added it ourselves */
  862. return (BUS_PROBE_NOWILDCARD);
  863. }
  864. static int
  865. ofwfb_scattach(device_t dev)
  866. {
  867. return (sc_attach_unit(device_get_unit(dev),
  868. device_get_flags(dev) | SC_AUTODETECT_KBD));
  869. }
  870. static device_method_t ofwfb_sc_methods[] = {
  871. DEVMETHOD(device_identify, ofwfb_scidentify),
  872. DEVMETHOD(device_probe, ofwfb_scprobe),
  873. DEVMETHOD(device_attach, ofwfb_scattach),
  874. { 0, 0 }
  875. };
  876. static driver_t ofwfb_sc_driver = {
  877. SC_DRIVER_NAME,
  878. ofwfb_sc_methods,
  879. sizeof(sc_softc_t),
  880. };
  881. static devclass_t sc_devclass;
  882. DRIVER_MODULE(ofwfb, nexus, ofwfb_sc_driver, sc_devclass, 0, 0);
  883. /*
  884. * Utility routines from <dev/fb/fbreg.h>
  885. */
  886. void
  887. ofwfb_bcopy(const void *s, void *d, size_t c)
  888. {
  889. bcopy(s, d, c);
  890. }
  891. void
  892. ofwfb_bzero(void *d, size_t c)
  893. {
  894. bzero(d, c);
  895. }
  896. void
  897. ofwfb_fillw(int pat, void *base, size_t cnt)
  898. {
  899. u_int16_t *bptr = base;
  900. while (cnt--)
  901. *bptr++ = pat;
  902. }
  903. u_int16_t
  904. ofwfb_readw(u_int16_t *addr)
  905. {
  906. return (*addr);
  907. }
  908. void
  909. ofwfb_writew(u_int16_t *addr, u_int16_t val)
  910. {
  911. *addr = val;
  912. }