diff options
author | Jeff Garzik <jgarzik@pretzel.yyz.us> | 2005-06-26 17:11:03 -0400 |
---|---|---|
committer | Jeff Garzik <jgarzik@pobox.com> | 2005-06-26 17:11:03 -0400 |
commit | 8b0ee07e108b2eefdab5bb73f33223f18926c3b2 (patch) | |
tree | f68ca04180c5488301a40ec212ef2eb2467cf56c /drivers/char | |
parent | 4638aef40ba9ebb9734caeed1f373c24015259fd (diff) | |
parent | 8678887e7fb43cd6c9be6c9807b05e77848e0920 (diff) |
Merge upstream (approx. 2.6.12-git8) into 'janitor' branch of netdev-2.6.
Diffstat (limited to 'drivers/char')
89 files changed, 4615 insertions, 1523 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 5ed6515ae01f..43d0cb19ef6a 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
@@ -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..1aff819f3832 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -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 ad9c11391d81..c1fe013c64f3 100644 --- a/drivers/char/agp/agp.h +++ b/drivers/char/agp/agp.h | |||
@@ -278,6 +278,8 @@ void agp3_generic_cleanup(void); | |||
278 | #define AGP_GENERIC_SIZES_ENTRIES 11 | 278 | #define AGP_GENERIC_SIZES_ENTRIES 11 |
279 | extern struct aper_size_info_16 agp3_generic_sizes[]; | 279 | extern struct aper_size_info_16 agp3_generic_sizes[]; |
280 | 280 | ||
281 | #define virt_to_gart(x) (phys_to_gart(virt_to_phys(x))) | ||
282 | #define gart_to_virt(x) (phys_to_virt(gart_to_phys(x))) | ||
281 | 283 | ||
282 | extern int agp_off; | 284 | extern int agp_off; |
283 | extern int agp_try_unsupported_boot; | 285 | extern int agp_try_unsupported_boot; |
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c index 0212febda654..9c9c9c2247ce 100644 --- a/drivers/char/agp/ali-agp.c +++ b/drivers/char/agp/ali-agp.c | |||
@@ -150,7 +150,7 @@ static void *m1541_alloc_page(struct agp_bridge_data *bridge) | |||
150 | pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); | 150 | pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); |
151 | pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, | 151 | pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, |
152 | (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | | 152 | (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | |
153 | virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN )); | 153 | virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN )); |
154 | return addr; | 154 | return addr; |
155 | } | 155 | } |
156 | 156 | ||
@@ -174,7 +174,7 @@ static void m1541_destroy_page(void * addr) | |||
174 | pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); | 174 | pci_read_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, &temp); |
175 | pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, | 175 | pci_write_config_dword(agp_bridge->dev, ALI_CACHE_FLUSH_CTRL, |
176 | (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | | 176 | (((temp & ALI_CACHE_FLUSH_ADDR_MASK) | |
177 | virt_to_phys(addr)) | ALI_CACHE_FLUSH_EN)); | 177 | virt_to_gart(addr)) | ALI_CACHE_FLUSH_EN)); |
178 | agp_generic_destroy_page(addr); | 178 | agp_generic_destroy_page(addr); |
179 | } | 179 | } |
180 | 180 | ||
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index e62a3c2c44a9..3a41672e4d66 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c | |||
@@ -43,7 +43,7 @@ static int amd_create_page_map(struct amd_page_map *page_map) | |||
43 | 43 | ||
44 | SetPageReserved(virt_to_page(page_map->real)); | 44 | SetPageReserved(virt_to_page(page_map->real)); |
45 | global_cache_flush(); | 45 | global_cache_flush(); |
46 | page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), | 46 | page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real), |
47 | PAGE_SIZE); | 47 | PAGE_SIZE); |
48 | if (page_map->remapped == NULL) { | 48 | if (page_map->remapped == NULL) { |
49 | ClearPageReserved(virt_to_page(page_map->real)); | 49 | ClearPageReserved(virt_to_page(page_map->real)); |
@@ -154,7 +154,7 @@ static int amd_create_gatt_table(struct agp_bridge_data *bridge) | |||
154 | 154 | ||
155 | agp_bridge->gatt_table_real = (u32 *)page_dir.real; | 155 | agp_bridge->gatt_table_real = (u32 *)page_dir.real; |
156 | agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped; | 156 | agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped; |
157 | agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real); | 157 | agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real); |
158 | 158 | ||
159 | /* Get the address for the gart region. | 159 | /* Get the address for the gart region. |
160 | * This is a bus address even on the alpha, b/c its | 160 | * This is a bus address even on the alpha, b/c its |
@@ -167,7 +167,7 @@ static int amd_create_gatt_table(struct agp_bridge_data *bridge) | |||
167 | 167 | ||
168 | /* Calculate the agp offset */ | 168 | /* Calculate the agp offset */ |
169 | for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) { | 169 | for (i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) { |
170 | writel(virt_to_phys(amd_irongate_private.gatt_pages[i]->real) | 1, | 170 | writel(virt_to_gart(amd_irongate_private.gatt_pages[i]->real) | 1, |
171 | page_dir.remapped+GET_PAGE_DIR_OFF(addr)); | 171 | page_dir.remapped+GET_PAGE_DIR_OFF(addr)); |
172 | readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */ | 172 | readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */ |
173 | } | 173 | } |
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index 399c042f68f0..1407945a5892 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c | |||
@@ -219,7 +219,7 @@ static struct aper_size_info_32 amd_8151_sizes[7] = | |||
219 | 219 | ||
220 | static int amd_8151_configure(void) | 220 | static int amd_8151_configure(void) |
221 | { | 221 | { |
222 | unsigned long gatt_bus = virt_to_phys(agp_bridge->gatt_table_real); | 222 | unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real); |
223 | 223 | ||
224 | /* Configure AGP regs in each x86-64 host bridge. */ | 224 | /* Configure AGP regs in each x86-64 host bridge. */ |
225 | for_each_nb() { | 225 | for_each_nb() { |
@@ -591,7 +591,7 @@ static void __devexit agp_amd64_remove(struct pci_dev *pdev) | |||
591 | { | 591 | { |
592 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); | 592 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); |
593 | 593 | ||
594 | release_mem_region(virt_to_phys(bridge->gatt_table_real), | 594 | release_mem_region(virt_to_gart(bridge->gatt_table_real), |
595 | amd64_aperture_sizes[bridge->aperture_size_idx].size); | 595 | amd64_aperture_sizes[bridge->aperture_size_idx].size); |
596 | agp_remove_bridge(bridge); | 596 | agp_remove_bridge(bridge); |
597 | agp_put_bridge(bridge); | 597 | agp_put_bridge(bridge); |
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index a65f8827c283..e572ced9100a 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c | |||
@@ -61,7 +61,7 @@ static int ati_create_page_map(ati_page_map *page_map) | |||
61 | 61 | ||
62 | SetPageReserved(virt_to_page(page_map->real)); | 62 | SetPageReserved(virt_to_page(page_map->real)); |
63 | err = map_page_into_agp(virt_to_page(page_map->real)); | 63 | err = map_page_into_agp(virt_to_page(page_map->real)); |
64 | page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), | 64 | page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real), |
65 | PAGE_SIZE); | 65 | PAGE_SIZE); |
66 | if (page_map->remapped == NULL || err) { | 66 | if (page_map->remapped == NULL || err) { |
67 | ClearPageReserved(virt_to_page(page_map->real)); | 67 | ClearPageReserved(virt_to_page(page_map->real)); |
@@ -343,7 +343,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge) | |||
343 | 343 | ||
344 | agp_bridge->gatt_table_real = (u32 *)page_dir.real; | 344 | agp_bridge->gatt_table_real = (u32 *)page_dir.real; |
345 | agp_bridge->gatt_table = (u32 __iomem *) page_dir.remapped; | 345 | agp_bridge->gatt_table = (u32 __iomem *) page_dir.remapped; |
346 | agp_bridge->gatt_bus_addr = virt_to_bus(page_dir.real); | 346 | agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real); |
347 | 347 | ||
348 | /* Write out the size register */ | 348 | /* Write out the size register */ |
349 | current_size = A_SIZE_LVL2(agp_bridge->current_size); | 349 | current_size = A_SIZE_LVL2(agp_bridge->current_size); |
@@ -373,7 +373,7 @@ static int ati_create_gatt_table(struct agp_bridge_data *bridge) | |||
373 | 373 | ||
374 | /* Calculate the agp offset */ | 374 | /* Calculate the agp offset */ |
375 | for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) { | 375 | for(i = 0; i < value->num_entries / 1024; i++, addr += 0x00400000) { |
376 | writel(virt_to_bus(ati_generic_private.gatt_pages[i]->real) | 1, | 376 | writel(virt_to_gart(ati_generic_private.gatt_pages[i]->real) | 1, |
377 | page_dir.remapped+GET_PAGE_DIR_OFF(addr)); | 377 | page_dir.remapped+GET_PAGE_DIR_OFF(addr)); |
378 | readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */ | 378 | readl(page_dir.remapped+GET_PAGE_DIR_OFF(addr)); /* PCI Posting. */ |
379 | } | 379 | } |
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index 2f3dfb63bdc6..4d4e602fdc7e 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c | |||
@@ -148,7 +148,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) | |||
148 | return -ENOMEM; | 148 | return -ENOMEM; |
149 | } | 149 | } |
150 | 150 | ||
151 | bridge->scratch_page_real = virt_to_phys(addr); | 151 | bridge->scratch_page_real = virt_to_gart(addr); |
152 | bridge->scratch_page = | 152 | bridge->scratch_page = |
153 | bridge->driver->mask_memory(bridge, bridge->scratch_page_real, 0); | 153 | bridge->driver->mask_memory(bridge, bridge->scratch_page_real, 0); |
154 | } | 154 | } |
@@ -189,7 +189,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) | |||
189 | err_out: | 189 | err_out: |
190 | if (bridge->driver->needs_scratch_page) | 190 | if (bridge->driver->needs_scratch_page) |
191 | bridge->driver->agp_destroy_page( | 191 | bridge->driver->agp_destroy_page( |
192 | phys_to_virt(bridge->scratch_page_real)); | 192 | gart_to_virt(bridge->scratch_page_real)); |
193 | if (got_gatt) | 193 | if (got_gatt) |
194 | bridge->driver->free_gatt_table(bridge); | 194 | bridge->driver->free_gatt_table(bridge); |
195 | if (got_keylist) { | 195 | if (got_keylist) { |
@@ -214,7 +214,7 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge) | |||
214 | if (bridge->driver->agp_destroy_page && | 214 | if (bridge->driver->agp_destroy_page && |
215 | bridge->driver->needs_scratch_page) | 215 | bridge->driver->needs_scratch_page) |
216 | bridge->driver->agp_destroy_page( | 216 | bridge->driver->agp_destroy_page( |
217 | phys_to_virt(bridge->scratch_page_real)); | 217 | gart_to_virt(bridge->scratch_page_real)); |
218 | } | 218 | } |
219 | 219 | ||
220 | /* When we remove the global variable agp_bridge from all drivers | 220 | /* When we remove the global variable agp_bridge from all drivers |
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c index 1383c3165ea1..ac19fdcd21c1 100644 --- a/drivers/char/agp/efficeon-agp.c +++ b/drivers/char/agp/efficeon-agp.c | |||
@@ -219,7 +219,7 @@ static int efficeon_create_gatt_table(struct agp_bridge_data *bridge) | |||
219 | 219 | ||
220 | efficeon_private.l1_table[index] = page; | 220 | efficeon_private.l1_table[index] = page; |
221 | 221 | ||
222 | value = __pa(page) | pati | present | index; | 222 | value = virt_to_gart(page) | pati | present | index; |
223 | 223 | ||
224 | pci_write_config_dword(agp_bridge->dev, | 224 | pci_write_config_dword(agp_bridge->dev, |
225 | EFFICEON_ATTPAGE, value); | 225 | EFFICEON_ATTPAGE, value); |
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index c321a924e38a..f0079e991bdc 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c | |||
@@ -153,7 +153,7 @@ void agp_free_memory(struct agp_memory *curr) | |||
153 | } | 153 | } |
154 | if (curr->page_count != 0) { | 154 | if (curr->page_count != 0) { |
155 | for (i = 0; i < curr->page_count; i++) { | 155 | for (i = 0; i < curr->page_count; i++) { |
156 | curr->bridge->driver->agp_destroy_page(phys_to_virt(curr->memory[i])); | 156 | curr->bridge->driver->agp_destroy_page(gart_to_virt(curr->memory[i])); |
157 | } | 157 | } |
158 | } | 158 | } |
159 | agp_free_key(curr->key); | 159 | agp_free_key(curr->key); |
@@ -209,7 +209,7 @@ struct agp_memory *agp_allocate_memory(struct agp_bridge_data *bridge, | |||
209 | agp_free_memory(new); | 209 | agp_free_memory(new); |
210 | return NULL; | 210 | return NULL; |
211 | } | 211 | } |
212 | new->memory[i] = virt_to_phys(addr); | 212 | new->memory[i] = virt_to_gart(addr); |
213 | new->page_count++; | 213 | new->page_count++; |
214 | } | 214 | } |
215 | new->bridge = bridge; | 215 | new->bridge = bridge; |
@@ -295,19 +295,6 @@ int agp_num_entries(void) | |||
295 | EXPORT_SYMBOL_GPL(agp_num_entries); | 295 | EXPORT_SYMBOL_GPL(agp_num_entries); |
296 | 296 | ||
297 | 297 | ||
298 | static int check_bridge_mode(struct pci_dev *dev) | ||
299 | { | ||
300 | u32 agp3; | ||
301 | u8 cap_ptr; | ||
302 | |||
303 | cap_ptr = pci_find_capability(dev, PCI_CAP_ID_AGP); | ||
304 | pci_read_config_dword(dev, cap_ptr+AGPSTAT, &agp3); | ||
305 | if (agp3 & AGPSTAT_MODE_3_0) | ||
306 | return 1; | ||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | |||
311 | /** | 298 | /** |
312 | * agp_copy_info - copy bridge state information | 299 | * agp_copy_info - copy bridge state information |
313 | * | 300 | * |
@@ -328,7 +315,7 @@ int agp_copy_info(struct agp_bridge_data *bridge, struct agp_kern_info *info) | |||
328 | info->version.minor = bridge->version->minor; | 315 | info->version.minor = bridge->version->minor; |
329 | info->chipset = SUPPORTED; | 316 | info->chipset = SUPPORTED; |
330 | info->device = bridge->dev; | 317 | info->device = bridge->dev; |
331 | if (check_bridge_mode(bridge->dev)) | 318 | if (bridge->mode & AGPSTAT_MODE_3_0) |
332 | info->mode = bridge->mode & ~AGP3_RESERVED_MASK; | 319 | info->mode = bridge->mode & ~AGP3_RESERVED_MASK; |
333 | else | 320 | else |
334 | info->mode = bridge->mode & ~AGP2_RESERVED_MASK; | 321 | info->mode = bridge->mode & ~AGP2_RESERVED_MASK; |
@@ -661,7 +648,7 @@ u32 agp_collect_device_status(struct agp_bridge_data *bridge, u32 requested_mode | |||
661 | bridge_agpstat &= ~AGPSTAT_FW; | 648 | bridge_agpstat &= ~AGPSTAT_FW; |
662 | 649 | ||
663 | /* Check to see if we are operating in 3.0 mode */ | 650 | /* Check to see if we are operating in 3.0 mode */ |
664 | if (check_bridge_mode(agp_bridge->dev)) | 651 | if (agp_bridge->mode & AGPSTAT_MODE_3_0) |
665 | agp_v3_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat); | 652 | agp_v3_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat); |
666 | else | 653 | else |
667 | agp_v2_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat); | 654 | agp_v2_parse_one(&requested_mode, &bridge_agpstat, &vga_agpstat); |
@@ -732,7 +719,7 @@ void agp_generic_enable(struct agp_bridge_data *bridge, u32 requested_mode) | |||
732 | 719 | ||
733 | /* Do AGP version specific frobbing. */ | 720 | /* Do AGP version specific frobbing. */ |
734 | if (bridge->major_version >= 3) { | 721 | if (bridge->major_version >= 3) { |
735 | if (check_bridge_mode(bridge->dev)) { | 722 | if (bridge->mode & AGPSTAT_MODE_3_0) { |
736 | /* If we have 3.5, we can do the isoch stuff. */ | 723 | /* If we have 3.5, we can do the isoch stuff. */ |
737 | if (bridge->minor_version >= 5) | 724 | if (bridge->minor_version >= 5) |
738 | agp_3_5_enable(bridge); | 725 | agp_3_5_enable(bridge); |
@@ -806,8 +793,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge) | |||
806 | break; | 793 | break; |
807 | } | 794 | } |
808 | 795 | ||
809 | table = (char *) __get_free_pages(GFP_KERNEL, | 796 | table = alloc_gatt_pages(page_order); |
810 | page_order); | ||
811 | 797 | ||
812 | if (table == NULL) { | 798 | if (table == NULL) { |
813 | i++; | 799 | i++; |
@@ -838,7 +824,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge) | |||
838 | size = ((struct aper_size_info_fixed *) temp)->size; | 824 | size = ((struct aper_size_info_fixed *) temp)->size; |
839 | page_order = ((struct aper_size_info_fixed *) temp)->page_order; | 825 | page_order = ((struct aper_size_info_fixed *) temp)->page_order; |
840 | num_entries = ((struct aper_size_info_fixed *) temp)->num_entries; | 826 | num_entries = ((struct aper_size_info_fixed *) temp)->num_entries; |
841 | table = (char *) __get_free_pages(GFP_KERNEL, page_order); | 827 | table = alloc_gatt_pages(page_order); |
842 | } | 828 | } |
843 | 829 | ||
844 | if (table == NULL) | 830 | if (table == NULL) |
@@ -853,7 +839,7 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge) | |||
853 | agp_gatt_table = (void *)table; | 839 | agp_gatt_table = (void *)table; |
854 | 840 | ||
855 | bridge->driver->cache_flush(); | 841 | bridge->driver->cache_flush(); |
856 | bridge->gatt_table = ioremap_nocache(virt_to_phys(table), | 842 | bridge->gatt_table = ioremap_nocache(virt_to_gart(table), |
857 | (PAGE_SIZE * (1 << page_order))); | 843 | (PAGE_SIZE * (1 << page_order))); |
858 | bridge->driver->cache_flush(); | 844 | bridge->driver->cache_flush(); |
859 | 845 | ||
@@ -861,11 +847,11 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge) | |||
861 | for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) | 847 | for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) |
862 | ClearPageReserved(page); | 848 | ClearPageReserved(page); |
863 | 849 | ||
864 | free_pages((unsigned long) table, page_order); | 850 | free_gatt_pages(table, page_order); |
865 | 851 | ||
866 | return -ENOMEM; | 852 | return -ENOMEM; |
867 | } | 853 | } |
868 | bridge->gatt_bus_addr = virt_to_phys(bridge->gatt_table_real); | 854 | bridge->gatt_bus_addr = virt_to_gart(bridge->gatt_table_real); |
869 | 855 | ||
870 | /* AK: bogus, should encode addresses > 4GB */ | 856 | /* AK: bogus, should encode addresses > 4GB */ |
871 | for (i = 0; i < num_entries; i++) { | 857 | for (i = 0; i < num_entries; i++) { |
@@ -919,7 +905,7 @@ int agp_generic_free_gatt_table(struct agp_bridge_data *bridge) | |||
919 | for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) | 905 | for (page = virt_to_page(table); page <= virt_to_page(table_end); page++) |
920 | ClearPageReserved(page); | 906 | ClearPageReserved(page); |
921 | 907 | ||
922 | free_pages((unsigned long) bridge->gatt_table_real, page_order); | 908 | free_gatt_pages(bridge->gatt_table_real, page_order); |
923 | 909 | ||
924 | agp_gatt_table = NULL; | 910 | agp_gatt_table = NULL; |
925 | bridge->gatt_table = NULL; | 911 | bridge->gatt_table = NULL; |
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c index 6052bfa04c72..99762b6c19ae 100644 --- a/drivers/char/agp/hp-agp.c +++ b/drivers/char/agp/hp-agp.c | |||
@@ -110,7 +110,7 @@ static int __init hp_zx1_ioc_shared(void) | |||
110 | hp->gart_size = HP_ZX1_GART_SIZE; | 110 | hp->gart_size = HP_ZX1_GART_SIZE; |
111 | hp->gatt_entries = hp->gart_size / hp->io_page_size; | 111 | hp->gatt_entries = hp->gart_size / hp->io_page_size; |
112 | 112 | ||
113 | hp->io_pdir = phys_to_virt(readq(hp->ioc_regs+HP_ZX1_PDIR_BASE)); | 113 | hp->io_pdir = gart_to_virt(readq(hp->ioc_regs+HP_ZX1_PDIR_BASE)); |
114 | hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)]; | 114 | hp->gatt = &hp->io_pdir[HP_ZX1_IOVA_TO_PDIR(hp->gart_base)]; |
115 | 115 | ||
116 | if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) { | 116 | if (hp->gatt[0] != HP_ZX1_SBA_IOMMU_COOKIE) { |
@@ -248,7 +248,7 @@ hp_zx1_configure (void) | |||
248 | agp_bridge->mode = readl(hp->lba_regs+hp->lba_cap_offset+PCI_AGP_STATUS); | 248 | agp_bridge->mode = readl(hp->lba_regs+hp->lba_cap_offset+PCI_AGP_STATUS); |
249 | 249 | ||
250 | if (hp->io_pdir_owner) { | 250 | if (hp->io_pdir_owner) { |
251 | writel(virt_to_phys(hp->io_pdir), hp->ioc_regs+HP_ZX1_PDIR_BASE); | 251 | writel(virt_to_gart(hp->io_pdir), hp->ioc_regs+HP_ZX1_PDIR_BASE); |
252 | readl(hp->ioc_regs+HP_ZX1_PDIR_BASE); | 252 | readl(hp->ioc_regs+HP_ZX1_PDIR_BASE); |
253 | writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG); | 253 | writel(hp->io_tlb_ps, hp->ioc_regs+HP_ZX1_TCNFG); |
254 | readl(hp->ioc_regs+HP_ZX1_TCNFG); | 254 | readl(hp->ioc_regs+HP_ZX1_TCNFG); |
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c index adbea896c0d2..94943298c03e 100644 --- a/drivers/char/agp/i460-agp.c +++ b/drivers/char/agp/i460-agp.c | |||
@@ -372,7 +372,7 @@ static int i460_alloc_large_page (struct lp_desc *lp) | |||
372 | } | 372 | } |
373 | memset(lp->alloced_map, 0, map_size); | 373 | memset(lp->alloced_map, 0, map_size); |
374 | 374 | ||
375 | lp->paddr = virt_to_phys(lpage); | 375 | lp->paddr = virt_to_gart(lpage); |
376 | lp->refcount = 0; | 376 | lp->refcount = 0; |
377 | atomic_add(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp); | 377 | atomic_add(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp); |
378 | return 0; | 378 | return 0; |
@@ -383,7 +383,7 @@ static void i460_free_large_page (struct lp_desc *lp) | |||
383 | kfree(lp->alloced_map); | 383 | kfree(lp->alloced_map); |
384 | lp->alloced_map = NULL; | 384 | lp->alloced_map = NULL; |
385 | 385 | ||
386 | free_pages((unsigned long) phys_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT); | 386 | free_pages((unsigned long) gart_to_virt(lp->paddr), I460_IO_PAGE_SHIFT - PAGE_SHIFT); |
387 | atomic_sub(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp); | 387 | atomic_sub(I460_KPAGES_PER_IOPAGE, &agp_bridge->current_memory_agp); |
388 | } | 388 | } |
389 | 389 | ||
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index 8c7d727432bb..51266d6b4d78 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c | |||
@@ -286,7 +286,7 @@ static struct agp_memory *alloc_agpphysmem_i8xx(size_t pg_count, int type) | |||
286 | if (new == NULL) | 286 | if (new == NULL) |
287 | return NULL; | 287 | return NULL; |
288 | 288 | ||
289 | new->memory[0] = virt_to_phys(addr); | 289 | new->memory[0] = virt_to_gart(addr); |
290 | if (pg_count == 4) { | 290 | if (pg_count == 4) { |
291 | /* kludge to get 4 physical pages for ARGB cursor */ | 291 | /* kludge to get 4 physical pages for ARGB cursor */ |
292 | new->memory[1] = new->memory[0] + PAGE_SIZE; | 292 | new->memory[1] = new->memory[0] + PAGE_SIZE; |
@@ -329,10 +329,10 @@ static void intel_i810_free_by_type(struct agp_memory *curr) | |||
329 | agp_free_key(curr->key); | 329 | agp_free_key(curr->key); |
330 | if(curr->type == AGP_PHYS_MEMORY) { | 330 | if(curr->type == AGP_PHYS_MEMORY) { |
331 | if (curr->page_count == 4) | 331 | if (curr->page_count == 4) |
332 | i8xx_destroy_pages(phys_to_virt(curr->memory[0])); | 332 | i8xx_destroy_pages(gart_to_virt(curr->memory[0])); |
333 | else | 333 | else |
334 | agp_bridge->driver->agp_destroy_page( | 334 | agp_bridge->driver->agp_destroy_page( |
335 | phys_to_virt(curr->memory[0])); | 335 | gart_to_virt(curr->memory[0])); |
336 | vfree(curr->memory); | 336 | vfree(curr->memory); |
337 | } | 337 | } |
338 | kfree(curr); | 338 | kfree(curr); |
@@ -418,7 +418,8 @@ static void intel_i830_init_gtt_entries(void) | |||
418 | case I915_GMCH_GMS_STOLEN_48M: | 418 | case I915_GMCH_GMS_STOLEN_48M: |
419 | /* Check it's really I915G */ | 419 | /* Check it's really I915G */ |
420 | if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || | 420 | if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || |
421 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) | 421 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || |
422 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB) | ||
422 | gtt_entries = MB(48) - KB(size); | 423 | gtt_entries = MB(48) - KB(size); |
423 | else | 424 | else |
424 | gtt_entries = 0; | 425 | gtt_entries = 0; |
@@ -426,7 +427,8 @@ static void intel_i830_init_gtt_entries(void) | |||
426 | case I915_GMCH_GMS_STOLEN_64M: | 427 | case I915_GMCH_GMS_STOLEN_64M: |
427 | /* Check it's really I915G */ | 428 | /* Check it's really I915G */ |
428 | if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || | 429 | if (agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915G_HB || |
429 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB) | 430 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82915GM_HB || |
431 | agp_bridge->dev->device == PCI_DEVICE_ID_INTEL_82945G_HB) | ||
430 | gtt_entries = MB(64) - KB(size); | 432 | gtt_entries = MB(64) - KB(size); |
431 | else | 433 | else |
432 | gtt_entries = 0; | 434 | gtt_entries = 0; |
@@ -1662,6 +1664,14 @@ static int __devinit agp_intel_probe(struct pci_dev *pdev, | |||
1662 | } | 1664 | } |
1663 | name = "915GM"; | 1665 | name = "915GM"; |
1664 | break; | 1666 | break; |
1667 | case PCI_DEVICE_ID_INTEL_82945G_HB: | ||
1668 | if (find_i830(PCI_DEVICE_ID_INTEL_82945G_IG)) { | ||
1669 | bridge->driver = &intel_915_driver; | ||
1670 | } else { | ||
1671 | bridge->driver = &intel_845_driver; | ||
1672 | } | ||
1673 | name = "945G"; | ||
1674 | break; | ||
1665 | case PCI_DEVICE_ID_INTEL_7505_0: | 1675 | case PCI_DEVICE_ID_INTEL_7505_0: |
1666 | bridge->driver = &intel_7505_driver; | 1676 | bridge->driver = &intel_7505_driver; |
1667 | name = "E7505"; | 1677 | name = "E7505"; |
@@ -1801,6 +1811,7 @@ static struct pci_device_id agp_intel_pci_table[] = { | |||
1801 | ID(PCI_DEVICE_ID_INTEL_7205_0), | 1811 | ID(PCI_DEVICE_ID_INTEL_7205_0), |
1802 | ID(PCI_DEVICE_ID_INTEL_82915G_HB), | 1812 | ID(PCI_DEVICE_ID_INTEL_82915G_HB), |
1803 | ID(PCI_DEVICE_ID_INTEL_82915GM_HB), | 1813 | ID(PCI_DEVICE_ID_INTEL_82915GM_HB), |
1814 | ID(PCI_DEVICE_ID_INTEL_82945G_HB), | ||
1804 | { } | 1815 | { } |
1805 | }; | 1816 | }; |
1806 | 1817 | ||
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c index 4b3eda267976..d3aa159c9dec 100644 --- a/drivers/char/agp/sgi-agp.c +++ b/drivers/char/agp/sgi-agp.c | |||
@@ -133,11 +133,14 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start, | |||
133 | off_t j; | 133 | off_t j; |
134 | void *temp; | 134 | void *temp; |
135 | struct agp_bridge_data *bridge; | 135 | struct agp_bridge_data *bridge; |
136 | u64 *table; | ||
136 | 137 | ||
137 | bridge = mem->bridge; | 138 | bridge = mem->bridge; |
138 | if (!bridge) | 139 | if (!bridge) |
139 | return -EINVAL; | 140 | return -EINVAL; |
140 | 141 | ||
142 | table = (u64 *)bridge->gatt_table; | ||
143 | |||
141 | temp = bridge->current_size; | 144 | temp = bridge->current_size; |
142 | 145 | ||
143 | switch (bridge->driver->size_type) { | 146 | switch (bridge->driver->size_type) { |
@@ -175,7 +178,7 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start, | |||
175 | j = pg_start; | 178 | j = pg_start; |
176 | 179 | ||
177 | while (j < (pg_start + mem->page_count)) { | 180 | while (j < (pg_start + mem->page_count)) { |
178 | if (*(bridge->gatt_table + j)) | 181 | if (table[j]) |
179 | return -EBUSY; | 182 | return -EBUSY; |
180 | j++; | 183 | j++; |
181 | } | 184 | } |
@@ -186,7 +189,7 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start, | |||
186 | } | 189 | } |
187 | 190 | ||
188 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { | 191 | for (i = 0, j = pg_start; i < mem->page_count; i++, j++) { |
189 | *(bridge->gatt_table + j) = | 192 | table[j] = |
190 | bridge->driver->mask_memory(bridge, mem->memory[i], | 193 | bridge->driver->mask_memory(bridge, mem->memory[i], |
191 | mem->type); | 194 | mem->type); |
192 | } | 195 | } |
@@ -200,6 +203,7 @@ static int sgi_tioca_remove_memory(struct agp_memory *mem, off_t pg_start, | |||
200 | { | 203 | { |
201 | size_t i; | 204 | size_t i; |
202 | struct agp_bridge_data *bridge; | 205 | struct agp_bridge_data *bridge; |
206 | u64 *table; | ||
203 | 207 | ||
204 | bridge = mem->bridge; | 208 | bridge = mem->bridge; |
205 | if (!bridge) | 209 | if (!bridge) |
@@ -209,8 +213,10 @@ static int sgi_tioca_remove_memory(struct agp_memory *mem, off_t pg_start, | |||
209 | return -EINVAL; | 213 | return -EINVAL; |
210 | } | 214 | } |
211 | 215 | ||
216 | table = (u64 *)bridge->gatt_table; | ||
217 | |||
212 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { | 218 | for (i = pg_start; i < (mem->page_count + pg_start); i++) { |
213 | *(bridge->gatt_table + i) = 0; | 219 | table[i] = 0; |
214 | } | 220 | } |
215 | 221 | ||
216 | bridge->driver->tlb_flush(mem); | 222 | bridge->driver->tlb_flush(mem); |
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index 10c23302dd84..a9fb12c20eb7 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c | |||
@@ -51,7 +51,7 @@ static int serverworks_create_page_map(struct serverworks_page_map *page_map) | |||
51 | } | 51 | } |
52 | SetPageReserved(virt_to_page(page_map->real)); | 52 | SetPageReserved(virt_to_page(page_map->real)); |
53 | global_cache_flush(); | 53 | global_cache_flush(); |
54 | page_map->remapped = ioremap_nocache(virt_to_phys(page_map->real), | 54 | page_map->remapped = ioremap_nocache(virt_to_gart(page_map->real), |
55 | PAGE_SIZE); | 55 | PAGE_SIZE); |
56 | if (page_map->remapped == NULL) { | 56 | if (page_map->remapped == NULL) { |
57 | ClearPageReserved(virt_to_page(page_map->real)); | 57 | ClearPageReserved(virt_to_page(page_map->real)); |
@@ -162,7 +162,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge) | |||
162 | /* Create a fake scratch directory */ | 162 | /* Create a fake scratch directory */ |
163 | for(i = 0; i < 1024; i++) { | 163 | for(i = 0; i < 1024; i++) { |
164 | writel(agp_bridge->scratch_page, serverworks_private.scratch_dir.remapped+i); | 164 | writel(agp_bridge->scratch_page, serverworks_private.scratch_dir.remapped+i); |
165 | writel(virt_to_phys(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i); | 165 | writel(virt_to_gart(serverworks_private.scratch_dir.real) | 1, page_dir.remapped+i); |
166 | } | 166 | } |
167 | 167 | ||
168 | retval = serverworks_create_gatt_pages(value->num_entries / 1024); | 168 | retval = serverworks_create_gatt_pages(value->num_entries / 1024); |
@@ -174,7 +174,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge) | |||
174 | 174 | ||
175 | agp_bridge->gatt_table_real = (u32 *)page_dir.real; | 175 | agp_bridge->gatt_table_real = (u32 *)page_dir.real; |
176 | agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped; | 176 | agp_bridge->gatt_table = (u32 __iomem *)page_dir.remapped; |
177 | agp_bridge->gatt_bus_addr = virt_to_phys(page_dir.real); | 177 | agp_bridge->gatt_bus_addr = virt_to_gart(page_dir.real); |
178 | 178 | ||
179 | /* Get the address for the gart region. | 179 | /* Get the address for the gart region. |
180 | * This is a bus address even on the alpha, b/c its | 180 | * This is a bus address even on the alpha, b/c its |
@@ -187,7 +187,7 @@ static int serverworks_create_gatt_table(struct agp_bridge_data *bridge) | |||
187 | /* Calculate the agp offset */ | 187 | /* Calculate the agp offset */ |
188 | 188 | ||
189 | for(i = 0; i < value->num_entries / 1024; i++) | 189 | for(i = 0; i < value->num_entries / 1024; i++) |
190 | writel(virt_to_phys(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i); | 190 | writel(virt_to_gart(serverworks_private.gatt_pages[i]->real)|1, page_dir.remapped+i); |
191 | 191 | ||
192 | return 0; | 192 | return 0; |
193 | } | 193 | } |
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index a673971f2a90..c8255312b8c1 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c | |||
@@ -407,7 +407,7 @@ static int uninorth_create_gatt_table(struct agp_bridge_data *bridge) | |||
407 | 407 | ||
408 | bridge->gatt_table_real = (u32 *) table; | 408 | bridge->gatt_table_real = (u32 *) table; |
409 | bridge->gatt_table = (u32 *)table; | 409 | bridge->gatt_table = (u32 *)table; |
410 | bridge->gatt_bus_addr = virt_to_phys(table); | 410 | bridge->gatt_bus_addr = virt_to_gart(table); |
411 | 411 | ||
412 | for (i = 0; i < num_entries; i++) | 412 | for (i = 0; i < num_entries; i++) |
413 | bridge->gatt_table[i] = 0; | 413 | bridge->gatt_table[i] = 0; |
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..c2b12eab67c9 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 |
diff --git a/drivers/char/drm/Makefile b/drivers/char/drm/Makefile index 23ab26321e9a..7444dec40b94 100644 --- a/drivers/char/drm/Makefile +++ b/drivers/char/drm/Makefile | |||
@@ -19,6 +19,11 @@ 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 | 21 | ||
22 | ifeq ($(CONFIG_COMPAT),y) | ||
23 | drm-objs += drm_ioc32.o | ||
24 | radeon-objs += radeon_ioc32.o | ||
25 | endif | ||
26 | |||
22 | obj-$(CONFIG_DRM) += drm.o | 27 | obj-$(CONFIG_DRM) += drm.o |
23 | obj-$(CONFIG_DRM_GAMMA) += gamma.o | 28 | obj-$(CONFIG_DRM_GAMMA) += gamma.o |
24 | obj-$(CONFIG_DRM_TDFX) += tdfx.o | 29 | obj-$(CONFIG_DRM_TDFX) += tdfx.o |
diff --git a/drivers/char/drm/drmP.h b/drivers/char/drm/drmP.h index 21f4c54e1a8d..b04ddf12a0ff 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; |
@@ -775,6 +778,8 @@ extern int drm_version(struct inode *inode, struct file *filp, | |||
775 | unsigned int cmd, unsigned long arg); | 778 | unsigned int cmd, unsigned long arg); |
776 | extern int drm_ioctl(struct inode *inode, struct file *filp, | 779 | extern int drm_ioctl(struct inode *inode, struct file *filp, |
777 | unsigned int cmd, unsigned long arg); | 780 | unsigned int cmd, unsigned long arg); |
781 | extern long drm_compat_ioctl(struct file *filp, | ||
782 | unsigned int cmd, unsigned long arg); | ||
778 | extern int drm_takedown(drm_device_t * dev); | 783 | extern int drm_takedown(drm_device_t * dev); |
779 | 784 | ||
780 | /* Device support (drm_fops.h) */ | 785 | /* Device support (drm_fops.h) */ |
diff --git a/drivers/char/drm/drm_bufs.c b/drivers/char/drm/drm_bufs.c index 4113bcba67fe..3407380b865a 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 | ||
diff --git a/drivers/char/drm/drm_context.c b/drivers/char/drm/drm_context.c index f15c86c57875..fdf661f234ed 100644 --- a/drivers/char/drm/drm_context.c +++ b/drivers/char/drm/drm_context.c | |||
@@ -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: |
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_pciids.h b/drivers/char/drm/drm_pciids.h index 54a2914e3a32..11c6950158b3 100644 --- a/drivers/char/drm/drm_pciids.h +++ b/drivers/char/drm/drm_pciids.h | |||
@@ -220,5 +220,6 @@ | |||
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}, \ | ||
223 | {0, 0, 0} | 224 | {0, 0, 0} |
224 | 225 | ||
diff --git a/drivers/char/drm/i915_dma.c b/drivers/char/drm/i915_dma.c index 7300a09dbd5c..b5903f9f1423 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" |
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..e6a9e1d1d283 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" |
diff --git a/drivers/char/drm/i915_drv.h b/drivers/char/drm/i915_drv.h index f6ca92a565db..fa940d64b85d 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_ |
diff --git a/drivers/char/drm/i915_irq.c b/drivers/char/drm/i915_irq.c index b0239262a84a..a101cc9cfd7e 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" |
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/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/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/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/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/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 49d67f5384a2..e0a53570fea1 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c | |||
@@ -44,6 +44,8 @@ | |||
44 | #include <linux/ipmi.h> | 44 | #include <linux/ipmi.h> |
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> | ||
48 | #include <linux/compat.h> | ||
47 | 49 | ||
48 | #define IPMI_DEVINTF_VERSION "v33" | 50 | #define IPMI_DEVINTF_VERSION "v33" |
49 | 51 | ||
@@ -499,10 +501,205 @@ static int ipmi_ioctl(struct inode *inode, | |||
499 | return rv; | 501 | return rv; |
500 | } | 502 | } |
501 | 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 | ||
502 | 696 | ||
503 | static struct file_operations ipmi_fops = { | 697 | static struct file_operations ipmi_fops = { |
504 | .owner = THIS_MODULE, | 698 | .owner = THIS_MODULE, |
505 | .ioctl = ipmi_ioctl, | 699 | .ioctl = ipmi_ioctl, |
700 | #ifdef CONFIG_COMPAT | ||
701 | .compat_ioctl = compat_ipmi_ioctl, | ||
702 | #endif | ||
506 | .open = ipmi_open, | 703 | .open = ipmi_open, |
507 | .release = ipmi_release, | 704 | .release = ipmi_release, |
508 | .fasync = ipmi_fasync, | 705 | .fasync = ipmi_fasync, |
@@ -519,15 +716,21 @@ MODULE_PARM_DESC(ipmi_major, "Sets the major number of the IPMI device. By" | |||
519 | " interface. Other values will set the major device number" | 716 | " interface. Other values will set the major device number" |
520 | " to that value."); | 717 | " to that value."); |
521 | 718 | ||
719 | static struct class *ipmi_class; | ||
720 | |||
522 | static void ipmi_new_smi(int if_num) | 721 | static void ipmi_new_smi(int if_num) |
523 | { | 722 | { |
524 | devfs_mk_cdev(MKDEV(ipmi_major, if_num), | 723 | dev_t dev = MKDEV(ipmi_major, if_num); |
525 | S_IFCHR | S_IRUSR | S_IWUSR, | 724 | |
725 | devfs_mk_cdev(dev, S_IFCHR | S_IRUSR | S_IWUSR, | ||
526 | "ipmidev/%d", if_num); | 726 | "ipmidev/%d", if_num); |
727 | |||
728 | class_device_create(ipmi_class, dev, NULL, "ipmi%d", if_num); | ||
527 | } | 729 | } |
528 | 730 | ||
529 | static void ipmi_smi_gone(int if_num) | 731 | static void ipmi_smi_gone(int if_num) |
530 | { | 732 | { |
733 | class_device_destroy(ipmi_class, MKDEV(ipmi_major, if_num)); | ||
531 | devfs_remove("ipmidev/%d", if_num); | 734 | devfs_remove("ipmidev/%d", if_num); |
532 | } | 735 | } |
533 | 736 | ||
@@ -548,8 +751,15 @@ static __init int init_ipmi_devintf(void) | |||
548 | printk(KERN_INFO "ipmi device interface version " | 751 | printk(KERN_INFO "ipmi device interface version " |
549 | IPMI_DEVINTF_VERSION "\n"); | 752 | IPMI_DEVINTF_VERSION "\n"); |
550 | 753 | ||
754 | ipmi_class = class_create(THIS_MODULE, "ipmi"); | ||
755 | if (IS_ERR(ipmi_class)) { | ||
756 | printk(KERN_ERR "ipmi: can't register device class\n"); | ||
757 | return PTR_ERR(ipmi_class); | ||
758 | } | ||
759 | |||
551 | rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops); | 760 | rv = register_chrdev(ipmi_major, DEVICE_NAME, &ipmi_fops); |
552 | if (rv < 0) { | 761 | if (rv < 0) { |
762 | class_destroy(ipmi_class); | ||
553 | 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); |
554 | return rv; | 764 | return rv; |
555 | } | 765 | } |
@@ -563,6 +773,7 @@ static __init int init_ipmi_devintf(void) | |||
563 | rv = ipmi_smi_watcher_register(&smi_watcher); | 773 | rv = ipmi_smi_watcher_register(&smi_watcher); |
564 | if (rv) { | 774 | if (rv) { |
565 | unregister_chrdev(ipmi_major, DEVICE_NAME); | 775 | unregister_chrdev(ipmi_major, DEVICE_NAME); |
776 | class_destroy(ipmi_class); | ||
566 | printk(KERN_WARNING "ipmi: can't register smi watcher\n"); | 777 | printk(KERN_WARNING "ipmi: can't register smi watcher\n"); |
567 | return rv; | 778 | return rv; |
568 | } | 779 | } |
@@ -573,6 +784,7 @@ module_init(init_ipmi_devintf); | |||
573 | 784 | ||
574 | static __exit void cleanup_ipmi(void) | 785 | static __exit void cleanup_ipmi(void) |
575 | { | 786 | { |
787 | class_destroy(ipmi_class); | ||
576 | ipmi_smi_watcher_unregister(&smi_watcher); | 788 | ipmi_smi_watcher_unregister(&smi_watcher); |
577 | devfs_remove(DEVICE_NAME); | 789 | devfs_remove(DEVICE_NAME); |
578 | 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..1813d0d198f1 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; |
@@ -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/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/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..42187381506b 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> |
@@ -273,6 +276,40 @@ static int mmap_kmem(struct file * file, struct vm_area_struct * vma) | |||
273 | return mmap_mem(file, vma); | 276 | return mmap_mem(file, vma); |
274 | } | 277 | } |
275 | 278 | ||
279 | #ifdef CONFIG_CRASH_DUMP | ||
280 | /* | ||
281 | * Read memory corresponding to the old kernel. | ||
282 | */ | ||
283 | static ssize_t read_oldmem(struct file *file, char __user *buf, | ||
284 | size_t count, loff_t *ppos) | ||
285 | { | ||
286 | unsigned long pfn, offset; | ||
287 | size_t read = 0, csize; | ||
288 | int rc = 0; | ||
289 | |||
290 | while (count) { | ||
291 | pfn = *ppos / PAGE_SIZE; | ||
292 | if (pfn > saved_max_pfn) | ||
293 | return read; | ||
294 | |||
295 | offset = (unsigned long)(*ppos % PAGE_SIZE); | ||
296 | if (count > PAGE_SIZE - offset) | ||
297 | csize = PAGE_SIZE - offset; | ||
298 | else | ||
299 | csize = count; | ||
300 | |||
301 | rc = copy_oldmem_page(pfn, buf, csize, offset, 1); | ||
302 | if (rc < 0) | ||
303 | return rc; | ||
304 | buf += csize; | ||
305 | *ppos += csize; | ||
306 | read += csize; | ||
307 | count -= csize; | ||
308 | } | ||
309 | return read; | ||
310 | } | ||
311 | #endif | ||
312 | |||
276 | extern long vread(char *buf, char *addr, unsigned long count); | 313 | extern long vread(char *buf, char *addr, unsigned long count); |
277 | extern long vwrite(char *buf, char *addr, unsigned long count); | 314 | extern long vwrite(char *buf, char *addr, unsigned long count); |
278 | 315 | ||
@@ -484,7 +521,7 @@ static ssize_t write_kmem(struct file * file, const char __user * buf, | |||
484 | return virtr + wrote; | 521 | return virtr + wrote; |
485 | } | 522 | } |
486 | 523 | ||
487 | #if defined(CONFIG_ISA) || !defined(__mc68000__) | 524 | #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, | 525 | static ssize_t read_port(struct file * file, char __user * buf, |
489 | size_t count, loff_t *ppos) | 526 | size_t count, loff_t *ppos) |
490 | { | 527 | { |
@@ -721,6 +758,7 @@ static int open_port(struct inode * inode, struct file * filp) | |||
721 | #define read_full read_zero | 758 | #define read_full read_zero |
722 | #define open_mem open_port | 759 | #define open_mem open_port |
723 | #define open_kmem open_mem | 760 | #define open_kmem open_mem |
761 | #define open_oldmem open_mem | ||
724 | 762 | ||
725 | static struct file_operations mem_fops = { | 763 | static struct file_operations mem_fops = { |
726 | .llseek = memory_lseek, | 764 | .llseek = memory_lseek, |
@@ -744,7 +782,7 @@ static struct file_operations null_fops = { | |||
744 | .write = write_null, | 782 | .write = write_null, |
745 | }; | 783 | }; |
746 | 784 | ||
747 | #if defined(CONFIG_ISA) || !defined(__mc68000__) | 785 | #if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI)) |
748 | static struct file_operations port_fops = { | 786 | static struct file_operations port_fops = { |
749 | .llseek = memory_lseek, | 787 | .llseek = memory_lseek, |
750 | .read = read_port, | 788 | .read = read_port, |
@@ -770,6 +808,13 @@ static struct file_operations full_fops = { | |||
770 | .write = write_full, | 808 | .write = write_full, |
771 | }; | 809 | }; |
772 | 810 | ||
811 | #ifdef CONFIG_CRASH_DUMP | ||
812 | static struct file_operations oldmem_fops = { | ||
813 | .read = read_oldmem, | ||
814 | .open = open_oldmem, | ||
815 | }; | ||
816 | #endif | ||
817 | |||
773 | static ssize_t kmsg_write(struct file * file, const char __user * buf, | 818 | static ssize_t kmsg_write(struct file * file, const char __user * buf, |
774 | size_t count, loff_t *ppos) | 819 | size_t count, loff_t *ppos) |
775 | { | 820 | { |
@@ -804,7 +849,7 @@ static int memory_open(struct inode * inode, struct file * filp) | |||
804 | case 3: | 849 | case 3: |
805 | filp->f_op = &null_fops; | 850 | filp->f_op = &null_fops; |
806 | break; | 851 | break; |
807 | #if defined(CONFIG_ISA) || !defined(__mc68000__) | 852 | #if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI)) |
808 | case 4: | 853 | case 4: |
809 | filp->f_op = &port_fops; | 854 | filp->f_op = &port_fops; |
810 | break; | 855 | break; |
@@ -825,6 +870,11 @@ static int memory_open(struct inode * inode, struct file * filp) | |||
825 | case 11: | 870 | case 11: |
826 | filp->f_op = &kmsg_fops; | 871 | filp->f_op = &kmsg_fops; |
827 | break; | 872 | break; |
873 | #ifdef CONFIG_CRASH_DUMP | ||
874 | case 12: | ||
875 | filp->f_op = &oldmem_fops; | ||
876 | break; | ||
877 | #endif | ||
828 | default: | 878 | default: |
829 | return -ENXIO; | 879 | return -ENXIO; |
830 | } | 880 | } |
@@ -846,7 +896,7 @@ static const struct { | |||
846 | {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, | 896 | {1, "mem", S_IRUSR | S_IWUSR | S_IRGRP, &mem_fops}, |
847 | {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, | 897 | {2, "kmem", S_IRUSR | S_IWUSR | S_IRGRP, &kmem_fops}, |
848 | {3, "null", S_IRUGO | S_IWUGO, &null_fops}, | 898 | {3, "null", S_IRUGO | S_IWUGO, &null_fops}, |
849 | #if defined(CONFIG_ISA) || !defined(__mc68000__) | 899 | #if (defined(CONFIG_ISA) || !defined(__mc68000__)) && (!defined(CONFIG_PPC_ISERIES) || defined(CONFIG_PCI)) |
850 | {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops}, | 900 | {4, "port", S_IRUSR | S_IWUSR | S_IRGRP, &port_fops}, |
851 | #endif | 901 | #endif |
852 | {5, "zero", S_IRUGO | S_IWUGO, &zero_fops}, | 902 | {5, "zero", S_IRUGO | S_IWUGO, &zero_fops}, |
@@ -854,9 +904,12 @@ static const struct { | |||
854 | {8, "random", S_IRUGO | S_IWUSR, &random_fops}, | 904 | {8, "random", S_IRUGO | S_IWUSR, &random_fops}, |
855 | {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops}, | 905 | {9, "urandom", S_IRUGO | S_IWUSR, &urandom_fops}, |
856 | {11,"kmsg", S_IRUGO | S_IWUSR, &kmsg_fops}, | 906 | {11,"kmsg", S_IRUGO | S_IWUSR, &kmsg_fops}, |
907 | #ifdef CONFIG_CRASH_DUMP | ||
908 | {12,"oldmem", S_IRUSR | S_IWUSR | S_IRGRP, &oldmem_fops}, | ||
909 | #endif | ||
857 | }; | 910 | }; |
858 | 911 | ||
859 | static struct class_simple *mem_class; | 912 | static struct class *mem_class; |
860 | 913 | ||
861 | static int __init chr_dev_init(void) | 914 | static int __init chr_dev_init(void) |
862 | { | 915 | { |
@@ -865,10 +918,9 @@ static int __init chr_dev_init(void) | |||
865 | if (register_chrdev(MEM_MAJOR,"mem",&memory_fops)) | 918 | if (register_chrdev(MEM_MAJOR,"mem",&memory_fops)) |
866 | printk("unable to get major %d for memory devs\n", MEM_MAJOR); | 919 | printk("unable to get major %d for memory devs\n", MEM_MAJOR); |
867 | 920 | ||
868 | mem_class = class_simple_create(THIS_MODULE, "mem"); | 921 | mem_class = class_create(THIS_MODULE, "mem"); |
869 | for (i = 0; i < ARRAY_SIZE(devlist); i++) { | 922 | for (i = 0; i < ARRAY_SIZE(devlist); i++) { |
870 | class_simple_device_add(mem_class, | 923 | class_device_create(mem_class, MKDEV(MEM_MAJOR, devlist[i].minor), |
871 | MKDEV(MEM_MAJOR, devlist[i].minor), | ||
872 | NULL, devlist[i].name); | 924 | NULL, devlist[i].name); |
873 | devfs_mk_cdev(MKDEV(MEM_MAJOR, devlist[i].minor), | 925 | devfs_mk_cdev(MKDEV(MEM_MAJOR, devlist[i].minor), |
874 | S_IFCHR | devlist[i].mode, devlist[i].name); | 926 | S_IFCHR | devlist[i].mode, devlist[i].name); |
diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 0937544762da..31cf84d69026 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 |
@@ -314,16 +312,10 @@ static int __init misc_init(void) | |||
314 | #ifdef CONFIG_PMAC_PBOOK | 312 | #ifdef CONFIG_PMAC_PBOOK |
315 | pmu_device_init(); | 313 | pmu_device_init(); |
316 | #endif | 314 | #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)) { | 315 | if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) { |
324 | printk("unable to get major %d for misc devices\n", | 316 | printk("unable to get major %d for misc devices\n", |
325 | MISC_MAJOR); | 317 | MISC_MAJOR); |
326 | class_simple_destroy(misc_class); | 318 | class_destroy(misc_class); |
327 | return -EIO; | 319 | return -EIO; |
328 | } | 320 | } |
329 | return 0; | 321 | return 0; |
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/mxser.c b/drivers/char/mxser.c index 7a245068e3e5..f022f0944434 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
@@ -1995,9 +1995,6 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status) | |||
1995 | unsigned char ch, gdl; | 1995 | unsigned char ch, gdl; |
1996 | int ignored = 0; | 1996 | int ignored = 0; |
1997 | int cnt = 0; | 1997 | int cnt = 0; |
1998 | unsigned char *cp; | ||
1999 | char *fp; | ||
2000 | int count; | ||
2001 | int recv_room; | 1998 | int recv_room; |
2002 | int max = 256; | 1999 | int max = 256; |
2003 | unsigned long flags; | 2000 | unsigned long flags; |
@@ -2011,10 +2008,6 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status) | |||
2011 | //return; | 2008 | //return; |
2012 | } | 2009 | } |
2013 | 2010 | ||
2014 | cp = tty->flip.char_buf; | ||
2015 | fp = tty->flip.flag_buf; | ||
2016 | count = 0; | ||
2017 | |||
2018 | // following add by Victor Yu. 09-02-2002 | 2011 | // following add by Victor Yu. 09-02-2002 |
2019 | if (info->IsMoxaMustChipFlag != MOXA_OTHER_UART) { | 2012 | if (info->IsMoxaMustChipFlag != MOXA_OTHER_UART) { |
2020 | 2013 | ||
@@ -2041,12 +2034,10 @@ static void mxser_receive_chars(struct mxser_struct *info, int *status) | |||
2041 | } | 2034 | } |
2042 | while (gdl--) { | 2035 | while (gdl--) { |
2043 | ch = inb(info->base + UART_RX); | 2036 | ch = inb(info->base + UART_RX); |
2044 | count++; | 2037 | tty_insert_flip_char(tty, ch, 0); |
2045 | *cp++ = ch; | ||
2046 | *fp++ = 0; | ||
2047 | cnt++; | 2038 | cnt++; |
2048 | /* | 2039 | /* |
2049 | if((count>=HI_WATER) && (info->stop_rx==0)){ | 2040 | if((cnt>=HI_WATER) && (info->stop_rx==0)){ |
2050 | mxser_stoprx(tty); | 2041 | mxser_stoprx(tty); |
2051 | info->stop_rx=1; | 2042 | info->stop_rx=1; |
2052 | break; | 2043 | break; |
@@ -2061,7 +2052,7 @@ intr_old: | |||
2061 | if (max-- < 0) | 2052 | if (max-- < 0) |
2062 | break; | 2053 | break; |
2063 | /* | 2054 | /* |
2064 | if((count>=HI_WATER) && (info->stop_rx==0)){ | 2055 | if((cnt>=HI_WATER) && (info->stop_rx==0)){ |
2065 | mxser_stoprx(tty); | 2056 | mxser_stoprx(tty); |
2066 | info->stop_rx=1; | 2057 | info->stop_rx=1; |
2067 | break; | 2058 | break; |
@@ -2078,36 +2069,33 @@ intr_old: | |||
2078 | if (++ignored > 100) | 2069 | if (++ignored > 100) |
2079 | break; | 2070 | break; |
2080 | } else { | 2071 | } else { |
2081 | count++; | 2072 | char flag = 0; |
2082 | if (*status & UART_LSR_SPECIAL) { | 2073 | if (*status & UART_LSR_SPECIAL) { |
2083 | if (*status & UART_LSR_BI) { | 2074 | if (*status & UART_LSR_BI) { |
2084 | *fp++ = TTY_BREAK; | 2075 | flag = TTY_BREAK; |
2085 | /* added by casper 1/11/2000 */ | 2076 | /* added by casper 1/11/2000 */ |
2086 | info->icount.brk++; | 2077 | info->icount.brk++; |
2087 | |||
2088 | /* */ | 2078 | /* */ |
2089 | if (info->flags & ASYNC_SAK) | 2079 | if (info->flags & ASYNC_SAK) |
2090 | do_SAK(tty); | 2080 | do_SAK(tty); |
2091 | } else if (*status & UART_LSR_PE) { | 2081 | } else if (*status & UART_LSR_PE) { |
2092 | *fp++ = TTY_PARITY; | 2082 | flag = TTY_PARITY; |
2093 | /* added by casper 1/11/2000 */ | 2083 | /* added by casper 1/11/2000 */ |
2094 | info->icount.parity++; | 2084 | info->icount.parity++; |
2095 | /* */ | 2085 | /* */ |
2096 | } else if (*status & UART_LSR_FE) { | 2086 | } else if (*status & UART_LSR_FE) { |
2097 | *fp++ = TTY_FRAME; | 2087 | flag = TTY_FRAME; |
2098 | /* added by casper 1/11/2000 */ | 2088 | /* added by casper 1/11/2000 */ |
2099 | info->icount.frame++; | 2089 | info->icount.frame++; |
2100 | /* */ | 2090 | /* */ |
2101 | } else if (*status & UART_LSR_OE) { | 2091 | } else if (*status & UART_LSR_OE) { |
2102 | *fp++ = TTY_OVERRUN; | 2092 | flag = TTY_OVERRUN; |
2103 | /* added by casper 1/11/2000 */ | 2093 | /* added by casper 1/11/2000 */ |
2104 | info->icount.overrun++; | 2094 | info->icount.overrun++; |
2105 | /* */ | 2095 | /* */ |
2106 | } else | 2096 | } |
2107 | *fp++ = 0; | 2097 | } |
2108 | } else | 2098 | tty_insert_flip_char(tty, ch, flag); |
2109 | *fp++ = 0; | ||
2110 | *cp++ = ch; | ||
2111 | cnt++; | 2099 | cnt++; |
2112 | if (cnt >= recv_room) { | 2100 | if (cnt >= recv_room) { |
2113 | if (!info->ldisc_stop_rx) { | 2101 | if (!info->ldisc_stop_rx) { |
@@ -2132,13 +2120,13 @@ intr_old: | |||
2132 | // above add by Victor Yu. 09-02-2002 | 2120 | // above add by Victor Yu. 09-02-2002 |
2133 | } while (*status & UART_LSR_DR); | 2121 | } while (*status & UART_LSR_DR); |
2134 | 2122 | ||
2135 | end_intr: // add by Victor Yu. 09-02-2002 | 2123 | end_intr: // add by Victor Yu. 09-02-2002 |
2136 | 2124 | ||
2137 | mxvar_log.rxcnt[info->port] += cnt; | 2125 | mxvar_log.rxcnt[info->port] += cnt; |
2138 | info->mon_data.rxcnt += cnt; | 2126 | info->mon_data.rxcnt += cnt; |
2139 | info->mon_data.up_rxcnt += cnt; | 2127 | info->mon_data.up_rxcnt += cnt; |
2140 | spin_unlock_irqrestore(&info->slock, flags); | 2128 | spin_unlock_irqrestore(&info->slock, flags); |
2141 | 2129 | ||
2142 | tty_flip_buffer_push(tty); | 2130 | tty_flip_buffer_push(tty); |
2143 | } | 2131 | } |
2144 | 2132 | ||
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/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/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/raw.c b/drivers/char/raw.c index a2e33ec79615..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 */ |
@@ -122,13 +122,13 @@ raw_ioctl(struct inode *inode, struct file *filp, | |||
122 | { | 122 | { |
123 | struct block_device *bdev = filp->private_data; | 123 | struct block_device *bdev = filp->private_data; |
124 | 124 | ||
125 | return ioctl_by_bdev(bdev, command, arg); | 125 | return blkdev_ioctl(bdev->bd_inode, NULL, command, arg); |
126 | } | 126 | } |
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..7db3370f4972 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; |
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/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..f463d6baa685 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"); |
@@ -1798,7 +1876,7 @@ static void rp_flush_buffer(struct tty_struct *tty) | |||
1798 | * init's aiopic and serial port hardware. | 1876 | * init's aiopic and serial port hardware. |
1799 | * Inputs: i is the board number (0-n) | 1877 | * Inputs: i is the board number (0-n) |
1800 | */ | 1878 | */ |
1801 | __init int register_PCI(int i, struct pci_dev *dev) | 1879 | static __init int register_PCI(int i, struct pci_dev *dev) |
1802 | { | 1880 | { |
1803 | int num_aiops, aiop, max_num_aiops, num_chan, chan; | 1881 | int num_aiops, aiop, max_num_aiops, num_chan, chan; |
1804 | unsigned int aiopio[MAX_AIOPS_PER_BOARD]; | 1882 | unsigned int aiopio[MAX_AIOPS_PER_BOARD]; |
@@ -2453,72 +2531,6 @@ static void rp_cleanup_module(void) | |||
2453 | } | 2531 | } |
2454 | #endif | 2532 | #endif |
2455 | 2533 | ||
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 | /*************************************************************************** | 2534 | /*************************************************************************** |
2523 | Function: sInitController | 2535 | Function: sInitController |
2524 | Purpose: Initialization of controller global registers and controller | 2536 | Purpose: Initialization of controller global registers and controller |
@@ -2554,22 +2566,22 @@ Call: sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize, | |||
2554 | FREQ_4HZ - 4 Hertz | 2566 | FREQ_4HZ - 4 Hertz |
2555 | If IRQNum is set to 0 the Frequency parameter is | 2567 | If IRQNum is set to 0 the Frequency parameter is |
2556 | overidden, it is forced to a value of FREQ_DIS. | 2568 | overidden, it is forced to a value of FREQ_DIS. |
2557 | int PeriodicOnly: TRUE if all interrupts except the periodic | 2569 | int PeriodicOnly: 1 if all interrupts except the periodic |
2558 | interrupt are to be blocked. | 2570 | interrupt are to be blocked. |
2559 | FALSE is both the periodic interrupt and | 2571 | 0 is both the periodic interrupt and |
2560 | other channel interrupts are allowed. | 2572 | other channel interrupts are allowed. |
2561 | If IRQNum is set to 0 the PeriodicOnly parameter is | 2573 | If IRQNum is set to 0 the PeriodicOnly parameter is |
2562 | overidden, it is forced to a value of FALSE. | 2574 | overidden, it is forced to a value of 0. |
2563 | Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller | 2575 | Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller |
2564 | initialization failed. | 2576 | initialization failed. |
2565 | 2577 | ||
2566 | Comments: | 2578 | Comments: |
2567 | If periodic interrupts are to be disabled but AIOP interrupts | 2579 | If periodic interrupts are to be disabled but AIOP interrupts |
2568 | are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE. | 2580 | are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0. |
2569 | 2581 | ||
2570 | If interrupts are to be completely disabled set IRQNum to 0. | 2582 | If interrupts are to be completely disabled set IRQNum to 0. |
2571 | 2583 | ||
2572 | Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an | 2584 | Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an |
2573 | invalid combination. | 2585 | invalid combination. |
2574 | 2586 | ||
2575 | This function performs initialization of global interrupt modes, | 2587 | This function performs initialization of global interrupt modes, |
@@ -2589,9 +2601,9 @@ Warnings: No range checking on any of the parameters is done. | |||
2589 | After this function all AIOPs on the controller are disabled, | 2601 | After this function all AIOPs on the controller are disabled, |
2590 | they can be enabled with sEnAiop(). | 2602 | they can be enabled with sEnAiop(). |
2591 | */ | 2603 | */ |
2592 | int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO, | 2604 | static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO, |
2593 | ByteIO_t * AiopIOList, int AiopIOListSize, int IRQNum, | 2605 | ByteIO_t * AiopIOList, int AiopIOListSize, |
2594 | Byte_t Frequency, int PeriodicOnly) | 2606 | int IRQNum, Byte_t Frequency, int PeriodicOnly) |
2595 | { | 2607 | { |
2596 | int i; | 2608 | int i; |
2597 | ByteIO_t io; | 2609 | ByteIO_t io; |
@@ -2687,22 +2699,22 @@ Call: sPCIInitController(CtlP,CtlNum,AiopIOList,AiopIOListSize, | |||
2687 | FREQ_4HZ - 4 Hertz | 2699 | FREQ_4HZ - 4 Hertz |
2688 | If IRQNum is set to 0 the Frequency parameter is | 2700 | If IRQNum is set to 0 the Frequency parameter is |
2689 | overidden, it is forced to a value of FREQ_DIS. | 2701 | overidden, it is forced to a value of FREQ_DIS. |
2690 | int PeriodicOnly: TRUE if all interrupts except the periodic | 2702 | int PeriodicOnly: 1 if all interrupts except the periodic |
2691 | interrupt are to be blocked. | 2703 | interrupt are to be blocked. |
2692 | FALSE is both the periodic interrupt and | 2704 | 0 is both the periodic interrupt and |
2693 | other channel interrupts are allowed. | 2705 | other channel interrupts are allowed. |
2694 | If IRQNum is set to 0 the PeriodicOnly parameter is | 2706 | If IRQNum is set to 0 the PeriodicOnly parameter is |
2695 | overidden, it is forced to a value of FALSE. | 2707 | overidden, it is forced to a value of 0. |
2696 | Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller | 2708 | Return: int: Number of AIOPs on the controller, or CTLID_NULL if controller |
2697 | initialization failed. | 2709 | initialization failed. |
2698 | 2710 | ||
2699 | Comments: | 2711 | Comments: |
2700 | If periodic interrupts are to be disabled but AIOP interrupts | 2712 | If periodic interrupts are to be disabled but AIOP interrupts |
2701 | are allowed, set Frequency to FREQ_DIS and PeriodicOnly to FALSE. | 2713 | are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0. |
2702 | 2714 | ||
2703 | If interrupts are to be completely disabled set IRQNum to 0. | 2715 | If interrupts are to be completely disabled set IRQNum to 0. |
2704 | 2716 | ||
2705 | Setting Frequency to FREQ_DIS and PeriodicOnly to TRUE is an | 2717 | Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an |
2706 | invalid combination. | 2718 | invalid combination. |
2707 | 2719 | ||
2708 | This function performs initialization of global interrupt modes, | 2720 | This function performs initialization of global interrupt modes, |
@@ -2722,11 +2734,11 @@ Warnings: No range checking on any of the parameters is done. | |||
2722 | After this function all AIOPs on the controller are disabled, | 2734 | After this function all AIOPs on the controller are disabled, |
2723 | they can be enabled with sEnAiop(). | 2735 | they can be enabled with sEnAiop(). |
2724 | */ | 2736 | */ |
2725 | int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum, | 2737 | static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum, |
2726 | ByteIO_t * AiopIOList, int AiopIOListSize, | 2738 | ByteIO_t * AiopIOList, int AiopIOListSize, |
2727 | WordIO_t ConfigIO, int IRQNum, Byte_t Frequency, | 2739 | WordIO_t ConfigIO, int IRQNum, Byte_t Frequency, |
2728 | int PeriodicOnly, int altChanRingIndicator, | 2740 | int PeriodicOnly, int altChanRingIndicator, |
2729 | int UPCIRingInd) | 2741 | int UPCIRingInd) |
2730 | { | 2742 | { |
2731 | int i; | 2743 | int i; |
2732 | ByteIO_t io; | 2744 | ByteIO_t io; |
@@ -2784,7 +2796,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. | 2796 | Warnings: No context switches are allowed while executing this function. |
2785 | 2797 | ||
2786 | */ | 2798 | */ |
2787 | int sReadAiopID(ByteIO_t io) | 2799 | static int sReadAiopID(ByteIO_t io) |
2788 | { | 2800 | { |
2789 | Byte_t AiopID; /* ID byte from AIOP */ | 2801 | Byte_t AiopID; /* ID byte from AIOP */ |
2790 | 2802 | ||
@@ -2810,7 +2822,7 @@ Comments: The number of channels is determined by write/reads from identical | |||
2810 | AIOP, otherwise it is an 8 channel. | 2822 | AIOP, otherwise it is an 8 channel. |
2811 | Warnings: No context switches are allowed while executing this function. | 2823 | Warnings: No context switches are allowed while executing this function. |
2812 | */ | 2824 | */ |
2813 | int sReadAiopNumChan(WordIO_t io) | 2825 | static int sReadAiopNumChan(WordIO_t io) |
2814 | { | 2826 | { |
2815 | Word_t x; | 2827 | Word_t x; |
2816 | static Byte_t R[4] = { 0x00, 0x00, 0x34, 0x12 }; | 2828 | static Byte_t R[4] = { 0x00, 0x00, 0x34, 0x12 }; |
@@ -2834,15 +2846,15 @@ Call: sInitChan(CtlP,ChP,AiopNum,ChanNum) | |||
2834 | CHANNEL_T *ChP; Ptr to channel structure | 2846 | CHANNEL_T *ChP; Ptr to channel structure |
2835 | int AiopNum; AIOP number within controller | 2847 | int AiopNum; AIOP number within controller |
2836 | int ChanNum; Channel number within AIOP | 2848 | int ChanNum; Channel number within AIOP |
2837 | Return: int: TRUE if initialization succeeded, FALSE if it fails because channel | 2849 | Return: int: 1 if initialization succeeded, 0 if it fails because channel |
2838 | number exceeds number of channels available in AIOP. | 2850 | number exceeds number of channels available in AIOP. |
2839 | Comments: This function must be called before a channel can be used. | 2851 | Comments: This function must be called before a channel can be used. |
2840 | Warnings: No range checking on any of the parameters is done. | 2852 | Warnings: No range checking on any of the parameters is done. |
2841 | 2853 | ||
2842 | No context switches are allowed while executing this function. | 2854 | No context switches are allowed while executing this function. |
2843 | */ | 2855 | */ |
2844 | int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum, | 2856 | static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum, |
2845 | int ChanNum) | 2857 | int ChanNum) |
2846 | { | 2858 | { |
2847 | int i; | 2859 | int i; |
2848 | WordIO_t AiopIO; | 2860 | WordIO_t AiopIO; |
@@ -2853,7 +2865,7 @@ int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum, | |||
2853 | int brd9600; | 2865 | int brd9600; |
2854 | 2866 | ||
2855 | if (ChanNum >= CtlP->AiopNumChan[AiopNum]) | 2867 | if (ChanNum >= CtlP->AiopNumChan[AiopNum]) |
2856 | return (FALSE); /* exceeds num chans in AIOP */ | 2868 | return 0; /* exceeds num chans in AIOP */ |
2857 | 2869 | ||
2858 | /* Channel, AIOP, and controller identifiers */ | 2870 | /* Channel, AIOP, and controller identifiers */ |
2859 | ChP->CtlP = CtlP; | 2871 | ChP->CtlP = CtlP; |
@@ -2968,7 +2980,7 @@ int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum, | |||
2968 | ChP->TxPrioBuf = ChOff + _TXP_BUF; | 2980 | ChP->TxPrioBuf = ChOff + _TXP_BUF; |
2969 | sEnRxProcessor(ChP); /* start the Rx processor */ | 2981 | sEnRxProcessor(ChP); /* start the Rx processor */ |
2970 | 2982 | ||
2971 | return (TRUE); | 2983 | return 1; |
2972 | } | 2984 | } |
2973 | 2985 | ||
2974 | /*************************************************************************** | 2986 | /*************************************************************************** |
@@ -2989,7 +3001,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 | 3001 | After calling this function a delay of 4 uS is required to ensure |
2990 | that the receive processor is no longer processing this channel. | 3002 | that the receive processor is no longer processing this channel. |
2991 | */ | 3003 | */ |
2992 | void sStopRxProcessor(CHANNEL_T * ChP) | 3004 | static void sStopRxProcessor(CHANNEL_T * ChP) |
2993 | { | 3005 | { |
2994 | Byte_t R[4]; | 3006 | Byte_t R[4]; |
2995 | 3007 | ||
@@ -3014,18 +3026,18 @@ Comments: To prevent data from being enqueued or dequeued in the Tx FIFO | |||
3014 | this function. | 3026 | this function. |
3015 | Warnings: No context switches are allowed while executing this function. | 3027 | Warnings: No context switches are allowed while executing this function. |
3016 | */ | 3028 | */ |
3017 | void sFlushRxFIFO(CHANNEL_T * ChP) | 3029 | static void sFlushRxFIFO(CHANNEL_T * ChP) |
3018 | { | 3030 | { |
3019 | int i; | 3031 | int i; |
3020 | Byte_t Ch; /* channel number within AIOP */ | 3032 | Byte_t Ch; /* channel number within AIOP */ |
3021 | int RxFIFOEnabled; /* TRUE if Rx FIFO enabled */ | 3033 | int RxFIFOEnabled; /* 1 if Rx FIFO enabled */ |
3022 | 3034 | ||
3023 | if (sGetRxCnt(ChP) == 0) /* Rx FIFO empty */ | 3035 | if (sGetRxCnt(ChP) == 0) /* Rx FIFO empty */ |
3024 | return; /* don't need to flush */ | 3036 | return; /* don't need to flush */ |
3025 | 3037 | ||
3026 | RxFIFOEnabled = FALSE; | 3038 | RxFIFOEnabled = 0; |
3027 | if (ChP->R[0x32] == 0x08) { /* Rx FIFO is enabled */ | 3039 | if (ChP->R[0x32] == 0x08) { /* Rx FIFO is enabled */ |
3028 | RxFIFOEnabled = TRUE; | 3040 | RxFIFOEnabled = 1; |
3029 | sDisRxFIFO(ChP); /* disable it */ | 3041 | sDisRxFIFO(ChP); /* disable it */ |
3030 | for (i = 0; i < 2000 / 200; i++) /* delay 2 uS to allow proc to disable FIFO */ | 3042 | 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 */ | 3043 | sInB(ChP->IntChan); /* depends on bus i/o timing */ |
@@ -3056,18 +3068,18 @@ Comments: To prevent data from being enqueued or dequeued in the Tx FIFO | |||
3056 | this function. | 3068 | this function. |
3057 | Warnings: No context switches are allowed while executing this function. | 3069 | Warnings: No context switches are allowed while executing this function. |
3058 | */ | 3070 | */ |
3059 | void sFlushTxFIFO(CHANNEL_T * ChP) | 3071 | static void sFlushTxFIFO(CHANNEL_T * ChP) |
3060 | { | 3072 | { |
3061 | int i; | 3073 | int i; |
3062 | Byte_t Ch; /* channel number within AIOP */ | 3074 | Byte_t Ch; /* channel number within AIOP */ |
3063 | int TxEnabled; /* TRUE if transmitter enabled */ | 3075 | int TxEnabled; /* 1 if transmitter enabled */ |
3064 | 3076 | ||
3065 | if (sGetTxCnt(ChP) == 0) /* Tx FIFO empty */ | 3077 | if (sGetTxCnt(ChP) == 0) /* Tx FIFO empty */ |
3066 | return; /* don't need to flush */ | 3078 | return; /* don't need to flush */ |
3067 | 3079 | ||
3068 | TxEnabled = FALSE; | 3080 | TxEnabled = 0; |
3069 | if (ChP->TxControl[3] & TX_ENABLE) { | 3081 | if (ChP->TxControl[3] & TX_ENABLE) { |
3070 | TxEnabled = TRUE; | 3082 | TxEnabled = 1; |
3071 | sDisTransmit(ChP); /* disable transmitter */ | 3083 | sDisTransmit(ChP); /* disable transmitter */ |
3072 | } | 3084 | } |
3073 | sStopRxProcessor(ChP); /* stop Rx processor */ | 3085 | sStopRxProcessor(ChP); /* stop Rx processor */ |
@@ -3096,7 +3108,7 @@ Comments: The priority byte is transmitted before any data in the Tx FIFO. | |||
3096 | 3108 | ||
3097 | Warnings: No context switches are allowed while executing this function. | 3109 | Warnings: No context switches are allowed while executing this function. |
3098 | */ | 3110 | */ |
3099 | int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data) | 3111 | static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data) |
3100 | { | 3112 | { |
3101 | Byte_t DWBuf[4]; /* buffer for double word writes */ | 3113 | Byte_t DWBuf[4]; /* buffer for double word writes */ |
3102 | Word_t *WordPtr; /* must be far because Win SS != DS */ | 3114 | Word_t *WordPtr; /* must be far because Win SS != DS */ |
@@ -3158,7 +3170,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 | 3170 | enable channel interrupts. This would allow the global interrupt |
3159 | status register to be used to determine which AIOPs need service. | 3171 | status register to be used to determine which AIOPs need service. |
3160 | */ | 3172 | */ |
3161 | void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags) | 3173 | static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags) |
3162 | { | 3174 | { |
3163 | Byte_t Mask; /* Interrupt Mask Register */ | 3175 | Byte_t Mask; /* Interrupt Mask Register */ |
3164 | 3176 | ||
@@ -3202,7 +3214,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 | 3214 | this channel's bit from being set in the AIOP's Interrupt Channel |
3203 | Register. | 3215 | Register. |
3204 | */ | 3216 | */ |
3205 | void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags) | 3217 | static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags) |
3206 | { | 3218 | { |
3207 | Byte_t Mask; /* Interrupt Mask Register */ | 3219 | Byte_t Mask; /* Interrupt Mask Register */ |
3208 | 3220 | ||
@@ -3218,7 +3230,7 @@ void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags) | |||
3218 | } | 3230 | } |
3219 | } | 3231 | } |
3220 | 3232 | ||
3221 | void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode) | 3233 | static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode) |
3222 | { | 3234 | { |
3223 | sOutB(ChP->CtlP->AiopIO[2], (mode & 0x18) | ChP->ChanNum); | 3235 | sOutB(ChP->CtlP->AiopIO[2], (mode & 0x18) | ChP->ChanNum); |
3224 | } | 3236 | } |
@@ -3227,7 +3239,7 @@ void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode) | |||
3227 | * Not an official SSCI function, but how to reset RocketModems. | 3239 | * Not an official SSCI function, but how to reset RocketModems. |
3228 | * ISA bus version | 3240 | * ISA bus version |
3229 | */ | 3241 | */ |
3230 | void sModemReset(CONTROLLER_T * CtlP, int chan, int on) | 3242 | static void sModemReset(CONTROLLER_T * CtlP, int chan, int on) |
3231 | { | 3243 | { |
3232 | ByteIO_t addr; | 3244 | ByteIO_t addr; |
3233 | Byte_t val; | 3245 | Byte_t val; |
@@ -3252,7 +3264,7 @@ void sModemReset(CONTROLLER_T * CtlP, int chan, int on) | |||
3252 | * Not an official SSCI function, but how to reset RocketModems. | 3264 | * Not an official SSCI function, but how to reset RocketModems. |
3253 | * PCI bus version | 3265 | * PCI bus version |
3254 | */ | 3266 | */ |
3255 | void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on) | 3267 | static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on) |
3256 | { | 3268 | { |
3257 | ByteIO_t addr; | 3269 | ByteIO_t addr; |
3258 | 3270 | ||
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/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/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..af79805b5576 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,6 +95,21 @@ 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) |
@@ -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/tipar.c b/drivers/char/tipar.c index 0c5ba9dc9063..659335d80ee7 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 | ||
@@ -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/tpm.c b/drivers/char/tpm/tpm.c index 87235330fdbe..854475c54f0e 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_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/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..d7aa7a29f67e 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
@@ -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/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/i8xx_tco.c b/drivers/char/watchdog/i8xx_tco.c index c337978dc966..b14d642439ed 100644 --- a/drivers/char/watchdog/i8xx_tco.c +++ b/drivers/char/watchdog/i8xx_tco.c | |||
@@ -382,6 +382,7 @@ static struct pci_device_id i8xx_tco_pci_tbl[] = { | |||
382 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2, PCI_ANY_ID, PCI_ANY_ID, }, | 382 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH6_2, PCI_ANY_ID, PCI_ANY_ID, }, |
383 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, }, | 383 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0, PCI_ANY_ID, PCI_ANY_ID, }, |
384 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, }, | 384 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1, PCI_ANY_ID, PCI_ANY_ID, }, |
385 | { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_1, PCI_ANY_ID, PCI_ANY_ID, }, | ||
385 | { 0, }, /* End of list */ | 386 | { 0, }, /* End of list */ |
386 | }; | 387 | }; |
387 | MODULE_DEVICE_TABLE (pci, i8xx_tco_pci_tbl); | 388 | MODULE_DEVICE_TABLE (pci, i8xx_tco_pci_tbl); |
diff --git a/drivers/char/watchdog/ixp2000_wdt.c b/drivers/char/watchdog/ixp2000_wdt.c index ab659d37b4d2..4e98c215e5b1 100644 --- a/drivers/char/watchdog/ixp2000_wdt.c +++ b/drivers/char/watchdog/ixp2000_wdt.c | |||
@@ -192,7 +192,12 @@ static struct miscdevice ixp2000_wdt_miscdev = | |||
192 | 192 | ||
193 | static int __init ixp2000_wdt_init(void) | 193 | static int __init ixp2000_wdt_init(void) |
194 | { | 194 | { |
195 | wdt_tick_rate = (*IXP2000_T1_CLD * HZ)/ 256;; | 195 | if ((*IXP2000_PRODUCT_ID & 0x001ffef0) == 0x00000000) { |
196 | printk(KERN_INFO "Unable to use IXP2000 watchdog due to IXP2800 erratum #25.\n"); | ||
197 | return -EIO; | ||
198 | } | ||
199 | |||
200 | wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256; | ||
196 | 201 | ||
197 | return misc_register(&ixp2000_wdt_miscdev); | 202 | return misc_register(&ixp2000_wdt_miscdev); |
198 | } | 203 | } |
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); | ||