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