[18bf2a3] | 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)
|
---|