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