fb.c revision 1.3 1 /* $NetBSD: fb.c,v 1.3 1999/02/15 04:36:33 hubertf 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 int
456 fbmmap(dev, off, prot)
457 dev_t dev;
458 int off, prot;
459 {
460 register int unit = FBUNIT(dev);
461 register struct fb_softc *fb = fb_cd.cd_devs[unit];
462 register struct fbreg *fbp = &fb->fbreg;
463 register int page;
464
465 if (unit >= NFB)
466 return -1;
467
468 if (off & PGOFSET)
469 return -1;
470
471 if (off < 0)
472 return -1;
473
474 fblock();
475 fbp->fb_device = fb->fbs_device;
476 fbp->fb_command = FB_CGETPAGE;
477 fbp->fb_data = off;
478 fbstart(fbp, 1);
479 page = fbp->fb_data;
480 if (fbp->fb_result == FB_RERROR)
481 page = -1;
482 else
483 fb->fbs_flag = 1;
484 fbunlock(fbp->fb_result);
485
486 return page;
487 }
488
489 #if 0 /* not needed? */
490 int
491 fbpoll(dev, events, p)
492 dev_t dev;
493 int events;
494 struct proc *p;
495 {
496 return -1;
497 }
498 #endif
499
500 static void
501 fblock()
502 {
503 int s;
504
505 #ifdef USE_RAW_INTR
506 fbwait();
507 #endif
508 s = splfb();
509 while (fbstate & FB_BUSY) {
510 fbstate |= FB_WANTED;
511 tsleep(&fbstate, FBPRI | PCATCH, "fblock", 0);
512 }
513 fbstate |= FB_BUSY;
514 splx(s);
515 }
516
517 static void
518 fbunlock(error)
519 int error;
520 {
521 int s = splfb();
522
523 #ifdef CPU_SINGLE
524 fbstate &= ~FB_BUSY;
525 if (fbstate & FB_WANTED) {
526 fbstate &= ~FB_WANTED;
527 wakeup(&fbstate);
528 }
529 #else
530 #ifdef USE_RAW_INTR
531 fbstate &= ~FB_BUSY;
532 if (fbstate & FB_WANTED) {
533 fbstate &= ~FB_WANTED;
534 wakeup(&fbstate);
535 }
536 #else
537 if (error || (fbstate & FB_DELAY) == 0) {
538 fbstate &= ~(FB_BUSY | FB_WAIT | FB_DELAY);
539 if (fbstate & FB_WANTED) {
540 fbstate &= ~FB_WANTED;
541 wakeup(&fbstate);
542 }
543 }
544 if (fbstate & FB_DELAY) {
545 fbstate &= ~FB_DELAY;
546 fbstate |= FB_DELAY2;
547 }
548 #endif
549 #endif /* CPU_SINGLE */
550 splx(s);
551 }
552
553 static int
554 fbinit(fbp)
555 struct fbreg *fbp;
556 {
557 fblock();
558
559 fbp->fb_command = FB_COPEN;
560 fbstart(fbp, 1);
561 if (fbp->fb_result != FB_ROK) {
562 fbunlock(0);
563 return FB_RERROR;
564 }
565
566 fbp->fb_command = FB_CUNSETCURSOR;
567 fbstart(fbp, 0);
568
569 fbunlock(0);
570
571 return FB_ROK;
572 }
573
574 static void
575 fbreset(fbp)
576 struct fbreg *fbp;
577 {
578 fblock();
579
580 fbp->fb_command = FB_CUNSETCURSOR;
581 fbstart(fbp, 1);
582
583 fbp->fb_command = FB_CCLOSE;
584 fbstart(fbp, 0);
585
586 fbunlock(0);
587 }
588 #endif /* NFB > 0 */
589