| [9a57cc4] | 1 | Submitted By: Jim Gifford (patches at jg555 dot com) | 
|---|
|  | 2 | Date: 2007-02-04 | 
|---|
|  | 3 | Initial Package Version: 2.6.20 | 
|---|
|  | 4 | Origin: Gentoo - Jeff Waters | 
|---|
|  | 5 | Upstream Status: N/A | 
|---|
|  | 6 | Description: Adds Support for the x86 Cobalt Series | 
|---|
|  | 7 |  | 
|---|
|  | 8 | diff -Naur linux-2.6.20.orig/Makefile linux-2.6.20/Makefile | 
|---|
|  | 9 | --- linux-2.6.20.orig/Makefile  2007-02-04 10:44:54.000000000 -0800 | 
|---|
|  | 10 | +++ linux-2.6.20/Makefile       2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 11 | @@ -206,6 +206,7 @@ | 
|---|
|  | 12 | KBUILD_MODULES := | 
|---|
|  | 13 | KBUILD_BUILTIN := 1 | 
|---|
|  | 14 |  | 
|---|
|  | 15 | +DRIVERS-$(CONFIG_COBALT_RAQ) += drivers/cobalt/cobalt.o | 
|---|
|  | 16 | #      If we have only "make modules", don't compile built-in objects. | 
|---|
|  | 17 | #      When we're building modules with modversions, we need to consider | 
|---|
|  | 18 | #      the built-in objects during the descend as well, in order to | 
|---|
|  | 19 | @@ -703,6 +704,11 @@ | 
|---|
|  | 20 | cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) \ | 
|---|
|  | 21 | $(if $(CONFIG_KALLSYMS_ALL),--all-symbols) > $@ | 
|---|
|  | 22 |  | 
|---|
|  | 23 | + | 
|---|
|  | 24 | +cobalt: vmlinux | 
|---|
|  | 25 | +       strip vmlinux | 
|---|
|  | 26 | +       bzip2 vmlinux | 
|---|
|  | 27 | + | 
|---|
|  | 28 | .tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE | 
|---|
|  | 29 | $(call if_changed_dep,as_o_S) | 
|---|
|  | 30 |  | 
|---|
|  | 31 | diff -Naur linux-2.6.20.orig/arch/i386/kernel/Makefile linux-2.6.20/arch/i386/kernel/Makefile | 
|---|
|  | 32 | --- linux-2.6.20.orig/arch/i386/kernel/Makefile 2007-02-04 10:44:54.000000000 -0800 | 
|---|
|  | 33 | +++ linux-2.6.20/arch/i386/kernel/Makefile      2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 34 | @@ -55,6 +55,7 @@ | 
|---|
|  | 35 | targets += vsyscall-note.o vsyscall.lds | 
|---|
|  | 36 |  | 
|---|
|  | 37 | # The DSO images are built using a special linker script. | 
|---|
|  | 38 | +obj-$(CONFIG_COBALT_RAQ)       += cobalt.o | 
|---|
|  | 39 | quiet_cmd_syscall = SYSCALL $@ | 
|---|
|  | 40 | cmd_syscall = $(CC) -m elf_i386 -nostdlib $(SYSCFLAGS_$(@F)) \ | 
|---|
|  | 41 | -Wl,-T,$(filter-out FORCE,$^) -o $@ | 
|---|
|  | 42 | diff -Naur linux-2.6.20.orig/arch/i386/kernel/cobalt.c linux-2.6.20/arch/i386/kernel/cobalt.c | 
|---|
|  | 43 | --- linux-2.6.20.orig/arch/i386/kernel/cobalt.c 1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 44 | +++ linux-2.6.20/arch/i386/kernel/cobalt.c      2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 45 | @@ -0,0 +1,281 @@ | 
|---|
|  | 46 | +/* $Id: cobalt.c,v 1.34 2002/11/04 17:54:14 thockin Exp $ */ | 
|---|
|  | 47 | +#include <linux/config.h> | 
|---|
|  | 48 | + | 
|---|
|  | 49 | +#include <linux/types.h> | 
|---|
|  | 50 | +#include <linux/stddef.h> | 
|---|
|  | 51 | +#include <linux/kernel.h> | 
|---|
|  | 52 | +#include <linux/ptrace.h> | 
|---|
|  | 53 | +#include <linux/reboot.h> | 
|---|
|  | 54 | +#include <linux/delay.h> | 
|---|
|  | 55 | +#include <linux/pci.h> | 
|---|
|  | 56 | +#include <linux/timer.h> | 
|---|
|  | 57 | +#include <linux/init.h> | 
|---|
|  | 58 | + | 
|---|
|  | 59 | +#include <cobalt/cobalt.h> | 
|---|
|  | 60 | +#include <cobalt/misc.h> | 
|---|
|  | 61 | +#include <cobalt/led.h> | 
|---|
|  | 62 | +#include <cobalt/wdt.h> | 
|---|
|  | 63 | +#include <cobalt/acpi.h> | 
|---|
|  | 64 | +#include <cobalt/superio.h> | 
|---|
|  | 65 | +#include <cobalt/systype.h> | 
|---|
|  | 66 | + | 
|---|
|  | 67 | +#define MAX_NMI_PS     10 | 
|---|
|  | 68 | + | 
|---|
|  | 69 | +static u8 last_err; | 
|---|
|  | 70 | +static u32 last_address; | 
|---|
|  | 71 | +static unsigned long nmi_repeats; | 
|---|
|  | 72 | +static struct timer_list nmi_timer; | 
|---|
|  | 73 | +static int timer_added; | 
|---|
|  | 74 | +static unsigned long nmi_count; | 
|---|
|  | 75 | +static spinlock_t nmi_state_lock = SPIN_LOCK_UNLOCKED; | 
|---|
|  | 76 | + | 
|---|
|  | 77 | +static inline void | 
|---|
|  | 78 | +ledonoff(unsigned long on, unsigned long off) | 
|---|
|  | 79 | +{ | 
|---|
|  | 80 | +#ifdef CONFIG_COBALT_LED | 
|---|
|  | 81 | +       unsigned long start; | 
|---|
|  | 82 | +       int haltok = current_cpu_data.hlt_works_ok; | 
|---|
|  | 83 | + | 
|---|
|  | 84 | +       if (on) { | 
|---|
|  | 85 | +               start = jiffies; | 
|---|
|  | 86 | +               cobalt_led_set(cobalt_led_get() | LED_SHUTDOWN); | 
|---|
|  | 87 | +               while (jiffies < start + on) { | 
|---|
|  | 88 | +                       if (haltok) __asm__("hlt"); | 
|---|
|  | 89 | +               } | 
|---|
|  | 90 | +       } | 
|---|
|  | 91 | + | 
|---|
|  | 92 | +       if (off) { | 
|---|
|  | 93 | +               start = jiffies; | 
|---|
|  | 94 | +               cobalt_led_set(cobalt_led_get() & ~LED_SHUTDOWN); | 
|---|
|  | 95 | +               while (jiffies < start + off) { | 
|---|
|  | 96 | +                       if (haltok) __asm__("hlt"); | 
|---|
|  | 97 | +               } | 
|---|
|  | 98 | +       } | 
|---|
|  | 99 | +#endif | 
|---|
|  | 100 | +} | 
|---|
|  | 101 | + | 
|---|
|  | 102 | +/* clla this holding nmi_state_lock */ | 
|---|
|  | 103 | +static inline void | 
|---|
|  | 104 | +do_repeats(void) | 
|---|
|  | 105 | +{ | 
|---|
|  | 106 | +       if (nmi_repeats) { | 
|---|
|  | 107 | +               printk("NMI: last error repeated %lu times\n", nmi_repeats); | 
|---|
|  | 108 | +               nmi_repeats = 0; | 
|---|
|  | 109 | +       } | 
|---|
|  | 110 | +} | 
|---|
|  | 111 | + | 
|---|
|  | 112 | +static void | 
|---|
|  | 113 | +nmi_throttle_fn(unsigned long data) | 
|---|
|  | 114 | +{ | 
|---|
|  | 115 | +       unsigned long flags; | 
|---|
|  | 116 | + | 
|---|
|  | 117 | +       spin_lock_irqsave(&nmi_state_lock, flags); | 
|---|
|  | 118 | + | 
|---|
|  | 119 | +       /* clear any repeated NMIs */ | 
|---|
|  | 120 | +       do_repeats(); | 
|---|
|  | 121 | + | 
|---|
|  | 122 | +       /* have we had a lot of errors this second */ | 
|---|
|  | 123 | +       if (nmi_count > MAX_NMI_PS) { | 
|---|
|  | 124 | +               printk("NMI: %lu messages were throttled\n", | 
|---|
|  | 125 | +                       nmi_count - MAX_NMI_PS); | 
|---|
|  | 126 | +               nmi_count = 0; | 
|---|
|  | 127 | +       } | 
|---|
|  | 128 | + | 
|---|
|  | 129 | +       /* de-activate the timer - will be reactivated by an NMI */ | 
|---|
|  | 130 | +       del_timer(&nmi_timer); | 
|---|
|  | 131 | +       timer_added = 0; | 
|---|
|  | 132 | + | 
|---|
|  | 133 | +       spin_unlock_irqrestore(&nmi_state_lock, flags); | 
|---|
|  | 134 | +} | 
|---|
|  | 135 | + | 
|---|
|  | 136 | +void | 
|---|
|  | 137 | +cobalt_nmi(unsigned char reason, struct pt_regs *regs) | 
|---|
|  | 138 | +{ | 
|---|
|  | 139 | +       if (cobt_is_5k()) { | 
|---|
|  | 140 | +               static struct pci_dev *cnb_dev; | 
|---|
|  | 141 | +               u8 err; | 
|---|
|  | 142 | +               u32 address = 0; | 
|---|
|  | 143 | +               unsigned long flags; | 
|---|
|  | 144 | + | 
|---|
|  | 145 | +               /* find our memory controller */ | 
|---|
|  | 146 | +               if (!cnb_dev) { | 
|---|
|  | 147 | +                       cnb_dev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, | 
|---|
|  | 148 | +                                 PCI_DEVICE_ID_SERVERWORKS_LE, NULL); | 
|---|
|  | 149 | +               } | 
|---|
|  | 150 | +               if (!cnb_dev) { | 
|---|
|  | 151 | +                       EPRINTK("can't find north bridge for NMI status\n"); | 
|---|
|  | 152 | +                       return; | 
|---|
|  | 153 | +               } | 
|---|
|  | 154 | + | 
|---|
|  | 155 | +               /* read the error number */ | 
|---|
|  | 156 | +               pci_read_config_byte(cnb_dev, 0x47, &err); | 
|---|
|  | 157 | + | 
|---|
|  | 158 | +               /* if a memory error was detected, where? */ | 
|---|
|  | 159 | +               if (err & 0x06) { | 
|---|
|  | 160 | +                       pci_read_config_dword(cnb_dev, 0x94, &address); | 
|---|
|  | 161 | +               } | 
|---|
|  | 162 | + | 
|---|
|  | 163 | +               spin_lock_irqsave(&nmi_state_lock, flags); | 
|---|
|  | 164 | + | 
|---|
|  | 165 | +               /* set up the timer, if it isn't set to go already */ | 
|---|
|  | 166 | +               if (!timer_added) { | 
|---|
|  | 167 | +                       init_timer(&nmi_timer); | 
|---|
|  | 168 | +                       nmi_timer.expires = jiffies + HZ; | 
|---|
|  | 169 | +                       nmi_timer.function = nmi_throttle_fn; | 
|---|
|  | 170 | +                       add_timer(&nmi_timer); | 
|---|
|  | 171 | +                       timer_added = 1; | 
|---|
|  | 172 | +               } | 
|---|
|  | 173 | + | 
|---|
|  | 174 | +               /* if we already printed this error */ | 
|---|
|  | 175 | +               if (last_err && err == last_err && address == last_address) { | 
|---|
|  | 176 | +                       nmi_repeats++; | 
|---|
|  | 177 | +                       spin_unlock_irqrestore(&nmi_state_lock, flags); | 
|---|
|  | 178 | +               } else { | 
|---|
|  | 179 | +                       unsigned long nmi_now; | 
|---|
|  | 180 | + | 
|---|
|  | 181 | +                       /* different error - show repeats */ | 
|---|
|  | 182 | +                       do_repeats(); | 
|---|
|  | 183 | + | 
|---|
|  | 184 | +                       /* we only want to do a few messages per second */ | 
|---|
|  | 185 | +                       nmi_now = nmi_count++; | 
|---|
|  | 186 | + | 
|---|
|  | 187 | +                       spin_unlock_irqrestore(&nmi_state_lock, flags); | 
|---|
|  | 188 | + | 
|---|
|  | 189 | +                       /* generate a new message */ | 
|---|
|  | 190 | +                       if (nmi_now < MAX_NMI_PS) { | 
|---|
|  | 191 | +                               /* only remember NMIs that we can print */ | 
|---|
|  | 192 | +                               last_err = err; | 
|---|
|  | 193 | +                               last_address = address; | 
|---|
|  | 194 | + | 
|---|
|  | 195 | +                               printk("NMI:"); | 
|---|
|  | 196 | +                               if (err & 0x40) | 
|---|
|  | 197 | +                                       printk(" (PCI tx data error)"); | 
|---|
|  | 198 | +                               if (err & 0x20) | 
|---|
|  | 199 | +                                       printk(" (PCI rx data error)"); | 
|---|
|  | 200 | +                               if (err & 0x10) | 
|---|
|  | 201 | +                                       printk(" (PCI address error)"); | 
|---|
|  | 202 | +                               if (err & 0x04) | 
|---|
|  | 203 | +                                       printk(" (DRAM uncorrectable error)"); | 
|---|
|  | 204 | +                               if (err & 0x02) | 
|---|
|  | 205 | +                                       printk(" (DRAM correctable error)"); | 
|---|
|  | 206 | +                               if (err & 0x01) | 
|---|
|  | 207 | +                                       printk(" (Shutdown cycle detected)"); | 
|---|
|  | 208 | + | 
|---|
|  | 209 | +                               if (err & 0x06) { | 
|---|
|  | 210 | +                                       u8 row, dimm, ecc; | 
|---|
|  | 211 | + | 
|---|
|  | 212 | +                                       row = (address >> 29) & 0x7; | 
|---|
|  | 213 | +                                       pci_read_config_byte(cnb_dev, | 
|---|
|  | 214 | +                                               0x7c + (row >> 1), &dimm); | 
|---|
|  | 215 | +                                       dimm = ((row & 1) ? | 
|---|
|  | 216 | +                                               (dimm >> 4) : dimm) & 0xf; | 
|---|
|  | 217 | +                                       pci_read_config_byte(cnb_dev, 0xe8, | 
|---|
|  | 218 | +                                               &ecc); | 
|---|
|  | 219 | + | 
|---|
|  | 220 | +                                       printk(" [memory row %d, DIMM type %d, " | 
|---|
|  | 221 | +                                               "col=0x%x, row=0x%x, ECC=0x%x]", | 
|---|
|  | 222 | +                                               row, dimm, | 
|---|
|  | 223 | +                                               (address >> 15) & 0x3fff, | 
|---|
|  | 224 | +                                               address & 0x7fff, ecc); | 
|---|
|  | 225 | +                               } | 
|---|
|  | 226 | +                               printk("\n"); | 
|---|
|  | 227 | +                       } | 
|---|
|  | 228 | +               } | 
|---|
|  | 229 | + | 
|---|
|  | 230 | +               /* clear errors */ | 
|---|
|  | 231 | +               pci_write_config_byte(cnb_dev, 0x47, err); | 
|---|
|  | 232 | +       } else { | 
|---|
|  | 233 | +               /* TODO: make throttling generic, handle GP NMIs */ | 
|---|
|  | 234 | +               printk("NMI: unknown error\n"); | 
|---|
|  | 235 | +       } | 
|---|
|  | 236 | +} | 
|---|
|  | 237 | + | 
|---|
|  | 238 | +void | 
|---|
|  | 239 | +cobalt_restart(void) | 
|---|
|  | 240 | +{ | 
|---|
|  | 241 | +       if (cobt_is_3k()) { | 
|---|
|  | 242 | +               /* kick watchdog */ | 
|---|
|  | 243 | +               cobalt_wdt_trigger_reboot(); | 
|---|
|  | 244 | +       } else if (cobt_is_5k()) { | 
|---|
|  | 245 | +               /* set "Enable Hard Reset" bit to 1 */ | 
|---|
|  | 246 | +               outb(0x02, 0x0cf9); | 
|---|
|  | 247 | + | 
|---|
|  | 248 | +               /* 0-to-1 transition of bit 2 will cause reset of processor */ | 
|---|
|  | 249 | +               outb(0x06, 0x0cf9); | 
|---|
|  | 250 | +       } | 
|---|
|  | 251 | +       mdelay(3000); | 
|---|
|  | 252 | + | 
|---|
|  | 253 | +       /* we should not get here unless there is a BAD error */ | 
|---|
|  | 254 | +       EPRINTK("can not restart - halting\n"); | 
|---|
|  | 255 | +       machine_halt(); | 
|---|
|  | 256 | +} | 
|---|
|  | 257 | + | 
|---|
|  | 258 | +void | 
|---|
|  | 259 | +cobalt_halt(void) | 
|---|
|  | 260 | +{ | 
|---|
|  | 261 | +       int haltok = current_cpu_data.hlt_works_ok; | 
|---|
|  | 262 | + | 
|---|
|  | 263 | +       if (cobt_is_5k()) { | 
|---|
|  | 264 | +               /* we have soft power-off */ | 
|---|
|  | 265 | +               machine_power_off(); | 
|---|
|  | 266 | +       } | 
|---|
|  | 267 | + | 
|---|
|  | 268 | +       /* | 
|---|
|  | 269 | +        * we want to do cpu_idle, but we don't actually want to | 
|---|
|  | 270 | +        * call cpu_idle. bleah. | 
|---|
|  | 271 | +        */ | 
|---|
|  | 272 | +       while (1) { | 
|---|
|  | 273 | +               ledonoff(HZ >> 1, HZ >> 1); | 
|---|
|  | 274 | +               if (haltok) { | 
|---|
|  | 275 | +                       __asm__("hlt"); | 
|---|
|  | 276 | +               } | 
|---|
|  | 277 | +       } | 
|---|
|  | 278 | +} | 
|---|
|  | 279 | + | 
|---|
|  | 280 | +void | 
|---|
|  | 281 | +cobalt_power_off(void) | 
|---|
|  | 282 | +{ | 
|---|
|  | 283 | +       u16 addr; | 
|---|
|  | 284 | + | 
|---|
|  | 285 | +       if (cobt_is_monterey()) { | 
|---|
|  | 286 | +               u8 val; | 
|---|
|  | 287 | +               /* use card control reg. 7 to select logical device 2 (APC) */ | 
|---|
|  | 288 | +               addr = superio_ldev_base(PC87317_DEV_RTC); | 
|---|
|  | 289 | + | 
|---|
|  | 290 | +               /* set up bank 2 */ | 
|---|
|  | 291 | +               outb(PC87317_RTC_CRA, addr); | 
|---|
|  | 292 | +               val = inb(addr + 1) & 0x8f; | 
|---|
|  | 293 | +               outb(val | PC87317_RTC_BANK_2, addr + 1); | 
|---|
|  | 294 | + | 
|---|
|  | 295 | +               /* power off the machine with APCR1 */ | 
|---|
|  | 296 | +               outb(PC87317_APCR1, addr); | 
|---|
|  | 297 | +               val = inb(addr + 1); | 
|---|
|  | 298 | +               outb(0x20 | val, addr + 1); | 
|---|
|  | 299 | +       } else if (cobt_is_alpine()) { | 
|---|
|  | 300 | +               int i; | 
|---|
|  | 301 | +               /* clear status bits, base addr 3 */ | 
|---|
|  | 302 | +               addr = superio_ldev_base_n(PC87417_DEV_SWC, 3); | 
|---|
|  | 303 | +               for (i = 0; i < 4; i++) { | 
|---|
|  | 304 | +                       /* | 
|---|
|  | 305 | +                        * if we have an event while running, | 
|---|
|  | 306 | +                        * we can't halt unless we clear these | 
|---|
|  | 307 | +                        * */ | 
|---|
|  | 308 | +                       outb(0xff, addr+i); | 
|---|
|  | 309 | +               } | 
|---|
|  | 310 | + | 
|---|
|  | 311 | +               /* set sleep state, base addr 2 */ | 
|---|
|  | 312 | +               addr = superio_ldev_base_n(PC87417_DEV_SWC, 2); | 
|---|
|  | 313 | +               /* PM1b_CNT_HIGH @offset 1 - set state to S5 */ | 
|---|
|  | 314 | +               outb(0x34, addr+1); | 
|---|
|  | 315 | +       } | 
|---|
|  | 316 | +       mdelay(3000); | 
|---|
|  | 317 | +       EPRINTK("can not power off\n"); | 
|---|
|  | 318 | +} | 
|---|
|  | 319 | + | 
|---|
|  | 320 | +/* put arch specific stuff to run at init time here */ | 
|---|
|  | 321 | +static int __init | 
|---|
|  | 322 | +cobalt_arch_init(void) | 
|---|
|  | 323 | +{ | 
|---|
|  | 324 | +       return 0; | 
|---|
|  | 325 | +} | 
|---|
|  | 326 | +module_init(cobalt_arch_init); | 
|---|
|  | 327 | diff -Naur linux-2.6.20.orig/arch/i386/kernel/process.c linux-2.6.20/arch/i386/kernel/process.c | 
|---|
|  | 328 | --- linux-2.6.20.orig/arch/i386/kernel/process.c        2007-02-04 10:44:54.000000000 -0800 | 
|---|
|  | 329 | +++ linux-2.6.20/arch/i386/kernel/process.c     2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 330 | @@ -52,6 +52,11 @@ | 
|---|
|  | 331 | #include <asm/math_emu.h> | 
|---|
|  | 332 | #endif | 
|---|
|  | 333 |  | 
|---|
|  | 334 | +#ifdef CONFIG_COBALT_RAQ | 
|---|
|  | 335 | +#include <cobalt/misc.h> | 
|---|
|  | 336 | +#include <cobalt/lcd.h> | 
|---|
|  | 337 | +#endif | 
|---|
|  | 338 | + | 
|---|
|  | 339 | #include <linux/err.h> | 
|---|
|  | 340 |  | 
|---|
|  | 341 | #include <asm/tlbflush.h> | 
|---|
|  | 342 | @@ -477,6 +482,12 @@ | 
|---|
|  | 343 | void dump_thread(struct pt_regs * regs, struct user * dump) | 
|---|
|  | 344 | { | 
|---|
|  | 345 | int i; | 
|---|
|  | 346 | + | 
|---|
|  | 347 | +#ifdef CONFIG_COBALT_RAQ | 
|---|
|  | 348 | +       cobalt_flush(); | 
|---|
|  | 349 | +       cobalt_restart(); | 
|---|
|  | 350 | +#endif | 
|---|
|  | 351 | + | 
|---|
|  | 352 |  | 
|---|
|  | 353 | /* changed the size calculations - should hopefully work better. lbt */ | 
|---|
|  | 354 | dump->magic = CMAGIC; | 
|---|
|  | 355 | diff -Naur linux-2.6.20.orig/arch/i386/kernel/reboot.c linux-2.6.20/arch/i386/kernel/reboot.c | 
|---|
|  | 356 | --- linux-2.6.20.orig/arch/i386/kernel/reboot.c 2007-02-04 10:44:54.000000000 -0800 | 
|---|
|  | 357 | +++ linux-2.6.20/arch/i386/kernel/reboot.c      2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 358 | @@ -19,6 +19,11 @@ | 
|---|
|  | 359 | #include "mach_reboot.h" | 
|---|
|  | 360 | #include <linux/reboot_fixups.h> | 
|---|
|  | 361 |  | 
|---|
|  | 362 | +#ifdef CONFIG_COBALT_RAQ | 
|---|
|  | 363 | +#include <cobalt/misc.h> | 
|---|
|  | 364 | +#include <cobalt/lcd.h> | 
|---|
|  | 365 | +#endif | 
|---|
|  | 366 | + | 
|---|
|  | 367 | /* | 
|---|
|  | 368 | * Power off function, if any | 
|---|
|  | 369 | */ | 
|---|
|  | 370 | @@ -280,8 +285,38 @@ | 
|---|
|  | 371 | EXPORT_SYMBOL(machine_real_restart); | 
|---|
|  | 372 | #endif | 
|---|
|  | 373 |  | 
|---|
|  | 374 | +/* kill some time at halt/reboot to allow drives with large cache to sync */ | 
|---|
|  | 375 | + | 
|---|
|  | 376 | +#ifdef CONFIG_COBALT_RAQ | 
|---|
|  | 377 | +void cobalt_flush(void) | 
|---|
|  | 378 | +{ | 
|---|
|  | 379 | +       int i; | 
|---|
|  | 380 | +       static int flushed; | 
|---|
|  | 381 | + | 
|---|
|  | 382 | +       if (flushed) | 
|---|
|  | 383 | +               return; | 
|---|
|  | 384 | +       flushed = 1; | 
|---|
|  | 385 | + | 
|---|
|  | 386 | +       printk("waiting for devices to flush"); | 
|---|
|  | 387 | +       for (i = 0 ; i < 10; i++) { | 
|---|
|  | 388 | +               printk("."); | 
|---|
|  | 389 | +               mdelay(500); | 
|---|
|  | 390 | +#ifdef CONFIG_COBALT_LCD | 
|---|
|  | 391 | +               if (i == 8) | 
|---|
|  | 392 | +                       cobalt_lcd_off(); | 
|---|
|  | 393 | +#endif | 
|---|
|  | 394 | +       } | 
|---|
|  | 395 | +       printk("done\n"); | 
|---|
|  | 396 | +} | 
|---|
|  | 397 | +#endif | 
|---|
|  | 398 | + | 
|---|
|  | 399 | void machine_shutdown(void) | 
|---|
|  | 400 | { | 
|---|
|  | 401 | +#ifdef CONFIG_COBALT_RAQ | 
|---|
|  | 402 | +       cobalt_flush(); | 
|---|
|  | 403 | +       cobalt_halt(); | 
|---|
|  | 404 | +#endif | 
|---|
|  | 405 | + | 
|---|
|  | 406 | #ifdef CONFIG_SMP | 
|---|
|  | 407 | int reboot_cpu_id; | 
|---|
|  | 408 |  | 
|---|
|  | 409 | @@ -318,6 +353,9 @@ | 
|---|
|  | 410 |  | 
|---|
|  | 411 | void machine_emergency_restart(void) | 
|---|
|  | 412 | { | 
|---|
|  | 413 | +#ifdef CONFIG_COBALT_RAQ | 
|---|
|  | 414 | +       cobalt_restart(); | 
|---|
|  | 415 | +#endif | 
|---|
|  | 416 | if (!reboot_thru_bios) { | 
|---|
|  | 417 | if (efi_enabled) { | 
|---|
|  | 418 | efi.reset_system(EFI_RESET_COLD, EFI_SUCCESS, 0, NULL); | 
|---|
|  | 419 | @@ -342,6 +380,10 @@ | 
|---|
|  | 420 |  | 
|---|
|  | 421 | void machine_restart(char * __unused) | 
|---|
|  | 422 | { | 
|---|
|  | 423 | +#ifdef CONFIG_COBALT_RAQ | 
|---|
|  | 424 | +       cobalt_flush(); | 
|---|
|  | 425 | +       cobalt_restart(); | 
|---|
|  | 426 | +#endif | 
|---|
|  | 427 | machine_shutdown(); | 
|---|
|  | 428 | machine_emergency_restart(); | 
|---|
|  | 429 | } | 
|---|
|  | 430 | diff -Naur linux-2.6.20.orig/arch/i386/kernel/traps.c linux-2.6.20/arch/i386/kernel/traps.c | 
|---|
|  | 431 | --- linux-2.6.20.orig/arch/i386/kernel/traps.c  2007-02-04 10:44:54.000000000 -0800 | 
|---|
|  | 432 | +++ linux-2.6.20/arch/i386/kernel/traps.c       2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 433 | @@ -61,6 +61,10 @@ | 
|---|
|  | 434 |  | 
|---|
|  | 435 | int panic_on_unrecovered_nmi; | 
|---|
|  | 436 |  | 
|---|
|  | 437 | +#ifdef CONFIG_COBALT_RAQ | 
|---|
|  | 438 | +#include <cobalt/misc.h> | 
|---|
|  | 439 | +#endif | 
|---|
|  | 440 | + | 
|---|
|  | 441 | asmlinkage int system_call(void); | 
|---|
|  | 442 |  | 
|---|
|  | 443 | /* Do we ignore FPU interrupts ? */ | 
|---|
|  | 444 | @@ -631,6 +635,9 @@ | 
|---|
|  | 445 | static __kprobes void | 
|---|
|  | 446 | mem_parity_error(unsigned char reason, struct pt_regs * regs) | 
|---|
|  | 447 | { | 
|---|
|  | 448 | +#ifdef CONFIG_COBALT_RAQ | 
|---|
|  | 449 | +       cobalt_nmi(reason, regs); | 
|---|
|  | 450 | +#else | 
|---|
|  | 451 | printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on " | 
|---|
|  | 452 | "CPU %d.\n", reason, smp_processor_id()); | 
|---|
|  | 453 | printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n"); | 
|---|
|  | 454 | @@ -638,7 +645,7 @@ | 
|---|
|  | 455 | panic("NMI: Not continuing"); | 
|---|
|  | 456 |  | 
|---|
|  | 457 | printk(KERN_EMERG "Dazed and confused, but trying to continue\n"); | 
|---|
|  | 458 | - | 
|---|
|  | 459 | +#endif | 
|---|
|  | 460 | /* Clear and disable the memory parity error line. */ | 
|---|
|  | 461 | clear_mem_error(reason); | 
|---|
|  | 462 | } | 
|---|
|  | 463 | diff -Naur linux-2.6.20.orig/drivers/Kconfig linux-2.6.20/drivers/Kconfig | 
|---|
|  | 464 | --- linux-2.6.20.orig/drivers/Kconfig   2007-02-04 10:44:54.000000000 -0800 | 
|---|
|  | 465 | +++ linux-2.6.20/drivers/Kconfig        2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 466 | @@ -82,4 +82,6 @@ | 
|---|
|  | 467 |  | 
|---|
|  | 468 | source "drivers/kvm/Kconfig" | 
|---|
|  | 469 |  | 
|---|
|  | 470 | +source "drivers/cobalt/Kconfig" | 
|---|
|  | 471 | + | 
|---|
|  | 472 | endmenu | 
|---|
|  | 473 | diff -Naur linux-2.6.20.orig/drivers/Makefile linux-2.6.20/drivers/Makefile | 
|---|
|  | 474 | --- linux-2.6.20.orig/drivers/Makefile  2007-02-04 10:44:54.000000000 -0800 | 
|---|
|  | 475 | +++ linux-2.6.20/drivers/Makefile       2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 476 | @@ -67,6 +67,8 @@ | 
|---|
|  | 477 | obj-$(CONFIG_EDAC)             += edac/ | 
|---|
|  | 478 | obj-$(CONFIG_MCA)              += mca/ | 
|---|
|  | 479 | obj-$(CONFIG_EISA)             += eisa/ | 
|---|
|  | 480 | +obj-$(CONFIG_COBALT_RAQ)       += cobalt/ | 
|---|
|  | 481 | + | 
|---|
|  | 482 | obj-$(CONFIG_CPU_FREQ)         += cpufreq/ | 
|---|
|  | 483 | obj-$(CONFIG_MMC)              += mmc/ | 
|---|
|  | 484 | obj-$(CONFIG_NEW_LEDS)         += leds/ | 
|---|
|  | 485 | diff -Naur linux-2.6.20.orig/drivers/char/Kconfig linux-2.6.20/drivers/char/Kconfig | 
|---|
|  | 486 | --- linux-2.6.20.orig/drivers/char/Kconfig      2007-02-04 10:44:54.000000000 -0800 | 
|---|
|  | 487 | +++ linux-2.6.20/drivers/char/Kconfig   2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 488 | @@ -808,7 +808,7 @@ | 
|---|
|  | 489 | will get access to the real time clock (or hardware clock) built | 
|---|
|  | 490 | into your computer. | 
|---|
|  | 491 |  | 
|---|
|  | 492 | -config COBALT_LCD | 
|---|
|  | 493 | +config COBALT_MIPS_LCD | 
|---|
|  | 494 | bool "Support for Cobalt LCD" | 
|---|
|  | 495 | depends on MIPS_COBALT | 
|---|
|  | 496 | help | 
|---|
|  | 497 | diff -Naur linux-2.6.20.orig/drivers/char/Makefile linux-2.6.20/drivers/char/Makefile | 
|---|
|  | 498 | --- linux-2.6.20.orig/drivers/char/Makefile     2007-02-04 10:44:54.000000000 -0800 | 
|---|
|  | 499 | +++ linux-2.6.20/drivers/char/Makefile  2007-02-04 20:38:36.000000000 -0800 | 
|---|
|  | 500 | @@ -79,7 +79,7 @@ | 
|---|
|  | 501 | obj-$(CONFIG_I8K)              += i8k.o | 
|---|
|  | 502 | obj-$(CONFIG_DS1620)           += ds1620.o | 
|---|
|  | 503 | obj-$(CONFIG_HW_RANDOM)                += hw_random/ | 
|---|
|  | 504 | -obj-$(CONFIG_COBALT_LCD)       += lcd.o | 
|---|
|  | 505 | +obj-$(CONFIG_COBALT_MIPS_LCD)  += lcd.o | 
|---|
|  | 506 | obj-$(CONFIG_PPDEV)            += ppdev.o | 
|---|
|  | 507 | obj-$(CONFIG_NWBUTTON)         += nwbutton.o | 
|---|
|  | 508 | obj-$(CONFIG_NWFLASH)          += nwflash.o | 
|---|
|  | 509 | diff -Naur linux-2.6.20.orig/drivers/char/misc.c linux-2.6.20/drivers/char/misc.c | 
|---|
|  | 510 | --- linux-2.6.20.orig/drivers/char/misc.c       2007-02-04 10:44:54.000000000 -0800 | 
|---|
|  | 511 | +++ linux-2.6.20/drivers/char/misc.c    2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 512 | @@ -49,6 +49,17 @@ | 
|---|
|  | 513 | #include <linux/tty.h> | 
|---|
|  | 514 | #include <linux/kmod.h> | 
|---|
|  | 515 |  | 
|---|
|  | 516 | +#ifdef CONFIG_COBALT_RAQ | 
|---|
|  | 517 | +#include <cobalt/cobalt.h> | 
|---|
|  | 518 | +#include <cobalt/systype.h> | 
|---|
|  | 519 | +#include <cobalt/superio.h> | 
|---|
|  | 520 | +#include <cobalt/serialnum.h> | 
|---|
|  | 521 | +#include <cobalt/i2c.h> | 
|---|
|  | 522 | +#include <cobalt/misc.h> | 
|---|
|  | 523 | +#include <cobalt/lcd.h> | 
|---|
|  | 524 | +#endif | 
|---|
|  | 525 | + | 
|---|
|  | 526 | + | 
|---|
|  | 527 | /* | 
|---|
|  | 528 | * Head entry for the doubly linked miscdevice list | 
|---|
|  | 529 | */ | 
|---|
|  | 530 | @@ -63,6 +74,13 @@ | 
|---|
|  | 531 |  | 
|---|
|  | 532 | extern int pmu_device_init(void); | 
|---|
|  | 533 |  | 
|---|
|  | 534 | +#ifdef CONFIG_COBALT_RAQ | 
|---|
|  | 535 | +extern int cobalt_init(void); | 
|---|
|  | 536 | +#endif | 
|---|
|  | 537 | +#ifdef CONFIG_COBALT_MIPS_LCD | 
|---|
|  | 538 | +module_init(lcd_init); | 
|---|
|  | 539 | +#endif | 
|---|
|  | 540 | + | 
|---|
|  | 541 | #ifdef CONFIG_PROC_FS | 
|---|
|  | 542 | static void *misc_seq_start(struct seq_file *seq, loff_t *pos) | 
|---|
|  | 543 | { | 
|---|
|  | 544 | diff -Naur linux-2.6.20.orig/drivers/char/nvram.c linux-2.6.20/drivers/char/nvram.c | 
|---|
|  | 545 | --- linux-2.6.20.orig/drivers/char/nvram.c      2007-02-04 10:44:54.000000000 -0800 | 
|---|
|  | 546 | +++ linux-2.6.20/drivers/char/nvram.c   2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 547 | @@ -49,8 +49,7 @@ | 
|---|
|  | 548 | #if defined(CONFIG_ATARI) | 
|---|
|  | 549 | #  define MACH ATARI | 
|---|
|  | 550 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__)  /* and others?? */ | 
|---|
|  | 551 | -#define MACH PC | 
|---|
|  | 552 | -#  if defined(CONFIG_COBALT) | 
|---|
|  | 553 | +#  if defined(CONFIG_COBALT_RAQ) | 
|---|
|  | 554 | #    include <linux/cobalt-nvram.h> | 
|---|
|  | 555 | #    define MACH COBALT | 
|---|
|  | 556 | #  else | 
|---|
|  | 557 | diff -Naur linux-2.6.20.orig/drivers/cobalt/Kconfig linux-2.6.20/drivers/cobalt/Kconfig | 
|---|
|  | 558 | --- linux-2.6.20.orig/drivers/cobalt/Kconfig    1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 559 | +++ linux-2.6.20/drivers/cobalt/Kconfig 2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 560 | @@ -0,0 +1,133 @@ | 
|---|
|  | 561 | +# | 
|---|
|  | 562 | +# Cobalt Drivers | 
|---|
|  | 563 | +# | 
|---|
|  | 564 | + | 
|---|
|  | 565 | +menu "Cobalt RaQ/Qube Hardware" | 
|---|
|  | 566 | + | 
|---|
|  | 567 | +config COBALT_RAQ | 
|---|
|  | 568 | +       bool "Cobalt RaQ/Qube Hardware Support" | 
|---|
|  | 569 | +       select INPUT | 
|---|
|  | 570 | +       default n | 
|---|
|  | 571 | +       ---help--- | 
|---|
|  | 572 | +         NOTE: This support is for x86 Cobalts, not MIPS versions | 
|---|
|  | 573 | + | 
|---|
|  | 574 | +         If you have a Gen III or Gen V Cobalt RaQ/Qube machine, it's probably | 
|---|
|  | 575 | +         a good idea to say Y here and choose from the options below. | 
|---|
|  | 576 | + | 
|---|
|  | 577 | +config COBALT_GEN_III | 
|---|
|  | 578 | +       bool "Gen III (3000 series) system support" | 
|---|
|  | 579 | +       depends on COBALT_RAQ | 
|---|
|  | 580 | +       default y | 
|---|
|  | 581 | +       ---help--- | 
|---|
|  | 582 | +         If you have one of the following Gen III Cobalt systems, say Y here. | 
|---|
|  | 583 | +         Otherwise, it's best to say N. | 
|---|
|  | 584 | + | 
|---|
|  | 585 | +          - RaQ 3 | 
|---|
|  | 586 | +          - RaQ 4 | 
|---|
|  | 587 | +          - Qube3 | 
|---|
|  | 588 | + | 
|---|
|  | 589 | +config COBALT_GEN_V | 
|---|
|  | 590 | +       bool "Gen V (5000 series) system support" | 
|---|
|  | 591 | +       depends on COBALT_RAQ | 
|---|
|  | 592 | +       default n | 
|---|
|  | 593 | +       ---help--- | 
|---|
|  | 594 | +         If you have one of the following Gen V Cobalt systems, say Y here. | 
|---|
|  | 595 | +         Otherwise, it's best to say N. | 
|---|
|  | 596 | + | 
|---|
|  | 597 | +          - RaQ XTR | 
|---|
|  | 598 | +          - RaQ550 | 
|---|
|  | 599 | + | 
|---|
|  | 600 | +config COBALT_OLDPROC | 
|---|
|  | 601 | +       bool "Create legacy /proc files" | 
|---|
|  | 602 | +       depends on COBALT_RAQ | 
|---|
|  | 603 | +       default y | 
|---|
|  | 604 | +       ---help--- | 
|---|
|  | 605 | +         Creates entries in /proc/cobalt which provide useful information about | 
|---|
|  | 606 | +         your RaQ/Qube.  Best to say Y here. | 
|---|
|  | 607 | + | 
|---|
|  | 608 | +menu "Cobalt Hardware Options" | 
|---|
|  | 609 | +       depends on COBALT_RAQ | 
|---|
|  | 610 | + | 
|---|
|  | 611 | +       config COBALT_LCD | 
|---|
|  | 612 | +                       bool "Front panel LCD support" | 
|---|
|  | 613 | +                       default y | 
|---|
|  | 614 | +                       ---help--- | 
|---|
|  | 615 | +                         Handles support for the front panel LCD screen and buttons. | 
|---|
|  | 616 | + | 
|---|
|  | 617 | +       config COBALT_LCD_TWIDDLE | 
|---|
|  | 618 | +                       bool "Twiddle LCD on boot" | 
|---|
|  | 619 | +                       depends on COBALT_LCD | 
|---|
|  | 620 | +                       default y | 
|---|
|  | 621 | +                       ---help--- | 
|---|
|  | 622 | +                         Gives you a nice little twiddle on the LCD while booting. | 
|---|
|  | 623 | + | 
|---|
|  | 624 | +       config COBALT_LED | 
|---|
|  | 625 | +                       bool "Software controlled LED support" | 
|---|
|  | 626 | +                       default y | 
|---|
|  | 627 | +                       ---help--- | 
|---|
|  | 628 | +                         Allows software to play with the LEDs on the front of the | 
|---|
|  | 629 | +                         system. | 
|---|
|  | 630 | + | 
|---|
|  | 631 | +       config COBALT_SERNUM | 
|---|
|  | 632 | +                       tristate "Serial number support" | 
|---|
|  | 633 | +                       depends on COBALT_OLDPROC | 
|---|
|  | 634 | +                       default y | 
|---|
|  | 635 | +                       ---help--- | 
|---|
|  | 636 | +                         Allows you to retrieve the system's serial number via a /proc | 
|---|
|  | 637 | +                         entry. | 
|---|
|  | 638 | + | 
|---|
|  | 639 | +       config COBALT_WDT | 
|---|
|  | 640 | +                       bool "Watchdog timer support" | 
|---|
|  | 641 | +                       depends on WATCHDOG | 
|---|
|  | 642 | +                       default y | 
|---|
|  | 643 | +                       ---help--- | 
|---|
|  | 644 | +                         w00f? | 
|---|
|  | 645 | + | 
|---|
|  | 646 | +       config COBALT_SENSORS | 
|---|
|  | 647 | +                       bool "System sensors support" | 
|---|
|  | 648 | +                       depends on COBALT_OLDPROC | 
|---|
|  | 649 | +                       default y | 
|---|
|  | 650 | +                       ---help--- | 
|---|
|  | 651 | +                         Allows you to retrieve system temperatures via /proc entries. | 
|---|
|  | 652 | + | 
|---|
|  | 653 | +       config COBALT_FANS | 
|---|
|  | 654 | +                       tristate "Fan tachometer support" | 
|---|
|  | 655 | +                       depends on COBALT_OLDPROC | 
|---|
|  | 656 | +                       depends on COBALT_GEN_V | 
|---|
|  | 657 | +                       default y | 
|---|
|  | 658 | +                       ---help--- | 
|---|
|  | 659 | +                         Allows you to retrieve fan speeds via /proc entries. | 
|---|
|  | 660 | + | 
|---|
|  | 661 | +       config COBALT_RAMINFO | 
|---|
|  | 662 | +                       tristate "Memory information support" | 
|---|
|  | 663 | +                       depends on COBALT_OLDPROC | 
|---|
|  | 664 | +                       default y | 
|---|
|  | 665 | +                       ---help--- | 
|---|
|  | 666 | +                         Got DIMMs?  This will tell you how much and in which slot via a | 
|---|
|  | 667 | +                         /proc entry. | 
|---|
|  | 668 | + | 
|---|
|  | 669 | +       config COBALT_RULER | 
|---|
|  | 670 | +                       bool "Disk drive ruler support" | 
|---|
|  | 671 | +                       depends on COBALT_OLDPROC | 
|---|
|  | 672 | +                       depends on COBALT_GEN_V | 
|---|
|  | 673 | +                       default y | 
|---|
|  | 674 | +                       ---help--- | 
|---|
|  | 675 | +                         Not sure what this does... A purple tape measure maybe? | 
|---|
|  | 676 | + | 
|---|
|  | 677 | +       config COBALT_ACPI | 
|---|
|  | 678 | +                       bool "Cobalt ACPI support" | 
|---|
|  | 679 | +                       depends on COBALT_GEN_V | 
|---|
|  | 680 | +                       default y | 
|---|
|  | 681 | +                       ---help--- | 
|---|
|  | 682 | +                         ACPI support for the Generation V Cobalts. | 
|---|
|  | 683 | + | 
|---|
|  | 684 | +       config COBALT_EMU_ACPI | 
|---|
|  | 685 | +                       bool "/proc/acpi emulation" | 
|---|
|  | 686 | +                       depends on COBALT_ACPI | 
|---|
|  | 687 | +                       default y | 
|---|
|  | 688 | +                       ---help--- | 
|---|
|  | 689 | +                         Emulates the /proc/acpi interface. | 
|---|
|  | 690 | + | 
|---|
|  | 691 | +endmenu | 
|---|
|  | 692 | + | 
|---|
|  | 693 | +endmenu | 
|---|
|  | 694 | diff -Naur linux-2.6.20.orig/drivers/cobalt/Makefile linux-2.6.20/drivers/cobalt/Makefile | 
|---|
|  | 695 | --- linux-2.6.20.orig/drivers/cobalt/Makefile   1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 696 | +++ linux-2.6.20/drivers/cobalt/Makefile        2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 697 | @@ -0,0 +1,18 @@ | 
|---|
|  | 698 | +# | 
|---|
|  | 699 | +# Makefile for the Sun/Cobalt device drivers | 
|---|
|  | 700 | +# | 
|---|
|  | 701 | + | 
|---|
|  | 702 | +#O_TARGET := cobalt.o | 
|---|
|  | 703 | + | 
|---|
|  | 704 | +#export-objs := init.o systype.o wdt.o i2c.o | 
|---|
|  | 705 | + | 
|---|
|  | 706 | +obj-$(CONFIG_COBALT_RAQ)       += init.o systype.o i2c.o wdt.o | 
|---|
|  | 707 | +obj-$(CONFIG_COBALT_ACPI)      += acpi.o | 
|---|
|  | 708 | +obj-$(CONFIG_COBALT_SERNUM)    += serialnum.o | 
|---|
|  | 709 | +obj-$(CONFIG_COBALT_LCD)       += lcd.o | 
|---|
|  | 710 | +obj-$(CONFIG_COBALT_LED)       += net.o led.o | 
|---|
|  | 711 | +obj-$(CONFIG_COBALT_SENSORS)   += sensors.o | 
|---|
|  | 712 | +obj-$(CONFIG_COBALT_FANS)      += fans.o | 
|---|
|  | 713 | +obj-$(CONFIG_COBALT_RAMINFO)   += raminfo.o | 
|---|
|  | 714 | +obj-$(CONFIG_COBALT_RULER)     += ruler.o | 
|---|
|  | 715 | + | 
|---|
|  | 716 | diff -Naur linux-2.6.20.orig/drivers/cobalt/README linux-2.6.20/drivers/cobalt/README | 
|---|
|  | 717 | --- linux-2.6.20.orig/drivers/cobalt/README     1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 718 | +++ linux-2.6.20/drivers/cobalt/README  2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 719 | @@ -0,0 +1,19 @@ | 
|---|
|  | 720 | +Notes on Cobalt's drivers: | 
|---|
|  | 721 | + | 
|---|
|  | 722 | +You will notice in several places constructs such as this: | 
|---|
|  | 723 | + | 
|---|
|  | 724 | +       if (cobt_is_3k()) { | 
|---|
|  | 725 | +               foo(); | 
|---|
|  | 726 | +       } else if (cobt_is_5k()) { | 
|---|
|  | 727 | +               bar(); | 
|---|
|  | 728 | +       } | 
|---|
|  | 729 | + | 
|---|
|  | 730 | +The goal here is to only compile in code that is needed, but to allow one to | 
|---|
|  | 731 | +define support for both 3k and 5k (and more?) style systems.  The systype | 
|---|
|  | 732 | +check macros are very simple and clean.  They check whether config-time | 
|---|
|  | 733 | +support for the generation has been enabled, and (if so) whether the current | 
|---|
|  | 734 | +systype matches the spcified generation.  This leaves the code free from | 
|---|
|  | 735 | +#ifdef cruft, but lets the compiler throw out unsupported generation-specific | 
|---|
|  | 736 | +code with if (0) detection. | 
|---|
|  | 737 | + | 
|---|
|  | 738 | +-- | 
|---|
|  | 739 | diff -Naur linux-2.6.20.orig/drivers/cobalt/acpi.c linux-2.6.20/drivers/cobalt/acpi.c | 
|---|
|  | 740 | --- linux-2.6.20.orig/drivers/cobalt/acpi.c     1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 741 | +++ linux-2.6.20/drivers/cobalt/acpi.c  2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 742 | @@ -0,0 +1,1994 @@ | 
|---|
|  | 743 | + /* | 
|---|
|  | 744 | + * cobalt acpi driver | 
|---|
|  | 745 | + * Copyright (c) 2000, Cobalt Networks, Inc. | 
|---|
|  | 746 | + * Copyright (c) 2001, Sun Microsystems, Inc. | 
|---|
|  | 747 | + * $Id: acpi.c,v 1.32 2002/06/26 19:08:54 duncan Exp $ | 
|---|
|  | 748 | + * | 
|---|
|  | 749 | + * author: asun@cobalt.com, thockin@sun.com | 
|---|
|  | 750 | + * modified by: jeff@404ster.com | 
|---|
|  | 751 | + * | 
|---|
|  | 752 | + * this driver just sets stuff up for ACPI interrupts | 
|---|
|  | 753 | + * | 
|---|
|  | 754 | + * if acpi support really existed in the kernel, we would read | 
|---|
|  | 755 | + * data from the ACPI tables. however, it doesn't. as a result, | 
|---|
|  | 756 | + * we use some hardcoded values. | 
|---|
|  | 757 | + * | 
|---|
|  | 758 | + * This should be SMP safe.  The only data that needs protection is the acpi | 
|---|
|  | 759 | + * handler list.  It gets scanned at timer-interrupts, must use | 
|---|
|  | 760 | + * irqsave/restore locks. Read/write locks would be useful if there were any | 
|---|
|  | 761 | + * other times that the list was read but never written. --TPH | 
|---|
|  | 762 | + * | 
|---|
|  | 763 | + * /proc/acpi emulation emulates the /proc/acpi/events interface supplied by | 
|---|
|  | 764 | + * the INTEL acpi drivers.  A lot of the code to handle it has been adapted | 
|---|
|  | 765 | + * from there. | 
|---|
|  | 766 | + */ | 
|---|
|  | 767 | + | 
|---|
|  | 768 | +#include <stdarg.h> | 
|---|
|  | 769 | +#include <stddef.h> | 
|---|
|  | 770 | +#include <linux/init.h> | 
|---|
|  | 771 | +#include <linux/sched.h> | 
|---|
|  | 772 | +#include <linux/config.h> | 
|---|
|  | 773 | +#include <linux/pci.h> | 
|---|
|  | 774 | +#include <linux/sched.h> | 
|---|
|  | 775 | +#include <linux/ioport.h> | 
|---|
|  | 776 | +#include <linux/delay.h> | 
|---|
|  | 777 | +#include <linux/spinlock.h> | 
|---|
|  | 778 | +#include <linux/proc_fs.h> | 
|---|
|  | 779 | +#include <linux/poll.h> | 
|---|
|  | 780 | +#include <linux/interrupt.h> | 
|---|
|  | 781 | +#include <asm/uaccess.h> | 
|---|
|  | 782 | +#include <asm/io.h> | 
|---|
|  | 783 | +#include <asm/irq.h> | 
|---|
|  | 784 | + | 
|---|
|  | 785 | +#include <cobalt/cobalt.h> | 
|---|
|  | 786 | +#include <cobalt/systype.h> | 
|---|
|  | 787 | +#include <cobalt/acpi.h> | 
|---|
|  | 788 | +#include <cobalt/superio.h> | 
|---|
|  | 789 | + | 
|---|
|  | 790 | +#define ACPI_DRIVER                    "Cobalt Networks ACPI driver" | 
|---|
|  | 791 | +#define ACPI_DRIVER_VMAJ               1 | 
|---|
|  | 792 | +#define ACPI_DRIVER_VMIN               0 | 
|---|
|  | 793 | + | 
|---|
|  | 794 | +#define POWER_BUTTON_SHUTDOWN  0 | 
|---|
|  | 795 | + | 
|---|
|  | 796 | +#define ACPI_IRQ       10      /* XXX: hardcoded interrupt */ | 
|---|
|  | 797 | +#define ACPI_NAME      "sci" | 
|---|
|  | 798 | +#define ACPI_MAGIC     0xc0b7ac21 | 
|---|
|  | 799 | + | 
|---|
|  | 800 | +#define SUPERIO_EVENT  0xff | 
|---|
|  | 801 | +#define OSB4_EVENT     0x40 | 
|---|
|  | 802 | +#define OSB4_INDEX_PORT        SERVERWORKS_ACPI_INDEX_PORT | 
|---|
|  | 803 | +#define OSB4_DATA_PORT SERVERWORKS_ACPI_DATA_PORT | 
|---|
|  | 804 | + | 
|---|
|  | 805 | +#define GEN_ACPI_TMR_STS      (0x1 <<  0) | 
|---|
|  | 806 | +#define GEN_ACPI_BM_STS       (0x1 <<  4) | 
|---|
|  | 807 | +#define GEN_ACPI_GBL_STS      (0x1 <<  5) | 
|---|
|  | 808 | +#define GEN_ACPI_PWRBTN_STS   (0x1 <<  8) | 
|---|
|  | 809 | +#define GEN_ACPI_SLPBTN_STS   (0x1 <<  9) | 
|---|
|  | 810 | +#define GEN_ACPI_RTC_STS      (0x1 << 10) | 
|---|
|  | 811 | +#define GEN_ACPI_WAK_STS      (0x1 << 15) | 
|---|
|  | 812 | + | 
|---|
|  | 813 | +#ifdef CONFIG_COBALT_EMU_ACPI | 
|---|
|  | 814 | +static int cobalt_acpi_setup_proc(void); | 
|---|
|  | 815 | +static int cobalt_acpi_open_event(struct inode *inode, struct file *file); | 
|---|
|  | 816 | +static int cobalt_acpi_close_event(struct inode *inode, struct file *file); | 
|---|
|  | 817 | +static ssize_t cobalt_acpi_read_event(struct file *file, char *buf, | 
|---|
|  | 818 | +       size_t count, loff_t *ppos); | 
|---|
|  | 819 | +static unsigned int cobalt_acpi_poll_event(struct file *file, poll_table *wait); | 
|---|
|  | 820 | +#endif | 
|---|
|  | 821 | + | 
|---|
|  | 822 | + | 
|---|
|  | 823 | + | 
|---|
|  | 824 | +typedef struct | 
|---|
|  | 825 | +{ | 
|---|
|  | 826 | +    u16 hw_type; | 
|---|
|  | 827 | +    cobalt_acpi_hw_handler hw_handler; | 
|---|
|  | 828 | +    cobalt_acpi_enable_handler en_handler; | 
|---|
|  | 829 | +    void *data; | 
|---|
|  | 830 | +    struct list_head link; | 
|---|
|  | 831 | +} hw_handler_datum; | 
|---|
|  | 832 | + | 
|---|
|  | 833 | +typedef struct | 
|---|
|  | 834 | +{ | 
|---|
|  | 835 | +    u16 hw_type; | 
|---|
|  | 836 | +    u16 table_len; | 
|---|
|  | 837 | +    u16 *table; | 
|---|
|  | 838 | +    struct list_head link; | 
|---|
|  | 839 | +} trans_table_datum; | 
|---|
|  | 840 | + | 
|---|
|  | 841 | +typedef struct | 
|---|
|  | 842 | +{ | 
|---|
|  | 843 | +    cobalt_acpi_evt_handler handler; | 
|---|
|  | 844 | +    u16 ev_type; | 
|---|
|  | 845 | +    void *data; | 
|---|
|  | 846 | +    struct list_head link; | 
|---|
|  | 847 | +} evt_handler_datum; | 
|---|
|  | 848 | + | 
|---|
|  | 849 | +typedef struct | 
|---|
|  | 850 | +{ | 
|---|
|  | 851 | +    cobalt_acpi_evt evt; | 
|---|
|  | 852 | +    struct list_head link; | 
|---|
|  | 853 | +} evt_list_datum; | 
|---|
|  | 854 | + | 
|---|
|  | 855 | +static LIST_HEAD( hw_handler_list ); | 
|---|
|  | 856 | +static spinlock_t hw_handler_list_lock = SPIN_LOCK_UNLOCKED; | 
|---|
|  | 857 | +static LIST_HEAD( trans_table_list ); | 
|---|
|  | 858 | +static spinlock_t trans_table_list_lock = SPIN_LOCK_UNLOCKED; | 
|---|
|  | 859 | +static LIST_HEAD( evt_handler_list ); | 
|---|
|  | 860 | +static spinlock_t evt_handler_list_lock = SPIN_LOCK_UNLOCKED; | 
|---|
|  | 861 | +static LIST_HEAD( dispatch_queue ); | 
|---|
|  | 862 | +static spinlock_t dispatch_queue_lock = SPIN_LOCK_UNLOCKED; | 
|---|
|  | 863 | + | 
|---|
|  | 864 | +typedef struct | 
|---|
|  | 865 | +{ | 
|---|
|  | 866 | +    u16 hw_type; | 
|---|
|  | 867 | + | 
|---|
|  | 868 | +       /* block lengths */ | 
|---|
|  | 869 | +    u16 pm1_evt_len; | 
|---|
|  | 870 | +    u16 pm1_cnt_len; | 
|---|
|  | 871 | +    u16 pm2_cnt_len; | 
|---|
|  | 872 | +    u16 pm_tmr_len; | 
|---|
|  | 873 | +    u16 gpe0_len; | 
|---|
|  | 874 | +    u16 gpe1_len; | 
|---|
|  | 875 | + | 
|---|
|  | 876 | +       /* block I/O locations */ | 
|---|
|  | 877 | +    u16 pm1a_evt_blk; | 
|---|
|  | 878 | +    u16 pm1b_evt_blk; | 
|---|
|  | 879 | +    u16 pm1a_cnt_blk; | 
|---|
|  | 880 | +    u16 pm1b_cnt_blk; | 
|---|
|  | 881 | +    u16 pm2_cnt_blk; | 
|---|
|  | 882 | +    u16 pm_tmr_blk; | 
|---|
|  | 883 | +    u16 p_blk; | 
|---|
|  | 884 | +    u16 gpe0_blk; | 
|---|
|  | 885 | +    u16 gpe1_blk; | 
|---|
|  | 886 | + | 
|---|
|  | 887 | +       /* ponters to strings for the io names */ | 
|---|
|  | 888 | +    char *pm1a_evt_nam; | 
|---|
|  | 889 | +    char *pm1b_evt_nam; | 
|---|
|  | 890 | +    char *pm1a_cnt_nam; | 
|---|
|  | 891 | +    char *pm1b_cnt_nam; | 
|---|
|  | 892 | +    char *pm2_cnt_nam; | 
|---|
|  | 893 | +    char *pm_tmr_nam; | 
|---|
|  | 894 | +    char *p_nam; | 
|---|
|  | 895 | +    char *gpe0_nam; | 
|---|
|  | 896 | +    char *gpe1_nam; | 
|---|
|  | 897 | + | 
|---|
|  | 898 | +       /* reference counts for events */ | 
|---|
|  | 899 | +    atomic_t tmr_ref_cnt; | 
|---|
|  | 900 | +    atomic_t bm_ref_cnt; | 
|---|
|  | 901 | +    atomic_t gbl_ref_cnt; | 
|---|
|  | 902 | +    atomic_t pwrbtn_ref_cnt; | 
|---|
|  | 903 | +    atomic_t slpbtn_ref_cnt; | 
|---|
|  | 904 | +    atomic_t rtc_ref_cnt; | 
|---|
|  | 905 | +    atomic_t wak_ref_cnt; | 
|---|
|  | 906 | +    atomic_t *gpe_ref_cnt; | 
|---|
|  | 907 | + | 
|---|
|  | 908 | + | 
|---|
|  | 909 | +} generic_acpi_regions; | 
|---|
|  | 910 | + | 
|---|
|  | 911 | + | 
|---|
|  | 912 | +static void cobalt_acpi_enable_event( u16 ev_type, int en ); | 
|---|
|  | 913 | +static void cobalt_acpi_run_enable_handler( u16 hw_type, u16 ev_type, | 
|---|
|  | 914 | +                                           u16 ev_data, int en); | 
|---|
|  | 915 | +static int cobalt_acpi_apply_evt_handlers( evt_list_datum *d ); | 
|---|
|  | 916 | +static int cobalt_acpi_run_dispatch_queue( void ); | 
|---|
|  | 917 | +static irqreturn_t acpi_interrupt(int irq, void *dev_id, struct pt_regs *regs); | 
|---|
|  | 918 | +static void cobalt_acpi_cleanup( void ); | 
|---|
|  | 919 | + | 
|---|
|  | 920 | +static int register_acpi_regions( generic_acpi_regions *regions, char * subsys_name ); | 
|---|
|  | 921 | +static int unregister_acpi_regions( generic_acpi_regions *regions ); | 
|---|
|  | 922 | +static void cobalt_acpi_handle_pm1_blk( u16 io_addr, u16 len, | 
|---|
|  | 923 | +                                       generic_acpi_regions * regions ); | 
|---|
|  | 924 | +static void cobalt_acpi_handle_gpe_blk( u16 io_addr, u16 len, | 
|---|
|  | 925 | +                                       generic_acpi_regions * regions ); | 
|---|
|  | 926 | +static int cobalt_acpi_generic_hw_handler( int irq, void *dev_id, | 
|---|
|  | 927 | +                                          struct pt_regs *regs, void * data ); | 
|---|
|  | 928 | + | 
|---|
|  | 929 | +static int cobalt_acpi_osb4_init( void ); | 
|---|
|  | 930 | +static int cobalt_acpi_osb4_cleanup( void ); | 
|---|
|  | 931 | +static int get_osb4_regions( generic_acpi_regions *regions); | 
|---|
|  | 932 | + | 
|---|
|  | 933 | +static int cobalt_acpi_csb5_init( void ); | 
|---|
|  | 934 | +static int cobalt_acpi_csb5_cleanup( void ); | 
|---|
|  | 935 | +static int get_csb5_regions( generic_acpi_regions *regions); | 
|---|
|  | 936 | + | 
|---|
|  | 937 | +static int cobalt_acpi_pc8731x_init( void ); | 
|---|
|  | 938 | +static int cobalt_acpi_pc8731x_cleanup( void ); | 
|---|
|  | 939 | +static int get_pc8731x_regions( generic_acpi_regions *regions ); | 
|---|
|  | 940 | + | 
|---|
|  | 941 | +static int cobalt_acpi_pc8741x_init( void ); | 
|---|
|  | 942 | +static int cobalt_acpi_pc8741x_cleanup( void ); | 
|---|
|  | 943 | +static int get_pc8741x_regions( generic_acpi_regions *regions ); | 
|---|
|  | 944 | + | 
|---|
|  | 945 | +static int cobalt_acpi_monterey_init( void ); | 
|---|
|  | 946 | +static int cobalt_acpi_monterey_cleanup( void ); | 
|---|
|  | 947 | + | 
|---|
|  | 948 | +static int cobalt_acpi_alpine_init( void ); | 
|---|
|  | 949 | +static int cobalt_acpi_alpine_cleanup( void ); | 
|---|
|  | 950 | + | 
|---|
|  | 951 | +static __inline__ struct list_head *list_pop( struct list_head *head ) | 
|---|
|  | 952 | +{ | 
|---|
|  | 953 | +    struct list_head *e; | 
|---|
|  | 954 | + | 
|---|
|  | 955 | +    if( list_empty( head ) ) | 
|---|
|  | 956 | +       return NULL; | 
|---|
|  | 957 | + | 
|---|
|  | 958 | +    e = head->next; | 
|---|
|  | 959 | +    list_del( e ); | 
|---|
|  | 960 | +    return e; | 
|---|
|  | 961 | +} | 
|---|
|  | 962 | + | 
|---|
|  | 963 | +static __inline__ u16 get_reg(u16 index, u16 data, u8 port) | 
|---|
|  | 964 | +{ | 
|---|
|  | 965 | +    u16 reg; | 
|---|
|  | 966 | + | 
|---|
|  | 967 | +    outb(port, index); | 
|---|
|  | 968 | +    reg = inb(data); | 
|---|
|  | 969 | +    outb(port + 1, index); | 
|---|
|  | 970 | +    reg |= inb(data) << 8; | 
|---|
|  | 971 | +    return reg; | 
|---|
|  | 972 | +} | 
|---|
|  | 973 | + | 
|---|
|  | 974 | +/* | 
|---|
|  | 975 | + * | 
|---|
|  | 976 | + * Main ACPI Subsystem Code | 
|---|
|  | 977 | + * | 
|---|
|  | 978 | + */ | 
|---|
|  | 979 | + | 
|---|
|  | 980 | +extern int cobalt_acpi_register_hw_handler( u16 hw_type, | 
|---|
|  | 981 | +                                           cobalt_acpi_hw_handler hw_handler, | 
|---|
|  | 982 | +                                           cobalt_acpi_enable_handler en_handler, | 
|---|
|  | 983 | +                                           void *data ) | 
|---|
|  | 984 | +{ | 
|---|
|  | 985 | +    hw_handler_datum *d; | 
|---|
|  | 986 | +    unsigned long flags; | 
|---|
|  | 987 | + | 
|---|
|  | 988 | +    if( ! (d = (hw_handler_datum *) kmalloc( sizeof( hw_handler_datum ), GFP_ATOMIC )) ) | 
|---|
|  | 989 | +       return -ENOMEM; | 
|---|
|  | 990 | + | 
|---|
|  | 991 | +    d->hw_type = hw_type; | 
|---|
|  | 992 | +    d->hw_handler = hw_handler; | 
|---|
|  | 993 | +    d->en_handler = en_handler; | 
|---|
|  | 994 | +    d->data = data; | 
|---|
|  | 995 | + | 
|---|
|  | 996 | +    spin_lock_irqsave( &hw_handler_list_lock, flags ); | 
|---|
|  | 997 | +    list_add( &(d->link), &hw_handler_list ); | 
|---|
|  | 998 | +    spin_unlock_irqrestore( &hw_handler_list_lock, flags ); | 
|---|
|  | 999 | + | 
|---|
|  | 1000 | +    return 0; | 
|---|
|  | 1001 | +} | 
|---|
|  | 1002 | + | 
|---|
|  | 1003 | +extern int cobalt_acpi_unregister_hw_handler( cobalt_acpi_hw_handler handler ) | 
|---|
|  | 1004 | +{ | 
|---|
|  | 1005 | +    struct list_head *pos; | 
|---|
|  | 1006 | +    unsigned long flags; | 
|---|
|  | 1007 | + | 
|---|
|  | 1008 | +    spin_lock_irqsave( &hw_handler_list_lock, flags ); | 
|---|
|  | 1009 | +    list_for_each( pos, &hw_handler_list ) | 
|---|
|  | 1010 | +       { | 
|---|
|  | 1011 | +           if( list_entry( pos, hw_handler_datum, link )->hw_handler == handler ) | 
|---|
|  | 1012 | +           { | 
|---|
|  | 1013 | +               list_del( pos ); | 
|---|
|  | 1014 | +               spin_unlock_irqrestore( &hw_handler_list_lock, flags ); | 
|---|
|  | 1015 | + | 
|---|
|  | 1016 | +               kfree( list_entry( pos, hw_handler_datum, link ) ); | 
|---|
|  | 1017 | +               return 0; | 
|---|
|  | 1018 | +           } | 
|---|
|  | 1019 | + | 
|---|
|  | 1020 | +       }; | 
|---|
|  | 1021 | + | 
|---|
|  | 1022 | +    spin_unlock_irqrestore( &hw_handler_list_lock, flags ); | 
|---|
|  | 1023 | +    return -1; | 
|---|
|  | 1024 | +} | 
|---|
|  | 1025 | + | 
|---|
|  | 1026 | +extern int cobalt_acpi_register_trans_table( u16 hw_type, u16 table_len, u16 *table ) | 
|---|
|  | 1027 | +{ | 
|---|
|  | 1028 | +    trans_table_datum *d; | 
|---|
|  | 1029 | +    unsigned long flags; | 
|---|
|  | 1030 | + | 
|---|
|  | 1031 | +    if( ! (d = (trans_table_datum *) kmalloc( sizeof( trans_table_datum ), GFP_ATOMIC )) ) | 
|---|
|  | 1032 | +       return -ENOMEM; | 
|---|
|  | 1033 | + | 
|---|
|  | 1034 | +    d->hw_type = hw_type; | 
|---|
|  | 1035 | +    d->table_len = table_len; | 
|---|
|  | 1036 | +    d->table = table; | 
|---|
|  | 1037 | + | 
|---|
|  | 1038 | +    spin_lock_irqsave( &trans_table_list_lock, flags ); | 
|---|
|  | 1039 | +    list_add( &(d->link), &trans_table_list ); | 
|---|
|  | 1040 | +    spin_unlock_irqrestore( &trans_table_list_lock, flags ); | 
|---|
|  | 1041 | + | 
|---|
|  | 1042 | +    return 0; | 
|---|
|  | 1043 | +} | 
|---|
|  | 1044 | + | 
|---|
|  | 1045 | +extern int cobalt_acpi_unregister_trans_table( u16 hw_type ) | 
|---|
|  | 1046 | +{ | 
|---|
|  | 1047 | +    struct list_head *pos; | 
|---|
|  | 1048 | +    unsigned long flags; | 
|---|
|  | 1049 | + | 
|---|
|  | 1050 | +    spin_lock_irqsave( &trans_table_list_lock, flags ); | 
|---|
|  | 1051 | +    list_for_each( pos, &trans_table_list ) | 
|---|
|  | 1052 | +       { | 
|---|
|  | 1053 | +           if( list_entry( pos, trans_table_datum, link )->hw_type == hw_type ) | 
|---|
|  | 1054 | +           { | 
|---|
|  | 1055 | +               list_del( pos ); | 
|---|
|  | 1056 | +               spin_unlock_irqrestore( &trans_table_list_lock, flags ); | 
|---|
|  | 1057 | + | 
|---|
|  | 1058 | +               kfree( list_entry( pos, trans_table_datum, link ) ); | 
|---|
|  | 1059 | +               return 0; | 
|---|
|  | 1060 | +           } | 
|---|
|  | 1061 | + | 
|---|
|  | 1062 | +       }; | 
|---|
|  | 1063 | + | 
|---|
|  | 1064 | +    spin_unlock_irqrestore( &trans_table_list_lock, flags ); | 
|---|
|  | 1065 | +    return -1; | 
|---|
|  | 1066 | +} | 
|---|
|  | 1067 | + | 
|---|
|  | 1068 | +extern int cobalt_acpi_register_evt_handler( cobalt_acpi_evt_handler handler, | 
|---|
|  | 1069 | +                                            u16 ev_type, | 
|---|
|  | 1070 | +                                            void *data ) | 
|---|
|  | 1071 | +{ | 
|---|
|  | 1072 | +    evt_handler_datum *d; | 
|---|
|  | 1073 | +    unsigned long flags; | 
|---|
|  | 1074 | + | 
|---|
|  | 1075 | +    if( ! (d = (evt_handler_datum *) kmalloc( sizeof( evt_handler_datum ), GFP_ATOMIC )) ) | 
|---|
|  | 1076 | +       return -ENOMEM; | 
|---|
|  | 1077 | + | 
|---|
|  | 1078 | +    d->handler = handler; | 
|---|
|  | 1079 | +    d->data = data; | 
|---|
|  | 1080 | +    d->ev_type = ev_type; | 
|---|
|  | 1081 | + | 
|---|
|  | 1082 | +    spin_lock_irqsave( &evt_handler_list_lock, flags ); | 
|---|
|  | 1083 | +    list_add( &(d->link), &evt_handler_list ); | 
|---|
|  | 1084 | +    spin_unlock_irqrestore( &evt_handler_list_lock, flags ); | 
|---|
|  | 1085 | + | 
|---|
|  | 1086 | +    cobalt_acpi_enable_event( ev_type, 1 ); | 
|---|
|  | 1087 | + | 
|---|
|  | 1088 | +    return 0; | 
|---|
|  | 1089 | +} | 
|---|
|  | 1090 | + | 
|---|
|  | 1091 | +extern int cobalt_acpi_unregister_evt_handler( cobalt_acpi_evt_handler handler ) | 
|---|
|  | 1092 | +{ | 
|---|
|  | 1093 | +    struct list_head *pos; | 
|---|
|  | 1094 | +    unsigned long flags; | 
|---|
|  | 1095 | + | 
|---|
|  | 1096 | + | 
|---|
|  | 1097 | +    spin_lock_irqsave( &evt_handler_list_lock, flags ); | 
|---|
|  | 1098 | +    list_for_each( pos, &evt_handler_list ) | 
|---|
|  | 1099 | +       { | 
|---|
|  | 1100 | +           if( list_entry( pos, evt_handler_datum, link )->handler == handler ) | 
|---|
|  | 1101 | +           { | 
|---|
|  | 1102 | +               list_del( pos ); | 
|---|
|  | 1103 | +               spin_unlock_irqrestore( &evt_handler_list_lock, flags ); | 
|---|
|  | 1104 | + | 
|---|
|  | 1105 | +               cobalt_acpi_enable_event( list_entry( pos, | 
|---|
|  | 1106 | +                                                     evt_handler_datum, | 
|---|
|  | 1107 | +                                                     link )->ev_type, 0 ); | 
|---|
|  | 1108 | + | 
|---|
|  | 1109 | +               kfree( list_entry( pos, evt_handler_datum, link ) ); | 
|---|
|  | 1110 | +               return 0; | 
|---|
|  | 1111 | +           } | 
|---|
|  | 1112 | + | 
|---|
|  | 1113 | +       }; | 
|---|
|  | 1114 | + | 
|---|
|  | 1115 | +    spin_unlock_irqrestore( &evt_handler_list_lock, flags ); | 
|---|
|  | 1116 | +    return -EINVAL; | 
|---|
|  | 1117 | +} | 
|---|
|  | 1118 | + | 
|---|
|  | 1119 | +static void cobalt_acpi_enable_event( u16 ev_type, int en ) | 
|---|
|  | 1120 | +{ | 
|---|
|  | 1121 | +    if( ev_type >= 0x8000 ) | 
|---|
|  | 1122 | +    { | 
|---|
|  | 1123 | +       struct list_head *pos; | 
|---|
|  | 1124 | +       trans_table_datum *d; | 
|---|
|  | 1125 | +       int i; | 
|---|
|  | 1126 | +       unsigned long flags; | 
|---|
|  | 1127 | + | 
|---|
|  | 1128 | +       spin_lock_irqsave( &trans_table_list_lock, flags ); | 
|---|
|  | 1129 | +       list_for_each( pos, &trans_table_list ) | 
|---|
|  | 1130 | +           { | 
|---|
|  | 1131 | +               d = list_entry( pos, trans_table_datum, link ); | 
|---|
|  | 1132 | +               for( i=0 ; i<d->table_len ; i++ ) | 
|---|
|  | 1133 | +               { | 
|---|
|  | 1134 | +                   if( d->table[i] == ev_type ) | 
|---|
|  | 1135 | +                   { | 
|---|
|  | 1136 | +                       cobalt_acpi_run_enable_handler( d->hw_type, | 
|---|
|  | 1137 | +                                                       COBALT_ACPI_EVT_GPE, | 
|---|
|  | 1138 | +                                                       i, en ); | 
|---|
|  | 1139 | +                   } | 
|---|
|  | 1140 | +               } | 
|---|
|  | 1141 | +           } | 
|---|
|  | 1142 | +       spin_unlock_irqrestore( &trans_table_list_lock, flags ); | 
|---|
|  | 1143 | +    } | 
|---|
|  | 1144 | +    else | 
|---|
|  | 1145 | +       cobalt_acpi_run_enable_handler( COBALT_ACPI_HW_ANY, ev_type, 0, en); | 
|---|
|  | 1146 | +} | 
|---|
|  | 1147 | + | 
|---|
|  | 1148 | +static void cobalt_acpi_run_enable_handler( u16 hw_type, u16 ev_type, | 
|---|
|  | 1149 | +                                           u16 ev_data, int en) | 
|---|
|  | 1150 | +{ | 
|---|
|  | 1151 | +    struct list_head *pos; | 
|---|
|  | 1152 | +    unsigned long flags; | 
|---|
|  | 1153 | +    hw_handler_datum *d; | 
|---|
|  | 1154 | + | 
|---|
|  | 1155 | +    spin_lock_irqsave(&hw_handler_list_lock, flags); | 
|---|
|  | 1156 | +    list_for_each( pos, &hw_handler_list ) | 
|---|
|  | 1157 | +       { | 
|---|
|  | 1158 | +           d = list_entry( pos, hw_handler_datum, link ); | 
|---|
|  | 1159 | +           if( (!hw_type) || (d->hw_type == hw_type) ) | 
|---|
|  | 1160 | +               d->en_handler( ev_type, ev_data, en, d->data ); | 
|---|
|  | 1161 | +       } | 
|---|
|  | 1162 | +    spin_unlock_irqrestore(&hw_handler_list_lock, flags); | 
|---|
|  | 1163 | + | 
|---|
|  | 1164 | +} | 
|---|
|  | 1165 | + | 
|---|
|  | 1166 | +static int cobalt_acpi_translate_event( cobalt_acpi_evt *evt ) | 
|---|
|  | 1167 | +{ | 
|---|
|  | 1168 | +    struct list_head *pos; | 
|---|
|  | 1169 | +    unsigned long flags; | 
|---|
|  | 1170 | +    trans_table_datum *d; | 
|---|
|  | 1171 | + | 
|---|
|  | 1172 | +    if( evt->ev_type != COBALT_ACPI_EVT_GPE ) | 
|---|
|  | 1173 | +       return 0; | 
|---|
|  | 1174 | + | 
|---|
|  | 1175 | +    spin_lock_irqsave( &trans_table_list_lock, flags ); | 
|---|
|  | 1176 | +    list_for_each( pos, &trans_table_list ) | 
|---|
|  | 1177 | +       { | 
|---|
|  | 1178 | +           d = list_entry( pos, trans_table_datum, link ); | 
|---|
|  | 1179 | +           if( d->hw_type == evt->hw_type ) | 
|---|
|  | 1180 | +           { | 
|---|
|  | 1181 | +               if( evt->ev_data >= d->table_len ) | 
|---|
|  | 1182 | +                   goto err_out; | 
|---|
|  | 1183 | + | 
|---|
|  | 1184 | +               if( d->table[ evt->ev_data ] != COBALT_ACPI_EVT_NONE ) | 
|---|
|  | 1185 | +               { | 
|---|
|  | 1186 | +                   evt->ev_type = d->table[ evt->ev_data ]; | 
|---|
|  | 1187 | +                   evt->ev_data = 0; | 
|---|
|  | 1188 | +               } | 
|---|
|  | 1189 | + | 
|---|
|  | 1190 | +               spin_unlock_irqrestore( &trans_table_list_lock, flags ); | 
|---|
|  | 1191 | +               return 0; | 
|---|
|  | 1192 | +           } | 
|---|
|  | 1193 | +       } | 
|---|
|  | 1194 | + | 
|---|
|  | 1195 | +  err_out: | 
|---|
|  | 1196 | +    spin_unlock_irqrestore( &trans_table_list_lock, flags ); | 
|---|
|  | 1197 | +    return -1; | 
|---|
|  | 1198 | +} | 
|---|
|  | 1199 | + | 
|---|
|  | 1200 | +extern int cobalt_acpi_post_event( cobalt_acpi_evt evt ) | 
|---|
|  | 1201 | +{ | 
|---|
|  | 1202 | +    evt_list_datum *d; | 
|---|
|  | 1203 | +    unsigned long flags; | 
|---|
|  | 1204 | + | 
|---|
|  | 1205 | +    if( ! (d = (evt_list_datum *) kmalloc( sizeof( evt_handler_datum ), GFP_ATOMIC )) ) | 
|---|
|  | 1206 | +       return -ENOMEM; | 
|---|
|  | 1207 | + | 
|---|
|  | 1208 | + | 
|---|
|  | 1209 | +    cobalt_acpi_translate_event( &evt ); | 
|---|
|  | 1210 | + | 
|---|
|  | 1211 | +    memcpy( &(d->evt), &evt, sizeof(evt) ); | 
|---|
|  | 1212 | + | 
|---|
|  | 1213 | +    spin_lock_irqsave( &dispatch_queue_lock, flags ); | 
|---|
|  | 1214 | +    list_add_tail( &(d->link), &dispatch_queue ); | 
|---|
|  | 1215 | +    spin_unlock_irqrestore( &dispatch_queue_lock, flags ); | 
|---|
|  | 1216 | + | 
|---|
|  | 1217 | +    return 0; | 
|---|
|  | 1218 | +} | 
|---|
|  | 1219 | + | 
|---|
|  | 1220 | +static int cobalt_acpi_apply_evt_handlers( evt_list_datum *d ) | 
|---|
|  | 1221 | +{ | 
|---|
|  | 1222 | +    struct list_head *pos; | 
|---|
|  | 1223 | +    evt_handler_datum *evt_h; | 
|---|
|  | 1224 | +    int ret,err = 0; | 
|---|
|  | 1225 | +    unsigned long flags; | 
|---|
|  | 1226 | + | 
|---|
|  | 1227 | +    spin_lock_irqsave( &evt_handler_list_lock, flags ); | 
|---|
|  | 1228 | +    list_for_each( pos, &evt_handler_list ) | 
|---|
|  | 1229 | +       { | 
|---|
|  | 1230 | +           evt_h = list_entry( pos, evt_handler_datum, link ); | 
|---|
|  | 1231 | +           if( (! evt_h->ev_type) || (evt_h->ev_type == d->evt.ev_type) ) | 
|---|
|  | 1232 | +           { | 
|---|
|  | 1233 | +               if( (ret = evt_h->handler( &d->evt, evt_h->data )) < 0 ) | 
|---|
|  | 1234 | +                   err = ret; | 
|---|
|  | 1235 | +           } | 
|---|
|  | 1236 | +       } | 
|---|
|  | 1237 | +    spin_unlock_irqrestore( &evt_handler_list_lock, flags ); | 
|---|
|  | 1238 | + | 
|---|
|  | 1239 | +    return err; | 
|---|
|  | 1240 | +} | 
|---|
|  | 1241 | + | 
|---|
|  | 1242 | +static int cobalt_acpi_run_dispatch_queue( void ) | 
|---|
|  | 1243 | +{ | 
|---|
|  | 1244 | +    struct list_head *pos; | 
|---|
|  | 1245 | +    int ret; | 
|---|
|  | 1246 | +    int err=0; | 
|---|
|  | 1247 | +    evt_list_datum *d; | 
|---|
|  | 1248 | +    unsigned long flags; | 
|---|
|  | 1249 | + | 
|---|
|  | 1250 | +    spin_lock_irqsave( &dispatch_queue_lock, flags ); | 
|---|
|  | 1251 | +    while( (pos = list_pop( &dispatch_queue )) ) | 
|---|
|  | 1252 | +    { | 
|---|
|  | 1253 | +       d = list_entry( pos, evt_list_datum, link ); | 
|---|
|  | 1254 | +       if( (ret = cobalt_acpi_apply_evt_handlers( d )) < 0 ) | 
|---|
|  | 1255 | +           err = ret; | 
|---|
|  | 1256 | +#ifdef CONFIG_COBALT_EMU_ACPI | 
|---|
|  | 1257 | +       cobalt_acpi_generate_proc_evt( &d->evt ); | 
|---|
|  | 1258 | +#endif | 
|---|
|  | 1259 | +       kfree( d ); | 
|---|
|  | 1260 | +    } | 
|---|
|  | 1261 | +    spin_unlock_irqrestore( &dispatch_queue_lock, flags ); | 
|---|
|  | 1262 | + | 
|---|
|  | 1263 | +    return err; | 
|---|
|  | 1264 | +} | 
|---|
|  | 1265 | + | 
|---|
|  | 1266 | +static irqreturn_t acpi_interrupt(int irq, void *dev_id, struct pt_regs *regs) | 
|---|
|  | 1267 | +{ | 
|---|
|  | 1268 | +    struct list_head *pos; | 
|---|
|  | 1269 | +    hw_handler_datum *d; | 
|---|
|  | 1270 | +    int ret=0, err=0; | 
|---|
|  | 1271 | +    unsigned long flags; | 
|---|
|  | 1272 | + | 
|---|
|  | 1273 | +    spin_lock_irqsave(&hw_handler_list_lock, flags); | 
|---|
|  | 1274 | +    list_for_each( pos, &hw_handler_list ) | 
|---|
|  | 1275 | +       { | 
|---|
|  | 1276 | +           d = list_entry( pos, hw_handler_datum, link ); | 
|---|
|  | 1277 | +           if( (ret = d->hw_handler( irq, dev_id, regs, d->data )) < 0 ) | 
|---|
|  | 1278 | +               err = ret; | 
|---|
|  | 1279 | + | 
|---|
|  | 1280 | +       } | 
|---|
|  | 1281 | +    spin_unlock_irqrestore(&hw_handler_list_lock, flags); | 
|---|
|  | 1282 | + | 
|---|
|  | 1283 | +    if( (err = cobalt_acpi_run_dispatch_queue()) < 0 ) | 
|---|
|  | 1284 | +       err = ret; | 
|---|
|  | 1285 | + | 
|---|
|  | 1286 | +    if( err ) | 
|---|
|  | 1287 | +       EPRINTK( "error at interrupt time of type %d.\n", err ); | 
|---|
|  | 1288 | + | 
|---|
|  | 1289 | +    return IRQ_HANDLED; | 
|---|
|  | 1290 | +} | 
|---|
|  | 1291 | + | 
|---|
|  | 1292 | + | 
|---|
|  | 1293 | + | 
|---|
|  | 1294 | + | 
|---|
|  | 1295 | +int __init cobalt_acpi_init(void) | 
|---|
|  | 1296 | +{ | 
|---|
|  | 1297 | +    int err; | 
|---|
|  | 1298 | + | 
|---|
|  | 1299 | +    printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", ACPI_DRIVER,ACPI_DRIVER_VMAJ,ACPI_DRIVER_VMIN); | 
|---|
|  | 1300 | + | 
|---|
|  | 1301 | +    if( cobt_is_monterey() ) | 
|---|
|  | 1302 | +       cobalt_acpi_monterey_init(); | 
|---|
|  | 1303 | +    else if( cobt_is_alpine() ) | 
|---|
|  | 1304 | +       cobalt_acpi_alpine_init(); | 
|---|
|  | 1305 | + | 
|---|
|  | 1306 | +    if( cobt_is_5k() ) | 
|---|
|  | 1307 | +    { | 
|---|
|  | 1308 | +       if( pci_find_device(PCI_VENDOR_ID_SERVERWORKS, | 
|---|
|  | 1309 | +                           PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL ) ) | 
|---|
|  | 1310 | +       { | 
|---|
|  | 1311 | +           if( (err = cobalt_acpi_osb4_init()) < 0 ) | 
|---|
|  | 1312 | +           { | 
|---|
|  | 1313 | +               goto cleanup; | 
|---|
|  | 1314 | +           } | 
|---|
|  | 1315 | +       } | 
|---|
|  | 1316 | + | 
|---|
|  | 1317 | +       if( pci_find_device(PCI_VENDOR_ID_SERVERWORKS, | 
|---|
|  | 1318 | +                           PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL ) ) | 
|---|
|  | 1319 | +       { | 
|---|
|  | 1320 | +           if( (err = cobalt_acpi_csb5_init()) < 0 ) | 
|---|
|  | 1321 | +           { | 
|---|
|  | 1322 | +               goto cleanup; | 
|---|
|  | 1323 | +           } | 
|---|
|  | 1324 | +       } | 
|---|
|  | 1325 | + | 
|---|
|  | 1326 | +       switch( superio_type() ) | 
|---|
|  | 1327 | +       { | 
|---|
|  | 1328 | +           case SIO_TYPE_PC8731X: | 
|---|
|  | 1329 | +               if( (err = cobalt_acpi_pc8731x_init()) ) | 
|---|
|  | 1330 | +               { | 
|---|
|  | 1331 | +                   goto cleanup; | 
|---|
|  | 1332 | +               } | 
|---|
|  | 1333 | +               break; | 
|---|
|  | 1334 | + | 
|---|
|  | 1335 | +           case SIO_TYPE_PC8741X: | 
|---|
|  | 1336 | +               if( (err = cobalt_acpi_pc8741x_init()) ) | 
|---|
|  | 1337 | +               { | 
|---|
|  | 1338 | +                   goto cleanup; | 
|---|
|  | 1339 | +               } | 
|---|
|  | 1340 | +               break; | 
|---|
|  | 1341 | + | 
|---|
|  | 1342 | +           case SIO_TYPE_UNKNOWN: | 
|---|
|  | 1343 | +               EPRINTK("unknown superio type\n"); | 
|---|
|  | 1344 | +               break; | 
|---|
|  | 1345 | +       } | 
|---|
|  | 1346 | + | 
|---|
|  | 1347 | +           /* setup an interrupt handler for an ACPI SCI */ | 
|---|
|  | 1348 | +       err = request_irq(ACPI_IRQ, acpi_interrupt, | 
|---|
|  | 1349 | +                         SA_SHIRQ, ACPI_NAME, (void *)ACPI_MAGIC); | 
|---|
|  | 1350 | +       if (err) { | 
|---|
|  | 1351 | +           EPRINTK("can't assign ACPI IRQ (%d)\n", ACPI_IRQ); | 
|---|
|  | 1352 | +           return err; | 
|---|
|  | 1353 | +       } | 
|---|
|  | 1354 | + | 
|---|
|  | 1355 | +#ifdef CONFIG_COBALT_EMU_ACPI | 
|---|
|  | 1356 | +       cobalt_acpi_setup_proc(); | 
|---|
|  | 1357 | +#endif | 
|---|
|  | 1358 | +    } | 
|---|
|  | 1359 | + | 
|---|
|  | 1360 | +       /* enable some events we may want */ | 
|---|
|  | 1361 | +    cobalt_acpi_enable_event( COBALT_ACPI_EVT_PWRBTN, 1 ); | 
|---|
|  | 1362 | + | 
|---|
|  | 1363 | +    return 0; | 
|---|
|  | 1364 | + | 
|---|
|  | 1365 | +  cleanup: | 
|---|
|  | 1366 | +    cobalt_acpi_cleanup(); | 
|---|
|  | 1367 | +    return err; | 
|---|
|  | 1368 | +} | 
|---|
|  | 1369 | + | 
|---|
|  | 1370 | +static void cobalt_acpi_cleanup( void ) | 
|---|
|  | 1371 | +{ | 
|---|
|  | 1372 | +    cobalt_acpi_osb4_cleanup(); | 
|---|
|  | 1373 | +    cobalt_acpi_csb5_cleanup(); | 
|---|
|  | 1374 | +    cobalt_acpi_pc8731x_cleanup(); | 
|---|
|  | 1375 | +    cobalt_acpi_pc8741x_cleanup(); | 
|---|
|  | 1376 | + | 
|---|
|  | 1377 | +    if( cobt_is_monterey() ) | 
|---|
|  | 1378 | +       cobalt_acpi_monterey_cleanup(); | 
|---|
|  | 1379 | +    if( cobt_is_alpine() ) | 
|---|
|  | 1380 | +       cobalt_acpi_alpine_cleanup(); | 
|---|
|  | 1381 | +} | 
|---|
|  | 1382 | + | 
|---|
|  | 1383 | +/* | 
|---|
|  | 1384 | + * | 
|---|
|  | 1385 | + * Generic ACPI HW Support | 
|---|
|  | 1386 | + * | 
|---|
|  | 1387 | + */ | 
|---|
|  | 1388 | + | 
|---|
|  | 1389 | +static __inline__ char *region_name( char * subsys_name, char * blk_name ) | 
|---|
|  | 1390 | +{ | 
|---|
|  | 1391 | +    char * new_name; | 
|---|
|  | 1392 | + | 
|---|
|  | 1393 | +    if( !( new_name = (char *) kmalloc( strlen(subsys_name) + strlen(blk_name) + 14, | 
|---|
|  | 1394 | +                                       GFP_ATOMIC)) ) | 
|---|
|  | 1395 | +       return NULL; | 
|---|
|  | 1396 | + | 
|---|
|  | 1397 | +    sprintf( new_name, "%s (%s)", subsys_name, blk_name ); | 
|---|
|  | 1398 | +    return new_name; | 
|---|
|  | 1399 | +} | 
|---|
|  | 1400 | + | 
|---|
|  | 1401 | +static void free_region_names( generic_acpi_regions *regions ) | 
|---|
|  | 1402 | +{ | 
|---|
|  | 1403 | +    if( regions->pm1a_evt_nam ) | 
|---|
|  | 1404 | +       kfree( regions->pm1a_evt_nam ); | 
|---|
|  | 1405 | + | 
|---|
|  | 1406 | +    if( regions->pm1b_evt_nam ) | 
|---|
|  | 1407 | +       kfree( regions->pm1b_evt_nam ); | 
|---|
|  | 1408 | + | 
|---|
|  | 1409 | +    if( regions->pm1a_cnt_nam ) | 
|---|
|  | 1410 | +       kfree( regions->pm1a_cnt_nam ); | 
|---|
|  | 1411 | + | 
|---|
|  | 1412 | +    if( regions->pm1b_cnt_nam ) | 
|---|
|  | 1413 | +       kfree( regions->pm1b_cnt_nam ); | 
|---|
|  | 1414 | + | 
|---|
|  | 1415 | +    if( regions->pm2_cnt_nam ) | 
|---|
|  | 1416 | +       kfree( regions->pm2_cnt_nam ); | 
|---|
|  | 1417 | + | 
|---|
|  | 1418 | +    if( regions->pm_tmr_nam ) | 
|---|
|  | 1419 | +       kfree( regions->pm_tmr_nam ); | 
|---|
|  | 1420 | + | 
|---|
|  | 1421 | +    if( regions->p_nam ) | 
|---|
|  | 1422 | +       kfree( regions->p_nam ); | 
|---|
|  | 1423 | + | 
|---|
|  | 1424 | +    if( regions->gpe0_nam ) | 
|---|
|  | 1425 | +       kfree( regions->gpe0_nam ); | 
|---|
|  | 1426 | + | 
|---|
|  | 1427 | +    if( regions->gpe1_nam ) | 
|---|
|  | 1428 | +       kfree( regions->gpe1_nam ); | 
|---|
|  | 1429 | +} | 
|---|
|  | 1430 | + | 
|---|
|  | 1431 | +static int register_acpi_regions( generic_acpi_regions *regions,  char * subsys_name ) | 
|---|
|  | 1432 | +{ | 
|---|
|  | 1433 | +    int i; | 
|---|
|  | 1434 | + | 
|---|
|  | 1435 | +    if( regions->pm1a_evt_blk && regions->pm1_evt_len ) | 
|---|
|  | 1436 | +    { | 
|---|
|  | 1437 | +       if( !(regions->pm1a_evt_nam = region_name( subsys_name, "pm1a_evt_blk" )) ) | 
|---|
|  | 1438 | +           goto cleanup0; | 
|---|
|  | 1439 | + | 
|---|
|  | 1440 | +       if( !request_region( regions->pm1a_evt_blk, regions->pm1_evt_len, | 
|---|
|  | 1441 | +                            regions->pm1a_evt_nam ) ) | 
|---|
|  | 1442 | +           goto cleanup0; | 
|---|
|  | 1443 | +    } | 
|---|
|  | 1444 | + | 
|---|
|  | 1445 | +    if( regions->pm1b_evt_blk && regions->pm1_evt_len ) | 
|---|
|  | 1446 | +    { | 
|---|
|  | 1447 | +       if( !(regions->pm1b_evt_nam = region_name( subsys_name, "pm1b_evt_blk" )) ) | 
|---|
|  | 1448 | +           goto cleanup0; | 
|---|
|  | 1449 | + | 
|---|
|  | 1450 | +       if( !request_region( regions->pm1b_evt_blk, regions->pm1_evt_len, | 
|---|
|  | 1451 | +                            regions->pm1b_evt_nam) ) | 
|---|
|  | 1452 | +           goto cleanup1; | 
|---|
|  | 1453 | +    } | 
|---|
|  | 1454 | + | 
|---|
|  | 1455 | +    if( regions->pm1a_cnt_blk && regions->pm1_cnt_len ) | 
|---|
|  | 1456 | +    { | 
|---|
|  | 1457 | +       if( !(regions->pm1a_cnt_nam = region_name( subsys_name, "pm1a_cnt_blk" )) ) | 
|---|
|  | 1458 | +           goto cleanup1; | 
|---|
|  | 1459 | + | 
|---|
|  | 1460 | +       if( !request_region( regions->pm1a_cnt_blk, regions->pm1_cnt_len, | 
|---|
|  | 1461 | +                            regions->pm1a_cnt_nam ) ) | 
|---|
|  | 1462 | +           goto cleanup2; | 
|---|
|  | 1463 | +    } | 
|---|
|  | 1464 | + | 
|---|
|  | 1465 | +    if( regions->pm1b_cnt_blk && regions->pm1_cnt_len ) | 
|---|
|  | 1466 | +    { | 
|---|
|  | 1467 | +       if( !(regions->pm1b_cnt_nam = region_name( subsys_name, "pm1b_cnt_blk" )) ) | 
|---|
|  | 1468 | +           goto cleanup2; | 
|---|
|  | 1469 | + | 
|---|
|  | 1470 | +       if( !request_region( regions->pm1b_cnt_blk, regions->pm1_cnt_len, | 
|---|
|  | 1471 | +                            regions->pm1b_cnt_nam ) ) | 
|---|
|  | 1472 | +           goto cleanup3; | 
|---|
|  | 1473 | +    } | 
|---|
|  | 1474 | + | 
|---|
|  | 1475 | +    if( regions->pm2_cnt_blk && regions->pm2_cnt_len ) | 
|---|
|  | 1476 | +    { | 
|---|
|  | 1477 | +       if( !(regions->pm2_cnt_nam = region_name( subsys_name, "pm2_cnt_blk" )) ) | 
|---|
|  | 1478 | +           goto cleanup3; | 
|---|
|  | 1479 | + | 
|---|
|  | 1480 | +       if( !request_region( regions->pm2_cnt_blk, regions->pm2_cnt_len, | 
|---|
|  | 1481 | +                            regions->pm2_cnt_nam ) ) | 
|---|
|  | 1482 | +           goto cleanup4; | 
|---|
|  | 1483 | +    } | 
|---|
|  | 1484 | + | 
|---|
|  | 1485 | +    if( regions->pm_tmr_blk && regions->pm_tmr_len ) | 
|---|
|  | 1486 | +    { | 
|---|
|  | 1487 | +       if( !(regions->pm_tmr_nam = region_name( subsys_name, "pm_tmp_blk" )) ) | 
|---|
|  | 1488 | +           goto cleanup4; | 
|---|
|  | 1489 | + | 
|---|
|  | 1490 | +       if( !request_region( regions->pm_tmr_blk, regions->pm_tmr_len, | 
|---|
|  | 1491 | +                            regions->pm_tmr_nam ) ) | 
|---|
|  | 1492 | +           goto cleanup5; | 
|---|
|  | 1493 | +    } | 
|---|
|  | 1494 | + | 
|---|
|  | 1495 | +    if( regions->p_blk ) | 
|---|
|  | 1496 | +    { | 
|---|
|  | 1497 | +       if( !(regions->p_nam = region_name( subsys_name, "p_blk" )) ) | 
|---|
|  | 1498 | +           goto cleanup5; | 
|---|
|  | 1499 | + | 
|---|
|  | 1500 | +       if( !request_region( regions->p_blk, 6, regions->p_nam ) ) | 
|---|
|  | 1501 | +           goto cleanup6; | 
|---|
|  | 1502 | +    } | 
|---|
|  | 1503 | + | 
|---|
|  | 1504 | +    if( regions->gpe0_blk && regions->gpe0_len ) | 
|---|
|  | 1505 | +    { | 
|---|
|  | 1506 | +       if( !(regions->gpe0_nam = region_name( subsys_name, "gpe0_blk" )) ) | 
|---|
|  | 1507 | +           goto cleanup6; | 
|---|
|  | 1508 | + | 
|---|
|  | 1509 | +       if( !request_region( regions->gpe0_blk, regions->gpe0_len, | 
|---|
|  | 1510 | +                            regions->gpe0_nam ) ) | 
|---|
|  | 1511 | +           goto cleanup7; | 
|---|
|  | 1512 | +    } | 
|---|
|  | 1513 | + | 
|---|
|  | 1514 | +    if( regions->gpe1_blk && regions->gpe1_len ) | 
|---|
|  | 1515 | +    { | 
|---|
|  | 1516 | +       if( !(regions->gpe1_nam = region_name( subsys_name, "gpe1_blk" )) ) | 
|---|
|  | 1517 | +           goto cleanup7; | 
|---|
|  | 1518 | + | 
|---|
|  | 1519 | +       if( !request_region( regions->gpe1_blk, regions->gpe1_len, | 
|---|
|  | 1520 | +                            regions->gpe1_nam ) ) | 
|---|
|  | 1521 | +           goto cleanup8; | 
|---|
|  | 1522 | +    } | 
|---|
|  | 1523 | + | 
|---|
|  | 1524 | +    if( (regions->gpe_ref_cnt = (atomic_t *) kmalloc( sizeof( atomic_t ) * | 
|---|
|  | 1525 | +                                                     regions->gpe0_len * 8, | 
|---|
|  | 1526 | +                                                     GFP_ATOMIC)) == NULL ) | 
|---|
|  | 1527 | +       goto cleanup9; | 
|---|
|  | 1528 | + | 
|---|
|  | 1529 | +    memset( regions->gpe_ref_cnt, 0x0, sizeof( atomic_t ) * regions->gpe0_len * 8 ); | 
|---|
|  | 1530 | + | 
|---|
|  | 1531 | +       /* disable all events and ack them */ | 
|---|
|  | 1532 | +    if( regions->pm1a_evt_blk ) | 
|---|
|  | 1533 | +    { | 
|---|
|  | 1534 | +       outw( 0x0000, regions->pm1a_evt_blk + regions->pm1_evt_len/2 ); | 
|---|
|  | 1535 | +       outw( 0xffff, regions->pm1a_evt_blk ); | 
|---|
|  | 1536 | +    } | 
|---|
|  | 1537 | + | 
|---|
|  | 1538 | +    if( regions->pm1b_evt_blk ) | 
|---|
|  | 1539 | +    { | 
|---|
|  | 1540 | +       outw( 0x0000, regions->pm1b_evt_blk + regions->pm1_evt_len/2 ); | 
|---|
|  | 1541 | +       outw( 0xffff, regions->pm1b_evt_blk ); | 
|---|
|  | 1542 | +    } | 
|---|
|  | 1543 | + | 
|---|
|  | 1544 | +    if( regions->gpe0_blk ) | 
|---|
|  | 1545 | +    { | 
|---|
|  | 1546 | +       for( i=0 ; i<(regions->gpe0_len/2) ; i++ ) | 
|---|
|  | 1547 | +       { | 
|---|
|  | 1548 | +           outb( 0x00, regions->gpe0_blk + regions->gpe0_len/2 + i ); | 
|---|
|  | 1549 | +           outb( 0xff, regions->gpe0_blk + i ); | 
|---|
|  | 1550 | +       } | 
|---|
|  | 1551 | +    } | 
|---|
|  | 1552 | + | 
|---|
|  | 1553 | +    if( regions->gpe1_blk ) | 
|---|
|  | 1554 | +    { | 
|---|
|  | 1555 | +       for( i=0 ; i<(regions->gpe1_len/2) ; i++ ) | 
|---|
|  | 1556 | +       { | 
|---|
|  | 1557 | +           outb( 0x00, regions->gpe1_blk + regions->gpe1_len/2 + i ); | 
|---|
|  | 1558 | +           outb( 0xff, regions->gpe1_blk + i ); | 
|---|
|  | 1559 | +       } | 
|---|
|  | 1560 | +    } | 
|---|
|  | 1561 | + | 
|---|
|  | 1562 | +    return 0; | 
|---|
|  | 1563 | + | 
|---|
|  | 1564 | +  cleanup9: | 
|---|
|  | 1565 | +    if( regions->gpe1_blk ) | 
|---|
|  | 1566 | +    { | 
|---|
|  | 1567 | +       release_region( regions->gpe1_blk, regions->gpe1_len ); | 
|---|
|  | 1568 | +       regions->gpe1_blk = 0; | 
|---|
|  | 1569 | +    } | 
|---|
|  | 1570 | + | 
|---|
|  | 1571 | +  cleanup8: | 
|---|
|  | 1572 | +    if( regions->gpe0_blk ) | 
|---|
|  | 1573 | +    { | 
|---|
|  | 1574 | +       release_region( regions->gpe0_blk, regions->gpe0_len ); | 
|---|
|  | 1575 | +       regions->gpe0_blk = 0; | 
|---|
|  | 1576 | +    } | 
|---|
|  | 1577 | + | 
|---|
|  | 1578 | +  cleanup7: | 
|---|
|  | 1579 | +    if( regions->p_blk ) | 
|---|
|  | 1580 | +    { | 
|---|
|  | 1581 | +       release_region( regions->p_blk, 6 ); | 
|---|
|  | 1582 | +       regions->p_blk = 0; | 
|---|
|  | 1583 | +    } | 
|---|
|  | 1584 | + | 
|---|
|  | 1585 | +  cleanup6: | 
|---|
|  | 1586 | +    if( regions->pm_tmr_blk ) | 
|---|
|  | 1587 | +    { | 
|---|
|  | 1588 | +       release_region( regions->pm_tmr_blk, regions->pm_tmr_len ); | 
|---|
|  | 1589 | +       regions->pm_tmr_blk = 0; | 
|---|
|  | 1590 | +    } | 
|---|
|  | 1591 | + | 
|---|
|  | 1592 | +  cleanup5: | 
|---|
|  | 1593 | +    if( regions->pm2_cnt_blk ) | 
|---|
|  | 1594 | +    { | 
|---|
|  | 1595 | +       release_region( regions->pm2_cnt_blk, regions->pm2_cnt_len ); | 
|---|
|  | 1596 | +       regions->pm2_cnt_blk = 0; | 
|---|
|  | 1597 | +    } | 
|---|
|  | 1598 | + | 
|---|
|  | 1599 | +  cleanup4: | 
|---|
|  | 1600 | +    if( regions->pm1b_cnt_blk ) | 
|---|
|  | 1601 | +    { | 
|---|
|  | 1602 | +       release_region( regions->pm1b_cnt_blk, regions->pm1_cnt_len ); | 
|---|
|  | 1603 | +       regions->pm1b_cnt_blk = 0; | 
|---|
|  | 1604 | +    } | 
|---|
|  | 1605 | + | 
|---|
|  | 1606 | +  cleanup3: | 
|---|
|  | 1607 | +    if( regions->pm1a_cnt_blk ) | 
|---|
|  | 1608 | +    { | 
|---|
|  | 1609 | +       release_region( regions->pm1a_cnt_blk, regions->pm1_cnt_len ); | 
|---|
|  | 1610 | +       regions->pm1a_cnt_blk = 0; | 
|---|
|  | 1611 | +    } | 
|---|
|  | 1612 | + | 
|---|
|  | 1613 | +  cleanup2: | 
|---|
|  | 1614 | +    if( regions->pm1b_evt_blk ) | 
|---|
|  | 1615 | +    { | 
|---|
|  | 1616 | +       release_region( regions->pm1b_evt_blk, regions->pm1_evt_len ); | 
|---|
|  | 1617 | +       regions->pm1b_evt_blk = 0; | 
|---|
|  | 1618 | +    } | 
|---|
|  | 1619 | + | 
|---|
|  | 1620 | +  cleanup1: | 
|---|
|  | 1621 | +    if( regions->pm1a_evt_blk ) | 
|---|
|  | 1622 | +    { | 
|---|
|  | 1623 | +       release_region( regions->pm1a_evt_blk, regions->pm1_evt_len ); | 
|---|
|  | 1624 | +       regions->pm1a_evt_blk = 0; | 
|---|
|  | 1625 | +    } | 
|---|
|  | 1626 | + | 
|---|
|  | 1627 | +  cleanup0: | 
|---|
|  | 1628 | +    free_region_names( regions ); | 
|---|
|  | 1629 | + | 
|---|
|  | 1630 | +    return -EBUSY; | 
|---|
|  | 1631 | +} | 
|---|
|  | 1632 | + | 
|---|
|  | 1633 | +static int unregister_acpi_regions( generic_acpi_regions *regions ) | 
|---|
|  | 1634 | +{ | 
|---|
|  | 1635 | +    if( regions->pm1a_evt_blk && regions->pm1_evt_len ) | 
|---|
|  | 1636 | +    { | 
|---|
|  | 1637 | +       release_region( regions->pm1a_evt_blk, regions->pm1_evt_len ); | 
|---|
|  | 1638 | +       regions->pm1a_evt_blk = 0; | 
|---|
|  | 1639 | +    } | 
|---|
|  | 1640 | + | 
|---|
|  | 1641 | +    if( regions->pm1b_evt_blk && regions->pm1_evt_len ) | 
|---|
|  | 1642 | +    { | 
|---|
|  | 1643 | +       release_region( regions->pm1b_evt_blk, regions->pm1_evt_len ); | 
|---|
|  | 1644 | +       regions->pm1b_evt_blk = 0; | 
|---|
|  | 1645 | +    } | 
|---|
|  | 1646 | + | 
|---|
|  | 1647 | +    if( regions->pm1a_cnt_blk && regions->pm1_cnt_len ) | 
|---|
|  | 1648 | +    { | 
|---|
|  | 1649 | +       release_region( regions->pm1a_cnt_blk, regions->pm1_cnt_len ); | 
|---|
|  | 1650 | +       regions->pm1a_cnt_blk = 0; | 
|---|
|  | 1651 | +    } | 
|---|
|  | 1652 | + | 
|---|
|  | 1653 | +    if( regions->pm1b_cnt_blk && regions->pm1_cnt_len ) | 
|---|
|  | 1654 | +    { | 
|---|
|  | 1655 | +       release_region( regions->pm1b_cnt_blk, regions->pm1_cnt_len ); | 
|---|
|  | 1656 | +       regions->pm1b_cnt_blk = 0; | 
|---|
|  | 1657 | +    } | 
|---|
|  | 1658 | + | 
|---|
|  | 1659 | +    if( regions->pm2_cnt_blk && regions->pm2_cnt_len ) | 
|---|
|  | 1660 | +    { | 
|---|
|  | 1661 | +       release_region( regions->pm2_cnt_blk, regions->pm2_cnt_len ); | 
|---|
|  | 1662 | +       regions->pm2_cnt_blk = 0; | 
|---|
|  | 1663 | +    } | 
|---|
|  | 1664 | + | 
|---|
|  | 1665 | +    if( regions->pm_tmr_blk && regions->pm_tmr_len ) | 
|---|
|  | 1666 | +    { | 
|---|
|  | 1667 | +       release_region( regions->pm_tmr_blk, regions->pm_tmr_len ); | 
|---|
|  | 1668 | +       regions->pm_tmr_blk = 0; | 
|---|
|  | 1669 | +    } | 
|---|
|  | 1670 | + | 
|---|
|  | 1671 | +    if( regions->p_blk ) | 
|---|
|  | 1672 | +    { | 
|---|
|  | 1673 | +       release_region( regions->p_blk, 6 ); | 
|---|
|  | 1674 | +       regions->p_blk = 0; | 
|---|
|  | 1675 | +    } | 
|---|
|  | 1676 | + | 
|---|
|  | 1677 | +    if( regions->gpe0_blk && regions->gpe0_len ) | 
|---|
|  | 1678 | +    { | 
|---|
|  | 1679 | +       release_region( regions->gpe0_blk, regions->gpe0_len ); | 
|---|
|  | 1680 | +       regions->gpe0_blk = 0; | 
|---|
|  | 1681 | +    } | 
|---|
|  | 1682 | + | 
|---|
|  | 1683 | +    if( regions->gpe1_blk && regions->gpe1_len ) | 
|---|
|  | 1684 | +    { | 
|---|
|  | 1685 | +       release_region( regions->gpe1_blk, regions->gpe1_len ); | 
|---|
|  | 1686 | +       regions->gpe1_blk = 0; | 
|---|
|  | 1687 | +    } | 
|---|
|  | 1688 | + | 
|---|
|  | 1689 | +    if( regions->gpe_ref_cnt ) | 
|---|
|  | 1690 | +       kfree( regions->gpe_ref_cnt ); | 
|---|
|  | 1691 | + | 
|---|
|  | 1692 | +    free_region_names( regions ); | 
|---|
|  | 1693 | + | 
|---|
|  | 1694 | +    return 0; | 
|---|
|  | 1695 | +} | 
|---|
|  | 1696 | + | 
|---|
|  | 1697 | +static void cobalt_acpi_handle_pm1_blk( u16 io_addr, u16 len, | 
|---|
|  | 1698 | +                                      generic_acpi_regions * regions ) | 
|---|
|  | 1699 | +{ | 
|---|
|  | 1700 | +    cobalt_acpi_evt evt; | 
|---|
|  | 1701 | +    u16 sts, en; | 
|---|
|  | 1702 | + | 
|---|
|  | 1703 | +    evt.hw_type = regions->hw_type; | 
|---|
|  | 1704 | + | 
|---|
|  | 1705 | +    if( (sts = inw( io_addr )) && | 
|---|
|  | 1706 | +       (en  = inw( io_addr + len/2 )) ) | 
|---|
|  | 1707 | +    { | 
|---|
|  | 1708 | + | 
|---|
|  | 1709 | + | 
|---|
|  | 1710 | +           /* clear status bits */ | 
|---|
|  | 1711 | +       outw( sts, io_addr); | 
|---|
|  | 1712 | + | 
|---|
|  | 1713 | +       if( (en  & GEN_ACPI_TMR_STS) && | 
|---|
|  | 1714 | +           (sts & GEN_ACPI_TMR_STS) ) | 
|---|
|  | 1715 | +       { | 
|---|
|  | 1716 | +           evt.ev_type = COBALT_ACPI_EVT_TMR; | 
|---|
|  | 1717 | +           evt.ev_data = 0x0; | 
|---|
|  | 1718 | +           cobalt_acpi_post_event( evt ); | 
|---|
|  | 1719 | +       } | 
|---|
|  | 1720 | +       if( (en & GEN_ACPI_BM_STS) && | 
|---|
|  | 1721 | +           (sts & GEN_ACPI_BM_STS) ) | 
|---|
|  | 1722 | +       { | 
|---|
|  | 1723 | +           evt.ev_type = COBALT_ACPI_EVT_BM; | 
|---|
|  | 1724 | +           evt.ev_data = 0x0; | 
|---|
|  | 1725 | +           cobalt_acpi_post_event( evt ); | 
|---|
|  | 1726 | +       } | 
|---|
|  | 1727 | +       if( (en  & GEN_ACPI_GBL_STS) && | 
|---|
|  | 1728 | +           (sts & GEN_ACPI_GBL_STS) ) | 
|---|
|  | 1729 | +       { | 
|---|
|  | 1730 | +           evt.ev_type = COBALT_ACPI_EVT_GBL; | 
|---|
|  | 1731 | +           evt.ev_data = 0x0; | 
|---|
|  | 1732 | +           cobalt_acpi_post_event( evt ); | 
|---|
|  | 1733 | +       } | 
|---|
|  | 1734 | +       if( (en  & GEN_ACPI_PWRBTN_STS) && | 
|---|
|  | 1735 | +           (sts & GEN_ACPI_PWRBTN_STS) ) | 
|---|
|  | 1736 | +       { | 
|---|
|  | 1737 | +           evt.ev_type = COBALT_ACPI_EVT_PWRBTN; | 
|---|
|  | 1738 | +           evt.ev_data = 0x0; | 
|---|
|  | 1739 | +           cobalt_acpi_post_event( evt ); | 
|---|
|  | 1740 | +       } | 
|---|
|  | 1741 | +       if( (en  & GEN_ACPI_SLPBTN_STS) && | 
|---|
|  | 1742 | +           (sts & GEN_ACPI_SLPBTN_STS) ) | 
|---|
|  | 1743 | +       { | 
|---|
|  | 1744 | +           evt.ev_type = COBALT_ACPI_EVT_SLPBTN; | 
|---|
|  | 1745 | +           evt.ev_data = 0x0; | 
|---|
|  | 1746 | +           cobalt_acpi_post_event( evt ); | 
|---|
|  | 1747 | +       } | 
|---|
|  | 1748 | +       if( (en & GEN_ACPI_RTC_STS) && | 
|---|
|  | 1749 | +           (sts & GEN_ACPI_RTC_STS) ) | 
|---|
|  | 1750 | +       { | 
|---|
|  | 1751 | +           evt.ev_type = COBALT_ACPI_EVT_RTC; | 
|---|
|  | 1752 | +           evt.ev_data = 0x0; | 
|---|
|  | 1753 | +           cobalt_acpi_post_event( evt ); | 
|---|
|  | 1754 | +       } | 
|---|
|  | 1755 | +       if( (sts & GEN_ACPI_WAK_STS) ) | 
|---|
|  | 1756 | +       { | 
|---|
|  | 1757 | +           evt.ev_type = COBALT_ACPI_EVT_WAK; | 
|---|
|  | 1758 | +           evt.ev_data = 0x0; | 
|---|
|  | 1759 | +           cobalt_acpi_post_event( evt ); | 
|---|
|  | 1760 | +       } | 
|---|
|  | 1761 | +    } | 
|---|
|  | 1762 | +} | 
|---|
|  | 1763 | + | 
|---|
|  | 1764 | +static void cobalt_acpi_handle_gpe_blk( u16 io_addr, u16 len, | 
|---|
|  | 1765 | +                                       generic_acpi_regions * regions ) | 
|---|
|  | 1766 | +{ | 
|---|
|  | 1767 | +    cobalt_acpi_evt evt; | 
|---|
|  | 1768 | +    int i,j; | 
|---|
|  | 1769 | +    u8 sts, en; | 
|---|
|  | 1770 | + | 
|---|
|  | 1771 | +    evt.hw_type = regions->hw_type; | 
|---|
|  | 1772 | +    evt.ev_type = COBALT_ACPI_EVT_GPE; | 
|---|
|  | 1773 | + | 
|---|
|  | 1774 | +    for( i=0 ; i<(len/2) ; i++ ) | 
|---|
|  | 1775 | +    { | 
|---|
|  | 1776 | +       sts = inb( io_addr + i ); | 
|---|
|  | 1777 | +       en =  inb( io_addr + len/2 + i ); | 
|---|
|  | 1778 | + | 
|---|
|  | 1779 | +           /* clear status bits */ | 
|---|
|  | 1780 | +       outb( sts, io_addr); | 
|---|
|  | 1781 | + | 
|---|
|  | 1782 | +       for( j=0 ; j<8 ; j++ ) | 
|---|
|  | 1783 | +       { | 
|---|
|  | 1784 | +           if( (en  & 0x1) && | 
|---|
|  | 1785 | +               (sts & 0x1) ) | 
|---|
|  | 1786 | +           { | 
|---|
|  | 1787 | +               evt.ev_data = i*8 + j; | 
|---|
|  | 1788 | +               cobalt_acpi_post_event( evt ); | 
|---|
|  | 1789 | +           } | 
|---|
|  | 1790 | +           en >>= 1; | 
|---|
|  | 1791 | +           sts >>= 1; | 
|---|
|  | 1792 | +       } | 
|---|
|  | 1793 | +    } | 
|---|
|  | 1794 | +} | 
|---|
|  | 1795 | + | 
|---|
|  | 1796 | +static int cobalt_acpi_generic_hw_handler( int irq, void *dev_id, | 
|---|
|  | 1797 | +                                          struct pt_regs *regs, void * data ) | 
|---|
|  | 1798 | +{ | 
|---|
|  | 1799 | +    generic_acpi_regions * regions = (generic_acpi_regions *) data; | 
|---|
|  | 1800 | +    cobalt_acpi_evt evt; | 
|---|
|  | 1801 | + | 
|---|
|  | 1802 | +    evt.hw_type = regions->hw_type; | 
|---|
|  | 1803 | + | 
|---|
|  | 1804 | +       /* various PM events */ | 
|---|
|  | 1805 | +    if( regions->pm1a_evt_blk ) | 
|---|
|  | 1806 | +       cobalt_acpi_handle_pm1_blk( regions->pm1a_evt_blk, regions->pm1_evt_len, regions ); | 
|---|
|  | 1807 | + | 
|---|
|  | 1808 | +    if( regions->pm1b_evt_blk ) | 
|---|
|  | 1809 | +       cobalt_acpi_handle_pm1_blk( regions->pm1b_evt_blk, regions->pm1_evt_len, regions ); | 
|---|
|  | 1810 | + | 
|---|
|  | 1811 | +    if( regions->gpe0_blk ) | 
|---|
|  | 1812 | +       cobalt_acpi_handle_gpe_blk( regions->gpe0_blk, regions->gpe0_len, regions ); | 
|---|
|  | 1813 | + | 
|---|
|  | 1814 | +    if( regions->gpe1_blk ) | 
|---|
|  | 1815 | +       cobalt_acpi_handle_gpe_blk( regions->gpe1_blk, regions->gpe1_len, regions ); | 
|---|
|  | 1816 | + | 
|---|
|  | 1817 | + | 
|---|
|  | 1818 | +    return 0; | 
|---|
|  | 1819 | +} | 
|---|
|  | 1820 | + | 
|---|
|  | 1821 | +static int cobalt_acpi_generic_en_handler( u16 ev_type, u16 ev_data, int en, void *data ) | 
|---|
|  | 1822 | +{ | 
|---|
|  | 1823 | +    generic_acpi_regions * regions = (generic_acpi_regions *) data; | 
|---|
|  | 1824 | +    int block, offset; | 
|---|
|  | 1825 | +    u8 data8; | 
|---|
|  | 1826 | +    u16 data16; | 
|---|
|  | 1827 | + | 
|---|
|  | 1828 | +    switch( ev_type ) | 
|---|
|  | 1829 | +    { | 
|---|
|  | 1830 | +       case COBALT_ACPI_EVT_TMR: | 
|---|
|  | 1831 | +           data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); | 
|---|
|  | 1832 | + | 
|---|
|  | 1833 | +           if( en ) | 
|---|
|  | 1834 | +           { | 
|---|
|  | 1835 | +               data16 |= GEN_ACPI_TMR_STS; | 
|---|
|  | 1836 | +               atomic_inc( ®ions->tmr_ref_cnt ); | 
|---|
|  | 1837 | +           } | 
|---|
|  | 1838 | +           else | 
|---|
|  | 1839 | +           { | 
|---|
|  | 1840 | +               if( atomic_dec_and_test( ®ions->tmr_ref_cnt ) ) | 
|---|
|  | 1841 | +                   data16 &= ~GEN_ACPI_TMR_STS; | 
|---|
|  | 1842 | +           } | 
|---|
|  | 1843 | +           outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); | 
|---|
|  | 1844 | +           break; | 
|---|
|  | 1845 | + | 
|---|
|  | 1846 | +       case COBALT_ACPI_EVT_BM: | 
|---|
|  | 1847 | +           data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); | 
|---|
|  | 1848 | + | 
|---|
|  | 1849 | +           if( en ) | 
|---|
|  | 1850 | +           { | 
|---|
|  | 1851 | +               data16 |= GEN_ACPI_BM_STS; | 
|---|
|  | 1852 | +               atomic_inc( ®ions->bm_ref_cnt ); | 
|---|
|  | 1853 | +           } | 
|---|
|  | 1854 | +           else | 
|---|
|  | 1855 | +           { | 
|---|
|  | 1856 | +               if( atomic_dec_and_test( ®ions->bm_ref_cnt ) ) | 
|---|
|  | 1857 | +                   data16 &= ~GEN_ACPI_BM_STS; | 
|---|
|  | 1858 | +           } | 
|---|
|  | 1859 | +           outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); | 
|---|
|  | 1860 | +           break; | 
|---|
|  | 1861 | + | 
|---|
|  | 1862 | +       case COBALT_ACPI_EVT_GBL: | 
|---|
|  | 1863 | +           data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); | 
|---|
|  | 1864 | + | 
|---|
|  | 1865 | +           if( en ) | 
|---|
|  | 1866 | +           { | 
|---|
|  | 1867 | +               data16 |= GEN_ACPI_GBL_STS; | 
|---|
|  | 1868 | +               atomic_inc( ®ions->gbl_ref_cnt ); | 
|---|
|  | 1869 | +           } | 
|---|
|  | 1870 | +           else | 
|---|
|  | 1871 | +           { | 
|---|
|  | 1872 | +               if( atomic_dec_and_test( ®ions->gbl_ref_cnt ) ) | 
|---|
|  | 1873 | +                   data16 &= ~GEN_ACPI_GBL_STS; | 
|---|
|  | 1874 | +           } | 
|---|
|  | 1875 | +           outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); | 
|---|
|  | 1876 | +           break; | 
|---|
|  | 1877 | + | 
|---|
|  | 1878 | +       case COBALT_ACPI_EVT_PWRBTN: | 
|---|
|  | 1879 | +           data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); | 
|---|
|  | 1880 | + | 
|---|
|  | 1881 | +           if( en ) | 
|---|
|  | 1882 | +           { | 
|---|
|  | 1883 | +               data16 |= GEN_ACPI_PWRBTN_STS; | 
|---|
|  | 1884 | +               atomic_inc( ®ions->pwrbtn_ref_cnt ); | 
|---|
|  | 1885 | +           } | 
|---|
|  | 1886 | +           else | 
|---|
|  | 1887 | +           { | 
|---|
|  | 1888 | +               if( atomic_dec_and_test( ®ions->pwrbtn_ref_cnt ) ) | 
|---|
|  | 1889 | +                   data16 &= ~GEN_ACPI_PWRBTN_STS; | 
|---|
|  | 1890 | +           } | 
|---|
|  | 1891 | +           outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); | 
|---|
|  | 1892 | +           break; | 
|---|
|  | 1893 | + | 
|---|
|  | 1894 | +       case COBALT_ACPI_EVT_SLPBTN: | 
|---|
|  | 1895 | +           data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); | 
|---|
|  | 1896 | + | 
|---|
|  | 1897 | +           if( en ) | 
|---|
|  | 1898 | +           { | 
|---|
|  | 1899 | +               data16 |= GEN_ACPI_SLPBTN_STS; | 
|---|
|  | 1900 | +               atomic_inc( ®ions->slpbtn_ref_cnt ); | 
|---|
|  | 1901 | +           } | 
|---|
|  | 1902 | +           else | 
|---|
|  | 1903 | +           { | 
|---|
|  | 1904 | +               if( atomic_dec_and_test( ®ions->slpbtn_ref_cnt ) ) | 
|---|
|  | 1905 | +                   data16 &= ~GEN_ACPI_SLPBTN_STS; | 
|---|
|  | 1906 | +           } | 
|---|
|  | 1907 | +           outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); | 
|---|
|  | 1908 | +           break; | 
|---|
|  | 1909 | + | 
|---|
|  | 1910 | +       case COBALT_ACPI_EVT_RTC: | 
|---|
|  | 1911 | +           data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); | 
|---|
|  | 1912 | + | 
|---|
|  | 1913 | +           if( en ) | 
|---|
|  | 1914 | +           { | 
|---|
|  | 1915 | +               data16 |= GEN_ACPI_RTC_STS; | 
|---|
|  | 1916 | +               atomic_inc( ®ions->rtc_ref_cnt ); | 
|---|
|  | 1917 | +           } | 
|---|
|  | 1918 | +           else | 
|---|
|  | 1919 | +           { | 
|---|
|  | 1920 | +               if( atomic_dec_and_test( ®ions->rtc_ref_cnt ) ) | 
|---|
|  | 1921 | +                   data16 &= ~GEN_ACPI_RTC_STS; | 
|---|
|  | 1922 | +           } | 
|---|
|  | 1923 | +           outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); | 
|---|
|  | 1924 | +           break; | 
|---|
|  | 1925 | + | 
|---|
|  | 1926 | +       case COBALT_ACPI_EVT_WAK: | 
|---|
|  | 1927 | +           data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); | 
|---|
|  | 1928 | + | 
|---|
|  | 1929 | +           if( en ) | 
|---|
|  | 1930 | +           { | 
|---|
|  | 1931 | +               data16 |= GEN_ACPI_WAK_STS; | 
|---|
|  | 1932 | +               atomic_inc( ®ions->wak_ref_cnt ); | 
|---|
|  | 1933 | +           } | 
|---|
|  | 1934 | +           else | 
|---|
|  | 1935 | +           { | 
|---|
|  | 1936 | +               if( atomic_dec_and_test( ®ions->wak_ref_cnt ) ) | 
|---|
|  | 1937 | +                   data16 &= ~GEN_ACPI_WAK_STS; | 
|---|
|  | 1938 | +           } | 
|---|
|  | 1939 | +           outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); | 
|---|
|  | 1940 | +           break; | 
|---|
|  | 1941 | + | 
|---|
|  | 1942 | +       case COBALT_ACPI_EVT_GPE: | 
|---|
|  | 1943 | +           if( (ev_data/8) >= (regions->gpe0_len / 2) ) | 
|---|
|  | 1944 | +               return -EINVAL; | 
|---|
|  | 1945 | + | 
|---|
|  | 1946 | +           block = ev_data / 8; | 
|---|
|  | 1947 | +           offset = ev_data % 8; | 
|---|
|  | 1948 | + | 
|---|
|  | 1949 | +           data8 = inb( regions->gpe0_blk + (regions->gpe0_len / 2) + block ); | 
|---|
|  | 1950 | + | 
|---|
|  | 1951 | +           if( en ) | 
|---|
|  | 1952 | +           { | 
|---|
|  | 1953 | +               data8 |= 0x1 << offset; | 
|---|
|  | 1954 | +               atomic_inc( ®ions->gpe_ref_cnt[ev_data] ); | 
|---|
|  | 1955 | +           } | 
|---|
|  | 1956 | +           else | 
|---|
|  | 1957 | +           { | 
|---|
|  | 1958 | +               if( atomic_dec_and_test( ®ions->gpe_ref_cnt[ev_data] ) ) | 
|---|
|  | 1959 | +                   data8 &= ~( 0x1 << offset ); | 
|---|
|  | 1960 | +           } | 
|---|
|  | 1961 | + | 
|---|
|  | 1962 | +           outb( data8, regions->gpe0_blk + (regions->gpe0_len / 2) + block ); | 
|---|
|  | 1963 | + | 
|---|
|  | 1964 | +           break; | 
|---|
|  | 1965 | + | 
|---|
|  | 1966 | +       default: | 
|---|
|  | 1967 | +           return -EINVAL; | 
|---|
|  | 1968 | + | 
|---|
|  | 1969 | +    } | 
|---|
|  | 1970 | + | 
|---|
|  | 1971 | +    return 0; | 
|---|
|  | 1972 | +} | 
|---|
|  | 1973 | + | 
|---|
|  | 1974 | +/* | 
|---|
|  | 1975 | + * | 
|---|
|  | 1976 | + * Generic ServerWorks region code | 
|---|
|  | 1977 | + * | 
|---|
|  | 1978 | + */ | 
|---|
|  | 1979 | + | 
|---|
|  | 1980 | +static int get_serverworks_regions( generic_acpi_regions *regions, u16 type ) | 
|---|
|  | 1981 | +{ | 
|---|
|  | 1982 | +   int reg; | 
|---|
|  | 1983 | + | 
|---|
|  | 1984 | +    memset( regions, 0x0, sizeof( *regions ) ); | 
|---|
|  | 1985 | + | 
|---|
|  | 1986 | +    regions->hw_type = type; | 
|---|
|  | 1987 | + | 
|---|
|  | 1988 | +    regions->pm1_evt_len = 4; | 
|---|
|  | 1989 | +    regions->pm1_cnt_len = 2; | 
|---|
|  | 1990 | +    regions->pm_tmr_len = 4; | 
|---|
|  | 1991 | +    regions->gpe0_len = 8; | 
|---|
|  | 1992 | + | 
|---|
|  | 1993 | +    if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x20)) ) | 
|---|
|  | 1994 | +       regions->pm1a_evt_blk = (u16) reg; | 
|---|
|  | 1995 | + | 
|---|
|  | 1996 | +    if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x22)) ) | 
|---|
|  | 1997 | +       regions->pm1a_cnt_blk = (u16) reg; | 
|---|
|  | 1998 | + | 
|---|
|  | 1999 | +    if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x24)) ) | 
|---|
|  | 2000 | +       regions->pm_tmr_blk = (u16) reg; | 
|---|
|  | 2001 | + | 
|---|
|  | 2002 | +    if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x26)) ) | 
|---|
|  | 2003 | +       regions->p_blk = (u16) reg; | 
|---|
|  | 2004 | + | 
|---|
|  | 2005 | +    if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x28)) ) | 
|---|
|  | 2006 | +       regions->gpe0_blk = (u16) reg; | 
|---|
|  | 2007 | + | 
|---|
|  | 2008 | +    if( type == COBALT_ACPI_HW_OSB4 ) | 
|---|
|  | 2009 | +    { | 
|---|
|  | 2010 | +       regions->pm2_cnt_len = 1; | 
|---|
|  | 2011 | +       if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x2E)) ) | 
|---|
|  | 2012 | +           regions->pm2_cnt_blk = (u16) reg; | 
|---|
|  | 2013 | +    } | 
|---|
|  | 2014 | + | 
|---|
|  | 2015 | +    switch( type ) | 
|---|
|  | 2016 | +    { | 
|---|
|  | 2017 | +       case COBALT_ACPI_HW_OSB4: | 
|---|
|  | 2018 | +           return register_acpi_regions( regions, "OSB4" ); | 
|---|
|  | 2019 | + | 
|---|
|  | 2020 | +       case COBALT_ACPI_HW_CSB5: | 
|---|
|  | 2021 | +           return register_acpi_regions( regions, "CSB5" ); | 
|---|
|  | 2022 | +    } | 
|---|
|  | 2023 | + | 
|---|
|  | 2024 | +    return -EINVAL; | 
|---|
|  | 2025 | + | 
|---|
|  | 2026 | +} | 
|---|
|  | 2027 | + | 
|---|
|  | 2028 | +/* | 
|---|
|  | 2029 | + * | 
|---|
|  | 2030 | + * ServerWorks OSB4 | 
|---|
|  | 2031 | + * | 
|---|
|  | 2032 | + */ | 
|---|
|  | 2033 | + | 
|---|
|  | 2034 | +static generic_acpi_regions osb4_regions; | 
|---|
|  | 2035 | + | 
|---|
|  | 2036 | +static int cobalt_acpi_osb4_init( void ) | 
|---|
|  | 2037 | +{ | 
|---|
|  | 2038 | +    int err; | 
|---|
|  | 2039 | + | 
|---|
|  | 2040 | +    if( (err = get_osb4_regions( &osb4_regions )) < 0 ) | 
|---|
|  | 2041 | +       return err; | 
|---|
|  | 2042 | + | 
|---|
|  | 2043 | +    if( (err = cobalt_acpi_register_hw_handler( COBALT_ACPI_HW_OSB4, | 
|---|
|  | 2044 | +                                               cobalt_acpi_generic_hw_handler, | 
|---|
|  | 2045 | +                                               cobalt_acpi_generic_en_handler, | 
|---|
|  | 2046 | +                                               &osb4_regions )) < 0 ) | 
|---|
|  | 2047 | +       return err; | 
|---|
|  | 2048 | + | 
|---|
|  | 2049 | +    return 0; | 
|---|
|  | 2050 | +} | 
|---|
|  | 2051 | + | 
|---|
|  | 2052 | +static int cobalt_acpi_osb4_cleanup( void ) | 
|---|
|  | 2053 | +{ | 
|---|
|  | 2054 | +    unregister_acpi_regions( &osb4_regions ); | 
|---|
|  | 2055 | +    return 0; | 
|---|
|  | 2056 | +} | 
|---|
|  | 2057 | + | 
|---|
|  | 2058 | +static int get_osb4_regions( generic_acpi_regions *regions) | 
|---|
|  | 2059 | +{ | 
|---|
|  | 2060 | +    return get_serverworks_regions( regions, COBALT_ACPI_HW_OSB4 ); | 
|---|
|  | 2061 | +} | 
|---|
|  | 2062 | + | 
|---|
|  | 2063 | +/* | 
|---|
|  | 2064 | + * | 
|---|
|  | 2065 | + * ServerWorks CSB5 | 
|---|
|  | 2066 | + * | 
|---|
|  | 2067 | + */ | 
|---|
|  | 2068 | + | 
|---|
|  | 2069 | +/* static generic_acpi_regions csb5_regions; */ | 
|---|
|  | 2070 | + | 
|---|
|  | 2071 | +static generic_acpi_regions csb5_regions; | 
|---|
|  | 2072 | + | 
|---|
|  | 2073 | +static int cobalt_acpi_csb5_init( void ) | 
|---|
|  | 2074 | +{ | 
|---|
|  | 2075 | +    int err; | 
|---|
|  | 2076 | + | 
|---|
|  | 2077 | +    if( (err = get_csb5_regions( &csb5_regions )) < 0 ) | 
|---|
|  | 2078 | +       return err; | 
|---|
|  | 2079 | + | 
|---|
|  | 2080 | +    if( (err = cobalt_acpi_register_hw_handler( COBALT_ACPI_HW_CSB5, | 
|---|
|  | 2081 | +                                               cobalt_acpi_generic_hw_handler, | 
|---|
|  | 2082 | +                                               cobalt_acpi_generic_en_handler, | 
|---|
|  | 2083 | +                                               &csb5_regions )) < 0 ) | 
|---|
|  | 2084 | +       return err; | 
|---|
|  | 2085 | + | 
|---|
|  | 2086 | +    return 0; | 
|---|
|  | 2087 | +} | 
|---|
|  | 2088 | + | 
|---|
|  | 2089 | +static int cobalt_acpi_csb5_cleanup( void ) | 
|---|
|  | 2090 | +{ | 
|---|
|  | 2091 | +    unregister_acpi_regions( &csb5_regions ); | 
|---|
|  | 2092 | +    return 0; | 
|---|
|  | 2093 | +} | 
|---|
|  | 2094 | + | 
|---|
|  | 2095 | +static int get_csb5_regions( generic_acpi_regions *regions) | 
|---|
|  | 2096 | +{ | 
|---|
|  | 2097 | +    return get_serverworks_regions( regions, COBALT_ACPI_HW_CSB5 ); | 
|---|
|  | 2098 | +} | 
|---|
|  | 2099 | + | 
|---|
|  | 2100 | +/* | 
|---|
|  | 2101 | + * | 
|---|
|  | 2102 | + * NatSemi PC8731x | 
|---|
|  | 2103 | + * | 
|---|
|  | 2104 | + */ | 
|---|
|  | 2105 | +static generic_acpi_regions pc8731x_regions; | 
|---|
|  | 2106 | + | 
|---|
|  | 2107 | +static int cobalt_acpi_pc8731x_init( void ) | 
|---|
|  | 2108 | +{ | 
|---|
|  | 2109 | +    int err; | 
|---|
|  | 2110 | + | 
|---|
|  | 2111 | +    if( (err = get_pc8731x_regions( &pc8731x_regions )) < 0 ) | 
|---|
|  | 2112 | +       return err; | 
|---|
|  | 2113 | + | 
|---|
|  | 2114 | +    if( (err = cobalt_acpi_register_hw_handler( COBALT_ACPI_HW_PC8731X, | 
|---|
|  | 2115 | +                                               cobalt_acpi_generic_hw_handler, | 
|---|
|  | 2116 | +                                               cobalt_acpi_generic_en_handler, | 
|---|
|  | 2117 | +                                               &pc8731x_regions )) < 0 ) | 
|---|
|  | 2118 | +       return err; | 
|---|
|  | 2119 | + | 
|---|
|  | 2120 | +    return 0; | 
|---|
|  | 2121 | +} | 
|---|
|  | 2122 | + | 
|---|
|  | 2123 | +static int cobalt_acpi_pc8731x_cleanup( void ) | 
|---|
|  | 2124 | +{ | 
|---|
|  | 2125 | +    unregister_acpi_regions( &pc8731x_regions ); | 
|---|
|  | 2126 | +    return 0; | 
|---|
|  | 2127 | +} | 
|---|
|  | 2128 | + | 
|---|
|  | 2129 | +static int get_pc8731x_regions( generic_acpi_regions *regions ) | 
|---|
|  | 2130 | +{ | 
|---|
|  | 2131 | +    int reg; | 
|---|
|  | 2132 | +    u16 addr; | 
|---|
|  | 2133 | + | 
|---|
|  | 2134 | +    memset( regions, 0x0, sizeof( *regions ) ); | 
|---|
|  | 2135 | + | 
|---|
|  | 2136 | +    regions->hw_type = COBALT_ACPI_HW_PC8731X; | 
|---|
|  | 2137 | + | 
|---|
|  | 2138 | +    regions->pm1_evt_len = 4; | 
|---|
|  | 2139 | +    regions->pm1_cnt_len = 2; | 
|---|
|  | 2140 | +    regions->pm_tmr_len = 4; | 
|---|
|  | 2141 | +    regions->gpe0_len = 4; | 
|---|
|  | 2142 | + | 
|---|
|  | 2143 | +       /* superi/o -- select pm logical device and get base address */ | 
|---|
|  | 2144 | +    addr = superio_ldev_base(PC87317_DEV_PM); | 
|---|
|  | 2145 | +    if( addr ) | 
|---|
|  | 2146 | +    { | 
|---|
|  | 2147 | +           /* get registers */ | 
|---|
|  | 2148 | +       if( (reg = get_reg(addr, addr + 1, 0x08)) ) | 
|---|
|  | 2149 | +           regions->pm1a_evt_blk = reg; | 
|---|
|  | 2150 | + | 
|---|
|  | 2151 | +       if( (reg = get_reg(addr, addr + 1, 0x0a)) ) | 
|---|
|  | 2152 | +           regions->pm_tmr_blk = reg; | 
|---|
|  | 2153 | + | 
|---|
|  | 2154 | +       if( (reg = get_reg(addr, addr + 1, 0x0c)) ) | 
|---|
|  | 2155 | +           regions->pm1a_cnt_blk = reg; | 
|---|
|  | 2156 | + | 
|---|
|  | 2157 | +       if( (reg = get_reg(addr, addr + 1, 0x0e)) ) | 
|---|
|  | 2158 | +           regions->gpe0_blk = reg; | 
|---|
|  | 2159 | +    } | 
|---|
|  | 2160 | + | 
|---|
|  | 2161 | +    return register_acpi_regions( regions, "pc8731x" ); | 
|---|
|  | 2162 | +} | 
|---|
|  | 2163 | + | 
|---|
|  | 2164 | +/* | 
|---|
|  | 2165 | + * | 
|---|
|  | 2166 | + * NatSemi PC8741x | 
|---|
|  | 2167 | + * | 
|---|
|  | 2168 | + */ | 
|---|
|  | 2169 | + | 
|---|
|  | 2170 | +static generic_acpi_regions pc8741x_regions; | 
|---|
|  | 2171 | + | 
|---|
|  | 2172 | +static int cobalt_acpi_pc8741x_init( void ) | 
|---|
|  | 2173 | +{ | 
|---|
|  | 2174 | +    int err; | 
|---|
|  | 2175 | + | 
|---|
|  | 2176 | +    if( (err = get_pc8741x_regions( &pc8741x_regions )) < 0 ) | 
|---|
|  | 2177 | +       return err; | 
|---|
|  | 2178 | + | 
|---|
|  | 2179 | +    if( (err = cobalt_acpi_register_hw_handler( COBALT_ACPI_HW_PC8741X, | 
|---|
|  | 2180 | +                                               cobalt_acpi_generic_hw_handler, | 
|---|
|  | 2181 | +                                               cobalt_acpi_generic_en_handler, | 
|---|
|  | 2182 | +                                               &pc8741x_regions )) < 0 ) | 
|---|
|  | 2183 | +       return err; | 
|---|
|  | 2184 | + | 
|---|
|  | 2185 | +    return 0; | 
|---|
|  | 2186 | +} | 
|---|
|  | 2187 | + | 
|---|
|  | 2188 | +static int cobalt_acpi_pc8741x_cleanup( void ) | 
|---|
|  | 2189 | +{ | 
|---|
|  | 2190 | +    unregister_acpi_regions( &pc8741x_regions ); | 
|---|
|  | 2191 | +    return 0; | 
|---|
|  | 2192 | +} | 
|---|
|  | 2193 | + | 
|---|
|  | 2194 | +static int get_pc8741x_regions( generic_acpi_regions *regions ) | 
|---|
|  | 2195 | +{ | 
|---|
|  | 2196 | +    int reg; | 
|---|
|  | 2197 | + | 
|---|
|  | 2198 | +    memset( regions, 0x0, sizeof( *regions ) ); | 
|---|
|  | 2199 | + | 
|---|
|  | 2200 | +    regions->hw_type = COBALT_ACPI_HW_PC8741X; | 
|---|
|  | 2201 | + | 
|---|
|  | 2202 | +    regions->pm1_evt_len = 4; | 
|---|
|  | 2203 | +    regions->pm1_cnt_len = 2; | 
|---|
|  | 2204 | +    regions->pm_tmr_len = 4; | 
|---|
|  | 2205 | +    regions->gpe0_len = 8; | 
|---|
|  | 2206 | + | 
|---|
|  | 2207 | +       /* get registers */ | 
|---|
|  | 2208 | +    if( (reg = superio_ldev_base_n(PC87417_DEV_SWC, 1)) ) | 
|---|
|  | 2209 | +       regions->pm1a_evt_blk = reg; | 
|---|
|  | 2210 | + | 
|---|
|  | 2211 | +    if( (reg = superio_ldev_base_n(PC87417_DEV_SWC, 2)) ) | 
|---|
|  | 2212 | +       regions->pm1a_cnt_blk = reg; | 
|---|
|  | 2213 | + | 
|---|
|  | 2214 | +    if( (reg = superio_ldev_base_n(PC87417_DEV_SWC, 3)) ) | 
|---|
|  | 2215 | +       regions->gpe0_blk = reg; | 
|---|
|  | 2216 | + | 
|---|
|  | 2217 | +    return register_acpi_regions( regions, "pc8741x" ); | 
|---|
|  | 2218 | +} | 
|---|
|  | 2219 | + | 
|---|
|  | 2220 | +/* | 
|---|
|  | 2221 | + * | 
|---|
|  | 2222 | + * Platform support | 
|---|
|  | 2223 | + * | 
|---|
|  | 2224 | + */ | 
|---|
|  | 2225 | + | 
|---|
|  | 2226 | +/* | 
|---|
|  | 2227 | + * | 
|---|
|  | 2228 | + * Monterey | 
|---|
|  | 2229 | + * | 
|---|
|  | 2230 | + */ | 
|---|
|  | 2231 | + | 
|---|
|  | 2232 | +static u16 cobalt_acpi_monterey_osb4_table[] = { | 
|---|
|  | 2233 | +/* GPE  0 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2234 | +/* GPE  1 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2235 | +/* GPE  2 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2236 | +/* GPE  3 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2237 | +/* GPE  4 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2238 | +/* GPE  5 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2239 | +/* GPE  6 */ COBALT_ACPI_EVT_SLED, | 
|---|
|  | 2240 | +/* GPE  7 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2241 | +/* GPE  8 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2242 | +/* GPE  9 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2243 | +/* GPE 10 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2244 | +/* GPE 11 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2245 | +/* GPE 12 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2246 | +/* GPE 13 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2247 | +/* GPE 14 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2248 | +/* GPE 15 */ COBALT_ACPI_EVT_NONE }; | 
|---|
|  | 2249 | + | 
|---|
|  | 2250 | +static u16 cobalt_acpi_monterey_superio_table[] = { | 
|---|
|  | 2251 | +/* GPE  0 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2252 | +/* GPE  1 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2253 | +/* GPE  2 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2254 | +/* GPE  3 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2255 | +/* GPE  4 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2256 | +/* GPE  5 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2257 | +/* GPE  6 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2258 | +/* GPE  7 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2259 | +/* GPE  8 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2260 | +/* GPE  9 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2261 | +/* GPE 10 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2262 | +/* GPE 11 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2263 | +/* GPE 12 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2264 | +/* GPE 13 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2265 | +/* GPE 14 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2266 | +/* GPE 15 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2267 | +/* GPE 16 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2268 | +/* GPE 17 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2269 | +/* GPE 18 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2270 | +/* GPE 19 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2271 | +/* GPE 20 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2272 | +/* GPE 21 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2273 | +/* GPE 22 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2274 | +/* GPE 23 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2275 | +/* GPE 24 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2276 | +/* GPE 25 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2277 | +/* GPE 26 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2278 | +/* GPE 27 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2279 | +/* GPE 28 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2280 | +/* GPE 29 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2281 | +/* GPE 30 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2282 | +/* GPE 31 */ COBALT_ACPI_EVT_NONE }; | 
|---|
|  | 2283 | + | 
|---|
|  | 2284 | +static int cobalt_acpi_monterey_init( void ) | 
|---|
|  | 2285 | +{ | 
|---|
|  | 2286 | +    int err; | 
|---|
|  | 2287 | + | 
|---|
|  | 2288 | +    err = cobalt_acpi_register_trans_table( COBALT_ACPI_HW_OSB4, | 
|---|
|  | 2289 | +                                           sizeof( cobalt_acpi_monterey_osb4_table )/sizeof( u16 ), | 
|---|
|  | 2290 | +                                           cobalt_acpi_monterey_osb4_table ); | 
|---|
|  | 2291 | +    if( err < 0 ) | 
|---|
|  | 2292 | +       return err; | 
|---|
|  | 2293 | + | 
|---|
|  | 2294 | +    err = cobalt_acpi_register_trans_table( COBALT_ACPI_HW_PC8731X, | 
|---|
|  | 2295 | +                                           sizeof( cobalt_acpi_monterey_superio_table )/sizeof( u16 ), | 
|---|
|  | 2296 | +                                           cobalt_acpi_monterey_superio_table ); | 
|---|
|  | 2297 | +    if( err < 0 ) | 
|---|
|  | 2298 | +       return err; | 
|---|
|  | 2299 | + | 
|---|
|  | 2300 | +    return 0; | 
|---|
|  | 2301 | +} | 
|---|
|  | 2302 | + | 
|---|
|  | 2303 | +static int cobalt_acpi_monterey_cleanup( void ) | 
|---|
|  | 2304 | +{ | 
|---|
|  | 2305 | +    cobalt_acpi_unregister_trans_table( COBALT_ACPI_HW_OSB4 ); | 
|---|
|  | 2306 | +    cobalt_acpi_unregister_trans_table( COBALT_ACPI_HW_PC8731X ); | 
|---|
|  | 2307 | + | 
|---|
|  | 2308 | +    return 0; | 
|---|
|  | 2309 | +} | 
|---|
|  | 2310 | + | 
|---|
|  | 2311 | +/* | 
|---|
|  | 2312 | + * | 
|---|
|  | 2313 | + * Alpine | 
|---|
|  | 2314 | + * | 
|---|
|  | 2315 | + */ | 
|---|
|  | 2316 | + | 
|---|
|  | 2317 | +static u16 cobalt_acpi_alpine_csb5_table[] = { | 
|---|
|  | 2318 | +/* GPE  0 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2319 | +/* GPE  1 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2320 | +/* GPE  2 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2321 | +/* GPE  3 */ COBALT_ACPI_EVT_FAN, | 
|---|
|  | 2322 | +/* GPE  4 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2323 | +/* GPE  5 */ COBALT_ACPI_EVT_SM_INT, | 
|---|
|  | 2324 | +/* GPE  6 */ COBALT_ACPI_EVT_THERM, | 
|---|
|  | 2325 | +/* GPE  7 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2326 | +/* GPE  8 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2327 | +/* GPE  9 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2328 | +/* GPE 10 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2329 | +/* GPE 11 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2330 | +/* GPE 12 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2331 | +/* GPE 13 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2332 | +/* GPE 14 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2333 | +/* GPE 15 */ COBALT_ACPI_EVT_NONE }; | 
|---|
|  | 2334 | + | 
|---|
|  | 2335 | +static u16 cobalt_acpi_alpine_superio_table[] = { | 
|---|
|  | 2336 | +/* GPE  0 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2337 | +/* GPE  1 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2338 | +/* GPE  2 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2339 | +/* GPE  3 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2340 | +/* GPE  4 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2341 | +/* GPE  5 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2342 | +/* GPE  6 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2343 | +/* GPE  7 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2344 | +/* GPE  8 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2345 | +/* GPE  9 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2346 | +/* GPE 10 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2347 | +/* GPE 11 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2348 | +/* GPE 12 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2349 | +/* GPE 13 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2350 | +/* GPE 14 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2351 | +/* GPE 15 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2352 | +/* GPE 16 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2353 | +/* GPE 17 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2354 | +/* GPE 18 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2355 | +/* GPE 19 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2356 | +/* GPE 20 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2357 | +/* GPE 21 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2358 | +/* GPE 22 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2359 | +/* GPE 23 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2360 | +/* GPE 24 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2361 | +/* GPE 25 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2362 | +/* GPE 26 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2363 | +/* GPE 27 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2364 | +/* GPE 28 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2365 | +/* GPE 29 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2366 | +/* GPE 30 */ COBALT_ACPI_EVT_NONE, | 
|---|
|  | 2367 | +/* GPE 31 */ COBALT_ACPI_EVT_NONE }; | 
|---|
|  | 2368 | + | 
|---|
|  | 2369 | +static int cobalt_acpi_alpine_init( void ) | 
|---|
|  | 2370 | +{ | 
|---|
|  | 2371 | +    int err; | 
|---|
|  | 2372 | + | 
|---|
|  | 2373 | +    err = cobalt_acpi_register_trans_table( COBALT_ACPI_HW_CSB5, | 
|---|
|  | 2374 | +                                           sizeof( cobalt_acpi_alpine_csb5_table )/sizeof( u16 ), | 
|---|
|  | 2375 | +                                           cobalt_acpi_alpine_csb5_table ); | 
|---|
|  | 2376 | +    if( err < 0 ) | 
|---|
|  | 2377 | +       return err; | 
|---|
|  | 2378 | + | 
|---|
|  | 2379 | +    err = cobalt_acpi_register_trans_table( COBALT_ACPI_HW_PC8741X, | 
|---|
|  | 2380 | +                                           sizeof( cobalt_acpi_alpine_superio_table )/sizeof( u16 ), | 
|---|
|  | 2381 | +                                           cobalt_acpi_alpine_superio_table ); | 
|---|
|  | 2382 | +    if( err < 0 ) | 
|---|
|  | 2383 | +       return err; | 
|---|
|  | 2384 | + | 
|---|
|  | 2385 | +    return 0; | 
|---|
|  | 2386 | +} | 
|---|
|  | 2387 | + | 
|---|
|  | 2388 | +static int cobalt_acpi_alpine_cleanup( void ) | 
|---|
|  | 2389 | +{ | 
|---|
|  | 2390 | +    cobalt_acpi_unregister_trans_table( COBALT_ACPI_HW_CSB5 ); | 
|---|
|  | 2391 | +    cobalt_acpi_unregister_trans_table( COBALT_ACPI_HW_PC8741X ); | 
|---|
|  | 2392 | + | 
|---|
|  | 2393 | +    return 0; | 
|---|
|  | 2394 | +} | 
|---|
|  | 2395 | + | 
|---|
|  | 2396 | +/* | 
|---|
|  | 2397 | + * end platform support | 
|---|
|  | 2398 | + */ | 
|---|
|  | 2399 | +#ifdef CONFIG_COBALT_EMU_ACPI | 
|---|
|  | 2400 | +/* | 
|---|
|  | 2401 | + * This is all necessary because we don't have BIOS support for ACPI yet. | 
|---|
|  | 2402 | + * We can fake it here, and when full support is ready just yank this. | 
|---|
|  | 2403 | + */ | 
|---|
|  | 2404 | +typedef struct { | 
|---|
|  | 2405 | +       char *device_type; | 
|---|
|  | 2406 | +       char *device_instance; | 
|---|
|  | 2407 | +       u32 event_type; | 
|---|
|  | 2408 | +       u32 event_data; | 
|---|
|  | 2409 | +       struct list_head list; | 
|---|
|  | 2410 | +} cobalt_acpi_event_t; | 
|---|
|  | 2411 | + | 
|---|
|  | 2412 | +#define COBALT_ACPI_MAX_STRING_LENGTH  80 | 
|---|
|  | 2413 | + | 
|---|
|  | 2414 | +static LIST_HEAD(cobalt_acpi_event_list); | 
|---|
|  | 2415 | +static DECLARE_WAIT_QUEUE_HEAD(cobalt_acpi_event_wait_queue); | 
|---|
|  | 2416 | +static int event_is_open = 0; | 
|---|
|  | 2417 | +static spinlock_t cobalt_acpi_event_lock = SPIN_LOCK_UNLOCKED; | 
|---|
|  | 2418 | + | 
|---|
|  | 2419 | +static struct proc_dir_entry *cobalt_acpi_proc_root; | 
|---|
|  | 2420 | +static struct proc_dir_entry *cobalt_acpi_proc_event; | 
|---|
|  | 2421 | + | 
|---|
|  | 2422 | +static struct file_operations proc_event_ops = { | 
|---|
|  | 2423 | +       open: cobalt_acpi_open_event, | 
|---|
|  | 2424 | +       read: cobalt_acpi_read_event, | 
|---|
|  | 2425 | +       release: cobalt_acpi_close_event, | 
|---|
|  | 2426 | +       poll: cobalt_acpi_poll_event, | 
|---|
|  | 2427 | +}; | 
|---|
|  | 2428 | + | 
|---|
|  | 2429 | +static int | 
|---|
|  | 2430 | +cobalt_acpi_setup_proc(void) | 
|---|
|  | 2431 | +{ | 
|---|
|  | 2432 | +       cobalt_acpi_proc_root = proc_mkdir("acpi", NULL); | 
|---|
|  | 2433 | +       if (!cobalt_acpi_proc_root) { | 
|---|
|  | 2434 | +               return -ENOMEM; | 
|---|
|  | 2435 | +       } | 
|---|
|  | 2436 | + | 
|---|
|  | 2437 | +       cobalt_acpi_proc_event = create_proc_entry("event", S_IRUSR, | 
|---|
|  | 2438 | +                                               cobalt_acpi_proc_root); | 
|---|
|  | 2439 | +       if (!cobalt_acpi_proc_event) { | 
|---|
|  | 2440 | +               return -ENOMEM; | 
|---|
|  | 2441 | +       } | 
|---|
|  | 2442 | + | 
|---|
|  | 2443 | +       cobalt_acpi_proc_event->proc_fops = &proc_event_ops; | 
|---|
|  | 2444 | + | 
|---|
|  | 2445 | +       return 0; | 
|---|
|  | 2446 | +} | 
|---|
|  | 2447 | + | 
|---|
|  | 2448 | + | 
|---|
|  | 2449 | +int | 
|---|
|  | 2450 | +cobalt_acpi_generate_proc_evt( cobalt_acpi_evt * evt ) | 
|---|
|  | 2451 | +{ | 
|---|
|  | 2452 | +       cobalt_acpi_event_t *event = NULL, *tmp; | 
|---|
|  | 2453 | +       unsigned long flags = 0; | 
|---|
|  | 2454 | +       char *dev_type; | 
|---|
|  | 2455 | +       char *dev_instance; | 
|---|
|  | 2456 | +       u32 event_type; | 
|---|
|  | 2457 | +       u32 event_data; | 
|---|
|  | 2458 | +       struct list_head *pos; | 
|---|
|  | 2459 | + | 
|---|
|  | 2460 | +       /* drop event on the floor if no one's listening */ | 
|---|
|  | 2461 | +       if (!event_is_open) | 
|---|
|  | 2462 | +               return 0; | 
|---|
|  | 2463 | + | 
|---|
|  | 2464 | +       event_type = (evt->ev_type << 0x10) | | 
|---|
|  | 2465 | +           evt->hw_type; | 
|---|
|  | 2466 | +       event_data = evt->ev_data; | 
|---|
|  | 2467 | + | 
|---|
|  | 2468 | + | 
|---|
|  | 2469 | +           /* | 
|---|
|  | 2470 | +            * Check to see if an event of this type is already | 
|---|
|  | 2471 | +            * pending | 
|---|
|  | 2472 | +            */ | 
|---|
|  | 2473 | +       spin_lock_irqsave(&cobalt_acpi_event_lock, flags); | 
|---|
|  | 2474 | +       list_for_each( pos, &cobalt_acpi_event_list ) | 
|---|
|  | 2475 | +           { | 
|---|
|  | 2476 | +               tmp = list_entry(pos, cobalt_acpi_event_t, list); | 
|---|
|  | 2477 | +               if( (tmp->event_type == event_type) && | 
|---|
|  | 2478 | +                   (tmp->event_data == event_data) ) | 
|---|
|  | 2479 | +               { | 
|---|
|  | 2480 | +                   spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags); | 
|---|
|  | 2481 | +                   return 0; | 
|---|
|  | 2482 | +               } | 
|---|
|  | 2483 | + | 
|---|
|  | 2484 | + | 
|---|
|  | 2485 | +           } | 
|---|
|  | 2486 | +       spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags); | 
|---|
|  | 2487 | + | 
|---|
|  | 2488 | + | 
|---|
|  | 2489 | +           /* parse the event struct */ | 
|---|
|  | 2490 | +       switch( evt->ev_type ) | 
|---|
|  | 2491 | +       { | 
|---|
|  | 2492 | +           case COBALT_ACPI_EVT_TMR: | 
|---|
|  | 2493 | +               dev_type = "generic"; | 
|---|
|  | 2494 | +               dev_instance = "timer"; | 
|---|
|  | 2495 | +               break; | 
|---|
|  | 2496 | + | 
|---|
|  | 2497 | +           case COBALT_ACPI_EVT_BM: | 
|---|
|  | 2498 | +               dev_type = "generic"; | 
|---|
|  | 2499 | +               dev_instance = "bus-master"; | 
|---|
|  | 2500 | +               break; | 
|---|
|  | 2501 | + | 
|---|
|  | 2502 | +           case COBALT_ACPI_EVT_GBL: | 
|---|
|  | 2503 | +               dev_type = "generic"; | 
|---|
|  | 2504 | +               dev_instance = "global"; | 
|---|
|  | 2505 | +               break; | 
|---|
|  | 2506 | + | 
|---|
|  | 2507 | +           case COBALT_ACPI_EVT_PWRBTN: | 
|---|
|  | 2508 | +               dev_type = "button"; | 
|---|
|  | 2509 | +               dev_instance = "power"; | 
|---|
|  | 2510 | +               break; | 
|---|
|  | 2511 | + | 
|---|
|  | 2512 | +           case COBALT_ACPI_EVT_SLPBTN: | 
|---|
|  | 2513 | +               dev_type = "button"; | 
|---|
|  | 2514 | +               dev_instance = "sleep"; | 
|---|
|  | 2515 | +               break; | 
|---|
|  | 2516 | + | 
|---|
|  | 2517 | +           case COBALT_ACPI_EVT_RTC: | 
|---|
|  | 2518 | +               dev_type = "generic"; | 
|---|
|  | 2519 | +               dev_instance = "rtc"; | 
|---|
|  | 2520 | +               break; | 
|---|
|  | 2521 | + | 
|---|
|  | 2522 | +           case COBALT_ACPI_EVT_WAK: | 
|---|
|  | 2523 | +               dev_type = "generic"; | 
|---|
|  | 2524 | +               dev_instance = "wake"; | 
|---|
|  | 2525 | +               break; | 
|---|
|  | 2526 | + | 
|---|
|  | 2527 | +           case COBALT_ACPI_EVT_GPE: | 
|---|
|  | 2528 | +               dev_type = "generic"; | 
|---|
|  | 2529 | +               dev_instance = "gpe"; | 
|---|
|  | 2530 | +               break; | 
|---|
|  | 2531 | + | 
|---|
|  | 2532 | +           case COBALT_ACPI_EVT_SLED: | 
|---|
|  | 2533 | +               dev_type = "cobalt"; | 
|---|
|  | 2534 | +               dev_instance = "sled"; | 
|---|
|  | 2535 | +               break; | 
|---|
|  | 2536 | + | 
|---|
|  | 2537 | +           case COBALT_ACPI_EVT_THERM: | 
|---|
|  | 2538 | +               dev_type = "cobalt"; | 
|---|
|  | 2539 | +               dev_instance = "therm_trip"; | 
|---|
|  | 2540 | +               break; | 
|---|
|  | 2541 | + | 
|---|
|  | 2542 | +           case COBALT_ACPI_EVT_FAN: | 
|---|
|  | 2543 | +               dev_type = "cobalt"; | 
|---|
|  | 2544 | +               dev_instance = "fan"; | 
|---|
|  | 2545 | +               break; | 
|---|
|  | 2546 | + | 
|---|
|  | 2547 | +           case COBALT_ACPI_EVT_SM_INT: | 
|---|
|  | 2548 | +               dev_type = "cobalt"; | 
|---|
|  | 2549 | +               dev_instance = "sm_int"; | 
|---|
|  | 2550 | +               break; | 
|---|
|  | 2551 | + | 
|---|
|  | 2552 | +           case COBALT_ACPI_EVT_VOLT: | 
|---|
|  | 2553 | +               dev_type = "cobalt"; | 
|---|
|  | 2554 | +               dev_instance = "volt_trip"; | 
|---|
|  | 2555 | +               break; | 
|---|
|  | 2556 | + | 
|---|
|  | 2557 | +           default: | 
|---|
|  | 2558 | +               dev_type = "unknown"; | 
|---|
|  | 2559 | +               dev_instance = "unknown"; | 
|---|
|  | 2560 | +               break; | 
|---|
|  | 2561 | +       } | 
|---|
|  | 2562 | + | 
|---|
|  | 2563 | + | 
|---|
|  | 2564 | +       /* | 
|---|
|  | 2565 | +        * Allocate a new event structure. | 
|---|
|  | 2566 | +        */ | 
|---|
|  | 2567 | +       event = kmalloc(sizeof(*event), GFP_ATOMIC); | 
|---|
|  | 2568 | +       if (!event) | 
|---|
|  | 2569 | +               goto alloc_error; | 
|---|
|  | 2570 | + | 
|---|
|  | 2571 | +       event->device_type=NULL; | 
|---|
|  | 2572 | +       event->device_instance=NULL; | 
|---|
|  | 2573 | + | 
|---|
|  | 2574 | +       event->device_type = kmalloc(strlen(dev_type) + sizeof(char), | 
|---|
|  | 2575 | +               GFP_ATOMIC); | 
|---|
|  | 2576 | +       if (!event->device_type) | 
|---|
|  | 2577 | +               goto alloc_error; | 
|---|
|  | 2578 | + | 
|---|
|  | 2579 | +       event->device_instance = kmalloc(strlen(dev_instance) + sizeof(char), | 
|---|
|  | 2580 | +               GFP_ATOMIC ); | 
|---|
|  | 2581 | +       if (!event->device_instance) | 
|---|
|  | 2582 | +               goto alloc_error; | 
|---|
|  | 2583 | + | 
|---|
|  | 2584 | +       /* | 
|---|
|  | 2585 | +        * Set event data. | 
|---|
|  | 2586 | +        */ | 
|---|
|  | 2587 | +       strcpy(event->device_type, dev_type); | 
|---|
|  | 2588 | +       strcpy(event->device_instance, dev_instance); | 
|---|
|  | 2589 | +       event->event_type = event_type; | 
|---|
|  | 2590 | +       event->event_data = event_data; | 
|---|
|  | 2591 | + | 
|---|
|  | 2592 | +       /* | 
|---|
|  | 2593 | +        * Add to the end of our event list. | 
|---|
|  | 2594 | +        */ | 
|---|
|  | 2595 | +       spin_lock_irqsave(&cobalt_acpi_event_lock, flags); | 
|---|
|  | 2596 | +       list_add_tail(&event->list, &cobalt_acpi_event_list); | 
|---|
|  | 2597 | +       spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags); | 
|---|
|  | 2598 | + | 
|---|
|  | 2599 | +       /* | 
|---|
|  | 2600 | +        * Signal waiting threads (if any). | 
|---|
|  | 2601 | +        */ | 
|---|
|  | 2602 | +       wake_up_interruptible(&cobalt_acpi_event_wait_queue); | 
|---|
|  | 2603 | + | 
|---|
|  | 2604 | +       return 0; | 
|---|
|  | 2605 | + | 
|---|
|  | 2606 | +alloc_error: | 
|---|
|  | 2607 | +       if(event) | 
|---|
|  | 2608 | +       { | 
|---|
|  | 2609 | +           if (event->device_instance) | 
|---|
|  | 2610 | +               kfree(event->device_instance); | 
|---|
|  | 2611 | + | 
|---|
|  | 2612 | +           if (event->device_type) | 
|---|
|  | 2613 | +               kfree(event->device_type); | 
|---|
|  | 2614 | + | 
|---|
|  | 2615 | +           kfree(event); | 
|---|
|  | 2616 | +       } | 
|---|
|  | 2617 | + | 
|---|
|  | 2618 | +       return -ENOMEM; | 
|---|
|  | 2619 | +} | 
|---|
|  | 2620 | + | 
|---|
|  | 2621 | + | 
|---|
|  | 2622 | +static int | 
|---|
|  | 2623 | +cobalt_acpi_open_event(struct inode *inode, struct file *file) | 
|---|
|  | 2624 | +{ | 
|---|
|  | 2625 | +    unsigned long flags; | 
|---|
|  | 2626 | +    spin_lock_irqsave(&cobalt_acpi_event_lock, flags); | 
|---|
|  | 2627 | + | 
|---|
|  | 2628 | +    if (event_is_open) | 
|---|
|  | 2629 | +       goto out_busy; | 
|---|
|  | 2630 | + | 
|---|
|  | 2631 | +    event_is_open = 1; | 
|---|
|  | 2632 | + | 
|---|
|  | 2633 | +    spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags); | 
|---|
|  | 2634 | +    return 0; | 
|---|
|  | 2635 | + | 
|---|
|  | 2636 | +out_busy: | 
|---|
|  | 2637 | +    spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags); | 
|---|
|  | 2638 | +    return -EBUSY; | 
|---|
|  | 2639 | +} | 
|---|
|  | 2640 | + | 
|---|
|  | 2641 | + | 
|---|
|  | 2642 | +static int | 
|---|
|  | 2643 | +cobalt_acpi_close_event(struct inode *inode, struct file *file) | 
|---|
|  | 2644 | +{ | 
|---|
|  | 2645 | +    unsigned long flags; | 
|---|
|  | 2646 | +    struct list_head *pos; | 
|---|
|  | 2647 | +    cobalt_acpi_event_t *tmp; | 
|---|
|  | 2648 | + | 
|---|
|  | 2649 | +    spin_lock_irqsave(&cobalt_acpi_event_lock, flags); | 
|---|
|  | 2650 | + | 
|---|
|  | 2651 | +    while( (pos = list_pop( &cobalt_acpi_event_list )) ) | 
|---|
|  | 2652 | +    { | 
|---|
|  | 2653 | +       tmp = list_entry(pos, cobalt_acpi_event_t, list); | 
|---|
|  | 2654 | +       if (tmp->device_instance) | 
|---|
|  | 2655 | +               kfree(tmp->device_instance); | 
|---|
|  | 2656 | + | 
|---|
|  | 2657 | +       if (tmp->device_type) | 
|---|
|  | 2658 | +               kfree(tmp->device_type); | 
|---|
|  | 2659 | + | 
|---|
|  | 2660 | +       kfree( tmp ); | 
|---|
|  | 2661 | +    } | 
|---|
|  | 2662 | +    event_is_open = 0; | 
|---|
|  | 2663 | +    spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags); | 
|---|
|  | 2664 | +    return 0; | 
|---|
|  | 2665 | +} | 
|---|
|  | 2666 | + | 
|---|
|  | 2667 | +#define ACPI_MAX_STRING_LENGTH         80 | 
|---|
|  | 2668 | +static ssize_t | 
|---|
|  | 2669 | +cobalt_acpi_read_event(struct file *file, char *buf, size_t count, loff_t *ppos) | 
|---|
|  | 2670 | +{ | 
|---|
|  | 2671 | +       cobalt_acpi_event_t *event = NULL; | 
|---|
|  | 2672 | +       unsigned long flags = 0; | 
|---|
|  | 2673 | +       static char str[ACPI_MAX_STRING_LENGTH]; | 
|---|
|  | 2674 | +       static int strsize; | 
|---|
|  | 2675 | +       static char *ptr; | 
|---|
|  | 2676 | + | 
|---|
|  | 2677 | +       if (!strsize) { | 
|---|
|  | 2678 | +               DECLARE_WAITQUEUE(wait, current); | 
|---|
|  | 2679 | + | 
|---|
|  | 2680 | +               if (list_empty(&cobalt_acpi_event_list)) { | 
|---|
|  | 2681 | +                       if (file->f_flags & O_NONBLOCK) { | 
|---|
|  | 2682 | +                               return -EAGAIN; | 
|---|
|  | 2683 | +                       } | 
|---|
|  | 2684 | +                       set_current_state(TASK_INTERRUPTIBLE); | 
|---|
|  | 2685 | +                       add_wait_queue(&cobalt_acpi_event_wait_queue, &wait); | 
|---|
|  | 2686 | + | 
|---|
|  | 2687 | +                       if (list_empty(&cobalt_acpi_event_list)) { | 
|---|
|  | 2688 | +                               schedule(); | 
|---|
|  | 2689 | +                       } | 
|---|
|  | 2690 | + | 
|---|
|  | 2691 | +                       remove_wait_queue(&cobalt_acpi_event_wait_queue, &wait); | 
|---|
|  | 2692 | +                       set_current_state(TASK_RUNNING); | 
|---|
|  | 2693 | + | 
|---|
|  | 2694 | +                       if (signal_pending(current)) { | 
|---|
|  | 2695 | +                               return -ERESTARTSYS; | 
|---|
|  | 2696 | +                       } | 
|---|
|  | 2697 | +               } | 
|---|
|  | 2698 | + | 
|---|
|  | 2699 | +               spin_lock_irqsave(&cobalt_acpi_event_lock, flags); | 
|---|
|  | 2700 | +               event = list_entry(cobalt_acpi_event_list.next, | 
|---|
|  | 2701 | +                       cobalt_acpi_event_t, list); | 
|---|
|  | 2702 | +               list_del(&event->list); | 
|---|
|  | 2703 | +               spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags); | 
|---|
|  | 2704 | + | 
|---|
|  | 2705 | +               strsize = sprintf(str, "%s %s %08x %08x\n", | 
|---|
|  | 2706 | +                       event->device_type, event->device_instance, | 
|---|
|  | 2707 | +                       event->event_type, event->event_data); | 
|---|
|  | 2708 | +               ptr = str; | 
|---|
|  | 2709 | + | 
|---|
|  | 2710 | +               kfree(event->device_type); | 
|---|
|  | 2711 | +               kfree(event->device_instance); | 
|---|
|  | 2712 | +               kfree(event); | 
|---|
|  | 2713 | +       } | 
|---|
|  | 2714 | +       if (strsize < count) | 
|---|
|  | 2715 | +               count = strsize; | 
|---|
|  | 2716 | + | 
|---|
|  | 2717 | +       if (copy_to_user(buf, ptr, count)) | 
|---|
|  | 2718 | +               return -EFAULT; | 
|---|
|  | 2719 | + | 
|---|
|  | 2720 | +       *ppos += count; | 
|---|
|  | 2721 | +       strsize -= count; | 
|---|
|  | 2722 | +       ptr += count; | 
|---|
|  | 2723 | + | 
|---|
|  | 2724 | +       return count; | 
|---|
|  | 2725 | +} | 
|---|
|  | 2726 | + | 
|---|
|  | 2727 | +static unsigned int | 
|---|
|  | 2728 | +cobalt_acpi_poll_event(struct file *file, poll_table *wait) | 
|---|
|  | 2729 | +{ | 
|---|
|  | 2730 | +       poll_wait(file, &cobalt_acpi_event_wait_queue, wait); | 
|---|
|  | 2731 | +       if (!list_empty(&cobalt_acpi_event_list)) | 
|---|
|  | 2732 | +               return POLLIN | POLLRDNORM; | 
|---|
|  | 2733 | +       return 0; | 
|---|
|  | 2734 | +} | 
|---|
|  | 2735 | + | 
|---|
|  | 2736 | +#endif /* CONFIG_COBALT_EMU_ACPI */ | 
|---|
|  | 2737 | diff -Naur linux-2.6.20.orig/drivers/cobalt/fans.c linux-2.6.20/drivers/cobalt/fans.c | 
|---|
|  | 2738 | --- linux-2.6.20.orig/drivers/cobalt/fans.c     1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 2739 | +++ linux-2.6.20/drivers/cobalt/fans.c  2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 2740 | @@ -0,0 +1,419 @@ | 
|---|
|  | 2741 | +/* $Id: fans.c,v 1.18 2002/03/16 21:33:02 duncan Exp $ | 
|---|
|  | 2742 | + * Copyright (c) 2000-2001 Sun Microsystems, Inc | 
|---|
|  | 2743 | + * | 
|---|
|  | 2744 | + * This should be SMP safe.  The critical data (the info list) and the | 
|---|
|  | 2745 | + * critical code (inb()/outb() calls) are protected by fan_lock.  It is | 
|---|
|  | 2746 | + * locked at the only external access points - the proc read()/write() | 
|---|
|  | 2747 | + * methods. --TPH | 
|---|
|  | 2748 | + */ | 
|---|
|  | 2749 | +#include <linux/config.h> | 
|---|
|  | 2750 | +#if defined(CONFIG_COBALT_FANS) || defined(CONFIG_COBALT_FANS_MODULE) | 
|---|
|  | 2751 | + | 
|---|
|  | 2752 | +#include <stdarg.h> | 
|---|
|  | 2753 | +#include <stddef.h> | 
|---|
|  | 2754 | + | 
|---|
|  | 2755 | +#include <linux/init.h> | 
|---|
|  | 2756 | +#include <linux/sched.h> | 
|---|
|  | 2757 | +#include <linux/module.h> | 
|---|
|  | 2758 | +#include <linux/pci.h> | 
|---|
|  | 2759 | +#include <linux/errno.h> | 
|---|
|  | 2760 | +#include <linux/proc_fs.h> | 
|---|
|  | 2761 | +#include <linux/time.h> | 
|---|
|  | 2762 | + | 
|---|
|  | 2763 | +#include <asm/io.h> | 
|---|
|  | 2764 | +#include <asm/uaccess.h> | 
|---|
|  | 2765 | + | 
|---|
|  | 2766 | +#include <cobalt/cobalt.h> | 
|---|
|  | 2767 | +#include <cobalt/systype.h> | 
|---|
|  | 2768 | + | 
|---|
|  | 2769 | +#define FAN_DRIVER      "Cobalt Networks Fan driver" | 
|---|
|  | 2770 | +#define FAN_DRIVER_VMAJ 1 | 
|---|
|  | 2771 | +#define FAN_DRIVER_VMIN 0 | 
|---|
|  | 2772 | + | 
|---|
|  | 2773 | +/* GPIO base is assigned by BIOS, perhaps we should probe it */ | 
|---|
|  | 2774 | +#define GPIO_BASE              0x600 | 
|---|
|  | 2775 | +#define FAN_GPIO_MAX           8 | 
|---|
|  | 2776 | +#define FAN_RPM(fn,ms)         ((fn).hcyl * (60000000 / (fn).poles) / (ms)) | 
|---|
|  | 2777 | +#define FAN_VALID(f)           ((f)->mask && (f)->poles) | 
|---|
|  | 2778 | +#define FAN_CACHE_TIME         2 /* seconds */ | 
|---|
|  | 2779 | +#define FAN_SAMPLE_LEN         50 /* milliseconds */ | 
|---|
|  | 2780 | + | 
|---|
|  | 2781 | +/* | 
|---|
|  | 2782 | + * fans are attached to GPIO pins | 
|---|
|  | 2783 | + * each pin is part of a port, multiple fans are controlled by a port | 
|---|
|  | 2784 | + */ | 
|---|
|  | 2785 | +struct fan_info { | 
|---|
|  | 2786 | +       int id;                 /* fan number */ | 
|---|
|  | 2787 | +       uint8_t mask;           /* mask within the port */ | 
|---|
|  | 2788 | +       int poles;              /* # of magnetic poles (divisor) */ | 
|---|
|  | 2789 | +       int hcyl;               /* # of half cycles */ | 
|---|
|  | 2790 | +       unsigned rpm;           /* calculated fan speed */ | 
|---|
|  | 2791 | +       char *type;             /* FAN description */ | 
|---|
|  | 2792 | +}; | 
|---|
|  | 2793 | + | 
|---|
|  | 2794 | +struct fan_gpio { | 
|---|
|  | 2795 | +       int port;               /* GPIO Port */ | 
|---|
|  | 2796 | +       uint16_t base;          /* GPDI (data in) base address */ | 
|---|
|  | 2797 | +       uint8_t latch;          /* latched 'data in' value */ | 
|---|
|  | 2798 | +       long tcache;            /* latched 'epoch' value */ | 
|---|
|  | 2799 | +       struct fan_info fan[FAN_GPIO_MAX]; | 
|---|
|  | 2800 | +}; | 
|---|
|  | 2801 | + | 
|---|
|  | 2802 | +/* the current fanlist */ | 
|---|
|  | 2803 | +static struct fan_gpio *sys_fanlist; | 
|---|
|  | 2804 | +static spinlock_t fan_lock = SPIN_LOCK_UNLOCKED; | 
|---|
|  | 2805 | + | 
|---|
|  | 2806 | +static struct fan_gpio fan_gpio_raqxtr[] = { | 
|---|
|  | 2807 | +       { | 
|---|
|  | 2808 | +               port: 1, | 
|---|
|  | 2809 | +               base: GPIO_BASE, | 
|---|
|  | 2810 | +               fan: { | 
|---|
|  | 2811 | +                       { mask: 0x2, poles: 4, type: "processor" }, | 
|---|
|  | 2812 | +                       { mask: 0x4, poles: 4, type: "processor" }, | 
|---|
|  | 2813 | +                       { mask: 0 }, | 
|---|
|  | 2814 | +               }, | 
|---|
|  | 2815 | +       }, | 
|---|
|  | 2816 | +       { | 
|---|
|  | 2817 | +               port: 2, | 
|---|
|  | 2818 | +               base: GPIO_BASE+4, | 
|---|
|  | 2819 | +               fan: { | 
|---|
|  | 2820 | +                       { mask: 0x10, poles: 4 }, | 
|---|
|  | 2821 | +                       { mask: 0x20, poles: 4 }, | 
|---|
|  | 2822 | +                       { mask: 0x40, poles: 4 }, | 
|---|
|  | 2823 | +                       { mask: 0x80, poles: 4 }, | 
|---|
|  | 2824 | +                       { mask: 0 }, | 
|---|
|  | 2825 | +               }, | 
|---|
|  | 2826 | +       }, | 
|---|
|  | 2827 | +       { port: -1 } | 
|---|
|  | 2828 | +}; | 
|---|
|  | 2829 | + | 
|---|
|  | 2830 | +static struct fan_gpio fan_gpio_alpine[] = { | 
|---|
|  | 2831 | +       { | 
|---|
|  | 2832 | +               port: 2, | 
|---|
|  | 2833 | +               base: GPIO_BASE+7, | 
|---|
|  | 2834 | +               fan:  { | 
|---|
|  | 2835 | +                       { mask: 0x4, poles: 4 }, | 
|---|
|  | 2836 | +                       { mask: 0x8, poles: 4 }, | 
|---|
|  | 2837 | +                       { mask: 0x10, poles: 4 }, | 
|---|
|  | 2838 | +                       { mask: 0x20, poles: 4, type: "power supply" }, | 
|---|
|  | 2839 | +                       { mask: 0x40, poles: 4, type: "processor" }, | 
|---|
|  | 2840 | +                       { mask: 0 }, | 
|---|
|  | 2841 | +               }, | 
|---|
|  | 2842 | +       }, | 
|---|
|  | 2843 | +       { port: -1 } | 
|---|
|  | 2844 | +}; | 
|---|
|  | 2845 | + | 
|---|
|  | 2846 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 2847 | +#ifdef CONFIG_COBALT_OLDPROC | 
|---|
|  | 2848 | +static struct proc_dir_entry *proc_faninfo; | 
|---|
|  | 2849 | +#endif /* CONFIG_COBALT_OLDPROC */ | 
|---|
|  | 2850 | +static struct proc_dir_entry *proc_cfaninfo; | 
|---|
|  | 2851 | +#endif /* CONFIG_PROC_FS */ | 
|---|
|  | 2852 | + | 
|---|
|  | 2853 | +static struct fan_info *fan_info_find(int id); | 
|---|
|  | 2854 | +static int fan_control(struct fan_info *fi, int todo); | 
|---|
|  | 2855 | +static int fan_info_print(char *buffer); | 
|---|
|  | 2856 | +static int fan_read_proc(char *buf, char **start, off_t pos, | 
|---|
|  | 2857 | +                        int len, int *eof, void *x); | 
|---|
|  | 2858 | +static int fan_write_proc(struct file *file, const char *buf, | 
|---|
|  | 2859 | +                         unsigned long len, void *x); | 
|---|
|  | 2860 | + | 
|---|
|  | 2861 | +int __init | 
|---|
|  | 2862 | +cobalt_fan_init(void) | 
|---|
|  | 2863 | +{ | 
|---|
|  | 2864 | +       if (cobt_is_monterey()) { | 
|---|
|  | 2865 | +               sys_fanlist = (struct fan_gpio *)fan_gpio_raqxtr; | 
|---|
|  | 2866 | +       } else if (cobt_is_alpine()) { | 
|---|
|  | 2867 | +               sys_fanlist = (struct fan_gpio *)fan_gpio_alpine; | 
|---|
|  | 2868 | +       } else { | 
|---|
|  | 2869 | +               sys_fanlist = NULL; | 
|---|
|  | 2870 | +               return -ENOSYS; | 
|---|
|  | 2871 | +       } | 
|---|
|  | 2872 | + | 
|---|
|  | 2873 | +    printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", FAN_DRIVER,FAN_DRIVER_VMAJ,FAN_DRIVER_VMIN); | 
|---|
|  | 2874 | + | 
|---|
|  | 2875 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 2876 | +#ifdef CONFIG_COBALT_OLDPROC | 
|---|
|  | 2877 | +       proc_faninfo = create_proc_entry("faninfo", S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, NULL); | 
|---|
|  | 2878 | +       if (!proc_faninfo) { | 
|---|
|  | 2879 | +               EPRINTK("can't create /proc/faninfo\n"); | 
|---|
|  | 2880 | +               return -ENOENT; | 
|---|
|  | 2881 | +       } | 
|---|
|  | 2882 | +       proc_faninfo->owner = THIS_MODULE; | 
|---|
|  | 2883 | +       proc_faninfo->read_proc = fan_read_proc; | 
|---|
|  | 2884 | +       proc_faninfo->write_proc = fan_write_proc; | 
|---|
|  | 2885 | +#endif /* CONFIG_COBALT_OLDPROC */ | 
|---|
|  | 2886 | +       proc_cfaninfo = create_proc_entry("faninfo", S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, proc_cobalt); | 
|---|
|  | 2887 | +       if (!proc_cfaninfo) { | 
|---|
|  | 2888 | +               EPRINTK("can't create /proc/cobalt/faninfo\n"); | 
|---|
|  | 2889 | +               return -ENOENT; | 
|---|
|  | 2890 | +       } | 
|---|
|  | 2891 | +       proc_cfaninfo->owner = THIS_MODULE; | 
|---|
|  | 2892 | +       proc_cfaninfo->read_proc = fan_read_proc; | 
|---|
|  | 2893 | +       proc_cfaninfo->write_proc = fan_write_proc; | 
|---|
|  | 2894 | +#endif /* CONFIG_PROC_FS */ | 
|---|
|  | 2895 | + | 
|---|
|  | 2896 | +       return 0; | 
|---|
|  | 2897 | +} | 
|---|
|  | 2898 | + | 
|---|
|  | 2899 | +static void __exit | 
|---|
|  | 2900 | +cobalt_fan_exit(void) | 
|---|
|  | 2901 | +{ | 
|---|
|  | 2902 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 2903 | +#ifdef CONFIG_COBALT_OLDPROC | 
|---|
|  | 2904 | +       if (proc_faninfo) { | 
|---|
|  | 2905 | +               remove_proc_entry("faninfo", NULL); | 
|---|
|  | 2906 | +       } | 
|---|
|  | 2907 | +#endif /* CONFIG_COBALT_OLDPROC */ | 
|---|
|  | 2908 | +       if (proc_cfaninfo) { | 
|---|
|  | 2909 | +               remove_proc_entry("faninfo", proc_cobalt); | 
|---|
|  | 2910 | +       } | 
|---|
|  | 2911 | +#endif /* CONFIG_PROC_FS */ | 
|---|
|  | 2912 | + | 
|---|
|  | 2913 | +       sys_fanlist = NULL; | 
|---|
|  | 2914 | +} | 
|---|
|  | 2915 | + | 
|---|
|  | 2916 | +/* | 
|---|
|  | 2917 | + * Samples fan tachometer square wave to calculate and report RPM | 
|---|
|  | 2918 | + */ | 
|---|
|  | 2919 | +static int | 
|---|
|  | 2920 | +get_faninfo(char *buffer) | 
|---|
|  | 2921 | +{ | 
|---|
|  | 2922 | +       struct fan_gpio *fg; | 
|---|
|  | 2923 | +       struct timeval utime; | 
|---|
|  | 2924 | +       unsigned long elapsed, start; | 
|---|
|  | 2925 | +       int i, val, len; | 
|---|
|  | 2926 | + | 
|---|
|  | 2927 | +       if (!sys_fanlist || !cobt_is_5k()) { | 
|---|
|  | 2928 | +               /* software is keyed off this string - do not change it ! */ | 
|---|
|  | 2929 | +               return sprintf(buffer, "Fan monitoring not supported.\n"); | 
|---|
|  | 2930 | +       } | 
|---|
|  | 2931 | + | 
|---|
|  | 2932 | +       /* save start timestamp */ | 
|---|
|  | 2933 | +       do_gettimeofday(&utime); | 
|---|
|  | 2934 | +       start = utime.tv_usec; | 
|---|
|  | 2935 | + | 
|---|
|  | 2936 | +       /* initialize 'previous' values. we do edge detection by | 
|---|
|  | 2937 | +        * looking for transitions from previous values */ | 
|---|
|  | 2938 | +       for (fg = sys_fanlist; fg->port >= 0; fg++) { | 
|---|
|  | 2939 | +               if (fg->tcache && utime.tv_sec < fg->tcache+FAN_CACHE_TIME) { | 
|---|
|  | 2940 | +                       return fan_info_print(buffer); | 
|---|
|  | 2941 | +               } | 
|---|
|  | 2942 | +               fg->tcache = utime.tv_sec; | 
|---|
|  | 2943 | +               fg->latch = inb(fg->base); | 
|---|
|  | 2944 | +               for (i = 0; i < FAN_GPIO_MAX; i++) { | 
|---|
|  | 2945 | +                       fg->fan[i].hcyl = 0; | 
|---|
|  | 2946 | +                       fg->fan[i].rpm = 0; | 
|---|
|  | 2947 | +               } | 
|---|
|  | 2948 | +       } | 
|---|
|  | 2949 | + | 
|---|
|  | 2950 | +       /* We are counting the number of halfcycles in a square wave | 
|---|
|  | 2951 | +        * that pass in a given amount of time to determine frequency */ | 
|---|
|  | 2952 | +       do { | 
|---|
|  | 2953 | +               for (fg=sys_fanlist; fg->port>=0; fg++) { | 
|---|
|  | 2954 | +                       val = inb(fg->base); | 
|---|
|  | 2955 | +                       for (i=0; i<FAN_GPIO_MAX; i++) { | 
|---|
|  | 2956 | +                               struct fan_info *p = &fg->fan[i]; | 
|---|
|  | 2957 | +                               if (FAN_VALID(p)) { | 
|---|
|  | 2958 | +                                       if ((val ^ fg->latch) & p->mask) { | 
|---|
|  | 2959 | +                                               p->hcyl++; | 
|---|
|  | 2960 | +                                       } | 
|---|
|  | 2961 | +                               } | 
|---|
|  | 2962 | +                       } | 
|---|
|  | 2963 | +                       fg->latch = val; | 
|---|
|  | 2964 | +               } | 
|---|
|  | 2965 | + | 
|---|
|  | 2966 | +               do_gettimeofday(&utime); | 
|---|
|  | 2967 | +               if (utime.tv_usec > start) { | 
|---|
|  | 2968 | +                       elapsed = utime.tv_usec - start; | 
|---|
|  | 2969 | +               } else { | 
|---|
|  | 2970 | +                       elapsed = utime.tv_usec + 1000001 - start; | 
|---|
|  | 2971 | +               } | 
|---|
|  | 2972 | + | 
|---|
|  | 2973 | +       } while (elapsed < (FAN_SAMPLE_LEN) * 1000); | 
|---|
|  | 2974 | + | 
|---|
|  | 2975 | +       /* Fan rpm = 60 / ( t * poles ) | 
|---|
|  | 2976 | +        *  where t is 1/2 the period and poles are the number of | 
|---|
|  | 2977 | +        *  magnetic poles for the fan. | 
|---|
|  | 2978 | +        * | 
|---|
|  | 2979 | +        * For the Sunon KDE1204PKBX fans on Raq XTR, poles = 4 | 
|---|
|  | 2980 | +        * So, in terms of cycles, | 
|---|
|  | 2981 | +        * | 
|---|
|  | 2982 | +        *  rpm = 60 s/m    halfcycles | 
|---|
|  | 2983 | +        *        ------ *  -------------- * 1,000,000 us/s * 2 | 
|---|
|  | 2984 | +        *        4         2 * elapsed us | 
|---|
|  | 2985 | +        * | 
|---|
|  | 2986 | +        *      = (60,000,000 / 4 poles) * halfcycles / elapsed | 
|---|
|  | 2987 | +        *      = 15,000,000 * halfcycles / elapsed | 
|---|
|  | 2988 | +        * | 
|---|
|  | 2989 | +        * Note, by this method and sampling for 50ms, our accuracy | 
|---|
|  | 2990 | +        *  is +/- 300 rpm.  The fans are spec'ed for +/- 1000 rpm | 
|---|
|  | 2991 | +        */ | 
|---|
|  | 2992 | +       for (val=len=0, fg=sys_fanlist; fg->port>=0; fg++) { | 
|---|
|  | 2993 | +               for (i=0; i<FAN_GPIO_MAX; i++) { | 
|---|
|  | 2994 | +                       struct fan_info *p = &fg->fan[i]; | 
|---|
|  | 2995 | +                       if (FAN_VALID(p)) { | 
|---|
|  | 2996 | +                               p->id = val++; | 
|---|
|  | 2997 | +                               p->rpm = FAN_RPM(fg->fan[i], elapsed); | 
|---|
|  | 2998 | +                               len += sprintf(buffer+len, "fan %d     : %u\n", | 
|---|
|  | 2999 | +                                       p->id, p->rpm); | 
|---|
|  | 3000 | +                       } | 
|---|
|  | 3001 | +               } | 
|---|
|  | 3002 | +       } | 
|---|
|  | 3003 | + | 
|---|
|  | 3004 | +       return len; | 
|---|
|  | 3005 | +} | 
|---|
|  | 3006 | + | 
|---|
|  | 3007 | +static int | 
|---|
|  | 3008 | +fan_info_print(char *buffer) | 
|---|
|  | 3009 | +{ | 
|---|
|  | 3010 | +       struct fan_gpio *fg; | 
|---|
|  | 3011 | +       int i, len=0; | 
|---|
|  | 3012 | + | 
|---|
|  | 3013 | +       if (!sys_fanlist) { | 
|---|
|  | 3014 | +               return -1; | 
|---|
|  | 3015 | +       } | 
|---|
|  | 3016 | + | 
|---|
|  | 3017 | +       for (fg=sys_fanlist; fg->port>=0; fg++) { | 
|---|
|  | 3018 | +               for (i=0; i<FAN_GPIO_MAX; i++) { | 
|---|
|  | 3019 | +                       struct fan_info *p = &fg->fan[i]; | 
|---|
|  | 3020 | +                       if (FAN_VALID(p)) { | 
|---|
|  | 3021 | +                               len += sprintf(buffer+len, "fan %d     : %u\n", | 
|---|
|  | 3022 | +                                       p->id, p->rpm); | 
|---|
|  | 3023 | +                       } | 
|---|
|  | 3024 | +               } | 
|---|
|  | 3025 | +       } | 
|---|
|  | 3026 | + | 
|---|
|  | 3027 | +       return len; | 
|---|
|  | 3028 | +} | 
|---|
|  | 3029 | + | 
|---|
|  | 3030 | +/* FIXME: generify */ | 
|---|
|  | 3031 | +static int | 
|---|
|  | 3032 | +fan_control(struct fan_info *fi, int todo) | 
|---|
|  | 3033 | +{ | 
|---|
|  | 3034 | +       if (fi && cobt_is_alpine()) { | 
|---|
|  | 3035 | +               switch (fi->id) { | 
|---|
|  | 3036 | +               case 4: { | 
|---|
|  | 3037 | +                       /* CPU FAN */ | 
|---|
|  | 3038 | +                       uint8_t gpdo = inb(GPIO_BASE+6); | 
|---|
|  | 3039 | + | 
|---|
|  | 3040 | +                       if (todo) { | 
|---|
|  | 3041 | +                               gpdo &= ~fi->mask; /* 0 = on */ | 
|---|
|  | 3042 | +                       } else { | 
|---|
|  | 3043 | +                               gpdo |= fi->mask;  /* 1 = off */ | 
|---|
|  | 3044 | +                       } | 
|---|
|  | 3045 | +                       outb(gpdo, GPIO_BASE+6); | 
|---|
|  | 3046 | +                       return 0; | 
|---|
|  | 3047 | +               } | 
|---|
|  | 3048 | +               default: | 
|---|
|  | 3049 | +                       return -ENODEV; | 
|---|
|  | 3050 | +               } | 
|---|
|  | 3051 | +       } | 
|---|
|  | 3052 | + | 
|---|
|  | 3053 | +       return -ENOSYS; | 
|---|
|  | 3054 | +} | 
|---|
|  | 3055 | + | 
|---|
|  | 3056 | +static struct fan_info * | 
|---|
|  | 3057 | +fan_info_find(int id) | 
|---|
|  | 3058 | +{ | 
|---|
|  | 3059 | +       struct fan_gpio *fg; | 
|---|
|  | 3060 | +       int i; | 
|---|
|  | 3061 | + | 
|---|
|  | 3062 | +       if (!sys_fanlist) { | 
|---|
|  | 3063 | +               return NULL; | 
|---|
|  | 3064 | +       } | 
|---|
|  | 3065 | + | 
|---|
|  | 3066 | +       for (fg=sys_fanlist; fg->port>=0; fg++) { | 
|---|
|  | 3067 | +               for (i=0; i<FAN_GPIO_MAX; i++) { | 
|---|
|  | 3068 | +                       if (FAN_VALID(&fg->fan[i])) { | 
|---|
|  | 3069 | +                               if (fg->fan[i].id == id) { | 
|---|
|  | 3070 | +                                       return &fg->fan[i]; | 
|---|
|  | 3071 | +                               } | 
|---|
|  | 3072 | +                       } | 
|---|
|  | 3073 | +               } | 
|---|
|  | 3074 | +       } | 
|---|
|  | 3075 | + | 
|---|
|  | 3076 | +       return NULL; | 
|---|
|  | 3077 | +} | 
|---|
|  | 3078 | + | 
|---|
|  | 3079 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 3080 | +static int | 
|---|
|  | 3081 | +fan_read_proc(char *buf, char **start, off_t pos, int len, int *eof, void *x) | 
|---|
|  | 3082 | +{ | 
|---|
|  | 3083 | +       int plen; | 
|---|
|  | 3084 | + | 
|---|
|  | 3085 | +       //MOD_INC_USE_COUNT; | 
|---|
|  | 3086 | + | 
|---|
|  | 3087 | +       spin_lock(&fan_lock); | 
|---|
|  | 3088 | +       plen = get_faninfo(buf); | 
|---|
|  | 3089 | +       spin_unlock(&fan_lock); | 
|---|
|  | 3090 | + | 
|---|
|  | 3091 | +       //MOD_DEC_USE_COUNT; | 
|---|
|  | 3092 | + | 
|---|
|  | 3093 | +       return cobalt_gen_proc_read(buf, plen, start, pos, len, eof); | 
|---|
|  | 3094 | +} | 
|---|
|  | 3095 | + | 
|---|
|  | 3096 | +static int | 
|---|
|  | 3097 | +fan_write_proc(struct file *file, const char *buf, unsigned long len, void *x) | 
|---|
|  | 3098 | +{ | 
|---|
|  | 3099 | +       char *page; | 
|---|
|  | 3100 | +       int retval = -EINVAL; | 
|---|
|  | 3101 | + | 
|---|
|  | 3102 | +       //MOD_INC_USE_COUNT; | 
|---|
|  | 3103 | + | 
|---|
|  | 3104 | +       if (len > PAGE_SIZE) { | 
|---|
|  | 3105 | +               //MOD_DEC_USE_COUNT; | 
|---|
|  | 3106 | +               return -EOVERFLOW; | 
|---|
|  | 3107 | +       } | 
|---|
|  | 3108 | + | 
|---|
|  | 3109 | +       page = (char *)__get_free_page(GFP_KERNEL); | 
|---|
|  | 3110 | +       if (!page) { | 
|---|
|  | 3111 | +               //MOD_DEC_USE_COUNT; | 
|---|
|  | 3112 | +               return -ENOMEM; | 
|---|
|  | 3113 | +       } | 
|---|
|  | 3114 | + | 
|---|
|  | 3115 | +       if (copy_from_user(page, buf, len)) { | 
|---|
|  | 3116 | +               free_page((unsigned long)page); | 
|---|
|  | 3117 | +               //MOD_DEC_USE_COUNT; | 
|---|
|  | 3118 | +               return -EFAULT; | 
|---|
|  | 3119 | +       } | 
|---|
|  | 3120 | +       page[len] = '\0'; | 
|---|
|  | 3121 | + | 
|---|
|  | 3122 | +       /* format: `fan ID COMMAND' */ | 
|---|
|  | 3123 | +       if (len>5 && !strncmp("fan ", page, 4)) { | 
|---|
|  | 3124 | +               if (*(page+4) != '\0') { | 
|---|
|  | 3125 | +                       struct fan_info *finf; | 
|---|
|  | 3126 | +                       char *nextpg = NULL; | 
|---|
|  | 3127 | + | 
|---|
|  | 3128 | +                       spin_lock(&fan_lock); | 
|---|
|  | 3129 | +                       finf = fan_info_find(simple_strtoul(page+4,&nextpg,0)); | 
|---|
|  | 3130 | +                       if (!finf) { | 
|---|
|  | 3131 | +                               retval = -ENOENT; | 
|---|
|  | 3132 | +                       } else if (nextpg != '\0') { | 
|---|
|  | 3133 | +                               if (!strncmp("on", nextpg+1, 2)) { | 
|---|
|  | 3134 | +                                       retval = fan_control(finf, 1); | 
|---|
|  | 3135 | +                               } | 
|---|
|  | 3136 | +                               else if (!strncmp("off", nextpg+1, 3)) { | 
|---|
|  | 3137 | +                                       retval = fan_control(finf, 0); | 
|---|
|  | 3138 | +                               } | 
|---|
|  | 3139 | +                       } | 
|---|
|  | 3140 | +                       spin_unlock(&fan_lock); | 
|---|
|  | 3141 | +               } | 
|---|
|  | 3142 | +       } | 
|---|
|  | 3143 | + | 
|---|
|  | 3144 | +       free_page((unsigned long)page); | 
|---|
|  | 3145 | +       //MOD_DEC_USE_COUNT; | 
|---|
|  | 3146 | + | 
|---|
|  | 3147 | +       return (retval < 0) ? retval : len; | 
|---|
|  | 3148 | +} | 
|---|
|  | 3149 | +#endif /* CONFIG_PROC_FS */ | 
|---|
|  | 3150 | + | 
|---|
|  | 3151 | +#if defined(CONFIG_COBALT_FANS_MODULE) | 
|---|
|  | 3152 | +module_init(cobalt_fan_init); | 
|---|
|  | 3153 | +module_exit(cobalt_fan_exit); | 
|---|
|  | 3154 | + | 
|---|
|  | 3155 | +MODULE_AUTHOR("Sun Cobalt"); | 
|---|
|  | 3156 | +MODULE_DESCRIPTION("Sun Cobalt fan tachometers"); | 
|---|
|  | 3157 | +#endif | 
|---|
|  | 3158 | + | 
|---|
|  | 3159 | +#endif /* CONFIG_COBALT_FANS || CONFIG_COBALT_FANS_MODULE */ | 
|---|
|  | 3160 | diff -Naur linux-2.6.20.orig/drivers/cobalt/i2c.c linux-2.6.20/drivers/cobalt/i2c.c | 
|---|
|  | 3161 | --- linux-2.6.20.orig/drivers/cobalt/i2c.c      1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 3162 | +++ linux-2.6.20/drivers/cobalt/i2c.c   2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 3163 | @@ -0,0 +1,519 @@ | 
|---|
|  | 3164 | +/* | 
|---|
|  | 3165 | + * $Id: i2c.c,v 1.19 2002/09/17 23:41:29 sparker Exp $ | 
|---|
|  | 3166 | + * i2c.c : Cobalt I2C driver support | 
|---|
|  | 3167 | + * | 
|---|
|  | 3168 | + * Copyright (C) 2000 Cobalt Networks, Inc. | 
|---|
|  | 3169 | + * Copyright (C) 2001 Sun Microsystems, Inc. | 
|---|
|  | 3170 | + * | 
|---|
|  | 3171 | + * Modified By: jeff@404ster.com | 
|---|
|  | 3172 | + * | 
|---|
|  | 3173 | + * This should be SMP safe.  All the exported functions lock on enter and | 
|---|
|  | 3174 | + * unlock on exit.  These exported functions may be called at interupt time, | 
|---|
|  | 3175 | + * so we have to use the IRQ safe locks.  NOTE: no function herein may call | 
|---|
|  | 3176 | + * any exported function herein. --TPH | 
|---|
|  | 3177 | + */ | 
|---|
|  | 3178 | +#include <stddef.h> | 
|---|
|  | 3179 | +#include <linux/init.h> | 
|---|
|  | 3180 | +#include <linux/types.h> | 
|---|
|  | 3181 | +#include <linux/config.h> | 
|---|
|  | 3182 | +#include <linux/pci.h> | 
|---|
|  | 3183 | +#include <linux/delay.h> | 
|---|
|  | 3184 | +#include <linux/module.h> | 
|---|
|  | 3185 | +#include <asm/io.h> | 
|---|
|  | 3186 | + | 
|---|
|  | 3187 | +#include <cobalt/cobalt.h> | 
|---|
|  | 3188 | +#include <cobalt/i2c.h> | 
|---|
|  | 3189 | +#include <cobalt/systype.h> | 
|---|
|  | 3190 | + | 
|---|
|  | 3191 | +#define I2C_3K_STATUS                  0x00 | 
|---|
|  | 3192 | +#define I2C_3K_CMD                     0x01 | 
|---|
|  | 3193 | +#define I2C_3K_START                   0x02 | 
|---|
|  | 3194 | +#define I2C_3K_ADDR                    0x03 | 
|---|
|  | 3195 | +#define I2C_3K_LOW_DATA                        0x04 | 
|---|
|  | 3196 | +#define I2C_3K_HIGH_DATA               0x05 | 
|---|
|  | 3197 | +#define I2C_3K_BLOCK_DATA              0x06 | 
|---|
|  | 3198 | +#define I2C_3K_INDEX                   0x07 | 
|---|
|  | 3199 | +#define I2C_3K_STATUS_IDLE             0x04 | 
|---|
|  | 3200 | +#define I2C_3K_CMD_RW_BYTE             0x20 | 
|---|
|  | 3201 | +#define I2C_3K_CMD_RW_WORD             0x30 | 
|---|
|  | 3202 | +#define I2C_3K_CMD_RW_BLOCK            0xC0 | 
|---|
|  | 3203 | +#define I2C_3K_CMD_RESET_PTR           0x80 | 
|---|
|  | 3204 | + | 
|---|
|  | 3205 | +#define I2C_5K_HOST_STATUS             0x00 | 
|---|
|  | 3206 | +#define I2C_5K_SLAVE_STATUS            0x01 | 
|---|
|  | 3207 | +#define I2C_5K_HOST_CONTROL            0x02 | 
|---|
|  | 3208 | +#define I2C_5K_HOST_COMMAND            0x03 | 
|---|
|  | 3209 | +#define I2C_5K_HOST_ADDR               0x04 | 
|---|
|  | 3210 | +#define I2C_5K_DATA_0                  0x05 | 
|---|
|  | 3211 | +#define I2C_5K_DATA_1                  0x06 | 
|---|
|  | 3212 | +#define I2C_5K_BLOCK_DATA              0x07 | 
|---|
|  | 3213 | +#define I2C_5K_SLAVE_CONTROL           0x08 | 
|---|
|  | 3214 | +#define I2C_5K_SHADOW_COMMAND          0x09 | 
|---|
|  | 3215 | +#define I2C_5K_SLAVE_EVENT             0x0a | 
|---|
|  | 3216 | +#define I2C_5K_SLAVE_DATA              0x0c | 
|---|
|  | 3217 | +#define I2C_5K_HOST_STATUS_BUSY                0x01 | 
|---|
|  | 3218 | +#define I2C_5K_HOST_CMD_START          0x40 | 
|---|
|  | 3219 | +#define I2C_5K_HOST_CMD_QUICK_RW       (0 << 2) | 
|---|
|  | 3220 | +#define I2C_5K_HOST_CMD_BYTE_RW                (1 << 2) | 
|---|
|  | 3221 | +#define I2C_5K_HOST_CMD_BYTE_DATA_RW   (2 << 2) | 
|---|
|  | 3222 | +#define I2C_5K_HOST_CMD_WORD_DATA_RW   (3 << 2) | 
|---|
|  | 3223 | +#define I2C_5K_HOST_CMD_BLOCK_DATA_RW  (5 << 2) | 
|---|
|  | 3224 | + | 
|---|
|  | 3225 | +#define I2C_WRITE                      0 | 
|---|
|  | 3226 | +#define I2C_READ                       1 | 
|---|
|  | 3227 | + | 
|---|
|  | 3228 | +/* this delay was determined empirically */ | 
|---|
|  | 3229 | +#define I2C_WRITE_UDELAY                1000 | 
|---|
|  | 3230 | + | 
|---|
|  | 3231 | +struct cobalt_i2c_data { | 
|---|
|  | 3232 | +       const unsigned char status; | 
|---|
|  | 3233 | +       const unsigned char addr; | 
|---|
|  | 3234 | +       const unsigned char index; | 
|---|
|  | 3235 | +       const unsigned char data_low; | 
|---|
|  | 3236 | +       const unsigned char data_high; | 
|---|
|  | 3237 | +       const unsigned char data_block; | 
|---|
|  | 3238 | +       const unsigned char rw_byte; | 
|---|
|  | 3239 | +       const unsigned char rw_word; | 
|---|
|  | 3240 | +       const unsigned char rw_block; | 
|---|
|  | 3241 | +       unsigned int io_port; | 
|---|
|  | 3242 | +}; | 
|---|
|  | 3243 | + | 
|---|
|  | 3244 | +struct cobalt_i2c_data cobalt_i2c_3k = { | 
|---|
|  | 3245 | +       I2C_3K_STATUS, | 
|---|
|  | 3246 | +       I2C_3K_ADDR, | 
|---|
|  | 3247 | +       I2C_3K_INDEX, | 
|---|
|  | 3248 | +       I2C_3K_LOW_DATA, | 
|---|
|  | 3249 | +       I2C_3K_HIGH_DATA, | 
|---|
|  | 3250 | +       I2C_3K_BLOCK_DATA, | 
|---|
|  | 3251 | +       I2C_3K_CMD_RW_BYTE, | 
|---|
|  | 3252 | +       I2C_3K_CMD_RW_WORD, | 
|---|
|  | 3253 | +       I2C_3K_CMD_RW_BLOCK, | 
|---|
|  | 3254 | +       0L | 
|---|
|  | 3255 | +}; | 
|---|
|  | 3256 | + | 
|---|
|  | 3257 | +struct cobalt_i2c_data cobalt_i2c_5k = { | 
|---|
|  | 3258 | +       I2C_5K_HOST_STATUS, | 
|---|
|  | 3259 | +       I2C_5K_HOST_ADDR, | 
|---|
|  | 3260 | +       I2C_5K_HOST_COMMAND, | 
|---|
|  | 3261 | +       I2C_5K_DATA_0, | 
|---|
|  | 3262 | +       I2C_5K_DATA_1, | 
|---|
|  | 3263 | +       I2C_5K_BLOCK_DATA, | 
|---|
|  | 3264 | +       I2C_5K_HOST_CMD_BYTE_DATA_RW, | 
|---|
|  | 3265 | +       I2C_5K_HOST_CMD_WORD_DATA_RW, | 
|---|
|  | 3266 | +       I2C_5K_HOST_CMD_BLOCK_DATA_RW, | 
|---|
|  | 3267 | +       0L | 
|---|
|  | 3268 | +}; | 
|---|
|  | 3269 | + | 
|---|
|  | 3270 | +/* a global pointer for our i2c data */ | 
|---|
|  | 3271 | +struct cobalt_i2c_data *i2c_data; | 
|---|
|  | 3272 | + | 
|---|
|  | 3273 | +#define I2C_REG(r)                     (i2c_data->io_port + i2c_data->r) | 
|---|
|  | 3274 | +#define I2C_CMD(c)                     (i2c_data->c) | 
|---|
|  | 3275 | + | 
|---|
|  | 3276 | +#define I2C_LOCK       (1 << 0) | 
|---|
|  | 3277 | +#define I2C_DEAD       (1 << 1) | 
|---|
|  | 3278 | +static unsigned long i2c_state; | 
|---|
|  | 3279 | + | 
|---|
|  | 3280 | +static int initialized; | 
|---|
|  | 3281 | + | 
|---|
|  | 3282 | +static inline int | 
|---|
|  | 3283 | +do_i2c_lock(void) | 
|---|
|  | 3284 | +{ | 
|---|
|  | 3285 | +       int i = 0; | 
|---|
|  | 3286 | + | 
|---|
|  | 3287 | +       if (test_bit(I2C_DEAD, &i2c_state)) | 
|---|
|  | 3288 | +               return -1; | 
|---|
|  | 3289 | + | 
|---|
|  | 3290 | +       while (test_and_set_bit(I2C_LOCK, &i2c_state)) { | 
|---|
|  | 3291 | +               if (i++ > 5) | 
|---|
|  | 3292 | +                       return -1; | 
|---|
|  | 3293 | +               udelay(10); | 
|---|
|  | 3294 | +       } | 
|---|
|  | 3295 | +       udelay(1); | 
|---|
|  | 3296 | +       return 0; | 
|---|
|  | 3297 | +} | 
|---|
|  | 3298 | + | 
|---|
|  | 3299 | +static inline void | 
|---|
|  | 3300 | +do_i2c_unlock(void) | 
|---|
|  | 3301 | +{ | 
|---|
|  | 3302 | +       clear_bit(I2C_LOCK, &i2c_state); | 
|---|
|  | 3303 | +} | 
|---|
|  | 3304 | + | 
|---|
|  | 3305 | +/* do a little squelching */ | 
|---|
|  | 3306 | +#define NOISE_RATE (5*HZ) | 
|---|
|  | 3307 | +static int | 
|---|
|  | 3308 | +i2c_noisy(void) | 
|---|
|  | 3309 | +{ | 
|---|
|  | 3310 | +       static unsigned long last_time; | 
|---|
|  | 3311 | +       static unsigned int messages; | 
|---|
|  | 3312 | + | 
|---|
|  | 3313 | +       if ((long) (jiffies - last_time) > NOISE_RATE) { | 
|---|
|  | 3314 | +               last_time = jiffies; | 
|---|
|  | 3315 | +               if (messages) { | 
|---|
|  | 3316 | +                       WPRINTK("skipped %u kernel messages\n", messages); | 
|---|
|  | 3317 | +                       messages = 0; | 
|---|
|  | 3318 | +               } | 
|---|
|  | 3319 | +               return 0; | 
|---|
|  | 3320 | +       } | 
|---|
|  | 3321 | +       messages++; | 
|---|
|  | 3322 | +       return 1; | 
|---|
|  | 3323 | +} | 
|---|
|  | 3324 | + | 
|---|
|  | 3325 | +static int | 
|---|
|  | 3326 | +i2c_wait_for_smi(void) | 
|---|
|  | 3327 | +{ | 
|---|
|  | 3328 | +       static unsigned int shutup = 0; | 
|---|
|  | 3329 | +       int timeout=10; | 
|---|
|  | 3330 | +       int status; | 
|---|
|  | 3331 | + | 
|---|
|  | 3332 | +       while (timeout--) { | 
|---|
|  | 3333 | +               udelay(100); /* wait */ | 
|---|
|  | 3334 | +               status = inb_p(I2C_REG(status)); | 
|---|
|  | 3335 | + | 
|---|
|  | 3336 | +               if (cobt_is_3k()) { | 
|---|
|  | 3337 | +                       if (status & I2C_3K_STATUS_IDLE) { | 
|---|
|  | 3338 | +                               return 0; | 
|---|
|  | 3339 | +                       } | 
|---|
|  | 3340 | +               } else if (cobt_is_5k()) { | 
|---|
|  | 3341 | +                       if (!(status & I2C_5K_HOST_STATUS_BUSY)) { | 
|---|
|  | 3342 | +                               return 0; | 
|---|
|  | 3343 | +                       } | 
|---|
|  | 3344 | +               } | 
|---|
|  | 3345 | +               outb_p(status, I2C_REG(status)); | 
|---|
|  | 3346 | +       } | 
|---|
|  | 3347 | + | 
|---|
|  | 3348 | +       /* still busy - complain */ | 
|---|
|  | 3349 | +       if (!i2c_noisy()) { | 
|---|
|  | 3350 | +               if (++shutup > 2) { | 
|---|
|  | 3351 | +                       EPRINTK("i2c seems to be dead - sorry\n"); | 
|---|
|  | 3352 | +                       set_bit(I2C_DEAD, &i2c_state); | 
|---|
|  | 3353 | +               } else { | 
|---|
|  | 3354 | +                       WPRINTK("i2c timeout: status busy (0x%x), resetting\n", | 
|---|
|  | 3355 | +                               status); | 
|---|
|  | 3356 | +               } | 
|---|
|  | 3357 | +       } | 
|---|
|  | 3358 | + | 
|---|
|  | 3359 | +       /* punch the abort bit */ | 
|---|
|  | 3360 | +       if (cobt_is_3k()) { | 
|---|
|  | 3361 | +               outb_p(4, i2c_data->io_port + I2C_3K_CMD); | 
|---|
|  | 3362 | +       } else if (cobt_is_5k()) { | 
|---|
|  | 3363 | +               outb_p(2, i2c_data->io_port + I2C_5K_HOST_CONTROL); | 
|---|
|  | 3364 | +               outb_p(1, i2c_data->io_port + I2C_5K_HOST_CONTROL); | 
|---|
|  | 3365 | +       } | 
|---|
|  | 3366 | + | 
|---|
|  | 3367 | +       return -1; | 
|---|
|  | 3368 | +} | 
|---|
|  | 3369 | + | 
|---|
|  | 3370 | +static inline int | 
|---|
|  | 3371 | +i2c_setup(const int dev, const int index, const int r) | 
|---|
|  | 3372 | +{ | 
|---|
|  | 3373 | +       if (i2c_wait_for_smi() < 0) | 
|---|
|  | 3374 | +               return -1; | 
|---|
|  | 3375 | + | 
|---|
|  | 3376 | +       /* clear status */ | 
|---|
|  | 3377 | +       outb_p(0xff, I2C_REG(status)); | 
|---|
|  | 3378 | + | 
|---|
|  | 3379 | +       /* device address */ | 
|---|
|  | 3380 | +       outb_p((dev|r) & 0xff, I2C_REG(addr)); | 
|---|
|  | 3381 | + | 
|---|
|  | 3382 | +       /* I2C index */ | 
|---|
|  | 3383 | +       outb_p(index & 0xff, I2C_REG(index)); | 
|---|
|  | 3384 | + | 
|---|
|  | 3385 | +       return 0; | 
|---|
|  | 3386 | +} | 
|---|
|  | 3387 | + | 
|---|
|  | 3388 | +static inline int | 
|---|
|  | 3389 | +i2c_cmd(const unsigned char command) | 
|---|
|  | 3390 | +{ | 
|---|
|  | 3391 | +       if (cobt_is_3k()) { | 
|---|
|  | 3392 | +               outb_p(command, i2c_data->io_port + I2C_3K_CMD); | 
|---|
|  | 3393 | +               outb_p(0xff, i2c_data->io_port + I2C_3K_START); | 
|---|
|  | 3394 | +       } else if (cobt_is_5k()) { | 
|---|
|  | 3395 | +               outb_p(I2C_5K_HOST_CMD_START | command, | 
|---|
|  | 3396 | +                       i2c_data->io_port + I2C_5K_HOST_CONTROL); | 
|---|
|  | 3397 | +       } | 
|---|
|  | 3398 | + | 
|---|
|  | 3399 | +       if (i2c_wait_for_smi() < 0) | 
|---|
|  | 3400 | +               return -1; | 
|---|
|  | 3401 | + | 
|---|
|  | 3402 | +       return 0; | 
|---|
|  | 3403 | +} | 
|---|
|  | 3404 | + | 
|---|
|  | 3405 | +int | 
|---|
|  | 3406 | +cobalt_i2c_init(void) | 
|---|
|  | 3407 | +{ | 
|---|
|  | 3408 | +       struct pci_dev *i2cdev = NULL; | 
|---|
|  | 3409 | + | 
|---|
|  | 3410 | +        if( ! initialized ) { | 
|---|
|  | 3411 | +               if (cobt_is_3k()) { | 
|---|
|  | 3412 | +                       i2c_data = &cobalt_i2c_3k; | 
|---|
|  | 3413 | +                       i2cdev = pci_find_device(PCI_VENDOR_ID_AL, | 
|---|
|  | 3414 | +                               PCI_DEVICE_ID_AL_M7101, NULL); | 
|---|
|  | 3415 | +                       if (!i2cdev) { | 
|---|
|  | 3416 | +                               EPRINTK("can't find PMU for i2c access\n"); | 
|---|
|  | 3417 | +                               return -1; | 
|---|
|  | 3418 | +                       } | 
|---|
|  | 3419 | +                       pci_read_config_dword(i2cdev, 0x14, &i2c_data->io_port); | 
|---|
|  | 3420 | +               } else if (cobt_is_5k()) { | 
|---|
|  | 3421 | +                       i2c_data = &cobalt_i2c_5k; | 
|---|
|  | 3422 | +                       i2cdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, | 
|---|
|  | 3423 | +                               PCI_DEVICE_ID_SERVERWORKS_OSB4, i2cdev); | 
|---|
|  | 3424 | +                       if (!i2cdev) { | 
|---|
|  | 3425 | +                           i2cdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, | 
|---|
|  | 3426 | +                           PCI_DEVICE_ID_SERVERWORKS_CSB5, i2cdev); | 
|---|
|  | 3427 | +                           if (!i2cdev) { | 
|---|
|  | 3428 | +                               EPRINTK("can't find OSB4 or CSB5 for i2c access\n"); | 
|---|
|  | 3429 | +                               return -1; | 
|---|
|  | 3430 | +                           } | 
|---|
|  | 3431 | +                       } | 
|---|
|  | 3432 | +                       pci_read_config_dword(i2cdev, 0x90, &i2c_data->io_port); | 
|---|
|  | 3433 | +               } | 
|---|
|  | 3434 | + | 
|---|
|  | 3435 | +               i2c_data->io_port &= 0xfff0; | 
|---|
|  | 3436 | +               if (!i2c_data->io_port) { | 
|---|
|  | 3437 | +                       EPRINTK("i2c IO port not found\n"); | 
|---|
|  | 3438 | +               } | 
|---|
|  | 3439 | +               initialized = 1; | 
|---|
|  | 3440 | +       } | 
|---|
|  | 3441 | + | 
|---|
|  | 3442 | +       return 0; | 
|---|
|  | 3443 | +} | 
|---|
|  | 3444 | + | 
|---|
|  | 3445 | +int | 
|---|
|  | 3446 | +cobalt_i2c_reset(void) | 
|---|
|  | 3447 | +{ | 
|---|
|  | 3448 | +       int r; | 
|---|
|  | 3449 | + | 
|---|
|  | 3450 | +       if( !initialized ) { | 
|---|
|  | 3451 | +               if( cobalt_i2c_init() < 0 ) | 
|---|
|  | 3452 | +                       return -1; | 
|---|
|  | 3453 | +       } | 
|---|
|  | 3454 | + | 
|---|
|  | 3455 | +               if (do_i2c_lock() < 0) | 
|---|
|  | 3456 | +               return -1; | 
|---|
|  | 3457 | + | 
|---|
|  | 3458 | +       if (cobt_is_3k()) { | 
|---|
|  | 3459 | +               /* clear status */ | 
|---|
|  | 3460 | +               outb_p(0xff, i2c_data->io_port + I2C_3K_STATUS); | 
|---|
|  | 3461 | +               /* reset SMB devs */ | 
|---|
|  | 3462 | +               outb_p(0x08, i2c_data->io_port + I2C_3K_CMD); | 
|---|
|  | 3463 | +               /* start command */ | 
|---|
|  | 3464 | +               outb_p(0xff, i2c_data->io_port + I2C_3K_START); | 
|---|
|  | 3465 | +       } else if (cobt_is_5k()) { | 
|---|
|  | 3466 | +               /* clear status */ | 
|---|
|  | 3467 | +               outb_p(0x2, i2c_data->io_port + I2C_5K_HOST_CONTROL); | 
|---|
|  | 3468 | +               outb_p(0x1, i2c_data->io_port + I2C_5K_HOST_CONTROL); | 
|---|
|  | 3469 | +               outb_p(0xff, i2c_data->io_port + I2C_5K_HOST_STATUS); | 
|---|
|  | 3470 | +               outb_p(I2C_5K_HOST_CMD_START | 0x08, | 
|---|
|  | 3471 | +                       i2c_data->io_port + I2C_5K_HOST_CONTROL); | 
|---|
|  | 3472 | +       } | 
|---|
|  | 3473 | + | 
|---|
|  | 3474 | +       r = i2c_wait_for_smi(); | 
|---|
|  | 3475 | + | 
|---|
|  | 3476 | +       do_i2c_unlock(); | 
|---|
|  | 3477 | + | 
|---|
|  | 3478 | +       return r; | 
|---|
|  | 3479 | +} | 
|---|
|  | 3480 | + | 
|---|
|  | 3481 | +int | 
|---|
|  | 3482 | +cobalt_i2c_read_byte(const int dev, const int index) | 
|---|
|  | 3483 | +{ | 
|---|
|  | 3484 | +       int val = 0; | 
|---|
|  | 3485 | + | 
|---|
|  | 3486 | +       if( !initialized ) { | 
|---|
|  | 3487 | +               if( cobalt_i2c_init() < 0 ) | 
|---|
|  | 3488 | +                       return -1; | 
|---|
|  | 3489 | +       } | 
|---|
|  | 3490 | + | 
|---|
|  | 3491 | +       if (do_i2c_lock() < 0) | 
|---|
|  | 3492 | +               return -1; | 
|---|
|  | 3493 | + | 
|---|
|  | 3494 | +       if (i2c_setup(dev, index, I2C_READ) < 0 | 
|---|
|  | 3495 | +        || i2c_cmd(I2C_CMD(rw_byte)) < 0) { | 
|---|
|  | 3496 | +               val = -1; | 
|---|
|  | 3497 | +       } | 
|---|
|  | 3498 | + | 
|---|
|  | 3499 | +       if (val == 0) { | 
|---|
|  | 3500 | +               val = inb_p(I2C_REG(data_low)); | 
|---|
|  | 3501 | +       } | 
|---|
|  | 3502 | + | 
|---|
|  | 3503 | +       do_i2c_unlock(); | 
|---|
|  | 3504 | + | 
|---|
|  | 3505 | +       return val; | 
|---|
|  | 3506 | +} | 
|---|
|  | 3507 | + | 
|---|
|  | 3508 | +int | 
|---|
|  | 3509 | +cobalt_i2c_read_word(const int dev, const int index) | 
|---|
|  | 3510 | +{ | 
|---|
|  | 3511 | +       int val = 0; | 
|---|
|  | 3512 | + | 
|---|
|  | 3513 | +       if( !initialized ) { | 
|---|
|  | 3514 | +               if( cobalt_i2c_init() < 0 ) | 
|---|
|  | 3515 | +                       return -1; | 
|---|
|  | 3516 | +       } | 
|---|
|  | 3517 | + | 
|---|
|  | 3518 | +       if (do_i2c_lock() < 0) | 
|---|
|  | 3519 | +               return -1; | 
|---|
|  | 3520 | + | 
|---|
|  | 3521 | +       if (i2c_setup(dev, index, I2C_READ) < 0 | 
|---|
|  | 3522 | +        || i2c_cmd(I2C_CMD(rw_word)) < 0) { | 
|---|
|  | 3523 | +               val = -1; | 
|---|
|  | 3524 | +       } | 
|---|
|  | 3525 | + | 
|---|
|  | 3526 | +       if (val == 0) { | 
|---|
|  | 3527 | +               val = inb_p(I2C_REG(data_low)); | 
|---|
|  | 3528 | +               val += inb_p(I2C_REG(data_high)) << 8; | 
|---|
|  | 3529 | +       } | 
|---|
|  | 3530 | + | 
|---|
|  | 3531 | +       do_i2c_unlock(); | 
|---|
|  | 3532 | + | 
|---|
|  | 3533 | +       return val; | 
|---|
|  | 3534 | +} | 
|---|
|  | 3535 | + | 
|---|
|  | 3536 | +int | 
|---|
|  | 3537 | +cobalt_i2c_read_block(const int dev, const int index, | 
|---|
|  | 3538 | +       unsigned char *data, int count) | 
|---|
|  | 3539 | +{ | 
|---|
|  | 3540 | +       if( !initialized ) { | 
|---|
|  | 3541 | +               if( cobalt_i2c_init() < 0 ) | 
|---|
|  | 3542 | +                       return -1; | 
|---|
|  | 3543 | +       } | 
|---|
|  | 3544 | + | 
|---|
|  | 3545 | +       if (do_i2c_lock() < 0) | 
|---|
|  | 3546 | +               return -1; | 
|---|
|  | 3547 | + | 
|---|
|  | 3548 | +       if (i2c_setup(dev, index, I2C_READ) < 0) { | 
|---|
|  | 3549 | +               do_i2c_unlock(); | 
|---|
|  | 3550 | +               return -1; | 
|---|
|  | 3551 | +       } | 
|---|
|  | 3552 | + | 
|---|
|  | 3553 | +       outb_p(count & 0xff, I2C_REG(data_low)); | 
|---|
|  | 3554 | +       outb_p(count & 0xff, I2C_REG(data_high)); | 
|---|
|  | 3555 | + | 
|---|
|  | 3556 | +       if (i2c_cmd(I2C_CMD(rw_block)) < 0) { | 
|---|
|  | 3557 | +               do_i2c_unlock(); | 
|---|
|  | 3558 | +               return -1; | 
|---|
|  | 3559 | +       } | 
|---|
|  | 3560 | + | 
|---|
|  | 3561 | +       while (count) { | 
|---|
|  | 3562 | +               /* read a byte of block data */ | 
|---|
|  | 3563 | +               *data = inb_p(I2C_REG(data_block)); | 
|---|
|  | 3564 | +               data++; | 
|---|
|  | 3565 | +               count--; | 
|---|
|  | 3566 | +       } | 
|---|
|  | 3567 | + | 
|---|
|  | 3568 | +       do_i2c_unlock(); | 
|---|
|  | 3569 | + | 
|---|
|  | 3570 | +       return 0; | 
|---|
|  | 3571 | +} | 
|---|
|  | 3572 | + | 
|---|
|  | 3573 | +int | 
|---|
|  | 3574 | +cobalt_i2c_write_byte(const int dev, const int index, const u8 val) | 
|---|
|  | 3575 | +{ | 
|---|
|  | 3576 | +       int r = 0; | 
|---|
|  | 3577 | + | 
|---|
|  | 3578 | +       if( !initialized ) { | 
|---|
|  | 3579 | +               if( cobalt_i2c_init() < 0 ) | 
|---|
|  | 3580 | +                       return -1; | 
|---|
|  | 3581 | +       } | 
|---|
|  | 3582 | + | 
|---|
|  | 3583 | +       if (do_i2c_lock() < 0) | 
|---|
|  | 3584 | +               return -1; | 
|---|
|  | 3585 | + | 
|---|
|  | 3586 | +       if (i2c_setup(dev, index, I2C_WRITE) < 0) { | 
|---|
|  | 3587 | +               r = -1; | 
|---|
|  | 3588 | +       } | 
|---|
|  | 3589 | + | 
|---|
|  | 3590 | +       if (r == 0) { | 
|---|
|  | 3591 | +               outb_p(val & 0xff, I2C_REG(data_low)); | 
|---|
|  | 3592 | + | 
|---|
|  | 3593 | +               if (i2c_cmd(I2C_CMD(rw_byte)) < 0) { | 
|---|
|  | 3594 | +                       r = -1; | 
|---|
|  | 3595 | +               } | 
|---|
|  | 3596 | +       } | 
|---|
|  | 3597 | + | 
|---|
|  | 3598 | +       udelay(I2C_WRITE_UDELAY); | 
|---|
|  | 3599 | + | 
|---|
|  | 3600 | +       do_i2c_unlock(); | 
|---|
|  | 3601 | + | 
|---|
|  | 3602 | +       return r; | 
|---|
|  | 3603 | +} | 
|---|
|  | 3604 | + | 
|---|
|  | 3605 | +int | 
|---|
|  | 3606 | +cobalt_i2c_write_word(const int dev, const int index, const u16 val) | 
|---|
|  | 3607 | +{ | 
|---|
|  | 3608 | +       int r = 0; | 
|---|
|  | 3609 | + | 
|---|
|  | 3610 | +       if( !initialized ) { | 
|---|
|  | 3611 | +               if( cobalt_i2c_init() < 0 ) | 
|---|
|  | 3612 | +                       return -1; | 
|---|
|  | 3613 | +       } | 
|---|
|  | 3614 | + | 
|---|
|  | 3615 | +       if (do_i2c_lock() < 0) | 
|---|
|  | 3616 | +               return -1; | 
|---|
|  | 3617 | + | 
|---|
|  | 3618 | +       if (i2c_setup(dev, index, I2C_WRITE) < 0) { | 
|---|
|  | 3619 | +               r = -1; | 
|---|
|  | 3620 | +       } | 
|---|
|  | 3621 | + | 
|---|
|  | 3622 | +       if (r == 0) { | 
|---|
|  | 3623 | +               outb_p(val & 0xff, I2C_REG(data_low)); | 
|---|
|  | 3624 | +               outb_p((val >> 8) & 0xff, I2C_REG(data_high)); | 
|---|
|  | 3625 | + | 
|---|
|  | 3626 | +               if (i2c_cmd(I2C_CMD(rw_word)) < 0) { | 
|---|
|  | 3627 | +                       r = -1; | 
|---|
|  | 3628 | +               } | 
|---|
|  | 3629 | +       } | 
|---|
|  | 3630 | + | 
|---|
|  | 3631 | +       udelay(I2C_WRITE_UDELAY); | 
|---|
|  | 3632 | + | 
|---|
|  | 3633 | +       do_i2c_unlock(); | 
|---|
|  | 3634 | + | 
|---|
|  | 3635 | +       return r; | 
|---|
|  | 3636 | +} | 
|---|
|  | 3637 | + | 
|---|
|  | 3638 | +int | 
|---|
|  | 3639 | +cobalt_i2c_write_block(int dev, int index, unsigned char *data, int count) | 
|---|
|  | 3640 | +{ | 
|---|
|  | 3641 | +       if( !initialized ) { | 
|---|
|  | 3642 | +               if( cobalt_i2c_init() < 0 ) | 
|---|
|  | 3643 | +                       return -1; | 
|---|
|  | 3644 | +       } | 
|---|
|  | 3645 | + | 
|---|
|  | 3646 | +       if (do_i2c_lock() < 0) | 
|---|
|  | 3647 | +               return -1; | 
|---|
|  | 3648 | + | 
|---|
|  | 3649 | +       if (i2c_setup(dev, index, I2C_WRITE) < 0) { | 
|---|
|  | 3650 | +               do_i2c_unlock(); | 
|---|
|  | 3651 | +               return -1; | 
|---|
|  | 3652 | +       } | 
|---|
|  | 3653 | + | 
|---|
|  | 3654 | +       outb_p(count & 0xff, I2C_REG(data_low)); | 
|---|
|  | 3655 | +       outb_p(count & 0xff, I2C_REG(data_high)); | 
|---|
|  | 3656 | + | 
|---|
|  | 3657 | +       if (i2c_cmd(I2C_CMD(rw_block)) < 0) { | 
|---|
|  | 3658 | +               do_i2c_unlock(); | 
|---|
|  | 3659 | +               return -1; | 
|---|
|  | 3660 | +       } | 
|---|
|  | 3661 | + | 
|---|
|  | 3662 | +       while (count) { | 
|---|
|  | 3663 | +               /* write a byte of block data */ | 
|---|
|  | 3664 | +               outb_p(*data, I2C_REG(data_block)); | 
|---|
|  | 3665 | +               data++; | 
|---|
|  | 3666 | +               count--; | 
|---|
|  | 3667 | +       } | 
|---|
|  | 3668 | + | 
|---|
|  | 3669 | +       udelay(I2C_WRITE_UDELAY); | 
|---|
|  | 3670 | + | 
|---|
|  | 3671 | +       do_i2c_unlock(); | 
|---|
|  | 3672 | + | 
|---|
|  | 3673 | +       return 0; | 
|---|
|  | 3674 | +} | 
|---|
|  | 3675 | + | 
|---|
|  | 3676 | +EXPORT_SYMBOL(cobalt_i2c_reset); | 
|---|
|  | 3677 | +EXPORT_SYMBOL(cobalt_i2c_read_byte); | 
|---|
|  | 3678 | +EXPORT_SYMBOL(cobalt_i2c_read_word); | 
|---|
|  | 3679 | +EXPORT_SYMBOL(cobalt_i2c_read_block); | 
|---|
|  | 3680 | +EXPORT_SYMBOL(cobalt_i2c_write_byte); | 
|---|
|  | 3681 | +EXPORT_SYMBOL(cobalt_i2c_write_word); | 
|---|
|  | 3682 | +EXPORT_SYMBOL(cobalt_i2c_write_block); | 
|---|
|  | 3683 | diff -Naur linux-2.6.20.orig/drivers/cobalt/init.c linux-2.6.20/drivers/cobalt/init.c | 
|---|
|  | 3684 | --- linux-2.6.20.orig/drivers/cobalt/init.c     1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 3685 | +++ linux-2.6.20/drivers/cobalt/init.c  2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 3686 | @@ -0,0 +1,114 @@ | 
|---|
|  | 3687 | +/* $Id: init.c,v 1.22 2002/11/04 17:54:15 thockin Exp $ */ | 
|---|
|  | 3688 | +/* | 
|---|
|  | 3689 | + *   Copyright (c) 2001  Sun Microsystems | 
|---|
|  | 3690 | + *   Generic initialization, to reduce pollution of other files | 
|---|
|  | 3691 | + */ | 
|---|
|  | 3692 | +#include <linux/config.h> | 
|---|
|  | 3693 | +#include <linux/module.h> | 
|---|
|  | 3694 | +#include <linux/stddef.h> | 
|---|
|  | 3695 | +#include <linux/version.h> | 
|---|
|  | 3696 | +#include <linux/types.h> | 
|---|
|  | 3697 | +#include <linux/init.h> | 
|---|
|  | 3698 | +#include <linux/proc_fs.h> | 
|---|
|  | 3699 | +#include <cobalt/cobalt.h> | 
|---|
|  | 3700 | + | 
|---|
|  | 3701 | +static int cobalt_proc_init(void); | 
|---|
|  | 3702 | +extern int cobalt_i2c_init(void); | 
|---|
|  | 3703 | +extern int cobalt_net_init(void); | 
|---|
|  | 3704 | +extern int cobalt_systype_init(void); | 
|---|
|  | 3705 | +extern void cobalt_boardrev_init(void); | 
|---|
|  | 3706 | +extern int cobalt_led_init(void); | 
|---|
|  | 3707 | +extern int cobalt_lcd_init(void); | 
|---|
|  | 3708 | +extern int cobalt_serialnum_init(void); | 
|---|
|  | 3709 | +extern int cobalt_wdt_init(void); | 
|---|
|  | 3710 | +extern int cobalt_sensors_init(void); | 
|---|
|  | 3711 | +extern int cobalt_fan_init(void); | 
|---|
|  | 3712 | +extern int cobalt_acpi_init(void); | 
|---|
|  | 3713 | +extern int cobalt_ruler_init(void); | 
|---|
|  | 3714 | +extern int cobalt_raminfo_init(void); | 
|---|
|  | 3715 | + | 
|---|
|  | 3716 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 3717 | +struct proc_dir_entry *proc_cobalt; | 
|---|
|  | 3718 | +EXPORT_SYMBOL(proc_cobalt); | 
|---|
|  | 3719 | +#endif | 
|---|
|  | 3720 | +spinlock_t cobalt_superio_lock = SPIN_LOCK_UNLOCKED; | 
|---|
|  | 3721 | + | 
|---|
|  | 3722 | +/* initialize all the cobalt specific stuff */ | 
|---|
|  | 3723 | +int __init | 
|---|
|  | 3724 | +cobalt_init(void) | 
|---|
|  | 3725 | +{ | 
|---|
|  | 3726 | +    cobalt_proc_init(); | 
|---|
|  | 3727 | +    cobalt_systype_init(); | 
|---|
|  | 3728 | +#ifdef CONFIG_COBALT_RAQ | 
|---|
|  | 3729 | +    /* we might keep the boardrev on an i2c chip */ | 
|---|
|  | 3730 | +    cobalt_i2c_init(); | 
|---|
|  | 3731 | +#endif | 
|---|
|  | 3732 | +    cobalt_boardrev_init(); | 
|---|
|  | 3733 | +#ifdef CONFIG_COBALT_ACPI | 
|---|
|  | 3734 | +    cobalt_acpi_init(); | 
|---|
|  | 3735 | +#endif | 
|---|
|  | 3736 | +#ifdef CONFIG_COBALT_LED | 
|---|
|  | 3737 | +    cobalt_net_init(); | 
|---|
|  | 3738 | +    cobalt_led_init(); | 
|---|
|  | 3739 | +#endif | 
|---|
|  | 3740 | +#ifdef CONFIG_COBALT_LCD | 
|---|
|  | 3741 | +    cobalt_lcd_init(); | 
|---|
|  | 3742 | +#endif | 
|---|
|  | 3743 | +#ifdef CONFIG_COBALT_RULER | 
|---|
|  | 3744 | +    cobalt_ruler_init(); | 
|---|
|  | 3745 | +#endif | 
|---|
|  | 3746 | +#ifdef CONFIG_COBALT_SERNUM | 
|---|
|  | 3747 | +    cobalt_serialnum_init(); | 
|---|
|  | 3748 | +#endif | 
|---|
|  | 3749 | +#ifdef CONFIG_COBALT_RAQ | 
|---|
|  | 3750 | +    /* some systems use WDT it for reboot */ | 
|---|
|  | 3751 | +    cobalt_wdt_init(); | 
|---|
|  | 3752 | +#endif | 
|---|
|  | 3753 | +#ifdef CONFIG_COBALT_SENSORS | 
|---|
|  | 3754 | +    cobalt_sensors_init(); | 
|---|
|  | 3755 | +#endif | 
|---|
|  | 3756 | +#ifdef CONFIG_COBALT_FANS | 
|---|
|  | 3757 | +    cobalt_fan_init(); | 
|---|
|  | 3758 | +#endif | 
|---|
|  | 3759 | +#ifdef CONFIG_COBALT_RAMINFO | 
|---|
|  | 3760 | +    cobalt_raminfo_init(); | 
|---|
|  | 3761 | +#endif | 
|---|
|  | 3762 | +    return 0; | 
|---|
|  | 3763 | +} | 
|---|
|  | 3764 | + | 
|---|
|  | 3765 | +static int __init | 
|---|
|  | 3766 | +cobalt_proc_init(void) | 
|---|
|  | 3767 | +{ | 
|---|
|  | 3768 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 3769 | +       proc_cobalt = proc_mkdir("cobalt", 0); | 
|---|
|  | 3770 | +       if (!proc_cobalt) { | 
|---|
|  | 3771 | +               EPRINTK("can't create /proc/cobalt\n"); | 
|---|
|  | 3772 | +               return -1; | 
|---|
|  | 3773 | +       } | 
|---|
|  | 3774 | +#endif | 
|---|
|  | 3775 | + | 
|---|
|  | 3776 | +       return 0; | 
|---|
|  | 3777 | +} | 
|---|
|  | 3778 | + | 
|---|
|  | 3779 | +/* a function that handles the blah stuff in a simple proc read function */ | 
|---|
|  | 3780 | +int | 
|---|
|  | 3781 | +cobalt_gen_proc_read(char *buf, int plen, char **start, off_t pos, | 
|---|
|  | 3782 | +       int len, int *eof) | 
|---|
|  | 3783 | +{ | 
|---|
|  | 3784 | +       /* trying to read a bad offset? */ | 
|---|
|  | 3785 | +       if (pos >= plen) { | 
|---|
|  | 3786 | +               *eof = 1; | 
|---|
|  | 3787 | +               return 0; | 
|---|
|  | 3788 | +       } | 
|---|
|  | 3789 | + | 
|---|
|  | 3790 | +       /* did we write everything we wanted to? */ | 
|---|
|  | 3791 | +       if (len >= (plen-pos)) { | 
|---|
|  | 3792 | +               *eof = 1; | 
|---|
|  | 3793 | +       } | 
|---|
|  | 3794 | + | 
|---|
|  | 3795 | +       *start = buf + pos; | 
|---|
|  | 3796 | +       plen -= pos; | 
|---|
|  | 3797 | + | 
|---|
|  | 3798 | +       return (len > plen) ? plen : len; | 
|---|
|  | 3799 | +} | 
|---|
|  | 3800 | +EXPORT_SYMBOL(cobalt_gen_proc_read); | 
|---|
|  | 3801 | diff -Naur linux-2.6.20.orig/drivers/cobalt/lcd.c linux-2.6.20/drivers/cobalt/lcd.c | 
|---|
|  | 3802 | --- linux-2.6.20.orig/drivers/cobalt/lcd.c      1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 3803 | +++ linux-2.6.20/drivers/cobalt/lcd.c   2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 3804 | @@ -0,0 +1,835 @@ | 
|---|
|  | 3805 | +/* | 
|---|
|  | 3806 | + * $Id: lcd.c,v 1.44 2002/05/10 18:44:45 duncan Exp $ | 
|---|
|  | 3807 | + * lcd.c : driver for Cobalt LCD/Buttons | 
|---|
|  | 3808 | + * | 
|---|
|  | 3809 | + * Copyright 1996-2000 Cobalt Networks, Inc. | 
|---|
|  | 3810 | + * Copyright 2001 Sun Microsystems, Inc. | 
|---|
|  | 3811 | + * | 
|---|
|  | 3812 | + * By: Andrew Bose | 
|---|
|  | 3813 | + *     Timothy Stonis | 
|---|
|  | 3814 | + *     Tim Hockin | 
|---|
|  | 3815 | + *     Adrian Sun | 
|---|
|  | 3816 | + *     Duncan Laurie | 
|---|
|  | 3817 | + * | 
|---|
|  | 3818 | + * Modified By: jeff@404ster.com | 
|---|
|  | 3819 | + * | 
|---|
|  | 3820 | + * This should be SMP safe. We're hardly performance critical, | 
|---|
|  | 3821 | + * so we lock around lcd_ioctl() and just where needed by other external | 
|---|
|  | 3822 | + * functions.  There is a static global waiters variable that is atomic_t, and | 
|---|
|  | 3823 | + * so should be safe. --TPH | 
|---|
|  | 3824 | + */ | 
|---|
|  | 3825 | + | 
|---|
|  | 3826 | +#include <linux/config.h> | 
|---|
|  | 3827 | + | 
|---|
|  | 3828 | +#ifdef CONFIG_COBALT_LCD | 
|---|
|  | 3829 | + | 
|---|
|  | 3830 | +#include <linux/module.h> | 
|---|
|  | 3831 | +#include <linux/types.h> | 
|---|
|  | 3832 | +#include <linux/errno.h> | 
|---|
|  | 3833 | +#include <linux/miscdevice.h> | 
|---|
|  | 3834 | +#include <linux/slab.h> | 
|---|
|  | 3835 | +#include <linux/ioport.h> | 
|---|
|  | 3836 | +#include <linux/fcntl.h> | 
|---|
|  | 3837 | +#include <linux/stat.h> | 
|---|
|  | 3838 | +#include <linux/netdevice.h> | 
|---|
|  | 3839 | +#include <linux/proc_fs.h> | 
|---|
|  | 3840 | +#include <linux/in6.h> | 
|---|
|  | 3841 | +#include <linux/pci.h> | 
|---|
|  | 3842 | +#include <linux/init.h> | 
|---|
|  | 3843 | +#include <linux/timer.h> | 
|---|
|  | 3844 | +#include <linux/kernel.h> | 
|---|
|  | 3845 | + | 
|---|
|  | 3846 | +#include <asm/io.h> | 
|---|
|  | 3847 | +#include <asm/segment.h> | 
|---|
|  | 3848 | +#include <asm/system.h> | 
|---|
|  | 3849 | +#include <asm/uaccess.h> | 
|---|
|  | 3850 | +#include <asm/checksum.h> | 
|---|
|  | 3851 | +#include <linux/delay.h> | 
|---|
|  | 3852 | + | 
|---|
|  | 3853 | +#include <cobalt/cobalt.h> | 
|---|
|  | 3854 | +#include <cobalt/systype.h> | 
|---|
|  | 3855 | +#include <cobalt/lcd.h> | 
|---|
|  | 3856 | +#include <cobalt/superio.h> | 
|---|
|  | 3857 | +#include <cobalt/i2c.h> | 
|---|
|  | 3858 | + | 
|---|
|  | 3859 | +#define TWIDDLE_HZ (HZ/10) | 
|---|
|  | 3860 | + | 
|---|
|  | 3861 | +#ifndef min | 
|---|
|  | 3862 | +#define min(a, b)  ((a) < (b) ? (a) : (b)) | 
|---|
|  | 3863 | +#endif | 
|---|
|  | 3864 | + | 
|---|
|  | 3865 | +#define LCD_DRIVER             "Cobalt Networks LCD driver" | 
|---|
|  | 3866 | +#define LCD_DRIVER_VMAJ                4 | 
|---|
|  | 3867 | +#define LCD_DRIVER_VMIN                0 | 
|---|
|  | 3868 | + | 
|---|
|  | 3869 | +/* io registers */ | 
|---|
|  | 3870 | +#define LPT                    0x0378 | 
|---|
|  | 3871 | +#define LCD_DATA_ADDRESS       LPT+0 | 
|---|
|  | 3872 | +#define LCD_CONTROL_ADDRESS    LPT+2 | 
|---|
|  | 3873 | + | 
|---|
|  | 3874 | +/* LCD device info */ | 
|---|
|  | 3875 | +#define LCD_Addr               0x80 | 
|---|
|  | 3876 | +#define DD_R00                 0x00 | 
|---|
|  | 3877 | +#define DD_R01                 0x27 | 
|---|
|  | 3878 | +#define DD_R10                 0x40 | 
|---|
|  | 3879 | +#define DD_R11                 0x67 | 
|---|
|  | 3880 | + | 
|---|
|  | 3881 | +/* driver functions */ | 
|---|
|  | 3882 | +static int cobalt_lcd_open(struct inode *, struct file *); | 
|---|
|  | 3883 | +static ssize_t cobalt_lcd_read(struct file *, char *, size_t, loff_t *); | 
|---|
|  | 3884 | +static int cobalt_lcd_read_proc(char *, char **, off_t, int, int *, void *); | 
|---|
|  | 3885 | +static char *cobalt_lcddev_read_line(int, char *); | 
|---|
|  | 3886 | +static int cobalt_lcd_ioctl(struct inode *, struct file *, | 
|---|
|  | 3887 | +       unsigned int, unsigned long); | 
|---|
|  | 3888 | +static int cobalt_lcd_panic(struct notifier_block *self, unsigned long, void *); | 
|---|
|  | 3889 | + | 
|---|
|  | 3890 | +/* globals used throughout */ | 
|---|
|  | 3891 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 3892 | +#ifdef CONFIG_COBALT_OLDPROC | 
|---|
|  | 3893 | +static struct proc_dir_entry *proc_lcd; | 
|---|
|  | 3894 | +#endif | 
|---|
|  | 3895 | +static struct proc_dir_entry *proc_clcd; | 
|---|
|  | 3896 | +#endif | 
|---|
|  | 3897 | +static int lcd_present; | 
|---|
|  | 3898 | +static int has_i2c_lcd; | 
|---|
|  | 3899 | +static spinlock_t lcd_lock = SPIN_LOCK_UNLOCKED; | 
|---|
|  | 3900 | + | 
|---|
|  | 3901 | +/* various file operations we support for this driver */ | 
|---|
|  | 3902 | +static struct file_operations lcd_fops = { | 
|---|
|  | 3903 | +       .read = cobalt_lcd_read, | 
|---|
|  | 3904 | +       .ioctl = cobalt_lcd_ioctl, | 
|---|
|  | 3905 | +       .open = cobalt_lcd_open, | 
|---|
|  | 3906 | +}; | 
|---|
|  | 3907 | + | 
|---|
|  | 3908 | +/* device structure */ | 
|---|
|  | 3909 | +static struct miscdevice lcd_dev = { | 
|---|
|  | 3910 | +       MISC_DYNAMIC_MINOR, | 
|---|
|  | 3911 | +       "lcd", | 
|---|
|  | 3912 | +       &lcd_fops | 
|---|
|  | 3913 | +}; | 
|---|
|  | 3914 | + | 
|---|
|  | 3915 | +static int disable_lcd; | 
|---|
|  | 3916 | +static int __init | 
|---|
|  | 3917 | +lcd_disable_setup(char *str) | 
|---|
|  | 3918 | +{ | 
|---|
|  | 3919 | +       disable_lcd = 1; | 
|---|
|  | 3920 | +       return 0; | 
|---|
|  | 3921 | +} | 
|---|
|  | 3922 | +__setup("nolcd", lcd_disable_setup); | 
|---|
|  | 3923 | + | 
|---|
|  | 3924 | +/* Read a control instruction from the LCD */ | 
|---|
|  | 3925 | +static inline int | 
|---|
|  | 3926 | +lcddev_read_inst(void) | 
|---|
|  | 3927 | +{ | 
|---|
|  | 3928 | +       int a = 0; | 
|---|
|  | 3929 | + | 
|---|
|  | 3930 | +       if (cobt_is_5k() && has_i2c_lcd) { | 
|---|
|  | 3931 | +               a = cobalt_i2c_read_byte( | 
|---|
|  | 3932 | +                       COBALT_I2C_DEV_LCD_INST | COBALT_I2C_READ, 0); | 
|---|
|  | 3933 | +       } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) { | 
|---|
|  | 3934 | +               outb(0x21, LCD_CONTROL_ADDRESS); /* RS=0, R/W=1, E=0 */ | 
|---|
|  | 3935 | +               outb(0x20, LCD_CONTROL_ADDRESS); /* RS=0, R/W=1, E=1 */ | 
|---|
|  | 3936 | +               a = inb(LCD_DATA_ADDRESS); | 
|---|
|  | 3937 | +               outb(0x21, LCD_CONTROL_ADDRESS); /* RS=0, R/W=1, E=0 */ | 
|---|
|  | 3938 | +               outb(0x01, LCD_CONTROL_ADDRESS); /* RS=0, R/W=1, E=0 */ | 
|---|
|  | 3939 | +       } | 
|---|
|  | 3940 | + | 
|---|
|  | 3941 | +       /* small delay */ | 
|---|
|  | 3942 | +       udelay(100); | 
|---|
|  | 3943 | + | 
|---|
|  | 3944 | +       return a; | 
|---|
|  | 3945 | +} | 
|---|
|  | 3946 | + | 
|---|
|  | 3947 | +#define LCD_MAX_POLL 10000 | 
|---|
|  | 3948 | +static inline void | 
|---|
|  | 3949 | +lcddev_poll_wait(void) | 
|---|
|  | 3950 | +{ | 
|---|
|  | 3951 | +       int i=0; | 
|---|
|  | 3952 | + | 
|---|
|  | 3953 | +       while (i++ < LCD_MAX_POLL) { | 
|---|
|  | 3954 | +               int r = lcddev_read_inst(); | 
|---|
|  | 3955 | +               if (r < 0 || !(r & 0x80)) | 
|---|
|  | 3956 | +                       break; | 
|---|
|  | 3957 | +       } | 
|---|
|  | 3958 | +} | 
|---|
|  | 3959 | + | 
|---|
|  | 3960 | +/* Write a control instruction to the LCD */ | 
|---|
|  | 3961 | +static inline void | 
|---|
|  | 3962 | +lcddev_write_inst(unsigned char data) | 
|---|
|  | 3963 | +{ | 
|---|
|  | 3964 | +       lcddev_poll_wait(); | 
|---|
|  | 3965 | + | 
|---|
|  | 3966 | +       if (cobt_is_5k() && has_i2c_lcd) { | 
|---|
|  | 3967 | +               cobalt_i2c_write_byte( | 
|---|
|  | 3968 | +                       COBALT_I2C_DEV_LCD_INST | COBALT_I2C_WRITE, 0, data); | 
|---|
|  | 3969 | +       } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) { | 
|---|
|  | 3970 | +               outb(0x03, LCD_CONTROL_ADDRESS); /* RS=0, R/W=0, E=0 */ | 
|---|
|  | 3971 | +               outb(data, LCD_DATA_ADDRESS); | 
|---|
|  | 3972 | +               outb(0x02, LCD_CONTROL_ADDRESS); /* RS=0, R/W=0, E=1 */ | 
|---|
|  | 3973 | +               outb(0x03, LCD_CONTROL_ADDRESS); /* RS=0, R/W=0, E=0 */ | 
|---|
|  | 3974 | +               outb(0x01, LCD_CONTROL_ADDRESS); /* RS=0, R/W=1, E=0 */ | 
|---|
|  | 3975 | +       } | 
|---|
|  | 3976 | + | 
|---|
|  | 3977 | +       /* small delay */ | 
|---|
|  | 3978 | +       udelay(100); | 
|---|
|  | 3979 | +} | 
|---|
|  | 3980 | + | 
|---|
|  | 3981 | +/* Write one byte of data to the LCD */ | 
|---|
|  | 3982 | +static inline void | 
|---|
|  | 3983 | +lcddev_write_data(unsigned char data) | 
|---|
|  | 3984 | +{ | 
|---|
|  | 3985 | +       lcddev_poll_wait(); | 
|---|
|  | 3986 | + | 
|---|
|  | 3987 | +       if (cobt_is_5k() && has_i2c_lcd) { | 
|---|
|  | 3988 | +               cobalt_i2c_write_byte( | 
|---|
|  | 3989 | +                       COBALT_I2C_DEV_LCD_DATA | COBALT_I2C_WRITE, 0, data); | 
|---|
|  | 3990 | +       } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) { | 
|---|
|  | 3991 | +               outb(0x07, LCD_CONTROL_ADDRESS); /* RS=1, R/W=0, E=0 */ | 
|---|
|  | 3992 | +               outb(data, LCD_DATA_ADDRESS); | 
|---|
|  | 3993 | +               outb(0x06, LCD_CONTROL_ADDRESS); /* RS=1, R/W=0, E=1 */ | 
|---|
|  | 3994 | +               outb(0x07, LCD_CONTROL_ADDRESS); /* RS=1, R/W=0, E=0 */ | 
|---|
|  | 3995 | +               outb(0x05, LCD_CONTROL_ADDRESS); /* RS=1, R/W=1, E=0 */ | 
|---|
|  | 3996 | +       } | 
|---|
|  | 3997 | +       /* small delay */ | 
|---|
|  | 3998 | +       udelay(100); | 
|---|
|  | 3999 | +} | 
|---|
|  | 4000 | + | 
|---|
|  | 4001 | +/* Read one byte of data from the LCD */ | 
|---|
|  | 4002 | +static inline unsigned char | 
|---|
|  | 4003 | +lcddev_read_data(void) | 
|---|
|  | 4004 | +{ | 
|---|
|  | 4005 | +       unsigned char a = 0; | 
|---|
|  | 4006 | + | 
|---|
|  | 4007 | +       lcddev_poll_wait(); | 
|---|
|  | 4008 | + | 
|---|
|  | 4009 | +       if (cobt_is_5k() && has_i2c_lcd) { | 
|---|
|  | 4010 | +               a = cobalt_i2c_read_byte( | 
|---|
|  | 4011 | +                       COBALT_I2C_DEV_LCD_DATA | COBALT_I2C_READ, 0); | 
|---|
|  | 4012 | +       } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) { | 
|---|
|  | 4013 | +               outb(0x25, LCD_CONTROL_ADDRESS); /* RS=1, R/W=1, E=0 */ | 
|---|
|  | 4014 | +               outb(0x24, LCD_CONTROL_ADDRESS); /* RS=1, R/W=1, E=1 */ | 
|---|
|  | 4015 | +               a = inb(LCD_DATA_ADDRESS); | 
|---|
|  | 4016 | +               outb(0x25, LCD_CONTROL_ADDRESS); /* RS=1, R/W=1, E=0 */ | 
|---|
|  | 4017 | +               outb(0x01, LCD_CONTROL_ADDRESS); /* RS=1, R/W=1, E=0 */ | 
|---|
|  | 4018 | +       } | 
|---|
|  | 4019 | + | 
|---|
|  | 4020 | +       /* small delay */ | 
|---|
|  | 4021 | +       udelay(100); | 
|---|
|  | 4022 | + | 
|---|
|  | 4023 | +       return a; | 
|---|
|  | 4024 | +} | 
|---|
|  | 4025 | + | 
|---|
|  | 4026 | +static inline void | 
|---|
|  | 4027 | +lcddev_init(void) | 
|---|
|  | 4028 | +{ | 
|---|
|  | 4029 | +       lcddev_write_inst(0x38); | 
|---|
|  | 4030 | +       lcddev_write_inst(0x38); | 
|---|
|  | 4031 | +       lcddev_write_inst(0x38); | 
|---|
|  | 4032 | +       lcddev_write_inst(0x06); | 
|---|
|  | 4033 | +       lcddev_write_inst(0x0c); | 
|---|
|  | 4034 | +} | 
|---|
|  | 4035 | + | 
|---|
|  | 4036 | +static inline char | 
|---|
|  | 4037 | +read_buttons(void) | 
|---|
|  | 4038 | +{ | 
|---|
|  | 4039 | +       char r = 0; | 
|---|
|  | 4040 | + | 
|---|
|  | 4041 | +       if (cobt_is_5k() && has_i2c_lcd) { | 
|---|
|  | 4042 | +               unsigned char inst; | 
|---|
|  | 4043 | +               inst = cobalt_i2c_read_byte(COBALT_I2C_DEV_FP_BUTTONS, 0); | 
|---|
|  | 4044 | +               switch (inst) { | 
|---|
|  | 4045 | +                       case 0x3e: r = BUTTON_Next_B; break; | 
|---|
|  | 4046 | +                       case 0x3d: r = BUTTON_Enter_B; break; | 
|---|
|  | 4047 | +                       case 0x1f: r = BUTTON_Left_B; break; | 
|---|
|  | 4048 | +                       case 0x3b: r = BUTTON_Right_B; break; | 
|---|
|  | 4049 | +                       case 0x2f: r = BUTTON_Up_B; break; | 
|---|
|  | 4050 | +                       case 0x37: r = BUTTON_Down_B; break; | 
|---|
|  | 4051 | +                       case 0x3f: | 
|---|
|  | 4052 | +                       default: r = BUTTON_NONE_B; | 
|---|
|  | 4053 | +               } | 
|---|
|  | 4054 | +       } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) { | 
|---|
|  | 4055 | +               outb(0x29, LCD_CONTROL_ADDRESS); /* Sel=0, Bi=1 */ | 
|---|
|  | 4056 | +               r = inb(LCD_DATA_ADDRESS) & BUTTON_MASK; | 
|---|
|  | 4057 | +       } | 
|---|
|  | 4058 | + | 
|---|
|  | 4059 | +       return r; | 
|---|
|  | 4060 | +} | 
|---|
|  | 4061 | + | 
|---|
|  | 4062 | +static inline int | 
|---|
|  | 4063 | +button_pressed(void) | 
|---|
|  | 4064 | +{ | 
|---|
|  | 4065 | +       unsigned char b; | 
|---|
|  | 4066 | +       unsigned long flags; | 
|---|
|  | 4067 | + | 
|---|
|  | 4068 | +       spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4069 | +       b = read_buttons(); | 
|---|
|  | 4070 | +       spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4071 | + | 
|---|
|  | 4072 | +       switch (b) { | 
|---|
|  | 4073 | +       case BUTTON_Next: | 
|---|
|  | 4074 | +       case BUTTON_Next_B: | 
|---|
|  | 4075 | +       case BUTTON_Reset_B: | 
|---|
|  | 4076 | +               return b; | 
|---|
|  | 4077 | +       default: | 
|---|
|  | 4078 | +           break; | 
|---|
|  | 4079 | +       } | 
|---|
|  | 4080 | + | 
|---|
|  | 4081 | +       return 0; | 
|---|
|  | 4082 | +} | 
|---|
|  | 4083 | + | 
|---|
|  | 4084 | +/* this could be protected by CAP_RAW_IO here, or by the FS permissions */ | 
|---|
|  | 4085 | +static int | 
|---|
|  | 4086 | +cobalt_lcd_ioctl(struct inode *inode, struct file *file, | 
|---|
|  | 4087 | +       unsigned int cmd, unsigned long arg) | 
|---|
|  | 4088 | +{ | 
|---|
|  | 4089 | +       struct lcd_display button_display, display; | 
|---|
|  | 4090 | +       unsigned long address, a; | 
|---|
|  | 4091 | +       int index; | 
|---|
|  | 4092 | +       int dlen = sizeof(struct lcd_display); | 
|---|
|  | 4093 | +       int r = 0; | 
|---|
|  | 4094 | +       unsigned long flags; | 
|---|
|  | 4095 | + | 
|---|
|  | 4096 | +#ifdef CONFIG_COBALT_LCD_TWIDDLE | 
|---|
|  | 4097 | +       cobalt_lcd_stop_twiddle(); | 
|---|
|  | 4098 | +#endif | 
|---|
|  | 4099 | +       switch (cmd) { | 
|---|
|  | 4100 | +       /* Turn the LCD on */ | 
|---|
|  | 4101 | +       case LCD_On: | 
|---|
|  | 4102 | +               spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4103 | +               lcddev_write_inst(0x0F); | 
|---|
|  | 4104 | +               spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4105 | +               break; | 
|---|
|  | 4106 | + | 
|---|
|  | 4107 | +       /* Turn the LCD off */ | 
|---|
|  | 4108 | +       case LCD_Off: | 
|---|
|  | 4109 | +               spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4110 | +               lcddev_write_inst(0x08); | 
|---|
|  | 4111 | +               spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4112 | +               break; | 
|---|
|  | 4113 | + | 
|---|
|  | 4114 | +       /* Reset the LCD */ | 
|---|
|  | 4115 | +       case LCD_Reset: | 
|---|
|  | 4116 | +               spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4117 | +               lcddev_write_inst(0x3F); | 
|---|
|  | 4118 | +               lcddev_write_inst(0x3F); | 
|---|
|  | 4119 | +               lcddev_write_inst(0x3F); | 
|---|
|  | 4120 | +               lcddev_write_inst(0x3F); | 
|---|
|  | 4121 | +               lcddev_write_inst(0x01); | 
|---|
|  | 4122 | +               lcddev_write_inst(0x06); | 
|---|
|  | 4123 | +               spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4124 | +               break; | 
|---|
|  | 4125 | + | 
|---|
|  | 4126 | +       /* Clear the LCD */ | 
|---|
|  | 4127 | +       case LCD_Clear: | 
|---|
|  | 4128 | +               spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4129 | +               lcddev_write_inst(0x01); | 
|---|
|  | 4130 | +               spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4131 | +               break; | 
|---|
|  | 4132 | + | 
|---|
|  | 4133 | +       /* Move the cursor one position to the left */ | 
|---|
|  | 4134 | +       case LCD_Cursor_Left: | 
|---|
|  | 4135 | +               spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4136 | +               lcddev_write_inst(0x10); | 
|---|
|  | 4137 | +               spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4138 | +               break; | 
|---|
|  | 4139 | + | 
|---|
|  | 4140 | +       /* Move the cursor one position to the right */ | 
|---|
|  | 4141 | +       case LCD_Cursor_Right: | 
|---|
|  | 4142 | +               spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4143 | +               lcddev_write_inst(0x14); | 
|---|
|  | 4144 | +               spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4145 | +               break; | 
|---|
|  | 4146 | + | 
|---|
|  | 4147 | +       /* Turn the cursor off */ | 
|---|
|  | 4148 | +       case LCD_Cursor_Off: | 
|---|
|  | 4149 | +               spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4150 | +               lcddev_write_inst(0x0C); | 
|---|
|  | 4151 | +               spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4152 | +               break; | 
|---|
|  | 4153 | + | 
|---|
|  | 4154 | +       /* Turn the cursor on */ | 
|---|
|  | 4155 | +       case LCD_Cursor_On: | 
|---|
|  | 4156 | +               spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4157 | +               lcddev_write_inst(0x0F); | 
|---|
|  | 4158 | +               spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4159 | +               break; | 
|---|
|  | 4160 | + | 
|---|
|  | 4161 | +       /* Turn blinking off? I don't know what this does - TJS */ | 
|---|
|  | 4162 | +       case LCD_Blink_Off: | 
|---|
|  | 4163 | +               spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4164 | +               lcddev_write_inst(0x0E); | 
|---|
|  | 4165 | +               spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4166 | +               break; | 
|---|
|  | 4167 | + | 
|---|
|  | 4168 | +       /* Get the current cursor position */ | 
|---|
|  | 4169 | +       case LCD_Get_Cursor_Pos: | 
|---|
|  | 4170 | +               spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4171 | +               display.cursor_address = (unsigned char)lcddev_read_inst(); | 
|---|
|  | 4172 | +               display.cursor_address = display.cursor_address & 0x07F; | 
|---|
|  | 4173 | +               spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4174 | +               if (copy_to_user((struct lcd_display *)arg, &display, dlen)) { | 
|---|
|  | 4175 | +                       r = -EFAULT; | 
|---|
|  | 4176 | +               } | 
|---|
|  | 4177 | +               break; | 
|---|
|  | 4178 | + | 
|---|
|  | 4179 | +       /* Set the cursor position */ | 
|---|
|  | 4180 | +       case LCD_Set_Cursor_Pos: | 
|---|
|  | 4181 | +               if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) { | 
|---|
|  | 4182 | +                       r = -EFAULT; | 
|---|
|  | 4183 | +                       break; | 
|---|
|  | 4184 | +               } | 
|---|
|  | 4185 | +               a = display.cursor_address | LCD_Addr; | 
|---|
|  | 4186 | +               spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4187 | +               lcddev_write_inst(a); | 
|---|
|  | 4188 | +               spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4189 | +               break; | 
|---|
|  | 4190 | + | 
|---|
|  | 4191 | +       /* Get the value at the current cursor position? - TJS */ | 
|---|
|  | 4192 | +       case LCD_Get_Cursor: | 
|---|
|  | 4193 | +               spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4194 | +               display.character = lcddev_read_data(); | 
|---|
|  | 4195 | +               lcddev_write_inst(0x10); | 
|---|
|  | 4196 | +               spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4197 | +               if (copy_to_user((struct lcd_display *)arg, &display, dlen)) { | 
|---|
|  | 4198 | +                       r = -EFAULT; | 
|---|
|  | 4199 | +               } | 
|---|
|  | 4200 | +               break; | 
|---|
|  | 4201 | + | 
|---|
|  | 4202 | +       /* Set the character at the cursor position? - TJS */ | 
|---|
|  | 4203 | +       case LCD_Set_Cursor: | 
|---|
|  | 4204 | +               if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) { | 
|---|
|  | 4205 | +                       r = -EFAULT; | 
|---|
|  | 4206 | +                       break; | 
|---|
|  | 4207 | +               } | 
|---|
|  | 4208 | +               spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4209 | +               lcddev_write_data(display.character); | 
|---|
|  | 4210 | +               lcddev_write_inst(0x10); | 
|---|
|  | 4211 | +               spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4212 | +               break; | 
|---|
|  | 4213 | + | 
|---|
|  | 4214 | +       /* Dunno what this does - TJS */ | 
|---|
|  | 4215 | +       case LCD_Disp_Left: | 
|---|
|  | 4216 | +               spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4217 | +               lcddev_write_inst(0x18); | 
|---|
|  | 4218 | +               spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4219 | +               break; | 
|---|
|  | 4220 | + | 
|---|
|  | 4221 | +       /* Dunno what this does - TJS */ | 
|---|
|  | 4222 | +       case LCD_Disp_Right: | 
|---|
|  | 4223 | +               spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4224 | +               lcddev_write_inst(0x1C); | 
|---|
|  | 4225 | +               spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4226 | +               break; | 
|---|
|  | 4227 | + | 
|---|
|  | 4228 | +       /* Dunno what this does - TJS */ | 
|---|
|  | 4229 | +       case LCD_Home: | 
|---|
|  | 4230 | +               spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4231 | +               lcddev_write_inst(0x02); | 
|---|
|  | 4232 | +               spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4233 | +               break; | 
|---|
|  | 4234 | + | 
|---|
|  | 4235 | +       /* Write a string to the LCD */ | 
|---|
|  | 4236 | +       case LCD_Write: | 
|---|
|  | 4237 | +               if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) { | 
|---|
|  | 4238 | +                       r = -EFAULT; | 
|---|
|  | 4239 | +                       break; | 
|---|
|  | 4240 | +               } | 
|---|
|  | 4241 | + | 
|---|
|  | 4242 | +               spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4243 | + | 
|---|
|  | 4244 | +               display.size1 = display.size1 > 0 ? | 
|---|
|  | 4245 | +                 min(display.size1, (int) sizeof(display.line1)) : 0; | 
|---|
|  | 4246 | +               display.size2 = display.size2 > 0 ? | 
|---|
|  | 4247 | +                 min(display.size2, (int) sizeof(display.line2)) : 0; | 
|---|
|  | 4248 | + | 
|---|
|  | 4249 | +               /* First line */ | 
|---|
|  | 4250 | +               lcddev_write_inst(0x80); | 
|---|
|  | 4251 | +               for (index = 0; index < display.size1; index++) | 
|---|
|  | 4252 | +                       lcddev_write_data(display.line1[index]); | 
|---|
|  | 4253 | +               for (index = display.size1; index < sizeof(display.line1); index++) | 
|---|
|  | 4254 | +                       lcddev_write_data(' '); | 
|---|
|  | 4255 | + | 
|---|
|  | 4256 | +               /* Second line */ | 
|---|
|  | 4257 | +               lcddev_write_inst(0xC0); | 
|---|
|  | 4258 | +               for (index = 0; index < display.size2; index++) | 
|---|
|  | 4259 | +                       lcddev_write_data(display.line2[index]); | 
|---|
|  | 4260 | +               for (index = display.size2; index < sizeof(display.line2); index++) | 
|---|
|  | 4261 | +                       lcddev_write_data(' '); | 
|---|
|  | 4262 | + | 
|---|
|  | 4263 | +               spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4264 | +               break; | 
|---|
|  | 4265 | + | 
|---|
|  | 4266 | +       /* Read what's on the LCD */ | 
|---|
|  | 4267 | +       case LCD_Read: | 
|---|
|  | 4268 | +               spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4269 | + | 
|---|
|  | 4270 | +               for (address = DD_R00; address <= DD_R01; address++) { | 
|---|
|  | 4271 | +                       lcddev_write_inst(address | LCD_Addr); | 
|---|
|  | 4272 | +                       display.line1[address] = lcddev_read_data(); | 
|---|
|  | 4273 | +               } | 
|---|
|  | 4274 | +               for (address = DD_R10; address <= DD_R11; address++) { | 
|---|
|  | 4275 | +                       lcddev_write_inst(address | LCD_Addr); | 
|---|
|  | 4276 | +                       display.line2[address - DD_R10] = lcddev_read_data(); | 
|---|
|  | 4277 | +               } | 
|---|
|  | 4278 | + | 
|---|
|  | 4279 | +               spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4280 | + | 
|---|
|  | 4281 | +               display.line1[DD_R01] = '\0'; | 
|---|
|  | 4282 | +               display.line2[DD_R01] = '\0'; | 
|---|
|  | 4283 | + | 
|---|
|  | 4284 | +               if (copy_to_user((struct lcd_display *)arg, &display, dlen)) { | 
|---|
|  | 4285 | +                       r = -EFAULT; | 
|---|
|  | 4286 | +               } | 
|---|
|  | 4287 | +               break; | 
|---|
|  | 4288 | + | 
|---|
|  | 4289 | +       case LCD_Raw_Inst: | 
|---|
|  | 4290 | +               if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) { | 
|---|
|  | 4291 | +                       r = -EFAULT; | 
|---|
|  | 4292 | +                       break; | 
|---|
|  | 4293 | +               } | 
|---|
|  | 4294 | +               spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4295 | +               lcddev_write_inst(display.character); | 
|---|
|  | 4296 | +               spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4297 | +               break; | 
|---|
|  | 4298 | + | 
|---|
|  | 4299 | +       case LCD_Raw_Data: | 
|---|
|  | 4300 | +               if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) { | 
|---|
|  | 4301 | +                       r = -EFAULT; | 
|---|
|  | 4302 | +                       break; | 
|---|
|  | 4303 | +               } | 
|---|
|  | 4304 | +               spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4305 | +               lcddev_write_data(display.character); | 
|---|
|  | 4306 | +               spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4307 | +               break; | 
|---|
|  | 4308 | + | 
|---|
|  | 4309 | +       case LCD_Type: | 
|---|
|  | 4310 | +               if (cobt_is_5k() && has_i2c_lcd) { | 
|---|
|  | 4311 | +                       if (put_user(LCD_TYPE_I2C, (int *)arg)) { | 
|---|
|  | 4312 | +                               r = -EFAULT; | 
|---|
|  | 4313 | +                       } | 
|---|
|  | 4314 | +               } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) { | 
|---|
|  | 4315 | +                       if (put_user(LCD_TYPE_PARALLEL_B, (int *)arg)) { | 
|---|
|  | 4316 | +                               r = -EFAULT; | 
|---|
|  | 4317 | +                       } | 
|---|
|  | 4318 | +               } | 
|---|
|  | 4319 | +               break; | 
|---|
|  | 4320 | + | 
|---|
|  | 4321 | +       /* Read the buttons */ | 
|---|
|  | 4322 | +       case BUTTON_Read: | 
|---|
|  | 4323 | +               spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4324 | +               button_display.buttons = read_buttons(); | 
|---|
|  | 4325 | +               spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4326 | +               if (copy_to_user((struct lcd_display *)arg, | 
|---|
|  | 4327 | +                               &button_display, dlen)) { | 
|---|
|  | 4328 | +                       r = -EFAULT; | 
|---|
|  | 4329 | +               } | 
|---|
|  | 4330 | +               break; | 
|---|
|  | 4331 | + | 
|---|
|  | 4332 | +#ifdef CONFIG_COBALT_LED | 
|---|
|  | 4333 | +       /* a slightly different api that allows you to set 32 leds */ | 
|---|
|  | 4334 | +       case LED32_Set: | 
|---|
|  | 4335 | +               cobalt_led_set_lazy(arg); | 
|---|
|  | 4336 | +               break; | 
|---|
|  | 4337 | + | 
|---|
|  | 4338 | +       case LED32_Bit_Set: | 
|---|
|  | 4339 | +               cobalt_led_set_bits_lazy(arg); | 
|---|
|  | 4340 | +               break; | 
|---|
|  | 4341 | + | 
|---|
|  | 4342 | +       case LED32_Bit_Clear: | 
|---|
|  | 4343 | +               cobalt_led_clear_bits_lazy(arg); | 
|---|
|  | 4344 | +               break; | 
|---|
|  | 4345 | + | 
|---|
|  | 4346 | +       case LED32_Get: | 
|---|
|  | 4347 | +               *(unsigned int *)arg = cobalt_led_get(); | 
|---|
|  | 4348 | +               break; | 
|---|
|  | 4349 | + | 
|---|
|  | 4350 | +       /* set all the leds */ | 
|---|
|  | 4351 | +       case LED_Set: | 
|---|
|  | 4352 | +               if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) { | 
|---|
|  | 4353 | +                       r = -EFAULT; | 
|---|
|  | 4354 | +                       break; | 
|---|
|  | 4355 | +               } | 
|---|
|  | 4356 | +               cobalt_led_set_lazy(display.leds); | 
|---|
|  | 4357 | +               break; | 
|---|
|  | 4358 | + | 
|---|
|  | 4359 | +       /* set a single led */ | 
|---|
|  | 4360 | +       case LED_Bit_Set: | 
|---|
|  | 4361 | +               if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) { | 
|---|
|  | 4362 | +                       r = -EFAULT; | 
|---|
|  | 4363 | +                       break; | 
|---|
|  | 4364 | +               } | 
|---|
|  | 4365 | +               cobalt_led_set_bits_lazy(display.leds); | 
|---|
|  | 4366 | +               break; | 
|---|
|  | 4367 | + | 
|---|
|  | 4368 | +       /* clear an led */ | 
|---|
|  | 4369 | +       case LED_Bit_Clear: | 
|---|
|  | 4370 | +               if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) { | 
|---|
|  | 4371 | +                       r = -EFAULT; | 
|---|
|  | 4372 | +                       break; | 
|---|
|  | 4373 | +               } | 
|---|
|  | 4374 | +               cobalt_led_clear_bits_lazy(display.leds); | 
|---|
|  | 4375 | +               break; | 
|---|
|  | 4376 | +#endif | 
|---|
|  | 4377 | + | 
|---|
|  | 4378 | +       default: | 
|---|
|  | 4379 | +           break; | 
|---|
|  | 4380 | +       } | 
|---|
|  | 4381 | + | 
|---|
|  | 4382 | +       return r; | 
|---|
|  | 4383 | +} | 
|---|
|  | 4384 | + | 
|---|
|  | 4385 | +static int | 
|---|
|  | 4386 | +cobalt_lcd_open(struct inode *inode, struct file *file) | 
|---|
|  | 4387 | +{ | 
|---|
|  | 4388 | +       if (!lcd_present) { | 
|---|
|  | 4389 | +               return -ENXIO; | 
|---|
|  | 4390 | +       } else { | 
|---|
|  | 4391 | +               return 0; | 
|---|
|  | 4392 | +       } | 
|---|
|  | 4393 | +} | 
|---|
|  | 4394 | + | 
|---|
|  | 4395 | +/* LCD daemon sits on this, we wake it up once a key is pressed */ | 
|---|
|  | 4396 | +static ssize_t | 
|---|
|  | 4397 | +cobalt_lcd_read(struct file *file, char *buf, size_t count, loff_t *ppos) | 
|---|
|  | 4398 | +{ | 
|---|
|  | 4399 | +       int bnow; | 
|---|
|  | 4400 | +       static unsigned long lcd_waiters; | 
|---|
|  | 4401 | + | 
|---|
|  | 4402 | +       if (test_and_set_bit(0, &lcd_waiters)) { | 
|---|
|  | 4403 | +               return -EINVAL; | 
|---|
|  | 4404 | +       } | 
|---|
|  | 4405 | + | 
|---|
|  | 4406 | +       while (((bnow = button_pressed()) == 0) && !(signal_pending(current))) { | 
|---|
|  | 4407 | +               if (file->f_flags & O_NONBLOCK) { | 
|---|
|  | 4408 | +                       lcd_waiters = 0; | 
|---|
|  | 4409 | +                       return -EAGAIN; | 
|---|
|  | 4410 | +               } | 
|---|
|  | 4411 | +               set_current_state(TASK_INTERRUPTIBLE); | 
|---|
|  | 4412 | +               schedule_timeout(2 * HZ); | 
|---|
|  | 4413 | +       } | 
|---|
|  | 4414 | +       lcd_waiters = 0; | 
|---|
|  | 4415 | + | 
|---|
|  | 4416 | +       if (signal_pending(current)) { | 
|---|
|  | 4417 | +               return -ERESTARTSYS; | 
|---|
|  | 4418 | +       } | 
|---|
|  | 4419 | + | 
|---|
|  | 4420 | +       return bnow; | 
|---|
|  | 4421 | +} | 
|---|
|  | 4422 | + | 
|---|
|  | 4423 | +/* read a single line from the LCD into a string */ | 
|---|
|  | 4424 | +static char * | 
|---|
|  | 4425 | +cobalt_lcddev_read_line(int lineno, char *line) | 
|---|
|  | 4426 | +{ | 
|---|
|  | 4427 | +       unsigned long addr, min, max; | 
|---|
|  | 4428 | +       unsigned long flags; | 
|---|
|  | 4429 | + | 
|---|
|  | 4430 | +       switch (lineno) { | 
|---|
|  | 4431 | +       case 0: | 
|---|
|  | 4432 | +               min = DD_R00; | 
|---|
|  | 4433 | +               max = DD_R01; | 
|---|
|  | 4434 | +               break; | 
|---|
|  | 4435 | +       case 1: | 
|---|
|  | 4436 | +               min = DD_R10; | 
|---|
|  | 4437 | +               max = DD_R11; | 
|---|
|  | 4438 | +               break; | 
|---|
|  | 4439 | +       default: | 
|---|
|  | 4440 | +               min = 1; | 
|---|
|  | 4441 | +               max = 0; | 
|---|
|  | 4442 | +       } | 
|---|
|  | 4443 | + | 
|---|
|  | 4444 | +       spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4445 | +       for (addr = min; addr <= max; addr++) { | 
|---|
|  | 4446 | +               lcddev_write_inst(addr | LCD_Addr); | 
|---|
|  | 4447 | +               udelay(150); | 
|---|
|  | 4448 | +               line[addr-min] = lcddev_read_data(); | 
|---|
|  | 4449 | +               udelay(150); | 
|---|
|  | 4450 | +       } | 
|---|
|  | 4451 | +       spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4452 | +       line[addr-min] = '\0'; | 
|---|
|  | 4453 | + | 
|---|
|  | 4454 | +       return line; | 
|---|
|  | 4455 | +} | 
|---|
|  | 4456 | + | 
|---|
|  | 4457 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 4458 | +static int | 
|---|
|  | 4459 | +cobalt_lcd_read_proc(char *buf, char **start, off_t pos, | 
|---|
|  | 4460 | +                               int len, int *eof, void *private) | 
|---|
|  | 4461 | +{ | 
|---|
|  | 4462 | +       int plen = 0; | 
|---|
|  | 4463 | +       char line[COBALT_LCD_LINELEN+1]; | 
|---|
|  | 4464 | + | 
|---|
|  | 4465 | +       /* first line */ | 
|---|
|  | 4466 | +       cobalt_lcddev_read_line(0, line); | 
|---|
|  | 4467 | +       plen += sprintf(buf+plen, "%s\n", line); | 
|---|
|  | 4468 | + | 
|---|
|  | 4469 | +       /* second line */ | 
|---|
|  | 4470 | +       cobalt_lcddev_read_line(1, line); | 
|---|
|  | 4471 | +       plen += sprintf(buf+plen, "%s\n", line); | 
|---|
|  | 4472 | + | 
|---|
|  | 4473 | +       return cobalt_gen_proc_read(buf, plen, start, pos, len, eof); | 
|---|
|  | 4474 | +} | 
|---|
|  | 4475 | +#endif | 
|---|
|  | 4476 | + | 
|---|
|  | 4477 | +static char *lcd_panic_str1 = "Kernel"; | 
|---|
|  | 4478 | +static char *lcd_panic_str2 = "Panic!"; | 
|---|
|  | 4479 | + | 
|---|
|  | 4480 | +static int cobalt_lcd_panic(struct notifier_block *self, unsigned long a, void *b) | 
|---|
|  | 4481 | +{ | 
|---|
|  | 4482 | +    int i; | 
|---|
|  | 4483 | +    int len; | 
|---|
|  | 4484 | + | 
|---|
|  | 4485 | +    if( !lcd_present ) | 
|---|
|  | 4486 | +        return 0; | 
|---|
|  | 4487 | + | 
|---|
|  | 4488 | +#ifdef CONFIG_COBALT_LCD_TWIDDLE | 
|---|
|  | 4489 | +    cobalt_lcd_stop_twiddle(); | 
|---|
|  | 4490 | +#endif | 
|---|
|  | 4491 | + | 
|---|
|  | 4492 | +    lcddev_write_inst( (DD_R00) | LCD_Addr); | 
|---|
|  | 4493 | +    len = strlen( lcd_panic_str1 ); | 
|---|
|  | 4494 | +    for( i=0 ; i<16 ; i++ ) | 
|---|
|  | 4495 | +       lcddev_write_data( (i<len)?lcd_panic_str1[i]:' ' ); | 
|---|
|  | 4496 | + | 
|---|
|  | 4497 | +    lcddev_write_inst( (DD_R10) | LCD_Addr); | 
|---|
|  | 4498 | +    len = strlen( lcd_panic_str2 ); | 
|---|
|  | 4499 | +    for( i=0 ; i<16 ; i++ ) | 
|---|
|  | 4500 | +       lcddev_write_data( (i<len)?lcd_panic_str2[i]:' ' ); | 
|---|
|  | 4501 | + | 
|---|
|  | 4502 | +    return 0; | 
|---|
|  | 4503 | +} | 
|---|
|  | 4504 | + | 
|---|
|  | 4505 | +#ifdef CONFIG_COBALT_LCD_TWIDDLE | 
|---|
|  | 4506 | +static struct timer_list twiddle_timer; | 
|---|
|  | 4507 | +static int twiddling; | 
|---|
|  | 4508 | +static void | 
|---|
|  | 4509 | +twiddle_timer_func(unsigned long data) | 
|---|
|  | 4510 | +{ | 
|---|
|  | 4511 | +       static int state=1; | 
|---|
|  | 4512 | +       static int pos=0; | 
|---|
|  | 4513 | +       unsigned long flags; | 
|---|
|  | 4514 | + | 
|---|
|  | 4515 | +       spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4516 | + | 
|---|
|  | 4517 | +       lcddev_write_inst((DD_R10+4+pos) | LCD_Addr); | 
|---|
|  | 4518 | +       lcddev_write_data(' '); | 
|---|
|  | 4519 | + | 
|---|
|  | 4520 | +       pos += state; | 
|---|
|  | 4521 | +       if (pos < 0) { | 
|---|
|  | 4522 | +               state = 1; | 
|---|
|  | 4523 | +               pos = 1; | 
|---|
|  | 4524 | +       } | 
|---|
|  | 4525 | +       if (pos > 11) { | 
|---|
|  | 4526 | +               state = -1; | 
|---|
|  | 4527 | +               pos = 10; | 
|---|
|  | 4528 | +       } | 
|---|
|  | 4529 | + | 
|---|
|  | 4530 | +       lcddev_write_inst((DD_R10+4+pos) | LCD_Addr); | 
|---|
|  | 4531 | +       lcddev_write_data(0xff); | 
|---|
|  | 4532 | + | 
|---|
|  | 4533 | +       spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4534 | + | 
|---|
|  | 4535 | +       mod_timer(&twiddle_timer, jiffies + TWIDDLE_HZ); | 
|---|
|  | 4536 | +} | 
|---|
|  | 4537 | + | 
|---|
|  | 4538 | +void | 
|---|
|  | 4539 | +cobalt_lcd_start_twiddle(void) | 
|---|
|  | 4540 | +{ | 
|---|
|  | 4541 | +    init_timer(&twiddle_timer); | 
|---|
|  | 4542 | +       twiddle_timer.expires = jiffies + TWIDDLE_HZ; | 
|---|
|  | 4543 | +       twiddle_timer.data = 0; | 
|---|
|  | 4544 | +       twiddle_timer.function = &twiddle_timer_func; | 
|---|
|  | 4545 | +       add_timer(&twiddle_timer); | 
|---|
|  | 4546 | +       twiddling=1; | 
|---|
|  | 4547 | +} | 
|---|
|  | 4548 | + | 
|---|
|  | 4549 | +void | 
|---|
|  | 4550 | +cobalt_lcd_stop_twiddle(void) | 
|---|
|  | 4551 | +{ | 
|---|
|  | 4552 | +       unsigned long flags; | 
|---|
|  | 4553 | + | 
|---|
|  | 4554 | +    spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4555 | +       if (twiddling) { | 
|---|
|  | 4556 | +               del_timer_sync(&twiddle_timer); | 
|---|
|  | 4557 | +               twiddling = 0; | 
|---|
|  | 4558 | +       } | 
|---|
|  | 4559 | +       spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4560 | +} | 
|---|
|  | 4561 | +#endif /* CONFIG_COBALT_LCD_TWIDDLE */ | 
|---|
|  | 4562 | + | 
|---|
|  | 4563 | +/* stop the lcd */ | 
|---|
|  | 4564 | +void cobalt_lcd_off(void) | 
|---|
|  | 4565 | +{ | 
|---|
|  | 4566 | +       unsigned long flags; | 
|---|
|  | 4567 | + | 
|---|
|  | 4568 | +       spin_lock_irqsave(&lcd_lock, flags); | 
|---|
|  | 4569 | +       lcddev_write_inst(0x01); /* clear */ | 
|---|
|  | 4570 | +       lcddev_write_inst(0x08); /* off */ | 
|---|
|  | 4571 | +       spin_unlock_irqrestore(&lcd_lock, flags); | 
|---|
|  | 4572 | +} | 
|---|
|  | 4573 | + | 
|---|
|  | 4574 | +static int initialized; | 
|---|
|  | 4575 | +static struct notifier_block lcd_nb; | 
|---|
|  | 4576 | + | 
|---|
|  | 4577 | +int __init | 
|---|
|  | 4578 | +cobalt_lcd_init(void) | 
|---|
|  | 4579 | +{ | 
|---|
|  | 4580 | +    int retval; | 
|---|
|  | 4581 | + | 
|---|
|  | 4582 | +       if (initialized) | 
|---|
|  | 4583 | +               return 0; | 
|---|
|  | 4584 | + | 
|---|
|  | 4585 | +       initialized=1; | 
|---|
|  | 4586 | +    printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", LCD_DRIVER,LCD_DRIVER_VMAJ,LCD_DRIVER_VMIN); | 
|---|
|  | 4587 | + | 
|---|
|  | 4588 | +       if (disable_lcd) { | 
|---|
|  | 4589 | +               printk(KERN_INFO "%s DISABLED\n", LCD_DRIVER); | 
|---|
|  | 4590 | +               return 0; | 
|---|
|  | 4591 | +       } | 
|---|
|  | 4592 | + | 
|---|
|  | 4593 | +    retval = misc_register(&lcd_dev); | 
|---|
|  | 4594 | + | 
|---|
|  | 4595 | +       if (cobt_is_monterey() | 
|---|
|  | 4596 | +        && (cobalt_i2c_read_byte(COBALT_I2C_DEV_LCD_INST, 0) != 0xff)) { | 
|---|
|  | 4597 | +           printk(KERN_INFO "  - LCD is an I2C device\n"); | 
|---|
|  | 4598 | +               has_i2c_lcd = 1; | 
|---|
|  | 4599 | +       } else { | 
|---|
|  | 4600 | +               has_i2c_lcd = 0; | 
|---|
|  | 4601 | +       } | 
|---|
|  | 4602 | + | 
|---|
|  | 4603 | +       /* flag ourselves as present */ | 
|---|
|  | 4604 | +       lcd_present = 1; | 
|---|
|  | 4605 | + | 
|---|
|  | 4606 | +       /* initialize the device */ | 
|---|
|  | 4607 | +       lcddev_init(); | 
|---|
|  | 4608 | + | 
|---|
|  | 4609 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 4610 | +#ifdef CONFIG_COBALT_OLDPROC | 
|---|
|  | 4611 | +       /* create /proc/lcd */ | 
|---|
|  | 4612 | +       proc_lcd = create_proc_read_entry("lcd", S_IRUSR, NULL, | 
|---|
|  | 4613 | +               cobalt_lcd_read_proc, NULL); | 
|---|
|  | 4614 | +       if (!proc_lcd) { | 
|---|
|  | 4615 | +               EPRINTK("can't create /proc/lcd\n"); | 
|---|
|  | 4616 | +       } | 
|---|
|  | 4617 | +#endif | 
|---|
|  | 4618 | +    proc_clcd = create_proc_read_entry("lcd", S_IRUSR, proc_cobalt, | 
|---|
|  | 4619 | +               cobalt_lcd_read_proc, NULL); | 
|---|
|  | 4620 | +       if (!proc_clcd) { | 
|---|
|  | 4621 | +               EPRINTK("can't create /proc/cobalt/lcd\n"); | 
|---|
|  | 4622 | +       } | 
|---|
|  | 4623 | +#endif | 
|---|
|  | 4624 | + | 
|---|
|  | 4625 | +#ifdef CONFIG_COBALT_LCD_TWIDDLE | 
|---|
|  | 4626 | +       cobalt_lcd_start_twiddle(); | 
|---|
|  | 4627 | +#endif | 
|---|
|  | 4628 | + | 
|---|
|  | 4629 | +            /* register panic notifier */ | 
|---|
|  | 4630 | +        lcd_nb.notifier_call = cobalt_lcd_panic; | 
|---|
|  | 4631 | +        lcd_nb.next = NULL; | 
|---|
|  | 4632 | +        lcd_nb.priority = 0; | 
|---|
|  | 4633 | + | 
|---|
|  | 4634 | +        atomic_notifier_chain_register( &panic_notifier_list, &lcd_nb ); | 
|---|
|  | 4635 | + | 
|---|
|  | 4636 | +       return 0; | 
|---|
|  | 4637 | +} | 
|---|
|  | 4638 | + | 
|---|
|  | 4639 | +#endif /* CONFIG_COBALT_LCD */ | 
|---|
|  | 4640 | diff -Naur linux-2.6.20.orig/drivers/cobalt/led.c linux-2.6.20/drivers/cobalt/led.c | 
|---|
|  | 4641 | --- linux-2.6.20.orig/drivers/cobalt/led.c      1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 4642 | +++ linux-2.6.20/drivers/cobalt/led.c   2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 4643 | @@ -0,0 +1,504 @@ | 
|---|
|  | 4644 | + /* | 
|---|
|  | 4645 | + * $Id: led.c,v 1.36 2002/05/10 18:44:45 duncan Exp $ | 
|---|
|  | 4646 | + * led.c : driver for Cobalt LEDs | 
|---|
|  | 4647 | + * | 
|---|
|  | 4648 | + * Copyright 1996-2000 Cobalt Networks, Inc. | 
|---|
|  | 4649 | + * Copyright 2001 Sun Microsystems, Inc. | 
|---|
|  | 4650 | + * | 
|---|
|  | 4651 | + * By: Andrew Bose | 
|---|
|  | 4652 | + *     Timothy Stonis | 
|---|
|  | 4653 | + *     Tim Hockin | 
|---|
|  | 4654 | + *     Adrian Sun | 
|---|
|  | 4655 | + *     Duncan Laurie | 
|---|
|  | 4656 | + * | 
|---|
|  | 4657 | + * Modified By: jeff@404ster.com | 
|---|
|  | 4658 | + * | 
|---|
|  | 4659 | + * This should be SMP safe.  There is one definite critical region: the | 
|---|
|  | 4660 | + * handler list (led_handler_lock).  The led_state is protected by led_lock, | 
|---|
|  | 4661 | + * so should be safe against simultaneous writes.  Bit banging of lights is | 
|---|
|  | 4662 | + * currently also a protected region (led_lock, rather than add a new lock). | 
|---|
|  | 4663 | + */ | 
|---|
|  | 4664 | + | 
|---|
|  | 4665 | +#include <linux/config.h> | 
|---|
|  | 4666 | + | 
|---|
|  | 4667 | +#ifdef CONFIG_COBALT_LED | 
|---|
|  | 4668 | + | 
|---|
|  | 4669 | +#include <linux/module.h> | 
|---|
|  | 4670 | +#include <linux/types.h> | 
|---|
|  | 4671 | +#include <linux/errno.h> | 
|---|
|  | 4672 | +#include <linux/miscdevice.h> | 
|---|
|  | 4673 | +#include <linux/slab.h> | 
|---|
|  | 4674 | +#include <linux/ioport.h> | 
|---|
|  | 4675 | +#include <linux/fcntl.h> | 
|---|
|  | 4676 | +#include <linux/netdevice.h> | 
|---|
|  | 4677 | +#include <linux/pci.h> | 
|---|
|  | 4678 | +#include <linux/init.h> | 
|---|
|  | 4679 | +#include <linux/timer.h> | 
|---|
|  | 4680 | +#include <linux/nvram.h> | 
|---|
|  | 4681 | +#include <asm/io.h> | 
|---|
|  | 4682 | +#include <linux/delay.h> | 
|---|
|  | 4683 | + | 
|---|
|  | 4684 | +#include <cobalt/cobalt.h> | 
|---|
|  | 4685 | +#include <cobalt/systype.h> | 
|---|
|  | 4686 | +#include <cobalt/led.h> | 
|---|
|  | 4687 | +#include <cobalt/i2c.h> | 
|---|
|  | 4688 | +#include <cobalt/superio.h> | 
|---|
|  | 4689 | + | 
|---|
|  | 4690 | +#define LED_DRIVER                     "Cobalt Networks LED driver" | 
|---|
|  | 4691 | +#define LED_DRIVER_VMAJ                1 | 
|---|
|  | 4692 | +#define LED_DRIVER_VMIN                0 | 
|---|
|  | 4693 | + | 
|---|
|  | 4694 | +/* the rate at which software controlled frontpanel LEDs blink */ | 
|---|
|  | 4695 | +#define FPLED_DEFAULT_HZ       (HZ/20) | 
|---|
|  | 4696 | + | 
|---|
|  | 4697 | +/* | 
|---|
|  | 4698 | + * This is the abstracted state of active LEDs - see the defines for LED_* | 
|---|
|  | 4699 | + * LED masks are always 'unsigned int'.  You must hold led_lock to muck with | 
|---|
|  | 4700 | + * these. | 
|---|
|  | 4701 | + */ | 
|---|
|  | 4702 | +static unsigned int led_state; | 
|---|
|  | 4703 | +static unsigned int led_blips; | 
|---|
|  | 4704 | + | 
|---|
|  | 4705 | +/* leds are PCI on genIII */ | 
|---|
|  | 4706 | +static struct pci_dev *led_dev; | 
|---|
|  | 4707 | +/* on XTR the front panel LEDs are software controlled */ | 
|---|
|  | 4708 | +struct led_handler { | 
|---|
|  | 4709 | +       unsigned int (*function)(void *); | 
|---|
|  | 4710 | +       void *data; | 
|---|
|  | 4711 | +       struct led_handler *next; | 
|---|
|  | 4712 | +       struct led_handler *prev; | 
|---|
|  | 4713 | +}; | 
|---|
|  | 4714 | +struct led_handler *led_handler_list; | 
|---|
|  | 4715 | +static spinlock_t led_handler_lock = SPIN_LOCK_UNLOCKED; | 
|---|
|  | 4716 | +static struct timer_list timer; | 
|---|
|  | 4717 | + | 
|---|
|  | 4718 | +static spinlock_t led_lock = SPIN_LOCK_UNLOCKED; | 
|---|
|  | 4719 | + | 
|---|
|  | 4720 | +/* | 
|---|
|  | 4721 | + * RaQ 3 | 
|---|
|  | 4722 | + * RaQ 4 | 
|---|
|  | 4723 | + * Qube 3 | 
|---|
|  | 4724 | + */ | 
|---|
|  | 4725 | +#define RAQ3_SHUTLOGO_ADDR     0x7e | 
|---|
|  | 4726 | +#define RAQ3_SHUTDOWN_OFF      0x40 /* reverse polarity */ | 
|---|
|  | 4727 | +#define RAQ3_COBALTLOGO_ON     0x80 | 
|---|
|  | 4728 | +#define QUBE3_LIGHTBAR_ON      0xc0 /* direct polarity */ | 
|---|
|  | 4729 | +#define RAQ3_WEBLIGHT_ADDR     0xb8 | 
|---|
|  | 4730 | +#define RAQ3_WEBLIGHT_ON       0x80 | 
|---|
|  | 4731 | + | 
|---|
|  | 4732 | +/* | 
|---|
|  | 4733 | + * RaQ XTR | 
|---|
|  | 4734 | + */ | 
|---|
|  | 4735 | +#define MONTEREY_FPLED00               0x8000 | 
|---|
|  | 4736 | +#define MONTEREY_FPLED01               0x4000 | 
|---|
|  | 4737 | +#define MONTEREY_FPLED02               0x2000 | 
|---|
|  | 4738 | +#define MONTEREY_FPLED03               0x0200 | 
|---|
|  | 4739 | +#define MONTEREY_FPLED04               0x0080 | 
|---|
|  | 4740 | +#define MONTEREY_FPLED05               0x0040 | 
|---|
|  | 4741 | +#define MONTEREY_FPLED10               0x1000 | 
|---|
|  | 4742 | +#define MONTEREY_FPLED11               0x0800 | 
|---|
|  | 4743 | +#define MONTEREY_FPLED12               0x0400 | 
|---|
|  | 4744 | +#define MONTEREY_FPLED13               0x0100 | 
|---|
|  | 4745 | +#define MONTEREY_FPLED14               0x0020 | 
|---|
|  | 4746 | +#define MONTEREY_FPLED15               0x0010 | 
|---|
|  | 4747 | +#define MONTEREY_FPLED_ETH0_TXRX       MONTEREY_FPLED00 | 
|---|
|  | 4748 | +#define MONTEREY_FPLED_ETH0_LINK       MONTEREY_FPLED10 | 
|---|
|  | 4749 | +#define MONTEREY_FPLED_ETH1_TXRX       MONTEREY_FPLED01 | 
|---|
|  | 4750 | +#define MONTEREY_FPLED_ETH1_LINK       MONTEREY_FPLED11 | 
|---|
|  | 4751 | +#define MONTEREY_FPLED_DISK0           MONTEREY_FPLED02 | 
|---|
|  | 4752 | +#define MONTEREY_FPLED_DISK1           MONTEREY_FPLED03 | 
|---|
|  | 4753 | +#define MONTEREY_FPLED_DISK2           MONTEREY_FPLED04 | 
|---|
|  | 4754 | +#define MONTEREY_FPLED_DISK3           MONTEREY_FPLED05 | 
|---|
|  | 4755 | +#define MONTEREY_FPLED_WEB             MONTEREY_FPLED12 | 
|---|
|  | 4756 | +#define MONTEREY_LOGOLED_BIT           0x40 | 
|---|
|  | 4757 | +#define MONTEREY_SYSFAULTLED_BIT       0x80 | 
|---|
|  | 4758 | +#define MONTEREY_SLED0                 (1<<3) | 
|---|
|  | 4759 | +#define MONTEREY_SLED1                 (1<<2) | 
|---|
|  | 4760 | +#define MONTEREY_SLED2                 (1<<1) | 
|---|
|  | 4761 | +#define MONTEREY_SLED3                 (1<<0) | 
|---|
|  | 4762 | + | 
|---|
|  | 4763 | +/* | 
|---|
|  | 4764 | + * Alpine | 
|---|
|  | 4765 | + */ | 
|---|
|  | 4766 | +#define ALPINE_WEBLED_PORT             0x60e | 
|---|
|  | 4767 | +#define ALPINE_WEBLED_BIT              0x20 | 
|---|
|  | 4768 | +#define ALPINE_POWERLED_PORT           0x50b | 
|---|
|  | 4769 | +#define ALPINE_POWERLED_CFG             0x23 | 
|---|
|  | 4770 | +#define ALPINE_LOGOLED_BIT             0x02 | 
|---|
|  | 4771 | +#define ALPINE_SYSFAULTLED_BIT         0x07 | 
|---|
|  | 4772 | + | 
|---|
|  | 4773 | +/* | 
|---|
|  | 4774 | + * actually set the leds (icky details hidden within) | 
|---|
|  | 4775 | + * this must be protected against itself with led_lock | 
|---|
|  | 4776 | + * */ | 
|---|
|  | 4777 | +static void | 
|---|
|  | 4778 | +__set_led_hw(const unsigned int newstate) | 
|---|
|  | 4779 | +{ | 
|---|
|  | 4780 | +       if (cobt_is_pacifica() && led_dev) { | 
|---|
|  | 4781 | +               unsigned char tmp; | 
|---|
|  | 4782 | +               /* RaQ 3, RaQ 4 | 
|---|
|  | 4783 | +                * - shutdown light | 
|---|
|  | 4784 | +                * - logo light | 
|---|
|  | 4785 | +                * - web light | 
|---|
|  | 4786 | +                */ | 
|---|
|  | 4787 | + | 
|---|
|  | 4788 | +               /* read the current state of shutdown/logo lights */ | 
|---|
|  | 4789 | +               pci_read_config_byte(led_dev, RAQ3_SHUTLOGO_ADDR, &tmp); | 
|---|
|  | 4790 | + | 
|---|
|  | 4791 | +               /* reverse polarity for shutdown light */ | 
|---|
|  | 4792 | +               if (newstate & LED_SHUTDOWN) | 
|---|
|  | 4793 | +                       tmp &= ~RAQ3_SHUTDOWN_OFF; | 
|---|
|  | 4794 | +               else | 
|---|
|  | 4795 | +                       tmp |= RAQ3_SHUTDOWN_OFF; | 
|---|
|  | 4796 | + | 
|---|
|  | 4797 | +               /* logo light is straight forward */ | 
|---|
|  | 4798 | +               if (newstate & LED_COBALTLOGO) | 
|---|
|  | 4799 | +                       tmp |= RAQ3_COBALTLOGO_ON; | 
|---|
|  | 4800 | +               else | 
|---|
|  | 4801 | +                       tmp &= ~RAQ3_COBALTLOGO_ON; | 
|---|
|  | 4802 | + | 
|---|
|  | 4803 | +               /* write new shutdown/logo light state */ | 
|---|
|  | 4804 | +               pci_write_config_byte(led_dev, RAQ3_SHUTLOGO_ADDR, tmp); | 
|---|
|  | 4805 | + | 
|---|
|  | 4806 | +               /* read web light state */ | 
|---|
|  | 4807 | +               pci_read_config_byte(led_dev, RAQ3_WEBLIGHT_ADDR, &tmp); | 
|---|
|  | 4808 | +               if (newstate & LED_WEBLIGHT) { | 
|---|
|  | 4809 | +                       tmp |= RAQ3_WEBLIGHT_ON; | 
|---|
|  | 4810 | +               } else { | 
|---|
|  | 4811 | +                       tmp &= ~RAQ3_WEBLIGHT_ON; | 
|---|
|  | 4812 | +               } | 
|---|
|  | 4813 | + | 
|---|
|  | 4814 | +               /* write new web light state */ | 
|---|
|  | 4815 | +               pci_write_config_byte(led_dev, RAQ3_WEBLIGHT_ADDR, tmp); | 
|---|
|  | 4816 | +       } else if (cobt_is_carmel() && led_dev) { | 
|---|
|  | 4817 | +               unsigned char tmp; | 
|---|
|  | 4818 | +               /* Qube 3 | 
|---|
|  | 4819 | +                * - no shutdown light | 
|---|
|  | 4820 | +                * - lightbar instead of logo | 
|---|
|  | 4821 | +                * - no web led (wired to 2nd IDE reset for staggered startup) | 
|---|
|  | 4822 | +                */ | 
|---|
|  | 4823 | + | 
|---|
|  | 4824 | +               /* read the current state of lightbar */ | 
|---|
|  | 4825 | +               pci_read_config_byte(led_dev, RAQ3_SHUTLOGO_ADDR, &tmp); | 
|---|
|  | 4826 | +               if (newstate & LED_COBALTLOGO) { | 
|---|
|  | 4827 | +                       tmp |= QUBE3_LIGHTBAR_ON; | 
|---|
|  | 4828 | +               } else { | 
|---|
|  | 4829 | +                       tmp &= ~QUBE3_LIGHTBAR_ON; | 
|---|
|  | 4830 | +               } | 
|---|
|  | 4831 | + | 
|---|
|  | 4832 | +               /* write new lightbar state */ | 
|---|
|  | 4833 | +               pci_write_config_byte(led_dev, RAQ3_SHUTLOGO_ADDR, tmp); | 
|---|
|  | 4834 | +       } else if (cobt_is_monterey()) { | 
|---|
|  | 4835 | +               unsigned int tmp = 0; | 
|---|
|  | 4836 | +               u8 val; | 
|---|
|  | 4837 | +               unsigned long flags; | 
|---|
|  | 4838 | + | 
|---|
|  | 4839 | +               if (newstate & LED_WEBLIGHT) { | 
|---|
|  | 4840 | +                       tmp |= MONTEREY_FPLED_WEB; | 
|---|
|  | 4841 | +               } | 
|---|
|  | 4842 | +               if (newstate & LED_ETH0_TXRX) { | 
|---|
|  | 4843 | +                       tmp |= MONTEREY_FPLED_ETH0_TXRX; | 
|---|
|  | 4844 | +               } | 
|---|
|  | 4845 | +               if (newstate & LED_ETH0_LINK) { | 
|---|
|  | 4846 | +                       tmp |= MONTEREY_FPLED_ETH0_LINK; | 
|---|
|  | 4847 | +               } | 
|---|
|  | 4848 | +               if (newstate & LED_ETH1_TXRX) { | 
|---|
|  | 4849 | +                       tmp |= MONTEREY_FPLED_ETH1_TXRX; | 
|---|
|  | 4850 | +               } | 
|---|
|  | 4851 | +               if (newstate & LED_ETH1_LINK) { | 
|---|
|  | 4852 | +                       tmp |= MONTEREY_FPLED_ETH1_LINK; | 
|---|
|  | 4853 | +               } | 
|---|
|  | 4854 | +               if (newstate & LED_DISK0) { | 
|---|
|  | 4855 | +                       tmp |= MONTEREY_FPLED_DISK0; | 
|---|
|  | 4856 | +               } | 
|---|
|  | 4857 | +               if (newstate & LED_DISK1) { | 
|---|
|  | 4858 | +                       tmp |= MONTEREY_FPLED_DISK1; | 
|---|
|  | 4859 | +               } | 
|---|
|  | 4860 | +               if (newstate & LED_DISK2) { | 
|---|
|  | 4861 | +                       tmp |= MONTEREY_FPLED_DISK2; | 
|---|
|  | 4862 | +               } | 
|---|
|  | 4863 | +               if (newstate & LED_DISK3) { | 
|---|
|  | 4864 | +                       tmp |= MONTEREY_FPLED_DISK3; | 
|---|
|  | 4865 | +               } | 
|---|
|  | 4866 | +               /* 3 LED's are unused on Monterey, but we support them */ | 
|---|
|  | 4867 | +               if (newstate & LED_MONTEREY_UNUSED0) { | 
|---|
|  | 4868 | +                       tmp |= MONTEREY_FPLED13; | 
|---|
|  | 4869 | +               } | 
|---|
|  | 4870 | +               if (newstate & LED_MONTEREY_UNUSED1) { | 
|---|
|  | 4871 | +                       tmp |= MONTEREY_FPLED14; | 
|---|
|  | 4872 | +               } | 
|---|
|  | 4873 | +               if (newstate & LED_MONTEREY_UNUSED2) { | 
|---|
|  | 4874 | +                       tmp |= MONTEREY_FPLED15; | 
|---|
|  | 4875 | +               } | 
|---|
|  | 4876 | +               /* I2C controlled front-panel lights */ | 
|---|
|  | 4877 | +               cobalt_i2c_write_byte(COBALT_I2C_DEV_LED_I, 0, tmp & 0xff); | 
|---|
|  | 4878 | +               cobalt_i2c_write_byte(COBALT_I2C_DEV_LED_II, 0, tmp >> 8); | 
|---|
|  | 4879 | + | 
|---|
|  | 4880 | +               /* drive sled LEDs are on a different i2c device */ | 
|---|
|  | 4881 | +               tmp = 0xf0; /* high nibble means something else */ | 
|---|
|  | 4882 | +               if (newstate * LED_SLED0) | 
|---|
|  | 4883 | +                       tmp |= MONTEREY_SLED0; | 
|---|
|  | 4884 | +               if (newstate * LED_SLED1) | 
|---|
|  | 4885 | +                       tmp |= MONTEREY_SLED1; | 
|---|
|  | 4886 | +               if (newstate * LED_SLED2) | 
|---|
|  | 4887 | +                       tmp |= MONTEREY_SLED2; | 
|---|
|  | 4888 | +               if (newstate * LED_SLED3) | 
|---|
|  | 4889 | +                       tmp |= MONTEREY_SLED3; | 
|---|
|  | 4890 | +               cobalt_i2c_write_byte(COBALT_I2C_DEV_RULER, 0, tmp); | 
|---|
|  | 4891 | + | 
|---|
|  | 4892 | +               /* sysfault and logo are in APC page of nvram */ | 
|---|
|  | 4893 | +               spin_lock_irqsave(&rtc_lock, flags); | 
|---|
|  | 4894 | +               superio_set_rtc_bank(PC87317_RTC_BANK_APC); | 
|---|
|  | 4895 | +               val = CMOS_READ(PC87317_APCR4); | 
|---|
|  | 4896 | + | 
|---|
|  | 4897 | +               /* reverse polarity */ | 
|---|
|  | 4898 | +               if (newstate & LED_COBALTLOGO) { | 
|---|
|  | 4899 | +                       val &= ~MONTEREY_LOGOLED_BIT; /* logo is on */ | 
|---|
|  | 4900 | +               } else { | 
|---|
|  | 4901 | +                       val |= MONTEREY_LOGOLED_BIT; /* logo is off */ | 
|---|
|  | 4902 | +               } | 
|---|
|  | 4903 | + | 
|---|
|  | 4904 | +               if (newstate & LED_SYSFAULT) { | 
|---|
|  | 4905 | +                       val |= MONTEREY_SYSFAULTLED_BIT; | 
|---|
|  | 4906 | +               } else { | 
|---|
|  | 4907 | +                       val &= ~MONTEREY_SYSFAULTLED_BIT; | 
|---|
|  | 4908 | +               } | 
|---|
|  | 4909 | + | 
|---|
|  | 4910 | +               CMOS_WRITE(val, PC87317_APCR4); | 
|---|
|  | 4911 | +               superio_set_rtc_bank(PC87317_RTC_BANK_MAIN); | 
|---|
|  | 4912 | +               spin_unlock_irqrestore(&rtc_lock, flags); | 
|---|
|  | 4913 | +       } else if (cobt_is_alpine()) { | 
|---|
|  | 4914 | +               unsigned char val; | 
|---|
|  | 4915 | + | 
|---|
|  | 4916 | +               /* web LED is reverse polarity */ | 
|---|
|  | 4917 | +               val = inb(ALPINE_WEBLED_PORT); | 
|---|
|  | 4918 | +               if (newstate & LED_WEBLIGHT) { | 
|---|
|  | 4919 | +                       val &= ~ALPINE_WEBLED_BIT; | 
|---|
|  | 4920 | +               } else { | 
|---|
|  | 4921 | +                       val |= ALPINE_WEBLED_BIT; | 
|---|
|  | 4922 | +               } | 
|---|
|  | 4923 | +               outb(val, ALPINE_WEBLED_PORT); | 
|---|
|  | 4924 | + | 
|---|
|  | 4925 | +                    /* | 
|---|
|  | 4926 | +                     * the power led is controled by switching the pin between | 
|---|
|  | 4927 | +                     * a GPIO pin (on) and a LED pin (off) | 
|---|
|  | 4928 | +                     */ | 
|---|
|  | 4929 | + | 
|---|
|  | 4930 | +                outb( ALPINE_POWERLED_CFG, 0x2e ); | 
|---|
|  | 4931 | +                val = inb( 0x2f ); | 
|---|
|  | 4932 | +               if (newstate & LED_COBALTLOGO) { | 
|---|
|  | 4933 | +                       val &= ~ALPINE_LOGOLED_BIT; | 
|---|
|  | 4934 | +               } else { | 
|---|
|  | 4935 | +                       val |= ALPINE_LOGOLED_BIT; | 
|---|
|  | 4936 | +               } | 
|---|
|  | 4937 | +                outb( val, 0x2f ); | 
|---|
|  | 4938 | + | 
|---|
|  | 4939 | +               if (newstate & LED_SYSFAULT) { | 
|---|
|  | 4940 | +                    val = ALPINE_SYSFAULTLED_BIT; | 
|---|
|  | 4941 | +               } else { | 
|---|
|  | 4942 | +                    val = 0; | 
|---|
|  | 4943 | +               } | 
|---|
|  | 4944 | + | 
|---|
|  | 4945 | +               outb(val, ALPINE_POWERLED_PORT); | 
|---|
|  | 4946 | +       } | 
|---|
|  | 4947 | +} | 
|---|
|  | 4948 | + | 
|---|
|  | 4949 | +/* blip the front panel leds */ | 
|---|
|  | 4950 | +static void | 
|---|
|  | 4951 | +led_timer_func(unsigned long data) | 
|---|
|  | 4952 | +{ | 
|---|
|  | 4953 | +       unsigned int leds = 0; | 
|---|
|  | 4954 | +       struct led_handler *p; | 
|---|
|  | 4955 | +       unsigned long flags; | 
|---|
|  | 4956 | + | 
|---|
|  | 4957 | +       /* call all registered callbacks */ | 
|---|
|  | 4958 | +       spin_lock_irqsave(&led_handler_lock, flags); | 
|---|
|  | 4959 | +       for (p = led_handler_list; p; p = p->next) { | 
|---|
|  | 4960 | +               leds |= p->function(p->data); | 
|---|
|  | 4961 | +       } | 
|---|
|  | 4962 | +       spin_unlock_irqrestore(&led_handler_lock, flags); | 
|---|
|  | 4963 | + | 
|---|
|  | 4964 | +       /* set the led hardware */ | 
|---|
|  | 4965 | +       spin_lock_irqsave(&led_lock, flags); | 
|---|
|  | 4966 | +       __set_led_hw(led_state | leds | led_blips); | 
|---|
|  | 4967 | +       led_blips = 0; | 
|---|
|  | 4968 | +       spin_unlock_irqrestore(&led_lock, flags); | 
|---|
|  | 4969 | + | 
|---|
|  | 4970 | +       /* re-arm ourself */ | 
|---|
|  | 4971 | +       mod_timer(&timer, jiffies + FPLED_DEFAULT_HZ); | 
|---|
|  | 4972 | +} | 
|---|
|  | 4973 | + | 
|---|
|  | 4974 | +static void | 
|---|
|  | 4975 | +__cobalt_led_set(const unsigned int leds) | 
|---|
|  | 4976 | +{ | 
|---|
|  | 4977 | +       led_state = leds; | 
|---|
|  | 4978 | +       __set_led_hw(leds); | 
|---|
|  | 4979 | +} | 
|---|
|  | 4980 | + | 
|---|
|  | 4981 | +void | 
|---|
|  | 4982 | +cobalt_led_set(const unsigned int leds) | 
|---|
|  | 4983 | +{ | 
|---|
|  | 4984 | +       unsigned long flags; | 
|---|
|  | 4985 | +       spin_lock_irqsave(&led_lock, flags); | 
|---|
|  | 4986 | +       __cobalt_led_set(leds); | 
|---|
|  | 4987 | +       spin_unlock_irqrestore(&led_lock, flags); | 
|---|
|  | 4988 | +} | 
|---|
|  | 4989 | + | 
|---|
|  | 4990 | +void | 
|---|
|  | 4991 | +cobalt_led_set_bits(const unsigned int leds) | 
|---|
|  | 4992 | +{ | 
|---|
|  | 4993 | +       unsigned long flags; | 
|---|
|  | 4994 | +       spin_lock_irqsave(&led_lock, flags); | 
|---|
|  | 4995 | +       __cobalt_led_set(led_state | leds); | 
|---|
|  | 4996 | +       spin_unlock_irqrestore(&led_lock, flags); | 
|---|
|  | 4997 | +} | 
|---|
|  | 4998 | + | 
|---|
|  | 4999 | +void | 
|---|
|  | 5000 | +cobalt_led_clear_bits(const unsigned int leds) | 
|---|
|  | 5001 | +{ | 
|---|
|  | 5002 | +       unsigned long flags; | 
|---|
|  | 5003 | +       spin_lock_irqsave(&led_lock, flags); | 
|---|
|  | 5004 | +       __cobalt_led_set(led_state & ~leds); | 
|---|
|  | 5005 | +       spin_unlock_irqrestore(&led_lock, flags); | 
|---|
|  | 5006 | +} | 
|---|
|  | 5007 | + | 
|---|
|  | 5008 | +static void | 
|---|
|  | 5009 | +__cobalt_led_set_lazy(const unsigned int leds) | 
|---|
|  | 5010 | +{ | 
|---|
|  | 5011 | +       /* the next led timer run will catch these changes */ | 
|---|
|  | 5012 | +       led_state = leds; | 
|---|
|  | 5013 | +       /* remember lights that were 'blipped' to force an edge */ | 
|---|
|  | 5014 | +       led_blips |= leds; | 
|---|
|  | 5015 | +} | 
|---|
|  | 5016 | + | 
|---|
|  | 5017 | +void | 
|---|
|  | 5018 | +cobalt_led_set_lazy(const unsigned int leds) | 
|---|
|  | 5019 | +{ | 
|---|
|  | 5020 | +       unsigned long flags; | 
|---|
|  | 5021 | +       spin_lock_irqsave(&led_lock, flags); | 
|---|
|  | 5022 | +       __cobalt_led_set_lazy(leds); | 
|---|
|  | 5023 | +       spin_unlock_irqrestore(&led_lock, flags); | 
|---|
|  | 5024 | +} | 
|---|
|  | 5025 | + | 
|---|
|  | 5026 | +void | 
|---|
|  | 5027 | +cobalt_led_set_bits_lazy(const unsigned int leds) | 
|---|
|  | 5028 | +{ | 
|---|
|  | 5029 | +       unsigned long flags; | 
|---|
|  | 5030 | +       spin_lock_irqsave(&led_lock, flags); | 
|---|
|  | 5031 | +       __cobalt_led_set_lazy(led_state | leds); | 
|---|
|  | 5032 | +       spin_unlock_irqrestore(&led_lock, flags); | 
|---|
|  | 5033 | +} | 
|---|
|  | 5034 | + | 
|---|
|  | 5035 | +void | 
|---|
|  | 5036 | +cobalt_led_clear_bits_lazy(const unsigned int leds) | 
|---|
|  | 5037 | +{ | 
|---|
|  | 5038 | +       unsigned long flags; | 
|---|
|  | 5039 | +       spin_lock_irqsave(&led_lock, flags); | 
|---|
|  | 5040 | +       __cobalt_led_set_lazy(led_state & ~leds); | 
|---|
|  | 5041 | +       spin_unlock_irqrestore(&led_lock, flags); | 
|---|
|  | 5042 | +} | 
|---|
|  | 5043 | + | 
|---|
|  | 5044 | +unsigned int | 
|---|
|  | 5045 | +cobalt_led_get(void) | 
|---|
|  | 5046 | +{ | 
|---|
|  | 5047 | +       unsigned int r; | 
|---|
|  | 5048 | +       unsigned long flags; | 
|---|
|  | 5049 | + | 
|---|
|  | 5050 | +       spin_lock_irqsave(&led_lock, flags); | 
|---|
|  | 5051 | +       r = led_state; | 
|---|
|  | 5052 | +       spin_unlock_irqrestore(&led_lock, flags); | 
|---|
|  | 5053 | + | 
|---|
|  | 5054 | +       return r; | 
|---|
|  | 5055 | +} | 
|---|
|  | 5056 | + | 
|---|
|  | 5057 | +int | 
|---|
|  | 5058 | +cobalt_fpled_register(unsigned int (*function)(void *), void *data) | 
|---|
|  | 5059 | +{ | 
|---|
|  | 5060 | +       struct led_handler *newh; | 
|---|
|  | 5061 | +       unsigned long flags; | 
|---|
|  | 5062 | + | 
|---|
|  | 5063 | +       newh = kmalloc(sizeof(*newh), GFP_ATOMIC); | 
|---|
|  | 5064 | +       if (!newh) { | 
|---|
|  | 5065 | +               EPRINTK("can't allocate memory for handler %p(%p)\n", | 
|---|
|  | 5066 | +                       function, data); | 
|---|
|  | 5067 | +               return -1; | 
|---|
|  | 5068 | +       } | 
|---|
|  | 5069 | + | 
|---|
|  | 5070 | +       spin_lock_irqsave(&led_handler_lock, flags); | 
|---|
|  | 5071 | + | 
|---|
|  | 5072 | +       /* head insert */ | 
|---|
|  | 5073 | +       newh->function = function; | 
|---|
|  | 5074 | +       newh->data = data; | 
|---|
|  | 5075 | +       newh->next = led_handler_list; | 
|---|
|  | 5076 | +       newh->prev = NULL; | 
|---|
|  | 5077 | +       if (led_handler_list) { | 
|---|
|  | 5078 | +               led_handler_list->prev = newh; | 
|---|
|  | 5079 | +       } | 
|---|
|  | 5080 | +       led_handler_list = newh; | 
|---|
|  | 5081 | + | 
|---|
|  | 5082 | +       spin_unlock_irqrestore(&led_handler_lock, flags); | 
|---|
|  | 5083 | + | 
|---|
|  | 5084 | +       return 0; | 
|---|
|  | 5085 | +} | 
|---|
|  | 5086 | + | 
|---|
|  | 5087 | +int | 
|---|
|  | 5088 | +cobalt_fpled_unregister(unsigned int (*function)(void *), void *data) | 
|---|
|  | 5089 | +{ | 
|---|
|  | 5090 | +       int r = -1; | 
|---|
|  | 5091 | +       struct led_handler *p; | 
|---|
|  | 5092 | +       unsigned long flags; | 
|---|
|  | 5093 | + | 
|---|
|  | 5094 | +       spin_lock_irqsave(&led_handler_lock, flags); | 
|---|
|  | 5095 | + | 
|---|
|  | 5096 | +       for (p = led_handler_list; p; p = p->next) { | 
|---|
|  | 5097 | +               if (p->function == function && p->data == data) { | 
|---|
|  | 5098 | +                       if (p->prev) { | 
|---|
|  | 5099 | +                               p->prev->next = p->next; | 
|---|
|  | 5100 | +                       } | 
|---|
|  | 5101 | +                       if (p->next) { | 
|---|
|  | 5102 | +                               p->next->prev = p->prev; | 
|---|
|  | 5103 | +                       } | 
|---|
|  | 5104 | +                       r = 0; | 
|---|
|  | 5105 | +                       break; | 
|---|
|  | 5106 | +               } | 
|---|
|  | 5107 | +       } | 
|---|
|  | 5108 | + | 
|---|
|  | 5109 | +       spin_unlock_irqrestore(&led_handler_lock, flags); | 
|---|
|  | 5110 | + | 
|---|
|  | 5111 | +       return r; | 
|---|
|  | 5112 | +} | 
|---|
|  | 5113 | + | 
|---|
|  | 5114 | +int __init | 
|---|
|  | 5115 | +cobalt_led_init(void) | 
|---|
|  | 5116 | +{ | 
|---|
|  | 5117 | +       unsigned int leds = LED_SHUTDOWN | LED_COBALTLOGO; | 
|---|
|  | 5118 | + | 
|---|
|  | 5119 | +    printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", LED_DRIVER,LED_DRIVER_VMAJ,LED_DRIVER_VMIN); | 
|---|
|  | 5120 | + | 
|---|
|  | 5121 | +       if (cobt_is_3k()) { | 
|---|
|  | 5122 | +               /* LEDs for RaQ3/4 and Qube3 are on the PMU */ | 
|---|
|  | 5123 | +               led_dev = pci_find_device(PCI_VENDOR_ID_AL, | 
|---|
|  | 5124 | +                       PCI_DEVICE_ID_AL_M7101, NULL); | 
|---|
|  | 5125 | +               if (!led_dev) { | 
|---|
|  | 5126 | +                       EPRINTK("can't find PMU for LED control\n"); | 
|---|
|  | 5127 | +                       return -1; | 
|---|
|  | 5128 | +               } | 
|---|
|  | 5129 | +       } | 
|---|
|  | 5130 | + | 
|---|
|  | 5131 | +       /* setup up timer for fp leds */ | 
|---|
|  | 5132 | +       init_timer(&timer); | 
|---|
|  | 5133 | +       timer.expires = jiffies + FPLED_DEFAULT_HZ; | 
|---|
|  | 5134 | +       timer.data = 0; | 
|---|
|  | 5135 | +       timer.function = &led_timer_func; | 
|---|
|  | 5136 | +       add_timer(&timer); | 
|---|
|  | 5137 | + | 
|---|
|  | 5138 | +       /* set the initial state */ | 
|---|
|  | 5139 | +       leds |= cobalt_cmos_read_flag(COBT_CMOS_SYSFAULT_FLAG) ? | 
|---|
|  | 5140 | +               LED_SYSFAULT : 0; | 
|---|
|  | 5141 | +       led_state = leds; | 
|---|
|  | 5142 | +       __set_led_hw(leds); | 
|---|
|  | 5143 | + | 
|---|
|  | 5144 | +       return 0; | 
|---|
|  | 5145 | +} | 
|---|
|  | 5146 | + | 
|---|
|  | 5147 | +#endif /* CONFIG_COBALT_LED */ | 
|---|
|  | 5148 | diff -Naur linux-2.6.20.orig/drivers/cobalt/net.c linux-2.6.20/drivers/cobalt/net.c | 
|---|
|  | 5149 | --- linux-2.6.20.orig/drivers/cobalt/net.c      1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 5150 | +++ linux-2.6.20/drivers/cobalt/net.c   2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 5151 | @@ -0,0 +1,133 @@ | 
|---|
|  | 5152 | +/* | 
|---|
|  | 5153 | + * cobalt net wrappers | 
|---|
|  | 5154 | + * Copyright (c) 2000, Cobalt Networks, Inc. | 
|---|
|  | 5155 | + * Copyright (c) 2001, Sun Microsystems, Inc. | 
|---|
|  | 5156 | + * $Id: net.c,v 1.11 2001/10/27 00:40:24 thockin Exp $ | 
|---|
|  | 5157 | + * author: thockin@sun.com | 
|---|
|  | 5158 | + * | 
|---|
|  | 5159 | + * This should be SMP safe.  The only critical data is the list of devices. | 
|---|
|  | 5160 | + * The LED handler runs at timer-interrupt, so we must use the IRQ safe forms | 
|---|
|  | 5161 | + * of the locks. --TPH | 
|---|
|  | 5162 | + */ | 
|---|
|  | 5163 | + | 
|---|
|  | 5164 | +#include <stdarg.h> | 
|---|
|  | 5165 | +#include <stddef.h> | 
|---|
|  | 5166 | +#include <linux/init.h> | 
|---|
|  | 5167 | +#include <linux/config.h> | 
|---|
|  | 5168 | +#include <linux/pci.h> | 
|---|
|  | 5169 | +#include <linux/ioport.h> | 
|---|
|  | 5170 | +#include <linux/netdevice.h> | 
|---|
|  | 5171 | +#include <asm/io.h> | 
|---|
|  | 5172 | + | 
|---|
|  | 5173 | +#include <cobalt/cobalt.h> | 
|---|
|  | 5174 | +#include <cobalt/net.h> | 
|---|
|  | 5175 | +#include <cobalt/led.h> | 
|---|
|  | 5176 | + | 
|---|
|  | 5177 | +#define MAX_COBT_NETDEVS       2 | 
|---|
|  | 5178 | +static struct net_device *netdevs[MAX_COBT_NETDEVS]; | 
|---|
|  | 5179 | +static int n_netdevs; | 
|---|
|  | 5180 | +static spinlock_t cobaltnet_lock = SPIN_LOCK_UNLOCKED; | 
|---|
|  | 5181 | + | 
|---|
|  | 5182 | +#if defined(CONFIG_COBALT_LED) | 
|---|
|  | 5183 | +static unsigned int | 
|---|
|  | 5184 | +net_led_handler(void *data) | 
|---|
|  | 5185 | +{ | 
|---|
|  | 5186 | +       int i; | 
|---|
|  | 5187 | +       unsigned int leds = 0; | 
|---|
|  | 5188 | +       static int txrxmap[MAX_COBT_NETDEVS] = {LED_ETH0_TXRX, LED_ETH1_TXRX}; | 
|---|
|  | 5189 | +       static int linkmap[MAX_COBT_NETDEVS] = {LED_ETH0_LINK, LED_ETH1_LINK}; | 
|---|
|  | 5190 | +       unsigned long flags; | 
|---|
|  | 5191 | +       static unsigned long net_old[MAX_COBT_NETDEVS]; | 
|---|
|  | 5192 | + | 
|---|
|  | 5193 | +       spin_lock_irqsave(&cobaltnet_lock, flags); | 
|---|
|  | 5194 | + | 
|---|
|  | 5195 | +       for (i = 0; i < n_netdevs; i++) { | 
|---|
|  | 5196 | +               unsigned long txrxstate; | 
|---|
|  | 5197 | +               struct net_device *dev = netdevs[i]; | 
|---|
|  | 5198 | +               if (!dev) { | 
|---|
|  | 5199 | +                       continue; | 
|---|
|  | 5200 | +               } | 
|---|
|  | 5201 | +               /* check for link */ | 
|---|
|  | 5202 | +               if (netif_running(dev) && netif_carrier_ok(dev)) { | 
|---|
|  | 5203 | +                       leds |= linkmap[i]; | 
|---|
|  | 5204 | +               } | 
|---|
|  | 5205 | +               /* check for tx/rx */ | 
|---|
|  | 5206 | +               txrxstate = dev->trans_start ^ dev->last_rx; | 
|---|
|  | 5207 | +               if (txrxstate != net_old[i]) { | 
|---|
|  | 5208 | +                       leds |= txrxmap[i]; | 
|---|
|  | 5209 | +                       net_old[i] = txrxstate; | 
|---|
|  | 5210 | +               } | 
|---|
|  | 5211 | +       } | 
|---|
|  | 5212 | + | 
|---|
|  | 5213 | +       spin_unlock_irqrestore(&cobaltnet_lock, flags); | 
|---|
|  | 5214 | + | 
|---|
|  | 5215 | +       return leds; | 
|---|
|  | 5216 | +} | 
|---|
|  | 5217 | +#endif | 
|---|
|  | 5218 | + | 
|---|
|  | 5219 | +/* | 
|---|
|  | 5220 | + * We try to be VERY explicit here.  Fine for now, may eventually break down. | 
|---|
|  | 5221 | + */ | 
|---|
|  | 5222 | +void | 
|---|
|  | 5223 | +cobalt_net_register(struct net_device *ndev) | 
|---|
|  | 5224 | +{ | 
|---|
|  | 5225 | +       unsigned long flags; | 
|---|
|  | 5226 | +       int i; | 
|---|
|  | 5227 | + | 
|---|
|  | 5228 | +       if (!ndev) { | 
|---|
|  | 5229 | +               return; | 
|---|
|  | 5230 | +       } | 
|---|
|  | 5231 | + | 
|---|
|  | 5232 | +       /* we'll track the first MAX_COBT_NETDEVS NICs */ | 
|---|
|  | 5233 | +       if (n_netdevs >= MAX_COBT_NETDEVS) { | 
|---|
|  | 5234 | +               return; | 
|---|
|  | 5235 | +       } | 
|---|
|  | 5236 | + | 
|---|
|  | 5237 | +       spin_lock_irqsave(&cobaltnet_lock, flags); | 
|---|
|  | 5238 | + | 
|---|
|  | 5239 | +       /* find a free slot */ | 
|---|
|  | 5240 | +       for (i = 0; i < MAX_COBT_NETDEVS; i++) { | 
|---|
|  | 5241 | +               if (!netdevs[i]) { | 
|---|
|  | 5242 | +                       netdevs[i] = ndev; | 
|---|
|  | 5243 | +                       n_netdevs++; | 
|---|
|  | 5244 | +                       break; | 
|---|
|  | 5245 | +               } | 
|---|
|  | 5246 | +       } | 
|---|
|  | 5247 | + | 
|---|
|  | 5248 | +       spin_unlock_irqrestore(&cobaltnet_lock, flags); | 
|---|
|  | 5249 | +} | 
|---|
|  | 5250 | + | 
|---|
|  | 5251 | +void | 
|---|
|  | 5252 | +cobalt_net_unregister(struct net_device *ndev) | 
|---|
|  | 5253 | +{ | 
|---|
|  | 5254 | +       int i; | 
|---|
|  | 5255 | +       unsigned long flags; | 
|---|
|  | 5256 | + | 
|---|
|  | 5257 | +       if (!ndev) { | 
|---|
|  | 5258 | +               return; | 
|---|
|  | 5259 | +       } | 
|---|
|  | 5260 | + | 
|---|
|  | 5261 | +       spin_lock_irqsave(&cobaltnet_lock, flags); | 
|---|
|  | 5262 | + | 
|---|
|  | 5263 | +       /* try to remove it from the list */ | 
|---|
|  | 5264 | +       for (i = 0; i < MAX_COBT_NETDEVS; i++) { | 
|---|
|  | 5265 | +               if (netdevs[i] == ndev) { | 
|---|
|  | 5266 | +                       netdevs[i] = NULL; | 
|---|
|  | 5267 | +                       n_netdevs--; | 
|---|
|  | 5268 | +                       break; | 
|---|
|  | 5269 | +               } | 
|---|
|  | 5270 | +       } | 
|---|
|  | 5271 | + | 
|---|
|  | 5272 | +       spin_unlock_irqrestore(&cobaltnet_lock, flags); | 
|---|
|  | 5273 | +} | 
|---|
|  | 5274 | + | 
|---|
|  | 5275 | +int __init | 
|---|
|  | 5276 | +cobalt_net_init(void) | 
|---|
|  | 5277 | +{ | 
|---|
|  | 5278 | +#if defined(CONFIG_COBALT_LED) | 
|---|
|  | 5279 | +       /* register an LED handler */ | 
|---|
|  | 5280 | +       cobalt_fpled_register(net_led_handler, NULL); | 
|---|
|  | 5281 | +#endif | 
|---|
|  | 5282 | + | 
|---|
|  | 5283 | +       return 0; | 
|---|
|  | 5284 | +} | 
|---|
|  | 5285 | diff -Naur linux-2.6.20.orig/drivers/cobalt/raminfo.c linux-2.6.20/drivers/cobalt/raminfo.c | 
|---|
|  | 5286 | --- linux-2.6.20.orig/drivers/cobalt/raminfo.c  1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 5287 | +++ linux-2.6.20/drivers/cobalt/raminfo.c       2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 5288 | @@ -0,0 +1,320 @@ | 
|---|
|  | 5289 | +/* $Id: raminfo.c,v 1.7 2001/10/29 22:21:36 thockin Exp $ | 
|---|
|  | 5290 | + * | 
|---|
|  | 5291 | + * Copyright (c) 2000-2001 Sun Microsystems, Inc. | 
|---|
|  | 5292 | + * All Rights Reserved. | 
|---|
|  | 5293 | + * | 
|---|
|  | 5294 | + * This is SMP safe - the init runs once on load, and the rest is just | 
|---|
|  | 5295 | + * printing information. --TPH | 
|---|
|  | 5296 | + */ | 
|---|
|  | 5297 | +#include <linux/config.h> | 
|---|
|  | 5298 | + | 
|---|
|  | 5299 | +#if defined(CONFIG_COBALT_RAMINFO) || defined(CONFIG_COBALT_RAMINFO_MODULE) | 
|---|
|  | 5300 | + | 
|---|
|  | 5301 | +#include <linux/module.h> | 
|---|
|  | 5302 | +#include <linux/init.h> | 
|---|
|  | 5303 | +#include <linux/pci.h> | 
|---|
|  | 5304 | +#include <linux/proc_fs.h> | 
|---|
|  | 5305 | + | 
|---|
|  | 5306 | +#include <cobalt/cobalt.h> | 
|---|
|  | 5307 | +#include <cobalt/systype.h> | 
|---|
|  | 5308 | + | 
|---|
|  | 5309 | +#define RAM_DRIVER                     "Cobalt Networks RAM Info driver" | 
|---|
|  | 5310 | +#define RAM_DRIVER_VMAJ                1 | 
|---|
|  | 5311 | +#define RAM_DRIVER_VMIN                0 | 
|---|
|  | 5312 | + | 
|---|
|  | 5313 | +#define MAX_DIMM_SLOTS 4 | 
|---|
|  | 5314 | + | 
|---|
|  | 5315 | +enum dimm_t { | 
|---|
|  | 5316 | +       DIMM_TYPE_FPM_DRAM, | 
|---|
|  | 5317 | +       DIMM_TYPE_EDO_DRAM, | 
|---|
|  | 5318 | +       DIMM_TYPE_REG_SDRAM, | 
|---|
|  | 5319 | +       DIMM_TYPE_SDRAM | 
|---|
|  | 5320 | +}; | 
|---|
|  | 5321 | + | 
|---|
|  | 5322 | +static char *dimm_desc[] = { | 
|---|
|  | 5323 | +       "Fast-page Mode DRAM", | 
|---|
|  | 5324 | +       "EDO DRAM", | 
|---|
|  | 5325 | +       "Registered SDRAM", | 
|---|
|  | 5326 | +       "SDRAM", | 
|---|
|  | 5327 | +}; | 
|---|
|  | 5328 | + | 
|---|
|  | 5329 | +struct dimm_slot { | 
|---|
|  | 5330 | +       int num; | 
|---|
|  | 5331 | +       enum dimm_t type; | 
|---|
|  | 5332 | +       uint16_t size; | 
|---|
|  | 5333 | +       int ecc; | 
|---|
|  | 5334 | +}; | 
|---|
|  | 5335 | + | 
|---|
|  | 5336 | +struct raminfo { | 
|---|
|  | 5337 | +       int total; | 
|---|
|  | 5338 | +       int (*query)(struct dimm_slot *); | 
|---|
|  | 5339 | +       struct pci_dev *dev; | 
|---|
|  | 5340 | +       struct dimm_slot *dimm; | 
|---|
|  | 5341 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 5342 | +       struct proc_dir_entry *proc; | 
|---|
|  | 5343 | +#endif /* CONFIG_PROC_FS */ | 
|---|
|  | 5344 | +}; | 
|---|
|  | 5345 | + | 
|---|
|  | 5346 | +/*########################################################################*/ | 
|---|
|  | 5347 | + | 
|---|
|  | 5348 | +static int serverworks_le_dimm_info(struct dimm_slot *); | 
|---|
|  | 5349 | +static int ali_1541_dimm_info(struct dimm_slot *); | 
|---|
|  | 5350 | +static int raminfo_read_proc(char*, char**, off_t, int, int*, void*); | 
|---|
|  | 5351 | + | 
|---|
|  | 5352 | +/* RaQ-3, RaQ-4, Qube-3 | 
|---|
|  | 5353 | + * - uses ALI M1541 for memory controller | 
|---|
|  | 5354 | + * - has 2 dimm slots */ | 
|---|
|  | 5355 | +static struct raminfo gen3_raminfo = { | 
|---|
|  | 5356 | +       total: 2, | 
|---|
|  | 5357 | +       query: ali_1541_dimm_info | 
|---|
|  | 5358 | +}; | 
|---|
|  | 5359 | +/* RaQ-XTR (Monterey) | 
|---|
|  | 5360 | + * - uses ServerWorks CNB30LE for Memory Controller | 
|---|
|  | 5361 | + * - has 4 dimm slots */ | 
|---|
|  | 5362 | +static struct raminfo gen5_monterey_raminfo = { | 
|---|
|  | 5363 | +       total: 4, | 
|---|
|  | 5364 | +       query: serverworks_le_dimm_info | 
|---|
|  | 5365 | +}; | 
|---|
|  | 5366 | +/* RaQ (Alpine) | 
|---|
|  | 5367 | + * - uses ServerWorks CNB30LE for Memory Controller | 
|---|
|  | 5368 | + * - has 2 dimm slots */ | 
|---|
|  | 5369 | +static struct raminfo gen5_alpine_raminfo = { | 
|---|
|  | 5370 | +       total: 2, | 
|---|
|  | 5371 | +       query: serverworks_le_dimm_info | 
|---|
|  | 5372 | +}; | 
|---|
|  | 5373 | + | 
|---|
|  | 5374 | +static struct raminfo *sys_raminfo; | 
|---|
|  | 5375 | + | 
|---|
|  | 5376 | +/*########################################################################*/ | 
|---|
|  | 5377 | + | 
|---|
|  | 5378 | +#define SERVERWORKS_DRAM_MRPR          (0x90) | 
|---|
|  | 5379 | +#define SERVERWORKS_DRAM_MRAR(slot)    (0x7c + (slot)) | 
|---|
|  | 5380 | +#define SERVERWORKS_DRAM_ECCR          (0xe0) | 
|---|
|  | 5381 | + | 
|---|
|  | 5382 | +static int | 
|---|
|  | 5383 | +serverworks_le_dimm_info(struct dimm_slot *dimm) | 
|---|
|  | 5384 | +{ | 
|---|
|  | 5385 | +       int row; | 
|---|
|  | 5386 | +       uint8_t rar, active, eccr; | 
|---|
|  | 5387 | +       uint16_t ma_map[] = { | 
|---|
|  | 5388 | +               32, 16, 32, 256, 512, 128, 128, 64, 256, 128, 64, 64, 128, | 
|---|
|  | 5389 | +       }; | 
|---|
|  | 5390 | + | 
|---|
|  | 5391 | +       if (!sys_raminfo || !sys_raminfo->dev || !dimm) | 
|---|
|  | 5392 | +               return -ENOSYS; | 
|---|
|  | 5393 | + | 
|---|
|  | 5394 | +       pci_read_config_byte(sys_raminfo->dev, | 
|---|
|  | 5395 | +                            SERVERWORKS_DRAM_MRPR, &active); | 
|---|
|  | 5396 | +       pci_read_config_byte(sys_raminfo->dev, | 
|---|
|  | 5397 | +                            SERVERWORKS_DRAM_MRAR(dimm->num), &rar); | 
|---|
|  | 5398 | + | 
|---|
|  | 5399 | +       /* serverworks uses only registered sdram */ | 
|---|
|  | 5400 | +       dimm->type = DIMM_TYPE_REG_SDRAM; | 
|---|
|  | 5401 | +       dimm->size = 0; | 
|---|
|  | 5402 | + | 
|---|
|  | 5403 | +       /* check to see if ECC is enabled (bit 4 of reg 0xE0) */ | 
|---|
|  | 5404 | +       pci_read_config_byte(sys_raminfo->dev, | 
|---|
|  | 5405 | +                            SERVERWORKS_DRAM_ECCR, &eccr); | 
|---|
|  | 5406 | +       dimm->ecc = (eccr & (1<<2)) ? 1 : 0; | 
|---|
|  | 5407 | + | 
|---|
|  | 5408 | +       /* two rows for each dimm slot */ | 
|---|
|  | 5409 | +       for (row=2*dimm->num; row<=(2*dimm->num+1); row++) { | 
|---|
|  | 5410 | +               /* each active row will have corresponding bit | 
|---|
|  | 5411 | +                * set in the Memory Row Presence Register */ | 
|---|
|  | 5412 | +               if (active & (1 << row)) { | 
|---|
|  | 5413 | +                       /* lookup size ma_map table */ | 
|---|
|  | 5414 | +                       dimm->size += ma_map[ rar & 0xf ]; | 
|---|
|  | 5415 | +               } | 
|---|
|  | 5416 | +               /* two rows per RAR register, bits 7-4 and bits 3-0 */ | 
|---|
|  | 5417 | +               rar >>= 4; | 
|---|
|  | 5418 | +       } | 
|---|
|  | 5419 | + | 
|---|
|  | 5420 | +       return 0; | 
|---|
|  | 5421 | +} | 
|---|
|  | 5422 | + | 
|---|
|  | 5423 | +#define ALI_DRAM_CONF_1(row)           (0x60 + ((row) * 2)) | 
|---|
|  | 5424 | +#define ALI_DRAM_CONF_2(row)           (0x61 + ((row) * 2)) | 
|---|
|  | 5425 | +#define ALI_DIMM_TYPE(d2)              (((d2) >> 4) & 0x3) | 
|---|
|  | 5426 | +#define ALI_DIMM_MMAP(d2)              (((d2) >> 6) & 0x3) | 
|---|
|  | 5427 | +#define ALI_DIMM_SIZE(d1, d2)          (((((d2) & 0xf) << 8) | (d1)) + 1) | 
|---|
|  | 5428 | + | 
|---|
|  | 5429 | +static int | 
|---|
|  | 5430 | +ali_1541_dimm_info(struct dimm_slot *dimm) | 
|---|
|  | 5431 | +{ | 
|---|
|  | 5432 | +       int row; | 
|---|
|  | 5433 | +       uint8_t dbc1, dbc2; | 
|---|
|  | 5434 | + | 
|---|
|  | 5435 | +       if (!sys_raminfo || !sys_raminfo->dev || !dimm) | 
|---|
|  | 5436 | +               return -ENOSYS; | 
|---|
|  | 5437 | + | 
|---|
|  | 5438 | +       dimm->size = 0; | 
|---|
|  | 5439 | +       dimm->ecc  = 0; | 
|---|
|  | 5440 | + | 
|---|
|  | 5441 | +       /* read two rows per dimm (for double-side) */ | 
|---|
|  | 5442 | +       for (row=2*dimm->num; row<=(2*dimm->num + 1); row++) { | 
|---|
|  | 5443 | +               pci_read_config_byte(sys_raminfo->dev, | 
|---|
|  | 5444 | +                                    ALI_DRAM_CONF_2(row), &dbc2); | 
|---|
|  | 5445 | + | 
|---|
|  | 5446 | +               /* row is empty iff dimm type and ma_map are both 0 */ | 
|---|
|  | 5447 | +               if (!ALI_DIMM_TYPE(dbc2) && !ALI_DIMM_MMAP(dbc2)) | 
|---|
|  | 5448 | +                       continue; | 
|---|
|  | 5449 | + | 
|---|
|  | 5450 | +               pci_read_config_byte(sys_raminfo->dev, | 
|---|
|  | 5451 | +                                    ALI_DRAM_CONF_1(row), &dbc1); | 
|---|
|  | 5452 | + | 
|---|
|  | 5453 | +               /* type is bits 4-5 of dimm conf reg 2 */ | 
|---|
|  | 5454 | +               dimm->type = ALI_DIMM_TYPE(dbc2); | 
|---|
|  | 5455 | + | 
|---|
|  | 5456 | +               /* A27-A20 address lines are bits 7-0 of dimm conf reg 1 | 
|---|
|  | 5457 | +                * A31-A28 address lines are bits 3-0 of dimm conf reg 2 */ | 
|---|
|  | 5458 | +               dimm->size = ALI_DIMM_SIZE(dbc1, dbc2); | 
|---|
|  | 5459 | +       } | 
|---|
|  | 5460 | + | 
|---|
|  | 5461 | +       /* the M1541 uses "not less than" policy to determine which row a | 
|---|
|  | 5462 | +        * memory address resides in.  the top address boundary for each | 
|---|
|  | 5463 | +        * row is the maximum memory value minus 1.  so to determine the | 
|---|
|  | 5464 | +        * size of a row you must subtract the size of the previous row. | 
|---|
|  | 5465 | +        * (unless this is slot 0 or the first populated slot) */ | 
|---|
|  | 5466 | +       if (dimm->num > 0 && dimm->size > 0) { | 
|---|
|  | 5467 | +               uint16_t sz; | 
|---|
|  | 5468 | +               pci_read_config_byte(sys_raminfo->dev, | 
|---|
|  | 5469 | +                                    ALI_DRAM_CONF_1(2*dimm->num - 1), &dbc1); | 
|---|
|  | 5470 | +               pci_read_config_byte(sys_raminfo->dev, | 
|---|
|  | 5471 | +                                    ALI_DRAM_CONF_2(2*dimm->num - 1), &dbc2); | 
|---|
|  | 5472 | +               sz = ALI_DIMM_SIZE(dbc1, dbc2); | 
|---|
|  | 5473 | +               dimm->size -= (sz > 1) ? sz : 0; | 
|---|
|  | 5474 | +       } | 
|---|
|  | 5475 | + | 
|---|
|  | 5476 | +       return 0; | 
|---|
|  | 5477 | +} | 
|---|
|  | 5478 | + | 
|---|
|  | 5479 | +int __init | 
|---|
|  | 5480 | +cobalt_raminfo_init(void) | 
|---|
|  | 5481 | +{ | 
|---|
|  | 5482 | +       int j; | 
|---|
|  | 5483 | + | 
|---|
|  | 5484 | +       /* determine system type and find memory controller pci dev | 
|---|
|  | 5485 | +        * so we don't have to do pci lookup for each proc read */ | 
|---|
|  | 5486 | +       if (cobt_is_3k()) { | 
|---|
|  | 5487 | +               sys_raminfo = &gen3_raminfo; | 
|---|
|  | 5488 | +               sys_raminfo->dev = pci_find_device(PCI_VENDOR_ID_AL, | 
|---|
|  | 5489 | +                                  PCI_DEVICE_ID_AL_M1541, NULL); | 
|---|
|  | 5490 | +       } else if (cobt_is_5k()) { | 
|---|
|  | 5491 | +               if (cobt_is_monterey()) { | 
|---|
|  | 5492 | +                       sys_raminfo = &gen5_monterey_raminfo; | 
|---|
|  | 5493 | +               } else if (cobt_is_alpine()) { | 
|---|
|  | 5494 | +                       sys_raminfo = &gen5_alpine_raminfo; | 
|---|
|  | 5495 | +               } else { | 
|---|
|  | 5496 | +                       EPRINTK("unable to identify gen5 board\n"); | 
|---|
|  | 5497 | +                       return -ENOSYS; | 
|---|
|  | 5498 | +               } | 
|---|
|  | 5499 | +               sys_raminfo->dev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, | 
|---|
|  | 5500 | +                                  PCI_DEVICE_ID_SERVERWORKS_LE, NULL); | 
|---|
|  | 5501 | +       } | 
|---|
|  | 5502 | + | 
|---|
|  | 5503 | +       if (!sys_raminfo || !sys_raminfo->dev) { | 
|---|
|  | 5504 | +               EPRINTK("unable to identify system type\n"); | 
|---|
|  | 5505 | +               return -ENOSYS; | 
|---|
|  | 5506 | +       } | 
|---|
|  | 5507 | + | 
|---|
|  | 5508 | +       printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", RAM_DRIVER,RAM_DRIVER_VMAJ,RAM_DRIVER_VMIN); | 
|---|
|  | 5509 | + | 
|---|
|  | 5510 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 5511 | +       /* add entry to /proc filesytem */ | 
|---|
|  | 5512 | +       sys_raminfo->proc = create_proc_entry("raminfo", | 
|---|
|  | 5513 | +                           S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, proc_cobalt); | 
|---|
|  | 5514 | +       if (!sys_raminfo->proc) { | 
|---|
|  | 5515 | +               EPRINTK("can't create /proc/cobalt/raminfo\n"); | 
|---|
|  | 5516 | +               return -ENOENT; | 
|---|
|  | 5517 | +       } | 
|---|
|  | 5518 | +       sys_raminfo->proc->owner = THIS_MODULE; | 
|---|
|  | 5519 | +       sys_raminfo->proc->write_proc = NULL; | 
|---|
|  | 5520 | +       sys_raminfo->proc->read_proc = raminfo_read_proc; | 
|---|
|  | 5521 | +#endif /* CONFIG_PROC_FS */ | 
|---|
|  | 5522 | + | 
|---|
|  | 5523 | +       /* create arrary of dimm slots to store info */ | 
|---|
|  | 5524 | +       sys_raminfo->dimm = kmalloc( | 
|---|
|  | 5525 | +               sys_raminfo->total * sizeof(struct dimm_slot), GFP_ATOMIC); | 
|---|
|  | 5526 | +       if (!sys_raminfo->dimm) { | 
|---|
|  | 5527 | +               EPRINTK("unable to allocate memory\n"); | 
|---|
|  | 5528 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 5529 | +               if (sys_raminfo->proc) { | 
|---|
|  | 5530 | +                       remove_proc_entry("raminfo", proc_cobalt); | 
|---|
|  | 5531 | +                       sys_raminfo->proc = NULL; | 
|---|
|  | 5532 | +               } | 
|---|
|  | 5533 | +#endif /* CONFIG_PROC_FS */ | 
|---|
|  | 5534 | +               return -ENOMEM; | 
|---|
|  | 5535 | +       } | 
|---|
|  | 5536 | + | 
|---|
|  | 5537 | +       { | 
|---|
|  | 5538 | +               struct dimm_slot *ds = sys_raminfo->dimm; | 
|---|
|  | 5539 | +               for (j=0; j<sys_raminfo->total; j++, ds++) { | 
|---|
|  | 5540 | +                       if (!ds) continue; | 
|---|
|  | 5541 | +                       ds->num = j; | 
|---|
|  | 5542 | +                       if (sys_raminfo->query(ds) < 0) { | 
|---|
|  | 5543 | +                               EPRINTK("unable to read dimm %d\n", j); | 
|---|
|  | 5544 | +                               ds->num = -1; | 
|---|
|  | 5545 | +                       } | 
|---|
|  | 5546 | +               } | 
|---|
|  | 5547 | +       } | 
|---|
|  | 5548 | + | 
|---|
|  | 5549 | +       return 0; | 
|---|
|  | 5550 | +} | 
|---|
|  | 5551 | + | 
|---|
|  | 5552 | +static void __exit | 
|---|
|  | 5553 | +cobalt_raminfo_exit(void) | 
|---|
|  | 5554 | +{ | 
|---|
|  | 5555 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 5556 | +       if (sys_raminfo->proc) { | 
|---|
|  | 5557 | +               remove_proc_entry("raminfo", proc_cobalt); | 
|---|
|  | 5558 | +               sys_raminfo->proc = NULL; | 
|---|
|  | 5559 | +       } | 
|---|
|  | 5560 | +#endif /* CONFIG_PROC_FS */ | 
|---|
|  | 5561 | + | 
|---|
|  | 5562 | +       if (sys_raminfo->dimm) { | 
|---|
|  | 5563 | +               kfree(sys_raminfo->dimm); | 
|---|
|  | 5564 | +               sys_raminfo->dimm = NULL; | 
|---|
|  | 5565 | +       } | 
|---|
|  | 5566 | + | 
|---|
|  | 5567 | +       sys_raminfo->dev = NULL; | 
|---|
|  | 5568 | +       sys_raminfo = NULL; | 
|---|
|  | 5569 | +} | 
|---|
|  | 5570 | + | 
|---|
|  | 5571 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 5572 | +static int | 
|---|
|  | 5573 | +raminfo_read_proc(char *buf, char **st, off_t off, int len, int *eof, void *x) | 
|---|
|  | 5574 | +{ | 
|---|
|  | 5575 | +       int rlen, i; | 
|---|
|  | 5576 | +       struct dimm_slot *ds; | 
|---|
|  | 5577 | + | 
|---|
|  | 5578 | +       if (!sys_raminfo) | 
|---|
|  | 5579 | +               return -ENOSYS; | 
|---|
|  | 5580 | + | 
|---|
|  | 5581 | +       //MOD_INC_USE_COUNT; | 
|---|
|  | 5582 | + | 
|---|
|  | 5583 | +       ds = sys_raminfo->dimm; | 
|---|
|  | 5584 | +       for (rlen=i=0; i<sys_raminfo->total; i++, ds++) { | 
|---|
|  | 5585 | +               if (!ds || ds->num < 0) | 
|---|
|  | 5586 | +                       continue; | 
|---|
|  | 5587 | +               rlen += sprintf(buf+rlen, "%d [%s%s]: %u MB\n", i, | 
|---|
|  | 5588 | +                               ds->size ? dimm_desc[ds->type] : "Empty", | 
|---|
|  | 5589 | +                               ds->size ? ds->ecc ? "+ECC" : "" : "", | 
|---|
|  | 5590 | +                               ds->size); | 
|---|
|  | 5591 | +       } | 
|---|
|  | 5592 | + | 
|---|
|  | 5593 | +       //MOD_DEC_USE_COUNT; | 
|---|
|  | 5594 | + | 
|---|
|  | 5595 | +       return cobalt_gen_proc_read(buf, rlen, st, off, len, eof); | 
|---|
|  | 5596 | +} | 
|---|
|  | 5597 | +#endif /* CONFIG_PROC_FS */ | 
|---|
|  | 5598 | + | 
|---|
|  | 5599 | +#ifdef CONFIG_COBALT_RAMINFO_MODULE | 
|---|
|  | 5600 | +module_init(cobalt_raminfo_init); | 
|---|
|  | 5601 | +module_exit(cobalt_raminfo_exit); | 
|---|
|  | 5602 | +#endif | 
|---|
|  | 5603 | + | 
|---|
|  | 5604 | +MODULE_AUTHOR("Sun Cobalt"); | 
|---|
|  | 5605 | +MODULE_DESCRIPTION("DIMM Information"); | 
|---|
|  | 5606 | +MODULE_LICENSE("GPL"); | 
|---|
|  | 5607 | + | 
|---|
|  | 5608 | +#endif /* CONFIG_COBALT_RAMINFO || CONFIG_COBALT_RAMINFO_MODULE */ | 
|---|
|  | 5609 | diff -Naur linux-2.6.20.orig/drivers/cobalt/ruler.c linux-2.6.20/drivers/cobalt/ruler.c | 
|---|
|  | 5610 | --- linux-2.6.20.orig/drivers/cobalt/ruler.c    1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 5611 | +++ linux-2.6.20/drivers/cobalt/ruler.c 2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 5612 | @@ -0,0 +1,419 @@ | 
|---|
|  | 5613 | +/* | 
|---|
|  | 5614 | + * cobalt ruler driver | 
|---|
|  | 5615 | + * Copyright (c) 2000, Cobalt Networks, Inc. | 
|---|
|  | 5616 | + * Copyright (c) 2001, Sun Microsystems, Inc. | 
|---|
|  | 5617 | + * $Id: ruler.c,v 1.23 2002/08/29 00:33:01 uzi Exp $ | 
|---|
|  | 5618 | + * | 
|---|
|  | 5619 | + * author: asun@cobalt.com, thockin@sun.com | 
|---|
|  | 5620 | + * | 
|---|
|  | 5621 | + * This should be SMP safe.  There is one critical piece of data, and thus | 
|---|
|  | 5622 | + * one lock.  The ruler_lock protects the arrays of channels(hwifs) and | 
|---|
|  | 5623 | + * busproc function pointers.  These are only ever written in the | 
|---|
|  | 5624 | + * register/unregister functions but read in several other places.  A | 
|---|
|  | 5625 | + * read/write lock is appropriate. The global switches and sled_leds are | 
|---|
|  | 5626 | + * atomic_t. --TPH | 
|---|
|  | 5627 | + */ | 
|---|
|  | 5628 | + | 
|---|
|  | 5629 | +#include <stdarg.h> | 
|---|
|  | 5630 | +#include <stddef.h> | 
|---|
|  | 5631 | +#include <linux/init.h> | 
|---|
|  | 5632 | +#include <linux/sched.h> | 
|---|
|  | 5633 | +#include <linux/timer.h> | 
|---|
|  | 5634 | +#include <linux/config.h> | 
|---|
|  | 5635 | +#include <linux/pci.h> | 
|---|
|  | 5636 | +#include <linux/proc_fs.h> | 
|---|
|  | 5637 | +#include <linux/sched.h> | 
|---|
|  | 5638 | +#include <linux/ioport.h> | 
|---|
|  | 5639 | +#include <linux/ide.h> | 
|---|
|  | 5640 | +#include <linux/hdreg.h> | 
|---|
|  | 5641 | +#include <linux/notifier.h> | 
|---|
|  | 5642 | +#include <linux/sysctl.h> | 
|---|
|  | 5643 | +#include <linux/reboot.h> | 
|---|
|  | 5644 | +#include <linux/delay.h> | 
|---|
|  | 5645 | +#include <linux/ide.h> | 
|---|
|  | 5646 | +#include <asm/io.h> | 
|---|
|  | 5647 | + | 
|---|
|  | 5648 | +#include <cobalt/cobalt.h> | 
|---|
|  | 5649 | +#include <cobalt/systype.h> | 
|---|
|  | 5650 | +#include <cobalt/i2c.h> | 
|---|
|  | 5651 | +#include <cobalt/acpi.h> | 
|---|
|  | 5652 | +#include <cobalt/led.h> | 
|---|
|  | 5653 | +#include <cobalt/ruler.h> | 
|---|
|  | 5654 | + | 
|---|
|  | 5655 | +#define RULER_TIMEOUT          (HZ >> 1)  /* .5s */ | 
|---|
|  | 5656 | +#define MAX_COBT_DRIVES                4 | 
|---|
|  | 5657 | + | 
|---|
|  | 5658 | +#define RULER_DRIVER                   "Cobalt Networks Disk Ruler driver" | 
|---|
|  | 5659 | +#define RULER_DRIVER_VMAJ              1 | 
|---|
|  | 5660 | +#define RULER_DRIVER_VMIN              0 | 
|---|
|  | 5661 | + | 
|---|
|  | 5662 | +/* all of this is for gen V */ | 
|---|
|  | 5663 | +static struct timer_list cobalt_ruler_timer; | 
|---|
|  | 5664 | +static rwlock_t ruler_lock = RW_LOCK_UNLOCKED; | 
|---|
|  | 5665 | +static ide_drive_t *channels[MAX_COBT_DRIVES]; | 
|---|
|  | 5666 | + | 
|---|
|  | 5667 | +static int (*busprocs[MAX_COBT_DRIVES])(ide_drive_t *, int); | 
|---|
|  | 5668 | + | 
|---|
|  | 5669 | +//static cob_busprocs_t busprocs[MAX_COBT_DRIVES]; | 
|---|
|  | 5670 | + | 
|---|
|  | 5671 | +/* NOTE: switches is a bitmask of DETACHED sleds */ | 
|---|
|  | 5672 | +static atomic_t switches = ATOMIC_INIT(0); | 
|---|
|  | 5673 | +static atomic_t sled_leds = ATOMIC_INIT(0); | 
|---|
|  | 5674 | +static int sled_led_map[] = {LED_SLED0, LED_SLED1, LED_SLED2, LED_SLED3}; | 
|---|
|  | 5675 | +static int ruler_detect; | 
|---|
|  | 5676 | +static int initialized; | 
|---|
|  | 5677 | + | 
|---|
|  | 5678 | +static void ruler_hwif_added(ide_hwif_t *hwif, int idx); | 
|---|
|  | 5679 | + | 
|---|
|  | 5680 | +static inline u8 | 
|---|
|  | 5681 | +read_switches(void) | 
|---|
|  | 5682 | +{ | 
|---|
|  | 5683 | +       u8 state = 0; | 
|---|
|  | 5684 | +       if (cobt_is_monterey()) { | 
|---|
|  | 5685 | +               int tries = 3; | 
|---|
|  | 5686 | + | 
|---|
|  | 5687 | +               /* i2c can be busy, and this can read wrong - try a few times */ | 
|---|
|  | 5688 | +               while (tries--) { | 
|---|
|  | 5689 | +                       state = cobalt_i2c_read_byte(COBALT_I2C_DEV_DRV_SWITCH, | 
|---|
|  | 5690 | +                               0); | 
|---|
|  | 5691 | +                       if ((state & 0xf0) != 0xf0) { | 
|---|
|  | 5692 | +                               break; | 
|---|
|  | 5693 | +                       } | 
|---|
|  | 5694 | +               } | 
|---|
|  | 5695 | +       } | 
|---|
|  | 5696 | + | 
|---|
|  | 5697 | +       return state; | 
|---|
|  | 5698 | +} | 
|---|
|  | 5699 | + | 
|---|
|  | 5700 | +static inline unsigned int | 
|---|
|  | 5701 | +get_sled_leds(void) | 
|---|
|  | 5702 | +{ | 
|---|
|  | 5703 | +       return atomic_read(&sled_leds); | 
|---|
|  | 5704 | +} | 
|---|
|  | 5705 | + | 
|---|
|  | 5706 | +/* | 
|---|
|  | 5707 | + * deal with sled leds: LED on means OK to remove | 
|---|
|  | 5708 | + * NOTE: all the reset lines are kept high. | 
|---|
|  | 5709 | + * NOTE: the reset lines are in the reverse order of the switches. | 
|---|
|  | 5710 | + */ | 
|---|
|  | 5711 | +static void | 
|---|
|  | 5712 | +set_sled_leds(unsigned int leds) | 
|---|
|  | 5713 | +{ | 
|---|
|  | 5714 | +       if (cobt_is_monterey()) { | 
|---|
|  | 5715 | +               unsigned int offed = get_sled_leds(); | 
|---|
|  | 5716 | + | 
|---|
|  | 5717 | +               offed &= ~leds; | 
|---|
|  | 5718 | +               atomic_set(&sled_leds, leds); | 
|---|
|  | 5719 | +#ifdef CONFIG_COBALT_LED | 
|---|
|  | 5720 | +               cobalt_led_clear_bits_lazy(offed); | 
|---|
|  | 5721 | +               cobalt_led_set_bits_lazy(leds); | 
|---|
|  | 5722 | +#endif | 
|---|
|  | 5723 | +       } | 
|---|
|  | 5724 | +} | 
|---|
|  | 5725 | + | 
|---|
|  | 5726 | +/* this must be called with the ruler_lock held for read */ | 
|---|
|  | 5727 | +static int | 
|---|
|  | 5728 | +do_busproc(int idx, ide_drive_t *drive, int arg) | 
|---|
|  | 5729 | +{ | 
|---|
|  | 5730 | +       if (cobt_is_monterey()) { | 
|---|
|  | 5731 | +               /* sed sled LEDs */ | 
|---|
|  | 5732 | +               switch (arg) { | 
|---|
|  | 5733 | +                       case BUSSTATE_ON: | 
|---|
|  | 5734 | +                               set_sled_leds(get_sled_leds() & | 
|---|
|  | 5735 | +                                       ~sled_led_map[idx]); | 
|---|
|  | 5736 | +                               break; | 
|---|
|  | 5737 | +                       case BUSSTATE_OFF: | 
|---|
|  | 5738 | +                       case BUSSTATE_TRISTATE: | 
|---|
|  | 5739 | +                               set_sled_leds(get_sled_leds() | | 
|---|
|  | 5740 | +                                       sled_led_map[idx]); | 
|---|
|  | 5741 | +                               break; | 
|---|
|  | 5742 | +                       default: | 
|---|
|  | 5743 | +                               WPRINTK("unknown busproc argument (%d)\n", arg); | 
|---|
|  | 5744 | +               } | 
|---|
|  | 5745 | +       } | 
|---|
|  | 5746 | + | 
|---|
|  | 5747 | +       /* do the real work */ | 
|---|
|  | 5748 | +       return busprocs[idx](drive, arg); | 
|---|
|  | 5749 | +} | 
|---|
|  | 5750 | + | 
|---|
|  | 5751 | +static void | 
|---|
|  | 5752 | +ruler_timer_fn(unsigned long data) | 
|---|
|  | 5753 | +{ | 
|---|
|  | 5754 | +       if (cobt_is_monterey()) { | 
|---|
|  | 5755 | +               u8 state; | 
|---|
|  | 5756 | +               int i; | 
|---|
|  | 5757 | +               unsigned int now, expected, bit, swcur; | 
|---|
|  | 5758 | + | 
|---|
|  | 5759 | +               state = read_switches(); | 
|---|
|  | 5760 | +               if ((state & 0xf0) == 0xf0) { | 
|---|
|  | 5761 | +                       return; | 
|---|
|  | 5762 | +               } | 
|---|
|  | 5763 | +               swcur = atomic_read(&switches); | 
|---|
|  | 5764 | + | 
|---|
|  | 5765 | +               state &= 0xf; | 
|---|
|  | 5766 | +               read_lock(&ruler_lock); | 
|---|
|  | 5767 | +               for (i = 0; i < MAX_COBT_DRIVES; i++) { | 
|---|
|  | 5768 | +                       bit = 1 << i; | 
|---|
|  | 5769 | +                       now = state & bit; | 
|---|
|  | 5770 | +                       expected = swcur & bit; | 
|---|
|  | 5771 | +                       if (now == expected) { | 
|---|
|  | 5772 | +                               /* no changes to worry about */ | 
|---|
|  | 5773 | +                               continue; | 
|---|
|  | 5774 | +                       } | 
|---|
|  | 5775 | + | 
|---|
|  | 5776 | +                       if (now) { | 
|---|
|  | 5777 | +                               /* a freshly detached drive */ | 
|---|
|  | 5778 | +                               atomic_set(&switches, swcur | bit); | 
|---|
|  | 5779 | +                               if (channels[i]) { | 
|---|
|  | 5780 | +                                       printk("disabling ide ruler " | 
|---|
|  | 5781 | +                                               "channel %d\n", i); | 
|---|
|  | 5782 | +                                       do_busproc(i, channels[i], | 
|---|
|  | 5783 | +                                               BUSSTATE_TRISTATE); | 
|---|
|  | 5784 | +                               } else { | 
|---|
|  | 5785 | +                                       WPRINTK("drive detach on bad " | 
|---|
|  | 5786 | +                                               "channel (%d)\n", i); | 
|---|
|  | 5787 | +                               } | 
|---|
|  | 5788 | +                               set_sled_leds(get_sled_leds() | | 
|---|
|  | 5789 | +                                       sled_led_map[i]); | 
|---|
|  | 5790 | +                       } else { | 
|---|
|  | 5791 | +                               /* | 
|---|
|  | 5792 | +                                * do we want to do anything when a re-attach | 
|---|
|  | 5793 | +                                * is detected? | 
|---|
|  | 5794 | +                                */ | 
|---|
|  | 5795 | +                       } | 
|---|
|  | 5796 | +               } | 
|---|
|  | 5797 | +               read_unlock(&ruler_lock); | 
|---|
|  | 5798 | +       } | 
|---|
|  | 5799 | +} | 
|---|
|  | 5800 | + | 
|---|
|  | 5801 | +#ifdef CONFIG_COBALT_ACPI | 
|---|
|  | 5802 | +static int | 
|---|
|  | 5803 | +ruler_interrupt(cobalt_acpi_evt *evt, void * data) | 
|---|
|  | 5804 | +{ | 
|---|
|  | 5805 | +       if (cobt_is_monterey() && ruler_detect) { | 
|---|
|  | 5806 | +               u8 state; | 
|---|
|  | 5807 | + | 
|---|
|  | 5808 | +               state = read_switches(); | 
|---|
|  | 5809 | +               if ((state & 0xf0) != 0xf0) { | 
|---|
|  | 5810 | +                       /* this is protected inside mod_timer */ | 
|---|
|  | 5811 | +                       mod_timer(&cobalt_ruler_timer, jiffies + RULER_TIMEOUT); | 
|---|
|  | 5812 | +               } | 
|---|
|  | 5813 | + | 
|---|
|  | 5814 | +               evt->ev_data = state; | 
|---|
|  | 5815 | +               /* empirical: delay enough to debounce */ | 
|---|
|  | 5816 | +               udelay(10); | 
|---|
|  | 5817 | +       } | 
|---|
|  | 5818 | +       return 0; | 
|---|
|  | 5819 | +} | 
|---|
|  | 5820 | +#endif /* CONFIG_COBALT_ACPI */ | 
|---|
|  | 5821 | + | 
|---|
|  | 5822 | +#if defined(CONFIG_COBALT_LED) | 
|---|
|  | 5823 | +/* figure which LEDs to blink */ | 
|---|
|  | 5824 | +static unsigned int | 
|---|
|  | 5825 | +ide_led_handler(void *data) | 
|---|
|  | 5826 | +{ | 
|---|
|  | 5827 | +       ide_hwif_t *hwif; | 
|---|
|  | 5828 | +       unsigned int leds = 0; | 
|---|
|  | 5829 | + | 
|---|
|  | 5830 | +       if (cobt_is_monterey()) { | 
|---|
|  | 5831 | +               int i; | 
|---|
|  | 5832 | +               static int ledmap[MAX_COBT_DRIVES] = { | 
|---|
|  | 5833 | +                       LED_DISK0, LED_DISK1, LED_DISK2, LED_DISK3 | 
|---|
|  | 5834 | +               }; | 
|---|
|  | 5835 | +               static unsigned long old[MAX_COBT_DRIVES]; | 
|---|
|  | 5836 | + | 
|---|
|  | 5837 | +               read_lock(&ruler_lock); | 
|---|
|  | 5838 | + | 
|---|
|  | 5839 | +               for (i = 0; i < MAX_COBT_DRIVES; i++) { | 
|---|
|  | 5840 | +                       if (channels[i]) | 
|---|
|  | 5841 | +                       { | 
|---|
|  | 5842 | +                               hwif = HWIF(channels[i]); | 
|---|
|  | 5843 | +                               if (hwif->drives[0].present && | 
|---|
|  | 5844 | +                                   hwif->drives[0].service_start != old[i]) { | 
|---|
|  | 5845 | +                                       leds |= ledmap[i]; | 
|---|
|  | 5846 | +                                       old[i] = hwif->drives[0].service_start; | 
|---|
|  | 5847 | +                               } | 
|---|
|  | 5848 | +                       } | 
|---|
|  | 5849 | +               } | 
|---|
|  | 5850 | + | 
|---|
|  | 5851 | +               read_unlock(&ruler_lock); | 
|---|
|  | 5852 | +       } | 
|---|
|  | 5853 | + | 
|---|
|  | 5854 | +       return leds; | 
|---|
|  | 5855 | +} | 
|---|
|  | 5856 | +#endif | 
|---|
|  | 5857 | + | 
|---|
|  | 5858 | +/* this is essentially an exported function - it is in the hwif structs */ | 
|---|
|  | 5859 | +static int ruler_busproc_fn(ide_drive_t *drive, int arg) | 
|---|
|  | 5860 | +{ | 
|---|
|  | 5861 | +       int r = 0; | 
|---|
|  | 5862 | +       if (cobt_is_monterey()) { | 
|---|
|  | 5863 | +               int idx; | 
|---|
|  | 5864 | + | 
|---|
|  | 5865 | +               read_lock(&ruler_lock); | 
|---|
|  | 5866 | + | 
|---|
|  | 5867 | +               for (idx = 0; idx < MAX_COBT_DRIVES; idx++) { | 
|---|
|  | 5868 | +                       if (channels[idx] == drive) { | 
|---|
|  | 5869 | +                               break; | 
|---|
|  | 5870 | +                       } | 
|---|
|  | 5871 | +               } | 
|---|
|  | 5872 | + | 
|---|
|  | 5873 | +               if (idx >= MAX_COBT_DRIVES) { | 
|---|
|  | 5874 | +                       /* not a hwif we manage? */ | 
|---|
|  | 5875 | +                       return 0; | 
|---|
|  | 5876 | +               } | 
|---|
|  | 5877 | + | 
|---|
|  | 5878 | +               r = do_busproc(idx, drive, arg); | 
|---|
|  | 5879 | +               read_unlock(&ruler_lock); | 
|---|
|  | 5880 | +       } | 
|---|
|  | 5881 | + | 
|---|
|  | 5882 | +       return r; | 
|---|
|  | 5883 | +} | 
|---|
|  | 5884 | + | 
|---|
|  | 5885 | +/* | 
|---|
|  | 5886 | + * We try to be VERY explicit here.  Fine for now, may eventually break down. | 
|---|
|  | 5887 | + */ | 
|---|
|  | 5888 | +void | 
|---|
|  | 5889 | +cobalt_ruler_register(ide_drive_t *drive) | 
|---|
|  | 5890 | +{ | 
|---|
|  | 5891 | +       ide_hwif_t *hwif = HWIF(drive); | 
|---|
|  | 5892 | + | 
|---|
|  | 5893 | +       if (cobt_is_monterey()) { | 
|---|
|  | 5894 | +               struct pci_dev *dev; | 
|---|
|  | 5895 | +               int idx; | 
|---|
|  | 5896 | +               unsigned long flags; | 
|---|
|  | 5897 | + | 
|---|
|  | 5898 | +               if (!hwif) { | 
|---|
|  | 5899 | +                       return; | 
|---|
|  | 5900 | +               } | 
|---|
|  | 5901 | + | 
|---|
|  | 5902 | +               /* Cobalt rulers only have HPT370 controllers on bus 1 */ | 
|---|
|  | 5903 | +               dev = hwif->pci_dev; | 
|---|
|  | 5904 | +               if (!dev) | 
|---|
|  | 5905 | +                       return; | 
|---|
|  | 5906 | + | 
|---|
|  | 5907 | +               if (dev->vendor != PCI_VENDOR_ID_TTI | 
|---|
|  | 5908 | +                || dev->device != PCI_DEVICE_ID_TTI_HPT366 | 
|---|
|  | 5909 | +                || dev->bus->number != 1) { | 
|---|
|  | 5910 | +                       /* ignore it */ | 
|---|
|  | 5911 | +                       return; | 
|---|
|  | 5912 | +               } | 
|---|
|  | 5913 | + | 
|---|
|  | 5914 | +               /* IDE ruler has controllers at dev 3 and 4, ONLY */ | 
|---|
|  | 5915 | +               if (dev->devfn == PCI_DEVFN(3,0)) { | 
|---|
|  | 5916 | +                       idx = hwif->channel; | 
|---|
|  | 5917 | +               } else if (dev->devfn == PCI_DEVFN(4,0)) { | 
|---|
|  | 5918 | +                       idx = 2 + hwif->channel; | 
|---|
|  | 5919 | +               } else { | 
|---|
|  | 5920 | +                       return; | 
|---|
|  | 5921 | +               } | 
|---|
|  | 5922 | + | 
|---|
|  | 5923 | +               if (idx >= MAX_COBT_DRIVES) { | 
|---|
|  | 5924 | +                       return; | 
|---|
|  | 5925 | +               } | 
|---|
|  | 5926 | + | 
|---|
|  | 5927 | +               write_lock_irqsave(&ruler_lock, flags); | 
|---|
|  | 5928 | + | 
|---|
|  | 5929 | +               /* save a pointer to the hwif, and trap it's busproc() */ | 
|---|
|  | 5930 | +               channels[idx] = drive; | 
|---|
|  | 5931 | +               if (hwif->busproc) { | 
|---|
|  | 5932 | +                       busprocs[idx] = HWIF(drive)->busproc; | 
|---|
|  | 5933 | +                       hwif->busproc = &ruler_busproc_fn; | 
|---|
|  | 5934 | +               } | 
|---|
|  | 5935 | + | 
|---|
|  | 5936 | +               write_unlock_irqrestore(&ruler_lock, flags); | 
|---|
|  | 5937 | + | 
|---|
|  | 5938 | +               /* now that we have trapped it, do what we need to initialize | 
|---|
|  | 5939 | +                * the drive - if we haven't been initialized, we'll call this | 
|---|
|  | 5940 | +                * later. | 
|---|
|  | 5941 | +                */ | 
|---|
|  | 5942 | +               if (initialized) { | 
|---|
|  | 5943 | +                       ruler_hwif_added(hwif, idx); | 
|---|
|  | 5944 | +               } | 
|---|
|  | 5945 | +       } | 
|---|
|  | 5946 | +} | 
|---|
|  | 5947 | + | 
|---|
|  | 5948 | +static void | 
|---|
|  | 5949 | +ruler_hwif_added(ide_hwif_t *hwif, int idx) | 
|---|
|  | 5950 | +{ | 
|---|
|  | 5951 | +       /* the associated switch should be closed */ | 
|---|
|  | 5952 | +       if (hwif->drives[0].present) { | 
|---|
|  | 5953 | +               /* set the sled LED off - not safe to remove */ | 
|---|
|  | 5954 | +               set_sled_leds(get_sled_leds() & ~sled_led_map[idx]); | 
|---|
|  | 5955 | +       } | 
|---|
|  | 5956 | +} | 
|---|
|  | 5957 | + | 
|---|
|  | 5958 | +void cobalt_ruler_unregister(ide_drive_t *drive) | 
|---|
|  | 5959 | +{ | 
|---|
|  | 5960 | +       if (cobt_is_monterey()) { | 
|---|
|  | 5961 | +               int i; | 
|---|
|  | 5962 | +               unsigned long flags; | 
|---|
|  | 5963 | + | 
|---|
|  | 5964 | +               write_lock_irqsave(&ruler_lock, flags); | 
|---|
|  | 5965 | + | 
|---|
|  | 5966 | +               for (i = 0; i < MAX_COBT_DRIVES; i++) { | 
|---|
|  | 5967 | +                       if (channels[i] == drive) { | 
|---|
|  | 5968 | +                               channels[i] = NULL; | 
|---|
|  | 5969 | +                               HWIF(drive)->busproc = busprocs[i]; | 
|---|
|  | 5970 | +                               busprocs[i] = NULL; | 
|---|
|  | 5971 | +                       } | 
|---|
|  | 5972 | +               } | 
|---|
|  | 5973 | + | 
|---|
|  | 5974 | +               write_unlock_irqrestore(&ruler_lock, flags); | 
|---|
|  | 5975 | +       } | 
|---|
|  | 5976 | +} | 
|---|
|  | 5977 | + | 
|---|
|  | 5978 | +int __init | 
|---|
|  | 5979 | +cobalt_ruler_init(void) | 
|---|
|  | 5980 | +{ | 
|---|
|  | 5981 | +       if (cobt_is_monterey()) { | 
|---|
|  | 5982 | +               int err; | 
|---|
|  | 5983 | +               u8 tmp; | 
|---|
|  | 5984 | +               int i; | 
|---|
|  | 5985 | + | 
|---|
|  | 5986 | +               /* initialize switches */ | 
|---|
|  | 5987 | +               tmp = read_switches(); | 
|---|
|  | 5988 | +               ruler_detect = ((tmp & 0xf0) == 0xf0) ? 0 : 1; | 
|---|
|  | 5989 | +               tmp &= 0xf; | 
|---|
|  | 5990 | +               atomic_set(&switches, tmp); | 
|---|
|  | 5991 | + | 
|---|
|  | 5992 | +               /* initialize our timer */ | 
|---|
|  | 5993 | +               init_timer(&cobalt_ruler_timer); | 
|---|
|  | 5994 | +               cobalt_ruler_timer.function = ruler_timer_fn; | 
|---|
|  | 5995 | + | 
|---|
|  | 5996 | +        printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", RULER_DRIVER,RULER_DRIVER_VMAJ,RULER_DRIVER_VMIN); | 
|---|
|  | 5997 | + | 
|---|
|  | 5998 | +#ifdef CONFIG_COBALT_ACPI | 
|---|
|  | 5999 | +               err = cobalt_acpi_register_evt_handler(ruler_interrupt, | 
|---|
|  | 6000 | +                       COBALT_ACPI_EVT_SLED, NULL ); | 
|---|
|  | 6001 | + | 
|---|
|  | 6002 | +               if (err) { | 
|---|
|  | 6003 | +                       EPRINTK("can't register interrupt handler %p\n", | 
|---|
|  | 6004 | +                               ruler_interrupt); | 
|---|
|  | 6005 | +               } | 
|---|
|  | 6006 | +#endif | 
|---|
|  | 6007 | + | 
|---|
|  | 6008 | +               /* set initial sled LED state */ | 
|---|
|  | 6009 | +               set_sled_leds(LED_SLED0 | LED_SLED1 | LED_SLED2 | LED_SLED3); | 
|---|
|  | 6010 | + | 
|---|
|  | 6011 | +               /* run through any devices that were registered before */ | 
|---|
|  | 6012 | +               for (i = 0; i < MAX_COBT_DRIVES; i++) { | 
|---|
|  | 6013 | +                       if (channels[i]) { | 
|---|
|  | 6014 | +                               ruler_hwif_added(HWIF(channels[i]), i); | 
|---|
|  | 6015 | +                       } | 
|---|
|  | 6016 | +               } | 
|---|
|  | 6017 | + | 
|---|
|  | 6018 | +#if defined(CONFIG_COBALT_LED) | 
|---|
|  | 6019 | +               /* register for a blinky LEDs callback */ | 
|---|
|  | 6020 | +               err = cobalt_fpled_register(ide_led_handler, NULL); | 
|---|
|  | 6021 | +               if (err) { | 
|---|
|  | 6022 | +                       EPRINTK("can't register LED handler %p\n", | 
|---|
|  | 6023 | +                               ide_led_handler); | 
|---|
|  | 6024 | +               } | 
|---|
|  | 6025 | +#endif | 
|---|
|  | 6026 | +       } | 
|---|
|  | 6027 | + | 
|---|
|  | 6028 | +       initialized = 1; | 
|---|
|  | 6029 | + | 
|---|
|  | 6030 | +       return 0; | 
|---|
|  | 6031 | +} | 
|---|
|  | 6032 | diff -Naur linux-2.6.20.orig/drivers/cobalt/sensors.c linux-2.6.20/drivers/cobalt/sensors.c | 
|---|
|  | 6033 | --- linux-2.6.20.orig/drivers/cobalt/sensors.c  1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 6034 | +++ linux-2.6.20/drivers/cobalt/sensors.c       2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 6035 | @@ -0,0 +1,525 @@ | 
|---|
|  | 6036 | +/* $Id: sensors.c,v 1.31 2002/08/29 00:33:01 uzi Exp $ | 
|---|
|  | 6037 | + * Copyright (c) 2000-2001 Sun Microsystems, Inc | 
|---|
|  | 6038 | + * | 
|---|
|  | 6039 | + * This should be SMP safe.  There is just one race - the read in /proc. | 
|---|
|  | 6040 | + * It now guards against itself with a semaphore.  Note that we don't use a | 
|---|
|  | 6041 | + * spinlock because any of the methods may (and do!) block. | 
|---|
|  | 6042 | + */ | 
|---|
|  | 6043 | +#include <linux/config.h> | 
|---|
|  | 6044 | +#ifdef CONFIG_COBALT_SENSORS | 
|---|
|  | 6045 | + | 
|---|
|  | 6046 | +#include <stdarg.h> | 
|---|
|  | 6047 | +#include <stddef.h> | 
|---|
|  | 6048 | + | 
|---|
|  | 6049 | +#include <linux/init.h> | 
|---|
|  | 6050 | +#include <linux/sched.h> | 
|---|
|  | 6051 | +#include <linux/timer.h> | 
|---|
|  | 6052 | +#include <linux/config.h> | 
|---|
|  | 6053 | +#include <linux/delay.h> | 
|---|
|  | 6054 | +#include <linux/ctype.h> | 
|---|
|  | 6055 | +#include <linux/proc_fs.h> | 
|---|
|  | 6056 | + | 
|---|
|  | 6057 | +#include <asm/io.h> | 
|---|
|  | 6058 | +#include <asm/uaccess.h> | 
|---|
|  | 6059 | + | 
|---|
|  | 6060 | +#include <cobalt/cobalt.h> | 
|---|
|  | 6061 | +#include <cobalt/systype.h> | 
|---|
|  | 6062 | +#include <cobalt/i2c.h> | 
|---|
|  | 6063 | +#include <cobalt/sensors.h> | 
|---|
|  | 6064 | +#include <cobalt/acpi.h> | 
|---|
|  | 6065 | + | 
|---|
|  | 6066 | +#define SENS_DRIVER                    "Cobalt Networks Sensor driver" | 
|---|
|  | 6067 | +#define SENS_DRIVER_VMAJ               1 | 
|---|
|  | 6068 | +#define SENS_DRIVER_VMIN               0 | 
|---|
|  | 6069 | + | 
|---|
|  | 6070 | +/* externals */ | 
|---|
|  | 6071 | +unsigned int cobalt_nthermals; | 
|---|
|  | 6072 | +unsigned int cobalt_nvoltages; | 
|---|
|  | 6073 | + | 
|---|
|  | 6074 | +/* data about a sensor for generic handling */ | 
|---|
|  | 6075 | +/* we could add data about a low/high range, if needed */ | 
|---|
|  | 6076 | +struct sensor { | 
|---|
|  | 6077 | +       int sensor; /* sensor #, so maps can be logically ordered */ | 
|---|
|  | 6078 | +       char *desc; | 
|---|
|  | 6079 | +       int last_val; | 
|---|
|  | 6080 | +       unsigned long cache; | 
|---|
|  | 6081 | +       unsigned long cache_timeout; | 
|---|
|  | 6082 | +       /* pre/post hook - 1 for pre, 0 for post */ | 
|---|
|  | 6083 | +       void (*setup)(struct sensor *s, int pre); | 
|---|
|  | 6084 | +       /* read as an int, to be passed to format() */ | 
|---|
|  | 6085 | +       int (*read)(struct sensor *s); | 
|---|
|  | 6086 | +       /* hook for scaling values */ | 
|---|
|  | 6087 | +       int (*scale)(struct sensor *s, int val); | 
|---|
|  | 6088 | +       /* format the value as a string */ | 
|---|
|  | 6089 | +       char *(*format)(struct sensor *s, int val, char *buf, int len); | 
|---|
|  | 6090 | +}; | 
|---|
|  | 6091 | + | 
|---|
|  | 6092 | +/* some stuff for generic formatting */ | 
|---|
|  | 6093 | +#define DEC_SCALAR             100 | 
|---|
|  | 6094 | +static char *decimal_format(struct sensor *s, int val, char *buf, int len); | 
|---|
|  | 6095 | + | 
|---|
|  | 6096 | +static DECLARE_MUTEX(sensor_sem); | 
|---|
|  | 6097 | +static struct sensor *therm_map; | 
|---|
|  | 6098 | +static struct sensor *volt_map; | 
|---|
|  | 6099 | + | 
|---|
|  | 6100 | +#define CACHE_DEF              30 | 
|---|
|  | 6101 | + | 
|---|
|  | 6102 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 6103 | +static struct proc_dir_entry *proc_csensors; | 
|---|
|  | 6104 | +static struct proc_dir_entry *proc_therm; | 
|---|
|  | 6105 | +static struct proc_dir_entry *proc_volt; | 
|---|
|  | 6106 | +static int therm_read_proc(char *buf, char **start, off_t pos, int len, | 
|---|
|  | 6107 | +       int *eof, void *x); | 
|---|
|  | 6108 | +static int therm_write_proc(struct file *file, const char *buf, | 
|---|
|  | 6109 | +       unsigned long len, void *x); | 
|---|
|  | 6110 | +static int volt_read_proc(char *buf, char **start, off_t pos, int len, | 
|---|
|  | 6111 | +       int *eof, void *x); | 
|---|
|  | 6112 | +static int volt_write_proc(struct file *file, const char *buf, | 
|---|
|  | 6113 | +       unsigned long len, void *x); | 
|---|
|  | 6114 | +#endif | 
|---|
|  | 6115 | + | 
|---|
|  | 6116 | +static int lm77_therm_read(struct sensor *s); | 
|---|
|  | 6117 | +static int adm1029_init(void); | 
|---|
|  | 6118 | +static int adm1029_therm_read(struct sensor *s); | 
|---|
|  | 6119 | +static int adm1029_volt_read(struct sensor *s); | 
|---|
|  | 6120 | +static int alpine_vcore_scale(struct sensor *s, int val); | 
|---|
|  | 6121 | +static void alpine_vbat_switch(struct sensor *s, int pre); | 
|---|
|  | 6122 | +static int alpine_vbat_scale(struct sensor *s, int val); | 
|---|
|  | 6123 | + | 
|---|
|  | 6124 | +/* sensor name mappings */ | 
|---|
|  | 6125 | +static struct sensor gen3_therm_map[] = { | 
|---|
|  | 6126 | +       {0, "CPU", 0, 0, CACHE_DEF, NULL, lm77_therm_read, NULL, decimal_format}, | 
|---|
|  | 6127 | +}; | 
|---|
|  | 6128 | +static struct sensor monterey_therm_map[] = { | 
|---|
|  | 6129 | +       {0, "CPU0", 0, 0, CACHE_DEF, NULL, lm77_therm_read, NULL, decimal_format}, | 
|---|
|  | 6130 | +       {1, "CPU1", 0, 0, CACHE_DEF, NULL, lm77_therm_read, NULL, decimal_format}, | 
|---|
|  | 6131 | +       {2, "Case0", 0, 0, CACHE_DEF, NULL, lm77_therm_read, NULL, decimal_format}, | 
|---|
|  | 6132 | +       {3, "Case1", 0, 0, CACHE_DEF, NULL, lm77_therm_read, NULL, decimal_format}, | 
|---|
|  | 6133 | +}; | 
|---|
|  | 6134 | +static struct sensor alpine_therm_map[] = { | 
|---|
|  | 6135 | +       {1, "CPU", 0, 0, CACHE_DEF, NULL, adm1029_therm_read, NULL, decimal_format}, | 
|---|
|  | 6136 | +       {0, "Case", 0, 0, CACHE_DEF, NULL, adm1029_therm_read, NULL, decimal_format}, | 
|---|
|  | 6137 | +}; | 
|---|
|  | 6138 | +static struct sensor alpine_volt_map[] = { | 
|---|
|  | 6139 | +       {0, "Vcore", 0, 0, CACHE_DEF, NULL, adm1029_volt_read, | 
|---|
|  | 6140 | +               alpine_vcore_scale, decimal_format}, | 
|---|
|  | 6141 | +       {1, "Vtt", 0, 0, CACHE_DEF, NULL, adm1029_volt_read, NULL, decimal_format}, | 
|---|
|  | 6142 | +       {0, "Vbat", 0, 0, CACHE_DEF<<10, alpine_vbat_switch, adm1029_volt_read, | 
|---|
|  | 6143 | +               alpine_vbat_scale, decimal_format}, | 
|---|
|  | 6144 | +}; | 
|---|
|  | 6145 | + | 
|---|
|  | 6146 | +int __init | 
|---|
|  | 6147 | +cobalt_sensors_init(void) | 
|---|
|  | 6148 | +{ | 
|---|
|  | 6149 | +       if (cobt_is_3k()) { | 
|---|
|  | 6150 | +               cobalt_nthermals = 1; | 
|---|
|  | 6151 | +               cobalt_nvoltages = 0; | 
|---|
|  | 6152 | +               therm_map = gen3_therm_map; | 
|---|
|  | 6153 | +       } else if (cobt_is_monterey()) { | 
|---|
|  | 6154 | +               cobalt_nthermals = 4; | 
|---|
|  | 6155 | +               cobalt_nvoltages = 0; | 
|---|
|  | 6156 | +               therm_map = monterey_therm_map; | 
|---|
|  | 6157 | +       } else if (cobt_is_alpine()) { | 
|---|
|  | 6158 | +               cobalt_nthermals = 2; | 
|---|
|  | 6159 | +               cobalt_nvoltages = 3; | 
|---|
|  | 6160 | +               therm_map = alpine_therm_map; | 
|---|
|  | 6161 | +               volt_map = alpine_volt_map; | 
|---|
|  | 6162 | +               adm1029_init(); | 
|---|
|  | 6163 | +       } else  { | 
|---|
|  | 6164 | +               return -1; | 
|---|
|  | 6165 | +       } | 
|---|
|  | 6166 | + | 
|---|
|  | 6167 | +    printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", SENS_DRIVER,SENS_DRIVER_VMAJ,SENS_DRIVER_VMIN); | 
|---|
|  | 6168 | + | 
|---|
|  | 6169 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 6170 | +       /* make files in /proc */ | 
|---|
|  | 6171 | +       proc_csensors = proc_mkdir("sensors", proc_cobalt); | 
|---|
|  | 6172 | +       if (!proc_csensors) { | 
|---|
|  | 6173 | +               EPRINTK("can't create /proc/cobalt/sensors\n"); | 
|---|
|  | 6174 | +               return -1; | 
|---|
|  | 6175 | +       } | 
|---|
|  | 6176 | +       if (cobalt_nthermals) { | 
|---|
|  | 6177 | +               proc_therm = create_proc_entry("thermal", | 
|---|
|  | 6178 | +                                              S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, | 
|---|
|  | 6179 | +                                              proc_csensors); | 
|---|
|  | 6180 | +               if (!proc_therm) { | 
|---|
|  | 6181 | +                       EPRINTK("can't create /proc/cobalt/sensors/thermal\n"); | 
|---|
|  | 6182 | +               } | 
|---|
|  | 6183 | +               proc_therm->read_proc = therm_read_proc; | 
|---|
|  | 6184 | +               proc_therm->write_proc = therm_write_proc; | 
|---|
|  | 6185 | +       } | 
|---|
|  | 6186 | +       if (cobalt_nvoltages) { | 
|---|
|  | 6187 | +               proc_volt = create_proc_entry("voltage", | 
|---|
|  | 6188 | +                                             S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, | 
|---|
|  | 6189 | +                                             proc_csensors); | 
|---|
|  | 6190 | +               if (!proc_volt) { | 
|---|
|  | 6191 | +                       EPRINTK("can't create /proc/cobalt/sensors/voltage\n"); | 
|---|
|  | 6192 | +               } | 
|---|
|  | 6193 | +               proc_volt->read_proc = volt_read_proc; | 
|---|
|  | 6194 | +               proc_volt->write_proc = volt_write_proc; | 
|---|
|  | 6195 | + | 
|---|
|  | 6196 | +       } | 
|---|
|  | 6197 | +#endif | 
|---|
|  | 6198 | + | 
|---|
|  | 6199 | +       return 0; | 
|---|
|  | 6200 | +} | 
|---|
|  | 6201 | + | 
|---|
|  | 6202 | +static char * | 
|---|
|  | 6203 | +sensor_read(struct sensor *s, char *buf, int len) | 
|---|
|  | 6204 | +{ | 
|---|
|  | 6205 | +       int val; | 
|---|
|  | 6206 | + | 
|---|
|  | 6207 | +       if (s->cache && time_after(s->cache_timeout*HZ + s->cache, jiffies)) | 
|---|
|  | 6208 | +               val = s->last_val; | 
|---|
|  | 6209 | +       else { | 
|---|
|  | 6210 | +               if (s->setup) s->setup(s, 1); | 
|---|
|  | 6211 | +               val = s->read(s); | 
|---|
|  | 6212 | +               s->last_val = val; | 
|---|
|  | 6213 | +               s->cache = jiffies; | 
|---|
|  | 6214 | +               if (s->setup) s->setup(s, 0); | 
|---|
|  | 6215 | +       } | 
|---|
|  | 6216 | + | 
|---|
|  | 6217 | +       if (s->scale) val = s->scale(s, val); | 
|---|
|  | 6218 | +       return s->format(s, val, buf, len); | 
|---|
|  | 6219 | +} | 
|---|
|  | 6220 | + | 
|---|
|  | 6221 | +/* exported - nicer inline functions in header */ | 
|---|
|  | 6222 | +char * | 
|---|
|  | 6223 | +__cobalt_thermal_read(unsigned int idx, char *buf, int len) | 
|---|
|  | 6224 | +{ | 
|---|
|  | 6225 | +       if (idx >= cobalt_nthermals || !buf) { | 
|---|
|  | 6226 | +               return NULL; | 
|---|
|  | 6227 | +       } | 
|---|
|  | 6228 | + | 
|---|
|  | 6229 | +       return sensor_read(&therm_map[idx], buf, len); | 
|---|
|  | 6230 | +} | 
|---|
|  | 6231 | + | 
|---|
|  | 6232 | +/* exported - nicer inline functions in header */ | 
|---|
|  | 6233 | +char * | 
|---|
|  | 6234 | +__cobalt_voltage_read(unsigned int idx, char *buf, int len) | 
|---|
|  | 6235 | +{ | 
|---|
|  | 6236 | +       if (idx >= cobalt_nvoltages || !buf) { | 
|---|
|  | 6237 | +               return NULL; | 
|---|
|  | 6238 | +       } | 
|---|
|  | 6239 | + | 
|---|
|  | 6240 | +       return sensor_read(&volt_map[idx], buf, len); | 
|---|
|  | 6241 | +} | 
|---|
|  | 6242 | + | 
|---|
|  | 6243 | +/* generic function for formatting decimal scaled data */ | 
|---|
|  | 6244 | +static char * | 
|---|
|  | 6245 | +decimal_format(struct sensor *s, int val, char *buf, int len) | 
|---|
|  | 6246 | +{ | 
|---|
|  | 6247 | +       int plen; | 
|---|
|  | 6248 | + | 
|---|
|  | 6249 | +       if (!buf || len <= 0) { | 
|---|
|  | 6250 | +               return NULL; | 
|---|
|  | 6251 | +       } | 
|---|
|  | 6252 | + | 
|---|
|  | 6253 | +       plen = snprintf(buf, len, "%d", val/DEC_SCALAR); | 
|---|
|  | 6254 | +       len -= plen; | 
|---|
|  | 6255 | + | 
|---|
|  | 6256 | +       if (val % DEC_SCALAR && len > 0) { | 
|---|
|  | 6257 | +               snprintf(buf+plen, len, ".%02d", val%DEC_SCALAR); | 
|---|
|  | 6258 | +       } | 
|---|
|  | 6259 | + | 
|---|
|  | 6260 | +       return buf; | 
|---|
|  | 6261 | +} | 
|---|
|  | 6262 | + | 
|---|
|  | 6263 | +#define LM77_TEMP              0x0 | 
|---|
|  | 6264 | +static int | 
|---|
|  | 6265 | +lm77_therm_read(struct sensor *s) | 
|---|
|  | 6266 | +{ | 
|---|
|  | 6267 | +       int sensor = s->sensor; | 
|---|
|  | 6268 | +       int tmp; | 
|---|
|  | 6269 | +       int val = 0; | 
|---|
|  | 6270 | +       int tries = 2; | 
|---|
|  | 6271 | + | 
|---|
|  | 6272 | +       /* sometimes it reads as zero... try again */ | 
|---|
|  | 6273 | +       while (tries--) { | 
|---|
|  | 6274 | +               /* LM77 returns the bytes backwards - <shrug> */ | 
|---|
|  | 6275 | +               /* address = base + deviceid + 1 for read */ | 
|---|
|  | 6276 | +               val = cobalt_i2c_read_word(COBALT_I2C_DEV_LM77 + | 
|---|
|  | 6277 | +                       (sensor<<1) + 1, LM77_TEMP); | 
|---|
|  | 6278 | +               if (val < 0) { | 
|---|
|  | 6279 | +                       /* read failed, return the last known value */ | 
|---|
|  | 6280 | +                       return s->last_val; | 
|---|
|  | 6281 | +               } | 
|---|
|  | 6282 | + | 
|---|
|  | 6283 | +               tmp = (val<<8 & 0xff00) + (val>>8 & 0x00ff); | 
|---|
|  | 6284 | +               if (tmp) { | 
|---|
|  | 6285 | +                       val = tmp >> 4; | 
|---|
|  | 6286 | +                       val *= DEC_SCALAR; | 
|---|
|  | 6287 | +                       if (tmp & 0x8) { | 
|---|
|  | 6288 | +                               val += DEC_SCALAR/2; | 
|---|
|  | 6289 | +                       } | 
|---|
|  | 6290 | +                       break; | 
|---|
|  | 6291 | +               } | 
|---|
|  | 6292 | +       } | 
|---|
|  | 6293 | +       return val; | 
|---|
|  | 6294 | +} | 
|---|
|  | 6295 | + | 
|---|
|  | 6296 | +#define ADM1029_CTL_CFAULT_OVER                0x01 | 
|---|
|  | 6297 | +#define ADM1029_CTL_ALARM_OVER         0x02 | 
|---|
|  | 6298 | +#define ADM1029_CTL_INT_OVER           0x04 | 
|---|
|  | 6299 | +#define ADM1029_CTL_ALARM_LOW          0x08 | 
|---|
|  | 6300 | +#define ADM1029_CTL_CFAULT_UNDER       0x10 | 
|---|
|  | 6301 | +#define ADM1029_CTL_ALARM_UNDER                0x20 | 
|---|
|  | 6302 | +#define ADM1029_CTL_INT_UNDER          0x40 | 
|---|
|  | 6303 | +#define ADM1029_CTL_LATCH              0x80 | 
|---|
|  | 6304 | + | 
|---|
|  | 6305 | +#define ADM1029_FAN_CTL(i)             (0x18 + i) | 
|---|
|  | 6306 | +#define ADM1029_TEMP_CTL(i)            (0x40 + i) | 
|---|
|  | 6307 | +#define ADM1029_AIN_CTL(i)             (0x50 + i) | 
|---|
|  | 6308 | + | 
|---|
|  | 6309 | +#define ADM1029_TEMP_HIGH(i)           (0x90 + i) | 
|---|
|  | 6310 | +#define ADM1029_TEMP_LOW(i)            (0x98 + i) | 
|---|
|  | 6311 | +#define ADM1029_AIN_HIGH(i)            (0xa8 + i) | 
|---|
|  | 6312 | +#define ADM1029_AIN_LOW(i)             (0xb0 + i) | 
|---|
|  | 6313 | + | 
|---|
|  | 6314 | +#define ADM1029_TEMP_VALUE(i)          (0xa0 + i) | 
|---|
|  | 6315 | +#define ADM1029_AIN_VALUE(i)           (0xb8 + i) | 
|---|
|  | 6316 | + | 
|---|
|  | 6317 | +#ifdef CONFIG_COBALT_ACPI | 
|---|
|  | 6318 | +static int | 
|---|
|  | 6319 | +adm1029_handler(cobalt_acpi_evt *evt, void * data) | 
|---|
|  | 6320 | +{ | 
|---|
|  | 6321 | +       int j, k; | 
|---|
|  | 6322 | + | 
|---|
|  | 6323 | +       switch (evt->ev_type) { | 
|---|
|  | 6324 | +       case COBALT_ACPI_EVT_SM_INT: | 
|---|
|  | 6325 | +               evt->ev_data = 0; | 
|---|
|  | 6326 | +               evt->ev_type = COBALT_ACPI_EVT_VOLT; | 
|---|
|  | 6327 | +               for (j=0; j<cobalt_nvoltages; j++) { | 
|---|
|  | 6328 | +                       k = cobalt_i2c_read_byte(COBALT_I2C_DEV_ADM1029, | 
|---|
|  | 6329 | +                                ADM1029_AIN_CTL(volt_map[j].sensor)); | 
|---|
|  | 6330 | +                       if (k & ADM1029_CTL_LATCH) { | 
|---|
|  | 6331 | +                               evt->ev_data |= (1 << j); | 
|---|
|  | 6332 | +                               volt_map[j].cache = 0; | 
|---|
|  | 6333 | +                       } | 
|---|
|  | 6334 | +               } | 
|---|
|  | 6335 | +               break; | 
|---|
|  | 6336 | + | 
|---|
|  | 6337 | +       case COBALT_ACPI_EVT_THERM: | 
|---|
|  | 6338 | +               evt->ev_data = 0; | 
|---|
|  | 6339 | +               for (j=0; j<cobalt_nthermals; j++) { | 
|---|
|  | 6340 | +                       k = cobalt_i2c_read_byte(COBALT_I2C_DEV_ADM1029, | 
|---|
|  | 6341 | +                                ADM1029_TEMP_CTL(therm_map[j].sensor)); | 
|---|
|  | 6342 | +                       if (k & ADM1029_CTL_LATCH) { | 
|---|
|  | 6343 | +                               evt->ev_data |= (1 << j); | 
|---|
|  | 6344 | +                               therm_map[j].cache = 0; | 
|---|
|  | 6345 | +                       } | 
|---|
|  | 6346 | +               } | 
|---|
|  | 6347 | +               break; | 
|---|
|  | 6348 | + | 
|---|
|  | 6349 | +       default: | 
|---|
|  | 6350 | +               return -1; | 
|---|
|  | 6351 | +       } | 
|---|
|  | 6352 | +       return 0; | 
|---|
|  | 6353 | +} | 
|---|
|  | 6354 | +#endif /* CONFIG_COBALT_ACPI */ | 
|---|
|  | 6355 | + | 
|---|
|  | 6356 | +static int | 
|---|
|  | 6357 | +adm1029_init(void) | 
|---|
|  | 6358 | +{ | 
|---|
|  | 6359 | + | 
|---|
|  | 6360 | +#ifdef CONFIG_COBALT_ACPI | 
|---|
|  | 6361 | +       cobalt_acpi_register_evt_handler(adm1029_handler, | 
|---|
|  | 6362 | +               COBALT_ACPI_EVT_THERM, NULL); | 
|---|
|  | 6363 | +       cobalt_acpi_register_evt_handler(adm1029_handler, | 
|---|
|  | 6364 | +               COBALT_ACPI_EVT_SM_INT, NULL); | 
|---|
|  | 6365 | +#endif | 
|---|
|  | 6366 | + | 
|---|
|  | 6367 | +       return 0; | 
|---|
|  | 6368 | +} | 
|---|
|  | 6369 | + | 
|---|
|  | 6370 | +static int | 
|---|
|  | 6371 | +adm1029_therm_read(struct sensor *s) | 
|---|
|  | 6372 | +{ | 
|---|
|  | 6373 | +       int sensor = s->sensor; | 
|---|
|  | 6374 | +       int val; | 
|---|
|  | 6375 | + | 
|---|
|  | 6376 | +       val = cobalt_i2c_read_byte(COBALT_I2C_DEV_ADM1029, | 
|---|
|  | 6377 | +               ADM1029_TEMP_VALUE(sensor)); | 
|---|
|  | 6378 | +       if (val < 0) { | 
|---|
|  | 6379 | +               /* read failed, return the last known value */ | 
|---|
|  | 6380 | +               return s->last_val; | 
|---|
|  | 6381 | +       } | 
|---|
|  | 6382 | +       if (val & 0x80) { | 
|---|
|  | 6383 | +               val -= 256; | 
|---|
|  | 6384 | +       } | 
|---|
|  | 6385 | +       val *= DEC_SCALAR; | 
|---|
|  | 6386 | + | 
|---|
|  | 6387 | +       return val; | 
|---|
|  | 6388 | +} | 
|---|
|  | 6389 | + | 
|---|
|  | 6390 | +static int | 
|---|
|  | 6391 | +adm1029_volt_read(struct sensor *s) | 
|---|
|  | 6392 | +{ | 
|---|
|  | 6393 | +       int sensor = s->sensor; | 
|---|
|  | 6394 | +       int val; | 
|---|
|  | 6395 | + | 
|---|
|  | 6396 | +       val = cobalt_i2c_read_byte(COBALT_I2C_DEV_ADM1029, | 
|---|
|  | 6397 | +               ADM1029_AIN_VALUE(sensor)); | 
|---|
|  | 6398 | +       if (val < 0) { | 
|---|
|  | 6399 | +               /* read failed, return the last known value */ | 
|---|
|  | 6400 | +               return s->last_val; | 
|---|
|  | 6401 | +       } | 
|---|
|  | 6402 | + | 
|---|
|  | 6403 | +       /* already scaled by 100 */ | 
|---|
|  | 6404 | +       val *= DEC_SCALAR/100; | 
|---|
|  | 6405 | + | 
|---|
|  | 6406 | +       return val; | 
|---|
|  | 6407 | +} | 
|---|
|  | 6408 | + | 
|---|
|  | 6409 | +static int | 
|---|
|  | 6410 | +alpine_vcore_scale(struct sensor *s, int val) | 
|---|
|  | 6411 | +{ | 
|---|
|  | 6412 | +       /* the measured Vbat switch cost is negligable | 
|---|
|  | 6413 | +        * due to very low current through the diode */ | 
|---|
|  | 6414 | +       return val; | 
|---|
|  | 6415 | +} | 
|---|
|  | 6416 | + | 
|---|
|  | 6417 | +#define VBAT_REG       0x608 | 
|---|
|  | 6418 | +#define VBAT_BIT       0x1 | 
|---|
|  | 6419 | +static void | 
|---|
|  | 6420 | +alpine_vbat_switch(struct sensor *s, int pre) | 
|---|
|  | 6421 | +{ | 
|---|
|  | 6422 | +       unsigned char v = inb(VBAT_REG); | 
|---|
|  | 6423 | +       unsigned long j = jiffies; | 
|---|
|  | 6424 | + | 
|---|
|  | 6425 | +       if (pre) { | 
|---|
|  | 6426 | +               v |= VBAT_BIT; | 
|---|
|  | 6427 | +               /* | 
|---|
|  | 6428 | +                * disable AIN0 INT# assertion before switching to | 
|---|
|  | 6429 | +                * Vbat because the input is shared with Vcore and | 
|---|
|  | 6430 | +                * their acceptable ranges are very different. | 
|---|
|  | 6431 | +                */ | 
|---|
|  | 6432 | +               cobalt_i2c_write_byte(COBALT_I2C_DEV_ADM1029, | 
|---|
|  | 6433 | +                       ADM1029_AIN_CTL(s->sensor), 0x0); | 
|---|
|  | 6434 | +       } else { | 
|---|
|  | 6435 | +               v &= ~VBAT_BIT; | 
|---|
|  | 6436 | +       } | 
|---|
|  | 6437 | + | 
|---|
|  | 6438 | +       outb(v, VBAT_REG); | 
|---|
|  | 6439 | + | 
|---|
|  | 6440 | +       /* | 
|---|
|  | 6441 | +        * wait for the round-robin monitor to complete a cycle | 
|---|
|  | 6442 | +        * before _and_ after toggling Vbat switch, otherwise | 
|---|
|  | 6443 | +        * stale data in AIN0 will trigger INT# assertion. | 
|---|
|  | 6444 | +        */ | 
|---|
|  | 6445 | +       while ((jiffies - j) < HZ) { | 
|---|
|  | 6446 | +               /* block for ~ 1sec */ | 
|---|
|  | 6447 | +               set_current_state(TASK_INTERRUPTIBLE); | 
|---|
|  | 6448 | +               schedule_timeout(HZ); | 
|---|
|  | 6449 | +       } | 
|---|
|  | 6450 | + | 
|---|
|  | 6451 | +       if (!pre) { | 
|---|
|  | 6452 | +               /* | 
|---|
|  | 6453 | +                * now re-enable INT# assertion capability for AIN0 | 
|---|
|  | 6454 | +                * (this also clears the AIN0 fault latch at bit 7) | 
|---|
|  | 6455 | +                */ | 
|---|
|  | 6456 | +               cobalt_i2c_write_byte(COBALT_I2C_DEV_ADM1029, | 
|---|
|  | 6457 | +                       ADM1029_AIN_CTL(s->sensor), | 
|---|
|  | 6458 | +                       ADM1029_CTL_INT_OVER | ADM1029_CTL_INT_UNDER); | 
|---|
|  | 6459 | +       } | 
|---|
|  | 6460 | +} | 
|---|
|  | 6461 | + | 
|---|
|  | 6462 | +static int | 
|---|
|  | 6463 | +alpine_vbat_scale(struct sensor *s, int val) | 
|---|
|  | 6464 | +{ | 
|---|
|  | 6465 | +       /* | 
|---|
|  | 6466 | +        * The spec says 2.5V max - but empirically, 3.3V works :) | 
|---|
|  | 6467 | +        * The Vbat switch costs 0.3 volts | 
|---|
|  | 6468 | +        */ | 
|---|
|  | 6469 | +       if (val) val += (3 * DEC_SCALAR)/10; | 
|---|
|  | 6470 | + | 
|---|
|  | 6471 | +       return val; | 
|---|
|  | 6472 | +} | 
|---|
|  | 6473 | + | 
|---|
|  | 6474 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 6475 | +static int | 
|---|
|  | 6476 | +sensor_write_proc(int nsensors, struct sensor *map, | 
|---|
|  | 6477 | +       struct file *file, const char *buf, unsigned long len, void *x) | 
|---|
|  | 6478 | +{ | 
|---|
|  | 6479 | +       char *pg; | 
|---|
|  | 6480 | + | 
|---|
|  | 6481 | +       if (len > PAGE_SIZE) { | 
|---|
|  | 6482 | +               return -EOVERFLOW; | 
|---|
|  | 6483 | +       } | 
|---|
|  | 6484 | + | 
|---|
|  | 6485 | +       pg = (char *)__get_free_page(GFP_KERNEL); | 
|---|
|  | 6486 | +       if (!pg) { | 
|---|
|  | 6487 | +               return -ENOMEM; | 
|---|
|  | 6488 | +       } | 
|---|
|  | 6489 | + | 
|---|
|  | 6490 | +       if (copy_from_user(pg, buf, len)) { | 
|---|
|  | 6491 | +               free_page((unsigned long)pg); | 
|---|
|  | 6492 | +               return -EFAULT; | 
|---|
|  | 6493 | +       } | 
|---|
|  | 6494 | +       pg[len] = '\0'; | 
|---|
|  | 6495 | + | 
|---|
|  | 6496 | +       /* format: `cache_timeout #' in seconds */ | 
|---|
|  | 6497 | +       if (len>15 && !strncmp("cache_timeout ", pg, 14) && isdigit(*(pg+14))) { | 
|---|
|  | 6498 | +               unsigned long i, sec = simple_strtoul(pg+14, NULL, 0); | 
|---|
|  | 6499 | +               for (i=0; i<nsensors; i++) | 
|---|
|  | 6500 | +                       map[i].cache_timeout = sec; | 
|---|
|  | 6501 | +       } | 
|---|
|  | 6502 | + | 
|---|
|  | 6503 | +       free_page((unsigned long)pg); | 
|---|
|  | 6504 | +       return len; | 
|---|
|  | 6505 | +} | 
|---|
|  | 6506 | + | 
|---|
|  | 6507 | +static int | 
|---|
|  | 6508 | +sensor_read_proc(int nsensors, struct sensor *map, | 
|---|
|  | 6509 | +       char *buf, char **start, off_t pos, int len, int *eof, void *x) | 
|---|
|  | 6510 | +{ | 
|---|
|  | 6511 | +       int i; | 
|---|
|  | 6512 | +       static int plen = 0; | 
|---|
|  | 6513 | + | 
|---|
|  | 6514 | +       down(&sensor_sem); | 
|---|
|  | 6515 | + | 
|---|
|  | 6516 | +       /* remember how big our last read was to avoid read() calling twice */ | 
|---|
|  | 6517 | +       if (pos && pos >= plen) { | 
|---|
|  | 6518 | +               *eof = 1; | 
|---|
|  | 6519 | +               up(&sensor_sem); | 
|---|
|  | 6520 | +               return 0; | 
|---|
|  | 6521 | +       } | 
|---|
|  | 6522 | + | 
|---|
|  | 6523 | +       plen = 0; | 
|---|
|  | 6524 | +       for (i = 0; i < nsensors; i++) { | 
|---|
|  | 6525 | +               char sbuf[32]; | 
|---|
|  | 6526 | +               if (sensor_read(&map[i], sbuf, sizeof(sbuf))) | 
|---|
|  | 6527 | +                       plen += sprintf(buf+plen, "%d [%s]: %s\n", i, map[i].desc, sbuf); | 
|---|
|  | 6528 | +       } | 
|---|
|  | 6529 | + | 
|---|
|  | 6530 | +       up(&sensor_sem); | 
|---|
|  | 6531 | + | 
|---|
|  | 6532 | +       return cobalt_gen_proc_read(buf, plen, start, pos, len, eof); | 
|---|
|  | 6533 | +} | 
|---|
|  | 6534 | + | 
|---|
|  | 6535 | +static int | 
|---|
|  | 6536 | +therm_read_proc(char *buf, char **start, off_t pos, int len, int *eof, void *x) | 
|---|
|  | 6537 | +{ | 
|---|
|  | 6538 | +       return sensor_read_proc(cobalt_nthermals, therm_map, | 
|---|
|  | 6539 | +               buf, start, pos, len, eof, x); | 
|---|
|  | 6540 | +} | 
|---|
|  | 6541 | +static int | 
|---|
|  | 6542 | +therm_write_proc(struct file *file, const char *buf, unsigned long len, void *x) | 
|---|
|  | 6543 | +{ | 
|---|
|  | 6544 | +       return sensor_write_proc(cobalt_nthermals, therm_map, file, buf, len, x); | 
|---|
|  | 6545 | +} | 
|---|
|  | 6546 | + | 
|---|
|  | 6547 | +static int | 
|---|
|  | 6548 | +volt_read_proc(char *buf, char **start, off_t pos, int len, int *eof, void *x) | 
|---|
|  | 6549 | +{ | 
|---|
|  | 6550 | +       return sensor_read_proc(cobalt_nvoltages, volt_map, | 
|---|
|  | 6551 | +               buf, start, pos, len, eof, x); | 
|---|
|  | 6552 | +} | 
|---|
|  | 6553 | +static int | 
|---|
|  | 6554 | +volt_write_proc(struct file *file, const char *buf, unsigned long len, void *x) | 
|---|
|  | 6555 | +{ | 
|---|
|  | 6556 | +       return sensor_write_proc(cobalt_nvoltages, volt_map, file, buf, len, x); | 
|---|
|  | 6557 | +} | 
|---|
|  | 6558 | +#endif /* CONFIG_PROC_FS */ | 
|---|
|  | 6559 | + | 
|---|
|  | 6560 | +#endif /* CONFIG_COBALT_SENSORS */ | 
|---|
|  | 6561 | diff -Naur linux-2.6.20.orig/drivers/cobalt/serialnum.c linux-2.6.20/drivers/cobalt/serialnum.c | 
|---|
|  | 6562 | --- linux-2.6.20.orig/drivers/cobalt/serialnum.c        1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 6563 | +++ linux-2.6.20/drivers/cobalt/serialnum.c     2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 6564 | @@ -0,0 +1,453 @@ | 
|---|
|  | 6565 | +/* $Id: serialnum.c,v 1.15 2001/10/23 20:15:27 thockin Exp $ */ | 
|---|
|  | 6566 | +/* | 
|---|
|  | 6567 | + * | 
|---|
|  | 6568 | + *   Author: Philip Gladstone, Axent Technologies | 
|---|
|  | 6569 | + *           modified for Nat Semi PC[89]7317 by asun@cobalt.com | 
|---|
|  | 6570 | + *           ported to 2.4.x by thockin@sun.com | 
|---|
|  | 6571 | + *           alpine serial eeprom by erik.glling@sun.com | 
|---|
|  | 6572 | + *   Copyright (c) 2000  Axent Technologies, Cobalt Networks | 
|---|
|  | 6573 | + *   Copyright (c) 2001  Axent Technologies, Sun Microsystems | 
|---|
|  | 6574 | + * | 
|---|
|  | 6575 | + *   This module interrogates the DS2401 Silicon Serial Number chip | 
|---|
|  | 6576 | + *   that is attached to all x86 Cobalt systems. | 
|---|
|  | 6577 | + * | 
|---|
|  | 6578 | + *   It exports /proc/cobalt/hostid which is four bytes generated from of | 
|---|
|  | 6579 | + *   the id. It can be linked to /var/adm/hostid or /etc/hostid for the | 
|---|
|  | 6580 | + *   hostid command to use. | 
|---|
|  | 6581 | + * | 
|---|
|  | 6582 | + *   It exports /proc/cobalt/serialnumber which is the entire 64 bit value | 
|---|
|  | 6583 | + *   read back (in ascii). | 
|---|
|  | 6584 | + * | 
|---|
|  | 6585 | + *   For the guts of the 1 wire protocol used herein, please see the DS2401 | 
|---|
|  | 6586 | + *   specification. | 
|---|
|  | 6587 | + * | 
|---|
|  | 6588 | + *   This program is free software; you can redistribute it and/or modify | 
|---|
|  | 6589 | + *   it under the terms of the GNU General Public License as published by | 
|---|
|  | 6590 | + *   the Free Software Foundation; either version 2 of the License, or | 
|---|
|  | 6591 | + *   (at your option) any later version. | 
|---|
|  | 6592 | + * | 
|---|
|  | 6593 | + *   This program is distributed in the hope that it will be useful, | 
|---|
|  | 6594 | + *   but WITHOUT ANY WARRANTY; without even the implied warranty of | 
|---|
|  | 6595 | + *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
|---|
|  | 6596 | + *   GNU General Public License for more details. | 
|---|
|  | 6597 | + * | 
|---|
|  | 6598 | + *   You should have received a copy of the GNU General Public License | 
|---|
|  | 6599 | + *   along with this program; if not, write to the Free Software | 
|---|
|  | 6600 | + *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | 
|---|
|  | 6601 | + * | 
|---|
|  | 6602 | + * This driver is SMP safe by nature. --TPH | 
|---|
|  | 6603 | + */ | 
|---|
|  | 6604 | +#include <linux/config.h> | 
|---|
|  | 6605 | +#if defined (CONFIG_COBALT_SERNUM) || defined(CONFIG_COBALT_SERNUM_MODULE) | 
|---|
|  | 6606 | + | 
|---|
|  | 6607 | +#include <linux/module.h> | 
|---|
|  | 6608 | +#include <linux/stddef.h> | 
|---|
|  | 6609 | +#include <linux/version.h> | 
|---|
|  | 6610 | +#include <linux/types.h> | 
|---|
|  | 6611 | +#include <linux/proc_fs.h> | 
|---|
|  | 6612 | +#include <linux/delay.h> | 
|---|
|  | 6613 | +#include <asm/uaccess.h> | 
|---|
|  | 6614 | +#include <linux/pci.h> | 
|---|
|  | 6615 | +#include <linux/init.h> | 
|---|
|  | 6616 | +#include <asm/io.h> | 
|---|
|  | 6617 | + | 
|---|
|  | 6618 | +#include <cobalt/cobalt.h> | 
|---|
|  | 6619 | +#include <cobalt/systype.h> | 
|---|
|  | 6620 | +#include <cobalt/superio.h> | 
|---|
|  | 6621 | +#include <cobalt/serialnum.h> | 
|---|
|  | 6622 | +#include <cobalt/i2c.h> | 
|---|
|  | 6623 | + | 
|---|
|  | 6624 | +#include <linux/interrupt.h> | 
|---|
|  | 6625 | + | 
|---|
|  | 6626 | +#define SN_DRIVER                      "Cobalt Networks Serial Number driver" | 
|---|
|  | 6627 | +#define SN_DRIVER_VMAJ         1 | 
|---|
|  | 6628 | +#define SN_DRIVER_VMIN         6 | 
|---|
|  | 6629 | + | 
|---|
|  | 6630 | +/* dependent on systype */ | 
|---|
|  | 6631 | +static unsigned int sn_direction; | 
|---|
|  | 6632 | +static unsigned int sn_output; | 
|---|
|  | 6633 | +static unsigned int sn_input; | 
|---|
|  | 6634 | +static unsigned int sn_mask; | 
|---|
|  | 6635 | + | 
|---|
|  | 6636 | +/* 3k style systems */ | 
|---|
|  | 6637 | +#define III_SN_DIRECTION       0x7d | 
|---|
|  | 6638 | +#define III_SN_OUTPUT          0x7e | 
|---|
|  | 6639 | +#define III_SN_INPUT           0x7f | 
|---|
|  | 6640 | +#define III_SN_MASK            0x08 | 
|---|
|  | 6641 | +static struct pci_dev *id_dev; | 
|---|
|  | 6642 | + | 
|---|
|  | 6643 | +/* 5k style systems */ | 
|---|
|  | 6644 | +#define V_SN_DIRECTION         (sn_io_base + 0x01) | 
|---|
|  | 6645 | +#define V_SN_OUTPUT            (sn_io_base + 0x00) | 
|---|
|  | 6646 | +#define V_SN_INPUT             (sn_io_base + 0x00) | 
|---|
|  | 6647 | +#define V_SN_MASK              (sn_io_base + 0x01) | 
|---|
|  | 6648 | +static unsigned int sn_io_base; | 
|---|
|  | 6649 | + | 
|---|
|  | 6650 | +#define SSN_SIZE       8       /* bytes */ | 
|---|
|  | 6651 | +static char ssn_string[SSN_SIZE * 2 + 1]; | 
|---|
|  | 6652 | +static unsigned long hostid; | 
|---|
|  | 6653 | +static int debug; | 
|---|
|  | 6654 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 6655 | +#ifdef CONFIG_COBALT_OLDPROC | 
|---|
|  | 6656 | +static struct proc_dir_entry *proc_hostid; | 
|---|
|  | 6657 | +static struct proc_dir_entry *proc_serialnum; | 
|---|
|  | 6658 | +#endif | 
|---|
|  | 6659 | +static struct proc_dir_entry *proc_chostid; | 
|---|
|  | 6660 | +static struct proc_dir_entry *proc_cserialnum; | 
|---|
|  | 6661 | +#endif | 
|---|
|  | 6662 | + | 
|---|
|  | 6663 | +static int | 
|---|
|  | 6664 | +hostid_read(char *buf, char **start, off_t pos, int len, int *eof, void *x) | 
|---|
|  | 6665 | +{ | 
|---|
|  | 6666 | +       int plen = sizeof(hostid); | 
|---|
|  | 6667 | +       memcpy(buf, &hostid, sizeof(hostid)); | 
|---|
|  | 6668 | +       return cobalt_gen_proc_read(buf, plen, start, pos, len, eof); | 
|---|
|  | 6669 | +} | 
|---|
|  | 6670 | + | 
|---|
|  | 6671 | +static int | 
|---|
|  | 6672 | +serialnum_read(char *buf, char **start, off_t pos, int len, int *eof, void *x) | 
|---|
|  | 6673 | +{ | 
|---|
|  | 6674 | +       int plen = sizeof(ssn_string); | 
|---|
|  | 6675 | +       sprintf(buf, "%s\n", ssn_string); | 
|---|
|  | 6676 | +       return cobalt_gen_proc_read(buf, plen, start, pos, len, eof); | 
|---|
|  | 6677 | +} | 
|---|
|  | 6678 | + | 
|---|
|  | 6679 | +/* set up the requisite IO bits */ | 
|---|
|  | 6680 | +static int __init | 
|---|
|  | 6681 | +io_init(void) | 
|---|
|  | 6682 | +{ | 
|---|
|  | 6683 | +       unsigned char data; | 
|---|
|  | 6684 | + | 
|---|
|  | 6685 | +       if (cobt_is_3k()) { | 
|---|
|  | 6686 | +               /* The GPIO tied to the ID chip is on the PMU */ | 
|---|
|  | 6687 | +               id_dev = pci_find_device(PCI_VENDOR_ID_AL, | 
|---|
|  | 6688 | +                       PCI_DEVICE_ID_AL_M7101, NULL); | 
|---|
|  | 6689 | +               if (!id_dev) { | 
|---|
|  | 6690 | +                       EPRINTK("can't find PMU for serialnumber access\n"); | 
|---|
|  | 6691 | +                       return -ENXIO; | 
|---|
|  | 6692 | +               } | 
|---|
|  | 6693 | + | 
|---|
|  | 6694 | +               /* Set input mode on GPIO3 */ | 
|---|
|  | 6695 | +               pci_read_config_byte(id_dev, sn_direction, &data); | 
|---|
|  | 6696 | +               if (debug > 1) { | 
|---|
|  | 6697 | +                       WPRINTK("read of register 0x%x = 0x%x\n", | 
|---|
|  | 6698 | +                               sn_direction, data); | 
|---|
|  | 6699 | +               } | 
|---|
|  | 6700 | +               if (data & sn_mask) { | 
|---|
|  | 6701 | +                       pci_write_config_byte(id_dev, sn_direction, | 
|---|
|  | 6702 | +                               data & ~sn_mask); | 
|---|
|  | 6703 | +               } | 
|---|
|  | 6704 | + | 
|---|
|  | 6705 | +               /* Set the output value to be 0 */ | 
|---|
|  | 6706 | +               pci_read_config_byte(id_dev, sn_output, &data); | 
|---|
|  | 6707 | +               if (debug > 1) { | 
|---|
|  | 6708 | +                       WPRINTK("read of register 0x%x = 0x%x\n", | 
|---|
|  | 6709 | +                               sn_output, data); | 
|---|
|  | 6710 | +               } | 
|---|
|  | 6711 | +               if (data & sn_mask) { | 
|---|
|  | 6712 | +                       pci_write_config_byte(id_dev, sn_output, | 
|---|
|  | 6713 | +                               data & ~sn_mask); | 
|---|
|  | 6714 | +               } | 
|---|
|  | 6715 | +       } else if (cobt_is_5k()) { | 
|---|
|  | 6716 | +               u16 addr; | 
|---|
|  | 6717 | + | 
|---|
|  | 6718 | +               addr = superio_ldev_base(PC87317_DEV_GPIO); | 
|---|
|  | 6719 | +               if (addr) { | 
|---|
|  | 6720 | +                       u8 val; | 
|---|
|  | 6721 | + | 
|---|
|  | 6722 | +                       sn_io_base = addr; | 
|---|
|  | 6723 | + | 
|---|
|  | 6724 | +                       /* set output value to 0 */ | 
|---|
|  | 6725 | +                       val = inb(sn_direction); | 
|---|
|  | 6726 | +                       outb(val | sn_mask, sn_direction); | 
|---|
|  | 6727 | +                       data = inb(sn_output); | 
|---|
|  | 6728 | +                       if (data & sn_mask) { | 
|---|
|  | 6729 | +                               outb(data & ~sn_mask, sn_output); | 
|---|
|  | 6730 | +                       } | 
|---|
|  | 6731 | +                       /* set to input */ | 
|---|
|  | 6732 | +                       outb(val & ~sn_mask, sn_direction); | 
|---|
|  | 6733 | +               } | 
|---|
|  | 6734 | +       } else { | 
|---|
|  | 6735 | +               return -ENXIO; | 
|---|
|  | 6736 | +       } | 
|---|
|  | 6737 | + | 
|---|
|  | 6738 | +       /* pick proper variables */ | 
|---|
|  | 6739 | +       if (cobt_is_3k()) { | 
|---|
|  | 6740 | +               sn_direction = III_SN_DIRECTION; | 
|---|
|  | 6741 | +               sn_output = III_SN_OUTPUT; | 
|---|
|  | 6742 | +               sn_input = III_SN_INPUT; | 
|---|
|  | 6743 | +               sn_mask = III_SN_MASK; | 
|---|
|  | 6744 | +       } else if (cobt_is_5k()) { | 
|---|
|  | 6745 | +               sn_direction = V_SN_DIRECTION; | 
|---|
|  | 6746 | +               sn_output = V_SN_OUTPUT; | 
|---|
|  | 6747 | +               sn_input = V_SN_INPUT; | 
|---|
|  | 6748 | +               sn_mask = V_SN_MASK; | 
|---|
|  | 6749 | +       } else { | 
|---|
|  | 6750 | +               return -1; | 
|---|
|  | 6751 | +       } | 
|---|
|  | 6752 | + | 
|---|
|  | 6753 | +       /* Let things calm down */ | 
|---|
|  | 6754 | +       udelay(500); | 
|---|
|  | 6755 | +       return 0; | 
|---|
|  | 6756 | +} | 
|---|
|  | 6757 | + | 
|---|
|  | 6758 | +/* write out a bit */ | 
|---|
|  | 6759 | +static void __init | 
|---|
|  | 6760 | +io_write(int delay) | 
|---|
|  | 6761 | +{ | 
|---|
|  | 6762 | +       if (cobt_is_3k()) { | 
|---|
|  | 6763 | +               unsigned char data; | 
|---|
|  | 6764 | +               /* Set output mode on GPIO3 */ | 
|---|
|  | 6765 | +               pci_read_config_byte(id_dev, sn_direction, &data); | 
|---|
|  | 6766 | +               pci_write_config_byte(id_dev, sn_direction, data | sn_mask); | 
|---|
|  | 6767 | +               udelay(delay); | 
|---|
|  | 6768 | + | 
|---|
|  | 6769 | +               /* Set input mode */ | 
|---|
|  | 6770 | +               pci_write_config_byte(id_dev, sn_direction, data & ~sn_mask); | 
|---|
|  | 6771 | +       } else if (cobt_is_5k()) { | 
|---|
|  | 6772 | +               unsigned char direction; | 
|---|
|  | 6773 | + | 
|---|
|  | 6774 | +               /* change to output and back */ | 
|---|
|  | 6775 | +               direction = inb(sn_direction); | 
|---|
|  | 6776 | +               outb(direction | sn_mask, sn_direction); | 
|---|
|  | 6777 | +               udelay(delay); | 
|---|
|  | 6778 | +               outb(direction & ~sn_mask, sn_direction); | 
|---|
|  | 6779 | +       } | 
|---|
|  | 6780 | +} | 
|---|
|  | 6781 | + | 
|---|
|  | 6782 | +/* read in a bit */ | 
|---|
|  | 6783 | +static int __init | 
|---|
|  | 6784 | +io_read(void) | 
|---|
|  | 6785 | +{ | 
|---|
|  | 6786 | +       unsigned char data = 0; | 
|---|
|  | 6787 | + | 
|---|
|  | 6788 | +       /* Get the input value */ | 
|---|
|  | 6789 | +       if (cobt_is_3k()) { | 
|---|
|  | 6790 | +               pci_read_config_byte(id_dev, sn_input, &data); | 
|---|
|  | 6791 | +       } else if (cobt_is_5k()) { | 
|---|
|  | 6792 | +               data = inb(sn_input); | 
|---|
|  | 6793 | +       } | 
|---|
|  | 6794 | + | 
|---|
|  | 6795 | +       return (data & sn_mask) ? 1 : 0; | 
|---|
|  | 6796 | +} | 
|---|
|  | 6797 | + | 
|---|
|  | 6798 | +static void __init | 
|---|
|  | 6799 | +io_write_byte(unsigned char c) | 
|---|
|  | 6800 | +{ | 
|---|
|  | 6801 | +       int i; | 
|---|
|  | 6802 | +       unsigned long flags; | 
|---|
|  | 6803 | + | 
|---|
|  | 6804 | +       local_save_flags(flags); | 
|---|
|  | 6805 | + | 
|---|
|  | 6806 | +       for (i = 0; i < 8; i++, c >>= 1) { | 
|---|
|  | 6807 | +               local_irq_disable(); | 
|---|
|  | 6808 | +               if (c & 1) { | 
|---|
|  | 6809 | +                       /* Transmit a 1 */ | 
|---|
|  | 6810 | +                       io_write(5); | 
|---|
|  | 6811 | +                       udelay(80); | 
|---|
|  | 6812 | +               } else { | 
|---|
|  | 6813 | +                       /* Transmit a 0 */ | 
|---|
|  | 6814 | +                       io_write(80); | 
|---|
|  | 6815 | +                       udelay(10); | 
|---|
|  | 6816 | +               } | 
|---|
|  | 6817 | +               local_irq_restore(flags); | 
|---|
|  | 6818 | +       } | 
|---|
|  | 6819 | +} | 
|---|
|  | 6820 | + | 
|---|
|  | 6821 | +static int __init | 
|---|
|  | 6822 | +io_read_byte(void) | 
|---|
|  | 6823 | +{ | 
|---|
|  | 6824 | +       int i; | 
|---|
|  | 6825 | +       int c = 0; | 
|---|
|  | 6826 | +       unsigned long flags; | 
|---|
|  | 6827 | + | 
|---|
|  | 6828 | +       local_save_flags(flags); | 
|---|
|  | 6829 | + | 
|---|
|  | 6830 | +       for (i = 0; i < 8; i++) { | 
|---|
|  | 6831 | +               local_irq_disable(); | 
|---|
|  | 6832 | +               io_write(1);    /* Start the read */ | 
|---|
|  | 6833 | +               udelay(2); | 
|---|
|  | 6834 | +               if (io_read()) { | 
|---|
|  | 6835 | +                       c |= 1 << i; | 
|---|
|  | 6836 | +               } | 
|---|
|  | 6837 | +               udelay(60); | 
|---|
|  | 6838 | +               local_irq_restore(flags); | 
|---|
|  | 6839 | +       } | 
|---|
|  | 6840 | + | 
|---|
|  | 6841 | +       return c; | 
|---|
|  | 6842 | +} | 
|---|
|  | 6843 | + | 
|---|
|  | 6844 | +static int __init | 
|---|
|  | 6845 | +get_ssn(unsigned char *buf) | 
|---|
|  | 6846 | +{ | 
|---|
|  | 6847 | +       int i; | 
|---|
|  | 6848 | +       unsigned long flags; | 
|---|
|  | 6849 | + | 
|---|
|  | 6850 | +       /* | 
|---|
|  | 6851 | +        * Alpine does not have a dallas chip.  Instead | 
|---|
|  | 6852 | +        * we read from an eprom. | 
|---|
|  | 6853 | +        */ | 
|---|
|  | 6854 | +       if (cobt_is_alpine()) { | 
|---|
|  | 6855 | +               for (i = 0; i < 8; i++) { | 
|---|
|  | 6856 | +                       buf[i] = cobalt_i2c_read_byte(COBALT_I2C_DEV_AT24C02, | 
|---|
|  | 6857 | +                               12 + i); | 
|---|
|  | 6858 | +               } | 
|---|
|  | 6859 | +               return 0; | 
|---|
|  | 6860 | +       } | 
|---|
|  | 6861 | + | 
|---|
|  | 6862 | +       /* | 
|---|
|  | 6863 | +        * bit-bang the Dallas 2401 | 
|---|
|  | 6864 | +        */ | 
|---|
|  | 6865 | + | 
|---|
|  | 6866 | +       local_save_flags(flags); | 
|---|
|  | 6867 | +       local_irq_disable(); | 
|---|
|  | 6868 | + | 
|---|
|  | 6869 | +       /* Master Reset Pulse */ | 
|---|
|  | 6870 | +       for (i = 0; i < 600; i += 30) { | 
|---|
|  | 6871 | +               if (io_read()) { | 
|---|
|  | 6872 | +                       break; | 
|---|
|  | 6873 | +               } | 
|---|
|  | 6874 | +       } | 
|---|
|  | 6875 | + | 
|---|
|  | 6876 | +       if (i >= 600) { | 
|---|
|  | 6877 | +               if (debug) { | 
|---|
|  | 6878 | +                       EPRINTK("the data line seems to be held low\n"); | 
|---|
|  | 6879 | +               } | 
|---|
|  | 6880 | +               local_irq_restore(flags); | 
|---|
|  | 6881 | +               return -ENXIO; | 
|---|
|  | 6882 | +       } | 
|---|
|  | 6883 | + | 
|---|
|  | 6884 | +       io_write(600); | 
|---|
|  | 6885 | + | 
|---|
|  | 6886 | +       for (i = 0; i < 300; i += 15) { | 
|---|
|  | 6887 | +               udelay(15); | 
|---|
|  | 6888 | +               if (io_read() == 0) { | 
|---|
|  | 6889 | +                       /* We got a presence pulse */ | 
|---|
|  | 6890 | +                       udelay(600);    /* Wait for things to quiet down */ | 
|---|
|  | 6891 | +                       break; | 
|---|
|  | 6892 | +               } | 
|---|
|  | 6893 | +       } | 
|---|
|  | 6894 | +       local_irq_restore(flags); | 
|---|
|  | 6895 | + | 
|---|
|  | 6896 | +       if (i >= 300) { | 
|---|
|  | 6897 | +               if (debug) | 
|---|
|  | 6898 | +                       EPRINTK("no presence pulse detected\n"); | 
|---|
|  | 6899 | +               return -ENXIO; | 
|---|
|  | 6900 | +       } | 
|---|
|  | 6901 | + | 
|---|
|  | 6902 | +       io_write_byte(0x33); | 
|---|
|  | 6903 | + | 
|---|
|  | 6904 | +       for (i = 0; i < 8; i++) { | 
|---|
|  | 6905 | +               int rc; | 
|---|
|  | 6906 | + | 
|---|
|  | 6907 | +               rc = io_read_byte(); | 
|---|
|  | 6908 | +               if (rc < 0) { | 
|---|
|  | 6909 | +                       return rc; | 
|---|
|  | 6910 | +               } | 
|---|
|  | 6911 | + | 
|---|
|  | 6912 | +               *buf++ = rc; | 
|---|
|  | 6913 | +       } | 
|---|
|  | 6914 | + | 
|---|
|  | 6915 | +       return 0; | 
|---|
|  | 6916 | +} | 
|---|
|  | 6917 | + | 
|---|
|  | 6918 | +int __init | 
|---|
|  | 6919 | +cobalt_serialnum_init(void) | 
|---|
|  | 6920 | +{ | 
|---|
|  | 6921 | +       unsigned char ssn[SSN_SIZE]; | 
|---|
|  | 6922 | +       int rc; | 
|---|
|  | 6923 | +       int i; | 
|---|
|  | 6924 | + | 
|---|
|  | 6925 | +    printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", SN_DRIVER,SN_DRIVER_VMAJ,SN_DRIVER_VMIN); | 
|---|
|  | 6926 | +       /* set up for proper IO */ | 
|---|
|  | 6927 | +       rc = io_init(); | 
|---|
|  | 6928 | +       if (rc) { | 
|---|
|  | 6929 | +               return rc; | 
|---|
|  | 6930 | +       } | 
|---|
|  | 6931 | + | 
|---|
|  | 6932 | +       /* | 
|---|
|  | 6933 | +        * NOTE: the below algorithm CAN NOT be changed.  We have many systems | 
|---|
|  | 6934 | +        * out there registered with the serial number AS DERIVED by this | 
|---|
|  | 6935 | +        * algorithm. | 
|---|
|  | 6936 | +        */ | 
|---|
|  | 6937 | + | 
|---|
|  | 6938 | +       rc = get_ssn(ssn); | 
|---|
|  | 6939 | +       if (rc) { | 
|---|
|  | 6940 | +               return rc; | 
|---|
|  | 6941 | +       } | 
|---|
|  | 6942 | + | 
|---|
|  | 6943 | +       /* Convert to ssn_string */ | 
|---|
|  | 6944 | +       for (i = 7; i >= 0; i--) { | 
|---|
|  | 6945 | +               sprintf(ssn_string + (7 - i) * 2, "%02x", ssn[i]); | 
|---|
|  | 6946 | +       } | 
|---|
|  | 6947 | + | 
|---|
|  | 6948 | +       /* get four bytes for a pretty unique (not guaranteed) hostid */ | 
|---|
|  | 6949 | +       hostid = *(unsigned long *)ssn ^ *(unsigned long *)(ssn+4); | 
|---|
|  | 6950 | + | 
|---|
|  | 6951 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 6952 | +#ifdef CONFIG_COBALT_OLDPROC | 
|---|
|  | 6953 | +       proc_hostid = create_proc_read_entry("hostid", 0, NULL, | 
|---|
|  | 6954 | +               hostid_read, NULL); | 
|---|
|  | 6955 | +       if (!proc_hostid) { | 
|---|
|  | 6956 | +               EPRINTK("can't create /proc/hostid\n"); | 
|---|
|  | 6957 | +       } | 
|---|
|  | 6958 | +       proc_serialnum = create_proc_read_entry("serialnumber", 0, NULL, | 
|---|
|  | 6959 | +               serialnum_read, NULL); | 
|---|
|  | 6960 | +       if (!proc_serialnum) { | 
|---|
|  | 6961 | +               EPRINTK("can't create /proc/serialnumber\n"); | 
|---|
|  | 6962 | +       } | 
|---|
|  | 6963 | +#endif | 
|---|
|  | 6964 | +       proc_chostid = create_proc_read_entry("hostid", 0, proc_cobalt, | 
|---|
|  | 6965 | +               hostid_read, NULL); | 
|---|
|  | 6966 | +       if (!proc_chostid) { | 
|---|
|  | 6967 | +               EPRINTK("can't create /proc/cobalt/hostid\n"); | 
|---|
|  | 6968 | +       } | 
|---|
|  | 6969 | +       proc_cserialnum = create_proc_read_entry("serialnumber", 0, | 
|---|
|  | 6970 | +               proc_cobalt, serialnum_read, NULL); | 
|---|
|  | 6971 | +       if (!proc_cserialnum) { | 
|---|
|  | 6972 | +               EPRINTK("can't create /proc/cobalt/serialnumber\n"); | 
|---|
|  | 6973 | +       } | 
|---|
|  | 6974 | +#endif | 
|---|
|  | 6975 | + | 
|---|
|  | 6976 | +       return 0; | 
|---|
|  | 6977 | +} | 
|---|
|  | 6978 | + | 
|---|
|  | 6979 | +char * | 
|---|
|  | 6980 | +cobalt_serialnum_get(void) | 
|---|
|  | 6981 | +{ | 
|---|
|  | 6982 | +       return ssn_string; | 
|---|
|  | 6983 | +} | 
|---|
|  | 6984 | + | 
|---|
|  | 6985 | +unsigned long | 
|---|
|  | 6986 | +cobalt_hostid_get(void) | 
|---|
|  | 6987 | +{ | 
|---|
|  | 6988 | +       return hostid; | 
|---|
|  | 6989 | +} | 
|---|
|  | 6990 | + | 
|---|
|  | 6991 | +#if defined(CONFIG_COBALT_SERNUM_MODULE) | 
|---|
|  | 6992 | +MODULE_PARM(debug, "i"); | 
|---|
|  | 6993 | + | 
|---|
|  | 6994 | +int | 
|---|
|  | 6995 | +init_module(void) | 
|---|
|  | 6996 | +{ | 
|---|
|  | 6997 | +       return cobalt_serialnum_init(); | 
|---|
|  | 6998 | +} | 
|---|
|  | 6999 | + | 
|---|
|  | 7000 | +void | 
|---|
|  | 7001 | +cleanup_module(void) | 
|---|
|  | 7002 | +{ | 
|---|
|  | 7003 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 7004 | +#ifdef CONFIG_COBALT_OLDPROC | 
|---|
|  | 7005 | +       remove_proc_entry("hostid", NULL); | 
|---|
|  | 7006 | +       remove_proc_entry("serialnumber", NULL); | 
|---|
|  | 7007 | +#endif | 
|---|
|  | 7008 | +       remove_proc_entry("hostid", proc_cobalt); | 
|---|
|  | 7009 | +       remove_proc_entry("serialnumber", proc_cobalt); | 
|---|
|  | 7010 | +#endif | 
|---|
|  | 7011 | +} | 
|---|
|  | 7012 | + | 
|---|
|  | 7013 | +module_init(init_module); | 
|---|
|  | 7014 | +module_exit(cleanup_module); | 
|---|
|  | 7015 | +#endif /* MODULE */ | 
|---|
|  | 7016 | + | 
|---|
|  | 7017 | +#endif /* CONFIG_COBALT_SERNUM */ | 
|---|
|  | 7018 | diff -Naur linux-2.6.20.orig/drivers/cobalt/systype.c linux-2.6.20/drivers/cobalt/systype.c | 
|---|
|  | 7019 | --- linux-2.6.20.orig/drivers/cobalt/systype.c  1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 7020 | +++ linux-2.6.20/drivers/cobalt/systype.c       2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 7021 | @@ -0,0 +1,280 @@ | 
|---|
|  | 7022 | +/* | 
|---|
|  | 7023 | + * $Id: systype.c,v 1.33 2002/11/04 17:54:15 thockin Exp $ | 
|---|
|  | 7024 | + * systype.c : routines for figuring out which Cobalt system this is | 
|---|
|  | 7025 | + * | 
|---|
|  | 7026 | + * Copyright 2001-2002 Sun Microsystems, Inc. | 
|---|
|  | 7027 | + * | 
|---|
|  | 7028 | + * By:  Tim Hockin | 
|---|
|  | 7029 | + *     Adrian Sun | 
|---|
|  | 7030 | + *     Duncan Laurie | 
|---|
|  | 7031 | + * | 
|---|
|  | 7032 | + * This driver is SMP safe by nature. --TPH | 
|---|
|  | 7033 | + */ | 
|---|
|  | 7034 | + | 
|---|
|  | 7035 | +#include <linux/config.h> | 
|---|
|  | 7036 | + | 
|---|
|  | 7037 | +#include <linux/pci.h> | 
|---|
|  | 7038 | +#include <linux/init.h> | 
|---|
|  | 7039 | +#include <linux/proc_fs.h> | 
|---|
|  | 7040 | +#include <linux/module.h> | 
|---|
|  | 7041 | + | 
|---|
|  | 7042 | +#include <cobalt/cobalt.h> | 
|---|
|  | 7043 | +#include <cobalt/systype.h> | 
|---|
|  | 7044 | +#include <cobalt/i2c.h> | 
|---|
|  | 7045 | + | 
|---|
|  | 7046 | +/* for easy first-pass analysis */ | 
|---|
|  | 7047 | +#if defined(CONFIG_COBALT_GEN_III) | 
|---|
|  | 7048 | +int COBALT_GENERATION_III_DEFINED; | 
|---|
|  | 7049 | +#endif | 
|---|
|  | 7050 | +#if defined(CONFIG_COBALT_GEN_V) | 
|---|
|  | 7051 | +int COBALT_GENERATION_V_DEFINED; | 
|---|
|  | 7052 | +#endif | 
|---|
|  | 7053 | + | 
|---|
|  | 7054 | +cobt_sys_t cobt_type = COBT_UNINITIALIZED; | 
|---|
|  | 7055 | +EXPORT_SYMBOL(cobt_type); | 
|---|
|  | 7056 | +unsigned long cobt_rev; | 
|---|
|  | 7057 | +EXPORT_SYMBOL(cobt_rev); | 
|---|
|  | 7058 | + | 
|---|
|  | 7059 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 7060 | +static struct proc_dir_entry *proc_systype; | 
|---|
|  | 7061 | +#endif | 
|---|
|  | 7062 | +static int systype_read_proc(char *buf, char **start, off_t pos, int len, | 
|---|
|  | 7063 | +       int *eof, void *x); | 
|---|
|  | 7064 | +static char *systype_str(cobt_sys_t type); | 
|---|
|  | 7065 | +static unsigned long boardrev_read(void); | 
|---|
|  | 7066 | + | 
|---|
|  | 7067 | +void __init | 
|---|
|  | 7068 | +cobalt_boardrev_init(void) | 
|---|
|  | 7069 | +{ | 
|---|
|  | 7070 | +       cobt_rev = boardrev_read(); | 
|---|
|  | 7071 | +} | 
|---|
|  | 7072 | + | 
|---|
|  | 7073 | +int __init | 
|---|
|  | 7074 | +cobalt_systype_init(void) | 
|---|
|  | 7075 | +{ | 
|---|
|  | 7076 | +       cobalt_systype_probe(); | 
|---|
|  | 7077 | + | 
|---|
|  | 7078 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 7079 | +       proc_systype = create_proc_read_entry("systype", 0, | 
|---|
|  | 7080 | +               proc_cobalt, systype_read_proc, NULL); | 
|---|
|  | 7081 | +       if (!proc_systype) { | 
|---|
|  | 7082 | +               EPRINTK("can't create /proc/cobalt/systype\n"); | 
|---|
|  | 7083 | +       } | 
|---|
|  | 7084 | +#endif | 
|---|
|  | 7085 | + | 
|---|
|  | 7086 | +       if (cobt_type == COBT_UNKNOWN) { | 
|---|
|  | 7087 | +               printk(KERN_INFO "Cobalt system type is unknown, trouble will ensue (I can vouch for this)\n"); | 
|---|
|  | 7088 | +               return -1; | 
|---|
|  | 7089 | +       } else { | 
|---|
|  | 7090 | +           printk(KERN_INFO "Cobalt system type is %s\n",systype_str(cobt_type)); | 
|---|
|  | 7091 | +           return 0; | 
|---|
|  | 7092 | +    } | 
|---|
|  | 7093 | +} | 
|---|
|  | 7094 | + | 
|---|
|  | 7095 | +#if defined(CONFIG_COBALT_GEN_III) | 
|---|
|  | 7096 | +static cobt_sys_t | 
|---|
|  | 7097 | +systype_probe_3k(void) | 
|---|
|  | 7098 | +{ | 
|---|
|  | 7099 | +       struct pci_dev *pdev; | 
|---|
|  | 7100 | +       cobt_sys_t retval = COBT_UNKNOWN; | 
|---|
|  | 7101 | + | 
|---|
|  | 7102 | +       /* board identifier for RaQ3/4 vs Qube3 is on the PMU @ 0x7f */ | 
|---|
|  | 7103 | +       pdev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL); | 
|---|
|  | 7104 | +       if (pdev) { | 
|---|
|  | 7105 | +               /* | 
|---|
|  | 7106 | +                * check to see what board we are on | 
|---|
|  | 7107 | +                * ( RaQ 3, RaQ 4, Qube 3 ) | 
|---|
|  | 7108 | +                */ | 
|---|
|  | 7109 | +               unsigned char val; | 
|---|
|  | 7110 | + | 
|---|
|  | 7111 | +           /* momentarily set DOGB# to input */ | 
|---|
|  | 7112 | +               pci_read_config_byte(pdev, 0x7d, &val); | 
|---|
|  | 7113 | +               pci_write_config_byte(pdev, 0x7d, val & ~0x20); | 
|---|
|  | 7114 | + | 
|---|
|  | 7115 | +               /* read the GPIO register */ | 
|---|
|  | 7116 | +               pci_read_config_byte(pdev, 0x7f, &val); | 
|---|
|  | 7117 | +               /* RaQ3/4 boards have DOGB (0x20) high, | 
|---|
|  | 7118 | +                * Qube3 has DOGB low */ | 
|---|
|  | 7119 | +               if (val & 0x20) { | 
|---|
|  | 7120 | +                   retval = COBT_PACIFICA; | 
|---|
|  | 7121 | +               } else { | 
|---|
|  | 7122 | +                   retval = COBT_CARMEL; | 
|---|
|  | 7123 | +               } | 
|---|
|  | 7124 | + | 
|---|
|  | 7125 | +               /* change DOGB back to output */ | 
|---|
|  | 7126 | +               pci_read_config_byte(pdev, 0x7d, &val); | 
|---|
|  | 7127 | +               pci_write_config_byte(pdev, 0x7d, val | 0x20); | 
|---|
|  | 7128 | +       } | 
|---|
|  | 7129 | + | 
|---|
|  | 7130 | +       /* assign to this, so the compiler shuts up */ | 
|---|
|  | 7131 | +       COBALT_GENERATION_III_DEFINED = 1; | 
|---|
|  | 7132 | + | 
|---|
|  | 7133 | +       return retval; | 
|---|
|  | 7134 | +} | 
|---|
|  | 7135 | +#else | 
|---|
|  | 7136 | +#define systype_probe_3k()     (COBT_UNKNOWN) | 
|---|
|  | 7137 | +#endif | 
|---|
|  | 7138 | + | 
|---|
|  | 7139 | +#if defined(CONFIG_COBALT_GEN_V) | 
|---|
|  | 7140 | +static cobt_sys_t | 
|---|
|  | 7141 | +systype_probe_5k(void) | 
|---|
|  | 7142 | +{ | 
|---|
|  | 7143 | +       struct pci_dev *pdev; | 
|---|
|  | 7144 | +       cobt_sys_t retval = COBT_UNKNOWN; | 
|---|
|  | 7145 | + | 
|---|
|  | 7146 | +       /* is it a gen V ? */ | 
|---|
|  | 7147 | +       pdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, | 
|---|
|  | 7148 | +               PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL); | 
|---|
|  | 7149 | +       if (pdev) { | 
|---|
|  | 7150 | +               retval = COBT_MONTEREY; | 
|---|
|  | 7151 | +               goto out; | 
|---|
|  | 7152 | +       } | 
|---|
|  | 7153 | + | 
|---|
|  | 7154 | +       pdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, | 
|---|
|  | 7155 | +               PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL); | 
|---|
|  | 7156 | +       if (pdev) { | 
|---|
|  | 7157 | +               pdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, | 
|---|
|  | 7158 | +                       PCI_DEVICE_ID_SERVERWORKS_LE, NULL); | 
|---|
|  | 7159 | +               if (pdev) { | 
|---|
|  | 7160 | +                       retval = COBT_ALPINE; | 
|---|
|  | 7161 | +                       goto out; | 
|---|
|  | 7162 | +               } | 
|---|
|  | 7163 | +       } | 
|---|
|  | 7164 | + | 
|---|
|  | 7165 | +out: | 
|---|
|  | 7166 | +       /* assign to this, so the compiler shuts up */ | 
|---|
|  | 7167 | +       COBALT_GENERATION_V_DEFINED = 1; | 
|---|
|  | 7168 | + | 
|---|
|  | 7169 | +       return retval; | 
|---|
|  | 7170 | +} | 
|---|
|  | 7171 | +#else | 
|---|
|  | 7172 | +#define systype_probe_5k()     (COBT_UNKNOWN) | 
|---|
|  | 7173 | +#endif | 
|---|
|  | 7174 | + | 
|---|
|  | 7175 | +static cobt_sys_t | 
|---|
|  | 7176 | +systype_probe_gp(void) | 
|---|
|  | 7177 | +{ | 
|---|
|  | 7178 | +       struct pci_dev *pdev; | 
|---|
|  | 7179 | +       cobt_sys_t retval = COBT_UNKNOWN; | 
|---|
|  | 7180 | + | 
|---|
|  | 7181 | +       /* is it a GP system? */ | 
|---|
|  | 7182 | +       pdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, | 
|---|
|  | 7183 | +               PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL); | 
|---|
|  | 7184 | +       if (pdev) { | 
|---|
|  | 7185 | +               pdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, | 
|---|
|  | 7186 | +                       PCI_DEVICE_ID_SERVERWORKS_HE, NULL); | 
|---|
|  | 7187 | +               if (pdev) { | 
|---|
|  | 7188 | +                       retval = COBT_BIGBEAR; | 
|---|
|  | 7189 | +               } | 
|---|
|  | 7190 | +       } | 
|---|
|  | 7191 | + | 
|---|
|  | 7192 | +       return retval; | 
|---|
|  | 7193 | +} | 
|---|
|  | 7194 | + | 
|---|
|  | 7195 | +cobt_sys_t | 
|---|
|  | 7196 | +cobalt_systype_probe(void) | 
|---|
|  | 7197 | +{ | 
|---|
|  | 7198 | +       static int init_done = 0; | 
|---|
|  | 7199 | + | 
|---|
|  | 7200 | +       if (init_done) { | 
|---|
|  | 7201 | +               return cobt_type; | 
|---|
|  | 7202 | +       } | 
|---|
|  | 7203 | + | 
|---|
|  | 7204 | +       /* check for 3k family systems */ | 
|---|
|  | 7205 | + | 
|---|
|  | 7206 | +       cobt_type = systype_probe_3k(); | 
|---|
|  | 7207 | +       if (cobt_type != COBT_UNKNOWN) | 
|---|
|  | 7208 | +               goto out; | 
|---|
|  | 7209 | + | 
|---|
|  | 7210 | +       /* check for 5k family systems */ | 
|---|
|  | 7211 | +       cobt_type = systype_probe_5k(); | 
|---|
|  | 7212 | +       if (cobt_type != COBT_UNKNOWN) | 
|---|
|  | 7213 | +               goto out; | 
|---|
|  | 7214 | + | 
|---|
|  | 7215 | +       /* it's a GP system or unknown */ | 
|---|
|  | 7216 | +       cobt_type = systype_probe_gp(); | 
|---|
|  | 7217 | + | 
|---|
|  | 7218 | +out: | 
|---|
|  | 7219 | +       if (cobt_type != COBT_UNKNOWN) { | 
|---|
|  | 7220 | +               init_done = 1; | 
|---|
|  | 7221 | +       } | 
|---|
|  | 7222 | + | 
|---|
|  | 7223 | +       return cobt_type; | 
|---|
|  | 7224 | +} | 
|---|
|  | 7225 | +EXPORT_SYMBOL(cobalt_systype_probe); | 
|---|
|  | 7226 | + | 
|---|
|  | 7227 | +#ifdef CONFIG_PROC_FS | 
|---|
|  | 7228 | +static int | 
|---|
|  | 7229 | +systype_read_proc(char *buf, char **start, off_t pos, int len, | 
|---|
|  | 7230 | +       int *eof, void *x) | 
|---|
|  | 7231 | +{ | 
|---|
|  | 7232 | +       int plen = sprintf(buf, "%s\n", systype_str(cobt_type)); | 
|---|
|  | 7233 | +       return cobalt_gen_proc_read(buf, plen, start, pos, len, eof); | 
|---|
|  | 7234 | +} | 
|---|
|  | 7235 | +#endif | 
|---|
|  | 7236 | + | 
|---|
|  | 7237 | +static char * | 
|---|
|  | 7238 | +systype_str(cobt_sys_t type) | 
|---|
|  | 7239 | +{ | 
|---|
|  | 7240 | +       switch (type) { | 
|---|
|  | 7241 | +               case COBT_PACIFICA: | 
|---|
|  | 7242 | +                       return "Pacifica"; | 
|---|
|  | 7243 | +                       break; | 
|---|
|  | 7244 | +               case COBT_CARMEL: | 
|---|
|  | 7245 | +                       return "Carmel"; | 
|---|
|  | 7246 | +                       break; | 
|---|
|  | 7247 | +               case COBT_MONTEREY: | 
|---|
|  | 7248 | +                       return "Monterey"; | 
|---|
|  | 7249 | +                       break; | 
|---|
|  | 7250 | +               case COBT_ALPINE: | 
|---|
|  | 7251 | +                       return "Alpine"; | 
|---|
|  | 7252 | +                       break; | 
|---|
|  | 7253 | +               case COBT_BIGBEAR: | 
|---|
|  | 7254 | +                       return "BigBear"; | 
|---|
|  | 7255 | +                       break; | 
|---|
|  | 7256 | +               case COBT_UNKNOWN: | 
|---|
|  | 7257 | +               default: | 
|---|
|  | 7258 | +                       return "unknown"; | 
|---|
|  | 7259 | +                       break; | 
|---|
|  | 7260 | +       } | 
|---|
|  | 7261 | +} | 
|---|
|  | 7262 | + | 
|---|
|  | 7263 | +static unsigned long | 
|---|
|  | 7264 | +boardrev_read(void) | 
|---|
|  | 7265 | +{ | 
|---|
|  | 7266 | +       unsigned long rev; | 
|---|
|  | 7267 | + | 
|---|
|  | 7268 | +       switch (cobt_type) { | 
|---|
|  | 7269 | +#ifdef CONFIG_COBALT_RAQ | 
|---|
|  | 7270 | +       case COBT_PACIFICA: | 
|---|
|  | 7271 | +       case COBT_CARMEL: | 
|---|
|  | 7272 | +               /* No usable board rev on these systems */ | 
|---|
|  | 7273 | +               return 0; | 
|---|
|  | 7274 | +       case COBT_MONTEREY: | 
|---|
|  | 7275 | +               /* | 
|---|
|  | 7276 | +                * the boardrev on monterey is strapped off of GPM[3:0] | 
|---|
|  | 7277 | +                * and is read from port 0xc52 | 
|---|
|  | 7278 | +                */ | 
|---|
|  | 7279 | +               return inb(0xc52); | 
|---|
|  | 7280 | +       case COBT_ALPINE: | 
|---|
|  | 7281 | +               /* | 
|---|
|  | 7282 | +                * the boardrev on alpine in stored in the i2c eeprom | 
|---|
|  | 7283 | +                * location 4 | 
|---|
|  | 7284 | +                */ | 
|---|
|  | 7285 | +               rev = cobalt_i2c_read_byte(COBALT_I2C_DEV_AT24C02, 0x04); | 
|---|
|  | 7286 | +               rev |= cobalt_i2c_read_byte(COBALT_I2C_DEV_AT24C02, 0x05) << 8; | 
|---|
|  | 7287 | +               rev |= cobalt_i2c_read_byte(COBALT_I2C_DEV_AT24C02, 0x06) << 16; | 
|---|
|  | 7288 | +               rev |= cobalt_i2c_read_byte(COBALT_I2C_DEV_AT24C02, 0x07) << 24; | 
|---|
|  | 7289 | +               if (rev == 0xffffffff) | 
|---|
|  | 7290 | +                       rev = 0; | 
|---|
|  | 7291 | +               return rev; | 
|---|
|  | 7292 | +#endif | 
|---|
|  | 7293 | +       case COBT_BIGBEAR: | 
|---|
|  | 7294 | +               /* No board revs at this time */ | 
|---|
|  | 7295 | +               return 0; | 
|---|
|  | 7296 | +       case COBT_UNKNOWN: | 
|---|
|  | 7297 | +       case COBT_UNINITIALIZED: | 
|---|
|  | 7298 | +               return 0; | 
|---|
|  | 7299 | +       } | 
|---|
|  | 7300 | +       return 0; | 
|---|
|  | 7301 | +} | 
|---|
|  | 7302 | diff -Naur linux-2.6.20.orig/drivers/cobalt/wdt.c linux-2.6.20/drivers/cobalt/wdt.c | 
|---|
|  | 7303 | --- linux-2.6.20.orig/drivers/cobalt/wdt.c      1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 7304 | +++ linux-2.6.20/drivers/cobalt/wdt.c   2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 7305 | @@ -0,0 +1,424 @@ | 
|---|
|  | 7306 | +/* $Id: wdt.c,v 1.21 2002/07/02 00:38:17 asun Exp $ */ | 
|---|
|  | 7307 | +/* | 
|---|
|  | 7308 | + * Cobalt kernel WDT timer driver | 
|---|
|  | 7309 | + * Tim Hockin <thockin@cobaltnet.com> | 
|---|
|  | 7310 | + * Adrian Sun <asun@cobalt.com> | 
|---|
|  | 7311 | + * Chris Johnson <cjohnson@cobalt.com> | 
|---|
|  | 7312 | + * Copyright (c)1999-2000, Cobalt Networks | 
|---|
|  | 7313 | + * Copyright (c)2001, Sun Microsystems | 
|---|
|  | 7314 | + * | 
|---|
|  | 7315 | + * This should be SMP safe.  Every external function (except trigger_reboot) | 
|---|
|  | 7316 | + * grabs the wdt lock.  No function in this file may call any exported | 
|---|
|  | 7317 | + * function (excepting trigger_reboot).  The disable counter is an atomic, so | 
|---|
|  | 7318 | + * there should be no issues there. --TPH | 
|---|
|  | 7319 | + */ | 
|---|
|  | 7320 | +#include <linux/config.h> | 
|---|
|  | 7321 | + | 
|---|
|  | 7322 | +#include <linux/module.h> | 
|---|
|  | 7323 | +#include <stdarg.h> | 
|---|
|  | 7324 | +#include <stddef.h> | 
|---|
|  | 7325 | +#include <linux/init.h> | 
|---|
|  | 7326 | +#include <linux/sched.h> | 
|---|
|  | 7327 | +#include <linux/timer.h> | 
|---|
|  | 7328 | +#include <linux/config.h> | 
|---|
|  | 7329 | +#include <linux/pci.h> | 
|---|
|  | 7330 | +#include <linux/delay.h> | 
|---|
|  | 7331 | +#include <asm/io.h> | 
|---|
|  | 7332 | +#include <asm/msr.h> | 
|---|
|  | 7333 | + | 
|---|
|  | 7334 | +#include <cobalt/cobalt.h> | 
|---|
|  | 7335 | +#include <cobalt/systype.h> | 
|---|
|  | 7336 | +#include <cobalt/wdt.h> | 
|---|
|  | 7337 | +#include <cobalt/superio.h> | 
|---|
|  | 7338 | + | 
|---|
|  | 7339 | +#define DOGB                   0x20 | 
|---|
|  | 7340 | +#define ALI_7101_WDT           0x92 | 
|---|
|  | 7341 | +#define ALI_WDT_ARM            0x01 | 
|---|
|  | 7342 | +#define WDT_3K_TIMEOUT                 (HZ >> 4)       /* 1/16 second */ | 
|---|
|  | 7343 | + | 
|---|
|  | 7344 | +#define WDT_SUPERIO_TIMEOUT    (0x01)          /* 1 minute */ | 
|---|
|  | 7345 | +#define WDT_5K_TIMEOUT                 (HZ << 3)       /* 8 seconds */ | 
|---|
|  | 7346 | + | 
|---|
|  | 7347 | +#define WDT_DRIVER                     "Cobalt Networks Watchdog Timer driver" | 
|---|
|  | 7348 | +#define WDT_DRIVER_VMAJ                1 | 
|---|
|  | 7349 | +#define WDT_DRIVER_VMIN                0 | 
|---|
|  | 7350 | + | 
|---|
|  | 7351 | +static unsigned long wdt_timeout; | 
|---|
|  | 7352 | +static unsigned long long tsc_per_wdt; | 
|---|
|  | 7353 | +static int initialized; | 
|---|
|  | 7354 | + | 
|---|
|  | 7355 | +#ifdef CONFIG_COBALT_WDT | 
|---|
|  | 7356 | +struct timer_list cobalt_wdt_timer; | 
|---|
|  | 7357 | +static atomic_t cobalt_wdt_disable_count = ATOMIC_INIT(0); | 
|---|
|  | 7358 | +static spinlock_t wdt_lock = SPIN_LOCK_UNLOCKED; | 
|---|
|  | 7359 | +#endif | 
|---|
|  | 7360 | + | 
|---|
|  | 7361 | +/* gen III */ | 
|---|
|  | 7362 | +static struct pci_dev *cobalt_pmu; | 
|---|
|  | 7363 | +static int use_pic; | 
|---|
|  | 7364 | +/* gen V */ | 
|---|
|  | 7365 | +static u16 superio_pm_port; | 
|---|
|  | 7366 | + | 
|---|
|  | 7367 | +#ifdef CONFIG_COBALT_WDT | 
|---|
|  | 7368 | +static void do_refresh(void); | 
|---|
|  | 7369 | +static void do_cleardog(void); | 
|---|
|  | 7370 | +static void do_disable(void); | 
|---|
|  | 7371 | +static void do_reenable(void); | 
|---|
|  | 7372 | +#endif | 
|---|
|  | 7373 | + | 
|---|
|  | 7374 | +static unsigned long __init | 
|---|
|  | 7375 | +chipset_setup(void) | 
|---|
|  | 7376 | +{ | 
|---|
|  | 7377 | +       unsigned char tmp; | 
|---|
|  | 7378 | +       if (cobt_is_3k()) { | 
|---|
|  | 7379 | +               /* | 
|---|
|  | 7380 | +                * Set up the PMU for 3k boards. It has a max | 
|---|
|  | 7381 | +                * of a 1 second timeout. | 
|---|
|  | 7382 | +                */ | 
|---|
|  | 7383 | +               struct pci_dev *south; | 
|---|
|  | 7384 | + | 
|---|
|  | 7385 | +               /* PMU (1543 ver A1-E) has a built-in WDT.  Set it to 1 sec */ | 
|---|
|  | 7386 | +               cobalt_pmu = pci_find_device(PCI_VENDOR_ID_AL, | 
|---|
|  | 7387 | +                       PCI_DEVICE_ID_AL_M7101, NULL); | 
|---|
|  | 7388 | +               if (!cobalt_pmu) { | 
|---|
|  | 7389 | +                       EPRINTK("can't find south bridge for WDT\n"); | 
|---|
|  | 7390 | +                       return 0; | 
|---|
|  | 7391 | +               } | 
|---|
|  | 7392 | +               pci_write_config_byte(cobalt_pmu, ALI_7101_WDT, 0x02); | 
|---|
|  | 7393 | + | 
|---|
|  | 7394 | +               /* why it is called 1543, but DevId is 1533 I'll never know */ | 
|---|
|  | 7395 | +               south = pci_find_device(PCI_VENDOR_ID_AL, | 
|---|
|  | 7396 | +                       PCI_DEVICE_ID_AL_M1533, NULL); | 
|---|
|  | 7397 | +               if (!south) { | 
|---|
|  | 7398 | +                       EPRINTK("can't find south bridge for WDT\n"); | 
|---|
|  | 7399 | +                       use_pic = 1; | 
|---|
|  | 7400 | +               } else { | 
|---|
|  | 7401 | +                       /* reversion # is here - must match ???1001?(b) | 
|---|
|  | 7402 | +                        * else use PIC for WDT */ | 
|---|
|  | 7403 | +                       pci_read_config_byte(south, 0x5e, &tmp); | 
|---|
|  | 7404 | +                       use_pic = ((tmp & 0x1e) != 0x12); | 
|---|
|  | 7405 | +               } | 
|---|
|  | 7406 | + | 
|---|
|  | 7407 | +               if (!use_pic) { | 
|---|
|  | 7408 | +                       /* set DOGB GPIO pin to OUTPUT - JIC */ | 
|---|
|  | 7409 | +                       pci_read_config_byte(cobalt_pmu, 0x7d, &tmp); | 
|---|
|  | 7410 | +                       pci_write_config_byte(cobalt_pmu, 0x7d, tmp | DOGB); | 
|---|
|  | 7411 | +               } | 
|---|
|  | 7412 | +               return WDT_3K_TIMEOUT; | 
|---|
|  | 7413 | +       } else if (cobt_is_monterey()) { | 
|---|
|  | 7414 | +               /* | 
|---|
|  | 7415 | +                * Set up the Nat. Semi SuperI/O for XTR. It has a | 
|---|
|  | 7416 | +                * minimum of a 1 minute timeout. | 
|---|
|  | 7417 | +                */ | 
|---|
|  | 7418 | + | 
|---|
|  | 7419 | +               /* superi/o -- select pm logical device and get base address */ | 
|---|
|  | 7420 | +               superio_pm_port = superio_ldev_base(PC87317_DEV_PM); | 
|---|
|  | 7421 | +#ifdef CONFIG_COBALT_WDT | 
|---|
|  | 7422 | +               if (!superio_pm_port) { | 
|---|
|  | 7423 | +                       return 0; | 
|---|
|  | 7424 | +               } | 
|---|
|  | 7425 | +               outb(PC87317_PMDEV_WDTO, superio_pm_port); | 
|---|
|  | 7426 | +               outb(WDT_SUPERIO_TIMEOUT, superio_pm_port + 1); | 
|---|
|  | 7427 | +#endif | 
|---|
|  | 7428 | +               return WDT_5K_TIMEOUT; | 
|---|
|  | 7429 | +       } else if (cobt_is_alpine()) { | 
|---|
|  | 7430 | +               /* | 
|---|
|  | 7431 | +                * Set up the Nat. Semi SuperI/O for Alpine. It has a | 
|---|
|  | 7432 | +                * minimum of a 1 minute timeout. | 
|---|
|  | 7433 | +                */ | 
|---|
|  | 7434 | + | 
|---|
|  | 7435 | +               /* superi/o -- select pm logical device and get base address */ | 
|---|
|  | 7436 | +               superio_pm_port = superio_ldev_base(PC87417_DEV_SWC); | 
|---|
|  | 7437 | +#ifdef CONFIG_COBALT_WDT | 
|---|
|  | 7438 | +               if (!superio_pm_port) { | 
|---|
|  | 7439 | +                       return 0; | 
|---|
|  | 7440 | +               } | 
|---|
|  | 7441 | +               /* select the WDT bank of SWC */ | 
|---|
|  | 7442 | +               outb(PC87417_SWCBANK_WDT, superio_pm_port+PC87417_SWC_BANK); | 
|---|
|  | 7443 | +               /* clear event config... */ | 
|---|
|  | 7444 | +               tmp = inb(superio_pm_port+PC87417_WDT_CONFIG); | 
|---|
|  | 7445 | +               outb(0, superio_pm_port+PC87417_WDT_CONFIG); | 
|---|
|  | 7446 | +               /* ...before mucking with timeout */ | 
|---|
|  | 7447 | +               outb(WDT_SUPERIO_TIMEOUT, | 
|---|
|  | 7448 | +                       superio_pm_port+PC87417_WDT_TIMEOUT); | 
|---|
|  | 7449 | +               /* restore the event config */ | 
|---|
|  | 7450 | +               outb(tmp, superio_pm_port+PC87417_WDT_CONFIG); | 
|---|
|  | 7451 | +               /* enable the counter */ | 
|---|
|  | 7452 | +               outb(1, superio_pm_port+PC87417_WDT_CONTROL); | 
|---|
|  | 7453 | +#endif | 
|---|
|  | 7454 | +               return WDT_5K_TIMEOUT; | 
|---|
|  | 7455 | +       } | 
|---|
|  | 7456 | + | 
|---|
|  | 7457 | +       return 0; | 
|---|
|  | 7458 | +} | 
|---|
|  | 7459 | + | 
|---|
|  | 7460 | +void __init | 
|---|
|  | 7461 | +cobalt_wdt_init(void) | 
|---|
|  | 7462 | +{ | 
|---|
|  | 7463 | +       unsigned long long start, stop; | 
|---|
|  | 7464 | + | 
|---|
|  | 7465 | +    printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", WDT_DRIVER,WDT_DRIVER_VMAJ,WDT_DRIVER_VMIN); | 
|---|
|  | 7466 | + | 
|---|
|  | 7467 | +       wdt_timeout = chipset_setup(); | 
|---|
|  | 7468 | + | 
|---|
|  | 7469 | +       /* figure out time */ | 
|---|
|  | 7470 | +       rdtscll(start); | 
|---|
|  | 7471 | +       udelay(100); | 
|---|
|  | 7472 | +       rdtscll(stop); | 
|---|
|  | 7473 | + | 
|---|
|  | 7474 | +       /* | 
|---|
|  | 7475 | +        * (int) (stop - start) * 10 == tsc per msec | 
|---|
|  | 7476 | +        * 1000 / HZ == msec per tick | 
|---|
|  | 7477 | +        * wdt_timeout == ticks per watchdog rearm | 
|---|
|  | 7478 | +        */ | 
|---|
|  | 7479 | +       tsc_per_wdt = (int) (stop - start) * 10 * (1000 * wdt_timeout / HZ); | 
|---|
|  | 7480 | + | 
|---|
|  | 7481 | +#ifdef CONFIG_COBALT_WDT | 
|---|
|  | 7482 | +       /* set the timer going */ | 
|---|
|  | 7483 | +       init_timer(&cobalt_wdt_timer); | 
|---|
|  | 7484 | +       cobalt_wdt_timer.function = cobalt_wdt_refresh; | 
|---|
|  | 7485 | +       cobalt_wdt_timer.data = 1; | 
|---|
|  | 7486 | +       cobalt_wdt_timer.expires = jiffies + wdt_timeout; | 
|---|
|  | 7487 | +       add_timer(&cobalt_wdt_timer); | 
|---|
|  | 7488 | + | 
|---|
|  | 7489 | +       /* the first timer tick will set it going */ | 
|---|
|  | 7490 | + | 
|---|
|  | 7491 | +       if (cobt_is_3k() && use_pic) { | 
|---|
|  | 7492 | +               WPRINTK("Cobalt WDT - old board, using PIC controller\n"); | 
|---|
|  | 7493 | +       } | 
|---|
|  | 7494 | +#endif /* CONFIG_COBALT_WDT */ | 
|---|
|  | 7495 | + | 
|---|
|  | 7496 | +       initialized = 1; | 
|---|
|  | 7497 | +} | 
|---|
|  | 7498 | + | 
|---|
|  | 7499 | +static inline void | 
|---|
|  | 7500 | +hw_disable(void) | 
|---|
|  | 7501 | +{ | 
|---|
|  | 7502 | +       if (cobt_is_3k()) { | 
|---|
|  | 7503 | +               char tmp; | 
|---|
|  | 7504 | +               /* read the value, disable (reset) WDT */ | 
|---|
|  | 7505 | +               pci_read_config_byte(cobalt_pmu, ALI_7101_WDT, &tmp); | 
|---|
|  | 7506 | +               pci_write_config_byte(cobalt_pmu, ALI_7101_WDT, | 
|---|
|  | 7507 | +                       (tmp & ~ALI_WDT_ARM)); | 
|---|
|  | 7508 | +       } else if (cobt_is_monterey()) { | 
|---|
|  | 7509 | +               outb(PC87317_PMDEV_WDTO, superio_pm_port); | 
|---|
|  | 7510 | +               outb(0, superio_pm_port + 1); | 
|---|
|  | 7511 | +       } else if (cobt_is_alpine()) { | 
|---|
|  | 7512 | +               unsigned char tmp; | 
|---|
|  | 7513 | +               /* select the WDT bank of SWC */ | 
|---|
|  | 7514 | +               outb(PC87417_SWCBANK_WDT, superio_pm_port + PC87417_SWC_BANK); | 
|---|
|  | 7515 | +               /* clear event config before mucking with timeout */ | 
|---|
|  | 7516 | +               tmp = inb(superio_pm_port + PC87417_WDT_CONFIG); | 
|---|
|  | 7517 | +               outb(0, superio_pm_port + PC87417_WDT_CONFIG); | 
|---|
|  | 7518 | +               /* | 
|---|
|  | 7519 | +                * Disable it by setting a 0 time-out. | 
|---|
|  | 7520 | +                * The spec says 00h is reserved, but NSC confirms this is the | 
|---|
|  | 7521 | +                * way to disable the device. | 
|---|
|  | 7522 | +                */ | 
|---|
|  | 7523 | +               outb(0, superio_pm_port + PC87417_WDT_TIMEOUT); | 
|---|
|  | 7524 | +               /* restore the event config */ | 
|---|
|  | 7525 | +               outb(tmp, superio_pm_port + PC87417_WDT_CONFIG); | 
|---|
|  | 7526 | +       } | 
|---|
|  | 7527 | +} | 
|---|
|  | 7528 | + | 
|---|
|  | 7529 | +static inline void | 
|---|
|  | 7530 | +hw_enable(void) | 
|---|
|  | 7531 | +{ | 
|---|
|  | 7532 | +       if (cobt_is_3k()) { | 
|---|
|  | 7533 | +               unsigned char tmp; | 
|---|
|  | 7534 | +               /* read the value, disable (reset) WDT, enable WDT */ | 
|---|
|  | 7535 | +               pci_read_config_byte(cobalt_pmu, ALI_7101_WDT, &tmp); | 
|---|
|  | 7536 | +               pci_write_config_byte(cobalt_pmu, ALI_7101_WDT, | 
|---|
|  | 7537 | +                       (tmp | ALI_WDT_ARM)); | 
|---|
|  | 7538 | +               if (use_pic) { | 
|---|
|  | 7539 | +                       /* transition GPIO 5 (DOGB) to arm/clear timer */ | 
|---|
|  | 7540 | +                       pci_read_config_byte(cobalt_pmu, 0x7e, &tmp); | 
|---|
|  | 7541 | +                       pci_write_config_byte(cobalt_pmu, 0x7e, tmp ^ DOGB); | 
|---|
|  | 7542 | +               } | 
|---|
|  | 7543 | +       } else if (cobt_is_monterey()) { | 
|---|
|  | 7544 | +               outb(PC87317_PMDEV_WDTO, superio_pm_port); | 
|---|
|  | 7545 | +               outb(WDT_SUPERIO_TIMEOUT, superio_pm_port + 1); | 
|---|
|  | 7546 | +       } else if (cobt_is_alpine()) { | 
|---|
|  | 7547 | +               unsigned char tmp; | 
|---|
|  | 7548 | +               /* select the WDT bank of SWC */ | 
|---|
|  | 7549 | +               outb(PC87417_SWCBANK_WDT, superio_pm_port + PC87417_SWC_BANK); | 
|---|
|  | 7550 | +               /* clear event config before mucking with timeout */ | 
|---|
|  | 7551 | +               tmp = inb(superio_pm_port + PC87417_WDT_CONFIG); | 
|---|
|  | 7552 | +               outb(0, superio_pm_port + PC87417_WDT_CONFIG); | 
|---|
|  | 7553 | +               /* enable and refresh the timer */ | 
|---|
|  | 7554 | +               outb(WDT_SUPERIO_TIMEOUT, | 
|---|
|  | 7555 | +                       superio_pm_port + PC87417_WDT_TIMEOUT); | 
|---|
|  | 7556 | +               outb(0x80, superio_pm_port + PC87417_WDT_CONTROL); | 
|---|
|  | 7557 | +               /* restore event config */ | 
|---|
|  | 7558 | +               outb(tmp, superio_pm_port + PC87417_WDT_CONFIG); | 
|---|
|  | 7559 | +       } | 
|---|
|  | 7560 | +} | 
|---|
|  | 7561 | + | 
|---|
|  | 7562 | +#ifdef CONFIG_COBALT_WDT | 
|---|
|  | 7563 | +static void | 
|---|
|  | 7564 | +do_refresh(void) | 
|---|
|  | 7565 | +{ | 
|---|
|  | 7566 | +       if (!initialized) { | 
|---|
|  | 7567 | +               return; | 
|---|
|  | 7568 | +       } | 
|---|
|  | 7569 | + | 
|---|
|  | 7570 | +       do_cleardog(); | 
|---|
|  | 7571 | + | 
|---|
|  | 7572 | +       /* re-arm the timer - this is locked in mod_timer() */ | 
|---|
|  | 7573 | +       mod_timer(&cobalt_wdt_timer, jiffies + wdt_timeout); | 
|---|
|  | 7574 | +} | 
|---|
|  | 7575 | +#endif | 
|---|
|  | 7576 | + | 
|---|
|  | 7577 | +EXPORT_SYMBOL(cobalt_wdt_refresh); | 
|---|
|  | 7578 | +void | 
|---|
|  | 7579 | +cobalt_wdt_refresh(unsigned long refresh_timer) | 
|---|
|  | 7580 | +{ | 
|---|
|  | 7581 | +#ifdef CONFIG_COBALT_WDT | 
|---|
|  | 7582 | +       unsigned long flags; | 
|---|
|  | 7583 | +       spin_lock_irqsave(&wdt_lock, flags); | 
|---|
|  | 7584 | +       do_refresh(); | 
|---|
|  | 7585 | +       spin_unlock_irqrestore(&wdt_lock, flags); | 
|---|
|  | 7586 | +#endif | 
|---|
|  | 7587 | +} | 
|---|
|  | 7588 | + | 
|---|
|  | 7589 | +#ifdef CONFIG_COBALT_WDT | 
|---|
|  | 7590 | +static void | 
|---|
|  | 7591 | +do_cleardog(void) | 
|---|
|  | 7592 | +{ | 
|---|
|  | 7593 | +       static unsigned long long last_tsc = 0; | 
|---|
|  | 7594 | +       unsigned long long tmp; | 
|---|
|  | 7595 | + | 
|---|
|  | 7596 | +       if (!initialized || (atomic_read(&cobalt_wdt_disable_count) > 0)) { | 
|---|
|  | 7597 | +               return; | 
|---|
|  | 7598 | +       } | 
|---|
|  | 7599 | + | 
|---|
|  | 7600 | +       /* only bother if we're due */ | 
|---|
|  | 7601 | +       rdtscll(tmp); | 
|---|
|  | 7602 | +       if ((int)(tmp - last_tsc) < tsc_per_wdt) { | 
|---|
|  | 7603 | +               return; | 
|---|
|  | 7604 | +       } | 
|---|
|  | 7605 | + | 
|---|
|  | 7606 | +       if (cobt_is_3k() || cobt_is_monterey()) { | 
|---|
|  | 7607 | +               /* this is how we re-start the clock */ | 
|---|
|  | 7608 | +               hw_disable(); | 
|---|
|  | 7609 | +               hw_enable(); | 
|---|
|  | 7610 | +       } else if (cobt_is_alpine()) { | 
|---|
|  | 7611 | +               /* select the WDT bank of SWC */ | 
|---|
|  | 7612 | +               outb(PC87417_SWCBANK_WDT, superio_pm_port + PC87417_SWC_BANK); | 
|---|
|  | 7613 | +               /* refresh the timer */ | 
|---|
|  | 7614 | +               outb(0x80, superio_pm_port + PC87417_WDT_CONTROL); | 
|---|
|  | 7615 | +       } | 
|---|
|  | 7616 | + | 
|---|
|  | 7617 | +       rdtscll(last_tsc); | 
|---|
|  | 7618 | +} | 
|---|
|  | 7619 | +#endif | 
|---|
|  | 7620 | + | 
|---|
|  | 7621 | +EXPORT_SYMBOL(cobalt_wdt_cleardog); | 
|---|
|  | 7622 | +void | 
|---|
|  | 7623 | +cobalt_wdt_cleardog(void) | 
|---|
|  | 7624 | +{ | 
|---|
|  | 7625 | +#ifdef CONFIG_COBALT_WDT | 
|---|
|  | 7626 | +       unsigned long flags; | 
|---|
|  | 7627 | + | 
|---|
|  | 7628 | +       spin_lock_irqsave(&wdt_lock, flags); | 
|---|
|  | 7629 | +       do_cleardog(); | 
|---|
|  | 7630 | +       spin_unlock_irqrestore(&wdt_lock, flags); | 
|---|
|  | 7631 | +#endif | 
|---|
|  | 7632 | +} | 
|---|
|  | 7633 | + | 
|---|
|  | 7634 | +/* | 
|---|
|  | 7635 | + * this is called from machine_restart. it should not be used on | 
|---|
|  | 7636 | + * 5k machines. | 
|---|
|  | 7637 | + */ | 
|---|
|  | 7638 | +EXPORT_SYMBOL(cobalt_wdt_trigger_reboot); | 
|---|
|  | 7639 | +void | 
|---|
|  | 7640 | +cobalt_wdt_trigger_reboot(void) | 
|---|
|  | 7641 | +{ | 
|---|
|  | 7642 | +       if (cobt_is_3k()) { | 
|---|
|  | 7643 | +               if (!cobalt_pmu) { | 
|---|
|  | 7644 | +                       WPRINTK("no PMU found!\n"); | 
|---|
|  | 7645 | +                       WPRINTK("reboot not possible!\n"); | 
|---|
|  | 7646 | +                       return; | 
|---|
|  | 7647 | +               } | 
|---|
|  | 7648 | + | 
|---|
|  | 7649 | +#ifdef CONFIG_COBALT_WDT | 
|---|
|  | 7650 | +               /* stop feeding it */ | 
|---|
|  | 7651 | +               del_timer_sync(&cobalt_wdt_timer); | 
|---|
|  | 7652 | +#endif | 
|---|
|  | 7653 | + | 
|---|
|  | 7654 | +               /* kiss your rear goodbye... */ | 
|---|
|  | 7655 | +               initialized = 0; | 
|---|
|  | 7656 | +               hw_disable(); | 
|---|
|  | 7657 | +               hw_enable(); | 
|---|
|  | 7658 | +       } | 
|---|
|  | 7659 | +} | 
|---|
|  | 7660 | + | 
|---|
|  | 7661 | +#ifdef CONFIG_COBALT_WDT | 
|---|
|  | 7662 | +static void | 
|---|
|  | 7663 | +do_disable(void) | 
|---|
|  | 7664 | +{ | 
|---|
|  | 7665 | +       if (!initialized) { | 
|---|
|  | 7666 | +               return; | 
|---|
|  | 7667 | +       } | 
|---|
|  | 7668 | + | 
|---|
|  | 7669 | +       if (atomic_read(&cobalt_wdt_disable_count) == 0) { | 
|---|
|  | 7670 | +               atomic_inc(&cobalt_wdt_disable_count); | 
|---|
|  | 7671 | +               del_timer_sync(&cobalt_wdt_timer); | 
|---|
|  | 7672 | +               hw_disable(); | 
|---|
|  | 7673 | +       } | 
|---|
|  | 7674 | +} | 
|---|
|  | 7675 | +#endif | 
|---|
|  | 7676 | + | 
|---|
|  | 7677 | +EXPORT_SYMBOL(cobalt_wdt_disable); | 
|---|
|  | 7678 | +void | 
|---|
|  | 7679 | +cobalt_wdt_disable(void) | 
|---|
|  | 7680 | +{ | 
|---|
|  | 7681 | +#ifdef CONFIG_COBALT_WDT | 
|---|
|  | 7682 | +       unsigned long flags; | 
|---|
|  | 7683 | + | 
|---|
|  | 7684 | +       if (cobt_is_3k() && use_pic) { | 
|---|
|  | 7685 | +               WPRINTK("in PIC mode - cannot disable\n"); | 
|---|
|  | 7686 | +               return; | 
|---|
|  | 7687 | +       } | 
|---|
|  | 7688 | + | 
|---|
|  | 7689 | +       spin_lock_irqsave(&wdt_lock, flags); | 
|---|
|  | 7690 | +       do_disable(); | 
|---|
|  | 7691 | +       spin_unlock_irqrestore(&wdt_lock, flags); | 
|---|
|  | 7692 | +#endif | 
|---|
|  | 7693 | +} | 
|---|
|  | 7694 | + | 
|---|
|  | 7695 | +#ifdef CONFIG_COBALT_WDT | 
|---|
|  | 7696 | +static void | 
|---|
|  | 7697 | +do_reenable(void) | 
|---|
|  | 7698 | +{ | 
|---|
|  | 7699 | +       int dcnt; | 
|---|
|  | 7700 | + | 
|---|
|  | 7701 | +       if (!initialized) { | 
|---|
|  | 7702 | +               return; | 
|---|
|  | 7703 | +       } | 
|---|
|  | 7704 | + | 
|---|
|  | 7705 | +       atomic_dec(&cobalt_wdt_disable_count); | 
|---|
|  | 7706 | +       dcnt = atomic_read(&cobalt_wdt_disable_count); | 
|---|
|  | 7707 | + | 
|---|
|  | 7708 | +       if (dcnt == 0) { | 
|---|
|  | 7709 | +               do_refresh(); | 
|---|
|  | 7710 | +       } else if (dcnt < 0) { | 
|---|
|  | 7711 | +               WPRINTK("too many enables\n"); | 
|---|
|  | 7712 | +               atomic_set(&cobalt_wdt_disable_count, 0); | 
|---|
|  | 7713 | +       } | 
|---|
|  | 7714 | +} | 
|---|
|  | 7715 | +#endif | 
|---|
|  | 7716 | + | 
|---|
|  | 7717 | + | 
|---|
|  | 7718 | +EXPORT_SYMBOL(cobalt_wdt_reenable); | 
|---|
|  | 7719 | +void | 
|---|
|  | 7720 | +cobalt_wdt_reenable(void) | 
|---|
|  | 7721 | +{ | 
|---|
|  | 7722 | +#ifdef CONFIG_COBALT_WDT | 
|---|
|  | 7723 | +       unsigned long flags; | 
|---|
|  | 7724 | + | 
|---|
|  | 7725 | +       spin_lock_irqsave(&wdt_lock, flags); | 
|---|
|  | 7726 | +       do_reenable(); | 
|---|
|  | 7727 | +       spin_unlock_irqrestore(&wdt_lock, flags); | 
|---|
|  | 7728 | +#endif | 
|---|
|  | 7729 | +} | 
|---|
|  | 7730 | diff -Naur linux-2.6.20.orig/drivers/net/Kconfig linux-2.6.20/drivers/net/Kconfig | 
|---|
|  | 7731 | --- linux-2.6.20.orig/drivers/net/Kconfig       2007-02-04 10:44:54.000000000 -0800 | 
|---|
|  | 7732 | +++ linux-2.6.20/drivers/net/Kconfig    2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 7733 | @@ -1527,6 +1527,16 @@ | 
|---|
|  | 7734 | <file:Documentation/networking/net-modules.txt>.  The module | 
|---|
|  | 7735 | will be called e100. | 
|---|
|  | 7736 |  | 
|---|
|  | 7737 | +config E100_IGNORE_CSUM | 
|---|
|  | 7738 | +       bool "Ignore bad EEPROM checksum" | 
|---|
|  | 7739 | +       depends on E100 && EXPERIMENTAL && !CLEAN_COMPILE | 
|---|
|  | 7740 | +       help | 
|---|
|  | 7741 | +         This option tells the e100 driver to ignore bad EEPROM checksums. | 
|---|
|  | 7742 | +         Usually this is a bad idea, as an incorrect checksum can indicate a | 
|---|
|  | 7743 | +         serious issue with the network card. | 
|---|
|  | 7744 | + | 
|---|
|  | 7745 | +         If unsure, say N. | 
|---|
|  | 7746 | + | 
|---|
|  | 7747 | config LNE390 | 
|---|
|  | 7748 | tristate "Mylex EISA LNE390A/B support (EXPERIMENTAL)" | 
|---|
|  | 7749 | depends on NET_PCI && EISA && EXPERIMENTAL | 
|---|
|  | 7750 | diff -Naur linux-2.6.20.orig/drivers/net/e100.c linux-2.6.20/drivers/net/e100.c | 
|---|
|  | 7751 | --- linux-2.6.20.orig/drivers/net/e100.c        2007-02-04 10:44:54.000000000 -0800 | 
|---|
|  | 7752 | +++ linux-2.6.20/drivers/net/e100.c     2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 7753 | @@ -162,6 +162,7 @@ | 
|---|
|  | 7754 | #define DRV_VERSION            "3.5.17-k2"DRV_EXT | 
|---|
|  | 7755 | #define DRV_DESCRIPTION                "Intel(R) PRO/100 Network Driver" | 
|---|
|  | 7756 | #define DRV_COPYRIGHT          "Copyright(c) 1999-2006 Intel Corporation" | 
|---|
|  | 7757 | +#define DRV_MODIFIED           "Modified by <jeff@404ster.com> to ignore bad EEPROM checksums" | 
|---|
|  | 7758 | #define PFX                    DRV_NAME ": " | 
|---|
|  | 7759 |  | 
|---|
|  | 7760 | #define E100_WATCHDOG_PERIOD   (2 * HZ) | 
|---|
|  | 7761 | @@ -758,9 +759,15 @@ | 
|---|
|  | 7762 | * the sum of words should be 0xBABA */ | 
|---|
|  | 7763 | checksum = le16_to_cpu(0xBABA - checksum); | 
|---|
|  | 7764 | if(checksum != nic->eeprom[nic->eeprom_wc - 1]) { | 
|---|
|  | 7765 | +#if defined(CONFIG_E100_IGNORE_CSUM) | 
|---|
|  | 7766 | +DPRINTK(PROBE, ERR, "EEPROM corrupted, ignoring and moving on\n"); | 
|---|
|  | 7767 | +DPRINTK(PROBE, ERR, "    Caclulated Checksum: %X\n",checksum); | 
|---|
|  | 7768 | +DPRINTK(PROBE, ERR, "    EEPROM Checksum:     %X\n",nic->eeprom[nic->eeprom_wc - 1]); | 
|---|
|  | 7769 | +#else | 
|---|
|  | 7770 | DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); | 
|---|
|  | 7771 | if (!eeprom_bad_csum_allow) | 
|---|
|  | 7772 | return -EAGAIN; | 
|---|
|  | 7773 | +#endif | 
|---|
|  | 7774 | } | 
|---|
|  | 7775 |  | 
|---|
|  | 7776 | return 0; | 
|---|
|  | 7777 | @@ -2876,6 +2883,9 @@ | 
|---|
|  | 7778 | if(((1 << debug) - 1) & NETIF_MSG_DRV) { | 
|---|
|  | 7779 | printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); | 
|---|
|  | 7780 | printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT); | 
|---|
|  | 7781 | +#if defined(CONFIG_E100_IGNORE_CSUM) | 
|---|
|  | 7782 | +               printk(KERN_INFO PFX "%s\n", DRV_MODIFIED); | 
|---|
|  | 7783 | +#endif | 
|---|
|  | 7784 | } | 
|---|
|  | 7785 | return pci_register_driver(&e100_driver); | 
|---|
|  | 7786 | } | 
|---|
|  | 7787 | diff -Naur linux-2.6.20.orig/include/cobalt/acpi.h linux-2.6.20/include/cobalt/acpi.h | 
|---|
|  | 7788 | --- linux-2.6.20.orig/include/cobalt/acpi.h     1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 7789 | +++ linux-2.6.20/include/cobalt/acpi.h  2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 7790 | @@ -0,0 +1,82 @@ | 
|---|
|  | 7791 | +/* | 
|---|
|  | 7792 | + * $Id: cobalt-acpi.h,v 1.7 2001/10/27 07:03:31 erik Exp $ | 
|---|
|  | 7793 | + * cobalt-acpi.h : support for ACPI interrupts | 
|---|
|  | 7794 | + * | 
|---|
|  | 7795 | + * Copyright 2000 Cobalt Networks, Inc. | 
|---|
|  | 7796 | + * Copyright 2001 Sun Microsystems, Inc. | 
|---|
|  | 7797 | + */ | 
|---|
|  | 7798 | +#ifndef COBALT_ACPI_H | 
|---|
|  | 7799 | +#define COBALT_ACPI_H | 
|---|
|  | 7800 | + | 
|---|
|  | 7801 | +#define SERVERWORKS_ACPI_INDEX_PORT    0x0cd6 | 
|---|
|  | 7802 | +#define SERVERWORKS_ACPI_DATA_PORT     0x0cd7 | 
|---|
|  | 7803 | + | 
|---|
|  | 7804 | + | 
|---|
|  | 7805 | +typedef struct | 
|---|
|  | 7806 | +{ | 
|---|
|  | 7807 | +    u16 hw_type; | 
|---|
|  | 7808 | +    u16 ev_type; | 
|---|
|  | 7809 | +    u32 ev_data; | 
|---|
|  | 7810 | +} cobalt_acpi_evt; | 
|---|
|  | 7811 | + | 
|---|
|  | 7812 | +enum __cobalt_acpi_hw_types | 
|---|
|  | 7813 | +{ | 
|---|
|  | 7814 | +    COBALT_ACPI_HW_ANY = 0x0000, | 
|---|
|  | 7815 | +    COBALT_ACPI_HW_OSB4 = 0x0001, | 
|---|
|  | 7816 | +    COBALT_ACPI_HW_CSB5 = 0x0002, | 
|---|
|  | 7817 | +    COBALT_ACPI_HW_PC8731X = 0x0003, | 
|---|
|  | 7818 | +    COBALT_ACPI_HW_PC8741X = 0x0004, | 
|---|
|  | 7819 | +}; | 
|---|
|  | 7820 | + | 
|---|
|  | 7821 | +enum __cobalt_acpi_event_types | 
|---|
|  | 7822 | +{ | 
|---|
|  | 7823 | +    COBALT_ACPI_EVT_NONE = 0x0000, | 
|---|
|  | 7824 | +    COBALT_ACPI_EVT_TMR = 0x0001, /* Timer Event */ | 
|---|
|  | 7825 | +    COBALT_ACPI_EVT_BM = 0x00002, /* Bus Master Event */ | 
|---|
|  | 7826 | +    COBALT_ACPI_EVT_GBL = 0x0003, /* BIOS Global Lock release */ | 
|---|
|  | 7827 | +    COBALT_ACPI_EVT_PWRBTN = 0x0004, /* Power Button press */ | 
|---|
|  | 7828 | +    COBALT_ACPI_EVT_SLPBTN = 0x0005, /* Sleep Button press */ | 
|---|
|  | 7829 | +    COBALT_ACPI_EVT_RTC = 0x0006, /* RTC Alarm */ | 
|---|
|  | 7830 | +    COBALT_ACPI_EVT_WAK = 0x0007, /* Wake event */ | 
|---|
|  | 7831 | +    COBALT_ACPI_EVT_GPE = 0x0008, /* General Purpose Event (ev_data = gpe number) */ | 
|---|
|  | 7832 | + | 
|---|
|  | 7833 | +       /* events greater than 0x7fff are symbolic events */ | 
|---|
|  | 7834 | +    COBALT_ACPI_EVT_SLED = 0x8000, /* Sled removal */ | 
|---|
|  | 7835 | +    COBALT_ACPI_EVT_THERM = 0x8001, /* Thermal trip */ | 
|---|
|  | 7836 | +    COBALT_ACPI_EVT_FAN = 0x8002, /* Fan Down */ | 
|---|
|  | 7837 | +    COBALT_ACPI_EVT_SM_INT = 0x8003, /* System Monitor Interrupt */ | 
|---|
|  | 7838 | +    COBALT_ACPI_EVT_VOLT = 0x8004, /* System Monitor Interrupt */ | 
|---|
|  | 7839 | + | 
|---|
|  | 7840 | +}; | 
|---|
|  | 7841 | + | 
|---|
|  | 7842 | +typedef int (* cobalt_acpi_hw_handler)( int irq, void *dev_id, struct pt_regs *regs, void * data ); | 
|---|
|  | 7843 | +typedef int (* cobalt_acpi_enable_handler)( u16 ev_type, u16 ev_data, int en, void *data ); | 
|---|
|  | 7844 | +typedef int (* cobalt_acpi_evt_handler)( cobalt_acpi_evt *evt, void * data ); | 
|---|
|  | 7845 | + | 
|---|
|  | 7846 | + | 
|---|
|  | 7847 | +extern int cobalt_acpi_register_hw_handler( u16 hw_type, | 
|---|
|  | 7848 | +                                           cobalt_acpi_hw_handler hw_handler, | 
|---|
|  | 7849 | +                                           cobalt_acpi_enable_handler en_handler, | 
|---|
|  | 7850 | +                                           void *data ); | 
|---|
|  | 7851 | +extern int cobalt_acpi_unregister_hw_handler( cobalt_acpi_hw_handler handler ); | 
|---|
|  | 7852 | + | 
|---|
|  | 7853 | +extern int cobalt_acpi_register_trans_table( u16 hw_type, u16 table_len, u16 *table ); | 
|---|
|  | 7854 | +extern int cobalt_acpi_unregister_trans_table( u16 hw_type ); | 
|---|
|  | 7855 | + | 
|---|
|  | 7856 | +extern int cobalt_acpi_register_evt_handler( cobalt_acpi_evt_handler handler, | 
|---|
|  | 7857 | +                                            u16 evt_type, | 
|---|
|  | 7858 | +                                            void *data ); | 
|---|
|  | 7859 | +extern int cobalt_acpi_unregister_evt_handler( cobalt_acpi_evt_handler handler ); | 
|---|
|  | 7860 | + | 
|---|
|  | 7861 | +extern int cobalt_acpi_post_event( cobalt_acpi_evt evt ); | 
|---|
|  | 7862 | + | 
|---|
|  | 7863 | +#ifdef CONFIG_COBALT_EMU_ACPI | 
|---|
|  | 7864 | +int cobalt_acpi_generate_proc_evt( cobalt_acpi_evt * evt ); | 
|---|
|  | 7865 | +#else | 
|---|
|  | 7866 | +#define cobalt_acpi_generate_proc_evt( a ) | 
|---|
|  | 7867 | +#endif | 
|---|
|  | 7868 | + | 
|---|
|  | 7869 | + | 
|---|
|  | 7870 | + | 
|---|
|  | 7871 | + | 
|---|
|  | 7872 | +#endif /* COBALT_ACPI_H */ | 
|---|
|  | 7873 | diff -Naur linux-2.6.20.orig/include/cobalt/cobalt.h linux-2.6.20/include/cobalt/cobalt.h | 
|---|
|  | 7874 | --- linux-2.6.20.orig/include/cobalt/cobalt.h   1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 7875 | +++ linux-2.6.20/include/cobalt/cobalt.h        2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 7876 | @@ -0,0 +1,58 @@ | 
|---|
|  | 7877 | +/* $Id: cobalt.h,v 1.16 2002/11/04 17:54:15 thockin Exp $ */ | 
|---|
|  | 7878 | +/* Copyright 2001 Sun Microsystems, Inc. */ | 
|---|
|  | 7879 | +#include <linux/config.h> | 
|---|
|  | 7880 | +#if !defined(COBALT_H) && defined(CONFIG_COBALT_RAQ) | 
|---|
|  | 7881 | +#define COBALT_H | 
|---|
|  | 7882 | + | 
|---|
|  | 7883 | +/* generational support - for easy checking */ | 
|---|
|  | 7884 | +#ifdef CONFIG_COBALT_GEN_III | 
|---|
|  | 7885 | +# define COBT_SUPPORT_GEN_III 1 | 
|---|
|  | 7886 | +#else | 
|---|
|  | 7887 | +# define COBT_SUPPORT_GEN_III 0 | 
|---|
|  | 7888 | +#endif | 
|---|
|  | 7889 | + | 
|---|
|  | 7890 | +#ifdef CONFIG_COBALT_GEN_V | 
|---|
|  | 7891 | +# define COBT_SUPPORT_GEN_V 1 | 
|---|
|  | 7892 | +#else | 
|---|
|  | 7893 | +# define COBT_SUPPORT_GEN_V 0 | 
|---|
|  | 7894 | +#endif | 
|---|
|  | 7895 | + | 
|---|
|  | 7896 | +/* macros for consistent errors/warnings */ | 
|---|
|  | 7897 | +#define EPRINTK(fmt, args...) \ | 
|---|
|  | 7898 | +       printk(KERN_ERR "%s:%s: " fmt , __FILE__ , __FUNCTION__ , ##args) | 
|---|
|  | 7899 | + | 
|---|
|  | 7900 | +#define WPRINTK(fmt, args...) \ | 
|---|
|  | 7901 | +       printk(KERN_WARNING "%s:%s: " fmt , __FILE__ , __FUNCTION__ , ##args) | 
|---|
|  | 7902 | + | 
|---|
|  | 7903 | +/* the root of /proc/cobalt */ | 
|---|
|  | 7904 | +extern struct proc_dir_entry *proc_cobalt; | 
|---|
|  | 7905 | +int cobalt_gen_proc_read(char *buf, int plen, char **start, off_t pos, | 
|---|
|  | 7906 | +       int len, int *eof); | 
|---|
|  | 7907 | + | 
|---|
|  | 7908 | +//#ifdef CONFIG_COBALT_RAQ | 
|---|
|  | 7909 | +/* keep this test up to date with new generation defines */ | 
|---|
|  | 7910 | +#if !defined(CONFIG_COBALT_GEN_III) && !defined(CONFIG_COBALT_GEN_V) | 
|---|
|  | 7911 | +/* barf if no generation has been selected */ | 
|---|
|  | 7912 | +#error You asked for CONFIG_COBALT_RAQ, but no CONFIG_COBALT_GEN_* ! | 
|---|
|  | 7913 | +#endif | 
|---|
|  | 7914 | + | 
|---|
|  | 7915 | +/* accesses for CMOS */ | 
|---|
|  | 7916 | +#include <linux/mc146818rtc.h> | 
|---|
|  | 7917 | +#include <cobalt/nvram.h> | 
|---|
|  | 7918 | + | 
|---|
|  | 7919 | +static inline int | 
|---|
|  | 7920 | +cobalt_cmos_read_flag(const unsigned int flag) | 
|---|
|  | 7921 | +{ | 
|---|
|  | 7922 | +       unsigned long flags; | 
|---|
|  | 7923 | +       u16 cmosfl; | 
|---|
|  | 7924 | + | 
|---|
|  | 7925 | +       spin_lock_irqsave(&rtc_lock, flags); | 
|---|
|  | 7926 | +       cmosfl = CMOS_READ(COBT_CMOS_FLAG_BYTE_0) << 8; | 
|---|
|  | 7927 | +       cmosfl |= CMOS_READ(COBT_CMOS_FLAG_BYTE_1); | 
|---|
|  | 7928 | +       spin_unlock_irqrestore(&rtc_lock, flags); | 
|---|
|  | 7929 | + | 
|---|
|  | 7930 | +       return (cmosfl & flag) ? 1 : 0; | 
|---|
|  | 7931 | +} | 
|---|
|  | 7932 | +//#endif /* CONFIG_COBALT_RAQ */ | 
|---|
|  | 7933 | + | 
|---|
|  | 7934 | +#endif /* !defined(COBALT_H) && defined(CONFIG_COBALT_RAQ) */ | 
|---|
|  | 7935 | diff -Naur linux-2.6.20.orig/include/cobalt/i2c.h linux-2.6.20/include/cobalt/i2c.h | 
|---|
|  | 7936 | --- linux-2.6.20.orig/include/cobalt/i2c.h      1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 7937 | +++ linux-2.6.20/include/cobalt/i2c.h   2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 7938 | @@ -0,0 +1,40 @@ | 
|---|
|  | 7939 | +/* | 
|---|
|  | 7940 | + * $Id: cobalt-i2c.h,v 1.3 2001/08/22 05:48:04 asun Exp $ | 
|---|
|  | 7941 | + * cobalt-i2c.h : I2C support for LCD/Front Panel | 
|---|
|  | 7942 | + * | 
|---|
|  | 7943 | + * Copyright 2000 Cobalt Networks, Inc. | 
|---|
|  | 7944 | + * Copyright 2001 Sun Microsystems, Inc. | 
|---|
|  | 7945 | + */ | 
|---|
|  | 7946 | +#ifndef COBALT_I2C_H | 
|---|
|  | 7947 | +#define COBALT_I2C_H | 
|---|
|  | 7948 | + | 
|---|
|  | 7949 | +#include <linux/types.h> | 
|---|
|  | 7950 | +#include <cobalt/cobalt.h> | 
|---|
|  | 7951 | + | 
|---|
|  | 7952 | +#define COBALT_I2C_DEV_LED_I           0x40 | 
|---|
|  | 7953 | +#define COBALT_I2C_DEV_LED_II          0x42 | 
|---|
|  | 7954 | +#define COBALT_I2C_DEV_LCD_DATA                0x4a | 
|---|
|  | 7955 | +#define COBALT_I2C_DEV_LCD_INST                0x48 | 
|---|
|  | 7956 | +#define COBALT_I2C_DEV_FP_BUTTONS      0x41 | 
|---|
|  | 7957 | +#define COBALT_I2C_DEV_DRV_SWITCH      0x45 | 
|---|
|  | 7958 | +#define COBALT_I2C_DEV_RULER           0x46 | 
|---|
|  | 7959 | +#define COBALT_I2C_DEV_LM77            0x90 | 
|---|
|  | 7960 | +#define COBALT_I2C_DEV_ADM1029         0x5e | 
|---|
|  | 7961 | +#define COBALT_I2C_DEV_AT24C02         0xae | 
|---|
|  | 7962 | + | 
|---|
|  | 7963 | +#define COBALT_I2C_READ                        0x01 | 
|---|
|  | 7964 | +#define COBALT_I2C_WRITE               0x00 | 
|---|
|  | 7965 | + | 
|---|
|  | 7966 | +extern int cobalt_i2c_reset(void); | 
|---|
|  | 7967 | +extern int cobalt_i2c_read_byte(const int dev, const int index); | 
|---|
|  | 7968 | +extern int cobalt_i2c_read_word(const int dev, const int index); | 
|---|
|  | 7969 | +extern int cobalt_i2c_read_block(const int dev, const int index, | 
|---|
|  | 7970 | +                                unsigned char *data, int count); | 
|---|
|  | 7971 | +extern int cobalt_i2c_write_byte(const int dev, const int index, | 
|---|
|  | 7972 | +                                const u8 val); | 
|---|
|  | 7973 | +extern int cobalt_i2c_write_word(const int dev, const int index, | 
|---|
|  | 7974 | +                                const u16 val); | 
|---|
|  | 7975 | +extern int cobalt_i2c_write_block(const int dev, const int index, | 
|---|
|  | 7976 | +                                 unsigned char *data, int count); | 
|---|
|  | 7977 | + | 
|---|
|  | 7978 | +#endif /* COBALT_I2C_H */ | 
|---|
|  | 7979 | diff -Naur linux-2.6.20.orig/include/cobalt/lcd.h linux-2.6.20/include/cobalt/lcd.h | 
|---|
|  | 7980 | --- linux-2.6.20.orig/include/cobalt/lcd.h      1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 7981 | +++ linux-2.6.20/include/cobalt/lcd.h   2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 7982 | @@ -0,0 +1,95 @@ | 
|---|
|  | 7983 | +/* | 
|---|
|  | 7984 | + * $Id: cobalt-lcd.h,v 1.12 2001/11/30 05:38:46 asun Exp $ | 
|---|
|  | 7985 | + * cobalt-lcd.h : some useful defines for the Cobalt LCD driver | 
|---|
|  | 7986 | + *             (must be useable from both kernel and user space) | 
|---|
|  | 7987 | + * | 
|---|
|  | 7988 | + * Copyright 1996-2000 Cobalt Networks, Inc. | 
|---|
|  | 7989 | + * Copyright 2001 Sun Microsystems, Inc. | 
|---|
|  | 7990 | + * | 
|---|
|  | 7991 | + * By: Andrew Bose | 
|---|
|  | 7992 | + *     Timothy Stonis (x86 version) | 
|---|
|  | 7993 | + *     Tim Hockin | 
|---|
|  | 7994 | + *     Adrian Sun | 
|---|
|  | 7995 | + *     Erik Gilling | 
|---|
|  | 7996 | + *     Duncan Laurie | 
|---|
|  | 7997 | + */ | 
|---|
|  | 7998 | +#ifndef COBALT_LCD_H | 
|---|
|  | 7999 | +#define COBALT_LCD_H | 
|---|
|  | 8000 | + | 
|---|
|  | 8001 | +#ifdef __KERNEL__ | 
|---|
|  | 8002 | +#include <cobalt/cobalt.h> | 
|---|
|  | 8003 | +#endif | 
|---|
|  | 8004 | +#include <cobalt/led.h> | 
|---|
|  | 8005 | + | 
|---|
|  | 8006 | +#define COBALT_LCD_LINELEN     40 | 
|---|
|  | 8007 | +struct lcd_display { | 
|---|
|  | 8008 | +       unsigned long buttons; | 
|---|
|  | 8009 | +       int size1; | 
|---|
|  | 8010 | +       int size2; | 
|---|
|  | 8011 | +       unsigned char line1[COBALT_LCD_LINELEN]; | 
|---|
|  | 8012 | +       unsigned char line2[COBALT_LCD_LINELEN]; | 
|---|
|  | 8013 | +       unsigned char cursor_address; | 
|---|
|  | 8014 | +       unsigned char character; | 
|---|
|  | 8015 | +       unsigned char leds; | 
|---|
|  | 8016 | +       unsigned char *RomImage; | 
|---|
|  | 8017 | +}; | 
|---|
|  | 8018 | + | 
|---|
|  | 8019 | +/* different lcd types */ | 
|---|
|  | 8020 | +#define LCD_TYPE_UNKNOWN       0 | 
|---|
|  | 8021 | +#define LCD_TYPE_PARALLEL      1 | 
|---|
|  | 8022 | +#define LCD_TYPE_PARALLEL_B    2 | 
|---|
|  | 8023 | +#define LCD_TYPE_I2C           3 | 
|---|
|  | 8024 | + | 
|---|
|  | 8025 | +/* Function command codes for ioctl */ | 
|---|
|  | 8026 | +#define LCD_On                 1 | 
|---|
|  | 8027 | +#define LCD_Off                        2 | 
|---|
|  | 8028 | +#define LCD_Clear              3 | 
|---|
|  | 8029 | +#define LCD_Reset              4 | 
|---|
|  | 8030 | +#define LCD_Cursor_Left                5 | 
|---|
|  | 8031 | +#define LCD_Cursor_Right       6 | 
|---|
|  | 8032 | +#define LCD_Disp_Left          7 | 
|---|
|  | 8033 | +#define LCD_Disp_Right         8 | 
|---|
|  | 8034 | +#define LCD_Get_Cursor         9 | 
|---|
|  | 8035 | +#define LCD_Set_Cursor         10 | 
|---|
|  | 8036 | +#define LCD_Home               11 | 
|---|
|  | 8037 | +#define LCD_Read               12 | 
|---|
|  | 8038 | +#define LCD_Write              13 | 
|---|
|  | 8039 | +#define LCD_Cursor_Off         14 | 
|---|
|  | 8040 | +#define LCD_Cursor_On          15 | 
|---|
|  | 8041 | +#define LCD_Get_Cursor_Pos     16 | 
|---|
|  | 8042 | +#define LCD_Set_Cursor_Pos     17 | 
|---|
|  | 8043 | +#define LCD_Blink_Off          18 | 
|---|
|  | 8044 | +#define LCD_Raw_Inst           19 | 
|---|
|  | 8045 | +#define LCD_Raw_Data           20 | 
|---|
|  | 8046 | +#define LCD_Type               21 | 
|---|
|  | 8047 | + | 
|---|
|  | 8048 | +/* LED controls */ | 
|---|
|  | 8049 | +#define LED_Set                        40 | 
|---|
|  | 8050 | +#define LED_Bit_Set            41 | 
|---|
|  | 8051 | +#define LED_Bit_Clear          42 | 
|---|
|  | 8052 | +#define LED32_Set              43 | 
|---|
|  | 8053 | +#define LED32_Bit_Set          44 | 
|---|
|  | 8054 | +#define LED32_Bit_Clear                45 | 
|---|
|  | 8055 | +#define LED32_Get              46 | 
|---|
|  | 8056 | + | 
|---|
|  | 8057 | +/* button ioctls */ | 
|---|
|  | 8058 | +#define BUTTON_Read            50 | 
|---|
|  | 8059 | + | 
|---|
|  | 8060 | +/* Button defs */ | 
|---|
|  | 8061 | +#define BUTTON_Next            0x3D | 
|---|
|  | 8062 | +#define BUTTON_Next_B          0x7E | 
|---|
|  | 8063 | +#define BUTTON_Reset_B         0xFC | 
|---|
|  | 8064 | +#define BUTTON_NONE_B          0xFE | 
|---|
|  | 8065 | +#define BUTTON_Left_B          0xFA | 
|---|
|  | 8066 | +#define BUTTON_Right_B         0xDE | 
|---|
|  | 8067 | +#define BUTTON_Up_B            0xF6 | 
|---|
|  | 8068 | +#define BUTTON_Down_B          0xEE | 
|---|
|  | 8069 | +#define BUTTON_Enter_B         0xBE | 
|---|
|  | 8070 | + | 
|---|
|  | 8071 | +#define BUTTON_MASK             0xFE | 
|---|
|  | 8072 | + | 
|---|
|  | 8073 | +void cobalt_lcd_start_twiddle(void); | 
|---|
|  | 8074 | +void cobalt_lcd_stop_twiddle(void); | 
|---|
|  | 8075 | +void cobalt_lcd_off(void); | 
|---|
|  | 8076 | + | 
|---|
|  | 8077 | +#endif /* COBALT_LCD_H */ | 
|---|
|  | 8078 | diff -Naur linux-2.6.20.orig/include/cobalt/led.h linux-2.6.20/include/cobalt/led.h | 
|---|
|  | 8079 | --- linux-2.6.20.orig/include/cobalt/led.h      1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 8080 | +++ linux-2.6.20/include/cobalt/led.h   2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 8081 | @@ -0,0 +1,59 @@ | 
|---|
|  | 8082 | +/* | 
|---|
|  | 8083 | + * $Id: cobalt-led.h,v 1.7 2001/11/08 01:15:33 thockin Exp $ | 
|---|
|  | 8084 | + * cobalt-led.c | 
|---|
|  | 8085 | + * | 
|---|
|  | 8086 | + * Copyright 1996-2000 Cobalt Networks, Inc. | 
|---|
|  | 8087 | + * Copyright 2001 Sun Microsystems, Inc. | 
|---|
|  | 8088 | + * | 
|---|
|  | 8089 | + * By: Andrew Bose | 
|---|
|  | 8090 | + *     Timothy Stonis (x86 version) | 
|---|
|  | 8091 | + *     Tim Hockin | 
|---|
|  | 8092 | + *     Adrian Sun | 
|---|
|  | 8093 | + *     Erik Gilling | 
|---|
|  | 8094 | + *     Duncan Laurie | 
|---|
|  | 8095 | + */ | 
|---|
|  | 8096 | +#ifndef COBALT_LED_H | 
|---|
|  | 8097 | +#define COBALT_LED_H | 
|---|
|  | 8098 | + | 
|---|
|  | 8099 | +/* the set of all leds available on Cobalt systems */ | 
|---|
|  | 8100 | +#define LED_SHUTDOWN           (1 << 0) | 
|---|
|  | 8101 | +#define LED_WEBLIGHT           (1 << 1) | 
|---|
|  | 8102 | +#define LED_COBALTLOGO         (1 << 2) | 
|---|
|  | 8103 | +#define LED_ETH0_TXRX          (1 << 3) | 
|---|
|  | 8104 | +#define LED_ETH0_LINK          (1 << 4) | 
|---|
|  | 8105 | +#define LED_ETH1_TXRX          (1 << 5) | 
|---|
|  | 8106 | +#define LED_ETH1_LINK          (1 << 6) | 
|---|
|  | 8107 | +#define LED_DISK0              (1 << 7) | 
|---|
|  | 8108 | +#define LED_DISK1              (1 << 8) | 
|---|
|  | 8109 | +#define LED_DISK2              (1 << 9) | 
|---|
|  | 8110 | +#define LED_DISK3              (1 << 10) | 
|---|
|  | 8111 | +#define LED_SYSFAULT           (1 << 11) | 
|---|
|  | 8112 | +#define LED_MONTEREY_UNUSED0   (1 << 12) | 
|---|
|  | 8113 | +#define LED_MONTEREY_UNUSED1   (1 << 13) | 
|---|
|  | 8114 | +/* LED_MONTEREY_UNUSED2 is below */ | 
|---|
|  | 8115 | +#define LED_HEART              LED_MONTEREY_UNUSED0 | 
|---|
|  | 8116 | +#define LED_SPARE              LED_MONTEREY_UNUSED1 | 
|---|
|  | 8117 | +#define LED_SLED0              (1 << 14) | 
|---|
|  | 8118 | +#define LED_SLED1              (1 << 15) | 
|---|
|  | 8119 | +#define LED_SLED2              (1 << 16) | 
|---|
|  | 8120 | +#define LED_SLED3              (1 << 17) | 
|---|
|  | 8121 | +#define LED_MONTEREY_UNUSED2   (1 << 18) | 
|---|
|  | 8122 | +#define LED_SPARE2             LED_MONTEREY_UNUSED2 | 
|---|
|  | 8123 | + | 
|---|
|  | 8124 | +#ifdef __KERNEL__ | 
|---|
|  | 8125 | + | 
|---|
|  | 8126 | +extern void cobalt_led_set(const unsigned int leds); | 
|---|
|  | 8127 | +extern void cobalt_led_set_bits(const unsigned int leds); | 
|---|
|  | 8128 | +extern void cobalt_led_clear_bits(const unsigned int leds); | 
|---|
|  | 8129 | +extern void cobalt_led_set_lazy(const unsigned int leds); | 
|---|
|  | 8130 | +extern void cobalt_led_set_bits_lazy(const unsigned int leds); | 
|---|
|  | 8131 | +extern void cobalt_led_clear_bits_lazy(const unsigned int leds); | 
|---|
|  | 8132 | +extern unsigned int cobalt_led_get(void); | 
|---|
|  | 8133 | + | 
|---|
|  | 8134 | +extern int cobalt_fpled_register(unsigned int (*fn)(void *), void *data); | 
|---|
|  | 8135 | +extern int cobalt_fpled_unregister(unsigned int (*fn)(void *), void *data); | 
|---|
|  | 8136 | + | 
|---|
|  | 8137 | +#endif /* __KERNEL__ */ | 
|---|
|  | 8138 | + | 
|---|
|  | 8139 | +#endif /* COBALT_LED_H */ | 
|---|
|  | 8140 | + | 
|---|
|  | 8141 | diff -Naur linux-2.6.20.orig/include/cobalt/misc.h linux-2.6.20/include/cobalt/misc.h | 
|---|
|  | 8142 | --- linux-2.6.20.orig/include/cobalt/misc.h     1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 8143 | +++ linux-2.6.20/include/cobalt/misc.h  2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 8144 | @@ -0,0 +1,12 @@ | 
|---|
|  | 8145 | +/* $Id: cobalt-misc.h,v 1.1 2001/04/04 03:36:43 thockin Exp $ */ | 
|---|
|  | 8146 | +/* Copyright 2001 Sun Microsystems, Inc. */ | 
|---|
|  | 8147 | +#ifndef COBALT_MISC_H | 
|---|
|  | 8148 | +#define COBALT_MISC_H | 
|---|
|  | 8149 | + | 
|---|
|  | 8150 | +void cobalt_flush(void); | 
|---|
|  | 8151 | +void cobalt_nmi(unsigned char reason, struct pt_regs *regs); | 
|---|
|  | 8152 | +void cobalt_restart(void); | 
|---|
|  | 8153 | +void cobalt_halt(void); | 
|---|
|  | 8154 | +void cobalt_power_off(void); | 
|---|
|  | 8155 | + | 
|---|
|  | 8156 | +#endif | 
|---|
|  | 8157 | diff -Naur linux-2.6.20.orig/include/cobalt/net.h linux-2.6.20/include/cobalt/net.h | 
|---|
|  | 8158 | --- linux-2.6.20.orig/include/cobalt/net.h      1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 8159 | +++ linux-2.6.20/include/cobalt/net.h   2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 8160 | @@ -0,0 +1,12 @@ | 
|---|
|  | 8161 | +/* $Id: cobalt-net.h,v 1.3 2002/10/25 01:02:42 thockin Exp $ */ | 
|---|
|  | 8162 | +/* Copyright 2001 Sun Microsystems, Inc. */ | 
|---|
|  | 8163 | +#ifndef COBALT_NET_H | 
|---|
|  | 8164 | +#define COBALT_NET_H | 
|---|
|  | 8165 | + | 
|---|
|  | 8166 | +#include <linux/netdevice.h> | 
|---|
|  | 8167 | +#include <linux/config.h> | 
|---|
|  | 8168 | + | 
|---|
|  | 8169 | +void cobalt_net_register(struct net_device *ndev); | 
|---|
|  | 8170 | +void cobalt_net_unregister(struct net_device *ndev); | 
|---|
|  | 8171 | + | 
|---|
|  | 8172 | +#endif | 
|---|
|  | 8173 | diff -Naur linux-2.6.20.orig/include/cobalt/nvram.h linux-2.6.20/include/cobalt/nvram.h | 
|---|
|  | 8174 | --- linux-2.6.20.orig/include/cobalt/nvram.h    1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 8175 | +++ linux-2.6.20/include/cobalt/nvram.h 2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 8176 | @@ -0,0 +1,125 @@ | 
|---|
|  | 8177 | +/* | 
|---|
|  | 8178 | + * $Id: cobalt-nvram.h,v 1.21 2002/11/02 00:57:06 thockin Exp $ | 
|---|
|  | 8179 | + * cobalt-nvram.h : defines for the various fields in the cobalt NVRAM | 
|---|
|  | 8180 | + * | 
|---|
|  | 8181 | + * Copyright 2001 Sun Microsystems, Inc. | 
|---|
|  | 8182 | + */ | 
|---|
|  | 8183 | + | 
|---|
|  | 8184 | +#ifndef COBALT_NVRAM_H | 
|---|
|  | 8185 | +#define COBALT_NVRAM_H | 
|---|
|  | 8186 | + | 
|---|
|  | 8187 | +#include <linux/nvram.h> | 
|---|
|  | 8188 | + | 
|---|
|  | 8189 | +#define COBT_CMOS_INFO_MAX             0x7f    /* top address allowed */ | 
|---|
|  | 8190 | +#define COBT_CMOS_BIOS_DRIVE_INFO      0x12    /* drive info would go here */ | 
|---|
|  | 8191 | + | 
|---|
|  | 8192 | +#define COBT_CMOS_CKS_START            NVRAM_OFFSET(0x0e) | 
|---|
|  | 8193 | +#define COBT_CMOS_CKS_END              NVRAM_OFFSET(0x7f) | 
|---|
|  | 8194 | + | 
|---|
|  | 8195 | +/* flag bytes - 16 flags for now, leave room for more */ | 
|---|
|  | 8196 | +#define COBT_CMOS_FLAG_BYTE_0          NVRAM_OFFSET(0x10) | 
|---|
|  | 8197 | +#define COBT_CMOS_FLAG_BYTE_1          NVRAM_OFFSET(0x11) | 
|---|
|  | 8198 | + | 
|---|
|  | 8199 | +/* flags in flag bytes - up to 16 */ | 
|---|
|  | 8200 | +#define COBT_CMOS_FLAG_MIN             0x0001 | 
|---|
|  | 8201 | +#define COBT_CMOS_CONSOLE_FLAG         0x0001 /* console on/off */ | 
|---|
|  | 8202 | +#define COBT_CMOS_DEBUG_FLAG           0x0002 /* ROM debug messages */ | 
|---|
|  | 8203 | +#define COBT_CMOS_AUTO_PROMPT_FLAG     0x0004 /* boot to ROM prompt? */ | 
|---|
|  | 8204 | +#define COBT_CMOS_CLEAN_BOOT_FLAG      0x0008 /* set by a clean shutdown */ | 
|---|
|  | 8205 | +#define COBT_CMOS_HW_NOPROBE_FLAG      0x0010 /* go easy on the probing */ | 
|---|
|  | 8206 | +#define COBT_CMOS_SYSFAULT_FLAG                0x0020 /* system fault detected */ | 
|---|
|  | 8207 | +#define COBT_CMOS_OOPSPANIC_FLAG       0x0040 /* panic on oops */ | 
|---|
|  | 8208 | +#define COBT_CMOS_DELAY_CACHE_FLAG     0x0080 /* delay cache initialization */ | 
|---|
|  | 8209 | +#define COBT_CMOS_NOLOGO_FLAG          0x0100 /* hide "C" logo @ boot */ | 
|---|
|  | 8210 | +#define COBT_CMOS_VERSION_FLAG         0x0200 /* the version field is valid */ | 
|---|
|  | 8211 | +#define COBT_CMOS_FLAG_MAX             0x0200 | 
|---|
|  | 8212 | + | 
|---|
|  | 8213 | +/* leave byte 0x12 blank - Linux looks for drive info here */ | 
|---|
|  | 8214 | + | 
|---|
|  | 8215 | +/* CMOS structure version, valid if COBT_CMOS_VERSION_FLAG is true */ | 
|---|
|  | 8216 | +#define COBT_CMOS_VERSION              NVRAM_OFFSET(0x13) | 
|---|
|  | 8217 | +#define COBT_CMOS_VER_BTOCODE          1 /* min. version needed for btocode */ | 
|---|
|  | 8218 | + | 
|---|
|  | 8219 | +/* index of default boot method */ | 
|---|
|  | 8220 | +#define COBT_CMOS_BOOT_METHOD          NVRAM_OFFSET(0x20) | 
|---|
|  | 8221 | +#define COBT_CMOS_BOOT_METHOD_DISK     0 | 
|---|
|  | 8222 | +#define COBT_CMOS_BOOT_METHOD_ROM      1 | 
|---|
|  | 8223 | +#define COBT_CMOS_BOOT_METHOD_NET      2 | 
|---|
|  | 8224 | +#define COBT_CMOS_BOOT_METHOD_NNET     3 | 
|---|
|  | 8225 | +#define COBT_CMOS_BOOT_METHOD_OTHER    4 | 
|---|
|  | 8226 | + | 
|---|
|  | 8227 | +#define COBT_CMOS_BOOT_DEV_MIN         NVRAM_OFFSET(0x21) | 
|---|
|  | 8228 | +/* major #, minor # of first through fourth boot device */ | 
|---|
|  | 8229 | +#define COBT_CMOS_BOOT_DEV0_MAJ                NVRAM_OFFSET(0x21) | 
|---|
|  | 8230 | +#define COBT_CMOS_BOOT_DEV0_MIN                NVRAM_OFFSET(0x22) | 
|---|
|  | 8231 | +#define COBT_CMOS_BOOT_DEV1_MAJ                NVRAM_OFFSET(0x23) | 
|---|
|  | 8232 | +#define COBT_CMOS_BOOT_DEV1_MIN                NVRAM_OFFSET(0x24) | 
|---|
|  | 8233 | +#define COBT_CMOS_BOOT_DEV2_MAJ                NVRAM_OFFSET(0x25) | 
|---|
|  | 8234 | +#define COBT_CMOS_BOOT_DEV2_MIN                NVRAM_OFFSET(0x26) | 
|---|
|  | 8235 | +#define COBT_CMOS_BOOT_DEV3_MAJ                NVRAM_OFFSET(0x27) | 
|---|
|  | 8236 | +#define COBT_CMOS_BOOT_DEV3_MIN                NVRAM_OFFSET(0x28) | 
|---|
|  | 8237 | +#define COBT_CMOS_BOOT_DEV_MAX         NVRAM_OFFSET(0x28) | 
|---|
|  | 8238 | + | 
|---|
|  | 8239 | +/* checksum of bytes 0xe-0x7f */ | 
|---|
|  | 8240 | +#define COBT_CMOS_CHECKSUM             NVRAM_OFFSET(0x2e) | 
|---|
|  | 8241 | + | 
|---|
|  | 8242 | +/* running uptime counter, units of 5 minutes (32 bits =~ 41000 years) */ | 
|---|
|  | 8243 | +#define COBT_CMOS_UPTIME_0             NVRAM_OFFSET(0x30) | 
|---|
|  | 8244 | +#define COBT_CMOS_UPTIME_1             NVRAM_OFFSET(0x31) | 
|---|
|  | 8245 | +#define COBT_CMOS_UPTIME_2             NVRAM_OFFSET(0x32) | 
|---|
|  | 8246 | +#define COBT_CMOS_UPTIME_3             NVRAM_OFFSET(0x33) | 
|---|
|  | 8247 | + | 
|---|
|  | 8248 | +/* count of successful boots (32 bits) */ | 
|---|
|  | 8249 | +#define COBT_CMOS_BOOTCOUNT_0          NVRAM_OFFSET(0x38) | 
|---|
|  | 8250 | +#define COBT_CMOS_BOOTCOUNT_1          NVRAM_OFFSET(0x39) | 
|---|
|  | 8251 | +#define COBT_CMOS_BOOTCOUNT_2          NVRAM_OFFSET(0x3a) | 
|---|
|  | 8252 | +#define COBT_CMOS_BOOTCOUNT_3          NVRAM_OFFSET(0x3b) | 
|---|
|  | 8253 | + | 
|---|
|  | 8254 | +/* 13 bytes: system serial number, same as on the back of the system */ | 
|---|
|  | 8255 | +#define COBT_CMOS_SYS_SERNUM_LEN       13 | 
|---|
|  | 8256 | +#define COBT_CMOS_SYS_SERNUM_0         NVRAM_OFFSET(0x40) | 
|---|
|  | 8257 | +#define COBT_CMOS_SYS_SERNUM_1         NVRAM_OFFSET(0x41) | 
|---|
|  | 8258 | +#define COBT_CMOS_SYS_SERNUM_2         NVRAM_OFFSET(0x42) | 
|---|
|  | 8259 | +#define COBT_CMOS_SYS_SERNUM_3         NVRAM_OFFSET(0x43) | 
|---|
|  | 8260 | +#define COBT_CMOS_SYS_SERNUM_4         NVRAM_OFFSET(0x44) | 
|---|
|  | 8261 | +#define COBT_CMOS_SYS_SERNUM_5         NVRAM_OFFSET(0x45) | 
|---|
|  | 8262 | +#define COBT_CMOS_SYS_SERNUM_6         NVRAM_OFFSET(0x46) | 
|---|
|  | 8263 | +#define COBT_CMOS_SYS_SERNUM_7         NVRAM_OFFSET(0x47) | 
|---|
|  | 8264 | +#define COBT_CMOS_SYS_SERNUM_8         NVRAM_OFFSET(0x48) | 
|---|
|  | 8265 | +#define COBT_CMOS_SYS_SERNUM_9         NVRAM_OFFSET(0x49) | 
|---|
|  | 8266 | +#define COBT_CMOS_SYS_SERNUM_10                NVRAM_OFFSET(0x4a) | 
|---|
|  | 8267 | +#define COBT_CMOS_SYS_SERNUM_11                NVRAM_OFFSET(0x4b) | 
|---|
|  | 8268 | +#define COBT_CMOS_SYS_SERNUM_12                NVRAM_OFFSET(0x4c) | 
|---|
|  | 8269 | +/* checksum for serial num - 1 byte */ | 
|---|
|  | 8270 | +#define COBT_CMOS_SYS_SERNUM_CSUM      NVRAM_OFFSET(0x4f) | 
|---|
|  | 8271 | + | 
|---|
|  | 8272 | +#define COBT_CMOS_ROM_REV_MAJ          NVRAM_OFFSET(0x50) | 
|---|
|  | 8273 | +#define COBT_CMOS_ROM_REV_MIN          NVRAM_OFFSET(0x51) | 
|---|
|  | 8274 | +#define COBT_CMOS_ROM_REV_REV          NVRAM_OFFSET(0x52) | 
|---|
|  | 8275 | + | 
|---|
|  | 8276 | +#define COBT_CMOS_BTO_CODE_0           NVRAM_OFFSET(0x53) | 
|---|
|  | 8277 | +#define COBT_CMOS_BTO_CODE_1           NVRAM_OFFSET(0x54) | 
|---|
|  | 8278 | +#define COBT_CMOS_BTO_CODE_2           NVRAM_OFFSET(0x55) | 
|---|
|  | 8279 | +#define COBT_CMOS_BTO_CODE_3           NVRAM_OFFSET(0x56) | 
|---|
|  | 8280 | + | 
|---|
|  | 8281 | +#define COBT_CMOS_BTO_IP_CSUM          NVRAM_OFFSET(0x57) | 
|---|
|  | 8282 | +#define COBT_CMOS_BTO_IP_0             NVRAM_OFFSET(0x58) | 
|---|
|  | 8283 | +#define COBT_CMOS_BTO_IP_1             NVRAM_OFFSET(0x59) | 
|---|
|  | 8284 | +#define COBT_CMOS_BTO_IP_2             NVRAM_OFFSET(0x5a) | 
|---|
|  | 8285 | +#define COBT_CMOS_BTO_IP_3             NVRAM_OFFSET(0x5b) | 
|---|
|  | 8286 | + | 
|---|
|  | 8287 | +/* byte for load/run methods */ | 
|---|
|  | 8288 | +#define COBT_CMOS_BOOT_TYPE            NVRAM_OFFSET(0x5c) | 
|---|
|  | 8289 | +#define COBT_CMOS_BOOT_KERN_DEV                0x01 /* use kernel on major/minor */ | 
|---|
|  | 8290 | +#define COBT_CMOS_BOOT_KERN_ROM                0x02 /* use rom kernel */ | 
|---|
|  | 8291 | +#define COBT_CMOS_BOOT_KERN_NET                0x03 /* use net kernel */ | 
|---|
|  | 8292 | +#define COBT_CMOS_BOOT_KERN_MASK       0x0f /* mask for above */ | 
|---|
|  | 8293 | + | 
|---|
|  | 8294 | +#define COBT_CMOS_BOOT_FS_DEV          0x10 /* use major/minor number dev */ | 
|---|
|  | 8295 | +#define COBT_CMOS_BOOT_FS_NET          0x30 /* use net fs */ | 
|---|
|  | 8296 | +#define COBT_CMOS_BOOT_FS_MASK         0xf0 /* mask for above */ | 
|---|
|  | 8297 | + | 
|---|
|  | 8298 | +/* HA mode we're in (Twin Peaks) */ | 
|---|
|  | 8299 | +#define COBT_CMOS_HA_MODE              NVRAM_OFFSET(0x62) | 
|---|
|  | 8300 | + | 
|---|
|  | 8301 | +#endif /* COBALT_NVRAM_H */ | 
|---|
|  | 8302 | diff -Naur linux-2.6.20.orig/include/cobalt/ruler.h linux-2.6.20/include/cobalt/ruler.h | 
|---|
|  | 8303 | --- linux-2.6.20.orig/include/cobalt/ruler.h    1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 8304 | +++ linux-2.6.20/include/cobalt/ruler.h 2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 8305 | @@ -0,0 +1,15 @@ | 
|---|
|  | 8306 | +/* $Id: cobalt-ruler.h,v 1.4 2001/06/08 20:46:44 thockin Exp $ */ | 
|---|
|  | 8307 | +/* Copyright 2001 Sun Microsystems, Inc. */ | 
|---|
|  | 8308 | +#ifndef COBALT_RULER_H | 
|---|
|  | 8309 | +#define COBALT_RULER_H | 
|---|
|  | 8310 | + | 
|---|
|  | 8311 | +#include <linux/ide.h> | 
|---|
|  | 8312 | + | 
|---|
|  | 8313 | +void cobalt_ruler_register(ide_drive_t *hwif); | 
|---|
|  | 8314 | +void cobalt_ruler_unregister(ide_drive_t *hwif); | 
|---|
|  | 8315 | + | 
|---|
|  | 8316 | +//typedef int (*cob_busproc_t) (struct hwif_s *, int); | 
|---|
|  | 8317 | + | 
|---|
|  | 8318 | +//int *cob_busproc_t (ide_drive_t *, int); | 
|---|
|  | 8319 | + | 
|---|
|  | 8320 | +#endif | 
|---|
|  | 8321 | diff -Naur linux-2.6.20.orig/include/cobalt/sensors.h linux-2.6.20/include/cobalt/sensors.h | 
|---|
|  | 8322 | --- linux-2.6.20.orig/include/cobalt/sensors.h  1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 8323 | +++ linux-2.6.20/include/cobalt/sensors.h       2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 8324 | @@ -0,0 +1,29 @@ | 
|---|
|  | 8325 | +/* $Id: cobalt-sensors.h,v 1.2 2001/09/25 18:10:29 thockin Exp $ */ | 
|---|
|  | 8326 | +/* Copyright 2001 Sun Microsystems, Inc. */ | 
|---|
|  | 8327 | +#ifndef COBALT_SENSORS_H | 
|---|
|  | 8328 | +#define COBALT_SENSORS_H | 
|---|
|  | 8329 | + | 
|---|
|  | 8330 | +#include <cobalt/cobalt.h> | 
|---|
|  | 8331 | + | 
|---|
|  | 8332 | +extern unsigned int cobalt_nthermals; | 
|---|
|  | 8333 | +extern unsigned int cobalt_nvoltages; | 
|---|
|  | 8334 | + | 
|---|
|  | 8335 | +/* return NULL if the sensor doesn't exist, fill buf if it does */ | 
|---|
|  | 8336 | +char *__cobalt_thermal_read(unsigned int sensor, char *buf, int len); | 
|---|
|  | 8337 | +char *__cobalt_voltage_read(unsigned int sensor, char *buf, int len); | 
|---|
|  | 8338 | + | 
|---|
|  | 8339 | +static inline char * | 
|---|
|  | 8340 | +cobalt_thermal_read(unsigned int sensor) | 
|---|
|  | 8341 | +{ | 
|---|
|  | 8342 | +       char buf[32]; | 
|---|
|  | 8343 | +       return __cobalt_thermal_read(sensor, buf, sizeof(buf)-1); | 
|---|
|  | 8344 | +} | 
|---|
|  | 8345 | + | 
|---|
|  | 8346 | +static inline char * | 
|---|
|  | 8347 | +cobalt_voltage_read(unsigned int sensor) | 
|---|
|  | 8348 | +{ | 
|---|
|  | 8349 | +       char buf[32]; | 
|---|
|  | 8350 | +       return __cobalt_voltage_read(sensor, buf, sizeof(buf)-1); | 
|---|
|  | 8351 | +} | 
|---|
|  | 8352 | + | 
|---|
|  | 8353 | +#endif | 
|---|
|  | 8354 | diff -Naur linux-2.6.20.orig/include/cobalt/serialnum.h linux-2.6.20/include/cobalt/serialnum.h | 
|---|
|  | 8355 | --- linux-2.6.20.orig/include/cobalt/serialnum.h        1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 8356 | +++ linux-2.6.20/include/cobalt/serialnum.h     2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 8357 | @@ -0,0 +1,16 @@ | 
|---|
|  | 8358 | +/* | 
|---|
|  | 8359 | + * $Id: cobalt-serialnum.h,v 1.1 2001/03/07 01:58:24 thockin Exp $ | 
|---|
|  | 8360 | + * cobalt-serialnum.h : access to the DS2401 serial number | 
|---|
|  | 8361 | + * | 
|---|
|  | 8362 | + * Copyright 2000 Cobalt Networks, Inc. | 
|---|
|  | 8363 | + * Copyright 2001 Sun Microsystems, Inc. | 
|---|
|  | 8364 | + */ | 
|---|
|  | 8365 | +#ifndef COBALT_SERIALNUM_H | 
|---|
|  | 8366 | +#define COBALT_SERIALNUM_H | 
|---|
|  | 8367 | + | 
|---|
|  | 8368 | +#include <cobalt/cobalt.h> | 
|---|
|  | 8369 | + | 
|---|
|  | 8370 | +char *cobalt_serialnum_get(void); | 
|---|
|  | 8371 | +unsigned long cobalt_hostid_get(void); | 
|---|
|  | 8372 | + | 
|---|
|  | 8373 | +#endif /* COBALT_SERIALNUM_H */ | 
|---|
|  | 8374 | diff -Naur linux-2.6.20.orig/include/cobalt/superio.h linux-2.6.20/include/cobalt/superio.h | 
|---|
|  | 8375 | --- linux-2.6.20.orig/include/cobalt/superio.h  1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 8376 | +++ linux-2.6.20/include/cobalt/superio.h       2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 8377 | @@ -0,0 +1,225 @@ | 
|---|
|  | 8378 | +/* | 
|---|
|  | 8379 | + * $Id: cobalt-superio.h,v 1.11 2001/11/02 12:00:03 duncan Exp $ | 
|---|
|  | 8380 | + * cobalt-superio.h : SuperIO support for Sun/Cobalt servers | 
|---|
|  | 8381 | + * | 
|---|
|  | 8382 | + * Copyright 2000 Cobalt Networks, Inc. | 
|---|
|  | 8383 | + * Copyright 2001 Sun Microsystems, Inc. | 
|---|
|  | 8384 | + */ | 
|---|
|  | 8385 | +#ifndef COBALT_SUPERIO_H | 
|---|
|  | 8386 | +#define COBALT_SUPERIO_H | 
|---|
|  | 8387 | + | 
|---|
|  | 8388 | +#include <cobalt/cobalt.h> | 
|---|
|  | 8389 | +#include <cobalt/systype.h> | 
|---|
|  | 8390 | + | 
|---|
|  | 8391 | +/* the lock that protects superio accesses */ | 
|---|
|  | 8392 | +extern spinlock_t cobalt_superio_lock; | 
|---|
|  | 8393 | + | 
|---|
|  | 8394 | +/* | 
|---|
|  | 8395 | + * The main functions of the SuperIO are accessed via index/data registers | 
|---|
|  | 8396 | + * These are the same for both SuperIO chip families | 
|---|
|  | 8397 | + */ | 
|---|
|  | 8398 | +#define SUPERIO_INDEX_PORT     0x2e | 
|---|
|  | 8399 | +#define SUPERIO_DATA_PORT      0x2f | 
|---|
|  | 8400 | + | 
|---|
|  | 8401 | +/* | 
|---|
|  | 8402 | + * This index allows you to select a logical device | 
|---|
|  | 8403 | + */ | 
|---|
|  | 8404 | +#define SUPERIO_LOGICAL_DEV    0x07 | 
|---|
|  | 8405 | + | 
|---|
|  | 8406 | +/* | 
|---|
|  | 8407 | + * Type of SUPERIO | 
|---|
|  | 8408 | + */ | 
|---|
|  | 8409 | +#define SUPERIO_SID             0x20 | 
|---|
|  | 8410 | + | 
|---|
|  | 8411 | +/* | 
|---|
|  | 8412 | + * Some indices that are common to all logical devices | 
|---|
|  | 8413 | + */ | 
|---|
|  | 8414 | +#define SUPERIO_ACTIVATE       0x30 | 
|---|
|  | 8415 | +#define SUPERIO_ADDR_HIGH      0x60 | 
|---|
|  | 8416 | +#define SUPERIO_ADDR_LOW       0x61 | 
|---|
|  | 8417 | +#define SUPERIO_INTR_PIN       0x70 | 
|---|
|  | 8418 | +#define SUPERIO_INTR_TYPE      0x71 | 
|---|
|  | 8419 | + | 
|---|
|  | 8420 | + | 
|---|
|  | 8421 | +/* | 
|---|
|  | 8422 | + * PC87317 SuperIO is found on XTR | 
|---|
|  | 8423 | + */ | 
|---|
|  | 8424 | + | 
|---|
|  | 8425 | +/* | 
|---|
|  | 8426 | + * logical devices - write to LOGICAL_DEV index | 
|---|
|  | 8427 | + */ | 
|---|
|  | 8428 | +#define PC87317_DEV_RTC                0x02 | 
|---|
|  | 8429 | +#define PC87317_DEV_GPIO       0x07 | 
|---|
|  | 8430 | +#define PC87317_DEV_PM         0x08 | 
|---|
|  | 8431 | + | 
|---|
|  | 8432 | +/* withing the PM dev, are the following indices */ | 
|---|
|  | 8433 | +#define PC87317_PMDEV_WDTO     0x05 | 
|---|
|  | 8434 | +#define PC87317_PMDEV_GPELO    0x0e | 
|---|
|  | 8435 | +#define PC87317_PMDEV_GPEHI    0x0f | 
|---|
|  | 8436 | + | 
|---|
|  | 8437 | +/* within the APC bank of RTC */ | 
|---|
|  | 8438 | +#define PC87317_APCR1          0x40 | 
|---|
|  | 8439 | +#define PC87317_APCR2          0x41 | 
|---|
|  | 8440 | +#define PC87317_APCR3          0x49 | 
|---|
|  | 8441 | +#define PC87317_APCR4          0x4a | 
|---|
|  | 8442 | +#define PC87317_APCR5          0x4b | 
|---|
|  | 8443 | +#define PC87317_APCR6          0x4c | 
|---|
|  | 8444 | +#define PC87317_APCR7          0x4d | 
|---|
|  | 8445 | + | 
|---|
|  | 8446 | +#define PC87317_RTC_BANK_MAIN  0 | 
|---|
|  | 8447 | +#define PC87317_RTC_BANK_RTC   1 | 
|---|
|  | 8448 | +#define PC87317_RTC_BANK_APC   2 | 
|---|
|  | 8449 | +#define PC87317_RTC_CRA                0x0a | 
|---|
|  | 8450 | +#define PC87317_RTC_BANK_0     0x20 | 
|---|
|  | 8451 | +#define PC87317_RTC_BANK_1     0x30 | 
|---|
|  | 8452 | +#define PC87317_RTC_BANK_2     0x40 | 
|---|
|  | 8453 | + | 
|---|
|  | 8454 | +#define PC87317_PWRBUTTON      0x01 | 
|---|
|  | 8455 | +#define PC87317_PM1_STATUS     0x01 | 
|---|
|  | 8456 | + | 
|---|
|  | 8457 | +/* offsets from GPEHI/GPELO */ | 
|---|
|  | 8458 | +#define PC87317_GPE_GP1_STS0   0x00 | 
|---|
|  | 8459 | +#define PC87317_GPE_GP1_STS1   0x01 | 
|---|
|  | 8460 | +#define PC87317_GPE_GP1_STS2   0x02 | 
|---|
|  | 8461 | +#define PC87317_GPE_GP1_STS3   0x03 | 
|---|
|  | 8462 | +#define PC87317_GPE_GP1_EN0    0x04 | 
|---|
|  | 8463 | +#define PC87317_GPE_GP1_EN1    0x05 | 
|---|
|  | 8464 | +#define PC87317_GPE_GP1_EN2    0x06 | 
|---|
|  | 8465 | +#define PC87317_GPE_GP1_EN3    0x07 | 
|---|
|  | 8466 | +#define PC87317_GPE_GP2_EN0    0x08 | 
|---|
|  | 8467 | +#define PC87317_GPE_SMI_CMD    0x0c | 
|---|
|  | 8468 | + | 
|---|
|  | 8469 | +/* | 
|---|
|  | 8470 | + * PC87417 family is found on alpine | 
|---|
|  | 8471 | + */ | 
|---|
|  | 8472 | + | 
|---|
|  | 8473 | +#define PC87417_DEV_SWC                0x4 | 
|---|
|  | 8474 | +#define PC87417_DEV_GPIO       0x7 | 
|---|
|  | 8475 | +#define PC87417_DEV_RTC                0x10 | 
|---|
|  | 8476 | + | 
|---|
|  | 8477 | +/* registers in the SWC dev */ | 
|---|
|  | 8478 | +#define PC87417_SWC_PWONCTL    0x9 | 
|---|
|  | 8479 | +/* | 
|---|
|  | 8480 | + * within the System Wake Control device, there are banks, write the bank you | 
|---|
|  | 8481 | + * want to SWC_BANK | 
|---|
|  | 8482 | + */ | 
|---|
|  | 8483 | +#define PC87417_SWC_BANK       0xf | 
|---|
|  | 8484 | +#define PC87417_SWCBANK_ACPI   0x2 | 
|---|
|  | 8485 | +#define PC87417_SWCBANK_WDT    0x3 | 
|---|
|  | 8486 | + | 
|---|
|  | 8487 | +/* | 
|---|
|  | 8488 | + * the SWC WDT bank has 3 main registers | 
|---|
|  | 8489 | + */ | 
|---|
|  | 8490 | +#define PC87417_WDT_CONTROL    0x10 | 
|---|
|  | 8491 | +#define PC87417_WDT_TIMEOUT    0x11 | 
|---|
|  | 8492 | +#define PC87417_WDT_CONFIG     0x12 | 
|---|
|  | 8493 | + | 
|---|
|  | 8494 | +/* | 
|---|
|  | 8495 | + * within the SWC, two regs serve as index/data for wake-event enabling | 
|---|
|  | 8496 | + */ | 
|---|
|  | 8497 | +#define PC87417_SWC_WKEVENT    0x0 | 
|---|
|  | 8498 | +#define PC87417_SWC_WKSTATE    0x1 | 
|---|
|  | 8499 | +#define PC87417_SWCWKEVENT_GPIOE42 0xa | 
|---|
|  | 8500 | +#define PC87417_SWCWKEVENT_RTC         0x18 | 
|---|
|  | 8501 | + | 
|---|
|  | 8502 | + | 
|---|
|  | 8503 | +/* | 
|---|
|  | 8504 | + * types of superIOs | 
|---|
|  | 8505 | + */ | 
|---|
|  | 8506 | +enum superio_type_t | 
|---|
|  | 8507 | +{ | 
|---|
|  | 8508 | +    SIO_TYPE_UNKNOWN, | 
|---|
|  | 8509 | +    SIO_TYPE_PC8731X, | 
|---|
|  | 8510 | +    SIO_TYPE_PC8741X, | 
|---|
|  | 8511 | +}; | 
|---|
|  | 8512 | + | 
|---|
|  | 8513 | + | 
|---|
|  | 8514 | + | 
|---|
|  | 8515 | +#define PC8731X_SID 0xd0 | 
|---|
|  | 8516 | +#define PC9731X_SID 0xdf | 
|---|
|  | 8517 | +#define PC8741X_SID 0xee | 
|---|
|  | 8518 | + | 
|---|
|  | 8519 | +static inline int superio_type( void ) | 
|---|
|  | 8520 | +{ | 
|---|
|  | 8521 | +    u8 reg; | 
|---|
|  | 8522 | +    unsigned long flags; | 
|---|
|  | 8523 | +    enum superio_type_t type; | 
|---|
|  | 8524 | + | 
|---|
|  | 8525 | +    spin_lock_irqsave(&cobalt_superio_lock, flags); | 
|---|
|  | 8526 | + | 
|---|
|  | 8527 | +    outb(SUPERIO_SID, SUPERIO_INDEX_PORT); | 
|---|
|  | 8528 | +    reg = inb( SUPERIO_DATA_PORT ); | 
|---|
|  | 8529 | +    switch( reg ) | 
|---|
|  | 8530 | +    { | 
|---|
|  | 8531 | +       case PC8731X_SID: | 
|---|
|  | 8532 | +       case PC9731X_SID: | 
|---|
|  | 8533 | +           type = SIO_TYPE_PC8731X; | 
|---|
|  | 8534 | +           break; | 
|---|
|  | 8535 | + | 
|---|
|  | 8536 | +       case PC8741X_SID: | 
|---|
|  | 8537 | +           type = SIO_TYPE_PC8741X; | 
|---|
|  | 8538 | +           break; | 
|---|
|  | 8539 | + | 
|---|
|  | 8540 | +       default: | 
|---|
|  | 8541 | +           type = SIO_TYPE_UNKNOWN; | 
|---|
|  | 8542 | +           break; | 
|---|
|  | 8543 | +    } | 
|---|
|  | 8544 | + | 
|---|
|  | 8545 | +    spin_unlock_irqrestore(&cobalt_superio_lock, flags); | 
|---|
|  | 8546 | + | 
|---|
|  | 8547 | +    return type; | 
|---|
|  | 8548 | +} | 
|---|
|  | 8549 | + | 
|---|
|  | 8550 | +/* | 
|---|
|  | 8551 | + * stuff to make life easier | 
|---|
|  | 8552 | + */ | 
|---|
|  | 8553 | + | 
|---|
|  | 8554 | +/* read the base address of a particular superio logical device */ | 
|---|
|  | 8555 | +#define superio_ldev_base(ldev)                superio_ldev_base_n(ldev, 0) | 
|---|
|  | 8556 | +static inline unsigned short | 
|---|
|  | 8557 | +superio_ldev_base_n(int ldev, int n) | 
|---|
|  | 8558 | +{ | 
|---|
|  | 8559 | +       unsigned long flags; | 
|---|
|  | 8560 | +       unsigned short addr; | 
|---|
|  | 8561 | + | 
|---|
|  | 8562 | +       spin_lock_irqsave(&cobalt_superio_lock, flags); | 
|---|
|  | 8563 | + | 
|---|
|  | 8564 | +       /* select the logical device */ | 
|---|
|  | 8565 | +       outb(SUPERIO_LOGICAL_DEV, SUPERIO_INDEX_PORT); | 
|---|
|  | 8566 | +       outb(ldev, SUPERIO_DATA_PORT); | 
|---|
|  | 8567 | + | 
|---|
|  | 8568 | +       /* read the 2-byte base address */ | 
|---|
|  | 8569 | +       outb(SUPERIO_ADDR_HIGH+(n*2), SUPERIO_INDEX_PORT); | 
|---|
|  | 8570 | +       addr = inb(SUPERIO_DATA_PORT) << 8; | 
|---|
|  | 8571 | +       outb(SUPERIO_ADDR_LOW+(n*2), SUPERIO_INDEX_PORT); | 
|---|
|  | 8572 | +       addr |= inb(SUPERIO_DATA_PORT); | 
|---|
|  | 8573 | + | 
|---|
|  | 8574 | +       spin_unlock_irqrestore(&cobalt_superio_lock, flags); | 
|---|
|  | 8575 | + | 
|---|
|  | 8576 | +       return addr; | 
|---|
|  | 8577 | +} | 
|---|
|  | 8578 | + | 
|---|
|  | 8579 | +static inline void | 
|---|
|  | 8580 | +superio_set_rtc_bank(const unsigned int page) | 
|---|
|  | 8581 | +{ | 
|---|
|  | 8582 | +       if (cobt_is_monterey()) { | 
|---|
|  | 8583 | +               unsigned char val; | 
|---|
|  | 8584 | + | 
|---|
|  | 8585 | +               val = CMOS_READ(0xa); | 
|---|
|  | 8586 | +               val &= ~0x70; | 
|---|
|  | 8587 | +               switch (page) { | 
|---|
|  | 8588 | +               case PC87317_RTC_BANK_MAIN: | 
|---|
|  | 8589 | +                       val |= 0x20; | 
|---|
|  | 8590 | +                       break; | 
|---|
|  | 8591 | +               case PC87317_RTC_BANK_RTC: | 
|---|
|  | 8592 | +                       val |= 0x30; | 
|---|
|  | 8593 | +                       break; | 
|---|
|  | 8594 | +               case PC87317_RTC_BANK_APC: | 
|---|
|  | 8595 | +                       val |= 0x40; | 
|---|
|  | 8596 | +                       break; | 
|---|
|  | 8597 | +               } | 
|---|
|  | 8598 | +               CMOS_WRITE(val, 0xa); | 
|---|
|  | 8599 | +       } | 
|---|
|  | 8600 | +} | 
|---|
|  | 8601 | + | 
|---|
|  | 8602 | +#endif /* COBALT_SUPERIO_H */ | 
|---|
|  | 8603 | diff -Naur linux-2.6.20.orig/include/cobalt/systype.h linux-2.6.20/include/cobalt/systype.h | 
|---|
|  | 8604 | --- linux-2.6.20.orig/include/cobalt/systype.h  1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 8605 | +++ linux-2.6.20/include/cobalt/systype.h       2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 8606 | @@ -0,0 +1,99 @@ | 
|---|
|  | 8607 | +/* | 
|---|
|  | 8608 | + * $Id: cobalt-systype.h,v 1.8 2002/08/08 22:46:50 carls Exp $ | 
|---|
|  | 8609 | + * cobalt-systype.h : figure out what Cobalt system we are on | 
|---|
|  | 8610 | + * | 
|---|
|  | 8611 | + * Copyright 2000 Cobalt Networks, Inc. | 
|---|
|  | 8612 | + * Copyright 2001-2002 Sun Microsystems, Inc. | 
|---|
|  | 8613 | + */ | 
|---|
|  | 8614 | +#ifndef COBALT_SYSTYPE_H | 
|---|
|  | 8615 | +#define COBALT_SYSTYPE_H | 
|---|
|  | 8616 | + | 
|---|
|  | 8617 | +#include <cobalt/cobalt.h> | 
|---|
|  | 8618 | + | 
|---|
|  | 8619 | +typedef enum { | 
|---|
|  | 8620 | +       COBT_UNINITIALIZED, | 
|---|
|  | 8621 | +       COBT_UNKNOWN, | 
|---|
|  | 8622 | +       COBT_PACIFICA, | 
|---|
|  | 8623 | +       COBT_CARMEL, | 
|---|
|  | 8624 | +       COBT_MONTEREY, | 
|---|
|  | 8625 | +       COBT_ALPINE, | 
|---|
|  | 8626 | +       COBT_BIGBEAR, | 
|---|
|  | 8627 | +} cobt_sys_t; | 
|---|
|  | 8628 | + | 
|---|
|  | 8629 | +extern cobt_sys_t cobt_type; | 
|---|
|  | 8630 | +extern cobt_sys_t cobalt_systype_probe(void); | 
|---|
|  | 8631 | +extern unsigned long cobt_rev; | 
|---|
|  | 8632 | + | 
|---|
|  | 8633 | +/* | 
|---|
|  | 8634 | + * one test for each major board-type | 
|---|
|  | 8635 | + * COBT_SUPPORT_* from cobalt.h | 
|---|
|  | 8636 | + */ | 
|---|
|  | 8637 | + | 
|---|
|  | 8638 | +/* pacifica is the RaQ 3 and RaQ 4 platform */ | 
|---|
|  | 8639 | +static inline int | 
|---|
|  | 8640 | +cobt_is_pacifica(void) | 
|---|
|  | 8641 | +{ | 
|---|
|  | 8642 | +       if (!COBT_SUPPORT_GEN_III) { | 
|---|
|  | 8643 | +               return 0; | 
|---|
|  | 8644 | +       } | 
|---|
|  | 8645 | +       if (cobt_type == COBT_UNINITIALIZED) { | 
|---|
|  | 8646 | +               cobalt_systype_probe(); | 
|---|
|  | 8647 | +       } | 
|---|
|  | 8648 | +       return (cobt_type == COBT_PACIFICA); | 
|---|
|  | 8649 | +} | 
|---|
|  | 8650 | + | 
|---|
|  | 8651 | +/* carmel is the Qube 3 platform */ | 
|---|
|  | 8652 | +static inline int | 
|---|
|  | 8653 | +cobt_is_carmel(void) | 
|---|
|  | 8654 | +{ | 
|---|
|  | 8655 | +       if (!COBT_SUPPORT_GEN_III) { | 
|---|
|  | 8656 | +               return 0; | 
|---|
|  | 8657 | +       } | 
|---|
|  | 8658 | +       if (cobt_type == COBT_UNINITIALIZED) { | 
|---|
|  | 8659 | +               cobalt_systype_probe(); | 
|---|
|  | 8660 | +       } | 
|---|
|  | 8661 | +       return (cobt_type == COBT_CARMEL); | 
|---|
|  | 8662 | +} | 
|---|
|  | 8663 | + | 
|---|
|  | 8664 | +/* monterey is the RaQ XTR platform */ | 
|---|
|  | 8665 | +static inline int | 
|---|
|  | 8666 | +cobt_is_monterey(void) | 
|---|
|  | 8667 | +{ | 
|---|
|  | 8668 | +       if (!COBT_SUPPORT_GEN_V) { | 
|---|
|  | 8669 | +               return 0; | 
|---|
|  | 8670 | +       } | 
|---|
|  | 8671 | +       if (cobt_type == COBT_UNINITIALIZED) { | 
|---|
|  | 8672 | +               cobalt_systype_probe(); | 
|---|
|  | 8673 | +       } | 
|---|
|  | 8674 | +       return (cobt_type == COBT_MONTEREY); | 
|---|
|  | 8675 | +} | 
|---|
|  | 8676 | + | 
|---|
|  | 8677 | +static inline int | 
|---|
|  | 8678 | +cobt_is_alpine(void) | 
|---|
|  | 8679 | +{ | 
|---|
|  | 8680 | +       if (!COBT_SUPPORT_GEN_V) { | 
|---|
|  | 8681 | +               return 0; | 
|---|
|  | 8682 | +       } | 
|---|
|  | 8683 | +       if (cobt_type == COBT_UNINITIALIZED) { | 
|---|
|  | 8684 | +               cobalt_systype_probe(); | 
|---|
|  | 8685 | +       } | 
|---|
|  | 8686 | +       return (cobt_type == COBT_ALPINE); | 
|---|
|  | 8687 | +} | 
|---|
|  | 8688 | + | 
|---|
|  | 8689 | +static inline int | 
|---|
|  | 8690 | +cobt_is_bigbear(void) | 
|---|
|  | 8691 | +{ | 
|---|
|  | 8692 | +       if (!COBT_SUPPORT_GEN_V) { | 
|---|
|  | 8693 | +               return 0; | 
|---|
|  | 8694 | +       } | 
|---|
|  | 8695 | +       if (cobt_type == COBT_UNINITIALIZED) { | 
|---|
|  | 8696 | +               cobalt_systype_probe(); | 
|---|
|  | 8697 | +       } | 
|---|
|  | 8698 | +       return (cobt_type == COBT_BIGBEAR); | 
|---|
|  | 8699 | +} | 
|---|
|  | 8700 | + | 
|---|
|  | 8701 | +/* one for each major generation */ | 
|---|
|  | 8702 | +#define cobt_is_3k()    (cobt_is_pacifica() || cobt_is_carmel()) | 
|---|
|  | 8703 | +#define cobt_is_5k()    (cobt_is_monterey() || cobt_is_alpine() || cobt_is_bigbear()) | 
|---|
|  | 8704 | + | 
|---|
|  | 8705 | +#endif | 
|---|
|  | 8706 | diff -Naur linux-2.6.20.orig/include/cobalt/wdt.h linux-2.6.20/include/cobalt/wdt.h | 
|---|
|  | 8707 | --- linux-2.6.20.orig/include/cobalt/wdt.h      1969-12-31 16:00:00.000000000 -0800 | 
|---|
|  | 8708 | +++ linux-2.6.20/include/cobalt/wdt.h   2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 8709 | @@ -0,0 +1,16 @@ | 
|---|
|  | 8710 | +/* $Id: cobalt-wdt.h,v 1.1 2001/03/07 01:58:24 thockin Exp $ */ | 
|---|
|  | 8711 | +/* Copyright 2001 Sun Microsystems, Inc. */ | 
|---|
|  | 8712 | +#ifndef COBALT_WDT_H | 
|---|
|  | 8713 | +#define COBALT_WDT_H | 
|---|
|  | 8714 | + | 
|---|
|  | 8715 | +#include <cobalt/cobalt.h> | 
|---|
|  | 8716 | + | 
|---|
|  | 8717 | +void cobalt_wdt_refresh(unsigned long refresh_timer); | 
|---|
|  | 8718 | +void cobalt_wdt_trigger_reboot(void); | 
|---|
|  | 8719 | + | 
|---|
|  | 8720 | +void cobalt_wdt_disable(void); | 
|---|
|  | 8721 | +void cobalt_wdt_reenable(void); | 
|---|
|  | 8722 | + | 
|---|
|  | 8723 | +void cobalt_wdt_cleardog(void); | 
|---|
|  | 8724 | + | 
|---|
|  | 8725 | +#endif | 
|---|
|  | 8726 | diff -Naur linux-2.6.20.orig/init/main.c linux-2.6.20/init/main.c | 
|---|
|  | 8727 | --- linux-2.6.20.orig/init/main.c       2007-02-04 10:44:54.000000000 -0800 | 
|---|
|  | 8728 | +++ linux-2.6.20/init/main.c    2007-02-04 20:37:44.000000000 -0800 | 
|---|
|  | 8729 | @@ -681,6 +681,10 @@ | 
|---|
|  | 8730 | * | 
|---|
|  | 8731 | * Now we can finally start doing some real work.. | 
|---|
|  | 8732 | */ | 
|---|
|  | 8733 | +#ifdef CONFIG_COBALT_RAQ | 
|---|
|  | 8734 | +extern int cobalt_init(void); | 
|---|
|  | 8735 | +#endif | 
|---|
|  | 8736 | + | 
|---|
|  | 8737 | static void __init do_basic_setup(void) | 
|---|
|  | 8738 | { | 
|---|
|  | 8739 | /* drivers will send hotplug events */ | 
|---|
|  | 8740 | @@ -693,6 +697,10 @@ | 
|---|
|  | 8741 | #endif | 
|---|
|  | 8742 |  | 
|---|
|  | 8743 | do_initcalls(); | 
|---|
|  | 8744 | + | 
|---|
|  | 8745 | +#ifdef CONFIG_COBALT_RAQ | 
|---|
|  | 8746 | +    cobalt_init(); | 
|---|
|  | 8747 | +#endif | 
|---|
|  | 8748 | } | 
|---|
|  | 8749 |  | 
|---|
|  | 8750 | static void __init do_pre_smp_initcalls(void) | 
|---|