📄 cirrus.c
字号:
}/* Scanline offset */ if (modeinfo->bytesPerPixel == 4) { /* At 32bpp the chip does an extra multiplication by two. */ if (cirrus_chiptype >= CLGD5436) { /* Do these chipsets multiply by 4? */ moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 5; SETBITSFROMVALUE(moderegs[CIRRUS_CR1B], 0x10, modeinfo->lineWidth, 0x2000); } else { moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 4; SETBITSFROMVALUE(moderegs[CIRRUS_CR1B], 0x10, modeinfo->lineWidth, 0x1000); } } else if (modeinfo->bitsPerPixel == 4) /* 16 color mode (planar). */ moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 1; else { moderegs[VGA_SCANLINEOFFSET] = modeinfo->lineWidth >> 3; SETBITSFROMVALUE(moderegs[CIRRUS_CR1B], 0x10, modeinfo->lineWidth, 0x800); }/* Clocking */ moderegs[VGA_MISCOUTPUT] |= 0x0C; /* Use VCLK3. */ moderegs[CIRRUS_VCLK3NUMERATOR] = fixed_clock_numerator[modetiming->selectedClockNo]; moderegs[CIRRUS_VCLK3DENOMINATOR] = fixed_clock_denominator[modetiming->selectedClockNo];/* DAC register and Sequencer Mode */ { unsigned char DAC, SR7; DAC = 0x00; SR7 = 0x00; if (modeinfo->bytesPerPixel > 0) SR7 = 0x01; /* Packed-pixel mode. */ if (modeinfo->bytesPerPixel == 2) { int rgbmode; rgbmode = 0; /* 5-5-5 RGB. */ if (modeinfo->colorBits == 16) rgbmode = 1; /* Add one for 5-6-5 RGB. */ if (cirrus_chiptype >= CLGD5426) { /* Pixel clock (double edge) mode. */ DAC = 0xD0 + rgbmode; SR7 = 0x07; } else { /* Single-edge (double VCLK). */ DAC = 0xF0 + rgbmode; SR7 = 0x03; } } if (modeinfo->bytesPerPixel >= 3) { /* Set 8-8-8 RGB mode. */ DAC = 0xE5; SR7 = 0x05; if (modeinfo->bytesPerPixel == 4) SR7 = 0x09; }#ifdef SUPPORT_5434_PALETTE_CLOCK_DOUBLING if (modeinfo->bytesPerPixel == 1 && (modetiming->flags & HADJUSTED)) { /* Palette clock doubling mode on 5434 8bpp. */ DAC = 0x4A; SR7 = 0x07; }#endif moderegs[CIRRUS_HIDDENDAC] = DAC; moderegs[CIRRUS_SR7] = SR7; }/* DRAM control and CRT FIFO */ if (cirrus_chiptype >= CLGD5422) /* Enable large CRT FIFO. */ moderegs[CIRRUS_DRAMCONTROL] |= 0x20; if (cirrus_memory == 2048 && cirrus_chiptype <= CLGD5429) /* Enable DRAM Bank Select. */ moderegs[CIRRUS_DRAMCONTROL] |= 0x80; if (cirrus_chiptype >= CLGD5424) { /* CRT FIFO threshold setting. */ unsigned char threshold; threshold = 8;/* if (cirrus_chiptype >= CLGD5434) threshold = 1;*/ /* XXX Needs more elaborate setting. */ SETBITS(moderegs[CIRRUS_PERFTUNING], 0x0F, threshold); } if (CHIP_HAS_MCLK_REGISTER()) if (programmedMCLK != actualMCLK && modeinfo->bytesPerPixel > 0) /* Program higher MCLK for packed-pixel modes. */ moderegs[CIRRUS_MCLKREGISTER] = programmedMCLK;}/* This is the clock mapping function that is put in the CardSpecs. */static int cirrus_map_clock(int bpp, int pixelclock){ if (bpp == 24 && cirrus_chiptype < CLGD5436) /* Most chips need a tripled clock for 24bpp. */ return pixelclock * 3; if (bpp == 16 && cirrus_chiptype <= CLGD5424) /* The 5422/24 need to use a doubled clock. */ return pixelclock * 2; return pixelclock;}/* This is the horizontal CRTC mapping function in the CardSpecs. */static int cirrus_map_horizontal_crtc(int bpp, int pixelclock, int htiming){#ifdef ALWAYS_USE_5434_PALETTE_CLOCK_DOUBLING if (bpp == 8 && cirrus_chiptype >= CLGD5434)#else if (bpp == 8 && cirrus_chiptype >= CLGD5434 && pixelclock > 86000)#endif /* 5434 palette clock doubling mode; divide CRTC by 2. */ return htiming / 2; /* Otherwise, don't change. */ return htiming;}static void init_acceleration_specs_for_mode(AccelSpecs * accelspecs, int bpp, int width_in_pixels);static int cirrus_setmode(int mode, int prv_mode){ unsigned char *moderegs; ModeTiming *modetiming; ModeInfo *modeinfo; if ((mode < G640x480x256 && mode != G320x200x256) || mode == G720x348x2) { __svgalib_clear_accelspecs(__svgalib_driverspecs->accelspecs); /* Let the standard VGA driver set standard VGA modes */ /* But first reset an Cirrus extended register that */ /* an old XFree86 Trident probe corrupts. */ outw(CRT_IC, 0x4a0b); return __svgalib_vga_driverspecs.setmode(mode, prv_mode); } if (!cirrus_modeavailable(mode)) return 1; modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); modetiming = malloc(sizeof(ModeTiming)); if (__svgalib_getmodetiming(modetiming, modeinfo, cardspecs)) { free(modetiming); free(modeinfo); return 1; } moderegs = malloc(CIRRUS_TOTAL_REGS); cirrus_initializemode(moderegs, modetiming, modeinfo); free(modetiming); __svgalib_setregs(moderegs); /* Set standard regs. */ cirrus_setregs(moderegs, mode); /* Set extended regs. */ free(moderegs); __svgalib_InitializeAcceleratorInterface(modeinfo); init_acceleration_specs_for_mode(__svgalib_driverspecs->accelspecs, modeinfo->bitsPerPixel, modeinfo->lineWidth / modeinfo->bytesPerPixel); __svgalib_cirrusaccel_init(__svgalib_driverspecs->accelspecs, modeinfo->bitsPerPixel, modeinfo->lineWidth / modeinfo->bytesPerPixel); free(modeinfo); return 0;}/* Unlock chipset-specific registers */static void cirrus_unlock(void){ int vgaIOBase, temp; /* Are we Mono or Color? */ vgaIOBase = (inb(0x3CC) & 0x01) ? 0x3D0 : 0x3B0; outb(SEQ_I, 0x06); outb(SEQ_D, 0x12); /* unlock cirrus special */ /* Put the Vert. Retrace End Reg in temp */ outb(vgaIOBase + 4, 0x11); temp = inb(vgaIOBase + 5); /* Put it back with PR bit set to 0 */ /* This unprotects the 0-7 CRTC regs so */ /* they can be modified, i.e. we can set */ /* the timing. */ outb(vgaIOBase + 5, temp & 0x7F);}/* Relock chipset-specific registers *//* (currently not used) */static void cirrus_lock(void){ outb(SEQ_I, 0x06); outb(SEQ_D, 0x0F); /* relock cirrus special */}/* Indentify chipset, initialize and return non-zero if detected */static int cirrus_test(void){ int oldlockreg; int lockreg; outb(SEQ_I, 0x06); oldlockreg = inb(SEQ_D); cirrus_unlock(); /* If it's a Cirrus at all, we should be */ /* able to read back the lock register */ outb(SEQ_I, 0x06); lockreg = inb(SEQ_D); /* Ok, if it's not 0x12, we're not a Cirrus542X. */ if (lockreg != 0x12) { outb(SEQ_I, 0x06); outb(SEQ_D, oldlockreg); return 0; } /* The above check seems to be weak, so we also check the chip ID. */ outb(__svgalib_CRT_I, 0x27); switch (inb(__svgalib_CRT_D) >> 2) { case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x27: /* 5429 */ case 0x28: /* 5430 */ case 0x2A: /* 5434 */ case 0x2B: /* 5436 */ case 0x2E: /* 5446 */ case 0x0E: /* 7548 */ break; default: outb(SEQ_I, 0x06); outb(SEQ_D, oldlockreg); return 0; } if (cirrus_init(0, 0, 0)) return 0; /* failure */ return 1;}/* Bank switching function -- set 64K page number */static void cirrus_setpage_2M(int page){ /* Cirrus banking register has been set to 16K granularity */ outw(GRA_I, (page << 10) + 0x09);}static void cirrus_setpage(int page){ /* default 4K granularity */ outw(GRA_I, (page << 12) + 0x09);}/* No r/w paging */static void cirrus_setrdpage(int page){}static void cirrus_setwrpage(int page){}/* Set display start address (not for 16 color modes) *//* Cirrus supports any address in video memory (up to 2Mb) */static void cirrus_setdisplaystart(int address){ outw(CRT_IC, 0x0d + ((address >> 2) & 0x00ff) * 256); /* sa2-sa9 */ outw(CRT_IC, 0x0c + ((address >> 2) & 0xff00)); /* sa10-sa17 */ inb(0x3da); /* set ATC to addressing mode */ outb(ATT_IW, 0x13 + 0x20); /* select ATC reg 0x13 */ /* Cirrus specific bits 0,1 and 18,19,20: */ outb(ATT_IW, (inb(ATT_R) & 0xf0) | (address & 3)); /* write sa0-1 to bits 0-1; other cards use bits 1-2 */ outb(CRT_IC, 0x1b); outb(CRT_DC, (inb(CRT_DC) & 0xf2) | ((address & 0x40000) >> 18) /* sa18: write to bit 0 */ |((address & 0x80000) >> 17) /* sa19: write to bit 2 */ |((address & 0x100000) >> 17)); /* sa20: write to bit 3 */ outb(CRT_IC, 0x1d); if (cirrus_memory > 2048) outb(CRT_DC, (inb(CRT_DC) & 0x7f) | ((address & 0x200000) >> 14)); /* sa21: write to bit 7 */}/* Set logical scanline length (usually multiple of 8) *//* Cirrus supports multiples of 8, up to 4088 */static void cirrus_setlogicalwidth(int width){ outw(CRT_IC, 0x13 + (width >> 3) * 256); /* lw3-lw11 */ outb(CRT_IC, 0x1b); outb(CRT_DC, (inb(CRT_DC) & 0xef) | ((width & 0x800) >> 7)); /* write lw12 to bit 4 of Sequencer reg. 0x1b */}static void cirrus_setlinear(int addr){ int val; outb(SEQ_I, 0x07); val = inb(SEQ_D); outb(SEQ_D, (val & 0x0f) | (addr << 4));}static int cirrus_linear(int op, int param){ if (op == LINEAR_ENABLE) { cirrus_setlinear(0xE); return 0; } if (op == LINEAR_DISABLE) { cirrus_setlinear(0); return 0; } if (cirrus_chiptype >= CLGD5424 && cirrus_chiptype <= CLGD5429) { if (op == LINEAR_QUERY_BASE) { if (param == 0) return 0xE00000; /* 14MB */ /* * Trying 64MB on a system with 16MB of memory is unsafe if the * card maps at 14MB. 14 MB was not attempted because of the * system memory check in vga_setlinearaddressing(). However, * linear addressing is enabled when looking at 64MB, causing a * clash between video card and system memory at 14MB. */ if (__svgalib_physmem() <= 13 * 1024 * 1024) { if (param == 1) return 0x4000000; /* 64MB */ if (param == 2) return 0x4E00000; /* 78MB */ if (param == 3) return 0x2000000; /* 32MB */ if (param == 4) return 0x3E00000; /* 62MB */ } return -1; } } if (cirrus_chiptype >= CLGD5430) { if (op == LINEAR_QUERY_BASE) { if(cirrus_pci_linear)return cirrus_pci_linear; if (param == 0) return 0x04000000; /* 64MB */ if (param == 1) return 0x80000000; /* 2048MB */ if (param == 2) return 0x02000000; /* 32MB */ if (param == 3) return 0x08000000; /* 128MB */ /* While we're busy, try some common PCI */ /* motherboard-configured addresses as well. */ /* We only read, so should be safe. */ if (param == 4) return 0xA0000000; if (param == 5) return 0xA8000000; if (param == 6) return 0xE0000000; if (param == 7) return 0XFE000000; /* * Some PCI/VL motherboards only seem to let the * VL slave slot respond at addresses >= 2048MB. */ if (param == 8) return 0x84000000; if (param == 9) return 0x88000000; return -1; } } if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) return 0; /* No granularity or range. */ else return -1; /* Unknown function. */}/* Function table (exported) */DriverSpecs __svgalib_cirrus_driverspecs ={ cirrus_saveregs, cirrus_setregs, cirrus_unlock, cirrus_lock, cirrus_test, cirrus_init, cirrus_setpage, cirrus_setrdpage, cirrus_setwrpage, cirrus_setmode, cirrus_modeavailable, cirrus_setdisplaystart, cirrus_setlogicalwidth, cirrus_getmodeinfo, 0, /* old blit funcs */ 0, 0, 0, 0, 0, /* ext_set */ 0, /* accel */ cirrus_linear, NULL, /* Accelspecs */ NULL, /* Emulation */};/* Initialize chipset (called after detection) */static char *cirrus_chipname[] ={ "5420", "7548", "5420-75QC-B", "5422", "5422-80QC-C", "5424", "5426", "5428", "5429", "5430", "5434", "5436"};static unsigned char fixedMCLK[4] ={0x1c, 0x19, 0x17, 0x15};static int cirrus_init(int force, int par1, int par2){ unsigned char v; cirrus_unlock(); if (force) { cirrus_memory = par1; cirrus_chiptype = par2; } else { unsigned char partstatus; outb(__svgalib_CRT_I, 0x27); cirrus_chiptype = inb(__svgalib_CRT_D) >> 2; cirrus_chiprev = 0; partstatus = __svgalib_inCR(0x25); switch (cirrus_chiptype) { case 0x22: cirrus_chiptype = CLGD5420;#if 0 /* Check for CL-GD5420-75QC-B. */ /* It has a Hidden-DAC register. */ outb(0x3C6, 0x00); outb(0x3C6, 0xFF); inb(0x3C6);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -