DIGI RIGHTSWITCH NETWORK DRIVER
P: Rick Richardson
-M: rick@dgii.com
+M: rick@remotepoint.com
L: linux-net@vger.rutgers.edu
W: http://www.dgii.com/linux/
S: Maintained
IDE DRIVER [GENERAL]
P: Andre Hedrick
-M: hedrick@astro.dyer.vanderbilt.edu
+M: andre@linux-ide.org
L: linux-kernel@vger.rutgers.edu
S: Maintained
VERSION = 2
PATCHLEVEL = 2
SUBLEVEL = 16
-EXTRAVERSION = pre8
+EXTRAVERSION =
ARCH := $(shell uname -m | sed -e s/i.86/i386/ -e s/sun4u/sparc64/ -e s/arm.*/arm/ -e s/sa110/arm/)
srm_printk("Initrd positioned at %#lx\n", initrd_start);
#endif
- nbytes = srm_dispatch(CCB_GET_ENV, ENV_BOOTED_OSFLAGS,
- envval, sizeof(envval));
+ nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
if (nbytes < 0 || nbytes >= sizeof(envval)) {
nbytes = 0;
}
char bootdev[256];
long result;
- result = srm_dispatch(CCB_GET_ENV, ENV_BOOTED_DEV, bootdev, 255);
+ result = callback_getenv(ENV_BOOTED_DEV, bootdev, 255);
if (result < 0)
return result;
- return srm_dispatch(CCB_OPEN, bootdev, result & 255);
+ return callback_open(bootdev, result & 255);
}
static inline long close(long dev)
{
- return srm_dispatch(CCB_CLOSE, dev);
+ return callback_close(dev);
}
static inline long load(long dev, unsigned long addr, unsigned long count)
extern char _end;
long result, boot_size = &_end - (char *) BOOT_ADDR;
- result = srm_dispatch(CCB_GET_ENV, ENV_BOOTED_FILE, bootfile, 255);
+ result = callback_getenv(ENV_BOOTED_FILE, bootfile, 255);
if (result < 0)
return result;
result &= 255;
if (result)
srm_printk("Boot file specification (%s) not implemented\n",
bootfile);
- return srm_dispatch(CCB_READ, dev, count, addr, boot_size/512 + 1);
+ return callback_read(dev, count, addr, boot_size/512 + 1);
}
/*
return;
}
- nbytes = srm_dispatch(CCB_GET_ENV, ENV_BOOTED_OSFLAGS,
- envval, sizeof(envval));
+ nbytes = callback_getenv(ENV_BOOTED_OSFLAGS, envval, sizeof(envval));
if (nbytes < 0) {
nbytes = 0;
}
*/
#define ALIGN(val,align) (((val) + ((align) - 1)) & ~((align) - 1))
+static short __inline__
+__disable_dev(struct pci_dev *dev)
+{
+ unsigned short cmd, orig_cmd;
+
+ pcibios_read_config_word(dev->bus->number, dev->devfn,
+ PCI_COMMAND, &cmd);
+
+ orig_cmd = cmd;
+ cmd &= (~PCI_COMMAND_IO & ~PCI_COMMAND_MEMORY & ~PCI_COMMAND_MASTER);
+
+ pcibios_write_config_word(dev->bus->number, dev->devfn,
+ PCI_COMMAND, cmd);
+ return orig_cmd;
+}
+
+static void __inline__
+__enable_dev(struct pci_dev *dev, short orig_cmd)
+{
+ pcibios_write_config_word(dev->bus->number, dev->devfn,
+ PCI_COMMAND, orig_cmd);
+}
/*
* The following structure records initial configuration of devices
struct srm_io_reset *next;
struct pci_dev *dev;
u32 io;
+ short cmd;
u8 reg;
} *srm_io_resets;
{
struct srm_irq_reset *qreset;
struct srm_io_reset *ireset;
+ struct pci_dev *last_dev;
/* Reset any IRQs that we changed. */
for (qreset = srm_irq_resets; qreset ; qreset = qreset->next) {
#endif
}
+ /* Disable any devices which had IO addresses that we changed. */
+ last_dev = NULL;
+ for (ireset = srm_io_resets; ireset ; ireset = ireset->next) {
+ if (ireset->dev != last_dev) {
+ ireset->cmd = __disable_dev(ireset->dev);
+ last_dev = ireset->dev;
+ }
+ }
+
/* Reset any IO addresses that we changed. */
for (ireset = srm_io_resets; ireset ; ireset = ireset->next) {
pcibios_write_config_dword(ireset->dev->bus->number,
ireset->io);
#endif
}
+
+ /* Re-enable any devices which had IO addresses that we changed. */
+ last_dev = NULL;
+ for (ireset = srm_io_resets; ireset ; ireset = ireset->next) {
+ if (ireset->dev != last_dev) {
+ __enable_dev(ireset->dev, ireset->cmd);
+ last_dev = ireset->dev;
+ }
+ }
}
static void
new_irq_reset(struct pci_dev *dev, u8 irq)
{
- struct srm_irq_reset *n;
- n = kmalloc(sizeof(*n), GFP_KERNEL);
+ struct srm_irq_reset *new;
+ new = kmalloc(sizeof(*new), GFP_KERNEL);
- n->next = srm_irq_resets;
- n->dev = dev;
- n->irq = irq;
- srm_irq_resets = n;
+ new->next = srm_irq_resets;
+ new->dev = dev;
+ new->irq = irq;
+ srm_irq_resets = new;
}
static void
new_io_reset(struct pci_dev *dev, u8 reg, u32 io)
{
- struct srm_io_reset *n;
- n = kmalloc(sizeof(*n), GFP_KERNEL);
-
- n->next = srm_io_resets;
- n->dev = dev;
- n->reg = reg;
- n->io = io;
- srm_io_resets = n;
+ struct srm_io_reset *new;
+ new = kmalloc(sizeof(*new), GFP_KERNEL);
+
+ new->next = srm_io_resets;
+ new->dev = dev;
+ new->reg = reg;
+ new->io = io;
+ srm_io_resets = new;
}
static void __init
disable_dev(struct pci_dev *dev)
{
- struct pci_bus *bus;
- unsigned short cmd;
-
/*
* HACK: the PCI-to-EISA bridge does not seem to identify
* itself as a bridge... :-(
/*
* We don't have code that will init the CYPRESS bridge correctly
* so we do the next best thing, and depend on the previous
- * console code to do the right thing, and ignore it here... :-\
+ * console code to do the right thing, and ignore it mostly... :-\
*/
if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
- dev->device == PCI_DEVICE_ID_CONTAQ_82C693) {
+ dev->device == PCI_DEVICE_ID_CONTAQ_82C693 &&
+ PCI_FUNC(dev->devfn) == 0) {
DBG_DEVS(("disable_dev: ignoring CYPRESS bridge...\n"));
return;
}
DBG_DEVS(("disable_dev: disabling %04x:%04x\n",
dev->vendor, dev->device));
- bus = dev->bus;
- pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd);
-
- /* hack, turn it off first... */
- cmd &= (~PCI_COMMAND_IO & ~PCI_COMMAND_MEMORY & ~PCI_COMMAND_MASTER);
- pcibios_write_config_word(bus->number, dev->devfn, PCI_COMMAND, cmd);
+ (void)__disable_dev(dev);
}
unsigned int orig_base;
unsigned int alignto;
unsigned long handle;
+ int start_idx = 0;
/*
* HACK: the PCI-to-EISA bridge does not seem to identify
/*
* We don't have code that will init the CYPRESS bridge correctly
* so we do the next best thing, and depend on the previous
- * console code to do the right thing, and ignore it here... :-\
+ * console code to do the right thing, and ignore it mostly... :-\
*/
if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
dev->device == PCI_DEVICE_ID_CONTAQ_82C693) {
+ int func = PCI_FUNC(dev->devfn);
+ if (func == 0) {
DBG_DEVS(("layout_dev: ignoring CYPRESS bridge...\n"));
return;
+ }
+ if (func == 1 || func == 2) {
+ start_idx = 4; /* bypass BAR 0 - 3 for the IDE devs */
+ }
}
bus = dev->bus;
pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd);
- for (idx = 0; idx <= 5; idx++) {
+ for (idx = start_idx; idx <= 5; idx++) {
off = PCI_BASE_ADDRESS_0 + 4*idx;
/*
* Figure out how much space and of what type this
dev->device, dev->class, cmd|PCI_COMMAND_MASTER));
}
+/* We must save away the current bridge settings for restore during exit. */
+static void __init
+save_bridge_setup(struct pci_dev *bridge)
+{
+ unsigned int dword;
+
+ pcibios_read_config_dword(bridge->bus->number, bridge->devfn,
+ PCI_IO_BASE, &dword);
+ new_io_reset(bridge, PCI_IO_BASE, dword);
+
+ pcibios_read_config_dword(bridge->bus->number, bridge->devfn,
+ PCI_IO_BASE_UPPER16, &dword);
+ new_io_reset(bridge, PCI_IO_BASE_UPPER16, dword);
+
+ pcibios_read_config_dword(bridge->bus->number, bridge->devfn,
+ PCI_PREF_BASE_UPPER32, &dword);
+ new_io_reset(bridge, PCI_PREF_BASE_UPPER32, dword);
+
+ pcibios_read_config_dword(bridge->bus->number, bridge->devfn,
+ PCI_PREF_LIMIT_UPPER32, &dword);
+ new_io_reset(bridge, PCI_PREF_LIMIT_UPPER32, dword);
+
+ pcibios_read_config_dword(bridge->bus->number, bridge->devfn,
+ PCI_MEMORY_BASE, &dword);
+ new_io_reset(bridge, PCI_MEMORY_BASE, dword);
+
+ pcibios_read_config_dword(bridge->bus->number, bridge->devfn,
+ PCI_PREF_MEMORY_BASE, &dword);
+ new_io_reset(bridge, PCI_PREF_MEMORY_BASE, dword);
+
+ /* Must use dword that contains PCI_BRIDGE_CONTROL. */
+ pcibios_read_config_dword(bridge->bus->number, bridge->devfn,
+ PCI_INTERRUPT_LINE, &dword);
+ new_io_reset(bridge, PCI_INTERRUPT_LINE, dword);
+
+ pcibios_read_config_dword(bridge->bus->number, bridge->devfn,
+ PCI_COMMAND, &dword);
+ new_io_reset(bridge, PCI_COMMAND, dword);
+}
+
static int __init
layout_bus(struct pci_bus *bus)
{
if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA)
found_vga = 1;
}
+
/*
* Recursively allocate space for all of the sub-buses:
*/
for (child = bus->children; child; child = child->next) {
found_vga += layout_bus(child);
}
+
/*
* Align the current bases on 4K and 1MB boundaries:
*/
DBG_DEVS(("layout_bus: config bus %d bridge\n", bus->number));
+ save_bridge_setup(bridge);
+
/*
* Set up the top and bottom of the PCI I/O segment
* for this bus.
layout_hoses(void)
{
struct linux_hose_info * hose;
- int i;
/* On multiple bus machines, we play games with pci_root in order
that all of the busses are probed as part of the normal PCI
IRONGATE0->agpmode);
}
#else
-#define irongate_register_dump(x) 1
+#define irongate_register_dump(x)
#endif
void __init
frame->ld_lock);
}
+void
+mcpcia_print_system_area(unsigned long la_ptr)
+{
+ struct el_common *frame;
+ int i;
+
+ struct IOD_subpacket {
+ unsigned long base;
+ unsigned int whoami;
+ unsigned int rsvd1;
+ unsigned int pci_rev;
+ unsigned int cap_ctrl;
+ unsigned int hae_mem;
+ unsigned int hae_io;
+ unsigned int int_ctl;
+ unsigned int int_reg;
+ unsigned int int_mask0;
+ unsigned int int_mask1;
+ unsigned int mc_err0;
+ unsigned int mc_err1;
+ unsigned int cap_err;
+ unsigned int rsvd2;
+ unsigned int pci_err1;
+ unsigned int mdpa_stat;
+ unsigned int mdpa_syn;
+ unsigned int mdpb_stat;
+ unsigned int mdpb_syn;
+ unsigned int rsvd3;
+ unsigned int rsvd4;
+ unsigned int rsvd5;
+ } *iodpp;
+
+ frame = (struct el_common *)la_ptr;
+
+ iodpp = (struct IOD_subpacket *) (la_ptr + frame->sys_offset);
+
+ for (i = 0; i < hose_count; i++, iodpp++) {
+ printk("IOD %d Register Subpacket - Bridge Base Address %16lx\n",
+ i, iodpp->base);
+ printk(" WHOAMI = %8x\n", iodpp->whoami);
+ printk(" PCI_REV = %8x\n", iodpp->pci_rev);
+ printk(" CAP_CTRL = %8x\n", iodpp->cap_ctrl);
+ printk(" HAE_MEM = %8x\n", iodpp->hae_mem);
+ printk(" HAE_IO = %8x\n", iodpp->hae_io);
+ printk(" INT_CTL = %8x\n", iodpp->int_ctl);
+ printk(" INT_REG = %8x\n", iodpp->int_reg);
+ printk(" INT_MASK0 = %8x\n", iodpp->int_mask0);
+ printk(" INT_MASK1 = %8x\n", iodpp->int_mask1);
+ printk(" MC_ERR0 = %8x\n", iodpp->mc_err0);
+ printk(" MC_ERR1 = %8x\n", iodpp->mc_err1);
+ printk(" CAP_ERR = %8x\n", iodpp->cap_err);
+ printk(" PCI_ERR1 = %8x\n", iodpp->pci_err1);
+ printk(" MDPA_STAT = %8x\n", iodpp->mdpa_stat);
+ printk(" MDPA_SYN = %8x\n", iodpp->mdpa_syn);
+ printk(" MDPB_STAT = %8x\n", iodpp->mdpb_stat);
+ printk(" MDPB_SYN = %8x\n", iodpp->mdpb_syn);
+ }
+}
+
void
mcpcia_machine_check(unsigned long vector, unsigned long la_ptr,
struct pt_regs * regs)
if (vector != 0x620 && vector != 0x630
&& ! MCPCIA_mcheck_expected[cpu]) {
mcpcia_print_uncorrectable(mchk_logout);
+ mcpcia_print_system_area(la_ptr);
}
}
unsigned long __init init_IRQ(unsigned long memory)
{
wrent(entInt, 0);
+
alpha_mv.init_irq();
+
+ /* If we had wanted SRM console printk echoing early, undo it now. */
+ if (alpha_using_srm && srmcons_output) {
+ unregister_srm_console();
+ }
+
return memory;
}
struct linux_hose_info *hose);
extern void irongate_init_arch(unsigned long *, unsigned long *);
extern void irongate_machine_check(u64, u64, struct pt_regs *);
+extern int irongate_pci_clr_err(void);
/* core_lca.c */
extern int lca_hose_read_config_byte (u8, u8, u8, u8 *value,
/* setup.c */
extern unsigned long srm_hae;
+extern int srmcons_output;
+extern void register_srm_console(void);
+extern void unregister_srm_console(void);
/* smp.c */
extern void setup_smp(void);
extern int ptrace_cancel_bpt (struct task_struct *child);
/* ../mm/init.c */
+extern void switch_to_system_map(void);
void srm_paging_stop(void);
/* irq.c */
#include <asm/page.h>
#include <asm/dma.h>
#include <asm/io.h>
-
+#include <asm/console.h>
#include "proto.h"
int alpha_using_srm, alpha_use_srm_setup;
#endif
+/* Using SRM callbacks for initial console output. This works from
+ setup_arch() time through the end of init_IRQ(), as those places
+ are under our control.
+
+ By default, OFF; set it with a bootcommand arg of "srmcons".
+*/
+int srmcons_output = 0;
+
+/* For PS/2 presence */
unsigned char aux_device_present = 0xaa;
#define N(a) (sizeof(a)/sizeof(a[0]))
setup_arch(char **cmdline_p, unsigned long * memory_start_p,
unsigned long * memory_end_p)
{
- extern char _end[];
-
struct alpha_machine_vector *vec = NULL;
struct percpu_struct *cpu;
char *type_name, *var_name, *p;
unsigned long memory_end_override = 0;
+ extern char _end;
+ void *kernel_end = &_end; /* End of the kernel. */
hwrpb = (struct hwrpb_struct*) __va(INIT_HWRPB->phys_addr);
+#ifdef CONFIG_ALPHA_GENERIC
+ /* Assume that we've booted from SRM if we havn't booted from MILO.
+ Detect the later by looking for "MILO" in the system serial nr. */
+ alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0;
+#endif
+
+ kernel_end = callback_init(kernel_end);
+
/*
- * Locate the command line.
- */
+ Process the command line.
- /* Hack for Jensen... since we're restricted to 8 or 16 chars for
+ Hack for Jensen... since we're restricted to 8 or 16 chars for
boot flags depending on the boot mode, we need some shorthand.
This should do for installation. Later we'll add other
- abbreviations as well... */
+ abbreviations as well...
+ */
if (strcmp(COMMAND_LINE, "INSTALL") == 0) {
strcpy(command_line, "root=/dev/fd0 load_ramdisk=1");
} else {
memory_end_override = get_memory_end_override(p+4);
continue;
}
+ if (strncmp(p, "srmcons", 7) == 0) {
+ srmcons_output = 1;
+ continue;
+ }
}
/* Replace the command line, not that we've killed it with strtok. */
strcpy(command_line, saved_command_line);
+ /* If we want SRM console printk echoing early, do it now. */
+ if (alpha_using_srm && srmcons_output) {
+ register_srm_console();
+ }
+
/*
* Indentify and reconfigure for the current system.
*/
alpha_mv = *vec;
}
-#ifdef CONFIG_ALPHA_GENERIC
- /* Assume that we've booted from SRM if we havn't booted from MILO.
- Detect the later by looking for "MILO" in the system serial nr. */
- alpha_using_srm = strncmp((const char *)hwrpb->ssn, "MILO", 4) != 0;
-#endif
-
printk("%s on %s%s%s using machine vector %s from %s\n",
#ifdef CONFIG_ALPHA_GENERIC
"Booting GENERIC",
wrmces(0x7);
/* Find our memory. */
- *memory_start_p = (unsigned long) _end;
+ *memory_start_p = (unsigned long)kernel_end;
*memory_end_p = find_end_memory();
if (memory_end_override && memory_end_override < *memory_end_p) {
printk("Overriding memory size from %luMB to %luMB\n",
struct memdesc_struct * memdesc;
memdesc = (struct memdesc_struct *)
- (INIT_HWRPB->mddt_offset + (unsigned long) INIT_HWRPB);
+ (hwrpb->mddt_offset + (unsigned long)hwrpb);
cluster = memdesc->cluster;
for (i = memdesc->numclusters ; i > 0; i--, cluster++) {
static int rawhide_indices[] = {0,0,0,1,1,2,2,3,3,4,4};
static char tsunami_names[][16] = {
- "0", "DP264", "Warhol", "Windjammer", "Monet", "Clipper",
+ "EarlyMonet", "DP264", "Warhol", "Windjammer", "Monet", "Clipper",
"Goldrush", "Webbrick", "Catamaran"
};
static int tsunami_indices[] = {0,1,2,3,4,5,6,7,8};
static struct alpha_machine_vector *tsunami_vecs[] __initlocaldata =
{
- NULL,
+ &monet_mv, /* HACK for early Monets */
&dp264_mv, /* dp264 */
&dp264_mv, /* warhol */
&dp264_mv, /* windjammer */
if (!vec) {
/* Member ID is a bit-field. */
- long member = (variation >> 10) & 0x3f;
+ long member = HWRPB_MEMBER_ID(variation);
switch (type) {
case ST_DEC_ALCOR:
return len;
}
+
+#if defined(CONFIG_ALPHA_GENERIC) || defined(CONFIG_ALPHA_SRM)
+/*
+ * Manage the SRM callbacks as a "console".
+ */
+static struct console srmcons;
+
+void __init register_srm_console(void)
+{
+ register_console(&srmcons);
+}
+
+void __init unregister_srm_console(void)
+{
+ unregister_console(&srmcons);
+}
+
+static void srm_console_write(struct console *co, const char *s,
+ unsigned count)
+{
+ srm_printk(s);
+}
+
+static kdev_t srm_console_device(struct console *c)
+{
+ /* Huh? */
+ return MKDEV(TTY_MAJOR, 64 + c->index);
+}
+
+static int srm_console_wait_key(struct console *co)
+{
+ /* Huh? */
+ return 1;
+}
+
+static int __init srm_console_setup(struct console *co, char *options)
+{
+ return 1;
+}
+
+static struct console srmcons = {
+ "srm0",
+ srm_console_write,
+ NULL,
+ srm_console_device,
+ srm_console_wait_key,
+ NULL,
+ srm_console_setup,
+ CON_PRINTBUFFER | CON_ENABLED, /* fake it out */
+ -1,
+ 0,
+ NULL
+};
+
+#else
+void __init register_srm_console(void)
+{
+}
+void __init unregister_srm_console(void)
+{
+}
+#endif
layout_all_busses(DEFAULT_IO_BASE, DEFAULT_MEM_BASE);
common_pci_fixup(monet_map_irq, monet_swizzle);
SMC669_Init(1);
- es1888_init();
+
+ /* HACK: early Monets had a member ID of 0 and the ES1888
+ located in a non-standard spot, so do this only for
+ official Monets */
+ if (HWRPB_MEMBER_ID(hwrpb->sys_variation) != 0)
+ es1888_init();
}
static void __init
mikasa_machine_check(unsigned long vector, unsigned long la_ptr,
struct pt_regs * regs)
{
-#define MCHK_NO_DEVSEL 0x205L
-#define MCHK_NO_TABT 0x204L
+#define MCHK_NO_DEVSEL 0x205U
+#define MCHK_NO_TABT 0x204U
struct el_common *mchk_header;
struct el_apecs_procdata *mchk_procdata;
struct el_apecs_mikasa_sysdata_mcheck *mchk_sysdata;
unsigned long *ptr;
+ unsigned int code; /* workaround EGCS problem */
int i;
mchk_header = (struct el_common *)la_ptr;
* ignore the machine check.
*/
- if (apecs_mcheck_expected
- && ((unsigned int)mchk_header->code == MCHK_NO_DEVSEL
- || (unsigned int)mchk_header->code == MCHK_NO_TABT)) {
+ code = mchk_header->code; /* workaround EGCS problem */
+
+ if (apecs_mcheck_expected &&
+ (code == MCHK_NO_DEVSEL || code == MCHK_NO_TABT))
+ {
apecs_mcheck_expected = 0;
apecs_mcheck_taken = 1;
mb();
vector);
}
else {
- printk(KERN_CRIT "APECS machine check:\n");
- printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx\n",
- vector, la_ptr);
+ printk(KERN_CRIT "MIKASA APECS machine check:\n");
+ printk(KERN_CRIT " vector=0x%lx la_ptr=0x%lx code=0x%x\n",
+ vector, la_ptr, code);
printk(KERN_CRIT
" pc=0x%lx size=0x%x procoffset=0x%x sysoffset 0x%x\n",
regs->pc, mchk_header->size, mchk_header->proc_offset,
DO_DEFAULT_RTC,
DO_CIA_IO,
DO_CIA_BUS,
- machine_check: mikasa_machine_check,
+ machine_check: cia_machine_check,
max_dma_address: ALPHA_MAX_DMA_ADDRESS,
nr_irqs: 32,
{
unsigned char control;
- cli();
+ __cli();
/* Reset periodic interrupt frequency. */
CMOS_WRITE(0x26, RTC_FREQ_SELECT);
CMOS_WRITE(control, RTC_CONTROL);
CMOS_READ(RTC_INTR_FLAGS);
- sti();
+ __sti();
}
#endif
break;
case LINUX_REBOOT_CMD_RESTART:
{
- int v;
+ unsigned char v;
irongate_hose_read_config_byte(0, 0x07<<3, 0x43, &v, 0);
irongate_hose_write_config_byte(0, 0x07<<3, 0x43, v | 0x80, 0);
outb(1, 0x92);
break;
}
- printk(KERN_CRIT "> NAUTILUS Machine check 0x%x [%s]\n", vector, mchk_class);
+ printk(KERN_CRIT "> NAUTILUS Machine check 0x%lx [%s]\n",
+ vector, mchk_class);
if ( cpu_analysis )
ev6_cpu_machine_check( vector,
{
void (*irq_handler)(int, void *, struct pt_regs *);
unsigned int year, mon, day, hour, min, sec, cc1, cc2;
- unsigned long cycle_freq, one_percent;
+ unsigned long cycle_freq, ppm_error;
long diff;
/*
cc1 = cc2;
}
- /* If the given value is within 1% of what we calculated,
- accept it. Otherwise, use what we found. */
- cycle_freq = hwrpb->cycle_freq;
- one_percent = cycle_freq / 100;
+ /* This code used to check for a 1% error.
+ * PWS600au reports 598802395 which is way off. (ntpd has problems.)
+ * So I tightened down the check. Hal Murray, Feb 27, 2000.
+ *
+ * HWRPB cycle_freq may be 0 (uninitialized) due to MILO, so make
+ * sure that we handle this case by forcing use of est_cycle_freq.
+ */
+ if (!(cycle_freq = hwrpb->cycle_freq))
+ cycle_freq = est_cycle_freq;
+
diff = cycle_freq - est_cycle_freq;
if (diff < 0)
diff = -diff;
- if (diff > one_percent) {
+ ppm_error = (diff * 1000000L) / cycle_freq;
+#if 0
+ printk("Alpha clock init: HWRPB %lu, Measured %lu, error=%lu ppm.\n",
+ hwrpb->cycle_freq, est_cycle_freq, ppm_error);
+#endif
+ if (ppm_error > 1000) {
+ printk("HWRPB cycle frequency (%lu) seems inaccurate -"
+ " using the measured value of %lu Hz\n",
+ cycle_freq, est_cycle_freq);
cycle_freq = est_cycle_freq;
- printk("HWRPB cycle frequency bogus. Estimated %lu Hz\n",
- cycle_freq);
}
else {
est_cycle_freq = 0;
got_exception:
/* Ok, we caught the exception, but we don't want it. Is there
someone to pass it along to? */
- if ((fixup = search_exception_table(pc)) != 0) {
+ if ((fixup = search_exception_table(pc, regs.gp)) != 0) {
unsigned long newpc;
newpc = fixup_exception(una_reg, fixup, pc);
# Makefile for alpha-specific library files..
#
+.S.s:
+ $(CC) -D__ASSEMBLY__ $(AFLAGS) -E -o $*.s $<
+.S.o:
+ $(CC) -D__ASSEMBLY__ $(AFLAGS) -c -o $*.o $<
+
OBJS = __divqu.o __remqu.o __divlu.o __remlu.o memset.o memcpy.o io.o \
checksum.o csum_partial_copy.o strlen.o \
strcat.o strcpy.o strncat.o strncpy.o stxcpy.o stxncpy.o \
strchr.o strrchr.o \
copy_user.o clear_user.o strncpy_from_user.o strlen_user.o \
csum_ipv6_magic.o strcasecmp.o semaphore.o \
- srm_dispatch.o srm_fixup.o srm_puts.o srm_printk.o
+ callback_srm.o callback_init.o srm_puts.o srm_printk.o
lib.a: $(OBJS)
$(AR) rcs lib.a $(OBJS)
--- /dev/null
+/*
+ * arch/alpha/lib/callback_init.c
+ */
+
+#include <asm/page.h>
+#include <asm/hwrpb.h>
+#include <asm/console.h>
+#include <asm/pgtable.h>
+#include <asm/init.h>
+
+#include "../kernel/proto.h"
+
+int callback_init_done = 0;
+
+/* This is the SRM version. Maybe there will be a DBM version. */
+
+void * __init callback_init(void * kernel_end)
+{
+ int i, j;
+ unsigned long vaddr = CONSOLE_REMAP_START;
+ struct crb_struct * crb;
+ pgd_t * pgd = pgd_offset_k(vaddr);
+ pmd_t * pmd;
+ void * two_pte_pages;
+
+ /* Always page align the end of the kernel. */
+ kernel_end = (void *)
+ (((unsigned long)kernel_end + ~PAGE_MASK) & PAGE_MASK);
+
+ if (!alpha_using_srm) {
+ switch_to_system_map();
+ return kernel_end;
+ }
+
+ /* Allocate some memory for the pages. */
+ two_pte_pages = kernel_end;
+ kernel_end = two_pte_pages + 2*PAGE_SIZE;
+ memset(two_pte_pages, 0, 2*PAGE_SIZE);
+
+ /* Starting at the HWRPB, locate the CRB. */
+ crb = (struct crb_struct *)((char *)hwrpb + hwrpb->crb_offset);
+
+ /* Tell the console whither the console is to be remapped. */
+ if (srm_fixup(vaddr, (unsigned long)hwrpb))
+ __halt(); /* "We're boned." --Bender */
+
+ /* Edit the procedure descriptors for DISPATCH and FIXUP. */
+ crb->dispatch_va = (struct procdesc_struct *)
+ (vaddr + (unsigned long)crb->dispatch_va - crb->map[0].va);
+ crb->fixup_va = (struct procdesc_struct *)
+ (vaddr + (unsigned long)crb->fixup_va - crb->map[0].va);
+
+ switch_to_system_map();
+
+ /*
+ * Set up the first and second level PTEs for console callbacks.
+ * There is an assumption here that only one of each is needed,
+ * and this allows for 8MB. Currently (late 1999), big consoles
+ * are still under 3MB.
+ */
+ pgd_set(pgd, (pmd_t *)two_pte_pages);
+ pmd = pmd_offset(pgd, vaddr);
+ pmd_set(pmd, (pte_t *)(two_pte_pages + PAGE_SIZE));
+
+ /*
+ * Set up the third level PTEs and update the virtual addresses
+ * of the CRB entries.
+ */
+ for (i = 0; i < crb->map_entries; ++i) {
+ unsigned long paddr = crb->map[i].pa;
+ crb->map[i].va = vaddr;
+ for (j = 0; j < crb->map[i].count; ++j) {
+ set_pte(pte_offset(pmd, vaddr),
+ mk_pte_phys(paddr, PAGE_KERNEL));
+ paddr += PAGE_SIZE;
+ vaddr += PAGE_SIZE;
+ }
+ }
+
+ callback_init_done = 1;
+ return kernel_end;
+}
+
--- /dev/null
+/*
+ * arch/alpha/lib/callback_srm.S
+ */
+
+#include <linux/config.h>
+#include <asm/console.h>
+
+.text
+#define HWRPB_CRB_OFFSET 0xc0
+
+#if defined(CONFIG_ALPHA_SRM) || defined(CONFIG_ALPHA_GENERIC)
+.align 4
+srm_dispatch:
+#if defined(CONFIG_ALPHA_GENERIC)
+ ldl $4,alpha_using_srm
+ beq $4,nosrm
+#endif
+ ldq $0,hwrpb # gp is set up by CALLBACK macro.
+ ldl $25,0($25) # Pick up the wrapper data.
+ mov $20,$21 # Shift arguments right.
+ mov $19,$20
+ ldq $1,HWRPB_CRB_OFFSET($0)
+ mov $18,$19
+ mov $17,$18
+ mov $16,$17
+ addq $0,$1,$2 # CRB address
+ ldq $27,0($2) # DISPATCH procedure descriptor (VMS call std)
+ extwl $25,0,$16 # SRM callback function code
+ ldq $3,8($27) # call address
+ extwl $25,2,$25 # argument information (VMS calling std)
+ jmp ($3) # Return directly to caller of wrapper.
+
+.align 4
+.globl srm_fixup
+.ent srm_fixup
+srm_fixup:
+ ldgp $29,0($27)
+#if defined(CONFIG_ALPHA_GENERIC)
+ ldl $4,alpha_using_srm
+ beq $4,nosrm
+#endif
+ ldq $0,hwrpb
+ ldq $1,HWRPB_CRB_OFFSET($0)
+ addq $0,$1,$2 # CRB address
+ ldq $27,16($2) # VA of FIXUP procedure descriptor
+ ldq $3,8($27) # call address
+ lda $25,2($31) # two integer arguments
+ jmp ($3) # Return directly to caller of srm_fixup.
+.end srm_fixup
+
+#if defined(CONFIG_ALPHA_GENERIC)
+.align 3
+nosrm:
+ lda $0,-1($31)
+ ret
+#endif
+
+#define CALLBACK(NAME, CODE, ARG_CNT) \
+.align 4; .globl callback_##NAME; .ent callback_##NAME; callback_##NAME##: \
+ldgp $29,0($27); br $25,srm_dispatch; .word CODE, ARG_CNT; .end callback_##NAME
+
+#else /* defined(CONFIG_ALPHA_SRM) || defined(CONFIG_ALPHA_GENERIC) */
+
+#define CALLBACK(NAME, CODE, ARG_CNT) \
+.align 3; .globl callback_##NAME; .ent callback_##NAME; callback_##NAME##: \
+lda $0,-1($31); ret; .end callback_##NAME
+
+.align 3
+.globl srm_fixup
+.ent srm_fixup
+srm_fixup:
+ lda $0,-1($31)
+ ret
+.end srm_fixup
+#endif /* defined(CONFIG_ALPHA_SRM) || defined(CONFIG_ALPHA_GENERIC) */
+
+CALLBACK(puts, CCB_PUTS, 4)
+CALLBACK(open, CCB_OPEN, 3)
+CALLBACK(close, CCB_CLOSE, 2)
+CALLBACK(read, CCB_READ, 5)
+CALLBACK(getenv, CCB_GET_ENV, 4)
+CALLBACK(setenv, CCB_SET_ENV, 4)
+CALLBACK(getc, CCB_GETC, 2)
+CALLBACK(reset_term, CCB_RESET_TERM, 2)
+CALLBACK(term_int, CCB_SET_TERM_INT, 3)
+CALLBACK(term_ctl, CCB_SET_TERM_CTL, 3)
+CALLBACK(process_keycode, CCB_PROCESS_KEYCODE, 3)
+CALLBACK(ioctl, CCB_IOCTL, 6)
+CALLBACK(write, CCB_WRITE, 5)
+CALLBACK(reset_env, CCB_RESET_ENV, 4)
+CALLBACK(save_env, CCB_SAVE_ENV, 1)
+CALLBACK(pswitch, CCB_PSWITCH, 3)
+CALLBACK(bios_emul, CCB_BIOS_EMUL, 5)
+
+.data
+__alpha_using_srm: # For use by bootpheader
+ .long 7 # value is not 1 for link debugging
+ .weak alpha_using_srm; alpha_using_srm = __alpha_using_srm
+__callback_init_done: # For use by bootpheader
+ .long 7 # value is not 1 for link debugging
+ .weak callback_init_done; callback_init_done = __callback_init_done
+
extql $3,$7,$3
extqh $2,$7,$1
bis $3,$1,$1
- stq $1,0($6)
+ EXO( stq $1,0($6) )
addq $7,8,$7
subq $0,8,$0
addq $6,8,$6
+++ /dev/null
-/*
- * arch/alpha/lib/srm_dispatch.S
- */
-
-.globl srm_dispatch
-.ent srm_dispatch
-srm_dispatch:
- .frame $30,30,$26
- subq $30,80,$30
- stq $26,0($30)
- stq $8,8($30)
- stq $9,16($30)
- stq $10,24($30)
- stq $11,32($30)
- stq $12,40($30)
- stq $13,48($30)
- stq $14,56($30)
- stq $15,64($30)
- stq $29,72($30)
- .mask 0x2400FF00, -80
- .prologue 0
-
- ldq $1,hwrpb
- ldq $2,0xc0($1) /* crb offset */
- addq $2,$1,$2 /* crb */
- ldq $27,0($2) /* dispatch procedure value */
-
- ldq $2,8($27) /* dispatch call address */
- jsr $26,($2) /* call it (weird VMS call seq) */
-
- ldq $26,0($30)
- ldq $8,8($30)
- ldq $9,16($30)
- ldq $10,24($30)
- ldq $11,32($30)
- ldq $12,40($30)
- ldq $13,48($30)
- ldq $14,56($30)
- ldq $15,64($30)
- ldq $29,72($30)
- addq $30,80,$30
- ret $31,($26),1
-.end srm_dispatch
+++ /dev/null
-/*
- * arch/alpha/lib/srm_fixup.S
- */
-
-.globl srm_fixup
-.ent srm_fixup
-srm_fixup:
- .frame $30,30,$26
- subq $30,80,$30
- stq $26,0($30)
- stq $8,8($30)
- stq $9,16($30)
- stq $10,24($30)
- stq $11,32($30)
- stq $12,40($30)
- stq $13,48($30)
- stq $14,56($30)
- stq $15,64($30)
- stq $29,72($30)
- .mask 0x2400FF00, -80
- .prologue 0
-
- ldq $2,0xc0($17) /* crb offset */
- addq $2,$1,$2 /* crb */
- ldq $27,16($2) /* fixup procedure value */
-
- ldq $2,8($27) /* dispatch call address */
- jsr $26,($2) /* call it (weird VMS call seq) */
-
- ldq $26,0($30)
- ldq $8,8($30)
- ldq $9,16($30)
- ldq $10,24($30)
- ldq $11,32($30)
- ldq $12,40($30)
- ldq $13,48($30)
- ldq $14,56($30)
- ldq $15,64($30)
- ldq $29,72($30)
- addq $30,80,$30
- ret $31,($26),1
-.end srm_fixup
{
static char buf[1024];
va_list args;
- long i;
+ long len, num_lf;
+ char *src, *dst;
va_start(args, fmt);
- i = vsprintf(buf,fmt,args);
+ len = vsprintf(buf, fmt, args);
va_end(args);
- srm_puts(buf);
- return i;
+ /* Count number of linefeeds in string. */
+ num_lf = 0;
+ for (src = buf; *src; ++src) {
+ if (*src == '\n') {
+ ++num_lf;
+ }
+ }
+
+ /* Expand each linefeed into carriage-return/linefeed. */
+ if (num_lf) {
+ for (dst = src + num_lf; src >= buf; ) {
+ if (*src == '\n') {
+ *dst-- = '\r';
+ }
+ *dst-- = *src--;
+ }
+ }
+
+ srm_puts(buf, num_lf+len);
+ return len;
}
#include <linux/string.h>
#include <asm/console.h>
-void
-srm_puts(const char *str)
+long
+srm_puts(const char *str, long len)
{
- /* Expand \n to \r\n as we go. */
+ long remaining, written;
- while (*str) {
- long len;
- const char *e = str;
+ if (!callback_init_done)
+ return len;
- if (*str == '\n') {
- if (srm_dispatch(CCB_PUTS, 0, "\r", 1) < 0)
- return;
- ++e;
- }
-
- e = strchr(e, '\n') ? : strchr(e, '\0');
- len = e - str;
-
- while (len > 0) {
- long written = srm_dispatch(CCB_PUTS, 0, str, len);
- if (written < 0)
- return;
- len -= written & 0xffffffff;
- str += written & 0xffffffff;
- }
- }
+ for (remaining = len; remaining > 0; remaining -= written)
+ {
+ written = callback_puts(0, str, remaining);
+ written &= 0xffffffff;
+ str += written;
+ }
+ return len;
}
register unsigned long gp __asm__("$29");
-unsigned
-search_exception_table(unsigned long addr)
+static unsigned
+search_exception_table_without_gp(unsigned long addr)
{
unsigned ret;
return 0;
}
+
+unsigned
+search_exception_table(unsigned long addr, unsigned long exc_gp)
+{
+ unsigned ret;
+
+#ifndef CONFIG_MODULES
+ ret = search_one_table(__start___ex_table, __stop___ex_table - 1,
+ addr - exc_gp);
+ if (ret) return ret;
+#else
+ /* The kernel is the last "module" -- no need to treat it special. */
+ struct module *mp;
+ for (mp = module_list; mp ; mp = mp->next) {
+ if (!mp->ex_table_start)
+ continue;
+ ret = search_one_table(mp->ex_table_start,
+ mp->ex_table_end - 1, addr - exc_gp);
+ if (ret) return ret;
+ }
+#endif
+
+ /*
+ * The search failed with the exception gp. To be safe, try the
+ * old method before giving up.
+ */
+ ret = search_exception_table_without_gp(addr);
+ if (ret) {
+ printk(KERN_ALERT, "%s: [%lx] EX_TABLE search fail with"
+ "exc frame GP, success with raw GP\n",
+ current->comm, addr);
+ return ret;
+ }
+ return 0;
+}
no_context:
/* Are we prepared to handle this fault as an exception? */
- if ((fixup = search_exception_table(regs->pc)) != 0) {
+ if ((fixup = search_exception_table(regs->pc, regs->gp)) != 0) {
unsigned long newpc;
newpc = fixup_exception(dpf_reg, fixup, regs->pc);
-#if 0
- printk("%s: Exception at [<%lx>] (%lx)\n",
+#if 1
+ printk("%s: Exception at [<%lx>] (%lx) handled successfully.\n",
current->comm, regs->pc, newpc);
#endif
regs->pc = newpc;
return (struct thread_struct *) __reload_tss(pcb);
}
+void
+switch_to_system_map(void)
+{
+ unsigned long newptbr;
+ struct thread_struct *original_pcb_ptr;
+
+ memset(swapper_pg_dir, 0, PAGE_SIZE);
+ newptbr = ((unsigned long) swapper_pg_dir - PAGE_OFFSET) >> PAGE_SHIFT;
+ pgd_val(swapper_pg_dir[1023]) =
+ (newptbr << 32) | pgprot_val(PAGE_KERNEL);
+
+
+ /* Also set up the real kernel PCB while we're at it. */
+ init_task.tss.ptbr = newptbr;
+ init_task.tss.pal_flags = 1; /* set FEN, clear everything else */
+ init_task.tss.flags = 0;
+
+ hwrpb->vptb = 0xfffffffe00000000;
+ hwrpb_update_checksum(hwrpb);
+
+ wrvptptr(0xfffffffe00000000);
+ original_pcb_ptr = load_PCB(&init_task.tss);
+ tbia();
+
+ /* Save off the contents of the original PCB so that we can
+ restore the original console's page tables for a clean reboot.
+
+ Note that the PCB is supposed to be a physical address, but
+ since KSEG values also happen to work, folks get confused.
+ Check this here. */
+
+ if ((unsigned long)original_pcb_ptr < PAGE_OFFSET) {
+ original_pcb_ptr = (struct thread_struct *)
+ phys_to_virt((unsigned long) original_pcb_ptr);
+ }
+ original_pcb = *original_pcb_ptr;
+}
+
/*
* paging_init() sets up the page tables: in the alpha version this actually
* unmaps the bootup page table (as we're now in KSEG, so we don't need it).
paging_init(unsigned long start_mem, unsigned long end_mem)
{
int i;
- unsigned long newptbr;
struct memclust_struct * cluster;
struct memdesc_struct * memdesc;
- struct thread_struct *original_pcb_ptr;
/* initialize mem_map[] */
start_mem = free_area_init(start_mem, end_mem);
clear_bit(PG_reserved, &mem_map[pfn++].flags);
}
- /* Initialize the kernel's page tables. Linux puts the vptb in
- the last slot of the L1 page table. */
memset((void *) ZERO_PAGE(0), 0, PAGE_SIZE);
- memset(swapper_pg_dir, 0, PAGE_SIZE);
- newptbr = MAP_NR(swapper_pg_dir);
- pgd_val(swapper_pg_dir[1023]) =
- (newptbr << 32) | pgprot_val(PAGE_KERNEL);
-
- /* Set the vptb. This is often done by the bootloader, but
- shouldn't be required. */
- if (hwrpb->vptb != 0xfffffffe00000000) {
- wrvptptr(0xfffffffe00000000);
- hwrpb->vptb = 0xfffffffe00000000;
- hwrpb_update_checksum(hwrpb);
- }
-
- /* Also set up the real kernel PCB while we're at it. */
- init_task.tss.ptbr = newptbr;
- init_task.tss.pal_flags = 1; /* set FEN, clear everything else */
- init_task.tss.flags = 0;
- original_pcb_ptr = load_PCB(&init_task.tss);
- tbia();
-
- /* Save off the contents of the original PCB so that we can
- restore the original console's page tables for a clean reboot.
-
- Note that the PCB is supposed to be a physical address, but
- since KSEG values also happen to work, folks get confused.
- Check this here. */
-
- if ((unsigned long)original_pcb_ptr < PAGE_OFFSET) {
- original_pcb_ptr = (struct thread_struct *)
- phys_to_virt((unsigned long) original_pcb_ptr);
- }
- original_pcb = *original_pcb_ptr;
return start_mem;
}
OUTPUT_FORMAT("elf64-alpha")
ENTRY(__start)
+PHDRS { kernel PT_LOAD ; }
SECTIONS
{
. = 0xfffffc0000310000;
_text = .;
- .text : { *(.text) }
+ .text : { *(.text) } :kernel
.text2 : { *(.text2) }
_etext = .;
if (!strncmp(id->model, "KODAK ATA_FLASH", 15) /* Kodak */
|| !strncmp(id->model, "Hitachi CV", 10) /* Hitachi */
|| !strncmp(id->model, "SunDisk SDCFB", 13) /* SunDisk */
+ || !strncmp(id->model, "ATA_FLASH", 9) /* Simple Tech */
|| !strncmp(id->model, "HAGIWARA HPC", 12)) /* Hagiwara */
{
return 1; /* yes, it is a flash memory card */
* so we just sleep for a little while and let it do it's thing
*/
current->state = TASK_INTERRUPTIBLE;
- schedule_timeout(3*HZ);
+ schedule_timeout(5*HZ);
if(i2o_claim_device(d, &i2o_block_handler))
{
static int i2o_cfg_context = -1;
static void *page_buf;
static void *i2o_buffer;
-static spinlock_t i2o_config_lock = SPIN_LOCK_UNLOCKED;
+static spinlock_t i2o_queue_lock = SPIN_LOCK_UNLOCKED;
+
struct wait_queue *i2o_wait_queue;
#define MODINC(x,y) (x = x++ % y)
(unsigned char *)(msg + 5),
inf->event_q[inf->q_in].data_size);
- spin_lock(&i2o_config_lock);
+ spin_lock(&i2o_queue_lock);
MODINC(inf->q_in, I2O_EVT_Q_LEN);
if(inf->q_len == I2O_EVT_Q_LEN)
{
// Keep I2OEVTGET on another CPU from touching this
inf->q_len++;
}
- spin_unlock(&i2o_config_lock);
+ spin_unlock(&i2o_queue_lock);
// printk(KERN_INFO "File %p w/id %d has %d events\n",
memcpy(&kget.info, &p->event_q[p->q_out], sizeof(struct i2o_evt_info));
MODINC(p->q_out, I2O_EVT_Q_LEN);
- spin_lock_irqsave(&i2o_config_lock, flags);
+ spin_lock_irqsave(&i2o_queue_lock, flags);
+ /* FIXME - ought to lock the q_ values here!! */
p->q_len--;
kget.pending = p->q_len;
kget.lost = p->q_lost;
- spin_unlock_irqrestore(&i2o_config_lock, flags);
+ spin_unlock_irqrestore(&i2o_queue_lock, flags);
__copy_to_user(uget, &kget, sizeof(struct i2o_evt_get));
tmp->q_lost = 0;
tmp->next = open_files;
- spin_lock_irqsave(&i2o_config_lock, flags);
+ spin_lock_irqsave(&i2o_queue_lock, flags);
open_files = tmp;
- spin_unlock_irqrestore(&i2o_config_lock, flags);
+ spin_unlock_irqrestore(&i2o_queue_lock, flags);
MOD_INC_USE_COUNT;
return 0;
p1 = p2 = NULL;
- spin_lock_irqsave(&i2o_config_lock, flags);
+ spin_lock_irqsave(&i2o_queue_lock, flags);
for(p1 = open_files; p1; )
{
if(p1->q_id == id)
p2 = p1;
p1 = p1->next;
}
- spin_unlock_irqrestore(&i2o_config_lock, flags);
+ spin_unlock_irqrestore(&i2o_queue_lock, flags);
MOD_DEC_USE_COUNT;
return 0;
#define MODINC(x,y) (x = x++ % y)
/*
- * I2O configuration spinlock. This isnt a big deal for contention
+ * I2O configuration semaphore. This isnt a big deal for contention
* so we have one only
*/
-static spinlock_t i2o_configuration_lock = SPIN_LOCK_UNLOCKED;
+static struct semaphore i2o_configuration_lock = MUTEX;
/*
int i2o_install_handler(struct i2o_handler *h)
{
int i;
- spin_lock(&i2o_configuration_lock);
+ down(&i2o_configuration_lock);
for(i=0;i<MAX_I2O_MODULES;i++)
{
if(i2o_handlers[i]==NULL)
{
h->context = i;
i2o_handlers[i]=h;
- spin_unlock(&i2o_configuration_lock);
+ up(&i2o_configuration_lock);
return 0;
}
}
- spin_unlock(&i2o_configuration_lock);
+ up(&i2o_configuration_lock);
return -ENOSPC;
}
{
int i;
- spin_lock(&i2o_configuration_lock);
+ down(&i2o_configuration_lock);
d->controller=c;
d->owner=NULL;
d->next=c->devices;
for(i = 0; i < I2O_MAX_MANAGERS; i++)
d->managers[i] = NULL;
- spin_unlock(&i2o_configuration_lock);
+ up(&i2o_configuration_lock);
return 0;
}
{
int ret;
- spin_lock(&i2o_configuration_lock);
+ down(&i2o_configuration_lock);
ret = __i2o_delete_device(d);
- spin_unlock(&i2o_configuration_lock);
+ up(&i2o_configuration_lock);
return ret;
}
int i2o_install_controller(struct i2o_controller *c)
{
int i;
- spin_lock(&i2o_configuration_lock);
+ down(&i2o_configuration_lock);
for(i=0;i<MAX_I2O_CONTROLLERS;i++)
{
if(i2o_controllers[i]==NULL)
sprintf(c->name, "i2o/iop%d", i);
i2o_num_controllers++;
sema_init(&c->lct_sem, 0);
- spin_unlock(&i2o_configuration_lock);
+ up(&i2o_configuration_lock);
return 0;
}
}
printk(KERN_ERR "No free i2o controller slots.\n");
- spin_unlock(&i2o_configuration_lock);
+ up(&i2o_configuration_lock);
return -EBUSY;
}
if(c->status_block->iop_state == ADAPTER_STATE_OPERATIONAL)
i2o_event_register(c, core_context, 0, 0, 0);
- spin_lock(&i2o_configuration_lock);
+ down(&i2o_configuration_lock);
if((users=atomic_read(&c->users)))
{
printk(KERN_INFO "%s busy: %d users for controller.\n", c->name, users);
c->bus_disable(c);
- spin_unlock(&i2o_configuration_lock);
+ up(&i2o_configuration_lock);
return -EBUSY;
}
while(c->devices)
{
/* Shouldnt happen */
c->bus_disable(c);
- spin_unlock(&i2o_configuration_lock);
+ up(&i2o_configuration_lock);
return -EBUSY;
}
}
c->destructor(c);
*p=c->next;
- spin_unlock(&i2o_configuration_lock);
+ up(&i2o_configuration_lock);
if(c->page_frame)
kfree(c->page_frame);
}
p=&((*p)->next);
}
- spin_unlock(&i2o_configuration_lock);
+ up(&i2o_configuration_lock);
printk(KERN_ERR "i2o_delete_controller: bad pointer!\n");
return -ENOENT;
}
if(n<0 || n>=MAX_I2O_CONTROLLERS)
return NULL;
- spin_lock(&i2o_configuration_lock);
+ down(&i2o_configuration_lock);
c=i2o_controllers[n];
if(c!=NULL)
atomic_inc(&c->users);
- spin_unlock(&i2o_configuration_lock);
+ up(&i2o_configuration_lock);
return c;
}
*/
int i2o_claim_device(struct i2o_device *d, struct i2o_handler *h)
{
- spin_lock(&i2o_configuration_lock);
+ down(&i2o_configuration_lock);
if(d->owner)
{
printk(KERN_INFO "issue claim called, but dev has owner!");
- spin_unlock(&i2o_configuration_lock);
+ up(&i2o_configuration_lock);
return -EBUSY;
}
if(i2o_issue_claim(d->controller,d->lct_data.tid, h->context, 1, I2O_CLAIM_PRIMARY))
{
- spin_unlock(&i2o_configuration_lock);
+ up(&i2o_configuration_lock);
return -EBUSY;
}
d->owner=h;
- spin_unlock(&i2o_configuration_lock);
+ up(&i2o_configuration_lock);
return 0;
}
{
int err = 0;
- spin_lock(&i2o_configuration_lock);
+ down(&i2o_configuration_lock);
if(d->owner != h)
{
- spin_unlock(&i2o_configuration_lock);
+ up(&i2o_configuration_lock);
return -ENOENT;
}
d->owner = NULL;
- spin_unlock(&i2o_configuration_lock);
+ up(&i2o_configuration_lock);
return err;
}
u32 *msg;
long time;
- printk("begin RESET\n");
+ dprintk(("begin RESET\n"));
/* Quiesce all IOPs first */
for (iop = i2o_controller_chain; iop; iop = iop->next)
* as we can't init the IOPs w/o a system table
*/
- printk("SYSTAB\n");
+ dprintk(("SYSTAB\n"));
if (i2o_build_sys_table() < 0) {
i2o_sys_shutdown();
return;
}
- printk("ONLINE\n");
+ dprintk(("ONLINE\n"));
/* If IOP don't get online, we need to rebuild the System table */
for (iop = i2o_controller_chain; iop; iop = niop) {
goto rebuild_sys_tab;
}
- printk("ACTIVE\n");
+ dprintk(("ACTIVE\n"));
/* Active IOPs now in OPERATIONAL state
*
i2o_event_register(iop, core_context, 0, 0, 0xFFFFFFFF);
}
- printk("DONE\n");
+ dprintk(("DONE\n"));
}
/*
{
/* In INIT state, Wait Inbound Q to initilaize (in i2o_status_get) */
/* In READY state, Get status */
- u32 m;
- printk("ACTIVATE\n");
+ dprintk(("ACTIVATE\n"));
if (i2o_status_get(iop) < 0) {
printk(KERN_INFO "Unable to obtain status of IOP, attempting a reset.\n");
{
dprintk((KERN_INFO "%s: already running...trying to reset\n",
iop->name));
- printk("Outbound q2\n");
-
- if (i2o_init_outbound_q(iop) < 0) {
- i2o_reset_controller(iop);
+ dprintk(("Outbound q2\n"));
- if (i2o_status_get(iop) < 0 ||
- iop->status_block->iop_state != ADAPTER_STATE_RESET)
- {
- printk(KERN_CRIT "%s: Failed to initialize.\n", iop->name);
- i2o_delete_controller(iop);
- return -1;
- }
- if (i2o_init_outbound_q(iop) < 0) {
- i2o_delete_controller(iop);
- return -1;
- }
- }
- }
- else
- {
- printk("Outbound q\n");
-
- if (i2o_init_outbound_q(iop) < 0) {
+ i2o_reset_controller(iop);
+ if (i2o_status_get(iop) < 0 || iop->status_block->iop_state != ADAPTER_STATE_RESET)
+ {
+ printk(KERN_CRIT "%s: Failed to initialize.\n", iop->name);
i2o_delete_controller(iop);
return -1;
}
}
+ if (i2o_init_outbound_q(iop) < 0) {
+ i2o_delete_controller(iop);
+ return -1;
+ }
+
/* In HOLD state */
- printk("HRT\n");
+ dprintk("HRT\n");
if (i2o_hrt_get(iop) < 0) {
i2o_delete_controller(iop);
return -1;
}
- printk("DONE\n");
+ dprintk("DONE\n");
return 0;
}
{
if(i2o_handlers[i] && i2o_handlers[i]->new_dev_notify && (i2o_handlers[i]->class&d->lct_data.class_id))
{
- spin_lock(&i2o_dev_lock);
+ spin_lock_irqsave(&i2o_dev_lock, flags);
i2o_handlers[i]->new_dev_notify(c,d);
- spin_unlock(&i2o_dev_lock);
+ spin_unlock_irqrestore(&i2o_dev_lock, flags);
}
}
void *tmp;
char name[16];
struct fs_struct *fs;
+ unsigned long flags;
lock_kernel();
if(!found)
{
dprintk((KERN_INFO "Deleted device!\n"));
- spin_lock(&i2o_dev_lock);
+ spin_lock_irqsave(&i2o_dev_lock,flags);
i2o_delete_device(d);
- spin_unlock(&i2o_dev_lock);
+ spin_unlock_irqrestore(&i2o_dev_lock,flags);
}
d = d1;
}
* The RightSwitch is a 4 (EISA) or 6 (PCI) port etherswitch and
* a NIC on an internal board.
*
- * Author: Rick Richardson, rick@dgii.com, rick_richardson@dgii.com
+ * Author: Rick Richardson, rick@remotepoint.com
* Derived from the SVR4.2 (UnixWare) driver for the same card.
*
* Copyright 1995-1996 Digi International Inc.
*
*/
-static char *version = "$Id: dgrs.c,v 1.12 1996/12/21 13:43:58 rick Exp $";
+static char *version = "$Id: dgrs.c,v 1.13 2000/06/06 04:07:00 rick Exp $";
#include <linux/version.h>
#include <linux/module.h>
I596_RFD *rfdp; /* Current RFD list */
I596_RBD *rbdp; /* Current RBD list */
- int intrcnt; /* Count of interrupts */
+ volatile int intrcnt; /* Count of interrupts */
/*
* SE-4 (EISA) board variables
*/
if (priv->plxreg)
OUTL(dev->base_addr + PLX_LCL2PCI_DOORBELL, 1);
- rc = request_irq(dev->irq, &dgrs_intr, 0, "RightSwitch", dev);
+ rc = request_irq(dev->irq, &dgrs_intr, SA_SHIRQ, "RightSwitch", dev);
if (rc)
return (rc);
#ifndef MODULE
int via_rhine_probe(struct device *dev)
{
- printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
+ static int did_version = 0;
+ if (!did_version++)
+ printk(KERN_INFO "%s" KERN_INFO "%s", versionA, versionB);
return pci_etherdev_probe(dev, pci_tbl);
}
#endif
error = ncp_del_file_or_subdir2(NCP_SERVER(dir), dentry);
#ifdef CONFIG_NCPFS_STRONG
- /* 9C is Invalid path.. It should be 8F, 90 - read only, but
- it is not :-( */
- if (error == 0x9C && NCP_SERVER(dir)->m.flags & NCP_MOUNT_STRONG) { /* R/O */
+ /* 9C is Invalid path, used by traditional NW filesystem...
+ 8F, 90 is Some/All read-only and is used by NSS :-( */
+ if ((error == 0x9C || error == 0x8F || error == 0x90) && NCP_SERVER(dir)->m.flags & NCP_MOUNT_STRONG) { /* R/O */
error = ncp_force_unlink(dir, dentry);
}
#endif
old_dir, _old_name,
new_dir, _new_name);
#ifdef CONFIG_NCPFS_STRONG
- if ((error == 0x90 || error == -EACCES) && NCP_SERVER(old_dir)->m.flags & NCP_MOUNT_STRONG) { /* RO */
+ if ((error == 0x90 || error == 0x8B || error == -EACCES) && NCP_SERVER(old_dir)->m.flags & NCP_MOUNT_STRONG) { /* RO */
error = ncp_force_rename(old_dir, old_dentry, _old_name,
new_dir, new_dentry, _new_name);
}
switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
case aHIDDEN:
if (server->m.flags & NCP_MOUNT_SYMLINKS) {
- if ((inode->i_size >= NCP_MIN_SYMLINK_SIZE)
- && (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
+ if (inode->i_size <= NCP_MAX_SYMLINK_SIZE) {
inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
break;
}
switch (nwi->attributes & (aHIDDEN|aSYSTEM)) {
case aHIDDEN:
if (server->m.flags & NCP_MOUNT_SYMLINKS) {
- if ((inode->i_size >= NCP_MIN_SYMLINK_SIZE)
- && (inode->i_size <= NCP_MAX_SYMLINK_SIZE)) {
+ if (inode->i_size <= NCP_MAX_SYMLINK_SIZE) {
inode->i_mode = (inode->i_mode & ~S_IFMT) | S_IFLNK;
break;
}
goto repeat;
}
else {
+ brelse (bh);
return NULL;
}
}
#define CCB_GET_ENV 0x22
#define CCB_SAVE_ENV 0x23
+#define CCB_PSWITCH 0x30
+#define CCB_BIOS_EMUL 0x32
/*
* Environment variable numbers
*/
#define ENV_BOOT_RESET 0x09
#define ENV_DUMP_DEV 0x0A
#define ENV_ENABLE_AUDIT 0x0B
-#define ENV_LICENCE 0x0C
+#define ENV_LICENSE 0x0C
#define ENV_CHAR_SET 0x0D
#define ENV_LANGUAGE 0x0E
#define ENV_TTY_DEV 0x0F
+#define NO_SRM_CONSOLE -1L
+
#ifdef __KERNEL__
-extern long srm_dispatch(long code, ...);
-extern void srm_puts(const char *);
+#ifndef __ASSEMBLY__
+extern long callback_puts(long unit, const char *s, long length);
+extern long callback_open(const char *device, long length);
+extern long callback_close(long unit);
+extern long callback_read(long channel, long count, const char *buf, long lbn);
+extern long callback_getenv(long id, const char *buf, unsigned long buf_size);
+
+extern int srm_fixup(unsigned long new_callback_addr,
+ unsigned long new_hwrpb_addr);
+extern long srm_puts(const char *, long len);
extern long srm_printk(const char *, ...)
__attribute__ ((format (printf, 1, 2)));
struct crb_struct;
struct hwrpb_struct;
-extern long srm_fixup(struct crb_struct *, struct hwrpb_struct *);
+
+extern int callback_init_done;
+extern void * callback_init(void *);
+#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
#endif /* __AXP_CONSOLE_H */
tsunami_64 mpr2;
tsunami_64 mpr3;
tsunami_64 mctl;
+ tsunami_64 __pad1;
tsunami_64 ttr;
tsunami_64 tdr;
tsunami_64 dim2;
unsigned long dsr_offset; /* "Dynamic System Recognition Data Block Table" */
};
+#define HWRPB_MEMBER_ID(v) (((v) >> 10) & 0x3f)
+
#ifdef __KERNEL__
extern struct hwrpb_struct *hwrpb;
* in <asm/page.h> (currently 8192).
*/
#include <linux/config.h>
+#include <linux/mm.h>
#include <asm/system.h>
#include <asm/processor.h> /* For TASK_SIZE */
/* Number of pointers that fit on a page: this will go away. */
#define PTRS_PER_PAGE (1UL << (PAGE_SHIFT-3))
-#define VMALLOC_START 0xFFFFFE0000000000
+#define CONSOLE_REMAP_START 0xFFFFFE0000000000
+#define VMALLOC_START (CONSOLE_REMAP_START + PMD_SIZE)
#define VMALLOC_VMADDR(x) ((unsigned long)(x))
#define VMALLOC_END (~0UL)
#define draina() \
__asm__ __volatile__ ("call_pal %0 #draina" : : "i" (PAL_draina) : "memory")
+#define __halt() \
+__asm__ __volatile__ ("call_pal %0 #halt" : : "i" (PAL_halt))
+
enum implver_enum {
IMPLVER_EV4,
IMPLVER_EV5,
};
/* Returns 0 if exception not found and fixup.unit otherwise. */
-extern unsigned search_exception_table(unsigned long);
+extern unsigned search_exception_table(unsigned long, unsigned long);
/* Returns the new pc */
#define fixup_exception(map_reg, fixup_unit, pc) \