📄 fb_sub.c
字号:
/* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * * This code is derived from software contributed to Berkeley by * Sony Corp. and Kazumasa Utashiro of Software Research Associates, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by the University of * California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * from: $Hdr: fb_sub.c,v 4.300 91/06/27 20:43:09 root Rel41 $ SONY * * @(#)fb_sub.c 8.2 (Berkeley) 9/23/93 */#include "fb.h"#if NFB > 0/* * Frame buffer driver */#include <sys/types.h>#include <machine/pte.h>#include <machine/cpu.h>#include <machine/param.h>#include <sys/param.h>#include <sys/proc.h>#include <sys/user.h>#include <sys/buf.h>#include <vm/vm.h>#include <sys/systm.h>#include <sys/map.h>#include <sys/uio.h>#include <sys/kernel.h>#include <news3400/iop/framebuf.h>#include <news3400/iop/fbreg.h>#ifdef CPU_DOUBLE#ifdef IPC_MRX#include "../ipc/newsipc.h"#ifdef mips#define ipc_phys(x) K0_TT0(x)#define ipc_log(x) TT0_K0(x)#else /* mips */#define ipc_phys(x) (caddr_t)((int)(x) & ~0x80000000)#define ipc_log(x) (caddr_t)((int)(x) | 0x80000000)#endif /* mips */#endif /* IPC_MRX */#else /* CPU_DOUBLE */#define ipc_phys(x) (caddr_t)((int)(x))#define ipc_log(x) (caddr_t)((int)(x) | 0x80000000)#endif /* CPU_DOUBLE */#define MAX_FBMAP 3static struct fb_map fbmap[MAX_FBMAP];/* bitblt type */#define BLTTYPE(ts, td) ((ts) << 2 | (td))static lSrcDest srcdestlist[MAX_BATCHBITBLT];#define MAX_SIZE (MAX_BATCHBITBLT * sizeof(lSrcDest))#define ODD_ADDR(x) (((unsigned)(x))&1)#define MAXMSEG 4static int segind;static struct memseg { caddr_t adrs; int len; int rw; caddr_t oadrs; int olen; struct fb_map *map;} mseg[MAXMSEG];#define BASE(a) ((int)(a) & ~(NBPG - 1))#ifdef CPU_DOUBLECOPYIN(src, dst, len, seg) caddr_t src; caddr_t dst; int len; int seg;{ switch (seg) { case UIO_SYSSPACE: bcopy(src, dst, len); return (0); case UIO_USERSPACE: return (copyin(src, dst, len)); default: panic("COPYIN: seg"); /* NOTREACHED */ }}#endif /* CPU_DOUBLE */fbgetmap(addr, len, map) caddr_t addr; int len; struct fb_map *map;{ register struct pte *pte; register caddr_t *p; unsigned v; register int npf; int o; v = pmax_btop(addr); o = (int)addr & PGOFSET; npf = btoc(len + o); if (npf > NFBMAP) return (EINVAL); map->fm_vaddr = addr; map->fm_offset = o; map->fm_count = len;#ifdef CPU_DOUBLE if (addr >= (caddr_t)KERNBASE) {#ifdef mips p = map->fm_addr; if (MACH_IS_CACHED(addr)) { addr = ptob(v); while (--npf >= 0) { *p++ = (caddr_t)K0_TT0(addr); addr += NBPG; } return (0); } if (MACH_IS_MAPPED(addr)) pte = kvtopte(addr); else if (addr >= (caddr_t)&u) pte = curproc->p_addr + btop(addr - (caddr_t)&u); else panic("fbgetmap: bad kernel addr"); while (--npf >= 0) *p++ = (caddr_t)PHYS_TT0(ptob(pte++->pg_pfnum));#else /* mips */ pte = kvtopte(addr); p = map->fm_addr; while (--npf >= 0) *p++ = (caddr_t)ptob(pte++->pg_pfnum);#endif /* mips */ return (0); } pte = vtopte(curproc, v); /*KU:XXXXXXXXXXXXXXXXXX*/ p = map->fm_addr; while (--npf >= 0) { if (pte->pg_pfnum == 0) panic("iop zero uentry");#ifdef mips *p++ = (caddr_t)PHYS_TT0(ptob(pte++->pg_pfnum));#else *p++ = (caddr_t)ptob(pte++->pg_pfnum);#endif }#endif /* CPU_DOUBLE */ return (0);}fblockmem(ad, len, rw, map, seg) register caddr_t ad; register int len; int rw; struct fb_map *map; int seg;{ register struct memseg *msp; /* validity check */ if (len < 0) return EFAULT; else if (len == 0) return 0; else if (ad == 0) return EFAULT; else if (seg == UIO_USERSPACE && !useracc(ad, len, rw == B_READ ? B_WRITE : B_READ)) return EFAULT; else if (segind >= MAXMSEG) return EFAULT; /* insertion sort */ for (msp = mseg + segind - 1; msp >= mseg; msp--) { if (msp->adrs > ad) *(msp + 1) = *msp; else break; } msp++;#ifdef CPU_SINGLE switch (seg) { case UIO_SYSSPACE: map->fm_vaddr = ad; map->fm_offset = 0; break; case UIO_USERSPACE: msp->adrs = (caddr_t)BASE(ad); msp->len = (caddr_t)BASE(ad + len + NBPG - 1) - msp->adrs; break; default: panic("fblockmem: seg"); /* NOTREACHED */ }#else /* CPU_SINGLE */ msp->adrs = (caddr_t)BASE(ad); msp->len = (caddr_t)BASE(ad + len + NBPG - 1) - msp->adrs;#endif /* CPU_SINGLE */ msp->rw = rw; msp->oadrs = ad; msp->olen = len; msp->map = map; segind++; return (0);}fblocksbitmap(bm, rw, map) register lBitmap *bm; int rw; struct fb_map *map;{ register int len; register int error = 0; if (bm->depth > 32) return EINVAL; if (bm->type == BM_FB || bm->type == BM_0 || bm->type == BM_1) return 0; if (bm->type == BM_MEM) len = bm->width * bm->rect.extent.y * bm->depth * sizeof(Word); if (len < 0 || len > FB_MAX_IO) return(EINVAL); error = fblockmem((caddr_t)(bm->base), len, rw, map, UIO_USERSPACE); if (error) return error; bm->base = (Word *)ipc_phys(map); return 0;}voidfbinitlock(){ segind = 0;}voidfbdolock(){ register struct memseg *msp0, *msp1, *mspl; register int i, tlen; mspl = mseg + segind; for (msp0 = mseg, msp1 = mseg + 1; msp1 < mspl; msp0++, msp1++) { if (msp0->adrs + msp0->len > msp1->adrs) { tlen = msp1->adrs - msp0->adrs + msp1->len; msp1->adrs = msp0->adrs; msp1->len = msp0->len > tlen ? msp0->len : tlen; msp0->len = 0; msp1->rw = (msp0->rw == B_READ || msp1->rw == B_READ) ? B_READ : B_WRITE; } } /* lock */ curproc->p_flag |= P_PHYSIO; for (i = 0; i < segind; i++) if (mseg[i].len && mseg[i].adrs && mseg[i].adrs < (caddr_t)KERNBASE) vslock(mseg[i].adrs, mseg[i].len); /* make map */ for (i = 0; i < segind; i++) fbgetmap(mseg[i].oadrs, mseg[i].olen, mseg[i].map);}voidfbunlock(){ register int i; int s = splfb(); for (i = 0; i < segind; i++) { if (mseg[i].len && mseg[i].adrs && mseg[i].adrs < (caddr_t)KERNBASE) { vsunlock(mseg[i].adrs, mseg[i].len, mseg[i].rw);#if defined(mips) && defined(CPU_DOUBLE) if (mseg[i].rw == B_READ) clean_kudcache(curproc, mseg[i].adrs, mseg[i].len);#endif } } curproc->p_flag &= ~P_PHYSIO; splx(s); /* for 'fbinitlock() o wasureru ukkariyasan'... */ segind = 0;}checkbitmap(bm) register lBitmap *bm;{ if (bm->depth > 32) return EINVAL; switch(bm->type) { case BM_FB: case BM_0: case BM_1: break; case BM_MEM: if (ODD_ADDR(bm->base)) return EINVAL; if (bm->width == 0) return EINVAL; if ((bm->width * bm->rect.extent.y) << 1 > FB_MAX_IO) return EINVAL; break; default: return EINVAL; } if (bm->rect.extent.x < 0 || bm->rect.extent.y < 0) return EINVAL; else return 0;}checkdepth(sbm, dbm) lBitmap *sbm, *dbm;{ register int ds = sbm->depth; register int dd = dbm->depth; if (ds > 1 && dd > 1 && ds != dd) return -1; else return((ds > 1) << 1 | (dd > 1));}dobitblt(fbp, sbm, dbm) struct fbreg *fbp; lBitmap *sbm, *dbm;{ register int error; if (error = fblocksbitmap(sbm, B_WRITE, fbmap)) return error; if (error = fblocksbitmap(dbm, B_READ, fbmap + 1)) return error; fbdolock(); fbstart(fbp, 1); fbunlock(); /* reset address */ if (sbm->type == BM_MEM) sbm->base = (Word *)((struct fb_map *)ipc_log(sbm->base))->fm_vaddr; if (dbm->type == BM_MEM) dbm->base = (Word *)((struct fb_map *)ipc_log(dbm->base))->fm_vaddr; return 0;}fbnbitblt(fbp, cmd) register struct fbreg *fbp; register lBitblt *cmd;{ register lBitblt *regcmd; register int len, lens, lend; register int i; int pmask, mode; int error = 0; int blttype = BLTTYPE(cmd->srcBitmap.type, cmd->destBitmap.type);#ifdef CPU_DOUBLE if ((blttype == BLTTYPE(BM_MEM, BM_MEM)) || (blttype == BLTTYPE(BM_0, BM_MEM)) || (blttype == BLTTYPE(BM_1, BM_MEM))) { return(mfbnbitblt(fbp, cmd)); /* NOTREACHED */ }#endif fbinitlock(); if (error = checkbitmap(&cmd->srcBitmap)) return error; if (error = checkbitmap(&cmd->destBitmap)) return error; if ((mode = checkdepth(&cmd->srcBitmap, &cmd->destBitmap)) < 0) return EINVAL; fbp->fb_command = FB_CBITBLT; fbp->fb_bitblt = *cmd; regcmd = &fbp->fb_bitblt; /* process bitblt command */ switch (blttype) { case BLTTYPE(BM_FB, BM_FB): case BLTTYPE(BM_0, BM_FB): case BLTTYPE(BM_1, BM_FB): fbstart(fbp, 0); break; case BLTTYPE(BM_FB, BM_MEM): case BLTTYPE(BM_0, BM_MEM): case BLTTYPE(BM_1, BM_MEM): len = cmd->destBitmap.width * cmd->destBitmap.rect.extent.y << 1; if (len * cmd->destBitmap.depth <= FB_MAX_IO) { error = dobitblt(fbp, ®cmd->srcBitmap, ®cmd->destBitmap); return error; } /* bitblt each plane */ regcmd->destBitmap.depth = 1; pmask = regcmd->planemask; for (i = 0; i < cmd->destBitmap.depth; i++) { if (mode == 3) /* N to N */ regcmd->planemask = pmask & (1 << i); if (error = dobitblt(fbp, ®cmd->srcBitmap, ®cmd->destBitmap)) return error; regcmd->destBitmap.base += len >> 1; if (mode == 1) { /* N to N */ regcmd->planemask >>= 1; regcmd->fore_color >>= 1; regcmd->aux_color >>= 1; } } break; case BLTTYPE(BM_MEM, BM_FB): len = cmd->srcBitmap.width * cmd->srcBitmap.rect.extent.y << 1; if (len * cmd->srcBitmap.depth <= FB_MAX_IO) { error = dobitblt(fbp, ®cmd->srcBitmap, ®cmd->destBitmap); return error; } /* bitblt each plane */ regcmd->srcBitmap.depth = 1; pmask = regcmd->planemask; regcmd->fore_color = 0xff; regcmd->aux_color = 0; if (mode == 2) { /* N to 1 */ for (i = 0; i < cmd->srcBitmap.depth; i++) if (pmask & (1 << i)) break; if (i >= cmd->srcBitmap.depth) return 0; regcmd->srcBitmap.base += (len >> 1) * i; error = dobitblt(fbp, ®cmd->srcBitmap, ®cmd->destBitmap); return error; } /* else (N to N) */ for (i = 0; i < cmd->srcBitmap.depth; i++) { regcmd->planemask = pmask & (1 << i); if (error = dobitblt(fbp, ®cmd->srcBitmap, ®cmd->destBitmap)) return error; regcmd->srcBitmap.base += len >> 1; regcmd->planemask >>= 1; } return 0; case BLTTYPE(BM_MEM, BM_MEM): lens = cmd->srcBitmap.width * cmd->srcBitmap.rect.extent.y << 1; lend = cmd->destBitmap.width * cmd->destBitmap.rect.extent.y << 1; if (lens * cmd->srcBitmap.depth <= FB_MAX_IO && lend * cmd->destBitmap.depth <= FB_MAX_IO) { error = dobitblt(fbp, ®cmd->srcBitmap, ®cmd->destBitmap); return error; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -