📄 sticore.c
字号:
dest = nf; dest += sizeof(struct sti_rom_font); memcpy(dest, fbfont->data, bpc*256); cooked_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL); if (!cooked_font) { kfree(nf); return NULL; } cooked_font->raw = nf; cooked_font->next_font = NULL; cooked_rom->font_start = cooked_font; return cooked_font;}#elsestruct sti_cooked_font * __initsti_select_fbfont(struct sti_cooked_rom *cooked_rom, char *fbfont_name){ return NULL;}#endifstruct sti_cooked_font * __initsti_select_font(struct sti_cooked_rom *rom, int (*search_font_fnc) (struct sti_cooked_rom *,int,int) ){ struct sti_cooked_font *font; int i; int index = num_sti_roms; /* check for framebuffer-font first */ if ((font = sti_select_fbfont(rom, font_name[index]))) return font; if (font_width[index] && font_height[index]) font_index[index] = search_font_fnc(rom, font_height[index], font_width[index]); for (font = rom->font_start, i = font_index[index]; font && (i > 0); font = font->next_font, i--); if (font) return font; else return rom->font_start;}static void __init sti_dump_rom(struct sti_rom *rom){ printk(KERN_INFO " id %04x-%04x, conforms to spec rev. %d.%02x\n", rom->graphics_id[0], rom->graphics_id[1], rom->revno[0] >> 4, rom->revno[0] & 0x0f); DPRINTK((" supports %d monitors\n", rom->num_mons)); DPRINTK((" font start %08x\n", rom->font_start)); DPRINTK((" region list %08x\n", rom->region_list)); DPRINTK((" init_graph %08x\n", rom->init_graph)); DPRINTK((" bus support %02x\n", rom->bus_support)); DPRINTK((" ext bus support %02x\n", rom->ext_bus_support)); DPRINTK((" alternate code type %d\n", rom->alt_code_type));}static int __init sti_cook_fonts(struct sti_cooked_rom *cooked_rom, struct sti_rom *raw_rom){ struct sti_rom_font *raw_font, *font_start; struct sti_cooked_font *cooked_font; cooked_font = kmalloc(sizeof(*cooked_font), GFP_KERNEL); if (!cooked_font) return 0; 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 1; cooked_font = cooked_font->next_font; cooked_font->raw = raw_font; } cooked_font->next_font = NULL; return 1;}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;}#define BMODE_RELOCATE(offset) offset = (offset) / 4;#define BMODE_LAST_ADDR_OFFS 0x50static void * __initsti_bmode_font_raw(struct sti_cooked_font *f){ unsigned char *n, *p, *q; int size = f->raw->bytes_per_char*256+sizeof(struct sti_rom_font); n = kmalloc (4*size, GFP_KERNEL); if (!n) return NULL; memset (n, 0, 4*size); p = n + 3; q = (unsigned char *)f->raw; while (size--) { *p = *q++; p+=4; } return n + 3;}static void __initsti_bmode_rom_copy(unsigned long base, unsigned long count, void *dest){ unsigned long dest_len = count; unsigned long dest_start = (unsigned long) dest; while (count) { count--; *(u8 *)dest = gsc_readl(base); base += 4; dest++; } sti_flush(dest_start, dest_len);}static struct sti_rom * __initsti_get_bmode_rom (unsigned long address){ struct sti_rom *raw; u32 size; struct sti_rom_font *raw_font, *font_start; sti_bmode_rom_copy(address + BMODE_LAST_ADDR_OFFS, sizeof(size), &size); size = (size+3) / 4; raw = kmalloc(size, GFP_KERNEL); if (raw) { sti_bmode_rom_copy(address, size, raw); memmove (&raw->res004, &raw->type[0], 0x3c); raw->type[3] = raw->res004; BMODE_RELOCATE (raw->region_list); BMODE_RELOCATE (raw->font_start); BMODE_RELOCATE (raw->init_graph); BMODE_RELOCATE (raw->state_mgmt); BMODE_RELOCATE (raw->font_unpmv); BMODE_RELOCATE (raw->block_move); BMODE_RELOCATE (raw->inq_conf); raw_font = ((void *)raw) + raw->font_start; font_start = raw_font; while (raw_font->next_font) { BMODE_RELOCATE (raw_font->next_font); raw_font = ((void *)font_start) + raw_font->next_font; } } return raw;}struct sti_rom * __initsti_get_wmode_rom (unsigned long address){ struct sti_rom *raw; unsigned long size; /* read the ROM size directly from the struct in ROM */ size = gsc_readl(address + offsetof(struct sti_rom,last_addr)); raw = kmalloc(size, GFP_KERNEL); if (raw) sti_rom_copy(address, size, raw); return raw;}int __initsti_read_rom(int wordmode, struct sti_struct *sti, unsigned long address){ struct sti_cooked_rom *cooked; struct sti_rom *raw = NULL; cooked = kmalloc(sizeof *cooked, GFP_KERNEL); if (!cooked) goto out_err; if (wordmode) raw = sti_get_wmode_rom (address); else raw = sti_get_bmode_rom (address); if (!raw) goto out_err; if (!sti_cook_fonts(cooked, raw)) { printk(KERN_ERR "No font found for STI at %08lx\n", address); goto out_err; } if (raw->region_list) memcpy(sti->regions, ((void *)raw)+raw->region_list, sizeof(sti->regions)); address = (unsigned long) STI_PTR(raw); sti->font_unpmv = address + (raw->font_unpmv & 0x03ffffff); sti->block_move = address + (raw->block_move & 0x03ffffff); sti->init_graph = address + (raw->init_graph & 0x03ffffff); sti->inq_conf = address + (raw->inq_conf & 0x03ffffff); sti->rom = cooked; sti->rom->raw = raw; sti->font = sti_select_font(sti->rom, sti_search_font); sti->font_width = sti->font->raw->width; sti->font_height = sti->font->raw->height; if (!wordmode) sti->font->raw = sti_bmode_font_raw(sti->font); sti->sti_mem_request = raw->sti_mem_req; sti->graphics_id[0] = raw->graphics_id[0]; sti->graphics_id[1] = raw->graphics_id[1]; sti_dump_rom(raw); return 1;out_err: kfree(raw); kfree(cooked); return 0;}static struct sti_struct * __initsti_try_rom_generic(unsigned long address, unsigned long hpa, struct pci_dev *pd){ struct sti_struct *sti; int ok; u32 sig; if (num_sti_roms >= MAX_STI_ROMS) { printk(KERN_WARNING "maximum number of STI ROMS reached !\n"); return NULL; } sti = kmalloc(sizeof(*sti), GFP_KERNEL); if (!sti) { printk(KERN_ERR "Not enough memory !\n"); return NULL; } memset(sti, 0, sizeof(*sti)); spin_lock_init(&sti->lock);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(address)) goto out_err; sig = gsc_readl(address); /* check for a PCI ROM structure */ if ((le32_to_cpu(sig)==0xaa55)) { unsigned int i, rm_offset; u32 *rm; i = gsc_readl(address+0x04); if (i != 1) { /* The ROM could have multiple architecture * dependent images (e.g. i386, parisc,...) */ printk(KERN_WARNING "PCI ROM is not a STI ROM type image (0x%8x)\n", i); goto out_err; } sti->pd = pd; i = gsc_readl(address+0x0c); DPRINTK(("PCI ROM size (from header) = %d kB\n", le16_to_cpu(i>>16)*512/1024)); rm_offset = le16_to_cpu(i & 0xffff); if (rm_offset) { /* read 16 bytes from the pci region mapper array */ rm = (u32*) &sti->rm_entry; *rm++ = gsc_readl(address+rm_offset+0x00); *rm++ = gsc_readl(address+rm_offset+0x04); *rm++ = gsc_readl(address+rm_offset+0x08); *rm++ = gsc_readl(address+rm_offset+0x0c); DPRINTK(("PCI region Mapper offset = %08x: ", rm_offset)); for (i=0; i<16; i++) DPRINTK(("%02x ", sti->rm_entry[i])); DPRINTK(("\n")); } address += le32_to_cpu(gsc_readl(address+8)); DPRINTK(("sig %04x, PCI STI ROM at %08lx\n", sig, address)); goto test_rom; } ok = 0; if ((sig & 0xff) == 0x01) { DPRINTK((" byte mode ROM at %08lx, hpa at %08lx\n", address, hpa)); ok = sti_read_rom(0, sti, address); } if ((sig & 0xffff) == 0x0303) { DPRINTK((" word mode ROM at %08lx, hpa at %08lx\n", address, hpa)); ok = sti_read_rom(1, sti, address); } if (!ok) goto out_err; if (sti_init_glob_cfg(sti, address, hpa)) goto out_err; /* not enough memory */ /* disable STI PCI ROM. ROM and card RAM overlap and * leaving it enabled would force HPMCs */ if (sti->pd) { unsigned long rom_base; rom_base = pci_resource_start(sti->pd, PCI_ROM_RESOURCE); pci_write_config_dword(sti->pd, PCI_ROM_ADDRESS, rom_base & ~PCI_ROM_ADDRESS_ENABLE); DPRINTK((KERN_DEBUG "STI PCI ROM disabled\n")); } if (sti_init_graph(sti)) goto out_err; sti_inq_conf(sti); sti_dump_globcfg(sti->glob_cfg, sti->sti_mem_request); sti_dump_outptr(sti); printk(KERN_INFO " graphics card name: %s\n", sti->outptr.dev_name ); sti_roms[num_sti_roms] = sti; num_sti_roms++; return sti;out_err: kfree(sti); return NULL;}static void __init sticore_check_for_default_sti(struct sti_struct *sti, char *path){ if (strcmp (path, default_sti_path) == 0) default_sti = sti;}/* * on newer systems PDC gives the address of the ROM * in the additional address field addr[1] while on * older Systems the PDC stores it in page0->proc_sti */static int __init sticore_pa_init(struct parisc_device *dev){ char pa_path[21]; struct sti_struct *sti = NULL; int hpa = dev->hpa.start; if (dev->num_addrs && dev->addr[0]) sti = sti_try_rom_generic(dev->addr[0], hpa, NULL); if (!sti) sti = sti_try_rom_generic(hpa, hpa, NULL); if (!sti) sti = sti_try_rom_generic(PAGE0->proc_sti, hpa, NULL); if (!sti) return 1; print_pa_hwpath(dev, pa_path); sticore_check_for_default_sti(sti, pa_path); return 0;}static int __devinit sticore_pci_init(struct pci_dev *pd, const struct pci_device_id *ent){#ifdef CONFIG_PCI unsigned long fb_base, rom_base; unsigned int fb_len, rom_len; struct sti_struct *sti; pci_enable_device(pd); fb_base = pci_resource_start(pd, 0); fb_len = pci_resource_len(pd, 0); rom_base = pci_resource_start(pd, PCI_ROM_RESOURCE); rom_len = pci_resource_len(pd, PCI_ROM_RESOURCE); if (rom_base) { pci_write_config_dword(pd, PCI_ROM_ADDRESS, rom_base | PCI_ROM_ADDRESS_ENABLE); DPRINTK((KERN_DEBUG "STI PCI ROM enabled at 0x%08lx\n", rom_base)); } printk(KERN_INFO "STI PCI graphic ROM found at %08lx (%u kB), fb at %08lx (%u MB)\n", rom_base, rom_len/1024, fb_base, fb_len/1024/1024); DPRINTK((KERN_DEBUG "Trying PCI STI ROM at %08lx, PCI hpa at %08lx\n", rom_base, fb_base)); sti = sti_try_rom_generic(rom_base, fb_base, pd); if (sti) { char pa_path[30]; print_pci_hwpath(pd, pa_path); sticore_check_for_default_sti(sti, pa_path); } if (!sti) { printk(KERN_WARNING "Unable to handle STI device '%s'\n", pci_name(pd)); return -ENODEV; }#endif /* CONFIG_PCI */ return 0;}static void __devexit sticore_pci_remove(struct pci_dev *pd){ BUG();}static struct pci_device_id sti_pci_tbl[] = { { PCI_DEVICE(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_VISUALIZE_EG) }, { PCI_DEVICE(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_VISUALIZE_FX6) }, { PCI_DEVICE(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_VISUALIZE_FX4) }, { PCI_DEVICE(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_VISUALIZE_FX2) }, { PCI_DEVICE(PCI_VENDOR_ID_HP, PCI_DEVICE_ID_HP_VISUALIZE_FXE) }, { 0, } /* terminate list */};MODULE_DEVICE_TABLE(pci, sti_pci_tbl);static struct pci_driver pci_sti_driver = { .name = "sti", .id_table = sti_pci_tbl, .probe = sticore_pci_init, .remove = sticore_pci_remove,};static struct parisc_device_id sti_pa_tbl[] = { { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00077 }, { HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00085 }, { 0, }};static struct parisc_driver pa_sti_driver = { .name = "sti", .id_table = sti_pa_tbl, .probe = sticore_pa_init,};/* * sti_init_roms() - detects all STI ROMs and stores them in sti_roms[] */static int sticore_initialized;static void __init sti_init_roms(void){ if (sticore_initialized) return; sticore_initialized = 1; printk(KERN_INFO "STI GSC/PCI core graphics driver " STI_DRIVERVERSION "\n"); /* Register drivers for native & PCI cards */ register_parisc_driver(&pa_sti_driver); pci_register_driver(&pci_sti_driver); /* if we didn't find the given default sti, take the first one */ if (!default_sti) default_sti = sti_roms[0];}/* * index = 0 gives default sti * index > 0 gives other stis in detection order */struct sti_struct * sti_get_rom(unsigned int index){ if (!sticore_initialized) sti_init_roms(); if (index == 0) return default_sti; if (index > num_sti_roms) return NULL; return sti_roms[index-1];}EXPORT_SYMBOL(sti_get_rom);MODULE_AUTHOR("Philipp Rumpf, Helge Deller, Thomas Bogendoerfer");MODULE_DESCRIPTION("Core STI driver for HP's NGLE series graphics cards in HP PARISC machines");MODULE_LICENSE("GPL v2");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -