Commit | Line | Data |
---|---|---|
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 | ||
50 | extern 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 | ||
65 | static 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 | */ | |
75 | int fbprobe(), fbattach(); | |
76 | ||
77 | struct iop_device *fbinfo[NFB]; | |
78 | struct 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 */ | |
86 | static struct fb_softc fb_softc[NFB]; | |
87 | static struct fbreg fbreg[NFB]; | |
88 | static int fbstate; | |
89 | static struct fbreg *last_fb; | |
90 | ||
91 | static 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 | ||
111 | static void fblock(), fbunlock(), fbreset(); | |
112 | static 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 | ||
126 | typedef struct fbreg *fbregp; | |
127 | int fb_waiting; | |
128 | ||
129 | Xfb_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 | ||
141 | static void | |
142 | fbwait() | |
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 | ||
153 | void | |
154 | fbstart(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 | ||
172 | void | |
173 | fbstart(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 | ||
193 | void | |
194 | fbcint(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 */ | |
225 | fbprobe(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 */ | |
270 | fbattach(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*/ | |
301 | fbopen(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*/ | |
332 | fbclose(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 | ||
365 | fbioctl(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 | ||
580 | fbmmap(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 | ||
609 | static void | |
610 | fblock() | |
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 | ||
626 | static void | |
627 | fbunlock(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 | ||
662 | static int | |
663 | fbinit(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 | ||
683 | static void | |
684 | fbreset(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 */ |