📄 suncons.c
字号:
}}/* CG6 support code *//* 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 be 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 0x800000struct bt_regs { unsigned int addr; /* address register */ unsigned int color_map; /* color map */ unsigned int control; /* control register */ unsigned int cursor; /* cursor map register */};/* The contents are unknown */struct cg6_tec { int tec_matrix; int tec_clip; int tec_vdc;};struct cg6_thc { unsigned int thc_xxx0[512]; /* ??? */ unsigned int thc_hsync1; /* hsync timing */ unsigned int thc_hsync2; unsigned int thc_hsync3; unsigned int thc_vsync1; /* vsync timing */ unsigned int thc_vsync2; unsigned int thc_refresh; unsigned int thc_misc; unsigned int thc_xxx1[56]; unsigned int thc_cursxy; /* cursor x,y position (16 bits each) */ unsigned int thc_cursmask[32]; /* cursor mask bits */ unsigned int thc_cursbits[32]; /* what to show where mask enabled */};static voidcg6_restore_palette (void){ volatile struct bt_regs *bt; bt = fbinfo [0].info.cg6.bt; bt->addr = 0; bt->color_map = 0xffffffff; bt->color_map = 0xffffffff; bt->color_map = 0xffffffff;}/* Ugh: X wants to mmap a bunch of cute stuff at the same time :-( *//* So, we just mmap the things that are being asked for */static intcg6_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma, long base, void *xx){ unsigned int size, page, r, map_size; unsigned int map_offset = 0; fbinfo_t *fb = (fbinfo_t *) xx; size = vma->vm_end - vma->vm_start; if (vma->vm_offset & ~PAGE_MASK) return -ENXIO; /* To stop the swapper from even considering these pages */ vma->vm_flags |= FB_MMAP_VM_FLAGS; /* Each page, see which map applies */ for (page = 0; page < size; ){ switch (vma->vm_offset+page){ case CG6_TEC: map_size = PAGE_SIZE; map_offset = get_phys ((uint)fb->info.cg6.tec); break; case CG6_FBC: map_size = PAGE_SIZE; map_offset = get_phys ((uint)fb->info.cg6.fbc); break; case CG6_FHC: map_size = PAGE_SIZE; map_offset = get_phys ((uint)fb->info.cg6.fhc); break; case CG6_THC: map_size = PAGE_SIZE; map_offset = get_phys ((uint)fb->info.cg6.thc); break; case CG6_BTREGS: map_size = PAGE_SIZE; map_offset = get_phys ((uint)fb->info.cg6.bt); break; case CG6_DHC: map_size = PAGE_SIZE * 40; map_offset = get_phys ((uint)fb->info.cg6.dhc); break; case CG6_ROM: map_size = 0; break; case CG6_RAM: map_size = size-page; map_offset = get_phys ((uint) con_fb_base); if (map_size < fb->type.fb_size) map_size = fb->type.fb_size; break; default: map_size = 0; break; } if (!map_size){ page += PAGE_SIZE; continue; } r = io_remap_page_range (vma->vm_start+page, map_offset, map_size, vma->vm_page_prot, fb->space); if (r) return -EAGAIN; page += map_size; } vma->vm_inode = inode; inode->i_count++; return 0;}#define BT_D4M3(x) ((((x) >> 2) << 1) + ((x) >> 2)) /* (x / 4) * 3 */#define BT_D4M4(x) ((x) & ~3) /* (x / 4) * 4 */static voidcg6_loadcmap (void *fbinfo, int index, int count){ fbinfo_t *fb = (fbinfo_t *) fbinfo; struct bt_regs *bt = fb->info.cg6.bt; int i; bt->addr = index << 24; for (i = index; count--; i++){ bt->color_map = color_map.map [i][0] << 24; bt->color_map = color_map.map [i][1] << 24; bt->color_map = color_map.map [i][2] << 24; }}/* Load cursor information */static voidcg6_setcursor (struct cg6_info *info){ unsigned int v; struct cg6_cursor *c = &info->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); } info->thc->thc_cursxy = v;}#undef posstatic intcg6_scursor (struct fbcursor *cursor, fbinfo_t *fb){ int op = cursor->set; volatile struct cg6_thc *thc = fb->info.cg6.thc; struct cg6_cursor *cursor_info = &fb->info.cg6.cursor; int i, bytes = 0; if (op & FB_CUR_SETSHAPE){ if ((unsigned int) cursor->size.fbx > 32) return -EINVAL; if ((unsigned int) cursor->size.fby > 32) return -EINVAL; bytes = (cursor->size.fby * 32)/8; i = verify_area (VERIFY_READ, cursor->image, bytes); if (i) return i; i = verify_area (VERIFY_READ, cursor->mask, bytes); if (i) return i; } if (op & (FB_CUR_SETCUR | FB_CUR_SETPOS | FB_CUR_SETHOT)){ if (op & FB_CUR_SETCUR) cursor_info->enable = cursor->enable; if (op & FB_CUR_SETPOS) cursor_info->cpos = cursor->pos; if (op & FB_CUR_SETHOT) cursor_info->chot = cursor->hot; cg6_setcursor (&fb->info.cg6); } if (op & FB_CUR_SETSHAPE){ unsigned int u; cursor_info->size = cursor->size; memset ((void *)&cursor_info->bits, 0, sizeof (cursor_info->size)); memcpy (cursor_info->bits [0], cursor->mask, bytes); memcpy (cursor_info->bits [1], cursor->image, bytes); u = ~0; if (cursor_info->size.fbx < 32) u = ~(u >> cursor_info->size.fbx); for (i = 0; i < 32; i++){ int m = cursor_info->bits [0][i] & u; thc->thc_cursmask [i] = m; thc->thc_cursbits [i] = m & cursor_info->bits [1][i]; } } return 0;}/* Handle cg6-specific ioctls */static intcg6_ioctl (struct inode *inode, struct file *file, unsigned cmd, unsigned long arg, fbinfo_t *fb){ int i; switch (cmd){ case FBIOGCURMAX: i = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct fbcurpos)); if (i) return i; ((struct fbcurpos *) arg)->fbx = 32; ((struct fbcurpos *) arg)->fby = 32; break; case FBIOSVIDEO: /* vesa_blank and vesa_unblank could do the job on fb [0] */ break; case FBIOSCURSOR: return cg6_scursor ((struct fbcursor *) arg, fb); case FBIOSCURPOS: /* i= verify_area (VERIFY_READ, (void *) arg, sizeof (struct fbcurpos)); if (i) return i; */ fb->info.cg6.cursor.cpos = *(struct fbcurpos *)arg; cg6_setcursor (&fb->info.cg6); break; default: return -EINVAL; } return 0;}static voidcg6_setup (int slot, unsigned int cg6, int cg6_io){ struct cg6_info *cg6info; printk ("cgsix%d at 0x%8.8x\n", slot, (unsigned int) cg6); /* Fill in parameters we left out */ fbinfo [slot].type.fb_cmsize = 256; fbinfo [slot].mmap = cg6_mmap; fbinfo [slot].loadcmap = cg6_loadcmap; fbinfo [slot].ioctl = (void *) cg6_ioctl; fbinfo [slot].blank = 0; fbinfo [slot].unblank = 0; cg6info = (struct cg6_info *) &fbinfo [slot].info.cg6; /* Map the hardware registers */ cg6info->bt = sparc_alloc_io ((void *) cg6+CG6_BROOKTREE_OFFSET, 0, sizeof (struct bt_regs),"cgsix_dac", cg6_io, 0); cg6info->fhc = sparc_alloc_io ((void *) cg6+CG6_FHC_OFFSET, 0, sizeof (int), "cgsix_fhc", cg6_io, 0); cg6info->thc = sparc_alloc_io ((void *) cg6+CG6_THC_OFFSET, 0, sizeof (struct cg6_thc), "cgsix_thc", cg6_io, 0); cg6info->tec = sparc_alloc_io ((void *) cg6+CG6_TEC_OFFSET, 0, sizeof (struct cg6_tec), "cgsix_tec", cg6_io, 0); cg6info->dhc = sparc_alloc_io ((void *) cg6+CG6_DHC_OFFSET, 0, 0x40000, "cgsix_dhc", cg6_io, 0); cg6info->fbc = sparc_alloc_io ((void *) cg6+CG6_FBC_OFFSET, 0, 0x1000, "cgsix_fbc", cg6_io, 0); if (!con_fb_base){ con_fb_base = sparc_alloc_io ((void *) cg6+CG6_RAM_OFFSET, 0, fbinfo [slot].type.fb_size, "cgsix_ram", cg6_io, 0); } if (!slot) restore_palette = cg6_restore_palette;}/* The cg3 driver, obio space addresses for mapping the cg3 stuff */#define CG3_REGS 0x400000#define CG3_RAM 0x800000#define D4M3(x) ((((x)>>2)<<1) + ((x)>>2)) /* (x/4)*3 */#define D4M4(x) ((x)&~0x3) /* (x/4)*4 *//* The cg3 palette is loaded with 4 color values at each time *//* so you end up with: (rgb)(r), (gb)(rg), (b)(rgb), and so on */static voidcg3_loadcmap (void *fbinfo, int index, int count){ fbinfo_t *fb = (fbinfo_t *) fbinfo; struct bt_regs *bt = fb->info.cg3.bt; int *i, steps; i = &color_map.raw [D4M3(index)]; steps = D4M3(index+count-1) - D4M3(index)+3; bt->addr = D4M4(index); while (steps--) bt->color_map = *i++;}/* The cg3 is presumed to emulate a cg4, I guess older programs will want that *//* addresses above 0x4000000 are for cg3, below that it's cg4 emulation */static intcg3_mmap (struct inode *inode, struct file *file, struct vm_area_struct *vma, long base, void *xx){ unsigned int size, page, r, map_size; unsigned int map_offset = 0; fbinfo_t *fb = (fbinfo_t *) xx; size = vma->vm_end - vma->vm_start; if (vma->vm_offset & ~PAGE_MASK) return -ENXIO; /* To stop the swapper from even considering these pages */ vma->vm_flags |= FB_MMAP_VM_FLAGS; /* Each page, see which map applies */ for (page = 0; page < size; ){ switch (vma->vm_offset+page){ case CG3_MMAP_OFFSET: map_size = size-page; map_offset = get_phys ((uint) con_fb_base); if (map_size > fb->type.fb_size) map_size = fb->type.fb_size; break; default: map_size = 0; break; } if (!map_size){ page += PAGE_SIZE; continue; } r = io_remap_page_range (vma->vm_start+page, map_offset, map_size, vma->vm_page_prot, fb->space); if (r) return -EAGAIN; page += map_size; } vma->vm_inode = inode; inode->i_count++; return 0;}static voidcg3_setup (int slot, unsigned int cg3, int cg3_io){ struct cg3_info *cg3info; printk ("cgthree%d at 0x%8.8x\n", slot, cg3); /* Fill in parameters we left out */ fbinfo [slot].type.fb_cmsize = 256; fbinfo [slot].mmap = cg3_mmap; fbinfo [slot].loadcmap = cg3_loadcmap; fbinfo [slot].ioctl = 0; /* no special ioctls */ cg3info = (struct cg3_info *) &fbinfo [slot].info.cg3; /* Map the card registers */ cg3info->bt = sparc_alloc_io ((void *) cg3+CG3_REGS, 0, sizeof (struct bt_regs),"cg3_bt", cg3_io, 0); if (!con_fb_base){
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -