xref: /netbsd/sys/arch/powerpc/oea/ofw_rascons.c (revision 49067be8)
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