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

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

Updated to Linux 2.6.20.1

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