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