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