Home | History | Annotate | Line # | Download | only in dev
fb.c revision 1.4
      1 /*	$NetBSD: fb.c,v 1.4 2000/06/26 04:55:51 simonb Exp $	*/
      2 /*
      3  * Copyright (c) 1992, 1993
      4  *	The Regents of the University of California.  All rights reserved.
      5  *
      6  * This code is derived from software contributed to Berkeley by
      7  * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. All advertising materials mentioning features or use of this software
     18  *    must display the following acknowledgement:
     19  *	This product includes software developed by the University of
     20  *	California, Berkeley and its contributors.
     21  * 4. Neither the name of the University nor the names of its contributors
     22  *    may be used to endorse or promote products derived from this software
     23  *    without specific prior written permission.
     24  *
     25  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     35  * SUCH DAMAGE.
     36  *
     37  * from: $Hdr: fb.c,v 4.300 91/06/27 20:43:06 root Rel41 $ SONY
     38  *
     39  *	@(#)fb.c	8.1 (Berkeley) 6/11/93
     40  */
     41 
     42 #include "fb.h"
     43 #if NFB > 0
     44 /*
     45  * Frame buffer driver
     46  */
     47 
     48 #include <sys/param.h>
     49 #include <sys/types.h>
     50 #include <sys/device.h>
     51 #include <sys/systm.h>
     52 #include <sys/proc.h>
     53 
     54 #include <machine/cpu.h>
     55 #include <machine/autoconf.h>
     56 #include <machine/framebuf.h>
     57 
     58 #include <newsmips/dev/fbreg.h>
     59 
     60 #define FB_USED		1
     61 #define VIDEO_USED	2
     62 
     63 struct fb_softc {
     64 	struct device sc_dev;
     65 	int fbs_state;
     66 	int fbs_device;
     67 	lScrType fbs_type;
     68 	int fbs_flag;
     69 	struct fbreg fbreg;
     70 };
     71 
     72 static int	fbmatch __P((struct device *, struct cfdata *, void *));
     73 static void	fbattach __P((struct device *, struct device *, void *));
     74 static void	fblock __P((void));
     75 static void	fbunlock __P((int));
     76 static int	fbinit __P((struct fbreg *));
     77 static void	fbreset __P((struct fbreg *));
     78 
     79 struct cfattach fb_ca = {
     80 	sizeof(struct fb_softc), fbmatch, fbattach
     81 };
     82 
     83 extern struct cfdriver fb_cd;
     84 
     85 static char *devname[] = {
     86 /* 0*/	"",
     87 /* 1*/	"NWB-512",
     88 /* 2*/	"NWB-225",
     89 /* 3*/	"POP-MONO",
     90 /* 4*/	"POP-COLOR",
     91 /* 5*/	"NWB-514",
     92 /* 6*/	"NWB-251",
     93 /* 7*/	"LCD-MONO",
     94 /* 8*/	"LDC-COLOR",
     95 /* 9*/	"NWB-518",
     96 /*10*/	"NWB-252",
     97 /*11*/	"NWB-253",
     98 /*12*/	"NWB-254",
     99 /*13*/	"NWB-255",
    100 /*14*/	"SLB-101",
    101 /*15*/	"NWB-256",
    102 /*16*/	"NWB-257",
    103 };
    104 
    105 static int fbstate = 0;
    106 
    107 extern int fb253_probe();
    108 extern void bmcnattach();
    109 extern int fbstart __P((struct fbreg *, int));
    110 extern int search_fbdev __P((int, int));
    111 extern int fbgetscrtype();
    112 extern int fbsetpalette();
    113 extern int fbgetpalette();
    114 extern int fbsetcursor();
    115 extern int fbnsetcursor();
    116 extern int fbsetxy();
    117 
    118 static int
    119 fbmatch(parent, cf, aux)
    120 	struct device *parent;
    121 	struct cfdata *cf;
    122 	void *aux;
    123 {
    124 	struct confargs *ca = aux;
    125 	struct fbreg fbreg;
    126 	struct fbreg *fbp = &fbreg;
    127 	int unit = cf->cf_unit;
    128 
    129 	if (strcmp(ca->ca_name, "fb"))
    130 		return 0;
    131 
    132 	fbp->fb_command = FB_CPROBE;
    133 	fbp->fb_device = 0;
    134 	fbp->fb_unit = unit;
    135 	fbp->fb_data = -1;
    136 	fbstart(fbp, 1);
    137 
    138 	if (fbp->fb_result != FB_ROK)
    139 		return 0;
    140 
    141 	return 1;
    142 }
    143 
    144 static void
    145 fbattach(parent, self, aux)
    146 	struct device *parent;
    147 	struct device *self;
    148 	void *aux;
    149 {
    150 	struct fb_softc *fb = (struct fb_softc *)self;
    151 	struct fbreg *fbp = &fb->fbreg;
    152 	int unit = fb->sc_dev.dv_cfdata->cf_unit;
    153 	extern int tty00_is_console;
    154 
    155 	fb->fbs_device = unit;
    156 
    157 	fbp->fb_command = FB_CATTACH;
    158 	fbp->fb_device = fb->fbs_device;
    159 	fbstart(fbp, 1);
    160 	fb->fbs_type = fbp->fb_scrtype;
    161 
    162 	if (fb->fbs_type.type) {
    163 		fb->fbs_state = 0;
    164 		fb->fbs_flag = 0;
    165 		printf(": %s",
    166 			(fb->fbs_type.type < sizeof(devname)/sizeof(*devname))
    167 				? devname[(int)fb->fbs_type.type] : "UNKNOWN");
    168 		printf(" (%d x %d %d plane)",
    169 				fb->fbs_type.visiblerect.extent.x,
    170 				fb->fbs_type.visiblerect.extent.y,
    171 				fb->fbs_type.plane);
    172 	}
    173 
    174 	if (! tty00_is_console) {	/* XXX */
    175 		printf(" (console)");
    176 		bmcnattach();
    177 	}
    178 	printf("\n");
    179 }
    180 
    181 int
    182 fbopen(dev, flags, mode, p)
    183 	dev_t dev;
    184 	int flags, mode;
    185 	struct proc *p;
    186 {
    187 	register int unit = FBUNIT(dev);
    188 	register struct fb_softc *fb = fb_cd.cd_devs[unit];
    189 	register struct fbreg *fbp = &fb->fbreg;
    190 
    191 	if (unit >= NFB)
    192 		return ENXIO;
    193 	if (fb->fbs_flag && !FBVIDEO(dev))
    194 		return EBUSY;
    195 
    196 	if (fb->fbs_state == 0) {
    197 		fbp->fb_device = fb->fbs_device;
    198 		if (fbinit(fbp))
    199 			return EBUSY;
    200 	}
    201 
    202         fb->fbs_state |= FBVIDEO(dev) ? VIDEO_USED : FB_USED;
    203 
    204 	return 0;
    205 }
    206 
    207 int
    208 fbclose(dev, flags, mode, p)
    209 	dev_t dev;
    210 	int flags, mode;
    211 	struct proc *p;
    212 {
    213 	register int unit = FBUNIT(dev);
    214 	register struct fb_softc *fb = fb_cd.cd_devs[unit];
    215 	register struct fbreg *fbp = &fb->fbreg;
    216 
    217 	if (unit >= NFB)
    218 		return ENXIO;
    219 
    220 	if (fb->fbs_state == 0)
    221 		return 0;
    222 
    223 	if (!FBVIDEO(dev))
    224 		fb->fbs_flag = 0;
    225 
    226 	fb->fbs_state &= ~(FBVIDEO(dev) ? VIDEO_USED : FB_USED);
    227 
    228 	if (fb->fbs_state == 0) {
    229 		fbp->fb_device = fb->fbs_device;
    230 		fbreset(fbp);
    231 	}
    232 
    233 	return 0;
    234 }
    235 
    236 int
    237 fbioctl(dev, cmd, data, flags, p)
    238 	dev_t dev;
    239 	u_long cmd;
    240 	caddr_t data;
    241 	int flags;
    242 	struct proc *p;
    243 {
    244 	register int unit = FBUNIT(dev);
    245 	register struct fb_softc *fb = fb_cd.cd_devs[unit];
    246 	register struct fbreg *fbp = &fb->fbreg;
    247 	register int error = 0;
    248 
    249 	if (unit >= NFB)
    250 		return ENXIO;
    251 
    252 	fblock();
    253 
    254 	fbp->fb_device = fb->fbs_device;
    255 
    256 	switch (cmd) {
    257 	case FBIOCENABLE:
    258 		fb->fbs_flag = 0;
    259 		break;
    260 	case FBIOCDISABLE:
    261 		fb->fbs_flag = 1;
    262 		break;
    263 	case FBIOCAUTODIM:
    264 		fbp->fb_command = FB_CAUTODIM;
    265 		fbp->fb_data = *((int *)data);
    266 		fbstart(fbp, 0);
    267 		break;
    268 	case FBIOCSETDIM:
    269 		fbp->fb_command = FB_CSETDIM;
    270 		fbp->fb_data = *((int*)data);
    271 		fbstart(fbp, 0);
    272 		break;
    273 	case FBIOCGETDIM:
    274 		fbp->fb_command = FB_CGETDIM;
    275 		fbstart(fbp, 1);
    276 		*((int*)data) = fbp->fb_data;
    277 		break;
    278 #ifdef notyet
    279 	case FBIOCBITBLT:
    280 		error = fbbitblt(fbp, (sBitblt *)data);
    281 		break;
    282 	case FBIOCNBITBLT:
    283 		error = fbnbitblt(fbp, (lBitblt *)data, UIO_USERSPACE);
    284 		break;
    285 	case FBIOCBATCHBITBLT:
    286 		error = fbbatchbitblt(fbp, (sBatchBitblt*)data, UIO_USERSPACE);
    287 		break;
    288 	case FBIOCNBATCHBITBLT:
    289 		error = fbnbatchbitblt(fbp, (lBatchBitblt*)data, UIO_USERSPACE);
    290 		break;
    291 	case FBIOCTILEBITBLT:
    292 		error = fbtilebitblt(fbp, (sTileBitblt *)data);
    293 		break;
    294 	case FBIOCNTILEBITBLT:
    295 		error = fbntilebitblt(fbp, (lTileBitblt *)data);
    296 		break;
    297 	case FBIOCBITBLT3:
    298 		error = fbbitblt3(fbp, (sBitblt3 *)data);
    299 		break;
    300 	case FBIOCNBITBLT3:
    301 		error = fbnbitblt3(fbp, (lBitblt3 *)data);
    302 		break;
    303 	case FBIOCPOLYLINE:
    304 		error = fbpolyline(fbp, (sPrimLine *)data, 0);
    305 		break;
    306 	case FBIOCNPOLYLINE:
    307 		error = fbnpolyline(fbp, (lPrimLine *)data, 0, UIO_USERSPACE);
    308 		break;
    309 	case FBIOCDJPOLYLINE:
    310 		error = fbpolyline(fbp, (sPrimLine *)data, 1);
    311 		break;
    312 	case FBIOCNDJPOLYLINE:
    313 		error = fbnpolyline(fbp, (lPrimLine *)data, 1, UIO_USERSPACE);
    314 		break;
    315 	case FBIOCPOLYMARKER:
    316 		error = fbpolymarker(fbp, (sPrimMarker *)data);
    317 		break;
    318 	case FBIOCNPOLYMARKER:
    319 		error = fbnpolymarker(fbp, (lPrimMarker *)data, UIO_USERSPACE);
    320 		break;
    321 	case FBIOCRECTANGLE:
    322 		error = fbrectangle(fbp, (sPrimRect *)data);
    323 		break;
    324 	case FBIOCNRECTANGLE:
    325 		error = fbnrectangle(fbp, (lPrimRect *)data);
    326 		break;
    327 	case FBIOCFILLSCAN:
    328 		error = fbfillscan(fbp, (sPrimFill *)data);
    329 		break;
    330 	case FBIOCNFILLSCAN:
    331 		error = fbnfillscan(fbp, (lPrimFill *)data, UIO_USERSPACE);
    332 		break;
    333 	case FBIOCTEXT:
    334 		error = fbtext(fbp, (sPrimText *)data);
    335 		break;
    336 	case FBIOCNTEXT:
    337 		error = fbntext(fbp, (lPrimText *)data);
    338 		break;
    339 	case FBIOCPOLYDOT:
    340 		error = fbpolydot(fbp, (sPrimDot *)data);
    341 		break;
    342 	case FBIOCNPOLYDOT:
    343 		error = fbnpolydot(fbp, (lPrimDot *)data, UIO_USERSPACE);
    344 		break;
    345 #endif
    346 
    347 	case FBIOCGETSCRTYPE:
    348 		fbgetscrtype(fbp, (sScrType *)data);
    349 		break;
    350 	case FBIOCNGETSCRTYPE:
    351 		fbp->fb_command = FB_CGETSCRTYPE;
    352 		fbstart(fbp, 1);
    353 		*((lScrType*)data) = fbp->fb_scrtype;
    354 		break;
    355 	case FBIOCSETPALETTE:
    356 		fbsetpalette(fbp, (sPalette *)data);
    357 		break;
    358 #ifdef notyet
    359 	case FBIOCNSETPALETTE:
    360 		error = fbnsetpalette(fbp, (lPalette *)data);
    361 		break;
    362 #endif
    363 	case FBIOCGETPALETTE:
    364 		fbgetpalette(fbp, (sPalette *)data);
    365 		break;
    366 #ifdef notyet
    367 	case FBIOCNGETPALETTE:
    368 		error = fbngetpalette(fbp, (lPalette *)data);
    369 		break;
    370 #endif
    371 	case FBIOCSETCURSOR:
    372 		fbsetcursor(fbp, (sCursor *)data);
    373 		break;
    374 	case FBIOCNSETCURSOR:
    375 		fbnsetcursor(fbp, (lCursor *)data);
    376 		break;
    377 	case FBIOCNSETCURSOR2:
    378 		fbp->fb_command = FB_CSETCURSOR;
    379 		fbp->fb_cursor = *((lCursor2 *)data);
    380 		fbstart(fbp, 0);
    381 		break;
    382 	case FBIOCUNSETCURSOR:
    383 		fbp->fb_command = FB_CUNSETCURSOR;
    384 		fbstart(fbp, 0);
    385 		break;
    386 	case FBIOCNUNSETCURSOR:
    387 		fbp->fb_command = FB_CUNSETCURSOR;
    388 		fbstart(fbp, 0);
    389 		break;
    390 	case FBIOCSHOWCURSOR:
    391 		fbp->fb_command = FB_CSHOWCURSOR;
    392 		fbstart(fbp, 0);
    393 		break;
    394 	case FBIOCNSHOWCURSOR:
    395 		fbp->fb_command = FB_CSHOWCURSOR;
    396 		fbstart(fbp, 0);
    397 		break;
    398 	case FBIOCHIDECURSOR:
    399 		fbp->fb_command = FB_CHIDECURSOR;
    400 		fbstart(fbp, 0);
    401 		break;
    402 	case FBIOCNHIDECURSOR:
    403 		fbp->fb_command = FB_CHIDECURSOR;
    404 		fbstart(fbp, 0);
    405 		break;
    406 	case FBIOCSETXY:
    407 		fbsetxy(fbp, (sPoint *)data);
    408 		break;
    409 	case FBIOCNSETXY:
    410 		fbp->fb_command = FB_CSETXY;
    411 		fbp->fb_point = *((lPoint *)data);
    412 		fbstart(fbp, 0);
    413 		break;
    414 	case FBIOCNSETPALETTEMODE:
    415 		fbp->fb_command = FB_CSETPMODE;
    416 		fbp->fb_data = *((int*)data);
    417 		fbstart(fbp, 0);
    418 		break;
    419 	case FBIOCNGETPALETTEMODE:
    420 		fbp->fb_command = FB_CGETPMODE;
    421 		fbstart(fbp, 1);
    422 		*((int*)data) = fbp->fb_data;
    423 		break;
    424 	case FBIOCNSETVIDEO:
    425 		fbp->fb_command = FB_CSETVIDEO;
    426 		fbp->fb_videoctl = *((lVideoCtl*)data);
    427 		fbstart(fbp, 0);
    428 		break;
    429 	case FBIOCNGETVIDEO:
    430 		fbp->fb_command = FB_CGETVIDEO;
    431 		fbp->fb_videostatus.request = VIDEO_STATUS;
    432 		fbstart(fbp, 1);
    433 		*((lVideoStatus*)data) = fbp->fb_videostatus;
    434 		error = fbp->fb_result;
    435 		break;
    436 	case FBIOCNIOCTL:
    437 		fbp->fb_command = FB_CIOCTL;
    438 		fbp->fb_fbioctl = *((lFbIoctl*)data);
    439 		fbstart(fbp, 1);
    440 		*((lFbIoctl*)data) = fbp->fb_fbioctl;
    441 		if (fbp->fb_result == FB_RERROR)
    442 			error = EINVAL;
    443 		break;
    444 
    445 	default:
    446 		error = ENXIO;
    447 		break;
    448 	}
    449 
    450 	fbunlock(error);
    451 
    452 	return error;
    453 }
    454 
    455 paddr_t
    456 fbmmap(dev, off, prot)
    457 	dev_t dev;
    458 	off_t off;
    459 	int prot;
    460 {
    461 	int unit = FBUNIT(dev);
    462 	struct fb_softc *fb = fb_cd.cd_devs[unit];
    463 	struct fbreg *fbp = &fb->fbreg;
    464 	paddr_t page;
    465 
    466 	if (unit >= NFB)
    467 		return -1;
    468 
    469         if (off & PGOFSET)
    470                 return -1;
    471 
    472 	if (off < 0)
    473 		return -1;
    474 
    475 	fblock();
    476 	fbp->fb_device = fb->fbs_device;
    477 	fbp->fb_command = FB_CGETPAGE;
    478 	fbp->fb_data = off;
    479 	fbstart(fbp, 1);
    480 	page = fbp->fb_data;
    481 	if (fbp->fb_result == FB_RERROR)
    482 		page = -1;
    483 	else
    484 		fb->fbs_flag = 1;
    485 	fbunlock(fbp->fb_result);
    486 
    487 	return page;
    488 }
    489 
    490 #if 0	/* not needed? */
    491 int
    492 fbpoll(dev, events, p)
    493 	dev_t dev;
    494 	int events;
    495 	struct proc *p;
    496 {
    497 	return -1;
    498 }
    499 #endif
    500 
    501 static void
    502 fblock()
    503 {
    504 	int s;
    505 
    506 #ifdef USE_RAW_INTR
    507 	fbwait();
    508 #endif
    509 	s = splfb();
    510 	while (fbstate & FB_BUSY) {
    511 		fbstate |= FB_WANTED;
    512 		tsleep(&fbstate, FBPRI | PCATCH, "fblock", 0);
    513 	}
    514 	fbstate |= FB_BUSY;
    515 	splx(s);
    516 }
    517 
    518 static void
    519 fbunlock(error)
    520 	int error;
    521 {
    522 	int s = splfb();
    523 
    524 #ifdef CPU_SINGLE
    525 	fbstate &= ~FB_BUSY;
    526 	if (fbstate & FB_WANTED) {
    527 		fbstate &= ~FB_WANTED;
    528 		wakeup(&fbstate);
    529 	}
    530 #else
    531 #ifdef USE_RAW_INTR
    532 	fbstate &= ~FB_BUSY;
    533 	if (fbstate & FB_WANTED) {
    534 		fbstate &= ~FB_WANTED;
    535 		wakeup(&fbstate);
    536 	}
    537 #else
    538 	if (error || (fbstate & FB_DELAY) == 0) {
    539 		fbstate &= ~(FB_BUSY | FB_WAIT | FB_DELAY);
    540 		if (fbstate & FB_WANTED) {
    541 			fbstate &= ~FB_WANTED;
    542 			wakeup(&fbstate);
    543 		}
    544 	}
    545 	if (fbstate & FB_DELAY) {
    546 		fbstate &= ~FB_DELAY;
    547 		fbstate |= FB_DELAY2;
    548 	}
    549 #endif
    550 #endif /* CPU_SINGLE */
    551 	splx(s);
    552 }
    553 
    554 static int
    555 fbinit(fbp)
    556 	struct fbreg *fbp;
    557 {
    558 	fblock();
    559 
    560 	fbp->fb_command = FB_COPEN;
    561 	fbstart(fbp, 1);
    562 	if (fbp->fb_result != FB_ROK) {
    563 		fbunlock(0);
    564 		return FB_RERROR;
    565 	}
    566 
    567 	fbp->fb_command = FB_CUNSETCURSOR;
    568 	fbstart(fbp, 0);
    569 
    570 	fbunlock(0);
    571 
    572 	return FB_ROK;
    573 }
    574 
    575 static void
    576 fbreset(fbp)
    577 	struct fbreg *fbp;
    578 {
    579 	fblock();
    580 
    581 	fbp->fb_command = FB_CUNSETCURSOR;
    582 	fbstart(fbp, 1);
    583 
    584 	fbp->fb_command = FB_CCLOSE;
    585 	fbstart(fbp, 0);
    586 
    587 	fbunlock(0);
    588 }
    589 #endif /* NFB > 0 */
    590