diff options
Diffstat (limited to 'drivers/video/console/sticore.c')
| -rw-r--r-- | drivers/video/console/sticore.c | 251 |
1 files changed, 142 insertions, 109 deletions
diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c index 6468a297e34..7da1ad03acb 100644 --- a/drivers/video/console/sticore.c +++ b/drivers/video/console/sticore.c @@ -3,7 +3,7 @@ * core code for console driver using HP's STI firmware * * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> - * Copyright (C) 2001-2003 Helge Deller <deller@gmx.de> + * Copyright (C) 2001-2013 Helge Deller <deller@gmx.de> * Copyright (C) 2001-2002 Thomas Bogendoerfer <tsbogend@alpha.franken.de> * * TODO: @@ -22,13 +22,15 @@ #include <linux/font.h> #include <asm/hardware.h> +#include <asm/page.h> #include <asm/parisc-device.h> +#include <asm/pdc.h> #include <asm/cacheflush.h> #include <asm/grfioctl.h> -#include "../sticore.h" +#include "../fbdev/sticore.h" -#define STI_DRIVERVERSION "Version 0.9a" +#define STI_DRIVERVERSION "Version 0.9b" static struct sti_struct *default_sti __read_mostly; @@ -71,28 +73,34 @@ static const struct sti_init_flags default_init_flags = { static int sti_init_graph(struct sti_struct *sti) { - struct sti_init_inptr_ext inptr_ext = { 0, }; - struct sti_init_inptr inptr = { - .text_planes = 3, /* # of text planes (max 3 for STI) */ - .ext_ptr = STI_PTR(&inptr_ext) - }; - struct sti_init_outptr outptr = { 0, }; + struct sti_init_inptr *inptr = &sti->sti_data->init_inptr; + struct sti_init_inptr_ext *inptr_ext = &sti->sti_data->init_inptr_ext; + struct sti_init_outptr *outptr = &sti->sti_data->init_outptr; unsigned long flags; - int ret; + int ret, err; spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->init_graph, &default_init_flags, &inptr, - &outptr, sti->glob_cfg); + memset(inptr, 0, sizeof(*inptr)); + inptr->text_planes = 3; /* # of text planes (max 3 for STI) */ + memset(inptr_ext, 0, sizeof(*inptr_ext)); + inptr->ext_ptr = STI_PTR(inptr_ext); + outptr->errno = 0; + + ret = sti_call(sti, sti->init_graph, &default_init_flags, inptr, + outptr, sti->glob_cfg); + + if (ret >= 0) + sti->text_planes = outptr->text_planes; + err = outptr->errno; spin_unlock_irqrestore(&sti->lock, flags); if (ret < 0) { - printk(KERN_ERR "STI init_graph failed (ret %d, errno %d)\n",ret,outptr.errno); + pr_err("STI init_graph failed (ret %d, errno %d)\n", ret, err); return -1; } - sti->text_planes = outptr.text_planes; return 0; } @@ -102,16 +110,18 @@ static const struct sti_conf_flags default_conf_flags = { static void sti_inq_conf(struct sti_struct *sti) { - struct sti_conf_inptr inptr = { 0, }; + struct sti_conf_inptr *inptr = &sti->sti_data->inq_inptr; + struct sti_conf_outptr *outptr = &sti->sti_data->inq_outptr; unsigned long flags; s32 ret; - sti->outptr.ext_ptr = STI_PTR(&sti->outptr_ext); + outptr->ext_ptr = STI_PTR(&sti->sti_data->inq_outptr_ext); do { spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->inq_conf, &default_conf_flags, - &inptr, &sti->outptr, sti->glob_cfg); + memset(inptr, 0, sizeof(*inptr)); + ret = sti_call(sti, sti->inq_conf, &default_conf_flags, + inptr, outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); } while (ret == 1); } @@ -124,7 +134,8 @@ static const struct sti_font_flags default_font_flags = { void sti_putc(struct sti_struct *sti, int c, int y, int x) { - struct sti_font_inptr inptr = { + struct sti_font_inptr *inptr = &sti->sti_data->font_inptr; + struct sti_font_inptr inptr_default = { .font_start_addr= STI_PTR(sti->font->raw), .index = c_index(sti, c), .fg_color = c_fg(sti, c), @@ -132,14 +143,15 @@ sti_putc(struct sti_struct *sti, int c, int y, int x) .dest_x = x * sti->font_width, .dest_y = y * sti->font_height, }; - struct sti_font_outptr outptr = { 0, }; + struct sti_font_outptr *outptr = &sti->sti_data->font_outptr; 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); + *inptr = inptr_default; + ret = sti_call(sti, sti->font_unpmv, &default_font_flags, + inptr, outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); } while (ret == 1); } @@ -154,7 +166,8 @@ void sti_set(struct sti_struct *sti, int src_y, int src_x, int height, int width, u8 color) { - struct sti_blkmv_inptr inptr = { + struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr; + struct sti_blkmv_inptr inptr_default = { .fg_color = color, .bg_color = color, .src_x = src_x, @@ -164,14 +177,15 @@ sti_set(struct sti_struct *sti, int src_y, int src_x, .width = width, .height = height, }; - struct sti_blkmv_outptr outptr = { 0, }; + struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr; s32 ret; unsigned long flags; do { spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->block_move, &clear_blkmv_flags, - &inptr, &outptr, sti->glob_cfg); + *inptr = inptr_default; + ret = sti_call(sti, sti->block_move, &clear_blkmv_flags, + inptr, outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); } while (ret == 1); } @@ -180,7 +194,8 @@ void sti_clear(struct sti_struct *sti, int src_y, int src_x, int height, int width, int c) { - struct sti_blkmv_inptr inptr = { + struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr; + struct sti_blkmv_inptr inptr_default = { .fg_color = c_fg(sti, c), .bg_color = c_bg(sti, c), .src_x = src_x * sti->font_width, @@ -190,14 +205,15 @@ sti_clear(struct sti_struct *sti, int src_y, int src_x, .width = width * sti->font_width, .height = height* sti->font_height, }; - struct sti_blkmv_outptr outptr = { 0, }; + struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr; s32 ret; unsigned long flags; do { spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->block_move, &clear_blkmv_flags, - &inptr, &outptr, sti->glob_cfg); + *inptr = inptr_default; + ret = sti_call(sti, sti->block_move, &clear_blkmv_flags, + inptr, outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); } while (ret == 1); } @@ -210,7 +226,8 @@ void sti_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 = { + struct sti_blkmv_inptr *inptr = &sti->sti_data->blkmv_inptr; + struct sti_blkmv_inptr inptr_default = { .src_x = src_x * sti->font_width, .src_y = src_y * sti->font_height, .dest_x = dst_x * sti->font_width, @@ -218,14 +235,15 @@ sti_bmove(struct sti_struct *sti, int src_y, int src_x, .width = width * sti->font_width, .height = height* sti->font_height, }; - struct sti_blkmv_outptr outptr = { 0, }; + struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr; s32 ret; unsigned long flags; do { spin_lock_irqsave(&sti->lock, flags); - ret = STI_CALL(sti->block_move, &default_blkmv_flags, - &inptr, &outptr, sti->glob_cfg); + *inptr = inptr_default; + ret = sti_call(sti, sti->block_move, &default_blkmv_flags, + inptr, outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); } while (ret == 1); } @@ -236,8 +254,7 @@ static void sti_flush(unsigned long start, unsigned long end) flush_icache_range(start, end); } -static void __devinit sti_rom_copy(unsigned long base, unsigned long count, - void *dest) +static void sti_rom_copy(unsigned long base, unsigned long count, void *dest) { unsigned long dest_start = (unsigned long) dest; @@ -264,7 +281,7 @@ static void __devinit sti_rom_copy(unsigned long base, unsigned long count, static char default_sti_path[21] __read_mostly; #ifndef MODULE -static int __devinit sti_setup(char *str) +static int sti_setup(char *str) { if (str) strlcpy (default_sti_path, str, sizeof (default_sti_path)); @@ -283,12 +300,12 @@ __setup("sti=", sti_setup); -static char __devinitdata *font_name[MAX_STI_ROMS] = { "VGA8x16", }; -static int __devinitdata font_index[MAX_STI_ROMS], - font_height[MAX_STI_ROMS], - font_width[MAX_STI_ROMS]; +static char *font_name[MAX_STI_ROMS]; +static int font_index[MAX_STI_ROMS], + font_height[MAX_STI_ROMS], + font_width[MAX_STI_ROMS]; #ifndef MODULE -static int __devinit sti_font_setup(char *str) +static int sti_font_setup(char *str) { char *x; int i = 0; @@ -341,8 +358,8 @@ __setup("sti_font=", sti_font_setup); -static void __devinit -sti_dump_globcfg(struct sti_glob_cfg *glob_cfg, unsigned int sti_mem_request) +static void sti_dump_globcfg(struct sti_glob_cfg *glob_cfg, + unsigned int sti_mem_request) { struct sti_glob_cfg_ext *cfg; @@ -381,46 +398,41 @@ sti_dump_globcfg(struct sti_glob_cfg *glob_cfg, unsigned int sti_mem_request) cfg->sti_mem_addr, sti_mem_request)); } -static void __devinit -sti_dump_outptr(struct sti_struct *sti) +static void sti_dump_outptr(struct sti_struct *sti) { DPRINTK((KERN_INFO "%d bits per pixel\n" "%d used bits\n" "%d planes\n" "attributes %08x\n", - sti->outptr.bits_per_pixel, - sti->outptr.bits_used, - sti->outptr.planes, - sti->outptr.attributes)); + sti->sti_data->inq_outptr.bits_per_pixel, + sti->sti_data->inq_outptr.bits_used, + sti->sti_data->inq_outptr.planes, + sti->sti_data->inq_outptr.attributes)); } -static int __devinit -sti_init_glob_cfg(struct sti_struct *sti, - unsigned long rom_address, unsigned long hpa) +static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, + unsigned long hpa) { struct sti_glob_cfg *glob_cfg; struct sti_glob_cfg_ext *glob_cfg_ext; void *save_addr; void *sti_mem_addr; - const int save_addr_size = 1024; /* XXX */ - int i; + int i, size; - if (!sti->sti_mem_request) + if (sti->sti_mem_request < 256) sti->sti_mem_request = 256; /* STI default */ - glob_cfg = kzalloc(sizeof(*sti->glob_cfg), GFP_KERNEL); - glob_cfg_ext = kzalloc(sizeof(*glob_cfg_ext), GFP_KERNEL); - save_addr = kzalloc(save_addr_size, GFP_KERNEL); - sti_mem_addr = kzalloc(sti->sti_mem_request, GFP_KERNEL); + size = sizeof(struct sti_all_data) + sti->sti_mem_request - 256; - if (!(glob_cfg && glob_cfg_ext && save_addr && sti_mem_addr)) { - kfree(glob_cfg); - kfree(glob_cfg_ext); - kfree(save_addr); - kfree(sti_mem_addr); + sti->sti_data = kzalloc(size, STI_LOWMEM); + if (!sti->sti_data) return -ENOMEM; - } + + glob_cfg = &sti->sti_data->glob_cfg; + glob_cfg_ext = &sti->sti_data->glob_cfg_ext; + save_addr = &sti->sti_data->save_addr; + sti_mem_addr = &sti->sti_data->sti_mem_addr; glob_cfg->ext_ptr = STI_PTR(glob_cfg_ext); glob_cfg->save_addr = STI_PTR(save_addr); @@ -476,32 +488,31 @@ sti_init_glob_cfg(struct sti_struct *sti, return 0; } -#ifdef CONFIG_FB -static struct sti_cooked_font __devinit -*sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) +#ifdef CONFIG_FONT_SUPPORT +static struct sti_cooked_font * +sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) { - const struct font_desc *fbfont; + const struct font_desc *fbfont = NULL; unsigned int size, bpc; void *dest; struct sti_rom_font *nf; struct sti_cooked_font *cooked_font; - if (!fbfont_name || !strlen(fbfont_name)) - return NULL; - fbfont = find_font(fbfont_name); + if (fbfont_name && strlen(fbfont_name)) + fbfont = find_font(fbfont_name); if (!fbfont) fbfont = get_default_font(1024,768, ~(u32)0, ~(u32)0); if (!fbfont) return NULL; - DPRINTK((KERN_DEBUG "selected %dx%d fb-font %s\n", - fbfont->width, fbfont->height, fbfont->name)); + pr_info("STI selected %dx%d framebuffer font %s for sticon\n", + fbfont->width, fbfont->height, fbfont->name); bpc = ((fbfont->width+7)/8) * fbfont->height; size = bpc * 256; size += sizeof(struct sti_rom_font); - nf = kzalloc(size, GFP_KERNEL); + nf = kzalloc(size, STI_LOWMEM); if (!nf) return NULL; @@ -533,16 +544,15 @@ static struct sti_cooked_font __devinit return cooked_font; } #else -static struct sti_cooked_font __devinit -*sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) +static struct sti_cooked_font * +sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) { return NULL; } #endif -static struct sti_cooked_font __devinit -*sti_select_font(struct sti_cooked_rom *rom, - int (*search_font_fnc)(struct sti_cooked_rom *, int, int)) +static struct sti_cooked_font *sti_select_font(struct sti_cooked_rom *rom, + int (*search_font_fnc)(struct sti_cooked_rom *, int, int)) { struct sti_cooked_font *font; int i; @@ -567,8 +577,7 @@ static struct sti_cooked_font __devinit } -static void __devinit -sti_dump_rom(struct sti_rom *rom) +static void sti_dump_rom(struct sti_rom *rom) { printk(KERN_INFO " id %04x-%04x, conforms to spec rev. %d.%02x\n", rom->graphics_id[0], @@ -585,9 +594,8 @@ sti_dump_rom(struct sti_rom *rom) } -static int __devinit -sti_cook_fonts(struct sti_cooked_rom *cooked_rom, - struct sti_rom *raw_rom) +static int 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; @@ -620,8 +628,7 @@ sti_cook_fonts(struct sti_cooked_rom *cooked_rom, } -static int __devinit -sti_search_font(struct sti_cooked_rom *rom, int height, int width) +static int sti_search_font(struct sti_cooked_rom *rom, int height, int width) { struct sti_cooked_font *font; int i = 0; @@ -637,13 +644,12 @@ sti_search_font(struct sti_cooked_rom *rom, int height, int width) #define BMODE_RELOCATE(offset) offset = (offset) / 4; #define BMODE_LAST_ADDR_OFFS 0x50 -static void * __devinit -sti_bmode_font_raw(struct sti_cooked_font *f) +static void *sti_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 = kzalloc (4*size, GFP_KERNEL); + n = kzalloc(4*size, STI_LOWMEM); if (!n) return NULL; p = n + 3; @@ -655,8 +661,8 @@ sti_bmode_font_raw(struct sti_cooked_font *f) return n + 3; } -static void __devinit -sti_bmode_rom_copy(unsigned long base, unsigned long count, void *dest) +static void sti_bmode_rom_copy(unsigned long base, unsigned long count, + void *dest) { unsigned long dest_start = (unsigned long) dest; @@ -670,8 +676,7 @@ sti_bmode_rom_copy(unsigned long base, unsigned long count, void *dest) sti_flush(dest_start, (unsigned long)dest); } -static struct sti_rom * __devinit -sti_get_bmode_rom (unsigned long address) +static struct sti_rom *sti_get_bmode_rom (unsigned long address) { struct sti_rom *raw; u32 size; @@ -680,7 +685,7 @@ sti_get_bmode_rom (unsigned long address) sti_bmode_rom_copy(address + BMODE_LAST_ADDR_OFFS, sizeof(size), &size); size = (size+3) / 4; - raw = kmalloc(size, GFP_KERNEL); + raw = kmalloc(size, STI_LOWMEM); if (raw) { sti_bmode_rom_copy(address, size, raw); memmove (&raw->res004, &raw->type[0], 0x3c); @@ -706,7 +711,7 @@ sti_get_bmode_rom (unsigned long address) return raw; } -static struct sti_rom __devinit *sti_get_wmode_rom(unsigned long address) +static struct sti_rom *sti_get_wmode_rom(unsigned long address) { struct sti_rom *raw; unsigned long size; @@ -714,15 +719,15 @@ static struct sti_rom __devinit *sti_get_wmode_rom(unsigned long address) /* 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); + raw = kmalloc(size, STI_LOWMEM); if (raw) sti_rom_copy(address, size, raw); return raw; } -static int __devinit sti_read_rom(int wordmode, struct sti_struct *sti, - unsigned long address) +static int sti_read_rom(int wordmode, struct sti_struct *sti, + unsigned long address) { struct sti_cooked_rom *cooked; struct sti_rom *raw = NULL; @@ -750,6 +755,10 @@ static int __devinit sti_read_rom(int wordmode, struct sti_struct *sti, address = (unsigned long) STI_PTR(raw); + pr_info("STI ROM supports 32 %sbit firmware functions.\n", + raw->alt_code_type == ALT_CODE_TYPE_PA_RISC_64 + ? "and 64 " : ""); + sti->font_unpmv = address + (raw->font_unpmv & 0x03ffffff); sti->block_move = address + (raw->block_move & 0x03ffffff); sti->init_graph = address + (raw->init_graph & 0x03ffffff); @@ -804,8 +813,9 @@ out_err: return 0; } -static struct sti_struct * __devinit -sti_try_rom_generic(unsigned long address, unsigned long hpa, struct pci_dev *pd) +static struct sti_struct *sti_try_rom_generic(unsigned long address, + unsigned long hpa, + struct pci_dev *pd) { struct sti_struct *sti; int ok; @@ -907,7 +917,8 @@ test_rom: 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 ); + pr_info(" graphics card name: %s\n", + sti->sti_data->inq_outptr.dev_name); sti_roms[num_sti_roms] = sti; num_sti_roms++; @@ -919,7 +930,7 @@ out_err: return NULL; } -static void __devinit sticore_check_for_default_sti(struct sti_struct *sti, char *path) +static void sticore_check_for_default_sti(struct sti_struct *sti, char *path) { if (strcmp (path, default_sti_path) == 0) default_sti = sti; @@ -930,7 +941,7 @@ static void __devinit sticore_check_for_default_sti(struct sti_struct *sti, char * in the additional address field addr[1] while on * older Systems the PDC stores it in page0->proc_sti */ -static int __devinit sticore_pa_init(struct parisc_device *dev) +static int sticore_pa_init(struct parisc_device *dev) { char pa_path[21]; struct sti_struct *sti = NULL; @@ -951,8 +962,7 @@ static int __devinit sticore_pa_init(struct parisc_device *dev) } -static int __devinit sticore_pci_init(struct pci_dev *pd, - const struct pci_device_id *ent) +static int sticore_pci_init(struct pci_dev *pd, const struct pci_device_id *ent) { #ifdef CONFIG_PCI unsigned long fb_base, rom_base; @@ -999,7 +1009,7 @@ static int __devinit sticore_pci_init(struct pci_dev *pd, } -static void __devexit sticore_pci_remove(struct pci_dev *pd) +static void sticore_pci_remove(struct pci_dev *pd) { BUG(); } @@ -1041,7 +1051,7 @@ static struct parisc_driver pa_sti_driver = { static int sticore_initialized __read_mostly; -static void __devinit sti_init_roms(void) +static void sti_init_roms(void) { if (sticore_initialized) return; @@ -1080,6 +1090,29 @@ struct sti_struct * sti_get_rom(unsigned int index) } EXPORT_SYMBOL(sti_get_rom); + +int sti_call(const struct sti_struct *sti, unsigned long func, + const void *flags, void *inptr, void *outptr, + struct sti_glob_cfg *glob_cfg) +{ + unsigned long _flags = STI_PTR(flags); + unsigned long _inptr = STI_PTR(inptr); + unsigned long _outptr = STI_PTR(outptr); + unsigned long _glob_cfg = STI_PTR(glob_cfg); + int ret; + +#ifdef CONFIG_64BIT + /* Check for overflow when using 32bit STI on 64bit kernel. */ + if (WARN_ONCE(_flags>>32 || _inptr>>32 || _outptr>>32 || _glob_cfg>>32, + "Out of 32bit-range pointers!")) + return -1; +#endif + + ret = pdc_sti_call(func, _flags, _inptr, _outptr, _glob_cfg); + + return ret; +} + 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"); |
