source: clfs-embedded/patches/linux-2.6.20.1-cobalt_x86-1.patch@ 56d186f

Last change on this file since 56d186f was 9a57cc4, checked in by Jim Gifford <clfs@…>, 18 years ago

Updated to Linux 2.6.20.1

  • Property mode set to 100644
File size: 217.6 KB
  • linux-2.6.20

    Submitted By: Jim Gifford (patches at jg555 dot com)
    Date: 2007-02-04
    Initial Package Version: 2.6.20
    Origin: Gentoo - Jeff Waters
    Upstream Status: N/A
    Description: Adds Support for the x86 Cobalt Series
    
    diff -Naur linux-2.6.20.orig/Makefile linux-2.6.20/Makefile
    old new  
    206206KBUILD_MODULES :=
    207207KBUILD_BUILTIN := 1
    208208
     209DRIVERS-$(CONFIG_COBALT_RAQ) += drivers/cobalt/cobalt.o
    209210#       If we have only "make modules", don't compile built-in objects.
    210211#       When we're building modules with modversions, we need to consider
    211212#       the built-in objects during the descend as well, in order to
     
    703704      cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) \
    704705                     $(if $(CONFIG_KALLSYMS_ALL),--all-symbols) > $@
    705706
     707
     708cobalt: vmlinux
     709        strip vmlinux
     710        bzip2 vmlinux
     711
    706712.tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE
    707713        $(call if_changed_dep,as_o_S)
    708714
  • arch/i386/kernel/Makefile

    diff -Naur linux-2.6.20.orig/arch/i386/kernel/Makefile linux-2.6.20/arch/i386/kernel/Makefile
    old new  
    5555targets += vsyscall-note.o vsyscall.lds
    5656
    5757# The DSO images are built using a special linker script.
     58obj-$(CONFIG_COBALT_RAQ)        += cobalt.o
    5859quiet_cmd_syscall = SYSCALL $@
    5960      cmd_syscall = $(CC) -m elf_i386 -nostdlib $(SYSCFLAGS_$(@F)) \
    6061                          -Wl,-T,$(filter-out FORCE,$^) -o $@
  • arch/i386/kernel/cobalt.c

    diff -Naur linux-2.6.20.orig/arch/i386/kernel/cobalt.c linux-2.6.20/arch/i386/kernel/cobalt.c
    old new  
     1/* $Id: cobalt.c,v 1.34 2002/11/04 17:54:14 thockin Exp $ */
     2#include <linux/config.h>
     3
     4#include <linux/types.h>
     5#include <linux/stddef.h>
     6#include <linux/kernel.h>
     7#include <linux/ptrace.h>
     8#include <linux/reboot.h>
     9#include <linux/delay.h>
     10#include <linux/pci.h>
     11#include <linux/timer.h>
     12#include <linux/init.h>
     13
     14#include <cobalt/cobalt.h>
     15#include <cobalt/misc.h>
     16#include <cobalt/led.h>
     17#include <cobalt/wdt.h>
     18#include <cobalt/acpi.h>
     19#include <cobalt/superio.h>
     20#include <cobalt/systype.h>
     21
     22#define MAX_NMI_PS      10
     23
     24static u8 last_err;
     25static u32 last_address;
     26static unsigned long nmi_repeats;
     27static struct timer_list nmi_timer;
     28static int timer_added;
     29static unsigned long nmi_count;
     30static spinlock_t nmi_state_lock = SPIN_LOCK_UNLOCKED;
     31
     32static inline void
     33ledonoff(unsigned long on, unsigned long off)
     34{
     35#ifdef CONFIG_COBALT_LED
     36        unsigned long start;
     37        int haltok = current_cpu_data.hlt_works_ok;
     38
     39        if (on) {
     40                start = jiffies;
     41                cobalt_led_set(cobalt_led_get() | LED_SHUTDOWN);
     42                while (jiffies < start + on) {
     43                        if (haltok) __asm__("hlt");
     44                }
     45        }
     46
     47        if (off) {
     48                start = jiffies;
     49                cobalt_led_set(cobalt_led_get() & ~LED_SHUTDOWN);
     50                while (jiffies < start + off) {
     51                        if (haltok) __asm__("hlt");
     52                }
     53        }
     54#endif
     55}
     56
     57/* clla this holding nmi_state_lock */
     58static inline void
     59do_repeats(void)
     60{
     61        if (nmi_repeats) {
     62                printk("NMI: last error repeated %lu times\n", nmi_repeats);
     63                nmi_repeats = 0;
     64        }
     65}
     66
     67static void
     68nmi_throttle_fn(unsigned long data)
     69{
     70        unsigned long flags;
     71
     72        spin_lock_irqsave(&nmi_state_lock, flags);
     73
     74        /* clear any repeated NMIs */
     75        do_repeats();
     76
     77        /* have we had a lot of errors this second */
     78        if (nmi_count > MAX_NMI_PS) {
     79                printk("NMI: %lu messages were throttled\n",
     80                        nmi_count - MAX_NMI_PS);
     81                nmi_count = 0;
     82        }
     83
     84        /* de-activate the timer - will be reactivated by an NMI */
     85        del_timer(&nmi_timer);
     86        timer_added = 0;
     87
     88        spin_unlock_irqrestore(&nmi_state_lock, flags);
     89}
     90
     91void
     92cobalt_nmi(unsigned char reason, struct pt_regs *regs)
     93{
     94        if (cobt_is_5k()) {
     95                static struct pci_dev *cnb_dev;
     96                u8 err;
     97                u32 address = 0;
     98                unsigned long flags;
     99
     100                /* find our memory controller */
     101                if (!cnb_dev) {
     102                        cnb_dev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
     103                                  PCI_DEVICE_ID_SERVERWORKS_LE, NULL);
     104                }
     105                if (!cnb_dev) {
     106                        EPRINTK("can't find north bridge for NMI status\n");
     107                        return;
     108                }
     109
     110                /* read the error number */
     111                pci_read_config_byte(cnb_dev, 0x47, &err);
     112
     113                /* if a memory error was detected, where? */
     114                if (err & 0x06) {
     115                        pci_read_config_dword(cnb_dev, 0x94, &address);
     116                }
     117
     118                spin_lock_irqsave(&nmi_state_lock, flags);
     119
     120                /* set up the timer, if it isn't set to go already */
     121                if (!timer_added) {
     122                        init_timer(&nmi_timer);
     123                        nmi_timer.expires = jiffies + HZ;
     124                        nmi_timer.function = nmi_throttle_fn;
     125                        add_timer(&nmi_timer);
     126                        timer_added = 1;
     127                }
     128
     129                /* if we already printed this error */
     130                if (last_err && err == last_err && address == last_address) {
     131                        nmi_repeats++;
     132                        spin_unlock_irqrestore(&nmi_state_lock, flags);
     133                } else {
     134                        unsigned long nmi_now;
     135
     136                        /* different error - show repeats */
     137                        do_repeats();
     138
     139                        /* we only want to do a few messages per second */
     140                        nmi_now = nmi_count++;
     141
     142                        spin_unlock_irqrestore(&nmi_state_lock, flags);
     143
     144                        /* generate a new message */
     145                        if (nmi_now < MAX_NMI_PS) {
     146                                /* only remember NMIs that we can print */
     147                                last_err = err;
     148                                last_address = address;
     149
     150                                printk("NMI:");
     151                                if (err & 0x40)
     152                                        printk(" (PCI tx data error)");
     153                                if (err & 0x20)
     154                                        printk(" (PCI rx data error)");
     155                                if (err & 0x10)
     156                                        printk(" (PCI address error)");
     157                                if (err & 0x04)
     158                                        printk(" (DRAM uncorrectable error)");
     159                                if (err & 0x02)
     160                                        printk(" (DRAM correctable error)");
     161                                if (err & 0x01)
     162                                        printk(" (Shutdown cycle detected)");
     163
     164                                if (err & 0x06) {
     165                                        u8 row, dimm, ecc;
     166
     167                                        row = (address >> 29) & 0x7;
     168                                        pci_read_config_byte(cnb_dev,
     169                                                0x7c + (row >> 1), &dimm);
     170                                        dimm = ((row & 1) ?
     171                                                (dimm >> 4) : dimm) & 0xf;
     172                                        pci_read_config_byte(cnb_dev, 0xe8,
     173                                                &ecc);
     174
     175                                        printk(" [memory row %d, DIMM type %d, "
     176                                                "col=0x%x, row=0x%x, ECC=0x%x]",
     177                                                row, dimm,
     178                                                (address >> 15) & 0x3fff,
     179                                                address & 0x7fff, ecc);
     180                                }
     181                                printk("\n");
     182                        }
     183                }
     184
     185                /* clear errors */
     186                pci_write_config_byte(cnb_dev, 0x47, err);
     187        } else {
     188                /* TODO: make throttling generic, handle GP NMIs */
     189                printk("NMI: unknown error\n");
     190        }
     191}
     192
     193void
     194cobalt_restart(void)
     195{
     196        if (cobt_is_3k()) {
     197                /* kick watchdog */
     198                cobalt_wdt_trigger_reboot();
     199        } else if (cobt_is_5k()) {
     200                /* set "Enable Hard Reset" bit to 1 */
     201                outb(0x02, 0x0cf9);
     202
     203                /* 0-to-1 transition of bit 2 will cause reset of processor */
     204                outb(0x06, 0x0cf9);
     205        }
     206        mdelay(3000);
     207
     208        /* we should not get here unless there is a BAD error */
     209        EPRINTK("can not restart - halting\n");
     210        machine_halt();
     211}
     212
     213void
     214cobalt_halt(void)
     215{
     216        int haltok = current_cpu_data.hlt_works_ok;
     217
     218        if (cobt_is_5k()) {
     219                /* we have soft power-off */
     220                machine_power_off();
     221        }
     222
     223        /*
     224         * we want to do cpu_idle, but we don't actually want to
     225         * call cpu_idle. bleah.
     226         */
     227        while (1) {
     228                ledonoff(HZ >> 1, HZ >> 1);
     229                if (haltok) {
     230                        __asm__("hlt");
     231                }
     232        }
     233}
     234
     235void
     236cobalt_power_off(void)
     237{
     238        u16 addr;
     239
     240        if (cobt_is_monterey()) {
     241                u8 val;
     242                /* use card control reg. 7 to select logical device 2 (APC) */
     243                addr = superio_ldev_base(PC87317_DEV_RTC);
     244
     245                /* set up bank 2 */
     246                outb(PC87317_RTC_CRA, addr);
     247                val = inb(addr + 1) & 0x8f;
     248                outb(val | PC87317_RTC_BANK_2, addr + 1);
     249
     250                /* power off the machine with APCR1 */
     251                outb(PC87317_APCR1, addr);
     252                val = inb(addr + 1);
     253                outb(0x20 | val, addr + 1);
     254        } else if (cobt_is_alpine()) {
     255                int i;
     256                /* clear status bits, base addr 3 */
     257                addr = superio_ldev_base_n(PC87417_DEV_SWC, 3);
     258                for (i = 0; i < 4; i++) {
     259                        /*
     260                         * if we have an event while running,
     261                         * we can't halt unless we clear these
     262                         * */
     263                        outb(0xff, addr+i);
     264                }
     265
     266                /* set sleep state, base addr 2 */
     267                addr = superio_ldev_base_n(PC87417_DEV_SWC, 2);
     268                /* PM1b_CNT_HIGH @offset 1 - set state to S5 */
     269                outb(0x34, addr+1);
     270        }
     271        mdelay(3000);
     272        EPRINTK("can not power off\n");
     273}
     274
     275/* put arch specific stuff to run at init time here */
     276static int __init
     277cobalt_arch_init(void)
     278{
     279        return 0;
     280}
     281module_init(cobalt_arch_init);
  • arch/i386/kernel/process.c

    diff -Naur linux-2.6.20.orig/arch/i386/kernel/process.c linux-2.6.20/arch/i386/kernel/process.c
    old new  
    5252#include <asm/math_emu.h>
    5353#endif
    5454
     55#ifdef CONFIG_COBALT_RAQ
     56#include <cobalt/misc.h>
     57#include <cobalt/lcd.h>
     58#endif
     59
    5560#include <linux/err.h>
    5661
    5762#include <asm/tlbflush.h>
     
    477482void dump_thread(struct pt_regs * regs, struct user * dump)
    478483{
    479484        int i;
     485       
     486#ifdef CONFIG_COBALT_RAQ
     487        cobalt_flush();
     488        cobalt_restart();
     489#endif
     490
    480491
    481492/* changed the size calculations - should hopefully work better. lbt */
    482493        dump->magic = CMAGIC;
  • arch/i386/kernel/reboot.c

    diff -Naur linux-2.6.20.orig/arch/i386/kernel/reboot.c linux-2.6.20/arch/i386/kernel/reboot.c
    old new  
    1919#include "mach_reboot.h"
    2020#include <linux/reboot_fixups.h>
    2121
     22#ifdef CONFIG_COBALT_RAQ
     23#include <cobalt/misc.h>
     24#include <cobalt/lcd.h>
     25#endif
     26
    2227/*
    2328 * Power off function, if any
    2429 */
     
    280285EXPORT_SYMBOL(machine_real_restart);
    281286#endif
    282287
     288/* kill some time at halt/reboot to allow drives with large cache to sync */
     289
     290#ifdef CONFIG_COBALT_RAQ
     291void cobalt_flush(void)
     292{
     293        int i;
     294        static int flushed;
     295
     296        if (flushed)
     297                return;
     298        flushed = 1;
     299
     300        printk("waiting for devices to flush");
     301        for (i = 0 ; i < 10; i++) {
     302                printk(".");
     303                mdelay(500);
     304#ifdef CONFIG_COBALT_LCD
     305                if (i == 8)
     306                        cobalt_lcd_off();
     307#endif
     308        }
     309        printk("done\n");
     310}
     311#endif
     312
    283313void machine_shutdown(void)
    284314{
     315#ifdef CONFIG_COBALT_RAQ
     316        cobalt_flush();
     317        cobalt_halt();
     318#endif
     319
    285320#ifdef CONFIG_SMP
    286321        int reboot_cpu_id;
    287322
     
    318353
    319354void machine_emergency_restart(void)
    320355{
     356#ifdef CONFIG_COBALT_RAQ
     357        cobalt_restart();
     358#endif
    321359        if (!reboot_thru_bios) {
    322360                if (efi_enabled) {
    323361                        efi.reset_system(EFI_RESET_COLD, EFI_SUCCESS, 0, NULL);
     
    342380
    343381void machine_restart(char * __unused)
    344382{
     383#ifdef CONFIG_COBALT_RAQ
     384        cobalt_flush();
     385        cobalt_restart();
     386#endif
    345387        machine_shutdown();
    346388        machine_emergency_restart();
    347389}
  • arch/i386/kernel/traps.c

    diff -Naur linux-2.6.20.orig/arch/i386/kernel/traps.c linux-2.6.20/arch/i386/kernel/traps.c
    old new  
    6161
    6262int panic_on_unrecovered_nmi;
    6363
     64#ifdef CONFIG_COBALT_RAQ
     65#include <cobalt/misc.h>
     66#endif
     67
    6468asmlinkage int system_call(void);
    6569
    6670/* Do we ignore FPU interrupts ? */
     
    631635static __kprobes void
    632636mem_parity_error(unsigned char reason, struct pt_regs * regs)
    633637{
     638#ifdef CONFIG_COBALT_RAQ
     639        cobalt_nmi(reason, regs);
     640#else
    634641        printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on "
    635642                "CPU %d.\n", reason, smp_processor_id());
    636643        printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n");
     
    638645                panic("NMI: Not continuing");
    639646
    640647        printk(KERN_EMERG "Dazed and confused, but trying to continue\n");
    641 
     648#endif
    642649        /* Clear and disable the memory parity error line. */
    643650        clear_mem_error(reason);
    644651}
  • drivers/Kconfig

    diff -Naur linux-2.6.20.orig/drivers/Kconfig linux-2.6.20/drivers/Kconfig
    old new  
    8282
    8383source "drivers/kvm/Kconfig"
    8484
     85source "drivers/cobalt/Kconfig"
     86
    8587endmenu
  • drivers/Makefile

    diff -Naur linux-2.6.20.orig/drivers/Makefile linux-2.6.20/drivers/Makefile
    old new  
    6767obj-$(CONFIG_EDAC)              += edac/
    6868obj-$(CONFIG_MCA)               += mca/
    6969obj-$(CONFIG_EISA)              += eisa/
     70obj-$(CONFIG_COBALT_RAQ)        += cobalt/
     71
    7072obj-$(CONFIG_CPU_FREQ)          += cpufreq/
    7173obj-$(CONFIG_MMC)               += mmc/
    7274obj-$(CONFIG_NEW_LEDS)          += leds/
  • drivers/char/Kconfig

    diff -Naur linux-2.6.20.orig/drivers/char/Kconfig linux-2.6.20/drivers/char/Kconfig
    old new  
    808808          will get access to the real time clock (or hardware clock) built
    809809          into your computer.
    810810
    811 config COBALT_LCD
     811config COBALT_MIPS_LCD
    812812        bool "Support for Cobalt LCD"
    813813        depends on MIPS_COBALT
    814814        help
  • drivers/char/Makefile

    diff -Naur linux-2.6.20.orig/drivers/char/Makefile linux-2.6.20/drivers/char/Makefile
    old new  
    7979obj-$(CONFIG_I8K)               += i8k.o
    8080obj-$(CONFIG_DS1620)            += ds1620.o
    8181obj-$(CONFIG_HW_RANDOM)         += hw_random/
    82 obj-$(CONFIG_COBALT_LCD)        += lcd.o
     82obj-$(CONFIG_COBALT_MIPS_LCD)   += lcd.o
    8383obj-$(CONFIG_PPDEV)             += ppdev.o
    8484obj-$(CONFIG_NWBUTTON)          += nwbutton.o
    8585obj-$(CONFIG_NWFLASH)           += nwflash.o
  • drivers/char/misc.c

    diff -Naur linux-2.6.20.orig/drivers/char/misc.c linux-2.6.20/drivers/char/misc.c
    old new  
    4949#include <linux/tty.h>
    5050#include <linux/kmod.h>
    5151
     52#ifdef CONFIG_COBALT_RAQ
     53#include <cobalt/cobalt.h>
     54#include <cobalt/systype.h>
     55#include <cobalt/superio.h>
     56#include <cobalt/serialnum.h>
     57#include <cobalt/i2c.h>
     58#include <cobalt/misc.h>
     59#include <cobalt/lcd.h>
     60#endif
     61
     62
    5263/*
    5364 * Head entry for the doubly linked miscdevice list
    5465 */
     
    6374
    6475extern int pmu_device_init(void);
    6576
     77#ifdef CONFIG_COBALT_RAQ
     78extern int cobalt_init(void);
     79#endif
     80#ifdef CONFIG_COBALT_MIPS_LCD
     81module_init(lcd_init);
     82#endif
     83
    6684#ifdef CONFIG_PROC_FS
    6785static void *misc_seq_start(struct seq_file *seq, loff_t *pos)
    6886{
  • drivers/char/nvram.c

    diff -Naur linux-2.6.20.orig/drivers/char/nvram.c linux-2.6.20/drivers/char/nvram.c
    old new  
    4949#if defined(CONFIG_ATARI)
    5050#  define MACH ATARI
    5151#elif defined(__i386__) || defined(__x86_64__) || defined(__arm__)  /* and others?? */
    52 #define MACH PC
    53 #  if defined(CONFIG_COBALT)
     52#  if defined(CONFIG_COBALT_RAQ)
    5453#    include <linux/cobalt-nvram.h>
    5554#    define MACH COBALT
    5655#  else
  • drivers/cobalt/Kconfig

    diff -Naur linux-2.6.20.orig/drivers/cobalt/Kconfig linux-2.6.20/drivers/cobalt/Kconfig
    old new  
     1#
     2# Cobalt Drivers
     3#
     4
     5menu "Cobalt RaQ/Qube Hardware"
     6
     7config COBALT_RAQ
     8        bool "Cobalt RaQ/Qube Hardware Support"
     9        select INPUT
     10        default n
     11        ---help---
     12          NOTE: This support is for x86 Cobalts, not MIPS versions
     13         
     14          If you have a Gen III or Gen V Cobalt RaQ/Qube machine, it's probably
     15          a good idea to say Y here and choose from the options below.
     16
     17config COBALT_GEN_III
     18        bool "Gen III (3000 series) system support"
     19        depends on COBALT_RAQ
     20        default y
     21        ---help---
     22          If you have one of the following Gen III Cobalt systems, say Y here.
     23          Otherwise, it's best to say N.
     24         
     25           - RaQ 3
     26           - RaQ 4
     27           - Qube3
     28
     29config COBALT_GEN_V
     30        bool "Gen V (5000 series) system support"
     31        depends on COBALT_RAQ
     32        default n
     33        ---help---
     34          If you have one of the following Gen V Cobalt systems, say Y here.
     35          Otherwise, it's best to say N.
     36         
     37           - RaQ XTR
     38           - RaQ550
     39
     40config COBALT_OLDPROC
     41        bool "Create legacy /proc files"
     42        depends on COBALT_RAQ
     43        default y
     44        ---help---
     45          Creates entries in /proc/cobalt which provide useful information about
     46          your RaQ/Qube.  Best to say Y here.
     47
     48menu "Cobalt Hardware Options"
     49        depends on COBALT_RAQ
     50       
     51        config COBALT_LCD
     52                        bool "Front panel LCD support"
     53                        default y
     54                        ---help---
     55                          Handles support for the front panel LCD screen and buttons.
     56       
     57        config COBALT_LCD_TWIDDLE
     58                        bool "Twiddle LCD on boot"
     59                        depends on COBALT_LCD
     60                        default y
     61                        ---help---
     62                          Gives you a nice little twiddle on the LCD while booting.
     63       
     64        config COBALT_LED
     65                        bool "Software controlled LED support"
     66                        default y
     67                        ---help---
     68                          Allows software to play with the LEDs on the front of the
     69                          system.
     70       
     71        config COBALT_SERNUM
     72                        tristate "Serial number support"
     73                        depends on COBALT_OLDPROC
     74                        default y
     75                        ---help---
     76                          Allows you to retrieve the system's serial number via a /proc
     77                          entry.
     78       
     79        config COBALT_WDT
     80                        bool "Watchdog timer support"
     81                        depends on WATCHDOG
     82                        default y
     83                        ---help---
     84                          w00f?
     85       
     86        config COBALT_SENSORS
     87                        bool "System sensors support"
     88                        depends on COBALT_OLDPROC
     89                        default y
     90                        ---help---
     91                          Allows you to retrieve system temperatures via /proc entries.
     92       
     93        config COBALT_FANS
     94                        tristate "Fan tachometer support"
     95                        depends on COBALT_OLDPROC
     96                        depends on COBALT_GEN_V
     97                        default y
     98                        ---help---
     99                          Allows you to retrieve fan speeds via /proc entries.
     100       
     101        config COBALT_RAMINFO
     102                        tristate "Memory information support"
     103                        depends on COBALT_OLDPROC
     104                        default y
     105                        ---help---
     106                          Got DIMMs?  This will tell you how much and in which slot via a
     107                          /proc entry.
     108       
     109        config COBALT_RULER
     110                        bool "Disk drive ruler support"
     111                        depends on COBALT_OLDPROC
     112                        depends on COBALT_GEN_V
     113                        default y
     114                        ---help---
     115                          Not sure what this does... A purple tape measure maybe?
     116       
     117        config COBALT_ACPI
     118                        bool "Cobalt ACPI support"
     119                        depends on COBALT_GEN_V
     120                        default y
     121                        ---help---
     122                          ACPI support for the Generation V Cobalts.
     123       
     124        config COBALT_EMU_ACPI
     125                        bool "/proc/acpi emulation"
     126                        depends on COBALT_ACPI
     127                        default y
     128                        ---help---
     129                          Emulates the /proc/acpi interface.
     130
     131endmenu
     132
     133endmenu
  • drivers/cobalt/Makefile

    diff -Naur linux-2.6.20.orig/drivers/cobalt/Makefile linux-2.6.20/drivers/cobalt/Makefile
    old new  
     1#
     2# Makefile for the Sun/Cobalt device drivers
     3#
     4
     5#O_TARGET := cobalt.o
     6
     7#export-objs := init.o systype.o wdt.o i2c.o
     8
     9obj-$(CONFIG_COBALT_RAQ)        += init.o systype.o i2c.o wdt.o
     10obj-$(CONFIG_COBALT_ACPI)       += acpi.o
     11obj-$(CONFIG_COBALT_SERNUM)     += serialnum.o
     12obj-$(CONFIG_COBALT_LCD)        += lcd.o
     13obj-$(CONFIG_COBALT_LED)        += net.o led.o
     14obj-$(CONFIG_COBALT_SENSORS)    += sensors.o
     15obj-$(CONFIG_COBALT_FANS)       += fans.o
     16obj-$(CONFIG_COBALT_RAMINFO)    += raminfo.o
     17obj-$(CONFIG_COBALT_RULER)      += ruler.o
     18
  • drivers/cobalt/README

    diff -Naur linux-2.6.20.orig/drivers/cobalt/README linux-2.6.20/drivers/cobalt/README
    old new  
     1Notes on Cobalt's drivers:
     2
     3You will notice in several places constructs such as this:
     4
     5        if (cobt_is_3k()) {
     6                foo();
     7        } else if (cobt_is_5k()) {
     8                bar();
     9        }
     10
     11The goal here is to only compile in code that is needed, but to allow one to
     12define support for both 3k and 5k (and more?) style systems.  The systype
     13check macros are very simple and clean.  They check whether config-time
     14support for the generation has been enabled, and (if so) whether the current
     15systype matches the spcified generation.  This leaves the code free from
     16#ifdef cruft, but lets the compiler throw out unsupported generation-specific
     17code with if (0) detection.
     18
     19--
  • drivers/cobalt/acpi.c

    diff -Naur linux-2.6.20.orig/drivers/cobalt/acpi.c linux-2.6.20/drivers/cobalt/acpi.c
    old new  
     1 /*
     2 * cobalt acpi driver
     3 * Copyright (c) 2000, Cobalt Networks, Inc.
     4 * Copyright (c) 2001, Sun Microsystems, Inc.
     5 * $Id: acpi.c,v 1.32 2002/06/26 19:08:54 duncan Exp $
     6 *
     7 * author: asun@cobalt.com, thockin@sun.com
     8 * modified by: jeff@404ster.com
     9 *
     10 * this driver just sets stuff up for ACPI interrupts
     11 *
     12 * if acpi support really existed in the kernel, we would read
     13 * data from the ACPI tables. however, it doesn't. as a result,
     14 * we use some hardcoded values.
     15 *
     16 * This should be SMP safe.  The only data that needs protection is the acpi
     17 * handler list.  It gets scanned at timer-interrupts, must use
     18 * irqsave/restore locks. Read/write locks would be useful if there were any
     19 * other times that the list was read but never written. --TPH
     20 *
     21 * /proc/acpi emulation emulates the /proc/acpi/events interface supplied by
     22 * the INTEL acpi drivers.  A lot of the code to handle it has been adapted
     23 * from there.
     24 */
     25
     26#include <stdarg.h>
     27#include <stddef.h>
     28#include <linux/init.h>
     29#include <linux/sched.h>
     30#include <linux/config.h>
     31#include <linux/pci.h>
     32#include <linux/sched.h>
     33#include <linux/ioport.h>
     34#include <linux/delay.h>
     35#include <linux/spinlock.h>
     36#include <linux/proc_fs.h>
     37#include <linux/poll.h>
     38#include <linux/interrupt.h>
     39#include <asm/uaccess.h>
     40#include <asm/io.h>
     41#include <asm/irq.h>
     42
     43#include <cobalt/cobalt.h>
     44#include <cobalt/systype.h>
     45#include <cobalt/acpi.h>
     46#include <cobalt/superio.h>
     47
     48#define ACPI_DRIVER                     "Cobalt Networks ACPI driver"
     49#define ACPI_DRIVER_VMAJ                1
     50#define ACPI_DRIVER_VMIN                0
     51
     52#define POWER_BUTTON_SHUTDOWN   0
     53
     54#define ACPI_IRQ        10      /* XXX: hardcoded interrupt */
     55#define ACPI_NAME       "sci"
     56#define ACPI_MAGIC      0xc0b7ac21
     57
     58#define SUPERIO_EVENT   0xff
     59#define OSB4_EVENT      0x40
     60#define OSB4_INDEX_PORT SERVERWORKS_ACPI_INDEX_PORT
     61#define OSB4_DATA_PORT  SERVERWORKS_ACPI_DATA_PORT
     62
     63#define GEN_ACPI_TMR_STS      (0x1 <<  0)
     64#define GEN_ACPI_BM_STS       (0x1 <<  4)
     65#define GEN_ACPI_GBL_STS      (0x1 <<  5)
     66#define GEN_ACPI_PWRBTN_STS   (0x1 <<  8)
     67#define GEN_ACPI_SLPBTN_STS   (0x1 <<  9)
     68#define GEN_ACPI_RTC_STS      (0x1 << 10)
     69#define GEN_ACPI_WAK_STS      (0x1 << 15)
     70
     71#ifdef CONFIG_COBALT_EMU_ACPI
     72static int cobalt_acpi_setup_proc(void);
     73static int cobalt_acpi_open_event(struct inode *inode, struct file *file);
     74static int cobalt_acpi_close_event(struct inode *inode, struct file *file);
     75static ssize_t cobalt_acpi_read_event(struct file *file, char *buf,
     76        size_t count, loff_t *ppos);
     77static unsigned int cobalt_acpi_poll_event(struct file *file, poll_table *wait);
     78#endif
     79
     80
     81
     82typedef struct
     83{
     84    u16 hw_type;
     85    cobalt_acpi_hw_handler hw_handler;
     86    cobalt_acpi_enable_handler en_handler;
     87    void *data;
     88    struct list_head link;
     89} hw_handler_datum;
     90
     91typedef struct
     92{
     93    u16 hw_type;
     94    u16 table_len;
     95    u16 *table;
     96    struct list_head link;
     97} trans_table_datum;
     98
     99typedef struct
     100{
     101    cobalt_acpi_evt_handler handler;
     102    u16 ev_type;
     103    void *data;
     104    struct list_head link;
     105} evt_handler_datum;
     106
     107typedef struct
     108{
     109    cobalt_acpi_evt evt;
     110    struct list_head link;
     111} evt_list_datum;
     112
     113static LIST_HEAD( hw_handler_list );
     114static spinlock_t hw_handler_list_lock = SPIN_LOCK_UNLOCKED;
     115static LIST_HEAD( trans_table_list );
     116static spinlock_t trans_table_list_lock = SPIN_LOCK_UNLOCKED;
     117static LIST_HEAD( evt_handler_list );
     118static spinlock_t evt_handler_list_lock = SPIN_LOCK_UNLOCKED;
     119static LIST_HEAD( dispatch_queue );
     120static spinlock_t dispatch_queue_lock = SPIN_LOCK_UNLOCKED;
     121 
     122typedef struct
     123{
     124    u16 hw_type;
     125
     126        /* block lengths */
     127    u16 pm1_evt_len;
     128    u16 pm1_cnt_len;
     129    u16 pm2_cnt_len;
     130    u16 pm_tmr_len;
     131    u16 gpe0_len;
     132    u16 gpe1_len;
     133   
     134        /* block I/O locations */
     135    u16 pm1a_evt_blk;
     136    u16 pm1b_evt_blk;
     137    u16 pm1a_cnt_blk;
     138    u16 pm1b_cnt_blk;
     139    u16 pm2_cnt_blk;
     140    u16 pm_tmr_blk;
     141    u16 p_blk;
     142    u16 gpe0_blk;
     143    u16 gpe1_blk;
     144
     145        /* ponters to strings for the io names */
     146    char *pm1a_evt_nam;
     147    char *pm1b_evt_nam;
     148    char *pm1a_cnt_nam;
     149    char *pm1b_cnt_nam;
     150    char *pm2_cnt_nam;
     151    char *pm_tmr_nam;
     152    char *p_nam;
     153    char *gpe0_nam;
     154    char *gpe1_nam;
     155
     156        /* reference counts for events */
     157    atomic_t tmr_ref_cnt;
     158    atomic_t bm_ref_cnt;
     159    atomic_t gbl_ref_cnt;
     160    atomic_t pwrbtn_ref_cnt;
     161    atomic_t slpbtn_ref_cnt;
     162    atomic_t rtc_ref_cnt;
     163    atomic_t wak_ref_cnt;
     164    atomic_t *gpe_ref_cnt;
     165
     166
     167} generic_acpi_regions;
     168
     169
     170static void cobalt_acpi_enable_event( u16 ev_type, int en );
     171static void cobalt_acpi_run_enable_handler( u16 hw_type, u16 ev_type,
     172                                            u16 ev_data, int en);
     173static int cobalt_acpi_apply_evt_handlers( evt_list_datum *d );
     174static int cobalt_acpi_run_dispatch_queue( void );
     175static irqreturn_t acpi_interrupt(int irq, void *dev_id, struct pt_regs *regs);
     176static void cobalt_acpi_cleanup( void );
     177
     178static int register_acpi_regions( generic_acpi_regions *regions, char * subsys_name );
     179static int unregister_acpi_regions( generic_acpi_regions *regions );
     180static void cobalt_acpi_handle_pm1_blk( u16 io_addr, u16 len,
     181                                        generic_acpi_regions * regions );
     182static void cobalt_acpi_handle_gpe_blk( u16 io_addr, u16 len,
     183                                        generic_acpi_regions * regions );
     184static int cobalt_acpi_generic_hw_handler( int irq, void *dev_id,
     185                                           struct pt_regs *regs, void * data );
     186
     187static int cobalt_acpi_osb4_init( void );
     188static int cobalt_acpi_osb4_cleanup( void );
     189static int get_osb4_regions( generic_acpi_regions *regions);
     190
     191static int cobalt_acpi_csb5_init( void );
     192static int cobalt_acpi_csb5_cleanup( void );
     193static int get_csb5_regions( generic_acpi_regions *regions);
     194
     195static int cobalt_acpi_pc8731x_init( void );
     196static int cobalt_acpi_pc8731x_cleanup( void );
     197static int get_pc8731x_regions( generic_acpi_regions *regions );
     198
     199static int cobalt_acpi_pc8741x_init( void );
     200static int cobalt_acpi_pc8741x_cleanup( void );
     201static int get_pc8741x_regions( generic_acpi_regions *regions );
     202
     203static int cobalt_acpi_monterey_init( void );
     204static int cobalt_acpi_monterey_cleanup( void );
     205
     206static int cobalt_acpi_alpine_init( void );
     207static int cobalt_acpi_alpine_cleanup( void );
     208
     209static __inline__ struct list_head *list_pop( struct list_head *head )
     210{
     211    struct list_head *e;
     212   
     213    if( list_empty( head ) )
     214        return NULL;
     215   
     216    e = head->next;
     217    list_del( e );
     218    return e;
     219}
     220
     221static __inline__ u16 get_reg(u16 index, u16 data, u8 port)
     222{
     223    u16 reg;
     224
     225    outb(port, index);
     226    reg = inb(data);
     227    outb(port + 1, index);
     228    reg |= inb(data) << 8;
     229    return reg;
     230}
     231
     232/*
     233 *
     234 * Main ACPI Subsystem Code
     235 *
     236 */
     237
     238extern int cobalt_acpi_register_hw_handler( u16 hw_type,
     239                                            cobalt_acpi_hw_handler hw_handler,
     240                                            cobalt_acpi_enable_handler en_handler,
     241                                            void *data )
     242{
     243    hw_handler_datum *d;
     244    unsigned long flags;
     245
     246    if( ! (d = (hw_handler_datum *) kmalloc( sizeof( hw_handler_datum ), GFP_ATOMIC )) )
     247        return -ENOMEM;
     248
     249    d->hw_type = hw_type;
     250    d->hw_handler = hw_handler;
     251    d->en_handler = en_handler;
     252    d->data = data;
     253
     254    spin_lock_irqsave( &hw_handler_list_lock, flags );
     255    list_add( &(d->link), &hw_handler_list );
     256    spin_unlock_irqrestore( &hw_handler_list_lock, flags );
     257
     258    return 0;
     259}
     260
     261extern int cobalt_acpi_unregister_hw_handler( cobalt_acpi_hw_handler handler )
     262{
     263    struct list_head *pos;
     264    unsigned long flags;
     265   
     266    spin_lock_irqsave( &hw_handler_list_lock, flags );
     267    list_for_each( pos, &hw_handler_list )
     268        {
     269            if( list_entry( pos, hw_handler_datum, link )->hw_handler == handler )
     270            {
     271                list_del( pos );
     272                spin_unlock_irqrestore( &hw_handler_list_lock, flags );
     273
     274                kfree( list_entry( pos, hw_handler_datum, link ) );
     275                return 0;
     276            }
     277               
     278        };
     279   
     280    spin_unlock_irqrestore( &hw_handler_list_lock, flags );
     281    return -1;
     282}
     283
     284extern int cobalt_acpi_register_trans_table( u16 hw_type, u16 table_len, u16 *table )
     285{
     286    trans_table_datum *d;
     287    unsigned long flags;
     288   
     289    if( ! (d = (trans_table_datum *) kmalloc( sizeof( trans_table_datum ), GFP_ATOMIC )) )
     290        return -ENOMEM;
     291
     292    d->hw_type = hw_type;
     293    d->table_len = table_len;
     294    d->table = table;
     295
     296    spin_lock_irqsave( &trans_table_list_lock, flags );
     297    list_add( &(d->link), &trans_table_list );
     298    spin_unlock_irqrestore( &trans_table_list_lock, flags );
     299
     300    return 0;
     301}
     302
     303extern int cobalt_acpi_unregister_trans_table( u16 hw_type )
     304{
     305    struct list_head *pos;
     306    unsigned long flags;
     307   
     308    spin_lock_irqsave( &trans_table_list_lock, flags );
     309    list_for_each( pos, &trans_table_list )
     310        {
     311            if( list_entry( pos, trans_table_datum, link )->hw_type == hw_type )
     312            {
     313                list_del( pos );
     314                spin_unlock_irqrestore( &trans_table_list_lock, flags );
     315               
     316                kfree( list_entry( pos, trans_table_datum, link ) );
     317                return 0;
     318            }
     319               
     320        };
     321   
     322    spin_unlock_irqrestore( &trans_table_list_lock, flags );
     323    return -1;
     324}
     325
     326extern int cobalt_acpi_register_evt_handler( cobalt_acpi_evt_handler handler,
     327                                             u16 ev_type,
     328                                             void *data )
     329{
     330    evt_handler_datum *d;
     331    unsigned long flags;
     332   
     333    if( ! (d = (evt_handler_datum *) kmalloc( sizeof( evt_handler_datum ), GFP_ATOMIC )) )
     334        return -ENOMEM;
     335
     336    d->handler = handler;
     337    d->data = data;
     338    d->ev_type = ev_type;
     339
     340    spin_lock_irqsave( &evt_handler_list_lock, flags );
     341    list_add( &(d->link), &evt_handler_list );
     342    spin_unlock_irqrestore( &evt_handler_list_lock, flags );
     343
     344    cobalt_acpi_enable_event( ev_type, 1 );
     345
     346    return 0;
     347}
     348
     349extern int cobalt_acpi_unregister_evt_handler( cobalt_acpi_evt_handler handler )
     350{
     351    struct list_head *pos;
     352    unsigned long flags;
     353   
     354
     355    spin_lock_irqsave( &evt_handler_list_lock, flags );
     356    list_for_each( pos, &evt_handler_list )
     357        {
     358            if( list_entry( pos, evt_handler_datum, link )->handler == handler )
     359            {
     360                list_del( pos );
     361                spin_unlock_irqrestore( &evt_handler_list_lock, flags );
     362               
     363                cobalt_acpi_enable_event( list_entry( pos,
     364                                                      evt_handler_datum,
     365                                                      link )->ev_type, 0 );
     366
     367                kfree( list_entry( pos, evt_handler_datum, link ) );
     368                return 0;
     369            }
     370               
     371        };
     372   
     373    spin_unlock_irqrestore( &evt_handler_list_lock, flags );
     374    return -EINVAL;
     375}
     376
     377static void cobalt_acpi_enable_event( u16 ev_type, int en )
     378{
     379    if( ev_type >= 0x8000 )
     380    {
     381        struct list_head *pos;
     382        trans_table_datum *d;
     383        int i;
     384        unsigned long flags;
     385
     386        spin_lock_irqsave( &trans_table_list_lock, flags );
     387        list_for_each( pos, &trans_table_list )
     388            {
     389                d = list_entry( pos, trans_table_datum, link );
     390                for( i=0 ; i<d->table_len ; i++ )
     391                {
     392                    if( d->table[i] == ev_type )
     393                    {
     394                        cobalt_acpi_run_enable_handler( d->hw_type,
     395                                                        COBALT_ACPI_EVT_GPE,
     396                                                        i, en );
     397                    }
     398                }
     399            }
     400        spin_unlock_irqrestore( &trans_table_list_lock, flags );
     401    }
     402    else
     403        cobalt_acpi_run_enable_handler( COBALT_ACPI_HW_ANY, ev_type, 0, en);
     404}
     405
     406static void cobalt_acpi_run_enable_handler( u16 hw_type, u16 ev_type,
     407                                            u16 ev_data, int en)
     408{   
     409    struct list_head *pos;
     410    unsigned long flags;
     411    hw_handler_datum *d;
     412
     413    spin_lock_irqsave(&hw_handler_list_lock, flags);
     414    list_for_each( pos, &hw_handler_list )
     415        {
     416            d = list_entry( pos, hw_handler_datum, link );
     417            if( (!hw_type) || (d->hw_type == hw_type) )
     418                d->en_handler( ev_type, ev_data, en, d->data );
     419        }
     420    spin_unlock_irqrestore(&hw_handler_list_lock, flags);
     421   
     422}
     423
     424static int cobalt_acpi_translate_event( cobalt_acpi_evt *evt )
     425{
     426    struct list_head *pos;
     427    unsigned long flags;
     428    trans_table_datum *d;
     429
     430    if( evt->ev_type != COBALT_ACPI_EVT_GPE )
     431        return 0;
     432
     433    spin_lock_irqsave( &trans_table_list_lock, flags );
     434    list_for_each( pos, &trans_table_list )
     435        {
     436            d = list_entry( pos, trans_table_datum, link );
     437            if( d->hw_type == evt->hw_type )
     438            {
     439                if( evt->ev_data >= d->table_len )
     440                    goto err_out;
     441
     442                if( d->table[ evt->ev_data ] != COBALT_ACPI_EVT_NONE )
     443                {
     444                    evt->ev_type = d->table[ evt->ev_data ];
     445                    evt->ev_data = 0;
     446                }
     447               
     448                spin_unlock_irqrestore( &trans_table_list_lock, flags );
     449                return 0;
     450            }
     451        }
     452
     453  err_out:
     454    spin_unlock_irqrestore( &trans_table_list_lock, flags );
     455    return -1;
     456}
     457
     458extern int cobalt_acpi_post_event( cobalt_acpi_evt evt )
     459{
     460    evt_list_datum *d;
     461    unsigned long flags;
     462   
     463    if( ! (d = (evt_list_datum *) kmalloc( sizeof( evt_handler_datum ), GFP_ATOMIC )) )
     464        return -ENOMEM;
     465   
     466
     467    cobalt_acpi_translate_event( &evt );
     468
     469    memcpy( &(d->evt), &evt, sizeof(evt) );
     470
     471    spin_lock_irqsave( &dispatch_queue_lock, flags );
     472    list_add_tail( &(d->link), &dispatch_queue );
     473    spin_unlock_irqrestore( &dispatch_queue_lock, flags );
     474
     475    return 0;
     476}
     477
     478static int cobalt_acpi_apply_evt_handlers( evt_list_datum *d )
     479{
     480    struct list_head *pos;
     481    evt_handler_datum *evt_h;
     482    int ret,err = 0;
     483    unsigned long flags;
     484   
     485    spin_lock_irqsave( &evt_handler_list_lock, flags );
     486    list_for_each( pos, &evt_handler_list )
     487        {
     488            evt_h = list_entry( pos, evt_handler_datum, link );
     489            if( (! evt_h->ev_type) || (evt_h->ev_type == d->evt.ev_type) )
     490            {
     491                if( (ret = evt_h->handler( &d->evt, evt_h->data )) < 0 )
     492                    err = ret;
     493            }
     494        }
     495    spin_unlock_irqrestore( &evt_handler_list_lock, flags );
     496
     497    return err;
     498}
     499
     500static int cobalt_acpi_run_dispatch_queue( void )
     501{
     502    struct list_head *pos;
     503    int ret;
     504    int err=0;
     505    evt_list_datum *d;
     506    unsigned long flags;
     507
     508    spin_lock_irqsave( &dispatch_queue_lock, flags );
     509    while( (pos = list_pop( &dispatch_queue )) )
     510    {
     511        d = list_entry( pos, evt_list_datum, link );
     512        if( (ret = cobalt_acpi_apply_evt_handlers( d )) < 0 )
     513            err = ret;
     514#ifdef CONFIG_COBALT_EMU_ACPI
     515        cobalt_acpi_generate_proc_evt( &d->evt );
     516#endif
     517        kfree( d );
     518    }
     519    spin_unlock_irqrestore( &dispatch_queue_lock, flags );
     520
     521    return err;
     522}
     523
     524static irqreturn_t acpi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
     525{
     526    struct list_head *pos;
     527    hw_handler_datum *d;
     528    int ret=0, err=0;
     529    unsigned long flags;
     530
     531    spin_lock_irqsave(&hw_handler_list_lock, flags);
     532    list_for_each( pos, &hw_handler_list )
     533        {
     534            d = list_entry( pos, hw_handler_datum, link );
     535            if( (ret = d->hw_handler( irq, dev_id, regs, d->data )) < 0 )
     536                err = ret;
     537           
     538        }
     539    spin_unlock_irqrestore(&hw_handler_list_lock, flags);
     540
     541    if( (err = cobalt_acpi_run_dispatch_queue()) < 0 )
     542        err = ret;
     543
     544    if( err )
     545        EPRINTK( "error at interrupt time of type %d.\n", err );
     546
     547    return IRQ_HANDLED;
     548}
     549
     550
     551
     552
     553int __init cobalt_acpi_init(void)
     554{
     555    int err;
     556
     557    printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", ACPI_DRIVER,ACPI_DRIVER_VMAJ,ACPI_DRIVER_VMIN);
     558   
     559    if( cobt_is_monterey() )
     560        cobalt_acpi_monterey_init();
     561    else if( cobt_is_alpine() )
     562        cobalt_acpi_alpine_init();
     563
     564    if( cobt_is_5k() )
     565    {
     566        if( pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
     567                            PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL ) )
     568        {
     569            if( (err = cobalt_acpi_osb4_init()) < 0 )
     570            {
     571                goto cleanup;
     572            }
     573        }
     574       
     575        if( pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
     576                            PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL ) )
     577        {
     578            if( (err = cobalt_acpi_csb5_init()) < 0 )
     579            {
     580                goto cleanup;
     581            }
     582        }
     583
     584        switch( superio_type() )
     585        {
     586            case SIO_TYPE_PC8731X:
     587                if( (err = cobalt_acpi_pc8731x_init()) )
     588                {
     589                    goto cleanup;
     590                }
     591                break;
     592
     593            case SIO_TYPE_PC8741X:
     594                if( (err = cobalt_acpi_pc8741x_init()) )
     595                {
     596                    goto cleanup;
     597                }
     598                break;
     599
     600            case SIO_TYPE_UNKNOWN:
     601                EPRINTK("unknown superio type\n");
     602                break;
     603        }
     604       
     605            /* setup an interrupt handler for an ACPI SCI */
     606        err = request_irq(ACPI_IRQ, acpi_interrupt,
     607                          SA_SHIRQ, ACPI_NAME, (void *)ACPI_MAGIC);
     608        if (err) {
     609            EPRINTK("can't assign ACPI IRQ (%d)\n", ACPI_IRQ);
     610            return err;
     611        }
     612
     613#ifdef CONFIG_COBALT_EMU_ACPI
     614        cobalt_acpi_setup_proc();
     615#endif
     616    }
     617
     618        /* enable some events we may want */
     619    cobalt_acpi_enable_event( COBALT_ACPI_EVT_PWRBTN, 1 );
     620
     621    return 0;
     622   
     623  cleanup:
     624    cobalt_acpi_cleanup();
     625    return err;
     626}
     627
     628static void cobalt_acpi_cleanup( void )
     629{
     630    cobalt_acpi_osb4_cleanup();
     631    cobalt_acpi_csb5_cleanup();
     632    cobalt_acpi_pc8731x_cleanup();
     633    cobalt_acpi_pc8741x_cleanup();
     634
     635    if( cobt_is_monterey() )
     636        cobalt_acpi_monterey_cleanup();
     637    if( cobt_is_alpine() )
     638        cobalt_acpi_alpine_cleanup();
     639}
     640
     641/*
     642 *
     643 * Generic ACPI HW Support
     644 *
     645 */
     646
     647static __inline__ char *region_name( char * subsys_name, char * blk_name )
     648{
     649    char * new_name;
     650   
     651    if( !( new_name = (char *) kmalloc( strlen(subsys_name) + strlen(blk_name) + 14,
     652                                        GFP_ATOMIC)) )
     653        return NULL;
     654
     655    sprintf( new_name, "%s (%s)", subsys_name, blk_name );
     656    return new_name;
     657}
     658
     659static void free_region_names( generic_acpi_regions *regions )
     660{
     661    if( regions->pm1a_evt_nam )
     662        kfree( regions->pm1a_evt_nam );
     663
     664    if( regions->pm1b_evt_nam )
     665        kfree( regions->pm1b_evt_nam );
     666
     667    if( regions->pm1a_cnt_nam )
     668        kfree( regions->pm1a_cnt_nam );
     669
     670    if( regions->pm1b_cnt_nam )
     671        kfree( regions->pm1b_cnt_nam );
     672
     673    if( regions->pm2_cnt_nam )
     674        kfree( regions->pm2_cnt_nam );
     675
     676    if( regions->pm_tmr_nam )
     677        kfree( regions->pm_tmr_nam );
     678
     679    if( regions->p_nam )
     680        kfree( regions->p_nam );
     681
     682    if( regions->gpe0_nam )
     683        kfree( regions->gpe0_nam );
     684
     685    if( regions->gpe1_nam )
     686        kfree( regions->gpe1_nam );
     687}
     688
     689static int register_acpi_regions( generic_acpi_regions *regions,  char * subsys_name )
     690{
     691    int i;
     692   
     693    if( regions->pm1a_evt_blk && regions->pm1_evt_len )
     694    {
     695        if( !(regions->pm1a_evt_nam = region_name( subsys_name, "pm1a_evt_blk" )) )
     696            goto cleanup0;
     697
     698        if( !request_region( regions->pm1a_evt_blk, regions->pm1_evt_len,
     699                             regions->pm1a_evt_nam ) )
     700            goto cleanup0;
     701    }
     702
     703    if( regions->pm1b_evt_blk && regions->pm1_evt_len )
     704    {
     705        if( !(regions->pm1b_evt_nam = region_name( subsys_name, "pm1b_evt_blk" )) )
     706            goto cleanup0;
     707
     708        if( !request_region( regions->pm1b_evt_blk, regions->pm1_evt_len,
     709                             regions->pm1b_evt_nam) )
     710            goto cleanup1;
     711    }
     712
     713    if( regions->pm1a_cnt_blk && regions->pm1_cnt_len )
     714    {
     715        if( !(regions->pm1a_cnt_nam = region_name( subsys_name, "pm1a_cnt_blk" )) )
     716            goto cleanup1;
     717
     718        if( !request_region( regions->pm1a_cnt_blk, regions->pm1_cnt_len,
     719                             regions->pm1a_cnt_nam ) )
     720            goto cleanup2;
     721    }
     722
     723    if( regions->pm1b_cnt_blk && regions->pm1_cnt_len )
     724    {
     725        if( !(regions->pm1b_cnt_nam = region_name( subsys_name, "pm1b_cnt_blk" )) )
     726            goto cleanup2;
     727
     728        if( !request_region( regions->pm1b_cnt_blk, regions->pm1_cnt_len,
     729                             regions->pm1b_cnt_nam ) )
     730            goto cleanup3;
     731    }
     732
     733    if( regions->pm2_cnt_blk && regions->pm2_cnt_len )
     734    {
     735        if( !(regions->pm2_cnt_nam = region_name( subsys_name, "pm2_cnt_blk" )) )
     736            goto cleanup3;
     737
     738        if( !request_region( regions->pm2_cnt_blk, regions->pm2_cnt_len,
     739                             regions->pm2_cnt_nam ) )
     740            goto cleanup4;
     741    }
     742
     743    if( regions->pm_tmr_blk && regions->pm_tmr_len )
     744    {
     745        if( !(regions->pm_tmr_nam = region_name( subsys_name, "pm_tmp_blk" )) )
     746            goto cleanup4;
     747
     748        if( !request_region( regions->pm_tmr_blk, regions->pm_tmr_len,
     749                             regions->pm_tmr_nam ) )
     750            goto cleanup5;
     751    }
     752
     753    if( regions->p_blk )
     754    {
     755        if( !(regions->p_nam = region_name( subsys_name, "p_blk" )) )
     756            goto cleanup5;
     757
     758        if( !request_region( regions->p_blk, 6, regions->p_nam ) )
     759            goto cleanup6;
     760    }
     761
     762    if( regions->gpe0_blk && regions->gpe0_len )
     763    {
     764        if( !(regions->gpe0_nam = region_name( subsys_name, "gpe0_blk" )) )
     765            goto cleanup6;
     766
     767        if( !request_region( regions->gpe0_blk, regions->gpe0_len,
     768                             regions->gpe0_nam ) )
     769            goto cleanup7;
     770    }
     771
     772    if( regions->gpe1_blk && regions->gpe1_len )
     773    {
     774        if( !(regions->gpe1_nam = region_name( subsys_name, "gpe1_blk" )) )
     775            goto cleanup7;
     776
     777        if( !request_region( regions->gpe1_blk, regions->gpe1_len,
     778                             regions->gpe1_nam ) )
     779            goto cleanup8;
     780    }
     781
     782    if( (regions->gpe_ref_cnt = (atomic_t *) kmalloc( sizeof( atomic_t ) *
     783                                                      regions->gpe0_len * 8,
     784                                                      GFP_ATOMIC)) == NULL )
     785        goto cleanup9;
     786
     787    memset( regions->gpe_ref_cnt, 0x0, sizeof( atomic_t ) * regions->gpe0_len * 8 );
     788
     789        /* disable all events and ack them */
     790    if( regions->pm1a_evt_blk )
     791    {
     792        outw( 0x0000, regions->pm1a_evt_blk + regions->pm1_evt_len/2 );
     793        outw( 0xffff, regions->pm1a_evt_blk );
     794    }
     795
     796    if( regions->pm1b_evt_blk )
     797    {
     798        outw( 0x0000, regions->pm1b_evt_blk + regions->pm1_evt_len/2 );
     799        outw( 0xffff, regions->pm1b_evt_blk );
     800    }
     801
     802    if( regions->gpe0_blk )
     803    {
     804        for( i=0 ; i<(regions->gpe0_len/2) ; i++ )
     805        {
     806            outb( 0x00, regions->gpe0_blk + regions->gpe0_len/2 + i );
     807            outb( 0xff, regions->gpe0_blk + i );
     808        }
     809    }
     810
     811    if( regions->gpe1_blk )
     812    {
     813        for( i=0 ; i<(regions->gpe1_len/2) ; i++ )
     814        {
     815            outb( 0x00, regions->gpe1_blk + regions->gpe1_len/2 + i );
     816            outb( 0xff, regions->gpe1_blk + i );
     817        }
     818    }
     819
     820    return 0;
     821       
     822  cleanup9:
     823    if( regions->gpe1_blk )
     824    {
     825        release_region( regions->gpe1_blk, regions->gpe1_len );
     826        regions->gpe1_blk = 0;
     827    }
     828
     829  cleanup8:
     830    if( regions->gpe0_blk )
     831    {
     832        release_region( regions->gpe0_blk, regions->gpe0_len );
     833        regions->gpe0_blk = 0;
     834    }
     835
     836  cleanup7:
     837    if( regions->p_blk )
     838    {
     839        release_region( regions->p_blk, 6 );
     840        regions->p_blk = 0;
     841    }
     842
     843  cleanup6:
     844    if( regions->pm_tmr_blk )
     845    {
     846        release_region( regions->pm_tmr_blk, regions->pm_tmr_len );
     847        regions->pm_tmr_blk = 0;
     848    }
     849
     850  cleanup5:
     851    if( regions->pm2_cnt_blk )
     852    {
     853        release_region( regions->pm2_cnt_blk, regions->pm2_cnt_len );
     854        regions->pm2_cnt_blk = 0;
     855    }
     856
     857  cleanup4:
     858    if( regions->pm1b_cnt_blk )
     859    {
     860        release_region( regions->pm1b_cnt_blk, regions->pm1_cnt_len );
     861        regions->pm1b_cnt_blk = 0;
     862    }
     863
     864  cleanup3:
     865    if( regions->pm1a_cnt_blk )
     866    {
     867        release_region( regions->pm1a_cnt_blk, regions->pm1_cnt_len );
     868        regions->pm1a_cnt_blk = 0;
     869    }
     870
     871  cleanup2:
     872    if( regions->pm1b_evt_blk )
     873    {
     874        release_region( regions->pm1b_evt_blk, regions->pm1_evt_len );
     875        regions->pm1b_evt_blk = 0;
     876    }
     877
     878  cleanup1:
     879    if( regions->pm1a_evt_blk )
     880    {
     881        release_region( regions->pm1a_evt_blk, regions->pm1_evt_len );
     882        regions->pm1a_evt_blk = 0;
     883    }
     884
     885  cleanup0:
     886    free_region_names( regions );
     887   
     888    return -EBUSY;
     889}
     890
     891static int unregister_acpi_regions( generic_acpi_regions *regions )
     892{
     893    if( regions->pm1a_evt_blk && regions->pm1_evt_len )
     894    {
     895        release_region( regions->pm1a_evt_blk, regions->pm1_evt_len );
     896        regions->pm1a_evt_blk = 0;
     897    }
     898   
     899    if( regions->pm1b_evt_blk && regions->pm1_evt_len )
     900    {
     901        release_region( regions->pm1b_evt_blk, regions->pm1_evt_len );
     902        regions->pm1b_evt_blk = 0;
     903    }
     904
     905    if( regions->pm1a_cnt_blk && regions->pm1_cnt_len )
     906    {
     907        release_region( regions->pm1a_cnt_blk, regions->pm1_cnt_len );
     908        regions->pm1a_cnt_blk = 0;
     909    }
     910
     911    if( regions->pm1b_cnt_blk && regions->pm1_cnt_len )
     912    {
     913        release_region( regions->pm1b_cnt_blk, regions->pm1_cnt_len );
     914        regions->pm1b_cnt_blk = 0;
     915    }
     916
     917    if( regions->pm2_cnt_blk && regions->pm2_cnt_len )
     918    {
     919        release_region( regions->pm2_cnt_blk, regions->pm2_cnt_len );
     920        regions->pm2_cnt_blk = 0;
     921    }
     922
     923    if( regions->pm_tmr_blk && regions->pm_tmr_len )
     924    {
     925        release_region( regions->pm_tmr_blk, regions->pm_tmr_len );
     926        regions->pm_tmr_blk = 0;
     927    }
     928
     929    if( regions->p_blk )
     930    {
     931        release_region( regions->p_blk, 6 );
     932        regions->p_blk = 0;
     933    }
     934
     935    if( regions->gpe0_blk && regions->gpe0_len )
     936    {
     937        release_region( regions->gpe0_blk, regions->gpe0_len );
     938        regions->gpe0_blk = 0;
     939    }
     940
     941    if( regions->gpe1_blk && regions->gpe1_len )
     942    {
     943        release_region( regions->gpe1_blk, regions->gpe1_len );
     944        regions->gpe1_blk = 0;
     945    }
     946
     947    if( regions->gpe_ref_cnt )
     948        kfree( regions->gpe_ref_cnt );
     949   
     950    free_region_names( regions );
     951
     952    return 0;
     953}
     954
     955static void cobalt_acpi_handle_pm1_blk( u16 io_addr, u16 len,
     956                                       generic_acpi_regions * regions )
     957{
     958    cobalt_acpi_evt evt;
     959    u16 sts, en;
     960   
     961    evt.hw_type = regions->hw_type;
     962   
     963    if( (sts = inw( io_addr )) &&
     964        (en  = inw( io_addr + len/2 )) )
     965    {
     966
     967
     968            /* clear status bits */
     969        outw( sts, io_addr);
     970
     971        if( (en  & GEN_ACPI_TMR_STS) &&
     972            (sts & GEN_ACPI_TMR_STS) )
     973        {
     974            evt.ev_type = COBALT_ACPI_EVT_TMR;
     975            evt.ev_data = 0x0;
     976            cobalt_acpi_post_event( evt );
     977        }
     978        if( (en & GEN_ACPI_BM_STS) &&
     979            (sts & GEN_ACPI_BM_STS) )
     980        {
     981            evt.ev_type = COBALT_ACPI_EVT_BM;
     982            evt.ev_data = 0x0;
     983            cobalt_acpi_post_event( evt );
     984        }
     985        if( (en  & GEN_ACPI_GBL_STS) &&
     986            (sts & GEN_ACPI_GBL_STS) )
     987        {
     988            evt.ev_type = COBALT_ACPI_EVT_GBL;
     989            evt.ev_data = 0x0;
     990            cobalt_acpi_post_event( evt );
     991        }
     992        if( (en  & GEN_ACPI_PWRBTN_STS) &&
     993            (sts & GEN_ACPI_PWRBTN_STS) )
     994        {
     995            evt.ev_type = COBALT_ACPI_EVT_PWRBTN;
     996            evt.ev_data = 0x0;
     997            cobalt_acpi_post_event( evt );
     998        }
     999        if( (en  & GEN_ACPI_SLPBTN_STS) &&
     1000            (sts & GEN_ACPI_SLPBTN_STS) )
     1001        {
     1002            evt.ev_type = COBALT_ACPI_EVT_SLPBTN;
     1003            evt.ev_data = 0x0;
     1004            cobalt_acpi_post_event( evt );
     1005        }
     1006        if( (en & GEN_ACPI_RTC_STS) &&
     1007            (sts & GEN_ACPI_RTC_STS) )
     1008        {
     1009            evt.ev_type = COBALT_ACPI_EVT_RTC;
     1010            evt.ev_data = 0x0;
     1011            cobalt_acpi_post_event( evt );
     1012        }
     1013        if( (sts & GEN_ACPI_WAK_STS) )
     1014        {
     1015            evt.ev_type = COBALT_ACPI_EVT_WAK;
     1016            evt.ev_data = 0x0;
     1017            cobalt_acpi_post_event( evt );
     1018        }
     1019    }
     1020}
     1021
     1022static void cobalt_acpi_handle_gpe_blk( u16 io_addr, u16 len,
     1023                                        generic_acpi_regions * regions )
     1024{
     1025    cobalt_acpi_evt evt;
     1026    int i,j;
     1027    u8 sts, en;
     1028   
     1029    evt.hw_type = regions->hw_type;
     1030    evt.ev_type = COBALT_ACPI_EVT_GPE;
     1031
     1032    for( i=0 ; i<(len/2) ; i++ )
     1033    {
     1034        sts = inb( io_addr + i );
     1035        en =  inb( io_addr + len/2 + i );
     1036
     1037            /* clear status bits */
     1038        outb( sts, io_addr);
     1039
     1040        for( j=0 ; j<8 ; j++ )
     1041        {
     1042            if( (en  & 0x1) &&
     1043                (sts & 0x1) )
     1044            {
     1045                evt.ev_data = i*8 + j;
     1046                cobalt_acpi_post_event( evt );
     1047            }
     1048            en >>= 1;
     1049            sts >>= 1;
     1050        }
     1051    }
     1052}
     1053
     1054static int cobalt_acpi_generic_hw_handler( int irq, void *dev_id,
     1055                                           struct pt_regs *regs, void * data )
     1056{
     1057    generic_acpi_regions * regions = (generic_acpi_regions *) data;
     1058    cobalt_acpi_evt evt;
     1059
     1060    evt.hw_type = regions->hw_type;
     1061
     1062        /* various PM events */
     1063    if( regions->pm1a_evt_blk )
     1064        cobalt_acpi_handle_pm1_blk( regions->pm1a_evt_blk, regions->pm1_evt_len, regions );
     1065
     1066    if( regions->pm1b_evt_blk )
     1067        cobalt_acpi_handle_pm1_blk( regions->pm1b_evt_blk, regions->pm1_evt_len, regions );
     1068
     1069    if( regions->gpe0_blk )
     1070        cobalt_acpi_handle_gpe_blk( regions->gpe0_blk, regions->gpe0_len, regions );
     1071
     1072    if( regions->gpe1_blk )
     1073        cobalt_acpi_handle_gpe_blk( regions->gpe1_blk, regions->gpe1_len, regions );
     1074       
     1075
     1076    return 0;
     1077}
     1078
     1079static int cobalt_acpi_generic_en_handler( u16 ev_type, u16 ev_data, int en, void *data )
     1080{
     1081    generic_acpi_regions * regions = (generic_acpi_regions *) data;
     1082    int block, offset;
     1083    u8 data8;
     1084    u16 data16;
     1085   
     1086    switch( ev_type )
     1087    {
     1088        case COBALT_ACPI_EVT_TMR:
     1089            data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
     1090           
     1091            if( en )
     1092            {
     1093                data16 |= GEN_ACPI_TMR_STS;
     1094                atomic_inc( &regions->tmr_ref_cnt );
     1095            }
     1096            else
     1097            {
     1098                if( atomic_dec_and_test( &regions->tmr_ref_cnt ) )
     1099                    data16 &= ~GEN_ACPI_TMR_STS;
     1100            }
     1101            outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
     1102            break;
     1103           
     1104        case COBALT_ACPI_EVT_BM:
     1105            data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
     1106           
     1107            if( en )
     1108            {
     1109                data16 |= GEN_ACPI_BM_STS;
     1110                atomic_inc( &regions->bm_ref_cnt );
     1111            }
     1112            else
     1113            {
     1114                if( atomic_dec_and_test( &regions->bm_ref_cnt ) )
     1115                    data16 &= ~GEN_ACPI_BM_STS;
     1116            }
     1117            outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
     1118            break;
     1119           
     1120        case COBALT_ACPI_EVT_GBL:
     1121            data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
     1122           
     1123            if( en )
     1124            {
     1125                data16 |= GEN_ACPI_GBL_STS;
     1126                atomic_inc( &regions->gbl_ref_cnt );
     1127            }
     1128            else
     1129            {
     1130                if( atomic_dec_and_test( &regions->gbl_ref_cnt ) )
     1131                    data16 &= ~GEN_ACPI_GBL_STS;
     1132            }
     1133            outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
     1134            break;
     1135           
     1136        case COBALT_ACPI_EVT_PWRBTN:
     1137            data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
     1138           
     1139            if( en )
     1140            {
     1141                data16 |= GEN_ACPI_PWRBTN_STS;
     1142                atomic_inc( &regions->pwrbtn_ref_cnt );
     1143            }
     1144            else
     1145            {
     1146                if( atomic_dec_and_test( &regions->pwrbtn_ref_cnt ) )
     1147                    data16 &= ~GEN_ACPI_PWRBTN_STS;
     1148            }
     1149            outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
     1150            break;
     1151           
     1152        case COBALT_ACPI_EVT_SLPBTN:
     1153            data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
     1154           
     1155            if( en )
     1156            {
     1157                data16 |= GEN_ACPI_SLPBTN_STS;
     1158                atomic_inc( &regions->slpbtn_ref_cnt );
     1159            }
     1160            else
     1161            {
     1162                if( atomic_dec_and_test( &regions->slpbtn_ref_cnt ) )
     1163                    data16 &= ~GEN_ACPI_SLPBTN_STS;
     1164            }
     1165            outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
     1166            break;
     1167           
     1168        case COBALT_ACPI_EVT_RTC:
     1169            data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
     1170           
     1171            if( en )
     1172            {
     1173                data16 |= GEN_ACPI_RTC_STS;
     1174                atomic_inc( &regions->rtc_ref_cnt );
     1175            }
     1176            else
     1177            {
     1178                if( atomic_dec_and_test( &regions->rtc_ref_cnt ) )
     1179                    data16 &= ~GEN_ACPI_RTC_STS;
     1180            }
     1181            outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
     1182            break;
     1183           
     1184        case COBALT_ACPI_EVT_WAK:
     1185            data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
     1186           
     1187            if( en )
     1188            {
     1189                data16 |= GEN_ACPI_WAK_STS;
     1190                atomic_inc( &regions->wak_ref_cnt );
     1191            }
     1192            else
     1193            {
     1194                if( atomic_dec_and_test( &regions->wak_ref_cnt ) )
     1195                    data16 &= ~GEN_ACPI_WAK_STS;
     1196            }
     1197            outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
     1198            break;
     1199           
     1200        case COBALT_ACPI_EVT_GPE:
     1201            if( (ev_data/8) >= (regions->gpe0_len / 2) )
     1202                return -EINVAL;
     1203           
     1204            block = ev_data / 8;
     1205            offset = ev_data % 8;
     1206           
     1207            data8 = inb( regions->gpe0_blk + (regions->gpe0_len / 2) + block );
     1208           
     1209            if( en )
     1210            {
     1211                data8 |= 0x1 << offset;
     1212                atomic_inc( &regions->gpe_ref_cnt[ev_data] );
     1213            }
     1214            else
     1215            {
     1216                if( atomic_dec_and_test( &regions->gpe_ref_cnt[ev_data] ) )
     1217                    data8 &= ~( 0x1 << offset );
     1218            }
     1219           
     1220            outb( data8, regions->gpe0_blk + (regions->gpe0_len / 2) + block );
     1221           
     1222            break;
     1223           
     1224        default:
     1225            return -EINVAL;
     1226                   
     1227    }
     1228
     1229    return 0;
     1230}
     1231
     1232/*
     1233 *
     1234 * Generic ServerWorks region code
     1235 *
     1236 */
     1237
     1238static int get_serverworks_regions( generic_acpi_regions *regions, u16 type )
     1239{
     1240   int reg;
     1241   
     1242    memset( regions, 0x0, sizeof( *regions ) );
     1243   
     1244    regions->hw_type = type;
     1245
     1246    regions->pm1_evt_len = 4;
     1247    regions->pm1_cnt_len = 2;
     1248    regions->pm_tmr_len = 4;
     1249    regions->gpe0_len = 8;
     1250
     1251    if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x20)) )
     1252        regions->pm1a_evt_blk = (u16) reg;
     1253   
     1254    if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x22)) )
     1255        regions->pm1a_cnt_blk = (u16) reg;
     1256   
     1257    if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x24)) )
     1258        regions->pm_tmr_blk = (u16) reg;
     1259   
     1260    if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x26)) )
     1261        regions->p_blk = (u16) reg;
     1262   
     1263    if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x28)) )
     1264        regions->gpe0_blk = (u16) reg;
     1265
     1266    if( type == COBALT_ACPI_HW_OSB4 )
     1267    {
     1268        regions->pm2_cnt_len = 1;
     1269        if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x2E)) )
     1270            regions->pm2_cnt_blk = (u16) reg;
     1271    }
     1272
     1273    switch( type )
     1274    {
     1275        case COBALT_ACPI_HW_OSB4:
     1276            return register_acpi_regions( regions, "OSB4" );
     1277
     1278        case COBALT_ACPI_HW_CSB5:
     1279            return register_acpi_regions( regions, "CSB5" );
     1280    }
     1281   
     1282    return -EINVAL;
     1283
     1284}
     1285
     1286/*
     1287 *
     1288 * ServerWorks OSB4
     1289 *
     1290 */
     1291
     1292static generic_acpi_regions osb4_regions;
     1293
     1294static int cobalt_acpi_osb4_init( void )
     1295{
     1296    int err;
     1297   
     1298    if( (err = get_osb4_regions( &osb4_regions )) < 0 )
     1299        return err;
     1300
     1301    if( (err = cobalt_acpi_register_hw_handler( COBALT_ACPI_HW_OSB4,
     1302                                                cobalt_acpi_generic_hw_handler,
     1303                                                cobalt_acpi_generic_en_handler,
     1304                                                &osb4_regions )) < 0 )
     1305        return err;
     1306
     1307    return 0;
     1308}
     1309
     1310static int cobalt_acpi_osb4_cleanup( void )
     1311{
     1312    unregister_acpi_regions( &osb4_regions );
     1313    return 0;
     1314}
     1315
     1316static int get_osb4_regions( generic_acpi_regions *regions)
     1317{
     1318    return get_serverworks_regions( regions, COBALT_ACPI_HW_OSB4 );
     1319}
     1320
     1321/*
     1322 *
     1323 * ServerWorks CSB5
     1324 *
     1325 */
     1326
     1327/* static generic_acpi_regions csb5_regions; */
     1328
     1329static generic_acpi_regions csb5_regions;
     1330
     1331static int cobalt_acpi_csb5_init( void )
     1332{
     1333    int err;
     1334   
     1335    if( (err = get_csb5_regions( &csb5_regions )) < 0 )
     1336        return err;
     1337
     1338    if( (err = cobalt_acpi_register_hw_handler( COBALT_ACPI_HW_CSB5,
     1339                                                cobalt_acpi_generic_hw_handler,
     1340                                                cobalt_acpi_generic_en_handler,
     1341                                                &csb5_regions )) < 0 )
     1342        return err;
     1343
     1344    return 0;
     1345}
     1346
     1347static int cobalt_acpi_csb5_cleanup( void )
     1348{
     1349    unregister_acpi_regions( &csb5_regions );
     1350    return 0;
     1351}
     1352
     1353static int get_csb5_regions( generic_acpi_regions *regions)
     1354{
     1355    return get_serverworks_regions( regions, COBALT_ACPI_HW_CSB5 );
     1356}
     1357
     1358/*
     1359 *
     1360 * NatSemi PC8731x
     1361 *
     1362 */
     1363static generic_acpi_regions pc8731x_regions;
     1364
     1365static int cobalt_acpi_pc8731x_init( void )
     1366{
     1367    int err;
     1368   
     1369    if( (err = get_pc8731x_regions( &pc8731x_regions )) < 0 )
     1370        return err;
     1371
     1372    if( (err = cobalt_acpi_register_hw_handler( COBALT_ACPI_HW_PC8731X,
     1373                                                cobalt_acpi_generic_hw_handler,
     1374                                                cobalt_acpi_generic_en_handler,
     1375                                                &pc8731x_regions )) < 0 )
     1376        return err;
     1377
     1378    return 0;
     1379}
     1380
     1381static int cobalt_acpi_pc8731x_cleanup( void )
     1382{
     1383    unregister_acpi_regions( &pc8731x_regions );
     1384    return 0;
     1385}
     1386
     1387static int get_pc8731x_regions( generic_acpi_regions *regions )
     1388{
     1389    int reg;
     1390    u16 addr;
     1391   
     1392    memset( regions, 0x0, sizeof( *regions ) );
     1393
     1394    regions->hw_type = COBALT_ACPI_HW_PC8731X;
     1395
     1396    regions->pm1_evt_len = 4;
     1397    regions->pm1_cnt_len = 2;
     1398    regions->pm_tmr_len = 4;
     1399    regions->gpe0_len = 4;
     1400   
     1401        /* superi/o -- select pm logical device and get base address */
     1402    addr = superio_ldev_base(PC87317_DEV_PM);
     1403    if( addr )
     1404    {
     1405            /* get registers */
     1406        if( (reg = get_reg(addr, addr + 1, 0x08)) )
     1407            regions->pm1a_evt_blk = reg;
     1408
     1409        if( (reg = get_reg(addr, addr + 1, 0x0a)) )
     1410            regions->pm_tmr_blk = reg;
     1411
     1412        if( (reg = get_reg(addr, addr + 1, 0x0c)) )
     1413            regions->pm1a_cnt_blk = reg;
     1414
     1415        if( (reg = get_reg(addr, addr + 1, 0x0e)) )
     1416            regions->gpe0_blk = reg;
     1417    }
     1418   
     1419    return register_acpi_regions( regions, "pc8731x" );
     1420}
     1421
     1422/*
     1423 *
     1424 * NatSemi PC8741x
     1425 *
     1426 */
     1427
     1428static generic_acpi_regions pc8741x_regions;
     1429
     1430static int cobalt_acpi_pc8741x_init( void )
     1431{
     1432    int err;
     1433   
     1434    if( (err = get_pc8741x_regions( &pc8741x_regions )) < 0 )
     1435        return err;
     1436
     1437    if( (err = cobalt_acpi_register_hw_handler( COBALT_ACPI_HW_PC8741X,
     1438                                                cobalt_acpi_generic_hw_handler,
     1439                                                cobalt_acpi_generic_en_handler,
     1440                                                &pc8741x_regions )) < 0 )
     1441        return err;
     1442
     1443    return 0;
     1444}
     1445
     1446static int cobalt_acpi_pc8741x_cleanup( void )
     1447{
     1448    unregister_acpi_regions( &pc8741x_regions );
     1449    return 0;
     1450}
     1451
     1452static int get_pc8741x_regions( generic_acpi_regions *regions )
     1453{
     1454    int reg;
     1455   
     1456    memset( regions, 0x0, sizeof( *regions ) );
     1457
     1458    regions->hw_type = COBALT_ACPI_HW_PC8741X;
     1459
     1460    regions->pm1_evt_len = 4;
     1461    regions->pm1_cnt_len = 2;
     1462    regions->pm_tmr_len = 4;
     1463    regions->gpe0_len = 8;
     1464   
     1465        /* get registers */
     1466    if( (reg = superio_ldev_base_n(PC87417_DEV_SWC, 1)) )
     1467        regions->pm1a_evt_blk = reg;
     1468
     1469    if( (reg = superio_ldev_base_n(PC87417_DEV_SWC, 2)) )
     1470        regions->pm1a_cnt_blk = reg;
     1471
     1472    if( (reg = superio_ldev_base_n(PC87417_DEV_SWC, 3)) )
     1473        regions->gpe0_blk = reg;
     1474
     1475    return register_acpi_regions( regions, "pc8741x" );
     1476}
     1477
     1478/*
     1479 *
     1480 * Platform support
     1481 *
     1482 */
     1483
     1484/*
     1485 *
     1486 * Monterey
     1487 *
     1488 */
     1489
     1490static u16 cobalt_acpi_monterey_osb4_table[] = {
     1491/* GPE  0 */ COBALT_ACPI_EVT_NONE,
     1492/* GPE  1 */ COBALT_ACPI_EVT_NONE,
     1493/* GPE  2 */ COBALT_ACPI_EVT_NONE,
     1494/* GPE  3 */ COBALT_ACPI_EVT_NONE,
     1495/* GPE  4 */ COBALT_ACPI_EVT_NONE,
     1496/* GPE  5 */ COBALT_ACPI_EVT_NONE,
     1497/* GPE  6 */ COBALT_ACPI_EVT_SLED,
     1498/* GPE  7 */ COBALT_ACPI_EVT_NONE,
     1499/* GPE  8 */ COBALT_ACPI_EVT_NONE,
     1500/* GPE  9 */ COBALT_ACPI_EVT_NONE,
     1501/* GPE 10 */ COBALT_ACPI_EVT_NONE,
     1502/* GPE 11 */ COBALT_ACPI_EVT_NONE,
     1503/* GPE 12 */ COBALT_ACPI_EVT_NONE,
     1504/* GPE 13 */ COBALT_ACPI_EVT_NONE,
     1505/* GPE 14 */ COBALT_ACPI_EVT_NONE,
     1506/* GPE 15 */ COBALT_ACPI_EVT_NONE };
     1507
     1508static u16 cobalt_acpi_monterey_superio_table[] = {
     1509/* GPE  0 */ COBALT_ACPI_EVT_NONE,
     1510/* GPE  1 */ COBALT_ACPI_EVT_NONE,
     1511/* GPE  2 */ COBALT_ACPI_EVT_NONE,
     1512/* GPE  3 */ COBALT_ACPI_EVT_NONE,
     1513/* GPE  4 */ COBALT_ACPI_EVT_NONE,
     1514/* GPE  5 */ COBALT_ACPI_EVT_NONE,
     1515/* GPE  6 */ COBALT_ACPI_EVT_NONE,
     1516/* GPE  7 */ COBALT_ACPI_EVT_NONE,
     1517/* GPE  8 */ COBALT_ACPI_EVT_NONE,
     1518/* GPE  9 */ COBALT_ACPI_EVT_NONE,
     1519/* GPE 10 */ COBALT_ACPI_EVT_NONE,
     1520/* GPE 11 */ COBALT_ACPI_EVT_NONE,
     1521/* GPE 12 */ COBALT_ACPI_EVT_NONE,
     1522/* GPE 13 */ COBALT_ACPI_EVT_NONE,
     1523/* GPE 14 */ COBALT_ACPI_EVT_NONE,
     1524/* GPE 15 */ COBALT_ACPI_EVT_NONE,
     1525/* GPE 16 */ COBALT_ACPI_EVT_NONE,
     1526/* GPE 17 */ COBALT_ACPI_EVT_NONE,
     1527/* GPE 18 */ COBALT_ACPI_EVT_NONE,
     1528/* GPE 19 */ COBALT_ACPI_EVT_NONE,
     1529/* GPE 20 */ COBALT_ACPI_EVT_NONE,
     1530/* GPE 21 */ COBALT_ACPI_EVT_NONE,
     1531/* GPE 22 */ COBALT_ACPI_EVT_NONE,
     1532/* GPE 23 */ COBALT_ACPI_EVT_NONE,
     1533/* GPE 24 */ COBALT_ACPI_EVT_NONE,
     1534/* GPE 25 */ COBALT_ACPI_EVT_NONE,
     1535/* GPE 26 */ COBALT_ACPI_EVT_NONE,
     1536/* GPE 27 */ COBALT_ACPI_EVT_NONE,
     1537/* GPE 28 */ COBALT_ACPI_EVT_NONE,
     1538/* GPE 29 */ COBALT_ACPI_EVT_NONE,
     1539/* GPE 30 */ COBALT_ACPI_EVT_NONE,
     1540/* GPE 31 */ COBALT_ACPI_EVT_NONE };
     1541
     1542static int cobalt_acpi_monterey_init( void )
     1543{
     1544    int err;
     1545   
     1546    err = cobalt_acpi_register_trans_table( COBALT_ACPI_HW_OSB4,
     1547                                            sizeof( cobalt_acpi_monterey_osb4_table )/sizeof( u16 ),
     1548                                            cobalt_acpi_monterey_osb4_table );                       
     1549    if( err < 0 )
     1550        return err;
     1551
     1552    err = cobalt_acpi_register_trans_table( COBALT_ACPI_HW_PC8731X,
     1553                                            sizeof( cobalt_acpi_monterey_superio_table )/sizeof( u16 ),
     1554                                            cobalt_acpi_monterey_superio_table );
     1555    if( err < 0 )
     1556        return err;
     1557
     1558    return 0;
     1559}
     1560
     1561static int cobalt_acpi_monterey_cleanup( void )
     1562{
     1563    cobalt_acpi_unregister_trans_table( COBALT_ACPI_HW_OSB4 );
     1564    cobalt_acpi_unregister_trans_table( COBALT_ACPI_HW_PC8731X );
     1565
     1566    return 0;
     1567}
     1568
     1569/*
     1570 *
     1571 * Alpine
     1572 *
     1573 */
     1574
     1575static u16 cobalt_acpi_alpine_csb5_table[] = {
     1576/* GPE  0 */ COBALT_ACPI_EVT_NONE,
     1577/* GPE  1 */ COBALT_ACPI_EVT_NONE,
     1578/* GPE  2 */ COBALT_ACPI_EVT_NONE,
     1579/* GPE  3 */ COBALT_ACPI_EVT_FAN,
     1580/* GPE  4 */ COBALT_ACPI_EVT_NONE,
     1581/* GPE  5 */ COBALT_ACPI_EVT_SM_INT,
     1582/* GPE  6 */ COBALT_ACPI_EVT_THERM,
     1583/* GPE  7 */ COBALT_ACPI_EVT_NONE,
     1584/* GPE  8 */ COBALT_ACPI_EVT_NONE,
     1585/* GPE  9 */ COBALT_ACPI_EVT_NONE,
     1586/* GPE 10 */ COBALT_ACPI_EVT_NONE,
     1587/* GPE 11 */ COBALT_ACPI_EVT_NONE,
     1588/* GPE 12 */ COBALT_ACPI_EVT_NONE,
     1589/* GPE 13 */ COBALT_ACPI_EVT_NONE,
     1590/* GPE 14 */ COBALT_ACPI_EVT_NONE,
     1591/* GPE 15 */ COBALT_ACPI_EVT_NONE };
     1592
     1593static u16 cobalt_acpi_alpine_superio_table[] = {
     1594/* GPE  0 */ COBALT_ACPI_EVT_NONE,
     1595/* GPE  1 */ COBALT_ACPI_EVT_NONE,
     1596/* GPE  2 */ COBALT_ACPI_EVT_NONE,
     1597/* GPE  3 */ COBALT_ACPI_EVT_NONE,
     1598/* GPE  4 */ COBALT_ACPI_EVT_NONE,
     1599/* GPE  5 */ COBALT_ACPI_EVT_NONE,
     1600/* GPE  6 */ COBALT_ACPI_EVT_NONE,
     1601/* GPE  7 */ COBALT_ACPI_EVT_NONE,
     1602/* GPE  8 */ COBALT_ACPI_EVT_NONE,
     1603/* GPE  9 */ COBALT_ACPI_EVT_NONE,
     1604/* GPE 10 */ COBALT_ACPI_EVT_NONE,
     1605/* GPE 11 */ COBALT_ACPI_EVT_NONE,
     1606/* GPE 12 */ COBALT_ACPI_EVT_NONE,
     1607/* GPE 13 */ COBALT_ACPI_EVT_NONE,
     1608/* GPE 14 */ COBALT_ACPI_EVT_NONE,
     1609/* GPE 15 */ COBALT_ACPI_EVT_NONE,
     1610/* GPE 16 */ COBALT_ACPI_EVT_NONE,
     1611/* GPE 17 */ COBALT_ACPI_EVT_NONE,
     1612/* GPE 18 */ COBALT_ACPI_EVT_NONE,
     1613/* GPE 19 */ COBALT_ACPI_EVT_NONE,
     1614/* GPE 20 */ COBALT_ACPI_EVT_NONE,
     1615/* GPE 21 */ COBALT_ACPI_EVT_NONE,
     1616/* GPE 22 */ COBALT_ACPI_EVT_NONE,
     1617/* GPE 23 */ COBALT_ACPI_EVT_NONE,
     1618/* GPE 24 */ COBALT_ACPI_EVT_NONE,
     1619/* GPE 25 */ COBALT_ACPI_EVT_NONE,
     1620/* GPE 26 */ COBALT_ACPI_EVT_NONE,
     1621/* GPE 27 */ COBALT_ACPI_EVT_NONE,
     1622/* GPE 28 */ COBALT_ACPI_EVT_NONE,
     1623/* GPE 29 */ COBALT_ACPI_EVT_NONE,
     1624/* GPE 30 */ COBALT_ACPI_EVT_NONE,
     1625/* GPE 31 */ COBALT_ACPI_EVT_NONE };
     1626
     1627static int cobalt_acpi_alpine_init( void )
     1628{
     1629    int err;
     1630   
     1631    err = cobalt_acpi_register_trans_table( COBALT_ACPI_HW_CSB5,
     1632                                            sizeof( cobalt_acpi_alpine_csb5_table )/sizeof( u16 ),
     1633                                            cobalt_acpi_alpine_csb5_table );                         
     1634    if( err < 0 )
     1635        return err;
     1636
     1637    err = cobalt_acpi_register_trans_table( COBALT_ACPI_HW_PC8741X,
     1638                                            sizeof( cobalt_acpi_alpine_superio_table )/sizeof( u16 ),
     1639                                            cobalt_acpi_alpine_superio_table );
     1640    if( err < 0 )
     1641        return err;
     1642
     1643    return 0;
     1644}
     1645
     1646static int cobalt_acpi_alpine_cleanup( void )
     1647{
     1648    cobalt_acpi_unregister_trans_table( COBALT_ACPI_HW_CSB5 );
     1649    cobalt_acpi_unregister_trans_table( COBALT_ACPI_HW_PC8741X );
     1650
     1651    return 0;
     1652}
     1653
     1654/*
     1655 * end platform support
     1656 */
     1657#ifdef CONFIG_COBALT_EMU_ACPI
     1658/*
     1659 * This is all necessary because we don't have BIOS support for ACPI yet.
     1660 * We can fake it here, and when full support is ready just yank this.
     1661 */
     1662typedef struct {
     1663        char *device_type;
     1664        char *device_instance;
     1665        u32 event_type;
     1666        u32 event_data;
     1667        struct list_head list;
     1668} cobalt_acpi_event_t;
     1669
     1670#define COBALT_ACPI_MAX_STRING_LENGTH   80
     1671
     1672static LIST_HEAD(cobalt_acpi_event_list);
     1673static DECLARE_WAIT_QUEUE_HEAD(cobalt_acpi_event_wait_queue);
     1674static int event_is_open = 0;
     1675static spinlock_t cobalt_acpi_event_lock = SPIN_LOCK_UNLOCKED;
     1676
     1677static struct proc_dir_entry *cobalt_acpi_proc_root;
     1678static struct proc_dir_entry *cobalt_acpi_proc_event;
     1679
     1680static struct file_operations proc_event_ops = {
     1681        open: cobalt_acpi_open_event,
     1682        read: cobalt_acpi_read_event,
     1683        release: cobalt_acpi_close_event,
     1684        poll: cobalt_acpi_poll_event,
     1685};
     1686
     1687static int
     1688cobalt_acpi_setup_proc(void)
     1689{
     1690        cobalt_acpi_proc_root = proc_mkdir("acpi", NULL);
     1691        if (!cobalt_acpi_proc_root) {
     1692                return -ENOMEM;
     1693        }
     1694
     1695        cobalt_acpi_proc_event = create_proc_entry("event", S_IRUSR,
     1696                                                cobalt_acpi_proc_root);
     1697        if (!cobalt_acpi_proc_event) {
     1698                return -ENOMEM;
     1699        }
     1700
     1701        cobalt_acpi_proc_event->proc_fops = &proc_event_ops;
     1702 
     1703        return 0;
     1704}
     1705
     1706
     1707int
     1708cobalt_acpi_generate_proc_evt( cobalt_acpi_evt * evt )
     1709{
     1710        cobalt_acpi_event_t *event = NULL, *tmp;
     1711        unsigned long flags = 0;
     1712        char *dev_type;
     1713        char *dev_instance;
     1714        u32 event_type;
     1715        u32 event_data;
     1716        struct list_head *pos;
     1717
     1718        /* drop event on the floor if no one's listening */
     1719        if (!event_is_open)
     1720                return 0;
     1721       
     1722        event_type = (evt->ev_type << 0x10) |
     1723            evt->hw_type;
     1724        event_data = evt->ev_data;
     1725
     1726
     1727            /*
     1728             * Check to see if an event of this type is already
     1729             * pending
     1730             */
     1731        spin_lock_irqsave(&cobalt_acpi_event_lock, flags);
     1732        list_for_each( pos, &cobalt_acpi_event_list )
     1733            {
     1734                tmp = list_entry(pos, cobalt_acpi_event_t, list);
     1735                if( (tmp->event_type == event_type) &&
     1736                    (tmp->event_data == event_data) )
     1737                {
     1738                    spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags);
     1739                    return 0;
     1740                }
     1741
     1742
     1743            }
     1744        spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags);
     1745
     1746
     1747            /* parse the event struct */
     1748        switch( evt->ev_type )
     1749        {
     1750            case COBALT_ACPI_EVT_TMR:
     1751                dev_type = "generic";
     1752                dev_instance = "timer";
     1753                break;
     1754
     1755            case COBALT_ACPI_EVT_BM:
     1756                dev_type = "generic";
     1757                dev_instance = "bus-master";
     1758                break;
     1759               
     1760            case COBALT_ACPI_EVT_GBL:
     1761                dev_type = "generic";
     1762                dev_instance = "global";
     1763                break;     
     1764               
     1765            case COBALT_ACPI_EVT_PWRBTN:
     1766                dev_type = "button";
     1767                dev_instance = "power";
     1768                break;     
     1769
     1770            case COBALT_ACPI_EVT_SLPBTN:
     1771                dev_type = "button";
     1772                dev_instance = "sleep";
     1773                break;     
     1774               
     1775            case COBALT_ACPI_EVT_RTC:
     1776                dev_type = "generic";
     1777                dev_instance = "rtc";
     1778                break;     
     1779
     1780            case COBALT_ACPI_EVT_WAK:
     1781                dev_type = "generic";
     1782                dev_instance = "wake";
     1783                break;     
     1784
     1785            case COBALT_ACPI_EVT_GPE:
     1786                dev_type = "generic";
     1787                dev_instance = "gpe";
     1788                break;     
     1789
     1790            case COBALT_ACPI_EVT_SLED:
     1791                dev_type = "cobalt";
     1792                dev_instance = "sled";
     1793                break;     
     1794               
     1795            case COBALT_ACPI_EVT_THERM:
     1796                dev_type = "cobalt";
     1797                dev_instance = "therm_trip";
     1798                break;
     1799
     1800            case COBALT_ACPI_EVT_FAN:
     1801                dev_type = "cobalt";
     1802                dev_instance = "fan";
     1803                break;
     1804
     1805            case COBALT_ACPI_EVT_SM_INT:
     1806                dev_type = "cobalt";
     1807                dev_instance = "sm_int";
     1808                break;
     1809
     1810            case COBALT_ACPI_EVT_VOLT:
     1811                dev_type = "cobalt";
     1812                dev_instance = "volt_trip";
     1813                break;
     1814               
     1815            default:
     1816                dev_type = "unknown";
     1817                dev_instance = "unknown";
     1818                break;
     1819        }
     1820             
     1821               
     1822        /*
     1823         * Allocate a new event structure.
     1824         */
     1825        event = kmalloc(sizeof(*event), GFP_ATOMIC);
     1826        if (!event)
     1827                goto alloc_error;
     1828
     1829        event->device_type=NULL;
     1830        event->device_instance=NULL;
     1831
     1832        event->device_type = kmalloc(strlen(dev_type) + sizeof(char),
     1833                GFP_ATOMIC);
     1834        if (!event->device_type)
     1835                goto alloc_error;
     1836
     1837        event->device_instance = kmalloc(strlen(dev_instance) + sizeof(char),
     1838                GFP_ATOMIC );
     1839        if (!event->device_instance)
     1840                goto alloc_error;
     1841
     1842        /*
     1843         * Set event data.
     1844         */
     1845        strcpy(event->device_type, dev_type);
     1846        strcpy(event->device_instance, dev_instance);
     1847        event->event_type = event_type;
     1848        event->event_data = event_data;
     1849
     1850        /*
     1851         * Add to the end of our event list.
     1852         */
     1853        spin_lock_irqsave(&cobalt_acpi_event_lock, flags);
     1854        list_add_tail(&event->list, &cobalt_acpi_event_list);
     1855        spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags);
     1856
     1857        /*
     1858         * Signal waiting threads (if any).
     1859         */
     1860        wake_up_interruptible(&cobalt_acpi_event_wait_queue);
     1861
     1862        return 0;
     1863
     1864alloc_error:
     1865        if(event)
     1866        {
     1867            if (event->device_instance)
     1868                kfree(event->device_instance);
     1869           
     1870            if (event->device_type)
     1871                kfree(event->device_type);
     1872           
     1873            kfree(event);               
     1874        }
     1875
     1876        return -ENOMEM;
     1877}
     1878
     1879
     1880static int
     1881cobalt_acpi_open_event(struct inode *inode, struct file *file)
     1882{
     1883    unsigned long flags;
     1884    spin_lock_irqsave(&cobalt_acpi_event_lock, flags);
     1885
     1886    if (event_is_open)
     1887        goto out_busy;
     1888
     1889    event_is_open = 1;
     1890   
     1891    spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags);
     1892    return 0;
     1893
     1894out_busy:
     1895    spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags);
     1896    return -EBUSY;
     1897}
     1898
     1899
     1900static int
     1901cobalt_acpi_close_event(struct inode *inode, struct file *file)
     1902{
     1903    unsigned long flags;
     1904    struct list_head *pos;
     1905    cobalt_acpi_event_t *tmp;
     1906   
     1907    spin_lock_irqsave(&cobalt_acpi_event_lock, flags);
     1908
     1909    while( (pos = list_pop( &cobalt_acpi_event_list )) )
     1910    {
     1911        tmp = list_entry(pos, cobalt_acpi_event_t, list);
     1912        if (tmp->device_instance)
     1913                kfree(tmp->device_instance);
     1914           
     1915        if (tmp->device_type)
     1916                kfree(tmp->device_type);
     1917       
     1918        kfree( tmp );
     1919    }
     1920    event_is_open = 0;
     1921    spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags);
     1922    return 0;
     1923}
     1924
     1925#define ACPI_MAX_STRING_LENGTH          80
     1926static ssize_t
     1927cobalt_acpi_read_event(struct file *file, char *buf, size_t count, loff_t *ppos)
     1928{
     1929        cobalt_acpi_event_t *event = NULL;
     1930        unsigned long flags = 0;
     1931        static char str[ACPI_MAX_STRING_LENGTH];
     1932        static int strsize;
     1933        static char *ptr;
     1934
     1935        if (!strsize) {
     1936                DECLARE_WAITQUEUE(wait, current);
     1937
     1938                if (list_empty(&cobalt_acpi_event_list)) {
     1939                        if (file->f_flags & O_NONBLOCK) {
     1940                                return -EAGAIN;
     1941                        }
     1942                        set_current_state(TASK_INTERRUPTIBLE);
     1943                        add_wait_queue(&cobalt_acpi_event_wait_queue, &wait);
     1944       
     1945                        if (list_empty(&cobalt_acpi_event_list)) {
     1946                                schedule();
     1947                        }
     1948       
     1949                        remove_wait_queue(&cobalt_acpi_event_wait_queue, &wait);
     1950                        set_current_state(TASK_RUNNING);
     1951         
     1952                        if (signal_pending(current)) {
     1953                                return -ERESTARTSYS;
     1954                        }
     1955                }
     1956
     1957                spin_lock_irqsave(&cobalt_acpi_event_lock, flags);
     1958                event = list_entry(cobalt_acpi_event_list.next,
     1959                        cobalt_acpi_event_t, list);
     1960                list_del(&event->list);
     1961                spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags);
     1962
     1963                strsize = sprintf(str, "%s %s %08x %08x\n",
     1964                        event->device_type, event->device_instance,
     1965                        event->event_type, event->event_data);
     1966                ptr = str;
     1967
     1968                kfree(event->device_type);
     1969                kfree(event->device_instance);
     1970                kfree(event);
     1971        }
     1972        if (strsize < count)
     1973                count = strsize;
     1974
     1975        if (copy_to_user(buf, ptr, count))
     1976                return -EFAULT;
     1977
     1978        *ppos += count;
     1979        strsize -= count;
     1980        ptr += count;
     1981
     1982        return count;
     1983}
     1984
     1985static unsigned int
     1986cobalt_acpi_poll_event(struct file *file, poll_table *wait)
     1987{
     1988        poll_wait(file, &cobalt_acpi_event_wait_queue, wait);
     1989        if (!list_empty(&cobalt_acpi_event_list))
     1990                return POLLIN | POLLRDNORM;
     1991        return 0;
     1992}
     1993
     1994#endif /* CONFIG_COBALT_EMU_ACPI */
  • drivers/cobalt/fans.c

    diff -Naur linux-2.6.20.orig/drivers/cobalt/fans.c linux-2.6.20/drivers/cobalt/fans.c
    old new  
     1/* $Id: fans.c,v 1.18 2002/03/16 21:33:02 duncan Exp $
     2 * Copyright (c) 2000-2001 Sun Microsystems, Inc
     3 *
     4 * This should be SMP safe.  The critical data (the info list) and the
     5 * critical code (inb()/outb() calls) are protected by fan_lock.  It is
     6 * locked at the only external access points - the proc read()/write()
     7 * methods. --TPH
     8 */
     9#include <linux/config.h>
     10#if defined(CONFIG_COBALT_FANS) || defined(CONFIG_COBALT_FANS_MODULE)
     11
     12#include <stdarg.h>
     13#include <stddef.h>
     14
     15#include <linux/init.h>
     16#include <linux/sched.h>
     17#include <linux/module.h>
     18#include <linux/pci.h>
     19#include <linux/errno.h>
     20#include <linux/proc_fs.h>
     21#include <linux/time.h>
     22
     23#include <asm/io.h>
     24#include <asm/uaccess.h>
     25
     26#include <cobalt/cobalt.h>
     27#include <cobalt/systype.h>
     28
     29#define FAN_DRIVER      "Cobalt Networks Fan driver"
     30#define FAN_DRIVER_VMAJ 1
     31#define FAN_DRIVER_VMIN 0
     32
     33/* GPIO base is assigned by BIOS, perhaps we should probe it */
     34#define GPIO_BASE               0x600
     35#define FAN_GPIO_MAX            8
     36#define FAN_RPM(fn,ms)          ((fn).hcyl * (60000000 / (fn).poles) / (ms))
     37#define FAN_VALID(f)            ((f)->mask && (f)->poles)
     38#define FAN_CACHE_TIME          2 /* seconds */
     39#define FAN_SAMPLE_LEN          50 /* milliseconds */
     40
     41/*
     42 * fans are attached to GPIO pins
     43 * each pin is part of a port, multiple fans are controlled by a port
     44 */
     45struct fan_info {
     46        int id;                 /* fan number */
     47        uint8_t mask;           /* mask within the port */
     48        int poles;              /* # of magnetic poles (divisor) */
     49        int hcyl;               /* # of half cycles */
     50        unsigned rpm;           /* calculated fan speed */
     51        char *type;             /* FAN description */
     52};
     53
     54struct fan_gpio {
     55        int port;               /* GPIO Port */
     56        uint16_t base;          /* GPDI (data in) base address */
     57        uint8_t latch;          /* latched 'data in' value */
     58        long tcache;            /* latched 'epoch' value */
     59        struct fan_info fan[FAN_GPIO_MAX];
     60};
     61
     62/* the current fanlist */
     63static struct fan_gpio *sys_fanlist;
     64static spinlock_t fan_lock = SPIN_LOCK_UNLOCKED;
     65
     66static struct fan_gpio fan_gpio_raqxtr[] = {
     67        {
     68                port: 1,
     69                base: GPIO_BASE,
     70                fan: {
     71                        { mask: 0x2, poles: 4, type: "processor" },
     72                        { mask: 0x4, poles: 4, type: "processor" },
     73                        { mask: 0 },
     74                },
     75        },
     76        {
     77                port: 2,
     78                base: GPIO_BASE+4,
     79                fan: {
     80                        { mask: 0x10, poles: 4 },
     81                        { mask: 0x20, poles: 4 },
     82                        { mask: 0x40, poles: 4 },
     83                        { mask: 0x80, poles: 4 },
     84                        { mask: 0 },
     85                },
     86        },
     87        { port: -1 }
     88};
     89
     90static struct fan_gpio fan_gpio_alpine[] = {
     91        {
     92                port: 2,
     93                base: GPIO_BASE+7,
     94                fan:  {
     95                        { mask: 0x4, poles: 4 },
     96                        { mask: 0x8, poles: 4 },
     97                        { mask: 0x10, poles: 4 },
     98                        { mask: 0x20, poles: 4, type: "power supply" },
     99                        { mask: 0x40, poles: 4, type: "processor" },
     100                        { mask: 0 },
     101                },
     102        },
     103        { port: -1 }
     104};
     105
     106#ifdef CONFIG_PROC_FS
     107#ifdef CONFIG_COBALT_OLDPROC
     108static struct proc_dir_entry *proc_faninfo;
     109#endif /* CONFIG_COBALT_OLDPROC */
     110static struct proc_dir_entry *proc_cfaninfo;
     111#endif /* CONFIG_PROC_FS */
     112
     113static struct fan_info *fan_info_find(int id);
     114static int fan_control(struct fan_info *fi, int todo);
     115static int fan_info_print(char *buffer);
     116static int fan_read_proc(char *buf, char **start, off_t pos,
     117                         int len, int *eof, void *x);
     118static int fan_write_proc(struct file *file, const char *buf,
     119                          unsigned long len, void *x);
     120
     121int __init
     122cobalt_fan_init(void)
     123{
     124        if (cobt_is_monterey()) {
     125                sys_fanlist = (struct fan_gpio *)fan_gpio_raqxtr;
     126        } else if (cobt_is_alpine()) {
     127                sys_fanlist = (struct fan_gpio *)fan_gpio_alpine;
     128        } else {
     129                sys_fanlist = NULL;
     130                return -ENOSYS;
     131        }
     132
     133    printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", FAN_DRIVER,FAN_DRIVER_VMAJ,FAN_DRIVER_VMIN);
     134   
     135#ifdef CONFIG_PROC_FS
     136#ifdef CONFIG_COBALT_OLDPROC
     137        proc_faninfo = create_proc_entry("faninfo", S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, NULL);
     138        if (!proc_faninfo) {
     139                EPRINTK("can't create /proc/faninfo\n");
     140                return -ENOENT;
     141        }
     142        proc_faninfo->owner = THIS_MODULE;
     143        proc_faninfo->read_proc = fan_read_proc;
     144        proc_faninfo->write_proc = fan_write_proc;
     145#endif /* CONFIG_COBALT_OLDPROC */
     146        proc_cfaninfo = create_proc_entry("faninfo", S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, proc_cobalt);
     147        if (!proc_cfaninfo) {
     148                EPRINTK("can't create /proc/cobalt/faninfo\n");
     149                return -ENOENT;
     150        }
     151        proc_cfaninfo->owner = THIS_MODULE;
     152        proc_cfaninfo->read_proc = fan_read_proc;
     153        proc_cfaninfo->write_proc = fan_write_proc;
     154#endif /* CONFIG_PROC_FS */
     155
     156        return 0;
     157}
     158
     159static void __exit
     160cobalt_fan_exit(void)
     161{
     162#ifdef CONFIG_PROC_FS
     163#ifdef CONFIG_COBALT_OLDPROC
     164        if (proc_faninfo) {
     165                remove_proc_entry("faninfo", NULL);
     166        }
     167#endif /* CONFIG_COBALT_OLDPROC */
     168        if (proc_cfaninfo) {
     169                remove_proc_entry("faninfo", proc_cobalt);
     170        }
     171#endif /* CONFIG_PROC_FS */
     172
     173        sys_fanlist = NULL;
     174}
     175
     176/*
     177 * Samples fan tachometer square wave to calculate and report RPM
     178 */
     179static int
     180get_faninfo(char *buffer)
     181{
     182        struct fan_gpio *fg;
     183        struct timeval utime;
     184        unsigned long elapsed, start;
     185        int i, val, len;
     186
     187        if (!sys_fanlist || !cobt_is_5k()) {
     188                /* software is keyed off this string - do not change it ! */
     189                return sprintf(buffer, "Fan monitoring not supported.\n");
     190        }
     191
     192        /* save start timestamp */
     193        do_gettimeofday(&utime);
     194        start = utime.tv_usec;
     195
     196        /* initialize 'previous' values. we do edge detection by
     197         * looking for transitions from previous values */
     198        for (fg = sys_fanlist; fg->port >= 0; fg++) {
     199                if (fg->tcache && utime.tv_sec < fg->tcache+FAN_CACHE_TIME) {
     200                        return fan_info_print(buffer);
     201                }
     202                fg->tcache = utime.tv_sec;
     203                fg->latch = inb(fg->base);
     204                for (i = 0; i < FAN_GPIO_MAX; i++) {
     205                        fg->fan[i].hcyl = 0;
     206                        fg->fan[i].rpm = 0;
     207                }
     208        }
     209
     210        /* We are counting the number of halfcycles in a square wave
     211         * that pass in a given amount of time to determine frequency */
     212        do {
     213                for (fg=sys_fanlist; fg->port>=0; fg++) {
     214                        val = inb(fg->base);
     215                        for (i=0; i<FAN_GPIO_MAX; i++) {
     216                                struct fan_info *p = &fg->fan[i];
     217                                if (FAN_VALID(p)) {
     218                                        if ((val ^ fg->latch) & p->mask) {
     219                                                p->hcyl++;
     220                                        }
     221                                }
     222                        }
     223                        fg->latch = val;
     224                }
     225
     226                do_gettimeofday(&utime);
     227                if (utime.tv_usec > start) {
     228                        elapsed = utime.tv_usec - start;
     229                } else {
     230                        elapsed = utime.tv_usec + 1000001 - start;
     231                }
     232
     233        } while (elapsed < (FAN_SAMPLE_LEN) * 1000);
     234
     235        /* Fan rpm = 60 / ( t * poles )
     236         *  where t is 1/2 the period and poles are the number of
     237         *  magnetic poles for the fan.
     238         * 
     239         * For the Sunon KDE1204PKBX fans on Raq XTR, poles = 4
     240         * So, in terms of cycles,
     241         *
     242         *  rpm = 60 s/m    halfcycles       
     243         *        ------ *  -------------- * 1,000,000 us/s * 2
     244         *        4         2 * elapsed us
     245         *
     246         *      = (60,000,000 / 4 poles) * halfcycles / elapsed
     247         *      = 15,000,000 * halfcycles / elapsed
     248         *
     249         * Note, by this method and sampling for 50ms, our accuracy
     250         *  is +/- 300 rpm.  The fans are spec'ed for +/- 1000 rpm
     251         */
     252        for (val=len=0, fg=sys_fanlist; fg->port>=0; fg++) {
     253                for (i=0; i<FAN_GPIO_MAX; i++) {
     254                        struct fan_info *p = &fg->fan[i];
     255                        if (FAN_VALID(p)) {
     256                                p->id = val++;
     257                                p->rpm = FAN_RPM(fg->fan[i], elapsed);
     258                                len += sprintf(buffer+len, "fan %d     : %u\n",
     259                                        p->id, p->rpm);
     260                        }
     261                }
     262        }
     263
     264        return len;
     265}
     266
     267static int
     268fan_info_print(char *buffer)
     269{
     270        struct fan_gpio *fg;
     271        int i, len=0;
     272
     273        if (!sys_fanlist) {
     274                return -1;
     275        }
     276
     277        for (fg=sys_fanlist; fg->port>=0; fg++) {
     278                for (i=0; i<FAN_GPIO_MAX; i++) {
     279                        struct fan_info *p = &fg->fan[i];
     280                        if (FAN_VALID(p)) {
     281                                len += sprintf(buffer+len, "fan %d     : %u\n",
     282                                        p->id, p->rpm);
     283                        }
     284                }
     285        }
     286
     287        return len;
     288}
     289
     290/* FIXME: generify */
     291static int
     292fan_control(struct fan_info *fi, int todo)
     293{
     294        if (fi && cobt_is_alpine()) {
     295                switch (fi->id) {
     296                case 4: {
     297                        /* CPU FAN */
     298                        uint8_t gpdo = inb(GPIO_BASE+6);
     299
     300                        if (todo) {
     301                                gpdo &= ~fi->mask; /* 0 = on */
     302                        } else {
     303                                gpdo |= fi->mask;  /* 1 = off */
     304                        }
     305                        outb(gpdo, GPIO_BASE+6);
     306                        return 0;
     307                }
     308                default:
     309                        return -ENODEV;
     310                }
     311        }
     312
     313        return -ENOSYS;
     314}
     315
     316static struct fan_info *
     317fan_info_find(int id)
     318{
     319        struct fan_gpio *fg;
     320        int i;
     321
     322        if (!sys_fanlist) {
     323                return NULL;
     324        }
     325
     326        for (fg=sys_fanlist; fg->port>=0; fg++) {
     327                for (i=0; i<FAN_GPIO_MAX; i++) {
     328                        if (FAN_VALID(&fg->fan[i])) {
     329                                if (fg->fan[i].id == id) {
     330                                        return &fg->fan[i];
     331                                }
     332                        }
     333                }
     334        }
     335
     336        return NULL;
     337}
     338
     339#ifdef CONFIG_PROC_FS
     340static int
     341fan_read_proc(char *buf, char **start, off_t pos, int len, int *eof, void *x)
     342{
     343        int plen;
     344
     345        //MOD_INC_USE_COUNT;
     346
     347        spin_lock(&fan_lock);
     348        plen = get_faninfo(buf);
     349        spin_unlock(&fan_lock);
     350
     351        //MOD_DEC_USE_COUNT;
     352
     353        return cobalt_gen_proc_read(buf, plen, start, pos, len, eof);
     354}
     355
     356static int
     357fan_write_proc(struct file *file, const char *buf, unsigned long len, void *x)
     358{
     359        char *page;
     360        int retval = -EINVAL;
     361
     362        //MOD_INC_USE_COUNT;
     363
     364        if (len > PAGE_SIZE) {
     365                //MOD_DEC_USE_COUNT;
     366                return -EOVERFLOW;
     367        }
     368
     369        page = (char *)__get_free_page(GFP_KERNEL);
     370        if (!page) {
     371                //MOD_DEC_USE_COUNT;
     372                return -ENOMEM;
     373        }
     374
     375        if (copy_from_user(page, buf, len)) {
     376                free_page((unsigned long)page);
     377                //MOD_DEC_USE_COUNT;
     378                return -EFAULT;
     379        }
     380        page[len] = '\0';
     381
     382        /* format: `fan ID COMMAND' */
     383        if (len>5 && !strncmp("fan ", page, 4)) {
     384                if (*(page+4) != '\0') {
     385                        struct fan_info *finf;
     386                        char *nextpg = NULL;
     387
     388                        spin_lock(&fan_lock);
     389                        finf = fan_info_find(simple_strtoul(page+4,&nextpg,0));
     390                        if (!finf) {
     391                                retval = -ENOENT;
     392                        } else if (nextpg != '\0') {
     393                                if (!strncmp("on", nextpg+1, 2)) {
     394                                        retval = fan_control(finf, 1);
     395                                }
     396                                else if (!strncmp("off", nextpg+1, 3)) {
     397                                        retval = fan_control(finf, 0);
     398                                }
     399                        }
     400                        spin_unlock(&fan_lock);
     401                }
     402        }
     403
     404        free_page((unsigned long)page);
     405        //MOD_DEC_USE_COUNT;
     406       
     407        return (retval < 0) ? retval : len;
     408}
     409#endif /* CONFIG_PROC_FS */
     410
     411#if defined(CONFIG_COBALT_FANS_MODULE)
     412module_init(cobalt_fan_init);
     413module_exit(cobalt_fan_exit);
     414
     415MODULE_AUTHOR("Sun Cobalt");
     416MODULE_DESCRIPTION("Sun Cobalt fan tachometers");
     417#endif
     418
     419#endif /* CONFIG_COBALT_FANS || CONFIG_COBALT_FANS_MODULE */
  • drivers/cobalt/i2c.c

    diff -Naur linux-2.6.20.orig/drivers/cobalt/i2c.c linux-2.6.20/drivers/cobalt/i2c.c
    old new  
     1/*
     2 * $Id: i2c.c,v 1.19 2002/09/17 23:41:29 sparker Exp $
     3 * i2c.c : Cobalt I2C driver support
     4 *
     5 * Copyright (C) 2000 Cobalt Networks, Inc.
     6 * Copyright (C) 2001 Sun Microsystems, Inc.
     7 *
     8 * Modified By: jeff@404ster.com
     9 *
     10 * This should be SMP safe.  All the exported functions lock on enter and
     11 * unlock on exit.  These exported functions may be called at interupt time,
     12 * so we have to use the IRQ safe locks.  NOTE: no function herein may call
     13 * any exported function herein. --TPH
     14 */
     15#include <stddef.h>
     16#include <linux/init.h>
     17#include <linux/types.h>
     18#include <linux/config.h>
     19#include <linux/pci.h>
     20#include <linux/delay.h>
     21#include <linux/module.h>
     22#include <asm/io.h>
     23
     24#include <cobalt/cobalt.h>
     25#include <cobalt/i2c.h>
     26#include <cobalt/systype.h>
     27
     28#define I2C_3K_STATUS                   0x00
     29#define I2C_3K_CMD                      0x01
     30#define I2C_3K_START                    0x02
     31#define I2C_3K_ADDR                     0x03
     32#define I2C_3K_LOW_DATA                 0x04
     33#define I2C_3K_HIGH_DATA                0x05
     34#define I2C_3K_BLOCK_DATA               0x06
     35#define I2C_3K_INDEX                    0x07
     36#define I2C_3K_STATUS_IDLE              0x04
     37#define I2C_3K_CMD_RW_BYTE              0x20
     38#define I2C_3K_CMD_RW_WORD              0x30
     39#define I2C_3K_CMD_RW_BLOCK             0xC0
     40#define I2C_3K_CMD_RESET_PTR            0x80
     41
     42#define I2C_5K_HOST_STATUS              0x00
     43#define I2C_5K_SLAVE_STATUS             0x01
     44#define I2C_5K_HOST_CONTROL             0x02
     45#define I2C_5K_HOST_COMMAND             0x03
     46#define I2C_5K_HOST_ADDR                0x04
     47#define I2C_5K_DATA_0                   0x05
     48#define I2C_5K_DATA_1                   0x06
     49#define I2C_5K_BLOCK_DATA               0x07
     50#define I2C_5K_SLAVE_CONTROL            0x08
     51#define I2C_5K_SHADOW_COMMAND           0x09
     52#define I2C_5K_SLAVE_EVENT              0x0a
     53#define I2C_5K_SLAVE_DATA               0x0c
     54#define I2C_5K_HOST_STATUS_BUSY         0x01
     55#define I2C_5K_HOST_CMD_START           0x40
     56#define I2C_5K_HOST_CMD_QUICK_RW        (0 << 2)
     57#define I2C_5K_HOST_CMD_BYTE_RW         (1 << 2)
     58#define I2C_5K_HOST_CMD_BYTE_DATA_RW    (2 << 2)
     59#define I2C_5K_HOST_CMD_WORD_DATA_RW    (3 << 2)
     60#define I2C_5K_HOST_CMD_BLOCK_DATA_RW   (5 << 2)
     61
     62#define I2C_WRITE                       0
     63#define I2C_READ                        1
     64
     65/* this delay was determined empirically */
     66#define I2C_WRITE_UDELAY                1000
     67
     68struct cobalt_i2c_data {
     69        const unsigned char status;
     70        const unsigned char addr;
     71        const unsigned char index;
     72        const unsigned char data_low;
     73        const unsigned char data_high;
     74        const unsigned char data_block;
     75        const unsigned char rw_byte;
     76        const unsigned char rw_word;
     77        const unsigned char rw_block;
     78        unsigned int io_port;
     79};
     80
     81struct cobalt_i2c_data cobalt_i2c_3k = {
     82        I2C_3K_STATUS,
     83        I2C_3K_ADDR,
     84        I2C_3K_INDEX,
     85        I2C_3K_LOW_DATA,
     86        I2C_3K_HIGH_DATA,
     87        I2C_3K_BLOCK_DATA,
     88        I2C_3K_CMD_RW_BYTE,
     89        I2C_3K_CMD_RW_WORD,
     90        I2C_3K_CMD_RW_BLOCK,
     91        0L
     92};
     93
     94struct cobalt_i2c_data cobalt_i2c_5k = {
     95        I2C_5K_HOST_STATUS,
     96        I2C_5K_HOST_ADDR,
     97        I2C_5K_HOST_COMMAND,
     98        I2C_5K_DATA_0,
     99        I2C_5K_DATA_1,
     100        I2C_5K_BLOCK_DATA,
     101        I2C_5K_HOST_CMD_BYTE_DATA_RW,
     102        I2C_5K_HOST_CMD_WORD_DATA_RW,
     103        I2C_5K_HOST_CMD_BLOCK_DATA_RW,
     104        0L
     105};
     106
     107/* a global pointer for our i2c data */
     108struct cobalt_i2c_data *i2c_data;
     109
     110#define I2C_REG(r)                      (i2c_data->io_port + i2c_data->r)
     111#define I2C_CMD(c)                      (i2c_data->c)
     112
     113#define I2C_LOCK        (1 << 0)
     114#define I2C_DEAD        (1 << 1)
     115static unsigned long i2c_state;
     116
     117static int initialized;
     118
     119static inline int
     120do_i2c_lock(void)
     121{
     122        int i = 0;
     123
     124        if (test_bit(I2C_DEAD, &i2c_state))
     125                return -1;
     126
     127        while (test_and_set_bit(I2C_LOCK, &i2c_state)) {
     128                if (i++ > 5)
     129                        return -1;
     130                udelay(10);
     131        }
     132        udelay(1);
     133        return 0;
     134}
     135
     136static inline void
     137do_i2c_unlock(void)
     138{
     139        clear_bit(I2C_LOCK, &i2c_state);
     140}
     141
     142/* do a little squelching */
     143#define NOISE_RATE (5*HZ)
     144static int
     145i2c_noisy(void)
     146{
     147        static unsigned long last_time;
     148        static unsigned int messages;
     149
     150        if ((long) (jiffies - last_time) > NOISE_RATE) {
     151                last_time = jiffies;
     152                if (messages) {
     153                        WPRINTK("skipped %u kernel messages\n", messages);
     154                        messages = 0;
     155                }
     156                return 0;
     157        }
     158        messages++;
     159        return 1;
     160}
     161
     162static int
     163i2c_wait_for_smi(void)
     164{
     165        static unsigned int shutup = 0;
     166        int timeout=10;
     167        int status;
     168
     169        while (timeout--) {
     170                udelay(100); /* wait */
     171                status = inb_p(I2C_REG(status));
     172
     173                if (cobt_is_3k()) {
     174                        if (status & I2C_3K_STATUS_IDLE) {
     175                                return 0;
     176                        }
     177                } else if (cobt_is_5k()) {
     178                        if (!(status & I2C_5K_HOST_STATUS_BUSY)) {
     179                                return 0;
     180                        }
     181                }
     182                outb_p(status, I2C_REG(status));
     183        }
     184
     185        /* still busy - complain */
     186        if (!i2c_noisy()) {
     187                if (++shutup > 2) {
     188                        EPRINTK("i2c seems to be dead - sorry\n");
     189                        set_bit(I2C_DEAD, &i2c_state);
     190                } else {
     191                        WPRINTK("i2c timeout: status busy (0x%x), resetting\n",
     192                                status);
     193                }
     194        }
     195
     196        /* punch the abort bit */
     197        if (cobt_is_3k()) {
     198                outb_p(4, i2c_data->io_port + I2C_3K_CMD);
     199        } else if (cobt_is_5k()) {
     200                outb_p(2, i2c_data->io_port + I2C_5K_HOST_CONTROL);
     201                outb_p(1, i2c_data->io_port + I2C_5K_HOST_CONTROL);
     202        }
     203
     204        return -1;
     205}
     206
     207static inline int
     208i2c_setup(const int dev, const int index, const int r)
     209{
     210        if (i2c_wait_for_smi() < 0)
     211                return -1;
     212
     213        /* clear status */
     214        outb_p(0xff, I2C_REG(status));
     215
     216        /* device address */
     217        outb_p((dev|r) & 0xff, I2C_REG(addr));
     218
     219        /* I2C index */
     220        outb_p(index & 0xff, I2C_REG(index));
     221
     222        return 0;
     223}
     224       
     225static inline int
     226i2c_cmd(const unsigned char command)
     227{
     228        if (cobt_is_3k()) {
     229                outb_p(command, i2c_data->io_port + I2C_3K_CMD);
     230                outb_p(0xff, i2c_data->io_port + I2C_3K_START);
     231        } else if (cobt_is_5k()) {
     232                outb_p(I2C_5K_HOST_CMD_START | command,
     233                        i2c_data->io_port + I2C_5K_HOST_CONTROL);
     234        }
     235
     236        if (i2c_wait_for_smi() < 0)
     237                return -1;
     238
     239        return 0;
     240}
     241
     242int
     243cobalt_i2c_init(void)
     244{
     245        struct pci_dev *i2cdev = NULL;
     246
     247        if( ! initialized ) {
     248                if (cobt_is_3k()) {
     249                        i2c_data = &cobalt_i2c_3k;
     250                        i2cdev = pci_find_device(PCI_VENDOR_ID_AL,
     251                                PCI_DEVICE_ID_AL_M7101, NULL);
     252                        if (!i2cdev) {
     253                                EPRINTK("can't find PMU for i2c access\n");
     254                                return -1;
     255                        }
     256                        pci_read_config_dword(i2cdev, 0x14, &i2c_data->io_port);
     257                } else if (cobt_is_5k()) {
     258                        i2c_data = &cobalt_i2c_5k;
     259                        i2cdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
     260                                PCI_DEVICE_ID_SERVERWORKS_OSB4, i2cdev);
     261                        if (!i2cdev) {
     262                            i2cdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
     263                            PCI_DEVICE_ID_SERVERWORKS_CSB5, i2cdev);
     264                            if (!i2cdev) {
     265                                EPRINTK("can't find OSB4 or CSB5 for i2c access\n");
     266                                return -1;
     267                            }
     268                        }
     269                        pci_read_config_dword(i2cdev, 0x90, &i2c_data->io_port);
     270                }
     271
     272                i2c_data->io_port &= 0xfff0;
     273                if (!i2c_data->io_port) {
     274                        EPRINTK("i2c IO port not found\n");
     275                }
     276                initialized = 1;
     277        }
     278
     279        return 0;
     280}
     281
     282int
     283cobalt_i2c_reset(void)
     284{
     285        int r;
     286
     287        if( !initialized ) {
     288                if( cobalt_i2c_init() < 0 )
     289                        return -1;
     290        }
     291
     292        if (do_i2c_lock() < 0)
     293                return -1;
     294
     295        if (cobt_is_3k()) {
     296                /* clear status */
     297                outb_p(0xff, i2c_data->io_port + I2C_3K_STATUS);
     298                /* reset SMB devs */
     299                outb_p(0x08, i2c_data->io_port + I2C_3K_CMD);
     300                /* start command */
     301                outb_p(0xff, i2c_data->io_port + I2C_3K_START);
     302        } else if (cobt_is_5k()) {
     303                /* clear status */
     304                outb_p(0x2, i2c_data->io_port + I2C_5K_HOST_CONTROL);
     305                outb_p(0x1, i2c_data->io_port + I2C_5K_HOST_CONTROL);
     306                outb_p(0xff, i2c_data->io_port + I2C_5K_HOST_STATUS);
     307                outb_p(I2C_5K_HOST_CMD_START | 0x08,
     308                        i2c_data->io_port + I2C_5K_HOST_CONTROL);
     309        }
     310
     311        r = i2c_wait_for_smi();
     312
     313        do_i2c_unlock();
     314
     315        return r;
     316}
     317
     318int
     319cobalt_i2c_read_byte(const int dev, const int index)
     320{
     321        int val = 0;
     322
     323        if( !initialized ) {
     324                if( cobalt_i2c_init() < 0 )
     325                        return -1;
     326        }
     327
     328        if (do_i2c_lock() < 0)
     329                return -1;
     330
     331        if (i2c_setup(dev, index, I2C_READ) < 0
     332         || i2c_cmd(I2C_CMD(rw_byte)) < 0) {
     333                val = -1;
     334        }
     335
     336        if (val == 0) {
     337                val = inb_p(I2C_REG(data_low));
     338        }
     339
     340        do_i2c_unlock();
     341
     342        return val;
     343}
     344
     345int
     346cobalt_i2c_read_word(const int dev, const int index)
     347{
     348        int val = 0;
     349
     350        if( !initialized ) {
     351                if( cobalt_i2c_init() < 0 )
     352                        return -1;
     353        }
     354
     355        if (do_i2c_lock() < 0)
     356                return -1;
     357       
     358        if (i2c_setup(dev, index, I2C_READ) < 0
     359         || i2c_cmd(I2C_CMD(rw_word)) < 0) {
     360                val = -1;
     361        }
     362
     363        if (val == 0) {
     364                val = inb_p(I2C_REG(data_low));
     365                val += inb_p(I2C_REG(data_high)) << 8;
     366        }
     367
     368        do_i2c_unlock();
     369
     370        return val;
     371}
     372
     373int
     374cobalt_i2c_read_block(const int dev, const int index,
     375        unsigned char *data, int count)
     376{
     377        if( !initialized ) {
     378                if( cobalt_i2c_init() < 0 )
     379                        return -1;
     380        }
     381
     382        if (do_i2c_lock() < 0)
     383                return -1;
     384       
     385        if (i2c_setup(dev, index, I2C_READ) < 0) {
     386                do_i2c_unlock();
     387                return -1;
     388        }
     389
     390        outb_p(count & 0xff, I2C_REG(data_low));
     391        outb_p(count & 0xff, I2C_REG(data_high));
     392
     393        if (i2c_cmd(I2C_CMD(rw_block)) < 0) {
     394                do_i2c_unlock();
     395                return -1;
     396        }
     397
     398        while (count) {
     399                /* read a byte of block data */
     400                *data = inb_p(I2C_REG(data_block));
     401                data++;
     402                count--;
     403        }
     404
     405        do_i2c_unlock();
     406
     407        return 0;       
     408}
     409
     410int
     411cobalt_i2c_write_byte(const int dev, const int index, const u8 val)
     412{
     413        int r = 0;
     414
     415        if( !initialized ) {
     416                if( cobalt_i2c_init() < 0 )
     417                        return -1;
     418        }
     419
     420        if (do_i2c_lock() < 0)
     421                return -1;
     422
     423        if (i2c_setup(dev, index, I2C_WRITE) < 0) {
     424                r = -1;
     425        }
     426
     427        if (r == 0) {
     428                outb_p(val & 0xff, I2C_REG(data_low));
     429
     430                if (i2c_cmd(I2C_CMD(rw_byte)) < 0) {
     431                        r = -1;
     432                }
     433        }
     434
     435        udelay(I2C_WRITE_UDELAY);
     436
     437        do_i2c_unlock();
     438
     439        return r;       
     440}
     441
     442int
     443cobalt_i2c_write_word(const int dev, const int index, const u16 val)
     444{
     445        int r = 0;
     446
     447        if( !initialized ) {
     448                if( cobalt_i2c_init() < 0 )
     449                        return -1;
     450        }
     451
     452        if (do_i2c_lock() < 0)
     453                return -1;
     454
     455        if (i2c_setup(dev, index, I2C_WRITE) < 0) {
     456                r = -1;
     457        }
     458
     459        if (r == 0) {
     460                outb_p(val & 0xff, I2C_REG(data_low));
     461                outb_p((val >> 8) & 0xff, I2C_REG(data_high));
     462
     463                if (i2c_cmd(I2C_CMD(rw_word)) < 0) {
     464                        r = -1;
     465                }
     466        }
     467       
     468        udelay(I2C_WRITE_UDELAY);
     469
     470        do_i2c_unlock();
     471
     472        return r;       
     473}
     474
     475int
     476cobalt_i2c_write_block(int dev, int index, unsigned char *data, int count)
     477{
     478        if( !initialized ) {
     479                if( cobalt_i2c_init() < 0 )
     480                        return -1;
     481        }
     482
     483        if (do_i2c_lock() < 0)
     484                return -1;
     485
     486        if (i2c_setup(dev, index, I2C_WRITE) < 0) {
     487                do_i2c_unlock();
     488                return -1;
     489        }
     490
     491        outb_p(count & 0xff, I2C_REG(data_low));
     492        outb_p(count & 0xff, I2C_REG(data_high));
     493
     494        if (i2c_cmd(I2C_CMD(rw_block)) < 0) {
     495                do_i2c_unlock();
     496                return -1;
     497        }
     498
     499        while (count) {
     500                /* write a byte of block data */
     501                outb_p(*data, I2C_REG(data_block));
     502                data++;
     503                count--;
     504        }
     505
     506        udelay(I2C_WRITE_UDELAY);
     507
     508        do_i2c_unlock();
     509
     510        return 0;       
     511}
     512
     513EXPORT_SYMBOL(cobalt_i2c_reset);
     514EXPORT_SYMBOL(cobalt_i2c_read_byte);
     515EXPORT_SYMBOL(cobalt_i2c_read_word);
     516EXPORT_SYMBOL(cobalt_i2c_read_block);
     517EXPORT_SYMBOL(cobalt_i2c_write_byte);
     518EXPORT_SYMBOL(cobalt_i2c_write_word);
     519EXPORT_SYMBOL(cobalt_i2c_write_block);
  • drivers/cobalt/init.c

    diff -Naur linux-2.6.20.orig/drivers/cobalt/init.c linux-2.6.20/drivers/cobalt/init.c
    old new  
     1/* $Id: init.c,v 1.22 2002/11/04 17:54:15 thockin Exp $ */
     2/*
     3 *   Copyright (c) 2001  Sun Microsystems
     4 *   Generic initialization, to reduce pollution of other files
     5 */
     6#include <linux/config.h>
     7#include <linux/module.h>
     8#include <linux/stddef.h>
     9#include <linux/version.h>
     10#include <linux/types.h>
     11#include <linux/init.h>
     12#include <linux/proc_fs.h>
     13#include <cobalt/cobalt.h>
     14
     15static int cobalt_proc_init(void);
     16extern int cobalt_i2c_init(void);
     17extern int cobalt_net_init(void);
     18extern int cobalt_systype_init(void);
     19extern void cobalt_boardrev_init(void);
     20extern int cobalt_led_init(void);
     21extern int cobalt_lcd_init(void);
     22extern int cobalt_serialnum_init(void);
     23extern int cobalt_wdt_init(void);
     24extern int cobalt_sensors_init(void);
     25extern int cobalt_fan_init(void);
     26extern int cobalt_acpi_init(void);
     27extern int cobalt_ruler_init(void);
     28extern int cobalt_raminfo_init(void);
     29
     30#ifdef CONFIG_PROC_FS
     31struct proc_dir_entry *proc_cobalt;
     32EXPORT_SYMBOL(proc_cobalt);
     33#endif
     34spinlock_t cobalt_superio_lock = SPIN_LOCK_UNLOCKED;
     35
     36/* initialize all the cobalt specific stuff */
     37int __init
     38cobalt_init(void)
     39{
     40    cobalt_proc_init();
     41    cobalt_systype_init();
     42#ifdef CONFIG_COBALT_RAQ
     43    /* we might keep the boardrev on an i2c chip */
     44    cobalt_i2c_init();
     45#endif
     46    cobalt_boardrev_init();
     47#ifdef CONFIG_COBALT_ACPI
     48    cobalt_acpi_init();
     49#endif
     50#ifdef CONFIG_COBALT_LED
     51    cobalt_net_init();
     52    cobalt_led_init();
     53#endif
     54#ifdef CONFIG_COBALT_LCD
     55    cobalt_lcd_init();
     56#endif
     57#ifdef CONFIG_COBALT_RULER
     58    cobalt_ruler_init();
     59#endif
     60#ifdef CONFIG_COBALT_SERNUM
     61    cobalt_serialnum_init();
     62#endif
     63#ifdef CONFIG_COBALT_RAQ
     64    /* some systems use WDT it for reboot */
     65    cobalt_wdt_init();
     66#endif
     67#ifdef CONFIG_COBALT_SENSORS
     68    cobalt_sensors_init();
     69#endif
     70#ifdef CONFIG_COBALT_FANS
     71    cobalt_fan_init();
     72#endif
     73#ifdef CONFIG_COBALT_RAMINFO
     74    cobalt_raminfo_init();
     75#endif
     76    return 0;
     77}
     78
     79static int __init
     80cobalt_proc_init(void)
     81{
     82#ifdef CONFIG_PROC_FS
     83        proc_cobalt = proc_mkdir("cobalt", 0);
     84        if (!proc_cobalt) {
     85                EPRINTK("can't create /proc/cobalt\n");
     86                return -1;
     87        }
     88#endif
     89
     90        return 0;
     91}
     92
     93/* a function that handles the blah stuff in a simple proc read function */
     94int
     95cobalt_gen_proc_read(char *buf, int plen, char **start, off_t pos,
     96        int len, int *eof)
     97{
     98        /* trying to read a bad offset? */
     99        if (pos >= plen) {
     100                *eof = 1;
     101                return 0;
     102        }
     103
     104        /* did we write everything we wanted to? */
     105        if (len >= (plen-pos)) {
     106                *eof = 1;
     107        }
     108
     109        *start = buf + pos;
     110        plen -= pos;
     111
     112        return (len > plen) ? plen : len;
     113}
     114EXPORT_SYMBOL(cobalt_gen_proc_read);
  • drivers/cobalt/lcd.c

    diff -Naur linux-2.6.20.orig/drivers/cobalt/lcd.c linux-2.6.20/drivers/cobalt/lcd.c
    old new  
     1/*
     2 * $Id: lcd.c,v 1.44 2002/05/10 18:44:45 duncan Exp $
     3 * lcd.c : driver for Cobalt LCD/Buttons
     4 *
     5 * Copyright 1996-2000 Cobalt Networks, Inc.
     6 * Copyright 2001 Sun Microsystems, Inc.
     7 *
     8 * By:  Andrew Bose
     9 *      Timothy Stonis
     10 *      Tim Hockin
     11 *      Adrian Sun
     12 *      Duncan Laurie
     13 *
     14 * Modified By: jeff@404ster.com
     15 *
     16 * This should be SMP safe. We're hardly performance critical,
     17 * so we lock around lcd_ioctl() and just where needed by other external
     18 * functions.  There is a static global waiters variable that is atomic_t, and
     19 * so should be safe. --TPH
     20 */
     21
     22#include <linux/config.h>
     23
     24#ifdef CONFIG_COBALT_LCD
     25
     26#include <linux/module.h>
     27#include <linux/types.h>
     28#include <linux/errno.h>
     29#include <linux/miscdevice.h>
     30#include <linux/slab.h>
     31#include <linux/ioport.h>
     32#include <linux/fcntl.h>
     33#include <linux/stat.h>
     34#include <linux/netdevice.h>
     35#include <linux/proc_fs.h>
     36#include <linux/in6.h>
     37#include <linux/pci.h>
     38#include <linux/init.h>
     39#include <linux/timer.h>
     40#include <linux/kernel.h>
     41
     42#include <asm/io.h>
     43#include <asm/segment.h>
     44#include <asm/system.h>
     45#include <asm/uaccess.h>
     46#include <asm/checksum.h>
     47#include <linux/delay.h>
     48
     49#include <cobalt/cobalt.h>
     50#include <cobalt/systype.h>
     51#include <cobalt/lcd.h>
     52#include <cobalt/superio.h>
     53#include <cobalt/i2c.h>
     54
     55#define TWIDDLE_HZ (HZ/10)
     56
     57#ifndef min
     58#define min(a, b)  ((a) < (b) ? (a) : (b))
     59#endif
     60
     61#define LCD_DRIVER              "Cobalt Networks LCD driver"
     62#define LCD_DRIVER_VMAJ         4
     63#define LCD_DRIVER_VMIN         0
     64
     65/* io registers */
     66#define LPT                     0x0378
     67#define LCD_DATA_ADDRESS        LPT+0
     68#define LCD_CONTROL_ADDRESS     LPT+2
     69
     70/* LCD device info */
     71#define LCD_Addr                0x80
     72#define DD_R00                  0x00
     73#define DD_R01                  0x27
     74#define DD_R10                  0x40
     75#define DD_R11                  0x67
     76
     77/* driver functions */
     78static int cobalt_lcd_open(struct inode *, struct file *);
     79static ssize_t cobalt_lcd_read(struct file *, char *, size_t, loff_t *);
     80static int cobalt_lcd_read_proc(char *, char **, off_t, int, int *, void *);
     81static char *cobalt_lcddev_read_line(int, char *);
     82static int cobalt_lcd_ioctl(struct inode *, struct file *,
     83        unsigned int, unsigned long);
     84static int cobalt_lcd_panic(struct notifier_block *self, unsigned long, void *);
     85
     86/* globals used throughout */
     87#ifdef CONFIG_PROC_FS
     88#ifdef CONFIG_COBALT_OLDPROC
     89static struct proc_dir_entry *proc_lcd;
     90#endif
     91static struct proc_dir_entry *proc_clcd;
     92#endif
     93static int lcd_present;
     94static int has_i2c_lcd;
     95static spinlock_t lcd_lock = SPIN_LOCK_UNLOCKED;
     96
     97/* various file operations we support for this driver */
     98static struct file_operations lcd_fops = {
     99        .read = cobalt_lcd_read,
     100        .ioctl = cobalt_lcd_ioctl,
     101        .open = cobalt_lcd_open,
     102};
     103
     104/* device structure */
     105static struct miscdevice lcd_dev = {
     106        MISC_DYNAMIC_MINOR,
     107        "lcd",
     108        &lcd_fops
     109};
     110
     111static int disable_lcd;
     112static int __init
     113lcd_disable_setup(char *str)
     114{
     115        disable_lcd = 1;
     116        return 0;
     117}
     118__setup("nolcd", lcd_disable_setup);
     119
     120/* Read a control instruction from the LCD */
     121static inline int
     122lcddev_read_inst(void)
     123{
     124        int a = 0;
     125
     126        if (cobt_is_5k() && has_i2c_lcd) {
     127                a = cobalt_i2c_read_byte(
     128                        COBALT_I2C_DEV_LCD_INST | COBALT_I2C_READ, 0);
     129        } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) {
     130                outb(0x21, LCD_CONTROL_ADDRESS); /* RS=0, R/W=1, E=0 */
     131                outb(0x20, LCD_CONTROL_ADDRESS); /* RS=0, R/W=1, E=1 */
     132                a = inb(LCD_DATA_ADDRESS);
     133                outb(0x21, LCD_CONTROL_ADDRESS); /* RS=0, R/W=1, E=0 */
     134                outb(0x01, LCD_CONTROL_ADDRESS); /* RS=0, R/W=1, E=0 */
     135        }
     136
     137        /* small delay */
     138        udelay(100);
     139
     140        return a;
     141}
     142
     143#define LCD_MAX_POLL 10000
     144static inline void
     145lcddev_poll_wait(void)
     146{
     147        int i=0;
     148
     149        while (i++ < LCD_MAX_POLL) {
     150                int r = lcddev_read_inst();
     151                if (r < 0 || !(r & 0x80))
     152                        break;
     153        }
     154}
     155
     156/* Write a control instruction to the LCD */
     157static inline void
     158lcddev_write_inst(unsigned char data)
     159{
     160        lcddev_poll_wait();
     161
     162        if (cobt_is_5k() && has_i2c_lcd) {
     163                cobalt_i2c_write_byte(
     164                        COBALT_I2C_DEV_LCD_INST | COBALT_I2C_WRITE, 0, data);
     165        } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) {
     166                outb(0x03, LCD_CONTROL_ADDRESS); /* RS=0, R/W=0, E=0 */
     167                outb(data, LCD_DATA_ADDRESS);
     168                outb(0x02, LCD_CONTROL_ADDRESS); /* RS=0, R/W=0, E=1 */
     169                outb(0x03, LCD_CONTROL_ADDRESS); /* RS=0, R/W=0, E=0 */
     170                outb(0x01, LCD_CONTROL_ADDRESS); /* RS=0, R/W=1, E=0 */
     171        }
     172
     173        /* small delay */
     174        udelay(100);
     175}
     176
     177/* Write one byte of data to the LCD */
     178static inline void
     179lcddev_write_data(unsigned char data)
     180{
     181        lcddev_poll_wait();
     182
     183        if (cobt_is_5k() && has_i2c_lcd) {
     184                cobalt_i2c_write_byte(
     185                        COBALT_I2C_DEV_LCD_DATA | COBALT_I2C_WRITE, 0, data);
     186        } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) {
     187                outb(0x07, LCD_CONTROL_ADDRESS); /* RS=1, R/W=0, E=0 */
     188                outb(data, LCD_DATA_ADDRESS);
     189                outb(0x06, LCD_CONTROL_ADDRESS); /* RS=1, R/W=0, E=1 */
     190                outb(0x07, LCD_CONTROL_ADDRESS); /* RS=1, R/W=0, E=0 */
     191                outb(0x05, LCD_CONTROL_ADDRESS); /* RS=1, R/W=1, E=0 */
     192        }
     193        /* small delay */
     194        udelay(100);
     195}
     196
     197/* Read one byte of data from the LCD */
     198static inline unsigned char
     199lcddev_read_data(void)
     200{
     201        unsigned char a = 0;
     202
     203        lcddev_poll_wait();
     204
     205        if (cobt_is_5k() && has_i2c_lcd) {
     206                a = cobalt_i2c_read_byte(
     207                        COBALT_I2C_DEV_LCD_DATA | COBALT_I2C_READ, 0);
     208        } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) {
     209                outb(0x25, LCD_CONTROL_ADDRESS); /* RS=1, R/W=1, E=0 */
     210                outb(0x24, LCD_CONTROL_ADDRESS); /* RS=1, R/W=1, E=1 */
     211                a = inb(LCD_DATA_ADDRESS);
     212                outb(0x25, LCD_CONTROL_ADDRESS); /* RS=1, R/W=1, E=0 */
     213                outb(0x01, LCD_CONTROL_ADDRESS); /* RS=1, R/W=1, E=0 */
     214        }
     215
     216        /* small delay */
     217        udelay(100);
     218
     219        return a;
     220}
     221
     222static inline void
     223lcddev_init(void)
     224{
     225        lcddev_write_inst(0x38);
     226        lcddev_write_inst(0x38);
     227        lcddev_write_inst(0x38);
     228        lcddev_write_inst(0x06);
     229        lcddev_write_inst(0x0c);
     230}
     231
     232static inline char
     233read_buttons(void)
     234{
     235        char r = 0;
     236
     237        if (cobt_is_5k() && has_i2c_lcd) {
     238                unsigned char inst;
     239                inst = cobalt_i2c_read_byte(COBALT_I2C_DEV_FP_BUTTONS, 0);
     240                switch (inst) {
     241                        case 0x3e: r = BUTTON_Next_B; break;
     242                        case 0x3d: r = BUTTON_Enter_B; break;
     243                        case 0x1f: r = BUTTON_Left_B; break;
     244                        case 0x3b: r = BUTTON_Right_B; break;
     245                        case 0x2f: r = BUTTON_Up_B; break;
     246                        case 0x37: r = BUTTON_Down_B; break;
     247                        case 0x3f:
     248                        default: r = BUTTON_NONE_B;
     249                }
     250        } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) {
     251                outb(0x29, LCD_CONTROL_ADDRESS); /* Sel=0, Bi=1 */
     252                r = inb(LCD_DATA_ADDRESS) & BUTTON_MASK;
     253        }
     254       
     255        return r;
     256}
     257
     258static inline int
     259button_pressed(void)
     260{
     261        unsigned char b;
     262        unsigned long flags;
     263
     264        spin_lock_irqsave(&lcd_lock, flags);
     265        b = read_buttons();
     266        spin_unlock_irqrestore(&lcd_lock, flags);
     267
     268        switch (b) {
     269        case BUTTON_Next:
     270        case BUTTON_Next_B:
     271        case BUTTON_Reset_B:
     272                return b;
     273        default:
     274            break;
     275        }
     276
     277        return 0;
     278}
     279
     280/* this could be protected by CAP_RAW_IO here, or by the FS permissions */
     281static int
     282cobalt_lcd_ioctl(struct inode *inode, struct file *file,
     283        unsigned int cmd, unsigned long arg)
     284{
     285        struct lcd_display button_display, display;
     286        unsigned long address, a;
     287        int index;
     288        int dlen = sizeof(struct lcd_display);
     289        int r = 0;
     290        unsigned long flags;
     291
     292#ifdef CONFIG_COBALT_LCD_TWIDDLE
     293        cobalt_lcd_stop_twiddle();
     294#endif 
     295        switch (cmd) {
     296        /* Turn the LCD on */
     297        case LCD_On:
     298                spin_lock_irqsave(&lcd_lock, flags);
     299                lcddev_write_inst(0x0F);
     300                spin_unlock_irqrestore(&lcd_lock, flags);
     301                break;         
     302
     303        /* Turn the LCD off */
     304        case LCD_Off:
     305                spin_lock_irqsave(&lcd_lock, flags);
     306                lcddev_write_inst(0x08);
     307                spin_unlock_irqrestore(&lcd_lock, flags);
     308                break;
     309
     310        /* Reset the LCD */
     311        case LCD_Reset:
     312                spin_lock_irqsave(&lcd_lock, flags);
     313                lcddev_write_inst(0x3F);
     314                lcddev_write_inst(0x3F);
     315                lcddev_write_inst(0x3F);
     316                lcddev_write_inst(0x3F);
     317                lcddev_write_inst(0x01);
     318                lcddev_write_inst(0x06);
     319                spin_unlock_irqrestore(&lcd_lock, flags);
     320                break;
     321
     322        /* Clear the LCD */
     323        case LCD_Clear:
     324                spin_lock_irqsave(&lcd_lock, flags);
     325                lcddev_write_inst(0x01);
     326                spin_unlock_irqrestore(&lcd_lock, flags);
     327                break;
     328
     329        /* Move the cursor one position to the left */
     330        case LCD_Cursor_Left:
     331                spin_lock_irqsave(&lcd_lock, flags);
     332                lcddev_write_inst(0x10);
     333                spin_unlock_irqrestore(&lcd_lock, flags);
     334                break;
     335
     336        /* Move the cursor one position to the right */
     337        case LCD_Cursor_Right:
     338                spin_lock_irqsave(&lcd_lock, flags);
     339                lcddev_write_inst(0x14);
     340                spin_unlock_irqrestore(&lcd_lock, flags);
     341                break; 
     342
     343        /* Turn the cursor off */
     344        case LCD_Cursor_Off:
     345                spin_lock_irqsave(&lcd_lock, flags);
     346                lcddev_write_inst(0x0C);
     347                spin_unlock_irqrestore(&lcd_lock, flags);
     348                break;
     349
     350        /* Turn the cursor on */
     351        case LCD_Cursor_On:
     352                spin_lock_irqsave(&lcd_lock, flags);
     353                lcddev_write_inst(0x0F);
     354                spin_unlock_irqrestore(&lcd_lock, flags);
     355                break;
     356
     357        /* Turn blinking off? I don't know what this does - TJS */
     358        case LCD_Blink_Off:
     359                spin_lock_irqsave(&lcd_lock, flags);
     360                lcddev_write_inst(0x0E);
     361                spin_unlock_irqrestore(&lcd_lock, flags);
     362                break;
     363
     364        /* Get the current cursor position */
     365        case LCD_Get_Cursor_Pos:
     366                spin_lock_irqsave(&lcd_lock, flags);
     367                display.cursor_address = (unsigned char)lcddev_read_inst();
     368                display.cursor_address = display.cursor_address & 0x07F;
     369                spin_unlock_irqrestore(&lcd_lock, flags);
     370                if (copy_to_user((struct lcd_display *)arg, &display, dlen)) {
     371                        r = -EFAULT;
     372                }
     373                break;
     374
     375        /* Set the cursor position */
     376        case LCD_Set_Cursor_Pos:
     377                if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) {
     378                        r = -EFAULT;
     379                        break;
     380                }
     381                a = display.cursor_address | LCD_Addr;
     382                spin_lock_irqsave(&lcd_lock, flags);
     383                lcddev_write_inst(a);
     384                spin_unlock_irqrestore(&lcd_lock, flags);
     385                break;
     386
     387        /* Get the value at the current cursor position? - TJS */
     388        case LCD_Get_Cursor:
     389                spin_lock_irqsave(&lcd_lock, flags);
     390                display.character = lcddev_read_data();
     391                lcddev_write_inst(0x10);
     392                spin_unlock_irqrestore(&lcd_lock, flags);
     393                if (copy_to_user((struct lcd_display *)arg, &display, dlen)) {
     394                        r = -EFAULT;
     395                }
     396                break;
     397
     398        /* Set the character at the cursor position? - TJS */
     399        case LCD_Set_Cursor:
     400                if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) {
     401                        r = -EFAULT;
     402                        break;
     403                }
     404                spin_lock_irqsave(&lcd_lock, flags);
     405                lcddev_write_data(display.character);
     406                lcddev_write_inst(0x10);
     407                spin_unlock_irqrestore(&lcd_lock, flags);
     408                break;
     409
     410        /* Dunno what this does - TJS */
     411        case LCD_Disp_Left:
     412                spin_lock_irqsave(&lcd_lock, flags);
     413                lcddev_write_inst(0x18);
     414                spin_unlock_irqrestore(&lcd_lock, flags);
     415                break;
     416
     417        /* Dunno what this does - TJS */
     418        case LCD_Disp_Right:
     419                spin_lock_irqsave(&lcd_lock, flags);
     420                lcddev_write_inst(0x1C);
     421                spin_unlock_irqrestore(&lcd_lock, flags);
     422                break;
     423
     424        /* Dunno what this does - TJS */
     425        case LCD_Home:
     426                spin_lock_irqsave(&lcd_lock, flags);
     427                lcddev_write_inst(0x02);
     428                spin_unlock_irqrestore(&lcd_lock, flags);
     429                break;
     430
     431        /* Write a string to the LCD */
     432        case LCD_Write:
     433                if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) {
     434                        r = -EFAULT;
     435                        break;
     436                }
     437
     438                spin_lock_irqsave(&lcd_lock, flags);
     439
     440                display.size1 = display.size1 > 0 ?
     441                  min(display.size1, (int) sizeof(display.line1)) : 0;
     442                display.size2 = display.size2 > 0 ?
     443                  min(display.size2, (int) sizeof(display.line2)) : 0;
     444
     445                /* First line */
     446                lcddev_write_inst(0x80);
     447                for (index = 0; index < display.size1; index++)
     448                        lcddev_write_data(display.line1[index]);
     449                for (index = display.size1; index < sizeof(display.line1); index++)
     450                        lcddev_write_data(' ');
     451
     452                /* Second line */
     453                lcddev_write_inst(0xC0);       
     454                for (index = 0; index < display.size2; index++)
     455                        lcddev_write_data(display.line2[index]);
     456                for (index = display.size2; index < sizeof(display.line2); index++)
     457                        lcddev_write_data(' ');
     458
     459                spin_unlock_irqrestore(&lcd_lock, flags);
     460                break; 
     461
     462        /* Read what's on the LCD */
     463        case LCD_Read:
     464                spin_lock_irqsave(&lcd_lock, flags);
     465
     466                for (address = DD_R00; address <= DD_R01; address++) {
     467                        lcddev_write_inst(address | LCD_Addr);
     468                        display.line1[address] = lcddev_read_data();
     469                }
     470                for (address = DD_R10; address <= DD_R11; address++) {
     471                        lcddev_write_inst(address | LCD_Addr);
     472                        display.line2[address - DD_R10] = lcddev_read_data();
     473                }
     474
     475                spin_unlock_irqrestore(&lcd_lock, flags);
     476
     477                display.line1[DD_R01] = '\0';
     478                display.line2[DD_R01] = '\0';
     479
     480                if (copy_to_user((struct lcd_display *)arg, &display, dlen)) {
     481                        r = -EFAULT;
     482                }
     483                break;
     484
     485        case LCD_Raw_Inst:
     486                if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) {
     487                        r = -EFAULT;
     488                        break;
     489                }
     490                spin_lock_irqsave(&lcd_lock, flags);
     491                lcddev_write_inst(display.character);
     492                spin_unlock_irqrestore(&lcd_lock, flags);
     493                break;
     494
     495        case LCD_Raw_Data:
     496                if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) {
     497                        r = -EFAULT;
     498                        break;
     499                }
     500                spin_lock_irqsave(&lcd_lock, flags);
     501                lcddev_write_data(display.character);
     502                spin_unlock_irqrestore(&lcd_lock, flags);
     503                break;
     504
     505        case LCD_Type:
     506                if (cobt_is_5k() && has_i2c_lcd) {
     507                        if (put_user(LCD_TYPE_I2C, (int *)arg)) {
     508                                r = -EFAULT;
     509                        }
     510                } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) {
     511                        if (put_user(LCD_TYPE_PARALLEL_B, (int *)arg)) {
     512                                r = -EFAULT;
     513                        }
     514                }
     515                break;
     516               
     517        /* Read the buttons */
     518        case BUTTON_Read:
     519                spin_lock_irqsave(&lcd_lock, flags);
     520                button_display.buttons = read_buttons();
     521                spin_unlock_irqrestore(&lcd_lock, flags);
     522                if (copy_to_user((struct lcd_display *)arg,
     523                                &button_display, dlen)) {
     524                        r = -EFAULT;
     525                }
     526                break;
     527       
     528#ifdef CONFIG_COBALT_LED
     529        /* a slightly different api that allows you to set 32 leds */
     530        case LED32_Set:
     531                cobalt_led_set_lazy(arg);
     532                break;
     533
     534        case LED32_Bit_Set:
     535                cobalt_led_set_bits_lazy(arg);
     536                break;
     537
     538        case LED32_Bit_Clear:
     539                cobalt_led_clear_bits_lazy(arg);
     540                break;
     541
     542        case LED32_Get:
     543                *(unsigned int *)arg = cobalt_led_get();
     544                break;
     545
     546        /* set all the leds */
     547        case LED_Set:
     548                if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) {
     549                        r = -EFAULT;
     550                        break;
     551                }
     552                cobalt_led_set_lazy(display.leds);
     553                break;
     554
     555        /* set a single led */
     556        case LED_Bit_Set:
     557                if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) {
     558                        r = -EFAULT;
     559                        break;
     560                }
     561                cobalt_led_set_bits_lazy(display.leds);
     562                break;
     563
     564        /* clear an led */
     565        case LED_Bit_Clear:
     566                if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) {
     567                        r = -EFAULT;
     568                        break;
     569                }
     570                cobalt_led_clear_bits_lazy(display.leds);
     571                break;
     572#endif
     573
     574        default:
     575            break;
     576        }
     577
     578        return r;
     579}
     580
     581static int
     582cobalt_lcd_open(struct inode *inode, struct file *file)
     583{
     584        if (!lcd_present) {
     585                return -ENXIO;
     586        } else {
     587                return 0;
     588        }
     589}
     590
     591/* LCD daemon sits on this, we wake it up once a key is pressed */
     592static ssize_t
     593cobalt_lcd_read(struct file *file, char *buf, size_t count, loff_t *ppos)
     594{
     595        int bnow;
     596        static unsigned long lcd_waiters;
     597
     598        if (test_and_set_bit(0, &lcd_waiters)) {
     599                return -EINVAL;
     600        }
     601
     602        while (((bnow = button_pressed()) == 0) && !(signal_pending(current))) {
     603                if (file->f_flags & O_NONBLOCK) {
     604                        lcd_waiters = 0;
     605                        return -EAGAIN;
     606                }
     607                set_current_state(TASK_INTERRUPTIBLE);
     608                schedule_timeout(2 * HZ);
     609        }
     610        lcd_waiters = 0;
     611
     612        if (signal_pending(current)) {
     613                return -ERESTARTSYS;
     614        }
     615
     616        return bnow;
     617}
     618
     619/* read a single line from the LCD into a string */
     620static char *
     621cobalt_lcddev_read_line(int lineno, char *line)
     622{
     623        unsigned long addr, min, max;
     624        unsigned long flags;
     625       
     626        switch (lineno) {
     627        case 0:
     628                min = DD_R00;
     629                max = DD_R01;
     630                break;
     631        case 1:
     632                min = DD_R10;
     633                max = DD_R11;
     634                break;
     635        default:
     636                min = 1;
     637                max = 0;
     638        }
     639
     640        spin_lock_irqsave(&lcd_lock, flags);
     641        for (addr = min; addr <= max; addr++) {
     642                lcddev_write_inst(addr | LCD_Addr);
     643                udelay(150);
     644                line[addr-min] = lcddev_read_data();
     645                udelay(150);
     646        }
     647        spin_unlock_irqrestore(&lcd_lock, flags);
     648        line[addr-min] = '\0';
     649
     650        return line;
     651}
     652
     653#ifdef CONFIG_PROC_FS
     654static int
     655cobalt_lcd_read_proc(char *buf, char **start, off_t pos,
     656                                int len, int *eof, void *private)
     657{
     658        int plen = 0;
     659        char line[COBALT_LCD_LINELEN+1];
     660
     661        /* first line */
     662        cobalt_lcddev_read_line(0, line);
     663        plen += sprintf(buf+plen, "%s\n", line);
     664
     665        /* second line */
     666        cobalt_lcddev_read_line(1, line);
     667        plen += sprintf(buf+plen, "%s\n", line);
     668       
     669        return cobalt_gen_proc_read(buf, plen, start, pos, len, eof);
     670}
     671#endif
     672
     673static char *lcd_panic_str1 = "Kernel";
     674static char *lcd_panic_str2 = "Panic!";
     675
     676static int cobalt_lcd_panic(struct notifier_block *self, unsigned long a, void *b)
     677{
     678    int i;
     679    int len;
     680   
     681    if( !lcd_present )
     682        return 0;
     683   
     684#ifdef CONFIG_COBALT_LCD_TWIDDLE
     685    cobalt_lcd_stop_twiddle();
     686#endif
     687
     688    lcddev_write_inst( (DD_R00) | LCD_Addr);
     689    len = strlen( lcd_panic_str1 );
     690    for( i=0 ; i<16 ; i++ )
     691        lcddev_write_data( (i<len)?lcd_panic_str1[i]:' ' );
     692
     693    lcddev_write_inst( (DD_R10) | LCD_Addr);
     694    len = strlen( lcd_panic_str2 );
     695    for( i=0 ; i<16 ; i++ )
     696        lcddev_write_data( (i<len)?lcd_panic_str2[i]:' ' );
     697
     698    return 0;
     699}
     700
     701#ifdef CONFIG_COBALT_LCD_TWIDDLE
     702static struct timer_list twiddle_timer;
     703static int twiddling;
     704static void
     705twiddle_timer_func(unsigned long data)
     706{
     707        static int state=1;
     708        static int pos=0;
     709        unsigned long flags;
     710
     711        spin_lock_irqsave(&lcd_lock, flags);
     712
     713        lcddev_write_inst((DD_R10+4+pos) | LCD_Addr);
     714        lcddev_write_data(' ');
     715
     716        pos += state;
     717        if (pos < 0) {
     718                state = 1;
     719                pos = 1;
     720        }
     721        if (pos > 11) {
     722                state = -1;
     723                pos = 10;
     724        }
     725
     726        lcddev_write_inst((DD_R10+4+pos) | LCD_Addr);
     727        lcddev_write_data(0xff);
     728
     729        spin_unlock_irqrestore(&lcd_lock, flags);
     730
     731        mod_timer(&twiddle_timer, jiffies + TWIDDLE_HZ);
     732}
     733
     734void
     735cobalt_lcd_start_twiddle(void)
     736{
     737    init_timer(&twiddle_timer);
     738        twiddle_timer.expires = jiffies + TWIDDLE_HZ;
     739        twiddle_timer.data = 0;
     740        twiddle_timer.function = &twiddle_timer_func;
     741        add_timer(&twiddle_timer);
     742        twiddling=1;
     743}
     744
     745void
     746cobalt_lcd_stop_twiddle(void)
     747{
     748        unsigned long flags;
     749   
     750    spin_lock_irqsave(&lcd_lock, flags);
     751        if (twiddling) {
     752                del_timer_sync(&twiddle_timer);
     753                twiddling = 0;
     754        }
     755        spin_unlock_irqrestore(&lcd_lock, flags);
     756}
     757#endif /* CONFIG_COBALT_LCD_TWIDDLE */
     758
     759/* stop the lcd */
     760void cobalt_lcd_off(void)
     761{
     762        unsigned long flags;
     763
     764        spin_lock_irqsave(&lcd_lock, flags);
     765        lcddev_write_inst(0x01); /* clear */
     766        lcddev_write_inst(0x08); /* off */
     767        spin_unlock_irqrestore(&lcd_lock, flags);
     768}
     769
     770static int initialized;
     771static struct notifier_block lcd_nb;
     772
     773int __init
     774cobalt_lcd_init(void)
     775{       
     776    int retval;
     777   
     778        if (initialized)
     779                return 0;
     780
     781        initialized=1;
     782    printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", LCD_DRIVER,LCD_DRIVER_VMAJ,LCD_DRIVER_VMIN);
     783   
     784        if (disable_lcd) {
     785                printk(KERN_INFO "%s DISABLED\n", LCD_DRIVER);
     786                return 0;
     787        }
     788
     789    retval = misc_register(&lcd_dev);
     790       
     791        if (cobt_is_monterey()
     792         && (cobalt_i2c_read_byte(COBALT_I2C_DEV_LCD_INST, 0) != 0xff)) {
     793            printk(KERN_INFO "  - LCD is an I2C device\n");
     794                has_i2c_lcd = 1;
     795        } else {
     796                has_i2c_lcd = 0;
     797        }
     798
     799        /* flag ourselves as present */
     800        lcd_present = 1;
     801
     802        /* initialize the device */
     803        lcddev_init();
     804
     805#ifdef CONFIG_PROC_FS
     806#ifdef CONFIG_COBALT_OLDPROC
     807        /* create /proc/lcd */
     808        proc_lcd = create_proc_read_entry("lcd", S_IRUSR, NULL,
     809                cobalt_lcd_read_proc, NULL);
     810        if (!proc_lcd) {
     811                EPRINTK("can't create /proc/lcd\n");
     812        }
     813#endif
     814    proc_clcd = create_proc_read_entry("lcd", S_IRUSR, proc_cobalt,
     815                cobalt_lcd_read_proc, NULL);
     816        if (!proc_clcd) {
     817                EPRINTK("can't create /proc/cobalt/lcd\n");
     818        }
     819#endif
     820
     821#ifdef CONFIG_COBALT_LCD_TWIDDLE
     822        cobalt_lcd_start_twiddle();
     823#endif
     824
     825            /* register panic notifier */
     826        lcd_nb.notifier_call = cobalt_lcd_panic;
     827        lcd_nb.next = NULL;
     828        lcd_nb.priority = 0;
     829       
     830        atomic_notifier_chain_register( &panic_notifier_list, &lcd_nb );
     831
     832        return 0;
     833}
     834
     835#endif /* CONFIG_COBALT_LCD */
  • drivers/cobalt/led.c

    diff -Naur linux-2.6.20.orig/drivers/cobalt/led.c linux-2.6.20/drivers/cobalt/led.c
    old new  
     1 /*
     2 * $Id: led.c,v 1.36 2002/05/10 18:44:45 duncan Exp $
     3 * led.c : driver for Cobalt LEDs
     4 *
     5 * Copyright 1996-2000 Cobalt Networks, Inc.
     6 * Copyright 2001 Sun Microsystems, Inc.
     7 *
     8 * By:  Andrew Bose
     9 *      Timothy Stonis
     10 *      Tim Hockin
     11 *      Adrian Sun
     12 *      Duncan Laurie
     13 *
     14 * Modified By: jeff@404ster.com
     15 *
     16 * This should be SMP safe.  There is one definite critical region: the
     17 * handler list (led_handler_lock).  The led_state is protected by led_lock,
     18 * so should be safe against simultaneous writes.  Bit banging of lights is
     19 * currently also a protected region (led_lock, rather than add a new lock).
     20 */
     21
     22#include <linux/config.h>
     23
     24#ifdef CONFIG_COBALT_LED
     25
     26#include <linux/module.h>
     27#include <linux/types.h>
     28#include <linux/errno.h>
     29#include <linux/miscdevice.h>
     30#include <linux/slab.h>
     31#include <linux/ioport.h>
     32#include <linux/fcntl.h>
     33#include <linux/netdevice.h>
     34#include <linux/pci.h>
     35#include <linux/init.h>
     36#include <linux/timer.h>
     37#include <linux/nvram.h>
     38#include <asm/io.h>
     39#include <linux/delay.h>
     40
     41#include <cobalt/cobalt.h>
     42#include <cobalt/systype.h>
     43#include <cobalt/led.h>
     44#include <cobalt/i2c.h>
     45#include <cobalt/superio.h>
     46
     47#define LED_DRIVER                      "Cobalt Networks LED driver"
     48#define LED_DRIVER_VMAJ         1
     49#define LED_DRIVER_VMIN         0
     50
     51/* the rate at which software controlled frontpanel LEDs blink */
     52#define FPLED_DEFAULT_HZ        (HZ/20)
     53
     54/*
     55 * This is the abstracted state of active LEDs - see the defines for LED_*
     56 * LED masks are always 'unsigned int'.  You must hold led_lock to muck with
     57 * these.
     58 */
     59static unsigned int led_state;
     60static unsigned int led_blips;
     61
     62/* leds are PCI on genIII */
     63static struct pci_dev *led_dev;
     64/* on XTR the front panel LEDs are software controlled */
     65struct led_handler {
     66        unsigned int (*function)(void *);
     67        void *data;
     68        struct led_handler *next;
     69        struct led_handler *prev;
     70};
     71struct led_handler *led_handler_list;
     72static spinlock_t led_handler_lock = SPIN_LOCK_UNLOCKED;
     73static struct timer_list timer;
     74
     75static spinlock_t led_lock = SPIN_LOCK_UNLOCKED;
     76
     77/*
     78 * RaQ 3
     79 * RaQ 4
     80 * Qube 3
     81 */
     82#define RAQ3_SHUTLOGO_ADDR      0x7e
     83#define RAQ3_SHUTDOWN_OFF       0x40 /* reverse polarity */
     84#define RAQ3_COBALTLOGO_ON      0x80
     85#define QUBE3_LIGHTBAR_ON       0xc0 /* direct polarity */
     86#define RAQ3_WEBLIGHT_ADDR      0xb8
     87#define RAQ3_WEBLIGHT_ON        0x80
     88
     89/*
     90 * RaQ XTR
     91 */
     92#define MONTEREY_FPLED00                0x8000
     93#define MONTEREY_FPLED01                0x4000
     94#define MONTEREY_FPLED02                0x2000
     95#define MONTEREY_FPLED03                0x0200
     96#define MONTEREY_FPLED04                0x0080
     97#define MONTEREY_FPLED05                0x0040
     98#define MONTEREY_FPLED10                0x1000
     99#define MONTEREY_FPLED11                0x0800
     100#define MONTEREY_FPLED12                0x0400
     101#define MONTEREY_FPLED13                0x0100
     102#define MONTEREY_FPLED14                0x0020
     103#define MONTEREY_FPLED15                0x0010
     104#define MONTEREY_FPLED_ETH0_TXRX        MONTEREY_FPLED00
     105#define MONTEREY_FPLED_ETH0_LINK        MONTEREY_FPLED10
     106#define MONTEREY_FPLED_ETH1_TXRX        MONTEREY_FPLED01
     107#define MONTEREY_FPLED_ETH1_LINK        MONTEREY_FPLED11
     108#define MONTEREY_FPLED_DISK0            MONTEREY_FPLED02
     109#define MONTEREY_FPLED_DISK1            MONTEREY_FPLED03
     110#define MONTEREY_FPLED_DISK2            MONTEREY_FPLED04
     111#define MONTEREY_FPLED_DISK3            MONTEREY_FPLED05
     112#define MONTEREY_FPLED_WEB              MONTEREY_FPLED12
     113#define MONTEREY_LOGOLED_BIT            0x40
     114#define MONTEREY_SYSFAULTLED_BIT        0x80
     115#define MONTEREY_SLED0                  (1<<3)
     116#define MONTEREY_SLED1                  (1<<2)
     117#define MONTEREY_SLED2                  (1<<1)
     118#define MONTEREY_SLED3                  (1<<0)
     119
     120/*
     121 * Alpine
     122 */
     123#define ALPINE_WEBLED_PORT              0x60e
     124#define ALPINE_WEBLED_BIT               0x20
     125#define ALPINE_POWERLED_PORT            0x50b
     126#define ALPINE_POWERLED_CFG             0x23
     127#define ALPINE_LOGOLED_BIT              0x02
     128#define ALPINE_SYSFAULTLED_BIT          0x07
     129
     130/*
     131 * actually set the leds (icky details hidden within)
     132 * this must be protected against itself with led_lock
     133 * */
     134static void
     135__set_led_hw(const unsigned int newstate)
     136{
     137        if (cobt_is_pacifica() && led_dev) {
     138                unsigned char tmp;
     139                /* RaQ 3, RaQ 4
     140                 * - shutdown light
     141                 * - logo light
     142                 * - web light
     143                 */
     144
     145                /* read the current state of shutdown/logo lights */
     146                pci_read_config_byte(led_dev, RAQ3_SHUTLOGO_ADDR, &tmp);
     147
     148                /* reverse polarity for shutdown light */
     149                if (newstate & LED_SHUTDOWN)
     150                        tmp &= ~RAQ3_SHUTDOWN_OFF;
     151                else
     152                        tmp |= RAQ3_SHUTDOWN_OFF;
     153
     154                /* logo light is straight forward */
     155                if (newstate & LED_COBALTLOGO)
     156                        tmp |= RAQ3_COBALTLOGO_ON;
     157                else
     158                        tmp &= ~RAQ3_COBALTLOGO_ON;
     159
     160                /* write new shutdown/logo light state */
     161                pci_write_config_byte(led_dev, RAQ3_SHUTLOGO_ADDR, tmp);
     162
     163                /* read web light state */
     164                pci_read_config_byte(led_dev, RAQ3_WEBLIGHT_ADDR, &tmp);
     165                if (newstate & LED_WEBLIGHT) {
     166                        tmp |= RAQ3_WEBLIGHT_ON;
     167                } else {
     168                        tmp &= ~RAQ3_WEBLIGHT_ON;
     169                }
     170
     171                /* write new web light state */
     172                pci_write_config_byte(led_dev, RAQ3_WEBLIGHT_ADDR, tmp);
     173        } else if (cobt_is_carmel() && led_dev) {
     174                unsigned char tmp;
     175                /* Qube 3
     176                 * - no shutdown light
     177                 * - lightbar instead of logo
     178                 * - no web led (wired to 2nd IDE reset for staggered startup)
     179                 */
     180
     181                /* read the current state of lightbar */
     182                pci_read_config_byte(led_dev, RAQ3_SHUTLOGO_ADDR, &tmp);
     183                if (newstate & LED_COBALTLOGO) {
     184                        tmp |= QUBE3_LIGHTBAR_ON;
     185                } else {
     186                        tmp &= ~QUBE3_LIGHTBAR_ON;
     187                }
     188
     189                /* write new lightbar state */
     190                pci_write_config_byte(led_dev, RAQ3_SHUTLOGO_ADDR, tmp);
     191        } else if (cobt_is_monterey()) {
     192                unsigned int tmp = 0;
     193                u8 val;
     194                unsigned long flags;
     195
     196                if (newstate & LED_WEBLIGHT) {
     197                        tmp |= MONTEREY_FPLED_WEB;
     198                }
     199                if (newstate & LED_ETH0_TXRX) {
     200                        tmp |= MONTEREY_FPLED_ETH0_TXRX;
     201                }
     202                if (newstate & LED_ETH0_LINK) {
     203                        tmp |= MONTEREY_FPLED_ETH0_LINK;
     204                }
     205                if (newstate & LED_ETH1_TXRX) {
     206                        tmp |= MONTEREY_FPLED_ETH1_TXRX;
     207                }
     208                if (newstate & LED_ETH1_LINK) {
     209                        tmp |= MONTEREY_FPLED_ETH1_LINK;
     210                }
     211                if (newstate & LED_DISK0) {
     212                        tmp |= MONTEREY_FPLED_DISK0;
     213                }
     214                if (newstate & LED_DISK1) {
     215                        tmp |= MONTEREY_FPLED_DISK1;
     216                }
     217                if (newstate & LED_DISK2) {
     218                        tmp |= MONTEREY_FPLED_DISK2;
     219                }
     220                if (newstate & LED_DISK3) {
     221                        tmp |= MONTEREY_FPLED_DISK3;
     222                }
     223                /* 3 LED's are unused on Monterey, but we support them */
     224                if (newstate & LED_MONTEREY_UNUSED0) {
     225                        tmp |= MONTEREY_FPLED13;
     226                }
     227                if (newstate & LED_MONTEREY_UNUSED1) {
     228                        tmp |= MONTEREY_FPLED14;
     229                }
     230                if (newstate & LED_MONTEREY_UNUSED2) {
     231                        tmp |= MONTEREY_FPLED15;
     232                }
     233                /* I2C controlled front-panel lights */
     234                cobalt_i2c_write_byte(COBALT_I2C_DEV_LED_I, 0, tmp & 0xff);
     235                cobalt_i2c_write_byte(COBALT_I2C_DEV_LED_II, 0, tmp >> 8);
     236               
     237                /* drive sled LEDs are on a different i2c device */
     238                tmp = 0xf0; /* high nibble means something else */
     239                if (newstate * LED_SLED0)
     240                        tmp |= MONTEREY_SLED0;
     241                if (newstate * LED_SLED1)
     242                        tmp |= MONTEREY_SLED1;
     243                if (newstate * LED_SLED2)
     244                        tmp |= MONTEREY_SLED2;
     245                if (newstate * LED_SLED3)
     246                        tmp |= MONTEREY_SLED3;
     247                cobalt_i2c_write_byte(COBALT_I2C_DEV_RULER, 0, tmp);
     248
     249                /* sysfault and logo are in APC page of nvram */
     250                spin_lock_irqsave(&rtc_lock, flags);
     251                superio_set_rtc_bank(PC87317_RTC_BANK_APC);
     252                val = CMOS_READ(PC87317_APCR4);
     253
     254                /* reverse polarity */
     255                if (newstate & LED_COBALTLOGO) {
     256                        val &= ~MONTEREY_LOGOLED_BIT; /* logo is on */
     257                } else {
     258                        val |= MONTEREY_LOGOLED_BIT; /* logo is off */
     259                }
     260
     261                if (newstate & LED_SYSFAULT) {
     262                        val |= MONTEREY_SYSFAULTLED_BIT;
     263                } else {
     264                        val &= ~MONTEREY_SYSFAULTLED_BIT;
     265                }
     266
     267                CMOS_WRITE(val, PC87317_APCR4);
     268                superio_set_rtc_bank(PC87317_RTC_BANK_MAIN);
     269                spin_unlock_irqrestore(&rtc_lock, flags);
     270        } else if (cobt_is_alpine()) {
     271                unsigned char val;
     272           
     273                /* web LED is reverse polarity */
     274                val = inb(ALPINE_WEBLED_PORT);
     275                if (newstate & LED_WEBLIGHT) {
     276                        val &= ~ALPINE_WEBLED_BIT;
     277                } else {
     278                        val |= ALPINE_WEBLED_BIT;
     279                }
     280                outb(val, ALPINE_WEBLED_PORT);
     281
     282                    /*
     283                     * the power led is controled by switching the pin between
     284                     * a GPIO pin (on) and a LED pin (off)
     285                     */
     286
     287                outb( ALPINE_POWERLED_CFG, 0x2e );
     288                val = inb( 0x2f );
     289                if (newstate & LED_COBALTLOGO) {
     290                        val &= ~ALPINE_LOGOLED_BIT;
     291                } else {
     292                        val |= ALPINE_LOGOLED_BIT;     
     293                }
     294                outb( val, 0x2f );
     295
     296                if (newstate & LED_SYSFAULT) {
     297                    val = ALPINE_SYSFAULTLED_BIT;
     298                } else {
     299                    val = 0;
     300                }
     301
     302                outb(val, ALPINE_POWERLED_PORT);
     303        }
     304}
     305
     306/* blip the front panel leds */
     307static void
     308led_timer_func(unsigned long data)
     309{
     310        unsigned int leds = 0;
     311        struct led_handler *p;
     312        unsigned long flags;
     313
     314        /* call all registered callbacks */
     315        spin_lock_irqsave(&led_handler_lock, flags);
     316        for (p = led_handler_list; p; p = p->next) {
     317                leds |= p->function(p->data);
     318        }
     319        spin_unlock_irqrestore(&led_handler_lock, flags);
     320       
     321        /* set the led hardware */
     322        spin_lock_irqsave(&led_lock, flags);
     323        __set_led_hw(led_state | leds | led_blips);
     324        led_blips = 0;
     325        spin_unlock_irqrestore(&led_lock, flags);
     326
     327        /* re-arm ourself */
     328        mod_timer(&timer, jiffies + FPLED_DEFAULT_HZ);
     329}
     330
     331static void
     332__cobalt_led_set(const unsigned int leds)
     333{
     334        led_state = leds;
     335        __set_led_hw(leds);
     336}
     337
     338void
     339cobalt_led_set(const unsigned int leds)
     340{
     341        unsigned long flags;
     342        spin_lock_irqsave(&led_lock, flags);
     343        __cobalt_led_set(leds);
     344        spin_unlock_irqrestore(&led_lock, flags);
     345}
     346
     347void
     348cobalt_led_set_bits(const unsigned int leds)
     349{
     350        unsigned long flags;
     351        spin_lock_irqsave(&led_lock, flags);
     352        __cobalt_led_set(led_state | leds);
     353        spin_unlock_irqrestore(&led_lock, flags);
     354}
     355
     356void
     357cobalt_led_clear_bits(const unsigned int leds)
     358{
     359        unsigned long flags;
     360        spin_lock_irqsave(&led_lock, flags);
     361        __cobalt_led_set(led_state & ~leds);
     362        spin_unlock_irqrestore(&led_lock, flags);
     363}
     364
     365static void
     366__cobalt_led_set_lazy(const unsigned int leds)
     367{
     368        /* the next led timer run will catch these changes */
     369        led_state = leds;
     370        /* remember lights that were 'blipped' to force an edge */
     371        led_blips |= leds;
     372}
     373
     374void
     375cobalt_led_set_lazy(const unsigned int leds)
     376{
     377        unsigned long flags;
     378        spin_lock_irqsave(&led_lock, flags);
     379        __cobalt_led_set_lazy(leds);
     380        spin_unlock_irqrestore(&led_lock, flags);
     381}
     382
     383void
     384cobalt_led_set_bits_lazy(const unsigned int leds)
     385{
     386        unsigned long flags;
     387        spin_lock_irqsave(&led_lock, flags);
     388        __cobalt_led_set_lazy(led_state | leds);
     389        spin_unlock_irqrestore(&led_lock, flags);
     390}
     391
     392void
     393cobalt_led_clear_bits_lazy(const unsigned int leds)
     394{
     395        unsigned long flags;
     396        spin_lock_irqsave(&led_lock, flags);
     397        __cobalt_led_set_lazy(led_state & ~leds);
     398        spin_unlock_irqrestore(&led_lock, flags);
     399}
     400
     401unsigned int
     402cobalt_led_get(void)
     403{
     404        unsigned int r;
     405        unsigned long flags;
     406
     407        spin_lock_irqsave(&led_lock, flags);
     408        r = led_state;
     409        spin_unlock_irqrestore(&led_lock, flags);
     410
     411        return r;
     412}
     413
     414int
     415cobalt_fpled_register(unsigned int (*function)(void *), void *data)
     416{
     417        struct led_handler *newh;
     418        unsigned long flags;
     419
     420        newh = kmalloc(sizeof(*newh), GFP_ATOMIC);
     421        if (!newh) {
     422                EPRINTK("can't allocate memory for handler %p(%p)\n",
     423                        function, data);
     424                return -1;
     425        }
     426
     427        spin_lock_irqsave(&led_handler_lock, flags);
     428
     429        /* head insert */
     430        newh->function = function;
     431        newh->data = data;
     432        newh->next = led_handler_list;
     433        newh->prev = NULL;
     434        if (led_handler_list) {
     435                led_handler_list->prev = newh;
     436        }
     437        led_handler_list = newh;
     438       
     439        spin_unlock_irqrestore(&led_handler_lock, flags);
     440
     441        return 0;
     442}
     443
     444int
     445cobalt_fpled_unregister(unsigned int (*function)(void *), void *data)
     446{
     447        int r = -1;
     448        struct led_handler *p;
     449        unsigned long flags;
     450       
     451        spin_lock_irqsave(&led_handler_lock, flags);
     452
     453        for (p = led_handler_list; p; p = p->next) {
     454                if (p->function == function && p->data == data) {
     455                        if (p->prev) {
     456                                p->prev->next = p->next;
     457                        }
     458                        if (p->next) {
     459                                p->next->prev = p->prev;
     460                        }
     461                        r = 0;
     462                        break;
     463                }
     464        }
     465
     466        spin_unlock_irqrestore(&led_handler_lock, flags);
     467
     468        return r;
     469}
     470
     471int __init
     472cobalt_led_init(void)
     473{       
     474        unsigned int leds = LED_SHUTDOWN | LED_COBALTLOGO;
     475   
     476    printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", LED_DRIVER,LED_DRIVER_VMAJ,LED_DRIVER_VMIN);
     477
     478        if (cobt_is_3k()) {
     479                /* LEDs for RaQ3/4 and Qube3 are on the PMU */
     480                led_dev = pci_find_device(PCI_VENDOR_ID_AL,
     481                        PCI_DEVICE_ID_AL_M7101, NULL);
     482                if (!led_dev) {
     483                        EPRINTK("can't find PMU for LED control\n");
     484                        return -1;
     485                }
     486        }
     487       
     488        /* setup up timer for fp leds */
     489        init_timer(&timer);
     490        timer.expires = jiffies + FPLED_DEFAULT_HZ;
     491        timer.data = 0;
     492        timer.function = &led_timer_func;
     493        add_timer(&timer);
     494
     495        /* set the initial state */
     496        leds |= cobalt_cmos_read_flag(COBT_CMOS_SYSFAULT_FLAG) ?
     497                LED_SYSFAULT : 0;
     498        led_state = leds;
     499        __set_led_hw(leds);
     500
     501        return 0;
     502}
     503
     504#endif /* CONFIG_COBALT_LED */
  • drivers/cobalt/net.c

    diff -Naur linux-2.6.20.orig/drivers/cobalt/net.c linux-2.6.20/drivers/cobalt/net.c
    old new  
     1/*
     2 * cobalt net wrappers
     3 * Copyright (c) 2000, Cobalt Networks, Inc.
     4 * Copyright (c) 2001, Sun Microsystems, Inc.
     5 * $Id: net.c,v 1.11 2001/10/27 00:40:24 thockin Exp $
     6 * author: thockin@sun.com
     7 *
     8 * This should be SMP safe.  The only critical data is the list of devices.
     9 * The LED handler runs at timer-interrupt, so we must use the IRQ safe forms
     10 * of the locks. --TPH
     11 */
     12
     13#include <stdarg.h>
     14#include <stddef.h>
     15#include <linux/init.h>
     16#include <linux/config.h>
     17#include <linux/pci.h>
     18#include <linux/ioport.h>
     19#include <linux/netdevice.h>
     20#include <asm/io.h>
     21
     22#include <cobalt/cobalt.h>
     23#include <cobalt/net.h>
     24#include <cobalt/led.h>
     25
     26#define MAX_COBT_NETDEVS        2
     27static struct net_device *netdevs[MAX_COBT_NETDEVS];
     28static int n_netdevs;
     29static spinlock_t cobaltnet_lock = SPIN_LOCK_UNLOCKED;
     30
     31#if defined(CONFIG_COBALT_LED)
     32static unsigned int
     33net_led_handler(void *data)
     34{
     35        int i;
     36        unsigned int leds = 0;
     37        static int txrxmap[MAX_COBT_NETDEVS] = {LED_ETH0_TXRX, LED_ETH1_TXRX};
     38        static int linkmap[MAX_COBT_NETDEVS] = {LED_ETH0_LINK, LED_ETH1_LINK};
     39        unsigned long flags;
     40        static unsigned long net_old[MAX_COBT_NETDEVS];
     41
     42        spin_lock_irqsave(&cobaltnet_lock, flags);
     43
     44        for (i = 0; i < n_netdevs; i++) {
     45                unsigned long txrxstate;
     46                struct net_device *dev = netdevs[i];
     47                if (!dev) {
     48                        continue;
     49                }
     50                /* check for link */
     51                if (netif_running(dev) && netif_carrier_ok(dev)) {
     52                        leds |= linkmap[i];
     53                }
     54                /* check for tx/rx */
     55                txrxstate = dev->trans_start ^ dev->last_rx;
     56                if (txrxstate != net_old[i]) {
     57                        leds |= txrxmap[i];
     58                        net_old[i] = txrxstate;
     59                }
     60        }
     61
     62        spin_unlock_irqrestore(&cobaltnet_lock, flags);
     63
     64        return leds;
     65}
     66#endif
     67
     68/*
     69 * We try to be VERY explicit here.  Fine for now, may eventually break down.
     70 */
     71void
     72cobalt_net_register(struct net_device *ndev)
     73{
     74        unsigned long flags;
     75        int i;
     76       
     77        if (!ndev) {
     78                return;
     79        }
     80
     81        /* we'll track the first MAX_COBT_NETDEVS NICs */
     82        if (n_netdevs >= MAX_COBT_NETDEVS) {
     83                return;
     84        }
     85
     86        spin_lock_irqsave(&cobaltnet_lock, flags);
     87
     88        /* find a free slot */
     89        for (i = 0; i < MAX_COBT_NETDEVS; i++) {
     90                if (!netdevs[i]) {
     91                        netdevs[i] = ndev;
     92                        n_netdevs++;
     93                        break;
     94                }
     95        }
     96
     97        spin_unlock_irqrestore(&cobaltnet_lock, flags);
     98}
     99
     100void
     101cobalt_net_unregister(struct net_device *ndev)
     102{
     103        int i;
     104        unsigned long flags;
     105       
     106        if (!ndev) {
     107                return;
     108        }
     109
     110        spin_lock_irqsave(&cobaltnet_lock, flags);
     111
     112        /* try to remove it from the list */
     113        for (i = 0; i < MAX_COBT_NETDEVS; i++) {
     114                if (netdevs[i] == ndev) {
     115                        netdevs[i] = NULL;
     116                        n_netdevs--;
     117                        break;
     118                }
     119        }
     120
     121        spin_unlock_irqrestore(&cobaltnet_lock, flags);
     122}
     123
     124int __init
     125cobalt_net_init(void)
     126{
     127#if defined(CONFIG_COBALT_LED)
     128        /* register an LED handler */
     129        cobalt_fpled_register(net_led_handler, NULL);
     130#endif
     131
     132        return 0;
     133}
  • drivers/cobalt/raminfo.c

    diff -Naur linux-2.6.20.orig/drivers/cobalt/raminfo.c linux-2.6.20/drivers/cobalt/raminfo.c
    old new  
     1/* $Id: raminfo.c,v 1.7 2001/10/29 22:21:36 thockin Exp $
     2 *
     3 * Copyright (c) 2000-2001 Sun Microsystems, Inc.
     4 * All Rights Reserved.
     5 *
     6 * This is SMP safe - the init runs once on load, and the rest is just
     7 * printing information. --TPH
     8 */
     9#include <linux/config.h>
     10
     11#if defined(CONFIG_COBALT_RAMINFO) || defined(CONFIG_COBALT_RAMINFO_MODULE)
     12
     13#include <linux/module.h>
     14#include <linux/init.h>
     15#include <linux/pci.h>
     16#include <linux/proc_fs.h>
     17
     18#include <cobalt/cobalt.h>
     19#include <cobalt/systype.h>
     20
     21#define RAM_DRIVER                      "Cobalt Networks RAM Info driver"
     22#define RAM_DRIVER_VMAJ         1
     23#define RAM_DRIVER_VMIN         0
     24
     25#define MAX_DIMM_SLOTS  4
     26
     27enum dimm_t {
     28        DIMM_TYPE_FPM_DRAM,
     29        DIMM_TYPE_EDO_DRAM,
     30        DIMM_TYPE_REG_SDRAM,
     31        DIMM_TYPE_SDRAM
     32};
     33
     34static char *dimm_desc[] = {
     35        "Fast-page Mode DRAM",
     36        "EDO DRAM",
     37        "Registered SDRAM",
     38        "SDRAM",
     39};
     40
     41struct dimm_slot {
     42        int num;
     43        enum dimm_t type;
     44        uint16_t size;
     45        int ecc;
     46};
     47
     48struct raminfo {
     49        int total;
     50        int (*query)(struct dimm_slot *);
     51        struct pci_dev *dev;
     52        struct dimm_slot *dimm;
     53#ifdef CONFIG_PROC_FS
     54        struct proc_dir_entry *proc;
     55#endif /* CONFIG_PROC_FS */
     56};
     57
     58/*########################################################################*/
     59
     60static int serverworks_le_dimm_info(struct dimm_slot *);
     61static int ali_1541_dimm_info(struct dimm_slot *);
     62static int raminfo_read_proc(char*, char**, off_t, int, int*, void*);
     63
     64/* RaQ-3, RaQ-4, Qube-3
     65 * - uses ALI M1541 for memory controller
     66 * - has 2 dimm slots */
     67static struct raminfo gen3_raminfo = {
     68        total: 2,
     69        query: ali_1541_dimm_info
     70};
     71/* RaQ-XTR (Monterey)
     72 * - uses ServerWorks CNB30LE for Memory Controller
     73 * - has 4 dimm slots */
     74static struct raminfo gen5_monterey_raminfo = {
     75        total: 4,
     76        query: serverworks_le_dimm_info
     77};
     78/* RaQ (Alpine)
     79 * - uses ServerWorks CNB30LE for Memory Controller
     80 * - has 2 dimm slots */
     81static struct raminfo gen5_alpine_raminfo = {
     82        total: 2,
     83        query: serverworks_le_dimm_info
     84};
     85
     86static struct raminfo *sys_raminfo;
     87
     88/*########################################################################*/
     89
     90#define SERVERWORKS_DRAM_MRPR           (0x90)
     91#define SERVERWORKS_DRAM_MRAR(slot)     (0x7c + (slot))
     92#define SERVERWORKS_DRAM_ECCR           (0xe0)
     93
     94static int
     95serverworks_le_dimm_info(struct dimm_slot *dimm)
     96{
     97        int row;
     98        uint8_t rar, active, eccr;
     99        uint16_t ma_map[] = {
     100                32, 16, 32, 256, 512, 128, 128, 64, 256, 128, 64, 64, 128,
     101        };
     102
     103        if (!sys_raminfo || !sys_raminfo->dev || !dimm)
     104                return -ENOSYS;
     105
     106        pci_read_config_byte(sys_raminfo->dev,
     107                             SERVERWORKS_DRAM_MRPR, &active);
     108        pci_read_config_byte(sys_raminfo->dev,
     109                             SERVERWORKS_DRAM_MRAR(dimm->num), &rar);
     110
     111        /* serverworks uses only registered sdram */
     112        dimm->type = DIMM_TYPE_REG_SDRAM;
     113        dimm->size = 0;
     114
     115        /* check to see if ECC is enabled (bit 4 of reg 0xE0) */
     116        pci_read_config_byte(sys_raminfo->dev,
     117                             SERVERWORKS_DRAM_ECCR, &eccr);
     118        dimm->ecc = (eccr & (1<<2)) ? 1 : 0;
     119
     120        /* two rows for each dimm slot */
     121        for (row=2*dimm->num; row<=(2*dimm->num+1); row++) {
     122                /* each active row will have corresponding bit
     123                 * set in the Memory Row Presence Register */
     124                if (active & (1 << row)) {
     125                        /* lookup size ma_map table */
     126                        dimm->size += ma_map[ rar & 0xf ];
     127                }
     128                /* two rows per RAR register, bits 7-4 and bits 3-0 */
     129                rar >>= 4;
     130        }
     131
     132        return 0;
     133}
     134
     135#define ALI_DRAM_CONF_1(row)            (0x60 + ((row) * 2))
     136#define ALI_DRAM_CONF_2(row)            (0x61 + ((row) * 2))
     137#define ALI_DIMM_TYPE(d2)               (((d2) >> 4) & 0x3)
     138#define ALI_DIMM_MMAP(d2)               (((d2) >> 6) & 0x3)
     139#define ALI_DIMM_SIZE(d1, d2)           (((((d2) & 0xf) << 8) | (d1)) + 1)
     140
     141static int
     142ali_1541_dimm_info(struct dimm_slot *dimm)
     143{
     144        int row;
     145        uint8_t dbc1, dbc2;
     146
     147        if (!sys_raminfo || !sys_raminfo->dev || !dimm)
     148                return -ENOSYS;
     149
     150        dimm->size = 0;
     151        dimm->ecc  = 0;
     152
     153        /* read two rows per dimm (for double-side) */
     154        for (row=2*dimm->num; row<=(2*dimm->num + 1); row++) {
     155                pci_read_config_byte(sys_raminfo->dev,
     156                                     ALI_DRAM_CONF_2(row), &dbc2);
     157
     158                /* row is empty iff dimm type and ma_map are both 0 */
     159                if (!ALI_DIMM_TYPE(dbc2) && !ALI_DIMM_MMAP(dbc2))
     160                        continue;
     161
     162                pci_read_config_byte(sys_raminfo->dev,
     163                                     ALI_DRAM_CONF_1(row), &dbc1);
     164
     165                /* type is bits 4-5 of dimm conf reg 2 */
     166                dimm->type = ALI_DIMM_TYPE(dbc2);
     167
     168                /* A27-A20 address lines are bits 7-0 of dimm conf reg 1
     169                 * A31-A28 address lines are bits 3-0 of dimm conf reg 2 */
     170                dimm->size = ALI_DIMM_SIZE(dbc1, dbc2);
     171        }
     172
     173        /* the M1541 uses "not less than" policy to determine which row a
     174         * memory address resides in.  the top address boundary for each
     175         * row is the maximum memory value minus 1.  so to determine the
     176         * size of a row you must subtract the size of the previous row.
     177         * (unless this is slot 0 or the first populated slot) */
     178        if (dimm->num > 0 && dimm->size > 0) {
     179                uint16_t sz;
     180                pci_read_config_byte(sys_raminfo->dev,
     181                                     ALI_DRAM_CONF_1(2*dimm->num - 1), &dbc1);
     182                pci_read_config_byte(sys_raminfo->dev,
     183                                     ALI_DRAM_CONF_2(2*dimm->num - 1), &dbc2);
     184                sz = ALI_DIMM_SIZE(dbc1, dbc2);
     185                dimm->size -= (sz > 1) ? sz : 0;
     186        }
     187       
     188        return 0;
     189}
     190
     191int __init
     192cobalt_raminfo_init(void)
     193{
     194        int j;
     195
     196        /* determine system type and find memory controller pci dev
     197         * so we don't have to do pci lookup for each proc read */
     198        if (cobt_is_3k()) {
     199                sys_raminfo = &gen3_raminfo;
     200                sys_raminfo->dev = pci_find_device(PCI_VENDOR_ID_AL,
     201                                   PCI_DEVICE_ID_AL_M1541, NULL);
     202        } else if (cobt_is_5k()) {
     203                if (cobt_is_monterey()) {
     204                        sys_raminfo = &gen5_monterey_raminfo;
     205                } else if (cobt_is_alpine()) {
     206                        sys_raminfo = &gen5_alpine_raminfo;
     207                } else {
     208                        EPRINTK("unable to identify gen5 board\n");
     209                        return -ENOSYS;
     210                }
     211                sys_raminfo->dev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
     212                                   PCI_DEVICE_ID_SERVERWORKS_LE, NULL);
     213        }
     214
     215        if (!sys_raminfo || !sys_raminfo->dev) {
     216                EPRINTK("unable to identify system type\n");
     217                return -ENOSYS;
     218        }
     219       
     220        printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", RAM_DRIVER,RAM_DRIVER_VMAJ,RAM_DRIVER_VMIN);
     221
     222#ifdef CONFIG_PROC_FS
     223        /* add entry to /proc filesytem */
     224        sys_raminfo->proc = create_proc_entry("raminfo",
     225                            S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, proc_cobalt);
     226        if (!sys_raminfo->proc) {
     227                EPRINTK("can't create /proc/cobalt/raminfo\n");
     228                return -ENOENT;
     229        }
     230        sys_raminfo->proc->owner = THIS_MODULE;
     231        sys_raminfo->proc->write_proc = NULL;
     232        sys_raminfo->proc->read_proc = raminfo_read_proc;
     233#endif /* CONFIG_PROC_FS */
     234
     235        /* create arrary of dimm slots to store info */
     236        sys_raminfo->dimm = kmalloc(
     237                sys_raminfo->total * sizeof(struct dimm_slot), GFP_ATOMIC);
     238        if (!sys_raminfo->dimm) {
     239                EPRINTK("unable to allocate memory\n");
     240#ifdef CONFIG_PROC_FS
     241                if (sys_raminfo->proc) {
     242                        remove_proc_entry("raminfo", proc_cobalt);
     243                        sys_raminfo->proc = NULL;
     244                }
     245#endif /* CONFIG_PROC_FS */
     246                return -ENOMEM;
     247        }
     248
     249        {
     250                struct dimm_slot *ds = sys_raminfo->dimm;
     251                for (j=0; j<sys_raminfo->total; j++, ds++) {
     252                        if (!ds) continue;
     253                        ds->num = j;
     254                        if (sys_raminfo->query(ds) < 0) {
     255                                EPRINTK("unable to read dimm %d\n", j);
     256                                ds->num = -1;
     257                        }
     258                }
     259        }
     260
     261        return 0;
     262}
     263
     264static void __exit
     265cobalt_raminfo_exit(void)
     266{
     267#ifdef CONFIG_PROC_FS
     268        if (sys_raminfo->proc) {
     269                remove_proc_entry("raminfo", proc_cobalt);
     270                sys_raminfo->proc = NULL;
     271        }
     272#endif /* CONFIG_PROC_FS */
     273
     274        if (sys_raminfo->dimm) {
     275                kfree(sys_raminfo->dimm);
     276                sys_raminfo->dimm = NULL;
     277        }
     278
     279        sys_raminfo->dev = NULL;
     280        sys_raminfo = NULL;
     281}
     282
     283#ifdef CONFIG_PROC_FS
     284static int
     285raminfo_read_proc(char *buf, char **st, off_t off, int len, int *eof, void *x)
     286{
     287        int rlen, i;
     288        struct dimm_slot *ds;
     289
     290        if (!sys_raminfo)
     291                return -ENOSYS;
     292
     293        //MOD_INC_USE_COUNT;
     294
     295        ds = sys_raminfo->dimm;
     296        for (rlen=i=0; i<sys_raminfo->total; i++, ds++) {
     297                if (!ds || ds->num < 0)
     298                        continue;
     299                rlen += sprintf(buf+rlen, "%d [%s%s]: %u MB\n", i,
     300                                ds->size ? dimm_desc[ds->type] : "Empty",
     301                                ds->size ? ds->ecc ? "+ECC" : "" : "",
     302                                ds->size);
     303        }
     304
     305        //MOD_DEC_USE_COUNT;
     306
     307        return cobalt_gen_proc_read(buf, rlen, st, off, len, eof);
     308}
     309#endif /* CONFIG_PROC_FS */
     310
     311#ifdef CONFIG_COBALT_RAMINFO_MODULE
     312module_init(cobalt_raminfo_init);
     313module_exit(cobalt_raminfo_exit);
     314#endif
     315
     316MODULE_AUTHOR("Sun Cobalt");
     317MODULE_DESCRIPTION("DIMM Information");
     318MODULE_LICENSE("GPL");
     319
     320#endif /* CONFIG_COBALT_RAMINFO || CONFIG_COBALT_RAMINFO_MODULE */
  • drivers/cobalt/ruler.c

    diff -Naur linux-2.6.20.orig/drivers/cobalt/ruler.c linux-2.6.20/drivers/cobalt/ruler.c
    old new  
     1/*
     2 * cobalt ruler driver
     3 * Copyright (c) 2000, Cobalt Networks, Inc.
     4 * Copyright (c) 2001, Sun Microsystems, Inc.
     5 * $Id: ruler.c,v 1.23 2002/08/29 00:33:01 uzi Exp $
     6 *
     7 * author: asun@cobalt.com, thockin@sun.com
     8 *
     9 * This should be SMP safe.  There is one critical piece of data, and thus
     10 * one lock.  The ruler_lock protects the arrays of channels(hwifs) and
     11 * busproc function pointers.  These are only ever written in the
     12 * register/unregister functions but read in several other places.  A
     13 * read/write lock is appropriate. The global switches and sled_leds are
     14 * atomic_t. --TPH
     15 */
     16
     17#include <stdarg.h>
     18#include <stddef.h>
     19#include <linux/init.h>
     20#include <linux/sched.h>
     21#include <linux/timer.h>
     22#include <linux/config.h>
     23#include <linux/pci.h>
     24#include <linux/proc_fs.h>
     25#include <linux/sched.h>
     26#include <linux/ioport.h>
     27#include <linux/ide.h>
     28#include <linux/hdreg.h>
     29#include <linux/notifier.h>
     30#include <linux/sysctl.h>
     31#include <linux/reboot.h>
     32#include <linux/delay.h>
     33#include <linux/ide.h>
     34#include <asm/io.h>
     35
     36#include <cobalt/cobalt.h>
     37#include <cobalt/systype.h>
     38#include <cobalt/i2c.h>
     39#include <cobalt/acpi.h>
     40#include <cobalt/led.h>
     41#include <cobalt/ruler.h>
     42
     43#define RULER_TIMEOUT           (HZ >> 1)  /* .5s */
     44#define MAX_COBT_DRIVES         4
     45
     46#define RULER_DRIVER                    "Cobalt Networks Disk Ruler driver"
     47#define RULER_DRIVER_VMAJ               1
     48#define RULER_DRIVER_VMIN               0
     49
     50/* all of this is for gen V */
     51static struct timer_list cobalt_ruler_timer;
     52static rwlock_t ruler_lock = RW_LOCK_UNLOCKED;
     53static ide_drive_t *channels[MAX_COBT_DRIVES];
     54
     55static int (*busprocs[MAX_COBT_DRIVES])(ide_drive_t *, int);
     56
     57//static cob_busprocs_t busprocs[MAX_COBT_DRIVES];
     58
     59/* NOTE: switches is a bitmask of DETACHED sleds */
     60static atomic_t switches = ATOMIC_INIT(0);     
     61static atomic_t sled_leds = ATOMIC_INIT(0);
     62static int sled_led_map[] = {LED_SLED0, LED_SLED1, LED_SLED2, LED_SLED3};
     63static int ruler_detect;
     64static int initialized;
     65
     66static void ruler_hwif_added(ide_hwif_t *hwif, int idx);
     67
     68static inline u8
     69read_switches(void)
     70{
     71        u8 state = 0;
     72        if (cobt_is_monterey()) {
     73                int tries = 3;
     74
     75                /* i2c can be busy, and this can read wrong - try a few times */
     76                while (tries--) {
     77                        state = cobalt_i2c_read_byte(COBALT_I2C_DEV_DRV_SWITCH,
     78                                0);
     79                        if ((state & 0xf0) != 0xf0) {
     80                                break;
     81                        }
     82                }
     83        }
     84
     85        return state;
     86}
     87
     88static inline unsigned int
     89get_sled_leds(void)
     90{
     91        return atomic_read(&sled_leds);
     92}
     93
     94/*
     95 * deal with sled leds: LED on means OK to remove
     96 * NOTE: all the reset lines are kept high.
     97 * NOTE: the reset lines are in the reverse order of the switches.
     98 */
     99static void
     100set_sled_leds(unsigned int leds)
     101{
     102        if (cobt_is_monterey()) {
     103                unsigned int offed = get_sled_leds();
     104
     105                offed &= ~leds;
     106                atomic_set(&sled_leds, leds);
     107#ifdef CONFIG_COBALT_LED
     108                cobalt_led_clear_bits_lazy(offed);
     109                cobalt_led_set_bits_lazy(leds);
     110#endif
     111        }
     112}
     113
     114/* this must be called with the ruler_lock held for read */
     115static int
     116do_busproc(int idx, ide_drive_t *drive, int arg)
     117{
     118        if (cobt_is_monterey()) {
     119                /* sed sled LEDs */
     120                switch (arg) {
     121                        case BUSSTATE_ON:
     122                                set_sled_leds(get_sled_leds() &
     123                                        ~sled_led_map[idx]);
     124                                break;
     125                        case BUSSTATE_OFF:
     126                        case BUSSTATE_TRISTATE:
     127                                set_sled_leds(get_sled_leds() |
     128                                        sled_led_map[idx]);
     129                                break;
     130                        default:
     131                                WPRINTK("unknown busproc argument (%d)\n", arg);
     132                }
     133        }
     134
     135        /* do the real work */
     136        return busprocs[idx](drive, arg);
     137}
     138
     139static void
     140ruler_timer_fn(unsigned long data)
     141{
     142        if (cobt_is_monterey()) {
     143                u8 state;
     144                int i;
     145                unsigned int now, expected, bit, swcur;
     146
     147                state = read_switches();
     148                if ((state & 0xf0) == 0xf0) {
     149                        return;
     150                }
     151                swcur = atomic_read(&switches);
     152       
     153                state &= 0xf;
     154                read_lock(&ruler_lock);
     155                for (i = 0; i < MAX_COBT_DRIVES; i++) {
     156                        bit = 1 << i;
     157                        now = state & bit;
     158                        expected = swcur & bit;
     159                        if (now == expected) {
     160                                /* no changes to worry about */
     161                                continue;
     162                        }
     163
     164                        if (now) {
     165                                /* a freshly detached drive */
     166                                atomic_set(&switches, swcur | bit);
     167                                if (channels[i]) {
     168                                        printk("disabling ide ruler "
     169                                                "channel %d\n", i);
     170                                        do_busproc(i, channels[i],
     171                                                BUSSTATE_TRISTATE);
     172                                } else {
     173                                        WPRINTK("drive detach on bad "
     174                                                "channel (%d)\n", i);
     175                                }
     176                                set_sled_leds(get_sled_leds() |
     177                                        sled_led_map[i]);
     178                        } else {
     179                                /*
     180                                 * do we want to do anything when a re-attach
     181                                 * is detected?
     182                                 */
     183                        }
     184                }
     185                read_unlock(&ruler_lock);
     186        }
     187}
     188
     189#ifdef CONFIG_COBALT_ACPI
     190static int
     191ruler_interrupt(cobalt_acpi_evt *evt, void * data)
     192{
     193        if (cobt_is_monterey() && ruler_detect) {
     194                u8 state;
     195
     196                state = read_switches();
     197                if ((state & 0xf0) != 0xf0) {
     198                        /* this is protected inside mod_timer */
     199                        mod_timer(&cobalt_ruler_timer, jiffies + RULER_TIMEOUT);
     200                }
     201               
     202                evt->ev_data = state;
     203                /* empirical: delay enough to debounce */
     204                udelay(10);
     205        }
     206        return 0;
     207}
     208#endif /* CONFIG_COBALT_ACPI */
     209
     210#if defined(CONFIG_COBALT_LED)
     211/* figure which LEDs to blink */
     212static unsigned int
     213ide_led_handler(void *data)
     214{
     215        ide_hwif_t *hwif;
     216        unsigned int leds = 0;
     217
     218        if (cobt_is_monterey()) {
     219                int i;
     220                static int ledmap[MAX_COBT_DRIVES] = {
     221                        LED_DISK0, LED_DISK1, LED_DISK2, LED_DISK3
     222                };
     223                static unsigned long old[MAX_COBT_DRIVES];
     224
     225                read_lock(&ruler_lock);
     226
     227                for (i = 0; i < MAX_COBT_DRIVES; i++) {
     228                        if (channels[i])
     229                        {
     230                                hwif = HWIF(channels[i]);
     231                                if (hwif->drives[0].present &&
     232                                    hwif->drives[0].service_start != old[i]) {
     233                                        leds |= ledmap[i];
     234                                        old[i] = hwif->drives[0].service_start;
     235                                }
     236                        }
     237                }
     238
     239                read_unlock(&ruler_lock);
     240        }
     241
     242        return leds;
     243}
     244#endif
     245
     246/* this is essentially an exported function - it is in the hwif structs */
     247static int ruler_busproc_fn(ide_drive_t *drive, int arg)
     248{
     249        int r = 0;
     250        if (cobt_is_monterey()) {
     251                int idx;
     252
     253                read_lock(&ruler_lock);
     254
     255                for (idx = 0; idx < MAX_COBT_DRIVES; idx++) {
     256                        if (channels[idx] == drive) {
     257                                break;
     258                        }
     259                }
     260
     261                if (idx >= MAX_COBT_DRIVES) {
     262                        /* not a hwif we manage? */
     263                        return 0;
     264                }
     265
     266                r = do_busproc(idx, drive, arg);
     267                read_unlock(&ruler_lock);
     268        }
     269
     270        return r;
     271}
     272       
     273/*
     274 * We try to be VERY explicit here.  Fine for now, may eventually break down.
     275 */
     276void
     277cobalt_ruler_register(ide_drive_t *drive)
     278{
     279        ide_hwif_t *hwif = HWIF(drive);
     280
     281        if (cobt_is_monterey()) {
     282                struct pci_dev *dev;
     283                int idx;
     284                unsigned long flags;
     285
     286                if (!hwif) {
     287                        return;
     288                }
     289
     290                /* Cobalt rulers only have HPT370 controllers on bus 1 */
     291                dev = hwif->pci_dev;
     292                if (!dev)
     293                        return;
     294
     295                if (dev->vendor != PCI_VENDOR_ID_TTI
     296                 || dev->device != PCI_DEVICE_ID_TTI_HPT366
     297                 || dev->bus->number != 1) {
     298                        /* ignore it */
     299                        return;
     300                }
     301
     302                /* IDE ruler has controllers at dev 3 and 4, ONLY */
     303                if (dev->devfn == PCI_DEVFN(3,0)) {
     304                        idx = hwif->channel;
     305                } else if (dev->devfn == PCI_DEVFN(4,0)) {
     306                        idx = 2 + hwif->channel;
     307                } else {
     308                        return;
     309                }
     310
     311                if (idx >= MAX_COBT_DRIVES) {
     312                        return;
     313                }
     314
     315                write_lock_irqsave(&ruler_lock, flags);
     316
     317                /* save a pointer to the hwif, and trap it's busproc() */
     318                channels[idx] = drive;
     319                if (hwif->busproc) {
     320                        busprocs[idx] = HWIF(drive)->busproc;
     321                        hwif->busproc = &ruler_busproc_fn;
     322                }
     323
     324                write_unlock_irqrestore(&ruler_lock, flags);
     325
     326                /* now that we have trapped it, do what we need to initialize
     327                 * the drive - if we haven't been initialized, we'll call this
     328                 * later.
     329                 */
     330                if (initialized) {
     331                        ruler_hwif_added(hwif, idx);
     332                }
     333        }
     334}
     335
     336static void
     337ruler_hwif_added(ide_hwif_t *hwif, int idx)
     338{
     339        /* the associated switch should be closed */
     340        if (hwif->drives[0].present) {
     341                /* set the sled LED off - not safe to remove */
     342                set_sled_leds(get_sled_leds() & ~sled_led_map[idx]);
     343        }
     344}
     345
     346void cobalt_ruler_unregister(ide_drive_t *drive)
     347{
     348        if (cobt_is_monterey()) {
     349                int i;
     350                unsigned long flags;
     351
     352                write_lock_irqsave(&ruler_lock, flags);
     353
     354                for (i = 0; i < MAX_COBT_DRIVES; i++) {
     355                        if (channels[i] == drive) {
     356                                channels[i] = NULL;
     357                                HWIF(drive)->busproc = busprocs[i];
     358                                busprocs[i] = NULL;
     359                        }
     360                }
     361
     362                write_unlock_irqrestore(&ruler_lock, flags);
     363        }
     364}
     365
     366int __init
     367cobalt_ruler_init(void)
     368{
     369        if (cobt_is_monterey()) {
     370                int err;
     371                u8 tmp;
     372                int i;
     373
     374                /* initialize switches */
     375                tmp = read_switches();
     376                ruler_detect = ((tmp & 0xf0) == 0xf0) ? 0 : 1;
     377                tmp &= 0xf;
     378                atomic_set(&switches, tmp);
     379
     380                /* initialize our timer */
     381                init_timer(&cobalt_ruler_timer);
     382                cobalt_ruler_timer.function = ruler_timer_fn;
     383       
     384        printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", RULER_DRIVER,RULER_DRIVER_VMAJ,RULER_DRIVER_VMIN);
     385       
     386#ifdef CONFIG_COBALT_ACPI
     387                err = cobalt_acpi_register_evt_handler(ruler_interrupt,
     388                        COBALT_ACPI_EVT_SLED, NULL );
     389               
     390                if (err) {
     391                        EPRINTK("can't register interrupt handler %p\n",
     392                                ruler_interrupt);
     393                }
     394#endif
     395       
     396                /* set initial sled LED state */
     397                set_sled_leds(LED_SLED0 | LED_SLED1 | LED_SLED2 | LED_SLED3);
     398
     399                /* run through any devices that were registered before */
     400                for (i = 0; i < MAX_COBT_DRIVES; i++) {
     401                        if (channels[i]) {
     402                                ruler_hwif_added(HWIF(channels[i]), i);
     403                        }
     404                }
     405               
     406#if defined(CONFIG_COBALT_LED)
     407                /* register for a blinky LEDs callback */
     408                err = cobalt_fpled_register(ide_led_handler, NULL);
     409                if (err) {
     410                        EPRINTK("can't register LED handler %p\n",
     411                                ide_led_handler);
     412                }
     413#endif
     414        }
     415
     416        initialized = 1;
     417
     418        return 0;
     419}
  • drivers/cobalt/sensors.c

    diff -Naur linux-2.6.20.orig/drivers/cobalt/sensors.c linux-2.6.20/drivers/cobalt/sensors.c
    old new  
     1/* $Id: sensors.c,v 1.31 2002/08/29 00:33:01 uzi Exp $
     2 * Copyright (c) 2000-2001 Sun Microsystems, Inc
     3 *
     4 * This should be SMP safe.  There is just one race - the read in /proc.
     5 * It now guards against itself with a semaphore.  Note that we don't use a
     6 * spinlock because any of the methods may (and do!) block.
     7 */
     8#include <linux/config.h>
     9#ifdef CONFIG_COBALT_SENSORS
     10
     11#include <stdarg.h>
     12#include <stddef.h>
     13
     14#include <linux/init.h>
     15#include <linux/sched.h>
     16#include <linux/timer.h>
     17#include <linux/config.h>
     18#include <linux/delay.h>
     19#include <linux/ctype.h>
     20#include <linux/proc_fs.h>
     21
     22#include <asm/io.h>
     23#include <asm/uaccess.h>
     24
     25#include <cobalt/cobalt.h>
     26#include <cobalt/systype.h>
     27#include <cobalt/i2c.h>
     28#include <cobalt/sensors.h>
     29#include <cobalt/acpi.h>
     30
     31#define SENS_DRIVER                     "Cobalt Networks Sensor driver"
     32#define SENS_DRIVER_VMAJ                1
     33#define SENS_DRIVER_VMIN                0
     34
     35/* externals */
     36unsigned int cobalt_nthermals;
     37unsigned int cobalt_nvoltages;
     38
     39/* data about a sensor for generic handling */
     40/* we could add data about a low/high range, if needed */
     41struct sensor {
     42        int sensor; /* sensor #, so maps can be logically ordered */
     43        char *desc;
     44        int last_val;
     45        unsigned long cache;
     46        unsigned long cache_timeout;
     47        /* pre/post hook - 1 for pre, 0 for post */
     48        void (*setup)(struct sensor *s, int pre);
     49        /* read as an int, to be passed to format() */
     50        int (*read)(struct sensor *s);
     51        /* hook for scaling values */
     52        int (*scale)(struct sensor *s, int val);
     53        /* format the value as a string */
     54        char *(*format)(struct sensor *s, int val, char *buf, int len);
     55};
     56
     57/* some stuff for generic formatting */
     58#define DEC_SCALAR              100
     59static char *decimal_format(struct sensor *s, int val, char *buf, int len);
     60
     61static DECLARE_MUTEX(sensor_sem);
     62static struct sensor *therm_map;
     63static struct sensor *volt_map;
     64
     65#define CACHE_DEF               30
     66
     67#ifdef CONFIG_PROC_FS
     68static struct proc_dir_entry *proc_csensors;
     69static struct proc_dir_entry *proc_therm;
     70static struct proc_dir_entry *proc_volt;
     71static int therm_read_proc(char *buf, char **start, off_t pos, int len,
     72        int *eof, void *x);
     73static int therm_write_proc(struct file *file, const char *buf,
     74        unsigned long len, void *x);
     75static int volt_read_proc(char *buf, char **start, off_t pos, int len,
     76        int *eof, void *x);
     77static int volt_write_proc(struct file *file, const char *buf,
     78        unsigned long len, void *x);
     79#endif
     80
     81static int lm77_therm_read(struct sensor *s);
     82static int adm1029_init(void);
     83static int adm1029_therm_read(struct sensor *s);
     84static int adm1029_volt_read(struct sensor *s);
     85static int alpine_vcore_scale(struct sensor *s, int val);
     86static void alpine_vbat_switch(struct sensor *s, int pre);
     87static int alpine_vbat_scale(struct sensor *s, int val);
     88
     89/* sensor name mappings */
     90static struct sensor gen3_therm_map[] = {
     91        {0, "CPU", 0, 0, CACHE_DEF, NULL, lm77_therm_read, NULL, decimal_format},
     92};
     93static struct sensor monterey_therm_map[] = {
     94        {0, "CPU0", 0, 0, CACHE_DEF, NULL, lm77_therm_read, NULL, decimal_format},
     95        {1, "CPU1", 0, 0, CACHE_DEF, NULL, lm77_therm_read, NULL, decimal_format},
     96        {2, "Case0", 0, 0, CACHE_DEF, NULL, lm77_therm_read, NULL, decimal_format},
     97        {3, "Case1", 0, 0, CACHE_DEF, NULL, lm77_therm_read, NULL, decimal_format},
     98};
     99static struct sensor alpine_therm_map[] = {
     100        {1, "CPU", 0, 0, CACHE_DEF, NULL, adm1029_therm_read, NULL, decimal_format},
     101        {0, "Case", 0, 0, CACHE_DEF, NULL, adm1029_therm_read, NULL, decimal_format},
     102};
     103static struct sensor alpine_volt_map[] = {
     104        {0, "Vcore", 0, 0, CACHE_DEF, NULL, adm1029_volt_read,
     105                alpine_vcore_scale, decimal_format},
     106        {1, "Vtt", 0, 0, CACHE_DEF, NULL, adm1029_volt_read, NULL, decimal_format},
     107        {0, "Vbat", 0, 0, CACHE_DEF<<10, alpine_vbat_switch, adm1029_volt_read,
     108                alpine_vbat_scale, decimal_format},
     109};
     110
     111int __init
     112cobalt_sensors_init(void)
     113{
     114        if (cobt_is_3k()) {
     115                cobalt_nthermals = 1;
     116                cobalt_nvoltages = 0;
     117                therm_map = gen3_therm_map;
     118        } else if (cobt_is_monterey()) {
     119                cobalt_nthermals = 4;
     120                cobalt_nvoltages = 0;
     121                therm_map = monterey_therm_map;
     122        } else if (cobt_is_alpine()) {
     123                cobalt_nthermals = 2;
     124                cobalt_nvoltages = 3;
     125                therm_map = alpine_therm_map;
     126                volt_map = alpine_volt_map;
     127                adm1029_init();
     128        } else  {
     129                return -1;
     130        }
     131   
     132    printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", SENS_DRIVER,SENS_DRIVER_VMAJ,SENS_DRIVER_VMIN);
     133   
     134#ifdef CONFIG_PROC_FS
     135        /* make files in /proc */
     136        proc_csensors = proc_mkdir("sensors", proc_cobalt);
     137        if (!proc_csensors) {
     138                EPRINTK("can't create /proc/cobalt/sensors\n");
     139                return -1;
     140        }
     141        if (cobalt_nthermals) {
     142                proc_therm = create_proc_entry("thermal",
     143                                               S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
     144                                               proc_csensors);
     145                if (!proc_therm) {
     146                        EPRINTK("can't create /proc/cobalt/sensors/thermal\n");
     147                }
     148                proc_therm->read_proc = therm_read_proc;
     149                proc_therm->write_proc = therm_write_proc;
     150        }
     151        if (cobalt_nvoltages) {
     152                proc_volt = create_proc_entry("voltage",
     153                                              S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
     154                                              proc_csensors);
     155                if (!proc_volt) {
     156                        EPRINTK("can't create /proc/cobalt/sensors/voltage\n");
     157                }
     158                proc_volt->read_proc = volt_read_proc;
     159                proc_volt->write_proc = volt_write_proc;
     160
     161        }
     162#endif
     163
     164        return 0;
     165}
     166
     167static char *
     168sensor_read(struct sensor *s, char *buf, int len)
     169{
     170        int val;
     171
     172        if (s->cache && time_after(s->cache_timeout*HZ + s->cache, jiffies))
     173                val = s->last_val;
     174        else {
     175                if (s->setup) s->setup(s, 1);
     176                val = s->read(s);
     177                s->last_val = val;
     178                s->cache = jiffies;
     179                if (s->setup) s->setup(s, 0);
     180        }
     181               
     182        if (s->scale) val = s->scale(s, val);
     183        return s->format(s, val, buf, len);
     184}
     185
     186/* exported - nicer inline functions in header */
     187char *
     188__cobalt_thermal_read(unsigned int idx, char *buf, int len)
     189{
     190        if (idx >= cobalt_nthermals || !buf) {
     191                return NULL;
     192        }
     193
     194        return sensor_read(&therm_map[idx], buf, len);
     195}
     196
     197/* exported - nicer inline functions in header */
     198char *
     199__cobalt_voltage_read(unsigned int idx, char *buf, int len)
     200{
     201        if (idx >= cobalt_nvoltages || !buf) {
     202                return NULL;
     203        }
     204
     205        return sensor_read(&volt_map[idx], buf, len);
     206}
     207
     208/* generic function for formatting decimal scaled data */
     209static char *
     210decimal_format(struct sensor *s, int val, char *buf, int len)
     211{
     212        int plen;
     213       
     214        if (!buf || len <= 0) {
     215                return NULL;
     216        }
     217
     218        plen = snprintf(buf, len, "%d", val/DEC_SCALAR);
     219        len -= plen;
     220
     221        if (val % DEC_SCALAR && len > 0) {
     222                snprintf(buf+plen, len, ".%02d", val%DEC_SCALAR);
     223        }
     224
     225        return buf;
     226}
     227
     228#define LM77_TEMP               0x0
     229static int
     230lm77_therm_read(struct sensor *s)
     231{
     232        int sensor = s->sensor;
     233        int tmp;
     234        int val = 0;
     235        int tries = 2;
     236
     237        /* sometimes it reads as zero... try again */
     238        while (tries--) {
     239                /* LM77 returns the bytes backwards - <shrug> */
     240                /* address = base + deviceid + 1 for read */
     241                val = cobalt_i2c_read_word(COBALT_I2C_DEV_LM77 +
     242                        (sensor<<1) + 1, LM77_TEMP);
     243                if (val < 0) {
     244                        /* read failed, return the last known value */
     245                        return s->last_val;
     246                }
     247
     248                tmp = (val<<8 & 0xff00) + (val>>8 & 0x00ff);
     249                if (tmp) {
     250                        val = tmp >> 4;
     251                        val *= DEC_SCALAR;
     252                        if (tmp & 0x8) {
     253                                val += DEC_SCALAR/2;
     254                        }
     255                        break;
     256                }
     257        }
     258        return val;
     259}
     260
     261#define ADM1029_CTL_CFAULT_OVER         0x01
     262#define ADM1029_CTL_ALARM_OVER          0x02
     263#define ADM1029_CTL_INT_OVER            0x04
     264#define ADM1029_CTL_ALARM_LOW           0x08
     265#define ADM1029_CTL_CFAULT_UNDER        0x10
     266#define ADM1029_CTL_ALARM_UNDER         0x20
     267#define ADM1029_CTL_INT_UNDER           0x40
     268#define ADM1029_CTL_LATCH               0x80
     269
     270#define ADM1029_FAN_CTL(i)              (0x18 + i)
     271#define ADM1029_TEMP_CTL(i)             (0x40 + i)
     272#define ADM1029_AIN_CTL(i)              (0x50 + i)
     273
     274#define ADM1029_TEMP_HIGH(i)            (0x90 + i)
     275#define ADM1029_TEMP_LOW(i)             (0x98 + i)
     276#define ADM1029_AIN_HIGH(i)             (0xa8 + i)
     277#define ADM1029_AIN_LOW(i)              (0xb0 + i)
     278
     279#define ADM1029_TEMP_VALUE(i)           (0xa0 + i)
     280#define ADM1029_AIN_VALUE(i)            (0xb8 + i)
     281
     282#ifdef CONFIG_COBALT_ACPI
     283static int
     284adm1029_handler(cobalt_acpi_evt *evt, void * data)
     285{
     286        int j, k;
     287
     288        switch (evt->ev_type) {
     289        case COBALT_ACPI_EVT_SM_INT:
     290                evt->ev_data = 0;
     291                evt->ev_type = COBALT_ACPI_EVT_VOLT;
     292                for (j=0; j<cobalt_nvoltages; j++) {
     293                        k = cobalt_i2c_read_byte(COBALT_I2C_DEV_ADM1029,
     294                                 ADM1029_AIN_CTL(volt_map[j].sensor));
     295                        if (k & ADM1029_CTL_LATCH) {
     296                                evt->ev_data |= (1 << j);
     297                                volt_map[j].cache = 0;
     298                        }
     299                }
     300                break;
     301
     302        case COBALT_ACPI_EVT_THERM:
     303                evt->ev_data = 0;
     304                for (j=0; j<cobalt_nthermals; j++) {
     305                        k = cobalt_i2c_read_byte(COBALT_I2C_DEV_ADM1029,
     306                                 ADM1029_TEMP_CTL(therm_map[j].sensor));
     307                        if (k & ADM1029_CTL_LATCH) {
     308                                evt->ev_data |= (1 << j);
     309                                therm_map[j].cache = 0;
     310                        }
     311                }
     312                break;
     313
     314        default:
     315                return -1;
     316        }
     317        return 0;
     318}
     319#endif /* CONFIG_COBALT_ACPI */
     320
     321static int
     322adm1029_init(void)
     323{
     324
     325#ifdef CONFIG_COBALT_ACPI
     326        cobalt_acpi_register_evt_handler(adm1029_handler,
     327                COBALT_ACPI_EVT_THERM, NULL);
     328        cobalt_acpi_register_evt_handler(adm1029_handler,
     329                COBALT_ACPI_EVT_SM_INT, NULL);
     330#endif
     331
     332        return 0;
     333}
     334
     335static int
     336adm1029_therm_read(struct sensor *s)
     337{
     338        int sensor = s->sensor;
     339        int val;
     340
     341        val = cobalt_i2c_read_byte(COBALT_I2C_DEV_ADM1029,
     342                ADM1029_TEMP_VALUE(sensor));
     343        if (val < 0) {
     344                /* read failed, return the last known value */
     345                return s->last_val;
     346        }
     347        if (val & 0x80) {
     348                val -= 256;
     349        }
     350        val *= DEC_SCALAR;
     351
     352        return val;
     353}
     354
     355static int
     356adm1029_volt_read(struct sensor *s)
     357{
     358        int sensor = s->sensor;
     359        int val;
     360
     361        val = cobalt_i2c_read_byte(COBALT_I2C_DEV_ADM1029,
     362                ADM1029_AIN_VALUE(sensor));
     363        if (val < 0) {
     364                /* read failed, return the last known value */
     365                return s->last_val;
     366        }
     367       
     368        /* already scaled by 100 */
     369        val *= DEC_SCALAR/100;
     370
     371        return val;
     372}
     373
     374static int
     375alpine_vcore_scale(struct sensor *s, int val)
     376{
     377        /* the measured Vbat switch cost is negligable
     378         * due to very low current through the diode */
     379        return val;
     380}
     381
     382#define VBAT_REG        0x608
     383#define VBAT_BIT        0x1
     384static void
     385alpine_vbat_switch(struct sensor *s, int pre)
     386{
     387        unsigned char v = inb(VBAT_REG);
     388        unsigned long j = jiffies;
     389
     390        if (pre) {
     391                v |= VBAT_BIT;
     392                /*
     393                 * disable AIN0 INT# assertion before switching to
     394                 * Vbat because the input is shared with Vcore and
     395                 * their acceptable ranges are very different.
     396                 */
     397                cobalt_i2c_write_byte(COBALT_I2C_DEV_ADM1029,
     398                        ADM1029_AIN_CTL(s->sensor), 0x0);
     399        } else {
     400                v &= ~VBAT_BIT;
     401        }
     402
     403        outb(v, VBAT_REG);
     404
     405        /*
     406         * wait for the round-robin monitor to complete a cycle
     407         * before _and_ after toggling Vbat switch, otherwise
     408         * stale data in AIN0 will trigger INT# assertion.
     409         */
     410        while ((jiffies - j) < HZ) {
     411                /* block for ~ 1sec */
     412                set_current_state(TASK_INTERRUPTIBLE);
     413                schedule_timeout(HZ);
     414        }
     415
     416        if (!pre) {
     417                /*
     418                 * now re-enable INT# assertion capability for AIN0
     419                 * (this also clears the AIN0 fault latch at bit 7)
     420                 */
     421                cobalt_i2c_write_byte(COBALT_I2C_DEV_ADM1029,
     422                        ADM1029_AIN_CTL(s->sensor),
     423                        ADM1029_CTL_INT_OVER | ADM1029_CTL_INT_UNDER);
     424        }
     425}
     426
     427static int
     428alpine_vbat_scale(struct sensor *s, int val)
     429{
     430        /*
     431         * The spec says 2.5V max - but empirically, 3.3V works :)
     432         * The Vbat switch costs 0.3 volts
     433         */
     434        if (val) val += (3 * DEC_SCALAR)/10;
     435
     436        return val;
     437}
     438
     439#ifdef CONFIG_PROC_FS
     440static int
     441sensor_write_proc(int nsensors, struct sensor *map,
     442        struct file *file, const char *buf, unsigned long len, void *x)
     443{
     444        char *pg;
     445
     446        if (len > PAGE_SIZE) {
     447                return -EOVERFLOW;
     448        }
     449
     450        pg = (char *)__get_free_page(GFP_KERNEL);
     451        if (!pg) {
     452                return -ENOMEM;
     453        }
     454
     455        if (copy_from_user(pg, buf, len)) {
     456                free_page((unsigned long)pg);
     457                return -EFAULT;
     458        }
     459        pg[len] = '\0';
     460
     461        /* format: `cache_timeout #' in seconds */
     462        if (len>15 && !strncmp("cache_timeout ", pg, 14) && isdigit(*(pg+14))) {
     463                unsigned long i, sec = simple_strtoul(pg+14, NULL, 0);
     464                for (i=0; i<nsensors; i++)
     465                        map[i].cache_timeout = sec;
     466        }
     467
     468        free_page((unsigned long)pg);
     469        return len;
     470}
     471
     472static int
     473sensor_read_proc(int nsensors, struct sensor *map,
     474        char *buf, char **start, off_t pos, int len, int *eof, void *x)
     475{
     476        int i;
     477        static int plen = 0;
     478
     479        down(&sensor_sem);
     480
     481        /* remember how big our last read was to avoid read() calling twice */
     482        if (pos && pos >= plen) {
     483                *eof = 1;
     484                up(&sensor_sem);
     485                return 0;
     486        }
     487
     488        plen = 0;
     489        for (i = 0; i < nsensors; i++) {
     490                char sbuf[32];
     491                if (sensor_read(&map[i], sbuf, sizeof(sbuf)))
     492                        plen += sprintf(buf+plen, "%d [%s]: %s\n", i, map[i].desc, sbuf);
     493        }
     494
     495        up(&sensor_sem);
     496
     497        return cobalt_gen_proc_read(buf, plen, start, pos, len, eof);
     498}
     499
     500static int
     501therm_read_proc(char *buf, char **start, off_t pos, int len, int *eof, void *x)
     502{
     503        return sensor_read_proc(cobalt_nthermals, therm_map,
     504                buf, start, pos, len, eof, x);
     505}
     506static int
     507therm_write_proc(struct file *file, const char *buf, unsigned long len, void *x)
     508{
     509        return sensor_write_proc(cobalt_nthermals, therm_map, file, buf, len, x);
     510}
     511
     512static int
     513volt_read_proc(char *buf, char **start, off_t pos, int len, int *eof, void *x)
     514{
     515        return sensor_read_proc(cobalt_nvoltages, volt_map,
     516                buf, start, pos, len, eof, x);
     517}
     518static int
     519volt_write_proc(struct file *file, const char *buf, unsigned long len, void *x)
     520{
     521        return sensor_write_proc(cobalt_nvoltages, volt_map, file, buf, len, x);
     522}
     523#endif /* CONFIG_PROC_FS */
     524
     525#endif /* CONFIG_COBALT_SENSORS */
  • drivers/cobalt/serialnum.c

    diff -Naur linux-2.6.20.orig/drivers/cobalt/serialnum.c linux-2.6.20/drivers/cobalt/serialnum.c
    old new  
     1/* $Id: serialnum.c,v 1.15 2001/10/23 20:15:27 thockin Exp $ */
     2/*
     3 *
     4 *   Author: Philip Gladstone, Axent Technologies
     5 *           modified for Nat Semi PC[89]7317 by asun@cobalt.com
     6 *           ported to 2.4.x by thockin@sun.com
     7 *           alpine serial eeprom by erik.glling@sun.com
     8 *   Copyright (c) 2000  Axent Technologies, Cobalt Networks
     9 *   Copyright (c) 2001  Axent Technologies, Sun Microsystems
     10 *
     11 *   This module interrogates the DS2401 Silicon Serial Number chip
     12 *   that is attached to all x86 Cobalt systems.
     13 *
     14 *   It exports /proc/cobalt/hostid which is four bytes generated from of
     15 *   the id. It can be linked to /var/adm/hostid or /etc/hostid for the
     16 *   hostid command to use.
     17 *
     18 *   It exports /proc/cobalt/serialnumber which is the entire 64 bit value
     19 *   read back (in ascii).
     20 *
     21 *   For the guts of the 1 wire protocol used herein, please see the DS2401
     22 *   specification.
     23 *
     24 *   This program is free software; you can redistribute it and/or modify
     25 *   it under the terms of the GNU General Public License as published by
     26 *   the Free Software Foundation; either version 2 of the License, or
     27 *   (at your option) any later version.
     28 *
     29 *   This program is distributed in the hope that it will be useful,
     30 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
     31 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     32 *   GNU General Public License for more details.
     33 *
     34 *   You should have received a copy of the GNU General Public License
     35 *   along with this program; if not, write to the Free Software
     36 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     37 *
     38 * This driver is SMP safe by nature. --TPH
     39 */
     40#include <linux/config.h>
     41#if defined (CONFIG_COBALT_SERNUM) || defined(CONFIG_COBALT_SERNUM_MODULE)
     42
     43#include <linux/module.h>
     44#include <linux/stddef.h>
     45#include <linux/version.h>
     46#include <linux/types.h>
     47#include <linux/proc_fs.h>
     48#include <linux/delay.h>
     49#include <asm/uaccess.h>
     50#include <linux/pci.h>
     51#include <linux/init.h>
     52#include <asm/io.h>
     53
     54#include <cobalt/cobalt.h>
     55#include <cobalt/systype.h>
     56#include <cobalt/superio.h>
     57#include <cobalt/serialnum.h>
     58#include <cobalt/i2c.h>
     59
     60#include <linux/interrupt.h>
     61
     62#define SN_DRIVER                       "Cobalt Networks Serial Number driver"
     63#define SN_DRIVER_VMAJ          1
     64#define SN_DRIVER_VMIN          6
     65
     66/* dependent on systype */
     67static unsigned int sn_direction;
     68static unsigned int sn_output;
     69static unsigned int sn_input;
     70static unsigned int sn_mask;
     71
     72/* 3k style systems */
     73#define III_SN_DIRECTION        0x7d
     74#define III_SN_OUTPUT           0x7e
     75#define III_SN_INPUT            0x7f
     76#define III_SN_MASK             0x08
     77static struct pci_dev *id_dev;
     78
     79/* 5k style systems */
     80#define V_SN_DIRECTION          (sn_io_base + 0x01)
     81#define V_SN_OUTPUT             (sn_io_base + 0x00)
     82#define V_SN_INPUT              (sn_io_base + 0x00)
     83#define V_SN_MASK               (sn_io_base + 0x01)
     84static unsigned int sn_io_base;
     85
     86#define SSN_SIZE        8       /* bytes */
     87static char ssn_string[SSN_SIZE * 2 + 1];
     88static unsigned long hostid;
     89static int debug;
     90#ifdef CONFIG_PROC_FS
     91#ifdef CONFIG_COBALT_OLDPROC
     92static struct proc_dir_entry *proc_hostid;
     93static struct proc_dir_entry *proc_serialnum;
     94#endif
     95static struct proc_dir_entry *proc_chostid;
     96static struct proc_dir_entry *proc_cserialnum;
     97#endif
     98
     99static int
     100hostid_read(char *buf, char **start, off_t pos, int len, int *eof, void *x)
     101{
     102        int plen = sizeof(hostid);
     103        memcpy(buf, &hostid, sizeof(hostid));
     104        return cobalt_gen_proc_read(buf, plen, start, pos, len, eof);
     105}
     106
     107static int
     108serialnum_read(char *buf, char **start, off_t pos, int len, int *eof, void *x)
     109{
     110        int plen = sizeof(ssn_string);
     111        sprintf(buf, "%s\n", ssn_string);
     112        return cobalt_gen_proc_read(buf, plen, start, pos, len, eof);
     113}
     114
     115/* set up the requisite IO bits */
     116static int __init
     117io_init(void)
     118{
     119        unsigned char data;
     120
     121        if (cobt_is_3k()) {
     122                /* The GPIO tied to the ID chip is on the PMU */
     123                id_dev = pci_find_device(PCI_VENDOR_ID_AL,
     124                        PCI_DEVICE_ID_AL_M7101, NULL);
     125                if (!id_dev) {
     126                        EPRINTK("can't find PMU for serialnumber access\n");
     127                        return -ENXIO;
     128                }
     129
     130                /* Set input mode on GPIO3 */
     131                pci_read_config_byte(id_dev, sn_direction, &data);
     132                if (debug > 1) {
     133                        WPRINTK("read of register 0x%x = 0x%x\n",
     134                                sn_direction, data);
     135                }
     136                if (data & sn_mask) {
     137                        pci_write_config_byte(id_dev, sn_direction,
     138                                data & ~sn_mask);
     139                }
     140
     141                /* Set the output value to be 0 */
     142                pci_read_config_byte(id_dev, sn_output, &data);
     143                if (debug > 1) {
     144                        WPRINTK("read of register 0x%x = 0x%x\n",
     145                                sn_output, data);
     146                }
     147                if (data & sn_mask) {
     148                        pci_write_config_byte(id_dev, sn_output,
     149                                data & ~sn_mask);
     150                }
     151        } else if (cobt_is_5k()) {
     152                u16 addr;
     153
     154                addr = superio_ldev_base(PC87317_DEV_GPIO);
     155                if (addr) {
     156                        u8 val;
     157
     158                        sn_io_base = addr;
     159
     160                        /* set output value to 0 */
     161                        val = inb(sn_direction);
     162                        outb(val | sn_mask, sn_direction);
     163                        data = inb(sn_output);
     164                        if (data & sn_mask) {
     165                                outb(data & ~sn_mask, sn_output);
     166                        }
     167                        /* set to input */
     168                        outb(val & ~sn_mask, sn_direction);
     169                }
     170        } else {
     171                return -ENXIO;
     172        }
     173
     174        /* pick proper variables */
     175        if (cobt_is_3k()) {
     176                sn_direction = III_SN_DIRECTION;
     177                sn_output = III_SN_OUTPUT;
     178                sn_input = III_SN_INPUT;
     179                sn_mask = III_SN_MASK;
     180        } else if (cobt_is_5k()) {
     181                sn_direction = V_SN_DIRECTION;
     182                sn_output = V_SN_OUTPUT;
     183                sn_input = V_SN_INPUT;
     184                sn_mask = V_SN_MASK;
     185        } else {
     186                return -1;
     187        }
     188
     189        /* Let things calm down */
     190        udelay(500);
     191        return 0;
     192}
     193
     194/* write out a bit */
     195static void __init
     196io_write(int delay)
     197{
     198        if (cobt_is_3k()) {
     199                unsigned char data;
     200                /* Set output mode on GPIO3 */
     201                pci_read_config_byte(id_dev, sn_direction, &data);
     202                pci_write_config_byte(id_dev, sn_direction, data | sn_mask);
     203                udelay(delay);
     204
     205                /* Set input mode */
     206                pci_write_config_byte(id_dev, sn_direction, data & ~sn_mask);
     207        } else if (cobt_is_5k()) {
     208                unsigned char direction;
     209
     210                /* change to output and back */
     211                direction = inb(sn_direction);
     212                outb(direction | sn_mask, sn_direction);
     213                udelay(delay);
     214                outb(direction & ~sn_mask, sn_direction);
     215        }
     216}
     217
     218/* read in a bit */
     219static int __init
     220io_read(void)
     221{
     222        unsigned char data = 0;
     223
     224        /* Get the input value */
     225        if (cobt_is_3k()) {
     226                pci_read_config_byte(id_dev, sn_input, &data);
     227        } else if (cobt_is_5k()) {
     228                data = inb(sn_input);
     229        }
     230
     231        return (data & sn_mask) ? 1 : 0;
     232}
     233
     234static void __init
     235io_write_byte(unsigned char c)
     236{
     237        int i;
     238        unsigned long flags;
     239
     240        local_save_flags(flags);
     241
     242        for (i = 0; i < 8; i++, c >>= 1) {
     243                local_irq_disable();
     244                if (c & 1) {
     245                        /* Transmit a 1 */
     246                        io_write(5);
     247                        udelay(80);
     248                } else {
     249                        /* Transmit a 0 */
     250                        io_write(80);
     251                        udelay(10);
     252                }
     253                local_irq_restore(flags);
     254        }
     255}
     256
     257static int __init
     258io_read_byte(void)
     259{
     260        int i;
     261        int c = 0;
     262        unsigned long flags;
     263
     264        local_save_flags(flags);
     265
     266        for (i = 0; i < 8; i++) {
     267                local_irq_disable();
     268                io_write(1);    /* Start the read */
     269                udelay(2);
     270                if (io_read()) {
     271                        c |= 1 << i;
     272                }
     273                udelay(60);
     274                local_irq_restore(flags);
     275        }
     276
     277        return c;
     278}
     279
     280static int __init
     281get_ssn(unsigned char *buf)
     282{
     283        int i;
     284        unsigned long flags;
     285
     286        /*
     287         * Alpine does not have a dallas chip.  Instead
     288         * we read from an eprom.
     289         */
     290        if (cobt_is_alpine()) {
     291                for (i = 0; i < 8; i++) {
     292                        buf[i] = cobalt_i2c_read_byte(COBALT_I2C_DEV_AT24C02,
     293                                12 + i);
     294                }
     295                return 0;
     296        }
     297
     298        /*
     299         * bit-bang the Dallas 2401
     300         */
     301
     302        local_save_flags(flags);
     303        local_irq_disable();
     304
     305        /* Master Reset Pulse */
     306        for (i = 0; i < 600; i += 30) {
     307                if (io_read()) {
     308                        break;
     309                }
     310        }
     311
     312        if (i >= 600) {
     313                if (debug) {
     314                        EPRINTK("the data line seems to be held low\n");
     315                }
     316                local_irq_restore(flags);
     317                return -ENXIO;
     318        }
     319
     320        io_write(600);
     321
     322        for (i = 0; i < 300; i += 15) {
     323                udelay(15);
     324                if (io_read() == 0) {
     325                        /* We got a presence pulse */
     326                        udelay(600);    /* Wait for things to quiet down */
     327                        break;
     328                }
     329        }
     330        local_irq_restore(flags);
     331
     332        if (i >= 300) {
     333                if (debug)
     334                        EPRINTK("no presence pulse detected\n");
     335                return -ENXIO;
     336        }
     337
     338        io_write_byte(0x33);
     339
     340        for (i = 0; i < 8; i++) {
     341                int rc;
     342
     343                rc = io_read_byte();
     344                if (rc < 0) {
     345                        return rc;
     346                }
     347
     348                *buf++ = rc;
     349        }
     350
     351        return 0;
     352}
     353
     354int __init
     355cobalt_serialnum_init(void)
     356{
     357        unsigned char ssn[SSN_SIZE];
     358        int rc;
     359        int i;
     360
     361    printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", SN_DRIVER,SN_DRIVER_VMAJ,SN_DRIVER_VMIN);
     362        /* set up for proper IO */
     363        rc = io_init();
     364        if (rc) {
     365                return rc;
     366        }
     367
     368        /*
     369         * NOTE: the below algorithm CAN NOT be changed.  We have many systems
     370         * out there registered with the serial number AS DERIVED by this
     371         * algorithm.
     372         */
     373
     374        rc = get_ssn(ssn);
     375        if (rc) {
     376                return rc;
     377        }
     378
     379        /* Convert to ssn_string */
     380        for (i = 7; i >= 0; i--) {
     381                sprintf(ssn_string + (7 - i) * 2, "%02x", ssn[i]);
     382        }
     383
     384        /* get four bytes for a pretty unique (not guaranteed) hostid */
     385        hostid = *(unsigned long *)ssn ^ *(unsigned long *)(ssn+4);
     386
     387#ifdef CONFIG_PROC_FS
     388#ifdef CONFIG_COBALT_OLDPROC
     389        proc_hostid = create_proc_read_entry("hostid", 0, NULL,
     390                hostid_read, NULL);
     391        if (!proc_hostid) {
     392                EPRINTK("can't create /proc/hostid\n");
     393        }
     394        proc_serialnum = create_proc_read_entry("serialnumber", 0, NULL,
     395                serialnum_read, NULL);
     396        if (!proc_serialnum) {
     397                EPRINTK("can't create /proc/serialnumber\n");
     398        }
     399#endif
     400        proc_chostid = create_proc_read_entry("hostid", 0, proc_cobalt,
     401                hostid_read, NULL);
     402        if (!proc_chostid) {
     403                EPRINTK("can't create /proc/cobalt/hostid\n");
     404        }
     405        proc_cserialnum = create_proc_read_entry("serialnumber", 0,
     406                proc_cobalt, serialnum_read, NULL);
     407        if (!proc_cserialnum) {
     408                EPRINTK("can't create /proc/cobalt/serialnumber\n");
     409        }
     410#endif
     411
     412        return 0;
     413}
     414
     415char *
     416cobalt_serialnum_get(void)
     417{
     418        return ssn_string;
     419}
     420
     421unsigned long
     422cobalt_hostid_get(void)
     423{
     424        return hostid;
     425}
     426
     427#if defined(CONFIG_COBALT_SERNUM_MODULE)
     428MODULE_PARM(debug, "i");
     429
     430int
     431init_module(void)
     432{
     433        return cobalt_serialnum_init();
     434}
     435
     436void
     437cleanup_module(void)
     438{
     439#ifdef CONFIG_PROC_FS
     440#ifdef CONFIG_COBALT_OLDPROC
     441        remove_proc_entry("hostid", NULL);
     442        remove_proc_entry("serialnumber", NULL);
     443#endif
     444        remove_proc_entry("hostid", proc_cobalt);
     445        remove_proc_entry("serialnumber", proc_cobalt);
     446#endif
     447}
     448
     449module_init(init_module);
     450module_exit(cleanup_module);
     451#endif /* MODULE */
     452
     453#endif /* CONFIG_COBALT_SERNUM */
  • drivers/cobalt/systype.c

    diff -Naur linux-2.6.20.orig/drivers/cobalt/systype.c linux-2.6.20/drivers/cobalt/systype.c
    old new  
     1/*
     2 * $Id: systype.c,v 1.33 2002/11/04 17:54:15 thockin Exp $
     3 * systype.c : routines for figuring out which Cobalt system this is
     4 *
     5 * Copyright 2001-2002 Sun Microsystems, Inc.
     6 *
     7 * By:  Tim Hockin
     8 *      Adrian Sun
     9 *      Duncan Laurie
     10 *
     11 * This driver is SMP safe by nature. --TPH
     12 */
     13
     14#include <linux/config.h>
     15
     16#include <linux/pci.h>
     17#include <linux/init.h>
     18#include <linux/proc_fs.h>
     19#include <linux/module.h>
     20
     21#include <cobalt/cobalt.h>
     22#include <cobalt/systype.h>
     23#include <cobalt/i2c.h>
     24
     25/* for easy first-pass analysis */
     26#if defined(CONFIG_COBALT_GEN_III)
     27int COBALT_GENERATION_III_DEFINED;
     28#endif
     29#if defined(CONFIG_COBALT_GEN_V)
     30int COBALT_GENERATION_V_DEFINED;
     31#endif
     32
     33cobt_sys_t cobt_type = COBT_UNINITIALIZED;
     34EXPORT_SYMBOL(cobt_type);
     35unsigned long cobt_rev;
     36EXPORT_SYMBOL(cobt_rev);
     37
     38#ifdef CONFIG_PROC_FS
     39static struct proc_dir_entry *proc_systype;
     40#endif
     41static int systype_read_proc(char *buf, char **start, off_t pos, int len,
     42        int *eof, void *x);
     43static char *systype_str(cobt_sys_t type);
     44static unsigned long boardrev_read(void);
     45
     46void __init
     47cobalt_boardrev_init(void)
     48{
     49        cobt_rev = boardrev_read();
     50}
     51
     52int __init
     53cobalt_systype_init(void)
     54{
     55        cobalt_systype_probe();
     56   
     57#ifdef CONFIG_PROC_FS
     58        proc_systype = create_proc_read_entry("systype", 0,
     59                proc_cobalt, systype_read_proc, NULL);
     60        if (!proc_systype) {
     61                EPRINTK("can't create /proc/cobalt/systype\n");
     62        }
     63#endif
     64
     65        if (cobt_type == COBT_UNKNOWN) {
     66                printk(KERN_INFO "Cobalt system type is unknown, trouble will ensue (I can vouch for this)\n");
     67                return -1;
     68        } else {
     69            printk(KERN_INFO "Cobalt system type is %s\n",systype_str(cobt_type));
     70            return 0;
     71    }
     72}
     73
     74#if defined(CONFIG_COBALT_GEN_III)
     75static cobt_sys_t
     76systype_probe_3k(void)
     77{
     78        struct pci_dev *pdev;
     79        cobt_sys_t retval = COBT_UNKNOWN;
     80
     81        /* board identifier for RaQ3/4 vs Qube3 is on the PMU @ 0x7f */
     82        pdev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL);
     83        if (pdev) {
     84                /*
     85                 * check to see what board we are on
     86                 * ( RaQ 3, RaQ 4, Qube 3 )
     87                 */
     88                unsigned char val;
     89
     90            /* momentarily set DOGB# to input */
     91                pci_read_config_byte(pdev, 0x7d, &val);
     92                pci_write_config_byte(pdev, 0x7d, val & ~0x20);
     93
     94                /* read the GPIO register */
     95                pci_read_config_byte(pdev, 0x7f, &val);
     96                /* RaQ3/4 boards have DOGB (0x20) high,
     97                 * Qube3 has DOGB low */
     98                if (val & 0x20) {
     99                    retval = COBT_PACIFICA;
     100                } else {
     101                    retval = COBT_CARMEL;
     102                }
     103
     104                /* change DOGB back to output */
     105                pci_read_config_byte(pdev, 0x7d, &val);
     106                pci_write_config_byte(pdev, 0x7d, val | 0x20);
     107        }
     108   
     109        /* assign to this, so the compiler shuts up */
     110        COBALT_GENERATION_III_DEFINED = 1;
     111
     112        return retval;
     113}
     114#else
     115#define systype_probe_3k()      (COBT_UNKNOWN)
     116#endif
     117
     118#if defined(CONFIG_COBALT_GEN_V)
     119static cobt_sys_t
     120systype_probe_5k(void)
     121{
     122        struct pci_dev *pdev;
     123        cobt_sys_t retval = COBT_UNKNOWN;
     124
     125        /* is it a gen V ? */
     126        pdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
     127                PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL);
     128        if (pdev) {
     129                retval = COBT_MONTEREY;
     130                goto out;
     131        }
     132
     133        pdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
     134                PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL);
     135        if (pdev) {
     136                pdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
     137                        PCI_DEVICE_ID_SERVERWORKS_LE, NULL);
     138                if (pdev) {
     139                        retval = COBT_ALPINE;
     140                        goto out;
     141                }
     142        }
     143
     144out:
     145        /* assign to this, so the compiler shuts up */
     146        COBALT_GENERATION_V_DEFINED = 1;
     147
     148        return retval;
     149}
     150#else
     151#define systype_probe_5k()      (COBT_UNKNOWN)
     152#endif
     153
     154static cobt_sys_t
     155systype_probe_gp(void)
     156{
     157        struct pci_dev *pdev;
     158        cobt_sys_t retval = COBT_UNKNOWN;
     159
     160        /* is it a GP system? */
     161        pdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
     162                PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL);
     163        if (pdev) {
     164                pdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
     165                        PCI_DEVICE_ID_SERVERWORKS_HE, NULL);
     166                if (pdev) {
     167                        retval = COBT_BIGBEAR;
     168                }       
     169        }
     170
     171        return retval;
     172}
     173
     174cobt_sys_t
     175cobalt_systype_probe(void)
     176{
     177        static int init_done = 0;
     178
     179        if (init_done) {
     180                return cobt_type;
     181        }
     182
     183        /* check for 3k family systems */
     184       
     185        cobt_type = systype_probe_3k();
     186        if (cobt_type != COBT_UNKNOWN)
     187                goto out;
     188
     189        /* check for 5k family systems */
     190        cobt_type = systype_probe_5k();
     191        if (cobt_type != COBT_UNKNOWN)
     192                goto out;
     193
     194        /* it's a GP system or unknown */
     195        cobt_type = systype_probe_gp();
     196
     197out:
     198        if (cobt_type != COBT_UNKNOWN) {
     199                init_done = 1;
     200        }
     201
     202        return cobt_type;
     203}
     204EXPORT_SYMBOL(cobalt_systype_probe);
     205
     206#ifdef CONFIG_PROC_FS
     207static int
     208systype_read_proc(char *buf, char **start, off_t pos, int len,
     209        int *eof, void *x)
     210{
     211        int plen = sprintf(buf, "%s\n", systype_str(cobt_type));
     212        return cobalt_gen_proc_read(buf, plen, start, pos, len, eof);
     213}
     214#endif
     215
     216static char *
     217systype_str(cobt_sys_t type)
     218{
     219        switch (type) {
     220                case COBT_PACIFICA:
     221                        return "Pacifica";
     222                        break;
     223                case COBT_CARMEL:
     224                        return "Carmel";
     225                        break;
     226                case COBT_MONTEREY:
     227                        return "Monterey";
     228                        break;
     229                case COBT_ALPINE:
     230                        return "Alpine";
     231                        break;
     232                case COBT_BIGBEAR:
     233                        return "BigBear";
     234                        break;
     235                case COBT_UNKNOWN:
     236                default:
     237                        return "unknown";
     238                        break;
     239        }
     240}
     241
     242static unsigned long
     243boardrev_read(void)
     244{
     245        unsigned long rev;
     246
     247        switch (cobt_type) {
     248#ifdef CONFIG_COBALT_RAQ
     249        case COBT_PACIFICA:
     250        case COBT_CARMEL:
     251                /* No usable board rev on these systems */
     252                return 0;
     253        case COBT_MONTEREY:
     254                /*
     255                 * the boardrev on monterey is strapped off of GPM[3:0]
     256                 * and is read from port 0xc52
     257                 */
     258                return inb(0xc52);
     259        case COBT_ALPINE:
     260                /*
     261                 * the boardrev on alpine in stored in the i2c eeprom
     262                 * location 4
     263                 */
     264                rev = cobalt_i2c_read_byte(COBALT_I2C_DEV_AT24C02, 0x04);
     265                rev |= cobalt_i2c_read_byte(COBALT_I2C_DEV_AT24C02, 0x05) << 8;
     266                rev |= cobalt_i2c_read_byte(COBALT_I2C_DEV_AT24C02, 0x06) << 16;
     267                rev |= cobalt_i2c_read_byte(COBALT_I2C_DEV_AT24C02, 0x07) << 24;
     268                if (rev == 0xffffffff)
     269                        rev = 0;
     270                return rev;
     271#endif
     272        case COBT_BIGBEAR:
     273                /* No board revs at this time */
     274                return 0;
     275        case COBT_UNKNOWN:
     276        case COBT_UNINITIALIZED:
     277                return 0;
     278        }
     279        return 0;
     280}
  • drivers/cobalt/wdt.c

    diff -Naur linux-2.6.20.orig/drivers/cobalt/wdt.c linux-2.6.20/drivers/cobalt/wdt.c
    old new  
     1/* $Id: wdt.c,v 1.21 2002/07/02 00:38:17 asun Exp $ */
     2/*
     3 * Cobalt kernel WDT timer driver
     4 * Tim Hockin <thockin@cobaltnet.com>
     5 * Adrian Sun <asun@cobalt.com>
     6 * Chris Johnson <cjohnson@cobalt.com>
     7 * Copyright (c)1999-2000, Cobalt Networks
     8 * Copyright (c)2001, Sun Microsystems
     9 *
     10 * This should be SMP safe.  Every external function (except trigger_reboot)
     11 * grabs the wdt lock.  No function in this file may call any exported
     12 * function (excepting trigger_reboot).  The disable counter is an atomic, so
     13 * there should be no issues there. --TPH
     14 */
     15#include <linux/config.h>
     16
     17#include <linux/module.h>
     18#include <stdarg.h>
     19#include <stddef.h>
     20#include <linux/init.h>
     21#include <linux/sched.h>
     22#include <linux/timer.h>
     23#include <linux/config.h>
     24#include <linux/pci.h>
     25#include <linux/delay.h>
     26#include <asm/io.h>
     27#include <asm/msr.h>
     28
     29#include <cobalt/cobalt.h>
     30#include <cobalt/systype.h>
     31#include <cobalt/wdt.h>
     32#include <cobalt/superio.h>
     33
     34#define DOGB                    0x20
     35#define ALI_7101_WDT            0x92
     36#define ALI_WDT_ARM             0x01
     37#define WDT_3K_TIMEOUT          (HZ >> 4)       /* 1/16 second */
     38
     39#define WDT_SUPERIO_TIMEOUT     (0x01)          /* 1 minute */
     40#define WDT_5K_TIMEOUT          (HZ << 3)       /* 8 seconds */
     41
     42#define WDT_DRIVER                      "Cobalt Networks Watchdog Timer driver"
     43#define WDT_DRIVER_VMAJ         1
     44#define WDT_DRIVER_VMIN         0
     45
     46static unsigned long wdt_timeout;
     47static unsigned long long tsc_per_wdt;
     48static int initialized;
     49
     50#ifdef CONFIG_COBALT_WDT
     51struct timer_list cobalt_wdt_timer;
     52static atomic_t cobalt_wdt_disable_count = ATOMIC_INIT(0);
     53static spinlock_t wdt_lock = SPIN_LOCK_UNLOCKED;
     54#endif
     55
     56/* gen III */
     57static struct pci_dev *cobalt_pmu;
     58static int use_pic;
     59/* gen V */
     60static u16 superio_pm_port;
     61
     62#ifdef CONFIG_COBALT_WDT
     63static void do_refresh(void);
     64static void do_cleardog(void);
     65static void do_disable(void);
     66static void do_reenable(void);
     67#endif
     68       
     69static unsigned long __init
     70chipset_setup(void)
     71{
     72        unsigned char tmp;
     73        if (cobt_is_3k()) {
     74                /*
     75                 * Set up the PMU for 3k boards. It has a max
     76                 * of a 1 second timeout.
     77                 */
     78                struct pci_dev *south;
     79
     80                /* PMU (1543 ver A1-E) has a built-in WDT.  Set it to 1 sec */
     81                cobalt_pmu = pci_find_device(PCI_VENDOR_ID_AL,
     82                        PCI_DEVICE_ID_AL_M7101, NULL);
     83                if (!cobalt_pmu) {
     84                        EPRINTK("can't find south bridge for WDT\n");
     85                        return 0;
     86                }
     87                pci_write_config_byte(cobalt_pmu, ALI_7101_WDT, 0x02);
     88       
     89                /* why it is called 1543, but DevId is 1533 I'll never know */
     90                south = pci_find_device(PCI_VENDOR_ID_AL,
     91                        PCI_DEVICE_ID_AL_M1533, NULL);
     92                if (!south) {
     93                        EPRINTK("can't find south bridge for WDT\n");
     94                        use_pic = 1;
     95                } else {
     96                        /* reversion # is here - must match ???1001?(b)
     97                         * else use PIC for WDT */
     98                        pci_read_config_byte(south, 0x5e, &tmp);
     99                        use_pic = ((tmp & 0x1e) != 0x12);
     100                }
     101
     102                if (!use_pic) {
     103                        /* set DOGB GPIO pin to OUTPUT - JIC */
     104                        pci_read_config_byte(cobalt_pmu, 0x7d, &tmp);
     105                        pci_write_config_byte(cobalt_pmu, 0x7d, tmp | DOGB);
     106                }
     107                return WDT_3K_TIMEOUT;
     108        } else if (cobt_is_monterey()) {
     109                /*
     110                 * Set up the Nat. Semi SuperI/O for XTR. It has a
     111                 * minimum of a 1 minute timeout.
     112                 */
     113       
     114                /* superi/o -- select pm logical device and get base address */
     115                superio_pm_port = superio_ldev_base(PC87317_DEV_PM);
     116#ifdef CONFIG_COBALT_WDT
     117                if (!superio_pm_port) {
     118                        return 0;
     119                }
     120                outb(PC87317_PMDEV_WDTO, superio_pm_port);
     121                outb(WDT_SUPERIO_TIMEOUT, superio_pm_port + 1);
     122#endif
     123                return WDT_5K_TIMEOUT;
     124        } else if (cobt_is_alpine()) {
     125                /*
     126                 * Set up the Nat. Semi SuperI/O for Alpine. It has a
     127                 * minimum of a 1 minute timeout.
     128                 */
     129       
     130                /* superi/o -- select pm logical device and get base address */
     131                superio_pm_port = superio_ldev_base(PC87417_DEV_SWC);
     132#ifdef CONFIG_COBALT_WDT
     133                if (!superio_pm_port) {
     134                        return 0;
     135                }
     136                /* select the WDT bank of SWC */
     137                outb(PC87417_SWCBANK_WDT, superio_pm_port+PC87417_SWC_BANK);
     138                /* clear event config... */
     139                tmp = inb(superio_pm_port+PC87417_WDT_CONFIG);
     140                outb(0, superio_pm_port+PC87417_WDT_CONFIG);
     141                /* ...before mucking with timeout */
     142                outb(WDT_SUPERIO_TIMEOUT,
     143                        superio_pm_port+PC87417_WDT_TIMEOUT);
     144                /* restore the event config */
     145                outb(tmp, superio_pm_port+PC87417_WDT_CONFIG);
     146                /* enable the counter */
     147                outb(1, superio_pm_port+PC87417_WDT_CONTROL);
     148#endif
     149                return WDT_5K_TIMEOUT;
     150        }
     151
     152        return 0;
     153}
     154
     155void __init
     156cobalt_wdt_init(void)
     157{
     158        unsigned long long start, stop;
     159
     160    printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", WDT_DRIVER,WDT_DRIVER_VMAJ,WDT_DRIVER_VMIN);
     161   
     162        wdt_timeout = chipset_setup();
     163
     164        /* figure out time */
     165        rdtscll(start);
     166        udelay(100);
     167        rdtscll(stop);
     168
     169        /*
     170         * (int) (stop - start) * 10 == tsc per msec
     171         * 1000 / HZ == msec per tick
     172         * wdt_timeout == ticks per watchdog rearm
     173         */
     174        tsc_per_wdt = (int) (stop - start) * 10 * (1000 * wdt_timeout / HZ);
     175
     176#ifdef CONFIG_COBALT_WDT
     177        /* set the timer going */
     178        init_timer(&cobalt_wdt_timer);
     179        cobalt_wdt_timer.function = cobalt_wdt_refresh;
     180        cobalt_wdt_timer.data = 1;
     181        cobalt_wdt_timer.expires = jiffies + wdt_timeout;
     182        add_timer(&cobalt_wdt_timer);
     183
     184        /* the first timer tick will set it going */
     185
     186        if (cobt_is_3k() && use_pic) {
     187                WPRINTK("Cobalt WDT - old board, using PIC controller\n");
     188        }
     189#endif /* CONFIG_COBALT_WDT */
     190
     191        initialized = 1;
     192}
     193
     194static inline void
     195hw_disable(void)
     196{
     197        if (cobt_is_3k()) {
     198                char tmp;
     199                /* read the value, disable (reset) WDT */
     200                pci_read_config_byte(cobalt_pmu, ALI_7101_WDT, &tmp);
     201                pci_write_config_byte(cobalt_pmu, ALI_7101_WDT,
     202                        (tmp & ~ALI_WDT_ARM));
     203        } else if (cobt_is_monterey()) {
     204                outb(PC87317_PMDEV_WDTO, superio_pm_port);
     205                outb(0, superio_pm_port + 1);
     206        } else if (cobt_is_alpine()) {
     207                unsigned char tmp;
     208                /* select the WDT bank of SWC */
     209                outb(PC87417_SWCBANK_WDT, superio_pm_port + PC87417_SWC_BANK);
     210                /* clear event config before mucking with timeout */
     211                tmp = inb(superio_pm_port + PC87417_WDT_CONFIG);
     212                outb(0, superio_pm_port + PC87417_WDT_CONFIG);
     213                /*
     214                 * Disable it by setting a 0 time-out.
     215                 * The spec says 00h is reserved, but NSC confirms this is the
     216                 * way to disable the device.
     217                 */
     218                outb(0, superio_pm_port + PC87417_WDT_TIMEOUT);
     219                /* restore the event config */
     220                outb(tmp, superio_pm_port + PC87417_WDT_CONFIG);
     221        }
     222}
     223
     224static inline void
     225hw_enable(void)
     226{
     227        if (cobt_is_3k()) {
     228                unsigned char tmp;
     229                /* read the value, disable (reset) WDT, enable WDT */
     230                pci_read_config_byte(cobalt_pmu, ALI_7101_WDT, &tmp);
     231                pci_write_config_byte(cobalt_pmu, ALI_7101_WDT,
     232                        (tmp | ALI_WDT_ARM));
     233                if (use_pic) {
     234                        /* transition GPIO 5 (DOGB) to arm/clear timer */
     235                        pci_read_config_byte(cobalt_pmu, 0x7e, &tmp);
     236                        pci_write_config_byte(cobalt_pmu, 0x7e, tmp ^ DOGB);
     237                }
     238        } else if (cobt_is_monterey()) {
     239                outb(PC87317_PMDEV_WDTO, superio_pm_port);
     240                outb(WDT_SUPERIO_TIMEOUT, superio_pm_port + 1);
     241        } else if (cobt_is_alpine()) {
     242                unsigned char tmp;
     243                /* select the WDT bank of SWC */
     244                outb(PC87417_SWCBANK_WDT, superio_pm_port + PC87417_SWC_BANK);
     245                /* clear event config before mucking with timeout */
     246                tmp = inb(superio_pm_port + PC87417_WDT_CONFIG);
     247                outb(0, superio_pm_port + PC87417_WDT_CONFIG);
     248                /* enable and refresh the timer */
     249                outb(WDT_SUPERIO_TIMEOUT,
     250                        superio_pm_port + PC87417_WDT_TIMEOUT);
     251                outb(0x80, superio_pm_port + PC87417_WDT_CONTROL);
     252                /* restore event config */
     253                outb(tmp, superio_pm_port + PC87417_WDT_CONFIG);
     254        }
     255}
     256
     257#ifdef CONFIG_COBALT_WDT
     258static void
     259do_refresh(void)
     260{
     261        if (!initialized) {
     262                return;
     263        }
     264
     265        do_cleardog();
     266       
     267        /* re-arm the timer - this is locked in mod_timer() */
     268        mod_timer(&cobalt_wdt_timer, jiffies + wdt_timeout);
     269}
     270#endif
     271
     272EXPORT_SYMBOL(cobalt_wdt_refresh);
     273void
     274cobalt_wdt_refresh(unsigned long refresh_timer)
     275{
     276#ifdef CONFIG_COBALT_WDT
     277        unsigned long flags;
     278        spin_lock_irqsave(&wdt_lock, flags);
     279        do_refresh();
     280        spin_unlock_irqrestore(&wdt_lock, flags);
     281#endif
     282}
     283
     284#ifdef CONFIG_COBALT_WDT
     285static void
     286do_cleardog(void)
     287{
     288        static unsigned long long last_tsc = 0;
     289        unsigned long long tmp;
     290
     291        if (!initialized || (atomic_read(&cobalt_wdt_disable_count) > 0)) {
     292                return;
     293        }
     294
     295        /* only bother if we're due */
     296        rdtscll(tmp);
     297        if ((int)(tmp - last_tsc) < tsc_per_wdt) {
     298                return;
     299        }
     300
     301        if (cobt_is_3k() || cobt_is_monterey()) {
     302                /* this is how we re-start the clock */
     303                hw_disable();
     304                hw_enable();
     305        } else if (cobt_is_alpine()) {
     306                /* select the WDT bank of SWC */
     307                outb(PC87417_SWCBANK_WDT, superio_pm_port + PC87417_SWC_BANK);
     308                /* refresh the timer */
     309                outb(0x80, superio_pm_port + PC87417_WDT_CONTROL);
     310        }
     311
     312        rdtscll(last_tsc);
     313}
     314#endif
     315
     316EXPORT_SYMBOL(cobalt_wdt_cleardog);
     317void
     318cobalt_wdt_cleardog(void)
     319{
     320#ifdef CONFIG_COBALT_WDT
     321        unsigned long flags;
     322
     323        spin_lock_irqsave(&wdt_lock, flags);
     324        do_cleardog();
     325        spin_unlock_irqrestore(&wdt_lock, flags);
     326#endif
     327}
     328
     329/*
     330 * this is called from machine_restart. it should not be used on
     331 * 5k machines.
     332 */
     333EXPORT_SYMBOL(cobalt_wdt_trigger_reboot);
     334void
     335cobalt_wdt_trigger_reboot(void)
     336{
     337        if (cobt_is_3k()) {
     338                if (!cobalt_pmu) {
     339                        WPRINTK("no PMU found!\n");
     340                        WPRINTK("reboot not possible!\n");
     341                        return;
     342                }
     343
     344#ifdef CONFIG_COBALT_WDT
     345                /* stop feeding it */
     346                del_timer_sync(&cobalt_wdt_timer);
     347#endif
     348
     349                /* kiss your rear goodbye... */
     350                initialized = 0;
     351                hw_disable();
     352                hw_enable();
     353        }
     354}
     355
     356#ifdef CONFIG_COBALT_WDT
     357static void
     358do_disable(void)
     359{
     360        if (!initialized) {
     361                return;
     362        }
     363
     364        if (atomic_read(&cobalt_wdt_disable_count) == 0) {
     365                atomic_inc(&cobalt_wdt_disable_count);
     366                del_timer_sync(&cobalt_wdt_timer);
     367                hw_disable();
     368        }
     369}
     370#endif
     371
     372EXPORT_SYMBOL(cobalt_wdt_disable);
     373void
     374cobalt_wdt_disable(void)
     375{
     376#ifdef CONFIG_COBALT_WDT
     377        unsigned long flags;
     378
     379        if (cobt_is_3k() && use_pic) {
     380                WPRINTK("in PIC mode - cannot disable\n");
     381                return;
     382        }
     383
     384        spin_lock_irqsave(&wdt_lock, flags);
     385        do_disable();
     386        spin_unlock_irqrestore(&wdt_lock, flags);
     387#endif
     388}
     389
     390#ifdef CONFIG_COBALT_WDT
     391static void
     392do_reenable(void)
     393{
     394        int dcnt;
     395
     396        if (!initialized) {
     397                return;
     398        }
     399
     400        atomic_dec(&cobalt_wdt_disable_count);
     401        dcnt = atomic_read(&cobalt_wdt_disable_count);
     402
     403        if (dcnt == 0) {
     404                do_refresh();
     405        } else if (dcnt < 0) {
     406                WPRINTK("too many enables\n");
     407                atomic_set(&cobalt_wdt_disable_count, 0);
     408        }
     409}
     410#endif
     411
     412
     413EXPORT_SYMBOL(cobalt_wdt_reenable);
     414void
     415cobalt_wdt_reenable(void)
     416{
     417#ifdef CONFIG_COBALT_WDT
     418        unsigned long flags;
     419
     420        spin_lock_irqsave(&wdt_lock, flags);
     421        do_reenable();
     422        spin_unlock_irqrestore(&wdt_lock, flags);
     423#endif
     424}
  • drivers/net/Kconfig

    diff -Naur linux-2.6.20.orig/drivers/net/Kconfig linux-2.6.20/drivers/net/Kconfig
    old new  
    15271527          <file:Documentation/networking/net-modules.txt>.  The module
    15281528          will be called e100.
    15291529
     1530config E100_IGNORE_CSUM
     1531        bool "Ignore bad EEPROM checksum"
     1532        depends on E100 && EXPERIMENTAL && !CLEAN_COMPILE
     1533        help
     1534          This option tells the e100 driver to ignore bad EEPROM checksums.
     1535          Usually this is a bad idea, as an incorrect checksum can indicate a
     1536          serious issue with the network card.
     1537         
     1538          If unsure, say N.
     1539
    15301540config LNE390
    15311541        tristate "Mylex EISA LNE390A/B support (EXPERIMENTAL)"
    15321542        depends on NET_PCI && EISA && EXPERIMENTAL
  • drivers/net/e100.c

    diff -Naur linux-2.6.20.orig/drivers/net/e100.c linux-2.6.20/drivers/net/e100.c
    old new  
    162162#define DRV_VERSION             "3.5.17-k2"DRV_EXT
    163163#define DRV_DESCRIPTION         "Intel(R) PRO/100 Network Driver"
    164164#define DRV_COPYRIGHT           "Copyright(c) 1999-2006 Intel Corporation"
     165#define DRV_MODIFIED            "Modified by <jeff@404ster.com> to ignore bad EEPROM checksums"
    165166#define PFX                     DRV_NAME ": "
    166167
    167168#define E100_WATCHDOG_PERIOD    (2 * HZ)
     
    758759         * the sum of words should be 0xBABA */
    759760        checksum = le16_to_cpu(0xBABA - checksum);
    760761        if(checksum != nic->eeprom[nic->eeprom_wc - 1]) {
     762#if defined(CONFIG_E100_IGNORE_CSUM)
     763DPRINTK(PROBE, ERR, "EEPROM corrupted, ignoring and moving on\n");
     764DPRINTK(PROBE, ERR, "    Caclulated Checksum: %X\n",checksum);
     765DPRINTK(PROBE, ERR, "    EEPROM Checksum:     %X\n",nic->eeprom[nic->eeprom_wc - 1]);
     766#else
    761767                DPRINTK(PROBE, ERR, "EEPROM corrupted\n");
    762768                if (!eeprom_bad_csum_allow)
    763769                        return -EAGAIN;
     770#endif
    764771        }
    765772
    766773        return 0;
     
    28762883        if(((1 << debug) - 1) & NETIF_MSG_DRV) {
    28772884                printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
    28782885                printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT);
     2886#if defined(CONFIG_E100_IGNORE_CSUM)
     2887                printk(KERN_INFO PFX "%s\n", DRV_MODIFIED);
     2888#endif
    28792889        }
    28802890        return pci_register_driver(&e100_driver);
    28812891}
  • include/cobalt/acpi.h

    diff -Naur linux-2.6.20.orig/include/cobalt/acpi.h linux-2.6.20/include/cobalt/acpi.h
    old new  
     1/*
     2 * $Id: cobalt-acpi.h,v 1.7 2001/10/27 07:03:31 erik Exp $
     3 * cobalt-acpi.h : support for ACPI interrupts
     4 *
     5 * Copyright 2000 Cobalt Networks, Inc.
     6 * Copyright 2001 Sun Microsystems, Inc.
     7 */
     8#ifndef COBALT_ACPI_H
     9#define COBALT_ACPI_H
     10
     11#define SERVERWORKS_ACPI_INDEX_PORT     0x0cd6
     12#define SERVERWORKS_ACPI_DATA_PORT      0x0cd7
     13
     14
     15typedef struct
     16{
     17    u16 hw_type;
     18    u16 ev_type;
     19    u32 ev_data;
     20} cobalt_acpi_evt;
     21
     22enum __cobalt_acpi_hw_types
     23{
     24    COBALT_ACPI_HW_ANY = 0x0000,
     25    COBALT_ACPI_HW_OSB4 = 0x0001,
     26    COBALT_ACPI_HW_CSB5 = 0x0002,
     27    COBALT_ACPI_HW_PC8731X = 0x0003,
     28    COBALT_ACPI_HW_PC8741X = 0x0004,
     29};
     30
     31enum __cobalt_acpi_event_types
     32{
     33    COBALT_ACPI_EVT_NONE = 0x0000,
     34    COBALT_ACPI_EVT_TMR = 0x0001, /* Timer Event */
     35    COBALT_ACPI_EVT_BM = 0x00002, /* Bus Master Event */
     36    COBALT_ACPI_EVT_GBL = 0x0003, /* BIOS Global Lock release */
     37    COBALT_ACPI_EVT_PWRBTN = 0x0004, /* Power Button press */
     38    COBALT_ACPI_EVT_SLPBTN = 0x0005, /* Sleep Button press */
     39    COBALT_ACPI_EVT_RTC = 0x0006, /* RTC Alarm */
     40    COBALT_ACPI_EVT_WAK = 0x0007, /* Wake event */
     41    COBALT_ACPI_EVT_GPE = 0x0008, /* General Purpose Event (ev_data = gpe number) */
     42
     43        /* events greater than 0x7fff are symbolic events */
     44    COBALT_ACPI_EVT_SLED = 0x8000, /* Sled removal */
     45    COBALT_ACPI_EVT_THERM = 0x8001, /* Thermal trip */
     46    COBALT_ACPI_EVT_FAN = 0x8002, /* Fan Down */
     47    COBALT_ACPI_EVT_SM_INT = 0x8003, /* System Monitor Interrupt */
     48    COBALT_ACPI_EVT_VOLT = 0x8004, /* System Monitor Interrupt */
     49   
     50};
     51
     52typedef int (* cobalt_acpi_hw_handler)( int irq, void *dev_id, struct pt_regs *regs, void * data );
     53typedef int (* cobalt_acpi_enable_handler)( u16 ev_type, u16 ev_data, int en, void *data );
     54typedef int (* cobalt_acpi_evt_handler)( cobalt_acpi_evt *evt, void * data );
     55
     56
     57extern int cobalt_acpi_register_hw_handler( u16 hw_type,
     58                                            cobalt_acpi_hw_handler hw_handler,
     59                                            cobalt_acpi_enable_handler en_handler,
     60                                            void *data );
     61extern int cobalt_acpi_unregister_hw_handler( cobalt_acpi_hw_handler handler );
     62
     63extern int cobalt_acpi_register_trans_table( u16 hw_type, u16 table_len, u16 *table );
     64extern int cobalt_acpi_unregister_trans_table( u16 hw_type );
     65
     66extern int cobalt_acpi_register_evt_handler( cobalt_acpi_evt_handler handler,
     67                                             u16 evt_type,
     68                                             void *data );
     69extern int cobalt_acpi_unregister_evt_handler( cobalt_acpi_evt_handler handler );
     70
     71extern int cobalt_acpi_post_event( cobalt_acpi_evt evt );
     72
     73#ifdef CONFIG_COBALT_EMU_ACPI
     74int cobalt_acpi_generate_proc_evt( cobalt_acpi_evt * evt );
     75#else
     76#define cobalt_acpi_generate_proc_evt( a )
     77#endif
     78
     79   
     80
     81
     82#endif /* COBALT_ACPI_H */
  • include/cobalt/cobalt.h

    diff -Naur linux-2.6.20.orig/include/cobalt/cobalt.h linux-2.6.20/include/cobalt/cobalt.h
    old new  
     1/* $Id: cobalt.h,v 1.16 2002/11/04 17:54:15 thockin Exp $ */
     2/* Copyright 2001 Sun Microsystems, Inc. */
     3#include <linux/config.h>
     4#if !defined(COBALT_H) && defined(CONFIG_COBALT_RAQ)
     5#define COBALT_H
     6
     7/* generational support - for easy checking */
     8#ifdef CONFIG_COBALT_GEN_III
     9# define COBT_SUPPORT_GEN_III 1
     10#else
     11# define COBT_SUPPORT_GEN_III 0
     12#endif
     13
     14#ifdef CONFIG_COBALT_GEN_V
     15# define COBT_SUPPORT_GEN_V 1
     16#else
     17# define COBT_SUPPORT_GEN_V 0
     18#endif
     19
     20/* macros for consistent errors/warnings */
     21#define EPRINTK(fmt, args...) \
     22        printk(KERN_ERR "%s:%s: " fmt , __FILE__ , __FUNCTION__ , ##args)
     23
     24#define WPRINTK(fmt, args...) \
     25        printk(KERN_WARNING "%s:%s: " fmt , __FILE__ , __FUNCTION__ , ##args)
     26
     27/* the root of /proc/cobalt */
     28extern struct proc_dir_entry *proc_cobalt;
     29int cobalt_gen_proc_read(char *buf, int plen, char **start, off_t pos,
     30        int len, int *eof);
     31
     32//#ifdef CONFIG_COBALT_RAQ
     33/* keep this test up to date with new generation defines */
     34#if !defined(CONFIG_COBALT_GEN_III) && !defined(CONFIG_COBALT_GEN_V)
     35/* barf if no generation has been selected */
     36#error You asked for CONFIG_COBALT_RAQ, but no CONFIG_COBALT_GEN_* !
     37#endif
     38
     39/* accesses for CMOS */
     40#include <linux/mc146818rtc.h>
     41#include <cobalt/nvram.h>
     42
     43static inline int
     44cobalt_cmos_read_flag(const unsigned int flag)
     45{
     46        unsigned long flags;
     47        u16 cmosfl;
     48
     49        spin_lock_irqsave(&rtc_lock, flags);
     50        cmosfl = CMOS_READ(COBT_CMOS_FLAG_BYTE_0) << 8;
     51        cmosfl |= CMOS_READ(COBT_CMOS_FLAG_BYTE_1);
     52        spin_unlock_irqrestore(&rtc_lock, flags);
     53
     54        return (cmosfl & flag) ? 1 : 0;
     55}
     56//#endif /* CONFIG_COBALT_RAQ */
     57
     58#endif /* !defined(COBALT_H) && defined(CONFIG_COBALT_RAQ) */
  • include/cobalt/i2c.h

    diff -Naur linux-2.6.20.orig/include/cobalt/i2c.h linux-2.6.20/include/cobalt/i2c.h
    old new  
     1/*
     2 * $Id: cobalt-i2c.h,v 1.3 2001/08/22 05:48:04 asun Exp $
     3 * cobalt-i2c.h : I2C support for LCD/Front Panel
     4 *
     5 * Copyright 2000 Cobalt Networks, Inc.
     6 * Copyright 2001 Sun Microsystems, Inc.
     7 */
     8#ifndef COBALT_I2C_H
     9#define COBALT_I2C_H
     10
     11#include <linux/types.h>
     12#include <cobalt/cobalt.h>
     13
     14#define COBALT_I2C_DEV_LED_I            0x40
     15#define COBALT_I2C_DEV_LED_II           0x42
     16#define COBALT_I2C_DEV_LCD_DATA         0x4a
     17#define COBALT_I2C_DEV_LCD_INST         0x48
     18#define COBALT_I2C_DEV_FP_BUTTONS       0x41
     19#define COBALT_I2C_DEV_DRV_SWITCH       0x45
     20#define COBALT_I2C_DEV_RULER            0x46
     21#define COBALT_I2C_DEV_LM77             0x90
     22#define COBALT_I2C_DEV_ADM1029          0x5e
     23#define COBALT_I2C_DEV_AT24C02          0xae
     24
     25#define COBALT_I2C_READ                 0x01
     26#define COBALT_I2C_WRITE                0x00
     27
     28extern int cobalt_i2c_reset(void);
     29extern int cobalt_i2c_read_byte(const int dev, const int index);
     30extern int cobalt_i2c_read_word(const int dev, const int index);
     31extern int cobalt_i2c_read_block(const int dev, const int index,
     32                                 unsigned char *data, int count);
     33extern int cobalt_i2c_write_byte(const int dev, const int index,
     34                                 const u8 val);
     35extern int cobalt_i2c_write_word(const int dev, const int index,
     36                                 const u16 val);
     37extern int cobalt_i2c_write_block(const int dev, const int index,
     38                                  unsigned char *data, int count);
     39
     40#endif /* COBALT_I2C_H */
  • include/cobalt/lcd.h

    diff -Naur linux-2.6.20.orig/include/cobalt/lcd.h linux-2.6.20/include/cobalt/lcd.h
    old new  
     1/*
     2 * $Id: cobalt-lcd.h,v 1.12 2001/11/30 05:38:46 asun Exp $
     3 * cobalt-lcd.h : some useful defines for the Cobalt LCD driver
     4 *              (must be useable from both kernel and user space)
     5 *
     6 * Copyright 1996-2000 Cobalt Networks, Inc.
     7 * Copyright 2001 Sun Microsystems, Inc.
     8 *
     9 * By:  Andrew Bose     
     10 *      Timothy Stonis (x86 version)
     11 *      Tim Hockin
     12 *      Adrian Sun
     13 *      Erik Gilling
     14 *      Duncan Laurie
     15 */
     16#ifndef COBALT_LCD_H
     17#define COBALT_LCD_H
     18
     19#ifdef __KERNEL__
     20#include <cobalt/cobalt.h>
     21#endif
     22#include <cobalt/led.h>
     23
     24#define COBALT_LCD_LINELEN      40
     25struct lcd_display {
     26        unsigned long buttons;
     27        int size1;
     28        int size2;
     29        unsigned char line1[COBALT_LCD_LINELEN];
     30        unsigned char line2[COBALT_LCD_LINELEN];
     31        unsigned char cursor_address;
     32        unsigned char character;
     33        unsigned char leds;
     34        unsigned char *RomImage;
     35};
     36
     37/* different lcd types */
     38#define LCD_TYPE_UNKNOWN        0
     39#define LCD_TYPE_PARALLEL       1
     40#define LCD_TYPE_PARALLEL_B     2
     41#define LCD_TYPE_I2C            3
     42
     43/* Function command codes for ioctl */
     44#define LCD_On                  1
     45#define LCD_Off                 2
     46#define LCD_Clear               3
     47#define LCD_Reset               4
     48#define LCD_Cursor_Left         5
     49#define LCD_Cursor_Right        6
     50#define LCD_Disp_Left           7
     51#define LCD_Disp_Right          8
     52#define LCD_Get_Cursor          9
     53#define LCD_Set_Cursor          10
     54#define LCD_Home                11
     55#define LCD_Read                12             
     56#define LCD_Write               13     
     57#define LCD_Cursor_Off          14
     58#define LCD_Cursor_On           15
     59#define LCD_Get_Cursor_Pos      16
     60#define LCD_Set_Cursor_Pos      17
     61#define LCD_Blink_Off           18
     62#define LCD_Raw_Inst            19
     63#define LCD_Raw_Data            20
     64#define LCD_Type                21
     65
     66/* LED controls */
     67#define LED_Set                 40     
     68#define LED_Bit_Set             41
     69#define LED_Bit_Clear           42
     70#define LED32_Set               43     
     71#define LED32_Bit_Set           44
     72#define LED32_Bit_Clear         45
     73#define LED32_Get               46     
     74
     75/* button ioctls */
     76#define BUTTON_Read             50
     77
     78/* Button defs */
     79#define BUTTON_Next             0x3D
     80#define BUTTON_Next_B           0x7E
     81#define BUTTON_Reset_B          0xFC
     82#define BUTTON_NONE_B           0xFE
     83#define BUTTON_Left_B           0xFA
     84#define BUTTON_Right_B          0xDE
     85#define BUTTON_Up_B             0xF6
     86#define BUTTON_Down_B           0xEE
     87#define BUTTON_Enter_B          0xBE
     88
     89#define BUTTON_MASK             0xFE
     90
     91void cobalt_lcd_start_twiddle(void);
     92void cobalt_lcd_stop_twiddle(void);
     93void cobalt_lcd_off(void);
     94
     95#endif /* COBALT_LCD_H */
  • include/cobalt/led.h

    diff -Naur linux-2.6.20.orig/include/cobalt/led.h linux-2.6.20/include/cobalt/led.h
    old new  
     1/*
     2 * $Id: cobalt-led.h,v 1.7 2001/11/08 01:15:33 thockin Exp $
     3 * cobalt-led.c
     4 *
     5 * Copyright 1996-2000 Cobalt Networks, Inc.
     6 * Copyright 2001 Sun Microsystems, Inc.
     7 *
     8 * By:  Andrew Bose     
     9 *      Timothy Stonis (x86 version)
     10 *      Tim Hockin
     11 *      Adrian Sun
     12 *      Erik Gilling
     13 *      Duncan Laurie
     14 */
     15#ifndef COBALT_LED_H
     16#define COBALT_LED_H
     17
     18/* the set of all leds available on Cobalt systems */
     19#define LED_SHUTDOWN            (1 << 0)
     20#define LED_WEBLIGHT            (1 << 1)
     21#define LED_COBALTLOGO          (1 << 2)
     22#define LED_ETH0_TXRX           (1 << 3)
     23#define LED_ETH0_LINK           (1 << 4)
     24#define LED_ETH1_TXRX           (1 << 5)
     25#define LED_ETH1_LINK           (1 << 6)
     26#define LED_DISK0               (1 << 7)
     27#define LED_DISK1               (1 << 8)
     28#define LED_DISK2               (1 << 9)
     29#define LED_DISK3               (1 << 10)
     30#define LED_SYSFAULT            (1 << 11)
     31#define LED_MONTEREY_UNUSED0    (1 << 12)
     32#define LED_MONTEREY_UNUSED1    (1 << 13)
     33/* LED_MONTEREY_UNUSED2 is below */
     34#define LED_HEART               LED_MONTEREY_UNUSED0
     35#define LED_SPARE               LED_MONTEREY_UNUSED1
     36#define LED_SLED0               (1 << 14)
     37#define LED_SLED1               (1 << 15)
     38#define LED_SLED2               (1 << 16)
     39#define LED_SLED3               (1 << 17)
     40#define LED_MONTEREY_UNUSED2    (1 << 18)
     41#define LED_SPARE2              LED_MONTEREY_UNUSED2
     42
     43#ifdef __KERNEL__
     44
     45extern void cobalt_led_set(const unsigned int leds);
     46extern void cobalt_led_set_bits(const unsigned int leds);
     47extern void cobalt_led_clear_bits(const unsigned int leds);
     48extern void cobalt_led_set_lazy(const unsigned int leds);
     49extern void cobalt_led_set_bits_lazy(const unsigned int leds);
     50extern void cobalt_led_clear_bits_lazy(const unsigned int leds);
     51extern unsigned int cobalt_led_get(void);
     52
     53extern int cobalt_fpled_register(unsigned int (*fn)(void *), void *data);
     54extern int cobalt_fpled_unregister(unsigned int (*fn)(void *), void *data);
     55
     56#endif /* __KERNEL__ */
     57
     58#endif /* COBALT_LED_H */
     59
  • include/cobalt/misc.h

    diff -Naur linux-2.6.20.orig/include/cobalt/misc.h linux-2.6.20/include/cobalt/misc.h
    old new  
     1/* $Id: cobalt-misc.h,v 1.1 2001/04/04 03:36:43 thockin Exp $ */
     2/* Copyright 2001 Sun Microsystems, Inc. */
     3#ifndef COBALT_MISC_H
     4#define COBALT_MISC_H
     5
     6void cobalt_flush(void);
     7void cobalt_nmi(unsigned char reason, struct pt_regs *regs);
     8void cobalt_restart(void);
     9void cobalt_halt(void);
     10void cobalt_power_off(void);
     11
     12#endif
  • include/cobalt/net.h

    diff -Naur linux-2.6.20.orig/include/cobalt/net.h linux-2.6.20/include/cobalt/net.h
    old new  
     1/* $Id: cobalt-net.h,v 1.3 2002/10/25 01:02:42 thockin Exp $ */
     2/* Copyright 2001 Sun Microsystems, Inc. */
     3#ifndef COBALT_NET_H
     4#define COBALT_NET_H
     5
     6#include <linux/netdevice.h>
     7#include <linux/config.h>
     8
     9void cobalt_net_register(struct net_device *ndev);
     10void cobalt_net_unregister(struct net_device *ndev);
     11
     12#endif
  • include/cobalt/nvram.h

    diff -Naur linux-2.6.20.orig/include/cobalt/nvram.h linux-2.6.20/include/cobalt/nvram.h
    old new  
     1/*
     2 * $Id: cobalt-nvram.h,v 1.21 2002/11/02 00:57:06 thockin Exp $
     3 * cobalt-nvram.h : defines for the various fields in the cobalt NVRAM
     4 *
     5 * Copyright 2001 Sun Microsystems, Inc.
     6 */
     7
     8#ifndef COBALT_NVRAM_H
     9#define COBALT_NVRAM_H
     10
     11#include <linux/nvram.h>
     12
     13#define COBT_CMOS_INFO_MAX              0x7f    /* top address allowed */
     14#define COBT_CMOS_BIOS_DRIVE_INFO       0x12    /* drive info would go here */
     15
     16#define COBT_CMOS_CKS_START             NVRAM_OFFSET(0x0e)
     17#define COBT_CMOS_CKS_END               NVRAM_OFFSET(0x7f)
     18
     19/* flag bytes - 16 flags for now, leave room for more */
     20#define COBT_CMOS_FLAG_BYTE_0           NVRAM_OFFSET(0x10)
     21#define COBT_CMOS_FLAG_BYTE_1           NVRAM_OFFSET(0x11)
     22
     23/* flags in flag bytes - up to 16 */
     24#define COBT_CMOS_FLAG_MIN              0x0001
     25#define COBT_CMOS_CONSOLE_FLAG          0x0001 /* console on/off */
     26#define COBT_CMOS_DEBUG_FLAG            0x0002 /* ROM debug messages */
     27#define COBT_CMOS_AUTO_PROMPT_FLAG      0x0004 /* boot to ROM prompt? */
     28#define COBT_CMOS_CLEAN_BOOT_FLAG       0x0008 /* set by a clean shutdown */
     29#define COBT_CMOS_HW_NOPROBE_FLAG       0x0010 /* go easy on the probing */
     30#define COBT_CMOS_SYSFAULT_FLAG         0x0020 /* system fault detected */
     31#define COBT_CMOS_OOPSPANIC_FLAG        0x0040 /* panic on oops */
     32#define COBT_CMOS_DELAY_CACHE_FLAG      0x0080 /* delay cache initialization */
     33#define COBT_CMOS_NOLOGO_FLAG           0x0100 /* hide "C" logo @ boot */
     34#define COBT_CMOS_VERSION_FLAG          0x0200 /* the version field is valid */
     35#define COBT_CMOS_FLAG_MAX              0x0200
     36
     37/* leave byte 0x12 blank - Linux looks for drive info here */
     38
     39/* CMOS structure version, valid if COBT_CMOS_VERSION_FLAG is true */
     40#define COBT_CMOS_VERSION               NVRAM_OFFSET(0x13)
     41#define COBT_CMOS_VER_BTOCODE           1 /* min. version needed for btocode */
     42
     43/* index of default boot method */
     44#define COBT_CMOS_BOOT_METHOD           NVRAM_OFFSET(0x20)
     45#define COBT_CMOS_BOOT_METHOD_DISK      0
     46#define COBT_CMOS_BOOT_METHOD_ROM       1
     47#define COBT_CMOS_BOOT_METHOD_NET       2
     48#define COBT_CMOS_BOOT_METHOD_NNET      3
     49#define COBT_CMOS_BOOT_METHOD_OTHER     4
     50
     51#define COBT_CMOS_BOOT_DEV_MIN          NVRAM_OFFSET(0x21)
     52/* major #, minor # of first through fourth boot device */
     53#define COBT_CMOS_BOOT_DEV0_MAJ         NVRAM_OFFSET(0x21)
     54#define COBT_CMOS_BOOT_DEV0_MIN         NVRAM_OFFSET(0x22)
     55#define COBT_CMOS_BOOT_DEV1_MAJ         NVRAM_OFFSET(0x23)
     56#define COBT_CMOS_BOOT_DEV1_MIN         NVRAM_OFFSET(0x24)
     57#define COBT_CMOS_BOOT_DEV2_MAJ         NVRAM_OFFSET(0x25)
     58#define COBT_CMOS_BOOT_DEV2_MIN         NVRAM_OFFSET(0x26)
     59#define COBT_CMOS_BOOT_DEV3_MAJ         NVRAM_OFFSET(0x27)
     60#define COBT_CMOS_BOOT_DEV3_MIN         NVRAM_OFFSET(0x28)
     61#define COBT_CMOS_BOOT_DEV_MAX          NVRAM_OFFSET(0x28)
     62
     63/* checksum of bytes 0xe-0x7f */
     64#define COBT_CMOS_CHECKSUM              NVRAM_OFFSET(0x2e)
     65
     66/* running uptime counter, units of 5 minutes (32 bits =~ 41000 years) */
     67#define COBT_CMOS_UPTIME_0              NVRAM_OFFSET(0x30)
     68#define COBT_CMOS_UPTIME_1              NVRAM_OFFSET(0x31)
     69#define COBT_CMOS_UPTIME_2              NVRAM_OFFSET(0x32)
     70#define COBT_CMOS_UPTIME_3              NVRAM_OFFSET(0x33)
     71
     72/* count of successful boots (32 bits) */
     73#define COBT_CMOS_BOOTCOUNT_0           NVRAM_OFFSET(0x38)
     74#define COBT_CMOS_BOOTCOUNT_1           NVRAM_OFFSET(0x39)
     75#define COBT_CMOS_BOOTCOUNT_2           NVRAM_OFFSET(0x3a)
     76#define COBT_CMOS_BOOTCOUNT_3           NVRAM_OFFSET(0x3b)
     77
     78/* 13 bytes: system serial number, same as on the back of the system */
     79#define COBT_CMOS_SYS_SERNUM_LEN        13
     80#define COBT_CMOS_SYS_SERNUM_0          NVRAM_OFFSET(0x40)
     81#define COBT_CMOS_SYS_SERNUM_1          NVRAM_OFFSET(0x41)
     82#define COBT_CMOS_SYS_SERNUM_2          NVRAM_OFFSET(0x42)
     83#define COBT_CMOS_SYS_SERNUM_3          NVRAM_OFFSET(0x43)
     84#define COBT_CMOS_SYS_SERNUM_4          NVRAM_OFFSET(0x44)
     85#define COBT_CMOS_SYS_SERNUM_5          NVRAM_OFFSET(0x45)
     86#define COBT_CMOS_SYS_SERNUM_6          NVRAM_OFFSET(0x46)
     87#define COBT_CMOS_SYS_SERNUM_7          NVRAM_OFFSET(0x47)
     88#define COBT_CMOS_SYS_SERNUM_8          NVRAM_OFFSET(0x48)
     89#define COBT_CMOS_SYS_SERNUM_9          NVRAM_OFFSET(0x49)
     90#define COBT_CMOS_SYS_SERNUM_10         NVRAM_OFFSET(0x4a)
     91#define COBT_CMOS_SYS_SERNUM_11         NVRAM_OFFSET(0x4b)
     92#define COBT_CMOS_SYS_SERNUM_12         NVRAM_OFFSET(0x4c)
     93/* checksum for serial num - 1 byte */
     94#define COBT_CMOS_SYS_SERNUM_CSUM       NVRAM_OFFSET(0x4f)
     95
     96#define COBT_CMOS_ROM_REV_MAJ           NVRAM_OFFSET(0x50)
     97#define COBT_CMOS_ROM_REV_MIN           NVRAM_OFFSET(0x51)
     98#define COBT_CMOS_ROM_REV_REV           NVRAM_OFFSET(0x52)
     99
     100#define COBT_CMOS_BTO_CODE_0            NVRAM_OFFSET(0x53)
     101#define COBT_CMOS_BTO_CODE_1            NVRAM_OFFSET(0x54)
     102#define COBT_CMOS_BTO_CODE_2            NVRAM_OFFSET(0x55)
     103#define COBT_CMOS_BTO_CODE_3            NVRAM_OFFSET(0x56)
     104
     105#define COBT_CMOS_BTO_IP_CSUM           NVRAM_OFFSET(0x57)
     106#define COBT_CMOS_BTO_IP_0              NVRAM_OFFSET(0x58)
     107#define COBT_CMOS_BTO_IP_1              NVRAM_OFFSET(0x59)
     108#define COBT_CMOS_BTO_IP_2              NVRAM_OFFSET(0x5a)
     109#define COBT_CMOS_BTO_IP_3              NVRAM_OFFSET(0x5b)
     110
     111/* byte for load/run methods */
     112#define COBT_CMOS_BOOT_TYPE             NVRAM_OFFSET(0x5c)
     113#define COBT_CMOS_BOOT_KERN_DEV         0x01 /* use kernel on major/minor */
     114#define COBT_CMOS_BOOT_KERN_ROM         0x02 /* use rom kernel */
     115#define COBT_CMOS_BOOT_KERN_NET         0x03 /* use net kernel */
     116#define COBT_CMOS_BOOT_KERN_MASK        0x0f /* mask for above */
     117
     118#define COBT_CMOS_BOOT_FS_DEV           0x10 /* use major/minor number dev */
     119#define COBT_CMOS_BOOT_FS_NET           0x30 /* use net fs */
     120#define COBT_CMOS_BOOT_FS_MASK          0xf0 /* mask for above */
     121
     122/* HA mode we're in (Twin Peaks) */
     123#define COBT_CMOS_HA_MODE               NVRAM_OFFSET(0x62)
     124
     125#endif /* COBALT_NVRAM_H */
  • include/cobalt/ruler.h

    diff -Naur linux-2.6.20.orig/include/cobalt/ruler.h linux-2.6.20/include/cobalt/ruler.h
    old new  
     1/* $Id: cobalt-ruler.h,v 1.4 2001/06/08 20:46:44 thockin Exp $ */
     2/* Copyright 2001 Sun Microsystems, Inc. */
     3#ifndef COBALT_RULER_H
     4#define COBALT_RULER_H
     5
     6#include <linux/ide.h>
     7
     8void cobalt_ruler_register(ide_drive_t *hwif);
     9void cobalt_ruler_unregister(ide_drive_t *hwif);
     10
     11//typedef int (*cob_busproc_t) (struct hwif_s *, int);
     12
     13//int *cob_busproc_t (ide_drive_t *, int);
     14
     15#endif
  • include/cobalt/sensors.h

    diff -Naur linux-2.6.20.orig/include/cobalt/sensors.h linux-2.6.20/include/cobalt/sensors.h
    old new  
     1/* $Id: cobalt-sensors.h,v 1.2 2001/09/25 18:10:29 thockin Exp $ */
     2/* Copyright 2001 Sun Microsystems, Inc. */
     3#ifndef COBALT_SENSORS_H
     4#define COBALT_SENSORS_H
     5
     6#include <cobalt/cobalt.h>
     7
     8extern unsigned int cobalt_nthermals;
     9extern unsigned int cobalt_nvoltages;
     10
     11/* return NULL if the sensor doesn't exist, fill buf if it does */
     12char *__cobalt_thermal_read(unsigned int sensor, char *buf, int len);
     13char *__cobalt_voltage_read(unsigned int sensor, char *buf, int len);
     14
     15static inline char *
     16cobalt_thermal_read(unsigned int sensor)
     17{
     18        char buf[32];
     19        return __cobalt_thermal_read(sensor, buf, sizeof(buf)-1);
     20}
     21
     22static inline char *
     23cobalt_voltage_read(unsigned int sensor)
     24{
     25        char buf[32];
     26        return __cobalt_voltage_read(sensor, buf, sizeof(buf)-1);
     27}
     28
     29#endif
  • include/cobalt/serialnum.h

    diff -Naur linux-2.6.20.orig/include/cobalt/serialnum.h linux-2.6.20/include/cobalt/serialnum.h
    old new  
     1/*
     2 * $Id: cobalt-serialnum.h,v 1.1 2001/03/07 01:58:24 thockin Exp $
     3 * cobalt-serialnum.h : access to the DS2401 serial number
     4 *
     5 * Copyright 2000 Cobalt Networks, Inc.
     6 * Copyright 2001 Sun Microsystems, Inc.
     7 */
     8#ifndef COBALT_SERIALNUM_H
     9#define COBALT_SERIALNUM_H
     10
     11#include <cobalt/cobalt.h>
     12
     13char *cobalt_serialnum_get(void);
     14unsigned long cobalt_hostid_get(void);
     15
     16#endif /* COBALT_SERIALNUM_H */
  • include/cobalt/superio.h

    diff -Naur linux-2.6.20.orig/include/cobalt/superio.h linux-2.6.20/include/cobalt/superio.h
    old new  
     1/*
     2 * $Id: cobalt-superio.h,v 1.11 2001/11/02 12:00:03 duncan Exp $
     3 * cobalt-superio.h : SuperIO support for Sun/Cobalt servers
     4 *
     5 * Copyright 2000 Cobalt Networks, Inc.
     6 * Copyright 2001 Sun Microsystems, Inc.
     7 */
     8#ifndef COBALT_SUPERIO_H
     9#define COBALT_SUPERIO_H
     10
     11#include <cobalt/cobalt.h>
     12#include <cobalt/systype.h>
     13
     14/* the lock that protects superio accesses */
     15extern spinlock_t cobalt_superio_lock;
     16
     17/*
     18 * The main functions of the SuperIO are accessed via index/data registers
     19 * These are the same for both SuperIO chip families
     20 */
     21#define SUPERIO_INDEX_PORT      0x2e
     22#define SUPERIO_DATA_PORT       0x2f
     23
     24/*
     25 * This index allows you to select a logical device
     26 */
     27#define SUPERIO_LOGICAL_DEV     0x07
     28
     29/*
     30 * Type of SUPERIO
     31 */
     32#define SUPERIO_SID             0x20
     33
     34/*
     35 * Some indices that are common to all logical devices
     36 */
     37#define SUPERIO_ACTIVATE        0x30
     38#define SUPERIO_ADDR_HIGH       0x60
     39#define SUPERIO_ADDR_LOW        0x61
     40#define SUPERIO_INTR_PIN        0x70
     41#define SUPERIO_INTR_TYPE       0x71
     42
     43
     44/*
     45 * PC87317 SuperIO is found on XTR
     46 */
     47
     48/*
     49 * logical devices - write to LOGICAL_DEV index
     50 */
     51#define PC87317_DEV_RTC         0x02
     52#define PC87317_DEV_GPIO        0x07
     53#define PC87317_DEV_PM          0x08
     54
     55/* withing the PM dev, are the following indices */
     56#define PC87317_PMDEV_WDTO      0x05
     57#define PC87317_PMDEV_GPELO     0x0e
     58#define PC87317_PMDEV_GPEHI     0x0f
     59
     60/* within the APC bank of RTC */
     61#define PC87317_APCR1           0x40
     62#define PC87317_APCR2           0x41
     63#define PC87317_APCR3           0x49
     64#define PC87317_APCR4           0x4a
     65#define PC87317_APCR5           0x4b
     66#define PC87317_APCR6           0x4c
     67#define PC87317_APCR7           0x4d
     68
     69#define PC87317_RTC_BANK_MAIN   0
     70#define PC87317_RTC_BANK_RTC    1
     71#define PC87317_RTC_BANK_APC    2
     72#define PC87317_RTC_CRA         0x0a
     73#define PC87317_RTC_BANK_0      0x20
     74#define PC87317_RTC_BANK_1      0x30
     75#define PC87317_RTC_BANK_2      0x40
     76
     77#define PC87317_PWRBUTTON       0x01
     78#define PC87317_PM1_STATUS      0x01
     79
     80/* offsets from GPEHI/GPELO */
     81#define PC87317_GPE_GP1_STS0    0x00
     82#define PC87317_GPE_GP1_STS1    0x01
     83#define PC87317_GPE_GP1_STS2    0x02
     84#define PC87317_GPE_GP1_STS3    0x03
     85#define PC87317_GPE_GP1_EN0     0x04
     86#define PC87317_GPE_GP1_EN1     0x05
     87#define PC87317_GPE_GP1_EN2     0x06
     88#define PC87317_GPE_GP1_EN3     0x07
     89#define PC87317_GPE_GP2_EN0     0x08
     90#define PC87317_GPE_SMI_CMD     0x0c
     91
     92/*
     93 * PC87417 family is found on alpine
     94 */
     95
     96#define PC87417_DEV_SWC         0x4
     97#define PC87417_DEV_GPIO        0x7
     98#define PC87417_DEV_RTC         0x10
     99
     100/* registers in the SWC dev */
     101#define PC87417_SWC_PWONCTL     0x9
     102/*
     103 * within the System Wake Control device, there are banks, write the bank you
     104 * want to SWC_BANK
     105 */
     106#define PC87417_SWC_BANK        0xf
     107#define PC87417_SWCBANK_ACPI    0x2
     108#define PC87417_SWCBANK_WDT     0x3
     109
     110/*
     111 * the SWC WDT bank has 3 main registers
     112 */
     113#define PC87417_WDT_CONTROL     0x10
     114#define PC87417_WDT_TIMEOUT     0x11
     115#define PC87417_WDT_CONFIG      0x12
     116
     117/*
     118 * within the SWC, two regs serve as index/data for wake-event enabling
     119 */
     120#define PC87417_SWC_WKEVENT     0x0
     121#define PC87417_SWC_WKSTATE     0x1
     122#define PC87417_SWCWKEVENT_GPIOE42 0xa
     123#define PC87417_SWCWKEVENT_RTC  0x18
     124
     125
     126/*
     127 * types of superIOs
     128 */
     129enum superio_type_t
     130{
     131    SIO_TYPE_UNKNOWN,
     132    SIO_TYPE_PC8731X,
     133    SIO_TYPE_PC8741X,
     134};
     135
     136
     137
     138#define PC8731X_SID 0xd0
     139#define PC9731X_SID 0xdf
     140#define PC8741X_SID 0xee
     141
     142static inline int superio_type( void )
     143{
     144    u8 reg;
     145    unsigned long flags;
     146    enum superio_type_t type;
     147
     148    spin_lock_irqsave(&cobalt_superio_lock, flags);
     149
     150    outb(SUPERIO_SID, SUPERIO_INDEX_PORT);
     151    reg = inb( SUPERIO_DATA_PORT );
     152    switch( reg )
     153    {
     154        case PC8731X_SID:
     155        case PC9731X_SID:
     156            type = SIO_TYPE_PC8731X;
     157            break;
     158
     159        case PC8741X_SID:
     160            type = SIO_TYPE_PC8741X;
     161            break;
     162
     163        default:
     164            type = SIO_TYPE_UNKNOWN;
     165            break;
     166    }
     167
     168    spin_unlock_irqrestore(&cobalt_superio_lock, flags);
     169
     170    return type;
     171}
     172
     173/*
     174 * stuff to make life easier
     175 */
     176
     177/* read the base address of a particular superio logical device */
     178#define superio_ldev_base(ldev)         superio_ldev_base_n(ldev, 0)
     179static inline unsigned short
     180superio_ldev_base_n(int ldev, int n)
     181{
     182        unsigned long flags;
     183        unsigned short addr;
     184
     185        spin_lock_irqsave(&cobalt_superio_lock, flags);
     186
     187        /* select the logical device */
     188        outb(SUPERIO_LOGICAL_DEV, SUPERIO_INDEX_PORT);
     189        outb(ldev, SUPERIO_DATA_PORT);
     190
     191        /* read the 2-byte base address */
     192        outb(SUPERIO_ADDR_HIGH+(n*2), SUPERIO_INDEX_PORT);
     193        addr = inb(SUPERIO_DATA_PORT) << 8;
     194        outb(SUPERIO_ADDR_LOW+(n*2), SUPERIO_INDEX_PORT);
     195        addr |= inb(SUPERIO_DATA_PORT);
     196
     197        spin_unlock_irqrestore(&cobalt_superio_lock, flags);
     198
     199        return addr;
     200}
     201
     202static inline void
     203superio_set_rtc_bank(const unsigned int page)
     204{
     205        if (cobt_is_monterey()) {
     206                unsigned char val;
     207
     208                val = CMOS_READ(0xa);
     209                val &= ~0x70;
     210                switch (page) {
     211                case PC87317_RTC_BANK_MAIN:
     212                        val |= 0x20;
     213                        break;
     214                case PC87317_RTC_BANK_RTC:
     215                        val |= 0x30;
     216                        break;
     217                case PC87317_RTC_BANK_APC:
     218                        val |= 0x40;
     219                        break;
     220                }
     221                CMOS_WRITE(val, 0xa);
     222        }
     223}
     224
     225#endif /* COBALT_SUPERIO_H */
  • include/cobalt/systype.h

    diff -Naur linux-2.6.20.orig/include/cobalt/systype.h linux-2.6.20/include/cobalt/systype.h
    old new  
     1/*
     2 * $Id: cobalt-systype.h,v 1.8 2002/08/08 22:46:50 carls Exp $
     3 * cobalt-systype.h : figure out what Cobalt system we are on
     4 *
     5 * Copyright 2000 Cobalt Networks, Inc.
     6 * Copyright 2001-2002 Sun Microsystems, Inc.
     7 */
     8#ifndef COBALT_SYSTYPE_H
     9#define COBALT_SYSTYPE_H
     10
     11#include <cobalt/cobalt.h>
     12
     13typedef enum {
     14        COBT_UNINITIALIZED,
     15        COBT_UNKNOWN,
     16        COBT_PACIFICA,
     17        COBT_CARMEL,
     18        COBT_MONTEREY,
     19        COBT_ALPINE,
     20        COBT_BIGBEAR,
     21} cobt_sys_t;
     22
     23extern cobt_sys_t cobt_type;
     24extern cobt_sys_t cobalt_systype_probe(void);
     25extern unsigned long cobt_rev;
     26
     27/*
     28 * one test for each major board-type
     29 * COBT_SUPPORT_* from cobalt.h
     30 */
     31
     32/* pacifica is the RaQ 3 and RaQ 4 platform */
     33static inline int
     34cobt_is_pacifica(void)
     35{
     36        if (!COBT_SUPPORT_GEN_III) {
     37                return 0;
     38        }
     39        if (cobt_type == COBT_UNINITIALIZED) {
     40                cobalt_systype_probe();
     41        }
     42        return (cobt_type == COBT_PACIFICA);
     43}
     44
     45/* carmel is the Qube 3 platform */
     46static inline int
     47cobt_is_carmel(void)
     48{
     49        if (!COBT_SUPPORT_GEN_III) {
     50                return 0;
     51        }
     52        if (cobt_type == COBT_UNINITIALIZED) {
     53                cobalt_systype_probe();
     54        }
     55        return (cobt_type == COBT_CARMEL);
     56}
     57
     58/* monterey is the RaQ XTR platform */
     59static inline int
     60cobt_is_monterey(void)
     61{
     62        if (!COBT_SUPPORT_GEN_V) {
     63                return 0;
     64        }
     65        if (cobt_type == COBT_UNINITIALIZED) {
     66                cobalt_systype_probe();
     67        }
     68        return (cobt_type == COBT_MONTEREY);
     69}
     70
     71static inline int
     72cobt_is_alpine(void)
     73{
     74        if (!COBT_SUPPORT_GEN_V) {
     75                return 0;
     76        }
     77        if (cobt_type == COBT_UNINITIALIZED) {
     78                cobalt_systype_probe();
     79        }
     80        return (cobt_type == COBT_ALPINE);
     81}
     82
     83static inline int
     84cobt_is_bigbear(void)
     85{
     86        if (!COBT_SUPPORT_GEN_V) {
     87                return 0;
     88        }
     89        if (cobt_type == COBT_UNINITIALIZED) {
     90                cobalt_systype_probe();
     91        }
     92        return (cobt_type == COBT_BIGBEAR);
     93}
     94
     95/* one for each major generation */
     96#define cobt_is_3k()     (cobt_is_pacifica() || cobt_is_carmel())
     97#define cobt_is_5k()     (cobt_is_monterey() || cobt_is_alpine() || cobt_is_bigbear())
     98
     99#endif
  • include/cobalt/wdt.h

    diff -Naur linux-2.6.20.orig/include/cobalt/wdt.h linux-2.6.20/include/cobalt/wdt.h
    old new  
     1/* $Id: cobalt-wdt.h,v 1.1 2001/03/07 01:58:24 thockin Exp $ */
     2/* Copyright 2001 Sun Microsystems, Inc. */
     3#ifndef COBALT_WDT_H
     4#define COBALT_WDT_H
     5
     6#include <cobalt/cobalt.h>
     7
     8void cobalt_wdt_refresh(unsigned long refresh_timer);
     9void cobalt_wdt_trigger_reboot(void);
     10
     11void cobalt_wdt_disable(void);
     12void cobalt_wdt_reenable(void);
     13
     14void cobalt_wdt_cleardog(void);
     15
     16#endif
  • init/main.c

    diff -Naur linux-2.6.20.orig/init/main.c linux-2.6.20/init/main.c
    old new  
    681681 *
    682682 * Now we can finally start doing some real work..
    683683 */
     684#ifdef CONFIG_COBALT_RAQ
     685extern int cobalt_init(void);
     686#endif
     687
    684688static void __init do_basic_setup(void)
    685689{
    686690        /* drivers will send hotplug events */
     
    693697#endif
    694698
    695699        do_initcalls();
     700       
     701#ifdef CONFIG_COBALT_RAQ
     702    cobalt_init();
     703#endif
    696704}
    697705
    698706static void __init do_pre_smp_initcalls(void)
Note: See TracBrowser for help on using the repository browser.