Commit 136e336b authored by Matthew Wilcox's avatar Matthew Wilcox Committed by Linus Torvalds

[PATCH] drivers/parisc

This huge patch moves a bunch of drivers from arch/parisc/kernel to
drivers/parisc and adds some new drivers in drivers/parisc.
parent 5088d993
# HP 712 kernel keymap. This uses 7 modifier combinations.
keymaps 0-2,4-5,8,12
# ie, plain, Shift, AltGr, Control, Control+Shift, Alt and Control+Alt
# Change the above line into
# keymaps 0-2,4-6,8,12
# in case you want the entries
# altgr control keycode 83 = Boot
# altgr control keycode 111 = Boot
# below.
#
# In fact AltGr is used very little, and one more keymap can
# be saved by mapping AltGr to Alt (and adapting a few entries):
# keycode 100 = Alt
#
keycode 1 = F9 F19 Console_21
control keycode 1 = F9
alt keycode 1 = Console_9
control alt keycode 1 = Console_9
keycode 2 =
keycode 3 = F5 F15 Console_17
control keycode 3 = F5
alt keycode 3 = Console_5
control alt keycode 3 = Console_5
keycode 4 = F3 F13 Console_15
control keycode 4 = F3
alt keycode 4 = Console_3
control alt keycode 4 = Console_3
keycode 5 = F1 F11 Console_13
control keycode 5 = F1
alt keycode 5 = Console_1
control alt keycode 5 = Console_1
keycode 6 = F2 F12 Console_14
control keycode 6 = F2
alt keycode 6 = Console_2
control alt keycode 6 = Console_2
keycode 7 = F12 F12 Console_24
control keycode 7 = F12
alt keycode 7 = Console_12
control alt keycode 7 = Console_12
keycode 8 =
keycode 9 = F10 F20 Console_22
control keycode 9 = F10
alt keycode 9 = Console_10
control alt keycode 9 = Console_10
keycode 10 = F8 F18 Console_20
control keycode 10 = F8
alt keycode 10 = Console_8
control alt keycode 10 = Console_8
keycode 11 = F6 F16 Console_18
control keycode 11 = F6
alt keycode 11 = Console_6
control alt keycode 11 = Console_6
keycode 12 = F4 F14 Console_16
control keycode 12 = F4
alt keycode 12 = Console_4
control alt keycode 12 = Console_4
keycode 13 = Tab Tab
alt keycode 13 = Meta_Tab
keycode 14 = grave asciitilde
control keycode 14 = nul
alt keycode 14 = Meta_grave
keycode 15 =
keycode 16 =
keycode 17 = Alt
keycode 18 = Shift
keycode 19 =
keycode 20 = Control
keycode 21 = q
keycode 22 = one exclam exclam
keycode 23 =
keycode 24 =
keycode 25 =
keycode 26 = z
keycode 27 = s
keycode 28 = a
altgr keycode 28 = Hex_A
keycode 29 = w
keycode 30 = two at at
keycode 31 =
keycode 32 =
keycode 33 = c
altgr keycode 46 = Hex_C
keycode 34 = x
keycode 35 = d
altgr keycode 35 = Hex_D
keycode 36 = e
altgr keycode 36 = Hex_E
keycode 37 = four dollar
keycode 38 = three numbersign
keycode 39 =
keycode 40 =
keycode 41 =
keycode 42 = v
keycode 43 = f
altgr keycode 43 = Hex_F
keycode 44 = t
keycode 45 = r
keycode 46 = five percent
keycode 47 =
keycode 48 =
keycode 49 = n
keycode 50 = b
altgr keycode 50 = Hex_B
keycode 51 = h
keycode 52 = g
keycode 53 = y
keycode 54 = six asciicircum
keycode 55 =
keycode 56 =
keycode 57 =
keycode 58 = m
keycode 59 = j
keycode 60 = u
keycode 61 = seven ampersand
keycode 62 = eight asterisk asterisk
keycode 63 =
keycode 64 =
keycode 65 = comma less
alt keycode 65 = Meta_comma
keycode 66 = k
keycode 67 = i
keycode 68 = o
keycode 69 = zero parenright bracketright
keycode 70 = nine parenleft bracketleft
keycode 71 =
keycode 72 =
keycode 73 = period greater
control keycode 73 = Compose
alt keycode 73 = Meta_period
keycode 74 = slash question
control keycode 74 = Delete
alt keycode 53 = Meta_slash
keycode 75 = l
keycode 76 = semicolon colon
alt keycode 39 = Meta_semicolon
keycode 77 = p
keycode 78 = minus underscore
keycode 79 =
keycode 80 =
keycode 81 =
keycode 82 = apostrophe quotedbl
control keycode 82 = Control_g
alt keycode 40 = Meta_apostrophe
keycode 83 =
keycode 84 = bracketleft braceleft
control keycode 84 = Escape
alt keycode 26 = Meta_bracketleft
keycode 85 = equal plus
keycode 86 =
keycode 87 =
keycode 88 = Caps_Lock
keycode 88 =
keycode 89 =
keycode 89 =
keycode 89 =
keycode 90 = Return
alt keycode 90 = Meta_Control_m
keycode 91 = bracketright braceright asciitilde
control keycode 91 = Control_bracketright
alt keycode 91 = Meta_bracketright
keycode 92 =
keycode 93 = backslash bar
control keycode 43 = Control_backslash
alt keycode 43 = Meta_backslash
keycode 94 =
keycode 95 =
keycode 96 =
keycode 97 =
keycode 98 =
keycode 99 =
keycode 100 =
keycode 101 =
keycode 102 = BackSpace
keycode 103 =
keycode 104 =
keycode 105 = KP_1
alt keycode 105 = Ascii_1
altgr keycode 105 = Hex_1
keycode 106 =
keycode 107 = KP_4
alt keycode 107 = Ascii_4
altgr keycode 107 = Hex_4
keycode 108 = KP_7
alt keycode 108 = Ascii_7
altgr keycode 108 = Hex_7
keycode 109 =
keycode 110 =
keycode 111 =
keycode 112 = KP_0
alt keycode 82 = Ascii_0
altgr keycode 82 = Hex_0
keycode 113 = KP_Period
keycode 114 = KP_2
alt keycode 114 = Ascii_2
altgr keycode 114 = Hex_2
keycode 115 = KP_5
alt keycode 115 = Ascii_5
altgr keycode 115 = Hex_5
keycode 116 = KP_6
alt keycode 116 = Ascii_6
altgr keycode 116 = Hex_6
keycode 117 = KP_8
alt keycode 117 = Ascii_8
altgr keycode 117 = Hex_8
keycode 118 = Escape
keycode 119 =
keycode 120 = F11
keycode 121 = KP_Add
keycode 122 = KP_3
alt keycode 122 = Ascii_3
altgr keycode 122 = Hex_3
keycode 123 = KP_Subtract
keycode 124 = KP_Multiply
keycode 125 = KP_9
alt keycode 125 = Ascii_9
altgr keycode 125 = Hex_9
keycode 126 =
# 131!!
keycode 127 = F7 F17 Console_19
control keycode 127 = F7
alt keycode 127 = Console_7
control alt keycode 127 = Console_7
string F1 = "\033[[A"
string F2 = "\033[[B"
string F3 = "\033[[C"
string F4 = "\033[[D"
string F5 = "\033[[E"
string F6 = "\033[17~"
string F7 = "\033[18~"
string F8 = "\033[19~"
string F9 = "\033[20~"
string F10 = "\033[21~"
string F11 = "\033[23~"
string F12 = "\033[24~"
string F13 = "\033[25~"
string F14 = "\033[26~"
string F15 = "\033[28~"
string F16 = "\033[29~"
string F17 = "\033[31~"
string F18 = "\033[32~"
string F19 = "\033[33~"
string F20 = "\033[34~"
string Find = "\033[1~"
string Insert = "\033[2~"
string Remove = "\033[3~"
string Select = "\033[4~"
string Prior = "\033[5~"
string Next = "\033[6~"
string Macro = "\033[M"
string Pause = "\033[P"
compose '`' 'A' to ''
compose '`' 'a' to ''
compose '\'' 'A' to ''
compose '\'' 'a' to ''
compose '^' 'A' to ''
compose '^' 'a' to ''
compose '~' 'A' to ''
compose '~' 'a' to ''
compose '"' 'A' to ''
compose '"' 'a' to ''
compose 'O' 'A' to ''
compose 'o' 'a' to ''
compose '0' 'A' to ''
compose '0' 'a' to ''
compose 'A' 'A' to ''
compose 'a' 'a' to ''
compose 'A' 'E' to ''
compose 'a' 'e' to ''
compose ',' 'C' to ''
compose ',' 'c' to ''
compose '`' 'E' to ''
compose '`' 'e' to ''
compose '\'' 'E' to ''
compose '\'' 'e' to ''
compose '^' 'E' to ''
compose '^' 'e' to ''
compose '"' 'E' to ''
compose '"' 'e' to ''
compose '`' 'I' to ''
compose '`' 'i' to ''
compose '\'' 'I' to ''
compose '\'' 'i' to ''
compose '^' 'I' to ''
compose '^' 'i' to ''
compose '"' 'I' to ''
compose '"' 'i' to ''
compose '-' 'D' to ''
compose '-' 'd' to ''
compose '~' 'N' to ''
compose '~' 'n' to ''
compose '`' 'O' to ''
compose '`' 'o' to ''
compose '\'' 'O' to ''
compose '\'' 'o' to ''
compose '^' 'O' to ''
compose '^' 'o' to ''
compose '~' 'O' to ''
compose '~' 'o' to ''
compose '"' 'O' to ''
compose '"' 'o' to ''
compose '/' 'O' to ''
compose '/' 'o' to ''
compose '`' 'U' to ''
compose '`' 'u' to ''
compose '\'' 'U' to ''
compose '\'' 'u' to ''
compose '^' 'U' to ''
compose '^' 'u' to ''
compose '"' 'U' to ''
compose '"' 'u' to ''
compose '\'' 'Y' to ''
compose '\'' 'y' to ''
compose 'T' 'H' to ''
compose 't' 'h' to ''
compose 's' 's' to ''
compose '"' 'y' to ''
compose 's' 'z' to ''
compose 'i' 'j' to ''
/* arch/parisc/kernel/pdc.c - safe pdc access routines
*
* Copyright 1999 SuSE GmbH Nuernberg (Philipp Rumpf, prumpf@tux.org)
* portions Copyright 1999 The Puffin Group, (Alex deVries, David Kennedy)
*
* only these routines should be used out of the real kernel (i.e. everything
* using virtual addresses) for obvious reasons */
/* I think it would be in everyone's best interest to follow this
* guidelines when writing PDC wrappers:
*
* - the name of the pdc wrapper should match one of the macros
* used for the first two arguments
* - don't use caps for random parts of the name
* - use ASSERT_ALIGN to ensure the aligment of the arguments is
* correct
* - use __pa() to convert virtual (kernel) pointers to physical
* ones.
* - the name of the struct used for pdc return values should equal
* one of the macros used for the first two arguments to the
* corresponding PDC call
* - keep the order of arguments
* - don't be smart (setting trailing NUL bytes for strings, return
* something useful even if the call failed) unless you are sure
* it's not going to affect functionality or performance
*
* Example:
* int pdc_cache_info(struct pdc_cache_info *cache_info )
* {
* ASSERT_ALIGN(cache_info, 8);
*
* return mem_pdc_call(PDC_CACHE,PDC_CACHE_INFO,__pa(cache_info),0);
* }
* prumpf 991016
*/
#include <linux/kernel.h>
#include <linux/string.h>
#include <asm/page.h>
#include <asm/pdc.h>
#include <asm/real.h>
#include <asm/system.h>
#define ASSERT_ALIGN(ptr, align) \
do { if(((unsigned long)(ptr)) & (align-1)) { \
printk("PDC: %s:%d %s() called with " \
"unaligned argument from %p", __FILE__, __LINE__, \
__FUNCTION__, __builtin_return_address(0)); \
\
return -1; \
} } while(0)
/* verify address can be accessed without an HPMC */
int pdc_add_valid(void *address)
{
ASSERT_ALIGN(address, 4);
return mem_pdc_call(PDC_ADD_VALID, PDC_ADD_VALID_VERIFY, (unsigned long)address);
}
#if 0
int pdc_chassis_warn(struct pdc_chassis_warn *address)
{
ASSERT_ALIGN(address, 4);
return mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_WARN, __pa(address), 0);
}
#endif
int pdc_chassis_disp(unsigned long disp)
{
return mem_pdc_call(PDC_CHASSIS, PDC_CHASSIS_DISP, disp);
}
int pdc_chassis_info(void *pdc_result, void *chassis_info, unsigned long len)
{
ASSERT_ALIGN(pdc_result, 4);
ASSERT_ALIGN(chassis_info, 4);
return mem_pdc_call(PDC_CHASSIS,PDC_RETURN_CHASSIS_INFO,
__pa(pdc_result), __pa(chassis_info), len);
}
int pdc_hpa_processor(void *address)
{
/* We're using 0 for the last parameter just to make sure.
It's actually HVERSION dependant. And remember, life is
hard without a backspace. */
ASSERT_ALIGN(address, 4);
return mem_pdc_call(PDC_HPA, PDC_HPA_PROCESSOR, __pa(address),0);
}
#if 0
int pdc_hpa_modules(void *address)
{
return mem_pdc_call(PDC_HPA, PDC_HPA_MODULES, address);
}
#endif
int pdc_iodc_read(void *address, void * hpa, unsigned int index,
void * iodc_data, unsigned int iodc_data_size)
{
ASSERT_ALIGN(address, 4);
ASSERT_ALIGN(iodc_data, 8);
return mem_pdc_call(PDC_IODC, PDC_IODC_READ,
__pa(address), hpa, index, __pa(iodc_data), iodc_data_size);
}
int pdc_system_map_find_mods(void *pdc_mod_info,
void *mod_path, int index)
{
return mem_pdc_call(PDC_SYSTEM_MAP, PDC_FIND_MODULE,
__pa(pdc_mod_info), __pa(mod_path), (long)index);
}
int pdc_model_info(struct pdc_model *model) {
ASSERT_ALIGN(model, 8);
return mem_pdc_call(PDC_MODEL,PDC_MODEL_INFO,__pa(model),0);
}
/* get system model name from PDC ROM (e.g. 9000/715 or 9000/778/B160L) */
int pdc_model_sysmodel(char * name)
{
struct pdc_model_sysmodel sys_model;
int retval;
ASSERT_ALIGN(&sys_model, 8);
ASSERT_ALIGN(name, 4);
sys_model.mod_len = 0;
retval = mem_pdc_call(PDC_MODEL,PDC_MODEL_SYSMODEL,__pa(&sys_model),
OS_ID_HPUX,__pa(name));
if (retval == PDC_RET_OK)
name[sys_model.mod_len] = '\0'; /* add trailing '\0' */
else
name[0] = 0;
return retval;
}
/* id: 0 = cpu revision, 1 = boot-rom-version */
int pdc_model_versions(struct pdc_model_cpuid *cpu_id, int id) {
return mem_pdc_call(PDC_MODEL,PDC_MODEL_VERSIONS,__pa(cpu_id),id);
}
int pdc_model_cpuid(struct pdc_model_cpuid *cpu_id) {
cpu_id->cpuid = 0; /* preset zero (call maybe not implemented!) */
return mem_pdc_call(PDC_MODEL,6,__pa(cpu_id),0); /* 6="return CPU ID" */
}
int pdc_cache_info(struct pdc_cache_info *cache_info) {
ASSERT_ALIGN(cache_info, 8);
return mem_pdc_call(PDC_CACHE,PDC_CACHE_INFO,__pa(cache_info),0);
}
#ifndef __LP64__
int pdc_btlb_info( struct pdc_btlb_info *btlb ) {
int status;
status = mem_pdc_call(PDC_BLOCK_TLB,PDC_BTLB_INFO,__pa(btlb),0);
if (status<0) btlb->max_size = 0;
return status;
}
int pdc_mem_map_hpa(void *r_addr, void *mod_path) {
return mem_pdc_call(PDC_MEM_MAP,PDC_MEM_MAP_HPA,
__pa(r_addr),__pa(mod_path));
}
int pdc_lan_station_id(char *lan_addr, void *net_hpa) {
struct pdc_lan_station_id id;
unsigned char *addr;
if (mem_pdc_call(PDC_LAN_STATION_ID, PDC_LAN_STATION_ID_READ,
__pa(&id), net_hpa) < 0)
addr = 0; /* FIXME: else read MAC from NVRAM */
else
addr = id.addr;
if (addr)
memmove( lan_addr, addr, PDC_LAN_STATION_ID_SIZE);
else
memset( lan_addr, 0, PDC_LAN_STATION_ID_SIZE);
return (addr != 0);
}
#endif
/* Similar to PDC_PAT stuff in pdcpat.c - but added for Forte/Allegro boxes */
int pdc_pci_irt_size(void *r_addr, void *hpa)
{
return mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL_SIZE,
__pa(r_addr), hpa);
}
int pdc_pci_irt(void *r_addr, void *hpa, void *tbl)
{
return mem_pdc_call(PDC_PCI_INDEX, PDC_PCI_GET_INT_TBL,
__pa(r_addr), hpa, __pa(tbl));
}
/* access the TOD clock */
int pdc_tod_read(struct pdc_tod *tod)
{
ASSERT_ALIGN(tod, 8);
return mem_pdc_call(PDC_TOD, PDC_TOD_READ, __pa(tod), 0);
}
int pdc_tod_set(unsigned long sec, unsigned long usec)
{
return mem_pdc_call(PDC_TOD, PDC_TOD_WRITE, sec, usec);
}
/*
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file "COPYING" in the main directory of this archive
* for more details.
*
* Copyright (C) 2000 Hewlett Packard (Paul Bame bame@puffin.external.hp.com)
*
* most of these calls might reasonably be moved to ../kernel -PB
*
* The basic principle is to construct a stack frame in C then call
* some assembly which adopts that stack, does some rfi magic, may
* switch wide/narrow mode, and calls the routine described by the
* 'fn' parameter WHICH IS NOT A FUNCTION POINTER!!!!!!!!!!!!!!!!
*/
#include <linux/spinlock.h>
#include <asm/system.h>
#include <stdarg.h>
#include <asm/pgtable.h> /* for __pa() */
#include <asm/pdc.h>
static spinlock_t pdc_lock = SPIN_LOCK_UNLOCKED;
/***************** 32-bit real-mode calls ***********/
/* The struct below is used
* to overlay real_stack (real2.S), preparing a 32-bit call frame.
* real32_call_asm() then uses this stack in narrow real mode
*/
struct narrow_stack {
/* use int, not long which is 64 bits */
unsigned int arg13;
unsigned int arg12;
unsigned int arg11;
unsigned int arg10;
unsigned int arg9;
unsigned int arg8;
unsigned int arg7;
unsigned int arg6;
unsigned int arg5;
unsigned int arg4;
unsigned int arg3;
unsigned int arg2;
unsigned int arg1;
unsigned int arg0;
unsigned int frame_marker[8];
unsigned int sp;
/* in reality, there's nearly 8k of stack after this */
};
long
real32_call(unsigned long fn, ...)
{
unsigned long r;
va_list args;
unsigned long flags;
extern struct narrow_stack real_stack;
extern unsigned long real32_call_asm(unsigned int *,
unsigned int *, unsigned int);
va_start(args, fn);
real_stack.arg0 = va_arg(args, unsigned int);
real_stack.arg1 = va_arg(args, unsigned int);
real_stack.arg2 = va_arg(args, unsigned int);
real_stack.arg3 = va_arg(args, unsigned int);
real_stack.arg4 = va_arg(args, unsigned int);
real_stack.arg5 = va_arg(args, unsigned int);
real_stack.arg6 = va_arg(args, unsigned int);
real_stack.arg7 = va_arg(args, unsigned int);
real_stack.arg8 = va_arg(args, unsigned int);
real_stack.arg9 = va_arg(args, unsigned int);
real_stack.arg10 = va_arg(args, unsigned int);
real_stack.arg11 = va_arg(args, unsigned int);
real_stack.arg12 = va_arg(args, unsigned int);
real_stack.arg13 = va_arg(args, unsigned int);
va_end(args);
if (fn == 0) {
/* mem_pdc call */
fn = PAGE0->mem_pdc;
}
spin_lock_irqsave(&pdc_lock, flags);
r = real32_call_asm(&real_stack.sp, &real_stack.arg0, fn);
spin_unlock_irqrestore(&pdc_lock, flags);
return r;
}
#ifdef __LP64__
/***************** 64-bit real-mode calls ***********/
struct wide_stack {
unsigned long arg0;
unsigned long arg1;
unsigned long arg2;
unsigned long arg3;
unsigned long arg4;
unsigned long arg5;
unsigned long arg6;
unsigned long arg7;
unsigned long arg8;
unsigned long arg9;
unsigned long arg10;
unsigned long arg11;
unsigned long arg12;
unsigned long arg13;
unsigned long frame_marker[2]; /* rp, previous sp */
unsigned long sp;
/* in reality, there's nearly 8k of stack after this */
};
long
real64_call(unsigned long fn, ...)
{
unsigned long r;
va_list args;
unsigned long flags;
extern struct wide_stack real_stack;
extern unsigned long real64_call_asm(unsigned long *,
unsigned long *, unsigned long);
va_start(args, fn);
real_stack.arg0 = va_arg(args, unsigned long);
real_stack.arg1 = va_arg(args, unsigned long);
real_stack.arg2 = va_arg(args, unsigned long);
real_stack.arg3 = va_arg(args, unsigned long);
real_stack.arg4 = va_arg(args, unsigned long);
real_stack.arg5 = va_arg(args, unsigned long);
real_stack.arg6 = va_arg(args, unsigned long);
real_stack.arg7 = va_arg(args, unsigned long);
real_stack.arg8 = va_arg(args, unsigned long);
real_stack.arg9 = va_arg(args, unsigned long);
real_stack.arg10 = va_arg(args, unsigned long);
real_stack.arg11 = va_arg(args, unsigned long);
real_stack.arg12 = va_arg(args, unsigned long);
real_stack.arg13 = va_arg(args, unsigned long);
va_end(args);
if (fn == 0) {
/* mem_pdc call */
fn = PAGE0->mem_pdc_hi;
fn <<= 32;
fn |= PAGE0->mem_pdc;
}
spin_lock_irqsave(&pdc_lock, flags);
r = real64_call_asm(&real_stack.sp, &real_stack.arg0, fn);
spin_unlock_irqrestore(&pdc_lock, flags);
return r;
}
#endif
......@@ -6,6 +6,7 @@
#
obj-$(CONFIG_PCI) += pci/
obj-$(CONFIG_PARISC) += parisc/
obj-$(CONFIG_ACPI) += acpi/
obj-y += serial/
obj-$(CONFIG_PARPORT) += parport/
......
menu "Bus options (PCI, PCMCIA, EISA, GSC, ISA)"
config GSC
bool "VSC/GSC/HSC bus support"
default y
help
The VSC, GSC and HSC busses were used from the earliest 700-series
workstations up to and including the C360/J2240 workstations. They
were also used in servers from the E-class to the K-class. They
are not found in B1000, C3000, J5000, A500, L1000, N4000 and upwards.
If in doubt, say "Y".
config IOMMU_CCIO
bool "U2/Uturn I/O MMU"
depends on GSC
help
Say Y here to enable DMA management routines for the first
generation of PA-RISC cache-coherent machines. Programs the
U2/Uturn chip in "Virtual Mode" and use the I/O MMU.
config GSC_LASI
bool "Lasi I/O support"
depends on GSC
help
Say Y here to directly support the Lasi controller chip found on
PA-RISC workstations. Linux-oriented documentation for this chip
can be found at <http://www.parisc-linux.org/documentation/>.
config GSC_WAX
bool "Wax I/O support"
depends on GSC
help
Say Y here to support the Wax GSC to EISA Bridge found in some older
systems, including B/C/D/R class. Some machines use Wax for other
purposes, such as providing one of the serial ports or being an
interface chip for an X.25 GSC card.
config EISA
bool "EISA support"
depends on GSC
help
Say Y here if you have an EISA bus in your machine. This code
supports both the Mongoose & Wax EISA adapters. It is sadly
incomplete and lacks support for card-to-host DMA.
config ISA
bool
depends on EISA
config PCI
bool "PCI support"
help
All recent HP machines have PCI slots, and you should say Y here
if you have a recent machine. If you are convinced you do not have
PCI slots in your machine (eg a 712), then you may say "N" here.
Beware that some GSC cards have a Dino onboard and PCI inside them,
so it may be safest to say "Y" anyway.
config GSC_DINO
bool "GSCtoPCI/Dino PCI support"
depends on PCI && GSC
help
Say Y here to support the Dino & Cujo GSC to PCI bridges found in
machines from the B132 to the C360, the J2240 and the A180. Some
GSC/HSC cards (eg gigabit & dual 100 Mbit Ethernet) have a Dino on
the card, and you also need to say Y here if you have such a card.
If in doubt, say Y.
config PCI_LBA
bool "LBA/Elroy PCI support"
depends on PCI
help
Say Y here to support the Elroy PCI Lower Bus Adapter. This is
present on B, C, J, L and N-class machines with 4-digit model
numbers and the A400/A500.
config IOSAPIC
bool
depends on PCI_LBA
default y
config IOMMU_SBA
bool
depends on PCI_LBA
default y
#config PCI_EPIC
# bool "EPIC/SAGA PCI support"
# depends on PCI
config SUPERIO
bool
depends on PCI
help
Say Y here to support the SuperIO chip found in Bxxxx, C3xxx and
J5xxx+ machines.
source "drivers/pci/Kconfig"
config CHASSIS_LCD_LED
bool "Chassis LCD and LED support"
endmenu
#
# Makefile for most of the non-PCI devices in PA-RISC machines
#
export-objs := gsc.o superio.o
obj-y := gsc.o power.o
obj-m :=
obj-n :=
obj- :=
obj-$(CONFIG_GSC_DINO) += dino.o
obj-$(CONFIG_GSC_LASI) += lasi.o asp.o
obj-$(CONFIG_GSC_WAX) += wax.o
obj-$(CONFIG_EISA) += eisa.o eisa_enumerator.o eisa_eeprom.o
obj-$(CONFIG_SUPERIO) += superio.o
obj-$(CONFIG_PCI_LBA) += lba_pci.o
# I/O SAPIC is also on IA64 platforms.
# The two could be merged into a common source some day.
obj-$(CONFIG_IOSAPIC) += iosapic.o
obj-$(CONFIG_IOMMU_SBA) += sba_iommu.o
# Only use one of them: ccio-rm-dma is for PCX-W systems *only*
# obj-$(CONFIG_IOMMU_CCIO) += ccio-rm-dma.o
obj-$(CONFIG_IOMMU_CCIO) += ccio-dma.o
obj-$(CONFIG_CHASSIS_LCD_LED) += led.o
/*
** HP VISUALIZE Workstation PCI Bus Defect
**
** "HP has discovered a potential system defect that can affect
** the behavior of five models of HP VISUALIZE workstations when
** equipped with third-party or customer-installed PCI I/O expansion
** cards. The defect is limited to the HP C180, C160, C160L, B160L,
** and B132L VISUALIZE workstations, and will only be encountered
** when data is transmitted through PCI I/O expansion cards on the
** PCI bus. HP-supplied graphics cards that utilize the PCI bus are
** not affected."
**
** REVISIT: "go/pci_defect" link below is stale.
** HP Internal can use <http://hpfcdma.fc.hp.com:80/Dino/>
**
** Product First Good Serial Number
** C200/C240 (US) US67350000
**B132L+/B180 (US) US67390000
** C200 (Europe) 3713G01000
** B180L (Europe) 3720G01000
**
** Note that many boards were fixed/replaced under a free replacement
** program. Assume a machine is only "suspect" until proven otherwise.
**
** "The pci_check program will also be available as application
** patch PHSS_12295"
*/
/*
* ASP Device Driver
*
* (c) Copyright 2000 The Puffin Group Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* by Helge Deller <deller@gmx.de>
*/
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <asm/io.h>
#include <asm/led.h>
#include "gsc.h"
#define ASP_GSC_IRQ 3 /* hardcoded interrupt for GSC */
#define ASP_VER_OFFSET 0x20 /* offset of ASP version */
#define ASP_LED_ADDR 0xf0800020
#define VIPER_INT_WORD 0xFFFBF088 /* addr of viper interrupt word */
static int asp_choose_irq(struct parisc_device *dev)
{
int irq = -1;
switch (dev->id.sversion) {
case 0x71: irq = 22; break; /* SCSI */
case 0x72: irq = 23; break; /* LAN */
case 0x73: irq = 30; break; /* HIL */
case 0x74: irq = 24; break; /* Centronics */
case 0x75: irq = (dev->hw_path == 4) ? 26 : 25; break; /* RS232 */
case 0x76: irq = 21; break; /* EISA BA */
case 0x77: irq = 20; break; /* Graphics1 */
case 0x7a: irq = 18; break; /* Audio (Bushmaster) */
case 0x7b: irq = 18; break; /* Audio (Scorpio) */
case 0x7c: irq = 28; break; /* FW SCSI */
case 0x7d: irq = 27; break; /* FDDI */
case 0x7f: irq = 18; break; /* Audio (Outfield) */
}
return irq;
}
/* There are two register ranges we're interested in. Interrupt /
* Status / LED are at 0xf080xxxx and Asp special registers are at
* 0xf082fxxx. PDC only tells us that Asp is at 0xf082f000, so for
* the purposes of interrupt handling, we have to tell other bits of
* the kernel to look at the other registers.
*/
#define ASP_INTERRUPT_ADDR 0xf0800000
int __init
asp_init_chip(struct parisc_device *dev)
{
struct busdevice *asp;
struct gsc_irq gsc_irq;
int irq, ret;
asp = kmalloc(sizeof(struct busdevice), GFP_KERNEL);
if(!asp)
return -ENOMEM;
asp->version = gsc_readb(dev->hpa + ASP_VER_OFFSET) & 0xf;
asp->name = (asp->version == 1) ? "Asp" : "Cutoff";
asp->hpa = ASP_INTERRUPT_ADDR;
printk(KERN_INFO "%s version %d at 0x%lx found.\n",
asp->name, asp->version, dev->hpa);
/* the IRQ ASP should use */
ret = -EBUSY;
irq = gsc_claim_irq(&gsc_irq, ASP_GSC_IRQ);
if (irq < 0) {
printk(KERN_ERR "%s(): cannot get GSC irq\n", __FUNCTION__);
goto out;
}
ret = request_irq(gsc_irq.irq, busdev_barked, 0, "asp", asp);
if (ret < 0)
goto out;
/* Save this for debugging later */
asp->parent_irq = gsc_irq.irq;
asp->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data;
/* Program VIPER to interrupt on the ASP irq */
gsc_writel((1 << (31 - ASP_GSC_IRQ)),VIPER_INT_WORD);
/* Done init'ing, register this driver */
ret = gsc_common_irqsetup(dev, asp);
if (ret)
goto out;
fixup_child_irqs(dev, asp->busdev_region->data.irqbase, asp_choose_irq);
/* Mongoose is a sibling of Asp, not a child... */
fixup_child_irqs(dev->parent, asp->busdev_region->data.irqbase,
asp_choose_irq);
/* initialize the chassis LEDs */
#ifdef CONFIG_CHASSIS_LCD_LED
register_led_driver(DISPLAY_MODEL_OLD_ASP, LED_CMD_REG_NONE,
(char *)ASP_LED_ADDR);
#endif
return 0;
out:
kfree(asp);
return ret;
}
static struct parisc_device_id asp_tbl[] = {
{ HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00070 },
{ 0, }
};
struct parisc_driver asp_driver = {
name: "Asp",
id_table: asp_tbl,
probe: asp_init_chip,
};
......@@ -56,26 +56,6 @@
#define UTURN_IOA_RUNWAY 0x581
#define UTURN_BC_GSC 0x502
static int ccio_driver_callback(struct hp_device *, struct pa_iodc_driver *);
static struct pa_iodc_driver ccio_drivers_for[] = {
{HPHW_BCPORT, U2_BC_GSC, 0x0, 0xb, 0, 0x10,
DRIVER_CHECK_HVERSION +
DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
MODULE_NAME, "U2 I/O MMU", (void *) ccio_driver_callback},
{HPHW_BCPORT, UTURN_BC_GSC, 0x0, 0xb, 0, 0x10,
DRIVER_CHECK_HVERSION +
DRIVER_CHECK_SVERSION + DRIVER_CHECK_HWTYPE,
MODULE_NAME, "Uturn I/O MMU", (void *) ccio_driver_callback},
{0,0,0,0,0,0,
0,
(char *) NULL, (char *) NULL, (void *) NULL }
};
#define IS_U2(id) ( \
(((id)->hw_type == HPHW_IOA) && ((id)->hversion == U2_IOA_RUNWAY)) || \
(((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == U2_BC_GSC)) \
......@@ -86,17 +66,10 @@ static struct pa_iodc_driver ccio_drivers_for[] = {
(((id)->hw_type == HPHW_BCPORT) && ((id)->hversion == UTURN_BC_GSC)) \
)
void __init ccio_init(void)
{
register_driver(ccio_drivers_for);
}
static int ccio_dma_supported( struct pci_dev *dev, u64 mask)
{
if (dev == NULL) {
printk(MODULE_NAME ": EISA/ISA/et al not supported\n");
printk(KERN_ERR MODULE_NAME ": EISA/ISA/et al not supported\n");
BUG();
return(0);
}
......@@ -182,8 +155,6 @@ static struct pci_dma_ops ccio_ops = {
ccio_unmap_sg,
NULL, /* dma_sync_single : NOP for U2 */
NULL, /* dma_sync_sg : ditto */
};
......@@ -193,9 +164,11 @@ static struct pci_dma_ops ccio_ops = {
** have work to do.
*/
static int
ccio_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri)
ccio_probe(struct parisc_device *dev)
{
printk("%s found %s at 0x%p\n", dri->name, dri->version, d->hpa);
printk(KERN_INFO "%s found %s at 0x%lx\n", MODULE_NAME,
dev->id.hversion == U2_BC_GSC ? "U2" : "UTurn",
dev->hpa);
/*
** FIXME - should check U2 registers to verify it's really running
......@@ -210,3 +183,20 @@ ccio_driver_callback(struct hp_device *d, struct pa_iodc_driver *dri)
hppa_dma_ops = &ccio_ops;
return 0;
}
static struct parisc_device_id ccio_tbl[] = {
{ HPHW_BCPORT, HVERSION_REV_ANY_ID, U2_BC_GSC, 0xc },
{ HPHW_BCPORT, HVERSION_REV_ANY_ID, UTURN_BC_GSC, 0xc },
{ 0, }
};
static struct parisc_driver ccio_driver = {
name: "U2/Uturn",
id_table: ccio_tbl,
probe: ccio_probe,
};
void __init ccio_init(void)
{
register_parisc_driver(&ccio_driver);
}
This diff is collapsed.
This diff is collapsed.
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/slab.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <asm/eisa_eeprom.h>
#define EISA_EEPROM_MINOR 241
static unsigned long eeprom_addr;
static long long eisa_eeprom_llseek(struct file *file, loff_t offset, int origin )
{
switch (origin) {
case 0:
/* nothing to do */
break;
case 1:
offset += file->f_pos;
break;
case 2:
offset += HPEE_MAX_LENGTH;
break;
}
return (offset >= 0 && offset < HPEE_MAX_LENGTH) ? (file->f_pos = offset) : -EINVAL;
}
static ssize_t eisa_eeprom_read(struct file * file,
char *buf, size_t count, loff_t *ppos )
{
unsigned char *tmp;
ssize_t ret;
int i;
if (*ppos >= HPEE_MAX_LENGTH)
return 0;
count = *ppos + count < HPEE_MAX_LENGTH ? count : HPEE_MAX_LENGTH - *ppos;
tmp = kmalloc(count, GFP_KERNEL);
if (tmp) {
for (i = 0; i < count; i++)
tmp[i] = gsc_readb(eeprom_addr+(*ppos)++);
if (copy_to_user (buf, tmp, count))
ret = -EFAULT;
else
ret = count;
kfree (tmp);
} else
ret = -ENOMEM;
return ret;
}
static int eisa_eeprom_ioctl(struct inode *inode, struct file *file,
unsigned int cmd,
unsigned long arg)
{
return -ENOTTY;
}
static int eisa_eeprom_open(struct inode *inode, struct file *file)
{
if (file->f_mode & 2 || eeprom_addr == 0)
return -EINVAL;
return 0;
}
static int eisa_eeprom_release(struct inode *inode, struct file *file)
{
return 0;
}
/*
* The various file operations we support.
*/
static struct file_operations eisa_eeprom_fops = {
owner: THIS_MODULE,
llseek: eisa_eeprom_llseek,
read: eisa_eeprom_read,
ioctl: eisa_eeprom_ioctl,
open: eisa_eeprom_open,
release: eisa_eeprom_release,
};
static struct miscdevice eisa_eeprom_dev=
{
EISA_EEPROM_MINOR,
"eisa eeprom",
&eisa_eeprom_fops
};
int __init eisa_eeprom_init(unsigned long addr)
{
if (addr) {
eeprom_addr = addr;
misc_register(&eisa_eeprom_dev);
printk(KERN_INFO "EISA EEPROM at 0x%lx\n", eeprom_addr);
}
return 0;
}
MODULE_LICENSE("GPL");
This diff is collapsed.
/*
* Interrupt management for most GSC and related devices.
*
* (c) Copyright 1999 Alex deVries for The Puffin Group
* (c) Copyright 1999 Grant Grundler for Hewlett-Packard
* (c) Copyright 1999 Matthew Wilcox
* (c) Copyright 2000 Helge Deller
* (c) Copyright 2001 Matthew Wilcox for Hewlett-Packard
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#include <linux/bitops.h>
#include <linux/config.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <asm/irq.h>
#include "gsc.h"
#undef DEBUG
#ifdef DEBUG
#define DEBPRINTK printk
#else
#define DEBPRINTK(x,...)
#endif
int gsc_alloc_irq(struct gsc_irq *i)
{
int irq = txn_alloc_irq();
if (irq < 0) {
printk("cannot get irq\n");
return irq;
}
i->txn_addr = txn_alloc_addr(irq);
i->txn_data = txn_alloc_data(irq, GSC_EIM_WIDTH);
i->irq = irq;
return irq;
}
int gsc_claim_irq(struct gsc_irq *i, int irq)
{
int c = irq;
irq += IRQ_FROM_REGION(CPU_IRQ_REGION); /* virtualize the IRQ first */
irq = txn_claim_irq(irq);
if (irq < 0) {
printk("cannot claim irq %d\n", c);
return irq;
}
i->txn_addr = txn_alloc_addr(irq);
i->txn_data = txn_alloc_data(irq, GSC_EIM_WIDTH);
i->irq = irq;
return irq;
}
EXPORT_SYMBOL(gsc_alloc_irq);
EXPORT_SYMBOL(gsc_claim_irq);
/* IRQ bits must be numbered from Most Significant Bit */
#define GSC_FIX_IRQ(x) (31-(x))
#define GSC_MASK_IRQ(x) (1<<(GSC_FIX_IRQ(x)))
/* Common interrupt demultiplexer used by Asp, Lasi & Wax. */
void busdev_barked(int busdev_irq, void *dev, struct pt_regs *regs)
{
unsigned long irq;
struct busdevice *busdev = (struct busdevice *) dev;
/*
Don't need to protect OFFSET_IRR with spinlock since this is
the only place it's touched.
Protect busdev_region by disabling this region's interrupts,
modifying the region, and then re-enabling the region.
*/
irq = gsc_readl(busdev->hpa+OFFSET_IRR);
if (irq == 0) {
printk(KERN_ERR "%s: barking without apparent reason.\n", busdev->name);
} else {
DEBPRINTK ("%s (0x%x) barked, mask=0x%x, irq=%d\n",
busdev->name, busdev->busdev_region->data.irqbase,
irq, GSC_FIX_IRQ(ffs(irq))+1 );
do_irq_mask(irq, busdev->busdev_region, regs);
}
}
static void
busdev_disable_irq(void *irq_dev, int irq)
{
/* Disable the IRQ line by clearing the bit in the IMR */
u32 imr = gsc_readl(BUSDEV_DEV(irq_dev)->hpa+OFFSET_IMR);
imr &= ~(GSC_MASK_IRQ(irq));
DEBPRINTK( KERN_WARNING "%s(%p, %d) %s: IMR 0x%x\n",
__FUNCTION__, irq_dev, irq, BUSDEV_DEV(irq_dev)->name, imr);
gsc_writel(imr, BUSDEV_DEV(irq_dev)->hpa+OFFSET_IMR);
}
static void
busdev_enable_irq(void *irq_dev, int irq)
{
/* Enable the IRQ line by setting the bit in the IMR */
unsigned long addr = BUSDEV_DEV(irq_dev)->hpa + OFFSET_IMR;
u32 imr = gsc_readl(addr);
imr |= GSC_MASK_IRQ(irq);
DEBPRINTK (KERN_WARNING "%s(%p, %d) %s: IMR 0x%x\n",
__FUNCTION__, irq_dev, irq, BUSDEV_DEV(irq_dev)->name, imr);
gsc_writel(imr, addr);
// gsc_writel(~0L, addr);
/* FIXME: read IPR to make sure the IRQ isn't already pending.
** If so, we need to read IRR and manually call do_irq_mask().
** This code should be shared with busdev_unmask_irq().
*/
}
static void
busdev_mask_irq(void *irq_dev, int irq)
{
/* FIXME: Clear the IMR bit in busdev for that IRQ */
}
static void
busdev_unmask_irq(void *irq_dev, int irq)
{
/* FIXME: Read IPR. Set the IMR bit in busdev for that IRQ.
call do_irq_mask() if IPR is non-zero
*/
}
struct irq_region_ops busdev_irq_ops = {
disable_irq: busdev_disable_irq,
enable_irq: busdev_enable_irq,
mask_irq: busdev_mask_irq,
unmask_irq: busdev_unmask_irq
};
int gsc_common_irqsetup(struct parisc_device *parent, struct busdevice *busdev)
{
struct resource *res;
busdev->gsc = parent;
/* the IRQs we simulate */
busdev->busdev_region = alloc_irq_region(32, &busdev_irq_ops,
busdev->name, busdev);
if (!busdev->busdev_region)
return -ENOMEM;
/* allocate resource region */
res = request_mem_region(busdev->hpa, 0x100000, busdev->name);
if (res) {
res->flags = IORESOURCE_MEM; /* do not mark it busy ! */
}
#if 0
printk(KERN_WARNING "%s IRQ %d EIM 0x%x", busdev->name,
busdev->parent_irq, busdev->eim);
if (gsc_readl(busdev->hpa + OFFSET_IMR))
printk(" IMR is non-zero! (0x%x)",
gsc_readl(busdev->hpa + OFFSET_IMR));
printk("\n");
#endif
return 0;
}
extern struct parisc_driver lasi_driver;
extern struct parisc_driver asp_driver;
extern struct parisc_driver wax_driver;
void __init gsc_init(void)
{
#ifdef CONFIG_GSC_LASI
register_parisc_driver(&lasi_driver);
register_parisc_driver(&asp_driver);
#endif
#ifdef CONFIG_GSC_WAX
register_parisc_driver(&wax_driver);
#endif
}
/*
* drivers/parisc/gsc.h
* Declarations for functions in gsc.c
* Copyright (c) 2000-2002 Helge Deller, Matthew Wilcox
*
* Distributed under the terms of the GPL, version 2
*/
#include <linux/interrupt.h>
#include <asm/hardware.h>
#define OFFSET_IRR 0x0000 /* Interrupt request register */
#define OFFSET_IMR 0x0004 /* Interrupt mask register */
#define OFFSET_IPR 0x0008 /* Interrupt pending register */
#define OFFSET_ICR 0x000C /* Interrupt control register */
#define OFFSET_IAR 0x0010 /* Interrupt address register */
/* PA I/O Architected devices support at least 5 bits in the EIM register. */
#define GSC_EIM_WIDTH 5
struct gsc_irq {
unsigned long txn_addr; /* IRQ "target" */
int txn_data; /* HW "IRQ" */
int irq; /* virtual IRQ */
};
struct busdevice {
struct parisc_device *gsc;
unsigned long hpa;
char *name;
int version;
int type;
int parent_irq;
int eim;
struct irq_region *busdev_region;
};
/* short cut to keep the compiler happy */
#define BUSDEV_DEV(x) ((struct busdevice *) (x))
int gsc_common_irqsetup(struct parisc_device *parent, struct busdevice *busdev);
extern int gsc_alloc_irq(struct gsc_irq *dev); /* dev needs an irq */
extern int gsc_claim_irq(struct gsc_irq *dev, int irq); /* dev needs this irq */
void busdev_barked(int busdev_irq, void *dev, struct pt_regs *regs);
......@@ -111,22 +111,25 @@ struct vector_info {
struct irt_entry *vi_irte; /* IRT entry */
u32 *vi_eoi_addr; /* precalculate EOI reg address */
u32 vi_eoi_data; /* IA64: ? PA: swapped txn_data */
u8 vi_status; /* status/flags */
u8 vi_irqline; /* INTINn(IRQ) */
int vi_txn_irq; /* virtual IRQ number for processor */
ulong vi_txn_addr; /* IA64: id_eid PA: partial HPA */
ulong vi_txn_data; /* IA64: vector PA: EIR bit */
u8 vi_status; /* status/flags */
u8 vi_irqline; /* INTINn(IRQ) */
char vi_name[32]; /* user visible identity */
};
struct iosapic_info {
struct iosapic_info *isi_next; /* list of I/O SAPIC */
volatile void *isi_hpa; /* physical base address */
unsigned long isi_hpa; /* physical base address */
struct irq_region *isi_region; /* each I/O SAPIC is one region */
struct vector_info *isi_vector; /* IRdT (IRQ line) array */
int isi_num_vectors; /* size of IRdT array */
int isi_status; /* status/flags */
unsigned int isi_version; /* DEBUG: data fr version reg */
/* round up to next cacheline */
char isi_name[20]; /* identify region for users */
};
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*
* WAX Device Driver
*
* (c) Copyright 2000 The Puffin Group Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* by Helge Deller <deller@gmx.de>
*/
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/types.h>
#include <asm/io.h>
#include <asm/hardware.h>
#include <asm/irq.h>
#include "gsc.h"
#define WAX_GSC_IRQ 7 /* Hardcoded Interrupt for GSC */
#define WAX_GSC_NMI_IRQ 29
static int wax_choose_irq(struct parisc_device *dev)
{
int irq = -1;
switch (dev->id.sversion) {
case 0x73: irq = 30; break; /* HIL */
case 0x8c: irq = 25; break; /* RS232 */
case 0x90: irq = 21; break; /* WAX EISA BA */
}
return irq;
}
static void __init
wax_init_irq(struct busdevice *wax)
{
unsigned long base = wax->hpa;
/* Stop WAX barking for a bit */
gsc_writel(0x00000000, base+OFFSET_IMR);
/* clear pending interrupts */
(volatile u32) gsc_readl(base+OFFSET_IRR);
/* We're not really convinced we want to reset the onboard
* devices. Firmware does it for us...
*/
/* Resets */
// gsc_writel(0xFFFFFFFF, base+0x1000); /* HIL */
// gsc_writel(0xFFFFFFFF, base+0x2000); /* RS232-B on Wax */
/* Ok we hit it on the head with a hammer, our Dog is now
** comatose and muzzled. Devices will now unmask WAX
** interrupts as they are registered as irq's in the WAX range.
*/
}
int __init
wax_init_chip(struct parisc_device *dev)
{
struct busdevice *wax;
struct gsc_irq gsc_irq;
int irq, ret;
wax = kmalloc(sizeof(struct busdevice), GFP_KERNEL);
if (!wax)
return -ENOMEM;
wax->name = "Wax";
wax->hpa = dev->hpa;
wax->version = 0; /* gsc_readb(wax->hpa+WAX_VER); */
printk(KERN_INFO "%s at 0x%lx found.\n", wax->name, wax->hpa);
/* Stop wax hissing for a bit */
wax_init_irq(wax);
/* the IRQ wax should use */
irq = gsc_claim_irq(&gsc_irq, WAX_GSC_IRQ);
if (irq < 0) {
printk(KERN_ERR "%s(): cannot get GSC irq\n",
__FUNCTION__);
kfree(wax);
return -EBUSY;
}
ret = request_irq(gsc_irq.irq, busdev_barked, 0, "wax", wax);
if (ret < 0) {
kfree(wax);
return ret;
}
/* Save this for debugging later */
wax->parent_irq = gsc_irq.irq;
wax->eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data;
/* enable IRQ's for devices below WAX */
gsc_writel(wax->eim, wax->hpa + OFFSET_IAR);
/* Done init'ing, register this driver */
ret = gsc_common_irqsetup(dev, wax);
if (ret) {
kfree(wax);
return ret;
}
fixup_child_irqs(dev, wax->busdev_region->data.irqbase,
wax_choose_irq);
/* On 715-class machines, Wax EISA is a sibling of Wax, not a child. */
if (dev->parent->id.hw_type != HPHW_IOA) {
fixup_child_irqs(dev->parent, wax->busdev_region->data.irqbase,
wax_choose_irq);
}
return ret;
}
static struct parisc_device_id wax_tbl[] = {
{ HPHW_BA, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x0008e },
{ 0, }
};
MODULE_DEVICE_TABLE(parisc, wax_tbl);
struct parisc_driver wax_driver = {
name: "Wax",
id_table: wax_tbl,
probe: wax_init_chip,
};
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment