nextdisplay.c revision 1.19
1/* $NetBSD: nextdisplay.c,v 1.19 2006/04/12 19:38:23 jmmv Exp $ */
2
3/*
4 * Copyright (c) 1998 Matt DeBergalis
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *      This product includes software developed by Matt DeBergalis
18 * 4. The name of the author may not be used to endorse or promote products
19 *    derived from this software without specific prior written permission
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#include <sys/cdefs.h>
34__KERNEL_RCSID(0, "$NetBSD: nextdisplay.c,v 1.19 2006/04/12 19:38:23 jmmv Exp $");
35
36#include <sys/cdefs.h>			/* RCS ID & Copyright macro defns */
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/kernel.h>
41#include <sys/device.h>
42#include <sys/malloc.h>
43
44#include <machine/bus.h>
45#include <machine/cpu.h>
46
47#include <next68k/next68k/nextrom.h>
48#include <next68k/next68k/isr.h>
49
50#include <next68k/dev/intiovar.h>
51#include <next68k/dev/nextdisplayvar.h>
52#include <dev/wscons/wsconsio.h>
53
54#include <dev/rcons/raster.h>
55#include <dev/wscons/wscons_raster.h>
56#include <dev/wscons/wsdisplayvar.h>
57
58extern int turbo;
59
60int nextdisplay_match(struct device *, struct cfdata *, void *);
61void nextdisplay_attach(struct device *, struct device *, void *);
62
63CFATTACH_DECL(nextdisplay, sizeof(struct nextdisplay_softc),
64    nextdisplay_match, nextdisplay_attach, NULL, NULL);
65
66const struct wsdisplay_emulops nextdisplay_mono_emulops = {
67	rcons_cursor,
68	rcons_mapchar,
69	rcons_putchar,
70	rcons_copycols,
71	rcons_erasecols,
72	rcons_copyrows,
73	rcons_eraserows,
74	rcons_allocattr
75};
76
77struct wsscreen_descr nextdisplay_mono = {
78	"mono",
79	0, 0, /* will be filled in -- XXX shouldn't, it's global */
80	&nextdisplay_mono_emulops,
81	0, 0
82};
83
84struct wsscreen_descr nextdisplay_color = {
85        "color",
86        0, 0, /* again, filled in */
87        &nextdisplay_mono_emulops,
88        0, 0
89};
90
91const struct wsscreen_descr *_nextdisplay_scrlist_mono[] = {
92	&nextdisplay_mono,
93};
94
95const struct wsscreen_descr *_nextdisplay_scrlist_color[] = {
96        &nextdisplay_color,
97};
98
99const struct wsscreen_list nextdisplay_screenlist_mono = {
100	sizeof(_nextdisplay_scrlist_mono) / sizeof(struct wsscreen_descr *),
101	_nextdisplay_scrlist_mono
102};
103
104const struct wsscreen_list nextdisplay_screenlist_color = {
105	sizeof(_nextdisplay_scrlist_color) / sizeof(struct wsscreen_descr *),
106	_nextdisplay_scrlist_color
107};
108
109static int	nextdisplay_ioctl(void *, void *, u_long, caddr_t, int,
110		    struct lwp *);
111static paddr_t	nextdisplay_mmap(void *, void *, off_t, int);
112static int	nextdisplay_alloc_screen(void *, const struct wsscreen_descr *,
113		void **, int *, int *, long *);
114static void	nextdisplay_free_screen(void *, void *);
115static int	nextdisplay_show_screen(void *, void *, int,
116					void (*) (void *, int, int), void *);
117static int	nextdisplay_load_font(void *, void *, struct wsdisplay_font *);
118
119const struct wsdisplay_accessops nextdisplay_accessops = {
120	nextdisplay_ioctl,
121	nextdisplay_mmap,
122	nextdisplay_alloc_screen,
123	nextdisplay_free_screen,
124	nextdisplay_show_screen,
125	nextdisplay_load_font
126};
127
128void nextdisplay_init(struct nextdisplay_config *, int);
129int nextdisplay_intr(void *);
130
131vaddr_t nextdisplay_consaddr;
132static int nextdisplay_is_console(vaddr_t);
133
134static struct nextdisplay_config nextdisplay_console_dc;
135
136static int
137nextdisplay_is_console(vaddr_t addr)
138{
139	return (nextdisplay_console_dc.isconsole
140			&& (addr == nextdisplay_consaddr));
141}
142
143int
144nextdisplay_match(struct device *parent, struct cfdata *match, void *aux)
145{
146	if (rom_machine_type == NeXT_WARP9 ||
147	    rom_machine_type == NeXT_X15 ||
148	    rom_machine_type == NeXT_WARP9C ||
149	    rom_machine_type == NeXT_TURBO_MONO ||
150	    rom_machine_type == NeXT_TURBO_COLOR)
151		return (1);
152	else
153		return (0);
154}
155
156void
157nextdisplay_init(struct nextdisplay_config *dc, int color)
158{
159	struct raster *rap;
160	struct rcons *rcp;
161	int i;
162
163	/* printf("in nextdisplay_init\n"); */
164
165	if (color) {
166		dc->dc_vaddr = colorbase;
167		dc->dc_paddr = COLORBASE;
168		dc->dc_size = NEXT_P_C16_VIDEOSIZE;
169	} else {
170		dc->dc_vaddr = monobase;
171		dc->dc_paddr = MONOBASE;
172		dc->dc_size = NEXT_P_VIDEOSIZE;
173	}
174
175	dc->dc_wid = 1120;
176	dc->dc_ht = 832;
177	dc->dc_depth = color ? 16 : 2;
178	dc->dc_rowbytes = (turbo ? 1120 : 1152) * dc->dc_depth / 8;
179
180	dc->dc_videobase = dc->dc_vaddr;
181
182#if 0
183	printf("intiobase at: %08x\n", intiobase);
184	printf("intiolimit at: %08x\n", intiolimit);
185	printf("videobase at: %08x\n", color ? colorbase : monobase);
186	printf("videolimit at: %08x\n", color ? colorlimit : monolimit);
187
188	printf("virtual fb at: %08x\n", dc->dc_vaddr);
189	printf("physical fb at: %08x\n", dc->dc_paddr);
190	printf("fb size: %08x\n", dc->dc_size);
191
192	printf("dc_wid: %08x\n", dc->dc_wid);
193	printf("dc_ht: %08x\n", dc->dc_ht);
194	printf("dc_depth: %08x\n", dc->dc_depth);
195	printf("dc_rowbytes: %08x\n", dc->dc_rowbytes);
196	printf("dc_videobase: %08x\n", dc->dc_videobase);
197#endif
198
199	/* clear the screen */
200	for (i = 0; i < dc->dc_ht * dc->dc_rowbytes; i += sizeof(u_int32_t))
201		*(u_int32_t *)(dc->dc_videobase + i) =
202			(color ? 0x0 : 0xffffffff);
203
204	rap = &dc->dc_raster;
205	rap->width = dc->dc_wid;
206	rap->height = dc->dc_ht;
207	rap->depth = color ? 16 : 2;
208	rap->linelongs = dc->dc_rowbytes / sizeof(u_int32_t);
209	rap->pixels = (u_int32_t *)dc->dc_videobase;
210
211	/* initialize the raster console blitter */
212	rcp = &dc->dc_rcons;
213	rcp->rc_sp = rap;
214	rcp->rc_crow = rcp->rc_ccol = -1;
215	rcp->rc_crowp = &rcp->rc_crow;
216	rcp->rc_ccolp = &rcp->rc_ccol;
217	rcons_init(rcp, 34, 80);
218
219	if (color) {
220		nextdisplay_color.nrows = dc->dc_rcons.rc_maxrow;
221		nextdisplay_color.ncols = dc->dc_rcons.rc_maxcol;
222	} else {
223		nextdisplay_mono.nrows = dc->dc_rcons.rc_maxrow;
224		nextdisplay_mono.ncols = dc->dc_rcons.rc_maxcol;
225	}
226}
227
228void
229nextdisplay_attach(struct device *parent, struct device *self, void *aux)
230{
231	struct nextdisplay_softc *sc = (void *)self;
232	struct wsemuldisplaydev_attach_args waa;
233	int isconsole;
234	int iscolor;
235	paddr_t addr;
236
237	if (rom_machine_type == NeXT_WARP9C ||
238	    rom_machine_type == NeXT_TURBO_COLOR) {
239		iscolor = 1;
240		addr = colorbase;
241	} else {
242		iscolor = 0;
243		addr = monobase;
244	}
245
246	isconsole = nextdisplay_is_console(addr);
247
248	if (isconsole) {
249		sc->sc_dc = &nextdisplay_console_dc;
250		sc->nscreens = 1;
251	} else {
252		sc->sc_dc = (struct nextdisplay_config *)
253				malloc(sizeof(struct nextdisplay_config), M_DEVBUF, M_WAITOK);
254		nextdisplay_init(sc->sc_dc, iscolor);
255	}
256
257	printf(": %d x %d, %dbpp\n", sc->sc_dc->dc_wid, sc->sc_dc->dc_ht,
258	       sc->sc_dc->dc_depth);
259
260	if (iscolor) {
261#if 0
262		uint8_t x;
263
264		x = *(volatile uint8_t *)IIOV(NEXT_P_C16_CMD_REG);
265		printf("%s: cmd=%02x\n", sc->sc_dev.dv_xname, x);
266#endif
267		*(volatile uint8_t *)IIOV(NEXT_P_C16_CMD_REG) = 0x05;
268		isrlink_autovec(nextdisplay_intr, sc, NEXT_I_IPL(NEXT_I_C16_VIDEO), 1, NULL);
269		INTR_ENABLE(NEXT_I_C16_VIDEO);
270	}
271
272	/* initialize the raster */
273	waa.console = isconsole;
274	waa.scrdata = iscolor ? &nextdisplay_screenlist_color : &nextdisplay_screenlist_mono;
275	waa.accessops = &nextdisplay_accessops;
276	waa.accesscookie = sc;
277#if 0
278	printf("nextdisplay: access cookie is %p\n", sc);
279#endif
280	config_found(self, &waa, wsemuldisplaydevprint);
281}
282
283int
284nextdisplay_intr(void *arg)
285{
286#if 0
287	uint8_t x;
288#endif
289
290	if (!INTR_OCCURRED(NEXT_I_C16_VIDEO))
291		return (0);
292#if 0
293	x = *(volatile uint8_t *)IIOV(NEXT_P_C16_CMD_REG);
294	printf("I%02x", x);
295#endif
296	*(volatile uint8_t *)IIOV(NEXT_P_C16_CMD_REG) = 0x05;
297	return (1);
298}
299
300int
301nextdisplay_ioctl(void *v, void *vs, u_long cmd, caddr_t data, int flag,
302	struct lwp *l)
303{
304	struct nextdisplay_softc *sc = v;
305	struct nextdisplay_config *dc = sc->sc_dc;
306
307	switch (cmd) {
308	case WSDISPLAYIO_GTYPE:
309		*(int *)data = dc->dc_type;
310		return 0;
311
312	case WSDISPLAYIO_SCURSOR:
313		printf("nextdisplay_ioctl: wsdisplayio_scursor\n");
314		return EPASSTHROUGH;
315
316	case WSDISPLAYIO_SCURPOS:
317		printf("nextdisplay_ioctl: wsdisplayio_scurpos\n");
318		return EPASSTHROUGH;
319
320	case WSDISPLAYIO_GINFO:
321	case WSDISPLAYIO_GETCMAP:
322	case WSDISPLAYIO_PUTCMAP:
323	case WSDISPLAYIO_GVIDEO:
324	case WSDISPLAYIO_SVIDEO:
325	case WSDISPLAYIO_GCURPOS:
326	case WSDISPLAYIO_GCURMAX:
327	case WSDISPLAYIO_GCURSOR:
328		printf("nextdisplay_ioctl: listed but unsupported ioctl\n");
329		return EPASSTHROUGH;
330	}
331
332	return EPASSTHROUGH;
333}
334
335static paddr_t
336nextdisplay_mmap(void *v, void *vs, off_t offset, int prot)
337{
338
339	/* XXX */
340	printf("nextdisplay_mmap: failed\n");
341	return -1;
342}
343
344int
345nextdisplay_alloc_screen(void *v, const struct wsscreen_descr *type,
346    void **cookiep, int *curxp, int *curyp, long *defattrp)
347{
348	struct nextdisplay_softc *sc = v;
349	long defattr;
350
351	/* only allow one screen */
352	if (sc->nscreens > 0)
353		return (ENOMEM);
354
355	*cookiep = &sc->sc_dc->dc_rcons; /* one and only for now */
356	*curxp = 0;
357	*curyp = 0;
358	rcons_allocattr(&sc->sc_dc->dc_rcons, 0, 0,
359			(strcmp(type->name, "color") == 0)
360			? 0
361			: WSATTR_REVERSE, &defattr);
362	*defattrp = defattr;
363	sc->nscreens++;
364#if 0
365	printf("nextdisplay: allocating screen\n");
366#endif
367	return (0);
368}
369
370void
371nextdisplay_free_screen(void *v, void *cookie)
372{
373	struct nextdisplay_softc *sc = v;
374
375	if (sc->sc_dc == &nextdisplay_console_dc)
376		panic("nextdisplay_free_screen: console");
377
378	sc->nscreens--;
379}
380
381int
382nextdisplay_show_screen(void *v, void *cookie, int waitok,
383    void (*cb)(void *, int, int), void *cbarg)
384{
385
386	return (0);
387}
388
389static int
390nextdisplay_load_font(void *v, void *cookie, struct wsdisplay_font *font)
391{
392	return (EPASSTHROUGH);
393}
394
395int
396nextdisplay_cnattach(void)
397{
398	struct nextdisplay_config *dc = &nextdisplay_console_dc;
399	long defattr;
400	int iscolor;
401
402	if (rom_machine_type == NeXT_WARP9C ||
403	    rom_machine_type == NeXT_TURBO_COLOR)
404		iscolor = 1;
405	else
406		iscolor = 0;
407
408	/* set up the display */
409	nextdisplay_init(&nextdisplay_console_dc, iscolor);
410	nextdisplay_consaddr = nextdisplay_console_dc.dc_vaddr;
411
412	rcons_allocattr(&dc->dc_rcons, 0, 0,
413			iscolor ? 0 : WSATTR_REVERSE, &defattr);
414
415	wsdisplay_cnattach(iscolor ? &nextdisplay_color : &nextdisplay_mono,
416			   &dc->dc_rcons, 0, 0, defattr);
417
418	dc->isconsole = 1;
419	return (0);
420}
421