xref: /openbsd/sys/arch/sparc64/dev/vgafb.c (revision 78b63d65)
1 /*	$OpenBSD: vgafb.c,v 1.2 2001/12/14 19:17:02 jason Exp $	*/
2 
3 /*
4  * Copyright (c) 2001 Jason L. Wright (jason@thought.net)
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 Jason L. Wright
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
23  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
25  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include <sys/param.h>
35 #include <sys/systm.h>
36 #include <sys/kernel.h>
37 #include <sys/errno.h>
38 #include <sys/device.h>
39 #include <sys/ioctl.h>
40 #include <sys/malloc.h>
41 
42 #include <machine/bus.h>
43 #include <machine/intr.h>
44 #include <machine/autoconf.h>
45 #include <machine/openfirm.h>
46 
47 #include <dev/pci/pcivar.h>
48 #include <dev/wscons/wsconsio.h>
49 #include <dev/wscons/wsdisplayvar.h>
50 #include <dev/wscons/wscons_raster.h>
51 #include <dev/rcons/raster.h>
52 
53 struct vgafb_softc {
54 	struct device sc_dev;
55 	struct sbusdev sc_sd;
56 	int sc_nscreens;
57 	int sc_width, sc_height, sc_depth, sc_linebytes, sc_node;
58 	bus_space_tag_t sc_bt;
59 	bus_space_handle_t sc_bh;
60 	struct rcons sc_rcons;
61 	struct raster sc_raster;
62 };
63 
64 struct wsdisplay_emulops vgafb_emulops = {
65 	rcons_cursor,
66 	rcons_mapchar,
67 	rcons_putchar,
68 	rcons_copycols,
69 	rcons_erasecols,
70 	rcons_copyrows,
71 	rcons_eraserows,
72 	rcons_alloc_attr
73 };
74 
75 struct wsscreen_descr vgafb_stdscreen = {
76 	"std",
77 	0, 0,	/* will be filled in -- XXX shouldn't, it's global. */
78 	0,
79 	0, 0,
80 	WSSCREEN_REVERSE
81 };
82 
83 const struct wsscreen_descr *vgafb_scrlist[] = {
84 	&vgafb_stdscreen,
85 	/* XXX other formats? */
86 };
87 
88 struct wsscreen_list vgafb_screenlist = {
89 	sizeof(vgafb_scrlist) / sizeof(struct wsscreen_descr *), vgafb_scrlist
90 };
91 
92 int vgafb_ioctl __P((void *, u_long, caddr_t, int, struct proc *));
93 int vgafb_alloc_screen __P((void *, const struct wsscreen_descr *, void **,
94     int *, int *, long *));
95 void vgafb_free_screen __P((void *, void *));
96 int vgafb_show_screen __P((void *, void *, int,
97     void (*cb) __P((void *, int, int)), void *));
98 paddr_t vgafb_mmap __P((void *, off_t, int));
99 int vgafb_is_console __P((int));
100 
101 static int a2int __P((char *, int));
102 
103 struct wsdisplay_accessops vgafb_accessops = {
104 	vgafb_ioctl,
105 	vgafb_mmap,
106 	vgafb_alloc_screen,
107 	vgafb_free_screen,
108 	vgafb_show_screen,
109 	0 /* load_font */
110 };
111 
112 int	vgafbmatch	__P((struct device *, void *, void *));
113 void	vgafbattach	__P((struct device *, struct device *, void *));
114 
115 struct cfattach vgafb_ca = {
116 	sizeof (struct vgafb_softc), vgafbmatch, vgafbattach
117 };
118 
119 struct cfdriver vgafb_cd = {
120 	NULL, "vgafb", DV_DULL
121 };
122 
123 int
124 vgafbmatch(parent, vcf, aux)
125 	struct device *parent;
126 	void *vcf, *aux;
127 {
128 	struct pci_attach_args *pa = aux;
129 
130 	if (PCI_CLASS(pa->pa_class) == PCI_CLASS_PREHISTORIC &&
131 	    PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_PREHISTORIC_VGA)
132 		return (1);
133 
134 	if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY &&
135 	    PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_VGA)
136 		return (1);
137 
138 	if (PCI_CLASS(pa->pa_class) == PCI_CLASS_DISPLAY &&
139 	    PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_DISPLAY_MISC)
140 		return (1);
141 
142 	return (0);
143 }
144 
145 void
146 vgafbattach(parent, self, aux)
147 	struct device *parent, *self;
148 	void *aux;
149 {
150 	struct vgafb_softc *sc = (struct vgafb_softc *)self;
151 	struct pci_attach_args *pa = aux;
152 	struct wsemuldisplaydev_attach_args waa;
153 	bus_size_t memsize;
154 	long defattr;
155 	int console;
156 	bus_addr_t membase;
157 
158 	sc->sc_node = PCITAG_NODE(pa->pa_tag);
159 
160 	sc->sc_depth = getpropint(sc->sc_node, "depth", -1);
161 	if (sc->sc_depth == -1)
162 		sc->sc_depth = 8;
163 
164 	sc->sc_linebytes = getpropint(sc->sc_node, "linebytes", -1);
165 	if (sc->sc_linebytes == -1)
166 		sc->sc_linebytes = 1152;
167 
168 	sc->sc_height = getpropint(sc->sc_node, "height", -1);
169 	if (sc->sc_height == -1)
170 		sc->sc_height = 900;
171 
172 	sc->sc_width = getpropint(sc->sc_node, "width", -1);
173 	if (sc->sc_width == -1)
174 		sc->sc_width = 1152;
175 
176 	console = vgafb_is_console(sc->sc_node);
177 
178 	if (pci_mem_find(pa->pa_pc, pa->pa_tag, 0x10,
179 	    &membase, &memsize, NULL)) {
180 		printf(": can't find mem space\n");
181 		goto fail;
182 	}
183 	if (bus_space_map2(pa->pa_memt, SBUS_BUS_SPACE,
184 	    membase, memsize, 0, NULL, &sc->sc_bh)) {
185 		printf(": can't map mem space\n");
186 		goto fail;
187 	}
188 	sc->sc_bt = pa->pa_memt;
189 
190 	sc->sc_rcons.rc_sp = &sc->sc_raster;
191 	sc->sc_raster.width = sc->sc_width;
192 	sc->sc_raster.height = sc->sc_height;
193 	sc->sc_raster.depth = sc->sc_depth;
194 	sc->sc_raster.linelongs = sc->sc_linebytes / 4;
195 	sc->sc_raster.pixels = (void *)sc->sc_bh;
196 
197 	if (console == 0 ||
198 	    romgetcursoraddr(&sc->sc_rcons.rc_crowp, &sc->sc_rcons.rc_ccolp)) {
199 		sc->sc_rcons.rc_crow = sc->sc_rcons.rc_ccol = -1;
200 		sc->sc_rcons.rc_crowp = &sc->sc_rcons.rc_crow;
201 		sc->sc_rcons.rc_ccolp = &sc->sc_rcons.rc_ccol;
202 	}
203 
204 	sc->sc_rcons.rc_maxcol =
205 	    a2int(getpropstring(optionsnode, "screen-#columns"), 80);
206 	sc->sc_rcons.rc_maxrow =
207 	    a2int(getpropstring(optionsnode, "screen-#rows"), 34);
208 
209 	rcons_init(&sc->sc_rcons,
210 	    sc->sc_rcons.rc_maxrow, sc->sc_rcons.rc_maxcol);
211 
212 	vgafb_stdscreen.nrows = sc->sc_rcons.rc_maxrow;
213 	vgafb_stdscreen.ncols = sc->sc_rcons.rc_maxcol;
214 	vgafb_stdscreen.textops = &vgafb_emulops;
215 	rcons_alloc_attr(&sc->sc_rcons, 0, 0, 0, &defattr);
216 
217 	printf("\n");
218 
219 	if (console)
220 		wsdisplay_cnattach(&vgafb_stdscreen, &sc->sc_rcons,
221 		    *sc->sc_rcons.rc_ccolp, *sc->sc_rcons.rc_crowp, defattr);
222 
223 	waa.console = console;
224 	waa.scrdata = &vgafb_screenlist;
225 	waa.accessops = &vgafb_accessops;
226 	waa.accesscookie = sc;
227 	config_found(self, &waa, wsemuldisplaydevprint);
228 
229 	return;
230 fail:
231 }
232 
233 int
234 vgafb_ioctl(v, cmd, data, flags, p)
235 	void *v;
236 	u_long cmd;
237 	caddr_t data;
238 	int flags;
239 	struct proc *p;
240 {
241 	struct vgafb_softc *sc = v;
242 	struct wsdisplay_fbinfo *wdf;
243 
244 	switch (cmd) {
245 	case WSDISPLAYIO_GTYPE:
246 		*(u_int *)data = WSDISPLAY_TYPE_UNKNOWN;
247 		break;
248 	case WSDISPLAYIO_GINFO:
249 		wdf = (void *)data;
250 		wdf->height = sc->sc_height;
251 		wdf->width  = sc->sc_width;
252 		wdf->depth  = sc->sc_depth;
253 		wdf->cmsize = 256;
254 		break;
255 	case WSDISPLAYIO_LINEBYTES:
256 		*(u_int *)data = sc->sc_linebytes;
257 		break;
258 
259 #if 0
260 	case WSDISPLAYIO_GETCMAP:
261 		return vgafb_getcmap(vc, (struct wsdisplay_cmap *)data);
262 	case WSDISPLAYIO_PUTCMAP:
263 		return vgafb_putcmap(vc, (struct wsdisplay_cmap *)data);
264 #endif
265 
266 	case WSDISPLAYIO_SVIDEO:
267 	case WSDISPLAYIO_GVIDEO:
268 	case WSDISPLAYIO_GCURPOS:
269 	case WSDISPLAYIO_SCURPOS:
270 	case WSDISPLAYIO_GCURMAX:
271 	case WSDISPLAYIO_GCURSOR:
272 	case WSDISPLAYIO_SCURSOR:
273 	default:
274 		return -1; /* not supported yet */
275         }
276 
277 	return (0);
278 }
279 
280 int
281 vgafb_alloc_screen(v, type, cookiep, curxp, curyp, attrp)
282 	void *v;
283 	const struct wsscreen_descr *type;
284 	void **cookiep;
285 	int *curxp, *curyp;
286 	long *attrp;
287 {
288 	struct vgafb_softc *sc = v;
289 
290 	if (sc->sc_nscreens > 0)
291 		return (ENOMEM);
292 
293 	*cookiep = &sc->sc_rcons;
294 	*curyp = *sc->sc_rcons.rc_crowp;
295 	*curxp = *sc->sc_rcons.rc_ccolp;
296 	rcons_alloc_attr(&sc->sc_rcons, 0, 0, 0, attrp);
297 	sc->sc_nscreens++;
298 	return (0);
299 }
300 
301 void
302 vgafb_free_screen(v, cookie)
303 	void *v;
304 	void *cookie;
305 {
306 	struct vgafb_softc *sc = v;
307 
308 	sc->sc_nscreens--;
309 }
310 
311 int
312 vgafb_show_screen(v, cookie, waitok, cb, cbarg)
313 	void *v;
314 	void *cookie;
315 	int waitok;
316 	void (*cb) __P((void *, int, int));
317 	void *cbarg;
318 {
319 	return (0);
320 }
321 
322 paddr_t
323 vgafb_mmap(v, offset, prot)
324 	void *v;
325 	off_t offset;
326 	int prot;
327 {
328 #if 0
329 	struct vgafb_softc *sc = v;
330 #endif
331 
332 	if (offset & PGOFSET)
333 		return (-1);
334 	return (-1);
335 }
336 
337 static int
338 a2int(char *cp, int deflt)
339 {
340 	int i = 0;
341 
342 	if (*cp == '\0')
343 		return (deflt);
344 	while (*cp != '\0')
345 		i = i * 10 + *cp++ - '0';
346 	return (i);
347 }
348 
349 int
350 vgafb_is_console(node)
351 	int node;
352 {
353 	extern int fbnode;
354 
355 	return (fbnode == node);
356 }
357