diff options
author | Dave Jones <davej@redhat.com> | 2005-08-18 01:56:07 -0400 |
---|---|---|
committer | Dave Jones <davej@redhat.com> | 2005-08-18 01:56:07 -0400 |
commit | a8b3e6f10f08f66ae1072efd087b30966a3654f6 (patch) | |
tree | 1d1409855f8ad5beabafe061c6453edd84ba94c8 /drivers/char | |
parent | 46acac3b4fd8ef66eec63b51de8d556a17c7d4f7 (diff) | |
parent | 099d44e869f1886b5eb02a5145ca97b5e4142e28 (diff) |
Merge /pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'drivers/char')
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 | ||
736 | config GEN_RTC | 736 | config 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 | ||
932 | config GPIO_VR41XX | ||
933 | tristate "NEC VR4100 series General-purpose I/O Unit support" | ||
934 | depends on CPU_VR41XX | ||
935 | |||
932 | config RAW_DRIVER | 936 | config 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 | ||
943 | config HPET | 947 | config 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 | |||
40 | obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o | 40 | obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o |
41 | obj-$(CONFIG_SX) += sx.o generic_serial.o | 41 | obj-$(CONFIG_SX) += sx.o generic_serial.o |
42 | obj-$(CONFIG_RIO) += rio/ generic_serial.o | 42 | obj-$(CONFIG_RIO) += rio/ generic_serial.o |
43 | obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o hvsi.o | 43 | obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o hvc_vio.o hvsi.o |
44 | obj-$(CONFIG_RAW_DRIVER) += raw.o | 44 | obj-$(CONFIG_RAW_DRIVER) += raw.o |
45 | obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o | 45 | obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o |
46 | obj-$(CONFIG_MMTIMER) += mmtimer.o | 46 | obj-$(CONFIG_MMTIMER) += mmtimer.o |
@@ -80,6 +80,7 @@ obj-$(CONFIG_PPDEV) += ppdev.o | |||
80 | obj-$(CONFIG_NWBUTTON) += nwbutton.o | 80 | obj-$(CONFIG_NWBUTTON) += nwbutton.o |
81 | obj-$(CONFIG_NWFLASH) += nwflash.o | 81 | obj-$(CONFIG_NWFLASH) += nwflash.o |
82 | obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o | 82 | obj-$(CONFIG_SCx200_GPIO) += scx200_gpio.o |
83 | obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o | ||
83 | obj-$(CONFIG_TANBAC_TB0219) += tb0219.o | 84 | obj-$(CONFIG_TANBAC_TB0219) += tb0219.o |
84 | 85 | ||
85 | obj-$(CONFIG_WATCHDOG) += watchdog/ | 86 | obj-$(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 | ||
862 | static void rs_put_char(struct tty_struct *tty, unsigned char ch) | 862 | static 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) | |||
910 | static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count) | 915 | static 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 | ||
1966 | int register_serial(struct serial_struct *req); | ||
1967 | void unregister_serial(int line); | ||
1968 | |||
1969 | |||
1970 | static struct tty_operations serial_ops = { | 1976 | static 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 | # |
7 | config DRM | 7 | config 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 | ||
99 | config 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 | |||
18 | radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o | 18 | radeon-objs := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o radeon_irq.o |
19 | ffb-objs := ffb_drv.o ffb_context.o | 19 | ffb-objs := ffb_drv.o ffb_context.o |
20 | sis-objs := sis_drv.o sis_ds.o sis_mm.o | 20 | sis-objs := sis_drv.o sis_ds.o sis_mm.o |
21 | via-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 | |||
23 | ifeq ($(CONFIG_COMPAT),y) | ||
24 | drm-objs += drm_ioc32.o | ||
25 | radeon-objs += radeon_ioc32.o | ||
26 | mga-objs += mga_ioc32.o | ||
27 | r128-objs += r128_ioc32.o | ||
28 | i915-objs += i915_ioc32.o | ||
29 | endif | ||
21 | 30 | ||
22 | obj-$(CONFIG_DRM) += drm.o | 31 | obj-$(CONFIG_DRM) += drm.o |
23 | obj-$(CONFIG_DRM_GAMMA) += gamma.o | 32 | obj-$(CONFIG_DRM_GAMMA) += gamma.o |
@@ -30,4 +39,5 @@ obj-$(CONFIG_DRM_I830) += i830.o | |||
30 | obj-$(CONFIG_DRM_I915) += i915.o | 39 | obj-$(CONFIG_DRM_I915) += i915.o |
31 | obj-$(CONFIG_DRM_FFB) += ffb.o | 40 | obj-$(CONFIG_DRM_FFB) += ffb.o |
32 | obj-$(CONFIG_DRM_SIS) += sis.o | 41 | obj-$(CONFIG_DRM_SIS) += sis.o |
42 | obj-$(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 | ||
55 | unsigned long drm_ati_alloc_pcigart_table( void ) | 55 | static 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 { \ | |||
316 | typedef int drm_ioctl_t( struct inode *inode, struct file *filp, | 316 | typedef 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 | ||
319 | typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd, | ||
320 | unsigned long arg); | ||
321 | |||
319 | typedef struct drm_ioctl_desc { | 322 | typedef 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) */ |
772 | extern int drm_init(struct drm_driver *driver); | 775 | extern int drm_init(struct drm_driver *driver); |
773 | extern void drm_exit(struct drm_driver *driver); | 776 | extern void drm_exit(struct drm_driver *driver); |
774 | extern int drm_version(struct inode *inode, struct file *filp, | ||
775 | unsigned int cmd, unsigned long arg); | ||
776 | extern int drm_ioctl(struct inode *inode, struct file *filp, | 777 | extern int drm_ioctl(struct inode *inode, struct file *filp, |
777 | unsigned int cmd, unsigned long arg); | 778 | unsigned int cmd, unsigned long arg); |
779 | extern long drm_compat_ioctl(struct file *filp, | ||
780 | unsigned int cmd, unsigned long arg); | ||
778 | extern int drm_takedown(drm_device_t * dev); | 781 | extern int drm_takedown(drm_device_t * dev); |
779 | 782 | ||
780 | /* Device support (drm_fops.h) */ | 783 | /* Device support (drm_fops.h) */ |
781 | extern int drm_open(struct inode *inode, struct file *filp); | 784 | extern int drm_open(struct inode *inode, struct file *filp); |
782 | extern int drm_stub_open(struct inode *inode, struct file *filp); | 785 | extern int drm_stub_open(struct inode *inode, struct file *filp); |
783 | extern int drm_open_helper(struct inode *inode, struct file *filp, | ||
784 | drm_device_t *dev); | ||
785 | extern int drm_flush(struct file *filp); | 786 | extern int drm_flush(struct file *filp); |
786 | extern int drm_fasync(int fd, struct file *filp, int on); | 787 | extern int drm_fasync(int fd, struct file *filp, int on); |
787 | extern int drm_release(struct inode *inode, struct file *filp); | 788 | extern int drm_release(struct inode *inode, struct file *filp); |
788 | 789 | ||
789 | /* Mapping support (drm_vm.h) */ | 790 | /* Mapping support (drm_vm.h) */ |
790 | extern void drm_vm_open(struct vm_area_struct *vma); | ||
791 | extern void drm_vm_close(struct vm_area_struct *vma); | ||
792 | extern void drm_vm_shm_close(struct vm_area_struct *vma); | ||
793 | extern int drm_mmap_dma(struct file *filp, | ||
794 | struct vm_area_struct *vma); | ||
795 | extern int drm_mmap(struct file *filp, struct vm_area_struct *vma); | 791 | extern int drm_mmap(struct file *filp, struct vm_area_struct *vma); |
796 | extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait); | 792 | extern unsigned int drm_poll(struct file *filp, struct poll_table_struct *wait); |
797 | extern 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" |
801 | extern void drm_mem_init(void); | 796 | extern void drm_mem_init(void); |
802 | extern int drm_mem_info(char *buf, char **start, off_t offset, | 797 | extern 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); |
804 | extern void *drm_calloc(size_t nmemb, size_t size, int area); | ||
805 | extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, | 799 | extern void *drm_realloc(void *oldpt, size_t oldsize, size_t size, |
806 | int area); | 800 | int area); |
807 | extern unsigned long drm_alloc_pages(int order, int area); | 801 | extern unsigned long drm_alloc_pages(int order, int area); |
@@ -849,9 +843,6 @@ extern int drm_newctx( struct inode *inode, struct file *filp, | |||
849 | extern int drm_rmctx( struct inode *inode, struct file *filp, | 843 | extern 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 | ||
852 | extern int drm_context_switch(drm_device_t *dev, int old, int new); | ||
853 | extern int drm_context_switch_complete(drm_device_t *dev, int new); | ||
854 | |||
855 | extern int drm_ctxbitmap_init( drm_device_t *dev ); | 846 | extern int drm_ctxbitmap_init( drm_device_t *dev ); |
856 | extern void drm_ctxbitmap_cleanup( drm_device_t *dev ); | 847 | extern void drm_ctxbitmap_cleanup( drm_device_t *dev ); |
857 | extern void drm_ctxbitmap_free( drm_device_t *dev, int ctx_handle ); | 848 | extern 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) */ |
872 | extern int drm_add_magic(drm_device_t *dev, drm_file_t *priv, | ||
873 | drm_magic_t magic); | ||
874 | extern int drm_remove_magic(drm_device_t *dev, drm_magic_t magic); | ||
875 | extern int drm_getmagic(struct inode *inode, struct file *filp, | 863 | extern int drm_getmagic(struct inode *inode, struct file *filp, |
876 | unsigned int cmd, unsigned long arg); | 864 | unsigned int cmd, unsigned long arg); |
877 | extern int drm_authmagic(struct inode *inode, struct file *filp, | 865 | extern 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); |
889 | extern int drm_lock_take(__volatile__ unsigned int *lock, | 877 | extern int drm_lock_take(__volatile__ unsigned int *lock, |
890 | unsigned int context); | 878 | unsigned int context); |
891 | extern int drm_lock_transfer(drm_device_t *dev, | ||
892 | __volatile__ unsigned int *lock, | ||
893 | unsigned int context); | ||
894 | extern int drm_lock_free(drm_device_t *dev, | 879 | extern 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); |
897 | extern int drm_notifier(void *priv); | ||
898 | 882 | ||
899 | /* Buffer management support (drm_bufs.h) */ | 883 | /* Buffer management support (drm_bufs.h) */ |
900 | extern int drm_order( unsigned long size ); | 884 | extern 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) */ |
923 | extern int drm_control( struct inode *inode, struct file *filp, | 907 | extern int drm_control( struct inode *inode, struct file *filp, |
924 | unsigned int cmd, unsigned long arg ); | 908 | unsigned int cmd, unsigned long arg ); |
925 | extern int drm_irq_install( drm_device_t *dev ); | ||
926 | extern int drm_irq_uninstall( drm_device_t *dev ); | 909 | extern int drm_irq_uninstall( drm_device_t *dev ); |
927 | extern irqreturn_t drm_irq_handler( DRM_IRQ_ARGS ); | 910 | extern irqreturn_t drm_irq_handler( DRM_IRQ_ARGS ); |
928 | extern void drm_driver_irq_preinstall( drm_device_t *dev ); | 911 | extern void drm_driver_irq_preinstall( drm_device_t *dev ); |
@@ -962,7 +945,6 @@ extern int drm_agp_unbind_memory(DRM_AGP_MEM *handle); | |||
962 | extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, | 945 | extern int drm_get_dev(struct pci_dev *pdev, const struct pci_device_id *ent, |
963 | struct drm_driver *driver); | 946 | struct drm_driver *driver); |
964 | extern int drm_put_dev(drm_device_t * dev); | 947 | extern int drm_put_dev(drm_device_t * dev); |
965 | extern int drm_get_head(drm_device_t * dev, drm_head_t *head); | ||
966 | extern int drm_put_head(drm_head_t * head); | 948 | extern int drm_put_head(drm_head_t * head); |
967 | extern unsigned int drm_debug; | 949 | extern unsigned int drm_debug; |
968 | extern unsigned int drm_cards_limit; | 950 | extern 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() */ | ||
1046 | static __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 |
1063 | extern void *drm_alloc(size_t size, int area); | 1051 | extern void *drm_alloc(size_t size, int area); |
1064 | extern void drm_free(void *pt, size_t size, int area); | 1052 | extern void drm_free(void *pt, size_t size, int area); |
1053 | extern 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 | */ |
90 | int drm_add_magic(drm_device_t *dev, drm_file_t *priv, drm_magic_t magic) | 90 | static 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 | */ |
127 | int drm_remove_magic(drm_device_t *dev, drm_magic_t magic) | 127 | static 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 | } |
61 | EXPORT_SYMBOL(drm_order); | 61 | EXPORT_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 | */ | ||
69 | static 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 | */ |
348 | int drm_addbufs_agp( struct inode *inode, struct file *filp, | 359 | static 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 | ||
513 | int drm_addbufs_pci( struct inode *inode, struct file *filp, | 524 | static 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 | ||
743 | int drm_addbufs_sg( struct inode *inode, struct file *filp, | 754 | static 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 | */ |
87 | int drm_ctxbitmap_next( drm_device_t *dev ) | 87 | static 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 | } |
268 | bad: | 268 | bad: |
@@ -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 | */ |
329 | int drm_context_switch_complete( drm_device_t *dev, int new ) | 329 | static 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 | ||
54 | static int drm_version(struct inode *inode, struct file *filp, | ||
55 | unsigned int cmd, unsigned long arg); | ||
56 | |||
54 | /** Ioctl table */ | 57 | /** Ioctl table */ |
55 | drm_ioctl_desc_t drm_ioctls[] = { | 58 | static 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 | */ |
450 | int drm_version( struct inode *inode, struct file *filp, | 453 | static 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 | ||
40 | static int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t *dev); | ||
41 | |||
40 | static int drm_setup( drm_device_t *dev ) | 42 | static 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 | */ |
344 | int drm_open_helper(struct inode *inode, struct file *filp, drm_device_t *dev) | 346 | static 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 | } |
444 | EXPORT_SYMBOL(drm_poll); | 446 | EXPORT_SYMBOL(drm_poll); |
445 | 447 | ||
446 | |||
447 | /** No-op. */ | ||
448 | ssize_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 | |||
70 | typedef 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 | |||
82 | static 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 | |||
124 | typedef struct drm_unique32 { | ||
125 | u32 unique_len; /**< Length of unique */ | ||
126 | u32 unique; /**< Unique name for driver instantiation */ | ||
127 | } drm_unique32_t; | ||
128 | |||
129 | static 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 | |||
159 | static 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 | |||
180 | typedef 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 | |||
189 | static 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 | |||
227 | static 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 | |||
270 | static 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 | |||
290 | typedef 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 | |||
299 | static 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 | |||
333 | typedef 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 | |||
341 | static 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 | |||
370 | typedef 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 | |||
379 | static 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 | |||
410 | static 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 | |||
433 | typedef struct drm_buf_info32 { | ||
434 | int count; /**< Entries in list */ | ||
435 | u32 list; | ||
436 | } drm_buf_info32_t; | ||
437 | |||
438 | static 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 | |||
490 | typedef 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 | |||
497 | typedef 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 | |||
503 | static 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 | |||
557 | typedef struct drm_buf_free32 { | ||
558 | int count; | ||
559 | u32 list; | ||
560 | } drm_buf_free32_t; | ||
561 | |||
562 | static 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 | |||
584 | typedef 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 | |||
589 | static 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 | |||
611 | static 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 | |||
642 | typedef struct drm_ctx_res32 { | ||
643 | int count; | ||
644 | u32 contexts; | ||
645 | } drm_ctx_res32_t; | ||
646 | |||
647 | static 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 | |||
678 | typedef 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 | |||
691 | static 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 | ||
735 | typedef struct drm_agp_mode32 { | ||
736 | u32 mode; /**< AGP mode */ | ||
737 | } drm_agp_mode32_t; | ||
738 | |||
739 | static 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 | |||
757 | typedef 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 | |||
771 | static 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 | |||
805 | typedef 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 | |||
812 | static 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 | |||
845 | static 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 | |||
862 | typedef 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 | |||
867 | static 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 | |||
887 | static 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 | |||
905 | typedef 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 | |||
910 | static 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 | |||
938 | static 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 | |||
956 | struct drm_wait_vblank_request32 { | ||
957 | drm_vblank_seq_type_t type; | ||
958 | unsigned int sequence; | ||
959 | u32 signal; | ||
960 | }; | ||
961 | |||
962 | struct 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 | |||
969 | typedef union drm_wait_vblank32 { | ||
970 | struct drm_wait_vblank_request32 request; | ||
971 | struct drm_wait_vblank_reply32 reply; | ||
972 | } drm_wait_vblank32_t; | ||
973 | |||
974 | static 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 | |||
1009 | drm_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 | */ | ||
1049 | long 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 | } | ||
1069 | EXPORT_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 | */ |
92 | int drm_irq_install( drm_device_t *dev ) | 92 | static 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 | ||
38 | static int drm_lock_transfer(drm_device_t *dev, | ||
39 | __volatile__ unsigned int *lock, | ||
40 | unsigned int context); | ||
41 | static 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 | */ |
228 | int drm_lock_transfer(drm_device_t *dev, | 233 | static 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 | */ |
285 | int drm_notifier(void *priv) | 291 | static 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() */ | ||
69 | void *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 | } | ||
79 | EXPORT_SYMBOL(drm_calloc); | ||
80 | |||
81 | /** Wrapper around kmalloc() and kfree() */ | 68 | /** Wrapper around kmalloc() and kfree() */ |
82 | void *drm_realloc(void *oldpt, size_t oldsize, size_t size, int area) | 69 | void *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 | */ |
60 | struct drm_proc_list { | 60 | static 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 | */ | ||
172 | int 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 | |||
200 | err_g1: | ||
201 | drm_free(dev, sizeof(*dev), DRM_MEM_STUB); | ||
202 | return ret; | ||
203 | } | ||
204 | EXPORT_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 | */ |
217 | int drm_get_head(drm_device_t *dev, drm_head_t *head) | 171 | static 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 | */ | ||
230 | int 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 | |||
258 | err_g1: | ||
259 | drm_free(dev, sizeof(*dev), DRM_MEM_STUB); | ||
260 | return ret; | ||
261 | } | ||
262 | EXPORT_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 | ||
41 | static void drm_vm_open(struct vm_area_struct *vma); | ||
42 | static 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 | */ |
166 | void drm_vm_shm_close(struct vm_area_struct *vma) | 168 | static 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 | */ |
402 | void drm_vm_open(struct vm_area_struct *vma) | 404 | static 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 | */ |
431 | void drm_vm_close(struct vm_area_struct *vma) | 433 | static 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 | */ |
466 | int drm_mmap_dma(struct file *filp, struct vm_area_struct *vma) | 468 | static 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 | ||
93 | static struct file_operations i810_buffer_fops = { | 93 | static 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 | |||
102 | int 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 | ||
120 | static 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 | |||
129 | static int i810_map_buffer(drm_buf_t *buf, struct file *filp) | 129 | static 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 | ||
1006 | int i810_flush_ioctl(struct inode *inode, struct file *filp, | 1006 | static 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 */ |
117 | extern void i810_reclaim_buffers(drm_device_t *dev, struct file *filp); | 117 | extern void i810_reclaim_buffers(drm_device_t *dev, struct file *filp); |
118 | extern int i810_mmap_buffers(struct file *filp, struct vm_area_struct *vma); | ||
119 | 118 | ||
120 | extern int i810_driver_dma_quiescent(drm_device_t *dev); | 119 | extern int i810_driver_dma_quiescent(drm_device_t *dev); |
121 | extern void i810_driver_release(drm_device_t *dev, struct file *filp); | 120 | extern 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 | ||
95 | static struct file_operations i830_buffer_fops = { | 95 | static 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 | |||
104 | int 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 | ||
122 | static 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 | |||
131 | static int i830_map_buffer(drm_buf_t *buf, struct file *filp) | 131 | static 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 | ||
43 | int postinit( struct drm_device *dev, unsigned long flags ) | 43 | static 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 */ |
124 | extern void i830_reclaim_buffers(drm_device_t *dev, struct file *filp); | 124 | extern void i830_reclaim_buffers(drm_device_t *dev, struct file *filp); |
125 | 125 | ||
126 | extern int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma); | ||
127 | |||
128 | /* i830_irq.c */ | 126 | /* i830_irq.c */ |
129 | extern int i830_irq_emit( struct inode *inode, struct file *filp, | 127 | extern 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 | 57 | static int i830_emit_irq(drm_device_t *dev) | |
58 | int 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 | ||
76 | int i830_wait_irq(drm_device_t *dev, int irq_nr) | 75 | static 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 | ||
15 | drm_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 | |||
30 | int 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 | ||
78 | int i915_dma_cleanup(drm_device_t * dev) | 81 | static 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 | ||
230 | int i915_dma_init(DRM_IOCTL_ARGS) | 233 | static 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 | ||
541 | int i915_flush_ioctl(DRM_IOCTL_ARGS) | 544 | static 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 | ||
550 | int i915_batchbuffer(DRM_IOCTL_ARGS) | 553 | static 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 | ||
584 | int i915_cmdbuffer(DRM_IOCTL_ARGS) | 587 | static 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 | ||
620 | int i915_do_cleanup_pageflip(drm_device_t * dev) | 623 | static 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 | |||
631 | int 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 | ||
642 | int i915_getparam(DRM_IOCTL_ARGS) | 634 | static 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 | ||
677 | int i915_setparam(DRM_IOCTL_ARGS) | 669 | static 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 | ||
718 | drm_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 | |||
733 | int 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 | ||
18 | int postinit( struct drm_device *dev, unsigned long flags ) | 37 | static 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 */ |
82 | extern int i915_dma_init(DRM_IOCTL_ARGS); | ||
83 | extern int i915_dma_cleanup(drm_device_t * dev); | ||
84 | extern int i915_flush_ioctl(DRM_IOCTL_ARGS); | ||
85 | extern int i915_batchbuffer(DRM_IOCTL_ARGS); | ||
86 | extern int i915_flip_bufs(DRM_IOCTL_ARGS); | ||
87 | extern int i915_getparam(DRM_IOCTL_ARGS); | ||
88 | extern int i915_setparam(DRM_IOCTL_ARGS); | ||
89 | extern int i915_cmdbuffer(DRM_IOCTL_ARGS); | ||
90 | extern void i915_kernel_lost_context(drm_device_t * dev); | 102 | extern void i915_kernel_lost_context(drm_device_t * dev); |
91 | extern void i915_driver_pretakedown(drm_device_t *dev); | 103 | extern void i915_driver_pretakedown(drm_device_t *dev); |
92 | extern void i915_driver_prerelease(drm_device_t *dev, DRMFILE filp); | 104 | extern 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 */ |
95 | extern int i915_irq_emit(DRM_IOCTL_ARGS); | 107 | extern int i915_irq_emit(DRM_IOCTL_ARGS); |
96 | extern int i915_irq_wait(DRM_IOCTL_ARGS); | 108 | extern int i915_irq_wait(DRM_IOCTL_ARGS); |
97 | extern int i915_wait_irq(drm_device_t * dev, int irq_nr); | ||
98 | extern int i915_emit_irq(drm_device_t * dev); | ||
99 | 109 | ||
100 | extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); | 110 | extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS); |
101 | extern void i915_driver_irq_preinstall(drm_device_t *dev); | 111 | extern void i915_driver_irq_preinstall(drm_device_t *dev); |
@@ -110,6 +120,10 @@ extern void i915_mem_takedown(struct mem_block **heap); | |||
110 | extern void i915_mem_release(drm_device_t * dev, | 120 | extern void i915_mem_release(drm_device_t * dev, |
111 | DRMFILE filp, struct mem_block *heap); | 121 | DRMFILE filp, struct mem_block *heap); |
112 | 122 | ||
123 | extern 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 | |||
39 | typedef 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 | |||
48 | static 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 | |||
72 | typedef 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 | |||
81 | static 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 | |||
106 | typedef struct drm_i915_irq_emit32 { | ||
107 | u32 irq_seq; | ||
108 | } drm_i915_irq_emit32_t; | ||
109 | |||
110 | static 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 | } | ||
128 | typedef struct drm_i915_getparam32 { | ||
129 | int param; | ||
130 | u32 value; | ||
131 | } drm_i915_getparam32_t; | ||
132 | |||
133 | static 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 | |||
153 | typedef 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 | |||
160 | static 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 | |||
183 | drm_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 | */ | ||
200 | long 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 | ||
39 | int i915_emit_irq(drm_device_t * dev) | 59 | static 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 | ||
59 | int i915_wait_irq(drm_device_t * dev, int irq_nr) | 79 | static 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 ); | |||
137 | extern void mga_driver_irq_preinstall( drm_device_t *dev ); | 137 | extern void mga_driver_irq_preinstall( drm_device_t *dev ); |
138 | extern void mga_driver_irq_postinstall( drm_device_t *dev ); | 138 | extern void mga_driver_irq_postinstall( drm_device_t *dev ); |
139 | extern void mga_driver_irq_uninstall( drm_device_t *dev ); | 139 | extern void mga_driver_irq_uninstall( drm_device_t *dev ); |
140 | extern 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 | |||
40 | typedef 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 | |||
61 | static 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 | |||
107 | typedef struct drm_mga_getparam32 { | ||
108 | int param; | ||
109 | u32 value; | ||
110 | } drm_mga_getparam32_t; | ||
111 | |||
112 | |||
113 | static 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 | |||
132 | drm_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 | */ | ||
146 | long 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 ); | |||
156 | extern void r128_driver_pretakedown(drm_device_t *dev); | 156 | extern void r128_driver_pretakedown(drm_device_t *dev); |
157 | extern void r128_driver_prerelease(drm_device_t *dev, DRMFILE filp); | 157 | extern void r128_driver_prerelease(drm_device_t *dev, DRMFILE filp); |
158 | 158 | ||
159 | extern 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 | |||
39 | typedef 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 | |||
63 | static 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 | |||
103 | typedef 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 | |||
112 | static 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 | |||
136 | typedef struct drm_r128_stipple32 { | ||
137 | u32 mask; | ||
138 | } drm_r128_stipple32_t; | ||
139 | |||
140 | static 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 | |||
158 | typedef struct drm_r128_getparam32 { | ||
159 | int param; | ||
160 | u32 value; | ||
161 | } drm_r128_getparam32_t; | ||
162 | |||
163 | static 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 | |||
182 | drm_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 | */ | ||
198 | long 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 | ||
1310 | int r128_do_cleanup_pageflip( drm_device_t *dev ) | 1310 | static 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 ); | |||
317 | extern int radeon_postinit( struct drm_device *dev, unsigned long flags ); | 317 | extern int radeon_postinit( struct drm_device *dev, unsigned long flags ); |
318 | extern int radeon_postcleanup( struct drm_device *dev ); | 318 | extern int radeon_postcleanup( struct drm_device *dev ); |
319 | 319 | ||
320 | extern 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 | |||
38 | typedef 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 | |||
61 | static 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 | |||
100 | typedef 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 | |||
109 | static 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 | |||
133 | typedef struct drm_radeon_stipple32 { | ||
134 | u32 mask; | ||
135 | } drm_radeon_stipple32_t; | ||
136 | |||
137 | static 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 | |||
157 | typedef 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 | |||
163 | typedef 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 | |||
172 | static 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 | |||
212 | typedef 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 | |||
221 | static 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 | |||
246 | typedef struct drm_radeon_cmd_buffer32 { | ||
247 | int bufsz; | ||
248 | u32 buf; | ||
249 | int nbox; | ||
250 | u32 boxes; | ||
251 | } drm_radeon_cmd_buffer32_t; | ||
252 | |||
253 | static 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 | |||
276 | typedef struct drm_radeon_getparam32 { | ||
277 | int param; | ||
278 | u32 value; | ||
279 | } drm_radeon_getparam32_t; | ||
280 | |||
281 | static 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 | |||
301 | typedef 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 | |||
308 | static 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 | |||
330 | typedef struct drm_radeon_irq_emit32 { | ||
331 | u32 irq_seq; | ||
332 | } drm_radeon_irq_emit32_t; | ||
333 | |||
334 | static 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 | |||
353 | drm_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 | */ | ||
374 | long 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 | ||
38 | static __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 | ||
88 | static __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 | |||
96 | static int radeon_emit_irq(drm_device_t *dev) | 94 | static 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 | ||
230 | void radeon_driver_irq_postinstall( drm_device_t *dev ) { | 224 | void 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 | |||
71 | static void via_cmdbuf_start(drm_via_private_t * dev_priv); | ||
72 | static void via_cmdbuf_pause(drm_via_private_t * dev_priv); | ||
73 | static void via_cmdbuf_reset(drm_via_private_t * dev_priv); | ||
74 | static void via_cmdbuf_rewind(drm_via_private_t * dev_priv); | ||
75 | static int via_wait_idle(drm_via_private_t * dev_priv); | ||
76 | static void via_pad_cache(drm_via_private_t *dev_priv, int qwords); | ||
77 | |||
78 | |||
79 | /* | ||
80 | * Free space in command buffer. | ||
81 | */ | ||
82 | |||
83 | static uint32_t | ||
84 | via_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 | |||
99 | static uint32_t | ||
100 | via_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 | |||
115 | static inline int | ||
116 | via_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 | |||
145 | static 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 | |||
158 | int 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 | |||
176 | static 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 | |||
227 | int 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 | |||
264 | static 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 | |||
319 | int 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 | |||
329 | int 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 | |||
338 | int 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 | |||
359 | extern int | ||
360 | via_parse_command_stream(drm_device_t *dev, const uint32_t * buf, unsigned int size); | ||
361 | static 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 | |||
381 | int 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 | |||
404 | static 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 | */ | ||
419 | static 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 | */ | ||
429 | static 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 | |||
495 | static 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 | |||
504 | static 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 | |||
540 | static 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 | |||
578 | static 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 | |||
588 | static 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 | |||
597 | static 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 | |||
655 | static void via_cmdbuf_rewind(drm_via_private_t * dev_priv) | ||
656 | { | ||
657 | via_cmdbuf_jump(dev_priv); | ||
658 | } | ||
659 | |||
660 | static 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 | |||
669 | static void via_cmdbuf_pause(drm_via_private_t * dev_priv) | ||
670 | { | ||
671 | via_cmdbuf_flush(dev_priv, HC_HAGPBpID_PAUSE); | ||
672 | } | ||
673 | |||
674 | static 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 | |||
684 | int | ||
685 | via_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 | ||
108 | typedef struct { | ||
109 | uint32_t offset; | ||
110 | uint32_t size; | ||
111 | } drm_via_agp_t; | ||
112 | |||
113 | typedef struct { | ||
114 | uint32_t offset; | ||
115 | uint32_t size; | ||
116 | } drm_via_fb_t; | ||
117 | |||
118 | typedef 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 | |||
126 | typedef 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 | |||
138 | typedef 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 | |||
148 | typedef 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 | |||
160 | typedef 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 | |||
168 | typedef 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 | |||
174 | typedef 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 | |||
197 | typedef 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 | |||
206 | typedef 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 | |||
215 | struct 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 | |||
222 | typedef 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 | |||
229 | int via_fb_init(DRM_IOCTL_ARGS); | ||
230 | int via_mem_alloc(DRM_IOCTL_ARGS); | ||
231 | int via_mem_free(DRM_IOCTL_ARGS); | ||
232 | int via_agp_init(DRM_IOCTL_ARGS); | ||
233 | int via_map_init(DRM_IOCTL_ARGS); | ||
234 | int via_decoder_futex(DRM_IOCTL_ARGS); | ||
235 | int via_dma_init(DRM_IOCTL_ARGS); | ||
236 | int via_cmdbuffer(DRM_IOCTL_ARGS); | ||
237 | int via_flush_ioctl(DRM_IOCTL_ARGS); | ||
238 | int via_pci_cmdbuffer(DRM_IOCTL_ARGS); | ||
239 | int via_cmdbuf_size(DRM_IOCTL_ARGS); | ||
240 | int 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 | |||
32 | static 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 | |||
44 | static 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 | |||
57 | static struct pci_device_id pciidlist[] = { | ||
58 | viadrv_PCI_IDS | ||
59 | }; | ||
60 | |||
61 | static 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 | |||
76 | static 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 | |||
110 | static int __init via_init(void) | ||
111 | { | ||
112 | via_init_command_verifier(); | ||
113 | return drm_init(&driver); | ||
114 | } | ||
115 | |||
116 | static void __exit via_exit(void) | ||
117 | { | ||
118 | drm_exit(&driver); | ||
119 | } | ||
120 | |||
121 | module_init(via_init); | ||
122 | module_exit(via_exit); | ||
123 | |||
124 | MODULE_AUTHOR(DRIVER_AUTHOR); | ||
125 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
126 | MODULE_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 | |||
45 | typedef struct drm_via_ring_buffer { | ||
46 | drm_map_t map; | ||
47 | char *virtual_start; | ||
48 | } drm_via_ring_buffer_t; | ||
49 | |||
50 | typedef uint32_t maskarray_t[5]; | ||
51 | |||
52 | typedef 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 | |||
59 | typedef 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 | |||
97 | extern int via_init_context(drm_device_t * dev, int context); | ||
98 | extern int via_final_context(drm_device_t * dev, int context); | ||
99 | |||
100 | extern int via_do_cleanup_map(drm_device_t * dev); | ||
101 | extern int via_map_init(struct inode *inode, struct file *filp, | ||
102 | unsigned int cmd, unsigned long arg); | ||
103 | extern int via_driver_vblank_wait(drm_device_t * dev, unsigned int *sequence); | ||
104 | |||
105 | extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS); | ||
106 | extern void via_driver_irq_preinstall(drm_device_t * dev); | ||
107 | extern void via_driver_irq_postinstall(drm_device_t * dev); | ||
108 | extern void via_driver_irq_uninstall(drm_device_t * dev); | ||
109 | |||
110 | extern int via_dma_cleanup(drm_device_t * dev); | ||
111 | extern void via_init_command_verifier(void); | ||
112 | extern int via_driver_dma_quiescent(drm_device_t * dev); | ||
113 | extern void via_init_futex(drm_via_private_t *dev_priv); | ||
114 | extern void via_cleanup_futex(drm_via_private_t *dev_priv); | ||
115 | extern 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" | ||
35 | extern unsigned int VIA_DEBUG; | ||
36 | |||
37 | set_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 | |||
53 | int 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 | |||
68 | int 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 | |||
98 | int 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 | |||
109 | int 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 | |||
120 | int 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 | |||
131 | memHeap_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 | |||
149 | static 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 | |||
189 | PMemBlock 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 | |||
227 | static __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 | |||
241 | int 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 | ||
33 | typedef unsigned long ITEM_TYPE; | ||
34 | |||
35 | typedef struct { | ||
36 | ITEM_TYPE val; | ||
37 | int alloc_next, free_next; | ||
38 | } list_item_t; | ||
39 | |||
40 | typedef struct { | ||
41 | int alloc; | ||
42 | int free; | ||
43 | int trace; | ||
44 | list_item_t list[SET_SIZE]; | ||
45 | } set_t; | ||
46 | |||
47 | set_t *via_setInit(void); | ||
48 | int via_setAdd(set_t * set, ITEM_TYPE item); | ||
49 | int via_setDel(set_t * set, ITEM_TYPE item); | ||
50 | int via_setFirst(set_t * set, ITEM_TYPE * item); | ||
51 | int via_setNext(set_t * set, ITEM_TYPE * item); | ||
52 | int via_setDestroy(set_t * set); | ||
53 | |||
54 | #endif | ||
55 | |||
56 | #ifndef MM_INC | ||
57 | #define MM_INC | ||
58 | |||
59 | struct 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 | }; | ||
67 | typedef struct mem_block_t TMemBlock; | ||
68 | typedef struct mem_block_t *PMemBlock; | ||
69 | |||
70 | /* a heap is just the first block in a chain */ | ||
71 | typedef struct mem_block_t memHeap_t; | ||
72 | |||
73 | static __inline__ int mmBlockSize(PMemBlock b) | ||
74 | { | ||
75 | return b->size; | ||
76 | } | ||
77 | |||
78 | static __inline__ int mmOffset(PMemBlock b) | ||
79 | { | ||
80 | return b->ofs; | ||
81 | } | ||
82 | |||
83 | static __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 | */ | ||
92 | memHeap_t *via_mmInit(int ofs, int size); | ||
93 | |||
94 | PMemBlock 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 | */ | ||
102 | int 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 | |||
60 | static 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 }}; | ||
63 | static int via_num_pro_group_a = sizeof(via_pro_group_a_irqs)/sizeof(maskarray_t); | ||
64 | |||
65 | static maskarray_t via_unichrome_irqs[] = {}; | ||
66 | static int via_num_unichrome = sizeof(via_unichrome_irqs)/sizeof(maskarray_t); | ||
67 | |||
68 | |||
69 | static 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 | |||
76 | irqreturn_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 | |||
127 | static __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 | |||
139 | int 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 | |||
166 | static int | ||
167 | via_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 | |||
208 | void 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 | |||
250 | void 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 | |||
269 | void 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 | |||
288 | int 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 | |||
28 | static 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 | |||
76 | int 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 | |||
91 | int 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 | |||
32 | typedef 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 | |||
38 | static via_context_t global_ppriv[MAX_CONTEXT]; | ||
39 | |||
40 | static int via_agp_alloc(drm_via_mem_t * mem); | ||
41 | static int via_agp_free(drm_via_mem_t * mem); | ||
42 | static int via_fb_alloc(drm_via_mem_t * mem); | ||
43 | static int via_fb_free(drm_via_mem_t * mem); | ||
44 | |||
45 | static 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 | |||
59 | static 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 */ | ||
73 | static memHeap_t *AgpHeap = NULL; | ||
74 | |||
75 | int 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 */ | ||
90 | static memHeap_t *FBHeap = NULL; | ||
91 | |||
92 | int 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 | |||
105 | int 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 | |||
136 | int 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 | |||
193 | int 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 | |||
218 | static 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 | |||
255 | static 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 | |||
290 | int 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 | |||
312 | static 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 | |||
340 | static 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 | |||
27 | typedef struct { | ||
28 | unsigned int context; | ||
29 | unsigned int size; | ||
30 | unsigned long offset; | ||
31 | unsigned long free; | ||
32 | } drm_via_mm_t; | ||
33 | |||
34 | typedef 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 | |||
39 | typedef 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 | |||
49 | typedef 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 | |||
86 | static 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 | |||
114 | typedef struct{ | ||
115 | unsigned int code; | ||
116 | hazard_t hz; | ||
117 | } hz_init_t; | ||
118 | |||
119 | |||
120 | |||
121 | static 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 | |||
174 | static 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 | |||
232 | static 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 | |||
240 | static hazard_t table1[256]; | ||
241 | static hazard_t table2[256]; | ||
242 | static hazard_t table3[256]; | ||
243 | |||
244 | |||
245 | |||
246 | static __inline__ int | ||
247 | eat_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 | |||
262 | static __inline__ drm_map_t * | ||
263 | via_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 | |||
299 | static __inline__ int | ||
300 | finish_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 | |||
344 | static __inline__ int | ||
345 | investigate_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 | |||
496 | static __inline__ int | ||
497 | via_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 | |||
588 | static __inline__ verifier_state_t | ||
589 | via_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 | |||
681 | static __inline__ verifier_state_t | ||
682 | via_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 | |||
728 | static __inline__ int | ||
729 | verify_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 | |||
747 | static __inline__ int | ||
748 | verify_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 | |||
767 | static __inline__ verifier_state_t | ||
768 | via_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 | |||
799 | static __inline__ verifier_state_t | ||
800 | via_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 | |||
815 | static __inline__ verifier_state_t | ||
816 | via_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 | |||
848 | static __inline__ verifier_state_t | ||
849 | via_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 | |||
866 | static __inline__ verifier_state_t | ||
867 | via_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 | |||
904 | static __inline__ verifier_state_t | ||
905 | via_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 | |||
925 | int | ||
926 | via_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 | |||
988 | int | ||
989 | via_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 | |||
1041 | static void | ||
1042 | setup_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 | |||
1055 | void | ||
1056 | via_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 | |||
29 | typedef enum{ | ||
30 | no_sequence = 0, | ||
31 | z_address, | ||
32 | dest_address, | ||
33 | tex_address | ||
34 | }drm_via_sequence_t; | ||
35 | |||
36 | |||
37 | |||
38 | typedef 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 | |||
58 | extern 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 | |||
32 | void | ||
33 | via_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 | |||
45 | void | ||
46 | via_cleanup_futex(drm_via_private_t *dev_priv) | ||
47 | { | ||
48 | } | ||
49 | |||
50 | void | ||
51 | via_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 | |||
67 | int | ||
68 | via_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 | ||
170 | static unsigned int ds1620_in(int cmd, int bits) | 169 | static 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 | ||
147 | static struct class_simple *dsp56k_class; | 147 | static struct class *dsp56k_class; |
148 | 148 | ||
149 | static int dsp56k_reset(void) | 149 | static 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 | ||
528 | out_class: | 528 | out_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); |
531 | out_chrdev: | 531 | out_chrdev: |
532 | unregister_chrdev(DSP56K_MAJOR, "dsp56k"); | 532 | unregister_chrdev(DSP56K_MAJOR, "dsp56k"); |
533 | out: | 533 | out: |
@@ -537,8 +537,8 @@ module_init(dsp56k_init_driver); | |||
537 | 537 | ||
538 | static void __exit dsp56k_cleanup_driver(void) | 538 | static 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 | ||
102 | static struct class_simple *zft_class; | 102 | static 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 | ||
64 | static struct tty_driver *hvc_driver; | ||
65 | #ifdef CONFIG_MAGIC_SYSRQ | ||
66 | static 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 | ||
69 | static struct tty_driver *hvc_driver; | ||
70 | static struct task_struct *hvc_task; | ||
71 | |||
72 | /* Picks up late kicks after list walk but before schedule() */ | ||
73 | static int hvc_kicked; | ||
74 | |||
75 | #ifdef CONFIG_MAGIC_SYSRQ | ||
76 | static int sysrq_pressed; | ||
77 | #endif | ||
78 | |||
74 | struct hvc_struct { | 79 | struct 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); | |||
97 | static DEFINE_SPINLOCK(hvc_structs_lock); | 102 | static 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 | */ | ||
109 | static 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 | */ | ||
116 | struct 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 | */ |
105 | static uint32_t vtermnos[MAX_NR_HVC_CONSOLES]; | 146 | static struct hv_ops *cons_ops[MAX_NR_HVC_CONSOLES]; |
147 | static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] = | ||
148 | {[0 ... MAX_NR_HVC_CONSOLES - 1] = -1}; | ||
106 | 149 | ||
107 | /* Used for accounting purposes */ | 150 | /* |
108 | static int num_vterms = 0; | 151 | * Console APIs, NOT TTY. These APIs are available immediately when |
152 | * hvc_console_setup() finds adapters. | ||
153 | */ | ||
109 | 154 | ||
110 | static struct task_struct *hvc_task; | 155 | void 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 | |||
193 | static 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 | |||
202 | static 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 | |||
213 | struct 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 | */ |
116 | static int hvc_count = -1; | 237 | static int __init hvc_console_init(void) |
238 | { | ||
239 | register_console(&hvc_con_driver); | ||
240 | return 0; | ||
241 | } | ||
242 | console_initcall(hvc_console_init); | ||
117 | 243 | ||
118 | /* Picks up late kicks after list walk but before schedule() */ | 244 | /* |
119 | static 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 | */ | ||
250 | int 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 | } | ||
283 | EXPORT_SYMBOL(hvc_instantiate); | ||
120 | 284 | ||
121 | /* Wake the sleeping khvcd */ | 285 | /* Wake the sleeping khvcd */ |
122 | static void hvc_kick(void) | 286 | static 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 | ||
292 | static 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 | */ |
132 | static irqreturn_t hvc_handle_interrupt(int irq, void *dev_instance, struct pt_regs *regs) | 298 | static 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 | */ | ||
148 | struct 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 | ||
580 | char hvc_driver_name[] = "hvc_console"; | ||
581 | |||
582 | static struct vio_device_id hvc_driver_table[] __devinitdata= { | ||
583 | {"serial", "hvterm1"}, | ||
584 | { NULL, } | ||
585 | }; | ||
586 | MODULE_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. */ |
589 | static void destroy_hvc_struct(struct kobject *kobj) | 723 | static 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 | ||
609 | static int __devinit hvc_probe( | 743 | struct 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 | } |
784 | EXPORT_SYMBOL(hvc_alloc); | ||
640 | 785 | ||
641 | static int __devexit hvc_remove(struct vio_dev *dev) | 786 | int __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 | 820 | EXPORT_SYMBOL(hvc_remove); | |
677 | static 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. */ |
686 | int __init hvc_init(void) | 824 | int __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 | } |
856 | module_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 | */ | ||
727 | static void __exit hvc_exit(void) | 861 | static 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 | */ | ||
747 | int 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 | |||
759 | void 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 | |||
797 | static struct tty_driver *hvc_console_device(struct console *c, int *index) | ||
798 | { | ||
799 | *index = c->index; | ||
800 | return hvc_driver; | ||
801 | } | ||
802 | |||
803 | static int __init hvc_console_setup(struct console *co, char *options) | ||
804 | { | ||
805 | return 0; | ||
806 | } | ||
807 | |||
808 | struct 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. */ | ||
818 | static 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 | } | ||
828 | console_initcall(hvc_console_init); | ||
829 | |||
830 | module_init(hvc_init); | ||
831 | module_exit(hvc_exit); | 870 | module_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 | |||
38 | char hvc_driver_name[] = "hvc_console"; | ||
39 | |||
40 | static struct vio_device_id hvc_driver_table[] __devinitdata = { | ||
41 | {"serial", "hvterm1"}, | ||
42 | { NULL, } | ||
43 | }; | ||
44 | MODULE_DEVICE_TABLE(vio, hvc_driver_table); | ||
45 | |||
46 | static 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 | |||
68 | static struct hv_ops hvc_get_put_ops = { | ||
69 | .get_chars = filtered_get_chars, | ||
70 | .put_chars = hvc_put_chars, | ||
71 | }; | ||
72 | |||
73 | static 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 | |||
90 | static 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 | |||
97 | static 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 | |||
107 | static 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 | } | ||
116 | module_init(hvc_vio_init); /* after drivers/char/hvc_console.c */ | ||
117 | |||
118 | static void hvc_vio_exit(void) | ||
119 | { | ||
120 | vio_unregister_driver(&hvc_vio_driver); | ||
121 | } | ||
122 | module_exit(hvc_vio_exit); | ||
123 | |||
124 | /* the device tree order defines our numbering */ | ||
125 | static 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 | } | ||
152 | console_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 | ||
1469 | static ssize_t hvcs_partner_vtys_show(struct device *dev, char *buf) | 1469 | static 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 | } |
1481 | static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL); | 1481 | static DEVICE_ATTR(partner_vtys, S_IRUGO, hvcs_partner_vtys_show, NULL); |
1482 | 1482 | ||
1483 | static ssize_t hvcs_partner_clcs_show(struct device *dev, char *buf) | 1483 | static 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 | } |
1495 | static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL); | 1495 | static DEVICE_ATTR(partner_clcs, S_IRUGO, hvcs_partner_clcs_show, NULL); |
1496 | 1496 | ||
1497 | static ssize_t hvcs_current_vty_store(struct device *dev, const char * buf, | 1497 | static 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 | ||
1508 | static ssize_t hvcs_current_vty_show(struct device *dev, char *buf) | 1508 | static 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) | |||
1521 | static DEVICE_ATTR(current_vty, | 1521 | static 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 | ||
1524 | static ssize_t hvcs_vterm_state_store(struct device *dev, const char *buf, | 1524 | static 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 | ||
1562 | static ssize_t hvcs_vterm_state_show(struct device *dev, char *buf) | 1562 | static 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) | |||
1574 | static DEVICE_ATTR(vterm_state, S_IRUGO | S_IWUSR, | 1574 | static 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 | ||
1577 | static ssize_t hvcs_index_show(struct device *dev, char *buf) | 1577 | static 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 */ | ||
295 | static int hvsi_read(struct hvsi_struct *hp, char *buf, int count) | 294 | static 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 | ||
305 | static void hvsi_recv_control(struct hvsi_struct *hp, uint8_t *packet, | 303 | static 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" | 57 | static char bios_version[4]; |
56 | |||
57 | static char *supported_models[] = { | ||
58 | "Inspiron", | ||
59 | "Latitude", | ||
60 | NULL | ||
61 | }; | ||
62 | |||
63 | static char system_vendor[48] = "?"; | ||
64 | static char product_name [48] = "?"; | ||
65 | static char bios_version [4] = "?"; | ||
66 | static char serial_number[16] = "?"; | ||
67 | 58 | ||
68 | MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)"); | 59 | MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)"); |
69 | MODULE_DESCRIPTION("Driver for accessing SMM BIOS on Dell laptops"); | 60 | MODULE_DESCRIPTION("Driver for accessing SMM BIOS on Dell laptops"); |
@@ -73,6 +64,10 @@ static int force; | |||
73 | module_param(force, bool, 0); | 64 | module_param(force, bool, 0); |
74 | MODULE_PARM_DESC(force, "Force loading without checking for supported models"); | 65 | MODULE_PARM_DESC(force, "Force loading without checking for supported models"); |
75 | 66 | ||
67 | static int ignore_dmi; | ||
68 | module_param(ignore_dmi, bool, 0); | ||
69 | MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match"); | ||
70 | |||
76 | static int restricted; | 71 | static int restricted; |
77 | module_param(restricted, bool, 0); | 72 | module_param(restricted, bool, 0); |
78 | MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set"); | 73 | MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set"); |
@@ -81,69 +76,69 @@ static int power_status; | |||
81 | module_param(power_status, bool, 0600); | 76 | module_param(power_status, bool, 0600); |
82 | MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k"); | 77 | MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k"); |
83 | 78 | ||
84 | static ssize_t i8k_read(struct file *, char __user *, size_t, loff_t *); | 79 | static int i8k_open_fs(struct inode *inode, struct file *file); |
85 | static int i8k_ioctl(struct inode *, struct file *, unsigned int, | 80 | static int i8k_ioctl(struct inode *, struct file *, unsigned int, |
86 | unsigned long); | 81 | unsigned long); |
87 | 82 | ||
88 | static struct file_operations i8k_fops = { | 83 | static 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 | |||
91 | struct 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 | ||
93 | typedef struct { | 100 | static 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 | |||
102 | typedef 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 | */ |
111 | static int i8k_smm(SMMRegisters *regs) | 108 | static 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 | */ |
153 | static int i8k_get_bios_version(void) | 148 | static 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(®s)) < 0) { | ||
160 | return rc; | ||
161 | } | ||
162 | |||
163 | return regs.eax; | ||
164 | } | ||
165 | 151 | ||
166 | /* | 152 | return i8k_smm(®s) ? : regs.eax; |
167 | * Read the machine id. | ||
168 | */ | ||
169 | static 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 | */ |
178 | static int i8k_get_fn_status(void) | 158 | static 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(®s)) < 0) |
184 | if ((rc=i8k_smm(®s)) < 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 | */ |
203 | static int i8k_get_power_status(void) | 181 | static 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(®s)) < 0) |
209 | if ((rc=i8k_smm(®s)) < 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 | */ |
224 | static int i8k_get_fan_status(int fan) | 195 | static 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(®s)) < 0) { | ||
232 | return rc; | ||
233 | } | ||
234 | 198 | ||
235 | return (regs.eax & 0xff); | 199 | regs.ebx = fan & 0xff; |
200 | return i8k_smm(®s) ? : regs.eax & 0xff; | ||
236 | } | 201 | } |
237 | 202 | ||
238 | /* | 203 | /* |
@@ -240,16 +205,10 @@ static int i8k_get_fan_status(int fan) | |||
240 | */ | 205 | */ |
241 | static int i8k_get_fan_speed(int fan) | 206 | static 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(®s) ? : (regs.eax & 0xffff) * I8K_FAN_MULT; |
248 | if ((rc=i8k_smm(®s)) < 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 | */ |
258 | static int i8k_set_fan(int fan, int speed) | 217 | static 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(®s)) < 0) { | ||
268 | return rc; | ||
269 | } | ||
270 | 223 | ||
271 | return (i8k_get_fan_status(fan)); | 224 | return i8k_smm(®s) ? : i8k_get_fan_status(fan); |
272 | } | 225 | } |
273 | 226 | ||
274 | /* | 227 | /* |
275 | * Read the cpu temperature. | 228 | * Read the cpu temperature. |
276 | */ | 229 | */ |
277 | static int i8k_get_cpu_temp(void) | 230 | static 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(®s)) < 0) | ||
241 | return rc; | ||
286 | 242 | ||
287 | regs.eax = I8K_SMM_GET_TEMP; | 243 | temp = regs.eax & 0xff; |
288 | if ((rc=i8k_smm(®s)) < 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 | ||
312 | static int i8k_get_dell_signature(void) | 264 | static 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(®s)) < 0) |
318 | if ((rc=i8k_smm(®s)) < 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 | ||
329 | static int i8k_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, | 275 | static 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; |
421 | static 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 | ||
467 | static 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 | ||
493 | static 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 | */ | ||
518 | static 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 | ||
537 | static void __init dmi_decode(DMIHeader *dmi) | 363 | /* |
364 | * Print the information for /proc/i8k. | ||
365 | */ | ||
366 | static 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 | ||
579 | static 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 | ||
622 | static int __init dmi_iterate(void (*decode)(DMIHeader *)) | 405 | static 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 | */ | ||
659 | static 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; | 410 | static 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 | */ |
689 | static int __init i8k_probe(void) | 445 | static 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 | 504 | static int __init i8k_init(void) |
747 | static | ||
748 | #endif | ||
749 | int __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? */ |
774 | int 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 | ||
779 | void cleanup_module(void) | 527 | static 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 */ | 532 | module_init(i8k_init); |
533 | module_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 |
100 | static 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 | ||
165 | cmdSyntaxPtr | 166 | cmdSyntaxPtr |
166 | i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag) | 167 | i2cmdUnixFlags(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 | //****************************************************************************** |
190 | cmdSyntaxPtr | 192 | static cmdSyntaxPtr |
191 | i2cmdBaudDef(int which, unsigned short rate) | 193 | i2cmdBaudDef(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 | // | ||
74 | extern cmdSyntaxPtr i2cmdUnixFlags(USHORT iflag,USHORT cflag,USHORT lflag); | ||
75 | extern 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]; | |||
302 | static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0}; | 302 | static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0}; |
303 | 303 | ||
304 | /* for sysfs class support */ | 304 | /* for sysfs class support */ |
305 | static struct class_simple *ip2_class; | 305 | static 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 | ||
800 | out_class: | 800 | out_class: |
801 | class_simple_destroy(ip2_class); | 801 | class_destroy(ip2_class); |
802 | out_chrdev: | 802 | out_chrdev: |
803 | unregister_chrdev(IP2_IPL_MAJOR, "ip2"); | 803 | unregister_chrdev(IP2_IPL_MAJOR, "ip2"); |
804 | out: | 804 | out: |
@@ -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 | ||
2695 | do_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 | |||
2704 | service_it: | 2694 | service_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 | |||
520 | struct compat_ipmi_msg { | ||
521 | u8 netfn; | ||
522 | u8 cmd; | ||
523 | u16 data_len; | ||
524 | compat_uptr_t data; | ||
525 | }; | ||
526 | |||
527 | struct 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 | |||
534 | struct 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 | |||
542 | struct 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 | */ | ||
551 | static 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 | |||
566 | static 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 | |||
577 | static 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 | |||
593 | static 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 | |||
604 | static 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 | |||
620 | static 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 | */ | ||
635 | static 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 | ||
504 | static struct file_operations ipmi_fops = { | 697 | static 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 | ||
523 | static struct class_simple *ipmi_class; | 719 | static struct class *ipmi_class; |
524 | 720 | ||
525 | static void ipmi_new_smi(int if_num) | 721 | static 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 | ||
535 | static void ipmi_smi_gone(int if_num) | 731 | static 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 | ||
589 | static __exit void cleanup_ipmi(void) | 785 | static __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 | ||
55 | static int initialized = 0; | 55 | static int initialized = 0; |
56 | 56 | ||
57 | static struct proc_dir_entry *proc_ipmi_root = NULL; | 57 | #ifdef CONFIG_PROC_FS |
58 | struct 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 | ||
127 | struct ipmi_proc_entry | 130 | struct 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 | ||
1538 | static void remove_proc_entries(ipmi_smi_t smi) | 1551 | static 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 | ||
1553 | static int | 1570 | static 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 | ||
2750 | static volatile int stop_operation = 0; | 2770 | static atomic_t stop_operation; |
2751 | static volatile int timer_stopped = 0; | ||
2752 | static unsigned int ticks_to_req_ev = IPMI_REQUEST_EV_TIME; | 2771 | static unsigned int ticks_to_req_ev = IPMI_REQUEST_EV_TIME; |
2753 | 2772 | ||
2754 | static void ipmi_timeout(unsigned long data) | 2773 | static 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); | |||
3177 | EXPORT_SYMBOL(ipmi_set_my_LUN); | 3194 | EXPORT_SYMBOL(ipmi_set_my_LUN); |
3178 | EXPORT_SYMBOL(ipmi_get_my_LUN); | 3195 | EXPORT_SYMBOL(ipmi_get_my_LUN); |
3179 | EXPORT_SYMBOL(ipmi_smi_add_proc_entry); | 3196 | EXPORT_SYMBOL(ipmi_smi_add_proc_entry); |
3197 | EXPORT_SYMBOL(proc_ipmi_root); | ||
3180 | EXPORT_SYMBOL(ipmi_user_set_run_to_completion); | 3198 | EXPORT_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? */ |
45 | extern void (*pm_power_off)(void); | 48 | extern 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 */ | ||
56 | static int poweroff_control = IPMI_CHASSIS_POWER_DOWN; | ||
57 | |||
58 | /* parameter definition to allow user to flag power cycle */ | ||
59 | module_param(poweroff_control, int, IPMI_CHASSIS_POWER_DOWN); | ||
60 | MODULE_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. */ |
48 | static unsigned int mfg_id; | 63 | static unsigned int mfg_id; |
49 | static unsigned int prod_id; | 64 | static unsigned int prod_id; |
@@ -75,10 +90,10 @@ static struct ipmi_recv_msg halt_recv_msg = | |||
75 | 90 | ||
76 | static void receive_handler(struct ipmi_recv_msg *recv_msg, void *handler_data) | 91 | static 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 | ||
84 | static struct ipmi_user_hndl ipmi_poweroff_handler = | 99 | static 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. */ |
110 | static int ipmi_request_in_rc_mode(ipmi_user_t user, | 125 | static 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 */ | ||
542 | static 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 */ | ||
550 | static 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 | */ |
515 | static int ipmi_poweroff_init (void) | 579 | static 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 | ||
1729 | inline static int dmi_checksum(u8 *buf) | 1729 | static 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 | 134 | static int nowayout = WATCHDOG_NOWAYOUT; |
135 | static int nowayout = 1; | ||
136 | #else | ||
137 | static int nowayout; | ||
138 | #endif | ||
139 | 135 | ||
140 | static ipmi_user_t watchdog_user = NULL; | 136 | static 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 | ||
1759 | static int __init register_ioregion(void) | 1759 | static 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 | ||
1774 | static void __exit unregister_ioregion(void) | 1774 | static 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 | ||
1806 | static int __init register_drivers(void) | 1806 | static 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 | ||
1837 | static void __exit unregister_drivers(void) | 1837 | static 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 | ||
1845 | static int __init register_isr(void) | 1845 | static 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 | ||
1886 | static int __init isicom_init(void) | 1886 | static 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 | ||
409 | static int stli_eisamempsize = sizeof(stli_eisamemprobeaddrs) / sizeof(unsigned long); | 409 | static int stli_eisamempsize = sizeof(stli_eisamemprobeaddrs) / sizeof(unsigned long); |
410 | int 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 | ||
795 | static struct class_simple *istallion_class; | 794 | static 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 @@ | |||
146 | static struct lp_struct lp_table[LP_NO]; | 146 | static struct lp_struct lp_table[LP_NO]; |
147 | 147 | ||
148 | static unsigned int lp_count = 0; | 148 | static unsigned int lp_count = 0; |
149 | static struct class_simple *lp_class; | 149 | static struct class *lp_class; |
150 | 150 | ||
151 | #ifdef CONFIG_LP_CONSOLE | 151 | #ifdef CONFIG_LP_CONSOLE |
152 | static struct parport *console_registered; // initially NULL | 152 | static 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 | ||
932 | out_class: | 932 | out_class: |
933 | class_simple_destroy(lp_class); | 933 | class_destroy(lp_class); |
934 | out_devfs: | 934 | out_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 | ||
702 | static ssize_t show_algo(struct device *dev, char *buf) | 702 | static 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 | ||
718 | static ssize_t store_algo(struct device *dev, const char *buf, size_t count) | 718 | static 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 | ||
259 | static int mmap_kmem(struct file * file, struct vm_area_struct * vma) | 262 | static 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 | */ | ||
287 | static 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 | |||
276 | extern long vread(char *buf, char *addr, unsigned long count); | 317 | extern long vread(char *buf, char *addr, unsigned long count); |
277 | extern long vwrite(char *buf, char *addr, unsigned long count); | 318 | extern 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)) |
488 | static ssize_t read_port(struct file * file, char __user * buf, | 529 | static 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 | ||
725 | static struct file_operations mem_fops = { | 767 | static 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)) |
748 | static struct file_operations port_fops = { | 790 | static 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 | ||
816 | static struct file_operations oldmem_fops = { | ||
817 | .read = read_oldmem, | ||
818 | .open = open_oldmem, | ||
819 | }; | ||
820 | #endif | ||
821 | |||
773 | static ssize_t kmsg_write(struct file * file, const char __user * buf, | 822 | static 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 | ||
859 | static struct class_simple *mem_class; | 916 | static struct class *mem_class; |
860 | 917 | ||
861 | static int __init chr_dev_init(void) | 918 | static 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]; | |||
66 | extern int rtc_DP8570A_init(void); | 66 | extern int rtc_DP8570A_init(void); |
67 | extern int rtc_MK48T08_init(void); | 67 | extern int rtc_MK48T08_init(void); |
68 | extern int pmu_device_init(void); | 68 | extern int pmu_device_init(void); |
69 | extern int tosh_init(void); | ||
70 | extern int i8k_init(void); | ||
71 | 69 | ||
72 | #ifdef CONFIG_PROC_FS | 70 | #ifdef CONFIG_PROC_FS |
73 | static void *misc_seq_start(struct seq_file *seq, loff_t *pos) | 71 | static 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 | */ |
183 | static struct class_simple *misc_class; | 181 | static struct class *misc_class; |
184 | 182 | ||
185 | static struct file_operations misc_fops = { | 183 | static 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 | ||
110 | void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex, | 110 | static 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 | ||
144 | unsigned char dsp3780I_ReadGenCfg(unsigned short usDspBaseIO, | 145 | unsigned 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 | ||
171 | int dsp3780I_EnableDSP(DSP_3780I_CONFIG_SETTINGS * pSettings, | 173 | int 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); |
339 | void dsp3780I_WriteMsaCfg(unsigned short usDspBaseIO, | 339 | void dsp3780I_WriteMsaCfg(unsigned short usDspBaseIO, |
340 | unsigned long ulMsaAddr, unsigned short usValue); | 340 | unsigned long ulMsaAddr, unsigned short usValue); |
341 | void dsp3780I_WriteGenCfg(unsigned short usDspBaseIO, unsigned uIndex, | ||
342 | unsigned char ucValue); | ||
343 | unsigned char dsp3780I_ReadGenCfg(unsigned short usDspBaseIO, | ||
344 | unsigned uIndex); | ||
345 | int dsp3780I_GetIPCSource(unsigned short usDspBaseIO, | 341 | int 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) \ |
475 | static ssize_t mwave_show_##attr_name(struct device *dev, char *buf) \ | 475 | static 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) | |||
292 | int tp3780I_EnableDSP(THINKPAD_BD_DATA * pBDData) | 286 | int 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 | ||
412 | exit_cleanup: | 404 | exit_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 = | |||
960 | static void __exit n_hdlc_exit(void) | 960 | static 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 | ||
214 | void | 214 | static 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 | ||
220 | void | 221 | void |
221 | nvram_set_checksum(void) | 222 | nvram_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); | |||
921 | EXPORT_SYMBOL(nvram_write_byte); | 923 | EXPORT_SYMBOL(nvram_write_byte); |
922 | EXPORT_SYMBOL(__nvram_check_checksum); | 924 | EXPORT_SYMBOL(__nvram_check_checksum); |
923 | EXPORT_SYMBOL(nvram_check_checksum); | 925 | EXPORT_SYMBOL(nvram_check_checksum); |
924 | EXPORT_SYMBOL(__nvram_set_checksum); | ||
925 | EXPORT_SYMBOL(nvram_set_checksum); | ||
926 | MODULE_ALIAS_MISCDEV(NVRAM_MINOR); | 926 | MODULE_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 | ||
3078 | static struct pcmcia_device_id mgslpc_ids[] = { | ||
3079 | PCMCIA_DEVICE_MANF_CARD(0x02c5, 0x0050), | ||
3080 | PCMCIA_DEVICE_NULL | ||
3081 | }; | ||
3082 | MODULE_DEVICE_TABLE(pcmcia, mgslpc_ids); | ||
3083 | |||
3084 | static struct pcmcia_driver mgslpc_driver = { | 3084 | static 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 | ||
3093 | static struct tty_operations mgslpc_ops = { | 3095 | static 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 | ||
740 | static struct class_simple *ppdev_class; | 740 | static struct class *ppdev_class; |
741 | 741 | ||
742 | static struct file_operations pp_fops = { | 742 | static 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 | ||
753 | static void pp_attach(struct parport *port) | 753 | static 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 | ||
759 | static void pp_detach(struct parport *port) | 759 | static 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 | ||
764 | static struct parport_driver pp_driver = { | 764 | static 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); |
802 | out_chrdev: | 802 | out_chrdev: |
803 | unregister_chrdev(PP_MAJOR, CHRDEV); | 803 | unregister_chrdev(PP_MAJOR, CHRDEV); |
804 | out: | 804 | out: |
@@ -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 | ||
274 | static int trickle_thresh = INPUT_POOL_WORDS * 28; | 274 | static int trickle_thresh __read_mostly = INPUT_POOL_WORDS * 28; |
275 | 275 | ||
276 | static DEFINE_PER_CPU(int, trickle_count) = 0; | 276 | static 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 | ||
30 | static struct class_simple *raw_class; | 30 | static struct class *raw_class; |
31 | static struct raw_device_data raw_devices[MAX_RAW_MINORS]; | 31 | static struct raw_device_data raw_devices[MAX_RAW_MINORS]; |
32 | static DECLARE_MUTEX(raw_mutex); | 32 | static DECLARE_MUTEX(raw_mutex); |
33 | static struct file_operations raw_ctl_fops; /* forward declaration */ | 33 | static struct file_operations raw_ctl_fops; /* forward declaration */ |
@@ -127,8 +127,8 @@ raw_ioctl(struct inode *inode, struct file *filp, | |||
127 | 127 | ||
128 | static void bind_device(struct raw_config_request *rq) | 128 | static 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); | |||
147 | extern int rio_pcicopy(char *src, char *dst, int n); | 147 | extern int rio_pcicopy(char *src, char *dst, int n); |
148 | extern int rio_minor (struct tty_struct *tty); | 148 | extern int rio_minor (struct tty_struct *tty); |
149 | extern int rio_ismodem (struct tty_struct *tty); | 149 | extern int rio_ismodem (struct tty_struct *tty); |
150 | extern void rio_udelay (int usecs); | ||
151 | 150 | ||
152 | extern void rio_start_card_running (struct Host * HostP); | 151 | extern 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 | ||
357 | void rio_udelay (int usecs) | ||
358 | { | ||
359 | udelay (usecs); | ||
360 | } | ||
361 | |||
362 | static int rio_set_real_termios (void *ptr) | 357 | static 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 | ||
164 | static 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 | |||
185 | static 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 | |||
201 | static 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 | |||
212 | static Byte_t sBitMapClrTbl[8] = { | ||
213 | 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f | ||
214 | }; | ||
215 | |||
216 | static Byte_t sBitMapSetTbl[8] = { | ||
217 | 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 | ||
218 | }; | ||
219 | |||
220 | static 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); | |||
177 | static unsigned char GetLineNumber(int ctrl, int aiop, int ch); | 235 | static unsigned char GetLineNumber(int ctrl, int aiop, int ch); |
178 | static unsigned char SetLineNumber(int ctrl, int aiop, int ch); | 236 | static unsigned char SetLineNumber(int ctrl, int aiop, int ch); |
179 | static void rp_start(struct tty_struct *tty); | 237 | static void rp_start(struct tty_struct *tty); |
238 | static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum, | ||
239 | int ChanNum); | ||
240 | static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode); | ||
241 | static void sFlushRxFIFO(CHANNEL_T * ChP); | ||
242 | static void sFlushTxFIFO(CHANNEL_T * ChP); | ||
243 | static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags); | ||
244 | static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags); | ||
245 | static void sModemReset(CONTROLLER_T * CtlP, int chan, int on); | ||
246 | static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on); | ||
247 | static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data); | ||
248 | static 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); | ||
253 | static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO, | ||
254 | ByteIO_t * AiopIOList, int AiopIOListSize, | ||
255 | int IRQNum, Byte_t Frequency, int PeriodicOnly); | ||
256 | static int sReadAiopID(ByteIO_t io); | ||
257 | static int sReadAiopNumChan(WordIO_t io); | ||
180 | 258 | ||
181 | #ifdef MODULE | 259 | #ifdef MODULE |
182 | MODULE_AUTHOR("Theodore Ts'o"); | 260 | MODULE_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); |
440 | done: | ||
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) | 1880 | static __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 | |||
2464 | static 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 | |||
2485 | static 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 | |||
2501 | CONTROLLER_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 | |||
2512 | Byte_t sBitMapClrTbl[8] = { | ||
2513 | 0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f | ||
2514 | }; | ||
2515 | |||
2516 | Byte_t sBitMapSetTbl[8] = { | ||
2517 | 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80 | ||
2518 | }; | ||
2519 | |||
2520 | int sClockPrescale = 0x14; | ||
2521 | |||
2522 | /*************************************************************************** | 2535 | /*************************************************************************** |
2523 | Function: sInitController | 2536 | Function: sInitController |
2524 | Purpose: Initialization of controller global registers and controller | 2537 | Purpose: 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. |
2563 | Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller | 2576 | Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller |
2564 | initialization failed. | 2577 | initialization failed. |
2565 | 2578 | ||
2566 | Comments: | 2579 | Comments: |
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 | */ |
2592 | int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO, | 2605 | static 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. |
2696 | Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller | 2709 | Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller |
2697 | initialization failed. | 2710 | initialization failed. |
2698 | 2711 | ||
2699 | Comments: | 2712 | Comments: |
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 | */ |
2725 | int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum, | 2738 | static 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 | |||
2784 | Warnings: No context switches are allowed while executing this function. | 2797 | Warnings: No context switches are allowed while executing this function. |
2785 | 2798 | ||
2786 | */ | 2799 | */ |
2787 | int sReadAiopID(ByteIO_t io) | 2800 | static 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. |
2811 | Warnings: No context switches are allowed while executing this function. | 2824 | Warnings: No context switches are allowed while executing this function. |
2812 | */ | 2825 | */ |
2813 | int sReadAiopNumChan(WordIO_t io) | 2826 | static 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 |
2837 | Return: int: TRUE if initialization succeeded, FALSE if it fails because channel | 2850 | Return: 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. |
2839 | Comments: This function must be called before a channel can be used. | 2852 | Comments: This function must be called before a channel can be used. |
2840 | Warnings: No range checking on any of the parameters is done. | 2853 | Warnings: 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 | */ |
2844 | int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum, | 2857 | static 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 | */ |
2992 | void sStopRxProcessor(CHANNEL_T * ChP) | 3005 | static 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. |
3015 | Warnings: No context switches are allowed while executing this function. | 3028 | Warnings: No context switches are allowed while executing this function. |
3016 | */ | 3029 | */ |
3017 | void sFlushRxFIFO(CHANNEL_T * ChP) | 3030 | static 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. |
3057 | Warnings: No context switches are allowed while executing this function. | 3070 | Warnings: No context switches are allowed while executing this function. |
3058 | */ | 3071 | */ |
3059 | void sFlushTxFIFO(CHANNEL_T * ChP) | 3072 | static 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 | ||
3097 | Warnings: No context switches are allowed while executing this function. | 3110 | Warnings: No context switches are allowed while executing this function. |
3098 | */ | 3111 | */ |
3099 | int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data) | 3112 | static 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 | */ |
3161 | void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags) | 3174 | static 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 | */ |
3205 | void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags) | 3218 | static 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 | ||
3221 | void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode) | 3234 | static 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 | */ |
3230 | void sModemReset(CONTROLLER_T * CtlP, int chan, int on) | 3243 | static 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 | */ |
3255 | void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on) | 3268 | static 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 | ||
1133 | int 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 | |||
1140 | int 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 | |||
1150 | int sReadAiopID(ByteIO_t io); | ||
1151 | int sReadAiopNumChan(WordIO_t io); | ||
1152 | int sInitChan(CONTROLLER_T * CtlP, | ||
1153 | CHANNEL_T * ChP, int AiopNum, int ChanNum); | ||
1154 | Byte_t sGetRxErrStatus(CHANNEL_T * ChP); | ||
1155 | void sStopRxProcessor(CHANNEL_T * ChP); | ||
1156 | void sStopSWInFlowCtl(CHANNEL_T * ChP); | ||
1157 | void sFlushRxFIFO(CHANNEL_T * ChP); | ||
1158 | void sFlushTxFIFO(CHANNEL_T * ChP); | ||
1159 | int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data); | ||
1160 | void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags); | ||
1161 | void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags); | ||
1162 | void sModemReset(CONTROLLER_T * CtlP, int chan, int on); | ||
1163 | void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on); | ||
1164 | void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode); | ||
1165 | |||
1166 | extern Byte_t R[RDATASIZE]; | ||
1167 | extern CONTROLLER_T sController[CTL_SIZE]; | ||
1168 | extern Byte_t sIRQMap[16]; | ||
1169 | extern Byte_t sBitMapClrTbl[8]; | ||
1170 | extern Byte_t sBitMapSetTbl[8]; | ||
1171 | extern 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 | ||
360 | static 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 | ||
442 | struct sonypi_keypress { | ||
443 | struct input_dev *dev; | ||
444 | int key; | ||
445 | }; | ||
446 | |||
442 | static struct sonypi_device { | 447 | static 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 | ||
711 | static void input_keyrelease(void *data) | 716 | static 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 | |||
728 | static 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); |
1314 | out_infifo: | 1301 | out_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); | ||
1317 | out_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); | ||
1320 | out_inkmallocinput1: | ||
1321 | free_irq(sonypi_device.irq, sonypi_irq); | 1304 | free_irq(sonypi_device.irq, sonypi_irq); |
1322 | out_reqirq: | 1305 | out_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 | ||
722 | static struct class_simple *stallion_class; | 722 | static 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 */ | ||
100 | static void sysrq_handle_crashdump(int key, struct pt_regs *pt_regs, | ||
101 | struct tty_struct *tty) | ||
102 | { | ||
103 | crash_kexec(pt_regs); | ||
104 | } | ||
105 | static 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 */ |
98 | static void sysrq_handle_reboot(int key, struct pt_regs *pt_regs, | 114 | static 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 | ||
105 | static struct sysrq_key_op sysrq_reboot_op = { | 121 | static struct sysrq_key_op sysrq_reboot_op = { |
@@ -212,7 +228,7 @@ static struct sysrq_key_op sysrq_term_op = { | |||
212 | 228 | ||
213 | static void moom_callback(void *ignored) | 229 | static void moom_callback(void *ignored) |
214 | { | 230 | { |
215 | out_of_memory(GFP_KERNEL); | 231 | out_of_memory(GFP_KERNEL, 0); |
216 | } | 232 | } |
217 | 233 | ||
218 | static DECLARE_WORK(moom_work, moom_callback, NULL); | 234 | static 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 | ||
28 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>"); | 30 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>"); |
29 | MODULE_DESCRIPTION("TANBAC TB0219 base board driver"); | 31 | MODULE_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 | ||
271 | static 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 | |||
269 | static int tb0219_probe(struct device *dev) | 286 | static 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 */ | |||
90 | static unsigned int tp_count; /* tipar count */ | 90 | static unsigned int tp_count; /* tipar count */ |
91 | static unsigned long opened; /* opened devices */ | 91 | static unsigned long opened; /* opened devices */ |
92 | 92 | ||
93 | static struct class_simple *tipar_class; | 93 | static 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 = { | |||
396 | static int __init | 396 | static int __init |
397 | tipar_setup(char *str) | 397 | tipar_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 | ||
460 | out_class: | 460 | out_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); |
463 | out: | 463 | out: |
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 | ||
76 | static int tosh_id = 0x0000; | 76 | MODULE_LICENSE("GPL"); |
77 | static int tosh_bios = 0x0000; | 77 | MODULE_AUTHOR("Jonathan Buzzard <jonathan@buzzard.org.uk>"); |
78 | static int tosh_date = 0x0000; | 78 | MODULE_DESCRIPTION("Toshiba laptop SMM driver"); |
79 | static int tosh_sci = 0x0000; | 79 | MODULE_SUPPORTED_DEVICE("toshiba"); |
80 | static int tosh_fan = 0; | ||
81 | |||
82 | static int tosh_fn = 0; | ||
83 | 80 | ||
84 | module_param(tosh_fn, int, 0); | 81 | static int tosh_fn; |
82 | module_param_named(fn, tosh_fn, int, 0); | ||
83 | MODULE_PARM_DESC(fn, "User specified Fn key detection port"); | ||
85 | 84 | ||
85 | static int tosh_id; | ||
86 | static int tosh_bios; | ||
87 | static int tosh_date; | ||
88 | static int tosh_sci; | ||
89 | static int tosh_fan; | ||
86 | 90 | ||
87 | static int tosh_ioctl(struct inode *, struct file *, unsigned int, | 91 | static 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 | ||
478 | int __init tosh_init(void) | 482 | static 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 | 512 | static void __exit toshiba_exit(void) |
510 | int init_module(void) | ||
511 | { | ||
512 | return tosh_init(); | ||
513 | } | ||
514 | |||
515 | void 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 | ||
527 | MODULE_LICENSE("GPL"); | 518 | module_init(toshiba_init); |
528 | MODULE_PARM_DESC(tosh_fn, "User specified Fn key detection port"); | 519 | module_exit(toshiba_exit); |
529 | MODULE_AUTHOR("Jonathan Buzzard <jonathan@buzzard.org.uk>"); | ||
530 | MODULE_DESCRIPTION("Toshiba laptop SMM driver"); | ||
531 | MODULE_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 | ||
21 | config TCG_NSC | 23 | config 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 | ||
40 | config 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 | |||
38 | endmenu | 52 | endmenu |
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 @@ | |||
4 | obj-$(CONFIG_TCG_TPM) += tpm.o | 4 | obj-$(CONFIG_TCG_TPM) += tpm.o |
5 | obj-$(CONFIG_TCG_NSC) += tpm_nsc.o | 5 | obj-$(CONFIG_TCG_NSC) += tpm_nsc.o |
6 | obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o | 6 | obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o |
7 | 7 | obj-$(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 */ | 31 | enum 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 | ||
41 | static LIST_HEAD(tpm_chip_list); | 38 | static LIST_HEAD(tpm_chip_list); |
42 | static DEFINE_SPINLOCK(driver_lock); | 39 | static DEFINE_SPINLOCK(driver_lock); |
43 | static int dev_mask[32]; | 40 | static int dev_mask[TPM_NUM_MASK_ENTRIES]; |
44 | 41 | ||
45 | static void user_reader_timeout(unsigned long ptr) | 42 | static 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 | ||
55 | void tpm_time_expired(unsigned long ptr) | ||
56 | { | ||
57 | int *exp = (int *) ptr; | ||
58 | *exp = 1; | ||
59 | } | ||
60 | |||
61 | EXPORT_SYMBOL_GPL(tpm_time_expired); | ||
62 | |||
63 | /* | ||
64 | * Initialize the LPC bus and enable the TPM ports | ||
65 | */ | ||
66 | int 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 | |||
127 | EXPORT_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 | */ |
132 | static ssize_t tpm_transmit(struct tpm_chip *chip, const char *buf, | 55 | static 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 | ||
187 | out_recv: | 104 | out_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); |
109 | out: | ||
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 |
198 | static u8 cap_pcr[] = { | 116 | static 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 |
208 | static u8 pcrread[] = { | 126 | static 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 | ||
215 | static ssize_t show_pcrs(struct device *dev, char *buf) | 133 | ssize_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 | } |
174 | out: | ||
246 | return str - buf; | 175 | return str - buf; |
247 | } | 176 | } |
248 | 177 | EXPORT_SYMBOL_GPL(tpm_show_pcrs); | |
249 | static DEVICE_ATTR(pcrs, S_IRUGO, show_pcrs, NULL); | ||
250 | 178 | ||
251 | #define READ_PUBEK_RESULT_SIZE 314 | 179 | #define READ_PUBEK_RESULT_SIZE 314 |
252 | static u8 readpubek[] = { | 180 | static 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 | ||
258 | static ssize_t show_pubek(struct device *dev, char *buf) | 186 | ssize_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; |
244 | out: | ||
245 | kfree(data); | ||
246 | return rc; | ||
310 | } | 247 | } |
311 | 248 | ||
312 | static DEVICE_ATTR(pubek, S_IRUGO, show_pubek, NULL); | 249 | EXPORT_SYMBOL_GPL(tpm_show_pubek); |
313 | 250 | ||
314 | #define CAP_VER_RESULT_SIZE 18 | 251 | #define CAP_VER_RESULT_SIZE 18 |
315 | static u8 cap_version[] = { | 252 | static 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 |
324 | static u8 cap_manufacturer[] = { | 261 | static 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 | ||
333 | static ssize_t show_caps(struct device *dev, char *buf) | 270 | ssize_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 | } |
304 | EXPORT_SYMBOL_GPL(tpm_show_caps); | ||
305 | |||
306 | ssize_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 | } | ||
316 | EXPORT_SYMBOL_GPL(tpm_store_cancel); | ||
366 | 317 | ||
367 | static 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); | |||
422 | int tpm_release(struct inode *inode, struct file *file) | 372 | int 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); | |||
609 | int tpm_register_hardware(struct pci_dev *pci_dev, | 527 | int 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 | ||
679 | EXPORT_SYMBOL_GPL(tpm_register_hardware); | 601 | sysfs_create_group(&pci_dev->dev.kobj, chip->vendor->attr_group); |
680 | 602 | ||
681 | static int __init init_tpm(void) | ||
682 | { | ||
683 | return 0; | 603 | return 0; |
684 | } | 604 | } |
685 | 605 | ||
686 | static void __exit cleanup_tpm(void) | 606 | EXPORT_SYMBOL_GPL(tpm_register_hardware); |
687 | { | ||
688 | |||
689 | } | ||
690 | |||
691 | module_init(init_tpm); | ||
692 | module_exit(cleanup_tpm); | ||
693 | 607 | ||
694 | MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)"); | 608 | MODULE_AUTHOR("Leendert van Doorn (leendert@watson.ibm.com)"); |
695 | MODULE_DESCRIPTION("TPM Driver"); | 609 | MODULE_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) | 28 | enum tpm_timeout { |
29 | TPM_TIMEOUT = 5, /* msecs */ | ||
30 | }; | ||
29 | 31 | ||
30 | /* TPM addresses */ | 32 | /* TPM addresses */ |
31 | #define TPM_ADDR 0x4E | 33 | enum tpm_addr { |
32 | #define TPM_DATA 0x4F | 34 | TPM_SUPERIO_ADDR = 0x2E, |
35 | TPM_ADDR = 0x4E, | ||
36 | }; | ||
37 | |||
38 | extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr, | ||
39 | char *); | ||
40 | extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr, | ||
41 | char *); | ||
42 | extern ssize_t tpm_show_caps(struct device *, struct device_attribute *attr, | ||
43 | char *); | ||
44 | extern ssize_t tpm_store_cancel(struct device *, struct device_attribute *attr, | ||
45 | const char *, size_t); | ||
33 | 46 | ||
34 | struct tpm_chip; | 47 | struct tpm_chip; |
35 | 48 | ||
36 | struct tpm_vendor_specific { | 49 | struct 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 | ||
47 | struct tpm_chip { | 62 | struct 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 | ||
69 | static inline int tpm_read_index(int index) | 82 | static 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 | ||
75 | static inline void tpm_write_index(int index, int value) | 88 | static 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 | ||
81 | extern void tpm_time_expired(unsigned long); | ||
82 | extern int tpm_lpc_bus_init(struct pci_dev *, u16); | ||
83 | |||
84 | extern int tpm_register_hardware(struct pci_dev *, | 94 | extern int tpm_register_hardware(struct pci_dev *, |
85 | struct tpm_vendor_specific *); | 95 | struct tpm_vendor_specific *); |
86 | extern int tpm_open(struct inode *, struct file *); | 96 | extern 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 | 25 | enum 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 | 31 | enum 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 | 36 | enum 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 | ||
37 | static int tpm_atml_recv(struct tpm_chip *chip, u8 * buf, size_t count) | 43 | static 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 | ||
130 | static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); | ||
131 | static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL); | ||
132 | static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL); | ||
133 | static DEVICE_ATTR(cancel, S_IWUSR |S_IWGRP, NULL, tpm_store_cancel); | ||
134 | |||
135 | static 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 | |||
143 | static struct attribute_group atmel_attr_grp = { .attrs = atmel_attrs }; | ||
144 | |||
124 | static struct tpm_vendor_specific tpm_atmel = { | 145 | static 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 */ | ||
33 | static int TPM_INF_DATA = 0; | ||
34 | static int TPM_INF_ADDR = 0; | ||
35 | |||
36 | /* TPM header definitions */ | ||
37 | enum 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 | |||
55 | enum infineon_tpm_register { | ||
56 | WRFIFO = 0x00, | ||
57 | RDFIFO = 0x01, | ||
58 | STAT = 0x02, | ||
59 | CMD = 0x03 | ||
60 | }; | ||
61 | |||
62 | enum infineon_tpm_command_bits { | ||
63 | CMD_DIS = 0x00, | ||
64 | CMD_LP = 0x01, | ||
65 | CMD_RES = 0x02, | ||
66 | CMD_IRQC = 0x06 | ||
67 | }; | ||
68 | |||
69 | enum 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 */ | ||
79 | enum 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 | |||
94 | static int number_of_wtx; | ||
95 | |||
96 | static 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 | |||
133 | static 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 | |||
156 | static 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 | |||
170 | static 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 | |||
182 | static 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 | |||
193 | static 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 | |||
199 | recv_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 | |||
263 | static 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 | |||
310 | static 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 | |||
319 | static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); | ||
320 | static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL); | ||
321 | static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL); | ||
322 | static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel); | ||
323 | |||
324 | static 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 | |||
332 | static struct attribute_group inf_attr_grp = {.attrs = inf_attrs }; | ||
333 | |||
334 | static 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 | |||
343 | static 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 | |||
353 | static const struct pnp_device_id tpm_pnp_tbl[] = { | ||
354 | /* Infineon TPMs */ | ||
355 | {"IFX0101", 0}, | ||
356 | {"IFX0102", 0}, | ||
357 | {"", 0} | ||
358 | }; | ||
359 | |||
360 | static 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 | |||
373 | static 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 | |||
379 | static 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 | |||
494 | static 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 | |||
506 | MODULE_DEVICE_TABLE(pci, tpm_pci_tbl); | ||
507 | |||
508 | static 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 | |||
517 | static int __init init_inf(void) | ||
518 | { | ||
519 | return pci_register_driver(&inf_pci_driver); | ||
520 | } | ||
521 | |||
522 | static void __exit cleanup_inf(void) | ||
523 | { | ||
524 | pci_unregister_driver(&inf_pci_driver); | ||
525 | } | ||
526 | |||
527 | module_init(init_inf); | ||
528 | module_exit(cleanup_inf); | ||
529 | |||
530 | MODULE_AUTHOR("Marcel Selhorst <selhorst@crypto.rub.de>"); | ||
531 | MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); | ||
532 | MODULE_VERSION("1.5"); | ||
533 | MODULE_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 | 25 | enum 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 | 33 | enum 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 | 43 | enum 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 */ | 50 | enum 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 */ | 60 | enum 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 | */ |
56 | static int wait_for_stat(struct tpm_chip *chip, u8 mask, u8 val, u8 * data) | 68 | static 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) | |||
84 | static int nsc_wait_for_ready(struct tpm_chip *chip) | 90 | static 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 | ||
232 | static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); | ||
233 | static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL); | ||
234 | static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps, NULL); | ||
235 | static DEVICE_ATTR(cancel, S_IWUSR|S_IWGRP, NULL, tpm_store_cancel); | ||
236 | |||
237 | static 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 | |||
245 | static struct attribute_group nsc_attr_grp = { .attrs = nsc_attrs }; | ||
246 | |||
231 | static struct tpm_vendor_specific tpm_nsc = { | 247 | static 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 | ||
242 | static int __devinit tpm_nsc_init(struct pci_dev *pci_dev, | 258 | static 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 | ||
252 | static DEFINE_SPINLOCK(tty_ldisc_lock); | 253 | static DEFINE_SPINLOCK(tty_ldisc_lock); |
253 | static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); | 254 | static DECLARE_WAIT_QUEUE_HEAD(tty_ldisc_wait); |
254 | static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */ | 255 | static struct tty_ldisc tty_ldiscs[NR_LDISCS]; /* line disc dispatch table */ |
255 | 256 | ||
256 | int tty_register_ldisc(int disc, struct tty_ldisc *new_ldisc) | 257 | int 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 | |||
281 | EXPORT_SYMBOL(tty_register_ldisc); | 274 | EXPORT_SYMBOL(tty_register_ldisc); |
282 | 275 | ||
276 | int 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 | } | ||
293 | EXPORT_SYMBOL(tty_unregister_ldisc); | ||
294 | |||
283 | struct tty_ldisc *tty_ldisc_get(int disc) | 295 | struct 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 | ||
2172 | static int send_break(struct tty_struct *tty, int duration) | 2184 | static 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 | ||
2657 | static struct class_simple *tty_class; | 2668 | static 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, | |||
2701 | void tty_unregister_device(struct tty_driver *driver, unsigned index) | 2712 | void 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 | ||
2707 | EXPORT_SYMBOL(tty_register_device); | 2718 | EXPORT_SYMBOL(tty_register_device); |
@@ -2918,7 +2929,7 @@ extern int vty_init(void); | |||
2918 | 2929 | ||
2919 | static int __init tty_class_init(void) | 2930 | static 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 | ||
477 | static struct class_simple *vc_class; | 477 | static struct class *vc_class; |
478 | 478 | ||
479 | void vcs_make_devfs(struct tty_struct *tty) | 479 | void 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 | } |
490 | void vcs_remove_devfs(struct tty_struct *tty) | 490 | void 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 | ||
498 | int __init vcs_init(void) | 498 | int __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 | ||
238 | static struct mtget viomtget[VIOTAPE_MAX_TAPE]; | 238 | static struct mtget viomtget[VIOTAPE_MAX_TAPE]; |
239 | 239 | ||
240 | static struct class_simple *tape_class; | 240 | static struct class *tape_class; |
241 | 241 | ||
242 | static struct device *tape_device[VIOTAPE_MAX_TAPE]; | 242 | static 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 | ||
1072 | unreg_class: | 1072 | unreg_class: |
1073 | class_simple_destroy(tape_class); | 1073 | class_destroy(tape_class); |
1074 | unreg_chrdev: | 1074 | unreg_chrdev: |
1075 | unregister_chrdev(VIOTAPE_MAJOR, "viotape"); | 1075 | unregister_chrdev(VIOTAPE_MAJOR, "viotape"); |
1076 | clear_handler: | 1076 | clear_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 | |||
38 | MODULE_AUTHOR("Yoichi Yuasa <yuasa@hh.iij4u.or.jp>"); | ||
39 | MODULE_DESCRIPTION("NEC VR4100 series General-purpose I/O Unit driver"); | ||
40 | MODULE_LICENSE("GPL"); | ||
41 | |||
42 | static int major; /* default is dynamic major device number */ | ||
43 | module_param(major, int, 0); | ||
44 | MODULE_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 | |||
90 | static spinlock_t giu_lock; | ||
91 | static struct resource *giu_resource1; | ||
92 | static struct resource *giu_resource2; | ||
93 | static unsigned long giu_flags; | ||
94 | static unsigned int giu_nr_pins; | ||
95 | |||
96 | static 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 | |||
105 | static 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 | |||
116 | static 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 | |||
127 | static 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 | |||
138 | static void shutdown_giuint_low_irq(unsigned int irq) | ||
139 | { | ||
140 | giu_clear(GIUINTENL, 1 << GPIO_PIN_OF_IRQ(irq)); | ||
141 | } | ||
142 | |||
143 | static 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 | |||
150 | static 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 | |||
159 | static 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 | |||
165 | static 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 | |||
175 | static 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 | |||
186 | static void shutdown_giuint_high_irq(unsigned int irq) | ||
187 | { | ||
188 | giu_clear(GIUINTENH, 1 << (GPIO_PIN_OF_IRQ(irq) - GIUINT_HIGH_OFFSET)); | ||
189 | } | ||
190 | |||
191 | static 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 | |||
198 | static 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 | |||
207 | static 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 | |||
213 | static 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 | |||
223 | static 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 | |||
256 | void 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 | |||
321 | EXPORT_SYMBOL_GPL(vr41xx_set_irq_trigger); | ||
322 | |||
323 | void 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 | |||
344 | EXPORT_SYMBOL_GPL(vr41xx_set_irq_level); | ||
345 | |||
346 | gpio_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 | |||
373 | EXPORT_SYMBOL_GPL(vr41xx_gpio_get_pin); | ||
374 | |||
375 | int 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 | |||
411 | EXPORT_SYMBOL_GPL(vr41xx_gpio_set_pin); | ||
412 | |||
413 | int 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 | |||
461 | EXPORT_SYMBOL_GPL(vr41xx_gpio_set_direction); | ||
462 | |||
463 | int 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 | |||
500 | EXPORT_SYMBOL_GPL(vr41xx_gpio_pullupdown); | ||
501 | |||
502 | static 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 | |||
524 | static 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 | |||
586 | static 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 | |||
597 | static 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 | |||
608 | static 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 | |||
616 | static 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 | |||
700 | static 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 | |||
711 | static struct platform_device *giu_platform_device; | ||
712 | |||
713 | static struct device_driver giu_device_driver = { | ||
714 | .name = "GIU", | ||
715 | .bus = &platform_bus_type, | ||
716 | .probe = giu_probe, | ||
717 | .remove = giu_remove, | ||
718 | }; | ||
719 | |||
720 | static 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 | |||
735 | static void __devexit vr41xx_giu_exit(void) | ||
736 | { | ||
737 | driver_unregister(&giu_device_driver); | ||
738 | |||
739 | platform_device_unregister(giu_platform_device); | ||
740 | } | ||
741 | |||
742 | module_init(vr41xx_giu_init); | ||
743 | module_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 | */ |
2868 | static void blank_screen_t(unsigned long dummy) | 2868 | static 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 | ||
418 | config 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 | |||
33 | obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o | 33 | obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o |
34 | obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o | 34 | obj-$(CONFIG_IXP2000_WATCHDOG) += ixp2000_wdt.o |
35 | obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o | 35 | obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o |
36 | obj-$(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; | |||
82 | module_param(wdt_start, int, 0); | 82 | module_param(wdt_start, int, 0); |
83 | MODULE_PARM_DESC(wdt_start, "Acquire WDT 'start' io port (default 0x443)"); | 83 | MODULE_PARM_DESC(wdt_start, "Acquire WDT 'start' io port (default 0x443)"); |
84 | 84 | ||
85 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 85 | static int nowayout = WATCHDOG_NOWAYOUT; |
86 | static int nowayout = 1; | ||
87 | #else | ||
88 | static int nowayout = 0; | ||
89 | #endif | ||
90 | |||
91 | module_param(nowayout, int, 0); | 86 | module_param(nowayout, int, 0); |
92 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 87 | MODULE_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 */ | |||
73 | module_param(timeout, int, 0); | 73 | module_param(timeout, int, 0); |
74 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); | 74 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); |
75 | 75 | ||
76 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 76 | static int nowayout = WATCHDOG_NOWAYOUT; |
77 | static int nowayout = 1; | ||
78 | #else | ||
79 | static int nowayout = 0; | ||
80 | #endif | ||
81 | |||
82 | module_param(nowayout, int, 0); | 77 | module_param(nowayout, int, 0); |
83 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 78 | MODULE_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; | |||
38 | module_param(timeout, int, 0); | 38 | module_param(timeout, int, 0); |
39 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (0<timeout<18000, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | 39 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (0<timeout<18000, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); |
40 | 40 | ||
41 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 41 | static int nowayout = WATCHDOG_NOWAYOUT; |
42 | static int nowayout = 1; | ||
43 | #else | ||
44 | static int nowayout = 0; | ||
45 | #endif | ||
46 | |||
47 | module_param(nowayout, int, 0); | 42 | module_param(nowayout, int, 0); |
48 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 43 | MODULE_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 | ||
319 | static struct pci_device_id ali_pci_tbl[] = { | 314 | static 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 | }; |
323 | MODULE_DEVICE_TABLE(pci, ali_pci_tbl); | 318 | MODULE_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; | |||
75 | static char wdt_expect_close; | 75 | static char wdt_expect_close; |
76 | static struct pci_dev *alim7101_pmu; | 76 | static struct pci_dev *alim7101_pmu; |
77 | 77 | ||
78 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 78 | static int nowayout = WATCHDOG_NOWAYOUT; |
79 | static int nowayout = 1; | ||
80 | #else | ||
81 | static int nowayout = 0; | ||
82 | #endif | ||
83 | |||
84 | module_param(nowayout, int, 0); | 79 | module_param(nowayout, int, 0); |
85 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 80 | MODULE_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 | 75 | static int nowayout = WATCHDOG_NOWAYOUT; |
76 | static int nowayout = 1; | ||
77 | #else | ||
78 | static int nowayout = 0; | ||
79 | #endif | ||
80 | |||
81 | module_param(nowayout, int, 0); | 76 | module_param(nowayout, int, 0); |
82 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 77 | MODULE_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 */ | |||
105 | module_param(heartbeat, int, 0); | 108 | module_param(heartbeat, int, 0); |
106 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<heartbeat<39, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); | 109 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<heartbeat<39, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); |
107 | 110 | ||
108 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 111 | static int nowayout = WATCHDOG_NOWAYOUT; |
109 | static int nowayout = 1; | ||
110 | #else | ||
111 | static int nowayout = 0; | ||
112 | #endif | ||
113 | |||
114 | module_param(nowayout, int, 0); | 112 | module_param(nowayout, int, 0); |
115 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 113 | MODULE_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 | ||
144 | static int tco_timer_stop (void) | 150 | static 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) | |||
160 | static int tco_timer_keepalive (void) | 173 | static 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 | ||
511 | static void __exit watchdog_cleanup (void) | 528 | static 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 | ||
118 | static int wd_margin = WD_TIMO; | 118 | static int wd_margin = WD_TIMO; |
119 | 119 | ||
120 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 120 | static int nowayout = WATCHDOG_NOWAYOUT; |
121 | static int nowayout = 1; | ||
122 | #else | ||
123 | static int nowayout = 0; | ||
124 | #endif | ||
125 | |||
126 | module_param(nowayout, int, 0); | 121 | module_param(nowayout, int, 0); |
127 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 122 | MODULE_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: " |
30 | static int indydog_alive; | 30 | static int indydog_alive; |
31 | 31 | ||
32 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | ||
33 | static int nowayout = 1; | ||
34 | #else | ||
35 | static 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 | ||
34 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
40 | module_param(nowayout, int, 0); | 35 | module_param(nowayout, int, 0); |
41 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 36 | MODULE_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 | 33 | static int nowayout = WATCHDOG_NOWAYOUT; |
34 | static int nowayout = 1; | ||
35 | #else | ||
36 | static int nowayout = 0; | ||
37 | #endif | ||
38 | static unsigned int heartbeat = 60; /* (secs) Default is 1 minute */ | 34 | static unsigned int heartbeat = 60; /* (secs) Default is 1 minute */ |
39 | static unsigned long wdt_status; | 35 | static 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 | ||
193 | static int __init ixp2000_wdt_init(void) | 189 | static 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 | 30 | static int nowayout = WATCHDOG_NOWAYOUT; |
31 | static int nowayout = 1; | ||
32 | #else | ||
33 | static int nowayout = 0; | ||
34 | #endif | ||
35 | static int heartbeat = 60; /* (secs) Default is 1 minute */ | 31 | static int heartbeat = 60; /* (secs) Default is 1 minute */ |
36 | static unsigned long wdt_status; | 32 | static unsigned long wdt_status; |
37 | static unsigned long boot_status; | 33 | static 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"); | |||
94 | MODULE_LICENSE("GPL"); | 94 | MODULE_LICENSE("GPL"); |
95 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | 95 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |
96 | 96 | ||
97 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 97 | static int nowayout = WATCHDOG_NOWAYOUT; |
98 | static int nowayout = 1; | ||
99 | #else | ||
100 | static int nowayout = 0; | ||
101 | #endif | ||
102 | |||
103 | module_param(nowayout, int, 0); | 98 | module_param(nowayout, int, 0); |
104 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 99 | MODULE_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; | |||
62 | static struct timer_list mixcomwd_timer = TIMER_INITIALIZER(NULL, 0, 0); | 62 | static struct timer_list mixcomwd_timer = TIMER_INITIALIZER(NULL, 0, 0); |
63 | static char expect_close; | 63 | static char expect_close; |
64 | 64 | ||
65 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 65 | static int nowayout = WATCHDOG_NOWAYOUT; |
66 | static int nowayout = 1; | ||
67 | #else | ||
68 | static int nowayout = 0; | ||
69 | #endif | ||
70 | |||
71 | module_param(nowayout, int, 0); | 66 | module_param(nowayout, int, 0); |
72 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 67 | MODULE_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; | |||
146 | module_param(heartbeat, int, 0); | 146 | module_param(heartbeat, int, 0); |
147 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<=heartbeat<=7200, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); | 147 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<=heartbeat<=7200, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); |
148 | 148 | ||
149 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 149 | static int nowayout = WATCHDOG_NOWAYOUT; |
150 | static int nowayout = 1; | ||
151 | #else | ||
152 | static int nowayout = 0; | ||
153 | #endif | ||
154 | |||
155 | module_param(nowayout, int, 0); | 150 | module_param(nowayout, int, 0); |
156 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 151 | MODULE_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; | |||
103 | module_param(heartbeat, int, 0); | 103 | module_param(heartbeat, int, 0); |
104 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); | 104 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); |
105 | 105 | ||
106 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 106 | static int nowayout = WATCHDOG_NOWAYOUT; |
107 | static int nowayout = 1; | ||
108 | #else | ||
109 | static int nowayout = 0; | ||
110 | #endif | ||
111 | |||
112 | module_param(nowayout, int, 0); | 107 | module_param(nowayout, int, 0); |
113 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 108 | MODULE_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; | |||
79 | module_param(heartbeat, int, 0); | 79 | module_param(heartbeat, int, 0); |
80 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); | 80 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); |
81 | 81 | ||
82 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 82 | static int nowayout = WATCHDOG_NOWAYOUT; |
83 | static int nowayout = 1; | ||
84 | #else | ||
85 | static int nowayout = 0; | ||
86 | #endif | ||
87 | |||
88 | module_param(nowayout, int, 0); | 83 | module_param(nowayout, int, 0); |
89 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 84 | MODULE_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 | 65 | static int nowayout = WATCHDOG_NOWAYOUT; |
66 | static int nowayout = 1; | ||
67 | #else | ||
68 | static int nowayout = 0; | ||
69 | #endif | ||
70 | |||
71 | static int tmr_margin = CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME; | 66 | static int tmr_margin = CONFIG_S3C2410_WATCHDOG_DEFAULT_TIME; |
72 | static int tmr_atboot = CONFIG_S3C2410_WATCHDOG_ATBOOT; | 67 | static int tmr_atboot = CONFIG_S3C2410_WATCHDOG_ATBOOT; |
73 | static int soft_noboot = 0; | 68 | static 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 | ||
41 | static unsigned long sa1100wdt_users; | 40 | static unsigned long sa1100wdt_users; |
42 | static int expect_close; | ||
43 | static int pre_margin; | 41 | static int pre_margin; |
44 | static int boot_status; | 42 | static int boot_status; |
45 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | ||
46 | static int nowayout = 1; | ||
47 | #else | ||
48 | static 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 | */ |
74 | static int sa1100dog_release(struct inode *inode, struct file *file) | 68 | static 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 | ||
90 | static ssize_t sa1100dog_write(struct file *file, const char *data, size_t len, loff_t *ppos) | 77 | static 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 | ||
114 | static struct watchdog_info ident = { | 86 | static 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 | ||
120 | static int sa1100dog_ioctl(struct inode *inode, struct file *file, | 91 | static int sa1100dog_ioctl(struct inode *inode, struct file *file, |
@@ -176,7 +147,7 @@ static struct file_operations sa1100dog_fops = | |||
176 | static struct miscdevice sa1100dog_miscdev = | 147 | static 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"); | |||
216 | module_param(margin, int, 0); | 186 | module_param(margin, int, 0); |
217 | MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)"); | 187 | MODULE_PARM_DESC(margin, "Watchdog margin in seconds (default 60s)"); |
218 | 188 | ||
219 | module_param(nowayout, int, 0); | ||
220 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); | ||
221 | |||
222 | MODULE_LICENSE("GPL"); | 189 | MODULE_LICENSE("GPL"); |
223 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | 190 | MODULE_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 | |||
98 | module_param(timeout, int, 0); | 98 | module_param(timeout, int, 0); |
99 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | 99 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); |
100 | 100 | ||
101 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 101 | static int nowayout = WATCHDOG_NOWAYOUT; |
102 | static int nowayout = 1; | ||
103 | #else | ||
104 | static int nowayout = 0; | ||
105 | #endif | ||
106 | |||
107 | module_param(nowayout, int, 0); | 102 | module_param(nowayout, int, 0); |
108 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 103 | MODULE_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"); | |||
91 | module_param(timeout, int, 0); | 91 | module_param(timeout, int, 0); |
92 | MODULE_PARM_DESC(timeout, "range is 0-255 minutes, default is 1"); | 92 | MODULE_PARM_DESC(timeout, "range is 0-255 minutes, default is 1"); |
93 | 93 | ||
94 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 94 | static int nowayout = WATCHDOG_NOWAYOUT; |
95 | static int nowayout = 1; | ||
96 | #else | ||
97 | static int nowayout = 0; | ||
98 | #endif | ||
99 | |||
100 | module_param(nowayout, int, 0); | 95 | module_param(nowayout, int, 0); |
101 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 96 | MODULE_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 | |||
94 | module_param(timeout, int, 0); | 94 | module_param(timeout, int, 0); |
95 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | 95 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); |
96 | 96 | ||
97 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 97 | static int nowayout = WATCHDOG_NOWAYOUT; |
98 | static int nowayout = 1; | ||
99 | #else | ||
100 | static int nowayout = 0; | ||
101 | #endif | ||
102 | |||
103 | module_param(nowayout, int, 0); | 98 | module_param(nowayout, int, 0); |
104 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 99 | MODULE_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"); | |||
39 | MODULE_LICENSE("GPL"); | 39 | MODULE_LICENSE("GPL"); |
40 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | 40 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |
41 | 41 | ||
42 | #ifndef CONFIG_WATCHDOG_NOWAYOUT | ||
43 | #define CONFIG_WATCHDOG_NOWAYOUT 0 | ||
44 | #endif | ||
45 | |||
46 | static int margin = 60; /* in seconds */ | 42 | static int margin = 60; /* in seconds */ |
47 | module_param(margin, int, 0); | 43 | module_param(margin, int, 0); |
48 | MODULE_PARM_DESC(margin, "Watchdog margin in seconds"); | 44 | MODULE_PARM_DESC(margin, "Watchdog margin in seconds"); |
49 | 45 | ||
50 | static int nowayout = CONFIG_WATCHDOG_NOWAYOUT; | 46 | static int nowayout = WATCHDOG_NOWAYOUT; |
51 | module_param(nowayout, int, 0); | 47 | module_param(nowayout, int, 0); |
52 | MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); | 48 | MODULE_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 */ |
76 | static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ | 76 | static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ |
77 | 77 | ||
78 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 78 | static int nowayout = WATCHDOG_NOWAYOUT; |
79 | static int nowayout = 1; | ||
80 | #else | ||
81 | static 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 */ | |||
56 | module_param(soft_margin, int, 0); | 56 | module_param(soft_margin, int, 0); |
57 | MODULE_PARM_DESC(soft_margin, "Watchdog soft_margin in seconds. (0<soft_margin<65536, default=" __MODULE_STRING(TIMER_MARGIN) ")"); | 57 | MODULE_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 | 59 | static int nowayout = WATCHDOG_NOWAYOUT; |
60 | static int nowayout = 1; | ||
61 | #else | ||
62 | static int nowayout = 0; | ||
63 | #endif | ||
64 | |||
65 | module_param(nowayout, int, 0); | 60 | module_param(nowayout, int, 0); |
66 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 61 | MODULE_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 */ | |||
54 | module_param(timeout, int, 0); | 54 | module_param(timeout, int, 0); |
55 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); | 55 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); |
56 | 56 | ||
57 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 57 | static int nowayout = WATCHDOG_NOWAYOUT; |
58 | static int nowayout = 1; | ||
59 | #else | ||
60 | static int nowayout = 0; | ||
61 | #endif | ||
62 | |||
63 | module_param(nowayout, int, 0); | 58 | module_param(nowayout, int, 0); |
64 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 59 | MODULE_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); | |||
85 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | 85 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); |
86 | 86 | ||
87 | 87 | ||
88 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 88 | static int nowayout = WATCHDOG_NOWAYOUT; |
89 | static int nowayout = 1; | ||
90 | #else | ||
91 | static int nowayout = 0; | ||
92 | #endif | ||
93 | |||
94 | module_param(nowayout, int, 0); | 89 | module_param(nowayout, int, 0); |
95 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 90 | MODULE_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 */ | |||
63 | module_param(timeout, int, 0); | 63 | module_param(timeout, int, 0); |
64 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255, default=" __MODULE_STRING(WD_TIMO) "."); | 64 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255, default=" __MODULE_STRING(WD_TIMO) "."); |
65 | 65 | ||
66 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 66 | static int nowayout = WATCHDOG_NOWAYOUT; |
67 | static int nowayout = 1; | ||
68 | #else | ||
69 | static int nowayout = 0; | ||
70 | #endif | ||
71 | |||
72 | module_param(nowayout, int, 0); | 67 | module_param(nowayout, int, 0); |
73 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 68 | MODULE_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 | |||
47 | MODULE_AUTHOR("Utz Bacher <utz.bacher@de.ibm.com>"); | ||
48 | MODULE_DESCRIPTION("RTAS watchdog driver"); | ||
49 | MODULE_LICENSE("GPL"); | ||
50 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
51 | MODULE_ALIAS_MISCDEV(TEMP_MINOR); | ||
52 | |||
53 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | ||
54 | static int wdrtas_nowayout = 1; | ||
55 | #else | ||
56 | static int wdrtas_nowayout = 0; | ||
57 | #endif | ||
58 | |||
59 | static atomic_t wdrtas_miscdev_open = ATOMIC_INIT(0); | ||
60 | static char wdrtas_expect_close = 0; | ||
61 | |||
62 | static int wdrtas_interval; | ||
63 | |||
64 | #define WDRTAS_THERMAL_SENSOR 3 | ||
65 | static int wdrtas_token_get_sensor_state; | ||
66 | #define WDRTAS_SURVEILLANCE_IND 9000 | ||
67 | static int wdrtas_token_set_indicator; | ||
68 | #define WDRTAS_SP_SPI 28 | ||
69 | static int wdrtas_token_get_sp; | ||
70 | static int wdrtas_token_event_scan; | ||
71 | |||
72 | #define WDRTAS_DEFAULT_INTERVAL 300 | ||
73 | |||
74 | #define WDRTAS_LOGBUFFER_LEN 128 | ||
75 | static 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 | */ | ||
90 | static int | ||
91 | wdrtas_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 | */ | ||
120 | static int | ||
121 | wdrtas_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 | */ | ||
145 | static void | ||
146 | wdrtas_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 | */ | ||
157 | static void | ||
158 | wdrtas_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 | */ | ||
169 | static void | ||
170 | wdrtas_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 | */ | ||
196 | static void | ||
197 | wdrtas_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 | */ | ||
222 | static int | ||
223 | wdrtas_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 | */ | ||
247 | static int | ||
248 | wdrtas_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 | */ | ||
259 | static int | ||
260 | wdrtas_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 | */ | ||
280 | static ssize_t | ||
281 | wdrtas_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 | |||
304 | out: | ||
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 | */ | ||
319 | static int | ||
320 | wdrtas_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 | */ | ||
403 | static int | ||
404 | wdrtas_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 | */ | ||
427 | static int | ||
428 | wdrtas_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 | */ | ||
457 | static ssize_t | ||
458 | wdrtas_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 | */ | ||
482 | static int | ||
483 | wdrtas_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 | */ | ||
497 | static int | ||
498 | wdrtas_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 | */ | ||
513 | static int | ||
514 | wdrtas_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 | |||
524 | static 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 | |||
533 | static struct miscdevice wdrtas_miscdev = { | ||
534 | .minor = WATCHDOG_MINOR, | ||
535 | .name = "watchdog", | ||
536 | .fops = &wdrtas_fops, | ||
537 | }; | ||
538 | |||
539 | static 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 | |||
547 | static struct miscdevice wdrtas_tempdev = { | ||
548 | .minor = TEMP_MINOR, | ||
549 | .name = "temperature", | ||
550 | .fops = &wdrtas_temp_fops, | ||
551 | }; | ||
552 | |||
553 | static 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 | */ | ||
566 | static int | ||
567 | wdrtas_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 | */ | ||
607 | static void | ||
608 | wdrtas_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 | */ | ||
623 | static int | ||
624 | wdrtas_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 | */ | ||
655 | static int __init | ||
656 | wdrtas_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 | */ | ||
684 | static void __exit | ||
685 | wdrtas_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 | |||
695 | module_init(wdrtas_init); | ||
696 | module_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; | |||
63 | module_param(heartbeat, int, 0); | 63 | module_param(heartbeat, int, 0); |
64 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")"); | 64 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")"); |
65 | 65 | ||
66 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 66 | static int nowayout = WATCHDOG_NOWAYOUT; |
67 | static int nowayout = 1; | ||
68 | #else | ||
69 | static int nowayout = 0; | ||
70 | #endif | ||
71 | |||
72 | module_param(nowayout, int, 0); | 67 | module_param(nowayout, int, 0); |
73 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 68 | MODULE_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 | |||
53 | module_param(testmode, int, 0); | 53 | module_param(testmode, int, 0); |
54 | MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0"); | 54 | MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0"); |
55 | 55 | ||
56 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 56 | static int nowayout = WATCHDOG_NOWAYOUT; |
57 | static int nowayout = 1; | ||
58 | #else | ||
59 | static int nowayout = 0; | ||
60 | #endif | ||
61 | |||
62 | module_param(nowayout, int, 0); | 57 | module_param(nowayout, int, 0); |
63 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 58 | MODULE_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; | |||
89 | module_param(heartbeat, int, 0); | 89 | module_param(heartbeat, int, 0); |
90 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")"); | 90 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (0<heartbeat<65536, default=" __MODULE_STRING(WD_TIMO) ")"); |
91 | 91 | ||
92 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 92 | static int nowayout = WATCHDOG_NOWAYOUT; |
93 | static int nowayout = 1; | ||
94 | #else | ||
95 | static int nowayout = 0; | ||
96 | #endif | ||
97 | |||
98 | module_param(nowayout, int, 0); | 93 | module_param(nowayout, int, 0); |
99 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=CONFIG_WATCHDOG_NOWAYOUT)"); | 94 | MODULE_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"); |