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