1 /*	$OpenBSD: bwtwo.c,v 1.34 2006/12/03 16:38:12 miod Exp $	*/
2 /*	$NetBSD: bwtwo.c,v 1.33 1997/05/24 20:16:02 pk Exp $ */
3 
4 /*
5  * Copyright (c) 2002 Miodrag Vallat.  All rights reserved.
6  * Copyright (c) 1996 Jason R. Thorpe.  All rights reserved.
7  * Copyright (c) 1992, 1993
8  *	The Regents of the University of California.  All rights reserved.
9  *
10  * This software was developed by the Computer Systems Engineering group
11  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
12  * contributed to Berkeley.
13  *
14  * All advertising materials mentioning features or use of this software
15  * must display the following acknowledgement:
16  *	This product includes software developed by the University of
17  *	California, Lawrence Berkeley Laboratory.
18  *
19  * Redistribution and use in source and binary forms, with or without
20  * modification, are permitted provided that the following conditions
21  * are met:
22  * 1. Redistributions of source code must retain the above copyright
23  *    notice, this list of conditions and the following disclaimer.
24  * 2. Redistributions in binary form must reproduce the above copyright
25  *    notice, this list of conditions and the following disclaimer in the
26  *    documentation and/or other materials provided with the distribution.
27  * 3. Neither the name of the University nor the names of its contributors
28  *    may be used to endorse or promote products derived from this software
29  *    without specific prior written permission.
30  *
31  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
32  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
33  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
34  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
35  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
39  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
40  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41  * SUCH DAMAGE.
42  *
43  *	@(#)bwtwo.c	8.1 (Berkeley) 6/11/93
44  */
45 
46 /*
47  * black&white display (bwtwo) driver.
48  *
49  * P4 and overlay plane support by Jason R. Thorpe <thorpej@NetBSD.ORG>.
50  * Overlay plane handling hints and ideas provided by Brad Spencer.
51  */
52 
53 #include <sys/param.h>
54 #include <sys/systm.h>
55 #include <sys/device.h>
56 #include <sys/ioctl.h>
57 #include <sys/malloc.h>
58 #include <sys/mman.h>
59 #include <sys/tty.h>
60 #include <sys/conf.h>
61 
62 #include <uvm/uvm_extern.h>
63 
64 #include <machine/autoconf.h>
65 #include <machine/eeprom.h>
66 #include <machine/ctlreg.h>
67 #include <machine/conf.h>
68 #include <sparc/sparc/asm.h>
69 
70 #include <sparc/dev/btreg.h>
71 #include <sparc/dev/bwtworeg.h>
72 #include <sparc/dev/sbusvar.h>
73 #if defined(SUN4)
74 #include <sparc/dev/pfourreg.h>
75 #endif
76 
77 #include <dev/wscons/wsconsio.h>
78 #include <dev/wscons/wsdisplayvar.h>
79 #include <dev/rasops/rasops.h>
80 #include <machine/fbvar.h>
81 
82 #include <machine/pmap.h>
83 
84 /* per-display variables */
85 struct bwtwo_softc {
86 	struct	sunfb sc_sunfb;		/* common base part */
87 	volatile struct fbcontrol *sc_reg;/* control registers */
88 	struct rom_reg	sc_phys;	/* phys address description */
89 	int	sc_bustype;		/* type of bus we live on */
90 	int	sc_pixeloffset;		/* offset to framebuffer */
91 };
92 
93 void	bwtwo_burner(void *, u_int, u_int);
94 int	bwtwo_intr(void *);
95 int	bwtwo_ioctl(void *, u_long, caddr_t, int, struct proc *);
96 paddr_t	bwtwo_mmap(void *, off_t, int);
97 
98 struct wsdisplay_accessops bwtwo_accessops = {
99 	bwtwo_ioctl,
100 	bwtwo_mmap,
101 	NULL,	/* alloc_screen */
102 	NULL,	/* free_screen */
103 	NULL,	/* show_screen */
104 	NULL,	/* load_font */
105 	NULL,	/* scrollback */
106 	NULL,	/* getchar */
107 	bwtwo_burner,
108 	NULL	/* pollc */
109 };
110 
111 
112 /* autoconfiguration driver */
113 void	bwtwoattach(struct device *, struct device *, void *);
114 int	bwtwomatch(struct device *, void *, void *);
115 
116 struct cfattach bwtwo_ca = {
117 	sizeof(struct bwtwo_softc), bwtwomatch, bwtwoattach
118 };
119 
120 struct cfdriver bwtwo_cd = {
121 	NULL, "bwtwo", DV_DULL
122 };
123 
124 int
bwtwomatch(struct device * parent,void * vcf,void * aux)125 bwtwomatch(struct device *parent, void *vcf, void *aux)
126 {
127 	struct cfdata *cf = vcf;
128 	struct confargs *ca = aux;
129 	struct romaux *ra = &ca->ca_ra;
130 
131 	if (strcmp(cf->cf_driver->cd_name, ra->ra_name))
132 		return (0);
133 
134 #if 0
135 	if (CPU_ISSUN4 && cf->cf_unit != 0)
136 		return (0);
137 #endif
138 
139 	if (ca->ca_bustype == BUS_SBUS)
140 		return (1);
141 
142 	/*
143 	 * Make sure there's hardware there.
144 	 */
145 	if (probeget(ra->ra_vaddr, 4) == -1)
146 		return (0);
147 
148 	switch (ca->ca_bustype) {
149 	case BUS_VME16:
150 	case BUS_VME32:
151 		return (1);
152 	case BUS_OBIO:
153 #if defined(SUN4)
154 		if (CPU_ISSUN4) {
155 			/*
156 			 * Check for a pfour framebuffer, but do not match the
157 			 * overlay planes for color pfour framebuffers.
158 			 */
159 			switch (fb_pfour_id(ra->ra_vaddr)) {
160 			case PFOUR_ID_BW:
161 			case PFOUR_NOTPFOUR:
162 				return (1);
163 			case PFOUR_ID_COLOR8P1:		/* bwtwo in ... */
164 			case PFOUR_ID_COLOR24:		/* ...overlay plane */
165 			default:
166 				return (0);
167 			}
168 		}
169 #endif
170 		return (1);
171 	default:
172 		return (0);
173 	}
174 }
175 
176 void
bwtwoattach(struct device * parent,struct device * self,void * args)177 bwtwoattach(struct device *parent, struct device *self, void *args)
178 {
179 	struct bwtwo_softc *sc = (struct bwtwo_softc *)self;
180 	struct confargs *ca = args;
181 	int node = ca->ca_ra.ra_node;
182 	int isconsole = 0;
183 	int sbus = 1;
184 	char *nam;
185 
186 	printf(": ");
187 
188 	/*
189 	 * Map the control register.
190 	 */
191 #if defined(SUN4)
192 	if (CPU_ISSUN4 && ca->ca_bustype == BUS_OBIO &&
193 	    fb_pfour_id(ca->ca_ra.ra_vaddr) != PFOUR_NOTPFOUR) {
194 		SET(sc->sc_sunfb.sf_flags, FB_PFOUR);
195 		sc->sc_sunfb.sf_pfour = (volatile u_int32_t *)
196 		    mapiodev(ca->ca_ra.ra_reg, 0, sizeof(u_int32_t));
197 	} else
198 #endif
199 	{
200 		sc->sc_reg = (volatile struct fbcontrol *)
201 		    mapiodev(ca->ca_ra.ra_reg, BWREG_REG,
202 			     sizeof(struct fbcontrol));
203 	}
204 
205 	/* Set up default pixel offset.  May be changed below. */
206 	sc->sc_pixeloffset = BWREG_MEM;
207 
208 	switch (ca->ca_bustype) {
209 	case BUS_OBIO:
210 		if (CPU_ISSUN4M)	/* 4m has framebuffer on obio */
211 			goto obp_name;
212 
213 		sbus = node = 0;
214 #if defined(SUN4)
215 		if (ISSET(sc->sc_sunfb.sf_flags, FB_PFOUR)) {
216 			nam = "p4";
217 			sc->sc_pixeloffset = PFOUR_BW_OFF;
218 		} else
219 #endif
220 			nam = NULL;
221 		break;
222 
223 	case BUS_VME32:
224 	case BUS_VME16:
225 		sbus = node = 0;
226 		nam = NULL;
227 		break;
228 
229 	case BUS_SBUS:
230 obp_name:
231 #if defined(SUN4C) || defined(SUN4M)
232 		nam = getpropstring(node, "model");
233 #endif
234 		break;
235 	}
236 
237 	if (nam != NULL && *nam != '\0')
238 		printf("%s, ", nam);
239 
240 #if defined(SUN4)
241 	if (CPU_ISSUN4) {
242 		struct eeprom *eep = (struct eeprom *)eeprom_va;
243 		int constype = ISSET(sc->sc_sunfb.sf_flags, FB_PFOUR) ?
244 		    EE_CONS_P4OPT : EE_CONS_BW;
245 		/*
246 		 * Assume this is the console if there's no eeprom info
247 		 * to be found.
248 		 */
249 		if (eep == NULL || eep->eeConsole == constype)
250 			isconsole = 1;
251 		else
252 		/*
253 		 * On sun4 systems without on-board framebuffers (such as
254 		 * the 4/3xx models), the PROM will accept the EE_CONS_BW
255 		 * setting although the framebuffer is a P4.
256 		 * Accept this setting as well.
257 		 */
258 		if (eep->eeConsole == EE_CONS_BW)
259 			isconsole = 1;
260 	}
261 #endif
262 
263 	if (CPU_ISSUN4COR4M)
264 		isconsole = node == fbnode;
265 
266 	sc->sc_phys = ca->ca_ra.ra_reg[0];
267 	sc->sc_bustype = ca->ca_bustype;
268 
269 	/* enable video */
270 	bwtwo_burner(sc, 1, 0);
271 
272 	fb_setsize(&sc->sc_sunfb, 1, 1152, 900, node, ca->ca_bustype);
273 	printf("%dx%d\n", sc->sc_sunfb.sf_width, sc->sc_sunfb.sf_height);
274 
275 	sc->sc_sunfb.sf_ro.ri_bits = mapiodev(ca->ca_ra.ra_reg,
276 	    sc->sc_pixeloffset, round_page(sc->sc_sunfb.sf_fbsize));
277 	sc->sc_sunfb.sf_ro.ri_hw = sc;
278 	fbwscons_init(&sc->sc_sunfb, isconsole ? 0 : RI_CLEAR);
279 
280 	if (isconsole) {
281 		fbwscons_console_init(&sc->sc_sunfb, -1);
282 	}
283 
284 	fbwscons_attach(&sc->sc_sunfb, &bwtwo_accessops, isconsole);
285 }
286 
287 int
bwtwo_ioctl(void * v,u_long cmd,caddr_t data,int flags,struct proc * p)288 bwtwo_ioctl(void *v, u_long cmd, caddr_t data, int flags, struct proc *p)
289 {
290 	struct bwtwo_softc *sc = v;
291 	struct wsdisplay_fbinfo *wdf;
292 
293 	switch (cmd) {
294 	case WSDISPLAYIO_GTYPE:
295 		*(u_int *)data = WSDISPLAY_TYPE_SUNBW;
296 		break;
297 	case WSDISPLAYIO_GINFO:
298 		wdf = (struct wsdisplay_fbinfo *)data;
299 		wdf->height = sc->sc_sunfb.sf_height;
300 		wdf->width = sc->sc_sunfb.sf_width;
301 		wdf->depth = sc->sc_sunfb.sf_depth;
302 		wdf->cmsize = 0;	/* no colormap */
303 		break;
304 	case WSDISPLAYIO_LINEBYTES:
305 		*(u_int *)data = sc->sc_sunfb.sf_linebytes;
306 		break;
307 
308 	case WSDISPLAYIO_GETCMAP:
309 	case WSDISPLAYIO_PUTCMAP:
310 		break;
311 
312 	case WSDISPLAYIO_SVIDEO:
313 	case WSDISPLAYIO_GVIDEO:
314 		break;
315 
316 	case WSDISPLAYIO_GCURPOS:
317 	case WSDISPLAYIO_SCURPOS:
318 	case WSDISPLAYIO_GCURMAX:
319 	case WSDISPLAYIO_GCURSOR:
320 	case WSDISPLAYIO_SCURSOR:
321 	default:
322 		return (-1);	/* not supported yet */
323 	}
324 
325 	return (0);
326 }
327 
328 paddr_t
bwtwo_mmap(void * v,off_t offset,int prot)329 bwtwo_mmap(void *v, off_t offset, int prot)
330 {
331 	struct bwtwo_softc *sc = v;
332 
333 	if (offset & PGOFSET)
334 		return (-1);
335 
336 	if (offset >= 0 && offset < sc->sc_sunfb.sf_fbsize) {
337 		return (REG2PHYS(&sc->sc_phys, sc->sc_pixeloffset + offset) |
338 		    PMAP_NC);
339 	}
340 
341 	return (-1);
342 }
343 
344 void
bwtwo_burner(void * v,u_int on,u_int flags)345 bwtwo_burner(void *v, u_int on, u_int flags)
346 {
347 	struct bwtwo_softc *sc = v;
348 	int s;
349 
350 #if defined(SUN4)
351 	if (CPU_ISSUN4 && (sc->sc_bustype == BUS_OBIO)) {
352 		if (ISSET(sc->sc_sunfb.sf_flags, FB_PFOUR)) {
353 			fb_pfour_burner(v, on, flags);
354 			return;
355 		}
356 		if (on)
357 			stba(AC_SYSENABLE, ASI_CONTROL,
358 			    lduba(AC_SYSENABLE, ASI_CONTROL) | SYSEN_VIDEO);
359 		else
360 			stba(AC_SYSENABLE, ASI_CONTROL,
361 			    lduba(AC_SYSENABLE, ASI_CONTROL) & ~SYSEN_VIDEO);
362 
363 		return;
364 	}
365 #endif
366 
367 	s = splhigh();
368 	if (on)
369 		sc->sc_reg->fbc_ctrl |= FBC_VENAB | FBC_TIMING;
370 	else {
371 		sc->sc_reg->fbc_ctrl &= ~FBC_VENAB;
372 		if (flags & WSDISPLAY_BURN_VBLANK)
373 			sc->sc_reg->fbc_ctrl &= ~FBC_TIMING;
374 	}
375 	splx(s);
376 }
377