diff -ruN dist-2.4.5/drivers/cobalt/README cobalt-2.4.5/drivers/cobalt/README --- dist-2.4.5/drivers/cobalt/README Wed Dec 31 16:00:00 1969 +++ cobalt-2.4.5/drivers/cobalt/README Thu May 31 14:32:15 2001 @@ -0,0 +1,19 @@ +Notes on Cobalt's drivers: + +You will notice in several places constructs such as this: + + if (cobt_is_3k()) { + foo(); + } else if (cobt_is_5k()) { + bar(); + } + +The goal here is to only compile in code that is needed, but to allow one to +define support for both 3k and 5k (and more?) style systems. The systype +check macros are very simple and clean. They check whether config-time +support for the generation has been enabled, and (if so) whether systype +detected the specified generation. This leaves the code free from #ifdef +cruft, but lets the compiler throw out unsupported generation-specific code +with if (0) detection. + +-- diff -ruN dist-2.4.5/drivers/cobalt/ruler.c cobalt-2.4.5/drivers/cobalt/ruler.c --- dist-2.4.5/drivers/cobalt/ruler.c Wed Dec 31 16:00:00 1969 +++ cobalt-2.4.5/drivers/cobalt/ruler.c Thu May 31 14:32:15 2001 @@ -0,0 +1,393 @@ +/* + * cobalt ruler driver + * Copyright (c) 2000, Cobalt Networks, Inc. + * $Id: ruler.c,v 1.10 2001/05/30 07:19:48 thockin Exp $ + * + * author: asun@cobalt.com, thockin@sun.com + * + * This should be SMP safe. There are two critical pieces of data, and thsu + * two locks. The ruler_lock protects the arrays of channels(hwifs) and + * busproc function pointers. These are only ever written in the + * register/unregister functions but read in several other places. A + * read/write lock is appropriate. The second lock is the lock on the sled + * led state and the I2C_DEV_RULER. It gets called from timer context, so + * irqsave it. The global switches and sled_leds are atomic_t. --TPH + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define RULER_TIMEOUT (HZ >> 1) /* .5s */ +#define MAX_COBT_DRIVES 4 +#define LED_SLED0 (1 << 3) +#define LED_SLED1 (1 << 2) +#define LED_SLED2 (1 << 1) +#define LED_SLED3 (1 << 0) + +/* all of this is for gen V */ +static struct timer_list cobalt_ruler_timer; +static rwlock_t ruler_lock = RW_LOCK_UNLOCKED; +static spinlock_t rled_lock = SPIN_LOCK_UNLOCKED; +static ide_hwif_t *channels[MAX_COBT_DRIVES]; +static ide_busproc_t *busprocs[MAX_COBT_DRIVES]; +/* NOTE: switches is a bitmask of DETACHED sleds */ +static atomic_t switches = ATOMIC_INIT(0); +static atomic_t sled_leds = ATOMIC_INIT(0); +static int sled_led_map[] = {LED_SLED0, LED_SLED1, LED_SLED2, LED_SLED3}; +static int ruler_detect; + +static inline u8 +read_switches(void) +{ + u8 state = 0; + if (cobt_is_5k()) { + int tries = 3; + + /* i2c can be busy, and this can read wrong - try a few times */ + while (tries--) { + state = cobalt_i2c_read_byte(COBALT_I2C_DEV_DRV_SWITCH, + 0); + if ((state & 0xf0) != 0xf0) { + break; + } + } + } + + return state; +} + +/* + * deal with sled leds: LED on means OK to remove + * NOTE: all the reset lines are kept high. + * NOTE: the reset lines are in the reverse order of the switches. + */ +static void +set_sled_leds(u8 leds) +{ + if (cobt_is_5k()) { + unsigned long flags; + + spin_lock_irqsave(&rled_lock, flags); + + atomic_set(&sled_leds, leds); + leds |= 0xf0; + cobalt_i2c_write_byte(COBALT_I2C_DEV_RULER, 0, leds); + + spin_unlock_irqrestore(&rled_lock, flags); + } +} + +static inline u8 +get_sled_leds(void) +{ + return atomic_read(&sled_leds); +} + +/* this must be called with the ruler_lock held for read */ +static int +do_busproc(int idx, ide_hwif_t *hwif, int arg) +{ + if (cobt_is_5k()) { + /* sed sled LEDs */ + switch (arg) { + case BUSSTATE_ON: + set_sled_leds(get_sled_leds() & + ~sled_led_map[idx]); + break; + case BUSSTATE_OFF: + case BUSSTATE_TRISTATE: + set_sled_leds(get_sled_leds() | + sled_led_map[idx]); + break; + default: + WPRINTK("unknown busproc argument (%d)\n", arg); + } + } + + /* do the real work */ + return busprocs[idx](hwif, arg); +} + +static void +ruler_timer_fn(unsigned long data) +{ + if (cobt_is_5k()) { + u8 state; + int i; + unsigned int now, expected, bit, swcur; + + state = read_switches(); + if ((state & 0xf0) == 0xf0) { + return; + } + swcur = atomic_read(&switches); + + state &= 0xf; + read_lock(&ruler_lock); + for (i = 0; i < MAX_COBT_DRIVES; i++) { + bit = 1 << i; + now = state & bit; + expected = swcur & bit; + if (now == expected) { + /* no changes to worry about */ + continue; + } + + if (now) { + /* a freshly detached drive */ + atomic_set(&switches, swcur | bit); + if (channels[i]) { + printk("disabling ide ruler " + "channel %d\n", i); + do_busproc(i, channels[i], + BUSSTATE_TRISTATE); + } else { + WPRINTK("drive detach on bad " + "channel (%d)\n", i); + } + set_sled_leds(get_sled_leds() | + sled_led_map[i]); + } else { + /* + * do we want to do anything when a re-attach + * is detected? + */ + } + } + read_unlock(&ruler_lock); + } +} + +static void +ruler_interrupt(int irq, void *dev_id, struct pt_regs *regs) +{ + if (cobt_is_5k() && ruler_detect) { + u8 state; + + state = read_switches(); + if ((state & 0xf0) != 0xf0) { + /* this is protected inside mod_timer */ + mod_timer(&cobalt_ruler_timer, jiffies + RULER_TIMEOUT); + } + + /* empirical: delay enough to debounce */ + udelay(10); + } +} + +#if defined(CONFIG_COBALT_LED) +/* figure which LEDs to blink */ +static unsigned int +ide_led_handler(void *data) +{ + unsigned int leds = 0; + + if (cobt_is_5k()) { + int i; + static int ledmap[MAX_COBT_DRIVES] = { + LED_DISK0, LED_DISK1, LED_DISK2, LED_DISK3 + }; + static unsigned long old[MAX_COBT_DRIVES]; + + read_lock(&ruler_lock); + + for (i = 0; i < MAX_COBT_DRIVES; i++) { + if (channels[i] && channels[i]->drives[0].present + && channels[i]->drives[0].service_start != old[i]) { + leds |= ledmap[i]; + old[i] = channels[i]->drives[0].service_start; + } + } + + read_unlock(&ruler_lock); + } + + return leds; +} +#endif + +/* this is essentially an exported function - it is in the hwif structs */ +static int +ruler_busproc_fn(ide_hwif_t *hwif, int arg) +{ + int r = 0; + + if (cobt_is_5k()) { + int idx; + + read_lock(&ruler_lock); + + for (idx = 0; idx < MAX_COBT_DRIVES; idx++) { + if (channels[idx] == hwif) { + break; + } + } + + if (idx >= MAX_COBT_DRIVES) { + /* not a hwif we manage? */ + return 0; + } + + r = do_busproc(idx, hwif, arg); + + read_unlock(&ruler_lock); + + } + + return r; +} + +/* + * We try to be VERY explicit here. Fine for now, may eventually break down. + */ +void +cobalt_ruler_register(ide_hwif_t *hwif) +{ + if (cobt_is_5k()) { + struct pci_dev *dev; + int idx; + unsigned long flags; + + if (!hwif) { + return; + } + + /* Cobalt rulers only have HPT370 controllers on bus 1 */ + dev = hwif->pci_dev; + if (dev->vendor != PCI_VENDOR_ID_TTI + || dev->device != PCI_DEVICE_ID_TTI_HPT366 + || dev->bus->number != 1) { + /* ignore it */ + return; + } + + /* IDE ruler has controllers at dev 3 and 4, ONLY */ + if (dev->devfn == PCI_DEVFN(3,0)) { + idx = hwif->channel; + } else if (dev->devfn == PCI_DEVFN(4,0)) { + idx = 2 + hwif->channel; + } else { + return; + } + + if (idx >= MAX_COBT_DRIVES) { + return; + } + + write_lock_irqsave(&ruler_lock, flags); + + /* save a pointer to the hwif, and trap it's busproc() */ + channels[idx] = hwif; + if (hwif->busproc) { + busprocs[idx] = hwif->busproc; + hwif->busproc = ruler_busproc_fn; + } + + write_unlock_irqrestore(&ruler_lock, flags); + + /* the associated switch should be closed */ + if (hwif->drives[0].present) { + /* set the sled LED off - not safe to remove */ + set_sled_leds(get_sled_leds() & ~sled_led_map[idx]); + } + } +} + +void +cobalt_ruler_unregister(ide_hwif_t *hwif) +{ + if (cobt_is_5k()) { + int i; + unsigned long flags; + + write_lock_irqsave(&ruler_lock, flags); + + for (i = 0; i < MAX_COBT_DRIVES; i++) { + if (channels[i] == hwif) { + channels[i] = NULL; + hwif->busproc = busprocs[i]; + busprocs[i] = NULL; + } + } + + write_unlock_irqrestore(&ruler_lock, flags); + } +} + +void +cobalt_ruler_powerdown(void) +{ + if (cobt_is_5k()) { + unsigned long flags; + spin_lock_irqsave(&rled_lock, flags); + cobalt_i2c_write_byte(COBALT_I2C_DEV_RULER, 0, 0x0); + atomic_set(&sled_leds, 0); + spin_unlock_irqrestore(&rled_lock, flags); + } +} + +int __init +cobalt_ruler_init(void) +{ + if (cobt_is_5k()) { + int err; + u8 tmp; + + /* initialize switches */ + tmp = read_switches(); + ruler_detect = ((tmp & 0xf0) == 0xf0) ? 0 : 1; + tmp &= 0xf; + atomic_set(&switches, tmp); + + /* initialize space for hwif variables */ + memset(channels, 0, sizeof(channels)); + + /* initialize our timer */ + init_timer(&cobalt_ruler_timer); + cobalt_ruler_timer.function = ruler_timer_fn; + + /* register an interrupt handler */ + err = cobalt_acpi_register_handler(ruler_interrupt); + if (err) { + EPRINTK("can't register interrupt handler %p\n", + ruler_interrupt); + } + + /* set initial sled LED state */ + set_sled_leds(LED_SLED0 | LED_SLED1 | LED_SLED2 | LED_SLED3); + + /* register for a blinky LEDs callback */ +#if defined(CONFIG_COBALT_LED) + err = cobalt_fpled_register(ide_led_handler, NULL); + if (err) { + EPRINTK("can't register LED handler %p\n", + ide_led_handler); + } +#endif + + printk(KERN_INFO "Cobalt Networks ruler driver v1.2\n"); + } + + return 0; +} diff -ruN dist-2.4.5/drivers/cobalt/serialnum.c cobalt-2.4.5/drivers/cobalt/serialnum.c --- dist-2.4.5/drivers/cobalt/serialnum.c Wed Dec 31 16:00:00 1969 +++ cobalt-2.4.5/drivers/cobalt/serialnum.c Thu May 31 14:32:15 2001 @@ -0,0 +1,476 @@ +/* $Id: serialnum.c,v 1.4 2001/05/30 07:19:48 thockin Exp $ */ +/* + * + * Author: Philip Gladstone, Axent Technologies + * modified for Nat Semi PC[89]7317 by asun@cobalt.com + * ported to 2.4.x by thockin@sun.com + * Copyright (c) 2000 Axent Technologies, Cobalt Networks + * Copyright (c) 2001 Axent Technologies, Sun Microsystems + * + * This module interrogates the DS2401 Silicon Serial Number chip + * that is attached to all x86 Cobalt systems. + * + * It exports /proc/cobalt/hostid which is four bytes generated from of + * the id. It can be linked to /var/adm/hostid or /etc/hostid for the + * hostid command to use. + * + * It exports /proc/cobalt/serialnumber which is the entire 64 bit value + * read back (in ascii). + * + * For the guts of the 1 wire protocol used herein, please see the DS2401 + * specification. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This driver is SMP safe by nature. --TPH + */ +#include +#ifdef CONFIG_COBALT_SERNUM + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* dependent on systype */ +static unsigned int sn_direction; +static unsigned int sn_output; +static unsigned int sn_input; +static unsigned int sn_mask; + +/* 3k style systems */ +#define III_SN_DIRECTION 0x7d +#define III_SN_OUTPUT 0x7e +#define III_SN_INPUT 0x7f +#define III_SN_MASK 0x08 +static struct pci_dev *id_dev; + +/* 5k style systems */ +#define V_SN_DIRECTION (sn_io_base + 0x01) +#define V_SN_OUTPUT (sn_io_base + 0x00) +#define V_SN_INPUT (sn_io_base + 0x00) +#define V_SN_MASK (sn_io_base + 0x01) +static unsigned int sn_io_base; + +#define SSN_SIZE 8 /* bytes */ +static char ssn_string[SSN_SIZE * 2 + 1]; +static unsigned long hostid; +static int debug; +#ifdef CONFIG_PROC_FS +#ifdef CONFIG_COBALT_OLDPROC +static struct proc_dir_entry *proc_hostid; +static struct proc_dir_entry *proc_serialnum; +#endif +static struct proc_dir_entry *proc_chostid; +static struct proc_dir_entry *proc_cserialnum; +#endif + +static int +hostid_read(char *buf, char **start, off_t pos, int len, int *eof, void *x) +{ + int plen = sizeof(hostid); + + if (pos >= plen) { + *eof = 1; + return 0; + } + + memcpy(buf, &hostid, sizeof(hostid)); + *start = buf + pos; + plen -= pos; + + if (len > plen) { + return plen; + } else { + return len; + } +} + +static int +serialnum_read(char *buf, char **start, off_t pos, int len, int *eof, void *x) +{ + int plen = sizeof(ssn_string); + + if (pos >= plen+1) { + *eof = 1; + return 0; + } + + sprintf(buf, "%s\n", ssn_string); + *start = buf + pos; + plen -= pos; + + if (len > plen) { + return plen; + } else { + return len; + } +} + +/* set up the requisite IO bits */ +static int __init +io_init(void) +{ + unsigned char data; + + if (cobt_is_3k()) { + /* The GPIO tied to the ID chip is on the PMU */ + id_dev = pci_find_device(PCI_VENDOR_ID_AL, + PCI_DEVICE_ID_AL_M7101, NULL); + if (!id_dev) { + EPRINTK("can't find PMU for serialnumber access\n"); + return -ENXIO; + } + + /* Set input mode on GPIO3 */ + pci_read_config_byte(id_dev, sn_direction, &data); + if (debug > 1) { + WPRINTK("read of register 0x%x = 0x%x\n", + sn_direction, data); + } + if (data & sn_mask) { + pci_write_config_byte(id_dev, sn_direction, + data & ~sn_mask); + } + + /* Set the output value to be 0 */ + pci_read_config_byte(id_dev, sn_output, &data); + if (debug > 1) { + WPRINTK("read of register 0x%x = 0x%x\n", + sn_output, data); + } + if (data & sn_mask) { + pci_write_config_byte(id_dev, sn_output, + data & ~sn_mask); + } + } else if (cobt_is_5k()) { + u16 addr; + unsigned long flags; + + spin_lock_irqsave(&cobalt_superio_lock, flags); + outb(SUPERIO_LOGICAL_DEV, SUPERIO_INDEX_PORT); + outb(SUPERIO_DEV_GPIO, SUPERIO_DATA_PORT); + outb(SUPERIO_ADDR_HIGH, SUPERIO_INDEX_PORT); + addr = inb(SUPERIO_DATA_PORT) << 8; + outb(SUPERIO_ADDR_LOW, SUPERIO_INDEX_PORT); + addr |= inb(SUPERIO_DATA_PORT); + spin_unlock_irqrestore(&cobalt_superio_lock, flags); + if (addr) { + u8 val; + + sn_io_base = addr; + + /* set output value to 0 */ + val = inb(sn_direction); + outb(val | sn_mask, sn_direction); + data = inb(sn_output); + if (data & sn_mask) { + outb(data & ~sn_mask, sn_output); + } + /* set to input */ + outb(val & ~sn_mask, sn_direction); + } + } else { + return -ENXIO; + } + + /* Let things calm down */ + udelay(500); + return 0; +} + +/* write out a bit */ +static void __init +io_write(int delay) +{ + if (cobt_is_3k()) { + unsigned char data; + /* Set output mode on GPIO3 */ + pci_read_config_byte(id_dev, sn_direction, &data); + pci_write_config_byte(id_dev, sn_direction, data | sn_mask); + udelay(delay); + + /* Set input mode */ + pci_write_config_byte(id_dev, sn_direction, data & ~sn_mask); + } else if (cobt_is_5k()) { + unsigned char direction; + + /* change to output and back */ + direction = inb(sn_direction); + outb(direction | sn_mask, sn_direction); + udelay(delay); + outb(direction & ~sn_mask, sn_direction); + } +} + +/* read in a bit */ +static int __init +io_read(void) +{ + unsigned char data = 0; + + /* Get the input value */ + if (cobt_is_3k()) { + pci_read_config_byte(id_dev, sn_input, &data); + } else if (cobt_is_5k()) { + data = inb(sn_input); + } + + return (data & sn_mask) ? 1 : 0; +} + +static void __init +io_write_byte(unsigned char c) +{ + int i; + unsigned long flags; + + save_flags(flags); + + for (i = 0; i < 8; i++, c >>= 1) { + cli(); + if (c & 1) { + /* Transmit a 1 */ + io_write(5); + udelay(80); + } else { + /* Transmit a 0 */ + io_write(80); + udelay(10); + } + restore_flags(flags); + } +} + +static int __init +io_read_byte(void) +{ + int i; + int c = 0; + unsigned long flags; + + save_flags(flags); + + for (i = 0; i < 8; i++) { + cli(); + io_write(1); /* Start the read */ + udelay(2); + if (io_read()) { + c |= 1 << i; + } + udelay(60); + restore_flags(flags); + } + + return c; +} + +static int __init +get_ssn(unsigned char *buf) +{ + int i; + unsigned long flags; + + save_flags(flags); + cli(); + + /* Master Reset Pulse */ + for (i = 0; i < 600; i += 30) { + if (io_read()) { + break; + } + } + + if (i >= 600) { + if (debug) { + EPRINTK("the data line seems to be held low\n"); + } + return -ENXIO; + } + + io_write(600); + + for (i = 0; i < 300; i += 15) { + udelay(15); + if (io_read() == 0) { + /* We got a presence pulse */ + udelay(600); /* Wait for things to quiet down */ + break; + } + } + restore_flags(flags); + + if (i >= 300) { + if (debug) + EPRINTK("no presence pulse detected\n"); + return -ENXIO; + } + + io_write_byte(0x33); + + for (i = 0; i < 8; i++) { + int rc; + + rc = io_read_byte(); + if (rc < 0) { + return rc; + } + + *buf++ = rc; + } + + return 0; +} + +int __init +cobalt_serialnum_init(void) +{ + char *version; + char vstring[32]; + unsigned char ssn[SSN_SIZE]; + int rc; + int i; + + /* pick proper variables */ + if (cobt_is_3k()) { + sn_direction = III_SN_DIRECTION; + sn_output = III_SN_OUTPUT; + sn_input = III_SN_INPUT; + sn_mask = III_SN_MASK; + } else if (cobt_is_5k()) { + sn_direction = V_SN_DIRECTION; + sn_output = V_SN_OUTPUT; + sn_input = V_SN_INPUT; + sn_mask = V_SN_MASK; + } else { + return -1; + } + + /* get version from CVS */ + version = strchr("$Revision: 1.4 $", ':') + 2; + if (version) { + char *p; + + strncpy(vstring, version, sizeof(vstring)); + if ((p = strchr(vstring, ' '))) { + *p = '\0'; + } + } else { + strncpy(vstring, "unknown", sizeof(vstring)); + } + + /* set up for proper IO */ + rc = io_init(); + if (rc) { + return rc; + } + + /* + * NOTE: the below algorithm CAN NOT be changed. We have many systems + * out there registered with the serial number AS DERIVED by this + * algorithm. + */ + + rc = get_ssn(ssn); + if (rc) { + return rc; + } + + /* Convert to ssn_string */ + for (i = 7; i >= 0; i--) { + sprintf(ssn_string + (7 - i) * 2, "%02x", ssn[i]); + } + + /* get four bytes for a pretty unique (not guaranteed) hostid */ + hostid = *(unsigned long *)ssn ^ *(unsigned long *)(ssn+4); + +#ifdef CONFIG_PROC_FS +#ifdef CONFIG_COBALT_OLDPROC + proc_hostid = create_proc_read_entry("hostid", 0, NULL, + hostid_read, NULL); + if (!proc_hostid) { + EPRINTK("can't create /proc/hostid\n"); + } + proc_serialnum = create_proc_read_entry("serialnumber", 0, NULL, + serialnum_read, NULL); + if (!proc_serialnum) { + EPRINTK("can't create /proc/serialnumber\n"); + } +#endif + proc_chostid = create_proc_read_entry("hostid", 0, proc_cobalt, + hostid_read, NULL); + if (!proc_chostid) { + EPRINTK("can't create /proc/cobalt/hostid\n"); + } + proc_cserialnum = create_proc_read_entry("serialnumber", 0, + proc_cobalt, serialnum_read, NULL); + if (!proc_cserialnum) { + EPRINTK("can't create /proc/cobalt/serialnumber\n"); + } +#endif + + /* done */ + printk(KERN_INFO "Cobalt Networks serial number version %s: %s\n", + vstring, ssn_string); + + return 0; +} + +char * +cobalt_serialnum_get(void) +{ + return ssn_string; +} + +unsigned long +cobalt_hostid_get(void) +{ + return hostid; +} + +#ifdef MODULE +MODULE_PARM(debug, "i"); + +int +init_module(void) +{ + return cobalt_serialnum_init(); +} + +void +cleanup_module(void) +{ +#ifdef CONFIG_PROC_FS +#ifdef CONFIG_COBALT_OLDPROC + remove_proc_entry("hostid", NULL); + remove_proc_entry("serialnumber", NULL); +#endif + remove_proc_entry("hostid", proc_cobalt); + remove_proc_entry("serialnumber", proc_cobalt); +#endif +} +#endif /* MODULE */ + +#endif /* CONFIG_COBALT_SERNUM */ diff -ruN dist-2.4.5/drivers/cobalt/systype.c cobalt-2.4.5/drivers/cobalt/systype.c --- dist-2.4.5/drivers/cobalt/systype.c Wed Dec 31 16:00:00 1969 +++ cobalt-2.4.5/drivers/cobalt/systype.c Thu May 31 14:32:15 2001 @@ -0,0 +1,141 @@ +/* + * $Id: systype.c,v 1.4 2001/05/30 07:19:48 thockin Exp $ + * systype.c : routines for figuring out which Cobalt system this is + * + * Copyright 2001 Sun Microsystems, Inc. + * + * By: Tim Hockin + * Adrian Sun + * Duncan Laurie + * + * This driver is SMP safe by nature. --TPH + */ + +#include + +#ifdef CONFIG_COBALT + +#include +#include +#include + +#include +#include + +cobt_sys_t cobt_type = COBT_UNKNOWN; + +#ifdef CONFIG_PROC_FS +static struct proc_dir_entry *proc_systype; +#endif +static int systype_read_proc(char *buf, char **start, off_t pos, int len, + int *eof, void *x); +static char *systype_str(cobt_sys_t type); + +int __init +cobalt_systype_init(void) +{ + static int init_done = 0; + struct pci_dev *pdev; + + if (init_done) { + return 0; + } + init_done = 1; + +#if defined(CONFIG_COBALT_GEN_III) + /* board identifier for RaQ3/4 vs Qube3 is on the PMU @ 0x7f */ + pdev = pci_find_device(PCI_VENDOR_ID_AL, + PCI_DEVICE_ID_AL_M7101, NULL); + if (pdev) { + /* + * check to see what board we are on + * ( RaQ 3, RaQ 4, Qube 3 ) + */ + unsigned char val; + + /* momentarily set DOGB# to input */ + pci_read_config_byte(pdev, 0x7d, &val); + pci_write_config_byte(pdev, 0x7d, val & ~0x20); + + /* read the GPIO register */ + pci_read_config_byte(pdev, 0x7f, &val); + /* RaQ3/4 boards have DOGB (0x20) high, + * Qube3 has DOGB low */ + cobt_type = (val & 0x20) ? COBT_RAQ3 : COBT_QUBE3; + + /* change DOGB back to output */ + pci_read_config_byte(pdev, 0x7d, &val); + pci_write_config_byte(pdev, 0x7d, val | 0x20); + } +#endif +#if defined(CONFIG_COBALT_GEN_V) + /* is it a gen V ? */ + pdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, + PCI_DEVICE_ID_SERVERWORKS_LE, NULL); + if (pdev) { + cobt_type = COBT_RAQXTR; + } +#endif /* CONFIG_COBALT_GEN */ + +#ifdef CONFIG_PROC_FS + proc_systype = create_proc_read_entry("systype", S_IFREG | S_IRUGO, + proc_cobalt, systype_read_proc, NULL); + if (!proc_systype) { + EPRINTK("can't create /proc/cobalt/systype\n"); + } +#endif + + printk("Cobalt system type: "); + if (cobt_type == COBT_UNKNOWN) { + printk("unknown (trouble will ensue)\n"); + return -1; + } else { + printk("%s\n", systype_str(cobt_type)); + } + + return 0; +} + +static int +systype_read_proc(char *buf, char **start, off_t pos, int len, + int *eof, void *x) +{ + int plen = 0; + + plen += sprintf(buf+plen, "%s\n", systype_str(cobt_type)); + + if (pos >= plen) { + *eof = 1; + return 0; + } + + *start = buf + pos; + plen -= pos; + + if (len > plen) { + return plen; + } else { + return len; + } +} + +static char * +systype_str(cobt_sys_t type) +{ + switch (type) { + case COBT_RAQ3: + return "RaQ 3/4"; + break; + case COBT_QUBE3: + return "Qube 3"; + break; + case COBT_RAQXTR: + return "RaQ XTR"; + break; + case COBT_UNKNOWN: + default: + return "unknown"; + break; + } +} +#endif /* CONFIG_COBALT */ diff -ruN dist-2.4.5/drivers/cobalt/thermal.c cobalt-2.4.5/drivers/cobalt/thermal.c --- dist-2.4.5/drivers/cobalt/thermal.c Wed Dec 31 16:00:00 1969 +++ cobalt-2.4.5/drivers/cobalt/thermal.c Thu May 31 14:32:15 2001 @@ -0,0 +1,144 @@ +/* $Id: thermal.c,v 1.3 2001/05/30 07:19:48 thockin Exp $ + * Copyright (c) 2000-2001 Sun Microsystems, Inc + * + * This is SMP safe. The only protectable operationis a single I2C access, + * which gets protected by I2C. This may change in the future with different + * thermal sensors. --TPH + */ +#include +#ifdef CONFIG_COBALT_THERMAL + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +unsigned int cobalt_thermal_id_max; +#ifdef CONFIG_PROC_FS +static struct proc_dir_entry *proc_therm; +#endif + +static char *degrees(int); +static int thermal_read_proc(char *buf, char **start, off_t pos, int len, + int *eof, void *x); + +int __init +cobalt_thermal_init(void) +{ + if (cobt_is_3k()) { + cobalt_thermal_id_max = 0; /* 3k's have 1 thermal */ + } else if (cobt_is_5k()) { + cobalt_thermal_id_max = 3; /* monterey has 4 temp sensors */ + } + +#ifdef CONFIG_PROC_FS + /* make a file in /proc */ + proc_therm = create_proc_read_entry("thermal_sensors", S_IFREG, + proc_cobalt, thermal_read_proc, NULL); + if (!proc_therm) { + EPRINTK("can't create /proc/cobalt/thermal_sensors\n"); + } +#endif + + printk("Cobalt Networks thermal sensors v1.4\n"); + + return 0; +} + +#define LM77_TEMP 0x0 +#define LM77_STATUS 0x1 +#define LM77_HYST 0x2 +#define LM77_CRIT 0x3 +#define LM77_LOW 0x4 +#define LM77_HIGH 0x5 + +#ifndef min +#define min(a,b) ((a) < (b) ? (a) : (b)) +#endif + +char * +cobalt_temp_read(unsigned int sensor) +{ + int tmp; + int val = 0; + int tries = 2; + static int last_val = 0; + + if (sensor > cobalt_thermal_id_max) { + return NULL; + } + + /* sometimes it reads as zero... try again */ + while (tries--) { + /* LM77 returns the bytes backwards - */ + /* address = base + deviceid + 1 for read */ + tmp = cobalt_i2c_read_word(COBALT_I2C_DEV_TEMP + + (sensor<<1) + 1, LM77_TEMP); + if (tmp < 0) { + /* read failed, return the last known value */ + return degrees(last_val); + } + + val = (tmp<<8 & 0xff00) + (tmp>>8 & 0x00ff); + if (val) { + last_val = val; + break; + } + } + return degrees(val); +} + +/* build a string - measured in degrees C */ +static char * +degrees(int val) +{ + static char temp[16] = "unknown"; + + sprintf(temp, "%d", val>>4); + if (val & 0x0008) { + sprintf(temp+strlen(temp), ".5"); + } + return temp; +} + +static int +thermal_read_proc(char *buf, char **start, off_t pos, int len, + int *eof, void *x) +{ + int i; + int plen = 0; + + for (i = 0; i <= cobalt_thermal_id_max; i++) { + char *c; + c = cobalt_temp_read(i); + if (!c) { + continue; + } + plen += sprintf(buf+plen, "%d: %s\n", i, c); + } + + if (pos >= plen) { + *eof = 1; + return 0; + } + + *start = buf + pos; + plen -= pos; + + if (len > plen) { + return plen; + } else { + return len; + } +} + +#endif /* CONFIG_COBALT_THERMAL */ diff -ruN dist-2.4.5/drivers/cobalt/wdt.c cobalt-2.4.5/drivers/cobalt/wdt.c --- dist-2.4.5/drivers/cobalt/wdt.c Wed Dec 31 16:00:00 1969 +++ cobalt-2.4.5/drivers/cobalt/wdt.c Thu May 31 14:32:15 2001 @@ -0,0 +1,371 @@ +/* $Id: wdt.c,v 1.8 2001/05/30 22:34:57 thockin Exp $ */ +/* + * Cobalt kernel WDT timer driver + * Tim Hockin + * Adrian Sun + * Chris Johnson + * Copyright (c)1999-2000, Cobalt Networks + * Copyright (c)2001, Sun Microsystems + * + * This should be SMP safe. Every external function (except trigger_reboot) + * grabs the wdt lock. No function in this file may call any exported + * function (excepting trigger_reboot). The disable counter is an atomic, so + * there should be no issues there. --TPH + */ +#include +#ifdef CONFIG_COBALT_WDT + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DOGB 0x20 +#define ALI_7101_WDT 0x92 +#define ALI_WDT_ARM 0x01 +#define WDT_3K_TIMEOUT (HZ >> 4) /* 1/16 second */ + +#define SUPERIO_TIMEOUT (0x01) /* 1 minute */ +#define WDT_5K_TIMEOUT (HZ << 3) /* 8 seconds */ + +struct timer_list cobalt_wdt_timer; +static unsigned long wdt_timeout; +static unsigned long long tsc_per_wdt; +static atomic_t cobalt_wdt_disable_count = ATOMIC_INIT(0); +static int initialized; +static spinlock_t wdt_lock = SPIN_LOCK_UNLOCKED; + +/* gen III */ +static struct pci_dev *cobalt_pmu; +static int use_pic; +/* gen V */ +static u16 superio_pm_port; + +static void do_refresh(void); +static void do_cleardog(void); +static void do_disable(void); +static void do_reenable(void); + +static unsigned long __init +chipset_setup(void) +{ + if (cobt_is_3k()) { + /* + * Set up the PMU for 3k boards. It has a max + * of a 1 second timeout. + */ + struct pci_dev *south; + char tmp; + + /* PMU (1543 ver A1-E) has a built-in WDT. Set it to 1 sec */ + cobalt_pmu = pci_find_device(PCI_VENDOR_ID_AL, + PCI_DEVICE_ID_AL_M7101, NULL); + if (!cobalt_pmu) { + EPRINTK("can't find south bridge for WDT\n"); + return 0; + } + pci_write_config_byte(cobalt_pmu, ALI_7101_WDT, 0x02); + + /* why it is called 1543, but DevId is 1533 I'll never know */ + south = pci_find_device(PCI_VENDOR_ID_AL, + PCI_DEVICE_ID_AL_M1533, NULL); + if (!south) { + EPRINTK("can't find south bridge for WDT\n"); + use_pic = 1; + } else { + /* reversion # is here - must match ???1001?(b) + * else use PIC for WDT */ + pci_read_config_byte(south, 0x5e, &tmp); + use_pic = ((tmp & 0x1e) != 0x12); + } + + if (!use_pic) { + /* set DOGB GPIO pin to OUTPUT - JIC */ + pci_read_config_byte(cobalt_pmu, 0x7d, &tmp); + pci_write_config_byte(cobalt_pmu, 0x7d, tmp | DOGB); + } + return WDT_3K_TIMEOUT; + } else if (cobt_is_5k()) { + unsigned long flags; + + /* + * Set up the Nat. Semi SuperI/O for Monterey. It has a + * minimum of a 1 minute timeout. + */ + + spin_lock_irqsave(&cobalt_superio_lock, flags); + + /* superi/o -- select pm logical device and get base address */ + outb(SUPERIO_LOGICAL_DEV, SUPERIO_INDEX_PORT); + outb(SUPERIO_DEV_PM, SUPERIO_DATA_PORT); + outb(SUPERIO_ADDR_HIGH, SUPERIO_INDEX_PORT); + superio_pm_port = inb(SUPERIO_DATA_PORT) << 8; + outb(SUPERIO_ADDR_LOW, SUPERIO_INDEX_PORT); + superio_pm_port |= inb(SUPERIO_DATA_PORT); + if (superio_pm_port) { + outb(SUPERIO_WDT_DEV, superio_pm_port); + outb(SUPERIO_TIMEOUT, superio_pm_port + 1); + } + + spin_unlock_irqrestore(&cobalt_superio_lock, flags); + + return WDT_5K_TIMEOUT; + } + + return 0; +} + +void __init +cobalt_wdt_init(void) +{ + unsigned long long start, stop; + + wdt_timeout = chipset_setup(); + + /* figure out time */ + rdtscll(start); + udelay(100); + rdtscll(stop); + + /* + * (int) (stop - start) * 10 == tsc per msec + * 1000 / HZ == msec per tick + * wdt_timeout == ticks per watchdog rearm + */ + tsc_per_wdt = (int) (stop - start) * 10 * (1000 * wdt_timeout / HZ); + +#if !defined(CONFIG_COBALT_BOOTLOADER) + /* set the timer going */ + init_timer(&cobalt_wdt_timer); + cobalt_wdt_timer.function = cobalt_wdt_refresh; + cobalt_wdt_timer.data = 1; + cobalt_wdt_timer.expires = jiffies + wdt_timeout; + add_timer(&cobalt_wdt_timer); + + /* the first timer tick will set it going */ + printk("Cobalt Networks watchdog v1.4"); + if (cobt_is_3k() && use_pic) { + printk(" (old revision board: using PIC controller)"); + } + printk("\n"); +#endif /* BOOTLOADER */ + + initialized = 1; +} + +static inline void +hw_disable(void) +{ + if (cobt_is_3k()) { + char tmp; + + /* read the value, disable (reset) WDT */ + pci_read_config_byte(cobalt_pmu, ALI_7101_WDT, &tmp); + pci_write_config_byte(cobalt_pmu, ALI_7101_WDT, + (tmp & ~ALI_WDT_ARM)); + } else if (cobt_is_5k()) { + unsigned long flags; + spin_lock_irqsave(&cobalt_superio_lock, flags); + outb(SUPERIO_WDT_DEV, superio_pm_port); + outb(0x0, superio_pm_port + 1); + spin_unlock_irqrestore(&cobalt_superio_lock, flags); + } +} + +static inline void +hw_enable(void) +{ + if (cobt_is_3k()) { + unsigned char tmp; + /* read the value, disable (reset) WDT, enable WDT */ + pci_read_config_byte(cobalt_pmu, ALI_7101_WDT, &tmp); + pci_write_config_byte(cobalt_pmu, ALI_7101_WDT, + (tmp | ALI_WDT_ARM)); + if (use_pic) { + /* transition GPIO 5 (DOGB) to arm/clear timer */ + pci_read_config_byte(cobalt_pmu, 0x7e, &tmp); + pci_write_config_byte(cobalt_pmu, 0x7e, tmp ^ DOGB); + } + } else if (cobt_is_5k()) { + unsigned long flags; + spin_lock_irqsave(&cobalt_superio_lock, flags); + outb(SUPERIO_WDT_DEV, superio_pm_port); + outb(SUPERIO_TIMEOUT, superio_pm_port + 1); + spin_unlock_irqrestore(&cobalt_superio_lock, flags); + } +} + +static void +do_refresh(void) +{ + if (!initialized) { + return; + } + + do_cleardog(); + + /* re-arm the timer - this is locked in mod_timer() */ + mod_timer(&cobalt_wdt_timer, jiffies + wdt_timeout); +} + +EXPORT_SYMBOL(cobalt_wdt_refresh); +void +cobalt_wdt_refresh(unsigned long refresh_timer) +{ + unsigned long flags; + +#ifdef CONFIG_COBALT_BOOTLOADER + return; +#endif + + spin_lock_irqsave(&wdt_lock, flags); + do_refresh(); + spin_unlock_irqrestore(&wdt_lock, flags); +} + +static void +do_cleardog(void) +{ + static unsigned long long last_tsc = 0; + unsigned long long tmp; + + if (!initialized || (atomic_read(&cobalt_wdt_disable_count) > 0)) { + return; + } + + /* only bother if we're due */ + rdtscll(tmp); + if ((int)(tmp - last_tsc) < tsc_per_wdt) { + return; + } + + hw_disable(); + hw_enable(); + + rdtscll(last_tsc); +} + +EXPORT_SYMBOL(cobalt_wdt_cleardog); +void +cobalt_wdt_cleardog(void) +{ + unsigned long flags; + +#ifdef CONFIG_COBALT_BOOTLOADER + return; +#endif + + spin_lock_irqsave(&wdt_lock, flags); + do_cleardog(); + spin_unlock_irqrestore(&wdt_lock, flags); +} + +/* + * this is called from machine_restart. it should not be used on + * 5k machines. + */ +EXPORT_SYMBOL(cobalt_wdt_trigger_reboot); +void +cobalt_wdt_trigger_reboot(void) +{ + if (cobt_is_3k()) { + if (!cobalt_pmu) { + WPRINTK("no PMU found!\n"); + WPRINTK("reboot not possible!\n"); + return; + } + +#if !defined(CONFIG_COBALT_BOOTLOADER) + /* stop feeding it */ + del_timer(&cobalt_wdt_timer); +#endif + + /* kiss your rear goodbye... */ + initialized = 0; + hw_disable(); + hw_enable(); + } +} + +static void +do_disable(void) +{ + if (!initialized) { + return; + } + + if (atomic_read(&cobalt_wdt_disable_count) == 0) { + atomic_inc(&cobalt_wdt_disable_count); + del_timer(&cobalt_wdt_timer); + hw_disable(); + } +} + +EXPORT_SYMBOL(cobalt_wdt_disable); +void +cobalt_wdt_disable(void) +{ + unsigned long flags; + +#ifdef CONFIG_COBALT_BOOTLOADER + return; +#endif + + if (cobt_is_3k() && use_pic) { + WPRINTK("in PIC mode - cannot disable\n"); + return; + } + + spin_lock_irqsave(&wdt_lock, flags); + do_disable(); + spin_unlock_irqrestore(&wdt_lock, flags); +} + +static void +do_reenable(void) +{ + int dcnt; + + if (!initialized) { + return; + } + + atomic_dec(&cobalt_wdt_disable_count); + dcnt = atomic_read(&cobalt_wdt_disable_count); + + if (dcnt == 0) { + do_refresh(); + } else if (dcnt < 0) { + WPRINTK("too many enables\n"); + atomic_set(&cobalt_wdt_disable_count, 0); + } +} + + +EXPORT_SYMBOL(cobalt_wdt_reenable); +void +cobalt_wdt_reenable(void) +{ + unsigned long flags; + +#ifdef CONFIG_COBALT_BOOTLOADER + return; +#endif + + spin_lock_irqsave(&wdt_lock, flags); + do_reenable(); + spin_unlock_irqrestore(&wdt_lock, flags); +} + +#endif /* CONFIG_COBALT_WDT */ diff -ruN dist-2.4.5/include/linux/cobalt-acpi.h cobalt-2.4.5/include/linux/cobalt-acpi.h --- dist-2.4.5/include/linux/cobalt-acpi.h Wed Dec 31 16:00:00 1969 +++ cobalt-2.4.5/include/linux/cobalt-acpi.h Thu May 31 14:33:16 2001 @@ -0,0 +1,16 @@ +/* + * $Id: $ + * cobalt-acpi.h : support for ACPI interrupts + * + * Copyright 2000 Cobalt Networks, Inc. + * Copyright 2001 Sun Microsystems, Inc. + */ +#ifndef COBALT_ACPI_H +#define COBALT_ACPI_H + +extern int cobalt_acpi_register_handler(void (*function) + (int, void *, struct pt_regs *)); +extern int cobalt_acpi_unregister_handler(void (*function) + (int, void *, struct pt_regs *)); + +#endif /* COBALT_ACPI_H */ diff -ruN dist-2.4.5/include/linux/cobalt.h cobalt-2.4.5/include/linux/cobalt.h --- dist-2.4.5/include/linux/cobalt.h Wed Dec 31 16:00:00 1969 +++ cobalt-2.4.5/include/linux/cobalt.h Thu May 31 14:33:16 2001 @@ -0,0 +1,76 @@ +/* $Id: cobalt.h,v 1.5 2001/05/30 07:19:48 thockin Exp $ */ +/* Copyright 2001 Sun Microsystems, Inc. */ +#ifndef COBALT_H +#define COBALT_H + +/* generational support - for easy checking */ +#ifdef CONFIG_COBALT_GEN_III +# define COBT_SUPPORT_GEN_III 1 +#else +# define COBT_SUPPORT_GEN_III 0 +#endif + +#ifdef CONFIG_COBALT_GEN_V +# define COBT_SUPPORT_GEN_V 1 +#else +# define COBT_SUPPORT_GEN_V 0 +#endif + +/* keep this test up to date with new generation defines */ +#if !defined(CONFIG_COBALT_GEN_III) && !defined(CONFIG_COBALT_GEN_V) +/* barf if no generation has been selected */ +#error You asked for CONFIG_COBALT, but no CONFIG_COBALT_GEN ! +#endif + +/* macros for consistent errors/warnings */ +#define EPRINTK(fmt, args...) \ + printk(KERN_ERR "%s:%s" fmt , __FILE__ , __FUNCTION__ , ##args) + +#define WPRINTK(fmt, args...) \ + printk(KERN_WARNING "%s:%s" fmt , __FILE__ , __FUNCTION__ , ##args) + +/* accesses for CMOS */ +#include +#define CMOS_FLAG_MIN 0x0001 +#define CMOS_SYSFAULT_FLAG 0x0020 +#define CMOS_OOPSPANIC_FLAG 0x0040 +#define CMOS_FLAG_MAX 0x0040 + +#define CMOS_ADDR_PORT 0x70 +#define CMOS_DATA_PORT 0x71 +#define CMOS_INFO_MAX 0xff +#define CMOS_FLAG_BYTE_0 0x10 +#define CMOS_FLAG_BYTE_1 0x11 + +static inline u8 +cobalt_cmos_read_byte(int index) +{ + u8 data; + unsigned long flags; + + if (index > CMOS_INFO_MAX) + return 0; + + spin_lock_irqsave(&rtc_lock, flags); + outb(index, CMOS_ADDR_PORT); + data = inb(CMOS_DATA_PORT); + spin_unlock_irqrestore(&rtc_lock, flags); + + return data; +} + +static inline int +cobalt_cmos_read_flag(const unsigned int flag) +{ + u16 cmosfl; + + cmosfl = cobalt_cmos_read_byte(CMOS_FLAG_BYTE_0) << 8; + cmosfl |= cobalt_cmos_read_byte(CMOS_FLAG_BYTE_1); + + return (cmosfl & flag) ? 1 : 0; +} + +/* the root of /proc/cobalt */ +extern struct proc_dir_entry *proc_cobalt; + +#endif diff -ruN dist-2.4.5/include/linux/cobalt-i2c.h cobalt-2.4.5/include/linux/cobalt-i2c.h --- dist-2.4.5/include/linux/cobalt-i2c.h Wed Dec 31 16:00:00 1969 +++ cobalt-2.4.5/include/linux/cobalt-i2c.h Thu May 31 14:33:16 2001 @@ -0,0 +1,37 @@ +/* + * $Id: cobalt-i2c.h,v 1.1 2001/03/07 01:58:24 thockin Exp $ + * cobalt-i2c.h : I2C support for LCD/Front Panel + * + * Copyright 2000 Cobalt Networks, Inc. + * Copyright 2001 Sun Microsystems, Inc. + */ +#ifndef COBALT_I2C_H +#define COBALT_I2C_H + +#include +#include + +#define COBALT_I2C_DEV_LED_I 0x40 +#define COBALT_I2C_DEV_LED_II 0x42 +#define COBALT_I2C_DEV_LCD_DATA 0x4a +#define COBALT_I2C_DEV_LCD_INST 0x48 +#define COBALT_I2C_DEV_FP_BUTTONS 0x41 +#define COBALT_I2C_DEV_DRV_SWITCH 0x45 +#define COBALT_I2C_DEV_RULER 0x46 +#define COBALT_I2C_DEV_TEMP 0x90 +#define COBALT_I2C_READ 0x01 +#define COBALT_I2C_WRITE 0x00 + +extern int cobalt_i2c_reset(void); +extern int cobalt_i2c_read_byte(const int dev, const int index); +extern int cobalt_i2c_read_word(const int dev, const int index); +extern int cobalt_i2c_read_block(const int dev, const int index, + unsigned char *data, int count); +extern int cobalt_i2c_write_byte(const int dev, const int index, + const u8 val); +extern int cobalt_i2c_write_word(const int dev, const int index, + const u16 val); +extern int cobalt_i2c_write_block(const int dev, const int index, + unsigned char *data, int count); + +#endif /* COBALT_I2C_H */ diff -ruN dist-2.4.5/include/linux/cobalt-lcd.h cobalt-2.4.5/include/linux/cobalt-lcd.h --- dist-2.4.5/include/linux/cobalt-lcd.h Wed Dec 31 16:00:00 1969 +++ cobalt-2.4.5/include/linux/cobalt-lcd.h Thu May 31 14:33:16 2001 @@ -0,0 +1,90 @@ +/* + * $Id: cobalt-lcd.h,v 1.2 2001/04/11 03:53:41 thockin Exp $ + * cobalt-lcd.h : some useful defines for the Cobalt LCD driver + * (must be useable from both kernel and user space) + * + * Copyright 1996-2000 Cobalt Networks, Inc. + * Copyright 2001 Sun Microsystems, Inc. + * + * By: Andrew Bose + * Timothy Stonis (x86 version) + * Tim Hockin + * Adrian Sun + * Erik Gilling + * Duncan Laurie + */ +#ifndef COBALT_LCD_H +#define COBALT_LCD_H + +#include +#include + +/* this is the generic device minor assigned to /dev/lcd */ +#define COBALT_LCD_MINOR 156 +#define COBALT_LCD_LINELEN 40 + +struct lcd_display { + unsigned long buttons; + int size1; + int size2; + unsigned char line1[COBALT_LCD_LINELEN]; + unsigned char line2[COBALT_LCD_LINELEN]; + unsigned char cursor_address; + unsigned char character; + unsigned char leds; + unsigned char *RomImage; +}; + +/* different lcd types */ +#define LCD_TYPE_UNKNOWN 0 +#define LCD_TYPE_PARALLEL 1 +#define LCD_TYPE_PARALLEL_B 2 +#define LCD_TYPE_I2C 3 + +/* Function command codes for ioctl */ +#define LCD_On 1 +#define LCD_Off 2 +#define LCD_Clear 3 +#define LCD_Reset 4 +#define LCD_Cursor_Left 5 +#define LCD_Cursor_Right 6 +#define LCD_Disp_Left 7 +#define LCD_Disp_Right 8 +#define LCD_Get_Cursor 9 +#define LCD_Set_Cursor 10 +#define LCD_Home 11 +#define LCD_Read 12 +#define LCD_Write 13 +#define LCD_Cursor_Off 14 +#define LCD_Cursor_On 15 +#define LCD_Get_Cursor_Pos 16 +#define LCD_Set_Cursor_Pos 17 +#define LCD_Blink_Off 18 +#define LCD_Raw_Inst 19 +#define LCD_Raw_Data 20 +#define LCD_Type 21 + +/* LED controls */ +#define LED_Set 40 +#define LED_Bit_Set 41 +#define LED_Bit_Clear 42 +#define LED32_Set 43 +#define LED32_Bit_Set 44 +#define LED32_Bit_Clear 45 + +/* button ioctls */ +#define BUTTON_Read 50 + +/* Button defs */ +#define BUTTON_Next 0x3D +#define BUTTON_Next_B 0x7E +#define BUTTON_Reset_B 0xFC +#define BUTTON_NONE_B 0xFE +#define BUTTON_Left_B 0xFA +#define BUTTON_Right_B 0xDE +#define BUTTON_Up_B 0xF6 +#define BUTTON_Down_B 0xEE +#define BUTTON_Enter_B 0xBE +#define BUTTON_Power 0x01 + +#endif /* COBALT_LCD_H */ diff -ruN dist-2.4.5/include/linux/cobalt-led.h cobalt-2.4.5/include/linux/cobalt-led.h --- dist-2.4.5/include/linux/cobalt-led.h Wed Dec 31 16:00:00 1969 +++ cobalt-2.4.5/include/linux/cobalt-led.h Thu May 31 14:33:16 2001 @@ -0,0 +1,45 @@ +/* + * $Id: cobalt-led.h,v 1.1 2001/04/11 03:53:41 thockin Exp $ + * cobalt-led.c + * + * Copyright 1996-2000 Cobalt Networks, Inc. + * Copyright 2001 Sun Microsystems, Inc. + * + * By: Andrew Bose + * Timothy Stonis (x86 version) + * Tim Hockin + * Adrian Sun + * Erik Gilling + * Duncan Laurie + */ +#ifndef COBALT_LED_H +#define COBALT_LED_H + +#include + +/* the set of all leds available on Cobalt systems */ +#define LED_SHUTDOWN (1 << 0) +#define LED_WEBLIGHT (1 << 1) +#define LED_COBALTLOGO (1 << 2) +#define LED_ETH0_TXRX (1 << 3) +#define LED_ETH0_LINK (1 << 4) +#define LED_ETH1_TXRX (1 << 5) +#define LED_ETH1_LINK (1 << 6) +#define LED_DISK0 (1 << 7) +#define LED_DISK1 (1 << 8) +#define LED_DISK2 (1 << 9) +#define LED_DISK3 (1 << 10) +#define LED_SYSFAULT (1 << 11) +#define LED_HEART (1 << 12) +#define LED_SPARE (1 << 13) + +#ifdef __KERNEL__ +extern void cobalt_led_set(const unsigned int leds); +extern void cobalt_led_set_lazy(const unsigned int leds); +extern unsigned int cobalt_led_get(void); +extern int cobalt_fpled_register(unsigned int (*fn)(void *), void *data); +extern int cobalt_fpled_unregister(unsigned int (*fn)(void *), void *data); +#endif + +#endif /* COBALT_LED_H */ + diff -ruN dist-2.4.5/include/linux/cobalt-misc.h cobalt-2.4.5/include/linux/cobalt-misc.h --- dist-2.4.5/include/linux/cobalt-misc.h Wed Dec 31 16:00:00 1969 +++ cobalt-2.4.5/include/linux/cobalt-misc.h Thu May 31 14:33:16 2001 @@ -0,0 +1,11 @@ +/* $Id: $ */ +/* Copyright 2001 Sun Microsystems, Inc. */ +#ifndef COBALT_MISC_H +#define COBALT_MISC_H + +void cobalt_nmi(unsigned char reason, struct pt_regs *regs); +void cobalt_restart(void); +void cobalt_halt(void); +void cobalt_power_off(void); + +#endif diff -ruN dist-2.4.5/include/linux/cobalt-net.h cobalt-2.4.5/include/linux/cobalt-net.h --- dist-2.4.5/include/linux/cobalt-net.h Wed Dec 31 16:00:00 1969 +++ cobalt-2.4.5/include/linux/cobalt-net.h Thu May 31 14:33:16 2001 @@ -0,0 +1,11 @@ +/* $Id: cobalt-net.h,v 1.1 2001/04/13 02:15:35 thockin Exp $ */ +/* Copyright 2001 Sun Microsystems, Inc. */ +#ifndef COBALT_NET_H +#define COBALT_NET_H + +#include + +void cobalt_net_register(struct net_device *ndev); +void cobalt_net_unregister(struct net_device *ndev); + +#endif diff -ruN dist-2.4.5/include/linux/cobalt-ruler.h cobalt-2.4.5/include/linux/cobalt-ruler.h --- dist-2.4.5/include/linux/cobalt-ruler.h Wed Dec 31 16:00:00 1969 +++ cobalt-2.4.5/include/linux/cobalt-ruler.h Thu May 31 14:33:16 2001 @@ -0,0 +1,12 @@ +/* $Id: cobalt-ruler.h,v 1.2 2001/04/27 03:13:53 thockin Exp $ */ +/* Copyright 2001 Sun Microsystems, Inc. */ +#ifndef COBALT_RULER_H +#define COBALT_RULER_H + +#include + +void cobalt_ruler_register(ide_hwif_t *hwif); +void cobalt_ruler_unregister(ide_hwif_t *hwif); +void cobalt_ruler_powerdown(void); + +#endif diff -ruN dist-2.4.5/include/linux/cobalt-serialnum.h cobalt-2.4.5/include/linux/cobalt-serialnum.h --- dist-2.4.5/include/linux/cobalt-serialnum.h Wed Dec 31 16:00:00 1969 +++ cobalt-2.4.5/include/linux/cobalt-serialnum.h Thu May 31 14:33:16 2001 @@ -0,0 +1,16 @@ +/* + * $Id: $ + * cobalt-serialnum.h : access to the DS2401 serial number + * + * Copyright 2000 Cobalt Networks, Inc. + * Copyright 2001 Sun Microsystems, Inc. + */ +#ifndef COBALT_SERIALNUM_H +#define COBALT_SERIALNUM_H + +#include + +char *cobalt_serialnum_get(void); +unsigned long cobalt_hostid_get(void); + +#endif /* COBALT_SERIALNUM_H */ diff -ruN dist-2.4.5/include/linux/cobalt-superio.h cobalt-2.4.5/include/linux/cobalt-superio.h --- dist-2.4.5/include/linux/cobalt-superio.h Wed Dec 31 16:00:00 1969 +++ cobalt-2.4.5/include/linux/cobalt-superio.h Thu May 31 14:33:16 2001 @@ -0,0 +1,41 @@ +/* + * $Id: cobalt-superio.h,v 1.1 2001/03/07 01:58:24 thockin Exp $ + * cobalt-superio.h : SuperIO support for Sun/Cobalt servers + * + * Copyright 2000 Cobalt Networks, Inc. + * Copyright 2001 Sun Microsystems, Inc. + */ +#ifndef COBALT_SUPERIO_H +#define COBALT_SUPERIO_H + +#include + +#define SUPERIO_INDEX_PORT 0x2e +#define SUPERIO_DATA_PORT 0x2f + +#define SUPERIO_LOGICAL_DEV 0x07 +#define SUPERIO_DEV_RTC 0x02 +#define SUPERIO_DEV_GPIO 0x07 +#define SUPERIO_DEV_PM 0x08 + +#define SUPERIO_ACTIVATE 0x30 +#define SUPERIO_ADDR_HIGH 0x60 +#define SUPERIO_ADDR_LOW 0x61 +#define SUPERIO_INTR_PIN 0x70 +#define SUPERIO_INTR_TYPE 0x71 + +#define SUPERIO_APCR1 0x40 +#define SUPERIO_APCR4 0x4a + +#define SUPERIO_RTC_CRA 0x0a +#define SUPERIO_RTC_BANK_0 0x20 +#define SUPERIO_RTC_BANK_2 0x40 + +#define SUPERIO_PWRBUTTON 0x01 +#define SUPERIO_PM1_STATUS 0x01 + +#define SUPERIO_WDT_DEV 0x05 + +extern spinlock_t cobalt_superio_lock; + +#endif /* COBALT_SUPERIO_H */ diff -ruN dist-2.4.5/include/linux/cobalt-systype.h cobalt-2.4.5/include/linux/cobalt-systype.h --- dist-2.4.5/include/linux/cobalt-systype.h Wed Dec 31 16:00:00 1969 +++ cobalt-2.4.5/include/linux/cobalt-systype.h Thu May 31 14:33:16 2001 @@ -0,0 +1,29 @@ +/* + * $Id: cobalt-systype.h,v 1.1 2001/03/07 01:58:24 thockin Exp $ + * cobalt-systype.h : figure out what Cobalt system we are on + * + * Copyright 2000 Cobalt Networks, Inc. + * Copyright 2001 Sun Microsystems, Inc. + */ +#ifndef COBALT_SYSTYPE_H +#define COBALT_SYSTYPE_H + +#include + +typedef enum { + COBT_UNKNOWN, + COBT_RAQ3, + COBT_QUBE3, + COBT_RAQXTR, +} cobt_sys_t; + +extern cobt_sys_t cobt_type; +/* one for each major board-type - COBT_SUPPORT_* from */ +#define cobt_is_raq3() (COBT_SUPPORT_GEN_III && cobt_type == COBT_RAQ3) +#define cobt_is_qube3() (COBT_SUPPORT_GEN_III && cobt_type == COBT_QUBE3) +#define cobt_is_raqxtr() (COBT_SUPPORT_GEN_V && cobt_type == COBT_RAQXTR) +/* one for each major generation */ +#define cobt_is_3k() (cobt_is_raq3() || cobt_is_qube3()) +#define cobt_is_5k() (cobt_is_raqxtr()) + +#endif diff -ruN dist-2.4.5/include/linux/cobalt-thermal.h cobalt-2.4.5/include/linux/cobalt-thermal.h --- dist-2.4.5/include/linux/cobalt-thermal.h Wed Dec 31 16:00:00 1969 +++ cobalt-2.4.5/include/linux/cobalt-thermal.h Thu May 31 14:33:16 2001 @@ -0,0 +1,12 @@ +/* $Id: $ */ +/* Copyright 2001 Sun Microsystems, Inc. */ +#ifndef COBALT_THERMAL_H +#define COBALT_THERMAL_H + +#include + +extern unsigned int cobalt_thermal_id_max; + +char *cobalt_temp_read(unsigned int sensor); + +#endif diff -ruN dist-2.4.5/include/linux/cobalt-wdt.h cobalt-2.4.5/include/linux/cobalt-wdt.h --- dist-2.4.5/include/linux/cobalt-wdt.h Wed Dec 31 16:00:00 1969 +++ cobalt-2.4.5/include/linux/cobalt-wdt.h Thu May 31 14:33:16 2001 @@ -0,0 +1,16 @@ +/* $Id: $ */ +/* Copyright 2001 Sun Microsystems, Inc. */ +#ifndef COBALT_WDT_H +#define COBALT_WDT_H + +#include + +void cobalt_wdt_refresh(unsigned long refresh_timer); +void cobalt_wdt_trigger_reboot(void); + +void cobalt_wdt_disable(void); +void cobalt_wdt_reenable(void); + +void cobalt_wdt_cleardog(void); + +#endif diff -ruN dist-2.4.5/arch/i386/config.in cobalt-2.4.5/arch/i386/config.in --- dist-2.4.5/arch/i386/config.in Thu May 24 15:14:08 2001 +++ cobalt-2.4.5/arch/i386/config.in Thu May 31 14:31:37 2001 @@ -192,6 +192,7 @@ define_bool CONFIG_X86_LOCAL_APIC y define_bool CONFIG_PCI y else + source drivers/cobalt/Config.in if [ "$CONFIG_SMP" = "y" ]; then define_bool CONFIG_X86_IO_APIC y define_bool CONFIG_X86_LOCAL_APIC y diff -ruN dist-2.4.5/Documentation/Configure.help cobalt-2.4.5/Documentation/Configure.help --- dist-2.4.5/Documentation/Configure.help Thu May 24 15:03:06 2001 +++ cobalt-2.4.5/Documentation/Configure.help Thu May 31 14:31:29 2001 @@ -13035,6 +13035,121 @@ If unsure, say N. +Cobalt Networks support +CONFIG_COBALT + Support for Cobalt Networks x86-based servers. + +Gen III (3000 series) system support +CONFIG_COBALT_GEN_III + This option enables support for the 3000 series of Cobalt Networks + systems. This includes the RaQ 3, RaQ 4, and Qube 3 product lines. + + This platform uses an AMD K6-2 processor, an ALI M1541/1533 chipset, + an optional NCR 53c875 SCSI controller, and two Intel 82559ER or + National Semiconductor DP83815 NICs. + + Getting this option wrong will likely result in a kernel that does + not boot. Selecting support for more than 1 system series will add + bloat to your kernel, but will not cause anything bad to happen. + + If you have a Cobalt Networks System, but aren't sure what kind, + say Y here. + +Gen V (5000 series) system support +CONFIG_COBALT_GEN_V + This option enables support for the 5000 series of Cobalt Networks + systems. This includes the RaQ XTR product line. + + This platform uses Intel Pentium III Coppermine FCPGA CPUs, the + ServerWorks LE chipset (with registered ECC DIMMs only!), two + HighPoint HPT370 IDE controllers, and two National Semiconductor + DP83815 NICs. + + Getting this option wrong will likely result in a kernel that does + not boot. Selecting support for more than 1 system series will add + bloat to your kernel, but will not cause anything bad to happen. + + If you have a Cobalt Networks System, but aren't sure what kind, + say Y here. + +Create legacy /proc files +CONFIG_COBALT_OLDPROC + This option forces some Cobalt Networks drivers to support legacy + files in /proc. Older versions of these drivers exported files + directly in /proc, as opposed to the newer /proc/cobalt. If you say + N to this option, the old filenames will no longer be exported. + Regardless of your selection here, files in /proc/cobalt will be + exported. Of course, you have to include support for /proc fs, too. + + It is safe to say Y here. + +Front panel LCD support +CONFIG_COBALT_LCD + This enables support for the Cobalt Networks front panel. This is + for the LCD panel and buttons. The primary method for connection is + via the parallel port (IO base 0x370), but newer systems use an + I2C bus. + + If you have a Cobalt Networks system, you should say Y here. + +Software controlled LED support +CONFIG_COBALT_LED + This enables support for the software-controlled LEDs on Cobalt + Networks systems. This includes the fault light and front panel LEDs + on the RaQ XTR, the lightbar on the Qube 3, and others. + + If you have a Cobalt Networks system, you should say Y here. + +Silicon serial number support +CONFIG_COBALT_SERNUM + This enables support for the on-board serial number on Cobalt Networks + systems. This is a universally-unique 64-bit serial number. Some + systems use a Dallas DS2401 chip, others have an I2C based EEPROM. + + If you select Y here, the files /proc/cobalt/hostid and + /proc/cobalt/serialnumber will be created. The hostid file contains a + 32 bit integer generated from the serial number, in binary form. The + serialnumber file contains the hexadecimal representation of the serial + number, in ASCII. + + If you have a Cobalt Networks system, you should say Y here. + +Chipset watchdog timer support +CONFIG_COBALT_WDT + This enables support for the watchdog timer built into Cobalt chipsets. + The timer wakes up periodically, to make find out if system has hung, + or disabled interrupts too long. The result of detecting a hang is a + hard reboot. + + If you have a Cobalt Networks system, you should say Y here. + +Thermal sensor support +CONFIG_COBALT_THERMAL + This enables support for the thermal sensor(s) built into Cobalt + Networks systems. This driver exports /proc/cobalt/thermal_sensors. + + If you have a Cobalt Networks system, you should say Y here. + +Fan tachometer support +CONFIG_COBALT_FANS + This enables support for the fan tachometers built into some Cobalt + Networks systems. This driver exports /proc/cobalt/faninfo. Some + Cobalt software depends on this feature, and enabling it does not cause + any risks. + + If you have a Cobalt Networks system, you should say Y here, unless you + are absolutely sure. + +Disk drive ruler support +CONFIG_COBALT_RULER + This enables support for the cobalt hard drive ruler, found on some + Cobalt systems, including the RaQ XTR. This is the device that enables + swapping of drives. It is not needed for basic disk operation. + Enabling this on a system with no ruler will have no adverse effects. + + If you have a Cobalt Networks system, you should say Y here, + unless you are absolutely sure. + I2C support CONFIG_I2C I2C (pronounce: I-square-C) is a slow serial bus protocol used in diff -ruN dist-2.4.5/arch/i386/kernel/Makefile cobalt-2.4.5/arch/i386/kernel/Makefile --- dist-2.4.5/arch/i386/kernel/Makefile Fri Dec 29 14:35:47 2000 +++ cobalt-2.4.5/arch/i386/kernel/Makefile Thu May 31 14:31:37 2001 @@ -40,5 +40,6 @@ obj-$(CONFIG_X86_LOCAL_APIC) += apic.o obj-$(CONFIG_X86_IO_APIC) += io_apic.o mpparse.o obj-$(CONFIG_X86_VISWS_APIC) += visws_apic.o +obj-$(CONFIG_COBALT) += cobalt.o include $(TOPDIR)/Rules.make diff -ruN dist-2.4.5/arch/i386/kernel/cobalt.c cobalt-2.4.5/arch/i386/kernel/cobalt.c --- dist-2.4.5/arch/i386/kernel/cobalt.c Wed Dec 31 16:00:00 1969 +++ cobalt-2.4.5/arch/i386/kernel/cobalt.c Thu May 31 14:31:37 2001 @@ -0,0 +1,168 @@ +/* $Id: cobalt.c,v 1.4 2001/04/17 05:38:51 asun Exp $ */ +#include + +#ifdef CONFIG_COBALT +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static inline void ledonoff(unsigned long on, unsigned long off); + +void +cobalt_nmi(unsigned char reason, struct pt_regs *regs) +{ +#if defined(CONFIG_COBALT_GEN_V) + struct pci_dev *cnb_dev; + u8 err; + + printk("NMI:"); + cnb_dev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, + PCI_DEVICE_ID_SERVERWORKS_LE, NULL); + if (!cnb_dev) { + printk("%s: can't find north bridge for NMI status\n", + __FILE__); + return; + } + + pci_read_config_byte(cnb_dev, 0x47, &err); + if (err & 0x40) + printk(" (PCI tx data error)"); + if (err & 0x20) + printk(" (PCI rx data error)"); + if (err & 0x10) + printk(" (PCI address error)"); + if (err & 0x04) + printk(" (DRAM uncorrectable error)"); + if (err & 0x02) + printk(" (DRAM correctable error)"); + if (err & 0x01) + printk(" (Shutdown cycle detected)"); + + if (err & 0x06) { + u32 address; + u8 row, dimm, ecc; + + pci_read_config_dword(cnb_dev, 0x94, &address); + row = (address >> 29) & 0x7; + pci_read_config_byte(cnb_dev, 0x7c + (row >> 1), &dimm); + dimm = ((row & 1) ? (dimm >> 4) : dimm) & 0xf; + pci_read_config_byte(cnb_dev, 0xe8, &ecc); + + printk(" [memory row 0x%x, DIMM type %d " + "(col addr=0x%x, row addr=0x%x) ECC=0x%x]", row, + dimm, (address >> 15) & 0x3fff, address & 0x7fff, + ecc); + } + printk("\n"); + + /* clear errors */ + pci_write_config_byte(cnb_dev, 0x47, err); +#endif +} + +void +cobalt_restart(void) +{ +#if defined(CONFIG_COBALT_GEN_III) + /* kick watchdog */ + cobalt_wdt_trigger_reboot(); +#elif defined (CONFIG_COBALT_GEN_V) + cobalt_ruler_powerdown(); + + /* set "Enable Hard Reset" bit to 1 */ + outb(0x02, 0x0cf9); + + /* the 0-to-1 transition of bit 2 will cause reset of processor */ + outb(0x06, 0x0cf9); +#endif + + /* we should not get here unless there is a BAD error */ + printk("%s: can not restart - halting\n", __FILE__); + machine_halt(); +} + +void +cobalt_halt(void) +{ + int haltok = current_cpu_data.hlt_works_ok; + +#if defined(CONFIG_COBALT_GEN_V) + /* we have soft power-off */ + machine_power_off(); +#endif + + /* + * we want to do cpu_idle, but we don't actually want to + * call cpu_idle. bleah. + */ + while (1) { + ledonoff(HZ >> 1, HZ >> 1); + if (haltok) { + __asm__("hlt"); + } + } +} + +static inline void +ledonoff(unsigned long on, unsigned long off) +{ +#if defined(CONFIG_COBALT_LCD) + unsigned long start; + int haltok = current_cpu_data.hlt_works_ok; + + if (on) { + start = jiffies; + cobalt_led_set(cobalt_led_get() | LED_SHUTDOWN); + while (jiffies < start + on) { + if (haltok) __asm__("hlt"); + } + } + + if (off) { + start = jiffies; + cobalt_led_set(cobalt_led_get() & ~LED_SHUTDOWN); + while (jiffies < start + off) { + if (haltok) __asm__("hlt"); + } + } +#endif +} + +void +cobalt_power_off(void) +{ +#if defined(CONFIG_COBALT_GEN_V) + u16 addr; + u8 val; + + /* use card control register 7 to select logical device 2 (APC) */ + outb(SUPERIO_LOGICAL_DEV, SUPERIO_INDEX_PORT); + outb(SUPERIO_DEV_RTC, SUPERIO_DATA_PORT); + + /* get the base register */ + outb(SUPERIO_ADDR_HIGH, SUPERIO_INDEX_PORT); + addr = inb(SUPERIO_DATA_PORT) << 8; + outb(SUPERIO_ADDR_LOW, SUPERIO_INDEX_PORT); + addr |= inb(SUPERIO_DATA_PORT); + if (addr) { + /* set up bank 2 */ + outb(SUPERIO_RTC_CRA, addr); + val = inb(addr + 1) & 0x8f; + outb(val | SUPERIO_RTC_BANK_2, addr + 1); + + /* power off the machine with APCR1 */ + outb(SUPERIO_APCR1, addr); + val = inb(addr + 1); + outb(0x20 | val, addr + 1); + } +#endif +} + +#endif /* CONFIG_COBALT */ diff -ruN dist-2.4.5/arch/i386/kernel/process.c cobalt-2.4.5/arch/i386/kernel/process.c --- dist-2.4.5/arch/i386/kernel/process.c Fri Feb 9 11:29:44 2001 +++ cobalt-2.4.5/arch/i386/kernel/process.c Thu May 31 14:31:38 2001 @@ -46,6 +46,9 @@ #ifdef CONFIG_MATH_EMULATION #include #endif +#ifdef CONFIG_COBALT +#include +#endif #include @@ -354,6 +357,10 @@ disable_IO_APIC(); #endif +#ifdef CONFIG_COBALT + cobalt_restart(); +#endif + if(!reboot_thru_bios) { /* rebooting needs to touch the page at absolute addr 0 */ *((unsigned short *)__va(0x472)) = reboot_mode; @@ -376,10 +383,17 @@ void machine_halt(void) { +#ifdef CONFIG_COBALT + cobalt_halt(); +#endif } void machine_power_off(void) { +#ifdef CONFIG_COBALT + cobalt_power_off(); +#endif + if (pm_power_off) pm_power_off(); } diff -ruN dist-2.4.5/arch/i386/kernel/setup.c cobalt-2.4.5/arch/i386/kernel/setup.c --- dist-2.4.5/arch/i386/kernel/setup.c Fri May 25 17:07:09 2001 +++ cobalt-2.4.5/arch/i386/kernel/setup.c Thu May 31 14:31:38 2001 @@ -104,6 +104,10 @@ #include #include #include +#ifdef CONFIG_COBALT +#include +#endif + /* * Machine setup.. */ @@ -2441,9 +2445,13 @@ x86_cap_flags[i] != NULL ) p += sprintf(p, " %s", x86_cap_flags[i]); - p += sprintf(p, "\nbogomips\t: %lu.%02lu\n\n", + p += sprintf(p, "\nbogomips\t: %lu.%02lu\n", c->loops_per_jiffy/(500000/HZ), (c->loops_per_jiffy/(5000/HZ)) % 100); +#ifdef CONFIG_COBALT + p += sprintf(p, "temperature\t: %s\n", cobalt_temp_read(n)); +#endif + p += sprintf(p, "\n"); } return p - buffer; } diff -ruN dist-2.4.5/arch/i386/kernel/traps.c cobalt-2.4.5/arch/i386/kernel/traps.c --- dist-2.4.5/arch/i386/kernel/traps.c Mon May 7 14:15:21 2001 +++ cobalt-2.4.5/arch/i386/kernel/traps.c Thu May 31 14:31:38 2001 @@ -46,6 +46,9 @@ #include #include #endif +#ifdef CONFIG_COBALT +#include +#endif #include @@ -347,12 +350,18 @@ static void mem_parity_error(unsigned char reason, struct pt_regs * regs) { +#if defined(CONFIG_COBALT_GEN_V) + cobalt_nmi(reason, regs); +#else printk("Uhhuh. NMI received. Dazed and confused, but trying to continue\n"); printk("You probably have a hardware problem with your RAM chips\n"); +#endif - /* Clear and disable the memory parity error line. */ - reason = (reason & 0xf) | 4; - outb(reason, 0x61); + /* Clear and re-enable the memory parity error line. */ + reason &= 0xf; + outb(reason | 4, 0x61); + outb(reason & ~4, 0x61); + } static void io_check_error(unsigned char reason, struct pt_regs * regs) diff -ruN dist-2.4.5/drivers/Makefile cobalt-2.4.5/drivers/Makefile --- dist-2.4.5/drivers/Makefile Wed May 16 10:27:02 2001 +++ cobalt-2.4.5/drivers/Makefile Thu May 31 14:32:02 2001 @@ -7,7 +7,7 @@ mod-subdirs := dio mtd sbus video macintosh usb input telephony sgi i2o ide \ - scsi md ieee1394 pnp isdn atm fc4 net/hamradio i2c acpi + scsi md ieee1394 pnp isdn atm fc4 net/hamradio i2c acpi cobalt subdir-y := parport char block net sound misc media cdrom subdir-m := $(subdir-y) @@ -42,6 +42,7 @@ subdir-$(CONFIG_HAMRADIO) += net/hamradio subdir-$(CONFIG_I2C) += i2c subdir-$(CONFIG_ACPI) += acpi +subdir-$(CONFIG_COBALT) += cobalt include $(TOPDIR)/Rules.make diff -ruN dist-2.4.5/drivers/char/mem.c cobalt-2.4.5/drivers/char/mem.c --- dist-2.4.5/drivers/char/mem.c Sat May 19 18:11:36 2001 +++ cobalt-2.4.5/drivers/char/mem.c Thu May 31 14:32:09 2001 @@ -26,6 +26,9 @@ #include #include +#ifdef CONFIG_COBALT +extern int cobalt_init(void); +#endif #ifdef CONFIG_I2C extern int i2c_init_all(void); #endif @@ -644,6 +647,9 @@ #endif #if defined(CONFIG_ADB) adbdev_init(); +#endif +#ifdef CONFIG_COBALT + cobalt_init(); #endif return 0; } diff -ruN dist-2.4.5/Makefile cobalt-2.4.5/Makefile --- dist-2.4.5/Makefile Fri May 25 09:51:33 2001 +++ cobalt-2.4.5/Makefile Thu May 31 14:31:28 2001 @@ -177,6 +177,7 @@ DRIVERS-$(CONFIG_PHONE) += drivers/telephony/telephony.o DRIVERS-$(CONFIG_ACPI) += drivers/acpi/acpi.o DRIVERS-$(CONFIG_MD) += drivers/md/mddev.o +DRIVERS-$(CONFIG_COBALT) += drivers/cobalt/cobalt.o DRIVERS := $(DRIVERS-y) @@ -193,6 +194,10 @@ drivers/zorro/devlist.h drivers/zorro/gen-devlist \ drivers/sound/bin2hex drivers/sound/hex2hex \ drivers/atm/fore200e_mkfirm drivers/atm/{pca,sba}*{.bin,.bin1,.bin2} \ + drivers/scsi/aic7xxx/aicasm/aicasm_gram.c \ + drivers/scsi/aic7xxx/aicasm/aicasm_scan.c \ + drivers/scsi/aic7xxx/aicasm/y.tab.h \ + drivers/scsi/aic7xxx/aicasm/aicasm \ net/khttpd/make_times_h \ net/khttpd/times.h \ submenu*