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