📄 stifb.c
字号:
static voidelkSetupPlanes(struct stifb_info *fb){ SETUP_RAMDAC(fb); SETUP_FB(fb);}static void ngleSetupAttrPlanes(struct stifb_info *fb, int BufferNumber){ SETUP_ATTR_ACCESS(fb, BufferNumber); SET_ATTR_SIZE(fb, fb->info.var.xres, fb->info.var.yres); FINISH_ATTR_ACCESS(fb); SETUP_FB(fb);}static voidrattlerSetupPlanes(struct stifb_info *fb){ CRX24_SETUP_RAMDAC(fb); /* replacement for: SETUP_FB(fb, CRX24_OVERLAY_PLANES); */ WRITE_WORD(0x83000300, fb, REG_14); SETUP_HW(fb); WRITE_BYTE(1, fb, REG_16b1); fb_memset(fb->info.fix.smem_start, 0xff, fb->info.var.yres*fb->info.fix.line_length); CRX24_SET_OVLY_MASK(fb); SETUP_FB(fb);}#define HYPER_CMAP_TYPE 0#define NGLE_CMAP_INDEXED0_TYPE 0#define NGLE_CMAP_OVERLAY_TYPE 3/* typedef of LUT (Colormap) BLT Control Register */typedef union /* Note assumption that fields are packed left-to-right */{ u32 all; struct { unsigned enable : 1; unsigned waitBlank : 1; unsigned reserved1 : 4; unsigned lutOffset : 10; /* Within destination LUT */ unsigned lutType : 2; /* Cursor, image, overlay */ unsigned reserved2 : 4; unsigned length : 10; } fields;} NgleLutBltCtl;#if 0static NgleLutBltCtlsetNgleLutBltCtl(struct stifb_info *fb, int offsetWithinLut, int length){ NgleLutBltCtl lutBltCtl; /* set enable, zero reserved fields */ lutBltCtl.all = 0x80000000; lutBltCtl.fields.length = length; switch (fb->id) { case S9000_ID_A1439A: /* CRX24 */ if (fb->var.bits_per_pixel == 8) { lutBltCtl.fields.lutType = NGLE_CMAP_OVERLAY_TYPE; lutBltCtl.fields.lutOffset = 0; } else { lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE; lutBltCtl.fields.lutOffset = 0 * 256; } break; case S9000_ID_ARTIST: lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE; lutBltCtl.fields.lutOffset = 0 * 256; break; default: lutBltCtl.fields.lutType = NGLE_CMAP_INDEXED0_TYPE; lutBltCtl.fields.lutOffset = 0; break; } /* Offset points to start of LUT. Adjust for within LUT */ lutBltCtl.fields.lutOffset += offsetWithinLut; return lutBltCtl;}#endifstatic NgleLutBltCtlsetHyperLutBltCtl(struct stifb_info *fb, int offsetWithinLut, int length) { NgleLutBltCtl lutBltCtl; /* set enable, zero reserved fields */ lutBltCtl.all = 0x80000000; lutBltCtl.fields.length = length; lutBltCtl.fields.lutType = HYPER_CMAP_TYPE; /* Expect lutIndex to be 0 or 1 for image cmaps, 2 or 3 for overlay cmaps */ if (fb->info.var.bits_per_pixel == 8) lutBltCtl.fields.lutOffset = 2 * 256; else lutBltCtl.fields.lutOffset = 0 * 256; /* Offset points to start of LUT. Adjust for within LUT */ lutBltCtl.fields.lutOffset += offsetWithinLut; return lutBltCtl;}static void hyperUndoITE(struct stifb_info *fb){ int nFreeFifoSlots = 0; u32 fbAddr; NGLE_LOCK(fb); GET_FIFO_SLOTS(fb, nFreeFifoSlots, 1); WRITE_WORD(0xffffffff, fb, REG_32); /* Write overlay transparency mask so only entry 255 is transparent */ /* Hardware setup for full-depth write to "magic" location */ GET_FIFO_SLOTS(fb, nFreeFifoSlots, 7); NGLE_QUICK_SET_DST_BM_ACCESS(fb, BA(IndexedDcd, Otc04, Ots08, AddrLong, BAJustPoint(0), BINovly, BAIndexBase(0))); NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb, IBOvals(RopSrc, MaskAddrOffset(0), BitmapExtent08, StaticReg(0), DataDynamic, MaskOtc, BGx(0), FGx(0))); /* Now prepare to write to the "magic" location */ fbAddr = NGLE_LONG_FB_ADDRESS(0, 1532, 0); NGLE_BINC_SET_DSTADDR(fb, fbAddr); NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, 0xffffff); NGLE_BINC_SET_DSTMASK(fb, 0xffffffff); /* Finally, write a zero to clear the mask */ NGLE_BINC_WRITE32(fb, 0); NGLE_UNLOCK(fb);}static void ngleDepth8_ClearImagePlanes(struct stifb_info *fb){ /* FIXME! */}static void ngleDepth24_ClearImagePlanes(struct stifb_info *fb){ /* FIXME! */}static voidngleResetAttrPlanes(struct stifb_info *fb, unsigned int ctlPlaneReg){ int nFreeFifoSlots = 0; u32 packed_dst; u32 packed_len; NGLE_LOCK(fb); GET_FIFO_SLOTS(fb, nFreeFifoSlots, 4); NGLE_QUICK_SET_DST_BM_ACCESS(fb, BA(IndexedDcd, Otc32, OtsIndirect, AddrLong, BAJustPoint(0), BINattr, BAIndexBase(0))); NGLE_QUICK_SET_CTL_PLN_REG(fb, ctlPlaneReg); NGLE_SET_TRANSFERDATA(fb, 0xffffffff); NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb, IBOvals(RopSrc, MaskAddrOffset(0), BitmapExtent08, StaticReg(1), DataDynamic, MaskOtc, BGx(0), FGx(0))); packed_dst = 0; packed_len = (fb->info.var.xres << 16) | fb->info.var.yres; GET_FIFO_SLOTS(fb, nFreeFifoSlots, 2); NGLE_SET_DSTXY(fb, packed_dst); SET_LENXY_START_RECFILL(fb, packed_len); /* * In order to work around an ELK hardware problem (Buffy doesn't * always flush it's buffers when writing to the attribute * planes), at least 4 pixels must be written to the attribute * planes starting at (X == 1280) and (Y != to the last Y written * by BIF): */ if (fb->id == S9000_ID_A1659A) { /* ELK_DEVICE_ID */ /* It's safe to use scanline zero: */ packed_dst = (1280 << 16); GET_FIFO_SLOTS(fb, nFreeFifoSlots, 2); NGLE_SET_DSTXY(fb, packed_dst); packed_len = (4 << 16) | 1; SET_LENXY_START_RECFILL(fb, packed_len); } /* ELK Hardware Kludge */ /**** Finally, set the Control Plane Register back to zero: ****/ GET_FIFO_SLOTS(fb, nFreeFifoSlots, 1); NGLE_QUICK_SET_CTL_PLN_REG(fb, 0); NGLE_UNLOCK(fb);} static voidngleClearOverlayPlanes(struct stifb_info *fb, int mask, int data){ int nFreeFifoSlots = 0; u32 packed_dst; u32 packed_len; NGLE_LOCK(fb); /* Hardware setup */ GET_FIFO_SLOTS(fb, nFreeFifoSlots, 8); NGLE_QUICK_SET_DST_BM_ACCESS(fb, BA(IndexedDcd, Otc04, Ots08, AddrLong, BAJustPoint(0), BINovly, BAIndexBase(0))); NGLE_SET_TRANSFERDATA(fb, 0xffffffff); /* Write foreground color */ NGLE_REALLY_SET_IMAGE_FG_COLOR(fb, data); NGLE_REALLY_SET_IMAGE_PLANEMASK(fb, mask); packed_dst = 0; packed_len = (fb->info.var.xres << 16) | fb->info.var.yres; NGLE_SET_DSTXY(fb, packed_dst); /* Write zeroes to overlay planes */ NGLE_QUICK_SET_IMAGE_BITMAP_OP(fb, IBOvals(RopSrc, MaskAddrOffset(0), BitmapExtent08, StaticReg(0), DataDynamic, MaskOtc, BGx(0), FGx(0))); SET_LENXY_START_RECFILL(fb, packed_len); NGLE_UNLOCK(fb);}static void hyperResetPlanes(struct stifb_info *fb, int enable){ unsigned int controlPlaneReg; NGLE_LOCK(fb); if (IS_24_DEVICE(fb)) if (fb->info.var.bits_per_pixel == 32) controlPlaneReg = 0x04000F00; else controlPlaneReg = 0x00000F00; /* 0x00000800 should be enought, but lets clear all 4 bits */ else controlPlaneReg = 0x00000F00; /* 0x00000100 should be enought, but lets clear all 4 bits */ switch (enable) { case ENABLE: /* clear screen */ if (IS_24_DEVICE(fb)) ngleDepth24_ClearImagePlanes(fb); else ngleDepth8_ClearImagePlanes(fb); /* Paint attribute planes for default case. * On Hyperdrive, this means all windows using overlay cmap 0. */ ngleResetAttrPlanes(fb, controlPlaneReg); /* clear overlay planes */ ngleClearOverlayPlanes(fb, 0xff, 255); /************************************************** ** Also need to counteract ITE settings **************************************************/ hyperUndoITE(fb); break; case DISABLE: /* clear screen */ if (IS_24_DEVICE(fb)) ngleDepth24_ClearImagePlanes(fb); else ngleDepth8_ClearImagePlanes(fb); ngleResetAttrPlanes(fb, controlPlaneReg); ngleClearOverlayPlanes(fb, 0xff, 0); break; case -1: /* RESET */ hyperUndoITE(fb); ngleResetAttrPlanes(fb, controlPlaneReg); break; } NGLE_UNLOCK(fb);}/* Return pointer to in-memory structure holding ELK device-dependent ROM values. */static void ngleGetDeviceRomData(struct stifb_info *fb){#if 0XXX: FIXME: !!! int *pBytePerLongDevDepData;/* data byte == LSB */ int *pRomTable; NgleDevRomData *pPackedDevRomData; int sizePackedDevRomData = sizeof(*pPackedDevRomData); char *pCard8; int i; char *mapOrigin = NULL; int romTableIdx; pPackedDevRomData = fb->ngle_rom; SETUP_HW(fb); if (fb->id == S9000_ID_ARTIST) { pPackedDevRomData->cursor_pipeline_delay = 4; pPackedDevRomData->video_interleaves = 4; } else { /* Get pointer to unpacked byte/long data in ROM */ pBytePerLongDevDepData = fb->sti->regions[NGLEDEVDEPROM_CRT_REGION]; /* Tomcat supports several resolutions: 1280x1024, 1024x768, 640x480 */ if (fb->id == S9000_ID_TOMCAT) { /* jump to the correct ROM table */ GET_ROMTABLE_INDEX(romTableIdx); while (romTableIdx > 0) { pCard8 = (Card8 *) pPackedDevRomData; pRomTable = pBytePerLongDevDepData; /* Pack every fourth byte from ROM into structure */ for (i = 0; i < sizePackedDevRomData; i++) { *pCard8++ = (Card8) (*pRomTable++); } pBytePerLongDevDepData = (Card32 *) ((Card8 *) pBytePerLongDevDepData + pPackedDevRomData->sizeof_ngle_data); romTableIdx--; } } pCard8 = (Card8 *) pPackedDevRomData; /* Pack every fourth byte from ROM into structure */ for (i = 0; i < sizePackedDevRomData; i++) { *pCard8++ = (Card8) (*pBytePerLongDevDepData++); } } SETUP_FB(fb);#endif}#define HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES 4#define HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE 8#define HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE 10#define HYPERBOWL_MODE2_8_24 15/* HCRX specific boot-time initialization */static void __initSETUP_HCRX(struct stifb_info *fb){ int hyperbowl; int nFreeFifoSlots = 0; if (fb->id != S9000_ID_HCRX) return; /* Initialize Hyperbowl registers */ GET_FIFO_SLOTS(fb, nFreeFifoSlots, 7); if (IS_24_DEVICE(fb)) { hyperbowl = (fb->info.var.bits_per_pixel == 32) ? HYPERBOWL_MODE01_8_24_LUT0_TRANSPARENT_LUT1_OPAQUE : HYPERBOWL_MODE01_8_24_LUT0_OPAQUE_LUT1_OPAQUE; /* First write to Hyperbowl must happen twice (bug) */ WRITE_WORD(hyperbowl, fb, REG_40); WRITE_WORD(hyperbowl, fb, REG_40); WRITE_WORD(HYPERBOWL_MODE2_8_24, fb, REG_39); WRITE_WORD(0x014c0148, fb, REG_42); /* Set lut 0 to be the direct color */ WRITE_WORD(0x404c4048, fb, REG_43); WRITE_WORD(0x034c0348, fb, REG_44); WRITE_WORD(0x444c4448, fb, REG_45); } else { hyperbowl = HYPERBOWL_MODE_FOR_8_OVER_88_LUT0_NO_TRANSPARENCIES; /* First write to Hyperbowl must happen twice (bug) */ WRITE_WORD(hyperbowl, fb, REG_40); WRITE_WORD(hyperbowl, fb, REG_40); WRITE_WORD(0x00000000, fb, REG_42); WRITE_WORD(0x00000000, fb, REG_43); WRITE_WORD(0x00000000, fb, REG_44); WRITE_WORD(0x444c4048, fb, REG_45); }}/* ------------------- driver specific functions --------------------------- */#define TMPBUFLEN 2048static ssize_tstifb_read(struct file *file, char *buf, size_t count, loff_t *ppos){ unsigned long p = *ppos; struct inode *inode = file->f_dentry->d_inode; int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; char tmpbuf[TMPBUFLEN]; if (!info || ! info->screen_base) return -ENODEV; if (p >= info->fix.smem_len) return 0; if (count >= info->fix.smem_len) count = info->fix.smem_len; if (count + p > info->fix.smem_len) count = info->fix.smem_len - p; if (count > sizeof(tmpbuf)) count = sizeof(tmpbuf); if (count) { char *base_addr; base_addr = info->screen_base; memcpy_fromio(&tmpbuf, base_addr+p, count); count -= copy_to_user(buf, &tmpbuf, count); if (!count) return -EFAULT; *ppos += count; } return count;}static ssize_tstifb_write(struct file *file, const char *buf, size_t count, loff_t *ppos){ struct inode *inode = file->f_dentry->d_inode; int fbidx = iminor(inode); struct fb_info *info = registered_fb[fbidx]; unsigned long p = *ppos; size_t c; int err; char tmpbuf[TMPBUFLEN]; if (!info || !info->screen_base) return -ENODEV; if (p > info->fix.smem_len) return -ENOSPC; if (count >= info->fix.smem_len) count = info->fix.smem_len; err = 0; if (count + p > info->fix.smem_len) { count = info->fix.smem_len - p; err = -ENOSPC; } p += (unsigned long)info->screen_base; c = count; while (c) { int len = c > sizeof(tmpbuf) ? sizeof(tmpbuf) : c; err = -EFAULT; if (copy_from_user(&tmpbuf, buf, len)) break; memcpy_toio(p, &tmpbuf, len); c -= len; p += len; buf += len; *ppos += len;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -