xref: /original-bsd/sys/news3400/iop/fb_sub.c (revision 0c769079)
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_sub.c,v 4.300 91/06/27 20:43:09 root Rel41 $ SONY
11  *
12  *	@(#)fb_sub.c	7.2 (Berkeley) 12/17/92
13  */
14 
15 #include "fb.h"
16 #if NFB > 0
17 /*
18  * Frame buffer driver
19  */
20 
21 #include <machine/fix_machine_type.h>
22 
23 #include <sys/types.h>
24 #include <machine/pte.h>
25 #include <machine/cpu.h>
26 #include <machine/param.h>
27 
28 #include <sys/param.h>
29 #include <sys/proc.h>
30 #include <sys/user.h>
31 #include <sys/buf.h>
32 #include <vm/vm.h>
33 #include <sys/systm.h>
34 #include <sys/map.h>
35 #include <sys/uio.h>
36 #include <sys/kernel.h>
37 
38 #include <news3400/iop/framebuf.h>
39 #include <news3400/iop/fbreg.h>
40 #ifdef CPU_DOUBLE
41 #ifdef IPC_MRX
42 #include "../ipc/newsipc.h"
43 #ifdef mips
44 #define ipc_phys(x)	K0_TT0(x)
45 #define ipc_log(x)	TT0_K0(x)
46 #else /* mips */
47 #define	ipc_phys(x)	(caddr_t)((int)(x) & ~0x80000000)
48 #define	ipc_log(x)	(caddr_t)((int)(x) | 0x80000000)
49 #endif /* mips */
50 #endif /* IPC_MRX */
51 #else /* CPU_DOUBLE */
52 #define ipc_phys(x)	(caddr_t)((int)(x))
53 #define ipc_log(x)	(caddr_t)((int)(x) | 0x80000000)
54 #endif /* CPU_DOUBLE */
55 
56 #define MAX_FBMAP	3
57 static struct fb_map	fbmap[MAX_FBMAP];
58 
59 /* bitblt type */
60 #define BLTTYPE(ts, td)	((ts) << 2 | (td))
61 
62 static lSrcDest	srcdestlist[MAX_BATCHBITBLT];
63 #define MAX_SIZE	(MAX_BATCHBITBLT * sizeof(lSrcDest))
64 
65 #define ODD_ADDR(x)	(((unsigned)(x))&1)
66 
67 #define MAXMSEG	4
68 static int	segind;
69 static struct memseg {
70 	caddr_t		adrs;
71 	int		len;
72 	int		rw;
73 	caddr_t		oadrs;
74 	int		olen;
75 	struct fb_map	*map;
76 } mseg[MAXMSEG];
77 
78 #define BASE(a)	((int)(a) & ~(NBPG - 1))
79 
80 #ifdef CPU_DOUBLE
81 COPYIN(src, dst, len, seg)
82 	caddr_t src;
83 	caddr_t dst;
84 	int len;
85 	int seg;
86 {
87 
88 	switch (seg) {
89 	case UIO_SYSSPACE:
90 		bcopy(src, dst, len);
91 		return (0);
92 	case UIO_USERSPACE:
93 		return (copyin(src, dst, len));
94 	default:
95 		panic("COPYIN: seg");
96 		/* NOTREACHED */
97 	}
98 }
99 #endif /* CPU_DOUBLE */
100 
101 fbgetmap(addr, len, map)
102 	caddr_t addr;
103 	int len;
104 	struct fb_map *map;
105 {
106 	register struct pte *pte;
107 	register caddr_t *p;
108 	unsigned v;
109 	register int npf;
110 	int o;
111 
112 	v = pmax_btop(addr);
113 	o = (int)addr & PGOFSET;
114 	npf = btoc(len + o);
115 	if (npf > NFBMAP)
116 		return (EINVAL);
117 
118 	map->fm_vaddr = addr;
119 	map->fm_offset = o;
120 	map->fm_count = len;
121 
122 #ifdef CPU_DOUBLE
123 	if (addr >= (caddr_t)KERNBASE) {
124 #ifdef mips
125 		p = map->fm_addr;
126 		if (MACH_IS_CACHED(addr)) {
127 			addr = ptob(v);
128 			while (--npf >= 0) {
129 				*p++ = (caddr_t)K0_TT0(addr);
130 				addr += NBPG;
131 			}
132 			return (0);
133 		}
134 		if (MACH_IS_MAPPED(addr))
135 			pte = kvtopte(addr);
136 		else if (addr >= (caddr_t)&u)
137 			pte = curproc->p_addr + btop(addr - (caddr_t)&u);
138 		else
139 			panic("fbgetmap: bad kernel addr");
140 		while (--npf >= 0)
141 			*p++ = (caddr_t)PHYS_TT0(ptob(pte++->pg_pfnum));
142 #else /* mips */
143 		pte = kvtopte(addr);
144 		p = map->fm_addr;
145 		while (--npf >= 0)
146 			*p++ = (caddr_t)ptob(pte++->pg_pfnum);
147 #endif /* mips */
148 		return (0);
149 	}
150 	pte = vtopte(curproc, v);		/*KU:XXXXXXXXXXXXXXXXXX*/
151 	p = map->fm_addr;
152 	while (--npf >= 0) {
153 		if (pte->pg_pfnum == 0)
154 			panic("iop zero uentry");
155 #ifdef mips
156 		*p++ = (caddr_t)PHYS_TT0(ptob(pte++->pg_pfnum));
157 #else
158 		*p++ = (caddr_t)ptob(pte++->pg_pfnum);
159 #endif
160 	}
161 
162 #endif /* CPU_DOUBLE */
163 	return (0);
164 }
165 
166 fblockmem(ad, len, rw, map, seg)
167 	register caddr_t ad;
168 	register int len;
169 	int rw;
170 	struct fb_map *map;
171 	int seg;
172 {
173 	register struct memseg *msp;
174 
175 	/* validity check */
176 	if (len < 0)
177 		return EFAULT;
178 	else if (len == 0)
179 		return 0;
180 	else if (ad == 0)
181 		return EFAULT;
182 	else if (seg == UIO_USERSPACE &&
183 		 !useracc(ad, len, rw == B_READ ? B_WRITE : B_READ))
184 		return EFAULT;
185 	else if (segind >= MAXMSEG)
186 		return EFAULT;
187 
188 	/* insertion sort */
189 	for (msp = mseg + segind - 1; msp >= mseg; msp--) {
190 		if (msp->adrs > ad)
191 			*(msp + 1) = *msp;
192 		else
193 			break;
194 	}
195 	msp++;
196 #ifdef CPU_SINGLE
197 	switch (seg) {
198 	case UIO_SYSSPACE:
199 		map->fm_vaddr = ad;
200 		map->fm_offset = 0;
201 		break;
202 	case UIO_USERSPACE:
203 		msp->adrs = (caddr_t)BASE(ad);
204 		msp->len = (caddr_t)BASE(ad + len + NBPG - 1) - msp->adrs;
205 		break;
206 	default:
207 		panic("fblockmem: seg");
208 		/* NOTREACHED */
209 	}
210 #else /* CPU_SINGLE */
211 	msp->adrs = (caddr_t)BASE(ad);
212 	msp->len = (caddr_t)BASE(ad + len + NBPG - 1) - msp->adrs;
213 #endif /* CPU_SINGLE */
214 	msp->rw = rw;
215 	msp->oadrs = ad;
216 	msp->olen = len;
217 	msp->map = map;
218 	segind++;
219 
220 	return (0);
221 }
222 
223 fblocksbitmap(bm, rw, map)
224 	register lBitmap *bm;
225 	int rw;
226 	struct fb_map *map;
227 {
228 	register int len;
229 	register int error = 0;
230 
231 	if (bm->depth > 32)
232 		return EINVAL;
233 	if (bm->type == BM_FB || bm->type == BM_0 || bm->type == BM_1)
234 		return 0;
235 	if (bm->type == BM_MEM)
236 		len = bm->width * bm->rect.extent.y * bm->depth * sizeof(Word);
237 	if (len < 0 || len > FB_MAX_IO)
238 		return(EINVAL);
239 	error = fblockmem((caddr_t)(bm->base), len, rw, map, UIO_USERSPACE);
240 	if (error)
241 		return error;
242 
243 	bm->base = (Word *)ipc_phys(map);
244 	return 0;
245 }
246 
247 void
248 fbinitlock()
249 {
250 	segind = 0;
251 }
252 
253 void
254 fbdolock()
255 {
256 	register struct memseg *msp0, *msp1, *mspl;
257 	register int i, tlen;
258 
259 	mspl = mseg + segind;
260 	for (msp0 = mseg, msp1 = mseg + 1; msp1 < mspl; msp0++, msp1++) {
261 		if (msp0->adrs + msp0->len > msp1->adrs) {
262 			tlen = msp1->adrs - msp0->adrs + msp1->len;
263 			msp1->adrs = msp0->adrs;
264 			msp1->len = msp0->len > tlen ? msp0->len : tlen;
265 			msp0->len = 0;
266 			msp1->rw = (msp0->rw == B_READ || msp1->rw == B_READ) ?
267 					B_READ : B_WRITE;
268 		}
269 	}
270 
271 	/* lock */
272 	curproc->p_flag |= SPHYSIO;
273 	for (i = 0; i < segind; i++)
274 		if (mseg[i].len && mseg[i].adrs && mseg[i].adrs
275 		    < (caddr_t)KERNBASE)
276 			vslock(mseg[i].adrs, mseg[i].len);
277 
278 	/* make map */
279 	for (i = 0; i < segind; i++)
280 		fbgetmap(mseg[i].oadrs, mseg[i].olen, mseg[i].map);
281 }
282 
283 void
284 fbunlock()
285 {
286 	register int i;
287 	int s = splfb();
288 
289 	for (i = 0; i < segind; i++) {
290 		if (mseg[i].len && mseg[i].adrs && mseg[i].adrs
291 		    < (caddr_t)KERNBASE) {
292 			vsunlock(mseg[i].adrs, mseg[i].len, mseg[i].rw);
293 #if defined(mips) && defined(CPU_DOUBLE)
294 			if (mseg[i].rw == B_READ)
295 				clean_kudcache(curproc,
296 					       mseg[i].adrs, mseg[i].len);
297 #endif
298 		}
299 	}
300 	curproc->p_flag &= ~SPHYSIO;
301 	splx(s);
302 
303 	/* for 'fbinitlock() o wasureru ukkariyasan'... */
304 	segind = 0;
305 }
306 
307 checkbitmap(bm)
308 	register lBitmap *bm;
309 {
310 	if (bm->depth > 32)
311 		return EINVAL;
312 
313 	switch(bm->type) {
314 	case BM_FB:
315 	case BM_0:
316 	case BM_1:
317 		break;
318 	case BM_MEM:
319 		if (ODD_ADDR(bm->base))
320 			return EINVAL;
321 		if (bm->width == 0)
322 			return EINVAL;
323 		if ((bm->width * bm->rect.extent.y) << 1 > FB_MAX_IO)
324 			return EINVAL;
325 		break;
326 	default:
327 		return EINVAL;
328 	}
329 
330 	if (bm->rect.extent.x < 0 || bm->rect.extent.y < 0)
331 		return EINVAL;
332 	else
333 		return 0;
334 }
335 
336 checkdepth(sbm, dbm)
337 	lBitmap	*sbm, *dbm;
338 {
339 	register int ds = sbm->depth;
340 	register int dd = dbm->depth;
341 
342 	if (ds > 1 && dd > 1 && ds != dd)
343 		return -1;
344 	else
345 		return((ds > 1) << 1 | (dd > 1));
346 }
347 
348 dobitblt(fbp, sbm, dbm)
349 	struct fbreg *fbp;
350 	lBitmap	*sbm, *dbm;
351 {
352 	register int error;
353 
354 	if (error = fblocksbitmap(sbm, B_WRITE, fbmap))
355 		return error;
356 	if (error = fblocksbitmap(dbm, B_READ, fbmap + 1))
357 		return error;
358 	fbdolock();
359 	fbstart(fbp, 1);
360 	fbunlock();
361 
362 	/* reset address */
363 	if (sbm->type == BM_MEM)
364 		sbm->base =
365 		    (Word *)((struct fb_map *)ipc_log(sbm->base))->fm_vaddr;
366 	if (dbm->type == BM_MEM)
367 		dbm->base =
368 		    (Word *)((struct fb_map *)ipc_log(dbm->base))->fm_vaddr;
369 	return 0;
370 }
371 
372 fbnbitblt(fbp, cmd)
373 	register struct fbreg *fbp;
374 	register lBitblt *cmd;
375 {
376 	register lBitblt *regcmd;
377 	register int len, lens, lend;
378 	register int i;
379 	int pmask, mode;
380 	int error = 0;
381 	int blttype = BLTTYPE(cmd->srcBitmap.type, cmd->destBitmap.type);
382 
383 #ifdef CPU_DOUBLE
384 	if ((blttype == BLTTYPE(BM_MEM, BM_MEM)) ||
385 	    (blttype == BLTTYPE(BM_0, BM_MEM)) ||
386 	    (blttype == BLTTYPE(BM_1, BM_MEM))) {
387 		return(mfbnbitblt(fbp, cmd));
388 		/* NOTREACHED */
389 	}
390 #endif
391 
392 	fbinitlock();
393 	if (error = checkbitmap(&cmd->srcBitmap))
394 		return error;
395 	if (error = checkbitmap(&cmd->destBitmap))
396 		return error;
397 	if ((mode = checkdepth(&cmd->srcBitmap, &cmd->destBitmap)) < 0)
398 		return EINVAL;
399 
400 	fbp->fb_command = FB_CBITBLT;
401 	fbp->fb_bitblt = *cmd;
402 	regcmd = &fbp->fb_bitblt;
403 
404 	/* process bitblt command */
405 	switch (blttype) {
406 	case BLTTYPE(BM_FB, BM_FB):
407 	case BLTTYPE(BM_0, BM_FB):
408 	case BLTTYPE(BM_1, BM_FB):
409 		fbstart(fbp, 0);
410 		break;
411 
412 	case BLTTYPE(BM_FB, BM_MEM):
413 	case BLTTYPE(BM_0, BM_MEM):
414 	case BLTTYPE(BM_1, BM_MEM):
415 		len = cmd->destBitmap.width * cmd->destBitmap.rect.extent.y << 1;
416 		if (len * cmd->destBitmap.depth <= FB_MAX_IO) {
417 			error = dobitblt(fbp, &regcmd->srcBitmap,
418 					      &regcmd->destBitmap);
419 			return error;
420 		}
421 
422 		/* bitblt each plane */
423 		regcmd->destBitmap.depth = 1;
424 		pmask = regcmd->planemask;
425 		for (i = 0; i < cmd->destBitmap.depth; i++) {
426 			if (mode == 3)	/* N to N */
427 				regcmd->planemask = pmask & (1 << i);
428 
429 			if (error = dobitblt(fbp, &regcmd->srcBitmap,
430 						  &regcmd->destBitmap))
431 				return error;
432 
433 			regcmd->destBitmap.base += len >> 1;
434 			if (mode == 1) {	/* N to N */
435 				regcmd->planemask >>= 1;
436 				regcmd->fore_color >>= 1;
437 				regcmd->aux_color >>= 1;
438 			}
439 		}
440 		break;
441 
442 	case BLTTYPE(BM_MEM, BM_FB):
443 		len = cmd->srcBitmap.width * cmd->srcBitmap.rect.extent.y << 1;
444 
445 		if (len * cmd->srcBitmap.depth <= FB_MAX_IO) {
446 			error = dobitblt(fbp, &regcmd->srcBitmap,
447 					      &regcmd->destBitmap);
448 			return error;
449 		}
450 
451 		/* bitblt each plane */
452 		regcmd->srcBitmap.depth = 1;
453 		pmask = regcmd->planemask;
454 		regcmd->fore_color = 0xff;
455 		regcmd->aux_color = 0;
456 		if (mode == 2) {	/* N to 1 */
457 			for (i = 0; i < cmd->srcBitmap.depth; i++)
458 				if (pmask & (1 << i))
459 					break;
460 			if (i >= cmd->srcBitmap.depth)
461 				return 0;
462 			regcmd->srcBitmap.base += (len >> 1) * i;
463 			error = dobitblt(fbp, &regcmd->srcBitmap,
464 					      &regcmd->destBitmap);
465 			return error;
466 		}
467 		/* else (N to N) */
468 		for (i = 0; i < cmd->srcBitmap.depth; i++) {
469 			regcmd->planemask = pmask & (1 << i);
470 			if (error = dobitblt(fbp, &regcmd->srcBitmap,
471 						  &regcmd->destBitmap))
472 				return error;
473 			regcmd->srcBitmap.base += len >> 1;
474 			regcmd->planemask >>= 1;
475 		}
476 		return 0;
477 
478 	case BLTTYPE(BM_MEM, BM_MEM):
479 		lens = cmd->srcBitmap.width * cmd->srcBitmap.rect.extent.y << 1;
480 		lend = cmd->destBitmap.width * cmd->destBitmap.rect.extent.y << 1;
481 		if (lens * cmd->srcBitmap.depth <= FB_MAX_IO &&
482 		    lend * cmd->destBitmap.depth <= FB_MAX_IO) {
483 			error = dobitblt(fbp, &regcmd->srcBitmap,
484 					      &regcmd->destBitmap);
485 			return error;
486 		}
487 
488 		regcmd->srcBitmap.depth = 1;
489 		regcmd->destBitmap.depth = 1;
490 		pmask = regcmd->planemask;
491 		if (mode == 2) {	/* N to 1 */
492 			regcmd->fore_color = 0xff;
493 			regcmd->aux_color = 0;
494 			for (i = 0; i < cmd->srcBitmap.depth; i++)
495 				if (pmask & (1 << i))
496 					break;
497 			if (i >= cmd->srcBitmap.depth)
498 				return 0;
499 			regcmd->srcBitmap.base += (lens >> 1) * i;
500 			error = dobitblt(fbp, &regcmd->srcBitmap,
501 					      &regcmd->destBitmap);
502 			return error;
503 		} else if (mode == 1) {	/* 1 to N */
504 			for (i = 0; i < cmd->srcBitmap.depth; i++) {
505 				if (error = dobitblt(fbp, &regcmd->srcBitmap,
506 							  &regcmd->destBitmap))
507 					return error;
508 				regcmd->planemask >>= 1;
509 				regcmd->fore_color >>= 1;
510 				regcmd->aux_color >>= 1;
511 				regcmd->destBitmap.base += lend >> 1;
512 			}
513 			return 0;
514 		} else {		/* N to N */
515 			regcmd->fore_color = 0xff;
516 			regcmd->aux_color = 0;
517 			for (i = 0; i < cmd->srcBitmap.depth; i++) {
518 				if (error = dobitblt(fbp, &regcmd->srcBitmap,
519 							  &regcmd->destBitmap))
520 					return error;
521 				regcmd->srcBitmap.base += lens >> 1;
522 				regcmd->destBitmap.base += lend >> 1;
523 				regcmd->planemask >>= 1;
524 			}
525 			return 0;
526 		}
527 		break;
528 
529 	default:
530 		return EINVAL;
531 	}
532 
533 	return error;
534 }
535 
536 fbbitblt(fbp, cmd)
537 	struct fbreg *fbp;
538 	register sBitblt *cmd;
539 {
540 	lBitblt lcmd;
541 	register lBitblt *lcmdp;
542 
543 	lcmdp = &lcmd;
544 
545 	lcmdp->func = cmd->func;
546 	lcmdp->transp = cmd->transp;
547 	lcmdp->fore_color = cmd->fore_color;
548 	lcmdp->aux_color = cmd->aux_color;
549 	lcmdp->planemask = cmd->planemask;
550 	lcmdp->srcBitmap.type = cmd->srcBitmap.type;
551 	lcmdp->srcBitmap.depth = cmd->srcBitmap.depth;
552 	lcmdp->srcBitmap.width = cmd->srcBitmap.width;
553 	lcmdp->srcBitmap.rect.origin.x = cmd->srcBitmap.rect.origin.x;
554 	lcmdp->srcBitmap.rect.origin.y = cmd->srcBitmap.rect.origin.y;
555 	lcmdp->srcBitmap.rect.extent.x = cmd->srcBitmap.rect.extent.x;
556 	lcmdp->srcBitmap.rect.extent.y = cmd->srcBitmap.rect.extent.y;
557 	lcmdp->srcBitmap.base = cmd->srcBitmap.base;
558 	lcmdp->srcRect.origin.x = cmd->srcRect.origin.x;
559 	lcmdp->srcRect.origin.y = cmd->srcRect.origin.y;
560 	lcmdp->srcRect.extent.x = cmd->srcRect.extent.x;
561 	lcmdp->srcRect.extent.y = cmd->srcRect.extent.y;
562 	lcmdp->destBitmap.type = cmd->destBitmap.type;
563 	lcmdp->destBitmap.depth = cmd->destBitmap.depth;
564 	lcmdp->destBitmap.width = cmd->destBitmap.width;
565 	lcmdp->destBitmap.rect.origin.x = cmd->destBitmap.rect.origin.x;
566 	lcmdp->destBitmap.rect.origin.y = cmd->destBitmap.rect.origin.y;
567 	lcmdp->destBitmap.rect.extent.x = cmd->destBitmap.rect.extent.x;
568 	lcmdp->destBitmap.rect.extent.y = cmd->destBitmap.rect.extent.y;
569 	lcmdp->destBitmap.base = cmd->destBitmap.base;
570 	lcmdp->destClip.origin.x = cmd->destClip.origin.x;
571 	lcmdp->destClip.origin.y = cmd->destClip.origin.y;
572 	lcmdp->destClip.extent.x = cmd->destClip.extent.x;
573 	lcmdp->destClip.extent.y = cmd->destClip.extent.y;
574 	lcmdp->destPoint.x = cmd->destPoint.x;
575 	lcmdp->destPoint.y = cmd->destPoint.y;
576 	return (fbnbitblt(fbp, lcmdp));
577 }
578 
579 procbatchbitblt(fbp, mode, cmd)
580 	struct fbreg *fbp;
581 	int mode;
582 	register lBatchBitblt *cmd;
583 {
584 	register lBatchBitblt *regcmd;
585 	register int len, lens, lend;
586 	register int i;
587 	int pmask;
588 	int error = 0;
589 
590 	regcmd = &fbp->fb_batchbitblt;
591 	/* process batch bitblt command */
592 	switch (BLTTYPE(regcmd->srcBitmap.type, regcmd->destBitmap.type)) {
593 	case BLTTYPE(BM_FB, BM_FB):
594 	case BLTTYPE(BM_0, BM_FB):
595 	case BLTTYPE(BM_1, BM_FB):
596 		fbdolock();
597 		fbstart(fbp, cmd->nSrcDest);
598 		fbunlock();
599 		break;
600 
601 	case BLTTYPE(BM_FB, BM_MEM):
602 	case BLTTYPE(BM_0, BM_MEM):
603 	case BLTTYPE(BM_1, BM_MEM):
604 		len = cmd->destBitmap.width * cmd->destBitmap.rect.extent.y << 1;
605 		if (len * cmd->destBitmap.depth <= FB_MAX_IO) {
606 			error = dobitblt(fbp, &regcmd->srcBitmap,
607 					      &regcmd->destBitmap);
608 			return error;
609 		}
610 
611 		/* bitblt each plane */
612 		regcmd->destBitmap.depth = 1;
613 		pmask = regcmd->planemask;
614 		for (i = 0; i < cmd->destBitmap.depth; i++) {
615 			if (mode == 3)	/* N to N */
616 				regcmd->planemask = pmask & (1 << i);
617 
618 			if (error = dobitblt(fbp, &regcmd->srcBitmap,
619 						  &regcmd->destBitmap))
620 				return error;
621 
622 			regcmd->destBitmap.base += len >> 1;
623 			if (mode == 1) {	/* N to N */
624 				regcmd->planemask >>= 1;
625 				regcmd->fore_color >>= 1;
626 				regcmd->aux_color >>= 1;
627 			}
628 		}
629 		break;
630 
631 	case BLTTYPE(BM_MEM, BM_FB):
632 		len = cmd->srcBitmap.width * cmd->srcBitmap.rect.extent.y << 1;
633 
634 		if (len * cmd->srcBitmap.depth <= FB_MAX_IO) {
635 			error = dobitblt(fbp, &regcmd->srcBitmap,
636 					      &regcmd->destBitmap);
637 			return error;
638 		}
639 
640 		/* bitblt each plane */
641 		regcmd->srcBitmap.depth = 1;
642 		pmask = regcmd->planemask;
643 		regcmd->fore_color = 0xff;
644 		regcmd->aux_color = 0;
645 		if (mode == 2) {	/* N to 1 */
646 			for (i = 0; i < cmd->srcBitmap.depth; i++)
647 				if (pmask & (1 << i))
648 					break;
649 			if (i >= cmd->srcBitmap.depth)
650 				return 0;
651 			regcmd->srcBitmap.base += (len >> 1) * i;
652 			error = dobitblt(fbp, &regcmd->srcBitmap,
653 					      &regcmd->destBitmap);
654 			return error;
655 		}
656 		/* else (N to N) */
657 		for (i = 0; i < cmd->srcBitmap.depth; i++) {
658 			regcmd->planemask = pmask & (1 << i);
659 			if (error = dobitblt(fbp, &regcmd->srcBitmap,
660 						  &regcmd->destBitmap))
661 				return error;
662 			regcmd->srcBitmap.base += len >> 1;
663 			regcmd->planemask >>= 1;
664 		}
665 		return 0;
666 
667 	case BLTTYPE(BM_MEM, BM_MEM):
668 		lens = cmd->srcBitmap.width * cmd->srcBitmap.rect.extent.y << 1;
669 		lend = cmd->destBitmap.width * cmd->destBitmap.rect.extent.y << 1;
670 		if (lens * cmd->srcBitmap.depth <= FB_MAX_IO &&
671 		    lend * cmd->destBitmap.depth <= FB_MAX_IO) {
672 			error = dobitblt(fbp, &regcmd->srcBitmap,
673 					      &regcmd->destBitmap);
674 			return error;
675 		}
676 
677 		regcmd->srcBitmap.depth = 1;
678 		regcmd->destBitmap.depth = 1;
679 		pmask = regcmd->planemask;
680 		if (mode == 2) {	/* N to 1 */
681 			regcmd->fore_color = 0xff;
682 			regcmd->aux_color = 0;
683 			for (i = 0; i < cmd->srcBitmap.depth; i++)
684 				if (pmask & (1 << i))
685 					break;
686 			if (i >= cmd->srcBitmap.depth)
687 				return 0;
688 			regcmd->srcBitmap.base += (lens >> 1) * i;
689 			error = dobitblt(fbp, &regcmd->srcBitmap,
690 					      &regcmd->destBitmap);
691 			return error;
692 		} else if (mode == 1) {	/* 1 to N */
693 			for (i = 0; i < cmd->srcBitmap.depth; i++) {
694 				if (error = dobitblt(fbp, &regcmd->srcBitmap,
695 							  &regcmd->destBitmap))
696 					return error;
697 				regcmd->planemask >>= 1;
698 				regcmd->fore_color >>= 1;
699 				regcmd->aux_color >>= 1;
700 				regcmd->destBitmap.base += lend >> 1;
701 			}
702 			return 0;
703 		} else {		/* N to N */
704 			regcmd->fore_color = 0xff;
705 			regcmd->aux_color = 0;
706 			for (i = 0; i < cmd->srcBitmap.depth; i++) {
707 				if (error = dobitblt(fbp, &regcmd->srcBitmap,
708 							  &regcmd->destBitmap))
709 					return error;
710 				regcmd->srcBitmap.base += lens >> 1;
711 				regcmd->destBitmap.base += lend >> 1;
712 				regcmd->planemask >>= 1;
713 			}
714 			return 0;
715 		}
716 		break;
717 
718 	default:
719 		return EINVAL;
720 	}
721 
722 	return error;
723 }
724 
725 fbnbatchbitblt(fbp, cmd, seg)
726 	register struct fbreg *fbp;
727 	register lBatchBitblt *cmd;
728 	int seg;
729 {
730 	register int error;
731 	register int mode;
732 	register int len;
733 
734 #ifdef CPU_DOUBLE
735 	int blttype = BLTTYPE(cmd->srcBitmap.type, cmd->destBitmap.type);
736 
737 	if ((blttype == BLTTYPE(BM_MEM, BM_MEM)) ||
738 	    (blttype == BLTTYPE(BM_0, BM_MEM)) ||
739 	    (blttype == BLTTYPE(BM_1, BM_MEM))) {
740 		return(mfbnbatchbitblt(fbp, cmd, seg));
741 		/* notreached */
742 	}
743 #endif
744 
745 	fbinitlock();
746 	fbp->fb_command = FB_CBATCHBITBLT;
747 	fbp->fb_batchbitblt = *cmd;
748 
749 	if (error = checkbitmap(&cmd->srcBitmap))
750 		return error;
751 	if (error = checkbitmap(&cmd->destBitmap))
752 		return error;
753 	if ((mode = checkdepth(&cmd->srcBitmap, &cmd->destBitmap)) < 0)
754 		return EINVAL;
755 
756 #ifdef CPU_SINGLE
757 	if ((len = cmd->nSrcDest * sizeof(lSrcDest)) <= 0)
758 		return EINVAL;
759 	if (error = fblockmem((caddr_t)cmd->srcDestList,
760 			      len, B_WRITE, fbmap + 2, seg))
761 		return error;
762 	fbp->fb_batchbitblt.srcDestList = (lSrcDest *)ipc_phys(fbmap + 2);
763 	error = procbatchbitblt(fbp, mode, cmd);
764 #else
765 	fbp->fb_batchbitblt.srcDestList = (lSrcDest*)ipc_phys(srcdestlist);
766 	while(cmd->nSrcDest > 0) {
767 		len = min(cmd->nSrcDest, (MAX_SIZE / sizeof(lSrcDest)));
768 		error = COPYIN((caddr_t)cmd->srcDestList, (caddr_t)srcdestlist,
769 				len * sizeof(lSrcDest), seg);
770 		if (error)
771 			return error;
772 		cmd->nSrcDest -= len;
773 		cmd->srcDestList += len;
774 		fbp->fb_batchbitblt.nSrcDest = len;
775 
776 		if (error = procbatchbitblt(fbp, mode, cmd))
777 			return error;
778 	}
779 #endif /* CPU_DOUBLE */
780 	return error;
781 }
782 
783 fbbatchbitblt(fbp, cmd)
784 	struct fbreg *fbp;
785 	register sBatchBitblt *cmd;
786 {
787 	lBatchBitblt lcmd;
788 	register lBatchBitblt *lcmdp;
789 	static lSrcDest ls[100];
790 	register lSrcDest *lp;
791 	register sSrcDest *sp;
792 	register int ns;
793 
794 	lcmdp = &lcmd;
795 
796 	lcmdp->func = cmd->func;
797 	lcmdp->transp = cmd->transp;
798 	lcmdp->fore_color = cmd->fore_color;
799 	lcmdp->aux_color = cmd->aux_color;
800 	lcmdp->planemask = cmd->planemask;
801 	lcmdp->srcBitmap.type = cmd->srcBitmap.type;
802 	lcmdp->srcBitmap.depth = cmd->srcBitmap.depth;
803 	lcmdp->srcBitmap.width = cmd->srcBitmap.width;
804 	lcmdp->srcBitmap.rect.origin.x = cmd->srcBitmap.rect.origin.x;
805 	lcmdp->srcBitmap.rect.origin.y = cmd->srcBitmap.rect.origin.y;
806 	lcmdp->srcBitmap.rect.extent.x = cmd->srcBitmap.rect.extent.x;
807 	lcmdp->srcBitmap.rect.extent.y = cmd->srcBitmap.rect.extent.y;
808 	lcmdp->srcBitmap.base = cmd->srcBitmap.base;
809 	lcmdp->destBitmap.type = cmd->destBitmap.type;
810 	lcmdp->destBitmap.depth = cmd->destBitmap.depth;
811 	lcmdp->destBitmap.width = cmd->destBitmap.width;
812 	lcmdp->destBitmap.rect.origin.x = cmd->destBitmap.rect.origin.x;
813 	lcmdp->destBitmap.rect.origin.y = cmd->destBitmap.rect.origin.y;
814 	lcmdp->destBitmap.rect.extent.x = cmd->destBitmap.rect.extent.x;
815 	lcmdp->destBitmap.rect.extent.y = cmd->destBitmap.rect.extent.y;
816 	lcmdp->destBitmap.base = cmd->destBitmap.base;
817 	lcmdp->destClip.origin.x = cmd->destClip.origin.x;
818 	lcmdp->destClip.origin.y = cmd->destClip.origin.y;
819 	lcmdp->destClip.extent.x = cmd->destClip.extent.x;
820 	lcmdp->destClip.extent.y = cmd->destClip.extent.y;
821 	lcmdp->srcDestList = ls;
822 	sp = (sSrcDest *)cmd->srcDestList;
823 	while (cmd->nSrcDest) {
824 		lcmdp->nSrcDest = ns = min(cmd->nSrcDest, 100);
825 		cmd->nSrcDest -= ns;
826 		lp = ls;
827 		while (ns-- > 0) {
828 			int error;
829 			sSrcDest tmp;
830 
831 			error = copyin((caddr_t)sp, (caddr_t)&tmp, sizeof(tmp));
832 			if (error)
833 				return (error);
834 			lp->srcRect.origin.x = tmp.srcRect.origin.x;
835 			lp->srcRect.origin.y = tmp.srcRect.origin.y;
836 			lp->srcRect.extent.x = tmp.srcRect.extent.x;
837 			lp->srcRect.extent.y = tmp.srcRect.extent.y;
838 			lp->destPoint.x = tmp.destPoint.x;
839 			lp->destPoint.y = tmp.destPoint.y;
840 			lp++;
841 			sp++;
842 		}
843 		fbnbatchbitblt(fbp, lcmdp, UIO_SYSSPACE);
844 	}
845 }
846 
847 fbntilebitblt(fbp, cmd)
848 	register struct fbreg *fbp;
849 	register lTileBitblt *cmd;
850 {
851 	register lTileBitblt *regcmd;
852 	register int len, lens, lend;
853 	register int i;
854 	int mode;
855 	int pmask;
856 	int error;
857 	int blttype = BLTTYPE(cmd->ptnBitmap.type, cmd->destBitmap.type);
858 
859 #ifdef CPU_DOUBLE
860 	if ((blttype == BLTTYPE(BM_MEM, BM_MEM)) ||
861 	    (blttype == BLTTYPE(BM_0, BM_MEM)) ||
862 	    (blttype == BLTTYPE(BM_1, BM_MEM))) {
863 		return(mfbntilebitblt(fbp, cmd));
864 		/* NOTREACHED */
865 	}
866 #endif
867 
868 	if (error = checkbitmap(&cmd->ptnBitmap))
869 		return error;
870 	if (error = checkbitmap(&cmd->destBitmap))
871 		return error;
872 	if ((mode = checkdepth(&cmd->ptnBitmap, &cmd->destBitmap)) < 0)
873 		return EINVAL;
874 
875 	fbp->fb_command = FB_CTILEBITBLT;
876 	fbp->fb_tilebitblt = *cmd;
877 	regcmd = &fbp->fb_tilebitblt;
878 
879 	/* process bitblt command */
880 	switch (blttype) {
881 	case BLTTYPE(BM_FB, BM_FB):
882 	case BLTTYPE(BM_0, BM_FB):
883 	case BLTTYPE(BM_1, BM_FB):
884 		fbstart(fbp, 0);
885 		break;
886 
887 	case BLTTYPE(BM_FB, BM_MEM):
888 	case BLTTYPE(BM_0, BM_MEM):
889 	case BLTTYPE(BM_1, BM_MEM):
890 		len = cmd->destBitmap.width * cmd->destBitmap.rect.extent.y << 1;
891 		if (len * cmd->destBitmap.depth <= FB_MAX_IO) {
892 			error = dobitblt(fbp, &regcmd->ptnBitmap,
893 					      &regcmd->destBitmap);
894 			return error;
895 		}
896 
897 		/* bitblt each plane */
898 		regcmd->destBitmap.depth = 1;
899 		pmask = regcmd->planemask;
900 		for (i = 0; i < cmd->destBitmap.depth; i++) {
901 			if (mode == 3)	/* N to N */
902 				regcmd->planemask = pmask & (1 << i);
903 
904 			if (error = dobitblt(fbp, &regcmd->ptnBitmap,
905 						  &regcmd->destBitmap))
906 				return error;
907 
908 			regcmd->destBitmap.base += len >> 1;
909 			if (mode == 1) {	/* N to N */
910 				regcmd->planemask >>= 1;
911 				regcmd->fore_color >>= 1;
912 				regcmd->aux_color >>= 1;
913 			}
914 		}
915 		break;
916 
917 	case BLTTYPE(BM_MEM, BM_FB):
918 		len = cmd->ptnBitmap.width * cmd->ptnBitmap.rect.extent.y << 1;
919 
920 		if (len * cmd->ptnBitmap.depth <= FB_MAX_IO) {
921 			error = dobitblt(fbp, &regcmd->ptnBitmap,
922 					      &regcmd->destBitmap);
923 			return error;
924 		}
925 
926 		/* bitblt each plane */
927 		regcmd->ptnBitmap.depth = 1;
928 		pmask = regcmd->planemask;
929 		regcmd->fore_color = 0xff;
930 		regcmd->aux_color = 0;
931 		if (mode == 2) {	/* N to 1 */
932 			for (i = 0; i < cmd->ptnBitmap.depth; i++)
933 				if (pmask & (1 << i))
934 					break;
935 			if (i >= cmd->ptnBitmap.depth)
936 				return 0;
937 			regcmd->ptnBitmap.base += (len >> 1) * i;
938 			error = dobitblt(fbp, &regcmd->ptnBitmap,
939 					      &regcmd->destBitmap);
940 			return error;
941 		}
942 		/* else (N to N) */
943 		for (i = 0; i < cmd->ptnBitmap.depth; i++) {
944 			regcmd->planemask = pmask & (1 << i);
945 			if (error = dobitblt(fbp, &regcmd->ptnBitmap,
946 						  &regcmd->destBitmap))
947 				return error;
948 			regcmd->ptnBitmap.base += len >> 1;
949 			regcmd->planemask >>= 1;
950 		}
951 		return 0;
952 
953 	case BLTTYPE(BM_MEM, BM_MEM):
954 		lens = cmd->ptnBitmap.width * cmd->ptnBitmap.rect.extent.y << 1;
955 		lend = cmd->destBitmap.width * cmd->destBitmap.rect.extent.y << 1;
956 		if (lens * cmd->ptnBitmap.depth <= FB_MAX_IO &&
957 		    lend * cmd->destBitmap.depth <= FB_MAX_IO) {
958 			error = dobitblt(fbp, &regcmd->ptnBitmap,
959 					      &regcmd->destBitmap);
960 			return error;
961 		}
962 
963 		regcmd->ptnBitmap.depth = 1;
964 		regcmd->destBitmap.depth = 1;
965 		pmask = regcmd->planemask;
966 		if (mode == 2) {	/* N to 1 */
967 			regcmd->fore_color = 0xff;
968 			regcmd->aux_color = 0;
969 			for (i = 0; i < cmd->ptnBitmap.depth; i++)
970 				if (pmask & (1 << i))
971 					break;
972 			if (i >= cmd->ptnBitmap.depth)
973 				return 0;
974 			regcmd->ptnBitmap.base += (lens >> 1) * i;
975 			error = dobitblt(fbp, &regcmd->ptnBitmap,
976 					      &regcmd->destBitmap);
977 			return error;
978 		} else if (mode == 1) {	/* 1 to N */
979 			for (i = 0; i < cmd->ptnBitmap.depth; i++) {
980 				if (error = dobitblt(fbp, &regcmd->ptnBitmap,
981 							  &regcmd->destBitmap))
982 					return error;
983 				regcmd->planemask >>= 1;
984 				regcmd->fore_color >>= 1;
985 				regcmd->aux_color >>= 1;
986 				regcmd->destBitmap.base += lend >> 1;
987 			}
988 			return 0;
989 		} else {		/* N to N */
990 			for (i = 0; i < cmd->ptnBitmap.depth; i++) {
991 				if (error = dobitblt(fbp, &regcmd->ptnBitmap,
992 							  &regcmd->destBitmap))
993 					return error;
994 				regcmd->ptnBitmap.base += lens >> 1;
995 				regcmd->destBitmap.base += lend >> 1;
996 				regcmd->planemask >>= 1;
997 			}
998 			return 0;
999 		}
1000 		break;
1001 
1002 	default:
1003 		return EINVAL;
1004 	}
1005 	return error;
1006 }
1007 
1008 fbtilebitblt(fbp, cmd)
1009 	struct fbreg *fbp;
1010 	register sTileBitblt *cmd;
1011 {
1012 	lTileBitblt lcmd;
1013 	register lTileBitblt *lcmdp;
1014 
1015 	lcmdp = &lcmd;
1016 
1017 	lcmdp->func = cmd->func;
1018 	lcmdp->transp = cmd->transp;
1019 	lcmdp->fore_color = cmd->fore_color;
1020 	lcmdp->aux_color = cmd->aux_color;
1021 	lcmdp->planemask = cmd->planemask;
1022 	lcmdp->ptnBitmap.type = cmd->ptnBitmap.type;
1023 	lcmdp->ptnBitmap.depth = cmd->ptnBitmap.depth;
1024 	lcmdp->ptnBitmap.width = cmd->ptnBitmap.width;
1025 	lcmdp->ptnBitmap.rect.origin.x = cmd->ptnBitmap.rect.origin.x;
1026 	lcmdp->ptnBitmap.rect.origin.y = cmd->ptnBitmap.rect.origin.y;
1027 	lcmdp->ptnBitmap.rect.extent.x = cmd->ptnBitmap.rect.extent.x;
1028 	lcmdp->ptnBitmap.rect.extent.y = cmd->ptnBitmap.rect.extent.y;
1029 	lcmdp->ptnBitmap.base = cmd->ptnBitmap.base;
1030 	lcmdp->ptnRect.origin.x = cmd->ptnRect.origin.x;
1031 	lcmdp->ptnRect.origin.y = cmd->ptnRect.origin.y;
1032 	lcmdp->ptnRect.extent.x = cmd->ptnRect.extent.x;
1033 	lcmdp->ptnRect.extent.y = cmd->ptnRect.extent.y;
1034 	lcmdp->refPoint.x = cmd->refPoint.x;
1035 	lcmdp->refPoint.y = cmd->refPoint.y;
1036 	lcmdp->destBitmap.type = cmd->destBitmap.type;
1037 	lcmdp->destBitmap.depth = cmd->destBitmap.depth;
1038 	lcmdp->destBitmap.width = cmd->destBitmap.width;
1039 	lcmdp->destBitmap.rect.origin.x = cmd->destBitmap.rect.origin.x;
1040 	lcmdp->destBitmap.rect.origin.y = cmd->destBitmap.rect.origin.y;
1041 	lcmdp->destBitmap.rect.extent.x = cmd->destBitmap.rect.extent.x;
1042 	lcmdp->destBitmap.rect.extent.y = cmd->destBitmap.rect.extent.y;
1043 	lcmdp->destBitmap.base = cmd->destBitmap.base;
1044 	lcmdp->destClip.origin.x = cmd->destClip.origin.x;
1045 	lcmdp->destClip.origin.y = cmd->destClip.origin.y;
1046 	lcmdp->destClip.extent.x = cmd->destClip.extent.x;
1047 	lcmdp->destClip.extent.y = cmd->destClip.extent.y;
1048 	lcmdp->destRect.origin.x = cmd->destRect.origin.x;
1049 	lcmdp->destRect.origin.y = cmd->destRect.origin.y;
1050 	lcmdp->destRect.extent.x = cmd->destRect.extent.x;
1051 	lcmdp->destRect.extent.y = cmd->destRect.extent.y;
1052 	return (fbntilebitblt(fbp, lcmdp));
1053 }
1054 
1055 /* ARGSUSED */
1056 fbbitblt3(fbp, cmd)
1057 	struct fbreg *fbp;
1058 	sBitblt3 *cmd;
1059 {
1060 	return ENXIO;
1061 }
1062 
1063 /* ARGSUSED */
1064 fbnbitblt3(fbp, cmd)
1065 	struct fbreg *fbp;
1066 	lBitblt3 *cmd;
1067 {
1068 	return ENXIO;
1069 }
1070 
1071 fbnpolyline(fbp, cmd, dj, seg)
1072 	struct fbreg *fbp;
1073 	register lPrimLine *cmd;
1074 	int dj;			/* if not zero, disjoint polyline */
1075 	int seg;
1076 {
1077 	register int error = 0;
1078 	register int len;
1079 
1080 #ifdef CPU_DOUBLE
1081 	if(cmd->drawBM.type == BM_MEM) {
1082 		return(mfbnpolyline(fbp, cmd, dj, seg));
1083 		/* NOTREACHED */
1084 	}
1085 #endif
1086 
1087 	fbinitlock();
1088 	fbp->fb_command = dj ? FB_CDJPOLYLINE : FB_CPOLYLINE;
1089 	fbp->fb_polyline = *cmd;
1090 
1091 	if ((cmd->np & 1) && dj)
1092 		return EINVAL;
1093 
1094 #ifdef CPU_SINGLE
1095 	if (error = fblocksbitmap(&fbp->fb_polyline.drawBM, B_READ, fbmap))
1096 		return error;
1097 	if ((len = cmd->np * sizeof(lPoint)) <= 0)
1098 		return EINVAL;
1099 	error = fblockmem((caddr_t)cmd->plist, len, B_WRITE, fbmap + 1, seg);
1100 	if (error)
1101 		return error;
1102 	fbp->fb_polyline.plist = (lPoint *)ipc_phys(fbmap + 1);
1103 
1104 	fbdolock();
1105 	fbstart(fbp, 1);
1106 	fbunlock();
1107 #else /* CPU_SINGLE */
1108 	fbp->fb_polyline.plist = (lPoint *)ipc_phys(srcdestlist);
1109 	while (cmd->np > 0) {
1110 		len = min(cmd->np, ((MAX_SIZE / sizeof(lPoint)) & ~1));
1111 		fbp->fb_polyline.np = len;
1112 		if (error = COPYIN((caddr_t)cmd->plist, (caddr_t)srcdestlist,
1113 				   len * sizeof(lPoint), seg)) {
1114 			return error;
1115 		}
1116 		cmd->np -= len;
1117 		cmd->plist += len;
1118 
1119 		if (fbp->fb_polyline.drawBM.type == BM_MEM) {
1120 			if (error = fblocksbitmap(&fbp->fb_polyline.drawBM,
1121 						  B_READ, fbmap)) {
1122 				return error;
1123 			}
1124 			fbdolock();
1125 			fbstart(fbp, 1);
1126 			fbunlock();
1127 		} else if (cmd->np)
1128 			fbstart(fbp, 1);
1129 		else
1130 			fbstart(fbp, 0);
1131 		if (!dj && cmd->np) {
1132 			cmd->np++;
1133 			cmd->plist--;
1134 		}
1135 	}
1136 #endif /* CPU_SINGLE */
1137 	return error;
1138 }
1139 
1140 fbpolyline(fbp, cmd, dj)
1141 	struct fbreg *fbp;
1142 	register sPrimLine *cmd;
1143 	int dj;
1144 {
1145 	lPrimLine lcmd;
1146 	register lPrimLine *lcmdp;
1147 	static lPoint 	pl[100];
1148 	register lPoint *lp;
1149 	register sPoint *sp;
1150 	register int	np;
1151 
1152 	lcmdp = &lcmd;
1153 
1154 	lcmdp->func = cmd->func;
1155 	lcmdp->transp = cmd->transp;
1156 	lcmdp->fore_color = cmd->fore_color;
1157 	lcmdp->aux_color = cmd->aux_color;
1158 	lcmdp->planemask = cmd->planemask;
1159 	lcmdp->drawBM.type = cmd->drawBM.type;
1160 	lcmdp->drawBM.depth = cmd->drawBM.depth;
1161 	lcmdp->drawBM.width = cmd->drawBM.width;
1162 	lcmdp->drawBM.rect.origin.x = cmd->drawBM.rect.origin.x;
1163 	lcmdp->drawBM.rect.origin.y = cmd->drawBM.rect.origin.y;
1164 	lcmdp->drawBM.rect.extent.x = cmd->drawBM.rect.extent.x;
1165 	lcmdp->drawBM.rect.extent.y = cmd->drawBM.rect.extent.y;
1166 	lcmdp->drawBM.base = cmd->drawBM.base;
1167 	lcmdp->clip.origin.x = cmd->clip.origin.x;
1168 	lcmdp->clip.origin.y = cmd->clip.origin.y;
1169 	lcmdp->clip.extent.x = cmd->clip.extent.x;
1170 	lcmdp->clip.extent.y = cmd->clip.extent.y;
1171 	lcmdp->lptn = cmd->lptn;
1172 	lcmdp->dlpf = cmd->dlpf;
1173 	lcmdp->plist = pl;
1174 	sp = (sPoint *)cmd->plist;
1175 	while (cmd->np) {
1176 		lcmdp->np = np = min(cmd->np, 100);
1177 		cmd->np -= np;
1178 		lp = pl;
1179 		while (np-- > 0) {
1180 			int error;
1181 			sPoint tmp;
1182 
1183 			if (error = copyin((caddr_t)sp, (caddr_t)&tmp, sizeof (tmp)))
1184 				return (error);
1185 			lp->x = tmp.x;
1186 			lp->y = tmp.y;
1187 			lp++;
1188 			sp++;
1189 		}
1190 		fbnpolyline(fbp, lcmdp, dj, UIO_SYSSPACE);
1191 	}
1192 }
1193 
1194 fbnfillscan(fbp, cmd, seg)
1195 	struct fbreg *fbp;
1196 	register lPrimFill *cmd;
1197 	int seg;
1198 {
1199 	register int error;
1200 	register int len;
1201 
1202 #ifdef CPU_DOUBLE
1203 	int blttype = BLTTYPE(cmd->ptnBM.type, cmd->drawBM.type);
1204 
1205 	if ((blttype == BLTTYPE(BM_MEM, BM_MEM)) ||
1206 	    (blttype == BLTTYPE(BM_0, BM_MEM)) ||
1207 	    (blttype == BLTTYPE(BM_1, BM_MEM))) {
1208 		return(mfbnfillscan(fbp, cmd, seg));
1209 		/* NOTREACHED */
1210 	}
1211 #endif
1212 
1213 	fbinitlock();
1214 	fbp->fb_command = FB_CFILLSCAN;
1215 	fbp->fb_fillscan = *cmd;
1216 
1217 #ifdef CPU_SINGLE
1218 	if (error = fblocksbitmap(&fbp->fb_fillscan.ptnBM, B_WRITE, fbmap))
1219 		return error;
1220 	if (error = fblocksbitmap(&fbp->fb_fillscan.drawBM, B_READ, fbmap + 1))
1221 		return error;
1222 	if ((len = cmd->nscan * sizeof(lScanl)) <= 0)
1223 		return EINVAL;
1224 	if (error = fblockmem(cmd->scan, len, B_WRITE, fbmap + 2, seg))
1225 		return error;
1226 	fbp->fb_fillscan.scan = (lScanl *)ipc_phys(fbmap + 2);
1227 
1228 	fbdolock();
1229 	fbstart(fbp, 1);
1230 	fbunlock();
1231 #else /* CPU_SINGLE */
1232 	fbp->fb_fillscan.scan = (lScanl *)ipc_phys(srcdestlist);
1233 	while (cmd->nscan > 0) {
1234 		len = min(cmd->nscan, (MAX_SIZE / sizeof(lScanl)));
1235 		fbp->fb_fillscan.nscan = len;
1236 		if (error = COPYIN((caddr_t)cmd->scan, (caddr_t)srcdestlist,
1237 				   len * sizeof(lScanl), seg)) {
1238 			return error;
1239 		}
1240 		cmd->nscan -= len;
1241 		cmd->scan += len;
1242 		if (fbp->fb_fillscan.ptnBM.type == BM_MEM ||
1243 		    fbp->fb_fillscan.drawBM.type == BM_MEM) {
1244 
1245 			if (error = fblocksbitmap(&fbp->fb_fillscan.ptnBM,
1246 						  B_WRITE, fbmap)) {
1247 				return error;
1248 			}
1249 			if (error = fblocksbitmap(&fbp->fb_fillscan.drawBM,
1250 						  B_READ, fbmap + 1)) {
1251 				return error;
1252 			}
1253 
1254 			fbdolock();
1255 			fbstart(fbp, 1);
1256 			fbunlock();
1257 		} else if (cmd->nscan)
1258 			fbstart(fbp, 1);
1259 		else
1260 			fbstart(fbp, 0);
1261 	}
1262 #endif /* CPU_SINGLE */
1263 	return error;
1264 }
1265 
1266 fbfillscan(fbp, cmd)
1267 	struct fbreg *fbp;
1268 	register sPrimFill *cmd;
1269 {
1270 	lPrimFill lcmd;
1271 	register lPrimFill *lcmdp;
1272 	static lScanl	ls[100];
1273 	register lScanl	*lp;
1274 	register sScanl	*sp;
1275 	register int	ns;
1276 
1277 	lcmdp = &lcmd;
1278 	lcmdp->func = cmd->func;
1279 	lcmdp->transp = cmd->transp;
1280 	lcmdp->fore_color = cmd->fore_color;
1281 	lcmdp->aux_color = cmd->aux_color;
1282 	lcmdp->planemask = cmd->planemask;
1283 	lcmdp->refPoint.x = cmd->refPoint.x;
1284 	lcmdp->refPoint.y = cmd->refPoint.y;
1285 	lcmdp->ptnRect.origin.x = cmd->ptnRect.origin.x;
1286 	lcmdp->ptnRect.origin.y = cmd->ptnRect.origin.y;
1287 	lcmdp->ptnRect.extent.x = cmd->ptnRect.extent.x;
1288 	lcmdp->ptnRect.extent.y = cmd->ptnRect.extent.y;
1289 	lcmdp->ptnBM.type = cmd->ptnBM.type;
1290 	lcmdp->ptnBM.depth = cmd->ptnBM.depth;
1291 	lcmdp->ptnBM.width = cmd->ptnBM.width;
1292 	lcmdp->ptnBM.rect.origin.x = cmd->ptnBM.rect.origin.x;
1293 	lcmdp->ptnBM.rect.origin.y = cmd->ptnBM.rect.origin.y;
1294 	lcmdp->ptnBM.rect.extent.x = cmd->ptnBM.rect.extent.x;
1295 	lcmdp->ptnBM.rect.extent.y = cmd->ptnBM.rect.extent.y;
1296 	lcmdp->ptnBM.base = cmd->ptnBM.base;
1297 	lcmdp->drawBM.type = cmd->drawBM.type;
1298 	lcmdp->drawBM.depth = cmd->drawBM.depth;
1299 	lcmdp->drawBM.width = cmd->drawBM.width;
1300 	lcmdp->drawBM.rect.origin.x = cmd->drawBM.rect.origin.x;
1301 	lcmdp->drawBM.rect.origin.y = cmd->drawBM.rect.origin.y;
1302 	lcmdp->drawBM.rect.extent.x = cmd->drawBM.rect.extent.x;
1303 	lcmdp->drawBM.rect.extent.y = cmd->drawBM.rect.extent.y;
1304 	lcmdp->drawBM.base = cmd->drawBM.base;
1305 	lcmdp->clip.origin.x = cmd->clip.origin.x;
1306 	lcmdp->clip.origin.y = cmd->clip.origin.y;
1307 	lcmdp->clip.extent.x = cmd->clip.extent.x;
1308 	lcmdp->clip.extent.y = cmd->clip.extent.y;
1309 	lcmdp->scan = ls;
1310 	sp = (sScanl *)cmd->scan;
1311 	while (cmd->nscan) {
1312 		lcmdp->nscan = ns = min(cmd->nscan, 100);
1313 		cmd->nscan -= ns;
1314 		lp = ls;
1315 		while (ns-- > 0) {
1316 			int error;
1317 			sScanl tmp;
1318 
1319 			if (error = copyin((caddr_t)sp, (caddr_t)&tmp, sizeof (tmp)))
1320 				return (error);
1321 			lp->x0 = tmp.x0;
1322 			lp->x1 = tmp.x1;
1323 			lp->y = tmp.y;
1324 			lp++;
1325 			sp++;
1326 		}
1327 		fbnfillscan(fbp, lcmdp, UIO_SYSSPACE);
1328 	}
1329 }
1330 
1331 fbnrectangle(fbp, cmd)
1332 	struct fbreg *fbp;
1333 	register lPrimRect *cmd;
1334 {
1335 	register int error = 0;
1336 
1337 #ifdef CPU_DOUBLE
1338 	int blttype = BLTTYPE(cmd->ptnBM.type, cmd->drawBM.type);
1339 
1340 	if ((blttype == BLTTYPE(BM_MEM, BM_MEM)) ||
1341 	    (blttype == BLTTYPE(BM_0, BM_MEM)) ||
1342 	    (blttype == BLTTYPE(BM_1, BM_MEM))) {
1343 		return(mfbnrectangle(fbp, cmd));
1344 		/* NOTREACHED */
1345 	}
1346 #endif /* CPU_DOUBLE */
1347 
1348 	fbinitlock();
1349 	fbp->fb_command = FB_CRECTANGLE;
1350 	fbp->fb_rectangle = *cmd;
1351 
1352 	if (error = fblocksbitmap(&fbp->fb_rectangle.drawBM, B_READ, fbmap))
1353 		return error;
1354 	if (error = fblocksbitmap(&fbp->fb_rectangle.ptnBM, B_WRITE, fbmap + 1))
1355 		return error;
1356 
1357 	if (fbp->fb_rectangle.drawBM.type == BM_MEM ||
1358 	    fbp->fb_rectangle.ptnBM.type == BM_MEM) {
1359 		fbdolock();
1360 		fbstart(fbp, 1);
1361 		fbunlock();
1362 	} else {
1363 		fbstart(fbp, 0);
1364 	}
1365 
1366 	return error;
1367 }
1368 
1369 fbrectangle(fbp, cmd)
1370 	struct fbreg *fbp;
1371 	register sPrimRect *cmd;
1372 {
1373 	lPrimRect lcmd;
1374 	register lPrimRect *lcmdp;
1375 
1376 	lcmdp = &lcmd;
1377 
1378 	lcmdp->func = cmd->func;
1379 	lcmdp->transp = cmd->transp;
1380 	lcmdp->fore_color = cmd->fore_color;
1381 	lcmdp->aux_color = cmd->aux_color;
1382 	lcmdp->planemask = cmd->planemask;
1383 	lcmdp->rect.origin.x = cmd->rect.origin.x;
1384 	lcmdp->rect.origin.y = cmd->rect.origin.y;
1385 	lcmdp->rect.extent.x = cmd->rect.extent.x;
1386 	lcmdp->rect.extent.y = cmd->rect.extent.y;
1387 	lcmdp->refPoint.x = cmd->refPoint.x;
1388 	lcmdp->refPoint.y = cmd->refPoint.y;
1389 	lcmdp->ptnRect.origin.x = cmd->ptnRect.origin.x;
1390 	lcmdp->ptnRect.origin.y = cmd->ptnRect.origin.y;
1391 	lcmdp->ptnRect.extent.x = cmd->ptnRect.extent.x;
1392 	lcmdp->ptnRect.extent.y = cmd->ptnRect.extent.y;
1393 	lcmdp->ptnBM.type = cmd->ptnBM.type;
1394 	lcmdp->ptnBM.depth = cmd->ptnBM.depth;
1395 	lcmdp->ptnBM.width = cmd->ptnBM.width;
1396 	lcmdp->ptnBM.rect.origin.x = cmd->ptnBM.rect.origin.x;
1397 	lcmdp->ptnBM.rect.origin.y = cmd->ptnBM.rect.origin.y;
1398 	lcmdp->ptnBM.rect.extent.x = cmd->ptnBM.rect.extent.x;
1399 	lcmdp->ptnBM.rect.extent.y = cmd->ptnBM.rect.extent.y;
1400 	lcmdp->ptnBM.base = cmd->ptnBM.base;
1401 	lcmdp->drawBM.type = cmd->drawBM.type;
1402 	lcmdp->drawBM.depth = cmd->drawBM.depth;
1403 	lcmdp->drawBM.width = cmd->drawBM.width;
1404 	lcmdp->drawBM.rect.origin.x = cmd->drawBM.rect.origin.x;
1405 	lcmdp->drawBM.rect.origin.y = cmd->drawBM.rect.origin.y;
1406 	lcmdp->drawBM.rect.extent.x = cmd->drawBM.rect.extent.x;
1407 	lcmdp->drawBM.rect.extent.y = cmd->drawBM.rect.extent.y;
1408 	lcmdp->drawBM.base = cmd->drawBM.base;
1409 	lcmdp->clip.origin.x = cmd->clip.origin.x;
1410 	lcmdp->clip.origin.y = cmd->clip.origin.y;
1411 	lcmdp->clip.extent.x = cmd->clip.extent.x;
1412 	lcmdp->clip.extent.y = cmd->clip.extent.y;
1413 	return (fbnrectangle(fbp, lcmdp));
1414 }
1415 
1416 fbnpolymarker(fbp, cmd, seg)
1417 	register struct fbreg *fbp;
1418 	register lPrimMarker *cmd;
1419 	int seg;
1420 {
1421 	register int error;
1422 	register int len;
1423 
1424 #ifdef CPU_DOUBLE
1425 	int blttype = BLTTYPE(cmd->ptnBM.type, cmd->drawBM.type);
1426 
1427 	if ((blttype == BLTTYPE(BM_MEM, BM_MEM)) ||
1428 	    (blttype == BLTTYPE(BM_0, BM_MEM)) ||
1429 	    (blttype == BLTTYPE(BM_1, BM_MEM))) {
1430 		return(mfbnpolymarker(fbp, cmd, seg));
1431 		/* NOTREACHED */
1432 	}
1433 #endif /* CPU_DOUBLE */
1434 
1435 	fbinitlock();
1436 	fbp->fb_command = FB_CPOLYMARKER;
1437 	fbp->fb_polymarker = *cmd;
1438 
1439 #ifdef CPU_SINGLE
1440 	if (error = fblocksbitmap(&fbp->fb_polymarker.ptnBM, B_WRITE, fbmap))
1441 		return error;
1442 	if (error = fblocksbitmap(&fbp->fb_polymarker.drawBM, B_READ, fbmap+1))
1443 		return error;
1444 	if ((len = cmd->np * sizeof(lPoint)) <= 0)
1445 		return EINVAL;
1446 	if (error = fblockmem(cmd->plist, len, B_WRITE, fbmap + 2, seg))
1447 		return error;
1448 	fbp->fb_polymarker.plist = (lPoint *)ipc_phys(fbmap + 2);
1449 
1450 	fbdolock();
1451 	fbstart(fbp, 1);
1452 	fbunlock();
1453 #else /* CPU_SINGLE */
1454 	fbp->fb_polymarker.plist = (lPoint *)ipc_phys(srcdestlist);
1455 	while (cmd->np > 0) {
1456 		len = min(cmd->np, (MAX_SIZE / sizeof(lPoint)));
1457 		fbp->fb_polymarker.np = len;
1458 		if (error = COPYIN((caddr_t)cmd->plist, (caddr_t)srcdestlist,
1459 				   len * sizeof(lPoint), seg)) {
1460 			return error;
1461 		}
1462 		cmd->np -= len;
1463 		cmd->plist += len;
1464 
1465 		if (fbp->fb_polymarker.ptnBM.type == BM_MEM ||
1466 		    fbp->fb_polymarker.drawBM.type == BM_MEM) {
1467 
1468 			if (error = fblocksbitmap(&fbp->fb_polymarker.ptnBM,
1469 						  B_WRITE, fbmap)) {
1470 				return error;
1471 			}
1472 			if (error = fblocksbitmap(&fbp->fb_polymarker.drawBM,
1473 						  B_READ, fbmap + 1)) {
1474 				return error;
1475 			}
1476 
1477 			fbdolock();
1478 			fbstart(fbp, 1);
1479 			fbunlock();
1480 		} else if (cmd->np)
1481 			fbstart(fbp, 1);
1482 		else
1483 			fbstart(fbp, 0);
1484 	}
1485 #endif /* CPU_SINGLE */
1486 	return error;
1487 }
1488 
1489 fbpolymarker(fbp, cmd)
1490 	struct fbreg *fbp;
1491 	register sPrimMarker *cmd;
1492 {
1493 	lPrimMarker lcmd;
1494 	register lPrimMarker *lcmdp;
1495 	static lPoint pl[100];
1496 	register lPoint *lp;
1497 	register sPoint *sp;
1498 	register int np;
1499 
1500 	lcmdp = &lcmd;
1501 	lcmdp->func = cmd->func;
1502 	lcmdp->transp = cmd->transp;
1503 	lcmdp->fore_color = cmd->fore_color;
1504 	lcmdp->aux_color = cmd->aux_color;
1505 	lcmdp->planemask = cmd->planemask;
1506 	lcmdp->ptnRect.origin.x = cmd->ptnRect.origin.x;
1507 	lcmdp->ptnRect.origin.y = cmd->ptnRect.origin.y;
1508 	lcmdp->ptnRect.extent.x = cmd->ptnRect.extent.x;
1509 	lcmdp->ptnRect.extent.y = cmd->ptnRect.extent.y;
1510 	lcmdp->ptnBM.type = cmd->ptnBM.type;
1511 	lcmdp->ptnBM.depth = cmd->ptnBM.depth;
1512 	lcmdp->ptnBM.width = cmd->ptnBM.width;
1513 	lcmdp->ptnBM.rect.origin.x = cmd->ptnBM.rect.origin.x;
1514 	lcmdp->ptnBM.rect.origin.y = cmd->ptnBM.rect.origin.y;
1515 	lcmdp->ptnBM.rect.extent.x = cmd->ptnBM.rect.extent.x;
1516 	lcmdp->ptnBM.rect.extent.y = cmd->ptnBM.rect.extent.y;
1517 	lcmdp->ptnBM.base = cmd->ptnBM.base;
1518 	lcmdp->drawBM.type = cmd->drawBM.type;
1519 	lcmdp->drawBM.depth = cmd->drawBM.depth;
1520 	lcmdp->drawBM.width = cmd->drawBM.width;
1521 	lcmdp->drawBM.rect.origin.x = cmd->drawBM.rect.origin.x;
1522 	lcmdp->drawBM.rect.origin.y = cmd->drawBM.rect.origin.y;
1523 	lcmdp->drawBM.rect.extent.x = cmd->drawBM.rect.extent.x;
1524 	lcmdp->drawBM.rect.extent.y = cmd->drawBM.rect.extent.y;
1525 	lcmdp->drawBM.base = cmd->drawBM.base;
1526 	lcmdp->clip.origin.x = cmd->clip.origin.x;
1527 	lcmdp->clip.origin.y = cmd->clip.origin.y;
1528 	lcmdp->clip.extent.x = cmd->clip.extent.x;
1529 	lcmdp->clip.extent.y = cmd->clip.extent.y;
1530 	lcmdp->plist = pl;
1531 	sp = (sPoint *)cmd->plist;
1532 	while (cmd->np) {
1533 		lcmdp->np = np = min(cmd->np, 100);
1534 		cmd->np -= np;
1535 		while (np-- > 0) {
1536 			int error;
1537 			sPoint tmp;
1538 
1539 			if (error = copyin((caddr_t)sp, (caddr_t)&tmp, sizeof (tmp)))
1540 				return (error);
1541 			lp->x = tmp.x;
1542 			lp->y = tmp.y;
1543 			lp++;
1544 			sp++;
1545 		}
1546 		fbnpolymarker(fbp, lcmdp, UIO_SYSSPACE);
1547 	}
1548 }
1549 
1550 fbnpolydot(fbp, cmd, seg)
1551 	register struct fbreg *fbp;
1552 	register lPrimDot *cmd;
1553 	int seg;
1554 {
1555 	register int error;
1556 	register int len;
1557 
1558 #ifdef CPU_DOUBLE
1559 	if (cmd->drawBM.type == BM_MEM)
1560 		return (mfbnpolydot(fbp, cmd, seg));
1561 #endif
1562 
1563 	fbinitlock();
1564 	fbp->fb_command = FB_CPOLYDOT;
1565 	fbp->fb_polydot = *cmd;
1566 
1567 #ifdef CPU_SINGLE
1568 	if (error = fblocksbitmap(&fbp->fb_polydot.drawBM, B_READ, fbmap + 1))
1569 		return error;
1570 	if ((len = cmd->np * sizeof(lPoint)) <= 0)
1571 		return EINVAL;
1572 	if (error = fblockmem(cmd->plist, len, B_WRITE, fbmap + 2, seg))
1573 		return error;
1574 	fbp->fb_polydot.plist = (lPoint *)ipc_phys(fbmap + 2);
1575 
1576 	fbdolock();
1577 	fbstart(fbp, 1);
1578 	fbunlock();
1579 #else /* CPU_SINGLE */
1580 	fbp->fb_polydot.plist = (lPoint *)ipc_phys(srcdestlist);
1581 	while (cmd->np > 0) {
1582 		len = min(cmd->np, (MAX_SIZE / sizeof(lPoint)));
1583 		fbp->fb_polydot.np = len;
1584 		if (error = COPYIN((caddr_t)cmd->plist, (caddr_t)srcdestlist,
1585 				   len * sizeof(lPoint), seg)) {
1586 			return error;
1587 		}
1588 		cmd->np -= len;
1589 		cmd->plist += len;
1590 
1591 		if (fbp->fb_polydot.drawBM.type == BM_MEM) {
1592 			if (error = fblocksbitmap(&fbp->fb_polydot.drawBM,
1593 						  B_READ, fbmap + 1)) {
1594 				return error;
1595 			}
1596 
1597 			fbdolock();
1598 			fbstart(fbp, 1);
1599 			fbunlock();
1600 		} else if (cmd->np)
1601 			fbstart(fbp, 1);
1602 		else
1603 			fbstart(fbp, 0);
1604 	}
1605 #endif /* CPU_SINGLE */
1606 	return error;
1607 }
1608 
1609 fbpolydot(fbp, cmd)
1610 	struct fbreg *fbp;
1611 	register sPrimDot *cmd;
1612 {
1613 	lPrimDot lcmd;
1614 	register lPrimDot *lcmdp;
1615 	static lPoint	pl[100];
1616 	register lPoint	*lp;
1617 	register sPoint	*sp;
1618 	register int	np;
1619 
1620 	lcmdp = &lcmd;
1621 	lcmdp->func = cmd->func;
1622 	lcmdp->transp = cmd->transp;
1623 	lcmdp->fore_color = cmd->fore_color;
1624 	lcmdp->aux_color = cmd->aux_color;
1625 	lcmdp->planemask = cmd->planemask;
1626 	lcmdp->drawBM.type = cmd->drawBM.type;
1627 	lcmdp->drawBM.depth = cmd->drawBM.depth;
1628 	lcmdp->drawBM.width = cmd->drawBM.width;
1629 	lcmdp->drawBM.rect.origin.x = cmd->drawBM.rect.origin.x;
1630 	lcmdp->drawBM.rect.origin.y = cmd->drawBM.rect.origin.y;
1631 	lcmdp->drawBM.rect.extent.x = cmd->drawBM.rect.extent.x;
1632 	lcmdp->drawBM.rect.extent.y = cmd->drawBM.rect.extent.y;
1633 	lcmdp->drawBM.base = cmd->drawBM.base;
1634 	lcmdp->clip.origin.x = cmd->clip.origin.x;
1635 	lcmdp->clip.origin.y = cmd->clip.origin.y;
1636 	lcmdp->clip.extent.x = cmd->clip.extent.x;
1637 	lcmdp->clip.extent.y = cmd->clip.extent.y;
1638 	lcmdp->plist = pl;
1639 	sp = (sPoint *)cmd->plist;
1640 	while (cmd->np) {
1641 		lcmdp->np = np = min(cmd->np, 100);
1642 		cmd->np -= np;
1643 		while (np-- > 0) {
1644 			int error;
1645 			sPoint tmp;
1646 
1647 			if (error = copyin((caddr_t)sp, (caddr_t)&tmp, sizeof (tmp)))
1648 				return (error);
1649 			lp->x = tmp.x;
1650 			lp->y = tmp.y;
1651 			lp++;
1652 			sp++;
1653 		}
1654 		fbnpolydot(fbp, lcmdp, UIO_SYSSPACE);
1655 	}
1656 }
1657 
1658 fbntext(fbp, cmd)
1659 	register struct fbreg *fbp;
1660 	register lPrimText *cmd;
1661 {
1662 	register int error;
1663 
1664 #ifdef CPU_DOUBLE
1665 	int blttype = BLTTYPE(cmd->fontBM.type, cmd->drawBM.type);
1666 
1667 	if ((cmd->type == ASCII) &&
1668 	    ((blttype == BLTTYPE(BM_MEM, BM_MEM)) ||
1669 	     (blttype == BLTTYPE(BM_0, BM_MEM)) ||
1670 	     (blttype == BLTTYPE(BM_1, BM_MEM)))
1671 	) {
1672 		return(mfbntext(fbp, cmd));
1673 		/* NOTREACHED */
1674 	}
1675 #endif /* CPU_DOUBLE */
1676 
1677 	fbinitlock();
1678 	fbp->fb_command = FB_CTEXT;
1679 	fbp->fb_text = *cmd;
1680 
1681 
1682 	if (error = fblocksbitmap(&fbp->fb_text.drawBM, B_READ, fbmap))
1683 		return error;
1684 
1685 	if (cmd->type == ASCII) {
1686 		if (error = fblocksbitmap(&fbp->fb_text.fontBM,
1687 					  B_WRITE, fbmap + 1)) {
1688 			return error;
1689 		}
1690 	}
1691 
1692 #ifdef CPU_SINGLE
1693 	if (error = fblockmem(cmd->str, cmd->len, B_WRITE, fbmap + 2, UIO_USERSPACE))
1694 		return error;
1695 	fbp->fb_text.str = (unsigned char *)ipc_phys(fbmap + 2);
1696 
1697 	fbdolock();
1698 	fbstart(fbp, 1);
1699 	fbunlock();
1700 #else /* CPU_SINGLE */
1701 	fbp->fb_text.str = (unsigned char *)ipc_phys(srcdestlist);
1702 	if (error = COPYIN((caddr_t)cmd->str,
1703 			   (caddr_t)srcdestlist, cmd->len, UIO_USERSPACE)) {
1704 		return error;
1705 	}
1706 
1707 	if (fbp->fb_text.drawBM.type == BM_MEM ||
1708 	    (cmd->type == ASCII && fbp->fb_text.fontBM.type == BM_MEM)) {
1709 		fbdolock();
1710 		fbstart(fbp, 1);
1711 		fbunlock();
1712 	} else
1713 		fbstart(fbp, 0);
1714 #endif /* CPU_SINGLE */
1715 	return error;
1716 }
1717 
1718 fbtext(fbp, cmd)
1719 	struct fbreg *fbp;
1720 	register sPrimText *cmd;
1721 {
1722 	lPrimText lcmd;
1723 	register lPrimText *lcmdp;
1724 
1725 	lcmdp = &lcmd;
1726 
1727 	lcmdp->func = cmd->func;
1728 	lcmdp->transp = cmd->transp;
1729 	lcmdp->fore_color = cmd->fore_color;
1730 	lcmdp->aux_color = cmd->aux_color;
1731 	lcmdp->planemask = cmd->planemask;
1732 	lcmdp->type = cmd->type;
1733 	lcmdp->p.x = cmd->p.x;
1734 	lcmdp->p.y = cmd->p.y;
1735 	lcmdp->dx = cmd->dx;
1736 	lcmdp->dy = cmd->dy;
1737 	lcmdp->ex_factor = cmd->ex_factor;
1738 	lcmdp->fp.x = cmd->fp.x;
1739 	lcmdp->fp.y = cmd->fp.y;
1740 	lcmdp->width = cmd->width;
1741 	lcmdp->height = cmd->height;
1742 	lcmdp->column = cmd->column;
1743 	lcmdp->first_chr = cmd->first_chr;
1744 	lcmdp->last_chr = cmd->last_chr;
1745 	lcmdp->fontBM.type = cmd->fontBM.type;
1746 	lcmdp->fontBM.depth = cmd->fontBM.depth;
1747 	lcmdp->fontBM.width = cmd->fontBM.width;
1748 	lcmdp->fontBM.rect.origin.x = cmd->fontBM.rect.origin.x;
1749 	lcmdp->fontBM.rect.origin.y = cmd->fontBM.rect.origin.y;
1750 	lcmdp->fontBM.rect.extent.x = cmd->fontBM.rect.extent.x;
1751 	lcmdp->fontBM.rect.extent.y = cmd->fontBM.rect.extent.y;
1752 	lcmdp->fontBM.base = cmd->fontBM.base;
1753 	lcmdp->drawBM.type = cmd->drawBM.type;
1754 	lcmdp->drawBM.depth = cmd->drawBM.depth;
1755 	lcmdp->drawBM.width = cmd->drawBM.width;
1756 	lcmdp->drawBM.rect.origin.x = cmd->drawBM.rect.origin.x;
1757 	lcmdp->drawBM.rect.origin.y = cmd->drawBM.rect.origin.y;
1758 	lcmdp->drawBM.rect.extent.x = cmd->drawBM.rect.extent.x;
1759 	lcmdp->drawBM.rect.extent.y = cmd->drawBM.rect.extent.y;
1760 	lcmdp->drawBM.base = cmd->drawBM.base;
1761 	lcmdp->clip.origin.x = cmd->clip.origin.x;
1762 	lcmdp->clip.origin.y = cmd->clip.origin.y;
1763 	lcmdp->clip.extent.x = cmd->clip.extent.x;
1764 	lcmdp->clip.extent.y = cmd->clip.extent.y;
1765 	lcmdp->len = cmd->len;
1766 	lcmdp->str = cmd->str;
1767 	return (fbntext(fbp, lcmdp));
1768 }
1769 
1770 fbsetcursor(fbp, data)
1771 	struct fbreg *fbp;
1772 	sCursor	*data;
1773 {
1774 	register struct fbreg *fbregp;
1775 
1776 	fbregp = fbp;
1777 
1778 	fbregp->fb_command = FB_CSETCURSOR;
1779 	fbregp->fb_cursor.func = data->func;
1780 	fbregp->fb_cursor.cursor_color = data->cursor_color;
1781 	fbregp->fb_cursor.mask_color = data->mask_color;
1782 	fbregp->fb_cursor.hot.x = data->hot.x;
1783 	fbregp->fb_cursor.hot.y = data->hot.y;
1784 	fbregp->fb_cursor.size.x = data->size.x;
1785 	fbregp->fb_cursor.size.y = data->size.y;
1786 	fbregp->fb_cursor.cursorRect.origin.x = data->cursorRect.origin.x;
1787 	fbregp->fb_cursor.cursorRect.origin.y = data->cursorRect.origin.y;
1788 	fbregp->fb_cursor.cursorRect.extent.x = data->cursorRect.extent.x;
1789 	fbregp->fb_cursor.cursorRect.extent.y = data->cursorRect.extent.y;
1790 	fbregp->fb_cursor.maskRect.origin.x = data->maskRect.origin.x;
1791 	fbregp->fb_cursor.maskRect.origin.y = data->maskRect.origin.y;
1792 	fbregp->fb_cursor.maskRect.extent.x = data->maskRect.extent.x;
1793 	fbregp->fb_cursor.maskRect.extent.y = data->maskRect.extent.y;
1794 	fbregp->fb_cursor.saveRect.origin.x = data->saveRect.origin.x;
1795 	fbregp->fb_cursor.saveRect.origin.y = data->saveRect.origin.y;
1796 	fbregp->fb_cursor.saveRect.extent.x = data->saveRect.extent.x;
1797 	fbregp->fb_cursor.saveRect.extent.y = data->saveRect.extent.y;
1798 	fbregp->fb_cursor.moveArea.origin.x = data->moveArea.origin.x;
1799 	fbregp->fb_cursor.moveArea.origin.y = data->moveArea.origin.y;
1800 	fbregp->fb_cursor.moveArea.extent.x = data->moveArea.extent.x;
1801 	fbregp->fb_cursor.moveArea.extent.y = data->moveArea.extent.y;
1802 	fbstart(fbp, 0);
1803 	return 0;
1804 }
1805 
1806 fbnsetcursor(fbp, data)
1807 	struct fbreg *fbp;
1808 	lCursor	*data;
1809 {
1810 	register struct fbreg *fbregp;
1811 
1812 	fbregp = fbp;
1813 
1814 	fbregp->fb_command = FB_CSETCURSOR;
1815 	fbregp->fb_cursor.func = data->func;
1816 	fbregp->fb_cursor.cursor_color = data->cursor_color;
1817 	fbregp->fb_cursor.mask_color = data->mask_color;
1818 	fbregp->fb_cursor.hot.x = data->hot.x;
1819 	fbregp->fb_cursor.hot.y = data->hot.y;
1820 	fbregp->fb_cursor.size.x = data->size.x;
1821 	fbregp->fb_cursor.size.y = data->size.y;
1822 	fbregp->fb_cursor.cursorRect.origin.x = data->cursorRect.origin.x;
1823 	fbregp->fb_cursor.cursorRect.origin.y = data->cursorRect.origin.y;
1824 	fbregp->fb_cursor.cursorRect.extent.x = data->cursorRect.extent.x;
1825 	fbregp->fb_cursor.cursorRect.extent.y = data->cursorRect.extent.y;
1826 	fbregp->fb_cursor.maskRect.origin.x = data->maskRect.origin.x;
1827 	fbregp->fb_cursor.maskRect.origin.y = data->maskRect.origin.y;
1828 	fbregp->fb_cursor.maskRect.extent.x = data->maskRect.extent.x;
1829 	fbregp->fb_cursor.maskRect.extent.y = data->maskRect.extent.y;
1830 	fbregp->fb_cursor.saveRect.origin.x = data->saveRect.origin.x;
1831 	fbregp->fb_cursor.saveRect.origin.y = data->saveRect.origin.y;
1832 	fbregp->fb_cursor.saveRect.extent.x = data->saveRect.extent.x;
1833 	fbregp->fb_cursor.saveRect.extent.y = data->saveRect.extent.y;
1834 	fbregp->fb_cursor.moveArea.origin.x = data->moveArea.origin.x;
1835 	fbregp->fb_cursor.moveArea.origin.y = data->moveArea.origin.y;
1836 	fbregp->fb_cursor.moveArea.extent.x = data->moveArea.extent.x;
1837 	fbregp->fb_cursor.moveArea.extent.y = data->moveArea.extent.y;
1838 	fbstart(fbp, 0);
1839 	return 0;
1840 }
1841 
1842 fbgetscrtype(fbp, data)
1843 	struct fbreg *fbp;
1844 	sScrType *data;
1845 {
1846 	fbp->fb_command = FB_CGETSCRTYPE;
1847 	fbstart(fbp, 1);
1848 	data->colorwidth = fbp->fb_scrtype.colorwidth;
1849 	data->plane = fbp->fb_scrtype.plane;
1850 	data->bufferrect.origin.x = fbp->fb_scrtype.bufferrect.origin.x;
1851 	data->bufferrect.origin.y = fbp->fb_scrtype.bufferrect.origin.y;
1852 	data->bufferrect.extent.x = fbp->fb_scrtype.bufferrect.extent.x;
1853 	data->bufferrect.extent.y = fbp->fb_scrtype.bufferrect.extent.y;
1854 	data->visiblerect.origin.x = fbp->fb_scrtype.visiblerect.origin.x;
1855 	data->visiblerect.origin.y = fbp->fb_scrtype.visiblerect.origin.y;
1856 	data->visiblerect.extent.x = fbp->fb_scrtype.visiblerect.extent.x;
1857 	data->visiblerect.extent.y = fbp->fb_scrtype.visiblerect.extent.y;
1858 	return 0;
1859 }
1860 
1861 fbsetxy(fbp, data)
1862 	struct fbreg *fbp;
1863 	sPoint *data;
1864 {
1865 	fbp->fb_command = FB_CSETXY;
1866 	fbp->fb_point.x = data->x;
1867 	fbp->fb_point.y = data->y;
1868 	fbstart(fbp, 0);
1869 	return 0;
1870 }
1871 
1872 fbsetpalette(fbp, data)
1873 	struct fbreg *fbp;
1874 	sPalette *data;
1875 {
1876 	lPalette	pal;
1877 
1878 	fbp->fb_command = FB_CSETPALETTE;
1879 	fbp->fb_palette.count = 1;
1880 	*(sPalette *)srcdestlist = *data;
1881 #ifdef CPU_SINGLE
1882 	fbmap[0].fm_vaddr = (caddr_t)srcdestlist;
1883 	fbmap[0].fm_offset = 0;
1884 	fbp->fb_palette.palette = (sPalette *)ipc_phys(fbmap);
1885 #else
1886 	fbp->fb_palette.palette = (sPalette *)ipc_phys(srcdestlist);
1887 #endif
1888 	fbstart(fbp, 0);
1889 	return 0;
1890 }
1891 
1892 fbnsetpalette(fbp, cmd)
1893 	struct fbreg *fbp;
1894 	lPalette *cmd;
1895 {
1896 	register int error;
1897 	register int count;
1898 #ifdef CPU_SINGLE
1899 	register int len;
1900 #endif
1901 
1902 	fbinitlock();
1903 	fbp->fb_command = FB_CSETPALETTE;
1904 #ifdef CPU_SINGLE
1905 	fbp->fb_palette.count = cmd->count;
1906 	if ((len = cmd->count * sizeof(sPalette)) <= 0)
1907 		return EINVAL;
1908 	if (error = fblockmem(cmd->palette, len, B_WRITE, fbmap, UIO_USERSPACE))
1909 		return error;
1910 	fbp->fb_palette.palette = (sPalette *)ipc_phys(fbmap);
1911 
1912 	fbdolock();
1913 	fbstart(fbp, 1);
1914 	fbunlock();
1915 #else /* CPU_SINGLE */
1916 	fbp->fb_palette.palette = (sPalette *)ipc_phys(srcdestlist);
1917 	while (cmd->count > 0) {
1918 		count = min(cmd->count, (MAX_SIZE / sizeof(sPalette)));
1919 		fbp->fb_palette.count = count;
1920 		if (error = COPYIN((caddr_t)cmd->palette, (caddr_t)srcdestlist,
1921 				   count * sizeof(sPalette), UIO_USERSPACE)) {
1922 			break;
1923 		}
1924 		cmd->count -= count;
1925 		cmd->palette += count;
1926 
1927 		fbstart(fbp, 0);
1928 	}
1929 #endif /* CPU_SINGLE */
1930 	return error;
1931 }
1932 
1933 fbgetpalette(fbp, data)
1934 	struct fbreg *fbp;
1935 	sPalette *data;
1936 {
1937 	lPalette pal;
1938 
1939 	fbp->fb_command = FB_CGETPALETTE;
1940 	fbp->fb_palette.count = 1;
1941 	*(sPalette *)srcdestlist = *data;
1942 #ifdef CPU_SINGLE
1943 	fbmap[0].fm_vaddr = (caddr_t)srcdestlist;
1944 	fbmap[0].fm_offset = 0;
1945 	fbp->fb_palette.palette = (sPalette *)ipc_phys(fbmap);
1946 #else
1947 	fbp->fb_palette.palette = (sPalette *)ipc_phys(srcdestlist);
1948 #endif
1949 	fbstart(fbp, 1);
1950 #ifdef mips
1951 	MachFlushDCache((caddr_t)srcdestlist, sizeof (sPalette));
1952 	*data = *(sPalette *)MACH_CACHED_TO_UNCACHED(srcdestlist);
1953 #else
1954 	*data = *(sPalette *)srcdestlist;
1955 #endif
1956 	return fbp->fb_result;
1957 }
1958 
1959 fbngetpalette(fbp, cmd)
1960 	struct fbreg *fbp;
1961 	lPalette *cmd;
1962 {
1963 	register int error;
1964 	register int count;
1965 #ifdef CPU_SINGLE
1966 	register int len;
1967 #else
1968 	register int savecount;
1969 	register sPalette *savep;
1970 #endif
1971 
1972 	fbinitlock();
1973 	fbp->fb_command = FB_CGETPALETTE;
1974 #ifdef CPU_SINGLE
1975 	fbp->fb_palette.count = cmd->count;
1976 	if ((len = cmd->count * sizeof(sPalette)) <= 0)
1977 		return EINVAL;
1978 	if (error = fblockmem(cmd->palette, len, B_WRITE, fbmap, UIO_USERSPACE))
1979 		return error;
1980 	fbp->fb_palette.palette = (sPalette *)ipc_phys(fbmap);
1981 
1982 	fbdolock();
1983 	fbstart(fbp, 1);
1984 	fbunlock();
1985 #else /* CPU_SINGLE */
1986 	savecount = cmd->count;
1987 	savep = cmd->palette;
1988 	fbp->fb_palette.palette = (sPalette *)ipc_phys(srcdestlist);
1989 	while (cmd->count > 0) {
1990 		count = min(cmd->count, (MAX_SIZE / sizeof(sPalette)));
1991 		fbp->fb_palette.count = count;
1992 		if (error = COPYIN((caddr_t)cmd->palette, (caddr_t)srcdestlist,
1993 				   count * sizeof(sPalette), UIO_USERSPACE)) {
1994 			break;
1995 		}
1996 		fbstart(fbp, 1);
1997 #ifdef mips
1998 		MachFlushDCache((caddr_t)srcdestlist, sizeof (sPalette));
1999 		error = copyout((caddr_t)MACH_CACHED_TO_UNCACHED(srcdestlist),
2000 				(caddr_t)cmd->palette,
2001 				count * sizeof(sPalette));
2002 #else
2003 		error = copyout((caddr_t)srcdestlist,
2004 				(caddr_t)cmd->palette,
2005 				count * sizeof(sPalette));
2006 #endif
2007 		if (error)
2008 			break;
2009 		cmd->count -= count;
2010 		cmd->palette += count;
2011 	}
2012 	cmd->count = savecount;
2013 	cmd->palette = savep;
2014 #endif /* CPU_SINGLE */
2015 	return fbp->fb_result;
2016 }
2017 #endif /* NFB > 0 */
2018