make kernel includes standard
[unix-history] / usr / src / sys / news3400 / iop / fb.c
CommitLineData
af5295ff
KM
1/*
2 * Copyright (c) 1992 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc.
7 *
8 * %sccs.include.redist.c%
9 *
10 * from: $Hdr: fb.c,v 4.300 91/06/27 20:43:06 root Rel41 $ SONY
11 *
5b7c2955 12 * @(#)fb.c 7.2 (Berkeley) %G%
af5295ff
KM
13 */
14
5b7c2955 15#include <machine/fix_machine_type.h>
af5295ff
KM
16
17#include "fb.h"
18#if NFB > 0
19/*
20 * Frame buffer driver
21 */
22
5b7c2955
KU
23#include <sys/types.h>
24#include <machine/pte.h>
25#include <machine/cpu.h>
af5295ff 26
5b7c2955
KU
27#include <sys/param.h>
28#include <sys/proc.h>
29#include <sys/user.h>
30#include <sys/buf.h>
31#include <vm/vm.h>
32#include <sys/systm.h>
33#include <sys/map.h>
34#include <sys/uio.h>
35#include <sys/kernel.h>
af5295ff 36
5b7c2955
KU
37#include <news3400/iop/framebuf.h>
38#include <news3400/iop/fbreg.h>
39#include <news3400/iodev/ioptohb.h>
af5295ff
KM
40
41#ifdef CPU_SINGLE
5b7c2955 42#include <news3400/hbdev/hbvar.h>
af5295ff
KM
43
44#define ipc_phys(x) (caddr_t)((int)(x))
45#define ipc_log(x) (caddr_t)((int)(x) | 0x80000000)
46
47#define iop_driver hb_driver
48#define iop_device hb_device
49
50extern rop_xint();
51#else /* CPU_SINGLE */
5b7c2955 52#include <news3400/iop/iopvar.h>
af5295ff
KM
53
54#ifdef IPC_MRX
55#include "../ipc/newsipc.h"
56
57#ifdef mips
58#define ipc_phys(x) K0_TT0(x)
59#define ipc_log(x) TT0_K0(x)
60#else
61#define ipc_phys(x) (caddr_t)((int)(x) & ~0x80000000)
62#define ipc_log(x) (caddr_t)((int)(x) | 0x80000000)
63#endif
64
65static int port_fb, port_fb_iop;
66#endif /* IPC_MRX */
67#endif /* CPU_SINGLE */
68
69#define FB_USED 1
70#define VIDEO_USED 2
71
72/*
73 * driver definition
74 */
75int fbprobe(), fbattach();
76
77struct iop_device *fbinfo[NFB];
78struct iop_driver fbdriver =
79#ifdef CPU_SINGLE
80 { fbprobe, 0, fbattach, 0, 0, "fb", fbinfo, "fbc", 0, 0 };
81#else
82 { fbprobe, 0, fbattach, 0, "fb", fbinfo };
83#endif
84
85/* static */
86static struct fb_softc fb_softc[NFB];
87static struct fbreg fbreg[NFB];
88static int fbstate;
89static struct fbreg *last_fb;
90
91static char *devname[] = {
92/* 0*/ "",
93/* 1*/ "NWB-512",
94/* 2*/ "NWB-225",
95/* 3*/ "POP-MONO",
96/* 4*/ "POP-COLOR",
97/* 5*/ "NWB-514",
98/* 6*/ "NWB-251",
99/* 7*/ "LCD-MONO",
100/* 8*/ "LDC-COLOR",
101/* 9*/ "NWB-518",
102/*10*/ "NWB-252",
103/*11*/ "NWB-253",
104/*12*/ "NWB-254",
105/*13*/ "NWB-255",
106/*14*/ "SLB-101",
107/*15*/ "NWB-256",
108/*16*/ "NWB-257",
109};
110
111static void fblock(), fbunlock(), fbreset();
112static int fbinit();
113
114#ifdef CPU_DOUBLE
115#ifdef USE_RAW_INTR
116
117#include "../mrx/h/ipc.h"
118
119#ifdef mips
120# define FB_ADDR &IPC_ARG(&ipc_block, ARG_CPU, 4)
121#else
122# define FB_ADDR &IPC_ARG(&ipc_block, ARG_CPU0, 4)
123# define volatile
124#endif
125
126typedef struct fbreg *fbregp;
127int fb_waiting;
128
129Xfb_intr(chan, arg)
130 int chan;
131 int arg;
132{
133
134 intrcnt[INTR_BITMAP]++;
135 if (fb_waiting) {
136 fb_waiting = 0;
137 wakeup((caddr_t)&fb_waiting);
138 }
139}
140
141static void
142fbwait()
143{
144 int s = splfb();
145
146 while (*(volatile fbregp *)FB_ADDR) {
147 fb_waiting = 1;
148 sleep((caddr_t)&fb_waiting, FBPRI);
149 }
150 (void) splx(s);
151}
152
153void
154fbstart(fbp, wait)
155 struct fbreg *fbp;
156 int wait;
157{
158
159 fbwait();
160 *(volatile fbregp *)FB_ADDR =
161#ifdef mips
162 (volatile fbregp)ipc_phys(MACH_UNCACHED_TO_CACHED(fbp));
163#else
164 (volatile fbregp)ipc_phys(fbp);
165#endif
166 if (wait)
167 fbwait();
168}
169
170#else /* USE_RAW_INTR */
171
172void
173fbstart(fbp, wait)
174 register struct fbreg *fbp;
175 int wait;
176{
177 int s = splfb();
178
179#ifdef IPC_MRX
180 msg_send(port_fb_iop, port_fb, fbp, sizeof(*fbp), MSG_INDIRECT);
181#endif
182
183 last_fb = fbp;
184 if (wait) {
185 fbstate |= FB_WAIT;
186 sleep((caddr_t)fbreg, FBPRI);
187 } else {
188 fbstate |= FB_DELAY;
189 }
190 splx(s);
191}
192
193void
194fbcint(arg)
195 int arg;
196{
197
198 intrcnt[INTR_BITMAP]++;
199
200#ifdef IPC_MRX
201 msg_recv(arg, NULL, NULL, NULL, 0);
202#ifdef mips
203 clean_dcache((caddr_t)last_fb, sizeof(struct fbreg));
204#endif
205#endif /* IPC_MRX */
206
207 if (fbstate & FB_WAIT) {
208 fbstate &= ~FB_WAIT;
209 wakeup((caddr_t)fbreg);
210 } else if (fbstate & FB_DELAY) {
211 fbstate &= ~FB_DELAY;
212 } else if (fbstate & FB_DELAY2) {
213 fbstate &= ~(FB_BUSY|FB_DELAY2);
214 if (fbstate & FB_WANTED) {
215 fbstate &= ~FB_WANTED;
216 wakeup((caddr_t)&fbstate);
217 }
218 }
219 return;
220}
221#endif /* USE_RAW_INTR */
222#endif /* CPU_DOUBLE */
223
224/* ARGSUSED */
225fbprobe(ii)
226 struct iop_device *ii;
227{
228 register int unit = ii->ii_unit;
229 register struct fb_softc *fb = &fb_softc[unit];
230#if defined(IPC_MRX) && defined(mips)
231 register struct fbreg *fbp =
232 (struct fbreg *)MACH_CACHED_TO_UNCACHED(&fbreg[unit]);
233#else
234 register struct fbreg *fbp = &fbreg[unit];
235#endif
236
237#ifdef CPU_SINGLE
238 if (unit == 0)
239 register_hb_intr2(rop_xint, ii->ii_unit, ii->ii_intr);
240#endif
241
242#ifdef IPC_MRX
243 if (port_fb_iop <= 0) {
244#ifdef USE_RAW_INTR
245 register_ipcintr(4, Xfb_intr);
246#endif
247 port_fb_iop = object_query("framebuf");
248 if (port_fb_iop <= 0) {
249 return (0);
250 }
251#ifndef USE_RAW_INTR
252 port_fb = port_create("@port_fb", fbcint, -1);
253#endif
254 }
255#endif /* IPC_MRX */
256
257 fbp->fb_command = FB_CPROBE;
258 fbp->fb_device = 0;
259 fbp->fb_unit = unit;
260 fbp->fb_data = -1;
261 fbstart(fbp, 1);
262
263 if ((fb->fbs_device = fbp->fb_data) == -1)
264 return (0);
265 else
266 return (-1);
267}
268
269/* ARGSUSED */
270fbattach(ii)
271 struct iop_device *ii;
272{
273 register int unit = ii->ii_unit;
274 register struct fb_softc *fb = &fb_softc[unit];
275#if defined(IPC_MRX) && defined(mips)
276 register struct fbreg *fbp =
277 (struct fbreg *)MACH_CACHED_TO_UNCACHED(&fbreg[unit]);
278#else
279 register struct fbreg *fbp = &fbreg[unit];
280#endif
281
282 fbp->fb_command = FB_CATTACH;
283 fbp->fb_device = fb->fbs_device;
284 fbstart(fbp, 1);
285 fb->fbs_type = fbp->fb_scrtype;
286
287 if (fb->fbs_type.type) {
288 fb->fbs_state = 0;
289 fb->fbs_flag = 0;
290 printf("fb%d: %s", unit,
291 (fb->fbs_type.type < sizeof(devname)/sizeof(*devname))
292 ? devname[fb->fbs_type.type] : "UNKNOWN");
293 printf(" (%d x %d %d plane)\n",
294 fb->fbs_type.visiblerect.extent.x,
295 fb->fbs_type.visiblerect.extent.y,
296 fb->fbs_type.plane);
297 }
298}
299
300/*ARGSUSED*/
301fbopen(dev, flag)
302 dev_t dev;
303 int flag;
304{
305 register int unit = FBUNIT(dev);
306 register struct fb_softc *fb = &fb_softc[unit];
307 register struct iop_device *ii;
308#if defined(IPC_MRX) && defined(mips)
309 register struct fbreg *fbp =
310 (struct fbreg *)MACH_CACHED_TO_UNCACHED(&fbreg[unit]);
311#else
312 register struct fbreg *fbp = &fbreg[unit];
313#endif
314
315 if (unit >= NFB || (ii = fbinfo[unit]) == 0 || ii->ii_alive == 0)
316 return (ENXIO);
317 if (fb->fbs_flag && !FBVIDEO(dev))
318 return (EBUSY);
319
320 if (fb->fbs_state == 0) {
321 fbp->fb_device = fb->fbs_device;
322 if(fbinit(fbp))
323 return (EBUSY);
324 }
325
326 fb->fbs_state |= FBVIDEO(dev) ? VIDEO_USED : FB_USED;
327
328 return (0);
329}
330
331/*ARGSUSED*/
332fbclose(dev, flag)
333 dev_t dev;
334 int flag;
335{
336 register int unit = FBUNIT(dev);
337 register struct fb_softc *fb = &fb_softc[unit];
338 register struct iop_device *ii;
339#if defined(IPC_MRX) && defined(mips)
340 register struct fbreg *fbp =
341 (struct fbreg *)MACH_CACHED_TO_UNCACHED(&fbreg[unit]);
342#else
343 register struct fbreg *fbp = &fbreg[unit];
344#endif
345
346 if (unit >= NFB || (ii = fbinfo[unit]) == 0 || ii->ii_alive == 0)
347 return (ENXIO);
348
349 if (fb->fbs_state == 0)
350 return(0);
351
352 if(!FBVIDEO(dev))
353 fb->fbs_flag = 0;
354
355 fb->fbs_state &= ~(FBVIDEO(dev) ? VIDEO_USED : FB_USED);
356
357 if (fb->fbs_state == 0) {
358 fbp->fb_device = fb->fbs_device;
359 fbreset(fbp);
360 }
361
362 return (0);
363}
364
365fbioctl(dev, cmd, data, flag)
366 dev_t dev;
367 caddr_t data;
368{
369 register int unit = FBUNIT(dev);
370 register struct fb_softc *fb = &fb_softc[unit];
371 register struct iop_device *ii;
372 register int error = 0;
373#if defined(IPC_MRX) && defined(mips)
374 register struct fbreg *fbp =
375 (struct fbreg *)MACH_CACHED_TO_UNCACHED(&fbreg[unit]);
376#else
377 register struct fbreg *fbp = &fbreg[unit];
378#endif
379
380 if (unit >= NFB || (ii = fbinfo[unit]) == 0 || ii->ii_alive == 0)
381 return (ENXIO);
382
383 fblock();
384
385 fbp->fb_device = fb->fbs_device;
386
387 switch (cmd) {
388 case FBIOCENABLE:
389 fb->fbs_flag = 0;
390 break;
391 case FBIOCDISABLE:
392 fb->fbs_flag = 1;
393 break;
394 case FBIOCAUTODIM:
395 fbp->fb_command = FB_CAUTODIM;
396 fbp->fb_data = *((int *)data);
397 fbstart(fbp, 0);
398 break;
399 case FBIOCSETDIM:
400 fbp->fb_command = FB_CSETDIM;
401 fbp->fb_data = *((int*)data);
402 fbstart(fbp, 0);
403 break;
404 case FBIOCGETDIM:
405 fbp->fb_command = FB_CGETDIM;
406 fbstart(fbp, 1);
407 *((int*)data) = fbp->fb_data;
408 break;
409 case FBIOCBITBLT:
410 error = fbbitblt(fbp, (sBitblt *)data);
411 break;
412 case FBIOCNBITBLT:
413 error = fbnbitblt(fbp, (lBitblt *)data, UIO_USERSPACE);
414 break;
415 case FBIOCBATCHBITBLT:
416 error = fbbatchbitblt(fbp, (sBatchBitblt*)data, UIO_USERSPACE);
417 break;
418 case FBIOCNBATCHBITBLT:
419 error = fbnbatchbitblt(fbp, (lBatchBitblt*)data, UIO_USERSPACE);
420 break;
421 case FBIOCTILEBITBLT:
422 error = fbtilebitblt(fbp, (sTileBitblt *)data);
423 break;
424 case FBIOCNTILEBITBLT:
425 error = fbntilebitblt(fbp, (lTileBitblt *)data);
426 break;
427 case FBIOCBITBLT3:
428 error = fbbitblt3(fbp, (sBitblt3 *)data);
429 break;
430 case FBIOCNBITBLT3:
431 error = fbnbitblt3(fbp, (lBitblt3 *)data);
432 break;
433 case FBIOCPOLYLINE:
434 error = fbpolyline(fbp, (sPrimLine *)data, 0);
435 break;
436 case FBIOCNPOLYLINE:
437 error = fbnpolyline(fbp, (lPrimLine *)data, 0, UIO_USERSPACE);
438 break;
439 case FBIOCDJPOLYLINE:
440 error = fbpolyline(fbp, (sPrimLine *)data, 1);
441 break;
442 case FBIOCNDJPOLYLINE:
443 error = fbnpolyline(fbp, (lPrimLine *)data, 1, UIO_USERSPACE);
444 break;
445 case FBIOCPOLYMARKER:
446 error = fbpolymarker(fbp, (sPrimMarker *)data);
447 break;
448 case FBIOCNPOLYMARKER:
449 error = fbnpolymarker(fbp, (lPrimMarker *)data, UIO_USERSPACE);
450 break;
451 case FBIOCRECTANGLE:
452 error = fbrectangle(fbp, (sPrimRect *)data);
453 break;
454 case FBIOCNRECTANGLE:
455 error = fbnrectangle(fbp, (lPrimRect *)data);
456 break;
457 case FBIOCFILLSCAN:
458 error = fbfillscan(fbp, (sPrimFill *)data);
459 break;
460 case FBIOCNFILLSCAN:
461 error = fbnfillscan(fbp, (lPrimFill *)data, UIO_USERSPACE);
462 break;
463 case FBIOCTEXT:
464 error = fbtext(fbp, (sPrimText *)data);
465 break;
466 case FBIOCNTEXT:
467 error = fbntext(fbp, (lPrimText *)data);
468 break;
469 case FBIOCPOLYDOT:
470 error = fbpolydot(fbp, (sPrimDot *)data);
471 break;
472 case FBIOCNPOLYDOT:
473 error = fbnpolydot(fbp, (lPrimDot *)data, UIO_USERSPACE);
474 break;
475
476 case FBIOCGETSCRTYPE:
477 fbgetscrtype(fbp, (sScrType *)data);
478 break;
479 case FBIOCNGETSCRTYPE:
480 fbp->fb_command = FB_CGETSCRTYPE;
481 fbstart(fbp, 1);
482 *((lScrType*)data) = fbp->fb_scrtype;
483 break;
484 case FBIOCSETPALETTE:
485 fbsetpalette(fbp, (sPalette *)data);
486 break;
487 case FBIOCNSETPALETTE:
488 error = fbnsetpalette(fbp, (lPalette *)data);
489 break;
490 case FBIOCGETPALETTE:
491 fbgetpalette(fbp, (sPalette *)data);
492 break;
493 case FBIOCNGETPALETTE:
494 error = fbngetpalette(fbp, (lPalette *)data);
495 break;
496 case FBIOCSETCURSOR:
497 fbsetcursor(fbp, (sCursor *)data);
498 break;
499 case FBIOCNSETCURSOR:
500 fbnsetcursor(fbp, (lCursor *)data);
501 break;
502 case FBIOCNSETCURSOR2:
503 fbp->fb_command = FB_CSETCURSOR;
504 fbp->fb_cursor = *((lCursor2 *)data);
505 fbstart(fbp, 0);
506 break;
507 case FBIOCUNSETCURSOR:
508 fbp->fb_command = FB_CUNSETCURSOR;
509 fbstart(fbp, 0);
510 break;
511 case FBIOCNUNSETCURSOR:
512 fbp->fb_command = FB_CUNSETCURSOR;
513 fbstart(fbp, 0);
514 break;
515 case FBIOCSHOWCURSOR:
516 fbp->fb_command = FB_CSHOWCURSOR;
517 fbstart(fbp, 0);
518 break;
519 case FBIOCNSHOWCURSOR:
520 fbp->fb_command = FB_CSHOWCURSOR;
521 fbstart(fbp, 0);
522 break;
523 case FBIOCHIDECURSOR:
524 fbp->fb_command = FB_CHIDECURSOR;
525 fbstart(fbp, 0);
526 break;
527 case FBIOCNHIDECURSOR:
528 fbp->fb_command = FB_CHIDECURSOR;
529 fbstart(fbp, 0);
530 break;
531 case FBIOCSETXY:
532 fbsetxy(fbp, (sPoint *)data);
533 break;
534 case FBIOCNSETXY:
535 fbp->fb_command = FB_CSETXY;
536 fbp->fb_point = *((lPoint *)data);
537 fbstart(fbp, 0);
538 break;
539 case FBIOCNSETPALETTEMODE:
540 fbp->fb_command = FB_CSETPMODE;
541 fbp->fb_data = *((int*)data);
542 fbstart(fbp, 0);
543 break;
544 case FBIOCNGETPALETTEMODE:
545 fbp->fb_command = FB_CGETPMODE;
546 fbstart(fbp, 1);
547 *((int*)data) = fbp->fb_data;
548 break;
549 case FBIOCNSETVIDEO:
550 fbp->fb_command = FB_CSETVIDEO;
551 fbp->fb_videoctl = *((lVideoCtl*)data);
552 fbstart(fbp, 0);
553 break;
554 case FBIOCNGETVIDEO:
555 fbp->fb_command = FB_CGETVIDEO;
556 fbp->fb_videostatus.request = VIDEO_STATUS;
557 fbstart(fbp, 1);
558 *((lVideoStatus*)data) = fbp->fb_videostatus;
559 error = fbp->fb_result;
560 break;
561 case FBIOCNIOCTL:
562 fbp->fb_command = FB_CIOCTL;
563 fbp->fb_fbioctl = *((lFbIoctl*)data);
564 fbstart(fbp, 1);
565 *((lFbIoctl*)data) = fbp->fb_fbioctl;
566 if (fbp->fb_result == FB_RERROR)
567 error = EINVAL;
568 break;
569
570 default:
571 error = ENXIO;
572 break;
573 }
574
575 fbunlock(error);
576
577 return (error);
578}
579
580fbmmap(dev, off, prot)
581 dev_t dev;
582 off_t off;
583 int prot;
584{
585 register int unit = FBUNIT(dev);
586 register struct fb_softc *fb = &fb_softc[unit];
587 register struct iop_device *ii;
588 register int page;
589 register struct fbreg *fbp = &fbreg[unit];
590
591 if (unit >= NFB || (ii = fbinfo[unit]) == 0 || ii->ii_alive == 0)
592 return (-1);
593
594 fblock();
595 fbp->fb_device = fb->fbs_device;
596 fbp->fb_command = FB_CGETPAGE;
597 fbp->fb_data = off;
598 fbstart(fbp, 1);
599 page = fbp->fb_data;
600 if (fbp->fb_result == FB_RERROR)
601 page = -1;
602 else
603 fb->fbs_flag = 1;
604 fbunlock(fbp->fb_result);
605
606 return (page);
607}
608
609static void
610fblock()
611{
612 int s;
613
614#ifdef USE_RAW_INTR
615 fbwait();
616#endif
617 s = splfb();
618 while (fbstate & FB_BUSY) {
619 fbstate |= FB_WANTED;
620 sleep((caddr_t)&fbstate, FBPRI);
621 }
622 fbstate |= FB_BUSY;
623 splx(s);
624}
625
626static void
627fbunlock(error)
628 int error;
629{
630 int s = splfb();
631
632#ifdef CPU_SINGLE
633 fbstate &= ~FB_BUSY;
634 if (fbstate & FB_WANTED) {
635 fbstate &= ~FB_WANTED;
636 wakeup((caddr_t)&fbstate);
637 }
638#else
639#ifdef USE_RAW_INTR
640 fbstate &= ~FB_BUSY;
641 if (fbstate & FB_WANTED) {
642 fbstate &= ~FB_WANTED;
643 wakeup((caddr_t)&fbstate);
644 }
645#else
646 if (error || (fbstate & FB_DELAY) == 0) {
647 fbstate &= ~(FB_BUSY | FB_WAIT | FB_DELAY);
648 if (fbstate & FB_WANTED) {
649 fbstate &= ~FB_WANTED;
650 wakeup((caddr_t)&fbstate);
651 }
652 }
653 if (fbstate & FB_DELAY) {
654 fbstate &= ~FB_DELAY;
655 fbstate |= FB_DELAY2;
656 }
657#endif
658#endif /* CPU_SINGLE */
659 splx(s);
660}
661
662static int
663fbinit(fbp)
664 struct fbreg *fbp;
665{
666 fblock();
667
668 fbp->fb_command = FB_COPEN;
669 fbstart(fbp, 1);
670 if (fbp->fb_result != FB_ROK) {
671 fbunlock(0);
672 return (FB_RERROR);
673 }
674
675 fbp->fb_command = FB_CUNSETCURSOR;
676 fbstart(fbp, 0);
677
678 fbunlock(0);
679
680 return (FB_ROK);
681}
682
683static void
684fbreset(fbp)
685 struct fbreg *fbp;
686{
687 fblock();
688
689 fbp->fb_command = FB_CUNSETCURSOR;
690 fbstart(fbp, 1);
691
692 fbp->fb_command = FB_CCLOSE;
693 fbstart(fbp, 0);
694
695 fbunlock(0);
696}
697#endif /* NFB */