source: patches/linux-2.6.18.3-cobalt_x86-1.patch@ 24e3a57

clfs-1.2 clfs-2.1 clfs-3.0.0-systemd clfs-3.0.0-sysvinit systemd sysvinit
Last change on this file since 24e3a57 was 715c21d, checked in by Jim Gifford <clfs@…>, 18 years ago

Added: Linux 2.6.18.3 Patches

  • Property mode set to 100644
File size: 217.8 KB
RevLine 
[715c21d]1Submitted By: Jim Gifford (patches at jg555 dot com)
2Date: 2006-11-15
3Initial Package Version: 2.6.18.2
4Origin: Gentoo - Jeff Waters
5Upstream Status: N/A
6Description: Adds Support for the x86 Cobalt Series
7
8diff -Naur linux-2.6.18.2.orig/Makefile linux-2.6.18.2/Makefile
9--- linux-2.6.18.2.orig/Makefile 2006-11-03 17:33:58.000000000 -0800
10+++ linux-2.6.18.2/Makefile 2006-11-15 21:20:19.730033585 -0800
11@@ -197,6 +197,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@@ -702,6 +703,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
31diff -Naur linux-2.6.18.2.orig/arch/i386/kernel/Makefile linux-2.6.18.2/arch/i386/kernel/Makefile
32--- linux-2.6.18.2.orig/arch/i386/kernel/Makefile 2006-11-03 17:33:58.000000000 -0800
33+++ linux-2.6.18.2/arch/i386/kernel/Makefile 2006-11-15 21:20:19.730033585 -0800
34@@ -52,6 +52,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 $@
42diff -Naur linux-2.6.18.2.orig/arch/i386/kernel/cobalt.c linux-2.6.18.2/arch/i386/kernel/cobalt.c
43--- linux-2.6.18.2.orig/arch/i386/kernel/cobalt.c 1969-12-31 16:00:00.000000000 -0800
44+++ linux-2.6.18.2/arch/i386/kernel/cobalt.c 2006-11-15 21:20:19.730033585 -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);
327diff -Naur linux-2.6.18.2.orig/arch/i386/kernel/process.c linux-2.6.18.2/arch/i386/kernel/process.c
328--- linux-2.6.18.2.orig/arch/i386/kernel/process.c 2006-11-03 17:33:58.000000000 -0800
329+++ linux-2.6.18.2/arch/i386/kernel/process.c 2006-11-15 21:28:11.450334183 -0800
330@@ -51,6 +51,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@@ -482,6 +487,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;
355diff -Naur linux-2.6.18.2.orig/arch/i386/kernel/reboot.c linux-2.6.18.2/arch/i386/kernel/reboot.c
356--- linux-2.6.18.2.orig/arch/i386/kernel/reboot.c 2006-11-03 17:33:58.000000000 -0800
357+++ linux-2.6.18.2/arch/i386/kernel/reboot.c 2006-11-15 21:26:57.096812163 -0800
358@@ -18,6 +18,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@@ -283,8 +288,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@@ -321,6 +356,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@@ -345,6 +383,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 }
430diff -Naur linux-2.6.18.2.orig/arch/i386/kernel/traps.c linux-2.6.18.2/arch/i386/kernel/traps.c
431--- linux-2.6.18.2.orig/arch/i386/kernel/traps.c 2006-11-03 17:33:58.000000000 -0800
432+++ linux-2.6.18.2/arch/i386/kernel/traps.c 2006-11-15 21:20:19.734033452 -0800
433@@ -56,6 +56,10 @@
434
435 #include "mach_traps.h"
436
437+#ifdef CONFIG_COBALT_RAQ
438+#include <cobalt/misc.h>
439+#endif
440+
441 asmlinkage int system_call(void);
442
443 struct desc_struct default_ldt[] = { { 0, 0 }, { 0, 0 }, { 0, 0 },
444@@ -631,11 +635,14 @@
445
446 static void 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. Dazed and confused, but trying "
452 "to continue\n");
453 printk(KERN_EMERG "You probably have a hardware problem with your RAM "
454 "chips\n");
455-
456+#endif
457 /* Clear and disable the memory parity error line. */
458 clear_mem_error(reason);
459 }
460diff -Naur linux-2.6.18.2.orig/drivers/Kconfig linux-2.6.18.2/drivers/Kconfig
461--- linux-2.6.18.2.orig/drivers/Kconfig 2006-11-03 17:33:58.000000000 -0800
462+++ linux-2.6.18.2/drivers/Kconfig 2006-11-15 21:20:19.734033452 -0800
463@@ -74,4 +74,6 @@
464
465 source "drivers/dma/Kconfig"
466
467+source "drivers/cobalt/Kconfig"
468+
469 endmenu
470diff -Naur linux-2.6.18.2.orig/drivers/Makefile linux-2.6.18.2/drivers/Makefile
471--- linux-2.6.18.2.orig/drivers/Makefile 2006-11-03 17:33:58.000000000 -0800
472+++ linux-2.6.18.2/drivers/Makefile 2006-11-15 21:20:19.734033452 -0800
473@@ -65,6 +65,8 @@
474 obj-$(CONFIG_EDAC) += edac/
475 obj-$(CONFIG_MCA) += mca/
476 obj-$(CONFIG_EISA) += eisa/
477+obj-$(CONFIG_COBALT_RAQ) += cobalt/
478+
479 obj-$(CONFIG_CPU_FREQ) += cpufreq/
480 obj-$(CONFIG_MMC) += mmc/
481 obj-$(CONFIG_NEW_LEDS) += leds/
482diff -Naur linux-2.6.18.2.orig/drivers/char/Kconfig linux-2.6.18.2/drivers/char/Kconfig
483--- linux-2.6.18.2.orig/drivers/char/Kconfig 2006-11-03 17:33:58.000000000 -0800
484+++ linux-2.6.18.2/drivers/char/Kconfig 2006-11-15 21:20:19.734033452 -0800
485@@ -809,7 +809,7 @@
486 Samsung S3C2410. This can provide periodic interrupt rates
487 from 1Hz to 64Hz for user programs, and wakeup from Alarm.
488
489-config COBALT_LCD
490+config COBALT_MIPS_LCD
491 bool "Support for Cobalt LCD"
492 depends on MIPS_COBALT
493 help
494diff -Naur linux-2.6.18.2.orig/drivers/char/Makefile linux-2.6.18.2/drivers/char/Makefile
495--- linux-2.6.18.2.orig/drivers/char/Makefile 2006-11-03 17:33:58.000000000 -0800
496+++ linux-2.6.18.2/drivers/char/Makefile 2006-11-15 21:20:19.734033452 -0800
497@@ -77,7 +77,7 @@
498 obj-$(CONFIG_DS1620) += ds1620.o
499 obj-$(CONFIG_HW_RANDOM) += hw_random/
500 obj-$(CONFIG_FTAPE) += ftape/
501-obj-$(CONFIG_COBALT_LCD) += lcd.o
502+obj-$(CONFIG_COBALT_MIPS_LCD) += lcd.o
503 obj-$(CONFIG_PPDEV) += ppdev.o
504 obj-$(CONFIG_NWBUTTON) += nwbutton.o
505 obj-$(CONFIG_NWFLASH) += nwflash.o
506diff -Naur linux-2.6.18.2.orig/drivers/char/misc.c linux-2.6.18.2/drivers/char/misc.c
507--- linux-2.6.18.2.orig/drivers/char/misc.c 2006-11-03 17:33:58.000000000 -0800
508+++ linux-2.6.18.2/drivers/char/misc.c 2006-11-15 21:20:19.734033452 -0800
509@@ -49,6 +49,17 @@
510 #include <linux/tty.h>
511 #include <linux/kmod.h>
512
513+#ifdef CONFIG_COBALT_RAQ
514+#include <cobalt/cobalt.h>
515+#include <cobalt/systype.h>
516+#include <cobalt/superio.h>
517+#include <cobalt/serialnum.h>
518+#include <cobalt/i2c.h>
519+#include <cobalt/misc.h>
520+#include <cobalt/lcd.h>
521+#endif
522+
523+
524 /*
525 * Head entry for the doubly linked miscdevice list
526 */
527@@ -63,6 +74,13 @@
528
529 extern int pmu_device_init(void);
530
531+#ifdef CONFIG_COBALT_RAQ
532+extern int cobalt_init(void);
533+#endif
534+#ifdef CONFIG_COBALT_MIPS_LCD
535+module_init(lcd_init);
536+#endif
537+
538 #ifdef CONFIG_PROC_FS
539 static void *misc_seq_start(struct seq_file *seq, loff_t *pos)
540 {
541diff -Naur linux-2.6.18.2.orig/drivers/char/nvram.c linux-2.6.18.2/drivers/char/nvram.c
542--- linux-2.6.18.2.orig/drivers/char/nvram.c 2006-11-03 17:33:58.000000000 -0800
543+++ linux-2.6.18.2/drivers/char/nvram.c 2006-11-15 21:20:19.734033452 -0800
544@@ -49,8 +49,7 @@
545 #if defined(CONFIG_ATARI)
546 # define MACH ATARI
547 #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) /* and others?? */
548-#define MACH PC
549-# if defined(CONFIG_COBALT)
550+# if defined(CONFIG_COBALT_RAQ)
551 # include <linux/cobalt-nvram.h>
552 # define MACH COBALT
553 # else
554diff -Naur linux-2.6.18.2.orig/drivers/cobalt/Kconfig linux-2.6.18.2/drivers/cobalt/Kconfig
555--- linux-2.6.18.2.orig/drivers/cobalt/Kconfig 1969-12-31 16:00:00.000000000 -0800
556+++ linux-2.6.18.2/drivers/cobalt/Kconfig 2006-11-15 21:20:19.734033452 -0800
557@@ -0,0 +1,133 @@
558+#
559+# Cobalt Drivers
560+#
561+
562+menu "Cobalt RaQ/Qube Hardware"
563+
564+config COBALT_RAQ
565+ bool "Cobalt RaQ/Qube Hardware Support"
566+ select INPUT
567+ default n
568+ ---help---
569+ NOTE: This support is for x86 Cobalts, not MIPS versions
570+
571+ If you have a Gen III or Gen V Cobalt RaQ/Qube machine, it's probably
572+ a good idea to say Y here and choose from the options below.
573+
574+config COBALT_GEN_III
575+ bool "Gen III (3000 series) system support"
576+ depends on COBALT_RAQ
577+ default y
578+ ---help---
579+ If you have one of the following Gen III Cobalt systems, say Y here.
580+ Otherwise, it's best to say N.
581+
582+ - RaQ 3
583+ - RaQ 4
584+ - Qube3
585+
586+config COBALT_GEN_V
587+ bool "Gen V (5000 series) system support"
588+ depends on COBALT_RAQ
589+ default n
590+ ---help---
591+ If you have one of the following Gen V Cobalt systems, say Y here.
592+ Otherwise, it's best to say N.
593+
594+ - RaQ XTR
595+ - RaQ550
596+
597+config COBALT_OLDPROC
598+ bool "Create legacy /proc files"
599+ depends on COBALT_RAQ
600+ default y
601+ ---help---
602+ Creates entries in /proc/cobalt which provide useful information about
603+ your RaQ/Qube. Best to say Y here.
604+
605+menu "Cobalt Hardware Options"
606+ depends on COBALT_RAQ
607+
608+ config COBALT_LCD
609+ bool "Front panel LCD support"
610+ default y
611+ ---help---
612+ Handles support for the front panel LCD screen and buttons.
613+
614+ config COBALT_LCD_TWIDDLE
615+ bool "Twiddle LCD on boot"
616+ depends on COBALT_LCD
617+ default y
618+ ---help---
619+ Gives you a nice little twiddle on the LCD while booting.
620+
621+ config COBALT_LED
622+ bool "Software controlled LED support"
623+ default y
624+ ---help---
625+ Allows software to play with the LEDs on the front of the
626+ system.
627+
628+ config COBALT_SERNUM
629+ tristate "Serial number support"
630+ depends on COBALT_OLDPROC
631+ default y
632+ ---help---
633+ Allows you to retrieve the system's serial number via a /proc
634+ entry.
635+
636+ config COBALT_WDT
637+ bool "Watchdog timer support"
638+ depends on WATCHDOG
639+ default y
640+ ---help---
641+ w00f?
642+
643+ config COBALT_SENSORS
644+ bool "System sensors support"
645+ depends on COBALT_OLDPROC
646+ default y
647+ ---help---
648+ Allows you to retrieve system temperatures via /proc entries.
649+
650+ config COBALT_FANS
651+ tristate "Fan tachometer support"
652+ depends on COBALT_OLDPROC
653+ depends on COBALT_GEN_V
654+ default y
655+ ---help---
656+ Allows you to retrieve fan speeds via /proc entries.
657+
658+ config COBALT_RAMINFO
659+ tristate "Memory information support"
660+ depends on COBALT_OLDPROC
661+ default y
662+ ---help---
663+ Got DIMMs? This will tell you how much and in which slot via a
664+ /proc entry.
665+
666+ config COBALT_RULER
667+ bool "Disk drive ruler support"
668+ depends on COBALT_OLDPROC
669+ depends on COBALT_GEN_V
670+ default y
671+ ---help---
672+ Not sure what this does... A purple tape measure maybe?
673+
674+ config COBALT_ACPI
675+ bool "Cobalt ACPI support"
676+ depends on COBALT_GEN_V
677+ default y
678+ ---help---
679+ ACPI support for the Generation V Cobalts.
680+
681+ config COBALT_EMU_ACPI
682+ bool "/proc/acpi emulation"
683+ depends on COBALT_ACPI
684+ default y
685+ ---help---
686+ Emulates the /proc/acpi interface.
687+
688+endmenu
689+
690+endmenu
691diff -Naur linux-2.6.18.2.orig/drivers/cobalt/Makefile linux-2.6.18.2/drivers/cobalt/Makefile
692--- linux-2.6.18.2.orig/drivers/cobalt/Makefile 1969-12-31 16:00:00.000000000 -0800
693+++ linux-2.6.18.2/drivers/cobalt/Makefile 2006-11-15 21:20:19.734033452 -0800
694@@ -0,0 +1,18 @@
695+#
696+# Makefile for the Sun/Cobalt device drivers
697+#
698+
699+#O_TARGET := cobalt.o
700+
701+#export-objs := init.o systype.o wdt.o i2c.o
702+
703+obj-$(CONFIG_COBALT_RAQ) += init.o systype.o i2c.o wdt.o
704+obj-$(CONFIG_COBALT_ACPI) += acpi.o
705+obj-$(CONFIG_COBALT_SERNUM) += serialnum.o
706+obj-$(CONFIG_COBALT_LCD) += lcd.o
707+obj-$(CONFIG_COBALT_LED) += net.o led.o
708+obj-$(CONFIG_COBALT_SENSORS) += sensors.o
709+obj-$(CONFIG_COBALT_FANS) += fans.o
710+obj-$(CONFIG_COBALT_RAMINFO) += raminfo.o
711+obj-$(CONFIG_COBALT_RULER) += ruler.o
712+
713diff -Naur linux-2.6.18.2.orig/drivers/cobalt/README linux-2.6.18.2/drivers/cobalt/README
714--- linux-2.6.18.2.orig/drivers/cobalt/README 1969-12-31 16:00:00.000000000 -0800
715+++ linux-2.6.18.2/drivers/cobalt/README 2006-11-15 21:20:19.734033452 -0800
716@@ -0,0 +1,19 @@
717+Notes on Cobalt's drivers:
718+
719+You will notice in several places constructs such as this:
720+
721+ if (cobt_is_3k()) {
722+ foo();
723+ } else if (cobt_is_5k()) {
724+ bar();
725+ }
726+
727+The goal here is to only compile in code that is needed, but to allow one to
728+define support for both 3k and 5k (and more?) style systems. The systype
729+check macros are very simple and clean. They check whether config-time
730+support for the generation has been enabled, and (if so) whether the current
731+systype matches the spcified generation. This leaves the code free from
732+#ifdef cruft, but lets the compiler throw out unsupported generation-specific
733+code with if (0) detection.
734+
735+--
736diff -Naur linux-2.6.18.2.orig/drivers/cobalt/acpi.c linux-2.6.18.2/drivers/cobalt/acpi.c
737--- linux-2.6.18.2.orig/drivers/cobalt/acpi.c 1969-12-31 16:00:00.000000000 -0800
738+++ linux-2.6.18.2/drivers/cobalt/acpi.c 2006-11-15 21:20:19.734033452 -0800
739@@ -0,0 +1,1994 @@
740+ /*
741+ * cobalt acpi driver
742+ * Copyright (c) 2000, Cobalt Networks, Inc.
743+ * Copyright (c) 2001, Sun Microsystems, Inc.
744+ * $Id: acpi.c,v 1.32 2002/06/26 19:08:54 duncan Exp $
745+ *
746+ * author: asun@cobalt.com, thockin@sun.com
747+ * modified by: jeff@404ster.com
748+ *
749+ * this driver just sets stuff up for ACPI interrupts
750+ *
751+ * if acpi support really existed in the kernel, we would read
752+ * data from the ACPI tables. however, it doesn't. as a result,
753+ * we use some hardcoded values.
754+ *
755+ * This should be SMP safe. The only data that needs protection is the acpi
756+ * handler list. It gets scanned at timer-interrupts, must use
757+ * irqsave/restore locks. Read/write locks would be useful if there were any
758+ * other times that the list was read but never written. --TPH
759+ *
760+ * /proc/acpi emulation emulates the /proc/acpi/events interface supplied by
761+ * the INTEL acpi drivers. A lot of the code to handle it has been adapted
762+ * from there.
763+ */
764+
765+#include <stdarg.h>
766+#include <stddef.h>
767+#include <linux/init.h>
768+#include <linux/sched.h>
769+#include <linux/config.h>
770+#include <linux/pci.h>
771+#include <linux/sched.h>
772+#include <linux/ioport.h>
773+#include <linux/delay.h>
774+#include <linux/spinlock.h>
775+#include <linux/proc_fs.h>
776+#include <linux/poll.h>
777+#include <linux/interrupt.h>
778+#include <asm/uaccess.h>
779+#include <asm/io.h>
780+#include <asm/irq.h>
781+
782+#include <cobalt/cobalt.h>
783+#include <cobalt/systype.h>
784+#include <cobalt/acpi.h>
785+#include <cobalt/superio.h>
786+
787+#define ACPI_DRIVER "Cobalt Networks ACPI driver"
788+#define ACPI_DRIVER_VMAJ 1
789+#define ACPI_DRIVER_VMIN 0
790+
791+#define POWER_BUTTON_SHUTDOWN 0
792+
793+#define ACPI_IRQ 10 /* XXX: hardcoded interrupt */
794+#define ACPI_NAME "sci"
795+#define ACPI_MAGIC 0xc0b7ac21
796+
797+#define SUPERIO_EVENT 0xff
798+#define OSB4_EVENT 0x40
799+#define OSB4_INDEX_PORT SERVERWORKS_ACPI_INDEX_PORT
800+#define OSB4_DATA_PORT SERVERWORKS_ACPI_DATA_PORT
801+
802+#define GEN_ACPI_TMR_STS (0x1 << 0)
803+#define GEN_ACPI_BM_STS (0x1 << 4)
804+#define GEN_ACPI_GBL_STS (0x1 << 5)
805+#define GEN_ACPI_PWRBTN_STS (0x1 << 8)
806+#define GEN_ACPI_SLPBTN_STS (0x1 << 9)
807+#define GEN_ACPI_RTC_STS (0x1 << 10)
808+#define GEN_ACPI_WAK_STS (0x1 << 15)
809+
810+#ifdef CONFIG_COBALT_EMU_ACPI
811+static int cobalt_acpi_setup_proc(void);
812+static int cobalt_acpi_open_event(struct inode *inode, struct file *file);
813+static int cobalt_acpi_close_event(struct inode *inode, struct file *file);
814+static ssize_t cobalt_acpi_read_event(struct file *file, char *buf,
815+ size_t count, loff_t *ppos);
816+static unsigned int cobalt_acpi_poll_event(struct file *file, poll_table *wait);
817+#endif
818+
819+
820+
821+typedef struct
822+{
823+ u16 hw_type;
824+ cobalt_acpi_hw_handler hw_handler;
825+ cobalt_acpi_enable_handler en_handler;
826+ void *data;
827+ struct list_head link;
828+} hw_handler_datum;
829+
830+typedef struct
831+{
832+ u16 hw_type;
833+ u16 table_len;
834+ u16 *table;
835+ struct list_head link;
836+} trans_table_datum;
837+
838+typedef struct
839+{
840+ cobalt_acpi_evt_handler handler;
841+ u16 ev_type;
842+ void *data;
843+ struct list_head link;
844+} evt_handler_datum;
845+
846+typedef struct
847+{
848+ cobalt_acpi_evt evt;
849+ struct list_head link;
850+} evt_list_datum;
851+
852+static LIST_HEAD( hw_handler_list );
853+static spinlock_t hw_handler_list_lock = SPIN_LOCK_UNLOCKED;
854+static LIST_HEAD( trans_table_list );
855+static spinlock_t trans_table_list_lock = SPIN_LOCK_UNLOCKED;
856+static LIST_HEAD( evt_handler_list );
857+static spinlock_t evt_handler_list_lock = SPIN_LOCK_UNLOCKED;
858+static LIST_HEAD( dispatch_queue );
859+static spinlock_t dispatch_queue_lock = SPIN_LOCK_UNLOCKED;
860+
861+typedef struct
862+{
863+ u16 hw_type;
864+
865+ /* block lengths */
866+ u16 pm1_evt_len;
867+ u16 pm1_cnt_len;
868+ u16 pm2_cnt_len;
869+ u16 pm_tmr_len;
870+ u16 gpe0_len;
871+ u16 gpe1_len;
872+
873+ /* block I/O locations */
874+ u16 pm1a_evt_blk;
875+ u16 pm1b_evt_blk;
876+ u16 pm1a_cnt_blk;
877+ u16 pm1b_cnt_blk;
878+ u16 pm2_cnt_blk;
879+ u16 pm_tmr_blk;
880+ u16 p_blk;
881+ u16 gpe0_blk;
882+ u16 gpe1_blk;
883+
884+ /* ponters to strings for the io names */
885+ char *pm1a_evt_nam;
886+ char *pm1b_evt_nam;
887+ char *pm1a_cnt_nam;
888+ char *pm1b_cnt_nam;
889+ char *pm2_cnt_nam;
890+ char *pm_tmr_nam;
891+ char *p_nam;
892+ char *gpe0_nam;
893+ char *gpe1_nam;
894+
895+ /* reference counts for events */
896+ atomic_t tmr_ref_cnt;
897+ atomic_t bm_ref_cnt;
898+ atomic_t gbl_ref_cnt;
899+ atomic_t pwrbtn_ref_cnt;
900+ atomic_t slpbtn_ref_cnt;
901+ atomic_t rtc_ref_cnt;
902+ atomic_t wak_ref_cnt;
903+ atomic_t *gpe_ref_cnt;
904+
905+
906+} generic_acpi_regions;
907+
908+
909+static void cobalt_acpi_enable_event( u16 ev_type, int en );
910+static void cobalt_acpi_run_enable_handler( u16 hw_type, u16 ev_type,
911+ u16 ev_data, int en);
912+static int cobalt_acpi_apply_evt_handlers( evt_list_datum *d );
913+static int cobalt_acpi_run_dispatch_queue( void );
914+static irqreturn_t acpi_interrupt(int irq, void *dev_id, struct pt_regs *regs);
915+static void cobalt_acpi_cleanup( void );
916+
917+static int register_acpi_regions( generic_acpi_regions *regions, char * subsys_name );
918+static int unregister_acpi_regions( generic_acpi_regions *regions );
919+static void cobalt_acpi_handle_pm1_blk( u16 io_addr, u16 len,
920+ generic_acpi_regions * regions );
921+static void cobalt_acpi_handle_gpe_blk( u16 io_addr, u16 len,
922+ generic_acpi_regions * regions );
923+static int cobalt_acpi_generic_hw_handler( int irq, void *dev_id,
924+ struct pt_regs *regs, void * data );
925+
926+static int cobalt_acpi_osb4_init( void );
927+static int cobalt_acpi_osb4_cleanup( void );
928+static int get_osb4_regions( generic_acpi_regions *regions);
929+
930+static int cobalt_acpi_csb5_init( void );
931+static int cobalt_acpi_csb5_cleanup( void );
932+static int get_csb5_regions( generic_acpi_regions *regions);
933+
934+static int cobalt_acpi_pc8731x_init( void );
935+static int cobalt_acpi_pc8731x_cleanup( void );
936+static int get_pc8731x_regions( generic_acpi_regions *regions );
937+
938+static int cobalt_acpi_pc8741x_init( void );
939+static int cobalt_acpi_pc8741x_cleanup( void );
940+static int get_pc8741x_regions( generic_acpi_regions *regions );
941+
942+static int cobalt_acpi_monterey_init( void );
943+static int cobalt_acpi_monterey_cleanup( void );
944+
945+static int cobalt_acpi_alpine_init( void );
946+static int cobalt_acpi_alpine_cleanup( void );
947+
948+static __inline__ struct list_head *list_pop( struct list_head *head )
949+{
950+ struct list_head *e;
951+
952+ if( list_empty( head ) )
953+ return NULL;
954+
955+ e = head->next;
956+ list_del( e );
957+ return e;
958+}
959+
960+static __inline__ u16 get_reg(u16 index, u16 data, u8 port)
961+{
962+ u16 reg;
963+
964+ outb(port, index);
965+ reg = inb(data);
966+ outb(port + 1, index);
967+ reg |= inb(data) << 8;
968+ return reg;
969+}
970+
971+/*
972+ *
973+ * Main ACPI Subsystem Code
974+ *
975+ */
976+
977+extern int cobalt_acpi_register_hw_handler( u16 hw_type,
978+ cobalt_acpi_hw_handler hw_handler,
979+ cobalt_acpi_enable_handler en_handler,
980+ void *data )
981+{
982+ hw_handler_datum *d;
983+ unsigned long flags;
984+
985+ if( ! (d = (hw_handler_datum *) kmalloc( sizeof( hw_handler_datum ), GFP_ATOMIC )) )
986+ return -ENOMEM;
987+
988+ d->hw_type = hw_type;
989+ d->hw_handler = hw_handler;
990+ d->en_handler = en_handler;
991+ d->data = data;
992+
993+ spin_lock_irqsave( &hw_handler_list_lock, flags );
994+ list_add( &(d->link), &hw_handler_list );
995+ spin_unlock_irqrestore( &hw_handler_list_lock, flags );
996+
997+ return 0;
998+}
999+
1000+extern int cobalt_acpi_unregister_hw_handler( cobalt_acpi_hw_handler handler )
1001+{
1002+ struct list_head *pos;
1003+ unsigned long flags;
1004+
1005+ spin_lock_irqsave( &hw_handler_list_lock, flags );
1006+ list_for_each( pos, &hw_handler_list )
1007+ {
1008+ if( list_entry( pos, hw_handler_datum, link )->hw_handler == handler )
1009+ {
1010+ list_del( pos );
1011+ spin_unlock_irqrestore( &hw_handler_list_lock, flags );
1012+
1013+ kfree( list_entry( pos, hw_handler_datum, link ) );
1014+ return 0;
1015+ }
1016+
1017+ };
1018+
1019+ spin_unlock_irqrestore( &hw_handler_list_lock, flags );
1020+ return -1;
1021+}
1022+
1023+extern int cobalt_acpi_register_trans_table( u16 hw_type, u16 table_len, u16 *table )
1024+{
1025+ trans_table_datum *d;
1026+ unsigned long flags;
1027+
1028+ if( ! (d = (trans_table_datum *) kmalloc( sizeof( trans_table_datum ), GFP_ATOMIC )) )
1029+ return -ENOMEM;
1030+
1031+ d->hw_type = hw_type;
1032+ d->table_len = table_len;
1033+ d->table = table;
1034+
1035+ spin_lock_irqsave( &trans_table_list_lock, flags );
1036+ list_add( &(d->link), &trans_table_list );
1037+ spin_unlock_irqrestore( &trans_table_list_lock, flags );
1038+
1039+ return 0;
1040+}
1041+
1042+extern int cobalt_acpi_unregister_trans_table( u16 hw_type )
1043+{
1044+ struct list_head *pos;
1045+ unsigned long flags;
1046+
1047+ spin_lock_irqsave( &trans_table_list_lock, flags );
1048+ list_for_each( pos, &trans_table_list )
1049+ {
1050+ if( list_entry( pos, trans_table_datum, link )->hw_type == hw_type )
1051+ {
1052+ list_del( pos );
1053+ spin_unlock_irqrestore( &trans_table_list_lock, flags );
1054+
1055+ kfree( list_entry( pos, trans_table_datum, link ) );
1056+ return 0;
1057+ }
1058+
1059+ };
1060+
1061+ spin_unlock_irqrestore( &trans_table_list_lock, flags );
1062+ return -1;
1063+}
1064+
1065+extern int cobalt_acpi_register_evt_handler( cobalt_acpi_evt_handler handler,
1066+ u16 ev_type,
1067+ void *data )
1068+{
1069+ evt_handler_datum *d;
1070+ unsigned long flags;
1071+
1072+ if( ! (d = (evt_handler_datum *) kmalloc( sizeof( evt_handler_datum ), GFP_ATOMIC )) )
1073+ return -ENOMEM;
1074+
1075+ d->handler = handler;
1076+ d->data = data;
1077+ d->ev_type = ev_type;
1078+
1079+ spin_lock_irqsave( &evt_handler_list_lock, flags );
1080+ list_add( &(d->link), &evt_handler_list );
1081+ spin_unlock_irqrestore( &evt_handler_list_lock, flags );
1082+
1083+ cobalt_acpi_enable_event( ev_type, 1 );
1084+
1085+ return 0;
1086+}
1087+
1088+extern int cobalt_acpi_unregister_evt_handler( cobalt_acpi_evt_handler handler )
1089+{
1090+ struct list_head *pos;
1091+ unsigned long flags;
1092+
1093+
1094+ spin_lock_irqsave( &evt_handler_list_lock, flags );
1095+ list_for_each( pos, &evt_handler_list )
1096+ {
1097+ if( list_entry( pos, evt_handler_datum, link )->handler == handler )
1098+ {
1099+ list_del( pos );
1100+ spin_unlock_irqrestore( &evt_handler_list_lock, flags );
1101+
1102+ cobalt_acpi_enable_event( list_entry( pos,
1103+ evt_handler_datum,
1104+ link )->ev_type, 0 );
1105+
1106+ kfree( list_entry( pos, evt_handler_datum, link ) );
1107+ return 0;
1108+ }
1109+
1110+ };
1111+
1112+ spin_unlock_irqrestore( &evt_handler_list_lock, flags );
1113+ return -EINVAL;
1114+}
1115+
1116+static void cobalt_acpi_enable_event( u16 ev_type, int en )
1117+{
1118+ if( ev_type >= 0x8000 )
1119+ {
1120+ struct list_head *pos;
1121+ trans_table_datum *d;
1122+ int i;
1123+ unsigned long flags;
1124+
1125+ spin_lock_irqsave( &trans_table_list_lock, flags );
1126+ list_for_each( pos, &trans_table_list )
1127+ {
1128+ d = list_entry( pos, trans_table_datum, link );
1129+ for( i=0 ; i<d->table_len ; i++ )
1130+ {
1131+ if( d->table[i] == ev_type )
1132+ {
1133+ cobalt_acpi_run_enable_handler( d->hw_type,
1134+ COBALT_ACPI_EVT_GPE,
1135+ i, en );
1136+ }
1137+ }
1138+ }
1139+ spin_unlock_irqrestore( &trans_table_list_lock, flags );
1140+ }
1141+ else
1142+ cobalt_acpi_run_enable_handler( COBALT_ACPI_HW_ANY, ev_type, 0, en);
1143+}
1144+
1145+static void cobalt_acpi_run_enable_handler( u16 hw_type, u16 ev_type,
1146+ u16 ev_data, int en)
1147+{
1148+ struct list_head *pos;
1149+ unsigned long flags;
1150+ hw_handler_datum *d;
1151+
1152+ spin_lock_irqsave(&hw_handler_list_lock, flags);
1153+ list_for_each( pos, &hw_handler_list )
1154+ {
1155+ d = list_entry( pos, hw_handler_datum, link );
1156+ if( (!hw_type) || (d->hw_type == hw_type) )
1157+ d->en_handler( ev_type, ev_data, en, d->data );
1158+ }
1159+ spin_unlock_irqrestore(&hw_handler_list_lock, flags);
1160+
1161+}
1162+
1163+static int cobalt_acpi_translate_event( cobalt_acpi_evt *evt )
1164+{
1165+ struct list_head *pos;
1166+ unsigned long flags;
1167+ trans_table_datum *d;
1168+
1169+ if( evt->ev_type != COBALT_ACPI_EVT_GPE )
1170+ return 0;
1171+
1172+ spin_lock_irqsave( &trans_table_list_lock, flags );
1173+ list_for_each( pos, &trans_table_list )
1174+ {
1175+ d = list_entry( pos, trans_table_datum, link );
1176+ if( d->hw_type == evt->hw_type )
1177+ {
1178+ if( evt->ev_data >= d->table_len )
1179+ goto err_out;
1180+
1181+ if( d->table[ evt->ev_data ] != COBALT_ACPI_EVT_NONE )
1182+ {
1183+ evt->ev_type = d->table[ evt->ev_data ];
1184+ evt->ev_data = 0;
1185+ }
1186+
1187+ spin_unlock_irqrestore( &trans_table_list_lock, flags );
1188+ return 0;
1189+ }
1190+ }
1191+
1192+ err_out:
1193+ spin_unlock_irqrestore( &trans_table_list_lock, flags );
1194+ return -1;
1195+}
1196+
1197+extern int cobalt_acpi_post_event( cobalt_acpi_evt evt )
1198+{
1199+ evt_list_datum *d;
1200+ unsigned long flags;
1201+
1202+ if( ! (d = (evt_list_datum *) kmalloc( sizeof( evt_handler_datum ), GFP_ATOMIC )) )
1203+ return -ENOMEM;
1204+
1205+
1206+ cobalt_acpi_translate_event( &evt );
1207+
1208+ memcpy( &(d->evt), &evt, sizeof(evt) );
1209+
1210+ spin_lock_irqsave( &dispatch_queue_lock, flags );
1211+ list_add_tail( &(d->link), &dispatch_queue );
1212+ spin_unlock_irqrestore( &dispatch_queue_lock, flags );
1213+
1214+ return 0;
1215+}
1216+
1217+static int cobalt_acpi_apply_evt_handlers( evt_list_datum *d )
1218+{
1219+ struct list_head *pos;
1220+ evt_handler_datum *evt_h;
1221+ int ret,err = 0;
1222+ unsigned long flags;
1223+
1224+ spin_lock_irqsave( &evt_handler_list_lock, flags );
1225+ list_for_each( pos, &evt_handler_list )
1226+ {
1227+ evt_h = list_entry( pos, evt_handler_datum, link );
1228+ if( (! evt_h->ev_type) || (evt_h->ev_type == d->evt.ev_type) )
1229+ {
1230+ if( (ret = evt_h->handler( &d->evt, evt_h->data )) < 0 )
1231+ err = ret;
1232+ }
1233+ }
1234+ spin_unlock_irqrestore( &evt_handler_list_lock, flags );
1235+
1236+ return err;
1237+}
1238+
1239+static int cobalt_acpi_run_dispatch_queue( void )
1240+{
1241+ struct list_head *pos;
1242+ int ret;
1243+ int err=0;
1244+ evt_list_datum *d;
1245+ unsigned long flags;
1246+
1247+ spin_lock_irqsave( &dispatch_queue_lock, flags );
1248+ while( (pos = list_pop( &dispatch_queue )) )
1249+ {
1250+ d = list_entry( pos, evt_list_datum, link );
1251+ if( (ret = cobalt_acpi_apply_evt_handlers( d )) < 0 )
1252+ err = ret;
1253+#ifdef CONFIG_COBALT_EMU_ACPI
1254+ cobalt_acpi_generate_proc_evt( &d->evt );
1255+#endif
1256+ kfree( d );
1257+ }
1258+ spin_unlock_irqrestore( &dispatch_queue_lock, flags );
1259+
1260+ return err;
1261+}
1262+
1263+static irqreturn_t acpi_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1264+{
1265+ struct list_head *pos;
1266+ hw_handler_datum *d;
1267+ int ret=0, err=0;
1268+ unsigned long flags;
1269+
1270+ spin_lock_irqsave(&hw_handler_list_lock, flags);
1271+ list_for_each( pos, &hw_handler_list )
1272+ {
1273+ d = list_entry( pos, hw_handler_datum, link );
1274+ if( (ret = d->hw_handler( irq, dev_id, regs, d->data )) < 0 )
1275+ err = ret;
1276+
1277+ }
1278+ spin_unlock_irqrestore(&hw_handler_list_lock, flags);
1279+
1280+ if( (err = cobalt_acpi_run_dispatch_queue()) < 0 )
1281+ err = ret;
1282+
1283+ if( err )
1284+ EPRINTK( "error at interrupt time of type %d.\n", err );
1285+
1286+ return IRQ_HANDLED;
1287+}
1288+
1289+
1290+
1291+
1292+int __init cobalt_acpi_init(void)
1293+{
1294+ int err;
1295+
1296+ printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", ACPI_DRIVER,ACPI_DRIVER_VMAJ,ACPI_DRIVER_VMIN);
1297+
1298+ if( cobt_is_monterey() )
1299+ cobalt_acpi_monterey_init();
1300+ else if( cobt_is_alpine() )
1301+ cobalt_acpi_alpine_init();
1302+
1303+ if( cobt_is_5k() )
1304+ {
1305+ if( pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
1306+ PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL ) )
1307+ {
1308+ if( (err = cobalt_acpi_osb4_init()) < 0 )
1309+ {
1310+ goto cleanup;
1311+ }
1312+ }
1313+
1314+ if( pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
1315+ PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL ) )
1316+ {
1317+ if( (err = cobalt_acpi_csb5_init()) < 0 )
1318+ {
1319+ goto cleanup;
1320+ }
1321+ }
1322+
1323+ switch( superio_type() )
1324+ {
1325+ case SIO_TYPE_PC8731X:
1326+ if( (err = cobalt_acpi_pc8731x_init()) )
1327+ {
1328+ goto cleanup;
1329+ }
1330+ break;
1331+
1332+ case SIO_TYPE_PC8741X:
1333+ if( (err = cobalt_acpi_pc8741x_init()) )
1334+ {
1335+ goto cleanup;
1336+ }
1337+ break;
1338+
1339+ case SIO_TYPE_UNKNOWN:
1340+ EPRINTK("unknown superio type\n");
1341+ break;
1342+ }
1343+
1344+ /* setup an interrupt handler for an ACPI SCI */
1345+ err = request_irq(ACPI_IRQ, acpi_interrupt,
1346+ SA_SHIRQ, ACPI_NAME, (void *)ACPI_MAGIC);
1347+ if (err) {
1348+ EPRINTK("can't assign ACPI IRQ (%d)\n", ACPI_IRQ);
1349+ return err;
1350+ }
1351+
1352+#ifdef CONFIG_COBALT_EMU_ACPI
1353+ cobalt_acpi_setup_proc();
1354+#endif
1355+ }
1356+
1357+ /* enable some events we may want */
1358+ cobalt_acpi_enable_event( COBALT_ACPI_EVT_PWRBTN, 1 );
1359+
1360+ return 0;
1361+
1362+ cleanup:
1363+ cobalt_acpi_cleanup();
1364+ return err;
1365+}
1366+
1367+static void cobalt_acpi_cleanup( void )
1368+{
1369+ cobalt_acpi_osb4_cleanup();
1370+ cobalt_acpi_csb5_cleanup();
1371+ cobalt_acpi_pc8731x_cleanup();
1372+ cobalt_acpi_pc8741x_cleanup();
1373+
1374+ if( cobt_is_monterey() )
1375+ cobalt_acpi_monterey_cleanup();
1376+ if( cobt_is_alpine() )
1377+ cobalt_acpi_alpine_cleanup();
1378+}
1379+
1380+/*
1381+ *
1382+ * Generic ACPI HW Support
1383+ *
1384+ */
1385+
1386+static __inline__ char *region_name( char * subsys_name, char * blk_name )
1387+{
1388+ char * new_name;
1389+
1390+ if( !( new_name = (char *) kmalloc( strlen(subsys_name) + strlen(blk_name) + 14,
1391+ GFP_ATOMIC)) )
1392+ return NULL;
1393+
1394+ sprintf( new_name, "%s (%s)", subsys_name, blk_name );
1395+ return new_name;
1396+}
1397+
1398+static void free_region_names( generic_acpi_regions *regions )
1399+{
1400+ if( regions->pm1a_evt_nam )
1401+ kfree( regions->pm1a_evt_nam );
1402+
1403+ if( regions->pm1b_evt_nam )
1404+ kfree( regions->pm1b_evt_nam );
1405+
1406+ if( regions->pm1a_cnt_nam )
1407+ kfree( regions->pm1a_cnt_nam );
1408+
1409+ if( regions->pm1b_cnt_nam )
1410+ kfree( regions->pm1b_cnt_nam );
1411+
1412+ if( regions->pm2_cnt_nam )
1413+ kfree( regions->pm2_cnt_nam );
1414+
1415+ if( regions->pm_tmr_nam )
1416+ kfree( regions->pm_tmr_nam );
1417+
1418+ if( regions->p_nam )
1419+ kfree( regions->p_nam );
1420+
1421+ if( regions->gpe0_nam )
1422+ kfree( regions->gpe0_nam );
1423+
1424+ if( regions->gpe1_nam )
1425+ kfree( regions->gpe1_nam );
1426+}
1427+
1428+static int register_acpi_regions( generic_acpi_regions *regions, char * subsys_name )
1429+{
1430+ int i;
1431+
1432+ if( regions->pm1a_evt_blk && regions->pm1_evt_len )
1433+ {
1434+ if( !(regions->pm1a_evt_nam = region_name( subsys_name, "pm1a_evt_blk" )) )
1435+ goto cleanup0;
1436+
1437+ if( !request_region( regions->pm1a_evt_blk, regions->pm1_evt_len,
1438+ regions->pm1a_evt_nam ) )
1439+ goto cleanup0;
1440+ }
1441+
1442+ if( regions->pm1b_evt_blk && regions->pm1_evt_len )
1443+ {
1444+ if( !(regions->pm1b_evt_nam = region_name( subsys_name, "pm1b_evt_blk" )) )
1445+ goto cleanup0;
1446+
1447+ if( !request_region( regions->pm1b_evt_blk, regions->pm1_evt_len,
1448+ regions->pm1b_evt_nam) )
1449+ goto cleanup1;
1450+ }
1451+
1452+ if( regions->pm1a_cnt_blk && regions->pm1_cnt_len )
1453+ {
1454+ if( !(regions->pm1a_cnt_nam = region_name( subsys_name, "pm1a_cnt_blk" )) )
1455+ goto cleanup1;
1456+
1457+ if( !request_region( regions->pm1a_cnt_blk, regions->pm1_cnt_len,
1458+ regions->pm1a_cnt_nam ) )
1459+ goto cleanup2;
1460+ }
1461+
1462+ if( regions->pm1b_cnt_blk && regions->pm1_cnt_len )
1463+ {
1464+ if( !(regions->pm1b_cnt_nam = region_name( subsys_name, "pm1b_cnt_blk" )) )
1465+ goto cleanup2;
1466+
1467+ if( !request_region( regions->pm1b_cnt_blk, regions->pm1_cnt_len,
1468+ regions->pm1b_cnt_nam ) )
1469+ goto cleanup3;
1470+ }
1471+
1472+ if( regions->pm2_cnt_blk && regions->pm2_cnt_len )
1473+ {
1474+ if( !(regions->pm2_cnt_nam = region_name( subsys_name, "pm2_cnt_blk" )) )
1475+ goto cleanup3;
1476+
1477+ if( !request_region( regions->pm2_cnt_blk, regions->pm2_cnt_len,
1478+ regions->pm2_cnt_nam ) )
1479+ goto cleanup4;
1480+ }
1481+
1482+ if( regions->pm_tmr_blk && regions->pm_tmr_len )
1483+ {
1484+ if( !(regions->pm_tmr_nam = region_name( subsys_name, "pm_tmp_blk" )) )
1485+ goto cleanup4;
1486+
1487+ if( !request_region( regions->pm_tmr_blk, regions->pm_tmr_len,
1488+ regions->pm_tmr_nam ) )
1489+ goto cleanup5;
1490+ }
1491+
1492+ if( regions->p_blk )
1493+ {
1494+ if( !(regions->p_nam = region_name( subsys_name, "p_blk" )) )
1495+ goto cleanup5;
1496+
1497+ if( !request_region( regions->p_blk, 6, regions->p_nam ) )
1498+ goto cleanup6;
1499+ }
1500+
1501+ if( regions->gpe0_blk && regions->gpe0_len )
1502+ {
1503+ if( !(regions->gpe0_nam = region_name( subsys_name, "gpe0_blk" )) )
1504+ goto cleanup6;
1505+
1506+ if( !request_region( regions->gpe0_blk, regions->gpe0_len,
1507+ regions->gpe0_nam ) )
1508+ goto cleanup7;
1509+ }
1510+
1511+ if( regions->gpe1_blk && regions->gpe1_len )
1512+ {
1513+ if( !(regions->gpe1_nam = region_name( subsys_name, "gpe1_blk" )) )
1514+ goto cleanup7;
1515+
1516+ if( !request_region( regions->gpe1_blk, regions->gpe1_len,
1517+ regions->gpe1_nam ) )
1518+ goto cleanup8;
1519+ }
1520+
1521+ if( (regions->gpe_ref_cnt = (atomic_t *) kmalloc( sizeof( atomic_t ) *
1522+ regions->gpe0_len * 8,
1523+ GFP_ATOMIC)) == NULL )
1524+ goto cleanup9;
1525+
1526+ memset( regions->gpe_ref_cnt, 0x0, sizeof( atomic_t ) * regions->gpe0_len * 8 );
1527+
1528+ /* disable all events and ack them */
1529+ if( regions->pm1a_evt_blk )
1530+ {
1531+ outw( 0x0000, regions->pm1a_evt_blk + regions->pm1_evt_len/2 );
1532+ outw( 0xffff, regions->pm1a_evt_blk );
1533+ }
1534+
1535+ if( regions->pm1b_evt_blk )
1536+ {
1537+ outw( 0x0000, regions->pm1b_evt_blk + regions->pm1_evt_len/2 );
1538+ outw( 0xffff, regions->pm1b_evt_blk );
1539+ }
1540+
1541+ if( regions->gpe0_blk )
1542+ {
1543+ for( i=0 ; i<(regions->gpe0_len/2) ; i++ )
1544+ {
1545+ outb( 0x00, regions->gpe0_blk + regions->gpe0_len/2 + i );
1546+ outb( 0xff, regions->gpe0_blk + i );
1547+ }
1548+ }
1549+
1550+ if( regions->gpe1_blk )
1551+ {
1552+ for( i=0 ; i<(regions->gpe1_len/2) ; i++ )
1553+ {
1554+ outb( 0x00, regions->gpe1_blk + regions->gpe1_len/2 + i );
1555+ outb( 0xff, regions->gpe1_blk + i );
1556+ }
1557+ }
1558+
1559+ return 0;
1560+
1561+ cleanup9:
1562+ if( regions->gpe1_blk )
1563+ {
1564+ release_region( regions->gpe1_blk, regions->gpe1_len );
1565+ regions->gpe1_blk = 0;
1566+ }
1567+
1568+ cleanup8:
1569+ if( regions->gpe0_blk )
1570+ {
1571+ release_region( regions->gpe0_blk, regions->gpe0_len );
1572+ regions->gpe0_blk = 0;
1573+ }
1574+
1575+ cleanup7:
1576+ if( regions->p_blk )
1577+ {
1578+ release_region( regions->p_blk, 6 );
1579+ regions->p_blk = 0;
1580+ }
1581+
1582+ cleanup6:
1583+ if( regions->pm_tmr_blk )
1584+ {
1585+ release_region( regions->pm_tmr_blk, regions->pm_tmr_len );
1586+ regions->pm_tmr_blk = 0;
1587+ }
1588+
1589+ cleanup5:
1590+ if( regions->pm2_cnt_blk )
1591+ {
1592+ release_region( regions->pm2_cnt_blk, regions->pm2_cnt_len );
1593+ regions->pm2_cnt_blk = 0;
1594+ }
1595+
1596+ cleanup4:
1597+ if( regions->pm1b_cnt_blk )
1598+ {
1599+ release_region( regions->pm1b_cnt_blk, regions->pm1_cnt_len );
1600+ regions->pm1b_cnt_blk = 0;
1601+ }
1602+
1603+ cleanup3:
1604+ if( regions->pm1a_cnt_blk )
1605+ {
1606+ release_region( regions->pm1a_cnt_blk, regions->pm1_cnt_len );
1607+ regions->pm1a_cnt_blk = 0;
1608+ }
1609+
1610+ cleanup2:
1611+ if( regions->pm1b_evt_blk )
1612+ {
1613+ release_region( regions->pm1b_evt_blk, regions->pm1_evt_len );
1614+ regions->pm1b_evt_blk = 0;
1615+ }
1616+
1617+ cleanup1:
1618+ if( regions->pm1a_evt_blk )
1619+ {
1620+ release_region( regions->pm1a_evt_blk, regions->pm1_evt_len );
1621+ regions->pm1a_evt_blk = 0;
1622+ }
1623+
1624+ cleanup0:
1625+ free_region_names( regions );
1626+
1627+ return -EBUSY;
1628+}
1629+
1630+static int unregister_acpi_regions( generic_acpi_regions *regions )
1631+{
1632+ if( regions->pm1a_evt_blk && regions->pm1_evt_len )
1633+ {
1634+ release_region( regions->pm1a_evt_blk, regions->pm1_evt_len );
1635+ regions->pm1a_evt_blk = 0;
1636+ }
1637+
1638+ if( regions->pm1b_evt_blk && regions->pm1_evt_len )
1639+ {
1640+ release_region( regions->pm1b_evt_blk, regions->pm1_evt_len );
1641+ regions->pm1b_evt_blk = 0;
1642+ }
1643+
1644+ if( regions->pm1a_cnt_blk && regions->pm1_cnt_len )
1645+ {
1646+ release_region( regions->pm1a_cnt_blk, regions->pm1_cnt_len );
1647+ regions->pm1a_cnt_blk = 0;
1648+ }
1649+
1650+ if( regions->pm1b_cnt_blk && regions->pm1_cnt_len )
1651+ {
1652+ release_region( regions->pm1b_cnt_blk, regions->pm1_cnt_len );
1653+ regions->pm1b_cnt_blk = 0;
1654+ }
1655+
1656+ if( regions->pm2_cnt_blk && regions->pm2_cnt_len )
1657+ {
1658+ release_region( regions->pm2_cnt_blk, regions->pm2_cnt_len );
1659+ regions->pm2_cnt_blk = 0;
1660+ }
1661+
1662+ if( regions->pm_tmr_blk && regions->pm_tmr_len )
1663+ {
1664+ release_region( regions->pm_tmr_blk, regions->pm_tmr_len );
1665+ regions->pm_tmr_blk = 0;
1666+ }
1667+
1668+ if( regions->p_blk )
1669+ {
1670+ release_region( regions->p_blk, 6 );
1671+ regions->p_blk = 0;
1672+ }
1673+
1674+ if( regions->gpe0_blk && regions->gpe0_len )
1675+ {
1676+ release_region( regions->gpe0_blk, regions->gpe0_len );
1677+ regions->gpe0_blk = 0;
1678+ }
1679+
1680+ if( regions->gpe1_blk && regions->gpe1_len )
1681+ {
1682+ release_region( regions->gpe1_blk, regions->gpe1_len );
1683+ regions->gpe1_blk = 0;
1684+ }
1685+
1686+ if( regions->gpe_ref_cnt )
1687+ kfree( regions->gpe_ref_cnt );
1688+
1689+ free_region_names( regions );
1690+
1691+ return 0;
1692+}
1693+
1694+static void cobalt_acpi_handle_pm1_blk( u16 io_addr, u16 len,
1695+ generic_acpi_regions * regions )
1696+{
1697+ cobalt_acpi_evt evt;
1698+ u16 sts, en;
1699+
1700+ evt.hw_type = regions->hw_type;
1701+
1702+ if( (sts = inw( io_addr )) &&
1703+ (en = inw( io_addr + len/2 )) )
1704+ {
1705+
1706+
1707+ /* clear status bits */
1708+ outw( sts, io_addr);
1709+
1710+ if( (en & GEN_ACPI_TMR_STS) &&
1711+ (sts & GEN_ACPI_TMR_STS) )
1712+ {
1713+ evt.ev_type = COBALT_ACPI_EVT_TMR;
1714+ evt.ev_data = 0x0;
1715+ cobalt_acpi_post_event( evt );
1716+ }
1717+ if( (en & GEN_ACPI_BM_STS) &&
1718+ (sts & GEN_ACPI_BM_STS) )
1719+ {
1720+ evt.ev_type = COBALT_ACPI_EVT_BM;
1721+ evt.ev_data = 0x0;
1722+ cobalt_acpi_post_event( evt );
1723+ }
1724+ if( (en & GEN_ACPI_GBL_STS) &&
1725+ (sts & GEN_ACPI_GBL_STS) )
1726+ {
1727+ evt.ev_type = COBALT_ACPI_EVT_GBL;
1728+ evt.ev_data = 0x0;
1729+ cobalt_acpi_post_event( evt );
1730+ }
1731+ if( (en & GEN_ACPI_PWRBTN_STS) &&
1732+ (sts & GEN_ACPI_PWRBTN_STS) )
1733+ {
1734+ evt.ev_type = COBALT_ACPI_EVT_PWRBTN;
1735+ evt.ev_data = 0x0;
1736+ cobalt_acpi_post_event( evt );
1737+ }
1738+ if( (en & GEN_ACPI_SLPBTN_STS) &&
1739+ (sts & GEN_ACPI_SLPBTN_STS) )
1740+ {
1741+ evt.ev_type = COBALT_ACPI_EVT_SLPBTN;
1742+ evt.ev_data = 0x0;
1743+ cobalt_acpi_post_event( evt );
1744+ }
1745+ if( (en & GEN_ACPI_RTC_STS) &&
1746+ (sts & GEN_ACPI_RTC_STS) )
1747+ {
1748+ evt.ev_type = COBALT_ACPI_EVT_RTC;
1749+ evt.ev_data = 0x0;
1750+ cobalt_acpi_post_event( evt );
1751+ }
1752+ if( (sts & GEN_ACPI_WAK_STS) )
1753+ {
1754+ evt.ev_type = COBALT_ACPI_EVT_WAK;
1755+ evt.ev_data = 0x0;
1756+ cobalt_acpi_post_event( evt );
1757+ }
1758+ }
1759+}
1760+
1761+static void cobalt_acpi_handle_gpe_blk( u16 io_addr, u16 len,
1762+ generic_acpi_regions * regions )
1763+{
1764+ cobalt_acpi_evt evt;
1765+ int i,j;
1766+ u8 sts, en;
1767+
1768+ evt.hw_type = regions->hw_type;
1769+ evt.ev_type = COBALT_ACPI_EVT_GPE;
1770+
1771+ for( i=0 ; i<(len/2) ; i++ )
1772+ {
1773+ sts = inb( io_addr + i );
1774+ en = inb( io_addr + len/2 + i );
1775+
1776+ /* clear status bits */
1777+ outb( sts, io_addr);
1778+
1779+ for( j=0 ; j<8 ; j++ )
1780+ {
1781+ if( (en & 0x1) &&
1782+ (sts & 0x1) )
1783+ {
1784+ evt.ev_data = i*8 + j;
1785+ cobalt_acpi_post_event( evt );
1786+ }
1787+ en >>= 1;
1788+ sts >>= 1;
1789+ }
1790+ }
1791+}
1792+
1793+static int cobalt_acpi_generic_hw_handler( int irq, void *dev_id,
1794+ struct pt_regs *regs, void * data )
1795+{
1796+ generic_acpi_regions * regions = (generic_acpi_regions *) data;
1797+ cobalt_acpi_evt evt;
1798+
1799+ evt.hw_type = regions->hw_type;
1800+
1801+ /* various PM events */
1802+ if( regions->pm1a_evt_blk )
1803+ cobalt_acpi_handle_pm1_blk( regions->pm1a_evt_blk, regions->pm1_evt_len, regions );
1804+
1805+ if( regions->pm1b_evt_blk )
1806+ cobalt_acpi_handle_pm1_blk( regions->pm1b_evt_blk, regions->pm1_evt_len, regions );
1807+
1808+ if( regions->gpe0_blk )
1809+ cobalt_acpi_handle_gpe_blk( regions->gpe0_blk, regions->gpe0_len, regions );
1810+
1811+ if( regions->gpe1_blk )
1812+ cobalt_acpi_handle_gpe_blk( regions->gpe1_blk, regions->gpe1_len, regions );
1813+
1814+
1815+ return 0;
1816+}
1817+
1818+static int cobalt_acpi_generic_en_handler( u16 ev_type, u16 ev_data, int en, void *data )
1819+{
1820+ generic_acpi_regions * regions = (generic_acpi_regions *) data;
1821+ int block, offset;
1822+ u8 data8;
1823+ u16 data16;
1824+
1825+ switch( ev_type )
1826+ {
1827+ case COBALT_ACPI_EVT_TMR:
1828+ data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
1829+
1830+ if( en )
1831+ {
1832+ data16 |= GEN_ACPI_TMR_STS;
1833+ atomic_inc( &regions->tmr_ref_cnt );
1834+ }
1835+ else
1836+ {
1837+ if( atomic_dec_and_test( &regions->tmr_ref_cnt ) )
1838+ data16 &= ~GEN_ACPI_TMR_STS;
1839+ }
1840+ outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
1841+ break;
1842+
1843+ case COBALT_ACPI_EVT_BM:
1844+ data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
1845+
1846+ if( en )
1847+ {
1848+ data16 |= GEN_ACPI_BM_STS;
1849+ atomic_inc( &regions->bm_ref_cnt );
1850+ }
1851+ else
1852+ {
1853+ if( atomic_dec_and_test( &regions->bm_ref_cnt ) )
1854+ data16 &= ~GEN_ACPI_BM_STS;
1855+ }
1856+ outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
1857+ break;
1858+
1859+ case COBALT_ACPI_EVT_GBL:
1860+ data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
1861+
1862+ if( en )
1863+ {
1864+ data16 |= GEN_ACPI_GBL_STS;
1865+ atomic_inc( &regions->gbl_ref_cnt );
1866+ }
1867+ else
1868+ {
1869+ if( atomic_dec_and_test( &regions->gbl_ref_cnt ) )
1870+ data16 &= ~GEN_ACPI_GBL_STS;
1871+ }
1872+ outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
1873+ break;
1874+
1875+ case COBALT_ACPI_EVT_PWRBTN:
1876+ data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
1877+
1878+ if( en )
1879+ {
1880+ data16 |= GEN_ACPI_PWRBTN_STS;
1881+ atomic_inc( &regions->pwrbtn_ref_cnt );
1882+ }
1883+ else
1884+ {
1885+ if( atomic_dec_and_test( &regions->pwrbtn_ref_cnt ) )
1886+ data16 &= ~GEN_ACPI_PWRBTN_STS;
1887+ }
1888+ outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
1889+ break;
1890+
1891+ case COBALT_ACPI_EVT_SLPBTN:
1892+ data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
1893+
1894+ if( en )
1895+ {
1896+ data16 |= GEN_ACPI_SLPBTN_STS;
1897+ atomic_inc( &regions->slpbtn_ref_cnt );
1898+ }
1899+ else
1900+ {
1901+ if( atomic_dec_and_test( &regions->slpbtn_ref_cnt ) )
1902+ data16 &= ~GEN_ACPI_SLPBTN_STS;
1903+ }
1904+ outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
1905+ break;
1906+
1907+ case COBALT_ACPI_EVT_RTC:
1908+ data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
1909+
1910+ if( en )
1911+ {
1912+ data16 |= GEN_ACPI_RTC_STS;
1913+ atomic_inc( &regions->rtc_ref_cnt );
1914+ }
1915+ else
1916+ {
1917+ if( atomic_dec_and_test( &regions->rtc_ref_cnt ) )
1918+ data16 &= ~GEN_ACPI_RTC_STS;
1919+ }
1920+ outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
1921+ break;
1922+
1923+ case COBALT_ACPI_EVT_WAK:
1924+ data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
1925+
1926+ if( en )
1927+ {
1928+ data16 |= GEN_ACPI_WAK_STS;
1929+ atomic_inc( &regions->wak_ref_cnt );
1930+ }
1931+ else
1932+ {
1933+ if( atomic_dec_and_test( &regions->wak_ref_cnt ) )
1934+ data16 &= ~GEN_ACPI_WAK_STS;
1935+ }
1936+ outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) );
1937+ break;
1938+
1939+ case COBALT_ACPI_EVT_GPE:
1940+ if( (ev_data/8) >= (regions->gpe0_len / 2) )
1941+ return -EINVAL;
1942+
1943+ block = ev_data / 8;
1944+ offset = ev_data % 8;
1945+
1946+ data8 = inb( regions->gpe0_blk + (regions->gpe0_len / 2) + block );
1947+
1948+ if( en )
1949+ {
1950+ data8 |= 0x1 << offset;
1951+ atomic_inc( &regions->gpe_ref_cnt[ev_data] );
1952+ }
1953+ else
1954+ {
1955+ if( atomic_dec_and_test( &regions->gpe_ref_cnt[ev_data] ) )
1956+ data8 &= ~( 0x1 << offset );
1957+ }
1958+
1959+ outb( data8, regions->gpe0_blk + (regions->gpe0_len / 2) + block );
1960+
1961+ break;
1962+
1963+ default:
1964+ return -EINVAL;
1965+
1966+ }
1967+
1968+ return 0;
1969+}
1970+
1971+/*
1972+ *
1973+ * Generic ServerWorks region code
1974+ *
1975+ */
1976+
1977+static int get_serverworks_regions( generic_acpi_regions *regions, u16 type )
1978+{
1979+ int reg;
1980+
1981+ memset( regions, 0x0, sizeof( *regions ) );
1982+
1983+ regions->hw_type = type;
1984+
1985+ regions->pm1_evt_len = 4;
1986+ regions->pm1_cnt_len = 2;
1987+ regions->pm_tmr_len = 4;
1988+ regions->gpe0_len = 8;
1989+
1990+ if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x20)) )
1991+ regions->pm1a_evt_blk = (u16) reg;
1992+
1993+ if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x22)) )
1994+ regions->pm1a_cnt_blk = (u16) reg;
1995+
1996+ if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x24)) )
1997+ regions->pm_tmr_blk = (u16) reg;
1998+
1999+ if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x26)) )
2000+ regions->p_blk = (u16) reg;
2001+
2002+ if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x28)) )
2003+ regions->gpe0_blk = (u16) reg;
2004+
2005+ if( type == COBALT_ACPI_HW_OSB4 )
2006+ {
2007+ regions->pm2_cnt_len = 1;
2008+ if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x2E)) )
2009+ regions->pm2_cnt_blk = (u16) reg;
2010+ }
2011+
2012+ switch( type )
2013+ {
2014+ case COBALT_ACPI_HW_OSB4:
2015+ return register_acpi_regions( regions, "OSB4" );
2016+
2017+ case COBALT_ACPI_HW_CSB5:
2018+ return register_acpi_regions( regions, "CSB5" );
2019+ }
2020+
2021+ return -EINVAL;
2022+
2023+}
2024+
2025+/*
2026+ *
2027+ * ServerWorks OSB4
2028+ *
2029+ */
2030+
2031+static generic_acpi_regions osb4_regions;
2032+
2033+static int cobalt_acpi_osb4_init( void )
2034+{
2035+ int err;
2036+
2037+ if( (err = get_osb4_regions( &osb4_regions )) < 0 )
2038+ return err;
2039+
2040+ if( (err = cobalt_acpi_register_hw_handler( COBALT_ACPI_HW_OSB4,
2041+ cobalt_acpi_generic_hw_handler,
2042+ cobalt_acpi_generic_en_handler,
2043+ &osb4_regions )) < 0 )
2044+ return err;
2045+
2046+ return 0;
2047+}
2048+
2049+static int cobalt_acpi_osb4_cleanup( void )
2050+{
2051+ unregister_acpi_regions( &osb4_regions );
2052+ return 0;
2053+}
2054+
2055+static int get_osb4_regions( generic_acpi_regions *regions)
2056+{
2057+ return get_serverworks_regions( regions, COBALT_ACPI_HW_OSB4 );
2058+}
2059+
2060+/*
2061+ *
2062+ * ServerWorks CSB5
2063+ *
2064+ */
2065+
2066+/* static generic_acpi_regions csb5_regions; */
2067+
2068+static generic_acpi_regions csb5_regions;
2069+
2070+static int cobalt_acpi_csb5_init( void )
2071+{
2072+ int err;
2073+
2074+ if( (err = get_csb5_regions( &csb5_regions )) < 0 )
2075+ return err;
2076+
2077+ if( (err = cobalt_acpi_register_hw_handler( COBALT_ACPI_HW_CSB5,
2078+ cobalt_acpi_generic_hw_handler,
2079+ cobalt_acpi_generic_en_handler,
2080+ &csb5_regions )) < 0 )
2081+ return err;
2082+
2083+ return 0;
2084+}
2085+
2086+static int cobalt_acpi_csb5_cleanup( void )
2087+{
2088+ unregister_acpi_regions( &csb5_regions );
2089+ return 0;
2090+}
2091+
2092+static int get_csb5_regions( generic_acpi_regions *regions)
2093+{
2094+ return get_serverworks_regions( regions, COBALT_ACPI_HW_CSB5 );
2095+}
2096+
2097+/*
2098+ *
2099+ * NatSemi PC8731x
2100+ *
2101+ */
2102+static generic_acpi_regions pc8731x_regions;
2103+
2104+static int cobalt_acpi_pc8731x_init( void )
2105+{
2106+ int err;
2107+
2108+ if( (err = get_pc8731x_regions( &pc8731x_regions )) < 0 )
2109+ return err;
2110+
2111+ if( (err = cobalt_acpi_register_hw_handler( COBALT_ACPI_HW_PC8731X,
2112+ cobalt_acpi_generic_hw_handler,
2113+ cobalt_acpi_generic_en_handler,
2114+ &pc8731x_regions )) < 0 )
2115+ return err;
2116+
2117+ return 0;
2118+}
2119+
2120+static int cobalt_acpi_pc8731x_cleanup( void )
2121+{
2122+ unregister_acpi_regions( &pc8731x_regions );
2123+ return 0;
2124+}
2125+
2126+static int get_pc8731x_regions( generic_acpi_regions *regions )
2127+{
2128+ int reg;
2129+ u16 addr;
2130+
2131+ memset( regions, 0x0, sizeof( *regions ) );
2132+
2133+ regions->hw_type = COBALT_ACPI_HW_PC8731X;
2134+
2135+ regions->pm1_evt_len = 4;
2136+ regions->pm1_cnt_len = 2;
2137+ regions->pm_tmr_len = 4;
2138+ regions->gpe0_len = 4;
2139+
2140+ /* superi/o -- select pm logical device and get base address */
2141+ addr = superio_ldev_base(PC87317_DEV_PM);
2142+ if( addr )
2143+ {
2144+ /* get registers */
2145+ if( (reg = get_reg(addr, addr + 1, 0x08)) )
2146+ regions->pm1a_evt_blk = reg;
2147+
2148+ if( (reg = get_reg(addr, addr + 1, 0x0a)) )
2149+ regions->pm_tmr_blk = reg;
2150+
2151+ if( (reg = get_reg(addr, addr + 1, 0x0c)) )
2152+ regions->pm1a_cnt_blk = reg;
2153+
2154+ if( (reg = get_reg(addr, addr + 1, 0x0e)) )
2155+ regions->gpe0_blk = reg;
2156+ }
2157+
2158+ return register_acpi_regions( regions, "pc8731x" );
2159+}
2160+
2161+/*
2162+ *
2163+ * NatSemi PC8741x
2164+ *
2165+ */
2166+
2167+static generic_acpi_regions pc8741x_regions;
2168+
2169+static int cobalt_acpi_pc8741x_init( void )
2170+{
2171+ int err;
2172+
2173+ if( (err = get_pc8741x_regions( &pc8741x_regions )) < 0 )
2174+ return err;
2175+
2176+ if( (err = cobalt_acpi_register_hw_handler( COBALT_ACPI_HW_PC8741X,
2177+ cobalt_acpi_generic_hw_handler,
2178+ cobalt_acpi_generic_en_handler,
2179+ &pc8741x_regions )) < 0 )
2180+ return err;
2181+
2182+ return 0;
2183+}
2184+
2185+static int cobalt_acpi_pc8741x_cleanup( void )
2186+{
2187+ unregister_acpi_regions( &pc8741x_regions );
2188+ return 0;
2189+}
2190+
2191+static int get_pc8741x_regions( generic_acpi_regions *regions )
2192+{
2193+ int reg;
2194+
2195+ memset( regions, 0x0, sizeof( *regions ) );
2196+
2197+ regions->hw_type = COBALT_ACPI_HW_PC8741X;
2198+
2199+ regions->pm1_evt_len = 4;
2200+ regions->pm1_cnt_len = 2;
2201+ regions->pm_tmr_len = 4;
2202+ regions->gpe0_len = 8;
2203+
2204+ /* get registers */
2205+ if( (reg = superio_ldev_base_n(PC87417_DEV_SWC, 1)) )
2206+ regions->pm1a_evt_blk = reg;
2207+
2208+ if( (reg = superio_ldev_base_n(PC87417_DEV_SWC, 2)) )
2209+ regions->pm1a_cnt_blk = reg;
2210+
2211+ if( (reg = superio_ldev_base_n(PC87417_DEV_SWC, 3)) )
2212+ regions->gpe0_blk = reg;
2213+
2214+ return register_acpi_regions( regions, "pc8741x" );
2215+}
2216+
2217+/*
2218+ *
2219+ * Platform support
2220+ *
2221+ */
2222+
2223+/*
2224+ *
2225+ * Monterey
2226+ *
2227+ */
2228+
2229+static u16 cobalt_acpi_monterey_osb4_table[] = {
2230+/* GPE 0 */ COBALT_ACPI_EVT_NONE,
2231+/* GPE 1 */ COBALT_ACPI_EVT_NONE,
2232+/* GPE 2 */ COBALT_ACPI_EVT_NONE,
2233+/* GPE 3 */ COBALT_ACPI_EVT_NONE,
2234+/* GPE 4 */ COBALT_ACPI_EVT_NONE,
2235+/* GPE 5 */ COBALT_ACPI_EVT_NONE,
2236+/* GPE 6 */ COBALT_ACPI_EVT_SLED,
2237+/* GPE 7 */ COBALT_ACPI_EVT_NONE,
2238+/* GPE 8 */ COBALT_ACPI_EVT_NONE,
2239+/* GPE 9 */ COBALT_ACPI_EVT_NONE,
2240+/* GPE 10 */ COBALT_ACPI_EVT_NONE,
2241+/* GPE 11 */ COBALT_ACPI_EVT_NONE,
2242+/* GPE 12 */ COBALT_ACPI_EVT_NONE,
2243+/* GPE 13 */ COBALT_ACPI_EVT_NONE,
2244+/* GPE 14 */ COBALT_ACPI_EVT_NONE,
2245+/* GPE 15 */ COBALT_ACPI_EVT_NONE };
2246+
2247+static u16 cobalt_acpi_monterey_superio_table[] = {
2248+/* GPE 0 */ COBALT_ACPI_EVT_NONE,
2249+/* GPE 1 */ COBALT_ACPI_EVT_NONE,
2250+/* GPE 2 */ COBALT_ACPI_EVT_NONE,
2251+/* GPE 3 */ COBALT_ACPI_EVT_NONE,
2252+/* GPE 4 */ COBALT_ACPI_EVT_NONE,
2253+/* GPE 5 */ COBALT_ACPI_EVT_NONE,
2254+/* GPE 6 */ COBALT_ACPI_EVT_NONE,
2255+/* GPE 7 */ COBALT_ACPI_EVT_NONE,
2256+/* GPE 8 */ COBALT_ACPI_EVT_NONE,
2257+/* GPE 9 */ COBALT_ACPI_EVT_NONE,
2258+/* GPE 10 */ COBALT_ACPI_EVT_NONE,
2259+/* GPE 11 */ COBALT_ACPI_EVT_NONE,
2260+/* GPE 12 */ COBALT_ACPI_EVT_NONE,
2261+/* GPE 13 */ COBALT_ACPI_EVT_NONE,
2262+/* GPE 14 */ COBALT_ACPI_EVT_NONE,
2263+/* GPE 15 */ COBALT_ACPI_EVT_NONE,
2264+/* GPE 16 */ COBALT_ACPI_EVT_NONE,
2265+/* GPE 17 */ COBALT_ACPI_EVT_NONE,
2266+/* GPE 18 */ COBALT_ACPI_EVT_NONE,
2267+/* GPE 19 */ COBALT_ACPI_EVT_NONE,
2268+/* GPE 20 */ COBALT_ACPI_EVT_NONE,
2269+/* GPE 21 */ COBALT_ACPI_EVT_NONE,
2270+/* GPE 22 */ COBALT_ACPI_EVT_NONE,
2271+/* GPE 23 */ COBALT_ACPI_EVT_NONE,
2272+/* GPE 24 */ COBALT_ACPI_EVT_NONE,
2273+/* GPE 25 */ COBALT_ACPI_EVT_NONE,
2274+/* GPE 26 */ COBALT_ACPI_EVT_NONE,
2275+/* GPE 27 */ COBALT_ACPI_EVT_NONE,
2276+/* GPE 28 */ COBALT_ACPI_EVT_NONE,
2277+/* GPE 29 */ COBALT_ACPI_EVT_NONE,
2278+/* GPE 30 */ COBALT_ACPI_EVT_NONE,
2279+/* GPE 31 */ COBALT_ACPI_EVT_NONE };
2280+
2281+static int cobalt_acpi_monterey_init( void )
2282+{
2283+ int err;
2284+
2285+ err = cobalt_acpi_register_trans_table( COBALT_ACPI_HW_OSB4,
2286+ sizeof( cobalt_acpi_monterey_osb4_table )/sizeof( u16 ),
2287+ cobalt_acpi_monterey_osb4_table );
2288+ if( err < 0 )
2289+ return err;
2290+
2291+ err = cobalt_acpi_register_trans_table( COBALT_ACPI_HW_PC8731X,
2292+ sizeof( cobalt_acpi_monterey_superio_table )/sizeof( u16 ),
2293+ cobalt_acpi_monterey_superio_table );
2294+ if( err < 0 )
2295+ return err;
2296+
2297+ return 0;
2298+}
2299+
2300+static int cobalt_acpi_monterey_cleanup( void )
2301+{
2302+ cobalt_acpi_unregister_trans_table( COBALT_ACPI_HW_OSB4 );
2303+ cobalt_acpi_unregister_trans_table( COBALT_ACPI_HW_PC8731X );
2304+
2305+ return 0;
2306+}
2307+
2308+/*
2309+ *
2310+ * Alpine
2311+ *
2312+ */
2313+
2314+static u16 cobalt_acpi_alpine_csb5_table[] = {
2315+/* GPE 0 */ COBALT_ACPI_EVT_NONE,
2316+/* GPE 1 */ COBALT_ACPI_EVT_NONE,
2317+/* GPE 2 */ COBALT_ACPI_EVT_NONE,
2318+/* GPE 3 */ COBALT_ACPI_EVT_FAN,
2319+/* GPE 4 */ COBALT_ACPI_EVT_NONE,
2320+/* GPE 5 */ COBALT_ACPI_EVT_SM_INT,
2321+/* GPE 6 */ COBALT_ACPI_EVT_THERM,
2322+/* GPE 7 */ COBALT_ACPI_EVT_NONE,
2323+/* GPE 8 */ COBALT_ACPI_EVT_NONE,
2324+/* GPE 9 */ COBALT_ACPI_EVT_NONE,
2325+/* GPE 10 */ COBALT_ACPI_EVT_NONE,
2326+/* GPE 11 */ COBALT_ACPI_EVT_NONE,
2327+/* GPE 12 */ COBALT_ACPI_EVT_NONE,
2328+/* GPE 13 */ COBALT_ACPI_EVT_NONE,
2329+/* GPE 14 */ COBALT_ACPI_EVT_NONE,
2330+/* GPE 15 */ COBALT_ACPI_EVT_NONE };
2331+
2332+static u16 cobalt_acpi_alpine_superio_table[] = {
2333+/* GPE 0 */ COBALT_ACPI_EVT_NONE,
2334+/* GPE 1 */ COBALT_ACPI_EVT_NONE,
2335+/* GPE 2 */ COBALT_ACPI_EVT_NONE,
2336+/* GPE 3 */ COBALT_ACPI_EVT_NONE,
2337+/* GPE 4 */ COBALT_ACPI_EVT_NONE,
2338+/* GPE 5 */ COBALT_ACPI_EVT_NONE,
2339+/* GPE 6 */ COBALT_ACPI_EVT_NONE,
2340+/* GPE 7 */ COBALT_ACPI_EVT_NONE,
2341+/* GPE 8 */ COBALT_ACPI_EVT_NONE,
2342+/* GPE 9 */ COBALT_ACPI_EVT_NONE,
2343+/* GPE 10 */ COBALT_ACPI_EVT_NONE,
2344+/* GPE 11 */ COBALT_ACPI_EVT_NONE,
2345+/* GPE 12 */ COBALT_ACPI_EVT_NONE,
2346+/* GPE 13 */ COBALT_ACPI_EVT_NONE,
2347+/* GPE 14 */ COBALT_ACPI_EVT_NONE,
2348+/* GPE 15 */ COBALT_ACPI_EVT_NONE,
2349+/* GPE 16 */ COBALT_ACPI_EVT_NONE,
2350+/* GPE 17 */ COBALT_ACPI_EVT_NONE,
2351+/* GPE 18 */ COBALT_ACPI_EVT_NONE,
2352+/* GPE 19 */ COBALT_ACPI_EVT_NONE,
2353+/* GPE 20 */ COBALT_ACPI_EVT_NONE,
2354+/* GPE 21 */ COBALT_ACPI_EVT_NONE,
2355+/* GPE 22 */ COBALT_ACPI_EVT_NONE,
2356+/* GPE 23 */ COBALT_ACPI_EVT_NONE,
2357+/* GPE 24 */ COBALT_ACPI_EVT_NONE,
2358+/* GPE 25 */ COBALT_ACPI_EVT_NONE,
2359+/* GPE 26 */ COBALT_ACPI_EVT_NONE,
2360+/* GPE 27 */ COBALT_ACPI_EVT_NONE,
2361+/* GPE 28 */ COBALT_ACPI_EVT_NONE,
2362+/* GPE 29 */ COBALT_ACPI_EVT_NONE,
2363+/* GPE 30 */ COBALT_ACPI_EVT_NONE,
2364+/* GPE 31 */ COBALT_ACPI_EVT_NONE };
2365+
2366+static int cobalt_acpi_alpine_init( void )
2367+{
2368+ int err;
2369+
2370+ err = cobalt_acpi_register_trans_table( COBALT_ACPI_HW_CSB5,
2371+ sizeof( cobalt_acpi_alpine_csb5_table )/sizeof( u16 ),
2372+ cobalt_acpi_alpine_csb5_table );
2373+ if( err < 0 )
2374+ return err;
2375+
2376+ err = cobalt_acpi_register_trans_table( COBALT_ACPI_HW_PC8741X,
2377+ sizeof( cobalt_acpi_alpine_superio_table )/sizeof( u16 ),
2378+ cobalt_acpi_alpine_superio_table );
2379+ if( err < 0 )
2380+ return err;
2381+
2382+ return 0;
2383+}
2384+
2385+static int cobalt_acpi_alpine_cleanup( void )
2386+{
2387+ cobalt_acpi_unregister_trans_table( COBALT_ACPI_HW_CSB5 );
2388+ cobalt_acpi_unregister_trans_table( COBALT_ACPI_HW_PC8741X );
2389+
2390+ return 0;
2391+}
2392+
2393+/*
2394+ * end platform support
2395+ */
2396+#ifdef CONFIG_COBALT_EMU_ACPI
2397+/*
2398+ * This is all necessary because we don't have BIOS support for ACPI yet.
2399+ * We can fake it here, and when full support is ready just yank this.
2400+ */
2401+typedef struct {
2402+ char *device_type;
2403+ char *device_instance;
2404+ u32 event_type;
2405+ u32 event_data;
2406+ struct list_head list;
2407+} cobalt_acpi_event_t;
2408+
2409+#define COBALT_ACPI_MAX_STRING_LENGTH 80
2410+
2411+static LIST_HEAD(cobalt_acpi_event_list);
2412+static DECLARE_WAIT_QUEUE_HEAD(cobalt_acpi_event_wait_queue);
2413+static int event_is_open = 0;
2414+static spinlock_t cobalt_acpi_event_lock = SPIN_LOCK_UNLOCKED;
2415+
2416+static struct proc_dir_entry *cobalt_acpi_proc_root;
2417+static struct proc_dir_entry *cobalt_acpi_proc_event;
2418+
2419+static struct file_operations proc_event_ops = {
2420+ open: cobalt_acpi_open_event,
2421+ read: cobalt_acpi_read_event,
2422+ release: cobalt_acpi_close_event,
2423+ poll: cobalt_acpi_poll_event,
2424+};
2425+
2426+static int
2427+cobalt_acpi_setup_proc(void)
2428+{
2429+ cobalt_acpi_proc_root = proc_mkdir("acpi", NULL);
2430+ if (!cobalt_acpi_proc_root) {
2431+ return -ENOMEM;
2432+ }
2433+
2434+ cobalt_acpi_proc_event = create_proc_entry("event", S_IRUSR,
2435+ cobalt_acpi_proc_root);
2436+ if (!cobalt_acpi_proc_event) {
2437+ return -ENOMEM;
2438+ }
2439+
2440+ cobalt_acpi_proc_event->proc_fops = &proc_event_ops;
2441+
2442+ return 0;
2443+}
2444+
2445+
2446+int
2447+cobalt_acpi_generate_proc_evt( cobalt_acpi_evt * evt )
2448+{
2449+ cobalt_acpi_event_t *event = NULL, *tmp;
2450+ unsigned long flags = 0;
2451+ char *dev_type;
2452+ char *dev_instance;
2453+ u32 event_type;
2454+ u32 event_data;
2455+ struct list_head *pos;
2456+
2457+ /* drop event on the floor if no one's listening */
2458+ if (!event_is_open)
2459+ return 0;
2460+
2461+ event_type = (evt->ev_type << 0x10) |
2462+ evt->hw_type;
2463+ event_data = evt->ev_data;
2464+
2465+
2466+ /*
2467+ * Check to see if an event of this type is already
2468+ * pending
2469+ */
2470+ spin_lock_irqsave(&cobalt_acpi_event_lock, flags);
2471+ list_for_each( pos, &cobalt_acpi_event_list )
2472+ {
2473+ tmp = list_entry(pos, cobalt_acpi_event_t, list);
2474+ if( (tmp->event_type == event_type) &&
2475+ (tmp->event_data == event_data) )
2476+ {
2477+ spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags);
2478+ return 0;
2479+ }
2480+
2481+
2482+ }
2483+ spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags);
2484+
2485+
2486+ /* parse the event struct */
2487+ switch( evt->ev_type )
2488+ {
2489+ case COBALT_ACPI_EVT_TMR:
2490+ dev_type = "generic";
2491+ dev_instance = "timer";
2492+ break;
2493+
2494+ case COBALT_ACPI_EVT_BM:
2495+ dev_type = "generic";
2496+ dev_instance = "bus-master";
2497+ break;
2498+
2499+ case COBALT_ACPI_EVT_GBL:
2500+ dev_type = "generic";
2501+ dev_instance = "global";
2502+ break;
2503+
2504+ case COBALT_ACPI_EVT_PWRBTN:
2505+ dev_type = "button";
2506+ dev_instance = "power";
2507+ break;
2508+
2509+ case COBALT_ACPI_EVT_SLPBTN:
2510+ dev_type = "button";
2511+ dev_instance = "sleep";
2512+ break;
2513+
2514+ case COBALT_ACPI_EVT_RTC:
2515+ dev_type = "generic";
2516+ dev_instance = "rtc";
2517+ break;
2518+
2519+ case COBALT_ACPI_EVT_WAK:
2520+ dev_type = "generic";
2521+ dev_instance = "wake";
2522+ break;
2523+
2524+ case COBALT_ACPI_EVT_GPE:
2525+ dev_type = "generic";
2526+ dev_instance = "gpe";
2527+ break;
2528+
2529+ case COBALT_ACPI_EVT_SLED:
2530+ dev_type = "cobalt";
2531+ dev_instance = "sled";
2532+ break;
2533+
2534+ case COBALT_ACPI_EVT_THERM:
2535+ dev_type = "cobalt";
2536+ dev_instance = "therm_trip";
2537+ break;
2538+
2539+ case COBALT_ACPI_EVT_FAN:
2540+ dev_type = "cobalt";
2541+ dev_instance = "fan";
2542+ break;
2543+
2544+ case COBALT_ACPI_EVT_SM_INT:
2545+ dev_type = "cobalt";
2546+ dev_instance = "sm_int";
2547+ break;
2548+
2549+ case COBALT_ACPI_EVT_VOLT:
2550+ dev_type = "cobalt";
2551+ dev_instance = "volt_trip";
2552+ break;
2553+
2554+ default:
2555+ dev_type = "unknown";
2556+ dev_instance = "unknown";
2557+ break;
2558+ }
2559+
2560+
2561+ /*
2562+ * Allocate a new event structure.
2563+ */
2564+ event = kmalloc(sizeof(*event), GFP_ATOMIC);
2565+ if (!event)
2566+ goto alloc_error;
2567+
2568+ event->device_type=NULL;
2569+ event->device_instance=NULL;
2570+
2571+ event->device_type = kmalloc(strlen(dev_type) + sizeof(char),
2572+ GFP_ATOMIC);
2573+ if (!event->device_type)
2574+ goto alloc_error;
2575+
2576+ event->device_instance = kmalloc(strlen(dev_instance) + sizeof(char),
2577+ GFP_ATOMIC );
2578+ if (!event->device_instance)
2579+ goto alloc_error;
2580+
2581+ /*
2582+ * Set event data.
2583+ */
2584+ strcpy(event->device_type, dev_type);
2585+ strcpy(event->device_instance, dev_instance);
2586+ event->event_type = event_type;
2587+ event->event_data = event_data;
2588+
2589+ /*
2590+ * Add to the end of our event list.
2591+ */
2592+ spin_lock_irqsave(&cobalt_acpi_event_lock, flags);
2593+ list_add_tail(&event->list, &cobalt_acpi_event_list);
2594+ spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags);
2595+
2596+ /*
2597+ * Signal waiting threads (if any).
2598+ */
2599+ wake_up_interruptible(&cobalt_acpi_event_wait_queue);
2600+
2601+ return 0;
2602+
2603+alloc_error:
2604+ if(event)
2605+ {
2606+ if (event->device_instance)
2607+ kfree(event->device_instance);
2608+
2609+ if (event->device_type)
2610+ kfree(event->device_type);
2611+
2612+ kfree(event);
2613+ }
2614+
2615+ return -ENOMEM;
2616+}
2617+
2618+
2619+static int
2620+cobalt_acpi_open_event(struct inode *inode, struct file *file)
2621+{
2622+ unsigned long flags;
2623+ spin_lock_irqsave(&cobalt_acpi_event_lock, flags);
2624+
2625+ if (event_is_open)
2626+ goto out_busy;
2627+
2628+ event_is_open = 1;
2629+
2630+ spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags);
2631+ return 0;
2632+
2633+out_busy:
2634+ spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags);
2635+ return -EBUSY;
2636+}
2637+
2638+
2639+static int
2640+cobalt_acpi_close_event(struct inode *inode, struct file *file)
2641+{
2642+ unsigned long flags;
2643+ struct list_head *pos;
2644+ cobalt_acpi_event_t *tmp;
2645+
2646+ spin_lock_irqsave(&cobalt_acpi_event_lock, flags);
2647+
2648+ while( (pos = list_pop( &cobalt_acpi_event_list )) )
2649+ {
2650+ tmp = list_entry(pos, cobalt_acpi_event_t, list);
2651+ if (tmp->device_instance)
2652+ kfree(tmp->device_instance);
2653+
2654+ if (tmp->device_type)
2655+ kfree(tmp->device_type);
2656+
2657+ kfree( tmp );
2658+ }
2659+ event_is_open = 0;
2660+ spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags);
2661+ return 0;
2662+}
2663+
2664+#define ACPI_MAX_STRING_LENGTH 80
2665+static ssize_t
2666+cobalt_acpi_read_event(struct file *file, char *buf, size_t count, loff_t *ppos)
2667+{
2668+ cobalt_acpi_event_t *event = NULL;
2669+ unsigned long flags = 0;
2670+ static char str[ACPI_MAX_STRING_LENGTH];
2671+ static int strsize;
2672+ static char *ptr;
2673+
2674+ if (!strsize) {
2675+ DECLARE_WAITQUEUE(wait, current);
2676+
2677+ if (list_empty(&cobalt_acpi_event_list)) {
2678+ if (file->f_flags & O_NONBLOCK) {
2679+ return -EAGAIN;
2680+ }
2681+ set_current_state(TASK_INTERRUPTIBLE);
2682+ add_wait_queue(&cobalt_acpi_event_wait_queue, &wait);
2683+
2684+ if (list_empty(&cobalt_acpi_event_list)) {
2685+ schedule();
2686+ }
2687+
2688+ remove_wait_queue(&cobalt_acpi_event_wait_queue, &wait);
2689+ set_current_state(TASK_RUNNING);
2690+
2691+ if (signal_pending(current)) {
2692+ return -ERESTARTSYS;
2693+ }
2694+ }
2695+
2696+ spin_lock_irqsave(&cobalt_acpi_event_lock, flags);
2697+ event = list_entry(cobalt_acpi_event_list.next,
2698+ cobalt_acpi_event_t, list);
2699+ list_del(&event->list);
2700+ spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags);
2701+
2702+ strsize = sprintf(str, "%s %s %08x %08x\n",
2703+ event->device_type, event->device_instance,
2704+ event->event_type, event->event_data);
2705+ ptr = str;
2706+
2707+ kfree(event->device_type);
2708+ kfree(event->device_instance);
2709+ kfree(event);
2710+ }
2711+ if (strsize < count)
2712+ count = strsize;
2713+
2714+ if (copy_to_user(buf, ptr, count))
2715+ return -EFAULT;
2716+
2717+ *ppos += count;
2718+ strsize -= count;
2719+ ptr += count;
2720+
2721+ return count;
2722+}
2723+
2724+static unsigned int
2725+cobalt_acpi_poll_event(struct file *file, poll_table *wait)
2726+{
2727+ poll_wait(file, &cobalt_acpi_event_wait_queue, wait);
2728+ if (!list_empty(&cobalt_acpi_event_list))
2729+ return POLLIN | POLLRDNORM;
2730+ return 0;
2731+}
2732+
2733+#endif /* CONFIG_COBALT_EMU_ACPI */
2734diff -Naur linux-2.6.18.2.orig/drivers/cobalt/fans.c linux-2.6.18.2/drivers/cobalt/fans.c
2735--- linux-2.6.18.2.orig/drivers/cobalt/fans.c 1969-12-31 16:00:00.000000000 -0800
2736+++ linux-2.6.18.2/drivers/cobalt/fans.c 2006-11-15 21:20:19.738033319 -0800
2737@@ -0,0 +1,419 @@
2738+/* $Id: fans.c,v 1.18 2002/03/16 21:33:02 duncan Exp $
2739+ * Copyright (c) 2000-2001 Sun Microsystems, Inc
2740+ *
2741+ * This should be SMP safe. The critical data (the info list) and the
2742+ * critical code (inb()/outb() calls) are protected by fan_lock. It is
2743+ * locked at the only external access points - the proc read()/write()
2744+ * methods. --TPH
2745+ */
2746+#include <linux/config.h>
2747+#if defined(CONFIG_COBALT_FANS) || defined(CONFIG_COBALT_FANS_MODULE)
2748+
2749+#include <stdarg.h>
2750+#include <stddef.h>
2751+
2752+#include <linux/init.h>
2753+#include <linux/sched.h>
2754+#include <linux/module.h>
2755+#include <linux/pci.h>
2756+#include <linux/errno.h>
2757+#include <linux/proc_fs.h>
2758+#include <linux/time.h>
2759+
2760+#include <asm/io.h>
2761+#include <asm/uaccess.h>
2762+
2763+#include <cobalt/cobalt.h>
2764+#include <cobalt/systype.h>
2765+
2766+#define FAN_DRIVER "Cobalt Networks Fan driver"
2767+#define FAN_DRIVER_VMAJ 1
2768+#define FAN_DRIVER_VMIN 0
2769+
2770+/* GPIO base is assigned by BIOS, perhaps we should probe it */
2771+#define GPIO_BASE 0x600
2772+#define FAN_GPIO_MAX 8
2773+#define FAN_RPM(fn,ms) ((fn).hcyl * (60000000 / (fn).poles) / (ms))
2774+#define FAN_VALID(f) ((f)->mask && (f)->poles)
2775+#define FAN_CACHE_TIME 2 /* seconds */
2776+#define FAN_SAMPLE_LEN 50 /* milliseconds */
2777+
2778+/*
2779+ * fans are attached to GPIO pins
2780+ * each pin is part of a port, multiple fans are controlled by a port
2781+ */
2782+struct fan_info {
2783+ int id; /* fan number */
2784+ uint8_t mask; /* mask within the port */
2785+ int poles; /* # of magnetic poles (divisor) */
2786+ int hcyl; /* # of half cycles */
2787+ unsigned rpm; /* calculated fan speed */
2788+ char *type; /* FAN description */
2789+};
2790+
2791+struct fan_gpio {
2792+ int port; /* GPIO Port */
2793+ uint16_t base; /* GPDI (data in) base address */
2794+ uint8_t latch; /* latched 'data in' value */
2795+ long tcache; /* latched 'epoch' value */
2796+ struct fan_info fan[FAN_GPIO_MAX];
2797+};
2798+
2799+/* the current fanlist */
2800+static struct fan_gpio *sys_fanlist;
2801+static spinlock_t fan_lock = SPIN_LOCK_UNLOCKED;
2802+
2803+static struct fan_gpio fan_gpio_raqxtr[] = {
2804+ {
2805+ port: 1,
2806+ base: GPIO_BASE,
2807+ fan: {
2808+ { mask: 0x2, poles: 4, type: "processor" },
2809+ { mask: 0x4, poles: 4, type: "processor" },
2810+ { mask: 0 },
2811+ },
2812+ },
2813+ {
2814+ port: 2,
2815+ base: GPIO_BASE+4,
2816+ fan: {
2817+ { mask: 0x10, poles: 4 },
2818+ { mask: 0x20, poles: 4 },
2819+ { mask: 0x40, poles: 4 },
2820+ { mask: 0x80, poles: 4 },
2821+ { mask: 0 },
2822+ },
2823+ },
2824+ { port: -1 }
2825+};
2826+
2827+static struct fan_gpio fan_gpio_alpine[] = {
2828+ {
2829+ port: 2,
2830+ base: GPIO_BASE+7,
2831+ fan: {
2832+ { mask: 0x4, poles: 4 },
2833+ { mask: 0x8, poles: 4 },
2834+ { mask: 0x10, poles: 4 },
2835+ { mask: 0x20, poles: 4, type: "power supply" },
2836+ { mask: 0x40, poles: 4, type: "processor" },
2837+ { mask: 0 },
2838+ },
2839+ },
2840+ { port: -1 }
2841+};
2842+
2843+#ifdef CONFIG_PROC_FS
2844+#ifdef CONFIG_COBALT_OLDPROC
2845+static struct proc_dir_entry *proc_faninfo;
2846+#endif /* CONFIG_COBALT_OLDPROC */
2847+static struct proc_dir_entry *proc_cfaninfo;
2848+#endif /* CONFIG_PROC_FS */
2849+
2850+static struct fan_info *fan_info_find(int id);
2851+static int fan_control(struct fan_info *fi, int todo);
2852+static int fan_info_print(char *buffer);
2853+static int fan_read_proc(char *buf, char **start, off_t pos,
2854+ int len, int *eof, void *x);
2855+static int fan_write_proc(struct file *file, const char *buf,
2856+ unsigned long len, void *x);
2857+
2858+int __init
2859+cobalt_fan_init(void)
2860+{
2861+ if (cobt_is_monterey()) {
2862+ sys_fanlist = (struct fan_gpio *)fan_gpio_raqxtr;
2863+ } else if (cobt_is_alpine()) {
2864+ sys_fanlist = (struct fan_gpio *)fan_gpio_alpine;
2865+ } else {
2866+ sys_fanlist = NULL;
2867+ return -ENOSYS;
2868+ }
2869+
2870+ printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", FAN_DRIVER,FAN_DRIVER_VMAJ,FAN_DRIVER_VMIN);
2871+
2872+#ifdef CONFIG_PROC_FS
2873+#ifdef CONFIG_COBALT_OLDPROC
2874+ proc_faninfo = create_proc_entry("faninfo", S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, NULL);
2875+ if (!proc_faninfo) {
2876+ EPRINTK("can't create /proc/faninfo\n");
2877+ return -ENOENT;
2878+ }
2879+ proc_faninfo->owner = THIS_MODULE;
2880+ proc_faninfo->read_proc = fan_read_proc;
2881+ proc_faninfo->write_proc = fan_write_proc;
2882+#endif /* CONFIG_COBALT_OLDPROC */
2883+ proc_cfaninfo = create_proc_entry("faninfo", S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, proc_cobalt);
2884+ if (!proc_cfaninfo) {
2885+ EPRINTK("can't create /proc/cobalt/faninfo\n");
2886+ return -ENOENT;
2887+ }
2888+ proc_cfaninfo->owner = THIS_MODULE;
2889+ proc_cfaninfo->read_proc = fan_read_proc;
2890+ proc_cfaninfo->write_proc = fan_write_proc;
2891+#endif /* CONFIG_PROC_FS */
2892+
2893+ return 0;
2894+}
2895+
2896+static void __exit
2897+cobalt_fan_exit(void)
2898+{
2899+#ifdef CONFIG_PROC_FS
2900+#ifdef CONFIG_COBALT_OLDPROC
2901+ if (proc_faninfo) {
2902+ remove_proc_entry("faninfo", NULL);
2903+ }
2904+#endif /* CONFIG_COBALT_OLDPROC */
2905+ if (proc_cfaninfo) {
2906+ remove_proc_entry("faninfo", proc_cobalt);
2907+ }
2908+#endif /* CONFIG_PROC_FS */
2909+
2910+ sys_fanlist = NULL;
2911+}
2912+
2913+/*
2914+ * Samples fan tachometer square wave to calculate and report RPM
2915+ */
2916+static int
2917+get_faninfo(char *buffer)
2918+{
2919+ struct fan_gpio *fg;
2920+ struct timeval utime;
2921+ unsigned long elapsed, start;
2922+ int i, val, len;
2923+
2924+ if (!sys_fanlist || !cobt_is_5k()) {
2925+ /* software is keyed off this string - do not change it ! */
2926+ return sprintf(buffer, "Fan monitoring not supported.\n");
2927+ }
2928+
2929+ /* save start timestamp */
2930+ do_gettimeofday(&utime);
2931+ start = utime.tv_usec;
2932+
2933+ /* initialize 'previous' values. we do edge detection by
2934+ * looking for transitions from previous values */
2935+ for (fg = sys_fanlist; fg->port >= 0; fg++) {
2936+ if (fg->tcache && utime.tv_sec < fg->tcache+FAN_CACHE_TIME) {
2937+ return fan_info_print(buffer);
2938+ }
2939+ fg->tcache = utime.tv_sec;
2940+ fg->latch = inb(fg->base);
2941+ for (i = 0; i < FAN_GPIO_MAX; i++) {
2942+ fg->fan[i].hcyl = 0;
2943+ fg->fan[i].rpm = 0;
2944+ }
2945+ }
2946+
2947+ /* We are counting the number of halfcycles in a square wave
2948+ * that pass in a given amount of time to determine frequency */
2949+ do {
2950+ for (fg=sys_fanlist; fg->port>=0; fg++) {
2951+ val = inb(fg->base);
2952+ for (i=0; i<FAN_GPIO_MAX; i++) {
2953+ struct fan_info *p = &fg->fan[i];
2954+ if (FAN_VALID(p)) {
2955+ if ((val ^ fg->latch) & p->mask) {
2956+ p->hcyl++;
2957+ }
2958+ }
2959+ }
2960+ fg->latch = val;
2961+ }
2962+
2963+ do_gettimeofday(&utime);
2964+ if (utime.tv_usec > start) {
2965+ elapsed = utime.tv_usec - start;
2966+ } else {
2967+ elapsed = utime.tv_usec + 1000001 - start;
2968+ }
2969+
2970+ } while (elapsed < (FAN_SAMPLE_LEN) * 1000);
2971+
2972+ /* Fan rpm = 60 / ( t * poles )
2973+ * where t is 1/2 the period and poles are the number of
2974+ * magnetic poles for the fan.
2975+ *
2976+ * For the Sunon KDE1204PKBX fans on Raq XTR, poles = 4
2977+ * So, in terms of cycles,
2978+ *
2979+ * rpm = 60 s/m halfcycles
2980+ * ------ * -------------- * 1,000,000 us/s * 2
2981+ * 4 2 * elapsed us
2982+ *
2983+ * = (60,000,000 / 4 poles) * halfcycles / elapsed
2984+ * = 15,000,000 * halfcycles / elapsed
2985+ *
2986+ * Note, by this method and sampling for 50ms, our accuracy
2987+ * is +/- 300 rpm. The fans are spec'ed for +/- 1000 rpm
2988+ */
2989+ for (val=len=0, fg=sys_fanlist; fg->port>=0; fg++) {
2990+ for (i=0; i<FAN_GPIO_MAX; i++) {
2991+ struct fan_info *p = &fg->fan[i];
2992+ if (FAN_VALID(p)) {
2993+ p->id = val++;
2994+ p->rpm = FAN_RPM(fg->fan[i], elapsed);
2995+ len += sprintf(buffer+len, "fan %d : %u\n",
2996+ p->id, p->rpm);
2997+ }
2998+ }
2999+ }
3000+
3001+ return len;
3002+}
3003+
3004+static int
3005+fan_info_print(char *buffer)
3006+{
3007+ struct fan_gpio *fg;
3008+ int i, len=0;
3009+
3010+ if (!sys_fanlist) {
3011+ return -1;
3012+ }
3013+
3014+ for (fg=sys_fanlist; fg->port>=0; fg++) {
3015+ for (i=0; i<FAN_GPIO_MAX; i++) {
3016+ struct fan_info *p = &fg->fan[i];
3017+ if (FAN_VALID(p)) {
3018+ len += sprintf(buffer+len, "fan %d : %u\n",
3019+ p->id, p->rpm);
3020+ }
3021+ }
3022+ }
3023+
3024+ return len;
3025+}
3026+
3027+/* FIXME: generify */
3028+static int
3029+fan_control(struct fan_info *fi, int todo)
3030+{
3031+ if (fi && cobt_is_alpine()) {
3032+ switch (fi->id) {
3033+ case 4: {
3034+ /* CPU FAN */
3035+ uint8_t gpdo = inb(GPIO_BASE+6);
3036+
3037+ if (todo) {
3038+ gpdo &= ~fi->mask; /* 0 = on */
3039+ } else {
3040+ gpdo |= fi->mask; /* 1 = off */
3041+ }
3042+ outb(gpdo, GPIO_BASE+6);
3043+ return 0;
3044+ }
3045+ default:
3046+ return -ENODEV;
3047+ }
3048+ }
3049+
3050+ return -ENOSYS;
3051+}
3052+
3053+static struct fan_info *
3054+fan_info_find(int id)
3055+{
3056+ struct fan_gpio *fg;
3057+ int i;
3058+
3059+ if (!sys_fanlist) {
3060+ return NULL;
3061+ }
3062+
3063+ for (fg=sys_fanlist; fg->port>=0; fg++) {
3064+ for (i=0; i<FAN_GPIO_MAX; i++) {
3065+ if (FAN_VALID(&fg->fan[i])) {
3066+ if (fg->fan[i].id == id) {
3067+ return &fg->fan[i];
3068+ }
3069+ }
3070+ }
3071+ }
3072+
3073+ return NULL;
3074+}
3075+
3076+#ifdef CONFIG_PROC_FS
3077+static int
3078+fan_read_proc(char *buf, char **start, off_t pos, int len, int *eof, void *x)
3079+{
3080+ int plen;
3081+
3082+ //MOD_INC_USE_COUNT;
3083+
3084+ spin_lock(&fan_lock);
3085+ plen = get_faninfo(buf);
3086+ spin_unlock(&fan_lock);
3087+
3088+ //MOD_DEC_USE_COUNT;
3089+
3090+ return cobalt_gen_proc_read(buf, plen, start, pos, len, eof);
3091+}
3092+
3093+static int
3094+fan_write_proc(struct file *file, const char *buf, unsigned long len, void *x)
3095+{
3096+ char *page;
3097+ int retval = -EINVAL;
3098+
3099+ //MOD_INC_USE_COUNT;
3100+
3101+ if (len > PAGE_SIZE) {
3102+ //MOD_DEC_USE_COUNT;
3103+ return -EOVERFLOW;
3104+ }
3105+
3106+ page = (char *)__get_free_page(GFP_KERNEL);
3107+ if (!page) {
3108+ //MOD_DEC_USE_COUNT;
3109+ return -ENOMEM;
3110+ }
3111+
3112+ if (copy_from_user(page, buf, len)) {
3113+ free_page((unsigned long)page);
3114+ //MOD_DEC_USE_COUNT;
3115+ return -EFAULT;
3116+ }
3117+ page[len] = '\0';
3118+
3119+ /* format: `fan ID COMMAND' */
3120+ if (len>5 && !strncmp("fan ", page, 4)) {
3121+ if (*(page+4) != '\0') {
3122+ struct fan_info *finf;
3123+ char *nextpg = NULL;
3124+
3125+ spin_lock(&fan_lock);
3126+ finf = fan_info_find(simple_strtoul(page+4,&nextpg,0));
3127+ if (!finf) {
3128+ retval = -ENOENT;
3129+ } else if (nextpg != '\0') {
3130+ if (!strncmp("on", nextpg+1, 2)) {
3131+ retval = fan_control(finf, 1);
3132+ }
3133+ else if (!strncmp("off", nextpg+1, 3)) {
3134+ retval = fan_control(finf, 0);
3135+ }
3136+ }
3137+ spin_unlock(&fan_lock);
3138+ }
3139+ }
3140+
3141+ free_page((unsigned long)page);
3142+ //MOD_DEC_USE_COUNT;
3143+
3144+ return (retval < 0) ? retval : len;
3145+}
3146+#endif /* CONFIG_PROC_FS */
3147+
3148+#if defined(CONFIG_COBALT_FANS_MODULE)
3149+module_init(cobalt_fan_init);
3150+module_exit(cobalt_fan_exit);
3151+
3152+MODULE_AUTHOR("Sun Cobalt");
3153+MODULE_DESCRIPTION("Sun Cobalt fan tachometers");
3154+#endif
3155+
3156+#endif /* CONFIG_COBALT_FANS || CONFIG_COBALT_FANS_MODULE */
3157diff -Naur linux-2.6.18.2.orig/drivers/cobalt/i2c.c linux-2.6.18.2/drivers/cobalt/i2c.c
3158--- linux-2.6.18.2.orig/drivers/cobalt/i2c.c 1969-12-31 16:00:00.000000000 -0800
3159+++ linux-2.6.18.2/drivers/cobalt/i2c.c 2006-11-15 21:20:19.738033319 -0800
3160@@ -0,0 +1,519 @@
3161+/*
3162+ * $Id: i2c.c,v 1.19 2002/09/17 23:41:29 sparker Exp $
3163+ * i2c.c : Cobalt I2C driver support
3164+ *
3165+ * Copyright (C) 2000 Cobalt Networks, Inc.
3166+ * Copyright (C) 2001 Sun Microsystems, Inc.
3167+ *
3168+ * Modified By: jeff@404ster.com
3169+ *
3170+ * This should be SMP safe. All the exported functions lock on enter and
3171+ * unlock on exit. These exported functions may be called at interupt time,
3172+ * so we have to use the IRQ safe locks. NOTE: no function herein may call
3173+ * any exported function herein. --TPH
3174+ */
3175+#include <stddef.h>
3176+#include <linux/init.h>
3177+#include <linux/types.h>
3178+#include <linux/config.h>
3179+#include <linux/pci.h>
3180+#include <linux/delay.h>
3181+#include <linux/module.h>
3182+#include <asm/io.h>
3183+
3184+#include <cobalt/cobalt.h>
3185+#include <cobalt/i2c.h>
3186+#include <cobalt/systype.h>
3187+
3188+#define I2C_3K_STATUS 0x00
3189+#define I2C_3K_CMD 0x01
3190+#define I2C_3K_START 0x02
3191+#define I2C_3K_ADDR 0x03
3192+#define I2C_3K_LOW_DATA 0x04
3193+#define I2C_3K_HIGH_DATA 0x05
3194+#define I2C_3K_BLOCK_DATA 0x06
3195+#define I2C_3K_INDEX 0x07
3196+#define I2C_3K_STATUS_IDLE 0x04
3197+#define I2C_3K_CMD_RW_BYTE 0x20
3198+#define I2C_3K_CMD_RW_WORD 0x30
3199+#define I2C_3K_CMD_RW_BLOCK 0xC0
3200+#define I2C_3K_CMD_RESET_PTR 0x80
3201+
3202+#define I2C_5K_HOST_STATUS 0x00
3203+#define I2C_5K_SLAVE_STATUS 0x01
3204+#define I2C_5K_HOST_CONTROL 0x02
3205+#define I2C_5K_HOST_COMMAND 0x03
3206+#define I2C_5K_HOST_ADDR 0x04
3207+#define I2C_5K_DATA_0 0x05
3208+#define I2C_5K_DATA_1 0x06
3209+#define I2C_5K_BLOCK_DATA 0x07
3210+#define I2C_5K_SLAVE_CONTROL 0x08
3211+#define I2C_5K_SHADOW_COMMAND 0x09
3212+#define I2C_5K_SLAVE_EVENT 0x0a
3213+#define I2C_5K_SLAVE_DATA 0x0c
3214+#define I2C_5K_HOST_STATUS_BUSY 0x01
3215+#define I2C_5K_HOST_CMD_START 0x40
3216+#define I2C_5K_HOST_CMD_QUICK_RW (0 << 2)
3217+#define I2C_5K_HOST_CMD_BYTE_RW (1 << 2)
3218+#define I2C_5K_HOST_CMD_BYTE_DATA_RW (2 << 2)
3219+#define I2C_5K_HOST_CMD_WORD_DATA_RW (3 << 2)
3220+#define I2C_5K_HOST_CMD_BLOCK_DATA_RW (5 << 2)
3221+
3222+#define I2C_WRITE 0
3223+#define I2C_READ 1
3224+
3225+/* this delay was determined empirically */
3226+#define I2C_WRITE_UDELAY 1000
3227+
3228+struct cobalt_i2c_data {
3229+ const unsigned char status;
3230+ const unsigned char addr;
3231+ const unsigned char index;
3232+ const unsigned char data_low;
3233+ const unsigned char data_high;
3234+ const unsigned char data_block;
3235+ const unsigned char rw_byte;
3236+ const unsigned char rw_word;
3237+ const unsigned char rw_block;
3238+ unsigned int io_port;
3239+};
3240+
3241+struct cobalt_i2c_data cobalt_i2c_3k = {
3242+ I2C_3K_STATUS,
3243+ I2C_3K_ADDR,
3244+ I2C_3K_INDEX,
3245+ I2C_3K_LOW_DATA,
3246+ I2C_3K_HIGH_DATA,
3247+ I2C_3K_BLOCK_DATA,
3248+ I2C_3K_CMD_RW_BYTE,
3249+ I2C_3K_CMD_RW_WORD,
3250+ I2C_3K_CMD_RW_BLOCK,
3251+ 0L
3252+};
3253+
3254+struct cobalt_i2c_data cobalt_i2c_5k = {
3255+ I2C_5K_HOST_STATUS,
3256+ I2C_5K_HOST_ADDR,
3257+ I2C_5K_HOST_COMMAND,
3258+ I2C_5K_DATA_0,
3259+ I2C_5K_DATA_1,
3260+ I2C_5K_BLOCK_DATA,
3261+ I2C_5K_HOST_CMD_BYTE_DATA_RW,
3262+ I2C_5K_HOST_CMD_WORD_DATA_RW,
3263+ I2C_5K_HOST_CMD_BLOCK_DATA_RW,
3264+ 0L
3265+};
3266+
3267+/* a global pointer for our i2c data */
3268+struct cobalt_i2c_data *i2c_data;
3269+
3270+#define I2C_REG(r) (i2c_data->io_port + i2c_data->r)
3271+#define I2C_CMD(c) (i2c_data->c)
3272+
3273+#define I2C_LOCK (1 << 0)
3274+#define I2C_DEAD (1 << 1)
3275+static unsigned long i2c_state;
3276+
3277+static int initialized;
3278+
3279+static inline int
3280+do_i2c_lock(void)
3281+{
3282+ int i = 0;
3283+
3284+ if (test_bit(I2C_DEAD, &i2c_state))
3285+ return -1;
3286+
3287+ while (test_and_set_bit(I2C_LOCK, &i2c_state)) {
3288+ if (i++ > 5)
3289+ return -1;
3290+ udelay(10);
3291+ }
3292+ udelay(1);
3293+ return 0;
3294+}
3295+
3296+static inline void
3297+do_i2c_unlock(void)
3298+{
3299+ clear_bit(I2C_LOCK, &i2c_state);
3300+}
3301+
3302+/* do a little squelching */
3303+#define NOISE_RATE (5*HZ)
3304+static int
3305+i2c_noisy(void)
3306+{
3307+ static unsigned long last_time;
3308+ static unsigned int messages;
3309+
3310+ if ((long) (jiffies - last_time) > NOISE_RATE) {
3311+ last_time = jiffies;
3312+ if (messages) {
3313+ WPRINTK("skipped %u kernel messages\n", messages);
3314+ messages = 0;
3315+ }
3316+ return 0;
3317+ }
3318+ messages++;
3319+ return 1;
3320+}
3321+
3322+static int
3323+i2c_wait_for_smi(void)
3324+{
3325+ static unsigned int shutup = 0;
3326+ int timeout=10;
3327+ int status;
3328+
3329+ while (timeout--) {
3330+ udelay(100); /* wait */
3331+ status = inb_p(I2C_REG(status));
3332+
3333+ if (cobt_is_3k()) {
3334+ if (status & I2C_3K_STATUS_IDLE) {
3335+ return 0;
3336+ }
3337+ } else if (cobt_is_5k()) {
3338+ if (!(status & I2C_5K_HOST_STATUS_BUSY)) {
3339+ return 0;
3340+ }
3341+ }
3342+ outb_p(status, I2C_REG(status));
3343+ }
3344+
3345+ /* still busy - complain */
3346+ if (!i2c_noisy()) {
3347+ if (++shutup > 2) {
3348+ EPRINTK("i2c seems to be dead - sorry\n");
3349+ set_bit(I2C_DEAD, &i2c_state);
3350+ } else {
3351+ WPRINTK("i2c timeout: status busy (0x%x), resetting\n",
3352+ status);
3353+ }
3354+ }
3355+
3356+ /* punch the abort bit */
3357+ if (cobt_is_3k()) {
3358+ outb_p(4, i2c_data->io_port + I2C_3K_CMD);
3359+ } else if (cobt_is_5k()) {
3360+ outb_p(2, i2c_data->io_port + I2C_5K_HOST_CONTROL);
3361+ outb_p(1, i2c_data->io_port + I2C_5K_HOST_CONTROL);
3362+ }
3363+
3364+ return -1;
3365+}
3366+
3367+static inline int
3368+i2c_setup(const int dev, const int index, const int r)
3369+{
3370+ if (i2c_wait_for_smi() < 0)
3371+ return -1;
3372+
3373+ /* clear status */
3374+ outb_p(0xff, I2C_REG(status));
3375+
3376+ /* device address */
3377+ outb_p((dev|r) & 0xff, I2C_REG(addr));
3378+
3379+ /* I2C index */
3380+ outb_p(index & 0xff, I2C_REG(index));
3381+
3382+ return 0;
3383+}
3384+
3385+static inline int
3386+i2c_cmd(const unsigned char command)
3387+{
3388+ if (cobt_is_3k()) {
3389+ outb_p(command, i2c_data->io_port + I2C_3K_CMD);
3390+ outb_p(0xff, i2c_data->io_port + I2C_3K_START);
3391+ } else if (cobt_is_5k()) {
3392+ outb_p(I2C_5K_HOST_CMD_START | command,
3393+ i2c_data->io_port + I2C_5K_HOST_CONTROL);
3394+ }
3395+
3396+ if (i2c_wait_for_smi() < 0)
3397+ return -1;
3398+
3399+ return 0;
3400+}
3401+
3402+int
3403+cobalt_i2c_init(void)
3404+{
3405+ struct pci_dev *i2cdev = NULL;
3406+
3407+ if( ! initialized ) {
3408+ if (cobt_is_3k()) {
3409+ i2c_data = &cobalt_i2c_3k;
3410+ i2cdev = pci_find_device(PCI_VENDOR_ID_AL,
3411+ PCI_DEVICE_ID_AL_M7101, NULL);
3412+ if (!i2cdev) {
3413+ EPRINTK("can't find PMU for i2c access\n");
3414+ return -1;
3415+ }
3416+ pci_read_config_dword(i2cdev, 0x14, &i2c_data->io_port);
3417+ } else if (cobt_is_5k()) {
3418+ i2c_data = &cobalt_i2c_5k;
3419+ i2cdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
3420+ PCI_DEVICE_ID_SERVERWORKS_OSB4, i2cdev);
3421+ if (!i2cdev) {
3422+ i2cdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
3423+ PCI_DEVICE_ID_SERVERWORKS_CSB5, i2cdev);
3424+ if (!i2cdev) {
3425+ EPRINTK("can't find OSB4 or CSB5 for i2c access\n");
3426+ return -1;
3427+ }
3428+ }
3429+ pci_read_config_dword(i2cdev, 0x90, &i2c_data->io_port);
3430+ }
3431+
3432+ i2c_data->io_port &= 0xfff0;
3433+ if (!i2c_data->io_port) {
3434+ EPRINTK("i2c IO port not found\n");
3435+ }
3436+ initialized = 1;
3437+ }
3438+
3439+ return 0;
3440+}
3441+
3442+int
3443+cobalt_i2c_reset(void)
3444+{
3445+ int r;
3446+
3447+ if( !initialized ) {
3448+ if( cobalt_i2c_init() < 0 )
3449+ return -1;
3450+ }
3451+
3452+ if (do_i2c_lock() < 0)
3453+ return -1;
3454+
3455+ if (cobt_is_3k()) {
3456+ /* clear status */
3457+ outb_p(0xff, i2c_data->io_port + I2C_3K_STATUS);
3458+ /* reset SMB devs */
3459+ outb_p(0x08, i2c_data->io_port + I2C_3K_CMD);
3460+ /* start command */
3461+ outb_p(0xff, i2c_data->io_port + I2C_3K_START);
3462+ } else if (cobt_is_5k()) {
3463+ /* clear status */
3464+ outb_p(0x2, i2c_data->io_port + I2C_5K_HOST_CONTROL);
3465+ outb_p(0x1, i2c_data->io_port + I2C_5K_HOST_CONTROL);
3466+ outb_p(0xff, i2c_data->io_port + I2C_5K_HOST_STATUS);
3467+ outb_p(I2C_5K_HOST_CMD_START | 0x08,
3468+ i2c_data->io_port + I2C_5K_HOST_CONTROL);
3469+ }
3470+
3471+ r = i2c_wait_for_smi();
3472+
3473+ do_i2c_unlock();
3474+
3475+ return r;
3476+}
3477+
3478+int
3479+cobalt_i2c_read_byte(const int dev, const int index)
3480+{
3481+ int val = 0;
3482+
3483+ if( !initialized ) {
3484+ if( cobalt_i2c_init() < 0 )
3485+ return -1;
3486+ }
3487+
3488+ if (do_i2c_lock() < 0)
3489+ return -1;
3490+
3491+ if (i2c_setup(dev, index, I2C_READ) < 0
3492+ || i2c_cmd(I2C_CMD(rw_byte)) < 0) {
3493+ val = -1;
3494+ }
3495+
3496+ if (val == 0) {
3497+ val = inb_p(I2C_REG(data_low));
3498+ }
3499+
3500+ do_i2c_unlock();
3501+
3502+ return val;
3503+}
3504+
3505+int
3506+cobalt_i2c_read_word(const int dev, const int index)
3507+{
3508+ int val = 0;
3509+
3510+ if( !initialized ) {
3511+ if( cobalt_i2c_init() < 0 )
3512+ return -1;
3513+ }
3514+
3515+ if (do_i2c_lock() < 0)
3516+ return -1;
3517+
3518+ if (i2c_setup(dev, index, I2C_READ) < 0
3519+ || i2c_cmd(I2C_CMD(rw_word)) < 0) {
3520+ val = -1;
3521+ }
3522+
3523+ if (val == 0) {
3524+ val = inb_p(I2C_REG(data_low));
3525+ val += inb_p(I2C_REG(data_high)) << 8;
3526+ }
3527+
3528+ do_i2c_unlock();
3529+
3530+ return val;
3531+}
3532+
3533+int
3534+cobalt_i2c_read_block(const int dev, const int index,
3535+ unsigned char *data, int count)
3536+{
3537+ if( !initialized ) {
3538+ if( cobalt_i2c_init() < 0 )
3539+ return -1;
3540+ }
3541+
3542+ if (do_i2c_lock() < 0)
3543+ return -1;
3544+
3545+ if (i2c_setup(dev, index, I2C_READ) < 0) {
3546+ do_i2c_unlock();
3547+ return -1;
3548+ }
3549+
3550+ outb_p(count & 0xff, I2C_REG(data_low));
3551+ outb_p(count & 0xff, I2C_REG(data_high));
3552+
3553+ if (i2c_cmd(I2C_CMD(rw_block)) < 0) {
3554+ do_i2c_unlock();
3555+ return -1;
3556+ }
3557+
3558+ while (count) {
3559+ /* read a byte of block data */
3560+ *data = inb_p(I2C_REG(data_block));
3561+ data++;
3562+ count--;
3563+ }
3564+
3565+ do_i2c_unlock();
3566+
3567+ return 0;
3568+}
3569+
3570+int
3571+cobalt_i2c_write_byte(const int dev, const int index, const u8 val)
3572+{
3573+ int r = 0;
3574+
3575+ if( !initialized ) {
3576+ if( cobalt_i2c_init() < 0 )
3577+ return -1;
3578+ }
3579+
3580+ if (do_i2c_lock() < 0)
3581+ return -1;
3582+
3583+ if (i2c_setup(dev, index, I2C_WRITE) < 0) {
3584+ r = -1;
3585+ }
3586+
3587+ if (r == 0) {
3588+ outb_p(val & 0xff, I2C_REG(data_low));
3589+
3590+ if (i2c_cmd(I2C_CMD(rw_byte)) < 0) {
3591+ r = -1;
3592+ }
3593+ }
3594+
3595+ udelay(I2C_WRITE_UDELAY);
3596+
3597+ do_i2c_unlock();
3598+
3599+ return r;
3600+}
3601+
3602+int
3603+cobalt_i2c_write_word(const int dev, const int index, const u16 val)
3604+{
3605+ int r = 0;
3606+
3607+ if( !initialized ) {
3608+ if( cobalt_i2c_init() < 0 )
3609+ return -1;
3610+ }
3611+
3612+ if (do_i2c_lock() < 0)
3613+ return -1;
3614+
3615+ if (i2c_setup(dev, index, I2C_WRITE) < 0) {
3616+ r = -1;
3617+ }
3618+
3619+ if (r == 0) {
3620+ outb_p(val & 0xff, I2C_REG(data_low));
3621+ outb_p((val >> 8) & 0xff, I2C_REG(data_high));
3622+
3623+ if (i2c_cmd(I2C_CMD(rw_word)) < 0) {
3624+ r = -1;
3625+ }
3626+ }
3627+
3628+ udelay(I2C_WRITE_UDELAY);
3629+
3630+ do_i2c_unlock();
3631+
3632+ return r;
3633+}
3634+
3635+int
3636+cobalt_i2c_write_block(int dev, int index, unsigned char *data, int count)
3637+{
3638+ if( !initialized ) {
3639+ if( cobalt_i2c_init() < 0 )
3640+ return -1;
3641+ }
3642+
3643+ if (do_i2c_lock() < 0)
3644+ return -1;
3645+
3646+ if (i2c_setup(dev, index, I2C_WRITE) < 0) {
3647+ do_i2c_unlock();
3648+ return -1;
3649+ }
3650+
3651+ outb_p(count & 0xff, I2C_REG(data_low));
3652+ outb_p(count & 0xff, I2C_REG(data_high));
3653+
3654+ if (i2c_cmd(I2C_CMD(rw_block)) < 0) {
3655+ do_i2c_unlock();
3656+ return -1;
3657+ }
3658+
3659+ while (count) {
3660+ /* write a byte of block data */
3661+ outb_p(*data, I2C_REG(data_block));
3662+ data++;
3663+ count--;
3664+ }
3665+
3666+ udelay(I2C_WRITE_UDELAY);
3667+
3668+ do_i2c_unlock();
3669+
3670+ return 0;
3671+}
3672+
3673+EXPORT_SYMBOL(cobalt_i2c_reset);
3674+EXPORT_SYMBOL(cobalt_i2c_read_byte);
3675+EXPORT_SYMBOL(cobalt_i2c_read_word);
3676+EXPORT_SYMBOL(cobalt_i2c_read_block);
3677+EXPORT_SYMBOL(cobalt_i2c_write_byte);
3678+EXPORT_SYMBOL(cobalt_i2c_write_word);
3679+EXPORT_SYMBOL(cobalt_i2c_write_block);
3680diff -Naur linux-2.6.18.2.orig/drivers/cobalt/init.c linux-2.6.18.2/drivers/cobalt/init.c
3681--- linux-2.6.18.2.orig/drivers/cobalt/init.c 1969-12-31 16:00:00.000000000 -0800
3682+++ linux-2.6.18.2/drivers/cobalt/init.c 2006-11-15 21:20:19.738033319 -0800
3683@@ -0,0 +1,114 @@
3684+/* $Id: init.c,v 1.22 2002/11/04 17:54:15 thockin Exp $ */
3685+/*
3686+ * Copyright (c) 2001 Sun Microsystems
3687+ * Generic initialization, to reduce pollution of other files
3688+ */
3689+#include <linux/config.h>
3690+#include <linux/module.h>
3691+#include <linux/stddef.h>
3692+#include <linux/version.h>
3693+#include <linux/types.h>
3694+#include <linux/init.h>
3695+#include <linux/proc_fs.h>
3696+#include <cobalt/cobalt.h>
3697+
3698+static int cobalt_proc_init(void);
3699+extern int cobalt_i2c_init(void);
3700+extern int cobalt_net_init(void);
3701+extern int cobalt_systype_init(void);
3702+extern void cobalt_boardrev_init(void);
3703+extern int cobalt_led_init(void);
3704+extern int cobalt_lcd_init(void);
3705+extern int cobalt_serialnum_init(void);
3706+extern int cobalt_wdt_init(void);
3707+extern int cobalt_sensors_init(void);
3708+extern int cobalt_fan_init(void);
3709+extern int cobalt_acpi_init(void);
3710+extern int cobalt_ruler_init(void);
3711+extern int cobalt_raminfo_init(void);
3712+
3713+#ifdef CONFIG_PROC_FS
3714+struct proc_dir_entry *proc_cobalt;
3715+EXPORT_SYMBOL(proc_cobalt);
3716+#endif
3717+spinlock_t cobalt_superio_lock = SPIN_LOCK_UNLOCKED;
3718+
3719+/* initialize all the cobalt specific stuff */
3720+int __init
3721+cobalt_init(void)
3722+{
3723+ cobalt_proc_init();
3724+ cobalt_systype_init();
3725+#ifdef CONFIG_COBALT_RAQ
3726+ /* we might keep the boardrev on an i2c chip */
3727+ cobalt_i2c_init();
3728+#endif
3729+ cobalt_boardrev_init();
3730+#ifdef CONFIG_COBALT_ACPI
3731+ cobalt_acpi_init();
3732+#endif
3733+#ifdef CONFIG_COBALT_LED
3734+ cobalt_net_init();
3735+ cobalt_led_init();
3736+#endif
3737+#ifdef CONFIG_COBALT_LCD
3738+ cobalt_lcd_init();
3739+#endif
3740+#ifdef CONFIG_COBALT_RULER
3741+ cobalt_ruler_init();
3742+#endif
3743+#ifdef CONFIG_COBALT_SERNUM
3744+ cobalt_serialnum_init();
3745+#endif
3746+#ifdef CONFIG_COBALT_RAQ
3747+ /* some systems use WDT it for reboot */
3748+ cobalt_wdt_init();
3749+#endif
3750+#ifdef CONFIG_COBALT_SENSORS
3751+ cobalt_sensors_init();
3752+#endif
3753+#ifdef CONFIG_COBALT_FANS
3754+ cobalt_fan_init();
3755+#endif
3756+#ifdef CONFIG_COBALT_RAMINFO
3757+ cobalt_raminfo_init();
3758+#endif
3759+ return 0;
3760+}
3761+
3762+static int __init
3763+cobalt_proc_init(void)
3764+{
3765+#ifdef CONFIG_PROC_FS
3766+ proc_cobalt = proc_mkdir("cobalt", 0);
3767+ if (!proc_cobalt) {
3768+ EPRINTK("can't create /proc/cobalt\n");
3769+ return -1;
3770+ }
3771+#endif
3772+
3773+ return 0;
3774+}
3775+
3776+/* a function that handles the blah stuff in a simple proc read function */
3777+int
3778+cobalt_gen_proc_read(char *buf, int plen, char **start, off_t pos,
3779+ int len, int *eof)
3780+{
3781+ /* trying to read a bad offset? */
3782+ if (pos >= plen) {
3783+ *eof = 1;
3784+ return 0;
3785+ }
3786+
3787+ /* did we write everything we wanted to? */
3788+ if (len >= (plen-pos)) {
3789+ *eof = 1;
3790+ }
3791+
3792+ *start = buf + pos;
3793+ plen -= pos;
3794+
3795+ return (len > plen) ? plen : len;
3796+}
3797+EXPORT_SYMBOL(cobalt_gen_proc_read);
3798diff -Naur linux-2.6.18.2.orig/drivers/cobalt/lcd.c linux-2.6.18.2/drivers/cobalt/lcd.c
3799--- linux-2.6.18.2.orig/drivers/cobalt/lcd.c 1969-12-31 16:00:00.000000000 -0800
3800+++ linux-2.6.18.2/drivers/cobalt/lcd.c 2006-11-15 21:20:19.738033319 -0800
3801@@ -0,0 +1,835 @@
3802+/*
3803+ * $Id: lcd.c,v 1.44 2002/05/10 18:44:45 duncan Exp $
3804+ * lcd.c : driver for Cobalt LCD/Buttons
3805+ *
3806+ * Copyright 1996-2000 Cobalt Networks, Inc.
3807+ * Copyright 2001 Sun Microsystems, Inc.
3808+ *
3809+ * By: Andrew Bose
3810+ * Timothy Stonis
3811+ * Tim Hockin
3812+ * Adrian Sun
3813+ * Duncan Laurie
3814+ *
3815+ * Modified By: jeff@404ster.com
3816+ *
3817+ * This should be SMP safe. We're hardly performance critical,
3818+ * so we lock around lcd_ioctl() and just where needed by other external
3819+ * functions. There is a static global waiters variable that is atomic_t, and
3820+ * so should be safe. --TPH
3821+ */
3822+
3823+#include <linux/config.h>
3824+
3825+#ifdef CONFIG_COBALT_LCD
3826+
3827+#include <linux/module.h>
3828+#include <linux/types.h>
3829+#include <linux/errno.h>
3830+#include <linux/miscdevice.h>
3831+#include <linux/slab.h>
3832+#include <linux/ioport.h>
3833+#include <linux/fcntl.h>
3834+#include <linux/stat.h>
3835+#include <linux/netdevice.h>
3836+#include <linux/proc_fs.h>
3837+#include <linux/in6.h>
3838+#include <linux/pci.h>
3839+#include <linux/init.h>
3840+#include <linux/timer.h>
3841+#include <linux/kernel.h>
3842+
3843+#include <asm/io.h>
3844+#include <asm/segment.h>
3845+#include <asm/system.h>
3846+#include <asm/uaccess.h>
3847+#include <asm/checksum.h>
3848+#include <linux/delay.h>
3849+
3850+#include <cobalt/cobalt.h>
3851+#include <cobalt/systype.h>
3852+#include <cobalt/lcd.h>
3853+#include <cobalt/superio.h>
3854+#include <cobalt/i2c.h>
3855+
3856+#define TWIDDLE_HZ (HZ/10)
3857+
3858+#ifndef min
3859+#define min(a, b) ((a) < (b) ? (a) : (b))
3860+#endif
3861+
3862+#define LCD_DRIVER "Cobalt Networks LCD driver"
3863+#define LCD_DRIVER_VMAJ 4
3864+#define LCD_DRIVER_VMIN 0
3865+
3866+/* io registers */
3867+#define LPT 0x0378
3868+#define LCD_DATA_ADDRESS LPT+0
3869+#define LCD_CONTROL_ADDRESS LPT+2
3870+
3871+/* LCD device info */
3872+#define LCD_Addr 0x80
3873+#define DD_R00 0x00
3874+#define DD_R01 0x27
3875+#define DD_R10 0x40
3876+#define DD_R11 0x67
3877+
3878+/* driver functions */
3879+static int cobalt_lcd_open(struct inode *, struct file *);
3880+static ssize_t cobalt_lcd_read(struct file *, char *, size_t, loff_t *);
3881+static int cobalt_lcd_read_proc(char *, char **, off_t, int, int *, void *);
3882+static char *cobalt_lcddev_read_line(int, char *);
3883+static int cobalt_lcd_ioctl(struct inode *, struct file *,
3884+ unsigned int, unsigned long);
3885+static int cobalt_lcd_panic(struct notifier_block *self, unsigned long, void *);
3886+
3887+/* globals used throughout */
3888+#ifdef CONFIG_PROC_FS
3889+#ifdef CONFIG_COBALT_OLDPROC
3890+static struct proc_dir_entry *proc_lcd;
3891+#endif
3892+static struct proc_dir_entry *proc_clcd;
3893+#endif
3894+static int lcd_present;
3895+static int has_i2c_lcd;
3896+static spinlock_t lcd_lock = SPIN_LOCK_UNLOCKED;
3897+
3898+/* various file operations we support for this driver */
3899+static struct file_operations lcd_fops = {
3900+ .read = cobalt_lcd_read,
3901+ .ioctl = cobalt_lcd_ioctl,
3902+ .open = cobalt_lcd_open,
3903+};
3904+
3905+/* device structure */
3906+static struct miscdevice lcd_dev = {
3907+ MISC_DYNAMIC_MINOR,
3908+ "lcd",
3909+ &lcd_fops
3910+};
3911+
3912+static int disable_lcd;
3913+static int __init
3914+lcd_disable_setup(char *str)
3915+{
3916+ disable_lcd = 1;
3917+ return 0;
3918+}
3919+__setup("nolcd", lcd_disable_setup);
3920+
3921+/* Read a control instruction from the LCD */
3922+static inline int
3923+lcddev_read_inst(void)
3924+{
3925+ int a = 0;
3926+
3927+ if (cobt_is_5k() && has_i2c_lcd) {
3928+ a = cobalt_i2c_read_byte(
3929+ COBALT_I2C_DEV_LCD_INST | COBALT_I2C_READ, 0);
3930+ } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) {
3931+ outb(0x21, LCD_CONTROL_ADDRESS); /* RS=0, R/W=1, E=0 */
3932+ outb(0x20, LCD_CONTROL_ADDRESS); /* RS=0, R/W=1, E=1 */
3933+ a = inb(LCD_DATA_ADDRESS);
3934+ outb(0x21, LCD_CONTROL_ADDRESS); /* RS=0, R/W=1, E=0 */
3935+ outb(0x01, LCD_CONTROL_ADDRESS); /* RS=0, R/W=1, E=0 */
3936+ }
3937+
3938+ /* small delay */
3939+ udelay(100);
3940+
3941+ return a;
3942+}
3943+
3944+#define LCD_MAX_POLL 10000
3945+static inline void
3946+lcddev_poll_wait(void)
3947+{
3948+ int i=0;
3949+
3950+ while (i++ < LCD_MAX_POLL) {
3951+ int r = lcddev_read_inst();
3952+ if (r < 0 || !(r & 0x80))
3953+ break;
3954+ }
3955+}
3956+
3957+/* Write a control instruction to the LCD */
3958+static inline void
3959+lcddev_write_inst(unsigned char data)
3960+{
3961+ lcddev_poll_wait();
3962+
3963+ if (cobt_is_5k() && has_i2c_lcd) {
3964+ cobalt_i2c_write_byte(
3965+ COBALT_I2C_DEV_LCD_INST | COBALT_I2C_WRITE, 0, data);
3966+ } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) {
3967+ outb(0x03, LCD_CONTROL_ADDRESS); /* RS=0, R/W=0, E=0 */
3968+ outb(data, LCD_DATA_ADDRESS);
3969+ outb(0x02, LCD_CONTROL_ADDRESS); /* RS=0, R/W=0, E=1 */
3970+ outb(0x03, LCD_CONTROL_ADDRESS); /* RS=0, R/W=0, E=0 */
3971+ outb(0x01, LCD_CONTROL_ADDRESS); /* RS=0, R/W=1, E=0 */
3972+ }
3973+
3974+ /* small delay */
3975+ udelay(100);
3976+}
3977+
3978+/* Write one byte of data to the LCD */
3979+static inline void
3980+lcddev_write_data(unsigned char data)
3981+{
3982+ lcddev_poll_wait();
3983+
3984+ if (cobt_is_5k() && has_i2c_lcd) {
3985+ cobalt_i2c_write_byte(
3986+ COBALT_I2C_DEV_LCD_DATA | COBALT_I2C_WRITE, 0, data);
3987+ } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) {
3988+ outb(0x07, LCD_CONTROL_ADDRESS); /* RS=1, R/W=0, E=0 */
3989+ outb(data, LCD_DATA_ADDRESS);
3990+ outb(0x06, LCD_CONTROL_ADDRESS); /* RS=1, R/W=0, E=1 */
3991+ outb(0x07, LCD_CONTROL_ADDRESS); /* RS=1, R/W=0, E=0 */
3992+ outb(0x05, LCD_CONTROL_ADDRESS); /* RS=1, R/W=1, E=0 */
3993+ }
3994+ /* small delay */
3995+ udelay(100);
3996+}
3997+
3998+/* Read one byte of data from the LCD */
3999+static inline unsigned char
4000+lcddev_read_data(void)
4001+{
4002+ unsigned char a = 0;
4003+
4004+ lcddev_poll_wait();
4005+
4006+ if (cobt_is_5k() && has_i2c_lcd) {
4007+ a = cobalt_i2c_read_byte(
4008+ COBALT_I2C_DEV_LCD_DATA | COBALT_I2C_READ, 0);
4009+ } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) {
4010+ outb(0x25, LCD_CONTROL_ADDRESS); /* RS=1, R/W=1, E=0 */
4011+ outb(0x24, LCD_CONTROL_ADDRESS); /* RS=1, R/W=1, E=1 */
4012+ a = inb(LCD_DATA_ADDRESS);
4013+ outb(0x25, LCD_CONTROL_ADDRESS); /* RS=1, R/W=1, E=0 */
4014+ outb(0x01, LCD_CONTROL_ADDRESS); /* RS=1, R/W=1, E=0 */
4015+ }
4016+
4017+ /* small delay */
4018+ udelay(100);
4019+
4020+ return a;
4021+}
4022+
4023+static inline void
4024+lcddev_init(void)
4025+{
4026+ lcddev_write_inst(0x38);
4027+ lcddev_write_inst(0x38);
4028+ lcddev_write_inst(0x38);
4029+ lcddev_write_inst(0x06);
4030+ lcddev_write_inst(0x0c);
4031+}
4032+
4033+static inline char
4034+read_buttons(void)
4035+{
4036+ char r = 0;
4037+
4038+ if (cobt_is_5k() && has_i2c_lcd) {
4039+ unsigned char inst;
4040+ inst = cobalt_i2c_read_byte(COBALT_I2C_DEV_FP_BUTTONS, 0);
4041+ switch (inst) {
4042+ case 0x3e: r = BUTTON_Next_B; break;
4043+ case 0x3d: r = BUTTON_Enter_B; break;
4044+ case 0x1f: r = BUTTON_Left_B; break;
4045+ case 0x3b: r = BUTTON_Right_B; break;
4046+ case 0x2f: r = BUTTON_Up_B; break;
4047+ case 0x37: r = BUTTON_Down_B; break;
4048+ case 0x3f:
4049+ default: r = BUTTON_NONE_B;
4050+ }
4051+ } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) {
4052+ outb(0x29, LCD_CONTROL_ADDRESS); /* Sel=0, Bi=1 */
4053+ r = inb(LCD_DATA_ADDRESS) & BUTTON_MASK;
4054+ }
4055+
4056+ return r;
4057+}
4058+
4059+static inline int
4060+button_pressed(void)
4061+{
4062+ unsigned char b;
4063+ unsigned long flags;
4064+
4065+ spin_lock_irqsave(&lcd_lock, flags);
4066+ b = read_buttons();
4067+ spin_unlock_irqrestore(&lcd_lock, flags);
4068+
4069+ switch (b) {
4070+ case BUTTON_Next:
4071+ case BUTTON_Next_B:
4072+ case BUTTON_Reset_B:
4073+ return b;
4074+ default:
4075+ break;
4076+ }
4077+
4078+ return 0;
4079+}
4080+
4081+/* this could be protected by CAP_RAW_IO here, or by the FS permissions */
4082+static int
4083+cobalt_lcd_ioctl(struct inode *inode, struct file *file,
4084+ unsigned int cmd, unsigned long arg)
4085+{
4086+ struct lcd_display button_display, display;
4087+ unsigned long address, a;
4088+ int index;
4089+ int dlen = sizeof(struct lcd_display);
4090+ int r = 0;
4091+ unsigned long flags;
4092+
4093+#ifdef CONFIG_COBALT_LCD_TWIDDLE
4094+ cobalt_lcd_stop_twiddle();
4095+#endif
4096+ switch (cmd) {
4097+ /* Turn the LCD on */
4098+ case LCD_On:
4099+ spin_lock_irqsave(&lcd_lock, flags);
4100+ lcddev_write_inst(0x0F);
4101+ spin_unlock_irqrestore(&lcd_lock, flags);
4102+ break;
4103+
4104+ /* Turn the LCD off */
4105+ case LCD_Off:
4106+ spin_lock_irqsave(&lcd_lock, flags);
4107+ lcddev_write_inst(0x08);
4108+ spin_unlock_irqrestore(&lcd_lock, flags);
4109+ break;
4110+
4111+ /* Reset the LCD */
4112+ case LCD_Reset:
4113+ spin_lock_irqsave(&lcd_lock, flags);
4114+ lcddev_write_inst(0x3F);
4115+ lcddev_write_inst(0x3F);
4116+ lcddev_write_inst(0x3F);
4117+ lcddev_write_inst(0x3F);
4118+ lcddev_write_inst(0x01);
4119+ lcddev_write_inst(0x06);
4120+ spin_unlock_irqrestore(&lcd_lock, flags);
4121+ break;
4122+
4123+ /* Clear the LCD */
4124+ case LCD_Clear:
4125+ spin_lock_irqsave(&lcd_lock, flags);
4126+ lcddev_write_inst(0x01);
4127+ spin_unlock_irqrestore(&lcd_lock, flags);
4128+ break;
4129+
4130+ /* Move the cursor one position to the left */
4131+ case LCD_Cursor_Left:
4132+ spin_lock_irqsave(&lcd_lock, flags);
4133+ lcddev_write_inst(0x10);
4134+ spin_unlock_irqrestore(&lcd_lock, flags);
4135+ break;
4136+
4137+ /* Move the cursor one position to the right */
4138+ case LCD_Cursor_Right:
4139+ spin_lock_irqsave(&lcd_lock, flags);
4140+ lcddev_write_inst(0x14);
4141+ spin_unlock_irqrestore(&lcd_lock, flags);
4142+ break;
4143+
4144+ /* Turn the cursor off */
4145+ case LCD_Cursor_Off:
4146+ spin_lock_irqsave(&lcd_lock, flags);
4147+ lcddev_write_inst(0x0C);
4148+ spin_unlock_irqrestore(&lcd_lock, flags);
4149+ break;
4150+
4151+ /* Turn the cursor on */
4152+ case LCD_Cursor_On:
4153+ spin_lock_irqsave(&lcd_lock, flags);
4154+ lcddev_write_inst(0x0F);
4155+ spin_unlock_irqrestore(&lcd_lock, flags);
4156+ break;
4157+
4158+ /* Turn blinking off? I don't know what this does - TJS */
4159+ case LCD_Blink_Off:
4160+ spin_lock_irqsave(&lcd_lock, flags);
4161+ lcddev_write_inst(0x0E);
4162+ spin_unlock_irqrestore(&lcd_lock, flags);
4163+ break;
4164+
4165+ /* Get the current cursor position */
4166+ case LCD_Get_Cursor_Pos:
4167+ spin_lock_irqsave(&lcd_lock, flags);
4168+ display.cursor_address = (unsigned char)lcddev_read_inst();
4169+ display.cursor_address = display.cursor_address & 0x07F;
4170+ spin_unlock_irqrestore(&lcd_lock, flags);
4171+ if (copy_to_user((struct lcd_display *)arg, &display, dlen)) {
4172+ r = -EFAULT;
4173+ }
4174+ break;
4175+
4176+ /* Set the cursor position */
4177+ case LCD_Set_Cursor_Pos:
4178+ if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) {
4179+ r = -EFAULT;
4180+ break;
4181+ }
4182+ a = display.cursor_address | LCD_Addr;
4183+ spin_lock_irqsave(&lcd_lock, flags);
4184+ lcddev_write_inst(a);
4185+ spin_unlock_irqrestore(&lcd_lock, flags);
4186+ break;
4187+
4188+ /* Get the value at the current cursor position? - TJS */
4189+ case LCD_Get_Cursor:
4190+ spin_lock_irqsave(&lcd_lock, flags);
4191+ display.character = lcddev_read_data();
4192+ lcddev_write_inst(0x10);
4193+ spin_unlock_irqrestore(&lcd_lock, flags);
4194+ if (copy_to_user((struct lcd_display *)arg, &display, dlen)) {
4195+ r = -EFAULT;
4196+ }
4197+ break;
4198+
4199+ /* Set the character at the cursor position? - TJS */
4200+ case LCD_Set_Cursor:
4201+ if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) {
4202+ r = -EFAULT;
4203+ break;
4204+ }
4205+ spin_lock_irqsave(&lcd_lock, flags);
4206+ lcddev_write_data(display.character);
4207+ lcddev_write_inst(0x10);
4208+ spin_unlock_irqrestore(&lcd_lock, flags);
4209+ break;
4210+
4211+ /* Dunno what this does - TJS */
4212+ case LCD_Disp_Left:
4213+ spin_lock_irqsave(&lcd_lock, flags);
4214+ lcddev_write_inst(0x18);
4215+ spin_unlock_irqrestore(&lcd_lock, flags);
4216+ break;
4217+
4218+ /* Dunno what this does - TJS */
4219+ case LCD_Disp_Right:
4220+ spin_lock_irqsave(&lcd_lock, flags);
4221+ lcddev_write_inst(0x1C);
4222+ spin_unlock_irqrestore(&lcd_lock, flags);
4223+ break;
4224+
4225+ /* Dunno what this does - TJS */
4226+ case LCD_Home:
4227+ spin_lock_irqsave(&lcd_lock, flags);
4228+ lcddev_write_inst(0x02);
4229+ spin_unlock_irqrestore(&lcd_lock, flags);
4230+ break;
4231+
4232+ /* Write a string to the LCD */
4233+ case LCD_Write:
4234+ if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) {
4235+ r = -EFAULT;
4236+ break;
4237+ }
4238+
4239+ spin_lock_irqsave(&lcd_lock, flags);
4240+
4241+ display.size1 = display.size1 > 0 ?
4242+ min(display.size1, (int) sizeof(display.line1)) : 0;
4243+ display.size2 = display.size2 > 0 ?
4244+ min(display.size2, (int) sizeof(display.line2)) : 0;
4245+
4246+ /* First line */
4247+ lcddev_write_inst(0x80);
4248+ for (index = 0; index < display.size1; index++)
4249+ lcddev_write_data(display.line1[index]);
4250+ for (index = display.size1; index < sizeof(display.line1); index++)
4251+ lcddev_write_data(' ');
4252+
4253+ /* Second line */
4254+ lcddev_write_inst(0xC0);
4255+ for (index = 0; index < display.size2; index++)
4256+ lcddev_write_data(display.line2[index]);
4257+ for (index = display.size2; index < sizeof(display.line2); index++)
4258+ lcddev_write_data(' ');
4259+
4260+ spin_unlock_irqrestore(&lcd_lock, flags);
4261+ break;
4262+
4263+ /* Read what's on the LCD */
4264+ case LCD_Read:
4265+ spin_lock_irqsave(&lcd_lock, flags);
4266+
4267+ for (address = DD_R00; address <= DD_R01; address++) {
4268+ lcddev_write_inst(address | LCD_Addr);
4269+ display.line1[address] = lcddev_read_data();
4270+ }
4271+ for (address = DD_R10; address <= DD_R11; address++) {
4272+ lcddev_write_inst(address | LCD_Addr);
4273+ display.line2[address - DD_R10] = lcddev_read_data();
4274+ }
4275+
4276+ spin_unlock_irqrestore(&lcd_lock, flags);
4277+
4278+ display.line1[DD_R01] = '\0';
4279+ display.line2[DD_R01] = '\0';
4280+
4281+ if (copy_to_user((struct lcd_display *)arg, &display, dlen)) {
4282+ r = -EFAULT;
4283+ }
4284+ break;
4285+
4286+ case LCD_Raw_Inst:
4287+ if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) {
4288+ r = -EFAULT;
4289+ break;
4290+ }
4291+ spin_lock_irqsave(&lcd_lock, flags);
4292+ lcddev_write_inst(display.character);
4293+ spin_unlock_irqrestore(&lcd_lock, flags);
4294+ break;
4295+
4296+ case LCD_Raw_Data:
4297+ if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) {
4298+ r = -EFAULT;
4299+ break;
4300+ }
4301+ spin_lock_irqsave(&lcd_lock, flags);
4302+ lcddev_write_data(display.character);
4303+ spin_unlock_irqrestore(&lcd_lock, flags);
4304+ break;
4305+
4306+ case LCD_Type:
4307+ if (cobt_is_5k() && has_i2c_lcd) {
4308+ if (put_user(LCD_TYPE_I2C, (int *)arg)) {
4309+ r = -EFAULT;
4310+ }
4311+ } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) {
4312+ if (put_user(LCD_TYPE_PARALLEL_B, (int *)arg)) {
4313+ r = -EFAULT;
4314+ }
4315+ }
4316+ break;
4317+
4318+ /* Read the buttons */
4319+ case BUTTON_Read:
4320+ spin_lock_irqsave(&lcd_lock, flags);
4321+ button_display.buttons = read_buttons();
4322+ spin_unlock_irqrestore(&lcd_lock, flags);
4323+ if (copy_to_user((struct lcd_display *)arg,
4324+ &button_display, dlen)) {
4325+ r = -EFAULT;
4326+ }
4327+ break;
4328+
4329+#ifdef CONFIG_COBALT_LED
4330+ /* a slightly different api that allows you to set 32 leds */
4331+ case LED32_Set:
4332+ cobalt_led_set_lazy(arg);
4333+ break;
4334+
4335+ case LED32_Bit_Set:
4336+ cobalt_led_set_bits_lazy(arg);
4337+ break;
4338+
4339+ case LED32_Bit_Clear:
4340+ cobalt_led_clear_bits_lazy(arg);
4341+ break;
4342+
4343+ case LED32_Get:
4344+ *(unsigned int *)arg = cobalt_led_get();
4345+ break;
4346+
4347+ /* set all the leds */
4348+ case LED_Set:
4349+ if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) {
4350+ r = -EFAULT;
4351+ break;
4352+ }
4353+ cobalt_led_set_lazy(display.leds);
4354+ break;
4355+
4356+ /* set a single led */
4357+ case LED_Bit_Set:
4358+ if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) {
4359+ r = -EFAULT;
4360+ break;
4361+ }
4362+ cobalt_led_set_bits_lazy(display.leds);
4363+ break;
4364+
4365+ /* clear an led */
4366+ case LED_Bit_Clear:
4367+ if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) {
4368+ r = -EFAULT;
4369+ break;
4370+ }
4371+ cobalt_led_clear_bits_lazy(display.leds);
4372+ break;
4373+#endif
4374+
4375+ default:
4376+ break;
4377+ }
4378+
4379+ return r;
4380+}
4381+
4382+static int
4383+cobalt_lcd_open(struct inode *inode, struct file *file)
4384+{
4385+ if (!lcd_present) {
4386+ return -ENXIO;
4387+ } else {
4388+ return 0;
4389+ }
4390+}
4391+
4392+/* LCD daemon sits on this, we wake it up once a key is pressed */
4393+static ssize_t
4394+cobalt_lcd_read(struct file *file, char *buf, size_t count, loff_t *ppos)
4395+{
4396+ int bnow;
4397+ static unsigned long lcd_waiters;
4398+
4399+ if (test_and_set_bit(0, &lcd_waiters)) {
4400+ return -EINVAL;
4401+ }
4402+
4403+ while (((bnow = button_pressed()) == 0) && !(signal_pending(current))) {
4404+ if (file->f_flags & O_NONBLOCK) {
4405+ lcd_waiters = 0;
4406+ return -EAGAIN;
4407+ }
4408+ set_current_state(TASK_INTERRUPTIBLE);
4409+ schedule_timeout(2 * HZ);
4410+ }
4411+ lcd_waiters = 0;
4412+
4413+ if (signal_pending(current)) {
4414+ return -ERESTARTSYS;
4415+ }
4416+
4417+ return bnow;
4418+}
4419+
4420+/* read a single line from the LCD into a string */
4421+static char *
4422+cobalt_lcddev_read_line(int lineno, char *line)
4423+{
4424+ unsigned long addr, min, max;
4425+ unsigned long flags;
4426+
4427+ switch (lineno) {
4428+ case 0:
4429+ min = DD_R00;
4430+ max = DD_R01;
4431+ break;
4432+ case 1:
4433+ min = DD_R10;
4434+ max = DD_R11;
4435+ break;
4436+ default:
4437+ min = 1;
4438+ max = 0;
4439+ }
4440+
4441+ spin_lock_irqsave(&lcd_lock, flags);
4442+ for (addr = min; addr <= max; addr++) {
4443+ lcddev_write_inst(addr | LCD_Addr);
4444+ udelay(150);
4445+ line[addr-min] = lcddev_read_data();
4446+ udelay(150);
4447+ }
4448+ spin_unlock_irqrestore(&lcd_lock, flags);
4449+ line[addr-min] = '\0';
4450+
4451+ return line;
4452+}
4453+
4454+#ifdef CONFIG_PROC_FS
4455+static int
4456+cobalt_lcd_read_proc(char *buf, char **start, off_t pos,
4457+ int len, int *eof, void *private)
4458+{
4459+ int plen = 0;
4460+ char line[COBALT_LCD_LINELEN+1];
4461+
4462+ /* first line */
4463+ cobalt_lcddev_read_line(0, line);
4464+ plen += sprintf(buf+plen, "%s\n", line);
4465+
4466+ /* second line */
4467+ cobalt_lcddev_read_line(1, line);
4468+ plen += sprintf(buf+plen, "%s\n", line);
4469+
4470+ return cobalt_gen_proc_read(buf, plen, start, pos, len, eof);
4471+}
4472+#endif
4473+
4474+static char *lcd_panic_str1 = "Kernel";
4475+static char *lcd_panic_str2 = "Panic!";
4476+
4477+static int cobalt_lcd_panic(struct notifier_block *self, unsigned long a, void *b)
4478+{
4479+ int i;
4480+ int len;
4481+
4482+ if( !lcd_present )
4483+ return 0;
4484+
4485+#ifdef CONFIG_COBALT_LCD_TWIDDLE
4486+ cobalt_lcd_stop_twiddle();
4487+#endif
4488+
4489+ lcddev_write_inst( (DD_R00) | LCD_Addr);
4490+ len = strlen( lcd_panic_str1 );
4491+ for( i=0 ; i<16 ; i++ )
4492+ lcddev_write_data( (i<len)?lcd_panic_str1[i]:' ' );
4493+
4494+ lcddev_write_inst( (DD_R10) | LCD_Addr);
4495+ len = strlen( lcd_panic_str2 );
4496+ for( i=0 ; i<16 ; i++ )
4497+ lcddev_write_data( (i<len)?lcd_panic_str2[i]:' ' );
4498+
4499+ return 0;
4500+}
4501+
4502+#ifdef CONFIG_COBALT_LCD_TWIDDLE
4503+static struct timer_list twiddle_timer;
4504+static int twiddling;
4505+static void
4506+twiddle_timer_func(unsigned long data)
4507+{
4508+ static int state=1;
4509+ static int pos=0;
4510+ unsigned long flags;
4511+
4512+ spin_lock_irqsave(&lcd_lock, flags);
4513+
4514+ lcddev_write_inst((DD_R10+4+pos) | LCD_Addr);
4515+ lcddev_write_data(' ');
4516+
4517+ pos += state;
4518+ if (pos < 0) {
4519+ state = 1;
4520+ pos = 1;
4521+ }
4522+ if (pos > 11) {
4523+ state = -1;
4524+ pos = 10;
4525+ }
4526+
4527+ lcddev_write_inst((DD_R10+4+pos) | LCD_Addr);
4528+ lcddev_write_data(0xff);
4529+
4530+ spin_unlock_irqrestore(&lcd_lock, flags);
4531+
4532+ mod_timer(&twiddle_timer, jiffies + TWIDDLE_HZ);
4533+}
4534+
4535+void
4536+cobalt_lcd_start_twiddle(void)
4537+{
4538+ init_timer(&twiddle_timer);
4539+ twiddle_timer.expires = jiffies + TWIDDLE_HZ;
4540+ twiddle_timer.data = 0;
4541+ twiddle_timer.function = &twiddle_timer_func;
4542+ add_timer(&twiddle_timer);
4543+ twiddling=1;
4544+}
4545+
4546+void
4547+cobalt_lcd_stop_twiddle(void)
4548+{
4549+ unsigned long flags;
4550+
4551+ spin_lock_irqsave(&lcd_lock, flags);
4552+ if (twiddling) {
4553+ del_timer_sync(&twiddle_timer);
4554+ twiddling = 0;
4555+ }
4556+ spin_unlock_irqrestore(&lcd_lock, flags);
4557+}
4558+#endif /* CONFIG_COBALT_LCD_TWIDDLE */
4559+
4560+/* stop the lcd */
4561+void cobalt_lcd_off(void)
4562+{
4563+ unsigned long flags;
4564+
4565+ spin_lock_irqsave(&lcd_lock, flags);
4566+ lcddev_write_inst(0x01); /* clear */
4567+ lcddev_write_inst(0x08); /* off */
4568+ spin_unlock_irqrestore(&lcd_lock, flags);
4569+}
4570+
4571+static int initialized;
4572+static struct notifier_block lcd_nb;
4573+
4574+int __init
4575+cobalt_lcd_init(void)
4576+{
4577+ int retval;
4578+
4579+ if (initialized)
4580+ return 0;
4581+
4582+ initialized=1;
4583+ printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", LCD_DRIVER,LCD_DRIVER_VMAJ,LCD_DRIVER_VMIN);
4584+
4585+ if (disable_lcd) {
4586+ printk(KERN_INFO "%s DISABLED\n", LCD_DRIVER);
4587+ return 0;
4588+ }
4589+
4590+ retval = misc_register(&lcd_dev);
4591+
4592+ if (cobt_is_monterey()
4593+ && (cobalt_i2c_read_byte(COBALT_I2C_DEV_LCD_INST, 0) != 0xff)) {
4594+ printk(KERN_INFO " - LCD is an I2C device\n");
4595+ has_i2c_lcd = 1;
4596+ } else {
4597+ has_i2c_lcd = 0;
4598+ }
4599+
4600+ /* flag ourselves as present */
4601+ lcd_present = 1;
4602+
4603+ /* initialize the device */
4604+ lcddev_init();
4605+
4606+#ifdef CONFIG_PROC_FS
4607+#ifdef CONFIG_COBALT_OLDPROC
4608+ /* create /proc/lcd */
4609+ proc_lcd = create_proc_read_entry("lcd", S_IRUSR, NULL,
4610+ cobalt_lcd_read_proc, NULL);
4611+ if (!proc_lcd) {
4612+ EPRINTK("can't create /proc/lcd\n");
4613+ }
4614+#endif
4615+ proc_clcd = create_proc_read_entry("lcd", S_IRUSR, proc_cobalt,
4616+ cobalt_lcd_read_proc, NULL);
4617+ if (!proc_clcd) {
4618+ EPRINTK("can't create /proc/cobalt/lcd\n");
4619+ }
4620+#endif
4621+
4622+#ifdef CONFIG_COBALT_LCD_TWIDDLE
4623+ cobalt_lcd_start_twiddle();
4624+#endif
4625+
4626+ /* register panic notifier */
4627+ lcd_nb.notifier_call = cobalt_lcd_panic;
4628+ lcd_nb.next = NULL;
4629+ lcd_nb.priority = 0;
4630+
4631+ atomic_notifier_chain_register( &panic_notifier_list, &lcd_nb );
4632+
4633+ return 0;
4634+}
4635+
4636+#endif /* CONFIG_COBALT_LCD */
4637diff -Naur linux-2.6.18.2.orig/drivers/cobalt/led.c linux-2.6.18.2/drivers/cobalt/led.c
4638--- linux-2.6.18.2.orig/drivers/cobalt/led.c 1969-12-31 16:00:00.000000000 -0800
4639+++ linux-2.6.18.2/drivers/cobalt/led.c 2006-11-15 21:20:19.738033319 -0800
4640@@ -0,0 +1,504 @@
4641+ /*
4642+ * $Id: led.c,v 1.36 2002/05/10 18:44:45 duncan Exp $
4643+ * led.c : driver for Cobalt LEDs
4644+ *
4645+ * Copyright 1996-2000 Cobalt Networks, Inc.
4646+ * Copyright 2001 Sun Microsystems, Inc.
4647+ *
4648+ * By: Andrew Bose
4649+ * Timothy Stonis
4650+ * Tim Hockin
4651+ * Adrian Sun
4652+ * Duncan Laurie
4653+ *
4654+ * Modified By: jeff@404ster.com
4655+ *
4656+ * This should be SMP safe. There is one definite critical region: the
4657+ * handler list (led_handler_lock). The led_state is protected by led_lock,
4658+ * so should be safe against simultaneous writes. Bit banging of lights is
4659+ * currently also a protected region (led_lock, rather than add a new lock).
4660+ */
4661+
4662+#include <linux/config.h>
4663+
4664+#ifdef CONFIG_COBALT_LED
4665+
4666+#include <linux/module.h>
4667+#include <linux/types.h>
4668+#include <linux/errno.h>
4669+#include <linux/miscdevice.h>
4670+#include <linux/slab.h>
4671+#include <linux/ioport.h>
4672+#include <linux/fcntl.h>
4673+#include <linux/netdevice.h>
4674+#include <linux/pci.h>
4675+#include <linux/init.h>
4676+#include <linux/timer.h>
4677+#include <linux/nvram.h>
4678+#include <asm/io.h>
4679+#include <linux/delay.h>
4680+
4681+#include <cobalt/cobalt.h>
4682+#include <cobalt/systype.h>
4683+#include <cobalt/led.h>
4684+#include <cobalt/i2c.h>
4685+#include <cobalt/superio.h>
4686+
4687+#define LED_DRIVER "Cobalt Networks LED driver"
4688+#define LED_DRIVER_VMAJ 1
4689+#define LED_DRIVER_VMIN 0
4690+
4691+/* the rate at which software controlled frontpanel LEDs blink */
4692+#define FPLED_DEFAULT_HZ (HZ/20)
4693+
4694+/*
4695+ * This is the abstracted state of active LEDs - see the defines for LED_*
4696+ * LED masks are always 'unsigned int'. You must hold led_lock to muck with
4697+ * these.
4698+ */
4699+static unsigned int led_state;
4700+static unsigned int led_blips;
4701+
4702+/* leds are PCI on genIII */
4703+static struct pci_dev *led_dev;
4704+/* on XTR the front panel LEDs are software controlled */
4705+struct led_handler {
4706+ unsigned int (*function)(void *);
4707+ void *data;
4708+ struct led_handler *next;
4709+ struct led_handler *prev;
4710+};
4711+struct led_handler *led_handler_list;
4712+static spinlock_t led_handler_lock = SPIN_LOCK_UNLOCKED;
4713+static struct timer_list timer;
4714+
4715+static spinlock_t led_lock = SPIN_LOCK_UNLOCKED;
4716+
4717+/*
4718+ * RaQ 3
4719+ * RaQ 4
4720+ * Qube 3
4721+ */
4722+#define RAQ3_SHUTLOGO_ADDR 0x7e
4723+#define RAQ3_SHUTDOWN_OFF 0x40 /* reverse polarity */
4724+#define RAQ3_COBALTLOGO_ON 0x80
4725+#define QUBE3_LIGHTBAR_ON 0xc0 /* direct polarity */
4726+#define RAQ3_WEBLIGHT_ADDR 0xb8
4727+#define RAQ3_WEBLIGHT_ON 0x80
4728+
4729+/*
4730+ * RaQ XTR
4731+ */
4732+#define MONTEREY_FPLED00 0x8000
4733+#define MONTEREY_FPLED01 0x4000
4734+#define MONTEREY_FPLED02 0x2000
4735+#define MONTEREY_FPLED03 0x0200
4736+#define MONTEREY_FPLED04 0x0080
4737+#define MONTEREY_FPLED05 0x0040
4738+#define MONTEREY_FPLED10 0x1000
4739+#define MONTEREY_FPLED11 0x0800
4740+#define MONTEREY_FPLED12 0x0400
4741+#define MONTEREY_FPLED13 0x0100
4742+#define MONTEREY_FPLED14 0x0020
4743+#define MONTEREY_FPLED15 0x0010
4744+#define MONTEREY_FPLED_ETH0_TXRX MONTEREY_FPLED00
4745+#define MONTEREY_FPLED_ETH0_LINK MONTEREY_FPLED10
4746+#define MONTEREY_FPLED_ETH1_TXRX MONTEREY_FPLED01
4747+#define MONTEREY_FPLED_ETH1_LINK MONTEREY_FPLED11
4748+#define MONTEREY_FPLED_DISK0 MONTEREY_FPLED02
4749+#define MONTEREY_FPLED_DISK1 MONTEREY_FPLED03
4750+#define MONTEREY_FPLED_DISK2 MONTEREY_FPLED04
4751+#define MONTEREY_FPLED_DISK3 MONTEREY_FPLED05
4752+#define MONTEREY_FPLED_WEB MONTEREY_FPLED12
4753+#define MONTEREY_LOGOLED_BIT 0x40
4754+#define MONTEREY_SYSFAULTLED_BIT 0x80
4755+#define MONTEREY_SLED0 (1<<3)
4756+#define MONTEREY_SLED1 (1<<2)
4757+#define MONTEREY_SLED2 (1<<1)
4758+#define MONTEREY_SLED3 (1<<0)
4759+
4760+/*
4761+ * Alpine
4762+ */
4763+#define ALPINE_WEBLED_PORT 0x60e
4764+#define ALPINE_WEBLED_BIT 0x20
4765+#define ALPINE_POWERLED_PORT 0x50b
4766+#define ALPINE_POWERLED_CFG 0x23
4767+#define ALPINE_LOGOLED_BIT 0x02
4768+#define ALPINE_SYSFAULTLED_BIT 0x07
4769+
4770+/*
4771+ * actually set the leds (icky details hidden within)
4772+ * this must be protected against itself with led_lock
4773+ * */
4774+static void
4775+__set_led_hw(const unsigned int newstate)
4776+{
4777+ if (cobt_is_pacifica() && led_dev) {
4778+ unsigned char tmp;
4779+ /* RaQ 3, RaQ 4
4780+ * - shutdown light
4781+ * - logo light
4782+ * - web light
4783+ */
4784+
4785+ /* read the current state of shutdown/logo lights */
4786+ pci_read_config_byte(led_dev, RAQ3_SHUTLOGO_ADDR, &tmp);
4787+
4788+ /* reverse polarity for shutdown light */
4789+ if (newstate & LED_SHUTDOWN)
4790+ tmp &= ~RAQ3_SHUTDOWN_OFF;
4791+ else
4792+ tmp |= RAQ3_SHUTDOWN_OFF;
4793+
4794+ /* logo light is straight forward */
4795+ if (newstate & LED_COBALTLOGO)
4796+ tmp |= RAQ3_COBALTLOGO_ON;
4797+ else
4798+ tmp &= ~RAQ3_COBALTLOGO_ON;
4799+
4800+ /* write new shutdown/logo light state */
4801+ pci_write_config_byte(led_dev, RAQ3_SHUTLOGO_ADDR, tmp);
4802+
4803+ /* read web light state */
4804+ pci_read_config_byte(led_dev, RAQ3_WEBLIGHT_ADDR, &tmp);
4805+ if (newstate & LED_WEBLIGHT) {
4806+ tmp |= RAQ3_WEBLIGHT_ON;
4807+ } else {
4808+ tmp &= ~RAQ3_WEBLIGHT_ON;
4809+ }
4810+
4811+ /* write new web light state */
4812+ pci_write_config_byte(led_dev, RAQ3_WEBLIGHT_ADDR, tmp);
4813+ } else if (cobt_is_carmel() && led_dev) {
4814+ unsigned char tmp;
4815+ /* Qube 3
4816+ * - no shutdown light
4817+ * - lightbar instead of logo
4818+ * - no web led (wired to 2nd IDE reset for staggered startup)
4819+ */
4820+
4821+ /* read the current state of lightbar */
4822+ pci_read_config_byte(led_dev, RAQ3_SHUTLOGO_ADDR, &tmp);
4823+ if (newstate & LED_COBALTLOGO) {
4824+ tmp |= QUBE3_LIGHTBAR_ON;
4825+ } else {
4826+ tmp &= ~QUBE3_LIGHTBAR_ON;
4827+ }
4828+
4829+ /* write new lightbar state */
4830+ pci_write_config_byte(led_dev, RAQ3_SHUTLOGO_ADDR, tmp);
4831+ } else if (cobt_is_monterey()) {
4832+ unsigned int tmp = 0;
4833+ u8 val;
4834+ unsigned long flags;
4835+
4836+ if (newstate & LED_WEBLIGHT) {
4837+ tmp |= MONTEREY_FPLED_WEB;
4838+ }
4839+ if (newstate & LED_ETH0_TXRX) {
4840+ tmp |= MONTEREY_FPLED_ETH0_TXRX;
4841+ }
4842+ if (newstate & LED_ETH0_LINK) {
4843+ tmp |= MONTEREY_FPLED_ETH0_LINK;
4844+ }
4845+ if (newstate & LED_ETH1_TXRX) {
4846+ tmp |= MONTEREY_FPLED_ETH1_TXRX;
4847+ }
4848+ if (newstate & LED_ETH1_LINK) {
4849+ tmp |= MONTEREY_FPLED_ETH1_LINK;
4850+ }
4851+ if (newstate & LED_DISK0) {
4852+ tmp |= MONTEREY_FPLED_DISK0;
4853+ }
4854+ if (newstate & LED_DISK1) {
4855+ tmp |= MONTEREY_FPLED_DISK1;
4856+ }
4857+ if (newstate & LED_DISK2) {
4858+ tmp |= MONTEREY_FPLED_DISK2;
4859+ }
4860+ if (newstate & LED_DISK3) {
4861+ tmp |= MONTEREY_FPLED_DISK3;
4862+ }
4863+ /* 3 LED's are unused on Monterey, but we support them */
4864+ if (newstate & LED_MONTEREY_UNUSED0) {
4865+ tmp |= MONTEREY_FPLED13;
4866+ }
4867+ if (newstate & LED_MONTEREY_UNUSED1) {
4868+ tmp |= MONTEREY_FPLED14;
4869+ }
4870+ if (newstate & LED_MONTEREY_UNUSED2) {
4871+ tmp |= MONTEREY_FPLED15;
4872+ }
4873+ /* I2C controlled front-panel lights */
4874+ cobalt_i2c_write_byte(COBALT_I2C_DEV_LED_I, 0, tmp & 0xff);
4875+ cobalt_i2c_write_byte(COBALT_I2C_DEV_LED_II, 0, tmp >> 8);
4876+
4877+ /* drive sled LEDs are on a different i2c device */
4878+ tmp = 0xf0; /* high nibble means something else */
4879+ if (newstate * LED_SLED0)
4880+ tmp |= MONTEREY_SLED0;
4881+ if (newstate * LED_SLED1)
4882+ tmp |= MONTEREY_SLED1;
4883+ if (newstate * LED_SLED2)
4884+ tmp |= MONTEREY_SLED2;
4885+ if (newstate * LED_SLED3)
4886+ tmp |= MONTEREY_SLED3;
4887+ cobalt_i2c_write_byte(COBALT_I2C_DEV_RULER, 0, tmp);
4888+
4889+ /* sysfault and logo are in APC page of nvram */
4890+ spin_lock_irqsave(&rtc_lock, flags);
4891+ superio_set_rtc_bank(PC87317_RTC_BANK_APC);
4892+ val = CMOS_READ(PC87317_APCR4);
4893+
4894+ /* reverse polarity */
4895+ if (newstate & LED_COBALTLOGO) {
4896+ val &= ~MONTEREY_LOGOLED_BIT; /* logo is on */
4897+ } else {
4898+ val |= MONTEREY_LOGOLED_BIT; /* logo is off */
4899+ }
4900+
4901+ if (newstate & LED_SYSFAULT) {
4902+ val |= MONTEREY_SYSFAULTLED_BIT;
4903+ } else {
4904+ val &= ~MONTEREY_SYSFAULTLED_BIT;
4905+ }
4906+
4907+ CMOS_WRITE(val, PC87317_APCR4);
4908+ superio_set_rtc_bank(PC87317_RTC_BANK_MAIN);
4909+ spin_unlock_irqrestore(&rtc_lock, flags);
4910+ } else if (cobt_is_alpine()) {
4911+ unsigned char val;
4912+
4913+ /* web LED is reverse polarity */
4914+ val = inb(ALPINE_WEBLED_PORT);
4915+ if (newstate & LED_WEBLIGHT) {
4916+ val &= ~ALPINE_WEBLED_BIT;
4917+ } else {
4918+ val |= ALPINE_WEBLED_BIT;
4919+ }
4920+ outb(val, ALPINE_WEBLED_PORT);
4921+
4922+ /*
4923+ * the power led is controled by switching the pin between
4924+ * a GPIO pin (on) and a LED pin (off)
4925+ */
4926+
4927+ outb( ALPINE_POWERLED_CFG, 0x2e );
4928+ val = inb( 0x2f );
4929+ if (newstate & LED_COBALTLOGO) {
4930+ val &= ~ALPINE_LOGOLED_BIT;
4931+ } else {
4932+ val |= ALPINE_LOGOLED_BIT;
4933+ }
4934+ outb( val, 0x2f );
4935+
4936+ if (newstate & LED_SYSFAULT) {
4937+ val = ALPINE_SYSFAULTLED_BIT;
4938+ } else {
4939+ val = 0;
4940+ }
4941+
4942+ outb(val, ALPINE_POWERLED_PORT);
4943+ }
4944+}
4945+
4946+/* blip the front panel leds */
4947+static void
4948+led_timer_func(unsigned long data)
4949+{
4950+ unsigned int leds = 0;
4951+ struct led_handler *p;
4952+ unsigned long flags;
4953+
4954+ /* call all registered callbacks */
4955+ spin_lock_irqsave(&led_handler_lock, flags);
4956+ for (p = led_handler_list; p; p = p->next) {
4957+ leds |= p->function(p->data);
4958+ }
4959+ spin_unlock_irqrestore(&led_handler_lock, flags);
4960+
4961+ /* set the led hardware */
4962+ spin_lock_irqsave(&led_lock, flags);
4963+ __set_led_hw(led_state | leds | led_blips);
4964+ led_blips = 0;
4965+ spin_unlock_irqrestore(&led_lock, flags);
4966+
4967+ /* re-arm ourself */
4968+ mod_timer(&timer, jiffies + FPLED_DEFAULT_HZ);
4969+}
4970+
4971+static void
4972+__cobalt_led_set(const unsigned int leds)
4973+{
4974+ led_state = leds;
4975+ __set_led_hw(leds);
4976+}
4977+
4978+void
4979+cobalt_led_set(const unsigned int leds)
4980+{
4981+ unsigned long flags;
4982+ spin_lock_irqsave(&led_lock, flags);
4983+ __cobalt_led_set(leds);
4984+ spin_unlock_irqrestore(&led_lock, flags);
4985+}
4986+
4987+void
4988+cobalt_led_set_bits(const unsigned int leds)
4989+{
4990+ unsigned long flags;
4991+ spin_lock_irqsave(&led_lock, flags);
4992+ __cobalt_led_set(led_state | leds);
4993+ spin_unlock_irqrestore(&led_lock, flags);
4994+}
4995+
4996+void
4997+cobalt_led_clear_bits(const unsigned int leds)
4998+{
4999+ unsigned long flags;
5000+ spin_lock_irqsave(&led_lock, flags);
5001+ __cobalt_led_set(led_state & ~leds);
5002+ spin_unlock_irqrestore(&led_lock, flags);
5003+}
5004+
5005+static void
5006+__cobalt_led_set_lazy(const unsigned int leds)
5007+{
5008+ /* the next led timer run will catch these changes */
5009+ led_state = leds;
5010+ /* remember lights that were 'blipped' to force an edge */
5011+ led_blips |= leds;
5012+}
5013+
5014+void
5015+cobalt_led_set_lazy(const unsigned int leds)
5016+{
5017+ unsigned long flags;
5018+ spin_lock_irqsave(&led_lock, flags);
5019+ __cobalt_led_set_lazy(leds);
5020+ spin_unlock_irqrestore(&led_lock, flags);
5021+}
5022+
5023+void
5024+cobalt_led_set_bits_lazy(const unsigned int leds)
5025+{
5026+ unsigned long flags;
5027+ spin_lock_irqsave(&led_lock, flags);
5028+ __cobalt_led_set_lazy(led_state | leds);
5029+ spin_unlock_irqrestore(&led_lock, flags);
5030+}
5031+
5032+void
5033+cobalt_led_clear_bits_lazy(const unsigned int leds)
5034+{
5035+ unsigned long flags;
5036+ spin_lock_irqsave(&led_lock, flags);
5037+ __cobalt_led_set_lazy(led_state & ~leds);
5038+ spin_unlock_irqrestore(&led_lock, flags);
5039+}
5040+
5041+unsigned int
5042+cobalt_led_get(void)
5043+{
5044+ unsigned int r;
5045+ unsigned long flags;
5046+
5047+ spin_lock_irqsave(&led_lock, flags);
5048+ r = led_state;
5049+ spin_unlock_irqrestore(&led_lock, flags);
5050+
5051+ return r;
5052+}
5053+
5054+int
5055+cobalt_fpled_register(unsigned int (*function)(void *), void *data)
5056+{
5057+ struct led_handler *newh;
5058+ unsigned long flags;
5059+
5060+ newh = kmalloc(sizeof(*newh), GFP_ATOMIC);
5061+ if (!newh) {
5062+ EPRINTK("can't allocate memory for handler %p(%p)\n",
5063+ function, data);
5064+ return -1;
5065+ }
5066+
5067+ spin_lock_irqsave(&led_handler_lock, flags);
5068+
5069+ /* head insert */
5070+ newh->function = function;
5071+ newh->data = data;
5072+ newh->next = led_handler_list;
5073+ newh->prev = NULL;
5074+ if (led_handler_list) {
5075+ led_handler_list->prev = newh;
5076+ }
5077+ led_handler_list = newh;
5078+
5079+ spin_unlock_irqrestore(&led_handler_lock, flags);
5080+
5081+ return 0;
5082+}
5083+
5084+int
5085+cobalt_fpled_unregister(unsigned int (*function)(void *), void *data)
5086+{
5087+ int r = -1;
5088+ struct led_handler *p;
5089+ unsigned long flags;
5090+
5091+ spin_lock_irqsave(&led_handler_lock, flags);
5092+
5093+ for (p = led_handler_list; p; p = p->next) {
5094+ if (p->function == function && p->data == data) {
5095+ if (p->prev) {
5096+ p->prev->next = p->next;
5097+ }
5098+ if (p->next) {
5099+ p->next->prev = p->prev;
5100+ }
5101+ r = 0;
5102+ break;
5103+ }
5104+ }
5105+
5106+ spin_unlock_irqrestore(&led_handler_lock, flags);
5107+
5108+ return r;
5109+}
5110+
5111+int __init
5112+cobalt_led_init(void)
5113+{
5114+ unsigned int leds = LED_SHUTDOWN | LED_COBALTLOGO;
5115+
5116+ printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", LED_DRIVER,LED_DRIVER_VMAJ,LED_DRIVER_VMIN);
5117+
5118+ if (cobt_is_3k()) {
5119+ /* LEDs for RaQ3/4 and Qube3 are on the PMU */
5120+ led_dev = pci_find_device(PCI_VENDOR_ID_AL,
5121+ PCI_DEVICE_ID_AL_M7101, NULL);
5122+ if (!led_dev) {
5123+ EPRINTK("can't find PMU for LED control\n");
5124+ return -1;
5125+ }
5126+ }
5127+
5128+ /* setup up timer for fp leds */
5129+ init_timer(&timer);
5130+ timer.expires = jiffies + FPLED_DEFAULT_HZ;
5131+ timer.data = 0;
5132+ timer.function = &led_timer_func;
5133+ add_timer(&timer);
5134+
5135+ /* set the initial state */
5136+ leds |= cobalt_cmos_read_flag(COBT_CMOS_SYSFAULT_FLAG) ?
5137+ LED_SYSFAULT : 0;
5138+ led_state = leds;
5139+ __set_led_hw(leds);
5140+
5141+ return 0;
5142+}
5143+
5144+#endif /* CONFIG_COBALT_LED */
5145diff -Naur linux-2.6.18.2.orig/drivers/cobalt/net.c linux-2.6.18.2/drivers/cobalt/net.c
5146--- linux-2.6.18.2.orig/drivers/cobalt/net.c 1969-12-31 16:00:00.000000000 -0800
5147+++ linux-2.6.18.2/drivers/cobalt/net.c 2006-11-15 21:20:19.738033319 -0800
5148@@ -0,0 +1,133 @@
5149+/*
5150+ * cobalt net wrappers
5151+ * Copyright (c) 2000, Cobalt Networks, Inc.
5152+ * Copyright (c) 2001, Sun Microsystems, Inc.
5153+ * $Id: net.c,v 1.11 2001/10/27 00:40:24 thockin Exp $
5154+ * author: thockin@sun.com
5155+ *
5156+ * This should be SMP safe. The only critical data is the list of devices.
5157+ * The LED handler runs at timer-interrupt, so we must use the IRQ safe forms
5158+ * of the locks. --TPH
5159+ */
5160+
5161+#include <stdarg.h>
5162+#include <stddef.h>
5163+#include <linux/init.h>
5164+#include <linux/config.h>
5165+#include <linux/pci.h>
5166+#include <linux/ioport.h>
5167+#include <linux/netdevice.h>
5168+#include <asm/io.h>
5169+
5170+#include <cobalt/cobalt.h>
5171+#include <cobalt/net.h>
5172+#include <cobalt/led.h>
5173+
5174+#define MAX_COBT_NETDEVS 2
5175+static struct net_device *netdevs[MAX_COBT_NETDEVS];
5176+static int n_netdevs;
5177+static spinlock_t cobaltnet_lock = SPIN_LOCK_UNLOCKED;
5178+
5179+#if defined(CONFIG_COBALT_LED)
5180+static unsigned int
5181+net_led_handler(void *data)
5182+{
5183+ int i;
5184+ unsigned int leds = 0;
5185+ static int txrxmap[MAX_COBT_NETDEVS] = {LED_ETH0_TXRX, LED_ETH1_TXRX};
5186+ static int linkmap[MAX_COBT_NETDEVS] = {LED_ETH0_LINK, LED_ETH1_LINK};
5187+ unsigned long flags;
5188+ static unsigned long net_old[MAX_COBT_NETDEVS];
5189+
5190+ spin_lock_irqsave(&cobaltnet_lock, flags);
5191+
5192+ for (i = 0; i < n_netdevs; i++) {
5193+ unsigned long txrxstate;
5194+ struct net_device *dev = netdevs[i];
5195+ if (!dev) {
5196+ continue;
5197+ }
5198+ /* check for link */
5199+ if (netif_running(dev) && netif_carrier_ok(dev)) {
5200+ leds |= linkmap[i];
5201+ }
5202+ /* check for tx/rx */
5203+ txrxstate = dev->trans_start ^ dev->last_rx;
5204+ if (txrxstate != net_old[i]) {
5205+ leds |= txrxmap[i];
5206+ net_old[i] = txrxstate;
5207+ }
5208+ }
5209+
5210+ spin_unlock_irqrestore(&cobaltnet_lock, flags);
5211+
5212+ return leds;
5213+}
5214+#endif
5215+
5216+/*
5217+ * We try to be VERY explicit here. Fine for now, may eventually break down.
5218+ */
5219+void
5220+cobalt_net_register(struct net_device *ndev)
5221+{
5222+ unsigned long flags;
5223+ int i;
5224+
5225+ if (!ndev) {
5226+ return;
5227+ }
5228+
5229+ /* we'll track the first MAX_COBT_NETDEVS NICs */
5230+ if (n_netdevs >= MAX_COBT_NETDEVS) {
5231+ return;
5232+ }
5233+
5234+ spin_lock_irqsave(&cobaltnet_lock, flags);
5235+
5236+ /* find a free slot */
5237+ for (i = 0; i < MAX_COBT_NETDEVS; i++) {
5238+ if (!netdevs[i]) {
5239+ netdevs[i] = ndev;
5240+ n_netdevs++;
5241+ break;
5242+ }
5243+ }
5244+
5245+ spin_unlock_irqrestore(&cobaltnet_lock, flags);
5246+}
5247+
5248+void
5249+cobalt_net_unregister(struct net_device *ndev)
5250+{
5251+ int i;
5252+ unsigned long flags;
5253+
5254+ if (!ndev) {
5255+ return;
5256+ }
5257+
5258+ spin_lock_irqsave(&cobaltnet_lock, flags);
5259+
5260+ /* try to remove it from the list */
5261+ for (i = 0; i < MAX_COBT_NETDEVS; i++) {
5262+ if (netdevs[i] == ndev) {
5263+ netdevs[i] = NULL;
5264+ n_netdevs--;
5265+ break;
5266+ }
5267+ }
5268+
5269+ spin_unlock_irqrestore(&cobaltnet_lock, flags);
5270+}
5271+
5272+int __init
5273+cobalt_net_init(void)
5274+{
5275+#if defined(CONFIG_COBALT_LED)
5276+ /* register an LED handler */
5277+ cobalt_fpled_register(net_led_handler, NULL);
5278+#endif
5279+
5280+ return 0;
5281+}
5282diff -Naur linux-2.6.18.2.orig/drivers/cobalt/raminfo.c linux-2.6.18.2/drivers/cobalt/raminfo.c
5283--- linux-2.6.18.2.orig/drivers/cobalt/raminfo.c 1969-12-31 16:00:00.000000000 -0800
5284+++ linux-2.6.18.2/drivers/cobalt/raminfo.c 2006-11-15 21:20:19.738033319 -0800
5285@@ -0,0 +1,320 @@
5286+/* $Id: raminfo.c,v 1.7 2001/10/29 22:21:36 thockin Exp $
5287+ *
5288+ * Copyright (c) 2000-2001 Sun Microsystems, Inc.
5289+ * All Rights Reserved.
5290+ *
5291+ * This is SMP safe - the init runs once on load, and the rest is just
5292+ * printing information. --TPH
5293+ */
5294+#include <linux/config.h>
5295+
5296+#if defined(CONFIG_COBALT_RAMINFO) || defined(CONFIG_COBALT_RAMINFO_MODULE)
5297+
5298+#include <linux/module.h>
5299+#include <linux/init.h>
5300+#include <linux/pci.h>
5301+#include <linux/proc_fs.h>
5302+
5303+#include <cobalt/cobalt.h>
5304+#include <cobalt/systype.h>
5305+
5306+#define RAM_DRIVER "Cobalt Networks RAM Info driver"
5307+#define RAM_DRIVER_VMAJ 1
5308+#define RAM_DRIVER_VMIN 0
5309+
5310+#define MAX_DIMM_SLOTS 4
5311+
5312+enum dimm_t {
5313+ DIMM_TYPE_FPM_DRAM,
5314+ DIMM_TYPE_EDO_DRAM,
5315+ DIMM_TYPE_REG_SDRAM,
5316+ DIMM_TYPE_SDRAM
5317+};
5318+
5319+static char *dimm_desc[] = {
5320+ "Fast-page Mode DRAM",
5321+ "EDO DRAM",
5322+ "Registered SDRAM",
5323+ "SDRAM",
5324+};
5325+
5326+struct dimm_slot {
5327+ int num;
5328+ enum dimm_t type;
5329+ uint16_t size;
5330+ int ecc;
5331+};
5332+
5333+struct raminfo {
5334+ int total;
5335+ int (*query)(struct dimm_slot *);
5336+ struct pci_dev *dev;
5337+ struct dimm_slot *dimm;
5338+#ifdef CONFIG_PROC_FS
5339+ struct proc_dir_entry *proc;
5340+#endif /* CONFIG_PROC_FS */
5341+};
5342+
5343+/*########################################################################*/
5344+
5345+static int serverworks_le_dimm_info(struct dimm_slot *);
5346+static int ali_1541_dimm_info(struct dimm_slot *);
5347+static int raminfo_read_proc(char*, char**, off_t, int, int*, void*);
5348+
5349+/* RaQ-3, RaQ-4, Qube-3
5350+ * - uses ALI M1541 for memory controller
5351+ * - has 2 dimm slots */
5352+static struct raminfo gen3_raminfo = {
5353+ total: 2,
5354+ query: ali_1541_dimm_info
5355+};
5356+/* RaQ-XTR (Monterey)
5357+ * - uses ServerWorks CNB30LE for Memory Controller
5358+ * - has 4 dimm slots */
5359+static struct raminfo gen5_monterey_raminfo = {
5360+ total: 4,
5361+ query: serverworks_le_dimm_info
5362+};
5363+/* RaQ (Alpine)
5364+ * - uses ServerWorks CNB30LE for Memory Controller
5365+ * - has 2 dimm slots */
5366+static struct raminfo gen5_alpine_raminfo = {
5367+ total: 2,
5368+ query: serverworks_le_dimm_info
5369+};
5370+
5371+static struct raminfo *sys_raminfo;
5372+
5373+/*########################################################################*/
5374+
5375+#define SERVERWORKS_DRAM_MRPR (0x90)
5376+#define SERVERWORKS_DRAM_MRAR(slot) (0x7c + (slot))
5377+#define SERVERWORKS_DRAM_ECCR (0xe0)
5378+
5379+static int
5380+serverworks_le_dimm_info(struct dimm_slot *dimm)
5381+{
5382+ int row;
5383+ uint8_t rar, active, eccr;
5384+ uint16_t ma_map[] = {
5385+ 32, 16, 32, 256, 512, 128, 128, 64, 256, 128, 64, 64, 128,
5386+ };
5387+
5388+ if (!sys_raminfo || !sys_raminfo->dev || !dimm)
5389+ return -ENOSYS;
5390+
5391+ pci_read_config_byte(sys_raminfo->dev,
5392+ SERVERWORKS_DRAM_MRPR, &active);
5393+ pci_read_config_byte(sys_raminfo->dev,
5394+ SERVERWORKS_DRAM_MRAR(dimm->num), &rar);
5395+
5396+ /* serverworks uses only registered sdram */
5397+ dimm->type = DIMM_TYPE_REG_SDRAM;
5398+ dimm->size = 0;
5399+
5400+ /* check to see if ECC is enabled (bit 4 of reg 0xE0) */
5401+ pci_read_config_byte(sys_raminfo->dev,
5402+ SERVERWORKS_DRAM_ECCR, &eccr);
5403+ dimm->ecc = (eccr & (1<<2)) ? 1 : 0;
5404+
5405+ /* two rows for each dimm slot */
5406+ for (row=2*dimm->num; row<=(2*dimm->num+1); row++) {
5407+ /* each active row will have corresponding bit
5408+ * set in the Memory Row Presence Register */
5409+ if (active & (1 << row)) {
5410+ /* lookup size ma_map table */
5411+ dimm->size += ma_map[ rar & 0xf ];
5412+ }
5413+ /* two rows per RAR register, bits 7-4 and bits 3-0 */
5414+ rar >>= 4;
5415+ }
5416+
5417+ return 0;
5418+}
5419+
5420+#define ALI_DRAM_CONF_1(row) (0x60 + ((row) * 2))
5421+#define ALI_DRAM_CONF_2(row) (0x61 + ((row) * 2))
5422+#define ALI_DIMM_TYPE(d2) (((d2) >> 4) & 0x3)
5423+#define ALI_DIMM_MMAP(d2) (((d2) >> 6) & 0x3)
5424+#define ALI_DIMM_SIZE(d1, d2) (((((d2) & 0xf) << 8) | (d1)) + 1)
5425+
5426+static int
5427+ali_1541_dimm_info(struct dimm_slot *dimm)
5428+{
5429+ int row;
5430+ uint8_t dbc1, dbc2;
5431+
5432+ if (!sys_raminfo || !sys_raminfo->dev || !dimm)
5433+ return -ENOSYS;
5434+
5435+ dimm->size = 0;
5436+ dimm->ecc = 0;
5437+
5438+ /* read two rows per dimm (for double-side) */
5439+ for (row=2*dimm->num; row<=(2*dimm->num + 1); row++) {
5440+ pci_read_config_byte(sys_raminfo->dev,
5441+ ALI_DRAM_CONF_2(row), &dbc2);
5442+
5443+ /* row is empty iff dimm type and ma_map are both 0 */
5444+ if (!ALI_DIMM_TYPE(dbc2) && !ALI_DIMM_MMAP(dbc2))
5445+ continue;
5446+
5447+ pci_read_config_byte(sys_raminfo->dev,
5448+ ALI_DRAM_CONF_1(row), &dbc1);
5449+
5450+ /* type is bits 4-5 of dimm conf reg 2 */
5451+ dimm->type = ALI_DIMM_TYPE(dbc2);
5452+
5453+ /* A27-A20 address lines are bits 7-0 of dimm conf reg 1
5454+ * A31-A28 address lines are bits 3-0 of dimm conf reg 2 */
5455+ dimm->size = ALI_DIMM_SIZE(dbc1, dbc2);
5456+ }
5457+
5458+ /* the M1541 uses "not less than" policy to determine which row a
5459+ * memory address resides in. the top address boundary for each
5460+ * row is the maximum memory value minus 1. so to determine the
5461+ * size of a row you must subtract the size of the previous row.
5462+ * (unless this is slot 0 or the first populated slot) */
5463+ if (dimm->num > 0 && dimm->size > 0) {
5464+ uint16_t sz;
5465+ pci_read_config_byte(sys_raminfo->dev,
5466+ ALI_DRAM_CONF_1(2*dimm->num - 1), &dbc1);
5467+ pci_read_config_byte(sys_raminfo->dev,
5468+ ALI_DRAM_CONF_2(2*dimm->num - 1), &dbc2);
5469+ sz = ALI_DIMM_SIZE(dbc1, dbc2);
5470+ dimm->size -= (sz > 1) ? sz : 0;
5471+ }
5472+
5473+ return 0;
5474+}
5475+
5476+int __init
5477+cobalt_raminfo_init(void)
5478+{
5479+ int j;
5480+
5481+ /* determine system type and find memory controller pci dev
5482+ * so we don't have to do pci lookup for each proc read */
5483+ if (cobt_is_3k()) {
5484+ sys_raminfo = &gen3_raminfo;
5485+ sys_raminfo->dev = pci_find_device(PCI_VENDOR_ID_AL,
5486+ PCI_DEVICE_ID_AL_M1541, NULL);
5487+ } else if (cobt_is_5k()) {
5488+ if (cobt_is_monterey()) {
5489+ sys_raminfo = &gen5_monterey_raminfo;
5490+ } else if (cobt_is_alpine()) {
5491+ sys_raminfo = &gen5_alpine_raminfo;
5492+ } else {
5493+ EPRINTK("unable to identify gen5 board\n");
5494+ return -ENOSYS;
5495+ }
5496+ sys_raminfo->dev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
5497+ PCI_DEVICE_ID_SERVERWORKS_LE, NULL);
5498+ }
5499+
5500+ if (!sys_raminfo || !sys_raminfo->dev) {
5501+ EPRINTK("unable to identify system type\n");
5502+ return -ENOSYS;
5503+ }
5504+
5505+ printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", RAM_DRIVER,RAM_DRIVER_VMAJ,RAM_DRIVER_VMIN);
5506+
5507+#ifdef CONFIG_PROC_FS
5508+ /* add entry to /proc filesytem */
5509+ sys_raminfo->proc = create_proc_entry("raminfo",
5510+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, proc_cobalt);
5511+ if (!sys_raminfo->proc) {
5512+ EPRINTK("can't create /proc/cobalt/raminfo\n");
5513+ return -ENOENT;
5514+ }
5515+ sys_raminfo->proc->owner = THIS_MODULE;
5516+ sys_raminfo->proc->write_proc = NULL;
5517+ sys_raminfo->proc->read_proc = raminfo_read_proc;
5518+#endif /* CONFIG_PROC_FS */
5519+
5520+ /* create arrary of dimm slots to store info */
5521+ sys_raminfo->dimm = kmalloc(
5522+ sys_raminfo->total * sizeof(struct dimm_slot), GFP_ATOMIC);
5523+ if (!sys_raminfo->dimm) {
5524+ EPRINTK("unable to allocate memory\n");
5525+#ifdef CONFIG_PROC_FS
5526+ if (sys_raminfo->proc) {
5527+ remove_proc_entry("raminfo", proc_cobalt);
5528+ sys_raminfo->proc = NULL;
5529+ }
5530+#endif /* CONFIG_PROC_FS */
5531+ return -ENOMEM;
5532+ }
5533+
5534+ {
5535+ struct dimm_slot *ds = sys_raminfo->dimm;
5536+ for (j=0; j<sys_raminfo->total; j++, ds++) {
5537+ if (!ds) continue;
5538+ ds->num = j;
5539+ if (sys_raminfo->query(ds) < 0) {
5540+ EPRINTK("unable to read dimm %d\n", j);
5541+ ds->num = -1;
5542+ }
5543+ }
5544+ }
5545+
5546+ return 0;
5547+}
5548+
5549+static void __exit
5550+cobalt_raminfo_exit(void)
5551+{
5552+#ifdef CONFIG_PROC_FS
5553+ if (sys_raminfo->proc) {
5554+ remove_proc_entry("raminfo", proc_cobalt);
5555+ sys_raminfo->proc = NULL;
5556+ }
5557+#endif /* CONFIG_PROC_FS */
5558+
5559+ if (sys_raminfo->dimm) {
5560+ kfree(sys_raminfo->dimm);
5561+ sys_raminfo->dimm = NULL;
5562+ }
5563+
5564+ sys_raminfo->dev = NULL;
5565+ sys_raminfo = NULL;
5566+}
5567+
5568+#ifdef CONFIG_PROC_FS
5569+static int
5570+raminfo_read_proc(char *buf, char **st, off_t off, int len, int *eof, void *x)
5571+{
5572+ int rlen, i;
5573+ struct dimm_slot *ds;
5574+
5575+ if (!sys_raminfo)
5576+ return -ENOSYS;
5577+
5578+ //MOD_INC_USE_COUNT;
5579+
5580+ ds = sys_raminfo->dimm;
5581+ for (rlen=i=0; i<sys_raminfo->total; i++, ds++) {
5582+ if (!ds || ds->num < 0)
5583+ continue;
5584+ rlen += sprintf(buf+rlen, "%d [%s%s]: %u MB\n", i,
5585+ ds->size ? dimm_desc[ds->type] : "Empty",
5586+ ds->size ? ds->ecc ? "+ECC" : "" : "",
5587+ ds->size);
5588+ }
5589+
5590+ //MOD_DEC_USE_COUNT;
5591+
5592+ return cobalt_gen_proc_read(buf, rlen, st, off, len, eof);
5593+}
5594+#endif /* CONFIG_PROC_FS */
5595+
5596+#ifdef CONFIG_COBALT_RAMINFO_MODULE
5597+module_init(cobalt_raminfo_init);
5598+module_exit(cobalt_raminfo_exit);
5599+#endif
5600+
5601+MODULE_AUTHOR("Sun Cobalt");
5602+MODULE_DESCRIPTION("DIMM Information");
5603+MODULE_LICENSE("GPL");
5604+
5605+#endif /* CONFIG_COBALT_RAMINFO || CONFIG_COBALT_RAMINFO_MODULE */
5606diff -Naur linux-2.6.18.2.orig/drivers/cobalt/ruler.c linux-2.6.18.2/drivers/cobalt/ruler.c
5607--- linux-2.6.18.2.orig/drivers/cobalt/ruler.c 1969-12-31 16:00:00.000000000 -0800
5608+++ linux-2.6.18.2/drivers/cobalt/ruler.c 2006-11-15 21:20:19.738033319 -0800
5609@@ -0,0 +1,419 @@
5610+/*
5611+ * cobalt ruler driver
5612+ * Copyright (c) 2000, Cobalt Networks, Inc.
5613+ * Copyright (c) 2001, Sun Microsystems, Inc.
5614+ * $Id: ruler.c,v 1.23 2002/08/29 00:33:01 uzi Exp $
5615+ *
5616+ * author: asun@cobalt.com, thockin@sun.com
5617+ *
5618+ * This should be SMP safe. There is one critical piece of data, and thus
5619+ * one lock. The ruler_lock protects the arrays of channels(hwifs) and
5620+ * busproc function pointers. These are only ever written in the
5621+ * register/unregister functions but read in several other places. A
5622+ * read/write lock is appropriate. The global switches and sled_leds are
5623+ * atomic_t. --TPH
5624+ */
5625+
5626+#include <stdarg.h>
5627+#include <stddef.h>
5628+#include <linux/init.h>
5629+#include <linux/sched.h>
5630+#include <linux/timer.h>
5631+#include <linux/config.h>
5632+#include <linux/pci.h>
5633+#include <linux/proc_fs.h>
5634+#include <linux/sched.h>
5635+#include <linux/ioport.h>
5636+#include <linux/ide.h>
5637+#include <linux/hdreg.h>
5638+#include <linux/notifier.h>
5639+#include <linux/sysctl.h>
5640+#include <linux/reboot.h>
5641+#include <linux/delay.h>
5642+#include <linux/ide.h>
5643+#include <asm/io.h>
5644+
5645+#include <cobalt/cobalt.h>
5646+#include <cobalt/systype.h>
5647+#include <cobalt/i2c.h>
5648+#include <cobalt/acpi.h>
5649+#include <cobalt/led.h>
5650+#include <cobalt/ruler.h>
5651+
5652+#define RULER_TIMEOUT (HZ >> 1) /* .5s */
5653+#define MAX_COBT_DRIVES 4
5654+
5655+#define RULER_DRIVER "Cobalt Networks Disk Ruler driver"
5656+#define RULER_DRIVER_VMAJ 1
5657+#define RULER_DRIVER_VMIN 0
5658+
5659+/* all of this is for gen V */
5660+static struct timer_list cobalt_ruler_timer;
5661+static rwlock_t ruler_lock = RW_LOCK_UNLOCKED;
5662+static ide_drive_t *channels[MAX_COBT_DRIVES];
5663+
5664+static int (*busprocs[MAX_COBT_DRIVES])(ide_drive_t *, int);
5665+
5666+//static cob_busprocs_t busprocs[MAX_COBT_DRIVES];
5667+
5668+/* NOTE: switches is a bitmask of DETACHED sleds */
5669+static atomic_t switches = ATOMIC_INIT(0);
5670+static atomic_t sled_leds = ATOMIC_INIT(0);
5671+static int sled_led_map[] = {LED_SLED0, LED_SLED1, LED_SLED2, LED_SLED3};
5672+static int ruler_detect;
5673+static int initialized;
5674+
5675+static void ruler_hwif_added(ide_hwif_t *hwif, int idx);
5676+
5677+static inline u8
5678+read_switches(void)
5679+{
5680+ u8 state = 0;
5681+ if (cobt_is_monterey()) {
5682+ int tries = 3;
5683+
5684+ /* i2c can be busy, and this can read wrong - try a few times */
5685+ while (tries--) {
5686+ state = cobalt_i2c_read_byte(COBALT_I2C_DEV_DRV_SWITCH,
5687+ 0);
5688+ if ((state & 0xf0) != 0xf0) {
5689+ break;
5690+ }
5691+ }
5692+ }
5693+
5694+ return state;
5695+}
5696+
5697+static inline unsigned int
5698+get_sled_leds(void)
5699+{
5700+ return atomic_read(&sled_leds);
5701+}
5702+
5703+/*
5704+ * deal with sled leds: LED on means OK to remove
5705+ * NOTE: all the reset lines are kept high.
5706+ * NOTE: the reset lines are in the reverse order of the switches.
5707+ */
5708+static void
5709+set_sled_leds(unsigned int leds)
5710+{
5711+ if (cobt_is_monterey()) {
5712+ unsigned int offed = get_sled_leds();
5713+
5714+ offed &= ~leds;
5715+ atomic_set(&sled_leds, leds);
5716+#ifdef CONFIG_COBALT_LED
5717+ cobalt_led_clear_bits_lazy(offed);
5718+ cobalt_led_set_bits_lazy(leds);
5719+#endif
5720+ }
5721+}
5722+
5723+/* this must be called with the ruler_lock held for read */
5724+static int
5725+do_busproc(int idx, ide_drive_t *drive, int arg)
5726+{
5727+ if (cobt_is_monterey()) {
5728+ /* sed sled LEDs */
5729+ switch (arg) {
5730+ case BUSSTATE_ON:
5731+ set_sled_leds(get_sled_leds() &
5732+ ~sled_led_map[idx]);
5733+ break;
5734+ case BUSSTATE_OFF:
5735+ case BUSSTATE_TRISTATE:
5736+ set_sled_leds(get_sled_leds() |
5737+ sled_led_map[idx]);
5738+ break;
5739+ default:
5740+ WPRINTK("unknown busproc argument (%d)\n", arg);
5741+ }
5742+ }
5743+
5744+ /* do the real work */
5745+ return busprocs[idx](drive, arg);
5746+}
5747+
5748+static void
5749+ruler_timer_fn(unsigned long data)
5750+{
5751+ if (cobt_is_monterey()) {
5752+ u8 state;
5753+ int i;
5754+ unsigned int now, expected, bit, swcur;
5755+
5756+ state = read_switches();
5757+ if ((state & 0xf0) == 0xf0) {
5758+ return;
5759+ }
5760+ swcur = atomic_read(&switches);
5761+
5762+ state &= 0xf;
5763+ read_lock(&ruler_lock);
5764+ for (i = 0; i < MAX_COBT_DRIVES; i++) {
5765+ bit = 1 << i;
5766+ now = state & bit;
5767+ expected = swcur & bit;
5768+ if (now == expected) {
5769+ /* no changes to worry about */
5770+ continue;
5771+ }
5772+
5773+ if (now) {
5774+ /* a freshly detached drive */
5775+ atomic_set(&switches, swcur | bit);
5776+ if (channels[i]) {
5777+ printk("disabling ide ruler "
5778+ "channel %d\n", i);
5779+ do_busproc(i, channels[i],
5780+ BUSSTATE_TRISTATE);
5781+ } else {
5782+ WPRINTK("drive detach on bad "
5783+ "channel (%d)\n", i);
5784+ }
5785+ set_sled_leds(get_sled_leds() |
5786+ sled_led_map[i]);
5787+ } else {
5788+ /*
5789+ * do we want to do anything when a re-attach
5790+ * is detected?
5791+ */
5792+ }
5793+ }
5794+ read_unlock(&ruler_lock);
5795+ }
5796+}
5797+
5798+#ifdef CONFIG_COBALT_ACPI
5799+static int
5800+ruler_interrupt(cobalt_acpi_evt *evt, void * data)
5801+{
5802+ if (cobt_is_monterey() && ruler_detect) {
5803+ u8 state;
5804+
5805+ state = read_switches();
5806+ if ((state & 0xf0) != 0xf0) {
5807+ /* this is protected inside mod_timer */
5808+ mod_timer(&cobalt_ruler_timer, jiffies + RULER_TIMEOUT);
5809+ }
5810+
5811+ evt->ev_data = state;
5812+ /* empirical: delay enough to debounce */
5813+ udelay(10);
5814+ }
5815+ return 0;
5816+}
5817+#endif /* CONFIG_COBALT_ACPI */
5818+
5819+#if defined(CONFIG_COBALT_LED)
5820+/* figure which LEDs to blink */
5821+static unsigned int
5822+ide_led_handler(void *data)
5823+{
5824+ ide_hwif_t *hwif;
5825+ unsigned int leds = 0;
5826+
5827+ if (cobt_is_monterey()) {
5828+ int i;
5829+ static int ledmap[MAX_COBT_DRIVES] = {
5830+ LED_DISK0, LED_DISK1, LED_DISK2, LED_DISK3
5831+ };
5832+ static unsigned long old[MAX_COBT_DRIVES];
5833+
5834+ read_lock(&ruler_lock);
5835+
5836+ for (i = 0; i < MAX_COBT_DRIVES; i++) {
5837+ if (channels[i])
5838+ {
5839+ hwif = HWIF(channels[i]);
5840+ if (hwif->drives[0].present &&
5841+ hwif->drives[0].service_start != old[i]) {
5842+ leds |= ledmap[i];
5843+ old[i] = hwif->drives[0].service_start;
5844+ }
5845+ }
5846+ }
5847+
5848+ read_unlock(&ruler_lock);
5849+ }
5850+
5851+ return leds;
5852+}
5853+#endif
5854+
5855+/* this is essentially an exported function - it is in the hwif structs */
5856+static int ruler_busproc_fn(ide_drive_t *drive, int arg)
5857+{
5858+ int r = 0;
5859+ if (cobt_is_monterey()) {
5860+ int idx;
5861+
5862+ read_lock(&ruler_lock);
5863+
5864+ for (idx = 0; idx < MAX_COBT_DRIVES; idx++) {
5865+ if (channels[idx] == drive) {
5866+ break;
5867+ }
5868+ }
5869+
5870+ if (idx >= MAX_COBT_DRIVES) {
5871+ /* not a hwif we manage? */
5872+ return 0;
5873+ }
5874+
5875+ r = do_busproc(idx, drive, arg);
5876+ read_unlock(&ruler_lock);
5877+ }
5878+
5879+ return r;
5880+}
5881+
5882+/*
5883+ * We try to be VERY explicit here. Fine for now, may eventually break down.
5884+ */
5885+void
5886+cobalt_ruler_register(ide_drive_t *drive)
5887+{
5888+ ide_hwif_t *hwif = HWIF(drive);
5889+
5890+ if (cobt_is_monterey()) {
5891+ struct pci_dev *dev;
5892+ int idx;
5893+ unsigned long flags;
5894+
5895+ if (!hwif) {
5896+ return;
5897+ }
5898+
5899+ /* Cobalt rulers only have HPT370 controllers on bus 1 */
5900+ dev = hwif->pci_dev;
5901+ if (!dev)
5902+ return;
5903+
5904+ if (dev->vendor != PCI_VENDOR_ID_TTI
5905+ || dev->device != PCI_DEVICE_ID_TTI_HPT366
5906+ || dev->bus->number != 1) {
5907+ /* ignore it */
5908+ return;
5909+ }
5910+
5911+ /* IDE ruler has controllers at dev 3 and 4, ONLY */
5912+ if (dev->devfn == PCI_DEVFN(3,0)) {
5913+ idx = hwif->channel;
5914+ } else if (dev->devfn == PCI_DEVFN(4,0)) {
5915+ idx = 2 + hwif->channel;
5916+ } else {
5917+ return;
5918+ }
5919+
5920+ if (idx >= MAX_COBT_DRIVES) {
5921+ return;
5922+ }
5923+
5924+ write_lock_irqsave(&ruler_lock, flags);
5925+
5926+ /* save a pointer to the hwif, and trap it's busproc() */
5927+ channels[idx] = drive;
5928+ if (hwif->busproc) {
5929+ busprocs[idx] = HWIF(drive)->busproc;
5930+ hwif->busproc = &ruler_busproc_fn;
5931+ }
5932+
5933+ write_unlock_irqrestore(&ruler_lock, flags);
5934+
5935+ /* now that we have trapped it, do what we need to initialize
5936+ * the drive - if we haven't been initialized, we'll call this
5937+ * later.
5938+ */
5939+ if (initialized) {
5940+ ruler_hwif_added(hwif, idx);
5941+ }
5942+ }
5943+}
5944+
5945+static void
5946+ruler_hwif_added(ide_hwif_t *hwif, int idx)
5947+{
5948+ /* the associated switch should be closed */
5949+ if (hwif->drives[0].present) {
5950+ /* set the sled LED off - not safe to remove */
5951+ set_sled_leds(get_sled_leds() & ~sled_led_map[idx]);
5952+ }
5953+}
5954+
5955+void cobalt_ruler_unregister(ide_drive_t *drive)
5956+{
5957+ if (cobt_is_monterey()) {
5958+ int i;
5959+ unsigned long flags;
5960+
5961+ write_lock_irqsave(&ruler_lock, flags);
5962+
5963+ for (i = 0; i < MAX_COBT_DRIVES; i++) {
5964+ if (channels[i] == drive) {
5965+ channels[i] = NULL;
5966+ HWIF(drive)->busproc = busprocs[i];
5967+ busprocs[i] = NULL;
5968+ }
5969+ }
5970+
5971+ write_unlock_irqrestore(&ruler_lock, flags);
5972+ }
5973+}
5974+
5975+int __init
5976+cobalt_ruler_init(void)
5977+{
5978+ if (cobt_is_monterey()) {
5979+ int err;
5980+ u8 tmp;
5981+ int i;
5982+
5983+ /* initialize switches */
5984+ tmp = read_switches();
5985+ ruler_detect = ((tmp & 0xf0) == 0xf0) ? 0 : 1;
5986+ tmp &= 0xf;
5987+ atomic_set(&switches, tmp);
5988+
5989+ /* initialize our timer */
5990+ init_timer(&cobalt_ruler_timer);
5991+ cobalt_ruler_timer.function = ruler_timer_fn;
5992+
5993+ printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", RULER_DRIVER,RULER_DRIVER_VMAJ,RULER_DRIVER_VMIN);
5994+
5995+#ifdef CONFIG_COBALT_ACPI
5996+ err = cobalt_acpi_register_evt_handler(ruler_interrupt,
5997+ COBALT_ACPI_EVT_SLED, NULL );
5998+
5999+ if (err) {
6000+ EPRINTK("can't register interrupt handler %p\n",
6001+ ruler_interrupt);
6002+ }
6003+#endif
6004+
6005+ /* set initial sled LED state */
6006+ set_sled_leds(LED_SLED0 | LED_SLED1 | LED_SLED2 | LED_SLED3);
6007+
6008+ /* run through any devices that were registered before */
6009+ for (i = 0; i < MAX_COBT_DRIVES; i++) {
6010+ if (channels[i]) {
6011+ ruler_hwif_added(HWIF(channels[i]), i);
6012+ }
6013+ }
6014+
6015+#if defined(CONFIG_COBALT_LED)
6016+ /* register for a blinky LEDs callback */
6017+ err = cobalt_fpled_register(ide_led_handler, NULL);
6018+ if (err) {
6019+ EPRINTK("can't register LED handler %p\n",
6020+ ide_led_handler);
6021+ }
6022+#endif
6023+ }
6024+
6025+ initialized = 1;
6026+
6027+ return 0;
6028+}
6029diff -Naur linux-2.6.18.2.orig/drivers/cobalt/sensors.c linux-2.6.18.2/drivers/cobalt/sensors.c
6030--- linux-2.6.18.2.orig/drivers/cobalt/sensors.c 1969-12-31 16:00:00.000000000 -0800
6031+++ linux-2.6.18.2/drivers/cobalt/sensors.c 2006-11-15 21:20:19.738033319 -0800
6032@@ -0,0 +1,525 @@
6033+/* $Id: sensors.c,v 1.31 2002/08/29 00:33:01 uzi Exp $
6034+ * Copyright (c) 2000-2001 Sun Microsystems, Inc
6035+ *
6036+ * This should be SMP safe. There is just one race - the read in /proc.
6037+ * It now guards against itself with a semaphore. Note that we don't use a
6038+ * spinlock because any of the methods may (and do!) block.
6039+ */
6040+#include <linux/config.h>
6041+#ifdef CONFIG_COBALT_SENSORS
6042+
6043+#include <stdarg.h>
6044+#include <stddef.h>
6045+
6046+#include <linux/init.h>
6047+#include <linux/sched.h>
6048+#include <linux/timer.h>
6049+#include <linux/config.h>
6050+#include <linux/delay.h>
6051+#include <linux/ctype.h>
6052+#include <linux/proc_fs.h>
6053+
6054+#include <asm/io.h>
6055+#include <asm/uaccess.h>
6056+
6057+#include <cobalt/cobalt.h>
6058+#include <cobalt/systype.h>
6059+#include <cobalt/i2c.h>
6060+#include <cobalt/sensors.h>
6061+#include <cobalt/acpi.h>
6062+
6063+#define SENS_DRIVER "Cobalt Networks Sensor driver"
6064+#define SENS_DRIVER_VMAJ 1
6065+#define SENS_DRIVER_VMIN 0
6066+
6067+/* externals */
6068+unsigned int cobalt_nthermals;
6069+unsigned int cobalt_nvoltages;
6070+
6071+/* data about a sensor for generic handling */
6072+/* we could add data about a low/high range, if needed */
6073+struct sensor {
6074+ int sensor; /* sensor #, so maps can be logically ordered */
6075+ char *desc;
6076+ int last_val;
6077+ unsigned long cache;
6078+ unsigned long cache_timeout;
6079+ /* pre/post hook - 1 for pre, 0 for post */
6080+ void (*setup)(struct sensor *s, int pre);
6081+ /* read as an int, to be passed to format() */
6082+ int (*read)(struct sensor *s);
6083+ /* hook for scaling values */
6084+ int (*scale)(struct sensor *s, int val);
6085+ /* format the value as a string */
6086+ char *(*format)(struct sensor *s, int val, char *buf, int len);
6087+};
6088+
6089+/* some stuff for generic formatting */
6090+#define DEC_SCALAR 100
6091+static char *decimal_format(struct sensor *s, int val, char *buf, int len);
6092+
6093+static DECLARE_MUTEX(sensor_sem);
6094+static struct sensor *therm_map;
6095+static struct sensor *volt_map;
6096+
6097+#define CACHE_DEF 30
6098+
6099+#ifdef CONFIG_PROC_FS
6100+static struct proc_dir_entry *proc_csensors;
6101+static struct proc_dir_entry *proc_therm;
6102+static struct proc_dir_entry *proc_volt;
6103+static int therm_read_proc(char *buf, char **start, off_t pos, int len,
6104+ int *eof, void *x);
6105+static int therm_write_proc(struct file *file, const char *buf,
6106+ unsigned long len, void *x);
6107+static int volt_read_proc(char *buf, char **start, off_t pos, int len,
6108+ int *eof, void *x);
6109+static int volt_write_proc(struct file *file, const char *buf,
6110+ unsigned long len, void *x);
6111+#endif
6112+
6113+static int lm77_therm_read(struct sensor *s);
6114+static int adm1029_init(void);
6115+static int adm1029_therm_read(struct sensor *s);
6116+static int adm1029_volt_read(struct sensor *s);
6117+static int alpine_vcore_scale(struct sensor *s, int val);
6118+static void alpine_vbat_switch(struct sensor *s, int pre);
6119+static int alpine_vbat_scale(struct sensor *s, int val);
6120+
6121+/* sensor name mappings */
6122+static struct sensor gen3_therm_map[] = {
6123+ {0, "CPU", 0, 0, CACHE_DEF, NULL, lm77_therm_read, NULL, decimal_format},
6124+};
6125+static struct sensor monterey_therm_map[] = {
6126+ {0, "CPU0", 0, 0, CACHE_DEF, NULL, lm77_therm_read, NULL, decimal_format},
6127+ {1, "CPU1", 0, 0, CACHE_DEF, NULL, lm77_therm_read, NULL, decimal_format},
6128+ {2, "Case0", 0, 0, CACHE_DEF, NULL, lm77_therm_read, NULL, decimal_format},
6129+ {3, "Case1", 0, 0, CACHE_DEF, NULL, lm77_therm_read, NULL, decimal_format},
6130+};
6131+static struct sensor alpine_therm_map[] = {
6132+ {1, "CPU", 0, 0, CACHE_DEF, NULL, adm1029_therm_read, NULL, decimal_format},
6133+ {0, "Case", 0, 0, CACHE_DEF, NULL, adm1029_therm_read, NULL, decimal_format},
6134+};
6135+static struct sensor alpine_volt_map[] = {
6136+ {0, "Vcore", 0, 0, CACHE_DEF, NULL, adm1029_volt_read,
6137+ alpine_vcore_scale, decimal_format},
6138+ {1, "Vtt", 0, 0, CACHE_DEF, NULL, adm1029_volt_read, NULL, decimal_format},
6139+ {0, "Vbat", 0, 0, CACHE_DEF<<10, alpine_vbat_switch, adm1029_volt_read,
6140+ alpine_vbat_scale, decimal_format},
6141+};
6142+
6143+int __init
6144+cobalt_sensors_init(void)
6145+{
6146+ if (cobt_is_3k()) {
6147+ cobalt_nthermals = 1;
6148+ cobalt_nvoltages = 0;
6149+ therm_map = gen3_therm_map;
6150+ } else if (cobt_is_monterey()) {
6151+ cobalt_nthermals = 4;
6152+ cobalt_nvoltages = 0;
6153+ therm_map = monterey_therm_map;
6154+ } else if (cobt_is_alpine()) {
6155+ cobalt_nthermals = 2;
6156+ cobalt_nvoltages = 3;
6157+ therm_map = alpine_therm_map;
6158+ volt_map = alpine_volt_map;
6159+ adm1029_init();
6160+ } else {
6161+ return -1;
6162+ }
6163+
6164+ printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", SENS_DRIVER,SENS_DRIVER_VMAJ,SENS_DRIVER_VMIN);
6165+
6166+#ifdef CONFIG_PROC_FS
6167+ /* make files in /proc */
6168+ proc_csensors = proc_mkdir("sensors", proc_cobalt);
6169+ if (!proc_csensors) {
6170+ EPRINTK("can't create /proc/cobalt/sensors\n");
6171+ return -1;
6172+ }
6173+ if (cobalt_nthermals) {
6174+ proc_therm = create_proc_entry("thermal",
6175+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
6176+ proc_csensors);
6177+ if (!proc_therm) {
6178+ EPRINTK("can't create /proc/cobalt/sensors/thermal\n");
6179+ }
6180+ proc_therm->read_proc = therm_read_proc;
6181+ proc_therm->write_proc = therm_write_proc;
6182+ }
6183+ if (cobalt_nvoltages) {
6184+ proc_volt = create_proc_entry("voltage",
6185+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH,
6186+ proc_csensors);
6187+ if (!proc_volt) {
6188+ EPRINTK("can't create /proc/cobalt/sensors/voltage\n");
6189+ }
6190+ proc_volt->read_proc = volt_read_proc;
6191+ proc_volt->write_proc = volt_write_proc;
6192+
6193+ }
6194+#endif
6195+
6196+ return 0;
6197+}
6198+
6199+static char *
6200+sensor_read(struct sensor *s, char *buf, int len)
6201+{
6202+ int val;
6203+
6204+ if (s->cache && time_after(s->cache_timeout*HZ + s->cache, jiffies))
6205+ val = s->last_val;
6206+ else {
6207+ if (s->setup) s->setup(s, 1);
6208+ val = s->read(s);
6209+ s->last_val = val;
6210+ s->cache = jiffies;
6211+ if (s->setup) s->setup(s, 0);
6212+ }
6213+
6214+ if (s->scale) val = s->scale(s, val);
6215+ return s->format(s, val, buf, len);
6216+}
6217+
6218+/* exported - nicer inline functions in header */
6219+char *
6220+__cobalt_thermal_read(unsigned int idx, char *buf, int len)
6221+{
6222+ if (idx >= cobalt_nthermals || !buf) {
6223+ return NULL;
6224+ }
6225+
6226+ return sensor_read(&therm_map[idx], buf, len);
6227+}
6228+
6229+/* exported - nicer inline functions in header */
6230+char *
6231+__cobalt_voltage_read(unsigned int idx, char *buf, int len)
6232+{
6233+ if (idx >= cobalt_nvoltages || !buf) {
6234+ return NULL;
6235+ }
6236+
6237+ return sensor_read(&volt_map[idx], buf, len);
6238+}
6239+
6240+/* generic function for formatting decimal scaled data */
6241+static char *
6242+decimal_format(struct sensor *s, int val, char *buf, int len)
6243+{
6244+ int plen;
6245+
6246+ if (!buf || len <= 0) {
6247+ return NULL;
6248+ }
6249+
6250+ plen = snprintf(buf, len, "%d", val/DEC_SCALAR);
6251+ len -= plen;
6252+
6253+ if (val % DEC_SCALAR && len > 0) {
6254+ snprintf(buf+plen, len, ".%02d", val%DEC_SCALAR);
6255+ }
6256+
6257+ return buf;
6258+}
6259+
6260+#define LM77_TEMP 0x0
6261+static int
6262+lm77_therm_read(struct sensor *s)
6263+{
6264+ int sensor = s->sensor;
6265+ int tmp;
6266+ int val = 0;
6267+ int tries = 2;
6268+
6269+ /* sometimes it reads as zero... try again */
6270+ while (tries--) {
6271+ /* LM77 returns the bytes backwards - <shrug> */
6272+ /* address = base + deviceid + 1 for read */
6273+ val = cobalt_i2c_read_word(COBALT_I2C_DEV_LM77 +
6274+ (sensor<<1) + 1, LM77_TEMP);
6275+ if (val < 0) {
6276+ /* read failed, return the last known value */
6277+ return s->last_val;
6278+ }
6279+
6280+ tmp = (val<<8 & 0xff00) + (val>>8 & 0x00ff);
6281+ if (tmp) {
6282+ val = tmp >> 4;
6283+ val *= DEC_SCALAR;
6284+ if (tmp & 0x8) {
6285+ val += DEC_SCALAR/2;
6286+ }
6287+ break;
6288+ }
6289+ }
6290+ return val;
6291+}
6292+
6293+#define ADM1029_CTL_CFAULT_OVER 0x01
6294+#define ADM1029_CTL_ALARM_OVER 0x02
6295+#define ADM1029_CTL_INT_OVER 0x04
6296+#define ADM1029_CTL_ALARM_LOW 0x08
6297+#define ADM1029_CTL_CFAULT_UNDER 0x10
6298+#define ADM1029_CTL_ALARM_UNDER 0x20
6299+#define ADM1029_CTL_INT_UNDER 0x40
6300+#define ADM1029_CTL_LATCH 0x80
6301+
6302+#define ADM1029_FAN_CTL(i) (0x18 + i)
6303+#define ADM1029_TEMP_CTL(i) (0x40 + i)
6304+#define ADM1029_AIN_CTL(i) (0x50 + i)
6305+
6306+#define ADM1029_TEMP_HIGH(i) (0x90 + i)
6307+#define ADM1029_TEMP_LOW(i) (0x98 + i)
6308+#define ADM1029_AIN_HIGH(i) (0xa8 + i)
6309+#define ADM1029_AIN_LOW(i) (0xb0 + i)
6310+
6311+#define ADM1029_TEMP_VALUE(i) (0xa0 + i)
6312+#define ADM1029_AIN_VALUE(i) (0xb8 + i)
6313+
6314+#ifdef CONFIG_COBALT_ACPI
6315+static int
6316+adm1029_handler(cobalt_acpi_evt *evt, void * data)
6317+{
6318+ int j, k;
6319+
6320+ switch (evt->ev_type) {
6321+ case COBALT_ACPI_EVT_SM_INT:
6322+ evt->ev_data = 0;
6323+ evt->ev_type = COBALT_ACPI_EVT_VOLT;
6324+ for (j=0; j<cobalt_nvoltages; j++) {
6325+ k = cobalt_i2c_read_byte(COBALT_I2C_DEV_ADM1029,
6326+ ADM1029_AIN_CTL(volt_map[j].sensor));
6327+ if (k & ADM1029_CTL_LATCH) {
6328+ evt->ev_data |= (1 << j);
6329+ volt_map[j].cache = 0;
6330+ }
6331+ }
6332+ break;
6333+
6334+ case COBALT_ACPI_EVT_THERM:
6335+ evt->ev_data = 0;
6336+ for (j=0; j<cobalt_nthermals; j++) {
6337+ k = cobalt_i2c_read_byte(COBALT_I2C_DEV_ADM1029,
6338+ ADM1029_TEMP_CTL(therm_map[j].sensor));
6339+ if (k & ADM1029_CTL_LATCH) {
6340+ evt->ev_data |= (1 << j);
6341+ therm_map[j].cache = 0;
6342+ }
6343+ }
6344+ break;
6345+
6346+ default:
6347+ return -1;
6348+ }
6349+ return 0;
6350+}
6351+#endif /* CONFIG_COBALT_ACPI */
6352+
6353+static int
6354+adm1029_init(void)
6355+{
6356+
6357+#ifdef CONFIG_COBALT_ACPI
6358+ cobalt_acpi_register_evt_handler(adm1029_handler,
6359+ COBALT_ACPI_EVT_THERM, NULL);
6360+ cobalt_acpi_register_evt_handler(adm1029_handler,
6361+ COBALT_ACPI_EVT_SM_INT, NULL);
6362+#endif
6363+
6364+ return 0;
6365+}
6366+
6367+static int
6368+adm1029_therm_read(struct sensor *s)
6369+{
6370+ int sensor = s->sensor;
6371+ int val;
6372+
6373+ val = cobalt_i2c_read_byte(COBALT_I2C_DEV_ADM1029,
6374+ ADM1029_TEMP_VALUE(sensor));
6375+ if (val < 0) {
6376+ /* read failed, return the last known value */
6377+ return s->last_val;
6378+ }
6379+ if (val & 0x80) {
6380+ val -= 256;
6381+ }
6382+ val *= DEC_SCALAR;
6383+
6384+ return val;
6385+}
6386+
6387+static int
6388+adm1029_volt_read(struct sensor *s)
6389+{
6390+ int sensor = s->sensor;
6391+ int val;
6392+
6393+ val = cobalt_i2c_read_byte(COBALT_I2C_DEV_ADM1029,
6394+ ADM1029_AIN_VALUE(sensor));
6395+ if (val < 0) {
6396+ /* read failed, return the last known value */
6397+ return s->last_val;
6398+ }
6399+
6400+ /* already scaled by 100 */
6401+ val *= DEC_SCALAR/100;
6402+
6403+ return val;
6404+}
6405+
6406+static int
6407+alpine_vcore_scale(struct sensor *s, int val)
6408+{
6409+ /* the measured Vbat switch cost is negligable
6410+ * due to very low current through the diode */
6411+ return val;
6412+}
6413+
6414+#define VBAT_REG 0x608
6415+#define VBAT_BIT 0x1
6416+static void
6417+alpine_vbat_switch(struct sensor *s, int pre)
6418+{
6419+ unsigned char v = inb(VBAT_REG);
6420+ unsigned long j = jiffies;
6421+
6422+ if (pre) {
6423+ v |= VBAT_BIT;
6424+ /*
6425+ * disable AIN0 INT# assertion before switching to
6426+ * Vbat because the input is shared with Vcore and
6427+ * their acceptable ranges are very different.
6428+ */
6429+ cobalt_i2c_write_byte(COBALT_I2C_DEV_ADM1029,
6430+ ADM1029_AIN_CTL(s->sensor), 0x0);
6431+ } else {
6432+ v &= ~VBAT_BIT;
6433+ }
6434+
6435+ outb(v, VBAT_REG);
6436+
6437+ /*
6438+ * wait for the round-robin monitor to complete a cycle
6439+ * before _and_ after toggling Vbat switch, otherwise
6440+ * stale data in AIN0 will trigger INT# assertion.
6441+ */
6442+ while ((jiffies - j) < HZ) {
6443+ /* block for ~ 1sec */
6444+ set_current_state(TASK_INTERRUPTIBLE);
6445+ schedule_timeout(HZ);
6446+ }
6447+
6448+ if (!pre) {
6449+ /*
6450+ * now re-enable INT# assertion capability for AIN0
6451+ * (this also clears the AIN0 fault latch at bit 7)
6452+ */
6453+ cobalt_i2c_write_byte(COBALT_I2C_DEV_ADM1029,
6454+ ADM1029_AIN_CTL(s->sensor),
6455+ ADM1029_CTL_INT_OVER | ADM1029_CTL_INT_UNDER);
6456+ }
6457+}
6458+
6459+static int
6460+alpine_vbat_scale(struct sensor *s, int val)
6461+{
6462+ /*
6463+ * The spec says 2.5V max - but empirically, 3.3V works :)
6464+ * The Vbat switch costs 0.3 volts
6465+ */
6466+ if (val) val += (3 * DEC_SCALAR)/10;
6467+
6468+ return val;
6469+}
6470+
6471+#ifdef CONFIG_PROC_FS
6472+static int
6473+sensor_write_proc(int nsensors, struct sensor *map,
6474+ struct file *file, const char *buf, unsigned long len, void *x)
6475+{
6476+ char *pg;
6477+
6478+ if (len > PAGE_SIZE) {
6479+ return -EOVERFLOW;
6480+ }
6481+
6482+ pg = (char *)__get_free_page(GFP_KERNEL);
6483+ if (!pg) {
6484+ return -ENOMEM;
6485+ }
6486+
6487+ if (copy_from_user(pg, buf, len)) {
6488+ free_page((unsigned long)pg);
6489+ return -EFAULT;
6490+ }
6491+ pg[len] = '\0';
6492+
6493+ /* format: `cache_timeout #' in seconds */
6494+ if (len>15 && !strncmp("cache_timeout ", pg, 14) && isdigit(*(pg+14))) {
6495+ unsigned long i, sec = simple_strtoul(pg+14, NULL, 0);
6496+ for (i=0; i<nsensors; i++)
6497+ map[i].cache_timeout = sec;
6498+ }
6499+
6500+ free_page((unsigned long)pg);
6501+ return len;
6502+}
6503+
6504+static int
6505+sensor_read_proc(int nsensors, struct sensor *map,
6506+ char *buf, char **start, off_t pos, int len, int *eof, void *x)
6507+{
6508+ int i;
6509+ static int plen = 0;
6510+
6511+ down(&sensor_sem);
6512+
6513+ /* remember how big our last read was to avoid read() calling twice */
6514+ if (pos && pos >= plen) {
6515+ *eof = 1;
6516+ up(&sensor_sem);
6517+ return 0;
6518+ }
6519+
6520+ plen = 0;
6521+ for (i = 0; i < nsensors; i++) {
6522+ char sbuf[32];
6523+ if (sensor_read(&map[i], sbuf, sizeof(sbuf)))
6524+ plen += sprintf(buf+plen, "%d [%s]: %s\n", i, map[i].desc, sbuf);
6525+ }
6526+
6527+ up(&sensor_sem);
6528+
6529+ return cobalt_gen_proc_read(buf, plen, start, pos, len, eof);
6530+}
6531+
6532+static int
6533+therm_read_proc(char *buf, char **start, off_t pos, int len, int *eof, void *x)
6534+{
6535+ return sensor_read_proc(cobalt_nthermals, therm_map,
6536+ buf, start, pos, len, eof, x);
6537+}
6538+static int
6539+therm_write_proc(struct file *file, const char *buf, unsigned long len, void *x)
6540+{
6541+ return sensor_write_proc(cobalt_nthermals, therm_map, file, buf, len, x);
6542+}
6543+
6544+static int
6545+volt_read_proc(char *buf, char **start, off_t pos, int len, int *eof, void *x)
6546+{
6547+ return sensor_read_proc(cobalt_nvoltages, volt_map,
6548+ buf, start, pos, len, eof, x);
6549+}
6550+static int
6551+volt_write_proc(struct file *file, const char *buf, unsigned long len, void *x)
6552+{
6553+ return sensor_write_proc(cobalt_nvoltages, volt_map, file, buf, len, x);
6554+}
6555+#endif /* CONFIG_PROC_FS */
6556+
6557+#endif /* CONFIG_COBALT_SENSORS */
6558diff -Naur linux-2.6.18.2.orig/drivers/cobalt/serialnum.c linux-2.6.18.2/drivers/cobalt/serialnum.c
6559--- linux-2.6.18.2.orig/drivers/cobalt/serialnum.c 1969-12-31 16:00:00.000000000 -0800
6560+++ linux-2.6.18.2/drivers/cobalt/serialnum.c 2006-11-15 21:20:19.742033186 -0800
6561@@ -0,0 +1,453 @@
6562+/* $Id: serialnum.c,v 1.15 2001/10/23 20:15:27 thockin Exp $ */
6563+/*
6564+ *
6565+ * Author: Philip Gladstone, Axent Technologies
6566+ * modified for Nat Semi PC[89]7317 by asun@cobalt.com
6567+ * ported to 2.4.x by thockin@sun.com
6568+ * alpine serial eeprom by erik.glling@sun.com
6569+ * Copyright (c) 2000 Axent Technologies, Cobalt Networks
6570+ * Copyright (c) 2001 Axent Technologies, Sun Microsystems
6571+ *
6572+ * This module interrogates the DS2401 Silicon Serial Number chip
6573+ * that is attached to all x86 Cobalt systems.
6574+ *
6575+ * It exports /proc/cobalt/hostid which is four bytes generated from of
6576+ * the id. It can be linked to /var/adm/hostid or /etc/hostid for the
6577+ * hostid command to use.
6578+ *
6579+ * It exports /proc/cobalt/serialnumber which is the entire 64 bit value
6580+ * read back (in ascii).
6581+ *
6582+ * For the guts of the 1 wire protocol used herein, please see the DS2401
6583+ * specification.
6584+ *
6585+ * This program is free software; you can redistribute it and/or modify
6586+ * it under the terms of the GNU General Public License as published by
6587+ * the Free Software Foundation; either version 2 of the License, or
6588+ * (at your option) any later version.
6589+ *
6590+ * This program is distributed in the hope that it will be useful,
6591+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
6592+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6593+ * GNU General Public License for more details.
6594+ *
6595+ * You should have received a copy of the GNU General Public License
6596+ * along with this program; if not, write to the Free Software
6597+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
6598+ *
6599+ * This driver is SMP safe by nature. --TPH
6600+ */
6601+#include <linux/config.h>
6602+#if defined (CONFIG_COBALT_SERNUM) || defined(CONFIG_COBALT_SERNUM_MODULE)
6603+
6604+#include <linux/module.h>
6605+#include <linux/stddef.h>
6606+#include <linux/version.h>
6607+#include <linux/types.h>
6608+#include <linux/proc_fs.h>
6609+#include <linux/delay.h>
6610+#include <asm/uaccess.h>
6611+#include <linux/pci.h>
6612+#include <linux/init.h>
6613+#include <asm/io.h>
6614+
6615+#include <cobalt/cobalt.h>
6616+#include <cobalt/systype.h>
6617+#include <cobalt/superio.h>
6618+#include <cobalt/serialnum.h>
6619+#include <cobalt/i2c.h>
6620+
6621+#include <linux/interrupt.h>
6622+
6623+#define SN_DRIVER "Cobalt Networks Serial Number driver"
6624+#define SN_DRIVER_VMAJ 1
6625+#define SN_DRIVER_VMIN 6
6626+
6627+/* dependent on systype */
6628+static unsigned int sn_direction;
6629+static unsigned int sn_output;
6630+static unsigned int sn_input;
6631+static unsigned int sn_mask;
6632+
6633+/* 3k style systems */
6634+#define III_SN_DIRECTION 0x7d
6635+#define III_SN_OUTPUT 0x7e
6636+#define III_SN_INPUT 0x7f
6637+#define III_SN_MASK 0x08
6638+static struct pci_dev *id_dev;
6639+
6640+/* 5k style systems */
6641+#define V_SN_DIRECTION (sn_io_base + 0x01)
6642+#define V_SN_OUTPUT (sn_io_base + 0x00)
6643+#define V_SN_INPUT (sn_io_base + 0x00)
6644+#define V_SN_MASK (sn_io_base + 0x01)
6645+static unsigned int sn_io_base;
6646+
6647+#define SSN_SIZE 8 /* bytes */
6648+static char ssn_string[SSN_SIZE * 2 + 1];
6649+static unsigned long hostid;
6650+static int debug;
6651+#ifdef CONFIG_PROC_FS
6652+#ifdef CONFIG_COBALT_OLDPROC
6653+static struct proc_dir_entry *proc_hostid;
6654+static struct proc_dir_entry *proc_serialnum;
6655+#endif
6656+static struct proc_dir_entry *proc_chostid;
6657+static struct proc_dir_entry *proc_cserialnum;
6658+#endif
6659+
6660+static int
6661+hostid_read(char *buf, char **start, off_t pos, int len, int *eof, void *x)
6662+{
6663+ int plen = sizeof(hostid);
6664+ memcpy(buf, &hostid, sizeof(hostid));
6665+ return cobalt_gen_proc_read(buf, plen, start, pos, len, eof);
6666+}
6667+
6668+static int
6669+serialnum_read(char *buf, char **start, off_t pos, int len, int *eof, void *x)
6670+{
6671+ int plen = sizeof(ssn_string);
6672+ sprintf(buf, "%s\n", ssn_string);
6673+ return cobalt_gen_proc_read(buf, plen, start, pos, len, eof);
6674+}
6675+
6676+/* set up the requisite IO bits */
6677+static int __init
6678+io_init(void)
6679+{
6680+ unsigned char data;
6681+
6682+ if (cobt_is_3k()) {
6683+ /* The GPIO tied to the ID chip is on the PMU */
6684+ id_dev = pci_find_device(PCI_VENDOR_ID_AL,
6685+ PCI_DEVICE_ID_AL_M7101, NULL);
6686+ if (!id_dev) {
6687+ EPRINTK("can't find PMU for serialnumber access\n");
6688+ return -ENXIO;
6689+ }
6690+
6691+ /* Set input mode on GPIO3 */
6692+ pci_read_config_byte(id_dev, sn_direction, &data);
6693+ if (debug > 1) {
6694+ WPRINTK("read of register 0x%x = 0x%x\n",
6695+ sn_direction, data);
6696+ }
6697+ if (data & sn_mask) {
6698+ pci_write_config_byte(id_dev, sn_direction,
6699+ data & ~sn_mask);
6700+ }
6701+
6702+ /* Set the output value to be 0 */
6703+ pci_read_config_byte(id_dev, sn_output, &data);
6704+ if (debug > 1) {
6705+ WPRINTK("read of register 0x%x = 0x%x\n",
6706+ sn_output, data);
6707+ }
6708+ if (data & sn_mask) {
6709+ pci_write_config_byte(id_dev, sn_output,
6710+ data & ~sn_mask);
6711+ }
6712+ } else if (cobt_is_5k()) {
6713+ u16 addr;
6714+
6715+ addr = superio_ldev_base(PC87317_DEV_GPIO);
6716+ if (addr) {
6717+ u8 val;
6718+
6719+ sn_io_base = addr;
6720+
6721+ /* set output value to 0 */
6722+ val = inb(sn_direction);
6723+ outb(val | sn_mask, sn_direction);
6724+ data = inb(sn_output);
6725+ if (data & sn_mask) {
6726+ outb(data & ~sn_mask, sn_output);
6727+ }
6728+ /* set to input */
6729+ outb(val & ~sn_mask, sn_direction);
6730+ }
6731+ } else {
6732+ return -ENXIO;
6733+ }
6734+
6735+ /* pick proper variables */
6736+ if (cobt_is_3k()) {
6737+ sn_direction = III_SN_DIRECTION;
6738+ sn_output = III_SN_OUTPUT;
6739+ sn_input = III_SN_INPUT;
6740+ sn_mask = III_SN_MASK;
6741+ } else if (cobt_is_5k()) {
6742+ sn_direction = V_SN_DIRECTION;
6743+ sn_output = V_SN_OUTPUT;
6744+ sn_input = V_SN_INPUT;
6745+ sn_mask = V_SN_MASK;
6746+ } else {
6747+ return -1;
6748+ }
6749+
6750+ /* Let things calm down */
6751+ udelay(500);
6752+ return 0;
6753+}
6754+
6755+/* write out a bit */
6756+static void __init
6757+io_write(int delay)
6758+{
6759+ if (cobt_is_3k()) {
6760+ unsigned char data;
6761+ /* Set output mode on GPIO3 */
6762+ pci_read_config_byte(id_dev, sn_direction, &data);
6763+ pci_write_config_byte(id_dev, sn_direction, data | sn_mask);
6764+ udelay(delay);
6765+
6766+ /* Set input mode */
6767+ pci_write_config_byte(id_dev, sn_direction, data & ~sn_mask);
6768+ } else if (cobt_is_5k()) {
6769+ unsigned char direction;
6770+
6771+ /* change to output and back */
6772+ direction = inb(sn_direction);
6773+ outb(direction | sn_mask, sn_direction);
6774+ udelay(delay);
6775+ outb(direction & ~sn_mask, sn_direction);
6776+ }
6777+}
6778+
6779+/* read in a bit */
6780+static int __init
6781+io_read(void)
6782+{
6783+ unsigned char data = 0;
6784+
6785+ /* Get the input value */
6786+ if (cobt_is_3k()) {
6787+ pci_read_config_byte(id_dev, sn_input, &data);
6788+ } else if (cobt_is_5k()) {
6789+ data = inb(sn_input);
6790+ }
6791+
6792+ return (data & sn_mask) ? 1 : 0;
6793+}
6794+
6795+static void __init
6796+io_write_byte(unsigned char c)
6797+{
6798+ int i;
6799+ unsigned long flags;
6800+
6801+ local_save_flags(flags);
6802+
6803+ for (i = 0; i < 8; i++, c >>= 1) {
6804+ local_irq_disable();
6805+ if (c & 1) {
6806+ /* Transmit a 1 */
6807+ io_write(5);
6808+ udelay(80);
6809+ } else {
6810+ /* Transmit a 0 */
6811+ io_write(80);
6812+ udelay(10);
6813+ }
6814+ local_irq_restore(flags);
6815+ }
6816+}
6817+
6818+static int __init
6819+io_read_byte(void)
6820+{
6821+ int i;
6822+ int c = 0;
6823+ unsigned long flags;
6824+
6825+ local_save_flags(flags);
6826+
6827+ for (i = 0; i < 8; i++) {
6828+ local_irq_disable();
6829+ io_write(1); /* Start the read */
6830+ udelay(2);
6831+ if (io_read()) {
6832+ c |= 1 << i;
6833+ }
6834+ udelay(60);
6835+ local_irq_restore(flags);
6836+ }
6837+
6838+ return c;
6839+}
6840+
6841+static int __init
6842+get_ssn(unsigned char *buf)
6843+{
6844+ int i;
6845+ unsigned long flags;
6846+
6847+ /*
6848+ * Alpine does not have a dallas chip. Instead
6849+ * we read from an eprom.
6850+ */
6851+ if (cobt_is_alpine()) {
6852+ for (i = 0; i < 8; i++) {
6853+ buf[i] = cobalt_i2c_read_byte(COBALT_I2C_DEV_AT24C02,
6854+ 12 + i);
6855+ }
6856+ return 0;
6857+ }
6858+
6859+ /*
6860+ * bit-bang the Dallas 2401
6861+ */
6862+
6863+ local_save_flags(flags);
6864+ local_irq_disable();
6865+
6866+ /* Master Reset Pulse */
6867+ for (i = 0; i < 600; i += 30) {
6868+ if (io_read()) {
6869+ break;
6870+ }
6871+ }
6872+
6873+ if (i >= 600) {
6874+ if (debug) {
6875+ EPRINTK("the data line seems to be held low\n");
6876+ }
6877+ local_irq_restore(flags);
6878+ return -ENXIO;
6879+ }
6880+
6881+ io_write(600);
6882+
6883+ for (i = 0; i < 300; i += 15) {
6884+ udelay(15);
6885+ if (io_read() == 0) {
6886+ /* We got a presence pulse */
6887+ udelay(600); /* Wait for things to quiet down */
6888+ break;
6889+ }
6890+ }
6891+ local_irq_restore(flags);
6892+
6893+ if (i >= 300) {
6894+ if (debug)
6895+ EPRINTK("no presence pulse detected\n");
6896+ return -ENXIO;
6897+ }
6898+
6899+ io_write_byte(0x33);
6900+
6901+ for (i = 0; i < 8; i++) {
6902+ int rc;
6903+
6904+ rc = io_read_byte();
6905+ if (rc < 0) {
6906+ return rc;
6907+ }
6908+
6909+ *buf++ = rc;
6910+ }
6911+
6912+ return 0;
6913+}
6914+
6915+int __init
6916+cobalt_serialnum_init(void)
6917+{
6918+ unsigned char ssn[SSN_SIZE];
6919+ int rc;
6920+ int i;
6921+
6922+ printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", SN_DRIVER,SN_DRIVER_VMAJ,SN_DRIVER_VMIN);
6923+ /* set up for proper IO */
6924+ rc = io_init();
6925+ if (rc) {
6926+ return rc;
6927+ }
6928+
6929+ /*
6930+ * NOTE: the below algorithm CAN NOT be changed. We have many systems
6931+ * out there registered with the serial number AS DERIVED by this
6932+ * algorithm.
6933+ */
6934+
6935+ rc = get_ssn(ssn);
6936+ if (rc) {
6937+ return rc;
6938+ }
6939+
6940+ /* Convert to ssn_string */
6941+ for (i = 7; i >= 0; i--) {
6942+ sprintf(ssn_string + (7 - i) * 2, "%02x", ssn[i]);
6943+ }
6944+
6945+ /* get four bytes for a pretty unique (not guaranteed) hostid */
6946+ hostid = *(unsigned long *)ssn ^ *(unsigned long *)(ssn+4);
6947+
6948+#ifdef CONFIG_PROC_FS
6949+#ifdef CONFIG_COBALT_OLDPROC
6950+ proc_hostid = create_proc_read_entry("hostid", 0, NULL,
6951+ hostid_read, NULL);
6952+ if (!proc_hostid) {
6953+ EPRINTK("can't create /proc/hostid\n");
6954+ }
6955+ proc_serialnum = create_proc_read_entry("serialnumber", 0, NULL,
6956+ serialnum_read, NULL);
6957+ if (!proc_serialnum) {
6958+ EPRINTK("can't create /proc/serialnumber\n");
6959+ }
6960+#endif
6961+ proc_chostid = create_proc_read_entry("hostid", 0, proc_cobalt,
6962+ hostid_read, NULL);
6963+ if (!proc_chostid) {
6964+ EPRINTK("can't create /proc/cobalt/hostid\n");
6965+ }
6966+ proc_cserialnum = create_proc_read_entry("serialnumber", 0,
6967+ proc_cobalt, serialnum_read, NULL);
6968+ if (!proc_cserialnum) {
6969+ EPRINTK("can't create /proc/cobalt/serialnumber\n");
6970+ }
6971+#endif
6972+
6973+ return 0;
6974+}
6975+
6976+char *
6977+cobalt_serialnum_get(void)
6978+{
6979+ return ssn_string;
6980+}
6981+
6982+unsigned long
6983+cobalt_hostid_get(void)
6984+{
6985+ return hostid;
6986+}
6987+
6988+#if defined(CONFIG_COBALT_SERNUM_MODULE)
6989+MODULE_PARM(debug, "i");
6990+
6991+int
6992+init_module(void)
6993+{
6994+ return cobalt_serialnum_init();
6995+}
6996+
6997+void
6998+cleanup_module(void)
6999+{
7000+#ifdef CONFIG_PROC_FS
7001+#ifdef CONFIG_COBALT_OLDPROC
7002+ remove_proc_entry("hostid", NULL);
7003+ remove_proc_entry("serialnumber", NULL);
7004+#endif
7005+ remove_proc_entry("hostid", proc_cobalt);
7006+ remove_proc_entry("serialnumber", proc_cobalt);
7007+#endif
7008+}
7009+
7010+module_init(init_module);
7011+module_exit(cleanup_module);
7012+#endif /* MODULE */
7013+
7014+#endif /* CONFIG_COBALT_SERNUM */
7015diff -Naur linux-2.6.18.2.orig/drivers/cobalt/systype.c linux-2.6.18.2/drivers/cobalt/systype.c
7016--- linux-2.6.18.2.orig/drivers/cobalt/systype.c 1969-12-31 16:00:00.000000000 -0800
7017+++ linux-2.6.18.2/drivers/cobalt/systype.c 2006-11-15 21:20:19.742033186 -0800
7018@@ -0,0 +1,280 @@
7019+/*
7020+ * $Id: systype.c,v 1.33 2002/11/04 17:54:15 thockin Exp $
7021+ * systype.c : routines for figuring out which Cobalt system this is
7022+ *
7023+ * Copyright 2001-2002 Sun Microsystems, Inc.
7024+ *
7025+ * By: Tim Hockin
7026+ * Adrian Sun
7027+ * Duncan Laurie
7028+ *
7029+ * This driver is SMP safe by nature. --TPH
7030+ */
7031+
7032+#include <linux/config.h>
7033+
7034+#include <linux/pci.h>
7035+#include <linux/init.h>
7036+#include <linux/proc_fs.h>
7037+#include <linux/module.h>
7038+
7039+#include <cobalt/cobalt.h>
7040+#include <cobalt/systype.h>
7041+#include <cobalt/i2c.h>
7042+
7043+/* for easy first-pass analysis */
7044+#if defined(CONFIG_COBALT_GEN_III)
7045+int COBALT_GENERATION_III_DEFINED;
7046+#endif
7047+#if defined(CONFIG_COBALT_GEN_V)
7048+int COBALT_GENERATION_V_DEFINED;
7049+#endif
7050+
7051+cobt_sys_t cobt_type = COBT_UNINITIALIZED;
7052+EXPORT_SYMBOL(cobt_type);
7053+unsigned long cobt_rev;
7054+EXPORT_SYMBOL(cobt_rev);
7055+
7056+#ifdef CONFIG_PROC_FS
7057+static struct proc_dir_entry *proc_systype;
7058+#endif
7059+static int systype_read_proc(char *buf, char **start, off_t pos, int len,
7060+ int *eof, void *x);
7061+static char *systype_str(cobt_sys_t type);
7062+static unsigned long boardrev_read(void);
7063+
7064+void __init
7065+cobalt_boardrev_init(void)
7066+{
7067+ cobt_rev = boardrev_read();
7068+}
7069+
7070+int __init
7071+cobalt_systype_init(void)
7072+{
7073+ cobalt_systype_probe();
7074+
7075+#ifdef CONFIG_PROC_FS
7076+ proc_systype = create_proc_read_entry("systype", 0,
7077+ proc_cobalt, systype_read_proc, NULL);
7078+ if (!proc_systype) {
7079+ EPRINTK("can't create /proc/cobalt/systype\n");
7080+ }
7081+#endif
7082+
7083+ if (cobt_type == COBT_UNKNOWN) {
7084+ printk(KERN_INFO "Cobalt system type is unknown, trouble will ensue (I can vouch for this)\n");
7085+ return -1;
7086+ } else {
7087+ printk(KERN_INFO "Cobalt system type is %s\n",systype_str(cobt_type));
7088+ return 0;
7089+ }
7090+}
7091+
7092+#if defined(CONFIG_COBALT_GEN_III)
7093+static cobt_sys_t
7094+systype_probe_3k(void)
7095+{
7096+ struct pci_dev *pdev;
7097+ cobt_sys_t retval = COBT_UNKNOWN;
7098+
7099+ /* board identifier for RaQ3/4 vs Qube3 is on the PMU @ 0x7f */
7100+ pdev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL);
7101+ if (pdev) {
7102+ /*
7103+ * check to see what board we are on
7104+ * ( RaQ 3, RaQ 4, Qube 3 )
7105+ */
7106+ unsigned char val;
7107+
7108+ /* momentarily set DOGB# to input */
7109+ pci_read_config_byte(pdev, 0x7d, &val);
7110+ pci_write_config_byte(pdev, 0x7d, val & ~0x20);
7111+
7112+ /* read the GPIO register */
7113+ pci_read_config_byte(pdev, 0x7f, &val);
7114+ /* RaQ3/4 boards have DOGB (0x20) high,
7115+ * Qube3 has DOGB low */
7116+ if (val & 0x20) {
7117+ retval = COBT_PACIFICA;
7118+ } else {
7119+ retval = COBT_CARMEL;
7120+ }
7121+
7122+ /* change DOGB back to output */
7123+ pci_read_config_byte(pdev, 0x7d, &val);
7124+ pci_write_config_byte(pdev, 0x7d, val | 0x20);
7125+ }
7126+
7127+ /* assign to this, so the compiler shuts up */
7128+ COBALT_GENERATION_III_DEFINED = 1;
7129+
7130+ return retval;
7131+}
7132+#else
7133+#define systype_probe_3k() (COBT_UNKNOWN)
7134+#endif
7135+
7136+#if defined(CONFIG_COBALT_GEN_V)
7137+static cobt_sys_t
7138+systype_probe_5k(void)
7139+{
7140+ struct pci_dev *pdev;
7141+ cobt_sys_t retval = COBT_UNKNOWN;
7142+
7143+ /* is it a gen V ? */
7144+ pdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
7145+ PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL);
7146+ if (pdev) {
7147+ retval = COBT_MONTEREY;
7148+ goto out;
7149+ }
7150+
7151+ pdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
7152+ PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL);
7153+ if (pdev) {
7154+ pdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
7155+ PCI_DEVICE_ID_SERVERWORKS_LE, NULL);
7156+ if (pdev) {
7157+ retval = COBT_ALPINE;
7158+ goto out;
7159+ }
7160+ }
7161+
7162+out:
7163+ /* assign to this, so the compiler shuts up */
7164+ COBALT_GENERATION_V_DEFINED = 1;
7165+
7166+ return retval;
7167+}
7168+#else
7169+#define systype_probe_5k() (COBT_UNKNOWN)
7170+#endif
7171+
7172+static cobt_sys_t
7173+systype_probe_gp(void)
7174+{
7175+ struct pci_dev *pdev;
7176+ cobt_sys_t retval = COBT_UNKNOWN;
7177+
7178+ /* is it a GP system? */
7179+ pdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
7180+ PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL);
7181+ if (pdev) {
7182+ pdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS,
7183+ PCI_DEVICE_ID_SERVERWORKS_HE, NULL);
7184+ if (pdev) {
7185+ retval = COBT_BIGBEAR;
7186+ }
7187+ }
7188+
7189+ return retval;
7190+}
7191+
7192+cobt_sys_t
7193+cobalt_systype_probe(void)
7194+{
7195+ static int init_done = 0;
7196+
7197+ if (init_done) {
7198+ return cobt_type;
7199+ }
7200+
7201+ /* check for 3k family systems */
7202+
7203+ cobt_type = systype_probe_3k();
7204+ if (cobt_type != COBT_UNKNOWN)
7205+ goto out;
7206+
7207+ /* check for 5k family systems */
7208+ cobt_type = systype_probe_5k();
7209+ if (cobt_type != COBT_UNKNOWN)
7210+ goto out;
7211+
7212+ /* it's a GP system or unknown */
7213+ cobt_type = systype_probe_gp();
7214+
7215+out:
7216+ if (cobt_type != COBT_UNKNOWN) {
7217+ init_done = 1;
7218+ }
7219+
7220+ return cobt_type;
7221+}
7222+EXPORT_SYMBOL(cobalt_systype_probe);
7223+
7224+#ifdef CONFIG_PROC_FS
7225+static int
7226+systype_read_proc(char *buf, char **start, off_t pos, int len,
7227+ int *eof, void *x)
7228+{
7229+ int plen = sprintf(buf, "%s\n", systype_str(cobt_type));
7230+ return cobalt_gen_proc_read(buf, plen, start, pos, len, eof);
7231+}
7232+#endif
7233+
7234+static char *
7235+systype_str(cobt_sys_t type)
7236+{
7237+ switch (type) {
7238+ case COBT_PACIFICA:
7239+ return "Pacifica";
7240+ break;
7241+ case COBT_CARMEL:
7242+ return "Carmel";
7243+ break;
7244+ case COBT_MONTEREY:
7245+ return "Monterey";
7246+ break;
7247+ case COBT_ALPINE:
7248+ return "Alpine";
7249+ break;
7250+ case COBT_BIGBEAR:
7251+ return "BigBear";
7252+ break;
7253+ case COBT_UNKNOWN:
7254+ default:
7255+ return "unknown";
7256+ break;
7257+ }
7258+}
7259+
7260+static unsigned long
7261+boardrev_read(void)
7262+{
7263+ unsigned long rev;
7264+
7265+ switch (cobt_type) {
7266+#ifdef CONFIG_COBALT_RAQ
7267+ case COBT_PACIFICA:
7268+ case COBT_CARMEL:
7269+ /* No usable board rev on these systems */
7270+ return 0;
7271+ case COBT_MONTEREY:
7272+ /*
7273+ * the boardrev on monterey is strapped off of GPM[3:0]
7274+ * and is read from port 0xc52
7275+ */
7276+ return inb(0xc52);
7277+ case COBT_ALPINE:
7278+ /*
7279+ * the boardrev on alpine in stored in the i2c eeprom
7280+ * location 4
7281+ */
7282+ rev = cobalt_i2c_read_byte(COBALT_I2C_DEV_AT24C02, 0x04);
7283+ rev |= cobalt_i2c_read_byte(COBALT_I2C_DEV_AT24C02, 0x05) << 8;
7284+ rev |= cobalt_i2c_read_byte(COBALT_I2C_DEV_AT24C02, 0x06) << 16;
7285+ rev |= cobalt_i2c_read_byte(COBALT_I2C_DEV_AT24C02, 0x07) << 24;
7286+ if (rev == 0xffffffff)
7287+ rev = 0;
7288+ return rev;
7289+#endif
7290+ case COBT_BIGBEAR:
7291+ /* No board revs at this time */
7292+ return 0;
7293+ case COBT_UNKNOWN:
7294+ case COBT_UNINITIALIZED:
7295+ return 0;
7296+ }
7297+ return 0;
7298+}
7299diff -Naur linux-2.6.18.2.orig/drivers/cobalt/wdt.c linux-2.6.18.2/drivers/cobalt/wdt.c
7300--- linux-2.6.18.2.orig/drivers/cobalt/wdt.c 1969-12-31 16:00:00.000000000 -0800
7301+++ linux-2.6.18.2/drivers/cobalt/wdt.c 2006-11-15 21:20:19.742033186 -0800
7302@@ -0,0 +1,424 @@
7303+/* $Id: wdt.c,v 1.21 2002/07/02 00:38:17 asun Exp $ */
7304+/*
7305+ * Cobalt kernel WDT timer driver
7306+ * Tim Hockin <thockin@cobaltnet.com>
7307+ * Adrian Sun <asun@cobalt.com>
7308+ * Chris Johnson <cjohnson@cobalt.com>
7309+ * Copyright (c)1999-2000, Cobalt Networks
7310+ * Copyright (c)2001, Sun Microsystems
7311+ *
7312+ * This should be SMP safe. Every external function (except trigger_reboot)
7313+ * grabs the wdt lock. No function in this file may call any exported
7314+ * function (excepting trigger_reboot). The disable counter is an atomic, so
7315+ * there should be no issues there. --TPH
7316+ */
7317+#include <linux/config.h>
7318+
7319+#include <linux/module.h>
7320+#include <stdarg.h>
7321+#include <stddef.h>
7322+#include <linux/init.h>
7323+#include <linux/sched.h>
7324+#include <linux/timer.h>
7325+#include <linux/config.h>
7326+#include <linux/pci.h>
7327+#include <linux/delay.h>
7328+#include <asm/io.h>
7329+#include <asm/msr.h>
7330+
7331+#include <cobalt/cobalt.h>
7332+#include <cobalt/systype.h>
7333+#include <cobalt/wdt.h>
7334+#include <cobalt/superio.h>
7335+
7336+#define DOGB 0x20
7337+#define ALI_7101_WDT 0x92
7338+#define ALI_WDT_ARM 0x01
7339+#define WDT_3K_TIMEOUT (HZ >> 4) /* 1/16 second */
7340+
7341+#define WDT_SUPERIO_TIMEOUT (0x01) /* 1 minute */
7342+#define WDT_5K_TIMEOUT (HZ << 3) /* 8 seconds */
7343+
7344+#define WDT_DRIVER "Cobalt Networks Watchdog Timer driver"
7345+#define WDT_DRIVER_VMAJ 1
7346+#define WDT_DRIVER_VMIN 0
7347+
7348+static unsigned long wdt_timeout;
7349+static unsigned long long tsc_per_wdt;
7350+static int initialized;
7351+
7352+#ifdef CONFIG_COBALT_WDT
7353+struct timer_list cobalt_wdt_timer;
7354+static atomic_t cobalt_wdt_disable_count = ATOMIC_INIT(0);
7355+static spinlock_t wdt_lock = SPIN_LOCK_UNLOCKED;
7356+#endif
7357+
7358+/* gen III */
7359+static struct pci_dev *cobalt_pmu;
7360+static int use_pic;
7361+/* gen V */
7362+static u16 superio_pm_port;
7363+
7364+#ifdef CONFIG_COBALT_WDT
7365+static void do_refresh(void);
7366+static void do_cleardog(void);
7367+static void do_disable(void);
7368+static void do_reenable(void);
7369+#endif
7370+
7371+static unsigned long __init
7372+chipset_setup(void)
7373+{
7374+ unsigned char tmp;
7375+ if (cobt_is_3k()) {
7376+ /*
7377+ * Set up the PMU for 3k boards. It has a max
7378+ * of a 1 second timeout.
7379+ */
7380+ struct pci_dev *south;
7381+
7382+ /* PMU (1543 ver A1-E) has a built-in WDT. Set it to 1 sec */
7383+ cobalt_pmu = pci_find_device(PCI_VENDOR_ID_AL,
7384+ PCI_DEVICE_ID_AL_M7101, NULL);
7385+ if (!cobalt_pmu) {
7386+ EPRINTK("can't find south bridge for WDT\n");
7387+ return 0;
7388+ }
7389+ pci_write_config_byte(cobalt_pmu, ALI_7101_WDT, 0x02);
7390+
7391+ /* why it is called 1543, but DevId is 1533 I'll never know */
7392+ south = pci_find_device(PCI_VENDOR_ID_AL,
7393+ PCI_DEVICE_ID_AL_M1533, NULL);
7394+ if (!south) {
7395+ EPRINTK("can't find south bridge for WDT\n");
7396+ use_pic = 1;
7397+ } else {
7398+ /* reversion # is here - must match ???1001?(b)
7399+ * else use PIC for WDT */
7400+ pci_read_config_byte(south, 0x5e, &tmp);
7401+ use_pic = ((tmp & 0x1e) != 0x12);
7402+ }
7403+
7404+ if (!use_pic) {
7405+ /* set DOGB GPIO pin to OUTPUT - JIC */
7406+ pci_read_config_byte(cobalt_pmu, 0x7d, &tmp);
7407+ pci_write_config_byte(cobalt_pmu, 0x7d, tmp | DOGB);
7408+ }
7409+ return WDT_3K_TIMEOUT;
7410+ } else if (cobt_is_monterey()) {
7411+ /*
7412+ * Set up the Nat. Semi SuperI/O for XTR. It has a
7413+ * minimum of a 1 minute timeout.
7414+ */
7415+
7416+ /* superi/o -- select pm logical device and get base address */
7417+ superio_pm_port = superio_ldev_base(PC87317_DEV_PM);
7418+#ifdef CONFIG_COBALT_WDT
7419+ if (!superio_pm_port) {
7420+ return 0;
7421+ }
7422+ outb(PC87317_PMDEV_WDTO, superio_pm_port);
7423+ outb(WDT_SUPERIO_TIMEOUT, superio_pm_port + 1);
7424+#endif
7425+ return WDT_5K_TIMEOUT;
7426+ } else if (cobt_is_alpine()) {
7427+ /*
7428+ * Set up the Nat. Semi SuperI/O for Alpine. It has a
7429+ * minimum of a 1 minute timeout.
7430+ */
7431+
7432+ /* superi/o -- select pm logical device and get base address */
7433+ superio_pm_port = superio_ldev_base(PC87417_DEV_SWC);
7434+#ifdef CONFIG_COBALT_WDT
7435+ if (!superio_pm_port) {
7436+ return 0;
7437+ }
7438+ /* select the WDT bank of SWC */
7439+ outb(PC87417_SWCBANK_WDT, superio_pm_port+PC87417_SWC_BANK);
7440+ /* clear event config... */
7441+ tmp = inb(superio_pm_port+PC87417_WDT_CONFIG);
7442+ outb(0, superio_pm_port+PC87417_WDT_CONFIG);
7443+ /* ...before mucking with timeout */
7444+ outb(WDT_SUPERIO_TIMEOUT,
7445+ superio_pm_port+PC87417_WDT_TIMEOUT);
7446+ /* restore the event config */
7447+ outb(tmp, superio_pm_port+PC87417_WDT_CONFIG);
7448+ /* enable the counter */
7449+ outb(1, superio_pm_port+PC87417_WDT_CONTROL);
7450+#endif
7451+ return WDT_5K_TIMEOUT;
7452+ }
7453+
7454+ return 0;
7455+}
7456+
7457+void __init
7458+cobalt_wdt_init(void)
7459+{
7460+ unsigned long long start, stop;
7461+
7462+ printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", WDT_DRIVER,WDT_DRIVER_VMAJ,WDT_DRIVER_VMIN);
7463+
7464+ wdt_timeout = chipset_setup();
7465+
7466+ /* figure out time */
7467+ rdtscll(start);
7468+ udelay(100);
7469+ rdtscll(stop);
7470+
7471+ /*
7472+ * (int) (stop - start) * 10 == tsc per msec
7473+ * 1000 / HZ == msec per tick
7474+ * wdt_timeout == ticks per watchdog rearm
7475+ */
7476+ tsc_per_wdt = (int) (stop - start) * 10 * (1000 * wdt_timeout / HZ);
7477+
7478+#ifdef CONFIG_COBALT_WDT
7479+ /* set the timer going */
7480+ init_timer(&cobalt_wdt_timer);
7481+ cobalt_wdt_timer.function = cobalt_wdt_refresh;
7482+ cobalt_wdt_timer.data = 1;
7483+ cobalt_wdt_timer.expires = jiffies + wdt_timeout;
7484+ add_timer(&cobalt_wdt_timer);
7485+
7486+ /* the first timer tick will set it going */
7487+
7488+ if (cobt_is_3k() && use_pic) {
7489+ WPRINTK("Cobalt WDT - old board, using PIC controller\n");
7490+ }
7491+#endif /* CONFIG_COBALT_WDT */
7492+
7493+ initialized = 1;
7494+}
7495+
7496+static inline void
7497+hw_disable(void)
7498+{
7499+ if (cobt_is_3k()) {
7500+ char tmp;
7501+ /* read the value, disable (reset) WDT */
7502+ pci_read_config_byte(cobalt_pmu, ALI_7101_WDT, &tmp);
7503+ pci_write_config_byte(cobalt_pmu, ALI_7101_WDT,
7504+ (tmp & ~ALI_WDT_ARM));
7505+ } else if (cobt_is_monterey()) {
7506+ outb(PC87317_PMDEV_WDTO, superio_pm_port);
7507+ outb(0, superio_pm_port + 1);
7508+ } else if (cobt_is_alpine()) {
7509+ unsigned char tmp;
7510+ /* select the WDT bank of SWC */
7511+ outb(PC87417_SWCBANK_WDT, superio_pm_port + PC87417_SWC_BANK);
7512+ /* clear event config before mucking with timeout */
7513+ tmp = inb(superio_pm_port + PC87417_WDT_CONFIG);
7514+ outb(0, superio_pm_port + PC87417_WDT_CONFIG);
7515+ /*
7516+ * Disable it by setting a 0 time-out.
7517+ * The spec says 00h is reserved, but NSC confirms this is the
7518+ * way to disable the device.
7519+ */
7520+ outb(0, superio_pm_port + PC87417_WDT_TIMEOUT);
7521+ /* restore the event config */
7522+ outb(tmp, superio_pm_port + PC87417_WDT_CONFIG);
7523+ }
7524+}
7525+
7526+static inline void
7527+hw_enable(void)
7528+{
7529+ if (cobt_is_3k()) {
7530+ unsigned char tmp;
7531+ /* read the value, disable (reset) WDT, enable WDT */
7532+ pci_read_config_byte(cobalt_pmu, ALI_7101_WDT, &tmp);
7533+ pci_write_config_byte(cobalt_pmu, ALI_7101_WDT,
7534+ (tmp | ALI_WDT_ARM));
7535+ if (use_pic) {
7536+ /* transition GPIO 5 (DOGB) to arm/clear timer */
7537+ pci_read_config_byte(cobalt_pmu, 0x7e, &tmp);
7538+ pci_write_config_byte(cobalt_pmu, 0x7e, tmp ^ DOGB);
7539+ }
7540+ } else if (cobt_is_monterey()) {
7541+ outb(PC87317_PMDEV_WDTO, superio_pm_port);
7542+ outb(WDT_SUPERIO_TIMEOUT, superio_pm_port + 1);
7543+ } else if (cobt_is_alpine()) {
7544+ unsigned char tmp;
7545+ /* select the WDT bank of SWC */
7546+ outb(PC87417_SWCBANK_WDT, superio_pm_port + PC87417_SWC_BANK);
7547+ /* clear event config before mucking with timeout */
7548+ tmp = inb(superio_pm_port + PC87417_WDT_CONFIG);
7549+ outb(0, superio_pm_port + PC87417_WDT_CONFIG);
7550+ /* enable and refresh the timer */
7551+ outb(WDT_SUPERIO_TIMEOUT,
7552+ superio_pm_port + PC87417_WDT_TIMEOUT);
7553+ outb(0x80, superio_pm_port + PC87417_WDT_CONTROL);
7554+ /* restore event config */
7555+ outb(tmp, superio_pm_port + PC87417_WDT_CONFIG);
7556+ }
7557+}
7558+
7559+#ifdef CONFIG_COBALT_WDT
7560+static void
7561+do_refresh(void)
7562+{
7563+ if (!initialized) {
7564+ return;
7565+ }
7566+
7567+ do_cleardog();
7568+
7569+ /* re-arm the timer - this is locked in mod_timer() */
7570+ mod_timer(&cobalt_wdt_timer, jiffies + wdt_timeout);
7571+}
7572+#endif
7573+
7574+EXPORT_SYMBOL(cobalt_wdt_refresh);
7575+void
7576+cobalt_wdt_refresh(unsigned long refresh_timer)
7577+{
7578+#ifdef CONFIG_COBALT_WDT
7579+ unsigned long flags;
7580+ spin_lock_irqsave(&wdt_lock, flags);
7581+ do_refresh();
7582+ spin_unlock_irqrestore(&wdt_lock, flags);
7583+#endif
7584+}
7585+
7586+#ifdef CONFIG_COBALT_WDT
7587+static void
7588+do_cleardog(void)
7589+{
7590+ static unsigned long long last_tsc = 0;
7591+ unsigned long long tmp;
7592+
7593+ if (!initialized || (atomic_read(&cobalt_wdt_disable_count) > 0)) {
7594+ return;
7595+ }
7596+
7597+ /* only bother if we're due */
7598+ rdtscll(tmp);
7599+ if ((int)(tmp - last_tsc) < tsc_per_wdt) {
7600+ return;
7601+ }
7602+
7603+ if (cobt_is_3k() || cobt_is_monterey()) {
7604+ /* this is how we re-start the clock */
7605+ hw_disable();
7606+ hw_enable();
7607+ } else if (cobt_is_alpine()) {
7608+ /* select the WDT bank of SWC */
7609+ outb(PC87417_SWCBANK_WDT, superio_pm_port + PC87417_SWC_BANK);
7610+ /* refresh the timer */
7611+ outb(0x80, superio_pm_port + PC87417_WDT_CONTROL);
7612+ }
7613+
7614+ rdtscll(last_tsc);
7615+}
7616+#endif
7617+
7618+EXPORT_SYMBOL(cobalt_wdt_cleardog);
7619+void
7620+cobalt_wdt_cleardog(void)
7621+{
7622+#ifdef CONFIG_COBALT_WDT
7623+ unsigned long flags;
7624+
7625+ spin_lock_irqsave(&wdt_lock, flags);
7626+ do_cleardog();
7627+ spin_unlock_irqrestore(&wdt_lock, flags);
7628+#endif
7629+}
7630+
7631+/*
7632+ * this is called from machine_restart. it should not be used on
7633+ * 5k machines.
7634+ */
7635+EXPORT_SYMBOL(cobalt_wdt_trigger_reboot);
7636+void
7637+cobalt_wdt_trigger_reboot(void)
7638+{
7639+ if (cobt_is_3k()) {
7640+ if (!cobalt_pmu) {
7641+ WPRINTK("no PMU found!\n");
7642+ WPRINTK("reboot not possible!\n");
7643+ return;
7644+ }
7645+
7646+#ifdef CONFIG_COBALT_WDT
7647+ /* stop feeding it */
7648+ del_timer_sync(&cobalt_wdt_timer);
7649+#endif
7650+
7651+ /* kiss your rear goodbye... */
7652+ initialized = 0;
7653+ hw_disable();
7654+ hw_enable();
7655+ }
7656+}
7657+
7658+#ifdef CONFIG_COBALT_WDT
7659+static void
7660+do_disable(void)
7661+{
7662+ if (!initialized) {
7663+ return;
7664+ }
7665+
7666+ if (atomic_read(&cobalt_wdt_disable_count) == 0) {
7667+ atomic_inc(&cobalt_wdt_disable_count);
7668+ del_timer_sync(&cobalt_wdt_timer);
7669+ hw_disable();
7670+ }
7671+}
7672+#endif
7673+
7674+EXPORT_SYMBOL(cobalt_wdt_disable);
7675+void
7676+cobalt_wdt_disable(void)
7677+{
7678+#ifdef CONFIG_COBALT_WDT
7679+ unsigned long flags;
7680+
7681+ if (cobt_is_3k() && use_pic) {
7682+ WPRINTK("in PIC mode - cannot disable\n");
7683+ return;
7684+ }
7685+
7686+ spin_lock_irqsave(&wdt_lock, flags);
7687+ do_disable();
7688+ spin_unlock_irqrestore(&wdt_lock, flags);
7689+#endif
7690+}
7691+
7692+#ifdef CONFIG_COBALT_WDT
7693+static void
7694+do_reenable(void)
7695+{
7696+ int dcnt;
7697+
7698+ if (!initialized) {
7699+ return;
7700+ }
7701+
7702+ atomic_dec(&cobalt_wdt_disable_count);
7703+ dcnt = atomic_read(&cobalt_wdt_disable_count);
7704+
7705+ if (dcnt == 0) {
7706+ do_refresh();
7707+ } else if (dcnt < 0) {
7708+ WPRINTK("too many enables\n");
7709+ atomic_set(&cobalt_wdt_disable_count, 0);
7710+ }
7711+}
7712+#endif
7713+
7714+
7715+EXPORT_SYMBOL(cobalt_wdt_reenable);
7716+void
7717+cobalt_wdt_reenable(void)
7718+{
7719+#ifdef CONFIG_COBALT_WDT
7720+ unsigned long flags;
7721+
7722+ spin_lock_irqsave(&wdt_lock, flags);
7723+ do_reenable();
7724+ spin_unlock_irqrestore(&wdt_lock, flags);
7725+#endif
7726+}
7727diff -Naur linux-2.6.18.2.orig/drivers/net/Kconfig linux-2.6.18.2/drivers/net/Kconfig
7728--- linux-2.6.18.2.orig/drivers/net/Kconfig 2006-11-03 17:33:58.000000000 -0800
7729+++ linux-2.6.18.2/drivers/net/Kconfig 2006-11-15 21:20:19.742033186 -0800
7730@@ -1486,6 +1486,16 @@
7731 <file:Documentation/networking/net-modules.txt>. The module
7732 will be called e100.
7733
7734+config E100_IGNORE_CSUM
7735+ bool "Ignore bad EEPROM checksum"
7736+ depends on E100 && EXPERIMENTAL && !CLEAN_COMPILE
7737+ help
7738+ This option tells the e100 driver to ignore bad EEPROM checksums.
7739+ Usually this is a bad idea, as an incorrect checksum can indicate a
7740+ serious issue with the network card.
7741+
7742+ If unsure, say N.
7743+
7744 config LNE390
7745 tristate "Mylex EISA LNE390A/B support (EXPERIMENTAL)"
7746 depends on NET_PCI && EISA && EXPERIMENTAL
7747diff -Naur linux-2.6.18.2.orig/drivers/net/e100.c linux-2.6.18.2/drivers/net/e100.c
7748--- linux-2.6.18.2.orig/drivers/net/e100.c 2006-11-03 17:33:58.000000000 -0800
7749+++ linux-2.6.18.2/drivers/net/e100.c 2006-11-15 21:20:19.742033186 -0800
7750@@ -162,6 +162,7 @@
7751 #define DRV_VERSION "3.5.10-k2"DRV_EXT
7752 #define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver"
7753 #define DRV_COPYRIGHT "Copyright(c) 1999-2005 Intel Corporation"
7754+#define DRV_MODIFIED "Modified by <jeff@404ster.com> to ignore bad EEPROM checksums"
7755 #define PFX DRV_NAME ": "
7756
7757 #define E100_WATCHDOG_PERIOD (2 * HZ)
7758@@ -758,9 +759,15 @@
7759 * the sum of words should be 0xBABA */
7760 checksum = le16_to_cpu(0xBABA - checksum);
7761 if(checksum != nic->eeprom[nic->eeprom_wc - 1]) {
7762+#if defined(CONFIG_E100_IGNORE_CSUM)
7763+DPRINTK(PROBE, ERR, "EEPROM corrupted, ignoring and moving on\n");
7764+DPRINTK(PROBE, ERR, " Caclulated Checksum: %X\n",checksum);
7765+DPRINTK(PROBE, ERR, " EEPROM Checksum: %X\n",nic->eeprom[nic->eeprom_wc - 1]);
7766+#else
7767 DPRINTK(PROBE, ERR, "EEPROM corrupted\n");
7768 if (!eeprom_bad_csum_allow)
7769 return -EAGAIN;
7770+#endif
7771 }
7772
7773 return 0;
7774@@ -2876,6 +2883,9 @@
7775 if(((1 << debug) - 1) & NETIF_MSG_DRV) {
7776 printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
7777 printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT);
7778+#if defined(CONFIG_E100_IGNORE_CSUM)
7779+ printk(KERN_INFO PFX "%s\n", DRV_MODIFIED);
7780+#endif
7781 }
7782 return pci_module_init(&e100_driver);
7783 }
7784diff -Naur linux-2.6.18.2.orig/include/cobalt/acpi.h linux-2.6.18.2/include/cobalt/acpi.h
7785--- linux-2.6.18.2.orig/include/cobalt/acpi.h 1969-12-31 16:00:00.000000000 -0800
7786+++ linux-2.6.18.2/include/cobalt/acpi.h 2006-11-15 21:20:19.742033186 -0800
7787@@ -0,0 +1,82 @@
7788+/*
7789+ * $Id: cobalt-acpi.h,v 1.7 2001/10/27 07:03:31 erik Exp $
7790+ * cobalt-acpi.h : support for ACPI interrupts
7791+ *
7792+ * Copyright 2000 Cobalt Networks, Inc.
7793+ * Copyright 2001 Sun Microsystems, Inc.
7794+ */
7795+#ifndef COBALT_ACPI_H
7796+#define COBALT_ACPI_H
7797+
7798+#define SERVERWORKS_ACPI_INDEX_PORT 0x0cd6
7799+#define SERVERWORKS_ACPI_DATA_PORT 0x0cd7
7800+
7801+
7802+typedef struct
7803+{
7804+ u16 hw_type;
7805+ u16 ev_type;
7806+ u32 ev_data;
7807+} cobalt_acpi_evt;
7808+
7809+enum __cobalt_acpi_hw_types
7810+{
7811+ COBALT_ACPI_HW_ANY = 0x0000,
7812+ COBALT_ACPI_HW_OSB4 = 0x0001,
7813+ COBALT_ACPI_HW_CSB5 = 0x0002,
7814+ COBALT_ACPI_HW_PC8731X = 0x0003,
7815+ COBALT_ACPI_HW_PC8741X = 0x0004,
7816+};
7817+
7818+enum __cobalt_acpi_event_types
7819+{
7820+ COBALT_ACPI_EVT_NONE = 0x0000,
7821+ COBALT_ACPI_EVT_TMR = 0x0001, /* Timer Event */
7822+ COBALT_ACPI_EVT_BM = 0x00002, /* Bus Master Event */
7823+ COBALT_ACPI_EVT_GBL = 0x0003, /* BIOS Global Lock release */
7824+ COBALT_ACPI_EVT_PWRBTN = 0x0004, /* Power Button press */
7825+ COBALT_ACPI_EVT_SLPBTN = 0x0005, /* Sleep Button press */
7826+ COBALT_ACPI_EVT_RTC = 0x0006, /* RTC Alarm */
7827+ COBALT_ACPI_EVT_WAK = 0x0007, /* Wake event */
7828+ COBALT_ACPI_EVT_GPE = 0x0008, /* General Purpose Event (ev_data = gpe number) */
7829+
7830+ /* events greater than 0x7fff are symbolic events */
7831+ COBALT_ACPI_EVT_SLED = 0x8000, /* Sled removal */
7832+ COBALT_ACPI_EVT_THERM = 0x8001, /* Thermal trip */
7833+ COBALT_ACPI_EVT_FAN = 0x8002, /* Fan Down */
7834+ COBALT_ACPI_EVT_SM_INT = 0x8003, /* System Monitor Interrupt */
7835+ COBALT_ACPI_EVT_VOLT = 0x8004, /* System Monitor Interrupt */
7836+
7837+};
7838+
7839+typedef int (* cobalt_acpi_hw_handler)( int irq, void *dev_id, struct pt_regs *regs, void * data );
7840+typedef int (* cobalt_acpi_enable_handler)( u16 ev_type, u16 ev_data, int en, void *data );
7841+typedef int (* cobalt_acpi_evt_handler)( cobalt_acpi_evt *evt, void * data );
7842+
7843+
7844+extern int cobalt_acpi_register_hw_handler( u16 hw_type,
7845+ cobalt_acpi_hw_handler hw_handler,
7846+ cobalt_acpi_enable_handler en_handler,
7847+ void *data );
7848+extern int cobalt_acpi_unregister_hw_handler( cobalt_acpi_hw_handler handler );
7849+
7850+extern int cobalt_acpi_register_trans_table( u16 hw_type, u16 table_len, u16 *table );
7851+extern int cobalt_acpi_unregister_trans_table( u16 hw_type );
7852+
7853+extern int cobalt_acpi_register_evt_handler( cobalt_acpi_evt_handler handler,
7854+ u16 evt_type,
7855+ void *data );
7856+extern int cobalt_acpi_unregister_evt_handler( cobalt_acpi_evt_handler handler );
7857+
7858+extern int cobalt_acpi_post_event( cobalt_acpi_evt evt );
7859+
7860+#ifdef CONFIG_COBALT_EMU_ACPI
7861+int cobalt_acpi_generate_proc_evt( cobalt_acpi_evt * evt );
7862+#else
7863+#define cobalt_acpi_generate_proc_evt( a )
7864+#endif
7865+
7866+
7867+
7868+
7869+#endif /* COBALT_ACPI_H */
7870diff -Naur linux-2.6.18.2.orig/include/cobalt/cobalt.h linux-2.6.18.2/include/cobalt/cobalt.h
7871--- linux-2.6.18.2.orig/include/cobalt/cobalt.h 1969-12-31 16:00:00.000000000 -0800
7872+++ linux-2.6.18.2/include/cobalt/cobalt.h 2006-11-15 21:20:19.742033186 -0800
7873@@ -0,0 +1,58 @@
7874+/* $Id: cobalt.h,v 1.16 2002/11/04 17:54:15 thockin Exp $ */
7875+/* Copyright 2001 Sun Microsystems, Inc. */
7876+#include <linux/config.h>
7877+#if !defined(COBALT_H) && defined(CONFIG_COBALT_RAQ)
7878+#define COBALT_H
7879+
7880+/* generational support - for easy checking */
7881+#ifdef CONFIG_COBALT_GEN_III
7882+# define COBT_SUPPORT_GEN_III 1
7883+#else
7884+# define COBT_SUPPORT_GEN_III 0
7885+#endif
7886+
7887+#ifdef CONFIG_COBALT_GEN_V
7888+# define COBT_SUPPORT_GEN_V 1
7889+#else
7890+# define COBT_SUPPORT_GEN_V 0
7891+#endif
7892+
7893+/* macros for consistent errors/warnings */
7894+#define EPRINTK(fmt, args...) \
7895+ printk(KERN_ERR "%s:%s: " fmt , __FILE__ , __FUNCTION__ , ##args)
7896+
7897+#define WPRINTK(fmt, args...) \
7898+ printk(KERN_WARNING "%s:%s: " fmt , __FILE__ , __FUNCTION__ , ##args)
7899+
7900+/* the root of /proc/cobalt */
7901+extern struct proc_dir_entry *proc_cobalt;
7902+int cobalt_gen_proc_read(char *buf, int plen, char **start, off_t pos,
7903+ int len, int *eof);
7904+
7905+//#ifdef CONFIG_COBALT_RAQ
7906+/* keep this test up to date with new generation defines */
7907+#if !defined(CONFIG_COBALT_GEN_III) && !defined(CONFIG_COBALT_GEN_V)
7908+/* barf if no generation has been selected */
7909+#error You asked for CONFIG_COBALT_RAQ, but no CONFIG_COBALT_GEN_* !
7910+#endif
7911+
7912+/* accesses for CMOS */
7913+#include <linux/mc146818rtc.h>
7914+#include <cobalt/nvram.h>
7915+
7916+static inline int
7917+cobalt_cmos_read_flag(const unsigned int flag)
7918+{
7919+ unsigned long flags;
7920+ u16 cmosfl;
7921+
7922+ spin_lock_irqsave(&rtc_lock, flags);
7923+ cmosfl = CMOS_READ(COBT_CMOS_FLAG_BYTE_0) << 8;
7924+ cmosfl |= CMOS_READ(COBT_CMOS_FLAG_BYTE_1);
7925+ spin_unlock_irqrestore(&rtc_lock, flags);
7926+
7927+ return (cmosfl & flag) ? 1 : 0;
7928+}
7929+//#endif /* CONFIG_COBALT_RAQ */
7930+
7931+#endif /* !defined(COBALT_H) && defined(CONFIG_COBALT_RAQ) */
7932diff -Naur linux-2.6.18.2.orig/include/cobalt/i2c.h linux-2.6.18.2/include/cobalt/i2c.h
7933--- linux-2.6.18.2.orig/include/cobalt/i2c.h 1969-12-31 16:00:00.000000000 -0800
7934+++ linux-2.6.18.2/include/cobalt/i2c.h 2006-11-15 21:20:19.742033186 -0800
7935@@ -0,0 +1,40 @@
7936+/*
7937+ * $Id: cobalt-i2c.h,v 1.3 2001/08/22 05:48:04 asun Exp $
7938+ * cobalt-i2c.h : I2C support for LCD/Front Panel
7939+ *
7940+ * Copyright 2000 Cobalt Networks, Inc.
7941+ * Copyright 2001 Sun Microsystems, Inc.
7942+ */
7943+#ifndef COBALT_I2C_H
7944+#define COBALT_I2C_H
7945+
7946+#include <linux/types.h>
7947+#include <cobalt/cobalt.h>
7948+
7949+#define COBALT_I2C_DEV_LED_I 0x40
7950+#define COBALT_I2C_DEV_LED_II 0x42
7951+#define COBALT_I2C_DEV_LCD_DATA 0x4a
7952+#define COBALT_I2C_DEV_LCD_INST 0x48
7953+#define COBALT_I2C_DEV_FP_BUTTONS 0x41
7954+#define COBALT_I2C_DEV_DRV_SWITCH 0x45
7955+#define COBALT_I2C_DEV_RULER 0x46
7956+#define COBALT_I2C_DEV_LM77 0x90
7957+#define COBALT_I2C_DEV_ADM1029 0x5e
7958+#define COBALT_I2C_DEV_AT24C02 0xae
7959+
7960+#define COBALT_I2C_READ 0x01
7961+#define COBALT_I2C_WRITE 0x00
7962+
7963+extern int cobalt_i2c_reset(void);
7964+extern int cobalt_i2c_read_byte(const int dev, const int index);
7965+extern int cobalt_i2c_read_word(const int dev, const int index);
7966+extern int cobalt_i2c_read_block(const int dev, const int index,
7967+ unsigned char *data, int count);
7968+extern int cobalt_i2c_write_byte(const int dev, const int index,
7969+ const u8 val);
7970+extern int cobalt_i2c_write_word(const int dev, const int index,
7971+ const u16 val);
7972+extern int cobalt_i2c_write_block(const int dev, const int index,
7973+ unsigned char *data, int count);
7974+
7975+#endif /* COBALT_I2C_H */
7976diff -Naur linux-2.6.18.2.orig/include/cobalt/lcd.h linux-2.6.18.2/include/cobalt/lcd.h
7977--- linux-2.6.18.2.orig/include/cobalt/lcd.h 1969-12-31 16:00:00.000000000 -0800
7978+++ linux-2.6.18.2/include/cobalt/lcd.h 2006-11-15 21:20:19.742033186 -0800
7979@@ -0,0 +1,95 @@
7980+/*
7981+ * $Id: cobalt-lcd.h,v 1.12 2001/11/30 05:38:46 asun Exp $
7982+ * cobalt-lcd.h : some useful defines for the Cobalt LCD driver
7983+ * (must be useable from both kernel and user space)
7984+ *
7985+ * Copyright 1996-2000 Cobalt Networks, Inc.
7986+ * Copyright 2001 Sun Microsystems, Inc.
7987+ *
7988+ * By: Andrew Bose
7989+ * Timothy Stonis (x86 version)
7990+ * Tim Hockin
7991+ * Adrian Sun
7992+ * Erik Gilling
7993+ * Duncan Laurie
7994+ */
7995+#ifndef COBALT_LCD_H
7996+#define COBALT_LCD_H
7997+
7998+#ifdef __KERNEL__
7999+#include <cobalt/cobalt.h>
8000+#endif
8001+#include <cobalt/led.h>
8002+
8003+#define COBALT_LCD_LINELEN 40
8004+struct lcd_display {
8005+ unsigned long buttons;
8006+ int size1;
8007+ int size2;
8008+ unsigned char line1[COBALT_LCD_LINELEN];
8009+ unsigned char line2[COBALT_LCD_LINELEN];
8010+ unsigned char cursor_address;
8011+ unsigned char character;
8012+ unsigned char leds;
8013+ unsigned char *RomImage;
8014+};
8015+
8016+/* different lcd types */
8017+#define LCD_TYPE_UNKNOWN 0
8018+#define LCD_TYPE_PARALLEL 1
8019+#define LCD_TYPE_PARALLEL_B 2
8020+#define LCD_TYPE_I2C 3
8021+
8022+/* Function command codes for ioctl */
8023+#define LCD_On 1
8024+#define LCD_Off 2
8025+#define LCD_Clear 3
8026+#define LCD_Reset 4
8027+#define LCD_Cursor_Left 5
8028+#define LCD_Cursor_Right 6
8029+#define LCD_Disp_Left 7
8030+#define LCD_Disp_Right 8
8031+#define LCD_Get_Cursor 9
8032+#define LCD_Set_Cursor 10
8033+#define LCD_Home 11
8034+#define LCD_Read 12
8035+#define LCD_Write 13
8036+#define LCD_Cursor_Off 14
8037+#define LCD_Cursor_On 15
8038+#define LCD_Get_Cursor_Pos 16
8039+#define LCD_Set_Cursor_Pos 17
8040+#define LCD_Blink_Off 18
8041+#define LCD_Raw_Inst 19
8042+#define LCD_Raw_Data 20
8043+#define LCD_Type 21
8044+
8045+/* LED controls */
8046+#define LED_Set 40
8047+#define LED_Bit_Set 41
8048+#define LED_Bit_Clear 42
8049+#define LED32_Set 43
8050+#define LED32_Bit_Set 44
8051+#define LED32_Bit_Clear 45
8052+#define LED32_Get 46
8053+
8054+/* button ioctls */
8055+#define BUTTON_Read 50
8056+
8057+/* Button defs */
8058+#define BUTTON_Next 0x3D
8059+#define BUTTON_Next_B 0x7E
8060+#define BUTTON_Reset_B 0xFC
8061+#define BUTTON_NONE_B 0xFE
8062+#define BUTTON_Left_B 0xFA
8063+#define BUTTON_Right_B 0xDE
8064+#define BUTTON_Up_B 0xF6
8065+#define BUTTON_Down_B 0xEE
8066+#define BUTTON_Enter_B 0xBE
8067+
8068+#define BUTTON_MASK 0xFE
8069+
8070+void cobalt_lcd_start_twiddle(void);
8071+void cobalt_lcd_stop_twiddle(void);
8072+void cobalt_lcd_off(void);
8073+
8074+#endif /* COBALT_LCD_H */
8075diff -Naur linux-2.6.18.2.orig/include/cobalt/led.h linux-2.6.18.2/include/cobalt/led.h
8076--- linux-2.6.18.2.orig/include/cobalt/led.h 1969-12-31 16:00:00.000000000 -0800
8077+++ linux-2.6.18.2/include/cobalt/led.h 2006-11-15 21:20:19.742033186 -0800
8078@@ -0,0 +1,59 @@
8079+/*
8080+ * $Id: cobalt-led.h,v 1.7 2001/11/08 01:15:33 thockin Exp $
8081+ * cobalt-led.c
8082+ *
8083+ * Copyright 1996-2000 Cobalt Networks, Inc.
8084+ * Copyright 2001 Sun Microsystems, Inc.
8085+ *
8086+ * By: Andrew Bose
8087+ * Timothy Stonis (x86 version)
8088+ * Tim Hockin
8089+ * Adrian Sun
8090+ * Erik Gilling
8091+ * Duncan Laurie
8092+ */
8093+#ifndef COBALT_LED_H
8094+#define COBALT_LED_H
8095+
8096+/* the set of all leds available on Cobalt systems */
8097+#define LED_SHUTDOWN (1 << 0)
8098+#define LED_WEBLIGHT (1 << 1)
8099+#define LED_COBALTLOGO (1 << 2)
8100+#define LED_ETH0_TXRX (1 << 3)
8101+#define LED_ETH0_LINK (1 << 4)
8102+#define LED_ETH1_TXRX (1 << 5)
8103+#define LED_ETH1_LINK (1 << 6)
8104+#define LED_DISK0 (1 << 7)
8105+#define LED_DISK1 (1 << 8)
8106+#define LED_DISK2 (1 << 9)
8107+#define LED_DISK3 (1 << 10)
8108+#define LED_SYSFAULT (1 << 11)
8109+#define LED_MONTEREY_UNUSED0 (1 << 12)
8110+#define LED_MONTEREY_UNUSED1 (1 << 13)
8111+/* LED_MONTEREY_UNUSED2 is below */
8112+#define LED_HEART LED_MONTEREY_UNUSED0
8113+#define LED_SPARE LED_MONTEREY_UNUSED1
8114+#define LED_SLED0 (1 << 14)
8115+#define LED_SLED1 (1 << 15)
8116+#define LED_SLED2 (1 << 16)
8117+#define LED_SLED3 (1 << 17)
8118+#define LED_MONTEREY_UNUSED2 (1 << 18)
8119+#define LED_SPARE2 LED_MONTEREY_UNUSED2
8120+
8121+#ifdef __KERNEL__
8122+
8123+extern void cobalt_led_set(const unsigned int leds);
8124+extern void cobalt_led_set_bits(const unsigned int leds);
8125+extern void cobalt_led_clear_bits(const unsigned int leds);
8126+extern void cobalt_led_set_lazy(const unsigned int leds);
8127+extern void cobalt_led_set_bits_lazy(const unsigned int leds);
8128+extern void cobalt_led_clear_bits_lazy(const unsigned int leds);
8129+extern unsigned int cobalt_led_get(void);
8130+
8131+extern int cobalt_fpled_register(unsigned int (*fn)(void *), void *data);
8132+extern int cobalt_fpled_unregister(unsigned int (*fn)(void *), void *data);
8133+
8134+#endif /* __KERNEL__ */
8135+
8136+#endif /* COBALT_LED_H */
8137+
8138diff -Naur linux-2.6.18.2.orig/include/cobalt/misc.h linux-2.6.18.2/include/cobalt/misc.h
8139--- linux-2.6.18.2.orig/include/cobalt/misc.h 1969-12-31 16:00:00.000000000 -0800
8140+++ linux-2.6.18.2/include/cobalt/misc.h 2006-11-15 21:27:17.024148165 -0800
8141@@ -0,0 +1,12 @@
8142+/* $Id: cobalt-misc.h,v 1.1 2001/04/04 03:36:43 thockin Exp $ */
8143+/* Copyright 2001 Sun Microsystems, Inc. */
8144+#ifndef COBALT_MISC_H
8145+#define COBALT_MISC_H
8146+
8147+void cobalt_flush(void);
8148+void cobalt_nmi(unsigned char reason, struct pt_regs *regs);
8149+void cobalt_restart(void);
8150+void cobalt_halt(void);
8151+void cobalt_power_off(void);
8152+
8153+#endif
8154diff -Naur linux-2.6.18.2.orig/include/cobalt/net.h linux-2.6.18.2/include/cobalt/net.h
8155--- linux-2.6.18.2.orig/include/cobalt/net.h 1969-12-31 16:00:00.000000000 -0800
8156+++ linux-2.6.18.2/include/cobalt/net.h 2006-11-15 21:20:19.746033053 -0800
8157@@ -0,0 +1,12 @@
8158+/* $Id: cobalt-net.h,v 1.3 2002/10/25 01:02:42 thockin Exp $ */
8159+/* Copyright 2001 Sun Microsystems, Inc. */
8160+#ifndef COBALT_NET_H
8161+#define COBALT_NET_H
8162+
8163+#include <linux/netdevice.h>
8164+#include <linux/config.h>
8165+
8166+void cobalt_net_register(struct net_device *ndev);
8167+void cobalt_net_unregister(struct net_device *ndev);
8168+
8169+#endif
8170diff -Naur linux-2.6.18.2.orig/include/cobalt/nvram.h linux-2.6.18.2/include/cobalt/nvram.h
8171--- linux-2.6.18.2.orig/include/cobalt/nvram.h 1969-12-31 16:00:00.000000000 -0800
8172+++ linux-2.6.18.2/include/cobalt/nvram.h 2006-11-15 21:20:19.746033053 -0800
8173@@ -0,0 +1,125 @@
8174+/*
8175+ * $Id: cobalt-nvram.h,v 1.21 2002/11/02 00:57:06 thockin Exp $
8176+ * cobalt-nvram.h : defines for the various fields in the cobalt NVRAM
8177+ *
8178+ * Copyright 2001 Sun Microsystems, Inc.
8179+ */
8180+
8181+#ifndef COBALT_NVRAM_H
8182+#define COBALT_NVRAM_H
8183+
8184+#include <linux/nvram.h>
8185+
8186+#define COBT_CMOS_INFO_MAX 0x7f /* top address allowed */
8187+#define COBT_CMOS_BIOS_DRIVE_INFO 0x12 /* drive info would go here */
8188+
8189+#define COBT_CMOS_CKS_START NVRAM_OFFSET(0x0e)
8190+#define COBT_CMOS_CKS_END NVRAM_OFFSET(0x7f)
8191+
8192+/* flag bytes - 16 flags for now, leave room for more */
8193+#define COBT_CMOS_FLAG_BYTE_0 NVRAM_OFFSET(0x10)
8194+#define COBT_CMOS_FLAG_BYTE_1 NVRAM_OFFSET(0x11)
8195+
8196+/* flags in flag bytes - up to 16 */
8197+#define COBT_CMOS_FLAG_MIN 0x0001
8198+#define COBT_CMOS_CONSOLE_FLAG 0x0001 /* console on/off */
8199+#define COBT_CMOS_DEBUG_FLAG 0x0002 /* ROM debug messages */
8200+#define COBT_CMOS_AUTO_PROMPT_FLAG 0x0004 /* boot to ROM prompt? */
8201+#define COBT_CMOS_CLEAN_BOOT_FLAG 0x0008 /* set by a clean shutdown */
8202+#define COBT_CMOS_HW_NOPROBE_FLAG 0x0010 /* go easy on the probing */
8203+#define COBT_CMOS_SYSFAULT_FLAG 0x0020 /* system fault detected */
8204+#define COBT_CMOS_OOPSPANIC_FLAG 0x0040 /* panic on oops */
8205+#define COBT_CMOS_DELAY_CACHE_FLAG 0x0080 /* delay cache initialization */
8206+#define COBT_CMOS_NOLOGO_FLAG 0x0100 /* hide "C" logo @ boot */
8207+#define COBT_CMOS_VERSION_FLAG 0x0200 /* the version field is valid */
8208+#define COBT_CMOS_FLAG_MAX 0x0200
8209+
8210+/* leave byte 0x12 blank - Linux looks for drive info here */
8211+
8212+/* CMOS structure version, valid if COBT_CMOS_VERSION_FLAG is true */
8213+#define COBT_CMOS_VERSION NVRAM_OFFSET(0x13)
8214+#define COBT_CMOS_VER_BTOCODE 1 /* min. version needed for btocode */
8215+
8216+/* index of default boot method */
8217+#define COBT_CMOS_BOOT_METHOD NVRAM_OFFSET(0x20)
8218+#define COBT_CMOS_BOOT_METHOD_DISK 0
8219+#define COBT_CMOS_BOOT_METHOD_ROM 1
8220+#define COBT_CMOS_BOOT_METHOD_NET 2
8221+#define COBT_CMOS_BOOT_METHOD_NNET 3
8222+#define COBT_CMOS_BOOT_METHOD_OTHER 4
8223+
8224+#define COBT_CMOS_BOOT_DEV_MIN NVRAM_OFFSET(0x21)
8225+/* major #, minor # of first through fourth boot device */
8226+#define COBT_CMOS_BOOT_DEV0_MAJ NVRAM_OFFSET(0x21)
8227+#define COBT_CMOS_BOOT_DEV0_MIN NVRAM_OFFSET(0x22)
8228+#define COBT_CMOS_BOOT_DEV1_MAJ NVRAM_OFFSET(0x23)
8229+#define COBT_CMOS_BOOT_DEV1_MIN NVRAM_OFFSET(0x24)
8230+#define COBT_CMOS_BOOT_DEV2_MAJ NVRAM_OFFSET(0x25)
8231+#define COBT_CMOS_BOOT_DEV2_MIN NVRAM_OFFSET(0x26)
8232+#define COBT_CMOS_BOOT_DEV3_MAJ NVRAM_OFFSET(0x27)
8233+#define COBT_CMOS_BOOT_DEV3_MIN NVRAM_OFFSET(0x28)
8234+#define COBT_CMOS_BOOT_DEV_MAX NVRAM_OFFSET(0x28)
8235+
8236+/* checksum of bytes 0xe-0x7f */
8237+#define COBT_CMOS_CHECKSUM NVRAM_OFFSET(0x2e)
8238+
8239+/* running uptime counter, units of 5 minutes (32 bits =~ 41000 years) */
8240+#define COBT_CMOS_UPTIME_0 NVRAM_OFFSET(0x30)
8241+#define COBT_CMOS_UPTIME_1 NVRAM_OFFSET(0x31)
8242+#define COBT_CMOS_UPTIME_2 NVRAM_OFFSET(0x32)
8243+#define COBT_CMOS_UPTIME_3 NVRAM_OFFSET(0x33)
8244+
8245+/* count of successful boots (32 bits) */
8246+#define COBT_CMOS_BOOTCOUNT_0 NVRAM_OFFSET(0x38)
8247+#define COBT_CMOS_BOOTCOUNT_1 NVRAM_OFFSET(0x39)
8248+#define COBT_CMOS_BOOTCOUNT_2 NVRAM_OFFSET(0x3a)
8249+#define COBT_CMOS_BOOTCOUNT_3 NVRAM_OFFSET(0x3b)
8250+
8251+/* 13 bytes: system serial number, same as on the back of the system */
8252+#define COBT_CMOS_SYS_SERNUM_LEN 13
8253+#define COBT_CMOS_SYS_SERNUM_0 NVRAM_OFFSET(0x40)
8254+#define COBT_CMOS_SYS_SERNUM_1 NVRAM_OFFSET(0x41)
8255+#define COBT_CMOS_SYS_SERNUM_2 NVRAM_OFFSET(0x42)
8256+#define COBT_CMOS_SYS_SERNUM_3 NVRAM_OFFSET(0x43)
8257+#define COBT_CMOS_SYS_SERNUM_4 NVRAM_OFFSET(0x44)
8258+#define COBT_CMOS_SYS_SERNUM_5 NVRAM_OFFSET(0x45)
8259+#define COBT_CMOS_SYS_SERNUM_6 NVRAM_OFFSET(0x46)
8260+#define COBT_CMOS_SYS_SERNUM_7 NVRAM_OFFSET(0x47)
8261+#define COBT_CMOS_SYS_SERNUM_8 NVRAM_OFFSET(0x48)
8262+#define COBT_CMOS_SYS_SERNUM_9 NVRAM_OFFSET(0x49)
8263+#define COBT_CMOS_SYS_SERNUM_10 NVRAM_OFFSET(0x4a)
8264+#define COBT_CMOS_SYS_SERNUM_11 NVRAM_OFFSET(0x4b)
8265+#define COBT_CMOS_SYS_SERNUM_12 NVRAM_OFFSET(0x4c)
8266+/* checksum for serial num - 1 byte */
8267+#define COBT_CMOS_SYS_SERNUM_CSUM NVRAM_OFFSET(0x4f)
8268+
8269+#define COBT_CMOS_ROM_REV_MAJ NVRAM_OFFSET(0x50)
8270+#define COBT_CMOS_ROM_REV_MIN NVRAM_OFFSET(0x51)
8271+#define COBT_CMOS_ROM_REV_REV NVRAM_OFFSET(0x52)
8272+
8273+#define COBT_CMOS_BTO_CODE_0 NVRAM_OFFSET(0x53)
8274+#define COBT_CMOS_BTO_CODE_1 NVRAM_OFFSET(0x54)
8275+#define COBT_CMOS_BTO_CODE_2 NVRAM_OFFSET(0x55)
8276+#define COBT_CMOS_BTO_CODE_3 NVRAM_OFFSET(0x56)
8277+
8278+#define COBT_CMOS_BTO_IP_CSUM NVRAM_OFFSET(0x57)
8279+#define COBT_CMOS_BTO_IP_0 NVRAM_OFFSET(0x58)
8280+#define COBT_CMOS_BTO_IP_1 NVRAM_OFFSET(0x59)
8281+#define COBT_CMOS_BTO_IP_2 NVRAM_OFFSET(0x5a)
8282+#define COBT_CMOS_BTO_IP_3 NVRAM_OFFSET(0x5b)
8283+
8284+/* byte for load/run methods */
8285+#define COBT_CMOS_BOOT_TYPE NVRAM_OFFSET(0x5c)
8286+#define COBT_CMOS_BOOT_KERN_DEV 0x01 /* use kernel on major/minor */
8287+#define COBT_CMOS_BOOT_KERN_ROM 0x02 /* use rom kernel */
8288+#define COBT_CMOS_BOOT_KERN_NET 0x03 /* use net kernel */
8289+#define COBT_CMOS_BOOT_KERN_MASK 0x0f /* mask for above */
8290+
8291+#define COBT_CMOS_BOOT_FS_DEV 0x10 /* use major/minor number dev */
8292+#define COBT_CMOS_BOOT_FS_NET 0x30 /* use net fs */
8293+#define COBT_CMOS_BOOT_FS_MASK 0xf0 /* mask for above */
8294+
8295+/* HA mode we're in (Twin Peaks) */
8296+#define COBT_CMOS_HA_MODE NVRAM_OFFSET(0x62)
8297+
8298+#endif /* COBALT_NVRAM_H */
8299diff -Naur linux-2.6.18.2.orig/include/cobalt/ruler.h linux-2.6.18.2/include/cobalt/ruler.h
8300--- linux-2.6.18.2.orig/include/cobalt/ruler.h 1969-12-31 16:00:00.000000000 -0800
8301+++ linux-2.6.18.2/include/cobalt/ruler.h 2006-11-15 21:20:19.746033053 -0800
8302@@ -0,0 +1,15 @@
8303+/* $Id: cobalt-ruler.h,v 1.4 2001/06/08 20:46:44 thockin Exp $ */
8304+/* Copyright 2001 Sun Microsystems, Inc. */
8305+#ifndef COBALT_RULER_H
8306+#define COBALT_RULER_H
8307+
8308+#include <linux/ide.h>
8309+
8310+void cobalt_ruler_register(ide_drive_t *hwif);
8311+void cobalt_ruler_unregister(ide_drive_t *hwif);
8312+
8313+//typedef int (*cob_busproc_t) (struct hwif_s *, int);
8314+
8315+//int *cob_busproc_t (ide_drive_t *, int);
8316+
8317+#endif
8318diff -Naur linux-2.6.18.2.orig/include/cobalt/sensors.h linux-2.6.18.2/include/cobalt/sensors.h
8319--- linux-2.6.18.2.orig/include/cobalt/sensors.h 1969-12-31 16:00:00.000000000 -0800
8320+++ linux-2.6.18.2/include/cobalt/sensors.h 2006-11-15 21:20:19.746033053 -0800
8321@@ -0,0 +1,29 @@
8322+/* $Id: cobalt-sensors.h,v 1.2 2001/09/25 18:10:29 thockin Exp $ */
8323+/* Copyright 2001 Sun Microsystems, Inc. */
8324+#ifndef COBALT_SENSORS_H
8325+#define COBALT_SENSORS_H
8326+
8327+#include <cobalt/cobalt.h>
8328+
8329+extern unsigned int cobalt_nthermals;
8330+extern unsigned int cobalt_nvoltages;
8331+
8332+/* return NULL if the sensor doesn't exist, fill buf if it does */
8333+char *__cobalt_thermal_read(unsigned int sensor, char *buf, int len);
8334+char *__cobalt_voltage_read(unsigned int sensor, char *buf, int len);
8335+
8336+static inline char *
8337+cobalt_thermal_read(unsigned int sensor)
8338+{
8339+ char buf[32];
8340+ return __cobalt_thermal_read(sensor, buf, sizeof(buf)-1);
8341+}
8342+
8343+static inline char *
8344+cobalt_voltage_read(unsigned int sensor)
8345+{
8346+ char buf[32];
8347+ return __cobalt_voltage_read(sensor, buf, sizeof(buf)-1);
8348+}
8349+
8350+#endif
8351diff -Naur linux-2.6.18.2.orig/include/cobalt/serialnum.h linux-2.6.18.2/include/cobalt/serialnum.h
8352--- linux-2.6.18.2.orig/include/cobalt/serialnum.h 1969-12-31 16:00:00.000000000 -0800
8353+++ linux-2.6.18.2/include/cobalt/serialnum.h 2006-11-15 21:20:19.746033053 -0800
8354@@ -0,0 +1,16 @@
8355+/*
8356+ * $Id: cobalt-serialnum.h,v 1.1 2001/03/07 01:58:24 thockin Exp $
8357+ * cobalt-serialnum.h : access to the DS2401 serial number
8358+ *
8359+ * Copyright 2000 Cobalt Networks, Inc.
8360+ * Copyright 2001 Sun Microsystems, Inc.
8361+ */
8362+#ifndef COBALT_SERIALNUM_H
8363+#define COBALT_SERIALNUM_H
8364+
8365+#include <cobalt/cobalt.h>
8366+
8367+char *cobalt_serialnum_get(void);
8368+unsigned long cobalt_hostid_get(void);
8369+
8370+#endif /* COBALT_SERIALNUM_H */
8371diff -Naur linux-2.6.18.2.orig/include/cobalt/superio.h linux-2.6.18.2/include/cobalt/superio.h
8372--- linux-2.6.18.2.orig/include/cobalt/superio.h 1969-12-31 16:00:00.000000000 -0800
8373+++ linux-2.6.18.2/include/cobalt/superio.h 2006-11-15 21:20:19.766032388 -0800
8374@@ -0,0 +1,225 @@
8375+/*
8376+ * $Id: cobalt-superio.h,v 1.11 2001/11/02 12:00:03 duncan Exp $
8377+ * cobalt-superio.h : SuperIO support for Sun/Cobalt servers
8378+ *
8379+ * Copyright 2000 Cobalt Networks, Inc.
8380+ * Copyright 2001 Sun Microsystems, Inc.
8381+ */
8382+#ifndef COBALT_SUPERIO_H
8383+#define COBALT_SUPERIO_H
8384+
8385+#include <cobalt/cobalt.h>
8386+#include <cobalt/systype.h>
8387+
8388+/* the lock that protects superio accesses */
8389+extern spinlock_t cobalt_superio_lock;
8390+
8391+/*
8392+ * The main functions of the SuperIO are accessed via index/data registers
8393+ * These are the same for both SuperIO chip families
8394+ */
8395+#define SUPERIO_INDEX_PORT 0x2e
8396+#define SUPERIO_DATA_PORT 0x2f
8397+
8398+/*
8399+ * This index allows you to select a logical device
8400+ */
8401+#define SUPERIO_LOGICAL_DEV 0x07
8402+
8403+/*
8404+ * Type of SUPERIO
8405+ */
8406+#define SUPERIO_SID 0x20
8407+
8408+/*
8409+ * Some indices that are common to all logical devices
8410+ */
8411+#define SUPERIO_ACTIVATE 0x30
8412+#define SUPERIO_ADDR_HIGH 0x60
8413+#define SUPERIO_ADDR_LOW 0x61
8414+#define SUPERIO_INTR_PIN 0x70
8415+#define SUPERIO_INTR_TYPE 0x71
8416+
8417+
8418+/*
8419+ * PC87317 SuperIO is found on XTR
8420+ */
8421+
8422+/*
8423+ * logical devices - write to LOGICAL_DEV index
8424+ */
8425+#define PC87317_DEV_RTC 0x02
8426+#define PC87317_DEV_GPIO 0x07
8427+#define PC87317_DEV_PM 0x08
8428+
8429+/* withing the PM dev, are the following indices */
8430+#define PC87317_PMDEV_WDTO 0x05
8431+#define PC87317_PMDEV_GPELO 0x0e
8432+#define PC87317_PMDEV_GPEHI 0x0f
8433+
8434+/* within the APC bank of RTC */
8435+#define PC87317_APCR1 0x40
8436+#define PC87317_APCR2 0x41
8437+#define PC87317_APCR3 0x49
8438+#define PC87317_APCR4 0x4a
8439+#define PC87317_APCR5 0x4b
8440+#define PC87317_APCR6 0x4c
8441+#define PC87317_APCR7 0x4d
8442+
8443+#define PC87317_RTC_BANK_MAIN 0
8444+#define PC87317_RTC_BANK_RTC 1
8445+#define PC87317_RTC_BANK_APC 2
8446+#define PC87317_RTC_CRA 0x0a
8447+#define PC87317_RTC_BANK_0 0x20
8448+#define PC87317_RTC_BANK_1 0x30
8449+#define PC87317_RTC_BANK_2 0x40
8450+
8451+#define PC87317_PWRBUTTON 0x01
8452+#define PC87317_PM1_STATUS 0x01
8453+
8454+/* offsets from GPEHI/GPELO */
8455+#define PC87317_GPE_GP1_STS0 0x00
8456+#define PC87317_GPE_GP1_STS1 0x01
8457+#define PC87317_GPE_GP1_STS2 0x02
8458+#define PC87317_GPE_GP1_STS3 0x03
8459+#define PC87317_GPE_GP1_EN0 0x04
8460+#define PC87317_GPE_GP1_EN1 0x05
8461+#define PC87317_GPE_GP1_EN2 0x06
8462+#define PC87317_GPE_GP1_EN3 0x07
8463+#define PC87317_GPE_GP2_EN0 0x08
8464+#define PC87317_GPE_SMI_CMD 0x0c
8465+
8466+/*
8467+ * PC87417 family is found on alpine
8468+ */
8469+
8470+#define PC87417_DEV_SWC 0x4
8471+#define PC87417_DEV_GPIO 0x7
8472+#define PC87417_DEV_RTC 0x10
8473+
8474+/* registers in the SWC dev */
8475+#define PC87417_SWC_PWONCTL 0x9
8476+/*
8477+ * within the System Wake Control device, there are banks, write the bank you
8478+ * want to SWC_BANK
8479+ */
8480+#define PC87417_SWC_BANK 0xf
8481+#define PC87417_SWCBANK_ACPI 0x2
8482+#define PC87417_SWCBANK_WDT 0x3
8483+
8484+/*
8485+ * the SWC WDT bank has 3 main registers
8486+ */
8487+#define PC87417_WDT_CONTROL 0x10
8488+#define PC87417_WDT_TIMEOUT 0x11
8489+#define PC87417_WDT_CONFIG 0x12
8490+
8491+/*
8492+ * within the SWC, two regs serve as index/data for wake-event enabling
8493+ */
8494+#define PC87417_SWC_WKEVENT 0x0
8495+#define PC87417_SWC_WKSTATE 0x1
8496+#define PC87417_SWCWKEVENT_GPIOE42 0xa
8497+#define PC87417_SWCWKEVENT_RTC 0x18
8498+
8499+
8500+/*
8501+ * types of superIOs
8502+ */
8503+enum superio_type_t
8504+{
8505+ SIO_TYPE_UNKNOWN,
8506+ SIO_TYPE_PC8731X,
8507+ SIO_TYPE_PC8741X,
8508+};
8509+
8510+
8511+
8512+#define PC8731X_SID 0xd0
8513+#define PC9731X_SID 0xdf
8514+#define PC8741X_SID 0xee
8515+
8516+static inline int superio_type( void )
8517+{
8518+ u8 reg;
8519+ unsigned long flags;
8520+ enum superio_type_t type;
8521+
8522+ spin_lock_irqsave(&cobalt_superio_lock, flags);
8523+
8524+ outb(SUPERIO_SID, SUPERIO_INDEX_PORT);
8525+ reg = inb( SUPERIO_DATA_PORT );
8526+ switch( reg )
8527+ {
8528+ case PC8731X_SID:
8529+ case PC9731X_SID:
8530+ type = SIO_TYPE_PC8731X;
8531+ break;
8532+
8533+ case PC8741X_SID:
8534+ type = SIO_TYPE_PC8741X;
8535+ break;
8536+
8537+ default:
8538+ type = SIO_TYPE_UNKNOWN;
8539+ break;
8540+ }
8541+
8542+ spin_unlock_irqrestore(&cobalt_superio_lock, flags);
8543+
8544+ return type;
8545+}
8546+
8547+/*
8548+ * stuff to make life easier
8549+ */
8550+
8551+/* read the base address of a particular superio logical device */
8552+#define superio_ldev_base(ldev) superio_ldev_base_n(ldev, 0)
8553+static inline unsigned short
8554+superio_ldev_base_n(int ldev, int n)
8555+{
8556+ unsigned long flags;
8557+ unsigned short addr;
8558+
8559+ spin_lock_irqsave(&cobalt_superio_lock, flags);
8560+
8561+ /* select the logical device */
8562+ outb(SUPERIO_LOGICAL_DEV, SUPERIO_INDEX_PORT);
8563+ outb(ldev, SUPERIO_DATA_PORT);
8564+
8565+ /* read the 2-byte base address */
8566+ outb(SUPERIO_ADDR_HIGH+(n*2), SUPERIO_INDEX_PORT);
8567+ addr = inb(SUPERIO_DATA_PORT) << 8;
8568+ outb(SUPERIO_ADDR_LOW+(n*2), SUPERIO_INDEX_PORT);
8569+ addr |= inb(SUPERIO_DATA_PORT);
8570+
8571+ spin_unlock_irqrestore(&cobalt_superio_lock, flags);
8572+
8573+ return addr;
8574+}
8575+
8576+static inline void
8577+superio_set_rtc_bank(const unsigned int page)
8578+{
8579+ if (cobt_is_monterey()) {
8580+ unsigned char val;
8581+
8582+ val = CMOS_READ(0xa);
8583+ val &= ~0x70;
8584+ switch (page) {
8585+ case PC87317_RTC_BANK_MAIN:
8586+ val |= 0x20;
8587+ break;
8588+ case PC87317_RTC_BANK_RTC:
8589+ val |= 0x30;
8590+ break;
8591+ case PC87317_RTC_BANK_APC:
8592+ val |= 0x40;
8593+ break;
8594+ }
8595+ CMOS_WRITE(val, 0xa);
8596+ }
8597+}
8598+
8599+#endif /* COBALT_SUPERIO_H */
8600diff -Naur linux-2.6.18.2.orig/include/cobalt/systype.h linux-2.6.18.2/include/cobalt/systype.h
8601--- linux-2.6.18.2.orig/include/cobalt/systype.h 1969-12-31 16:00:00.000000000 -0800
8602+++ linux-2.6.18.2/include/cobalt/systype.h 2006-11-15 21:20:19.766032388 -0800
8603@@ -0,0 +1,99 @@
8604+/*
8605+ * $Id: cobalt-systype.h,v 1.8 2002/08/08 22:46:50 carls Exp $
8606+ * cobalt-systype.h : figure out what Cobalt system we are on
8607+ *
8608+ * Copyright 2000 Cobalt Networks, Inc.
8609+ * Copyright 2001-2002 Sun Microsystems, Inc.
8610+ */
8611+#ifndef COBALT_SYSTYPE_H
8612+#define COBALT_SYSTYPE_H
8613+
8614+#include <cobalt/cobalt.h>
8615+
8616+typedef enum {
8617+ COBT_UNINITIALIZED,
8618+ COBT_UNKNOWN,
8619+ COBT_PACIFICA,
8620+ COBT_CARMEL,
8621+ COBT_MONTEREY,
8622+ COBT_ALPINE,
8623+ COBT_BIGBEAR,
8624+} cobt_sys_t;
8625+
8626+extern cobt_sys_t cobt_type;
8627+extern cobt_sys_t cobalt_systype_probe(void);
8628+extern unsigned long cobt_rev;
8629+
8630+/*
8631+ * one test for each major board-type
8632+ * COBT_SUPPORT_* from cobalt.h
8633+ */
8634+
8635+/* pacifica is the RaQ 3 and RaQ 4 platform */
8636+static inline int
8637+cobt_is_pacifica(void)
8638+{
8639+ if (!COBT_SUPPORT_GEN_III) {
8640+ return 0;
8641+ }
8642+ if (cobt_type == COBT_UNINITIALIZED) {
8643+ cobalt_systype_probe();
8644+ }
8645+ return (cobt_type == COBT_PACIFICA);
8646+}
8647+
8648+/* carmel is the Qube 3 platform */
8649+static inline int
8650+cobt_is_carmel(void)
8651+{
8652+ if (!COBT_SUPPORT_GEN_III) {
8653+ return 0;
8654+ }
8655+ if (cobt_type == COBT_UNINITIALIZED) {
8656+ cobalt_systype_probe();
8657+ }
8658+ return (cobt_type == COBT_CARMEL);
8659+}
8660+
8661+/* monterey is the RaQ XTR platform */
8662+static inline int
8663+cobt_is_monterey(void)
8664+{
8665+ if (!COBT_SUPPORT_GEN_V) {
8666+ return 0;
8667+ }
8668+ if (cobt_type == COBT_UNINITIALIZED) {
8669+ cobalt_systype_probe();
8670+ }
8671+ return (cobt_type == COBT_MONTEREY);
8672+}
8673+
8674+static inline int
8675+cobt_is_alpine(void)
8676+{
8677+ if (!COBT_SUPPORT_GEN_V) {
8678+ return 0;
8679+ }
8680+ if (cobt_type == COBT_UNINITIALIZED) {
8681+ cobalt_systype_probe();
8682+ }
8683+ return (cobt_type == COBT_ALPINE);
8684+}
8685+
8686+static inline int
8687+cobt_is_bigbear(void)
8688+{
8689+ if (!COBT_SUPPORT_GEN_V) {
8690+ return 0;
8691+ }
8692+ if (cobt_type == COBT_UNINITIALIZED) {
8693+ cobalt_systype_probe();
8694+ }
8695+ return (cobt_type == COBT_BIGBEAR);
8696+}
8697+
8698+/* one for each major generation */
8699+#define cobt_is_3k() (cobt_is_pacifica() || cobt_is_carmel())
8700+#define cobt_is_5k() (cobt_is_monterey() || cobt_is_alpine() || cobt_is_bigbear())
8701+
8702+#endif
8703diff -Naur linux-2.6.18.2.orig/include/cobalt/wdt.h linux-2.6.18.2/include/cobalt/wdt.h
8704--- linux-2.6.18.2.orig/include/cobalt/wdt.h 1969-12-31 16:00:00.000000000 -0800
8705+++ linux-2.6.18.2/include/cobalt/wdt.h 2006-11-15 21:20:19.766032388 -0800
8706@@ -0,0 +1,16 @@
8707+/* $Id: cobalt-wdt.h,v 1.1 2001/03/07 01:58:24 thockin Exp $ */
8708+/* Copyright 2001 Sun Microsystems, Inc. */
8709+#ifndef COBALT_WDT_H
8710+#define COBALT_WDT_H
8711+
8712+#include <cobalt/cobalt.h>
8713+
8714+void cobalt_wdt_refresh(unsigned long refresh_timer);
8715+void cobalt_wdt_trigger_reboot(void);
8716+
8717+void cobalt_wdt_disable(void);
8718+void cobalt_wdt_reenable(void);
8719+
8720+void cobalt_wdt_cleardog(void);
8721+
8722+#endif
8723diff -Naur linux-2.6.18.2.orig/init/main.c linux-2.6.18.2/init/main.c
8724--- linux-2.6.18.2.orig/init/main.c 2006-11-03 17:33:58.000000000 -0800
8725+++ linux-2.6.18.2/init/main.c 2006-11-15 21:20:19.770032256 -0800
8726@@ -650,6 +650,10 @@
8727 *
8728 * Now we can finally start doing some real work..
8729 */
8730+#ifdef CONFIG_COBALT_RAQ
8731+extern int cobalt_init(void);
8732+#endif
8733+
8734 static void __init do_basic_setup(void)
8735 {
8736 /* drivers will send hotplug events */
8737@@ -662,6 +666,10 @@
8738 #endif
8739
8740 do_initcalls();
8741+
8742+#ifdef CONFIG_COBALT_RAQ
8743+ cobalt_init();
8744+#endif
8745 }
8746
8747 static void do_pre_smp_initcalls(void)
Note: See TracBrowser for help on using the repository browser.