sis_main.c
来自「讲述linux的初始化过程」· C语言 代码 · 共 2,375 行 · 第 1/4 页
C
2,375 行
} else if ((pohThis->ulOffset + pohThis->ulSize) == ulLower) { pohPrev = pohThis; } pohThis = pohThis->pohNext; } delete_node(pohFreed); if (pohPrev && pohNext) { pohPrev->ulSize += (pohFreed->ulSize + pohNext->ulSize); delete_node(pohNext); free_node(pohFreed); free_node(pohNext); return (pohPrev); } if (pohPrev) { pohPrev->ulSize += pohFreed->ulSize; free_node(pohFreed); return (pohPrev); } if (pohNext) { pohNext->ulSize += pohFreed->ulSize; pohNext->ulOffset = pohFreed->ulOffset; free_node(pohFreed); return (pohNext); } insert_node(&heap.ohFree, pohFreed); return (pohFreed);}/* * Frees our basic data structure allocation unit by adding it to a free * list. */static void free_node(struct OH *poh){ if (poh == NULL) { return; } poh->pohNext = heap.pohFreeList; heap.pohFreeList = poh; return;}void sis_malloc(struct sis_memreq *req){ struct OH *poh; poh = poh_allocate(req->size); if (poh == NULL) { req->offset = 0; req->size = 0; DPRINTK("sisfb: VMEM Allocation Failed\n"); } else { DPRINTK("sisfb: VMEM Allocation Successed : 0x%p\n", (char *) (poh->ulOffset + (unsigned long) ivideo.video_vbase)); req->offset = poh->ulOffset; req->size = poh->ulSize; }}void sis_free(unsigned long base){ struct OH *poh; poh = poh_free(base); if (poh == NULL) { DPRINTK("sisfb: poh_free() failed at base 0x%x\n", (unsigned int) base); }}void sis_dispinfo(struct ap_data *rec){ rec->minfo.bpp = ivideo.video_bpp; rec->minfo.xres = ivideo.video_width; rec->minfo.yres = ivideo.video_height; rec->minfo.v_xres = ivideo.video_vwidth; rec->minfo.v_yres = ivideo.video_vheight; rec->minfo.org_x = ivideo.org_x; rec->minfo.org_y = ivideo.org_y; rec->minfo.vrate = ivideo.refresh_rate; rec->iobase = ivideo.vga_base - 0x30; rec->mem_size = ivideo.video_size; rec->disp_state = ivideo.disp_state; switch(HwExt.jChipID) { case SIS_Glamour: rec->chip = SiS_300; break; case SIS_Trojan: if((HwExt.revision_id & 0xf0) == 0x30) rec->chip = SiS_630S; else rec->chip = SiS_630; break; case SIS_Spartan: rec->chip = SiS_540; break; case SIS_730: rec->chip = SiS_730; break; default: rec->chip = SiS_UNKNOWN; break; }}/* ---------------------- SetMode Routines -------------------------- */void SetReg1(u16 port, u16 index, u16 data){ outb((u8) (index & 0xff), port); port++; outb((u8) (data & 0xff), port);}void SetReg3(u16 port, u16 data){ outb((u8) (data & 0xff), port);}void SetReg4(u16 port, unsigned long data){ outl((u32) (data & 0xffffffff), port);}u8 GetReg1(u16 port, u16 index){ u8 data; outb((u8) (index & 0xff), port); port += 1; data = inb(port); return (data);}u8 GetReg2(u16 port){ u8 data; data = inb(port); return (data);}u32 GetReg3(u16 port){ u32 data; data = inl(port); return (data);}void ClearDAC(u16 port){ int i,j; vgawb(DAC_ADR, 0x00); for(i=0; i<256; i++) for(j=0; j<3; j++) vgawb(DAC_DATA, 0);}void ClearBuffer(PHW_DEVICE_EXTENSION pHwExt){ memset((char *) ivideo.video_vbase, 0, video_linelength * ivideo.video_height);}static void pre_setmode(void){ unsigned char uCR30=0, uCR31=0; switch(uDispType & MASK_DISPTYPE_DISP2) { case MASK_DISPTYPE_CRT2: uCR30 = 0x41; uCR31 = 0x40; break; case MASK_DISPTYPE_LCD: uCR30 = 0x21; uCR31 = 0x40; break; case MASK_DISPTYPE_TV: if(ivideo.TV_type == TVMODE_HIVISION) uCR30 = 0x81; else if(ivideo.TV_plug == TVPLUG_SVIDEO) uCR30 = 0x09; else if(ivideo.TV_plug == TVPLUG_COMPOSITE) uCR30 = 0x05; else if(ivideo.TV_plug == TVPLUG_SCART) uCR30 = 0x11; uCR31 = 0x40; /* CR31[0] will be set in setmode() */ break; default: uCR30 = 0x00; uCR31 = 0x60; } vgawb(CRTC_ADR, 0x30); vgawb(CRTC_DATA, uCR30); vgawb(CRTC_ADR, 0x31); vgawb(CRTC_DATA, uCR31); vgawb(CRTC_ADR, 0x33); vgawb(CRTC_DATA, rate_idx & 0x0f);}static void post_setmode(void){ u8 uTemp; vgawb(CRTC_ADR, 0x17); uTemp = vgarb(CRTC_DATA); if(crt1off) /* turn off CRT1 */ uTemp &= ~0x80; else /* turn on CRT1 */ uTemp |= 0x80; vgawb(CRTC_DATA, uTemp); /* disable 24-bit palette RAM and Gamma correction */ vgawb(SEQ_ADR, 0x07); uTemp = vgarb(SEQ_DATA); uTemp &= ~0x04; vgawb(SEQ_DATA, uTemp);}static void search_mode(const char *name){ int i = 0; if (name == NULL) return; while (sisbios_mode[i].mode_no != 0) { if (!strcmp(name, sisbios_mode[i].name)) { mode_idx = i; break; } i++; } if (mode_idx < 0) DPRINTK("Invalid user mode : %s\n", name);}static u8 search_refresh_rate(unsigned int rate){ u16 xres, yres; int i = 0; xres = sisbios_mode[mode_idx].xres; yres = sisbios_mode[mode_idx].yres; while ((vrate[i].idx != 0) && (vrate[i].xres <= xres)) { if ((vrate[i].xres == xres) && (vrate[i].yres == yres) && (vrate[i].refresh == rate)) { rate_idx = vrate[i].idx; return rate_idx; } i++; } DPRINTK("sisfb: Unsupported rate %d in %dx%d mode\n", rate, xres, yres); return 0;}/* ------------------ Public Routines ------------------------------- *//* * Get the Fixed Part of the Display */static int sisfb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info){ DPRINTK("sisfb: sisfb_get_fix:[%d]\n", con); memset(fix, 0, sizeof(struct fb_fix_screeninfo)); strcpy(fix->id, fb_info.modename); fix->smem_start = ivideo.video_base; if(ivideo.video_size > 0x800000) fix->smem_len = RESERVED_MEM_SIZE_8M; /* reserved for Xserver */ else fix->smem_len = RESERVED_MEM_SIZE_4M; /* reserved for Xserver */ fix->type = video_type; fix->type_aux = 0; if (ivideo.video_bpp == 8) fix->visual = FB_VISUAL_PSEUDOCOLOR; else fix->visual = FB_VISUAL_TRUECOLOR; fix->xpanstep = 0; fix->ypanstep = 0; fix->ywrapstep = 0; fix->line_length = video_linelength; fix->mmio_start = ivideo.mmio_base; fix->mmio_len = MMIO_SIZE; fix->accel = FB_ACCEL_SIS_GLAMOUR; fix->reserved[0] = ivideo.video_size & 0xFFFF; fix->reserved[1] = (ivideo.video_size >> 16) & 0xFFFF; fix->reserved[2] = caps; /* capabilities */ return 0;}/* * Get the User Defined Part of the Display */static int sisfb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){ DPRINTK("sisfb: sisfb_get_var:[%d]\n", con); if (con == -1) memcpy(var, &default_var, sizeof(struct fb_var_screeninfo)); else *var = fb_display[con].var; return 0;}/* * Set the User Defined Part of the Display */static int sisfb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){ int err; unsigned int cols, rows; fb_display[con].var.activate = FB_ACTIVATE_NOW; /* Set mode */ if (do_set_var(var, con == currcon, info)) { crtc_to_var(var); /* return current mode to user */ return -EINVAL; } /* get actual setting value */ crtc_to_var(var); /* update display of current console */ sisfb_set_disp(con, var); if (info->changevar) (*info->changevar) (con); if ((err = fb_alloc_cmap(&fb_display[con].cmap, 0, 0))) return err; do_install_cmap(con, info); /* inform console to update struct display */ cols = sisbios_mode[mode_idx].cols; rows = sisbios_mode[mode_idx].rows; vc_resize_con(rows, cols, fb_display[con].conp->vc_num); return 0;}/* * Get the Colormap */static int sisfb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ DPRINTK("sisfb: sisfb_get_cmap:[%d]\n", con); if (con == currcon) return fb_get_cmap(cmap, kspc, sis_getcolreg, info); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else fb_copy_cmap(fb_default_cmap(video_cmap_len), cmap, kspc ? 0 : 2); return 0;}/* * Set the Colormap */static int sisfb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ int err; if (!fb_display[con].cmap.len) { /* no colormap allocated */ err = fb_alloc_cmap(&fb_display[con].cmap, video_cmap_len, 0); if (err) return err; } if (con == currcon) /* current console */ return fb_set_cmap(cmap, kspc, sis_setcolreg, info); else fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); return 0;}static int sisfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg, int con, struct fb_info *info){ switch (cmd) { case FBIO_ALLOC: if(!capable(CAP_SYS_RAWIO)) return -EPERM; sis_malloc((struct sis_memreq *) arg); break; case FBIO_FREE: if(!capable(CAP_SYS_RAWIO)) return -EPERM; sis_free(*(unsigned long *) arg); break; case FBIOGET_GLYPH: sis_get_glyph((struct GlyInfo *) arg); break; case FBIOGET_HWCINFO: { unsigned long *hwc_offset = (unsigned long *) arg; if (caps & HW_CURSOR_CAP) *hwc_offset = hwcursor_vbase - (unsigned long) ivideo.video_vbase; else *hwc_offset = 0; break; } case FBIOPUT_MODEINFO: { struct mode_info *x = (struct mode_info *)arg; /* Set Mode Parameters by XServer */ ivideo.video_bpp = x->bpp; ivideo.video_width = x->xres; ivideo.video_height = x->yres; ivideo.video_vwidth = x->v_xres; ivideo.video_vheight = x->v_yres; ivideo.org_x = x->org_x; ivideo.org_y = x->org_y; ivideo.refresh_rate = x->vrate; break; } case FBIOGET_DISPINFO: sis_dispinfo((struct ap_data *)arg); break; default: return -EINVAL; } return 0;}static int sisfb_mmap(struct fb_info *info, struct file *file, struct vm_area_struct *vma){ struct fb_var_screeninfo var; unsigned long start; unsigned long off; u32 len; if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) return -EINVAL; off = vma->vm_pgoff << PAGE_SHIFT; /* frame buffer memory */ start = (unsigned long) ivideo.video_base; len = PAGE_ALIGN((start & ~PAGE_MASK) + ivideo.video_size); if (off >= len) { /* memory mapped io */ off -= len; sisfb_get_var(&var, currcon, info); if (var.accel_flags) return -EINVAL; start = (unsigned long) ivideo.mmio_base; len = PAGE_ALIGN((start & ~PAGE_MASK) + MMIO_SIZE); } start &= PAGE_MASK; if ((vma->vm_end - vma->vm_start + off) > len) return -EINVAL; off += start; vma->vm_pgoff = off >> PAGE_SHIFT;#if defined(__i386__) if (boot_cpu_data.x86 > 3) pgprot_val(vma->vm_page_prot) |= _PAGE_PCD;#endif if (io_remap_page_range(vma->vm_start, off, vma->vm_end - vma->vm_start, vma->vm_page_prot)) return -EAGAIN; return 0;}static struct fb_ops sisfb_ops = { owner: THIS_MODULE, fb_get_fix: sisfb_get_fix, fb_get_var: sisfb_get_var, fb_set_var: sisfb_set_var, fb_get_cmap: sisfb_get_cmap, fb_set_cmap: sisfb_set_cmap, fb_ioctl: sisfb_ioctl, fb_mmap: sisfb_mmap,};int sisfb_setup(char *options){ char *this_opt; fb_info.fontname[0] = '\0'; ivideo.refresh_rate = 0; if (!options || !*options) return 0; for (this_opt = strtok(options, ","); this_opt; this_opt = strtok(NULL, ",")) { if (!*this_opt) continue; if (!strcmp(this_opt, "inverse")) { inverse = 1; fb_invert_cmaps(); } else if (!strncmp(this_opt, "font:", 5)) { strcpy(fb_info.fontname, this_opt + 5); } else if (!strncmp(this_opt, "mode:", 5)) { search_mode(this_opt + 5); } else if (!strncmp(this_opt, "vrate:", 6)) { ivideo.refresh_rate = simple_strtoul(this_opt + 6, NULL, 0); } else if (!strncmp(this_opt, "off", 3)) { sisfb_off = 1; } else if (!strncmp(this_opt, "crt1off", 7)) { crt1off = 1; } else DPRINTK("invalid parameter %s\n", this_opt); } return 0;}static int sisfb_update_var(int con, struct fb_info *info){ return 0;}/* * Switch Console (called by fbcon.c) */static int sisfb_switch(int con, struct fb_info *info){ int cols, rows; DPRINTK("sisfb: switch console from [%d] to [%d]\n", currcon, con); /* update colormap of current console */ if (fb_display[currcon].cmap.len) fb_get_cmap(&fb_display[currcon].cmap, 1, sis_getcolreg, info); fb_display[con].var.activate = FB_ACTIVATE_NOW; /* same mode, needn't change mode actually */ if (!memcmp(&fb_display[con].var, &fb_display[currcon].var, sizeof(struct fb_var_screeninfo))) { currcon = con; return 1; } currcon = con;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?