/* $Id: cgsixfb.c,v 1.7 1998/07/22 12:44:59 jj Exp $ * cgsixfb.c: CGsix (GX,GXplus) frame buffer driver * * Copyright (C) 1996,1998 Jakub Jelinek (jj@ultra.linux.cz) * Copyright (C) 1996 Miguel de Icaza (miguel@nuclecu.unam.mx) * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "sbusfb.h" #include /* Offset of interesting structures in the OBIO space */ /* * Brooktree is the video dac and is funny to program on the cg6. * (it's even funnier on the cg3) * The FBC could be the frame buffer control * The FHC could is the frame buffer hardware control. */ #define CG6_ROM_OFFSET 0x0 #define CG6_BROOKTREE_OFFSET 0x200000 #define CG6_DHC_OFFSET 0x240000 #define CG6_ALT_OFFSET 0x280000 #define CG6_FHC_OFFSET 0x300000 #define CG6_THC_OFFSET 0x301000 #define CG6_FBC_OFFSET 0x700000 #define CG6_TEC_OFFSET 0x701000 #define CG6_RAM_OFFSET 0x800000 /* FHC definitions */ #define CG6_FHC_FBID_SHIFT 24 #define CG6_FHC_FBID_MASK 255 #define CG6_FHC_REV_SHIFT 20 #define CG6_FHC_REV_MASK 15 #define CG6_FHC_FROP_DISABLE (1 << 19) #define CG6_FHC_ROW_DISABLE (1 << 18) #define CG6_FHC_SRC_DISABLE (1 << 17) #define CG6_FHC_DST_DISABLE (1 << 16) #define CG6_FHC_RESET (1 << 15) #define CG6_FHC_LITTLE_ENDIAN (1 << 13) #define CG6_FHC_RES_MASK (3 << 11) #define CG6_FHC_1024 (0 << 11) #define CG6_FHC_1152 (1 << 11) #define CG6_FHC_1280 (2 << 11) #define CG6_FHC_1600 (3 << 11) #define CG6_FHC_CPU_MASK (3 << 9) #define CG6_FHC_CPU_SPARC (0 << 9) #define CG6_FHC_CPU_68020 (1 << 9) #define CG6_FHC_CPU_386 (2 << 9) #define CG6_FHC_TEST (1 << 8) #define CG6_FHC_TEST_X_SHIFT 4 #define CG6_FHC_TEST_X_MASK 15 #define CG6_FHC_TEST_Y_SHIFT 0 #define CG6_FHC_TEST_Y_MASK 15 /* FBC mode definitions */ #define CG6_FBC_BLIT_IGNORE 0x00000000 #define CG6_FBC_BLIT_NOSRC 0x00100000 #define CG6_FBC_BLIT_SRC 0x00200000 #define CG6_FBC_BLIT_ILLEGAL 0x00300000 #define CG6_FBC_BLIT_MASK 0x00300000 #define CG6_FBC_VBLANK 0x00080000 #define CG6_FBC_MODE_IGNORE 0x00000000 #define CG6_FBC_MODE_COLOR8 0x00020000 #define CG6_FBC_MODE_COLOR1 0x00040000 #define CG6_FBC_MODE_HRMONO 0x00060000 #define CG6_FBC_MODE_MASK 0x00060000 #define CG6_FBC_DRAW_IGNORE 0x00000000 #define CG6_FBC_DRAW_RENDER 0x00008000 #define CG6_FBC_DRAW_PICK 0x00010000 #define CG6_FBC_DRAW_ILLEGAL 0x00018000 #define CG6_FBC_DRAW_MASK 0x00018000 #define CG6_FBC_BWRITE0_IGNORE 0x00000000 #define CG6_FBC_BWRITE0_ENABLE 0x00002000 #define CG6_FBC_BWRITE0_DISABLE 0x00004000 #define CG6_FBC_BWRITE0_ILLEGAL 0x00006000 #define CG6_FBC_BWRITE0_MASK 0x00006000 #define CG6_FBC_BWRITE1_IGNORE 0x00000000 #define CG6_FBC_BWRITE1_ENABLE 0x00000800 #define CG6_FBC_BWRITE1_DISABLE 0x00001000 #define CG6_FBC_BWRITE1_ILLEGAL 0x00001800 #define CG6_FBC_BWRITE1_MASK 0x00001800 #define CG6_FBC_BREAD_IGNORE 0x00000000 #define CG6_FBC_BREAD_0 0x00000200 #define CG6_FBC_BREAD_1 0x00000400 #define CG6_FBC_BREAD_ILLEGAL 0x00000600 #define CG6_FBC_BREAD_MASK 0x00000600 #define CG6_FBC_BDISP_IGNORE 0x00000000 #define CG6_FBC_BDISP_0 0x00000080 #define CG6_FBC_BDISP_1 0x00000100 #define CG6_FBC_BDISP_ILLEGAL 0x00000180 #define CG6_FBC_BDISP_MASK 0x00000180 #define CG6_FBC_INDEX_MOD 0x00000040 #define CG6_FBC_INDEX_MASK 0x00000030 /* THC definitions */ #define CG6_THC_MISC_REV_SHIFT 16 #define CG6_THC_MISC_REV_MASK 15 #define CG6_THC_MISC_RESET (1 << 12) #define CG6_THC_MISC_VIDEO (1 << 10) #define CG6_THC_MISC_SYNC (1 << 9) #define CG6_THC_MISC_VSYNC (1 << 8) #define CG6_THC_MISC_SYNC_ENAB (1 << 7) #define CG6_THC_MISC_CURS_RES (1 << 6) #define CG6_THC_MISC_INT_ENAB (1 << 5) #define CG6_THC_MISC_INT (1 << 4) #define CG6_THC_MISC_INIT 0x9f /* The contents are unknown */ struct cg6_tec { volatile int tec_matrix; volatile int tec_clip; volatile int tec_vdc; }; struct cg6_thc { uint thc_pad0[512]; volatile uint thc_hs; /* hsync timing */ volatile uint thc_hsdvs; volatile uint thc_hd; volatile uint thc_vs; /* vsync timing */ volatile uint thc_vd; volatile uint thc_refresh; volatile uint thc_misc; uint thc_pad1[56]; volatile uint thc_cursxy; /* cursor x,y position (16 bits each) */ volatile uint thc_cursmask[32]; /* cursor mask bits */ volatile uint thc_cursbits[32]; /* what to show where mask enabled */ }; struct cg6_fbc { u32 xxx0[1]; volatile u32 mode; volatile u32 clip; u32 xxx1[1]; volatile u32 s; volatile u32 draw; volatile u32 blit; volatile u32 font; u32 xxx2[24]; volatile u32 x0, y0, z0, color0; volatile u32 x1, y1, z1, color1; volatile u32 x2, y2, z2, color2; volatile u32 x3, y3, z3, color3; volatile u32 offx, offy; u32 xxx3[2]; volatile u32 incx, incy; u32 xxx4[2]; volatile u32 clipminx, clipminy; u32 xxx5[2]; volatile u32 clipmaxx, clipmaxy; u32 xxx6[2]; volatile u32 fg; volatile u32 bg; volatile u32 alu; volatile u32 pm; volatile u32 pixelm; u32 xxx7[2]; volatile u32 patalign; volatile u32 pattern[8]; u32 xxx8[432]; volatile u32 apointx, apointy, apointz; u32 xxx9[1]; volatile u32 rpointx, rpointy, rpointz; u32 xxx10[5]; volatile u32 pointr, pointg, pointb, pointa; volatile u32 alinex, aliney, alinez; u32 xxx11[1]; volatile u32 rlinex, rliney, rlinez; u32 xxx12[5]; volatile u32 liner, lineg, lineb, linea; volatile u32 atrix, atriy, atriz; u32 xxx13[1]; volatile u32 rtrix, rtriy, rtriz; u32 xxx14[5]; volatile u32 trir, trig, trib, tria; volatile u32 aquadx, aquady, aquadz; u32 xxx15[1]; volatile u32 rquadx, rquady, rquadz; u32 xxx16[5]; volatile u32 quadr, quadg, quadb, quada; volatile u32 arectx, arecty, arectz; u32 xxx17[1]; volatile u32 rrectx, rrecty, rrectz; u32 xxx18[5]; volatile u32 rectr, rectg, rectb, recta; }; static struct sbus_mmap_map cg6_mmap_map[] = { { CG6_FBC, CG6_FBC_OFFSET, PAGE_SIZE }, { CG6_TEC, CG6_TEC_OFFSET, PAGE_SIZE }, { CG6_BTREGS, CG6_BROOKTREE_OFFSET, PAGE_SIZE }, { CG6_FHC, CG6_FHC_OFFSET, PAGE_SIZE }, { CG6_THC, CG6_THC_OFFSET, PAGE_SIZE }, { CG6_ROM, CG6_ROM_OFFSET, 0x10000 }, { CG6_RAM, CG6_RAM_OFFSET, SBUS_MMAP_FBSIZE(1) }, { CG6_DHC, CG6_DHC_OFFSET, 0x40000 }, { 0, 0, 0 } }; static void cg6_setup(struct display *p) { p->next_line = sbusfbinfo(p->fb_info)->var.xres_virtual; p->next_plane = 0; } static void cg6_clear(struct vc_data *conp, struct display *p, int sy, int sx, int height, int width) { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct cg6_fbc *fbc = fb->s.cg6.fbc; int x, y, w, h; int i; do { i = fbc->s; } while (i & 0x10000000); fbc->fg = attr_bgcol_ec(p,conp); fbc->bg = attr_bgcol_ec(p,conp); fbc->pixelm = ~(0); fbc->alu = 0xea80ff00; fbc->s = 0; fbc->clip = 0; fbc->pm = ~(0); if (p->fontheightlog) { y = sy << p->fontheightlog; h = height << p->fontheightlog; } else { y = sy * p->fontheight; h = height * p->fontheight; } if (p->fontwidthlog) { x = sx << p->fontwidthlog; w = width << p->fontwidthlog; } else { x = sx * p->fontwidth; w = width * p->fontwidth; } fbc->arecty = y + fb->y_margin; fbc->arectx = x + fb->x_margin; fbc->arecty = y + fb->y_margin + h; fbc->arectx = x + fb->x_margin + w; do { i = fbc->draw; } while (i < 0 && (i & 0x20000000)); } static void cg6_fill(struct fb_info_sbusfb *fb, struct display *p, int s, int count, unsigned short *boxes) { int i; register struct cg6_fbc *fbc = fb->s.cg6.fbc; do { i = fbc->s; } while (i & 0x10000000); fbc->fg = attr_bgcol(p,s); fbc->bg = attr_bgcol(p,s); fbc->pixelm = ~(0); fbc->alu = 0xea80ff00; fbc->s = 0; fbc->clip = 0; fbc->pm = ~(0); while (count-- > 0) { fbc->arecty = boxes[1]; fbc->arectx = boxes[0]; fbc->arecty = boxes[3]; fbc->arectx = boxes[2]; boxes += 4; do { i = fbc->draw; } while (i < 0 && (i & 0x20000000)); } } static void cg6_putc(struct vc_data *conp, struct display *p, int c, int yy, int xx) { struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)p->fb_info; register struct cg6_fbc *fbc = fb->s.cg6.fbc; int i, x, y; u8 *fd; if (p->fontheightlog) { y = fb->y_margin + (yy << p->fontheightlog); i = ((c & p->charmask) << p->fontheightlog); } else { y = fb->y_margin + (yy * p->fontheight); i = (c & p->charmask) * p->fontheight; } #ifdef CONFIG_FBCON_FONTWIDTH8_ONLY fd = p->fontdata + i; x = fb->x_margin + xx * 8; #else if (p->fontwidth <= 8) fd = p->fontdata + i; else fd = p->fontdata + (i << 1); if (p->fontwidthlog) x = fb->x_margin + (xx << p->fontwidthlog); else x = fb->x_margin + (xx * p->fontwidth); #endif do { i = fbc->s; } while (i & 0x10000000); fbc->fg = attr_fgcol(p,c); fbc->bg = attr_bgcol(p,c); fbc->mode = 0x140000; fbc->alu = 0xe880fc30; fbc->pixelm = ~(0); fbc->s = 0; fbc->clip = 0; fbc->pm = 0xff; fbc->incx = 0; fbc->incy = 1; fbc->x0 = x; fbc->x1 = x + p->fontwidth - 1; fbc->y0 = y; #ifndef CONFIG_FBCON_FONTWIDTH8_ONLY if (p->fontwidth <= 8) { #endif for (i = 0; i < p->fontheight; i++) fbc->font = *fd++ << 24; #ifndef CONFIG_FBCON_FONTWIDTH8_ONLY } else { for (i = 0; i < p->fontheight; i++) { fbc->font = *(u16 *)fd << 16; fd += 2; } } #endif } static void cg6_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 cg6_fbc *fbc = fb->s.cg6.fbc; int i, x, y; u8 *fd1, *fd2, *fd3, *fd4; do { i = fbc->s; } while (i & 0x10000000); fbc->fg = attr_fgcol(p,*s); fbc->bg = attr_bgcol(p,*s); fbc->mode = 0x140000; fbc->alu = 0xe880fc30; fbc->pixelm = ~(0); fbc->s = 0; fbc->clip = 0; fbc->pm = 0xff; x = fb->x_margin; y = fb->y_margin; #ifdef CONFIG_FBCON_FONTWIDTH8_ONLY x += xx * 8; #else if (p->fontwidthlog) x += (xx << p->fontwidthlog); else x += xx * p->fontwidth; #endif if (p->fontheightlog) y += (yy << p->fontheightlog); else y += (yy * p->fontheight); #ifndef CONFIG_FBCON_FONTWIDTH8_ONLY if (p->fontwidth <= 8) { #endif while (count >= 4) { count -= 4; fbc->incx = 0; fbc->incy = 1; fbc->x0 = x; fbc->x1 = (x += 4 * p->fontwidth) - 1; fbc->y0 = y; if (p->fontheightlog) { fd1 = p->fontdata + ((*s++ & p->charmask) << p->fontheightlog); fd2 = p->fontdata + ((*s++ & p->charmask) << p->fontheightlog); fd3 = p->fontdata + ((*s++ & p->charmask) << p->fontheightlog); fd4 = p->fontdata + ((*s++ & p->charmask) << p->fontheightlog); } else { fd1 = p->fontdata + ((*s++ & p->charmask) * p->fontheight); fd2 = p->fontdata + ((*s++ & p->charmask) * p->fontheight); fd3 = p->fontdata + ((*s++ & p->charmask) * p->fontheight); fd4 = p->fontdata + ((*s++ & p->charmask) * p->fontheight); } #ifndef CONFIG_FBCON_FONTWIDTH8_ONLY if (p->fontwidth == 8) { #endif for (i = 0; i < p->fontheight; i++) fbc->font = ((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) << 8)) << 8)) << 8); #ifndef CONFIG_FBCON_FONTWIDTH8_ONLY } else { for (i = 0; i < p->fontheight; i++) fbc->font = (((u32)*fd4++) | ((((u32)*fd3++) | ((((u32)*fd2++) | (((u32)*fd1++) << p->fontwidth)) << p->fontwidth)) << p->fontwidth)) << (24 - 3 * p->fontwidth); } } } else { while (count >= 2) { count -= 2; fbc->incx = 0; fbc->incy = 1; fbc->x0 = x; fbc->x1 = (x += 2 * p->fontwidth) - 1; fbc->y0 = y; if (p->fontheightlog) { fd1 = p->fontdata + ((*s++ & p->charmask) << (p->fontheightlog + 1)); fd2 = p->fontdata + ((*s++ & p->charmask) << (p->fontheightlog + 1)); } else { fd1 = p->fontdata + (((*s++ & p->charmask) * p->fontheight) << 1); fd2 = p->fontdata + (((*s++ & p->charmask) * p->fontheight) << 1); } for (i = 0; i < p->fontheight; i++) { fbc->font = ((((u32)*(u16 *)fd1) << p->fontwidth) | ((u32)*(u16 *)fd2)) << (16 - p->fontwidth); fd1 += 2; fd2 += 2; } } #endif } while (count) { count--; fbc->incx = 0; fbc->incy = 1; fbc->x0 = x; fbc->x1 = (x += p->fontwidth) - 1; fbc->y0 = y; if (p->fontheightlog) i = ((*s++ & p->charmask) << p->fontheightlog); else i = ((*s++ & p->charmask) * p->fontheight); #ifndef CONFIG_FBCON_FONTWIDTH8_ONLY if (p->fontwidth <= 8) { #endif fd1 = p->fontdata + i; for (i = 0; i < p->fontheight; i++) fbc->font = *fd1++ << 24; #ifndef CONFIG_FBCON_FONTWIDTH8_ONLY } else { fd1 = p->fontdata + (i << 1); for (i = 0; i < p->fontheight; i++) { fbc->font = *(u16 *)fd1 << 16; fd1 += 2; } } #endif } } static void cg6_revc(struct display *p, int xx, int yy) { /* Not used if hw cursor */ } static void cg6_loadcmap (struct fb_info_sbusfb *fb, int index, int count) { struct bt_regs *bt = fb->s.cg6.bt; int i; bt->addr = index << 24; for (i = index; count--; i++){ bt->color_map = fb->color_map CM(i,0) << 24; bt->color_map = fb->color_map CM(i,1) << 24; bt->color_map = fb->color_map CM(i,2) << 24; } } static void cg6_restore_palette (struct fb_info_sbusfb *fb) { struct bt_regs *bt = fb->s.cg6.bt; bt->addr = 0; bt->color_map = 0xffffffff; bt->color_map = 0xffffffff; bt->color_map = 0xffffffff; } static struct display_switch cg6_dispsw __initdata = { cg6_setup, fbcon_redraw_bmove, cg6_clear, cg6_putc, cg6_putcs, cg6_revc, NULL, NULL, NULL, FONTWIDTHRANGE(1,16) /* Allow fontwidths up to 16 */ }; static void cg6_setcursormap (struct fb_info_sbusfb *fb, u8 *red, u8 *green, u8 *blue) { struct bt_regs *bt = fb->s.cg6.bt; bt->addr = 1 << 24; bt->cursor = red[0] << 24; bt->cursor = green[0] << 24; bt->cursor = blue[0] << 24; bt->addr = 3 << 24; bt->cursor = red[1] << 24; bt->cursor = green[1] << 24; bt->cursor = blue[1] << 24; } /* Set cursor shape */ static void cg6_setcurshape (struct fb_info_sbusfb *fb) { struct cg6_thc *thc = fb->s.cg6.thc; int i; for (i = 0; i < 32; i++) { thc->thc_cursmask [i] = fb->cursor.bits[0][i]; thc->thc_cursbits [i] = fb->cursor.bits[1][i]; } } /* Load cursor information */ static void cg6_setcursor (struct fb_info_sbusfb *fb) { unsigned int v; struct cg_cursor *c = &fb->cursor; if (c->enable) v = ((c->cpos.fbx - c->chot.fbx) << 16) |((c->cpos.fby - c->chot.fby) & 0xffff); else /* Magic constant to turn off the cursor */ v = ((65536-32) << 16) | (65536-32); fb->s.cg6.thc->thc_cursxy = v; } static void cg6_blank (struct fb_info_sbusfb *fb) { fb->s.cg6.thc->thc_misc &= ~CG6_THC_MISC_VIDEO; } static void cg6_unblank (struct fb_info_sbusfb *fb) { fb->s.cg6.thc->thc_misc |= CG6_THC_MISC_VIDEO; } static void cg6_reset (struct fb_info_sbusfb *fb) { unsigned int rev, conf; /* Turn off stuff in the Transform Engine. */ fb->s.cg6.tec->tec_matrix = 0; fb->s.cg6.tec->tec_clip = 0; fb->s.cg6.tec->tec_vdc = 0; /* Take care of bugs in old revisions. */ rev = (*(fb->s.cg6.fhc) >> CG6_FHC_REV_SHIFT) & CG6_FHC_REV_MASK; if (rev < 5) { conf = (*(fb->s.cg6.fhc) & CG6_FHC_RES_MASK) | CG6_FHC_CPU_68020 | CG6_FHC_TEST | (11 << CG6_FHC_TEST_X_SHIFT) | (11 << CG6_FHC_TEST_Y_SHIFT); if (rev < 2) conf |= CG6_FHC_DST_DISABLE; *(fb->s.cg6.fhc) = conf; } /* Set things in the FBC. */ fb->s.cg6.fbc->mode &= ~(CG6_FBC_BLIT_MASK | CG6_FBC_MODE_MASK | CG6_FBC_DRAW_MASK | CG6_FBC_BWRITE0_MASK | CG6_FBC_BWRITE1_MASK | CG6_FBC_BREAD_MASK | CG6_FBC_BDISP_MASK); fb->s.cg6.fbc->mode |= (CG6_FBC_BLIT_SRC | CG6_FBC_MODE_COLOR8 | CG6_FBC_DRAW_RENDER | CG6_FBC_BWRITE0_ENABLE | CG6_FBC_BWRITE1_DISABLE | CG6_FBC_BREAD_0 | CG6_FBC_BDISP_0); fb->s.cg6.fbc->clip = 0; fb->s.cg6.fbc->offx = 0; fb->s.cg6.fbc->offy = 0; fb->s.cg6.fbc->clipminx = 0; fb->s.cg6.fbc->clipminy = 0; fb->s.cg6.fbc->clipmaxx = fb->type.fb_width - 1; fb->s.cg6.fbc->clipmaxy = fb->type.fb_height - 1; /* Enable cursor in Brooktree DAC. */ fb->s.cg6.bt->addr = 0x06 << 24; fb->s.cg6.bt->control |= 0x03 << 24; } static void cg6_margins (struct fb_info_sbusfb *fb, struct display *p, int x_margin, int y_margin) { p->screen_base += (y_margin - fb->y_margin) * p->line_length + (x_margin - fb->x_margin); } static char idstring[60] __initdata = { 0 }; __initfunc(char *cgsixfb_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; unsigned long phys = fb->sbdp->reg_addrs[0].phys_addr; u32 conf; char *p; strcpy(fb->info.modename, "CGsix"); strcpy(fix->id, "CGsix"); fix->line_length = fb->var.xres_virtual; fix->accel = FB_ACCEL_SUN_CGSIX; var->accel_flags = FB_ACCELF_TEXT; disp->scrollmode = SCROLL_YREDRAW; if (!disp->screen_base) disp->screen_base = (char *)sparc_alloc_io(phys + CG6_RAM_OFFSET, 0, type->fb_size, "cgsix_ram", fb->iospace, 0); disp->screen_base += fix->line_length * fb->y_margin + fb->x_margin; fb->s.cg6.fbc = (struct cg6_fbc *)sparc_alloc_io(phys + CG6_FBC_OFFSET, 0, 4096, "cgsix_fbc", fb->iospace, 0); fb->s.cg6.tec = (struct cg6_tec *)sparc_alloc_io(phys + CG6_TEC_OFFSET, 0, sizeof(struct cg6_tec), "cgsix_tec", fb->iospace, 0); fb->s.cg6.thc = (struct cg6_thc *)sparc_alloc_io(phys + CG6_THC_OFFSET, 0, sizeof(struct cg6_thc), "cgsix_thc", fb->iospace, 0); fb->s.cg6.bt = (struct bt_regs *)sparc_alloc_io(phys + CG6_BROOKTREE_OFFSET, 0, sizeof(struct bt_regs), "cgsix_dac", fb->iospace, 0); fb->s.cg6.fhc = (u32 *)sparc_alloc_io(phys + CG6_FHC_OFFSET, 0, sizeof(u32), "cgsix_fhc", fb->iospace, 0); fb->dispsw = cg6_dispsw; fb->margins = cg6_margins; fb->loadcmap = cg6_loadcmap; fb->setcursor = cg6_setcursor; fb->setcursormap = cg6_setcursormap; fb->setcurshape = cg6_setcurshape; fb->restore_palette = cg6_restore_palette; fb->fill = cg6_fill; fb->blank = cg6_blank; fb->unblank = cg6_unblank; fb->reset = cg6_reset; fb->physbase = phys; fb->mmap_map = cg6_mmap_map; /* Initialize Brooktree DAC */ fb->s.cg6.bt->addr = 0x04 << 24; /* color planes */ fb->s.cg6.bt->control = 0xff << 24; fb->s.cg6.bt->addr = 0x05 << 24; fb->s.cg6.bt->control = 0x00 << 24; fb->s.cg6.bt->addr = 0x06 << 24; /* overlay plane */ fb->s.cg6.bt->control = 0x73 << 24; fb->s.cg6.bt->addr = 0x07 << 24; fb->s.cg6.bt->control = 0x00 << 24; conf = *fb->s.cg6.fhc; switch(conf & CG6_FHC_CPU_MASK) { case CG6_FHC_CPU_SPARC: p = "sparc"; break; case CG6_FHC_CPU_68020: p = "68020"; break; default: p = "i386"; break; } sprintf(idstring, #ifdef __sparc_v9__ "cgsix at %016lx TEC Rev %x CPU %s Rev %x", phys, #else "cgsix at %x.%08lx TEC Rev %x CPU %s Rev %x", fb->iospace, phys, #endif (fb->s.cg6.thc->thc_misc >> CG6_THC_MISC_REV_SHIFT) & CG6_THC_MISC_REV_MASK, p, conf >> CG6_FHC_REV_SHIFT & CG6_FHC_REV_MASK); cg6_reset(fb); return idstring; }