📄 creatorfb.c
字号:
} } spin_unlock_irqrestore(&fb->lock, flags);}static void ffb_putcs(struct vc_data *conp, struct display *p, const unsigned short *s, int count, int yy, int xx){ struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct ffb_fbc *fbc = fb->s.ffb.fbc; unsigned long flags; int i, xy; u8 *fd1, *fd2, *fd3, *fd4; u16 c; u64 fgbg; spin_lock_irqsave(&fb->lock, flags); c = scr_readw(s); fgbg = (((u64)(((u32 *)p->dispsw_data)[attr_fgcol(p, c)])) << 32) | ((u32 *)p->dispsw_data)[attr_bgcol(p, c)]; if (fgbg != *(u64 *)&fb->s.ffb.fg_cache) { FFBFifo(fb, 2); upa_writeq(fgbg, &fbc->fg); *(u64 *)&fb->s.ffb.fg_cache = fgbg; } xy = fb->s.ffb.xy_margin; if (fontwidthlog(p)) xy += (xx << fontwidthlog(p)); else xy += xx * fontwidth(p); if (fontheightlog(p)) xy += (yy << (16 + fontheightlog(p))); else xy += ((yy * fontheight(p)) << 16); if (fontwidth(p) <= 8) { while (count >= 4) { count -= 4; FFBFifo(fb, 2 + fontheight(p)); upa_writel(4 * fontwidth(p), &fbc->fontw); upa_writel(xy, &fbc->fontxy); if (fontheightlog(p)) { fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) << fontheightlog(p)); } else { fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); fd3 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); fd4 = p->fontdata + ((scr_readw(s++) & p->charmask) * fontheight(p)); } if (fontwidth(p) == 8) { for (i = 0; i < fontheight(p); i++) { u32 val; val = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) << 8)) << 8)) << 8); upa_writel(val, &fbc->font); } xy += 32; } else { for (i = 0; i < fontheight(p); i++) { u32 val = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) << fontwidth(p))) << fontwidth(p))) << fontwidth(p))) << (24 - 3 * fontwidth(p)); upa_writel(val, &fbc->font); } xy += 4 * fontwidth(p); } } } else { while (count >= 2) { count -= 2; FFBFifo(fb, 2 + fontheight(p)); upa_writel(2 * fontwidth(p), &fbc->fontw); upa_writel(xy, &fbc->fontxy); if (fontheightlog(p)) { fd1 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); fd2 = p->fontdata + ((scr_readw(s++) & p->charmask) << (fontheightlog(p) + 1)); } else { fd1 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1); fd2 = p->fontdata + (((scr_readw(s++) & p->charmask) * fontheight(p)) << 1); } for (i = 0; i < fontheight(p); i++) { u32 val = ((((u32)*(u16 *)fd1) << fontwidth(p)) | ((u32)*(u16 *)fd2)) << (16 - fontwidth(p)); upa_writel(val, &fbc->font); fd1 += 2; fd2 += 2; } xy += 2 * fontwidth(p); } } while (count) { count--; FFBFifo(fb, 2 + fontheight(p)); upa_writel(fontwidth(p), &fbc->fontw); upa_writel(xy, &fbc->fontxy); if (fontheightlog(p)) i = ((scr_readw(s++) & p->charmask) << fontheightlog(p)); else i = ((scr_readw(s++) & p->charmask) * fontheight(p)); if (fontwidth(p) <= 8) { fd1 = p->fontdata + i; for (i = 0; i < fontheight(p); i++) { u32 val = *fd1++ << 24; upa_writel(val, &fbc->font); } } else { fd1 = p->fontdata + (i << 1); for (i = 0; i < fontheight(p); i++) { u32 val = *(u16 *)fd1 << 16; upa_writel(val, &fbc->font); fd1 += 2; } } xy += fontwidth(p); } spin_unlock_irqrestore(&fb->lock, flags);}static void ffb_revc(struct display *p, int xx, int yy){ /* Not used if hw cursor */}#if 0static void ffb_blank(struct fb_info_sbusfb *fb){ struct ffb_dac *dac = fb->s.ffb.dac; unsigned long flags; u32 tmp; spin_lock_irqsave(&fb->lock, flags); upa_writel(0x6000, &dac->type); tmp = (upa_readl(&dac->value) & ~0x1); upa_writel(0x6000, &dac->type); upa_writel(tmp, &dac->value); spin_unlock_irqrestore(&fb->lock, flags);}#endifstatic void ffb_unblank(struct fb_info_sbusfb *fb){ struct ffb_dac *dac = fb->s.ffb.dac; unsigned long flags; u32 tmp; spin_lock_irqsave(&fb->lock, flags); upa_writel(0x6000, &dac->type); tmp = (upa_readl(&dac->value) | 0x1); upa_writel(0x6000, &dac->type); upa_writel(tmp, &dac->value); spin_unlock_irqrestore(&fb->lock, flags);}static void ffb_loadcmap (struct fb_info_sbusfb *fb, struct display *p, int index, int count){ struct ffb_dac *dac = fb->s.ffb.dac; unsigned long flags; int i, j = count; spin_lock_irqsave(&fb->lock, flags); upa_writel(0x2000 | index, &dac->type); for (i = index; j--; i++) { u32 val; /* Feed the colors in :)) */ val = ((fb->color_map CM(i,0))) | ((fb->color_map CM(i,1)) << 8) | ((fb->color_map CM(i,2)) << 16); upa_writel(val, &dac->value); } if (!p) goto out; for (i = index, j = count; i < 16 && j--; i++) ((u32 *)p->dispsw_data)[i] = ((fb->color_map CM(i,0))) | ((fb->color_map CM(i,1)) << 8) | ((fb->color_map CM(i,2)) << 16);out: spin_unlock_irqrestore(&fb->lock, flags);}static struct display_switch ffb_dispsw __initdata = { setup: ffb_setup, bmove: fbcon_redraw_bmove, clear: ffb_clear, putc: ffb_putc, putcs: ffb_putcs, revc: ffb_revc, fontwidthmask: FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */};static void ffb_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin){ register struct ffb_fbc *fbc = fb->s.ffb.fbc; unsigned long flags; spin_lock_irqsave(&fb->lock, flags); fb->s.ffb.xy_margin = (y_margin << 16) + x_margin; fb->s.ffb.yx_margin = (((u64)y_margin) << 32) + x_margin; p->screen_base += 8192 * (y_margin - fb->y_margin) + 4 * (x_margin - fb->x_margin); FFBWait(fbc); spin_unlock_irqrestore(&fb->lock, flags);}static __inline__ void __ffb_curs_enable (struct fb_info_sbusfb *fb, int enable){ struct ffb_dac *dac = fb->s.ffb.dac; u32 val; upa_writel(0x100, &dac->type2); if (fb->s.ffb.dac_rev <= 2) { val = enable ? 3 : 0; } else { val = enable ? 0 : 3; } upa_writel(val, &dac->value2);}static void ffb_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue){ struct ffb_dac *dac = fb->s.ffb.dac; unsigned long flags; spin_lock_irqsave(&fb->lock, flags); __ffb_curs_enable (fb, 0); upa_writel(0x102, &dac->type2); upa_writel((red[0] | (green[0]<<8) | (blue[0]<<16)), &dac->value2); upa_writel((red[1] | (green[1]<<8) | (blue[1]<<16)), &dac->value2); spin_unlock_irqrestore(&fb->lock, flags);}/* Set cursor shape */static void ffb_setcurshape (struct fb_info_sbusfb *fb){ struct ffb_dac *dac = fb->s.ffb.dac; unsigned long flags; int i, j; spin_lock_irqsave(&fb->lock, flags); __ffb_curs_enable (fb, 0); for (j = 0; j < 2; j++) { u32 val = j ? 0 : 0x80; upa_writel(val, &dac->type2); for (i = 0; i < 0x40; i++) { if (fb->cursor.size.fbx <= 32) { upa_writel(fb->cursor.bits [j][i], &dac->value2); upa_writel(0, &dac->value2); } else { upa_writel(fb->cursor.bits [j][2*i], &dac->value2); upa_writel(fb->cursor.bits [j][2*i+1], &dac->value2); } } } spin_unlock_irqrestore(&fb->lock, flags);}/* Load cursor information */static void ffb_setcursor (struct fb_info_sbusfb *fb){ struct ffb_dac *dac = fb->s.ffb.dac; struct cg_cursor *c = &fb->cursor; unsigned long flags; u32 val; spin_lock_irqsave(&fb->lock, flags); upa_writel(0x104, &dac->type2); /* Should this be just 0x7ff?? Should I do some margin handling and setcurshape in that case? */ val = (((c->cpos.fby - c->chot.fby) & 0xffff) << 16) |((c->cpos.fbx - c->chot.fbx) & 0xffff); upa_writel(val, &dac->value2); __ffb_curs_enable (fb, fb->cursor.enable); spin_unlock_irqrestore(&fb->lock, flags);}static void ffb_switch_from_graph (struct fb_info_sbusfb *fb){ register struct ffb_fbc *fbc = fb->s.ffb.fbc; unsigned long flags; spin_lock_irqsave(&fb->lock, flags); FFBWait(fbc); fb->s.ffb.fifo_cache = 0; FFBFifo(fb, 8); upa_writel(FFB_PPC_VCE_DISABLE|FFB_PPC_TBE_OPAQUE| FFB_PPC_APE_DISABLE|FFB_PPC_CS_CONST, &fbc->ppc); upa_writel(0x2000707f, &fbc->fbc); upa_writel(FFB_ROP_NEW, &fbc->rop); upa_writel(FFB_DRAWOP_RECTANGLE, &fbc->drawop); upa_writel(0xffffffff, &fbc->pmask); upa_writel(0x10000, &fbc->fontinc); upa_writel(fb->s.ffb.fg_cache, &fbc->fg); upa_writel(fb->s.ffb.bg_cache, &fbc->bg); FFBWait(fbc); spin_unlock_irqrestore(&fb->lock, flags);}static int __init ffb_rasterimg (struct fb_info *info, int start){ ffb_switch_from_graph (sbusfbinfo(info)); return 0;}static char idstring[60] __initdata = { 0 };static int __init creator_apply_upa_parent_ranges(int parent, struct linux_prom64_registers *regs){ struct linux_prom64_ranges ranges[PROMREG_MAX]; char name[128]; int len, i; prom_getproperty(parent, "name", name, sizeof(name)); if (strcmp(name, "upa") != 0) return 0; len = prom_getproperty(parent, "ranges", (void *) ranges, sizeof(ranges)); if (len <= 0) return 1; len /= sizeof(struct linux_prom64_ranges); for (i = 0; i < len; i++) { struct linux_prom64_ranges *rng = &ranges[i]; u64 phys_addr = regs->phys_addr; if (phys_addr >= rng->ot_child_base && phys_addr < (rng->ot_child_base + rng->or_size)) { regs->phys_addr -= rng->ot_child_base; regs->phys_addr += rng->ot_parent_base; return 0; } } return 1;}char __init *creatorfb_init(struct fb_info_sbusfb *fb){ struct fb_fix_screeninfo *fix = &fb->fix; struct fb_var_screeninfo *var = &fb->var; struct display *disp = &fb->disp; struct fbtype *type = &fb->type; struct linux_prom64_registers regs[2*PROMREG_MAX]; int i, afb = 0; unsigned int btype; char name[64]; struct fb_ops *fbops; if (prom_getproperty(fb->prom_node, "reg", (void *) regs, sizeof(regs)) <= 0) return NULL; if (creator_apply_upa_parent_ranges(fb->prom_parent, ®s[0])) return NULL; disp->dispsw_data = (void *)kmalloc(16 * sizeof(u32), GFP_KERNEL); if (disp->dispsw_data == NULL) return NULL; memset(disp->dispsw_data, 0, 16 * sizeof(u32)); fbops = kmalloc(sizeof(*fbops), GFP_KERNEL); if (fbops == NULL) { kfree(disp->dispsw_data); return NULL; } *fbops = *fb->info.fbops; fbops->fb_rasterimg = ffb_rasterimg; fb->info.fbops = fbops; prom_getstring(fb->prom_node, "name", name, sizeof(name)); if (!strcmp(name, "SUNW,afb")) afb = 1; btype = prom_getintdefault(fb->prom_node, "board_type", 0); strcpy(fb->info.modename, "Creator"); if (!afb) { if ((btype & 7) == 3) strcpy(fix->id, "Creator 3D"); else strcpy(fix->id, "Creator"); } else strcpy(fix->id, "Elite 3D"); fix->visual = FB_VISUAL_TRUECOLOR; fix->line_length = 8192; fix->accel = FB_ACCEL_SUN_CREATOR; var->bits_per_pixel = 32; var->green.offset = 8; var->blue.offset = 16; var->accel_flags = FB_ACCELF_TEXT; disp->scrollmode = SCROLL_YREDRAW; disp->screen_base = (char *)__va(regs[0].phys_addr) + FFB_DFB24_POFF + 8192 * fb->y_margin + 4 * fb->x_margin; fb->s.ffb.xy_margin = (fb->y_margin << 16) + fb->x_margin; fb->s.ffb.yx_margin = (((u64)fb->y_margin) << 32) + fb->x_margin; fb->s.ffb.fbc = (struct ffb_fbc *)(regs[0].phys_addr + FFB_FBC_REGS_POFF); fb->s.ffb.dac = (struct ffb_dac *)(regs[0].phys_addr + FFB_DAC_POFF); fb->dispsw = ffb_dispsw; fb->margins = ffb_margins; fb->loadcmap = ffb_loadcmap; fb->setcursor = ffb_setcursor; fb->setcursormap = ffb_setcursormap; fb->setcurshape = ffb_setcurshape; fb->switch_from_graph = ffb_switch_from_graph; fb->fill = ffb_fill;#if 0 /* XXX Can't enable this for now, I've seen cases * XXX where the VC was blanked, and Xsun24 was started * XXX via a remote login, the sunfb code did not * XXX unblank creator when it was mmap'd for some * XXX reason, investigate later... -DaveM */ fb->blank = ffb_blank; fb->unblank = ffb_unblank;#endif /* If there are any read errors or fifo overflow conditions, * clear them now. */ if((upa_readl(&fb->s.ffb.fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) upa_writel(FFB_UCSR_ALL_ERRORS, &fb->s.ffb.fbc->ucsr); ffb_switch_from_graph(fb); fb->physbase = regs[0].phys_addr; fb->mmap_map = ffb_mmap_map; fb->cursor.hwsize.fbx = 64; fb->cursor.hwsize.fby = 64; type->fb_depth = 24; upa_writel(0x8000, &fb->s.ffb.dac->type); fb->s.ffb.dac_rev = (upa_readl(&fb->s.ffb.dac->value) >> 0x1c); i = prom_getintdefault (fb->prom_node, "board_type", 8); sprintf(idstring, "%s at %016lx type %d DAC %d", fix->id, regs[0].phys_addr, i, fb->s.ffb.dac_rev); /* Elite3D has different DAC revision numbering, and no DAC revisions have the reversed meaning of cursor enable */ if (afb) fb->s.ffb.dac_rev = 10; /* Unblank it just to be sure. When there are multiple * FFB/AFB cards in the system, or it is not the OBP * chosen console, it will have video outputs off in * the DAC. */ ffb_unblank(fb); return idstring;}MODULE_LICENSE("GPL");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -