1 /* $NetBSD: ofw_rascons.c,v 1.9 2013/04/11 18:04:20 macallan Exp $ */ 2 3 /* 4 * Copyright (c) 1995, 1996 Carnegie-Mellon University. 5 * All rights reserved. 6 * 7 * Author: Chris G. Demetriou 8 * 9 * Permission to use, copy, modify and distribute this software and 10 * its documentation is hereby granted, provided that both the copyright 11 * notice and this permission notice appear in all copies of the 12 * software, derivative works or modified versions, and any portions 13 * thereof, and that both notices appear in supporting documentation. 14 * 15 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" 16 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND 17 * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 18 * 19 * Carnegie Mellon requests users of this software to return to 20 * 21 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 22 * School of Computer Science 23 * Carnegie Mellon University 24 * Pittsburgh PA 15213-3890 25 * 26 * any improvements or extensions that they make and grant Carnegie the 27 * rights to redistribute these changes. 28 */ 29 30 #include <sys/cdefs.h> 31 __KERNEL_RCSID(0, "$NetBSD: ofw_rascons.c,v 1.9 2013/04/11 18:04:20 macallan Exp $"); 32 33 #include "wsdisplay.h" 34 35 #include <sys/param.h> 36 #include <sys/buf.h> 37 #include <sys/bus.h> 38 #include <sys/conf.h> 39 #include <sys/device.h> 40 #include <sys/ioctl.h> 41 #include <sys/kernel.h> 42 #include <sys/systm.h> 43 44 #include <dev/ofw/openfirm.h> 45 #include <uvm/uvm_extern.h> 46 47 #include <machine/autoconf.h> 48 49 #include <dev/wscons/wsconsio.h> 50 #include <dev/wscons/wsdisplayvar.h> 51 #include <dev/rasops/rasops.h> 52 #include <dev/wscons/wsdisplay_vconsvar.h> 53 #include <dev/wsfont/wsfont.h> 54 55 #include <powerpc/oea/bat.h> 56 #include <powerpc/oea/ofw_rasconsvar.h> 57 58 /* we need a wsdisplay to do anything halfway useful */ 59 #if NWSDISPLAY > 0 60 61 #if defined(PPC_OEA64) || defined (PPC_OEA64_BRIDGE) 62 int rascons_enable_cache = 0; 63 #else 64 #ifdef OFB_ENABLE_CACHE 65 int rascons_enable_cache = 1; 66 #else 67 int rascons_enable_cache = 0; 68 #endif 69 #endif /* PPC_OEA64 */ 70 71 static int copy_rom_font(void); 72 static struct wsdisplay_font openfirm6x11; 73 static vaddr_t fbaddr; 74 static int romfont_loaded = 0; 75 76 struct vcons_screen rascons_console_screen; 77 78 struct wsscreen_descr rascons_stdscreen = { 79 "std", 80 0, 0, /* will be filled in -- XXX shouldn't, it's global */ 81 0, 82 0, 0, 83 WSSCREEN_REVERSE 84 }; 85 86 int 87 rascons_cnattach(void) 88 { 89 struct rasops_info *ri = &rascons_console_screen.scr_ri; 90 long defattr; 91 int crow = 0; 92 93 /* get current cursor position */ 94 OF_interpret("line#", 0, 1, &crow); 95 96 /* move (rom monitor) cursor to the lowest line - 1 */ 97 OF_interpret("#lines 2 - to line#", 0, 0); 98 99 wsfont_init(); 100 if (copy_rom_font() == 0) { 101 #if !defined(OFWOEA_WSCONS_NO_ROM_FONT) 102 romfont_loaded = 1; 103 #endif /* !OFWOEA_WSCONS_NO_ROM_FONT */ 104 } 105 106 /* set up rasops */ 107 rascons_init_rasops(console_node, ri); 108 109 /* 110 * no need to clear the screen here when we're mimicing firmware 111 * output anyway 112 */ 113 #if 0 114 if (ri->ri_width >= 1024 && ri->ri_height >= 768) { 115 int i, screenbytes = ri->ri_stride * ri->ri_height; 116 117 for (i = 0; i < screenbytes; i += sizeof(u_int32_t)) 118 *(u_int32_t *)(fbaddr + i) = 0xffffffff; 119 crow = 0; 120 } 121 #endif 122 123 rascons_stdscreen.nrows = ri->ri_rows; 124 rascons_stdscreen.ncols = ri->ri_cols; 125 rascons_stdscreen.textops = &ri->ri_ops; 126 rascons_stdscreen.capabilities = ri->ri_caps; 127 128 ri->ri_ops.allocattr(ri, 0, 0, 0, &defattr); 129 wsdisplay_preattach(&rascons_stdscreen, ri, 0, max(0, 130 min(crow, ri->ri_rows - 1)), defattr); 131 132 #if notyet 133 rascons_init_cmap(NULL); 134 #endif 135 136 return 0; 137 } 138 139 static int 140 copy_rom_font(void) 141 { 142 u_char *romfont; 143 int char_width, char_height; 144 int chosen, mmu, m, e; 145 146 /* Get ROM FONT address. */ 147 OF_interpret("font-adr", 0, 1, &romfont); 148 if (romfont == NULL) 149 return -1; 150 151 chosen = OF_finddevice("/chosen"); 152 OF_getprop(chosen, "mmu", &mmu, 4); 153 154 /* 155 * Convert to physcal address. We cannot access to Open Firmware's 156 * virtual address space. 157 */ 158 OF_call_method("translate", mmu, 1, 3, romfont, &romfont, &m, &e); 159 160 /* Get character size */ 161 OF_interpret("char-width", 0, 1, &char_width); 162 OF_interpret("char-height", 0, 1, &char_height); 163 164 openfirm6x11.name = "Open Firmware"; 165 openfirm6x11.firstchar = 32; 166 openfirm6x11.numchars = 96; 167 openfirm6x11.encoding = WSDISPLAY_FONTENC_ISO; 168 openfirm6x11.fontwidth = char_width; 169 openfirm6x11.fontheight = char_height; 170 openfirm6x11.stride = 1; 171 openfirm6x11.bitorder = WSDISPLAY_FONTORDER_L2R; 172 openfirm6x11.byteorder = WSDISPLAY_FONTORDER_L2R; 173 openfirm6x11.data = romfont; 174 175 return 0; 176 } 177 178 int 179 rascons_init_rasops(int node, struct rasops_info *ri) 180 { 181 int32_t width, height, linebytes, depth; 182 183 /* XXX /chaos/control doesn't have "width", "height", ... */ 184 width = height = -1; 185 if (OF_getprop(node, "width", &width, 4) != 4) 186 OF_interpret("screen-width", 0, 1, &width); 187 if (OF_getprop(node, "height", &height, 4) != 4) 188 OF_interpret("screen-height", 0, 1, &height); 189 if (OF_getprop(node, "linebytes", &linebytes, 4) != 4) 190 linebytes = width; /* XXX */ 191 if (OF_getprop(node, "depth", &depth, 4) != 4) 192 depth = 8; /* XXX */ 193 if (OF_getprop(node, "address", &fbaddr, 4) != 4) 194 OF_interpret("frame-buffer-adr", 0, 1, &fbaddr); 195 196 if (width == -1 || height == -1 || fbaddr == 0 || fbaddr == -1) 197 return false; 198 199 /* Enable write-through cache. */ 200 #if defined (PPC_OEA) && !defined (PPC_OEA64) && !defined (PPC_OEA64_BRIDGE) 201 if (rascons_enable_cache) { 202 vaddr_t va; 203 /* 204 * Let's try to find an empty 256M BAT to use 205 */ 206 for (va = SEGMENT_LENGTH; va < (USER_SR << ADDR_SR_SHFT); 207 va += SEGMENT_LENGTH) { 208 const u_int i = BAT_VA2IDX(va); 209 const u_int n = BAT_VA2IDX(SEGMENT_LENGTH); 210 u_int j; 211 for (j = 0; j < n; j++) { 212 if (battable[i+j].batu != 0) { 213 break; 214 } 215 } 216 if (j == n) { 217 register_t batl = BATL(fbaddr & 0xf0000000, 218 BAT_G | BAT_W | BAT_M, BAT_PP_RW); 219 register_t batu = BATL(va, BAT_BL_256M, BAT_Vs); 220 for (j = 0; j < n; j++) { 221 battable[i+j].batl = batl; 222 battable[i+j].batu = batu; 223 } 224 fbaddr &= SEGMENT_MASK; 225 fbaddr |= va; 226 break; 227 } 228 } 229 } 230 #endif /* PPC_OEA64 */ 231 232 /* initialize rasops */ 233 ri->ri_width = width; 234 ri->ri_height = height; 235 ri->ri_depth = depth; 236 ri->ri_stride = linebytes; 237 ri->ri_bits = (char *)fbaddr; 238 ri->ri_flg = RI_CENTER | RI_FULLCLEAR | RI_NO_AUTO; 239 240 /* mimic firmware output if we can find the ROM font */ 241 if (romfont_loaded) { 242 int cols, rows; 243 244 /* 245 * XXX this assumes we're the console which may or may not 246 * be the case 247 */ 248 OF_interpret("#lines", 0, 1, &rows); 249 OF_interpret("#columns", 0, 1, &cols); 250 ri->ri_font = &openfirm6x11; 251 ri->ri_wsfcookie = -1; /* not using wsfont */ 252 rasops_init(ri, rows, cols); 253 254 ri->ri_xorigin = (width - cols * ri->ri_font->fontwidth) >> 1; 255 ri->ri_yorigin = (height - rows * ri->ri_font->fontheight) 256 >> 1; 257 ri->ri_bits = (char *)fbaddr + ri->ri_xorigin + 258 ri->ri_stride * ri->ri_yorigin; 259 } else { 260 /* use as much of the screen as the font permits */ 261 rasops_init(ri, height/8, width/8); 262 ri->ri_caps = WSSCREEN_WSCOLORS; 263 rasops_reconfig(ri, height / ri->ri_font->fontheight, 264 width / ri->ri_font->fontwidth); 265 } 266 267 return true; 268 } 269 #else /* NWSDISPLAY > 0 */ 270 int 271 rascons_cnattach(void) 272 { 273 return -1; 274 } 275 #endif 276