source:
clfs-embedded/patches/linux-2.6.20.1-cobalt_x86-1.patch@
88b7bb1
Last change on this file since 88b7bb1 was 9a57cc4, checked in by , 18 years ago | |
---|---|
|
|
File size: 217.6 KB |
-
linux-2.6.20
Submitted By: Jim Gifford (patches at jg555 dot com) Date: 2007-02-04 Initial Package Version: 2.6.20 Origin: Gentoo - Jeff Waters Upstream Status: N/A Description: Adds Support for the x86 Cobalt Series diff -Naur linux-2.6.20.orig/Makefile linux-2.6.20/Makefile
old new 206 206 KBUILD_MODULES := 207 207 KBUILD_BUILTIN := 1 208 208 209 DRIVERS-$(CONFIG_COBALT_RAQ) += drivers/cobalt/cobalt.o 209 210 # If we have only "make modules", don't compile built-in objects. 210 211 # When we're building modules with modversions, we need to consider 211 212 # the built-in objects during the descend as well, in order to … … 703 704 cmd_kallsyms = $(NM) -n $< | $(KALLSYMS) \ 704 705 $(if $(CONFIG_KALLSYMS_ALL),--all-symbols) > $@ 705 706 707 708 cobalt: vmlinux 709 strip vmlinux 710 bzip2 vmlinux 711 706 712 .tmp_kallsyms1.o .tmp_kallsyms2.o .tmp_kallsyms3.o: %.o: %.S scripts FORCE 707 713 $(call if_changed_dep,as_o_S) 708 714 -
arch/i386/kernel/Makefile
diff -Naur linux-2.6.20.orig/arch/i386/kernel/Makefile linux-2.6.20/arch/i386/kernel/Makefile
old new 55 55 targets += vsyscall-note.o vsyscall.lds 56 56 57 57 # The DSO images are built using a special linker script. 58 obj-$(CONFIG_COBALT_RAQ) += cobalt.o 58 59 quiet_cmd_syscall = SYSCALL $@ 59 60 cmd_syscall = $(CC) -m elf_i386 -nostdlib $(SYSCFLAGS_$(@F)) \ 60 61 -Wl,-T,$(filter-out FORCE,$^) -o $@ -
arch/i386/kernel/cobalt.c
diff -Naur linux-2.6.20.orig/arch/i386/kernel/cobalt.c linux-2.6.20/arch/i386/kernel/cobalt.c
old new 1 /* $Id: cobalt.c,v 1.34 2002/11/04 17:54:14 thockin Exp $ */ 2 #include <linux/config.h> 3 4 #include <linux/types.h> 5 #include <linux/stddef.h> 6 #include <linux/kernel.h> 7 #include <linux/ptrace.h> 8 #include <linux/reboot.h> 9 #include <linux/delay.h> 10 #include <linux/pci.h> 11 #include <linux/timer.h> 12 #include <linux/init.h> 13 14 #include <cobalt/cobalt.h> 15 #include <cobalt/misc.h> 16 #include <cobalt/led.h> 17 #include <cobalt/wdt.h> 18 #include <cobalt/acpi.h> 19 #include <cobalt/superio.h> 20 #include <cobalt/systype.h> 21 22 #define MAX_NMI_PS 10 23 24 static u8 last_err; 25 static u32 last_address; 26 static unsigned long nmi_repeats; 27 static struct timer_list nmi_timer; 28 static int timer_added; 29 static unsigned long nmi_count; 30 static spinlock_t nmi_state_lock = SPIN_LOCK_UNLOCKED; 31 32 static inline void 33 ledonoff(unsigned long on, unsigned long off) 34 { 35 #ifdef CONFIG_COBALT_LED 36 unsigned long start; 37 int haltok = current_cpu_data.hlt_works_ok; 38 39 if (on) { 40 start = jiffies; 41 cobalt_led_set(cobalt_led_get() | LED_SHUTDOWN); 42 while (jiffies < start + on) { 43 if (haltok) __asm__("hlt"); 44 } 45 } 46 47 if (off) { 48 start = jiffies; 49 cobalt_led_set(cobalt_led_get() & ~LED_SHUTDOWN); 50 while (jiffies < start + off) { 51 if (haltok) __asm__("hlt"); 52 } 53 } 54 #endif 55 } 56 57 /* clla this holding nmi_state_lock */ 58 static inline void 59 do_repeats(void) 60 { 61 if (nmi_repeats) { 62 printk("NMI: last error repeated %lu times\n", nmi_repeats); 63 nmi_repeats = 0; 64 } 65 } 66 67 static void 68 nmi_throttle_fn(unsigned long data) 69 { 70 unsigned long flags; 71 72 spin_lock_irqsave(&nmi_state_lock, flags); 73 74 /* clear any repeated NMIs */ 75 do_repeats(); 76 77 /* have we had a lot of errors this second */ 78 if (nmi_count > MAX_NMI_PS) { 79 printk("NMI: %lu messages were throttled\n", 80 nmi_count - MAX_NMI_PS); 81 nmi_count = 0; 82 } 83 84 /* de-activate the timer - will be reactivated by an NMI */ 85 del_timer(&nmi_timer); 86 timer_added = 0; 87 88 spin_unlock_irqrestore(&nmi_state_lock, flags); 89 } 90 91 void 92 cobalt_nmi(unsigned char reason, struct pt_regs *regs) 93 { 94 if (cobt_is_5k()) { 95 static struct pci_dev *cnb_dev; 96 u8 err; 97 u32 address = 0; 98 unsigned long flags; 99 100 /* find our memory controller */ 101 if (!cnb_dev) { 102 cnb_dev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, 103 PCI_DEVICE_ID_SERVERWORKS_LE, NULL); 104 } 105 if (!cnb_dev) { 106 EPRINTK("can't find north bridge for NMI status\n"); 107 return; 108 } 109 110 /* read the error number */ 111 pci_read_config_byte(cnb_dev, 0x47, &err); 112 113 /* if a memory error was detected, where? */ 114 if (err & 0x06) { 115 pci_read_config_dword(cnb_dev, 0x94, &address); 116 } 117 118 spin_lock_irqsave(&nmi_state_lock, flags); 119 120 /* set up the timer, if it isn't set to go already */ 121 if (!timer_added) { 122 init_timer(&nmi_timer); 123 nmi_timer.expires = jiffies + HZ; 124 nmi_timer.function = nmi_throttle_fn; 125 add_timer(&nmi_timer); 126 timer_added = 1; 127 } 128 129 /* if we already printed this error */ 130 if (last_err && err == last_err && address == last_address) { 131 nmi_repeats++; 132 spin_unlock_irqrestore(&nmi_state_lock, flags); 133 } else { 134 unsigned long nmi_now; 135 136 /* different error - show repeats */ 137 do_repeats(); 138 139 /* we only want to do a few messages per second */ 140 nmi_now = nmi_count++; 141 142 spin_unlock_irqrestore(&nmi_state_lock, flags); 143 144 /* generate a new message */ 145 if (nmi_now < MAX_NMI_PS) { 146 /* only remember NMIs that we can print */ 147 last_err = err; 148 last_address = address; 149 150 printk("NMI:"); 151 if (err & 0x40) 152 printk(" (PCI tx data error)"); 153 if (err & 0x20) 154 printk(" (PCI rx data error)"); 155 if (err & 0x10) 156 printk(" (PCI address error)"); 157 if (err & 0x04) 158 printk(" (DRAM uncorrectable error)"); 159 if (err & 0x02) 160 printk(" (DRAM correctable error)"); 161 if (err & 0x01) 162 printk(" (Shutdown cycle detected)"); 163 164 if (err & 0x06) { 165 u8 row, dimm, ecc; 166 167 row = (address >> 29) & 0x7; 168 pci_read_config_byte(cnb_dev, 169 0x7c + (row >> 1), &dimm); 170 dimm = ((row & 1) ? 171 (dimm >> 4) : dimm) & 0xf; 172 pci_read_config_byte(cnb_dev, 0xe8, 173 &ecc); 174 175 printk(" [memory row %d, DIMM type %d, " 176 "col=0x%x, row=0x%x, ECC=0x%x]", 177 row, dimm, 178 (address >> 15) & 0x3fff, 179 address & 0x7fff, ecc); 180 } 181 printk("\n"); 182 } 183 } 184 185 /* clear errors */ 186 pci_write_config_byte(cnb_dev, 0x47, err); 187 } else { 188 /* TODO: make throttling generic, handle GP NMIs */ 189 printk("NMI: unknown error\n"); 190 } 191 } 192 193 void 194 cobalt_restart(void) 195 { 196 if (cobt_is_3k()) { 197 /* kick watchdog */ 198 cobalt_wdt_trigger_reboot(); 199 } else if (cobt_is_5k()) { 200 /* set "Enable Hard Reset" bit to 1 */ 201 outb(0x02, 0x0cf9); 202 203 /* 0-to-1 transition of bit 2 will cause reset of processor */ 204 outb(0x06, 0x0cf9); 205 } 206 mdelay(3000); 207 208 /* we should not get here unless there is a BAD error */ 209 EPRINTK("can not restart - halting\n"); 210 machine_halt(); 211 } 212 213 void 214 cobalt_halt(void) 215 { 216 int haltok = current_cpu_data.hlt_works_ok; 217 218 if (cobt_is_5k()) { 219 /* we have soft power-off */ 220 machine_power_off(); 221 } 222 223 /* 224 * we want to do cpu_idle, but we don't actually want to 225 * call cpu_idle. bleah. 226 */ 227 while (1) { 228 ledonoff(HZ >> 1, HZ >> 1); 229 if (haltok) { 230 __asm__("hlt"); 231 } 232 } 233 } 234 235 void 236 cobalt_power_off(void) 237 { 238 u16 addr; 239 240 if (cobt_is_monterey()) { 241 u8 val; 242 /* use card control reg. 7 to select logical device 2 (APC) */ 243 addr = superio_ldev_base(PC87317_DEV_RTC); 244 245 /* set up bank 2 */ 246 outb(PC87317_RTC_CRA, addr); 247 val = inb(addr + 1) & 0x8f; 248 outb(val | PC87317_RTC_BANK_2, addr + 1); 249 250 /* power off the machine with APCR1 */ 251 outb(PC87317_APCR1, addr); 252 val = inb(addr + 1); 253 outb(0x20 | val, addr + 1); 254 } else if (cobt_is_alpine()) { 255 int i; 256 /* clear status bits, base addr 3 */ 257 addr = superio_ldev_base_n(PC87417_DEV_SWC, 3); 258 for (i = 0; i < 4; i++) { 259 /* 260 * if we have an event while running, 261 * we can't halt unless we clear these 262 * */ 263 outb(0xff, addr+i); 264 } 265 266 /* set sleep state, base addr 2 */ 267 addr = superio_ldev_base_n(PC87417_DEV_SWC, 2); 268 /* PM1b_CNT_HIGH @offset 1 - set state to S5 */ 269 outb(0x34, addr+1); 270 } 271 mdelay(3000); 272 EPRINTK("can not power off\n"); 273 } 274 275 /* put arch specific stuff to run at init time here */ 276 static int __init 277 cobalt_arch_init(void) 278 { 279 return 0; 280 } 281 module_init(cobalt_arch_init); -
arch/i386/kernel/process.c
diff -Naur linux-2.6.20.orig/arch/i386/kernel/process.c linux-2.6.20/arch/i386/kernel/process.c
old new 52 52 #include <asm/math_emu.h> 53 53 #endif 54 54 55 #ifdef CONFIG_COBALT_RAQ 56 #include <cobalt/misc.h> 57 #include <cobalt/lcd.h> 58 #endif 59 55 60 #include <linux/err.h> 56 61 57 62 #include <asm/tlbflush.h> … … 477 482 void dump_thread(struct pt_regs * regs, struct user * dump) 478 483 { 479 484 int i; 485 486 #ifdef CONFIG_COBALT_RAQ 487 cobalt_flush(); 488 cobalt_restart(); 489 #endif 490 480 491 481 492 /* changed the size calculations - should hopefully work better. lbt */ 482 493 dump->magic = CMAGIC; -
arch/i386/kernel/reboot.c
diff -Naur linux-2.6.20.orig/arch/i386/kernel/reboot.c linux-2.6.20/arch/i386/kernel/reboot.c
old new 19 19 #include "mach_reboot.h" 20 20 #include <linux/reboot_fixups.h> 21 21 22 #ifdef CONFIG_COBALT_RAQ 23 #include <cobalt/misc.h> 24 #include <cobalt/lcd.h> 25 #endif 26 22 27 /* 23 28 * Power off function, if any 24 29 */ … … 280 285 EXPORT_SYMBOL(machine_real_restart); 281 286 #endif 282 287 288 /* kill some time at halt/reboot to allow drives with large cache to sync */ 289 290 #ifdef CONFIG_COBALT_RAQ 291 void cobalt_flush(void) 292 { 293 int i; 294 static int flushed; 295 296 if (flushed) 297 return; 298 flushed = 1; 299 300 printk("waiting for devices to flush"); 301 for (i = 0 ; i < 10; i++) { 302 printk("."); 303 mdelay(500); 304 #ifdef CONFIG_COBALT_LCD 305 if (i == 8) 306 cobalt_lcd_off(); 307 #endif 308 } 309 printk("done\n"); 310 } 311 #endif 312 283 313 void machine_shutdown(void) 284 314 { 315 #ifdef CONFIG_COBALT_RAQ 316 cobalt_flush(); 317 cobalt_halt(); 318 #endif 319 285 320 #ifdef CONFIG_SMP 286 321 int reboot_cpu_id; 287 322 … … 318 353 319 354 void machine_emergency_restart(void) 320 355 { 356 #ifdef CONFIG_COBALT_RAQ 357 cobalt_restart(); 358 #endif 321 359 if (!reboot_thru_bios) { 322 360 if (efi_enabled) { 323 361 efi.reset_system(EFI_RESET_COLD, EFI_SUCCESS, 0, NULL); … … 342 380 343 381 void machine_restart(char * __unused) 344 382 { 383 #ifdef CONFIG_COBALT_RAQ 384 cobalt_flush(); 385 cobalt_restart(); 386 #endif 345 387 machine_shutdown(); 346 388 machine_emergency_restart(); 347 389 } -
arch/i386/kernel/traps.c
diff -Naur linux-2.6.20.orig/arch/i386/kernel/traps.c linux-2.6.20/arch/i386/kernel/traps.c
old new 61 61 62 62 int panic_on_unrecovered_nmi; 63 63 64 #ifdef CONFIG_COBALT_RAQ 65 #include <cobalt/misc.h> 66 #endif 67 64 68 asmlinkage int system_call(void); 65 69 66 70 /* Do we ignore FPU interrupts ? */ … … 631 635 static __kprobes void 632 636 mem_parity_error(unsigned char reason, struct pt_regs * regs) 633 637 { 638 #ifdef CONFIG_COBALT_RAQ 639 cobalt_nmi(reason, regs); 640 #else 634 641 printk(KERN_EMERG "Uhhuh. NMI received for unknown reason %02x on " 635 642 "CPU %d.\n", reason, smp_processor_id()); 636 643 printk(KERN_EMERG "You have some hardware problem, likely on the PCI bus.\n"); … … 638 645 panic("NMI: Not continuing"); 639 646 640 647 printk(KERN_EMERG "Dazed and confused, but trying to continue\n"); 641 648 #endif 642 649 /* Clear and disable the memory parity error line. */ 643 650 clear_mem_error(reason); 644 651 } -
drivers/Kconfig
diff -Naur linux-2.6.20.orig/drivers/Kconfig linux-2.6.20/drivers/Kconfig
old new 82 82 83 83 source "drivers/kvm/Kconfig" 84 84 85 source "drivers/cobalt/Kconfig" 86 85 87 endmenu -
drivers/Makefile
diff -Naur linux-2.6.20.orig/drivers/Makefile linux-2.6.20/drivers/Makefile
old new 67 67 obj-$(CONFIG_EDAC) += edac/ 68 68 obj-$(CONFIG_MCA) += mca/ 69 69 obj-$(CONFIG_EISA) += eisa/ 70 obj-$(CONFIG_COBALT_RAQ) += cobalt/ 71 70 72 obj-$(CONFIG_CPU_FREQ) += cpufreq/ 71 73 obj-$(CONFIG_MMC) += mmc/ 72 74 obj-$(CONFIG_NEW_LEDS) += leds/ -
drivers/char/Kconfig
diff -Naur linux-2.6.20.orig/drivers/char/Kconfig linux-2.6.20/drivers/char/Kconfig
old new 808 808 will get access to the real time clock (or hardware clock) built 809 809 into your computer. 810 810 811 config COBALT_ LCD811 config COBALT_MIPS_LCD 812 812 bool "Support for Cobalt LCD" 813 813 depends on MIPS_COBALT 814 814 help -
drivers/char/Makefile
diff -Naur linux-2.6.20.orig/drivers/char/Makefile linux-2.6.20/drivers/char/Makefile
old new 79 79 obj-$(CONFIG_I8K) += i8k.o 80 80 obj-$(CONFIG_DS1620) += ds1620.o 81 81 obj-$(CONFIG_HW_RANDOM) += hw_random/ 82 obj-$(CONFIG_COBALT_ LCD) += lcd.o82 obj-$(CONFIG_COBALT_MIPS_LCD) += lcd.o 83 83 obj-$(CONFIG_PPDEV) += ppdev.o 84 84 obj-$(CONFIG_NWBUTTON) += nwbutton.o 85 85 obj-$(CONFIG_NWFLASH) += nwflash.o -
drivers/char/misc.c
diff -Naur linux-2.6.20.orig/drivers/char/misc.c linux-2.6.20/drivers/char/misc.c
old new 49 49 #include <linux/tty.h> 50 50 #include <linux/kmod.h> 51 51 52 #ifdef CONFIG_COBALT_RAQ 53 #include <cobalt/cobalt.h> 54 #include <cobalt/systype.h> 55 #include <cobalt/superio.h> 56 #include <cobalt/serialnum.h> 57 #include <cobalt/i2c.h> 58 #include <cobalt/misc.h> 59 #include <cobalt/lcd.h> 60 #endif 61 62 52 63 /* 53 64 * Head entry for the doubly linked miscdevice list 54 65 */ … … 63 74 64 75 extern int pmu_device_init(void); 65 76 77 #ifdef CONFIG_COBALT_RAQ 78 extern int cobalt_init(void); 79 #endif 80 #ifdef CONFIG_COBALT_MIPS_LCD 81 module_init(lcd_init); 82 #endif 83 66 84 #ifdef CONFIG_PROC_FS 67 85 static void *misc_seq_start(struct seq_file *seq, loff_t *pos) 68 86 { -
drivers/char/nvram.c
diff -Naur linux-2.6.20.orig/drivers/char/nvram.c linux-2.6.20/drivers/char/nvram.c
old new 49 49 #if defined(CONFIG_ATARI) 50 50 # define MACH ATARI 51 51 #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) /* and others?? */ 52 #define MACH PC 53 # if defined(CONFIG_COBALT) 52 # if defined(CONFIG_COBALT_RAQ) 54 53 # include <linux/cobalt-nvram.h> 55 54 # define MACH COBALT 56 55 # else -
drivers/cobalt/Kconfig
diff -Naur linux-2.6.20.orig/drivers/cobalt/Kconfig linux-2.6.20/drivers/cobalt/Kconfig
old new 1 # 2 # Cobalt Drivers 3 # 4 5 menu "Cobalt RaQ/Qube Hardware" 6 7 config COBALT_RAQ 8 bool "Cobalt RaQ/Qube Hardware Support" 9 select INPUT 10 default n 11 ---help--- 12 NOTE: This support is for x86 Cobalts, not MIPS versions 13 14 If you have a Gen III or Gen V Cobalt RaQ/Qube machine, it's probably 15 a good idea to say Y here and choose from the options below. 16 17 config COBALT_GEN_III 18 bool "Gen III (3000 series) system support" 19 depends on COBALT_RAQ 20 default y 21 ---help--- 22 If you have one of the following Gen III Cobalt systems, say Y here. 23 Otherwise, it's best to say N. 24 25 - RaQ 3 26 - RaQ 4 27 - Qube3 28 29 config COBALT_GEN_V 30 bool "Gen V (5000 series) system support" 31 depends on COBALT_RAQ 32 default n 33 ---help--- 34 If you have one of the following Gen V Cobalt systems, say Y here. 35 Otherwise, it's best to say N. 36 37 - RaQ XTR 38 - RaQ550 39 40 config COBALT_OLDPROC 41 bool "Create legacy /proc files" 42 depends on COBALT_RAQ 43 default y 44 ---help--- 45 Creates entries in /proc/cobalt which provide useful information about 46 your RaQ/Qube. Best to say Y here. 47 48 menu "Cobalt Hardware Options" 49 depends on COBALT_RAQ 50 51 config COBALT_LCD 52 bool "Front panel LCD support" 53 default y 54 ---help--- 55 Handles support for the front panel LCD screen and buttons. 56 57 config COBALT_LCD_TWIDDLE 58 bool "Twiddle LCD on boot" 59 depends on COBALT_LCD 60 default y 61 ---help--- 62 Gives you a nice little twiddle on the LCD while booting. 63 64 config COBALT_LED 65 bool "Software controlled LED support" 66 default y 67 ---help--- 68 Allows software to play with the LEDs on the front of the 69 system. 70 71 config COBALT_SERNUM 72 tristate "Serial number support" 73 depends on COBALT_OLDPROC 74 default y 75 ---help--- 76 Allows you to retrieve the system's serial number via a /proc 77 entry. 78 79 config COBALT_WDT 80 bool "Watchdog timer support" 81 depends on WATCHDOG 82 default y 83 ---help--- 84 w00f? 85 86 config COBALT_SENSORS 87 bool "System sensors support" 88 depends on COBALT_OLDPROC 89 default y 90 ---help--- 91 Allows you to retrieve system temperatures via /proc entries. 92 93 config COBALT_FANS 94 tristate "Fan tachometer support" 95 depends on COBALT_OLDPROC 96 depends on COBALT_GEN_V 97 default y 98 ---help--- 99 Allows you to retrieve fan speeds via /proc entries. 100 101 config COBALT_RAMINFO 102 tristate "Memory information support" 103 depends on COBALT_OLDPROC 104 default y 105 ---help--- 106 Got DIMMs? This will tell you how much and in which slot via a 107 /proc entry. 108 109 config COBALT_RULER 110 bool "Disk drive ruler support" 111 depends on COBALT_OLDPROC 112 depends on COBALT_GEN_V 113 default y 114 ---help--- 115 Not sure what this does... A purple tape measure maybe? 116 117 config COBALT_ACPI 118 bool "Cobalt ACPI support" 119 depends on COBALT_GEN_V 120 default y 121 ---help--- 122 ACPI support for the Generation V Cobalts. 123 124 config COBALT_EMU_ACPI 125 bool "/proc/acpi emulation" 126 depends on COBALT_ACPI 127 default y 128 ---help--- 129 Emulates the /proc/acpi interface. 130 131 endmenu 132 133 endmenu -
drivers/cobalt/Makefile
diff -Naur linux-2.6.20.orig/drivers/cobalt/Makefile linux-2.6.20/drivers/cobalt/Makefile
old new 1 # 2 # Makefile for the Sun/Cobalt device drivers 3 # 4 5 #O_TARGET := cobalt.o 6 7 #export-objs := init.o systype.o wdt.o i2c.o 8 9 obj-$(CONFIG_COBALT_RAQ) += init.o systype.o i2c.o wdt.o 10 obj-$(CONFIG_COBALT_ACPI) += acpi.o 11 obj-$(CONFIG_COBALT_SERNUM) += serialnum.o 12 obj-$(CONFIG_COBALT_LCD) += lcd.o 13 obj-$(CONFIG_COBALT_LED) += net.o led.o 14 obj-$(CONFIG_COBALT_SENSORS) += sensors.o 15 obj-$(CONFIG_COBALT_FANS) += fans.o 16 obj-$(CONFIG_COBALT_RAMINFO) += raminfo.o 17 obj-$(CONFIG_COBALT_RULER) += ruler.o 18 -
drivers/cobalt/README
diff -Naur linux-2.6.20.orig/drivers/cobalt/README linux-2.6.20/drivers/cobalt/README
old new 1 Notes on Cobalt's drivers: 2 3 You will notice in several places constructs such as this: 4 5 if (cobt_is_3k()) { 6 foo(); 7 } else if (cobt_is_5k()) { 8 bar(); 9 } 10 11 The goal here is to only compile in code that is needed, but to allow one to 12 define support for both 3k and 5k (and more?) style systems. The systype 13 check macros are very simple and clean. They check whether config-time 14 support for the generation has been enabled, and (if so) whether the current 15 systype matches the spcified generation. This leaves the code free from 16 #ifdef cruft, but lets the compiler throw out unsupported generation-specific 17 code with if (0) detection. 18 19 -- -
drivers/cobalt/acpi.c
diff -Naur linux-2.6.20.orig/drivers/cobalt/acpi.c linux-2.6.20/drivers/cobalt/acpi.c
old new 1 /* 2 * cobalt acpi driver 3 * Copyright (c) 2000, Cobalt Networks, Inc. 4 * Copyright (c) 2001, Sun Microsystems, Inc. 5 * $Id: acpi.c,v 1.32 2002/06/26 19:08:54 duncan Exp $ 6 * 7 * author: asun@cobalt.com, thockin@sun.com 8 * modified by: jeff@404ster.com 9 * 10 * this driver just sets stuff up for ACPI interrupts 11 * 12 * if acpi support really existed in the kernel, we would read 13 * data from the ACPI tables. however, it doesn't. as a result, 14 * we use some hardcoded values. 15 * 16 * This should be SMP safe. The only data that needs protection is the acpi 17 * handler list. It gets scanned at timer-interrupts, must use 18 * irqsave/restore locks. Read/write locks would be useful if there were any 19 * other times that the list was read but never written. --TPH 20 * 21 * /proc/acpi emulation emulates the /proc/acpi/events interface supplied by 22 * the INTEL acpi drivers. A lot of the code to handle it has been adapted 23 * from there. 24 */ 25 26 #include <stdarg.h> 27 #include <stddef.h> 28 #include <linux/init.h> 29 #include <linux/sched.h> 30 #include <linux/config.h> 31 #include <linux/pci.h> 32 #include <linux/sched.h> 33 #include <linux/ioport.h> 34 #include <linux/delay.h> 35 #include <linux/spinlock.h> 36 #include <linux/proc_fs.h> 37 #include <linux/poll.h> 38 #include <linux/interrupt.h> 39 #include <asm/uaccess.h> 40 #include <asm/io.h> 41 #include <asm/irq.h> 42 43 #include <cobalt/cobalt.h> 44 #include <cobalt/systype.h> 45 #include <cobalt/acpi.h> 46 #include <cobalt/superio.h> 47 48 #define ACPI_DRIVER "Cobalt Networks ACPI driver" 49 #define ACPI_DRIVER_VMAJ 1 50 #define ACPI_DRIVER_VMIN 0 51 52 #define POWER_BUTTON_SHUTDOWN 0 53 54 #define ACPI_IRQ 10 /* XXX: hardcoded interrupt */ 55 #define ACPI_NAME "sci" 56 #define ACPI_MAGIC 0xc0b7ac21 57 58 #define SUPERIO_EVENT 0xff 59 #define OSB4_EVENT 0x40 60 #define OSB4_INDEX_PORT SERVERWORKS_ACPI_INDEX_PORT 61 #define OSB4_DATA_PORT SERVERWORKS_ACPI_DATA_PORT 62 63 #define GEN_ACPI_TMR_STS (0x1 << 0) 64 #define GEN_ACPI_BM_STS (0x1 << 4) 65 #define GEN_ACPI_GBL_STS (0x1 << 5) 66 #define GEN_ACPI_PWRBTN_STS (0x1 << 8) 67 #define GEN_ACPI_SLPBTN_STS (0x1 << 9) 68 #define GEN_ACPI_RTC_STS (0x1 << 10) 69 #define GEN_ACPI_WAK_STS (0x1 << 15) 70 71 #ifdef CONFIG_COBALT_EMU_ACPI 72 static int cobalt_acpi_setup_proc(void); 73 static int cobalt_acpi_open_event(struct inode *inode, struct file *file); 74 static int cobalt_acpi_close_event(struct inode *inode, struct file *file); 75 static ssize_t cobalt_acpi_read_event(struct file *file, char *buf, 76 size_t count, loff_t *ppos); 77 static unsigned int cobalt_acpi_poll_event(struct file *file, poll_table *wait); 78 #endif 79 80 81 82 typedef struct 83 { 84 u16 hw_type; 85 cobalt_acpi_hw_handler hw_handler; 86 cobalt_acpi_enable_handler en_handler; 87 void *data; 88 struct list_head link; 89 } hw_handler_datum; 90 91 typedef struct 92 { 93 u16 hw_type; 94 u16 table_len; 95 u16 *table; 96 struct list_head link; 97 } trans_table_datum; 98 99 typedef struct 100 { 101 cobalt_acpi_evt_handler handler; 102 u16 ev_type; 103 void *data; 104 struct list_head link; 105 } evt_handler_datum; 106 107 typedef struct 108 { 109 cobalt_acpi_evt evt; 110 struct list_head link; 111 } evt_list_datum; 112 113 static LIST_HEAD( hw_handler_list ); 114 static spinlock_t hw_handler_list_lock = SPIN_LOCK_UNLOCKED; 115 static LIST_HEAD( trans_table_list ); 116 static spinlock_t trans_table_list_lock = SPIN_LOCK_UNLOCKED; 117 static LIST_HEAD( evt_handler_list ); 118 static spinlock_t evt_handler_list_lock = SPIN_LOCK_UNLOCKED; 119 static LIST_HEAD( dispatch_queue ); 120 static spinlock_t dispatch_queue_lock = SPIN_LOCK_UNLOCKED; 121 122 typedef struct 123 { 124 u16 hw_type; 125 126 /* block lengths */ 127 u16 pm1_evt_len; 128 u16 pm1_cnt_len; 129 u16 pm2_cnt_len; 130 u16 pm_tmr_len; 131 u16 gpe0_len; 132 u16 gpe1_len; 133 134 /* block I/O locations */ 135 u16 pm1a_evt_blk; 136 u16 pm1b_evt_blk; 137 u16 pm1a_cnt_blk; 138 u16 pm1b_cnt_blk; 139 u16 pm2_cnt_blk; 140 u16 pm_tmr_blk; 141 u16 p_blk; 142 u16 gpe0_blk; 143 u16 gpe1_blk; 144 145 /* ponters to strings for the io names */ 146 char *pm1a_evt_nam; 147 char *pm1b_evt_nam; 148 char *pm1a_cnt_nam; 149 char *pm1b_cnt_nam; 150 char *pm2_cnt_nam; 151 char *pm_tmr_nam; 152 char *p_nam; 153 char *gpe0_nam; 154 char *gpe1_nam; 155 156 /* reference counts for events */ 157 atomic_t tmr_ref_cnt; 158 atomic_t bm_ref_cnt; 159 atomic_t gbl_ref_cnt; 160 atomic_t pwrbtn_ref_cnt; 161 atomic_t slpbtn_ref_cnt; 162 atomic_t rtc_ref_cnt; 163 atomic_t wak_ref_cnt; 164 atomic_t *gpe_ref_cnt; 165 166 167 } generic_acpi_regions; 168 169 170 static void cobalt_acpi_enable_event( u16 ev_type, int en ); 171 static void cobalt_acpi_run_enable_handler( u16 hw_type, u16 ev_type, 172 u16 ev_data, int en); 173 static int cobalt_acpi_apply_evt_handlers( evt_list_datum *d ); 174 static int cobalt_acpi_run_dispatch_queue( void ); 175 static irqreturn_t acpi_interrupt(int irq, void *dev_id, struct pt_regs *regs); 176 static void cobalt_acpi_cleanup( void ); 177 178 static int register_acpi_regions( generic_acpi_regions *regions, char * subsys_name ); 179 static int unregister_acpi_regions( generic_acpi_regions *regions ); 180 static void cobalt_acpi_handle_pm1_blk( u16 io_addr, u16 len, 181 generic_acpi_regions * regions ); 182 static void cobalt_acpi_handle_gpe_blk( u16 io_addr, u16 len, 183 generic_acpi_regions * regions ); 184 static int cobalt_acpi_generic_hw_handler( int irq, void *dev_id, 185 struct pt_regs *regs, void * data ); 186 187 static int cobalt_acpi_osb4_init( void ); 188 static int cobalt_acpi_osb4_cleanup( void ); 189 static int get_osb4_regions( generic_acpi_regions *regions); 190 191 static int cobalt_acpi_csb5_init( void ); 192 static int cobalt_acpi_csb5_cleanup( void ); 193 static int get_csb5_regions( generic_acpi_regions *regions); 194 195 static int cobalt_acpi_pc8731x_init( void ); 196 static int cobalt_acpi_pc8731x_cleanup( void ); 197 static int get_pc8731x_regions( generic_acpi_regions *regions ); 198 199 static int cobalt_acpi_pc8741x_init( void ); 200 static int cobalt_acpi_pc8741x_cleanup( void ); 201 static int get_pc8741x_regions( generic_acpi_regions *regions ); 202 203 static int cobalt_acpi_monterey_init( void ); 204 static int cobalt_acpi_monterey_cleanup( void ); 205 206 static int cobalt_acpi_alpine_init( void ); 207 static int cobalt_acpi_alpine_cleanup( void ); 208 209 static __inline__ struct list_head *list_pop( struct list_head *head ) 210 { 211 struct list_head *e; 212 213 if( list_empty( head ) ) 214 return NULL; 215 216 e = head->next; 217 list_del( e ); 218 return e; 219 } 220 221 static __inline__ u16 get_reg(u16 index, u16 data, u8 port) 222 { 223 u16 reg; 224 225 outb(port, index); 226 reg = inb(data); 227 outb(port + 1, index); 228 reg |= inb(data) << 8; 229 return reg; 230 } 231 232 /* 233 * 234 * Main ACPI Subsystem Code 235 * 236 */ 237 238 extern int cobalt_acpi_register_hw_handler( u16 hw_type, 239 cobalt_acpi_hw_handler hw_handler, 240 cobalt_acpi_enable_handler en_handler, 241 void *data ) 242 { 243 hw_handler_datum *d; 244 unsigned long flags; 245 246 if( ! (d = (hw_handler_datum *) kmalloc( sizeof( hw_handler_datum ), GFP_ATOMIC )) ) 247 return -ENOMEM; 248 249 d->hw_type = hw_type; 250 d->hw_handler = hw_handler; 251 d->en_handler = en_handler; 252 d->data = data; 253 254 spin_lock_irqsave( &hw_handler_list_lock, flags ); 255 list_add( &(d->link), &hw_handler_list ); 256 spin_unlock_irqrestore( &hw_handler_list_lock, flags ); 257 258 return 0; 259 } 260 261 extern int cobalt_acpi_unregister_hw_handler( cobalt_acpi_hw_handler handler ) 262 { 263 struct list_head *pos; 264 unsigned long flags; 265 266 spin_lock_irqsave( &hw_handler_list_lock, flags ); 267 list_for_each( pos, &hw_handler_list ) 268 { 269 if( list_entry( pos, hw_handler_datum, link )->hw_handler == handler ) 270 { 271 list_del( pos ); 272 spin_unlock_irqrestore( &hw_handler_list_lock, flags ); 273 274 kfree( list_entry( pos, hw_handler_datum, link ) ); 275 return 0; 276 } 277 278 }; 279 280 spin_unlock_irqrestore( &hw_handler_list_lock, flags ); 281 return -1; 282 } 283 284 extern int cobalt_acpi_register_trans_table( u16 hw_type, u16 table_len, u16 *table ) 285 { 286 trans_table_datum *d; 287 unsigned long flags; 288 289 if( ! (d = (trans_table_datum *) kmalloc( sizeof( trans_table_datum ), GFP_ATOMIC )) ) 290 return -ENOMEM; 291 292 d->hw_type = hw_type; 293 d->table_len = table_len; 294 d->table = table; 295 296 spin_lock_irqsave( &trans_table_list_lock, flags ); 297 list_add( &(d->link), &trans_table_list ); 298 spin_unlock_irqrestore( &trans_table_list_lock, flags ); 299 300 return 0; 301 } 302 303 extern int cobalt_acpi_unregister_trans_table( u16 hw_type ) 304 { 305 struct list_head *pos; 306 unsigned long flags; 307 308 spin_lock_irqsave( &trans_table_list_lock, flags ); 309 list_for_each( pos, &trans_table_list ) 310 { 311 if( list_entry( pos, trans_table_datum, link )->hw_type == hw_type ) 312 { 313 list_del( pos ); 314 spin_unlock_irqrestore( &trans_table_list_lock, flags ); 315 316 kfree( list_entry( pos, trans_table_datum, link ) ); 317 return 0; 318 } 319 320 }; 321 322 spin_unlock_irqrestore( &trans_table_list_lock, flags ); 323 return -1; 324 } 325 326 extern int cobalt_acpi_register_evt_handler( cobalt_acpi_evt_handler handler, 327 u16 ev_type, 328 void *data ) 329 { 330 evt_handler_datum *d; 331 unsigned long flags; 332 333 if( ! (d = (evt_handler_datum *) kmalloc( sizeof( evt_handler_datum ), GFP_ATOMIC )) ) 334 return -ENOMEM; 335 336 d->handler = handler; 337 d->data = data; 338 d->ev_type = ev_type; 339 340 spin_lock_irqsave( &evt_handler_list_lock, flags ); 341 list_add( &(d->link), &evt_handler_list ); 342 spin_unlock_irqrestore( &evt_handler_list_lock, flags ); 343 344 cobalt_acpi_enable_event( ev_type, 1 ); 345 346 return 0; 347 } 348 349 extern int cobalt_acpi_unregister_evt_handler( cobalt_acpi_evt_handler handler ) 350 { 351 struct list_head *pos; 352 unsigned long flags; 353 354 355 spin_lock_irqsave( &evt_handler_list_lock, flags ); 356 list_for_each( pos, &evt_handler_list ) 357 { 358 if( list_entry( pos, evt_handler_datum, link )->handler == handler ) 359 { 360 list_del( pos ); 361 spin_unlock_irqrestore( &evt_handler_list_lock, flags ); 362 363 cobalt_acpi_enable_event( list_entry( pos, 364 evt_handler_datum, 365 link )->ev_type, 0 ); 366 367 kfree( list_entry( pos, evt_handler_datum, link ) ); 368 return 0; 369 } 370 371 }; 372 373 spin_unlock_irqrestore( &evt_handler_list_lock, flags ); 374 return -EINVAL; 375 } 376 377 static void cobalt_acpi_enable_event( u16 ev_type, int en ) 378 { 379 if( ev_type >= 0x8000 ) 380 { 381 struct list_head *pos; 382 trans_table_datum *d; 383 int i; 384 unsigned long flags; 385 386 spin_lock_irqsave( &trans_table_list_lock, flags ); 387 list_for_each( pos, &trans_table_list ) 388 { 389 d = list_entry( pos, trans_table_datum, link ); 390 for( i=0 ; i<d->table_len ; i++ ) 391 { 392 if( d->table[i] == ev_type ) 393 { 394 cobalt_acpi_run_enable_handler( d->hw_type, 395 COBALT_ACPI_EVT_GPE, 396 i, en ); 397 } 398 } 399 } 400 spin_unlock_irqrestore( &trans_table_list_lock, flags ); 401 } 402 else 403 cobalt_acpi_run_enable_handler( COBALT_ACPI_HW_ANY, ev_type, 0, en); 404 } 405 406 static void cobalt_acpi_run_enable_handler( u16 hw_type, u16 ev_type, 407 u16 ev_data, int en) 408 { 409 struct list_head *pos; 410 unsigned long flags; 411 hw_handler_datum *d; 412 413 spin_lock_irqsave(&hw_handler_list_lock, flags); 414 list_for_each( pos, &hw_handler_list ) 415 { 416 d = list_entry( pos, hw_handler_datum, link ); 417 if( (!hw_type) || (d->hw_type == hw_type) ) 418 d->en_handler( ev_type, ev_data, en, d->data ); 419 } 420 spin_unlock_irqrestore(&hw_handler_list_lock, flags); 421 422 } 423 424 static int cobalt_acpi_translate_event( cobalt_acpi_evt *evt ) 425 { 426 struct list_head *pos; 427 unsigned long flags; 428 trans_table_datum *d; 429 430 if( evt->ev_type != COBALT_ACPI_EVT_GPE ) 431 return 0; 432 433 spin_lock_irqsave( &trans_table_list_lock, flags ); 434 list_for_each( pos, &trans_table_list ) 435 { 436 d = list_entry( pos, trans_table_datum, link ); 437 if( d->hw_type == evt->hw_type ) 438 { 439 if( evt->ev_data >= d->table_len ) 440 goto err_out; 441 442 if( d->table[ evt->ev_data ] != COBALT_ACPI_EVT_NONE ) 443 { 444 evt->ev_type = d->table[ evt->ev_data ]; 445 evt->ev_data = 0; 446 } 447 448 spin_unlock_irqrestore( &trans_table_list_lock, flags ); 449 return 0; 450 } 451 } 452 453 err_out: 454 spin_unlock_irqrestore( &trans_table_list_lock, flags ); 455 return -1; 456 } 457 458 extern int cobalt_acpi_post_event( cobalt_acpi_evt evt ) 459 { 460 evt_list_datum *d; 461 unsigned long flags; 462 463 if( ! (d = (evt_list_datum *) kmalloc( sizeof( evt_handler_datum ), GFP_ATOMIC )) ) 464 return -ENOMEM; 465 466 467 cobalt_acpi_translate_event( &evt ); 468 469 memcpy( &(d->evt), &evt, sizeof(evt) ); 470 471 spin_lock_irqsave( &dispatch_queue_lock, flags ); 472 list_add_tail( &(d->link), &dispatch_queue ); 473 spin_unlock_irqrestore( &dispatch_queue_lock, flags ); 474 475 return 0; 476 } 477 478 static int cobalt_acpi_apply_evt_handlers( evt_list_datum *d ) 479 { 480 struct list_head *pos; 481 evt_handler_datum *evt_h; 482 int ret,err = 0; 483 unsigned long flags; 484 485 spin_lock_irqsave( &evt_handler_list_lock, flags ); 486 list_for_each( pos, &evt_handler_list ) 487 { 488 evt_h = list_entry( pos, evt_handler_datum, link ); 489 if( (! evt_h->ev_type) || (evt_h->ev_type == d->evt.ev_type) ) 490 { 491 if( (ret = evt_h->handler( &d->evt, evt_h->data )) < 0 ) 492 err = ret; 493 } 494 } 495 spin_unlock_irqrestore( &evt_handler_list_lock, flags ); 496 497 return err; 498 } 499 500 static int cobalt_acpi_run_dispatch_queue( void ) 501 { 502 struct list_head *pos; 503 int ret; 504 int err=0; 505 evt_list_datum *d; 506 unsigned long flags; 507 508 spin_lock_irqsave( &dispatch_queue_lock, flags ); 509 while( (pos = list_pop( &dispatch_queue )) ) 510 { 511 d = list_entry( pos, evt_list_datum, link ); 512 if( (ret = cobalt_acpi_apply_evt_handlers( d )) < 0 ) 513 err = ret; 514 #ifdef CONFIG_COBALT_EMU_ACPI 515 cobalt_acpi_generate_proc_evt( &d->evt ); 516 #endif 517 kfree( d ); 518 } 519 spin_unlock_irqrestore( &dispatch_queue_lock, flags ); 520 521 return err; 522 } 523 524 static irqreturn_t acpi_interrupt(int irq, void *dev_id, struct pt_regs *regs) 525 { 526 struct list_head *pos; 527 hw_handler_datum *d; 528 int ret=0, err=0; 529 unsigned long flags; 530 531 spin_lock_irqsave(&hw_handler_list_lock, flags); 532 list_for_each( pos, &hw_handler_list ) 533 { 534 d = list_entry( pos, hw_handler_datum, link ); 535 if( (ret = d->hw_handler( irq, dev_id, regs, d->data )) < 0 ) 536 err = ret; 537 538 } 539 spin_unlock_irqrestore(&hw_handler_list_lock, flags); 540 541 if( (err = cobalt_acpi_run_dispatch_queue()) < 0 ) 542 err = ret; 543 544 if( err ) 545 EPRINTK( "error at interrupt time of type %d.\n", err ); 546 547 return IRQ_HANDLED; 548 } 549 550 551 552 553 int __init cobalt_acpi_init(void) 554 { 555 int err; 556 557 printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", ACPI_DRIVER,ACPI_DRIVER_VMAJ,ACPI_DRIVER_VMIN); 558 559 if( cobt_is_monterey() ) 560 cobalt_acpi_monterey_init(); 561 else if( cobt_is_alpine() ) 562 cobalt_acpi_alpine_init(); 563 564 if( cobt_is_5k() ) 565 { 566 if( pci_find_device(PCI_VENDOR_ID_SERVERWORKS, 567 PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL ) ) 568 { 569 if( (err = cobalt_acpi_osb4_init()) < 0 ) 570 { 571 goto cleanup; 572 } 573 } 574 575 if( pci_find_device(PCI_VENDOR_ID_SERVERWORKS, 576 PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL ) ) 577 { 578 if( (err = cobalt_acpi_csb5_init()) < 0 ) 579 { 580 goto cleanup; 581 } 582 } 583 584 switch( superio_type() ) 585 { 586 case SIO_TYPE_PC8731X: 587 if( (err = cobalt_acpi_pc8731x_init()) ) 588 { 589 goto cleanup; 590 } 591 break; 592 593 case SIO_TYPE_PC8741X: 594 if( (err = cobalt_acpi_pc8741x_init()) ) 595 { 596 goto cleanup; 597 } 598 break; 599 600 case SIO_TYPE_UNKNOWN: 601 EPRINTK("unknown superio type\n"); 602 break; 603 } 604 605 /* setup an interrupt handler for an ACPI SCI */ 606 err = request_irq(ACPI_IRQ, acpi_interrupt, 607 SA_SHIRQ, ACPI_NAME, (void *)ACPI_MAGIC); 608 if (err) { 609 EPRINTK("can't assign ACPI IRQ (%d)\n", ACPI_IRQ); 610 return err; 611 } 612 613 #ifdef CONFIG_COBALT_EMU_ACPI 614 cobalt_acpi_setup_proc(); 615 #endif 616 } 617 618 /* enable some events we may want */ 619 cobalt_acpi_enable_event( COBALT_ACPI_EVT_PWRBTN, 1 ); 620 621 return 0; 622 623 cleanup: 624 cobalt_acpi_cleanup(); 625 return err; 626 } 627 628 static void cobalt_acpi_cleanup( void ) 629 { 630 cobalt_acpi_osb4_cleanup(); 631 cobalt_acpi_csb5_cleanup(); 632 cobalt_acpi_pc8731x_cleanup(); 633 cobalt_acpi_pc8741x_cleanup(); 634 635 if( cobt_is_monterey() ) 636 cobalt_acpi_monterey_cleanup(); 637 if( cobt_is_alpine() ) 638 cobalt_acpi_alpine_cleanup(); 639 } 640 641 /* 642 * 643 * Generic ACPI HW Support 644 * 645 */ 646 647 static __inline__ char *region_name( char * subsys_name, char * blk_name ) 648 { 649 char * new_name; 650 651 if( !( new_name = (char *) kmalloc( strlen(subsys_name) + strlen(blk_name) + 14, 652 GFP_ATOMIC)) ) 653 return NULL; 654 655 sprintf( new_name, "%s (%s)", subsys_name, blk_name ); 656 return new_name; 657 } 658 659 static void free_region_names( generic_acpi_regions *regions ) 660 { 661 if( regions->pm1a_evt_nam ) 662 kfree( regions->pm1a_evt_nam ); 663 664 if( regions->pm1b_evt_nam ) 665 kfree( regions->pm1b_evt_nam ); 666 667 if( regions->pm1a_cnt_nam ) 668 kfree( regions->pm1a_cnt_nam ); 669 670 if( regions->pm1b_cnt_nam ) 671 kfree( regions->pm1b_cnt_nam ); 672 673 if( regions->pm2_cnt_nam ) 674 kfree( regions->pm2_cnt_nam ); 675 676 if( regions->pm_tmr_nam ) 677 kfree( regions->pm_tmr_nam ); 678 679 if( regions->p_nam ) 680 kfree( regions->p_nam ); 681 682 if( regions->gpe0_nam ) 683 kfree( regions->gpe0_nam ); 684 685 if( regions->gpe1_nam ) 686 kfree( regions->gpe1_nam ); 687 } 688 689 static int register_acpi_regions( generic_acpi_regions *regions, char * subsys_name ) 690 { 691 int i; 692 693 if( regions->pm1a_evt_blk && regions->pm1_evt_len ) 694 { 695 if( !(regions->pm1a_evt_nam = region_name( subsys_name, "pm1a_evt_blk" )) ) 696 goto cleanup0; 697 698 if( !request_region( regions->pm1a_evt_blk, regions->pm1_evt_len, 699 regions->pm1a_evt_nam ) ) 700 goto cleanup0; 701 } 702 703 if( regions->pm1b_evt_blk && regions->pm1_evt_len ) 704 { 705 if( !(regions->pm1b_evt_nam = region_name( subsys_name, "pm1b_evt_blk" )) ) 706 goto cleanup0; 707 708 if( !request_region( regions->pm1b_evt_blk, regions->pm1_evt_len, 709 regions->pm1b_evt_nam) ) 710 goto cleanup1; 711 } 712 713 if( regions->pm1a_cnt_blk && regions->pm1_cnt_len ) 714 { 715 if( !(regions->pm1a_cnt_nam = region_name( subsys_name, "pm1a_cnt_blk" )) ) 716 goto cleanup1; 717 718 if( !request_region( regions->pm1a_cnt_blk, regions->pm1_cnt_len, 719 regions->pm1a_cnt_nam ) ) 720 goto cleanup2; 721 } 722 723 if( regions->pm1b_cnt_blk && regions->pm1_cnt_len ) 724 { 725 if( !(regions->pm1b_cnt_nam = region_name( subsys_name, "pm1b_cnt_blk" )) ) 726 goto cleanup2; 727 728 if( !request_region( regions->pm1b_cnt_blk, regions->pm1_cnt_len, 729 regions->pm1b_cnt_nam ) ) 730 goto cleanup3; 731 } 732 733 if( regions->pm2_cnt_blk && regions->pm2_cnt_len ) 734 { 735 if( !(regions->pm2_cnt_nam = region_name( subsys_name, "pm2_cnt_blk" )) ) 736 goto cleanup3; 737 738 if( !request_region( regions->pm2_cnt_blk, regions->pm2_cnt_len, 739 regions->pm2_cnt_nam ) ) 740 goto cleanup4; 741 } 742 743 if( regions->pm_tmr_blk && regions->pm_tmr_len ) 744 { 745 if( !(regions->pm_tmr_nam = region_name( subsys_name, "pm_tmp_blk" )) ) 746 goto cleanup4; 747 748 if( !request_region( regions->pm_tmr_blk, regions->pm_tmr_len, 749 regions->pm_tmr_nam ) ) 750 goto cleanup5; 751 } 752 753 if( regions->p_blk ) 754 { 755 if( !(regions->p_nam = region_name( subsys_name, "p_blk" )) ) 756 goto cleanup5; 757 758 if( !request_region( regions->p_blk, 6, regions->p_nam ) ) 759 goto cleanup6; 760 } 761 762 if( regions->gpe0_blk && regions->gpe0_len ) 763 { 764 if( !(regions->gpe0_nam = region_name( subsys_name, "gpe0_blk" )) ) 765 goto cleanup6; 766 767 if( !request_region( regions->gpe0_blk, regions->gpe0_len, 768 regions->gpe0_nam ) ) 769 goto cleanup7; 770 } 771 772 if( regions->gpe1_blk && regions->gpe1_len ) 773 { 774 if( !(regions->gpe1_nam = region_name( subsys_name, "gpe1_blk" )) ) 775 goto cleanup7; 776 777 if( !request_region( regions->gpe1_blk, regions->gpe1_len, 778 regions->gpe1_nam ) ) 779 goto cleanup8; 780 } 781 782 if( (regions->gpe_ref_cnt = (atomic_t *) kmalloc( sizeof( atomic_t ) * 783 regions->gpe0_len * 8, 784 GFP_ATOMIC)) == NULL ) 785 goto cleanup9; 786 787 memset( regions->gpe_ref_cnt, 0x0, sizeof( atomic_t ) * regions->gpe0_len * 8 ); 788 789 /* disable all events and ack them */ 790 if( regions->pm1a_evt_blk ) 791 { 792 outw( 0x0000, regions->pm1a_evt_blk + regions->pm1_evt_len/2 ); 793 outw( 0xffff, regions->pm1a_evt_blk ); 794 } 795 796 if( regions->pm1b_evt_blk ) 797 { 798 outw( 0x0000, regions->pm1b_evt_blk + regions->pm1_evt_len/2 ); 799 outw( 0xffff, regions->pm1b_evt_blk ); 800 } 801 802 if( regions->gpe0_blk ) 803 { 804 for( i=0 ; i<(regions->gpe0_len/2) ; i++ ) 805 { 806 outb( 0x00, regions->gpe0_blk + regions->gpe0_len/2 + i ); 807 outb( 0xff, regions->gpe0_blk + i ); 808 } 809 } 810 811 if( regions->gpe1_blk ) 812 { 813 for( i=0 ; i<(regions->gpe1_len/2) ; i++ ) 814 { 815 outb( 0x00, regions->gpe1_blk + regions->gpe1_len/2 + i ); 816 outb( 0xff, regions->gpe1_blk + i ); 817 } 818 } 819 820 return 0; 821 822 cleanup9: 823 if( regions->gpe1_blk ) 824 { 825 release_region( regions->gpe1_blk, regions->gpe1_len ); 826 regions->gpe1_blk = 0; 827 } 828 829 cleanup8: 830 if( regions->gpe0_blk ) 831 { 832 release_region( regions->gpe0_blk, regions->gpe0_len ); 833 regions->gpe0_blk = 0; 834 } 835 836 cleanup7: 837 if( regions->p_blk ) 838 { 839 release_region( regions->p_blk, 6 ); 840 regions->p_blk = 0; 841 } 842 843 cleanup6: 844 if( regions->pm_tmr_blk ) 845 { 846 release_region( regions->pm_tmr_blk, regions->pm_tmr_len ); 847 regions->pm_tmr_blk = 0; 848 } 849 850 cleanup5: 851 if( regions->pm2_cnt_blk ) 852 { 853 release_region( regions->pm2_cnt_blk, regions->pm2_cnt_len ); 854 regions->pm2_cnt_blk = 0; 855 } 856 857 cleanup4: 858 if( regions->pm1b_cnt_blk ) 859 { 860 release_region( regions->pm1b_cnt_blk, regions->pm1_cnt_len ); 861 regions->pm1b_cnt_blk = 0; 862 } 863 864 cleanup3: 865 if( regions->pm1a_cnt_blk ) 866 { 867 release_region( regions->pm1a_cnt_blk, regions->pm1_cnt_len ); 868 regions->pm1a_cnt_blk = 0; 869 } 870 871 cleanup2: 872 if( regions->pm1b_evt_blk ) 873 { 874 release_region( regions->pm1b_evt_blk, regions->pm1_evt_len ); 875 regions->pm1b_evt_blk = 0; 876 } 877 878 cleanup1: 879 if( regions->pm1a_evt_blk ) 880 { 881 release_region( regions->pm1a_evt_blk, regions->pm1_evt_len ); 882 regions->pm1a_evt_blk = 0; 883 } 884 885 cleanup0: 886 free_region_names( regions ); 887 888 return -EBUSY; 889 } 890 891 static int unregister_acpi_regions( generic_acpi_regions *regions ) 892 { 893 if( regions->pm1a_evt_blk && regions->pm1_evt_len ) 894 { 895 release_region( regions->pm1a_evt_blk, regions->pm1_evt_len ); 896 regions->pm1a_evt_blk = 0; 897 } 898 899 if( regions->pm1b_evt_blk && regions->pm1_evt_len ) 900 { 901 release_region( regions->pm1b_evt_blk, regions->pm1_evt_len ); 902 regions->pm1b_evt_blk = 0; 903 } 904 905 if( regions->pm1a_cnt_blk && regions->pm1_cnt_len ) 906 { 907 release_region( regions->pm1a_cnt_blk, regions->pm1_cnt_len ); 908 regions->pm1a_cnt_blk = 0; 909 } 910 911 if( regions->pm1b_cnt_blk && regions->pm1_cnt_len ) 912 { 913 release_region( regions->pm1b_cnt_blk, regions->pm1_cnt_len ); 914 regions->pm1b_cnt_blk = 0; 915 } 916 917 if( regions->pm2_cnt_blk && regions->pm2_cnt_len ) 918 { 919 release_region( regions->pm2_cnt_blk, regions->pm2_cnt_len ); 920 regions->pm2_cnt_blk = 0; 921 } 922 923 if( regions->pm_tmr_blk && regions->pm_tmr_len ) 924 { 925 release_region( regions->pm_tmr_blk, regions->pm_tmr_len ); 926 regions->pm_tmr_blk = 0; 927 } 928 929 if( regions->p_blk ) 930 { 931 release_region( regions->p_blk, 6 ); 932 regions->p_blk = 0; 933 } 934 935 if( regions->gpe0_blk && regions->gpe0_len ) 936 { 937 release_region( regions->gpe0_blk, regions->gpe0_len ); 938 regions->gpe0_blk = 0; 939 } 940 941 if( regions->gpe1_blk && regions->gpe1_len ) 942 { 943 release_region( regions->gpe1_blk, regions->gpe1_len ); 944 regions->gpe1_blk = 0; 945 } 946 947 if( regions->gpe_ref_cnt ) 948 kfree( regions->gpe_ref_cnt ); 949 950 free_region_names( regions ); 951 952 return 0; 953 } 954 955 static void cobalt_acpi_handle_pm1_blk( u16 io_addr, u16 len, 956 generic_acpi_regions * regions ) 957 { 958 cobalt_acpi_evt evt; 959 u16 sts, en; 960 961 evt.hw_type = regions->hw_type; 962 963 if( (sts = inw( io_addr )) && 964 (en = inw( io_addr + len/2 )) ) 965 { 966 967 968 /* clear status bits */ 969 outw( sts, io_addr); 970 971 if( (en & GEN_ACPI_TMR_STS) && 972 (sts & GEN_ACPI_TMR_STS) ) 973 { 974 evt.ev_type = COBALT_ACPI_EVT_TMR; 975 evt.ev_data = 0x0; 976 cobalt_acpi_post_event( evt ); 977 } 978 if( (en & GEN_ACPI_BM_STS) && 979 (sts & GEN_ACPI_BM_STS) ) 980 { 981 evt.ev_type = COBALT_ACPI_EVT_BM; 982 evt.ev_data = 0x0; 983 cobalt_acpi_post_event( evt ); 984 } 985 if( (en & GEN_ACPI_GBL_STS) && 986 (sts & GEN_ACPI_GBL_STS) ) 987 { 988 evt.ev_type = COBALT_ACPI_EVT_GBL; 989 evt.ev_data = 0x0; 990 cobalt_acpi_post_event( evt ); 991 } 992 if( (en & GEN_ACPI_PWRBTN_STS) && 993 (sts & GEN_ACPI_PWRBTN_STS) ) 994 { 995 evt.ev_type = COBALT_ACPI_EVT_PWRBTN; 996 evt.ev_data = 0x0; 997 cobalt_acpi_post_event( evt ); 998 } 999 if( (en & GEN_ACPI_SLPBTN_STS) && 1000 (sts & GEN_ACPI_SLPBTN_STS) ) 1001 { 1002 evt.ev_type = COBALT_ACPI_EVT_SLPBTN; 1003 evt.ev_data = 0x0; 1004 cobalt_acpi_post_event( evt ); 1005 } 1006 if( (en & GEN_ACPI_RTC_STS) && 1007 (sts & GEN_ACPI_RTC_STS) ) 1008 { 1009 evt.ev_type = COBALT_ACPI_EVT_RTC; 1010 evt.ev_data = 0x0; 1011 cobalt_acpi_post_event( evt ); 1012 } 1013 if( (sts & GEN_ACPI_WAK_STS) ) 1014 { 1015 evt.ev_type = COBALT_ACPI_EVT_WAK; 1016 evt.ev_data = 0x0; 1017 cobalt_acpi_post_event( evt ); 1018 } 1019 } 1020 } 1021 1022 static void cobalt_acpi_handle_gpe_blk( u16 io_addr, u16 len, 1023 generic_acpi_regions * regions ) 1024 { 1025 cobalt_acpi_evt evt; 1026 int i,j; 1027 u8 sts, en; 1028 1029 evt.hw_type = regions->hw_type; 1030 evt.ev_type = COBALT_ACPI_EVT_GPE; 1031 1032 for( i=0 ; i<(len/2) ; i++ ) 1033 { 1034 sts = inb( io_addr + i ); 1035 en = inb( io_addr + len/2 + i ); 1036 1037 /* clear status bits */ 1038 outb( sts, io_addr); 1039 1040 for( j=0 ; j<8 ; j++ ) 1041 { 1042 if( (en & 0x1) && 1043 (sts & 0x1) ) 1044 { 1045 evt.ev_data = i*8 + j; 1046 cobalt_acpi_post_event( evt ); 1047 } 1048 en >>= 1; 1049 sts >>= 1; 1050 } 1051 } 1052 } 1053 1054 static int cobalt_acpi_generic_hw_handler( int irq, void *dev_id, 1055 struct pt_regs *regs, void * data ) 1056 { 1057 generic_acpi_regions * regions = (generic_acpi_regions *) data; 1058 cobalt_acpi_evt evt; 1059 1060 evt.hw_type = regions->hw_type; 1061 1062 /* various PM events */ 1063 if( regions->pm1a_evt_blk ) 1064 cobalt_acpi_handle_pm1_blk( regions->pm1a_evt_blk, regions->pm1_evt_len, regions ); 1065 1066 if( regions->pm1b_evt_blk ) 1067 cobalt_acpi_handle_pm1_blk( regions->pm1b_evt_blk, regions->pm1_evt_len, regions ); 1068 1069 if( regions->gpe0_blk ) 1070 cobalt_acpi_handle_gpe_blk( regions->gpe0_blk, regions->gpe0_len, regions ); 1071 1072 if( regions->gpe1_blk ) 1073 cobalt_acpi_handle_gpe_blk( regions->gpe1_blk, regions->gpe1_len, regions ); 1074 1075 1076 return 0; 1077 } 1078 1079 static int cobalt_acpi_generic_en_handler( u16 ev_type, u16 ev_data, int en, void *data ) 1080 { 1081 generic_acpi_regions * regions = (generic_acpi_regions *) data; 1082 int block, offset; 1083 u8 data8; 1084 u16 data16; 1085 1086 switch( ev_type ) 1087 { 1088 case COBALT_ACPI_EVT_TMR: 1089 data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); 1090 1091 if( en ) 1092 { 1093 data16 |= GEN_ACPI_TMR_STS; 1094 atomic_inc( ®ions->tmr_ref_cnt ); 1095 } 1096 else 1097 { 1098 if( atomic_dec_and_test( ®ions->tmr_ref_cnt ) ) 1099 data16 &= ~GEN_ACPI_TMR_STS; 1100 } 1101 outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); 1102 break; 1103 1104 case COBALT_ACPI_EVT_BM: 1105 data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); 1106 1107 if( en ) 1108 { 1109 data16 |= GEN_ACPI_BM_STS; 1110 atomic_inc( ®ions->bm_ref_cnt ); 1111 } 1112 else 1113 { 1114 if( atomic_dec_and_test( ®ions->bm_ref_cnt ) ) 1115 data16 &= ~GEN_ACPI_BM_STS; 1116 } 1117 outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); 1118 break; 1119 1120 case COBALT_ACPI_EVT_GBL: 1121 data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); 1122 1123 if( en ) 1124 { 1125 data16 |= GEN_ACPI_GBL_STS; 1126 atomic_inc( ®ions->gbl_ref_cnt ); 1127 } 1128 else 1129 { 1130 if( atomic_dec_and_test( ®ions->gbl_ref_cnt ) ) 1131 data16 &= ~GEN_ACPI_GBL_STS; 1132 } 1133 outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); 1134 break; 1135 1136 case COBALT_ACPI_EVT_PWRBTN: 1137 data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); 1138 1139 if( en ) 1140 { 1141 data16 |= GEN_ACPI_PWRBTN_STS; 1142 atomic_inc( ®ions->pwrbtn_ref_cnt ); 1143 } 1144 else 1145 { 1146 if( atomic_dec_and_test( ®ions->pwrbtn_ref_cnt ) ) 1147 data16 &= ~GEN_ACPI_PWRBTN_STS; 1148 } 1149 outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); 1150 break; 1151 1152 case COBALT_ACPI_EVT_SLPBTN: 1153 data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); 1154 1155 if( en ) 1156 { 1157 data16 |= GEN_ACPI_SLPBTN_STS; 1158 atomic_inc( ®ions->slpbtn_ref_cnt ); 1159 } 1160 else 1161 { 1162 if( atomic_dec_and_test( ®ions->slpbtn_ref_cnt ) ) 1163 data16 &= ~GEN_ACPI_SLPBTN_STS; 1164 } 1165 outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); 1166 break; 1167 1168 case COBALT_ACPI_EVT_RTC: 1169 data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); 1170 1171 if( en ) 1172 { 1173 data16 |= GEN_ACPI_RTC_STS; 1174 atomic_inc( ®ions->rtc_ref_cnt ); 1175 } 1176 else 1177 { 1178 if( atomic_dec_and_test( ®ions->rtc_ref_cnt ) ) 1179 data16 &= ~GEN_ACPI_RTC_STS; 1180 } 1181 outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); 1182 break; 1183 1184 case COBALT_ACPI_EVT_WAK: 1185 data16 = inw( regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); 1186 1187 if( en ) 1188 { 1189 data16 |= GEN_ACPI_WAK_STS; 1190 atomic_inc( ®ions->wak_ref_cnt ); 1191 } 1192 else 1193 { 1194 if( atomic_dec_and_test( ®ions->wak_ref_cnt ) ) 1195 data16 &= ~GEN_ACPI_WAK_STS; 1196 } 1197 outw( data16, regions->pm1a_evt_blk + (regions->pm1_evt_len / 2) ); 1198 break; 1199 1200 case COBALT_ACPI_EVT_GPE: 1201 if( (ev_data/8) >= (regions->gpe0_len / 2) ) 1202 return -EINVAL; 1203 1204 block = ev_data / 8; 1205 offset = ev_data % 8; 1206 1207 data8 = inb( regions->gpe0_blk + (regions->gpe0_len / 2) + block ); 1208 1209 if( en ) 1210 { 1211 data8 |= 0x1 << offset; 1212 atomic_inc( ®ions->gpe_ref_cnt[ev_data] ); 1213 } 1214 else 1215 { 1216 if( atomic_dec_and_test( ®ions->gpe_ref_cnt[ev_data] ) ) 1217 data8 &= ~( 0x1 << offset ); 1218 } 1219 1220 outb( data8, regions->gpe0_blk + (regions->gpe0_len / 2) + block ); 1221 1222 break; 1223 1224 default: 1225 return -EINVAL; 1226 1227 } 1228 1229 return 0; 1230 } 1231 1232 /* 1233 * 1234 * Generic ServerWorks region code 1235 * 1236 */ 1237 1238 static int get_serverworks_regions( generic_acpi_regions *regions, u16 type ) 1239 { 1240 int reg; 1241 1242 memset( regions, 0x0, sizeof( *regions ) ); 1243 1244 regions->hw_type = type; 1245 1246 regions->pm1_evt_len = 4; 1247 regions->pm1_cnt_len = 2; 1248 regions->pm_tmr_len = 4; 1249 regions->gpe0_len = 8; 1250 1251 if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x20)) ) 1252 regions->pm1a_evt_blk = (u16) reg; 1253 1254 if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x22)) ) 1255 regions->pm1a_cnt_blk = (u16) reg; 1256 1257 if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x24)) ) 1258 regions->pm_tmr_blk = (u16) reg; 1259 1260 if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x26)) ) 1261 regions->p_blk = (u16) reg; 1262 1263 if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x28)) ) 1264 regions->gpe0_blk = (u16) reg; 1265 1266 if( type == COBALT_ACPI_HW_OSB4 ) 1267 { 1268 regions->pm2_cnt_len = 1; 1269 if( (reg = get_reg(OSB4_INDEX_PORT, OSB4_DATA_PORT, 0x2E)) ) 1270 regions->pm2_cnt_blk = (u16) reg; 1271 } 1272 1273 switch( type ) 1274 { 1275 case COBALT_ACPI_HW_OSB4: 1276 return register_acpi_regions( regions, "OSB4" ); 1277 1278 case COBALT_ACPI_HW_CSB5: 1279 return register_acpi_regions( regions, "CSB5" ); 1280 } 1281 1282 return -EINVAL; 1283 1284 } 1285 1286 /* 1287 * 1288 * ServerWorks OSB4 1289 * 1290 */ 1291 1292 static generic_acpi_regions osb4_regions; 1293 1294 static int cobalt_acpi_osb4_init( void ) 1295 { 1296 int err; 1297 1298 if( (err = get_osb4_regions( &osb4_regions )) < 0 ) 1299 return err; 1300 1301 if( (err = cobalt_acpi_register_hw_handler( COBALT_ACPI_HW_OSB4, 1302 cobalt_acpi_generic_hw_handler, 1303 cobalt_acpi_generic_en_handler, 1304 &osb4_regions )) < 0 ) 1305 return err; 1306 1307 return 0; 1308 } 1309 1310 static int cobalt_acpi_osb4_cleanup( void ) 1311 { 1312 unregister_acpi_regions( &osb4_regions ); 1313 return 0; 1314 } 1315 1316 static int get_osb4_regions( generic_acpi_regions *regions) 1317 { 1318 return get_serverworks_regions( regions, COBALT_ACPI_HW_OSB4 ); 1319 } 1320 1321 /* 1322 * 1323 * ServerWorks CSB5 1324 * 1325 */ 1326 1327 /* static generic_acpi_regions csb5_regions; */ 1328 1329 static generic_acpi_regions csb5_regions; 1330 1331 static int cobalt_acpi_csb5_init( void ) 1332 { 1333 int err; 1334 1335 if( (err = get_csb5_regions( &csb5_regions )) < 0 ) 1336 return err; 1337 1338 if( (err = cobalt_acpi_register_hw_handler( COBALT_ACPI_HW_CSB5, 1339 cobalt_acpi_generic_hw_handler, 1340 cobalt_acpi_generic_en_handler, 1341 &csb5_regions )) < 0 ) 1342 return err; 1343 1344 return 0; 1345 } 1346 1347 static int cobalt_acpi_csb5_cleanup( void ) 1348 { 1349 unregister_acpi_regions( &csb5_regions ); 1350 return 0; 1351 } 1352 1353 static int get_csb5_regions( generic_acpi_regions *regions) 1354 { 1355 return get_serverworks_regions( regions, COBALT_ACPI_HW_CSB5 ); 1356 } 1357 1358 /* 1359 * 1360 * NatSemi PC8731x 1361 * 1362 */ 1363 static generic_acpi_regions pc8731x_regions; 1364 1365 static int cobalt_acpi_pc8731x_init( void ) 1366 { 1367 int err; 1368 1369 if( (err = get_pc8731x_regions( &pc8731x_regions )) < 0 ) 1370 return err; 1371 1372 if( (err = cobalt_acpi_register_hw_handler( COBALT_ACPI_HW_PC8731X, 1373 cobalt_acpi_generic_hw_handler, 1374 cobalt_acpi_generic_en_handler, 1375 &pc8731x_regions )) < 0 ) 1376 return err; 1377 1378 return 0; 1379 } 1380 1381 static int cobalt_acpi_pc8731x_cleanup( void ) 1382 { 1383 unregister_acpi_regions( &pc8731x_regions ); 1384 return 0; 1385 } 1386 1387 static int get_pc8731x_regions( generic_acpi_regions *regions ) 1388 { 1389 int reg; 1390 u16 addr; 1391 1392 memset( regions, 0x0, sizeof( *regions ) ); 1393 1394 regions->hw_type = COBALT_ACPI_HW_PC8731X; 1395 1396 regions->pm1_evt_len = 4; 1397 regions->pm1_cnt_len = 2; 1398 regions->pm_tmr_len = 4; 1399 regions->gpe0_len = 4; 1400 1401 /* superi/o -- select pm logical device and get base address */ 1402 addr = superio_ldev_base(PC87317_DEV_PM); 1403 if( addr ) 1404 { 1405 /* get registers */ 1406 if( (reg = get_reg(addr, addr + 1, 0x08)) ) 1407 regions->pm1a_evt_blk = reg; 1408 1409 if( (reg = get_reg(addr, addr + 1, 0x0a)) ) 1410 regions->pm_tmr_blk = reg; 1411 1412 if( (reg = get_reg(addr, addr + 1, 0x0c)) ) 1413 regions->pm1a_cnt_blk = reg; 1414 1415 if( (reg = get_reg(addr, addr + 1, 0x0e)) ) 1416 regions->gpe0_blk = reg; 1417 } 1418 1419 return register_acpi_regions( regions, "pc8731x" ); 1420 } 1421 1422 /* 1423 * 1424 * NatSemi PC8741x 1425 * 1426 */ 1427 1428 static generic_acpi_regions pc8741x_regions; 1429 1430 static int cobalt_acpi_pc8741x_init( void ) 1431 { 1432 int err; 1433 1434 if( (err = get_pc8741x_regions( &pc8741x_regions )) < 0 ) 1435 return err; 1436 1437 if( (err = cobalt_acpi_register_hw_handler( COBALT_ACPI_HW_PC8741X, 1438 cobalt_acpi_generic_hw_handler, 1439 cobalt_acpi_generic_en_handler, 1440 &pc8741x_regions )) < 0 ) 1441 return err; 1442 1443 return 0; 1444 } 1445 1446 static int cobalt_acpi_pc8741x_cleanup( void ) 1447 { 1448 unregister_acpi_regions( &pc8741x_regions ); 1449 return 0; 1450 } 1451 1452 static int get_pc8741x_regions( generic_acpi_regions *regions ) 1453 { 1454 int reg; 1455 1456 memset( regions, 0x0, sizeof( *regions ) ); 1457 1458 regions->hw_type = COBALT_ACPI_HW_PC8741X; 1459 1460 regions->pm1_evt_len = 4; 1461 regions->pm1_cnt_len = 2; 1462 regions->pm_tmr_len = 4; 1463 regions->gpe0_len = 8; 1464 1465 /* get registers */ 1466 if( (reg = superio_ldev_base_n(PC87417_DEV_SWC, 1)) ) 1467 regions->pm1a_evt_blk = reg; 1468 1469 if( (reg = superio_ldev_base_n(PC87417_DEV_SWC, 2)) ) 1470 regions->pm1a_cnt_blk = reg; 1471 1472 if( (reg = superio_ldev_base_n(PC87417_DEV_SWC, 3)) ) 1473 regions->gpe0_blk = reg; 1474 1475 return register_acpi_regions( regions, "pc8741x" ); 1476 } 1477 1478 /* 1479 * 1480 * Platform support 1481 * 1482 */ 1483 1484 /* 1485 * 1486 * Monterey 1487 * 1488 */ 1489 1490 static u16 cobalt_acpi_monterey_osb4_table[] = { 1491 /* GPE 0 */ COBALT_ACPI_EVT_NONE, 1492 /* GPE 1 */ COBALT_ACPI_EVT_NONE, 1493 /* GPE 2 */ COBALT_ACPI_EVT_NONE, 1494 /* GPE 3 */ COBALT_ACPI_EVT_NONE, 1495 /* GPE 4 */ COBALT_ACPI_EVT_NONE, 1496 /* GPE 5 */ COBALT_ACPI_EVT_NONE, 1497 /* GPE 6 */ COBALT_ACPI_EVT_SLED, 1498 /* GPE 7 */ COBALT_ACPI_EVT_NONE, 1499 /* GPE 8 */ COBALT_ACPI_EVT_NONE, 1500 /* GPE 9 */ COBALT_ACPI_EVT_NONE, 1501 /* GPE 10 */ COBALT_ACPI_EVT_NONE, 1502 /* GPE 11 */ COBALT_ACPI_EVT_NONE, 1503 /* GPE 12 */ COBALT_ACPI_EVT_NONE, 1504 /* GPE 13 */ COBALT_ACPI_EVT_NONE, 1505 /* GPE 14 */ COBALT_ACPI_EVT_NONE, 1506 /* GPE 15 */ COBALT_ACPI_EVT_NONE }; 1507 1508 static u16 cobalt_acpi_monterey_superio_table[] = { 1509 /* GPE 0 */ COBALT_ACPI_EVT_NONE, 1510 /* GPE 1 */ COBALT_ACPI_EVT_NONE, 1511 /* GPE 2 */ COBALT_ACPI_EVT_NONE, 1512 /* GPE 3 */ COBALT_ACPI_EVT_NONE, 1513 /* GPE 4 */ COBALT_ACPI_EVT_NONE, 1514 /* GPE 5 */ COBALT_ACPI_EVT_NONE, 1515 /* GPE 6 */ COBALT_ACPI_EVT_NONE, 1516 /* GPE 7 */ COBALT_ACPI_EVT_NONE, 1517 /* GPE 8 */ COBALT_ACPI_EVT_NONE, 1518 /* GPE 9 */ COBALT_ACPI_EVT_NONE, 1519 /* GPE 10 */ COBALT_ACPI_EVT_NONE, 1520 /* GPE 11 */ COBALT_ACPI_EVT_NONE, 1521 /* GPE 12 */ COBALT_ACPI_EVT_NONE, 1522 /* GPE 13 */ COBALT_ACPI_EVT_NONE, 1523 /* GPE 14 */ COBALT_ACPI_EVT_NONE, 1524 /* GPE 15 */ COBALT_ACPI_EVT_NONE, 1525 /* GPE 16 */ COBALT_ACPI_EVT_NONE, 1526 /* GPE 17 */ COBALT_ACPI_EVT_NONE, 1527 /* GPE 18 */ COBALT_ACPI_EVT_NONE, 1528 /* GPE 19 */ COBALT_ACPI_EVT_NONE, 1529 /* GPE 20 */ COBALT_ACPI_EVT_NONE, 1530 /* GPE 21 */ COBALT_ACPI_EVT_NONE, 1531 /* GPE 22 */ COBALT_ACPI_EVT_NONE, 1532 /* GPE 23 */ COBALT_ACPI_EVT_NONE, 1533 /* GPE 24 */ COBALT_ACPI_EVT_NONE, 1534 /* GPE 25 */ COBALT_ACPI_EVT_NONE, 1535 /* GPE 26 */ COBALT_ACPI_EVT_NONE, 1536 /* GPE 27 */ COBALT_ACPI_EVT_NONE, 1537 /* GPE 28 */ COBALT_ACPI_EVT_NONE, 1538 /* GPE 29 */ COBALT_ACPI_EVT_NONE, 1539 /* GPE 30 */ COBALT_ACPI_EVT_NONE, 1540 /* GPE 31 */ COBALT_ACPI_EVT_NONE }; 1541 1542 static int cobalt_acpi_monterey_init( void ) 1543 { 1544 int err; 1545 1546 err = cobalt_acpi_register_trans_table( COBALT_ACPI_HW_OSB4, 1547 sizeof( cobalt_acpi_monterey_osb4_table )/sizeof( u16 ), 1548 cobalt_acpi_monterey_osb4_table ); 1549 if( err < 0 ) 1550 return err; 1551 1552 err = cobalt_acpi_register_trans_table( COBALT_ACPI_HW_PC8731X, 1553 sizeof( cobalt_acpi_monterey_superio_table )/sizeof( u16 ), 1554 cobalt_acpi_monterey_superio_table ); 1555 if( err < 0 ) 1556 return err; 1557 1558 return 0; 1559 } 1560 1561 static int cobalt_acpi_monterey_cleanup( void ) 1562 { 1563 cobalt_acpi_unregister_trans_table( COBALT_ACPI_HW_OSB4 ); 1564 cobalt_acpi_unregister_trans_table( COBALT_ACPI_HW_PC8731X ); 1565 1566 return 0; 1567 } 1568 1569 /* 1570 * 1571 * Alpine 1572 * 1573 */ 1574 1575 static u16 cobalt_acpi_alpine_csb5_table[] = { 1576 /* GPE 0 */ COBALT_ACPI_EVT_NONE, 1577 /* GPE 1 */ COBALT_ACPI_EVT_NONE, 1578 /* GPE 2 */ COBALT_ACPI_EVT_NONE, 1579 /* GPE 3 */ COBALT_ACPI_EVT_FAN, 1580 /* GPE 4 */ COBALT_ACPI_EVT_NONE, 1581 /* GPE 5 */ COBALT_ACPI_EVT_SM_INT, 1582 /* GPE 6 */ COBALT_ACPI_EVT_THERM, 1583 /* GPE 7 */ COBALT_ACPI_EVT_NONE, 1584 /* GPE 8 */ COBALT_ACPI_EVT_NONE, 1585 /* GPE 9 */ COBALT_ACPI_EVT_NONE, 1586 /* GPE 10 */ COBALT_ACPI_EVT_NONE, 1587 /* GPE 11 */ COBALT_ACPI_EVT_NONE, 1588 /* GPE 12 */ COBALT_ACPI_EVT_NONE, 1589 /* GPE 13 */ COBALT_ACPI_EVT_NONE, 1590 /* GPE 14 */ COBALT_ACPI_EVT_NONE, 1591 /* GPE 15 */ COBALT_ACPI_EVT_NONE }; 1592 1593 static u16 cobalt_acpi_alpine_superio_table[] = { 1594 /* GPE 0 */ COBALT_ACPI_EVT_NONE, 1595 /* GPE 1 */ COBALT_ACPI_EVT_NONE, 1596 /* GPE 2 */ COBALT_ACPI_EVT_NONE, 1597 /* GPE 3 */ COBALT_ACPI_EVT_NONE, 1598 /* GPE 4 */ COBALT_ACPI_EVT_NONE, 1599 /* GPE 5 */ COBALT_ACPI_EVT_NONE, 1600 /* GPE 6 */ COBALT_ACPI_EVT_NONE, 1601 /* GPE 7 */ COBALT_ACPI_EVT_NONE, 1602 /* GPE 8 */ COBALT_ACPI_EVT_NONE, 1603 /* GPE 9 */ COBALT_ACPI_EVT_NONE, 1604 /* GPE 10 */ COBALT_ACPI_EVT_NONE, 1605 /* GPE 11 */ COBALT_ACPI_EVT_NONE, 1606 /* GPE 12 */ COBALT_ACPI_EVT_NONE, 1607 /* GPE 13 */ COBALT_ACPI_EVT_NONE, 1608 /* GPE 14 */ COBALT_ACPI_EVT_NONE, 1609 /* GPE 15 */ COBALT_ACPI_EVT_NONE, 1610 /* GPE 16 */ COBALT_ACPI_EVT_NONE, 1611 /* GPE 17 */ COBALT_ACPI_EVT_NONE, 1612 /* GPE 18 */ COBALT_ACPI_EVT_NONE, 1613 /* GPE 19 */ COBALT_ACPI_EVT_NONE, 1614 /* GPE 20 */ COBALT_ACPI_EVT_NONE, 1615 /* GPE 21 */ COBALT_ACPI_EVT_NONE, 1616 /* GPE 22 */ COBALT_ACPI_EVT_NONE, 1617 /* GPE 23 */ COBALT_ACPI_EVT_NONE, 1618 /* GPE 24 */ COBALT_ACPI_EVT_NONE, 1619 /* GPE 25 */ COBALT_ACPI_EVT_NONE, 1620 /* GPE 26 */ COBALT_ACPI_EVT_NONE, 1621 /* GPE 27 */ COBALT_ACPI_EVT_NONE, 1622 /* GPE 28 */ COBALT_ACPI_EVT_NONE, 1623 /* GPE 29 */ COBALT_ACPI_EVT_NONE, 1624 /* GPE 30 */ COBALT_ACPI_EVT_NONE, 1625 /* GPE 31 */ COBALT_ACPI_EVT_NONE }; 1626 1627 static int cobalt_acpi_alpine_init( void ) 1628 { 1629 int err; 1630 1631 err = cobalt_acpi_register_trans_table( COBALT_ACPI_HW_CSB5, 1632 sizeof( cobalt_acpi_alpine_csb5_table )/sizeof( u16 ), 1633 cobalt_acpi_alpine_csb5_table ); 1634 if( err < 0 ) 1635 return err; 1636 1637 err = cobalt_acpi_register_trans_table( COBALT_ACPI_HW_PC8741X, 1638 sizeof( cobalt_acpi_alpine_superio_table )/sizeof( u16 ), 1639 cobalt_acpi_alpine_superio_table ); 1640 if( err < 0 ) 1641 return err; 1642 1643 return 0; 1644 } 1645 1646 static int cobalt_acpi_alpine_cleanup( void ) 1647 { 1648 cobalt_acpi_unregister_trans_table( COBALT_ACPI_HW_CSB5 ); 1649 cobalt_acpi_unregister_trans_table( COBALT_ACPI_HW_PC8741X ); 1650 1651 return 0; 1652 } 1653 1654 /* 1655 * end platform support 1656 */ 1657 #ifdef CONFIG_COBALT_EMU_ACPI 1658 /* 1659 * This is all necessary because we don't have BIOS support for ACPI yet. 1660 * We can fake it here, and when full support is ready just yank this. 1661 */ 1662 typedef struct { 1663 char *device_type; 1664 char *device_instance; 1665 u32 event_type; 1666 u32 event_data; 1667 struct list_head list; 1668 } cobalt_acpi_event_t; 1669 1670 #define COBALT_ACPI_MAX_STRING_LENGTH 80 1671 1672 static LIST_HEAD(cobalt_acpi_event_list); 1673 static DECLARE_WAIT_QUEUE_HEAD(cobalt_acpi_event_wait_queue); 1674 static int event_is_open = 0; 1675 static spinlock_t cobalt_acpi_event_lock = SPIN_LOCK_UNLOCKED; 1676 1677 static struct proc_dir_entry *cobalt_acpi_proc_root; 1678 static struct proc_dir_entry *cobalt_acpi_proc_event; 1679 1680 static struct file_operations proc_event_ops = { 1681 open: cobalt_acpi_open_event, 1682 read: cobalt_acpi_read_event, 1683 release: cobalt_acpi_close_event, 1684 poll: cobalt_acpi_poll_event, 1685 }; 1686 1687 static int 1688 cobalt_acpi_setup_proc(void) 1689 { 1690 cobalt_acpi_proc_root = proc_mkdir("acpi", NULL); 1691 if (!cobalt_acpi_proc_root) { 1692 return -ENOMEM; 1693 } 1694 1695 cobalt_acpi_proc_event = create_proc_entry("event", S_IRUSR, 1696 cobalt_acpi_proc_root); 1697 if (!cobalt_acpi_proc_event) { 1698 return -ENOMEM; 1699 } 1700 1701 cobalt_acpi_proc_event->proc_fops = &proc_event_ops; 1702 1703 return 0; 1704 } 1705 1706 1707 int 1708 cobalt_acpi_generate_proc_evt( cobalt_acpi_evt * evt ) 1709 { 1710 cobalt_acpi_event_t *event = NULL, *tmp; 1711 unsigned long flags = 0; 1712 char *dev_type; 1713 char *dev_instance; 1714 u32 event_type; 1715 u32 event_data; 1716 struct list_head *pos; 1717 1718 /* drop event on the floor if no one's listening */ 1719 if (!event_is_open) 1720 return 0; 1721 1722 event_type = (evt->ev_type << 0x10) | 1723 evt->hw_type; 1724 event_data = evt->ev_data; 1725 1726 1727 /* 1728 * Check to see if an event of this type is already 1729 * pending 1730 */ 1731 spin_lock_irqsave(&cobalt_acpi_event_lock, flags); 1732 list_for_each( pos, &cobalt_acpi_event_list ) 1733 { 1734 tmp = list_entry(pos, cobalt_acpi_event_t, list); 1735 if( (tmp->event_type == event_type) && 1736 (tmp->event_data == event_data) ) 1737 { 1738 spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags); 1739 return 0; 1740 } 1741 1742 1743 } 1744 spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags); 1745 1746 1747 /* parse the event struct */ 1748 switch( evt->ev_type ) 1749 { 1750 case COBALT_ACPI_EVT_TMR: 1751 dev_type = "generic"; 1752 dev_instance = "timer"; 1753 break; 1754 1755 case COBALT_ACPI_EVT_BM: 1756 dev_type = "generic"; 1757 dev_instance = "bus-master"; 1758 break; 1759 1760 case COBALT_ACPI_EVT_GBL: 1761 dev_type = "generic"; 1762 dev_instance = "global"; 1763 break; 1764 1765 case COBALT_ACPI_EVT_PWRBTN: 1766 dev_type = "button"; 1767 dev_instance = "power"; 1768 break; 1769 1770 case COBALT_ACPI_EVT_SLPBTN: 1771 dev_type = "button"; 1772 dev_instance = "sleep"; 1773 break; 1774 1775 case COBALT_ACPI_EVT_RTC: 1776 dev_type = "generic"; 1777 dev_instance = "rtc"; 1778 break; 1779 1780 case COBALT_ACPI_EVT_WAK: 1781 dev_type = "generic"; 1782 dev_instance = "wake"; 1783 break; 1784 1785 case COBALT_ACPI_EVT_GPE: 1786 dev_type = "generic"; 1787 dev_instance = "gpe"; 1788 break; 1789 1790 case COBALT_ACPI_EVT_SLED: 1791 dev_type = "cobalt"; 1792 dev_instance = "sled"; 1793 break; 1794 1795 case COBALT_ACPI_EVT_THERM: 1796 dev_type = "cobalt"; 1797 dev_instance = "therm_trip"; 1798 break; 1799 1800 case COBALT_ACPI_EVT_FAN: 1801 dev_type = "cobalt"; 1802 dev_instance = "fan"; 1803 break; 1804 1805 case COBALT_ACPI_EVT_SM_INT: 1806 dev_type = "cobalt"; 1807 dev_instance = "sm_int"; 1808 break; 1809 1810 case COBALT_ACPI_EVT_VOLT: 1811 dev_type = "cobalt"; 1812 dev_instance = "volt_trip"; 1813 break; 1814 1815 default: 1816 dev_type = "unknown"; 1817 dev_instance = "unknown"; 1818 break; 1819 } 1820 1821 1822 /* 1823 * Allocate a new event structure. 1824 */ 1825 event = kmalloc(sizeof(*event), GFP_ATOMIC); 1826 if (!event) 1827 goto alloc_error; 1828 1829 event->device_type=NULL; 1830 event->device_instance=NULL; 1831 1832 event->device_type = kmalloc(strlen(dev_type) + sizeof(char), 1833 GFP_ATOMIC); 1834 if (!event->device_type) 1835 goto alloc_error; 1836 1837 event->device_instance = kmalloc(strlen(dev_instance) + sizeof(char), 1838 GFP_ATOMIC ); 1839 if (!event->device_instance) 1840 goto alloc_error; 1841 1842 /* 1843 * Set event data. 1844 */ 1845 strcpy(event->device_type, dev_type); 1846 strcpy(event->device_instance, dev_instance); 1847 event->event_type = event_type; 1848 event->event_data = event_data; 1849 1850 /* 1851 * Add to the end of our event list. 1852 */ 1853 spin_lock_irqsave(&cobalt_acpi_event_lock, flags); 1854 list_add_tail(&event->list, &cobalt_acpi_event_list); 1855 spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags); 1856 1857 /* 1858 * Signal waiting threads (if any). 1859 */ 1860 wake_up_interruptible(&cobalt_acpi_event_wait_queue); 1861 1862 return 0; 1863 1864 alloc_error: 1865 if(event) 1866 { 1867 if (event->device_instance) 1868 kfree(event->device_instance); 1869 1870 if (event->device_type) 1871 kfree(event->device_type); 1872 1873 kfree(event); 1874 } 1875 1876 return -ENOMEM; 1877 } 1878 1879 1880 static int 1881 cobalt_acpi_open_event(struct inode *inode, struct file *file) 1882 { 1883 unsigned long flags; 1884 spin_lock_irqsave(&cobalt_acpi_event_lock, flags); 1885 1886 if (event_is_open) 1887 goto out_busy; 1888 1889 event_is_open = 1; 1890 1891 spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags); 1892 return 0; 1893 1894 out_busy: 1895 spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags); 1896 return -EBUSY; 1897 } 1898 1899 1900 static int 1901 cobalt_acpi_close_event(struct inode *inode, struct file *file) 1902 { 1903 unsigned long flags; 1904 struct list_head *pos; 1905 cobalt_acpi_event_t *tmp; 1906 1907 spin_lock_irqsave(&cobalt_acpi_event_lock, flags); 1908 1909 while( (pos = list_pop( &cobalt_acpi_event_list )) ) 1910 { 1911 tmp = list_entry(pos, cobalt_acpi_event_t, list); 1912 if (tmp->device_instance) 1913 kfree(tmp->device_instance); 1914 1915 if (tmp->device_type) 1916 kfree(tmp->device_type); 1917 1918 kfree( tmp ); 1919 } 1920 event_is_open = 0; 1921 spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags); 1922 return 0; 1923 } 1924 1925 #define ACPI_MAX_STRING_LENGTH 80 1926 static ssize_t 1927 cobalt_acpi_read_event(struct file *file, char *buf, size_t count, loff_t *ppos) 1928 { 1929 cobalt_acpi_event_t *event = NULL; 1930 unsigned long flags = 0; 1931 static char str[ACPI_MAX_STRING_LENGTH]; 1932 static int strsize; 1933 static char *ptr; 1934 1935 if (!strsize) { 1936 DECLARE_WAITQUEUE(wait, current); 1937 1938 if (list_empty(&cobalt_acpi_event_list)) { 1939 if (file->f_flags & O_NONBLOCK) { 1940 return -EAGAIN; 1941 } 1942 set_current_state(TASK_INTERRUPTIBLE); 1943 add_wait_queue(&cobalt_acpi_event_wait_queue, &wait); 1944 1945 if (list_empty(&cobalt_acpi_event_list)) { 1946 schedule(); 1947 } 1948 1949 remove_wait_queue(&cobalt_acpi_event_wait_queue, &wait); 1950 set_current_state(TASK_RUNNING); 1951 1952 if (signal_pending(current)) { 1953 return -ERESTARTSYS; 1954 } 1955 } 1956 1957 spin_lock_irqsave(&cobalt_acpi_event_lock, flags); 1958 event = list_entry(cobalt_acpi_event_list.next, 1959 cobalt_acpi_event_t, list); 1960 list_del(&event->list); 1961 spin_unlock_irqrestore(&cobalt_acpi_event_lock, flags); 1962 1963 strsize = sprintf(str, "%s %s %08x %08x\n", 1964 event->device_type, event->device_instance, 1965 event->event_type, event->event_data); 1966 ptr = str; 1967 1968 kfree(event->device_type); 1969 kfree(event->device_instance); 1970 kfree(event); 1971 } 1972 if (strsize < count) 1973 count = strsize; 1974 1975 if (copy_to_user(buf, ptr, count)) 1976 return -EFAULT; 1977 1978 *ppos += count; 1979 strsize -= count; 1980 ptr += count; 1981 1982 return count; 1983 } 1984 1985 static unsigned int 1986 cobalt_acpi_poll_event(struct file *file, poll_table *wait) 1987 { 1988 poll_wait(file, &cobalt_acpi_event_wait_queue, wait); 1989 if (!list_empty(&cobalt_acpi_event_list)) 1990 return POLLIN | POLLRDNORM; 1991 return 0; 1992 } 1993 1994 #endif /* CONFIG_COBALT_EMU_ACPI */ -
drivers/cobalt/fans.c
diff -Naur linux-2.6.20.orig/drivers/cobalt/fans.c linux-2.6.20/drivers/cobalt/fans.c
old new 1 /* $Id: fans.c,v 1.18 2002/03/16 21:33:02 duncan Exp $ 2 * Copyright (c) 2000-2001 Sun Microsystems, Inc 3 * 4 * This should be SMP safe. The critical data (the info list) and the 5 * critical code (inb()/outb() calls) are protected by fan_lock. It is 6 * locked at the only external access points - the proc read()/write() 7 * methods. --TPH 8 */ 9 #include <linux/config.h> 10 #if defined(CONFIG_COBALT_FANS) || defined(CONFIG_COBALT_FANS_MODULE) 11 12 #include <stdarg.h> 13 #include <stddef.h> 14 15 #include <linux/init.h> 16 #include <linux/sched.h> 17 #include <linux/module.h> 18 #include <linux/pci.h> 19 #include <linux/errno.h> 20 #include <linux/proc_fs.h> 21 #include <linux/time.h> 22 23 #include <asm/io.h> 24 #include <asm/uaccess.h> 25 26 #include <cobalt/cobalt.h> 27 #include <cobalt/systype.h> 28 29 #define FAN_DRIVER "Cobalt Networks Fan driver" 30 #define FAN_DRIVER_VMAJ 1 31 #define FAN_DRIVER_VMIN 0 32 33 /* GPIO base is assigned by BIOS, perhaps we should probe it */ 34 #define GPIO_BASE 0x600 35 #define FAN_GPIO_MAX 8 36 #define FAN_RPM(fn,ms) ((fn).hcyl * (60000000 / (fn).poles) / (ms)) 37 #define FAN_VALID(f) ((f)->mask && (f)->poles) 38 #define FAN_CACHE_TIME 2 /* seconds */ 39 #define FAN_SAMPLE_LEN 50 /* milliseconds */ 40 41 /* 42 * fans are attached to GPIO pins 43 * each pin is part of a port, multiple fans are controlled by a port 44 */ 45 struct fan_info { 46 int id; /* fan number */ 47 uint8_t mask; /* mask within the port */ 48 int poles; /* # of magnetic poles (divisor) */ 49 int hcyl; /* # of half cycles */ 50 unsigned rpm; /* calculated fan speed */ 51 char *type; /* FAN description */ 52 }; 53 54 struct fan_gpio { 55 int port; /* GPIO Port */ 56 uint16_t base; /* GPDI (data in) base address */ 57 uint8_t latch; /* latched 'data in' value */ 58 long tcache; /* latched 'epoch' value */ 59 struct fan_info fan[FAN_GPIO_MAX]; 60 }; 61 62 /* the current fanlist */ 63 static struct fan_gpio *sys_fanlist; 64 static spinlock_t fan_lock = SPIN_LOCK_UNLOCKED; 65 66 static struct fan_gpio fan_gpio_raqxtr[] = { 67 { 68 port: 1, 69 base: GPIO_BASE, 70 fan: { 71 { mask: 0x2, poles: 4, type: "processor" }, 72 { mask: 0x4, poles: 4, type: "processor" }, 73 { mask: 0 }, 74 }, 75 }, 76 { 77 port: 2, 78 base: GPIO_BASE+4, 79 fan: { 80 { mask: 0x10, poles: 4 }, 81 { mask: 0x20, poles: 4 }, 82 { mask: 0x40, poles: 4 }, 83 { mask: 0x80, poles: 4 }, 84 { mask: 0 }, 85 }, 86 }, 87 { port: -1 } 88 }; 89 90 static struct fan_gpio fan_gpio_alpine[] = { 91 { 92 port: 2, 93 base: GPIO_BASE+7, 94 fan: { 95 { mask: 0x4, poles: 4 }, 96 { mask: 0x8, poles: 4 }, 97 { mask: 0x10, poles: 4 }, 98 { mask: 0x20, poles: 4, type: "power supply" }, 99 { mask: 0x40, poles: 4, type: "processor" }, 100 { mask: 0 }, 101 }, 102 }, 103 { port: -1 } 104 }; 105 106 #ifdef CONFIG_PROC_FS 107 #ifdef CONFIG_COBALT_OLDPROC 108 static struct proc_dir_entry *proc_faninfo; 109 #endif /* CONFIG_COBALT_OLDPROC */ 110 static struct proc_dir_entry *proc_cfaninfo; 111 #endif /* CONFIG_PROC_FS */ 112 113 static struct fan_info *fan_info_find(int id); 114 static int fan_control(struct fan_info *fi, int todo); 115 static int fan_info_print(char *buffer); 116 static int fan_read_proc(char *buf, char **start, off_t pos, 117 int len, int *eof, void *x); 118 static int fan_write_proc(struct file *file, const char *buf, 119 unsigned long len, void *x); 120 121 int __init 122 cobalt_fan_init(void) 123 { 124 if (cobt_is_monterey()) { 125 sys_fanlist = (struct fan_gpio *)fan_gpio_raqxtr; 126 } else if (cobt_is_alpine()) { 127 sys_fanlist = (struct fan_gpio *)fan_gpio_alpine; 128 } else { 129 sys_fanlist = NULL; 130 return -ENOSYS; 131 } 132 133 printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", FAN_DRIVER,FAN_DRIVER_VMAJ,FAN_DRIVER_VMIN); 134 135 #ifdef CONFIG_PROC_FS 136 #ifdef CONFIG_COBALT_OLDPROC 137 proc_faninfo = create_proc_entry("faninfo", S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, NULL); 138 if (!proc_faninfo) { 139 EPRINTK("can't create /proc/faninfo\n"); 140 return -ENOENT; 141 } 142 proc_faninfo->owner = THIS_MODULE; 143 proc_faninfo->read_proc = fan_read_proc; 144 proc_faninfo->write_proc = fan_write_proc; 145 #endif /* CONFIG_COBALT_OLDPROC */ 146 proc_cfaninfo = create_proc_entry("faninfo", S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, proc_cobalt); 147 if (!proc_cfaninfo) { 148 EPRINTK("can't create /proc/cobalt/faninfo\n"); 149 return -ENOENT; 150 } 151 proc_cfaninfo->owner = THIS_MODULE; 152 proc_cfaninfo->read_proc = fan_read_proc; 153 proc_cfaninfo->write_proc = fan_write_proc; 154 #endif /* CONFIG_PROC_FS */ 155 156 return 0; 157 } 158 159 static void __exit 160 cobalt_fan_exit(void) 161 { 162 #ifdef CONFIG_PROC_FS 163 #ifdef CONFIG_COBALT_OLDPROC 164 if (proc_faninfo) { 165 remove_proc_entry("faninfo", NULL); 166 } 167 #endif /* CONFIG_COBALT_OLDPROC */ 168 if (proc_cfaninfo) { 169 remove_proc_entry("faninfo", proc_cobalt); 170 } 171 #endif /* CONFIG_PROC_FS */ 172 173 sys_fanlist = NULL; 174 } 175 176 /* 177 * Samples fan tachometer square wave to calculate and report RPM 178 */ 179 static int 180 get_faninfo(char *buffer) 181 { 182 struct fan_gpio *fg; 183 struct timeval utime; 184 unsigned long elapsed, start; 185 int i, val, len; 186 187 if (!sys_fanlist || !cobt_is_5k()) { 188 /* software is keyed off this string - do not change it ! */ 189 return sprintf(buffer, "Fan monitoring not supported.\n"); 190 } 191 192 /* save start timestamp */ 193 do_gettimeofday(&utime); 194 start = utime.tv_usec; 195 196 /* initialize 'previous' values. we do edge detection by 197 * looking for transitions from previous values */ 198 for (fg = sys_fanlist; fg->port >= 0; fg++) { 199 if (fg->tcache && utime.tv_sec < fg->tcache+FAN_CACHE_TIME) { 200 return fan_info_print(buffer); 201 } 202 fg->tcache = utime.tv_sec; 203 fg->latch = inb(fg->base); 204 for (i = 0; i < FAN_GPIO_MAX; i++) { 205 fg->fan[i].hcyl = 0; 206 fg->fan[i].rpm = 0; 207 } 208 } 209 210 /* We are counting the number of halfcycles in a square wave 211 * that pass in a given amount of time to determine frequency */ 212 do { 213 for (fg=sys_fanlist; fg->port>=0; fg++) { 214 val = inb(fg->base); 215 for (i=0; i<FAN_GPIO_MAX; i++) { 216 struct fan_info *p = &fg->fan[i]; 217 if (FAN_VALID(p)) { 218 if ((val ^ fg->latch) & p->mask) { 219 p->hcyl++; 220 } 221 } 222 } 223 fg->latch = val; 224 } 225 226 do_gettimeofday(&utime); 227 if (utime.tv_usec > start) { 228 elapsed = utime.tv_usec - start; 229 } else { 230 elapsed = utime.tv_usec + 1000001 - start; 231 } 232 233 } while (elapsed < (FAN_SAMPLE_LEN) * 1000); 234 235 /* Fan rpm = 60 / ( t * poles ) 236 * where t is 1/2 the period and poles are the number of 237 * magnetic poles for the fan. 238 * 239 * For the Sunon KDE1204PKBX fans on Raq XTR, poles = 4 240 * So, in terms of cycles, 241 * 242 * rpm = 60 s/m halfcycles 243 * ------ * -------------- * 1,000,000 us/s * 2 244 * 4 2 * elapsed us 245 * 246 * = (60,000,000 / 4 poles) * halfcycles / elapsed 247 * = 15,000,000 * halfcycles / elapsed 248 * 249 * Note, by this method and sampling for 50ms, our accuracy 250 * is +/- 300 rpm. The fans are spec'ed for +/- 1000 rpm 251 */ 252 for (val=len=0, fg=sys_fanlist; fg->port>=0; fg++) { 253 for (i=0; i<FAN_GPIO_MAX; i++) { 254 struct fan_info *p = &fg->fan[i]; 255 if (FAN_VALID(p)) { 256 p->id = val++; 257 p->rpm = FAN_RPM(fg->fan[i], elapsed); 258 len += sprintf(buffer+len, "fan %d : %u\n", 259 p->id, p->rpm); 260 } 261 } 262 } 263 264 return len; 265 } 266 267 static int 268 fan_info_print(char *buffer) 269 { 270 struct fan_gpio *fg; 271 int i, len=0; 272 273 if (!sys_fanlist) { 274 return -1; 275 } 276 277 for (fg=sys_fanlist; fg->port>=0; fg++) { 278 for (i=0; i<FAN_GPIO_MAX; i++) { 279 struct fan_info *p = &fg->fan[i]; 280 if (FAN_VALID(p)) { 281 len += sprintf(buffer+len, "fan %d : %u\n", 282 p->id, p->rpm); 283 } 284 } 285 } 286 287 return len; 288 } 289 290 /* FIXME: generify */ 291 static int 292 fan_control(struct fan_info *fi, int todo) 293 { 294 if (fi && cobt_is_alpine()) { 295 switch (fi->id) { 296 case 4: { 297 /* CPU FAN */ 298 uint8_t gpdo = inb(GPIO_BASE+6); 299 300 if (todo) { 301 gpdo &= ~fi->mask; /* 0 = on */ 302 } else { 303 gpdo |= fi->mask; /* 1 = off */ 304 } 305 outb(gpdo, GPIO_BASE+6); 306 return 0; 307 } 308 default: 309 return -ENODEV; 310 } 311 } 312 313 return -ENOSYS; 314 } 315 316 static struct fan_info * 317 fan_info_find(int id) 318 { 319 struct fan_gpio *fg; 320 int i; 321 322 if (!sys_fanlist) { 323 return NULL; 324 } 325 326 for (fg=sys_fanlist; fg->port>=0; fg++) { 327 for (i=0; i<FAN_GPIO_MAX; i++) { 328 if (FAN_VALID(&fg->fan[i])) { 329 if (fg->fan[i].id == id) { 330 return &fg->fan[i]; 331 } 332 } 333 } 334 } 335 336 return NULL; 337 } 338 339 #ifdef CONFIG_PROC_FS 340 static int 341 fan_read_proc(char *buf, char **start, off_t pos, int len, int *eof, void *x) 342 { 343 int plen; 344 345 //MOD_INC_USE_COUNT; 346 347 spin_lock(&fan_lock); 348 plen = get_faninfo(buf); 349 spin_unlock(&fan_lock); 350 351 //MOD_DEC_USE_COUNT; 352 353 return cobalt_gen_proc_read(buf, plen, start, pos, len, eof); 354 } 355 356 static int 357 fan_write_proc(struct file *file, const char *buf, unsigned long len, void *x) 358 { 359 char *page; 360 int retval = -EINVAL; 361 362 //MOD_INC_USE_COUNT; 363 364 if (len > PAGE_SIZE) { 365 //MOD_DEC_USE_COUNT; 366 return -EOVERFLOW; 367 } 368 369 page = (char *)__get_free_page(GFP_KERNEL); 370 if (!page) { 371 //MOD_DEC_USE_COUNT; 372 return -ENOMEM; 373 } 374 375 if (copy_from_user(page, buf, len)) { 376 free_page((unsigned long)page); 377 //MOD_DEC_USE_COUNT; 378 return -EFAULT; 379 } 380 page[len] = '\0'; 381 382 /* format: `fan ID COMMAND' */ 383 if (len>5 && !strncmp("fan ", page, 4)) { 384 if (*(page+4) != '\0') { 385 struct fan_info *finf; 386 char *nextpg = NULL; 387 388 spin_lock(&fan_lock); 389 finf = fan_info_find(simple_strtoul(page+4,&nextpg,0)); 390 if (!finf) { 391 retval = -ENOENT; 392 } else if (nextpg != '\0') { 393 if (!strncmp("on", nextpg+1, 2)) { 394 retval = fan_control(finf, 1); 395 } 396 else if (!strncmp("off", nextpg+1, 3)) { 397 retval = fan_control(finf, 0); 398 } 399 } 400 spin_unlock(&fan_lock); 401 } 402 } 403 404 free_page((unsigned long)page); 405 //MOD_DEC_USE_COUNT; 406 407 return (retval < 0) ? retval : len; 408 } 409 #endif /* CONFIG_PROC_FS */ 410 411 #if defined(CONFIG_COBALT_FANS_MODULE) 412 module_init(cobalt_fan_init); 413 module_exit(cobalt_fan_exit); 414 415 MODULE_AUTHOR("Sun Cobalt"); 416 MODULE_DESCRIPTION("Sun Cobalt fan tachometers"); 417 #endif 418 419 #endif /* CONFIG_COBALT_FANS || CONFIG_COBALT_FANS_MODULE */ -
drivers/cobalt/i2c.c
diff -Naur linux-2.6.20.orig/drivers/cobalt/i2c.c linux-2.6.20/drivers/cobalt/i2c.c
old new 1 /* 2 * $Id: i2c.c,v 1.19 2002/09/17 23:41:29 sparker Exp $ 3 * i2c.c : Cobalt I2C driver support 4 * 5 * Copyright (C) 2000 Cobalt Networks, Inc. 6 * Copyright (C) 2001 Sun Microsystems, Inc. 7 * 8 * Modified By: jeff@404ster.com 9 * 10 * This should be SMP safe. All the exported functions lock on enter and 11 * unlock on exit. These exported functions may be called at interupt time, 12 * so we have to use the IRQ safe locks. NOTE: no function herein may call 13 * any exported function herein. --TPH 14 */ 15 #include <stddef.h> 16 #include <linux/init.h> 17 #include <linux/types.h> 18 #include <linux/config.h> 19 #include <linux/pci.h> 20 #include <linux/delay.h> 21 #include <linux/module.h> 22 #include <asm/io.h> 23 24 #include <cobalt/cobalt.h> 25 #include <cobalt/i2c.h> 26 #include <cobalt/systype.h> 27 28 #define I2C_3K_STATUS 0x00 29 #define I2C_3K_CMD 0x01 30 #define I2C_3K_START 0x02 31 #define I2C_3K_ADDR 0x03 32 #define I2C_3K_LOW_DATA 0x04 33 #define I2C_3K_HIGH_DATA 0x05 34 #define I2C_3K_BLOCK_DATA 0x06 35 #define I2C_3K_INDEX 0x07 36 #define I2C_3K_STATUS_IDLE 0x04 37 #define I2C_3K_CMD_RW_BYTE 0x20 38 #define I2C_3K_CMD_RW_WORD 0x30 39 #define I2C_3K_CMD_RW_BLOCK 0xC0 40 #define I2C_3K_CMD_RESET_PTR 0x80 41 42 #define I2C_5K_HOST_STATUS 0x00 43 #define I2C_5K_SLAVE_STATUS 0x01 44 #define I2C_5K_HOST_CONTROL 0x02 45 #define I2C_5K_HOST_COMMAND 0x03 46 #define I2C_5K_HOST_ADDR 0x04 47 #define I2C_5K_DATA_0 0x05 48 #define I2C_5K_DATA_1 0x06 49 #define I2C_5K_BLOCK_DATA 0x07 50 #define I2C_5K_SLAVE_CONTROL 0x08 51 #define I2C_5K_SHADOW_COMMAND 0x09 52 #define I2C_5K_SLAVE_EVENT 0x0a 53 #define I2C_5K_SLAVE_DATA 0x0c 54 #define I2C_5K_HOST_STATUS_BUSY 0x01 55 #define I2C_5K_HOST_CMD_START 0x40 56 #define I2C_5K_HOST_CMD_QUICK_RW (0 << 2) 57 #define I2C_5K_HOST_CMD_BYTE_RW (1 << 2) 58 #define I2C_5K_HOST_CMD_BYTE_DATA_RW (2 << 2) 59 #define I2C_5K_HOST_CMD_WORD_DATA_RW (3 << 2) 60 #define I2C_5K_HOST_CMD_BLOCK_DATA_RW (5 << 2) 61 62 #define I2C_WRITE 0 63 #define I2C_READ 1 64 65 /* this delay was determined empirically */ 66 #define I2C_WRITE_UDELAY 1000 67 68 struct cobalt_i2c_data { 69 const unsigned char status; 70 const unsigned char addr; 71 const unsigned char index; 72 const unsigned char data_low; 73 const unsigned char data_high; 74 const unsigned char data_block; 75 const unsigned char rw_byte; 76 const unsigned char rw_word; 77 const unsigned char rw_block; 78 unsigned int io_port; 79 }; 80 81 struct cobalt_i2c_data cobalt_i2c_3k = { 82 I2C_3K_STATUS, 83 I2C_3K_ADDR, 84 I2C_3K_INDEX, 85 I2C_3K_LOW_DATA, 86 I2C_3K_HIGH_DATA, 87 I2C_3K_BLOCK_DATA, 88 I2C_3K_CMD_RW_BYTE, 89 I2C_3K_CMD_RW_WORD, 90 I2C_3K_CMD_RW_BLOCK, 91 0L 92 }; 93 94 struct cobalt_i2c_data cobalt_i2c_5k = { 95 I2C_5K_HOST_STATUS, 96 I2C_5K_HOST_ADDR, 97 I2C_5K_HOST_COMMAND, 98 I2C_5K_DATA_0, 99 I2C_5K_DATA_1, 100 I2C_5K_BLOCK_DATA, 101 I2C_5K_HOST_CMD_BYTE_DATA_RW, 102 I2C_5K_HOST_CMD_WORD_DATA_RW, 103 I2C_5K_HOST_CMD_BLOCK_DATA_RW, 104 0L 105 }; 106 107 /* a global pointer for our i2c data */ 108 struct cobalt_i2c_data *i2c_data; 109 110 #define I2C_REG(r) (i2c_data->io_port + i2c_data->r) 111 #define I2C_CMD(c) (i2c_data->c) 112 113 #define I2C_LOCK (1 << 0) 114 #define I2C_DEAD (1 << 1) 115 static unsigned long i2c_state; 116 117 static int initialized; 118 119 static inline int 120 do_i2c_lock(void) 121 { 122 int i = 0; 123 124 if (test_bit(I2C_DEAD, &i2c_state)) 125 return -1; 126 127 while (test_and_set_bit(I2C_LOCK, &i2c_state)) { 128 if (i++ > 5) 129 return -1; 130 udelay(10); 131 } 132 udelay(1); 133 return 0; 134 } 135 136 static inline void 137 do_i2c_unlock(void) 138 { 139 clear_bit(I2C_LOCK, &i2c_state); 140 } 141 142 /* do a little squelching */ 143 #define NOISE_RATE (5*HZ) 144 static int 145 i2c_noisy(void) 146 { 147 static unsigned long last_time; 148 static unsigned int messages; 149 150 if ((long) (jiffies - last_time) > NOISE_RATE) { 151 last_time = jiffies; 152 if (messages) { 153 WPRINTK("skipped %u kernel messages\n", messages); 154 messages = 0; 155 } 156 return 0; 157 } 158 messages++; 159 return 1; 160 } 161 162 static int 163 i2c_wait_for_smi(void) 164 { 165 static unsigned int shutup = 0; 166 int timeout=10; 167 int status; 168 169 while (timeout--) { 170 udelay(100); /* wait */ 171 status = inb_p(I2C_REG(status)); 172 173 if (cobt_is_3k()) { 174 if (status & I2C_3K_STATUS_IDLE) { 175 return 0; 176 } 177 } else if (cobt_is_5k()) { 178 if (!(status & I2C_5K_HOST_STATUS_BUSY)) { 179 return 0; 180 } 181 } 182 outb_p(status, I2C_REG(status)); 183 } 184 185 /* still busy - complain */ 186 if (!i2c_noisy()) { 187 if (++shutup > 2) { 188 EPRINTK("i2c seems to be dead - sorry\n"); 189 set_bit(I2C_DEAD, &i2c_state); 190 } else { 191 WPRINTK("i2c timeout: status busy (0x%x), resetting\n", 192 status); 193 } 194 } 195 196 /* punch the abort bit */ 197 if (cobt_is_3k()) { 198 outb_p(4, i2c_data->io_port + I2C_3K_CMD); 199 } else if (cobt_is_5k()) { 200 outb_p(2, i2c_data->io_port + I2C_5K_HOST_CONTROL); 201 outb_p(1, i2c_data->io_port + I2C_5K_HOST_CONTROL); 202 } 203 204 return -1; 205 } 206 207 static inline int 208 i2c_setup(const int dev, const int index, const int r) 209 { 210 if (i2c_wait_for_smi() < 0) 211 return -1; 212 213 /* clear status */ 214 outb_p(0xff, I2C_REG(status)); 215 216 /* device address */ 217 outb_p((dev|r) & 0xff, I2C_REG(addr)); 218 219 /* I2C index */ 220 outb_p(index & 0xff, I2C_REG(index)); 221 222 return 0; 223 } 224 225 static inline int 226 i2c_cmd(const unsigned char command) 227 { 228 if (cobt_is_3k()) { 229 outb_p(command, i2c_data->io_port + I2C_3K_CMD); 230 outb_p(0xff, i2c_data->io_port + I2C_3K_START); 231 } else if (cobt_is_5k()) { 232 outb_p(I2C_5K_HOST_CMD_START | command, 233 i2c_data->io_port + I2C_5K_HOST_CONTROL); 234 } 235 236 if (i2c_wait_for_smi() < 0) 237 return -1; 238 239 return 0; 240 } 241 242 int 243 cobalt_i2c_init(void) 244 { 245 struct pci_dev *i2cdev = NULL; 246 247 if( ! initialized ) { 248 if (cobt_is_3k()) { 249 i2c_data = &cobalt_i2c_3k; 250 i2cdev = pci_find_device(PCI_VENDOR_ID_AL, 251 PCI_DEVICE_ID_AL_M7101, NULL); 252 if (!i2cdev) { 253 EPRINTK("can't find PMU for i2c access\n"); 254 return -1; 255 } 256 pci_read_config_dword(i2cdev, 0x14, &i2c_data->io_port); 257 } else if (cobt_is_5k()) { 258 i2c_data = &cobalt_i2c_5k; 259 i2cdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, 260 PCI_DEVICE_ID_SERVERWORKS_OSB4, i2cdev); 261 if (!i2cdev) { 262 i2cdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, 263 PCI_DEVICE_ID_SERVERWORKS_CSB5, i2cdev); 264 if (!i2cdev) { 265 EPRINTK("can't find OSB4 or CSB5 for i2c access\n"); 266 return -1; 267 } 268 } 269 pci_read_config_dword(i2cdev, 0x90, &i2c_data->io_port); 270 } 271 272 i2c_data->io_port &= 0xfff0; 273 if (!i2c_data->io_port) { 274 EPRINTK("i2c IO port not found\n"); 275 } 276 initialized = 1; 277 } 278 279 return 0; 280 } 281 282 int 283 cobalt_i2c_reset(void) 284 { 285 int r; 286 287 if( !initialized ) { 288 if( cobalt_i2c_init() < 0 ) 289 return -1; 290 } 291 292 if (do_i2c_lock() < 0) 293 return -1; 294 295 if (cobt_is_3k()) { 296 /* clear status */ 297 outb_p(0xff, i2c_data->io_port + I2C_3K_STATUS); 298 /* reset SMB devs */ 299 outb_p(0x08, i2c_data->io_port + I2C_3K_CMD); 300 /* start command */ 301 outb_p(0xff, i2c_data->io_port + I2C_3K_START); 302 } else if (cobt_is_5k()) { 303 /* clear status */ 304 outb_p(0x2, i2c_data->io_port + I2C_5K_HOST_CONTROL); 305 outb_p(0x1, i2c_data->io_port + I2C_5K_HOST_CONTROL); 306 outb_p(0xff, i2c_data->io_port + I2C_5K_HOST_STATUS); 307 outb_p(I2C_5K_HOST_CMD_START | 0x08, 308 i2c_data->io_port + I2C_5K_HOST_CONTROL); 309 } 310 311 r = i2c_wait_for_smi(); 312 313 do_i2c_unlock(); 314 315 return r; 316 } 317 318 int 319 cobalt_i2c_read_byte(const int dev, const int index) 320 { 321 int val = 0; 322 323 if( !initialized ) { 324 if( cobalt_i2c_init() < 0 ) 325 return -1; 326 } 327 328 if (do_i2c_lock() < 0) 329 return -1; 330 331 if (i2c_setup(dev, index, I2C_READ) < 0 332 || i2c_cmd(I2C_CMD(rw_byte)) < 0) { 333 val = -1; 334 } 335 336 if (val == 0) { 337 val = inb_p(I2C_REG(data_low)); 338 } 339 340 do_i2c_unlock(); 341 342 return val; 343 } 344 345 int 346 cobalt_i2c_read_word(const int dev, const int index) 347 { 348 int val = 0; 349 350 if( !initialized ) { 351 if( cobalt_i2c_init() < 0 ) 352 return -1; 353 } 354 355 if (do_i2c_lock() < 0) 356 return -1; 357 358 if (i2c_setup(dev, index, I2C_READ) < 0 359 || i2c_cmd(I2C_CMD(rw_word)) < 0) { 360 val = -1; 361 } 362 363 if (val == 0) { 364 val = inb_p(I2C_REG(data_low)); 365 val += inb_p(I2C_REG(data_high)) << 8; 366 } 367 368 do_i2c_unlock(); 369 370 return val; 371 } 372 373 int 374 cobalt_i2c_read_block(const int dev, const int index, 375 unsigned char *data, int count) 376 { 377 if( !initialized ) { 378 if( cobalt_i2c_init() < 0 ) 379 return -1; 380 } 381 382 if (do_i2c_lock() < 0) 383 return -1; 384 385 if (i2c_setup(dev, index, I2C_READ) < 0) { 386 do_i2c_unlock(); 387 return -1; 388 } 389 390 outb_p(count & 0xff, I2C_REG(data_low)); 391 outb_p(count & 0xff, I2C_REG(data_high)); 392 393 if (i2c_cmd(I2C_CMD(rw_block)) < 0) { 394 do_i2c_unlock(); 395 return -1; 396 } 397 398 while (count) { 399 /* read a byte of block data */ 400 *data = inb_p(I2C_REG(data_block)); 401 data++; 402 count--; 403 } 404 405 do_i2c_unlock(); 406 407 return 0; 408 } 409 410 int 411 cobalt_i2c_write_byte(const int dev, const int index, const u8 val) 412 { 413 int r = 0; 414 415 if( !initialized ) { 416 if( cobalt_i2c_init() < 0 ) 417 return -1; 418 } 419 420 if (do_i2c_lock() < 0) 421 return -1; 422 423 if (i2c_setup(dev, index, I2C_WRITE) < 0) { 424 r = -1; 425 } 426 427 if (r == 0) { 428 outb_p(val & 0xff, I2C_REG(data_low)); 429 430 if (i2c_cmd(I2C_CMD(rw_byte)) < 0) { 431 r = -1; 432 } 433 } 434 435 udelay(I2C_WRITE_UDELAY); 436 437 do_i2c_unlock(); 438 439 return r; 440 } 441 442 int 443 cobalt_i2c_write_word(const int dev, const int index, const u16 val) 444 { 445 int r = 0; 446 447 if( !initialized ) { 448 if( cobalt_i2c_init() < 0 ) 449 return -1; 450 } 451 452 if (do_i2c_lock() < 0) 453 return -1; 454 455 if (i2c_setup(dev, index, I2C_WRITE) < 0) { 456 r = -1; 457 } 458 459 if (r == 0) { 460 outb_p(val & 0xff, I2C_REG(data_low)); 461 outb_p((val >> 8) & 0xff, I2C_REG(data_high)); 462 463 if (i2c_cmd(I2C_CMD(rw_word)) < 0) { 464 r = -1; 465 } 466 } 467 468 udelay(I2C_WRITE_UDELAY); 469 470 do_i2c_unlock(); 471 472 return r; 473 } 474 475 int 476 cobalt_i2c_write_block(int dev, int index, unsigned char *data, int count) 477 { 478 if( !initialized ) { 479 if( cobalt_i2c_init() < 0 ) 480 return -1; 481 } 482 483 if (do_i2c_lock() < 0) 484 return -1; 485 486 if (i2c_setup(dev, index, I2C_WRITE) < 0) { 487 do_i2c_unlock(); 488 return -1; 489 } 490 491 outb_p(count & 0xff, I2C_REG(data_low)); 492 outb_p(count & 0xff, I2C_REG(data_high)); 493 494 if (i2c_cmd(I2C_CMD(rw_block)) < 0) { 495 do_i2c_unlock(); 496 return -1; 497 } 498 499 while (count) { 500 /* write a byte of block data */ 501 outb_p(*data, I2C_REG(data_block)); 502 data++; 503 count--; 504 } 505 506 udelay(I2C_WRITE_UDELAY); 507 508 do_i2c_unlock(); 509 510 return 0; 511 } 512 513 EXPORT_SYMBOL(cobalt_i2c_reset); 514 EXPORT_SYMBOL(cobalt_i2c_read_byte); 515 EXPORT_SYMBOL(cobalt_i2c_read_word); 516 EXPORT_SYMBOL(cobalt_i2c_read_block); 517 EXPORT_SYMBOL(cobalt_i2c_write_byte); 518 EXPORT_SYMBOL(cobalt_i2c_write_word); 519 EXPORT_SYMBOL(cobalt_i2c_write_block); -
drivers/cobalt/init.c
diff -Naur linux-2.6.20.orig/drivers/cobalt/init.c linux-2.6.20/drivers/cobalt/init.c
old new 1 /* $Id: init.c,v 1.22 2002/11/04 17:54:15 thockin Exp $ */ 2 /* 3 * Copyright (c) 2001 Sun Microsystems 4 * Generic initialization, to reduce pollution of other files 5 */ 6 #include <linux/config.h> 7 #include <linux/module.h> 8 #include <linux/stddef.h> 9 #include <linux/version.h> 10 #include <linux/types.h> 11 #include <linux/init.h> 12 #include <linux/proc_fs.h> 13 #include <cobalt/cobalt.h> 14 15 static int cobalt_proc_init(void); 16 extern int cobalt_i2c_init(void); 17 extern int cobalt_net_init(void); 18 extern int cobalt_systype_init(void); 19 extern void cobalt_boardrev_init(void); 20 extern int cobalt_led_init(void); 21 extern int cobalt_lcd_init(void); 22 extern int cobalt_serialnum_init(void); 23 extern int cobalt_wdt_init(void); 24 extern int cobalt_sensors_init(void); 25 extern int cobalt_fan_init(void); 26 extern int cobalt_acpi_init(void); 27 extern int cobalt_ruler_init(void); 28 extern int cobalt_raminfo_init(void); 29 30 #ifdef CONFIG_PROC_FS 31 struct proc_dir_entry *proc_cobalt; 32 EXPORT_SYMBOL(proc_cobalt); 33 #endif 34 spinlock_t cobalt_superio_lock = SPIN_LOCK_UNLOCKED; 35 36 /* initialize all the cobalt specific stuff */ 37 int __init 38 cobalt_init(void) 39 { 40 cobalt_proc_init(); 41 cobalt_systype_init(); 42 #ifdef CONFIG_COBALT_RAQ 43 /* we might keep the boardrev on an i2c chip */ 44 cobalt_i2c_init(); 45 #endif 46 cobalt_boardrev_init(); 47 #ifdef CONFIG_COBALT_ACPI 48 cobalt_acpi_init(); 49 #endif 50 #ifdef CONFIG_COBALT_LED 51 cobalt_net_init(); 52 cobalt_led_init(); 53 #endif 54 #ifdef CONFIG_COBALT_LCD 55 cobalt_lcd_init(); 56 #endif 57 #ifdef CONFIG_COBALT_RULER 58 cobalt_ruler_init(); 59 #endif 60 #ifdef CONFIG_COBALT_SERNUM 61 cobalt_serialnum_init(); 62 #endif 63 #ifdef CONFIG_COBALT_RAQ 64 /* some systems use WDT it for reboot */ 65 cobalt_wdt_init(); 66 #endif 67 #ifdef CONFIG_COBALT_SENSORS 68 cobalt_sensors_init(); 69 #endif 70 #ifdef CONFIG_COBALT_FANS 71 cobalt_fan_init(); 72 #endif 73 #ifdef CONFIG_COBALT_RAMINFO 74 cobalt_raminfo_init(); 75 #endif 76 return 0; 77 } 78 79 static int __init 80 cobalt_proc_init(void) 81 { 82 #ifdef CONFIG_PROC_FS 83 proc_cobalt = proc_mkdir("cobalt", 0); 84 if (!proc_cobalt) { 85 EPRINTK("can't create /proc/cobalt\n"); 86 return -1; 87 } 88 #endif 89 90 return 0; 91 } 92 93 /* a function that handles the blah stuff in a simple proc read function */ 94 int 95 cobalt_gen_proc_read(char *buf, int plen, char **start, off_t pos, 96 int len, int *eof) 97 { 98 /* trying to read a bad offset? */ 99 if (pos >= plen) { 100 *eof = 1; 101 return 0; 102 } 103 104 /* did we write everything we wanted to? */ 105 if (len >= (plen-pos)) { 106 *eof = 1; 107 } 108 109 *start = buf + pos; 110 plen -= pos; 111 112 return (len > plen) ? plen : len; 113 } 114 EXPORT_SYMBOL(cobalt_gen_proc_read); -
drivers/cobalt/lcd.c
diff -Naur linux-2.6.20.orig/drivers/cobalt/lcd.c linux-2.6.20/drivers/cobalt/lcd.c
old new 1 /* 2 * $Id: lcd.c,v 1.44 2002/05/10 18:44:45 duncan Exp $ 3 * lcd.c : driver for Cobalt LCD/Buttons 4 * 5 * Copyright 1996-2000 Cobalt Networks, Inc. 6 * Copyright 2001 Sun Microsystems, Inc. 7 * 8 * By: Andrew Bose 9 * Timothy Stonis 10 * Tim Hockin 11 * Adrian Sun 12 * Duncan Laurie 13 * 14 * Modified By: jeff@404ster.com 15 * 16 * This should be SMP safe. We're hardly performance critical, 17 * so we lock around lcd_ioctl() and just where needed by other external 18 * functions. There is a static global waiters variable that is atomic_t, and 19 * so should be safe. --TPH 20 */ 21 22 #include <linux/config.h> 23 24 #ifdef CONFIG_COBALT_LCD 25 26 #include <linux/module.h> 27 #include <linux/types.h> 28 #include <linux/errno.h> 29 #include <linux/miscdevice.h> 30 #include <linux/slab.h> 31 #include <linux/ioport.h> 32 #include <linux/fcntl.h> 33 #include <linux/stat.h> 34 #include <linux/netdevice.h> 35 #include <linux/proc_fs.h> 36 #include <linux/in6.h> 37 #include <linux/pci.h> 38 #include <linux/init.h> 39 #include <linux/timer.h> 40 #include <linux/kernel.h> 41 42 #include <asm/io.h> 43 #include <asm/segment.h> 44 #include <asm/system.h> 45 #include <asm/uaccess.h> 46 #include <asm/checksum.h> 47 #include <linux/delay.h> 48 49 #include <cobalt/cobalt.h> 50 #include <cobalt/systype.h> 51 #include <cobalt/lcd.h> 52 #include <cobalt/superio.h> 53 #include <cobalt/i2c.h> 54 55 #define TWIDDLE_HZ (HZ/10) 56 57 #ifndef min 58 #define min(a, b) ((a) < (b) ? (a) : (b)) 59 #endif 60 61 #define LCD_DRIVER "Cobalt Networks LCD driver" 62 #define LCD_DRIVER_VMAJ 4 63 #define LCD_DRIVER_VMIN 0 64 65 /* io registers */ 66 #define LPT 0x0378 67 #define LCD_DATA_ADDRESS LPT+0 68 #define LCD_CONTROL_ADDRESS LPT+2 69 70 /* LCD device info */ 71 #define LCD_Addr 0x80 72 #define DD_R00 0x00 73 #define DD_R01 0x27 74 #define DD_R10 0x40 75 #define DD_R11 0x67 76 77 /* driver functions */ 78 static int cobalt_lcd_open(struct inode *, struct file *); 79 static ssize_t cobalt_lcd_read(struct file *, char *, size_t, loff_t *); 80 static int cobalt_lcd_read_proc(char *, char **, off_t, int, int *, void *); 81 static char *cobalt_lcddev_read_line(int, char *); 82 static int cobalt_lcd_ioctl(struct inode *, struct file *, 83 unsigned int, unsigned long); 84 static int cobalt_lcd_panic(struct notifier_block *self, unsigned long, void *); 85 86 /* globals used throughout */ 87 #ifdef CONFIG_PROC_FS 88 #ifdef CONFIG_COBALT_OLDPROC 89 static struct proc_dir_entry *proc_lcd; 90 #endif 91 static struct proc_dir_entry *proc_clcd; 92 #endif 93 static int lcd_present; 94 static int has_i2c_lcd; 95 static spinlock_t lcd_lock = SPIN_LOCK_UNLOCKED; 96 97 /* various file operations we support for this driver */ 98 static struct file_operations lcd_fops = { 99 .read = cobalt_lcd_read, 100 .ioctl = cobalt_lcd_ioctl, 101 .open = cobalt_lcd_open, 102 }; 103 104 /* device structure */ 105 static struct miscdevice lcd_dev = { 106 MISC_DYNAMIC_MINOR, 107 "lcd", 108 &lcd_fops 109 }; 110 111 static int disable_lcd; 112 static int __init 113 lcd_disable_setup(char *str) 114 { 115 disable_lcd = 1; 116 return 0; 117 } 118 __setup("nolcd", lcd_disable_setup); 119 120 /* Read a control instruction from the LCD */ 121 static inline int 122 lcddev_read_inst(void) 123 { 124 int a = 0; 125 126 if (cobt_is_5k() && has_i2c_lcd) { 127 a = cobalt_i2c_read_byte( 128 COBALT_I2C_DEV_LCD_INST | COBALT_I2C_READ, 0); 129 } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) { 130 outb(0x21, LCD_CONTROL_ADDRESS); /* RS=0, R/W=1, E=0 */ 131 outb(0x20, LCD_CONTROL_ADDRESS); /* RS=0, R/W=1, E=1 */ 132 a = inb(LCD_DATA_ADDRESS); 133 outb(0x21, LCD_CONTROL_ADDRESS); /* RS=0, R/W=1, E=0 */ 134 outb(0x01, LCD_CONTROL_ADDRESS); /* RS=0, R/W=1, E=0 */ 135 } 136 137 /* small delay */ 138 udelay(100); 139 140 return a; 141 } 142 143 #define LCD_MAX_POLL 10000 144 static inline void 145 lcddev_poll_wait(void) 146 { 147 int i=0; 148 149 while (i++ < LCD_MAX_POLL) { 150 int r = lcddev_read_inst(); 151 if (r < 0 || !(r & 0x80)) 152 break; 153 } 154 } 155 156 /* Write a control instruction to the LCD */ 157 static inline void 158 lcddev_write_inst(unsigned char data) 159 { 160 lcddev_poll_wait(); 161 162 if (cobt_is_5k() && has_i2c_lcd) { 163 cobalt_i2c_write_byte( 164 COBALT_I2C_DEV_LCD_INST | COBALT_I2C_WRITE, 0, data); 165 } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) { 166 outb(0x03, LCD_CONTROL_ADDRESS); /* RS=0, R/W=0, E=0 */ 167 outb(data, LCD_DATA_ADDRESS); 168 outb(0x02, LCD_CONTROL_ADDRESS); /* RS=0, R/W=0, E=1 */ 169 outb(0x03, LCD_CONTROL_ADDRESS); /* RS=0, R/W=0, E=0 */ 170 outb(0x01, LCD_CONTROL_ADDRESS); /* RS=0, R/W=1, E=0 */ 171 } 172 173 /* small delay */ 174 udelay(100); 175 } 176 177 /* Write one byte of data to the LCD */ 178 static inline void 179 lcddev_write_data(unsigned char data) 180 { 181 lcddev_poll_wait(); 182 183 if (cobt_is_5k() && has_i2c_lcd) { 184 cobalt_i2c_write_byte( 185 COBALT_I2C_DEV_LCD_DATA | COBALT_I2C_WRITE, 0, data); 186 } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) { 187 outb(0x07, LCD_CONTROL_ADDRESS); /* RS=1, R/W=0, E=0 */ 188 outb(data, LCD_DATA_ADDRESS); 189 outb(0x06, LCD_CONTROL_ADDRESS); /* RS=1, R/W=0, E=1 */ 190 outb(0x07, LCD_CONTROL_ADDRESS); /* RS=1, R/W=0, E=0 */ 191 outb(0x05, LCD_CONTROL_ADDRESS); /* RS=1, R/W=1, E=0 */ 192 } 193 /* small delay */ 194 udelay(100); 195 } 196 197 /* Read one byte of data from the LCD */ 198 static inline unsigned char 199 lcddev_read_data(void) 200 { 201 unsigned char a = 0; 202 203 lcddev_poll_wait(); 204 205 if (cobt_is_5k() && has_i2c_lcd) { 206 a = cobalt_i2c_read_byte( 207 COBALT_I2C_DEV_LCD_DATA | COBALT_I2C_READ, 0); 208 } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) { 209 outb(0x25, LCD_CONTROL_ADDRESS); /* RS=1, R/W=1, E=0 */ 210 outb(0x24, LCD_CONTROL_ADDRESS); /* RS=1, R/W=1, E=1 */ 211 a = inb(LCD_DATA_ADDRESS); 212 outb(0x25, LCD_CONTROL_ADDRESS); /* RS=1, R/W=1, E=0 */ 213 outb(0x01, LCD_CONTROL_ADDRESS); /* RS=1, R/W=1, E=0 */ 214 } 215 216 /* small delay */ 217 udelay(100); 218 219 return a; 220 } 221 222 static inline void 223 lcddev_init(void) 224 { 225 lcddev_write_inst(0x38); 226 lcddev_write_inst(0x38); 227 lcddev_write_inst(0x38); 228 lcddev_write_inst(0x06); 229 lcddev_write_inst(0x0c); 230 } 231 232 static inline char 233 read_buttons(void) 234 { 235 char r = 0; 236 237 if (cobt_is_5k() && has_i2c_lcd) { 238 unsigned char inst; 239 inst = cobalt_i2c_read_byte(COBALT_I2C_DEV_FP_BUTTONS, 0); 240 switch (inst) { 241 case 0x3e: r = BUTTON_Next_B; break; 242 case 0x3d: r = BUTTON_Enter_B; break; 243 case 0x1f: r = BUTTON_Left_B; break; 244 case 0x3b: r = BUTTON_Right_B; break; 245 case 0x2f: r = BUTTON_Up_B; break; 246 case 0x37: r = BUTTON_Down_B; break; 247 case 0x3f: 248 default: r = BUTTON_NONE_B; 249 } 250 } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) { 251 outb(0x29, LCD_CONTROL_ADDRESS); /* Sel=0, Bi=1 */ 252 r = inb(LCD_DATA_ADDRESS) & BUTTON_MASK; 253 } 254 255 return r; 256 } 257 258 static inline int 259 button_pressed(void) 260 { 261 unsigned char b; 262 unsigned long flags; 263 264 spin_lock_irqsave(&lcd_lock, flags); 265 b = read_buttons(); 266 spin_unlock_irqrestore(&lcd_lock, flags); 267 268 switch (b) { 269 case BUTTON_Next: 270 case BUTTON_Next_B: 271 case BUTTON_Reset_B: 272 return b; 273 default: 274 break; 275 } 276 277 return 0; 278 } 279 280 /* this could be protected by CAP_RAW_IO here, or by the FS permissions */ 281 static int 282 cobalt_lcd_ioctl(struct inode *inode, struct file *file, 283 unsigned int cmd, unsigned long arg) 284 { 285 struct lcd_display button_display, display; 286 unsigned long address, a; 287 int index; 288 int dlen = sizeof(struct lcd_display); 289 int r = 0; 290 unsigned long flags; 291 292 #ifdef CONFIG_COBALT_LCD_TWIDDLE 293 cobalt_lcd_stop_twiddle(); 294 #endif 295 switch (cmd) { 296 /* Turn the LCD on */ 297 case LCD_On: 298 spin_lock_irqsave(&lcd_lock, flags); 299 lcddev_write_inst(0x0F); 300 spin_unlock_irqrestore(&lcd_lock, flags); 301 break; 302 303 /* Turn the LCD off */ 304 case LCD_Off: 305 spin_lock_irqsave(&lcd_lock, flags); 306 lcddev_write_inst(0x08); 307 spin_unlock_irqrestore(&lcd_lock, flags); 308 break; 309 310 /* Reset the LCD */ 311 case LCD_Reset: 312 spin_lock_irqsave(&lcd_lock, flags); 313 lcddev_write_inst(0x3F); 314 lcddev_write_inst(0x3F); 315 lcddev_write_inst(0x3F); 316 lcddev_write_inst(0x3F); 317 lcddev_write_inst(0x01); 318 lcddev_write_inst(0x06); 319 spin_unlock_irqrestore(&lcd_lock, flags); 320 break; 321 322 /* Clear the LCD */ 323 case LCD_Clear: 324 spin_lock_irqsave(&lcd_lock, flags); 325 lcddev_write_inst(0x01); 326 spin_unlock_irqrestore(&lcd_lock, flags); 327 break; 328 329 /* Move the cursor one position to the left */ 330 case LCD_Cursor_Left: 331 spin_lock_irqsave(&lcd_lock, flags); 332 lcddev_write_inst(0x10); 333 spin_unlock_irqrestore(&lcd_lock, flags); 334 break; 335 336 /* Move the cursor one position to the right */ 337 case LCD_Cursor_Right: 338 spin_lock_irqsave(&lcd_lock, flags); 339 lcddev_write_inst(0x14); 340 spin_unlock_irqrestore(&lcd_lock, flags); 341 break; 342 343 /* Turn the cursor off */ 344 case LCD_Cursor_Off: 345 spin_lock_irqsave(&lcd_lock, flags); 346 lcddev_write_inst(0x0C); 347 spin_unlock_irqrestore(&lcd_lock, flags); 348 break; 349 350 /* Turn the cursor on */ 351 case LCD_Cursor_On: 352 spin_lock_irqsave(&lcd_lock, flags); 353 lcddev_write_inst(0x0F); 354 spin_unlock_irqrestore(&lcd_lock, flags); 355 break; 356 357 /* Turn blinking off? I don't know what this does - TJS */ 358 case LCD_Blink_Off: 359 spin_lock_irqsave(&lcd_lock, flags); 360 lcddev_write_inst(0x0E); 361 spin_unlock_irqrestore(&lcd_lock, flags); 362 break; 363 364 /* Get the current cursor position */ 365 case LCD_Get_Cursor_Pos: 366 spin_lock_irqsave(&lcd_lock, flags); 367 display.cursor_address = (unsigned char)lcddev_read_inst(); 368 display.cursor_address = display.cursor_address & 0x07F; 369 spin_unlock_irqrestore(&lcd_lock, flags); 370 if (copy_to_user((struct lcd_display *)arg, &display, dlen)) { 371 r = -EFAULT; 372 } 373 break; 374 375 /* Set the cursor position */ 376 case LCD_Set_Cursor_Pos: 377 if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) { 378 r = -EFAULT; 379 break; 380 } 381 a = display.cursor_address | LCD_Addr; 382 spin_lock_irqsave(&lcd_lock, flags); 383 lcddev_write_inst(a); 384 spin_unlock_irqrestore(&lcd_lock, flags); 385 break; 386 387 /* Get the value at the current cursor position? - TJS */ 388 case LCD_Get_Cursor: 389 spin_lock_irqsave(&lcd_lock, flags); 390 display.character = lcddev_read_data(); 391 lcddev_write_inst(0x10); 392 spin_unlock_irqrestore(&lcd_lock, flags); 393 if (copy_to_user((struct lcd_display *)arg, &display, dlen)) { 394 r = -EFAULT; 395 } 396 break; 397 398 /* Set the character at the cursor position? - TJS */ 399 case LCD_Set_Cursor: 400 if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) { 401 r = -EFAULT; 402 break; 403 } 404 spin_lock_irqsave(&lcd_lock, flags); 405 lcddev_write_data(display.character); 406 lcddev_write_inst(0x10); 407 spin_unlock_irqrestore(&lcd_lock, flags); 408 break; 409 410 /* Dunno what this does - TJS */ 411 case LCD_Disp_Left: 412 spin_lock_irqsave(&lcd_lock, flags); 413 lcddev_write_inst(0x18); 414 spin_unlock_irqrestore(&lcd_lock, flags); 415 break; 416 417 /* Dunno what this does - TJS */ 418 case LCD_Disp_Right: 419 spin_lock_irqsave(&lcd_lock, flags); 420 lcddev_write_inst(0x1C); 421 spin_unlock_irqrestore(&lcd_lock, flags); 422 break; 423 424 /* Dunno what this does - TJS */ 425 case LCD_Home: 426 spin_lock_irqsave(&lcd_lock, flags); 427 lcddev_write_inst(0x02); 428 spin_unlock_irqrestore(&lcd_lock, flags); 429 break; 430 431 /* Write a string to the LCD */ 432 case LCD_Write: 433 if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) { 434 r = -EFAULT; 435 break; 436 } 437 438 spin_lock_irqsave(&lcd_lock, flags); 439 440 display.size1 = display.size1 > 0 ? 441 min(display.size1, (int) sizeof(display.line1)) : 0; 442 display.size2 = display.size2 > 0 ? 443 min(display.size2, (int) sizeof(display.line2)) : 0; 444 445 /* First line */ 446 lcddev_write_inst(0x80); 447 for (index = 0; index < display.size1; index++) 448 lcddev_write_data(display.line1[index]); 449 for (index = display.size1; index < sizeof(display.line1); index++) 450 lcddev_write_data(' '); 451 452 /* Second line */ 453 lcddev_write_inst(0xC0); 454 for (index = 0; index < display.size2; index++) 455 lcddev_write_data(display.line2[index]); 456 for (index = display.size2; index < sizeof(display.line2); index++) 457 lcddev_write_data(' '); 458 459 spin_unlock_irqrestore(&lcd_lock, flags); 460 break; 461 462 /* Read what's on the LCD */ 463 case LCD_Read: 464 spin_lock_irqsave(&lcd_lock, flags); 465 466 for (address = DD_R00; address <= DD_R01; address++) { 467 lcddev_write_inst(address | LCD_Addr); 468 display.line1[address] = lcddev_read_data(); 469 } 470 for (address = DD_R10; address <= DD_R11; address++) { 471 lcddev_write_inst(address | LCD_Addr); 472 display.line2[address - DD_R10] = lcddev_read_data(); 473 } 474 475 spin_unlock_irqrestore(&lcd_lock, flags); 476 477 display.line1[DD_R01] = '\0'; 478 display.line2[DD_R01] = '\0'; 479 480 if (copy_to_user((struct lcd_display *)arg, &display, dlen)) { 481 r = -EFAULT; 482 } 483 break; 484 485 case LCD_Raw_Inst: 486 if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) { 487 r = -EFAULT; 488 break; 489 } 490 spin_lock_irqsave(&lcd_lock, flags); 491 lcddev_write_inst(display.character); 492 spin_unlock_irqrestore(&lcd_lock, flags); 493 break; 494 495 case LCD_Raw_Data: 496 if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) { 497 r = -EFAULT; 498 break; 499 } 500 spin_lock_irqsave(&lcd_lock, flags); 501 lcddev_write_data(display.character); 502 spin_unlock_irqrestore(&lcd_lock, flags); 503 break; 504 505 case LCD_Type: 506 if (cobt_is_5k() && has_i2c_lcd) { 507 if (put_user(LCD_TYPE_I2C, (int *)arg)) { 508 r = -EFAULT; 509 } 510 } else if (cobt_is_3k() || (cobt_is_5k() && !has_i2c_lcd)) { 511 if (put_user(LCD_TYPE_PARALLEL_B, (int *)arg)) { 512 r = -EFAULT; 513 } 514 } 515 break; 516 517 /* Read the buttons */ 518 case BUTTON_Read: 519 spin_lock_irqsave(&lcd_lock, flags); 520 button_display.buttons = read_buttons(); 521 spin_unlock_irqrestore(&lcd_lock, flags); 522 if (copy_to_user((struct lcd_display *)arg, 523 &button_display, dlen)) { 524 r = -EFAULT; 525 } 526 break; 527 528 #ifdef CONFIG_COBALT_LED 529 /* a slightly different api that allows you to set 32 leds */ 530 case LED32_Set: 531 cobalt_led_set_lazy(arg); 532 break; 533 534 case LED32_Bit_Set: 535 cobalt_led_set_bits_lazy(arg); 536 break; 537 538 case LED32_Bit_Clear: 539 cobalt_led_clear_bits_lazy(arg); 540 break; 541 542 case LED32_Get: 543 *(unsigned int *)arg = cobalt_led_get(); 544 break; 545 546 /* set all the leds */ 547 case LED_Set: 548 if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) { 549 r = -EFAULT; 550 break; 551 } 552 cobalt_led_set_lazy(display.leds); 553 break; 554 555 /* set a single led */ 556 case LED_Bit_Set: 557 if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) { 558 r = -EFAULT; 559 break; 560 } 561 cobalt_led_set_bits_lazy(display.leds); 562 break; 563 564 /* clear an led */ 565 case LED_Bit_Clear: 566 if (copy_from_user(&display, (struct lcd_display *)arg, dlen)) { 567 r = -EFAULT; 568 break; 569 } 570 cobalt_led_clear_bits_lazy(display.leds); 571 break; 572 #endif 573 574 default: 575 break; 576 } 577 578 return r; 579 } 580 581 static int 582 cobalt_lcd_open(struct inode *inode, struct file *file) 583 { 584 if (!lcd_present) { 585 return -ENXIO; 586 } else { 587 return 0; 588 } 589 } 590 591 /* LCD daemon sits on this, we wake it up once a key is pressed */ 592 static ssize_t 593 cobalt_lcd_read(struct file *file, char *buf, size_t count, loff_t *ppos) 594 { 595 int bnow; 596 static unsigned long lcd_waiters; 597 598 if (test_and_set_bit(0, &lcd_waiters)) { 599 return -EINVAL; 600 } 601 602 while (((bnow = button_pressed()) == 0) && !(signal_pending(current))) { 603 if (file->f_flags & O_NONBLOCK) { 604 lcd_waiters = 0; 605 return -EAGAIN; 606 } 607 set_current_state(TASK_INTERRUPTIBLE); 608 schedule_timeout(2 * HZ); 609 } 610 lcd_waiters = 0; 611 612 if (signal_pending(current)) { 613 return -ERESTARTSYS; 614 } 615 616 return bnow; 617 } 618 619 /* read a single line from the LCD into a string */ 620 static char * 621 cobalt_lcddev_read_line(int lineno, char *line) 622 { 623 unsigned long addr, min, max; 624 unsigned long flags; 625 626 switch (lineno) { 627 case 0: 628 min = DD_R00; 629 max = DD_R01; 630 break; 631 case 1: 632 min = DD_R10; 633 max = DD_R11; 634 break; 635 default: 636 min = 1; 637 max = 0; 638 } 639 640 spin_lock_irqsave(&lcd_lock, flags); 641 for (addr = min; addr <= max; addr++) { 642 lcddev_write_inst(addr | LCD_Addr); 643 udelay(150); 644 line[addr-min] = lcddev_read_data(); 645 udelay(150); 646 } 647 spin_unlock_irqrestore(&lcd_lock, flags); 648 line[addr-min] = '\0'; 649 650 return line; 651 } 652 653 #ifdef CONFIG_PROC_FS 654 static int 655 cobalt_lcd_read_proc(char *buf, char **start, off_t pos, 656 int len, int *eof, void *private) 657 { 658 int plen = 0; 659 char line[COBALT_LCD_LINELEN+1]; 660 661 /* first line */ 662 cobalt_lcddev_read_line(0, line); 663 plen += sprintf(buf+plen, "%s\n", line); 664 665 /* second line */ 666 cobalt_lcddev_read_line(1, line); 667 plen += sprintf(buf+plen, "%s\n", line); 668 669 return cobalt_gen_proc_read(buf, plen, start, pos, len, eof); 670 } 671 #endif 672 673 static char *lcd_panic_str1 = "Kernel"; 674 static char *lcd_panic_str2 = "Panic!"; 675 676 static int cobalt_lcd_panic(struct notifier_block *self, unsigned long a, void *b) 677 { 678 int i; 679 int len; 680 681 if( !lcd_present ) 682 return 0; 683 684 #ifdef CONFIG_COBALT_LCD_TWIDDLE 685 cobalt_lcd_stop_twiddle(); 686 #endif 687 688 lcddev_write_inst( (DD_R00) | LCD_Addr); 689 len = strlen( lcd_panic_str1 ); 690 for( i=0 ; i<16 ; i++ ) 691 lcddev_write_data( (i<len)?lcd_panic_str1[i]:' ' ); 692 693 lcddev_write_inst( (DD_R10) | LCD_Addr); 694 len = strlen( lcd_panic_str2 ); 695 for( i=0 ; i<16 ; i++ ) 696 lcddev_write_data( (i<len)?lcd_panic_str2[i]:' ' ); 697 698 return 0; 699 } 700 701 #ifdef CONFIG_COBALT_LCD_TWIDDLE 702 static struct timer_list twiddle_timer; 703 static int twiddling; 704 static void 705 twiddle_timer_func(unsigned long data) 706 { 707 static int state=1; 708 static int pos=0; 709 unsigned long flags; 710 711 spin_lock_irqsave(&lcd_lock, flags); 712 713 lcddev_write_inst((DD_R10+4+pos) | LCD_Addr); 714 lcddev_write_data(' '); 715 716 pos += state; 717 if (pos < 0) { 718 state = 1; 719 pos = 1; 720 } 721 if (pos > 11) { 722 state = -1; 723 pos = 10; 724 } 725 726 lcddev_write_inst((DD_R10+4+pos) | LCD_Addr); 727 lcddev_write_data(0xff); 728 729 spin_unlock_irqrestore(&lcd_lock, flags); 730 731 mod_timer(&twiddle_timer, jiffies + TWIDDLE_HZ); 732 } 733 734 void 735 cobalt_lcd_start_twiddle(void) 736 { 737 init_timer(&twiddle_timer); 738 twiddle_timer.expires = jiffies + TWIDDLE_HZ; 739 twiddle_timer.data = 0; 740 twiddle_timer.function = &twiddle_timer_func; 741 add_timer(&twiddle_timer); 742 twiddling=1; 743 } 744 745 void 746 cobalt_lcd_stop_twiddle(void) 747 { 748 unsigned long flags; 749 750 spin_lock_irqsave(&lcd_lock, flags); 751 if (twiddling) { 752 del_timer_sync(&twiddle_timer); 753 twiddling = 0; 754 } 755 spin_unlock_irqrestore(&lcd_lock, flags); 756 } 757 #endif /* CONFIG_COBALT_LCD_TWIDDLE */ 758 759 /* stop the lcd */ 760 void cobalt_lcd_off(void) 761 { 762 unsigned long flags; 763 764 spin_lock_irqsave(&lcd_lock, flags); 765 lcddev_write_inst(0x01); /* clear */ 766 lcddev_write_inst(0x08); /* off */ 767 spin_unlock_irqrestore(&lcd_lock, flags); 768 } 769 770 static int initialized; 771 static struct notifier_block lcd_nb; 772 773 int __init 774 cobalt_lcd_init(void) 775 { 776 int retval; 777 778 if (initialized) 779 return 0; 780 781 initialized=1; 782 printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", LCD_DRIVER,LCD_DRIVER_VMAJ,LCD_DRIVER_VMIN); 783 784 if (disable_lcd) { 785 printk(KERN_INFO "%s DISABLED\n", LCD_DRIVER); 786 return 0; 787 } 788 789 retval = misc_register(&lcd_dev); 790 791 if (cobt_is_monterey() 792 && (cobalt_i2c_read_byte(COBALT_I2C_DEV_LCD_INST, 0) != 0xff)) { 793 printk(KERN_INFO " - LCD is an I2C device\n"); 794 has_i2c_lcd = 1; 795 } else { 796 has_i2c_lcd = 0; 797 } 798 799 /* flag ourselves as present */ 800 lcd_present = 1; 801 802 /* initialize the device */ 803 lcddev_init(); 804 805 #ifdef CONFIG_PROC_FS 806 #ifdef CONFIG_COBALT_OLDPROC 807 /* create /proc/lcd */ 808 proc_lcd = create_proc_read_entry("lcd", S_IRUSR, NULL, 809 cobalt_lcd_read_proc, NULL); 810 if (!proc_lcd) { 811 EPRINTK("can't create /proc/lcd\n"); 812 } 813 #endif 814 proc_clcd = create_proc_read_entry("lcd", S_IRUSR, proc_cobalt, 815 cobalt_lcd_read_proc, NULL); 816 if (!proc_clcd) { 817 EPRINTK("can't create /proc/cobalt/lcd\n"); 818 } 819 #endif 820 821 #ifdef CONFIG_COBALT_LCD_TWIDDLE 822 cobalt_lcd_start_twiddle(); 823 #endif 824 825 /* register panic notifier */ 826 lcd_nb.notifier_call = cobalt_lcd_panic; 827 lcd_nb.next = NULL; 828 lcd_nb.priority = 0; 829 830 atomic_notifier_chain_register( &panic_notifier_list, &lcd_nb ); 831 832 return 0; 833 } 834 835 #endif /* CONFIG_COBALT_LCD */ -
drivers/cobalt/led.c
diff -Naur linux-2.6.20.orig/drivers/cobalt/led.c linux-2.6.20/drivers/cobalt/led.c
old new 1 /* 2 * $Id: led.c,v 1.36 2002/05/10 18:44:45 duncan Exp $ 3 * led.c : driver for Cobalt LEDs 4 * 5 * Copyright 1996-2000 Cobalt Networks, Inc. 6 * Copyright 2001 Sun Microsystems, Inc. 7 * 8 * By: Andrew Bose 9 * Timothy Stonis 10 * Tim Hockin 11 * Adrian Sun 12 * Duncan Laurie 13 * 14 * Modified By: jeff@404ster.com 15 * 16 * This should be SMP safe. There is one definite critical region: the 17 * handler list (led_handler_lock). The led_state is protected by led_lock, 18 * so should be safe against simultaneous writes. Bit banging of lights is 19 * currently also a protected region (led_lock, rather than add a new lock). 20 */ 21 22 #include <linux/config.h> 23 24 #ifdef CONFIG_COBALT_LED 25 26 #include <linux/module.h> 27 #include <linux/types.h> 28 #include <linux/errno.h> 29 #include <linux/miscdevice.h> 30 #include <linux/slab.h> 31 #include <linux/ioport.h> 32 #include <linux/fcntl.h> 33 #include <linux/netdevice.h> 34 #include <linux/pci.h> 35 #include <linux/init.h> 36 #include <linux/timer.h> 37 #include <linux/nvram.h> 38 #include <asm/io.h> 39 #include <linux/delay.h> 40 41 #include <cobalt/cobalt.h> 42 #include <cobalt/systype.h> 43 #include <cobalt/led.h> 44 #include <cobalt/i2c.h> 45 #include <cobalt/superio.h> 46 47 #define LED_DRIVER "Cobalt Networks LED driver" 48 #define LED_DRIVER_VMAJ 1 49 #define LED_DRIVER_VMIN 0 50 51 /* the rate at which software controlled frontpanel LEDs blink */ 52 #define FPLED_DEFAULT_HZ (HZ/20) 53 54 /* 55 * This is the abstracted state of active LEDs - see the defines for LED_* 56 * LED masks are always 'unsigned int'. You must hold led_lock to muck with 57 * these. 58 */ 59 static unsigned int led_state; 60 static unsigned int led_blips; 61 62 /* leds are PCI on genIII */ 63 static struct pci_dev *led_dev; 64 /* on XTR the front panel LEDs are software controlled */ 65 struct led_handler { 66 unsigned int (*function)(void *); 67 void *data; 68 struct led_handler *next; 69 struct led_handler *prev; 70 }; 71 struct led_handler *led_handler_list; 72 static spinlock_t led_handler_lock = SPIN_LOCK_UNLOCKED; 73 static struct timer_list timer; 74 75 static spinlock_t led_lock = SPIN_LOCK_UNLOCKED; 76 77 /* 78 * RaQ 3 79 * RaQ 4 80 * Qube 3 81 */ 82 #define RAQ3_SHUTLOGO_ADDR 0x7e 83 #define RAQ3_SHUTDOWN_OFF 0x40 /* reverse polarity */ 84 #define RAQ3_COBALTLOGO_ON 0x80 85 #define QUBE3_LIGHTBAR_ON 0xc0 /* direct polarity */ 86 #define RAQ3_WEBLIGHT_ADDR 0xb8 87 #define RAQ3_WEBLIGHT_ON 0x80 88 89 /* 90 * RaQ XTR 91 */ 92 #define MONTEREY_FPLED00 0x8000 93 #define MONTEREY_FPLED01 0x4000 94 #define MONTEREY_FPLED02 0x2000 95 #define MONTEREY_FPLED03 0x0200 96 #define MONTEREY_FPLED04 0x0080 97 #define MONTEREY_FPLED05 0x0040 98 #define MONTEREY_FPLED10 0x1000 99 #define MONTEREY_FPLED11 0x0800 100 #define MONTEREY_FPLED12 0x0400 101 #define MONTEREY_FPLED13 0x0100 102 #define MONTEREY_FPLED14 0x0020 103 #define MONTEREY_FPLED15 0x0010 104 #define MONTEREY_FPLED_ETH0_TXRX MONTEREY_FPLED00 105 #define MONTEREY_FPLED_ETH0_LINK MONTEREY_FPLED10 106 #define MONTEREY_FPLED_ETH1_TXRX MONTEREY_FPLED01 107 #define MONTEREY_FPLED_ETH1_LINK MONTEREY_FPLED11 108 #define MONTEREY_FPLED_DISK0 MONTEREY_FPLED02 109 #define MONTEREY_FPLED_DISK1 MONTEREY_FPLED03 110 #define MONTEREY_FPLED_DISK2 MONTEREY_FPLED04 111 #define MONTEREY_FPLED_DISK3 MONTEREY_FPLED05 112 #define MONTEREY_FPLED_WEB MONTEREY_FPLED12 113 #define MONTEREY_LOGOLED_BIT 0x40 114 #define MONTEREY_SYSFAULTLED_BIT 0x80 115 #define MONTEREY_SLED0 (1<<3) 116 #define MONTEREY_SLED1 (1<<2) 117 #define MONTEREY_SLED2 (1<<1) 118 #define MONTEREY_SLED3 (1<<0) 119 120 /* 121 * Alpine 122 */ 123 #define ALPINE_WEBLED_PORT 0x60e 124 #define ALPINE_WEBLED_BIT 0x20 125 #define ALPINE_POWERLED_PORT 0x50b 126 #define ALPINE_POWERLED_CFG 0x23 127 #define ALPINE_LOGOLED_BIT 0x02 128 #define ALPINE_SYSFAULTLED_BIT 0x07 129 130 /* 131 * actually set the leds (icky details hidden within) 132 * this must be protected against itself with led_lock 133 * */ 134 static void 135 __set_led_hw(const unsigned int newstate) 136 { 137 if (cobt_is_pacifica() && led_dev) { 138 unsigned char tmp; 139 /* RaQ 3, RaQ 4 140 * - shutdown light 141 * - logo light 142 * - web light 143 */ 144 145 /* read the current state of shutdown/logo lights */ 146 pci_read_config_byte(led_dev, RAQ3_SHUTLOGO_ADDR, &tmp); 147 148 /* reverse polarity for shutdown light */ 149 if (newstate & LED_SHUTDOWN) 150 tmp &= ~RAQ3_SHUTDOWN_OFF; 151 else 152 tmp |= RAQ3_SHUTDOWN_OFF; 153 154 /* logo light is straight forward */ 155 if (newstate & LED_COBALTLOGO) 156 tmp |= RAQ3_COBALTLOGO_ON; 157 else 158 tmp &= ~RAQ3_COBALTLOGO_ON; 159 160 /* write new shutdown/logo light state */ 161 pci_write_config_byte(led_dev, RAQ3_SHUTLOGO_ADDR, tmp); 162 163 /* read web light state */ 164 pci_read_config_byte(led_dev, RAQ3_WEBLIGHT_ADDR, &tmp); 165 if (newstate & LED_WEBLIGHT) { 166 tmp |= RAQ3_WEBLIGHT_ON; 167 } else { 168 tmp &= ~RAQ3_WEBLIGHT_ON; 169 } 170 171 /* write new web light state */ 172 pci_write_config_byte(led_dev, RAQ3_WEBLIGHT_ADDR, tmp); 173 } else if (cobt_is_carmel() && led_dev) { 174 unsigned char tmp; 175 /* Qube 3 176 * - no shutdown light 177 * - lightbar instead of logo 178 * - no web led (wired to 2nd IDE reset for staggered startup) 179 */ 180 181 /* read the current state of lightbar */ 182 pci_read_config_byte(led_dev, RAQ3_SHUTLOGO_ADDR, &tmp); 183 if (newstate & LED_COBALTLOGO) { 184 tmp |= QUBE3_LIGHTBAR_ON; 185 } else { 186 tmp &= ~QUBE3_LIGHTBAR_ON; 187 } 188 189 /* write new lightbar state */ 190 pci_write_config_byte(led_dev, RAQ3_SHUTLOGO_ADDR, tmp); 191 } else if (cobt_is_monterey()) { 192 unsigned int tmp = 0; 193 u8 val; 194 unsigned long flags; 195 196 if (newstate & LED_WEBLIGHT) { 197 tmp |= MONTEREY_FPLED_WEB; 198 } 199 if (newstate & LED_ETH0_TXRX) { 200 tmp |= MONTEREY_FPLED_ETH0_TXRX; 201 } 202 if (newstate & LED_ETH0_LINK) { 203 tmp |= MONTEREY_FPLED_ETH0_LINK; 204 } 205 if (newstate & LED_ETH1_TXRX) { 206 tmp |= MONTEREY_FPLED_ETH1_TXRX; 207 } 208 if (newstate & LED_ETH1_LINK) { 209 tmp |= MONTEREY_FPLED_ETH1_LINK; 210 } 211 if (newstate & LED_DISK0) { 212 tmp |= MONTEREY_FPLED_DISK0; 213 } 214 if (newstate & LED_DISK1) { 215 tmp |= MONTEREY_FPLED_DISK1; 216 } 217 if (newstate & LED_DISK2) { 218 tmp |= MONTEREY_FPLED_DISK2; 219 } 220 if (newstate & LED_DISK3) { 221 tmp |= MONTEREY_FPLED_DISK3; 222 } 223 /* 3 LED's are unused on Monterey, but we support them */ 224 if (newstate & LED_MONTEREY_UNUSED0) { 225 tmp |= MONTEREY_FPLED13; 226 } 227 if (newstate & LED_MONTEREY_UNUSED1) { 228 tmp |= MONTEREY_FPLED14; 229 } 230 if (newstate & LED_MONTEREY_UNUSED2) { 231 tmp |= MONTEREY_FPLED15; 232 } 233 /* I2C controlled front-panel lights */ 234 cobalt_i2c_write_byte(COBALT_I2C_DEV_LED_I, 0, tmp & 0xff); 235 cobalt_i2c_write_byte(COBALT_I2C_DEV_LED_II, 0, tmp >> 8); 236 237 /* drive sled LEDs are on a different i2c device */ 238 tmp = 0xf0; /* high nibble means something else */ 239 if (newstate * LED_SLED0) 240 tmp |= MONTEREY_SLED0; 241 if (newstate * LED_SLED1) 242 tmp |= MONTEREY_SLED1; 243 if (newstate * LED_SLED2) 244 tmp |= MONTEREY_SLED2; 245 if (newstate * LED_SLED3) 246 tmp |= MONTEREY_SLED3; 247 cobalt_i2c_write_byte(COBALT_I2C_DEV_RULER, 0, tmp); 248 249 /* sysfault and logo are in APC page of nvram */ 250 spin_lock_irqsave(&rtc_lock, flags); 251 superio_set_rtc_bank(PC87317_RTC_BANK_APC); 252 val = CMOS_READ(PC87317_APCR4); 253 254 /* reverse polarity */ 255 if (newstate & LED_COBALTLOGO) { 256 val &= ~MONTEREY_LOGOLED_BIT; /* logo is on */ 257 } else { 258 val |= MONTEREY_LOGOLED_BIT; /* logo is off */ 259 } 260 261 if (newstate & LED_SYSFAULT) { 262 val |= MONTEREY_SYSFAULTLED_BIT; 263 } else { 264 val &= ~MONTEREY_SYSFAULTLED_BIT; 265 } 266 267 CMOS_WRITE(val, PC87317_APCR4); 268 superio_set_rtc_bank(PC87317_RTC_BANK_MAIN); 269 spin_unlock_irqrestore(&rtc_lock, flags); 270 } else if (cobt_is_alpine()) { 271 unsigned char val; 272 273 /* web LED is reverse polarity */ 274 val = inb(ALPINE_WEBLED_PORT); 275 if (newstate & LED_WEBLIGHT) { 276 val &= ~ALPINE_WEBLED_BIT; 277 } else { 278 val |= ALPINE_WEBLED_BIT; 279 } 280 outb(val, ALPINE_WEBLED_PORT); 281 282 /* 283 * the power led is controled by switching the pin between 284 * a GPIO pin (on) and a LED pin (off) 285 */ 286 287 outb( ALPINE_POWERLED_CFG, 0x2e ); 288 val = inb( 0x2f ); 289 if (newstate & LED_COBALTLOGO) { 290 val &= ~ALPINE_LOGOLED_BIT; 291 } else { 292 val |= ALPINE_LOGOLED_BIT; 293 } 294 outb( val, 0x2f ); 295 296 if (newstate & LED_SYSFAULT) { 297 val = ALPINE_SYSFAULTLED_BIT; 298 } else { 299 val = 0; 300 } 301 302 outb(val, ALPINE_POWERLED_PORT); 303 } 304 } 305 306 /* blip the front panel leds */ 307 static void 308 led_timer_func(unsigned long data) 309 { 310 unsigned int leds = 0; 311 struct led_handler *p; 312 unsigned long flags; 313 314 /* call all registered callbacks */ 315 spin_lock_irqsave(&led_handler_lock, flags); 316 for (p = led_handler_list; p; p = p->next) { 317 leds |= p->function(p->data); 318 } 319 spin_unlock_irqrestore(&led_handler_lock, flags); 320 321 /* set the led hardware */ 322 spin_lock_irqsave(&led_lock, flags); 323 __set_led_hw(led_state | leds | led_blips); 324 led_blips = 0; 325 spin_unlock_irqrestore(&led_lock, flags); 326 327 /* re-arm ourself */ 328 mod_timer(&timer, jiffies + FPLED_DEFAULT_HZ); 329 } 330 331 static void 332 __cobalt_led_set(const unsigned int leds) 333 { 334 led_state = leds; 335 __set_led_hw(leds); 336 } 337 338 void 339 cobalt_led_set(const unsigned int leds) 340 { 341 unsigned long flags; 342 spin_lock_irqsave(&led_lock, flags); 343 __cobalt_led_set(leds); 344 spin_unlock_irqrestore(&led_lock, flags); 345 } 346 347 void 348 cobalt_led_set_bits(const unsigned int leds) 349 { 350 unsigned long flags; 351 spin_lock_irqsave(&led_lock, flags); 352 __cobalt_led_set(led_state | leds); 353 spin_unlock_irqrestore(&led_lock, flags); 354 } 355 356 void 357 cobalt_led_clear_bits(const unsigned int leds) 358 { 359 unsigned long flags; 360 spin_lock_irqsave(&led_lock, flags); 361 __cobalt_led_set(led_state & ~leds); 362 spin_unlock_irqrestore(&led_lock, flags); 363 } 364 365 static void 366 __cobalt_led_set_lazy(const unsigned int leds) 367 { 368 /* the next led timer run will catch these changes */ 369 led_state = leds; 370 /* remember lights that were 'blipped' to force an edge */ 371 led_blips |= leds; 372 } 373 374 void 375 cobalt_led_set_lazy(const unsigned int leds) 376 { 377 unsigned long flags; 378 spin_lock_irqsave(&led_lock, flags); 379 __cobalt_led_set_lazy(leds); 380 spin_unlock_irqrestore(&led_lock, flags); 381 } 382 383 void 384 cobalt_led_set_bits_lazy(const unsigned int leds) 385 { 386 unsigned long flags; 387 spin_lock_irqsave(&led_lock, flags); 388 __cobalt_led_set_lazy(led_state | leds); 389 spin_unlock_irqrestore(&led_lock, flags); 390 } 391 392 void 393 cobalt_led_clear_bits_lazy(const unsigned int leds) 394 { 395 unsigned long flags; 396 spin_lock_irqsave(&led_lock, flags); 397 __cobalt_led_set_lazy(led_state & ~leds); 398 spin_unlock_irqrestore(&led_lock, flags); 399 } 400 401 unsigned int 402 cobalt_led_get(void) 403 { 404 unsigned int r; 405 unsigned long flags; 406 407 spin_lock_irqsave(&led_lock, flags); 408 r = led_state; 409 spin_unlock_irqrestore(&led_lock, flags); 410 411 return r; 412 } 413 414 int 415 cobalt_fpled_register(unsigned int (*function)(void *), void *data) 416 { 417 struct led_handler *newh; 418 unsigned long flags; 419 420 newh = kmalloc(sizeof(*newh), GFP_ATOMIC); 421 if (!newh) { 422 EPRINTK("can't allocate memory for handler %p(%p)\n", 423 function, data); 424 return -1; 425 } 426 427 spin_lock_irqsave(&led_handler_lock, flags); 428 429 /* head insert */ 430 newh->function = function; 431 newh->data = data; 432 newh->next = led_handler_list; 433 newh->prev = NULL; 434 if (led_handler_list) { 435 led_handler_list->prev = newh; 436 } 437 led_handler_list = newh; 438 439 spin_unlock_irqrestore(&led_handler_lock, flags); 440 441 return 0; 442 } 443 444 int 445 cobalt_fpled_unregister(unsigned int (*function)(void *), void *data) 446 { 447 int r = -1; 448 struct led_handler *p; 449 unsigned long flags; 450 451 spin_lock_irqsave(&led_handler_lock, flags); 452 453 for (p = led_handler_list; p; p = p->next) { 454 if (p->function == function && p->data == data) { 455 if (p->prev) { 456 p->prev->next = p->next; 457 } 458 if (p->next) { 459 p->next->prev = p->prev; 460 } 461 r = 0; 462 break; 463 } 464 } 465 466 spin_unlock_irqrestore(&led_handler_lock, flags); 467 468 return r; 469 } 470 471 int __init 472 cobalt_led_init(void) 473 { 474 unsigned int leds = LED_SHUTDOWN | LED_COBALTLOGO; 475 476 printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", LED_DRIVER,LED_DRIVER_VMAJ,LED_DRIVER_VMIN); 477 478 if (cobt_is_3k()) { 479 /* LEDs for RaQ3/4 and Qube3 are on the PMU */ 480 led_dev = pci_find_device(PCI_VENDOR_ID_AL, 481 PCI_DEVICE_ID_AL_M7101, NULL); 482 if (!led_dev) { 483 EPRINTK("can't find PMU for LED control\n"); 484 return -1; 485 } 486 } 487 488 /* setup up timer for fp leds */ 489 init_timer(&timer); 490 timer.expires = jiffies + FPLED_DEFAULT_HZ; 491 timer.data = 0; 492 timer.function = &led_timer_func; 493 add_timer(&timer); 494 495 /* set the initial state */ 496 leds |= cobalt_cmos_read_flag(COBT_CMOS_SYSFAULT_FLAG) ? 497 LED_SYSFAULT : 0; 498 led_state = leds; 499 __set_led_hw(leds); 500 501 return 0; 502 } 503 504 #endif /* CONFIG_COBALT_LED */ -
drivers/cobalt/net.c
diff -Naur linux-2.6.20.orig/drivers/cobalt/net.c linux-2.6.20/drivers/cobalt/net.c
old new 1 /* 2 * cobalt net wrappers 3 * Copyright (c) 2000, Cobalt Networks, Inc. 4 * Copyright (c) 2001, Sun Microsystems, Inc. 5 * $Id: net.c,v 1.11 2001/10/27 00:40:24 thockin Exp $ 6 * author: thockin@sun.com 7 * 8 * This should be SMP safe. The only critical data is the list of devices. 9 * The LED handler runs at timer-interrupt, so we must use the IRQ safe forms 10 * of the locks. --TPH 11 */ 12 13 #include <stdarg.h> 14 #include <stddef.h> 15 #include <linux/init.h> 16 #include <linux/config.h> 17 #include <linux/pci.h> 18 #include <linux/ioport.h> 19 #include <linux/netdevice.h> 20 #include <asm/io.h> 21 22 #include <cobalt/cobalt.h> 23 #include <cobalt/net.h> 24 #include <cobalt/led.h> 25 26 #define MAX_COBT_NETDEVS 2 27 static struct net_device *netdevs[MAX_COBT_NETDEVS]; 28 static int n_netdevs; 29 static spinlock_t cobaltnet_lock = SPIN_LOCK_UNLOCKED; 30 31 #if defined(CONFIG_COBALT_LED) 32 static unsigned int 33 net_led_handler(void *data) 34 { 35 int i; 36 unsigned int leds = 0; 37 static int txrxmap[MAX_COBT_NETDEVS] = {LED_ETH0_TXRX, LED_ETH1_TXRX}; 38 static int linkmap[MAX_COBT_NETDEVS] = {LED_ETH0_LINK, LED_ETH1_LINK}; 39 unsigned long flags; 40 static unsigned long net_old[MAX_COBT_NETDEVS]; 41 42 spin_lock_irqsave(&cobaltnet_lock, flags); 43 44 for (i = 0; i < n_netdevs; i++) { 45 unsigned long txrxstate; 46 struct net_device *dev = netdevs[i]; 47 if (!dev) { 48 continue; 49 } 50 /* check for link */ 51 if (netif_running(dev) && netif_carrier_ok(dev)) { 52 leds |= linkmap[i]; 53 } 54 /* check for tx/rx */ 55 txrxstate = dev->trans_start ^ dev->last_rx; 56 if (txrxstate != net_old[i]) { 57 leds |= txrxmap[i]; 58 net_old[i] = txrxstate; 59 } 60 } 61 62 spin_unlock_irqrestore(&cobaltnet_lock, flags); 63 64 return leds; 65 } 66 #endif 67 68 /* 69 * We try to be VERY explicit here. Fine for now, may eventually break down. 70 */ 71 void 72 cobalt_net_register(struct net_device *ndev) 73 { 74 unsigned long flags; 75 int i; 76 77 if (!ndev) { 78 return; 79 } 80 81 /* we'll track the first MAX_COBT_NETDEVS NICs */ 82 if (n_netdevs >= MAX_COBT_NETDEVS) { 83 return; 84 } 85 86 spin_lock_irqsave(&cobaltnet_lock, flags); 87 88 /* find a free slot */ 89 for (i = 0; i < MAX_COBT_NETDEVS; i++) { 90 if (!netdevs[i]) { 91 netdevs[i] = ndev; 92 n_netdevs++; 93 break; 94 } 95 } 96 97 spin_unlock_irqrestore(&cobaltnet_lock, flags); 98 } 99 100 void 101 cobalt_net_unregister(struct net_device *ndev) 102 { 103 int i; 104 unsigned long flags; 105 106 if (!ndev) { 107 return; 108 } 109 110 spin_lock_irqsave(&cobaltnet_lock, flags); 111 112 /* try to remove it from the list */ 113 for (i = 0; i < MAX_COBT_NETDEVS; i++) { 114 if (netdevs[i] == ndev) { 115 netdevs[i] = NULL; 116 n_netdevs--; 117 break; 118 } 119 } 120 121 spin_unlock_irqrestore(&cobaltnet_lock, flags); 122 } 123 124 int __init 125 cobalt_net_init(void) 126 { 127 #if defined(CONFIG_COBALT_LED) 128 /* register an LED handler */ 129 cobalt_fpled_register(net_led_handler, NULL); 130 #endif 131 132 return 0; 133 } -
drivers/cobalt/raminfo.c
diff -Naur linux-2.6.20.orig/drivers/cobalt/raminfo.c linux-2.6.20/drivers/cobalt/raminfo.c
old new 1 /* $Id: raminfo.c,v 1.7 2001/10/29 22:21:36 thockin Exp $ 2 * 3 * Copyright (c) 2000-2001 Sun Microsystems, Inc. 4 * All Rights Reserved. 5 * 6 * This is SMP safe - the init runs once on load, and the rest is just 7 * printing information. --TPH 8 */ 9 #include <linux/config.h> 10 11 #if defined(CONFIG_COBALT_RAMINFO) || defined(CONFIG_COBALT_RAMINFO_MODULE) 12 13 #include <linux/module.h> 14 #include <linux/init.h> 15 #include <linux/pci.h> 16 #include <linux/proc_fs.h> 17 18 #include <cobalt/cobalt.h> 19 #include <cobalt/systype.h> 20 21 #define RAM_DRIVER "Cobalt Networks RAM Info driver" 22 #define RAM_DRIVER_VMAJ 1 23 #define RAM_DRIVER_VMIN 0 24 25 #define MAX_DIMM_SLOTS 4 26 27 enum dimm_t { 28 DIMM_TYPE_FPM_DRAM, 29 DIMM_TYPE_EDO_DRAM, 30 DIMM_TYPE_REG_SDRAM, 31 DIMM_TYPE_SDRAM 32 }; 33 34 static char *dimm_desc[] = { 35 "Fast-page Mode DRAM", 36 "EDO DRAM", 37 "Registered SDRAM", 38 "SDRAM", 39 }; 40 41 struct dimm_slot { 42 int num; 43 enum dimm_t type; 44 uint16_t size; 45 int ecc; 46 }; 47 48 struct raminfo { 49 int total; 50 int (*query)(struct dimm_slot *); 51 struct pci_dev *dev; 52 struct dimm_slot *dimm; 53 #ifdef CONFIG_PROC_FS 54 struct proc_dir_entry *proc; 55 #endif /* CONFIG_PROC_FS */ 56 }; 57 58 /*########################################################################*/ 59 60 static int serverworks_le_dimm_info(struct dimm_slot *); 61 static int ali_1541_dimm_info(struct dimm_slot *); 62 static int raminfo_read_proc(char*, char**, off_t, int, int*, void*); 63 64 /* RaQ-3, RaQ-4, Qube-3 65 * - uses ALI M1541 for memory controller 66 * - has 2 dimm slots */ 67 static struct raminfo gen3_raminfo = { 68 total: 2, 69 query: ali_1541_dimm_info 70 }; 71 /* RaQ-XTR (Monterey) 72 * - uses ServerWorks CNB30LE for Memory Controller 73 * - has 4 dimm slots */ 74 static struct raminfo gen5_monterey_raminfo = { 75 total: 4, 76 query: serverworks_le_dimm_info 77 }; 78 /* RaQ (Alpine) 79 * - uses ServerWorks CNB30LE for Memory Controller 80 * - has 2 dimm slots */ 81 static struct raminfo gen5_alpine_raminfo = { 82 total: 2, 83 query: serverworks_le_dimm_info 84 }; 85 86 static struct raminfo *sys_raminfo; 87 88 /*########################################################################*/ 89 90 #define SERVERWORKS_DRAM_MRPR (0x90) 91 #define SERVERWORKS_DRAM_MRAR(slot) (0x7c + (slot)) 92 #define SERVERWORKS_DRAM_ECCR (0xe0) 93 94 static int 95 serverworks_le_dimm_info(struct dimm_slot *dimm) 96 { 97 int row; 98 uint8_t rar, active, eccr; 99 uint16_t ma_map[] = { 100 32, 16, 32, 256, 512, 128, 128, 64, 256, 128, 64, 64, 128, 101 }; 102 103 if (!sys_raminfo || !sys_raminfo->dev || !dimm) 104 return -ENOSYS; 105 106 pci_read_config_byte(sys_raminfo->dev, 107 SERVERWORKS_DRAM_MRPR, &active); 108 pci_read_config_byte(sys_raminfo->dev, 109 SERVERWORKS_DRAM_MRAR(dimm->num), &rar); 110 111 /* serverworks uses only registered sdram */ 112 dimm->type = DIMM_TYPE_REG_SDRAM; 113 dimm->size = 0; 114 115 /* check to see if ECC is enabled (bit 4 of reg 0xE0) */ 116 pci_read_config_byte(sys_raminfo->dev, 117 SERVERWORKS_DRAM_ECCR, &eccr); 118 dimm->ecc = (eccr & (1<<2)) ? 1 : 0; 119 120 /* two rows for each dimm slot */ 121 for (row=2*dimm->num; row<=(2*dimm->num+1); row++) { 122 /* each active row will have corresponding bit 123 * set in the Memory Row Presence Register */ 124 if (active & (1 << row)) { 125 /* lookup size ma_map table */ 126 dimm->size += ma_map[ rar & 0xf ]; 127 } 128 /* two rows per RAR register, bits 7-4 and bits 3-0 */ 129 rar >>= 4; 130 } 131 132 return 0; 133 } 134 135 #define ALI_DRAM_CONF_1(row) (0x60 + ((row) * 2)) 136 #define ALI_DRAM_CONF_2(row) (0x61 + ((row) * 2)) 137 #define ALI_DIMM_TYPE(d2) (((d2) >> 4) & 0x3) 138 #define ALI_DIMM_MMAP(d2) (((d2) >> 6) & 0x3) 139 #define ALI_DIMM_SIZE(d1, d2) (((((d2) & 0xf) << 8) | (d1)) + 1) 140 141 static int 142 ali_1541_dimm_info(struct dimm_slot *dimm) 143 { 144 int row; 145 uint8_t dbc1, dbc2; 146 147 if (!sys_raminfo || !sys_raminfo->dev || !dimm) 148 return -ENOSYS; 149 150 dimm->size = 0; 151 dimm->ecc = 0; 152 153 /* read two rows per dimm (for double-side) */ 154 for (row=2*dimm->num; row<=(2*dimm->num + 1); row++) { 155 pci_read_config_byte(sys_raminfo->dev, 156 ALI_DRAM_CONF_2(row), &dbc2); 157 158 /* row is empty iff dimm type and ma_map are both 0 */ 159 if (!ALI_DIMM_TYPE(dbc2) && !ALI_DIMM_MMAP(dbc2)) 160 continue; 161 162 pci_read_config_byte(sys_raminfo->dev, 163 ALI_DRAM_CONF_1(row), &dbc1); 164 165 /* type is bits 4-5 of dimm conf reg 2 */ 166 dimm->type = ALI_DIMM_TYPE(dbc2); 167 168 /* A27-A20 address lines are bits 7-0 of dimm conf reg 1 169 * A31-A28 address lines are bits 3-0 of dimm conf reg 2 */ 170 dimm->size = ALI_DIMM_SIZE(dbc1, dbc2); 171 } 172 173 /* the M1541 uses "not less than" policy to determine which row a 174 * memory address resides in. the top address boundary for each 175 * row is the maximum memory value minus 1. so to determine the 176 * size of a row you must subtract the size of the previous row. 177 * (unless this is slot 0 or the first populated slot) */ 178 if (dimm->num > 0 && dimm->size > 0) { 179 uint16_t sz; 180 pci_read_config_byte(sys_raminfo->dev, 181 ALI_DRAM_CONF_1(2*dimm->num - 1), &dbc1); 182 pci_read_config_byte(sys_raminfo->dev, 183 ALI_DRAM_CONF_2(2*dimm->num - 1), &dbc2); 184 sz = ALI_DIMM_SIZE(dbc1, dbc2); 185 dimm->size -= (sz > 1) ? sz : 0; 186 } 187 188 return 0; 189 } 190 191 int __init 192 cobalt_raminfo_init(void) 193 { 194 int j; 195 196 /* determine system type and find memory controller pci dev 197 * so we don't have to do pci lookup for each proc read */ 198 if (cobt_is_3k()) { 199 sys_raminfo = &gen3_raminfo; 200 sys_raminfo->dev = pci_find_device(PCI_VENDOR_ID_AL, 201 PCI_DEVICE_ID_AL_M1541, NULL); 202 } else if (cobt_is_5k()) { 203 if (cobt_is_monterey()) { 204 sys_raminfo = &gen5_monterey_raminfo; 205 } else if (cobt_is_alpine()) { 206 sys_raminfo = &gen5_alpine_raminfo; 207 } else { 208 EPRINTK("unable to identify gen5 board\n"); 209 return -ENOSYS; 210 } 211 sys_raminfo->dev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, 212 PCI_DEVICE_ID_SERVERWORKS_LE, NULL); 213 } 214 215 if (!sys_raminfo || !sys_raminfo->dev) { 216 EPRINTK("unable to identify system type\n"); 217 return -ENOSYS; 218 } 219 220 printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", RAM_DRIVER,RAM_DRIVER_VMAJ,RAM_DRIVER_VMIN); 221 222 #ifdef CONFIG_PROC_FS 223 /* add entry to /proc filesytem */ 224 sys_raminfo->proc = create_proc_entry("raminfo", 225 S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, proc_cobalt); 226 if (!sys_raminfo->proc) { 227 EPRINTK("can't create /proc/cobalt/raminfo\n"); 228 return -ENOENT; 229 } 230 sys_raminfo->proc->owner = THIS_MODULE; 231 sys_raminfo->proc->write_proc = NULL; 232 sys_raminfo->proc->read_proc = raminfo_read_proc; 233 #endif /* CONFIG_PROC_FS */ 234 235 /* create arrary of dimm slots to store info */ 236 sys_raminfo->dimm = kmalloc( 237 sys_raminfo->total * sizeof(struct dimm_slot), GFP_ATOMIC); 238 if (!sys_raminfo->dimm) { 239 EPRINTK("unable to allocate memory\n"); 240 #ifdef CONFIG_PROC_FS 241 if (sys_raminfo->proc) { 242 remove_proc_entry("raminfo", proc_cobalt); 243 sys_raminfo->proc = NULL; 244 } 245 #endif /* CONFIG_PROC_FS */ 246 return -ENOMEM; 247 } 248 249 { 250 struct dimm_slot *ds = sys_raminfo->dimm; 251 for (j=0; j<sys_raminfo->total; j++, ds++) { 252 if (!ds) continue; 253 ds->num = j; 254 if (sys_raminfo->query(ds) < 0) { 255 EPRINTK("unable to read dimm %d\n", j); 256 ds->num = -1; 257 } 258 } 259 } 260 261 return 0; 262 } 263 264 static void __exit 265 cobalt_raminfo_exit(void) 266 { 267 #ifdef CONFIG_PROC_FS 268 if (sys_raminfo->proc) { 269 remove_proc_entry("raminfo", proc_cobalt); 270 sys_raminfo->proc = NULL; 271 } 272 #endif /* CONFIG_PROC_FS */ 273 274 if (sys_raminfo->dimm) { 275 kfree(sys_raminfo->dimm); 276 sys_raminfo->dimm = NULL; 277 } 278 279 sys_raminfo->dev = NULL; 280 sys_raminfo = NULL; 281 } 282 283 #ifdef CONFIG_PROC_FS 284 static int 285 raminfo_read_proc(char *buf, char **st, off_t off, int len, int *eof, void *x) 286 { 287 int rlen, i; 288 struct dimm_slot *ds; 289 290 if (!sys_raminfo) 291 return -ENOSYS; 292 293 //MOD_INC_USE_COUNT; 294 295 ds = sys_raminfo->dimm; 296 for (rlen=i=0; i<sys_raminfo->total; i++, ds++) { 297 if (!ds || ds->num < 0) 298 continue; 299 rlen += sprintf(buf+rlen, "%d [%s%s]: %u MB\n", i, 300 ds->size ? dimm_desc[ds->type] : "Empty", 301 ds->size ? ds->ecc ? "+ECC" : "" : "", 302 ds->size); 303 } 304 305 //MOD_DEC_USE_COUNT; 306 307 return cobalt_gen_proc_read(buf, rlen, st, off, len, eof); 308 } 309 #endif /* CONFIG_PROC_FS */ 310 311 #ifdef CONFIG_COBALT_RAMINFO_MODULE 312 module_init(cobalt_raminfo_init); 313 module_exit(cobalt_raminfo_exit); 314 #endif 315 316 MODULE_AUTHOR("Sun Cobalt"); 317 MODULE_DESCRIPTION("DIMM Information"); 318 MODULE_LICENSE("GPL"); 319 320 #endif /* CONFIG_COBALT_RAMINFO || CONFIG_COBALT_RAMINFO_MODULE */ -
drivers/cobalt/ruler.c
diff -Naur linux-2.6.20.orig/drivers/cobalt/ruler.c linux-2.6.20/drivers/cobalt/ruler.c
old new 1 /* 2 * cobalt ruler driver 3 * Copyright (c) 2000, Cobalt Networks, Inc. 4 * Copyright (c) 2001, Sun Microsystems, Inc. 5 * $Id: ruler.c,v 1.23 2002/08/29 00:33:01 uzi Exp $ 6 * 7 * author: asun@cobalt.com, thockin@sun.com 8 * 9 * This should be SMP safe. There is one critical piece of data, and thus 10 * one lock. The ruler_lock protects the arrays of channels(hwifs) and 11 * busproc function pointers. These are only ever written in the 12 * register/unregister functions but read in several other places. A 13 * read/write lock is appropriate. The global switches and sled_leds are 14 * atomic_t. --TPH 15 */ 16 17 #include <stdarg.h> 18 #include <stddef.h> 19 #include <linux/init.h> 20 #include <linux/sched.h> 21 #include <linux/timer.h> 22 #include <linux/config.h> 23 #include <linux/pci.h> 24 #include <linux/proc_fs.h> 25 #include <linux/sched.h> 26 #include <linux/ioport.h> 27 #include <linux/ide.h> 28 #include <linux/hdreg.h> 29 #include <linux/notifier.h> 30 #include <linux/sysctl.h> 31 #include <linux/reboot.h> 32 #include <linux/delay.h> 33 #include <linux/ide.h> 34 #include <asm/io.h> 35 36 #include <cobalt/cobalt.h> 37 #include <cobalt/systype.h> 38 #include <cobalt/i2c.h> 39 #include <cobalt/acpi.h> 40 #include <cobalt/led.h> 41 #include <cobalt/ruler.h> 42 43 #define RULER_TIMEOUT (HZ >> 1) /* .5s */ 44 #define MAX_COBT_DRIVES 4 45 46 #define RULER_DRIVER "Cobalt Networks Disk Ruler driver" 47 #define RULER_DRIVER_VMAJ 1 48 #define RULER_DRIVER_VMIN 0 49 50 /* all of this is for gen V */ 51 static struct timer_list cobalt_ruler_timer; 52 static rwlock_t ruler_lock = RW_LOCK_UNLOCKED; 53 static ide_drive_t *channels[MAX_COBT_DRIVES]; 54 55 static int (*busprocs[MAX_COBT_DRIVES])(ide_drive_t *, int); 56 57 //static cob_busprocs_t busprocs[MAX_COBT_DRIVES]; 58 59 /* NOTE: switches is a bitmask of DETACHED sleds */ 60 static atomic_t switches = ATOMIC_INIT(0); 61 static atomic_t sled_leds = ATOMIC_INIT(0); 62 static int sled_led_map[] = {LED_SLED0, LED_SLED1, LED_SLED2, LED_SLED3}; 63 static int ruler_detect; 64 static int initialized; 65 66 static void ruler_hwif_added(ide_hwif_t *hwif, int idx); 67 68 static inline u8 69 read_switches(void) 70 { 71 u8 state = 0; 72 if (cobt_is_monterey()) { 73 int tries = 3; 74 75 /* i2c can be busy, and this can read wrong - try a few times */ 76 while (tries--) { 77 state = cobalt_i2c_read_byte(COBALT_I2C_DEV_DRV_SWITCH, 78 0); 79 if ((state & 0xf0) != 0xf0) { 80 break; 81 } 82 } 83 } 84 85 return state; 86 } 87 88 static inline unsigned int 89 get_sled_leds(void) 90 { 91 return atomic_read(&sled_leds); 92 } 93 94 /* 95 * deal with sled leds: LED on means OK to remove 96 * NOTE: all the reset lines are kept high. 97 * NOTE: the reset lines are in the reverse order of the switches. 98 */ 99 static void 100 set_sled_leds(unsigned int leds) 101 { 102 if (cobt_is_monterey()) { 103 unsigned int offed = get_sled_leds(); 104 105 offed &= ~leds; 106 atomic_set(&sled_leds, leds); 107 #ifdef CONFIG_COBALT_LED 108 cobalt_led_clear_bits_lazy(offed); 109 cobalt_led_set_bits_lazy(leds); 110 #endif 111 } 112 } 113 114 /* this must be called with the ruler_lock held for read */ 115 static int 116 do_busproc(int idx, ide_drive_t *drive, int arg) 117 { 118 if (cobt_is_monterey()) { 119 /* sed sled LEDs */ 120 switch (arg) { 121 case BUSSTATE_ON: 122 set_sled_leds(get_sled_leds() & 123 ~sled_led_map[idx]); 124 break; 125 case BUSSTATE_OFF: 126 case BUSSTATE_TRISTATE: 127 set_sled_leds(get_sled_leds() | 128 sled_led_map[idx]); 129 break; 130 default: 131 WPRINTK("unknown busproc argument (%d)\n", arg); 132 } 133 } 134 135 /* do the real work */ 136 return busprocs[idx](drive, arg); 137 } 138 139 static void 140 ruler_timer_fn(unsigned long data) 141 { 142 if (cobt_is_monterey()) { 143 u8 state; 144 int i; 145 unsigned int now, expected, bit, swcur; 146 147 state = read_switches(); 148 if ((state & 0xf0) == 0xf0) { 149 return; 150 } 151 swcur = atomic_read(&switches); 152 153 state &= 0xf; 154 read_lock(&ruler_lock); 155 for (i = 0; i < MAX_COBT_DRIVES; i++) { 156 bit = 1 << i; 157 now = state & bit; 158 expected = swcur & bit; 159 if (now == expected) { 160 /* no changes to worry about */ 161 continue; 162 } 163 164 if (now) { 165 /* a freshly detached drive */ 166 atomic_set(&switches, swcur | bit); 167 if (channels[i]) { 168 printk("disabling ide ruler " 169 "channel %d\n", i); 170 do_busproc(i, channels[i], 171 BUSSTATE_TRISTATE); 172 } else { 173 WPRINTK("drive detach on bad " 174 "channel (%d)\n", i); 175 } 176 set_sled_leds(get_sled_leds() | 177 sled_led_map[i]); 178 } else { 179 /* 180 * do we want to do anything when a re-attach 181 * is detected? 182 */ 183 } 184 } 185 read_unlock(&ruler_lock); 186 } 187 } 188 189 #ifdef CONFIG_COBALT_ACPI 190 static int 191 ruler_interrupt(cobalt_acpi_evt *evt, void * data) 192 { 193 if (cobt_is_monterey() && ruler_detect) { 194 u8 state; 195 196 state = read_switches(); 197 if ((state & 0xf0) != 0xf0) { 198 /* this is protected inside mod_timer */ 199 mod_timer(&cobalt_ruler_timer, jiffies + RULER_TIMEOUT); 200 } 201 202 evt->ev_data = state; 203 /* empirical: delay enough to debounce */ 204 udelay(10); 205 } 206 return 0; 207 } 208 #endif /* CONFIG_COBALT_ACPI */ 209 210 #if defined(CONFIG_COBALT_LED) 211 /* figure which LEDs to blink */ 212 static unsigned int 213 ide_led_handler(void *data) 214 { 215 ide_hwif_t *hwif; 216 unsigned int leds = 0; 217 218 if (cobt_is_monterey()) { 219 int i; 220 static int ledmap[MAX_COBT_DRIVES] = { 221 LED_DISK0, LED_DISK1, LED_DISK2, LED_DISK3 222 }; 223 static unsigned long old[MAX_COBT_DRIVES]; 224 225 read_lock(&ruler_lock); 226 227 for (i = 0; i < MAX_COBT_DRIVES; i++) { 228 if (channels[i]) 229 { 230 hwif = HWIF(channels[i]); 231 if (hwif->drives[0].present && 232 hwif->drives[0].service_start != old[i]) { 233 leds |= ledmap[i]; 234 old[i] = hwif->drives[0].service_start; 235 } 236 } 237 } 238 239 read_unlock(&ruler_lock); 240 } 241 242 return leds; 243 } 244 #endif 245 246 /* this is essentially an exported function - it is in the hwif structs */ 247 static int ruler_busproc_fn(ide_drive_t *drive, int arg) 248 { 249 int r = 0; 250 if (cobt_is_monterey()) { 251 int idx; 252 253 read_lock(&ruler_lock); 254 255 for (idx = 0; idx < MAX_COBT_DRIVES; idx++) { 256 if (channels[idx] == drive) { 257 break; 258 } 259 } 260 261 if (idx >= MAX_COBT_DRIVES) { 262 /* not a hwif we manage? */ 263 return 0; 264 } 265 266 r = do_busproc(idx, drive, arg); 267 read_unlock(&ruler_lock); 268 } 269 270 return r; 271 } 272 273 /* 274 * We try to be VERY explicit here. Fine for now, may eventually break down. 275 */ 276 void 277 cobalt_ruler_register(ide_drive_t *drive) 278 { 279 ide_hwif_t *hwif = HWIF(drive); 280 281 if (cobt_is_monterey()) { 282 struct pci_dev *dev; 283 int idx; 284 unsigned long flags; 285 286 if (!hwif) { 287 return; 288 } 289 290 /* Cobalt rulers only have HPT370 controllers on bus 1 */ 291 dev = hwif->pci_dev; 292 if (!dev) 293 return; 294 295 if (dev->vendor != PCI_VENDOR_ID_TTI 296 || dev->device != PCI_DEVICE_ID_TTI_HPT366 297 || dev->bus->number != 1) { 298 /* ignore it */ 299 return; 300 } 301 302 /* IDE ruler has controllers at dev 3 and 4, ONLY */ 303 if (dev->devfn == PCI_DEVFN(3,0)) { 304 idx = hwif->channel; 305 } else if (dev->devfn == PCI_DEVFN(4,0)) { 306 idx = 2 + hwif->channel; 307 } else { 308 return; 309 } 310 311 if (idx >= MAX_COBT_DRIVES) { 312 return; 313 } 314 315 write_lock_irqsave(&ruler_lock, flags); 316 317 /* save a pointer to the hwif, and trap it's busproc() */ 318 channels[idx] = drive; 319 if (hwif->busproc) { 320 busprocs[idx] = HWIF(drive)->busproc; 321 hwif->busproc = &ruler_busproc_fn; 322 } 323 324 write_unlock_irqrestore(&ruler_lock, flags); 325 326 /* now that we have trapped it, do what we need to initialize 327 * the drive - if we haven't been initialized, we'll call this 328 * later. 329 */ 330 if (initialized) { 331 ruler_hwif_added(hwif, idx); 332 } 333 } 334 } 335 336 static void 337 ruler_hwif_added(ide_hwif_t *hwif, int idx) 338 { 339 /* the associated switch should be closed */ 340 if (hwif->drives[0].present) { 341 /* set the sled LED off - not safe to remove */ 342 set_sled_leds(get_sled_leds() & ~sled_led_map[idx]); 343 } 344 } 345 346 void cobalt_ruler_unregister(ide_drive_t *drive) 347 { 348 if (cobt_is_monterey()) { 349 int i; 350 unsigned long flags; 351 352 write_lock_irqsave(&ruler_lock, flags); 353 354 for (i = 0; i < MAX_COBT_DRIVES; i++) { 355 if (channels[i] == drive) { 356 channels[i] = NULL; 357 HWIF(drive)->busproc = busprocs[i]; 358 busprocs[i] = NULL; 359 } 360 } 361 362 write_unlock_irqrestore(&ruler_lock, flags); 363 } 364 } 365 366 int __init 367 cobalt_ruler_init(void) 368 { 369 if (cobt_is_monterey()) { 370 int err; 371 u8 tmp; 372 int i; 373 374 /* initialize switches */ 375 tmp = read_switches(); 376 ruler_detect = ((tmp & 0xf0) == 0xf0) ? 0 : 1; 377 tmp &= 0xf; 378 atomic_set(&switches, tmp); 379 380 /* initialize our timer */ 381 init_timer(&cobalt_ruler_timer); 382 cobalt_ruler_timer.function = ruler_timer_fn; 383 384 printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", RULER_DRIVER,RULER_DRIVER_VMAJ,RULER_DRIVER_VMIN); 385 386 #ifdef CONFIG_COBALT_ACPI 387 err = cobalt_acpi_register_evt_handler(ruler_interrupt, 388 COBALT_ACPI_EVT_SLED, NULL ); 389 390 if (err) { 391 EPRINTK("can't register interrupt handler %p\n", 392 ruler_interrupt); 393 } 394 #endif 395 396 /* set initial sled LED state */ 397 set_sled_leds(LED_SLED0 | LED_SLED1 | LED_SLED2 | LED_SLED3); 398 399 /* run through any devices that were registered before */ 400 for (i = 0; i < MAX_COBT_DRIVES; i++) { 401 if (channels[i]) { 402 ruler_hwif_added(HWIF(channels[i]), i); 403 } 404 } 405 406 #if defined(CONFIG_COBALT_LED) 407 /* register for a blinky LEDs callback */ 408 err = cobalt_fpled_register(ide_led_handler, NULL); 409 if (err) { 410 EPRINTK("can't register LED handler %p\n", 411 ide_led_handler); 412 } 413 #endif 414 } 415 416 initialized = 1; 417 418 return 0; 419 } -
drivers/cobalt/sensors.c
diff -Naur linux-2.6.20.orig/drivers/cobalt/sensors.c linux-2.6.20/drivers/cobalt/sensors.c
old new 1 /* $Id: sensors.c,v 1.31 2002/08/29 00:33:01 uzi Exp $ 2 * Copyright (c) 2000-2001 Sun Microsystems, Inc 3 * 4 * This should be SMP safe. There is just one race - the read in /proc. 5 * It now guards against itself with a semaphore. Note that we don't use a 6 * spinlock because any of the methods may (and do!) block. 7 */ 8 #include <linux/config.h> 9 #ifdef CONFIG_COBALT_SENSORS 10 11 #include <stdarg.h> 12 #include <stddef.h> 13 14 #include <linux/init.h> 15 #include <linux/sched.h> 16 #include <linux/timer.h> 17 #include <linux/config.h> 18 #include <linux/delay.h> 19 #include <linux/ctype.h> 20 #include <linux/proc_fs.h> 21 22 #include <asm/io.h> 23 #include <asm/uaccess.h> 24 25 #include <cobalt/cobalt.h> 26 #include <cobalt/systype.h> 27 #include <cobalt/i2c.h> 28 #include <cobalt/sensors.h> 29 #include <cobalt/acpi.h> 30 31 #define SENS_DRIVER "Cobalt Networks Sensor driver" 32 #define SENS_DRIVER_VMAJ 1 33 #define SENS_DRIVER_VMIN 0 34 35 /* externals */ 36 unsigned int cobalt_nthermals; 37 unsigned int cobalt_nvoltages; 38 39 /* data about a sensor for generic handling */ 40 /* we could add data about a low/high range, if needed */ 41 struct sensor { 42 int sensor; /* sensor #, so maps can be logically ordered */ 43 char *desc; 44 int last_val; 45 unsigned long cache; 46 unsigned long cache_timeout; 47 /* pre/post hook - 1 for pre, 0 for post */ 48 void (*setup)(struct sensor *s, int pre); 49 /* read as an int, to be passed to format() */ 50 int (*read)(struct sensor *s); 51 /* hook for scaling values */ 52 int (*scale)(struct sensor *s, int val); 53 /* format the value as a string */ 54 char *(*format)(struct sensor *s, int val, char *buf, int len); 55 }; 56 57 /* some stuff for generic formatting */ 58 #define DEC_SCALAR 100 59 static char *decimal_format(struct sensor *s, int val, char *buf, int len); 60 61 static DECLARE_MUTEX(sensor_sem); 62 static struct sensor *therm_map; 63 static struct sensor *volt_map; 64 65 #define CACHE_DEF 30 66 67 #ifdef CONFIG_PROC_FS 68 static struct proc_dir_entry *proc_csensors; 69 static struct proc_dir_entry *proc_therm; 70 static struct proc_dir_entry *proc_volt; 71 static int therm_read_proc(char *buf, char **start, off_t pos, int len, 72 int *eof, void *x); 73 static int therm_write_proc(struct file *file, const char *buf, 74 unsigned long len, void *x); 75 static int volt_read_proc(char *buf, char **start, off_t pos, int len, 76 int *eof, void *x); 77 static int volt_write_proc(struct file *file, const char *buf, 78 unsigned long len, void *x); 79 #endif 80 81 static int lm77_therm_read(struct sensor *s); 82 static int adm1029_init(void); 83 static int adm1029_therm_read(struct sensor *s); 84 static int adm1029_volt_read(struct sensor *s); 85 static int alpine_vcore_scale(struct sensor *s, int val); 86 static void alpine_vbat_switch(struct sensor *s, int pre); 87 static int alpine_vbat_scale(struct sensor *s, int val); 88 89 /* sensor name mappings */ 90 static struct sensor gen3_therm_map[] = { 91 {0, "CPU", 0, 0, CACHE_DEF, NULL, lm77_therm_read, NULL, decimal_format}, 92 }; 93 static struct sensor monterey_therm_map[] = { 94 {0, "CPU0", 0, 0, CACHE_DEF, NULL, lm77_therm_read, NULL, decimal_format}, 95 {1, "CPU1", 0, 0, CACHE_DEF, NULL, lm77_therm_read, NULL, decimal_format}, 96 {2, "Case0", 0, 0, CACHE_DEF, NULL, lm77_therm_read, NULL, decimal_format}, 97 {3, "Case1", 0, 0, CACHE_DEF, NULL, lm77_therm_read, NULL, decimal_format}, 98 }; 99 static struct sensor alpine_therm_map[] = { 100 {1, "CPU", 0, 0, CACHE_DEF, NULL, adm1029_therm_read, NULL, decimal_format}, 101 {0, "Case", 0, 0, CACHE_DEF, NULL, adm1029_therm_read, NULL, decimal_format}, 102 }; 103 static struct sensor alpine_volt_map[] = { 104 {0, "Vcore", 0, 0, CACHE_DEF, NULL, adm1029_volt_read, 105 alpine_vcore_scale, decimal_format}, 106 {1, "Vtt", 0, 0, CACHE_DEF, NULL, adm1029_volt_read, NULL, decimal_format}, 107 {0, "Vbat", 0, 0, CACHE_DEF<<10, alpine_vbat_switch, adm1029_volt_read, 108 alpine_vbat_scale, decimal_format}, 109 }; 110 111 int __init 112 cobalt_sensors_init(void) 113 { 114 if (cobt_is_3k()) { 115 cobalt_nthermals = 1; 116 cobalt_nvoltages = 0; 117 therm_map = gen3_therm_map; 118 } else if (cobt_is_monterey()) { 119 cobalt_nthermals = 4; 120 cobalt_nvoltages = 0; 121 therm_map = monterey_therm_map; 122 } else if (cobt_is_alpine()) { 123 cobalt_nthermals = 2; 124 cobalt_nvoltages = 3; 125 therm_map = alpine_therm_map; 126 volt_map = alpine_volt_map; 127 adm1029_init(); 128 } else { 129 return -1; 130 } 131 132 printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", SENS_DRIVER,SENS_DRIVER_VMAJ,SENS_DRIVER_VMIN); 133 134 #ifdef CONFIG_PROC_FS 135 /* make files in /proc */ 136 proc_csensors = proc_mkdir("sensors", proc_cobalt); 137 if (!proc_csensors) { 138 EPRINTK("can't create /proc/cobalt/sensors\n"); 139 return -1; 140 } 141 if (cobalt_nthermals) { 142 proc_therm = create_proc_entry("thermal", 143 S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 144 proc_csensors); 145 if (!proc_therm) { 146 EPRINTK("can't create /proc/cobalt/sensors/thermal\n"); 147 } 148 proc_therm->read_proc = therm_read_proc; 149 proc_therm->write_proc = therm_write_proc; 150 } 151 if (cobalt_nvoltages) { 152 proc_volt = create_proc_entry("voltage", 153 S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 154 proc_csensors); 155 if (!proc_volt) { 156 EPRINTK("can't create /proc/cobalt/sensors/voltage\n"); 157 } 158 proc_volt->read_proc = volt_read_proc; 159 proc_volt->write_proc = volt_write_proc; 160 161 } 162 #endif 163 164 return 0; 165 } 166 167 static char * 168 sensor_read(struct sensor *s, char *buf, int len) 169 { 170 int val; 171 172 if (s->cache && time_after(s->cache_timeout*HZ + s->cache, jiffies)) 173 val = s->last_val; 174 else { 175 if (s->setup) s->setup(s, 1); 176 val = s->read(s); 177 s->last_val = val; 178 s->cache = jiffies; 179 if (s->setup) s->setup(s, 0); 180 } 181 182 if (s->scale) val = s->scale(s, val); 183 return s->format(s, val, buf, len); 184 } 185 186 /* exported - nicer inline functions in header */ 187 char * 188 __cobalt_thermal_read(unsigned int idx, char *buf, int len) 189 { 190 if (idx >= cobalt_nthermals || !buf) { 191 return NULL; 192 } 193 194 return sensor_read(&therm_map[idx], buf, len); 195 } 196 197 /* exported - nicer inline functions in header */ 198 char * 199 __cobalt_voltage_read(unsigned int idx, char *buf, int len) 200 { 201 if (idx >= cobalt_nvoltages || !buf) { 202 return NULL; 203 } 204 205 return sensor_read(&volt_map[idx], buf, len); 206 } 207 208 /* generic function for formatting decimal scaled data */ 209 static char * 210 decimal_format(struct sensor *s, int val, char *buf, int len) 211 { 212 int plen; 213 214 if (!buf || len <= 0) { 215 return NULL; 216 } 217 218 plen = snprintf(buf, len, "%d", val/DEC_SCALAR); 219 len -= plen; 220 221 if (val % DEC_SCALAR && len > 0) { 222 snprintf(buf+plen, len, ".%02d", val%DEC_SCALAR); 223 } 224 225 return buf; 226 } 227 228 #define LM77_TEMP 0x0 229 static int 230 lm77_therm_read(struct sensor *s) 231 { 232 int sensor = s->sensor; 233 int tmp; 234 int val = 0; 235 int tries = 2; 236 237 /* sometimes it reads as zero... try again */ 238 while (tries--) { 239 /* LM77 returns the bytes backwards - <shrug> */ 240 /* address = base + deviceid + 1 for read */ 241 val = cobalt_i2c_read_word(COBALT_I2C_DEV_LM77 + 242 (sensor<<1) + 1, LM77_TEMP); 243 if (val < 0) { 244 /* read failed, return the last known value */ 245 return s->last_val; 246 } 247 248 tmp = (val<<8 & 0xff00) + (val>>8 & 0x00ff); 249 if (tmp) { 250 val = tmp >> 4; 251 val *= DEC_SCALAR; 252 if (tmp & 0x8) { 253 val += DEC_SCALAR/2; 254 } 255 break; 256 } 257 } 258 return val; 259 } 260 261 #define ADM1029_CTL_CFAULT_OVER 0x01 262 #define ADM1029_CTL_ALARM_OVER 0x02 263 #define ADM1029_CTL_INT_OVER 0x04 264 #define ADM1029_CTL_ALARM_LOW 0x08 265 #define ADM1029_CTL_CFAULT_UNDER 0x10 266 #define ADM1029_CTL_ALARM_UNDER 0x20 267 #define ADM1029_CTL_INT_UNDER 0x40 268 #define ADM1029_CTL_LATCH 0x80 269 270 #define ADM1029_FAN_CTL(i) (0x18 + i) 271 #define ADM1029_TEMP_CTL(i) (0x40 + i) 272 #define ADM1029_AIN_CTL(i) (0x50 + i) 273 274 #define ADM1029_TEMP_HIGH(i) (0x90 + i) 275 #define ADM1029_TEMP_LOW(i) (0x98 + i) 276 #define ADM1029_AIN_HIGH(i) (0xa8 + i) 277 #define ADM1029_AIN_LOW(i) (0xb0 + i) 278 279 #define ADM1029_TEMP_VALUE(i) (0xa0 + i) 280 #define ADM1029_AIN_VALUE(i) (0xb8 + i) 281 282 #ifdef CONFIG_COBALT_ACPI 283 static int 284 adm1029_handler(cobalt_acpi_evt *evt, void * data) 285 { 286 int j, k; 287 288 switch (evt->ev_type) { 289 case COBALT_ACPI_EVT_SM_INT: 290 evt->ev_data = 0; 291 evt->ev_type = COBALT_ACPI_EVT_VOLT; 292 for (j=0; j<cobalt_nvoltages; j++) { 293 k = cobalt_i2c_read_byte(COBALT_I2C_DEV_ADM1029, 294 ADM1029_AIN_CTL(volt_map[j].sensor)); 295 if (k & ADM1029_CTL_LATCH) { 296 evt->ev_data |= (1 << j); 297 volt_map[j].cache = 0; 298 } 299 } 300 break; 301 302 case COBALT_ACPI_EVT_THERM: 303 evt->ev_data = 0; 304 for (j=0; j<cobalt_nthermals; j++) { 305 k = cobalt_i2c_read_byte(COBALT_I2C_DEV_ADM1029, 306 ADM1029_TEMP_CTL(therm_map[j].sensor)); 307 if (k & ADM1029_CTL_LATCH) { 308 evt->ev_data |= (1 << j); 309 therm_map[j].cache = 0; 310 } 311 } 312 break; 313 314 default: 315 return -1; 316 } 317 return 0; 318 } 319 #endif /* CONFIG_COBALT_ACPI */ 320 321 static int 322 adm1029_init(void) 323 { 324 325 #ifdef CONFIG_COBALT_ACPI 326 cobalt_acpi_register_evt_handler(adm1029_handler, 327 COBALT_ACPI_EVT_THERM, NULL); 328 cobalt_acpi_register_evt_handler(adm1029_handler, 329 COBALT_ACPI_EVT_SM_INT, NULL); 330 #endif 331 332 return 0; 333 } 334 335 static int 336 adm1029_therm_read(struct sensor *s) 337 { 338 int sensor = s->sensor; 339 int val; 340 341 val = cobalt_i2c_read_byte(COBALT_I2C_DEV_ADM1029, 342 ADM1029_TEMP_VALUE(sensor)); 343 if (val < 0) { 344 /* read failed, return the last known value */ 345 return s->last_val; 346 } 347 if (val & 0x80) { 348 val -= 256; 349 } 350 val *= DEC_SCALAR; 351 352 return val; 353 } 354 355 static int 356 adm1029_volt_read(struct sensor *s) 357 { 358 int sensor = s->sensor; 359 int val; 360 361 val = cobalt_i2c_read_byte(COBALT_I2C_DEV_ADM1029, 362 ADM1029_AIN_VALUE(sensor)); 363 if (val < 0) { 364 /* read failed, return the last known value */ 365 return s->last_val; 366 } 367 368 /* already scaled by 100 */ 369 val *= DEC_SCALAR/100; 370 371 return val; 372 } 373 374 static int 375 alpine_vcore_scale(struct sensor *s, int val) 376 { 377 /* the measured Vbat switch cost is negligable 378 * due to very low current through the diode */ 379 return val; 380 } 381 382 #define VBAT_REG 0x608 383 #define VBAT_BIT 0x1 384 static void 385 alpine_vbat_switch(struct sensor *s, int pre) 386 { 387 unsigned char v = inb(VBAT_REG); 388 unsigned long j = jiffies; 389 390 if (pre) { 391 v |= VBAT_BIT; 392 /* 393 * disable AIN0 INT# assertion before switching to 394 * Vbat because the input is shared with Vcore and 395 * their acceptable ranges are very different. 396 */ 397 cobalt_i2c_write_byte(COBALT_I2C_DEV_ADM1029, 398 ADM1029_AIN_CTL(s->sensor), 0x0); 399 } else { 400 v &= ~VBAT_BIT; 401 } 402 403 outb(v, VBAT_REG); 404 405 /* 406 * wait for the round-robin monitor to complete a cycle 407 * before _and_ after toggling Vbat switch, otherwise 408 * stale data in AIN0 will trigger INT# assertion. 409 */ 410 while ((jiffies - j) < HZ) { 411 /* block for ~ 1sec */ 412 set_current_state(TASK_INTERRUPTIBLE); 413 schedule_timeout(HZ); 414 } 415 416 if (!pre) { 417 /* 418 * now re-enable INT# assertion capability for AIN0 419 * (this also clears the AIN0 fault latch at bit 7) 420 */ 421 cobalt_i2c_write_byte(COBALT_I2C_DEV_ADM1029, 422 ADM1029_AIN_CTL(s->sensor), 423 ADM1029_CTL_INT_OVER | ADM1029_CTL_INT_UNDER); 424 } 425 } 426 427 static int 428 alpine_vbat_scale(struct sensor *s, int val) 429 { 430 /* 431 * The spec says 2.5V max - but empirically, 3.3V works :) 432 * The Vbat switch costs 0.3 volts 433 */ 434 if (val) val += (3 * DEC_SCALAR)/10; 435 436 return val; 437 } 438 439 #ifdef CONFIG_PROC_FS 440 static int 441 sensor_write_proc(int nsensors, struct sensor *map, 442 struct file *file, const char *buf, unsigned long len, void *x) 443 { 444 char *pg; 445 446 if (len > PAGE_SIZE) { 447 return -EOVERFLOW; 448 } 449 450 pg = (char *)__get_free_page(GFP_KERNEL); 451 if (!pg) { 452 return -ENOMEM; 453 } 454 455 if (copy_from_user(pg, buf, len)) { 456 free_page((unsigned long)pg); 457 return -EFAULT; 458 } 459 pg[len] = '\0'; 460 461 /* format: `cache_timeout #' in seconds */ 462 if (len>15 && !strncmp("cache_timeout ", pg, 14) && isdigit(*(pg+14))) { 463 unsigned long i, sec = simple_strtoul(pg+14, NULL, 0); 464 for (i=0; i<nsensors; i++) 465 map[i].cache_timeout = sec; 466 } 467 468 free_page((unsigned long)pg); 469 return len; 470 } 471 472 static int 473 sensor_read_proc(int nsensors, struct sensor *map, 474 char *buf, char **start, off_t pos, int len, int *eof, void *x) 475 { 476 int i; 477 static int plen = 0; 478 479 down(&sensor_sem); 480 481 /* remember how big our last read was to avoid read() calling twice */ 482 if (pos && pos >= plen) { 483 *eof = 1; 484 up(&sensor_sem); 485 return 0; 486 } 487 488 plen = 0; 489 for (i = 0; i < nsensors; i++) { 490 char sbuf[32]; 491 if (sensor_read(&map[i], sbuf, sizeof(sbuf))) 492 plen += sprintf(buf+plen, "%d [%s]: %s\n", i, map[i].desc, sbuf); 493 } 494 495 up(&sensor_sem); 496 497 return cobalt_gen_proc_read(buf, plen, start, pos, len, eof); 498 } 499 500 static int 501 therm_read_proc(char *buf, char **start, off_t pos, int len, int *eof, void *x) 502 { 503 return sensor_read_proc(cobalt_nthermals, therm_map, 504 buf, start, pos, len, eof, x); 505 } 506 static int 507 therm_write_proc(struct file *file, const char *buf, unsigned long len, void *x) 508 { 509 return sensor_write_proc(cobalt_nthermals, therm_map, file, buf, len, x); 510 } 511 512 static int 513 volt_read_proc(char *buf, char **start, off_t pos, int len, int *eof, void *x) 514 { 515 return sensor_read_proc(cobalt_nvoltages, volt_map, 516 buf, start, pos, len, eof, x); 517 } 518 static int 519 volt_write_proc(struct file *file, const char *buf, unsigned long len, void *x) 520 { 521 return sensor_write_proc(cobalt_nvoltages, volt_map, file, buf, len, x); 522 } 523 #endif /* CONFIG_PROC_FS */ 524 525 #endif /* CONFIG_COBALT_SENSORS */ -
drivers/cobalt/serialnum.c
diff -Naur linux-2.6.20.orig/drivers/cobalt/serialnum.c linux-2.6.20/drivers/cobalt/serialnum.c
old new 1 /* $Id: serialnum.c,v 1.15 2001/10/23 20:15:27 thockin Exp $ */ 2 /* 3 * 4 * Author: Philip Gladstone, Axent Technologies 5 * modified for Nat Semi PC[89]7317 by asun@cobalt.com 6 * ported to 2.4.x by thockin@sun.com 7 * alpine serial eeprom by erik.glling@sun.com 8 * Copyright (c) 2000 Axent Technologies, Cobalt Networks 9 * Copyright (c) 2001 Axent Technologies, Sun Microsystems 10 * 11 * This module interrogates the DS2401 Silicon Serial Number chip 12 * that is attached to all x86 Cobalt systems. 13 * 14 * It exports /proc/cobalt/hostid which is four bytes generated from of 15 * the id. It can be linked to /var/adm/hostid or /etc/hostid for the 16 * hostid command to use. 17 * 18 * It exports /proc/cobalt/serialnumber which is the entire 64 bit value 19 * read back (in ascii). 20 * 21 * For the guts of the 1 wire protocol used herein, please see the DS2401 22 * specification. 23 * 24 * This program is free software; you can redistribute it and/or modify 25 * it under the terms of the GNU General Public License as published by 26 * the Free Software Foundation; either version 2 of the License, or 27 * (at your option) any later version. 28 * 29 * This program is distributed in the hope that it will be useful, 30 * but WITHOUT ANY WARRANTY; without even the implied warranty of 31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 32 * GNU General Public License for more details. 33 * 34 * You should have received a copy of the GNU General Public License 35 * along with this program; if not, write to the Free Software 36 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 37 * 38 * This driver is SMP safe by nature. --TPH 39 */ 40 #include <linux/config.h> 41 #if defined (CONFIG_COBALT_SERNUM) || defined(CONFIG_COBALT_SERNUM_MODULE) 42 43 #include <linux/module.h> 44 #include <linux/stddef.h> 45 #include <linux/version.h> 46 #include <linux/types.h> 47 #include <linux/proc_fs.h> 48 #include <linux/delay.h> 49 #include <asm/uaccess.h> 50 #include <linux/pci.h> 51 #include <linux/init.h> 52 #include <asm/io.h> 53 54 #include <cobalt/cobalt.h> 55 #include <cobalt/systype.h> 56 #include <cobalt/superio.h> 57 #include <cobalt/serialnum.h> 58 #include <cobalt/i2c.h> 59 60 #include <linux/interrupt.h> 61 62 #define SN_DRIVER "Cobalt Networks Serial Number driver" 63 #define SN_DRIVER_VMAJ 1 64 #define SN_DRIVER_VMIN 6 65 66 /* dependent on systype */ 67 static unsigned int sn_direction; 68 static unsigned int sn_output; 69 static unsigned int sn_input; 70 static unsigned int sn_mask; 71 72 /* 3k style systems */ 73 #define III_SN_DIRECTION 0x7d 74 #define III_SN_OUTPUT 0x7e 75 #define III_SN_INPUT 0x7f 76 #define III_SN_MASK 0x08 77 static struct pci_dev *id_dev; 78 79 /* 5k style systems */ 80 #define V_SN_DIRECTION (sn_io_base + 0x01) 81 #define V_SN_OUTPUT (sn_io_base + 0x00) 82 #define V_SN_INPUT (sn_io_base + 0x00) 83 #define V_SN_MASK (sn_io_base + 0x01) 84 static unsigned int sn_io_base; 85 86 #define SSN_SIZE 8 /* bytes */ 87 static char ssn_string[SSN_SIZE * 2 + 1]; 88 static unsigned long hostid; 89 static int debug; 90 #ifdef CONFIG_PROC_FS 91 #ifdef CONFIG_COBALT_OLDPROC 92 static struct proc_dir_entry *proc_hostid; 93 static struct proc_dir_entry *proc_serialnum; 94 #endif 95 static struct proc_dir_entry *proc_chostid; 96 static struct proc_dir_entry *proc_cserialnum; 97 #endif 98 99 static int 100 hostid_read(char *buf, char **start, off_t pos, int len, int *eof, void *x) 101 { 102 int plen = sizeof(hostid); 103 memcpy(buf, &hostid, sizeof(hostid)); 104 return cobalt_gen_proc_read(buf, plen, start, pos, len, eof); 105 } 106 107 static int 108 serialnum_read(char *buf, char **start, off_t pos, int len, int *eof, void *x) 109 { 110 int plen = sizeof(ssn_string); 111 sprintf(buf, "%s\n", ssn_string); 112 return cobalt_gen_proc_read(buf, plen, start, pos, len, eof); 113 } 114 115 /* set up the requisite IO bits */ 116 static int __init 117 io_init(void) 118 { 119 unsigned char data; 120 121 if (cobt_is_3k()) { 122 /* The GPIO tied to the ID chip is on the PMU */ 123 id_dev = pci_find_device(PCI_VENDOR_ID_AL, 124 PCI_DEVICE_ID_AL_M7101, NULL); 125 if (!id_dev) { 126 EPRINTK("can't find PMU for serialnumber access\n"); 127 return -ENXIO; 128 } 129 130 /* Set input mode on GPIO3 */ 131 pci_read_config_byte(id_dev, sn_direction, &data); 132 if (debug > 1) { 133 WPRINTK("read of register 0x%x = 0x%x\n", 134 sn_direction, data); 135 } 136 if (data & sn_mask) { 137 pci_write_config_byte(id_dev, sn_direction, 138 data & ~sn_mask); 139 } 140 141 /* Set the output value to be 0 */ 142 pci_read_config_byte(id_dev, sn_output, &data); 143 if (debug > 1) { 144 WPRINTK("read of register 0x%x = 0x%x\n", 145 sn_output, data); 146 } 147 if (data & sn_mask) { 148 pci_write_config_byte(id_dev, sn_output, 149 data & ~sn_mask); 150 } 151 } else if (cobt_is_5k()) { 152 u16 addr; 153 154 addr = superio_ldev_base(PC87317_DEV_GPIO); 155 if (addr) { 156 u8 val; 157 158 sn_io_base = addr; 159 160 /* set output value to 0 */ 161 val = inb(sn_direction); 162 outb(val | sn_mask, sn_direction); 163 data = inb(sn_output); 164 if (data & sn_mask) { 165 outb(data & ~sn_mask, sn_output); 166 } 167 /* set to input */ 168 outb(val & ~sn_mask, sn_direction); 169 } 170 } else { 171 return -ENXIO; 172 } 173 174 /* pick proper variables */ 175 if (cobt_is_3k()) { 176 sn_direction = III_SN_DIRECTION; 177 sn_output = III_SN_OUTPUT; 178 sn_input = III_SN_INPUT; 179 sn_mask = III_SN_MASK; 180 } else if (cobt_is_5k()) { 181 sn_direction = V_SN_DIRECTION; 182 sn_output = V_SN_OUTPUT; 183 sn_input = V_SN_INPUT; 184 sn_mask = V_SN_MASK; 185 } else { 186 return -1; 187 } 188 189 /* Let things calm down */ 190 udelay(500); 191 return 0; 192 } 193 194 /* write out a bit */ 195 static void __init 196 io_write(int delay) 197 { 198 if (cobt_is_3k()) { 199 unsigned char data; 200 /* Set output mode on GPIO3 */ 201 pci_read_config_byte(id_dev, sn_direction, &data); 202 pci_write_config_byte(id_dev, sn_direction, data | sn_mask); 203 udelay(delay); 204 205 /* Set input mode */ 206 pci_write_config_byte(id_dev, sn_direction, data & ~sn_mask); 207 } else if (cobt_is_5k()) { 208 unsigned char direction; 209 210 /* change to output and back */ 211 direction = inb(sn_direction); 212 outb(direction | sn_mask, sn_direction); 213 udelay(delay); 214 outb(direction & ~sn_mask, sn_direction); 215 } 216 } 217 218 /* read in a bit */ 219 static int __init 220 io_read(void) 221 { 222 unsigned char data = 0; 223 224 /* Get the input value */ 225 if (cobt_is_3k()) { 226 pci_read_config_byte(id_dev, sn_input, &data); 227 } else if (cobt_is_5k()) { 228 data = inb(sn_input); 229 } 230 231 return (data & sn_mask) ? 1 : 0; 232 } 233 234 static void __init 235 io_write_byte(unsigned char c) 236 { 237 int i; 238 unsigned long flags; 239 240 local_save_flags(flags); 241 242 for (i = 0; i < 8; i++, c >>= 1) { 243 local_irq_disable(); 244 if (c & 1) { 245 /* Transmit a 1 */ 246 io_write(5); 247 udelay(80); 248 } else { 249 /* Transmit a 0 */ 250 io_write(80); 251 udelay(10); 252 } 253 local_irq_restore(flags); 254 } 255 } 256 257 static int __init 258 io_read_byte(void) 259 { 260 int i; 261 int c = 0; 262 unsigned long flags; 263 264 local_save_flags(flags); 265 266 for (i = 0; i < 8; i++) { 267 local_irq_disable(); 268 io_write(1); /* Start the read */ 269 udelay(2); 270 if (io_read()) { 271 c |= 1 << i; 272 } 273 udelay(60); 274 local_irq_restore(flags); 275 } 276 277 return c; 278 } 279 280 static int __init 281 get_ssn(unsigned char *buf) 282 { 283 int i; 284 unsigned long flags; 285 286 /* 287 * Alpine does not have a dallas chip. Instead 288 * we read from an eprom. 289 */ 290 if (cobt_is_alpine()) { 291 for (i = 0; i < 8; i++) { 292 buf[i] = cobalt_i2c_read_byte(COBALT_I2C_DEV_AT24C02, 293 12 + i); 294 } 295 return 0; 296 } 297 298 /* 299 * bit-bang the Dallas 2401 300 */ 301 302 local_save_flags(flags); 303 local_irq_disable(); 304 305 /* Master Reset Pulse */ 306 for (i = 0; i < 600; i += 30) { 307 if (io_read()) { 308 break; 309 } 310 } 311 312 if (i >= 600) { 313 if (debug) { 314 EPRINTK("the data line seems to be held low\n"); 315 } 316 local_irq_restore(flags); 317 return -ENXIO; 318 } 319 320 io_write(600); 321 322 for (i = 0; i < 300; i += 15) { 323 udelay(15); 324 if (io_read() == 0) { 325 /* We got a presence pulse */ 326 udelay(600); /* Wait for things to quiet down */ 327 break; 328 } 329 } 330 local_irq_restore(flags); 331 332 if (i >= 300) { 333 if (debug) 334 EPRINTK("no presence pulse detected\n"); 335 return -ENXIO; 336 } 337 338 io_write_byte(0x33); 339 340 for (i = 0; i < 8; i++) { 341 int rc; 342 343 rc = io_read_byte(); 344 if (rc < 0) { 345 return rc; 346 } 347 348 *buf++ = rc; 349 } 350 351 return 0; 352 } 353 354 int __init 355 cobalt_serialnum_init(void) 356 { 357 unsigned char ssn[SSN_SIZE]; 358 int rc; 359 int i; 360 361 printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", SN_DRIVER,SN_DRIVER_VMAJ,SN_DRIVER_VMIN); 362 /* set up for proper IO */ 363 rc = io_init(); 364 if (rc) { 365 return rc; 366 } 367 368 /* 369 * NOTE: the below algorithm CAN NOT be changed. We have many systems 370 * out there registered with the serial number AS DERIVED by this 371 * algorithm. 372 */ 373 374 rc = get_ssn(ssn); 375 if (rc) { 376 return rc; 377 } 378 379 /* Convert to ssn_string */ 380 for (i = 7; i >= 0; i--) { 381 sprintf(ssn_string + (7 - i) * 2, "%02x", ssn[i]); 382 } 383 384 /* get four bytes for a pretty unique (not guaranteed) hostid */ 385 hostid = *(unsigned long *)ssn ^ *(unsigned long *)(ssn+4); 386 387 #ifdef CONFIG_PROC_FS 388 #ifdef CONFIG_COBALT_OLDPROC 389 proc_hostid = create_proc_read_entry("hostid", 0, NULL, 390 hostid_read, NULL); 391 if (!proc_hostid) { 392 EPRINTK("can't create /proc/hostid\n"); 393 } 394 proc_serialnum = create_proc_read_entry("serialnumber", 0, NULL, 395 serialnum_read, NULL); 396 if (!proc_serialnum) { 397 EPRINTK("can't create /proc/serialnumber\n"); 398 } 399 #endif 400 proc_chostid = create_proc_read_entry("hostid", 0, proc_cobalt, 401 hostid_read, NULL); 402 if (!proc_chostid) { 403 EPRINTK("can't create /proc/cobalt/hostid\n"); 404 } 405 proc_cserialnum = create_proc_read_entry("serialnumber", 0, 406 proc_cobalt, serialnum_read, NULL); 407 if (!proc_cserialnum) { 408 EPRINTK("can't create /proc/cobalt/serialnumber\n"); 409 } 410 #endif 411 412 return 0; 413 } 414 415 char * 416 cobalt_serialnum_get(void) 417 { 418 return ssn_string; 419 } 420 421 unsigned long 422 cobalt_hostid_get(void) 423 { 424 return hostid; 425 } 426 427 #if defined(CONFIG_COBALT_SERNUM_MODULE) 428 MODULE_PARM(debug, "i"); 429 430 int 431 init_module(void) 432 { 433 return cobalt_serialnum_init(); 434 } 435 436 void 437 cleanup_module(void) 438 { 439 #ifdef CONFIG_PROC_FS 440 #ifdef CONFIG_COBALT_OLDPROC 441 remove_proc_entry("hostid", NULL); 442 remove_proc_entry("serialnumber", NULL); 443 #endif 444 remove_proc_entry("hostid", proc_cobalt); 445 remove_proc_entry("serialnumber", proc_cobalt); 446 #endif 447 } 448 449 module_init(init_module); 450 module_exit(cleanup_module); 451 #endif /* MODULE */ 452 453 #endif /* CONFIG_COBALT_SERNUM */ -
drivers/cobalt/systype.c
diff -Naur linux-2.6.20.orig/drivers/cobalt/systype.c linux-2.6.20/drivers/cobalt/systype.c
old new 1 /* 2 * $Id: systype.c,v 1.33 2002/11/04 17:54:15 thockin Exp $ 3 * systype.c : routines for figuring out which Cobalt system this is 4 * 5 * Copyright 2001-2002 Sun Microsystems, Inc. 6 * 7 * By: Tim Hockin 8 * Adrian Sun 9 * Duncan Laurie 10 * 11 * This driver is SMP safe by nature. --TPH 12 */ 13 14 #include <linux/config.h> 15 16 #include <linux/pci.h> 17 #include <linux/init.h> 18 #include <linux/proc_fs.h> 19 #include <linux/module.h> 20 21 #include <cobalt/cobalt.h> 22 #include <cobalt/systype.h> 23 #include <cobalt/i2c.h> 24 25 /* for easy first-pass analysis */ 26 #if defined(CONFIG_COBALT_GEN_III) 27 int COBALT_GENERATION_III_DEFINED; 28 #endif 29 #if defined(CONFIG_COBALT_GEN_V) 30 int COBALT_GENERATION_V_DEFINED; 31 #endif 32 33 cobt_sys_t cobt_type = COBT_UNINITIALIZED; 34 EXPORT_SYMBOL(cobt_type); 35 unsigned long cobt_rev; 36 EXPORT_SYMBOL(cobt_rev); 37 38 #ifdef CONFIG_PROC_FS 39 static struct proc_dir_entry *proc_systype; 40 #endif 41 static int systype_read_proc(char *buf, char **start, off_t pos, int len, 42 int *eof, void *x); 43 static char *systype_str(cobt_sys_t type); 44 static unsigned long boardrev_read(void); 45 46 void __init 47 cobalt_boardrev_init(void) 48 { 49 cobt_rev = boardrev_read(); 50 } 51 52 int __init 53 cobalt_systype_init(void) 54 { 55 cobalt_systype_probe(); 56 57 #ifdef CONFIG_PROC_FS 58 proc_systype = create_proc_read_entry("systype", 0, 59 proc_cobalt, systype_read_proc, NULL); 60 if (!proc_systype) { 61 EPRINTK("can't create /proc/cobalt/systype\n"); 62 } 63 #endif 64 65 if (cobt_type == COBT_UNKNOWN) { 66 printk(KERN_INFO "Cobalt system type is unknown, trouble will ensue (I can vouch for this)\n"); 67 return -1; 68 } else { 69 printk(KERN_INFO "Cobalt system type is %s\n",systype_str(cobt_type)); 70 return 0; 71 } 72 } 73 74 #if defined(CONFIG_COBALT_GEN_III) 75 static cobt_sys_t 76 systype_probe_3k(void) 77 { 78 struct pci_dev *pdev; 79 cobt_sys_t retval = COBT_UNKNOWN; 80 81 /* board identifier for RaQ3/4 vs Qube3 is on the PMU @ 0x7f */ 82 pdev = pci_find_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, NULL); 83 if (pdev) { 84 /* 85 * check to see what board we are on 86 * ( RaQ 3, RaQ 4, Qube 3 ) 87 */ 88 unsigned char val; 89 90 /* momentarily set DOGB# to input */ 91 pci_read_config_byte(pdev, 0x7d, &val); 92 pci_write_config_byte(pdev, 0x7d, val & ~0x20); 93 94 /* read the GPIO register */ 95 pci_read_config_byte(pdev, 0x7f, &val); 96 /* RaQ3/4 boards have DOGB (0x20) high, 97 * Qube3 has DOGB low */ 98 if (val & 0x20) { 99 retval = COBT_PACIFICA; 100 } else { 101 retval = COBT_CARMEL; 102 } 103 104 /* change DOGB back to output */ 105 pci_read_config_byte(pdev, 0x7d, &val); 106 pci_write_config_byte(pdev, 0x7d, val | 0x20); 107 } 108 109 /* assign to this, so the compiler shuts up */ 110 COBALT_GENERATION_III_DEFINED = 1; 111 112 return retval; 113 } 114 #else 115 #define systype_probe_3k() (COBT_UNKNOWN) 116 #endif 117 118 #if defined(CONFIG_COBALT_GEN_V) 119 static cobt_sys_t 120 systype_probe_5k(void) 121 { 122 struct pci_dev *pdev; 123 cobt_sys_t retval = COBT_UNKNOWN; 124 125 /* is it a gen V ? */ 126 pdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, 127 PCI_DEVICE_ID_SERVERWORKS_OSB4, NULL); 128 if (pdev) { 129 retval = COBT_MONTEREY; 130 goto out; 131 } 132 133 pdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, 134 PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL); 135 if (pdev) { 136 pdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, 137 PCI_DEVICE_ID_SERVERWORKS_LE, NULL); 138 if (pdev) { 139 retval = COBT_ALPINE; 140 goto out; 141 } 142 } 143 144 out: 145 /* assign to this, so the compiler shuts up */ 146 COBALT_GENERATION_V_DEFINED = 1; 147 148 return retval; 149 } 150 #else 151 #define systype_probe_5k() (COBT_UNKNOWN) 152 #endif 153 154 static cobt_sys_t 155 systype_probe_gp(void) 156 { 157 struct pci_dev *pdev; 158 cobt_sys_t retval = COBT_UNKNOWN; 159 160 /* is it a GP system? */ 161 pdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, 162 PCI_DEVICE_ID_SERVERWORKS_CSB5, NULL); 163 if (pdev) { 164 pdev = pci_find_device(PCI_VENDOR_ID_SERVERWORKS, 165 PCI_DEVICE_ID_SERVERWORKS_HE, NULL); 166 if (pdev) { 167 retval = COBT_BIGBEAR; 168 } 169 } 170 171 return retval; 172 } 173 174 cobt_sys_t 175 cobalt_systype_probe(void) 176 { 177 static int init_done = 0; 178 179 if (init_done) { 180 return cobt_type; 181 } 182 183 /* check for 3k family systems */ 184 185 cobt_type = systype_probe_3k(); 186 if (cobt_type != COBT_UNKNOWN) 187 goto out; 188 189 /* check for 5k family systems */ 190 cobt_type = systype_probe_5k(); 191 if (cobt_type != COBT_UNKNOWN) 192 goto out; 193 194 /* it's a GP system or unknown */ 195 cobt_type = systype_probe_gp(); 196 197 out: 198 if (cobt_type != COBT_UNKNOWN) { 199 init_done = 1; 200 } 201 202 return cobt_type; 203 } 204 EXPORT_SYMBOL(cobalt_systype_probe); 205 206 #ifdef CONFIG_PROC_FS 207 static int 208 systype_read_proc(char *buf, char **start, off_t pos, int len, 209 int *eof, void *x) 210 { 211 int plen = sprintf(buf, "%s\n", systype_str(cobt_type)); 212 return cobalt_gen_proc_read(buf, plen, start, pos, len, eof); 213 } 214 #endif 215 216 static char * 217 systype_str(cobt_sys_t type) 218 { 219 switch (type) { 220 case COBT_PACIFICA: 221 return "Pacifica"; 222 break; 223 case COBT_CARMEL: 224 return "Carmel"; 225 break; 226 case COBT_MONTEREY: 227 return "Monterey"; 228 break; 229 case COBT_ALPINE: 230 return "Alpine"; 231 break; 232 case COBT_BIGBEAR: 233 return "BigBear"; 234 break; 235 case COBT_UNKNOWN: 236 default: 237 return "unknown"; 238 break; 239 } 240 } 241 242 static unsigned long 243 boardrev_read(void) 244 { 245 unsigned long rev; 246 247 switch (cobt_type) { 248 #ifdef CONFIG_COBALT_RAQ 249 case COBT_PACIFICA: 250 case COBT_CARMEL: 251 /* No usable board rev on these systems */ 252 return 0; 253 case COBT_MONTEREY: 254 /* 255 * the boardrev on monterey is strapped off of GPM[3:0] 256 * and is read from port 0xc52 257 */ 258 return inb(0xc52); 259 case COBT_ALPINE: 260 /* 261 * the boardrev on alpine in stored in the i2c eeprom 262 * location 4 263 */ 264 rev = cobalt_i2c_read_byte(COBALT_I2C_DEV_AT24C02, 0x04); 265 rev |= cobalt_i2c_read_byte(COBALT_I2C_DEV_AT24C02, 0x05) << 8; 266 rev |= cobalt_i2c_read_byte(COBALT_I2C_DEV_AT24C02, 0x06) << 16; 267 rev |= cobalt_i2c_read_byte(COBALT_I2C_DEV_AT24C02, 0x07) << 24; 268 if (rev == 0xffffffff) 269 rev = 0; 270 return rev; 271 #endif 272 case COBT_BIGBEAR: 273 /* No board revs at this time */ 274 return 0; 275 case COBT_UNKNOWN: 276 case COBT_UNINITIALIZED: 277 return 0; 278 } 279 return 0; 280 } -
drivers/cobalt/wdt.c
diff -Naur linux-2.6.20.orig/drivers/cobalt/wdt.c linux-2.6.20/drivers/cobalt/wdt.c
old new 1 /* $Id: wdt.c,v 1.21 2002/07/02 00:38:17 asun Exp $ */ 2 /* 3 * Cobalt kernel WDT timer driver 4 * Tim Hockin <thockin@cobaltnet.com> 5 * Adrian Sun <asun@cobalt.com> 6 * Chris Johnson <cjohnson@cobalt.com> 7 * Copyright (c)1999-2000, Cobalt Networks 8 * Copyright (c)2001, Sun Microsystems 9 * 10 * This should be SMP safe. Every external function (except trigger_reboot) 11 * grabs the wdt lock. No function in this file may call any exported 12 * function (excepting trigger_reboot). The disable counter is an atomic, so 13 * there should be no issues there. --TPH 14 */ 15 #include <linux/config.h> 16 17 #include <linux/module.h> 18 #include <stdarg.h> 19 #include <stddef.h> 20 #include <linux/init.h> 21 #include <linux/sched.h> 22 #include <linux/timer.h> 23 #include <linux/config.h> 24 #include <linux/pci.h> 25 #include <linux/delay.h> 26 #include <asm/io.h> 27 #include <asm/msr.h> 28 29 #include <cobalt/cobalt.h> 30 #include <cobalt/systype.h> 31 #include <cobalt/wdt.h> 32 #include <cobalt/superio.h> 33 34 #define DOGB 0x20 35 #define ALI_7101_WDT 0x92 36 #define ALI_WDT_ARM 0x01 37 #define WDT_3K_TIMEOUT (HZ >> 4) /* 1/16 second */ 38 39 #define WDT_SUPERIO_TIMEOUT (0x01) /* 1 minute */ 40 #define WDT_5K_TIMEOUT (HZ << 3) /* 8 seconds */ 41 42 #define WDT_DRIVER "Cobalt Networks Watchdog Timer driver" 43 #define WDT_DRIVER_VMAJ 1 44 #define WDT_DRIVER_VMIN 0 45 46 static unsigned long wdt_timeout; 47 static unsigned long long tsc_per_wdt; 48 static int initialized; 49 50 #ifdef CONFIG_COBALT_WDT 51 struct timer_list cobalt_wdt_timer; 52 static atomic_t cobalt_wdt_disable_count = ATOMIC_INIT(0); 53 static spinlock_t wdt_lock = SPIN_LOCK_UNLOCKED; 54 #endif 55 56 /* gen III */ 57 static struct pci_dev *cobalt_pmu; 58 static int use_pic; 59 /* gen V */ 60 static u16 superio_pm_port; 61 62 #ifdef CONFIG_COBALT_WDT 63 static void do_refresh(void); 64 static void do_cleardog(void); 65 static void do_disable(void); 66 static void do_reenable(void); 67 #endif 68 69 static unsigned long __init 70 chipset_setup(void) 71 { 72 unsigned char tmp; 73 if (cobt_is_3k()) { 74 /* 75 * Set up the PMU for 3k boards. It has a max 76 * of a 1 second timeout. 77 */ 78 struct pci_dev *south; 79 80 /* PMU (1543 ver A1-E) has a built-in WDT. Set it to 1 sec */ 81 cobalt_pmu = pci_find_device(PCI_VENDOR_ID_AL, 82 PCI_DEVICE_ID_AL_M7101, NULL); 83 if (!cobalt_pmu) { 84 EPRINTK("can't find south bridge for WDT\n"); 85 return 0; 86 } 87 pci_write_config_byte(cobalt_pmu, ALI_7101_WDT, 0x02); 88 89 /* why it is called 1543, but DevId is 1533 I'll never know */ 90 south = pci_find_device(PCI_VENDOR_ID_AL, 91 PCI_DEVICE_ID_AL_M1533, NULL); 92 if (!south) { 93 EPRINTK("can't find south bridge for WDT\n"); 94 use_pic = 1; 95 } else { 96 /* reversion # is here - must match ???1001?(b) 97 * else use PIC for WDT */ 98 pci_read_config_byte(south, 0x5e, &tmp); 99 use_pic = ((tmp & 0x1e) != 0x12); 100 } 101 102 if (!use_pic) { 103 /* set DOGB GPIO pin to OUTPUT - JIC */ 104 pci_read_config_byte(cobalt_pmu, 0x7d, &tmp); 105 pci_write_config_byte(cobalt_pmu, 0x7d, tmp | DOGB); 106 } 107 return WDT_3K_TIMEOUT; 108 } else if (cobt_is_monterey()) { 109 /* 110 * Set up the Nat. Semi SuperI/O for XTR. It has a 111 * minimum of a 1 minute timeout. 112 */ 113 114 /* superi/o -- select pm logical device and get base address */ 115 superio_pm_port = superio_ldev_base(PC87317_DEV_PM); 116 #ifdef CONFIG_COBALT_WDT 117 if (!superio_pm_port) { 118 return 0; 119 } 120 outb(PC87317_PMDEV_WDTO, superio_pm_port); 121 outb(WDT_SUPERIO_TIMEOUT, superio_pm_port + 1); 122 #endif 123 return WDT_5K_TIMEOUT; 124 } else if (cobt_is_alpine()) { 125 /* 126 * Set up the Nat. Semi SuperI/O for Alpine. It has a 127 * minimum of a 1 minute timeout. 128 */ 129 130 /* superi/o -- select pm logical device and get base address */ 131 superio_pm_port = superio_ldev_base(PC87417_DEV_SWC); 132 #ifdef CONFIG_COBALT_WDT 133 if (!superio_pm_port) { 134 return 0; 135 } 136 /* select the WDT bank of SWC */ 137 outb(PC87417_SWCBANK_WDT, superio_pm_port+PC87417_SWC_BANK); 138 /* clear event config... */ 139 tmp = inb(superio_pm_port+PC87417_WDT_CONFIG); 140 outb(0, superio_pm_port+PC87417_WDT_CONFIG); 141 /* ...before mucking with timeout */ 142 outb(WDT_SUPERIO_TIMEOUT, 143 superio_pm_port+PC87417_WDT_TIMEOUT); 144 /* restore the event config */ 145 outb(tmp, superio_pm_port+PC87417_WDT_CONFIG); 146 /* enable the counter */ 147 outb(1, superio_pm_port+PC87417_WDT_CONTROL); 148 #endif 149 return WDT_5K_TIMEOUT; 150 } 151 152 return 0; 153 } 154 155 void __init 156 cobalt_wdt_init(void) 157 { 158 unsigned long long start, stop; 159 160 printk(KERN_INFO "%s %d.%d (modified by jeff@404ster.com)\n", WDT_DRIVER,WDT_DRIVER_VMAJ,WDT_DRIVER_VMIN); 161 162 wdt_timeout = chipset_setup(); 163 164 /* figure out time */ 165 rdtscll(start); 166 udelay(100); 167 rdtscll(stop); 168 169 /* 170 * (int) (stop - start) * 10 == tsc per msec 171 * 1000 / HZ == msec per tick 172 * wdt_timeout == ticks per watchdog rearm 173 */ 174 tsc_per_wdt = (int) (stop - start) * 10 * (1000 * wdt_timeout / HZ); 175 176 #ifdef CONFIG_COBALT_WDT 177 /* set the timer going */ 178 init_timer(&cobalt_wdt_timer); 179 cobalt_wdt_timer.function = cobalt_wdt_refresh; 180 cobalt_wdt_timer.data = 1; 181 cobalt_wdt_timer.expires = jiffies + wdt_timeout; 182 add_timer(&cobalt_wdt_timer); 183 184 /* the first timer tick will set it going */ 185 186 if (cobt_is_3k() && use_pic) { 187 WPRINTK("Cobalt WDT - old board, using PIC controller\n"); 188 } 189 #endif /* CONFIG_COBALT_WDT */ 190 191 initialized = 1; 192 } 193 194 static inline void 195 hw_disable(void) 196 { 197 if (cobt_is_3k()) { 198 char tmp; 199 /* read the value, disable (reset) WDT */ 200 pci_read_config_byte(cobalt_pmu, ALI_7101_WDT, &tmp); 201 pci_write_config_byte(cobalt_pmu, ALI_7101_WDT, 202 (tmp & ~ALI_WDT_ARM)); 203 } else if (cobt_is_monterey()) { 204 outb(PC87317_PMDEV_WDTO, superio_pm_port); 205 outb(0, superio_pm_port + 1); 206 } else if (cobt_is_alpine()) { 207 unsigned char tmp; 208 /* select the WDT bank of SWC */ 209 outb(PC87417_SWCBANK_WDT, superio_pm_port + PC87417_SWC_BANK); 210 /* clear event config before mucking with timeout */ 211 tmp = inb(superio_pm_port + PC87417_WDT_CONFIG); 212 outb(0, superio_pm_port + PC87417_WDT_CONFIG); 213 /* 214 * Disable it by setting a 0 time-out. 215 * The spec says 00h is reserved, but NSC confirms this is the 216 * way to disable the device. 217 */ 218 outb(0, superio_pm_port + PC87417_WDT_TIMEOUT); 219 /* restore the event config */ 220 outb(tmp, superio_pm_port + PC87417_WDT_CONFIG); 221 } 222 } 223 224 static inline void 225 hw_enable(void) 226 { 227 if (cobt_is_3k()) { 228 unsigned char tmp; 229 /* read the value, disable (reset) WDT, enable WDT */ 230 pci_read_config_byte(cobalt_pmu, ALI_7101_WDT, &tmp); 231 pci_write_config_byte(cobalt_pmu, ALI_7101_WDT, 232 (tmp | ALI_WDT_ARM)); 233 if (use_pic) { 234 /* transition GPIO 5 (DOGB) to arm/clear timer */ 235 pci_read_config_byte(cobalt_pmu, 0x7e, &tmp); 236 pci_write_config_byte(cobalt_pmu, 0x7e, tmp ^ DOGB); 237 } 238 } else if (cobt_is_monterey()) { 239 outb(PC87317_PMDEV_WDTO, superio_pm_port); 240 outb(WDT_SUPERIO_TIMEOUT, superio_pm_port + 1); 241 } else if (cobt_is_alpine()) { 242 unsigned char tmp; 243 /* select the WDT bank of SWC */ 244 outb(PC87417_SWCBANK_WDT, superio_pm_port + PC87417_SWC_BANK); 245 /* clear event config before mucking with timeout */ 246 tmp = inb(superio_pm_port + PC87417_WDT_CONFIG); 247 outb(0, superio_pm_port + PC87417_WDT_CONFIG); 248 /* enable and refresh the timer */ 249 outb(WDT_SUPERIO_TIMEOUT, 250 superio_pm_port + PC87417_WDT_TIMEOUT); 251 outb(0x80, superio_pm_port + PC87417_WDT_CONTROL); 252 /* restore event config */ 253 outb(tmp, superio_pm_port + PC87417_WDT_CONFIG); 254 } 255 } 256 257 #ifdef CONFIG_COBALT_WDT 258 static void 259 do_refresh(void) 260 { 261 if (!initialized) { 262 return; 263 } 264 265 do_cleardog(); 266 267 /* re-arm the timer - this is locked in mod_timer() */ 268 mod_timer(&cobalt_wdt_timer, jiffies + wdt_timeout); 269 } 270 #endif 271 272 EXPORT_SYMBOL(cobalt_wdt_refresh); 273 void 274 cobalt_wdt_refresh(unsigned long refresh_timer) 275 { 276 #ifdef CONFIG_COBALT_WDT 277 unsigned long flags; 278 spin_lock_irqsave(&wdt_lock, flags); 279 do_refresh(); 280 spin_unlock_irqrestore(&wdt_lock, flags); 281 #endif 282 } 283 284 #ifdef CONFIG_COBALT_WDT 285 static void 286 do_cleardog(void) 287 { 288 static unsigned long long last_tsc = 0; 289 unsigned long long tmp; 290 291 if (!initialized || (atomic_read(&cobalt_wdt_disable_count) > 0)) { 292 return; 293 } 294 295 /* only bother if we're due */ 296 rdtscll(tmp); 297 if ((int)(tmp - last_tsc) < tsc_per_wdt) { 298 return; 299 } 300 301 if (cobt_is_3k() || cobt_is_monterey()) { 302 /* this is how we re-start the clock */ 303 hw_disable(); 304 hw_enable(); 305 } else if (cobt_is_alpine()) { 306 /* select the WDT bank of SWC */ 307 outb(PC87417_SWCBANK_WDT, superio_pm_port + PC87417_SWC_BANK); 308 /* refresh the timer */ 309 outb(0x80, superio_pm_port + PC87417_WDT_CONTROL); 310 } 311 312 rdtscll(last_tsc); 313 } 314 #endif 315 316 EXPORT_SYMBOL(cobalt_wdt_cleardog); 317 void 318 cobalt_wdt_cleardog(void) 319 { 320 #ifdef CONFIG_COBALT_WDT 321 unsigned long flags; 322 323 spin_lock_irqsave(&wdt_lock, flags); 324 do_cleardog(); 325 spin_unlock_irqrestore(&wdt_lock, flags); 326 #endif 327 } 328 329 /* 330 * this is called from machine_restart. it should not be used on 331 * 5k machines. 332 */ 333 EXPORT_SYMBOL(cobalt_wdt_trigger_reboot); 334 void 335 cobalt_wdt_trigger_reboot(void) 336 { 337 if (cobt_is_3k()) { 338 if (!cobalt_pmu) { 339 WPRINTK("no PMU found!\n"); 340 WPRINTK("reboot not possible!\n"); 341 return; 342 } 343 344 #ifdef CONFIG_COBALT_WDT 345 /* stop feeding it */ 346 del_timer_sync(&cobalt_wdt_timer); 347 #endif 348 349 /* kiss your rear goodbye... */ 350 initialized = 0; 351 hw_disable(); 352 hw_enable(); 353 } 354 } 355 356 #ifdef CONFIG_COBALT_WDT 357 static void 358 do_disable(void) 359 { 360 if (!initialized) { 361 return; 362 } 363 364 if (atomic_read(&cobalt_wdt_disable_count) == 0) { 365 atomic_inc(&cobalt_wdt_disable_count); 366 del_timer_sync(&cobalt_wdt_timer); 367 hw_disable(); 368 } 369 } 370 #endif 371 372 EXPORT_SYMBOL(cobalt_wdt_disable); 373 void 374 cobalt_wdt_disable(void) 375 { 376 #ifdef CONFIG_COBALT_WDT 377 unsigned long flags; 378 379 if (cobt_is_3k() && use_pic) { 380 WPRINTK("in PIC mode - cannot disable\n"); 381 return; 382 } 383 384 spin_lock_irqsave(&wdt_lock, flags); 385 do_disable(); 386 spin_unlock_irqrestore(&wdt_lock, flags); 387 #endif 388 } 389 390 #ifdef CONFIG_COBALT_WDT 391 static void 392 do_reenable(void) 393 { 394 int dcnt; 395 396 if (!initialized) { 397 return; 398 } 399 400 atomic_dec(&cobalt_wdt_disable_count); 401 dcnt = atomic_read(&cobalt_wdt_disable_count); 402 403 if (dcnt == 0) { 404 do_refresh(); 405 } else if (dcnt < 0) { 406 WPRINTK("too many enables\n"); 407 atomic_set(&cobalt_wdt_disable_count, 0); 408 } 409 } 410 #endif 411 412 413 EXPORT_SYMBOL(cobalt_wdt_reenable); 414 void 415 cobalt_wdt_reenable(void) 416 { 417 #ifdef CONFIG_COBALT_WDT 418 unsigned long flags; 419 420 spin_lock_irqsave(&wdt_lock, flags); 421 do_reenable(); 422 spin_unlock_irqrestore(&wdt_lock, flags); 423 #endif 424 } -
drivers/net/Kconfig
diff -Naur linux-2.6.20.orig/drivers/net/Kconfig linux-2.6.20/drivers/net/Kconfig
old new 1527 1527 <file:Documentation/networking/net-modules.txt>. The module 1528 1528 will be called e100. 1529 1529 1530 config E100_IGNORE_CSUM 1531 bool "Ignore bad EEPROM checksum" 1532 depends on E100 && EXPERIMENTAL && !CLEAN_COMPILE 1533 help 1534 This option tells the e100 driver to ignore bad EEPROM checksums. 1535 Usually this is a bad idea, as an incorrect checksum can indicate a 1536 serious issue with the network card. 1537 1538 If unsure, say N. 1539 1530 1540 config LNE390 1531 1541 tristate "Mylex EISA LNE390A/B support (EXPERIMENTAL)" 1532 1542 depends on NET_PCI && EISA && EXPERIMENTAL -
drivers/net/e100.c
diff -Naur linux-2.6.20.orig/drivers/net/e100.c linux-2.6.20/drivers/net/e100.c
old new 162 162 #define DRV_VERSION "3.5.17-k2"DRV_EXT 163 163 #define DRV_DESCRIPTION "Intel(R) PRO/100 Network Driver" 164 164 #define DRV_COPYRIGHT "Copyright(c) 1999-2006 Intel Corporation" 165 #define DRV_MODIFIED "Modified by <jeff@404ster.com> to ignore bad EEPROM checksums" 165 166 #define PFX DRV_NAME ": " 166 167 167 168 #define E100_WATCHDOG_PERIOD (2 * HZ) … … 758 759 * the sum of words should be 0xBABA */ 759 760 checksum = le16_to_cpu(0xBABA - checksum); 760 761 if(checksum != nic->eeprom[nic->eeprom_wc - 1]) { 762 #if defined(CONFIG_E100_IGNORE_CSUM) 763 DPRINTK(PROBE, ERR, "EEPROM corrupted, ignoring and moving on\n"); 764 DPRINTK(PROBE, ERR, " Caclulated Checksum: %X\n",checksum); 765 DPRINTK(PROBE, ERR, " EEPROM Checksum: %X\n",nic->eeprom[nic->eeprom_wc - 1]); 766 #else 761 767 DPRINTK(PROBE, ERR, "EEPROM corrupted\n"); 762 768 if (!eeprom_bad_csum_allow) 763 769 return -EAGAIN; 770 #endif 764 771 } 765 772 766 773 return 0; … … 2876 2883 if(((1 << debug) - 1) & NETIF_MSG_DRV) { 2877 2884 printk(KERN_INFO PFX "%s, %s\n", DRV_DESCRIPTION, DRV_VERSION); 2878 2885 printk(KERN_INFO PFX "%s\n", DRV_COPYRIGHT); 2886 #if defined(CONFIG_E100_IGNORE_CSUM) 2887 printk(KERN_INFO PFX "%s\n", DRV_MODIFIED); 2888 #endif 2879 2889 } 2880 2890 return pci_register_driver(&e100_driver); 2881 2891 } -
include/cobalt/acpi.h
diff -Naur linux-2.6.20.orig/include/cobalt/acpi.h linux-2.6.20/include/cobalt/acpi.h
old new 1 /* 2 * $Id: cobalt-acpi.h,v 1.7 2001/10/27 07:03:31 erik Exp $ 3 * cobalt-acpi.h : support for ACPI interrupts 4 * 5 * Copyright 2000 Cobalt Networks, Inc. 6 * Copyright 2001 Sun Microsystems, Inc. 7 */ 8 #ifndef COBALT_ACPI_H 9 #define COBALT_ACPI_H 10 11 #define SERVERWORKS_ACPI_INDEX_PORT 0x0cd6 12 #define SERVERWORKS_ACPI_DATA_PORT 0x0cd7 13 14 15 typedef struct 16 { 17 u16 hw_type; 18 u16 ev_type; 19 u32 ev_data; 20 } cobalt_acpi_evt; 21 22 enum __cobalt_acpi_hw_types 23 { 24 COBALT_ACPI_HW_ANY = 0x0000, 25 COBALT_ACPI_HW_OSB4 = 0x0001, 26 COBALT_ACPI_HW_CSB5 = 0x0002, 27 COBALT_ACPI_HW_PC8731X = 0x0003, 28 COBALT_ACPI_HW_PC8741X = 0x0004, 29 }; 30 31 enum __cobalt_acpi_event_types 32 { 33 COBALT_ACPI_EVT_NONE = 0x0000, 34 COBALT_ACPI_EVT_TMR = 0x0001, /* Timer Event */ 35 COBALT_ACPI_EVT_BM = 0x00002, /* Bus Master Event */ 36 COBALT_ACPI_EVT_GBL = 0x0003, /* BIOS Global Lock release */ 37 COBALT_ACPI_EVT_PWRBTN = 0x0004, /* Power Button press */ 38 COBALT_ACPI_EVT_SLPBTN = 0x0005, /* Sleep Button press */ 39 COBALT_ACPI_EVT_RTC = 0x0006, /* RTC Alarm */ 40 COBALT_ACPI_EVT_WAK = 0x0007, /* Wake event */ 41 COBALT_ACPI_EVT_GPE = 0x0008, /* General Purpose Event (ev_data = gpe number) */ 42 43 /* events greater than 0x7fff are symbolic events */ 44 COBALT_ACPI_EVT_SLED = 0x8000, /* Sled removal */ 45 COBALT_ACPI_EVT_THERM = 0x8001, /* Thermal trip */ 46 COBALT_ACPI_EVT_FAN = 0x8002, /* Fan Down */ 47 COBALT_ACPI_EVT_SM_INT = 0x8003, /* System Monitor Interrupt */ 48 COBALT_ACPI_EVT_VOLT = 0x8004, /* System Monitor Interrupt */ 49 50 }; 51 52 typedef int (* cobalt_acpi_hw_handler)( int irq, void *dev_id, struct pt_regs *regs, void * data ); 53 typedef int (* cobalt_acpi_enable_handler)( u16 ev_type, u16 ev_data, int en, void *data ); 54 typedef int (* cobalt_acpi_evt_handler)( cobalt_acpi_evt *evt, void * data ); 55 56 57 extern int cobalt_acpi_register_hw_handler( u16 hw_type, 58 cobalt_acpi_hw_handler hw_handler, 59 cobalt_acpi_enable_handler en_handler, 60 void *data ); 61 extern int cobalt_acpi_unregister_hw_handler( cobalt_acpi_hw_handler handler ); 62 63 extern int cobalt_acpi_register_trans_table( u16 hw_type, u16 table_len, u16 *table ); 64 extern int cobalt_acpi_unregister_trans_table( u16 hw_type ); 65 66 extern int cobalt_acpi_register_evt_handler( cobalt_acpi_evt_handler handler, 67 u16 evt_type, 68 void *data ); 69 extern int cobalt_acpi_unregister_evt_handler( cobalt_acpi_evt_handler handler ); 70 71 extern int cobalt_acpi_post_event( cobalt_acpi_evt evt ); 72 73 #ifdef CONFIG_COBALT_EMU_ACPI 74 int cobalt_acpi_generate_proc_evt( cobalt_acpi_evt * evt ); 75 #else 76 #define cobalt_acpi_generate_proc_evt( a ) 77 #endif 78 79 80 81 82 #endif /* COBALT_ACPI_H */ -
include/cobalt/cobalt.h
diff -Naur linux-2.6.20.orig/include/cobalt/cobalt.h linux-2.6.20/include/cobalt/cobalt.h
old new 1 /* $Id: cobalt.h,v 1.16 2002/11/04 17:54:15 thockin Exp $ */ 2 /* Copyright 2001 Sun Microsystems, Inc. */ 3 #include <linux/config.h> 4 #if !defined(COBALT_H) && defined(CONFIG_COBALT_RAQ) 5 #define COBALT_H 6 7 /* generational support - for easy checking */ 8 #ifdef CONFIG_COBALT_GEN_III 9 # define COBT_SUPPORT_GEN_III 1 10 #else 11 # define COBT_SUPPORT_GEN_III 0 12 #endif 13 14 #ifdef CONFIG_COBALT_GEN_V 15 # define COBT_SUPPORT_GEN_V 1 16 #else 17 # define COBT_SUPPORT_GEN_V 0 18 #endif 19 20 /* macros for consistent errors/warnings */ 21 #define EPRINTK(fmt, args...) \ 22 printk(KERN_ERR "%s:%s: " fmt , __FILE__ , __FUNCTION__ , ##args) 23 24 #define WPRINTK(fmt, args...) \ 25 printk(KERN_WARNING "%s:%s: " fmt , __FILE__ , __FUNCTION__ , ##args) 26 27 /* the root of /proc/cobalt */ 28 extern struct proc_dir_entry *proc_cobalt; 29 int cobalt_gen_proc_read(char *buf, int plen, char **start, off_t pos, 30 int len, int *eof); 31 32 //#ifdef CONFIG_COBALT_RAQ 33 /* keep this test up to date with new generation defines */ 34 #if !defined(CONFIG_COBALT_GEN_III) && !defined(CONFIG_COBALT_GEN_V) 35 /* barf if no generation has been selected */ 36 #error You asked for CONFIG_COBALT_RAQ, but no CONFIG_COBALT_GEN_* ! 37 #endif 38 39 /* accesses for CMOS */ 40 #include <linux/mc146818rtc.h> 41 #include <cobalt/nvram.h> 42 43 static inline int 44 cobalt_cmos_read_flag(const unsigned int flag) 45 { 46 unsigned long flags; 47 u16 cmosfl; 48 49 spin_lock_irqsave(&rtc_lock, flags); 50 cmosfl = CMOS_READ(COBT_CMOS_FLAG_BYTE_0) << 8; 51 cmosfl |= CMOS_READ(COBT_CMOS_FLAG_BYTE_1); 52 spin_unlock_irqrestore(&rtc_lock, flags); 53 54 return (cmosfl & flag) ? 1 : 0; 55 } 56 //#endif /* CONFIG_COBALT_RAQ */ 57 58 #endif /* !defined(COBALT_H) && defined(CONFIG_COBALT_RAQ) */ -
include/cobalt/i2c.h
diff -Naur linux-2.6.20.orig/include/cobalt/i2c.h linux-2.6.20/include/cobalt/i2c.h
old new 1 /* 2 * $Id: cobalt-i2c.h,v 1.3 2001/08/22 05:48:04 asun Exp $ 3 * cobalt-i2c.h : I2C support for LCD/Front Panel 4 * 5 * Copyright 2000 Cobalt Networks, Inc. 6 * Copyright 2001 Sun Microsystems, Inc. 7 */ 8 #ifndef COBALT_I2C_H 9 #define COBALT_I2C_H 10 11 #include <linux/types.h> 12 #include <cobalt/cobalt.h> 13 14 #define COBALT_I2C_DEV_LED_I 0x40 15 #define COBALT_I2C_DEV_LED_II 0x42 16 #define COBALT_I2C_DEV_LCD_DATA 0x4a 17 #define COBALT_I2C_DEV_LCD_INST 0x48 18 #define COBALT_I2C_DEV_FP_BUTTONS 0x41 19 #define COBALT_I2C_DEV_DRV_SWITCH 0x45 20 #define COBALT_I2C_DEV_RULER 0x46 21 #define COBALT_I2C_DEV_LM77 0x90 22 #define COBALT_I2C_DEV_ADM1029 0x5e 23 #define COBALT_I2C_DEV_AT24C02 0xae 24 25 #define COBALT_I2C_READ 0x01 26 #define COBALT_I2C_WRITE 0x00 27 28 extern int cobalt_i2c_reset(void); 29 extern int cobalt_i2c_read_byte(const int dev, const int index); 30 extern int cobalt_i2c_read_word(const int dev, const int index); 31 extern int cobalt_i2c_read_block(const int dev, const int index, 32 unsigned char *data, int count); 33 extern int cobalt_i2c_write_byte(const int dev, const int index, 34 const u8 val); 35 extern int cobalt_i2c_write_word(const int dev, const int index, 36 const u16 val); 37 extern int cobalt_i2c_write_block(const int dev, const int index, 38 unsigned char *data, int count); 39 40 #endif /* COBALT_I2C_H */ -
include/cobalt/lcd.h
diff -Naur linux-2.6.20.orig/include/cobalt/lcd.h linux-2.6.20/include/cobalt/lcd.h
old new 1 /* 2 * $Id: cobalt-lcd.h,v 1.12 2001/11/30 05:38:46 asun Exp $ 3 * cobalt-lcd.h : some useful defines for the Cobalt LCD driver 4 * (must be useable from both kernel and user space) 5 * 6 * Copyright 1996-2000 Cobalt Networks, Inc. 7 * Copyright 2001 Sun Microsystems, Inc. 8 * 9 * By: Andrew Bose 10 * Timothy Stonis (x86 version) 11 * Tim Hockin 12 * Adrian Sun 13 * Erik Gilling 14 * Duncan Laurie 15 */ 16 #ifndef COBALT_LCD_H 17 #define COBALT_LCD_H 18 19 #ifdef __KERNEL__ 20 #include <cobalt/cobalt.h> 21 #endif 22 #include <cobalt/led.h> 23 24 #define COBALT_LCD_LINELEN 40 25 struct lcd_display { 26 unsigned long buttons; 27 int size1; 28 int size2; 29 unsigned char line1[COBALT_LCD_LINELEN]; 30 unsigned char line2[COBALT_LCD_LINELEN]; 31 unsigned char cursor_address; 32 unsigned char character; 33 unsigned char leds; 34 unsigned char *RomImage; 35 }; 36 37 /* different lcd types */ 38 #define LCD_TYPE_UNKNOWN 0 39 #define LCD_TYPE_PARALLEL 1 40 #define LCD_TYPE_PARALLEL_B 2 41 #define LCD_TYPE_I2C 3 42 43 /* Function command codes for ioctl */ 44 #define LCD_On 1 45 #define LCD_Off 2 46 #define LCD_Clear 3 47 #define LCD_Reset 4 48 #define LCD_Cursor_Left 5 49 #define LCD_Cursor_Right 6 50 #define LCD_Disp_Left 7 51 #define LCD_Disp_Right 8 52 #define LCD_Get_Cursor 9 53 #define LCD_Set_Cursor 10 54 #define LCD_Home 11 55 #define LCD_Read 12 56 #define LCD_Write 13 57 #define LCD_Cursor_Off 14 58 #define LCD_Cursor_On 15 59 #define LCD_Get_Cursor_Pos 16 60 #define LCD_Set_Cursor_Pos 17 61 #define LCD_Blink_Off 18 62 #define LCD_Raw_Inst 19 63 #define LCD_Raw_Data 20 64 #define LCD_Type 21 65 66 /* LED controls */ 67 #define LED_Set 40 68 #define LED_Bit_Set 41 69 #define LED_Bit_Clear 42 70 #define LED32_Set 43 71 #define LED32_Bit_Set 44 72 #define LED32_Bit_Clear 45 73 #define LED32_Get 46 74 75 /* button ioctls */ 76 #define BUTTON_Read 50 77 78 /* Button defs */ 79 #define BUTTON_Next 0x3D 80 #define BUTTON_Next_B 0x7E 81 #define BUTTON_Reset_B 0xFC 82 #define BUTTON_NONE_B 0xFE 83 #define BUTTON_Left_B 0xFA 84 #define BUTTON_Right_B 0xDE 85 #define BUTTON_Up_B 0xF6 86 #define BUTTON_Down_B 0xEE 87 #define BUTTON_Enter_B 0xBE 88 89 #define BUTTON_MASK 0xFE 90 91 void cobalt_lcd_start_twiddle(void); 92 void cobalt_lcd_stop_twiddle(void); 93 void cobalt_lcd_off(void); 94 95 #endif /* COBALT_LCD_H */ -
include/cobalt/led.h
diff -Naur linux-2.6.20.orig/include/cobalt/led.h linux-2.6.20/include/cobalt/led.h
old new 1 /* 2 * $Id: cobalt-led.h,v 1.7 2001/11/08 01:15:33 thockin Exp $ 3 * cobalt-led.c 4 * 5 * Copyright 1996-2000 Cobalt Networks, Inc. 6 * Copyright 2001 Sun Microsystems, Inc. 7 * 8 * By: Andrew Bose 9 * Timothy Stonis (x86 version) 10 * Tim Hockin 11 * Adrian Sun 12 * Erik Gilling 13 * Duncan Laurie 14 */ 15 #ifndef COBALT_LED_H 16 #define COBALT_LED_H 17 18 /* the set of all leds available on Cobalt systems */ 19 #define LED_SHUTDOWN (1 << 0) 20 #define LED_WEBLIGHT (1 << 1) 21 #define LED_COBALTLOGO (1 << 2) 22 #define LED_ETH0_TXRX (1 << 3) 23 #define LED_ETH0_LINK (1 << 4) 24 #define LED_ETH1_TXRX (1 << 5) 25 #define LED_ETH1_LINK (1 << 6) 26 #define LED_DISK0 (1 << 7) 27 #define LED_DISK1 (1 << 8) 28 #define LED_DISK2 (1 << 9) 29 #define LED_DISK3 (1 << 10) 30 #define LED_SYSFAULT (1 << 11) 31 #define LED_MONTEREY_UNUSED0 (1 << 12) 32 #define LED_MONTEREY_UNUSED1 (1 << 13) 33 /* LED_MONTEREY_UNUSED2 is below */ 34 #define LED_HEART LED_MONTEREY_UNUSED0 35 #define LED_SPARE LED_MONTEREY_UNUSED1 36 #define LED_SLED0 (1 << 14) 37 #define LED_SLED1 (1 << 15) 38 #define LED_SLED2 (1 << 16) 39 #define LED_SLED3 (1 << 17) 40 #define LED_MONTEREY_UNUSED2 (1 << 18) 41 #define LED_SPARE2 LED_MONTEREY_UNUSED2 42 43 #ifdef __KERNEL__ 44 45 extern void cobalt_led_set(const unsigned int leds); 46 extern void cobalt_led_set_bits(const unsigned int leds); 47 extern void cobalt_led_clear_bits(const unsigned int leds); 48 extern void cobalt_led_set_lazy(const unsigned int leds); 49 extern void cobalt_led_set_bits_lazy(const unsigned int leds); 50 extern void cobalt_led_clear_bits_lazy(const unsigned int leds); 51 extern unsigned int cobalt_led_get(void); 52 53 extern int cobalt_fpled_register(unsigned int (*fn)(void *), void *data); 54 extern int cobalt_fpled_unregister(unsigned int (*fn)(void *), void *data); 55 56 #endif /* __KERNEL__ */ 57 58 #endif /* COBALT_LED_H */ 59 -
include/cobalt/misc.h
diff -Naur linux-2.6.20.orig/include/cobalt/misc.h linux-2.6.20/include/cobalt/misc.h
old new 1 /* $Id: cobalt-misc.h,v 1.1 2001/04/04 03:36:43 thockin Exp $ */ 2 /* Copyright 2001 Sun Microsystems, Inc. */ 3 #ifndef COBALT_MISC_H 4 #define COBALT_MISC_H 5 6 void cobalt_flush(void); 7 void cobalt_nmi(unsigned char reason, struct pt_regs *regs); 8 void cobalt_restart(void); 9 void cobalt_halt(void); 10 void cobalt_power_off(void); 11 12 #endif -
include/cobalt/net.h
diff -Naur linux-2.6.20.orig/include/cobalt/net.h linux-2.6.20/include/cobalt/net.h
old new 1 /* $Id: cobalt-net.h,v 1.3 2002/10/25 01:02:42 thockin Exp $ */ 2 /* Copyright 2001 Sun Microsystems, Inc. */ 3 #ifndef COBALT_NET_H 4 #define COBALT_NET_H 5 6 #include <linux/netdevice.h> 7 #include <linux/config.h> 8 9 void cobalt_net_register(struct net_device *ndev); 10 void cobalt_net_unregister(struct net_device *ndev); 11 12 #endif -
include/cobalt/nvram.h
diff -Naur linux-2.6.20.orig/include/cobalt/nvram.h linux-2.6.20/include/cobalt/nvram.h
old new 1 /* 2 * $Id: cobalt-nvram.h,v 1.21 2002/11/02 00:57:06 thockin Exp $ 3 * cobalt-nvram.h : defines for the various fields in the cobalt NVRAM 4 * 5 * Copyright 2001 Sun Microsystems, Inc. 6 */ 7 8 #ifndef COBALT_NVRAM_H 9 #define COBALT_NVRAM_H 10 11 #include <linux/nvram.h> 12 13 #define COBT_CMOS_INFO_MAX 0x7f /* top address allowed */ 14 #define COBT_CMOS_BIOS_DRIVE_INFO 0x12 /* drive info would go here */ 15 16 #define COBT_CMOS_CKS_START NVRAM_OFFSET(0x0e) 17 #define COBT_CMOS_CKS_END NVRAM_OFFSET(0x7f) 18 19 /* flag bytes - 16 flags for now, leave room for more */ 20 #define COBT_CMOS_FLAG_BYTE_0 NVRAM_OFFSET(0x10) 21 #define COBT_CMOS_FLAG_BYTE_1 NVRAM_OFFSET(0x11) 22 23 /* flags in flag bytes - up to 16 */ 24 #define COBT_CMOS_FLAG_MIN 0x0001 25 #define COBT_CMOS_CONSOLE_FLAG 0x0001 /* console on/off */ 26 #define COBT_CMOS_DEBUG_FLAG 0x0002 /* ROM debug messages */ 27 #define COBT_CMOS_AUTO_PROMPT_FLAG 0x0004 /* boot to ROM prompt? */ 28 #define COBT_CMOS_CLEAN_BOOT_FLAG 0x0008 /* set by a clean shutdown */ 29 #define COBT_CMOS_HW_NOPROBE_FLAG 0x0010 /* go easy on the probing */ 30 #define COBT_CMOS_SYSFAULT_FLAG 0x0020 /* system fault detected */ 31 #define COBT_CMOS_OOPSPANIC_FLAG 0x0040 /* panic on oops */ 32 #define COBT_CMOS_DELAY_CACHE_FLAG 0x0080 /* delay cache initialization */ 33 #define COBT_CMOS_NOLOGO_FLAG 0x0100 /* hide "C" logo @ boot */ 34 #define COBT_CMOS_VERSION_FLAG 0x0200 /* the version field is valid */ 35 #define COBT_CMOS_FLAG_MAX 0x0200 36 37 /* leave byte 0x12 blank - Linux looks for drive info here */ 38 39 /* CMOS structure version, valid if COBT_CMOS_VERSION_FLAG is true */ 40 #define COBT_CMOS_VERSION NVRAM_OFFSET(0x13) 41 #define COBT_CMOS_VER_BTOCODE 1 /* min. version needed for btocode */ 42 43 /* index of default boot method */ 44 #define COBT_CMOS_BOOT_METHOD NVRAM_OFFSET(0x20) 45 #define COBT_CMOS_BOOT_METHOD_DISK 0 46 #define COBT_CMOS_BOOT_METHOD_ROM 1 47 #define COBT_CMOS_BOOT_METHOD_NET 2 48 #define COBT_CMOS_BOOT_METHOD_NNET 3 49 #define COBT_CMOS_BOOT_METHOD_OTHER 4 50 51 #define COBT_CMOS_BOOT_DEV_MIN NVRAM_OFFSET(0x21) 52 /* major #, minor # of first through fourth boot device */ 53 #define COBT_CMOS_BOOT_DEV0_MAJ NVRAM_OFFSET(0x21) 54 #define COBT_CMOS_BOOT_DEV0_MIN NVRAM_OFFSET(0x22) 55 #define COBT_CMOS_BOOT_DEV1_MAJ NVRAM_OFFSET(0x23) 56 #define COBT_CMOS_BOOT_DEV1_MIN NVRAM_OFFSET(0x24) 57 #define COBT_CMOS_BOOT_DEV2_MAJ NVRAM_OFFSET(0x25) 58 #define COBT_CMOS_BOOT_DEV2_MIN NVRAM_OFFSET(0x26) 59 #define COBT_CMOS_BOOT_DEV3_MAJ NVRAM_OFFSET(0x27) 60 #define COBT_CMOS_BOOT_DEV3_MIN NVRAM_OFFSET(0x28) 61 #define COBT_CMOS_BOOT_DEV_MAX NVRAM_OFFSET(0x28) 62 63 /* checksum of bytes 0xe-0x7f */ 64 #define COBT_CMOS_CHECKSUM NVRAM_OFFSET(0x2e) 65 66 /* running uptime counter, units of 5 minutes (32 bits =~ 41000 years) */ 67 #define COBT_CMOS_UPTIME_0 NVRAM_OFFSET(0x30) 68 #define COBT_CMOS_UPTIME_1 NVRAM_OFFSET(0x31) 69 #define COBT_CMOS_UPTIME_2 NVRAM_OFFSET(0x32) 70 #define COBT_CMOS_UPTIME_3 NVRAM_OFFSET(0x33) 71 72 /* count of successful boots (32 bits) */ 73 #define COBT_CMOS_BOOTCOUNT_0 NVRAM_OFFSET(0x38) 74 #define COBT_CMOS_BOOTCOUNT_1 NVRAM_OFFSET(0x39) 75 #define COBT_CMOS_BOOTCOUNT_2 NVRAM_OFFSET(0x3a) 76 #define COBT_CMOS_BOOTCOUNT_3 NVRAM_OFFSET(0x3b) 77 78 /* 13 bytes: system serial number, same as on the back of the system */ 79 #define COBT_CMOS_SYS_SERNUM_LEN 13 80 #define COBT_CMOS_SYS_SERNUM_0 NVRAM_OFFSET(0x40) 81 #define COBT_CMOS_SYS_SERNUM_1 NVRAM_OFFSET(0x41) 82 #define COBT_CMOS_SYS_SERNUM_2 NVRAM_OFFSET(0x42) 83 #define COBT_CMOS_SYS_SERNUM_3 NVRAM_OFFSET(0x43) 84 #define COBT_CMOS_SYS_SERNUM_4 NVRAM_OFFSET(0x44) 85 #define COBT_CMOS_SYS_SERNUM_5 NVRAM_OFFSET(0x45) 86 #define COBT_CMOS_SYS_SERNUM_6 NVRAM_OFFSET(0x46) 87 #define COBT_CMOS_SYS_SERNUM_7 NVRAM_OFFSET(0x47) 88 #define COBT_CMOS_SYS_SERNUM_8 NVRAM_OFFSET(0x48) 89 #define COBT_CMOS_SYS_SERNUM_9 NVRAM_OFFSET(0x49) 90 #define COBT_CMOS_SYS_SERNUM_10 NVRAM_OFFSET(0x4a) 91 #define COBT_CMOS_SYS_SERNUM_11 NVRAM_OFFSET(0x4b) 92 #define COBT_CMOS_SYS_SERNUM_12 NVRAM_OFFSET(0x4c) 93 /* checksum for serial num - 1 byte */ 94 #define COBT_CMOS_SYS_SERNUM_CSUM NVRAM_OFFSET(0x4f) 95 96 #define COBT_CMOS_ROM_REV_MAJ NVRAM_OFFSET(0x50) 97 #define COBT_CMOS_ROM_REV_MIN NVRAM_OFFSET(0x51) 98 #define COBT_CMOS_ROM_REV_REV NVRAM_OFFSET(0x52) 99 100 #define COBT_CMOS_BTO_CODE_0 NVRAM_OFFSET(0x53) 101 #define COBT_CMOS_BTO_CODE_1 NVRAM_OFFSET(0x54) 102 #define COBT_CMOS_BTO_CODE_2 NVRAM_OFFSET(0x55) 103 #define COBT_CMOS_BTO_CODE_3 NVRAM_OFFSET(0x56) 104 105 #define COBT_CMOS_BTO_IP_CSUM NVRAM_OFFSET(0x57) 106 #define COBT_CMOS_BTO_IP_0 NVRAM_OFFSET(0x58) 107 #define COBT_CMOS_BTO_IP_1 NVRAM_OFFSET(0x59) 108 #define COBT_CMOS_BTO_IP_2 NVRAM_OFFSET(0x5a) 109 #define COBT_CMOS_BTO_IP_3 NVRAM_OFFSET(0x5b) 110 111 /* byte for load/run methods */ 112 #define COBT_CMOS_BOOT_TYPE NVRAM_OFFSET(0x5c) 113 #define COBT_CMOS_BOOT_KERN_DEV 0x01 /* use kernel on major/minor */ 114 #define COBT_CMOS_BOOT_KERN_ROM 0x02 /* use rom kernel */ 115 #define COBT_CMOS_BOOT_KERN_NET 0x03 /* use net kernel */ 116 #define COBT_CMOS_BOOT_KERN_MASK 0x0f /* mask for above */ 117 118 #define COBT_CMOS_BOOT_FS_DEV 0x10 /* use major/minor number dev */ 119 #define COBT_CMOS_BOOT_FS_NET 0x30 /* use net fs */ 120 #define COBT_CMOS_BOOT_FS_MASK 0xf0 /* mask for above */ 121 122 /* HA mode we're in (Twin Peaks) */ 123 #define COBT_CMOS_HA_MODE NVRAM_OFFSET(0x62) 124 125 #endif /* COBALT_NVRAM_H */ -
include/cobalt/ruler.h
diff -Naur linux-2.6.20.orig/include/cobalt/ruler.h linux-2.6.20/include/cobalt/ruler.h
old new 1 /* $Id: cobalt-ruler.h,v 1.4 2001/06/08 20:46:44 thockin Exp $ */ 2 /* Copyright 2001 Sun Microsystems, Inc. */ 3 #ifndef COBALT_RULER_H 4 #define COBALT_RULER_H 5 6 #include <linux/ide.h> 7 8 void cobalt_ruler_register(ide_drive_t *hwif); 9 void cobalt_ruler_unregister(ide_drive_t *hwif); 10 11 //typedef int (*cob_busproc_t) (struct hwif_s *, int); 12 13 //int *cob_busproc_t (ide_drive_t *, int); 14 15 #endif -
include/cobalt/sensors.h
diff -Naur linux-2.6.20.orig/include/cobalt/sensors.h linux-2.6.20/include/cobalt/sensors.h
old new 1 /* $Id: cobalt-sensors.h,v 1.2 2001/09/25 18:10:29 thockin Exp $ */ 2 /* Copyright 2001 Sun Microsystems, Inc. */ 3 #ifndef COBALT_SENSORS_H 4 #define COBALT_SENSORS_H 5 6 #include <cobalt/cobalt.h> 7 8 extern unsigned int cobalt_nthermals; 9 extern unsigned int cobalt_nvoltages; 10 11 /* return NULL if the sensor doesn't exist, fill buf if it does */ 12 char *__cobalt_thermal_read(unsigned int sensor, char *buf, int len); 13 char *__cobalt_voltage_read(unsigned int sensor, char *buf, int len); 14 15 static inline char * 16 cobalt_thermal_read(unsigned int sensor) 17 { 18 char buf[32]; 19 return __cobalt_thermal_read(sensor, buf, sizeof(buf)-1); 20 } 21 22 static inline char * 23 cobalt_voltage_read(unsigned int sensor) 24 { 25 char buf[32]; 26 return __cobalt_voltage_read(sensor, buf, sizeof(buf)-1); 27 } 28 29 #endif -
include/cobalt/serialnum.h
diff -Naur linux-2.6.20.orig/include/cobalt/serialnum.h linux-2.6.20/include/cobalt/serialnum.h
old new 1 /* 2 * $Id: cobalt-serialnum.h,v 1.1 2001/03/07 01:58:24 thockin Exp $ 3 * cobalt-serialnum.h : access to the DS2401 serial number 4 * 5 * Copyright 2000 Cobalt Networks, Inc. 6 * Copyright 2001 Sun Microsystems, Inc. 7 */ 8 #ifndef COBALT_SERIALNUM_H 9 #define COBALT_SERIALNUM_H 10 11 #include <cobalt/cobalt.h> 12 13 char *cobalt_serialnum_get(void); 14 unsigned long cobalt_hostid_get(void); 15 16 #endif /* COBALT_SERIALNUM_H */ -
include/cobalt/superio.h
diff -Naur linux-2.6.20.orig/include/cobalt/superio.h linux-2.6.20/include/cobalt/superio.h
old new 1 /* 2 * $Id: cobalt-superio.h,v 1.11 2001/11/02 12:00:03 duncan Exp $ 3 * cobalt-superio.h : SuperIO support for Sun/Cobalt servers 4 * 5 * Copyright 2000 Cobalt Networks, Inc. 6 * Copyright 2001 Sun Microsystems, Inc. 7 */ 8 #ifndef COBALT_SUPERIO_H 9 #define COBALT_SUPERIO_H 10 11 #include <cobalt/cobalt.h> 12 #include <cobalt/systype.h> 13 14 /* the lock that protects superio accesses */ 15 extern spinlock_t cobalt_superio_lock; 16 17 /* 18 * The main functions of the SuperIO are accessed via index/data registers 19 * These are the same for both SuperIO chip families 20 */ 21 #define SUPERIO_INDEX_PORT 0x2e 22 #define SUPERIO_DATA_PORT 0x2f 23 24 /* 25 * This index allows you to select a logical device 26 */ 27 #define SUPERIO_LOGICAL_DEV 0x07 28 29 /* 30 * Type of SUPERIO 31 */ 32 #define SUPERIO_SID 0x20 33 34 /* 35 * Some indices that are common to all logical devices 36 */ 37 #define SUPERIO_ACTIVATE 0x30 38 #define SUPERIO_ADDR_HIGH 0x60 39 #define SUPERIO_ADDR_LOW 0x61 40 #define SUPERIO_INTR_PIN 0x70 41 #define SUPERIO_INTR_TYPE 0x71 42 43 44 /* 45 * PC87317 SuperIO is found on XTR 46 */ 47 48 /* 49 * logical devices - write to LOGICAL_DEV index 50 */ 51 #define PC87317_DEV_RTC 0x02 52 #define PC87317_DEV_GPIO 0x07 53 #define PC87317_DEV_PM 0x08 54 55 /* withing the PM dev, are the following indices */ 56 #define PC87317_PMDEV_WDTO 0x05 57 #define PC87317_PMDEV_GPELO 0x0e 58 #define PC87317_PMDEV_GPEHI 0x0f 59 60 /* within the APC bank of RTC */ 61 #define PC87317_APCR1 0x40 62 #define PC87317_APCR2 0x41 63 #define PC87317_APCR3 0x49 64 #define PC87317_APCR4 0x4a 65 #define PC87317_APCR5 0x4b 66 #define PC87317_APCR6 0x4c 67 #define PC87317_APCR7 0x4d 68 69 #define PC87317_RTC_BANK_MAIN 0 70 #define PC87317_RTC_BANK_RTC 1 71 #define PC87317_RTC_BANK_APC 2 72 #define PC87317_RTC_CRA 0x0a 73 #define PC87317_RTC_BANK_0 0x20 74 #define PC87317_RTC_BANK_1 0x30 75 #define PC87317_RTC_BANK_2 0x40 76 77 #define PC87317_PWRBUTTON 0x01 78 #define PC87317_PM1_STATUS 0x01 79 80 /* offsets from GPEHI/GPELO */ 81 #define PC87317_GPE_GP1_STS0 0x00 82 #define PC87317_GPE_GP1_STS1 0x01 83 #define PC87317_GPE_GP1_STS2 0x02 84 #define PC87317_GPE_GP1_STS3 0x03 85 #define PC87317_GPE_GP1_EN0 0x04 86 #define PC87317_GPE_GP1_EN1 0x05 87 #define PC87317_GPE_GP1_EN2 0x06 88 #define PC87317_GPE_GP1_EN3 0x07 89 #define PC87317_GPE_GP2_EN0 0x08 90 #define PC87317_GPE_SMI_CMD 0x0c 91 92 /* 93 * PC87417 family is found on alpine 94 */ 95 96 #define PC87417_DEV_SWC 0x4 97 #define PC87417_DEV_GPIO 0x7 98 #define PC87417_DEV_RTC 0x10 99 100 /* registers in the SWC dev */ 101 #define PC87417_SWC_PWONCTL 0x9 102 /* 103 * within the System Wake Control device, there are banks, write the bank you 104 * want to SWC_BANK 105 */ 106 #define PC87417_SWC_BANK 0xf 107 #define PC87417_SWCBANK_ACPI 0x2 108 #define PC87417_SWCBANK_WDT 0x3 109 110 /* 111 * the SWC WDT bank has 3 main registers 112 */ 113 #define PC87417_WDT_CONTROL 0x10 114 #define PC87417_WDT_TIMEOUT 0x11 115 #define PC87417_WDT_CONFIG 0x12 116 117 /* 118 * within the SWC, two regs serve as index/data for wake-event enabling 119 */ 120 #define PC87417_SWC_WKEVENT 0x0 121 #define PC87417_SWC_WKSTATE 0x1 122 #define PC87417_SWCWKEVENT_GPIOE42 0xa 123 #define PC87417_SWCWKEVENT_RTC 0x18 124 125 126 /* 127 * types of superIOs 128 */ 129 enum superio_type_t 130 { 131 SIO_TYPE_UNKNOWN, 132 SIO_TYPE_PC8731X, 133 SIO_TYPE_PC8741X, 134 }; 135 136 137 138 #define PC8731X_SID 0xd0 139 #define PC9731X_SID 0xdf 140 #define PC8741X_SID 0xee 141 142 static inline int superio_type( void ) 143 { 144 u8 reg; 145 unsigned long flags; 146 enum superio_type_t type; 147 148 spin_lock_irqsave(&cobalt_superio_lock, flags); 149 150 outb(SUPERIO_SID, SUPERIO_INDEX_PORT); 151 reg = inb( SUPERIO_DATA_PORT ); 152 switch( reg ) 153 { 154 case PC8731X_SID: 155 case PC9731X_SID: 156 type = SIO_TYPE_PC8731X; 157 break; 158 159 case PC8741X_SID: 160 type = SIO_TYPE_PC8741X; 161 break; 162 163 default: 164 type = SIO_TYPE_UNKNOWN; 165 break; 166 } 167 168 spin_unlock_irqrestore(&cobalt_superio_lock, flags); 169 170 return type; 171 } 172 173 /* 174 * stuff to make life easier 175 */ 176 177 /* read the base address of a particular superio logical device */ 178 #define superio_ldev_base(ldev) superio_ldev_base_n(ldev, 0) 179 static inline unsigned short 180 superio_ldev_base_n(int ldev, int n) 181 { 182 unsigned long flags; 183 unsigned short addr; 184 185 spin_lock_irqsave(&cobalt_superio_lock, flags); 186 187 /* select the logical device */ 188 outb(SUPERIO_LOGICAL_DEV, SUPERIO_INDEX_PORT); 189 outb(ldev, SUPERIO_DATA_PORT); 190 191 /* read the 2-byte base address */ 192 outb(SUPERIO_ADDR_HIGH+(n*2), SUPERIO_INDEX_PORT); 193 addr = inb(SUPERIO_DATA_PORT) << 8; 194 outb(SUPERIO_ADDR_LOW+(n*2), SUPERIO_INDEX_PORT); 195 addr |= inb(SUPERIO_DATA_PORT); 196 197 spin_unlock_irqrestore(&cobalt_superio_lock, flags); 198 199 return addr; 200 } 201 202 static inline void 203 superio_set_rtc_bank(const unsigned int page) 204 { 205 if (cobt_is_monterey()) { 206 unsigned char val; 207 208 val = CMOS_READ(0xa); 209 val &= ~0x70; 210 switch (page) { 211 case PC87317_RTC_BANK_MAIN: 212 val |= 0x20; 213 break; 214 case PC87317_RTC_BANK_RTC: 215 val |= 0x30; 216 break; 217 case PC87317_RTC_BANK_APC: 218 val |= 0x40; 219 break; 220 } 221 CMOS_WRITE(val, 0xa); 222 } 223 } 224 225 #endif /* COBALT_SUPERIO_H */ -
include/cobalt/systype.h
diff -Naur linux-2.6.20.orig/include/cobalt/systype.h linux-2.6.20/include/cobalt/systype.h
old new 1 /* 2 * $Id: cobalt-systype.h,v 1.8 2002/08/08 22:46:50 carls Exp $ 3 * cobalt-systype.h : figure out what Cobalt system we are on 4 * 5 * Copyright 2000 Cobalt Networks, Inc. 6 * Copyright 2001-2002 Sun Microsystems, Inc. 7 */ 8 #ifndef COBALT_SYSTYPE_H 9 #define COBALT_SYSTYPE_H 10 11 #include <cobalt/cobalt.h> 12 13 typedef enum { 14 COBT_UNINITIALIZED, 15 COBT_UNKNOWN, 16 COBT_PACIFICA, 17 COBT_CARMEL, 18 COBT_MONTEREY, 19 COBT_ALPINE, 20 COBT_BIGBEAR, 21 } cobt_sys_t; 22 23 extern cobt_sys_t cobt_type; 24 extern cobt_sys_t cobalt_systype_probe(void); 25 extern unsigned long cobt_rev; 26 27 /* 28 * one test for each major board-type 29 * COBT_SUPPORT_* from cobalt.h 30 */ 31 32 /* pacifica is the RaQ 3 and RaQ 4 platform */ 33 static inline int 34 cobt_is_pacifica(void) 35 { 36 if (!COBT_SUPPORT_GEN_III) { 37 return 0; 38 } 39 if (cobt_type == COBT_UNINITIALIZED) { 40 cobalt_systype_probe(); 41 } 42 return (cobt_type == COBT_PACIFICA); 43 } 44 45 /* carmel is the Qube 3 platform */ 46 static inline int 47 cobt_is_carmel(void) 48 { 49 if (!COBT_SUPPORT_GEN_III) { 50 return 0; 51 } 52 if (cobt_type == COBT_UNINITIALIZED) { 53 cobalt_systype_probe(); 54 } 55 return (cobt_type == COBT_CARMEL); 56 } 57 58 /* monterey is the RaQ XTR platform */ 59 static inline int 60 cobt_is_monterey(void) 61 { 62 if (!COBT_SUPPORT_GEN_V) { 63 return 0; 64 } 65 if (cobt_type == COBT_UNINITIALIZED) { 66 cobalt_systype_probe(); 67 } 68 return (cobt_type == COBT_MONTEREY); 69 } 70 71 static inline int 72 cobt_is_alpine(void) 73 { 74 if (!COBT_SUPPORT_GEN_V) { 75 return 0; 76 } 77 if (cobt_type == COBT_UNINITIALIZED) { 78 cobalt_systype_probe(); 79 } 80 return (cobt_type == COBT_ALPINE); 81 } 82 83 static inline int 84 cobt_is_bigbear(void) 85 { 86 if (!COBT_SUPPORT_GEN_V) { 87 return 0; 88 } 89 if (cobt_type == COBT_UNINITIALIZED) { 90 cobalt_systype_probe(); 91 } 92 return (cobt_type == COBT_BIGBEAR); 93 } 94 95 /* one for each major generation */ 96 #define cobt_is_3k() (cobt_is_pacifica() || cobt_is_carmel()) 97 #define cobt_is_5k() (cobt_is_monterey() || cobt_is_alpine() || cobt_is_bigbear()) 98 99 #endif -
include/cobalt/wdt.h
diff -Naur linux-2.6.20.orig/include/cobalt/wdt.h linux-2.6.20/include/cobalt/wdt.h
old new 1 /* $Id: cobalt-wdt.h,v 1.1 2001/03/07 01:58:24 thockin Exp $ */ 2 /* Copyright 2001 Sun Microsystems, Inc. */ 3 #ifndef COBALT_WDT_H 4 #define COBALT_WDT_H 5 6 #include <cobalt/cobalt.h> 7 8 void cobalt_wdt_refresh(unsigned long refresh_timer); 9 void cobalt_wdt_trigger_reboot(void); 10 11 void cobalt_wdt_disable(void); 12 void cobalt_wdt_reenable(void); 13 14 void cobalt_wdt_cleardog(void); 15 16 #endif -
init/main.c
diff -Naur linux-2.6.20.orig/init/main.c linux-2.6.20/init/main.c
old new 681 681 * 682 682 * Now we can finally start doing some real work.. 683 683 */ 684 #ifdef CONFIG_COBALT_RAQ 685 extern int cobalt_init(void); 686 #endif 687 684 688 static void __init do_basic_setup(void) 685 689 { 686 690 /* drivers will send hotplug events */ … … 693 697 #endif 694 698 695 699 do_initcalls(); 700 701 #ifdef CONFIG_COBALT_RAQ 702 cobalt_init(); 703 #endif 696 704 } 697 705 698 706 static void __init do_pre_smp_initcalls(void)
Note:
See TracBrowser
for help on using the repository browser.