xref: /original-bsd/sys/news3400/fb/fb_start.c (revision 3705696b)
1 /*
2  * Copyright (c) 1992, 1993
3  *	The Regents of the University of California.  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_start.c,v 4.300 91/06/27 20:42:40 root Rel41 $ SONY
11  *
12  *	@(#)fb_start.c	8.1 (Berkeley) 06/11/93
13  */
14 
15 #include <sys/param.h>
16 #include <sys/systm.h>
17 
18 #ifdef IPC_MRX
19 #include "../../iop/framebuf.h"
20 #include "../../iop/fbreg.h"
21 #include "page.h"
22 #else
23 #include <news3400/iop/framebuf.h>
24 #include <news3400/iop/fbreg.h>
25 #endif
26 
27 #include <news3400/fb/fbdefs.h>
28 
29 #ifdef CPU_SINGLE
30 #include <machine/cpu.h>
31 extern struct tty cons;
32 extern int cnstart();
33 #define PRE_EMPT	need_resched()
34 #endif
35 
36 static struct fbdev	*cfb = 0;
37 static lPoint		mp;
38 #ifdef CPU_SINGLE
39 static int		curs_pending = 0;
40 #endif
41 
42 extern struct fbdevsw	fbdevsw[];
43 extern int		nfbdev;
44 
45 #ifdef CPU_SINGLE
46 extern char	*ext_fnt_addr[];
47 extern char	*ext_fnt24_addr[];
48 #else
49 extern char	**ext_fnt_addr;
50 extern char	**ext_fnt24_addr;
51 #endif
52 
53 static char copyfuncv[MAXPLANE] = {
54 	BF_S, BF_S, BF_S, BF_S, BF_S, BF_S, BF_S, BF_S,		/* SRC */
55 	BF_S, BF_S, BF_S, BF_S, BF_S, BF_S, BF_S, BF_S,		/* SRC */
56 	BF_S, BF_S, BF_S, BF_S, BF_S, BF_S, BF_S, BF_S		/* SRC */
57 };
58 
59 unsigned short fb_color_pallet_def[48] = {	/* define initial color */
60 /*	R,	G,	B	*/
61 	0,	0,	0,
62 	0,	0,	0x44,
63 	0,	0x44,	0,
64 	0,	0x44,	0x44,
65 	0x44,	0,	0,
66 	0x44,	0,	0x44,
67 	0x44,	0x44,	0,
68 	0x44,	0x44,	0x44,
69 	0x88,	0x88,	0x88,
70 	0,	0,	0xff,
71 	0,	0xff,	0,
72 	0,	0xff,	0xff,
73 	0xff,	0,	0,
74 	0xff,	0,	0xff,
75 	0xff,	0xff,	0,
76 	0xff,	0xff,	0xff
77 };
78 
79 unsigned short fb_gray_pallet_def[48] = {	/* define initial color */
80 /*	R,	G,	B	*/
81 	0xff,	0xff,	0xff,
82 	0xff,	0xff,	0,
83 	0xff,	0,	0xff,
84 	0xff,	0,	0,
85 	0,	0xff,	0xff,
86 	0,	0xff,	0,
87 	0,	0,	0xff,
88 	0x88,	0x88,	0x88,
89 	0x44,	0x44,	0x44,
90 	0x44,	0x44,	0,
91 	0x44,	0,	0x44,
92 	0x44,	0,	0,
93 	0,	0x44,	0x44,
94 	0,	0x44,	0,
95 	0,	0,	0x44,
96 	0,	0,	0
97 };
98 
99 static int bitmap_use;		/* shared variable for bitmap exclusion ctrl */
100 
101 #ifdef IPC_MRX
102 struct fb_map rommap;
103 #endif
104 
105 #ifdef CPU_SINGLE
106 void
107 lock_bitmap()
108 {
109 	int s;
110 
111 	/* wait(bitmap_use) */
112 	s = splbitmap();
113 	while (bitmap_use & FB_BUSY) {
114 		bitmap_use |= FB_WANTED;
115 		sleep((caddr_t)&bitmap_use, FBPRI);
116 	}
117 	bitmap_use |= FB_BUSY;
118 	splx(s);
119 }
120 
121 void
122 unlock_bitmap()
123 {
124 	int s;
125 
126 	/* signal(bitmap_use) */
127 	s = splbitmap();
128 	if (bitmap_use & FB_WANTED)
129 		wakeup((caddr_t)&bitmap_use);
130 	bitmap_use &= ~(FB_BUSY|FB_WANTED);
131 	splx(s);
132 }
133 
134 lock_bitmap_poll()
135 {
136 	int s;
137 
138 	/* wait(bitmap_use) */
139 
140 	s = splbitmap();
141 	if (bitmap_use & (FB_BUSY|FB_WANTED)) {
142 		splx(s);
143 		return (1);
144 	}
145 	bitmap_use |= FB_BUSY;
146 	splx(s);
147 	return (0);
148 }
149 
150 void
151 unlock_bitmap_poll()
152 {
153 	int s;
154 
155 	/* signal(bitmap_use) */
156 	s = splbitmap();
157 	if (bitmap_use & FB_WANTED)
158 		wakeup((caddr_t)&bitmap_use);
159 	bitmap_use &= ~(FB_BUSY|FB_WANTED);
160 	splx(s);
161 }
162 
163 bmlockedp()
164 {
165 	return (bitmap_use & (FB_WANTED|FB_BUSY));
166 }
167 
168 #ifdef NOTDEF /* KU:XXX not necessary for news3200 */
169 void
170 rop_wait(fb)
171 	struct fbdev *fb;
172 {
173 	register int s;
174 	int i;
175 
176 	s = splbitmap();
177 /* KU:XXX trick! */
178 #define in_interrupt()	((caddr_t)&fb < (caddr_t)MACH_CODE_START)
179 	if (in_interrupt() || (fb->run_flag & FB_WAITING)) {
180 		splx(s);
181 		fbbm_rop_wait(fb);
182 	} else {
183 		if (fbbm_ioctl(fb, FB_STATUSCHECK, 0) &
184 		    (FB_STATUS_ROPWAIT|FB_STATUS_ROPEXEC)) {
185 
186 			i = FB_INT_ROPDONE;
187 			fbbm_ioctl(fb, FB_INTENABLE, &i);
188 
189 			if (!(fbbm_ioctl(fb, FB_STATUSCHECK, 0) &
190 			    (FB_STATUS_ROPWAIT|FB_STATUS_ROPEXEC))) {
191 				i = FB_INT_ROPDONE;
192 				fbbm_ioctl(fb, FB_INTCLEAR, &i);
193 			} else {
194 				fb->run_flag |= FB_WAITING;
195 				sleep((caddr_t)&fb->run_flag, FBPRI);
196 			}
197 		}
198 		splx(s);
199 	}
200 }
201 #endif /* NOTDEF */
202 #else /* CPU_SINGLE */
203 #ifdef IPC_MRX
204 struct page {
205 	char bytes[NBPG];
206 };
207 extern struct page *page_base;
208 extern struct page *page_max;
209 extern struct map pagemap[];
210 extern struct pte_iop page_pt[];
211 extern int mapped_page;
212 
213 caddr_t
214 fb_map_page(map, n, prot)
215 	register int *map;
216 	register int n;
217 	register int prot;
218 {
219 	register int x;
220 	register struct pte_iop *p;
221 	register struct page *addr;
222 	register int s = spl7();
223 	static int last_x, last_n;
224 
225 	if (last_n >= n) {
226 		x = last_x;
227 	} else {
228 		rmfree(pagemap, last_n, last_x);
229 		mapped_page -= last_n;
230 		last_x = 0;
231 		last_n = 0;
232 		if ((x = rmalloc(pagemap, n)) <= 0) {
233 			splx(s);
234 			return (NULL);
235 		}
236 		mapped_page += n;
237 		last_x = x;
238 		last_n = n;
239 	}
240 	addr = page_base + x;
241 	prot |= PG_PAGE;
242 
243 	for (p = page_pt + x; n > 0; p++, n--) {
244 		*(int *)p = prot | *map++;
245 		tbis((caddr_t)addr);
246 		addr++;
247 	}
248 
249 	splx(s);
250 	return ((caddr_t)(page_base + x));
251 }
252 
253 caddr_t
254 fb_map_page2(map, n, prot)
255 	register int *map;
256 	register int n;
257 	register int prot;
258 {
259 	register int x;
260 	register struct pte_iop *p;
261 	register struct page *addr;
262 	register int s;
263 
264 	if (n == 0)
265 		return (NULL);
266 	s = spl7();
267 	if ((x = rmalloc(pagemap, n)) <= 0) {
268 		splx(s);
269 		return (NULL);
270 	}
271 	mapped_page += n;
272 	addr = page_base + x;
273 	prot |= PG_PAGE;
274 
275 	for (p = page_pt + x; n > 0; p++, n--) {
276 		*(int *)p = prot | (*map++);
277 		tbis((caddr_t)addr);
278 		addr++;
279 	}
280 
281 	splx(s);
282 	return ((caddr_t)(page_base + x));
283 }
284 #endif /* IPC_MRX */
285 #endif /* CPU_SINGLE */
286 
287 iopmemfbmap(addr, len, map)
288 	register caddr_t addr;
289 	register int len;
290 	register struct fb_map *map;
291 {
292 	register caddr_t *p;
293 	register int i;
294 
295 	map->fm_vaddr = addr;
296 	map->fm_offset = (unsigned)addr & CLOFSET;
297 	map->fm_count = len;
298 	len += map->fm_offset;
299 	p = map->fm_addr;
300 	addr -= map->fm_offset;
301 
302 	for (i = 0; i < NFBMAP && len > 0; i++) {
303 		*p++ = addr;
304 		addr += CLBYTES;
305 		len -= CLBYTES;
306 	}
307 }
308 
309 int
310 nofunc()
311 {
312 	return 0;
313 }
314 
315 int
316 error()
317 {
318 	return FB_RERROR;
319 }
320 
321 void
322 checkArea(fb, x, y)
323 	register struct fbdev *fb;
324 	register int *x, *y;
325 {
326 	if (*x < fb->moveArea.origin.x)
327 		*x = fb->moveArea.origin.x;
328 	if (*y < fb->moveArea.origin.y)
329 		*y = fb->moveArea.origin.y;
330 	if (*x >= (fb->moveArea.origin.x + fb->moveArea.extent.x))
331 		*x = (fb->moveArea.origin.x + fb->moveArea.extent.x) - 1;
332 	if (*y >= (fb->moveArea.origin.y + fb->moveArea.extent.y))
333 		*y = (fb->moveArea.origin.y + fb->moveArea.extent.y) - 1;
334 }
335 
336 cursorIn(fb, clip)
337 	register struct fbdev *fb;
338 	register lRectangle *clip;
339 {
340 	if (clip == 0)
341 		return (1);
342 	if (cfb != fb)
343 		return (0);
344 
345 	return (clip->origin.x < fb->cursorP.x + fb->size.x &&
346 		clip->origin.x + clip->extent.x > fb->cursorP.x &&
347 		clip->origin.y < fb->cursorP.y + fb->size.y &&
348 		clip->origin.y + clip->extent.y > fb->cursorP.y);
349 }
350 
351 void
352 fbcopy1(src, dst, fv)
353 	lPoint src;
354 	lPoint dst;
355 	char *fv;
356 {
357 	lRectangle sr, dr;
358 
359 	sr.origin = src;
360 	sr.extent = cfb->size;
361 	dr.origin = dst;
362 	if (cliprect2(&sr, &cfb->FrameRect, &dr, &cfb->VisRect)) {
363 		fbbm_rop_init(cfb, fv);
364 		fbbm_rop_copy(cfb, &sr, &dr.origin, 1, FB_PLANEALL);
365 	}
366 }
367 
368 void
369 fbcopy2(src, dst)
370 	lPoint src;
371 	lPoint dst;
372 {
373 	lRectangle sr, dr;
374 
375 	sr.origin = src;
376 	sr.extent = cfb->size;
377 	dr.origin = dst;
378 	if (cliprect2(&sr, &cfb->FrameRect, &dr, &cfb->FrameRect)) {
379 		fbbm_rop_init(cfb, copyfuncv);
380 		fbbm_rop_copy(cfb, &sr, &dr.origin, 0, FB_PLANEALL);
381 	}
382 }
383 
384 void
385 fbcopy3(src, dst)
386 	lPoint src;
387 	lPoint dst;
388 {
389 	lRectangle sr, dr;
390 
391 	sr.origin = src;
392 	sr.extent = cfb->size;
393 	dr.origin = dst;
394 	if (cliprect2(&sr, &cfb->FrameRect, &dr, &cfb->VisRect)) {
395 		fbbm_rop_init(cfb, copyfuncv);
396 		fbbm_rop_copy(cfb, &sr, &dr.origin, 0, FB_PLANEALL);
397 	}
398 }
399 
400 void
401 cursorOn(fb)
402 	register struct fbdev *fb;
403 {
404 #ifdef CPU_SINGLE
405 	int s = splbitmap();
406 #endif
407 
408 	if (cfb == fb && fb->cursorShow && !fb->cursorVis) {
409 		if (fb->hard_cursor) {
410 			fbbm_cursor_on(fb);
411 		} else {
412 			fbcopy2(fb->cursorP, fb->SaveRect.origin);
413 			fbcopy1(fb->MaskRect.origin, fb->cursorP,
414 				fb->maskfuncv);
415 			fbcopy1(fb->CursorRect.origin, fb->cursorP,
416 				fb->curfuncv);
417 		}
418 		fb->cursorVis = 1;
419 	}
420 #ifdef CPU_SINGLE
421 	splx(s);
422 #endif
423 }
424 
425 void
426 cursorOff(fb)
427 	register struct fbdev *fb;
428 {
429 #ifdef CPU_SINGLE
430 	int s = splbitmap();
431 #endif
432 
433 	if (cfb == fb && fb->cursorShow && fb->cursorVis) {
434 		if (fb->hard_cursor)
435 			fbbm_cursor_off(fb);
436 		else
437 			fbcopy3(fb->SaveRect.origin, fb->cursorP);
438 		fb->cursorVis = 0;
439 	}
440 #ifdef CPU_SINGLE
441 	splx(s);
442 #endif
443 }
444 
445 void
446 softCursorCheck(fb, stype, srect, dtype, drect)
447 	struct fbdev *fb;
448 	char stype, dtype;
449 	lRectangle *srect, *drect;
450 {
451 	if (cfb == fb  && cfb->cursorVis &&
452 	    ((stype == BM_FB && cursorIn(fb, srect)) ||
453 	    (dtype == BM_FB && cursorIn(fb, drect))))
454 		cursorOff(cfb);
455 }
456 
457 void
458 cursorCheck(fb, stype, srect, dtype, drect)
459 	struct fbdev *fb;
460 	char stype, dtype;
461 	lRectangle *srect, *drect;
462 {
463 	if (!fb->hard_cursor)
464 		softCursorCheck(fb, stype, srect, dtype, drect);
465 }
466 
467 int
468 redrawCursor(fb)
469 	register struct fbdev *fb;
470 {
471 	int s;
472 	lPoint	tmp;
473 
474 	if (cfb == fb && fb->cursorSet) {
475 		s = spl7();
476 		tmp = mp;
477 		splx(s);
478 
479 #ifdef CPU_SINGLE
480 		s = splbitmap();
481 #endif
482 		if (fb->cursorP.x != tmp.x || fb->cursorP.y != tmp.y) {
483 			if (fb->cursorVis) {
484 				if (! fb->hard_cursor) {
485 					fbcopy3(fb->SaveRect.origin,
486 						fb->cursorP);
487 				}
488 			}
489 			fb->cursorP = tmp;
490 			if (fb->hard_cursor) {
491 				fbbm_cursor_off(fb);
492 				fbbm_cursor_move(fb);
493 			}
494 			if (fb->cursorVis) {
495 				if (fb->hard_cursor) {
496 					fbbm_cursor_on(fb);
497 				} else {
498 					fbcopy2(fb->cursorP,
499 						fb->SaveRect.origin);
500 					fbcopy1(fb->MaskRect.origin,
501 						fb->cursorP, fb->maskfuncv);
502 					fbcopy1(fb->CursorRect.origin,
503 						fb->cursorP, fb->curfuncv);
504 				}
505 			}
506 		}
507 #ifdef CPU_SINGLE
508 		splx(s);
509 #endif
510 	}
511 	return (0);
512 }
513 
514 void
515 updateCursor(x, y, flag)
516 	int *x, *y;
517 	int flag;
518 {
519 	int s;
520 
521 	if (cfb && cfb->cursorSet) {
522 		checkArea(cfb, x, y);
523 		s = spl7();
524 		mp.x = *x - cfb->hot.x;
525 		mp.y = *y - cfb->hot.y;
526 		splx(s);
527 #ifdef CPU_SINGLE
528 		if (flag || cfb->hard_cursor) {
529 			curs_pending = 0;
530 			redrawCursor(cfb);
531 		} else if (cfb->type == FB_LCDM) {
532 			if (!lock_bitmap_poll()) {
533 				curs_pending = 0;
534 				redrawCursor(cfb);
535 				unlock_bitmap_poll();
536 			} else {
537 				curs_pending = 1;
538 			}
539 		}
540 #else
541 		redrawCursor(cfb);
542 #endif
543 	}
544 }
545 
546 setCursor(fb, cursor)
547 	register struct fbdev *fb;
548 	register lCursor2  *cursor;
549 {
550 	register char *fv;
551 	register int f0, f1, i, color;
552 #ifdef CPU_SINGLE
553 	register int s = splbitmap();
554 #endif
555 	int	data;
556 
557 	if (cfb == fb) {
558 		cursorOff(cfb);
559 		fb->cursorShow = 0;
560 		fb->cursorP.x += cfb->hot.x;
561 		fb->cursorP.y += cfb->hot.y;
562 #ifdef CPU_SINGLE
563 		data = FB_INT_VSYNC;
564 		fbbm_ioctl(fb, FB_INTCLEAR, &data);
565 #endif
566 		cfb = NULL;
567 	}
568 
569 	if (cursor) {
570 		fb->CursorRect = cursor->cursorRect;
571 		fb->MaskRect = cursor->maskRect;
572 		fb->SaveRect = cursor->saveRect;
573 		fb->moveArea = cursor->moveArea;
574 		fb->hot = cursor->hot;
575 		fb->size = cursor->size;
576 
577 		f0 = 0x4 | ((cursor->func >> 2) & 0x3);
578 		f1 = 0x4 | (cursor->func & 0x3);
579 
580 		i = fb->fbNplane;
581 		fv = fb->curfuncv;
582 		color = cursor->cursor_color;
583 		while (i-- > 0) {
584 			*fv++ = (color & 1) ? f1 : f0;
585 			color >>= 1;
586 		}
587 
588 		i = fb->fbNplane;
589 		fv = fb->maskfuncv;
590 		color = cursor->mask_color;
591 		while (i-- > 0) {
592 			*fv++ = (color & 1) ? f1 : f0;
593 			color >>= 1;
594 		}
595 
596 		checkArea(fb, &fb->cursorP.x, &fb->cursorP.y);
597 		fb->cursorP.x -= fb->hot.x;
598 		fb->cursorP.y -= fb->hot.y;
599 		fb->cursorSet = 1;
600 		fb->cursorShow = 0;
601 		fb->cursorVis = 0;
602 		if (fb->hard_cursor) {
603 			fbbm_cursor_off(fb);
604 			fbbm_cursor_set(fb, cursor->cursor_color, cursor->mask_color);
605 			fbbm_cursor_move(fb);
606 		}
607 	} else {
608 		fb->cursorP.x = fb->VisRect.extent.x / 2;
609 		fb->cursorP.y = fb->VisRect.extent.y / 2;
610 		fb->cursorSet = 0;
611 		fb->cursorShow = 0;
612 		fb->cursorVis = 0;
613 		if (fb->hard_cursor)
614 			fbbm_cursor_off(fb);
615 	}
616 #ifdef CPU_SINGLE
617 	splx(s);
618 #endif
619 	return (FB_ROK);
620 }
621 
622 showCursor(fb)
623 	register struct fbdev *fb;
624 {
625 	int data;
626 #ifdef CPU_SINGLE
627 	register int s = splbitmap();
628 #endif
629 
630 	if (fb->cursorSet && !fb->cursorShow) {
631 		if (cfb && cfb != fb) {
632 			cursorOff(cfb);
633 			cfb->cursorShow = 0;
634 		}
635 		cfb = fb;
636 		fb->cursorShow = 1;
637 		mp = fb->cursorP;
638 		cursorOn(fb);
639 #ifdef CPU_SINGLE
640 		data = FB_INT_VSYNC;
641 		fbbm_ioctl(fb, FB_INTENABLE, &data);
642 		splx(s);
643 #endif
644 		return (FB_ROK);
645 	}
646 #ifdef CPU_SINGLE
647 	splx(s);
648 #endif
649 	return (FB_RERROR);
650 }
651 
652 
653 hideCursor(fb)
654 	register struct fbdev *fb;
655 {
656 	int data;
657 #ifdef CPU_SINGLE
658 	int s = splbitmap();
659 #endif
660 
661 	if (cfb == fb) {
662 		cursorOff(fb);
663 		fb->cursorShow = 0;
664 #ifdef CPU_SINGLE
665 		data = FB_INT_VSYNC;
666 		fbbm_ioctl(fb, FB_INTCLEAR, &data);
667 		splx(s);
668 #endif
669 		return (FB_ROK);
670 	}
671 #ifdef CPU_SINGLE
672 	splx(s);
673 #endif
674 	return (FB_RERROR);
675 }
676 
677 
678 moveCursor(fb, point)
679 	struct fbdev *fb;
680 	lPoint *point;
681 {
682 	if (cfb == fb) {
683 		updateCursor(&point->x, &point->y, 1);
684 		return (FB_ROK);
685 	}
686 	return (FB_RERROR);
687 }
688 
689 #ifdef CPU_SINGLE
690 rop_xint()
691 {
692 	register struct fbdev *fb;
693 	register int i;
694 	register int done = 0;
695 	int event, data;
696 	int s = splbitmap();
697 
698 	for (i = 0, fb = fbdev; i < nfbdev; i++, fb++) {
699 		if (fb->type && (event = fbbm_ioctl(fb, FB_INTCHECK, 0))) {
700 #ifdef notyet /* KU:XXX */
701 			intrcnt[INTR_BITMAP]++;
702 #endif
703 			done = 1;
704 			if (event & FB_INT_VSYNC) {
705 				data = FB_INT_VSYNC;
706 				fbbm_ioctl(fb, FB_INTCLEAR, &data);
707 				if (!lock_bitmap_poll()) {
708 					curs_pending = 0;
709 					redrawCursor(fb);
710 					unlock_bitmap_poll();
711 				} else {
712 					curs_pending = 1;
713 				}
714 				data = FB_INT_VSYNC;
715 				fbbm_ioctl(fb, FB_INTENABLE, &data);
716 			}
717 			if (event & FB_INT_ROPDONE) {
718 				if(fb->run_flag & FB_WAITING) {
719 					data = FB_INT_ROPDONE;
720 					fbbm_ioctl(fb, FB_INTCLEAR, &data);
721 					if (!(fbbm_ioctl(fb, FB_STATUSCHECK, 0)
722 					& (FB_STATUS_ROPWAIT|FB_STATUS_ROPEXEC))) {
723 						fb->run_flag &= ~FB_WAITING;
724 						wakeup(&(fb->run_flag));
725 					} else {
726 						data = FB_INT_ROPDONE|0x100;
727 						fbbm_ioctl(fb, FB_INTENABLE, &data);
728 					}
729 				}
730 			}
731 		}
732 	}
733 	splx(s);
734 	return (done);
735 }
736 #endif /* CPU_SINGLE */
737 
738 cliprect2(sr, sc, dr, dc)
739 	register lRectangle *sr;
740 	register lRectangle *sc;
741 	register lRectangle *dr;
742 	register lRectangle *dc;
743 {
744 	register int d;
745 
746 	/* src left/right edge */
747 	if ((d = sr->origin.x - sc->origin.x) < 0) {
748 		sr->extent.x += d;
749 		sr->origin.x -= d;
750 		dr->origin.x -= d;
751 		d = sr->extent.x - sc->extent.x;
752 	} else
753 		d += sr->extent.x - sc->extent.x;
754 	if (d > 0)
755 		sr->extent.x -= d;
756 
757 	/* src top/bottom edge */
758 	if ((d = sr->origin.y - sc->origin.y) < 0) {
759 		sr->extent.y += d;
760 		sr->origin.y -= d;
761 		dr->origin.y -= d;
762 		d = sr->extent.y - sc->extent.y;
763 	} else
764 		d += sr->extent.y - sc->extent.y;
765 	if (d > 0)
766 		sr->extent.y -= d;
767 
768 	if (sr->extent.x <= 0 || sr->extent.y <= 0)
769 		return (0);
770 
771 	/* dst left/right edge */
772 	if ((d = dr->origin.x - dc->origin.x) < 0) {
773 		dr->origin.x -= d;
774 		sr->extent.x += d;
775 		sr->origin.x -= d;
776 		d = sr->extent.x - dc->extent.x;
777 	} else
778 		d += sr->extent.x - dc->extent.x;
779 	if (d > 0)
780 		sr->extent.x -= d;
781 
782 	/* dst top/bottom edge */
783 	if ((d = dr->origin.y - dc->origin.y) < 0) {
784 		dr->origin.y -= d;
785 		sr->extent.y += d;
786 		sr->origin.y -= d;
787 		d = sr->extent.y - dc->extent.y;
788 	} else
789 		d += sr->extent.y - dc->extent.y;
790 	if (d > 0)
791 		sr->extent.y -= d;
792 
793 	if (sr->extent.x <= 0 || sr->extent.y <= 0)
794 		return (0);
795 
796 	dr->extent = sr->extent;
797 	return (1);
798 }
799 
800 cliprect(r, crp, p)
801 	register lRectangle *r;
802 	register lRectangle *crp;
803 	register lRectangle *p;
804 {
805 	register int d;
806 
807 	/* left edge */
808 	if ((d = r->origin.x - crp->origin.x) < 0) {
809 		r->extent.x += d;
810 		r->origin.x -= d;
811 		if (p) {
812 			p->extent.x += d;
813 			p->origin.x -= d;
814 		}
815 		d = r->extent.x - crp->extent.x;
816 	} else
817 		d += r->extent.x - crp->extent.x;
818 
819 	/* right edge */
820 	if (d > 0) {
821 		r->extent.x -= d;
822 		if (p)
823 			p->extent.x -= d;
824 	}
825 
826 	/* top edge */
827 	if ((d = r->origin.y - crp->origin.y) < 0) {
828 		r->extent.y += d;
829 		r->origin.y -= d;
830 		if (p) {
831 			p->extent.y += d;
832 			p->origin.y -= d;
833 		}
834 		d = r->extent.y - crp->extent.y;
835 	} else
836 		d += r->extent.y - crp->extent.y;
837 
838 	/* bottom edge */
839 	if (d > 0) {
840 		r->extent.y -= d;
841 		if (p)
842 			p->extent.y -= d;
843 	}
844 
845 	return (r->extent.x > 0 && r->extent.y > 0);
846 }
847 
848 getclip(fb, bmp, crp)
849 	struct fbdev *fb;
850 	lBitmap *bmp;
851 	lRectangle *crp;
852 {
853 	/* limit clip rectangle to bitmap rectangle */
854 	if (!cliprect(crp, &bmp->rect, (lRectangle*)0))
855 		return (0);
856 
857 	/* limit clip rectangle to frame buffer */
858 	if ((bmp->type == BM_FB) &&
859 	    !cliprect(crp, &fb->FrameRect, (lRectangle*)0))
860 		return (0);
861 	return (1);
862 }
863 
864 
865 clipsrc(fb, bmp)
866 	struct fbdev *fb;
867 	lBitmap *bmp;
868 {
869 	/* limit clip rectangle to frame buffer */
870 	if (bmp->type == BM_FB &&
871 	    !cliprect(&bmp->rect, &fb->FrameRect, (lRectangle*)0))
872 		return (0);
873 	return (1);
874 }
875 
876 
877 setrop(fb, func, pmask, fore, aux, trans, sbp, dbp)
878 	register struct fbdev *fb;
879 	register unsigned int func;
880 	int pmask;
881 	register int fore, aux;
882 	int trans;
883 	lBitmap *sbp, *dbp;
884 {
885 	register char *funcp;
886 	register int i;
887 	char tmp[4];
888 
889 	/* set plane register */
890 
891 	fb->Mode = 0;
892 	fb->Pmask = pmask;
893 	fb->func = func;
894 	fb->fore = fore;
895 	fb->aux = aux;
896 	fb->trans = trans;
897 
898 	if (sbp->depth > 1)
899 		fb->Mode |= 2;
900 
901 	if (dbp->depth > 1)
902 		fb->Mode |= 1;
903 
904 	/* set rop function register */
905 	func &= 0xf;
906 
907 	tmp[0] = TRANS(trans, (func & 0x0c) | (func>>2));
908 	tmp[1] = TRANS(trans, (func>>2) | ((func<<2) & 0x0c));
909 	tmp[2] = TRANS(trans, func);
910 	tmp[3] = TRANS(trans, (func<<2) & 0x0c | func & 3);
911 
912 	funcp = fb->funcvec;
913 	for (i = fb->fbNplane; --i >= 0;) {
914 		*funcp++ = tmp[((fore & 1) << 1) | (aux & 1)];
915 		fore >>= 1; aux >>= 1;
916 	}
917 	return (0);
918 }
919 
920 /*
921  * bitblt within frame buffer
922  */
923 
924 bitblt_fb(fb, sbp, srp, dbp, dpp, crp)
925 	register struct fbdev *fb;
926 	register lBitmap *sbp;	/* source bitmap (FB) */
927 	lRectangle *srp;	/* source rectangle */
928 	lBitmap *dbp;		/* destination bitmap (FB) */
929 	lPoint *dpp;		/* destination point */
930 	lRectangle *crp;	/* clip region in destination */
931 {
932 	lRectangle sr;
933 	lRectangle dr;
934 	register int wplane, i, j;
935 
936 	sr = *srp;
937 	dr.origin = *dpp;
938 	if (crp && !cliprect2(&sr, &sbp->rect, &dr, crp))
939 		return (0);
940 
941 	fbbm_rop_init(fb, fb->funcvec);
942 
943 	switch (fb->Mode) {
944 
945 	case MODE_1to1:
946 		fb->Pmask &= 1;
947 
948 	case MODE_NtoN:
949 
950 		fbbm_rop_copy(fb, &sr, &dr.origin, 0, fb->Pmask);
951 		break;
952 
953 	case MODE_1toN:
954 		fbbm_rop_copy(fb, &sr, &dr.origin, 1, fb->Pmask);
955 		break;
956 
957 	case MODE_Nto1:
958 		wplane = 1;
959 		for (i = 0, j = sbp->depth; i < j; i++) {
960 			if (fb->Pmask & wplane) {
961 				fbbm_rop_copy(fb, &sr, &dr.origin, i + 1,
962 				    fb->Pmask >> 16);
963 				break;
964 			}
965 			wplane <<= 1;
966 		}
967 		break;
968 	default:
969 		return (-1);
970 	}
971 	return (0);
972 }
973 
974 /*
975  * bitblt from main memory to frame buffer
976  */
977 
978 bitblt_tofb(fb, sbp, srp, dbp, dpp, crp)
979 	register struct fbdev *fb;
980 	register lBitmap *sbp;	/* source bitmap (MEM) */
981 	lRectangle *srp;	/* source rectangle */
982 	lBitmap *dbp;		/* destination bitmap (FB) */
983 	lPoint *dpp;		/* destination point */
984 	lRectangle *crp;	/* clip region in destination */
985 {
986 	register unsigned p;
987 	register struct fb_map *smap;
988 	register int i, n, m;
989 	lRectangle sr;
990 	lRectangle dr;
991 	register int wplane;
992 #ifdef IPC_MRX
993 	extern struct fb_map rommap;
994 	register int pages;
995 #endif
996 
997 	smap = (struct fb_map*)sbp->base;
998 
999 	sr = *srp;
1000 	dr.origin = *dpp;
1001 	if (crp && !cliprect2(&sr, &sbp->rect, &dr, crp))
1002 		return (0);
1003 	dr.extent = sr.extent;
1004 
1005 	/* transform source rectangle */
1006 	sr.origin.x -= sbp->rect.origin.x;
1007 	sr.origin.y -= sbp->rect.origin.y;
1008 
1009 	/*
1010 	 * check memory map specification
1011 	 */
1012 	p = smap->fm_offset;
1013 #ifdef IPC_MRX
1014 	pages = btoc(smap->fm_offset + smap->fm_count);
1015 	rommap.fm_vaddr = fb_map_page(smap->fm_addr, pages,
1016 		    fb->cache_off ? PG_S|PG_WP|PG_CI : PG_S|PG_WP);
1017 	rommap.fm_offset = 0;
1018 	smap = &rommap;
1019 #endif
1020 
1021 	wplane = 1;
1022 
1023 	fbbm_rop_winit(fb);
1024 
1025 	switch (fb->Mode) {
1026 	case MODE_1to1:
1027 		fbbm_rop_write(fb, smap, p, sbp->width,
1028 			       &sr, &dr, fb->Pmask & 0x01);
1029 		break;
1030 	case MODE_1toN:
1031 		fbbm_rop_write(fb, smap, p, sbp->width,
1032 			       &sr, &dr, fb->Pmask);
1033 		break;
1034 	case MODE_Nto1:
1035 		m = sbp->width * sbp->rect.extent.y;
1036 		for (i = 0; i < sbp->depth; i++, wplane <<= 1) {
1037 			if (fb->Pmask & wplane) {
1038 				p += (m * i) << 1;
1039 				fbbm_rop_write(fb, smap, p, sbp->width,
1040 					       &sr, &dr, wplane);
1041 				break;
1042 			}
1043 			wplane <<= 1;
1044 		}
1045 		break;
1046 	case MODE_NtoN:
1047 		n = min(sbp->depth, fb->fbNplane);
1048 		m = sbp->width * sbp->rect.extent.y;
1049 		p += (m << 1) * n;
1050 		wplane = 1 << (n - 1);
1051 		for (i = n; i > 0; i--) {
1052 			/* get next plane */
1053 			p -= m << 1;
1054 			if (fb->Pmask & wplane)
1055 				fbbm_rop_write(fb, smap, p, sbp->width,
1056 					       &sr, &dr, wplane);
1057 			/* next plane mask */
1058 			wplane >>= 1;
1059 		}
1060 		break;
1061 	default:
1062 		return (-1);
1063 	}
1064 	return (0);
1065 }
1066 
1067 /*
1068  * bitblt from frame buffer to main memroy
1069  */
1070 
1071 bitblt_tomem(fb, sbp, srp, dbp, dpp, crp)
1072 	struct fbdev *fb;
1073 	lBitmap *sbp;		/* source bitmap (FB) */
1074 	lRectangle *srp;	/* source rectangle */
1075 	lBitmap *dbp;		/* destination bitmap (MEM) */
1076 	lPoint *dpp;		/* destination point */
1077 	lRectangle *crp;	/* clip region in destination */
1078 {
1079 	register struct fb_map *dmap;
1080 	register unsigned p;
1081 	register int i, n, m;
1082 	lRectangle sr;
1083 	lRectangle dr;
1084 	int plane;
1085 #ifdef IPC_MRX
1086 	extern struct fb_map rommap;
1087 	register int pages;
1088 #endif
1089 
1090 	dmap = (struct fb_map*)dbp->base;
1091 
1092 	sr = *srp;
1093 	dr.origin = *dpp;
1094 	if (crp && !cliprect2(&sr, &sbp->rect, &dr, crp))
1095 		return (0);
1096 	dr.extent = sr.extent;
1097 
1098 	dr.origin.x -= dbp->rect.origin.x;
1099 	dr.origin.y -= dbp->rect.origin.y;
1100 
1101 	p = dmap->fm_offset;
1102 #ifdef IPC_MRX
1103 	pages = btoc(dmap->fm_offset + dmap->fm_count);
1104 	rommap.fm_vaddr = fb_map_page(dmap->fm_addr, pages, PG_S);
1105 	rommap.fm_offset = 0;
1106 	dmap = &rommap;
1107 #endif
1108 
1109 	plane = 1;
1110 
1111 /*	Wait for rop busy */
1112 
1113 	switch (fb->Mode) {
1114 
1115 	case MODE_1to1:
1116 		if (fb->Pmask & plane)
1117 			fbbm_rop_read(fb, dmap, p, dbp->width,
1118 				      &sr, &dr, 0, 0);
1119 		break;
1120 
1121 	case MODE_1toN:
1122 		m = (dbp->width * dbp->rect.extent.y) << 1;
1123 		for (i = 0; i < dbp->depth; i++) {
1124 			if (fb->Pmask & plane)
1125 				fbbm_rop_read(fb, dmap, p, dbp->width,
1126 					      &sr, &dr, 0, i);
1127 			/* next plane */
1128 			p += m;
1129 			plane <<= 1;
1130 		}
1131 		break;
1132 
1133 	case MODE_Nto1:
1134 		for (i = 0; i < sbp->depth; i++, plane <<= 1) {
1135 			if (fb->Pmask & plane) {
1136 				fbbm_rop_read(fb, dmap, p, dbp->width,
1137 					      &sr, &dr, i, 0);
1138 				break;
1139 			}
1140 		}
1141 		break;
1142 
1143 	case MODE_NtoN:
1144 		n = min(dbp->depth, fb->fbNplane);
1145 		m = (dbp->width * dbp->rect.extent.y) << 1;
1146 		for (i = 0; i < n; i++) {
1147 			if (fb->Pmask & plane)
1148 				fbbm_rop_read(fb, dmap, p, dbp->width,
1149 					      &sr, &dr, i, i);
1150 			/* next plane */
1151 			p += m;
1152 			plane <<= 1;
1153 		}
1154 
1155 		break;
1156 
1157 	default:
1158 		return (-1);
1159 	}
1160 
1161 	return (0);
1162 }
1163 
1164 bitblt_mem(fb, sbp, srp, dbp, dpp, crp)
1165 	struct fbdev *fb;
1166 	register lBitmap *sbp;
1167 	lRectangle *srp;
1168 	register lBitmap *dbp;
1169 	lPoint *dpp;
1170 	lRectangle *crp;
1171 {
1172 	register int i;
1173 	register int plane;
1174 	register struct fb_map *smap, *dmap;
1175 	register unsigned int ps, pd;
1176 	lRectangle sr;
1177 	lRectangle dr;
1178 #ifdef IPC_MRX
1179 	static struct fb_map drommap;
1180 	int spages, dpages;
1181 #endif
1182 
1183 	smap = (struct fb_map*)sbp->base;
1184 	dmap = (struct fb_map*)dbp->base;
1185 
1186 	sr = *srp;
1187 	dr.origin = *dpp;
1188 	if (crp && !cliprect2(&sr, &sbp->rect, &dr, crp))
1189 		return (0);
1190 
1191 	/* normalize source/destination coordinates */
1192 	sr.origin.x -= sbp->rect.origin.x;
1193 	sr.origin.y -= sbp->rect.origin.y;
1194 	dr.origin.x -= dbp->rect.origin.x;
1195 	dr.origin.y -= dbp->rect.origin.y;
1196 
1197 	ps = smap->fm_offset;
1198 	pd = dmap->fm_offset;
1199 #ifdef IPC_MRX
1200 	spages = btoc(smap->fm_offset + smap->fm_count);
1201 	dpages = btoc(dmap->fm_offset + dmap->fm_count);
1202 	rommap.fm_vaddr = fb_map_page2(smap->fm_addr, spages, PG_S|PG_WP);
1203 	rommap.fm_offset = 0;
1204 	drommap.fm_vaddr = fb_map_page2(dmap->fm_addr, dpages, PG_S);
1205 	drommap.fm_offset = 0;
1206 	smap = &rommap;
1207 	dmap = &drommap;
1208 #endif
1209 
1210 	plane = 0x1;	/* plane 0 */
1211 
1212 	switch (fb->Mode) {
1213 
1214 	case MODE_1to1:
1215 		if (fb->Pmask & plane) {
1216 			mem_to_mem(fb->funcvec[0],
1217 				   smap, ps, sbp->width, dmap, pd, dbp->width,
1218 				   &sr, &dr.origin);
1219 		}
1220 		break;
1221 
1222 	case MODE_1toN:
1223 		for (i = 0; i < dbp->depth; i++) {
1224 			if (fb->Pmask & plane) {
1225 				mem_to_mem(fb->funcvec[i],
1226 					   smap, ps, sbp->width,
1227 					   dmap, pd, dbp->width,
1228 					   &sr, &dr.origin);
1229 			}
1230 			pd += (dbp->width * dbp->rect.extent.y) << 1;
1231 			plane <<= 1;
1232 		}
1233 		break;
1234 
1235 	case MODE_Nto1:
1236 		for (i = 0; i < sbp->depth; i++, plane <<= 1) {
1237 			if (fb->Pmask & plane)
1238 				break;
1239 		}
1240 		if (i < sbp->depth) {
1241 			ps += (sbp->width * sbp->rect.extent.y * i) << 1;
1242 			mem_to_mem(fb->funcvec[i],
1243 				   smap, ps, sbp->width, dmap, pd, dbp->width,
1244 				   &sr, &dr.origin);
1245 		}
1246 		break;
1247 
1248 	case MODE_NtoN:
1249 		for (i = 0; i < dbp->depth; i++) {
1250 			if (fb->Pmask & plane) {
1251 				mem_to_mem(fb->funcvec[i],
1252 					   smap, ps, sbp->width,
1253 					   dmap, pd, dbp->width,
1254 					   &sr, &dr.origin);
1255 			}
1256 			ps += (sbp->width * sbp->rect.extent.y) << 1;
1257 			pd += (dbp->width * dbp->rect.extent.y) << 1;
1258 			plane <<= 1;
1259 		}
1260 		break;
1261 
1262 	default:
1263 		return (-1);
1264 	}
1265 #ifdef IPC_MRX
1266 	page_unmap(rommap.fm_vaddr, spages);
1267 	page_unmap(drommap.fm_vaddr, dpages);
1268 #endif
1269 	return (0);
1270 }
1271 
1272 bitblt_nop()
1273 {
1274 	return (0);
1275 }
1276 
1277 /*
1278  * bitblt from '0' bitmap to frame buffer
1279  */
1280 
1281 bitblt_0tofb(fb, sbp, srp, dbp, dpp, crp)
1282 	register struct fbdev *fb;
1283 	lBitmap *sbp;		/* source bitmap (0) */
1284 	lRectangle *srp;	/* source rectangle */
1285 	lBitmap *dbp;		/* destination bitmap (FB) */
1286 	lPoint *dpp;		/* destination point */
1287 	lRectangle *crp;	/* clip region in destination */
1288 {
1289 	lRectangle sr;
1290 	lRectangle dr;
1291 
1292 	sr = *srp;
1293 	dr.origin = *dpp;
1294 	if (crp && !cliprect2(&sr, &sbp->rect, &dr, crp))
1295 		return (0);
1296 	dr.extent = sr.extent;
1297 
1298 	switch (fb->Mode) {
1299 
1300 	case MODE_1to1:
1301 	case MODE_Nto1:
1302 		fb->Pmask &= 1;
1303 		break;
1304 	case MODE_1toN:
1305 	case MODE_NtoN:
1306 		break;
1307 
1308 	default:
1309 		return (-1);
1310 	}
1311 
1312 	/*
1313 	 * write data into ROP data register
1314 	 */
1315 
1316 	fbbm_rop_cinit(fb, fb->Pmask, 0);
1317 	fbbm_rop_clear(fb, &dr);
1318 
1319 	return (0);
1320 }
1321 
1322 /*
1323  * bitblt from '1' bitmap to frame buffer
1324  */
1325 
1326 bitblt_1tofb(fb, sbp, srp, dbp, dpp, crp)
1327 	register struct fbdev *fb;
1328 	lBitmap *sbp;		/* source bitmap (1) */
1329 	lRectangle *srp;	/* source rectangle */
1330 	lBitmap *dbp;		/* destination bitmap (FB) */
1331 	lPoint *dpp;		/* destination point */
1332 	lRectangle *crp;	/* clip region in destination */
1333 {
1334 	lRectangle sr;
1335 	lRectangle dr;
1336 
1337 	sr = *srp;
1338 	dr.origin = *dpp;
1339 	if (crp && !cliprect2(&sr, &sbp->rect, &dr, crp))
1340 		return (0);
1341 	dr.extent = sr.extent;
1342 
1343 	switch (fb->Mode) {
1344 
1345 	case MODE_1to1:
1346 	case MODE_Nto1:
1347 		/* plane mask set */
1348 		fb->Pmask &= 0x1;
1349 		break;
1350 
1351 	case MODE_1toN:
1352 	case MODE_NtoN:
1353 		break;
1354 
1355 	default:
1356 		return (-1);
1357 	}
1358 
1359 	/*
1360 	 * write data into ROP data register
1361 	 */
1362 
1363 	fbbm_rop_cinit(fb, fb->Pmask, 1);
1364 	fbbm_rop_clear(fb, &dr);
1365 
1366 	return (0);
1367 }
1368 
1369 #ifndef CPU_DOUBLE
1370 /*
1371  * bitblt from '0' bitmap to main memory
1372  */
1373 
1374 bitblt_0tomem(fb, sbp, srp, dbp, dpp, crp)
1375 	register struct fbdev *fb;
1376 	lBitmap *sbp;		/* source bitmap (0) */
1377 	lRectangle *srp;	/* source rectangle */
1378 	register lBitmap *dbp;	/* destination bitmap (MEM) */
1379 	lPoint *dpp;		/* destination point */
1380 	lRectangle *crp;	/* clip region in destination */
1381 {
1382 	register struct fb_map *dmap;
1383 	register unsigned int p;
1384 	register int i, j;
1385 	register int plane;
1386 	lRectangle sr;
1387 	lRectangle dr;
1388 	int skip;
1389 
1390 	dmap = (struct fb_map*)dbp->base;
1391 
1392 	sr = *srp;
1393 	dr.origin = *dpp;
1394 	if (crp && !cliprect2(&sr, &sbp->rect, &dr, crp))
1395 		return (0);
1396 	dr.extent = sr.extent;
1397 
1398 	dr.origin.x -= dbp->rect.origin.x;
1399 	dr.origin.y -= dbp->rect.origin.y;
1400 
1401 	p = dmap->fm_offset;
1402 
1403 	plane = 0x1;
1404 
1405 	switch (fb->Mode) {
1406 
1407 	case MODE_1to1:
1408 		if (fb->Pmask & plane)
1409 			mem_clear(fb->funcvec[0], dmap, p, dbp->width, &dr, 0);
1410 		break;
1411 
1412 	case MODE_1toN:
1413 	case MODE_NtoN:
1414 		skip = (dbp->width * dbp->rect.extent.y) << 1;
1415 		for (i = 0, j = dbp->depth; i < j; i++) {
1416 			if (fb->Pmask & plane)
1417 				mem_clear(fb->funcvec[i], dmap, p, dbp->width,
1418 				    &dr, 0);
1419 			/* next plane */
1420 			p += skip;
1421 			plane <<= 1;
1422 		}
1423 		break;
1424 
1425 	case MODE_Nto1:
1426 		for (i = 0, j = sbp->depth; i < j; i++) {
1427 			if (fb->Pmask & plane) {
1428 				mem_clear(fb->funcvec[i], dmap, p, dbp->width,
1429 				    &dr, 0);
1430 				break;
1431 			}
1432 			plane <<= 1;
1433 		}
1434 		break;
1435 
1436 	default:
1437 		return (1);
1438 	}
1439 
1440 	return (0);
1441 }
1442 
1443 /*
1444  * bitblt from '1' bitmap to main memory
1445  */
1446 
1447 bitblt_1tomem(fb, sbp, srp, dbp, dpp, crp)
1448 	register struct fbdev *fb;
1449 	lBitmap *sbp;		/* source bitmap (1) */
1450 	lRectangle *srp;	/* source rectangle */
1451 	register lBitmap *dbp;	/* destination bitmap (MEM) */
1452 	lPoint *dpp;		/* destination point */
1453 	lRectangle *crp;	/* clip region in destination */
1454 {
1455 	register struct fb_map *dmap;
1456 	register unsigned p;
1457 	register int i, j;
1458 	register int plane;
1459 	lRectangle sr;
1460 	lRectangle dr;
1461 	int skip;
1462 
1463 	dmap = (struct fb_map*)dbp->base;
1464 
1465 	sr = *srp;
1466 	dr.origin = *dpp;
1467 	if (crp && !cliprect2(&sr, &sbp->rect, &dr, crp))
1468 		return (0);
1469 	dr.extent = sr.extent;
1470 
1471 	dr.origin.x -= dbp->rect.origin.x;
1472 	dr.origin.y -= dbp->rect.origin.y;
1473 
1474 	p = dmap->fm_offset;
1475 
1476 	plane = 0x1;
1477 
1478 	switch (fb->Mode) {
1479 
1480 	case MODE_1to1:
1481 		if (fb->Pmask & plane)
1482 			mem_clear(fb->funcvec[0], dmap, p, dbp->width, &dr, 1);
1483 		break;
1484 
1485 	case MODE_1toN:
1486 	case MODE_NtoN:
1487 		skip = (dbp->width * dbp->rect.extent.y) << 1;
1488 		for (i = 0, j = dbp->depth; i < j; i++) {
1489 			if (fb->Pmask & plane)
1490 				mem_clear(fb->funcvec[i], dmap, p, dbp->width,
1491 				    &dr, 1);
1492 			/* next plane */
1493 			p += skip;
1494 			plane <<= 1;
1495 		}
1496 		break;
1497 
1498 	case MODE_Nto1:
1499 		for (i = 0, j = sbp->depth; i < j; i++) {
1500 			if (fb->Pmask & plane) {
1501 				mem_clear(fb->funcvec[i], dmap, p, dbp->width,
1502 				    &dr, 1);
1503 				break;
1504 			}
1505 			plane <<= 1;
1506 		}
1507 		break;
1508 
1509 	default:
1510 		return (1);
1511 	}
1512 
1513 	return (0);
1514 }
1515 #endif /* !CPU_DOUBLE */
1516 
1517 int
1518 (*sel_ropfunc(stype, dtype))()
1519 	int stype;	/* source bitmap type */
1520 	int dtype;	/* dest bitmap type */
1521 {
1522 	if (dtype == BM_0)
1523 		return (bitblt_nop);
1524 	if (dtype == BM_1)
1525 		return (bitblt_nop);
1526 
1527 #ifdef CPU_DOUBLE
1528 	switch (stype) {
1529 	case BM_FB:
1530 		return (dtype == BM_FB) ? bitblt_fb : bitblt_tomem;
1531 		break;
1532 
1533 	case BM_MEM:
1534 		return (dtype == BM_FB) ? bitblt_tofb : bitblt_mem;
1535 		break;
1536 
1537 	case BM_0:
1538 		return (dtype == BM_FB) ? bitblt_0tofb : bitblt_nop;
1539 		break;
1540 	case BM_1:
1541 		return (dtype == BM_FB) ? bitblt_1tofb : bitblt_nop;
1542 		break;
1543 	}
1544 #else /* CPU_DOUBLE */
1545 	switch (stype) {
1546 	case BM_FB:
1547 		return (dtype == BM_FB) ? bitblt_fb : bitblt_tomem;
1548 		break;
1549 
1550 	case BM_MEM:
1551 		return (dtype == BM_FB) ? bitblt_tofb : bitblt_mem;
1552 		break;
1553 
1554 	case BM_0:
1555 		return (dtype == BM_FB) ? bitblt_0tofb : bitblt_0tomem;
1556 		break;
1557 	case BM_1:
1558 		return (dtype == BM_FB) ? bitblt_1tofb : bitblt_1tomem;
1559 		break;
1560 	}
1561 #endif /* CPU_DOUBLE */
1562 
1563 	return (bitblt_nop);
1564 }
1565 
1566 bitbltcmd(fb, cmd)
1567 	register struct fbdev *fb;
1568 	register lBitblt *cmd;
1569 {
1570 	lRectangle cr;
1571 	int ret;
1572 
1573 	cr = cmd->destClip;
1574 
1575 	if (!getclip(fb, &cmd->destBitmap, &cr))
1576 		return (0);
1577 	if (!clipsrc(fb, &cmd->srcBitmap))
1578 		return (0);
1579 
1580 	if (setrop(fb, cmd->func, cmd->planemask, cmd->fore_color, cmd->aux_color,
1581 		cmd->transp, &cmd->srcBitmap, &cmd->destBitmap) < 0)
1582 		return (FB_RERROR);
1583 
1584 	cursorCheck(fb, cmd->srcBitmap.type, &cmd->srcRect,
1585 			cmd->destBitmap.type, &cr);
1586 
1587 	ret = (*sel_ropfunc(cmd->srcBitmap.type, cmd->destBitmap.type))
1588 	    (fb, &cmd->srcBitmap, &cmd->srcRect, &cmd->destBitmap, &cmd->destPoint, &cr);
1589 
1590 	cursorOn(fb);
1591 
1592 	return (FB_ROK);
1593 }
1594 
1595 static
1596 batch_bitblt_01tofb(fb, sbp, clip, sdp, n, sw)
1597 	register struct fbdev *fb;
1598 	lBitmap *sbp;	/* source bitmap (MEM) */
1599 	register lRectangle *clip;
1600 	register lSrcDest *sdp;
1601 	register int n;
1602 	int sw;
1603 {
1604 	register void (*rop_clear)();
1605 	lRectangle *srect = &sbp->rect;
1606 
1607 	switch (fb->Mode) {
1608 
1609 	case MODE_1to1:
1610 	case MODE_Nto1:
1611 		fb->Pmask &= 1;
1612 		break;
1613 
1614 	case MODE_1toN:
1615 	case MODE_NtoN:
1616 		break;
1617 
1618 	default:
1619 		return (FB_RERROR);
1620 	}
1621 	fbbm_rop_cinit(fb, fb->Pmask, sw);
1622 	rop_clear = fb->fbbm_op->fb_rop_clear;
1623 	while (--n >= 0) {
1624 		lRectangle sr;
1625 		lRectangle dr;
1626 
1627 		sr = sdp->srcRect;
1628 		dr.origin = sdp->destPoint;
1629 		if (cliprect2(&sr, srect, &dr, clip))
1630 			(*rop_clear)(fb, &dr);
1631 		sdp++;
1632 	}
1633 	return (FB_ROK);
1634 }
1635 
1636 static
1637 batch_bitblt_fb(fb, sbp, clip, sdp, n)
1638 	register struct fbdev *fb;
1639 	register lBitmap *sbp;
1640 	register lRectangle *clip;
1641 	register lSrcDest *sdp;
1642 	register int n;
1643 {
1644 	register int wplane, i, j;
1645 	lRectangle sr;
1646 	lRectangle dr;
1647 
1648 	fbbm_rop_init(fb, fb->funcvec);
1649 	switch (fb->Mode) {
1650 
1651 	case MODE_1to1:
1652 		fb->Pmask &= 1;
1653 		while (--n >= 0) {
1654 			sr = sdp->srcRect;
1655 			dr.origin = sdp->destPoint;
1656 			if (cliprect2(&sr, &sbp->rect, &dr, clip))
1657 				fbbm_rop_copy(fb, &sr, &dr.origin, 0, fb->Pmask);
1658 			sdp++;
1659 		}
1660 		break;
1661 
1662 	case MODE_NtoN:
1663 		while (--n >= 0) {
1664 			sr = sdp->srcRect;
1665 			dr.origin = sdp->destPoint;
1666 			if (cliprect2(&sr, &sbp->rect, &dr, clip))
1667 				fbbm_rop_copy(fb, &sr, &dr.origin, 0, fb->Pmask);
1668 			sdp++;
1669 		}
1670 		break;
1671 
1672 	case MODE_1toN:
1673 		while (--n >= 0) {
1674 			sr = sdp->srcRect;
1675 			dr.origin = sdp->destPoint;
1676 			if (cliprect2(&sr, &sbp->rect, &dr, clip))
1677 				fbbm_rop_copy(fb, &sr, &dr.origin, 1, fb->Pmask);
1678 			sdp++;
1679 		}
1680 		break;
1681 
1682 	case MODE_Nto1:
1683 		for (; --n >= 0; sdp++) {
1684 			sr = sdp->srcRect;
1685 			dr.origin = sdp->destPoint;
1686 			if (!cliprect2(&sr, &sbp->rect, &dr, clip))
1687 				continue;
1688 			wplane = 1;
1689 			for (i = 0, j = sbp->depth; i < j; i++) {
1690 				if (fb->Pmask & wplane) {
1691 					fbbm_rop_copy(fb, &sr, &dr.origin,
1692 							i + 1, fb->Pmask >> 16);
1693 					break;
1694 				}
1695 				wplane <<= 1;
1696 			}
1697 		}
1698 		break;
1699 
1700 	default:
1701 		return (FB_RERROR);
1702 	}
1703 }
1704 
1705 static
1706 batch_bitblt_tofb(fb, sbp, dbp, crp, sdp, n)
1707 	register struct fbdev *fb;
1708 	register lBitmap *sbp;	/* source bitmap (MEM) */
1709 	lBitmap *dbp;		/* destination bitmap (FB) */
1710 	lRectangle *crp;	/* clip region in destination */
1711 	register lSrcDest *sdp;
1712 	register int n;
1713 {
1714 	register unsigned p;
1715 	register struct fb_map *smap;
1716 	register int i, j, m;
1717 	lRectangle sr;
1718 	lRectangle dr;
1719 	register int wplane;
1720 #ifdef IPC_MRX
1721 	extern struct fb_map rommap;
1722 	register int pages;
1723 #endif
1724 
1725 	fbbm_rop_winit(fb);
1726 	while (--n >= 0) {
1727 		sr = sdp->srcRect;
1728 		dr.origin = sdp->destPoint;
1729 		if (crp && !cliprect2(&sr, &sbp->rect, &dr, crp)) {
1730 			sdp++;
1731 			continue;
1732 		}
1733 		dr.extent = sr.extent;
1734 
1735 		/* transform source rectangle */
1736 		sr.origin.x -= sbp->rect.origin.x;
1737 		sr.origin.y -= sbp->rect.origin.y;
1738 
1739 		/*
1740 		 * check memory map specification
1741 		 */
1742 		smap = (struct fb_map*)sbp->base;
1743 		p = smap->fm_offset;
1744 #ifdef IPC_MRX
1745 		pages = btoc(smap->fm_offset + smap->fm_count);
1746 		rommap.fm_vaddr = fb_map_page(smap->fm_addr, pages,
1747 			    fb->cache_off ? PG_S|PG_WP|PG_CI : PG_S|PG_WP);
1748 		rommap.fm_offset = 0;
1749 		smap = &rommap;
1750 #endif
1751 
1752 		wplane = 1;
1753 
1754 		switch (fb->Mode) {
1755 		case MODE_1to1:
1756 			fbbm_rop_write(fb, smap, p, sbp->width,
1757 				       &sr, &dr, fb->Pmask & 0x01);
1758 			break;
1759 		case MODE_1toN:
1760 			fbbm_rop_write(fb, smap, p, sbp->width,
1761 				       &sr, &dr, fb->Pmask);
1762 			break;
1763 		case MODE_Nto1:
1764 			m = sbp->width * sbp->rect.extent.y;
1765 			for (i = 0; i < sbp->depth; i++, wplane <<= 1) {
1766 				if (fb->Pmask & wplane) {
1767 					p += (m * i) << 1;
1768 					fbbm_rop_write(fb, smap, p, sbp->width,
1769 						       &sr, &dr, wplane);
1770 					break;
1771 				}
1772 				wplane <<= 1;
1773 			}
1774 			break;
1775 		case MODE_NtoN:
1776 			j = min(sbp->depth, fb->fbNplane);
1777 			m = sbp->width * sbp->rect.extent.y;
1778 			p += (m << 1) * j;
1779 			wplane = 1 << (j - 1);
1780 			for (i = j; i > 0; i--) {
1781 				/* get next plane */
1782 				p -= m << 1;
1783 				if (fb->Pmask & wplane)
1784 					fbbm_rop_write(fb, smap, p, sbp->width,
1785 						       &sr, &dr, wplane);
1786 				/* next plane mask */
1787 				wplane >>= 1;
1788 			}
1789 			break;
1790 		default:
1791 			return (-1);
1792 		}
1793 		sdp++;
1794 	}
1795 	return (0);
1796 }
1797 
1798 batchbitbltcmd(fb, cmd)
1799 	register struct fbdev *fb;
1800 	register lBatchBitblt *cmd;
1801 {
1802 	register int n;
1803 	register lSrcDest *sdp;
1804 	register int (*blt)();
1805 	lRectangle cr;
1806 #ifdef CPU_SINGLE
1807 	struct fb_map *map;
1808 	unsigned int p;
1809 #endif
1810 	int error;
1811 
1812 	if (setrop(fb, cmd->func, cmd->planemask,
1813 	    cmd->fore_color, cmd->aux_color,
1814 	    cmd->transp, &cmd->srcBitmap, &cmd->destBitmap) < 0)
1815 		return (FB_RERROR);
1816 
1817 	cr = cmd->destClip;
1818 
1819 	if (!getclip(fb, &cmd->destBitmap, &cr))
1820 		return (FB_ROK);
1821 	if (!clipsrc(fb, &cmd->srcBitmap))
1822 		return (0);
1823 #ifdef CPU_SINGLE
1824 	map = (struct fb_map *)(cmd->srcDestList);
1825 	p = map->fm_offset;
1826 	sdp = (lSrcDest *)TypeAt(map, p);
1827 #else
1828 	sdp = cmd->srcDestList;
1829 #endif
1830 	n = cmd->nSrcDest;
1831 
1832 	cursorCheck(fb, cmd->srcBitmap.type, &cmd->srcBitmap.rect,
1833 	    cmd->destBitmap.type, &cr);
1834 
1835 	blt = sel_ropfunc(cmd->srcBitmap.type, cmd->destBitmap.type);
1836 	if (blt == bitblt_0tofb || blt == bitblt_1tofb) {
1837 		if (error =
1838 		    batch_bitblt_01tofb(fb, &cmd->srcBitmap, &cr, sdp, n,
1839 		    blt == bitblt_1tofb)) {
1840 			cursorOn(fb);
1841 			return (error);
1842 		}
1843 	} else if (blt == bitblt_fb) {
1844 		if (error =
1845 		    batch_bitblt_fb(fb, &cmd->srcBitmap, &cr, sdp, n)) {
1846 			cursorOn(fb);
1847 			return (error);
1848 		}
1849 	} else if (blt == bitblt_tofb) {
1850 		if (error =
1851 		    batch_bitblt_tofb(fb, &cmd->srcBitmap, &cmd->destBitmap,
1852 		    &cr, sdp, n)) {
1853 			cursorOn(fb);
1854 			return (error);
1855 		}
1856 	} else
1857 		while (--n >= 0) {
1858 			if ((*blt)(fb, &cmd->srcBitmap, &sdp->srcRect,
1859 			    &cmd->destBitmap, &sdp->destPoint, &cr) < 0) {
1860 				cursorOn(fb);
1861 				return (FB_RERROR);
1862 			}
1863 			PRE_EMPT;
1864 			sdp++;
1865 		}
1866 	cursorOn(fb);
1867 	return (FB_ROK);
1868 }
1869 
1870 tilebitbltcmd(fb, cmd)
1871 	struct fbdev *fb;
1872 	register lTileBitblt *cmd;
1873 {
1874 	lRectangle trect, rect, prect;
1875 	lPoint dp;
1876 	register int dx;
1877 	int dy;
1878 	register int offx, offy;
1879 	register int xlen, ylen;
1880 	int first;
1881 	register int (*blt)();
1882 	int t;
1883 
1884 	rect = cmd->destRect;
1885 	prect = cmd->ptnRect;
1886 
1887 	if (prect.extent.x <= 0 || prect.extent.y <= 0)
1888 		return;
1889 
1890 	if (cmd->ptnBitmap.type == BM_FB &&
1891 		!cliprect(&cmd->ptnBitmap.rect, &fb->FrameRect, (lRectangle*)0))
1892 		return;
1893 
1894 	/* clip pattern rectangle */
1895 	if (!cliprect(&prect, &cmd->ptnBitmap.rect, (lRectangle *)0))
1896 		return;
1897 
1898 	if (!getclip(fb, &cmd->destBitmap, &cmd->destClip)) return;
1899 
1900 	if (!cliprect(&rect, &cmd->destClip, (lRectangle *)0))
1901 		return;
1902 
1903 	if (setrop(fb, cmd->func, cmd->planemask, cmd->fore_color, cmd->aux_color,
1904 		cmd->transp, &cmd->ptnBitmap, &cmd->destBitmap) < 0)
1905 		return (FB_RERROR);
1906 
1907 	blt = sel_ropfunc(cmd->ptnBitmap.type, cmd->destBitmap.type);
1908 
1909 	offx = MOD(rect.origin.x - cmd->refPoint.x, prect.extent.x, t);
1910 	offy = MOD(rect.origin.y - cmd->refPoint.y, prect.extent.y, t);
1911 
1912 	dp = rect.origin;
1913 
1914 	trect.origin.x = prect.origin.x + offx;
1915 	trect.origin.y = prect.origin.y + offy;
1916 
1917 	dy = rect.extent.y;
1918 
1919 	cursorCheck(fb, cmd->ptnBitmap.type, &prect, cmd->destBitmap.type, &rect);
1920 
1921 	first = 1;
1922 	while (dy > 0) {
1923 		if (first) {	/* for the first time */
1924 			ylen = prect.extent.y - offy;
1925 			ylen = min(ylen, dy);
1926 			trect.extent.y = ylen;
1927 			trect.origin.y = prect.origin.y + offy;
1928 			first = 0;
1929 		} else {
1930 			ylen = min(prect.extent.y, dy);
1931 			trect.extent.y = ylen;
1932 			trect.origin.y = prect.origin.y;
1933 		}
1934 
1935 		dp.x = rect.origin.x;
1936 		dx = rect.extent.x;
1937 		xlen = prect.extent.x - offx;
1938 		trect.origin.x = prect.origin.x + offx;
1939 
1940 		if (dx < xlen) {
1941 			trect.extent.x = dx;
1942 			(*blt)(fb, &cmd->ptnBitmap, &trect, &cmd->destBitmap, &dp, (lRectangle *)0);
1943 		} else {
1944 			trect.extent.x = xlen;
1945 			(*blt)(fb, &cmd->ptnBitmap, &trect, &cmd->destBitmap, &dp, (lRectangle *)0);
1946 			dp.x += xlen;
1947 			dx -= xlen;
1948 			trect.origin.x = prect.origin.x;
1949 			while (dx > 0) {
1950 				xlen = min(dx, prect.extent.x);
1951 				trect.extent.x = xlen;
1952 				(*blt)(fb, &cmd->ptnBitmap, &trect, &cmd->destBitmap, &dp, (lRectangle *)0);
1953 				dp.x += xlen;
1954 				dx -= xlen;
1955 			}
1956 		}
1957 
1958 		dp.y += ylen;
1959 		dy -= ylen;
1960 	}
1961 
1962 	cursorOn(fb);
1963 }
1964 
1965 bitblt3cmd(fb, cmd)
1966 	struct fbdev fb;
1967 	lBitblt3 *cmd;
1968 {
1969 	return (FB_ROK);
1970 }
1971 
1972 draw_rectangle(fb, dp)
1973 	struct fbdev *fb;
1974 	lPrimRect *dp;
1975 {
1976 	lRectangle trect, rect, prect;
1977 	lPoint p;
1978 	register int dx;
1979 	int dy;
1980 	register int offx, offy;
1981 	register int xlen, ylen;
1982 	int first;
1983 	register int (*blt)();
1984 	int t;
1985 
1986 	rect = dp->rect;
1987 	prect = dp->ptnRect;
1988 
1989 	if (prect.extent.x <= 0 || prect.extent.y <= 0)
1990 		return;
1991 
1992 	if (dp->ptnBM.type == BM_FB &&
1993 		!cliprect(&dp->ptnBM.rect, &fb->FrameRect, (lRectangle*)0))
1994 		return;
1995 
1996 	/* clip pattern rectangle */
1997 	if (!cliprect(&prect, &dp->ptnBM.rect, (lRectangle *)0))
1998 		return;
1999 
2000 	if (!getclip(fb, &dp->drawBM, &dp->clip)) return;
2001 
2002 	if (!cliprect(&rect, &dp->clip, (lRectangle *)0))
2003 		return;
2004 
2005 	if (setrop(fb, dp->func, dp->planemask, dp->fore_color, dp->aux_color,
2006 			dp->transp, &dp->ptnBM, &dp->drawBM) < 0)
2007 		return (FB_RERROR);
2008 
2009 	blt = sel_ropfunc(dp->ptnBM.type, dp->drawBM.type);
2010 
2011 	offx = MOD(rect.origin.x - dp->refPoint.x, prect.extent.x, t);
2012 	offy = MOD(rect.origin.y - dp->refPoint.y, prect.extent.y, t);
2013 
2014 	p = rect.origin;
2015 
2016 	trect.origin.x = prect.origin.x + offx;
2017 	trect.origin.y = prect.origin.y + offy;
2018 
2019 	dy = rect.extent.y;
2020 
2021 	cursorCheck(fb, dp->ptnBM.type, &prect, dp->drawBM.type, &rect);
2022 
2023 	first = 1;
2024 	while (dy > 0) {
2025 		if (first) {	/* for the first time */
2026 			ylen = prect.extent.y - offy;
2027 			ylen = min(ylen, dy);
2028 			trect.extent.y = ylen;
2029 			trect.origin.y = prect.origin.y + offy;
2030 			first = 0;
2031 		} else {
2032 			ylen = min(prect.extent.y, dy);
2033 			trect.extent.y = ylen;
2034 			trect.origin.y = prect.origin.y;
2035 		}
2036 
2037 		p.x = rect.origin.x;
2038 		dx = rect.extent.x;
2039 		xlen = prect.extent.x - offx;
2040 		trect.origin.x = prect.origin.x + offx;
2041 
2042 		if (dx < xlen) {
2043 			trect.extent.x = dx;
2044 			(*blt)(fb, &dp->ptnBM, &trect, &dp->drawBM, &p, (lRectangle *)0);
2045 		} else {
2046 			trect.extent.x = xlen;
2047 			(*blt)(fb, &dp->ptnBM, &trect, &dp->drawBM, &p, (lRectangle *)0);
2048 			p.x += xlen;
2049 			dx -= xlen;
2050 			trect.origin.x = prect.origin.x;
2051 			while (dx > 0) {
2052 				xlen = min(dx, prect.extent.x);
2053 				trect.extent.x = xlen;
2054 				(*blt)(fb, &dp->ptnBM, &trect, &dp->drawBM, &p, (lRectangle *)0);
2055 				p.x += xlen;
2056 				dx -= xlen;
2057 			}
2058 		}
2059 
2060 		p.y += ylen;
2061 		dy -= ylen;
2062 	}
2063 
2064 	cursorOn(fb);
2065 }
2066 
2067 draw_polymarker(fb, dp)
2068 	struct fbdev *fb;
2069 	register lPrimMarker *dp;
2070 {
2071 	register lPoint *ps;
2072 	register int np;
2073 	lRectangle cr;
2074 	register int (*blt)();
2075 #ifdef CPU_SINGLE
2076 	struct fb_map *map;
2077 	unsigned int p;
2078 #endif
2079 
2080 	cr = dp->clip;
2081 
2082 	if ((dp->drawBM.type == BM_FB) &&
2083 			!getclip(fb, &dp->drawBM, &cr))
2084 		return (FB_ROK);
2085 
2086 	if (dp->ptnBM.type == BM_FB &&
2087 		!cliprect(&dp->ptnBM.rect, &fb->FrameRect, (lRectangle*)0))
2088 		return (FB_ROK);
2089 
2090 	if (setrop(fb, dp->func, dp->planemask, dp->fore_color, dp->aux_color,
2091 			dp->transp, &dp->ptnBM, &dp->drawBM) < 0)
2092 		return (FB_RERROR);
2093 
2094 	blt = sel_ropfunc(dp->ptnBM.type, dp->drawBM.type);
2095 
2096 	cursorCheck(fb, dp->ptnBM.type, &(dp->ptnRect), dp->drawBM.type, &cr);
2097 
2098 #ifdef CPU_SINGLE
2099 	map = (struct fb_map *)(dp->plist);
2100 	p = map->fm_offset;
2101 	ps = (lPoint *)TypeAt(map, p);
2102 #else
2103 	ps = dp->plist;
2104 #endif
2105 	np = dp->np;
2106 	while (--np >= 0) {
2107 		(*blt)(fb, &dp->ptnBM, &dp->ptnRect, &dp->drawBM, ps++, &cr);
2108 		PRE_EMPT;
2109 	}
2110 
2111 	cursorOn(fb);
2112 
2113 	return (FB_ROK);
2114 }
2115 
2116 static int patternx;
2117 static int patterny;
2118 static int patternwidth;
2119 static lBitmap *pbm;		/* pattern bitmap */
2120 static lBitmap *drawbm;		/* drawing bitmap */
2121 static int (*blt)();
2122 
2123 static
2124 fill_line(fb, len, dp, offx, offy)
2125 register struct fbdev *fb;
2126 register int len;
2127 register lPoint *dp;
2128 int offx, offy;
2129 {
2130 	register int plen;
2131 	static lRectangle srec = { 0, 0, 0, 1 };
2132 
2133 	srec.origin.x = patternx + offx;
2134 	srec.origin.y = patterny + offy;
2135 
2136 	if ((plen = patternwidth - offx) > len) {
2137 		srec.extent.x = len;
2138 		(*blt)(fb, pbm, &srec, drawbm, dp, (lRectangle *)0);
2139 		return;
2140 	}
2141 
2142 	srec.extent.x = plen;
2143 	(*blt)(fb, pbm, &srec, drawbm, dp, (lRectangle *)0);
2144 	dp->x += plen;
2145 	len -= plen;
2146 	srec.origin.x = patternx;
2147 	plen = patternwidth;
2148 
2149 	while (len > 0) {
2150 		srec.extent.x = min(plen, len);
2151 		(*blt)(fb, pbm, &srec, drawbm, dp, (lRectangle *)0);
2152 		dp->x += plen;
2153 		len -= plen;
2154 	}
2155 }
2156 
2157 fill_scan(fb, fdata)
2158 	register struct fbdev *fb;
2159 	register lPrimFill *fdata;
2160 {
2161 	register lScanl	*ls;
2162 	int nscan;
2163 	lRectangle clip;
2164 	lRectangle prect;
2165 	register int minx, maxx, miny, maxy;
2166 #ifdef CPU_SINGLE
2167 	struct fb_map *map;
2168 #endif
2169 	register void (*rop_clear)();
2170 	int (*sel_ropfunc())();
2171 
2172 	if ((nscan = fdata->nscan) <= 0)
2173 		return (FB_RERROR);
2174 
2175 	/* clip pattern rectangle */
2176 	prect = fdata->ptnRect;
2177 	if (!getclip(fb, &fdata->ptnBM, &prect))
2178 		return (0);
2179 
2180 	if (prect.extent.x <= 0 || prect.extent.y <= 0)
2181 		return (FB_RERROR);
2182 
2183 	/* clip clip rectangle */
2184 	clip = fdata->clip;
2185 	if (!getclip(fb, &fdata->drawBM, &clip))
2186 		return (0);
2187 
2188 	if (setrop(fb, fdata->func, fdata->planemask,
2189 	    fdata->fore_color, fdata->aux_color, fdata->transp,
2190 	    &fdata->ptnBM, &fdata->drawBM) < 0)
2191 		return (FB_RERROR);
2192 
2193 #ifdef CPU_SINGLE
2194 	map = (struct fb_map *)(fdata->scan);
2195 	ls = (lScanl *)TypeAt(map, map->fm_offset);
2196 #else
2197 	ls = fdata->scan;
2198 #endif
2199 
2200 	minx = clip.origin.x;
2201 	maxx = minx + clip.extent.x - 1;
2202 	miny = clip.origin.y;
2203 	maxy = miny + clip.extent.y - 1;
2204 
2205 	cursorCheck(fb, fdata->ptnBM.type, &prect, fdata->drawBM.type, &clip);
2206 
2207 	blt = sel_ropfunc(fdata->ptnBM.type, fdata->drawBM.type);
2208 	if (blt == bitblt_1tofb || blt == bitblt_0tofb) {
2209 		lRectangle dr;
2210 
2211 		if (fb->fbbm_op->fb_rop_fillscan != (void (*)())nofunc) {
2212 			fbbm_rop_fillscan(fb, ls, nscan, &clip,
2213 			    blt == bitblt_1tofb);
2214 			goto out;
2215 		}
2216 		dr.extent.y = 1;
2217 		fbbm_rop_cinit(fb, fb->Pmask, blt == bitblt_1tofb);
2218 		rop_clear = fb->fbbm_op->fb_rop_clear;
2219 		while (--nscan >= 0) {
2220 			if ((dr.origin.y = ls->y) >= miny &&
2221 			    dr.origin.y <= maxy) {
2222 				dr.origin.x = max(ls->x0, minx);
2223 				if ((dr.extent.x =
2224 				    min(ls->x1, maxx) - dr.origin.x + 1) > 0)
2225 					(*rop_clear)(fb, &dr);
2226 			}
2227 			ls++;
2228 		}
2229 	} else {
2230 		int len;
2231 		int refx, refy;
2232 		lPoint dp;
2233 		int sizex, sizey;
2234 		int t;
2235 
2236 		sizex = prect.extent.x;
2237 		sizey = prect.extent.y;
2238 		refx = fdata->refPoint.x;
2239 		refy = fdata->refPoint.y;
2240 
2241 		patternx = prect.origin.x;
2242 		patterny = prect.origin.y;
2243 		patternwidth = sizex;
2244 
2245 		pbm = &fdata->ptnBM;
2246 		drawbm = &fdata->drawBM;
2247 
2248 		while (--nscan >= 0) {
2249 			if ((dp.y = ls->y) >= miny && dp.y <= maxy) {
2250 				dp.x = max(ls->x0, minx);
2251 				if ((len = min(ls->x1, maxx) - dp.x + 1) > 0)
2252 					fill_line(fb, len, &dp,
2253 					    MOD((dp.x - refx), sizex, t),
2254 					    MOD((dp.y - refy), sizey, t));
2255 			}
2256 			ls++;
2257 		}
2258 	}
2259 out:
2260 	cursorOn(fb);
2261 	return (FB_ROK);
2262 }
2263 
2264 put_string(fb, sdata)
2265 	struct fbdev *fb;
2266 	lPrimText *sdata;
2267 {
2268 	register int x, y;
2269 	register int ex_factor = sdata->ex_factor;
2270 	register unsigned c;
2271 	register unsigned char *str;
2272 	int len = sdata->len;
2273 	int flen;
2274 	int i, j, k, l;
2275 	unsigned fchar = sdata->first_chr;
2276 	unsigned lchar = sdata->last_chr;
2277 	lRectangle cr, save;
2278 	register int (*bltfunc)();
2279 	register char *f_addr;		/* font address */
2280 	register char **fnt_addr;
2281 	static struct fb_map rommap;
2282 #ifdef CPU_SINGLE
2283 	struct fb_map *map;
2284 	unsigned int p;
2285 #endif
2286 
2287 	lBitmap *fontBM;
2288 	lRectangle srec;
2289 	lPoint dp;
2290 
2291 	extern int tmode;	/* in ../bm/vt100if.c */
2292 
2293 	x = sdata->p.x << 16;
2294 	y = sdata->p.y << 16;
2295 
2296 	srec.extent.x = sdata->width;
2297 	srec.extent.y = sdata->height;
2298 
2299 	switch (sdata->type) {
2300 
2301 	case ASCII:
2302 		fontBM = &sdata->fontBM;
2303 
2304 		break;
2305 
2306 	case ROM_ASCII:
2307 	case ROM_CONS:
2308 		if (sdata->width >= 12 && sdata->height >= 24) {
2309 			if (fb->Krom_BM1.type == (char)0xff) {
2310 				fontBM = &fb->Krom_BM0;
2311 				srec.extent.x = fb->Krom_font_extent0.x>>1;
2312 				srec.extent.y = fb->Krom_font_extent0.y;
2313 				fnt_addr = ext_fnt_addr;
2314 			} else {
2315 				fontBM = &fb->Krom_BM1;
2316 				srec.extent.x = fb->Krom_font_extent1.x>>1;
2317 				srec.extent.y = fb->Krom_font_extent1.y;
2318 				fnt_addr = ext_fnt24_addr;
2319 			}
2320 		} else {
2321 			if (fb->Krom_BM0.type == (char)0xff) {
2322 				fontBM = &fb->Krom_BM1;
2323 				srec.extent.x = fb->Krom_font_extent1.x>>1;
2324 				srec.extent.y = fb->Krom_font_extent1.y;
2325 				fnt_addr = ext_fnt24_addr;
2326 			} else {
2327 				fontBM = &fb->Krom_BM0;
2328 				srec.extent.x = fb->Krom_font_extent0.x>>1;
2329 				srec.extent.y = fb->Krom_font_extent0.y;
2330 				fnt_addr = ext_fnt_addr;
2331 			}
2332 		}
2333 
2334 		if (srec.extent.x > sdata->width)
2335 			srec.extent.x = sdata->width;
2336 		if (srec.extent.y > sdata->height)
2337 			srec.extent.y = sdata->height;
2338 		flen = (fontBM->width<<1) * fontBM->rect.extent.y;
2339 		fontBM->base = (Word *)&rommap;
2340 		break;
2341 
2342 	case ROM_KANJI:
2343 		if (sdata->width >= 24 && sdata->height >= 24) {
2344 			if (fb->Krom_BM1.type == (char)0xff) {
2345 				fontBM = &fb->Krom_BM0;
2346 				srec.extent = fb->Krom_font_extent0;
2347 				fnt_addr = ext_fnt_addr;
2348 			} else {
2349 				fontBM = &fb->Krom_BM1;
2350 				srec.extent = fb->Krom_font_extent1;
2351 				fnt_addr = ext_fnt24_addr;
2352 			}
2353 		} else {
2354 			if (fb->Krom_BM0.type == (char)0xff) {
2355 				fontBM = &fb->Krom_BM1;
2356 				srec.extent = fb->Krom_font_extent1;
2357 				fnt_addr = ext_fnt24_addr;
2358 			} else {
2359 				fontBM = &fb->Krom_BM0;
2360 				srec.extent = fb->Krom_font_extent0;
2361 				fnt_addr = ext_fnt_addr;
2362 			}
2363 		}
2364 
2365 		if (srec.extent.x > sdata->width)
2366 			srec.extent.x = sdata->width;
2367 		if (srec.extent.y > sdata->height)
2368 			srec.extent.y = sdata->height;
2369 		save.extent.x = srec.extent.x;
2370 		flen = (fontBM->width<<1) * fontBM->rect.extent.y;
2371 		fontBM->base = (Word *)&rommap;
2372 		break;
2373 
2374 	default:
2375 		return (FB_RERROR);
2376 	}
2377 
2378 	/* get clipping rectangle */
2379 	cr = sdata->clip;
2380 
2381 	if (!getclip(fb, &sdata->drawBM, &cr))
2382 		return (FB_ROK);
2383 
2384 	/* set rop code */
2385 	if (setrop(fb, sdata->func, sdata->planemask,
2386 			sdata->fore_color, sdata->aux_color,
2387 			sdata->transp, fontBM, &sdata->drawBM) < 0)
2388 		return (FB_RERROR);
2389 
2390 	/* select rop function */
2391 	bltfunc = sel_ropfunc(fontBM->type, sdata->drawBM.type);
2392 
2393 #ifdef CPU_SINGLE
2394 	map = (struct fb_map *)(sdata->str);
2395 	p = map->fm_offset;
2396 	str = (unsigned char *)TypeAt(map, p);
2397 #else
2398 	str = sdata->str;
2399 #endif
2400 
2401 	cursorCheck(fb, fontBM->type, &fontBM->rect, sdata->drawBM.type, &cr);
2402 
2403 	switch (sdata->type) {
2404 
2405 	case ASCII:
2406 		if (sdata->column == 0)
2407 			return (FB_RERROR);
2408 		while (len-- > 0) {
2409 			c = *str++;
2410 
2411 			if (c < fchar || c > lchar)
2412 				continue;
2413 
2414 			c -= fchar;
2415 			srec.origin.x = sdata->fp.x
2416 				+ sdata->width * (c % sdata->column);
2417 			srec.origin.y = sdata->fp.y
2418 				+ sdata->height * (c / sdata->column);
2419 			dp.x = x >> 16;
2420 			dp.y = y >> 16;
2421 
2422 			if (ex_factor == 1) {
2423 				(*bltfunc)(fb, fontBM, &srec, &sdata->drawBM,
2424 					&dp, &cr);
2425 			} else {
2426 				srec.extent.x = 1;
2427 
2428 				for (i = 0; i < sdata->width; i++) {
2429 					for (j = 0; j < ex_factor; j++) {
2430 						(*bltfunc)(fb, fontBM, &srec,
2431 							&sdata->drawBM,
2432 							&dp, &cr);
2433 						dp.x++;
2434 						PRE_EMPT;
2435 					}
2436 					srec.origin.x++;
2437 				}
2438 			}
2439 			x += sdata->dx;
2440 			y += sdata->dy;
2441 		}
2442 		break;
2443 
2444 	case ROM_ASCII:
2445 	case ROM_CONS:
2446 #ifdef IPC_MRX
2447 		if (fb->type == FB_NWB251)
2448 			fb->cache_off = 1;
2449 #endif
2450 		while (len-- > 0) {
2451 			c = *str++;
2452 			dp.x = x >> 16;
2453 			dp.y = y >> 16;
2454 			k = 0;
2455 			srec.origin.x = srec.origin.y = 0;
2456 
2457 			f_addr = 0;
2458 
2459 			if ((c >= 0x20) && (c <= 0x7e)) {
2460 				/*
2461 				 * ASCII char
2462 				 */
2463 				f_addr = fnt_addr[c];
2464 				goto disp;
2465 			}
2466 
2467 			if (sdata->type == ROM_ASCII) {
2468 				if ((c >= 0xa1) && (c <= 0xdf)) {
2469 					/*
2470 					 * KANA char
2471 					 */
2472 					f_addr = fnt_addr[c + 64];
2473 					goto disp;
2474 				}
2475 			}
2476 
2477 			if (sdata->type == ROM_CONS) {
2478 #ifdef KM_ASCII
2479 				if (tmode == KM_ASCII) {
2480 #endif
2481 					if ((c >= 0xa0) && (c <= 0xff)) {
2482 						/*
2483 						 * ISO char
2484 						 */
2485 						f_addr = fnt_addr[c - 32];
2486 						goto disp;
2487 					}
2488 #ifdef KM_ASCII
2489 				} else {
2490 					if ((c >= 0xa1) && (c <= 0xdf)) {
2491 						/*
2492 						 * KANA char
2493 						 */
2494 						f_addr = fnt_addr[c + 64];
2495 						goto disp;
2496 					}
2497 				}
2498 #endif
2499 			}
2500 
2501 disp:
2502 
2503 			if (f_addr) {
2504 				/*
2505 				 * not ROM font
2506 				 *	(font is in kernel data area)
2507 				 */
2508 				bltfunc = sel_ropfunc(BM_MEM,
2509 						sdata->drawBM.type);
2510 				rommap.fm_vaddr = f_addr;
2511 				rommap.fm_offset = 0;
2512 #ifdef IPC_MRX
2513 				iopmemfbmap(f_addr, flen, &rommap);
2514 #endif
2515 				k = 1;
2516 				l = fontBM->width;
2517 				fontBM->width = 1;
2518 				save = fontBM->rect;
2519 				fontBM->rect.origin = srec.origin;
2520 				fontBM->rect.extent.x = 12;
2521 			} else if (fontBM->type == BM_MEM) {
2522 				/*
2523 				 * KANJI ROM except pop[cm]fb
2524 				 */
2525 				f_addr = fbbm_Krom_addr(fb, c, &srec);
2526 				rommap.fm_vaddr = f_addr;
2527 				rommap.fm_offset = 0;
2528 #ifdef IPC_MRX
2529 				iopmemfbmap(f_addr, flen, &rommap);
2530 #endif
2531 			} else {
2532 				/*
2533 				 * XXX
2534 				 * fontBM->type == BM_FB -> fbbm_pop[cm]
2535 				 *
2536 				 * see fbpop[cm]_setup() routine
2537 				 * in fbbm_pop[cm].c
2538 				 */
2539 				bltfunc = sel_ropfunc(fontBM->type,
2540 							sdata->drawBM.type);
2541 
2542 				bzero((caddr_t)fontBM->base,
2543 						sizeof (struct fb_map));
2544 				fbbm_Krom_addr(fb, c, &srec);
2545 				fontBM->rect.origin = srec.origin;
2546 			}
2547 
2548 			if (ex_factor == 1) {
2549 				(*bltfunc)(fb, fontBM, &srec, &sdata->drawBM,
2550 					&dp, &cr);
2551 			} else {
2552 				srec.extent.x = 1;
2553 
2554 				for (i = 0; i < sdata->width; i++) {
2555 
2556 					for (j = 0; j < ex_factor; j++) {
2557 						(*bltfunc)(fb, fontBM, &srec,
2558 							&sdata->drawBM,
2559 							&dp, &cr);
2560 						dp.x++;
2561 					}
2562 					srec.origin.x++;
2563 				}
2564 			}
2565 			PRE_EMPT;
2566 			if (k != 0) {
2567 				fontBM->rect = save;
2568 				fontBM->width = l;
2569 			}
2570 			x += sdata->dx;
2571 			y += sdata->dy;
2572 		}
2573 #ifdef IPC_MRX
2574 		fb->cache_off = 0;
2575 #endif
2576 
2577 		break;
2578 
2579 	case ROM_KANJI:
2580 #ifdef IPC_MRX
2581 		if (fb->type == FB_NWB251)
2582 			fb->cache_off = 1;
2583 #endif
2584 		while (len > 1) {
2585 			c = *str++;
2586 			c <<= 8;
2587 			c |= *str++;
2588 			dp.x = x >> 16;
2589 			dp.y = y >> 16;
2590 			srec.origin.x = srec.origin.y = 0;
2591 
2592 			if (fontBM->type == BM_MEM) {
2593 				/*
2594 				 * KANJI ROM except pop[cm]fb
2595 				 */
2596 				f_addr = fbbm_Krom_addr(fb, c, &srec);
2597 				rommap.fm_vaddr = f_addr;
2598 				rommap.fm_offset = 0;
2599 #ifdef IPC_MRX
2600 				iopmemfbmap(f_addr, flen, &rommap);
2601 #endif
2602 			} else {
2603 				/*
2604 				 * XXX
2605 				 * fontBM->type == BM_FB ---> fbbm_pop[cm]
2606 				 *
2607 				 * see fbpop[cm]_setup() in fbbm_pop[cm].c
2608 				 */
2609 				bzero((caddr_t)fontBM->base,
2610 						sizeof (struct fb_map));
2611 				fbbm_Krom_addr(fb, c, &srec);
2612 				fontBM->rect.origin = srec.origin;
2613 			}
2614 
2615 			if (ex_factor == 1) {
2616 				(*bltfunc)(fb, fontBM, &srec, &sdata->drawBM,
2617 					&dp, &cr);
2618 			} else {
2619 				srec.extent.x = 1;
2620 				for (i = 0; i < sdata->width; i++) {
2621 					for (j = 0; j < ex_factor; j++) {
2622 						(*bltfunc)(fb, fontBM, &srec,
2623 							&sdata->drawBM,
2624 							&dp, &cr);
2625 						dp.x++;
2626 					}
2627 					srec.origin.x++;
2628 				}
2629 				srec.extent.x = save.extent.x;
2630 			}
2631 			PRE_EMPT;
2632 			x += sdata->dx;
2633 			y += sdata->dy;
2634 			len -= 2;
2635 		}
2636 #ifdef IPC_MRX
2637 		fb->cache_off = 0;
2638 #endif
2639 		break;
2640 
2641 	default:
2642 		cursorOn(fb);
2643 		return (FB_RERROR);
2644 	}
2645 
2646 	cursorOn(fb);
2647 
2648 	return (FB_ROK);
2649 }
2650 
2651 void
2652 linerop(fb, func, fore, aux, trans)
2653 	struct fbdev	*fb;
2654 	register unsigned func;
2655 	register int fore;
2656 	register int aux;
2657 	int trans;
2658 {
2659 	register char *funcv;
2660 	register int i;
2661 	char tmp[4];
2662 
2663 	/* set rop function register */
2664 	func &= 0xf;
2665 	tmp[0] = TRANS(trans, (func & 0x0c) | (func >> 2));
2666 	tmp[1] = TRANS(trans, (func >> 2) | ((func << 2) & 0x0c));
2667 	tmp[2] = TRANS(trans, func);
2668 	tmp[3] = TRANS(trans, (func << 2) & 0x0c | func & 3);
2669 
2670 	funcv = fb->funcvec;
2671 	for (i = fb->fbNplane; --i >= 0;) {
2672 		*funcv++ = tmp[((fore & 1) << 1) | (aux & 1)];
2673 		fore >>= 1; aux >>= 1;
2674 	}
2675 }
2676 
2677 /*
2678  * line clipping routine
2679  *
2680  *	DRAW	visual
2681  *	NODRAW	not visual
2682  */
2683 lineclip(p0, p1, r)
2684 	register lPoint *p0;
2685 	register lPoint *p1;
2686 	register lRectangle *r;		/* clipping rectangle */
2687 {
2688 	register lPoint *ptmp;
2689 	register int d0, d1, d2, limit;
2690 
2691 	/* sort 2 points by x-coordinate */
2692 	if (p0->x > p1->x) {
2693 		ptmp = p1;
2694 		p1 = p0;
2695 		p0 = ptmp;
2696 	}
2697 	limit = r->origin.x;
2698 	d0 = p1->y - p0->y;
2699 	d1 = p1->x - p0->x;
2700 	if ((d2 = limit - p0->x) > 0) {
2701 		if (p1->x < limit)
2702 			return (NODRAW);
2703 		p0->y += d2 * d0 / d1;
2704 		p0->x = limit;
2705 	}
2706 	limit += r->extent.x - 1;
2707 	if ((d2 = limit - p1->x) < 0) {
2708 		if (p0->x > limit)
2709 			return (NODRAW);
2710 		p1->y += d2 * d0 / d1;
2711 		p1->x = limit;
2712 	}
2713 
2714 	/* sort 2 points by y-coordinate */
2715 	if (p0->y > p1->y) {
2716 		ptmp = p1;
2717 		p1 = p0;
2718 		p0 = ptmp;
2719 	}
2720 	limit = r->origin.y;
2721 	d0 = p1->x - p0->x;
2722 	d1 = p1->y - p0->y;
2723 	if ((d2 = limit - p0->y) > 0) {
2724 		if (p1->y < limit)
2725 			return (NODRAW);
2726 		p0->x += d2 * d0 / d1;
2727 		p0->y = limit;
2728 	}
2729 	limit += r->extent.y - 1;
2730 	if ((d2 = limit - p1->y) < 0) {
2731 		if (p0->y > limit)
2732 			return (NODRAW);
2733 		p1->x += d2 * d0 / d1;
2734 		p1->y = limit;
2735 	}
2736 	return (DRAW);
2737 }
2738 
2739 #ifndef CPU_DOUBLE
2740 /*
2741 void
2742 point(p, x, s, fp)
2743 	register char *p;
2744 	register int x;
2745 	register int s;
2746 	register char *fp;
2747 {
2748 	x = 7 - (x & 7);
2749 	if ((1 << (3 - (((s & 1) << 1) | ((*p >> x) & 1)))) & *fp)
2750 		*p |= (1 << x);
2751 	else
2752 		*p &= ~(1 << x);
2753 }
2754 */
2755 #define point(p, x, s, fp) { \
2756 	int xx = 7 - ((x) & 7); \
2757 	if ((1 << (3 - ((((s) & 1) << 1) | ((*(p) >> xx) & 1)))) & *(fp)) \
2758 		*(p) |= (1 << xx); \
2759 	else \
2760 		*(p) &= ~(1 << xx); \
2761 }
2762 
2763 mem_vector(fb, p0, p1, mask, dbmp, lpf)
2764 	struct fbdev	*fb;
2765 	lPoint *p0, *p1;
2766 	int mask;		/* plane mask */
2767 	lBitmap *dbmp;		/* drawing bitmap */
2768 	int lpf;		/* if 0, don't draw last point */
2769 {
2770 	register struct fb_map *map = (struct fb_map *)dbmp->base;
2771 	register char *funcv = fb->funcvec;		/* rop function */
2772 	int p = (int)map->fm_offset;
2773 	register int pmask;
2774 	register unsigned int pat;
2775 	register int x = p0->x;
2776 	register int y = p0->y;
2777 	register char *fp;
2778 	int width = dbmp->width << 1;
2779 	int lim;
2780 	int size = width * dbmp->rect.extent.y;
2781 	int ddx, ddy;
2782 	int s, d, c;
2783 	int dx = p1->x - x;
2784 	int dy = p1->y - y;
2785 	int i, j;
2786 	int depth = dbmp->depth;
2787 
2788 	/* transformation */
2789 	x -= dbmp->rect.origin.x;
2790 	y -= dbmp->rect.origin.y;
2791 
2792 	pat = fb->pat;
2793 
2794 	ddx = 1;
2795 	ddy = dbmp->width << 1;
2796 	y = (int)p + y * ddy;
2797 
2798 	if (dx == 0)
2799 		ddx = 0;
2800 	else if (dx < 0) {
2801 		dx = -dx;
2802 		ddx = -ddx;
2803 	}
2804 
2805 	if (dy == 0)
2806 		ddy = 0;
2807 	else if (dy < 0) {
2808 		dy = -dy;
2809 		ddy = -ddy;
2810 	}
2811 
2812 	if (dx > dy) {	/* case x */
2813 		lim = dx;
2814 		if (lpf)
2815 			lim++;
2816 
2817 		s = -dx;
2818 		d = dx << 1;
2819 		c = dy << 1;
2820 
2821 		for (i = lim; i > 0; i--) {
2822 			(int)p = y + (x >> 3);
2823 
2824 			pat = (pat << 1) | ((pat & 0x80000000) ? 1: 0);
2825 
2826 			fp = funcv;
2827 			pmask = mask;
2828 
2829 			for (j = depth; j > 0; j--) {
2830 				if (pmask & 1) {
2831 					point(_TypeAt(map, p), x, pat, fp);
2832 				}
2833 
2834 				p += size;
2835 				pmask >>= 1;
2836 				fp++;
2837 			}
2838 
2839 			if ((s += c) >= 0) {
2840 				s -= d;
2841 				y += ddy;
2842 			}
2843 
2844 			x += ddx;
2845 		}
2846 	} else {			/* case y */
2847 		lim = dy;
2848 		if (lpf)
2849 			lim++;
2850 		s = -dy;
2851 		d = dy << 1;
2852 		c = dx << 1;
2853 
2854 		for (i = lim; i > 0; i--) {
2855 			(int)p = y + (x >> 3);
2856 			pat = (pat << 1) | ((pat & 0x80000000) ? 1: 0);
2857 
2858 			fp = funcv;
2859 			pmask = mask;
2860 
2861 			for (j = depth; j > 0; j--) {
2862 				if (pmask & 1) {
2863 					point(_TypeAt(map, p), x, pat, fp);
2864 				}
2865 
2866 				p += size;
2867 				pmask >>= 1;
2868 				fp++;
2869 			}
2870 
2871 			if ((s += c) >= 0) {
2872 				s -= d;
2873 				x += ddx;
2874 			}
2875 
2876 			y += ddy;
2877 		}
2878 	}
2879 
2880 	/* rotate pattern */
2881 	pat = fb->pat;
2882 
2883 	{
2884 		register int tmp;
2885 
2886 		tmp = lim & 31;
2887 		pat = (pat << tmp) | (pat >> (32 - tmp));
2888 	}
2889 
2890 	fb->pat = pat;
2891 }
2892 #endif /* !CPU_DOUBLE */
2893 
2894 /* polyline drawing */
2895 draw_polyline(fb, dp)
2896 	struct fbdev *fb;
2897 	register lPrimLine *dp;
2898 {
2899 	register lPoint *ps;
2900 	lPoint p0, p1;
2901 	register int np;
2902 	lRectangle clip, *clipp;
2903 #ifdef CPU_SINGLE
2904 	struct fb_map *map;
2905 	unsigned int p;
2906 #endif
2907 
2908 	/* clip rectangle */
2909 	clip = dp->clip;
2910 
2911 	if (clip.origin.x == -1)
2912 		clipp = 0;
2913 	else {
2914 		clipp = &clip;
2915 		if (!getclip(fb, &dp->drawBM, clipp)) return 0;
2916 	}
2917 #ifdef CPU_SINGLE
2918 	map = (struct fb_map *)(dp->plist);
2919 	p = map->fm_offset;
2920 	ps = (lPoint *)TypeAt(map, p);
2921 #else
2922 	ps = dp->plist;
2923 #endif
2924 	if (dp->drawBM.type == BM_FB) {
2925 
2926 		cursorCheck(fb, ~BM_FB, 0, dp->drawBM.type, clipp);
2927 		fbbm_rop_vect(fb, clipp, dp->func, dp->fore_color,
2928 				dp->aux_color, dp->transp, dp->planemask,
2929 				dp->np, ps, dp->lptn, (dp->dlpf)?1:0, 1);
2930 		cursorOn(fb);
2931 
2932 		return(FB_ROK);
2933 	}
2934 #ifndef CPU_DOUBLE
2935 	linerop(fb, dp->func, dp->fore_color, dp->aux_color, dp->transp);
2936 	p0 = *ps++;
2937 	np = dp->np - 1;
2938 	fb->pat = dp->lptn;
2939 	if (clipp) {
2940 		while (--np > 0) {
2941 			p1 = *ps;
2942 			if (lineclip(&p0, &p1, clipp)) {
2943 				mem_vector(fb, &p0, &p1,
2944 					dp->planemask, &dp->drawBM,
2945 					ps->x != p1.x || ps->y != p1.y);
2946 				PRE_EMPT;
2947 			}
2948 			p0 = *ps++;
2949 		}
2950 		p1 = *ps;
2951 		if (lineclip(&p0, &p1, clipp)) {
2952 			mem_vector(fb, &p0, &p1, dp->planemask, &dp->drawBM,
2953 				ps->x != p1.x || ps->y != p1.y || dp->dlpf);
2954 		}
2955 	} else {
2956 		while (--np > 0) {
2957 			p1 = *ps;
2958 			mem_vector(fb, &p0, &p1, dp->planemask, &dp->drawBM, 0);
2959 			PRE_EMPT;
2960 			p0 = *ps++;
2961 		}
2962 		p1 = *ps;
2963 		mem_vector(fb, &p0, &p1, dp->planemask, &dp->drawBM, dp->dlpf);
2964 	}
2965 #endif /* !CPU_DOUBLE */
2966 	return (FB_ROK);
2967 }
2968 
2969 /* disjoint polyline drawing */
2970 
2971 draw_dj_polyline(fb, dp)
2972 	struct fbdev *fb;
2973 	register lPrimLine *dp;
2974 {
2975 	register lPoint *ps;
2976 	lPoint p0, p1;
2977 	register int np;
2978 	lRectangle clip, *clipp;
2979 #ifdef CPU_SINGLE
2980 	struct fb_map *map;
2981 	unsigned int p;
2982 #endif
2983 
2984 	int lpf = (dp->dlpf)?1:0;
2985 
2986 	/* clip rectangle */
2987 	clip = dp->clip;
2988 
2989 	if (clip.origin.x == -1)
2990 		clipp = 0;
2991 	else {
2992 		clipp = &clip;
2993 		if(!getclip(fb, &dp->drawBM, clipp)) return (0);
2994 	}
2995 #ifdef CPU_SINGLE
2996 	map = (struct fb_map *)(dp->plist);
2997 	p = map->fm_offset;
2998 	ps = (lPoint *)TypeAt(map, p);
2999 #else
3000 	ps = dp->plist;
3001 #endif
3002 	if (dp->drawBM.type == BM_FB) {
3003 
3004 		cursorCheck(fb, ~BM_FB, 0, dp->drawBM.type, clipp);
3005 		fbbm_rop_vect(fb, clipp, dp->func, dp->fore_color,
3006 				dp->aux_color, dp->transp, dp->planemask,
3007 						dp->np, ps, dp->lptn, lpf, 0);
3008 		cursorOn(fb);
3009 		PRE_EMPT;
3010 
3011 		return (FB_ROK);
3012 	}
3013 #ifndef CPU_DOUBLE
3014 	linerop(fb, dp->func, dp->fore_color, dp->aux_color, dp->transp);
3015 	np = dp->np >> 1;
3016 	if (lpf) {
3017 		if (clipp) {
3018 			while (--np >= 0) {
3019 				p0 = *ps++;
3020 				p1 = *ps++;
3021 				fb->pat = dp->lptn;
3022 				if (lineclip(&p0, &p1, clipp)) {
3023 					mem_vector(fb, &p0, &p1,
3024 						dp->planemask, &dp->drawBM, 1);
3025 					PRE_EMPT;
3026 				}
3027 			}
3028 		} else {
3029 			while (--np >= 0) {
3030 				p0 = *ps++;
3031 				p1 = *ps++;
3032 				fb->pat = dp->lptn;
3033 				mem_vector(fb, &p0, &p1,
3034 					dp->planemask, &dp->drawBM, 1);
3035 				PRE_EMPT;
3036 			}
3037 		}
3038 	} else {
3039 		if (clipp) {
3040 			while (--np >= 0) {
3041 				p0 = *ps++;
3042 				p1 = *ps;
3043 				fb->pat = dp->lptn;
3044 				if (lineclip(&p0, &p1, clipp)) {
3045 					mem_vector(fb, &p0, &p1,
3046 						dp->planemask, &dp->drawBM,
3047 						ps->x != p1.x || ps->y != p1.y);
3048 					PRE_EMPT;
3049 				}
3050 				ps++;
3051 			}
3052 		} else {
3053 			while (--np >= 0) {
3054 				p0 = *ps++;
3055 				p1 = *ps++;
3056 				fb->pat = dp->lptn;
3057 				mem_vector(fb, &p0, &p1,
3058 					dp->planemask, &dp->drawBM, 0);
3059 				PRE_EMPT;
3060 			}
3061 		}
3062 	}
3063 #endif /* !CPU_DOUBLE */
3064 	return (FB_ROK);
3065 }
3066 
3067 static lRectangle	dotRect = {{ 0, 0 }, { 1, 1 }};
3068 
3069 emulate_polydot(fb, dp)
3070 	struct fbdev *fb;
3071 	register lPrimDot *dp;
3072 {
3073 	lPrimMarker marker;
3074 	lPrimMarker *cmdp;
3075 	register lPoint *ps;
3076 	register int np;
3077 	lRectangle cr;
3078 	register int (*blt)();
3079 #ifdef CPU_SINGLE
3080 	struct fb_map *map;
3081 	unsigned int p;
3082 #endif
3083 
3084 	cmdp = &marker;
3085 
3086 	cmdp->func = dp->func;
3087         cmdp->transp = dp->transp;
3088         cmdp->fore_color = dp->fore_color;
3089         cmdp->aux_color = dp->aux_color;
3090         cmdp->planemask = dp->planemask;
3091         cmdp->ptnRect = dotRect;
3092         cmdp->ptnBM.type = BM_1;
3093         cmdp->ptnBM.depth = 1;
3094         cmdp->ptnBM.rect = dotRect;
3095         cmdp->drawBM = dp->drawBM;
3096         cmdp->clip = dp->clip;
3097         cmdp->np = dp->np;
3098         cmdp->plist = dp->plist;
3099 
3100 	return (draw_polymarker(fb, cmdp));
3101 }
3102 
3103 #ifndef CPU_DOUBLE
3104 mem_dot(fb, p0, mask, dbmp)
3105 	struct fbdev	*fb;
3106 	lPoint		*p0;
3107 	register int	mask;		/* plane mask */
3108 	lBitmap		*dbmp;		/* drawing bitmap */
3109 {
3110 	register struct fb_map *map = (struct fb_map *)dbmp->base;
3111 	register char *funcv;	/* rop function */
3112 	register int p = (int)map->fm_offset;
3113 	register int depth;
3114 	int size;
3115 	int x, y;
3116 
3117 	x = p0->x - dbmp->rect.origin.x;
3118 	y = p0->y - dbmp->rect.origin.y;
3119 
3120 	size = (dbmp->width * dbmp->rect.extent.y) << 1;
3121 
3122 	p += y * (dbmp->width << 1) + (x >> 3);
3123 
3124 	funcv = fb->funcvec;
3125 	for (depth = dbmp->depth; --depth >= 0;) {
3126 		if (mask & 1) {
3127 			point(_TypeAt(map, p), x, ~0, funcv);
3128 		}
3129 		p += size;
3130 		mask >>= 1;
3131 		funcv++;
3132 	}
3133 }
3134 #endif /* !CPU_DOUBLE */
3135 
3136 draw_polydot(fb, dp)
3137 	struct fbdev *fb;
3138 	register lPrimDot *dp;
3139 {
3140 	register lPoint *ps;
3141 	lRectangle clip, *clipp;
3142 	register int np;
3143 #ifdef CPU_SINGLE
3144 	struct fb_map *map;
3145 	unsigned int p;
3146 #endif
3147 
3148 	if (fb->fbbm_op->fb_rop_dot == (void (*)())nofunc)
3149 		return (emulate_polydot(fb, dp));
3150 
3151 	/* clip rectangle */
3152 	clip = dp->clip;
3153 
3154 	if (clip.origin.x == -1)
3155 		clipp = 0;
3156 	else {
3157 		clipp = &clip;
3158 		if (!getclip(fb, &dp->drawBM, clipp)) return 0;
3159 	}
3160 
3161 #ifdef CPU_SINGLE
3162 	map = (struct fb_map *)(dp->plist);
3163 	p = map->fm_offset;
3164 	ps = (lPoint *)TypeAt(map, p);
3165 #else
3166 	ps = dp->plist;
3167 #endif
3168 
3169 	if (dp->drawBM.type == BM_FB) {
3170 		cursorCheck(fb, ~BM_FB, 0, dp->drawBM.type, clipp);
3171 		fbbm_rop_dot(fb, clipp, dp->func, dp->fore_color,
3172 				dp->aux_color, dp->transp, dp->planemask,
3173 				dp->np, ps);
3174 		cursorOn(fb);
3175 
3176 		return(FB_ROK);
3177 	}
3178 #ifndef CPU_DOUBLE
3179 	linerop(fb, dp->func, dp->fore_color, dp->aux_color, dp->transp);
3180 
3181 	np = dp->np;
3182 	if (clipp) {
3183 		register int x0, y0, x1, y1;
3184 
3185 		x0 = clipp->origin.x;
3186 		y0 = clipp->origin.y;
3187 		x1 = x0 + clipp->extent.x - 1;
3188 		y1 = y0 + clipp->extent.y - 1;
3189 		if (x1 <= 0 || y1 <= 0) return;
3190 
3191 		while (--np >= 0) {
3192 			if ((ps->x >= x0) && (ps->y >= y0) &&
3193 			    (ps->x <= x1) && (ps->y <= y1)) {
3194 				mem_dot(fb, ps, dp->planemask, &dp->drawBM);
3195 				PRE_EMPT;
3196 			}
3197 			ps++;
3198 		}
3199 	} else {
3200 		while (--np >= 0) {
3201 			mem_dot(fb, ps, dp->planemask, &dp->drawBM);
3202 			PRE_EMPT;
3203 			ps++;
3204 		}
3205 	}
3206 #endif /* !CPU_DOUBLE */
3207 	return (FB_ROK);
3208 }
3209 
3210 get_scrtype(fb, cmd)
3211 	register struct fbdev *fb;
3212 	register lScrType *cmd;
3213 {
3214 	cmd->colorwidth = fb->Colorwidth;
3215 	cmd->plane = fb->fbNplane;
3216 	cmd->bufferrect = fb->FrameRect;
3217 	cmd->visiblerect = fb->VisRect;
3218 	cmd->type = fb->type;
3219 	cmd->unit = fb->unit;
3220 
3221 	return FB_ROK;
3222 }
3223 
3224 fbstart(fbaddr, dummy)
3225 	register struct fbreg *fbaddr;
3226 	int dummy;
3227 {
3228 	register struct fbdev *fb = &fbdev[fbaddr->fb_device];
3229 	register int s;
3230 
3231 	FB_LOCK;
3232 
3233 	if (!fb) {
3234 		return (FB_RERROR);
3235 	}
3236 
3237 	/* reset dimmer count */
3238 	rst_dimmer_cnt();
3239 
3240 	switch(fbaddr->fb_command) {
3241 	case FB_CPROBE:
3242 		fbaddr->fb_data = search_fbdev(fbaddr->fb_device,
3243 						fbaddr->fb_unit);
3244 		fbaddr->fb_result = FB_ROK;
3245 		break;
3246 	case FB_CATTACH:
3247 		fbaddr->fb_result = get_scrtype(fb, &fbaddr->fb_scrtype);
3248 		break;
3249 	case FB_COPEN:
3250 		fbaddr->fb_result = fbbm_open(fb);
3251 		break;
3252 	case FB_CCLOSE:
3253 		fbaddr->fb_result = fbbm_close(fb);
3254 		break;
3255 	case FB_CSETDIM:
3256 		fbaddr->fb_result = fbbm_set_dimmer(fb, fbaddr->fb_data);
3257 		break;
3258 	case FB_CGETDIM:
3259 		if ((fbaddr->fb_data = fbbm_get_dimmer(fb)) == FB_RERROR)
3260 			fbaddr->fb_result = FB_RERROR;
3261 		else
3262 			fbaddr->fb_result = FB_ROK;
3263 		break;
3264 	case FB_CBITBLT:
3265 		fbaddr->fb_result = bitbltcmd(fb, &fbaddr->fb_bitblt);
3266 		break;
3267 	case FB_CBATCHBITBLT:
3268 		fbaddr->fb_result = batchbitbltcmd(fb, &fbaddr->fb_batchbitblt);
3269 		break;
3270 	case FB_CTILEBITBLT:
3271 		fbaddr->fb_result = tilebitbltcmd(fb, &fbaddr->fb_tilebitblt);
3272 		break;
3273 	case FB_CBITBLT3:
3274 		fbaddr->fb_result = bitblt3cmd(fb, &fbaddr->fb_bitblt3);
3275 		break;
3276 	case FB_CPOLYLINE:
3277 		fbaddr->fb_result = draw_polyline(fb, &fbaddr->fb_polyline);
3278 		break;
3279 	case FB_CDJPOLYLINE:
3280 		fbaddr->fb_result = draw_dj_polyline(fb, &fbaddr->fb_polyline);
3281 		break;
3282 	case FB_CRECTANGLE:
3283 		fbaddr->fb_result = draw_rectangle(fb, &fbaddr->fb_rectangle);
3284 		break;
3285 	case FB_CFILLSCAN:
3286 		fbaddr->fb_result = fill_scan(fb, &fbaddr->fb_fillscan);
3287 		break;
3288 	case FB_CPOLYMARKER:
3289 		fbaddr->fb_result = draw_polymarker(fb, &fbaddr->fb_polymarker);
3290 		break;
3291 	case FB_CTEXT:
3292 		fbaddr->fb_result = put_string(fb, &fbaddr->fb_text);
3293 		break;
3294 	case FB_CPOLYDOT:
3295 		fbaddr->fb_result = draw_polydot(fb, &fbaddr->fb_polydot);
3296 		break;
3297 	case FB_CGETSCRTYPE:
3298 		fbaddr->fb_result = get_scrtype(fb, &fbaddr->fb_scrtype);
3299 		break;
3300 	case FB_CSETPALETTE:
3301 		fbaddr->fb_result = fbbm_set_palette(fb, &fbaddr->fb_palette);
3302 		break;
3303 	case FB_CGETPALETTE:
3304 		fbaddr->fb_result = fbbm_get_palette(fb, &fbaddr->fb_palette);
3305 		break;
3306 	case FB_CSETCURSOR:
3307 		fbaddr->fb_result = setCursor(fb, &fbaddr->fb_cursor);
3308 		break;
3309 	case FB_CUNSETCURSOR:
3310 		fbaddr->fb_result = setCursor(fb, NULL);
3311 		break;
3312 	case FB_CSHOWCURSOR:
3313 		fbaddr->fb_result = showCursor(fb);
3314 		break;
3315 	case FB_CHIDECURSOR:
3316 		fbaddr->fb_result = hideCursor(fb);
3317 		break;
3318 	case FB_CSETXY:
3319 		fbaddr->fb_result = moveCursor(fb, &fbaddr->fb_point);
3320 		break;
3321 	case FB_CAUTODIM:
3322 		if (fbaddr->fb_data)
3323 			auto_dimmer_on(fb);
3324 		else
3325 			auto_dimmer_off(fb);
3326 		fbaddr->fb_result = FB_ROK;
3327 		break;
3328 	case FB_CSETVIDEO:
3329 		fbaddr->fb_result =
3330 			fbbm_ioctl(fb, FB_SETVIDEOCTL, &fbaddr->fb_videoctl);
3331 		break;
3332 	case FB_CGETVIDEO:
3333 		fbaddr->fb_result =
3334 			fbbm_ioctl(fb, FB_GETVIDEOSTATUS, &fbaddr->fb_videostatus);
3335 		break;
3336 	case FB_CSETPMODE:
3337 		fbaddr->fb_result =
3338 			fbbm_ioctl(fb, FB_SETPALETTEMODE, &fbaddr->fb_data);
3339 		break;
3340 	case FB_CGETPMODE:
3341 		fbaddr->fb_result =
3342 			fbbm_ioctl(fb, FB_GETPALETTEMODE, &fbaddr->fb_data);
3343 		break;
3344 #ifdef CPU_SINGLE
3345 	case FB_CGETPAGE:
3346 		fbaddr->fb_data = fbbm_get_page(fb, fbaddr->fb_data);
3347 		if (fbaddr->fb_data == -1)
3348 			fbaddr->fb_result = FB_RERROR;
3349 		else
3350 			fbaddr->fb_result = FB_ROK;
3351 		break;
3352 #endif
3353 	case FB_CIOCTL:
3354 		fbaddr->fb_fbioctl.request = fbbm_ioctl(fb,
3355 			fbaddr->fb_fbioctl.request, fbaddr->fb_fbioctl.param);
3356 		if (fbaddr->fb_fbioctl.request == -1)
3357 			fbaddr->fb_result = FB_RERROR;
3358 		else
3359 			fbaddr->fb_result = FB_ROK;
3360 		break;
3361 
3362 	default:
3363 		fbaddr->fb_result = FB_RERROR;
3364 		break;
3365 	}
3366 
3367 #ifdef CPU_SINGLE
3368 	if (cfb && curs_pending) {
3369 		curs_pending = 0;
3370 		redrawCursor(cfb);
3371 	}
3372 #endif
3373 
3374 	FB_UNLOCK;
3375 }
3376