diff options
26 files changed, 453 insertions, 346 deletions
diff --git a/arch/parisc/Kconfig b/arch/parisc/Kconfig index d9a50f7a666c..a1167ada29b6 100644 --- a/arch/parisc/Kconfig +++ b/arch/parisc/Kconfig @@ -375,5 +375,6 @@ config KEXEC_FILE endmenu +source "drivers/firmware/Kconfig" source "drivers/parisc/Kconfig" diff --git a/arch/parisc/configs/generic-32bit_defconfig b/arch/parisc/configs/generic-32bit_defconfig index 61bac8ff8f22..3cbcfad5f724 100644 --- a/arch/parisc/configs/generic-32bit_defconfig +++ b/arch/parisc/configs/generic-32bit_defconfig @@ -52,10 +52,6 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_CRYPTOLOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_SIZE=6144 -CONFIG_IDE=y -CONFIG_BLK_DEV_IDECD=y -CONFIG_BLK_DEV_GENERIC=y -CONFIG_BLK_DEV_NS87415=y CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=y CONFIG_BLK_DEV_SR=y @@ -65,6 +61,8 @@ CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_ZALON=y CONFIG_SCSI_DH=y CONFIG_ATA=y +CONFIG_ATA_GENERIC=y +CONFIG_PATA_NS87415=y CONFIG_MD=y CONFIG_BLK_DEV_MD=m CONFIG_MD_LINEAR=m diff --git a/arch/parisc/configs/generic-64bit_defconfig b/arch/parisc/configs/generic-64bit_defconfig index 59561e04e659..7e2d7026285e 100644 --- a/arch/parisc/configs/generic-64bit_defconfig +++ b/arch/parisc/configs/generic-64bit_defconfig @@ -58,11 +58,6 @@ CONFIG_PCI_IOV=y CONFIG_DEVTMPFS=y CONFIG_DEVTMPFS_MOUNT=y CONFIG_BLK_DEV_LOOP=y -CONFIG_IDE=y -CONFIG_IDE_GD=m -CONFIG_IDE_GD_ATAPI=y -CONFIG_BLK_DEV_IDECD=m -CONFIG_BLK_DEV_NS87415=y # CONFIG_SCSI_PROC_FS is not set CONFIG_BLK_DEV_SD=y CONFIG_BLK_DEV_SR=y @@ -76,6 +71,7 @@ CONFIG_SCSI_ZALON=y CONFIG_SCSI_QLA_ISCSI=m CONFIG_SCSI_DH=y CONFIG_ATA=y +CONFIG_PATA_NS87415=y CONFIG_PATA_SIL680=y CONFIG_ATA_GENERIC=y CONFIG_MD=y diff --git a/arch/parisc/include/asm/barrier.h b/arch/parisc/include/asm/barrier.h index 640d46edf32e..c705decf2bed 100644 --- a/arch/parisc/include/asm/barrier.h +++ b/arch/parisc/include/asm/barrier.h @@ -2,11 +2,15 @@ #ifndef __ASM_BARRIER_H #define __ASM_BARRIER_H +#include <asm/alternative.h> + #ifndef __ASSEMBLY__ /* The synchronize caches instruction executes as a nop on systems in which all memory references are performed in order. */ -#define synchronize_caches() __asm__ __volatile__ ("sync" : : : "memory") +#define synchronize_caches() asm volatile("sync" \ + ALTERNATIVE(ALT_COND_NO_SMP, INSN_NOP) \ + : : : "memory") #if defined(CONFIG_SMP) #define mb() do { synchronize_caches(); } while (0) diff --git a/arch/parisc/include/asm/cmpxchg.h b/arch/parisc/include/asm/cmpxchg.h index 068958575871..cf5ee9b0b393 100644 --- a/arch/parisc/include/asm/cmpxchg.h +++ b/arch/parisc/include/asm/cmpxchg.h @@ -14,22 +14,22 @@ extern void __xchg_called_with_bad_pointer(void); /* __xchg32/64 defined in arch/parisc/lib/bitops.c */ -extern unsigned long __xchg8(char, char *); -extern unsigned long __xchg32(int, int *); +extern unsigned long __xchg8(char, volatile char *); +extern unsigned long __xchg32(int, volatile int *); #ifdef CONFIG_64BIT -extern unsigned long __xchg64(unsigned long, unsigned long *); +extern unsigned long __xchg64(unsigned long, volatile unsigned long *); #endif /* optimizer better get rid of switch since size is a constant */ static inline unsigned long -__xchg(unsigned long x, __volatile__ void *ptr, int size) +__xchg(unsigned long x, volatile void *ptr, int size) { switch (size) { #ifdef CONFIG_64BIT - case 8: return __xchg64(x, (unsigned long *) ptr); + case 8: return __xchg64(x, (volatile unsigned long *) ptr); #endif - case 4: return __xchg32((int) x, (int *) ptr); - case 1: return __xchg8((char) x, (char *) ptr); + case 4: return __xchg32((int) x, (volatile int *) ptr); + case 1: return __xchg8((char) x, (volatile char *) ptr); } __xchg_called_with_bad_pointer(); return x; diff --git a/arch/parisc/include/asm/futex.h b/arch/parisc/include/asm/futex.h index c459f656c8c3..fceb9cf02fb3 100644 --- a/arch/parisc/include/asm/futex.h +++ b/arch/parisc/include/asm/futex.h @@ -16,7 +16,7 @@ static inline void _futex_spin_lock_irqsave(u32 __user *uaddr, unsigned long int *flags) { extern u32 lws_lock_start[]; - long index = ((long)uaddr & 0xf0) >> 2; + long index = ((long)uaddr & 0x3f8) >> 1; arch_spinlock_t *s = (arch_spinlock_t *)&lws_lock_start[index]; local_irq_save(*flags); arch_spin_lock(s); @@ -26,7 +26,7 @@ static inline void _futex_spin_unlock_irqrestore(u32 __user *uaddr, unsigned long int *flags) { extern u32 lws_lock_start[]; - long index = ((long)uaddr & 0xf0) >> 2; + long index = ((long)uaddr & 0x3f8) >> 1; arch_spinlock_t *s = (arch_spinlock_t *)&lws_lock_start[index]; arch_spin_unlock(s); local_irq_restore(*flags); diff --git a/arch/parisc/include/asm/socket.h b/arch/parisc/include/asm/socket.h index 79feff1b0721..33500c9f6e5e 100644 --- a/arch/parisc/include/asm/socket.h +++ b/arch/parisc/include/asm/socket.h @@ -4,8 +4,8 @@ #include <uapi/asm/socket.h> -/* O_NONBLOCK clashes with the bits used for socket types. Therefore we - * have to define SOCK_NONBLOCK to a different value here. +/* O_NONBLOCK clashed with the bits used for socket types. Therefore we + * had to define SOCK_NONBLOCK to a different value here. */ #define SOCK_NONBLOCK 0x40000000 diff --git a/arch/parisc/include/asm/spinlock.h b/arch/parisc/include/asm/spinlock.h index 51b6c47f802f..fa5ee8a45dbd 100644 --- a/arch/parisc/include/asm/spinlock.h +++ b/arch/parisc/include/asm/spinlock.h @@ -10,13 +10,21 @@ static inline int arch_spin_is_locked(arch_spinlock_t *x) { volatile unsigned int *a = __ldcw_align(x); - return *a == 0; + return READ_ONCE(*a) == 0; } -#define arch_spin_lock(lock) arch_spin_lock_flags(lock, 0) +static inline void arch_spin_lock(arch_spinlock_t *x) +{ + volatile unsigned int *a; + + a = __ldcw_align(x); + while (__ldcw(a) == 0) + while (*a == 0) + continue; +} static inline void arch_spin_lock_flags(arch_spinlock_t *x, - unsigned long flags) + unsigned long flags) { volatile unsigned int *a; @@ -25,10 +33,8 @@ static inline void arch_spin_lock_flags(arch_spinlock_t *x, while (*a == 0) if (flags & PSW_SM_I) { local_irq_enable(); - cpu_relax(); local_irq_disable(); - } else - cpu_relax(); + } } #define arch_spin_lock_flags arch_spin_lock_flags @@ -44,12 +50,9 @@ static inline void arch_spin_unlock(arch_spinlock_t *x) static inline int arch_spin_trylock(arch_spinlock_t *x) { volatile unsigned int *a; - int ret; a = __ldcw_align(x); - ret = __ldcw(a) != 0; - - return ret; + return __ldcw(a) != 0; } /* diff --git a/arch/parisc/include/uapi/asm/fcntl.h b/arch/parisc/include/uapi/asm/fcntl.h index 03ce20e5ad7d..03dee816cb13 100644 --- a/arch/parisc/include/uapi/asm/fcntl.h +++ b/arch/parisc/include/uapi/asm/fcntl.h @@ -3,22 +3,19 @@ #define _PARISC_FCNTL_H #define O_APPEND 000000010 -#define O_BLKSEEK 000000100 /* HPUX only */ #define O_CREAT 000000400 /* not fcntl */ #define O_EXCL 000002000 /* not fcntl */ #define O_LARGEFILE 000004000 #define __O_SYNC 000100000 #define O_SYNC (__O_SYNC|O_DSYNC) -#define O_NONBLOCK 000200004 /* HPUX has separate NDELAY & NONBLOCK */ +#define O_NONBLOCK 000200000 #define O_NOCTTY 000400000 /* not fcntl */ -#define O_DSYNC 001000000 /* HPUX only */ -#define O_RSYNC 002000000 /* HPUX only */ +#define O_DSYNC 001000000 #define O_NOATIME 004000000 #define O_CLOEXEC 010000000 /* set close_on_exec */ #define O_DIRECTORY 000010000 /* must be a directory */ #define O_NOFOLLOW 000000200 /* don't follow links */ -#define O_INVISIBLE 004000000 /* invisible I/O, for DMAPI/XDSM */ #define O_PATH 020000000 #define __O_TMPFILE 040000000 diff --git a/arch/parisc/include/uapi/asm/mman.h b/arch/parisc/include/uapi/asm/mman.h index 6fd8871e4081..ab78cba446ed 100644 --- a/arch/parisc/include/uapi/asm/mman.h +++ b/arch/parisc/include/uapi/asm/mman.h @@ -25,6 +25,7 @@ #define MAP_STACK 0x40000 /* give out an address that is best suited for process/thread stacks */ #define MAP_HUGETLB 0x80000 /* create a huge page mapping */ #define MAP_FIXED_NOREPLACE 0x100000 /* MAP_FIXED which doesn't unmap underlying mapping */ +#define MAP_UNINITIALIZED 0 /* uninitialized anonymous mmap */ #define MS_SYNC 1 /* synchronous memory sync */ #define MS_ASYNC 2 /* sync memory asynchronously */ diff --git a/arch/parisc/include/uapi/asm/signal.h b/arch/parisc/include/uapi/asm/signal.h index d38563a394f2..e605197b462c 100644 --- a/arch/parisc/include/uapi/asm/signal.h +++ b/arch/parisc/include/uapi/asm/signal.h @@ -35,11 +35,11 @@ #define SIGURG 29 #define SIGXFSZ 30 #define SIGUNUSED 31 -#define SIGSYS 31 /* Linux doesn't use this */ +#define SIGSYS 31 /* These should not be considered constants from userland. */ #define SIGRTMIN 32 -#define SIGRTMAX _NSIG /* it's 44 under HP/UX */ +#define SIGRTMAX _NSIG /* * SA_FLAGS values: @@ -61,7 +61,6 @@ #define SA_NODEFER 0x00000020 #define SA_RESTART 0x00000040 #define SA_NOCLDWAIT 0x00000080 -#define _SA_SIGGFAULT 0x00000100 /* HPUX */ #define SA_NOMASK SA_NODEFER #define SA_ONESHOT SA_RESETHAND diff --git a/arch/parisc/install.sh b/arch/parisc/install.sh index 6f68784fea25..056d588befdd 100644 --- a/arch/parisc/install.sh +++ b/arch/parisc/install.sh @@ -43,7 +43,7 @@ fi # Default install -if [ "$(basename $2)" = "zImage" ]; then +if [ "$(basename $2)" = "vmlinuz" ]; then # Compressed install echo "Installing compressed kernel" base=vmlinuz diff --git a/arch/parisc/kernel/cache.c b/arch/parisc/kernel/cache.c index b5e1d9f1b440..86a1a63563fd 100644 --- a/arch/parisc/kernel/cache.c +++ b/arch/parisc/kernel/cache.c @@ -383,12 +383,12 @@ EXPORT_SYMBOL(flush_kernel_icache_range_asm); static unsigned long parisc_cache_flush_threshold __ro_after_init = FLUSH_THRESHOLD; #define FLUSH_TLB_THRESHOLD (16*1024) /* 16 KiB minimum TLB threshold */ -static unsigned long parisc_tlb_flush_threshold __ro_after_init = FLUSH_TLB_THRESHOLD; +static unsigned long parisc_tlb_flush_threshold __ro_after_init = ~0UL; void __init parisc_setup_cache_timing(void) { unsigned long rangetime, alltime; - unsigned long size, start; + unsigned long size; unsigned long threshold; alltime = mfctl(16); @@ -422,14 +422,9 @@ void __init parisc_setup_cache_timing(void) goto set_tlb_threshold; } - size = 0; - start = (unsigned long) _text; + size = (unsigned long)_end - (unsigned long)_text; rangetime = mfctl(16); - while (start < (unsigned long) _end) { - flush_tlb_kernel_range(start, start + PAGE_SIZE); - start += PAGE_SIZE; - size += PAGE_SIZE; - } + flush_tlb_kernel_range((unsigned long)_text, (unsigned long)_end); rangetime = mfctl(16) - rangetime; alltime = mfctl(16); @@ -444,8 +439,11 @@ void __init parisc_setup_cache_timing(void) threshold/1024); set_tlb_threshold: - if (threshold > parisc_tlb_flush_threshold) + if (threshold > FLUSH_TLB_THRESHOLD) parisc_tlb_flush_threshold = threshold; + else + parisc_tlb_flush_threshold = FLUSH_TLB_THRESHOLD; + printk(KERN_INFO "TLB flush threshold set to %lu KiB\n", parisc_tlb_flush_threshold/1024); } diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S index 519f9056fd00..f6f28e41bb5e 100644 --- a/arch/parisc/kernel/entry.S +++ b/arch/parisc/kernel/entry.S @@ -899,20 +899,20 @@ intr_check_sig: * Only do signals if we are returning to user space */ LDREG PT_IASQ0(%r16), %r20 - cmpib,COND(=),n LINUX_GATEWAY_SPACE, %r20, intr_restore /* backward */ + cmpib,COND(=),n LINUX_GATEWAY_SPACE, %r20, intr_restore /* forward */ LDREG PT_IASQ1(%r16), %r20 - cmpib,COND(=),n LINUX_GATEWAY_SPACE, %r20, intr_restore /* backward */ - - /* NOTE: We need to enable interrupts if we have to deliver - * signals. We used to do this earlier but it caused kernel - * stack overflows. */ - ssm PSW_SM_I, %r0 + cmpib,COND(=),n LINUX_GATEWAY_SPACE, %r20, intr_restore /* forward */ copy %r0, %r25 /* long in_syscall = 0 */ #ifdef CONFIG_64BIT ldo -16(%r30),%r29 /* Reference param save area */ #endif + /* NOTE: We need to enable interrupts if we have to deliver + * signals. We used to do this earlier but it caused kernel + * stack overflows. */ + ssm PSW_SM_I, %r0 + BL do_notify_resume,%r2 copy %r16, %r26 /* struct pt_regs *regs */ diff --git a/arch/parisc/kernel/inventory.c b/arch/parisc/kernel/inventory.c index 9298f2285510..7ab2f2a54400 100644 --- a/arch/parisc/kernel/inventory.c +++ b/arch/parisc/kernel/inventory.c @@ -19,6 +19,7 @@ #include <linux/init.h> #include <linux/slab.h> #include <linux/mm.h> +#include <linux/platform_device.h> #include <asm/hardware.h> #include <asm/io.h> #include <asm/mmzone.h> @@ -641,4 +642,33 @@ void __init do_device_inventory(void) if (pa_serialize_tlb_flushes) pr_info("Merced bus found: Enable PxTLB serialization.\n"); #endif + +#if defined(CONFIG_FW_CFG_SYSFS) + if (running_on_qemu) { + struct resource res[3] = {0,}; + unsigned int base; + + base = ((unsigned long long) PAGE0->pad0[2] << 32) + | PAGE0->pad0[3]; /* SeaBIOS stored it here */ + + res[0].name = "fw_cfg"; + res[0].start = base; + res[0].end = base + 8 - 1; + res[0].flags = IORESOURCE_MEM; + + res[1].name = "ctrl"; + res[1].start = 0; + res[1].flags = IORESOURCE_REG; + + res[2].name = "data"; + res[2].start = 4; + res[2].flags = IORESOURCE_REG; + + if (base) { + pr_info("Found qemu fw_cfg interface at %#08x\n", base); + platform_device_register_simple("fw_cfg", + PLATFORM_DEVID_NONE, res, 3); + } + } +#endif } diff --git a/arch/parisc/kernel/smp.c b/arch/parisc/kernel/smp.c index 6271139d2213..10227f667c8a 100644 --- a/arch/parisc/kernel/smp.c +++ b/arch/parisc/kernel/smp.c @@ -173,9 +173,12 @@ ipi_interrupt(int irq, void *dev_id) this_cpu, which); return IRQ_NONE; } /* Switch */ - /* let in any pending interrupts */ - local_irq_enable(); - local_irq_disable(); + + /* before doing more, let in any pending interrupts */ + if (ops) { + local_irq_enable(); + local_irq_disable(); + } } /* while (ops) */ } return IRQ_HANDLED; diff --git a/arch/parisc/kernel/syscall.S b/arch/parisc/kernel/syscall.S index 3ad61a177f5b..322503780db6 100644 --- a/arch/parisc/kernel/syscall.S +++ b/arch/parisc/kernel/syscall.S @@ -571,8 +571,8 @@ lws_compare_and_swap: ldil L%lws_lock_start, %r20 ldo R%lws_lock_start(%r20), %r28 - /* Extract four bits from r26 and hash lock (Bits 4-7) */ - extru %r26, 27, 4, %r20 + /* Extract eight bits from r26 and hash lock (Bits 3-11) */ + extru %r26, 28, 8, %r20 /* Find lock to use, the hash is either one of 0 to 15, multiplied by 16 (keep it 16-byte aligned) @@ -761,8 +761,8 @@ cas2_lock_start: ldil L%lws_lock_start, %r20 ldo R%lws_lock_start(%r20), %r28 - /* Extract four bits from r26 and hash lock (Bits 4-7) */ - extru %r26, 27, 4, %r20 + /* Extract eight bits from r26 and hash lock (Bits 3-11) */ + extru %r26, 28, 8, %r20 /* Find lock to use, the hash is either one of 0 to 15, multiplied by 16 (keep it 16-byte aligned) @@ -950,7 +950,7 @@ END(sys_call_table64) .align L1_CACHE_BYTES ENTRY(lws_lock_start) /* lws locks */ - .rept 16 + .rept 256 /* Keep locks aligned at 16-bytes */ .word 1 .word 0 diff --git a/arch/parisc/lib/bitops.c b/arch/parisc/lib/bitops.c index 2e4d1f05a926..9ac683bf6ae7 100644 --- a/arch/parisc/lib/bitops.c +++ b/arch/parisc/lib/bitops.c @@ -18,7 +18,7 @@ arch_spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] __lock_aligned = { #endif #ifdef CONFIG_64BIT -unsigned long __xchg64(unsigned long x, unsigned long *ptr) +unsigned long __xchg64(unsigned long x, volatile unsigned long *ptr) { unsigned long temp, flags; @@ -30,7 +30,7 @@ unsigned long __xchg64(unsigned long x, unsigned long *ptr) } #endif -unsigned long __xchg32(int x, int *ptr) +unsigned long __xchg32(int x, volatile int *ptr) { unsigned long flags; long temp; @@ -43,7 +43,7 @@ unsigned long __xchg32(int x, int *ptr) } -unsigned long __xchg8(char x, char *ptr) +unsigned long __xchg8(char x, volatile char *ptr) { unsigned long flags; long temp; diff --git a/arch/parisc/lib/iomap.c b/arch/parisc/lib/iomap.c index ce400417d54e..f03adb1999e7 100644 --- a/arch/parisc/lib/iomap.c +++ b/arch/parisc/lib/iomap.c @@ -346,6 +346,16 @@ u64 ioread64be(const void __iomem *addr) return *((u64 *)addr); } +u64 ioread64_hi_lo(const void __iomem *addr) +{ + u32 low, high; + + high = ioread32(addr + sizeof(u32)); + low = ioread32(addr); + + return low + ((u64)high << 32); +} + void iowrite8(u8 datum, void __iomem *addr) { if (unlikely(INDIRECT_ADDR(addr))) { @@ -409,6 +419,12 @@ void iowrite64be(u64 datum, void __iomem *addr) } } +void iowrite64_hi_lo(u64 val, void __iomem *addr) +{ + iowrite32(val >> 32, addr + sizeof(u32)); + iowrite32(val, addr); +} + /* Repeating interfaces */ void ioread8_rep(const void __iomem *addr, void *dst, unsigned long count) @@ -511,6 +527,7 @@ EXPORT_SYMBOL(ioread32); EXPORT_SYMBOL(ioread32be); EXPORT_SYMBOL(ioread64); EXPORT_SYMBOL(ioread64be); +EXPORT_SYMBOL(ioread64_hi_lo); EXPORT_SYMBOL(iowrite8); EXPORT_SYMBOL(iowrite16); EXPORT_SYMBOL(iowrite16be); @@ -518,6 +535,7 @@ EXPORT_SYMBOL(iowrite32); EXPORT_SYMBOL(iowrite32be); EXPORT_SYMBOL(iowrite64); EXPORT_SYMBOL(iowrite64be); +EXPORT_SYMBOL(iowrite64_hi_lo); EXPORT_SYMBOL(ioread8_rep); EXPORT_SYMBOL(ioread16_rep); EXPORT_SYMBOL(ioread32_rep); diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 4843e94713a4..d78dd3c82e9d 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -186,7 +186,7 @@ config RASPBERRYPI_FIRMWARE config FW_CFG_SYSFS tristate "QEMU fw_cfg device support in sysfs" - depends on SYSFS && (ARM || ARM64 || PPC_PMAC || SPARC || X86) + depends on SYSFS && (ARM || ARM64 || PARISC || PPC_PMAC || SPARC || X86) depends on HAS_IOPORT_MAP default n help diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c index 6945c3c96637..0078260fbabe 100644 --- a/drivers/firmware/qemu_fw_cfg.c +++ b/drivers/firmware/qemu_fw_cfg.c @@ -215,6 +215,9 @@ static void fw_cfg_io_cleanup(void) # define FW_CFG_CTRL_OFF 0x08 # define FW_CFG_DATA_OFF 0x00 # define FW_CFG_DMA_OFF 0x10 +# elif defined(CONFIG_PARISC) /* parisc */ +# define FW_CFG_CTRL_OFF 0x00 +# define FW_CFG_DATA_OFF 0x04 # elif (defined(CONFIG_PPC_PMAC) || defined(CONFIG_SPARC32)) /* ppc/mac,sun4m */ # define FW_CFG_CTRL_OFF 0x00 # define FW_CFG_DATA_OFF 0x02 diff --git a/drivers/video/console/Kconfig b/drivers/video/console/Kconfig index 39deb22a4180..ee33b8ec62bb 100644 --- a/drivers/video/console/Kconfig +++ b/drivers/video/console/Kconfig @@ -119,6 +119,7 @@ config STI_CONSOLE bool "STI text console" depends on PARISC && HAS_IOMEM select FONT_SUPPORT + select CRC32 default y help The STI console is the builtin display/keyboard on HP-PARISC diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c index e7fd995d3aea..1b451165311c 100644 --- a/drivers/video/console/sticon.c +++ b/drivers/video/console/sticon.c @@ -2,7 +2,7 @@ * linux/drivers/video/console/sticon.c - console driver using HP's STI firmware * * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> - * Copyright (C) 2002 Helge Deller <deller@gmx.de> + * Copyright (C) 2002-2020 Helge Deller <deller@gmx.de> * * Based on linux/drivers/video/vgacon.c and linux/drivers/video/fbcon.c, * which were @@ -43,6 +43,9 @@ #include <linux/kd.h> #include <linux/selection.h> #include <linux/module.h> +#include <linux/slab.h> +#include <linux/font.h> +#include <linux/crc32.h> #include <asm/io.h> @@ -52,27 +55,15 @@ #define BLANK 0 static int vga_is_gfx; -/* this is the sti_struct used for this console */ -static struct sti_struct *sticon_sti; - -/* Software scrollback */ -static unsigned long softback_buf, softback_curr; -static unsigned long softback_in; -static unsigned long /* softback_top, */ softback_end; -static int softback_lines; - -/* software cursor */ -static int cursor_drawn; -#define CURSOR_DRAW_DELAY (1) -#define DEFAULT_CURSOR_BLINK_RATE (20) +#define STI_DEF_FONT sticon_sti->font -static int vbl_cursor_cnt; +/* borrowed from fbcon.c */ +#define FNTREFCOUNT(fd) (fd->refcount) +#define FNTCRC(fd) (fd->crc) +static struct sti_cooked_font *font_data[MAX_NR_CONSOLES]; -static inline void cursor_undrawn(void) -{ - vbl_cursor_cnt = 0; - cursor_drawn = 0; -} +/* this is the sti_struct used for this console */ +static struct sti_struct *sticon_sti; static const char *sticon_startup(void) { @@ -81,61 +72,43 @@ static const char *sticon_startup(void) static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos) { - int redraw_cursor = 0; - if (vga_is_gfx || console_blanked) return; if (conp->vc_mode != KD_TEXT) return; -#if 0 - if ((p->cursor_x == xpos) && (p->cursor_y == ypos)) { - cursor_undrawn(); - redraw_cursor = 1; - } -#endif - sti_putc(sticon_sti, c, ypos, xpos); - - if (redraw_cursor) - vbl_cursor_cnt = CURSOR_DRAW_DELAY; + sti_putc(sticon_sti, c, ypos, xpos, font_data[conp->vc_num]); } static void sticon_putcs(struct vc_data *conp, const unsigned short *s, int count, int ypos, int xpos) { - int redraw_cursor = 0; - if (vga_is_gfx || console_blanked) return; if (conp->vc_mode != KD_TEXT) return; -#if 0 - if ((p->cursor_y == ypos) && (xpos <= p->cursor_x) && - (p->cursor_x < (xpos + count))) { - cursor_undrawn(); - redraw_cursor = 1; - } -#endif - while (count--) { - sti_putc(sticon_sti, scr_readw(s++), ypos, xpos++); + sti_putc(sticon_sti, scr_readw(s++), ypos, xpos++, + font_data[conp->vc_num]); } - - if (redraw_cursor) - vbl_cursor_cnt = CURSOR_DRAW_DELAY; } static void sticon_cursor(struct vc_data *conp, int mode) { unsigned short car1; + /* no cursor update if screen is blanked */ + if (vga_is_gfx || console_blanked) + return; + car1 = conp->vc_screenbuf[conp->state.x + conp->state.y * conp->vc_cols]; switch (mode) { case CM_ERASE: - sti_putc(sticon_sti, car1, conp->state.y, conp->state.x); + sti_putc(sticon_sti, car1, conp->state.y, conp->state.x, + font_data[conp->vc_num]); break; case CM_MOVE: case CM_DRAW: @@ -146,7 +119,7 @@ static void sticon_cursor(struct vc_data *conp, int mode) case CUR_TWO_THIRDS: case CUR_BLOCK: sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11), - conp->state.y, conp->state.x); + conp->state.y, conp->state.x, font_data[conp->vc_num]); break; } break; @@ -165,42 +138,164 @@ static bool sticon_scroll(struct vc_data *conp, unsigned int t, switch (dir) { case SM_UP: - sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols); - sti_clear(sti, b - count, 0, count, conp->vc_cols, conp->vc_video_erase_char); + sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols, + font_data[conp->vc_num]); + sti_clear(sti, b - count, 0, count, conp->vc_cols, + conp->vc_video_erase_char, font_data[conp->vc_num]); break; case SM_DOWN: - sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols); - sti_clear(sti, t, 0, count, conp->vc_cols, conp->vc_video_erase_char); + sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols, + font_data[conp->vc_num]); + sti_clear(sti, t, 0, count, conp->vc_cols, + conp->vc_video_erase_char, font_data[conp->vc_num]); break; } return false; } +static int sticon_set_def_font(int unit, struct console_font *op) +{ + if (font_data[unit] != STI_DEF_FONT) { + if (--FNTREFCOUNT(font_data[unit]) == 0) { + kfree(font_data[unit]->raw_ptr); + kfree(font_data[unit]); + } + font_data[unit] = STI_DEF_FONT; + } + + return 0; +} + +static int sticon_set_font(struct vc_data *vc, struct console_font *op) +{ + struct sti_struct *sti = sticon_sti; + int vc_cols, vc_rows, vc_old_cols, vc_old_rows; + int unit = vc->vc_num; + int w = op->width; + int h = op->height; + int size, i, bpc, pitch; + struct sti_rom_font *new_font; + struct sti_cooked_font *cooked_font; + unsigned char *data = op->data, *p; + + if ((w < 6) || (h < 6) || (w > 32) || (h > 32) + || (op->charcount != 256 && op->charcount != 512)) + return -EINVAL; + pitch = ALIGN(w, 8) / 8; + bpc = pitch * h; + size = bpc * op->charcount; + + new_font = kmalloc(sizeof(*new_font) + size, STI_LOWMEM); + if (!new_font) + return -ENOMEM; + + new_font->first_char = 0; + new_font->last_char = op->charcount - 1; + new_font->width = w; + new_font->height = h; + new_font->font_type = STI_FONT_HPROMAN8; + new_font->bytes_per_char = bpc; + new_font->underline_height = 0; + new_font->underline_pos = 0; + + cooked_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL); + if (!cooked_font) { + kfree(new_font); + return -ENOMEM; + } + cooked_font->raw = new_font; + cooked_font->raw_ptr = new_font; + cooked_font->width = w; + cooked_font->height = h; + FNTREFCOUNT(cooked_font) = 0; /* usage counter */ + + p = (unsigned char *) new_font; + p += sizeof(*new_font); + for (i = 0; i < op->charcount; i++) { + memcpy(p, data, bpc); + data += pitch*32; + p += bpc; + } + FNTCRC(cooked_font) = crc32(0, new_font, size + sizeof(*new_font)); + sti_font_convert_bytemode(sti, cooked_font); + new_font = cooked_font->raw_ptr; + + /* check if font is already used by other console */ + for (i = 0; i < MAX_NR_CONSOLES; i++) { + if (font_data[i] != STI_DEF_FONT + && (FNTCRC(font_data[i]) == FNTCRC(cooked_font))) { + kfree(new_font); + kfree(cooked_font); + /* current font is the same as the new one */ + if (i == unit) + return 0; + cooked_font = font_data[i]; + new_font = cooked_font->raw_ptr; + break; + } + } + + /* clear screen with old font: we now may have less rows */ + vc_old_rows = vc->vc_rows; + vc_old_cols = vc->vc_cols; + sti_clear(sticon_sti, 0, 0, vc_old_rows, vc_old_cols, + vc->vc_video_erase_char, font_data[vc->vc_num]); + + /* delete old font in case it is a user font */ + sticon_set_def_font(unit, NULL); + + FNTREFCOUNT(cooked_font)++; + font_data[unit] = cooked_font; + + vc_cols = sti_onscreen_x(sti) / cooked_font->width; + vc_rows = sti_onscreen_y(sti) / cooked_font->height; + vc_resize(vc, vc_cols, vc_rows); + + /* need to repaint screen if cols & rows are same as old font */ + if (vc_cols == vc_old_cols && vc_rows == vc_old_rows) + update_screen(vc); + + return 0; +} + +static int sticon_font_default(struct vc_data *vc, struct console_font *op, char *name) +{ + return sticon_set_def_font(vc->vc_num, op); +} + +static int sticon_font_set(struct vc_data *vc, struct console_font *font, + unsigned int flags) +{ + return sticon_set_font(vc, font); +} + static void sticon_init(struct vc_data *c, int init) { struct sti_struct *sti = sticon_sti; int vc_cols, vc_rows; sti_set(sti, 0, 0, sti_onscreen_y(sti), sti_onscreen_x(sti), 0); - vc_cols = sti_onscreen_x(sti) / sti->font_width; - vc_rows = sti_onscreen_y(sti) / sti->font_height; + vc_cols = sti_onscreen_x(sti) / sti->font->width; + vc_rows = sti_onscreen_y(sti) / sti->font->height; c->vc_can_do_color = 1; if (init) { c->vc_cols = vc_cols; c->vc_rows = vc_rows; } else { - /* vc_rows = (c->vc_rows > vc_rows) ? vc_rows : c->vc_rows; */ - /* vc_cols = (c->vc_cols > vc_cols) ? vc_cols : c->vc_cols; */ vc_resize(c, vc_cols, vc_rows); -/* vc_resize_con(vc_rows, vc_cols, c->vc_num); */ } } static void sticon_deinit(struct vc_data *c) { + int i; + + /* free memory used by user font */ + for (i = 0; i < MAX_NR_CONSOLES; i++) + sticon_set_def_font(i, NULL); } static void sticon_clear(struct vc_data *conp, int sy, int sx, int height, @@ -209,7 +304,8 @@ static void sticon_clear(struct vc_data *conp, int sy, int sx, int height, if (!height || !width) return; - sti_clear(sticon_sti, sy, sx, height, width, conp->vc_video_erase_char); + sti_clear(sticon_sti, sy, sx, height, width, + conp->vc_video_erase_char, font_data[conp->vc_num]); } static int sticon_switch(struct vc_data *conp) @@ -224,64 +320,13 @@ static int sticon_blank(struct vc_data *c, int blank, int mode_switch) vga_is_gfx = 0; return 1; } - sti_clear(sticon_sti, 0,0, c->vc_rows, c->vc_cols, BLANK); + sti_clear(sticon_sti, 0, 0, c->vc_rows, c->vc_cols, BLANK, + font_data[c->vc_num]); if (mode_switch) vga_is_gfx = 1; return 1; } -static u16 *sticon_screen_pos(const struct vc_data *conp, int offset) -{ - int line; - unsigned long p; - - if (conp->vc_num != fg_console || !softback_lines) - return (u16 *)(conp->vc_origin + offset); - line = offset / conp->vc_size_row; - if (line >= softback_lines) - return (u16 *)(conp->vc_origin + offset - softback_lines * conp->vc_size_row); - p = softback_curr + offset; - if (p >= softback_end) - p += softback_buf - softback_end; - return (u16 *)p; -} - -static unsigned long sticon_getxy(struct vc_data *conp, unsigned long pos, - int *px, int *py) -{ - int x, y; - unsigned long ret; - if (pos >= conp->vc_origin && pos < conp->vc_scr_end) { - unsigned long offset = (pos - conp->vc_origin) / 2; - - x = offset % conp->vc_cols; - y = offset / conp->vc_cols; - if (conp->vc_num == fg_console) - y += softback_lines; - ret = pos + (conp->vc_cols - x) * 2; - } else if (conp->vc_num == fg_console && softback_lines) { - unsigned long offset = pos - softback_curr; - - if (pos < softback_curr) - offset += softback_end - softback_buf; - offset /= 2; - x = offset % conp->vc_cols; - y = offset / conp->vc_cols; - ret = pos + (conp->vc_cols - x) * 2; - if (ret == softback_end) - ret = softback_buf; - if (ret == softback_in) - ret = conp->vc_origin; - } else { - /* Should not happen */ - x = y = 0; - ret = conp->vc_origin; - } - if (px) *px = x; - if (py) *py = y; - return ret; -} - static u8 sticon_build_attr(struct vc_data *conp, u8 color, enum vc_intensity intens, bool blink, bool underline, bool reverse, @@ -312,10 +357,6 @@ static void sticon_invert_region(struct vc_data *conp, u16 *p, int count) } } -static void sticon_save_screen(struct vc_data *conp) -{ -} - static const struct consw sti_con = { .owner = THIS_MODULE, .con_startup = sticon_startup, @@ -328,18 +369,18 @@ static const struct consw sti_con = { .con_scroll = sticon_scroll, .con_switch = sticon_switch, .con_blank = sticon_blank, - .con_save_screen = sticon_save_screen, + .con_font_set = sticon_font_set, + .con_font_default = sticon_font_default, .con_build_attr = sticon_build_attr, .con_invert_region = sticon_invert_region, - .con_screen_pos = sticon_screen_pos, - .con_getxy = sticon_getxy, }; static int __init sticonsole_init(void) { - int err; + int err, i; + /* already initialized ? */ if (sticon_sti) return 0; @@ -348,14 +389,16 @@ static int __init sticonsole_init(void) if (!sticon_sti) return -ENODEV; - if (conswitchp == &dummy_con) { - printk(KERN_INFO "sticon: Initializing STI text console.\n"); - console_lock(); - err = do_take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1, 1); - console_unlock(); - return err; - } - return 0; + for (i = 0; i < MAX_NR_CONSOLES; i++) + font_data[i] = STI_DEF_FONT; + + pr_info("sticon: Initializing STI text console.\n"); + console_lock(); + err = do_take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1, + PAGE0->mem_cons.cl_class != CL_DUPLEX); + console_unlock(); + + return err; } module_init(sticonsole_init); diff --git a/drivers/video/console/sticore.c b/drivers/video/console/sticore.c index 84c3ca37040a..6a26a364f9bd 100644 --- a/drivers/video/console/sticore.c +++ b/drivers/video/console/sticore.c @@ -4,7 +4,7 @@ * core code for console driver using HP's STI firmware * * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> - * Copyright (C) 2001-2013 Helge Deller <deller@gmx.de> + * Copyright (C) 2001-2020 Helge Deller <deller@gmx.de> * Copyright (C) 2001-2002 Thomas Bogendoerfer <tsbogend@alpha.franken.de> * * TODO: @@ -14,6 +14,8 @@ * */ +#define pr_fmt(fmt) "%s: " fmt, KBUILD_MODNAME + #include <linux/module.h> #include <linux/types.h> #include <linux/kernel.h> @@ -133,16 +135,17 @@ static const struct sti_font_flags default_font_flags = { }; void -sti_putc(struct sti_struct *sti, int c, int y, int x) +sti_putc(struct sti_struct *sti, int c, int y, int x, + struct sti_cooked_font *font) { struct sti_font_inptr *inptr = &sti->sti_data->font_inptr; struct sti_font_inptr inptr_default = { - .font_start_addr= STI_PTR(sti->font->raw), + .font_start_addr = STI_PTR(font->raw), .index = c_index(sti, c), .fg_color = c_fg(sti, c), .bg_color = c_bg(sti, c), - .dest_x = x * sti->font_width, - .dest_y = y * sti->font_height, + .dest_x = x * font->width, + .dest_y = y * font->height, }; struct sti_font_outptr *outptr = &sti->sti_data->font_outptr; s32 ret; @@ -193,18 +196,18 @@ sti_set(struct sti_struct *sti, int src_y, int src_x, void sti_clear(struct sti_struct *sti, int src_y, int src_x, - int height, int width, int c) + int height, int width, int c, struct sti_cooked_font *font) { 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, - .src_y = src_y * sti->font_height, - .dest_x = src_x * sti->font_width, - .dest_y = src_y * sti->font_height, - .width = width * sti->font_width, - .height = height* sti->font_height, + .src_x = src_x * font->width, + .src_y = src_y * font->height, + .dest_x = src_x * font->width, + .dest_y = src_y * font->height, + .width = width * font->width, + .height = height * font->height, }; struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr; s32 ret; @@ -225,16 +228,17 @@ static const struct sti_blkmv_flags default_blkmv_flags = { void sti_bmove(struct sti_struct *sti, int src_y, int src_x, - int dst_y, int dst_x, int height, int width) + int dst_y, int dst_x, int height, int width, + struct sti_cooked_font *font) { 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, - .dest_y = dst_y * sti->font_height, - .width = width * sti->font_width, - .height = height* sti->font_height, + .src_x = src_x * font->width, + .src_y = src_y * font->height, + .dest_x = dst_x * font->width, + .dest_y = dst_y * font->height, + .width = width * font->width, + .height = height * font->height, }; struct sti_blkmv_outptr *outptr = &sti->sti_data->blkmv_outptr; s32 ret; @@ -301,36 +305,32 @@ __setup("sti=", sti_setup); -static char *font_name[MAX_STI_ROMS]; -static int font_index[MAX_STI_ROMS], - font_height[MAX_STI_ROMS], - font_width[MAX_STI_ROMS]; +static char *font_name; +static int font_index, + font_height, + font_width; #ifndef MODULE static int sti_font_setup(char *str) { - char *x; - int i = 0; + /* + * The default font can be selected in various ways. + * a) sti_font=VGA8x16, sti_font=10x20, sti_font=10*20 selects + * an built-in Linux framebuffer font. + * b) sti_font=<index>, where index is (1..x) with 1 selecting + * the first HP STI ROM built-in font.. + */ - /* we accept sti_font=VGA8x16, sti_font=10x20, sti_font=10*20 - * or sti_font=7 style command lines. */ + if (*str >= '0' && *str <= '9') { + char *x; - while (i<MAX_STI_ROMS && str && *str) { - if (*str>='0' && *str<='9') { - if ((x = strchr(str, 'x')) || (x = strchr(str, '*'))) { - font_height[i] = simple_strtoul(str, NULL, 0); - font_width[i] = simple_strtoul(x+1, NULL, 0); - } else { - font_index[i] = simple_strtoul(str, NULL, 0); - } + 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_name[i] = str; /* fb font name */ + font_index = simple_strtoul(str, NULL, 0); } - - if ((x = strchr(str, ','))) - *x++ = 0; - str = x; - - i++; + } else { + font_name = str; /* fb font name */ } return 1; @@ -344,7 +344,7 @@ static int sti_font_setup(char *str) * framebuffer font names (e.g. VGA8x16, SUN22x18). * This is only available if the fonts have been statically compiled * in with e.g. the CONFIG_FONT_8x16 or CONFIG_FONT_SUN12x22 options. - * - sti_font=<number> + * - sti_font=<number> (<number> = 1,2,3,...) * most STI ROMs have built-in HP specific fonts, which can be selected * by giving the desired number to the sticon driver. * NOTE: This number is machine and STI ROM dependend. @@ -364,8 +364,7 @@ static void sti_dump_globcfg(struct sti_glob_cfg *glob_cfg, { struct sti_glob_cfg_ext *cfg; - DPRINTK((KERN_INFO - "%d text planes\n" + pr_debug("%d text planes\n" "%4d x %4d screen resolution\n" "%4d x %4d offscreen\n" "%4d x %4d layout\n" @@ -382,12 +381,11 @@ static void sti_dump_globcfg(struct sti_glob_cfg *glob_cfg, 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)); + glob_cfg->save_addr); /* dump extended cfg */ cfg = PTR_STI((unsigned long)glob_cfg->ext_ptr); - DPRINTK(( KERN_INFO - "monitor %d\n" + pr_debug("monitor %d\n" "in friendly mode: %d\n" "power consumption %d watts\n" "freq ref %d\n" @@ -396,20 +394,19 @@ static void sti_dump_globcfg(struct sti_glob_cfg *glob_cfg, cfg->friendly_boot, cfg->power, cfg->freq_ref, - cfg->sti_mem_addr, sti_mem_request)); + cfg->sti_mem_addr, sti_mem_request); } static void sti_dump_outptr(struct sti_struct *sti) { - DPRINTK((KERN_INFO - "%d bits per pixel\n" + pr_debug("%d bits per pixel\n" "%d used bits\n" "%d planes\n" "attributes %08x\n", 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)); + sti->sti_data->inq_outptr.attributes); } static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, @@ -448,8 +445,7 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, if (offs != PCI_ROM_ADDRESS && (offs < PCI_BASE_ADDRESS_0 || offs > PCI_BASE_ADDRESS_5)) { - printk (KERN_WARNING - "STI pci region mapping for region %d (%02x) can't be mapped\n", + pr_warn("STI pci region mapping for region %d (%02x) can't be mapped\n", i,sti->rm_entry[i]); continue; } @@ -464,14 +460,14 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, if (len) glob_cfg->region_ptrs[i] = sti->regions_phys[i]; - DPRINTK(("region #%d: phys %08lx, region_ptr %08x, len=%lukB, " + pr_debug("region #%d: phys %08lx, region_ptr %08x, len=%lukB, " "btlb=%d, sysonly=%d, cache=%d, last=%d\n", i, sti->regions_phys[i], glob_cfg->region_ptrs[i], len/1024, sti->regions[i].region_desc.btlb, sti->regions[i].region_desc.sys_only, sti->regions[i].region_desc.cache, - sti->regions[i].region_desc.last)); + sti->regions[i].region_desc.last); /* last entry reached ? */ if (sti->regions[i].region_desc.last) @@ -479,8 +475,8 @@ static int sti_init_glob_cfg(struct sti_struct *sti, unsigned long rom_address, } if (++i<8 && sti->regions[i].region) - printk(KERN_WARNING "%s: *future ptr (0x%8x) not yet supported !\n", - __FILE__, sti->regions[i].region); + pr_warn("future ptr (0x%8x) not yet supported !\n", + sti->regions[i].region); glob_cfg_ext->sti_mem_addr = STI_PTR(sti_mem_addr); @@ -538,6 +534,7 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) } cooked_font->raw = nf; + cooked_font->raw_ptr = nf; cooked_font->next_font = NULL; cooked_rom->font_start = cooked_font; @@ -552,24 +549,38 @@ sti_select_fbfont(struct sti_cooked_rom *cooked_rom, const char *fbfont_name) } #endif -static struct sti_cooked_font *sti_select_font(struct sti_cooked_rom *rom, - int (*search_font_fnc)(struct sti_cooked_rom *, int, int)) +static int 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 *sti_select_font(struct sti_cooked_rom *rom) { 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_index) { + font = sti_select_fbfont(rom, font_name); + if (font) + return font; + } - if (font_width[index] && font_height[index]) - font_index[index] = search_font_fnc(rom, - font_height[index], font_width[index]); + if (font_width && font_height) + font_index = sti_search_font(rom, + font_height, font_width); - for (font = rom->font_start, i = font_index[index]; - font && (i > 0); - font = font->next_font, i--); + for (font = rom->font_start, i = font_index - 1; + font && (i > 0); + font = font->next_font, i--); if (font) return font; @@ -578,20 +589,35 @@ static struct sti_cooked_font *sti_select_font(struct sti_cooked_rom *rom, } -static void sti_dump_rom(struct sti_rom *rom) +static void sti_dump_rom(struct sti_struct *sti) { - printk(KERN_INFO " id %04x-%04x, conforms to spec rev. %d.%02x\n", + struct sti_rom *rom = sti->rom->raw; + struct sti_cooked_font *font_start; + int nr; + + pr_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)); + pr_debug(" supports %d monitors\n", rom->num_mons); + pr_debug(" font start %08x\n", rom->font_start); + pr_debug(" region list %08x\n", rom->region_list); + pr_debug(" init_graph %08x\n", rom->init_graph); + pr_debug(" bus support %02x\n", rom->bus_support); + pr_debug(" ext bus support %02x\n", rom->ext_bus_support); + pr_debug(" alternate code type %d\n", rom->alt_code_type); + + font_start = sti->rom->font_start; + nr = 0; + while (font_start) { + struct sti_rom_font *f = font_start->raw; + + pr_info(" built-in font #%d: size %dx%d, chars %d-%d, bpc %d\n", ++nr, + f->width, f->height, + f->first_char, f->last_char, f->bytes_per_char); + font_start = font_start->next_font; + } } @@ -628,39 +654,34 @@ static int sti_cook_fonts(struct sti_cooked_rom *cooked_rom, return 1; } - -static int 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 0x50 -static void *sti_bmode_font_raw(struct sti_cooked_font *f) +void sti_font_convert_bytemode(struct sti_struct *sti, struct sti_cooked_font *f) { unsigned char *n, *p, *q; - int size = f->raw->bytes_per_char*256+sizeof(struct sti_rom_font); - + int size = f->raw->bytes_per_char * 256 + sizeof(struct sti_rom_font); + struct sti_rom_font *old_font; + + if (sti->wordmode) + return; + + old_font = f->raw_ptr; n = kcalloc(4, size, STI_LOWMEM); + f->raw_ptr = n; if (!n) - return NULL; + return; p = n + 3; - q = (unsigned char *)f->raw; + q = (unsigned char *) f->raw; while (size--) { *p = *q++; - p+=4; + p += 4; } - return n + 3; + /* store new ptr to byte-mode font and delete old font */ + f->raw = (struct sti_rom_font *) (n + 3); + kfree(old_font); } +EXPORT_SYMBOL(sti_font_convert_bytemode); static void sti_bmode_rom_copy(unsigned long base, unsigned long count, void *dest) @@ -747,7 +768,7 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti, goto out_err; if (!sti_cook_fonts(cooked, raw)) { - printk(KERN_ERR "No font found for STI at %08lx\n", address); + pr_warn("No font found for STI at %08lx\n", address); goto out_err; } @@ -756,7 +777,8 @@ static int 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", + pr_info("STI %s ROM supports 32 %sbit firmware functions.\n", + wordmode ? "word mode" : "byte mode", raw->alt_code_type == ALT_CODE_TYPE_PA_RISC_64 ? "and 64 " : ""); @@ -767,18 +789,17 @@ static int sti_read_rom(int wordmode, struct sti_struct *sti, 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_dump_rom(sti); + + sti->wordmode = wordmode; + sti->font = sti_select_font(sti->rom); + sti->font->width = sti->font->raw->width; + sti->font->height = sti->font->raw->height; + sti_font_convert_bytemode(sti, 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); /* check if the ROM routines in this card are compatible */ if (wordmode || sti->graphics_id[1] != 0x09A02587) @@ -804,9 +825,9 @@ ok: return 1; msg_not_supported: - printk(KERN_ERR "Sorry, this GSC/STI card is not yet supported.\n"); - printk(KERN_ERR "Please see http://parisc-linux.org/faq/" - "graphics-howto.html for more info.\n"); + pr_warn("Sorry, this GSC/STI card is not yet supported.\n"); + pr_warn("Please see https://parisc.wiki.kernel.org/" + "index.php/Graphics_howto for more info.\n"); /* fall through */ out_err: kfree(raw); @@ -823,7 +844,7 @@ static struct sti_struct *sti_try_rom_generic(unsigned long address, u32 sig; if (num_sti_roms >= MAX_STI_ROMS) { - printk(KERN_WARNING "maximum number of STI ROMS reached !\n"); + pr_warn("maximum number of STI ROMS reached !\n"); return NULL; } @@ -849,16 +870,15 @@ test_rom: 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); + pr_warn("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)); + pr_debug("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 */ @@ -867,29 +887,24 @@ test_rom: *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)); + pr_debug("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)); + pr_debug(" 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)); + pr_debug(" word mode ROM at %08lx, hpa at %08lx\n", + address, hpa); ok = sti_read_rom(1, sti, address); } @@ -906,7 +921,7 @@ test_rom: 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")); + pr_debug("STI PCI ROM disabled\n"); } if (sti_init_graph(sti)) @@ -981,14 +996,14 @@ static int sticore_pci_init(struct pci_dev *pd, const struct pci_device_id *ent) 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)); + pr_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", + pr_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)); + pr_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) { @@ -998,8 +1013,7 @@ static int sticore_pci_init(struct pci_dev *pd, const struct pci_device_id *ent) } if (!sti) { - printk(KERN_WARNING "Unable to handle STI device '%s'\n", - pci_name(pd)); + pr_warn("Unable to handle STI device '%s'\n", pci_name(pd)); return -ENODEV; } #endif /* CONFIG_PCI */ @@ -1058,7 +1072,7 @@ static void sti_init_roms(void) sticore_initialized = 1; - printk(KERN_INFO "STI GSC/PCI core graphics driver " + pr_info("STI GSC/PCI core graphics driver " STI_DRIVERVERSION "\n"); /* Register drivers for native & PCI cards */ diff --git a/drivers/video/fbdev/sticore.h b/drivers/video/fbdev/sticore.h index fb8f58f9867a..c338f7848ae2 100644 --- a/drivers/video/fbdev/sticore.h +++ b/drivers/video/fbdev/sticore.h @@ -4,12 +4,6 @@ /* generic STI structures & functions */ -#if 0 -#define DPRINTK(x) printk x -#else -#define DPRINTK(x) -#endif - #define MAX_STI_ROMS 4 /* max no. of ROMs which this driver handles */ #define STI_REGION_MAX 8 /* hardcoded STI constants */ @@ -246,8 +240,12 @@ struct sti_rom_font { /* sticore internal font handling */ struct sti_cooked_font { - struct sti_rom_font *raw; + struct sti_rom_font *raw; /* native ptr for STI functions */ + void *raw_ptr; /* kmalloc'ed font data */ struct sti_cooked_font *next_font; + int height, width; + int refcount; + u32 crc; }; struct sti_cooked_rom { @@ -341,9 +339,6 @@ struct sti_all_data { struct sti_struct { spinlock_t lock; - /* the following fields needs to be filled in by the word/byte routines */ - int font_width; - int font_height; /* char **mon_strings; */ int sti_mem_request; u32 graphics_id[2]; @@ -362,6 +357,7 @@ struct sti_struct { struct sti_glob_cfg *glob_cfg; /* points into sti_all_data */ + int wordmode; struct sti_cooked_font *font; /* ptr to selected font (cooked) */ struct pci_dev *pd; @@ -380,6 +376,7 @@ struct sti_struct { /* sticore interface functions */ struct sti_struct *sti_get_rom(unsigned int index); /* 0: default sti */ +void sti_font_convert_bytemode(struct sti_struct *sti, struct sti_cooked_font *f); /* sticore main function to call STI firmware */ @@ -391,12 +388,14 @@ int sti_call(const struct sti_struct *sti, unsigned long func, /* functions to call the STI ROM directly */ -void sti_putc(struct sti_struct *sti, int c, int y, int x); +void sti_putc(struct sti_struct *sti, int c, int y, int x, + struct sti_cooked_font *font); void sti_set(struct sti_struct *sti, int src_y, int src_x, - int height, int width, u8 color); + int height, int width, u8 color); void sti_clear(struct sti_struct *sti, int src_y, int src_x, - int height, int width, int c); + int height, int width, int c, struct sti_cooked_font *font); void sti_bmove(struct sti_struct *sti, int src_y, int src_x, - int dst_y, int dst_x, int height, int width); + int dst_y, int dst_x, int height, int width, + struct sti_cooked_font *font); #endif /* STICORE_H */ diff --git a/tools/arch/parisc/include/uapi/asm/mman.h b/tools/arch/parisc/include/uapi/asm/mman.h index f9fd1325f5bd..506c06a6536f 100644 --- a/tools/arch/parisc/include/uapi/asm/mman.h +++ b/tools/arch/parisc/include/uapi/asm/mman.h @@ -39,6 +39,5 @@ #define MADV_SOFT_OFFLINE 101 /* MAP_32BIT is undefined on parisc, fix it for perf */ #define MAP_32BIT 0 -/* MAP_UNINITIALIZED is undefined on parisc, fix it for perf */ #define MAP_UNINITIALIZED 0 #endif |