📄 sis_main.c
字号:
sisfb_heap_size = sisfb_heap_end - sisfb_heap_start;#ifdef CONFIG_FB_SIS_315 cmdq_baseport = (unsigned long *) (ivideo.mmio_vbase + MMIO_QUEUE_PHYBASE); write_port = (unsigned long *) (ivideo.mmio_vbase + MMIO_QUEUE_WRITEPORT); read_port = (unsigned long *) (ivideo.mmio_vbase + MMIO_QUEUE_READPORT); DPRINTK ("AGP base: 0x%p, read: 0x%p, write: 0x%p\n", cmdq_baseport, read_port, write_port); agp_size = COMMAND_QUEUE_AREA_SIZE;#ifndef AGPOFF agp_info = vmalloc (sizeof (agp_kern_info)); memset ((void *) agp_info, 0x00, sizeof (agp_kern_info)); agp_copy_info (agp_info); agp_backend_acquire (); agp = agp_allocate_memory (COMMAND_QUEUE_AREA_SIZE / PAGE_SIZE, AGP_NORMAL_MEMORY); if (agp == NULL) { DPRINTK ("Allocate AGP buffer failed.\n"); agp_enabled = 0; } else { if (agp_bind_memory (agp, agp->pg_start) != 0) { DPRINTK ("AGP : can not bind memory\n"); agp_enabled = 0; } else { agp_enable (0); } }#else agp_enabled = 0;#endif if (agp_enabled) cmd_type = AGP_CMD_QUEUE; else if (sisfb_heap_size >= COMMAND_QUEUE_AREA_SIZE) cmd_type = VM_CMD_QUEUE; else cmd_type = MMIO_CMD; switch (agp_size) { case 0x80000: temp = SIS_CMD_QUEUE_SIZE_512k; break; case 0x100000: temp = SIS_CMD_QUEUE_SIZE_1M; break; case 0x200000: temp = SIS_CMD_QUEUE_SIZE_2M; break; case 0x400000: temp = SIS_CMD_QUEUE_SIZE_4M; break; } switch (cmd_type) { case AGP_CMD_QUEUE:#ifndef AGPOFF DPRINTK ("AGP buffer base:0x%lx, offset:0x%x, size is %dK\n", agp_info->aper_base, agp->physical, agp_size / 1024); agp_phys = agp_info->aper_base + agp->physical; vgawb (CRTC_ADR, IND_SIS_AGP_IO_PAD); vgawb (CRTC_DATA, 0); vgawb (CRTC_DATA, SIS_AGP_2X); vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_THRESHOLD); vgawb (SEQ_DATA, COMMAND_QUEUE_THRESHOLD); vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET); vgawb (SEQ_DATA, SIS_CMD_QUEUE_RESET); *write_port = *read_port; temp |= SIS_AGP_CMDQUEUE_ENABLE; vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET); vgawb (SEQ_DATA, temp); *cmdq_baseport = agp_phys; sisfb_caps |= AGP_CMD_QUEUE_CAP;#endif break; case VM_CMD_QUEUE: sisfb_heap_end -= COMMAND_QUEUE_AREA_SIZE; sisfb_heap_size -= COMMAND_QUEUE_AREA_SIZE; vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_THRESHOLD); vgawb (SEQ_DATA, COMMAND_QUEUE_THRESHOLD); vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET); vgawb (SEQ_DATA, SIS_CMD_QUEUE_RESET); *write_port = *read_port; temp |= SIS_VRAM_CMDQUEUE_ENABLE; vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET); vgawb (SEQ_DATA, temp); *cmdq_baseport = ivideo.video_size - COMMAND_QUEUE_AREA_SIZE; sisfb_caps |= VM_CMD_QUEUE_CAP; DPRINTK ("VM Cmd Queue offset = 0x%lx, size is %dK\n", *cmdq_baseport, COMMAND_QUEUE_AREA_SIZE / 1024); break; default: vgawb (SEQ_ADR, IND_SIS_CMDQUEUE_SET); vgawb (SEQ_DATA, SIS_MMIO_CMD_ENABLE); break; }#endif#ifdef CONFIG_FB_SIS_300 if (sisfb_heap_size >= TURBO_QUEUE_AREA_SIZE) { unsigned int tqueue_pos; u8 tq_state; tqueue_pos = (ivideo.video_size - TURBO_QUEUE_AREA_SIZE) / (64 * 1024); temp = (u8) (tqueue_pos & 0xff); vgawb (SEQ_ADR, IND_SIS_TURBOQUEUE_SET); tq_state = vgarb (SEQ_DATA); tq_state |= 0xf0; tq_state &= 0xfc; tq_state |= (u8) (tqueue_pos >> 8); vgawb (SEQ_DATA, tq_state); vgawb (SEQ_ADR, IND_SIS_TURBOQUEUE_ADR); vgawb (SEQ_DATA, temp); sisfb_caps |= TURBO_QUEUE_CAP; sisfb_heap_end -= TURBO_QUEUE_AREA_SIZE; sisfb_heap_size -= TURBO_QUEUE_AREA_SIZE; DPRINTK ("Turbo Queue: start at 0x%lx, size is %dK\n", sisfb_heap_end, TURBO_QUEUE_AREA_SIZE / 1024); }#endif if (sisfb_heap_size >= HW_CURSOR_AREA_SIZE) { sisfb_heap_end -= HW_CURSOR_AREA_SIZE; sisfb_heap_size -= HW_CURSOR_AREA_SIZE; sisfb_hwcursor_vbase = sisfb_heap_end; sisfb_caps |= HW_CURSOR_CAP; DPRINTK ("Hardware Cursor: start at 0x%lx, size is %dK\n", sisfb_heap_end, HW_CURSOR_AREA_SIZE / 1024); } sisfb_heap.poha_chain = NULL; sisfb_heap.poh_freelist = NULL; poh = sisfb_poh_new_node (); if (poh == NULL) return 1; poh->poh_next = &sisfb_heap.oh_free; poh->poh_prev = &sisfb_heap.oh_free; poh->size = sisfb_heap_end - sisfb_heap_start + 1; poh->offset = sisfb_heap_start - (unsigned long) ivideo.video_vbase; DPRINTK ("sisfb:Heap start:0x%p, end:0x%p, len=%dk\n", (char *) sisfb_heap_start, (char *) sisfb_heap_end, (unsigned int) poh->size / 1024); DPRINTK ("sisfb:First Node offset:0x%x, size:%dk\n", (unsigned int) poh->offset, (unsigned int) poh->size / 1024); sisfb_heap.oh_free.poh_next = poh; sisfb_heap.oh_free.poh_prev = poh; sisfb_heap.oh_free.size = 0; sisfb_heap.max_freesize = poh->size; sisfb_heap.oh_used.poh_next = &sisfb_heap.oh_used; sisfb_heap.oh_used.poh_prev = &sisfb_heap.oh_used; sisfb_heap.oh_used.size = SENTINEL; return 0;}static SIS_OH *sisfb_poh_new_node (void){ int i; unsigned long cOhs; SIS_OHALLOC *poha; SIS_OH *poh; if (sisfb_heap.poh_freelist == NULL) { poha = kmalloc (OH_ALLOC_SIZE, GFP_KERNEL); poha->poha_next = sisfb_heap.poha_chain; sisfb_heap.poha_chain = poha; cOhs = (OH_ALLOC_SIZE - sizeof (SIS_OHALLOC)) / sizeof (SIS_OH) + 1; poh = &poha->aoh[0]; for (i = cOhs - 1; i != 0; i--) { poh->poh_next = poh + 1; poh = poh + 1; } poh->poh_next = NULL; sisfb_heap.poh_freelist = &poha->aoh[0]; } poh = sisfb_heap.poh_freelist; sisfb_heap.poh_freelist = poh->poh_next; return (poh);}static SIS_OH *sisfb_poh_allocate (unsigned long size){ SIS_OH *pohThis; SIS_OH *pohRoot; int bAllocated = 0; if (size > sisfb_heap.max_freesize) { DPRINTK ("sisfb: Can't allocate %dk size on offscreen\n", (unsigned int) size / 1024); return (NULL); } pohThis = sisfb_heap.oh_free.poh_next; while (pohThis != &sisfb_heap.oh_free) { if (size <= pohThis->size) { bAllocated = 1; break; } pohThis = pohThis->poh_next; } if (!bAllocated) { DPRINTK ("sisfb: Can't allocate %dk size on offscreen\n", (unsigned int) size / 1024); return (NULL); } if (size == pohThis->size) { pohRoot = pohThis; sisfb_delete_node (pohThis); } else { pohRoot = sisfb_poh_new_node (); if (pohRoot == NULL) { return (NULL); } pohRoot->offset = pohThis->offset; pohRoot->size = size; pohThis->offset += size; pohThis->size -= size; } sisfb_heap.max_freesize -= size; pohThis = &sisfb_heap.oh_used; sisfb_insert_node (pohThis, pohRoot); return (pohRoot);}static void sisfb_delete_node (SIS_OH * poh){ SIS_OH *poh_prev; SIS_OH *poh_next; poh_prev = poh->poh_prev; poh_next = poh->poh_next; poh_prev->poh_next = poh_next; poh_next->poh_prev = poh_prev; return;}static void sisfb_insert_node (SIS_OH * pohList, SIS_OH * poh){ SIS_OH *pohTemp; pohTemp = pohList->poh_next; pohList->poh_next = poh; pohTemp->poh_prev = poh; poh->poh_prev = pohList; poh->poh_next = pohTemp;}static SIS_OH *sisfb_poh_free (unsigned long base){ SIS_OH *pohThis; SIS_OH *poh_freed; SIS_OH *poh_prev; SIS_OH *poh_next; unsigned long ulUpper; unsigned long ulLower; int foundNode = 0; poh_freed = sisfb_heap.oh_used.poh_next; while (poh_freed != &sisfb_heap.oh_used) { if (poh_freed->offset == base) { foundNode = 1; break; } poh_freed = poh_freed->poh_next; } if (!foundNode) return (NULL); sisfb_heap.max_freesize += poh_freed->size; poh_prev = poh_next = NULL; ulUpper = poh_freed->offset + poh_freed->size; ulLower = poh_freed->offset; pohThis = sisfb_heap.oh_free.poh_next; while (pohThis != &sisfb_heap.oh_free) { if (pohThis->offset == ulUpper) { poh_next = pohThis; } else if ((pohThis->offset + pohThis->size) == ulLower) { poh_prev = pohThis; } pohThis = pohThis->poh_next; } sisfb_delete_node (poh_freed); if (poh_prev && poh_next) { poh_prev->size += (poh_freed->size + poh_next->size); sisfb_delete_node (poh_next); sisfb_free_node (poh_freed); sisfb_free_node (poh_next); return (poh_prev); } if (poh_prev) { poh_prev->size += poh_freed->size; sisfb_free_node (poh_freed); return (poh_prev); } if (poh_next) { poh_next->size += poh_freed->size; poh_next->offset = poh_freed->offset; sisfb_free_node (poh_freed); return (poh_next); } sisfb_insert_node (&sisfb_heap.oh_free, poh_freed); return (poh_freed);}static void sisfb_free_node (SIS_OH * poh){ if (poh == NULL) { return; } poh->poh_next = sisfb_heap.poh_freelist; sisfb_heap.poh_freelist = poh; return;}void sis_malloc (struct sis_memreq *req){ SIS_OH *poh; poh = sisfb_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->offset + (unsigned long) ivideo.video_vbase)); req->offset = poh->offset; req->size = poh->size; }}void sis_free (unsigned long base){ SIS_OH *poh; poh = sisfb_poh_free (base); if (poh == NULL) { DPRINTK ("sisfb: sisfb_poh_free() failed at base 0x%x\n", (unsigned int) base); }}/* ------------------ SetMode Routines ------------------------------- */static void sisfb_pre_setmode (void){ u8 cr30 = 0, cr31 = 0; vgawb (CRTC_ADR, 0x31); cr31 = vgarb (CRTC_DATA) & ~0x60; switch (ivideo.disp_state & DISPTYPE_DISP2) { case DISPTYPE_CRT2: cr30 = (SIS_VB_OUTPUT_CRT2 | SIS_SIMULTANEOUS_VIEW_ENABLE); cr31 |= SIS_DRIVER_MODE; break; case DISPTYPE_LCD: cr30 = (SIS_VB_OUTPUT_LCD | SIS_SIMULTANEOUS_VIEW_ENABLE); cr31 |= SIS_DRIVER_MODE; break; case DISPTYPE_TV: if (ivideo.TV_type == TVMODE_HIVISION) cr30 = (SIS_VB_OUTPUT_HIVISION | SIS_SIMULTANEOUS_VIEW_ENABLE); else if (ivideo.TV_plug == TVPLUG_SVIDEO) cr30 = (SIS_VB_OUTPUT_SVIDEO | SIS_SIMULTANEOUS_VIEW_ENABLE); else if (ivideo.TV_plug == TVPLUG_COMPOSITE) cr30 = (SIS_VB_OUTPUT_COMPOSITE | SIS_SIMULTANEOUS_VIEW_ENABLE); else if (ivideo.TV_plug == TVPLUG_SCART) cr30 = (SIS_VB_OUTPUT_SCART | SIS_SIMULTANEOUS_VIEW_ENABLE); cr31 |= SIS_DRIVER_MODE; /*karl */ if (sisfb_tvmode == 1) cr31 |= 0x1; if (sisfb_tvmode == 2) cr31 &= ~0x1; break; default: cr30 = 0x00; cr31 |= (SIS_DRIVER_MODE | SIS_VB_OUTPUT_DISABLE); } vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR30); vgawb (CRTC_DATA, cr30); vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR31); vgawb (CRTC_DATA, cr31); vgawb (CRTC_ADR, IND_SIS_SCRATCH_REG_CR33); vgawb (CRTC_DATA, sisfb_rate_idx & 0x0F);}static void sisfb_post_setmode (void){ u8 reg; vgawb (CRTC_ADR, 0x17); reg = vgarb (CRTC_DATA); if ((ivideo.hasVB == HASVB_LVDS) || (ivideo.hasVB == HASVB_LVDS_CHRONTEL)) if (ivideo.video_bpp == 8) sisfb_crt1off = 0; if (sisfb_crt1off) reg &= ~0x80; else reg |= 0x80; vgawb (CRTC_DATA, reg); vgawb (SEQ_ADR, IND_SIS_RAMDAC_CONTROL); reg = vgarb (SEQ_DATA); reg &= ~0x04; vgawb (SEQ_DATA, reg); if ((ivideo.disp_state & DISPTYPE_TV) && (ivideo.hasVB == HASVB_301)) { /*karl */ vgawb (VB_PART4_ADR, 0x01); reg = vgarb (VB_PART4_DATA); if ((reg != 0xB1) && (reg != 0xB0)) { /*301B Revision ID */ // Eden Chen switch (ivideo.video_width) { case 320: filter_tb = (ivideo.TV_type == TVMODE_NTSC) ? 4 : 12; break; case 640: filter_tb = (ivideo.TV_type == TVMODE_NTSC) ? 5 : 13; break; case 720: filter_tb = (ivideo.TV_type == TVMODE_NTSC) ? 6 : 14; break; case 800: filter_tb = (ivideo.TV_type == TVMODE_NTSC) ? 7 : 15; break; default: filter = -1; break; } // ~Eden Chen // Eden Chen //vgawb(VB_PART1_ADR, 0x24); vgawb (VB_PART1_ADR, IND_SIS_CRT2_WRITE_ENABLE); // ~Eden Chen vgawb (VB_PART1_DATA, 0x1); // Eden Chen for Debug // ~Eden Chen if (ivideo.TV_type == TVMODE_NTSC) { vgawb (VB_PART2_ADR, 0x3A); reg = vgarb (VB_PART2_DATA); reg &= 0x1F; vgawb (VB_PART2_DATA, reg); if (ivideo.TV_plug == TVPLUG_SVIDEO) { vgawb (VB_PART2_ADR, 0x30); reg = vgarb (VB_PART2_DATA); reg &= 0xDF; vgawb (VB_PART2_DATA, reg); } else if (ivideo.TV_plug == TVPLUG_COMPOSITE) { vgawb (VB_PART2_ADR, 0x30); reg = vgarb (VB_PART2_DATA); reg |= 0x20; vgawb (VB_PART2_DATA, reg); switch (ivideo.video_width) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -