macfb.c revision 1.12
1/* $NetBSD: macfb.c,v 1.12 2005/12/11 12:18:02 christos 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 <sys/cdefs.h>
33__KERNEL_RCSID(0, "$NetBSD: macfb.c,v 1.12 2005/12/11 12:18:02 christos Exp $");
34
35#include "opt_wsdisplay_compat.h"
36#include "grf.h"
37
38#include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/kernel.h>
43#include <sys/device.h>
44#include <sys/malloc.h>
45
46#include <machine/cpu.h>
47#include <machine/bus.h>
48
49#include <machine/grfioctl.h>
50#include <mac68k/nubus/nubus.h>
51#include <mac68k/dev/grfvar.h>
52#include <mac68k/dev/macfbvar.h>
53#include <dev/wscons/wsconsio.h>
54
55#include <dev/rcons/raster.h>
56#include <dev/wscons/wscons_raster.h>
57#include <dev/wscons/wsdisplayvar.h>
58
59int macfb_match(struct device *, struct cfdata *, void *);
60void macfb_attach(struct device *, struct device *, void *);
61
62CFATTACH_DECL(macfb, sizeof(struct macfb_softc),
63    macfb_match, macfb_attach, NULL, NULL);
64
65const struct wsdisplay_emulops macfb_emulops = {
66	rcons_cursor,
67	rcons_mapchar,
68	rcons_putchar,
69	rcons_copycols,
70	rcons_erasecols,
71	rcons_copyrows,
72	rcons_eraserows,
73	rcons_allocattr
74};
75
76struct wsscreen_descr macfb_stdscreen = {
77	"std",
78	0, 0, /* will be filled in -- XXX shouldn't, it's global */
79	&macfb_emulops,
80	0, 0,
81	WSSCREEN_REVERSE
82};
83
84const struct wsscreen_descr *_macfb_scrlist[] = {
85	&macfb_stdscreen,
86};
87
88const struct wsscreen_list macfb_screenlist = {
89	sizeof(_macfb_scrlist) / sizeof(struct wsscreen_descr *),
90	_macfb_scrlist
91};
92
93static int	macfb_ioctl(void *, u_long, caddr_t, int, struct lwp *);
94static paddr_t	macfb_mmap(void *, off_t, int);
95static int	macfb_alloc_screen(void *, const struct wsscreen_descr *,
96		    void **, int *, int *, long *);
97static void	macfb_free_screen(void *, void *);
98static int	macfb_show_screen(void *, void *, int,
99		    void (*)(void *, int, int), void *);
100
101const struct wsdisplay_accessops macfb_accessops = {
102	macfb_ioctl,
103	macfb_mmap,
104	macfb_alloc_screen,
105	macfb_free_screen,
106	macfb_show_screen,
107	0 /* load_font */
108};
109
110void macfb_init(struct macfb_devconfig *);
111
112paddr_t macfb_consaddr;
113static int macfb_is_console(paddr_t);
114#ifdef WSDISPLAY_COMPAT_ITEFONT
115static void	init_itefont(void);
116#endif /* WSDISPLAY_COMPAT_ITEFONT */
117
118static struct macfb_devconfig macfb_console_dc;
119
120/* From Booter via locore */
121extern long		videoaddr;
122extern long		videorowbytes;
123extern long		videobitdepth;
124extern u_long		videosize;
125extern u_int32_t	mac68k_vidlog;
126extern u_int32_t	mac68k_vidphys;
127extern u_int32_t	mac68k_vidlen;
128
129static int
130macfb_is_console(paddr_t addr)
131{
132	if (addr != macfb_consaddr &&
133	    (addr >= 0xf9000000 && addr <= 0xfeffffff)) {
134		/*
135		 * This is in the NuBus standard slot space range, so we
136		 * may well have to look at 0xFssxxxxx, too.  Mask off the
137		 * slot number and duplicate it in bits 20-23, per IM:V
138		 * pp 459, 463, and IM:VI ch 30 p 17.
139		 * Note:  this is an ugly hack and I wish I knew what
140		 * to do about it.  -- sr
141		 */
142		addr = (paddr_t)(((u_long)addr & 0xff0fffff) |
143		    (((u_long)addr & 0x0f000000) >> 4));
144	}
145	return ((mac68k_machine.serial_console & 0x03) == 0
146	    && (addr == macfb_consaddr));
147}
148
149void
150macfb_clear(struct macfb_devconfig *dc)
151{
152	int i, rows;
153
154	/* clear the display */
155	rows = dc->dc_ht;
156	for (i = 0; rows-- > 0; i += dc->dc_rowbytes)
157		memset((u_char *)dc->dc_vaddr + dc->dc_offset + i,
158		    0, dc->dc_rowbytes);
159}
160
161void
162macfb_init(struct macfb_devconfig *dc)
163{
164	struct raster *rap;
165	struct rcons *rcp;
166
167	macfb_clear(dc);
168
169#ifdef WSDISPLAY_COMPAT_ITEFONT
170	init_itefont();
171#endif /* WSDISPLAY_COMPAT_ITEFONT */
172
173	rap = &dc->dc_raster;
174	rap->width = dc->dc_wid;
175	rap->height = dc->dc_ht;
176	rap->depth = dc->dc_depth;
177	rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t);
178	rap->pixels = (u_int32_t *)(dc->dc_vaddr + dc->dc_offset);
179
180	/* initialize the raster console blitter */
181	rcp = &dc->dc_rcons;
182	rcp->rc_sp = rap;
183	rcp->rc_crow = rcp->rc_ccol = -1;
184	rcp->rc_crowp = &rcp->rc_crow;
185	rcp->rc_ccolp = &rcp->rc_ccol;
186	rcons_init(rcp, 128, 192);
187
188	macfb_stdscreen.nrows = dc->dc_rcons.rc_maxrow;
189	macfb_stdscreen.ncols = dc->dc_rcons.rc_maxcol;
190}
191
192int
193macfb_match(struct device *parent, struct cfdata *match, void *aux)
194{
195	return (1);
196}
197
198void
199macfb_attach(struct device *parent, struct device *self, void *aux)
200{
201	struct grfbus_attach_args *ga = aux;
202	struct grfmode *gm = ga->ga_grfmode;
203	struct macfb_softc *sc;
204	struct wsemuldisplaydev_attach_args waa;
205	int isconsole;
206
207	sc = (struct macfb_softc *)self;
208
209	printf("\n");
210
211	isconsole = macfb_is_console(ga->ga_phys + ga->ga_grfmode->fboff);
212
213	if (isconsole) {
214		sc->sc_dc = &macfb_console_dc;
215		sc->nscreens = 1;
216	} else {
217		sc->sc_dc = malloc(sizeof(struct macfb_devconfig), M_DEVBUF, M_WAITOK);
218		sc->sc_dc->dc_vaddr = (vaddr_t)gm->fbbase;
219		sc->sc_dc->dc_paddr = ga->ga_phys;
220		sc->sc_dc->dc_size = gm->fbsize;
221
222		sc->sc_dc->dc_wid = gm->width;
223		sc->sc_dc->dc_ht = gm->height;
224		sc->sc_dc->dc_depth = gm->psize;
225		sc->sc_dc->dc_rowbytes = gm->rowbytes;
226
227		sc->sc_dc->dc_offset = gm->fboff;
228
229		macfb_clear(sc->sc_dc);
230
231		sc->nscreens = 1;
232	}
233
234	/* initialize the raster */
235	waa.console = isconsole;
236	waa.scrdata = &macfb_screenlist;
237	waa.accessops = &macfb_accessops;
238	waa.accesscookie = sc;
239
240	config_found(self, &waa, wsemuldisplaydevprint);
241
242#if NGRF > 0
243	grf_attach(sc, self->dv_unit);
244#endif
245}
246
247
248int
249macfb_ioctl(void *v, u_long cmd, caddr_t data, int flag, struct lwp *l)
250{
251	struct macfb_softc *sc = v;
252	struct macfb_devconfig *dc = sc->sc_dc;
253	struct wsdisplay_fbinfo *wdf;
254
255	switch (cmd) {
256	case WSDISPLAYIO_GTYPE:
257		*(int *)data = dc->dc_type;
258		return 0;
259
260	case WSDISPLAYIO_GINFO:
261		wdf = (struct wsdisplay_fbinfo *)data;
262		wdf->height = dc->dc_raster.height;
263		wdf->width = dc->dc_raster.width;
264		wdf->depth = dc->dc_raster.depth;
265		wdf->cmsize = 256;
266		return 0;
267
268	case WSDISPLAYIO_GCURMAX:
269	case WSDISPLAYIO_GCURPOS:
270	case WSDISPLAYIO_GCURSOR:
271	case WSDISPLAYIO_GETCMAP:
272	case WSDISPLAYIO_GVIDEO:
273	case WSDISPLAYIO_PUTCMAP:
274	case WSDISPLAYIO_SCURPOS:
275	case WSDISPLAYIO_SCURSOR:
276	case WSDISPLAYIO_SVIDEO:
277		/* NONE of these operations are supported. */
278		return EPASSTHROUGH;
279	}
280
281	return EPASSTHROUGH;
282}
283
284static paddr_t
285macfb_mmap(void *v, off_t offset, int prot)
286{
287	struct macfb_softc *sc = v;
288	struct macfb_devconfig *dc = sc->sc_dc;
289	paddr_t addr;
290
291	if (offset >= 0 &&
292	    offset < m68k_round_page(dc->dc_rowbytes * dc->dc_ht))
293		addr = m68k_btop(dc->dc_paddr + dc->dc_offset + offset);
294	else
295		addr = (-1);	/* XXX bogus */
296
297	return addr;
298}
299
300int
301macfb_alloc_screen(void *v, const struct wsscreen_descr *type, void **cookiep,
302    int *curxp, int *curyp, long *defattrp)
303{
304	struct macfb_softc *sc = v;
305	long defattr;
306
307	if (sc->nscreens > 0)
308		return (ENOMEM);
309
310	*cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
311	*curxp = 0;
312	*curyp = 0;
313	rcons_allocattr(&sc->sc_dc->dc_rcons, 0, 0, 0, &defattr);
314	*defattrp = defattr;
315	sc->nscreens++;
316	return (0);
317}
318
319void
320macfb_free_screen(void *v, void *cookie)
321{
322	struct macfb_softc *sc = v;
323
324	if (sc->sc_dc == &macfb_console_dc)
325		panic("cfb_free_screen: console");
326
327	sc->nscreens--;
328}
329
330int
331macfb_show_screen(void *v, void *cookie, int waitok,
332    void (*cb)(void *, int, int), void *cbarg)
333{
334	return 0;
335}
336
337int
338macfb_cnattach(paddr_t addr)
339{
340	struct macfb_devconfig *dc = &macfb_console_dc;
341	long defattr;
342
343	dc->dc_vaddr = m68k_trunc_page(videoaddr);
344	dc->dc_paddr = m68k_trunc_page(mac68k_vidphys);
345
346	dc->dc_wid = videosize & 0xffff;
347	dc->dc_ht = (videosize >> 16) & 0xffff;
348	dc->dc_depth = videobitdepth;
349	dc->dc_rowbytes = videorowbytes;
350
351	dc->dc_size = (mac68k_vidlen > 0) ?
352	    mac68k_vidlen : dc->dc_ht * dc->dc_rowbytes;
353	dc->dc_offset = m68k_page_offset(mac68k_vidphys);
354
355	/* set up the display */
356	macfb_init(&macfb_console_dc);
357
358	rcons_allocattr(&dc->dc_rcons, 0, 0, 0, &defattr);
359
360	wsdisplay_cnattach(&macfb_stdscreen, &dc->dc_rcons,
361			0, 0, defattr);
362
363	macfb_consaddr = addr;
364	dc->isconsole = 1;
365	return (0);
366}
367
368#ifdef WSDISPLAY_COMPAT_ITEFONT
369#include <mac68k/dev/6x10.h>
370
371void
372init_itefont(void)
373{
374	static int itefont_initted;
375	int i, j;
376
377	extern struct raster_font gallant19;		/* XXX */
378
379	if (itefont_initted)
380		return;
381	itefont_initted = 1;
382
383	/* XXX but we cannot use malloc here... */
384	gallant19.width = 6;
385	gallant19.height = 10;
386	gallant19.ascent = 0;
387
388	for (i = 32; i < 128; i++) {
389		u_int *p;
390
391		if (gallant19.chars[i].r == NULL)
392			continue;
393
394		gallant19.chars[i].r->width = 6;
395		gallant19.chars[i].r->height = 10;
396		p = gallant19.chars[i].r->pixels;
397
398		for (j = 0; j < 10; j++)
399			*p++ = Font6x10[i * 10 + j] << 26;
400	}
401}
402#endif /* WSDISPLAY_COMPAT_ITEFONT */
403