Merge branch 'parisc-5.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux

Pull parisc updates from Helge Deller:

 - Added fw_cfg support for parisc on qemu

 - Added font support in sti text console driver for byte- and word-mode
   ROMs

 - Switch to more fine grained lws locks and improve spinlock handling

 - Add ioread64_hi_lo() and iowrite64_hi_lo() to avoid 0-day linking
   errors

 - Mark pointers volatile in __xchg8(), __xchg32() and __xchg64() to
   help compiler

 - Header file cleanups, mostly removal of unused HP-UX compat defines

 - Drop one bit from our O_NONBLOCK define to become now 000200000

 - Add MAP_UNINITIALIZED define to avoid userspace compile errors

 - Drop CONFIG_IDE from defconfigs

 - Speed up synchronize_caches() on UP machines

 - Rewrite tlb flush threshold calculation

 - Comment fixes and cleanups

* 'parisc-5.10-1' of git://git.kernel.org/pub/scm/linux/kernel/git/deller/parisc-linux:
  parisc/sticon: Add user font support
  parisc/sticon: Always register sticon console driver
  parisc: Add MAP_UNINITIALIZED define
  parisc: Improve spinlock handling
  parisc: Install vmlinuz instead of zImage file
  parisc: Rewrite tlb flush threshold calculation
  parisc: Switch to more fine grained lws locks
  parisc: Mark pointers volatile in __xchg8(), __xchg32() and __xchg64()
  parisc: Fix comments and enable interrupts later
  parisc: Add alternative patching to synchronize_caches define
  parisc: Add ioread64_hi_lo() and iowrite64_hi_lo()
  parisc: disable CONFIG_IDE in defconfigs
  parisc: Drop useless comments in uapi/asm/signal.h
  parisc: Define O_NONBLOCK to become 000200000
  parisc: Drop HP-UX specific fcntl and signal flags
  parisc: Avoid external interrupts when IPI finishes
  parisc: Add qemu fw_cfg interface
  fw_cfg: Add support for parisc architecture
This commit is contained in:
Linus Torvalds 2020-10-15 15:42:55 -07:00
Родитель 578a7155c5 7ff3f14ddc
Коммит 7286d2a37e
26 изменённых файлов: 453 добавлений и 346 удалений

Просмотреть файл

@ -375,5 +375,6 @@ config KEXEC_FILE
endmenu
source "drivers/firmware/Kconfig"
source "drivers/parisc/Kconfig"

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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)

Просмотреть файл

@ -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;

Просмотреть файл

@ -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);

Просмотреть файл

@ -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

Просмотреть файл

@ -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;
}
/*

Просмотреть файл

@ -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

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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);
}

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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
}

Просмотреть файл

@ -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;

Просмотреть файл

@ -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

Просмотреть файл

@ -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;

Просмотреть файл

@ -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);

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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

Просмотреть файл

@ -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,28 +55,16 @@
#define BLANK 0
static int vga_is_gfx;
#define STI_DEF_FONT sticon_sti->font
/* borrowed from fbcon.c */
#define FNTREFCOUNT(fd) (fd->refcount)
#define FNTCRC(fd) (fd->crc)
static struct sti_cooked_font *font_data[MAX_NR_CONSOLES];
/* 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)
static int vbl_cursor_cnt;
static inline void cursor_undrawn(void)
{
vbl_cursor_cnt = 0;
cursor_drawn = 0;
}
static const char *sticon_startup(void)
{
return "STI console";
@ -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);

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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 */

Просмотреть файл

@ -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