⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sticore.c

📁 linux下的VIDEO接口驱动程序
💻 C
字号:
#include <linux/module.h>#include <linux/types.h>#include <linux/kernel.h>#include <linux/slab.h>#include <linux/init.h>#include <asm/uaccess.h>#include <asm/pgalloc.h>#include <asm/io.h>#include "sti.h"struct sti_struct default_sti = {	SPIN_LOCK_UNLOCKED,};static struct sti_font_flags default_font_flags = {	STI_WAIT, 0, 0, NULL};/* The colour indices used by STI are *   0 - Black *   1 - White *   2 - Red *   3 - Yellow/Brown *   4 - Green *   5 - Cyan *   6 - Blue *   7 - Magenta * * So we have the same colours as VGA (basically one bit each for R, G, B), * but have to translate them, anyway. */static u8 col_trans[8] = {        0, 6, 4, 5,        2, 7, 3, 1};#define c_fg(sti, c) col_trans[((c>> 8) & 7)]#define c_bg(sti, c) col_trans[((c>>11) & 7)]#define c_index(sti, c) (c&0xff)static struct sti_init_flags default_init_flags = {	STI_WAIT, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, NULL};voidsti_init_graph(struct sti_struct *sti) {	struct sti_init_inptr_ext inptr_ext = {		0, { 0 }, 0, NULL	};	struct sti_init_inptr inptr = {		3, STI_PTR(&inptr_ext)	};	struct sti_init_outptr outptr = { 0 };	unsigned long flags;	s32 ret;	spin_lock_irqsave(&sti->lock, flags);	ret = STI_CALL(sti->init_graph, &default_init_flags, &inptr,		&outptr, sti->glob_cfg);	spin_unlock_irqrestore(&sti->lock, flags);	sti->text_planes = outptr.text_planes;}static struct sti_conf_flags default_conf_flags = {	STI_WAIT, 0, NULL};voidsti_inq_conf(struct sti_struct *sti){	struct sti_conf_inptr inptr = { NULL };	struct sti_conf_outptr_ext outptr_ext = { future_ptr: NULL };	struct sti_conf_outptr outptr = {		ext_ptr: STI_PTR(&outptr_ext)	};	unsigned long flags;	s32 ret;		do {		spin_lock_irqsave(&sti->lock, flags);		ret = STI_CALL(sti->inq_conf, &default_conf_flags,			&inptr, &outptr, sti->glob_cfg);		spin_unlock_irqrestore(&sti->lock, flags);	} while(ret == 1);}voidsti_putc(struct sti_struct *sti, int c, int y, int x){	struct sti_font_inptr inptr = {		(u32) sti->font, c_index(sti, c), c_fg(sti, c), c_bg(sti, c),		x * sti_font_x(sti), y * sti_font_y(sti), NULL	};	struct sti_font_outptr outptr = {		0, NULL	};	s32 ret;	unsigned long flags;	do {		spin_lock_irqsave(&sti->lock, flags);		ret = STI_CALL(sti->font_unpmv, &default_font_flags,			&inptr, &outptr, sti->glob_cfg);		spin_unlock_irqrestore(&sti->lock, flags);	} while(ret == 1);}static struct sti_blkmv_flags clear_blkmv_flags = {	STI_WAIT, 1, 1, 0, 0, NULL};voidsti_set(struct sti_struct *sti, int src_y, int src_x,	int height, int width, u8 color){	struct sti_blkmv_inptr inptr = {		color, color,		src_x, src_y ,		src_x, src_y ,		width, height,		NULL	};	struct sti_blkmv_outptr outptr = { 0, NULL };	s32 ret = 0;	unsigned long flags;		do {		spin_lock_irqsave(&sti->lock, flags);		ret = STI_CALL(sti->block_move, &clear_blkmv_flags,			&inptr, &outptr, sti->glob_cfg);		spin_unlock_irqrestore(&sti->lock, flags);	} while(ret == 1);}voidsti_clear(struct sti_struct *sti, int src_y, int src_x,	  int height, int width){	struct sti_blkmv_inptr inptr = {		0, 0,		src_x * sti_font_x(sti), src_y * sti_font_y(sti),		src_x * sti_font_x(sti), src_y * sti_font_y(sti),		width * sti_font_x(sti), height* sti_font_y(sti),		NULL	};	struct sti_blkmv_outptr outptr = { 0, NULL };	s32 ret = 0;	unsigned long flags;	do {		spin_lock_irqsave(&sti->lock, flags);		ret = STI_CALL(sti->block_move, &clear_blkmv_flags,			&inptr, &outptr, sti->glob_cfg);		spin_unlock_irqrestore(&sti->lock, flags);	} while(ret == 1);}static struct sti_blkmv_flags default_blkmv_flags = {	STI_WAIT, 0, 0, 0, 0, NULL};voidsti_bmove(struct sti_struct *sti, int src_y, int src_x,	  int dst_y, int dst_x, int height, int width){	struct sti_blkmv_inptr inptr = {		0, 0,		src_x * sti_font_x(sti), src_y * sti_font_y(sti),		dst_x * sti_font_x(sti), dst_y * sti_font_y(sti),		width * sti_font_x(sti), height* sti_font_y(sti),		NULL	};	struct sti_blkmv_outptr outptr = { 0, NULL };	s32 ret = 0;	unsigned long flags;	do {		spin_lock_irqsave(&sti->lock, flags);		ret = STI_CALL(sti->block_move, &default_blkmv_flags,			&inptr, &outptr, sti->glob_cfg);		spin_unlock_irqrestore(&sti->lock, flags);	} while(ret == 1);}static void __initsti_rom_copy(unsigned long base, unsigned long offset,	     unsigned long count, void *dest){	void *savedest = dest;	int savecount = count;	while(count >= 4) {		count -= 4;		*(u32 *)dest = gsc_readl(base + offset);		offset += 4;		dest += 4;	}	while(count) {		count--;		*(u8 *)dest = gsc_readb(base + offset);		offset++;		dest++;	}	flush_kernel_dcache_range((unsigned long)dest, count);	flush_icache_range((unsigned long)dest, dest + count);}static void dump_sti_rom(struct sti_rom *rom){	printk("STI word mode ROM type %d\n", rom->type[3]);	printk(" supports %d monitors\n", rom->num_mons);	printk(" conforms to STI ROM spec revision %d.%02x\n",		rom->revno[0] >> 4, rom->revno[0] & 0x0f);	printk(" graphics id %02x%02x%02x%02x%02x%02x%02x%02x\n",		rom->graphics_id[0], 		rom->graphics_id[1], 		rom->graphics_id[2], 		rom->graphics_id[3], 		rom->graphics_id[4], 		rom->graphics_id[5], 		rom->graphics_id[6], 		rom->graphics_id[7]);	printk(" font start %08x\n", rom->font_start);	printk(" region list %08x\n", rom->region_list);	printk(" init_graph %08x\n", rom->init_graph);	printk(" alternate code type %d\n", rom->alt_code_type);}static void __init sti_cook_fonts(struct sti_cooked_rom *cooked_rom,				  struct sti_rom *raw_rom){	struct sti_rom_font *raw_font;	struct sti_cooked_font *cooked_font;	struct sti_rom_font *font_start;		cooked_font =		kmalloc(sizeof *cooked_font, GFP_KERNEL);	if(!cooked_font)		return;	cooked_rom->font_start = cooked_font;	raw_font = ((void *)raw_rom) + (raw_rom->font_start);	font_start = raw_font;	cooked_font->raw = raw_font;	while(raw_font->next_font) {		raw_font = ((void *)font_start) + (raw_font->next_font);				cooked_font->next_font =			kmalloc(sizeof *cooked_font, GFP_KERNEL);		if(!cooked_font->next_font)			return;		cooked_font = cooked_font->next_font;		cooked_font->raw = raw_font;	}	cooked_font->next_font = NULL;}static int font_index, font_height, font_width;static int __init sti_font_setup(char *str){	char *x;	/* we accept sti_font=10x20, sti_font=10*20 or sti_font=7 style	 * command lines. */	if((x = strchr(str, 'x')) || (x = strchr(str, '*'))) {		font_height = simple_strtoul(str, NULL, 0);		font_width = simple_strtoul(x+1, NULL, 0);	} else {		font_index = simple_strtoul(str, NULL, 0);	}	return 0;}__setup("sti_font=", sti_font_setup);static int __init sti_search_font(struct sti_cooked_rom *rom,				  int height, int width){	struct sti_cooked_font *font;	int i = 0;		for(font = rom->font_start; font; font = font->next_font, i++) {		if((font->raw->width == width) && (font->raw->height == height))			return i;	}	return 0;}static struct sti_cooked_font * __initsti_select_font(struct sti_cooked_rom *rom){	struct sti_cooked_font *font;	int i;	if(font_width && font_height)		font_index = sti_search_font(rom, font_height, font_width);	for(font = rom->font_start, i = font_index;	    font && (i > 0);	    font = font->next_font, i--);	if(font)		return font;	else		return rom->font_start;}	static void __initsti_dump_globcfg_ext(struct sti_glob_cfg_ext *cfg){	printk(	"monitor %d\n"		"in friendly mode: %d\n"		"power consumption %d watts\n"		"freq ref %d\n"		"sti_mem_addr %p\n",		cfg->curr_mon,		cfg->friendly_boot,		cfg->power,		cfg->freq_ref,		cfg->sti_mem_addr);}void __initsti_dump_globcfg(struct sti_glob_cfg *glob_cfg){	printk(	"%d text planes\n"		"%4d x %4d screen resolution\n"		"%4d x %4d offscreen\n"		"%4d x %4d layout\n"		"regions at %08x %08x %08x %08x\n"		"regions at %08x %08x %08x %08x\n"		"reent_lvl %d\n"		"save_addr %p\n",		glob_cfg->text_planes,		glob_cfg->onscreen_x, glob_cfg->onscreen_y,		glob_cfg->offscreen_x, glob_cfg->offscreen_y,		glob_cfg->total_x, glob_cfg->total_y,		glob_cfg->region_ptrs[0], glob_cfg->region_ptrs[1],		glob_cfg->region_ptrs[2], glob_cfg->region_ptrs[3],		glob_cfg->region_ptrs[4], glob_cfg->region_ptrs[5],		glob_cfg->region_ptrs[6], glob_cfg->region_ptrs[7],		glob_cfg->reent_lvl,		glob_cfg->save_addr);	sti_dump_globcfg_ext(PTR_STI(glob_cfg->ext_ptr));}		static void __initsti_init_glob_cfg(struct sti_struct *sti, unsigned long hpa,		  unsigned long rom_address){	struct sti_glob_cfg *glob_cfg;	struct sti_glob_cfg_ext *glob_cfg_ext;	void *save_addr;	void *sti_mem_addr;	glob_cfg = kmalloc(sizeof *sti->glob_cfg, GFP_KERNEL);	glob_cfg_ext = kmalloc(sizeof *glob_cfg_ext, GFP_KERNEL);	save_addr = kmalloc(1024 /*XXX*/, GFP_KERNEL);	sti_mem_addr = kmalloc(1024, GFP_KERNEL);	if((!glob_cfg) || (!glob_cfg_ext) || (!save_addr) || (!sti_mem_addr))		return;	memset(glob_cfg, 0, sizeof *glob_cfg);	memset(glob_cfg_ext, 0, sizeof *glob_cfg_ext);	memset(save_addr, 0, 1024);	memset(sti_mem_addr, 0, 1024);	glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext);	glob_cfg->save_addr = STI_PTR(save_addr);	glob_cfg->region_ptrs[0] = ((sti->regions[0]>>18)<<12) + rom_address;	glob_cfg->region_ptrs[1] = ((sti->regions[1]>>18)<<12) + hpa;	glob_cfg->region_ptrs[2] = ((sti->regions[2]>>18)<<12) + hpa;	glob_cfg->region_ptrs[3] = ((sti->regions[3]>>18)<<12) + hpa;	glob_cfg->region_ptrs[4] = ((sti->regions[4]>>18)<<12) + hpa;	glob_cfg->region_ptrs[5] = ((sti->regions[5]>>18)<<12) + hpa;	glob_cfg->region_ptrs[6] = ((sti->regions[6]>>18)<<12) + hpa;	glob_cfg->region_ptrs[7] = ((sti->regions[7]>>18)<<12) + hpa;		glob_cfg_ext->sti_mem_addr = STI_PTR(sti_mem_addr);	sti->glob_cfg = STI_PTR(glob_cfg);}/* address is a pointer to a word mode or pci rom */static struct sti_struct * __initsti_read_rom(unsigned long address){	struct sti_struct *ret = NULL;	struct sti_cooked_rom *cooked = NULL;	struct sti_rom *raw = NULL;	unsigned long size;	ret = &default_sti;	if(!ret)		goto out_err;	cooked = kmalloc(sizeof *cooked, GFP_KERNEL);	raw = kmalloc(sizeof *raw, GFP_KERNEL);		if(!(raw && cooked))		goto out_err;	/* reallocate raw */	sti_rom_copy(address, 0, sizeof *raw, raw);	dump_sti_rom(raw);	size = raw->last_addr;	/* kfree(raw); */	raw = kmalloc(size, GFP_KERNEL);	if(!raw)		goto out_err;	sti_rom_copy(address, 0, size, raw);	sti_cook_fonts(cooked, raw);#if 0	sti_cook_regions(cooked, raw);	sti_cook_functions(cooked, raw);#endif	if(raw->region_list) {		ret->regions = kmalloc(32, GFP_KERNEL);	/* FIXME */		memcpy(ret->regions, ((void *)raw)+raw->region_list, 32);	}	address = virt_to_phys(raw);	ret->font_unpmv = address+(raw->font_unpmv & 0x03ffffff);	ret->block_move = address+(raw->block_move & 0x03ffffff);	ret->init_graph = address+(raw->init_graph & 0x03ffffff);	ret->inq_conf = address+(raw->inq_conf     & 0x03ffffff);	ret->rom = cooked;	ret->rom->raw = raw;	ret->font = (struct sti_rom_font *) virt_to_phys(sti_select_font(ret->rom)->raw);	return ret;out_err:	if(raw)		kfree(raw);	if(cooked)		kfree(cooked);	return NULL;}static struct sti_struct * __initsti_try_rom(unsigned long address, unsigned long hpa){	struct sti_struct *sti = NULL;	u16 sig;	test_rom:	/* if we can't read the ROM, bail out early.  Not being able	 * to read the hpa is okay, for romless sti */	if(pdc_add_valid((void*)address))		return NULL;	printk("found potential STI ROM at %08lx\n", address);	sig = le16_to_cpu(gsc_readw(address));	if((sig==0x55aa) || (sig==0xaa55)) {		address += le32_to_cpu(gsc_readl(address+8));		printk("sig %04x, PCI STI ROM at %08lx\n",		       sig, address);		goto test_rom;	}	if((sig&0xff) == 0x01) {		printk("STI byte mode ROM at %08lx, ignored\n",		       address);		sti = NULL;	}	if(sig == 0x0303) {		printk("STI word mode ROM at %08lx\n",		       address);		sti = sti_read_rom(address);	}	if (!sti)		return NULL;	/* this is hacked.  We need a better way to find out the HPA for	 * romless STI (eg search for the graphics devices we know about	 * by sversion) */	if (!pdc_add_valid((void *)0xf5000000)) printk("f4000000 g\n");	if (!pdc_add_valid((void *)0xf7000000)) printk("f6000000 g\n");	if (!pdc_add_valid((void *)0xf9000000)) printk("f8000000 g\n");	if (!pdc_add_valid((void *)0xfb000000)) printk("fa000000 g\n");	sti_init_glob_cfg(sti, hpa, address);	sti_init_graph(sti);	sti_inq_conf(sti);	sti_dump_globcfg(PTR_STI(sti->glob_cfg));	return sti;}static unsigned long sti_address;static unsigned long sti_hpa;/* XXX: should build a list of STI ROMs */struct sti_struct * __initsti_init_roms(void){	struct sti_struct *tmp = NULL, *sti = NULL;	/* handle the command line */	if (sti_address && sti_hpa) {		return sti_try_rom(sti_address, sti_hpa);	}	/* 712, 715, some other boxes don't have a separate STI ROM,	 * but use part of the regular flash */	if (PAGE0->proc_sti) {		printk("STI ROM from PDC at %08x\n", PAGE0->proc_sti);		if (!pdc_add_valid((void *)0xf9000000))			sti = sti_try_rom(PAGE0->proc_sti, 0xf8000000);		else if (!pdc_add_valid((void *)0xf5000000))			sti = sti_try_rom(PAGE0->proc_sti, 0xf4000000);		else if (!pdc_add_valid((void *)0xf7000000))			sti = sti_try_rom(PAGE0->proc_sti, 0xf6000000);		else if (!pdc_add_valid((void *)0xfb000000))			sti = sti_try_rom(PAGE0->proc_sti, 0xfa000000);	}	/* standard locations for GSC graphic devices */	if (!pdc_add_valid((void *)0xf4000000))		tmp = sti_try_rom(0xf4000000, 0xf4000000);	sti = tmp ? tmp : sti;	if (!pdc_add_valid((void *)0xf6000000))		tmp = sti_try_rom(0xf6000000, 0xf6000000);	sti = tmp ? tmp : sti;	if (!pdc_add_valid((void *)0xf8000000))		tmp = sti_try_rom(0xf8000000, 0xf8000000);	sti = tmp ? tmp : sti;	if (!pdc_add_valid((void *)0xfa000000))		tmp = sti_try_rom(0xfa000000, 0xfa000000);	sti = tmp ? tmp : sti;	return sti;}static int __initsti_setup(char *str){	char *end;	if(strcmp(str, "pdc") == 0) {		sti_address = PAGE0->proc_sti;		return 1;	} else {		sti_address = simple_strtoul(str, &end, 16);		if((end == str) || (sti_address < 0xf0000000)) {			sti_address = 0;			return 0;		}		sti_hpa = sti_address;		return 1;	}	return 0;}__setup("sti=", sti_setup);MODULE_LICENSE("GPL");

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -