aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorDave Jones <davej@redhat.com>2005-08-18 01:56:07 -0400
committerDave Jones <davej@redhat.com>2005-08-18 01:56:07 -0400
commita8b3e6f10f08f66ae1072efd087b30966a3654f6 (patch)
tree1d1409855f8ad5beabafe061c6453edd84ba94c8 /drivers/char
parent46acac3b4fd8ef66eec63b51de8d556a17c7d4f7 (diff)
parent099d44e869f1886b5eb02a5145ca97b5e4142e28 (diff)
Merge /pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/Kconfig10
-rw-r--r--drivers/char/Makefile3
-rw-r--r--drivers/char/agp/agp.h1
-rw-r--r--drivers/char/agp/amd64-agp.c9
-rw-r--r--drivers/char/agp/intel-agp.c12
-rw-r--r--drivers/char/amiserial.c22
-rw-r--r--drivers/char/applicom.c2
-rw-r--r--drivers/char/drm/Kconfig9
-rw-r--r--drivers/char/drm/Makefile10
-rw-r--r--drivers/char/drm/ati_pcigart.c2
-rw-r--r--drivers/char/drm/drm.h2
-rw-r--r--drivers/char/drm/drmP.h35
-rw-r--r--drivers/char/drm/drm_auth.c4
-rw-r--r--drivers/char/drm/drm_bufs.c37
-rw-r--r--drivers/char/drm/drm_context.c10
-rw-r--r--drivers/char/drm/drm_drv.c9
-rw-r--r--drivers/char/drm/drm_fops.c14
-rw-r--r--drivers/char/drm/drm_ioc32.c1069
-rw-r--r--drivers/char/drm/drm_irq.c2
-rw-r--r--drivers/char/drm/drm_lock.c12
-rw-r--r--drivers/char/drm/drm_memory.c13
-rw-r--r--drivers/char/drm/drm_pciids.h8
-rw-r--r--drivers/char/drm/drm_proc.c2
-rw-r--r--drivers/char/drm/drm_stub.c92
-rw-r--r--drivers/char/drm/drm_vm.c10
-rw-r--r--drivers/char/drm/i810_dma.c24
-rw-r--r--drivers/char/drm/i810_drv.h1
-rw-r--r--drivers/char/drm/i830_dma.c20
-rw-r--r--drivers/char/drm/i830_drv.c2
-rw-r--r--drivers/char/drm/i830_drv.h2
-rw-r--r--drivers/char/drm/i830_irq.c5
-rw-r--r--drivers/char/drm/i915_dma.c84
-rw-r--r--drivers/char/drm/i915_drm.h27
-rw-r--r--drivers/char/drm/i915_drv.c30
-rw-r--r--drivers/char/drm/i915_drv.h38
-rw-r--r--drivers/char/drm/i915_ioc32.c221
-rw-r--r--drivers/char/drm/i915_irq.c28
-rw-r--r--drivers/char/drm/i915_mem.c24
-rw-r--r--drivers/char/drm/mga_drv.c3
-rw-r--r--drivers/char/drm/mga_drv.h2
-rw-r--r--drivers/char/drm/mga_ioc32.c167
-rw-r--r--drivers/char/drm/r128_drv.c3
-rw-r--r--drivers/char/drm/r128_drv.h3
-rw-r--r--drivers/char/drm/r128_ioc32.c219
-rw-r--r--drivers/char/drm/r128_state.c2
-rw-r--r--drivers/char/drm/radeon_drv.c3
-rw-r--r--drivers/char/drm/radeon_drv.h3
-rw-r--r--drivers/char/drm/radeon_ioc32.c395
-rw-r--r--drivers/char/drm/radeon_irq.c32
-rw-r--r--drivers/char/drm/via_3d_reg.h1651
-rw-r--r--drivers/char/drm/via_dma.c741
-rw-r--r--drivers/char/drm/via_drm.h243
-rw-r--r--drivers/char/drm/via_drv.c126
-rw-r--r--drivers/char/drm/via_drv.h118
-rw-r--r--drivers/char/drm/via_ds.c280
-rw-r--r--drivers/char/drm/via_ds.h104
-rw-r--r--drivers/char/drm/via_irq.c339
-rw-r--r--drivers/char/drm/via_map.c111
-rw-r--r--drivers/char/drm/via_mm.c361
-rw-r--r--drivers/char/drm/via_mm.h40
-rw-r--r--drivers/char/drm/via_verifier.c1061
-rw-r--r--drivers/char/drm/via_verifier.h61
-rw-r--r--drivers/char/drm/via_video.c98
-rw-r--r--drivers/char/ds1620.c3
-rw-r--r--drivers/char/dsp56k.c14
-rw-r--r--drivers/char/ftape/compressor/zftape-compress.c4
-rw-r--r--drivers/char/ftape/zftape/zftape-init.c30
-rw-r--r--drivers/char/hangcheck-timer.c2
-rw-r--r--drivers/char/hpet.c2
-rw-r--r--drivers/char/hvc_console.c429
-rw-r--r--drivers/char/hvc_vio.c152
-rw-r--r--drivers/char/hvcs.c14
-rw-r--r--drivers/char/hvsi.c8
-rw-r--r--drivers/char/hw_random.c2
-rw-r--r--drivers/char/i8k.c909
-rw-r--r--drivers/char/ip2/i2cmd.c6
-rw-r--r--drivers/char/ip2/i2cmd.h12
-rw-r--r--drivers/char/ip2main.c34
-rw-r--r--drivers/char/ipmi/ipmi_devintf.c210
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c52
-rw-r--r--drivers/char/ipmi/ipmi_poweroff.c137
-rw-r--r--drivers/char/ipmi/ipmi_si_intf.c2
-rw-r--r--drivers/char/ipmi/ipmi_watchdog.c6
-rw-r--r--drivers/char/isicom.c12
-rw-r--r--drivers/char/istallion.c13
-rw-r--r--drivers/char/keyboard.c4
-rw-r--r--drivers/char/lp.c12
-rw-r--r--drivers/char/mbcs.c4
-rw-r--r--drivers/char/mem.c80
-rw-r--r--drivers/char/misc.c27
-rw-r--r--drivers/char/moxa.c2
-rw-r--r--drivers/char/mwave/3780i.c6
-rw-r--r--drivers/char/mwave/3780i.h4
-rw-r--r--drivers/char/mwave/mwavedd.c2
-rw-r--r--drivers/char/mwave/tp3780i.c14
-rw-r--r--drivers/char/n_hdlc.c2
-rw-r--r--drivers/char/n_r3964.c2
-rw-r--r--drivers/char/n_tty.c33
-rw-r--r--drivers/char/nvram.c6
-rw-r--r--drivers/char/pcmcia/synclink_cs.c16
-rw-r--r--drivers/char/ppdev.c12
-rw-r--r--drivers/char/random.c2
-rw-r--r--drivers/char/raw.c18
-rw-r--r--drivers/char/rio/func.h1
-rw-r--r--drivers/char/rio/rio_linux.c9
-rw-r--r--drivers/char/rio/rioboot.c12
-rw-r--r--drivers/char/rio/rioinit.c7
-rw-r--r--drivers/char/rio/rioroute.c2
-rw-r--r--drivers/char/rio/riotable.c2
-rw-r--r--drivers/char/rio/riotty.c15
-rw-r--r--drivers/char/rocket.c229
-rw-r--r--drivers/char/rocket_int.h40
-rw-r--r--drivers/char/rtc.c19
-rw-r--r--drivers/char/snsc.c7
-rw-r--r--drivers/char/sonypi.c146
-rw-r--r--drivers/char/stallion.c10
-rw-r--r--drivers/char/sysrq.c28
-rw-r--r--drivers/char/tb0219.c19
-rw-r--r--drivers/char/tipar.c16
-rw-r--r--drivers/char/toshiba.c60
-rw-r--r--drivers/char/tpm/Kconfig14
-rw-r--r--drivers/char/tpm/Makefile2
-rw-r--r--drivers/char/tpm/tpm.c360
-rw-r--r--drivers/char/tpm/tpm.h38
-rw-r--r--drivers/char/tpm/tpm_atmel.c63
-rw-r--r--drivers/char/tpm/tpm_infineon.c533
-rw-r--r--drivers/char/tpm/tpm_nsc.c199
-rw-r--r--drivers/char/tty_io.c63
-rw-r--r--drivers/char/tty_ioctl.c4
-rw-r--r--drivers/char/vc_screen.c16
-rw-r--r--drivers/char/viotape.c16
-rw-r--r--drivers/char/vr41xx_giu.c743
-rw-r--r--drivers/char/vt.c6
-rw-r--r--drivers/char/vt_ioctl.c5
-rw-r--r--drivers/char/watchdog/Kconfig10
-rw-r--r--drivers/char/watchdog/Makefile1
-rw-r--r--drivers/char/watchdog/acquirewdt.c7
-rw-r--r--drivers/char/watchdog/advantechwdt.c7
-rw-r--r--drivers/char/watchdog/alim1535_wdt.c9
-rw-r--r--drivers/char/watchdog/alim7101_wdt.c7
-rw-r--r--drivers/char/watchdog/eurotechwdt.c9
-rw-r--r--drivers/char/watchdog/i8xx_tco.c50
-rw-r--r--drivers/char/watchdog/ib700wdt.c7
-rw-r--r--drivers/char/watchdog/indydog.c7
-rw-r--r--drivers/char/watchdog/ixp2000_wdt.c15
-rw-r--r--drivers/char/watchdog/ixp4xx_wdt.c8
-rw-r--r--drivers/char/watchdog/machzwd.c7
-rw-r--r--drivers/char/watchdog/mixcomwd.c7
-rw-r--r--drivers/char/watchdog/pcwd.c11
-rw-r--r--drivers/char/watchdog/pcwd_pci.c7
-rw-r--r--drivers/char/watchdog/pcwd_usb.c7
-rw-r--r--drivers/char/watchdog/s3c2410_wdt.c7
-rw-r--r--drivers/char/watchdog/sa1100_wdt.c53
-rw-r--r--drivers/char/watchdog/sbc60xxwdt.c7
-rw-r--r--drivers/char/watchdog/sc1200wdt.c7
-rw-r--r--drivers/char/watchdog/sc520_wdt.c7
-rw-r--r--drivers/char/watchdog/scx200_wdt.c6
-rw-r--r--drivers/char/watchdog/shwdt.c6
-rw-r--r--drivers/char/watchdog/softdog.c9
-rw-r--r--drivers/char/watchdog/w83627hf_wdt.c7
-rw-r--r--drivers/char/watchdog/w83877f_wdt.c7
-rw-r--r--drivers/char/watchdog/wafer5823wdt.c7
-rw-r--r--drivers/char/watchdog/wdrtas.c696
-rw-r--r--drivers/char/watchdog/wdt.c9
-rw-r--r--drivers/char/watchdog/wdt977.c7
-rw-r--r--drivers/char/watchdog/wdt_pci.c9
166 files changed, 11840 insertions, 2234 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 5ed6515ae01f..4f27e5519296 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -735,7 +735,7 @@ config SGI_IP27_RTC
735 735
736config GEN_RTC 736config GEN_RTC
737 tristate "Generic /dev/rtc emulation" 737 tristate "Generic /dev/rtc emulation"
738 depends on RTC!=y && !IA64 && !ARM 738 depends on RTC!=y && !IA64 && !ARM && !PPC64
739 ---help--- 739 ---help---
740 If you say Y here and create a character special file /dev/rtc with 740 If you say Y here and create a character special file /dev/rtc with
741 major number 10 and minor number 135 using mknod ("man mknod"), you 741 major number 10 and minor number 135 using mknod ("man mknod"), you
@@ -929,6 +929,10 @@ config SCx200_GPIO
929 929
930 If compiled as a module, it will be called scx200_gpio. 930 If compiled as a module, it will be called scx200_gpio.
931 931
932config GPIO_VR41XX
933 tristate "NEC VR4100 series General-purpose I/O Unit support"
934 depends on CPU_VR41XX
935
932config RAW_DRIVER 936config RAW_DRIVER
933 tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)" 937 tristate "RAW driver (/dev/raw/rawN) (OBSOLETE)"
934 help 938 help
@@ -936,8 +940,8 @@ config RAW_DRIVER
936 Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O. 940 Once bound, I/O against /dev/raw/rawN uses efficient zero-copy I/O.
937 See the raw(8) manpage for more details. 941 See the raw(8) manpage for more details.
938 942
939 The raw driver is deprecated and may be removed from 2.7 943 The raw driver is deprecated and will be removed soon.
940 kernels. Applications should simply open the device (eg /dev/hda1) 944 Applications should simply open the device (eg /dev/hda1)
941 with the O_DIRECT flag. 945 with the O_DIRECT flag.
942 946
943config HPET 947config HPET
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index e3f5c32aac55..08f69287ea36 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -40,7 +40,7 @@ obj-$(CONFIG_N_HDLC) += n_hdlc.o
40obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o 40obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
41obj-$(CONFIG_SX) += sx.o generic_serial.o 41obj-$(CONFIG_SX) += sx.o generic_serial.o
42obj-$(CONFIG_RIO) += rio/ generic_serial.o 42obj-$(CONFIG_RIO) += rio/ generic_serial.o
43obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o hvsi.o 43obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o hvc_vio.o hvsi.o
44obj-$(CONFIG_RAW_DRIVER) += raw.o 44obj-$(CONFIG_RAW_DRIVER) += raw.o
45obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o 45obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o
46obj-$(CONFIG_MMTIMER) += mmtimer.o 46obj-$(CONFIG_MMTIMER) += mmtimer.o
@@ -80,6 +80,7 @@ obj-$(CONFIG_PPDEV) += ppdev.o
80obj-$(CONFIG_NWBUTTON) += nwbutton.o 80obj-$(CONFIG_NWBUTTON) += nwbutton.o
81obj-$(CONFIG_NWFLASH) += nwflash.o 81obj-$(CONFIG_NWFLASH) += nwflash.o
82obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o 82obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o
83obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o
83obj-$(CONFIG_TANBAC_TB0219) += tb0219.o 84obj-$(CONFIG_TANBAC_TB0219) += tb0219.o
84 85
85obj-$(CONFIG_WATCHDOG) += watchdog/ 86obj-$(CONFIG_WATCHDOG) += watchdog/
diff --git a/drivers/char/agp/agp.h b/drivers/char/agp/agp.h
index c1fe013c64f3..b4af87c6f9c8 100644
--- a/drivers/char/agp/agp.h
+++ b/drivers/char/agp/agp.h
@@ -143,6 +143,7 @@ struct agp_bridge_data {
143 char major_version; 143 char major_version;
144 char minor_version; 144 char minor_version;
145 struct list_head list; 145 struct list_head list;
146 u32 apbase_config;
146}; 147};
147 148
148#define KB(x) ((x) * 1024) 149#define KB(x) ((x) * 1024)
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index 1407945a5892..59f589d733f9 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -686,6 +686,15 @@ static struct pci_device_id agp_amd64_pci_table[] = {
686 .subvendor = PCI_ANY_ID, 686 .subvendor = PCI_ANY_ID,
687 .subdevice = PCI_ANY_ID, 687 .subdevice = PCI_ANY_ID,
688 }, 688 },
689 /* SIS 760 */
690 {
691 .class = (PCI_CLASS_BRIDGE_HOST << 8),
692 .class_mask = ~0,
693 .vendor = PCI_VENDOR_ID_SI,
694 .device = PCI_DEVICE_ID_SI_760,
695 .subvendor = PCI_ANY_ID,
696 .subdevice = PCI_ANY_ID,
697 },
689 { } 698 { }
690}; 699};
691 700
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c
index 51266d6b4d78..1f7d415f432c 100644
--- a/drivers/char/agp/intel-agp.c
+++ b/drivers/char/agp/intel-agp.c
@@ -1047,9 +1047,15 @@ static int intel_845_configure(void)
1047 /* aperture size */ 1047 /* aperture size */
1048 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value); 1048 pci_write_config_byte(agp_bridge->dev, INTEL_APSIZE, current_size->size_value);
1049 1049
1050 /* address to map to */ 1050 if (agp_bridge->apbase_config != 0) {
1051 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp); 1051 pci_write_config_dword(agp_bridge->dev, AGP_APBASE,
1052 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK); 1052 agp_bridge->apbase_config);
1053 } else {
1054 /* address to map to */
1055 pci_read_config_dword(agp_bridge->dev, AGP_APBASE, &temp);
1056 agp_bridge->gart_bus_addr = (temp & PCI_BASE_ADDRESS_MEM_MASK);
1057 agp_bridge->apbase_config = temp;
1058 }
1053 1059
1054 /* attbase - aperture base */ 1060 /* attbase - aperture base */
1055 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr); 1061 pci_write_config_dword(agp_bridge->dev, INTEL_ATTBASE, agp_bridge->gatt_bus_addr);
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 1dc4259213a6..2a36561eec68 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -861,13 +861,18 @@ static void change_speed(struct async_struct *info,
861 861
862static void rs_put_char(struct tty_struct *tty, unsigned char ch) 862static void rs_put_char(struct tty_struct *tty, unsigned char ch)
863{ 863{
864 struct async_struct *info = (struct async_struct *)tty->driver_data; 864 struct async_struct *info;
865 unsigned long flags; 865 unsigned long flags;
866 866
867 if (!tty)
868 return;
869
870 info = tty->driver_data;
871
867 if (serial_paranoia_check(info, tty->name, "rs_put_char")) 872 if (serial_paranoia_check(info, tty->name, "rs_put_char"))
868 return; 873 return;
869 874
870 if (!tty || !info->xmit.buf) 875 if (!info->xmit.buf)
871 return; 876 return;
872 877
873 local_irq_save(flags); 878 local_irq_save(flags);
@@ -910,13 +915,18 @@ static void rs_flush_chars(struct tty_struct *tty)
910static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) 915static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count)
911{ 916{
912 int c, ret = 0; 917 int c, ret = 0;
913 struct async_struct *info = (struct async_struct *)tty->driver_data; 918 struct async_struct *info;
914 unsigned long flags; 919 unsigned long flags;
915 920
921 if (!tty)
922 return 0;
923
924 info = tty->driver_data;
925
916 if (serial_paranoia_check(info, tty->name, "rs_write")) 926 if (serial_paranoia_check(info, tty->name, "rs_write"))
917 return 0; 927 return 0;
918 928
919 if (!tty || !info->xmit.buf || !tmp_buf) 929 if (!info->xmit.buf || !tmp_buf)
920 return 0; 930 return 0;
921 931
922 local_save_flags(flags); 932 local_save_flags(flags);
@@ -1963,10 +1973,6 @@ static _INLINE_ void show_serial_version(void)
1963} 1973}
1964 1974
1965 1975
1966int register_serial(struct serial_struct *req);
1967void unregister_serial(int line);
1968
1969
1970static struct tty_operations serial_ops = { 1976static struct tty_operations serial_ops = {
1971 .open = rs_open, 1977 .open = rs_open,
1972 .close = rs_close, 1978 .close = rs_close,
diff --git a/drivers/char/applicom.c b/drivers/char/applicom.c
index 6bf2e27dc23a..11f9ee581124 100644
--- a/drivers/char/applicom.c
+++ b/drivers/char/applicom.c
@@ -599,7 +599,7 @@ static ssize_t ac_read (struct file *filp, char __user *buf, size_t count, loff_
599 599
600#ifdef DEBUG 600#ifdef DEBUG
601 if (loopcount++ > 2) { 601 if (loopcount++ > 2) {
602 printk("Looping in ac_read. loopcount %d\n", loopcount); 602 printk(KERN_DEBUG "Looping in ac_read. loopcount %d\n", loopcount);
603 } 603 }
604#endif 604#endif
605 } 605 }
diff --git a/drivers/char/drm/Kconfig b/drivers/char/drm/Kconfig
index d9a029934678..123417e43040 100644
--- a/drivers/char/drm/Kconfig
+++ b/drivers/char/drm/Kconfig
@@ -6,7 +6,7 @@
6# 6#
7config DRM 7config DRM
8 tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)" 8 tristate "Direct Rendering Manager (XFree86 4.1.0 and higher DRI support)"
9 depends on AGP || AGP=n 9 depends on (AGP || AGP=n) && PCI
10 help 10 help
11 Kernel-level support for the Direct Rendering Infrastructure (DRI) 11 Kernel-level support for the Direct Rendering Infrastructure (DRI)
12 introduced in XFree86 4.0. If you say Y here, you need to select 12 introduced in XFree86 4.0. If you say Y here, you need to select
@@ -96,3 +96,10 @@ config DRM_SIS
96 chipset. If M is selected the module will be called sis. AGP 96 chipset. If M is selected the module will be called sis. AGP
97 support is required for this driver to work. 97 support is required for this driver to work.
98 98
99config DRM_VIA
100 tristate "Via unichrome video cards"
101 depends on DRM
102 help
103 Choose this option if you have a Via unichrome or compatible video
104 chipset. If M is selected the module will be called via.
105
diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile
index 23ab26321e9a..ddd941045b1f 100644
--- a/drivers/char/drm/Makefile
+++ b/drivers/char/drm/Makefile
@@ -18,6 +18,15 @@ i915-objs := i915_drv.o i915_dma.o i915_irq.o i915_mem.o
18radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o 18radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o
19ffb-objs := ffb_drv.o ffb_context.o 19ffb-objs := ffb_drv.o ffb_context.o
20sis-objs := sis_drv.o sis_ds.o sis_mm.o 20sis-objs := sis_drv.o sis_ds.o sis_mm.o
21via-objs := via_irq.o via_drv.o via_ds.o via_map.o via_mm.o via_dma.o via_verifier.o via_video.o
22
23ifeq ($(CONFIG_COMPAT),y)
24drm-objs += drm_ioc32.o
25radeon-objs += radeon_ioc32.o
26mga-objs += mga_ioc32.o
27r128-objs += r128_ioc32.o
28i915-objs += i915_ioc32.o
29endif
21 30
22obj-$(CONFIG_DRM) += drm.o 31obj-$(CONFIG_DRM) += drm.o
23obj-$(CONFIG_DRM_GAMMA) += gamma.o 32obj-$(CONFIG_DRM_GAMMA) += gamma.o
@@ -30,4 +39,5 @@ obj-$(CONFIG_DRM_I830) += i830.o
30obj-$(CONFIG_DRM_I915) += i915.o 39obj-$(CONFIG_DRM_I915) += i915.o
31obj-$(CONFIG_DRM_FFB) += ffb.o 40obj-$(CONFIG_DRM_FFB) += ffb.o
32obj-$(CONFIG_DRM_SIS) += sis.o 41obj-$(CONFIG_DRM_SIS) += sis.o
42obj-$(CONFIG_DRM_VIA) +=via.o
33 43
diff --git a/drivers/char/drm/ati_pcigart.c b/drivers/char/drm/ati_pcigart.c
index fdca1876ecd5..0aec5ef481b8 100644
--- a/drivers/char/drm/ati_pcigart.c
+++ b/drivers/char/drm/ati_pcigart.c
@@ -52,7 +52,7 @@
52# define ATI_MAX_PCIGART_PAGES 8192 /**< 32 MB aperture, 4K pages */ 52# define ATI_MAX_PCIGART_PAGES 8192 /**< 32 MB aperture, 4K pages */
53# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */ 53# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */
54 54
55unsigned long drm_ati_alloc_pcigart_table( void ) 55static unsigned long drm_ati_alloc_pcigart_table( void )
56{ 56{
57 unsigned long address; 57 unsigned long address;
58 struct page *page; 58 struct page *page;
diff --git a/drivers/char/drm/drm.h b/drivers/char/drm/drm.h
index 587305282ea8..e8371dd87fbc 100644
--- a/drivers/char/drm/drm.h
+++ b/drivers/char/drm/drm.h
@@ -38,7 +38,9 @@
38#define _DRM_H_ 38#define _DRM_H_
39 39
40#if defined(__linux__) 40#if defined(__linux__)
41#if defined(__KERNEL__)
41#include <linux/config.h> 42#include <linux/config.h>
43#endif
42#include <asm/ioctl.h> /* For _IO* macros */ 44#include <asm/ioctl.h> /* For _IO* macros */
43#define DRM_IOCTL_NR(n) _IOC_NR(n) 45#define DRM_IOCTL_NR(n) _IOC_NR(n)
44#define DRM_IOC_VOID _IOC_NONE 46#define DRM_IOC_VOID _IOC_NONE
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h
index 21f4c54e1a8d..5df09cc8c6db 100644
--- a/drivers/char/drm/drmP.h
+++ b/drivers/char/drm/drmP.h
@@ -316,6 +316,9 @@ do { \
316typedef int drm_ioctl_t( struct inode *inode, struct file *filp, 316typedef int drm_ioctl_t( struct inode *inode, struct file *filp,
317 unsigned int cmd, unsigned long arg ); 317 unsigned int cmd, unsigned long arg );
318 318
319typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
320 unsigned long arg);
321
319typedef struct drm_ioctl_desc { 322typedef struct drm_ioctl_desc {
320 drm_ioctl_t *func; 323 drm_ioctl_t *func;
321 int auth_needed; 324 int auth_needed;
@@ -771,37 +774,28 @@ extern int drm_cpu_valid( void );
771 /* Driver support (drm_drv.h) */ 774 /* Driver support (drm_drv.h) */
772extern int drm_init(struct drm_driver *driver); 775extern int drm_init(struct drm_driver *driver);
773extern void drm_exit(struct drm_driver *driver); 776extern void drm_exit(struct drm_driver *driver);
774extern int drm_version(struct inode *inode, struct file *filp,
775 unsigned int cmd, unsigned long arg);
776extern int drm_ioctl(struct inode *inode, struct file *filp, 777extern int drm_ioctl(struct inode *inode, struct file *filp,
777 unsigned int cmd, unsigned long arg); 778 unsigned int cmd, unsigned long arg);
779extern long drm_compat_ioctl(struct file *filp,
780 unsigned int cmd, unsigned long arg);
778extern int drm_takedown(drm_device_t * dev); 781extern int drm_takedown(drm_device_t * dev);
779 782
780 /* Device support (drm_fops.h) */ 783 /* Device support (drm_fops.h) */
781extern int drm_open(struct inode *inode, struct file *filp); 784extern int drm_open(struct inode *inode, struct file *filp);
782extern int drm_stub_open(struct inode *inode, struct file *filp); 785extern int drm_stub_open(struct inode *inode, struct file *filp);
783extern int drm_open_helper(struct inode *inode, struct file *filp,
784 drm_device_t *dev);
785extern int drm_flush(struct file *filp); 786extern int drm_flush(struct file *filp);
786extern int drm_fasync(int fd, struct file *filp, int on); 787extern int drm_fasync(int fd, struct file *filp, int on);
787extern int drm_release(struct inode *inode, struct file *filp); 788extern int drm_release(struct inode *inode, struct file *filp);
788 789
789 /* Mapping support (drm_vm.h) */ 790 /* Mapping support (drm_vm.h) */
790extern void drm_vm_open(struct vm_area_struct *vma);
791extern void drm_vm_close(struct vm_area_struct *vma);
792extern void drm_vm_shm_close(struct vm_area_struct *vma);
793extern int drm_mmap_dma(struct file *filp,
794 struct vm_area_struct *vma);
795extern int drm_mmap(struct file *filp, struct vm_area_struct *vma); 791extern int drm_mmap(struct file *filp, struct vm_area_struct *vma);
796extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait); 792extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait);
797extern ssize_t drm_read(struct file *filp, char __user *buf, size_t count, loff_t *off);
798 793
799 /* Memory management support (drm_memory.h) */ 794 /* Memory management support (drm_memory.h) */
800#include "drm_memory.h" 795#include "drm_memory.h"
801extern void drm_mem_init(void); 796extern void drm_mem_init(void);
802extern int drm_mem_info(char *buf, char **start, off_t offset, 797extern int drm_mem_info(char *buf, char **start, off_t offset,
803 int request, int *eof, void *data); 798 int request, int *eof, void *data);
804extern void *drm_calloc(size_t nmemb, size_t size, int area);
805extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, 799extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size,
806 int area); 800 int area);
807extern unsigned long drm_alloc_pages(int order, int area); 801extern unsigned long drm_alloc_pages(int order, int area);
@@ -849,9 +843,6 @@ extern int drm_newctx( struct inode *inode, struct file *filp,
849extern int drm_rmctx( struct inode *inode, struct file *filp, 843extern int drm_rmctx( struct inode *inode, struct file *filp,
850 unsigned int cmd, unsigned long arg ); 844 unsigned int cmd, unsigned long arg );
851 845
852extern int drm_context_switch(drm_device_t *dev, int old, int new);
853extern int drm_context_switch_complete(drm_device_t *dev, int new);
854
855extern int drm_ctxbitmap_init( drm_device_t *dev ); 846extern int drm_ctxbitmap_init( drm_device_t *dev );
856extern void drm_ctxbitmap_cleanup( drm_device_t *dev ); 847extern void drm_ctxbitmap_cleanup( drm_device_t *dev );
857extern void drm_ctxbitmap_free( drm_device_t *dev, int ctx_handle ); 848extern void drm_ctxbitmap_free( drm_device_t *dev, int ctx_handle );
@@ -869,9 +860,6 @@ extern int drm_rmdraw(struct inode *inode, struct file *filp,
869 860
870 861
871 /* Authentication IOCTL support (drm_auth.h) */ 862 /* Authentication IOCTL support (drm_auth.h) */
872extern int drm_add_magic(drm_device_t *dev, drm_file_t *priv,
873 drm_magic_t magic);
874extern int drm_remove_magic(drm_device_t *dev, drm_magic_t magic);
875extern int drm_getmagic(struct inode *inode, struct file *filp, 863extern int drm_getmagic(struct inode *inode, struct file *filp,
876 unsigned int cmd, unsigned long arg); 864 unsigned int cmd, unsigned long arg);
877extern int drm_authmagic(struct inode *inode, struct file *filp, 865extern int drm_authmagic(struct inode *inode, struct file *filp,
@@ -888,13 +876,9 @@ extern int drm_unlock(struct inode *inode, struct file *filp,
888 unsigned int cmd, unsigned long arg); 876 unsigned int cmd, unsigned long arg);
889extern int drm_lock_take(__volatile__ unsigned int *lock, 877extern int drm_lock_take(__volatile__ unsigned int *lock,
890 unsigned int context); 878 unsigned int context);
891extern int drm_lock_transfer(drm_device_t *dev,
892 __volatile__ unsigned int *lock,
893 unsigned int context);
894extern int drm_lock_free(drm_device_t *dev, 879extern int drm_lock_free(drm_device_t *dev,
895 __volatile__ unsigned int *lock, 880 __volatile__ unsigned int *lock,
896 unsigned int context); 881 unsigned int context);
897extern int drm_notifier(void *priv);
898 882
899 /* Buffer management support (drm_bufs.h) */ 883 /* Buffer management support (drm_bufs.h) */
900extern int drm_order( unsigned long size ); 884extern int drm_order( unsigned long size );
@@ -922,7 +906,6 @@ extern void drm_core_reclaim_buffers(drm_device_t *dev, struct file *filp);
922 /* IRQ support (drm_irq.h) */ 906 /* IRQ support (drm_irq.h) */
923extern int drm_control( struct inode *inode, struct file *filp, 907extern int drm_control( struct inode *inode, struct file *filp,
924 unsigned int cmd, unsigned long arg ); 908 unsigned int cmd, unsigned long arg );
925extern int drm_irq_install( drm_device_t *dev );
926extern int drm_irq_uninstall( drm_device_t *dev ); 909extern int drm_irq_uninstall( drm_device_t *dev );
927extern irqreturn_t drm_irq_handler( DRM_IRQ_ARGS ); 910extern irqreturn_t drm_irq_handler( DRM_IRQ_ARGS );
928extern void drm_driver_irq_preinstall( drm_device_t *dev ); 911extern void drm_driver_irq_preinstall( drm_device_t *dev );
@@ -962,7 +945,6 @@ extern int drm_agp_unbind_memory(DRM_AGP_MEM *handle);
962extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, 945extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
963 struct drm_driver *driver); 946 struct drm_driver *driver);
964extern int drm_put_dev(drm_device_t * dev); 947extern int drm_put_dev(drm_device_t * dev);
965extern int drm_get_head(drm_device_t * dev, drm_head_t *head);
966extern int drm_put_head(drm_head_t * head); 948extern int drm_put_head(drm_head_t * head);
967extern unsigned int drm_debug; 949extern unsigned int drm_debug;
968extern unsigned int drm_cards_limit; 950extern unsigned int drm_cards_limit;
@@ -1059,9 +1041,16 @@ static __inline__ void drm_free(void *pt, size_t size, int area)
1059{ 1041{
1060 kfree(pt); 1042 kfree(pt);
1061} 1043}
1044
1045/** Wrapper around kcalloc() */
1046static __inline__ void *drm_calloc(size_t nmemb, size_t size, int area)
1047{
1048 return kcalloc(nmemb, size, GFP_KERNEL);
1049}
1062#else 1050#else
1063extern void *drm_alloc(size_t size, int area); 1051extern void *drm_alloc(size_t size, int area);
1064extern void drm_free(void *pt, size_t size, int area); 1052extern void drm_free(void *pt, size_t size, int area);
1053extern void *drm_calloc(size_t nmemb, size_t size, int area);
1065#endif 1054#endif
1066 1055
1067/*@}*/ 1056/*@}*/
diff --git a/drivers/char/drm/drm_auth.c b/drivers/char/drm/drm_auth.c
index b428761c4e91..dd140bca8f71 100644
--- a/drivers/char/drm/drm_auth.c
+++ b/drivers/char/drm/drm_auth.c
@@ -87,7 +87,7 @@ static drm_file_t *drm_find_file(drm_device_t *dev, drm_magic_t magic)
87 * associated the magic number hash key in drm_device::magiclist, while holding 87 * associated the magic number hash key in drm_device::magiclist, while holding
88 * the drm_device::struct_sem lock. 88 * the drm_device::struct_sem lock.
89 */ 89 */
90int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic) 90static int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
91{ 91{
92 int hash; 92 int hash;
93 drm_magic_entry_t *entry; 93 drm_magic_entry_t *entry;
@@ -124,7 +124,7 @@ int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic)
124 * Searches and unlinks the entry in drm_device::magiclist with the magic 124 * Searches and unlinks the entry in drm_device::magiclist with the magic
125 * number hash key, while holding the drm_device::struct_sem lock. 125 * number hash key, while holding the drm_device::struct_sem lock.
126 */ 126 */
127int drm_remove_magic(drm_device_t *dev, drm_magic_t magic) 127static int drm_remove_magic(drm_device_t *dev, drm_magic_t magic)
128{ 128{
129 drm_magic_entry_t *prev = NULL; 129 drm_magic_entry_t *prev = NULL;
130 drm_magic_entry_t *pt; 130 drm_magic_entry_t *pt;
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c
index 4113bcba67fe..4c6191d231b8 100644
--- a/drivers/char/drm/drm_bufs.c
+++ b/drivers/char/drm/drm_bufs.c
@@ -60,6 +60,15 @@ int drm_order( unsigned long size )
60} 60}
61EXPORT_SYMBOL(drm_order); 61EXPORT_SYMBOL(drm_order);
62 62
63#ifdef CONFIG_COMPAT
64/*
65 * Used to allocate 32-bit handles for _DRM_SHM regions
66 * The 0x10000000 value is chosen to be out of the way of
67 * FB/register and GART physical addresses.
68 */
69static unsigned int map32_handle = 0x10000000;
70#endif
71
63/** 72/**
64 * Ioctl to specify a range of memory that is available for mapping by a non-root process. 73 * Ioctl to specify a range of memory that is available for mapping by a non-root process.
65 * 74 *
@@ -187,16 +196,18 @@ int drm_addmap( struct inode *inode, struct file *filp,
187 196
188 down(&dev->struct_sem); 197 down(&dev->struct_sem);
189 list_add(&list->head, &dev->maplist->head); 198 list_add(&list->head, &dev->maplist->head);
199#ifdef CONFIG_COMPAT
200 /* Assign a 32-bit handle for _DRM_SHM mappings */
201 /* We do it here so that dev->struct_sem protects the increment */
202 if (map->type == _DRM_SHM)
203 map->offset = map32_handle += PAGE_SIZE;
204#endif
190 up(&dev->struct_sem); 205 up(&dev->struct_sem);
191 206
192 if ( copy_to_user( argp, map, sizeof(*map) ) ) 207 if ( copy_to_user( argp, map, sizeof(*map) ) )
193 return -EFAULT; 208 return -EFAULT;
194 if ( map->type != _DRM_SHM ) { 209 if (copy_to_user(&argp->handle, &map->offset, sizeof(map->offset)))
195 if ( copy_to_user( &argp->handle, 210 return -EFAULT;
196 &map->offset,
197 sizeof(map->offset) ) )
198 return -EFAULT;
199 }
200 return 0; 211 return 0;
201} 212}
202 213
@@ -240,7 +251,7 @@ int drm_rmmap(struct inode *inode, struct file *filp,
240 r_list = list_entry(list, drm_map_list_t, head); 251 r_list = list_entry(list, drm_map_list_t, head);
241 252
242 if(r_list->map && 253 if(r_list->map &&
243 r_list->map->handle == request.handle && 254 r_list->map->offset == (unsigned long) request.handle &&
244 r_list->map->flags & _DRM_REMOVABLE) break; 255 r_list->map->flags & _DRM_REMOVABLE) break;
245 } 256 }
246 257
@@ -345,8 +356,8 @@ static void drm_cleanup_buf_error(drm_device_t *dev, drm_buf_entry_t *entry)
345 * reallocates the buffer list of the same size order to accommodate the new 356 * reallocates the buffer list of the same size order to accommodate the new
346 * buffers. 357 * buffers.
347 */ 358 */
348int drm_addbufs_agp( struct inode *inode, struct file *filp, 359static int drm_addbufs_agp( struct inode *inode, struct file *filp,
349 unsigned int cmd, unsigned long arg ) 360 unsigned int cmd, unsigned long arg )
350{ 361{
351 drm_file_t *priv = filp->private_data; 362 drm_file_t *priv = filp->private_data;
352 drm_device_t *dev = priv->head->dev; 363 drm_device_t *dev = priv->head->dev;
@@ -510,8 +521,8 @@ int drm_addbufs_agp( struct inode *inode, struct file *filp,
510} 521}
511#endif /* __OS_HAS_AGP */ 522#endif /* __OS_HAS_AGP */
512 523
513int drm_addbufs_pci( struct inode *inode, struct file *filp, 524static int drm_addbufs_pci( struct inode *inode, struct file *filp,
514 unsigned int cmd, unsigned long arg ) 525 unsigned int cmd, unsigned long arg )
515{ 526{
516 drm_file_t *priv = filp->private_data; 527 drm_file_t *priv = filp->private_data;
517 drm_device_t *dev = priv->head->dev; 528 drm_device_t *dev = priv->head->dev;
@@ -740,8 +751,8 @@ int drm_addbufs_pci( struct inode *inode, struct file *filp,
740 751
741} 752}
742 753
743int drm_addbufs_sg( struct inode *inode, struct file *filp, 754static int drm_addbufs_sg( struct inode *inode, struct file *filp,
744 unsigned int cmd, unsigned long arg ) 755 unsigned int cmd, unsigned long arg )
745{ 756{
746 drm_file_t *priv = filp->private_data; 757 drm_file_t *priv = filp->private_data;
747 drm_device_t *dev = priv->head->dev; 758 drm_device_t *dev = priv->head->dev;
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c
index f15c86c57875..a7cfabd1ca2e 100644
--- a/drivers/char/drm/drm_context.c
+++ b/drivers/char/drm/drm_context.c
@@ -84,7 +84,7 @@ failed:
84 * drm_device::context_sareas to accommodate the new entry while holding the 84 * drm_device::context_sareas to accommodate the new entry while holding the
85 * drm_device::struct_sem lock. 85 * drm_device::struct_sem lock.
86 */ 86 */
87int drm_ctxbitmap_next( drm_device_t *dev ) 87static int drm_ctxbitmap_next( drm_device_t *dev )
88{ 88{
89 int bit; 89 int bit;
90 90
@@ -225,7 +225,7 @@ int drm_getsareactx(struct inode *inode, struct file *filp,
225 map = dev->context_sareas[request.ctx_id]; 225 map = dev->context_sareas[request.ctx_id];
226 up(&dev->struct_sem); 226 up(&dev->struct_sem);
227 227
228 request.handle = map->handle; 228 request.handle = (void *) map->offset;
229 if (copy_to_user(argp, &request, sizeof(request))) 229 if (copy_to_user(argp, &request, sizeof(request)))
230 return -EFAULT; 230 return -EFAULT;
231 return 0; 231 return 0;
@@ -261,8 +261,8 @@ int drm_setsareactx(struct inode *inode, struct file *filp,
261 down(&dev->struct_sem); 261 down(&dev->struct_sem);
262 list_for_each(list, &dev->maplist->head) { 262 list_for_each(list, &dev->maplist->head) {
263 r_list = list_entry(list, drm_map_list_t, head); 263 r_list = list_entry(list, drm_map_list_t, head);
264 if(r_list->map && 264 if (r_list->map
265 r_list->map->handle == request.handle) 265 && r_list->map->offset == (unsigned long) request.handle)
266 goto found; 266 goto found;
267 } 267 }
268bad: 268bad:
@@ -326,7 +326,7 @@ int drm_context_switch( drm_device_t *dev, int old, int new )
326 * hardware lock is held, clears the drm_device::context_flag and wakes up 326 * hardware lock is held, clears the drm_device::context_flag and wakes up
327 * drm_device::context_wait. 327 * drm_device::context_wait.
328 */ 328 */
329int drm_context_switch_complete( drm_device_t *dev, int new ) 329static int drm_context_switch_complete( drm_device_t *dev, int new )
330{ 330{
331 dev->last_context = new; /* PRE/POST: This is the _only_ writer. */ 331 dev->last_context = new; /* PRE/POST: This is the _only_ writer. */
332 dev->last_switch = jiffies; 332 dev->last_switch = jiffies;
diff --git a/drivers/char/drm/drm_drv.c b/drivers/char/drm/drm_drv.c
index 1e37ed0c6b8d..3333c250c4d9 100644
--- a/drivers/char/drm/drm_drv.c
+++ b/drivers/char/drm/drm_drv.c
@@ -51,8 +51,11 @@
51#include "drmP.h" 51#include "drmP.h"
52#include "drm_core.h" 52#include "drm_core.h"
53 53
54static int drm_version(struct inode *inode, struct file *filp,
55 unsigned int cmd, unsigned long arg);
56
54/** Ioctl table */ 57/** Ioctl table */
55drm_ioctl_desc_t drm_ioctls[] = { 58static drm_ioctl_desc_t drm_ioctls[] = {
56 [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { drm_version, 0, 0 }, 59 [DRM_IOCTL_NR(DRM_IOCTL_VERSION)] = { drm_version, 0, 0 },
57 [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 }, 60 [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE)] = { drm_getunique, 0, 0 },
58 [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 }, 61 [DRM_IOCTL_NR(DRM_IOCTL_GET_MAGIC)] = { drm_getmagic, 0, 0 },
@@ -447,8 +450,8 @@ module_exit( drm_core_exit );
447 * 450 *
448 * Fills in the version information in \p arg. 451 * Fills in the version information in \p arg.
449 */ 452 */
450int drm_version( struct inode *inode, struct file *filp, 453static int drm_version( struct inode *inode, struct file *filp,
451 unsigned int cmd, unsigned long arg ) 454 unsigned int cmd, unsigned long arg )
452{ 455{
453 drm_file_t *priv = filp->private_data; 456 drm_file_t *priv = filp->private_data;
454 drm_device_t *dev = priv->head->dev; 457 drm_device_t *dev = priv->head->dev;
diff --git a/drivers/char/drm/drm_fops.c b/drivers/char/drm/drm_fops.c
index 906794247aeb..10e64fde8d78 100644
--- a/drivers/char/drm/drm_fops.c
+++ b/drivers/char/drm/drm_fops.c
@@ -37,6 +37,8 @@
37#include "drmP.h" 37#include "drmP.h"
38#include <linux/poll.h> 38#include <linux/poll.h>
39 39
40static int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t *dev);
41
40static int drm_setup( drm_device_t *dev ) 42static int drm_setup( drm_device_t *dev )
41{ 43{
42 int i; 44 int i;
@@ -251,7 +253,7 @@ int drm_release( struct inode *inode, struct file *filp )
251 } 253 }
252 } 254 }
253 255
254 if (drm_core_check_feature(dev, DRIVER_HAVE_DMA)) 256 if (drm_core_check_feature(dev, DRIVER_HAVE_DMA) && !dev->driver->release)
255 { 257 {
256 dev->driver->reclaim_buffers(dev, filp); 258 dev->driver->reclaim_buffers(dev, filp);
257 } 259 }
@@ -259,7 +261,7 @@ int drm_release( struct inode *inode, struct file *filp )
259 drm_fasync( -1, filp, 0 ); 261 drm_fasync( -1, filp, 0 );
260 262
261 down( &dev->ctxlist_sem ); 263 down( &dev->ctxlist_sem );
262 if ( !list_empty( &dev->ctxlist->head ) ) { 264 if ( dev->ctxlist && (!list_empty(&dev->ctxlist->head))) {
263 drm_ctx_list_t *pos, *n; 265 drm_ctx_list_t *pos, *n;
264 266
265 list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) { 267 list_for_each_entry_safe( pos, n, &dev->ctxlist->head, head ) {
@@ -341,7 +343,7 @@ EXPORT_SYMBOL(drm_release);
341 * Creates and initializes a drm_file structure for the file private data in \p 343 * Creates and initializes a drm_file structure for the file private data in \p
342 * filp and add it into the double linked list in \p dev. 344 * filp and add it into the double linked list in \p dev.
343 */ 345 */
344int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t *dev) 346static int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t *dev)
345{ 347{
346 int minor = iminor(inode); 348 int minor = iminor(inode);
347 drm_file_t *priv; 349 drm_file_t *priv;
@@ -443,9 +445,3 @@ unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait)
443} 445}
444EXPORT_SYMBOL(drm_poll); 446EXPORT_SYMBOL(drm_poll);
445 447
446
447/** No-op. */
448ssize_t drm_read(struct file *filp, char __user *buf, size_t count, loff_t *off)
449{
450 return 0;
451}
diff --git a/drivers/char/drm/drm_ioc32.c b/drivers/char/drm/drm_ioc32.c
new file mode 100644
index 000000000000..8087a9636399
--- /dev/null
+++ b/drivers/char/drm/drm_ioc32.c
@@ -0,0 +1,1069 @@
1/**
2 * \file drm_ioc32.c
3 *
4 * 32-bit ioctl compatibility routines for the DRM.
5 *
6 * \author Paul Mackerras <paulus@samba.org>
7 *
8 * Copyright (C) Paul Mackerras 2005.
9 * All Rights Reserved.
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice (including the next
19 * paragraph) shall be included in all copies or substantial portions of the
20 * Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28 * IN THE SOFTWARE.
29 */
30#include <linux/compat.h>
31#include <linux/ioctl32.h>
32
33#include "drmP.h"
34#include "drm_core.h"
35
36#define DRM_IOCTL_VERSION32 DRM_IOWR(0x00, drm_version32_t)
37#define DRM_IOCTL_GET_UNIQUE32 DRM_IOWR(0x01, drm_unique32_t)
38#define DRM_IOCTL_GET_MAP32 DRM_IOWR(0x04, drm_map32_t)
39#define DRM_IOCTL_GET_CLIENT32 DRM_IOWR(0x05, drm_client32_t)
40#define DRM_IOCTL_GET_STATS32 DRM_IOR( 0x06, drm_stats32_t)
41
42#define DRM_IOCTL_SET_UNIQUE32 DRM_IOW( 0x10, drm_unique32_t)
43#define DRM_IOCTL_ADD_MAP32 DRM_IOWR(0x15, drm_map32_t)
44#define DRM_IOCTL_ADD_BUFS32 DRM_IOWR(0x16, drm_buf_desc32_t)
45#define DRM_IOCTL_MARK_BUFS32 DRM_IOW( 0x17, drm_buf_desc32_t)
46#define DRM_IOCTL_INFO_BUFS32 DRM_IOWR(0x18, drm_buf_info32_t)
47#define DRM_IOCTL_MAP_BUFS32 DRM_IOWR(0x19, drm_buf_map32_t)
48#define DRM_IOCTL_FREE_BUFS32 DRM_IOW( 0x1a, drm_buf_free32_t)
49
50#define DRM_IOCTL_RM_MAP32 DRM_IOW( 0x1b, drm_map32_t)
51
52#define DRM_IOCTL_SET_SAREA_CTX32 DRM_IOW( 0x1c, drm_ctx_priv_map32_t)
53#define DRM_IOCTL_GET_SAREA_CTX32 DRM_IOWR(0x1d, drm_ctx_priv_map32_t)
54
55#define DRM_IOCTL_RES_CTX32 DRM_IOWR(0x26, drm_ctx_res32_t)
56#define DRM_IOCTL_DMA32 DRM_IOWR(0x29, drm_dma32_t)
57
58#define DRM_IOCTL_AGP_ENABLE32 DRM_IOW( 0x32, drm_agp_mode32_t)
59#define DRM_IOCTL_AGP_INFO32 DRM_IOR( 0x33, drm_agp_info32_t)
60#define DRM_IOCTL_AGP_ALLOC32 DRM_IOWR(0x34, drm_agp_buffer32_t)
61#define DRM_IOCTL_AGP_FREE32 DRM_IOW( 0x35, drm_agp_buffer32_t)
62#define DRM_IOCTL_AGP_BIND32 DRM_IOW( 0x36, drm_agp_binding32_t)
63#define DRM_IOCTL_AGP_UNBIND32 DRM_IOW( 0x37, drm_agp_binding32_t)
64
65#define DRM_IOCTL_SG_ALLOC32 DRM_IOW( 0x38, drm_scatter_gather32_t)
66#define DRM_IOCTL_SG_FREE32 DRM_IOW( 0x39, drm_scatter_gather32_t)
67
68#define DRM_IOCTL_WAIT_VBLANK32 DRM_IOWR(0x3a, drm_wait_vblank32_t)
69
70typedef struct drm_version_32 {
71 int version_major; /**< Major version */
72 int version_minor; /**< Minor version */
73 int version_patchlevel;/**< Patch level */
74 u32 name_len; /**< Length of name buffer */
75 u32 name; /**< Name of driver */
76 u32 date_len; /**< Length of date buffer */
77 u32 date; /**< User-space buffer to hold date */
78 u32 desc_len; /**< Length of desc buffer */
79 u32 desc; /**< User-space buffer to hold desc */
80} drm_version32_t;
81
82static int compat_drm_version(struct file *file, unsigned int cmd,
83 unsigned long arg)
84{
85 drm_version32_t v32;
86 drm_version_t __user *version;
87 int err;
88
89 if (copy_from_user(&v32, (void __user *) arg, sizeof(v32)))
90 return -EFAULT;
91
92 version = compat_alloc_user_space(sizeof(*version));
93 if (!access_ok(VERIFY_WRITE, version, sizeof(*version)))
94 return -EFAULT;
95 if (__put_user(v32.name_len, &version->name_len)
96 || __put_user((void __user *)(unsigned long)v32.name,
97 &version->name)
98 || __put_user(v32.date_len, &version->date_len)
99 || __put_user((void __user *)(unsigned long)v32.date,
100 &version->date)
101 || __put_user(v32.desc_len, &version->desc_len)
102 || __put_user((void __user *)(unsigned long)v32.desc,
103 &version->desc))
104 return -EFAULT;
105
106 err = drm_ioctl(file->f_dentry->d_inode, file,
107 DRM_IOCTL_VERSION, (unsigned long) version);
108 if (err)
109 return err;
110
111 if (__get_user(v32.version_major, &version->version_major)
112 || __get_user(v32.version_minor, &version->version_minor)
113 || __get_user(v32.version_patchlevel, &version->version_patchlevel)
114 || __get_user(v32.name_len, &version->name_len)
115 || __get_user(v32.date_len, &version->date_len)
116 || __get_user(v32.desc_len, &version->desc_len))
117 return -EFAULT;
118
119 if (copy_to_user((void __user *) arg, &v32, sizeof(v32)))
120 return -EFAULT;
121 return 0;
122}
123
124typedef struct drm_unique32 {
125 u32 unique_len; /**< Length of unique */
126 u32 unique; /**< Unique name for driver instantiation */
127} drm_unique32_t;
128
129static int compat_drm_getunique(struct file *file, unsigned int cmd,
130 unsigned long arg)
131{
132 drm_unique32_t uq32;
133 drm_unique_t __user *u;
134 int err;
135
136 if (copy_from_user(&uq32, (void __user *) arg, sizeof(uq32)))
137 return -EFAULT;
138
139 u = compat_alloc_user_space(sizeof(*u));
140 if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
141 return -EFAULT;
142 if (__put_user(uq32.unique_len, &u->unique_len)
143 || __put_user((void __user *)(unsigned long) uq32.unique,
144 &u->unique))
145 return -EFAULT;
146
147 err = drm_ioctl(file->f_dentry->d_inode, file,
148 DRM_IOCTL_GET_UNIQUE, (unsigned long) u);
149 if (err)
150 return err;
151
152 if (__get_user(uq32.unique_len, &u->unique_len))
153 return -EFAULT;
154 if (copy_to_user((void __user *) arg, &uq32, sizeof(uq32)))
155 return -EFAULT;
156 return 0;
157}
158
159static int compat_drm_setunique(struct file *file, unsigned int cmd,
160 unsigned long arg)
161{
162 drm_unique32_t uq32;
163 drm_unique_t __user *u;
164
165 if (copy_from_user(&uq32, (void __user *) arg, sizeof(uq32)))
166 return -EFAULT;
167
168 u = compat_alloc_user_space(sizeof(*u));
169 if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
170 return -EFAULT;
171 if (__put_user(uq32.unique_len, &u->unique_len)
172 || __put_user((void __user *)(unsigned long) uq32.unique,
173 &u->unique))
174 return -EFAULT;
175
176 return drm_ioctl(file->f_dentry->d_inode, file,
177 DRM_IOCTL_SET_UNIQUE, (unsigned long) u);
178}
179
180typedef struct drm_map32 {
181 u32 offset; /**< Requested physical address (0 for SAREA)*/
182 u32 size; /**< Requested physical size (bytes) */
183 drm_map_type_t type; /**< Type of memory to map */
184 drm_map_flags_t flags; /**< Flags */
185 u32 handle; /**< User-space: "Handle" to pass to mmap() */
186 int mtrr; /**< MTRR slot used */
187} drm_map32_t;
188
189static int compat_drm_getmap(struct file *file, unsigned int cmd,
190 unsigned long arg)
191{
192 drm_map32_t __user *argp = (void __user *)arg;
193 drm_map32_t m32;
194 drm_map_t __user *map;
195 int idx, err;
196 void *handle;
197
198 if (get_user(idx, &argp->offset))
199 return -EFAULT;
200
201 map = compat_alloc_user_space(sizeof(*map));
202 if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
203 return -EFAULT;
204 if (__put_user(idx, &map->offset))
205 return -EFAULT;
206
207 err = drm_ioctl(file->f_dentry->d_inode, file,
208 DRM_IOCTL_GET_MAP, (unsigned long) map);
209 if (err)
210 return err;
211
212 if (__get_user(m32.offset, &map->offset)
213 || __get_user(m32.size, &map->size)
214 || __get_user(m32.type, &map->type)
215 || __get_user(m32.flags, &map->flags)
216 || __get_user(handle, &map->handle)
217 || __get_user(m32.mtrr, &map->mtrr))
218 return -EFAULT;
219
220 m32.handle = (unsigned long) handle;
221 if (copy_to_user(argp, &m32, sizeof(m32)))
222 return -EFAULT;
223 return 0;
224
225}
226
227static int compat_drm_addmap(struct file *file, unsigned int cmd,
228 unsigned long arg)
229{
230 drm_map32_t __user *argp = (void __user *)arg;
231 drm_map32_t m32;
232 drm_map_t __user *map;
233 int err;
234 void *handle;
235
236 if (copy_from_user(&m32, argp, sizeof(m32)))
237 return -EFAULT;
238
239 map = compat_alloc_user_space(sizeof(*map));
240 if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
241 return -EFAULT;
242 if (__put_user(m32.offset, &map->offset)
243 || __put_user(m32.size, &map->size)
244 || __put_user(m32.type, &map->type)
245 || __put_user(m32.flags, &map->flags))
246 return -EFAULT;
247
248 err = drm_ioctl(file->f_dentry->d_inode, file,
249 DRM_IOCTL_ADD_MAP, (unsigned long) map);
250 if (err)
251 return err;
252
253 if (__get_user(m32.offset, &map->offset)
254 || __get_user(m32.mtrr, &map->mtrr)
255 || __get_user(handle, &map->handle))
256 return -EFAULT;
257
258 m32.handle = (unsigned long) handle;
259 if (m32.handle != (unsigned long) handle && printk_ratelimit())
260 printk(KERN_ERR "compat_drm_addmap truncated handle"
261 " %p for type %d offset %x\n",
262 handle, m32.type, m32.offset);
263
264 if (copy_to_user(argp, &m32, sizeof(m32)))
265 return -EFAULT;
266
267 return 0;
268}
269
270static int compat_drm_rmmap(struct file *file, unsigned int cmd,
271 unsigned long arg)
272{
273 drm_map32_t __user *argp = (void __user *)arg;
274 drm_map_t __user *map;
275 u32 handle;
276
277 if (get_user(handle, &argp->handle))
278 return -EFAULT;
279
280 map = compat_alloc_user_space(sizeof(*map));
281 if (!access_ok(VERIFY_WRITE, map, sizeof(*map)))
282 return -EFAULT;
283 if (__put_user((void *)(unsigned long) handle, &map->handle))
284 return -EFAULT;
285
286 return drm_ioctl(file->f_dentry->d_inode, file,
287 DRM_IOCTL_RM_MAP, (unsigned long) map);
288}
289
290typedef struct drm_client32 {
291 int idx; /**< Which client desired? */
292 int auth; /**< Is client authenticated? */
293 u32 pid; /**< Process ID */
294 u32 uid; /**< User ID */
295 u32 magic; /**< Magic */
296 u32 iocs; /**< Ioctl count */
297} drm_client32_t;
298
299static int compat_drm_getclient(struct file *file, unsigned int cmd,
300 unsigned long arg)
301{
302 drm_client32_t c32;
303 drm_client32_t __user *argp = (void __user *)arg;
304 drm_client_t __user *client;
305 int idx, err;
306
307 if (get_user(idx, &argp->idx))
308 return -EFAULT;
309
310 client = compat_alloc_user_space(sizeof(*client));
311 if (!access_ok(VERIFY_WRITE, client, sizeof(*client)))
312 return -EFAULT;
313 if (__put_user(idx, &client->idx))
314 return -EFAULT;
315
316 err = drm_ioctl(file->f_dentry->d_inode, file,
317 DRM_IOCTL_GET_CLIENT, (unsigned long) client);
318 if (err)
319 return err;
320
321 if (__get_user(c32.auth, &client->auth)
322 || __get_user(c32.pid, &client->pid)
323 || __get_user(c32.uid, &client->uid)
324 || __get_user(c32.magic, &client->magic)
325 || __get_user(c32.iocs, &client->iocs))
326 return -EFAULT;
327
328 if (copy_to_user(argp, &c32, sizeof(c32)))
329 return -EFAULT;
330 return 0;
331}
332
333typedef struct drm_stats32 {
334 u32 count;
335 struct {
336 u32 value;
337 drm_stat_type_t type;
338 } data[15];
339} drm_stats32_t;
340
341static int compat_drm_getstats(struct file *file, unsigned int cmd,
342 unsigned long arg)
343{
344 drm_stats32_t s32;
345 drm_stats32_t __user *argp = (void __user *)arg;
346 drm_stats_t __user *stats;
347 int i, err;
348
349 stats = compat_alloc_user_space(sizeof(*stats));
350 if (!access_ok(VERIFY_WRITE, stats, sizeof(*stats)))
351 return -EFAULT;
352
353 err = drm_ioctl(file->f_dentry->d_inode, file,
354 DRM_IOCTL_GET_STATS, (unsigned long) stats);
355 if (err)
356 return err;
357
358 if (__get_user(s32.count, &stats->count))
359 return -EFAULT;
360 for (i = 0; i < 15; ++i)
361 if (__get_user(s32.data[i].value, &stats->data[i].value)
362 || __get_user(s32.data[i].type, &stats->data[i].type))
363 return -EFAULT;
364
365 if (copy_to_user(argp, &s32, sizeof(s32)))
366 return -EFAULT;
367 return 0;
368}
369
370typedef struct drm_buf_desc32 {
371 int count; /**< Number of buffers of this size */
372 int size; /**< Size in bytes */
373 int low_mark; /**< Low water mark */
374 int high_mark; /**< High water mark */
375 int flags;
376 u32 agp_start; /**< Start address in the AGP aperture */
377} drm_buf_desc32_t;
378
379static int compat_drm_addbufs(struct file *file, unsigned int cmd,
380 unsigned long arg)
381{
382 drm_buf_desc32_t __user *argp = (void __user *)arg;
383 drm_buf_desc_t __user *buf;
384 int err;
385 unsigned long agp_start;
386
387 buf = compat_alloc_user_space(sizeof(*buf));
388 if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf))
389 || !access_ok(VERIFY_WRITE, argp, sizeof(*argp)))
390 return -EFAULT;
391
392 if (__copy_in_user(buf, argp, offsetof(drm_buf_desc32_t, agp_start))
393 || __get_user(agp_start, &argp->agp_start)
394 || __put_user(agp_start, &buf->agp_start))
395 return -EFAULT;
396
397 err = drm_ioctl(file->f_dentry->d_inode, file,
398 DRM_IOCTL_ADD_BUFS, (unsigned long) buf);
399 if (err)
400 return err;
401
402 if (__copy_in_user(argp, buf, offsetof(drm_buf_desc32_t, agp_start))
403 || __get_user(agp_start, &buf->agp_start)
404 || __put_user(agp_start, &argp->agp_start))
405 return -EFAULT;
406
407 return 0;
408}
409
410static int compat_drm_markbufs(struct file *file, unsigned int cmd,
411 unsigned long arg)
412{
413 drm_buf_desc32_t b32;
414 drm_buf_desc32_t __user *argp = (void __user *)arg;
415 drm_buf_desc_t __user *buf;
416
417 if (copy_from_user(&b32, argp, sizeof(b32)))
418 return -EFAULT;
419
420 buf = compat_alloc_user_space(sizeof(*buf));
421 if (!access_ok(VERIFY_WRITE, buf, sizeof(*buf)))
422 return -EFAULT;
423
424 if (__put_user(b32.size, &buf->size)
425 || __put_user(b32.low_mark, &buf->low_mark)
426 || __put_user(b32.high_mark, &buf->high_mark))
427 return -EFAULT;
428
429 return drm_ioctl(file->f_dentry->d_inode, file,
430 DRM_IOCTL_MARK_BUFS, (unsigned long) buf);
431}
432
433typedef struct drm_buf_info32 {
434 int count; /**< Entries in list */
435 u32 list;
436} drm_buf_info32_t;
437
438static int compat_drm_infobufs(struct file *file, unsigned int cmd,
439 unsigned long arg)
440{
441 drm_buf_info32_t req32;
442 drm_buf_info32_t __user *argp = (void __user *)arg;
443 drm_buf_desc32_t __user *to;
444 drm_buf_info_t __user *request;
445 drm_buf_desc_t __user *list;
446 size_t nbytes;
447 int i, err;
448 int count, actual;
449
450 if (copy_from_user(&req32, argp, sizeof(req32)))
451 return -EFAULT;
452
453 count = req32.count;
454 to = (drm_buf_desc32_t __user *)(unsigned long) req32.list;
455 if (count < 0)
456 count = 0;
457 if (count > 0
458 && !access_ok(VERIFY_WRITE, to, count * sizeof(drm_buf_desc32_t)))
459 return -EFAULT;
460
461 nbytes = sizeof(*request) + count * sizeof(drm_buf_desc_t);
462 request = compat_alloc_user_space(nbytes);
463 if (!access_ok(VERIFY_WRITE, request, nbytes))
464 return -EFAULT;
465 list = (drm_buf_desc_t *) (request + 1);
466
467 if (__put_user(count, &request->count)
468 || __put_user(list, &request->list))
469 return -EFAULT;
470
471 err = drm_ioctl(file->f_dentry->d_inode, file,
472 DRM_IOCTL_INFO_BUFS, (unsigned long) request);
473 if (err)
474 return err;
475
476 if (__get_user(actual, &request->count))
477 return -EFAULT;
478 if (count >= actual)
479 for (i = 0; i < actual; ++i)
480 if (__copy_in_user(&to[i], &list[i],
481 offsetof(drm_buf_desc_t, flags)))
482 return -EFAULT;
483
484 if (__put_user(actual, &argp->count))
485 return -EFAULT;
486
487 return 0;
488}
489
490typedef struct drm_buf_pub32 {
491 int idx; /**< Index into the master buffer list */
492 int total; /**< Buffer size */
493 int used; /**< Amount of buffer in use (for DMA) */
494 u32 address; /**< Address of buffer */
495} drm_buf_pub32_t;
496
497typedef struct drm_buf_map32 {
498 int count; /**< Length of the buffer list */
499 u32 virtual; /**< Mmap'd area in user-virtual */
500 u32 list; /**< Buffer information */
501} drm_buf_map32_t;
502
503static int compat_drm_mapbufs(struct file *file, unsigned int cmd,
504 unsigned long arg)
505{
506 drm_buf_map32_t __user *argp = (void __user *)arg;
507 drm_buf_map32_t req32;
508 drm_buf_pub32_t __user *list32;
509 drm_buf_map_t __user *request;
510 drm_buf_pub_t __user *list;
511 int i, err;
512 int count, actual;
513 size_t nbytes;
514 void __user *addr;
515
516 if (copy_from_user(&req32, argp, sizeof(req32)))
517 return -EFAULT;
518 count = req32.count;
519 list32 = (void __user *)(unsigned long)req32.list;
520
521 if (count < 0)
522 return -EINVAL;
523 nbytes = sizeof(*request) + count * sizeof(drm_buf_pub_t);
524 request = compat_alloc_user_space(nbytes);
525 if (!access_ok(VERIFY_WRITE, request, nbytes))
526 return -EFAULT;
527 list = (drm_buf_pub_t *) (request + 1);
528
529 if (__put_user(count, &request->count)
530 || __put_user(list, &request->list))
531 return -EFAULT;
532
533 err = drm_ioctl(file->f_dentry->d_inode, file,
534 DRM_IOCTL_MAP_BUFS, (unsigned long) request);
535 if (err)
536 return err;
537
538 if (__get_user(actual, &request->count))
539 return -EFAULT;
540 if (count >= actual)
541 for (i = 0; i < actual; ++i)
542 if (__copy_in_user(&list32[i], &list[i],
543 offsetof(drm_buf_pub_t, address))
544 || __get_user(addr, &list[i].address)
545 || __put_user((unsigned long) addr,
546 &list32[i].address))
547 return -EFAULT;
548
549 if (__put_user(actual, &argp->count)
550 || __get_user(addr, &request->virtual)
551 || __put_user((unsigned long) addr, &argp->virtual))
552 return -EFAULT;
553
554 return 0;
555}
556
557typedef struct drm_buf_free32 {
558 int count;
559 u32 list;
560} drm_buf_free32_t;
561
562static int compat_drm_freebufs(struct file *file, unsigned int cmd,
563 unsigned long arg)
564{
565 drm_buf_free32_t req32;
566 drm_buf_free_t __user *request;
567 drm_buf_free32_t __user *argp = (void __user *)arg;
568
569 if (copy_from_user(&req32, argp, sizeof(req32)))
570 return -EFAULT;
571
572 request = compat_alloc_user_space(sizeof(*request));
573 if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
574 return -EFAULT;
575 if (__put_user(req32.count, &request->count)
576 || __put_user((int __user *)(unsigned long) req32.list,
577 &request->list))
578 return -EFAULT;
579
580 return drm_ioctl(file->f_dentry->d_inode, file,
581 DRM_IOCTL_FREE_BUFS, (unsigned long) request);
582}
583
584typedef struct drm_ctx_priv_map32 {
585 unsigned int ctx_id; /**< Context requesting private mapping */
586 u32 handle; /**< Handle of map */
587} drm_ctx_priv_map32_t;
588
589static int compat_drm_setsareactx(struct file *file, unsigned int cmd,
590 unsigned long arg)
591{
592 drm_ctx_priv_map32_t req32;
593 drm_ctx_priv_map_t __user *request;
594 drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
595
596 if (copy_from_user(&req32, argp, sizeof(req32)))
597 return -EFAULT;
598
599 request = compat_alloc_user_space(sizeof(*request));
600 if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
601 return -EFAULT;
602 if (__put_user(req32.ctx_id, &request->ctx_id)
603 || __put_user((void *)(unsigned long) req32.handle,
604 &request->handle))
605 return -EFAULT;
606
607 return drm_ioctl(file->f_dentry->d_inode, file,
608 DRM_IOCTL_SET_SAREA_CTX, (unsigned long) request);
609}
610
611static int compat_drm_getsareactx(struct file *file, unsigned int cmd,
612 unsigned long arg)
613{
614 drm_ctx_priv_map_t __user *request;
615 drm_ctx_priv_map32_t __user *argp = (void __user *)arg;
616 int err;
617 unsigned int ctx_id;
618 void *handle;
619
620 if (!access_ok(VERIFY_WRITE, argp, sizeof(*argp))
621 || __get_user(ctx_id, &argp->ctx_id))
622 return -EFAULT;
623
624 request = compat_alloc_user_space(sizeof(*request));
625 if (!access_ok(VERIFY_WRITE, request, sizeof(*request)))
626 return -EFAULT;
627 if (__put_user(ctx_id, &request->ctx_id))
628 return -EFAULT;
629
630 err = drm_ioctl(file->f_dentry->d_inode, file,
631 DRM_IOCTL_GET_SAREA_CTX, (unsigned long) request);
632 if (err)
633 return err;
634
635 if (__get_user(handle, &request->handle)
636 || __put_user((unsigned long) handle, &argp->handle))
637 return -EFAULT;
638
639 return 0;
640}
641
642typedef struct drm_ctx_res32 {
643 int count;
644 u32 contexts;
645} drm_ctx_res32_t;
646
647static int compat_drm_resctx(struct file *file, unsigned int cmd,
648 unsigned long arg)
649{
650 drm_ctx_res32_t __user *argp = (void __user *)arg;
651 drm_ctx_res32_t res32;
652 drm_ctx_res_t __user *res;
653 int err;
654
655 if (copy_from_user(&res32, argp, sizeof(res32)))
656 return -EFAULT;
657
658 res = compat_alloc_user_space(sizeof(*res));
659 if (!access_ok(VERIFY_WRITE, res, sizeof(*res)))
660 return -EFAULT;
661 if (__put_user(res32.count, &res->count)
662 || __put_user((drm_ctx_t __user *)(unsigned long) res32.contexts,
663 &res->contexts))
664 return -EFAULT;
665
666 err = drm_ioctl(file->f_dentry->d_inode, file,
667 DRM_IOCTL_RES_CTX, (unsigned long) res);
668 if (err)
669 return err;
670
671 if (__get_user(res32.count, &res->count)
672 || __put_user(res32.count, &argp->count))
673 return -EFAULT;
674
675 return 0;
676}
677
678typedef struct drm_dma32 {
679 int context; /**< Context handle */
680 int send_count; /**< Number of buffers to send */
681 u32 send_indices; /**< List of handles to buffers */
682 u32 send_sizes; /**< Lengths of data to send */
683 drm_dma_flags_t flags; /**< Flags */
684 int request_count; /**< Number of buffers requested */
685 int request_size; /**< Desired size for buffers */
686 u32 request_indices; /**< Buffer information */
687 u32 request_sizes;
688 int granted_count; /**< Number of buffers granted */
689} drm_dma32_t;
690
691static int compat_drm_dma(struct file *file, unsigned int cmd,
692 unsigned long arg)
693{
694 drm_dma32_t d32;
695 drm_dma32_t __user *argp = (void __user *) arg;
696 drm_dma_t __user *d;
697 int err;
698
699 if (copy_from_user(&d32, argp, sizeof(d32)))
700 return -EFAULT;
701
702 d = compat_alloc_user_space(sizeof(*d));
703 if (!access_ok(VERIFY_WRITE, d, sizeof(*d)))
704 return -EFAULT;
705
706 if (__put_user(d32.context, &d->context)
707 || __put_user(d32.send_count, &d->send_count)
708 || __put_user((int __user *)(unsigned long) d32.send_indices,
709 &d->send_indices)
710 || __put_user((int __user *)(unsigned long) d32.send_sizes,
711 &d->send_sizes)
712 || __put_user(d32.flags, &d->flags)
713 || __put_user(d32.request_count, &d->request_count)
714 || __put_user((int __user *)(unsigned long) d32.request_indices,
715 &d->request_indices)
716 || __put_user((int __user *)(unsigned long) d32.request_sizes,
717 &d->request_sizes))
718 return -EFAULT;
719
720 err = drm_ioctl(file->f_dentry->d_inode, file,
721 DRM_IOCTL_DMA, (unsigned long) d);
722 if (err)
723 return err;
724
725 if (__get_user(d32.request_size, &d->request_size)
726 || __get_user(d32.granted_count, &d->granted_count)
727 || __put_user(d32.request_size, &argp->request_size)
728 || __put_user(d32.granted_count, &argp->granted_count))
729 return -EFAULT;
730
731 return 0;
732}
733
734#if __OS_HAS_AGP
735typedef struct drm_agp_mode32 {
736 u32 mode; /**< AGP mode */
737} drm_agp_mode32_t;
738
739static int compat_drm_agp_enable(struct file *file, unsigned int cmd,
740 unsigned long arg)
741{
742 drm_agp_mode32_t __user *argp = (void __user *)arg;
743 drm_agp_mode32_t m32;
744 drm_agp_mode_t __user *mode;
745
746 if (get_user(m32.mode, &argp->mode))
747 return -EFAULT;
748
749 mode = compat_alloc_user_space(sizeof(*mode));
750 if (put_user(m32.mode, &mode->mode))
751 return -EFAULT;
752
753 return drm_ioctl(file->f_dentry->d_inode, file,
754 DRM_IOCTL_AGP_ENABLE, (unsigned long) mode);
755}
756
757typedef struct drm_agp_info32 {
758 int agp_version_major;
759 int agp_version_minor;
760 u32 mode;
761 u32 aperture_base; /* physical address */
762 u32 aperture_size; /* bytes */
763 u32 memory_allowed; /* bytes */
764 u32 memory_used;
765
766 /* PCI information */
767 unsigned short id_vendor;
768 unsigned short id_device;
769} drm_agp_info32_t;
770
771static int compat_drm_agp_info(struct file *file, unsigned int cmd,
772 unsigned long arg)
773{
774 drm_agp_info32_t __user *argp = (void __user *)arg;
775 drm_agp_info32_t i32;
776 drm_agp_info_t __user *info;
777 int err;
778
779 info = compat_alloc_user_space(sizeof(*info));
780 if (!access_ok(VERIFY_WRITE, info, sizeof(*info)))
781 return -EFAULT;
782
783 err = drm_ioctl(file->f_dentry->d_inode, file,
784 DRM_IOCTL_AGP_INFO, (unsigned long) info);
785 if (err)
786 return err;
787
788 if (__get_user(i32.agp_version_major, &info->agp_version_major)
789 || __get_user(i32.agp_version_minor, &info->agp_version_minor)
790 || __get_user(i32.mode, &info->mode)
791 || __get_user(i32.aperture_base, &info->aperture_base)
792 || __get_user(i32.aperture_size, &info->aperture_size)
793 || __get_user(i32.memory_allowed, &info->memory_allowed)
794 || __get_user(i32.memory_used, &info->memory_used)
795 || __get_user(i32.id_vendor, &info->id_vendor)
796 || __get_user(i32.id_device, &info->id_device))
797 return -EFAULT;
798
799 if (copy_to_user(argp, &i32, sizeof(i32)))
800 return -EFAULT;
801
802 return 0;
803}
804
805typedef struct drm_agp_buffer32 {
806 u32 size; /**< In bytes -- will round to page boundary */
807 u32 handle; /**< Used for binding / unbinding */
808 u32 type; /**< Type of memory to allocate */
809 u32 physical; /**< Physical used by i810 */
810} drm_agp_buffer32_t;
811
812static int compat_drm_agp_alloc(struct file *file, unsigned int cmd,
813 unsigned long arg)
814{
815 drm_agp_buffer32_t __user *argp = (void __user *)arg;
816 drm_agp_buffer32_t req32;
817 drm_agp_buffer_t __user *request;
818 int err;
819
820 if (copy_from_user(&req32, argp, sizeof(req32)))
821 return -EFAULT;
822
823 request = compat_alloc_user_space(sizeof(*request));
824 if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
825 || __put_user(req32.size, &request->size)
826 || __put_user(req32.type, &request->type))
827 return -EFAULT;
828
829 err = drm_ioctl(file->f_dentry->d_inode, file,
830 DRM_IOCTL_AGP_ALLOC, (unsigned long) request);
831 if (err)
832 return err;
833
834 if (__get_user(req32.handle, &request->handle)
835 || __get_user(req32.physical, &request->physical)
836 || copy_to_user(argp, &req32, sizeof(req32))) {
837 drm_ioctl(file->f_dentry->d_inode, file,
838 DRM_IOCTL_AGP_FREE, (unsigned long) request);
839 return -EFAULT;
840 }
841
842 return 0;
843}
844
845static int compat_drm_agp_free(struct file *file, unsigned int cmd,
846 unsigned long arg)
847{
848 drm_agp_buffer32_t __user *argp = (void __user *)arg;
849 drm_agp_buffer_t __user *request;
850 u32 handle;
851
852 request = compat_alloc_user_space(sizeof(*request));
853 if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
854 || get_user(handle, &argp->handle)
855 || __put_user(handle, &request->handle))
856 return -EFAULT;
857
858 return drm_ioctl(file->f_dentry->d_inode, file,
859 DRM_IOCTL_AGP_FREE, (unsigned long) request);
860}
861
862typedef struct drm_agp_binding32 {
863 u32 handle; /**< From drm_agp_buffer */
864 u32 offset; /**< In bytes -- will round to page boundary */
865} drm_agp_binding32_t;
866
867static int compat_drm_agp_bind(struct file *file, unsigned int cmd,
868 unsigned long arg)
869{
870 drm_agp_binding32_t __user *argp = (void __user *)arg;
871 drm_agp_binding32_t req32;
872 drm_agp_binding_t __user *request;
873
874 if (copy_from_user(&req32, argp, sizeof(req32)))
875 return -EFAULT;
876
877 request = compat_alloc_user_space(sizeof(*request));
878 if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
879 || __put_user(req32.handle, &request->handle)
880 || __put_user(req32.offset, &request->offset))
881 return -EFAULT;
882
883 return drm_ioctl(file->f_dentry->d_inode, file,
884 DRM_IOCTL_AGP_BIND, (unsigned long) request);
885}
886
887static int compat_drm_agp_unbind(struct file *file, unsigned int cmd,
888 unsigned long arg)
889{
890 drm_agp_binding32_t __user *argp = (void __user *)arg;
891 drm_agp_binding_t __user *request;
892 u32 handle;
893
894 request = compat_alloc_user_space(sizeof(*request));
895 if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
896 || get_user(handle, &argp->handle)
897 || __put_user(handle, &request->handle))
898 return -EFAULT;
899
900 return drm_ioctl(file->f_dentry->d_inode, file,
901 DRM_IOCTL_AGP_UNBIND, (unsigned long) request);
902}
903#endif /* __OS_HAS_AGP */
904
905typedef struct drm_scatter_gather32 {
906 u32 size; /**< In bytes -- will round to page boundary */
907 u32 handle; /**< Used for mapping / unmapping */
908} drm_scatter_gather32_t;
909
910static int compat_drm_sg_alloc(struct file *file, unsigned int cmd,
911 unsigned long arg)
912{
913 drm_scatter_gather32_t __user *argp = (void __user *)arg;
914 drm_scatter_gather_t __user *request;
915 int err;
916 unsigned long x;
917
918 request = compat_alloc_user_space(sizeof(*request));
919 if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
920 || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))
921 || __get_user(x, &argp->size)
922 || __put_user(x, &request->size))
923 return -EFAULT;
924
925 err = drm_ioctl(file->f_dentry->d_inode, file,
926 DRM_IOCTL_SG_ALLOC, (unsigned long) request);
927 if (err)
928 return err;
929
930 /* XXX not sure about the handle conversion here... */
931 if (__get_user(x, &request->handle)
932 || __put_user(x >> PAGE_SHIFT, &argp->handle))
933 return -EFAULT;
934
935 return 0;
936}
937
938static int compat_drm_sg_free(struct file *file, unsigned int cmd,
939 unsigned long arg)
940{
941 drm_scatter_gather32_t __user *argp = (void __user *)arg;
942 drm_scatter_gather_t __user *request;
943 unsigned long x;
944
945 request = compat_alloc_user_space(sizeof(*request));
946 if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
947 || !access_ok(VERIFY_WRITE, argp, sizeof(*argp))
948 || __get_user(x, &argp->handle)
949 || __put_user(x << PAGE_SHIFT, &request->handle))
950 return -EFAULT;
951
952 return drm_ioctl(file->f_dentry->d_inode, file,
953 DRM_IOCTL_SG_FREE, (unsigned long) request);
954}
955
956struct drm_wait_vblank_request32 {
957 drm_vblank_seq_type_t type;
958 unsigned int sequence;
959 u32 signal;
960};
961
962struct drm_wait_vblank_reply32 {
963 drm_vblank_seq_type_t type;
964 unsigned int sequence;
965 s32 tval_sec;
966 s32 tval_usec;
967};
968
969typedef union drm_wait_vblank32 {
970 struct drm_wait_vblank_request32 request;
971 struct drm_wait_vblank_reply32 reply;
972} drm_wait_vblank32_t;
973
974static int compat_drm_wait_vblank(struct file *file, unsigned int cmd,
975 unsigned long arg)
976{
977 drm_wait_vblank32_t __user *argp = (void __user *)arg;
978 drm_wait_vblank32_t req32;
979 drm_wait_vblank_t __user *request;
980 int err;
981
982 if (copy_from_user(&req32, argp, sizeof(req32)))
983 return -EFAULT;
984
985 request = compat_alloc_user_space(sizeof(*request));
986 if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
987 || __put_user(req32.request.type, &request->request.type)
988 || __put_user(req32.request.sequence, &request->request.sequence)
989 || __put_user(req32.request.signal, &request->request.signal))
990 return -EFAULT;
991
992 err = drm_ioctl(file->f_dentry->d_inode, file,
993 DRM_IOCTL_WAIT_VBLANK, (unsigned long) request);
994 if (err)
995 return err;
996
997 if (__get_user(req32.reply.type, &request->reply.type)
998 || __get_user(req32.reply.sequence, &request->reply.sequence)
999 || __get_user(req32.reply.tval_sec, &request->reply.tval_sec)
1000 || __get_user(req32.reply.tval_usec, &request->reply.tval_usec))
1001 return -EFAULT;
1002
1003 if (copy_to_user(argp, &req32, sizeof(req32)))
1004 return -EFAULT;
1005
1006 return 0;
1007}
1008
1009drm_ioctl_compat_t *drm_compat_ioctls[] = {
1010 [DRM_IOCTL_NR(DRM_IOCTL_VERSION32)] = compat_drm_version,
1011 [DRM_IOCTL_NR(DRM_IOCTL_GET_UNIQUE32)] = compat_drm_getunique,
1012 [DRM_IOCTL_NR(DRM_IOCTL_GET_MAP32)] = compat_drm_getmap,
1013 [DRM_IOCTL_NR(DRM_IOCTL_GET_CLIENT32)] = compat_drm_getclient,
1014 [DRM_IOCTL_NR(DRM_IOCTL_GET_STATS32)] = compat_drm_getstats,
1015 [DRM_IOCTL_NR(DRM_IOCTL_SET_UNIQUE32)] = compat_drm_setunique,
1016 [DRM_IOCTL_NR(DRM_IOCTL_ADD_MAP32)] = compat_drm_addmap,
1017 [DRM_IOCTL_NR(DRM_IOCTL_ADD_BUFS32)] = compat_drm_addbufs,
1018 [DRM_IOCTL_NR(DRM_IOCTL_MARK_BUFS32)] = compat_drm_markbufs,
1019 [DRM_IOCTL_NR(DRM_IOCTL_INFO_BUFS32)] = compat_drm_infobufs,
1020 [DRM_IOCTL_NR(DRM_IOCTL_MAP_BUFS32)] = compat_drm_mapbufs,
1021 [DRM_IOCTL_NR(DRM_IOCTL_FREE_BUFS32)] = compat_drm_freebufs,
1022 [DRM_IOCTL_NR(DRM_IOCTL_RM_MAP32)] = compat_drm_rmmap,
1023 [DRM_IOCTL_NR(DRM_IOCTL_SET_SAREA_CTX32)] = compat_drm_setsareactx,
1024 [DRM_IOCTL_NR(DRM_IOCTL_GET_SAREA_CTX32)] = compat_drm_getsareactx,
1025 [DRM_IOCTL_NR(DRM_IOCTL_RES_CTX32)] = compat_drm_resctx,
1026 [DRM_IOCTL_NR(DRM_IOCTL_DMA32)] = compat_drm_dma,
1027#if __OS_HAS_AGP
1028 [DRM_IOCTL_NR(DRM_IOCTL_AGP_ENABLE32)] = compat_drm_agp_enable,
1029 [DRM_IOCTL_NR(DRM_IOCTL_AGP_INFO32)] = compat_drm_agp_info,
1030 [DRM_IOCTL_NR(DRM_IOCTL_AGP_ALLOC32)] = compat_drm_agp_alloc,
1031 [DRM_IOCTL_NR(DRM_IOCTL_AGP_FREE32)] = compat_drm_agp_free,
1032 [DRM_IOCTL_NR(DRM_IOCTL_AGP_BIND32)] = compat_drm_agp_bind,
1033 [DRM_IOCTL_NR(DRM_IOCTL_AGP_UNBIND32)] = compat_drm_agp_unbind,
1034#endif
1035 [DRM_IOCTL_NR(DRM_IOCTL_SG_ALLOC32)] = compat_drm_sg_alloc,
1036 [DRM_IOCTL_NR(DRM_IOCTL_SG_FREE32)] = compat_drm_sg_free,
1037 [DRM_IOCTL_NR(DRM_IOCTL_WAIT_VBLANK32)] = compat_drm_wait_vblank,
1038};
1039
1040/**
1041 * Called whenever a 32-bit process running under a 64-bit kernel
1042 * performs an ioctl on /dev/drm.
1043 *
1044 * \param filp file pointer.
1045 * \param cmd command.
1046 * \param arg user argument.
1047 * \return zero on success or negative number on failure.
1048 */
1049long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
1050{
1051 unsigned int nr = DRM_IOCTL_NR(cmd);
1052 drm_ioctl_compat_t *fn;
1053 int ret;
1054
1055 if (nr >= DRM_ARRAY_SIZE(drm_compat_ioctls))
1056 return -ENOTTY;
1057
1058 fn = drm_compat_ioctls[nr];
1059
1060 lock_kernel(); /* XXX for now */
1061 if (fn != NULL)
1062 ret = (*fn)(filp, cmd, arg);
1063 else
1064 ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
1065 unlock_kernel();
1066
1067 return ret;
1068}
1069EXPORT_SYMBOL(drm_compat_ioctl);
diff --git a/drivers/char/drm/drm_irq.c b/drivers/char/drm/drm_irq.c
index 2e236ebcf27b..cdd4aecd25e2 100644
--- a/drivers/char/drm/drm_irq.c
+++ b/drivers/char/drm/drm_irq.c
@@ -89,7 +89,7 @@ int drm_irq_by_busid(struct inode *inode, struct file *filp,
89 * \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions 89 * \c drm_driver_irq_preinstall() and \c drm_driver_irq_postinstall() functions
90 * before and after the installation. 90 * before and after the installation.
91 */ 91 */
92int drm_irq_install( drm_device_t *dev ) 92static int drm_irq_install( drm_device_t *dev )
93{ 93{
94 int ret; 94 int ret;
95 unsigned long sh_flags=0; 95 unsigned long sh_flags=0;
diff --git a/drivers/char/drm/drm_lock.c b/drivers/char/drm/drm_lock.c
index d0d6fc661625..4702d863bcc6 100644
--- a/drivers/char/drm/drm_lock.c
+++ b/drivers/char/drm/drm_lock.c
@@ -35,6 +35,11 @@
35 35
36#include "drmP.h" 36#include "drmP.h"
37 37
38static int drm_lock_transfer(drm_device_t *dev,
39 __volatile__ unsigned int *lock,
40 unsigned int context);
41static int drm_notifier(void *priv);
42
38/** 43/**
39 * Lock ioctl. 44 * Lock ioctl.
40 * 45 *
@@ -225,8 +230,9 @@ int drm_lock_take(__volatile__ unsigned int *lock, unsigned int context)
225 * Resets the lock file pointer. 230 * Resets the lock file pointer.
226 * Marks the lock as held by the given context, via the \p cmpxchg instruction. 231 * Marks the lock as held by the given context, via the \p cmpxchg instruction.
227 */ 232 */
228int drm_lock_transfer(drm_device_t *dev, 233static int drm_lock_transfer(drm_device_t *dev,
229 __volatile__ unsigned int *lock, unsigned int context) 234 __volatile__ unsigned int *lock,
235 unsigned int context)
230{ 236{
231 unsigned int old, new, prev; 237 unsigned int old, new, prev;
232 238
@@ -282,7 +288,7 @@ int drm_lock_free(drm_device_t *dev,
282 * \return one if the signal should be delivered normally, or zero if the 288 * \return one if the signal should be delivered normally, or zero if the
283 * signal should be blocked. 289 * signal should be blocked.
284 */ 290 */
285int drm_notifier(void *priv) 291static int drm_notifier(void *priv)
286{ 292{
287 drm_sigdata_t *s = (drm_sigdata_t *)priv; 293 drm_sigdata_t *s = (drm_sigdata_t *)priv;
288 unsigned int old, new, prev; 294 unsigned int old, new, prev;
diff --git a/drivers/char/drm/drm_memory.c b/drivers/char/drm/drm_memory.c
index 7f53f756c052..ace3d42f4407 100644
--- a/drivers/char/drm/drm_memory.c
+++ b/drivers/char/drm/drm_memory.c
@@ -65,19 +65,6 @@ int drm_mem_info(char *buf, char **start, off_t offset,
65 return 0; 65 return 0;
66} 66}
67 67
68/** Wrapper around kmalloc() */
69void *drm_calloc(size_t nmemb, size_t size, int area)
70{
71 void *addr;
72
73 addr = kmalloc(size * nmemb, GFP_KERNEL);
74 if (addr != NULL)
75 memset((void *)addr, 0, size * nmemb);
76
77 return addr;
78}
79EXPORT_SYMBOL(drm_calloc);
80
81/** Wrapper around kmalloc() and kfree() */ 68/** Wrapper around kmalloc() and kfree() */
82void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area) 69void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area)
83{ 70{
diff --git a/drivers/char/drm/drm_pciids.h b/drivers/char/drm/drm_pciids.h
index 54a2914e3a32..70ca4fa55c9d 100644
--- a/drivers/char/drm/drm_pciids.h
+++ b/drivers/char/drm/drm_pciids.h
@@ -220,5 +220,13 @@
220 {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ 220 {0x8086, 0x2572, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
221 {0x8086, 0x2582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ 221 {0x8086, 0x2582, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
222 {0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \ 222 {0x8086, 0x2592, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
223 {0x8086, 0x2772, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
224 {0, 0, 0}
225
226#define viadrv_PCI_IDS \
227 {0x1106, 0x3022, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
228 {0x1106, 0x3122, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
229 {0x1106, 0x7205, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
230 {0x1106, 0x7204, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0}, \
223 {0, 0, 0} 231 {0, 0, 0}
224 232
diff --git a/drivers/char/drm/drm_proc.c b/drivers/char/drm/drm_proc.c
index 6e06e8c6a516..4774087d2e9e 100644
--- a/drivers/char/drm/drm_proc.c
+++ b/drivers/char/drm/drm_proc.c
@@ -57,7 +57,7 @@ static int drm_vma_info(char *buf, char **start, off_t offset,
57/** 57/**
58 * Proc file list. 58 * Proc file list.
59 */ 59 */
60struct drm_proc_list { 60static struct drm_proc_list {
61 const char *name; /**< file name */ 61 const char *name; /**< file name */
62 int (*f)(char *, char **, off_t, int, int *, void *); /**< proc callback*/ 62 int (*f)(char *, char **, off_t, int, int *, void *); /**< proc callback*/
63} drm_proc_list[] = { 63} drm_proc_list[] = {
diff --git a/drivers/char/drm/drm_stub.c b/drivers/char/drm/drm_stub.c
index 8ccbdef7bb3e..48829a1a086a 100644
--- a/drivers/char/drm/drm_stub.c
+++ b/drivers/char/drm/drm_stub.c
@@ -157,52 +157,6 @@ int drm_stub_open(struct inode *inode, struct file *filp)
157 return err; 157 return err;
158} 158}
159 159
160
161/**
162 * Register.
163 *
164 * \param pdev - PCI device structure
165 * \param ent entry from the PCI ID table with device type flags
166 * \return zero on success or a negative number on failure.
167 *
168 * Attempt to gets inter module "drm" information. If we are first
169 * then register the character device and inter module information.
170 * Try and register, if we fail to register, backout previous work.
171 */
172int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
173 struct drm_driver *driver)
174{
175 drm_device_t *dev;
176 int ret;
177
178 DRM_DEBUG("\n");
179
180 dev = drm_calloc(1, sizeof(*dev), DRM_MEM_STUB);
181 if (!dev)
182 return -ENOMEM;
183
184 pci_enable_device(pdev);
185
186 if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) {
187 printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
188 goto err_g1;
189 }
190 if ((ret = drm_get_head(dev, &dev->primary)))
191 goto err_g1;
192
193 /* postinit is a required function to display the signon banner */
194 /* drivers add secondary heads here if needed */
195 if ((ret = dev->driver->postinit(dev, ent->driver_data)))
196 goto err_g1;
197
198 return 0;
199
200err_g1:
201 drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
202 return ret;
203}
204EXPORT_SYMBOL(drm_get_dev);
205
206/** 160/**
207 * Get a secondary minor number. 161 * Get a secondary minor number.
208 * 162 *
@@ -214,7 +168,7 @@ EXPORT_SYMBOL(drm_get_dev);
214 * create the proc init entry via proc_init(). This routines assigns 168 * create the proc init entry via proc_init(). This routines assigns
215 * minor numbers to secondary heads of multi-headed cards 169 * minor numbers to secondary heads of multi-headed cards
216 */ 170 */
217int drm_get_head(drm_device_t *dev, drm_head_t *head) 171static int drm_get_head(drm_device_t *dev, drm_head_t *head)
218{ 172{
219 drm_head_t **heads = drm_heads; 173 drm_head_t **heads = drm_heads;
220 int ret; 174 int ret;
@@ -262,6 +216,50 @@ err_g1:
262 return ret; 216 return ret;
263} 217}
264 218
219/**
220 * Register.
221 *
222 * \param pdev - PCI device structure
223 * \param ent entry from the PCI ID table with device type flags
224 * \return zero on success or a negative number on failure.
225 *
226 * Attempt to gets inter module "drm" information. If we are first
227 * then register the character device and inter module information.
228 * Try and register, if we fail to register, backout previous work.
229 */
230int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent,
231 struct drm_driver *driver)
232{
233 drm_device_t *dev;
234 int ret;
235
236 DRM_DEBUG("\n");
237
238 dev = drm_calloc(1, sizeof(*dev), DRM_MEM_STUB);
239 if (!dev)
240 return -ENOMEM;
241
242 pci_enable_device(pdev);
243
244 if ((ret = drm_fill_in_dev(dev, pdev, ent, driver))) {
245 printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
246 goto err_g1;
247 }
248 if ((ret = drm_get_head(dev, &dev->primary)))
249 goto err_g1;
250
251 /* postinit is a required function to display the signon banner */
252 /* drivers add secondary heads here if needed */
253 if ((ret = dev->driver->postinit(dev, ent->driver_data)))
254 goto err_g1;
255
256 return 0;
257
258err_g1:
259 drm_free(dev, sizeof(*dev), DRM_MEM_STUB);
260 return ret;
261}
262EXPORT_SYMBOL(drm_get_dev);
265 263
266/** 264/**
267 * Put a device minor number. 265 * Put a device minor number.
diff --git a/drivers/char/drm/drm_vm.c b/drivers/char/drm/drm_vm.c
index fc72f30f312b..621220f3f372 100644
--- a/drivers/char/drm/drm_vm.c
+++ b/drivers/char/drm/drm_vm.c
@@ -38,6 +38,8 @@
38#include <linux/efi.h> 38#include <linux/efi.h>
39#endif 39#endif
40 40
41static void drm_vm_open(struct vm_area_struct *vma);
42static void drm_vm_close(struct vm_area_struct *vma);
41 43
42/** 44/**
43 * \c nopage method for AGP virtual memory. 45 * \c nopage method for AGP virtual memory.
@@ -163,7 +165,7 @@ static __inline__ struct page *drm_do_vm_shm_nopage(struct vm_area_struct *vma,
163 * Deletes map information if we are the last 165 * Deletes map information if we are the last
164 * person to close a mapping and it's not in the global maplist. 166 * person to close a mapping and it's not in the global maplist.
165 */ 167 */
166void drm_vm_shm_close(struct vm_area_struct *vma) 168static void drm_vm_shm_close(struct vm_area_struct *vma)
167{ 169{
168 drm_file_t *priv = vma->vm_file->private_data; 170 drm_file_t *priv = vma->vm_file->private_data;
169 drm_device_t *dev = priv->head->dev; 171 drm_device_t *dev = priv->head->dev;
@@ -399,7 +401,7 @@ static struct vm_operations_struct drm_vm_sg_ops = {
399 * Create a new drm_vma_entry structure as the \p vma private data entry and 401 * Create a new drm_vma_entry structure as the \p vma private data entry and
400 * add it to drm_device::vmalist. 402 * add it to drm_device::vmalist.
401 */ 403 */
402void drm_vm_open(struct vm_area_struct *vma) 404static void drm_vm_open(struct vm_area_struct *vma)
403{ 405{
404 drm_file_t *priv = vma->vm_file->private_data; 406 drm_file_t *priv = vma->vm_file->private_data;
405 drm_device_t *dev = priv->head->dev; 407 drm_device_t *dev = priv->head->dev;
@@ -428,7 +430,7 @@ void drm_vm_open(struct vm_area_struct *vma)
428 * Search the \p vma private data entry in drm_device::vmalist, unlink it, and 430 * Search the \p vma private data entry in drm_device::vmalist, unlink it, and
429 * free it. 431 * free it.
430 */ 432 */
431void drm_vm_close(struct vm_area_struct *vma) 433static void drm_vm_close(struct vm_area_struct *vma)
432{ 434{
433 drm_file_t *priv = vma->vm_file->private_data; 435 drm_file_t *priv = vma->vm_file->private_data;
434 drm_device_t *dev = priv->head->dev; 436 drm_device_t *dev = priv->head->dev;
@@ -463,7 +465,7 @@ void drm_vm_close(struct vm_area_struct *vma)
463 * Sets the virtual memory area operations structure to vm_dma_ops, the file 465 * Sets the virtual memory area operations structure to vm_dma_ops, the file
464 * pointer, and calls vm_open(). 466 * pointer, and calls vm_open().
465 */ 467 */
466int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) 468static int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma)
467{ 469{
468 drm_file_t *priv = filp->private_data; 470 drm_file_t *priv = filp->private_data;
469 drm_device_t *dev; 471 drm_device_t *dev;
diff --git a/drivers/char/drm/i810_dma.c b/drivers/char/drm/i810_dma.c
index 24857cc6c23b..18e0b7622893 100644
--- a/drivers/char/drm/i810_dma.c
+++ b/drivers/char/drm/i810_dma.c
@@ -90,16 +90,7 @@ static int i810_freelist_put(drm_device_t *dev, drm_buf_t *buf)
90 return 0; 90 return 0;
91} 91}
92 92
93static struct file_operations i810_buffer_fops = { 93static int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
94 .open = drm_open,
95 .flush = drm_flush,
96 .release = drm_release,
97 .ioctl = drm_ioctl,
98 .mmap = i810_mmap_buffers,
99 .fasync = drm_fasync,
100};
101
102int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
103{ 94{
104 drm_file_t *priv = filp->private_data; 95 drm_file_t *priv = filp->private_data;
105 drm_device_t *dev; 96 drm_device_t *dev;
@@ -126,6 +117,15 @@ int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
126 return 0; 117 return 0;
127} 118}
128 119
120static struct file_operations i810_buffer_fops = {
121 .open = drm_open,
122 .flush = drm_flush,
123 .release = drm_release,
124 .ioctl = drm_ioctl,
125 .mmap = i810_mmap_buffers,
126 .fasync = drm_fasync,
127};
128
129static int i810_map_buffer(drm_buf_t *buf, struct file *filp) 129static int i810_map_buffer(drm_buf_t *buf, struct file *filp)
130{ 130{
131 drm_file_t *priv = filp->private_data; 131 drm_file_t *priv = filp->private_data;
@@ -1003,8 +1003,8 @@ void i810_reclaim_buffers(drm_device_t *dev, struct file *filp)
1003 } 1003 }
1004} 1004}
1005 1005
1006int i810_flush_ioctl(struct inode *inode, struct file *filp, 1006static int i810_flush_ioctl(struct inode *inode, struct file *filp,
1007 unsigned int cmd, unsigned long arg) 1007 unsigned int cmd, unsigned long arg)
1008{ 1008{
1009 drm_file_t *priv = filp->private_data; 1009 drm_file_t *priv = filp->private_data;
1010 drm_device_t *dev = priv->head->dev; 1010 drm_device_t *dev = priv->head->dev;
diff --git a/drivers/char/drm/i810_drv.h b/drivers/char/drm/i810_drv.h
index fa23ca454e57..1b40538d1725 100644
--- a/drivers/char/drm/i810_drv.h
+++ b/drivers/char/drm/i810_drv.h
@@ -115,7 +115,6 @@ typedef struct drm_i810_private {
115 115
116 /* i810_dma.c */ 116 /* i810_dma.c */
117extern void i810_reclaim_buffers(drm_device_t *dev, struct file *filp); 117extern void i810_reclaim_buffers(drm_device_t *dev, struct file *filp);
118extern int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma);
119 118
120extern int i810_driver_dma_quiescent(drm_device_t *dev); 119extern int i810_driver_dma_quiescent(drm_device_t *dev);
121extern void i810_driver_release(drm_device_t *dev, struct file *filp); 120extern void i810_driver_release(drm_device_t *dev, struct file *filp);
diff --git a/drivers/char/drm/i830_dma.c b/drivers/char/drm/i830_dma.c
index 98adccf8e434..dc7733035864 100644
--- a/drivers/char/drm/i830_dma.c
+++ b/drivers/char/drm/i830_dma.c
@@ -92,16 +92,7 @@ static int i830_freelist_put(drm_device_t *dev, drm_buf_t *buf)
92 return 0; 92 return 0;
93} 93}
94 94
95static struct file_operations i830_buffer_fops = { 95static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
96 .open = drm_open,
97 .flush = drm_flush,
98 .release = drm_release,
99 .ioctl = drm_ioctl,
100 .mmap = i830_mmap_buffers,
101 .fasync = drm_fasync,
102};
103
104int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
105{ 96{
106 drm_file_t *priv = filp->private_data; 97 drm_file_t *priv = filp->private_data;
107 drm_device_t *dev; 98 drm_device_t *dev;
@@ -128,6 +119,15 @@ int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
128 return 0; 119 return 0;
129} 120}
130 121
122static struct file_operations i830_buffer_fops = {
123 .open = drm_open,
124 .flush = drm_flush,
125 .release = drm_release,
126 .ioctl = drm_ioctl,
127 .mmap = i830_mmap_buffers,
128 .fasync = drm_fasync,
129};
130
131static int i830_map_buffer(drm_buf_t *buf, struct file *filp) 131static int i830_map_buffer(drm_buf_t *buf, struct file *filp)
132{ 132{
133 drm_file_t *priv = filp->private_data; 133 drm_file_t *priv = filp->private_data;
diff --git a/drivers/char/drm/i830_drv.c b/drivers/char/drm/i830_drv.c
index aa80ad6a5ee0..bc36be76b8b2 100644
--- a/drivers/char/drm/i830_drv.c
+++ b/drivers/char/drm/i830_drv.c
@@ -40,7 +40,7 @@
40 40
41#include "drm_pciids.h" 41#include "drm_pciids.h"
42 42
43int postinit( struct drm_device *dev, unsigned long flags ) 43static int postinit( struct drm_device *dev, unsigned long flags )
44{ 44{
45 dev->counters += 4; 45 dev->counters += 4;
46 dev->types[6] = _DRM_STAT_IRQ; 46 dev->types[6] = _DRM_STAT_IRQ;
diff --git a/drivers/char/drm/i830_drv.h b/drivers/char/drm/i830_drv.h
index d4b2d093d6ab..df7746131dea 100644
--- a/drivers/char/drm/i830_drv.h
+++ b/drivers/char/drm/i830_drv.h
@@ -123,8 +123,6 @@ typedef struct drm_i830_private {
123/* i830_dma.c */ 123/* i830_dma.c */
124extern void i830_reclaim_buffers(drm_device_t *dev, struct file *filp); 124extern void i830_reclaim_buffers(drm_device_t *dev, struct file *filp);
125 125
126extern int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma);
127
128/* i830_irq.c */ 126/* i830_irq.c */
129extern int i830_irq_emit( struct inode *inode, struct file *filp, 127extern int i830_irq_emit( struct inode *inode, struct file *filp,
130 unsigned int cmd, unsigned long arg ); 128 unsigned int cmd, unsigned long arg );
diff --git a/drivers/char/drm/i830_irq.c b/drivers/char/drm/i830_irq.c
index 6d7729ffe2dc..a5923e5d0a77 100644
--- a/drivers/char/drm/i830_irq.c
+++ b/drivers/char/drm/i830_irq.c
@@ -54,8 +54,7 @@ irqreturn_t i830_driver_irq_handler( DRM_IRQ_ARGS )
54 return IRQ_HANDLED; 54 return IRQ_HANDLED;
55} 55}
56 56
57 57static int i830_emit_irq(drm_device_t *dev)
58int i830_emit_irq(drm_device_t *dev)
59{ 58{
60 drm_i830_private_t *dev_priv = dev->dev_private; 59 drm_i830_private_t *dev_priv = dev->dev_private;
61 RING_LOCALS; 60 RING_LOCALS;
@@ -73,7 +72,7 @@ int i830_emit_irq(drm_device_t *dev)
73} 72}
74 73
75 74
76int i830_wait_irq(drm_device_t *dev, int irq_nr) 75static int i830_wait_irq(drm_device_t *dev, int irq_nr)
77{ 76{
78 drm_i830_private_t *dev_priv = 77 drm_i830_private_t *dev_priv =
79 (drm_i830_private_t *)dev->dev_private; 78 (drm_i830_private_t *)dev->dev_private;
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c
index 7300a09dbd5c..acf9e52a9507 100644
--- a/drivers/char/drm/i915_dma.c
+++ b/drivers/char/drm/i915_dma.c
@@ -1,10 +1,30 @@
1/* i915_dma.c -- DMA support for the I915 -*- linux-c -*- 1/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
2 */ 2 */
3/************************************************************************** 3/**************************************************************************
4 * 4 *
5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. 5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * All Rights Reserved. 6 * All Rights Reserved.
7 * 7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sub license, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
18 * of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
24 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 *
8 **************************************************************************/ 28 **************************************************************************/
9 29
10#include "drmP.h" 30#include "drmP.h"
@@ -12,23 +32,6 @@
12#include "i915_drm.h" 32#include "i915_drm.h"
13#include "i915_drv.h" 33#include "i915_drv.h"
14 34
15drm_ioctl_desc_t i915_ioctls[] = {
16 [DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, 1, 1},
17 [DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, 1, 0},
18 [DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, 1, 0},
19 [DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, 1, 0},
20 [DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, 1, 0},
21 [DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, 1, 0},
22 [DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, 1, 0},
23 [DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, 1, 1},
24 [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, 1, 0},
25 [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, 1, 0},
26 [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, 1, 1},
27 [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, 1, 0}
28};
29
30int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
31
32/* Really want an OS-independent resettable timer. Would like to have 35/* Really want an OS-independent resettable timer. Would like to have
33 * this loop run for (eg) 3 sec, but have the timer reset every time 36 * this loop run for (eg) 3 sec, but have the timer reset every time
34 * the head pointer changes, so that EBUSY only happens if the ring 37 * the head pointer changes, so that EBUSY only happens if the ring
@@ -75,7 +78,7 @@ void i915_kernel_lost_context(drm_device_t * dev)
75 dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY; 78 dev_priv->sarea_priv->perf_boxes |= I915_BOX_RING_EMPTY;
76} 79}
77 80
78int i915_dma_cleanup(drm_device_t * dev) 81static int i915_dma_cleanup(drm_device_t * dev)
79{ 82{
80 /* Make sure interrupts are disabled here because the uninstall ioctl 83 /* Make sure interrupts are disabled here because the uninstall ioctl
81 * may not have been called from userspace and after dev_private 84 * may not have been called from userspace and after dev_private
@@ -227,7 +230,7 @@ static int i915_resume(drm_device_t * dev)
227 return 0; 230 return 0;
228} 231}
229 232
230int i915_dma_init(DRM_IOCTL_ARGS) 233static int i915_dma_init(DRM_IOCTL_ARGS)
231{ 234{
232 DRM_DEVICE; 235 DRM_DEVICE;
233 drm_i915_private_t *dev_priv; 236 drm_i915_private_t *dev_priv;
@@ -538,7 +541,7 @@ static int i915_quiescent(drm_device_t * dev)
538 return i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__); 541 return i915_wait_ring(dev, dev_priv->ring.Size - 8, __FUNCTION__);
539} 542}
540 543
541int i915_flush_ioctl(DRM_IOCTL_ARGS) 544static int i915_flush_ioctl(DRM_IOCTL_ARGS)
542{ 545{
543 DRM_DEVICE; 546 DRM_DEVICE;
544 547
@@ -547,7 +550,7 @@ int i915_flush_ioctl(DRM_IOCTL_ARGS)
547 return i915_quiescent(dev); 550 return i915_quiescent(dev);
548} 551}
549 552
550int i915_batchbuffer(DRM_IOCTL_ARGS) 553static int i915_batchbuffer(DRM_IOCTL_ARGS)
551{ 554{
552 DRM_DEVICE; 555 DRM_DEVICE;
553 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 556 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -581,7 +584,7 @@ int i915_batchbuffer(DRM_IOCTL_ARGS)
581 return ret; 584 return ret;
582} 585}
583 586
584int i915_cmdbuffer(DRM_IOCTL_ARGS) 587static int i915_cmdbuffer(DRM_IOCTL_ARGS)
585{ 588{
586 DRM_DEVICE; 589 DRM_DEVICE;
587 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 590 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -617,18 +620,7 @@ int i915_cmdbuffer(DRM_IOCTL_ARGS)
617 return 0; 620 return 0;
618} 621}
619 622
620int i915_do_cleanup_pageflip(drm_device_t * dev) 623static int i915_flip_bufs(DRM_IOCTL_ARGS)
621{
622 drm_i915_private_t *dev_priv = dev->dev_private;
623
624 DRM_DEBUG("%s\n", __FUNCTION__);
625 if (dev_priv->current_page != 0)
626 i915_dispatch_flip(dev);
627
628 return 0;
629}
630
631int i915_flip_bufs(DRM_IOCTL_ARGS)
632{ 624{
633 DRM_DEVICE; 625 DRM_DEVICE;
634 626
@@ -639,7 +631,7 @@ int i915_flip_bufs(DRM_IOCTL_ARGS)
639 return i915_dispatch_flip(dev); 631 return i915_dispatch_flip(dev);
640} 632}
641 633
642int i915_getparam(DRM_IOCTL_ARGS) 634static int i915_getparam(DRM_IOCTL_ARGS)
643{ 635{
644 DRM_DEVICE; 636 DRM_DEVICE;
645 drm_i915_private_t *dev_priv = dev->dev_private; 637 drm_i915_private_t *dev_priv = dev->dev_private;
@@ -674,7 +666,7 @@ int i915_getparam(DRM_IOCTL_ARGS)
674 return 0; 666 return 0;
675} 667}
676 668
677int i915_setparam(DRM_IOCTL_ARGS) 669static int i915_setparam(DRM_IOCTL_ARGS)
678{ 670{
679 DRM_DEVICE; 671 DRM_DEVICE;
680 drm_i915_private_t *dev_priv = dev->dev_private; 672 drm_i915_private_t *dev_priv = dev->dev_private;
@@ -723,3 +715,19 @@ void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp)
723 } 715 }
724} 716}
725 717
718drm_ioctl_desc_t i915_ioctls[] = {
719 [DRM_IOCTL_NR(DRM_I915_INIT)] = {i915_dma_init, 1, 1},
720 [DRM_IOCTL_NR(DRM_I915_FLUSH)] = {i915_flush_ioctl, 1, 0},
721 [DRM_IOCTL_NR(DRM_I915_FLIP)] = {i915_flip_bufs, 1, 0},
722 [DRM_IOCTL_NR(DRM_I915_BATCHBUFFER)] = {i915_batchbuffer, 1, 0},
723 [DRM_IOCTL_NR(DRM_I915_IRQ_EMIT)] = {i915_irq_emit, 1, 0},
724 [DRM_IOCTL_NR(DRM_I915_IRQ_WAIT)] = {i915_irq_wait, 1, 0},
725 [DRM_IOCTL_NR(DRM_I915_GETPARAM)] = {i915_getparam, 1, 0},
726 [DRM_IOCTL_NR(DRM_I915_SETPARAM)] = {i915_setparam, 1, 1},
727 [DRM_IOCTL_NR(DRM_I915_ALLOC)] = {i915_mem_alloc, 1, 0},
728 [DRM_IOCTL_NR(DRM_I915_FREE)] = {i915_mem_free, 1, 0},
729 [DRM_IOCTL_NR(DRM_I915_INIT_HEAP)] = {i915_mem_init_heap, 1, 1},
730 [DRM_IOCTL_NR(DRM_I915_CMDBUFFER)] = {i915_cmdbuffer, 1, 0}
731};
732
733int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
diff --git a/drivers/char/drm/i915_drm.h b/drivers/char/drm/i915_drm.h
index 7e55edf45c4f..23e027d29080 100644
--- a/drivers/char/drm/i915_drm.h
+++ b/drivers/char/drm/i915_drm.h
@@ -1,3 +1,30 @@
1/**************************************************************************
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the
8 * "Software"), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject to
12 * the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 **************************************************************************/
27
1#ifndef _I915_DRM_H_ 28#ifndef _I915_DRM_H_
2#define _I915_DRM_H_ 29#define _I915_DRM_H_
3 30
diff --git a/drivers/char/drm/i915_drv.c b/drivers/char/drm/i915_drv.c
index 002b7082e21b..1f59d3fc79bc 100644
--- a/drivers/char/drm/i915_drv.c
+++ b/drivers/char/drm/i915_drv.c
@@ -1,11 +1,30 @@
1/* i915_drv.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*- 1/* i915_drv.c -- i830,i845,i855,i865,i915 driver -*- linux-c -*-
2 */ 2 */
3
4/************************************************************************** 3/**************************************************************************
5 * 4 *
6 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. 5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
7 * All Rights Reserved. 6 * All Rights Reserved.
8 * 7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sub license, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
18 * of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
24 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 *
9 **************************************************************************/ 28 **************************************************************************/
10 29
11#include "drmP.h" 30#include "drmP.h"
@@ -15,7 +34,7 @@
15 34
16#include "drm_pciids.h" 35#include "drm_pciids.h"
17 36
18int postinit( struct drm_device *dev, unsigned long flags ) 37static int postinit( struct drm_device *dev, unsigned long flags )
19{ 38{
20 dev->counters += 4; 39 dev->counters += 4;
21 dev->types[6] = _DRM_STAT_IRQ; 40 dev->types[6] = _DRM_STAT_IRQ;
@@ -78,6 +97,9 @@ static struct drm_driver driver = {
78 .mmap = drm_mmap, 97 .mmap = drm_mmap,
79 .poll = drm_poll, 98 .poll = drm_poll,
80 .fasync = drm_fasync, 99 .fasync = drm_fasync,
100#ifdef CONFIG_COMPAT
101 .compat_ioctl = i915_compat_ioctl,
102#endif
81 }, 103 },
82 .pci_driver = { 104 .pci_driver = {
83 .name = DRIVER_NAME, 105 .name = DRIVER_NAME,
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h
index f6ca92a565db..9c37d2367dd5 100644
--- a/drivers/char/drm/i915_drv.h
+++ b/drivers/char/drm/i915_drv.h
@@ -1,10 +1,30 @@
1/* i915_drv.h -- Private header for the I915 driver -*- linux-c -*- 1/* i915_drv.h -- Private header for the I915 driver -*- linux-c -*-
2 */ 2 */
3/************************************************************************** 3/**************************************************************************
4 * 4 *
5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. 5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * All Rights Reserved. 6 * All Rights Reserved.
7 * 7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sub license, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
18 * of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
24 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 *
8 **************************************************************************/ 28 **************************************************************************/
9 29
10#ifndef _I915_DRV_H_ 30#ifndef _I915_DRV_H_
@@ -79,14 +99,6 @@ typedef struct drm_i915_private {
79} drm_i915_private_t; 99} drm_i915_private_t;
80 100
81 /* i915_dma.c */ 101 /* i915_dma.c */
82extern int i915_dma_init(DRM_IOCTL_ARGS);
83extern int i915_dma_cleanup(drm_device_t * dev);
84extern int i915_flush_ioctl(DRM_IOCTL_ARGS);
85extern int i915_batchbuffer(DRM_IOCTL_ARGS);
86extern int i915_flip_bufs(DRM_IOCTL_ARGS);
87extern int i915_getparam(DRM_IOCTL_ARGS);
88extern int i915_setparam(DRM_IOCTL_ARGS);
89extern int i915_cmdbuffer(DRM_IOCTL_ARGS);
90extern void i915_kernel_lost_context(drm_device_t * dev); 102extern void i915_kernel_lost_context(drm_device_t * dev);
91extern void i915_driver_pretakedown(drm_device_t *dev); 103extern void i915_driver_pretakedown(drm_device_t *dev);
92extern void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp); 104extern void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp);
@@ -94,8 +106,6 @@ extern void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp);
94/* i915_irq.c */ 106/* i915_irq.c */
95extern int i915_irq_emit(DRM_IOCTL_ARGS); 107extern int i915_irq_emit(DRM_IOCTL_ARGS);
96extern int i915_irq_wait(DRM_IOCTL_ARGS); 108extern int i915_irq_wait(DRM_IOCTL_ARGS);
97extern int i915_wait_irq(drm_device_t * dev, int irq_nr);
98extern int i915_emit_irq(drm_device_t * dev);
99 109
100extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); 110extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
101extern void i915_driver_irq_preinstall(drm_device_t *dev); 111extern void i915_driver_irq_preinstall(drm_device_t *dev);
@@ -110,6 +120,10 @@ extern void i915_mem_takedown(struct mem_block **heap);
110extern void i915_mem_release(drm_device_t * dev, 120extern void i915_mem_release(drm_device_t * dev,
111 DRMFILE filp, struct mem_block *heap); 121 DRMFILE filp, struct mem_block *heap);
112 122
123extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
124 unsigned long arg);
125
126
113#define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, reg) 127#define I915_READ(reg) DRM_READ32(dev_priv->mmio_map, reg)
114#define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, reg, val) 128#define I915_WRITE(reg,val) DRM_WRITE32(dev_priv->mmio_map, reg, val)
115#define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, reg) 129#define I915_READ16(reg) DRM_READ16(dev_priv->mmio_map, reg)
diff --git a/drivers/char/drm/i915_ioc32.c b/drivers/char/drm/i915_ioc32.c
new file mode 100644
index 000000000000..fe009e1b3a3f
--- /dev/null
+++ b/drivers/char/drm/i915_ioc32.c
@@ -0,0 +1,221 @@
1/**
2 * \file i915_ioc32.c
3 *
4 * 32-bit ioctl compatibility routines for the i915 DRM.
5 *
6 * \author Alan Hourihane <alanh@fairlite.demon.co.uk>
7 *
8 *
9 * Copyright (C) Paul Mackerras 2005
10 * Copyright (C) Alan Hourihane 2005
11 * All Rights Reserved.
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining a
14 * copy of this software and associated documentation files (the "Software"),
15 * to deal in the Software without restriction, including without limitation
16 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 * and/or sell copies of the Software, and to permit persons to whom the
18 * Software is furnished to do so, subject to the following conditions:
19 *
20 * The above copyright notice and this permission notice (including the next
21 * paragraph) shall be included in all copies or substantial portions of the
22 * Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
28 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30 * IN THE SOFTWARE.
31 */
32#include <linux/compat.h>
33#include <linux/ioctl32.h>
34
35#include "drmP.h"
36#include "drm.h"
37#include "i915_drm.h"
38
39typedef struct _drm_i915_batchbuffer32 {
40 int start; /* agp offset */
41 int used; /* nr bytes in use */
42 int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
43 int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
44 int num_cliprects; /* mulitpass with multiple cliprects? */
45 u32 cliprects; /* pointer to userspace cliprects */
46} drm_i915_batchbuffer32_t;
47
48static int compat_i915_batchbuffer(struct file *file, unsigned int cmd,
49 unsigned long arg)
50{
51 drm_i915_batchbuffer32_t batchbuffer32;
52 drm_i915_batchbuffer_t __user *batchbuffer;
53
54 if (copy_from_user(&batchbuffer32, (void __user *)arg, sizeof(batchbuffer32)))
55 return -EFAULT;
56
57 batchbuffer = compat_alloc_user_space(sizeof(*batchbuffer));
58 if (!access_ok(VERIFY_WRITE, batchbuffer, sizeof(*batchbuffer))
59 || __put_user(batchbuffer32.start, &batchbuffer->start)
60 || __put_user(batchbuffer32.used, &batchbuffer->used)
61 || __put_user(batchbuffer32.DR1, &batchbuffer->DR1)
62 || __put_user(batchbuffer32.DR4, &batchbuffer->DR4)
63 || __put_user(batchbuffer32.num_cliprects, &batchbuffer->num_cliprects)
64 || __put_user((int __user *)(unsigned long)batchbuffer32.cliprects,
65 &batchbuffer->cliprects))
66 return -EFAULT;
67
68 return drm_ioctl(file->f_dentry->d_inode, file,
69 DRM_IOCTL_I915_BATCHBUFFER, (unsigned long) batchbuffer);
70}
71
72typedef struct _drm_i915_cmdbuffer32 {
73 u32 buf; /* pointer to userspace command buffer */
74 int sz; /* nr bytes in buf */
75 int DR1; /* hw flags for GFX_OP_DRAWRECT_INFO */
76 int DR4; /* window origin for GFX_OP_DRAWRECT_INFO */
77 int num_cliprects; /* mulitpass with multiple cliprects? */
78 u32 cliprects; /* pointer to userspace cliprects */
79} drm_i915_cmdbuffer32_t;
80
81static int compat_i915_cmdbuffer(struct file *file, unsigned int cmd,
82 unsigned long arg)
83{
84 drm_i915_cmdbuffer32_t cmdbuffer32;
85 drm_i915_cmdbuffer_t __user *cmdbuffer;
86
87 if (copy_from_user(&cmdbuffer32, (void __user *)arg, sizeof(cmdbuffer32)))
88 return -EFAULT;
89
90 cmdbuffer = compat_alloc_user_space(sizeof(*cmdbuffer));
91 if (!access_ok(VERIFY_WRITE, cmdbuffer, sizeof(*cmdbuffer))
92 || __put_user((int __user *)(unsigned long)cmdbuffer32.buf,
93 &cmdbuffer->buf)
94 || __put_user(cmdbuffer32.sz, &cmdbuffer->sz)
95 || __put_user(cmdbuffer32.DR1, &cmdbuffer->DR1)
96 || __put_user(cmdbuffer32.DR4, &cmdbuffer->DR4)
97 || __put_user(cmdbuffer32.num_cliprects, &cmdbuffer->num_cliprects)
98 || __put_user((int __user *)(unsigned long)cmdbuffer32.cliprects,
99 &cmdbuffer->cliprects))
100 return -EFAULT;
101
102 return drm_ioctl(file->f_dentry->d_inode, file,
103 DRM_IOCTL_I915_CMDBUFFER, (unsigned long) cmdbuffer);
104}
105
106typedef struct drm_i915_irq_emit32 {
107 u32 irq_seq;
108} drm_i915_irq_emit32_t;
109
110static int compat_i915_irq_emit(struct file *file, unsigned int cmd,
111 unsigned long arg)
112{
113 drm_i915_irq_emit32_t req32;
114 drm_i915_irq_emit_t __user *request;
115
116 if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
117 return -EFAULT;
118
119 request = compat_alloc_user_space(sizeof(*request));
120 if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
121 || __put_user((int __user *)(unsigned long)req32.irq_seq,
122 &request->irq_seq))
123 return -EFAULT;
124
125 return drm_ioctl(file->f_dentry->d_inode, file,
126 DRM_IOCTL_I915_IRQ_EMIT, (unsigned long) request);
127}
128typedef struct drm_i915_getparam32 {
129 int param;
130 u32 value;
131} drm_i915_getparam32_t;
132
133static int compat_i915_getparam(struct file *file, unsigned int cmd,
134 unsigned long arg)
135{
136 drm_i915_getparam32_t req32;
137 drm_i915_getparam_t __user *request;
138
139 if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
140 return -EFAULT;
141
142 request = compat_alloc_user_space(sizeof(*request));
143 if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
144 || __put_user(req32.param, &request->param)
145 || __put_user((void __user *)(unsigned long)req32.value,
146 &request->value))
147 return -EFAULT;
148
149 return drm_ioctl(file->f_dentry->d_inode, file,
150 DRM_IOCTL_I915_GETPARAM, (unsigned long) request);
151}
152
153typedef struct drm_i915_mem_alloc32 {
154 int region;
155 int alignment;
156 int size;
157 u32 region_offset; /* offset from start of fb or agp */
158} drm_i915_mem_alloc32_t;
159
160static int compat_i915_alloc(struct file *file, unsigned int cmd,
161 unsigned long arg)
162{
163 drm_i915_mem_alloc32_t req32;
164 drm_i915_mem_alloc_t __user *request;
165
166 if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
167 return -EFAULT;
168
169 request = compat_alloc_user_space(sizeof(*request));
170 if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
171 || __put_user(req32.region, &request->region)
172 || __put_user(req32.alignment, &request->alignment)
173 || __put_user(req32.size, &request->size)
174 || __put_user((void __user *)(unsigned long)req32.region_offset,
175 &request->region_offset))
176 return -EFAULT;
177
178 return drm_ioctl(file->f_dentry->d_inode, file,
179 DRM_IOCTL_I915_ALLOC, (unsigned long) request);
180}
181
182
183drm_ioctl_compat_t *i915_compat_ioctls[] = {
184 [DRM_I915_BATCHBUFFER] = compat_i915_batchbuffer,
185 [DRM_I915_CMDBUFFER] = compat_i915_cmdbuffer,
186 [DRM_I915_GETPARAM] = compat_i915_getparam,
187 [DRM_I915_IRQ_EMIT] = compat_i915_irq_emit,
188 [DRM_I915_ALLOC] = compat_i915_alloc
189};
190
191/**
192 * Called whenever a 32-bit process running under a 64-bit kernel
193 * performs an ioctl on /dev/dri/card<n>.
194 *
195 * \param filp file pointer.
196 * \param cmd command.
197 * \param arg user argument.
198 * \return zero on success or negative number on failure.
199 */
200long i915_compat_ioctl(struct file *filp, unsigned int cmd,
201 unsigned long arg)
202{
203 unsigned int nr = DRM_IOCTL_NR(cmd);
204 drm_ioctl_compat_t *fn = NULL;
205 int ret;
206
207 if (nr < DRM_COMMAND_BASE)
208 return drm_compat_ioctl(filp, cmd, arg);
209
210 if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(i915_compat_ioctls))
211 fn = i915_compat_ioctls[nr - DRM_COMMAND_BASE];
212
213 lock_kernel(); /* XXX for now */
214 if (fn != NULL)
215 ret = (*fn)(filp, cmd, arg);
216 else
217 ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
218 unlock_kernel();
219
220 return ret;
221}
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c
index b0239262a84a..4fa448ee846b 100644
--- a/drivers/char/drm/i915_irq.c
+++ b/drivers/char/drm/i915_irq.c
@@ -1,10 +1,30 @@
1/* i915_dma.c -- DMA support for the I915 -*- linux-c -*- 1/* i915_dma.c -- DMA support for the I915 -*- linux-c -*-
2 */ 2 */
3/************************************************************************** 3/**************************************************************************
4 * 4 *
5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. 5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * All Rights Reserved. 6 * All Rights Reserved.
7 * 7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sub license, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
18 * of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
24 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 *
8 **************************************************************************/ 28 **************************************************************************/
9 29
10#include "drmP.h" 30#include "drmP.h"
@@ -36,7 +56,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
36 return IRQ_HANDLED; 56 return IRQ_HANDLED;
37} 57}
38 58
39int i915_emit_irq(drm_device_t * dev) 59static int i915_emit_irq(drm_device_t * dev)
40{ 60{
41 drm_i915_private_t *dev_priv = dev->dev_private; 61 drm_i915_private_t *dev_priv = dev->dev_private;
42 u32 ret; 62 u32 ret;
@@ -56,7 +76,7 @@ int i915_emit_irq(drm_device_t * dev)
56 return ret; 76 return ret;
57} 77}
58 78
59int i915_wait_irq(drm_device_t * dev, int irq_nr) 79static int i915_wait_irq(drm_device_t * dev, int irq_nr)
60{ 80{
61 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; 81 drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
62 int ret = 0; 82 int ret = 0;
diff --git a/drivers/char/drm/i915_mem.c b/drivers/char/drm/i915_mem.c
index d54a3005946b..9b1698f521be 100644
--- a/drivers/char/drm/i915_mem.c
+++ b/drivers/char/drm/i915_mem.c
@@ -1,10 +1,30 @@
1/* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*- 1/* i915_mem.c -- Simple agp/fb memory manager for i915 -*- linux-c -*-
2 */ 2 */
3/************************************************************************** 3/**************************************************************************
4 * 4 *
5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas. 5 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
6 * All Rights Reserved. 6 * All Rights Reserved.
7 * 7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the
10 * "Software"), to deal in the Software without restriction, including
11 * without limitation the rights to use, copy, modify, merge, publish,
12 * distribute, sub license, and/or sell copies of the Software, and to
13 * permit persons to whom the Software is furnished to do so, subject to
14 * the following conditions:
15 *
16 * The above copyright notice and this permission notice (including the
17 * next paragraph) shall be included in all copies or substantial portions
18 * of the Software.
19 *
20 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
21 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
24 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 *
8 **************************************************************************/ 28 **************************************************************************/
9 29
10#include "drmP.h" 30#include "drmP.h"
diff --git a/drivers/char/drm/mga_drv.c b/drivers/char/drm/mga_drv.c
index 22dab3e9d92a..844cca9cb29d 100644
--- a/drivers/char/drm/mga_drv.c
+++ b/drivers/char/drm/mga_drv.c
@@ -101,6 +101,9 @@ static struct drm_driver driver = {
101 .mmap = drm_mmap, 101 .mmap = drm_mmap,
102 .poll = drm_poll, 102 .poll = drm_poll,
103 .fasync = drm_fasync, 103 .fasync = drm_fasync,
104#ifdef CONFIG_COMPAT
105 .compat_ioctl = mga_compat_ioctl,
106#endif
104 }, 107 },
105 .pci_driver = { 108 .pci_driver = {
106 .name = DRIVER_NAME, 109 .name = DRIVER_NAME,
diff --git a/drivers/char/drm/mga_drv.h b/drivers/char/drm/mga_drv.h
index 1d84a1eb34db..9412e2816eb7 100644
--- a/drivers/char/drm/mga_drv.h
+++ b/drivers/char/drm/mga_drv.h
@@ -137,6 +137,8 @@ extern irqreturn_t mga_driver_irq_handler( DRM_IRQ_ARGS );
137extern void mga_driver_irq_preinstall( drm_device_t *dev ); 137extern void mga_driver_irq_preinstall( drm_device_t *dev );
138extern void mga_driver_irq_postinstall( drm_device_t *dev ); 138extern void mga_driver_irq_postinstall( drm_device_t *dev );
139extern void mga_driver_irq_uninstall( drm_device_t *dev ); 139extern void mga_driver_irq_uninstall( drm_device_t *dev );
140extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
141 unsigned long arg);
140 142
141#define mga_flush_write_combine() DRM_WRITEMEMORYBARRIER() 143#define mga_flush_write_combine() DRM_WRITEMEMORYBARRIER()
142 144
diff --git a/drivers/char/drm/mga_ioc32.c b/drivers/char/drm/mga_ioc32.c
new file mode 100644
index 000000000000..bc745cfa2095
--- /dev/null
+++ b/drivers/char/drm/mga_ioc32.c
@@ -0,0 +1,167 @@
1/**
2 * \file mga_ioc32.c
3 *
4 * 32-bit ioctl compatibility routines for the MGA DRM.
5 *
6 * \author Dave Airlie <airlied@linux.ie> with code from patches by Egbert Eich
7 *
8 *
9 * Copyright (C) Paul Mackerras 2005
10 * Copyright (C) Egbert Eich 2003,2004
11 * Copyright (C) Dave Airlie 2005
12 * All Rights Reserved.
13 *
14 * Permission is hereby granted, free of charge, to any person obtaining a
15 * copy of this software and associated documentation files (the "Software"),
16 * to deal in the Software without restriction, including without limitation
17 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
18 * and/or sell copies of the Software, and to permit persons to whom the
19 * Software is furnished to do so, subject to the following conditions:
20 *
21 * The above copyright notice and this permission notice (including the next
22 * paragraph) shall be included in all copies or substantial portions of the
23 * Software.
24 *
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
26 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
27 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
28 * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
29 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
30 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
31 * IN THE SOFTWARE.
32 */
33#include <linux/compat.h>
34#include <linux/ioctl32.h>
35
36#include "drmP.h"
37#include "drm.h"
38#include "mga_drm.h"
39
40typedef struct drm32_mga_init {
41 int func;
42 u32 sarea_priv_offset;
43 int chipset;
44 int sgram;
45 unsigned int maccess;
46 unsigned int fb_cpp;
47 unsigned int front_offset, front_pitch;
48 unsigned int back_offset, back_pitch;
49 unsigned int depth_cpp;
50 unsigned int depth_offset, depth_pitch;
51 unsigned int texture_offset[MGA_NR_TEX_HEAPS];
52 unsigned int texture_size[MGA_NR_TEX_HEAPS];
53 u32 fb_offset;
54 u32 mmio_offset;
55 u32 status_offset;
56 u32 warp_offset;
57 u32 primary_offset;
58 u32 buffers_offset;
59} drm_mga_init32_t;
60
61static int compat_mga_init(struct file *file, unsigned int cmd,
62 unsigned long arg)
63{
64 drm_mga_init32_t init32;
65 drm_mga_init_t __user *init;
66 int err = 0, i;
67
68 if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
69 return -EFAULT;
70
71 init = compat_alloc_user_space(sizeof(*init));
72 if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
73 || __put_user(init32.func, &init->func)
74 || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset)
75 || __put_user(init32.chipset, &init->chipset)
76 || __put_user(init32.sgram, &init->sgram)
77 || __put_user(init32.maccess, &init->maccess)
78 || __put_user(init32.fb_cpp, &init->fb_cpp)
79 || __put_user(init32.front_offset, &init->front_offset)
80 || __put_user(init32.front_pitch, &init->front_pitch)
81 || __put_user(init32.back_offset, &init->back_offset)
82 || __put_user(init32.back_pitch, &init->back_pitch)
83 || __put_user(init32.depth_cpp, &init->depth_cpp)
84 || __put_user(init32.depth_offset, &init->depth_offset)
85 || __put_user(init32.depth_pitch, &init->depth_pitch)
86 || __put_user(init32.fb_offset, &init->fb_offset)
87 || __put_user(init32.mmio_offset, &init->mmio_offset)
88 || __put_user(init32.status_offset, &init->status_offset)
89 || __put_user(init32.warp_offset, &init->warp_offset)
90 || __put_user(init32.primary_offset, &init->primary_offset)
91 || __put_user(init32.buffers_offset, &init->buffers_offset))
92 return -EFAULT;
93
94 for (i=0; i<MGA_NR_TEX_HEAPS; i++)
95 {
96 err |= __put_user(init32.texture_offset[i], &init->texture_offset[i]);
97 err |= __put_user(init32.texture_size[i], &init->texture_size[i]);
98 }
99 if (err)
100 return -EFAULT;
101
102 return drm_ioctl(file->f_dentry->d_inode, file,
103 DRM_IOCTL_MGA_INIT, (unsigned long) init);
104}
105
106
107typedef struct drm_mga_getparam32 {
108 int param;
109 u32 value;
110} drm_mga_getparam32_t;
111
112
113static int compat_mga_getparam(struct file *file, unsigned int cmd,
114 unsigned long arg)
115{
116 drm_mga_getparam32_t getparam32;
117 drm_mga_getparam_t __user *getparam;
118
119 if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32)))
120 return -EFAULT;
121
122 getparam = compat_alloc_user_space(sizeof(*getparam));
123 if (!access_ok(VERIFY_WRITE, getparam, sizeof(*getparam))
124 || __put_user(getparam32.param, &getparam->param)
125 || __put_user((void __user *)(unsigned long)getparam32.value, &getparam->value))
126 return -EFAULT;
127
128 return drm_ioctl(file->f_dentry->d_inode, file,
129 DRM_IOCTL_MGA_GETPARAM, (unsigned long)getparam);
130}
131
132drm_ioctl_compat_t *mga_compat_ioctls[] = {
133 [DRM_MGA_INIT] = compat_mga_init,
134 [DRM_MGA_GETPARAM] = compat_mga_getparam,
135};
136
137/**
138 * Called whenever a 32-bit process running under a 64-bit kernel
139 * performs an ioctl on /dev/dri/card<n>.
140 *
141 * \param filp file pointer.
142 * \param cmd command.
143 * \param arg user argument.
144 * \return zero on success or negative number on failure.
145 */
146long mga_compat_ioctl(struct file *filp, unsigned int cmd,
147 unsigned long arg)
148{
149 unsigned int nr = DRM_IOCTL_NR(cmd);
150 drm_ioctl_compat_t *fn = NULL;
151 int ret;
152
153 if (nr < DRM_COMMAND_BASE)
154 return drm_compat_ioctl(filp, cmd, arg);
155
156 if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(mga_compat_ioctls))
157 fn = mga_compat_ioctls[nr - DRM_COMMAND_BASE];
158
159 lock_kernel(); /* XXX for now */
160 if (fn != NULL)
161 ret = (*fn)(filp, cmd, arg);
162 else
163 ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
164 unlock_kernel();
165
166 return ret;
167}
diff --git a/drivers/char/drm/r128_drv.c b/drivers/char/drm/r128_drv.c
index ced63810237b..bc446da1b210 100644
--- a/drivers/char/drm/r128_drv.c
+++ b/drivers/char/drm/r128_drv.c
@@ -96,6 +96,9 @@ static struct drm_driver driver = {
96 .mmap = drm_mmap, 96 .mmap = drm_mmap,
97 .poll = drm_poll, 97 .poll = drm_poll,
98 .fasync = drm_fasync, 98 .fasync = drm_fasync,
99#ifdef CONFIG_COMPAT
100 .compat_ioctl = r128_compat_ioctl,
101#endif
99 }, 102 },
100 .pci_driver = { 103 .pci_driver = {
101 .name = DRIVER_NAME, 104 .name = DRIVER_NAME,
diff --git a/drivers/char/drm/r128_drv.h b/drivers/char/drm/r128_drv.h
index cf1aa5df459e..0fb687c9505e 100644
--- a/drivers/char/drm/r128_drv.h
+++ b/drivers/char/drm/r128_drv.h
@@ -156,6 +156,9 @@ extern void r128_driver_irq_uninstall( drm_device_t *dev );
156extern void r128_driver_pretakedown(drm_device_t *dev); 156extern void r128_driver_pretakedown(drm_device_t *dev);
157extern void r128_driver_prerelease(drm_device_t *dev, DRMFILE filp); 157extern void r128_driver_prerelease(drm_device_t *dev, DRMFILE filp);
158 158
159extern long r128_compat_ioctl(struct file *filp, unsigned int cmd,
160 unsigned long arg);
161
159/* Register definitions, register access macros and drmAddMap constants 162/* Register definitions, register access macros and drmAddMap constants
160 * for Rage 128 kernel driver. 163 * for Rage 128 kernel driver.
161 */ 164 */
diff --git a/drivers/char/drm/r128_ioc32.c b/drivers/char/drm/r128_ioc32.c
new file mode 100644
index 000000000000..60598ef9475a
--- /dev/null
+++ b/drivers/char/drm/r128_ioc32.c
@@ -0,0 +1,219 @@
1/**
2 * \file r128_ioc32.c
3 *
4 * 32-bit ioctl compatibility routines for the R128 DRM.
5 *
6 * \author Dave Airlie <airlied@linux.ie> with code from patches by Egbert Eich
7 *
8 * Copyright (C) Paul Mackerras 2005
9 * Copyright (C) Egbert Eich 2003,2004
10 * Copyright (C) Dave Airlie 2005
11 * All Rights Reserved.
12 *
13 * Permission is hereby granted, free of charge, to any person obtaining a
14 * copy of this software and associated documentation files (the "Software"),
15 * to deal in the Software without restriction, including without limitation
16 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 * and/or sell copies of the Software, and to permit persons to whom the
18 * Software is furnished to do so, subject to the following conditions:
19 *
20 * The above copyright notice and this permission notice (including the next
21 * paragraph) shall be included in all copies or substantial portions of the
22 * Software.
23 *
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
27 * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
28 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
30 * IN THE SOFTWARE.
31 */
32#include <linux/compat.h>
33#include <linux/ioctl32.h>
34
35#include "drmP.h"
36#include "drm.h"
37#include "r128_drm.h"
38
39typedef struct drm_r128_init32 {
40 int func;
41 unsigned int sarea_priv_offset;
42 int is_pci;
43 int cce_mode;
44 int cce_secure;
45 int ring_size;
46 int usec_timeout;
47
48 unsigned int fb_bpp;
49 unsigned int front_offset, front_pitch;
50 unsigned int back_offset, back_pitch;
51 unsigned int depth_bpp;
52 unsigned int depth_offset, depth_pitch;
53 unsigned int span_offset;
54
55 unsigned int fb_offset;
56 unsigned int mmio_offset;
57 unsigned int ring_offset;
58 unsigned int ring_rptr_offset;
59 unsigned int buffers_offset;
60 unsigned int agp_textures_offset;
61} drm_r128_init32_t;
62
63static int compat_r128_init(struct file *file, unsigned int cmd,
64 unsigned long arg)
65{
66 drm_r128_init32_t init32;
67 drm_r128_init_t __user *init;
68
69 if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
70 return -EFAULT;
71
72 init = compat_alloc_user_space(sizeof(*init));
73 if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
74 || __put_user(init32.func, &init->func)
75 || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset)
76 || __put_user(init32.is_pci, &init->is_pci)
77 || __put_user(init32.cce_mode, &init->cce_mode)
78 || __put_user(init32.cce_secure, &init->cce_secure)
79 || __put_user(init32.ring_size, &init->ring_size)
80 || __put_user(init32.usec_timeout, &init->usec_timeout)
81 || __put_user(init32.fb_bpp, &init->fb_bpp)
82 || __put_user(init32.front_offset, &init->front_offset)
83 || __put_user(init32.front_pitch, &init->front_pitch)
84 || __put_user(init32.back_offset, &init->back_offset)
85 || __put_user(init32.back_pitch, &init->back_pitch)
86 || __put_user(init32.depth_bpp, &init->depth_bpp)
87 || __put_user(init32.depth_offset, &init->depth_offset)
88 || __put_user(init32.depth_pitch, &init->depth_pitch)
89 || __put_user(init32.span_offset, &init->span_offset)
90 || __put_user(init32.fb_offset, &init->fb_offset)
91 || __put_user(init32.mmio_offset, &init->mmio_offset)
92 || __put_user(init32.ring_offset, &init->ring_offset)
93 || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset)
94 || __put_user(init32.buffers_offset, &init->buffers_offset)
95 || __put_user(init32.agp_textures_offset, &init->agp_textures_offset))
96 return -EFAULT;
97
98 return drm_ioctl(file->f_dentry->d_inode, file,
99 DRM_IOCTL_R128_INIT, (unsigned long)init);
100}
101
102
103typedef struct drm_r128_depth32 {
104 int func;
105 int n;
106 u32 x;
107 u32 y;
108 u32 buffer;
109 u32 mask;
110} drm_r128_depth32_t;
111
112static int compat_r128_depth(struct file *file, unsigned int cmd,
113 unsigned long arg)
114{
115 drm_r128_depth32_t depth32;
116 drm_r128_depth_t __user *depth;
117
118 if (copy_from_user(&depth32, (void __user *)arg, sizeof(depth32)))
119 return -EFAULT;
120
121 depth = compat_alloc_user_space(sizeof(*depth));
122 if (!access_ok(VERIFY_WRITE, depth, sizeof(*depth))
123 || __put_user(depth32.func, &depth->func)
124 || __put_user(depth32.n, &depth->n)
125 || __put_user((int __user *)(unsigned long)depth32.x, &depth->x)
126 || __put_user((int __user *)(unsigned long)depth32.y, &depth->y)
127 || __put_user((unsigned int __user *)(unsigned long)depth32.buffer, &depth->buffer)
128 || __put_user((unsigned char __user *)(unsigned long)depth32.mask, &depth->mask))
129 return -EFAULT;
130
131 return drm_ioctl(file->f_dentry->d_inode, file,
132 DRM_IOCTL_R128_DEPTH, (unsigned long)depth);
133
134}
135
136typedef struct drm_r128_stipple32 {
137 u32 mask;
138} drm_r128_stipple32_t;
139
140static int compat_r128_stipple(struct file *file, unsigned int cmd,
141 unsigned long arg)
142{
143 drm_r128_stipple32_t stipple32;
144 drm_r128_stipple_t __user *stipple;
145
146 if (copy_from_user(&stipple32, (void __user *)arg, sizeof(stipple32)))
147 return -EFAULT;
148
149 stipple = compat_alloc_user_space(sizeof(*stipple));
150 if (!access_ok(VERIFY_WRITE, stipple, sizeof(*stipple))
151 || __put_user((unsigned int __user *)(unsigned long)stipple32.mask, &stipple->mask))
152 return -EFAULT;
153
154 return drm_ioctl(file->f_dentry->d_inode, file,
155 DRM_IOCTL_R128_STIPPLE, (unsigned long)stipple);
156}
157
158typedef struct drm_r128_getparam32 {
159 int param;
160 u32 value;
161} drm_r128_getparam32_t;
162
163static int compat_r128_getparam(struct file *file, unsigned int cmd,
164 unsigned long arg)
165{
166 drm_r128_getparam32_t getparam32;
167 drm_r128_getparam_t __user *getparam;
168
169 if (copy_from_user(&getparam32, (void __user *)arg, sizeof(getparam32)))
170 return -EFAULT;
171
172 getparam = compat_alloc_user_space(sizeof(*getparam));
173 if (!access_ok(VERIFY_WRITE, getparam, sizeof(*getparam))
174 || __put_user(getparam32.param, &getparam->param)
175 || __put_user((void __user *)(unsigned long)getparam32.value, &getparam->value))
176 return -EFAULT;
177
178 return drm_ioctl(file->f_dentry->d_inode, file,
179 DRM_IOCTL_R128_GETPARAM, (unsigned long)getparam);
180}
181
182drm_ioctl_compat_t *r128_compat_ioctls[] = {
183 [DRM_R128_INIT] = compat_r128_init,
184 [DRM_R128_DEPTH] = compat_r128_depth,
185 [DRM_R128_STIPPLE] = compat_r128_stipple,
186 [DRM_R128_GETPARAM] = compat_r128_getparam,
187};
188
189/**
190 * Called whenever a 32-bit process running under a 64-bit kernel
191 * performs an ioctl on /dev/dri/card<n>.
192 *
193 * \param filp file pointer.
194 * \param cmd command.
195 * \param arg user argument.
196 * \return zero on success or negative number on failure.
197 */
198long r128_compat_ioctl(struct file *filp, unsigned int cmd,
199 unsigned long arg)
200{
201 unsigned int nr = DRM_IOCTL_NR(cmd);
202 drm_ioctl_compat_t *fn = NULL;
203 int ret;
204
205 if (nr < DRM_COMMAND_BASE)
206 return drm_compat_ioctl(filp, cmd, arg);
207
208 if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(r128_compat_ioctls))
209 fn = r128_compat_ioctls[nr - DRM_COMMAND_BASE];
210
211 lock_kernel(); /* XXX for now */
212 if (fn != NULL)
213 ret = (*fn)(filp, cmd, arg);
214 else
215 ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
216 unlock_kernel();
217
218 return ret;
219}
diff --git a/drivers/char/drm/r128_state.c b/drivers/char/drm/r128_state.c
index 53af69162829..426a71c049d9 100644
--- a/drivers/char/drm/r128_state.c
+++ b/drivers/char/drm/r128_state.c
@@ -1307,7 +1307,7 @@ static int r128_do_init_pageflip( drm_device_t *dev )
1307 return 0; 1307 return 0;
1308} 1308}
1309 1309
1310int r128_do_cleanup_pageflip( drm_device_t *dev ) 1310static int r128_do_cleanup_pageflip( drm_device_t *dev )
1311{ 1311{
1312 drm_r128_private_t *dev_priv = dev->dev_private; 1312 drm_r128_private_t *dev_priv = dev->dev_private;
1313 DRM_DEBUG( "\n" ); 1313 DRM_DEBUG( "\n" );
diff --git a/drivers/char/drm/radeon_drv.c b/drivers/char/drm/radeon_drv.c
index 7b983d96e53b..18e4e5b0952f 100644
--- a/drivers/char/drm/radeon_drv.c
+++ b/drivers/char/drm/radeon_drv.c
@@ -101,6 +101,9 @@ static struct drm_driver driver = {
101 .mmap = drm_mmap, 101 .mmap = drm_mmap,
102 .poll = drm_poll, 102 .poll = drm_poll,
103 .fasync = drm_fasync, 103 .fasync = drm_fasync,
104#ifdef CONFIG_COMPAT
105 .compat_ioctl = radeon_compat_ioctl,
106#endif
104 }, 107 },
105 .pci_driver = { 108 .pci_driver = {
106 .name = DRIVER_NAME, 109 .name = DRIVER_NAME,
diff --git a/drivers/char/drm/radeon_drv.h b/drivers/char/drm/radeon_drv.h
index 5837098afae8..771aa80a5e8c 100644
--- a/drivers/char/drm/radeon_drv.h
+++ b/drivers/char/drm/radeon_drv.h
@@ -317,6 +317,9 @@ extern int radeon_preinit( struct drm_device *dev, unsigned long flags );
317extern int radeon_postinit( struct drm_device *dev, unsigned long flags ); 317extern int radeon_postinit( struct drm_device *dev, unsigned long flags );
318extern int radeon_postcleanup( struct drm_device *dev ); 318extern int radeon_postcleanup( struct drm_device *dev );
319 319
320extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
321 unsigned long arg);
322
320/* Flags for stats.boxes 323/* Flags for stats.boxes
321 */ 324 */
322#define RADEON_BOX_DMA_IDLE 0x1 325#define RADEON_BOX_DMA_IDLE 0x1
diff --git a/drivers/char/drm/radeon_ioc32.c b/drivers/char/drm/radeon_ioc32.c
new file mode 100644
index 000000000000..bfe612215fb3
--- /dev/null
+++ b/drivers/char/drm/radeon_ioc32.c
@@ -0,0 +1,395 @@
1/**
2 * \file radeon_ioc32.c
3 *
4 * 32-bit ioctl compatibility routines for the Radeon DRM.
5 *
6 * \author Paul Mackerras <paulus@samba.org>
7 *
8 * Copyright (C) Paul Mackerras 2005
9 * All Rights Reserved.
10 *
11 * Permission is hereby granted, free of charge, to any person obtaining a
12 * copy of this software and associated documentation files (the "Software"),
13 * to deal in the Software without restriction, including without limitation
14 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 * and/or sell copies of the Software, and to permit persons to whom the
16 * Software is furnished to do so, subject to the following conditions:
17 *
18 * The above copyright notice and this permission notice (including the next
19 * paragraph) shall be included in all copies or substantial portions of the
20 * Software.
21 *
22 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
25 * THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
26 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
27 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
28 * IN THE SOFTWARE.
29 */
30#include <linux/compat.h>
31#include <linux/ioctl32.h>
32
33#include "drmP.h"
34#include "drm.h"
35#include "radeon_drm.h"
36#include "radeon_drv.h"
37
38typedef struct drm_radeon_init32 {
39 int func;
40 u32 sarea_priv_offset;
41 int is_pci;
42 int cp_mode;
43 int gart_size;
44 int ring_size;
45 int usec_timeout;
46
47 unsigned int fb_bpp;
48 unsigned int front_offset, front_pitch;
49 unsigned int back_offset, back_pitch;
50 unsigned int depth_bpp;
51 unsigned int depth_offset, depth_pitch;
52
53 u32 fb_offset;
54 u32 mmio_offset;
55 u32 ring_offset;
56 u32 ring_rptr_offset;
57 u32 buffers_offset;
58 u32 gart_textures_offset;
59} drm_radeon_init32_t;
60
61static int compat_radeon_cp_init(struct file *file, unsigned int cmd,
62 unsigned long arg)
63{
64 drm_radeon_init32_t init32;
65 drm_radeon_init_t __user *init;
66
67 if (copy_from_user(&init32, (void __user *)arg, sizeof(init32)))
68 return -EFAULT;
69
70 init = compat_alloc_user_space(sizeof(*init));
71 if (!access_ok(VERIFY_WRITE, init, sizeof(*init))
72 || __put_user(init32.func, &init->func)
73 || __put_user(init32.sarea_priv_offset, &init->sarea_priv_offset)
74 || __put_user(init32.is_pci, &init->is_pci)
75 || __put_user(init32.cp_mode, &init->cp_mode)
76 || __put_user(init32.gart_size, &init->gart_size)
77 || __put_user(init32.ring_size, &init->ring_size)
78 || __put_user(init32.usec_timeout, &init->usec_timeout)
79 || __put_user(init32.fb_bpp, &init->fb_bpp)
80 || __put_user(init32.front_offset, &init->front_offset)
81 || __put_user(init32.front_pitch, &init->front_pitch)
82 || __put_user(init32.back_offset, &init->back_offset)
83 || __put_user(init32.back_pitch, &init->back_pitch)
84 || __put_user(init32.depth_bpp, &init->depth_bpp)
85 || __put_user(init32.depth_offset, &init->depth_offset)
86 || __put_user(init32.depth_pitch, &init->depth_pitch)
87 || __put_user(init32.fb_offset, &init->fb_offset)
88 || __put_user(init32.mmio_offset, &init->mmio_offset)
89 || __put_user(init32.ring_offset, &init->ring_offset)
90 || __put_user(init32.ring_rptr_offset, &init->ring_rptr_offset)
91 || __put_user(init32.buffers_offset, &init->buffers_offset)
92 || __put_user(init32.gart_textures_offset,
93 &init->gart_textures_offset))
94 return -EFAULT;
95
96 return drm_ioctl(file->f_dentry->d_inode, file,
97 DRM_IOCTL_RADEON_CP_INIT, (unsigned long) init);
98}
99
100typedef struct drm_radeon_clear32 {
101 unsigned int flags;
102 unsigned int clear_color;
103 unsigned int clear_depth;
104 unsigned int color_mask;
105 unsigned int depth_mask; /* misnamed field: should be stencil */
106 u32 depth_boxes;
107} drm_radeon_clear32_t;
108
109static int compat_radeon_cp_clear(struct file *file, unsigned int cmd,
110 unsigned long arg)
111{
112 drm_radeon_clear32_t clr32;
113 drm_radeon_clear_t __user *clr;
114
115 if (copy_from_user(&clr32, (void __user *)arg, sizeof(clr32)))
116 return -EFAULT;
117
118 clr = compat_alloc_user_space(sizeof(*clr));
119 if (!access_ok(VERIFY_WRITE, clr, sizeof(*clr))
120 || __put_user(clr32.flags, &clr->flags)
121 || __put_user(clr32.clear_color, &clr->clear_color)
122 || __put_user(clr32.clear_depth, &clr->clear_depth)
123 || __put_user(clr32.color_mask, &clr->color_mask)
124 || __put_user(clr32.depth_mask, &clr->depth_mask)
125 || __put_user((void __user *)(unsigned long)clr32.depth_boxes,
126 &clr->depth_boxes))
127 return -EFAULT;
128
129 return drm_ioctl(file->f_dentry->d_inode, file,
130 DRM_IOCTL_RADEON_CLEAR, (unsigned long) clr);
131}
132
133typedef struct drm_radeon_stipple32 {
134 u32 mask;
135} drm_radeon_stipple32_t;
136
137static int compat_radeon_cp_stipple(struct file *file, unsigned int cmd,
138 unsigned long arg)
139{
140 drm_radeon_stipple32_t __user *argp = (void __user *) arg;
141 drm_radeon_stipple_t __user *request;
142 u32 mask;
143
144 if (get_user(mask, &argp->mask))
145 return -EFAULT;
146
147 request = compat_alloc_user_space(sizeof(*request));
148 if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
149 || __put_user((unsigned int __user *)(unsigned long) mask,
150 &request->mask))
151 return -EFAULT;
152
153 return drm_ioctl(file->f_dentry->d_inode, file,
154 DRM_IOCTL_RADEON_STIPPLE, (unsigned long) request);
155}
156
157typedef struct drm_radeon_tex_image32 {
158 unsigned int x, y; /* Blit coordinates */
159 unsigned int width, height;
160 u32 data;
161} drm_radeon_tex_image32_t;
162
163typedef struct drm_radeon_texture32 {
164 unsigned int offset;
165 int pitch;
166 int format;
167 int width; /* Texture image coordinates */
168 int height;
169 u32 image;
170} drm_radeon_texture32_t;
171
172static int compat_radeon_cp_texture(struct file *file, unsigned int cmd,
173 unsigned long arg)
174{
175 drm_radeon_texture32_t req32;
176 drm_radeon_texture_t __user *request;
177 drm_radeon_tex_image32_t img32;
178 drm_radeon_tex_image_t __user *image;
179
180 if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
181 return -EFAULT;
182 if (req32.image == 0)
183 return -EINVAL;
184 if (copy_from_user(&img32, (void __user *)(unsigned long)req32.image,
185 sizeof(img32)))
186 return -EFAULT;
187
188 request = compat_alloc_user_space(sizeof(*request) + sizeof(*image));
189 if (!access_ok(VERIFY_WRITE, request,
190 sizeof(*request) + sizeof(*image)))
191 return -EFAULT;
192 image = (drm_radeon_tex_image_t __user *) (request + 1);
193
194 if (__put_user(req32.offset, &request->offset)
195 || __put_user(req32.pitch, &request->pitch)
196 || __put_user(req32.format, &request->format)
197 || __put_user(req32.width, &request->width)
198 || __put_user(req32.height, &request->height)
199 || __put_user(image, &request->image)
200 || __put_user(img32.x, &image->x)
201 || __put_user(img32.y, &image->y)
202 || __put_user(img32.width, &image->width)
203 || __put_user(img32.height, &image->height)
204 || __put_user((const void __user *)(unsigned long)img32.data,
205 &image->data))
206 return -EFAULT;
207
208 return drm_ioctl(file->f_dentry->d_inode, file,
209 DRM_IOCTL_RADEON_TEXTURE, (unsigned long) request);
210}
211
212typedef struct drm_radeon_vertex2_32 {
213 int idx; /* Index of vertex buffer */
214 int discard; /* Client finished with buffer? */
215 int nr_states;
216 u32 state;
217 int nr_prims;
218 u32 prim;
219} drm_radeon_vertex2_32_t;
220
221static int compat_radeon_cp_vertex2(struct file *file, unsigned int cmd,
222 unsigned long arg)
223{
224 drm_radeon_vertex2_32_t req32;
225 drm_radeon_vertex2_t __user *request;
226
227 if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
228 return -EFAULT;
229
230 request = compat_alloc_user_space(sizeof(*request));
231 if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
232 || __put_user(req32.idx, &request->idx)
233 || __put_user(req32.discard, &request->discard)
234 || __put_user(req32.nr_states, &request->nr_states)
235 || __put_user((void __user *)(unsigned long)req32.state,
236 &request->state)
237 || __put_user(req32.nr_prims, &request->nr_prims)
238 || __put_user((void __user *)(unsigned long)req32.prim,
239 &request->prim))
240 return -EFAULT;
241
242 return drm_ioctl(file->f_dentry->d_inode, file,
243 DRM_IOCTL_RADEON_VERTEX2, (unsigned long) request);
244}
245
246typedef struct drm_radeon_cmd_buffer32 {
247 int bufsz;
248 u32 buf;
249 int nbox;
250 u32 boxes;
251} drm_radeon_cmd_buffer32_t;
252
253static int compat_radeon_cp_cmdbuf(struct file *file, unsigned int cmd,
254 unsigned long arg)
255{
256 drm_radeon_cmd_buffer32_t req32;
257 drm_radeon_cmd_buffer_t __user *request;
258
259 if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
260 return -EFAULT;
261
262 request = compat_alloc_user_space(sizeof(*request));
263 if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
264 || __put_user(req32.bufsz, &request->bufsz)
265 || __put_user((void __user *)(unsigned long)req32.buf,
266 &request->buf)
267 || __put_user(req32.nbox, &request->nbox)
268 || __put_user((void __user *)(unsigned long)req32.boxes,
269 &request->boxes))
270 return -EFAULT;
271
272 return drm_ioctl(file->f_dentry->d_inode, file,
273 DRM_IOCTL_RADEON_CMDBUF, (unsigned long) request);
274}
275
276typedef struct drm_radeon_getparam32 {
277 int param;
278 u32 value;
279} drm_radeon_getparam32_t;
280
281static int compat_radeon_cp_getparam(struct file *file, unsigned int cmd,
282 unsigned long arg)
283{
284 drm_radeon_getparam32_t req32;
285 drm_radeon_getparam_t __user *request;
286
287 if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
288 return -EFAULT;
289
290 request = compat_alloc_user_space(sizeof(*request));
291 if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
292 || __put_user(req32.param, &request->param)
293 || __put_user((void __user *)(unsigned long)req32.value,
294 &request->value))
295 return -EFAULT;
296
297 return drm_ioctl(file->f_dentry->d_inode, file,
298 DRM_IOCTL_RADEON_GETPARAM, (unsigned long) request);
299}
300
301typedef struct drm_radeon_mem_alloc32 {
302 int region;
303 int alignment;
304 int size;
305 u32 region_offset; /* offset from start of fb or GART */
306} drm_radeon_mem_alloc32_t;
307
308static int compat_radeon_mem_alloc(struct file *file, unsigned int cmd,
309 unsigned long arg)
310{
311 drm_radeon_mem_alloc32_t req32;
312 drm_radeon_mem_alloc_t __user *request;
313
314 if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
315 return -EFAULT;
316
317 request = compat_alloc_user_space(sizeof(*request));
318 if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
319 || __put_user(req32.region, &request->region)
320 || __put_user(req32.alignment, &request->alignment)
321 || __put_user(req32.size, &request->size)
322 || __put_user((int __user *)(unsigned long)req32.region_offset,
323 &request->region_offset))
324 return -EFAULT;
325
326 return drm_ioctl(file->f_dentry->d_inode, file,
327 DRM_IOCTL_RADEON_ALLOC, (unsigned long) request);
328}
329
330typedef struct drm_radeon_irq_emit32 {
331 u32 irq_seq;
332} drm_radeon_irq_emit32_t;
333
334static int compat_radeon_irq_emit(struct file *file, unsigned int cmd,
335 unsigned long arg)
336{
337 drm_radeon_irq_emit32_t req32;
338 drm_radeon_irq_emit_t __user *request;
339
340 if (copy_from_user(&req32, (void __user *) arg, sizeof(req32)))
341 return -EFAULT;
342
343 request = compat_alloc_user_space(sizeof(*request));
344 if (!access_ok(VERIFY_WRITE, request, sizeof(*request))
345 || __put_user((int __user *)(unsigned long)req32.irq_seq,
346 &request->irq_seq))
347 return -EFAULT;
348
349 return drm_ioctl(file->f_dentry->d_inode, file,
350 DRM_IOCTL_RADEON_IRQ_EMIT, (unsigned long) request);
351}
352
353drm_ioctl_compat_t *radeon_compat_ioctls[] = {
354 [DRM_RADEON_CP_INIT] = compat_radeon_cp_init,
355 [DRM_RADEON_CLEAR] = compat_radeon_cp_clear,
356 [DRM_RADEON_STIPPLE] = compat_radeon_cp_stipple,
357 [DRM_RADEON_TEXTURE] = compat_radeon_cp_texture,
358 [DRM_RADEON_VERTEX2] = compat_radeon_cp_vertex2,
359 [DRM_RADEON_CMDBUF] = compat_radeon_cp_cmdbuf,
360 [DRM_RADEON_GETPARAM] = compat_radeon_cp_getparam,
361 [DRM_RADEON_ALLOC] = compat_radeon_mem_alloc,
362 [DRM_RADEON_IRQ_EMIT] = compat_radeon_irq_emit,
363};
364
365/**
366 * Called whenever a 32-bit process running under a 64-bit kernel
367 * performs an ioctl on /dev/dri/card<n>.
368 *
369 * \param filp file pointer.
370 * \param cmd command.
371 * \param arg user argument.
372 * \return zero on success or negative number on failure.
373 */
374long radeon_compat_ioctl(struct file *filp, unsigned int cmd,
375 unsigned long arg)
376{
377 unsigned int nr = DRM_IOCTL_NR(cmd);
378 drm_ioctl_compat_t *fn = NULL;
379 int ret;
380
381 if (nr < DRM_COMMAND_BASE)
382 return drm_compat_ioctl(filp, cmd, arg);
383
384 if (nr < DRM_COMMAND_BASE + DRM_ARRAY_SIZE(radeon_compat_ioctls))
385 fn = radeon_compat_ioctls[nr - DRM_COMMAND_BASE];
386
387 lock_kernel(); /* XXX for now */
388 if (fn != NULL)
389 ret = (*fn)(filp, cmd, arg);
390 else
391 ret = drm_ioctl(filp->f_dentry->d_inode, filp, cmd, arg);
392 unlock_kernel();
393
394 return ret;
395}
diff --git a/drivers/char/drm/radeon_irq.c b/drivers/char/drm/radeon_irq.c
index 5b18bee6492e..40474a65f56d 100644
--- a/drivers/char/drm/radeon_irq.c
+++ b/drivers/char/drm/radeon_irq.c
@@ -35,6 +35,14 @@
35#include "radeon_drm.h" 35#include "radeon_drm.h"
36#include "radeon_drv.h" 36#include "radeon_drv.h"
37 37
38static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 mask)
39{
40 u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
41 if (irqs)
42 RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
43 return irqs;
44}
45
38/* Interrupts - Used for device synchronization and flushing in the 46/* Interrupts - Used for device synchronization and flushing in the
39 * following circumstances: 47 * following circumstances:
40 * 48 *
@@ -63,8 +71,8 @@ irqreturn_t radeon_driver_irq_handler( DRM_IRQ_ARGS )
63 /* Only consider the bits we're interested in - others could be used 71 /* Only consider the bits we're interested in - others could be used
64 * outside the DRM 72 * outside the DRM
65 */ 73 */
66 stat = RADEON_READ(RADEON_GEN_INT_STATUS) 74 stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
67 & (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT); 75 RADEON_CRTC_VBLANK_STAT));
68 if (!stat) 76 if (!stat)
69 return IRQ_NONE; 77 return IRQ_NONE;
70 78
@@ -80,19 +88,9 @@ irqreturn_t radeon_driver_irq_handler( DRM_IRQ_ARGS )
80 drm_vbl_send_signals( dev ); 88 drm_vbl_send_signals( dev );
81 } 89 }
82 90
83 /* Acknowledge interrupts we handle */
84 RADEON_WRITE(RADEON_GEN_INT_STATUS, stat);
85 return IRQ_HANDLED; 91 return IRQ_HANDLED;
86} 92}
87 93
88static __inline__ void radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv)
89{
90 u32 tmp = RADEON_READ( RADEON_GEN_INT_STATUS )
91 & (RADEON_SW_INT_TEST_ACK | RADEON_CRTC_VBLANK_STAT);
92 if (tmp)
93 RADEON_WRITE( RADEON_GEN_INT_STATUS, tmp );
94}
95
96static int radeon_emit_irq(drm_device_t *dev) 94static int radeon_emit_irq(drm_device_t *dev)
97{ 95{
98 drm_radeon_private_t *dev_priv = dev->dev_private; 96 drm_radeon_private_t *dev_priv = dev->dev_private;
@@ -123,11 +121,6 @@ static int radeon_wait_irq(drm_device_t *dev, int swi_nr)
123 121
124 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; 122 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
125 123
126 /* This is a hack to work around mysterious freezes on certain
127 * systems:
128 */
129 radeon_acknowledge_irqs( dev_priv );
130
131 DRM_WAIT_ON( ret, dev_priv->swi_queue, 3 * DRM_HZ, 124 DRM_WAIT_ON( ret, dev_priv->swi_queue, 3 * DRM_HZ,
132 RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr ); 125 RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr );
133 126
@@ -146,7 +139,7 @@ int radeon_driver_vblank_wait(drm_device_t *dev, unsigned int *sequence)
146 return DRM_ERR(EINVAL); 139 return DRM_ERR(EINVAL);
147 } 140 }
148 141
149 radeon_acknowledge_irqs( dev_priv ); 142 radeon_acknowledge_irqs(dev_priv, RADEON_CRTC_VBLANK_STAT);
150 143
151 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; 144 dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
152 145
@@ -224,7 +217,8 @@ void radeon_driver_irq_preinstall( drm_device_t *dev ) {
224 RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 ); 217 RADEON_WRITE( RADEON_GEN_INT_CNTL, 0 );
225 218
226 /* Clear bits if they're already high */ 219 /* Clear bits if they're already high */
227 radeon_acknowledge_irqs( dev_priv ); 220 radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
221 RADEON_CRTC_VBLANK_STAT));
228} 222}
229 223
230void radeon_driver_irq_postinstall( drm_device_t *dev ) { 224void radeon_driver_irq_postinstall( drm_device_t *dev ) {
diff --git a/drivers/char/drm/via_3d_reg.h b/drivers/char/drm/via_3d_reg.h
new file mode 100644
index 000000000000..cf61bb514db1
--- /dev/null
+++ b/drivers/char/drm/via_3d_reg.h
@@ -0,0 +1,1651 @@
1/*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25#ifndef VIA_3D_REG_H
26#define VIA_3D_REG_H
27#define HC_REG_BASE 0x0400
28
29#define HC_REG_TRANS_SPACE 0x0040
30
31#define HC_ParaN_MASK 0xffffffff
32#define HC_Para_MASK 0x00ffffff
33#define HC_SubA_MASK 0xff000000
34#define HC_SubA_SHIFT 24
35/* Transmission Setting
36 */
37#define HC_REG_TRANS_SET 0x003c
38#define HC_ParaSubType_MASK 0xff000000
39#define HC_ParaType_MASK 0x00ff0000
40#define HC_ParaOS_MASK 0x0000ff00
41#define HC_ParaAdr_MASK 0x000000ff
42#define HC_ParaSubType_SHIFT 24
43#define HC_ParaType_SHIFT 16
44#define HC_ParaOS_SHIFT 8
45#define HC_ParaAdr_SHIFT 0
46
47#define HC_ParaType_CmdVdata 0x0000
48#define HC_ParaType_NotTex 0x0001
49#define HC_ParaType_Tex 0x0002
50#define HC_ParaType_Palette 0x0003
51#define HC_ParaType_PreCR 0x0010
52#define HC_ParaType_Auto 0x00fe
53
54/* Transmission Space
55 */
56#define HC_REG_Hpara0 0x0040
57#define HC_REG_HpataAF 0x02fc
58
59/* Read
60 */
61#define HC_REG_HREngSt 0x0000
62#define HC_REG_HRFIFOempty 0x0004
63#define HC_REG_HRFIFOfull 0x0008
64#define HC_REG_HRErr 0x000c
65#define HC_REG_FIFOstatus 0x0010
66/* HC_REG_HREngSt 0x0000
67 */
68#define HC_HDASZC_MASK 0x00010000
69#define HC_HSGEMI_MASK 0x0000f000
70#define HC_HLGEMISt_MASK 0x00000f00
71#define HC_HCRSt_MASK 0x00000080
72#define HC_HSE0St_MASK 0x00000040
73#define HC_HSE1St_MASK 0x00000020
74#define HC_HPESt_MASK 0x00000010
75#define HC_HXESt_MASK 0x00000008
76#define HC_HBESt_MASK 0x00000004
77#define HC_HE2St_MASK 0x00000002
78#define HC_HE3St_MASK 0x00000001
79/* HC_REG_HRFIFOempty 0x0004
80 */
81#define HC_HRZDempty_MASK 0x00000010
82#define HC_HRTXAempty_MASK 0x00000008
83#define HC_HRTXDempty_MASK 0x00000004
84#define HC_HWZDempty_MASK 0x00000002
85#define HC_HWCDempty_MASK 0x00000001
86/* HC_REG_HRFIFOfull 0x0008
87 */
88#define HC_HRZDfull_MASK 0x00000010
89#define HC_HRTXAfull_MASK 0x00000008
90#define HC_HRTXDfull_MASK 0x00000004
91#define HC_HWZDfull_MASK 0x00000002
92#define HC_HWCDfull_MASK 0x00000001
93/* HC_REG_HRErr 0x000c
94 */
95#define HC_HAGPCMErr_MASK 0x80000000
96#define HC_HAGPCMErrC_MASK 0x70000000
97/* HC_REG_FIFOstatus 0x0010
98 */
99#define HC_HRFIFOATall_MASK 0x80000000
100#define HC_HRFIFOATbusy_MASK 0x40000000
101#define HC_HRATFGMDo_MASK 0x00000100
102#define HC_HRATFGMDi_MASK 0x00000080
103#define HC_HRATFRZD_MASK 0x00000040
104#define HC_HRATFRTXA_MASK 0x00000020
105#define HC_HRATFRTXD_MASK 0x00000010
106#define HC_HRATFWZD_MASK 0x00000008
107#define HC_HRATFWCD_MASK 0x00000004
108#define HC_HRATTXTAG_MASK 0x00000002
109#define HC_HRATTXCH_MASK 0x00000001
110
111/* AGP Command Setting
112 */
113#define HC_SubA_HAGPBstL 0x0060
114#define HC_SubA_HAGPBendL 0x0061
115#define HC_SubA_HAGPCMNT 0x0062
116#define HC_SubA_HAGPBpL 0x0063
117#define HC_SubA_HAGPBpH 0x0064
118/* HC_SubA_HAGPCMNT 0x0062
119 */
120#define HC_HAGPCMNT_MASK 0x00800000
121#define HC_HCmdErrClr_MASK 0x00400000
122#define HC_HAGPBendH_MASK 0x0000ff00
123#define HC_HAGPBstH_MASK 0x000000ff
124#define HC_HAGPBendH_SHIFT 8
125#define HC_HAGPBstH_SHIFT 0
126/* HC_SubA_HAGPBpL 0x0063
127 */
128#define HC_HAGPBpL_MASK 0x00fffffc
129#define HC_HAGPBpID_MASK 0x00000003
130#define HC_HAGPBpID_PAUSE 0x00000000
131#define HC_HAGPBpID_JUMP 0x00000001
132#define HC_HAGPBpID_STOP 0x00000002
133/* HC_SubA_HAGPBpH 0x0064
134 */
135#define HC_HAGPBpH_MASK 0x00ffffff
136
137/* Miscellaneous Settings
138 */
139#define HC_SubA_HClipTB 0x0070
140#define HC_SubA_HClipLR 0x0071
141#define HC_SubA_HFPClipTL 0x0072
142#define HC_SubA_HFPClipBL 0x0073
143#define HC_SubA_HFPClipLL 0x0074
144#define HC_SubA_HFPClipRL 0x0075
145#define HC_SubA_HFPClipTBH 0x0076
146#define HC_SubA_HFPClipLRH 0x0077
147#define HC_SubA_HLP 0x0078
148#define HC_SubA_HLPRF 0x0079
149#define HC_SubA_HSolidCL 0x007a
150#define HC_SubA_HPixGC 0x007b
151#define HC_SubA_HSPXYOS 0x007c
152#define HC_SubA_HVertexCNT 0x007d
153
154#define HC_HClipT_MASK 0x00fff000
155#define HC_HClipT_SHIFT 12
156#define HC_HClipB_MASK 0x00000fff
157#define HC_HClipB_SHIFT 0
158#define HC_HClipL_MASK 0x00fff000
159#define HC_HClipL_SHIFT 12
160#define HC_HClipR_MASK 0x00000fff
161#define HC_HClipR_SHIFT 0
162#define HC_HFPClipBH_MASK 0x0000ff00
163#define HC_HFPClipBH_SHIFT 8
164#define HC_HFPClipTH_MASK 0x000000ff
165#define HC_HFPClipTH_SHIFT 0
166#define HC_HFPClipRH_MASK 0x0000ff00
167#define HC_HFPClipRH_SHIFT 8
168#define HC_HFPClipLH_MASK 0x000000ff
169#define HC_HFPClipLH_SHIFT 0
170#define HC_HSolidCH_MASK 0x000000ff
171#define HC_HPixGC_MASK 0x00800000
172#define HC_HSPXOS_MASK 0x00fff000
173#define HC_HSPXOS_SHIFT 12
174#define HC_HSPYOS_MASK 0x00000fff
175
176/* Command
177 * Command A
178 */
179#define HC_HCmdHeader_MASK 0xfe000000 /*0xffe00000 */
180#define HC_HE3Fire_MASK 0x00100000
181#define HC_HPMType_MASK 0x000f0000
182#define HC_HEFlag_MASK 0x0000e000
183#define HC_HShading_MASK 0x00001c00
184#define HC_HPMValidN_MASK 0x00000200
185#define HC_HPLEND_MASK 0x00000100
186#define HC_HVCycle_MASK 0x000000ff
187#define HC_HVCycle_Style_MASK 0x000000c0
188#define HC_HVCycle_ChgA_MASK 0x00000030
189#define HC_HVCycle_ChgB_MASK 0x0000000c
190#define HC_HVCycle_ChgC_MASK 0x00000003
191#define HC_HPMType_Point 0x00000000
192#define HC_HPMType_Line 0x00010000
193#define HC_HPMType_Tri 0x00020000
194#define HC_HPMType_TriWF 0x00040000
195#define HC_HEFlag_NoAA 0x00000000
196#define HC_HEFlag_ab 0x00008000
197#define HC_HEFlag_bc 0x00004000
198#define HC_HEFlag_ca 0x00002000
199#define HC_HShading_Solid 0x00000000
200#define HC_HShading_FlatA 0x00000400
201#define HC_HShading_FlatB 0x00000800
202#define HC_HShading_FlatC 0x00000c00
203#define HC_HShading_Gouraud 0x00001000
204#define HC_HVCycle_Full 0x00000000
205#define HC_HVCycle_AFP 0x00000040
206#define HC_HVCycle_One 0x000000c0
207#define HC_HVCycle_NewA 0x00000000
208#define HC_HVCycle_AA 0x00000010
209#define HC_HVCycle_AB 0x00000020
210#define HC_HVCycle_AC 0x00000030
211#define HC_HVCycle_NewB 0x00000000
212#define HC_HVCycle_BA 0x00000004
213#define HC_HVCycle_BB 0x00000008
214#define HC_HVCycle_BC 0x0000000c
215#define HC_HVCycle_NewC 0x00000000
216#define HC_HVCycle_CA 0x00000001
217#define HC_HVCycle_CB 0x00000002
218#define HC_HVCycle_CC 0x00000003
219
220/* Command B
221 */
222#define HC_HLPrst_MASK 0x00010000
223#define HC_HLLastP_MASK 0x00008000
224#define HC_HVPMSK_MASK 0x00007f80
225#define HC_HBFace_MASK 0x00000040
226#define HC_H2nd1VT_MASK 0x0000003f
227#define HC_HVPMSK_X 0x00004000
228#define HC_HVPMSK_Y 0x00002000
229#define HC_HVPMSK_Z 0x00001000
230#define HC_HVPMSK_W 0x00000800
231#define HC_HVPMSK_Cd 0x00000400
232#define HC_HVPMSK_Cs 0x00000200
233#define HC_HVPMSK_S 0x00000100
234#define HC_HVPMSK_T 0x00000080
235
236/* Enable Setting
237 */
238#define HC_SubA_HEnable 0x0000
239#define HC_HenTXEnvMap_MASK 0x00200000
240#define HC_HenVertexCNT_MASK 0x00100000
241#define HC_HenCPUDAZ_MASK 0x00080000
242#define HC_HenDASZWC_MASK 0x00040000
243#define HC_HenFBCull_MASK 0x00020000
244#define HC_HenCW_MASK 0x00010000
245#define HC_HenAA_MASK 0x00008000
246#define HC_HenST_MASK 0x00004000
247#define HC_HenZT_MASK 0x00002000
248#define HC_HenZW_MASK 0x00001000
249#define HC_HenAT_MASK 0x00000800
250#define HC_HenAW_MASK 0x00000400
251#define HC_HenSP_MASK 0x00000200
252#define HC_HenLP_MASK 0x00000100
253#define HC_HenTXCH_MASK 0x00000080
254#define HC_HenTXMP_MASK 0x00000040
255#define HC_HenTXPP_MASK 0x00000020
256#define HC_HenTXTR_MASK 0x00000010
257#define HC_HenCS_MASK 0x00000008
258#define HC_HenFOG_MASK 0x00000004
259#define HC_HenABL_MASK 0x00000002
260#define HC_HenDT_MASK 0x00000001
261
262/* Z Setting
263 */
264#define HC_SubA_HZWBBasL 0x0010
265#define HC_SubA_HZWBBasH 0x0011
266#define HC_SubA_HZWBType 0x0012
267#define HC_SubA_HZBiasL 0x0013
268#define HC_SubA_HZWBend 0x0014
269#define HC_SubA_HZWTMD 0x0015
270#define HC_SubA_HZWCDL 0x0016
271#define HC_SubA_HZWCTAGnum 0x0017
272#define HC_SubA_HZCYNum 0x0018
273#define HC_SubA_HZWCFire 0x0019
274/* HC_SubA_HZWBType
275 */
276#define HC_HZWBType_MASK 0x00800000
277#define HC_HZBiasedWB_MASK 0x00400000
278#define HC_HZONEasFF_MASK 0x00200000
279#define HC_HZOONEasFF_MASK 0x00100000
280#define HC_HZWBFM_MASK 0x00030000
281#define HC_HZWBLoc_MASK 0x0000c000
282#define HC_HZWBPit_MASK 0x00003fff
283#define HC_HZWBFM_16 0x00000000
284#define HC_HZWBFM_32 0x00020000
285#define HC_HZWBFM_24 0x00030000
286#define HC_HZWBLoc_Local 0x00000000
287#define HC_HZWBLoc_SyS 0x00004000
288/* HC_SubA_HZWBend
289 */
290#define HC_HZWBend_MASK 0x00ffe000
291#define HC_HZBiasH_MASK 0x000000ff
292#define HC_HZWBend_SHIFT 10
293/* HC_SubA_HZWTMD
294 */
295#define HC_HZWTMD_MASK 0x00070000
296#define HC_HEBEBias_MASK 0x00007f00
297#define HC_HZNF_MASK 0x000000ff
298#define HC_HZWTMD_NeverPass 0x00000000
299#define HC_HZWTMD_LT 0x00010000
300#define HC_HZWTMD_EQ 0x00020000
301#define HC_HZWTMD_LE 0x00030000
302#define HC_HZWTMD_GT 0x00040000
303#define HC_HZWTMD_NE 0x00050000
304#define HC_HZWTMD_GE 0x00060000
305#define HC_HZWTMD_AllPass 0x00070000
306#define HC_HEBEBias_SHIFT 8
307/* HC_SubA_HZWCDL 0x0016
308 */
309#define HC_HZWCDL_MASK 0x00ffffff
310/* HC_SubA_HZWCTAGnum 0x0017
311 */
312#define HC_HZWCTAGnum_MASK 0x00ff0000
313#define HC_HZWCTAGnum_SHIFT 16
314#define HC_HZWCDH_MASK 0x000000ff
315#define HC_HZWCDH_SHIFT 0
316/* HC_SubA_HZCYNum 0x0018
317 */
318#define HC_HZCYNum_MASK 0x00030000
319#define HC_HZCYNum_SHIFT 16
320#define HC_HZWCQWnum_MASK 0x00003fff
321#define HC_HZWCQWnum_SHIFT 0
322/* HC_SubA_HZWCFire 0x0019
323 */
324#define HC_ZWCFire_MASK 0x00010000
325#define HC_HZWCQWnumLast_MASK 0x00003fff
326#define HC_HZWCQWnumLast_SHIFT 0
327
328/* Stencil Setting
329 */
330#define HC_SubA_HSTREF 0x0023
331#define HC_SubA_HSTMD 0x0024
332/* HC_SubA_HSBFM
333 */
334#define HC_HSBFM_MASK 0x00030000
335#define HC_HSBLoc_MASK 0x0000c000
336#define HC_HSBPit_MASK 0x00003fff
337/* HC_SubA_HSTREF
338 */
339#define HC_HSTREF_MASK 0x00ff0000
340#define HC_HSTOPMSK_MASK 0x0000ff00
341#define HC_HSTBMSK_MASK 0x000000ff
342#define HC_HSTREF_SHIFT 16
343#define HC_HSTOPMSK_SHIFT 8
344/* HC_SubA_HSTMD
345 */
346#define HC_HSTMD_MASK 0x00070000
347#define HC_HSTOPSF_MASK 0x000001c0
348#define HC_HSTOPSPZF_MASK 0x00000038
349#define HC_HSTOPSPZP_MASK 0x00000007
350#define HC_HSTMD_NeverPass 0x00000000
351#define HC_HSTMD_LT 0x00010000
352#define HC_HSTMD_EQ 0x00020000
353#define HC_HSTMD_LE 0x00030000
354#define HC_HSTMD_GT 0x00040000
355#define HC_HSTMD_NE 0x00050000
356#define HC_HSTMD_GE 0x00060000
357#define HC_HSTMD_AllPass 0x00070000
358#define HC_HSTOPSF_KEEP 0x00000000
359#define HC_HSTOPSF_ZERO 0x00000040
360#define HC_HSTOPSF_REPLACE 0x00000080
361#define HC_HSTOPSF_INCRSAT 0x000000c0
362#define HC_HSTOPSF_DECRSAT 0x00000100
363#define HC_HSTOPSF_INVERT 0x00000140
364#define HC_HSTOPSF_INCR 0x00000180
365#define HC_HSTOPSF_DECR 0x000001c0
366#define HC_HSTOPSPZF_KEEP 0x00000000
367#define HC_HSTOPSPZF_ZERO 0x00000008
368#define HC_HSTOPSPZF_REPLACE 0x00000010
369#define HC_HSTOPSPZF_INCRSAT 0x00000018
370#define HC_HSTOPSPZF_DECRSAT 0x00000020
371#define HC_HSTOPSPZF_INVERT 0x00000028
372#define HC_HSTOPSPZF_INCR 0x00000030
373#define HC_HSTOPSPZF_DECR 0x00000038
374#define HC_HSTOPSPZP_KEEP 0x00000000
375#define HC_HSTOPSPZP_ZERO 0x00000001
376#define HC_HSTOPSPZP_REPLACE 0x00000002
377#define HC_HSTOPSPZP_INCRSAT 0x00000003
378#define HC_HSTOPSPZP_DECRSAT 0x00000004
379#define HC_HSTOPSPZP_INVERT 0x00000005
380#define HC_HSTOPSPZP_INCR 0x00000006
381#define HC_HSTOPSPZP_DECR 0x00000007
382
383/* Alpha Setting
384 */
385#define HC_SubA_HABBasL 0x0030
386#define HC_SubA_HABBasH 0x0031
387#define HC_SubA_HABFM 0x0032
388#define HC_SubA_HATMD 0x0033
389#define HC_SubA_HABLCsat 0x0034
390#define HC_SubA_HABLCop 0x0035
391#define HC_SubA_HABLAsat 0x0036
392#define HC_SubA_HABLAop 0x0037
393#define HC_SubA_HABLRCa 0x0038
394#define HC_SubA_HABLRFCa 0x0039
395#define HC_SubA_HABLRCbias 0x003a
396#define HC_SubA_HABLRCb 0x003b
397#define HC_SubA_HABLRFCb 0x003c
398#define HC_SubA_HABLRAa 0x003d
399#define HC_SubA_HABLRAb 0x003e
400/* HC_SubA_HABFM
401 */
402#define HC_HABFM_MASK 0x00030000
403#define HC_HABLoc_MASK 0x0000c000
404#define HC_HABPit_MASK 0x000007ff
405/* HC_SubA_HATMD
406 */
407#define HC_HATMD_MASK 0x00000700
408#define HC_HATREF_MASK 0x000000ff
409#define HC_HATMD_NeverPass 0x00000000
410#define HC_HATMD_LT 0x00000100
411#define HC_HATMD_EQ 0x00000200
412#define HC_HATMD_LE 0x00000300
413#define HC_HATMD_GT 0x00000400
414#define HC_HATMD_NE 0x00000500
415#define HC_HATMD_GE 0x00000600
416#define HC_HATMD_AllPass 0x00000700
417/* HC_SubA_HABLCsat
418 */
419#define HC_HABLCsat_MASK 0x00010000
420#define HC_HABLCa_MASK 0x0000fc00
421#define HC_HABLCa_C_MASK 0x0000c000
422#define HC_HABLCa_OPC_MASK 0x00003c00
423#define HC_HABLFCa_MASK 0x000003f0
424#define HC_HABLFCa_C_MASK 0x00000300
425#define HC_HABLFCa_OPC_MASK 0x000000f0
426#define HC_HABLCbias_MASK 0x0000000f
427#define HC_HABLCbias_C_MASK 0x00000008
428#define HC_HABLCbias_OPC_MASK 0x00000007
429/*-- Define the input color.
430 */
431#define HC_XC_Csrc 0x00000000
432#define HC_XC_Cdst 0x00000001
433#define HC_XC_Asrc 0x00000002
434#define HC_XC_Adst 0x00000003
435#define HC_XC_Fog 0x00000004
436#define HC_XC_HABLRC 0x00000005
437#define HC_XC_minSrcDst 0x00000006
438#define HC_XC_maxSrcDst 0x00000007
439#define HC_XC_mimAsrcInvAdst 0x00000008
440#define HC_XC_OPC 0x00000000
441#define HC_XC_InvOPC 0x00000010
442#define HC_XC_OPCp5 0x00000020
443/*-- Define the input Alpha
444 */
445#define HC_XA_OPA 0x00000000
446#define HC_XA_InvOPA 0x00000010
447#define HC_XA_OPAp5 0x00000020
448#define HC_XA_0 0x00000000
449#define HC_XA_Asrc 0x00000001
450#define HC_XA_Adst 0x00000002
451#define HC_XA_Fog 0x00000003
452#define HC_XA_minAsrcFog 0x00000004
453#define HC_XA_minAsrcAdst 0x00000005
454#define HC_XA_maxAsrcFog 0x00000006
455#define HC_XA_maxAsrcAdst 0x00000007
456#define HC_XA_HABLRA 0x00000008
457#define HC_XA_minAsrcInvAdst 0x00000008
458#define HC_XA_HABLFRA 0x00000009
459/*--
460 */
461#define HC_HABLCa_OPC (HC_XC_OPC << 10)
462#define HC_HABLCa_InvOPC (HC_XC_InvOPC << 10)
463#define HC_HABLCa_OPCp5 (HC_XC_OPCp5 << 10)
464#define HC_HABLCa_Csrc (HC_XC_Csrc << 10)
465#define HC_HABLCa_Cdst (HC_XC_Cdst << 10)
466#define HC_HABLCa_Asrc (HC_XC_Asrc << 10)
467#define HC_HABLCa_Adst (HC_XC_Adst << 10)
468#define HC_HABLCa_Fog (HC_XC_Fog << 10)
469#define HC_HABLCa_HABLRCa (HC_XC_HABLRC << 10)
470#define HC_HABLCa_minSrcDst (HC_XC_minSrcDst << 10)
471#define HC_HABLCa_maxSrcDst (HC_XC_maxSrcDst << 10)
472#define HC_HABLFCa_OPC (HC_XC_OPC << 4)
473#define HC_HABLFCa_InvOPC (HC_XC_InvOPC << 4)
474#define HC_HABLFCa_OPCp5 (HC_XC_OPCp5 << 4)
475#define HC_HABLFCa_Csrc (HC_XC_Csrc << 4)
476#define HC_HABLFCa_Cdst (HC_XC_Cdst << 4)
477#define HC_HABLFCa_Asrc (HC_XC_Asrc << 4)
478#define HC_HABLFCa_Adst (HC_XC_Adst << 4)
479#define HC_HABLFCa_Fog (HC_XC_Fog << 4)
480#define HC_HABLFCa_HABLRCa (HC_XC_HABLRC << 4)
481#define HC_HABLFCa_minSrcDst (HC_XC_minSrcDst << 4)
482#define HC_HABLFCa_maxSrcDst (HC_XC_maxSrcDst << 4)
483#define HC_HABLFCa_mimAsrcInvAdst (HC_XC_mimAsrcInvAdst << 4)
484#define HC_HABLCbias_HABLRCbias 0x00000000
485#define HC_HABLCbias_Asrc 0x00000001
486#define HC_HABLCbias_Adst 0x00000002
487#define HC_HABLCbias_Fog 0x00000003
488#define HC_HABLCbias_Cin 0x00000004
489/* HC_SubA_HABLCop 0x0035
490 */
491#define HC_HABLdot_MASK 0x00010000
492#define HC_HABLCop_MASK 0x00004000
493#define HC_HABLCb_MASK 0x00003f00
494#define HC_HABLCb_C_MASK 0x00003000
495#define HC_HABLCb_OPC_MASK 0x00000f00
496#define HC_HABLFCb_MASK 0x000000fc
497#define HC_HABLFCb_C_MASK 0x000000c0
498#define HC_HABLFCb_OPC_MASK 0x0000003c
499#define HC_HABLCshift_MASK 0x00000003
500#define HC_HABLCb_OPC (HC_XC_OPC << 8)
501#define HC_HABLCb_InvOPC (HC_XC_InvOPC << 8)
502#define HC_HABLCb_OPCp5 (HC_XC_OPCp5 << 8)
503#define HC_HABLCb_Csrc (HC_XC_Csrc << 8)
504#define HC_HABLCb_Cdst (HC_XC_Cdst << 8)
505#define HC_HABLCb_Asrc (HC_XC_Asrc << 8)
506#define HC_HABLCb_Adst (HC_XC_Adst << 8)
507#define HC_HABLCb_Fog (HC_XC_Fog << 8)
508#define HC_HABLCb_HABLRCa (HC_XC_HABLRC << 8)
509#define HC_HABLCb_minSrcDst (HC_XC_minSrcDst << 8)
510#define HC_HABLCb_maxSrcDst (HC_XC_maxSrcDst << 8)
511#define HC_HABLFCb_OPC (HC_XC_OPC << 2)
512#define HC_HABLFCb_InvOPC (HC_XC_InvOPC << 2)
513#define HC_HABLFCb_OPCp5 (HC_XC_OPCp5 << 2)
514#define HC_HABLFCb_Csrc (HC_XC_Csrc << 2)
515#define HC_HABLFCb_Cdst (HC_XC_Cdst << 2)
516#define HC_HABLFCb_Asrc (HC_XC_Asrc << 2)
517#define HC_HABLFCb_Adst (HC_XC_Adst << 2)
518#define HC_HABLFCb_Fog (HC_XC_Fog << 2)
519#define HC_HABLFCb_HABLRCb (HC_XC_HABLRC << 2)
520#define HC_HABLFCb_minSrcDst (HC_XC_minSrcDst << 2)
521#define HC_HABLFCb_maxSrcDst (HC_XC_maxSrcDst << 2)
522#define HC_HABLFCb_mimAsrcInvAdst (HC_XC_mimAsrcInvAdst << 2)
523/* HC_SubA_HABLAsat 0x0036
524 */
525#define HC_HABLAsat_MASK 0x00010000
526#define HC_HABLAa_MASK 0x0000fc00
527#define HC_HABLAa_A_MASK 0x0000c000
528#define HC_HABLAa_OPA_MASK 0x00003c00
529#define HC_HABLFAa_MASK 0x000003f0
530#define HC_HABLFAa_A_MASK 0x00000300
531#define HC_HABLFAa_OPA_MASK 0x000000f0
532#define HC_HABLAbias_MASK 0x0000000f
533#define HC_HABLAbias_A_MASK 0x00000008
534#define HC_HABLAbias_OPA_MASK 0x00000007
535#define HC_HABLAa_OPA (HC_XA_OPA << 10)
536#define HC_HABLAa_InvOPA (HC_XA_InvOPA << 10)
537#define HC_HABLAa_OPAp5 (HC_XA_OPAp5 << 10)
538#define HC_HABLAa_0 (HC_XA_0 << 10)
539#define HC_HABLAa_Asrc (HC_XA_Asrc << 10)
540#define HC_HABLAa_Adst (HC_XA_Adst << 10)
541#define HC_HABLAa_Fog (HC_XA_Fog << 10)
542#define HC_HABLAa_minAsrcFog (HC_XA_minAsrcFog << 10)
543#define HC_HABLAa_minAsrcAdst (HC_XA_minAsrcAdst << 10)
544#define HC_HABLAa_maxAsrcFog (HC_XA_maxAsrcFog << 10)
545#define HC_HABLAa_maxAsrcAdst (HC_XA_maxAsrcAdst << 10)
546#define HC_HABLAa_HABLRA (HC_XA_HABLRA << 10)
547#define HC_HABLFAa_OPA (HC_XA_OPA << 4)
548#define HC_HABLFAa_InvOPA (HC_XA_InvOPA << 4)
549#define HC_HABLFAa_OPAp5 (HC_XA_OPAp5 << 4)
550#define HC_HABLFAa_0 (HC_XA_0 << 4)
551#define HC_HABLFAa_Asrc (HC_XA_Asrc << 4)
552#define HC_HABLFAa_Adst (HC_XA_Adst << 4)
553#define HC_HABLFAa_Fog (HC_XA_Fog << 4)
554#define HC_HABLFAa_minAsrcFog (HC_XA_minAsrcFog << 4)
555#define HC_HABLFAa_minAsrcAdst (HC_XA_minAsrcAdst << 4)
556#define HC_HABLFAa_maxAsrcFog (HC_XA_maxAsrcFog << 4)
557#define HC_HABLFAa_maxAsrcAdst (HC_XA_maxAsrcAdst << 4)
558#define HC_HABLFAa_minAsrcInvAdst (HC_XA_minAsrcInvAdst << 4)
559#define HC_HABLFAa_HABLFRA (HC_XA_HABLFRA << 4)
560#define HC_HABLAbias_HABLRAbias 0x00000000
561#define HC_HABLAbias_Asrc 0x00000001
562#define HC_HABLAbias_Adst 0x00000002
563#define HC_HABLAbias_Fog 0x00000003
564#define HC_HABLAbias_Aaa 0x00000004
565/* HC_SubA_HABLAop 0x0037
566 */
567#define HC_HABLAop_MASK 0x00004000
568#define HC_HABLAb_MASK 0x00003f00
569#define HC_HABLAb_OPA_MASK 0x00000f00
570#define HC_HABLFAb_MASK 0x000000fc
571#define HC_HABLFAb_OPA_MASK 0x0000003c
572#define HC_HABLAshift_MASK 0x00000003
573#define HC_HABLAb_OPA (HC_XA_OPA << 8)
574#define HC_HABLAb_InvOPA (HC_XA_InvOPA << 8)
575#define HC_HABLAb_OPAp5 (HC_XA_OPAp5 << 8)
576#define HC_HABLAb_0 (HC_XA_0 << 8)
577#define HC_HABLAb_Asrc (HC_XA_Asrc << 8)
578#define HC_HABLAb_Adst (HC_XA_Adst << 8)
579#define HC_HABLAb_Fog (HC_XA_Fog << 8)
580#define HC_HABLAb_minAsrcFog (HC_XA_minAsrcFog << 8)
581#define HC_HABLAb_minAsrcAdst (HC_XA_minAsrcAdst << 8)
582#define HC_HABLAb_maxAsrcFog (HC_XA_maxAsrcFog << 8)
583#define HC_HABLAb_maxAsrcAdst (HC_XA_maxAsrcAdst << 8)
584#define HC_HABLAb_HABLRA (HC_XA_HABLRA << 8)
585#define HC_HABLFAb_OPA (HC_XA_OPA << 2)
586#define HC_HABLFAb_InvOPA (HC_XA_InvOPA << 2)
587#define HC_HABLFAb_OPAp5 (HC_XA_OPAp5 << 2)
588#define HC_HABLFAb_0 (HC_XA_0 << 2)
589#define HC_HABLFAb_Asrc (HC_XA_Asrc << 2)
590#define HC_HABLFAb_Adst (HC_XA_Adst << 2)
591#define HC_HABLFAb_Fog (HC_XA_Fog << 2)
592#define HC_HABLFAb_minAsrcFog (HC_XA_minAsrcFog << 2)
593#define HC_HABLFAb_minAsrcAdst (HC_XA_minAsrcAdst << 2)
594#define HC_HABLFAb_maxAsrcFog (HC_XA_maxAsrcFog << 2)
595#define HC_HABLFAb_maxAsrcAdst (HC_XA_maxAsrcAdst << 2)
596#define HC_HABLFAb_minAsrcInvAdst (HC_XA_minAsrcInvAdst << 2)
597#define HC_HABLFAb_HABLFRA (HC_XA_HABLFRA << 2)
598/* HC_SubA_HABLRAa 0x003d
599 */
600#define HC_HABLRAa_MASK 0x00ff0000
601#define HC_HABLRFAa_MASK 0x0000ff00
602#define HC_HABLRAbias_MASK 0x000000ff
603#define HC_HABLRAa_SHIFT 16
604#define HC_HABLRFAa_SHIFT 8
605/* HC_SubA_HABLRAb 0x003e
606 */
607#define HC_HABLRAb_MASK 0x0000ff00
608#define HC_HABLRFAb_MASK 0x000000ff
609#define HC_HABLRAb_SHIFT 8
610
611/* Destination Setting
612 */
613#define HC_SubA_HDBBasL 0x0040
614#define HC_SubA_HDBBasH 0x0041
615#define HC_SubA_HDBFM 0x0042
616#define HC_SubA_HFBBMSKL 0x0043
617#define HC_SubA_HROP 0x0044
618/* HC_SubA_HDBFM 0x0042
619 */
620#define HC_HDBFM_MASK 0x001f0000
621#define HC_HDBLoc_MASK 0x0000c000
622#define HC_HDBPit_MASK 0x00003fff
623#define HC_HDBFM_RGB555 0x00000000
624#define HC_HDBFM_RGB565 0x00010000
625#define HC_HDBFM_ARGB4444 0x00020000
626#define HC_HDBFM_ARGB1555 0x00030000
627#define HC_HDBFM_BGR555 0x00040000
628#define HC_HDBFM_BGR565 0x00050000
629#define HC_HDBFM_ABGR4444 0x00060000
630#define HC_HDBFM_ABGR1555 0x00070000
631#define HC_HDBFM_ARGB0888 0x00080000
632#define HC_HDBFM_ARGB8888 0x00090000
633#define HC_HDBFM_ABGR0888 0x000a0000
634#define HC_HDBFM_ABGR8888 0x000b0000
635#define HC_HDBLoc_Local 0x00000000
636#define HC_HDBLoc_Sys 0x00004000
637/* HC_SubA_HROP 0x0044
638 */
639#define HC_HROP_MASK 0x00000f00
640#define HC_HFBBMSKH_MASK 0x000000ff
641#define HC_HROP_BLACK 0x00000000
642#define HC_HROP_DPon 0x00000100
643#define HC_HROP_DPna 0x00000200
644#define HC_HROP_Pn 0x00000300
645#define HC_HROP_PDna 0x00000400
646#define HC_HROP_Dn 0x00000500
647#define HC_HROP_DPx 0x00000600
648#define HC_HROP_DPan 0x00000700
649#define HC_HROP_DPa 0x00000800
650#define HC_HROP_DPxn 0x00000900
651#define HC_HROP_D 0x00000a00
652#define HC_HROP_DPno 0x00000b00
653#define HC_HROP_P 0x00000c00
654#define HC_HROP_PDno 0x00000d00
655#define HC_HROP_DPo 0x00000e00
656#define HC_HROP_WHITE 0x00000f00
657
658/* Fog Setting
659 */
660#define HC_SubA_HFogLF 0x0050
661#define HC_SubA_HFogCL 0x0051
662#define HC_SubA_HFogCH 0x0052
663#define HC_SubA_HFogStL 0x0053
664#define HC_SubA_HFogStH 0x0054
665#define HC_SubA_HFogOOdMF 0x0055
666#define HC_SubA_HFogOOdEF 0x0056
667#define HC_SubA_HFogEndL 0x0057
668#define HC_SubA_HFogDenst 0x0058
669/* HC_SubA_FogLF 0x0050
670 */
671#define HC_FogLF_MASK 0x00000010
672#define HC_FogEq_MASK 0x00000008
673#define HC_FogMD_MASK 0x00000007
674#define HC_FogMD_LocalFog 0x00000000
675#define HC_FogMD_LinearFog 0x00000002
676#define HC_FogMD_ExponentialFog 0x00000004
677#define HC_FogMD_Exponential2Fog 0x00000005
678/* #define HC_FogMD_FogTable 0x00000003 */
679
680/* HC_SubA_HFogDenst 0x0058
681 */
682#define HC_FogDenst_MASK 0x001fff00
683#define HC_FogEndL_MASK 0x000000ff
684
685/* Texture subtype definitions
686 */
687#define HC_SubType_Tex0 0x00000000
688#define HC_SubType_Tex1 0x00000001
689#define HC_SubType_TexGeneral 0x000000fe
690
691/* Attribute of texture n
692 */
693#define HC_SubA_HTXnL0BasL 0x0000
694#define HC_SubA_HTXnL1BasL 0x0001
695#define HC_SubA_HTXnL2BasL 0x0002
696#define HC_SubA_HTXnL3BasL 0x0003
697#define HC_SubA_HTXnL4BasL 0x0004
698#define HC_SubA_HTXnL5BasL 0x0005
699#define HC_SubA_HTXnL6BasL 0x0006
700#define HC_SubA_HTXnL7BasL 0x0007
701#define HC_SubA_HTXnL8BasL 0x0008
702#define HC_SubA_HTXnL9BasL 0x0009
703#define HC_SubA_HTXnLaBasL 0x000a
704#define HC_SubA_HTXnLbBasL 0x000b
705#define HC_SubA_HTXnLcBasL 0x000c
706#define HC_SubA_HTXnLdBasL 0x000d
707#define HC_SubA_HTXnLeBasL 0x000e
708#define HC_SubA_HTXnLfBasL 0x000f
709#define HC_SubA_HTXnL10BasL 0x0010
710#define HC_SubA_HTXnL11BasL 0x0011
711#define HC_SubA_HTXnL012BasH 0x0020
712#define HC_SubA_HTXnL345BasH 0x0021
713#define HC_SubA_HTXnL678BasH 0x0022
714#define HC_SubA_HTXnL9abBasH 0x0023
715#define HC_SubA_HTXnLcdeBasH 0x0024
716#define HC_SubA_HTXnLf1011BasH 0x0025
717#define HC_SubA_HTXnL0Pit 0x002b
718#define HC_SubA_HTXnL1Pit 0x002c
719#define HC_SubA_HTXnL2Pit 0x002d
720#define HC_SubA_HTXnL3Pit 0x002e
721#define HC_SubA_HTXnL4Pit 0x002f
722#define HC_SubA_HTXnL5Pit 0x0030
723#define HC_SubA_HTXnL6Pit 0x0031
724#define HC_SubA_HTXnL7Pit 0x0032
725#define HC_SubA_HTXnL8Pit 0x0033
726#define HC_SubA_HTXnL9Pit 0x0034
727#define HC_SubA_HTXnLaPit 0x0035
728#define HC_SubA_HTXnLbPit 0x0036
729#define HC_SubA_HTXnLcPit 0x0037
730#define HC_SubA_HTXnLdPit 0x0038
731#define HC_SubA_HTXnLePit 0x0039
732#define HC_SubA_HTXnLfPit 0x003a
733#define HC_SubA_HTXnL10Pit 0x003b
734#define HC_SubA_HTXnL11Pit 0x003c
735#define HC_SubA_HTXnL0_5WE 0x004b
736#define HC_SubA_HTXnL6_bWE 0x004c
737#define HC_SubA_HTXnLc_11WE 0x004d
738#define HC_SubA_HTXnL0_5HE 0x0051
739#define HC_SubA_HTXnL6_bHE 0x0052
740#define HC_SubA_HTXnLc_11HE 0x0053
741#define HC_SubA_HTXnL0OS 0x0077
742#define HC_SubA_HTXnTB 0x0078
743#define HC_SubA_HTXnMPMD 0x0079
744#define HC_SubA_HTXnCLODu 0x007a
745#define HC_SubA_HTXnFM 0x007b
746#define HC_SubA_HTXnTRCH 0x007c
747#define HC_SubA_HTXnTRCL 0x007d
748#define HC_SubA_HTXnTBC 0x007e
749#define HC_SubA_HTXnTRAH 0x007f
750#define HC_SubA_HTXnTBLCsat 0x0080
751#define HC_SubA_HTXnTBLCop 0x0081
752#define HC_SubA_HTXnTBLMPfog 0x0082
753#define HC_SubA_HTXnTBLAsat 0x0083
754#define HC_SubA_HTXnTBLRCa 0x0085
755#define HC_SubA_HTXnTBLRCb 0x0086
756#define HC_SubA_HTXnTBLRCc 0x0087
757#define HC_SubA_HTXnTBLRCbias 0x0088
758#define HC_SubA_HTXnTBLRAa 0x0089
759#define HC_SubA_HTXnTBLRFog 0x008a
760#define HC_SubA_HTXnBumpM00 0x0090
761#define HC_SubA_HTXnBumpM01 0x0091
762#define HC_SubA_HTXnBumpM10 0x0092
763#define HC_SubA_HTXnBumpM11 0x0093
764#define HC_SubA_HTXnLScale 0x0094
765#define HC_SubA_HTXSMD 0x0000
766/* HC_SubA_HTXnL012BasH 0x0020
767 */
768#define HC_HTXnL0BasH_MASK 0x000000ff
769#define HC_HTXnL1BasH_MASK 0x0000ff00
770#define HC_HTXnL2BasH_MASK 0x00ff0000
771#define HC_HTXnL1BasH_SHIFT 8
772#define HC_HTXnL2BasH_SHIFT 16
773/* HC_SubA_HTXnL345BasH 0x0021
774 */
775#define HC_HTXnL3BasH_MASK 0x000000ff
776#define HC_HTXnL4BasH_MASK 0x0000ff00
777#define HC_HTXnL5BasH_MASK 0x00ff0000
778#define HC_HTXnL4BasH_SHIFT 8
779#define HC_HTXnL5BasH_SHIFT 16
780/* HC_SubA_HTXnL678BasH 0x0022
781 */
782#define HC_HTXnL6BasH_MASK 0x000000ff
783#define HC_HTXnL7BasH_MASK 0x0000ff00
784#define HC_HTXnL8BasH_MASK 0x00ff0000
785#define HC_HTXnL7BasH_SHIFT 8
786#define HC_HTXnL8BasH_SHIFT 16
787/* HC_SubA_HTXnL9abBasH 0x0023
788 */
789#define HC_HTXnL9BasH_MASK 0x000000ff
790#define HC_HTXnLaBasH_MASK 0x0000ff00
791#define HC_HTXnLbBasH_MASK 0x00ff0000
792#define HC_HTXnLaBasH_SHIFT 8
793#define HC_HTXnLbBasH_SHIFT 16
794/* HC_SubA_HTXnLcdeBasH 0x0024
795 */
796#define HC_HTXnLcBasH_MASK 0x000000ff
797#define HC_HTXnLdBasH_MASK 0x0000ff00
798#define HC_HTXnLeBasH_MASK 0x00ff0000
799#define HC_HTXnLdBasH_SHIFT 8
800#define HC_HTXnLeBasH_SHIFT 16
801/* HC_SubA_HTXnLcdeBasH 0x0025
802 */
803#define HC_HTXnLfBasH_MASK 0x000000ff
804#define HC_HTXnL10BasH_MASK 0x0000ff00
805#define HC_HTXnL11BasH_MASK 0x00ff0000
806#define HC_HTXnL10BasH_SHIFT 8
807#define HC_HTXnL11BasH_SHIFT 16
808/* HC_SubA_HTXnL0Pit 0x002b
809 */
810#define HC_HTXnLnPit_MASK 0x00003fff
811#define HC_HTXnEnPit_MASK 0x00080000
812#define HC_HTXnLnPitE_MASK 0x00f00000
813#define HC_HTXnLnPitE_SHIFT 20
814/* HC_SubA_HTXnL0_5WE 0x004b
815 */
816#define HC_HTXnL0WE_MASK 0x0000000f
817#define HC_HTXnL1WE_MASK 0x000000f0
818#define HC_HTXnL2WE_MASK 0x00000f00
819#define HC_HTXnL3WE_MASK 0x0000f000
820#define HC_HTXnL4WE_MASK 0x000f0000
821#define HC_HTXnL5WE_MASK 0x00f00000
822#define HC_HTXnL1WE_SHIFT 4
823#define HC_HTXnL2WE_SHIFT 8
824#define HC_HTXnL3WE_SHIFT 12
825#define HC_HTXnL4WE_SHIFT 16
826#define HC_HTXnL5WE_SHIFT 20
827/* HC_SubA_HTXnL6_bWE 0x004c
828 */
829#define HC_HTXnL6WE_MASK 0x0000000f
830#define HC_HTXnL7WE_MASK 0x000000f0
831#define HC_HTXnL8WE_MASK 0x00000f00
832#define HC_HTXnL9WE_MASK 0x0000f000
833#define HC_HTXnLaWE_MASK 0x000f0000
834#define HC_HTXnLbWE_MASK 0x00f00000
835#define HC_HTXnL7WE_SHIFT 4
836#define HC_HTXnL8WE_SHIFT 8
837#define HC_HTXnL9WE_SHIFT 12
838#define HC_HTXnLaWE_SHIFT 16
839#define HC_HTXnLbWE_SHIFT 20
840/* HC_SubA_HTXnLc_11WE 0x004d
841 */
842#define HC_HTXnLcWE_MASK 0x0000000f
843#define HC_HTXnLdWE_MASK 0x000000f0
844#define HC_HTXnLeWE_MASK 0x00000f00
845#define HC_HTXnLfWE_MASK 0x0000f000
846#define HC_HTXnL10WE_MASK 0x000f0000
847#define HC_HTXnL11WE_MASK 0x00f00000
848#define HC_HTXnLdWE_SHIFT 4
849#define HC_HTXnLeWE_SHIFT 8
850#define HC_HTXnLfWE_SHIFT 12
851#define HC_HTXnL10WE_SHIFT 16
852#define HC_HTXnL11WE_SHIFT 20
853/* HC_SubA_HTXnL0_5HE 0x0051
854 */
855#define HC_HTXnL0HE_MASK 0x0000000f
856#define HC_HTXnL1HE_MASK 0x000000f0
857#define HC_HTXnL2HE_MASK 0x00000f00
858#define HC_HTXnL3HE_MASK 0x0000f000
859#define HC_HTXnL4HE_MASK 0x000f0000
860#define HC_HTXnL5HE_MASK 0x00f00000
861#define HC_HTXnL1HE_SHIFT 4
862#define HC_HTXnL2HE_SHIFT 8
863#define HC_HTXnL3HE_SHIFT 12
864#define HC_HTXnL4HE_SHIFT 16
865#define HC_HTXnL5HE_SHIFT 20
866/* HC_SubA_HTXnL6_bHE 0x0052
867 */
868#define HC_HTXnL6HE_MASK 0x0000000f
869#define HC_HTXnL7HE_MASK 0x000000f0
870#define HC_HTXnL8HE_MASK 0x00000f00
871#define HC_HTXnL9HE_MASK 0x0000f000
872#define HC_HTXnLaHE_MASK 0x000f0000
873#define HC_HTXnLbHE_MASK 0x00f00000
874#define HC_HTXnL7HE_SHIFT 4
875#define HC_HTXnL8HE_SHIFT 8
876#define HC_HTXnL9HE_SHIFT 12
877#define HC_HTXnLaHE_SHIFT 16
878#define HC_HTXnLbHE_SHIFT 20
879/* HC_SubA_HTXnLc_11HE 0x0053
880 */
881#define HC_HTXnLcHE_MASK 0x0000000f
882#define HC_HTXnLdHE_MASK 0x000000f0
883#define HC_HTXnLeHE_MASK 0x00000f00
884#define HC_HTXnLfHE_MASK 0x0000f000
885#define HC_HTXnL10HE_MASK 0x000f0000
886#define HC_HTXnL11HE_MASK 0x00f00000
887#define HC_HTXnLdHE_SHIFT 4
888#define HC_HTXnLeHE_SHIFT 8
889#define HC_HTXnLfHE_SHIFT 12
890#define HC_HTXnL10HE_SHIFT 16
891#define HC_HTXnL11HE_SHIFT 20
892/* HC_SubA_HTXnL0OS 0x0077
893 */
894#define HC_HTXnL0OS_MASK 0x003ff000
895#define HC_HTXnLVmax_MASK 0x00000fc0
896#define HC_HTXnLVmin_MASK 0x0000003f
897#define HC_HTXnL0OS_SHIFT 12
898#define HC_HTXnLVmax_SHIFT 6
899/* HC_SubA_HTXnTB 0x0078
900 */
901#define HC_HTXnTB_MASK 0x00f00000
902#define HC_HTXnFLSe_MASK 0x0000e000
903#define HC_HTXnFLSs_MASK 0x00001c00
904#define HC_HTXnFLTe_MASK 0x00000380
905#define HC_HTXnFLTs_MASK 0x00000070
906#define HC_HTXnFLDs_MASK 0x0000000f
907#define HC_HTXnTB_NoTB 0x00000000
908#define HC_HTXnTB_TBC_S 0x00100000
909#define HC_HTXnTB_TBC_T 0x00200000
910#define HC_HTXnTB_TB_S 0x00400000
911#define HC_HTXnTB_TB_T 0x00800000
912#define HC_HTXnFLSe_Nearest 0x00000000
913#define HC_HTXnFLSe_Linear 0x00002000
914#define HC_HTXnFLSe_NonLinear 0x00004000
915#define HC_HTXnFLSe_Sharp 0x00008000
916#define HC_HTXnFLSe_Flat_Gaussian_Cubic 0x0000c000
917#define HC_HTXnFLSs_Nearest 0x00000000
918#define HC_HTXnFLSs_Linear 0x00000400
919#define HC_HTXnFLSs_NonLinear 0x00000800
920#define HC_HTXnFLSs_Flat_Gaussian_Cubic 0x00001800
921#define HC_HTXnFLTe_Nearest 0x00000000
922#define HC_HTXnFLTe_Linear 0x00000080
923#define HC_HTXnFLTe_NonLinear 0x00000100
924#define HC_HTXnFLTe_Sharp 0x00000180
925#define HC_HTXnFLTe_Flat_Gaussian_Cubic 0x00000300
926#define HC_HTXnFLTs_Nearest 0x00000000
927#define HC_HTXnFLTs_Linear 0x00000010
928#define HC_HTXnFLTs_NonLinear 0x00000020
929#define HC_HTXnFLTs_Flat_Gaussian_Cubic 0x00000060
930#define HC_HTXnFLDs_Tex0 0x00000000
931#define HC_HTXnFLDs_Nearest 0x00000001
932#define HC_HTXnFLDs_Linear 0x00000002
933#define HC_HTXnFLDs_NonLinear 0x00000003
934#define HC_HTXnFLDs_Dither 0x00000004
935#define HC_HTXnFLDs_ConstLOD 0x00000005
936#define HC_HTXnFLDs_Ani 0x00000006
937#define HC_HTXnFLDs_AniDither 0x00000007
938/* HC_SubA_HTXnMPMD 0x0079
939 */
940#define HC_HTXnMPMD_SMASK 0x00070000
941#define HC_HTXnMPMD_TMASK 0x00380000
942#define HC_HTXnLODDTf_MASK 0x00000007
943#define HC_HTXnXY2ST_MASK 0x00000008
944#define HC_HTXnMPMD_Tsingle 0x00000000
945#define HC_HTXnMPMD_Tclamp 0x00080000
946#define HC_HTXnMPMD_Trepeat 0x00100000
947#define HC_HTXnMPMD_Tmirror 0x00180000
948#define HC_HTXnMPMD_Twrap 0x00200000
949#define HC_HTXnMPMD_Ssingle 0x00000000
950#define HC_HTXnMPMD_Sclamp 0x00010000
951#define HC_HTXnMPMD_Srepeat 0x00020000
952#define HC_HTXnMPMD_Smirror 0x00030000
953#define HC_HTXnMPMD_Swrap 0x00040000
954/* HC_SubA_HTXnCLODu 0x007a
955 */
956#define HC_HTXnCLODu_MASK 0x000ffc00
957#define HC_HTXnCLODd_MASK 0x000003ff
958#define HC_HTXnCLODu_SHIFT 10
959/* HC_SubA_HTXnFM 0x007b
960 */
961#define HC_HTXnFM_MASK 0x00ff0000
962#define HC_HTXnLoc_MASK 0x00000003
963#define HC_HTXnFM_INDEX 0x00000000
964#define HC_HTXnFM_Intensity 0x00080000
965#define HC_HTXnFM_Lum 0x00100000
966#define HC_HTXnFM_Alpha 0x00180000
967#define HC_HTXnFM_DX 0x00280000
968#define HC_HTXnFM_ARGB16 0x00880000
969#define HC_HTXnFM_ARGB32 0x00980000
970#define HC_HTXnFM_ABGR16 0x00a80000
971#define HC_HTXnFM_ABGR32 0x00b80000
972#define HC_HTXnFM_RGBA16 0x00c80000
973#define HC_HTXnFM_RGBA32 0x00d80000
974#define HC_HTXnFM_BGRA16 0x00e80000
975#define HC_HTXnFM_BGRA32 0x00f80000
976#define HC_HTXnFM_BUMPMAP 0x00380000
977#define HC_HTXnFM_Index1 (HC_HTXnFM_INDEX | 0x00000000)
978#define HC_HTXnFM_Index2 (HC_HTXnFM_INDEX | 0x00010000)
979#define HC_HTXnFM_Index4 (HC_HTXnFM_INDEX | 0x00020000)
980#define HC_HTXnFM_Index8 (HC_HTXnFM_INDEX | 0x00030000)
981#define HC_HTXnFM_T1 (HC_HTXnFM_Intensity | 0x00000000)
982#define HC_HTXnFM_T2 (HC_HTXnFM_Intensity | 0x00010000)
983#define HC_HTXnFM_T4 (HC_HTXnFM_Intensity | 0x00020000)
984#define HC_HTXnFM_T8 (HC_HTXnFM_Intensity | 0x00030000)
985#define HC_HTXnFM_L1 (HC_HTXnFM_Lum | 0x00000000)
986#define HC_HTXnFM_L2 (HC_HTXnFM_Lum | 0x00010000)
987#define HC_HTXnFM_L4 (HC_HTXnFM_Lum | 0x00020000)
988#define HC_HTXnFM_L8 (HC_HTXnFM_Lum | 0x00030000)
989#define HC_HTXnFM_AL44 (HC_HTXnFM_Lum | 0x00040000)
990#define HC_HTXnFM_AL88 (HC_HTXnFM_Lum | 0x00050000)
991#define HC_HTXnFM_A1 (HC_HTXnFM_Alpha | 0x00000000)
992#define HC_HTXnFM_A2 (HC_HTXnFM_Alpha | 0x00010000)
993#define HC_HTXnFM_A4 (HC_HTXnFM_Alpha | 0x00020000)
994#define HC_HTXnFM_A8 (HC_HTXnFM_Alpha | 0x00030000)
995#define HC_HTXnFM_DX1 (HC_HTXnFM_DX | 0x00010000)
996#define HC_HTXnFM_DX23 (HC_HTXnFM_DX | 0x00020000)
997#define HC_HTXnFM_DX45 (HC_HTXnFM_DX | 0x00030000)
998#define HC_HTXnFM_RGB555 (HC_HTXnFM_ARGB16 | 0x00000000)
999#define HC_HTXnFM_RGB565 (HC_HTXnFM_ARGB16 | 0x00010000)
1000#define HC_HTXnFM_ARGB1555 (HC_HTXnFM_ARGB16 | 0x00020000)
1001#define HC_HTXnFM_ARGB4444 (HC_HTXnFM_ARGB16 | 0x00030000)
1002#define HC_HTXnFM_ARGB0888 (HC_HTXnFM_ARGB32 | 0x00000000)
1003#define HC_HTXnFM_ARGB8888 (HC_HTXnFM_ARGB32 | 0x00010000)
1004#define HC_HTXnFM_BGR555 (HC_HTXnFM_ABGR16 | 0x00000000)
1005#define HC_HTXnFM_BGR565 (HC_HTXnFM_ABGR16 | 0x00010000)
1006#define HC_HTXnFM_ABGR1555 (HC_HTXnFM_ABGR16 | 0x00020000)
1007#define HC_HTXnFM_ABGR4444 (HC_HTXnFM_ABGR16 | 0x00030000)
1008#define HC_HTXnFM_ABGR0888 (HC_HTXnFM_ABGR32 | 0x00000000)
1009#define HC_HTXnFM_ABGR8888 (HC_HTXnFM_ABGR32 | 0x00010000)
1010#define HC_HTXnFM_RGBA5550 (HC_HTXnFM_RGBA16 | 0x00000000)
1011#define HC_HTXnFM_RGBA5551 (HC_HTXnFM_RGBA16 | 0x00020000)
1012#define HC_HTXnFM_RGBA4444 (HC_HTXnFM_RGBA16 | 0x00030000)
1013#define HC_HTXnFM_RGBA8880 (HC_HTXnFM_RGBA32 | 0x00000000)
1014#define HC_HTXnFM_RGBA8888 (HC_HTXnFM_RGBA32 | 0x00010000)
1015#define HC_HTXnFM_BGRA5550 (HC_HTXnFM_BGRA16 | 0x00000000)
1016#define HC_HTXnFM_BGRA5551 (HC_HTXnFM_BGRA16 | 0x00020000)
1017#define HC_HTXnFM_BGRA4444 (HC_HTXnFM_BGRA16 | 0x00030000)
1018#define HC_HTXnFM_BGRA8880 (HC_HTXnFM_BGRA32 | 0x00000000)
1019#define HC_HTXnFM_BGRA8888 (HC_HTXnFM_BGRA32 | 0x00010000)
1020#define HC_HTXnFM_VU88 (HC_HTXnFM_BUMPMAP | 0x00000000)
1021#define HC_HTXnFM_LVU655 (HC_HTXnFM_BUMPMAP | 0x00010000)
1022#define HC_HTXnFM_LVU888 (HC_HTXnFM_BUMPMAP | 0x00020000)
1023#define HC_HTXnLoc_Local 0x00000000
1024#define HC_HTXnLoc_Sys 0x00000002
1025#define HC_HTXnLoc_AGP 0x00000003
1026/* HC_SubA_HTXnTRAH 0x007f
1027 */
1028#define HC_HTXnTRAH_MASK 0x00ff0000
1029#define HC_HTXnTRAL_MASK 0x0000ff00
1030#define HC_HTXnTBA_MASK 0x000000ff
1031#define HC_HTXnTRAH_SHIFT 16
1032#define HC_HTXnTRAL_SHIFT 8
1033/* HC_SubA_HTXnTBLCsat 0x0080
1034 *-- Define the input texture.
1035 */
1036#define HC_XTC_TOPC 0x00000000
1037#define HC_XTC_InvTOPC 0x00000010
1038#define HC_XTC_TOPCp5 0x00000020
1039#define HC_XTC_Cbias 0x00000000
1040#define HC_XTC_InvCbias 0x00000010
1041#define HC_XTC_0 0x00000000
1042#define HC_XTC_Dif 0x00000001
1043#define HC_XTC_Spec 0x00000002
1044#define HC_XTC_Tex 0x00000003
1045#define HC_XTC_Cur 0x00000004
1046#define HC_XTC_Adif 0x00000005
1047#define HC_XTC_Fog 0x00000006
1048#define HC_XTC_Atex 0x00000007
1049#define HC_XTC_Acur 0x00000008
1050#define HC_XTC_HTXnTBLRC 0x00000009
1051#define HC_XTC_Ctexnext 0x0000000a
1052/*--
1053 */
1054#define HC_HTXnTBLCsat_MASK 0x00800000
1055#define HC_HTXnTBLCa_MASK 0x000fc000
1056#define HC_HTXnTBLCb_MASK 0x00001f80
1057#define HC_HTXnTBLCc_MASK 0x0000003f
1058#define HC_HTXnTBLCa_TOPC (HC_XTC_TOPC << 14)
1059#define HC_HTXnTBLCa_InvTOPC (HC_XTC_InvTOPC << 14)
1060#define HC_HTXnTBLCa_TOPCp5 (HC_XTC_TOPCp5 << 14)
1061#define HC_HTXnTBLCa_0 (HC_XTC_0 << 14)
1062#define HC_HTXnTBLCa_Dif (HC_XTC_Dif << 14)
1063#define HC_HTXnTBLCa_Spec (HC_XTC_Spec << 14)
1064#define HC_HTXnTBLCa_Tex (HC_XTC_Tex << 14)
1065#define HC_HTXnTBLCa_Cur (HC_XTC_Cur << 14)
1066#define HC_HTXnTBLCa_Adif (HC_XTC_Adif << 14)
1067#define HC_HTXnTBLCa_Fog (HC_XTC_Fog << 14)
1068#define HC_HTXnTBLCa_Atex (HC_XTC_Atex << 14)
1069#define HC_HTXnTBLCa_Acur (HC_XTC_Acur << 14)
1070#define HC_HTXnTBLCa_HTXnTBLRC (HC_XTC_HTXnTBLRC << 14)
1071#define HC_HTXnTBLCa_Ctexnext (HC_XTC_Ctexnext << 14)
1072#define HC_HTXnTBLCb_TOPC (HC_XTC_TOPC << 7)
1073#define HC_HTXnTBLCb_InvTOPC (HC_XTC_InvTOPC << 7)
1074#define HC_HTXnTBLCb_TOPCp5 (HC_XTC_TOPCp5 << 7)
1075#define HC_HTXnTBLCb_0 (HC_XTC_0 << 7)
1076#define HC_HTXnTBLCb_Dif (HC_XTC_Dif << 7)
1077#define HC_HTXnTBLCb_Spec (HC_XTC_Spec << 7)
1078#define HC_HTXnTBLCb_Tex (HC_XTC_Tex << 7)
1079#define HC_HTXnTBLCb_Cur (HC_XTC_Cur << 7)
1080#define HC_HTXnTBLCb_Adif (HC_XTC_Adif << 7)
1081#define HC_HTXnTBLCb_Fog (HC_XTC_Fog << 7)
1082#define HC_HTXnTBLCb_Atex (HC_XTC_Atex << 7)
1083#define HC_HTXnTBLCb_Acur (HC_XTC_Acur << 7)
1084#define HC_HTXnTBLCb_HTXnTBLRC (HC_XTC_HTXnTBLRC << 7)
1085#define HC_HTXnTBLCb_Ctexnext (HC_XTC_Ctexnext << 7)
1086#define HC_HTXnTBLCc_TOPC (HC_XTC_TOPC << 0)
1087#define HC_HTXnTBLCc_InvTOPC (HC_XTC_InvTOPC << 0)
1088#define HC_HTXnTBLCc_TOPCp5 (HC_XTC_TOPCp5 << 0)
1089#define HC_HTXnTBLCc_0 (HC_XTC_0 << 0)
1090#define HC_HTXnTBLCc_Dif (HC_XTC_Dif << 0)
1091#define HC_HTXnTBLCc_Spec (HC_XTC_Spec << 0)
1092#define HC_HTXnTBLCc_Tex (HC_XTC_Tex << 0)
1093#define HC_HTXnTBLCc_Cur (HC_XTC_Cur << 0)
1094#define HC_HTXnTBLCc_Adif (HC_XTC_Adif << 0)
1095#define HC_HTXnTBLCc_Fog (HC_XTC_Fog << 0)
1096#define HC_HTXnTBLCc_Atex (HC_XTC_Atex << 0)
1097#define HC_HTXnTBLCc_Acur (HC_XTC_Acur << 0)
1098#define HC_HTXnTBLCc_HTXnTBLRC (HC_XTC_HTXnTBLRC << 0)
1099#define HC_HTXnTBLCc_Ctexnext (HC_XTC_Ctexnext << 0)
1100/* HC_SubA_HTXnTBLCop 0x0081
1101 */
1102#define HC_HTXnTBLdot_MASK 0x00c00000
1103#define HC_HTXnTBLCop_MASK 0x00380000
1104#define HC_HTXnTBLCbias_MASK 0x0007c000
1105#define HC_HTXnTBLCshift_MASK 0x00001800
1106#define HC_HTXnTBLAop_MASK 0x00000380
1107#define HC_HTXnTBLAbias_MASK 0x00000078
1108#define HC_HTXnTBLAshift_MASK 0x00000003
1109#define HC_HTXnTBLCop_Add 0x00000000
1110#define HC_HTXnTBLCop_Sub 0x00080000
1111#define HC_HTXnTBLCop_Min 0x00100000
1112#define HC_HTXnTBLCop_Max 0x00180000
1113#define HC_HTXnTBLCop_Mask 0x00200000
1114#define HC_HTXnTBLCbias_Cbias (HC_XTC_Cbias << 14)
1115#define HC_HTXnTBLCbias_InvCbias (HC_XTC_InvCbias << 14)
1116#define HC_HTXnTBLCbias_0 (HC_XTC_0 << 14)
1117#define HC_HTXnTBLCbias_Dif (HC_XTC_Dif << 14)
1118#define HC_HTXnTBLCbias_Spec (HC_XTC_Spec << 14)
1119#define HC_HTXnTBLCbias_Tex (HC_XTC_Tex << 14)
1120#define HC_HTXnTBLCbias_Cur (HC_XTC_Cur << 14)
1121#define HC_HTXnTBLCbias_Adif (HC_XTC_Adif << 14)
1122#define HC_HTXnTBLCbias_Fog (HC_XTC_Fog << 14)
1123#define HC_HTXnTBLCbias_Atex (HC_XTC_Atex << 14)
1124#define HC_HTXnTBLCbias_Acur (HC_XTC_Acur << 14)
1125#define HC_HTXnTBLCbias_HTXnTBLRC (HC_XTC_HTXnTBLRC << 14)
1126#define HC_HTXnTBLCshift_1 0x00000000
1127#define HC_HTXnTBLCshift_2 0x00000800
1128#define HC_HTXnTBLCshift_No 0x00001000
1129#define HC_HTXnTBLCshift_DotP 0x00001800
1130/*=* John Sheng [2003.7.18] texture combine *=*/
1131#define HC_HTXnTBLDOT3 0x00080000
1132#define HC_HTXnTBLDOT4 0x000C0000
1133
1134#define HC_HTXnTBLAop_Add 0x00000000
1135#define HC_HTXnTBLAop_Sub 0x00000080
1136#define HC_HTXnTBLAop_Min 0x00000100
1137#define HC_HTXnTBLAop_Max 0x00000180
1138#define HC_HTXnTBLAop_Mask 0x00000200
1139#define HC_HTXnTBLAbias_Inv 0x00000040
1140#define HC_HTXnTBLAbias_Adif 0x00000000
1141#define HC_HTXnTBLAbias_Fog 0x00000008
1142#define HC_HTXnTBLAbias_Acur 0x00000010
1143#define HC_HTXnTBLAbias_HTXnTBLRAbias 0x00000018
1144#define HC_HTXnTBLAbias_Atex 0x00000020
1145#define HC_HTXnTBLAshift_1 0x00000000
1146#define HC_HTXnTBLAshift_2 0x00000001
1147#define HC_HTXnTBLAshift_No 0x00000002
1148/* #define HC_HTXnTBLAshift_DotP 0x00000003 */
1149/* HC_SubA_HTXnTBLMPFog 0x0082
1150 */
1151#define HC_HTXnTBLMPfog_MASK 0x00e00000
1152#define HC_HTXnTBLMPfog_0 0x00000000
1153#define HC_HTXnTBLMPfog_Adif 0x00200000
1154#define HC_HTXnTBLMPfog_Fog 0x00400000
1155#define HC_HTXnTBLMPfog_Atex 0x00600000
1156#define HC_HTXnTBLMPfog_Acur 0x00800000
1157#define HC_HTXnTBLMPfog_GHTXnTBLRFog 0x00a00000
1158/* HC_SubA_HTXnTBLAsat 0x0083
1159 *-- Define the texture alpha input.
1160 */
1161#define HC_XTA_TOPA 0x00000000
1162#define HC_XTA_InvTOPA 0x00000008
1163#define HC_XTA_TOPAp5 0x00000010
1164#define HC_XTA_Adif 0x00000000
1165#define HC_XTA_Fog 0x00000001
1166#define HC_XTA_Acur 0x00000002
1167#define HC_XTA_HTXnTBLRA 0x00000003
1168#define HC_XTA_Atex 0x00000004
1169#define HC_XTA_Atexnext 0x00000005
1170/*--
1171 */
1172#define HC_HTXnTBLAsat_MASK 0x00800000
1173#define HC_HTXnTBLAMB_MASK 0x00700000
1174#define HC_HTXnTBLAa_MASK 0x0007c000
1175#define HC_HTXnTBLAb_MASK 0x00000f80
1176#define HC_HTXnTBLAc_MASK 0x0000001f
1177#define HC_HTXnTBLAMB_SHIFT 20
1178#define HC_HTXnTBLAa_TOPA (HC_XTA_TOPA << 14)
1179#define HC_HTXnTBLAa_InvTOPA (HC_XTA_InvTOPA << 14)
1180#define HC_HTXnTBLAa_TOPAp5 (HC_XTA_TOPAp5 << 14)
1181#define HC_HTXnTBLAa_Adif (HC_XTA_Adif << 14)
1182#define HC_HTXnTBLAa_Fog (HC_XTA_Fog << 14)
1183#define HC_HTXnTBLAa_Acur (HC_XTA_Acur << 14)
1184#define HC_HTXnTBLAa_HTXnTBLRA (HC_XTA_HTXnTBLRA << 14)
1185#define HC_HTXnTBLAa_Atex (HC_XTA_Atex << 14)
1186#define HC_HTXnTBLAa_Atexnext (HC_XTA_Atexnext << 14)
1187#define HC_HTXnTBLAb_TOPA (HC_XTA_TOPA << 7)
1188#define HC_HTXnTBLAb_InvTOPA (HC_XTA_InvTOPA << 7)
1189#define HC_HTXnTBLAb_TOPAp5 (HC_XTA_TOPAp5 << 7)
1190#define HC_HTXnTBLAb_Adif (HC_XTA_Adif << 7)
1191#define HC_HTXnTBLAb_Fog (HC_XTA_Fog << 7)
1192#define HC_HTXnTBLAb_Acur (HC_XTA_Acur << 7)
1193#define HC_HTXnTBLAb_HTXnTBLRA (HC_XTA_HTXnTBLRA << 7)
1194#define HC_HTXnTBLAb_Atex (HC_XTA_Atex << 7)
1195#define HC_HTXnTBLAb_Atexnext (HC_XTA_Atexnext << 7)
1196#define HC_HTXnTBLAc_TOPA (HC_XTA_TOPA << 0)
1197#define HC_HTXnTBLAc_InvTOPA (HC_XTA_InvTOPA << 0)
1198#define HC_HTXnTBLAc_TOPAp5 (HC_XTA_TOPAp5 << 0)
1199#define HC_HTXnTBLAc_Adif (HC_XTA_Adif << 0)
1200#define HC_HTXnTBLAc_Fog (HC_XTA_Fog << 0)
1201#define HC_HTXnTBLAc_Acur (HC_XTA_Acur << 0)
1202#define HC_HTXnTBLAc_HTXnTBLRA (HC_XTA_HTXnTBLRA << 0)
1203#define HC_HTXnTBLAc_Atex (HC_XTA_Atex << 0)
1204#define HC_HTXnTBLAc_Atexnext (HC_XTA_Atexnext << 0)
1205/* HC_SubA_HTXnTBLRAa 0x0089
1206 */
1207#define HC_HTXnTBLRAa_MASK 0x00ff0000
1208#define HC_HTXnTBLRAb_MASK 0x0000ff00
1209#define HC_HTXnTBLRAc_MASK 0x000000ff
1210#define HC_HTXnTBLRAa_SHIFT 16
1211#define HC_HTXnTBLRAb_SHIFT 8
1212#define HC_HTXnTBLRAc_SHIFT 0
1213/* HC_SubA_HTXnTBLRFog 0x008a
1214 */
1215#define HC_HTXnTBLRFog_MASK 0x0000ff00
1216#define HC_HTXnTBLRAbias_MASK 0x000000ff
1217#define HC_HTXnTBLRFog_SHIFT 8
1218#define HC_HTXnTBLRAbias_SHIFT 0
1219/* HC_SubA_HTXnLScale 0x0094
1220 */
1221#define HC_HTXnLScale_MASK 0x0007fc00
1222#define HC_HTXnLOff_MASK 0x000001ff
1223#define HC_HTXnLScale_SHIFT 10
1224/* HC_SubA_HTXSMD 0x0000
1225 */
1226#define HC_HTXSMD_MASK 0x00000080
1227#define HC_HTXTMD_MASK 0x00000040
1228#define HC_HTXNum_MASK 0x00000038
1229#define HC_HTXTRMD_MASK 0x00000006
1230#define HC_HTXCHCLR_MASK 0x00000001
1231#define HC_HTXNum_SHIFT 3
1232
1233/* Texture Palette n
1234 */
1235#define HC_SubType_TexPalette0 0x00000000
1236#define HC_SubType_TexPalette1 0x00000001
1237#define HC_SubType_FogTable 0x00000010
1238#define HC_SubType_Stipple 0x00000014
1239/* HC_SubA_TexPalette0 0x0000
1240 */
1241#define HC_HTPnA_MASK 0xff000000
1242#define HC_HTPnR_MASK 0x00ff0000
1243#define HC_HTPnG_MASK 0x0000ff00
1244#define HC_HTPnB_MASK 0x000000ff
1245/* HC_SubA_FogTable 0x0010
1246 */
1247#define HC_HFPn3_MASK 0xff000000
1248#define HC_HFPn2_MASK 0x00ff0000
1249#define HC_HFPn1_MASK 0x0000ff00
1250#define HC_HFPn_MASK 0x000000ff
1251#define HC_HFPn3_SHIFT 24
1252#define HC_HFPn2_SHIFT 16
1253#define HC_HFPn1_SHIFT 8
1254
1255/* Auto Testing & Security
1256 */
1257#define HC_SubA_HenFIFOAT 0x0000
1258#define HC_SubA_HFBDrawFirst 0x0004
1259#define HC_SubA_HFBBasL 0x0005
1260#define HC_SubA_HFBDst 0x0006
1261/* HC_SubA_HenFIFOAT 0x0000
1262 */
1263#define HC_HenFIFOAT_MASK 0x00000020
1264#define HC_HenGEMILock_MASK 0x00000010
1265#define HC_HenFBASwap_MASK 0x00000008
1266#define HC_HenOT_MASK 0x00000004
1267#define HC_HenCMDQ_MASK 0x00000002
1268#define HC_HenTXCTSU_MASK 0x00000001
1269/* HC_SubA_HFBDrawFirst 0x0004
1270 */
1271#define HC_HFBDrawFirst_MASK 0x00000800
1272#define HC_HFBQueue_MASK 0x00000400
1273#define HC_HFBLock_MASK 0x00000200
1274#define HC_HEOF_MASK 0x00000100
1275#define HC_HFBBasH_MASK 0x000000ff
1276
1277/* GEMI Setting
1278 */
1279#define HC_SubA_HTArbRCM 0x0008
1280#define HC_SubA_HTArbRZ 0x000a
1281#define HC_SubA_HTArbWZ 0x000b
1282#define HC_SubA_HTArbRTX 0x000c
1283#define HC_SubA_HTArbRCW 0x000d
1284#define HC_SubA_HTArbE2 0x000e
1285#define HC_SubA_HArbRQCM 0x0010
1286#define HC_SubA_HArbWQCM 0x0011
1287#define HC_SubA_HGEMITout 0x0020
1288#define HC_SubA_HFthRTXD 0x0040
1289#define HC_SubA_HFthRTXA 0x0044
1290#define HC_SubA_HCMDQstL 0x0050
1291#define HC_SubA_HCMDQendL 0x0051
1292#define HC_SubA_HCMDQLen 0x0052
1293/* HC_SubA_HTArbRCM 0x0008
1294 */
1295#define HC_HTArbRCM_MASK 0x0000ffff
1296/* HC_SubA_HTArbRZ 0x000a
1297 */
1298#define HC_HTArbRZ_MASK 0x0000ffff
1299/* HC_SubA_HTArbWZ 0x000b
1300 */
1301#define HC_HTArbWZ_MASK 0x0000ffff
1302/* HC_SubA_HTArbRTX 0x000c
1303 */
1304#define HC_HTArbRTX_MASK 0x0000ffff
1305/* HC_SubA_HTArbRCW 0x000d
1306 */
1307#define HC_HTArbRCW_MASK 0x0000ffff
1308/* HC_SubA_HTArbE2 0x000e
1309 */
1310#define HC_HTArbE2_MASK 0x0000ffff
1311/* HC_SubA_HArbRQCM 0x0010
1312 */
1313#define HC_HTArbRQCM_MASK 0x0000ffff
1314/* HC_SubA_HArbWQCM 0x0011
1315 */
1316#define HC_HArbWQCM_MASK 0x0000ffff
1317/* HC_SubA_HGEMITout 0x0020
1318 */
1319#define HC_HGEMITout_MASK 0x000f0000
1320#define HC_HNPArbZC_MASK 0x0000ffff
1321#define HC_HGEMITout_SHIFT 16
1322/* HC_SubA_HFthRTXD 0x0040
1323 */
1324#define HC_HFthRTXD_MASK 0x00ff0000
1325#define HC_HFthRZD_MASK 0x0000ff00
1326#define HC_HFthWZD_MASK 0x000000ff
1327#define HC_HFthRTXD_SHIFT 16
1328#define HC_HFthRZD_SHIFT 8
1329/* HC_SubA_HFthRTXA 0x0044
1330 */
1331#define HC_HFthRTXA_MASK 0x000000ff
1332
1333/******************************************************************************
1334** Define the Halcyon Internal register access constants. For simulator only.
1335******************************************************************************/
1336#define HC_SIMA_HAGPBstL 0x0000
1337#define HC_SIMA_HAGPBendL 0x0001
1338#define HC_SIMA_HAGPCMNT 0x0002
1339#define HC_SIMA_HAGPBpL 0x0003
1340#define HC_SIMA_HAGPBpH 0x0004
1341#define HC_SIMA_HClipTB 0x0005
1342#define HC_SIMA_HClipLR 0x0006
1343#define HC_SIMA_HFPClipTL 0x0007
1344#define HC_SIMA_HFPClipBL 0x0008
1345#define HC_SIMA_HFPClipLL 0x0009
1346#define HC_SIMA_HFPClipRL 0x000a
1347#define HC_SIMA_HFPClipTBH 0x000b
1348#define HC_SIMA_HFPClipLRH 0x000c
1349#define HC_SIMA_HLP 0x000d
1350#define HC_SIMA_HLPRF 0x000e
1351#define HC_SIMA_HSolidCL 0x000f
1352#define HC_SIMA_HPixGC 0x0010
1353#define HC_SIMA_HSPXYOS 0x0011
1354#define HC_SIMA_HCmdA 0x0012
1355#define HC_SIMA_HCmdB 0x0013
1356#define HC_SIMA_HEnable 0x0014
1357#define HC_SIMA_HZWBBasL 0x0015
1358#define HC_SIMA_HZWBBasH 0x0016
1359#define HC_SIMA_HZWBType 0x0017
1360#define HC_SIMA_HZBiasL 0x0018
1361#define HC_SIMA_HZWBend 0x0019
1362#define HC_SIMA_HZWTMD 0x001a
1363#define HC_SIMA_HZWCDL 0x001b
1364#define HC_SIMA_HZWCTAGnum 0x001c
1365#define HC_SIMA_HZCYNum 0x001d
1366#define HC_SIMA_HZWCFire 0x001e
1367/* #define HC_SIMA_HSBBasL 0x001d */
1368/* #define HC_SIMA_HSBBasH 0x001e */
1369/* #define HC_SIMA_HSBFM 0x001f */
1370#define HC_SIMA_HSTREF 0x0020
1371#define HC_SIMA_HSTMD 0x0021
1372#define HC_SIMA_HABBasL 0x0022
1373#define HC_SIMA_HABBasH 0x0023
1374#define HC_SIMA_HABFM 0x0024
1375#define HC_SIMA_HATMD 0x0025
1376#define HC_SIMA_HABLCsat 0x0026
1377#define HC_SIMA_HABLCop 0x0027
1378#define HC_SIMA_HABLAsat 0x0028
1379#define HC_SIMA_HABLAop 0x0029
1380#define HC_SIMA_HABLRCa 0x002a
1381#define HC_SIMA_HABLRFCa 0x002b
1382#define HC_SIMA_HABLRCbias 0x002c
1383#define HC_SIMA_HABLRCb 0x002d
1384#define HC_SIMA_HABLRFCb 0x002e
1385#define HC_SIMA_HABLRAa 0x002f
1386#define HC_SIMA_HABLRAb 0x0030
1387#define HC_SIMA_HDBBasL 0x0031
1388#define HC_SIMA_HDBBasH 0x0032
1389#define HC_SIMA_HDBFM 0x0033
1390#define HC_SIMA_HFBBMSKL 0x0034
1391#define HC_SIMA_HROP 0x0035
1392#define HC_SIMA_HFogLF 0x0036
1393#define HC_SIMA_HFogCL 0x0037
1394#define HC_SIMA_HFogCH 0x0038
1395#define HC_SIMA_HFogStL 0x0039
1396#define HC_SIMA_HFogStH 0x003a
1397#define HC_SIMA_HFogOOdMF 0x003b
1398#define HC_SIMA_HFogOOdEF 0x003c
1399#define HC_SIMA_HFogEndL 0x003d
1400#define HC_SIMA_HFogDenst 0x003e
1401/*---- start of texture 0 setting ----
1402 */
1403#define HC_SIMA_HTX0L0BasL 0x0040
1404#define HC_SIMA_HTX0L1BasL 0x0041
1405#define HC_SIMA_HTX0L2BasL 0x0042
1406#define HC_SIMA_HTX0L3BasL 0x0043
1407#define HC_SIMA_HTX0L4BasL 0x0044
1408#define HC_SIMA_HTX0L5BasL 0x0045
1409#define HC_SIMA_HTX0L6BasL 0x0046
1410#define HC_SIMA_HTX0L7BasL 0x0047
1411#define HC_SIMA_HTX0L8BasL 0x0048
1412#define HC_SIMA_HTX0L9BasL 0x0049
1413#define HC_SIMA_HTX0LaBasL 0x004a
1414#define HC_SIMA_HTX0LbBasL 0x004b
1415#define HC_SIMA_HTX0LcBasL 0x004c
1416#define HC_SIMA_HTX0LdBasL 0x004d
1417#define HC_SIMA_HTX0LeBasL 0x004e
1418#define HC_SIMA_HTX0LfBasL 0x004f
1419#define HC_SIMA_HTX0L10BasL 0x0050
1420#define HC_SIMA_HTX0L11BasL 0x0051
1421#define HC_SIMA_HTX0L012BasH 0x0052
1422#define HC_SIMA_HTX0L345BasH 0x0053
1423#define HC_SIMA_HTX0L678BasH 0x0054
1424#define HC_SIMA_HTX0L9abBasH 0x0055
1425#define HC_SIMA_HTX0LcdeBasH 0x0056
1426#define HC_SIMA_HTX0Lf1011BasH 0x0057
1427#define HC_SIMA_HTX0L0Pit 0x0058
1428#define HC_SIMA_HTX0L1Pit 0x0059
1429#define HC_SIMA_HTX0L2Pit 0x005a
1430#define HC_SIMA_HTX0L3Pit 0x005b
1431#define HC_SIMA_HTX0L4Pit 0x005c
1432#define HC_SIMA_HTX0L5Pit 0x005d
1433#define HC_SIMA_HTX0L6Pit 0x005e
1434#define HC_SIMA_HTX0L7Pit 0x005f
1435#define HC_SIMA_HTX0L8Pit 0x0060
1436#define HC_SIMA_HTX0L9Pit 0x0061
1437#define HC_SIMA_HTX0LaPit 0x0062
1438#define HC_SIMA_HTX0LbPit 0x0063
1439#define HC_SIMA_HTX0LcPit 0x0064
1440#define HC_SIMA_HTX0LdPit 0x0065
1441#define HC_SIMA_HTX0LePit 0x0066
1442#define HC_SIMA_HTX0LfPit 0x0067
1443#define HC_SIMA_HTX0L10Pit 0x0068
1444#define HC_SIMA_HTX0L11Pit 0x0069
1445#define HC_SIMA_HTX0L0_5WE 0x006a
1446#define HC_SIMA_HTX0L6_bWE 0x006b
1447#define HC_SIMA_HTX0Lc_11WE 0x006c
1448#define HC_SIMA_HTX0L0_5HE 0x006d
1449#define HC_SIMA_HTX0L6_bHE 0x006e
1450#define HC_SIMA_HTX0Lc_11HE 0x006f
1451#define HC_SIMA_HTX0L0OS 0x0070
1452#define HC_SIMA_HTX0TB 0x0071
1453#define HC_SIMA_HTX0MPMD 0x0072
1454#define HC_SIMA_HTX0CLODu 0x0073
1455#define HC_SIMA_HTX0FM 0x0074
1456#define HC_SIMA_HTX0TRCH 0x0075
1457#define HC_SIMA_HTX0TRCL 0x0076
1458#define HC_SIMA_HTX0TBC 0x0077
1459#define HC_SIMA_HTX0TRAH 0x0078
1460#define HC_SIMA_HTX0TBLCsat 0x0079
1461#define HC_SIMA_HTX0TBLCop 0x007a
1462#define HC_SIMA_HTX0TBLMPfog 0x007b
1463#define HC_SIMA_HTX0TBLAsat 0x007c
1464#define HC_SIMA_HTX0TBLRCa 0x007d
1465#define HC_SIMA_HTX0TBLRCb 0x007e
1466#define HC_SIMA_HTX0TBLRCc 0x007f
1467#define HC_SIMA_HTX0TBLRCbias 0x0080
1468#define HC_SIMA_HTX0TBLRAa 0x0081
1469#define HC_SIMA_HTX0TBLRFog 0x0082
1470#define HC_SIMA_HTX0BumpM00 0x0083
1471#define HC_SIMA_HTX0BumpM01 0x0084
1472#define HC_SIMA_HTX0BumpM10 0x0085
1473#define HC_SIMA_HTX0BumpM11 0x0086
1474#define HC_SIMA_HTX0LScale 0x0087
1475/*---- end of texture 0 setting ---- 0x008f
1476 */
1477#define HC_SIMA_TX0TX1_OFF 0x0050
1478/*---- start of texture 1 setting ----
1479 */
1480#define HC_SIMA_HTX1L0BasL (HC_SIMA_HTX0L0BasL + HC_SIMA_TX0TX1_OFF)
1481#define HC_SIMA_HTX1L1BasL (HC_SIMA_HTX0L1BasL + HC_SIMA_TX0TX1_OFF)
1482#define HC_SIMA_HTX1L2BasL (HC_SIMA_HTX0L2BasL + HC_SIMA_TX0TX1_OFF)
1483#define HC_SIMA_HTX1L3BasL (HC_SIMA_HTX0L3BasL + HC_SIMA_TX0TX1_OFF)
1484#define HC_SIMA_HTX1L4BasL (HC_SIMA_HTX0L4BasL + HC_SIMA_TX0TX1_OFF)
1485#define HC_SIMA_HTX1L5BasL (HC_SIMA_HTX0L5BasL + HC_SIMA_TX0TX1_OFF)
1486#define HC_SIMA_HTX1L6BasL (HC_SIMA_HTX0L6BasL + HC_SIMA_TX0TX1_OFF)
1487#define HC_SIMA_HTX1L7BasL (HC_SIMA_HTX0L7BasL + HC_SIMA_TX0TX1_OFF)
1488#define HC_SIMA_HTX1L8BasL (HC_SIMA_HTX0L8BasL + HC_SIMA_TX0TX1_OFF)
1489#define HC_SIMA_HTX1L9BasL (HC_SIMA_HTX0L9BasL + HC_SIMA_TX0TX1_OFF)
1490#define HC_SIMA_HTX1LaBasL (HC_SIMA_HTX0LaBasL + HC_SIMA_TX0TX1_OFF)
1491#define HC_SIMA_HTX1LbBasL (HC_SIMA_HTX0LbBasL + HC_SIMA_TX0TX1_OFF)
1492#define HC_SIMA_HTX1LcBasL (HC_SIMA_HTX0LcBasL + HC_SIMA_TX0TX1_OFF)
1493#define HC_SIMA_HTX1LdBasL (HC_SIMA_HTX0LdBasL + HC_SIMA_TX0TX1_OFF)
1494#define HC_SIMA_HTX1LeBasL (HC_SIMA_HTX0LeBasL + HC_SIMA_TX0TX1_OFF)
1495#define HC_SIMA_HTX1LfBasL (HC_SIMA_HTX0LfBasL + HC_SIMA_TX0TX1_OFF)
1496#define HC_SIMA_HTX1L10BasL (HC_SIMA_HTX0L10BasL + HC_SIMA_TX0TX1_OFF)
1497#define HC_SIMA_HTX1L11BasL (HC_SIMA_HTX0L11BasL + HC_SIMA_TX0TX1_OFF)
1498#define HC_SIMA_HTX1L012BasH (HC_SIMA_HTX0L012BasH + HC_SIMA_TX0TX1_OFF)
1499#define HC_SIMA_HTX1L345BasH (HC_SIMA_HTX0L345BasH + HC_SIMA_TX0TX1_OFF)
1500#define HC_SIMA_HTX1L678BasH (HC_SIMA_HTX0L678BasH + HC_SIMA_TX0TX1_OFF)
1501#define HC_SIMA_HTX1L9abBasH (HC_SIMA_HTX0L9abBasH + HC_SIMA_TX0TX1_OFF)
1502#define HC_SIMA_HTX1LcdeBasH (HC_SIMA_HTX0LcdeBasH + HC_SIMA_TX0TX1_OFF)
1503#define HC_SIMA_HTX1Lf1011BasH (HC_SIMA_HTX0Lf1011BasH + HC_SIMA_TX0TX1_OFF)
1504#define HC_SIMA_HTX1L0Pit (HC_SIMA_HTX0L0Pit + HC_SIMA_TX0TX1_OFF)
1505#define HC_SIMA_HTX1L1Pit (HC_SIMA_HTX0L1Pit + HC_SIMA_TX0TX1_OFF)
1506#define HC_SIMA_HTX1L2Pit (HC_SIMA_HTX0L2Pit + HC_SIMA_TX0TX1_OFF)
1507#define HC_SIMA_HTX1L3Pit (HC_SIMA_HTX0L3Pit + HC_SIMA_TX0TX1_OFF)
1508#define HC_SIMA_HTX1L4Pit (HC_SIMA_HTX0L4Pit + HC_SIMA_TX0TX1_OFF)
1509#define HC_SIMA_HTX1L5Pit (HC_SIMA_HTX0L5Pit + HC_SIMA_TX0TX1_OFF)
1510#define HC_SIMA_HTX1L6Pit (HC_SIMA_HTX0L6Pit + HC_SIMA_TX0TX1_OFF)
1511#define HC_SIMA_HTX1L7Pit (HC_SIMA_HTX0L7Pit + HC_SIMA_TX0TX1_OFF)
1512#define HC_SIMA_HTX1L8Pit (HC_SIMA_HTX0L8Pit + HC_SIMA_TX0TX1_OFF)
1513#define HC_SIMA_HTX1L9Pit (HC_SIMA_HTX0L9Pit + HC_SIMA_TX0TX1_OFF)
1514#define HC_SIMA_HTX1LaPit (HC_SIMA_HTX0LaPit + HC_SIMA_TX0TX1_OFF)
1515#define HC_SIMA_HTX1LbPit (HC_SIMA_HTX0LbPit + HC_SIMA_TX0TX1_OFF)
1516#define HC_SIMA_HTX1LcPit (HC_SIMA_HTX0LcPit + HC_SIMA_TX0TX1_OFF)
1517#define HC_SIMA_HTX1LdPit (HC_SIMA_HTX0LdPit + HC_SIMA_TX0TX1_OFF)
1518#define HC_SIMA_HTX1LePit (HC_SIMA_HTX0LePit + HC_SIMA_TX0TX1_OFF)
1519#define HC_SIMA_HTX1LfPit (HC_SIMA_HTX0LfPit + HC_SIMA_TX0TX1_OFF)
1520#define HC_SIMA_HTX1L10Pit (HC_SIMA_HTX0L10Pit + HC_SIMA_TX0TX1_OFF)
1521#define HC_SIMA_HTX1L11Pit (HC_SIMA_HTX0L11Pit + HC_SIMA_TX0TX1_OFF)
1522#define HC_SIMA_HTX1L0_5WE (HC_SIMA_HTX0L0_5WE + HC_SIMA_TX0TX1_OFF)
1523#define HC_SIMA_HTX1L6_bWE (HC_SIMA_HTX0L6_bWE + HC_SIMA_TX0TX1_OFF)
1524#define HC_SIMA_HTX1Lc_11WE (HC_SIMA_HTX0Lc_11WE + HC_SIMA_TX0TX1_OFF)
1525#define HC_SIMA_HTX1L0_5HE (HC_SIMA_HTX0L0_5HE + HC_SIMA_TX0TX1_OFF)
1526#define HC_SIMA_HTX1L6_bHE (HC_SIMA_HTX0L6_bHE + HC_SIMA_TX0TX1_OFF)
1527#define HC_SIMA_HTX1Lc_11HE (HC_SIMA_HTX0Lc_11HE + HC_SIMA_TX0TX1_OFF)
1528#define HC_SIMA_HTX1L0OS (HC_SIMA_HTX0L0OS + HC_SIMA_TX0TX1_OFF)
1529#define HC_SIMA_HTX1TB (HC_SIMA_HTX0TB + HC_SIMA_TX0TX1_OFF)
1530#define HC_SIMA_HTX1MPMD (HC_SIMA_HTX0MPMD + HC_SIMA_TX0TX1_OFF)
1531#define HC_SIMA_HTX1CLODu (HC_SIMA_HTX0CLODu + HC_SIMA_TX0TX1_OFF)
1532#define HC_SIMA_HTX1FM (HC_SIMA_HTX0FM + HC_SIMA_TX0TX1_OFF)
1533#define HC_SIMA_HTX1TRCH (HC_SIMA_HTX0TRCH + HC_SIMA_TX0TX1_OFF)
1534#define HC_SIMA_HTX1TRCL (HC_SIMA_HTX0TRCL + HC_SIMA_TX0TX1_OFF)
1535#define HC_SIMA_HTX1TBC (HC_SIMA_HTX0TBC + HC_SIMA_TX0TX1_OFF)
1536#define HC_SIMA_HTX1TRAH (HC_SIMA_HTX0TRAH + HC_SIMA_TX0TX1_OFF)
1537#define HC_SIMA_HTX1LTC (HC_SIMA_HTX0LTC + HC_SIMA_TX0TX1_OFF)
1538#define HC_SIMA_HTX1LTA (HC_SIMA_HTX0LTA + HC_SIMA_TX0TX1_OFF)
1539#define HC_SIMA_HTX1TBLCsat (HC_SIMA_HTX0TBLCsat + HC_SIMA_TX0TX1_OFF)
1540#define HC_SIMA_HTX1TBLCop (HC_SIMA_HTX0TBLCop + HC_SIMA_TX0TX1_OFF)
1541#define HC_SIMA_HTX1TBLMPfog (HC_SIMA_HTX0TBLMPfog + HC_SIMA_TX0TX1_OFF)
1542#define HC_SIMA_HTX1TBLAsat (HC_SIMA_HTX0TBLAsat + HC_SIMA_TX0TX1_OFF)
1543#define HC_SIMA_HTX1TBLRCa (HC_SIMA_HTX0TBLRCa + HC_SIMA_TX0TX1_OFF)
1544#define HC_SIMA_HTX1TBLRCb (HC_SIMA_HTX0TBLRCb + HC_SIMA_TX0TX1_OFF)
1545#define HC_SIMA_HTX1TBLRCc (HC_SIMA_HTX0TBLRCc + HC_SIMA_TX0TX1_OFF)
1546#define HC_SIMA_HTX1TBLRCbias (HC_SIMA_HTX0TBLRCbias + HC_SIMA_TX0TX1_OFF)
1547#define HC_SIMA_HTX1TBLRAa (HC_SIMA_HTX0TBLRAa + HC_SIMA_TX0TX1_OFF)
1548#define HC_SIMA_HTX1TBLRFog (HC_SIMA_HTX0TBLRFog + HC_SIMA_TX0TX1_OFF)
1549#define HC_SIMA_HTX1BumpM00 (HC_SIMA_HTX0BumpM00 + HC_SIMA_TX0TX1_OFF)
1550#define HC_SIMA_HTX1BumpM01 (HC_SIMA_HTX0BumpM01 + HC_SIMA_TX0TX1_OFF)
1551#define HC_SIMA_HTX1BumpM10 (HC_SIMA_HTX0BumpM10 + HC_SIMA_TX0TX1_OFF)
1552#define HC_SIMA_HTX1BumpM11 (HC_SIMA_HTX0BumpM11 + HC_SIMA_TX0TX1_OFF)
1553#define HC_SIMA_HTX1LScale (HC_SIMA_HTX0LScale + HC_SIMA_TX0TX1_OFF)
1554/*---- end of texture 1 setting ---- 0xaf
1555 */
1556#define HC_SIMA_HTXSMD 0x00b0
1557#define HC_SIMA_HenFIFOAT 0x00b1
1558#define HC_SIMA_HFBDrawFirst 0x00b2
1559#define HC_SIMA_HFBBasL 0x00b3
1560#define HC_SIMA_HTArbRCM 0x00b4
1561#define HC_SIMA_HTArbRZ 0x00b5
1562#define HC_SIMA_HTArbWZ 0x00b6
1563#define HC_SIMA_HTArbRTX 0x00b7
1564#define HC_SIMA_HTArbRCW 0x00b8
1565#define HC_SIMA_HTArbE2 0x00b9
1566#define HC_SIMA_HGEMITout 0x00ba
1567#define HC_SIMA_HFthRTXD 0x00bb
1568#define HC_SIMA_HFthRTXA 0x00bc
1569/* Define the texture palette 0
1570 */
1571#define HC_SIMA_HTP0 0x0100
1572#define HC_SIMA_HTP1 0x0200
1573#define HC_SIMA_FOGTABLE 0x0300
1574#define HC_SIMA_STIPPLE 0x0400
1575#define HC_SIMA_HE3Fire 0x0440
1576#define HC_SIMA_TRANS_SET 0x0441
1577#define HC_SIMA_HREngSt 0x0442
1578#define HC_SIMA_HRFIFOempty 0x0443
1579#define HC_SIMA_HRFIFOfull 0x0444
1580#define HC_SIMA_HRErr 0x0445
1581#define HC_SIMA_FIFOstatus 0x0446
1582
1583/******************************************************************************
1584** Define the AGP command header.
1585******************************************************************************/
1586#define HC_ACMD_MASK 0xfe000000
1587#define HC_ACMD_SUB_MASK 0x0c000000
1588#define HC_ACMD_HCmdA 0xee000000
1589#define HC_ACMD_HCmdB 0xec000000
1590#define HC_ACMD_HCmdC 0xea000000
1591#define HC_ACMD_H1 0xf0000000
1592#define HC_ACMD_H2 0xf2000000
1593#define HC_ACMD_H3 0xf4000000
1594#define HC_ACMD_H4 0xf6000000
1595
1596#define HC_ACMD_H1IO_MASK 0x000001ff
1597#define HC_ACMD_H2IO1_MASK 0x001ff000
1598#define HC_ACMD_H2IO2_MASK 0x000001ff
1599#define HC_ACMD_H2IO1_SHIFT 12
1600#define HC_ACMD_H2IO2_SHIFT 0
1601#define HC_ACMD_H3IO_MASK 0x000001ff
1602#define HC_ACMD_H3COUNT_MASK 0x01fff000
1603#define HC_ACMD_H3COUNT_SHIFT 12
1604#define HC_ACMD_H4ID_MASK 0x000001ff
1605#define HC_ACMD_H4COUNT_MASK 0x01fffe00
1606#define HC_ACMD_H4COUNT_SHIFT 9
1607
1608/********************************************************************************
1609** Define Header
1610********************************************************************************/
1611#define HC_HEADER2 0xF210F110
1612
1613/********************************************************************************
1614** Define Dummy Value
1615********************************************************************************/
1616#define HC_DUMMY 0xCCCCCCCC
1617/********************************************************************************
1618** Define for DMA use
1619********************************************************************************/
1620#define HALCYON_HEADER2 0XF210F110
1621#define HALCYON_FIRECMD 0XEE100000
1622#define HALCYON_FIREMASK 0XFFF00000
1623#define HALCYON_CMDB 0XEC000000
1624#define HALCYON_CMDBMASK 0XFFFE0000
1625#define HALCYON_SUB_ADDR0 0X00000000
1626#define HALCYON_HEADER1MASK 0XFFFFFC00
1627#define HALCYON_HEADER1 0XF0000000
1628#define HC_SubA_HAGPBstL 0x0060
1629#define HC_SubA_HAGPBendL 0x0061
1630#define HC_SubA_HAGPCMNT 0x0062
1631#define HC_SubA_HAGPBpL 0x0063
1632#define HC_SubA_HAGPBpH 0x0064
1633#define HC_HAGPCMNT_MASK 0x00800000
1634#define HC_HCmdErrClr_MASK 0x00400000
1635#define HC_HAGPBendH_MASK 0x0000ff00
1636#define HC_HAGPBstH_MASK 0x000000ff
1637#define HC_HAGPBendH_SHIFT 8
1638#define HC_HAGPBstH_SHIFT 0
1639#define HC_HAGPBpL_MASK 0x00fffffc
1640#define HC_HAGPBpID_MASK 0x00000003
1641#define HC_HAGPBpID_PAUSE 0x00000000
1642#define HC_HAGPBpID_JUMP 0x00000001
1643#define HC_HAGPBpID_STOP 0x00000002
1644#define HC_HAGPBpH_MASK 0x00ffffff
1645
1646
1647#define VIA_VIDEO_HEADER5 0xFE040000
1648#define VIA_VIDEO_HEADER6 0xFE050000
1649#define VIA_VIDEO_HEADER7 0xFE060000
1650#define VIA_VIDEOMASK 0xFFFF0000
1651#endif
diff --git a/drivers/char/drm/via_dma.c b/drivers/char/drm/via_dma.c
new file mode 100644
index 000000000000..4f60f7f4193d
--- /dev/null
+++ b/drivers/char/drm/via_dma.c
@@ -0,0 +1,741 @@
1/* via_dma.c -- DMA support for the VIA Unichrome/Pro
2 *
3 * Copyright 2003 Tungsten Graphics, Inc., Cedar Park, Texas.
4 * All Rights Reserved.
5 *
6 * Copyright 2004 Digeo, Inc., Palo Alto, CA, U.S.A.
7 * All Rights Reserved.
8 *
9 * Copyright 2004 The Unichrome project.
10 * All Rights Reserved.
11 *
12 * Permission is hereby granted, free of charge, to any person obtaining a
13 * copy of this software and associated documentation files (the "Software"),
14 * to deal in the Software without restriction, including without limitation
15 * the rights to use, copy, modify, merge, publish, distribute, sub license,
16 * and/or sell copies of the Software, and to permit persons to whom the
17 * Software is furnished to do so, subject to the following conditions:
18 *
19 * The above copyright notice and this permission notice (including the
20 * next paragraph) shall be included in all copies or substantial portions
21 * of the Software.
22 *
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
26 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
27 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
28 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
29 * USE OR OTHER DEALINGS IN THE SOFTWARE.
30 *
31 * Authors:
32 * Tungsten Graphics,
33 * Erdi Chen,
34 * Thomas Hellstrom.
35 */
36
37#include "drmP.h"
38#include "drm.h"
39#include "via_drm.h"
40#include "via_drv.h"
41#include "via_3d_reg.h"
42
43#define CMDBUF_ALIGNMENT_SIZE (0x100)
44#define CMDBUF_ALIGNMENT_MASK (0x0ff)
45
46/* defines for VIA 3D registers */
47#define VIA_REG_STATUS 0x400
48#define VIA_REG_TRANSET 0x43C
49#define VIA_REG_TRANSPACE 0x440
50
51/* VIA_REG_STATUS(0x400): Engine Status */
52#define VIA_CMD_RGTR_BUSY 0x00000080 /* Command Regulator is busy */
53#define VIA_2D_ENG_BUSY 0x00000001 /* 2D Engine is busy */
54#define VIA_3D_ENG_BUSY 0x00000002 /* 3D Engine is busy */
55#define VIA_VR_QUEUE_BUSY 0x00020000 /* Virtual Queue is busy */
56
57#define SetReg2DAGP(nReg, nData) { \
58 *((uint32_t *)(vb)) = ((nReg) >> 2) | HALCYON_HEADER1; \
59 *((uint32_t *)(vb) + 1) = (nData); \
60 vb = ((uint32_t *)vb) + 2; \
61 dev_priv->dma_low +=8; \
62}
63
64#define via_flush_write_combine() DRM_MEMORYBARRIER()
65
66#define VIA_OUT_RING_QW(w1,w2) \
67 *vb++ = (w1); \
68 *vb++ = (w2); \
69 dev_priv->dma_low += 8;
70
71static void via_cmdbuf_start(drm_via_private_t * dev_priv);
72static void via_cmdbuf_pause(drm_via_private_t * dev_priv);
73static void via_cmdbuf_reset(drm_via_private_t * dev_priv);
74static void via_cmdbuf_rewind(drm_via_private_t * dev_priv);
75static int via_wait_idle(drm_via_private_t * dev_priv);
76static void via_pad_cache(drm_via_private_t *dev_priv, int qwords);
77
78
79/*
80 * Free space in command buffer.
81 */
82
83static uint32_t
84via_cmdbuf_space(drm_via_private_t *dev_priv)
85{
86 uint32_t agp_base = dev_priv->dma_offset +
87 (uint32_t) dev_priv->agpAddr;
88 uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base;
89
90 return ((hw_addr <= dev_priv->dma_low) ?
91 (dev_priv->dma_high + hw_addr - dev_priv->dma_low) :
92 (hw_addr - dev_priv->dma_low));
93}
94
95/*
96 * How much does the command regulator lag behind?
97 */
98
99static uint32_t
100via_cmdbuf_lag(drm_via_private_t *dev_priv)
101{
102 uint32_t agp_base = dev_priv->dma_offset +
103 (uint32_t) dev_priv->agpAddr;
104 uint32_t hw_addr = *(dev_priv->hw_addr_ptr) - agp_base;
105
106 return ((hw_addr <= dev_priv->dma_low) ?
107 (dev_priv->dma_low - hw_addr) :
108 (dev_priv->dma_wrap + dev_priv->dma_low - hw_addr));
109}
110
111/*
112 * Check that the given size fits in the buffer, otherwise wait.
113 */
114
115static inline int
116via_cmdbuf_wait(drm_via_private_t * dev_priv, unsigned int size)
117{
118 uint32_t agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
119 uint32_t cur_addr, hw_addr, next_addr;
120 volatile uint32_t *hw_addr_ptr;
121 uint32_t count;
122 hw_addr_ptr = dev_priv->hw_addr_ptr;
123 cur_addr = dev_priv->dma_low;
124 next_addr = cur_addr + size + 512*1024;
125 count = 1000000;
126 do {
127 hw_addr = *hw_addr_ptr - agp_base;
128 if (count-- == 0) {
129 DRM_ERROR("via_cmdbuf_wait timed out hw %x cur_addr %x next_addr %x\n",
130 hw_addr, cur_addr, next_addr);
131 return -1;
132 }
133 } while ((cur_addr < hw_addr) && (next_addr >= hw_addr));
134 return 0;
135}
136
137
138/*
139 * Checks whether buffer head has reach the end. Rewind the ring buffer
140 * when necessary.
141 *
142 * Returns virtual pointer to ring buffer.
143 */
144
145static inline uint32_t *via_check_dma(drm_via_private_t * dev_priv,
146 unsigned int size)
147{
148 if ((dev_priv->dma_low + size + 4*CMDBUF_ALIGNMENT_SIZE) > dev_priv->dma_high) {
149 via_cmdbuf_rewind(dev_priv);
150 }
151 if (via_cmdbuf_wait(dev_priv, size) != 0) {
152 return NULL;
153 }
154
155 return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low);
156}
157
158int via_dma_cleanup(drm_device_t * dev)
159{
160 if (dev->dev_private) {
161 drm_via_private_t *dev_priv =
162 (drm_via_private_t *) dev->dev_private;
163
164 if (dev_priv->ring.virtual_start) {
165 via_cmdbuf_reset(dev_priv);
166
167 drm_core_ioremapfree(&dev_priv->ring.map, dev);
168 dev_priv->ring.virtual_start = NULL;
169 }
170
171 }
172
173 return 0;
174}
175
176static int via_initialize(drm_device_t * dev,
177 drm_via_private_t * dev_priv,
178 drm_via_dma_init_t * init)
179{
180 if (!dev_priv || !dev_priv->mmio) {
181 DRM_ERROR("via_dma_init called before via_map_init\n");
182 return DRM_ERR(EFAULT);
183 }
184
185 if (dev_priv->ring.virtual_start != NULL) {
186 DRM_ERROR("%s called again without calling cleanup\n",
187 __FUNCTION__);
188 return DRM_ERR(EFAULT);
189 }
190
191 if (!dev->agp || !dev->agp->base) {
192 DRM_ERROR("%s called with no agp memory available\n",
193 __FUNCTION__);
194 return DRM_ERR(EFAULT);
195 }
196
197 dev_priv->ring.map.offset = dev->agp->base + init->offset;
198 dev_priv->ring.map.size = init->size;
199 dev_priv->ring.map.type = 0;
200 dev_priv->ring.map.flags = 0;
201 dev_priv->ring.map.mtrr = 0;
202
203 drm_core_ioremap(&dev_priv->ring.map, dev);
204
205 if (dev_priv->ring.map.handle == NULL) {
206 via_dma_cleanup(dev);
207 DRM_ERROR("can not ioremap virtual address for"
208 " ring buffer\n");
209 return DRM_ERR(ENOMEM);
210 }
211
212 dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
213
214 dev_priv->dma_ptr = dev_priv->ring.virtual_start;
215 dev_priv->dma_low = 0;
216 dev_priv->dma_high = init->size;
217 dev_priv->dma_wrap = init->size;
218 dev_priv->dma_offset = init->offset;
219 dev_priv->last_pause_ptr = NULL;
220 dev_priv->hw_addr_ptr = dev_priv->mmio->handle + init->reg_pause_addr;
221
222 via_cmdbuf_start(dev_priv);
223
224 return 0;
225}
226
227int via_dma_init(DRM_IOCTL_ARGS)
228{
229 DRM_DEVICE;
230 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
231 drm_via_dma_init_t init;
232 int retcode = 0;
233
234 DRM_COPY_FROM_USER_IOCTL(init, (drm_via_dma_init_t __user *) data,
235 sizeof(init));
236
237 switch (init.func) {
238 case VIA_INIT_DMA:
239 if (!capable(CAP_SYS_ADMIN))
240 retcode = DRM_ERR(EPERM);
241 else
242 retcode = via_initialize(dev, dev_priv, &init);
243 break;
244 case VIA_CLEANUP_DMA:
245 if (!capable(CAP_SYS_ADMIN))
246 retcode = DRM_ERR(EPERM);
247 else
248 retcode = via_dma_cleanup(dev);
249 break;
250 case VIA_DMA_INITIALIZED:
251 retcode = (dev_priv->ring.virtual_start != NULL) ?
252 0: DRM_ERR( EFAULT );
253 break;
254 default:
255 retcode = DRM_ERR(EINVAL);
256 break;
257 }
258
259 return retcode;
260}
261
262
263
264static int via_dispatch_cmdbuffer(drm_device_t * dev, drm_via_cmdbuffer_t * cmd)
265{
266 drm_via_private_t *dev_priv;
267 uint32_t *vb;
268 int ret;
269
270 dev_priv = (drm_via_private_t *) dev->dev_private;
271
272 if (dev_priv->ring.virtual_start == NULL) {
273 DRM_ERROR("%s called without initializing AGP ring buffer.\n",
274 __FUNCTION__);
275 return DRM_ERR(EFAULT);
276 }
277
278 if (cmd->size > VIA_PCI_BUF_SIZE) {
279 return DRM_ERR(ENOMEM);
280 }
281
282
283 if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
284 return DRM_ERR(EFAULT);
285
286 /*
287 * Running this function on AGP memory is dead slow. Therefore
288 * we run it on a temporary cacheable system memory buffer and
289 * copy it to AGP memory when ready.
290 */
291
292
293 if ((ret = via_verify_command_stream((uint32_t *)dev_priv->pci_buf, cmd->size, dev, 1))) {
294 return ret;
295 }
296
297
298 vb = via_check_dma(dev_priv, (cmd->size < 0x100) ? 0x102 : cmd->size);
299 if (vb == NULL) {
300 return DRM_ERR(EAGAIN);
301 }
302
303 memcpy(vb, dev_priv->pci_buf, cmd->size);
304
305 dev_priv->dma_low += cmd->size;
306
307 /*
308 * Small submissions somehow stalls the CPU. (AGP cache effects?)
309 * pad to greater size.
310 */
311
312 if (cmd->size < 0x100)
313 via_pad_cache(dev_priv,(0x100 - cmd->size) >> 3);
314 via_cmdbuf_pause(dev_priv);
315
316 return 0;
317}
318
319int via_driver_dma_quiescent(drm_device_t * dev)
320{
321 drm_via_private_t *dev_priv = dev->dev_private;
322
323 if (!via_wait_idle(dev_priv)) {
324 return DRM_ERR(EBUSY);
325 }
326 return 0;
327}
328
329int via_flush_ioctl(DRM_IOCTL_ARGS)
330{
331 DRM_DEVICE;
332
333 LOCK_TEST_WITH_RETURN( dev, filp );
334
335 return via_driver_dma_quiescent(dev);
336}
337
338int via_cmdbuffer(DRM_IOCTL_ARGS)
339{
340 DRM_DEVICE;
341 drm_via_cmdbuffer_t cmdbuf;
342 int ret;
343
344 LOCK_TEST_WITH_RETURN( dev, filp );
345
346 DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t __user *) data,
347 sizeof(cmdbuf));
348
349 DRM_DEBUG("via cmdbuffer, buf %p size %lu\n", cmdbuf.buf, cmdbuf.size);
350
351 ret = via_dispatch_cmdbuffer(dev, &cmdbuf);
352 if (ret) {
353 return ret;
354 }
355
356 return 0;
357}
358
359extern int
360via_parse_command_stream(drm_device_t *dev, const uint32_t * buf, unsigned int size);
361static int via_dispatch_pci_cmdbuffer(drm_device_t * dev,
362 drm_via_cmdbuffer_t * cmd)
363{
364 drm_via_private_t *dev_priv = dev->dev_private;
365 int ret;
366
367 if (cmd->size > VIA_PCI_BUF_SIZE) {
368 return DRM_ERR(ENOMEM);
369 }
370 if (DRM_COPY_FROM_USER(dev_priv->pci_buf, cmd->buf, cmd->size))
371 return DRM_ERR(EFAULT);
372
373 if ((ret = via_verify_command_stream((uint32_t *)dev_priv->pci_buf, cmd->size, dev, 0))) {
374 return ret;
375 }
376
377 ret = via_parse_command_stream(dev, (const uint32_t *)dev_priv->pci_buf, cmd->size);
378 return ret;
379}
380
381int via_pci_cmdbuffer(DRM_IOCTL_ARGS)
382{
383 DRM_DEVICE;
384 drm_via_cmdbuffer_t cmdbuf;
385 int ret;
386
387 LOCK_TEST_WITH_RETURN( dev, filp );
388
389 DRM_COPY_FROM_USER_IOCTL(cmdbuf, (drm_via_cmdbuffer_t __user *) data,
390 sizeof(cmdbuf));
391
392 DRM_DEBUG("via_pci_cmdbuffer, buf %p size %lu\n", cmdbuf.buf,
393 cmdbuf.size);
394
395 ret = via_dispatch_pci_cmdbuffer(dev, &cmdbuf);
396 if (ret) {
397 return ret;
398 }
399
400 return 0;
401}
402
403
404static inline uint32_t *via_align_buffer(drm_via_private_t * dev_priv,
405 uint32_t * vb, int qw_count)
406{
407 for (; qw_count > 0; --qw_count) {
408 VIA_OUT_RING_QW(HC_DUMMY, HC_DUMMY);
409 }
410 return vb;
411}
412
413
414/*
415 * This function is used internally by ring buffer mangement code.
416 *
417 * Returns virtual pointer to ring buffer.
418 */
419static inline uint32_t *via_get_dma(drm_via_private_t * dev_priv)
420{
421 return (uint32_t *) (dev_priv->dma_ptr + dev_priv->dma_low);
422}
423
424/*
425 * Hooks a segment of data into the tail of the ring-buffer by
426 * modifying the pause address stored in the buffer itself. If
427 * the regulator has already paused, restart it.
428 */
429static int via_hook_segment(drm_via_private_t *dev_priv,
430 uint32_t pause_addr_hi, uint32_t pause_addr_lo,
431 int no_pci_fire)
432{
433 int paused, count;
434 volatile uint32_t *paused_at = dev_priv->last_pause_ptr;
435
436 via_flush_write_combine();
437 while(! *(via_get_dma(dev_priv)-1));
438 *dev_priv->last_pause_ptr = pause_addr_lo;
439 via_flush_write_combine();
440
441 /*
442 * The below statement is inserted to really force the flush.
443 * Not sure it is needed.
444 */
445
446 while(! *dev_priv->last_pause_ptr);
447 dev_priv->last_pause_ptr = via_get_dma(dev_priv) - 1;
448 while(! *dev_priv->last_pause_ptr);
449
450
451 paused = 0;
452 count = 20;
453
454 while (!(paused = (VIA_READ(0x41c) & 0x80000000)) && count--);
455 if ((count <= 8) && (count >= 0)) {
456 uint32_t rgtr, ptr;
457 rgtr = *(dev_priv->hw_addr_ptr);
458 ptr = ((char *)dev_priv->last_pause_ptr - dev_priv->dma_ptr) +
459 dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4 -
460 CMDBUF_ALIGNMENT_SIZE;
461 if (rgtr <= ptr) {
462 DRM_ERROR("Command regulator\npaused at count %d, address %x, "
463 "while current pause address is %x.\n"
464 "Please mail this message to "
465 "<unichrome-devel@lists.sourceforge.net>\n",
466 count, rgtr, ptr);
467 }
468 }
469
470 if (paused && !no_pci_fire) {
471 uint32_t rgtr,ptr;
472 uint32_t ptr_low;
473
474 count = 1000000;
475 while ((VIA_READ(VIA_REG_STATUS) & VIA_CMD_RGTR_BUSY) && count--);
476
477 rgtr = *(dev_priv->hw_addr_ptr);
478 ptr = ((char *)paused_at - dev_priv->dma_ptr) +
479 dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr + 4;
480
481
482 ptr_low = (ptr > 3*CMDBUF_ALIGNMENT_SIZE) ?
483 ptr - 3*CMDBUF_ALIGNMENT_SIZE : 0;
484 if (rgtr <= ptr && rgtr >= ptr_low) {
485 VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
486 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
487 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
488 }
489 }
490 return paused;
491}
492
493
494
495static int via_wait_idle(drm_via_private_t * dev_priv)
496{
497 int count = 10000000;
498 while (count-- && (VIA_READ(VIA_REG_STATUS) &
499 (VIA_CMD_RGTR_BUSY | VIA_2D_ENG_BUSY |
500 VIA_3D_ENG_BUSY))) ;
501 return count;
502}
503
504static uint32_t *via_align_cmd(drm_via_private_t * dev_priv, uint32_t cmd_type,
505 uint32_t addr, uint32_t *cmd_addr_hi,
506 uint32_t *cmd_addr_lo,
507 int skip_wait)
508{
509 uint32_t agp_base;
510 uint32_t cmd_addr, addr_lo, addr_hi;
511 uint32_t *vb;
512 uint32_t qw_pad_count;
513
514 if (!skip_wait)
515 via_cmdbuf_wait(dev_priv, 2*CMDBUF_ALIGNMENT_SIZE);
516
517 vb = via_get_dma(dev_priv);
518 VIA_OUT_RING_QW( HC_HEADER2 | ((VIA_REG_TRANSET >> 2) << 12) |
519 (VIA_REG_TRANSPACE >> 2), HC_ParaType_PreCR << 16);
520 agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
521 qw_pad_count = (CMDBUF_ALIGNMENT_SIZE >> 3) -
522 ((dev_priv->dma_low & CMDBUF_ALIGNMENT_MASK) >> 3);
523
524
525 cmd_addr = (addr) ? addr :
526 agp_base + dev_priv->dma_low - 8 + (qw_pad_count << 3);
527 addr_lo = ((HC_SubA_HAGPBpL << 24) | (cmd_type & HC_HAGPBpID_MASK) |
528 (cmd_addr & HC_HAGPBpL_MASK));
529 addr_hi = ((HC_SubA_HAGPBpH << 24) | (cmd_addr >> 24));
530
531 vb = via_align_buffer(dev_priv, vb, qw_pad_count - 1);
532 VIA_OUT_RING_QW(*cmd_addr_hi = addr_hi,
533 *cmd_addr_lo = addr_lo);
534 return vb;
535}
536
537
538
539
540static void via_cmdbuf_start(drm_via_private_t * dev_priv)
541{
542 uint32_t pause_addr_lo, pause_addr_hi;
543 uint32_t start_addr, start_addr_lo;
544 uint32_t end_addr, end_addr_lo;
545 uint32_t command;
546 uint32_t agp_base;
547
548
549 dev_priv->dma_low = 0;
550
551 agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
552 start_addr = agp_base;
553 end_addr = agp_base + dev_priv->dma_high;
554
555 start_addr_lo = ((HC_SubA_HAGPBstL << 24) | (start_addr & 0xFFFFFF));
556 end_addr_lo = ((HC_SubA_HAGPBendL << 24) | (end_addr & 0xFFFFFF));
557 command = ((HC_SubA_HAGPCMNT << 24) | (start_addr >> 24) |
558 ((end_addr & 0xff000000) >> 16));
559
560 dev_priv->last_pause_ptr =
561 via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0,
562 &pause_addr_hi, & pause_addr_lo, 1) - 1;
563
564 via_flush_write_combine();
565 while(! *dev_priv->last_pause_ptr);
566
567 VIA_WRITE(VIA_REG_TRANSET, (HC_ParaType_PreCR << 16));
568 VIA_WRITE(VIA_REG_TRANSPACE, command);
569 VIA_WRITE(VIA_REG_TRANSPACE, start_addr_lo);
570 VIA_WRITE(VIA_REG_TRANSPACE, end_addr_lo);
571
572 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_hi);
573 VIA_WRITE(VIA_REG_TRANSPACE, pause_addr_lo);
574
575 VIA_WRITE(VIA_REG_TRANSPACE, command | HC_HAGPCMNT_MASK);
576}
577
578static void via_pad_cache(drm_via_private_t *dev_priv, int qwords)
579{
580 uint32_t *vb;
581
582 via_cmdbuf_wait(dev_priv, qwords + 2);
583 vb = via_get_dma(dev_priv);
584 VIA_OUT_RING_QW( HC_HEADER2, HC_ParaType_NotTex << 16);
585 via_align_buffer(dev_priv,vb,qwords);
586}
587
588static inline void via_dummy_bitblt(drm_via_private_t * dev_priv)
589{
590 uint32_t *vb = via_get_dma(dev_priv);
591 SetReg2DAGP(0x0C, (0 | (0 << 16)));
592 SetReg2DAGP(0x10, 0 | (0 << 16));
593 SetReg2DAGP(0x0, 0x1 | 0x2000 | 0xAA000000);
594}
595
596
597static void via_cmdbuf_jump(drm_via_private_t * dev_priv)
598{
599 uint32_t agp_base;
600 uint32_t pause_addr_lo, pause_addr_hi;
601 uint32_t jump_addr_lo, jump_addr_hi;
602 volatile uint32_t *last_pause_ptr;
603 uint32_t dma_low_save1, dma_low_save2;
604
605 agp_base = dev_priv->dma_offset + (uint32_t) dev_priv->agpAddr;
606 via_align_cmd(dev_priv, HC_HAGPBpID_JUMP, 0, &jump_addr_hi,
607 &jump_addr_lo, 0);
608
609 dev_priv->dma_wrap = dev_priv->dma_low;
610
611
612 /*
613 * Wrap command buffer to the beginning.
614 */
615
616 dev_priv->dma_low = 0;
617 if (via_cmdbuf_wait(dev_priv, CMDBUF_ALIGNMENT_SIZE) != 0) {
618 DRM_ERROR("via_cmdbuf_jump failed\n");
619 }
620
621 via_dummy_bitblt(dev_priv);
622 via_dummy_bitblt(dev_priv);
623
624 last_pause_ptr = via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
625 &pause_addr_lo, 0) -1;
626 via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
627 &pause_addr_lo, 0);
628
629 *last_pause_ptr = pause_addr_lo;
630 dma_low_save1 = dev_priv->dma_low;
631
632 /*
633 * Now, set a trap that will pause the regulator if it tries to rerun the old
634 * command buffer. (Which may happen if via_hook_segment detecs a command regulator pause
635 * and reissues the jump command over PCI, while the regulator has already taken the jump
636 * and actually paused at the current buffer end).
637 * There appears to be no other way to detect this condition, since the hw_addr_pointer
638 * does not seem to get updated immediately when a jump occurs.
639 */
640
641 last_pause_ptr = via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
642 &pause_addr_lo, 0) -1;
643 via_align_cmd(dev_priv, HC_HAGPBpID_PAUSE, 0, &pause_addr_hi,
644 &pause_addr_lo, 0);
645 *last_pause_ptr = pause_addr_lo;
646
647 dma_low_save2 = dev_priv->dma_low;
648 dev_priv->dma_low = dma_low_save1;
649 via_hook_segment( dev_priv, jump_addr_hi, jump_addr_lo, 0);
650 dev_priv->dma_low = dma_low_save2;
651 via_hook_segment( dev_priv, pause_addr_hi, pause_addr_lo, 0);
652}
653
654
655static void via_cmdbuf_rewind(drm_via_private_t * dev_priv)
656{
657 via_cmdbuf_jump(dev_priv);
658}
659
660static void via_cmdbuf_flush(drm_via_private_t * dev_priv, uint32_t cmd_type)
661{
662 uint32_t pause_addr_lo, pause_addr_hi;
663
664 via_align_cmd(dev_priv, cmd_type, 0, &pause_addr_hi, &pause_addr_lo, 0);
665 via_hook_segment( dev_priv, pause_addr_hi, pause_addr_lo, 0);
666}
667
668
669static void via_cmdbuf_pause(drm_via_private_t * dev_priv)
670{
671 via_cmdbuf_flush(dev_priv, HC_HAGPBpID_PAUSE);
672}
673
674static void via_cmdbuf_reset(drm_via_private_t * dev_priv)
675{
676 via_cmdbuf_flush(dev_priv, HC_HAGPBpID_STOP);
677 via_wait_idle(dev_priv);
678}
679
680/*
681 * User interface to the space and lag functions.
682 */
683
684int
685via_cmdbuf_size(DRM_IOCTL_ARGS)
686{
687 DRM_DEVICE;
688 drm_via_cmdbuf_size_t d_siz;
689 int ret = 0;
690 uint32_t tmp_size, count;
691 drm_via_private_t *dev_priv;
692
693 DRM_DEBUG("via cmdbuf_size\n");
694 LOCK_TEST_WITH_RETURN( dev, filp );
695
696 dev_priv = (drm_via_private_t *) dev->dev_private;
697
698 if (dev_priv->ring.virtual_start == NULL) {
699 DRM_ERROR("%s called without initializing AGP ring buffer.\n",
700 __FUNCTION__);
701 return DRM_ERR(EFAULT);
702 }
703
704 DRM_COPY_FROM_USER_IOCTL(d_siz, (drm_via_cmdbuf_size_t __user *) data,
705 sizeof(d_siz));
706
707
708 count = 1000000;
709 tmp_size = d_siz.size;
710 switch(d_siz.func) {
711 case VIA_CMDBUF_SPACE:
712 while (((tmp_size = via_cmdbuf_space(dev_priv)) < d_siz.size) && count--) {
713 if (!d_siz.wait) {
714 break;
715 }
716 }
717 if (!count) {
718 DRM_ERROR("VIA_CMDBUF_SPACE timed out.\n");
719 ret = DRM_ERR(EAGAIN);
720 }
721 break;
722 case VIA_CMDBUF_LAG:
723 while (((tmp_size = via_cmdbuf_lag(dev_priv)) > d_siz.size) && count--) {
724 if (!d_siz.wait) {
725 break;
726 }
727 }
728 if (!count) {
729 DRM_ERROR("VIA_CMDBUF_LAG timed out.\n");
730 ret = DRM_ERR(EAGAIN);
731 }
732 break;
733 default:
734 ret = DRM_ERR(EFAULT);
735 }
736 d_siz.size = tmp_size;
737
738 DRM_COPY_TO_USER_IOCTL((drm_via_cmdbuf_size_t __user *) data, d_siz,
739 sizeof(d_siz));
740 return ret;
741}
diff --git a/drivers/char/drm/via_drm.h b/drivers/char/drm/via_drm.h
new file mode 100644
index 000000000000..be346bb0a26a
--- /dev/null
+++ b/drivers/char/drm/via_drm.h
@@ -0,0 +1,243 @@
1/*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24#ifndef _VIA_DRM_H_
25#define _VIA_DRM_H_
26
27/* WARNING: These defines must be the same as what the Xserver uses.
28 * if you change them, you must change the defines in the Xserver.
29 */
30
31#ifndef _VIA_DEFINES_
32#define _VIA_DEFINES_
33
34#ifndef __KERNEL__
35#include "via_drmclient.h"
36#endif
37
38#define VIA_NR_SAREA_CLIPRECTS 8
39#define VIA_NR_XVMC_PORTS 10
40#define VIA_NR_XVMC_LOCKS 5
41#define VIA_MAX_CACHELINE_SIZE 64
42#define XVMCLOCKPTR(saPriv,lockNo) \
43 ((volatile drm_hw_lock_t *)(((((unsigned long) (saPriv)->XvMCLockArea) + \
44 (VIA_MAX_CACHELINE_SIZE - 1)) & \
45 ~(VIA_MAX_CACHELINE_SIZE - 1)) + \
46 VIA_MAX_CACHELINE_SIZE*(lockNo)))
47
48/* Each region is a minimum of 64k, and there are at most 64 of them.
49 */
50#define VIA_NR_TEX_REGIONS 64
51#define VIA_LOG_MIN_TEX_REGION_SIZE 16
52#endif
53
54#define VIA_UPLOAD_TEX0IMAGE 0x1 /* handled clientside */
55#define VIA_UPLOAD_TEX1IMAGE 0x2 /* handled clientside */
56#define VIA_UPLOAD_CTX 0x4
57#define VIA_UPLOAD_BUFFERS 0x8
58#define VIA_UPLOAD_TEX0 0x10
59#define VIA_UPLOAD_TEX1 0x20
60#define VIA_UPLOAD_CLIPRECTS 0x40
61#define VIA_UPLOAD_ALL 0xff
62
63/* VIA specific ioctls */
64#define DRM_VIA_ALLOCMEM 0x00
65#define DRM_VIA_FREEMEM 0x01
66#define DRM_VIA_AGP_INIT 0x02
67#define DRM_VIA_FB_INIT 0x03
68#define DRM_VIA_MAP_INIT 0x04
69#define DRM_VIA_DEC_FUTEX 0x05
70#define NOT_USED
71#define DRM_VIA_DMA_INIT 0x07
72#define DRM_VIA_CMDBUFFER 0x08
73#define DRM_VIA_FLUSH 0x09
74#define DRM_VIA_PCICMD 0x0a
75#define DRM_VIA_CMDBUF_SIZE 0x0b
76#define NOT_USED
77#define DRM_VIA_WAIT_IRQ 0x0d
78
79#define DRM_IOCTL_VIA_ALLOCMEM DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_ALLOCMEM, drm_via_mem_t)
80#define DRM_IOCTL_VIA_FREEMEM DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_FREEMEM, drm_via_mem_t)
81#define DRM_IOCTL_VIA_AGP_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_AGP_INIT, drm_via_agp_t)
82#define DRM_IOCTL_VIA_FB_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_FB_INIT, drm_via_fb_t)
83#define DRM_IOCTL_VIA_MAP_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_MAP_INIT, drm_via_init_t)
84#define DRM_IOCTL_VIA_DEC_FUTEX DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_DEC_FUTEX, drm_via_futex_t)
85#define DRM_IOCTL_VIA_DMA_INIT DRM_IOWR(DRM_COMMAND_BASE + DRM_VIA_DMA_INIT, drm_via_dma_init_t)
86#define DRM_IOCTL_VIA_CMDBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_CMDBUFFER, drm_via_cmdbuffer_t)
87#define DRM_IOCTL_VIA_FLUSH DRM_IO( DRM_COMMAND_BASE + DRM_VIA_FLUSH)
88#define DRM_IOCTL_VIA_PCICMD DRM_IOW( DRM_COMMAND_BASE + DRM_VIA_PCICMD, drm_via_cmdbuffer_t)
89#define DRM_IOCTL_VIA_CMDBUF_SIZE DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_CMDBUF_SIZE, \
90 drm_via_cmdbuf_size_t)
91#define DRM_IOCTL_VIA_WAIT_IRQ DRM_IOWR( DRM_COMMAND_BASE + DRM_VIA_WAIT_IRQ, drm_via_irqwait_t)
92
93/* Indices into buf.Setup where various bits of state are mirrored per
94 * context and per buffer. These can be fired at the card as a unit,
95 * or in a piecewise fashion as required.
96 */
97
98#define VIA_TEX_SETUP_SIZE 8
99
100/* Flags for clear ioctl
101 */
102#define VIA_FRONT 0x1
103#define VIA_BACK 0x2
104#define VIA_DEPTH 0x4
105#define VIA_STENCIL 0x8
106#define VIDEO 0
107#define AGP 1
108typedef struct {
109 uint32_t offset;
110 uint32_t size;
111} drm_via_agp_t;
112
113typedef struct {
114 uint32_t offset;
115 uint32_t size;
116} drm_via_fb_t;
117
118typedef struct {
119 uint32_t context;
120 uint32_t type;
121 uint32_t size;
122 unsigned long index;
123 unsigned long offset;
124} drm_via_mem_t;
125
126typedef struct _drm_via_init {
127 enum {
128 VIA_INIT_MAP = 0x01,
129 VIA_CLEANUP_MAP = 0x02
130 } func;
131
132 unsigned long sarea_priv_offset;
133 unsigned long fb_offset;
134 unsigned long mmio_offset;
135 unsigned long agpAddr;
136} drm_via_init_t;
137
138typedef struct _drm_via_futex {
139 enum {
140 VIA_FUTEX_WAIT = 0x00,
141 VIA_FUTEX_WAKE = 0X01
142 } func;
143 uint32_t ms;
144 uint32_t lock;
145 uint32_t val;
146} drm_via_futex_t;
147
148typedef struct _drm_via_dma_init {
149 enum {
150 VIA_INIT_DMA = 0x01,
151 VIA_CLEANUP_DMA = 0x02,
152 VIA_DMA_INITIALIZED = 0x03
153 } func;
154
155 unsigned long offset;
156 unsigned long size;
157 unsigned long reg_pause_addr;
158} drm_via_dma_init_t;
159
160typedef struct _drm_via_cmdbuffer {
161 char __user *buf;
162 unsigned long size;
163} drm_via_cmdbuffer_t;
164
165/* Warning: If you change the SAREA structure you must change the Xserver
166 * structure as well */
167
168typedef struct _drm_via_tex_region {
169 unsigned char next, prev; /* indices to form a circular LRU */
170 unsigned char inUse; /* owned by a client, or free? */
171 int age; /* tracked by clients to update local LRU's */
172} drm_via_tex_region_t;
173
174typedef struct _drm_via_sarea {
175 unsigned int dirty;
176 unsigned int nbox;
177 drm_clip_rect_t boxes[VIA_NR_SAREA_CLIPRECTS];
178 drm_via_tex_region_t texList[VIA_NR_TEX_REGIONS + 1];
179 int texAge; /* last time texture was uploaded */
180 int ctxOwner; /* last context to upload state */
181 int vertexPrim;
182
183 /*
184 * Below is for XvMC.
185 * We want the lock integers alone on, and aligned to, a cache line.
186 * Therefore this somewhat strange construct.
187 */
188
189 char XvMCLockArea[VIA_MAX_CACHELINE_SIZE * (VIA_NR_XVMC_LOCKS + 1)];
190
191 unsigned int XvMCDisplaying[VIA_NR_XVMC_PORTS];
192 unsigned int XvMCSubPicOn[VIA_NR_XVMC_PORTS];
193 unsigned int XvMCCtxNoGrabbed; /* Last context to hold decoder */
194
195} drm_via_sarea_t;
196
197typedef struct _drm_via_cmdbuf_size {
198 enum {
199 VIA_CMDBUF_SPACE = 0x01,
200 VIA_CMDBUF_LAG = 0x02
201 } func;
202 int wait;
203 uint32_t size;
204} drm_via_cmdbuf_size_t;
205
206typedef enum {
207 VIA_IRQ_ABSOLUTE = 0x0,
208 VIA_IRQ_RELATIVE = 0x1,
209 VIA_IRQ_SIGNAL = 0x10000000,
210 VIA_IRQ_FORCE_SEQUENCE = 0x20000000
211} via_irq_seq_type_t;
212
213#define VIA_IRQ_FLAGS_MASK 0xF0000000
214
215struct drm_via_wait_irq_request{
216 unsigned irq;
217 via_irq_seq_type_t type;
218 uint32_t sequence;
219 uint32_t signal;
220};
221
222typedef union drm_via_irqwait {
223 struct drm_via_wait_irq_request request;
224 struct drm_wait_vblank_reply reply;
225} drm_via_irqwait_t;
226
227#ifdef __KERNEL__
228
229int via_fb_init(DRM_IOCTL_ARGS);
230int via_mem_alloc(DRM_IOCTL_ARGS);
231int via_mem_free(DRM_IOCTL_ARGS);
232int via_agp_init(DRM_IOCTL_ARGS);
233int via_map_init(DRM_IOCTL_ARGS);
234int via_decoder_futex(DRM_IOCTL_ARGS);
235int via_dma_init(DRM_IOCTL_ARGS);
236int via_cmdbuffer(DRM_IOCTL_ARGS);
237int via_flush_ioctl(DRM_IOCTL_ARGS);
238int via_pci_cmdbuffer(DRM_IOCTL_ARGS);
239int via_cmdbuf_size(DRM_IOCTL_ARGS);
240int via_wait_irq(DRM_IOCTL_ARGS);
241
242#endif
243#endif /* _VIA_DRM_H_ */
diff --git a/drivers/char/drm/via_drv.c b/drivers/char/drm/via_drv.c
new file mode 100644
index 000000000000..275eefc79221
--- /dev/null
+++ b/drivers/char/drm/via_drv.c
@@ -0,0 +1,126 @@
1/*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25#include <linux/config.h>
26#include "drmP.h"
27#include "via_drm.h"
28#include "via_drv.h"
29
30#include "drm_pciids.h"
31
32static int postinit(struct drm_device *dev, unsigned long flags)
33{
34 DRM_INFO("Initialized %s %d.%d.%d %s on minor %d: %s\n",
35 DRIVER_NAME,
36 DRIVER_MAJOR,
37 DRIVER_MINOR,
38 DRIVER_PATCHLEVEL,
39 DRIVER_DATE, dev->primary.minor, pci_pretty_name(dev->pdev)
40 );
41 return 0;
42}
43
44static int version(drm_version_t * version)
45{
46 int len;
47
48 version->version_major = DRIVER_MAJOR;
49 version->version_minor = DRIVER_MINOR;
50 version->version_patchlevel = DRIVER_PATCHLEVEL;
51 DRM_COPY(version->name, DRIVER_NAME);
52 DRM_COPY(version->date, DRIVER_DATE);
53 DRM_COPY(version->desc, DRIVER_DESC);
54 return 0;
55}
56
57static struct pci_device_id pciidlist[] = {
58 viadrv_PCI_IDS
59};
60
61static drm_ioctl_desc_t ioctls[] = {
62 [DRM_IOCTL_NR(DRM_VIA_ALLOCMEM)] = {via_mem_alloc, 1, 0},
63 [DRM_IOCTL_NR(DRM_VIA_FREEMEM)] = {via_mem_free, 1, 0},
64 [DRM_IOCTL_NR(DRM_VIA_AGP_INIT)] = {via_agp_init, 1, 0},
65 [DRM_IOCTL_NR(DRM_VIA_FB_INIT)] = {via_fb_init, 1, 0},
66 [DRM_IOCTL_NR(DRM_VIA_MAP_INIT)] = {via_map_init, 1, 0},
67 [DRM_IOCTL_NR(DRM_VIA_DEC_FUTEX)] = {via_decoder_futex, 1, 0},
68 [DRM_IOCTL_NR(DRM_VIA_DMA_INIT)] = {via_dma_init, 1, 0},
69 [DRM_IOCTL_NR(DRM_VIA_CMDBUFFER)] = {via_cmdbuffer, 1, 0},
70 [DRM_IOCTL_NR(DRM_VIA_FLUSH)] = {via_flush_ioctl, 1, 0},
71 [DRM_IOCTL_NR(DRM_VIA_PCICMD)] = {via_pci_cmdbuffer, 1, 0},
72 [DRM_IOCTL_NR(DRM_VIA_CMDBUF_SIZE)] = {via_cmdbuf_size, 1, 0},
73 [DRM_IOCTL_NR(DRM_VIA_WAIT_IRQ)] = {via_wait_irq, 1, 0}
74};
75
76static struct drm_driver driver = {
77 .driver_features =
78 DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ |
79 DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
80 .context_ctor = via_init_context,
81 .context_dtor = via_final_context,
82 .vblank_wait = via_driver_vblank_wait,
83 .irq_preinstall = via_driver_irq_preinstall,
84 .irq_postinstall = via_driver_irq_postinstall,
85 .irq_uninstall = via_driver_irq_uninstall,
86 .irq_handler = via_driver_irq_handler,
87 .dma_quiescent = via_driver_dma_quiescent,
88 .reclaim_buffers = drm_core_reclaim_buffers,
89 .get_map_ofs = drm_core_get_map_ofs,
90 .get_reg_ofs = drm_core_get_reg_ofs,
91 .postinit = postinit,
92 .version = version,
93 .ioctls = ioctls,
94 .num_ioctls = DRM_ARRAY_SIZE(ioctls),
95 .fops = {
96 .owner = THIS_MODULE,
97 .open = drm_open,
98 .release = drm_release,
99 .ioctl = drm_ioctl,
100 .mmap = drm_mmap,
101 .poll = drm_poll,
102 .fasync = drm_fasync,
103 },
104 .pci_driver = {
105 .name = DRIVER_NAME,
106 .id_table = pciidlist,
107 }
108};
109
110static int __init via_init(void)
111{
112 via_init_command_verifier();
113 return drm_init(&driver);
114}
115
116static void __exit via_exit(void)
117{
118 drm_exit(&driver);
119}
120
121module_init(via_init);
122module_exit(via_exit);
123
124MODULE_AUTHOR(DRIVER_AUTHOR);
125MODULE_DESCRIPTION(DRIVER_DESC);
126MODULE_LICENSE("GPL and additional rights");
diff --git a/drivers/char/drm/via_drv.h b/drivers/char/drm/via_drv.h
new file mode 100644
index 000000000000..4eaa8b7c4c96
--- /dev/null
+++ b/drivers/char/drm/via_drv.h
@@ -0,0 +1,118 @@
1/*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24#ifndef _VIA_DRV_H_
25#define _VIA_DRV_H_
26
27#define DRIVER_AUTHOR "VIA"
28
29#define DRIVER_NAME "via"
30#define DRIVER_DESC "VIA Unichrome / Pro"
31#define DRIVER_DATE "20050523"
32
33#define DRIVER_MAJOR 2
34#define DRIVER_MINOR 6
35#define DRIVER_PATCHLEVEL 3
36
37#include "via_verifier.h"
38
39#define VIA_PCI_BUF_SIZE 60000
40#define VIA_FIRE_BUF_SIZE 1024
41#define VIA_NUM_IRQS 2
42
43
44
45typedef struct drm_via_ring_buffer {
46 drm_map_t map;
47 char *virtual_start;
48} drm_via_ring_buffer_t;
49
50typedef uint32_t maskarray_t[5];
51
52typedef struct drm_via_irq {
53 atomic_t irq_received;
54 uint32_t pending_mask;
55 uint32_t enable_mask;
56 wait_queue_head_t irq_queue;
57} drm_via_irq_t;
58
59typedef struct drm_via_private {
60 drm_via_sarea_t *sarea_priv;
61 drm_map_t *sarea;
62 drm_map_t *fb;
63 drm_map_t *mmio;
64 unsigned long agpAddr;
65 wait_queue_head_t decoder_queue[VIA_NR_XVMC_LOCKS];
66 char *dma_ptr;
67 unsigned int dma_low;
68 unsigned int dma_high;
69 unsigned int dma_offset;
70 uint32_t dma_wrap;
71 volatile uint32_t *last_pause_ptr;
72 volatile uint32_t *hw_addr_ptr;
73 drm_via_ring_buffer_t ring;
74 struct timeval last_vblank;
75 int last_vblank_valid;
76 unsigned usec_per_vblank;
77 drm_via_state_t hc_state;
78 char pci_buf[VIA_PCI_BUF_SIZE];
79 const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
80 uint32_t num_fire_offsets;
81 int pro_group_a;
82 drm_via_irq_t via_irqs[VIA_NUM_IRQS];
83 unsigned num_irqs;
84 maskarray_t *irq_masks;
85 uint32_t irq_enable_mask;
86 uint32_t irq_pending_mask;
87} drm_via_private_t;
88
89/* VIA MMIO register access */
90#define VIA_BASE ((dev_priv->mmio))
91
92#define VIA_READ(reg) DRM_READ32(VIA_BASE, reg)
93#define VIA_WRITE(reg,val) DRM_WRITE32(VIA_BASE, reg, val)
94#define VIA_READ8(reg) DRM_READ8(VIA_BASE, reg)
95#define VIA_WRITE8(reg,val) DRM_WRITE8(VIA_BASE, reg, val)
96
97extern int via_init_context(drm_device_t * dev, int context);
98extern int via_final_context(drm_device_t * dev, int context);
99
100extern int via_do_cleanup_map(drm_device_t * dev);
101extern int via_map_init(struct inode *inode, struct file *filp,
102 unsigned int cmd, unsigned long arg);
103extern int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence);
104
105extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
106extern void via_driver_irq_preinstall(drm_device_t * dev);
107extern void via_driver_irq_postinstall(drm_device_t * dev);
108extern void via_driver_irq_uninstall(drm_device_t * dev);
109
110extern int via_dma_cleanup(drm_device_t * dev);
111extern void via_init_command_verifier(void);
112extern int via_driver_dma_quiescent(drm_device_t * dev);
113extern void via_init_futex(drm_via_private_t *dev_priv);
114extern void via_cleanup_futex(drm_via_private_t *dev_priv);
115extern void via_release_futex(drm_via_private_t *dev_priv, int context);
116
117
118#endif
diff --git a/drivers/char/drm/via_ds.c b/drivers/char/drm/via_ds.c
new file mode 100644
index 000000000000..5c71e089246c
--- /dev/null
+++ b/drivers/char/drm/via_ds.c
@@ -0,0 +1,280 @@
1/*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sub license,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
20 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
24 */
25#include <linux/module.h>
26#include <linux/delay.h>
27#include <linux/errno.h>
28#include <linux/kernel.h>
29#include <linux/slab.h>
30#include <linux/poll.h>
31#include <linux/pci.h>
32#include <asm/io.h>
33
34#include "via_ds.h"
35extern unsigned int VIA_DEBUG;
36
37set_t *via_setInit(void)
38{
39 int i;
40 set_t *set;
41 set = (set_t *) drm_alloc(sizeof(set_t), DRM_MEM_DRIVER);
42 for (i = 0; i < SET_SIZE; i++) {
43 set->list[i].free_next = i + 1;
44 set->list[i].alloc_next = -1;
45 }
46 set->list[SET_SIZE - 1].free_next = -1;
47 set->free = 0;
48 set->alloc = -1;
49 set->trace = -1;
50 return set;
51}
52
53int via_setAdd(set_t * set, ITEM_TYPE item)
54{
55 int free = set->free;
56 if (free != -1) {
57 set->list[free].val = item;
58 set->free = set->list[free].free_next;
59 } else {
60 return 0;
61 }
62 set->list[free].alloc_next = set->alloc;
63 set->alloc = free;
64 set->list[free].free_next = -1;
65 return 1;
66}
67
68int via_setDel(set_t * set, ITEM_TYPE item)
69{
70 int alloc = set->alloc;
71 int prev = -1;
72
73 while (alloc != -1) {
74 if (set->list[alloc].val == item) {
75 if (prev != -1)
76 set->list[prev].alloc_next =
77 set->list[alloc].alloc_next;
78 else
79 set->alloc = set->list[alloc].alloc_next;
80 break;
81 }
82 prev = alloc;
83 alloc = set->list[alloc].alloc_next;
84 }
85
86 if (alloc == -1)
87 return 0;
88
89 set->list[alloc].free_next = set->free;
90 set->free = alloc;
91 set->list[alloc].alloc_next = -1;
92
93 return 1;
94}
95
96/* setFirst -> setAdd -> setNext is wrong */
97
98int via_setFirst(set_t * set, ITEM_TYPE * item)
99{
100 if (set->alloc == -1)
101 return 0;
102
103 *item = set->list[set->alloc].val;
104 set->trace = set->list[set->alloc].alloc_next;
105
106 return 1;
107}
108
109int via_setNext(set_t * set, ITEM_TYPE * item)
110{
111 if (set->trace == -1)
112 return 0;
113
114 *item = set->list[set->trace].val;
115 set->trace = set->list[set->trace].alloc_next;
116
117 return 1;
118}
119
120int via_setDestroy(set_t * set)
121{
122 drm_free(set, sizeof(set_t), DRM_MEM_DRIVER);
123
124 return 1;
125}
126
127#define ISFREE(bptr) ((bptr)->free)
128
129#define fprintf(fmt, arg...) do{}while(0)
130
131memHeap_t *via_mmInit(int ofs, int size)
132{
133 PMemBlock blocks;
134
135 if (size <= 0)
136 return NULL;
137
138 blocks = (TMemBlock *) drm_calloc(1, sizeof(TMemBlock), DRM_MEM_DRIVER);
139
140 if (blocks) {
141 blocks->ofs = ofs;
142 blocks->size = size;
143 blocks->free = 1;
144 return (memHeap_t *) blocks;
145 } else
146 return NULL;
147}
148
149static TMemBlock *SliceBlock(TMemBlock * p,
150 int startofs, int size,
151 int reserved, int alignment)
152{
153 TMemBlock *newblock;
154
155 /* break left */
156 if (startofs > p->ofs) {
157 newblock =
158 (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
159 DRM_MEM_DRIVER);
160 newblock->ofs = startofs;
161 newblock->size = p->size - (startofs - p->ofs);
162 newblock->free = 1;
163 newblock->next = p->next;
164 p->size -= newblock->size;
165 p->next = newblock;
166 p = newblock;
167 }
168
169 /* break right */
170 if (size < p->size) {
171 newblock =
172 (TMemBlock *) drm_calloc(1, sizeof(TMemBlock),
173 DRM_MEM_DRIVER);
174 newblock->ofs = startofs + size;
175 newblock->size = p->size - size;
176 newblock->free = 1;
177 newblock->next = p->next;
178 p->size = size;
179 p->next = newblock;
180 }
181
182 /* p = middle block */
183 p->align = alignment;
184 p->free = 0;
185 p->reserved = reserved;
186 return p;
187}
188
189PMemBlock via_mmAllocMem(memHeap_t * heap, int size, int align2,
190 int startSearch)
191{
192 int mask, startofs, endofs;
193 TMemBlock *p;
194
195 if (!heap || align2 < 0 || size <= 0)
196 return NULL;
197
198 mask = (1 << align2) - 1;
199 startofs = 0;
200 p = (TMemBlock *) heap;
201
202 while (p) {
203 if (ISFREE(p)) {
204 startofs = (p->ofs + mask) & ~mask;
205
206 if (startofs < startSearch)
207 startofs = startSearch;
208
209 endofs = startofs + size;
210
211 if (endofs <= (p->ofs + p->size))
212 break;
213 }
214
215 p = p->next;
216 }
217
218 if (!p)
219 return NULL;
220
221 p = SliceBlock(p, startofs, size, 0, mask + 1);
222 p->heap = heap;
223
224 return p;
225}
226
227static __inline__ int Join2Blocks(TMemBlock * p)
228{
229 if (p->free && p->next && p->next->free) {
230 TMemBlock *q = p->next;
231 p->size += q->size;
232 p->next = q->next;
233 drm_free(q, sizeof(TMemBlock), DRM_MEM_DRIVER);
234
235 return 1;
236 }
237
238 return 0;
239}
240
241int via_mmFreeMem(PMemBlock b)
242{
243 TMemBlock *p, *prev;
244
245 if (!b)
246 return 0;
247
248 if (!b->heap) {
249 fprintf(stderr, "no heap\n");
250
251 return -1;
252 }
253
254 p = b->heap;
255 prev = NULL;
256
257 while (p && p != b) {
258 prev = p;
259 p = p->next;
260 }
261
262 if (!p || p->free || p->reserved) {
263 if (!p)
264 fprintf(stderr, "block not found in heap\n");
265 else if (p->free)
266 fprintf(stderr, "block already free\n");
267 else
268 fprintf(stderr, "block is reserved\n");
269
270 return -1;
271 }
272
273 p->free = 1;
274 Join2Blocks(p);
275
276 if (prev)
277 Join2Blocks(prev);
278
279 return 0;
280}
diff --git a/drivers/char/drm/via_ds.h b/drivers/char/drm/via_ds.h
new file mode 100644
index 000000000000..d2bb9f37ca38
--- /dev/null
+++ b/drivers/char/drm/via_ds.h
@@ -0,0 +1,104 @@
1/*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 * Copyright 2000 Silicon Integrated Systems Corp, Inc., HsinChu, Taiwan.
5 * All rights reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sub license,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial portions
16 * of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
21 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
25 */
26#ifndef _via_ds_h_
27#define _via_ds_h_
28
29#include "drmP.h"
30
31/* Set Data Structure */
32#define SET_SIZE 5000
33typedef unsigned long ITEM_TYPE;
34
35typedef struct {
36 ITEM_TYPE val;
37 int alloc_next, free_next;
38} list_item_t;
39
40typedef struct {
41 int alloc;
42 int free;
43 int trace;
44 list_item_t list[SET_SIZE];
45} set_t;
46
47set_t *via_setInit(void);
48int via_setAdd(set_t * set, ITEM_TYPE item);
49int via_setDel(set_t * set, ITEM_TYPE item);
50int via_setFirst(set_t * set, ITEM_TYPE * item);
51int via_setNext(set_t * set, ITEM_TYPE * item);
52int via_setDestroy(set_t * set);
53
54#endif
55
56#ifndef MM_INC
57#define MM_INC
58
59struct mem_block_t {
60 struct mem_block_t *next;
61 struct mem_block_t *heap;
62 int ofs, size;
63 int align;
64 unsigned int free:1;
65 unsigned int reserved:1;
66};
67typedef struct mem_block_t TMemBlock;
68typedef struct mem_block_t *PMemBlock;
69
70/* a heap is just the first block in a chain */
71typedef struct mem_block_t memHeap_t;
72
73static __inline__ int mmBlockSize(PMemBlock b)
74{
75 return b->size;
76}
77
78static __inline__ int mmOffset(PMemBlock b)
79{
80 return b->ofs;
81}
82
83static __inline__ void mmMarkReserved(PMemBlock b)
84{
85 b->reserved = 1;
86}
87
88/*
89 * input: total size in bytes
90 * return: a heap pointer if OK, NULL if error
91 */
92memHeap_t *via_mmInit(int ofs, int size);
93
94PMemBlock via_mmAllocMem(memHeap_t * heap, int size, int align2,
95 int startSearch);
96
97/*
98 * Free block starts at offset
99 * input: pointer to a block
100 * return: 0 if OK, -1 if error
101 */
102int via_mmFreeMem(PMemBlock b);
103
104#endif
diff --git a/drivers/char/drm/via_irq.c b/drivers/char/drm/via_irq.c
new file mode 100644
index 000000000000..e8027f3a93b0
--- /dev/null
+++ b/drivers/char/drm/via_irq.c
@@ -0,0 +1,339 @@
1/* via_irq.c
2 *
3 * Copyright 2004 BEAM Ltd.
4 * Copyright 2002 Tungsten Graphics, Inc.
5 * Copyright 2005 Thomas Hellstrom.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a
9 * copy of this software and associated documentation files (the "Software"),
10 * to deal in the Software without restriction, including without limitation
11 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12 * and/or sell copies of the Software, and to permit persons to whom the
13 * Software is furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice (including the next
16 * paragraph) shall be included in all copies or substantial portions of the
17 * Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * BEAM LTD, TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
23 * DAMAGES OR
24 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
25 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
26 * DEALINGS IN THE SOFTWARE.
27 *
28 * Authors:
29 * Terry Barnaby <terry1@beam.ltd.uk>
30 * Keith Whitwell <keith@tungstengraphics.com>
31 * Thomas Hellstrom <unichrome@shipmail.org>
32 *
33 * This code provides standard DRM access to the Via Unichrome / Pro Vertical blank
34 * interrupt, as well as an infrastructure to handle other interrupts of the chip.
35 * The refresh rate is also calculated for video playback sync purposes.
36 */
37
38#include "drmP.h"
39#include "drm.h"
40#include "via_drm.h"
41#include "via_drv.h"
42
43#define VIA_REG_INTERRUPT 0x200
44
45/* VIA_REG_INTERRUPT */
46#define VIA_IRQ_GLOBAL (1 << 31)
47#define VIA_IRQ_VBLANK_ENABLE (1 << 19)
48#define VIA_IRQ_VBLANK_PENDING (1 << 3)
49#define VIA_IRQ_HQV0_ENABLE (1 << 11)
50#define VIA_IRQ_HQV1_ENABLE (1 << 25)
51#define VIA_IRQ_HQV0_PENDING (1 << 9)
52#define VIA_IRQ_HQV1_PENDING (1 << 10)
53
54/*
55 * Device-specific IRQs go here. This type might need to be extended with
56 * the register if there are multiple IRQ control registers.
57 * Currently we activate the HQV interrupts of Unichrome Pro group A.
58 */
59
60static maskarray_t via_pro_group_a_irqs[] = {
61 {VIA_IRQ_HQV0_ENABLE, VIA_IRQ_HQV0_PENDING, 0x000003D0, 0x00008010, 0x00000000 },
62 {VIA_IRQ_HQV1_ENABLE, VIA_IRQ_HQV1_PENDING, 0x000013D0, 0x00008010, 0x00000000 }};
63static int via_num_pro_group_a = sizeof(via_pro_group_a_irqs)/sizeof(maskarray_t);
64
65static maskarray_t via_unichrome_irqs[] = {};
66static int via_num_unichrome = sizeof(via_unichrome_irqs)/sizeof(maskarray_t);
67
68
69static unsigned time_diff(struct timeval *now,struct timeval *then)
70{
71 return (now->tv_usec >= then->tv_usec) ?
72 now->tv_usec - then->tv_usec :
73 1000000 - (then->tv_usec - now->tv_usec);
74}
75
76irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
77{
78 drm_device_t *dev = (drm_device_t *) arg;
79 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
80 u32 status;
81 int handled = 0;
82 struct timeval cur_vblank;
83 drm_via_irq_t *cur_irq = dev_priv->via_irqs;
84 int i;
85
86 status = VIA_READ(VIA_REG_INTERRUPT);
87 if (status & VIA_IRQ_VBLANK_PENDING) {
88 atomic_inc(&dev->vbl_received);
89 if (!(atomic_read(&dev->vbl_received) & 0x0F)) {
90 do_gettimeofday(&cur_vblank);
91 if (dev_priv->last_vblank_valid) {
92 dev_priv->usec_per_vblank =
93 time_diff( &cur_vblank,&dev_priv->last_vblank) >> 4;
94 }
95 dev_priv->last_vblank = cur_vblank;
96 dev_priv->last_vblank_valid = 1;
97 }
98 if (!(atomic_read(&dev->vbl_received) & 0xFF)) {
99 DRM_DEBUG("US per vblank is: %u\n",
100 dev_priv->usec_per_vblank);
101 }
102 DRM_WAKEUP(&dev->vbl_queue);
103 drm_vbl_send_signals(dev);
104 handled = 1;
105 }
106
107
108 for (i=0; i<dev_priv->num_irqs; ++i) {
109 if (status & cur_irq->pending_mask) {
110 atomic_inc( &cur_irq->irq_received );
111 DRM_WAKEUP( &cur_irq->irq_queue );
112 handled = 1;
113 }
114 cur_irq++;
115 }
116
117 /* Acknowlege interrupts */
118 VIA_WRITE(VIA_REG_INTERRUPT, status);
119
120
121 if (handled)
122 return IRQ_HANDLED;
123 else
124 return IRQ_NONE;
125}
126
127static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv)
128{
129 u32 status;
130
131 if (dev_priv) {
132 /* Acknowlege interrupts */
133 status = VIA_READ(VIA_REG_INTERRUPT);
134 VIA_WRITE(VIA_REG_INTERRUPT, status |
135 dev_priv->irq_pending_mask);
136 }
137}
138
139int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence)
140{
141 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
142 unsigned int cur_vblank;
143 int ret = 0;
144
145 DRM_DEBUG("viadrv_vblank_wait\n");
146 if (!dev_priv) {
147 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
148 return -EINVAL;
149 }
150
151 viadrv_acknowledge_irqs(dev_priv);
152
153 /* Assume that the user has missed the current sequence number
154 * by about a day rather than she wants to wait for years
155 * using vertical blanks...
156 */
157
158 DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
159 (((cur_vblank = atomic_read(&dev->vbl_received)) -
160 *sequence) <= (1 << 23)));
161
162 *sequence = cur_vblank;
163 return ret;
164}
165
166static int
167via_driver_irq_wait(drm_device_t * dev, unsigned int irq, int force_sequence,
168 unsigned int *sequence)
169{
170 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
171 unsigned int cur_irq_sequence;
172 drm_via_irq_t *cur_irq = dev_priv->via_irqs;
173 int ret = 0;
174 maskarray_t *masks = dev_priv->irq_masks;
175
176 DRM_DEBUG("%s\n", __FUNCTION__);
177
178 if (!dev_priv) {
179 DRM_ERROR("%s called with no initialization\n", __FUNCTION__);
180 return DRM_ERR(EINVAL);
181 }
182
183 if (irq >= dev_priv->num_irqs ) {
184 DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__, irq);
185 return DRM_ERR(EINVAL);
186 }
187
188 cur_irq += irq;
189
190 if (masks[irq][2] && !force_sequence) {
191 DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
192 ((VIA_READ(masks[irq][2]) & masks[irq][3]) == masks[irq][4]));
193 cur_irq_sequence = atomic_read(&cur_irq->irq_received);
194 } else {
195 DRM_WAIT_ON(ret, cur_irq->irq_queue, 3 * DRM_HZ,
196 (((cur_irq_sequence = atomic_read(&cur_irq->irq_received)) -
197 *sequence) <= (1 << 23)));
198 }
199 *sequence = cur_irq_sequence;
200 return ret;
201}
202
203
204/*
205 * drm_dma.h hooks
206 */
207
208void via_driver_irq_preinstall(drm_device_t * dev)
209{
210 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
211 u32 status;
212 drm_via_irq_t *cur_irq = dev_priv->via_irqs;
213 int i;
214
215 DRM_DEBUG("driver_irq_preinstall: dev_priv: %p\n", dev_priv);
216 if (dev_priv) {
217
218 dev_priv->irq_enable_mask = VIA_IRQ_VBLANK_ENABLE;
219 dev_priv->irq_pending_mask = VIA_IRQ_VBLANK_PENDING;
220
221 dev_priv->irq_masks = (dev_priv->pro_group_a) ?
222 via_pro_group_a_irqs : via_unichrome_irqs;
223 dev_priv->num_irqs = (dev_priv->pro_group_a) ?
224 via_num_pro_group_a : via_num_unichrome;
225
226 for(i=0; i < dev_priv->num_irqs; ++i) {
227 atomic_set(&cur_irq->irq_received, 0);
228 cur_irq->enable_mask = dev_priv->irq_masks[i][0];
229 cur_irq->pending_mask = dev_priv->irq_masks[i][1];
230 DRM_INIT_WAITQUEUE( &cur_irq->irq_queue );
231 dev_priv->irq_enable_mask |= cur_irq->enable_mask;
232 dev_priv->irq_pending_mask |= cur_irq->pending_mask;
233 cur_irq++;
234
235 DRM_DEBUG("Initializing IRQ %d\n", i);
236 }
237
238 dev_priv->last_vblank_valid = 0;
239
240 // Clear VSync interrupt regs
241 status = VIA_READ(VIA_REG_INTERRUPT);
242 VIA_WRITE(VIA_REG_INTERRUPT, status &
243 ~(dev_priv->irq_enable_mask));
244
245 /* Clear bits if they're already high */
246 viadrv_acknowledge_irqs(dev_priv);
247 }
248}
249
250void via_driver_irq_postinstall(drm_device_t * dev)
251{
252 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
253 u32 status;
254
255 DRM_DEBUG("via_driver_irq_postinstall\n");
256 if (dev_priv) {
257 status = VIA_READ(VIA_REG_INTERRUPT);
258 VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
259 | dev_priv->irq_enable_mask);
260
261 /* Some magic, oh for some data sheets ! */
262
263 VIA_WRITE8(0x83d4, 0x11);
264 VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
265
266 }
267}
268
269void via_driver_irq_uninstall(drm_device_t * dev)
270{
271 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
272 u32 status;
273
274 DRM_DEBUG("driver_irq_uninstall)\n");
275 if (dev_priv) {
276
277 /* Some more magic, oh for some data sheets ! */
278
279 VIA_WRITE8(0x83d4, 0x11);
280 VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
281
282 status = VIA_READ(VIA_REG_INTERRUPT);
283 VIA_WRITE(VIA_REG_INTERRUPT, status &
284 ~(VIA_IRQ_VBLANK_ENABLE | dev_priv->irq_enable_mask));
285 }
286}
287
288int via_wait_irq(DRM_IOCTL_ARGS)
289{
290 drm_file_t *priv = filp->private_data;
291 drm_device_t *dev = priv->head->dev;
292 drm_via_irqwait_t __user *argp = (void __user *)data;
293 drm_via_irqwait_t irqwait;
294 struct timeval now;
295 int ret = 0;
296 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
297 drm_via_irq_t *cur_irq = dev_priv->via_irqs;
298 int force_sequence;
299
300 if (!dev->irq)
301 return DRM_ERR(EINVAL);
302
303 DRM_COPY_FROM_USER_IOCTL(irqwait, argp, sizeof(irqwait));
304 if (irqwait.request.irq >= dev_priv->num_irqs) {
305 DRM_ERROR("%s Trying to wait on unknown irq %d\n", __FUNCTION__,
306 irqwait.request.irq);
307 return DRM_ERR(EINVAL);
308 }
309
310 cur_irq += irqwait.request.irq;
311
312 switch (irqwait.request.type & ~VIA_IRQ_FLAGS_MASK) {
313 case VIA_IRQ_RELATIVE:
314 irqwait.request.sequence += atomic_read(&cur_irq->irq_received);
315 irqwait.request.type &= ~_DRM_VBLANK_RELATIVE;
316 case VIA_IRQ_ABSOLUTE:
317 break;
318 default:
319 return DRM_ERR(EINVAL);
320 }
321
322 if (irqwait.request.type & VIA_IRQ_SIGNAL) {
323 DRM_ERROR("%s Signals on Via IRQs not implemented yet.\n",
324 __FUNCTION__);
325 return DRM_ERR(EINVAL);
326 }
327
328 force_sequence = (irqwait.request.type & VIA_IRQ_FORCE_SEQUENCE);
329
330 ret = via_driver_irq_wait(dev, irqwait.request.irq, force_sequence,
331 &irqwait.request.sequence);
332 do_gettimeofday(&now);
333 irqwait.reply.tval_sec = now.tv_sec;
334 irqwait.reply.tval_usec = now.tv_usec;
335
336 DRM_COPY_TO_USER_IOCTL(argp, irqwait, sizeof(irqwait));
337
338 return ret;
339}
diff --git a/drivers/char/drm/via_map.c b/drivers/char/drm/via_map.c
new file mode 100644
index 000000000000..bb171139e737
--- /dev/null
+++ b/drivers/char/drm/via_map.c
@@ -0,0 +1,111 @@
1/*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24#include "drmP.h"
25#include "via_drm.h"
26#include "via_drv.h"
27
28static int via_do_init_map(drm_device_t * dev, drm_via_init_t * init)
29{
30 drm_via_private_t *dev_priv;
31
32 DRM_DEBUG("%s\n", __FUNCTION__);
33
34 dev_priv = drm_alloc(sizeof(drm_via_private_t), DRM_MEM_DRIVER);
35 if (dev_priv == NULL)
36 return -ENOMEM;
37
38 memset(dev_priv, 0, sizeof(drm_via_private_t));
39
40 DRM_GETSAREA();
41 if (!dev_priv->sarea) {
42 DRM_ERROR("could not find sarea!\n");
43 dev->dev_private = (void *)dev_priv;
44 via_do_cleanup_map(dev);
45 return -EINVAL;
46 }
47
48 dev_priv->fb = drm_core_findmap(dev, init->fb_offset);
49 if (!dev_priv->fb) {
50 DRM_ERROR("could not find framebuffer!\n");
51 dev->dev_private = (void *)dev_priv;
52 via_do_cleanup_map(dev);
53 return -EINVAL;
54 }
55 dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);
56 if (!dev_priv->mmio) {
57 DRM_ERROR("could not find mmio region!\n");
58 dev->dev_private = (void *)dev_priv;
59 via_do_cleanup_map(dev);
60 return -EINVAL;
61 }
62
63 dev_priv->sarea_priv =
64 (drm_via_sarea_t *) ((u8 *) dev_priv->sarea->handle +
65 init->sarea_priv_offset);
66
67 dev_priv->agpAddr = init->agpAddr;
68
69 via_init_futex( dev_priv );
70 dev_priv->pro_group_a = (dev->pdev->device == 0x3118);
71
72 dev->dev_private = (void *)dev_priv;
73 return 0;
74}
75
76int via_do_cleanup_map(drm_device_t * dev)
77{
78 if (dev->dev_private) {
79
80 drm_via_private_t *dev_priv = dev->dev_private;
81
82 via_dma_cleanup(dev);
83
84 drm_free(dev_priv, sizeof(drm_via_private_t), DRM_MEM_DRIVER);
85 dev->dev_private = NULL;
86 }
87
88 return 0;
89}
90
91int via_map_init(DRM_IOCTL_ARGS)
92{
93 DRM_DEVICE;
94 drm_via_init_t init;
95
96 DRM_DEBUG("%s\n", __FUNCTION__);
97
98 DRM_COPY_FROM_USER_IOCTL(init, (drm_via_init_t __user *) data,
99 sizeof(init));
100
101 switch (init.func) {
102 case VIA_INIT_MAP:
103 return via_do_init_map(dev, &init);
104 case VIA_CLEANUP_MAP:
105 return via_do_cleanup_map(dev);
106 }
107
108 return -EINVAL;
109}
110
111
diff --git a/drivers/char/drm/via_mm.c b/drivers/char/drm/via_mm.c
new file mode 100644
index 000000000000..13921f3c0ec2
--- /dev/null
+++ b/drivers/char/drm/via_mm.c
@@ -0,0 +1,361 @@
1/*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24#include "drmP.h"
25#include "via_drm.h"
26#include "via_drv.h"
27#include "via_ds.h"
28#include "via_mm.h"
29
30#define MAX_CONTEXT 100
31
32typedef struct {
33 int used;
34 int context;
35 set_t *sets[2]; /* 0 for frame buffer, 1 for AGP , 2 for System */
36} via_context_t;
37
38static via_context_t global_ppriv[MAX_CONTEXT];
39
40static int via_agp_alloc(drm_via_mem_t * mem);
41static int via_agp_free(drm_via_mem_t * mem);
42static int via_fb_alloc(drm_via_mem_t * mem);
43static int via_fb_free(drm_via_mem_t * mem);
44
45static int add_alloc_set(int context, int type, unsigned int val)
46{
47 int i, retval = 0;
48
49 for (i = 0; i < MAX_CONTEXT; i++) {
50 if (global_ppriv[i].used && global_ppriv[i].context == context) {
51 retval = via_setAdd(global_ppriv[i].sets[type], val);
52 break;
53 }
54 }
55
56 return retval;
57}
58
59static int del_alloc_set(int context, int type, unsigned int val)
60{
61 int i, retval = 0;
62
63 for (i = 0; i < MAX_CONTEXT; i++)
64 if (global_ppriv[i].used && global_ppriv[i].context == context) {
65 retval = via_setDel(global_ppriv[i].sets[type], val);
66 break;
67 }
68
69 return retval;
70}
71
72/* agp memory management */
73static memHeap_t *AgpHeap = NULL;
74
75int via_agp_init(DRM_IOCTL_ARGS)
76{
77 drm_via_agp_t agp;
78
79 DRM_COPY_FROM_USER_IOCTL(agp, (drm_via_agp_t __user *) data,
80 sizeof(agp));
81
82 AgpHeap = via_mmInit(agp.offset, agp.size);
83
84 DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)agp.offset, (unsigned long)agp.size);
85
86 return 0;
87}
88
89/* fb memory management */
90static memHeap_t *FBHeap = NULL;
91
92int via_fb_init(DRM_IOCTL_ARGS)
93{
94 drm_via_fb_t fb;
95
96 DRM_COPY_FROM_USER_IOCTL(fb, (drm_via_fb_t __user *) data, sizeof(fb));
97
98 FBHeap = via_mmInit(fb.offset, fb.size);
99
100 DRM_DEBUG("offset = %lu, size = %lu", (unsigned long)fb.offset, (unsigned long)fb.size);
101
102 return 0;
103}
104
105int via_init_context(struct drm_device *dev, int context)
106{
107 int i;
108
109 for (i = 0; i < MAX_CONTEXT; i++)
110 if (global_ppriv[i].used &&
111 (global_ppriv[i].context == context))
112 break;
113
114 if (i >= MAX_CONTEXT) {
115 for (i = 0; i < MAX_CONTEXT; i++) {
116 if (!global_ppriv[i].used) {
117 global_ppriv[i].context = context;
118 global_ppriv[i].used = 1;
119 global_ppriv[i].sets[0] = via_setInit();
120 global_ppriv[i].sets[1] = via_setInit();
121 DRM_DEBUG("init allocation set, socket=%d,"
122 " context = %d\n", i, context);
123 break;
124 }
125 }
126
127 if ((i >= MAX_CONTEXT) || (global_ppriv[i].sets[0] == NULL) ||
128 (global_ppriv[i].sets[1] == NULL)) {
129 return 0;
130 }
131 }
132
133 return 1;
134}
135
136int via_final_context(struct drm_device *dev, int context)
137{
138 int i;
139 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
140
141 for (i = 0; i < MAX_CONTEXT; i++)
142 if (global_ppriv[i].used &&
143 (global_ppriv[i].context == context))
144 break;
145
146 if (i < MAX_CONTEXT) {
147 set_t *set;
148 ITEM_TYPE item;
149 int retval;
150
151 DRM_DEBUG("find socket %d, context = %d\n", i, context);
152
153 /* Video Memory */
154 set = global_ppriv[i].sets[0];
155 retval = via_setFirst(set, &item);
156 while (retval) {
157 DRM_DEBUG("free video memory 0x%lx\n", item);
158 via_mmFreeMem((PMemBlock) item);
159 retval = via_setNext(set, &item);
160 }
161 via_setDestroy(set);
162
163 /* AGP Memory */
164 set = global_ppriv[i].sets[1];
165 retval = via_setFirst(set, &item);
166 while (retval) {
167 DRM_DEBUG("free agp memory 0x%lx\n", item);
168 via_mmFreeMem((PMemBlock) item);
169 retval = via_setNext(set, &item);
170 }
171 via_setDestroy(set);
172 global_ppriv[i].used = 0;
173 }
174 via_release_futex(dev_priv, context);
175
176
177#if defined(__linux__)
178 /* Linux specific until context tracking code gets ported to BSD */
179 /* Last context, perform cleanup */
180 if (dev->ctx_count == 1 && dev->dev_private) {
181 DRM_DEBUG("Last Context\n");
182 if (dev->irq)
183 drm_irq_uninstall(dev);
184
185 via_cleanup_futex(dev_priv);
186 via_do_cleanup_map(dev);
187 }
188#endif
189
190 return 1;
191}
192
193int via_mem_alloc(DRM_IOCTL_ARGS)
194{
195 drm_via_mem_t mem;
196
197 DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data,
198 sizeof(mem));
199
200 switch (mem.type) {
201 case VIDEO:
202 if (via_fb_alloc(&mem) < 0)
203 return -EFAULT;
204 DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem,
205 sizeof(mem));
206 return 0;
207 case AGP:
208 if (via_agp_alloc(&mem) < 0)
209 return -EFAULT;
210 DRM_COPY_TO_USER_IOCTL((drm_via_mem_t __user *) data, mem,
211 sizeof(mem));
212 return 0;
213 }
214
215 return -EFAULT;
216}
217
218static int via_fb_alloc(drm_via_mem_t * mem)
219{
220 drm_via_mm_t fb;
221 PMemBlock block;
222 int retval = 0;
223
224 if (!FBHeap)
225 return -1;
226
227 fb.size = mem->size;
228 fb.context = mem->context;
229
230 block = via_mmAllocMem(FBHeap, fb.size, 5, 0);
231 if (block) {
232 fb.offset = block->ofs;
233 fb.free = (unsigned long)block;
234 if (!add_alloc_set(fb.context, VIDEO, fb.free)) {
235 DRM_DEBUG("adding to allocation set fails\n");
236 via_mmFreeMem((PMemBlock) fb.free);
237 retval = -1;
238 }
239 } else {
240 fb.offset = 0;
241 fb.size = 0;
242 fb.free = 0;
243 retval = -1;
244 }
245
246 mem->offset = fb.offset;
247 mem->index = fb.free;
248
249 DRM_DEBUG("alloc fb, size = %d, offset = %d\n", fb.size,
250 (int)fb.offset);
251
252 return retval;
253}
254
255static int via_agp_alloc(drm_via_mem_t * mem)
256{
257 drm_via_mm_t agp;
258 PMemBlock block;
259 int retval = 0;
260
261 if (!AgpHeap)
262 return -1;
263
264 agp.size = mem->size;
265 agp.context = mem->context;
266
267 block = via_mmAllocMem(AgpHeap, agp.size, 5, 0);
268 if (block) {
269 agp.offset = block->ofs;
270 agp.free = (unsigned long)block;
271 if (!add_alloc_set(agp.context, AGP, agp.free)) {
272 DRM_DEBUG("adding to allocation set fails\n");
273 via_mmFreeMem((PMemBlock) agp.free);
274 retval = -1;
275 }
276 } else {
277 agp.offset = 0;
278 agp.size = 0;
279 agp.free = 0;
280 }
281
282 mem->offset = agp.offset;
283 mem->index = agp.free;
284
285 DRM_DEBUG("alloc agp, size = %d, offset = %d\n", agp.size,
286 (unsigned int)agp.offset);
287 return retval;
288}
289
290int via_mem_free(DRM_IOCTL_ARGS)
291{
292 drm_via_mem_t mem;
293
294 DRM_COPY_FROM_USER_IOCTL(mem, (drm_via_mem_t __user *) data,
295 sizeof(mem));
296
297 switch (mem.type) {
298
299 case VIDEO:
300 if (via_fb_free(&mem) == 0)
301 return 0;
302 break;
303 case AGP:
304 if (via_agp_free(&mem) == 0)
305 return 0;
306 break;
307 }
308
309 return -EFAULT;
310}
311
312static int via_fb_free(drm_via_mem_t * mem)
313{
314 drm_via_mm_t fb;
315 int retval = 0;
316
317 if (!FBHeap) {
318 return -1;
319 }
320
321 fb.free = mem->index;
322 fb.context = mem->context;
323
324 if (!fb.free) {
325 return -1;
326
327 }
328
329 via_mmFreeMem((PMemBlock) fb.free);
330
331 if (!del_alloc_set(fb.context, VIDEO, fb.free)) {
332 retval = -1;
333 }
334
335 DRM_DEBUG("free fb, free = %ld\n", fb.free);
336
337 return retval;
338}
339
340static int via_agp_free(drm_via_mem_t * mem)
341{
342 drm_via_mm_t agp;
343
344 int retval = 0;
345
346 agp.free = mem->index;
347 agp.context = mem->context;
348
349 if (!agp.free)
350 return -1;
351
352 via_mmFreeMem((PMemBlock) agp.free);
353
354 if (!del_alloc_set(agp.context, AGP, agp.free)) {
355 retval = -1;
356 }
357
358 DRM_DEBUG("free agp, free = %ld\n", agp.free);
359
360 return retval;
361}
diff --git a/drivers/char/drm/via_mm.h b/drivers/char/drm/via_mm.h
new file mode 100644
index 000000000000..d57efda57c76
--- /dev/null
+++ b/drivers/char/drm/via_mm.h
@@ -0,0 +1,40 @@
1/*
2 * Copyright 1998-2003 VIA Technologies, Inc. All Rights Reserved.
3 * Copyright 2001-2003 S3 Graphics, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * VIA, S3 GRAPHICS, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24#ifndef _via_drm_mm_h_
25#define _via_drm_mm_h_
26
27typedef struct {
28 unsigned int context;
29 unsigned int size;
30 unsigned long offset;
31 unsigned long free;
32} drm_via_mm_t;
33
34typedef struct {
35 unsigned int size;
36 unsigned long handle;
37 void *virtual;
38} drm_via_dma_t;
39
40#endif
diff --git a/drivers/char/drm/via_verifier.c b/drivers/char/drm/via_verifier.c
new file mode 100644
index 000000000000..07923b0c7a97
--- /dev/null
+++ b/drivers/char/drm/via_verifier.c
@@ -0,0 +1,1061 @@
1/*
2 * Copyright 2004 The Unichrome Project. All Rights Reserved.
3 * Copyright 2005 Thomas Hellstrom. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sub license,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice (including the
13 * next paragraph) shall be included in all copies or substantial portions
14 * of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHOR(S), AND/OR THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 * Author: Thomas Hellstrom 2004, 2005.
25 * This code was written using docs obtained under NDA from VIA Inc.
26 *
27 * Don't run this code directly on an AGP buffer. Due to cache problems it will
28 * be very slow.
29 */
30
31
32#include "via_3d_reg.h"
33#include "drmP.h"
34#include "drm.h"
35#include "via_drm.h"
36#include "via_verifier.h"
37#include "via_drv.h"
38
39typedef enum{
40 state_command,
41 state_header2,
42 state_header1,
43 state_vheader5,
44 state_vheader6,
45 state_error
46} verifier_state_t;
47
48
49typedef enum{
50 no_check = 0,
51 check_for_header2,
52 check_for_header1,
53 check_for_header2_err,
54 check_for_header1_err,
55 check_for_fire,
56 check_z_buffer_addr0,
57 check_z_buffer_addr1,
58 check_z_buffer_addr_mode,
59 check_destination_addr0,
60 check_destination_addr1,
61 check_destination_addr_mode,
62 check_for_dummy,
63 check_for_dd,
64 check_texture_addr0,
65 check_texture_addr1,
66 check_texture_addr2,
67 check_texture_addr3,
68 check_texture_addr4,
69 check_texture_addr5,
70 check_texture_addr6,
71 check_texture_addr7,
72 check_texture_addr8,
73 check_texture_addr_mode,
74 check_for_vertex_count,
75 check_number_texunits,
76 forbidden_command
77}hazard_t;
78
79/*
80 * Associates each hazard above with a possible multi-command
81 * sequence. For example an address that is split over multiple
82 * commands and that needs to be checked at the first command
83 * that does not include any part of the address.
84 */
85
86static drm_via_sequence_t seqs[] = {
87 no_sequence,
88 no_sequence,
89 no_sequence,
90 no_sequence,
91 no_sequence,
92 no_sequence,
93 z_address,
94 z_address,
95 z_address,
96 dest_address,
97 dest_address,
98 dest_address,
99 no_sequence,
100 no_sequence,
101 tex_address,
102 tex_address,
103 tex_address,
104 tex_address,
105 tex_address,
106 tex_address,
107 tex_address,
108 tex_address,
109 tex_address,
110 tex_address,
111 no_sequence
112};
113
114typedef struct{
115 unsigned int code;
116 hazard_t hz;
117} hz_init_t;
118
119
120
121static hz_init_t init_table1[] = {
122 {0xf2, check_for_header2_err},
123 {0xf0, check_for_header1_err},
124 {0xee, check_for_fire},
125 {0xcc, check_for_dummy},
126 {0xdd, check_for_dd},
127 {0x00, no_check},
128 {0x10, check_z_buffer_addr0},
129 {0x11, check_z_buffer_addr1},
130 {0x12, check_z_buffer_addr_mode},
131 {0x13, no_check},
132 {0x14, no_check},
133 {0x15, no_check},
134 {0x23, no_check},
135 {0x24, no_check},
136 {0x33, no_check},
137 {0x34, no_check},
138 {0x35, no_check},
139 {0x36, no_check},
140 {0x37, no_check},
141 {0x38, no_check},
142 {0x39, no_check},
143 {0x3A, no_check},
144 {0x3B, no_check},
145 {0x3C, no_check},
146 {0x3D, no_check},
147 {0x3E, no_check},
148 {0x40, check_destination_addr0},
149 {0x41, check_destination_addr1},
150 {0x42, check_destination_addr_mode},
151 {0x43, no_check},
152 {0x44, no_check},
153 {0x50, no_check},
154 {0x51, no_check},
155 {0x52, no_check},
156 {0x53, no_check},
157 {0x54, no_check},
158 {0x55, no_check},
159 {0x56, no_check},
160 {0x57, no_check},
161 {0x58, no_check},
162 {0x70, no_check},
163 {0x71, no_check},
164 {0x78, no_check},
165 {0x79, no_check},
166 {0x7A, no_check},
167 {0x7B, no_check},
168 {0x7C, no_check},
169 {0x7D, check_for_vertex_count}
170};
171
172
173
174static hz_init_t init_table2[] = {
175 {0xf2, check_for_header2_err},
176 {0xf0, check_for_header1_err},
177 {0xee, check_for_fire},
178 {0xcc, check_for_dummy},
179 {0x00, check_texture_addr0},
180 {0x01, check_texture_addr0},
181 {0x02, check_texture_addr0},
182 {0x03, check_texture_addr0},
183 {0x04, check_texture_addr0},
184 {0x05, check_texture_addr0},
185 {0x06, check_texture_addr0},
186 {0x07, check_texture_addr0},
187 {0x08, check_texture_addr0},
188 {0x09, check_texture_addr0},
189 {0x20, check_texture_addr1},
190 {0x21, check_texture_addr1},
191 {0x22, check_texture_addr1},
192 {0x23, check_texture_addr4},
193 {0x2B, check_texture_addr3},
194 {0x2C, check_texture_addr3},
195 {0x2D, check_texture_addr3},
196 {0x2E, check_texture_addr3},
197 {0x2F, check_texture_addr3},
198 {0x30, check_texture_addr3},
199 {0x31, check_texture_addr3},
200 {0x32, check_texture_addr3},
201 {0x33, check_texture_addr3},
202 {0x34, check_texture_addr3},
203 {0x4B, check_texture_addr5},
204 {0x4C, check_texture_addr6},
205 {0x51, check_texture_addr7},
206 {0x52, check_texture_addr8},
207 {0x77, check_texture_addr2},
208 {0x78, no_check},
209 {0x79, no_check},
210 {0x7A, no_check},
211 {0x7B, check_texture_addr_mode},
212 {0x7C, no_check},
213 {0x7D, no_check},
214 {0x7E, no_check},
215 {0x7F, no_check},
216 {0x80, no_check},
217 {0x81, no_check},
218 {0x82, no_check},
219 {0x83, no_check},
220 {0x85, no_check},
221 {0x86, no_check},
222 {0x87, no_check},
223 {0x88, no_check},
224 {0x89, no_check},
225 {0x8A, no_check},
226 {0x90, no_check},
227 {0x91, no_check},
228 {0x92, no_check},
229 {0x93, no_check}
230};
231
232static hz_init_t init_table3[] = {
233 {0xf2, check_for_header2_err},
234 {0xf0, check_for_header1_err},
235 {0xcc, check_for_dummy},
236 {0x00, check_number_texunits}
237};
238
239
240static hazard_t table1[256];
241static hazard_t table2[256];
242static hazard_t table3[256];
243
244
245
246static __inline__ int
247eat_words(const uint32_t **buf, const uint32_t *buf_end, unsigned num_words)
248{
249 if ((*buf - buf_end) >= num_words) {
250 *buf += num_words;
251 return 0;
252 }
253 DRM_ERROR("Illegal termination of DMA command buffer\n");
254 return 1;
255}
256
257
258/*
259 * Partially stolen from drm_memory.h
260 */
261
262static __inline__ drm_map_t *
263via_drm_lookup_agp_map (drm_via_state_t *seq, unsigned long offset, unsigned long size,
264 drm_device_t *dev)
265{
266 struct list_head *list;
267 drm_map_list_t *r_list;
268 drm_map_t *map = seq->map_cache;
269
270 if (map && map->offset <= offset && (offset + size) <= (map->offset + map->size)) {
271 return map;
272 }
273
274 list_for_each(list, &dev->maplist->head) {
275 r_list = (drm_map_list_t *) list;
276 map = r_list->map;
277 if (!map)
278 continue;
279 if (map->offset <= offset && (offset + size) <= (map->offset + map->size) &&
280 !(map->flags & _DRM_RESTRICTED) && (map->type == _DRM_AGP)) {
281 seq->map_cache = map;
282 return map;
283 }
284 }
285 return NULL;
286}
287
288
289/*
290 * Require that all AGP texture levels reside in the same AGP map which should
291 * be mappable by the client. This is not a big restriction.
292 * FIXME: To actually enforce this security policy strictly, drm_rmmap
293 * would have to wait for dma quiescent before removing an AGP map.
294 * The via_drm_lookup_agp_map call in reality seems to take
295 * very little CPU time.
296 */
297
298
299static __inline__ int
300finish_current_sequence(drm_via_state_t *cur_seq)
301{
302 switch(cur_seq->unfinished) {
303 case z_address:
304 DRM_DEBUG("Z Buffer start address is 0x%x\n", cur_seq->z_addr);
305 break;
306 case dest_address:
307 DRM_DEBUG("Destination start address is 0x%x\n", cur_seq->d_addr);
308 break;
309 case tex_address:
310 if (cur_seq->agp_texture) {
311 unsigned start = cur_seq->tex_level_lo[cur_seq->texture];
312 unsigned end = cur_seq->tex_level_hi[cur_seq->texture];
313 unsigned long lo=~0, hi=0, tmp;
314 uint32_t *addr, *pitch, *height, tex;
315 unsigned i;
316
317 if (end > 9) end = 9;
318 if (start > 9) start = 9;
319
320 addr =&(cur_seq->t_addr[tex = cur_seq->texture][start]);
321 pitch = &(cur_seq->pitch[tex][start]);
322 height = &(cur_seq->height[tex][start]);
323
324 for (i=start; i<= end; ++i) {
325 tmp = *addr++;
326 if (tmp < lo) lo = tmp;
327 tmp += (*height++ << *pitch++);
328 if (tmp > hi) hi = tmp;
329 }
330
331 if (! via_drm_lookup_agp_map (cur_seq, lo, hi - lo, cur_seq->dev)) {
332 DRM_ERROR("AGP texture is not in allowed map\n");
333 return 2;
334 }
335 }
336 break;
337 default:
338 break;
339 }
340 cur_seq->unfinished = no_sequence;
341 return 0;
342}
343
344static __inline__ int
345investigate_hazard( uint32_t cmd, hazard_t hz, drm_via_state_t *cur_seq)
346{
347 register uint32_t tmp, *tmp_addr;
348
349 if (cur_seq->unfinished && (cur_seq->unfinished != seqs[hz])) {
350 int ret;
351 if ((ret = finish_current_sequence(cur_seq))) return ret;
352 }
353
354 switch(hz) {
355 case check_for_header2:
356 if (cmd == HALCYON_HEADER2) return 1;
357 return 0;
358 case check_for_header1:
359 if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) return 1;
360 return 0;
361 case check_for_header2_err:
362 if (cmd == HALCYON_HEADER2) return 1;
363 DRM_ERROR("Illegal DMA HALCYON_HEADER2 command\n");
364 break;
365 case check_for_header1_err:
366 if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1) return 1;
367 DRM_ERROR("Illegal DMA HALCYON_HEADER1 command\n");
368 break;
369 case check_for_fire:
370 if ((cmd & HALCYON_FIREMASK) == HALCYON_FIRECMD) return 1;
371 DRM_ERROR("Illegal DMA HALCYON_FIRECMD command\n");
372 break;
373 case check_for_dummy:
374 if (HC_DUMMY == cmd) return 0;
375 DRM_ERROR("Illegal DMA HC_DUMMY command\n");
376 break;
377 case check_for_dd:
378 if (0xdddddddd == cmd) return 0;
379 DRM_ERROR("Illegal DMA 0xdddddddd command\n");
380 break;
381 case check_z_buffer_addr0:
382 cur_seq->unfinished = z_address;
383 cur_seq->z_addr = (cur_seq->z_addr & 0xFF000000) |
384 (cmd & 0x00FFFFFF);
385 return 0;
386 case check_z_buffer_addr1:
387 cur_seq->unfinished = z_address;
388 cur_seq->z_addr = (cur_seq->z_addr & 0x00FFFFFF) |
389 ((cmd & 0xFF) << 24);
390 return 0;
391 case check_z_buffer_addr_mode:
392 cur_seq->unfinished = z_address;
393 if ((cmd & 0x0000C000) == 0) return 0;
394 DRM_ERROR("Attempt to place Z buffer in system memory\n");
395 return 2;
396 case check_destination_addr0:
397 cur_seq->unfinished = dest_address;
398 cur_seq->d_addr = (cur_seq->d_addr & 0xFF000000) |
399 (cmd & 0x00FFFFFF);
400 return 0;
401 case check_destination_addr1:
402 cur_seq->unfinished = dest_address;
403 cur_seq->d_addr = (cur_seq->d_addr & 0x00FFFFFF) |
404 ((cmd & 0xFF) << 24);
405 return 0;
406 case check_destination_addr_mode:
407 cur_seq->unfinished = dest_address;
408 if ((cmd & 0x0000C000) == 0) return 0;
409 DRM_ERROR("Attempt to place 3D drawing buffer in system memory\n");
410 return 2;
411 case check_texture_addr0:
412 cur_seq->unfinished = tex_address;
413 tmp = (cmd >> 24);
414 tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
415 *tmp_addr = (*tmp_addr & 0xFF000000) | (cmd & 0x00FFFFFF);
416 return 0;
417 case check_texture_addr1:
418 cur_seq->unfinished = tex_address;
419 tmp = ((cmd >> 24) - 0x20);
420 tmp += tmp << 1;
421 tmp_addr = &cur_seq->t_addr[cur_seq->texture][tmp];
422 *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
423 tmp_addr++;
424 *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF00) << 16);
425 tmp_addr++;
426 *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF0000) << 8);
427 return 0;
428 case check_texture_addr2:
429 cur_seq->unfinished = tex_address;
430 cur_seq->tex_level_lo[tmp = cur_seq->texture] = cmd & 0x3F;
431 cur_seq->tex_level_hi[tmp] = (cmd & 0xFC0) >> 6;
432 return 0;
433 case check_texture_addr3:
434 cur_seq->unfinished = tex_address;
435 tmp = ((cmd >> 24) - 0x2B);
436 cur_seq->pitch[cur_seq->texture][tmp] = (cmd & 0x00F00000) >> 20;
437 if (!tmp && (cmd & 0x000FFFFF)) {
438 DRM_ERROR("Unimplemented texture level 0 pitch mode.\n");
439 return 2;
440 }
441 return 0;
442 case check_texture_addr4:
443 cur_seq->unfinished = tex_address;
444 tmp_addr = &cur_seq->t_addr[cur_seq->texture][9];
445 *tmp_addr = (*tmp_addr & 0x00FFFFFF) | ((cmd & 0xFF) << 24);
446 return 0;
447 case check_texture_addr5:
448 case check_texture_addr6:
449 cur_seq->unfinished = tex_address;
450 /*
451 * Texture width. We don't care since we have the pitch.
452 */
453 return 0;
454 case check_texture_addr7:
455 cur_seq->unfinished = tex_address;
456 tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
457 tmp_addr[5] = 1 << ((cmd & 0x00F00000) >> 20);
458 tmp_addr[4] = 1 << ((cmd & 0x000F0000) >> 16);
459 tmp_addr[3] = 1 << ((cmd & 0x0000F000) >> 12);
460 tmp_addr[2] = 1 << ((cmd & 0x00000F00) >> 8);
461 tmp_addr[1] = 1 << ((cmd & 0x000000F0) >> 4);
462 tmp_addr[0] = 1 << (cmd & 0x0000000F);
463 return 0;
464 case check_texture_addr8:
465 cur_seq->unfinished = tex_address;
466 tmp_addr = &(cur_seq->height[cur_seq->texture][0]);
467 tmp_addr[9] = 1 << ((cmd & 0x0000F000) >> 12);
468 tmp_addr[8] = 1 << ((cmd & 0x00000F00) >> 8);
469 tmp_addr[7] = 1 << ((cmd & 0x000000F0) >> 4);
470 tmp_addr[6] = 1 << (cmd & 0x0000000F);
471 return 0;
472 case check_texture_addr_mode:
473 cur_seq->unfinished = tex_address;
474 if ( 2 == (tmp = cmd & 0x00000003)) {
475 DRM_ERROR("Attempt to fetch texture from system memory.\n");
476 return 2;
477 }
478 cur_seq->agp_texture = (tmp == 3);
479 cur_seq->tex_palette_size[cur_seq->texture] =
480 (cmd >> 16) & 0x000000007;
481 return 0;
482 case check_for_vertex_count:
483 cur_seq->vertex_count = cmd & 0x0000FFFF;
484 return 0;
485 case check_number_texunits:
486 cur_seq->multitex = (cmd >> 3) & 1;
487 return 0;
488 default:
489 DRM_ERROR("Illegal DMA data: 0x%x\n", cmd);
490 return 2;
491 }
492 return 2;
493}
494
495
496static __inline__ int
497via_check_prim_list(uint32_t const **buffer, const uint32_t *buf_end,
498 drm_via_state_t *cur_seq)
499{
500 drm_via_private_t *dev_priv = (drm_via_private_t *) cur_seq->dev->dev_private;
501 uint32_t a_fire, bcmd , dw_count;
502 int ret = 0;
503 int have_fire;
504 const uint32_t *buf = *buffer;
505
506 while(buf < buf_end) {
507 have_fire = 0;
508 if ((buf_end - buf) < 2) {
509 DRM_ERROR("Unexpected termination of primitive list.\n");
510 ret = 1;
511 break;
512 }
513 if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdB) break;
514 bcmd = *buf++;
515 if ((*buf & HC_ACMD_MASK) != HC_ACMD_HCmdA) {
516 DRM_ERROR("Expected Vertex List A command, got 0x%x\n",
517 *buf);
518 ret = 1;
519 break;
520 }
521 a_fire = *buf++ | HC_HPLEND_MASK | HC_HPMValidN_MASK | HC_HE3Fire_MASK;
522
523 /*
524 * How many dwords per vertex ?
525 */
526
527 if (cur_seq->agp && ((bcmd & (0xF << 11)) == 0)) {
528 DRM_ERROR("Illegal B command vertex data for AGP.\n");
529 ret = 1;
530 break;
531 }
532
533 dw_count = 0;
534 if (bcmd & (1 << 7)) dw_count += (cur_seq->multitex) ? 2:1;
535 if (bcmd & (1 << 8)) dw_count += (cur_seq->multitex) ? 2:1;
536 if (bcmd & (1 << 9)) dw_count++;
537 if (bcmd & (1 << 10)) dw_count++;
538 if (bcmd & (1 << 11)) dw_count++;
539 if (bcmd & (1 << 12)) dw_count++;
540 if (bcmd & (1 << 13)) dw_count++;
541 if (bcmd & (1 << 14)) dw_count++;
542
543 while(buf < buf_end) {
544 if (*buf == a_fire) {
545 if (dev_priv->num_fire_offsets >= VIA_FIRE_BUF_SIZE) {
546 DRM_ERROR("Fire offset buffer full.\n");
547 ret = 1;
548 break;
549 }
550 dev_priv->fire_offsets[dev_priv->num_fire_offsets++] = buf;
551 have_fire = 1;
552 buf++;
553 if (buf < buf_end && *buf == a_fire)
554 buf++;
555 break;
556 }
557 if ((*buf == HALCYON_HEADER2) ||
558 ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD)) {
559 DRM_ERROR("Missing Vertex Fire command, "
560 "Stray Vertex Fire command or verifier "
561 "lost sync.\n");
562 ret = 1;
563 break;
564 }
565 if ((ret = eat_words(&buf, buf_end, dw_count)))
566 break;
567 }
568 if (buf >= buf_end && !have_fire) {
569 DRM_ERROR("Missing Vertex Fire command or verifier "
570 "lost sync.\n");
571 ret = 1;
572 break;
573 }
574 if (cur_seq->agp && ((buf - cur_seq->buf_start) & 0x01)) {
575 DRM_ERROR("AGP Primitive list end misaligned.\n");
576 ret = 1;
577 break;
578 }
579 }
580 *buffer = buf;
581 return ret;
582}
583
584
585
586
587
588static __inline__ verifier_state_t
589via_check_header2( uint32_t const **buffer, const uint32_t *buf_end,
590 drm_via_state_t *hc_state)
591{
592 uint32_t cmd;
593 int hz_mode;
594 hazard_t hz;
595 const uint32_t *buf = *buffer;
596 const hazard_t *hz_table;
597
598
599 if ((buf_end - buf) < 2) {
600 DRM_ERROR("Illegal termination of DMA HALCYON_HEADER2 sequence.\n");
601 return state_error;
602 }
603 buf++;
604 cmd = (*buf++ & 0xFFFF0000) >> 16;
605
606 switch(cmd) {
607 case HC_ParaType_CmdVdata:
608 if (via_check_prim_list(&buf, buf_end, hc_state ))
609 return state_error;
610 *buffer = buf;
611 return state_command;
612 case HC_ParaType_NotTex:
613 hz_table = table1;
614 break;
615 case HC_ParaType_Tex:
616 hc_state->texture = 0;
617 hz_table = table2;
618 break;
619 case (HC_ParaType_Tex | (HC_SubType_Tex1 << 8)):
620 hc_state->texture = 1;
621 hz_table = table2;
622 break;
623 case (HC_ParaType_Tex | (HC_SubType_TexGeneral << 8)):
624 hz_table = table3;
625 break;
626 case HC_ParaType_Auto:
627 if (eat_words(&buf, buf_end, 2))
628 return state_error;
629 *buffer = buf;
630 return state_command;
631 case (HC_ParaType_Palette | (HC_SubType_Stipple << 8)):
632 if (eat_words(&buf, buf_end, 32))
633 return state_error;
634 *buffer = buf;
635 return state_command;
636 case (HC_ParaType_Palette | (HC_SubType_TexPalette0 << 8)):
637 case (HC_ParaType_Palette | (HC_SubType_TexPalette1 << 8)):
638 DRM_ERROR("Texture palettes are rejected because of "
639 "lack of info how to determine their size.\n");
640 return state_error;
641 case (HC_ParaType_Palette | (HC_SubType_FogTable << 8)):
642 DRM_ERROR("Fog factor palettes are rejected because of "
643 "lack of info how to determine their size.\n");
644 return state_error;
645 default:
646
647 /*
648 * There are some unimplemented HC_ParaTypes here, that
649 * need to be implemented if the Mesa driver is extended.
650 */
651
652 DRM_ERROR("Invalid or unimplemented HALCYON_HEADER2 "
653 "DMA subcommand: 0x%x. Previous dword: 0x%x\n",
654 cmd, *(buf -2));
655 *buffer = buf;
656 return state_error;
657 }
658
659 while(buf < buf_end) {
660 cmd = *buf++;
661 if ((hz = hz_table[cmd >> 24])) {
662 if ((hz_mode = investigate_hazard(cmd, hz, hc_state))) {
663 if (hz_mode == 1) {
664 buf--;
665 break;
666 }
667 return state_error;
668 }
669 } else if (hc_state->unfinished &&
670 finish_current_sequence(hc_state)) {
671 return state_error;
672 }
673 }
674 if (hc_state->unfinished && finish_current_sequence(hc_state)) {
675 return state_error;
676 }
677 *buffer = buf;
678 return state_command;
679}
680
681static __inline__ verifier_state_t
682via_parse_header2( drm_via_private_t *dev_priv, uint32_t const **buffer, const uint32_t *buf_end,
683 int *fire_count)
684{
685 uint32_t cmd;
686 const uint32_t *buf = *buffer;
687 const uint32_t *next_fire;
688 int burst = 0;
689
690 next_fire = dev_priv->fire_offsets[*fire_count];
691 buf++;
692 cmd = (*buf & 0xFFFF0000) >> 16;
693 VIA_WRITE(HC_REG_TRANS_SET + HC_REG_BASE, *buf++);
694 switch(cmd) {
695 case HC_ParaType_CmdVdata:
696 while ((buf < buf_end) &&
697 (*fire_count < dev_priv->num_fire_offsets) &&
698 (*buf & HC_ACMD_MASK) == HC_ACMD_HCmdB ) {
699 while(buf <= next_fire) {
700 VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE + (burst & 63), *buf++);
701 burst += 4;
702 }
703 if ( ( buf < buf_end ) && ((*buf & HALCYON_FIREMASK) == HALCYON_FIRECMD))
704 buf++;
705
706 if (++(*fire_count) < dev_priv->num_fire_offsets)
707 next_fire = dev_priv->fire_offsets[*fire_count];
708 }
709 break;
710 default:
711 while(buf < buf_end) {
712
713 if ( *buf == HC_HEADER2 ||
714 (*buf & HALCYON_HEADER1MASK) == HALCYON_HEADER1 ||
715 (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5 ||
716 (*buf & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6 ) break;
717
718 VIA_WRITE(HC_REG_TRANS_SPACE + HC_REG_BASE + (burst & 63), *buf++);
719 burst +=4;
720 }
721 }
722 *buffer = buf;
723 return state_command;
724}
725
726
727
728static __inline__ int
729verify_mmio_address( uint32_t address)
730{
731 if ((address > 0x3FF) && (address < 0xC00 )) {
732 DRM_ERROR("Invalid VIDEO DMA command. "
733 "Attempt to access 3D- or command burst area.\n");
734 return 1;
735 } else if ((address > 0xCFF) && (address < 0x1300)) {
736 DRM_ERROR("Invalid VIDEO DMA command. "
737 "Attempt to access PCI DMA area.\n");
738 return 1;
739 } else if (address > 0x13FF ) {
740 DRM_ERROR("Invalid VIDEO DMA command. "
741 "Attempt to access VGA registers.\n");
742 return 1;
743 }
744 return 0;
745}
746
747static __inline__ int
748verify_video_tail( uint32_t const **buffer, const uint32_t *buf_end, uint32_t dwords)
749{
750 const uint32_t *buf = *buffer;
751
752 if (buf_end - buf < dwords) {
753 DRM_ERROR("Illegal termination of video command.\n");
754 return 1;
755 }
756 while (dwords--) {
757 if (*buf++) {
758 DRM_ERROR("Illegal video command tail.\n");
759 return 1;
760 }
761 }
762 *buffer = buf;
763 return 0;
764}
765
766
767static __inline__ verifier_state_t
768via_check_header1( uint32_t const **buffer, const uint32_t *buf_end )
769{
770 uint32_t cmd;
771 const uint32_t *buf = *buffer;
772 verifier_state_t ret = state_command;
773
774 while (buf < buf_end) {
775 cmd = *buf;
776 if ((cmd > ((0x3FF >> 2) | HALCYON_HEADER1)) &&
777 (cmd < ((0xC00 >> 2) | HALCYON_HEADER1))) {
778 if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
779 break;
780 DRM_ERROR("Invalid HALCYON_HEADER1 command. "
781 "Attempt to access 3D- or command burst area.\n");
782 ret = state_error;
783 break;
784 } else if (cmd > ((0xCFF >> 2) | HALCYON_HEADER1)) {
785 if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1)
786 break;
787 DRM_ERROR("Invalid HALCYON_HEADER1 command. "
788 "Attempt to access VGA registers.\n");
789 ret = state_error;
790 break;
791 } else {
792 buf += 2;
793 }
794 }
795 *buffer = buf;
796 return ret;
797}
798
799static __inline__ verifier_state_t
800via_parse_header1( drm_via_private_t *dev_priv, uint32_t const **buffer, const uint32_t *buf_end )
801{
802 register uint32_t cmd;
803 const uint32_t *buf = *buffer;
804
805 while (buf < buf_end) {
806 cmd = *buf;
807 if ((cmd & HALCYON_HEADER1MASK) != HALCYON_HEADER1) break;
808 VIA_WRITE( (cmd & ~HALCYON_HEADER1MASK) << 2, *++buf);
809 buf++;
810 }
811 *buffer = buf;
812 return state_command;
813}
814
815static __inline__ verifier_state_t
816via_check_vheader5( uint32_t const **buffer, const uint32_t *buf_end )
817{
818 uint32_t data;
819 const uint32_t *buf = *buffer;
820
821 if (buf_end - buf < 4) {
822 DRM_ERROR("Illegal termination of video header5 command\n");
823 return state_error;
824 }
825
826 data = *buf++ & ~VIA_VIDEOMASK;
827 if (verify_mmio_address(data))
828 return state_error;
829
830 data = *buf++;
831 if (*buf++ != 0x00F50000) {
832 DRM_ERROR("Illegal header5 header data\n");
833 return state_error;
834 }
835 if (*buf++ != 0x00000000) {
836 DRM_ERROR("Illegal header5 header data\n");
837 return state_error;
838 }
839 if (eat_words(&buf, buf_end, data))
840 return state_error;
841 if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
842 return state_error;
843 *buffer = buf;
844 return state_command;
845
846}
847
848static __inline__ verifier_state_t
849via_parse_vheader5( drm_via_private_t *dev_priv, uint32_t const **buffer, const uint32_t *buf_end )
850{
851 uint32_t addr, count, i;
852 const uint32_t *buf = *buffer;
853
854 addr = *buf++ & ~VIA_VIDEOMASK;
855 i = count = *buf;
856 buf += 3;
857 while(i--) {
858 VIA_WRITE(addr, *buf++);
859 }
860 if (count & 3) buf += 4 - (count & 3);
861 *buffer = buf;
862 return state_command;
863}
864
865
866static __inline__ verifier_state_t
867via_check_vheader6( uint32_t const **buffer, const uint32_t *buf_end )
868{
869 uint32_t data;
870 const uint32_t *buf = *buffer;
871 uint32_t i;
872
873
874 if (buf_end - buf < 4) {
875 DRM_ERROR("Illegal termination of video header6 command\n");
876 return state_error;
877 }
878 buf++;
879 data = *buf++;
880 if (*buf++ != 0x00F60000) {
881 DRM_ERROR("Illegal header6 header data\n");
882 return state_error;
883 }
884 if (*buf++ != 0x00000000) {
885 DRM_ERROR("Illegal header6 header data\n");
886 return state_error;
887 }
888 if ((buf_end - buf) < (data << 1)) {
889 DRM_ERROR("Illegal termination of video header6 command\n");
890 return state_error;
891 }
892 for (i=0; i<data; ++i) {
893 if (verify_mmio_address(*buf++))
894 return state_error;
895 buf++;
896 }
897 data <<= 1;
898 if ((data & 3) && verify_video_tail(&buf, buf_end, 4 - (data & 3)))
899 return state_error;
900 *buffer = buf;
901 return state_command;
902}
903
904static __inline__ verifier_state_t
905via_parse_vheader6( drm_via_private_t *dev_priv, uint32_t const **buffer, const uint32_t *buf_end )
906{
907
908 uint32_t addr, count, i;
909 const uint32_t *buf = *buffer;
910
911 i = count = *++buf;
912 buf += 3;
913 while(i--) {
914 addr = *buf++;
915 VIA_WRITE(addr, *buf++);
916 }
917 count <<= 1;
918 if (count & 3) buf += 4 - (count & 3);
919 *buffer = buf;
920 return state_command;
921}
922
923
924
925int
926via_verify_command_stream(const uint32_t * buf, unsigned int size, drm_device_t *dev,
927 int agp)
928{
929
930 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
931 drm_via_state_t *hc_state = &dev_priv->hc_state;
932 drm_via_state_t saved_state = *hc_state;
933 uint32_t cmd;
934 const uint32_t *buf_end = buf + ( size >> 2 );
935 verifier_state_t state = state_command;
936 int pro_group_a = dev_priv->pro_group_a;
937
938 hc_state->dev = dev;
939 hc_state->unfinished = no_sequence;
940 hc_state->map_cache = NULL;
941 hc_state->agp = agp;
942 hc_state->buf_start = buf;
943 dev_priv->num_fire_offsets = 0;
944
945 while (buf < buf_end) {
946
947 switch (state) {
948 case state_header2:
949 state = via_check_header2( &buf, buf_end, hc_state );
950 break;
951 case state_header1:
952 state = via_check_header1( &buf, buf_end );
953 break;
954 case state_vheader5:
955 state = via_check_vheader5( &buf, buf_end );
956 break;
957 case state_vheader6:
958 state = via_check_vheader6( &buf, buf_end );
959 break;
960 case state_command:
961 if (HALCYON_HEADER2 == (cmd = *buf))
962 state = state_header2;
963 else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
964 state = state_header1;
965 else if (pro_group_a && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
966 state = state_vheader5;
967 else if (pro_group_a && (cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
968 state = state_vheader6;
969 else {
970 DRM_ERROR("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
971 cmd);
972 state = state_error;
973 }
974 break;
975 case state_error:
976 default:
977 *hc_state = saved_state;
978 return DRM_ERR(EINVAL);
979 }
980 }
981 if (state == state_error) {
982 *hc_state = saved_state;
983 return DRM_ERR(EINVAL);
984 }
985 return 0;
986}
987
988int
989via_parse_command_stream(drm_device_t *dev, const uint32_t * buf, unsigned int size)
990{
991
992 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
993 uint32_t cmd;
994 const uint32_t *buf_end = buf + ( size >> 2 );
995 verifier_state_t state = state_command;
996 int fire_count = 0;
997
998 while (buf < buf_end) {
999
1000 switch (state) {
1001 case state_header2:
1002 state = via_parse_header2( dev_priv, &buf, buf_end, &fire_count );
1003 break;
1004 case state_header1:
1005 state = via_parse_header1( dev_priv, &buf, buf_end );
1006 break;
1007 case state_vheader5:
1008 state = via_parse_vheader5( dev_priv, &buf, buf_end );
1009 break;
1010 case state_vheader6:
1011 state = via_parse_vheader6( dev_priv, &buf, buf_end );
1012 break;
1013 case state_command:
1014 if (HALCYON_HEADER2 == (cmd = *buf))
1015 state = state_header2;
1016 else if ((cmd & HALCYON_HEADER1MASK) == HALCYON_HEADER1)
1017 state = state_header1;
1018 else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER5)
1019 state = state_vheader5;
1020 else if ((cmd & VIA_VIDEOMASK) == VIA_VIDEO_HEADER6)
1021 state = state_vheader6;
1022 else {
1023 DRM_ERROR("Invalid / Unimplemented DMA HEADER command. 0x%x\n",
1024 cmd);
1025 state = state_error;
1026 }
1027 break;
1028 case state_error:
1029 default:
1030 return DRM_ERR(EINVAL);
1031 }
1032 }
1033 if (state == state_error) {
1034 return DRM_ERR(EINVAL);
1035 }
1036 return 0;
1037}
1038
1039
1040
1041static void
1042setup_hazard_table(hz_init_t init_table[], hazard_t table[], int size)
1043{
1044 int i;
1045
1046 for(i=0; i<256; ++i) {
1047 table[i] = forbidden_command;
1048 }
1049
1050 for(i=0; i<size; ++i) {
1051 table[init_table[i].code] = init_table[i].hz;
1052 }
1053}
1054
1055void
1056via_init_command_verifier( void )
1057{
1058 setup_hazard_table(init_table1, table1, sizeof(init_table1) / sizeof(hz_init_t));
1059 setup_hazard_table(init_table2, table2, sizeof(init_table2) / sizeof(hz_init_t));
1060 setup_hazard_table(init_table3, table3, sizeof(init_table3) / sizeof(hz_init_t));
1061}
diff --git a/drivers/char/drm/via_verifier.h b/drivers/char/drm/via_verifier.h
new file mode 100644
index 000000000000..a8e13592620f
--- /dev/null
+++ b/drivers/char/drm/via_verifier.h
@@ -0,0 +1,61 @@
1/*
2 * Copyright 2004 The Unichrome Project. All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sub license,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
13 * of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE UNICHROME PROJECT, AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Author: Thomas Hellström 2004.
24 */
25
26#ifndef _VIA_VERIFIER_H_
27#define _VIA_VERIFIER_H_
28
29typedef enum{
30 no_sequence = 0,
31 z_address,
32 dest_address,
33 tex_address
34}drm_via_sequence_t;
35
36
37
38typedef struct{
39 unsigned texture;
40 uint32_t z_addr;
41 uint32_t d_addr;
42 uint32_t t_addr[2][10];
43 uint32_t pitch[2][10];
44 uint32_t height[2][10];
45 uint32_t tex_level_lo[2];
46 uint32_t tex_level_hi[2];
47 uint32_t tex_palette_size[2];
48 drm_via_sequence_t unfinished;
49 int agp_texture;
50 int multitex;
51 drm_device_t *dev;
52 drm_map_t *map_cache;
53 uint32_t vertex_count;
54 int agp;
55 const uint32_t *buf_start;
56} drm_via_state_t;
57
58extern int via_verify_command_stream(const uint32_t * buf, unsigned int size,
59 drm_device_t *dev, int agp);
60
61#endif
diff --git a/drivers/char/drm/via_video.c b/drivers/char/drm/via_video.c
new file mode 100644
index 000000000000..1e2d444587bf
--- /dev/null
+++ b/drivers/char/drm/via_video.c
@@ -0,0 +1,98 @@
1/*
2 * Copyright 2005 Thomas Hellstrom. All Rights Reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sub license,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
13 * of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHOR(S), AND/OR THE COPYRIGHT HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Author: Thomas Hellstrom 2005.
24 *
25 * Video and XvMC related functions.
26 */
27
28#include "drmP.h"
29#include "via_drm.h"
30#include "via_drv.h"
31
32void
33via_init_futex(drm_via_private_t *dev_priv)
34{
35 unsigned int i;
36
37 DRM_DEBUG("%s\n", __FUNCTION__);
38
39 for (i = 0; i < VIA_NR_XVMC_LOCKS; ++i) {
40 DRM_INIT_WAITQUEUE(&(dev_priv->decoder_queue[i]));
41 XVMCLOCKPTR(dev_priv->sarea_priv, i)->lock = 0;
42 }
43}
44
45void
46via_cleanup_futex(drm_via_private_t *dev_priv)
47{
48}
49
50void
51via_release_futex(drm_via_private_t *dev_priv, int context)
52{
53 unsigned int i;
54 volatile int *lock;
55
56 for (i=0; i < VIA_NR_XVMC_LOCKS; ++i) {
57 lock = (int *) XVMCLOCKPTR(dev_priv->sarea_priv, i);
58 if ( (_DRM_LOCKING_CONTEXT( *lock ) == context)) {
59 if (_DRM_LOCK_IS_HELD( *lock ) && (*lock & _DRM_LOCK_CONT)) {
60 DRM_WAKEUP( &(dev_priv->decoder_queue[i]));
61 }
62 *lock = 0;
63 }
64 }
65}
66
67int
68via_decoder_futex(DRM_IOCTL_ARGS)
69{
70 DRM_DEVICE;
71 drm_via_futex_t fx;
72 volatile int *lock;
73 drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
74 drm_via_sarea_t *sAPriv = dev_priv->sarea_priv;
75 int ret = 0;
76
77 DRM_DEBUG("%s\n", __FUNCTION__);
78
79 DRM_COPY_FROM_USER_IOCTL(fx, (drm_via_futex_t __user *) data,
80 sizeof(fx));
81
82 if (fx.lock > VIA_NR_XVMC_LOCKS)
83 return -EFAULT;
84
85 lock = (int *)XVMCLOCKPTR(sAPriv, fx.lock);
86
87 switch (fx.func) {
88 case VIA_FUTEX_WAIT:
89 DRM_WAIT_ON(ret, dev_priv->decoder_queue[fx.lock],
90 (fx.ms / 10) * (DRM_HZ / 100), *lock != fx.val);
91 return ret;
92 case VIA_FUTEX_WAKE:
93 DRM_WAKEUP(&(dev_priv->decoder_queue[fx.lock]));
94 return 0;
95 }
96 return 0;
97}
98
diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c
index 7def6ad51798..62cda25724e3 100644
--- a/drivers/char/ds1620.c
+++ b/drivers/char/ds1620.c
@@ -163,8 +163,7 @@ static void ds1620_out(int cmd, int bits, int value)
163 netwinder_ds1620_reset(); 163 netwinder_ds1620_reset();
164 netwinder_unlock(&flags); 164 netwinder_unlock(&flags);
165 165
166 set_current_state(TASK_INTERRUPTIBLE); 166 msleep(20);
167 schedule_timeout(2);
168} 167}
169 168
170static unsigned int ds1620_in(int cmd, int bits) 169static unsigned int ds1620_in(int cmd, int bits)
diff --git a/drivers/char/dsp56k.c b/drivers/char/dsp56k.c
index 37d6649011ad..26271e3ca823 100644
--- a/drivers/char/dsp56k.c
+++ b/drivers/char/dsp56k.c
@@ -144,7 +144,7 @@ static struct dsp56k_device {
144 int tx_wsize, rx_wsize; 144 int tx_wsize, rx_wsize;
145} dsp56k; 145} dsp56k;
146 146
147static struct class_simple *dsp56k_class; 147static struct class *dsp56k_class;
148 148
149static int dsp56k_reset(void) 149static int dsp56k_reset(void)
150{ 150{
@@ -510,12 +510,12 @@ static int __init dsp56k_init_driver(void)
510 printk("DSP56k driver: Unable to register driver\n"); 510 printk("DSP56k driver: Unable to register driver\n");
511 return -ENODEV; 511 return -ENODEV;
512 } 512 }
513 dsp56k_class = class_simple_create(THIS_MODULE, "dsp56k"); 513 dsp56k_class = class_create(THIS_MODULE, "dsp56k");
514 if (IS_ERR(dsp56k_class)) { 514 if (IS_ERR(dsp56k_class)) {
515 err = PTR_ERR(dsp56k_class); 515 err = PTR_ERR(dsp56k_class);
516 goto out_chrdev; 516 goto out_chrdev;
517 } 517 }
518 class_simple_device_add(dsp56k_class, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k"); 518 class_device_create(dsp56k_class, MKDEV(DSP56K_MAJOR, 0), NULL, "dsp56k");
519 519
520 err = devfs_mk_cdev(MKDEV(DSP56K_MAJOR, 0), 520 err = devfs_mk_cdev(MKDEV(DSP56K_MAJOR, 0),
521 S_IFCHR | S_IRUSR | S_IWUSR, "dsp56k"); 521 S_IFCHR | S_IRUSR | S_IWUSR, "dsp56k");
@@ -526,8 +526,8 @@ static int __init dsp56k_init_driver(void)
526 goto out; 526 goto out;
527 527
528out_class: 528out_class:
529 class_simple_device_remove(MKDEV(DSP56K_MAJOR, 0)); 529 class_device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0));
530 class_simple_destroy(dsp56k_class); 530 class_destroy(dsp56k_class);
531out_chrdev: 531out_chrdev:
532 unregister_chrdev(DSP56K_MAJOR, "dsp56k"); 532 unregister_chrdev(DSP56K_MAJOR, "dsp56k");
533out: 533out:
@@ -537,8 +537,8 @@ module_init(dsp56k_init_driver);
537 537
538static void __exit dsp56k_cleanup_driver(void) 538static void __exit dsp56k_cleanup_driver(void)
539{ 539{
540 class_simple_device_remove(MKDEV(DSP56K_MAJOR, 0)); 540 class_device_destroy(dsp56k_class, MKDEV(DSP56K_MAJOR, 0));
541 class_simple_destroy(dsp56k_class); 541 class_destroy(dsp56k_class);
542 unregister_chrdev(DSP56K_MAJOR, "dsp56k"); 542 unregister_chrdev(DSP56K_MAJOR, "dsp56k");
543 devfs_remove("dsp56k"); 543 devfs_remove("dsp56k");
544} 544}
diff --git a/drivers/char/ftape/compressor/zftape-compress.c b/drivers/char/ftape/compressor/zftape-compress.c
index 220a227e6061..65ffc0be3df9 100644
--- a/drivers/char/ftape/compressor/zftape-compress.c
+++ b/drivers/char/ftape/compressor/zftape-compress.c
@@ -1176,8 +1176,8 @@ KERN_INFO "Compressor for zftape (lzrw3 algorithm)\n");
1176 } 1176 }
1177#else /* !MODULE */ 1177#else /* !MODULE */
1178 /* print a short no-nonsense boot message */ 1178 /* print a short no-nonsense boot message */
1179 printk("zftape compressor v1.00a 970514\n"); 1179 printk(KERN_INFO "zftape compressor v1.00a 970514\n");
1180 printk("For use with " FTAPE_VERSION "\n"); 1180 printk(KERN_INFO "For use with " FTAPE_VERSION "\n");
1181#endif /* MODULE */ 1181#endif /* MODULE */
1182 TRACE(ft_t_info, "zft_compressor_init @ 0x%p", zft_compressor_init); 1182 TRACE(ft_t_info, "zft_compressor_init @ 0x%p", zft_compressor_init);
1183 TRACE(ft_t_info, "installing compressor for zftape ..."); 1183 TRACE(ft_t_info, "installing compressor for zftape ...");
diff --git a/drivers/char/ftape/zftape/zftape-init.c b/drivers/char/ftape/zftape/zftape-init.c
index dbac7e54e8e0..5745b74044ec 100644
--- a/drivers/char/ftape/zftape/zftape-init.c
+++ b/drivers/char/ftape/zftape/zftape-init.c
@@ -99,7 +99,7 @@ static struct file_operations zft_cdev =
99 .release = zft_close, 99 .release = zft_close,
100}; 100};
101 101
102static struct class_simple *zft_class; 102static struct class *zft_class;
103 103
104/* Open floppy tape device 104/* Open floppy tape device
105 */ 105 */
@@ -329,29 +329,29 @@ KERN_INFO
329 "installing zftape VFS interface for ftape driver ..."); 329 "installing zftape VFS interface for ftape driver ...");
330 TRACE_CATCH(register_chrdev(QIC117_TAPE_MAJOR, "zft", &zft_cdev),); 330 TRACE_CATCH(register_chrdev(QIC117_TAPE_MAJOR, "zft", &zft_cdev),);
331 331
332 zft_class = class_simple_create(THIS_MODULE, "zft"); 332 zft_class = class_create(THIS_MODULE, "zft");
333 for (i = 0; i < 4; i++) { 333 for (i = 0; i < 4; i++) {
334 class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i); 334 class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i), NULL, "qft%i", i);
335 devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i), 335 devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i),
336 S_IFCHR | S_IRUSR | S_IWUSR, 336 S_IFCHR | S_IRUSR | S_IWUSR,
337 "qft%i", i); 337 "qft%i", i);
338 class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i); 338 class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4), NULL, "nqft%i", i);
339 devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 4), 339 devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 4),
340 S_IFCHR | S_IRUSR | S_IWUSR, 340 S_IFCHR | S_IRUSR | S_IWUSR,
341 "nqft%i", i); 341 "nqft%i", i);
342 class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i); 342 class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16), NULL, "zqft%i", i);
343 devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 16), 343 devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 16),
344 S_IFCHR | S_IRUSR | S_IWUSR, 344 S_IFCHR | S_IRUSR | S_IWUSR,
345 "zqft%i", i); 345 "zqft%i", i);
346 class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i); 346 class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20), NULL, "nzqft%i", i);
347 devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 20), 347 devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 20),
348 S_IFCHR | S_IRUSR | S_IWUSR, 348 S_IFCHR | S_IRUSR | S_IWUSR,
349 "nzqft%i", i); 349 "nzqft%i", i);
350 class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i); 350 class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32), NULL, "rawqft%i", i);
351 devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 32), 351 devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 32),
352 S_IFCHR | S_IRUSR | S_IWUSR, 352 S_IFCHR | S_IRUSR | S_IWUSR,
353 "rawqft%i", i); 353 "rawqft%i", i);
354 class_simple_device_add(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i); 354 class_device_create(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36), NULL, "nrawrawqft%i", i);
355 devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 36), 355 devfs_mk_cdev(MKDEV(QIC117_TAPE_MAJOR, i + 36),
356 S_IFCHR | S_IRUSR | S_IWUSR, 356 S_IFCHR | S_IRUSR | S_IWUSR,
357 "nrawqft%i", i); 357 "nrawqft%i", i);
@@ -381,19 +381,19 @@ static void zft_exit(void)
381 } 381 }
382 for (i = 0; i < 4; i++) { 382 for (i = 0; i < 4; i++) {
383 devfs_remove("qft%i", i); 383 devfs_remove("qft%i", i);
384 class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i)); 384 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i));
385 devfs_remove("nqft%i", i); 385 devfs_remove("nqft%i", i);
386 class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 4)); 386 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 4));
387 devfs_remove("zqft%i", i); 387 devfs_remove("zqft%i", i);
388 class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 16)); 388 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 16));
389 devfs_remove("nzqft%i", i); 389 devfs_remove("nzqft%i", i);
390 class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 20)); 390 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 20));
391 devfs_remove("rawqft%i", i); 391 devfs_remove("rawqft%i", i);
392 class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 32)); 392 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 32));
393 devfs_remove("nrawqft%i", i); 393 devfs_remove("nrawqft%i", i);
394 class_simple_device_remove(MKDEV(QIC117_TAPE_MAJOR, i + 36)); 394 class_device_destroy(zft_class, MKDEV(QIC117_TAPE_MAJOR, i + 36));
395 } 395 }
396 class_simple_destroy(zft_class); 396 class_destroy(zft_class);
397 zft_uninit_mem(); /* release remaining memory, if any */ 397 zft_uninit_mem(); /* release remaining memory, if any */
398 printk(KERN_INFO "zftape successfully unloaded.\n"); 398 printk(KERN_INFO "zftape successfully unloaded.\n");
399 TRACE_EXIT; 399 TRACE_EXIT;
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c
index 78e650fc5b41..81d811edf3c5 100644
--- a/drivers/char/hangcheck-timer.c
+++ b/drivers/char/hangcheck-timer.c
@@ -173,7 +173,7 @@ static void hangcheck_fire(unsigned long data)
173 } 173 }
174 if (hangcheck_reboot) { 174 if (hangcheck_reboot) {
175 printk(KERN_CRIT "Hangcheck: hangcheck is restarting the machine.\n"); 175 printk(KERN_CRIT "Hangcheck: hangcheck is restarting the machine.\n");
176 machine_restart(NULL); 176 emergency_restart();
177 } else { 177 } else {
178 printk(KERN_CRIT "Hangcheck: hangcheck value past margin!\n"); 178 printk(KERN_CRIT "Hangcheck: hangcheck value past margin!\n");
179 } 179 }
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 5ec732e6ca92..762fa430fb5b 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -834,7 +834,7 @@ int hpet_alloc(struct hpet_data *hdp)
834 printk("\n"); 834 printk("\n");
835 835
836 ns = hpetp->hp_period; /* femptoseconds, 10^-15 */ 836 ns = hpetp->hp_period; /* femptoseconds, 10^-15 */
837 do_div(ns, 1000000); /* convert to nanoseconds, 10^-9 */ 837 ns /= 1000000; /* convert to nanoseconds, 10^-9 */
838 printk(KERN_INFO "hpet%d: %ldns tick, %d %d-bit timers\n", 838 printk(KERN_INFO "hpet%d: %ldns tick, %d %d-bit timers\n",
839 hpetp->hp_which, ns, hpetp->hp_ntimer, 839 hpetp->hp_which, ns, hpetp->hp_ntimer,
840 cap & HPET_COUNTER_SIZE_MASK ? 64 : 32); 840 cap & HPET_COUNTER_SIZE_MASK ? 64 : 32);
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c
index 88cd858f74d0..cddb789902db 100644
--- a/drivers/char/hvc_console.c
+++ b/drivers/char/hvc_console.c
@@ -22,6 +22,7 @@
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */ 23 */
24 24
25#include <linux/config.h>
25#include <linux/console.h> 26#include <linux/console.h>
26#include <linux/cpumask.h> 27#include <linux/cpumask.h>
27#include <linux/init.h> 28#include <linux/init.h>
@@ -40,7 +41,6 @@
40#include <linux/delay.h> 41#include <linux/delay.h>
41#include <asm/uaccess.h> 42#include <asm/uaccess.h>
42#include <asm/hvconsole.h> 43#include <asm/hvconsole.h>
43#include <asm/vio.h>
44 44
45#define HVC_MAJOR 229 45#define HVC_MAJOR 229
46#define HVC_MINOR 0 46#define HVC_MINOR 0
@@ -61,16 +61,21 @@
61 */ 61 */
62#define HVC_ALLOC_TTY_ADAPTERS 8 62#define HVC_ALLOC_TTY_ADAPTERS 8
63 63
64static struct tty_driver *hvc_driver;
65#ifdef CONFIG_MAGIC_SYSRQ
66static int sysrq_pressed;
67#endif
68
69#define N_OUTBUF 16 64#define N_OUTBUF 16
70#define N_INBUF 16 65#define N_INBUF 16
71 66
72#define __ALIGNED__ __attribute__((__aligned__(8))) 67#define __ALIGNED__ __attribute__((__aligned__(8)))
73 68
69static struct tty_driver *hvc_driver;
70static struct task_struct *hvc_task;
71
72/* Picks up late kicks after list walk but before schedule() */
73static int hvc_kicked;
74
75#ifdef CONFIG_MAGIC_SYSRQ
76static int sysrq_pressed;
77#endif
78
74struct hvc_struct { 79struct hvc_struct {
75 spinlock_t lock; 80 spinlock_t lock;
76 int index; 81 int index;
@@ -80,11 +85,11 @@ struct hvc_struct {
80 char outbuf[N_OUTBUF] __ALIGNED__; 85 char outbuf[N_OUTBUF] __ALIGNED__;
81 int n_outbuf; 86 int n_outbuf;
82 uint32_t vtermno; 87 uint32_t vtermno;
88 struct hv_ops *ops;
83 int irq_requested; 89 int irq_requested;
84 int irq; 90 int irq;
85 struct list_head next; 91 struct list_head next;
86 struct kobject kobj; /* ref count & hvc_struct lifetime */ 92 struct kobject kobj; /* ref count & hvc_struct lifetime */
87 struct vio_dev *vdev;
88}; 93};
89 94
90/* dynamic list of hvc_struct instances */ 95/* dynamic list of hvc_struct instances */
@@ -97,26 +102,185 @@ static struct list_head hvc_structs = LIST_HEAD_INIT(hvc_structs);
97static DEFINE_SPINLOCK(hvc_structs_lock); 102static DEFINE_SPINLOCK(hvc_structs_lock);
98 103
99/* 104/*
105 * This value is used to assign a tty->index value to a hvc_struct based
106 * upon order of exposure via hvc_probe(), when we can not match it to
107 * a console canidate registered with hvc_instantiate().
108 */
109static int last_hvc = -1;
110
111/*
112 * Do not call this function with either the hvc_strucst_lock or the hvc_struct
113 * lock held. If successful, this function increments the kobject reference
114 * count against the target hvc_struct so it should be released when finished.
115 */
116struct hvc_struct *hvc_get_by_index(int index)
117{
118 struct hvc_struct *hp;
119 unsigned long flags;
120
121 spin_lock(&hvc_structs_lock);
122
123 list_for_each_entry(hp, &hvc_structs, next) {
124 spin_lock_irqsave(&hp->lock, flags);
125 if (hp->index == index) {
126 kobject_get(&hp->kobj);
127 spin_unlock_irqrestore(&hp->lock, flags);
128 spin_unlock(&hvc_structs_lock);
129 return hp;
130 }
131 spin_unlock_irqrestore(&hp->lock, flags);
132 }
133 hp = NULL;
134
135 spin_unlock(&hvc_structs_lock);
136 return hp;
137}
138
139
140/*
100 * Initial console vtermnos for console API usage prior to full console 141 * Initial console vtermnos for console API usage prior to full console
101 * initialization. Any vty adapter outside this range will not have usable 142 * initialization. Any vty adapter outside this range will not have usable
102 * console interfaces but can still be used as a tty device. This has to be 143 * console interfaces but can still be used as a tty device. This has to be
103 * static because kmalloc will not work during early console init. 144 * static because kmalloc will not work during early console init.
104 */ 145 */
105static uint32_t vtermnos[MAX_NR_HVC_CONSOLES]; 146static struct hv_ops *cons_ops[MAX_NR_HVC_CONSOLES];
147static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] =
148 {[0 ... MAX_NR_HVC_CONSOLES - 1] = -1};
106 149
107/* Used for accounting purposes */ 150/*
108static int num_vterms = 0; 151 * Console APIs, NOT TTY. These APIs are available immediately when
152 * hvc_console_setup() finds adapters.
153 */
109 154
110static struct task_struct *hvc_task; 155void hvc_console_print(struct console *co, const char *b, unsigned count)
156{
157 char c[16] __ALIGNED__;
158 unsigned i = 0, n = 0;
159 int r, donecr = 0, index = co->index;
160
161 /* Console access attempt outside of acceptable console range. */
162 if (index >= MAX_NR_HVC_CONSOLES)
163 return;
164
165 /* This console adapter was removed so it is not useable. */
166 if (vtermnos[index] < 0)
167 return;
168
169 while (count > 0 || i > 0) {
170 if (count > 0 && i < sizeof(c)) {
171 if (b[n] == '\n' && !donecr) {
172 c[i++] = '\r';
173 donecr = 1;
174 } else {
175 c[i++] = b[n++];
176 donecr = 0;
177 --count;
178 }
179 } else {
180 r = cons_ops[index]->put_chars(vtermnos[index], c, i);
181 if (r < 0) {
182 /* throw away chars on error */
183 i = 0;
184 } else if (r > 0) {
185 i -= r;
186 if (i > 0)
187 memmove(c, c+r, i);
188 }
189 }
190 }
191}
192
193static struct tty_driver *hvc_console_device(struct console *c, int *index)
194{
195 if (vtermnos[c->index] == -1)
196 return NULL;
197
198 *index = c->index;
199 return hvc_driver;
200}
201
202static int __init hvc_console_setup(struct console *co, char *options)
203{
204 if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES)
205 return -ENODEV;
206
207 if (vtermnos[co->index] == -1)
208 return -ENODEV;
209
210 return 0;
211}
212
213struct console hvc_con_driver = {
214 .name = "hvc",
215 .write = hvc_console_print,
216 .device = hvc_console_device,
217 .setup = hvc_console_setup,
218 .flags = CON_PRINTBUFFER,
219 .index = -1,
220};
111 221
112/* 222/*
113 * This value is used to associate a tty->index value to a hvc_struct based 223 * Early console initialization. Preceeds driver initialization.
114 * upon order of exposure via hvc_probe(). 224 *
225 * (1) we are first, and the user specified another driver
226 * -- index will remain -1
227 * (2) we are first and the user specified no driver
228 * -- index will be set to 0, then we will fail setup.
229 * (3) we are first and the user specified our driver
230 * -- index will be set to user specified driver, and we will fail
231 * (4) we are after driver, and this initcall will register us
232 * -- if the user didn't specify a driver then the console will match
233 *
234 * Note that for cases 2 and 3, we will match later when the io driver
235 * calls hvc_instantiate() and call register again.
115 */ 236 */
116static int hvc_count = -1; 237static int __init hvc_console_init(void)
238{
239 register_console(&hvc_con_driver);
240 return 0;
241}
242console_initcall(hvc_console_init);
117 243
118/* Picks up late kicks after list walk but before schedule() */ 244/*
119static int hvc_kicked; 245 * hvc_instantiate() is an early console discovery method which locates
246 * consoles * prior to the vio subsystem discovering them. Hotplugged
247 * vty adapters do NOT get an hvc_instantiate() callback since they
248 * appear after early console init.
249 */
250int hvc_instantiate(uint32_t vtermno, int index, struct hv_ops *ops)
251{
252 struct hvc_struct *hp;
253
254 if (index < 0 || index >= MAX_NR_HVC_CONSOLES)
255 return -1;
256
257 if (vtermnos[index] != -1)
258 return -1;
259
260 /* make sure no no tty has been registerd in this index */
261 hp = hvc_get_by_index(index);
262 if (hp) {
263 kobject_put(&hp->kobj);
264 return -1;
265 }
266
267 vtermnos[index] = vtermno;
268 cons_ops[index] = ops;
269
270 /* reserve all indices upto and including this index */
271 if (last_hvc < index)
272 last_hvc = index;
273
274 /* if this index is what the user requested, then register
275 * now (setup won't fail at this point). It's ok to just
276 * call register again if previously .setup failed.
277 */
278 if (index == hvc_con_driver.index)
279 register_console(&hvc_con_driver);
280
281 return 0;
282}
283EXPORT_SYMBOL(hvc_instantiate);
120 284
121/* Wake the sleeping khvcd */ 285/* Wake the sleeping khvcd */
122static void hvc_kick(void) 286static void hvc_kick(void)
@@ -125,13 +289,17 @@ static void hvc_kick(void)
125 wake_up_process(hvc_task); 289 wake_up_process(hvc_task);
126} 290}
127 291
292static int hvc_poll(struct hvc_struct *hp);
293
128/* 294/*
129 * NOTE: This API isn't used if the console adapter doesn't support interrupts. 295 * NOTE: This API isn't used if the console adapter doesn't support interrupts.
130 * In this case the console is poll driven. 296 * In this case the console is poll driven.
131 */ 297 */
132static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance, struct pt_regs *regs) 298static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance, struct pt_regs *regs)
133{ 299{
134 hvc_kick(); 300 /* if hvc_poll request a repoll, then kick the hvcd thread */
301 if (hvc_poll(dev_instance))
302 hvc_kick();
135 return IRQ_HANDLED; 303 return IRQ_HANDLED;
136} 304}
137 305
@@ -141,34 +309,6 @@ static void hvc_unthrottle(struct tty_struct *tty)
141} 309}
142 310
143/* 311/*
144 * Do not call this function with either the hvc_strucst_lock or the hvc_struct
145 * lock held. If successful, this function increments the kobject reference
146 * count against the target hvc_struct so it should be released when finished.
147 */
148struct hvc_struct *hvc_get_by_index(int index)
149{
150 struct hvc_struct *hp;
151 unsigned long flags;
152
153 spin_lock(&hvc_structs_lock);
154
155 list_for_each_entry(hp, &hvc_structs, next) {
156 spin_lock_irqsave(&hp->lock, flags);
157 if (hp->index == index) {
158 kobject_get(&hp->kobj);
159 spin_unlock_irqrestore(&hp->lock, flags);
160 spin_unlock(&hvc_structs_lock);
161 return hp;
162 }
163 spin_unlock_irqrestore(&hp->lock, flags);
164 }
165 hp = NULL;
166
167 spin_unlock(&hvc_structs_lock);
168 return hp;
169}
170
171/*
172 * The TTY interface won't be used until after the vio layer has exposed the vty 312 * The TTY interface won't be used until after the vio layer has exposed the vty
173 * adapter to the kernel. 313 * adapter to the kernel.
174 */ 314 */
@@ -329,7 +469,7 @@ static void hvc_push(struct hvc_struct *hp)
329{ 469{
330 int n; 470 int n;
331 471
332 n = hvc_put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf); 472 n = hp->ops->put_chars(hp->vtermno, hp->outbuf, hp->n_outbuf);
333 if (n <= 0) { 473 if (n <= 0) {
334 if (n == 0) 474 if (n == 0)
335 return; 475 return;
@@ -467,7 +607,7 @@ static int hvc_poll(struct hvc_struct *hp)
467 break; 607 break;
468 } 608 }
469 609
470 n = hvc_get_chars(hp->vtermno, buf, count); 610 n = hp->ops->get_chars(hp->vtermno, buf, count);
471 if (n <= 0) { 611 if (n <= 0) {
472 /* Hangup the tty when disconnected from host */ 612 /* Hangup the tty when disconnected from host */
473 if (n == -EPIPE) { 613 if (n == -EPIPE) {
@@ -479,14 +619,17 @@ static int hvc_poll(struct hvc_struct *hp)
479 } 619 }
480 for (i = 0; i < n; ++i) { 620 for (i = 0; i < n; ++i) {
481#ifdef CONFIG_MAGIC_SYSRQ 621#ifdef CONFIG_MAGIC_SYSRQ
482 /* Handle the SysRq Hack */ 622 if (hp->index == hvc_con_driver.index) {
483 if (buf[i] == '\x0f') { /* ^O -- should support a sequence */ 623 /* Handle the SysRq Hack */
484 sysrq_pressed = 1; 624 /* XXX should support a sequence */
485 continue; 625 if (buf[i] == '\x0f') { /* ^O */
486 } else if (sysrq_pressed) { 626 sysrq_pressed = 1;
487 handle_sysrq(buf[i], NULL, tty); 627 continue;
488 sysrq_pressed = 0; 628 } else if (sysrq_pressed) {
489 continue; 629 handle_sysrq(buf[i], NULL, tty);
630 sysrq_pressed = 0;
631 continue;
632 }
490 } 633 }
491#endif /* CONFIG_MAGIC_SYSRQ */ 634#endif /* CONFIG_MAGIC_SYSRQ */
492 tty_insert_flip_char(tty, buf[i], 0); 635 tty_insert_flip_char(tty, buf[i], 0);
@@ -497,8 +640,8 @@ static int hvc_poll(struct hvc_struct *hp)
497 640
498 /* 641 /*
499 * Account for the total amount read in one loop, and if above 642 * Account for the total amount read in one loop, and if above
500 * 64 bytes, we do a quick schedule loop to let the tty grok the 643 * 64 bytes, we do a quick schedule loop to let the tty grok
501 * data and eventually throttle us. 644 * the data and eventually throttle us.
502 */ 645 */
503 read_total += n; 646 read_total += n;
504 if (read_total >= 64) { 647 if (read_total >= 64) {
@@ -542,7 +685,6 @@ int khvcd(void *unused)
542 if (cpus_empty(cpus_in_xmon)) { 685 if (cpus_empty(cpus_in_xmon)) {
543 spin_lock(&hvc_structs_lock); 686 spin_lock(&hvc_structs_lock);
544 list_for_each_entry(hp, &hvc_structs, next) { 687 list_for_each_entry(hp, &hvc_structs, next) {
545 /*hp = list_entry(node, struct hvc_struct, * next); */
546 poll_mask |= hvc_poll(hp); 688 poll_mask |= hvc_poll(hp);
547 } 689 }
548 spin_unlock(&hvc_structs_lock); 690 spin_unlock(&hvc_structs_lock);
@@ -577,14 +719,6 @@ static struct tty_operations hvc_ops = {
577 .chars_in_buffer = hvc_chars_in_buffer, 719 .chars_in_buffer = hvc_chars_in_buffer,
578}; 720};
579 721
580char hvc_driver_name[] = "hvc_console";
581
582static struct vio_device_id hvc_driver_table[] __devinitdata= {
583 {"serial", "hvterm1"},
584 { NULL, }
585};
586MODULE_DEVICE_TABLE(vio, hvc_driver_table);
587
588/* callback when the kboject ref count reaches zero. */ 722/* callback when the kboject ref count reaches zero. */
589static void destroy_hvc_struct(struct kobject *kobj) 723static void destroy_hvc_struct(struct kobject *kobj)
590{ 724{
@@ -606,41 +740,51 @@ static struct kobj_type hvc_kobj_type = {
606 .release = destroy_hvc_struct, 740 .release = destroy_hvc_struct,
607}; 741};
608 742
609static int __devinit hvc_probe( 743struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq,
610 struct vio_dev *dev, 744 struct hv_ops *ops)
611 const struct vio_device_id *id)
612{ 745{
613 struct hvc_struct *hp; 746 struct hvc_struct *hp;
614 747 int i;
615 /* probed with invalid parameters. */
616 if (!dev || !id)
617 return -EPERM;
618 748
619 hp = kmalloc(sizeof(*hp), GFP_KERNEL); 749 hp = kmalloc(sizeof(*hp), GFP_KERNEL);
620 if (!hp) 750 if (!hp)
621 return -ENOMEM; 751 return ERR_PTR(-ENOMEM);
622 752
623 memset(hp, 0x00, sizeof(*hp)); 753 memset(hp, 0x00, sizeof(*hp));
624 hp->vtermno = dev->unit_address; 754
625 hp->vdev = dev; 755 hp->vtermno = vtermno;
626 hp->vdev->dev.driver_data = hp; 756 hp->irq = irq;
627 hp->irq = dev->irq; 757 hp->ops = ops;
628 758
629 kobject_init(&hp->kobj); 759 kobject_init(&hp->kobj);
630 hp->kobj.ktype = &hvc_kobj_type; 760 hp->kobj.ktype = &hvc_kobj_type;
631 761
632 spin_lock_init(&hp->lock); 762 spin_lock_init(&hp->lock);
633 spin_lock(&hvc_structs_lock); 763 spin_lock(&hvc_structs_lock);
634 hp->index = ++hvc_count; 764
765 /*
766 * find index to use:
767 * see if this vterm id matches one registered for console.
768 */
769 for (i=0; i < MAX_NR_HVC_CONSOLES; i++)
770 if (vtermnos[i] == hp->vtermno)
771 break;
772
773 /* no matching slot, just use a counter */
774 if (i >= MAX_NR_HVC_CONSOLES)
775 i = ++last_hvc;
776
777 hp->index = i;
778
635 list_add_tail(&(hp->next), &hvc_structs); 779 list_add_tail(&(hp->next), &hvc_structs);
636 spin_unlock(&hvc_structs_lock); 780 spin_unlock(&hvc_structs_lock);
637 781
638 return 0; 782 return hp;
639} 783}
784EXPORT_SYMBOL(hvc_alloc);
640 785
641static int __devexit hvc_remove(struct vio_dev *dev) 786int __devexit hvc_remove(struct hvc_struct *hp)
642{ 787{
643 struct hvc_struct *hp = dev->dev.driver_data;
644 unsigned long flags; 788 unsigned long flags;
645 struct kobject *kobjp; 789 struct kobject *kobjp;
646 struct tty_struct *tty; 790 struct tty_struct *tty;
@@ -673,23 +817,14 @@ static int __devexit hvc_remove(struct vio_dev *dev)
673 tty_hangup(tty); 817 tty_hangup(tty);
674 return 0; 818 return 0;
675} 819}
676 820EXPORT_SYMBOL(hvc_remove);
677static struct vio_driver hvc_vio_driver = {
678 .name = hvc_driver_name,
679 .id_table = hvc_driver_table,
680 .probe = hvc_probe,
681 .remove = hvc_remove,
682};
683 821
684/* Driver initialization. Follow console initialization. This is where the TTY 822/* Driver initialization. Follow console initialization. This is where the TTY
685 * interfaces start to become available. */ 823 * interfaces start to become available. */
686int __init hvc_init(void) 824int __init hvc_init(void)
687{ 825{
688 int rc; 826 /* We need more than hvc_count adapters due to hotplug additions. */
689
690 /* We need more than num_vterms adapters due to hotplug additions. */
691 hvc_driver = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS); 827 hvc_driver = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS);
692 /* hvc_driver = alloc_tty_driver(num_vterms); */
693 if (!hvc_driver) 828 if (!hvc_driver)
694 return -ENOMEM; 829 return -ENOMEM;
695 830
@@ -716,116 +851,20 @@ int __init hvc_init(void)
716 return -EIO; 851 return -EIO;
717 } 852 }
718 853
719 /* Register as a vio device to receive callbacks */ 854 return 0;
720 rc = vio_register_driver(&hvc_vio_driver);
721
722 return rc;
723} 855}
856module_init(hvc_init);
724 857
725/* This isn't particularily necessary due to this being a console driver but it 858/* This isn't particularily necessary due to this being a console driver
726 * is nice to be thorough */ 859 * but it is nice to be thorough.
860 */
727static void __exit hvc_exit(void) 861static void __exit hvc_exit(void)
728{ 862{
729 kthread_stop(hvc_task); 863 kthread_stop(hvc_task);
730 864
731 vio_unregister_driver(&hvc_vio_driver);
732 tty_unregister_driver(hvc_driver); 865 tty_unregister_driver(hvc_driver);
733 /* return tty_struct instances allocated in hvc_init(). */ 866 /* return tty_struct instances allocated in hvc_init(). */
734 put_tty_driver(hvc_driver); 867 put_tty_driver(hvc_driver);
868 unregister_console(&hvc_con_driver);
735} 869}
736
737/*
738 * Console APIs, NOT TTY. These APIs are available immediately when
739 * hvc_console_setup() finds adapters.
740 */
741
742/*
743 * hvc_instantiate() is an early console discovery method which locates consoles
744 * prior to the vio subsystem discovering them. Hotplugged vty adapters do NOT
745 * get an hvc_instantiate() callback since the appear after early console init.
746 */
747int hvc_instantiate(uint32_t vtermno, int index)
748{
749 if (index < 0 || index >= MAX_NR_HVC_CONSOLES)
750 return -1;
751
752 if (vtermnos[index] != -1)
753 return -1;
754
755 vtermnos[index] = vtermno;
756 return 0;
757}
758
759void hvc_console_print(struct console *co, const char *b, unsigned count)
760{
761 char c[16] __ALIGNED__;
762 unsigned i = 0, n = 0;
763 int r, donecr = 0;
764
765 /* Console access attempt outside of acceptable console range. */
766 if (co->index >= MAX_NR_HVC_CONSOLES)
767 return;
768
769 /* This console adapter was removed so it is not useable. */
770 if (vtermnos[co->index] < 0)
771 return;
772
773 while (count > 0 || i > 0) {
774 if (count > 0 && i < sizeof(c)) {
775 if (b[n] == '\n' && !donecr) {
776 c[i++] = '\r';
777 donecr = 1;
778 } else {
779 c[i++] = b[n++];
780 donecr = 0;
781 --count;
782 }
783 } else {
784 r = hvc_put_chars(vtermnos[co->index], c, i);
785 if (r < 0) {
786 /* throw away chars on error */
787 i = 0;
788 } else if (r > 0) {
789 i -= r;
790 if (i > 0)
791 memmove(c, c+r, i);
792 }
793 }
794 }
795}
796
797static struct tty_driver *hvc_console_device(struct console *c, int *index)
798{
799 *index = c->index;
800 return hvc_driver;
801}
802
803static int __init hvc_console_setup(struct console *co, char *options)
804{
805 return 0;
806}
807
808struct console hvc_con_driver = {
809 .name = "hvc",
810 .write = hvc_console_print,
811 .device = hvc_console_device,
812 .setup = hvc_console_setup,
813 .flags = CON_PRINTBUFFER,
814 .index = -1,
815};
816
817/* Early console initialization. Preceeds driver initialization. */
818static int __init hvc_console_init(void)
819{
820 int i;
821
822 for (i=0; i<MAX_NR_HVC_CONSOLES; i++)
823 vtermnos[i] = -1;
824 num_vterms = hvc_find_vtys();
825 register_console(&hvc_con_driver);
826 return 0;
827}
828console_initcall(hvc_console_init);
829
830module_init(hvc_init);
831module_exit(hvc_exit); 870module_exit(hvc_exit);
diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c
new file mode 100644
index 000000000000..60bb9152b832
--- /dev/null
+++ b/drivers/char/hvc_vio.c
@@ -0,0 +1,152 @@
1/*
2 * vio driver interface to hvc_console.c
3 *
4 * This code was moved here to allow the remaing code to be reused as a
5 * generic polling mode with semi-reliable transport driver core to the
6 * console and tty subsystems.
7 *
8 *
9 * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
10 * Copyright (C) 2001 Paul Mackerras <paulus@au.ibm.com>, IBM
11 * Copyright (C) 2004 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
12 * Copyright (C) 2004 IBM Corporation
13 *
14 * Additional Author(s):
15 * Ryan S. Arnold <rsa@us.ibm.com>
16 *
17 * This program is free software; you can redistribute it and/or modify
18 * it under the terms of the GNU General Public License as published by
19 * the Free Software Foundation; either version 2 of the License, or
20 * (at your option) any later version.
21 *
22 * This program is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * You should have received a copy of the GNU General Public License
28 * along with this program; if not, write to the Free Software
29 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 */
31
32#include <linux/types.h>
33#include <linux/init.h>
34#include <asm/hvconsole.h>
35#include <asm/vio.h>
36#include <asm/prom.h>
37
38char hvc_driver_name[] = "hvc_console";
39
40static struct vio_device_id hvc_driver_table[] __devinitdata = {
41 {"serial", "hvterm1"},
42 { NULL, }
43};
44MODULE_DEVICE_TABLE(vio, hvc_driver_table);
45
46static int filtered_get_chars(uint32_t vtermno, char *buf, int count)
47{
48 unsigned long got;
49 int i;
50
51 got = hvc_get_chars(vtermno, buf, count);
52
53 /*
54 * Work around a HV bug where it gives us a null
55 * after every \r. -- paulus
56 */
57 for (i = 1; i < got; ++i) {
58 if (buf[i] == 0 && buf[i-1] == '\r') {
59 --got;
60 if (i < got)
61 memmove(&buf[i], &buf[i+1],
62 got - i);
63 }
64 }
65 return got;
66}
67
68static struct hv_ops hvc_get_put_ops = {
69 .get_chars = filtered_get_chars,
70 .put_chars = hvc_put_chars,
71};
72
73static int __devinit hvc_vio_probe(struct vio_dev *vdev,
74 const struct vio_device_id *id)
75{
76 struct hvc_struct *hp;
77
78 /* probed with invalid parameters. */
79 if (!vdev || !id)
80 return -EPERM;
81
82 hp = hvc_alloc(vdev->unit_address, vdev->irq, &hvc_get_put_ops);
83 if (IS_ERR(hp))
84 return PTR_ERR(hp);
85 dev_set_drvdata(&vdev->dev, hp);
86
87 return 0;
88}
89
90static int __devexit hvc_vio_remove(struct vio_dev *vdev)
91{
92 struct hvc_struct *hp = dev_get_drvdata(&vdev->dev);
93
94 return hvc_remove(hp);
95}
96
97static struct vio_driver hvc_vio_driver = {
98 .name = hvc_driver_name,
99 .id_table = hvc_driver_table,
100 .probe = hvc_vio_probe,
101 .remove = hvc_vio_remove,
102 .driver = {
103 .owner = THIS_MODULE,
104 }
105};
106
107static int hvc_vio_init(void)
108{
109 int rc;
110
111 /* Register as a vio device to receive callbacks */
112 rc = vio_register_driver(&hvc_vio_driver);
113
114 return rc;
115}
116module_init(hvc_vio_init); /* after drivers/char/hvc_console.c */
117
118static void hvc_vio_exit(void)
119{
120 vio_unregister_driver(&hvc_vio_driver);
121}
122module_exit(hvc_vio_exit);
123
124/* the device tree order defines our numbering */
125static int hvc_find_vtys(void)
126{
127 struct device_node *vty;
128 int num_found = 0;
129
130 for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL;
131 vty = of_find_node_by_name(vty, "vty")) {
132 uint32_t *vtermno;
133
134 /* We have statically defined space for only a certain number
135 * of console adapters.
136 */
137 if (num_found >= MAX_NR_HVC_CONSOLES)
138 break;
139
140 vtermno = (uint32_t *)get_property(vty, "reg", NULL);
141 if (!vtermno)
142 continue;
143
144 if (device_is_compatible(vty, "hvterm1")) {
145 hvc_instantiate(*vtermno, num_found, &hvc_get_put_ops);
146 ++num_found;
147 }
148 }
149
150 return num_found;
151}
152console_initcall(hvc_find_vtys);
diff --git a/drivers/char/hvcs.c b/drivers/char/hvcs.c
index abfbdcfd4e72..3236d2404905 100644
--- a/drivers/char/hvcs.c
+++ b/drivers/char/hvcs.c
@@ -1466,7 +1466,7 @@ static inline struct hvcs_struct *from_vio_dev(struct vio_dev *viod)
1466} 1466}
1467/* The sysfs interface for the driver and devices */ 1467/* The sysfs interface for the driver and devices */
1468 1468
1469static ssize_t hvcs_partner_vtys_show(struct device *dev, char *buf) 1469static ssize_t hvcs_partner_vtys_show(struct device *dev, struct device_attribute *attr, char *buf)
1470{ 1470{
1471 struct vio_dev *viod = to_vio_dev(dev); 1471 struct vio_dev *viod = to_vio_dev(dev);
1472 struct hvcs_struct *hvcsd = from_vio_dev(viod); 1472 struct hvcs_struct *hvcsd = from_vio_dev(viod);
@@ -1480,7 +1480,7 @@ static ssize_t hvcs_partner_vtys_show(struct device *dev, char *buf)
1480} 1480}
1481static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL); 1481static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL);
1482 1482
1483static ssize_t hvcs_partner_clcs_show(struct device *dev, char *buf) 1483static ssize_t hvcs_partner_clcs_show(struct device *dev, struct device_attribute *attr, char *buf)
1484{ 1484{
1485 struct vio_dev *viod = to_vio_dev(dev); 1485 struct vio_dev *viod = to_vio_dev(dev);
1486 struct hvcs_struct *hvcsd = from_vio_dev(viod); 1486 struct hvcs_struct *hvcsd = from_vio_dev(viod);
@@ -1494,7 +1494,7 @@ static ssize_t hvcs_partner_clcs_show(struct device *dev, char *buf)
1494} 1494}
1495static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL); 1495static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL);
1496 1496
1497static ssize_t hvcs_current_vty_store(struct device *dev, const char * buf, 1497static ssize_t hvcs_current_vty_store(struct device *dev, struct device_attribute *attr, const char * buf,
1498 size_t count) 1498 size_t count)
1499{ 1499{
1500 /* 1500 /*
@@ -1505,7 +1505,7 @@ static ssize_t hvcs_current_vty_store(struct device *dev, const char * buf,
1505 return -EPERM; 1505 return -EPERM;
1506} 1506}
1507 1507
1508static ssize_t hvcs_current_vty_show(struct device *dev, char *buf) 1508static ssize_t hvcs_current_vty_show(struct device *dev, struct device_attribute *attr, char *buf)
1509{ 1509{
1510 struct vio_dev *viod = to_vio_dev(dev); 1510 struct vio_dev *viod = to_vio_dev(dev);
1511 struct hvcs_struct *hvcsd = from_vio_dev(viod); 1511 struct hvcs_struct *hvcsd = from_vio_dev(viod);
@@ -1521,7 +1521,7 @@ static ssize_t hvcs_current_vty_show(struct device *dev, char *buf)
1521static DEVICE_ATTR(current_vty, 1521static DEVICE_ATTR(current_vty,
1522 S_IRUGO | S_IWUSR, hvcs_current_vty_show, hvcs_current_vty_store); 1522 S_IRUGO | S_IWUSR, hvcs_current_vty_show, hvcs_current_vty_store);
1523 1523
1524static ssize_t hvcs_vterm_state_store(struct device *dev, const char *buf, 1524static ssize_t hvcs_vterm_state_store(struct device *dev, struct device_attribute *attr, const char *buf,
1525 size_t count) 1525 size_t count)
1526{ 1526{
1527 struct vio_dev *viod = to_vio_dev(dev); 1527 struct vio_dev *viod = to_vio_dev(dev);
@@ -1559,7 +1559,7 @@ static ssize_t hvcs_vterm_state_store(struct device *dev, const char *buf,
1559 return count; 1559 return count;
1560} 1560}
1561 1561
1562static ssize_t hvcs_vterm_state_show(struct device *dev, char *buf) 1562static ssize_t hvcs_vterm_state_show(struct device *dev, struct device_attribute *attr, char *buf)
1563{ 1563{
1564 struct vio_dev *viod = to_vio_dev(dev); 1564 struct vio_dev *viod = to_vio_dev(dev);
1565 struct hvcs_struct *hvcsd = from_vio_dev(viod); 1565 struct hvcs_struct *hvcsd = from_vio_dev(viod);
@@ -1574,7 +1574,7 @@ static ssize_t hvcs_vterm_state_show(struct device *dev, char *buf)
1574static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR, 1574static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR,
1575 hvcs_vterm_state_show, hvcs_vterm_state_store); 1575 hvcs_vterm_state_show, hvcs_vterm_state_store);
1576 1576
1577static ssize_t hvcs_index_show(struct device *dev, char *buf) 1577static ssize_t hvcs_index_show(struct device *dev, struct device_attribute *attr, char *buf)
1578{ 1578{
1579 struct vio_dev *viod = to_vio_dev(dev); 1579 struct vio_dev *viod = to_vio_dev(dev);
1580 struct hvcs_struct *hvcsd = from_vio_dev(viod); 1580 struct hvcs_struct *hvcsd = from_vio_dev(viod);
diff --git a/drivers/char/hvsi.c b/drivers/char/hvsi.c
index f1f1192ba2b5..a22aa940e01e 100644
--- a/drivers/char/hvsi.c
+++ b/drivers/char/hvsi.c
@@ -291,15 +291,13 @@ static void dump_packet(uint8_t *packet)
291 dump_hex(packet, header->len); 291 dump_hex(packet, header->len);
292} 292}
293 293
294/* can't use hvc_get_chars because that strips CRs */
295static int hvsi_read(struct hvsi_struct *hp, char *buf, int count) 294static int hvsi_read(struct hvsi_struct *hp, char *buf, int count)
296{ 295{
297 unsigned long got; 296 unsigned long got;
298 297
299 if (plpar_hcall(H_GET_TERM_CHAR, hp->vtermno, 0, 0, 0, &got, 298 got = hvc_get_chars(hp->vtermno, buf, count);
300 (unsigned long *)buf, (unsigned long *)buf+1) == H_Success) 299
301 return got; 300 return got;
302 return 0;
303} 301}
304 302
305static void hvsi_recv_control(struct hvsi_struct *hp, uint8_t *packet, 303static void hvsi_recv_control(struct hvsi_struct *hp, uint8_t *packet,
diff --git a/drivers/char/hw_random.c b/drivers/char/hw_random.c
index 7e6ac14c2450..3480535a09c5 100644
--- a/drivers/char/hw_random.c
+++ b/drivers/char/hw_random.c
@@ -579,7 +579,7 @@ static int __init rng_init (void)
579 579
580 /* Probe for Intel, AMD RNGs */ 580 /* Probe for Intel, AMD RNGs */
581 for_each_pci_dev(pdev) { 581 for_each_pci_dev(pdev) {
582 ent = pci_match_device (rng_pci_tbl, pdev); 582 ent = pci_match_id(rng_pci_tbl, pdev);
583 if (ent) { 583 if (ent) {
584 rng_ops = &rng_vendor_ops[ent->driver_data]; 584 rng_ops = &rng_vendor_ops[ent->driver_data];
585 goto match; 585 goto match;
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c
index a81197640283..6c4b3f986d0c 100644
--- a/drivers/char/i8k.c
+++ b/drivers/char/i8k.c
@@ -20,13 +20,14 @@
20#include <linux/types.h> 20#include <linux/types.h>
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/proc_fs.h> 22#include <linux/proc_fs.h>
23#include <linux/apm_bios.h> 23#include <linux/seq_file.h>
24#include <linux/dmi.h>
24#include <asm/uaccess.h> 25#include <asm/uaccess.h>
25#include <asm/io.h> 26#include <asm/io.h>
26 27
27#include <linux/i8k.h> 28#include <linux/i8k.h>
28 29
29#define I8K_VERSION "1.13 14/05/2002" 30#define I8K_VERSION "1.14 21/02/2005"
30 31
31#define I8K_SMM_FN_STATUS 0x0025 32#define I8K_SMM_FN_STATUS 0x0025
32#define I8K_SMM_POWER_STATUS 0x0069 33#define I8K_SMM_POWER_STATUS 0x0069
@@ -34,7 +35,8 @@
34#define I8K_SMM_GET_FAN 0x00a3 35#define I8K_SMM_GET_FAN 0x00a3
35#define I8K_SMM_GET_SPEED 0x02a3 36#define I8K_SMM_GET_SPEED 0x02a3
36#define I8K_SMM_GET_TEMP 0x10a3 37#define I8K_SMM_GET_TEMP 0x10a3
37#define I8K_SMM_GET_DELL_SIG 0xffa3 38#define I8K_SMM_GET_DELL_SIG1 0xfea3
39#define I8K_SMM_GET_DELL_SIG2 0xffa3
38#define I8K_SMM_BIOS_VERSION 0x00a6 40#define I8K_SMM_BIOS_VERSION 0x00a6
39 41
40#define I8K_FAN_MULT 30 42#define I8K_FAN_MULT 30
@@ -52,18 +54,7 @@
52 54
53#define I8K_TEMPERATURE_BUG 1 55#define I8K_TEMPERATURE_BUG 1
54 56
55#define DELL_SIGNATURE "Dell Computer" 57static char bios_version[4];
56
57static char *supported_models[] = {
58 "Inspiron",
59 "Latitude",
60 NULL
61};
62
63static char system_vendor[48] = "?";
64static char product_name [48] = "?";
65static char bios_version [4] = "?";
66static char serial_number[16] = "?";
67 58
68MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)"); 59MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)");
69MODULE_DESCRIPTION("Driver for accessing SMM BIOS on Dell laptops"); 60MODULE_DESCRIPTION("Driver for accessing SMM BIOS on Dell laptops");
@@ -73,6 +64,10 @@ static int force;
73module_param(force, bool, 0); 64module_param(force, bool, 0);
74MODULE_PARM_DESC(force, "Force loading without checking for supported models"); 65MODULE_PARM_DESC(force, "Force loading without checking for supported models");
75 66
67static int ignore_dmi;
68module_param(ignore_dmi, bool, 0);
69MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match");
70
76static int restricted; 71static int restricted;
77module_param(restricted, bool, 0); 72module_param(restricted, bool, 0);
78MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set"); 73MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set");
@@ -81,69 +76,69 @@ static int power_status;
81module_param(power_status, bool, 0600); 76module_param(power_status, bool, 0600);
82MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k"); 77MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k");
83 78
84static ssize_t i8k_read(struct file *, char __user *, size_t, loff_t *); 79static int i8k_open_fs(struct inode *inode, struct file *file);
85static int i8k_ioctl(struct inode *, struct file *, unsigned int, 80static int i8k_ioctl(struct inode *, struct file *, unsigned int,
86 unsigned long); 81 unsigned long);
87 82
88static struct file_operations i8k_fops = { 83static struct file_operations i8k_fops = {
89 .read = i8k_read, 84 .open = i8k_open_fs,
90 .ioctl = i8k_ioctl, 85 .read = seq_read,
86 .llseek = seq_lseek,
87 .release = single_release,
88 .ioctl = i8k_ioctl,
89};
90
91struct smm_regs {
92 unsigned int eax;
93 unsigned int ebx __attribute__ ((packed));
94 unsigned int ecx __attribute__ ((packed));
95 unsigned int edx __attribute__ ((packed));
96 unsigned int esi __attribute__ ((packed));
97 unsigned int edi __attribute__ ((packed));
91}; 98};
92 99
93typedef struct { 100static inline char *i8k_get_dmi_data(int field)
94 unsigned int eax; 101{
95 unsigned int ebx __attribute__ ((packed)); 102 return dmi_get_system_info(field) ? : "N/A";
96 unsigned int ecx __attribute__ ((packed)); 103}
97 unsigned int edx __attribute__ ((packed));
98 unsigned int esi __attribute__ ((packed));
99 unsigned int edi __attribute__ ((packed));
100} SMMRegisters;
101
102typedef struct {
103 u8 type;
104 u8 length;
105 u16 handle;
106} DMIHeader;
107 104
108/* 105/*
109 * Call the System Management Mode BIOS. Code provided by Jonathan Buzzard. 106 * Call the System Management Mode BIOS. Code provided by Jonathan Buzzard.
110 */ 107 */
111static int i8k_smm(SMMRegisters *regs) 108static int i8k_smm(struct smm_regs *regs)
112{ 109{
113 int rc; 110 int rc;
114 int eax = regs->eax; 111 int eax = regs->eax;
115 112
116 asm("pushl %%eax\n\t" \ 113 asm("pushl %%eax\n\t"
117 "movl 0(%%eax),%%edx\n\t" \ 114 "movl 0(%%eax),%%edx\n\t"
118 "push %%edx\n\t" \ 115 "push %%edx\n\t"
119 "movl 4(%%eax),%%ebx\n\t" \ 116 "movl 4(%%eax),%%ebx\n\t"
120 "movl 8(%%eax),%%ecx\n\t" \ 117 "movl 8(%%eax),%%ecx\n\t"
121 "movl 12(%%eax),%%edx\n\t" \ 118 "movl 12(%%eax),%%edx\n\t"
122 "movl 16(%%eax),%%esi\n\t" \ 119 "movl 16(%%eax),%%esi\n\t"
123 "movl 20(%%eax),%%edi\n\t" \ 120 "movl 20(%%eax),%%edi\n\t"
124 "popl %%eax\n\t" \ 121 "popl %%eax\n\t"
125 "out %%al,$0xb2\n\t" \ 122 "out %%al,$0xb2\n\t"
126 "out %%al,$0x84\n\t" \ 123 "out %%al,$0x84\n\t"
127 "xchgl %%eax,(%%esp)\n\t" 124 "xchgl %%eax,(%%esp)\n\t"
128 "movl %%ebx,4(%%eax)\n\t" \ 125 "movl %%ebx,4(%%eax)\n\t"
129 "movl %%ecx,8(%%eax)\n\t" \ 126 "movl %%ecx,8(%%eax)\n\t"
130 "movl %%edx,12(%%eax)\n\t" \ 127 "movl %%edx,12(%%eax)\n\t"
131 "movl %%esi,16(%%eax)\n\t" \ 128 "movl %%esi,16(%%eax)\n\t"
132 "movl %%edi,20(%%eax)\n\t" \ 129 "movl %%edi,20(%%eax)\n\t"
133 "popl %%edx\n\t" \ 130 "popl %%edx\n\t"
134 "movl %%edx,0(%%eax)\n\t" \ 131 "movl %%edx,0(%%eax)\n\t"
135 "lahf\n\t" \ 132 "lahf\n\t"
136 "shrl $8,%%eax\n\t" \ 133 "shrl $8,%%eax\n\t"
137 "andl $1,%%eax\n" \ 134 "andl $1,%%eax\n":"=a"(rc)
138 : "=a" (rc) 135 : "a"(regs)
139 : "a" (regs) 136 : "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory");
140 : "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory"); 137
141 138 if (rc != 0 || (regs->eax & 0xffff) == 0xffff || regs->eax == eax)
142 if ((rc != 0) || ((regs->eax & 0xffff) == 0xffff) || (regs->eax == eax)) { 139 return -EINVAL;
143 return -EINVAL; 140
144 } 141 return 0;
145
146 return 0;
147} 142}
148 143
149/* 144/*
@@ -152,24 +147,9 @@ static int i8k_smm(SMMRegisters *regs)
152 */ 147 */
153static int i8k_get_bios_version(void) 148static int i8k_get_bios_version(void)
154{ 149{
155 SMMRegisters regs = { 0, 0, 0, 0, 0, 0 }; 150 struct smm_regs regs = { .eax = I8K_SMM_BIOS_VERSION, };
156 int rc;
157
158 regs.eax = I8K_SMM_BIOS_VERSION;
159 if ((rc=i8k_smm(&regs)) < 0) {
160 return rc;
161 }
162
163 return regs.eax;
164}
165 151
166/* 152 return i8k_smm(&regs) ? : regs.eax;
167 * Read the machine id.
168 */
169static int i8k_get_serial_number(unsigned char *buff)
170{
171 strlcpy(buff, serial_number, sizeof(serial_number));
172 return 0;
173} 153}
174 154
175/* 155/*
@@ -177,24 +157,22 @@ static int i8k_get_serial_number(unsigned char *buff)
177 */ 157 */
178static int i8k_get_fn_status(void) 158static int i8k_get_fn_status(void)
179{ 159{
180 SMMRegisters regs = { 0, 0, 0, 0, 0, 0 }; 160 struct smm_regs regs = { .eax = I8K_SMM_FN_STATUS, };
181 int rc; 161 int rc;
182 162
183 regs.eax = I8K_SMM_FN_STATUS; 163 if ((rc = i8k_smm(&regs)) < 0)
184 if ((rc=i8k_smm(&regs)) < 0) { 164 return rc;
185 return rc; 165
186 } 166 switch ((regs.eax >> I8K_FN_SHIFT) & I8K_FN_MASK) {
187 167 case I8K_FN_UP:
188 switch ((regs.eax >> I8K_FN_SHIFT) & I8K_FN_MASK) { 168 return I8K_VOL_UP;
189 case I8K_FN_UP: 169 case I8K_FN_DOWN:
190 return I8K_VOL_UP; 170 return I8K_VOL_DOWN;
191 case I8K_FN_DOWN: 171 case I8K_FN_MUTE:
192 return I8K_VOL_DOWN; 172 return I8K_VOL_MUTE;
193 case I8K_FN_MUTE: 173 default:
194 return I8K_VOL_MUTE; 174 return 0;
195 default: 175 }
196 return 0;
197 }
198} 176}
199 177
200/* 178/*
@@ -202,20 +180,13 @@ static int i8k_get_fn_status(void)
202 */ 180 */
203static int i8k_get_power_status(void) 181static int i8k_get_power_status(void)
204{ 182{
205 SMMRegisters regs = { 0, 0, 0, 0, 0, 0 }; 183 struct smm_regs regs = { .eax = I8K_SMM_POWER_STATUS, };
206 int rc; 184 int rc;
207 185
208 regs.eax = I8K_SMM_POWER_STATUS; 186 if ((rc = i8k_smm(&regs)) < 0)
209 if ((rc=i8k_smm(&regs)) < 0) { 187 return rc;
210 return rc; 188
211 } 189 return (regs.eax & 0xff) == I8K_POWER_AC ? I8K_AC : I8K_BATTERY;
212
213 switch (regs.eax & 0xff) {
214 case I8K_POWER_AC:
215 return I8K_AC;
216 default:
217 return I8K_BATTERY;
218 }
219} 190}
220 191
221/* 192/*
@@ -223,16 +194,10 @@ static int i8k_get_power_status(void)
223 */ 194 */
224static int i8k_get_fan_status(int fan) 195static int i8k_get_fan_status(int fan)
225{ 196{
226 SMMRegisters regs = { 0, 0, 0, 0, 0, 0 }; 197 struct smm_regs regs = { .eax = I8K_SMM_GET_FAN, };
227 int rc;
228
229 regs.eax = I8K_SMM_GET_FAN;
230 regs.ebx = fan & 0xff;
231 if ((rc=i8k_smm(&regs)) < 0) {
232 return rc;
233 }
234 198
235 return (regs.eax & 0xff); 199 regs.ebx = fan & 0xff;
200 return i8k_smm(&regs) ? : regs.eax & 0xff;
236} 201}
237 202
238/* 203/*
@@ -240,16 +205,10 @@ static int i8k_get_fan_status(int fan)
240 */ 205 */
241static int i8k_get_fan_speed(int fan) 206static int i8k_get_fan_speed(int fan)
242{ 207{
243 SMMRegisters regs = { 0, 0, 0, 0, 0, 0 }; 208 struct smm_regs regs = { .eax = I8K_SMM_GET_SPEED, };
244 int rc;
245 209
246 regs.eax = I8K_SMM_GET_SPEED; 210 regs.ebx = fan & 0xff;
247 regs.ebx = fan & 0xff; 211 return i8k_smm(&regs) ? : (regs.eax & 0xffff) * I8K_FAN_MULT;
248 if ((rc=i8k_smm(&regs)) < 0) {
249 return rc;
250 }
251
252 return (regs.eax & 0xffff) * I8K_FAN_MULT;
253} 212}
254 213
255/* 214/*
@@ -257,532 +216,318 @@ static int i8k_get_fan_speed(int fan)
257 */ 216 */
258static int i8k_set_fan(int fan, int speed) 217static int i8k_set_fan(int fan, int speed)
259{ 218{
260 SMMRegisters regs = { 0, 0, 0, 0, 0, 0 }; 219 struct smm_regs regs = { .eax = I8K_SMM_SET_FAN, };
261 int rc;
262
263 speed = (speed < 0) ? 0 : ((speed > I8K_FAN_MAX) ? I8K_FAN_MAX : speed);
264 220
265 regs.eax = I8K_SMM_SET_FAN; 221 speed = (speed < 0) ? 0 : ((speed > I8K_FAN_MAX) ? I8K_FAN_MAX : speed);
266 regs.ebx = (fan & 0xff) | (speed << 8); 222 regs.ebx = (fan & 0xff) | (speed << 8);
267 if ((rc=i8k_smm(&regs)) < 0) {
268 return rc;
269 }
270 223
271 return (i8k_get_fan_status(fan)); 224 return i8k_smm(&regs) ? : i8k_get_fan_status(fan);
272} 225}
273 226
274/* 227/*
275 * Read the cpu temperature. 228 * Read the cpu temperature.
276 */ 229 */
277static int i8k_get_cpu_temp(void) 230static int i8k_get_temp(int sensor)
278{ 231{
279 SMMRegisters regs = { 0, 0, 0, 0, 0, 0 }; 232 struct smm_regs regs = { .eax = I8K_SMM_GET_TEMP, };
280 int rc; 233 int rc;
281 int temp; 234 int temp;
282 235
283#ifdef I8K_TEMPERATURE_BUG 236#ifdef I8K_TEMPERATURE_BUG
284 static int prev = 0; 237 static int prev;
285#endif 238#endif
239 regs.ebx = sensor & 0xff;
240 if ((rc = i8k_smm(&regs)) < 0)
241 return rc;
286 242
287 regs.eax = I8K_SMM_GET_TEMP; 243 temp = regs.eax & 0xff;
288 if ((rc=i8k_smm(&regs)) < 0) {
289 return rc;
290 }
291 temp = regs.eax & 0xff;
292 244
293#ifdef I8K_TEMPERATURE_BUG 245#ifdef I8K_TEMPERATURE_BUG
294 /* 246 /*
295 * Sometimes the temperature sensor returns 0x99, which is out of range. 247 * Sometimes the temperature sensor returns 0x99, which is out of range.
296 * In this case we return (once) the previous cached value. For example: 248 * In this case we return (once) the previous cached value. For example:
297 # 1003655137 00000058 00005a4b 249 # 1003655137 00000058 00005a4b
298 # 1003655138 00000099 00003a80 <--- 0x99 = 153 degrees 250 # 1003655138 00000099 00003a80 <--- 0x99 = 153 degrees
299 # 1003655139 00000054 00005c52 251 # 1003655139 00000054 00005c52
300 */ 252 */
301 if (temp > I8K_MAX_TEMP) { 253 if (temp > I8K_MAX_TEMP) {
302 temp = prev; 254 temp = prev;
303 prev = I8K_MAX_TEMP; 255 prev = I8K_MAX_TEMP;
304 } else { 256 } else {
305 prev = temp; 257 prev = temp;
306 } 258 }
307#endif 259#endif
308 260
309 return temp; 261 return temp;
310} 262}
311 263
312static int i8k_get_dell_signature(void) 264static int i8k_get_dell_signature(int req_fn)
313{ 265{
314 SMMRegisters regs = { 0, 0, 0, 0, 0, 0 }; 266 struct smm_regs regs = { .eax = req_fn, };
315 int rc; 267 int rc;
316 268
317 regs.eax = I8K_SMM_GET_DELL_SIG; 269 if ((rc = i8k_smm(&regs)) < 0)
318 if ((rc=i8k_smm(&regs)) < 0) { 270 return rc;
319 return rc;
320 }
321 271
322 if ((regs.eax == 1145651527) && (regs.edx == 1145392204)) { 272 return regs.eax == 1145651527 && regs.edx == 1145392204 ? 0 : -1;
323 return 0;
324 } else {
325 return -1;
326 }
327} 273}
328 274
329static int i8k_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, 275static int i8k_ioctl(struct inode *ip, struct file *fp, unsigned int cmd,
330 unsigned long arg) 276 unsigned long arg)
331{ 277{
332 int val; 278 int val = 0;
333 int speed; 279 int speed;
334 unsigned char buff[16]; 280 unsigned char buff[16];
335 int __user *argp = (int __user *)arg; 281 int __user *argp = (int __user *)arg;
336
337 if (!argp)
338 return -EINVAL;
339
340 switch (cmd) {
341 case I8K_BIOS_VERSION:
342 val = i8k_get_bios_version();
343 break;
344
345 case I8K_MACHINE_ID:
346 memset(buff, 0, 16);
347 val = i8k_get_serial_number(buff);
348 break;
349
350 case I8K_FN_STATUS:
351 val = i8k_get_fn_status();
352 break;
353
354 case I8K_POWER_STATUS:
355 val = i8k_get_power_status();
356 break;
357
358 case I8K_GET_TEMP:
359 val = i8k_get_cpu_temp();
360 break;
361
362 case I8K_GET_SPEED:
363 if (copy_from_user(&val, argp, sizeof(int))) {
364 return -EFAULT;
365 }
366 val = i8k_get_fan_speed(val);
367 break;
368
369 case I8K_GET_FAN:
370 if (copy_from_user(&val, argp, sizeof(int))) {
371 return -EFAULT;
372 }
373 val = i8k_get_fan_status(val);
374 break;
375 282
376 case I8K_SET_FAN: 283 if (!argp)
377 if (restricted && !capable(CAP_SYS_ADMIN)) { 284 return -EINVAL;
378 return -EPERM;
379 }
380 if (copy_from_user(&val, argp, sizeof(int))) {
381 return -EFAULT;
382 }
383 if (copy_from_user(&speed, argp+1, sizeof(int))) {
384 return -EFAULT;
385 }
386 val = i8k_set_fan(val, speed);
387 break;
388 285
389 default: 286 switch (cmd) {
390 return -EINVAL; 287 case I8K_BIOS_VERSION:
391 } 288 val = i8k_get_bios_version();
289 break;
392 290
393 if (val < 0) { 291 case I8K_MACHINE_ID:
394 return val; 292 memset(buff, 0, 16);
395 } 293 strlcpy(buff, i8k_get_dmi_data(DMI_PRODUCT_SERIAL), sizeof(buff));
294 break;
396 295
397 switch (cmd) { 296 case I8K_FN_STATUS:
398 case I8K_BIOS_VERSION: 297 val = i8k_get_fn_status();
399 if (copy_to_user(argp, &val, 4)) { 298 break;
400 return -EFAULT;
401 }
402 break;
403 case I8K_MACHINE_ID:
404 if (copy_to_user(argp, buff, 16)) {
405 return -EFAULT;
406 }
407 break;
408 default:
409 if (copy_to_user(argp, &val, sizeof(int))) {
410 return -EFAULT;
411 }
412 break;
413 }
414 299
415 return 0; 300 case I8K_POWER_STATUS:
416} 301 val = i8k_get_power_status();
302 break;
417 303
418/* 304 case I8K_GET_TEMP:
419 * Print the information for /proc/i8k. 305 val = i8k_get_temp(0);
420 */ 306 break;
421static int i8k_get_info(char *buffer, char **start, off_t fpos, int length)
422{
423 int n, fn_key, cpu_temp, ac_power;
424 int left_fan, right_fan, left_speed, right_speed;
425
426 cpu_temp = i8k_get_cpu_temp(); /* 11100 µs */
427 left_fan = i8k_get_fan_status(I8K_FAN_LEFT); /* 580 µs */
428 right_fan = i8k_get_fan_status(I8K_FAN_RIGHT); /* 580 µs */
429 left_speed = i8k_get_fan_speed(I8K_FAN_LEFT); /* 580 µs */
430 right_speed = i8k_get_fan_speed(I8K_FAN_RIGHT); /* 580 µs */
431 fn_key = i8k_get_fn_status(); /* 750 µs */
432 if (power_status) {
433 ac_power = i8k_get_power_status(); /* 14700 µs */
434 } else {
435 ac_power = -1;
436 }
437
438 /*
439 * Info:
440 *
441 * 1) Format version (this will change if format changes)
442 * 2) BIOS version
443 * 3) BIOS machine ID
444 * 4) Cpu temperature
445 * 5) Left fan status
446 * 6) Right fan status
447 * 7) Left fan speed
448 * 8) Right fan speed
449 * 9) AC power
450 * 10) Fn Key status
451 */
452 n = sprintf(buffer, "%s %s %s %d %d %d %d %d %d %d\n",
453 I8K_PROC_FMT,
454 bios_version,
455 serial_number,
456 cpu_temp,
457 left_fan,
458 right_fan,
459 left_speed,
460 right_speed,
461 ac_power,
462 fn_key);
463
464 return n;
465}
466 307
467static ssize_t i8k_read(struct file *f, char __user *buffer, size_t len, loff_t *fpos) 308 case I8K_GET_SPEED:
468{ 309 if (copy_from_user(&val, argp, sizeof(int)))
469 int n; 310 return -EFAULT;
470 char info[128];
471 311
472 n = i8k_get_info(info, NULL, 0, 128); 312 val = i8k_get_fan_speed(val);
473 if (n <= 0) { 313 break;
474 return n;
475 }
476 314
477 if (*fpos >= n) { 315 case I8K_GET_FAN:
478 return 0; 316 if (copy_from_user(&val, argp, sizeof(int)))
479 } 317 return -EFAULT;
480 318
481 if ((*fpos + len) >= n) { 319 val = i8k_get_fan_status(val);
482 len = n - *fpos; 320 break;
483 }
484 321
485 if (copy_to_user(buffer, info, len) != 0) { 322 case I8K_SET_FAN:
486 return -EFAULT; 323 if (restricted && !capable(CAP_SYS_ADMIN))
487 } 324 return -EPERM;
488 325
489 *fpos += len; 326 if (copy_from_user(&val, argp, sizeof(int)))
490 return len; 327 return -EFAULT;
491}
492 328
493static char* __init string_trim(char *s, int size) 329 if (copy_from_user(&speed, argp + 1, sizeof(int)))
494{ 330 return -EFAULT;
495 int len;
496 char *p;
497 331
498 if ((len = strlen(s)) > size) { 332 val = i8k_set_fan(val, speed);
499 len = size; 333 break;
500 }
501 334
502 for (p=s+len-1; len && (*p==' '); len--,p--) { 335 default:
503 *p = '\0'; 336 return -EINVAL;
504 } 337 }
505 338
506 return s; 339 if (val < 0)
507} 340 return val;
508 341
509/* DMI code, stolen from arch/i386/kernel/dmi_scan.c */ 342 switch (cmd) {
343 case I8K_BIOS_VERSION:
344 if (copy_to_user(argp, &val, 4))
345 return -EFAULT;
510 346
511/* 347 break;
512 * |<-- dmi->length -->| 348 case I8K_MACHINE_ID:
513 * | | 349 if (copy_to_user(argp, buff, 16))
514 * |dmi header s=N | string1,\0, ..., stringN,\0, ..., \0 350 return -EFAULT;
515 * | |
516 * +-----------------------+
517 */
518static char* __init dmi_string(DMIHeader *dmi, u8 s)
519{
520 u8 *p;
521 351
522 if (!s) { 352 break;
523 return ""; 353 default:
524 } 354 if (copy_to_user(argp, &val, sizeof(int)))
525 s--; 355 return -EFAULT;
526 356
527 p = (u8 *)dmi + dmi->length; 357 break;
528 while (s > 0) { 358 }
529 p += strlen(p);
530 p++;
531 s--;
532 }
533 359
534 return p; 360 return 0;
535} 361}
536 362
537static void __init dmi_decode(DMIHeader *dmi) 363/*
364 * Print the information for /proc/i8k.
365 */
366static int i8k_proc_show(struct seq_file *seq, void *offset)
538{ 367{
539 u8 *data = (u8 *) dmi; 368 int fn_key, cpu_temp, ac_power;
540 char *p; 369 int left_fan, right_fan, left_speed, right_speed;
541 370
542#ifdef I8K_DEBUG 371 cpu_temp = i8k_get_temp(0); /* 11100 µs */
543 int i; 372 left_fan = i8k_get_fan_status(I8K_FAN_LEFT); /* 580 µs */
544 printk("%08x ", (int)data); 373 right_fan = i8k_get_fan_status(I8K_FAN_RIGHT); /* 580 µs */
545 for (i=0; i<data[1] && i<64; i++) { 374 left_speed = i8k_get_fan_speed(I8K_FAN_LEFT); /* 580 µs */
546 printk("%02x ", data[i]); 375 right_speed = i8k_get_fan_speed(I8K_FAN_RIGHT); /* 580 µs */
547 } 376 fn_key = i8k_get_fn_status(); /* 750 µs */
548 printk("\n"); 377 if (power_status)
549#endif 378 ac_power = i8k_get_power_status(); /* 14700 µs */
550 379 else
551 switch (dmi->type) { 380 ac_power = -1;
552 case 0: /* BIOS Information */
553 p = dmi_string(dmi,data[5]);
554 if (*p) {
555 strlcpy(bios_version, p, sizeof(bios_version));
556 string_trim(bios_version, sizeof(bios_version));
557 }
558 break;
559 case 1: /* System Information */
560 p = dmi_string(dmi,data[4]);
561 if (*p) {
562 strlcpy(system_vendor, p, sizeof(system_vendor));
563 string_trim(system_vendor, sizeof(system_vendor));
564 }
565 p = dmi_string(dmi,data[5]);
566 if (*p) {
567 strlcpy(product_name, p, sizeof(product_name));
568 string_trim(product_name, sizeof(product_name));
569 }
570 p = dmi_string(dmi,data[7]);
571 if (*p) {
572 strlcpy(serial_number, p, sizeof(serial_number));
573 string_trim(serial_number, sizeof(serial_number));
574 }
575 break;
576 }
577}
578 381
579static int __init dmi_table(u32 base, int len, int num, void (*fn)(DMIHeader*))
580{
581 u8 *buf;
582 u8 *data;
583 DMIHeader *dmi;
584 int i = 1;
585
586 buf = ioremap(base, len);
587 if (buf == NULL) {
588 return -1;
589 }
590 data = buf;
591
592 /*
593 * Stop when we see al the items the table claimed to have
594 * or we run off the end of the table (also happens)
595 */
596 while ((i<num) && ((data-buf) < len)) {
597 dmi = (DMIHeader *)data;
598 /*
599 * Avoid misparsing crud if the length of the last
600 * record is crap
601 */
602 if ((data-buf+dmi->length) >= len) {
603 break;
604 }
605 fn(dmi);
606 data += dmi->length;
607 /* 382 /*
608 * Don't go off the end of the data if there is 383 * Info:
609 * stuff looking like string fill past the end 384 *
385 * 1) Format version (this will change if format changes)
386 * 2) BIOS version
387 * 3) BIOS machine ID
388 * 4) Cpu temperature
389 * 5) Left fan status
390 * 6) Right fan status
391 * 7) Left fan speed
392 * 8) Right fan speed
393 * 9) AC power
394 * 10) Fn Key status
610 */ 395 */
611 while (((data-buf) < len) && (*data || data[1])) { 396 return seq_printf(seq, "%s %s %s %d %d %d %d %d %d %d\n",
612 data++; 397 I8K_PROC_FMT,
613 } 398 bios_version,
614 data += 2; 399 dmi_get_system_info(DMI_PRODUCT_SERIAL) ? : "N/A",
615 i++; 400 cpu_temp,
616 } 401 left_fan, right_fan, left_speed, right_speed,
617 iounmap(buf); 402 ac_power, fn_key);
618
619 return 0;
620} 403}
621 404
622static int __init dmi_iterate(void (*decode)(DMIHeader *)) 405static int i8k_open_fs(struct inode *inode, struct file *file)
623{ 406{
624 unsigned char buf[20]; 407 return single_open(file, i8k_proc_show, NULL);
625 void __iomem *p = ioremap(0xe0000, 0x20000), *q;
626
627 if (!p)
628 return -1;
629
630 for (q = p; q < p + 0x20000; q += 16) {
631 memcpy_fromio(buf, q, 20);
632 if (memcmp(buf, "_DMI_", 5)==0) {
633 u16 num = buf[13]<<8 | buf[12];
634 u16 len = buf [7]<<8 | buf [6];
635 u32 base = buf[11]<<24 | buf[10]<<16 | buf[9]<<8 | buf[8];
636#ifdef I8K_DEBUG
637 printk(KERN_INFO "DMI %d.%d present.\n",
638 buf[14]>>4, buf[14]&0x0F);
639 printk(KERN_INFO "%d structures occupying %d bytes.\n",
640 buf[13]<<8 | buf[12],
641 buf [7]<<8 | buf[6]);
642 printk(KERN_INFO "DMI table at 0x%08X.\n",
643 buf[11]<<24 | buf[10]<<16 | buf[9]<<8 | buf[8]);
644#endif
645 if (dmi_table(base, len, num, decode)==0) {
646 iounmap(p);
647 return 0;
648 }
649 }
650 }
651 iounmap(p);
652 return -1;
653} 408}
654/* end of DMI code */
655
656/*
657 * Get DMI information.
658 */
659static int __init i8k_dmi_probe(void)
660{
661 char **p;
662
663 if (dmi_iterate(dmi_decode) != 0) {
664 printk(KERN_INFO "i8k: unable to get DMI information\n");
665 return -ENODEV;
666 }
667
668 if (strncmp(system_vendor,DELL_SIGNATURE,strlen(DELL_SIGNATURE)) != 0) {
669 printk(KERN_INFO "i8k: not running on a Dell system\n");
670 return -ENODEV;
671 }
672
673 for (p=supported_models; ; p++) {
674 if (!*p) {
675 printk(KERN_INFO "i8k: unsupported model: %s\n", product_name);
676 return -ENODEV;
677 }
678 if (strncmp(product_name,*p,strlen(*p)) == 0) {
679 break;
680 }
681 }
682 409
683 return 0; 410static struct dmi_system_id __initdata i8k_dmi_table[] = {
684} 411 {
412 .ident = "Dell Inspiron",
413 .matches = {
414 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer"),
415 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron"),
416 },
417 },
418 {
419 .ident = "Dell Latitude",
420 .matches = {
421 DMI_MATCH(DMI_SYS_VENDOR, "Dell Computer"),
422 DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"),
423 },
424 },
425 {
426 .ident = "Dell Inspiron 2",
427 .matches = {
428 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
429 DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron"),
430 },
431 },
432 {
433 .ident = "Dell Latitude 2",
434 .matches = {
435 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
436 DMI_MATCH(DMI_PRODUCT_NAME, "Latitude"),
437 },
438 },
439 { }
440};
685 441
686/* 442/*
687 * Probe for the presence of a supported laptop. 443 * Probe for the presence of a supported laptop.
688 */ 444 */
689static int __init i8k_probe(void) 445static int __init i8k_probe(void)
690{ 446{
691 char buff[4]; 447 char buff[4];
692 int version; 448 int version;
693 int smm_found = 0; 449
694
695 /*
696 * Get DMI information
697 */
698 if (i8k_dmi_probe() != 0) {
699 printk(KERN_INFO "i8k: vendor=%s, model=%s, version=%s\n",
700 system_vendor, product_name, bios_version);
701 }
702
703 /*
704 * Get SMM Dell signature
705 */
706 if (i8k_get_dell_signature() != 0) {
707 printk(KERN_INFO "i8k: unable to get SMM Dell signature\n");
708 } else {
709 smm_found = 1;
710 }
711
712 /*
713 * Get SMM BIOS version.
714 */
715 version = i8k_get_bios_version();
716 if (version <= 0) {
717 printk(KERN_INFO "i8k: unable to get SMM BIOS version\n");
718 } else {
719 smm_found = 1;
720 buff[0] = (version >> 16) & 0xff;
721 buff[1] = (version >> 8) & 0xff;
722 buff[2] = (version) & 0xff;
723 buff[3] = '\0';
724 /* 450 /*
725 * If DMI BIOS version is unknown use SMM BIOS version. 451 * Get DMI information
726 */ 452 */
727 if (bios_version[0] == '?') { 453 if (!dmi_check_system(i8k_dmi_table)) {
728 strcpy(bios_version, buff); 454 if (!ignore_dmi && !force)
455 return -ENODEV;
456
457 printk(KERN_INFO "i8k: not running on a supported Dell system.\n");
458 printk(KERN_INFO "i8k: vendor=%s, model=%s, version=%s\n",
459 i8k_get_dmi_data(DMI_SYS_VENDOR),
460 i8k_get_dmi_data(DMI_PRODUCT_NAME),
461 i8k_get_dmi_data(DMI_BIOS_VERSION));
729 } 462 }
463
464 strlcpy(bios_version, i8k_get_dmi_data(DMI_BIOS_VERSION), sizeof(bios_version));
465
730 /* 466 /*
731 * Check if the two versions match. 467 * Get SMM Dell signature
732 */ 468 */
733 if (strncmp(buff,bios_version,sizeof(bios_version)) != 0) { 469 if (i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG1) &&
734 printk(KERN_INFO "i8k: BIOS version mismatch: %s != %s\n", 470 i8k_get_dell_signature(I8K_SMM_GET_DELL_SIG2)) {
735 buff, bios_version); 471 printk(KERN_ERR "i8k: unable to get SMM Dell signature\n");
472 if (!force)
473 return -ENODEV;
736 } 474 }
737 }
738 475
739 if (!smm_found && !force) { 476 /*
740 return -ENODEV; 477 * Get SMM BIOS version.
741 } 478 */
479 version = i8k_get_bios_version();
480 if (version <= 0) {
481 printk(KERN_WARNING "i8k: unable to get SMM BIOS version\n");
482 } else {
483 buff[0] = (version >> 16) & 0xff;
484 buff[1] = (version >> 8) & 0xff;
485 buff[2] = (version) & 0xff;
486 buff[3] = '\0';
487 /*
488 * If DMI BIOS version is unknown use SMM BIOS version.
489 */
490 if (!dmi_get_system_info(DMI_BIOS_VERSION))
491 strlcpy(bios_version, buff, sizeof(bios_version));
492
493 /*
494 * Check if the two versions match.
495 */
496 if (strncmp(buff, bios_version, sizeof(bios_version)) != 0)
497 printk(KERN_WARNING "i8k: BIOS version mismatch: %s != %s\n",
498 buff, bios_version);
499 }
742 500
743 return 0; 501 return 0;
744} 502}
745 503
746#ifdef MODULE 504static int __init i8k_init(void)
747static
748#endif
749int __init i8k_init(void)
750{ 505{
751 struct proc_dir_entry *proc_i8k; 506 struct proc_dir_entry *proc_i8k;
752
753 /* Are we running on an supported laptop? */
754 if (i8k_probe() != 0) {
755 return -ENODEV;
756 }
757
758 /* Register the proc entry */
759 proc_i8k = create_proc_info_entry("i8k", 0, NULL, i8k_get_info);
760 if (!proc_i8k) {
761 return -ENOENT;
762 }
763 proc_i8k->proc_fops = &i8k_fops;
764 proc_i8k->owner = THIS_MODULE;
765
766 printk(KERN_INFO
767 "Dell laptop SMM driver v%s Massimo Dal Zotto (dz@debian.org)\n",
768 I8K_VERSION);
769
770 return 0;
771}
772 507
773#ifdef MODULE 508 /* Are we running on an supported laptop? */
774int init_module(void) 509 if (i8k_probe())
775{ 510 return -ENODEV;
776 return i8k_init(); 511
512 /* Register the proc entry */
513 proc_i8k = create_proc_entry("i8k", 0, NULL);
514 if (!proc_i8k)
515 return -ENOENT;
516
517 proc_i8k->proc_fops = &i8k_fops;
518 proc_i8k->owner = THIS_MODULE;
519
520 printk(KERN_INFO
521 "Dell laptop SMM driver v%s Massimo Dal Zotto (dz@debian.org)\n",
522 I8K_VERSION);
523
524 return 0;
777} 525}
778 526
779void cleanup_module(void) 527static void __exit i8k_exit(void)
780{ 528{
781 /* Remove the proc entry */ 529 remove_proc_entry("i8k", NULL);
782 remove_proc_entry("i8k", NULL);
783
784 printk(KERN_INFO "i8k: module unloaded\n");
785} 530}
786#endif
787 531
788/* end of file */ 532module_init(i8k_init);
533module_exit(i8k_exit);
diff --git a/drivers/char/ip2/i2cmd.c b/drivers/char/ip2/i2cmd.c
index fd299d6c42ac..cb8f4198e9a3 100644
--- a/drivers/char/ip2/i2cmd.c
+++ b/drivers/char/ip2/i2cmd.c
@@ -97,7 +97,7 @@ static UCHAR ct41[] = { 1, BYP, 0x29 }; // RESUME
97//static UCHAR ct44[]={ 2, BTH, 0x2C,0 }; // MS PING 97//static UCHAR ct44[]={ 2, BTH, 0x2C,0 }; // MS PING
98//static UCHAR ct45[]={ 1, BTH, 0x2D }; // HOTENAB 98//static UCHAR ct45[]={ 1, BTH, 0x2D }; // HOTENAB
99//static UCHAR ct46[]={ 1, BTH, 0x2E }; // HOTDSAB 99//static UCHAR ct46[]={ 1, BTH, 0x2E }; // HOTDSAB
100static UCHAR ct47[] = { 7, BTH, 0x2F,0,0,0,0,0,0 }; // UNIX FLAGS 100//static UCHAR ct47[]={ 7, BTH, 0x2F,0,0,0,0,0,0 }; // UNIX FLAGS
101//static UCHAR ct48[]={ 1, BTH, 0x30 }; // DSRFLOWENAB 101//static UCHAR ct48[]={ 1, BTH, 0x30 }; // DSRFLOWENAB
102//static UCHAR ct49[]={ 1, BTH, 0x31 }; // DSRFLOWDSAB 102//static UCHAR ct49[]={ 1, BTH, 0x31 }; // DSRFLOWDSAB
103//static UCHAR ct50[]={ 1, BTH, 0x32 }; // DTRFLOWENAB 103//static UCHAR ct50[]={ 1, BTH, 0x32 }; // DTRFLOWENAB
@@ -162,6 +162,7 @@ static UCHAR ct89[]={ 1, BYP, 0x59 }; // DSS_NOW
162// This routine sets the parameters of command 47 and returns a pointer to the 162// This routine sets the parameters of command 47 and returns a pointer to the
163// appropriate structure. 163// appropriate structure.
164//****************************************************************************** 164//******************************************************************************
165#if 0
165cmdSyntaxPtr 166cmdSyntaxPtr
166i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag) 167i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag)
167{ 168{
@@ -175,6 +176,7 @@ i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag)
175 pCM->cmd[6] = (unsigned char) (lflag >> 8); 176 pCM->cmd[6] = (unsigned char) (lflag >> 8);
176 return pCM; 177 return pCM;
177} 178}
179#endif /* 0 */
178 180
179//****************************************************************************** 181//******************************************************************************
180// Function: i2cmdBaudDef(which, rate) 182// Function: i2cmdBaudDef(which, rate)
@@ -187,7 +189,7 @@ i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag)
187// This routine sets the parameters of commands 54 or 55 (according to the 189// This routine sets the parameters of commands 54 or 55 (according to the
188// argument which), and returns a pointer to the appropriate structure. 190// argument which), and returns a pointer to the appropriate structure.
189//****************************************************************************** 191//******************************************************************************
190cmdSyntaxPtr 192static cmdSyntaxPtr
191i2cmdBaudDef(int which, unsigned short rate) 193i2cmdBaudDef(int which, unsigned short rate)
192{ 194{
193 cmdSyntaxPtr pCM; 195 cmdSyntaxPtr pCM;
diff --git a/drivers/char/ip2/i2cmd.h b/drivers/char/ip2/i2cmd.h
index c41728a85710..baa4e721b758 100644
--- a/drivers/char/ip2/i2cmd.h
+++ b/drivers/char/ip2/i2cmd.h
@@ -64,16 +64,6 @@ typedef struct _cmdSyntax
64 // directly from user-level 64 // directly from user-level
65#define VAR 0x10 // This command is of variable length! 65#define VAR 0x10 // This command is of variable length!
66 66
67//-----------------------------------
68// External declarations for i2cmd.c
69//-----------------------------------
70// Routine to set up parameters for the "define hot-key sequence" command. Since
71// there is more than one parameter to assign, we must use a function rather
72// than a macro (used usually).
73//
74extern cmdSyntaxPtr i2cmdUnixFlags(USHORT iflag,USHORT cflag,USHORT lflag);
75extern cmdSyntaxPtr i2cmdBaudDef(int which, USHORT rate);
76
77// Declarations for the global arrays used to bear the commands and their 67// Declarations for the global arrays used to bear the commands and their
78// arguments. 68// arguments.
79// 69//
@@ -433,6 +423,7 @@ static UCHAR cc02[];
433#define CMD_HOT_ENAB (cmdSyntaxPtr)(ct45) // Enable Hot-key checking 423#define CMD_HOT_ENAB (cmdSyntaxPtr)(ct45) // Enable Hot-key checking
434#define CMD_HOT_DSAB (cmdSyntaxPtr)(ct46) // Disable Hot-key checking 424#define CMD_HOT_DSAB (cmdSyntaxPtr)(ct46) // Disable Hot-key checking
435 425
426#if 0
436// COMMAND 47: Send Protocol info via Unix flags: 427// COMMAND 47: Send Protocol info via Unix flags:
437// iflag = Unix tty t_iflag 428// iflag = Unix tty t_iflag
438// cflag = Unix tty t_cflag 429// cflag = Unix tty t_cflag
@@ -441,6 +432,7 @@ static UCHAR cc02[];
441// within these flags 432// within these flags
442// 433//
443#define CMD_UNIX_FLAGS(iflag,cflag,lflag) i2cmdUnixFlags(iflag,cflag,lflag) 434#define CMD_UNIX_FLAGS(iflag,cflag,lflag) i2cmdUnixFlags(iflag,cflag,lflag)
435#endif /* 0 */
444 436
445#define CMD_DSRFL_ENAB (cmdSyntaxPtr)(ct48) // Enable DSR receiver ctrl 437#define CMD_DSRFL_ENAB (cmdSyntaxPtr)(ct48) // Enable DSR receiver ctrl
446#define CMD_DSRFL_DSAB (cmdSyntaxPtr)(ct49) // Disable DSR receiver ctrl 438#define CMD_DSRFL_DSAB (cmdSyntaxPtr)(ct49) // Disable DSR receiver ctrl
diff --git a/drivers/char/ip2main.c b/drivers/char/ip2main.c
index fca9a978fb73..cf0cd58d6305 100644
--- a/drivers/char/ip2main.c
+++ b/drivers/char/ip2main.c
@@ -302,7 +302,7 @@ static char rirqs[IP2_MAX_BOARDS];
302static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0}; 302static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0};
303 303
304/* for sysfs class support */ 304/* for sysfs class support */
305static struct class_simple *ip2_class; 305static struct class *ip2_class;
306 306
307// Some functions to keep track of what irq's we have 307// Some functions to keep track of what irq's we have
308 308
@@ -414,9 +414,9 @@ cleanup_module(void)
414 iiResetDelay( i2BoardPtrTable[i] ); 414 iiResetDelay( i2BoardPtrTable[i] );
415 /* free io addresses and Tibet */ 415 /* free io addresses and Tibet */
416 release_region( ip2config.addr[i], 8 ); 416 release_region( ip2config.addr[i], 8 );
417 class_simple_device_remove(MKDEV(IP2_IPL_MAJOR, 4 * i)); 417 class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i));
418 devfs_remove("ip2/ipl%d", i); 418 devfs_remove("ip2/ipl%d", i);
419 class_simple_device_remove(MKDEV(IP2_IPL_MAJOR, 4 * i + 1)); 419 class_device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
420 devfs_remove("ip2/stat%d", i); 420 devfs_remove("ip2/stat%d", i);
421 } 421 }
422 /* Disable and remove interrupt handler. */ 422 /* Disable and remove interrupt handler. */
@@ -425,7 +425,7 @@ cleanup_module(void)
425 clear_requested_irq( ip2config.irq[i]); 425 clear_requested_irq( ip2config.irq[i]);
426 } 426 }
427 } 427 }
428 class_simple_destroy(ip2_class); 428 class_destroy(ip2_class);
429 devfs_remove("ip2"); 429 devfs_remove("ip2");
430 if ( ( err = tty_unregister_driver ( ip2_tty_driver ) ) ) { 430 if ( ( err = tty_unregister_driver ( ip2_tty_driver ) ) ) {
431 printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err); 431 printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n", err);
@@ -700,7 +700,7 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
700 printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err ); 700 printk(KERN_ERR "IP2: failed to register IPL device (%d)\n", err );
701 } else { 701 } else {
702 /* create the sysfs class */ 702 /* create the sysfs class */
703 ip2_class = class_simple_create(THIS_MODULE, "ip2"); 703 ip2_class = class_create(THIS_MODULE, "ip2");
704 if (IS_ERR(ip2_class)) { 704 if (IS_ERR(ip2_class)) {
705 err = PTR_ERR(ip2_class); 705 err = PTR_ERR(ip2_class);
706 goto out_chrdev; 706 goto out_chrdev;
@@ -722,25 +722,25 @@ ip2_loadmain(int *iop, int *irqp, unsigned char *firmware, int firmsize)
722 } 722 }
723 723
724 if ( NULL != ( pB = i2BoardPtrTable[i] ) ) { 724 if ( NULL != ( pB = i2BoardPtrTable[i] ) ) {
725 class_simple_device_add(ip2_class, MKDEV(IP2_IPL_MAJOR, 725 class_device_create(ip2_class, MKDEV(IP2_IPL_MAJOR,
726 4 * i), NULL, "ipl%d", i); 726 4 * i), NULL, "ipl%d", i);
727 err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i), 727 err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i),
728 S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR, 728 S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
729 "ip2/ipl%d", i); 729 "ip2/ipl%d", i);
730 if (err) { 730 if (err) {
731 class_simple_device_remove(MKDEV(IP2_IPL_MAJOR, 731 class_device_destroy(ip2_class,
732 4 * i)); 732 MKDEV(IP2_IPL_MAJOR, 4 * i));
733 goto out_class; 733 goto out_class;
734 } 734 }
735 735
736 class_simple_device_add(ip2_class, MKDEV(IP2_IPL_MAJOR, 736 class_device_create(ip2_class, MKDEV(IP2_IPL_MAJOR,
737 4 * i + 1), NULL, "stat%d", i); 737 4 * i + 1), NULL, "stat%d", i);
738 err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i + 1), 738 err = devfs_mk_cdev(MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
739 S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR, 739 S_IRUSR | S_IWUSR | S_IRGRP | S_IFCHR,
740 "ip2/stat%d", i); 740 "ip2/stat%d", i);
741 if (err) { 741 if (err) {
742 class_simple_device_remove(MKDEV(IP2_IPL_MAJOR, 742 class_device_destroy(ip2_class,
743 4 * i + 1)); 743 MKDEV(IP2_IPL_MAJOR, 4 * i + 1));
744 goto out_class; 744 goto out_class;
745 } 745 }
746 746
@@ -798,7 +798,7 @@ retry:
798 goto out; 798 goto out;
799 799
800out_class: 800out_class:
801 class_simple_destroy(ip2_class); 801 class_destroy(ip2_class);
802out_chrdev: 802out_chrdev:
803 unregister_chrdev(IP2_IPL_MAJOR, "ip2"); 803 unregister_chrdev(IP2_IPL_MAJOR, "ip2");
804out: 804out:
@@ -2691,16 +2691,6 @@ no_xon:
2691 pCh->flags |= ASYNC_CHECK_CD; 2691 pCh->flags |= ASYNC_CHECK_CD;
2692 } 2692 }
2693 2693
2694#ifdef XXX
2695do_flags_thing: // This is a test, we don't do the flags thing
2696
2697 if ( (cflag & CRTSCTS) ) {
2698 cflag |= 014000000000;
2699 }
2700 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1,
2701 CMD_UNIX_FLAGS(iflag,cflag,lflag));
2702#endif
2703
2704service_it: 2694service_it:
2705 i2DrainOutput( pCh, 100 ); 2695 i2DrainOutput( pCh, 100 );
2706} 2696}
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c
index 6dc765dc5413..e0a53570fea1 100644
--- a/drivers/char/ipmi/ipmi_devintf.c
+++ b/drivers/char/ipmi/ipmi_devintf.c
@@ -45,6 +45,7 @@
45#include <asm/semaphore.h> 45#include <asm/semaphore.h>
46#include <linux/init.h> 46#include <linux/init.h>
47#include <linux/device.h> 47#include <linux/device.h>
48#include <linux/compat.h>
48 49
49#define IPMI_DEVINTF_VERSION "v33" 50#define IPMI_DEVINTF_VERSION "v33"
50 51
@@ -500,10 +501,205 @@ static int ipmi_ioctl(struct inode *inode,
500 return rv; 501 return rv;
501} 502}
502 503
504#ifdef CONFIG_COMPAT
505
506/*
507 * The following code contains code for supporting 32-bit compatible
508 * ioctls on 64-bit kernels. This allows running 32-bit apps on the
509 * 64-bit kernel
510 */
511#define COMPAT_IPMICTL_SEND_COMMAND \
512 _IOR(IPMI_IOC_MAGIC, 13, struct compat_ipmi_req)
513#define COMPAT_IPMICTL_SEND_COMMAND_SETTIME \
514 _IOR(IPMI_IOC_MAGIC, 21, struct compat_ipmi_req_settime)
515#define COMPAT_IPMICTL_RECEIVE_MSG \
516 _IOWR(IPMI_IOC_MAGIC, 12, struct compat_ipmi_recv)
517#define COMPAT_IPMICTL_RECEIVE_MSG_TRUNC \
518 _IOWR(IPMI_IOC_MAGIC, 11, struct compat_ipmi_recv)
519
520struct compat_ipmi_msg {
521 u8 netfn;
522 u8 cmd;
523 u16 data_len;
524 compat_uptr_t data;
525};
526
527struct compat_ipmi_req {
528 compat_uptr_t addr;
529 compat_uint_t addr_len;
530 compat_long_t msgid;
531 struct compat_ipmi_msg msg;
532};
533
534struct compat_ipmi_recv {
535 compat_int_t recv_type;
536 compat_uptr_t addr;
537 compat_uint_t addr_len;
538 compat_long_t msgid;
539 struct compat_ipmi_msg msg;
540};
541
542struct compat_ipmi_req_settime {
543 struct compat_ipmi_req req;
544 compat_int_t retries;
545 compat_uint_t retry_time_ms;
546};
547
548/*
549 * Define some helper functions for copying IPMI data
550 */
551static long get_compat_ipmi_msg(struct ipmi_msg *p64,
552 struct compat_ipmi_msg __user *p32)
553{
554 compat_uptr_t tmp;
555
556 if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
557 __get_user(p64->netfn, &p32->netfn) ||
558 __get_user(p64->cmd, &p32->cmd) ||
559 __get_user(p64->data_len, &p32->data_len) ||
560 __get_user(tmp, &p32->data))
561 return -EFAULT;
562 p64->data = compat_ptr(tmp);
563 return 0;
564}
565
566static long put_compat_ipmi_msg(struct ipmi_msg *p64,
567 struct compat_ipmi_msg __user *p32)
568{
569 if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
570 __put_user(p64->netfn, &p32->netfn) ||
571 __put_user(p64->cmd, &p32->cmd) ||
572 __put_user(p64->data_len, &p32->data_len))
573 return -EFAULT;
574 return 0;
575}
576
577static long get_compat_ipmi_req(struct ipmi_req *p64,
578 struct compat_ipmi_req __user *p32)
579{
580
581 compat_uptr_t tmp;
582
583 if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
584 __get_user(tmp, &p32->addr) ||
585 __get_user(p64->addr_len, &p32->addr_len) ||
586 __get_user(p64->msgid, &p32->msgid) ||
587 get_compat_ipmi_msg(&p64->msg, &p32->msg))
588 return -EFAULT;
589 p64->addr = compat_ptr(tmp);
590 return 0;
591}
592
593static long get_compat_ipmi_req_settime(struct ipmi_req_settime *p64,
594 struct compat_ipmi_req_settime __user *p32)
595{
596 if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
597 get_compat_ipmi_req(&p64->req, &p32->req) ||
598 __get_user(p64->retries, &p32->retries) ||
599 __get_user(p64->retry_time_ms, &p32->retry_time_ms))
600 return -EFAULT;
601 return 0;
602}
603
604static long get_compat_ipmi_recv(struct ipmi_recv *p64,
605 struct compat_ipmi_recv __user *p32)
606{
607 compat_uptr_t tmp;
608
609 if (!access_ok(VERIFY_READ, p32, sizeof(*p32)) ||
610 __get_user(p64->recv_type, &p32->recv_type) ||
611 __get_user(tmp, &p32->addr) ||
612 __get_user(p64->addr_len, &p32->addr_len) ||
613 __get_user(p64->msgid, &p32->msgid) ||
614 get_compat_ipmi_msg(&p64->msg, &p32->msg))
615 return -EFAULT;
616 p64->addr = compat_ptr(tmp);
617 return 0;
618}
619
620static long put_compat_ipmi_recv(struct ipmi_recv *p64,
621 struct compat_ipmi_recv __user *p32)
622{
623 if (!access_ok(VERIFY_WRITE, p32, sizeof(*p32)) ||
624 __put_user(p64->recv_type, &p32->recv_type) ||
625 __put_user(p64->addr_len, &p32->addr_len) ||
626 __put_user(p64->msgid, &p32->msgid) ||
627 put_compat_ipmi_msg(&p64->msg, &p32->msg))
628 return -EFAULT;
629 return 0;
630}
631
632/*
633 * Handle compatibility ioctls
634 */
635static long compat_ipmi_ioctl(struct file *filep, unsigned int cmd,
636 unsigned long arg)
637{
638 int rc;
639 struct ipmi_file_private *priv = filep->private_data;
640
641 switch(cmd) {
642 case COMPAT_IPMICTL_SEND_COMMAND:
643 {
644 struct ipmi_req rp;
645
646 if (get_compat_ipmi_req(&rp, compat_ptr(arg)))
647 return -EFAULT;
648
649 return handle_send_req(priv->user, &rp,
650 priv->default_retries,
651 priv->default_retry_time_ms);
652 }
653 case COMPAT_IPMICTL_SEND_COMMAND_SETTIME:
654 {
655 struct ipmi_req_settime sp;
656
657 if (get_compat_ipmi_req_settime(&sp, compat_ptr(arg)))
658 return -EFAULT;
659
660 return handle_send_req(priv->user, &sp.req,
661 sp.retries, sp.retry_time_ms);
662 }
663 case COMPAT_IPMICTL_RECEIVE_MSG:
664 case COMPAT_IPMICTL_RECEIVE_MSG_TRUNC:
665 {
666 struct ipmi_recv *precv64, recv64;
667
668 if (get_compat_ipmi_recv(&recv64, compat_ptr(arg)))
669 return -EFAULT;
670
671 precv64 = compat_alloc_user_space(sizeof(recv64));
672 if (copy_to_user(precv64, &recv64, sizeof(recv64)))
673 return -EFAULT;
674
675 rc = ipmi_ioctl(filep->f_dentry->d_inode, filep,
676 ((cmd == COMPAT_IPMICTL_RECEIVE_MSG)
677 ? IPMICTL_RECEIVE_MSG
678 : IPMICTL_RECEIVE_MSG_TRUNC),
679 (long) precv64);
680 if (rc != 0)
681 return rc;
682
683 if (copy_from_user(&recv64, precv64, sizeof(recv64)))
684 return -EFAULT;
685
686 if (put_compat_ipmi_recv(&recv64, compat_ptr(arg)))
687 return -EFAULT;
688
689 return rc;
690 }
691 default:
692 return ipmi_ioctl(filep->f_dentry->d_inode, filep, cmd, arg);
693 }
694}
695#endif
503 696
504static struct file_operations ipmi_fops = { 697static struct file_operations ipmi_fops = {
505 .owner = THIS_MODULE, 698 .owner = THIS_MODULE,
506 .ioctl = ipmi_ioctl, 699 .ioctl = ipmi_ioctl,
700#ifdef CONFIG_COMPAT
701 .compat_ioctl = compat_ipmi_ioctl,
702#endif
507 .open = ipmi_open, 703 .open = ipmi_open,
508 .release = ipmi_release, 704 .release = ipmi_release,
509 .fasync = ipmi_fasync, 705 .fasync = ipmi_fasync,
@@ -520,7 +716,7 @@ MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device. By"
520 " interface. Other values will set the major device number" 716 " interface. Other values will set the major device number"
521 " to that value."); 717 " to that value.");
522 718
523static struct class_simple *ipmi_class; 719static struct class *ipmi_class;
524 720
525static void ipmi_new_smi(int if_num) 721static void ipmi_new_smi(int if_num)
526{ 722{
@@ -529,12 +725,12 @@ static void ipmi_new_smi(int if_num)
529 devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR, 725 devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR,
530 "ipmidev/%d", if_num); 726 "ipmidev/%d", if_num);
531 727
532 class_simple_device_add(ipmi_class, dev, NULL, "ipmi%d", if_num); 728 class_device_create(ipmi_class, dev, NULL, "ipmi%d", if_num);
533} 729}
534 730
535static void ipmi_smi_gone(int if_num) 731static void ipmi_smi_gone(int if_num)
536{ 732{
537 class_simple_device_remove(MKDEV(ipmi_major, if_num)); 733 class_device_destroy(ipmi_class, MKDEV(ipmi_major, if_num));
538 devfs_remove("ipmidev/%d", if_num); 734 devfs_remove("ipmidev/%d", if_num);
539} 735}
540 736
@@ -555,7 +751,7 @@ static __init int init_ipmi_devintf(void)
555 printk(KERN_INFO "ipmi device interface version " 751 printk(KERN_INFO "ipmi device interface version "
556 IPMI_DEVINTF_VERSION "\n"); 752 IPMI_DEVINTF_VERSION "\n");
557 753
558 ipmi_class = class_simple_create(THIS_MODULE, "ipmi"); 754 ipmi_class = class_create(THIS_MODULE, "ipmi");
559 if (IS_ERR(ipmi_class)) { 755 if (IS_ERR(ipmi_class)) {
560 printk(KERN_ERR "ipmi: can't register device class\n"); 756 printk(KERN_ERR "ipmi: can't register device class\n");
561 return PTR_ERR(ipmi_class); 757 return PTR_ERR(ipmi_class);
@@ -563,7 +759,7 @@ static __init int init_ipmi_devintf(void)
563 759
564 rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops); 760 rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops);
565 if (rv < 0) { 761 if (rv < 0) {
566 class_simple_destroy(ipmi_class); 762 class_destroy(ipmi_class);
567 printk(KERN_ERR "ipmi: can't get major %d\n", ipmi_major); 763 printk(KERN_ERR "ipmi: can't get major %d\n", ipmi_major);
568 return rv; 764 return rv;
569 } 765 }
@@ -577,7 +773,7 @@ static __init int init_ipmi_devintf(void)
577 rv = ipmi_smi_watcher_register(&smi_watcher); 773 rv = ipmi_smi_watcher_register(&smi_watcher);
578 if (rv) { 774 if (rv) {
579 unregister_chrdev(ipmi_major, DEVICE_NAME); 775 unregister_chrdev(ipmi_major, DEVICE_NAME);
580 class_simple_destroy(ipmi_class); 776 class_destroy(ipmi_class);
581 printk(KERN_WARNING "ipmi: can't register smi watcher\n"); 777 printk(KERN_WARNING "ipmi: can't register smi watcher\n");
582 return rv; 778 return rv;
583 } 779 }
@@ -588,7 +784,7 @@ module_init(init_ipmi_devintf);
588 784
589static __exit void cleanup_ipmi(void) 785static __exit void cleanup_ipmi(void)
590{ 786{
591 class_simple_destroy(ipmi_class); 787 class_destroy(ipmi_class);
592 ipmi_smi_watcher_unregister(&smi_watcher); 788 ipmi_smi_watcher_unregister(&smi_watcher);
593 devfs_remove(DEVICE_NAME); 789 devfs_remove(DEVICE_NAME);
594 unregister_chrdev(ipmi_major, DEVICE_NAME); 790 unregister_chrdev(ipmi_major, DEVICE_NAME);
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index d7fb452af7f9..e16c13fe698d 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -54,7 +54,9 @@ static int ipmi_init_msghandler(void);
54 54
55static int initialized = 0; 55static int initialized = 0;
56 56
57static struct proc_dir_entry *proc_ipmi_root = NULL; 57#ifdef CONFIG_PROC_FS
58struct proc_dir_entry *proc_ipmi_root = NULL;
59#endif /* CONFIG_PROC_FS */
58 60
59#define MAX_EVENTS_IN_QUEUE 25 61#define MAX_EVENTS_IN_QUEUE 25
60 62
@@ -124,11 +126,13 @@ struct ipmi_channel
124 unsigned char protocol; 126 unsigned char protocol;
125}; 127};
126 128
129#ifdef CONFIG_PROC_FS
127struct ipmi_proc_entry 130struct ipmi_proc_entry
128{ 131{
129 char *name; 132 char *name;
130 struct ipmi_proc_entry *next; 133 struct ipmi_proc_entry *next;
131}; 134};
135#endif
132 136
133#define IPMI_IPMB_NUM_SEQ 64 137#define IPMI_IPMB_NUM_SEQ 64
134#define IPMI_MAX_CHANNELS 8 138#define IPMI_MAX_CHANNELS 8
@@ -156,10 +160,13 @@ struct ipmi_smi
156 struct ipmi_smi_handlers *handlers; 160 struct ipmi_smi_handlers *handlers;
157 void *send_info; 161 void *send_info;
158 162
163#ifdef CONFIG_PROC_FS
159 /* A list of proc entries for this interface. This does not 164 /* A list of proc entries for this interface. This does not
160 need a lock, only one thread creates it and only one thread 165 need a lock, only one thread creates it and only one thread
161 destroys it. */ 166 destroys it. */
167 spinlock_t proc_entry_lock;
162 struct ipmi_proc_entry *proc_entries; 168 struct ipmi_proc_entry *proc_entries;
169#endif
163 170
164 /* A table of sequence numbers for this interface. We use the 171 /* A table of sequence numbers for this interface. We use the
165 sequence numbers for IPMB messages that go out of the 172 sequence numbers for IPMB messages that go out of the
@@ -641,7 +648,7 @@ int ipmi_create_user(unsigned int if_num,
641 return -ENOMEM; 648 return -ENOMEM;
642 649
643 down_read(&interfaces_sem); 650 down_read(&interfaces_sem);
644 if ((if_num > MAX_IPMI_INTERFACES) || ipmi_interfaces[if_num] == NULL) 651 if ((if_num >= MAX_IPMI_INTERFACES) || ipmi_interfaces[if_num] == NULL)
645 { 652 {
646 rv = -EINVAL; 653 rv = -EINVAL;
647 goto out_unlock; 654 goto out_unlock;
@@ -1081,8 +1088,8 @@ static inline int i_ipmi_request(ipmi_user_t user,
1081 long seqid; 1088 long seqid;
1082 int broadcast = 0; 1089 int broadcast = 0;
1083 1090
1084 if (addr->channel > IPMI_NUM_CHANNELS) { 1091 if (addr->channel >= IPMI_MAX_CHANNELS) {
1085 spin_lock_irqsave(&intf->counter_lock, flags); 1092 spin_lock_irqsave(&intf->counter_lock, flags);
1086 intf->sent_invalid_commands++; 1093 intf->sent_invalid_commands++;
1087 spin_unlock_irqrestore(&intf->counter_lock, flags); 1094 spin_unlock_irqrestore(&intf->counter_lock, flags);
1088 rv = -EINVAL; 1095 rv = -EINVAL;
@@ -1470,8 +1477,9 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
1470 read_proc_t *read_proc, write_proc_t *write_proc, 1477 read_proc_t *read_proc, write_proc_t *write_proc,
1471 void *data, struct module *owner) 1478 void *data, struct module *owner)
1472{ 1479{
1473 struct proc_dir_entry *file;
1474 int rv = 0; 1480 int rv = 0;
1481#ifdef CONFIG_PROC_FS
1482 struct proc_dir_entry *file;
1475 struct ipmi_proc_entry *entry; 1483 struct ipmi_proc_entry *entry;
1476 1484
1477 /* Create a list element. */ 1485 /* Create a list element. */
@@ -1497,10 +1505,13 @@ int ipmi_smi_add_proc_entry(ipmi_smi_t smi, char *name,
1497 file->write_proc = write_proc; 1505 file->write_proc = write_proc;
1498 file->owner = owner; 1506 file->owner = owner;
1499 1507
1508 spin_lock(&smi->proc_entry_lock);
1500 /* Stick it on the list. */ 1509 /* Stick it on the list. */
1501 entry->next = smi->proc_entries; 1510 entry->next = smi->proc_entries;
1502 smi->proc_entries = entry; 1511 smi->proc_entries = entry;
1512 spin_unlock(&smi->proc_entry_lock);
1503 } 1513 }
1514#endif /* CONFIG_PROC_FS */
1504 1515
1505 return rv; 1516 return rv;
1506} 1517}
@@ -1509,6 +1520,7 @@ static int add_proc_entries(ipmi_smi_t smi, int num)
1509{ 1520{
1510 int rv = 0; 1521 int rv = 0;
1511 1522
1523#ifdef CONFIG_PROC_FS
1512 sprintf(smi->proc_dir_name, "%d", num); 1524 sprintf(smi->proc_dir_name, "%d", num);
1513 smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root); 1525 smi->proc_dir = proc_mkdir(smi->proc_dir_name, proc_ipmi_root);
1514 if (!smi->proc_dir) 1526 if (!smi->proc_dir)
@@ -1531,14 +1543,17 @@ static int add_proc_entries(ipmi_smi_t smi, int num)
1531 rv = ipmi_smi_add_proc_entry(smi, "version", 1543 rv = ipmi_smi_add_proc_entry(smi, "version",
1532 version_file_read_proc, NULL, 1544 version_file_read_proc, NULL,
1533 smi, THIS_MODULE); 1545 smi, THIS_MODULE);
1546#endif /* CONFIG_PROC_FS */
1534 1547
1535 return rv; 1548 return rv;
1536} 1549}
1537 1550
1538static void remove_proc_entries(ipmi_smi_t smi) 1551static void remove_proc_entries(ipmi_smi_t smi)
1539{ 1552{
1553#ifdef CONFIG_PROC_FS
1540 struct ipmi_proc_entry *entry; 1554 struct ipmi_proc_entry *entry;
1541 1555
1556 spin_lock(&smi->proc_entry_lock);
1542 while (smi->proc_entries) { 1557 while (smi->proc_entries) {
1543 entry = smi->proc_entries; 1558 entry = smi->proc_entries;
1544 smi->proc_entries = entry->next; 1559 smi->proc_entries = entry->next;
@@ -1547,7 +1562,9 @@ static void remove_proc_entries(ipmi_smi_t smi)
1547 kfree(entry->name); 1562 kfree(entry->name);
1548 kfree(entry); 1563 kfree(entry);
1549 } 1564 }
1565 spin_unlock(&smi->proc_entry_lock);
1550 remove_proc_entry(smi->proc_dir_name, proc_ipmi_root); 1566 remove_proc_entry(smi->proc_dir_name, proc_ipmi_root);
1567#endif /* CONFIG_PROC_FS */
1551} 1568}
1552 1569
1553static int 1570static int
@@ -1694,6 +1711,9 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers,
1694 new_intf->seq_table[j].seqid = 0; 1711 new_intf->seq_table[j].seqid = 0;
1695 } 1712 }
1696 new_intf->curr_seq = 0; 1713 new_intf->curr_seq = 0;
1714#ifdef CONFIG_PROC_FS
1715 spin_lock_init(&(new_intf->proc_entry_lock));
1716#endif
1697 spin_lock_init(&(new_intf->waiting_msgs_lock)); 1717 spin_lock_init(&(new_intf->waiting_msgs_lock));
1698 INIT_LIST_HEAD(&(new_intf->waiting_msgs)); 1718 INIT_LIST_HEAD(&(new_intf->waiting_msgs));
1699 spin_lock_init(&(new_intf->events_lock)); 1719 spin_lock_init(&(new_intf->events_lock));
@@ -2747,16 +2767,13 @@ static struct timer_list ipmi_timer;
2747 the queue and this silliness can go away. */ 2767 the queue and this silliness can go away. */
2748#define IPMI_REQUEST_EV_TIME (1000 / (IPMI_TIMEOUT_TIME)) 2768#define IPMI_REQUEST_EV_TIME (1000 / (IPMI_TIMEOUT_TIME))
2749 2769
2750static volatile int stop_operation = 0; 2770static atomic_t stop_operation;
2751static volatile int timer_stopped = 0;
2752static unsigned int ticks_to_req_ev = IPMI_REQUEST_EV_TIME; 2771static unsigned int ticks_to_req_ev = IPMI_REQUEST_EV_TIME;
2753 2772
2754static void ipmi_timeout(unsigned long data) 2773static void ipmi_timeout(unsigned long data)
2755{ 2774{
2756 if (stop_operation) { 2775 if (atomic_read(&stop_operation))
2757 timer_stopped = 1;
2758 return; 2776 return;
2759 }
2760 2777
2761 ticks_to_req_ev--; 2778 ticks_to_req_ev--;
2762 if (ticks_to_req_ev == 0) { 2779 if (ticks_to_req_ev == 0) {
@@ -2766,8 +2783,7 @@ static void ipmi_timeout(unsigned long data)
2766 2783
2767 ipmi_timeout_handler(IPMI_TIMEOUT_TIME); 2784 ipmi_timeout_handler(IPMI_TIMEOUT_TIME);
2768 2785
2769 ipmi_timer.expires += IPMI_TIMEOUT_JIFFIES; 2786 mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES);
2770 add_timer(&ipmi_timer);
2771} 2787}
2772 2788
2773 2789
@@ -3089,6 +3105,7 @@ static int ipmi_init_msghandler(void)
3089 ipmi_interfaces[i] = NULL; 3105 ipmi_interfaces[i] = NULL;
3090 } 3106 }
3091 3107
3108#ifdef CONFIG_PROC_FS
3092 proc_ipmi_root = proc_mkdir("ipmi", NULL); 3109 proc_ipmi_root = proc_mkdir("ipmi", NULL);
3093 if (!proc_ipmi_root) { 3110 if (!proc_ipmi_root) {
3094 printk(KERN_ERR PFX "Unable to create IPMI proc dir"); 3111 printk(KERN_ERR PFX "Unable to create IPMI proc dir");
@@ -3096,6 +3113,7 @@ static int ipmi_init_msghandler(void)
3096 } 3113 }
3097 3114
3098 proc_ipmi_root->owner = THIS_MODULE; 3115 proc_ipmi_root->owner = THIS_MODULE;
3116#endif /* CONFIG_PROC_FS */
3099 3117
3100 init_timer(&ipmi_timer); 3118 init_timer(&ipmi_timer);
3101 ipmi_timer.data = 0; 3119 ipmi_timer.data = 0;
@@ -3130,13 +3148,12 @@ static __exit void cleanup_ipmi(void)
3130 3148
3131 /* Tell the timer to stop, then wait for it to stop. This avoids 3149 /* Tell the timer to stop, then wait for it to stop. This avoids
3132 problems with race conditions removing the timer here. */ 3150 problems with race conditions removing the timer here. */
3133 stop_operation = 1; 3151 atomic_inc(&stop_operation);
3134 while (!timer_stopped) { 3152 del_timer_sync(&ipmi_timer);
3135 set_current_state(TASK_UNINTERRUPTIBLE);
3136 schedule_timeout(1);
3137 }
3138 3153
3154#ifdef CONFIG_PROC_FS
3139 remove_proc_entry(proc_ipmi_root->name, &proc_root); 3155 remove_proc_entry(proc_ipmi_root->name, &proc_root);
3156#endif /* CONFIG_PROC_FS */
3140 3157
3141 initialized = 0; 3158 initialized = 0;
3142 3159
@@ -3177,4 +3194,5 @@ EXPORT_SYMBOL(ipmi_get_my_address);
3177EXPORT_SYMBOL(ipmi_set_my_LUN); 3194EXPORT_SYMBOL(ipmi_set_my_LUN);
3178EXPORT_SYMBOL(ipmi_get_my_LUN); 3195EXPORT_SYMBOL(ipmi_get_my_LUN);
3179EXPORT_SYMBOL(ipmi_smi_add_proc_entry); 3196EXPORT_SYMBOL(ipmi_smi_add_proc_entry);
3197EXPORT_SYMBOL(proc_ipmi_root);
3180EXPORT_SYMBOL(ipmi_user_set_run_to_completion); 3198EXPORT_SYMBOL(ipmi_user_set_run_to_completion);
diff --git a/drivers/char/ipmi/ipmi_poweroff.c b/drivers/char/ipmi/ipmi_poweroff.c
index cb5cdc6f14bf..f951c30236c9 100644
--- a/drivers/char/ipmi/ipmi_poweroff.c
+++ b/drivers/char/ipmi/ipmi_poweroff.c
@@ -31,10 +31,13 @@
31 * with this program; if not, write to the Free Software Foundation, Inc., 31 * with this program; if not, write to the Free Software Foundation, Inc.,
32 * 675 Mass Ave, Cambridge, MA 02139, USA. 32 * 675 Mass Ave, Cambridge, MA 02139, USA.
33 */ 33 */
34#include <asm/semaphore.h> 34#include <linux/config.h>
35#include <linux/kdev_t.h>
36#include <linux/module.h> 35#include <linux/module.h>
36#include <linux/moduleparam.h>
37#include <linux/proc_fs.h>
37#include <linux/string.h> 38#include <linux/string.h>
39#include <linux/completion.h>
40#include <linux/kdev_t.h>
38#include <linux/ipmi.h> 41#include <linux/ipmi.h>
39#include <linux/ipmi_smi.h> 42#include <linux/ipmi_smi.h>
40 43
@@ -44,6 +47,18 @@
44/* Where to we insert our poweroff function? */ 47/* Where to we insert our poweroff function? */
45extern void (*pm_power_off)(void); 48extern void (*pm_power_off)(void);
46 49
50/* Definitions for controlling power off (if the system supports it). It
51 * conveniently matches the IPMI chassis control values. */
52#define IPMI_CHASSIS_POWER_DOWN 0 /* power down, the default. */
53#define IPMI_CHASSIS_POWER_CYCLE 0x02 /* power cycle */
54
55/* the IPMI data command */
56static int poweroff_control = IPMI_CHASSIS_POWER_DOWN;
57
58/* parameter definition to allow user to flag power cycle */
59module_param(poweroff_control, int, IPMI_CHASSIS_POWER_DOWN);
60MODULE_PARM_DESC(poweroff_control, " Set to 2 to enable power cycle instead of power down. Power cycle is contingent on hardware support, otherwise it defaults back to power down.");
61
47/* Stuff from the get device id command. */ 62/* Stuff from the get device id command. */
48static unsigned int mfg_id; 63static unsigned int mfg_id;
49static unsigned int prod_id; 64static unsigned int prod_id;
@@ -75,10 +90,10 @@ static struct ipmi_recv_msg halt_recv_msg =
75 90
76static void receive_handler(struct ipmi_recv_msg *recv_msg, void *handler_data) 91static void receive_handler(struct ipmi_recv_msg *recv_msg, void *handler_data)
77{ 92{
78 struct semaphore *sem = recv_msg->user_msg_data; 93 struct completion *comp = recv_msg->user_msg_data;
79 94
80 if (sem) 95 if (comp)
81 up(sem); 96 complete(comp);
82} 97}
83 98
84static struct ipmi_user_hndl ipmi_poweroff_handler = 99static struct ipmi_user_hndl ipmi_poweroff_handler =
@@ -91,27 +106,27 @@ static int ipmi_request_wait_for_response(ipmi_user_t user,
91 struct ipmi_addr *addr, 106 struct ipmi_addr *addr,
92 struct kernel_ipmi_msg *send_msg) 107 struct kernel_ipmi_msg *send_msg)
93{ 108{
94 int rv; 109 int rv;
95 struct semaphore sem; 110 struct completion comp;
96 111
97 sema_init (&sem, 0); 112 init_completion(&comp);
98 113
99 rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, &sem, 114 rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, &comp,
100 &halt_smi_msg, &halt_recv_msg, 0); 115 &halt_smi_msg, &halt_recv_msg, 0);
101 if (rv) 116 if (rv)
102 return rv; 117 return rv;
103 118
104 down (&sem); 119 wait_for_completion(&comp);
105 120
106 return halt_recv_msg.msg.data[0]; 121 return halt_recv_msg.msg.data[0];
107} 122}
108 123
109/* We are in run-to-completion mode, no semaphore is desired. */ 124/* We are in run-to-completion mode, no completion is desired. */
110static int ipmi_request_in_rc_mode(ipmi_user_t user, 125static int ipmi_request_in_rc_mode(ipmi_user_t user,
111 struct ipmi_addr *addr, 126 struct ipmi_addr *addr,
112 struct kernel_ipmi_msg *send_msg) 127 struct kernel_ipmi_msg *send_msg)
113{ 128{
114 int rv; 129 int rv;
115 130
116 rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, NULL, 131 rv = ipmi_request_supply_msgs(user, addr, 0, send_msg, NULL,
117 &halt_smi_msg, &halt_recv_msg, 0); 132 &halt_smi_msg, &halt_recv_msg, 0);
@@ -349,26 +364,38 @@ static void ipmi_poweroff_chassis (ipmi_user_t user)
349 smi_addr.channel = IPMI_BMC_CHANNEL; 364 smi_addr.channel = IPMI_BMC_CHANNEL;
350 smi_addr.lun = 0; 365 smi_addr.lun = 0;
351 366
352 printk(KERN_INFO PFX "Powering down via IPMI chassis control command\n"); 367 powercyclefailed:
368 printk(KERN_INFO PFX "Powering %s via IPMI chassis control command\n",
369 ((poweroff_control != IPMI_CHASSIS_POWER_CYCLE) ? "down" : "cycle"));
353 370
354 /* 371 /*
355 * Power down 372 * Power down
356 */ 373 */
357 send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST; 374 send_msg.netfn = IPMI_NETFN_CHASSIS_REQUEST;
358 send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD; 375 send_msg.cmd = IPMI_CHASSIS_CONTROL_CMD;
359 data[0] = 0; /* Power down */ 376 data[0] = poweroff_control;
360 send_msg.data = data; 377 send_msg.data = data;
361 send_msg.data_len = sizeof(data); 378 send_msg.data_len = sizeof(data);
362 rv = ipmi_request_in_rc_mode(user, 379 rv = ipmi_request_in_rc_mode(user,
363 (struct ipmi_addr *) &smi_addr, 380 (struct ipmi_addr *) &smi_addr,
364 &send_msg); 381 &send_msg);
365 if (rv) { 382 if (rv) {
366 printk(KERN_ERR PFX "Unable to send chassis powerdown message," 383 switch (poweroff_control) {
367 " IPMI error 0x%x\n", rv); 384 case IPMI_CHASSIS_POWER_CYCLE:
368 goto out; 385 /* power cycle failed, default to power down */
386 printk(KERN_ERR PFX "Unable to send chassis power " \
387 "cycle message, IPMI error 0x%x\n", rv);
388 poweroff_control = IPMI_CHASSIS_POWER_DOWN;
389 goto powercyclefailed;
390
391 case IPMI_CHASSIS_POWER_DOWN:
392 default:
393 printk(KERN_ERR PFX "Unable to send chassis power " \
394 "down message, IPMI error 0x%x\n", rv);
395 break;
396 }
369 } 397 }
370 398
371 out:
372 return; 399 return;
373} 400}
374 401
@@ -430,7 +457,8 @@ static void ipmi_po_new_smi(int if_num)
430 if (ready) 457 if (ready)
431 return; 458 return;
432 459
433 rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL, &ipmi_user); 460 rv = ipmi_create_user(if_num, &ipmi_poweroff_handler, NULL,
461 &ipmi_user);
434 if (rv) { 462 if (rv) {
435 printk(KERN_ERR PFX "could not create IPMI user, error %d\n", 463 printk(KERN_ERR PFX "could not create IPMI user, error %d\n",
436 rv); 464 rv);
@@ -509,21 +537,84 @@ static struct ipmi_smi_watcher smi_watcher =
509}; 537};
510 538
511 539
540#ifdef CONFIG_PROC_FS
541/* displays properties to proc */
542static int proc_read_chassctrl(char *page, char **start, off_t off, int count,
543 int *eof, void *data)
544{
545 return sprintf(page, "%d\t[ 0=powerdown 2=powercycle ]\n",
546 poweroff_control);
547}
548
549/* process property writes from proc */
550static int proc_write_chassctrl(struct file *file, const char *buffer,
551 unsigned long count, void *data)
552{
553 int rv = count;
554 unsigned int newval = 0;
555
556 sscanf(buffer, "%d", &newval);
557 switch (newval) {
558 case IPMI_CHASSIS_POWER_CYCLE:
559 printk(KERN_INFO PFX "power cycle is now enabled\n");
560 poweroff_control = newval;
561 break;
562
563 case IPMI_CHASSIS_POWER_DOWN:
564 poweroff_control = IPMI_CHASSIS_POWER_DOWN;
565 break;
566
567 default:
568 rv = -EINVAL;
569 break;
570 }
571
572 return rv;
573}
574#endif /* CONFIG_PROC_FS */
575
512/* 576/*
513 * Startup and shutdown functions. 577 * Startup and shutdown functions.
514 */ 578 */
515static int ipmi_poweroff_init (void) 579static int ipmi_poweroff_init (void)
516{ 580{
517 int rv; 581 int rv;
582 struct proc_dir_entry *file;
518 583
519 printk ("Copyright (C) 2004 MontaVista Software -" 584 printk ("Copyright (C) 2004 MontaVista Software -"
520 " IPMI Powerdown via sys_reboot version " 585 " IPMI Powerdown via sys_reboot version "
521 IPMI_POWEROFF_VERSION ".\n"); 586 IPMI_POWEROFF_VERSION ".\n");
522 587
588 switch (poweroff_control) {
589 case IPMI_CHASSIS_POWER_CYCLE:
590 printk(KERN_INFO PFX "Power cycle is enabled.\n");
591 break;
592
593 case IPMI_CHASSIS_POWER_DOWN:
594 default:
595 poweroff_control = IPMI_CHASSIS_POWER_DOWN;
596 break;
597 }
598
523 rv = ipmi_smi_watcher_register(&smi_watcher); 599 rv = ipmi_smi_watcher_register(&smi_watcher);
524 if (rv) 600 if (rv) {
525 printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv); 601 printk(KERN_ERR PFX "Unable to register SMI watcher: %d\n", rv);
602 goto out_err;
603 }
604
605#ifdef CONFIG_PROC_FS
606 file = create_proc_entry("poweroff_control", 0, proc_ipmi_root);
607 if (!file) {
608 printk(KERN_ERR PFX "Unable to create proc power control\n");
609 } else {
610 file->nlink = 1;
611 file->read_proc = proc_read_chassctrl;
612 file->write_proc = proc_write_chassctrl;
613 file->owner = THIS_MODULE;
614 }
615#endif
526 616
617 out_err:
527 return rv; 618 return rv;
528} 619}
529 620
@@ -532,6 +623,10 @@ static __exit void ipmi_poweroff_cleanup(void)
532{ 623{
533 int rv; 624 int rv;
534 625
626#ifdef CONFIG_PROC_FS
627 remove_proc_entry("poweroff_control", proc_ipmi_root);
628#endif
629
535 ipmi_smi_watcher_unregister(&smi_watcher); 630 ipmi_smi_watcher_unregister(&smi_watcher);
536 631
537 if (ready) { 632 if (ready) {
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c
index 298574e16061..a44b97304e95 100644
--- a/drivers/char/ipmi/ipmi_si_intf.c
+++ b/drivers/char/ipmi/ipmi_si_intf.c
@@ -1726,7 +1726,7 @@ static int dmi_table(u32 base, int len, int num)
1726 return status; 1726 return status;
1727} 1727}
1728 1728
1729inline static int dmi_checksum(u8 *buf) 1729static inline int dmi_checksum(u8 *buf)
1730{ 1730{
1731 u8 sum=0; 1731 u8 sum=0;
1732 int a; 1732 int a;
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c
index fcd1c02a32cb..d35a953961cb 100644
--- a/drivers/char/ipmi/ipmi_watchdog.c
+++ b/drivers/char/ipmi/ipmi_watchdog.c
@@ -131,11 +131,7 @@
131#define WDIOC_GET_PRETIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 22, int) 131#define WDIOC_GET_PRETIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 22, int)
132#endif 132#endif
133 133
134#ifdef CONFIG_WATCHDOG_NOWAYOUT 134static int nowayout = WATCHDOG_NOWAYOUT;
135static int nowayout = 1;
136#else
137static int nowayout;
138#endif
139 135
140static ipmi_user_t watchdog_user = NULL; 136static ipmi_user_t watchdog_user = NULL;
141 137
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c
index 601c7fccb4cf..1bbf507adda5 100644
--- a/drivers/char/isicom.c
+++ b/drivers/char/isicom.c
@@ -1756,7 +1756,7 @@ static void isicom_flush_buffer(struct tty_struct * tty)
1756} 1756}
1757 1757
1758 1758
1759static int __init register_ioregion(void) 1759static int __devinit register_ioregion(void)
1760{ 1760{
1761 int count, done=0; 1761 int count, done=0;
1762 for (count=0; count < BOARD_COUNT; count++ ) { 1762 for (count=0; count < BOARD_COUNT; count++ ) {
@@ -1771,7 +1771,7 @@ static int __init register_ioregion(void)
1771 return done; 1771 return done;
1772} 1772}
1773 1773
1774static void __exit unregister_ioregion(void) 1774static void unregister_ioregion(void)
1775{ 1775{
1776 int count; 1776 int count;
1777 for (count=0; count < BOARD_COUNT; count++ ) 1777 for (count=0; count < BOARD_COUNT; count++ )
@@ -1803,7 +1803,7 @@ static struct tty_operations isicom_ops = {
1803 .tiocmset = isicom_tiocmset, 1803 .tiocmset = isicom_tiocmset,
1804}; 1804};
1805 1805
1806static int __init register_drivers(void) 1806static int __devinit register_drivers(void)
1807{ 1807{
1808 int error; 1808 int error;
1809 1809
@@ -1834,7 +1834,7 @@ static int __init register_drivers(void)
1834 return 0; 1834 return 0;
1835} 1835}
1836 1836
1837static void __exit unregister_drivers(void) 1837static void unregister_drivers(void)
1838{ 1838{
1839 int error = tty_unregister_driver(isicom_normal); 1839 int error = tty_unregister_driver(isicom_normal);
1840 if (error) 1840 if (error)
@@ -1842,7 +1842,7 @@ static void __exit unregister_drivers(void)
1842 put_tty_driver(isicom_normal); 1842 put_tty_driver(isicom_normal);
1843} 1843}
1844 1844
1845static int __init register_isr(void) 1845static int __devinit register_isr(void)
1846{ 1846{
1847 int count, done=0; 1847 int count, done=0;
1848 unsigned long irqflags; 1848 unsigned long irqflags;
@@ -1883,7 +1883,7 @@ static void __exit unregister_isr(void)
1883 } 1883 }
1884} 1884}
1885 1885
1886static int __init isicom_init(void) 1886static int __devinit isicom_init(void)
1887{ 1887{
1888 int card, channel, base; 1888 int card, channel, base;
1889 struct isi_port * port; 1889 struct isi_port * port;
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 21aed0e8779d..52a073eee201 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -407,7 +407,6 @@ static unsigned long stli_eisamemprobeaddrs[] = {
407}; 407};
408 408
409static int stli_eisamempsize = sizeof(stli_eisamemprobeaddrs) / sizeof(unsigned long); 409static int stli_eisamempsize = sizeof(stli_eisamemprobeaddrs) / sizeof(unsigned long);
410int stli_eisaprobe = STLI_EISAPROBE;
411 410
412/* 411/*
413 * Define the Stallion PCI vendor and device IDs. 412 * Define the Stallion PCI vendor and device IDs.
@@ -792,7 +791,7 @@ static int stli_timeron;
792 791
793/*****************************************************************************/ 792/*****************************************************************************/
794 793
795static struct class_simple *istallion_class; 794static struct class *istallion_class;
796 795
797#ifdef MODULE 796#ifdef MODULE
798 797
@@ -854,10 +853,10 @@ static void __exit istallion_module_exit(void)
854 put_tty_driver(stli_serial); 853 put_tty_driver(stli_serial);
855 for (i = 0; i < 4; i++) { 854 for (i = 0; i < 4; i++) {
856 devfs_remove("staliomem/%d", i); 855 devfs_remove("staliomem/%d", i);
857 class_simple_device_remove(MKDEV(STL_SIOMEMMAJOR, i)); 856 class_device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, i));
858 } 857 }
859 devfs_remove("staliomem"); 858 devfs_remove("staliomem");
860 class_simple_destroy(istallion_class); 859 class_destroy(istallion_class);
861 if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"))) 860 if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
862 printk("STALLION: failed to un-register serial memory device, " 861 printk("STALLION: failed to un-register serial memory device, "
863 "errno=%d\n", -i); 862 "errno=%d\n", -i);
@@ -4685,7 +4684,7 @@ static int stli_initbrds(void)
4685#ifdef MODULE 4684#ifdef MODULE
4686 stli_argbrds(); 4685 stli_argbrds();
4687#endif 4686#endif
4688 if (stli_eisaprobe) 4687 if (STLI_EISAPROBE)
4689 stli_findeisabrds(); 4688 stli_findeisabrds();
4690#ifdef CONFIG_PCI 4689#ifdef CONFIG_PCI
4691 stli_findpcibrds(); 4690 stli_findpcibrds();
@@ -5242,12 +5241,12 @@ int __init stli_init(void)
5242 "device\n"); 5241 "device\n");
5243 5242
5244 devfs_mk_dir("staliomem"); 5243 devfs_mk_dir("staliomem");
5245 istallion_class = class_simple_create(THIS_MODULE, "staliomem"); 5244 istallion_class = class_create(THIS_MODULE, "staliomem");
5246 for (i = 0; i < 4; i++) { 5245 for (i = 0; i < 4; i++) {
5247 devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i), 5246 devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
5248 S_IFCHR | S_IRUSR | S_IWUSR, 5247 S_IFCHR | S_IRUSR | S_IWUSR,
5249 "staliomem/%d", i); 5248 "staliomem/%d", i);
5250 class_simple_device_add(istallion_class, MKDEV(STL_SIOMEMMAJOR, i), 5249 class_device_create(istallion_class, MKDEV(STL_SIOMEMMAJOR, i),
5251 NULL, "staliomem%d", i); 5250 NULL, "staliomem%d", i);
5252 } 5251 }
5253 5252
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index 7b19e02f112f..523fd3c8bbaa 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -198,10 +198,10 @@ int setkeycode(unsigned int scancode, unsigned int keycode)
198 198
199 if (scancode >= dev->keycodemax) 199 if (scancode >= dev->keycodemax)
200 return -EINVAL; 200 return -EINVAL;
201 if (keycode > KEY_MAX)
202 return -EINVAL;
203 if (keycode < 0 || keycode > KEY_MAX) 201 if (keycode < 0 || keycode > KEY_MAX)
204 return -EINVAL; 202 return -EINVAL;
203 if (keycode >> (dev->keycodesize * 8))
204 return -EINVAL;
205 205
206 oldkey = SET_INPUT_KEYCODE(dev, scancode, keycode); 206 oldkey = SET_INPUT_KEYCODE(dev, scancode, keycode);
207 207
diff --git a/drivers/char/lp.c b/drivers/char/lp.c
index 4dee945031d4..59eebe5a035f 100644
--- a/drivers/char/lp.c
+++ b/drivers/char/lp.c
@@ -146,7 +146,7 @@
146static struct lp_struct lp_table[LP_NO]; 146static struct lp_struct lp_table[LP_NO];
147 147
148static unsigned int lp_count = 0; 148static unsigned int lp_count = 0;
149static struct class_simple *lp_class; 149static struct class *lp_class;
150 150
151#ifdef CONFIG_LP_CONSOLE 151#ifdef CONFIG_LP_CONSOLE
152static struct parport *console_registered; // initially NULL 152static struct parport *console_registered; // initially NULL
@@ -804,7 +804,7 @@ static int lp_register(int nr, struct parport *port)
804 if (reset) 804 if (reset)
805 lp_reset(nr); 805 lp_reset(nr);
806 806
807 class_simple_device_add(lp_class, MKDEV(LP_MAJOR, nr), NULL, 807 class_device_create(lp_class, MKDEV(LP_MAJOR, nr), NULL,
808 "lp%d", nr); 808 "lp%d", nr);
809 devfs_mk_cdev(MKDEV(LP_MAJOR, nr), S_IFCHR | S_IRUGO | S_IWUGO, 809 devfs_mk_cdev(MKDEV(LP_MAJOR, nr), S_IFCHR | S_IRUGO | S_IWUGO,
810 "printers/%d", nr); 810 "printers/%d", nr);
@@ -907,7 +907,7 @@ static int __init lp_init (void)
907 } 907 }
908 908
909 devfs_mk_dir("printers"); 909 devfs_mk_dir("printers");
910 lp_class = class_simple_create(THIS_MODULE, "printer"); 910 lp_class = class_create(THIS_MODULE, "printer");
911 if (IS_ERR(lp_class)) { 911 if (IS_ERR(lp_class)) {
912 err = PTR_ERR(lp_class); 912 err = PTR_ERR(lp_class);
913 goto out_devfs; 913 goto out_devfs;
@@ -930,7 +930,7 @@ static int __init lp_init (void)
930 return 0; 930 return 0;
931 931
932out_class: 932out_class:
933 class_simple_destroy(lp_class); 933 class_destroy(lp_class);
934out_devfs: 934out_devfs:
935 devfs_remove("printers"); 935 devfs_remove("printers");
936 unregister_chrdev(LP_MAJOR, "lp"); 936 unregister_chrdev(LP_MAJOR, "lp");
@@ -981,10 +981,10 @@ static void lp_cleanup_module (void)
981 continue; 981 continue;
982 parport_unregister_device(lp_table[offset].dev); 982 parport_unregister_device(lp_table[offset].dev);
983 devfs_remove("printers/%d", offset); 983 devfs_remove("printers/%d", offset);
984 class_simple_device_remove(MKDEV(LP_MAJOR, offset)); 984 class_device_destroy(lp_class, MKDEV(LP_MAJOR, offset));
985 } 985 }
986 devfs_remove("printers"); 986 devfs_remove("printers");
987 class_simple_destroy(lp_class); 987 class_destroy(lp_class);
988} 988}
989 989
990__setup("lp=", lp_setup); 990__setup("lp=", lp_setup);
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c
index ac9cfa9701ea..115dbb35334b 100644
--- a/drivers/char/mbcs.c
+++ b/drivers/char/mbcs.c
@@ -699,7 +699,7 @@ static inline int mbcs_hw_init(struct mbcs_soft *soft)
699 return 0; 699 return 0;
700} 700}
701 701
702static ssize_t show_algo(struct device *dev, char *buf) 702static ssize_t show_algo(struct device *dev, struct device_attribute *attr, char *buf)
703{ 703{
704 struct cx_dev *cx_dev = to_cx_dev(dev); 704 struct cx_dev *cx_dev = to_cx_dev(dev);
705 struct mbcs_soft *soft = cx_dev->soft; 705 struct mbcs_soft *soft = cx_dev->soft;
@@ -715,7 +715,7 @@ static ssize_t show_algo(struct device *dev, char *buf)
715 (debug0 >> 32), (debug0 & 0xffffffff)); 715 (debug0 >> 32), (debug0 & 0xffffffff));
716} 716}
717 717
718static ssize_t store_algo(struct device *dev, const char *buf, size_t count) 718static ssize_t store_algo(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
719{ 719{
720 int n; 720 int n;
721 struct cx_dev *cx_dev = to_cx_dev(dev); 721 struct cx_dev *cx_dev = to_cx_dev(dev);
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index 947cb3cef816..850a78c9c4bc 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -23,7 +23,10 @@
23#include <linux/devfs_fs_kernel.h> 23#include <linux/devfs_fs_kernel.h>
24#include <linux/ptrace.h> 24#include <linux/ptrace.h>
25#include <linux/device.h> 25#include <linux/device.h>
26#include <linux/highmem.h>
27#include <linux/crash_dump.h>
26#include <linux/backing-dev.h> 28#include <linux/backing-dev.h>
29#include <linux/bootmem.h>
27 30
28#include <asm/uaccess.h> 31#include <asm/uaccess.h>
29#include <asm/io.h> 32#include <asm/io.h>
@@ -258,7 +261,11 @@ static int mmap_mem(struct file * file, struct vm_area_struct * vma)
258 261
259static int mmap_kmem(struct file * file, struct vm_area_struct * vma) 262static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
260{ 263{
261 unsigned long long val; 264 unsigned long pfn;
265
266 /* Turn a kernel-virtual address into a physical page frame */
267 pfn = __pa((u64)vma->vm_pgoff << PAGE_SHIFT) >> PAGE_SHIFT;
268
262 /* 269 /*
263 * RED-PEN: on some architectures there is more mapped memory 270 * RED-PEN: on some architectures there is more mapped memory
264 * than available in mem_map which pfn_valid checks 271 * than available in mem_map which pfn_valid checks
@@ -266,13 +273,47 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma)
266 * 273 *
267 * RED-PEN: vmalloc is not supported right now. 274 * RED-PEN: vmalloc is not supported right now.
268 */ 275 */
269 if (!pfn_valid(vma->vm_pgoff)) 276 if (!pfn_valid(pfn))
270 return -EIO; 277 return -EIO;
271 val = (u64)vma->vm_pgoff << PAGE_SHIFT; 278
272 vma->vm_pgoff = __pa(val) >> PAGE_SHIFT; 279 vma->vm_pgoff = pfn;
273 return mmap_mem(file, vma); 280 return mmap_mem(file, vma);
274} 281}
275 282
283#ifdef CONFIG_CRASH_DUMP
284/*
285 * Read memory corresponding to the old kernel.
286 */
287static ssize_t read_oldmem(struct file *file, char __user *buf,
288 size_t count, loff_t *ppos)
289{
290 unsigned long pfn, offset;
291 size_t read = 0, csize;
292 int rc = 0;
293
294 while (count) {
295 pfn = *ppos / PAGE_SIZE;
296 if (pfn > saved_max_pfn)
297 return read;
298
299 offset = (unsigned long)(*ppos % PAGE_SIZE);
300 if (count > PAGE_SIZE - offset)
301 csize = PAGE_SIZE - offset;
302 else
303 csize = count;
304
305 rc = copy_oldmem_page(pfn, buf, csize, offset, 1);
306 if (rc < 0)
307 return rc;
308 buf += csize;
309 *ppos += csize;
310 read += csize;
311 count -= csize;
312 }
313 return read;
314}
315#endif
316
276extern long vread(char *buf, char *addr, unsigned long count); 317extern long vread(char *buf, char *addr, unsigned long count);
277extern long vwrite(char *buf, char *addr, unsigned long count); 318extern long vwrite(char *buf, char *addr, unsigned long count);
278 319
@@ -484,7 +525,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf,
484 return virtr + wrote; 525 return virtr + wrote;
485} 526}
486 527
487#if defined(CONFIG_ISA) || !defined(__mc68000__) 528#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
488static ssize_t read_port(struct file * file, char __user * buf, 529static ssize_t read_port(struct file * file, char __user * buf,
489 size_t count, loff_t *ppos) 530 size_t count, loff_t *ppos)
490{ 531{
@@ -721,6 +762,7 @@ static int open_port(struct inode * inode, struct file * filp)
721#define read_full read_zero 762#define read_full read_zero
722#define open_mem open_port 763#define open_mem open_port
723#define open_kmem open_mem 764#define open_kmem open_mem
765#define open_oldmem open_mem
724 766
725static struct file_operations mem_fops = { 767static struct file_operations mem_fops = {
726 .llseek = memory_lseek, 768 .llseek = memory_lseek,
@@ -744,7 +786,7 @@ static struct file_operations null_fops = {
744 .write = write_null, 786 .write = write_null,
745}; 787};
746 788
747#if defined(CONFIG_ISA) || !defined(__mc68000__) 789#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
748static struct file_operations port_fops = { 790static struct file_operations port_fops = {
749 .llseek = memory_lseek, 791 .llseek = memory_lseek,
750 .read = read_port, 792 .read = read_port,
@@ -770,6 +812,13 @@ static struct file_operations full_fops = {
770 .write = write_full, 812 .write = write_full,
771}; 813};
772 814
815#ifdef CONFIG_CRASH_DUMP
816static struct file_operations oldmem_fops = {
817 .read = read_oldmem,
818 .open = open_oldmem,
819};
820#endif
821
773static ssize_t kmsg_write(struct file * file, const char __user * buf, 822static ssize_t kmsg_write(struct file * file, const char __user * buf,
774 size_t count, loff_t *ppos) 823 size_t count, loff_t *ppos)
775{ 824{
@@ -804,7 +853,7 @@ static int memory_open(struct inode * inode, struct file * filp)
804 case 3: 853 case 3:
805 filp->f_op = &null_fops; 854 filp->f_op = &null_fops;
806 break; 855 break;
807#if defined(CONFIG_ISA) || !defined(__mc68000__) 856#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
808 case 4: 857 case 4:
809 filp->f_op = &port_fops; 858 filp->f_op = &port_fops;
810 break; 859 break;
@@ -825,6 +874,11 @@ static int memory_open(struct inode * inode, struct file * filp)
825 case 11: 874 case 11:
826 filp->f_op = &kmsg_fops; 875 filp->f_op = &kmsg_fops;
827 break; 876 break;
877#ifdef CONFIG_CRASH_DUMP
878 case 12:
879 filp->f_op = &oldmem_fops;
880 break;
881#endif
828 default: 882 default:
829 return -ENXIO; 883 return -ENXIO;
830 } 884 }
@@ -846,7 +900,7 @@ static const struct {
846 {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, 900 {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops},
847 {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, 901 {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops},
848 {3, "null", S_IRUGO | S_IWUGO, &null_fops}, 902 {3, "null", S_IRUGO | S_IWUGO, &null_fops},
849#if defined(CONFIG_ISA) || !defined(__mc68000__) 903#if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI))
850 {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops}, 904 {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops},
851#endif 905#endif
852 {5, "zero", S_IRUGO | S_IWUGO, &zero_fops}, 906 {5, "zero", S_IRUGO | S_IWUGO, &zero_fops},
@@ -854,9 +908,12 @@ static const struct {
854 {8, "random", S_IRUGO | S_IWUSR, &random_fops}, 908 {8, "random", S_IRUGO | S_IWUSR, &random_fops},
855 {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops}, 909 {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops},
856 {11,"kmsg", S_IRUGO | S_IWUSR, &kmsg_fops}, 910 {11,"kmsg", S_IRUGO | S_IWUSR, &kmsg_fops},
911#ifdef CONFIG_CRASH_DUMP
912 {12,"oldmem", S_IRUSR | S_IWUSR | S_IRGRP, &oldmem_fops},
913#endif
857}; 914};
858 915
859static struct class_simple *mem_class; 916static struct class *mem_class;
860 917
861static int __init chr_dev_init(void) 918static int __init chr_dev_init(void)
862{ 919{
@@ -865,10 +922,9 @@ static int __init chr_dev_init(void)
865 if (register_chrdev(MEM_MAJOR,"mem",&memory_fops)) 922 if (register_chrdev(MEM_MAJOR,"mem",&memory_fops))
866 printk("unable to get major %d for memory devs\n", MEM_MAJOR); 923 printk("unable to get major %d for memory devs\n", MEM_MAJOR);
867 924
868 mem_class = class_simple_create(THIS_MODULE, "mem"); 925 mem_class = class_create(THIS_MODULE, "mem");
869 for (i = 0; i < ARRAY_SIZE(devlist); i++) { 926 for (i = 0; i < ARRAY_SIZE(devlist); i++) {
870 class_simple_device_add(mem_class, 927 class_device_create(mem_class, MKDEV(MEM_MAJOR, devlist[i].minor),
871 MKDEV(MEM_MAJOR, devlist[i].minor),
872 NULL, devlist[i].name); 928 NULL, devlist[i].name);
873 devfs_mk_cdev(MKDEV(MEM_MAJOR, devlist[i].minor), 929 devfs_mk_cdev(MKDEV(MEM_MAJOR, devlist[i].minor),
874 S_IFCHR | devlist[i].mode, devlist[i].name); 930 S_IFCHR | devlist[i].mode, devlist[i].name);
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index 0937544762da..931efd58f87a 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -66,8 +66,6 @@ static unsigned char misc_minors[DYNAMIC_MINORS / 8];
66extern int rtc_DP8570A_init(void); 66extern int rtc_DP8570A_init(void);
67extern int rtc_MK48T08_init(void); 67extern int rtc_MK48T08_init(void);
68extern int pmu_device_init(void); 68extern int pmu_device_init(void);
69extern int tosh_init(void);
70extern int i8k_init(void);
71 69
72#ifdef CONFIG_PROC_FS 70#ifdef CONFIG_PROC_FS
73static void *misc_seq_start(struct seq_file *seq, loff_t *pos) 71static void *misc_seq_start(struct seq_file *seq, loff_t *pos)
@@ -177,10 +175,10 @@ fail:
177 175
178/* 176/*
179 * TODO for 2.7: 177 * TODO for 2.7:
180 * - add a struct class_device to struct miscdevice and make all usages of 178 * - add a struct kref to struct miscdevice and make all usages of
181 * them dynamic. 179 * them dynamic.
182 */ 180 */
183static struct class_simple *misc_class; 181static struct class *misc_class;
184 182
185static struct file_operations misc_fops = { 183static struct file_operations misc_fops = {
186 .owner = THIS_MODULE, 184 .owner = THIS_MODULE,
@@ -238,8 +236,8 @@ int misc_register(struct miscdevice * misc)
238 } 236 }
239 dev = MKDEV(MISC_MAJOR, misc->minor); 237 dev = MKDEV(MISC_MAJOR, misc->minor);
240 238
241 misc->class = class_simple_device_add(misc_class, dev, 239 misc->class = class_device_create(misc_class, dev, misc->dev,
242 misc->dev, misc->name); 240 "%s", misc->name);
243 if (IS_ERR(misc->class)) { 241 if (IS_ERR(misc->class)) {
244 err = PTR_ERR(misc->class); 242 err = PTR_ERR(misc->class);
245 goto out; 243 goto out;
@@ -248,7 +246,7 @@ int misc_register(struct miscdevice * misc)
248 err = devfs_mk_cdev(dev, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP, 246 err = devfs_mk_cdev(dev, S_IFCHR|S_IRUSR|S_IWUSR|S_IRGRP,
249 misc->devfs_name); 247 misc->devfs_name);
250 if (err) { 248 if (err) {
251 class_simple_device_remove(dev); 249 class_device_destroy(misc_class, dev);
252 goto out; 250 goto out;
253 } 251 }
254 252
@@ -281,7 +279,7 @@ int misc_deregister(struct miscdevice * misc)
281 279
282 down(&misc_sem); 280 down(&misc_sem);
283 list_del(&misc->list); 281 list_del(&misc->list);
284 class_simple_device_remove(MKDEV(MISC_MAJOR, misc->minor)); 282 class_device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
285 devfs_remove(misc->devfs_name); 283 devfs_remove(misc->devfs_name);
286 if (i < DYNAMIC_MINORS && i>0) { 284 if (i < DYNAMIC_MINORS && i>0) {
287 misc_minors[i>>3] &= ~(1 << (misc->minor & 7)); 285 misc_minors[i>>3] &= ~(1 << (misc->minor & 7));
@@ -302,7 +300,7 @@ static int __init misc_init(void)
302 if (ent) 300 if (ent)
303 ent->proc_fops = &misc_proc_fops; 301 ent->proc_fops = &misc_proc_fops;
304#endif 302#endif
305 misc_class = class_simple_create(THIS_MODULE, "misc"); 303 misc_class = class_create(THIS_MODULE, "misc");
306 if (IS_ERR(misc_class)) 304 if (IS_ERR(misc_class))
307 return PTR_ERR(misc_class); 305 return PTR_ERR(misc_class);
308#ifdef CONFIG_MVME16x 306#ifdef CONFIG_MVME16x
@@ -311,19 +309,10 @@ static int __init misc_init(void)
311#ifdef CONFIG_BVME6000 309#ifdef CONFIG_BVME6000
312 rtc_DP8570A_init(); 310 rtc_DP8570A_init();
313#endif 311#endif
314#ifdef CONFIG_PMAC_PBOOK
315 pmu_device_init();
316#endif
317#ifdef CONFIG_TOSHIBA
318 tosh_init();
319#endif
320#ifdef CONFIG_I8K
321 i8k_init();
322#endif
323 if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) { 312 if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
324 printk("unable to get major %d for misc devices\n", 313 printk("unable to get major %d for misc devices\n",
325 MISC_MAJOR); 314 MISC_MAJOR);
326 class_simple_destroy(misc_class); 315 class_destroy(misc_class);
327 return -EIO; 316 return -EIO;
328 } 317 }
329 return 0; 318 return 0;
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index 7c24fbe831f8..95f7046ff059 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -451,7 +451,7 @@ static int __init moxa_init(void)
451 int n = (sizeof(moxa_pcibrds) / sizeof(moxa_pcibrds[0])) - 1; 451 int n = (sizeof(moxa_pcibrds) / sizeof(moxa_pcibrds[0])) - 1;
452 i = 0; 452 i = 0;
453 while (i < n) { 453 while (i < n) {
454 while ((p = pci_find_device(moxa_pcibrds[i].vendor, moxa_pcibrds[i].device, p))!=NULL) 454 while ((p = pci_get_device(moxa_pcibrds[i].vendor, moxa_pcibrds[i].device, p))!=NULL)
455 { 455 {
456 if (pci_enable_device(p)) 456 if (pci_enable_device(p))
457 continue; 457 continue;
diff --git a/drivers/char/mwave/3780i.c b/drivers/char/mwave/3780i.c
index ab00f51475df..613aed9e1840 100644
--- a/drivers/char/mwave/3780i.c
+++ b/drivers/char/mwave/3780i.c
@@ -107,8 +107,8 @@ void dsp3780I_WriteMsaCfg(unsigned short usDspBaseIO,
107 spin_unlock_irqrestore(&dsp_lock, flags); 107 spin_unlock_irqrestore(&dsp_lock, flags);
108} 108}
109 109
110void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex, 110static void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex,
111 unsigned char ucValue) 111 unsigned char ucValue)
112{ 112{
113 DSP_ISA_SLAVE_CONTROL rSlaveControl; 113 DSP_ISA_SLAVE_CONTROL rSlaveControl;
114 DSP_ISA_SLAVE_CONTROL rSlaveControl_Save; 114 DSP_ISA_SLAVE_CONTROL rSlaveControl_Save;
@@ -141,6 +141,7 @@ void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex,
141 141
142} 142}
143 143
144#if 0
144unsigned char dsp3780I_ReadGenCfg(unsigned short usDspBaseIO, 145unsigned char dsp3780I_ReadGenCfg(unsigned short usDspBaseIO,
145 unsigned uIndex) 146 unsigned uIndex)
146{ 147{
@@ -167,6 +168,7 @@ unsigned char dsp3780I_ReadGenCfg(unsigned short usDspBaseIO,
167 168
168 return ucValue; 169 return ucValue;
169} 170}
171#endif /* 0 */
170 172
171int dsp3780I_EnableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings, 173int dsp3780I_EnableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings,
172 unsigned short *pIrqMap, 174 unsigned short *pIrqMap,
diff --git a/drivers/char/mwave/3780i.h b/drivers/char/mwave/3780i.h
index 3e7d020d1bf4..270431ca7dae 100644
--- a/drivers/char/mwave/3780i.h
+++ b/drivers/char/mwave/3780i.h
@@ -338,10 +338,6 @@ unsigned short dsp3780I_ReadMsaCfg(unsigned short usDspBaseIO,
338 unsigned long ulMsaAddr); 338 unsigned long ulMsaAddr);
339void dsp3780I_WriteMsaCfg(unsigned short usDspBaseIO, 339void dsp3780I_WriteMsaCfg(unsigned short usDspBaseIO,
340 unsigned long ulMsaAddr, unsigned short usValue); 340 unsigned long ulMsaAddr, unsigned short usValue);
341void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex,
342 unsigned char ucValue);
343unsigned char dsp3780I_ReadGenCfg(unsigned short usDspBaseIO,
344 unsigned uIndex);
345int dsp3780I_GetIPCSource(unsigned short usDspBaseIO, 341int dsp3780I_GetIPCSource(unsigned short usDspBaseIO,
346 unsigned short *pusIPCSource); 342 unsigned short *pusIPCSource);
347 343
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c
index d37625d47746..d568991ac6b3 100644
--- a/drivers/char/mwave/mwavedd.c
+++ b/drivers/char/mwave/mwavedd.c
@@ -472,7 +472,7 @@ struct device mwave_device;
472 472
473/* Prevent code redundancy, create a macro for mwave_show_* functions. */ 473/* Prevent code redundancy, create a macro for mwave_show_* functions. */
474#define mwave_show_function(attr_name, format_string, field) \ 474#define mwave_show_function(attr_name, format_string, field) \
475static ssize_t mwave_show_##attr_name(struct device *dev, char *buf) \ 475static ssize_t mwave_show_##attr_name(struct device *dev, struct device_attribute *attr, char *buf) \
476{ \ 476{ \
477 DSP_3780I_CONFIG_SETTINGS *pSettings = \ 477 DSP_3780I_CONFIG_SETTINGS *pSettings = \
478 &mwave_s_mdd.rBDData.rDspSettings; \ 478 &mwave_s_mdd.rBDData.rDspSettings; \
diff --git a/drivers/char/mwave/tp3780i.c b/drivers/char/mwave/tp3780i.c
index ab650cd6efc0..d6c72e0934e2 100644
--- a/drivers/char/mwave/tp3780i.c
+++ b/drivers/char/mwave/tp3780i.c
@@ -242,20 +242,14 @@ int tp3780I_ClaimResources(THINKPAD_BD_DATA * pBDData)
242{ 242{
243 int retval = 0; 243 int retval = 0;
244 DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings; 244 DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
245#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
246 struct resource *pres; 245 struct resource *pres;
247#endif
248 246
249 PRINTK_2(TRACE_TP3780I, 247 PRINTK_2(TRACE_TP3780I,
250 "tp3780i::tp3780I_ClaimResources entry pBDData %p\n", pBDData); 248 "tp3780i::tp3780I_ClaimResources entry pBDData %p\n", pBDData);
251 249
252#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
253 pres = request_region(pSettings->usDspBaseIO, 16, "mwave_3780i"); 250 pres = request_region(pSettings->usDspBaseIO, 16, "mwave_3780i");
254 if ( pres == NULL ) retval = -EIO; 251 if ( pres == NULL ) retval = -EIO;
255#else 252
256 retval = check_region(pSettings->usDspBaseIO, 16);
257 if (!retval) request_region(pSettings->usDspBaseIO, 16, "mwave_3780i");
258#endif
259 if (retval) { 253 if (retval) {
260 PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_ClaimResources: Error: Could not claim I/O region starting at %x\n", pSettings->usDspBaseIO); 254 PRINTK_ERROR(KERN_ERR_MWAVE "tp3780i::tp3780I_ClaimResources: Error: Could not claim I/O region starting at %x\n", pSettings->usDspBaseIO);
261 retval = -EIO; 255 retval = -EIO;
@@ -292,7 +286,7 @@ int tp3780I_ReleaseResources(THINKPAD_BD_DATA * pBDData)
292int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData) 286int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData)
293{ 287{
294 DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings; 288 DSP_3780I_CONFIG_SETTINGS *pSettings = &pBDData->rDspSettings;
295 BOOLEAN bDSPPoweredUp = FALSE, bDSPEnabled = FALSE, bInterruptAllocated = FALSE; 289 BOOLEAN bDSPPoweredUp = FALSE, bInterruptAllocated = FALSE;
296 290
297 PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_EnableDSP entry pBDData %p\n", pBDData); 291 PRINTK_2(TRACE_TP3780I, "tp3780i::tp3780I_EnableDSP entry pBDData %p\n", pBDData);
298 292
@@ -397,8 +391,6 @@ int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData)
397 if (dsp3780I_EnableDSP(pSettings, s_ausThinkpadIrqToField, s_ausThinkpadDmaToField)) { 391 if (dsp3780I_EnableDSP(pSettings, s_ausThinkpadIrqToField, s_ausThinkpadDmaToField)) {
398 PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Error: dsp7880I_EnableDSP() failed\n"); 392 PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Error: dsp7880I_EnableDSP() failed\n");
399 goto exit_cleanup; 393 goto exit_cleanup;
400 } else {
401 bDSPEnabled = TRUE;
402 } 394 }
403 395
404 EnableSRAM(pBDData); 396 EnableSRAM(pBDData);
@@ -411,8 +403,6 @@ int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData)
411 403
412exit_cleanup: 404exit_cleanup:
413 PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Cleaning up\n"); 405 PRINTK_ERROR("tp3780i::tp3780I_EnableDSP: Cleaning up\n");
414 if (bDSPEnabled)
415 dsp3780I_DisableDSP(pSettings);
416 if (bDSPPoweredUp) 406 if (bDSPPoweredUp)
417 smapi_set_DSP_power_state(FALSE); 407 smapi_set_DSP_power_state(FALSE);
418 if (bInterruptAllocated) { 408 if (bInterruptAllocated) {
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c
index b3dbff1cf967..5079beda69b5 100644
--- a/drivers/char/n_hdlc.c
+++ b/drivers/char/n_hdlc.c
@@ -960,7 +960,7 @@ static char hdlc_unregister_fail[] __exitdata =
960static void __exit n_hdlc_exit(void) 960static void __exit n_hdlc_exit(void)
961{ 961{
962 /* Release tty registration of line discipline */ 962 /* Release tty registration of line discipline */
963 int status = tty_register_ldisc(N_HDLC, NULL); 963 int status = tty_unregister_ldisc(N_HDLC);
964 964
965 if (status) 965 if (status)
966 printk(hdlc_unregister_fail, status); 966 printk(hdlc_unregister_fail, status);
diff --git a/drivers/char/n_r3964.c b/drivers/char/n_r3964.c
index 3883073ab48f..2291a87e8ada 100644
--- a/drivers/char/n_r3964.c
+++ b/drivers/char/n_r3964.c
@@ -200,7 +200,7 @@ static void __exit r3964_exit(void)
200 200
201 TRACE_M ("cleanup_module()"); 201 TRACE_M ("cleanup_module()");
202 202
203 status=tty_register_ldisc(N_R3964, NULL); 203 status=tty_unregister_ldisc(N_R3964);
204 204
205 if(status!=0) 205 if(status!=0)
206 { 206 {
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c
index edba5a35bf21..09103b3d8f05 100644
--- a/drivers/char/n_tty.c
+++ b/drivers/char/n_tty.c
@@ -770,10 +770,8 @@ send_signal:
770 } 770 }
771 if (c == '\n') { 771 if (c == '\n') {
772 if (L_ECHO(tty) || L_ECHONL(tty)) { 772 if (L_ECHO(tty) || L_ECHONL(tty)) {
773 if (tty->read_cnt >= N_TTY_BUF_SIZE-1) { 773 if (tty->read_cnt >= N_TTY_BUF_SIZE-1)
774 put_char('\a', tty); 774 put_char('\a', tty);
775 return;
776 }
777 opost('\n', tty); 775 opost('\n', tty);
778 } 776 }
779 goto handle_newline; 777 goto handle_newline;
@@ -790,10 +788,8 @@ send_signal:
790 * XXX are EOL_CHAR and EOL2_CHAR echoed?!? 788 * XXX are EOL_CHAR and EOL2_CHAR echoed?!?
791 */ 789 */
792 if (L_ECHO(tty)) { 790 if (L_ECHO(tty)) {
793 if (tty->read_cnt >= N_TTY_BUF_SIZE-1) { 791 if (tty->read_cnt >= N_TTY_BUF_SIZE-1)
794 put_char('\a', tty); 792 put_char('\a', tty);
795 return;
796 }
797 /* Record the column of first canon char. */ 793 /* Record the column of first canon char. */
798 if (tty->canon_head == tty->read_head) 794 if (tty->canon_head == tty->read_head)
799 tty->canon_column = tty->column; 795 tty->canon_column = tty->column;
@@ -862,12 +858,9 @@ static int n_tty_receive_room(struct tty_struct *tty)
862 * that erase characters will be handled. Other excess 858 * that erase characters will be handled. Other excess
863 * characters will be beeped. 859 * characters will be beeped.
864 */ 860 */
865 if (tty->icanon && !tty->canon_data) 861 if (left <= 0)
866 return N_TTY_BUF_SIZE; 862 left = tty->icanon && !tty->canon_data;
867 863 return left;
868 if (left > 0)
869 return left;
870 return 0;
871} 864}
872 865
873/** 866/**
@@ -1473,13 +1466,17 @@ static ssize_t write_chan(struct tty_struct * tty, struct file * file,
1473 if (tty->driver->flush_chars) 1466 if (tty->driver->flush_chars)
1474 tty->driver->flush_chars(tty); 1467 tty->driver->flush_chars(tty);
1475 } else { 1468 } else {
1476 c = tty->driver->write(tty, b, nr); 1469 while (nr > 0) {
1477 if (c < 0) { 1470 c = tty->driver->write(tty, b, nr);
1478 retval = c; 1471 if (c < 0) {
1479 goto break_out; 1472 retval = c;
1473 goto break_out;
1474 }
1475 if (!c)
1476 break;
1477 b += c;
1478 nr -= c;
1480 } 1479 }
1481 b += c;
1482 nr -= c;
1483 } 1480 }
1484 if (!nr) 1481 if (!nr)
1485 break; 1482 break;
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index f63a3fd7ca6f..1af733d07321 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -211,12 +211,13 @@ nvram_check_checksum(void)
211 return rv; 211 return rv;
212} 212}
213 213
214void 214static void
215__nvram_set_checksum(void) 215__nvram_set_checksum(void)
216{ 216{
217 mach_set_checksum(); 217 mach_set_checksum();
218} 218}
219 219
220#if 0
220void 221void
221nvram_set_checksum(void) 222nvram_set_checksum(void)
222{ 223{
@@ -226,6 +227,7 @@ nvram_set_checksum(void)
226 __nvram_set_checksum(); 227 __nvram_set_checksum();
227 spin_unlock_irqrestore(&rtc_lock, flags); 228 spin_unlock_irqrestore(&rtc_lock, flags);
228} 229}
230#endif /* 0 */
229 231
230/* 232/*
231 * The are the file operation function for user access to /dev/nvram 233 * The are the file operation function for user access to /dev/nvram
@@ -921,6 +923,4 @@ EXPORT_SYMBOL(__nvram_write_byte);
921EXPORT_SYMBOL(nvram_write_byte); 923EXPORT_SYMBOL(nvram_write_byte);
922EXPORT_SYMBOL(__nvram_check_checksum); 924EXPORT_SYMBOL(__nvram_check_checksum);
923EXPORT_SYMBOL(nvram_check_checksum); 925EXPORT_SYMBOL(nvram_check_checksum);
924EXPORT_SYMBOL(__nvram_set_checksum);
925EXPORT_SYMBOL(nvram_set_checksum);
926MODULE_ALIAS_MISCDEV(NVRAM_MINOR); 926MODULE_ALIAS_MISCDEV(NVRAM_MINOR);
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index 1c8d866a49dc..7a0c74648124 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -71,7 +71,6 @@
71#include <linux/workqueue.h> 71#include <linux/workqueue.h>
72#include <linux/hdlc.h> 72#include <linux/hdlc.h>
73 73
74#include <pcmcia/version.h>
75#include <pcmcia/cs_types.h> 74#include <pcmcia/cs_types.h>
76#include <pcmcia/cs.h> 75#include <pcmcia/cs.h>
77#include <pcmcia/cistpl.h> 76#include <pcmcia/cistpl.h>
@@ -581,7 +580,7 @@ static dev_link_t *mgslpc_attach(void)
581 580
582 /* Interrupt setup */ 581 /* Interrupt setup */
583 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE; 582 link->irq.Attributes = IRQ_TYPE_EXCLUSIVE;
584 link->irq.IRQInfo1 = IRQ_INFO2_VALID | IRQ_LEVEL_ID; 583 link->irq.IRQInfo1 = IRQ_LEVEL_ID;
585 link->irq.Handler = NULL; 584 link->irq.Handler = NULL;
586 585
587 link->conf.Attributes = 0; 586 link->conf.Attributes = 0;
@@ -593,11 +592,6 @@ static dev_link_t *mgslpc_attach(void)
593 dev_list = link; 592 dev_list = link;
594 593
595 client_reg.dev_info = &dev_info; 594 client_reg.dev_info = &dev_info;
596 client_reg.EventMask =
597 CS_EVENT_CARD_INSERTION | CS_EVENT_CARD_REMOVAL |
598 CS_EVENT_RESET_PHYSICAL | CS_EVENT_CARD_RESET |
599 CS_EVENT_PM_SUSPEND | CS_EVENT_PM_RESUME;
600 client_reg.event_handler = &mgslpc_event;
601 client_reg.Version = 0x0210; 595 client_reg.Version = 0x0210;
602 client_reg.event_callback_args.client_data = link; 596 client_reg.event_callback_args.client_data = link;
603 597
@@ -3081,13 +3075,21 @@ void mgslpc_remove_device(MGSLPC_INFO *remove_info)
3081 } 3075 }
3082} 3076}
3083 3077
3078static struct pcmcia_device_id mgslpc_ids[] = {
3079 PCMCIA_DEVICE_MANF_CARD(0x02c5, 0x0050),
3080 PCMCIA_DEVICE_NULL
3081};
3082MODULE_DEVICE_TABLE(pcmcia, mgslpc_ids);
3083
3084static struct pcmcia_driver mgslpc_driver = { 3084static struct pcmcia_driver mgslpc_driver = {
3085 .owner = THIS_MODULE, 3085 .owner = THIS_MODULE,
3086 .drv = { 3086 .drv = {
3087 .name = "synclink_cs", 3087 .name = "synclink_cs",
3088 }, 3088 },
3089 .attach = mgslpc_attach, 3089 .attach = mgslpc_attach,
3090 .event = mgslpc_event,
3090 .detach = mgslpc_detach, 3091 .detach = mgslpc_detach,
3092 .id_table = mgslpc_ids,
3091}; 3093};
3092 3094
3093static struct tty_operations mgslpc_ops = { 3095static struct tty_operations mgslpc_ops = {
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c
index 5eda075c62bd..0e22880432bc 100644
--- a/drivers/char/ppdev.c
+++ b/drivers/char/ppdev.c
@@ -737,7 +737,7 @@ static unsigned int pp_poll (struct file * file, poll_table * wait)
737 return mask; 737 return mask;
738} 738}
739 739
740static struct class_simple *ppdev_class; 740static struct class *ppdev_class;
741 741
742static struct file_operations pp_fops = { 742static struct file_operations pp_fops = {
743 .owner = THIS_MODULE, 743 .owner = THIS_MODULE,
@@ -752,13 +752,13 @@ static struct file_operations pp_fops = {
752 752
753static void pp_attach(struct parport *port) 753static void pp_attach(struct parport *port)
754{ 754{
755 class_simple_device_add(ppdev_class, MKDEV(PP_MAJOR, port->number), 755 class_device_create(ppdev_class, MKDEV(PP_MAJOR, port->number),
756 NULL, "parport%d", port->number); 756 NULL, "parport%d", port->number);
757} 757}
758 758
759static void pp_detach(struct parport *port) 759static void pp_detach(struct parport *port)
760{ 760{
761 class_simple_device_remove(MKDEV(PP_MAJOR, port->number)); 761 class_device_destroy(ppdev_class, MKDEV(PP_MAJOR, port->number));
762} 762}
763 763
764static struct parport_driver pp_driver = { 764static struct parport_driver pp_driver = {
@@ -776,7 +776,7 @@ static int __init ppdev_init (void)
776 PP_MAJOR); 776 PP_MAJOR);
777 return -EIO; 777 return -EIO;
778 } 778 }
779 ppdev_class = class_simple_create(THIS_MODULE, CHRDEV); 779 ppdev_class = class_create(THIS_MODULE, CHRDEV);
780 if (IS_ERR(ppdev_class)) { 780 if (IS_ERR(ppdev_class)) {
781 err = PTR_ERR(ppdev_class); 781 err = PTR_ERR(ppdev_class);
782 goto out_chrdev; 782 goto out_chrdev;
@@ -798,7 +798,7 @@ out_class:
798 for (i = 0; i < PARPORT_MAX; i++) 798 for (i = 0; i < PARPORT_MAX; i++)
799 devfs_remove("parports/%d", i); 799 devfs_remove("parports/%d", i);
800 devfs_remove("parports"); 800 devfs_remove("parports");
801 class_simple_destroy(ppdev_class); 801 class_destroy(ppdev_class);
802out_chrdev: 802out_chrdev:
803 unregister_chrdev(PP_MAJOR, CHRDEV); 803 unregister_chrdev(PP_MAJOR, CHRDEV);
804out: 804out:
@@ -813,7 +813,7 @@ static void __exit ppdev_cleanup (void)
813 devfs_remove("parports/%d", i); 813 devfs_remove("parports/%d", i);
814 parport_unregister_driver(&pp_driver); 814 parport_unregister_driver(&pp_driver);
815 devfs_remove("parports"); 815 devfs_remove("parports");
816 class_simple_destroy(ppdev_class); 816 class_destroy(ppdev_class);
817 unregister_chrdev (PP_MAJOR, CHRDEV); 817 unregister_chrdev (PP_MAJOR, CHRDEV);
818} 818}
819 819
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 460b5d475edd..6b11d6b2129f 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -271,7 +271,7 @@ static int random_write_wakeup_thresh = 128;
271 * samples to avoid wasting CPU time and reduce lock contention. 271 * samples to avoid wasting CPU time and reduce lock contention.
272 */ 272 */
273 273
274static int trickle_thresh = INPUT_POOL_WORDS * 28; 274static int trickle_thresh __read_mostly = INPUT_POOL_WORDS * 28;
275 275
276static DEFINE_PER_CPU(int, trickle_count) = 0; 276static DEFINE_PER_CPU(int, trickle_count) = 0;
277 277
diff --git a/drivers/char/raw.c b/drivers/char/raw.c
index ca5f42bcaad9..f13e5de02207 100644
--- a/drivers/char/raw.c
+++ b/drivers/char/raw.c
@@ -27,7 +27,7 @@ struct raw_device_data {
27 int inuse; 27 int inuse;
28}; 28};
29 29
30static struct class_simple *raw_class; 30static struct class *raw_class;
31static struct raw_device_data raw_devices[MAX_RAW_MINORS]; 31static struct raw_device_data raw_devices[MAX_RAW_MINORS];
32static DECLARE_MUTEX(raw_mutex); 32static DECLARE_MUTEX(raw_mutex);
33static struct file_operations raw_ctl_fops; /* forward declaration */ 33static struct file_operations raw_ctl_fops; /* forward declaration */
@@ -127,8 +127,8 @@ raw_ioctl(struct inode *inode, struct file *filp,
127 127
128static void bind_device(struct raw_config_request *rq) 128static void bind_device(struct raw_config_request *rq)
129{ 129{
130 class_simple_device_remove(MKDEV(RAW_MAJOR, rq->raw_minor)); 130 class_device_destroy(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor));
131 class_simple_device_add(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor), 131 class_device_create(raw_class, MKDEV(RAW_MAJOR, rq->raw_minor),
132 NULL, "raw%d", rq->raw_minor); 132 NULL, "raw%d", rq->raw_minor);
133} 133}
134 134
@@ -200,8 +200,8 @@ static int raw_ctl_ioctl(struct inode *inode, struct file *filp,
200 if (rq.block_major == 0 && rq.block_minor == 0) { 200 if (rq.block_major == 0 && rq.block_minor == 0) {
201 /* unbind */ 201 /* unbind */
202 rawdev->binding = NULL; 202 rawdev->binding = NULL;
203 class_simple_device_remove(MKDEV(RAW_MAJOR, 203 class_device_destroy(raw_class,
204 rq.raw_minor)); 204 MKDEV(RAW_MAJOR, rq.raw_minor));
205 } else { 205 } else {
206 rawdev->binding = bdget(dev); 206 rawdev->binding = bdget(dev);
207 if (rawdev->binding == NULL) 207 if (rawdev->binding == NULL)
@@ -300,14 +300,14 @@ static int __init raw_init(void)
300 goto error; 300 goto error;
301 } 301 }
302 302
303 raw_class = class_simple_create(THIS_MODULE, "raw"); 303 raw_class = class_create(THIS_MODULE, "raw");
304 if (IS_ERR(raw_class)) { 304 if (IS_ERR(raw_class)) {
305 printk(KERN_ERR "Error creating raw class.\n"); 305 printk(KERN_ERR "Error creating raw class.\n");
306 cdev_del(&raw_cdev); 306 cdev_del(&raw_cdev);
307 unregister_chrdev_region(dev, MAX_RAW_MINORS); 307 unregister_chrdev_region(dev, MAX_RAW_MINORS);
308 goto error; 308 goto error;
309 } 309 }
310 class_simple_device_add(raw_class, MKDEV(RAW_MAJOR, 0), NULL, "rawctl"); 310 class_device_create(raw_class, MKDEV(RAW_MAJOR, 0), NULL, "rawctl");
311 311
312 devfs_mk_cdev(MKDEV(RAW_MAJOR, 0), 312 devfs_mk_cdev(MKDEV(RAW_MAJOR, 0),
313 S_IFCHR | S_IRUGO | S_IWUGO, 313 S_IFCHR | S_IRUGO | S_IWUGO,
@@ -331,8 +331,8 @@ static void __exit raw_exit(void)
331 devfs_remove("raw/raw%d", i); 331 devfs_remove("raw/raw%d", i);
332 devfs_remove("raw/rawctl"); 332 devfs_remove("raw/rawctl");
333 devfs_remove("raw"); 333 devfs_remove("raw");
334 class_simple_device_remove(MKDEV(RAW_MAJOR, 0)); 334 class_device_destroy(raw_class, MKDEV(RAW_MAJOR, 0));
335 class_simple_destroy(raw_class); 335 class_destroy(raw_class);
336 cdev_del(&raw_cdev); 336 cdev_del(&raw_cdev);
337 unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), MAX_RAW_MINORS); 337 unregister_chrdev_region(MKDEV(RAW_MAJOR, 0), MAX_RAW_MINORS);
338} 338}
diff --git a/drivers/char/rio/func.h b/drivers/char/rio/func.h
index e8f3860f4726..01987c6dc398 100644
--- a/drivers/char/rio/func.h
+++ b/drivers/char/rio/func.h
@@ -147,7 +147,6 @@ struct rio_info * rio_info_store( int cmd, struct rio_info * p);
147extern int rio_pcicopy(char *src, char *dst, int n); 147extern int rio_pcicopy(char *src, char *dst, int n);
148extern int rio_minor (struct tty_struct *tty); 148extern int rio_minor (struct tty_struct *tty);
149extern int rio_ismodem (struct tty_struct *tty); 149extern int rio_ismodem (struct tty_struct *tty);
150extern void rio_udelay (int usecs);
151 150
152extern void rio_start_card_running (struct Host * HostP); 151extern void rio_start_card_running (struct Host * HostP);
153 152
diff --git a/drivers/char/rio/rio_linux.c b/drivers/char/rio/rio_linux.c
index 763893e289b3..d7d484024e2b 100644
--- a/drivers/char/rio/rio_linux.c
+++ b/drivers/char/rio/rio_linux.c
@@ -354,11 +354,6 @@ int rio_ismodem(struct tty_struct *tty)
354} 354}
355 355
356 356
357void rio_udelay (int usecs)
358{
359 udelay (usecs);
360}
361
362static int rio_set_real_termios (void *ptr) 357static int rio_set_real_termios (void *ptr)
363{ 358{
364 int rv, modem; 359 int rv, modem;
@@ -1100,7 +1095,7 @@ static int __init rio_init(void)
1100 1095
1101#ifdef CONFIG_PCI 1096#ifdef CONFIG_PCI
1102 /* First look for the JET devices: */ 1097 /* First look for the JET devices: */
1103 while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, 1098 while ((pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX,
1104 PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, 1099 PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
1105 pdev))) { 1100 pdev))) {
1106 if (pci_enable_device(pdev)) continue; 1101 if (pci_enable_device(pdev)) continue;
@@ -1174,7 +1169,7 @@ static int __init rio_init(void)
1174 */ 1169 */
1175 1170
1176 /* Then look for the older RIO/PCI devices: */ 1171 /* Then look for the older RIO/PCI devices: */
1177 while ((pdev = pci_find_device (PCI_VENDOR_ID_SPECIALIX, 1172 while ((pdev = pci_get_device (PCI_VENDOR_ID_SPECIALIX,
1178 PCI_DEVICE_ID_SPECIALIX_RIO, 1173 PCI_DEVICE_ID_SPECIALIX_RIO,
1179 pdev))) { 1174 pdev))) {
1180 if (pci_enable_device(pdev)) continue; 1175 if (pci_enable_device(pdev)) continue;
diff --git a/drivers/char/rio/rioboot.c b/drivers/char/rio/rioboot.c
index a8be11dfcba3..34cbb13aad4b 100644
--- a/drivers/char/rio/rioboot.c
+++ b/drivers/char/rio/rioboot.c
@@ -902,7 +902,7 @@ static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, st
902 (HostP->Mapping[entry].RtaUniqueNum==RtaUniq)) 902 (HostP->Mapping[entry].RtaUniqueNum==RtaUniq))
903 { 903 {
904 HostP->Mapping[entry].Flags |= RTA_BOOTED|RTA_NEWBOOT; 904 HostP->Mapping[entry].Flags |= RTA_BOOTED|RTA_NEWBOOT;
905#if NEED_TO_FIX 905#ifdef NEED_TO_FIX
906 RIO_SV_BROADCAST(HostP->svFlags[entry]); 906 RIO_SV_BROADCAST(HostP->svFlags[entry]);
907#endif 907#endif
908 if ( (sysport=HostP->Mapping[entry].SysPort) != NO_PORT ) 908 if ( (sysport=HostP->Mapping[entry].SysPort) != NO_PORT )
@@ -918,7 +918,7 @@ static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, st
918 { 918 {
919 entry2 = HostP->Mapping[entry].ID2 - 1; 919 entry2 = HostP->Mapping[entry].ID2 - 1;
920 HostP->Mapping[entry2].Flags |= RTA_BOOTED|RTA_NEWBOOT; 920 HostP->Mapping[entry2].Flags |= RTA_BOOTED|RTA_NEWBOOT;
921#if NEED_TO_FIX 921#ifdef NEED_TO_FIX
922 RIO_SV_BROADCAST(HostP->svFlags[entry2]); 922 RIO_SV_BROADCAST(HostP->svFlags[entry2]);
923#endif 923#endif
924 sysport = HostP->Mapping[entry2].SysPort; 924 sysport = HostP->Mapping[entry2].SysPort;
@@ -1143,7 +1143,7 @@ static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, st
1143 CCOPY( MapP->Name, HostP->Mapping[entry].Name, MAX_NAME_LEN ); 1143 CCOPY( MapP->Name, HostP->Mapping[entry].Name, MAX_NAME_LEN );
1144 HostP->Mapping[entry].Flags = 1144 HostP->Mapping[entry].Flags =
1145 SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT; 1145 SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT;
1146#if NEED_TO_FIX 1146#ifdef NEED_TO_FIX
1147 RIO_SV_BROADCAST(HostP->svFlags[entry]); 1147 RIO_SV_BROADCAST(HostP->svFlags[entry]);
1148#endif 1148#endif
1149 RIOReMapPorts( p, HostP, &HostP->Mapping[entry] ); 1149 RIOReMapPorts( p, HostP, &HostP->Mapping[entry] );
@@ -1159,7 +1159,7 @@ static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, st
1159 "This RTA has a tentative entry on another host - delete that entry (1)\n"); 1159 "This RTA has a tentative entry on another host - delete that entry (1)\n");
1160 HostP->Mapping[entry].Flags = 1160 HostP->Mapping[entry].Flags =
1161 SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT; 1161 SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT;
1162#if NEED_TO_FIX 1162#ifdef NEED_TO_FIX
1163 RIO_SV_BROADCAST(HostP->svFlags[entry]); 1163 RIO_SV_BROADCAST(HostP->svFlags[entry]);
1164#endif 1164#endif
1165 } 1165 }
@@ -1169,7 +1169,7 @@ static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, st
1169 { 1169 {
1170 HostP->Mapping[entry2].Flags = SLOT_IN_USE | 1170 HostP->Mapping[entry2].Flags = SLOT_IN_USE |
1171 RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT; 1171 RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT;
1172#if NEED_TO_FIX 1172#ifdef NEED_TO_FIX
1173 RIO_SV_BROADCAST(HostP->svFlags[entry2]); 1173 RIO_SV_BROADCAST(HostP->svFlags[entry2]);
1174#endif 1174#endif
1175 HostP->Mapping[entry2].SysPort = MapP2->SysPort; 1175 HostP->Mapping[entry2].SysPort = MapP2->SysPort;
@@ -1188,7 +1188,7 @@ static int RIOBootComplete( struct rio_info *p, struct Host *HostP, uint Rup, st
1188 else 1188 else
1189 HostP->Mapping[entry2].Flags = SLOT_TENTATIVE | 1189 HostP->Mapping[entry2].Flags = SLOT_TENTATIVE |
1190 RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT; 1190 RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT;
1191#if NEED_TO_FIX 1191#ifdef NEED_TO_FIX
1192 RIO_SV_BROADCAST(HostP->svFlags[entry2]); 1192 RIO_SV_BROADCAST(HostP->svFlags[entry2]);
1193#endif 1193#endif
1194 bzero( (caddr_t)MapP2, sizeof(struct Map) ); 1194 bzero( (caddr_t)MapP2, sizeof(struct Map) );
diff --git a/drivers/char/rio/rioinit.c b/drivers/char/rio/rioinit.c
index dca941ed10cf..898a126ae3e6 100644
--- a/drivers/char/rio/rioinit.c
+++ b/drivers/char/rio/rioinit.c
@@ -37,6 +37,7 @@ static char *_rioinit_c_sccs_ = "@(#)rioinit.c 1.3";
37#include <linux/module.h> 37#include <linux/module.h>
38#include <linux/slab.h> 38#include <linux/slab.h>
39#include <linux/errno.h> 39#include <linux/errno.h>
40#include <linux/delay.h>
40#include <asm/io.h> 41#include <asm/io.h>
41#include <asm/system.h> 42#include <asm/system.h>
42#include <asm/string.h> 43#include <asm/string.h>
@@ -1560,14 +1561,14 @@ uint Slot;
1560 INTERRUPT_DISABLE | BYTE_OPERATION | 1561 INTERRUPT_DISABLE | BYTE_OPERATION |
1561 SLOW_LINKS | SLOW_AT_BUS); 1562 SLOW_LINKS | SLOW_AT_BUS);
1562 WBYTE(DpRamP->DpResetTpu, 0xFF); 1563 WBYTE(DpRamP->DpResetTpu, 0xFF);
1563 rio_udelay (3); 1564 udelay(3);
1564 1565
1565 rio_dprintk (RIO_DEBUG_INIT, "RIOHostReset: Don't know if it worked. Try reset again\n"); 1566 rio_dprintk (RIO_DEBUG_INIT, "RIOHostReset: Don't know if it worked. Try reset again\n");
1566 WBYTE(DpRamP->DpControl, BOOT_FROM_RAM | EXTERNAL_BUS_OFF | 1567 WBYTE(DpRamP->DpControl, BOOT_FROM_RAM | EXTERNAL_BUS_OFF |
1567 INTERRUPT_DISABLE | BYTE_OPERATION | 1568 INTERRUPT_DISABLE | BYTE_OPERATION |
1568 SLOW_LINKS | SLOW_AT_BUS); 1569 SLOW_LINKS | SLOW_AT_BUS);
1569 WBYTE(DpRamP->DpResetTpu, 0xFF); 1570 WBYTE(DpRamP->DpResetTpu, 0xFF);
1570 rio_udelay (3); 1571 udelay(3);
1571 break; 1572 break;
1572#ifdef FUTURE_RELEASE 1573#ifdef FUTURE_RELEASE
1573 case RIO_EISA: 1574 case RIO_EISA:
@@ -1599,7 +1600,7 @@ uint Slot;
1599 DpRamP->DpControl = RIO_PCI_BOOT_FROM_RAM; 1600 DpRamP->DpControl = RIO_PCI_BOOT_FROM_RAM;
1600 DpRamP->DpResetInt = 0xFF; 1601 DpRamP->DpResetInt = 0xFF;
1601 DpRamP->DpResetTpu = 0xFF; 1602 DpRamP->DpResetTpu = 0xFF;
1602 rio_udelay (100); 1603 udelay(100);
1603 /* for (i=0; i<6000; i++); */ 1604 /* for (i=0; i<6000; i++); */
1604 /* suspend( 3 ); */ 1605 /* suspend( 3 ); */
1605 break; 1606 break;
diff --git a/drivers/char/rio/rioroute.c b/drivers/char/rio/rioroute.c
index 106b31f48a21..e9564c9fb37c 100644
--- a/drivers/char/rio/rioroute.c
+++ b/drivers/char/rio/rioroute.c
@@ -1023,7 +1023,7 @@ RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit)
1023 if (link < LINKS_PER_UNIT) 1023 if (link < LINKS_PER_UNIT)
1024 return 1; 1024 return 1;
1025 1025
1026#if NEED_TO_FIX_THIS 1026#ifdef NEED_TO_FIX_THIS
1027 /* Ok so all the links are disconnected. But we may have only just 1027 /* Ok so all the links are disconnected. But we may have only just
1028 ** made this slot tentative and not yet received a topology update. 1028 ** made this slot tentative and not yet received a topology update.
1029 ** Lets check how long ago we made it tentative. 1029 ** Lets check how long ago we made it tentative.
diff --git a/drivers/char/rio/riotable.c b/drivers/char/rio/riotable.c
index 8fb26ad2aa12..e45bc275907a 100644
--- a/drivers/char/rio/riotable.c
+++ b/drivers/char/rio/riotable.c
@@ -771,7 +771,7 @@ int RIOAssignRta( struct rio_info *p, struct Map *MapP )
771 if ((MapP->Flags & RTA16_SECOND_SLOT) == 0) 771 if ((MapP->Flags & RTA16_SECOND_SLOT) == 0)
772 CCOPY( MapP->Name, HostMapP->Name, MAX_NAME_LEN ); 772 CCOPY( MapP->Name, HostMapP->Name, MAX_NAME_LEN );
773 HostMapP->Flags = SLOT_IN_USE | RTA_BOOTED; 773 HostMapP->Flags = SLOT_IN_USE | RTA_BOOTED;
774#if NEED_TO_FIX 774#ifdef NEED_TO_FIX
775 RIO_SV_BROADCAST(p->RIOHosts[host].svFlags[MapP->ID-1]); 775 RIO_SV_BROADCAST(p->RIOHosts[host].svFlags[MapP->ID-1]);
776#endif 776#endif
777 if (MapP->Flags & RTA16_SECOND_SLOT) 777 if (MapP->Flags & RTA16_SECOND_SLOT)
diff --git a/drivers/char/rio/riotty.c b/drivers/char/rio/riotty.c
index db655002671f..78a321afdf4f 100644
--- a/drivers/char/rio/riotty.c
+++ b/drivers/char/rio/riotty.c
@@ -524,16 +524,16 @@ riotclose(void *ptr)
524 register uint SysPort = dev; 524 register uint SysPort = dev;
525 struct ttystatics *tp; /* pointer to our ttystruct */ 525 struct ttystatics *tp; /* pointer to our ttystruct */
526#endif 526#endif
527 struct Port *PortP =ptr; /* pointer to the port structure */ 527 struct Port *PortP = ptr; /* pointer to the port structure */
528 int deleted = 0; 528 int deleted = 0;
529 int try = -1; /* Disable the timeouts by setting them to -1 */ 529 int try = -1; /* Disable the timeouts by setting them to -1 */
530 int repeat_this = -1; /* Congrats to those having 15 years of 530 int repeat_this = -1; /* Congrats to those having 15 years of
531 uptime! (You get to break the driver.) */ 531 uptime! (You get to break the driver.) */
532 long end_time; 532 unsigned long end_time;
533 struct tty_struct * tty; 533 struct tty_struct * tty;
534 unsigned long flags; 534 unsigned long flags;
535 int Modem; 535 int Modem;
536 int rv =0; 536 int rv = 0;
537 537
538 rio_dprintk (RIO_DEBUG_TTY, "port close SysPort %d\n",PortP->PortNum); 538 rio_dprintk (RIO_DEBUG_TTY, "port close SysPort %d\n",PortP->PortNum);
539 539
@@ -620,7 +620,7 @@ riotclose(void *ptr)
620 if (repeat_this -- <= 0) { 620 if (repeat_this -- <= 0) {
621 rv = -EINTR; 621 rv = -EINTR;
622 rio_dprintk (RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n"); 622 rio_dprintk (RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
623 RIOPreemptiveCmd(p, PortP, FCLOSE ); 623 RIOPreemptiveCmd(p, PortP, FCLOSE);
624 goto close_end; 624 goto close_end;
625 } 625 }
626 rio_dprintk (RIO_DEBUG_TTY, "Calling timeout to flush in closing\n"); 626 rio_dprintk (RIO_DEBUG_TTY, "Calling timeout to flush in closing\n");
@@ -656,14 +656,12 @@ riotclose(void *ptr)
656 goto close_end; 656 goto close_end;
657 } 657 }
658 658
659
660
661 /* Can't call RIOShortCommand with the port locked. */ 659 /* Can't call RIOShortCommand with the port locked. */
662 rio_spin_unlock_irqrestore(&PortP->portSem, flags); 660 rio_spin_unlock_irqrestore(&PortP->portSem, flags);
663 661
664 if (RIOShortCommand(p, PortP, CLOSE, 1, 0) == RIO_FAIL) { 662 if (RIOShortCommand(p, PortP, CLOSE, 1, 0) == RIO_FAIL) {
665 RIOPreemptiveCmd(p, PortP,FCLOSE); 663 RIOPreemptiveCmd(p, PortP, FCLOSE);
666 goto close_end; 664 goto close_end;
667 } 665 }
668 666
669 if (!deleted) 667 if (!deleted)
@@ -698,7 +696,6 @@ riotclose(void *ptr)
698*/ 696*/
699 PortP->Config &= ~(RIO_CTSFLOW|RIO_RTSFLOW); 697 PortP->Config &= ~(RIO_CTSFLOW|RIO_RTSFLOW);
700 698
701
702#ifdef STATS 699#ifdef STATS
703 PortP->Stat.CloseCnt++; 700 PortP->Stat.CloseCnt++;
704#endif 701#endif
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index 5bcbeb0cb9ae..5b1d3680c8ab 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -161,6 +161,64 @@ static Word_t upci_aiop_intr_bits[AIOP_CTL_SIZE] = {
161 UPCI_AIOP_INTR_BIT_3 161 UPCI_AIOP_INTR_BIT_3
162}; 162};
163 163
164static Byte_t RData[RDATASIZE] = {
165 0x00, 0x09, 0xf6, 0x82,
166 0x02, 0x09, 0x86, 0xfb,
167 0x04, 0x09, 0x00, 0x0a,
168 0x06, 0x09, 0x01, 0x0a,
169 0x08, 0x09, 0x8a, 0x13,
170 0x0a, 0x09, 0xc5, 0x11,
171 0x0c, 0x09, 0x86, 0x85,
172 0x0e, 0x09, 0x20, 0x0a,
173 0x10, 0x09, 0x21, 0x0a,
174 0x12, 0x09, 0x41, 0xff,
175 0x14, 0x09, 0x82, 0x00,
176 0x16, 0x09, 0x82, 0x7b,
177 0x18, 0x09, 0x8a, 0x7d,
178 0x1a, 0x09, 0x88, 0x81,
179 0x1c, 0x09, 0x86, 0x7a,
180 0x1e, 0x09, 0x84, 0x81,
181 0x20, 0x09, 0x82, 0x7c,
182 0x22, 0x09, 0x0a, 0x0a
183};
184
185static Byte_t RRegData[RREGDATASIZE] = {
186 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */
187 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */
188 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */
189 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */
190 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */
191 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */
192 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */
193 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */
194 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */
195 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */
196 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */
197 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */
198 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */
199};
200
201static CONTROLLER_T sController[CTL_SIZE] = {
202 {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
203 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
204 {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
205 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
206 {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
207 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
208 {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
209 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}}
210};
211
212static Byte_t sBitMapClrTbl[8] = {
213 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f
214};
215
216static Byte_t sBitMapSetTbl[8] = {
217 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
218};
219
220static int sClockPrescale = 0x14;
221
164/* 222/*
165 * Line number is the ttySIx number (x), the Minor number. We 223 * Line number is the ttySIx number (x), the Minor number. We
166 * assign them sequentially, starting at zero. The following 224 * assign them sequentially, starting at zero. The following
@@ -177,6 +235,26 @@ static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model);
177static unsigned char GetLineNumber(int ctrl, int aiop, int ch); 235static unsigned char GetLineNumber(int ctrl, int aiop, int ch);
178static unsigned char SetLineNumber(int ctrl, int aiop, int ch); 236static unsigned char SetLineNumber(int ctrl, int aiop, int ch);
179static void rp_start(struct tty_struct *tty); 237static void rp_start(struct tty_struct *tty);
238static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
239 int ChanNum);
240static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode);
241static void sFlushRxFIFO(CHANNEL_T * ChP);
242static void sFlushTxFIFO(CHANNEL_T * ChP);
243static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags);
244static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags);
245static void sModemReset(CONTROLLER_T * CtlP, int chan, int on);
246static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on);
247static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data);
248static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
249 ByteIO_t * AiopIOList, int AiopIOListSize,
250 WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
251 int PeriodicOnly, int altChanRingIndicator,
252 int UPCIRingInd);
253static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
254 ByteIO_t * AiopIOList, int AiopIOListSize,
255 int IRQNum, Byte_t Frequency, int PeriodicOnly);
256static int sReadAiopID(ByteIO_t io);
257static int sReadAiopNumChan(WordIO_t io);
180 258
181#ifdef MODULE 259#ifdef MODULE
182MODULE_AUTHOR("Theodore Ts'o"); 260MODULE_AUTHOR("Theodore Ts'o");
@@ -277,7 +355,7 @@ static void rp_do_receive(struct r_port *info,
277 ToRecv = space; 355 ToRecv = space;
278 356
279 if (ToRecv <= 0) 357 if (ToRecv <= 0)
280 return; 358 goto done;
281 359
282 /* 360 /*
283 * if status indicates there are errored characters in the 361 * if status indicates there are errored characters in the
@@ -359,6 +437,7 @@ static void rp_do_receive(struct r_port *info,
359 } 437 }
360 /* Push the data up to the tty layer */ 438 /* Push the data up to the tty layer */
361 ld->receive_buf(tty, tty->flip.char_buf, tty->flip.flag_buf, count); 439 ld->receive_buf(tty, tty->flip.char_buf, tty->flip.flag_buf, count);
440done:
362 tty_ldisc_deref(ld); 441 tty_ldisc_deref(ld);
363} 442}
364 443
@@ -1798,7 +1877,7 @@ static void rp_flush_buffer(struct tty_struct *tty)
1798 * init's aiopic and serial port hardware. 1877 * init's aiopic and serial port hardware.
1799 * Inputs: i is the board number (0-n) 1878 * Inputs: i is the board number (0-n)
1800 */ 1879 */
1801__init int register_PCI(int i, struct pci_dev *dev) 1880static __init int register_PCI(int i, struct pci_dev *dev)
1802{ 1881{
1803 int num_aiops, aiop, max_num_aiops, num_chan, chan; 1882 int num_aiops, aiop, max_num_aiops, num_chan, chan;
1804 unsigned int aiopio[MAX_AIOPS_PER_BOARD]; 1883 unsigned int aiopio[MAX_AIOPS_PER_BOARD];
@@ -2453,72 +2532,6 @@ static void rp_cleanup_module(void)
2453} 2532}
2454#endif 2533#endif
2455 2534
2456#ifndef TRUE
2457#define TRUE 1
2458#endif
2459
2460#ifndef FALSE
2461#define FALSE 0
2462#endif
2463
2464static Byte_t RData[RDATASIZE] = {
2465 0x00, 0x09, 0xf6, 0x82,
2466 0x02, 0x09, 0x86, 0xfb,
2467 0x04, 0x09, 0x00, 0x0a,
2468 0x06, 0x09, 0x01, 0x0a,
2469 0x08, 0x09, 0x8a, 0x13,
2470 0x0a, 0x09, 0xc5, 0x11,
2471 0x0c, 0x09, 0x86, 0x85,
2472 0x0e, 0x09, 0x20, 0x0a,
2473 0x10, 0x09, 0x21, 0x0a,
2474 0x12, 0x09, 0x41, 0xff,
2475 0x14, 0x09, 0x82, 0x00,
2476 0x16, 0x09, 0x82, 0x7b,
2477 0x18, 0x09, 0x8a, 0x7d,
2478 0x1a, 0x09, 0x88, 0x81,
2479 0x1c, 0x09, 0x86, 0x7a,
2480 0x1e, 0x09, 0x84, 0x81,
2481 0x20, 0x09, 0x82, 0x7c,
2482 0x22, 0x09, 0x0a, 0x0a
2483};
2484
2485static Byte_t RRegData[RREGDATASIZE] = {
2486 0x00, 0x09, 0xf6, 0x82, /* 00: Stop Rx processor */
2487 0x08, 0x09, 0x8a, 0x13, /* 04: Tx software flow control */
2488 0x0a, 0x09, 0xc5, 0x11, /* 08: XON char */
2489 0x0c, 0x09, 0x86, 0x85, /* 0c: XANY */
2490 0x12, 0x09, 0x41, 0xff, /* 10: Rx mask char */
2491 0x14, 0x09, 0x82, 0x00, /* 14: Compare/Ignore #0 */
2492 0x16, 0x09, 0x82, 0x7b, /* 18: Compare #1 */
2493 0x18, 0x09, 0x8a, 0x7d, /* 1c: Compare #2 */
2494 0x1a, 0x09, 0x88, 0x81, /* 20: Interrupt #1 */
2495 0x1c, 0x09, 0x86, 0x7a, /* 24: Ignore/Replace #1 */
2496 0x1e, 0x09, 0x84, 0x81, /* 28: Interrupt #2 */
2497 0x20, 0x09, 0x82, 0x7c, /* 2c: Ignore/Replace #2 */
2498 0x22, 0x09, 0x0a, 0x0a /* 30: Rx FIFO Enable */
2499};
2500
2501CONTROLLER_T sController[CTL_SIZE] = {
2502 {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
2503 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
2504 {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
2505 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
2506 {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
2507 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
2508 {-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
2509 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}}
2510};
2511
2512Byte_t sBitMapClrTbl[8] = {
2513 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f
2514};
2515
2516Byte_t sBitMapSetTbl[8] = {
2517 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
2518};
2519
2520int sClockPrescale = 0x14;
2521
2522/*************************************************************************** 2535/***************************************************************************
2523Function: sInitController 2536Function: sInitController
2524Purpose: Initialization of controller global registers and controller 2537Purpose: Initialization of controller global registers and controller
@@ -2554,22 +2567,22 @@ Call: sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize,
2554 FREQ_4HZ - 4 Hertz 2567 FREQ_4HZ - 4 Hertz
2555 If IRQNum is set to 0 the Frequency parameter is 2568 If IRQNum is set to 0 the Frequency parameter is
2556 overidden, it is forced to a value of FREQ_DIS. 2569 overidden, it is forced to a value of FREQ_DIS.
2557 int PeriodicOnly: TRUE if all interrupts except the periodic 2570 int PeriodicOnly: 1 if all interrupts except the periodic
2558 interrupt are to be blocked. 2571 interrupt are to be blocked.
2559 FALSE is both the periodic interrupt and 2572 0 is both the periodic interrupt and
2560 other channel interrupts are allowed. 2573 other channel interrupts are allowed.
2561 If IRQNum is set to 0 the PeriodicOnly parameter is 2574 If IRQNum is set to 0 the PeriodicOnly parameter is
2562 overidden, it is forced to a value of FALSE. 2575 overidden, it is forced to a value of 0.
2563Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller 2576Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
2564 initialization failed. 2577 initialization failed.
2565 2578
2566Comments: 2579Comments:
2567 If periodic interrupts are to be disabled but AIOP interrupts 2580 If periodic interrupts are to be disabled but AIOP interrupts
2568 are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE. 2581 are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
2569 2582
2570 If interrupts are to be completely disabled set IRQNum to 0. 2583 If interrupts are to be completely disabled set IRQNum to 0.
2571 2584
2572 Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an 2585 Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
2573 invalid combination. 2586 invalid combination.
2574 2587
2575 This function performs initialization of global interrupt modes, 2588 This function performs initialization of global interrupt modes,
@@ -2589,9 +2602,9 @@ Warnings: No range checking on any of the parameters is done.
2589 After this function all AIOPs on the controller are disabled, 2602 After this function all AIOPs on the controller are disabled,
2590 they can be enabled with sEnAiop(). 2603 they can be enabled with sEnAiop().
2591*/ 2604*/
2592int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO, 2605static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
2593 ByteIO_t * AiopIOList, int AiopIOListSize, int IRQNum, 2606 ByteIO_t * AiopIOList, int AiopIOListSize,
2594 Byte_t Frequency, int PeriodicOnly) 2607 int IRQNum, Byte_t Frequency, int PeriodicOnly)
2595{ 2608{
2596 int i; 2609 int i;
2597 ByteIO_t io; 2610 ByteIO_t io;
@@ -2687,22 +2700,22 @@ Call: sPCIInitController(CtlP,CtlNum,AiopIOList,AiopIOListSize,
2687 FREQ_4HZ - 4 Hertz 2700 FREQ_4HZ - 4 Hertz
2688 If IRQNum is set to 0 the Frequency parameter is 2701 If IRQNum is set to 0 the Frequency parameter is
2689 overidden, it is forced to a value of FREQ_DIS. 2702 overidden, it is forced to a value of FREQ_DIS.
2690 int PeriodicOnly: TRUE if all interrupts except the periodic 2703 int PeriodicOnly: 1 if all interrupts except the periodic
2691 interrupt are to be blocked. 2704 interrupt are to be blocked.
2692 FALSE is both the periodic interrupt and 2705 0 is both the periodic interrupt and
2693 other channel interrupts are allowed. 2706 other channel interrupts are allowed.
2694 If IRQNum is set to 0 the PeriodicOnly parameter is 2707 If IRQNum is set to 0 the PeriodicOnly parameter is
2695 overidden, it is forced to a value of FALSE. 2708 overidden, it is forced to a value of 0.
2696Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller 2709Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller
2697 initialization failed. 2710 initialization failed.
2698 2711
2699Comments: 2712Comments:
2700 If periodic interrupts are to be disabled but AIOP interrupts 2713 If periodic interrupts are to be disabled but AIOP interrupts
2701 are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE. 2714 are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
2702 2715
2703 If interrupts are to be completely disabled set IRQNum to 0. 2716 If interrupts are to be completely disabled set IRQNum to 0.
2704 2717
2705 Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an 2718 Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
2706 invalid combination. 2719 invalid combination.
2707 2720
2708 This function performs initialization of global interrupt modes, 2721 This function performs initialization of global interrupt modes,
@@ -2722,11 +2735,11 @@ Warnings: No range checking on any of the parameters is done.
2722 After this function all AIOPs on the controller are disabled, 2735 After this function all AIOPs on the controller are disabled,
2723 they can be enabled with sEnAiop(). 2736 they can be enabled with sEnAiop().
2724*/ 2737*/
2725int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum, 2738static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
2726 ByteIO_t * AiopIOList, int AiopIOListSize, 2739 ByteIO_t * AiopIOList, int AiopIOListSize,
2727 WordIO_t ConfigIO, int IRQNum, Byte_t Frequency, 2740 WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
2728 int PeriodicOnly, int altChanRingIndicator, 2741 int PeriodicOnly, int altChanRingIndicator,
2729 int UPCIRingInd) 2742 int UPCIRingInd)
2730{ 2743{
2731 int i; 2744 int i;
2732 ByteIO_t io; 2745 ByteIO_t io;
@@ -2784,7 +2797,7 @@ Return: int: Flag AIOPID_XXXX if a valid AIOP is found, where X
2784Warnings: No context switches are allowed while executing this function. 2797Warnings: No context switches are allowed while executing this function.
2785 2798
2786*/ 2799*/
2787int sReadAiopID(ByteIO_t io) 2800static int sReadAiopID(ByteIO_t io)
2788{ 2801{
2789 Byte_t AiopID; /* ID byte from AIOP */ 2802 Byte_t AiopID; /* ID byte from AIOP */
2790 2803
@@ -2810,7 +2823,7 @@ Comments: The number of channels is determined by write/reads from identical
2810 AIOP, otherwise it is an 8 channel. 2823 AIOP, otherwise it is an 8 channel.
2811Warnings: No context switches are allowed while executing this function. 2824Warnings: No context switches are allowed while executing this function.
2812*/ 2825*/
2813int sReadAiopNumChan(WordIO_t io) 2826static int sReadAiopNumChan(WordIO_t io)
2814{ 2827{
2815 Word_t x; 2828 Word_t x;
2816 static Byte_t R[4] = { 0x00, 0x00, 0x34, 0x12 }; 2829 static Byte_t R[4] = { 0x00, 0x00, 0x34, 0x12 };
@@ -2834,15 +2847,15 @@ Call: sInitChan(CtlP,ChP,AiopNum,ChanNum)
2834 CHANNEL_T *ChP; Ptr to channel structure 2847 CHANNEL_T *ChP; Ptr to channel structure
2835 int AiopNum; AIOP number within controller 2848 int AiopNum; AIOP number within controller
2836 int ChanNum; Channel number within AIOP 2849 int ChanNum; Channel number within AIOP
2837Return: int: TRUE if initialization succeeded, FALSE if it fails because channel 2850Return: int: 1 if initialization succeeded, 0 if it fails because channel
2838 number exceeds number of channels available in AIOP. 2851 number exceeds number of channels available in AIOP.
2839Comments: This function must be called before a channel can be used. 2852Comments: This function must be called before a channel can be used.
2840Warnings: No range checking on any of the parameters is done. 2853Warnings: No range checking on any of the parameters is done.
2841 2854
2842 No context switches are allowed while executing this function. 2855 No context switches are allowed while executing this function.
2843*/ 2856*/
2844int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum, 2857static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
2845 int ChanNum) 2858 int ChanNum)
2846{ 2859{
2847 int i; 2860 int i;
2848 WordIO_t AiopIO; 2861 WordIO_t AiopIO;
@@ -2853,7 +2866,7 @@ int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
2853 int brd9600; 2866 int brd9600;
2854 2867
2855 if (ChanNum >= CtlP->AiopNumChan[AiopNum]) 2868 if (ChanNum >= CtlP->AiopNumChan[AiopNum])
2856 return (FALSE); /* exceeds num chans in AIOP */ 2869 return 0; /* exceeds num chans in AIOP */
2857 2870
2858 /* Channel, AIOP, and controller identifiers */ 2871 /* Channel, AIOP, and controller identifiers */
2859 ChP->CtlP = CtlP; 2872 ChP->CtlP = CtlP;
@@ -2968,7 +2981,7 @@ int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
2968 ChP->TxPrioBuf = ChOff + _TXP_BUF; 2981 ChP->TxPrioBuf = ChOff + _TXP_BUF;
2969 sEnRxProcessor(ChP); /* start the Rx processor */ 2982 sEnRxProcessor(ChP); /* start the Rx processor */
2970 2983
2971 return (TRUE); 2984 return 1;
2972} 2985}
2973 2986
2974/*************************************************************************** 2987/***************************************************************************
@@ -2989,7 +3002,7 @@ Warnings: No context switches are allowed while executing this function.
2989 After calling this function a delay of 4 uS is required to ensure 3002 After calling this function a delay of 4 uS is required to ensure
2990 that the receive processor is no longer processing this channel. 3003 that the receive processor is no longer processing this channel.
2991*/ 3004*/
2992void sStopRxProcessor(CHANNEL_T * ChP) 3005static void sStopRxProcessor(CHANNEL_T * ChP)
2993{ 3006{
2994 Byte_t R[4]; 3007 Byte_t R[4];
2995 3008
@@ -3014,18 +3027,18 @@ Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
3014 this function. 3027 this function.
3015Warnings: No context switches are allowed while executing this function. 3028Warnings: No context switches are allowed while executing this function.
3016*/ 3029*/
3017void sFlushRxFIFO(CHANNEL_T * ChP) 3030static void sFlushRxFIFO(CHANNEL_T * ChP)
3018{ 3031{
3019 int i; 3032 int i;
3020 Byte_t Ch; /* channel number within AIOP */ 3033 Byte_t Ch; /* channel number within AIOP */
3021 int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */ 3034 int RxFIFOEnabled; /* 1 if Rx FIFO enabled */
3022 3035
3023 if (sGetRxCnt(ChP) == 0) /* Rx FIFO empty */ 3036 if (sGetRxCnt(ChP) == 0) /* Rx FIFO empty */
3024 return; /* don't need to flush */ 3037 return; /* don't need to flush */
3025 3038
3026 RxFIFOEnabled = FALSE; 3039 RxFIFOEnabled = 0;
3027 if (ChP->R[0x32] == 0x08) { /* Rx FIFO is enabled */ 3040 if (ChP->R[0x32] == 0x08) { /* Rx FIFO is enabled */
3028 RxFIFOEnabled = TRUE; 3041 RxFIFOEnabled = 1;
3029 sDisRxFIFO(ChP); /* disable it */ 3042 sDisRxFIFO(ChP); /* disable it */
3030 for (i = 0; i < 2000 / 200; i++) /* delay 2 uS to allow proc to disable FIFO */ 3043 for (i = 0; i < 2000 / 200; i++) /* delay 2 uS to allow proc to disable FIFO */
3031 sInB(ChP->IntChan); /* depends on bus i/o timing */ 3044 sInB(ChP->IntChan); /* depends on bus i/o timing */
@@ -3056,18 +3069,18 @@ Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
3056 this function. 3069 this function.
3057Warnings: No context switches are allowed while executing this function. 3070Warnings: No context switches are allowed while executing this function.
3058*/ 3071*/
3059void sFlushTxFIFO(CHANNEL_T * ChP) 3072static void sFlushTxFIFO(CHANNEL_T * ChP)
3060{ 3073{
3061 int i; 3074 int i;
3062 Byte_t Ch; /* channel number within AIOP */ 3075 Byte_t Ch; /* channel number within AIOP */
3063 int TxEnabled; /* TRUE if transmitter enabled */ 3076 int TxEnabled; /* 1 if transmitter enabled */
3064 3077
3065 if (sGetTxCnt(ChP) == 0) /* Tx FIFO empty */ 3078 if (sGetTxCnt(ChP) == 0) /* Tx FIFO empty */
3066 return; /* don't need to flush */ 3079 return; /* don't need to flush */
3067 3080
3068 TxEnabled = FALSE; 3081 TxEnabled = 0;
3069 if (ChP->TxControl[3] & TX_ENABLE) { 3082 if (ChP->TxControl[3] & TX_ENABLE) {
3070 TxEnabled = TRUE; 3083 TxEnabled = 1;
3071 sDisTransmit(ChP); /* disable transmitter */ 3084 sDisTransmit(ChP); /* disable transmitter */
3072 } 3085 }
3073 sStopRxProcessor(ChP); /* stop Rx processor */ 3086 sStopRxProcessor(ChP); /* stop Rx processor */
@@ -3096,7 +3109,7 @@ Comments: The priority byte is transmitted before any data in the Tx FIFO.
3096 3109
3097Warnings: No context switches are allowed while executing this function. 3110Warnings: No context switches are allowed while executing this function.
3098*/ 3111*/
3099int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data) 3112static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data)
3100{ 3113{
3101 Byte_t DWBuf[4]; /* buffer for double word writes */ 3114 Byte_t DWBuf[4]; /* buffer for double word writes */
3102 Word_t *WordPtr; /* must be far because Win SS != DS */ 3115 Word_t *WordPtr; /* must be far because Win SS != DS */
@@ -3158,7 +3171,7 @@ Comments: If an interrupt enable flag is set in Flags, that interrupt will be
3158 enable channel interrupts. This would allow the global interrupt 3171 enable channel interrupts. This would allow the global interrupt
3159 status register to be used to determine which AIOPs need service. 3172 status register to be used to determine which AIOPs need service.
3160*/ 3173*/
3161void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags) 3174static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags)
3162{ 3175{
3163 Byte_t Mask; /* Interrupt Mask Register */ 3176 Byte_t Mask; /* Interrupt Mask Register */
3164 3177
@@ -3202,7 +3215,7 @@ Comments: If an interrupt flag is set in Flags, that interrupt will be
3202 this channel's bit from being set in the AIOP's Interrupt Channel 3215 this channel's bit from being set in the AIOP's Interrupt Channel
3203 Register. 3216 Register.
3204*/ 3217*/
3205void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags) 3218static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags)
3206{ 3219{
3207 Byte_t Mask; /* Interrupt Mask Register */ 3220 Byte_t Mask; /* Interrupt Mask Register */
3208 3221
@@ -3218,7 +3231,7 @@ void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags)
3218 } 3231 }
3219} 3232}
3220 3233
3221void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode) 3234static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode)
3222{ 3235{
3223 sOutB(ChP->CtlP->AiopIO[2], (mode & 0x18) | ChP->ChanNum); 3236 sOutB(ChP->CtlP->AiopIO[2], (mode & 0x18) | ChP->ChanNum);
3224} 3237}
@@ -3227,7 +3240,7 @@ void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode)
3227 * Not an official SSCI function, but how to reset RocketModems. 3240 * Not an official SSCI function, but how to reset RocketModems.
3228 * ISA bus version 3241 * ISA bus version
3229 */ 3242 */
3230void sModemReset(CONTROLLER_T * CtlP, int chan, int on) 3243static void sModemReset(CONTROLLER_T * CtlP, int chan, int on)
3231{ 3244{
3232 ByteIO_t addr; 3245 ByteIO_t addr;
3233 Byte_t val; 3246 Byte_t val;
@@ -3252,7 +3265,7 @@ void sModemReset(CONTROLLER_T * CtlP, int chan, int on)
3252 * Not an official SSCI function, but how to reset RocketModems. 3265 * Not an official SSCI function, but how to reset RocketModems.
3253 * PCI bus version 3266 * PCI bus version
3254 */ 3267 */
3255void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on) 3268static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on)
3256{ 3269{
3257 ByteIO_t addr; 3270 ByteIO_t addr;
3258 3271
diff --git a/drivers/char/rocket_int.h b/drivers/char/rocket_int.h
index 802687290ee1..3a8bcc85bc14 100644
--- a/drivers/char/rocket_int.h
+++ b/drivers/char/rocket_int.h
@@ -1130,46 +1130,6 @@ Warnings: This function writes the data byte without checking to see if
1130*/ 1130*/
1131#define sWriteTxByte(IO,DATA) sOutB(IO,DATA) 1131#define sWriteTxByte(IO,DATA) sOutB(IO,DATA)
1132 1132
1133int sInitController(CONTROLLER_T * CtlP,
1134 int CtlNum,
1135 ByteIO_t MudbacIO,
1136 ByteIO_t * AiopIOList,
1137 int AiopIOListSize,
1138 int IRQNum, Byte_t Frequency, int PeriodicOnly);
1139
1140int sPCIInitController(CONTROLLER_T * CtlP,
1141 int CtlNum,
1142 ByteIO_t * AiopIOList,
1143 int AiopIOListSize,
1144 WordIO_t ConfigIO,
1145 int IRQNum,
1146 Byte_t Frequency,
1147 int PeriodicOnly,
1148 int altChanRingIndicator, int UPCIRingInd);
1149
1150int sReadAiopID(ByteIO_t io);
1151int sReadAiopNumChan(WordIO_t io);
1152int sInitChan(CONTROLLER_T * CtlP,
1153 CHANNEL_T * ChP, int AiopNum, int ChanNum);
1154Byte_t sGetRxErrStatus(CHANNEL_T * ChP);
1155void sStopRxProcessor(CHANNEL_T * ChP);
1156void sStopSWInFlowCtl(CHANNEL_T * ChP);
1157void sFlushRxFIFO(CHANNEL_T * ChP);
1158void sFlushTxFIFO(CHANNEL_T * ChP);
1159int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data);
1160void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags);
1161void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags);
1162void sModemReset(CONTROLLER_T * CtlP, int chan, int on);
1163void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on);
1164void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode);
1165
1166extern Byte_t R[RDATASIZE];
1167extern CONTROLLER_T sController[CTL_SIZE];
1168extern Byte_t sIRQMap[16];
1169extern Byte_t sBitMapClrTbl[8];
1170extern Byte_t sBitMapSetTbl[8];
1171extern int sClockPrescale;
1172
1173/* 1133/*
1174 * Begin Linux specific definitions for the Rocketport driver 1134 * Begin Linux specific definitions for the Rocketport driver
1175 * 1135 *
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index ff4f09804865..cd4fe8b1709f 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -78,6 +78,7 @@
78#include <linux/sysctl.h> 78#include <linux/sysctl.h>
79#include <linux/wait.h> 79#include <linux/wait.h>
80#include <linux/bcd.h> 80#include <linux/bcd.h>
81#include <linux/delay.h>
81 82
82#include <asm/current.h> 83#include <asm/current.h>
83#include <asm/uaccess.h> 84#include <asm/uaccess.h>
@@ -894,7 +895,6 @@ static int __init rtc_init(void)
894 struct proc_dir_entry *ent; 895 struct proc_dir_entry *ent;
895#if defined(__alpha__) || defined(__mips__) 896#if defined(__alpha__) || defined(__mips__)
896 unsigned int year, ctrl; 897 unsigned int year, ctrl;
897 unsigned long uip_watchdog;
898 char *guess = NULL; 898 char *guess = NULL;
899#endif 899#endif
900#ifdef __sparc__ 900#ifdef __sparc__
@@ -1000,12 +1000,8 @@ no_irq:
1000 /* Each operating system on an Alpha uses its own epoch. 1000 /* Each operating system on an Alpha uses its own epoch.
1001 Let's try to guess which one we are using now. */ 1001 Let's try to guess which one we are using now. */
1002 1002
1003 uip_watchdog = jiffies;
1004 if (rtc_is_updating() != 0) 1003 if (rtc_is_updating() != 0)
1005 while (jiffies - uip_watchdog < 2*HZ/100) { 1004 msleep(20);
1006 barrier();
1007 cpu_relax();
1008 }
1009 1005
1010 spin_lock_irq(&rtc_lock); 1006 spin_lock_irq(&rtc_lock);
1011 year = CMOS_READ(RTC_YEAR); 1007 year = CMOS_READ(RTC_YEAR);
@@ -1221,7 +1217,7 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
1221 1217
1222 /* 1218 /*
1223 * read RTC once any update in progress is done. The update 1219 * read RTC once any update in progress is done. The update
1224 * can take just over 2ms. We wait 10 to 20ms. There is no need to 1220 * can take just over 2ms. We wait 20ms. There is no need to
1225 * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP. 1221 * to poll-wait (up to 1s - eeccch) for the falling edge of RTC_UIP.
1226 * If you need to know *exactly* when a second has started, enable 1222 * If you need to know *exactly* when a second has started, enable
1227 * periodic update complete interrupts, (via ioctl) and then 1223 * periodic update complete interrupts, (via ioctl) and then
@@ -1229,11 +1225,10 @@ void rtc_get_rtc_time(struct rtc_time *rtc_tm)
1229 * Once the read clears, read the RTC time (again via ioctl). Easy. 1225 * Once the read clears, read the RTC time (again via ioctl). Easy.
1230 */ 1226 */
1231 1227
1232 if (rtc_is_updating() != 0) 1228 while (rtc_is_updating() != 0 && jiffies - uip_watchdog < 2*HZ/100) {
1233 while (jiffies - uip_watchdog < 2*HZ/100) { 1229 barrier();
1234 barrier(); 1230 cpu_relax();
1235 cpu_relax(); 1231 }
1236 }
1237 1232
1238 /* 1233 /*
1239 * Only the values that we read from the RTC are set. We leave 1234 * Only the values that we read from the RTC are set. We leave
diff --git a/drivers/char/snsc.c b/drivers/char/snsc.c
index e3c0b52d943f..261a41bf6d02 100644
--- a/drivers/char/snsc.c
+++ b/drivers/char/snsc.c
@@ -357,6 +357,8 @@ static struct file_operations scdrv_fops = {
357 .release = scdrv_release, 357 .release = scdrv_release,
358}; 358};
359 359
360static struct class *snsc_class;
361
360/* 362/*
361 * scdrv_init 363 * scdrv_init
362 * 364 *
@@ -372,7 +374,6 @@ scdrv_init(void)
372 char *devnamep; 374 char *devnamep;
373 struct sysctl_data_s *scd; 375 struct sysctl_data_s *scd;
374 void *salbuf; 376 void *salbuf;
375 struct class_simple *snsc_class;
376 dev_t first_dev, dev; 377 dev_t first_dev, dev;
377 nasid_t event_nasid = ia64_sn_get_console_nasid(); 378 nasid_t event_nasid = ia64_sn_get_console_nasid();
378 379
@@ -382,7 +383,7 @@ scdrv_init(void)
382 __FUNCTION__); 383 __FUNCTION__);
383 return -ENODEV; 384 return -ENODEV;
384 } 385 }
385 snsc_class = class_simple_create(THIS_MODULE, SYSCTL_BASENAME); 386 snsc_class = class_create(THIS_MODULE, SYSCTL_BASENAME);
386 387
387 for (cnode = 0; cnode < numionodes; cnode++) { 388 for (cnode = 0; cnode < numionodes; cnode++) {
388 geoid = cnodeid_get_geoid(cnode); 389 geoid = cnodeid_get_geoid(cnode);
@@ -436,7 +437,7 @@ scdrv_init(void)
436 continue; 437 continue;
437 } 438 }
438 439
439 class_simple_device_add(snsc_class, dev, NULL, 440 class_device_create(snsc_class, dev, NULL,
440 "%s", devname); 441 "%s", devname);
441 442
442 ia64_sn_irtr_intr_enable(scd->scd_nasid, 443 ia64_sn_irtr_intr_enable(scd->scd_nasid,
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index fd042060809a..cefbe985e55c 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -439,6 +439,11 @@ static struct {
439 { 0, 0 }, 439 { 0, 0 },
440}; 440};
441 441
442struct sonypi_keypress {
443 struct input_dev *dev;
444 int key;
445};
446
442static struct sonypi_device { 447static struct sonypi_device {
443 struct pci_dev *dev; 448 struct pci_dev *dev;
444 struct platform_device *pdev; 449 struct platform_device *pdev;
@@ -710,22 +715,61 @@ static void sonypi_setbluetoothpower(u8 state)
710 715
711static void input_keyrelease(void *data) 716static void input_keyrelease(void *data)
712{ 717{
713 struct input_dev *input_dev; 718 struct sonypi_keypress kp;
714 int key;
715
716 while (1) {
717 if (kfifo_get(sonypi_device.input_fifo,
718 (unsigned char *)&input_dev,
719 sizeof(input_dev)) != sizeof(input_dev))
720 return;
721 if (kfifo_get(sonypi_device.input_fifo,
722 (unsigned char *)&key,
723 sizeof(key)) != sizeof(key))
724 return;
725 719
720 while (kfifo_get(sonypi_device.input_fifo, (unsigned char *)&kp,
721 sizeof(kp)) == sizeof(kp)) {
726 msleep(10); 722 msleep(10);
727 input_report_key(input_dev, key, 0); 723 input_report_key(kp.dev, kp.key, 0);
728 input_sync(input_dev); 724 input_sync(kp.dev);
725 }
726}
727
728static void sonypi_report_input_event(u8 event)
729{
730 struct input_dev *jog_dev = &sonypi_device.input_jog_dev;
731 struct input_dev *key_dev = &sonypi_device.input_key_dev;
732 struct sonypi_keypress kp = { NULL };
733 int i;
734
735 switch (event) {
736 case SONYPI_EVENT_JOGDIAL_UP:
737 case SONYPI_EVENT_JOGDIAL_UP_PRESSED:
738 input_report_rel(jog_dev, REL_WHEEL, 1);
739 input_sync(jog_dev);
740 break;
741
742 case SONYPI_EVENT_JOGDIAL_DOWN:
743 case SONYPI_EVENT_JOGDIAL_DOWN_PRESSED:
744 input_report_rel(jog_dev, REL_WHEEL, -1);
745 input_sync(jog_dev);
746 break;
747
748 case SONYPI_EVENT_JOGDIAL_PRESSED:
749 kp.key = BTN_MIDDLE;
750 kp.dev = jog_dev;
751 break;
752
753 case SONYPI_EVENT_FNKEY_RELEASED:
754 /* Nothing, not all VAIOs generate this event */
755 break;
756
757 default:
758 for (i = 0; sonypi_inputkeys[i].sonypiev; i++)
759 if (event == sonypi_inputkeys[i].sonypiev) {
760 kp.dev = key_dev;
761 kp.key = sonypi_inputkeys[i].inputev;
762 break;
763 }
764 break;
765 }
766
767 if (kp.dev) {
768 input_report_key(kp.dev, kp.key, 1);
769 input_sync(kp.dev);
770 kfifo_put(sonypi_device.input_fifo,
771 (unsigned char *)&kp, sizeof(kp));
772 schedule_work(&sonypi_device.input_work);
729 } 773 }
730} 774}
731 775
@@ -768,51 +812,8 @@ found:
768 printk(KERN_INFO 812 printk(KERN_INFO
769 "sonypi: event port1=0x%02x,port2=0x%02x\n", v1, v2); 813 "sonypi: event port1=0x%02x,port2=0x%02x\n", v1, v2);
770 814
771 if (useinput) { 815 if (useinput)
772 struct input_dev *input_jog_dev = &sonypi_device.input_jog_dev; 816 sonypi_report_input_event(event);
773 struct input_dev *input_key_dev = &sonypi_device.input_key_dev;
774 switch (event) {
775 case SONYPI_EVENT_JOGDIAL_UP:
776 case SONYPI_EVENT_JOGDIAL_UP_PRESSED:
777 input_report_rel(input_jog_dev, REL_WHEEL, 1);
778 break;
779 case SONYPI_EVENT_JOGDIAL_DOWN:
780 case SONYPI_EVENT_JOGDIAL_DOWN_PRESSED:
781 input_report_rel(input_jog_dev, REL_WHEEL, -1);
782 break;
783 case SONYPI_EVENT_JOGDIAL_PRESSED: {
784 int key = BTN_MIDDLE;
785 input_report_key(input_jog_dev, key, 1);
786 kfifo_put(sonypi_device.input_fifo,
787 (unsigned char *)&input_jog_dev,
788 sizeof(input_jog_dev));
789 kfifo_put(sonypi_device.input_fifo,
790 (unsigned char *)&key, sizeof(key));
791 break;
792 }
793 case SONYPI_EVENT_FNKEY_RELEASED:
794 /* Nothing, not all VAIOs generate this event */
795 break;
796 }
797 input_sync(input_jog_dev);
798
799 for (i = 0; sonypi_inputkeys[i].sonypiev; i++) {
800 int key;
801
802 if (event != sonypi_inputkeys[i].sonypiev)
803 continue;
804
805 key = sonypi_inputkeys[i].inputev;
806 input_report_key(input_key_dev, key, 1);
807 kfifo_put(sonypi_device.input_fifo,
808 (unsigned char *)&input_key_dev,
809 sizeof(input_key_dev));
810 kfifo_put(sonypi_device.input_fifo,
811 (unsigned char *)&key, sizeof(key));
812 }
813 input_sync(input_key_dev);
814 schedule_work(&sonypi_device.input_work);
815 }
816 817
817 kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event)); 818 kfifo_put(sonypi_device.fifo, (unsigned char *)&event, sizeof(event));
818 kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN); 819 kill_fasync(&sonypi_device.fifo_async, SIGIO, POLL_IN);
@@ -1227,14 +1228,7 @@ static int __devinit sonypi_probe(void)
1227 sonypi_device.input_jog_dev.keybit[LONG(BTN_MOUSE)] = 1228 sonypi_device.input_jog_dev.keybit[LONG(BTN_MOUSE)] =
1228 BIT(BTN_MIDDLE); 1229 BIT(BTN_MIDDLE);
1229 sonypi_device.input_jog_dev.relbit[0] = BIT(REL_WHEEL); 1230 sonypi_device.input_jog_dev.relbit[0] = BIT(REL_WHEEL);
1230 sonypi_device.input_jog_dev.name = 1231 sonypi_device.input_jog_dev.name = SONYPI_JOG_INPUTNAME;
1231 kmalloc(sizeof(SONYPI_JOG_INPUTNAME), GFP_KERNEL);
1232 if (!sonypi_device.input_jog_dev.name) {
1233 printk(KERN_ERR "sonypi: kmalloc failed\n");
1234 ret = -ENOMEM;
1235 goto out_inkmallocinput1;
1236 }
1237 sprintf(sonypi_device.input_jog_dev.name, SONYPI_JOG_INPUTNAME);
1238 sonypi_device.input_jog_dev.id.bustype = BUS_ISA; 1232 sonypi_device.input_jog_dev.id.bustype = BUS_ISA;
1239 sonypi_device.input_jog_dev.id.vendor = PCI_VENDOR_ID_SONY; 1233 sonypi_device.input_jog_dev.id.vendor = PCI_VENDOR_ID_SONY;
1240 1234
@@ -1248,14 +1242,7 @@ static int __devinit sonypi_probe(void)
1248 if (sonypi_inputkeys[i].inputev) 1242 if (sonypi_inputkeys[i].inputev)
1249 set_bit(sonypi_inputkeys[i].inputev, 1243 set_bit(sonypi_inputkeys[i].inputev,
1250 sonypi_device.input_key_dev.keybit); 1244 sonypi_device.input_key_dev.keybit);
1251 sonypi_device.input_key_dev.name = 1245 sonypi_device.input_key_dev.name = SONYPI_KEY_INPUTNAME;
1252 kmalloc(sizeof(SONYPI_KEY_INPUTNAME), GFP_KERNEL);
1253 if (!sonypi_device.input_key_dev.name) {
1254 printk(KERN_ERR "sonypi: kmalloc failed\n");
1255 ret = -ENOMEM;
1256 goto out_inkmallocinput2;
1257 }
1258 sprintf(sonypi_device.input_key_dev.name, SONYPI_KEY_INPUTNAME);
1259 sonypi_device.input_key_dev.id.bustype = BUS_ISA; 1246 sonypi_device.input_key_dev.id.bustype = BUS_ISA;
1260 sonypi_device.input_key_dev.id.vendor = PCI_VENDOR_ID_SONY; 1247 sonypi_device.input_key_dev.id.vendor = PCI_VENDOR_ID_SONY;
1261 1248
@@ -1313,11 +1300,7 @@ out_platformdev:
1313 kfifo_free(sonypi_device.input_fifo); 1300 kfifo_free(sonypi_device.input_fifo);
1314out_infifo: 1301out_infifo:
1315 input_unregister_device(&sonypi_device.input_key_dev); 1302 input_unregister_device(&sonypi_device.input_key_dev);
1316 kfree(sonypi_device.input_key_dev.name);
1317out_inkmallocinput2:
1318 input_unregister_device(&sonypi_device.input_jog_dev); 1303 input_unregister_device(&sonypi_device.input_jog_dev);
1319 kfree(sonypi_device.input_jog_dev.name);
1320out_inkmallocinput1:
1321 free_irq(sonypi_device.irq, sonypi_irq); 1304 free_irq(sonypi_device.irq, sonypi_irq);
1322out_reqirq: 1305out_reqirq:
1323 release_region(sonypi_device.ioport1, sonypi_device.region_size); 1306 release_region(sonypi_device.ioport1, sonypi_device.region_size);
@@ -1337,13 +1320,14 @@ static void __devexit sonypi_remove(void)
1337{ 1320{
1338 sonypi_disable(); 1321 sonypi_disable();
1339 1322
1323 synchronize_sched(); /* Allow sonypi interrupt to complete. */
1324 flush_scheduled_work();
1325
1340 platform_device_unregister(sonypi_device.pdev); 1326 platform_device_unregister(sonypi_device.pdev);
1341 1327
1342 if (useinput) { 1328 if (useinput) {
1343 input_unregister_device(&sonypi_device.input_key_dev); 1329 input_unregister_device(&sonypi_device.input_key_dev);
1344 kfree(sonypi_device.input_key_dev.name);
1345 input_unregister_device(&sonypi_device.input_jog_dev); 1330 input_unregister_device(&sonypi_device.input_jog_dev);
1346 kfree(sonypi_device.input_jog_dev.name);
1347 kfifo_free(sonypi_device.input_fifo); 1331 kfifo_free(sonypi_device.input_fifo);
1348 } 1332 }
1349 1333
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c
index b8899f560b5e..951545a6ef2d 100644
--- a/drivers/char/stallion.c
+++ b/drivers/char/stallion.c
@@ -719,7 +719,7 @@ static struct file_operations stl_fsiomem = {
719 719
720/*****************************************************************************/ 720/*****************************************************************************/
721 721
722static struct class_simple *stallion_class; 722static struct class *stallion_class;
723 723
724/* 724/*
725 * Loadable module initialization stuff. 725 * Loadable module initialization stuff.
@@ -777,13 +777,13 @@ static void __exit stallion_module_exit(void)
777 } 777 }
778 for (i = 0; i < 4; i++) { 778 for (i = 0; i < 4; i++) {
779 devfs_remove("staliomem/%d", i); 779 devfs_remove("staliomem/%d", i);
780 class_simple_device_remove(MKDEV(STL_SIOMEMMAJOR, i)); 780 class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
781 } 781 }
782 devfs_remove("staliomem"); 782 devfs_remove("staliomem");
783 if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem"))) 783 if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
784 printk("STALLION: failed to un-register serial memory device, " 784 printk("STALLION: failed to un-register serial memory device, "
785 "errno=%d\n", -i); 785 "errno=%d\n", -i);
786 class_simple_destroy(stallion_class); 786 class_destroy(stallion_class);
787 787
788 if (stl_tmpwritebuf != (char *) NULL) 788 if (stl_tmpwritebuf != (char *) NULL)
789 kfree(stl_tmpwritebuf); 789 kfree(stl_tmpwritebuf);
@@ -3090,12 +3090,12 @@ static int __init stl_init(void)
3090 printk("STALLION: failed to register serial board device\n"); 3090 printk("STALLION: failed to register serial board device\n");
3091 devfs_mk_dir("staliomem"); 3091 devfs_mk_dir("staliomem");
3092 3092
3093 stallion_class = class_simple_create(THIS_MODULE, "staliomem"); 3093 stallion_class = class_create(THIS_MODULE, "staliomem");
3094 for (i = 0; i < 4; i++) { 3094 for (i = 0; i < 4; i++) {
3095 devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i), 3095 devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
3096 S_IFCHR|S_IRUSR|S_IWUSR, 3096 S_IFCHR|S_IRUSR|S_IWUSR,
3097 "staliomem/%d", i); 3097 "staliomem/%d", i);
3098 class_simple_device_add(stallion_class, MKDEV(STL_SIOMEMMAJOR, i), NULL, "staliomem%d", i); 3098 class_device_create(stallion_class, MKDEV(STL_SIOMEMMAJOR, i), NULL, "staliomem%d", i);
3099 } 3099 }
3100 3100
3101 stl_serial->owner = THIS_MODULE; 3101 stl_serial->owner = THIS_MODULE;
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c
index f59f7cbd525b..feb25158c8ee 100644
--- a/drivers/char/sysrq.c
+++ b/drivers/char/sysrq.c
@@ -35,6 +35,7 @@
35#include <linux/spinlock.h> 35#include <linux/spinlock.h>
36#include <linux/vt_kern.h> 36#include <linux/vt_kern.h>
37#include <linux/workqueue.h> 37#include <linux/workqueue.h>
38#include <linux/kexec.h>
38 39
39#include <asm/ptrace.h> 40#include <asm/ptrace.h>
40 41
@@ -94,12 +95,27 @@ static struct sysrq_key_op sysrq_unraw_op = {
94}; 95};
95#endif /* CONFIG_VT */ 96#endif /* CONFIG_VT */
96 97
98#ifdef CONFIG_KEXEC
99/* crashdump sysrq handler */
100static void sysrq_handle_crashdump(int key, struct pt_regs *pt_regs,
101 struct tty_struct *tty)
102{
103 crash_kexec(pt_regs);
104}
105static struct sysrq_key_op sysrq_crashdump_op = {
106 .handler = sysrq_handle_crashdump,
107 .help_msg = "Crashdump",
108 .action_msg = "Trigger a crashdump",
109 .enable_mask = SYSRQ_ENABLE_DUMP,
110};
111#endif
112
97/* reboot sysrq handler */ 113/* reboot sysrq handler */
98static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs, 114static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs,
99 struct tty_struct *tty) 115 struct tty_struct *tty)
100{ 116{
101 local_irq_enable(); 117 local_irq_enable();
102 machine_restart(NULL); 118 emergency_restart();
103} 119}
104 120
105static struct sysrq_key_op sysrq_reboot_op = { 121static struct sysrq_key_op sysrq_reboot_op = {
@@ -212,7 +228,7 @@ static struct sysrq_key_op sysrq_term_op = {
212 228
213static void moom_callback(void *ignored) 229static void moom_callback(void *ignored)
214{ 230{
215 out_of_memory(GFP_KERNEL); 231 out_of_memory(GFP_KERNEL, 0);
216} 232}
217 233
218static DECLARE_WORK(moom_work, moom_callback, NULL); 234static DECLARE_WORK(moom_work, moom_callback, NULL);
@@ -273,8 +289,12 @@ static struct sysrq_key_op *sysrq_key_table[SYSRQ_KEY_TABLE_LENGTH] = {
273 it is handled specially on the sparc 289 it is handled specially on the sparc
274 and will never arrive */ 290 and will never arrive */
275/* b */ &sysrq_reboot_op, 291/* b */ &sysrq_reboot_op,
276/* c */ NULL, 292#ifdef CONFIG_KEXEC
277/* d */ NULL, 293/* c */ &sysrq_crashdump_op,
294#else
295/* c */ NULL,
296#endif
297/* d */ NULL,
278/* e */ &sysrq_term_op, 298/* e */ &sysrq_term_op,
279/* f */ &sysrq_moom_op, 299/* f */ &sysrq_moom_op,
280/* g */ NULL, 300/* g */ NULL,
diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c
index 5413f2908859..eb7058cbf015 100644
--- a/drivers/char/tb0219.c
+++ b/drivers/char/tb0219.c
@@ -24,6 +24,8 @@
24 24
25#include <asm/io.h> 25#include <asm/io.h>
26#include <asm/reboot.h> 26#include <asm/reboot.h>
27#include <asm/vr41xx/giu.h>
28#include <asm/vr41xx/tb0219.h>
27 29
28MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>"); 30MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
29MODULE_DESCRIPTION("TANBAC TB0219 base board driver"); 31MODULE_DESCRIPTION("TANBAC TB0219 base board driver");
@@ -266,6 +268,21 @@ static void tb0219_restart(char *command)
266 tb0219_write(TB0219_RESET, 0); 268 tb0219_write(TB0219_RESET, 0);
267} 269}
268 270
271static void tb0219_pci_irq_init(void)
272{
273 /* PCI Slot 1 */
274 vr41xx_set_irq_trigger(TB0219_PCI_SLOT1_PIN, IRQ_TRIGGER_LEVEL, IRQ_SIGNAL_THROUGH);
275 vr41xx_set_irq_level(TB0219_PCI_SLOT1_PIN, IRQ_LEVEL_LOW);
276
277 /* PCI Slot 2 */
278 vr41xx_set_irq_trigger(TB0219_PCI_SLOT2_PIN, IRQ_TRIGGER_LEVEL, IRQ_SIGNAL_THROUGH);
279 vr41xx_set_irq_level(TB0219_PCI_SLOT2_PIN, IRQ_LEVEL_LOW);
280
281 /* PCI Slot 3 */
282 vr41xx_set_irq_trigger(TB0219_PCI_SLOT3_PIN, IRQ_TRIGGER_LEVEL, IRQ_SIGNAL_THROUGH);
283 vr41xx_set_irq_level(TB0219_PCI_SLOT3_PIN, IRQ_LEVEL_LOW);
284}
285
269static int tb0219_probe(struct device *dev) 286static int tb0219_probe(struct device *dev)
270{ 287{
271 int retval; 288 int retval;
@@ -292,6 +309,8 @@ static int tb0219_probe(struct device *dev)
292 old_machine_restart = _machine_restart; 309 old_machine_restart = _machine_restart;
293 _machine_restart = tb0219_restart; 310 _machine_restart = tb0219_restart;
294 311
312 tb0219_pci_irq_init();
313
295 if (major == 0) { 314 if (major == 0) {
296 major = retval; 315 major = retval;
297 printk(KERN_INFO "TB0219: major number %d\n", major); 316 printk(KERN_INFO "TB0219: major number %d\n", major);
diff --git a/drivers/char/tipar.c b/drivers/char/tipar.c
index 0c5ba9dc9063..ec78d2f161f7 100644
--- a/drivers/char/tipar.c
+++ b/drivers/char/tipar.c
@@ -90,7 +90,7 @@ static int timeout = TIMAXTIME; /* timeout in tenth of seconds */
90static unsigned int tp_count; /* tipar count */ 90static unsigned int tp_count; /* tipar count */
91static unsigned long opened; /* opened devices */ 91static unsigned long opened; /* opened devices */
92 92
93static struct class_simple *tipar_class; 93static struct class *tipar_class;
94 94
95/* --- macros for parport access -------------------------------------- */ 95/* --- macros for parport access -------------------------------------- */
96 96
@@ -396,7 +396,7 @@ static struct file_operations tipar_fops = {
396static int __init 396static int __init
397tipar_setup(char *str) 397tipar_setup(char *str)
398{ 398{
399 int ints[2]; 399 int ints[3];
400 400
401 str = get_options(str, ARRAY_SIZE(ints), ints); 401 str = get_options(str, ARRAY_SIZE(ints), ints);
402 402
@@ -436,7 +436,7 @@ tipar_register(int nr, struct parport *port)
436 goto out; 436 goto out;
437 } 437 }
438 438
439 class_simple_device_add(tipar_class, MKDEV(TIPAR_MAJOR, 439 class_device_create(tipar_class, MKDEV(TIPAR_MAJOR,
440 TIPAR_MINOR + nr), NULL, "par%d", nr); 440 TIPAR_MINOR + nr), NULL, "par%d", nr);
441 /* Use devfs, tree: /dev/ticables/par/[0..2] */ 441 /* Use devfs, tree: /dev/ticables/par/[0..2] */
442 err = devfs_mk_cdev(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr), 442 err = devfs_mk_cdev(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr),
@@ -458,8 +458,8 @@ tipar_register(int nr, struct parport *port)
458 goto out; 458 goto out;
459 459
460out_class: 460out_class:
461 class_simple_device_remove(MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr)); 461 class_device_destroy(tipar_class, MKDEV(TIPAR_MAJOR, TIPAR_MINOR + nr));
462 class_simple_destroy(tipar_class); 462 class_destroy(tipar_class);
463out: 463out:
464 return err; 464 return err;
465} 465}
@@ -505,7 +505,7 @@ tipar_init_module(void)
505 /* Use devfs with tree: /dev/ticables/par/[0..2] */ 505 /* Use devfs with tree: /dev/ticables/par/[0..2] */
506 devfs_mk_dir("ticables/par"); 506 devfs_mk_dir("ticables/par");
507 507
508 tipar_class = class_simple_create(THIS_MODULE, "ticables"); 508 tipar_class = class_create(THIS_MODULE, "ticables");
509 if (IS_ERR(tipar_class)) { 509 if (IS_ERR(tipar_class)) {
510 err = PTR_ERR(tipar_class); 510 err = PTR_ERR(tipar_class);
511 goto out_chrdev; 511 goto out_chrdev;
@@ -539,10 +539,10 @@ tipar_cleanup_module(void)
539 if (table[i].dev == NULL) 539 if (table[i].dev == NULL)
540 continue; 540 continue;
541 parport_unregister_device(table[i].dev); 541 parport_unregister_device(table[i].dev);
542 class_simple_device_remove(MKDEV(TIPAR_MAJOR, i)); 542 class_device_destroy(tipar_class, MKDEV(TIPAR_MAJOR, i));
543 devfs_remove("ticables/par/%d", i); 543 devfs_remove("ticables/par/%d", i);
544 } 544 }
545 class_simple_destroy(tipar_class); 545 class_destroy(tipar_class);
546 devfs_remove("ticables/par"); 546 devfs_remove("ticables/par");
547 547
548 pr_info("tipar: module unloaded\n"); 548 pr_info("tipar: module unloaded\n");
diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c
index 58e21fe44262..0c6f521abd0e 100644
--- a/drivers/char/toshiba.c
+++ b/drivers/char/toshiba.c
@@ -73,16 +73,20 @@
73 73
74#define TOSH_MINOR_DEV 181 74#define TOSH_MINOR_DEV 181
75 75
76static int tosh_id = 0x0000; 76MODULE_LICENSE("GPL");
77static int tosh_bios = 0x0000; 77MODULE_AUTHOR("Jonathan Buzzard <jonathan@buzzard.org.uk>");
78static int tosh_date = 0x0000; 78MODULE_DESCRIPTION("Toshiba laptop SMM driver");
79static int tosh_sci = 0x0000; 79MODULE_SUPPORTED_DEVICE("toshiba");
80static int tosh_fan = 0;
81
82static int tosh_fn = 0;
83 80
84module_param(tosh_fn, int, 0); 81static int tosh_fn;
82module_param_named(fn, tosh_fn, int, 0);
83MODULE_PARM_DESC(fn, "User specified Fn key detection port");
85 84
85static int tosh_id;
86static int tosh_bios;
87static int tosh_date;
88static int tosh_sci;
89static int tosh_fan;
86 90
87static int tosh_ioctl(struct inode *, struct file *, unsigned int, 91static int tosh_ioctl(struct inode *, struct file *, unsigned int,
88 unsigned long); 92 unsigned long);
@@ -359,7 +363,7 @@ static int tosh_get_machine_id(void)
359 unsigned long address; 363 unsigned long address;
360 364
361 id = (0x100*(int) isa_readb(0xffffe))+((int) isa_readb(0xffffa)); 365 id = (0x100*(int) isa_readb(0xffffe))+((int) isa_readb(0xffffa));
362 366
363 /* do we have a SCTTable machine identication number on our hands */ 367 /* do we have a SCTTable machine identication number on our hands */
364 368
365 if (id==0xfc2f) { 369 if (id==0xfc2f) {
@@ -424,7 +428,7 @@ static int tosh_probe(void)
424 } 428 }
425 429
426 /* call the Toshiba SCI support check routine */ 430 /* call the Toshiba SCI support check routine */
427 431
428 regs.eax = 0xf0f0; 432 regs.eax = 0xf0f0;
429 regs.ebx = 0x0000; 433 regs.ebx = 0x0000;
430 regs.ecx = 0x0000; 434 regs.ecx = 0x0000;
@@ -440,7 +444,7 @@ static int tosh_probe(void)
440 /* if we get this far then we are running on a Toshiba (probably)! */ 444 /* if we get this far then we are running on a Toshiba (probably)! */
441 445
442 tosh_sci = regs.edx & 0xffff; 446 tosh_sci = regs.edx & 0xffff;
443 447
444 /* next get the machine ID of the current laptop */ 448 /* next get the machine ID of the current laptop */
445 449
446 tosh_id = tosh_get_machine_id(); 450 tosh_id = tosh_get_machine_id();
@@ -475,16 +479,15 @@ static int tosh_probe(void)
475 return 0; 479 return 0;
476} 480}
477 481
478int __init tosh_init(void) 482static int __init toshiba_init(void)
479{ 483{
480 int retval; 484 int retval;
481 /* are we running on a Toshiba laptop */ 485 /* are we running on a Toshiba laptop */
482 486
483 if (tosh_probe()!=0) 487 if (tosh_probe())
484 return -EIO; 488 return -ENODEV;
485 489
486 printk(KERN_INFO "Toshiba System Managment Mode driver v" 490 printk(KERN_INFO "Toshiba System Managment Mode driver v" TOSH_VERSION "\n");
487 TOSH_VERSION"\n");
488 491
489 /* set the port to use for Fn status if not specified as a parameter */ 492 /* set the port to use for Fn status if not specified as a parameter */
490 if (tosh_fn==0x00) 493 if (tosh_fn==0x00)
@@ -492,12 +495,12 @@ int __init tosh_init(void)
492 495
493 /* register the device file */ 496 /* register the device file */
494 retval = misc_register(&tosh_device); 497 retval = misc_register(&tosh_device);
495 if(retval < 0) 498 if (retval < 0)
496 return retval; 499 return retval;
497 500
498#ifdef CONFIG_PROC_FS 501#ifdef CONFIG_PROC_FS
499 /* register the proc entry */ 502 /* register the proc entry */
500 if(create_proc_info_entry("toshiba", 0, NULL, tosh_get_info) == NULL){ 503 if (create_proc_info_entry("toshiba", 0, NULL, tosh_get_info) == NULL) {
501 misc_deregister(&tosh_device); 504 misc_deregister(&tosh_device);
502 return -ENOMEM; 505 return -ENOMEM;
503 } 506 }
@@ -506,27 +509,12 @@ int __init tosh_init(void)
506 return 0; 509 return 0;
507} 510}
508 511
509#ifdef MODULE 512static void __exit toshiba_exit(void)
510int init_module(void)
511{
512 return tosh_init();
513}
514
515void cleanup_module(void)
516{ 513{
517 /* remove the proc entry */
518
519 remove_proc_entry("toshiba", NULL); 514 remove_proc_entry("toshiba", NULL);
520
521 /* unregister the device file */
522
523 misc_deregister(&tosh_device); 515 misc_deregister(&tosh_device);
524} 516}
525#endif
526 517
527MODULE_LICENSE("GPL"); 518module_init(toshiba_init);
528MODULE_PARM_DESC(tosh_fn, "User specified Fn key detection port"); 519module_exit(toshiba_exit);
529MODULE_AUTHOR("Jonathan Buzzard <jonathan@buzzard.org.uk>");
530MODULE_DESCRIPTION("Toshiba laptop SMM driver");
531MODULE_SUPPORTED_DEVICE("toshiba");
532 520
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index 7a969778915a..79e9832ef1f3 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -17,6 +17,8 @@ config TCG_TPM
17 obtained at: <http://sourceforge.net/projects/trousers>. To 17 obtained at: <http://sourceforge.net/projects/trousers>. To
18 compile this driver as a module, choose M here; the module 18 compile this driver as a module, choose M here; the module
19 will be called tpm. If unsure, say N. 19 will be called tpm. If unsure, say N.
20 Note: For more TPM drivers enable CONFIG_PNP, CONFIG_ACPI_BUS
21 and CONFIG_PNPACPI.
20 22
21config TCG_NSC 23config TCG_NSC
22 tristate "National Semiconductor TPM Interface" 24 tristate "National Semiconductor TPM Interface"
@@ -35,5 +37,17 @@ config TCG_ATMEL
35 will be accessible from within Linux. To compile this driver 37 will be accessible from within Linux. To compile this driver
36 as a module, choose M here; the module will be called tpm_atmel. 38 as a module, choose M here; the module will be called tpm_atmel.
37 39
40config TCG_INFINEON
41 tristate "Infineon Technologies TPM Interface"
42 depends on TCG_TPM && PNPACPI
43 ---help---
44 If you have a TPM security chip from Infineon Technologies
45 (either SLD 9630 TT 1.1 or SLB 9635 TT 1.2) say Yes and it
46 will be accessible from within Linux.
47 To compile this driver as a module, choose M here; the module
48 will be called tpm_infineon.
49 Further information on this driver and the supported hardware
50 can be found at http://www.prosec.rub.de/tpm
51
38endmenu 52endmenu
39 53
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile
index 736d3df266f5..2392e404e8d1 100644
--- a/drivers/char/tpm/Makefile
+++ b/drivers/char/tpm/Makefile
@@ -4,4 +4,4 @@
4obj-$(CONFIG_TCG_TPM) += tpm.o 4obj-$(CONFIG_TCG_TPM) += tpm.o
5obj-$(CONFIG_TCG_NSC) += tpm_nsc.o 5obj-$(CONFIG_TCG_NSC) += tpm_nsc.o
6obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o 6obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o
7 7obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 87235330fdbe..049d128ae7f0 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -19,7 +19,7 @@
19 * 19 *
20 * Note, the TPM chip is not interrupt driven (only polling) 20 * Note, the TPM chip is not interrupt driven (only polling)
21 * and can have very long timeouts (minutes!). Hence the unusual 21 * and can have very long timeouts (minutes!). Hence the unusual
22 * calls to schedule_timeout. 22 * calls to msleep.
23 * 23 *
24 */ 24 */
25 25
@@ -28,19 +28,16 @@
28#include <linux/spinlock.h> 28#include <linux/spinlock.h>
29#include "tpm.h" 29#include "tpm.h"
30 30
31#define TPM_MINOR 224 /* officially assigned */ 31enum tpm_const {
32 32 TPM_MINOR = 224, /* officially assigned */
33#define TPM_BUFSIZE 2048 33 TPM_BUFSIZE = 2048,
34 34 TPM_NUM_DEVICES = 256,
35/* PCI configuration addresses */ 35 TPM_NUM_MASK_ENTRIES = TPM_NUM_DEVICES / (8 * sizeof(int))
36#define PCI_GEN_PMCON_1 0xA0 36};
37#define PCI_GEN1_DEC 0xE4
38#define PCI_LPC_EN 0xE6
39#define PCI_GEN2_DEC 0xEC
40 37
41static LIST_HEAD(tpm_chip_list); 38static LIST_HEAD(tpm_chip_list);
42static DEFINE_SPINLOCK(driver_lock); 39static DEFINE_SPINLOCK(driver_lock);
43static int dev_mask[32]; 40static int dev_mask[TPM_NUM_MASK_ENTRIES];
44 41
45static void user_reader_timeout(unsigned long ptr) 42static void user_reader_timeout(unsigned long ptr)
46{ 43{
@@ -52,92 +49,17 @@ static void user_reader_timeout(unsigned long ptr)
52 up(&chip->buffer_mutex); 49 up(&chip->buffer_mutex);
53} 50}
54 51
55void tpm_time_expired(unsigned long ptr)
56{
57 int *exp = (int *) ptr;
58 *exp = 1;
59}
60
61EXPORT_SYMBOL_GPL(tpm_time_expired);
62
63/*
64 * Initialize the LPC bus and enable the TPM ports
65 */
66int tpm_lpc_bus_init(struct pci_dev *pci_dev, u16 base)
67{
68 u32 lpcenable, tmp;
69 int is_lpcm = 0;
70
71 switch (pci_dev->vendor) {
72 case PCI_VENDOR_ID_INTEL:
73 switch (pci_dev->device) {
74 case PCI_DEVICE_ID_INTEL_82801CA_12:
75 case PCI_DEVICE_ID_INTEL_82801DB_12:
76 is_lpcm = 1;
77 break;
78 }
79 /* init ICH (enable LPC) */
80 pci_read_config_dword(pci_dev, PCI_GEN1_DEC, &lpcenable);
81 lpcenable |= 0x20000000;
82 pci_write_config_dword(pci_dev, PCI_GEN1_DEC, lpcenable);
83
84 if (is_lpcm) {
85 pci_read_config_dword(pci_dev, PCI_GEN1_DEC,
86 &lpcenable);
87 if ((lpcenable & 0x20000000) == 0) {
88 dev_err(&pci_dev->dev,
89 "cannot enable LPC\n");
90 return -ENODEV;
91 }
92 }
93
94 /* initialize TPM registers */
95 pci_read_config_dword(pci_dev, PCI_GEN2_DEC, &tmp);
96
97 if (!is_lpcm)
98 tmp = (tmp & 0xFFFF0000) | (base & 0xFFF0);
99 else
100 tmp =
101 (tmp & 0xFFFF0000) | (base & 0xFFF0) |
102 0x00000001;
103
104 pci_write_config_dword(pci_dev, PCI_GEN2_DEC, tmp);
105
106 if (is_lpcm) {
107 pci_read_config_dword(pci_dev, PCI_GEN_PMCON_1,
108 &tmp);
109 tmp |= 0x00000004; /* enable CLKRUN */
110 pci_write_config_dword(pci_dev, PCI_GEN_PMCON_1,
111 tmp);
112 }
113 tpm_write_index(0x0D, 0x55); /* unlock 4F */
114 tpm_write_index(0x0A, 0x00); /* int disable */
115 tpm_write_index(0x08, base); /* base addr lo */
116 tpm_write_index(0x09, (base & 0xFF00) >> 8); /* base addr hi */
117 tpm_write_index(0x0D, 0xAA); /* lock 4F */
118 break;
119 case PCI_VENDOR_ID_AMD:
120 /* nothing yet */
121 break;
122 }
123
124 return 0;
125}
126
127EXPORT_SYMBOL_GPL(tpm_lpc_bus_init);
128
129/* 52/*
130 * Internal kernel interface to transmit TPM commands 53 * Internal kernel interface to transmit TPM commands
131 */ 54 */
132static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, 55static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
133 size_t bufsiz) 56 size_t bufsiz)
134{ 57{
135 ssize_t len; 58 ssize_t rc;
136 u32 count; 59 u32 count;
137 __be32 *native_size; 60 unsigned long stop;
138 61
139 native_size = (__force __be32 *) (buf + 2); 62 count = be32_to_cpu(*((__be32 *) (buf + 2)));
140 count = be32_to_cpu(*native_size);
141 63
142 if (count == 0) 64 if (count == 0)
143 return -ENODATA; 65 return -ENODATA;
@@ -149,53 +71,49 @@ static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf,
149 71
150 down(&chip->tpm_mutex); 72 down(&chip->tpm_mutex);
151 73
152 if ((len = chip->vendor->send(chip, (u8 *) buf, count)) < 0) { 74 if ((rc = chip->vendor->send(chip, (u8 *) buf, count)) < 0) {
153 dev_err(&chip->pci_dev->dev, 75 dev_err(&chip->pci_dev->dev,
154 "tpm_transmit: tpm_send: error %zd\n", len); 76 "tpm_transmit: tpm_send: error %zd\n", rc);
155 return len; 77 goto out;
156 } 78 }
157 79
158 down(&chip->timer_manipulation_mutex); 80 stop = jiffies + 2 * 60 * HZ;
159 chip->time_expired = 0;
160 init_timer(&chip->device_timer);
161 chip->device_timer.function = tpm_time_expired;
162 chip->device_timer.expires = jiffies + 2 * 60 * HZ;
163 chip->device_timer.data = (unsigned long) &chip->time_expired;
164 add_timer(&chip->device_timer);
165 up(&chip->timer_manipulation_mutex);
166
167 do { 81 do {
168 u8 status = inb(chip->vendor->base + 1); 82 u8 status = inb(chip->vendor->base + 1);
169 if ((status & chip->vendor->req_complete_mask) == 83 if ((status & chip->vendor->req_complete_mask) ==
170 chip->vendor->req_complete_val) { 84 chip->vendor->req_complete_val) {
171 down(&chip->timer_manipulation_mutex);
172 del_singleshot_timer_sync(&chip->device_timer);
173 up(&chip->timer_manipulation_mutex);
174 goto out_recv; 85 goto out_recv;
175 } 86 }
176 set_current_state(TASK_UNINTERRUPTIBLE); 87
177 schedule_timeout(TPM_TIMEOUT); 88 if ((status == chip->vendor->req_canceled)) {
89 dev_err(&chip->pci_dev->dev, "Operation Canceled\n");
90 rc = -ECANCELED;
91 goto out;
92 }
93
94 msleep(TPM_TIMEOUT); /* CHECK */
178 rmb(); 95 rmb();
179 } while (!chip->time_expired); 96 } while (time_before(jiffies, stop));
180 97
181 98
182 chip->vendor->cancel(chip); 99 chip->vendor->cancel(chip);
183 dev_err(&chip->pci_dev->dev, "Time expired\n"); 100 dev_err(&chip->pci_dev->dev, "Operation Timed out\n");
184 up(&chip->tpm_mutex); 101 rc = -ETIME;
185 return -EIO; 102 goto out;
186 103
187out_recv: 104out_recv:
188 len = chip->vendor->recv(chip, (u8 *) buf, bufsiz); 105 rc = chip->vendor->recv(chip, (u8 *) buf, bufsiz);
189 if (len < 0) 106 if (rc < 0)
190 dev_err(&chip->pci_dev->dev, 107 dev_err(&chip->pci_dev->dev,
191 "tpm_transmit: tpm_recv: error %zd\n", len); 108 "tpm_transmit: tpm_recv: error %zd\n", rc);
109out:
192 up(&chip->tpm_mutex); 110 up(&chip->tpm_mutex);
193 return len; 111 return rc;
194} 112}
195 113
196#define TPM_DIGEST_SIZE 20 114#define TPM_DIGEST_SIZE 20
197#define CAP_PCR_RESULT_SIZE 18 115#define CAP_PCR_RESULT_SIZE 18
198static u8 cap_pcr[] = { 116static const u8 cap_pcr[] = {
199 0, 193, /* TPM_TAG_RQU_COMMAND */ 117 0, 193, /* TPM_TAG_RQU_COMMAND */
200 0, 0, 0, 22, /* length */ 118 0, 0, 0, 22, /* length */
201 0, 0, 0, 101, /* TPM_ORD_GetCapability */ 119 0, 0, 0, 101, /* TPM_ORD_GetCapability */
@@ -205,75 +123,94 @@ static u8 cap_pcr[] = {
205}; 123};
206 124
207#define READ_PCR_RESULT_SIZE 30 125#define READ_PCR_RESULT_SIZE 30
208static u8 pcrread[] = { 126static const u8 pcrread[] = {
209 0, 193, /* TPM_TAG_RQU_COMMAND */ 127 0, 193, /* TPM_TAG_RQU_COMMAND */
210 0, 0, 0, 14, /* length */ 128 0, 0, 0, 14, /* length */
211 0, 0, 0, 21, /* TPM_ORD_PcrRead */ 129 0, 0, 0, 21, /* TPM_ORD_PcrRead */
212 0, 0, 0, 0 /* PCR index */ 130 0, 0, 0, 0 /* PCR index */
213}; 131};
214 132
215static ssize_t show_pcrs(struct device *dev, char *buf) 133ssize_t tpm_show_pcrs(struct device *dev, struct device_attribute *attr,
134 char *buf)
216{ 135{
217 u8 data[READ_PCR_RESULT_SIZE]; 136 u8 data[READ_PCR_RESULT_SIZE];
218 ssize_t len; 137 ssize_t len;
219 int i, j, index, num_pcrs; 138 int i, j, num_pcrs;
139 __be32 index;
220 char *str = buf; 140 char *str = buf;
221 141
222 struct tpm_chip *chip = 142 struct tpm_chip *chip =
223 pci_get_drvdata(container_of(dev, struct pci_dev, dev)); 143 pci_get_drvdata(to_pci_dev(dev));
224 if (chip == NULL) 144 if (chip == NULL)
225 return -ENODEV; 145 return -ENODEV;
226 146
227 memcpy(data, cap_pcr, sizeof(cap_pcr)); 147 memcpy(data, cap_pcr, sizeof(cap_pcr));
228 if ((len = tpm_transmit(chip, data, sizeof(data))) 148 if ((len = tpm_transmit(chip, data, sizeof(data)))
229 < CAP_PCR_RESULT_SIZE) 149 < CAP_PCR_RESULT_SIZE) {
230 return len; 150 dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred "
151 "attempting to determine the number of PCRS\n",
152 be32_to_cpu(*((__be32 *) (data + 6))));
153 return 0;
154 }
231 155
232 num_pcrs = be32_to_cpu(*((__force __be32 *) (data + 14))); 156 num_pcrs = be32_to_cpu(*((__be32 *) (data + 14)));
233 157
234 for (i = 0; i < num_pcrs; i++) { 158 for (i = 0; i < num_pcrs; i++) {
235 memcpy(data, pcrread, sizeof(pcrread)); 159 memcpy(data, pcrread, sizeof(pcrread));
236 index = cpu_to_be32(i); 160 index = cpu_to_be32(i);
237 memcpy(data + 10, &index, 4); 161 memcpy(data + 10, &index, 4);
238 if ((len = tpm_transmit(chip, data, sizeof(data))) 162 if ((len = tpm_transmit(chip, data, sizeof(data)))
239 < READ_PCR_RESULT_SIZE) 163 < READ_PCR_RESULT_SIZE){
240 return len; 164 dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred"
165 " attempting to read PCR %d of %d\n",
166 be32_to_cpu(*((__be32 *) (data + 6))), i, num_pcrs);
167 goto out;
168 }
241 str += sprintf(str, "PCR-%02d: ", i); 169 str += sprintf(str, "PCR-%02d: ", i);
242 for (j = 0; j < TPM_DIGEST_SIZE; j++) 170 for (j = 0; j < TPM_DIGEST_SIZE; j++)
243 str += sprintf(str, "%02X ", *(data + 10 + j)); 171 str += sprintf(str, "%02X ", *(data + 10 + j));
244 str += sprintf(str, "\n"); 172 str += sprintf(str, "\n");
245 } 173 }
174out:
246 return str - buf; 175 return str - buf;
247} 176}
248 177EXPORT_SYMBOL_GPL(tpm_show_pcrs);
249static DEVICE_ATTR(pcrs, S_IRUGO, show_pcrs, NULL);
250 178
251#define READ_PUBEK_RESULT_SIZE 314 179#define READ_PUBEK_RESULT_SIZE 314
252static u8 readpubek[] = { 180static const u8 readpubek[] = {
253 0, 193, /* TPM_TAG_RQU_COMMAND */ 181 0, 193, /* TPM_TAG_RQU_COMMAND */
254 0, 0, 0, 30, /* length */ 182 0, 0, 0, 30, /* length */
255 0, 0, 0, 124, /* TPM_ORD_ReadPubek */ 183 0, 0, 0, 124, /* TPM_ORD_ReadPubek */
256}; 184};
257 185
258static ssize_t show_pubek(struct device *dev, char *buf) 186ssize_t tpm_show_pubek(struct device *dev, struct device_attribute *attr,
187 char *buf)
259{ 188{
260 u8 data[READ_PUBEK_RESULT_SIZE]; 189 u8 *data;
261 ssize_t len; 190 ssize_t len;
262 __be32 *native_val; 191 int i, rc;
263 int i;
264 char *str = buf; 192 char *str = buf;
265 193
266 struct tpm_chip *chip = 194 struct tpm_chip *chip =
267 pci_get_drvdata(container_of(dev, struct pci_dev, dev)); 195 pci_get_drvdata(to_pci_dev(dev));
268 if (chip == NULL) 196 if (chip == NULL)
269 return -ENODEV; 197 return -ENODEV;
270 198
199 data = kmalloc(READ_PUBEK_RESULT_SIZE, GFP_KERNEL);
200 if (!data)
201 return -ENOMEM;
202
271 memcpy(data, readpubek, sizeof(readpubek)); 203 memcpy(data, readpubek, sizeof(readpubek));
272 memset(data + sizeof(readpubek), 0, 20); /* zero nonce */ 204 memset(data + sizeof(readpubek), 0, 20); /* zero nonce */
273 205
274 if ((len = tpm_transmit(chip, data, sizeof(data))) < 206 if ((len = tpm_transmit(chip, data, READ_PUBEK_RESULT_SIZE)) <
275 READ_PUBEK_RESULT_SIZE) 207 READ_PUBEK_RESULT_SIZE) {
276 return len; 208 dev_dbg(&chip->pci_dev->dev, "A TPM error (%d) occurred "
209 "attempting to read the PUBEK\n",
210 be32_to_cpu(*((__be32 *) (data + 6))));
211 rc = 0;
212 goto out;
213 }
277 214
278 /* 215 /*
279 ignore header 10 bytes 216 ignore header 10 bytes
@@ -286,8 +223,6 @@ static ssize_t show_pubek(struct device *dev, char *buf)
286 ignore checksum 20 bytes 223 ignore checksum 20 bytes
287 */ 224 */
288 225
289 native_val = (__force __be32 *) (data + 34);
290
291 str += 226 str +=
292 sprintf(str, 227 sprintf(str,
293 "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n" 228 "Algorithm: %02X %02X %02X %02X\nEncscheme: %02X %02X\n"
@@ -298,21 +233,23 @@ static ssize_t show_pubek(struct device *dev, char *buf)
298 data[15], data[16], data[17], data[22], data[23], 233 data[15], data[16], data[17], data[22], data[23],
299 data[24], data[25], data[26], data[27], data[28], 234 data[24], data[25], data[26], data[27], data[28],
300 data[29], data[30], data[31], data[32], data[33], 235 data[29], data[30], data[31], data[32], data[33],
301 be32_to_cpu(*native_val) 236 be32_to_cpu(*((__be32 *) (data + 34))));
302 );
303 237
304 for (i = 0; i < 256; i++) { 238 for (i = 0; i < 256; i++) {
305 str += sprintf(str, "%02X ", data[i + 39]); 239 str += sprintf(str, "%02X ", data[i + 38]);
306 if ((i + 1) % 16 == 0) 240 if ((i + 1) % 16 == 0)
307 str += sprintf(str, "\n"); 241 str += sprintf(str, "\n");
308 } 242 }
309 return str - buf; 243 rc = str - buf;
244out:
245 kfree(data);
246 return rc;
310} 247}
311 248
312static DEVICE_ATTR(pubek, S_IRUGO, show_pubek, NULL); 249EXPORT_SYMBOL_GPL(tpm_show_pubek);
313 250
314#define CAP_VER_RESULT_SIZE 18 251#define CAP_VER_RESULT_SIZE 18
315static u8 cap_version[] = { 252static const u8 cap_version[] = {
316 0, 193, /* TPM_TAG_RQU_COMMAND */ 253 0, 193, /* TPM_TAG_RQU_COMMAND */
317 0, 0, 0, 18, /* length */ 254 0, 0, 0, 18, /* length */
318 0, 0, 0, 101, /* TPM_ORD_GetCapability */ 255 0, 0, 0, 101, /* TPM_ORD_GetCapability */
@@ -321,7 +258,7 @@ static u8 cap_version[] = {
321}; 258};
322 259
323#define CAP_MANUFACTURER_RESULT_SIZE 18 260#define CAP_MANUFACTURER_RESULT_SIZE 18
324static u8 cap_manufacturer[] = { 261static const u8 cap_manufacturer[] = {
325 0, 193, /* TPM_TAG_RQU_COMMAND */ 262 0, 193, /* TPM_TAG_RQU_COMMAND */
326 0, 0, 0, 22, /* length */ 263 0, 0, 0, 22, /* length */
327 0, 0, 0, 101, /* TPM_ORD_GetCapability */ 264 0, 0, 0, 101, /* TPM_ORD_GetCapability */
@@ -330,14 +267,15 @@ static u8 cap_manufacturer[] = {
330 0, 0, 1, 3 267 0, 0, 1, 3
331}; 268};
332 269
333static ssize_t show_caps(struct device *dev, char *buf) 270ssize_t tpm_show_caps(struct device *dev, struct device_attribute *attr,
271 char *buf)
334{ 272{
335 u8 data[READ_PUBEK_RESULT_SIZE]; 273 u8 data[sizeof(cap_manufacturer)];
336 ssize_t len; 274 ssize_t len;
337 char *str = buf; 275 char *str = buf;
338 276
339 struct tpm_chip *chip = 277 struct tpm_chip *chip =
340 pci_get_drvdata(container_of(dev, struct pci_dev, dev)); 278 pci_get_drvdata(to_pci_dev(dev));
341 if (chip == NULL) 279 if (chip == NULL)
342 return -ENODEV; 280 return -ENODEV;
343 281
@@ -348,7 +286,7 @@ static ssize_t show_caps(struct device *dev, char *buf)
348 return len; 286 return len;
349 287
350 str += sprintf(str, "Manufacturer: 0x%x\n", 288 str += sprintf(str, "Manufacturer: 0x%x\n",
351 be32_to_cpu(*(data + 14))); 289 be32_to_cpu(*((__be32 *) (data + 14))));
352 290
353 memcpy(data, cap_version, sizeof(cap_version)); 291 memcpy(data, cap_version, sizeof(cap_version));
354 292
@@ -363,8 +301,20 @@ static ssize_t show_caps(struct device *dev, char *buf)
363 301
364 return str - buf; 302 return str - buf;
365} 303}
304EXPORT_SYMBOL_GPL(tpm_show_caps);
305
306ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
307 const char *buf, size_t count)
308{
309 struct tpm_chip *chip = dev_get_drvdata(dev);
310 if (chip == NULL)
311 return 0;
312
313 chip->vendor->cancel(chip);
314 return count;
315}
316EXPORT_SYMBOL_GPL(tpm_store_cancel);
366 317
367static DEVICE_ATTR(caps, S_IRUGO, show_caps, NULL);
368 318
369/* 319/*
370 * Device file system interface to the TPM 320 * Device file system interface to the TPM
@@ -422,24 +372,15 @@ EXPORT_SYMBOL_GPL(tpm_open);
422int tpm_release(struct inode *inode, struct file *file) 372int tpm_release(struct inode *inode, struct file *file)
423{ 373{
424 struct tpm_chip *chip = file->private_data; 374 struct tpm_chip *chip = file->private_data;
425
426 file->private_data = NULL;
427 375
428 spin_lock(&driver_lock); 376 spin_lock(&driver_lock);
377 file->private_data = NULL;
429 chip->num_opens--; 378 chip->num_opens--;
430 spin_unlock(&driver_lock); 379 del_singleshot_timer_sync(&chip->user_read_timer);
431
432 down(&chip->timer_manipulation_mutex);
433 if (timer_pending(&chip->user_read_timer))
434 del_singleshot_timer_sync(&chip->user_read_timer);
435 else if (timer_pending(&chip->device_timer))
436 del_singleshot_timer_sync(&chip->device_timer);
437 up(&chip->timer_manipulation_mutex);
438
439 kfree(chip->data_buffer);
440 atomic_set(&chip->data_pending, 0); 380 atomic_set(&chip->data_pending, 0);
441
442 pci_dev_put(chip->pci_dev); 381 pci_dev_put(chip->pci_dev);
382 kfree(chip->data_buffer);
383 spin_unlock(&driver_lock);
443 return 0; 384 return 0;
444} 385}
445 386
@@ -453,10 +394,8 @@ ssize_t tpm_write(struct file * file, const char __user * buf,
453 394
454 /* cannot perform a write until the read has cleared 395 /* cannot perform a write until the read has cleared
455 either via tpm_read or a user_read_timer timeout */ 396 either via tpm_read or a user_read_timer timeout */
456 while (atomic_read(&chip->data_pending) != 0) { 397 while (atomic_read(&chip->data_pending) != 0)
457 set_current_state(TASK_UNINTERRUPTIBLE); 398 msleep(TPM_TIMEOUT);
458 schedule_timeout(TPM_TIMEOUT);
459 }
460 399
461 down(&chip->buffer_mutex); 400 down(&chip->buffer_mutex);
462 401
@@ -476,13 +415,7 @@ ssize_t tpm_write(struct file * file, const char __user * buf,
476 up(&chip->buffer_mutex); 415 up(&chip->buffer_mutex);
477 416
478 /* Set a timeout by which the reader must come claim the result */ 417 /* Set a timeout by which the reader must come claim the result */
479 down(&chip->timer_manipulation_mutex); 418 mod_timer(&chip->user_read_timer, jiffies + (60 * HZ));
480 init_timer(&chip->user_read_timer);
481 chip->user_read_timer.function = user_reader_timeout;
482 chip->user_read_timer.data = (unsigned long) chip;
483 chip->user_read_timer.expires = jiffies + (60 * HZ);
484 add_timer(&chip->user_read_timer);
485 up(&chip->timer_manipulation_mutex);
486 419
487 return in_size; 420 return in_size;
488} 421}
@@ -493,29 +426,19 @@ ssize_t tpm_read(struct file * file, char __user * buf,
493 size_t size, loff_t * off) 426 size_t size, loff_t * off)
494{ 427{
495 struct tpm_chip *chip = file->private_data; 428 struct tpm_chip *chip = file->private_data;
496 int ret_size = -ENODATA; 429 int ret_size;
497 430
498 if (atomic_read(&chip->data_pending) != 0) { /* Result available */ 431 del_singleshot_timer_sync(&chip->user_read_timer);
499 down(&chip->timer_manipulation_mutex); 432 ret_size = atomic_read(&chip->data_pending);
500 del_singleshot_timer_sync(&chip->user_read_timer); 433 atomic_set(&chip->data_pending, 0);
501 up(&chip->timer_manipulation_mutex); 434 if (ret_size > 0) { /* relay data */
435 if (size < ret_size)
436 ret_size = size;
502 437
503 down(&chip->buffer_mutex); 438 down(&chip->buffer_mutex);
504 439 if (copy_to_user
505 ret_size = atomic_read(&chip->data_pending); 440 ((void __user *) buf, chip->data_buffer, ret_size))
506 atomic_set(&chip->data_pending, 0); 441 ret_size = -EFAULT;
507
508 if (ret_size == 0) /* timeout just occurred */
509 ret_size = -ETIME;
510 else if (ret_size > 0) { /* relay data */
511 if (size < ret_size)
512 ret_size = size;
513
514 if (copy_to_user((void __user *) buf,
515 chip->data_buffer, ret_size)) {
516 ret_size = -EFAULT;
517 }
518 }
519 up(&chip->buffer_mutex); 442 up(&chip->buffer_mutex);
520 } 443 }
521 444
@@ -541,14 +464,13 @@ void __devexit tpm_remove(struct pci_dev *pci_dev)
541 464
542 pci_set_drvdata(pci_dev, NULL); 465 pci_set_drvdata(pci_dev, NULL);
543 misc_deregister(&chip->vendor->miscdev); 466 misc_deregister(&chip->vendor->miscdev);
467 kfree(chip->vendor->miscdev.name);
544 468
545 device_remove_file(&pci_dev->dev, &dev_attr_pubek); 469 sysfs_remove_group(&pci_dev->dev.kobj, chip->vendor->attr_group);
546 device_remove_file(&pci_dev->dev, &dev_attr_pcrs);
547 device_remove_file(&pci_dev->dev, &dev_attr_caps);
548 470
549 pci_disable_device(pci_dev); 471 pci_disable_device(pci_dev);
550 472
551 dev_mask[chip->dev_num / 32] &= !(1 << (chip->dev_num % 32)); 473 dev_mask[chip->dev_num / TPM_NUM_MASK_ENTRIES ] &= !(1 << (chip->dev_num % TPM_NUM_MASK_ENTRIES));
552 474
553 kfree(chip); 475 kfree(chip);
554 476
@@ -590,10 +512,6 @@ int tpm_pm_resume(struct pci_dev *pci_dev)
590 if (chip == NULL) 512 if (chip == NULL)
591 return -ENODEV; 513 return -ENODEV;
592 514
593 spin_lock(&driver_lock);
594 tpm_lpc_bus_init(pci_dev, chip->vendor->base);
595 spin_unlock(&driver_lock);
596
597 return 0; 515 return 0;
598} 516}
599 517
@@ -609,7 +527,9 @@ EXPORT_SYMBOL_GPL(tpm_pm_resume);
609int tpm_register_hardware(struct pci_dev *pci_dev, 527int tpm_register_hardware(struct pci_dev *pci_dev,
610 struct tpm_vendor_specific *entry) 528 struct tpm_vendor_specific *entry)
611{ 529{
612 char devname[7]; 530#define DEVNAME_SIZE 7
531
532 char *devname;
613 struct tpm_chip *chip; 533 struct tpm_chip *chip;
614 int i, j; 534 int i, j;
615 535
@@ -622,17 +542,21 @@ int tpm_register_hardware(struct pci_dev *pci_dev,
622 542
623 init_MUTEX(&chip->buffer_mutex); 543 init_MUTEX(&chip->buffer_mutex);
624 init_MUTEX(&chip->tpm_mutex); 544 init_MUTEX(&chip->tpm_mutex);
625 init_MUTEX(&chip->timer_manipulation_mutex);
626 INIT_LIST_HEAD(&chip->list); 545 INIT_LIST_HEAD(&chip->list);
627 546
547 init_timer(&chip->user_read_timer);
548 chip->user_read_timer.function = user_reader_timeout;
549 chip->user_read_timer.data = (unsigned long) chip;
550
628 chip->vendor = entry; 551 chip->vendor = entry;
629 552
630 chip->dev_num = -1; 553 chip->dev_num = -1;
631 554
632 for (i = 0; i < 32; i++) 555 for (i = 0; i < TPM_NUM_MASK_ENTRIES; i++)
633 for (j = 0; j < 8; j++) 556 for (j = 0; j < 8 * sizeof(int); j++)
634 if ((dev_mask[i] & (1 << j)) == 0) { 557 if ((dev_mask[i] & (1 << j)) == 0) {
635 chip->dev_num = i * 32 + j; 558 chip->dev_num =
559 i * TPM_NUM_MASK_ENTRIES + j;
636 dev_mask[i] |= 1 << j; 560 dev_mask[i] |= 1 << j;
637 goto dev_num_search_complete; 561 goto dev_num_search_complete;
638 } 562 }
@@ -648,7 +572,8 @@ dev_num_search_complete:
648 else 572 else
649 chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR; 573 chip->vendor->miscdev.minor = MISC_DYNAMIC_MINOR;
650 574
651 snprintf(devname, sizeof(devname), "%s%d", "tpm", chip->dev_num); 575 devname = kmalloc(DEVNAME_SIZE, GFP_KERNEL);
576 scnprintf(devname, DEVNAME_SIZE, "%s%d", "tpm", chip->dev_num);
652 chip->vendor->miscdev.name = devname; 577 chip->vendor->miscdev.name = devname;
653 578
654 chip->vendor->miscdev.dev = &(pci_dev->dev); 579 chip->vendor->miscdev.dev = &(pci_dev->dev);
@@ -665,31 +590,20 @@ dev_num_search_complete:
665 return -ENODEV; 590 return -ENODEV;
666 } 591 }
667 592
593 spin_lock(&driver_lock);
594
668 pci_set_drvdata(pci_dev, chip); 595 pci_set_drvdata(pci_dev, chip);
669 596
670 list_add(&chip->list, &tpm_chip_list); 597 list_add(&chip->list, &tpm_chip_list);
671 598
672 device_create_file(&pci_dev->dev, &dev_attr_pubek); 599 spin_unlock(&driver_lock);
673 device_create_file(&pci_dev->dev, &dev_attr_pcrs);
674 device_create_file(&pci_dev->dev, &dev_attr_caps);
675
676 return 0;
677}
678 600
679EXPORT_SYMBOL_GPL(tpm_register_hardware); 601 sysfs_create_group(&pci_dev->dev.kobj, chip->vendor->attr_group);
680 602
681static int __init init_tpm(void)
682{
683 return 0; 603 return 0;
684} 604}
685 605
686static void __exit cleanup_tpm(void) 606EXPORT_SYMBOL_GPL(tpm_register_hardware);
687{
688
689}
690
691module_init(init_tpm);
692module_exit(cleanup_tpm);
693 607
694MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)"); 608MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)");
695MODULE_DESCRIPTION("TPM Driver"); 609MODULE_DESCRIPTION("TPM Driver");
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index de0c796fce80..373b41f6b460 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -25,23 +25,38 @@
25#include <linux/fs.h> 25#include <linux/fs.h>
26#include <linux/miscdevice.h> 26#include <linux/miscdevice.h>
27 27
28#define TPM_TIMEOUT msecs_to_jiffies(5) 28enum tpm_timeout {
29 TPM_TIMEOUT = 5, /* msecs */
30};
29 31
30/* TPM addresses */ 32/* TPM addresses */
31#define TPM_ADDR 0x4E 33enum tpm_addr {
32#define TPM_DATA 0x4F 34 TPM_SUPERIO_ADDR = 0x2E,
35 TPM_ADDR = 0x4E,
36};
37
38extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr,
39 char *);
40extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr,
41 char *);
42extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr,
43 char *);
44extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr,
45 const char *, size_t);
33 46
34struct tpm_chip; 47struct tpm_chip;
35 48
36struct tpm_vendor_specific { 49struct tpm_vendor_specific {
37 u8 req_complete_mask; 50 u8 req_complete_mask;
38 u8 req_complete_val; 51 u8 req_complete_val;
52 u8 req_canceled;
39 u16 base; /* TPM base address */ 53 u16 base; /* TPM base address */
40 54
41 int (*recv) (struct tpm_chip *, u8 *, size_t); 55 int (*recv) (struct tpm_chip *, u8 *, size_t);
42 int (*send) (struct tpm_chip *, u8 *, size_t); 56 int (*send) (struct tpm_chip *, u8 *, size_t);
43 void (*cancel) (struct tpm_chip *); 57 void (*cancel) (struct tpm_chip *);
44 struct miscdevice miscdev; 58 struct miscdevice miscdev;
59 struct attribute_group *attr_group;
45}; 60};
46 61
47struct tpm_chip { 62struct tpm_chip {
@@ -58,29 +73,24 @@ struct tpm_chip {
58 73
59 struct timer_list user_read_timer; /* user needs to claim result */ 74 struct timer_list user_read_timer; /* user needs to claim result */
60 struct semaphore tpm_mutex; /* tpm is processing */ 75 struct semaphore tpm_mutex; /* tpm is processing */
61 struct timer_list device_timer; /* tpm is processing */
62 struct semaphore timer_manipulation_mutex;
63 76
64 struct tpm_vendor_specific *vendor; 77 struct tpm_vendor_specific *vendor;
65 78
66 struct list_head list; 79 struct list_head list;
67}; 80};
68 81
69static inline int tpm_read_index(int index) 82static inline int tpm_read_index(int base, int index)
70{ 83{
71 outb(index, TPM_ADDR); 84 outb(index, base);
72 return inb(TPM_DATA) & 0xFF; 85 return inb(base+1) & 0xFF;
73} 86}
74 87
75static inline void tpm_write_index(int index, int value) 88static inline void tpm_write_index(int base, int index, int value)
76{ 89{
77 outb(index, TPM_ADDR); 90 outb(index, base);
78 outb(value & 0xFF, TPM_DATA); 91 outb(value & 0xFF, base+1);
79} 92}
80 93
81extern void tpm_time_expired(unsigned long);
82extern int tpm_lpc_bus_init(struct pci_dev *, u16);
83
84extern int tpm_register_hardware(struct pci_dev *, 94extern int tpm_register_hardware(struct pci_dev *,
85 struct tpm_vendor_specific *); 95 struct tpm_vendor_specific *);
86extern int tpm_open(struct inode *, struct file *); 96extern int tpm_open(struct inode *, struct file *);
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c
index f9333e729b62..cc2cc77fd174 100644
--- a/drivers/char/tpm/tpm_atmel.c
+++ b/drivers/char/tpm/tpm_atmel.c
@@ -22,17 +22,23 @@
22#include "tpm.h" 22#include "tpm.h"
23 23
24/* Atmel definitions */ 24/* Atmel definitions */
25#define TPM_ATML_BASE 0x400 25enum tpm_atmel_addr {
26 TPM_ATMEL_BASE_ADDR_LO = 0x08,
27 TPM_ATMEL_BASE_ADDR_HI = 0x09
28};
26 29
27/* write status bits */ 30/* write status bits */
28#define ATML_STATUS_ABORT 0x01 31enum tpm_atmel_write_status {
29#define ATML_STATUS_LASTBYTE 0x04 32 ATML_STATUS_ABORT = 0x01,
30 33 ATML_STATUS_LASTBYTE = 0x04
34};
31/* read status bits */ 35/* read status bits */
32#define ATML_STATUS_BUSY 0x01 36enum tpm_atmel_read_status {
33#define ATML_STATUS_DATA_AVAIL 0x02 37 ATML_STATUS_BUSY = 0x01,
34#define ATML_STATUS_REWRITE 0x04 38 ATML_STATUS_DATA_AVAIL = 0x02,
35 39 ATML_STATUS_REWRITE = 0x04,
40 ATML_STATUS_READY = 0x08
41};
36 42
37static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count) 43static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count)
38{ 44{
@@ -121,13 +127,29 @@ static struct file_operations atmel_ops = {
121 .release = tpm_release, 127 .release = tpm_release,
122}; 128};
123 129
130static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
131static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
132static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
133static DEVICE_ATTR(cancel, S_IWUSR |S_IWGRP, NULL, tpm_store_cancel);
134
135static struct attribute* atmel_attrs[] = {
136 &dev_attr_pubek.attr,
137 &dev_attr_pcrs.attr,
138 &dev_attr_caps.attr,
139 &dev_attr_cancel.attr,
140 0,
141};
142
143static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs };
144
124static struct tpm_vendor_specific tpm_atmel = { 145static struct tpm_vendor_specific tpm_atmel = {
125 .recv = tpm_atml_recv, 146 .recv = tpm_atml_recv,
126 .send = tpm_atml_send, 147 .send = tpm_atml_send,
127 .cancel = tpm_atml_cancel, 148 .cancel = tpm_atml_cancel,
128 .req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL, 149 .req_complete_mask = ATML_STATUS_BUSY | ATML_STATUS_DATA_AVAIL,
129 .req_complete_val = ATML_STATUS_DATA_AVAIL, 150 .req_complete_val = ATML_STATUS_DATA_AVAIL,
130 .base = TPM_ATML_BASE, 151 .req_canceled = ATML_STATUS_READY,
152 .attr_group = &atmel_attr_grp,
131 .miscdev = { .fops = &atmel_ops, }, 153 .miscdev = { .fops = &atmel_ops, },
132}; 154};
133 155
@@ -136,27 +158,29 @@ static int __devinit tpm_atml_init(struct pci_dev *pci_dev,
136{ 158{
137 u8 version[4]; 159 u8 version[4];
138 int rc = 0; 160 int rc = 0;
161 int lo, hi;
139 162
140 if (pci_enable_device(pci_dev)) 163 if (pci_enable_device(pci_dev))
141 return -EIO; 164 return -EIO;
142 165
143 if (tpm_lpc_bus_init(pci_dev, TPM_ATML_BASE)) { 166 lo = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_LO);
144 rc = -ENODEV; 167 hi = tpm_read_index(TPM_ADDR, TPM_ATMEL_BASE_ADDR_HI);
145 goto out_err; 168
146 } 169 tpm_atmel.base = (hi<<8)|lo;
170 dev_dbg( &pci_dev->dev, "Operating with base: 0x%x\n", tpm_atmel.base);
147 171
148 /* verify that it is an Atmel part */ 172 /* verify that it is an Atmel part */
149 if (tpm_read_index(4) != 'A' || tpm_read_index(5) != 'T' 173 if (tpm_read_index(TPM_ADDR, 4) != 'A' || tpm_read_index(TPM_ADDR, 5) != 'T'
150 || tpm_read_index(6) != 'M' || tpm_read_index(7) != 'L') { 174 || tpm_read_index(TPM_ADDR, 6) != 'M' || tpm_read_index(TPM_ADDR, 7) != 'L') {
151 rc = -ENODEV; 175 rc = -ENODEV;
152 goto out_err; 176 goto out_err;
153 } 177 }
154 178
155 /* query chip for its version number */ 179 /* query chip for its version number */
156 if ((version[0] = tpm_read_index(0x00)) != 0xFF) { 180 if ((version[0] = tpm_read_index(TPM_ADDR, 0x00)) != 0xFF) {
157 version[1] = tpm_read_index(0x01); 181 version[1] = tpm_read_index(TPM_ADDR, 0x01);
158 version[2] = tpm_read_index(0x02); 182 version[2] = tpm_read_index(TPM_ADDR, 0x02);
159 version[3] = tpm_read_index(0x03); 183 version[3] = tpm_read_index(TPM_ADDR, 0x03);
160 } else { 184 } else {
161 dev_info(&pci_dev->dev, "version query failed\n"); 185 dev_info(&pci_dev->dev, "version query failed\n");
162 rc = -ENODEV; 186 rc = -ENODEV;
@@ -183,6 +207,7 @@ static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
183 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)}, 207 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
184 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)}, 208 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
185 {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)}, 209 {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
210 {PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB6LPC)},
186 {0,} 211 {0,}
187}; 212};
188 213
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c
new file mode 100644
index 000000000000..dc8c540391fd
--- /dev/null
+++ b/drivers/char/tpm/tpm_infineon.c
@@ -0,0 +1,533 @@
1/*
2 * Description:
3 * Device Driver for the Infineon Technologies
4 * SLD 9630 TT 1.1 and SLB 9635 TT 1.2 Trusted Platform Module
5 * Specifications at www.trustedcomputinggroup.org
6 *
7 * Copyright (C) 2005, Marcel Selhorst <selhorst@crypto.rub.de>
8 * Applied Data Security Group, Ruhr-University Bochum, Germany
9 * Project-Homepage: http://www.prosec.rub.de/tpm
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License as
13 * published by the Free Software Foundation, version 2 of the
14 * License.
15 */
16
17#include <acpi/acpi_bus.h>
18#include <linux/pnp.h>
19#include "tpm.h"
20
21/* Infineon specific definitions */
22/* maximum number of WTX-packages */
23#define TPM_MAX_WTX_PACKAGES 50
24/* msleep-Time for WTX-packages */
25#define TPM_WTX_MSLEEP_TIME 20
26/* msleep-Time --> Interval to check status register */
27#define TPM_MSLEEP_TIME 3
28/* gives number of max. msleep()-calls before throwing timeout */
29#define TPM_MAX_TRIES 5000
30#define TPM_INFINEON_DEV_VEN_VALUE 0x15D1
31
32/* These values will be filled after ACPI-call */
33static int TPM_INF_DATA = 0;
34static int TPM_INF_ADDR = 0;
35
36/* TPM header definitions */
37enum infineon_tpm_header {
38 TPM_VL_VER = 0x01,
39 TPM_VL_CHANNEL_CONTROL = 0x07,
40 TPM_VL_CHANNEL_PERSONALISATION = 0x0A,
41 TPM_VL_CHANNEL_TPM = 0x0B,
42 TPM_VL_CONTROL = 0x00,
43 TPM_INF_NAK = 0x15,
44 TPM_CTRL_WTX = 0x10,
45 TPM_CTRL_WTX_ABORT = 0x18,
46 TPM_CTRL_WTX_ABORT_ACK = 0x18,
47 TPM_CTRL_ERROR = 0x20,
48 TPM_CTRL_CHAININGACK = 0x40,
49 TPM_CTRL_CHAINING = 0x80,
50 TPM_CTRL_DATA = 0x04,
51 TPM_CTRL_DATA_CHA = 0x84,
52 TPM_CTRL_DATA_CHA_ACK = 0xC4
53};
54
55enum infineon_tpm_register {
56 WRFIFO = 0x00,
57 RDFIFO = 0x01,
58 STAT = 0x02,
59 CMD = 0x03
60};
61
62enum infineon_tpm_command_bits {
63 CMD_DIS = 0x00,
64 CMD_LP = 0x01,
65 CMD_RES = 0x02,
66 CMD_IRQC = 0x06
67};
68
69enum infineon_tpm_status_bits {
70 STAT_XFE = 0x00,
71 STAT_LPA = 0x01,
72 STAT_FOK = 0x02,
73 STAT_TOK = 0x03,
74 STAT_IRQA = 0x06,
75 STAT_RDA = 0x07
76};
77
78/* some outgoing values */
79enum infineon_tpm_values {
80 CHIP_ID1 = 0x20,
81 CHIP_ID2 = 0x21,
82 TPM_DAR = 0x30,
83 RESET_LP_IRQC_DISABLE = 0x41,
84 ENABLE_REGISTER_PAIR = 0x55,
85 IOLIMH = 0x60,
86 IOLIML = 0x61,
87 DISABLE_REGISTER_PAIR = 0xAA,
88 IDVENL = 0xF1,
89 IDVENH = 0xF2,
90 IDPDL = 0xF3,
91 IDPDH = 0xF4
92};
93
94static int number_of_wtx;
95
96static int empty_fifo(struct tpm_chip *chip, int clear_wrfifo)
97{
98 int status;
99 int check = 0;
100 int i;
101
102 if (clear_wrfifo) {
103 for (i = 0; i < 4096; i++) {
104 status = inb(chip->vendor->base + WRFIFO);
105 if (status == 0xff) {
106 if (check == 5)
107 break;
108 else
109 check++;
110 }
111 }
112 }
113 /* Note: The values which are currently in the FIFO of the TPM
114 are thrown away since there is no usage for them. Usually,
115 this has nothing to say, since the TPM will give its answer
116 immediately or will be aborted anyway, so the data here is
117 usually garbage and useless.
118 We have to clean this, because the next communication with
119 the TPM would be rubbish, if there is still some old data
120 in the Read FIFO.
121 */
122 i = 0;
123 do {
124 status = inb(chip->vendor->base + RDFIFO);
125 status = inb(chip->vendor->base + STAT);
126 i++;
127 if (i == TPM_MAX_TRIES)
128 return -EIO;
129 } while ((status & (1 << STAT_RDA)) != 0);
130 return 0;
131}
132
133static int wait(struct tpm_chip *chip, int wait_for_bit)
134{
135 int status;
136 int i;
137 for (i = 0; i < TPM_MAX_TRIES; i++) {
138 status = inb(chip->vendor->base + STAT);
139 /* check the status-register if wait_for_bit is set */
140 if (status & 1 << wait_for_bit)
141 break;
142 msleep(TPM_MSLEEP_TIME);
143 }
144 if (i == TPM_MAX_TRIES) { /* timeout occurs */
145 if (wait_for_bit == STAT_XFE)
146 dev_err(&chip->pci_dev->dev,
147 "Timeout in wait(STAT_XFE)\n");
148 if (wait_for_bit == STAT_RDA)
149 dev_err(&chip->pci_dev->dev,
150 "Timeout in wait(STAT_RDA)\n");
151 return -EIO;
152 }
153 return 0;
154};
155
156static void wait_and_send(struct tpm_chip *chip, u8 sendbyte)
157{
158 wait(chip, STAT_XFE);
159 outb(sendbyte, chip->vendor->base + WRFIFO);
160}
161
162 /* Note: WTX means Waiting-Time-Extension. Whenever the TPM needs more
163 calculation time, it sends a WTX-package, which has to be acknowledged
164 or aborted. This usually occurs if you are hammering the TPM with key
165 creation. Set the maximum number of WTX-packages in the definitions
166 above, if the number is reached, the waiting-time will be denied
167 and the TPM command has to be resend.
168 */
169
170static void tpm_wtx(struct tpm_chip *chip)
171{
172 number_of_wtx++;
173 dev_info(&chip->pci_dev->dev, "Granting WTX (%02d / %02d)\n",
174 number_of_wtx, TPM_MAX_WTX_PACKAGES);
175 wait_and_send(chip, TPM_VL_VER);
176 wait_and_send(chip, TPM_CTRL_WTX);
177 wait_and_send(chip, 0x00);
178 wait_and_send(chip, 0x00);
179 msleep(TPM_WTX_MSLEEP_TIME);
180}
181
182static void tpm_wtx_abort(struct tpm_chip *chip)
183{
184 dev_info(&chip->pci_dev->dev, "Aborting WTX\n");
185 wait_and_send(chip, TPM_VL_VER);
186 wait_and_send(chip, TPM_CTRL_WTX_ABORT);
187 wait_and_send(chip, 0x00);
188 wait_and_send(chip, 0x00);
189 number_of_wtx = 0;
190 msleep(TPM_WTX_MSLEEP_TIME);
191}
192
193static int tpm_inf_recv(struct tpm_chip *chip, u8 * buf, size_t count)
194{
195 int i;
196 int ret;
197 u32 size = 0;
198
199recv_begin:
200 /* start receiving header */
201 for (i = 0; i < 4; i++) {
202 ret = wait(chip, STAT_RDA);
203 if (ret)
204 return -EIO;
205 buf[i] = inb(chip->vendor->base + RDFIFO);
206 }
207
208 if (buf[0] != TPM_VL_VER) {
209 dev_err(&chip->pci_dev->dev,
210 "Wrong transport protocol implementation!\n");
211 return -EIO;
212 }
213
214 if (buf[1] == TPM_CTRL_DATA) {
215 /* size of the data received */
216 size = ((buf[2] << 8) | buf[3]);
217
218 for (i = 0; i < size; i++) {
219 wait(chip, STAT_RDA);
220 buf[i] = inb(chip->vendor->base + RDFIFO);
221 }
222
223 if ((size == 0x6D00) && (buf[1] == 0x80)) {
224 dev_err(&chip->pci_dev->dev,
225 "Error handling on vendor layer!\n");
226 return -EIO;
227 }
228
229 for (i = 0; i < size; i++)
230 buf[i] = buf[i + 6];
231
232 size = size - 6;
233 return size;
234 }
235
236 if (buf[1] == TPM_CTRL_WTX) {
237 dev_info(&chip->pci_dev->dev, "WTX-package received\n");
238 if (number_of_wtx < TPM_MAX_WTX_PACKAGES) {
239 tpm_wtx(chip);
240 goto recv_begin;
241 } else {
242 tpm_wtx_abort(chip);
243 goto recv_begin;
244 }
245 }
246
247 if (buf[1] == TPM_CTRL_WTX_ABORT_ACK) {
248 dev_info(&chip->pci_dev->dev, "WTX-abort acknowledged\n");
249 return size;
250 }
251
252 if (buf[1] == TPM_CTRL_ERROR) {
253 dev_err(&chip->pci_dev->dev, "ERROR-package received:\n");
254 if (buf[4] == TPM_INF_NAK)
255 dev_err(&chip->pci_dev->dev,
256 "-> Negative acknowledgement"
257 " - retransmit command!\n");
258 return -EIO;
259 }
260 return -EIO;
261}
262
263static int tpm_inf_send(struct tpm_chip *chip, u8 * buf, size_t count)
264{
265 int i;
266 int ret;
267 u8 count_high, count_low, count_4, count_3, count_2, count_1;
268
269 /* Disabling Reset, LP and IRQC */
270 outb(RESET_LP_IRQC_DISABLE, chip->vendor->base + CMD);
271
272 ret = empty_fifo(chip, 1);
273 if (ret) {
274 dev_err(&chip->pci_dev->dev, "Timeout while clearing FIFO\n");
275 return -EIO;
276 }
277
278 ret = wait(chip, STAT_XFE);
279 if (ret)
280 return -EIO;
281
282 count_4 = (count & 0xff000000) >> 24;
283 count_3 = (count & 0x00ff0000) >> 16;
284 count_2 = (count & 0x0000ff00) >> 8;
285 count_1 = (count & 0x000000ff);
286 count_high = ((count + 6) & 0xffffff00) >> 8;
287 count_low = ((count + 6) & 0x000000ff);
288
289 /* Sending Header */
290 wait_and_send(chip, TPM_VL_VER);
291 wait_and_send(chip, TPM_CTRL_DATA);
292 wait_and_send(chip, count_high);
293 wait_and_send(chip, count_low);
294
295 /* Sending Data Header */
296 wait_and_send(chip, TPM_VL_VER);
297 wait_and_send(chip, TPM_VL_CHANNEL_TPM);
298 wait_and_send(chip, count_4);
299 wait_and_send(chip, count_3);
300 wait_and_send(chip, count_2);
301 wait_and_send(chip, count_1);
302
303 /* Sending Data */
304 for (i = 0; i < count; i++) {
305 wait_and_send(chip, buf[i]);
306 }
307 return count;
308}
309
310static void tpm_inf_cancel(struct tpm_chip *chip)
311{
312 /*
313 Since we are using the legacy mode to communicate
314 with the TPM, we have no cancel functions, but have
315 a workaround for interrupting the TPM through WTX.
316 */
317}
318
319static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
320static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
321static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
322static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel);
323
324static struct attribute *inf_attrs[] = {
325 &dev_attr_pubek.attr,
326 &dev_attr_pcrs.attr,
327 &dev_attr_caps.attr,
328 &dev_attr_cancel.attr,
329 NULL,
330};
331
332static struct attribute_group inf_attr_grp = {.attrs = inf_attrs };
333
334static struct file_operations inf_ops = {
335 .owner = THIS_MODULE,
336 .llseek = no_llseek,
337 .open = tpm_open,
338 .read = tpm_read,
339 .write = tpm_write,
340 .release = tpm_release,
341};
342
343static struct tpm_vendor_specific tpm_inf = {
344 .recv = tpm_inf_recv,
345 .send = tpm_inf_send,
346 .cancel = tpm_inf_cancel,
347 .req_complete_mask = 0,
348 .req_complete_val = 0,
349 .attr_group = &inf_attr_grp,
350 .miscdev = {.fops = &inf_ops,},
351};
352
353static const struct pnp_device_id tpm_pnp_tbl[] = {
354 /* Infineon TPMs */
355 {"IFX0101", 0},
356 {"IFX0102", 0},
357 {"", 0}
358};
359
360static int __devinit tpm_inf_acpi_probe(struct pnp_dev *dev,
361 const struct pnp_device_id *dev_id)
362{
363 TPM_INF_ADDR = (pnp_port_start(dev, 0) & 0xff);
364 TPM_INF_DATA = ((TPM_INF_ADDR + 1) & 0xff);
365 tpm_inf.base = pnp_port_start(dev, 1);
366 dev_info(&dev->dev, "Found %s with ID %s\n",
367 dev->name, dev_id->id);
368 if (!((tpm_inf.base >> 8) & 0xff))
369 tpm_inf.base = 0;
370 return 0;
371}
372
373static struct pnp_driver tpm_inf_pnp = {
374 .name = "tpm_inf_pnp",
375 .id_table = tpm_pnp_tbl,
376 .probe = tpm_inf_acpi_probe,
377};
378
379static int __devinit tpm_inf_probe(struct pci_dev *pci_dev,
380 const struct pci_device_id *pci_id)
381{
382 int rc = 0;
383 u8 iol, ioh;
384 int vendorid[2];
385 int version[2];
386 int productid[2];
387 char chipname[20];
388
389 if (pci_enable_device(pci_dev))
390 return -EIO;
391
392 dev_info(&pci_dev->dev, "LPC-bus found at 0x%x\n", pci_id->device);
393
394 /* read IO-ports from ACPI */
395 pnp_register_driver(&tpm_inf_pnp);
396 pnp_unregister_driver(&tpm_inf_pnp);
397
398 /* Make sure, we have received valid config ports */
399 if (!TPM_INF_ADDR) {
400 pci_disable_device(pci_dev);
401 return -EIO;
402 }
403
404 /* query chip for its vendor, its version number a.s.o. */
405 outb(ENABLE_REGISTER_PAIR, TPM_INF_ADDR);
406 outb(IDVENL, TPM_INF_ADDR);
407 vendorid[1] = inb(TPM_INF_DATA);
408 outb(IDVENH, TPM_INF_ADDR);
409 vendorid[0] = inb(TPM_INF_DATA);
410 outb(IDPDL, TPM_INF_ADDR);
411 productid[1] = inb(TPM_INF_DATA);
412 outb(IDPDH, TPM_INF_ADDR);
413 productid[0] = inb(TPM_INF_DATA);
414 outb(CHIP_ID1, TPM_INF_ADDR);
415 version[1] = inb(TPM_INF_DATA);
416 outb(CHIP_ID2, TPM_INF_ADDR);
417 version[0] = inb(TPM_INF_DATA);
418
419 switch ((productid[0] << 8) | productid[1]) {
420 case 6:
421 sprintf(chipname, " (SLD 9630 TT 1.1)");
422 break;
423 case 11:
424 sprintf(chipname, " (SLB 9635 TT 1.2)");
425 break;
426 default:
427 sprintf(chipname, " (unknown chip)");
428 break;
429 }
430 chipname[19] = 0;
431
432 if ((vendorid[0] << 8 | vendorid[1]) == (TPM_INFINEON_DEV_VEN_VALUE)) {
433
434 if (tpm_inf.base == 0) {
435 dev_err(&pci_dev->dev, "No IO-ports found!\n");
436 pci_disable_device(pci_dev);
437 return -EIO;
438 }
439 /* configure TPM with IO-ports */
440 outb(IOLIMH, TPM_INF_ADDR);
441 outb(((tpm_inf.base >> 8) & 0xff), TPM_INF_DATA);
442 outb(IOLIML, TPM_INF_ADDR);
443 outb((tpm_inf.base & 0xff), TPM_INF_DATA);
444
445 /* control if IO-ports are set correctly */
446 outb(IOLIMH, TPM_INF_ADDR);
447 ioh = inb(TPM_INF_DATA);
448 outb(IOLIML, TPM_INF_ADDR);
449 iol = inb(TPM_INF_DATA);
450
451 if ((ioh << 8 | iol) != tpm_inf.base) {
452 dev_err(&pci_dev->dev,
453 "Could not set IO-ports to %04x\n",
454 tpm_inf.base);
455 pci_disable_device(pci_dev);
456 return -EIO;
457 }
458
459 /* activate register */
460 outb(TPM_DAR, TPM_INF_ADDR);
461 outb(0x01, TPM_INF_DATA);
462 outb(DISABLE_REGISTER_PAIR, TPM_INF_ADDR);
463
464 /* disable RESET, LP and IRQC */
465 outb(RESET_LP_IRQC_DISABLE, tpm_inf.base + CMD);
466
467 /* Finally, we're done, print some infos */
468 dev_info(&pci_dev->dev, "TPM found: "
469 "config base 0x%x, "
470 "io base 0x%x, "
471 "chip version %02x%02x, "
472 "vendor id %x%x (Infineon), "
473 "product id %02x%02x"
474 "%s\n",
475 TPM_INF_ADDR,
476 tpm_inf.base,
477 version[0], version[1],
478 vendorid[0], vendorid[1],
479 productid[0], productid[1], chipname);
480
481 rc = tpm_register_hardware(pci_dev, &tpm_inf);
482 if (rc < 0) {
483 pci_disable_device(pci_dev);
484 return -ENODEV;
485 }
486 return 0;
487 } else {
488 dev_info(&pci_dev->dev, "No Infineon TPM found!\n");
489 pci_disable_device(pci_dev);
490 return -ENODEV;
491 }
492}
493
494static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
495 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0)},
496 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_12)},
497 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
498 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
499 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
500 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)},
501 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)},
502 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2)},
503 {0,}
504};
505
506MODULE_DEVICE_TABLE(pci, tpm_pci_tbl);
507
508static struct pci_driver inf_pci_driver = {
509 .name = "tpm_inf",
510 .id_table = tpm_pci_tbl,
511 .probe = tpm_inf_probe,
512 .remove = __devexit_p(tpm_remove),
513 .suspend = tpm_pm_suspend,
514 .resume = tpm_pm_resume,
515};
516
517static int __init init_inf(void)
518{
519 return pci_register_driver(&inf_pci_driver);
520}
521
522static void __exit cleanup_inf(void)
523{
524 pci_unregister_driver(&inf_pci_driver);
525}
526
527module_init(init_inf);
528module_exit(cleanup_inf);
529
530MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>");
531MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2");
532MODULE_VERSION("1.5");
533MODULE_LICENSE("GPL");
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c
index 9cce833a0923..b4127348c063 100644
--- a/drivers/char/tpm/tpm_nsc.c
+++ b/drivers/char/tpm/tpm_nsc.c
@@ -22,43 +22,52 @@
22#include "tpm.h" 22#include "tpm.h"
23 23
24/* National definitions */ 24/* National definitions */
25#define TPM_NSC_BASE 0x360 25enum tpm_nsc_addr{
26#define TPM_NSC_IRQ 0x07 26 TPM_NSC_IRQ = 0x07,
27 TPM_NSC_BASE0_HI = 0x60,
28 TPM_NSC_BASE0_LO = 0x61,
29 TPM_NSC_BASE1_HI = 0x62,
30 TPM_NSC_BASE1_LO = 0x63
31};
27 32
28#define NSC_LDN_INDEX 0x07 33enum tpm_nsc_index {
29#define NSC_SID_INDEX 0x20 34 NSC_LDN_INDEX = 0x07,
30#define NSC_LDC_INDEX 0x30 35 NSC_SID_INDEX = 0x20,
31#define NSC_DIO_INDEX 0x60 36 NSC_LDC_INDEX = 0x30,
32#define NSC_CIO_INDEX 0x62 37 NSC_DIO_INDEX = 0x60,
33#define NSC_IRQ_INDEX 0x70 38 NSC_CIO_INDEX = 0x62,
34#define NSC_ITS_INDEX 0x71 39 NSC_IRQ_INDEX = 0x70,
40 NSC_ITS_INDEX = 0x71
41};
35 42
36#define NSC_STATUS 0x01 43enum tpm_nsc_status_loc {
37#define NSC_COMMAND 0x01 44 NSC_STATUS = 0x01,
38#define NSC_DATA 0x00 45 NSC_COMMAND = 0x01,
46 NSC_DATA = 0x00
47};
39 48
40/* status bits */ 49/* status bits */
41#define NSC_STATUS_OBF 0x01 /* output buffer full */ 50enum tpm_nsc_status {
42#define NSC_STATUS_IBF 0x02 /* input buffer full */ 51 NSC_STATUS_OBF = 0x01, /* output buffer full */
43#define NSC_STATUS_F0 0x04 /* F0 */ 52 NSC_STATUS_IBF = 0x02, /* input buffer full */
44#define NSC_STATUS_A2 0x08 /* A2 */ 53 NSC_STATUS_F0 = 0x04, /* F0 */
45#define NSC_STATUS_RDY 0x10 /* ready to receive command */ 54 NSC_STATUS_A2 = 0x08, /* A2 */
46#define NSC_STATUS_IBR 0x20 /* ready to receive data */ 55 NSC_STATUS_RDY = 0x10, /* ready to receive command */
56 NSC_STATUS_IBR = 0x20 /* ready to receive data */
57};
47 58
48/* command bits */ 59/* command bits */
49#define NSC_COMMAND_NORMAL 0x01 /* normal mode */ 60enum tpm_nsc_cmd_mode {
50#define NSC_COMMAND_EOC 0x03 61 NSC_COMMAND_NORMAL = 0x01, /* normal mode */
51#define NSC_COMMAND_CANCEL 0x22 62 NSC_COMMAND_EOC = 0x03,
52 63 NSC_COMMAND_CANCEL = 0x22
64};
53/* 65/*
54 * Wait for a certain status to appear 66 * Wait for a certain status to appear
55 */ 67 */
56static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data) 68static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
57{ 69{
58 int expired = 0; 70 unsigned long stop;
59 struct timer_list status_timer =
60 TIMER_INITIALIZER(tpm_time_expired, jiffies + 10 * HZ,
61 (unsigned long) &expired);
62 71
63 /* status immediately available check */ 72 /* status immediately available check */
64 *data = inb(chip->vendor->base + NSC_STATUS); 73 *data = inb(chip->vendor->base + NSC_STATUS);
@@ -66,17 +75,14 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
66 return 0; 75 return 0;
67 76
68 /* wait for status */ 77 /* wait for status */
69 add_timer(&status_timer); 78 stop = jiffies + 10 * HZ;
70 do { 79 do {
71 set_current_state(TASK_UNINTERRUPTIBLE); 80 msleep(TPM_TIMEOUT);
72 schedule_timeout(TPM_TIMEOUT);
73 *data = inb(chip->vendor->base + 1); 81 *data = inb(chip->vendor->base + 1);
74 if ((*data & mask) == val) { 82 if ((*data & mask) == val)
75 del_singleshot_timer_sync(&status_timer);
76 return 0; 83 return 0;
77 }
78 } 84 }
79 while (!expired); 85 while (time_before(jiffies, stop));
80 86
81 return -EBUSY; 87 return -EBUSY;
82} 88}
@@ -84,10 +90,7 @@ static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data)
84static int nsc_wait_for_ready(struct tpm_chip *chip) 90static int nsc_wait_for_ready(struct tpm_chip *chip)
85{ 91{
86 int status; 92 int status;
87 int expired = 0; 93 unsigned long stop;
88 struct timer_list status_timer =
89 TIMER_INITIALIZER(tpm_time_expired, jiffies + 100,
90 (unsigned long) &expired);
91 94
92 /* status immediately available check */ 95 /* status immediately available check */
93 status = inb(chip->vendor->base + NSC_STATUS); 96 status = inb(chip->vendor->base + NSC_STATUS);
@@ -97,19 +100,16 @@ static int nsc_wait_for_ready(struct tpm_chip *chip)
97 return 0; 100 return 0;
98 101
99 /* wait for status */ 102 /* wait for status */
100 add_timer(&status_timer); 103 stop = jiffies + 100;
101 do { 104 do {
102 set_current_state(TASK_UNINTERRUPTIBLE); 105 msleep(TPM_TIMEOUT);
103 schedule_timeout(TPM_TIMEOUT);
104 status = inb(chip->vendor->base + NSC_STATUS); 106 status = inb(chip->vendor->base + NSC_STATUS);
105 if (status & NSC_STATUS_OBF) 107 if (status & NSC_STATUS_OBF)
106 status = inb(chip->vendor->base + NSC_DATA); 108 status = inb(chip->vendor->base + NSC_DATA);
107 if (status & NSC_STATUS_RDY) { 109 if (status & NSC_STATUS_RDY)
108 del_singleshot_timer_sync(&status_timer);
109 return 0; 110 return 0;
110 }
111 } 111 }
112 while (!expired); 112 while (time_before(jiffies, stop));
113 113
114 dev_info(&chip->pci_dev->dev, "wait for ready failed\n"); 114 dev_info(&chip->pci_dev->dev, "wait for ready failed\n");
115 return -EBUSY; 115 return -EBUSY;
@@ -150,7 +150,8 @@ static int tpm_nsc_recv(struct tpm_chip *chip, u8 * buf, size_t count)
150 *p = inb(chip->vendor->base + NSC_DATA); 150 *p = inb(chip->vendor->base + NSC_DATA);
151 } 151 }
152 152
153 if ((data & NSC_STATUS_F0) == 0) { 153 if ((data & NSC_STATUS_F0) == 0 &&
154 (wait_for_stat(chip, NSC_STATUS_F0, NSC_STATUS_F0, &data) < 0)) {
154 dev_err(&chip->pci_dev->dev, "F0 not set\n"); 155 dev_err(&chip->pci_dev->dev, "F0 not set\n");
155 return -EIO; 156 return -EIO;
156 } 157 }
@@ -228,100 +229,95 @@ static struct file_operations nsc_ops = {
228 .release = tpm_release, 229 .release = tpm_release,
229}; 230};
230 231
232static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL);
233static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL);
234static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL);
235static DEVICE_ATTR(cancel, S_IWUSR|S_IWGRP, NULL, tpm_store_cancel);
236
237static struct attribute * nsc_attrs[] = {
238 &dev_attr_pubek.attr,
239 &dev_attr_pcrs.attr,
240 &dev_attr_caps.attr,
241 &dev_attr_cancel.attr,
242 0,
243};
244
245static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs };
246
231static struct tpm_vendor_specific tpm_nsc = { 247static struct tpm_vendor_specific tpm_nsc = {
232 .recv = tpm_nsc_recv, 248 .recv = tpm_nsc_recv,
233 .send = tpm_nsc_send, 249 .send = tpm_nsc_send,
234 .cancel = tpm_nsc_cancel, 250 .cancel = tpm_nsc_cancel,
235 .req_complete_mask = NSC_STATUS_OBF, 251 .req_complete_mask = NSC_STATUS_OBF,
236 .req_complete_val = NSC_STATUS_OBF, 252 .req_complete_val = NSC_STATUS_OBF,
237 .base = TPM_NSC_BASE, 253 .req_canceled = NSC_STATUS_RDY,
254 .attr_group = &nsc_attr_grp,
238 .miscdev = { .fops = &nsc_ops, }, 255 .miscdev = { .fops = &nsc_ops, },
239
240}; 256};
241 257
242static int __devinit tpm_nsc_init(struct pci_dev *pci_dev, 258static int __devinit tpm_nsc_init(struct pci_dev *pci_dev,
243 const struct pci_device_id *pci_id) 259 const struct pci_device_id *pci_id)
244{ 260{
245 int rc = 0; 261 int rc = 0;
262 int lo, hi;
263 int nscAddrBase = TPM_ADDR;
264
246 265
247 if (pci_enable_device(pci_dev)) 266 if (pci_enable_device(pci_dev))
248 return -EIO; 267 return -EIO;
249 268
250 if (tpm_lpc_bus_init(pci_dev, TPM_NSC_BASE)) { 269 /* select PM channel 1 */
251 rc = -ENODEV; 270 tpm_write_index(nscAddrBase,NSC_LDN_INDEX, 0x12);
252 goto out_err;
253 }
254 271
255 /* verify that it is a National part (SID) */ 272 /* verify that it is a National part (SID) */
256 if (tpm_read_index(NSC_SID_INDEX) != 0xEF) { 273 if (tpm_read_index(TPM_ADDR, NSC_SID_INDEX) != 0xEF) {
257 rc = -ENODEV; 274 nscAddrBase = (tpm_read_index(TPM_SUPERIO_ADDR, 0x2C)<<8)|
258 goto out_err; 275 (tpm_read_index(TPM_SUPERIO_ADDR, 0x2B)&0xFE);
276 if (tpm_read_index(nscAddrBase, NSC_SID_INDEX) != 0xF6) {
277 rc = -ENODEV;
278 goto out_err;
279 }
259 } 280 }
260 281
282 hi = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_HI);
283 lo = tpm_read_index(nscAddrBase, TPM_NSC_BASE0_LO);
284 tpm_nsc.base = (hi<<8) | lo;
285
261 dev_dbg(&pci_dev->dev, "NSC TPM detected\n"); 286 dev_dbg(&pci_dev->dev, "NSC TPM detected\n");
262 dev_dbg(&pci_dev->dev, 287 dev_dbg(&pci_dev->dev,
263 "NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n", 288 "NSC LDN 0x%x, SID 0x%x, SRID 0x%x\n",
264 tpm_read_index(0x07), tpm_read_index(0x20), 289 tpm_read_index(nscAddrBase,0x07), tpm_read_index(nscAddrBase,0x20),
265 tpm_read_index(0x27)); 290 tpm_read_index(nscAddrBase,0x27));
266 dev_dbg(&pci_dev->dev, 291 dev_dbg(&pci_dev->dev,
267 "NSC SIOCF1 0x%x SIOCF5 0x%x SIOCF6 0x%x SIOCF8 0x%x\n", 292 "NSC SIOCF1 0x%x SIOCF5 0x%x SIOCF6 0x%x SIOCF8 0x%x\n",
268 tpm_read_index(0x21), tpm_read_index(0x25), 293 tpm_read_index(nscAddrBase,0x21), tpm_read_index(nscAddrBase,0x25),
269 tpm_read_index(0x26), tpm_read_index(0x28)); 294 tpm_read_index(nscAddrBase,0x26), tpm_read_index(nscAddrBase,0x28));
270 dev_dbg(&pci_dev->dev, "NSC IO Base0 0x%x\n", 295 dev_dbg(&pci_dev->dev, "NSC IO Base0 0x%x\n",
271 (tpm_read_index(0x60) << 8) | tpm_read_index(0x61)); 296 (tpm_read_index(nscAddrBase,0x60) << 8) | tpm_read_index(nscAddrBase,0x61));
272 dev_dbg(&pci_dev->dev, "NSC IO Base1 0x%x\n", 297 dev_dbg(&pci_dev->dev, "NSC IO Base1 0x%x\n",
273 (tpm_read_index(0x62) << 8) | tpm_read_index(0x63)); 298 (tpm_read_index(nscAddrBase,0x62) << 8) | tpm_read_index(nscAddrBase,0x63));
274 dev_dbg(&pci_dev->dev, "NSC Interrupt number and wakeup 0x%x\n", 299 dev_dbg(&pci_dev->dev, "NSC Interrupt number and wakeup 0x%x\n",
275 tpm_read_index(0x70)); 300 tpm_read_index(nscAddrBase,0x70));
276 dev_dbg(&pci_dev->dev, "NSC IRQ type select 0x%x\n", 301 dev_dbg(&pci_dev->dev, "NSC IRQ type select 0x%x\n",
277 tpm_read_index(0x71)); 302 tpm_read_index(nscAddrBase,0x71));
278 dev_dbg(&pci_dev->dev, 303 dev_dbg(&pci_dev->dev,
279 "NSC DMA channel select0 0x%x, select1 0x%x\n", 304 "NSC DMA channel select0 0x%x, select1 0x%x\n",
280 tpm_read_index(0x74), tpm_read_index(0x75)); 305 tpm_read_index(nscAddrBase,0x74), tpm_read_index(nscAddrBase,0x75));
281 dev_dbg(&pci_dev->dev, 306 dev_dbg(&pci_dev->dev,
282 "NSC Config " 307 "NSC Config "
283 "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n", 308 "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x\n",
284 tpm_read_index(0xF0), tpm_read_index(0xF1), 309 tpm_read_index(nscAddrBase,0xF0), tpm_read_index(nscAddrBase,0xF1),
285 tpm_read_index(0xF2), tpm_read_index(0xF3), 310 tpm_read_index(nscAddrBase,0xF2), tpm_read_index(nscAddrBase,0xF3),
286 tpm_read_index(0xF4), tpm_read_index(0xF5), 311 tpm_read_index(nscAddrBase,0xF4), tpm_read_index(nscAddrBase,0xF5),
287 tpm_read_index(0xF6), tpm_read_index(0xF7), 312 tpm_read_index(nscAddrBase,0xF6), tpm_read_index(nscAddrBase,0xF7),
288 tpm_read_index(0xF8), tpm_read_index(0xF9)); 313 tpm_read_index(nscAddrBase,0xF8), tpm_read_index(nscAddrBase,0xF9));
289 314
290 dev_info(&pci_dev->dev, 315 dev_info(&pci_dev->dev,
291 "NSC PC21100 TPM revision %d\n", 316 "NSC TPM revision %d\n",
292 tpm_read_index(0x27) & 0x1F); 317 tpm_read_index(nscAddrBase, 0x27) & 0x1F);
293
294 if (tpm_read_index(NSC_LDC_INDEX) == 0)
295 dev_info(&pci_dev->dev, ": NSC TPM not active\n");
296
297 /* select PM channel 1 */
298 tpm_write_index(NSC_LDN_INDEX, 0x12);
299 tpm_read_index(NSC_LDN_INDEX);
300
301 /* disable the DPM module */
302 tpm_write_index(NSC_LDC_INDEX, 0);
303 tpm_read_index(NSC_LDC_INDEX);
304
305 /* set the data register base addresses */
306 tpm_write_index(NSC_DIO_INDEX, TPM_NSC_BASE >> 8);
307 tpm_write_index(NSC_DIO_INDEX + 1, TPM_NSC_BASE);
308 tpm_read_index(NSC_DIO_INDEX);
309 tpm_read_index(NSC_DIO_INDEX + 1);
310
311 /* set the command register base addresses */
312 tpm_write_index(NSC_CIO_INDEX, (TPM_NSC_BASE + 1) >> 8);
313 tpm_write_index(NSC_CIO_INDEX + 1, (TPM_NSC_BASE + 1));
314 tpm_read_index(NSC_DIO_INDEX);
315 tpm_read_index(NSC_DIO_INDEX + 1);
316
317 /* set the interrupt number to be used for the host interface */
318 tpm_write_index(NSC_IRQ_INDEX, TPM_NSC_IRQ);
319 tpm_write_index(NSC_ITS_INDEX, 0x00);
320 tpm_read_index(NSC_IRQ_INDEX);
321 318
322 /* enable the DPM module */ 319 /* enable the DPM module */
323 tpm_write_index(NSC_LDC_INDEX, 0x01); 320 tpm_write_index(nscAddrBase, NSC_LDC_INDEX, 0x01);
324 tpm_read_index(NSC_LDC_INDEX);
325 321
326 if ((rc = tpm_register_hardware(pci_dev, &tpm_nsc)) < 0) 322 if ((rc = tpm_register_hardware(pci_dev, &tpm_nsc)) < 0)
327 goto out_err; 323 goto out_err;
@@ -339,6 +335,9 @@ static struct pci_device_id tpm_pci_tbl[] __devinitdata = {
339 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)}, 335 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_0)},
340 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)}, 336 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801DB_12)},
341 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)}, 337 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801EB_0)},
338 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_0)},
339 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_1)},
340 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0)},
342 {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)}, 341 {PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8111_LPC)},
343 {0,} 342 {0,}
344}; 343};
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 26e5e19ed854..6e4be3bb2d89 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -94,6 +94,7 @@
94#include <linux/idr.h> 94#include <linux/idr.h>
95#include <linux/wait.h> 95#include <linux/wait.h>
96#include <linux/bitops.h> 96#include <linux/bitops.h>
97#include <linux/delay.h>
97 98
98#include <asm/uaccess.h> 99#include <asm/uaccess.h>
99#include <asm/system.h> 100#include <asm/system.h>
@@ -251,7 +252,7 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num)
251 252
252static DEFINE_SPINLOCK(tty_ldisc_lock); 253static DEFINE_SPINLOCK(tty_ldisc_lock);
253static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); 254static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait);
254static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */ 255static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */
255 256
256int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc) 257int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
257{ 258{
@@ -262,24 +263,35 @@ int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc)
262 return -EINVAL; 263 return -EINVAL;
263 264
264 spin_lock_irqsave(&tty_ldisc_lock, flags); 265 spin_lock_irqsave(&tty_ldisc_lock, flags);
265 if (new_ldisc) { 266 tty_ldiscs[disc] = *new_ldisc;
266 tty_ldiscs[disc] = *new_ldisc; 267 tty_ldiscs[disc].num = disc;
267 tty_ldiscs[disc].num = disc; 268 tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED;
268 tty_ldiscs[disc].flags |= LDISC_FLAG_DEFINED; 269 tty_ldiscs[disc].refcount = 0;
269 tty_ldiscs[disc].refcount = 0;
270 } else {
271 if(tty_ldiscs[disc].refcount)
272 ret = -EBUSY;
273 else
274 tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED;
275 }
276 spin_unlock_irqrestore(&tty_ldisc_lock, flags); 270 spin_unlock_irqrestore(&tty_ldisc_lock, flags);
277 271
278 return ret; 272 return ret;
279} 273}
280
281EXPORT_SYMBOL(tty_register_ldisc); 274EXPORT_SYMBOL(tty_register_ldisc);
282 275
276int tty_unregister_ldisc(int disc)
277{
278 unsigned long flags;
279 int ret = 0;
280
281 if (disc < N_TTY || disc >= NR_LDISCS)
282 return -EINVAL;
283
284 spin_lock_irqsave(&tty_ldisc_lock, flags);
285 if (tty_ldiscs[disc].refcount)
286 ret = -EBUSY;
287 else
288 tty_ldiscs[disc].flags &= ~LDISC_FLAG_DEFINED;
289 spin_unlock_irqrestore(&tty_ldisc_lock, flags);
290
291 return ret;
292}
293EXPORT_SYMBOL(tty_unregister_ldisc);
294
283struct tty_ldisc *tty_ldisc_get(int disc) 295struct tty_ldisc *tty_ldisc_get(int disc)
284{ 296{
285 unsigned long flags; 297 unsigned long flags;
@@ -2169,12 +2181,11 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
2169 return tty_set_ldisc(tty, ldisc); 2181 return tty_set_ldisc(tty, ldisc);
2170} 2182}
2171 2183
2172static int send_break(struct tty_struct *tty, int duration) 2184static int send_break(struct tty_struct *tty, unsigned int duration)
2173{ 2185{
2174 tty->driver->break_ctl(tty, -1); 2186 tty->driver->break_ctl(tty, -1);
2175 if (!signal_pending(current)) { 2187 if (!signal_pending(current)) {
2176 set_current_state(TASK_INTERRUPTIBLE); 2188 msleep_interruptible(duration);
2177 schedule_timeout(duration);
2178 } 2189 }
2179 tty->driver->break_ctl(tty, 0); 2190 tty->driver->break_ctl(tty, 0);
2180 if (signal_pending(current)) 2191 if (signal_pending(current))
@@ -2355,10 +2366,10 @@ int tty_ioctl(struct inode * inode, struct file * file,
2355 * all by anyone? 2366 * all by anyone?
2356 */ 2367 */
2357 if (!arg) 2368 if (!arg)
2358 return send_break(tty, HZ/4); 2369 return send_break(tty, 250);
2359 return 0; 2370 return 0;
2360 case TCSBRKP: /* support for POSIX tcsendbreak() */ 2371 case TCSBRKP: /* support for POSIX tcsendbreak() */
2361 return send_break(tty, arg ? arg*(HZ/10) : HZ/4); 2372 return send_break(tty, arg ? arg*100 : 250);
2362 2373
2363 case TIOCMGET: 2374 case TIOCMGET:
2364 return tty_tiocmget(tty, file, p); 2375 return tty_tiocmget(tty, file, p);
@@ -2654,7 +2665,7 @@ static void tty_default_put_char(struct tty_struct *tty, unsigned char ch)
2654 tty->driver->write(tty, &ch, 1); 2665 tty->driver->write(tty, &ch, 1);
2655} 2666}
2656 2667
2657static struct class_simple *tty_class; 2668static struct class *tty_class;
2658 2669
2659/** 2670/**
2660 * tty_register_device - register a tty device 2671 * tty_register_device - register a tty device
@@ -2687,7 +2698,7 @@ void tty_register_device(struct tty_driver *driver, unsigned index,
2687 pty_line_name(driver, index, name); 2698 pty_line_name(driver, index, name);
2688 else 2699 else
2689 tty_line_name(driver, index, name); 2700 tty_line_name(driver, index, name);
2690 class_simple_device_add(tty_class, dev, device, name); 2701 class_device_create(tty_class, dev, device, name);
2691} 2702}
2692 2703
2693/** 2704/**
@@ -2701,7 +2712,7 @@ void tty_register_device(struct tty_driver *driver, unsigned index,
2701void tty_unregister_device(struct tty_driver *driver, unsigned index) 2712void tty_unregister_device(struct tty_driver *driver, unsigned index)
2702{ 2713{
2703 devfs_remove("%s%d", driver->devfs_name, index + driver->name_base); 2714 devfs_remove("%s%d", driver->devfs_name, index + driver->name_base);
2704 class_simple_device_remove(MKDEV(driver->major, driver->minor_start) + index); 2715 class_device_destroy(tty_class, MKDEV(driver->major, driver->minor_start) + index);
2705} 2716}
2706 2717
2707EXPORT_SYMBOL(tty_register_device); 2718EXPORT_SYMBOL(tty_register_device);
@@ -2918,7 +2929,7 @@ extern int vty_init(void);
2918 2929
2919static int __init tty_class_init(void) 2930static int __init tty_class_init(void)
2920{ 2931{
2921 tty_class = class_simple_create(THIS_MODULE, "tty"); 2932 tty_class = class_create(THIS_MODULE, "tty");
2922 if (IS_ERR(tty_class)) 2933 if (IS_ERR(tty_class))
2923 return PTR_ERR(tty_class); 2934 return PTR_ERR(tty_class);
2924 return 0; 2935 return 0;
@@ -2947,14 +2958,14 @@ static int __init tty_init(void)
2947 register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0) 2958 register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
2948 panic("Couldn't register /dev/tty driver\n"); 2959 panic("Couldn't register /dev/tty driver\n");
2949 devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty"); 2960 devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty");
2950 class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty"); 2961 class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
2951 2962
2952 cdev_init(&console_cdev, &console_fops); 2963 cdev_init(&console_cdev, &console_fops);
2953 if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) || 2964 if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
2954 register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0) 2965 register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
2955 panic("Couldn't register /dev/console driver\n"); 2966 panic("Couldn't register /dev/console driver\n");
2956 devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console"); 2967 devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console");
2957 class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console"); 2968 class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
2958 2969
2959#ifdef CONFIG_UNIX98_PTYS 2970#ifdef CONFIG_UNIX98_PTYS
2960 cdev_init(&ptmx_cdev, &ptmx_fops); 2971 cdev_init(&ptmx_cdev, &ptmx_fops);
@@ -2962,7 +2973,7 @@ static int __init tty_init(void)
2962 register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0) 2973 register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
2963 panic("Couldn't register /dev/ptmx driver\n"); 2974 panic("Couldn't register /dev/ptmx driver\n");
2964 devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx"); 2975 devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx");
2965 class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx"); 2976 class_device_create(tty_class, MKDEV(TTYAUX_MAJOR, 2), NULL, "ptmx");
2966#endif 2977#endif
2967 2978
2968#ifdef CONFIG_VT 2979#ifdef CONFIG_VT
@@ -2971,7 +2982,7 @@ static int __init tty_init(void)
2971 register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0) 2982 register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
2972 panic("Couldn't register /dev/tty0 driver\n"); 2983 panic("Couldn't register /dev/tty0 driver\n");
2973 devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0"); 2984 devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0");
2974 class_simple_device_add(tty_class, MKDEV(TTY_MAJOR, 0), NULL, "tty0"); 2985 class_device_create(tty_class, MKDEV(TTY_MAJOR, 0), NULL, "tty0");
2975 2986
2976 vty_init(); 2987 vty_init();
2977#endif 2988#endif
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c
index 58597993954f..f19cf9d7792d 100644
--- a/drivers/char/tty_ioctl.c
+++ b/drivers/char/tty_ioctl.c
@@ -476,11 +476,11 @@ int n_tty_ioctl(struct tty_struct * tty, struct file * file,
476 ld = tty_ldisc_ref(tty); 476 ld = tty_ldisc_ref(tty);
477 switch (arg) { 477 switch (arg) {
478 case TCIFLUSH: 478 case TCIFLUSH:
479 if (ld->flush_buffer) 479 if (ld && ld->flush_buffer)
480 ld->flush_buffer(tty); 480 ld->flush_buffer(tty);
481 break; 481 break;
482 case TCIOFLUSH: 482 case TCIOFLUSH:
483 if (ld->flush_buffer) 483 if (ld && ld->flush_buffer)
484 ld->flush_buffer(tty); 484 ld->flush_buffer(tty);
485 /* fall through */ 485 /* fall through */
486 case TCOFLUSH: 486 case TCOFLUSH:
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index 7abe405b8657..79c2928a8817 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -474,7 +474,7 @@ static struct file_operations vcs_fops = {
474 .open = vcs_open, 474 .open = vcs_open,
475}; 475};
476 476
477static struct class_simple *vc_class; 477static struct class *vc_class;
478 478
479void vcs_make_devfs(struct tty_struct *tty) 479void vcs_make_devfs(struct tty_struct *tty)
480{ 480{
@@ -484,26 +484,26 @@ void vcs_make_devfs(struct tty_struct *tty)
484 devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 129), 484 devfs_mk_cdev(MKDEV(VCS_MAJOR, tty->index + 129),
485 S_IFCHR|S_IRUSR|S_IWUSR, 485 S_IFCHR|S_IRUSR|S_IWUSR,
486 "vcc/a%u", tty->index + 1); 486 "vcc/a%u", tty->index + 1);
487 class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, tty->index + 1), NULL, "vcs%u", tty->index + 1); 487 class_device_create(vc_class, MKDEV(VCS_MAJOR, tty->index + 1), NULL, "vcs%u", tty->index + 1);
488 class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, tty->index + 129), NULL, "vcsa%u", tty->index + 1); 488 class_device_create(vc_class, MKDEV(VCS_MAJOR, tty->index + 129), NULL, "vcsa%u", tty->index + 1);
489} 489}
490void vcs_remove_devfs(struct tty_struct *tty) 490void vcs_remove_devfs(struct tty_struct *tty)
491{ 491{
492 devfs_remove("vcc/%u", tty->index + 1); 492 devfs_remove("vcc/%u", tty->index + 1);
493 devfs_remove("vcc/a%u", tty->index + 1); 493 devfs_remove("vcc/a%u", tty->index + 1);
494 class_simple_device_remove(MKDEV(VCS_MAJOR, tty->index + 1)); 494 class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 1));
495 class_simple_device_remove(MKDEV(VCS_MAJOR, tty->index + 129)); 495 class_device_destroy(vc_class, MKDEV(VCS_MAJOR, tty->index + 129));
496} 496}
497 497
498int __init vcs_init(void) 498int __init vcs_init(void)
499{ 499{
500 if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops)) 500 if (register_chrdev(VCS_MAJOR, "vcs", &vcs_fops))
501 panic("unable to get major %d for vcs device", VCS_MAJOR); 501 panic("unable to get major %d for vcs device", VCS_MAJOR);
502 vc_class = class_simple_create(THIS_MODULE, "vc"); 502 vc_class = class_create(THIS_MODULE, "vc");
503 503
504 devfs_mk_cdev(MKDEV(VCS_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/0"); 504 devfs_mk_cdev(MKDEV(VCS_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/0");
505 devfs_mk_cdev(MKDEV(VCS_MAJOR, 128), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/a0"); 505 devfs_mk_cdev(MKDEV(VCS_MAJOR, 128), S_IFCHR|S_IRUSR|S_IWUSR, "vcc/a0");
506 class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, 0), NULL, "vcs"); 506 class_device_create(vc_class, MKDEV(VCS_MAJOR, 0), NULL, "vcs");
507 class_simple_device_add(vc_class, MKDEV(VCS_MAJOR, 128), NULL, "vcsa"); 507 class_device_create(vc_class, MKDEV(VCS_MAJOR, 128), NULL, "vcsa");
508 return 0; 508 return 0;
509} 509}
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index aea3cbf5219d..4764b4f9555d 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -237,7 +237,7 @@ static dma_addr_t viotape_unitinfo_token;
237 237
238static struct mtget viomtget[VIOTAPE_MAX_TAPE]; 238static struct mtget viomtget[VIOTAPE_MAX_TAPE];
239 239
240static struct class_simple *tape_class; 240static struct class *tape_class;
241 241
242static struct device *tape_device[VIOTAPE_MAX_TAPE]; 242static struct device *tape_device[VIOTAPE_MAX_TAPE];
243 243
@@ -956,9 +956,9 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
956 state[i].cur_part = 0; 956 state[i].cur_part = 0;
957 for (j = 0; j < MAX_PARTITIONS; ++j) 957 for (j = 0; j < MAX_PARTITIONS; ++j)
958 state[i].part_stat_rwi[j] = VIOT_IDLE; 958 state[i].part_stat_rwi[j] = VIOT_IDLE;
959 class_simple_device_add(tape_class, MKDEV(VIOTAPE_MAJOR, i), NULL, 959 class_device_create(tape_class, MKDEV(VIOTAPE_MAJOR, i), NULL,
960 "iseries!vt%d", i); 960 "iseries!vt%d", i);
961 class_simple_device_add(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80), 961 class_device_create(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80),
962 NULL, "iseries!nvt%d", i); 962 NULL, "iseries!nvt%d", i);
963 devfs_mk_cdev(MKDEV(VIOTAPE_MAJOR, i), S_IFCHR | S_IRUSR | S_IWUSR, 963 devfs_mk_cdev(MKDEV(VIOTAPE_MAJOR, i), S_IFCHR | S_IRUSR | S_IWUSR,
964 "iseries/vt%d", i); 964 "iseries/vt%d", i);
@@ -980,8 +980,8 @@ static int viotape_remove(struct vio_dev *vdev)
980 devfs_remove("iseries/nvt%d", i); 980 devfs_remove("iseries/nvt%d", i);
981 devfs_remove("iseries/vt%d", i); 981 devfs_remove("iseries/vt%d", i);
982 devfs_unregister_tape(state[i].dev_handle); 982 devfs_unregister_tape(state[i].dev_handle);
983 class_simple_device_remove(MKDEV(VIOTAPE_MAJOR, i | 0x80)); 983 class_device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i | 0x80));
984 class_simple_device_remove(MKDEV(VIOTAPE_MAJOR, i)); 984 class_device_destroy(tape_class, MKDEV(VIOTAPE_MAJOR, i));
985 return 0; 985 return 0;
986} 986}
987 987
@@ -1045,7 +1045,7 @@ int __init viotap_init(void)
1045 goto clear_handler; 1045 goto clear_handler;
1046 } 1046 }
1047 1047
1048 tape_class = class_simple_create(THIS_MODULE, "tape"); 1048 tape_class = class_create(THIS_MODULE, "tape");
1049 if (IS_ERR(tape_class)) { 1049 if (IS_ERR(tape_class)) {
1050 printk(VIOTAPE_KERN_WARN "Unable to allocat class\n"); 1050 printk(VIOTAPE_KERN_WARN "Unable to allocat class\n");
1051 ret = PTR_ERR(tape_class); 1051 ret = PTR_ERR(tape_class);
@@ -1070,7 +1070,7 @@ int __init viotap_init(void)
1070 return 0; 1070 return 0;
1071 1071
1072unreg_class: 1072unreg_class:
1073 class_simple_destroy(tape_class); 1073 class_destroy(tape_class);
1074unreg_chrdev: 1074unreg_chrdev:
1075 unregister_chrdev(VIOTAPE_MAJOR, "viotape"); 1075 unregister_chrdev(VIOTAPE_MAJOR, "viotape");
1076clear_handler: 1076clear_handler:
@@ -1110,7 +1110,7 @@ static void __exit viotap_exit(void)
1110 1110
1111 remove_proc_entry("iSeries/viotape", NULL); 1111 remove_proc_entry("iSeries/viotape", NULL);
1112 vio_unregister_driver(&viotape_driver); 1112 vio_unregister_driver(&viotape_driver);
1113 class_simple_destroy(tape_class); 1113 class_destroy(tape_class);
1114 ret = unregister_chrdev(VIOTAPE_MAJOR, "viotape"); 1114 ret = unregister_chrdev(VIOTAPE_MAJOR, "viotape");
1115 if (ret < 0) 1115 if (ret < 0)
1116 printk(VIOTAPE_KERN_WARN "Error unregistering device: %d\n", 1116 printk(VIOTAPE_KERN_WARN "Error unregistering device: %d\n",
diff --git a/drivers/char/vr41xx_giu.c b/drivers/char/vr41xx_giu.c
new file mode 100644
index 000000000000..683278bc5241
--- /dev/null
+++ b/drivers/char/vr41xx_giu.c
@@ -0,0 +1,743 @@
1/*
2 * Driver for NEC VR4100 series General-purpose I/O Unit.
3 *
4 * Copyright (C) 2002 MontaVista Software Inc.
5 * Author: Yoichi Yuasa <yyuasa@mvista.com or source@mvista.com>
6 * Copyright (C) 2003-2005 Yoichi Yuasa <yuasa@hh.iij4u.or.jp>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22#include <linux/device.h>
23#include <linux/errno.h>
24#include <linux/fs.h>
25#include <linux/init.h>
26#include <linux/irq.h>
27#include <linux/interrupt.h>
28#include <linux/kernel.h>
29#include <linux/module.h>
30#include <linux/spinlock.h>
31#include <linux/types.h>
32
33#include <asm/cpu.h>
34#include <asm/io.h>
35#include <asm/vr41xx/giu.h>
36#include <asm/vr41xx/vr41xx.h>
37
38MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>");
39MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver");
40MODULE_LICENSE("GPL");
41
42static int major; /* default is dynamic major device number */
43module_param(major, int, 0);
44MODULE_PARM_DESC(major, "Major device number");
45
46#define GIU_TYPE1_START 0x0b000100UL
47#define GIU_TYPE1_SIZE 0x20UL
48
49#define GIU_TYPE2_START 0x0f000140UL
50#define GIU_TYPE2_SIZE 0x20UL
51
52#define GIU_TYPE3_START 0x0f000140UL
53#define GIU_TYPE3_SIZE 0x28UL
54
55#define GIU_PULLUPDOWN_START 0x0b0002e0UL
56#define GIU_PULLUPDOWN_SIZE 0x04UL
57
58#define GIUIOSELL 0x00
59#define GIUIOSELH 0x02
60#define GIUPIODL 0x04
61#define GIUPIODH 0x06
62#define GIUINTSTATL 0x08
63#define GIUINTSTATH 0x0a
64#define GIUINTENL 0x0c
65#define GIUINTENH 0x0e
66#define GIUINTTYPL 0x10
67#define GIUINTTYPH 0x12
68#define GIUINTALSELL 0x14
69#define GIUINTALSELH 0x16
70#define GIUINTHTSELL 0x18
71#define GIUINTHTSELH 0x1a
72#define GIUPODATL 0x1c
73#define GIUPODATEN 0x1c
74#define GIUPODATH 0x1e
75 #define PIOEN0 0x0100
76 #define PIOEN1 0x0200
77#define GIUPODAT 0x1e
78#define GIUFEDGEINHL 0x20
79#define GIUFEDGEINHH 0x22
80#define GIUREDGEINHL 0x24
81#define GIUREDGEINHH 0x26
82
83#define GIUUSEUPDN 0x1e0
84#define GIUTERMUPDN 0x1e2
85
86#define GPIO_HAS_PULLUPDOWN_IO 0x0001
87#define GPIO_HAS_OUTPUT_ENABLE 0x0002
88#define GPIO_HAS_INTERRUPT_EDGE_SELECT 0x0100
89
90static spinlock_t giu_lock;
91static struct resource *giu_resource1;
92static struct resource *giu_resource2;
93static unsigned long giu_flags;
94static unsigned int giu_nr_pins;
95
96static void __iomem *giu_base;
97
98#define giu_read(offset) readw(giu_base + (offset))
99#define giu_write(offset, value) writew((value), giu_base + (offset))
100
101#define GPIO_PIN_OF_IRQ(irq) ((irq) - GIU_IRQ_BASE)
102#define GIUINT_HIGH_OFFSET 16
103#define GIUINT_HIGH_MAX 32
104
105static inline uint16_t giu_set(uint16_t offset, uint16_t set)
106{
107 uint16_t data;
108
109 data = giu_read(offset);
110 data |= set;
111 giu_write(offset, data);
112
113 return data;
114}
115
116static inline uint16_t giu_clear(uint16_t offset, uint16_t clear)
117{
118 uint16_t data;
119
120 data = giu_read(offset);
121 data &= ~clear;
122 giu_write(offset, data);
123
124 return data;
125}
126
127static unsigned int startup_giuint_low_irq(unsigned int irq)
128{
129 unsigned int pin;
130
131 pin = GPIO_PIN_OF_IRQ(irq);
132 giu_write(GIUINTSTATL, 1 << pin);
133 giu_set(GIUINTENL, 1 << pin);
134
135 return 0;
136}
137
138static void shutdown_giuint_low_irq(unsigned int irq)
139{
140 giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
141}
142
143static void enable_giuint_low_irq(unsigned int irq)
144{
145 giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
146}
147
148#define disable_giuint_low_irq shutdown_giuint_low_irq
149
150static void ack_giuint_low_irq(unsigned int irq)
151{
152 unsigned int pin;
153
154 pin = GPIO_PIN_OF_IRQ(irq);
155 giu_clear(GIUINTENL, 1 << pin);
156 giu_write(GIUINTSTATL, 1 << pin);
157}
158
159static void end_giuint_low_irq(unsigned int irq)
160{
161 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
162 giu_set(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq));
163}
164
165static struct hw_interrupt_type giuint_low_irq_type = {
166 .typename = "GIUINTL",
167 .startup = startup_giuint_low_irq,
168 .shutdown = shutdown_giuint_low_irq,
169 .enable = enable_giuint_low_irq,
170 .disable = disable_giuint_low_irq,
171 .ack = ack_giuint_low_irq,
172 .end = end_giuint_low_irq,
173};
174
175static unsigned int startup_giuint_high_irq(unsigned int irq)
176{
177 unsigned int pin;
178
179 pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
180 giu_write(GIUINTSTATH, 1 << pin);
181 giu_set(GIUINTENH, 1 << pin);
182
183 return 0;
184}
185
186static void shutdown_giuint_high_irq(unsigned int irq)
187{
188 giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
189}
190
191static void enable_giuint_high_irq(unsigned int irq)
192{
193 giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
194}
195
196#define disable_giuint_high_irq shutdown_giuint_high_irq
197
198static void ack_giuint_high_irq(unsigned int irq)
199{
200 unsigned int pin;
201
202 pin = GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET;
203 giu_clear(GIUINTENH, 1 << pin);
204 giu_write(GIUINTSTATH, 1 << pin);
205}
206
207static void end_giuint_high_irq(unsigned int irq)
208{
209 if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
210 giu_set(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET));
211}
212
213static struct hw_interrupt_type giuint_high_irq_type = {
214 .typename = "GIUINTH",
215 .startup = startup_giuint_high_irq,
216 .shutdown = shutdown_giuint_high_irq,
217 .enable = enable_giuint_high_irq,
218 .disable = disable_giuint_high_irq,
219 .ack = ack_giuint_high_irq,
220 .end = end_giuint_high_irq,
221};
222
223static int giu_get_irq(unsigned int irq, struct pt_regs *regs)
224{
225 uint16_t pendl, pendh, maskl, maskh;
226 int i;
227
228 pendl = giu_read(GIUINTSTATL);
229 pendh = giu_read(GIUINTSTATH);
230 maskl = giu_read(GIUINTENL);
231 maskh = giu_read(GIUINTENH);
232
233 maskl &= pendl;
234 maskh &= pendh;
235
236 if (maskl) {
237 for (i = 0; i < 16; i++) {
238 if (maskl & (1 << i))
239 return GIU_IRQ(i);
240 }
241 } else if (maskh) {
242 for (i = 0; i < 16; i++) {
243 if (maskh & (1 << i))
244 return GIU_IRQ(i + GIUINT_HIGH_OFFSET);
245 }
246 }
247
248 printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
249 maskl, pendl, maskh, pendh);
250
251 atomic_inc(&irq_err_count);
252
253 return -EINVAL;
254}
255
256void vr41xx_set_irq_trigger(unsigned int pin, irq_trigger_t trigger, irq_signal_t signal)
257{
258 uint16_t mask;
259
260 if (pin < GIUINT_HIGH_OFFSET) {
261 mask = 1 << pin;
262 if (trigger != IRQ_TRIGGER_LEVEL) {
263 giu_set(GIUINTTYPL, mask);
264 if (signal == IRQ_SIGNAL_HOLD)
265 giu_set(GIUINTHTSELL, mask);
266 else
267 giu_clear(GIUINTHTSELL, mask);
268 if (current_cpu_data.cputype == CPU_VR4133) {
269 switch (trigger) {
270 case IRQ_TRIGGER_EDGE_FALLING:
271 giu_set(GIUFEDGEINHL, mask);
272 giu_clear(GIUREDGEINHL, mask);
273 break;
274 case IRQ_TRIGGER_EDGE_RISING:
275 giu_clear(GIUFEDGEINHL, mask);
276 giu_set(GIUREDGEINHL, mask);
277 break;
278 default:
279 giu_set(GIUFEDGEINHL, mask);
280 giu_set(GIUREDGEINHL, mask);
281 break;
282 }
283 }
284 } else {
285 giu_clear(GIUINTTYPL, mask);
286 giu_clear(GIUINTHTSELL, mask);
287 }
288 giu_write(GIUINTSTATL, mask);
289 } else if (pin < GIUINT_HIGH_MAX) {
290 mask = 1 << (pin - GIUINT_HIGH_OFFSET);
291 if (trigger != IRQ_TRIGGER_LEVEL) {
292 giu_set(GIUINTTYPH, mask);
293 if (signal == IRQ_SIGNAL_HOLD)
294 giu_set(GIUINTHTSELH, mask);
295 else
296 giu_clear(GIUINTHTSELH, mask);
297 if (current_cpu_data.cputype == CPU_VR4133) {
298 switch (trigger) {
299 case IRQ_TRIGGER_EDGE_FALLING:
300 giu_set(GIUFEDGEINHH, mask);
301 giu_clear(GIUREDGEINHH, mask);
302 break;
303 case IRQ_TRIGGER_EDGE_RISING:
304 giu_clear(GIUFEDGEINHH, mask);
305 giu_set(GIUREDGEINHH, mask);
306 break;
307 default:
308 giu_set(GIUFEDGEINHH, mask);
309 giu_set(GIUREDGEINHH, mask);
310 break;
311 }
312 }
313 } else {
314 giu_clear(GIUINTTYPH, mask);
315 giu_clear(GIUINTHTSELH, mask);
316 }
317 giu_write(GIUINTSTATH, mask);
318 }
319}
320
321EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger);
322
323void vr41xx_set_irq_level(unsigned int pin, irq_level_t level)
324{
325 uint16_t mask;
326
327 if (pin < GIUINT_HIGH_OFFSET) {
328 mask = 1 << pin;
329 if (level == IRQ_LEVEL_HIGH)
330 giu_set(GIUINTALSELL, mask);
331 else
332 giu_clear(GIUINTALSELL, mask);
333 giu_write(GIUINTSTATL, mask);
334 } else if (pin < GIUINT_HIGH_MAX) {
335 mask = 1 << (pin - GIUINT_HIGH_OFFSET);
336 if (level == IRQ_LEVEL_HIGH)
337 giu_set(GIUINTALSELH, mask);
338 else
339 giu_clear(GIUINTALSELH, mask);
340 giu_write(GIUINTSTATH, mask);
341 }
342}
343
344EXPORT_SYMBOL_GPL(vr41xx_set_irq_level);
345
346gpio_data_t vr41xx_gpio_get_pin(unsigned int pin)
347{
348 uint16_t reg, mask;
349
350 if (pin >= giu_nr_pins)
351 return GPIO_DATA_INVAL;
352
353 if (pin < 16) {
354 reg = giu_read(GIUPIODL);
355 mask = (uint16_t)1 << pin;
356 } else if (pin < 32) {
357 reg = giu_read(GIUPIODH);
358 mask = (uint16_t)1 << (pin - 16);
359 } else if (pin < 48) {
360 reg = giu_read(GIUPODATL);
361 mask = (uint16_t)1 << (pin - 32);
362 } else {
363 reg = giu_read(GIUPODATH);
364 mask = (uint16_t)1 << (pin - 48);
365 }
366
367 if (reg & mask)
368 return GPIO_DATA_HIGH;
369
370 return GPIO_DATA_LOW;
371}
372
373EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin);
374
375int vr41xx_gpio_set_pin(unsigned int pin, gpio_data_t data)
376{
377 uint16_t offset, mask, reg;
378 unsigned long flags;
379
380 if (pin >= giu_nr_pins)
381 return -EINVAL;
382
383 if (pin < 16) {
384 offset = GIUPIODL;
385 mask = (uint16_t)1 << pin;
386 } else if (pin < 32) {
387 offset = GIUPIODH;
388 mask = (uint16_t)1 << (pin - 16);
389 } else if (pin < 48) {
390 offset = GIUPODATL;
391 mask = (uint16_t)1 << (pin - 32);
392 } else {
393 offset = GIUPODATH;
394 mask = (uint16_t)1 << (pin - 48);
395 }
396
397 spin_lock_irqsave(&giu_lock, flags);
398
399 reg = giu_read(offset);
400 if (data == GPIO_DATA_HIGH)
401 reg |= mask;
402 else
403 reg &= ~mask;
404 giu_write(offset, reg);
405
406 spin_unlock_irqrestore(&giu_lock, flags);
407
408 return 0;
409}
410
411EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin);
412
413int vr41xx_gpio_set_direction(unsigned int pin, gpio_direction_t dir)
414{
415 uint16_t offset, mask, reg;
416 unsigned long flags;
417
418 if (pin >= giu_nr_pins)
419 return -EINVAL;
420
421 if (pin < 16) {
422 offset = GIUIOSELL;
423 mask = (uint16_t)1 << pin;
424 } else if (pin < 32) {
425 offset = GIUIOSELH;
426 mask = (uint16_t)1 << (pin - 16);
427 } else {
428 if (giu_flags & GPIO_HAS_OUTPUT_ENABLE) {
429 offset = GIUPODATEN;
430 mask = (uint16_t)1 << (pin - 32);
431 } else {
432 switch (pin) {
433 case 48:
434 offset = GIUPODATH;
435 mask = PIOEN0;
436 break;
437 case 49:
438 offset = GIUPODATH;
439 mask = PIOEN1;
440 break;
441 default:
442 return -EINVAL;
443 }
444 }
445 }
446
447 spin_lock_irqsave(&giu_lock, flags);
448
449 reg = giu_read(offset);
450 if (dir == GPIO_OUTPUT)
451 reg |= mask;
452 else
453 reg &= ~mask;
454 giu_write(offset, reg);
455
456 spin_unlock_irqrestore(&giu_lock, flags);
457
458 return 0;
459}
460
461EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction);
462
463int vr41xx_gpio_pullupdown(unsigned int pin, gpio_pull_t pull)
464{
465 uint16_t reg, mask;
466 unsigned long flags;
467
468 if ((giu_flags & GPIO_HAS_PULLUPDOWN_IO) != GPIO_HAS_PULLUPDOWN_IO)
469 return -EPERM;
470
471 if (pin >= 15)
472 return -EINVAL;
473
474 mask = (uint16_t)1 << pin;
475
476 spin_lock_irqsave(&giu_lock, flags);
477
478 if (pull == GPIO_PULL_UP || pull == GPIO_PULL_DOWN) {
479 reg = giu_read(GIUTERMUPDN);
480 if (pull == GPIO_PULL_UP)
481 reg |= mask;
482 else
483 reg &= ~mask;
484 giu_write(GIUTERMUPDN, reg);
485
486 reg = giu_read(GIUUSEUPDN);
487 reg |= mask;
488 giu_write(GIUUSEUPDN, reg);
489 } else {
490 reg = giu_read(GIUUSEUPDN);
491 reg &= ~mask;
492 giu_write(GIUUSEUPDN, reg);
493 }
494
495 spin_unlock_irqrestore(&giu_lock, flags);
496
497 return 0;
498}
499
500EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown);
501
502static ssize_t gpio_read(struct file *file, char __user *buf, size_t len,
503 loff_t *ppos)
504{
505 unsigned int pin;
506 char value = '0';
507
508 pin = iminor(file->f_dentry->d_inode);
509 if (pin >= giu_nr_pins)
510 return -EBADF;
511
512 if (vr41xx_gpio_get_pin(pin) == GPIO_DATA_HIGH)
513 value = '1';
514
515 if (len <= 0)
516 return -EFAULT;
517
518 if (put_user(value, buf))
519 return -EFAULT;
520
521 return 1;
522}
523
524static ssize_t gpio_write(struct file *file, const char __user *data,
525 size_t len, loff_t *ppos)
526{
527 unsigned int pin;
528 size_t i;
529 char c;
530 int retval = 0;
531
532 pin = iminor(file->f_dentry->d_inode);
533 if (pin >= giu_nr_pins)
534 return -EBADF;
535
536 for (i = 0; i < len; i++) {
537 if (get_user(c, data + i))
538 return -EFAULT;
539
540 switch (c) {
541 case '0':
542 retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_LOW);
543 break;
544 case '1':
545 retval = vr41xx_gpio_set_pin(pin, GPIO_DATA_HIGH);
546 break;
547 case 'D':
548 printk(KERN_INFO "GPIO%d: pull down\n", pin);
549 retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DOWN);
550 break;
551 case 'd':
552 printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
553 retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
554 break;
555 case 'I':
556 printk(KERN_INFO "GPIO%d: input\n", pin);
557 retval = vr41xx_gpio_set_direction(pin, GPIO_INPUT);
558 break;
559 case 'O':
560 printk(KERN_INFO "GPIO%d: output\n", pin);
561 retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT);
562 break;
563 case 'o':
564 printk(KERN_INFO "GPIO%d: output disable\n", pin);
565 retval = vr41xx_gpio_set_direction(pin, GPIO_OUTPUT_DISABLE);
566 break;
567 case 'P':
568 printk(KERN_INFO "GPIO%d: pull up\n", pin);
569 retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_UP);
570 break;
571 case 'p':
572 printk(KERN_INFO "GPIO%d: pull up/down disable\n", pin);
573 retval = vr41xx_gpio_pullupdown(pin, GPIO_PULL_DISABLE);
574 break;
575 default:
576 break;
577 }
578
579 if (retval < 0)
580 break;
581 }
582
583 return i;
584}
585
586static int gpio_open(struct inode *inode, struct file *file)
587{
588 unsigned int pin;
589
590 pin = iminor(inode);
591 if (pin >= giu_nr_pins)
592 return -EBADF;
593
594 return nonseekable_open(inode, file);
595}
596
597static int gpio_release(struct inode *inode, struct file *file)
598{
599 unsigned int pin;
600
601 pin = iminor(inode);
602 if (pin >= giu_nr_pins)
603 return -EBADF;
604
605 return 0;
606}
607
608static struct file_operations gpio_fops = {
609 .owner = THIS_MODULE,
610 .read = gpio_read,
611 .write = gpio_write,
612 .open = gpio_open,
613 .release = gpio_release,
614};
615
616static int giu_probe(struct device *dev)
617{
618 unsigned long start, size, flags = 0;
619 unsigned int nr_pins = 0;
620 struct resource *res1, *res2 = NULL;
621 void *base;
622 int retval, i;
623
624 switch (current_cpu_data.cputype) {
625 case CPU_VR4111:
626 case CPU_VR4121:
627 start = GIU_TYPE1_START;
628 size = GIU_TYPE1_SIZE;
629 flags = GPIO_HAS_PULLUPDOWN_IO;
630 nr_pins = 50;
631 break;
632 case CPU_VR4122:
633 case CPU_VR4131:
634 start = GIU_TYPE2_START;
635 size = GIU_TYPE2_SIZE;
636 nr_pins = 36;
637 break;
638 case CPU_VR4133:
639 start = GIU_TYPE3_START;
640 size = GIU_TYPE3_SIZE;
641 flags = GPIO_HAS_INTERRUPT_EDGE_SELECT;
642 nr_pins = 48;
643 break;
644 default:
645 return -ENODEV;
646 }
647
648 res1 = request_mem_region(start, size, "GIU");
649 if (res1 == NULL)
650 return -EBUSY;
651
652 base = ioremap(start, size);
653 if (base == NULL) {
654 release_resource(res1);
655 return -ENOMEM;
656 }
657
658 if (flags & GPIO_HAS_PULLUPDOWN_IO) {
659 res2 = request_mem_region(GIU_PULLUPDOWN_START, GIU_PULLUPDOWN_SIZE, "GIU");
660 if (res2 == NULL) {
661 iounmap(base);
662 release_resource(res1);
663 return -EBUSY;
664 }
665 }
666
667 retval = register_chrdev(major, "GIU", &gpio_fops);
668 if (retval < 0) {
669 iounmap(base);
670 release_resource(res1);
671 release_resource(res2);
672 return retval;
673 }
674
675 if (major == 0) {
676 major = retval;
677 printk(KERN_INFO "GIU: major number %d\n", major);
678 }
679
680 spin_lock_init(&giu_lock);
681 giu_base = base;
682 giu_resource1 = res1;
683 giu_resource2 = res2;
684 giu_flags = flags;
685 giu_nr_pins = nr_pins;
686
687 giu_write(GIUINTENL, 0);
688 giu_write(GIUINTENH, 0);
689
690 for (i = GIU_IRQ_BASE; i <= GIU_IRQ_LAST; i++) {
691 if (i < GIU_IRQ(GIUINT_HIGH_OFFSET))
692 irq_desc[i].handler = &giuint_low_irq_type;
693 else
694 irq_desc[i].handler = &giuint_high_irq_type;
695 }
696
697 return cascade_irq(GIUINT_IRQ, giu_get_irq);
698}
699
700static int giu_remove(struct device *dev)
701{
702 iounmap(giu_base);
703
704 release_resource(giu_resource1);
705 if (giu_flags & GPIO_HAS_PULLUPDOWN_IO)
706 release_resource(giu_resource2);
707
708 return 0;
709}
710
711static struct platform_device *giu_platform_device;
712
713static struct device_driver giu_device_driver = {
714 .name = "GIU",
715 .bus = &platform_bus_type,
716 .probe = giu_probe,
717 .remove = giu_remove,
718};
719
720static int __devinit vr41xx_giu_init(void)
721{
722 int retval;
723
724 giu_platform_device = platform_device_register_simple("GIU", -1, NULL, 0);
725 if (IS_ERR(giu_platform_device))
726 return PTR_ERR(giu_platform_device);
727
728 retval = driver_register(&giu_device_driver);
729 if (retval < 0)
730 platform_device_unregister(giu_platform_device);
731
732 return retval;
733}
734
735static void __devexit vr41xx_giu_exit(void)
736{
737 driver_unregister(&giu_device_driver);
738
739 platform_device_unregister(giu_platform_device);
740}
741
742module_init(vr41xx_giu_init);
743module_exit(vr41xx_giu_exit);
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index e5ef1dfc5482..30d96739fb23 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -2796,7 +2796,7 @@ void do_blank_screen(int entering_gfx)
2796 return; 2796 return;
2797 2797
2798 if (vesa_off_interval) { 2798 if (vesa_off_interval) {
2799 blank_state = blank_vesa_wait, 2799 blank_state = blank_vesa_wait;
2800 mod_timer(&console_timer, jiffies + vesa_off_interval); 2800 mod_timer(&console_timer, jiffies + vesa_off_interval);
2801 } 2801 }
2802 2802
@@ -2867,6 +2867,10 @@ void unblank_screen(void)
2867 */ 2867 */
2868static void blank_screen_t(unsigned long dummy) 2868static void blank_screen_t(unsigned long dummy)
2869{ 2869{
2870 if (unlikely(!keventd_up())) {
2871 mod_timer(&console_timer, jiffies + blankinterval);
2872 return;
2873 }
2870 blank_timer_expired = 1; 2874 blank_timer_expired = 1;
2871 schedule_work(&console_work); 2875 schedule_work(&console_work);
2872} 2876}
diff --git a/drivers/char/vt_ioctl.c b/drivers/char/vt_ioctl.c
index 8971484b956b..1d44f69e1fda 100644
--- a/drivers/char/vt_ioctl.c
+++ b/drivers/char/vt_ioctl.c
@@ -25,6 +25,7 @@
25#include <linux/fs.h> 25#include <linux/fs.h>
26#include <linux/console.h> 26#include <linux/console.h>
27#include <linux/signal.h> 27#include <linux/signal.h>
28#include <linux/timex.h>
28 29
29#include <asm/io.h> 30#include <asm/io.h>
30#include <asm/uaccess.h> 31#include <asm/uaccess.h>
@@ -386,7 +387,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
386 if (!perm) 387 if (!perm)
387 return -EPERM; 388 return -EPERM;
388 if (arg) 389 if (arg)
389 arg = 1193182 / arg; 390 arg = CLOCK_TICK_RATE / arg;
390 kd_mksound(arg, 0); 391 kd_mksound(arg, 0);
391 return 0; 392 return 0;
392 393
@@ -403,7 +404,7 @@ int vt_ioctl(struct tty_struct *tty, struct file * file,
403 ticks = HZ * ((arg >> 16) & 0xffff) / 1000; 404 ticks = HZ * ((arg >> 16) & 0xffff) / 1000;
404 count = ticks ? (arg & 0xffff) : 0; 405 count = ticks ? (arg & 0xffff) : 0;
405 if (count) 406 if (count)
406 count = 1193182 / count; 407 count = CLOCK_TICK_RATE / count;
407 kd_mksound(count, ticks); 408 kd_mksound(count, ticks);
408 return 0; 409 return 0;
409 } 410 }
diff --git a/drivers/char/watchdog/Kconfig b/drivers/char/watchdog/Kconfig
index 06a31da2381c..b53e2e2b5aee 100644
--- a/drivers/char/watchdog/Kconfig
+++ b/drivers/char/watchdog/Kconfig
@@ -414,6 +414,16 @@ config WATCHDOG_RIO
414 machines. The watchdog timeout period is normally one minute but 414 machines. The watchdog timeout period is normally one minute but
415 can be changed with a boot-time parameter. 415 can be changed with a boot-time parameter.
416 416
417# ppc64 RTAS watchdog
418config WATCHDOG_RTAS
419 tristate "RTAS watchdog"
420 depends on WATCHDOG && PPC_RTAS
421 help
422 This driver adds watchdog support for the RTAS watchdog.
423
424 To compile this driver as a module, choose M here. The module
425 will be called wdrtas.
426
417# 427#
418# ISA-based Watchdog Cards 428# ISA-based Watchdog Cards
419# 429#
diff --git a/drivers/char/watchdog/Makefile b/drivers/char/watchdog/Makefile
index 1cd27efa35c1..c1838834ea7f 100644
--- a/drivers/char/watchdog/Makefile
+++ b/drivers/char/watchdog/Makefile
@@ -33,6 +33,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
33obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o 33obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
34obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o 34obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o
35obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o 35obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o
36obj-$(CONFIG_WATCHDOG_RTAS) += wdrtas.o
36 37
37# Only one watchdog can succeed. We probe the hardware watchdog 38# Only one watchdog can succeed. We probe the hardware watchdog
38# drivers first, then the softdog driver. This means if your hardware 39# drivers first, then the softdog driver. This means if your hardware
diff --git a/drivers/char/watchdog/acquirewdt.c b/drivers/char/watchdog/acquirewdt.c
index 8f302121741b..7289f4af93d0 100644
--- a/drivers/char/watchdog/acquirewdt.c
+++ b/drivers/char/watchdog/acquirewdt.c
@@ -82,12 +82,7 @@ static int wdt_start = 0x443;
82module_param(wdt_start, int, 0); 82module_param(wdt_start, int, 0);
83MODULE_PARM_DESC(wdt_start, "Acquire WDT 'start' io port (default 0x443)"); 83MODULE_PARM_DESC(wdt_start, "Acquire WDT 'start' io port (default 0x443)");
84 84
85#ifdef CONFIG_WATCHDOG_NOWAYOUT 85static int nowayout = WATCHDOG_NOWAYOUT;
86static int nowayout = 1;
87#else
88static int nowayout = 0;
89#endif
90
91module_param(nowayout, int, 0); 86module_param(nowayout, int, 0);
92MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 87MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
93 88
diff --git a/drivers/char/watchdog/advantechwdt.c b/drivers/char/watchdog/advantechwdt.c
index ea73c8379bdd..194a3fd36b91 100644
--- a/drivers/char/watchdog/advantechwdt.c
+++ b/drivers/char/watchdog/advantechwdt.c
@@ -73,12 +73,7 @@ static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
73module_param(timeout, int, 0); 73module_param(timeout, int, 0);
74MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); 74MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
75 75
76#ifdef CONFIG_WATCHDOG_NOWAYOUT 76static int nowayout = WATCHDOG_NOWAYOUT;
77static int nowayout = 1;
78#else
79static int nowayout = 0;
80#endif
81
82module_param(nowayout, int, 0); 77module_param(nowayout, int, 0);
83MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 78MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
84 79
diff --git a/drivers/char/watchdog/alim1535_wdt.c b/drivers/char/watchdog/alim1535_wdt.c
index 35dcbf8be7d1..8338ca300e2e 100644
--- a/drivers/char/watchdog/alim1535_wdt.c
+++ b/drivers/char/watchdog/alim1535_wdt.c
@@ -38,12 +38,7 @@ static int timeout = WATCHDOG_TIMEOUT;
38module_param(timeout, int, 0); 38module_param(timeout, int, 0);
39MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (0<timeout<18000, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); 39MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (0<timeout<18000, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
40 40
41#ifdef CONFIG_WATCHDOG_NOWAYOUT 41static int nowayout = WATCHDOG_NOWAYOUT;
42static int nowayout = 1;
43#else
44static int nowayout = 0;
45#endif
46
47module_param(nowayout, int, 0); 42module_param(nowayout, int, 0);
48MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 43MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
49 44
@@ -317,7 +312,7 @@ static int ali_notify_sys(struct notifier_block *this, unsigned long code, void
317 */ 312 */
318 313
319static struct pci_device_id ali_pci_tbl[] = { 314static struct pci_device_id ali_pci_tbl[] = {
320 { PCI_VENDOR_ID_AL, 1535, PCI_ANY_ID, PCI_ANY_ID,}, 315 { PCI_VENDOR_ID_AL, 0x1535, PCI_ANY_ID, PCI_ANY_ID,},
321 { 0, }, 316 { 0, },
322}; 317};
323MODULE_DEVICE_TABLE(pci, ali_pci_tbl); 318MODULE_DEVICE_TABLE(pci, ali_pci_tbl);
diff --git a/drivers/char/watchdog/alim7101_wdt.c b/drivers/char/watchdog/alim7101_wdt.c
index 90c091d9e0f5..c05ac188a4d7 100644
--- a/drivers/char/watchdog/alim7101_wdt.c
+++ b/drivers/char/watchdog/alim7101_wdt.c
@@ -75,12 +75,7 @@ static unsigned long wdt_is_open;
75static char wdt_expect_close; 75static char wdt_expect_close;
76static struct pci_dev *alim7101_pmu; 76static struct pci_dev *alim7101_pmu;
77 77
78#ifdef CONFIG_WATCHDOG_NOWAYOUT 78static int nowayout = WATCHDOG_NOWAYOUT;
79static int nowayout = 1;
80#else
81static int nowayout = 0;
82#endif
83
84module_param(nowayout, int, 0); 79module_param(nowayout, int, 0);
85MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 80MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
86 81
diff --git a/drivers/char/watchdog/eurotechwdt.c b/drivers/char/watchdog/eurotechwdt.c
index d10e554a14d6..25c2f2575611 100644
--- a/drivers/char/watchdog/eurotechwdt.c
+++ b/drivers/char/watchdog/eurotechwdt.c
@@ -72,12 +72,7 @@ static char *ev = "int";
72 72
73#define WDT_TIMEOUT 60 /* 1 minute */ 73#define WDT_TIMEOUT 60 /* 1 minute */
74 74
75#ifdef CONFIG_WATCHDOG_NOWAYOUT 75static int nowayout = WATCHDOG_NOWAYOUT;
76static int nowayout = 1;
77#else
78static int nowayout = 0;
79#endif
80
81module_param(nowayout, int, 0); 76module_param(nowayout, int, 0);
82MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 77MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
83 78
@@ -167,7 +162,7 @@ static irqreturn_t eurwdt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
167 printk(KERN_CRIT "Would Reboot.\n"); 162 printk(KERN_CRIT "Would Reboot.\n");
168#else 163#else
169 printk(KERN_CRIT "Initiating system reboot.\n"); 164 printk(KERN_CRIT "Initiating system reboot.\n");
170 machine_restart(NULL); 165 emergency_restart();
171#endif 166#endif
172 return IRQ_HANDLED; 167 return IRQ_HANDLED;
173} 168}
diff --git a/drivers/char/watchdog/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c
index b14d642439ed..a13395e2c372 100644
--- a/drivers/char/watchdog/i8xx_tco.c
+++ b/drivers/char/watchdog/i8xx_tco.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * i8xx_tco 0.07: TCO timer driver for i8xx chipsets 2 * i8xx_tco: TCO timer driver for i8xx chipsets
3 * 3 *
4 * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved. 4 * (c) Copyright 2000 kernel concepts <nils@kernelconcepts.de>, All Rights Reserved.
5 * http://www.kernelconcepts.de 5 * http://www.kernelconcepts.de
@@ -63,6 +63,9 @@
63 * 20050128 Wim Van Sebroeck <wim@iguana.be> 63 * 20050128 Wim Van Sebroeck <wim@iguana.be>
64 * 0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW 64 * 0.07 Added support for the ICH4-M, ICH6, ICH6R, ICH6-M, ICH6W and ICH6RW
65 * chipsets. Also added support for the "undocumented" ICH7 chipset. 65 * chipsets. Also added support for the "undocumented" ICH7 chipset.
66 * 20050807 Wim Van Sebroeck <wim@iguana.be>
67 * 0.08 Make sure that the watchdog is only "armed" when started.
68 * (Kernel Bug 4251)
66 */ 69 */
67 70
68/* 71/*
@@ -87,7 +90,7 @@
87#include "i8xx_tco.h" 90#include "i8xx_tco.h"
88 91
89/* Module and version information */ 92/* Module and version information */
90#define TCO_VERSION "0.07" 93#define TCO_VERSION "0.08"
91#define TCO_MODULE_NAME "i8xx TCO timer" 94#define TCO_MODULE_NAME "i8xx TCO timer"
92#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION 95#define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION
93#define PFX TCO_MODULE_NAME ": " 96#define PFX TCO_MODULE_NAME ": "
@@ -105,12 +108,7 @@ static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
105module_param(heartbeat, int, 0); 108module_param(heartbeat, int, 0);
106MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<heartbeat<39, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); 109MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<heartbeat<39, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
107 110
108#ifdef CONFIG_WATCHDOG_NOWAYOUT 111static int nowayout = WATCHDOG_NOWAYOUT;
109static int nowayout = 1;
110#else
111static int nowayout = 0;
112#endif
113
114module_param(nowayout, int, 0); 112module_param(nowayout, int, 0);
115MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 113MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
116 114
@@ -130,10 +128,18 @@ static int tco_timer_start (void)
130 unsigned char val; 128 unsigned char val;
131 129
132 spin_lock(&tco_lock); 130 spin_lock(&tco_lock);
131
132 /* disable chipset's NO_REBOOT bit */
133 pci_read_config_byte (i8xx_tco_pci, 0xd4, &val);
134 val &= 0xfd;
135 pci_write_config_byte (i8xx_tco_pci, 0xd4, val);
136
137 /* Bit 11: TCO Timer Halt -> 0 = The TCO timer is enabled to count */
133 val = inb (TCO1_CNT + 1); 138 val = inb (TCO1_CNT + 1);
134 val &= 0xf7; 139 val &= 0xf7;
135 outb (val, TCO1_CNT + 1); 140 outb (val, TCO1_CNT + 1);
136 val = inb (TCO1_CNT + 1); 141 val = inb (TCO1_CNT + 1);
142
137 spin_unlock(&tco_lock); 143 spin_unlock(&tco_lock);
138 144
139 if (val & 0x08) 145 if (val & 0x08)
@@ -143,13 +149,20 @@ static int tco_timer_start (void)
143 149
144static int tco_timer_stop (void) 150static int tco_timer_stop (void)
145{ 151{
146 unsigned char val; 152 unsigned char val, val1;
147 153
148 spin_lock(&tco_lock); 154 spin_lock(&tco_lock);
155 /* Bit 11: TCO Timer Halt -> 1 = The TCO timer is disabled */
149 val = inb (TCO1_CNT + 1); 156 val = inb (TCO1_CNT + 1);
150 val |= 0x08; 157 val |= 0x08;
151 outb (val, TCO1_CNT + 1); 158 outb (val, TCO1_CNT + 1);
152 val = inb (TCO1_CNT + 1); 159 val = inb (TCO1_CNT + 1);
160
161 /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
162 pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1);
163 val1 |= 0x02;
164 pci_write_config_byte (i8xx_tco_pci, 0xd4, val1);
165
153 spin_unlock(&tco_lock); 166 spin_unlock(&tco_lock);
154 167
155 if ((val & 0x08) == 0) 168 if ((val & 0x08) == 0)
@@ -160,6 +173,7 @@ static int tco_timer_stop (void)
160static int tco_timer_keepalive (void) 173static int tco_timer_keepalive (void)
161{ 174{
162 spin_lock(&tco_lock); 175 spin_lock(&tco_lock);
176 /* Reload the timer by writing to the TCO Timer Reload register */
163 outb (0x01, TCO1_RLD); 177 outb (0x01, TCO1_RLD);
164 spin_unlock(&tco_lock); 178 spin_unlock(&tco_lock);
165 return 0; 179 return 0;
@@ -401,7 +415,7 @@ static unsigned char __init i8xx_tco_getdevice (void)
401 */ 415 */
402 416
403 while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) { 417 while ((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)) != NULL) {
404 if (pci_match_device(i8xx_tco_pci_tbl, dev)) { 418 if (pci_match_id(i8xx_tco_pci_tbl, dev)) {
405 i8xx_tco_pci = dev; 419 i8xx_tco_pci = dev;
406 break; 420 break;
407 } 421 }
@@ -422,9 +436,8 @@ static unsigned char __init i8xx_tco_getdevice (void)
422 printk (KERN_ERR PFX "failed to get TCOBASE address\n"); 436 printk (KERN_ERR PFX "failed to get TCOBASE address\n");
423 return 0; 437 return 0;
424 } 438 }
425 /* 439
426 * Check chipset's NO_REBOOT bit 440 /* Check chipset's NO_REBOOT bit */
427 */
428 pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1); 441 pci_read_config_byte (i8xx_tco_pci, 0xd4, &val1);
429 if (val1 & 0x02) { 442 if (val1 & 0x02) {
430 val1 &= 0xfd; 443 val1 &= 0xfd;
@@ -435,6 +448,10 @@ static unsigned char __init i8xx_tco_getdevice (void)
435 return 0; /* Cannot reset NO_REBOOT bit */ 448 return 0; /* Cannot reset NO_REBOOT bit */
436 } 449 }
437 } 450 }
451 /* Disable reboots untill the watchdog starts */
452 val1 |= 0x02;
453 pci_write_config_byte (i8xx_tco_pci, 0xd4, val1);
454
438 /* Set the TCO_EN bit in SMI_EN register */ 455 /* Set the TCO_EN bit in SMI_EN register */
439 if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) { 456 if (!request_region (SMI_EN + 1, 1, "i8xx TCO")) {
440 printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", 457 printk (KERN_ERR PFX "I/O address 0x%04x already in use\n",
@@ -510,17 +527,10 @@ out:
510 527
511static void __exit watchdog_cleanup (void) 528static void __exit watchdog_cleanup (void)
512{ 529{
513 u8 val;
514
515 /* Stop the timer before we leave */ 530 /* Stop the timer before we leave */
516 if (!nowayout) 531 if (!nowayout)
517 tco_timer_stop (); 532 tco_timer_stop ();
518 533
519 /* Set the NO_REBOOT bit to prevent later reboots, just for sure */
520 pci_read_config_byte (i8xx_tco_pci, 0xd4, &val);
521 val |= 0x02;
522 pci_write_config_byte (i8xx_tco_pci, 0xd4, val);
523
524 /* Deregister */ 534 /* Deregister */
525 misc_deregister (&i8xx_tco_miscdev); 535 misc_deregister (&i8xx_tco_miscdev);
526 unregister_reboot_notifier(&i8xx_tco_notifier); 536 unregister_reboot_notifier(&i8xx_tco_notifier);
diff --git a/drivers/char/watchdog/ib700wdt.c b/drivers/char/watchdog/ib700wdt.c
index d974f16e84d2..cf60329eec85 100644
--- a/drivers/char/watchdog/ib700wdt.c
+++ b/drivers/char/watchdog/ib700wdt.c
@@ -117,12 +117,7 @@ static int wd_times[] = {
117 117
118static int wd_margin = WD_TIMO; 118static int wd_margin = WD_TIMO;
119 119
120#ifdef CONFIG_WATCHDOG_NOWAYOUT 120static int nowayout = WATCHDOG_NOWAYOUT;
121static int nowayout = 1;
122#else
123static int nowayout = 0;
124#endif
125
126module_param(nowayout, int, 0); 121module_param(nowayout, int, 0);
127MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 122MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
128 123
diff --git a/drivers/char/watchdog/indydog.c b/drivers/char/watchdog/indydog.c
index 6af2c799b57e..b4b94daba67e 100644
--- a/drivers/char/watchdog/indydog.c
+++ b/drivers/char/watchdog/indydog.c
@@ -29,14 +29,9 @@
29#define PFX "indydog: " 29#define PFX "indydog: "
30static int indydog_alive; 30static int indydog_alive;
31 31
32#ifdef CONFIG_WATCHDOG_NOWAYOUT
33static int nowayout = 1;
34#else
35static int nowayout = 0;
36#endif
37
38#define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */ 32#define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */
39 33
34static int nowayout = WATCHDOG_NOWAYOUT;
40module_param(nowayout, int, 0); 35module_param(nowayout, int, 0);
41MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 36MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
42 37
diff --git a/drivers/char/watchdog/ixp2000_wdt.c b/drivers/char/watchdog/ixp2000_wdt.c
index ab659d37b4d2..e7640bc4904b 100644
--- a/drivers/char/watchdog/ixp2000_wdt.c
+++ b/drivers/char/watchdog/ixp2000_wdt.c
@@ -30,11 +30,7 @@
30#include <asm/hardware.h> 30#include <asm/hardware.h>
31#include <asm/uaccess.h> 31#include <asm/uaccess.h>
32 32
33#ifdef CONFIG_WATCHDOG_NOWAYOUT 33static int nowayout = WATCHDOG_NOWAYOUT;
34static int nowayout = 1;
35#else
36static int nowayout = 0;
37#endif
38static unsigned int heartbeat = 60; /* (secs) Default is 1 minute */ 34static unsigned int heartbeat = 60; /* (secs) Default is 1 minute */
39static unsigned long wdt_status; 35static unsigned long wdt_status;
40 36
@@ -162,7 +158,7 @@ ixp2000_wdt_release(struct inode *inode, struct file *file)
162 if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) { 158 if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) {
163 wdt_disable(); 159 wdt_disable();
164 } else { 160 } else {
165 printk(KERN_CRIT "WATCHDOG: Device closed unexpectdly - " 161 printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
166 "timer will not stop\n"); 162 "timer will not stop\n");
167 } 163 }
168 164
@@ -192,7 +188,12 @@ static struct miscdevice ixp2000_wdt_miscdev =
192 188
193static int __init ixp2000_wdt_init(void) 189static int __init ixp2000_wdt_init(void)
194{ 190{
195 wdt_tick_rate = (*IXP2000_T1_CLD * HZ)/ 256;; 191 if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) {
192 printk(KERN_INFO "Unable to use IXP2000 watchdog due to IXP2800 erratum #25.\n");
193 return -EIO;
194 }
195
196 wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256;
196 197
197 return misc_register(&ixp2000_wdt_miscdev); 198 return misc_register(&ixp2000_wdt_miscdev);
198} 199}
diff --git a/drivers/char/watchdog/ixp4xx_wdt.c b/drivers/char/watchdog/ixp4xx_wdt.c
index 82396e06c8a8..8d916afbf4fa 100644
--- a/drivers/char/watchdog/ixp4xx_wdt.c
+++ b/drivers/char/watchdog/ixp4xx_wdt.c
@@ -27,11 +27,7 @@
27#include <asm/hardware.h> 27#include <asm/hardware.h>
28#include <asm/uaccess.h> 28#include <asm/uaccess.h>
29 29
30#ifdef CONFIG_WATCHDOG_NOWAYOUT 30static int nowayout = WATCHDOG_NOWAYOUT;
31static int nowayout = 1;
32#else
33static int nowayout = 0;
34#endif
35static int heartbeat = 60; /* (secs) Default is 1 minute */ 31static int heartbeat = 60; /* (secs) Default is 1 minute */
36static unsigned long wdt_status; 32static unsigned long wdt_status;
37static unsigned long boot_status; 33static unsigned long boot_status;
@@ -156,7 +152,7 @@ ixp4xx_wdt_release(struct inode *inode, struct file *file)
156 if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) { 152 if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) {
157 wdt_disable(); 153 wdt_disable();
158 } else { 154 } else {
159 printk(KERN_CRIT "WATCHDOG: Device closed unexpectdly - " 155 printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - "
160 "timer will not stop\n"); 156 "timer will not stop\n");
161 } 157 }
162 158
diff --git a/drivers/char/watchdog/machzwd.c b/drivers/char/watchdog/machzwd.c
index 9da395fa7794..a9a20aad61e7 100644
--- a/drivers/char/watchdog/machzwd.c
+++ b/drivers/char/watchdog/machzwd.c
@@ -94,12 +94,7 @@ MODULE_DESCRIPTION("MachZ ZF-Logic Watchdog driver");
94MODULE_LICENSE("GPL"); 94MODULE_LICENSE("GPL");
95MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 95MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
96 96
97#ifdef CONFIG_WATCHDOG_NOWAYOUT 97static int nowayout = WATCHDOG_NOWAYOUT;
98static int nowayout = 1;
99#else
100static int nowayout = 0;
101#endif
102
103module_param(nowayout, int, 0); 98module_param(nowayout, int, 0);
104MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 99MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
105 100
diff --git a/drivers/char/watchdog/mixcomwd.c b/drivers/char/watchdog/mixcomwd.c
index 3143e4a07535..c9b301dccec3 100644
--- a/drivers/char/watchdog/mixcomwd.c
+++ b/drivers/char/watchdog/mixcomwd.c
@@ -62,12 +62,7 @@ static int mixcomwd_timer_alive;
62static struct timer_list mixcomwd_timer = TIMER_INITIALIZER(NULL, 0, 0); 62static struct timer_list mixcomwd_timer = TIMER_INITIALIZER(NULL, 0, 0);
63static char expect_close; 63static char expect_close;
64 64
65#ifdef CONFIG_WATCHDOG_NOWAYOUT 65static int nowayout = WATCHDOG_NOWAYOUT;
66static int nowayout = 1;
67#else
68static int nowayout = 0;
69#endif
70
71module_param(nowayout, int, 0); 66module_param(nowayout, int, 0);
72MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 67MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
73 68
diff --git a/drivers/char/watchdog/pcwd.c b/drivers/char/watchdog/pcwd.c
index 592dca108866..427ad51b7a35 100644
--- a/drivers/char/watchdog/pcwd.c
+++ b/drivers/char/watchdog/pcwd.c
@@ -146,12 +146,7 @@ static int heartbeat = WATCHDOG_HEARTBEAT;
146module_param(heartbeat, int, 0); 146module_param(heartbeat, int, 0);
147MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<=heartbeat<=7200, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); 147MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<=heartbeat<=7200, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
148 148
149#ifdef CONFIG_WATCHDOG_NOWAYOUT 149static int nowayout = WATCHDOG_NOWAYOUT;
150static int nowayout = 1;
151#else
152static int nowayout = 0;
153#endif
154
155module_param(nowayout, int, 0); 150module_param(nowayout, int, 0);
156MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 151MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
157 152
@@ -344,7 +339,7 @@ static int pcwd_get_status(int *status)
344 *status |= WDIOF_OVERHEAT; 339 *status |= WDIOF_OVERHEAT;
345 if (temp_panic) { 340 if (temp_panic) {
346 printk (KERN_INFO PFX "Temperature overheat trip!\n"); 341 printk (KERN_INFO PFX "Temperature overheat trip!\n");
347 machine_power_off(); 342 kernel_power_off();
348 } 343 }
349 } 344 }
350 } else { 345 } else {
@@ -355,7 +350,7 @@ static int pcwd_get_status(int *status)
355 *status |= WDIOF_OVERHEAT; 350 *status |= WDIOF_OVERHEAT;
356 if (temp_panic) { 351 if (temp_panic) {
357 printk (KERN_INFO PFX "Temperature overheat trip!\n"); 352 printk (KERN_INFO PFX "Temperature overheat trip!\n");
358 machine_power_off(); 353 kernel_power_off();
359 } 354 }
360 } 355 }
361 } 356 }
diff --git a/drivers/char/watchdog/pcwd_pci.c b/drivers/char/watchdog/pcwd_pci.c
index 8ce066627326..2b13afb09c5d 100644
--- a/drivers/char/watchdog/pcwd_pci.c
+++ b/drivers/char/watchdog/pcwd_pci.c
@@ -103,12 +103,7 @@ static int heartbeat = WATCHDOG_HEARTBEAT;
103module_param(heartbeat, int, 0); 103module_param(heartbeat, int, 0);
104MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); 104MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
105 105
106#ifdef CONFIG_WATCHDOG_NOWAYOUT 106static int nowayout = WATCHDOG_NOWAYOUT;
107static int nowayout = 1;
108#else
109static int nowayout = 0;
110#endif
111
112module_param(nowayout, int, 0); 107module_param(nowayout, int, 0);
113MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 108MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
114 109
diff --git a/drivers/char/watchdog/pcwd_usb.c b/drivers/char/watchdog/pcwd_usb.c
index 1127201d73b8..092e9b133750 100644
--- a/drivers/char/watchdog/pcwd_usb.c
+++ b/drivers/char/watchdog/pcwd_usb.c
@@ -79,12 +79,7 @@ static int heartbeat = WATCHDOG_HEARTBEAT;
79module_param(heartbeat, int, 0); 79module_param(heartbeat, int, 0);
80MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); 80MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")");
81 81
82#ifdef CONFIG_WATCHDOG_NOWAYOUT 82static int nowayout = WATCHDOG_NOWAYOUT;
83static int nowayout = 1;
84#else
85static int nowayout = 0;
86#endif
87
88module_param(nowayout, int, 0); 83module_param(nowayout, int, 0);
89MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 84MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
90 85
diff --git a/drivers/char/watchdog/s3c2410_wdt.c b/drivers/char/watchdog/s3c2410_wdt.c
index 1699d2c28ce5..f85ac898a49a 100644
--- a/drivers/char/watchdog/s3c2410_wdt.c
+++ b/drivers/char/watchdog/s3c2410_wdt.c
@@ -62,12 +62,7 @@
62#define CONFIG_S3C2410_WATCHDOG_ATBOOT (0) 62#define CONFIG_S3C2410_WATCHDOG_ATBOOT (0)
63#define CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME (15) 63#define CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME (15)
64 64
65#ifdef CONFIG_WATCHDOG_NOWAYOUT 65static int nowayout = WATCHDOG_NOWAYOUT;
66static int nowayout = 1;
67#else
68static int nowayout = 0;
69#endif
70
71static int tmr_margin = CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME; 66static int tmr_margin = CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME;
72static int tmr_atboot = CONFIG_S3C2410_WATCHDOG_ATBOOT; 67static int tmr_atboot = CONFIG_S3C2410_WATCHDOG_ATBOOT;
73static int soft_noboot = 0; 68static int soft_noboot = 0;
diff --git a/drivers/char/watchdog/sa1100_wdt.c b/drivers/char/watchdog/sa1100_wdt.c
index 34e8f7b15e30..fb88b4041dca 100644
--- a/drivers/char/watchdog/sa1100_wdt.c
+++ b/drivers/char/watchdog/sa1100_wdt.c
@@ -36,17 +36,10 @@
36#include <asm/uaccess.h> 36#include <asm/uaccess.h>
37 37
38#define OSCR_FREQ CLOCK_TICK_RATE 38#define OSCR_FREQ CLOCK_TICK_RATE
39#define SA1100_CLOSE_MAGIC (0x5afc4453)
40 39
41static unsigned long sa1100wdt_users; 40static unsigned long sa1100wdt_users;
42static int expect_close;
43static int pre_margin; 41static int pre_margin;
44static int boot_status; 42static int boot_status;
45#ifdef CONFIG_WATCHDOG_NOWAYOUT
46static int nowayout = 1;
47#else
48static int nowayout = 0;
49#endif
50 43
51/* 44/*
52 * Allow only one person to hold it open 45 * Allow only one person to hold it open
@@ -66,55 +59,33 @@ static int sa1100dog_open(struct inode *inode, struct file *file)
66} 59}
67 60
68/* 61/*
69 * Shut off the timer. 62 * The watchdog cannot be disabled.
70 * Lock it in if it's a module and we defined ...NOWAYOUT 63 *
71 * Oddly, the watchdog can only be enabled, but we can turn off 64 * Previous comments suggested that turning off the interrupt by
72 * the interrupt, which appears to prevent the watchdog timing out. 65 * clearing OIER[E3] would prevent the watchdog timing out but this
66 * does not appear to be true (at least on the PXA255).
73 */ 67 */
74static int sa1100dog_release(struct inode *inode, struct file *file) 68static int sa1100dog_release(struct inode *inode, struct file *file)
75{ 69{
76 OSMR3 = OSCR + pre_margin; 70 printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n");
77
78 if (expect_close == SA1100_CLOSE_MAGIC) {
79 OIER &= ~OIER_E3;
80 } else {
81 printk(KERN_CRIT "WATCHDOG: WDT device closed unexpectedly. WDT will not stop!\n");
82 }
83 71
84 clear_bit(1, &sa1100wdt_users); 72 clear_bit(1, &sa1100wdt_users);
85 expect_close = 0;
86 73
87 return 0; 74 return 0;
88} 75}
89 76
90static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos) 77static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos)
91{ 78{
92 if (len) { 79 if (len)
93 if (!nowayout) {
94 size_t i;
95
96 expect_close = 0;
97
98 for (i = 0; i != len; i++) {
99 char c;
100
101 if (get_user(c, data + i))
102 return -EFAULT;
103 if (c == 'V')
104 expect_close = SA1100_CLOSE_MAGIC;
105 }
106 }
107 /* Refresh OSMR3 timer. */ 80 /* Refresh OSMR3 timer. */
108 OSMR3 = OSCR + pre_margin; 81 OSMR3 = OSCR + pre_margin;
109 }
110 82
111 return len; 83 return len;
112} 84}
113 85
114static struct watchdog_info ident = { 86static struct watchdog_info ident = {
115 .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | 87 .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING,
116 WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, 88 .identity = "SA1100/PXA255 Watchdog",
117 .identity = "SA1100 Watchdog",
118}; 89};
119 90
120static int sa1100dog_ioctl(struct inode *inode, struct file *file, 91static int sa1100dog_ioctl(struct inode *inode, struct file *file,
@@ -176,7 +147,7 @@ static struct file_operations sa1100dog_fops =
176static struct miscdevice sa1100dog_miscdev = 147static struct miscdevice sa1100dog_miscdev =
177{ 148{
178 .minor = WATCHDOG_MINOR, 149 .minor = WATCHDOG_MINOR,
179 .name = "SA1100/PXA2xx watchdog", 150 .name = "watchdog",
180 .fops = &sa1100dog_fops, 151 .fops = &sa1100dog_fops,
181}; 152};
182 153
@@ -198,7 +169,6 @@ static int __init sa1100dog_init(void)
198 if (ret == 0) 169 if (ret == 0)
199 printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n", 170 printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n",
200 margin); 171 margin);
201
202 return ret; 172 return ret;
203} 173}
204 174
@@ -216,8 +186,5 @@ MODULE_DESCRIPTION("SA1100/PXA2xx Watchdog");
216module_param(margin, int, 0); 186module_param(margin, int, 0);
217MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)"); 187MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)");
218 188
219module_param(nowayout, int, 0);
220MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started");
221
222MODULE_LICENSE("GPL"); 189MODULE_LICENSE("GPL");
223MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 190MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
diff --git a/drivers/char/watchdog/sbc60xxwdt.c b/drivers/char/watchdog/sbc60xxwdt.c
index d7de9880605a..ed0bd55fbfc1 100644
--- a/drivers/char/watchdog/sbc60xxwdt.c
+++ b/drivers/char/watchdog/sbc60xxwdt.c
@@ -98,12 +98,7 @@ static int timeout = WATCHDOG_TIMEOUT; /* in seconds, will be multiplied by HZ t
98module_param(timeout, int, 0); 98module_param(timeout, int, 0);
99MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); 99MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
100 100
101#ifdef CONFIG_WATCHDOG_NOWAYOUT 101static int nowayout = WATCHDOG_NOWAYOUT;
102static int nowayout = 1;
103#else
104static int nowayout = 0;
105#endif
106
107module_param(nowayout, int, 0); 102module_param(nowayout, int, 0);
108MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 103MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
109 104
diff --git a/drivers/char/watchdog/sc1200wdt.c b/drivers/char/watchdog/sc1200wdt.c
index 24401e84729e..515ce7572049 100644
--- a/drivers/char/watchdog/sc1200wdt.c
+++ b/drivers/char/watchdog/sc1200wdt.c
@@ -91,12 +91,7 @@ MODULE_PARM_DESC(io, "io port");
91module_param(timeout, int, 0); 91module_param(timeout, int, 0);
92MODULE_PARM_DESC(timeout, "range is 0-255 minutes, default is 1"); 92MODULE_PARM_DESC(timeout, "range is 0-255 minutes, default is 1");
93 93
94#ifdef CONFIG_WATCHDOG_NOWAYOUT 94static int nowayout = WATCHDOG_NOWAYOUT;
95static int nowayout = 1;
96#else
97static int nowayout = 0;
98#endif
99
100module_param(nowayout, int, 0); 95module_param(nowayout, int, 0);
101MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 96MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
102 97
diff --git a/drivers/char/watchdog/sc520_wdt.c b/drivers/char/watchdog/sc520_wdt.c
index f6d143e1900d..72501be79b0c 100644
--- a/drivers/char/watchdog/sc520_wdt.c
+++ b/drivers/char/watchdog/sc520_wdt.c
@@ -94,12 +94,7 @@ static int timeout = WATCHDOG_TIMEOUT; /* in seconds, will be multiplied by HZ t
94module_param(timeout, int, 0); 94module_param(timeout, int, 0);
95MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); 95MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
96 96
97#ifdef CONFIG_WATCHDOG_NOWAYOUT 97static int nowayout = WATCHDOG_NOWAYOUT;
98static int nowayout = 1;
99#else
100static int nowayout = 0;
101#endif
102
103module_param(nowayout, int, 0); 98module_param(nowayout, int, 0);
104MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 99MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
105 100
diff --git a/drivers/char/watchdog/scx200_wdt.c b/drivers/char/watchdog/scx200_wdt.c
index b569670e4ed5..c4568569f3a8 100644
--- a/drivers/char/watchdog/scx200_wdt.c
+++ b/drivers/char/watchdog/scx200_wdt.c
@@ -39,15 +39,11 @@ MODULE_DESCRIPTION("NatSemi SCx200 Watchdog Driver");
39MODULE_LICENSE("GPL"); 39MODULE_LICENSE("GPL");
40MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); 40MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
41 41
42#ifndef CONFIG_WATCHDOG_NOWAYOUT
43#define CONFIG_WATCHDOG_NOWAYOUT 0
44#endif
45
46static int margin = 60; /* in seconds */ 42static int margin = 60; /* in seconds */
47module_param(margin, int, 0); 43module_param(margin, int, 0);
48MODULE_PARM_DESC(margin, "Watchdog margin in seconds"); 44MODULE_PARM_DESC(margin, "Watchdog margin in seconds");
49 45
50static int nowayout = CONFIG_WATCHDOG_NOWAYOUT; 46static int nowayout = WATCHDOG_NOWAYOUT;
51module_param(nowayout, int, 0); 47module_param(nowayout, int, 0);
52MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); 48MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close");
53 49
diff --git a/drivers/char/watchdog/shwdt.c b/drivers/char/watchdog/shwdt.c
index 3bc9272a474c..1f4cab55b2ef 100644
--- a/drivers/char/watchdog/shwdt.c
+++ b/drivers/char/watchdog/shwdt.c
@@ -75,11 +75,7 @@ static unsigned long next_heartbeat;
75#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ 75#define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */
76static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ 76static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */
77 77
78#ifdef CONFIG_WATCHDOG_NOWAYOUT 78static int nowayout = WATCHDOG_NOWAYOUT;
79static int nowayout = 1;
80#else
81static int nowayout = 0;
82#endif
83 79
84/** 80/**
85 * sh_wdt_start - Start the Watchdog 81 * sh_wdt_start - Start the Watchdog
diff --git a/drivers/char/watchdog/softdog.c b/drivers/char/watchdog/softdog.c
index 117903498a01..4d7ed931f5c6 100644
--- a/drivers/char/watchdog/softdog.c
+++ b/drivers/char/watchdog/softdog.c
@@ -56,12 +56,7 @@ static int soft_margin = TIMER_MARGIN; /* in seconds */
56module_param(soft_margin, int, 0); 56module_param(soft_margin, int, 0);
57MODULE_PARM_DESC(soft_margin, "Watchdog soft_margin in seconds. (0<soft_margin<65536, default=" __MODULE_STRING(TIMER_MARGIN) ")"); 57MODULE_PARM_DESC(soft_margin, "Watchdog soft_margin in seconds. (0<soft_margin<65536, default=" __MODULE_STRING(TIMER_MARGIN) ")");
58 58
59#ifdef CONFIG_WATCHDOG_NOWAYOUT 59static int nowayout = WATCHDOG_NOWAYOUT;
60static int nowayout = 1;
61#else
62static int nowayout = 0;
63#endif
64
65module_param(nowayout, int, 0); 60module_param(nowayout, int, 0);
66MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 61MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
67 62
@@ -97,7 +92,7 @@ static void watchdog_fire(unsigned long data)
97 else 92 else
98 { 93 {
99 printk(KERN_CRIT PFX "Initiating system reboot.\n"); 94 printk(KERN_CRIT PFX "Initiating system reboot.\n");
100 machine_restart(NULL); 95 emergency_restart();
101 printk(KERN_CRIT PFX "Reboot didn't ?????\n"); 96 printk(KERN_CRIT PFX "Reboot didn't ?????\n");
102 } 97 }
103} 98}
diff --git a/drivers/char/watchdog/w83627hf_wdt.c b/drivers/char/watchdog/w83627hf_wdt.c
index 813c97038f84..465e0fd0423d 100644
--- a/drivers/char/watchdog/w83627hf_wdt.c
+++ b/drivers/char/watchdog/w83627hf_wdt.c
@@ -54,12 +54,7 @@ static int timeout = WATCHDOG_TIMEOUT; /* in seconds */
54module_param(timeout, int, 0); 54module_param(timeout, int, 0);
55MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); 55MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ".");
56 56
57#ifdef CONFIG_WATCHDOG_NOWAYOUT 57static int nowayout = WATCHDOG_NOWAYOUT;
58static int nowayout = 1;
59#else
60static int nowayout = 0;
61#endif
62
63module_param(nowayout, int, 0); 58module_param(nowayout, int, 0);
64MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 59MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
65 60
diff --git a/drivers/char/watchdog/w83877f_wdt.c b/drivers/char/watchdog/w83877f_wdt.c
index bccbd4d6ac2d..52a8bd0a5988 100644
--- a/drivers/char/watchdog/w83877f_wdt.c
+++ b/drivers/char/watchdog/w83877f_wdt.c
@@ -85,12 +85,7 @@ module_param(timeout, int, 0);
85MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); 85MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
86 86
87 87
88#ifdef CONFIG_WATCHDOG_NOWAYOUT 88static int nowayout = WATCHDOG_NOWAYOUT;
89static int nowayout = 1;
90#else
91static int nowayout = 0;
92#endif
93
94module_param(nowayout, int, 0); 89module_param(nowayout, int, 0);
95MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 90MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
96 91
diff --git a/drivers/char/watchdog/wafer5823wdt.c b/drivers/char/watchdog/wafer5823wdt.c
index abb0bea45c02..7cf6c9bbf486 100644
--- a/drivers/char/watchdog/wafer5823wdt.c
+++ b/drivers/char/watchdog/wafer5823wdt.c
@@ -63,12 +63,7 @@ static int timeout = WD_TIMO; /* in seconds */
63module_param(timeout, int, 0); 63module_param(timeout, int, 0);
64MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255, default=" __MODULE_STRING(WD_TIMO) "."); 64MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255, default=" __MODULE_STRING(WD_TIMO) ".");
65 65
66#ifdef CONFIG_WATCHDOG_NOWAYOUT 66static int nowayout = WATCHDOG_NOWAYOUT;
67static int nowayout = 1;
68#else
69static int nowayout = 0;
70#endif
71
72module_param(nowayout, int, 0); 67module_param(nowayout, int, 0);
73MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 68MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
74 69
diff --git a/drivers/char/watchdog/wdrtas.c b/drivers/char/watchdog/wdrtas.c
new file mode 100644
index 000000000000..619e2ffca33f
--- /dev/null
+++ b/drivers/char/watchdog/wdrtas.c
@@ -0,0 +1,696 @@
1/*
2 * FIXME: add wdrtas_get_status and wdrtas_get_boot_status as soon as
3 * RTAS calls are available
4 */
5
6/*
7 * RTAS watchdog driver
8 *
9 * (C) Copyright IBM Corp. 2005
10 * device driver to exploit watchdog RTAS functions
11 *
12 * Authors : Utz Bacher <utz.bacher@de.ibm.com>
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2, or (at your option)
17 * any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
27 */
28
29#include <linux/config.h>
30#include <linux/fs.h>
31#include <linux/init.h>
32#include <linux/kernel.h>
33#include <linux/miscdevice.h>
34#include <linux/module.h>
35#include <linux/notifier.h>
36#include <linux/reboot.h>
37#include <linux/types.h>
38#include <linux/watchdog.h>
39
40#include <asm/rtas.h>
41#include <asm/uaccess.h>
42
43#define WDRTAS_MAGIC_CHAR 42
44#define WDRTAS_SUPPORTED_MASK (WDIOF_SETTIMEOUT | \
45 WDIOF_MAGICCLOSE)
46
47MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>");
48MODULE_DESCRIPTION("RTAS watchdog driver");
49MODULE_LICENSE("GPL");
50MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
51MODULE_ALIAS_MISCDEV(TEMP_MINOR);
52
53#ifdef CONFIG_WATCHDOG_NOWAYOUT
54static int wdrtas_nowayout = 1;
55#else
56static int wdrtas_nowayout = 0;
57#endif
58
59static atomic_t wdrtas_miscdev_open = ATOMIC_INIT(0);
60static char wdrtas_expect_close = 0;
61
62static int wdrtas_interval;
63
64#define WDRTAS_THERMAL_SENSOR 3
65static int wdrtas_token_get_sensor_state;
66#define WDRTAS_SURVEILLANCE_IND 9000
67static int wdrtas_token_set_indicator;
68#define WDRTAS_SP_SPI 28
69static int wdrtas_token_get_sp;
70static int wdrtas_token_event_scan;
71
72#define WDRTAS_DEFAULT_INTERVAL 300
73
74#define WDRTAS_LOGBUFFER_LEN 128
75static char wdrtas_logbuffer[WDRTAS_LOGBUFFER_LEN];
76
77
78/*** watchdog access functions */
79
80/**
81 * wdrtas_set_interval - sets the watchdog interval
82 * @interval: new interval
83 *
84 * returns 0 on success, <0 on failures
85 *
86 * wdrtas_set_interval sets the watchdog keepalive interval by calling the
87 * RTAS function set-indicator (surveillance). The unit of interval is
88 * seconds.
89 */
90static int
91wdrtas_set_interval(int interval)
92{
93 long result;
94 static int print_msg = 10;
95
96 /* rtas uses minutes */
97 interval = (interval + 59) / 60;
98
99 result = rtas_call(wdrtas_token_set_indicator, 3, 1, NULL,
100 WDRTAS_SURVEILLANCE_IND, 0, interval);
101 if ( (result < 0) && (print_msg) ) {
102 printk(KERN_ERR "wdrtas: setting the watchdog to %i "
103 "timeout failed: %li\n", interval, result);
104 print_msg--;
105 }
106
107 return result;
108}
109
110/**
111 * wdrtas_get_interval - returns the current watchdog interval
112 * @fallback_value: value (in seconds) to use, if the RTAS call fails
113 *
114 * returns the interval
115 *
116 * wdrtas_get_interval returns the current watchdog keepalive interval
117 * as reported by the RTAS function ibm,get-system-parameter. The unit
118 * of the return value is seconds.
119 */
120static int
121wdrtas_get_interval(int fallback_value)
122{
123 long result;
124 char value[4];
125
126 result = rtas_call(wdrtas_token_get_sp, 3, 1, NULL,
127 WDRTAS_SP_SPI, (void *)__pa(&value), 4);
128 if ( (value[0] != 0) || (value[1] != 2) || (value[3] != 0) ||
129 (result < 0) ) {
130 printk(KERN_WARNING "wdrtas: could not get sp_spi watchdog "
131 "timeout (%li). Continuing\n", result);
132 return fallback_value;
133 }
134
135 /* rtas uses minutes */
136 return ((int)value[2]) * 60;
137}
138
139/**
140 * wdrtas_timer_start - starts watchdog
141 *
142 * wdrtas_timer_start starts the watchdog by calling the RTAS function
143 * set-interval (surveillance)
144 */
145static void
146wdrtas_timer_start(void)
147{
148 wdrtas_set_interval(wdrtas_interval);
149}
150
151/**
152 * wdrtas_timer_stop - stops watchdog
153 *
154 * wdrtas_timer_stop stops the watchdog timer by calling the RTAS function
155 * set-interval (surveillance)
156 */
157static void
158wdrtas_timer_stop(void)
159{
160 wdrtas_set_interval(0);
161}
162
163/**
164 * wdrtas_log_scanned_event - logs an event we received during keepalive
165 *
166 * wdrtas_log_scanned_event prints a message to the log buffer dumping
167 * the results of the last event-scan call
168 */
169static void
170wdrtas_log_scanned_event(void)
171{
172 int i;
173
174 for (i = 0; i < WDRTAS_LOGBUFFER_LEN; i += 16)
175 printk(KERN_INFO "wdrtas: dumping event (line %i/%i), data = "
176 "%02x %02x %02x %02x %02x %02x %02x %02x "
177 "%02x %02x %02x %02x %02x %02x %02x %02x\n",
178 (i / 16) + 1, (WDRTAS_LOGBUFFER_LEN / 16),
179 wdrtas_logbuffer[i + 0], wdrtas_logbuffer[i + 1],
180 wdrtas_logbuffer[i + 2], wdrtas_logbuffer[i + 3],
181 wdrtas_logbuffer[i + 4], wdrtas_logbuffer[i + 5],
182 wdrtas_logbuffer[i + 6], wdrtas_logbuffer[i + 7],
183 wdrtas_logbuffer[i + 8], wdrtas_logbuffer[i + 9],
184 wdrtas_logbuffer[i + 10], wdrtas_logbuffer[i + 11],
185 wdrtas_logbuffer[i + 12], wdrtas_logbuffer[i + 13],
186 wdrtas_logbuffer[i + 14], wdrtas_logbuffer[i + 15]);
187}
188
189/**
190 * wdrtas_timer_keepalive - resets watchdog timer to keep system alive
191 *
192 * wdrtas_timer_keepalive restarts the watchdog timer by calling the
193 * RTAS function event-scan and repeats these calls as long as there are
194 * events available. All events will be dumped.
195 */
196static void
197wdrtas_timer_keepalive(void)
198{
199 long result;
200
201 do {
202 result = rtas_call(wdrtas_token_event_scan, 4, 1, NULL,
203 RTAS_EVENT_SCAN_ALL_EVENTS, 0,
204 (void *)__pa(wdrtas_logbuffer),
205 WDRTAS_LOGBUFFER_LEN);
206 if (result < 0)
207 printk(KERN_ERR "wdrtas: event-scan failed: %li\n",
208 result);
209 if (result == 0)
210 wdrtas_log_scanned_event();
211 } while (result == 0);
212}
213
214/**
215 * wdrtas_get_temperature - returns current temperature
216 *
217 * returns temperature or <0 on failures
218 *
219 * wdrtas_get_temperature returns the current temperature in Fahrenheit. It
220 * uses the RTAS call get-sensor-state, token 3 to do so
221 */
222static int
223wdrtas_get_temperature(void)
224{
225 long result;
226 int temperature = 0;
227
228 result = rtas_call(wdrtas_token_get_sensor_state, 2, 2,
229 (void *)__pa(&temperature),
230 WDRTAS_THERMAL_SENSOR, 0);
231
232 if (result < 0)
233 printk(KERN_WARNING "wdrtas: reading the thermal sensor "
234 "faild: %li\n", result);
235 else
236 temperature = ((temperature * 9) / 5) + 32; /* fahrenheit */
237
238 return temperature;
239}
240
241/**
242 * wdrtas_get_status - returns the status of the watchdog
243 *
244 * returns a bitmask of defines WDIOF_... as defined in
245 * include/linux/watchdog.h
246 */
247static int
248wdrtas_get_status(void)
249{
250 return 0; /* TODO */
251}
252
253/**
254 * wdrtas_get_boot_status - returns the reason for the last boot
255 *
256 * returns a bitmask of defines WDIOF_... as defined in
257 * include/linux/watchdog.h, indicating why the watchdog rebooted the system
258 */
259static int
260wdrtas_get_boot_status(void)
261{
262 return 0; /* TODO */
263}
264
265/*** watchdog API and operations stuff */
266
267/* wdrtas_write - called when watchdog device is written to
268 * @file: file structure
269 * @buf: user buffer with data
270 * @len: amount to data written
271 * @ppos: position in file
272 *
273 * returns the number of successfully processed characters, which is always
274 * the number of bytes passed to this function
275 *
276 * wdrtas_write processes all the data given to it and looks for the magic
277 * character 'V'. This character allows the watchdog device to be closed
278 * properly.
279 */
280static ssize_t
281wdrtas_write(struct file *file, const char __user *buf,
282 size_t len, loff_t *ppos)
283{
284 int i;
285 char c;
286
287 if (!len)
288 goto out;
289
290 if (!wdrtas_nowayout) {
291 wdrtas_expect_close = 0;
292 /* look for 'V' */
293 for (i = 0; i < len; i++) {
294 if (get_user(c, buf + i))
295 return -EFAULT;
296 /* allow to close device */
297 if (c == 'V')
298 wdrtas_expect_close = WDRTAS_MAGIC_CHAR;
299 }
300 }
301
302 wdrtas_timer_keepalive();
303
304out:
305 return len;
306}
307
308/**
309 * wdrtas_ioctl - ioctl function for the watchdog device
310 * @inode: inode structure
311 * @file: file structure
312 * @cmd: command for ioctl
313 * @arg: argument pointer
314 *
315 * returns 0 on success, <0 on failure
316 *
317 * wdrtas_ioctl implements the watchdog API ioctls
318 */
319static int
320wdrtas_ioctl(struct inode *inode, struct file *file,
321 unsigned int cmd, unsigned long arg)
322{
323 int __user *argp = (void *)arg;
324 int i;
325 static struct watchdog_info wdinfo = {
326 .options = WDRTAS_SUPPORTED_MASK,
327 .firmware_version = 0,
328 .identity = "wdrtas"
329 };
330
331 switch (cmd) {
332 case WDIOC_GETSUPPORT:
333 if (copy_to_user(argp, &wdinfo, sizeof(wdinfo)))
334 return -EFAULT;
335 return 0;
336
337 case WDIOC_GETSTATUS:
338 i = wdrtas_get_status();
339 return put_user(i, argp);
340
341 case WDIOC_GETBOOTSTATUS:
342 i = wdrtas_get_boot_status();
343 return put_user(i, argp);
344
345 case WDIOC_GETTEMP:
346 if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE)
347 return -EOPNOTSUPP;
348
349 i = wdrtas_get_temperature();
350 return put_user(i, argp);
351
352 case WDIOC_SETOPTIONS:
353 if (get_user(i, argp))
354 return -EFAULT;
355 if (i & WDIOS_DISABLECARD)
356 wdrtas_timer_stop();
357 if (i & WDIOS_ENABLECARD) {
358 wdrtas_timer_keepalive();
359 wdrtas_timer_start();
360 }
361 if (i & WDIOS_TEMPPANIC) {
362 /* not implemented. Done by H8 */
363 }
364 return 0;
365
366 case WDIOC_KEEPALIVE:
367 wdrtas_timer_keepalive();
368 return 0;
369
370 case WDIOC_SETTIMEOUT:
371 if (get_user(i, argp))
372 return -EFAULT;
373
374 if (wdrtas_set_interval(i))
375 return -EINVAL;
376
377 wdrtas_timer_keepalive();
378
379 if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE)
380 wdrtas_interval = i;
381 else
382 wdrtas_interval = wdrtas_get_interval(i);
383 /* fallthrough */
384
385 case WDIOC_GETTIMEOUT:
386 return put_user(wdrtas_interval, argp);
387
388 default:
389 return -ENOIOCTLCMD;
390 }
391}
392
393/**
394 * wdrtas_open - open function of watchdog device
395 * @inode: inode structure
396 * @file: file structure
397 *
398 * returns 0 on success, -EBUSY if the file has been opened already, <0 on
399 * other failures
400 *
401 * function called when watchdog device is opened
402 */
403static int
404wdrtas_open(struct inode *inode, struct file *file)
405{
406 /* only open once */
407 if (atomic_inc_return(&wdrtas_miscdev_open) > 1) {
408 atomic_dec(&wdrtas_miscdev_open);
409 return -EBUSY;
410 }
411
412 wdrtas_timer_start();
413 wdrtas_timer_keepalive();
414
415 return nonseekable_open(inode, file);
416}
417
418/**
419 * wdrtas_close - close function of watchdog device
420 * @inode: inode structure
421 * @file: file structure
422 *
423 * returns 0 on success
424 *
425 * close function. Always succeeds
426 */
427static int
428wdrtas_close(struct inode *inode, struct file *file)
429{
430 /* only stop watchdog, if this was announced using 'V' before */
431 if (wdrtas_expect_close == WDRTAS_MAGIC_CHAR)
432 wdrtas_timer_stop();
433 else {
434 printk(KERN_WARNING "wdrtas: got unexpected close. Watchdog "
435 "not stopped.\n");
436 wdrtas_timer_keepalive();
437 }
438
439 wdrtas_expect_close = 0;
440 atomic_dec(&wdrtas_miscdev_open);
441 return 0;
442}
443
444/**
445 * wdrtas_temp_read - gives back the temperature in fahrenheit
446 * @file: file structure
447 * @buf: user buffer
448 * @count: number of bytes to be read
449 * @ppos: position in file
450 *
451 * returns always 1 or -EFAULT in case of user space copy failures, <0 on
452 * other failures
453 *
454 * wdrtas_temp_read gives the temperature to the users by copying this
455 * value as one byte into the user space buffer. The unit is Fahrenheit...
456 */
457static ssize_t
458wdrtas_temp_read(struct file *file, char __user *buf,
459 size_t count, loff_t *ppos)
460{
461 int temperature = 0;
462
463 temperature = wdrtas_get_temperature();
464 if (temperature < 0)
465 return temperature;
466
467 if (copy_to_user(buf, &temperature, 1))
468 return -EFAULT;
469
470 return 1;
471}
472
473/**
474 * wdrtas_temp_open - open function of temperature device
475 * @inode: inode structure
476 * @file: file structure
477 *
478 * returns 0 on success, <0 on failure
479 *
480 * function called when temperature device is opened
481 */
482static int
483wdrtas_temp_open(struct inode *inode, struct file *file)
484{
485 return nonseekable_open(inode, file);
486}
487
488/**
489 * wdrtas_temp_close - close function of temperature device
490 * @inode: inode structure
491 * @file: file structure
492 *
493 * returns 0 on success
494 *
495 * close function. Always succeeds
496 */
497static int
498wdrtas_temp_close(struct inode *inode, struct file *file)
499{
500 return 0;
501}
502
503/**
504 * wdrtas_reboot - reboot notifier function
505 * @nb: notifier block structure
506 * @code: reboot code
507 * @ptr: unused
508 *
509 * returns NOTIFY_DONE
510 *
511 * wdrtas_reboot stops the watchdog in case of a reboot
512 */
513static int
514wdrtas_reboot(struct notifier_block *this, unsigned long code, void *ptr)
515{
516 if ( (code==SYS_DOWN) || (code==SYS_HALT) )
517 wdrtas_timer_stop();
518
519 return NOTIFY_DONE;
520}
521
522/*** initialization stuff */
523
524static struct file_operations wdrtas_fops = {
525 .owner = THIS_MODULE,
526 .llseek = no_llseek,
527 .write = wdrtas_write,
528 .ioctl = wdrtas_ioctl,
529 .open = wdrtas_open,
530 .release = wdrtas_close,
531};
532
533static struct miscdevice wdrtas_miscdev = {
534 .minor = WATCHDOG_MINOR,
535 .name = "watchdog",
536 .fops = &wdrtas_fops,
537};
538
539static struct file_operations wdrtas_temp_fops = {
540 .owner = THIS_MODULE,
541 .llseek = no_llseek,
542 .read = wdrtas_temp_read,
543 .open = wdrtas_temp_open,
544 .release = wdrtas_temp_close,
545};
546
547static struct miscdevice wdrtas_tempdev = {
548 .minor = TEMP_MINOR,
549 .name = "temperature",
550 .fops = &wdrtas_temp_fops,
551};
552
553static struct notifier_block wdrtas_notifier = {
554 .notifier_call = wdrtas_reboot,
555};
556
557/**
558 * wdrtas_get_tokens - reads in RTAS tokens
559 *
560 * returns 0 on succes, <0 on failure
561 *
562 * wdrtas_get_tokens reads in the tokens for the RTAS calls used in
563 * this watchdog driver. It tolerates, if "get-sensor-state" and
564 * "ibm,get-system-parameter" are not available.
565 */
566static int
567wdrtas_get_tokens(void)
568{
569 wdrtas_token_get_sensor_state = rtas_token("get-sensor-state");
570 if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE) {
571 printk(KERN_WARNING "wdrtas: couldn't get token for "
572 "get-sensor-state. Trying to continue without "
573 "temperature support.\n");
574 }
575
576 wdrtas_token_get_sp = rtas_token("ibm,get-system-parameter");
577 if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE) {
578 printk(KERN_WARNING "wdrtas: couldn't get token for "
579 "ibm,get-system-parameter. Trying to continue with "
580 "a default timeout value of %i seconds.\n",
581 WDRTAS_DEFAULT_INTERVAL);
582 }
583
584 wdrtas_token_set_indicator = rtas_token("set-indicator");
585 if (wdrtas_token_set_indicator == RTAS_UNKNOWN_SERVICE) {
586 printk(KERN_ERR "wdrtas: couldn't get token for "
587 "set-indicator. Terminating watchdog code.\n");
588 return -EIO;
589 }
590
591 wdrtas_token_event_scan = rtas_token("event-scan");
592 if (wdrtas_token_event_scan == RTAS_UNKNOWN_SERVICE) {
593 printk(KERN_ERR "wdrtas: couldn't get token for event-scan. "
594 "Terminating watchdog code.\n");
595 return -EIO;
596 }
597
598 return 0;
599}
600
601/**
602 * wdrtas_unregister_devs - unregisters the misc dev handlers
603 *
604 * wdrtas_register_devs unregisters the watchdog and temperature watchdog
605 * misc devs
606 */
607static void
608wdrtas_unregister_devs(void)
609{
610 misc_deregister(&wdrtas_miscdev);
611 if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE)
612 misc_deregister(&wdrtas_tempdev);
613}
614
615/**
616 * wdrtas_register_devs - registers the misc dev handlers
617 *
618 * returns 0 on succes, <0 on failure
619 *
620 * wdrtas_register_devs registers the watchdog and temperature watchdog
621 * misc devs
622 */
623static int
624wdrtas_register_devs(void)
625{
626 int result;
627
628 result = misc_register(&wdrtas_miscdev);
629 if (result) {
630 printk(KERN_ERR "wdrtas: couldn't register watchdog misc "
631 "device. Terminating watchdog code.\n");
632 return result;
633 }
634
635 if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE) {
636 result = misc_register(&wdrtas_tempdev);
637 if (result) {
638 printk(KERN_WARNING "wdrtas: couldn't register "
639 "watchdog temperature misc device. Continuing "
640 "without temperature support.\n");
641 wdrtas_token_get_sensor_state = RTAS_UNKNOWN_SERVICE;
642 }
643 }
644
645 return 0;
646}
647
648/**
649 * wdrtas_init - init function of the watchdog driver
650 *
651 * returns 0 on succes, <0 on failure
652 *
653 * registers the file handlers and the reboot notifier
654 */
655static int __init
656wdrtas_init(void)
657{
658 if (wdrtas_get_tokens())
659 return -ENODEV;
660
661 if (wdrtas_register_devs())
662 return -ENODEV;
663
664 if (register_reboot_notifier(&wdrtas_notifier)) {
665 printk(KERN_ERR "wdrtas: could not register reboot notifier. "
666 "Terminating watchdog code.\n");
667 wdrtas_unregister_devs();
668 return -ENODEV;
669 }
670
671 if (wdrtas_token_get_sp == RTAS_UNKNOWN_SERVICE)
672 wdrtas_interval = WDRTAS_DEFAULT_INTERVAL;
673 else
674 wdrtas_interval = wdrtas_get_interval(WDRTAS_DEFAULT_INTERVAL);
675
676 return 0;
677}
678
679/**
680 * wdrtas_exit - exit function of the watchdog driver
681 *
682 * unregisters the file handlers and the reboot notifier
683 */
684static void __exit
685wdrtas_exit(void)
686{
687 if (!wdrtas_nowayout)
688 wdrtas_timer_stop();
689
690 wdrtas_unregister_devs();
691
692 unregister_reboot_notifier(&wdrtas_notifier);
693}
694
695module_init(wdrtas_init);
696module_exit(wdrtas_exit);
diff --git a/drivers/char/watchdog/wdt.c b/drivers/char/watchdog/wdt.c
index 5684aa379886..ec7e401228ee 100644
--- a/drivers/char/watchdog/wdt.c
+++ b/drivers/char/watchdog/wdt.c
@@ -63,12 +63,7 @@ static int wd_heartbeat;
63module_param(heartbeat, int, 0); 63module_param(heartbeat, int, 0);
64MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")"); 64MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")");
65 65
66#ifdef CONFIG_WATCHDOG_NOWAYOUT 66static int nowayout = WATCHDOG_NOWAYOUT;
67static int nowayout = 1;
68#else
69static int nowayout = 0;
70#endif
71
72module_param(nowayout, int, 0); 67module_param(nowayout, int, 0);
73MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 68MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
74 69
@@ -266,7 +261,7 @@ static irqreturn_t wdt_interrupt(int irq, void *dev_id, struct pt_regs *regs)
266 printk(KERN_CRIT "Would Reboot.\n"); 261 printk(KERN_CRIT "Would Reboot.\n");
267#else 262#else
268 printk(KERN_CRIT "Initiating system reboot.\n"); 263 printk(KERN_CRIT "Initiating system reboot.\n");
269 machine_restart(NULL); 264 emergency_restart();
270#endif 265#endif
271#else 266#else
272 printk(KERN_CRIT "Reset in 5ms.\n"); 267 printk(KERN_CRIT "Reset in 5ms.\n");
diff --git a/drivers/char/watchdog/wdt977.c b/drivers/char/watchdog/wdt977.c
index 072e9b214759..44d49dfacbb3 100644
--- a/drivers/char/watchdog/wdt977.c
+++ b/drivers/char/watchdog/wdt977.c
@@ -53,12 +53,7 @@ MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (60..15300), default=" __M
53module_param(testmode, int, 0); 53module_param(testmode, int, 0);
54MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0"); 54MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0");
55 55
56#ifdef CONFIG_WATCHDOG_NOWAYOUT 56static int nowayout = WATCHDOG_NOWAYOUT;
57static int nowayout = 1;
58#else
59static int nowayout = 0;
60#endif
61
62module_param(nowayout, int, 0); 57module_param(nowayout, int, 0);
63MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 58MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
64 59
diff --git a/drivers/char/watchdog/wdt_pci.c b/drivers/char/watchdog/wdt_pci.c
index 7651deda928c..4b3311993d48 100644
--- a/drivers/char/watchdog/wdt_pci.c
+++ b/drivers/char/watchdog/wdt_pci.c
@@ -89,12 +89,7 @@ static int wd_heartbeat;
89module_param(heartbeat, int, 0); 89module_param(heartbeat, int, 0);
90MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")"); 90MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")");
91 91
92#ifdef CONFIG_WATCHDOG_NOWAYOUT 92static int nowayout = WATCHDOG_NOWAYOUT;
93static int nowayout = 1;
94#else
95static int nowayout = 0;
96#endif
97
98module_param(nowayout, int, 0); 93module_param(nowayout, int, 0);
99MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); 94MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)");
100 95
@@ -311,7 +306,7 @@ static irqreturn_t wdtpci_interrupt(int irq, void *dev_id, struct pt_regs *regs)
311 printk(KERN_CRIT PFX "Would Reboot.\n"); 306 printk(KERN_CRIT PFX "Would Reboot.\n");
312#else 307#else
313 printk(KERN_CRIT PFX "Initiating system reboot.\n"); 308 printk(KERN_CRIT PFX "Initiating system reboot.\n");
314 machine_restart(NULL); 309 emergency_restart(NULL);
315#endif 310#endif
316#else 311#else
317 printk(KERN_CRIT PFX "Reset in 5ms.\n"); 312 printk(KERN_CRIT PFX "Reset in 5ms.\n");