creator_vt.c revision 271128
1/*- 2 * Copyright (c) 2014 Nathan Whitehorn 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include <sys/cdefs.h> 28__FBSDID("$FreeBSD: stable/10/sys/dev/fb/creator_vt.c 271128 2014-09-04 20:18:08Z emaste $"); 29 30#include <sys/param.h> 31#include <sys/kernel.h> 32#include <sys/systm.h> 33#include <sys/fbio.h> 34 35#include <dev/vt/vt.h> 36#include <dev/vt/hw/fb/vt_fb.h> 37#include <dev/vt/colors/vt_termcolors.h> 38 39#include <machine/bus.h> 40#include <machine/bus_private.h> 41 42#include <dev/ofw/openfirm.h> 43#include "creatorreg.h" 44 45static vd_probe_t creatorfb_probe; 46static vd_init_t creatorfb_init; 47static vd_blank_t creatorfb_blank; 48static vd_bitblt_text_t creatorfb_bitblt_text; 49static vd_bitblt_bmp_t creatorfb_bitblt_bitmap; 50 51static const struct vt_driver vt_creatorfb_driver = { 52 .vd_name = "creatorfb", 53 .vd_probe = creatorfb_probe, 54 .vd_init = creatorfb_init, 55 .vd_blank = creatorfb_blank, 56 .vd_bitblt_text = creatorfb_bitblt_text, 57 .vd_bitblt_bmp = creatorfb_bitblt_bitmap, 58 .vd_fb_ioctl = vt_fb_ioctl, 59 .vd_fb_mmap = vt_fb_mmap, 60 .vd_priority = VD_PRIORITY_SPECIFIC 61}; 62 63struct creatorfb_softc { 64 struct fb_info fb; 65 struct bus_space_tag memt[1]; 66 bus_space_handle_t memh; 67}; 68 69static struct creatorfb_softc creatorfb_conssoftc; 70VT_DRIVER_DECLARE(vt_creatorfb, vt_creatorfb_driver); 71 72static int 73creatorfb_probe(struct vt_device *vd) 74{ 75 phandle_t chosen, node; 76 ihandle_t stdout; 77 char type[64], name[64]; 78 79 chosen = OF_finddevice("/chosen"); 80 OF_getprop(chosen, "stdout", &stdout, sizeof(stdout)); 81 node = OF_instance_to_package(stdout); 82 if (node == -1) { 83 /* 84 * The "/chosen/stdout" does not exist try 85 * using "screen" directly. 86 */ 87 node = OF_finddevice("screen"); 88 } 89 OF_getprop(node, "device_type", type, sizeof(type)); 90 if (strcmp(type, "display") != 0) 91 return (CN_DEAD); 92 93 OF_getprop(node, "name", name, sizeof(name)); 94 if (strcmp(name, "SUNW,ffb") != 0 && strcmp(name, "SUNW,afb") != 0) 95 return (CN_DEAD); 96 97 /* Looks OK... */ 98 return (CN_INTERNAL); 99} 100 101static int 102creatorfb_init(struct vt_device *vd) 103{ 104 struct creatorfb_softc *sc; 105 phandle_t chosen; 106 phandle_t node; 107 ihandle_t handle; 108 uint32_t height, width; 109 char type[64], name[64]; 110 bus_addr_t phys; 111 int space; 112 113 /* Initialize softc */ 114 vd->vd_softc = sc = &creatorfb_conssoftc; 115 116 chosen = OF_finddevice("/chosen"); 117 OF_getprop(chosen, "stdout", &handle, sizeof(ihandle_t)); 118 node = OF_instance_to_package(handle); 119 if (node == -1) { 120 /* 121 * The "/chosen/stdout" does not exist try 122 * using "screen" directly. 123 */ 124 node = OF_finddevice("screen"); 125 handle = OF_open("screen"); 126 } 127 OF_getprop(node, "device_type", type, sizeof(type)); 128 if (strcmp(type, "display") != 0) 129 return (CN_DEAD); 130 131 OF_getprop(node, "name", name, sizeof(name)); 132 if (strcmp(name, "SUNW,ffb") != 0 && strcmp(name, "SUNW,afb") != 0) 133 return (CN_DEAD); 134 135 /* Make sure we have needed properties */ 136 if (OF_getproplen(node, "height") != sizeof(height) || 137 OF_getproplen(node, "width") != sizeof(width)) 138 return (CN_DEAD); 139 140 OF_getprop(node, "height", &height, sizeof(height)); 141 OF_getprop(node, "width", &width, sizeof(width)); 142 143 sc->fb.fb_height = height; 144 sc->fb.fb_width = width; 145 sc->fb.fb_bpp = sc->fb.fb_depth = 32; 146 sc->fb.fb_stride = 8192; /* Fixed */ 147 sc->fb.fb_size = sc->fb.fb_height * sc->fb.fb_stride; 148 149 /* Map linear framebuffer */ 150 if (OF_decode_addr(node, FFB_DFB24, &space, &phys) != 0) 151 return (CN_DEAD); 152 sc->fb.fb_pbase = phys; 153 sc->memh = sparc64_fake_bustag(space, phys, &sc->memt[0]); 154 155 /* 32-bit VGA palette */ 156 vt_generate_cons_palette(sc->fb.fb_cmap, COLOR_FORMAT_RGB, 157 255, 0, 255, 8, 255, 16); 158 sc->fb.fb_cmsize = 16; 159 160 vt_fb_init(vd); 161 162 return (CN_INTERNAL); 163} 164 165static void 166creatorfb_blank(struct vt_device *vd, term_color_t color) 167{ 168 struct creatorfb_softc *sc; 169 uint32_t c; 170 int i; 171 172 sc = vd->vd_softc; 173 c = sc->fb.fb_cmap[color]; 174 175 for (i = 0; i < sc->fb.fb_height; i++) 176 bus_space_set_region_4(sc->memt, sc->memh, i*sc->fb.fb_stride, 177 c, sc->fb.fb_width); 178} 179 180static void 181creatorfb_bitblt_bitmap(struct vt_device *vd, const struct vt_window *vw, 182 const uint8_t *pattern, const uint8_t *mask, 183 unsigned int width, unsigned int height, 184 unsigned int x, unsigned int y, term_color_t fg, term_color_t bg) 185{ 186 struct creatorfb_softc *sc = vd->vd_softc; 187 u_long line; 188 uint32_t fgc, bgc; 189 int c, l; 190 uint8_t b, m; 191 192 fgc = sc->fb.fb_cmap[fg]; 193 bgc = sc->fb.fb_cmap[bg]; 194 b = m = 0; 195 196 line = (sc->fb.fb_stride * y) + 4*x; 197 for (l = 0; 198 l < height && y + l < vw->vw_draw_area.tr_end.tp_row; 199 l++) { 200 for (c = 0; 201 c < width && x + c < vw->vw_draw_area.tr_end.tp_col; 202 c++) { 203 if (c % 8 == 0) 204 b = *pattern++; 205 else 206 b <<= 1; 207 if (mask != NULL) { 208 if (c % 8 == 0) 209 m = *mask++; 210 else 211 m <<= 1; 212 /* Skip pixel write if mask not set. */ 213 if ((m & 0x80) == 0) 214 continue; 215 } 216 bus_space_write_4(sc->memt, sc->memh, line + 4*c, 217 (b & 0x80) ? fgc : bgc); 218 } 219 line += sc->fb.fb_stride; 220 } 221} 222 223void 224creatorfb_bitblt_text(struct vt_device *vd, const struct vt_window *vw, 225 const term_rect_t *area) 226{ 227 unsigned int col, row, x, y; 228 struct vt_font *vf; 229 term_char_t c; 230 term_color_t fg, bg; 231 const uint8_t *pattern; 232 233 vf = vw->vw_font; 234 235 for (row = area->tr_begin.tp_row; row < area->tr_end.tp_row; ++row) { 236 for (col = area->tr_begin.tp_col; col < area->tr_end.tp_col; 237 ++col) { 238 x = col * vf->vf_width + 239 vw->vw_draw_area.tr_begin.tp_col; 240 y = row * vf->vf_height + 241 vw->vw_draw_area.tr_begin.tp_row; 242 243 c = VTBUF_GET_FIELD(&vw->vw_buf, row, col); 244 pattern = vtfont_lookup(vf, c); 245 vt_determine_colors(c, 246 VTBUF_ISCURSOR(&vw->vw_buf, row, col), &fg, &bg); 247 248 creatorfb_bitblt_bitmap(vd, vw, 249 pattern, NULL, vf->vf_width, vf->vf_height, 250 x, y, fg, bg); 251 } 252 } 253 254#ifndef SC_NO_CUTPASTE 255 if (!vd->vd_mshown) 256 return; 257 258 term_rect_t drawn_area; 259 260 drawn_area.tr_begin.tp_col = area->tr_begin.tp_col * vf->vf_width; 261 drawn_area.tr_begin.tp_row = area->tr_begin.tp_row * vf->vf_height; 262 drawn_area.tr_end.tp_col = area->tr_end.tp_col * vf->vf_width; 263 drawn_area.tr_end.tp_row = area->tr_end.tp_row * vf->vf_height; 264 265 if (vt_is_cursor_in_area(vd, &drawn_area)) { 266 creatorfb_bitblt_bitmap(vd, vw, 267 vd->vd_mcursor->map, vd->vd_mcursor->mask, 268 vd->vd_mcursor->width, vd->vd_mcursor->height, 269 vd->vd_mx_drawn + vw->vw_draw_area.tr_begin.tp_col, 270 vd->vd_my_drawn + vw->vw_draw_area.tr_begin.tp_row, 271 vd->vd_mcursor_fg, vd->vd_mcursor_bg); 272 } 273#endif 274} 275