Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 025a2215 authored by Jay Estabrook's avatar Jay Estabrook Committed by Linus Torvalds
Browse files

ALPHA: support graphics on non-zero PCI domains



This code replaces earlier and incomplete handling of graphics on non-zero PCI
domains (aka hoses or peer PCI buses).

An option (CONFIG_VGA_HOSE) is set TRUE if configuring a GENERIC kernel, or a
kernel for MARVEL, TITAN, or TSUNAMI machines, as these are the machines whose
SRM consoles are capable of configuring and handling graphics options on
non-zero hoses.  All other machines have the option set FALSE.

A routine, "find_console_vga_hose()", is used to find the graphics device
which the machine's firmware believes is the console device, and it sets a
global (pci_vga_hose) for later use in managing access to the device.  This is
called in "init_arch" on TITAN and TSUNAMI machines; MARVEL machines use a
custom version of this routine because of extra complexity.

A routine, "locate_and_init_vga()", is used to find the graphics device and
set a global (pci_vga_hose) for later use in managing access to the device, in
the case where "find_console_vga_hose" has failed.

Various adjustments are made to the ioremap and ioportmap routines for
detecting and translating "legacy" VGA register and memory references to the
real PCI domain.

[akpm@linux-foundation.org: don't statically init bss]
[akpm@linux-foundation.org: build fix]
Signed-off-by: default avatarJay Estabrook <jay.estabrook@hp.com>
Signed-off-by: default avatarIvan Kokshaysky <ink@jurassic.park.msu.ru>
Cc: Richard Henderson <rth@twiddle.net>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 8778beb9
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -481,6 +481,15 @@ config ALPHA_BROKEN_IRQ_MASK
	depends on ALPHA_GENERIC || ALPHA_PC164
	default y

config VGA_HOSE
	bool
	depends on ALPHA_GENERIC || ALPHA_TITAN || ALPHA_MARVEL || ALPHA_TSUNAMI
	default y
	help
	  Support VGA on an arbitrary hose; needed for several platforms
	  which always have multiple hoses, and whose consoles support it.


config ALPHA_SRM
	bool "Use SRM as bootloader" if ALPHA_CABRIOLET || ALPHA_AVANTI_CH || ALPHA_EB64P || ALPHA_PC164 || ALPHA_TAKARA || ALPHA_EB164 || ALPHA_ALCOR || ALPHA_MIATA || ALPHA_LX164 || ALPHA_SX164 || ALPHA_NAUTILUS || ALPHA_NONAME
	default y if ALPHA_JENSEN || ALPHA_MIKASA || ALPHA_SABLE || ALPHA_LYNX || ALPHA_NORITAKE || ALPHA_DP264 || ALPHA_RAWHIDE || ALPHA_EIGER || ALPHA_WILDFIRE || ALPHA_TITAN || ALPHA_SHARK || ALPHA_MARVEL
@@ -644,6 +653,13 @@ source "arch/alpha/oprofile/Kconfig"

source "arch/alpha/Kconfig.debug"

# DUMMY_CONSOLE may be defined in drivers/video/console/Kconfig
# but we also need it if VGA_HOSE is set
config DUMMY_CONSOLE
	bool
	depends on VGA_HOSE
	default y

source "security/Kconfig"

source "crypto/Kconfig"
+48 −22
Original line number Diff line number Diff line
@@ -9,16 +9,20 @@
#include <linux/init.h>
#include <linux/tty.h>
#include <linux/console.h>
#include <linux/vt.h>
#include <asm/vga.h>
#include <asm/machvec.h>

#include "pci_impl.h"

#ifdef CONFIG_VGA_HOSE

/*
 * Externally-visible vga hose bases
 */
unsigned long __vga_hose_io_base = 0;	/* base for default hose */
unsigned long __vga_hose_mem_base = 0;	/* base for default hose */
struct pci_controller *pci_vga_hose;
static struct resource alpha_vga = {
	.name	= "alpha-vga+",
	.start	= 0x3C0,
	.end	= 0x3DF
};

static struct pci_controller * __init 
default_vga_hose_select(struct pci_controller *h1, struct pci_controller *h2)
@@ -29,37 +33,59 @@ default_vga_hose_select(struct pci_controller *h1, struct pci_controller *h2)
	return h1;
}

void __init 
set_vga_hose(struct pci_controller *hose)
{
	if (hose) {
		__vga_hose_io_base = hose->io_space->start;
		__vga_hose_mem_base = hose->mem_space->start;
	}
}

void __init 
locate_and_init_vga(void *(*sel_func)(void *, void *))
{
	struct pci_controller *hose = NULL;
	struct pci_dev *dev = NULL;

	/* Default the select function */
	if (!sel_func) sel_func = (void *)default_vga_hose_select;

	/* Find the console VGA device */
	for(dev=NULL; (dev=pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, dev));) {
		if (!hose) hose = dev->sysdata;
		else hose = sel_func(hose, dev->sysdata);
		if (!hose)
			hose = dev->sysdata;
		else
			hose = sel_func(hose, dev->sysdata);
	}

	/* Did we already inititialize the correct one? */
	if (conswitchp == &vga_con &&
	    __vga_hose_io_base == hose->io_space->start &&
	    __vga_hose_mem_base == hose->mem_space->start)
	/* Did we already initialize the correct one? Is there one? */
	if (!hose || (conswitchp == &vga_con && pci_vga_hose == hose))
		return;

	/* Set the VGA hose and init the new console */
	set_vga_hose(hose);
	/* Create a new VGA ioport resource WRT the hose it is on. */
	alpha_vga.start += hose->io_space->start;
	alpha_vga.end += hose->io_space->start;
	request_resource(hose->io_space, &alpha_vga);

	/* Set the VGA hose and init the new console. */
	pci_vga_hose = hose;
	take_over_console(&vga_con, 0, MAX_NR_CONSOLES-1, 1);
}

void __init
find_console_vga_hose(void)
{
	u64 *pu64 = (u64 *)((u64)hwrpb + hwrpb->ctbt_offset);

	if (pu64[7] == 3) {	/* TERM_TYPE == graphics */
		struct pci_controller *hose;
		int h = (pu64[30] >> 24) & 0xff;	/* console hose # */

		/*
		 * Our hose numbering DOES match the console's, so find
		 * the right one...
		 */
		for (hose = hose_head; hose; hose = hose->next) {
			if (hose->index == h) break;
		}

		if (hose) {
			printk("Console graphics on hose %d\n", h);
			pci_vga_hose = hose;
		}
	}
}

#endif
+17 −26
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
#include <asm/rtc.h>
#include <asm/vga.h>

#include "proto.h"
#include "pci_impl.h"
@@ -367,9 +368,8 @@ marvel_io7_present(gct6_node *node)
}

static void __init
marvel_init_vga_hose(void)
marvel_find_console_vga_hose(void)
{
#ifdef CONFIG_VGA_HOSE
	u64 *pu64 = (u64 *)((u64)hwrpb + hwrpb->ctbt_offset);

	if (pu64[7] == 3) {	/* TERM_TYPE == graphics */
@@ -403,7 +403,6 @@ marvel_init_vga_hose(void)
			pci_vga_hose = hose;
		}
	}
#endif /* CONFIG_VGA_HOSE */
}

gct6_search_struct gct_wanted_node_list[] = {
@@ -459,7 +458,7 @@ marvel_init_arch(void)
		marvel_init_io7(io7);

	/* Check for graphic console location (if any).  */
	marvel_init_vga_hose();
	marvel_find_console_vga_hose();
}

void
@@ -684,9 +683,6 @@ __marvel_rtc_io(u8 b, unsigned long addr, int write)
/*
 * IO map support.
 */

#define __marvel_is_mem_vga(a)	(((a) >= 0xa0000) && ((a) <= 0xc0000))

void __iomem *
marvel_ioremap(unsigned long addr, unsigned long size)
{
@@ -698,13 +694,9 @@ marvel_ioremap(unsigned long addr, unsigned long size)
	unsigned long pfn;

	/*
	 * Adjust the addr.
	 * Adjust the address.
	 */ 
#ifdef CONFIG_VGA_HOSE
	if (pci_vga_hose && __marvel_is_mem_vga(addr)) {
		addr += pci_vga_hose->mem_space->start;
	}
#endif
	FIXUP_MEMADDR_VGA(addr);

	/*
	 * Find the hose.
@@ -781,7 +773,9 @@ marvel_ioremap(unsigned long addr, unsigned long size)
		return (void __iomem *) vaddr;
	}

	return NULL;
	/* Assume it was already a reasonable address */
	vaddr = baddr + hose->mem_space->start;
	return (void __iomem *) vaddr;
}

void
@@ -803,21 +797,12 @@ marvel_is_mmio(const volatile void __iomem *xaddr)
		return (addr & 0xFF000000UL) == 0;
}

#define __marvel_is_port_vga(a)	\
  (((a) >= 0x3b0) && ((a) < 0x3e0) && ((a) != 0x3b3) && ((a) != 0x3d3))
#define __marvel_is_port_kbd(a)	(((a) == 0x60) || ((a) == 0x64))
#define __marvel_is_port_rtc(a)	(((a) == 0x70) || ((a) == 0x71))

void __iomem *marvel_ioportmap (unsigned long addr)
{
	if (__marvel_is_port_rtc (addr) || __marvel_is_port_kbd(addr))
		;
#ifdef CONFIG_VGA_HOSE
	else if (__marvel_is_port_vga (addr) && pci_vga_hose)
		addr += pci_vga_hose->io_space->start;
#endif
	else
		return NULL;
	FIXUP_IOADDR_VGA(addr);
	return (void __iomem *)addr;
}

@@ -829,8 +814,14 @@ marvel_ioread8(void __iomem *xaddr)
		return 0;
	else if (__marvel_is_port_rtc(addr))
		return __marvel_rtc_io(0, addr, 0);
	else
	else if (marvel_is_ioaddr(addr))
		return __kernel_ldbu(*(vucp)addr);
	else
		/* this should catch other legacy addresses
		   that would normally fail on MARVEL,
		   because there really is nothing there...
		*/
		return ~0;
}

void
@@ -841,7 +832,7 @@ marvel_iowrite8(u8 b, void __iomem *xaddr)
		return;
	else if (__marvel_is_port_rtc(addr)) 
		__marvel_rtc_io(b, addr, 1);
	else
	else if (marvel_is_ioaddr(addr))
		__kernel_stb(b, *(vucp)addr);
}

+30 −40
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@
#include <asm/smp.h>
#include <asm/pgalloc.h>
#include <asm/tlbflush.h>
#include <asm/vga.h>

#include "proto.h"
#include "pci_impl.h"
@@ -34,6 +35,11 @@ struct
	unsigned long tba[4];
} saved_config[4] __attribute__((common));

/*
 * Is PChip 1 present? No need to query it more than once.
 */
static int titan_pchip1_present;

/*
 * BIOS32-style PCI interface:
 */
@@ -344,43 +350,17 @@ titan_init_one_pachip_port(titan_pachip_port *port, int index)
static void __init
titan_init_pachips(titan_pachip *pachip0, titan_pachip *pachip1)
{
	int pchip1_present = TITAN_cchip->csc.csr & 1L<<14;
	titan_pchip1_present = TITAN_cchip->csc.csr & 1L<<14;

	/* Init the ports in hose order... */
	titan_init_one_pachip_port(&pachip0->g_port, 0);	/* hose 0 */
	if (pchip1_present)
	if (titan_pchip1_present)
		titan_init_one_pachip_port(&pachip1->g_port, 1);/* hose 1 */
	titan_init_one_pachip_port(&pachip0->a_port, 2);	/* hose 2 */
	if (pchip1_present)
	if (titan_pchip1_present)
		titan_init_one_pachip_port(&pachip1->a_port, 3);/* hose 3 */
}

static void __init
titan_init_vga_hose(void)
{
#ifdef CONFIG_VGA_HOSE
	u64 *pu64 = (u64 *)((u64)hwrpb + hwrpb->ctbt_offset);

	if (pu64[7] == 3) {	/* TERM_TYPE == graphics */
		struct pci_controller *hose;
		int h = (pu64[30] >> 24) & 0xff;	/* console hose # */

		/*
		 * Our hose numbering matches the console's, so just find
		 * the right one...
		 */
		for (hose = hose_head; hose; hose = hose->next) {
			if (hose->index == h) break;
		}

		if (hose) {
			printk("Console graphics on hose %d\n", hose->index);
			pci_vga_hose = hose;
		}
	}
#endif /* CONFIG_VGA_HOSE */
}

void __init
titan_init_arch(void)
{
@@ -406,6 +386,7 @@ titan_init_arch(void)

	/* With multiple PCI busses, we play with I/O as physical addrs.  */
	ioport_resource.end = ~0UL;
	iomem_resource.end = ~0UL;

	/* PCI DMA Direct Mapping is 1GB at 2GB.  */
	__direct_map_base = 0x80000000;
@@ -415,7 +396,7 @@ titan_init_arch(void)
	titan_init_pachips(TITAN_pachip0, TITAN_pachip1);

	/* Check for graphic console location (if any).  */
	titan_init_vga_hose();
	find_console_vga_hose();
}

static void
@@ -441,9 +422,7 @@ titan_kill_one_pachip_port(titan_pachip_port *port, int index)
static void
titan_kill_pachips(titan_pachip *pachip0, titan_pachip *pachip1)
{
	int pchip1_present = TITAN_cchip->csc.csr & 1L<<14;

	if (pchip1_present) {
	if (titan_pchip1_present) {
		titan_kill_one_pachip_port(&pachip1->g_port, 1);
		titan_kill_one_pachip_port(&pachip1->a_port, 3);
	}
@@ -462,6 +441,14 @@ titan_kill_arch(int mode)
 * IO map support.
 */

void __iomem *
titan_ioportmap(unsigned long addr)
{
	FIXUP_IOADDR_VGA(addr);
	return (void __iomem *)(addr + TITAN_IO_BIAS);
}


void __iomem *
titan_ioremap(unsigned long addr, unsigned long size)
{
@@ -475,14 +462,12 @@ titan_ioremap(unsigned long addr, unsigned long size)
	unsigned long pfn;

	/*
	 * Adjust the addr.
	 * Adjust the address and hose, if necessary.
	 */ 
#ifdef CONFIG_VGA_HOSE
	if (pci_vga_hose && __titan_is_mem_vga(addr)) {
	if (pci_vga_hose && __is_mem_vga(addr)) {
		h = pci_vga_hose->index;
		addr += pci_vga_hose->mem_space->start;
	}
#endif

	/*
	 * Find the hose.
@@ -521,8 +506,10 @@ titan_ioremap(unsigned long addr, unsigned long size)
		 * Map it
		 */
		area = get_vm_area(size, VM_IOREMAP);
		if (!area)
		if (!area) {
			printk("ioremap failed... no vm_area...\n");
			return NULL;
		}

		ptes = hose->sg_pci->ptes;
		for (vaddr = (unsigned long)area->addr; 
@@ -539,7 +526,7 @@ titan_ioremap(unsigned long addr, unsigned long size)
			if (__alpha_remap_area_pages(vaddr,
						     pfn << PAGE_SHIFT, 
						     PAGE_SIZE, 0)) {
				printk("FAILED to map...\n");
				printk("FAILED to remap_area_pages...\n");
				vfree(area->addr);
				return NULL;
			}
@@ -551,7 +538,8 @@ titan_ioremap(unsigned long addr, unsigned long size)
		return (void __iomem *) vaddr;
	}

	return NULL;
	/* Assume a legacy (read: VGA) address, and return appropriately. */
	return (void __iomem *)(addr + TITAN_MEM_BIAS);
}

void
@@ -574,6 +562,7 @@ titan_is_mmio(const volatile void __iomem *xaddr)
}

#ifndef CONFIG_ALPHA_GENERIC
EXPORT_SYMBOL(titan_ioportmap);
EXPORT_SYMBOL(titan_ioremap);
EXPORT_SYMBOL(titan_iounmap);
EXPORT_SYMBOL(titan_is_mmio);
@@ -750,6 +739,7 @@ titan_agp_info(void)
	if (titan_query_agp(port))
		hosenum = 2;
	if (hosenum < 0 && 
	    titan_pchip1_present &&
	    titan_query_agp(port = &TITAN_pachip1->a_port)) 
		hosenum = 3;
	
+24 −0
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@

#include <asm/ptrace.h>
#include <asm/smp.h>
#include <asm/vga.h>

#include "proto.h"
#include "pci_impl.h"
@@ -349,6 +350,26 @@ tsunami_init_one_pchip(tsunami_pchip *pchip, int index)
	tsunami_pci_tbi(hose, 0, -1);
}


void __iomem *
tsunami_ioportmap(unsigned long addr)
{
	FIXUP_IOADDR_VGA(addr);
	return (void __iomem *)(addr + TSUNAMI_IO_BIAS);
}

void __iomem *
tsunami_ioremap(unsigned long addr, unsigned long size)
{
	FIXUP_MEMADDR_VGA(addr);
	return (void __iomem *)(addr + TSUNAMI_MEM_BIAS);
}

#ifndef CONFIG_ALPHA_GENERIC
EXPORT_SYMBOL(tsunami_ioportmap);
EXPORT_SYMBOL(tsunami_ioremap);
#endif

void __init
tsunami_init_arch(void)
{
@@ -393,6 +414,9 @@ tsunami_init_arch(void)
	tsunami_init_one_pchip(TSUNAMI_pchip0, 0);
	if (TSUNAMI_cchip->csc.csr & 1L<<14)
		tsunami_init_one_pchip(TSUNAMI_pchip1, 1);

	/* Check for graphic console location (if any).  */
	find_console_vga_hose();
}

static void
Loading