xref: /netbsd/sys/arch/powerpc/oea/ofw_rascons.c (revision db6ae655)
1*db6ae655Sandvar /*	$NetBSD: ofw_rascons.c,v 1.18 2021/08/17 22:00:30 andvar 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*db6ae655Sandvar __KERNEL_RCSID(0, "$NetBSD: ofw_rascons.c,v 1.18 2021/08/17 22:00:30 andvar Exp $");
3249067be8Smatt 
3349067be8Smatt #include "wsdisplay.h"
34b0f4d9f9Sgarbled 
35b0f4d9f9Sgarbled #include <sys/param.h>
36b0f4d9f9Sgarbled #include <sys/buf.h>
3749067be8Smatt #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>
5349067be8Smatt #include <dev/wsfont/wsfont.h>
54b0f4d9f9Sgarbled 
5549067be8Smatt #include <powerpc/oea/bat.h>
5644300870Smacallan #include <powerpc/oea/cpufeat.h>
57b0f4d9f9Sgarbled #include <powerpc/oea/ofw_rasconsvar.h>
58b0f4d9f9Sgarbled 
59b0f4d9f9Sgarbled /* we need a wsdisplay to do anything halfway useful */
60b0f4d9f9Sgarbled #if NWSDISPLAY > 0
61b0f4d9f9Sgarbled 
62b0f4d9f9Sgarbled static int copy_rom_font(void);
63b0f4d9f9Sgarbled static struct wsdisplay_font openfirm6x11;
64b0f4d9f9Sgarbled static vaddr_t fbaddr;
65b0f4d9f9Sgarbled static int romfont_loaded = 0;
6644300870Smacallan static int needs_finalize = 0;
67b0f4d9f9Sgarbled 
68b1172170Smacallan #define FONTBUFSIZE (2048)	/* enough for 96 6x11 bitmap characters */
69b1172170Smacallan static uint8_t fontbuf[FONTBUFSIZE];
70b1172170Smacallan 
71b0f4d9f9Sgarbled struct vcons_screen rascons_console_screen;
72b0f4d9f9Sgarbled 
73b0f4d9f9Sgarbled struct wsscreen_descr rascons_stdscreen = {
74b0f4d9f9Sgarbled 	"std",
75b0f4d9f9Sgarbled 	0, 0,	/* will be filled in -- XXX shouldn't, it's global */
76b0f4d9f9Sgarbled 	0,
77b0f4d9f9Sgarbled 	0, 0,
78b0f4d9f9Sgarbled 	WSSCREEN_REVERSE
79b0f4d9f9Sgarbled };
80b0f4d9f9Sgarbled 
81b0f4d9f9Sgarbled int
rascons_cnattach(void)82b0f4d9f9Sgarbled rascons_cnattach(void)
83b0f4d9f9Sgarbled {
84b0f4d9f9Sgarbled 	struct rasops_info *ri = &rascons_console_screen.scr_ri;
85b0f4d9f9Sgarbled 	long defattr;
86b0f4d9f9Sgarbled 	int crow = 0;
87b0f4d9f9Sgarbled 
88b0f4d9f9Sgarbled 	/* get current cursor position */
89b0f4d9f9Sgarbled 	OF_interpret("line#", 0, 1, &crow);
90d2b0a3e1Srin 	if (crow < 0)
91d2b0a3e1Srin 		crow = 0;
92b0f4d9f9Sgarbled 
93b0f4d9f9Sgarbled 	/* move (rom monitor) cursor to the lowest line - 1 */
94b1172170Smacallan 	/* XXXX - Why? */
95b1172170Smacallan #if 0
96b0f4d9f9Sgarbled 	OF_interpret("#lines 2 - to line#", 0, 0);
97b1172170Smacallan #endif
98b0f4d9f9Sgarbled 	wsfont_init();
99b0f4d9f9Sgarbled 	if (copy_rom_font() == 0) {
100ad3c3c99Smacallan #if !defined(OFWOEA_WSCONS_NO_ROM_FONT)
101b0f4d9f9Sgarbled 		romfont_loaded = 1;
102ad3c3c99Smacallan #endif /* !OFWOEA_WSCONS_NO_ROM_FONT */
103b0f4d9f9Sgarbled 	}
104b0f4d9f9Sgarbled 
105b0f4d9f9Sgarbled 	/* set up rasops */
106b0f4d9f9Sgarbled 	rascons_init_rasops(console_node, ri);
107b0f4d9f9Sgarbled 
108b0f4d9f9Sgarbled 	/*
109b0f4d9f9Sgarbled 	 * no need to clear the screen here when we're mimicing firmware
110b0f4d9f9Sgarbled 	 * output anyway
111b0f4d9f9Sgarbled 	 */
112b0f4d9f9Sgarbled #if 0
113b0f4d9f9Sgarbled 	if (ri->ri_width >= 1024 && ri->ri_height >= 768) {
114b0f4d9f9Sgarbled 		int i, screenbytes = ri->ri_stride * ri->ri_height;
115b0f4d9f9Sgarbled 
116b0f4d9f9Sgarbled 		for (i = 0; i < screenbytes; i += sizeof(u_int32_t))
117b0f4d9f9Sgarbled 			*(u_int32_t *)(fbaddr + i) = 0xffffffff;
118b0f4d9f9Sgarbled 		crow = 0;
119b0f4d9f9Sgarbled 	}
120b0f4d9f9Sgarbled #endif
121b0f4d9f9Sgarbled 
122b0f4d9f9Sgarbled 	rascons_stdscreen.nrows = ri->ri_rows;
123b0f4d9f9Sgarbled 	rascons_stdscreen.ncols = ri->ri_cols;
124b0f4d9f9Sgarbled 	rascons_stdscreen.textops = &ri->ri_ops;
125b0f4d9f9Sgarbled 	rascons_stdscreen.capabilities = ri->ri_caps;
126b0f4d9f9Sgarbled 
127a9a9825eSmacallan 	/*
128a9a9825eSmacallan 	 * XXX
129a9a9825eSmacallan 	 * On some G5 models ( so far, 970FX but not 970MP ) we can't seem to
130a9a9825eSmacallan 	 * access video memory in real mode, but a lot of code relies on rasops
131a9a9825eSmacallan 	 * data structures being set up early so we can't just push the whole
132a9a9825eSmacallan 	 * thing further down. Instead set things up but don't actually attach
133a9a9825eSmacallan 	 * the console until later.
134a9a9825eSmacallan 	 * This needs a better trigger but for now I can't reliably tell which
135a9a9825eSmacallan 	 * exact models / CPUs / other hardware actually need it.
136a9a9825eSmacallan 	 */
13744300870Smacallan 	if ((oeacpufeat & OEACPU_64_BRIDGE) != 0) {
13844300870Smacallan 		needs_finalize = 1;
13944300870Smacallan 	} else {
140b0f4d9f9Sgarbled 		ri->ri_ops.allocattr(ri, 0, 0, 0, &defattr);
141a8a5c538Sriastradh 		wsdisplay_preattach(&rascons_stdscreen, ri, 0, uimax(0,
142a8a5c538Sriastradh 		    uimin(crow, ri->ri_rows - 1)), defattr);
14344300870Smacallan 	}
144b0f4d9f9Sgarbled #if notyet
145b0f4d9f9Sgarbled 	rascons_init_cmap(NULL);
146b0f4d9f9Sgarbled #endif
147b0f4d9f9Sgarbled 
148b0f4d9f9Sgarbled 	return 0;
149b0f4d9f9Sgarbled }
150b0f4d9f9Sgarbled 
15144300870Smacallan void
rascons_add_rom_font(void)152b1172170Smacallan rascons_add_rom_font(void)
153b1172170Smacallan {
154b1172170Smacallan 	wsfont_init();
155b1172170Smacallan 	if (romfont_loaded) {
156b1172170Smacallan 		wsfont_add(&openfirm6x11, 0);
157b1172170Smacallan 	}
158b1172170Smacallan }
159b1172170Smacallan 
160b1172170Smacallan void
rascons_finalize(void)16144300870Smacallan rascons_finalize(void)
16244300870Smacallan {
16344300870Smacallan 	struct rasops_info *ri = &rascons_console_screen.scr_ri;
16444300870Smacallan 	long defattr;
165b1172170Smacallan 	int crow = 0;
16644300870Smacallan 
16744300870Smacallan 	if (needs_finalize == 0) return;
16844300870Smacallan 
169b1172170Smacallan 	/* get current cursor position */
170d2b0a3e1Srin 	if (romfont_loaded) {
171d2b0a3e1Srin 		OF_interpret("line#", 0, 1, &crow);
172d2b0a3e1Srin 		if (crow < 0)
173d2b0a3e1Srin 			crow = 0;
174d2b0a3e1Srin 	}
175b1172170Smacallan 
17644300870Smacallan 	ri->ri_ops.allocattr(ri, 0, 0, 0, &defattr);
177b1172170Smacallan 	wsdisplay_preattach(&rascons_stdscreen, ri, 0, uimax(0,
178b1172170Smacallan 		    uimin(crow, ri->ri_rows - 1)), defattr);
17944300870Smacallan }
18044300870Smacallan 
181b0f4d9f9Sgarbled static int
copy_rom_font(void)182df7f595eScegger copy_rom_font(void)
183b0f4d9f9Sgarbled {
184b0f4d9f9Sgarbled 	u_char *romfont;
185b1172170Smacallan 	int char_width, char_height, stride;
186b1172170Smacallan 	int chosen, mmu, m, e, size;
187b0f4d9f9Sgarbled 
188d2b0a3e1Srin 	/*
189d2b0a3e1Srin 	 * Get ROM FONT address.
190d2b0a3e1Srin 	 *
191d2b0a3e1Srin 	 * For some machines like ``PowerMac11,2'', Open Firmware does not
192d2b0a3e1Srin 	 * initialize console-related variables when auto-boot? is true;
193d2b0a3e1Srin 	 * -1 is returned instead of correct value. Fall back to wsfont
194d2b0a3e1Srin 	 * embedded in kernel in this case.
195d2b0a3e1Srin 	 */
196b0f4d9f9Sgarbled 	OF_interpret("font-adr", 0, 1, &romfont);
197d2b0a3e1Srin 	if (romfont == NULL || romfont == (u_char *)-1)
198b0f4d9f9Sgarbled 		return -1;
199b0f4d9f9Sgarbled 
200b0f4d9f9Sgarbled 	chosen = OF_finddevice("/chosen");
201b0f4d9f9Sgarbled 	OF_getprop(chosen, "mmu", &mmu, 4);
202b0f4d9f9Sgarbled 
203b0f4d9f9Sgarbled 	/*
204*db6ae655Sandvar 	 * Convert to physical address.  We cannot access to Open Firmware's
205b0f4d9f9Sgarbled 	 * virtual address space.
206b0f4d9f9Sgarbled 	 */
207b0f4d9f9Sgarbled 	OF_call_method("translate", mmu, 1, 3, romfont, &romfont, &m, &e);
208b0f4d9f9Sgarbled 
209b0f4d9f9Sgarbled 	/* Get character size */
210b0f4d9f9Sgarbled 	OF_interpret("char-width", 0, 1, &char_width);
211b0f4d9f9Sgarbled 	OF_interpret("char-height", 0, 1, &char_height);
212b0f4d9f9Sgarbled 
213b1172170Smacallan 	stride = (char_width + 7) >> 3;
214b1172170Smacallan 	size = stride * char_height * 96;
215b1172170Smacallan 	if (size > FONTBUFSIZE) return -1;
216b1172170Smacallan 
217b1172170Smacallan 	memcpy(fontbuf, romfont, size);
218b1172170Smacallan 
219b0f4d9f9Sgarbled 	openfirm6x11.name = "Open Firmware";
220b0f4d9f9Sgarbled 	openfirm6x11.firstchar = 32;
221b0f4d9f9Sgarbled 	openfirm6x11.numchars = 96;
222b0f4d9f9Sgarbled 	openfirm6x11.encoding = WSDISPLAY_FONTENC_ISO;
223b0f4d9f9Sgarbled 	openfirm6x11.fontwidth = char_width;
224b0f4d9f9Sgarbled 	openfirm6x11.fontheight = char_height;
225b1172170Smacallan 	openfirm6x11.stride = stride;
226b0f4d9f9Sgarbled 	openfirm6x11.bitorder = WSDISPLAY_FONTORDER_L2R;
227b0f4d9f9Sgarbled 	openfirm6x11.byteorder = WSDISPLAY_FONTORDER_L2R;
228b1172170Smacallan 	openfirm6x11.data = fontbuf;
229b0f4d9f9Sgarbled 
230b0f4d9f9Sgarbled 	return 0;
231b0f4d9f9Sgarbled }
232b0f4d9f9Sgarbled 
233b0f4d9f9Sgarbled int
rascons_init_rasops(int node,struct rasops_info * ri)234b0f4d9f9Sgarbled rascons_init_rasops(int node, struct rasops_info *ri)
235b0f4d9f9Sgarbled {
236b0f4d9f9Sgarbled 	int32_t width, height, linebytes, depth;
237b0f4d9f9Sgarbled 
238b0f4d9f9Sgarbled 	/* XXX /chaos/control doesn't have "width", "height", ... */
239b0f4d9f9Sgarbled 	width = height = -1;
240b0f4d9f9Sgarbled 	if (OF_getprop(node, "width", &width, 4) != 4)
241b0f4d9f9Sgarbled 		OF_interpret("screen-width", 0, 1, &width);
242b0f4d9f9Sgarbled 	if (OF_getprop(node, "height", &height, 4) != 4)
243b0f4d9f9Sgarbled 		OF_interpret("screen-height", 0, 1, &height);
244b0f4d9f9Sgarbled 	if (OF_getprop(node, "linebytes", &linebytes, 4) != 4)
245b0f4d9f9Sgarbled 		linebytes = width;			/* XXX */
246b0f4d9f9Sgarbled 	if (OF_getprop(node, "depth", &depth, 4) != 4)
247b0f4d9f9Sgarbled 		depth = 8;				/* XXX */
248b0f4d9f9Sgarbled 	if (OF_getprop(node, "address", &fbaddr, 4) != 4)
249b0f4d9f9Sgarbled 		OF_interpret("frame-buffer-adr", 0, 1, &fbaddr);
250b0f4d9f9Sgarbled 
251b0f4d9f9Sgarbled 	if (width == -1 || height == -1 || fbaddr == 0 || fbaddr == -1)
252b0f4d9f9Sgarbled 		return false;
253b0f4d9f9Sgarbled 
254b0f4d9f9Sgarbled 	/* initialize rasops */
255b0f4d9f9Sgarbled 	ri->ri_width = width;
256b0f4d9f9Sgarbled 	ri->ri_height = height;
257b0f4d9f9Sgarbled 	ri->ri_depth = depth;
258b0f4d9f9Sgarbled 	ri->ri_stride = linebytes;
259b0f4d9f9Sgarbled 	ri->ri_bits = (char *)fbaddr;
2602fcb22f4Smacallan 	ri->ri_flg = RI_CENTER | RI_FULLCLEAR | RI_NO_AUTO;
261b0f4d9f9Sgarbled 
262b0f4d9f9Sgarbled 	/* mimic firmware output if we can find the ROM font */
263b0f4d9f9Sgarbled 	if (romfont_loaded) {
264b1172170Smacallan 		int cols = 0, rows = 0;
265b0f4d9f9Sgarbled 
266b0f4d9f9Sgarbled 		/*
267b0f4d9f9Sgarbled 		 * XXX this assumes we're the console which may or may not
268b0f4d9f9Sgarbled 		 * be the case
269b0f4d9f9Sgarbled 		 */
270b0f4d9f9Sgarbled 		OF_interpret("#lines", 0, 1, &rows);
271b0f4d9f9Sgarbled 		OF_interpret("#columns", 0, 1, &cols);
272b0f4d9f9Sgarbled 		ri->ri_font = &openfirm6x11;
273b0f4d9f9Sgarbled 		ri->ri_wsfcookie = -1;		/* not using wsfont */
274b0f4d9f9Sgarbled 		rasops_init(ri, rows, cols);
275b1172170Smacallan #ifdef RASCONS_DEBUG
276b1172170Smacallan 		char buffer[128];
277b1172170Smacallan 		snprintf(buffer, 128, "bits %08x c %d w %d -> %d %d\n",
278b1172170Smacallan 		    (uint32_t)ri->ri_bits, cols, width, ri->ri_xorigin, ri->ri_yorigin);
279b1172170Smacallan 		OF_write(console_instance, buffer, strlen(buffer));
280b1172170Smacallan #endif
281b0f4d9f9Sgarbled 	} else {
282b0f4d9f9Sgarbled 		/* use as much of the screen as the font permits */
283b0f4d9f9Sgarbled 		rasops_init(ri, height/8, width/8);
284b0f4d9f9Sgarbled 		ri->ri_caps = WSSCREEN_WSCOLORS;
285b0f4d9f9Sgarbled 		rasops_reconfig(ri, height / ri->ri_font->fontheight,
286b0f4d9f9Sgarbled 		    width / ri->ri_font->fontwidth);
287b0f4d9f9Sgarbled 	}
288b0f4d9f9Sgarbled 
28981fd6b80Srin #ifdef macppc
290ff0bfa5fSrin 	if (depth == 8 && ofw_quiesce) {
291ff0bfa5fSrin 		/*
292ff0bfa5fSrin 		 * Open Firmware will be quiesced. This is last chance to
293ff0bfa5fSrin 		 * set color palette via ``color!'' method.
294ff0bfa5fSrin 		 */
295ff0bfa5fSrin 		for (int i = 0; i < 256; i++) {
296ff0bfa5fSrin 			OF_call_method_1("color!", console_instance, 4,
297ff0bfa5fSrin 			    rasops_cmap[3 * i], rasops_cmap[3 * i + 1],
298ff0bfa5fSrin 			    rasops_cmap[3 * i + 2], i);
299ff0bfa5fSrin 		}
300ff0bfa5fSrin 	}
30181fd6b80Srin #endif
302ff0bfa5fSrin 
303b0f4d9f9Sgarbled 	return true;
304b0f4d9f9Sgarbled }
305b0f4d9f9Sgarbled #else	/* NWSDISPLAY > 0 */
306b0f4d9f9Sgarbled int
rascons_cnattach(void)307df7f595eScegger rascons_cnattach(void)
308b0f4d9f9Sgarbled {
309b0f4d9f9Sgarbled 	return -1;
310b0f4d9f9Sgarbled }
311b0f4d9f9Sgarbled #endif
312