xref: /netbsd-src/sys/arch/mac68k/dev/macfb.c (revision 001c68bd94f75ce9270b69227c4199fbf34ee396)
1 /* $NetBSD: macfb.c,v 1.9 2002/10/02 05:36:37 thorpej Exp $ */
2 /*
3  * Copyright (c) 1998 Matt DeBergalis
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. All advertising materials mentioning features or use of this software
15  *    must display the following acknowledgement:
16  *      This product includes software developed by Matt DeBergalis
17  * 4. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31 
32 #include "opt_wsdisplay_compat.h"
33 #include "grf.h"
34 
35 #include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
36 
37 #include <sys/param.h>
38 #include <sys/systm.h>
39 #include <sys/kernel.h>
40 #include <sys/device.h>
41 #include <sys/malloc.h>
42 
43 #include <machine/cpu.h>
44 #include <machine/bus.h>
45 
46 #include <machine/grfioctl.h>
47 #include <mac68k/nubus/nubus.h>
48 #include <mac68k/dev/grfvar.h>
49 #include <mac68k/dev/macfbvar.h>
50 #include <dev/wscons/wsconsio.h>
51 
52 #include <dev/rcons/raster.h>
53 #include <dev/wscons/wscons_raster.h>
54 #include <dev/wscons/wsdisplayvar.h>
55 
56 int macfb_match __P((struct device *, struct cfdata *, void *));
57 void macfb_attach __P((struct device *, struct device *, void *));
58 
59 CFATTACH_DECL(macfb, sizeof(struct macfb_softc),
60     macfb_match, macfb_attach, NULL, NULL);
61 
62 const struct wsdisplay_emulops macfb_emulops = {
63 	rcons_cursor,
64 	rcons_mapchar,
65 	rcons_putchar,
66 	rcons_copycols,
67 	rcons_erasecols,
68 	rcons_copyrows,
69 	rcons_eraserows,
70 	rcons_allocattr
71 };
72 
73 struct wsscreen_descr macfb_stdscreen = {
74 	"std",
75 	0, 0, /* will be filled in -- XXX shouldn't, it's global */
76 	&macfb_emulops,
77 	0, 0,
78 	WSSCREEN_REVERSE
79 };
80 
81 const struct wsscreen_descr *_macfb_scrlist[] = {
82 	&macfb_stdscreen,
83 };
84 
85 const struct wsscreen_list macfb_screenlist = {
86 	sizeof(_macfb_scrlist) / sizeof(struct wsscreen_descr *),
87 	_macfb_scrlist
88 };
89 
90 static int	macfb_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
91 static paddr_t	macfb_mmap __P((void *, off_t, int));
92 static int	macfb_alloc_screen __P((void *, const struct wsscreen_descr *,
93 		    void **, int *, int *, long *));
94 static void	macfb_free_screen __P((void *, void *));
95 static int	macfb_show_screen __P((void *, void *, int,
96 		    void (*)(void *, int, int), void *));
97 
98 const struct wsdisplay_accessops macfb_accessops = {
99 	macfb_ioctl,
100 	macfb_mmap,
101 	macfb_alloc_screen,
102 	macfb_free_screen,
103 	macfb_show_screen,
104 	0 /* load_font */
105 };
106 
107 void macfb_init __P((struct macfb_devconfig *));
108 
109 paddr_t macfb_consaddr;
110 static int macfb_is_console __P((paddr_t addr));
111 #ifdef WSDISPLAY_COMPAT_ITEFONT
112 static void	init_itefont __P((void));
113 #endif /* WSDISPLAY_COMPAT_ITEFONT */
114 
115 static struct macfb_devconfig macfb_console_dc;
116 
117 /* From Booter via locore */
118 extern long		videoaddr;
119 extern long		videorowbytes;
120 extern long		videobitdepth;
121 extern u_long		videosize;
122 extern u_int32_t	mac68k_vidlog;
123 extern u_int32_t	mac68k_vidphys;
124 extern u_int32_t	mac68k_vidlen;
125 
126 static int
127 macfb_is_console(paddr_t addr)
128 {
129 	if (addr != macfb_consaddr &&
130 	    (addr >= 0xf9000000 && addr <= 0xfeffffff)) {
131 		/*
132 		 * This is in the NuBus standard slot space range, so we
133 		 * may well have to look at 0xFssxxxxx, too.  Mask off the
134 		 * slot number and duplicate it in bits 20-23, per IM:V
135 		 * pp 459, 463, and IM:VI ch 30 p 17.
136 		 * Note:  this is an ugly hack and I wish I knew what
137 		 * to do about it.  -- sr
138 		 */
139 		addr = (paddr_t)(((u_long)addr & 0xff0fffff) |
140 		    (((u_long)addr & 0x0f000000) >> 4));
141 	}
142 	return ((mac68k_machine.serial_console & 0x03) == 0
143 	    && (addr == macfb_consaddr));
144 }
145 
146 void
147 macfb_clear(dc)
148 	struct macfb_devconfig *dc;
149 {
150 	int i, rows;
151 
152 	/* clear the display */
153 	rows = dc->dc_ht;
154 	for (i = 0; rows-- > 0; i += dc->dc_rowbytes)
155 		memset((u_char *)dc->dc_vaddr + dc->dc_offset + i,
156 		    0, dc->dc_rowbytes);
157 }
158 
159 void
160 macfb_init(dc)
161 	struct macfb_devconfig *dc;
162 {
163 	struct raster *rap;
164 	struct rcons *rcp;
165 
166 	macfb_clear(dc);
167 
168 #ifdef WSDISPLAY_COMPAT_ITEFONT
169 	init_itefont();
170 #endif /* WSDISPLAY_COMPAT_ITEFONT */
171 
172 	rap = &dc->dc_raster;
173 	rap->width = dc->dc_wid;
174 	rap->height = dc->dc_ht;
175 	rap->depth = dc->dc_depth;
176 	rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t);
177 	rap->pixels = (u_int32_t *)(dc->dc_vaddr + dc->dc_offset);
178 
179 	/* initialize the raster console blitter */
180 	rcp = &dc->dc_rcons;
181 	rcp->rc_sp = rap;
182 	rcp->rc_crow = rcp->rc_ccol = -1;
183 	rcp->rc_crowp = &rcp->rc_crow;
184 	rcp->rc_ccolp = &rcp->rc_ccol;
185 	rcons_init(rcp, 128, 192);
186 
187 	macfb_stdscreen.nrows = dc->dc_rcons.rc_maxrow;
188 	macfb_stdscreen.ncols = dc->dc_rcons.rc_maxcol;
189 }
190 
191 int
192 macfb_match(parent, match, aux)
193 	struct device *parent;
194 	struct cfdata *match;
195 	void *aux;
196 {
197 	return (1);
198 }
199 
200 void
201 macfb_attach(parent, self, aux)
202 	struct device *parent;
203 	struct device *self;
204 	void *aux;
205 {
206 	struct grfbus_attach_args *ga = aux;
207 	struct grfmode *gm = ga->ga_grfmode;
208 	struct macfb_softc *sc;
209 	struct wsemuldisplaydev_attach_args waa;
210 	int isconsole;
211 
212 	sc = (struct macfb_softc *)self;
213 
214 	printf("\n");
215 
216 	isconsole = macfb_is_console(ga->ga_phys + ga->ga_grfmode->fboff);
217 
218 	if (isconsole) {
219 		sc->sc_dc = &macfb_console_dc;
220 		sc->nscreens = 1;
221 	} else {
222 		sc->sc_dc = malloc(sizeof(struct macfb_devconfig), M_DEVBUF, M_WAITOK);
223 		sc->sc_dc->dc_vaddr = (vaddr_t)gm->fbbase;
224 		sc->sc_dc->dc_paddr = ga->ga_phys;
225 		sc->sc_dc->dc_size = gm->fbsize;
226 
227 		sc->sc_dc->dc_wid = gm->width;
228 		sc->sc_dc->dc_ht = gm->height;
229 		sc->sc_dc->dc_depth = gm->psize;
230 		sc->sc_dc->dc_rowbytes = gm->rowbytes;
231 
232 		sc->sc_dc->dc_offset = gm->fboff;
233 
234 		macfb_clear(sc->sc_dc);
235 
236 		sc->nscreens = 1;
237 	}
238 
239 	/* initialize the raster */
240 	waa.console = isconsole;
241 	waa.scrdata = &macfb_screenlist;
242 	waa.accessops = &macfb_accessops;
243 	waa.accesscookie = sc;
244 
245 	config_found(self, &waa, wsemuldisplaydevprint);
246 
247 #if NGRF > 0
248 	grf_attach(sc, self->dv_unit);
249 #endif
250 }
251 
252 
253 int
254 macfb_ioctl(v, cmd, data, flag, p)
255 	void *v;
256 	u_long cmd;
257 	caddr_t data;
258 	int flag;
259 	struct proc *p;
260 {
261 	struct macfb_softc *sc = v;
262 	struct macfb_devconfig *dc = sc->sc_dc;
263 	struct wsdisplay_fbinfo *wdf;
264 
265 	switch (cmd) {
266 	case WSDISPLAYIO_GTYPE:
267 		*(int *)data = dc->dc_type;
268 		return 0;
269 
270 	case WSDISPLAYIO_GINFO:
271 		wdf = (struct wsdisplay_fbinfo *)data;
272 		wdf->height = dc->dc_raster.height;
273 		wdf->width = dc->dc_raster.width;
274 		wdf->depth = dc->dc_raster.depth;
275 		wdf->cmsize = 256;
276 		return 0;
277 
278 	case WSDISPLAYIO_GCURMAX:
279 	case WSDISPLAYIO_GCURPOS:
280 	case WSDISPLAYIO_GCURSOR:
281 	case WSDISPLAYIO_GETCMAP:
282 	case WSDISPLAYIO_GVIDEO:
283 	case WSDISPLAYIO_PUTCMAP:
284 	case WSDISPLAYIO_SCURPOS:
285 	case WSDISPLAYIO_SCURSOR:
286 	case WSDISPLAYIO_SVIDEO:
287 		/* NONE of these operations are supported. */
288 		return EPASSTHROUGH;
289 	}
290 
291 	return EPASSTHROUGH;
292 }
293 
294 static paddr_t
295 macfb_mmap(v, offset, prot)
296 	void *v;
297 	off_t offset;
298 	int prot;
299 {
300 	struct macfb_softc *sc = v;
301 	struct macfb_devconfig *dc = sc->sc_dc;
302 	paddr_t addr;
303 
304 	if (offset >= 0 &&
305 	    offset < m68k_round_page(dc->dc_rowbytes * dc->dc_ht))
306 		addr = m68k_btop(dc->dc_paddr + dc->dc_offset + offset);
307 	else
308 		addr = (-1);	/* XXX bogus */
309 
310 	return addr;
311 }
312 
313 int
314 macfb_alloc_screen(v, type, cookiep, curxp, curyp, defattrp)
315 	void *v;
316 	const struct wsscreen_descr *type;
317 	void **cookiep;
318 	int *curxp, *curyp;
319 	long *defattrp;
320 {
321 	struct macfb_softc *sc = v;
322 	long defattr;
323 
324 	if (sc->nscreens > 0)
325 		return (ENOMEM);
326 
327 	*cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
328 	*curxp = 0;
329 	*curyp = 0;
330 	rcons_allocattr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr);
331 	*defattrp = defattr;
332 	sc->nscreens++;
333 	return (0);
334 }
335 
336 void
337 macfb_free_screen(v, cookie)
338 	void *v;
339 	void *cookie;
340 {
341 	struct macfb_softc *sc = v;
342 
343 	if (sc->sc_dc == &macfb_console_dc)
344 		panic("cfb_free_screen: console");
345 
346 	sc->nscreens--;
347 }
348 
349 int
350 macfb_show_screen(v, cookie, waitok, cb, cbarg)
351 	void *v;
352 	void *cookie;
353 	int waitok;
354 	void (*cb) __P((void *, int, int));
355 	void *cbarg;
356 {
357 	return 0;
358 }
359 
360 int
361 macfb_cnattach(addr)
362 	paddr_t addr;
363 {
364 	struct macfb_devconfig *dc = &macfb_console_dc;
365 	long defattr;
366 
367 	dc->dc_vaddr = m68k_trunc_page(videoaddr);
368 	dc->dc_paddr = m68k_trunc_page(mac68k_vidphys);
369 
370 	dc->dc_wid = videosize & 0xffff;
371 	dc->dc_ht = (videosize >> 16) & 0xffff;
372 	dc->dc_depth = videobitdepth;
373 	dc->dc_rowbytes = videorowbytes;
374 
375 	dc->dc_size = (mac68k_vidlen > 0) ?
376 	    mac68k_vidlen : dc->dc_ht * dc->dc_rowbytes;
377 	dc->dc_offset = m68k_page_offset(mac68k_vidphys);
378 
379 	/* set up the display */
380 	macfb_init(&macfb_console_dc);
381 
382 	rcons_allocattr(&dc->dc_rcons, 0, 0, 0, &defattr);
383 
384 	wsdisplay_cnattach(&macfb_stdscreen, &dc->dc_rcons,
385 			0, 0, defattr);
386 
387 	macfb_consaddr = addr;
388 	dc->isconsole = 1;
389 	return (0);
390 }
391 
392 #ifdef WSDISPLAY_COMPAT_ITEFONT
393 #include <mac68k/dev/6x10.h>
394 
395 void
396 init_itefont()
397 {
398 	static int itefont_initted = 0;
399 	int i, j;
400 
401 	extern struct raster_font gallant19;		/* XXX */
402 
403 	if (itefont_initted)
404 		return;
405 	itefont_initted = 1;
406 
407 	/* XXX but we cannot use malloc here... */
408 	gallant19.width = 6;
409 	gallant19.height = 10;
410 	gallant19.ascent = 0;
411 
412 	for (i = 32; i < 128; i++) {
413 		u_int *p;
414 
415 		if (gallant19.chars[i].r == NULL)
416 			continue;
417 
418 		gallant19.chars[i].r->width = 6;
419 		gallant19.chars[i].r->height = 10;
420 		p = gallant19.chars[i].r->pixels;
421 
422 		for (j = 0; j < 10; j++)
423 			*p++ = Font6x10[i * 10 + j] << 26;
424 	}
425 }
426 #endif /* WSDISPLAY_COMPAT_ITEFONT */
427