aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/Kconfig32
-rw-r--r--drivers/char/Makefile2
-rw-r--r--drivers/char/agp/Kconfig4
-rw-r--r--drivers/char/agp/amd64-agp.c81
-rw-r--r--drivers/char/hangcheck-timer.c4
-rw-r--r--drivers/char/hw_random.c698
-rw-r--r--drivers/char/hw_random/Kconfig90
-rw-r--r--drivers/char/hw_random/Makefile11
-rw-r--r--drivers/char/hw_random/amd-rng.c152
-rw-r--r--drivers/char/hw_random/core.c354
-rw-r--r--drivers/char/hw_random/geode-rng.c128
-rw-r--r--drivers/char/hw_random/intel-rng.c189
-rw-r--r--drivers/char/hw_random/ixp4xx-rng.c73
-rw-r--r--drivers/char/hw_random/omap-rng.c208
-rw-r--r--drivers/char/hw_random/via-rng.c183
-rw-r--r--drivers/char/ipmi/ipmi_msghandler.c7
-rw-r--r--drivers/char/keyboard.c26
-rw-r--r--drivers/char/vt.c580
18 files changed, 2006 insertions, 816 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 63f28d169b36..3610c5729553 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -62,6 +62,23 @@ config HW_CONSOLE
62 depends on VT && !S390 && !UML 62 depends on VT && !S390 && !UML
63 default y 63 default y
64 64
65config VT_HW_CONSOLE_BINDING
66 bool "Support for binding and unbinding console drivers"
67 depends on HW_CONSOLE
68 default n
69 ---help---
70 The virtual terminal is the device that interacts with the physical
71 terminal through console drivers. On these systems, at least one
72 console driver is loaded. In other configurations, additional console
73 drivers may be enabled, such as the framebuffer console. If more than
74 1 console driver is enabled, setting this to 'y' will allow you to
75 select the console driver that will serve as the backend for the
76 virtual terminals.
77
78 See <file:Documentation/console/console.txt> for more
79 information. For framebuffer console users, please refer to
80 <file:Documentation/fb/fbcon.txt>.
81
65config SERIAL_NONSTANDARD 82config SERIAL_NONSTANDARD
66 bool "Non-standard serial port support" 83 bool "Non-standard serial port support"
67 ---help--- 84 ---help---
@@ -670,20 +687,7 @@ config NWFLASH
670 687
671 If you're not sure, say N. 688 If you're not sure, say N.
672 689
673config HW_RANDOM 690source "drivers/char/hw_random/Kconfig"
674 tristate "Intel/AMD/VIA HW Random Number Generator support"
675 depends on (X86 || IA64) && PCI
676 ---help---
677 This driver provides kernel-side support for the Random Number
678 Generator hardware found on Intel i8xx-based motherboards,
679 AMD 76x-based motherboards, and Via Nehemiah CPUs.
680
681 Provides a character driver, used to read() entropy data.
682
683 To compile this driver as a module, choose M here: the
684 module will be called hw_random.
685
686 If unsure, say N.
687 691
688config NVRAM 692config NVRAM
689 tristate "/dev/nvram support" 693 tristate "/dev/nvram support"
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index fb919bfb2824..524105597ea7 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -75,7 +75,7 @@ endif
75obj-$(CONFIG_TOSHIBA) += toshiba.o 75obj-$(CONFIG_TOSHIBA) += toshiba.o
76obj-$(CONFIG_I8K) += i8k.o 76obj-$(CONFIG_I8K) += i8k.o
77obj-$(CONFIG_DS1620) += ds1620.o 77obj-$(CONFIG_DS1620) += ds1620.o
78obj-$(CONFIG_HW_RANDOM) += hw_random.o 78obj-$(CONFIG_HW_RANDOM) += hw_random/
79obj-$(CONFIG_FTAPE) += ftape/ 79obj-$(CONFIG_FTAPE) += ftape/
80obj-$(CONFIG_COBALT_LCD) += lcd.o 80obj-$(CONFIG_COBALT_LCD) += lcd.o
81obj-$(CONFIG_PPDEV) += ppdev.o 81obj-$(CONFIG_PPDEV) += ppdev.o
diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig
index 46685a540772..9826a399fa02 100644
--- a/drivers/char/agp/Kconfig
+++ b/drivers/char/agp/Kconfig
@@ -55,9 +55,9 @@ config AGP_AMD
55 X on AMD Irongate, 761, and 762 chipsets. 55 X on AMD Irongate, 761, and 762 chipsets.
56 56
57config AGP_AMD64 57config AGP_AMD64
58 tristate "AMD Opteron/Athlon64 on-CPU GART support" if !GART_IOMMU 58 tristate "AMD Opteron/Athlon64 on-CPU GART support" if !IOMMU
59 depends on AGP && X86 59 depends on AGP && X86
60 default y if GART_IOMMU 60 default y if IOMMU
61 help 61 help
62 This option gives you AGP support for the GLX component of 62 This option gives you AGP support for the GLX component of
63 X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs. 63 X using the on-CPU northbridge of the AMD Athlon64/Opteron CPUs.
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c
index ac3c33a2e37d..f690ee8cb732 100644
--- a/drivers/char/agp/amd64-agp.c
+++ b/drivers/char/agp/amd64-agp.c
@@ -15,11 +15,9 @@
15#include <linux/agp_backend.h> 15#include <linux/agp_backend.h>
16#include <linux/mmzone.h> 16#include <linux/mmzone.h>
17#include <asm/page.h> /* PAGE_SIZE */ 17#include <asm/page.h> /* PAGE_SIZE */
18#include <asm/k8.h>
18#include "agp.h" 19#include "agp.h"
19 20
20/* Will need to be increased if AMD64 ever goes >8-way. */
21#define MAX_HAMMER_GARTS 8
22
23/* PTE bits. */ 21/* PTE bits. */
24#define GPTE_VALID 1 22#define GPTE_VALID 1
25#define GPTE_COHERENT 2 23#define GPTE_COHERENT 2
@@ -53,28 +51,12 @@
53#define ULI_X86_64_HTT_FEA_REG 0x50 51#define ULI_X86_64_HTT_FEA_REG 0x50
54#define ULI_X86_64_ENU_SCR_REG 0x54 52#define ULI_X86_64_ENU_SCR_REG 0x54
55 53
56static int nr_garts;
57static struct pci_dev * hammers[MAX_HAMMER_GARTS];
58
59static struct resource *aperture_resource; 54static struct resource *aperture_resource;
60static int __initdata agp_try_unsupported = 1; 55static int __initdata agp_try_unsupported = 1;
61 56
62#define for_each_nb() for(gart_iterator=0;gart_iterator<nr_garts;gart_iterator++)
63
64static void flush_amd64_tlb(struct pci_dev *dev)
65{
66 u32 tmp;
67
68 pci_read_config_dword (dev, AMD64_GARTCACHECTL, &tmp);
69 tmp |= INVGART;
70 pci_write_config_dword (dev, AMD64_GARTCACHECTL, tmp);
71}
72
73static void amd64_tlbflush(struct agp_memory *temp) 57static void amd64_tlbflush(struct agp_memory *temp)
74{ 58{
75 int gart_iterator; 59 k8_flush_garts();
76 for_each_nb()
77 flush_amd64_tlb(hammers[gart_iterator]);
78} 60}
79 61
80static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type) 62static int amd64_insert_memory(struct agp_memory *mem, off_t pg_start, int type)
@@ -153,7 +135,7 @@ static int amd64_fetch_size(void)
153 u32 temp; 135 u32 temp;
154 struct aper_size_info_32 *values; 136 struct aper_size_info_32 *values;
155 137
156 dev = hammers[0]; 138 dev = k8_northbridges[0];
157 if (dev==NULL) 139 if (dev==NULL)
158 return 0; 140 return 0;
159 141
@@ -201,9 +183,6 @@ static u64 amd64_configure (struct pci_dev *hammer, u64 gatt_table)
201 tmp &= ~(DISGARTCPU | DISGARTIO); 183 tmp &= ~(DISGARTCPU | DISGARTIO);
202 pci_write_config_dword(hammer, AMD64_GARTAPERTURECTL, tmp); 184 pci_write_config_dword(hammer, AMD64_GARTAPERTURECTL, tmp);
203 185
204 /* keep CPU's coherent. */
205 flush_amd64_tlb (hammer);
206
207 return aper_base; 186 return aper_base;
208} 187}
209 188
@@ -222,13 +201,14 @@ static struct aper_size_info_32 amd_8151_sizes[7] =
222static int amd_8151_configure(void) 201static int amd_8151_configure(void)
223{ 202{
224 unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real); 203 unsigned long gatt_bus = virt_to_gart(agp_bridge->gatt_table_real);
225 int gart_iterator; 204 int i;
226 205
227 /* Configure AGP regs in each x86-64 host bridge. */ 206 /* Configure AGP regs in each x86-64 host bridge. */
228 for_each_nb() { 207 for (i = 0; i < num_k8_northbridges; i++) {
229 agp_bridge->gart_bus_addr = 208 agp_bridge->gart_bus_addr =
230 amd64_configure(hammers[gart_iterator],gatt_bus); 209 amd64_configure(k8_northbridges[i], gatt_bus);
231 } 210 }
211 k8_flush_garts();
232 return 0; 212 return 0;
233} 213}
234 214
@@ -236,12 +216,13 @@ static int amd_8151_configure(void)
236static void amd64_cleanup(void) 216static void amd64_cleanup(void)
237{ 217{
238 u32 tmp; 218 u32 tmp;
239 int gart_iterator; 219 int i;
240 for_each_nb() { 220 for (i = 0; i < num_k8_northbridges; i++) {
221 struct pci_dev *dev = k8_northbridges[i];
241 /* disable gart translation */ 222 /* disable gart translation */
242 pci_read_config_dword (hammers[gart_iterator], AMD64_GARTAPERTURECTL, &tmp); 223 pci_read_config_dword (dev, AMD64_GARTAPERTURECTL, &tmp);
243 tmp &= ~AMD64_GARTEN; 224 tmp &= ~AMD64_GARTEN;
244 pci_write_config_dword (hammers[gart_iterator], AMD64_GARTAPERTURECTL, tmp); 225 pci_write_config_dword (dev, AMD64_GARTAPERTURECTL, tmp);
245 } 226 }
246} 227}
247 228
@@ -311,7 +292,7 @@ static int __devinit aperture_valid(u64 aper, u32 size)
311/* 292/*
312 * W*s centric BIOS sometimes only set up the aperture in the AGP 293 * W*s centric BIOS sometimes only set up the aperture in the AGP
313 * bridge, not the northbridge. On AMD64 this is handled early 294 * bridge, not the northbridge. On AMD64 this is handled early
314 * in aperture.c, but when GART_IOMMU is not enabled or we run 295 * in aperture.c, but when IOMMU is not enabled or we run
315 * on a 32bit kernel this needs to be redone. 296 * on a 32bit kernel this needs to be redone.
316 * Unfortunately it is impossible to fix the aperture here because it's too late 297 * Unfortunately it is impossible to fix the aperture here because it's too late
317 * to allocate that much memory. But at least error out cleanly instead of 298 * to allocate that much memory. But at least error out cleanly instead of
@@ -361,17 +342,15 @@ static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp,
361 342
362static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr) 343static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr)
363{ 344{
364 struct pci_dev *loop_dev = NULL; 345 int i;
365 int i = 0; 346
366 347 if (cache_k8_northbridges() < 0)
367 /* cache pci_devs of northbridges. */ 348 return -ENODEV;
368 while ((loop_dev = pci_get_device(PCI_VENDOR_ID_AMD, 0x1103, loop_dev)) 349
369 != NULL) { 350 i = 0;
370 if (i == MAX_HAMMER_GARTS) { 351 for (i = 0; i < num_k8_northbridges; i++) {
371 printk(KERN_ERR PFX "Too many northbridges for AGP\n"); 352 struct pci_dev *dev = k8_northbridges[i];
372 return -1; 353 if (fix_northbridge(dev, pdev, cap_ptr) < 0) {
373 }
374 if (fix_northbridge(loop_dev, pdev, cap_ptr) < 0) {
375 printk(KERN_ERR PFX "No usable aperture found.\n"); 354 printk(KERN_ERR PFX "No usable aperture found.\n");
376#ifdef __x86_64__ 355#ifdef __x86_64__
377 /* should port this to i386 */ 356 /* should port this to i386 */
@@ -379,10 +358,8 @@ static __devinit int cache_nbs (struct pci_dev *pdev, u32 cap_ptr)
379#endif 358#endif
380 return -1; 359 return -1;
381 } 360 }
382 hammers[i++] = loop_dev;
383 } 361 }
384 nr_garts = i; 362 return 0;
385 return i == 0 ? -1 : 0;
386} 363}
387 364
388/* Handle AMD 8151 quirks */ 365/* Handle AMD 8151 quirks */
@@ -450,7 +427,7 @@ static int __devinit uli_agp_init(struct pci_dev *pdev)
450 } 427 }
451 428
452 /* shadow x86-64 registers into ULi registers */ 429 /* shadow x86-64 registers into ULi registers */
453 pci_read_config_dword (hammers[0], AMD64_GARTAPERTUREBASE, &httfea); 430 pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &httfea);
454 431
455 /* if x86-64 aperture base is beyond 4G, exit here */ 432 /* if x86-64 aperture base is beyond 4G, exit here */
456 if ((httfea & 0x7fff) >> (32 - 25)) 433 if ((httfea & 0x7fff) >> (32 - 25))
@@ -513,7 +490,7 @@ static int __devinit nforce3_agp_init(struct pci_dev *pdev)
513 pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp); 490 pci_write_config_dword(dev1, NVIDIA_X86_64_1_APSIZE, tmp);
514 491
515 /* shadow x86-64 registers into NVIDIA registers */ 492 /* shadow x86-64 registers into NVIDIA registers */
516 pci_read_config_dword (hammers[0], AMD64_GARTAPERTUREBASE, &apbase); 493 pci_read_config_dword (k8_northbridges[0], AMD64_GARTAPERTUREBASE, &apbase);
517 494
518 /* if x86-64 aperture base is beyond 4G, exit here */ 495 /* if x86-64 aperture base is beyond 4G, exit here */
519 if ( (apbase & 0x7fff) >> (32 - 25) ) { 496 if ( (apbase & 0x7fff) >> (32 - 25) ) {
@@ -754,10 +731,6 @@ static struct pci_driver agp_amd64_pci_driver = {
754int __init agp_amd64_init(void) 731int __init agp_amd64_init(void)
755{ 732{
756 int err = 0; 733 int err = 0;
757 static struct pci_device_id amd64nb[] = {
758 { PCI_DEVICE(PCI_VENDOR_ID_AMD, 0x1103) },
759 { },
760 };
761 734
762 if (agp_off) 735 if (agp_off)
763 return -EINVAL; 736 return -EINVAL;
@@ -774,7 +747,7 @@ int __init agp_amd64_init(void)
774 } 747 }
775 748
776 /* First check that we have at least one AMD64 NB */ 749 /* First check that we have at least one AMD64 NB */
777 if (!pci_dev_present(amd64nb)) 750 if (!pci_dev_present(k8_nb_ids))
778 return -ENODEV; 751 return -ENODEV;
779 752
780 /* Look for any AGP bridge */ 753 /* Look for any AGP bridge */
@@ -802,7 +775,7 @@ static void __exit agp_amd64_cleanup(void)
802 775
803/* On AMD64 the PCI driver needs to initialize this driver early 776/* On AMD64 the PCI driver needs to initialize this driver early
804 for the IOMMU, so it has to be called via a backdoor. */ 777 for the IOMMU, so it has to be called via a backdoor. */
805#ifndef CONFIG_GART_IOMMU 778#ifndef CONFIG_IOMMU
806module_init(agp_amd64_init); 779module_init(agp_amd64_init);
807module_exit(agp_amd64_cleanup); 780module_exit(agp_amd64_cleanup);
808#endif 781#endif
diff --git a/drivers/char/hangcheck-timer.c b/drivers/char/hangcheck-timer.c
index ac626418b329..d69f2ad9a67d 100644
--- a/drivers/char/hangcheck-timer.c
+++ b/drivers/char/hangcheck-timer.c
@@ -117,12 +117,12 @@ __setup("hcheck_reboot", hangcheck_parse_reboot);
117__setup("hcheck_dump_tasks", hangcheck_parse_dump_tasks); 117__setup("hcheck_dump_tasks", hangcheck_parse_dump_tasks);
118#endif /* not MODULE */ 118#endif /* not MODULE */
119 119
120#if defined(CONFIG_X86) || defined(CONFIG_S390) 120#if defined(CONFIG_X86_64) || defined(CONFIG_S390)
121# define HAVE_MONOTONIC 121# define HAVE_MONOTONIC
122# define TIMER_FREQ 1000000000ULL 122# define TIMER_FREQ 1000000000ULL
123#elif defined(CONFIG_IA64) 123#elif defined(CONFIG_IA64)
124# define TIMER_FREQ ((unsigned long long)local_cpu_data->itc_freq) 124# define TIMER_FREQ ((unsigned long long)local_cpu_data->itc_freq)
125#elif defined(CONFIG_PPC64) 125#else
126# define TIMER_FREQ (HZ*loops_per_jiffy) 126# define TIMER_FREQ (HZ*loops_per_jiffy)
127#endif 127#endif
128 128
diff --git a/drivers/char/hw_random.c b/drivers/char/hw_random.c
deleted file mode 100644
index 29dc87e59020..000000000000
--- a/drivers/char/hw_random.c
+++ /dev/null
@@ -1,698 +0,0 @@
1/*
2 Added support for the AMD Geode LX RNG
3 (c) Copyright 2004-2005 Advanced Micro Devices, Inc.
4
5 derived from
6
7 Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
8 (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
9
10 derived from
11
12 Hardware driver for the AMD 768 Random Number Generator (RNG)
13 (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
14
15 derived from
16
17 Hardware driver for Intel i810 Random Number Generator (RNG)
18 Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
19 Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
20
21 Please read Documentation/hw_random.txt for details on use.
22
23 ----------------------------------------------------------
24 This software may be used and distributed according to the terms
25 of the GNU General Public License, incorporated herein by reference.
26
27 */
28
29
30#include <linux/module.h>
31#include <linux/kernel.h>
32#include <linux/fs.h>
33#include <linux/init.h>
34#include <linux/pci.h>
35#include <linux/interrupt.h>
36#include <linux/spinlock.h>
37#include <linux/random.h>
38#include <linux/miscdevice.h>
39#include <linux/smp_lock.h>
40#include <linux/mm.h>
41#include <linux/delay.h>
42
43#ifdef __i386__
44#include <asm/msr.h>
45#include <asm/cpufeature.h>
46#endif
47
48#include <asm/io.h>
49#include <asm/uaccess.h>
50
51
52/*
53 * core module and version information
54 */
55#define RNG_VERSION "1.0.0"
56#define RNG_MODULE_NAME "hw_random"
57#define RNG_DRIVER_NAME RNG_MODULE_NAME " hardware driver " RNG_VERSION
58#define PFX RNG_MODULE_NAME ": "
59
60
61/*
62 * debugging macros
63 */
64
65/* pr_debug() collapses to a no-op if DEBUG is not defined */
66#define DPRINTK(fmt, args...) pr_debug(PFX "%s: " fmt, __FUNCTION__ , ## args)
67
68
69#undef RNG_NDEBUG /* define to enable lightweight runtime checks */
70#ifdef RNG_NDEBUG
71#define assert(expr) \
72 if(!(expr)) { \
73 printk(KERN_DEBUG PFX "Assertion failed! %s,%s,%s," \
74 "line=%d\n", #expr, __FILE__, __FUNCTION__, __LINE__); \
75 }
76#else
77#define assert(expr)
78#endif
79
80#define RNG_MISCDEV_MINOR 183 /* official */
81
82static int rng_dev_open (struct inode *inode, struct file *filp);
83static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
84 loff_t * offp);
85
86static int __init intel_init (struct pci_dev *dev);
87static void intel_cleanup(void);
88static unsigned int intel_data_present (void);
89static u32 intel_data_read (void);
90
91static int __init amd_init (struct pci_dev *dev);
92static void amd_cleanup(void);
93static unsigned int amd_data_present (void);
94static u32 amd_data_read (void);
95
96#ifdef __i386__
97static int __init via_init(struct pci_dev *dev);
98static void via_cleanup(void);
99static unsigned int via_data_present (void);
100static u32 via_data_read (void);
101#endif
102
103static int __init geode_init(struct pci_dev *dev);
104static void geode_cleanup(void);
105static unsigned int geode_data_present (void);
106static u32 geode_data_read (void);
107
108struct rng_operations {
109 int (*init) (struct pci_dev *dev);
110 void (*cleanup) (void);
111 unsigned int (*data_present) (void);
112 u32 (*data_read) (void);
113 unsigned int n_bytes; /* number of bytes per ->data_read */
114};
115static struct rng_operations *rng_ops;
116
117static struct file_operations rng_chrdev_ops = {
118 .owner = THIS_MODULE,
119 .open = rng_dev_open,
120 .read = rng_dev_read,
121};
122
123
124static struct miscdevice rng_miscdev = {
125 RNG_MISCDEV_MINOR,
126 RNG_MODULE_NAME,
127 &rng_chrdev_ops,
128};
129
130enum {
131 rng_hw_none,
132 rng_hw_intel,
133 rng_hw_amd,
134#ifdef __i386__
135 rng_hw_via,
136#endif
137 rng_hw_geode,
138};
139
140static struct rng_operations rng_vendor_ops[] = {
141 /* rng_hw_none */
142 { },
143
144 /* rng_hw_intel */
145 { intel_init, intel_cleanup, intel_data_present,
146 intel_data_read, 1 },
147
148 /* rng_hw_amd */
149 { amd_init, amd_cleanup, amd_data_present, amd_data_read, 4 },
150
151#ifdef __i386__
152 /* rng_hw_via */
153 { via_init, via_cleanup, via_data_present, via_data_read, 1 },
154#endif
155
156 /* rng_hw_geode */
157 { geode_init, geode_cleanup, geode_data_present, geode_data_read, 4 }
158};
159
160/*
161 * Data for PCI driver interface
162 *
163 * This data only exists for exporting the supported
164 * PCI ids via MODULE_DEVICE_TABLE. We do not actually
165 * register a pci_driver, because someone else might one day
166 * want to register another driver on the same PCI id.
167 */
168static struct pci_device_id rng_pci_tbl[] = {
169 { 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_amd },
170 { 0x1022, 0x746b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_amd },
171
172 { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
173 { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
174 { 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
175 { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
176 { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
177 { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_intel },
178
179 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES,
180 PCI_ANY_ID, PCI_ANY_ID, 0, 0, rng_hw_geode },
181
182 { 0, }, /* terminate list */
183};
184MODULE_DEVICE_TABLE (pci, rng_pci_tbl);
185
186
187/***********************************************************************
188 *
189 * Intel RNG operations
190 *
191 */
192
193/*
194 * RNG registers (offsets from rng_mem)
195 */
196#define INTEL_RNG_HW_STATUS 0
197#define INTEL_RNG_PRESENT 0x40
198#define INTEL_RNG_ENABLED 0x01
199#define INTEL_RNG_STATUS 1
200#define INTEL_RNG_DATA_PRESENT 0x01
201#define INTEL_RNG_DATA 2
202
203/*
204 * Magic address at which Intel PCI bridges locate the RNG
205 */
206#define INTEL_RNG_ADDR 0xFFBC015F
207#define INTEL_RNG_ADDR_LEN 3
208
209/* token to our ioremap'd RNG register area */
210static void __iomem *rng_mem;
211
212static inline u8 intel_hwstatus (void)
213{
214 assert (rng_mem != NULL);
215 return readb (rng_mem + INTEL_RNG_HW_STATUS);
216}
217
218static inline u8 intel_hwstatus_set (u8 hw_status)
219{
220 assert (rng_mem != NULL);
221 writeb (hw_status, rng_mem + INTEL_RNG_HW_STATUS);
222 return intel_hwstatus ();
223}
224
225static unsigned int intel_data_present(void)
226{
227 assert (rng_mem != NULL);
228
229 return (readb (rng_mem + INTEL_RNG_STATUS) & INTEL_RNG_DATA_PRESENT) ?
230 1 : 0;
231}
232
233static u32 intel_data_read(void)
234{
235 assert (rng_mem != NULL);
236
237 return readb (rng_mem + INTEL_RNG_DATA);
238}
239
240static int __init intel_init (struct pci_dev *dev)
241{
242 int rc;
243 u8 hw_status;
244
245 DPRINTK ("ENTER\n");
246
247 rng_mem = ioremap (INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN);
248 if (rng_mem == NULL) {
249 printk (KERN_ERR PFX "cannot ioremap RNG Memory\n");
250 rc = -EBUSY;
251 goto err_out;
252 }
253
254 /* Check for Intel 82802 */
255 hw_status = intel_hwstatus ();
256 if ((hw_status & INTEL_RNG_PRESENT) == 0) {
257 printk (KERN_ERR PFX "RNG not detected\n");
258 rc = -ENODEV;
259 goto err_out_free_map;
260 }
261
262 /* turn RNG h/w on, if it's off */
263 if ((hw_status & INTEL_RNG_ENABLED) == 0)
264 hw_status = intel_hwstatus_set (hw_status | INTEL_RNG_ENABLED);
265 if ((hw_status & INTEL_RNG_ENABLED) == 0) {
266 printk (KERN_ERR PFX "cannot enable RNG, aborting\n");
267 rc = -EIO;
268 goto err_out_free_map;
269 }
270
271 DPRINTK ("EXIT, returning 0\n");
272 return 0;
273
274err_out_free_map:
275 iounmap (rng_mem);
276 rng_mem = NULL;
277err_out:
278 DPRINTK ("EXIT, returning %d\n", rc);
279 return rc;
280}
281
282static void intel_cleanup(void)
283{
284 u8 hw_status;
285
286 hw_status = intel_hwstatus ();
287 if (hw_status & INTEL_RNG_ENABLED)
288 intel_hwstatus_set (hw_status & ~INTEL_RNG_ENABLED);
289 else
290 printk(KERN_WARNING PFX "unusual: RNG already disabled\n");
291 iounmap(rng_mem);
292 rng_mem = NULL;
293}
294
295/***********************************************************************
296 *
297 * AMD RNG operations
298 *
299 */
300
301static u32 pmbase; /* PMxx I/O base */
302static struct pci_dev *amd_dev;
303
304static unsigned int amd_data_present (void)
305{
306 return inl(pmbase + 0xF4) & 1;
307}
308
309
310static u32 amd_data_read (void)
311{
312 return inl(pmbase + 0xF0);
313}
314
315static int __init amd_init (struct pci_dev *dev)
316{
317 int rc;
318 u8 rnen;
319
320 DPRINTK ("ENTER\n");
321
322 pci_read_config_dword(dev, 0x58, &pmbase);
323
324 pmbase &= 0x0000FF00;
325
326 if (pmbase == 0)
327 {
328 printk (KERN_ERR PFX "power management base not set\n");
329 rc = -EIO;
330 goto err_out;
331 }
332
333 pci_read_config_byte(dev, 0x40, &rnen);
334 rnen |= (1 << 7); /* RNG on */
335 pci_write_config_byte(dev, 0x40, rnen);
336
337 pci_read_config_byte(dev, 0x41, &rnen);
338 rnen |= (1 << 7); /* PMIO enable */
339 pci_write_config_byte(dev, 0x41, rnen);
340
341 pr_info( PFX "AMD768 system management I/O registers at 0x%X.\n",
342 pmbase);
343
344 amd_dev = dev;
345
346 DPRINTK ("EXIT, returning 0\n");
347 return 0;
348
349err_out:
350 DPRINTK ("EXIT, returning %d\n", rc);
351 return rc;
352}
353
354static void amd_cleanup(void)
355{
356 u8 rnen;
357
358 pci_read_config_byte(amd_dev, 0x40, &rnen);
359 rnen &= ~(1 << 7); /* RNG off */
360 pci_write_config_byte(amd_dev, 0x40, rnen);
361
362 /* FIXME: twiddle pmio, also? */
363}
364
365#ifdef __i386__
366/***********************************************************************
367 *
368 * VIA RNG operations
369 *
370 */
371
372enum {
373 VIA_STRFILT_CNT_SHIFT = 16,
374 VIA_STRFILT_FAIL = (1 << 15),
375 VIA_STRFILT_ENABLE = (1 << 14),
376 VIA_RAWBITS_ENABLE = (1 << 13),
377 VIA_RNG_ENABLE = (1 << 6),
378 VIA_XSTORE_CNT_MASK = 0x0F,
379
380 VIA_RNG_CHUNK_8 = 0x00, /* 64 rand bits, 64 stored bits */
381 VIA_RNG_CHUNK_4 = 0x01, /* 32 rand bits, 32 stored bits */
382 VIA_RNG_CHUNK_4_MASK = 0xFFFFFFFF,
383 VIA_RNG_CHUNK_2 = 0x02, /* 16 rand bits, 32 stored bits */
384 VIA_RNG_CHUNK_2_MASK = 0xFFFF,
385 VIA_RNG_CHUNK_1 = 0x03, /* 8 rand bits, 32 stored bits */
386 VIA_RNG_CHUNK_1_MASK = 0xFF,
387};
388
389static u32 via_rng_datum;
390
391/*
392 * Investigate using the 'rep' prefix to obtain 32 bits of random data
393 * in one insn. The upside is potentially better performance. The
394 * downside is that the instruction becomes no longer atomic. Due to
395 * this, just like familiar issues with /dev/random itself, the worst
396 * case of a 'rep xstore' could potentially pause a cpu for an
397 * unreasonably long time. In practice, this condition would likely
398 * only occur when the hardware is failing. (or so we hope :))
399 *
400 * Another possible performance boost may come from simply buffering
401 * until we have 4 bytes, thus returning a u32 at a time,
402 * instead of the current u8-at-a-time.
403 */
404
405static inline u32 xstore(u32 *addr, u32 edx_in)
406{
407 u32 eax_out;
408
409 asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */"
410 :"=m"(*addr), "=a"(eax_out)
411 :"D"(addr), "d"(edx_in));
412
413 return eax_out;
414}
415
416static unsigned int via_data_present(void)
417{
418 u32 bytes_out;
419
420 /* We choose the recommended 1-byte-per-instruction RNG rate,
421 * for greater randomness at the expense of speed. Larger
422 * values 2, 4, or 8 bytes-per-instruction yield greater
423 * speed at lesser randomness.
424 *
425 * If you change this to another VIA_CHUNK_n, you must also
426 * change the ->n_bytes values in rng_vendor_ops[] tables.
427 * VIA_CHUNK_8 requires further code changes.
428 *
429 * A copy of MSR_VIA_RNG is placed in eax_out when xstore
430 * completes.
431 */
432 via_rng_datum = 0; /* paranoia, not really necessary */
433 bytes_out = xstore(&via_rng_datum, VIA_RNG_CHUNK_1) & VIA_XSTORE_CNT_MASK;
434 if (bytes_out == 0)
435 return 0;
436
437 return 1;
438}
439
440static u32 via_data_read(void)
441{
442 return via_rng_datum;
443}
444
445static int __init via_init(struct pci_dev *dev)
446{
447 u32 lo, hi, old_lo;
448
449 /* Control the RNG via MSR. Tread lightly and pay very close
450 * close attention to values written, as the reserved fields
451 * are documented to be "undefined and unpredictable"; but it
452 * does not say to write them as zero, so I make a guess that
453 * we restore the values we find in the register.
454 */
455 rdmsr(MSR_VIA_RNG, lo, hi);
456
457 old_lo = lo;
458 lo &= ~(0x7f << VIA_STRFILT_CNT_SHIFT);
459 lo &= ~VIA_XSTORE_CNT_MASK;
460 lo &= ~(VIA_STRFILT_ENABLE | VIA_STRFILT_FAIL | VIA_RAWBITS_ENABLE);
461 lo |= VIA_RNG_ENABLE;
462
463 if (lo != old_lo)
464 wrmsr(MSR_VIA_RNG, lo, hi);
465
466 /* perhaps-unnecessary sanity check; remove after testing if
467 unneeded */
468 rdmsr(MSR_VIA_RNG, lo, hi);
469 if ((lo & VIA_RNG_ENABLE) == 0) {
470 printk(KERN_ERR PFX "cannot enable VIA C3 RNG, aborting\n");
471 return -ENODEV;
472 }
473
474 return 0;
475}
476
477static void via_cleanup(void)
478{
479 /* do nothing */
480}
481#endif
482
483/***********************************************************************
484 *
485 * AMD Geode RNG operations
486 *
487 */
488
489static void __iomem *geode_rng_base = NULL;
490
491#define GEODE_RNG_DATA_REG 0x50
492#define GEODE_RNG_STATUS_REG 0x54
493
494static u32 geode_data_read(void)
495{
496 u32 val;
497
498 assert(geode_rng_base != NULL);
499 val = readl(geode_rng_base + GEODE_RNG_DATA_REG);
500 return val;
501}
502
503static unsigned int geode_data_present(void)
504{
505 u32 val;
506
507 assert(geode_rng_base != NULL);
508 val = readl(geode_rng_base + GEODE_RNG_STATUS_REG);
509 return val;
510}
511
512static void geode_cleanup(void)
513{
514 iounmap(geode_rng_base);
515 geode_rng_base = NULL;
516}
517
518static int geode_init(struct pci_dev *dev)
519{
520 unsigned long rng_base = pci_resource_start(dev, 0);
521
522 if (rng_base == 0)
523 return 1;
524
525 geode_rng_base = ioremap(rng_base, 0x58);
526
527 if (geode_rng_base == NULL) {
528 printk(KERN_ERR PFX "Cannot ioremap RNG memory\n");
529 return -EBUSY;
530 }
531
532 return 0;
533}
534
535/***********************************************************************
536 *
537 * /dev/hwrandom character device handling (major 10, minor 183)
538 *
539 */
540
541static int rng_dev_open (struct inode *inode, struct file *filp)
542{
543 /* enforce read-only access to this chrdev */
544 if ((filp->f_mode & FMODE_READ) == 0)
545 return -EINVAL;
546 if (filp->f_mode & FMODE_WRITE)
547 return -EINVAL;
548
549 return 0;
550}
551
552
553static ssize_t rng_dev_read (struct file *filp, char __user *buf, size_t size,
554 loff_t * offp)
555{
556 static DEFINE_SPINLOCK(rng_lock);
557 unsigned int have_data;
558 u32 data = 0;
559 ssize_t ret = 0;
560
561 while (size) {
562 spin_lock(&rng_lock);
563
564 have_data = 0;
565 if (rng_ops->data_present()) {
566 data = rng_ops->data_read();
567 have_data = rng_ops->n_bytes;
568 }
569
570 spin_unlock (&rng_lock);
571
572 while (have_data && size) {
573 if (put_user((u8)data, buf++)) {
574 ret = ret ? : -EFAULT;
575 break;
576 }
577 size--;
578 ret++;
579 have_data--;
580 data>>=8;
581 }
582
583 if (filp->f_flags & O_NONBLOCK)
584 return ret ? : -EAGAIN;
585
586 if(need_resched())
587 schedule_timeout_interruptible(1);
588 else
589 udelay(200); /* FIXME: We could poll for 250uS ?? */
590
591 if (signal_pending (current))
592 return ret ? : -ERESTARTSYS;
593 }
594 return ret;
595}
596
597
598
599/*
600 * rng_init_one - look for and attempt to init a single RNG
601 */
602static int __init rng_init_one (struct pci_dev *dev)
603{
604 int rc;
605
606 DPRINTK ("ENTER\n");
607
608 assert(rng_ops != NULL);
609
610 rc = rng_ops->init(dev);
611 if (rc)
612 goto err_out;
613
614 rc = misc_register (&rng_miscdev);
615 if (rc) {
616 printk (KERN_ERR PFX "misc device register failed\n");
617 goto err_out_cleanup_hw;
618 }
619
620 DPRINTK ("EXIT, returning 0\n");
621 return 0;
622
623err_out_cleanup_hw:
624 rng_ops->cleanup();
625err_out:
626 DPRINTK ("EXIT, returning %d\n", rc);
627 return rc;
628}
629
630
631
632MODULE_AUTHOR("The Linux Kernel team");
633MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
634MODULE_LICENSE("GPL");
635
636
637/*
638 * rng_init - initialize RNG module
639 */
640static int __init rng_init (void)
641{
642 int rc;
643 struct pci_dev *pdev = NULL;
644 const struct pci_device_id *ent;
645
646 DPRINTK ("ENTER\n");
647
648 /* Probe for Intel, AMD, Geode RNGs */
649 for_each_pci_dev(pdev) {
650 ent = pci_match_id(rng_pci_tbl, pdev);
651 if (ent) {
652 rng_ops = &rng_vendor_ops[ent->driver_data];
653 goto match;
654 }
655 }
656
657#ifdef __i386__
658 /* Probe for VIA RNG */
659 if (cpu_has_xstore) {
660 rng_ops = &rng_vendor_ops[rng_hw_via];
661 pdev = NULL;
662 goto match;
663 }
664#endif
665
666 DPRINTK ("EXIT, returning -ENODEV\n");
667 return -ENODEV;
668
669match:
670 rc = rng_init_one (pdev);
671 if (rc)
672 return rc;
673
674 pr_info( RNG_DRIVER_NAME " loaded\n");
675
676 DPRINTK ("EXIT, returning 0\n");
677 return 0;
678}
679
680
681/*
682 * rng_init - shutdown RNG module
683 */
684static void __exit rng_cleanup (void)
685{
686 DPRINTK ("ENTER\n");
687
688 misc_deregister (&rng_miscdev);
689
690 if (rng_ops->cleanup)
691 rng_ops->cleanup();
692
693 DPRINTK ("EXIT\n");
694}
695
696
697module_init (rng_init);
698module_exit (rng_cleanup);
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig
new file mode 100644
index 000000000000..9f7635f75178
--- /dev/null
+++ b/drivers/char/hw_random/Kconfig
@@ -0,0 +1,90 @@
1#
2# Hardware Random Number Generator (RNG) configuration
3#
4
5config HW_RANDOM
6 bool "Hardware Random Number Generator Core support"
7 default y
8 ---help---
9 Hardware Random Number Generator Core infrastructure.
10
11 If unsure, say Y.
12
13config HW_RANDOM_INTEL
14 tristate "Intel HW Random Number Generator support"
15 depends on HW_RANDOM && (X86 || IA64) && PCI
16 default y
17 ---help---
18 This driver provides kernel-side support for the Random Number
19 Generator hardware found on Intel i8xx-based motherboards.
20
21 To compile this driver as a module, choose M here: the
22 module will be called intel-rng.
23
24 If unsure, say Y.
25
26config HW_RANDOM_AMD
27 tristate "AMD HW Random Number Generator support"
28 depends on HW_RANDOM && X86 && PCI
29 default y
30 ---help---
31 This driver provides kernel-side support for the Random Number
32 Generator hardware found on AMD 76x-based motherboards.
33
34 To compile this driver as a module, choose M here: the
35 module will be called amd-rng.
36
37 If unsure, say Y.
38
39config HW_RANDOM_GEODE
40 tristate "AMD Geode HW Random Number Generator support"
41 depends on HW_RANDOM && X86 && PCI
42 default y
43 ---help---
44 This driver provides kernel-side support for the Random Number
45 Generator hardware found on the AMD Geode LX.
46
47 To compile this driver as a module, choose M here: the
48 module will be called geode-rng.
49
50 If unsure, say Y.
51
52config HW_RANDOM_VIA
53 tristate "VIA HW Random Number Generator support"
54 depends on HW_RANDOM && X86_32
55 default y
56 ---help---
57 This driver provides kernel-side support for the Random Number
58 Generator hardware found on VIA based motherboards.
59
60 To compile this driver as a module, choose M here: the
61 module will be called via-rng.
62
63 If unsure, say Y.
64
65config HW_RANDOM_IXP4XX
66 tristate "Intel IXP4xx NPU HW Random Number Generator support"
67 depends on HW_RANDOM && ARCH_IXP4XX
68 default y
69 ---help---
70 This driver provides kernel-side support for the Random
71 Number Generator hardware found on the Intel IXP4xx NPU.
72
73 To compile this driver as a module, choose M here: the
74 module will be called ixp4xx-rng.
75
76 If unsure, say Y.
77
78config HW_RANDOM_OMAP
79 tristate "OMAP Random Number Generator support"
80 depends on HW_RANDOM && (ARCH_OMAP16XX || ARCH_OMAP24XX)
81 default y
82 ---help---
83 This driver provides kernel-side support for the Random Number
84 Generator hardware found on OMAP16xx and OMAP24xx multimedia
85 processors.
86
87 To compile this driver as a module, choose M here: the
88 module will be called omap-rng.
89
90 If unsure, say Y.
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile
new file mode 100644
index 000000000000..e263ae96f940
--- /dev/null
+++ b/drivers/char/hw_random/Makefile
@@ -0,0 +1,11 @@
1#
2# Makefile for HW Random Number Generator (RNG) device drivers.
3#
4
5obj-$(CONFIG_HW_RANDOM) += core.o
6obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o
7obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o
8obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o
9obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o
10obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o
11obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o
diff --git a/drivers/char/hw_random/amd-rng.c b/drivers/char/hw_random/amd-rng.c
new file mode 100644
index 000000000000..71e4e0f3fd54
--- /dev/null
+++ b/drivers/char/hw_random/amd-rng.c
@@ -0,0 +1,152 @@
1/*
2 * RNG driver for AMD RNGs
3 *
4 * Copyright 2005 (c) MontaVista Software, Inc.
5 *
6 * with the majority of the code coming from:
7 *
8 * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
9 * (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
10 *
11 * derived from
12 *
13 * Hardware driver for the AMD 768 Random Number Generator (RNG)
14 * (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
15 *
16 * derived from
17 *
18 * Hardware driver for Intel i810 Random Number Generator (RNG)
19 * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
20 * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
21 *
22 * This file is licensed under the terms of the GNU General Public
23 * License version 2. This program is licensed "as is" without any
24 * warranty of any kind, whether express or implied.
25 */
26
27#include <linux/module.h>
28#include <linux/kernel.h>
29#include <linux/pci.h>
30#include <linux/hw_random.h>
31#include <asm/io.h>
32
33
34#define PFX KBUILD_MODNAME ": "
35
36
37/*
38 * Data for PCI driver interface
39 *
40 * This data only exists for exporting the supported
41 * PCI ids via MODULE_DEVICE_TABLE. We do not actually
42 * register a pci_driver, because someone else might one day
43 * want to register another driver on the same PCI id.
44 */
45static const struct pci_device_id pci_tbl[] = {
46 { 0x1022, 0x7443, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
47 { 0x1022, 0x746b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
48 { 0, }, /* terminate list */
49};
50MODULE_DEVICE_TABLE(pci, pci_tbl);
51
52static struct pci_dev *amd_pdev;
53
54
55static int amd_rng_data_present(struct hwrng *rng)
56{
57 u32 pmbase = (u32)rng->priv;
58
59 return !!(inl(pmbase + 0xF4) & 1);
60}
61
62static int amd_rng_data_read(struct hwrng *rng, u32 *data)
63{
64 u32 pmbase = (u32)rng->priv;
65
66 *data = inl(pmbase + 0xF0);
67
68 return 4;
69}
70
71static int amd_rng_init(struct hwrng *rng)
72{
73 u8 rnen;
74
75 pci_read_config_byte(amd_pdev, 0x40, &rnen);
76 rnen |= (1 << 7); /* RNG on */
77 pci_write_config_byte(amd_pdev, 0x40, rnen);
78
79 pci_read_config_byte(amd_pdev, 0x41, &rnen);
80 rnen |= (1 << 7); /* PMIO enable */
81 pci_write_config_byte(amd_pdev, 0x41, rnen);
82
83 return 0;
84}
85
86static void amd_rng_cleanup(struct hwrng *rng)
87{
88 u8 rnen;
89
90 pci_read_config_byte(amd_pdev, 0x40, &rnen);
91 rnen &= ~(1 << 7); /* RNG off */
92 pci_write_config_byte(amd_pdev, 0x40, rnen);
93}
94
95
96static struct hwrng amd_rng = {
97 .name = "amd",
98 .init = amd_rng_init,
99 .cleanup = amd_rng_cleanup,
100 .data_present = amd_rng_data_present,
101 .data_read = amd_rng_data_read,
102};
103
104
105static int __init mod_init(void)
106{
107 int err = -ENODEV;
108 struct pci_dev *pdev = NULL;
109 const struct pci_device_id *ent;
110 u32 pmbase;
111
112 for_each_pci_dev(pdev) {
113 ent = pci_match_id(pci_tbl, pdev);
114 if (ent)
115 goto found;
116 }
117 /* Device not found. */
118 goto out;
119
120found:
121 err = pci_read_config_dword(pdev, 0x58, &pmbase);
122 if (err)
123 goto out;
124 err = -EIO;
125 pmbase &= 0x0000FF00;
126 if (pmbase == 0)
127 goto out;
128 amd_rng.priv = (unsigned long)pmbase;
129 amd_pdev = pdev;
130
131 printk(KERN_INFO "AMD768 RNG detected\n");
132 err = hwrng_register(&amd_rng);
133 if (err) {
134 printk(KERN_ERR PFX "RNG registering failed (%d)\n",
135 err);
136 goto out;
137 }
138out:
139 return err;
140}
141
142static void __exit mod_exit(void)
143{
144 hwrng_unregister(&amd_rng);
145}
146
147subsys_initcall(mod_init);
148module_exit(mod_exit);
149
150MODULE_AUTHOR("The Linux Kernel team");
151MODULE_DESCRIPTION("H/W RNG driver for AMD chipsets");
152MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
new file mode 100644
index 000000000000..88b026639f10
--- /dev/null
+++ b/drivers/char/hw_random/core.c
@@ -0,0 +1,354 @@
1/*
2 Added support for the AMD Geode LX RNG
3 (c) Copyright 2004-2005 Advanced Micro Devices, Inc.
4
5 derived from
6
7 Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
8 (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
9
10 derived from
11
12 Hardware driver for the AMD 768 Random Number Generator (RNG)
13 (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
14
15 derived from
16
17 Hardware driver for Intel i810 Random Number Generator (RNG)
18 Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
19 Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
20
21 Added generic RNG API
22 Copyright 2006 Michael Buesch <mbuesch@freenet.de>
23 Copyright 2005 (c) MontaVista Software, Inc.
24
25 Please read Documentation/hw_random.txt for details on use.
26
27 ----------------------------------------------------------
28 This software may be used and distributed according to the terms
29 of the GNU General Public License, incorporated herein by reference.
30
31 */
32
33
34#include <linux/device.h>
35#include <linux/hw_random.h>
36#include <linux/module.h>
37#include <linux/kernel.h>
38#include <linux/fs.h>
39#include <linux/init.h>
40#include <linux/miscdevice.h>
41#include <linux/delay.h>
42#include <asm/uaccess.h>
43
44
45#define RNG_MODULE_NAME "hw_random"
46#define PFX RNG_MODULE_NAME ": "
47#define RNG_MISCDEV_MINOR 183 /* official */
48
49
50static struct hwrng *current_rng;
51static LIST_HEAD(rng_list);
52static DEFINE_MUTEX(rng_mutex);
53
54
55static inline int hwrng_init(struct hwrng *rng)
56{
57 if (!rng->init)
58 return 0;
59 return rng->init(rng);
60}
61
62static inline void hwrng_cleanup(struct hwrng *rng)
63{
64 if (rng && rng->cleanup)
65 rng->cleanup(rng);
66}
67
68static inline int hwrng_data_present(struct hwrng *rng)
69{
70 if (!rng->data_present)
71 return 1;
72 return rng->data_present(rng);
73}
74
75static inline int hwrng_data_read(struct hwrng *rng, u32 *data)
76{
77 return rng->data_read(rng, data);
78}
79
80
81static int rng_dev_open(struct inode *inode, struct file *filp)
82{
83 /* enforce read-only access to this chrdev */
84 if ((filp->f_mode & FMODE_READ) == 0)
85 return -EINVAL;
86 if (filp->f_mode & FMODE_WRITE)
87 return -EINVAL;
88 return 0;
89}
90
91static ssize_t rng_dev_read(struct file *filp, char __user *buf,
92 size_t size, loff_t *offp)
93{
94 u32 data;
95 ssize_t ret = 0;
96 int i, err = 0;
97 int data_present;
98 int bytes_read;
99
100 while (size) {
101 err = -ERESTARTSYS;
102 if (mutex_lock_interruptible(&rng_mutex))
103 goto out;
104 if (!current_rng) {
105 mutex_unlock(&rng_mutex);
106 err = -ENODEV;
107 goto out;
108 }
109 if (filp->f_flags & O_NONBLOCK) {
110 data_present = hwrng_data_present(current_rng);
111 } else {
112 /* Some RNG require some time between data_reads to gather
113 * new entropy. Poll it.
114 */
115 for (i = 0; i < 20; i++) {
116 data_present = hwrng_data_present(current_rng);
117 if (data_present)
118 break;
119 udelay(10);
120 }
121 }
122 bytes_read = 0;
123 if (data_present)
124 bytes_read = hwrng_data_read(current_rng, &data);
125 mutex_unlock(&rng_mutex);
126
127 err = -EAGAIN;
128 if (!bytes_read && (filp->f_flags & O_NONBLOCK))
129 goto out;
130
131 err = -EFAULT;
132 while (bytes_read && size) {
133 if (put_user((u8)data, buf++))
134 goto out;
135 size--;
136 ret++;
137 bytes_read--;
138 data >>= 8;
139 }
140
141 if (need_resched())
142 schedule_timeout_interruptible(1);
143 err = -ERESTARTSYS;
144 if (signal_pending(current))
145 goto out;
146 }
147out:
148 return ret ? : err;
149}
150
151
152static struct file_operations rng_chrdev_ops = {
153 .owner = THIS_MODULE,
154 .open = rng_dev_open,
155 .read = rng_dev_read,
156};
157
158static struct miscdevice rng_miscdev = {
159 .minor = RNG_MISCDEV_MINOR,
160 .name = RNG_MODULE_NAME,
161 .fops = &rng_chrdev_ops,
162};
163
164
165static ssize_t hwrng_attr_current_store(struct class_device *class,
166 const char *buf, size_t len)
167{
168 int err;
169 struct hwrng *rng;
170
171 err = mutex_lock_interruptible(&rng_mutex);
172 if (err)
173 return -ERESTARTSYS;
174 err = -ENODEV;
175 list_for_each_entry(rng, &rng_list, list) {
176 if (strcmp(rng->name, buf) == 0) {
177 if (rng == current_rng) {
178 err = 0;
179 break;
180 }
181 err = hwrng_init(rng);
182 if (err)
183 break;
184 hwrng_cleanup(current_rng);
185 current_rng = rng;
186 err = 0;
187 break;
188 }
189 }
190 mutex_unlock(&rng_mutex);
191
192 return err ? : len;
193}
194
195static ssize_t hwrng_attr_current_show(struct class_device *class,
196 char *buf)
197{
198 int err;
199 ssize_t ret;
200 const char *name = "none";
201
202 err = mutex_lock_interruptible(&rng_mutex);
203 if (err)
204 return -ERESTARTSYS;
205 if (current_rng)
206 name = current_rng->name;
207 ret = snprintf(buf, PAGE_SIZE, "%s\n", name);
208 mutex_unlock(&rng_mutex);
209
210 return ret;
211}
212
213static ssize_t hwrng_attr_available_show(struct class_device *class,
214 char *buf)
215{
216 int err;
217 ssize_t ret = 0;
218 struct hwrng *rng;
219
220 err = mutex_lock_interruptible(&rng_mutex);
221 if (err)
222 return -ERESTARTSYS;
223 buf[0] = '\0';
224 list_for_each_entry(rng, &rng_list, list) {
225 strncat(buf, rng->name, PAGE_SIZE - ret - 1);
226 ret += strlen(rng->name);
227 strncat(buf, " ", PAGE_SIZE - ret - 1);
228 ret++;
229 }
230 strncat(buf, "\n", PAGE_SIZE - ret - 1);
231 ret++;
232 mutex_unlock(&rng_mutex);
233
234 return ret;
235}
236
237static CLASS_DEVICE_ATTR(rng_current, S_IRUGO | S_IWUSR,
238 hwrng_attr_current_show,
239 hwrng_attr_current_store);
240static CLASS_DEVICE_ATTR(rng_available, S_IRUGO,
241 hwrng_attr_available_show,
242 NULL);
243
244
245static void unregister_miscdev(void)
246{
247 class_device_remove_file(rng_miscdev.class,
248 &class_device_attr_rng_available);
249 class_device_remove_file(rng_miscdev.class,
250 &class_device_attr_rng_current);
251 misc_deregister(&rng_miscdev);
252}
253
254static int register_miscdev(void)
255{
256 int err;
257
258 err = misc_register(&rng_miscdev);
259 if (err)
260 goto out;
261 err = class_device_create_file(rng_miscdev.class,
262 &class_device_attr_rng_current);
263 if (err)
264 goto err_misc_dereg;
265 err = class_device_create_file(rng_miscdev.class,
266 &class_device_attr_rng_available);
267 if (err)
268 goto err_remove_current;
269out:
270 return err;
271
272err_remove_current:
273 class_device_remove_file(rng_miscdev.class,
274 &class_device_attr_rng_current);
275err_misc_dereg:
276 misc_deregister(&rng_miscdev);
277 goto out;
278}
279
280int hwrng_register(struct hwrng *rng)
281{
282 int must_register_misc;
283 int err = -EINVAL;
284 struct hwrng *old_rng, *tmp;
285
286 if (rng->name == NULL ||
287 rng->data_read == NULL)
288 goto out;
289
290 mutex_lock(&rng_mutex);
291
292 /* Must not register two RNGs with the same name. */
293 err = -EEXIST;
294 list_for_each_entry(tmp, &rng_list, list) {
295 if (strcmp(tmp->name, rng->name) == 0)
296 goto out_unlock;
297 }
298
299 must_register_misc = (current_rng == NULL);
300 old_rng = current_rng;
301 if (!old_rng) {
302 err = hwrng_init(rng);
303 if (err)
304 goto out_unlock;
305 current_rng = rng;
306 }
307 err = 0;
308 if (must_register_misc) {
309 err = register_miscdev();
310 if (err) {
311 if (!old_rng) {
312 hwrng_cleanup(rng);
313 current_rng = NULL;
314 }
315 goto out_unlock;
316 }
317 }
318 INIT_LIST_HEAD(&rng->list);
319 list_add_tail(&rng->list, &rng_list);
320out_unlock:
321 mutex_unlock(&rng_mutex);
322out:
323 return err;
324}
325EXPORT_SYMBOL_GPL(hwrng_register);
326
327void hwrng_unregister(struct hwrng *rng)
328{
329 int err;
330
331 mutex_lock(&rng_mutex);
332
333 list_del(&rng->list);
334 if (current_rng == rng) {
335 hwrng_cleanup(rng);
336 if (list_empty(&rng_list)) {
337 current_rng = NULL;
338 } else {
339 current_rng = list_entry(rng_list.prev, struct hwrng, list);
340 err = hwrng_init(current_rng);
341 if (err)
342 current_rng = NULL;
343 }
344 }
345 if (list_empty(&rng_list))
346 unregister_miscdev();
347
348 mutex_unlock(&rng_mutex);
349}
350EXPORT_SYMBOL_GPL(hwrng_unregister);
351
352
353MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
354MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/geode-rng.c b/drivers/char/hw_random/geode-rng.c
new file mode 100644
index 000000000000..be61f22ee7bb
--- /dev/null
+++ b/drivers/char/hw_random/geode-rng.c
@@ -0,0 +1,128 @@
1/*
2 * RNG driver for AMD Geode RNGs
3 *
4 * Copyright 2005 (c) MontaVista Software, Inc.
5 *
6 * with the majority of the code coming from:
7 *
8 * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
9 * (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
10 *
11 * derived from
12 *
13 * Hardware driver for the AMD 768 Random Number Generator (RNG)
14 * (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
15 *
16 * derived from
17 *
18 * Hardware driver for Intel i810 Random Number Generator (RNG)
19 * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
20 * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
21 *
22 * This file is licensed under the terms of the GNU General Public
23 * License version 2. This program is licensed "as is" without any
24 * warranty of any kind, whether express or implied.
25 */
26
27#include <linux/module.h>
28#include <linux/kernel.h>
29#include <linux/pci.h>
30#include <linux/hw_random.h>
31#include <asm/io.h>
32
33
34#define PFX KBUILD_MODNAME ": "
35
36#define GEODE_RNG_DATA_REG 0x50
37#define GEODE_RNG_STATUS_REG 0x54
38
39/*
40 * Data for PCI driver interface
41 *
42 * This data only exists for exporting the supported
43 * PCI ids via MODULE_DEVICE_TABLE. We do not actually
44 * register a pci_driver, because someone else might one day
45 * want to register another driver on the same PCI id.
46 */
47static const struct pci_device_id pci_tbl[] = {
48 { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_AES,
49 PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
50 { 0, }, /* terminate list */
51};
52MODULE_DEVICE_TABLE(pci, pci_tbl);
53
54
55static int geode_rng_data_read(struct hwrng *rng, u32 *data)
56{
57 void __iomem *mem = (void __iomem *)rng->priv;
58
59 *data = readl(mem + GEODE_RNG_DATA_REG);
60
61 return 4;
62}
63
64static int geode_rng_data_present(struct hwrng *rng)
65{
66 void __iomem *mem = (void __iomem *)rng->priv;
67
68 return !!(readl(mem + GEODE_RNG_STATUS_REG));
69}
70
71
72static struct hwrng geode_rng = {
73 .name = "geode",
74 .data_present = geode_rng_data_present,
75 .data_read = geode_rng_data_read,
76};
77
78
79static int __init mod_init(void)
80{
81 int err = -ENODEV;
82 struct pci_dev *pdev = NULL;
83 const struct pci_device_id *ent;
84 void __iomem *mem;
85 unsigned long rng_base;
86
87 for_each_pci_dev(pdev) {
88 ent = pci_match_id(pci_tbl, pdev);
89 if (ent)
90 goto found;
91 }
92 /* Device not found. */
93 goto out;
94
95found:
96 rng_base = pci_resource_start(pdev, 0);
97 if (rng_base == 0)
98 goto out;
99 err = -ENOMEM;
100 mem = ioremap(rng_base, 0x58);
101 if (!mem)
102 goto out;
103 geode_rng.priv = (unsigned long)mem;
104
105 printk(KERN_INFO "AMD Geode RNG detected\n");
106 err = hwrng_register(&geode_rng);
107 if (err) {
108 printk(KERN_ERR PFX "RNG registering failed (%d)\n",
109 err);
110 goto out;
111 }
112out:
113 return err;
114}
115
116static void __exit mod_exit(void)
117{
118 void __iomem *mem = (void __iomem *)geode_rng.priv;
119
120 hwrng_unregister(&geode_rng);
121 iounmap(mem);
122}
123
124subsys_initcall(mod_init);
125module_exit(mod_exit);
126
127MODULE_DESCRIPTION("H/W RNG driver for AMD Geode LX CPUs");
128MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/intel-rng.c b/drivers/char/hw_random/intel-rng.c
new file mode 100644
index 000000000000..6594bd5645f4
--- /dev/null
+++ b/drivers/char/hw_random/intel-rng.c
@@ -0,0 +1,189 @@
1/*
2 * RNG driver for Intel RNGs
3 *
4 * Copyright 2005 (c) MontaVista Software, Inc.
5 *
6 * with the majority of the code coming from:
7 *
8 * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
9 * (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
10 *
11 * derived from
12 *
13 * Hardware driver for the AMD 768 Random Number Generator (RNG)
14 * (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
15 *
16 * derived from
17 *
18 * Hardware driver for Intel i810 Random Number Generator (RNG)
19 * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
20 * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
21 *
22 * This file is licensed under the terms of the GNU General Public
23 * License version 2. This program is licensed "as is" without any
24 * warranty of any kind, whether express or implied.
25 */
26
27#include <linux/module.h>
28#include <linux/kernel.h>
29#include <linux/pci.h>
30#include <linux/hw_random.h>
31#include <asm/io.h>
32
33
34#define PFX KBUILD_MODNAME ": "
35
36/*
37 * RNG registers
38 */
39#define INTEL_RNG_HW_STATUS 0
40#define INTEL_RNG_PRESENT 0x40
41#define INTEL_RNG_ENABLED 0x01
42#define INTEL_RNG_STATUS 1
43#define INTEL_RNG_DATA_PRESENT 0x01
44#define INTEL_RNG_DATA 2
45
46/*
47 * Magic address at which Intel PCI bridges locate the RNG
48 */
49#define INTEL_RNG_ADDR 0xFFBC015F
50#define INTEL_RNG_ADDR_LEN 3
51
52/*
53 * Data for PCI driver interface
54 *
55 * This data only exists for exporting the supported
56 * PCI ids via MODULE_DEVICE_TABLE. We do not actually
57 * register a pci_driver, because someone else might one day
58 * want to register another driver on the same PCI id.
59 */
60static const struct pci_device_id pci_tbl[] = {
61 { 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
62 { 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
63 { 0x8086, 0x2430, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
64 { 0x8086, 0x2448, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
65 { 0x8086, 0x244e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
66 { 0x8086, 0x245e, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, },
67 { 0, }, /* terminate list */
68};
69MODULE_DEVICE_TABLE(pci, pci_tbl);
70
71
72static inline u8 hwstatus_get(void __iomem *mem)
73{
74 return readb(mem + INTEL_RNG_HW_STATUS);
75}
76
77static inline u8 hwstatus_set(void __iomem *mem,
78 u8 hw_status)
79{
80 writeb(hw_status, mem + INTEL_RNG_HW_STATUS);
81 return hwstatus_get(mem);
82}
83
84static int intel_rng_data_present(struct hwrng *rng)
85{
86 void __iomem *mem = (void __iomem *)rng->priv;
87
88 return !!(readb(mem + INTEL_RNG_STATUS) & INTEL_RNG_DATA_PRESENT);
89}
90
91static int intel_rng_data_read(struct hwrng *rng, u32 *data)
92{
93 void __iomem *mem = (void __iomem *)rng->priv;
94
95 *data = readb(mem + INTEL_RNG_DATA);
96
97 return 1;
98}
99
100static int intel_rng_init(struct hwrng *rng)
101{
102 void __iomem *mem = (void __iomem *)rng->priv;
103 u8 hw_status;
104 int err = -EIO;
105
106 hw_status = hwstatus_get(mem);
107 /* turn RNG h/w on, if it's off */
108 if ((hw_status & INTEL_RNG_ENABLED) == 0)
109 hw_status = hwstatus_set(mem, hw_status | INTEL_RNG_ENABLED);
110 if ((hw_status & INTEL_RNG_ENABLED) == 0) {
111 printk(KERN_ERR PFX "cannot enable RNG, aborting\n");
112 goto out;
113 }
114 err = 0;
115out:
116 return err;
117}
118
119static void intel_rng_cleanup(struct hwrng *rng)
120{
121 void __iomem *mem = (void __iomem *)rng->priv;
122 u8 hw_status;
123
124 hw_status = hwstatus_get(mem);
125 if (hw_status & INTEL_RNG_ENABLED)
126 hwstatus_set(mem, hw_status & ~INTEL_RNG_ENABLED);
127 else
128 printk(KERN_WARNING PFX "unusual: RNG already disabled\n");
129}
130
131
132static struct hwrng intel_rng = {
133 .name = "intel",
134 .init = intel_rng_init,
135 .cleanup = intel_rng_cleanup,
136 .data_present = intel_rng_data_present,
137 .data_read = intel_rng_data_read,
138};
139
140
141static int __init mod_init(void)
142{
143 int err = -ENODEV;
144 void __iomem *mem;
145 u8 hw_status;
146
147 if (!pci_dev_present(pci_tbl))
148 goto out; /* Device not found. */
149
150 err = -ENOMEM;
151 mem = ioremap(INTEL_RNG_ADDR, INTEL_RNG_ADDR_LEN);
152 if (!mem)
153 goto out;
154 intel_rng.priv = (unsigned long)mem;
155
156 /* Check for Intel 82802 */
157 err = -ENODEV;
158 hw_status = hwstatus_get(mem);
159 if ((hw_status & INTEL_RNG_PRESENT) == 0)
160 goto err_unmap;
161
162 printk(KERN_INFO "Intel 82802 RNG detected\n");
163 err = hwrng_register(&intel_rng);
164 if (err) {
165 printk(KERN_ERR PFX "RNG registering failed (%d)\n",
166 err);
167 goto out;
168 }
169out:
170 return err;
171
172err_unmap:
173 iounmap(mem);
174 goto out;
175}
176
177static void __exit mod_exit(void)
178{
179 void __iomem *mem = (void __iomem *)intel_rng.priv;
180
181 hwrng_unregister(&intel_rng);
182 iounmap(mem);
183}
184
185subsys_initcall(mod_init);
186module_exit(mod_exit);
187
188MODULE_DESCRIPTION("H/W RNG driver for Intel chipsets");
189MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/ixp4xx-rng.c b/drivers/char/hw_random/ixp4xx-rng.c
new file mode 100644
index 000000000000..ef71022423c9
--- /dev/null
+++ b/drivers/char/hw_random/ixp4xx-rng.c
@@ -0,0 +1,73 @@
1/*
2 * drivers/char/rng/ixp4xx-rng.c
3 *
4 * RNG driver for Intel IXP4xx family of NPUs
5 *
6 * Author: Deepak Saxena <dsaxena@plexity.net>
7 *
8 * Copyright 2005 (c) MontaVista Software, Inc.
9 *
10 * Fixes by Michael Buesch
11 *
12 * This file is licensed under the terms of the GNU General Public
13 * License version 2. This program is licensed "as is" without any
14 * warranty of any kind, whether express or implied.
15 */
16
17#include <linux/kernel.h>
18#include <linux/config.h>
19#include <linux/types.h>
20#include <linux/module.h>
21#include <linux/moduleparam.h>
22#include <linux/init.h>
23#include <linux/bitops.h>
24#include <linux/hw_random.h>
25
26#include <asm/io.h>
27#include <asm/hardware.h>
28
29
30static int ixp4xx_rng_data_read(struct hwrng *rng, u32 *buffer)
31{
32 void __iomem * rng_base = (void __iomem *)rng->priv;
33
34 *buffer = __raw_readl(rng_base);
35
36 return 4;
37}
38
39static struct hwrng ixp4xx_rng_ops = {
40 .name = "ixp4xx",
41 .data_read = ixp4xx_rng_data_read,
42};
43
44static int __init ixp4xx_rng_init(void)
45{
46 void __iomem * rng_base;
47 int err;
48
49 rng_base = ioremap(0x70002100, 4);
50 if (!rng_base)
51 return -ENOMEM;
52 ixp4xx_rng_ops.priv = (unsigned long)rng_base;
53 err = hwrng_register(&ixp4xx_rng_ops);
54 if (err)
55 iounmap(rng_base);
56
57 return err;
58}
59
60static void __exit ixp4xx_rng_exit(void)
61{
62 void __iomem * rng_base = (void __iomem *)ixp4xx_rng_ops.priv;
63
64 hwrng_unregister(&ixp4xx_rng_ops);
65 iounmap(rng_base);
66}
67
68subsys_initcall(ixp4xx_rng_init);
69module_exit(ixp4xx_rng_exit);
70
71MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>");
72MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver for IXP4xx");
73MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
new file mode 100644
index 000000000000..819516b35a79
--- /dev/null
+++ b/drivers/char/hw_random/omap-rng.c
@@ -0,0 +1,208 @@
1/*
2 * driver/char/hw_random/omap-rng.c
3 *
4 * RNG driver for TI OMAP CPU family
5 *
6 * Author: Deepak Saxena <dsaxena@plexity.net>
7 *
8 * Copyright 2005 (c) MontaVista Software, Inc.
9 *
10 * Mostly based on original driver:
11 *
12 * Copyright (C) 2005 Nokia Corporation
13 * Author: Juha Yrj��<juha.yrjola@nokia.com>
14 *
15 * This file is licensed under the terms of the GNU General Public
16 * License version 2. This program is licensed "as is" without any
17 * warranty of any kind, whether express or implied.
18 *
19 * TODO:
20 *
21 * - Make status updated be interrupt driven so we don't poll
22 *
23 */
24
25#include <linux/module.h>
26#include <linux/init.h>
27#include <linux/random.h>
28#include <linux/err.h>
29#include <linux/device.h>
30#include <linux/hw_random.h>
31
32#include <asm/io.h>
33#include <asm/hardware/clock.h>
34
35#define RNG_OUT_REG 0x00 /* Output register */
36#define RNG_STAT_REG 0x04 /* Status register
37 [0] = STAT_BUSY */
38#define RNG_ALARM_REG 0x24 /* Alarm register
39 [7:0] = ALARM_COUNTER */
40#define RNG_CONFIG_REG 0x28 /* Configuration register
41 [11:6] = RESET_COUNT
42 [5:3] = RING2_DELAY
43 [2:0] = RING1_DELAY */
44#define RNG_REV_REG 0x3c /* Revision register
45 [7:0] = REV_NB */
46#define RNG_MASK_REG 0x40 /* Mask and reset register
47 [2] = IT_EN
48 [1] = SOFTRESET
49 [0] = AUTOIDLE */
50#define RNG_SYSSTATUS 0x44 /* System status
51 [0] = RESETDONE */
52
53static void __iomem *rng_base;
54static struct clk *rng_ick;
55static struct device *rng_dev;
56
57static u32 omap_rng_read_reg(int reg)
58{
59 return __raw_readl(rng_base + reg);
60}
61
62static void omap_rng_write_reg(int reg, u32 val)
63{
64 __raw_writel(val, rng_base + reg);
65}
66
67/* REVISIT: Does the status bit really work on 16xx? */
68static int omap_rng_data_present(struct hwrng *rng)
69{
70 return omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1;
71}
72
73static int omap_rng_data_read(struct hwrng *rng, u32 *data)
74{
75 *data = omap_rng_read_reg(RNG_OUT_REG);
76
77 return 4;
78}
79
80static struct hwrng omap_rng_ops = {
81 .name = "omap",
82 .data_present = omap_rng_data_present,
83 .data_read = omap_rng_data_read,
84};
85
86static int __init omap_rng_probe(struct device *dev)
87{
88 struct platform_device *pdev = to_platform_device(dev);
89 struct resource *res, *mem;
90 int ret;
91
92 /*
93 * A bit ugly, and it will never actually happen but there can
94 * be only one RNG and this catches any bork
95 */
96 BUG_ON(rng_dev);
97
98 if (cpu_is_omap24xx()) {
99 rng_ick = clk_get(NULL, "rng_ick");
100 if (IS_ERR(rng_ick)) {
101 dev_err(dev, "Could not get rng_ick\n");
102 ret = PTR_ERR(rng_ick);
103 return ret;
104 }
105 else {
106 clk_use(rng_ick);
107 }
108 }
109
110 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
111
112 if (!res)
113 return -ENOENT;
114
115 mem = request_mem_region(res->start, res->end - res->start + 1,
116 pdev->name);
117 if (mem == NULL)
118 return -EBUSY;
119
120 dev_set_drvdata(dev, mem);
121 rng_base = (u32 __iomem *)io_p2v(res->start);
122
123 ret = hwrng_register(&omap_rng_ops);
124 if (ret) {
125 release_resource(mem);
126 rng_base = NULL;
127 return ret;
128 }
129
130 dev_info(dev, "OMAP Random Number Generator ver. %02x\n",
131 omap_rng_read_reg(RNG_REV_REG));
132 omap_rng_write_reg(RNG_MASK_REG, 0x1);
133
134 rng_dev = dev;
135
136 return 0;
137}
138
139static int __exit omap_rng_remove(struct device *dev)
140{
141 struct resource *mem = dev_get_drvdata(dev);
142
143 hwrng_unregister(&omap_rng_ops);
144
145 omap_rng_write_reg(RNG_MASK_REG, 0x0);
146
147 if (cpu_is_omap24xx()) {
148 clk_unuse(rng_ick);
149 clk_put(rng_ick);
150 }
151
152 release_resource(mem);
153 rng_base = NULL;
154
155 return 0;
156}
157
158#ifdef CONFIG_PM
159
160static int omap_rng_suspend(struct device *dev, pm_message_t message, u32 level)
161{
162 omap_rng_write_reg(RNG_MASK_REG, 0x0);
163
164 return 0;
165}
166
167static int omap_rng_resume(struct device *dev, pm_message_t message, u32 level)
168{
169 omap_rng_write_reg(RNG_MASK_REG, 0x1);
170
171 return 1;
172}
173
174#else
175
176#define omap_rng_suspend NULL
177#define omap_rng_resume NULL
178
179#endif
180
181
182static struct device_driver omap_rng_driver = {
183 .name = "omap_rng",
184 .bus = &platform_bus_type,
185 .probe = omap_rng_probe,
186 .remove = __exit_p(omap_rng_remove),
187 .suspend = omap_rng_suspend,
188 .resume = omap_rng_resume
189};
190
191static int __init omap_rng_init(void)
192{
193 if (!cpu_is_omap16xx() && !cpu_is_omap24xx())
194 return -ENODEV;
195
196 return driver_register(&omap_rng_driver);
197}
198
199static void __exit omap_rng_exit(void)
200{
201 driver_unregister(&omap_rng_driver);
202}
203
204module_init(omap_rng_init);
205module_exit(omap_rng_exit);
206
207MODULE_AUTHOR("Deepak Saxena (and others)");
208MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/via-rng.c b/drivers/char/hw_random/via-rng.c
new file mode 100644
index 000000000000..0e786b617bb8
--- /dev/null
+++ b/drivers/char/hw_random/via-rng.c
@@ -0,0 +1,183 @@
1/*
2 * RNG driver for VIA RNGs
3 *
4 * Copyright 2005 (c) MontaVista Software, Inc.
5 *
6 * with the majority of the code coming from:
7 *
8 * Hardware driver for the Intel/AMD/VIA Random Number Generators (RNG)
9 * (c) Copyright 2003 Red Hat Inc <jgarzik@redhat.com>
10 *
11 * derived from
12 *
13 * Hardware driver for the AMD 768 Random Number Generator (RNG)
14 * (c) Copyright 2001 Red Hat Inc <alan@redhat.com>
15 *
16 * derived from
17 *
18 * Hardware driver for Intel i810 Random Number Generator (RNG)
19 * Copyright 2000,2001 Jeff Garzik <jgarzik@pobox.com>
20 * Copyright 2000,2001 Philipp Rumpf <prumpf@mandrakesoft.com>
21 *
22 * This file is licensed under the terms of the GNU General Public
23 * License version 2. This program is licensed "as is" without any
24 * warranty of any kind, whether express or implied.
25 */
26
27#include <linux/module.h>
28#include <linux/kernel.h>
29#include <linux/pci.h>
30#include <linux/hw_random.h>
31#include <asm/io.h>
32#include <asm/msr.h>
33#include <asm/cpufeature.h>
34
35
36#define PFX KBUILD_MODNAME ": "
37
38
39enum {
40 VIA_STRFILT_CNT_SHIFT = 16,
41 VIA_STRFILT_FAIL = (1 << 15),
42 VIA_STRFILT_ENABLE = (1 << 14),
43 VIA_RAWBITS_ENABLE = (1 << 13),
44 VIA_RNG_ENABLE = (1 << 6),
45 VIA_XSTORE_CNT_MASK = 0x0F,
46
47 VIA_RNG_CHUNK_8 = 0x00, /* 64 rand bits, 64 stored bits */
48 VIA_RNG_CHUNK_4 = 0x01, /* 32 rand bits, 32 stored bits */
49 VIA_RNG_CHUNK_4_MASK = 0xFFFFFFFF,
50 VIA_RNG_CHUNK_2 = 0x02, /* 16 rand bits, 32 stored bits */
51 VIA_RNG_CHUNK_2_MASK = 0xFFFF,
52 VIA_RNG_CHUNK_1 = 0x03, /* 8 rand bits, 32 stored bits */
53 VIA_RNG_CHUNK_1_MASK = 0xFF,
54};
55
56/*
57 * Investigate using the 'rep' prefix to obtain 32 bits of random data
58 * in one insn. The upside is potentially better performance. The
59 * downside is that the instruction becomes no longer atomic. Due to
60 * this, just like familiar issues with /dev/random itself, the worst
61 * case of a 'rep xstore' could potentially pause a cpu for an
62 * unreasonably long time. In practice, this condition would likely
63 * only occur when the hardware is failing. (or so we hope :))
64 *
65 * Another possible performance boost may come from simply buffering
66 * until we have 4 bytes, thus returning a u32 at a time,
67 * instead of the current u8-at-a-time.
68 */
69
70static inline u32 xstore(u32 *addr, u32 edx_in)
71{
72 u32 eax_out;
73
74 asm(".byte 0x0F,0xA7,0xC0 /* xstore %%edi (addr=%0) */"
75 :"=m"(*addr), "=a"(eax_out)
76 :"D"(addr), "d"(edx_in));
77
78 return eax_out;
79}
80
81static int via_rng_data_present(struct hwrng *rng)
82{
83 u32 bytes_out;
84 u32 *via_rng_datum = (u32 *)(&rng->priv);
85
86 /* We choose the recommended 1-byte-per-instruction RNG rate,
87 * for greater randomness at the expense of speed. Larger
88 * values 2, 4, or 8 bytes-per-instruction yield greater
89 * speed at lesser randomness.
90 *
91 * If you change this to another VIA_CHUNK_n, you must also
92 * change the ->n_bytes values in rng_vendor_ops[] tables.
93 * VIA_CHUNK_8 requires further code changes.
94 *
95 * A copy of MSR_VIA_RNG is placed in eax_out when xstore
96 * completes.
97 */
98
99 *via_rng_datum = 0; /* paranoia, not really necessary */
100 bytes_out = xstore(via_rng_datum, VIA_RNG_CHUNK_1);
101 bytes_out &= VIA_XSTORE_CNT_MASK;
102 if (bytes_out == 0)
103 return 0;
104 return 1;
105}
106
107static int via_rng_data_read(struct hwrng *rng, u32 *data)
108{
109 u32 via_rng_datum = (u32)rng->priv;
110
111 *data = via_rng_datum;
112
113 return 1;
114}
115
116static int via_rng_init(struct hwrng *rng)
117{
118 u32 lo, hi, old_lo;
119
120 /* Control the RNG via MSR. Tread lightly and pay very close
121 * close attention to values written, as the reserved fields
122 * are documented to be "undefined and unpredictable"; but it
123 * does not say to write them as zero, so I make a guess that
124 * we restore the values we find in the register.
125 */
126 rdmsr(MSR_VIA_RNG, lo, hi);
127
128 old_lo = lo;
129 lo &= ~(0x7f << VIA_STRFILT_CNT_SHIFT);
130 lo &= ~VIA_XSTORE_CNT_MASK;
131 lo &= ~(VIA_STRFILT_ENABLE | VIA_STRFILT_FAIL | VIA_RAWBITS_ENABLE);
132 lo |= VIA_RNG_ENABLE;
133
134 if (lo != old_lo)
135 wrmsr(MSR_VIA_RNG, lo, hi);
136
137 /* perhaps-unnecessary sanity check; remove after testing if
138 unneeded */
139 rdmsr(MSR_VIA_RNG, lo, hi);
140 if ((lo & VIA_RNG_ENABLE) == 0) {
141 printk(KERN_ERR PFX "cannot enable VIA C3 RNG, aborting\n");
142 return -ENODEV;
143 }
144
145 return 0;
146}
147
148
149static struct hwrng via_rng = {
150 .name = "via",
151 .init = via_rng_init,
152 .data_present = via_rng_data_present,
153 .data_read = via_rng_data_read,
154};
155
156
157static int __init mod_init(void)
158{
159 int err;
160
161 if (!cpu_has_xstore)
162 return -ENODEV;
163 printk(KERN_INFO "VIA RNG detected\n");
164 err = hwrng_register(&via_rng);
165 if (err) {
166 printk(KERN_ERR PFX "RNG registering failed (%d)\n",
167 err);
168 goto out;
169 }
170out:
171 return err;
172}
173
174static void __exit mod_exit(void)
175{
176 hwrng_unregister(&via_rng);
177}
178
179subsys_initcall(mod_init);
180module_exit(mod_exit);
181
182MODULE_DESCRIPTION("H/W RNG driver for VIA chipsets");
183MODULE_LICENSE("GPL");
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c
index 586f1f81937a..b03ddab1bef5 100644
--- a/drivers/char/ipmi/ipmi_msghandler.c
+++ b/drivers/char/ipmi/ipmi_msghandler.c
@@ -936,11 +936,8 @@ int ipmi_set_gets_events(ipmi_user_t user, int val)
936 936
937 if (val) { 937 if (val) {
938 /* Deliver any queued events. */ 938 /* Deliver any queued events. */
939 list_for_each_entry_safe(msg, msg2, &intf->waiting_events, 939 list_for_each_entry_safe(msg, msg2, &intf->waiting_events, link)
940 link) { 940 list_move_tail(&msg->link, &msgs);
941 list_del(&msg->link);
942 list_add_tail(&msg->link, &msgs);
943 }
944 intf->waiting_events_count = 0; 941 intf->waiting_events_count = 0;
945 } 942 }
946 943
diff --git a/drivers/char/keyboard.c b/drivers/char/keyboard.c
index edd996f6fb87..4bb3d2272604 100644
--- a/drivers/char/keyboard.c
+++ b/drivers/char/keyboard.c
@@ -151,6 +151,7 @@ unsigned char kbd_sysrq_xlate[KEY_MAX + 1] =
151 "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */ 151 "230\177\000\000\213\214\000\000\000\000\000\000\000\000\000\000" /* 0x50 - 0x5f */
152 "\r\000/"; /* 0x60 - 0x6f */ 152 "\r\000/"; /* 0x60 - 0x6f */
153static int sysrq_down; 153static int sysrq_down;
154static int sysrq_alt_use;
154#endif 155#endif
155static int sysrq_alt; 156static int sysrq_alt;
156 157
@@ -673,7 +674,7 @@ static void k_dead2(struct vc_data *vc, unsigned char value, char up_flag, struc
673 */ 674 */
674static void k_dead(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) 675static void k_dead(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
675{ 676{
676 static unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' }; 677 static const unsigned char ret_diacr[NR_DEAD] = {'`', '\'', '^', '~', '"', ',' };
677 value = ret_diacr[value]; 678 value = ret_diacr[value];
678 k_deadunicode(vc, value, up_flag, regs); 679 k_deadunicode(vc, value, up_flag, regs);
679} 680}
@@ -710,8 +711,8 @@ static void k_cur(struct vc_data *vc, unsigned char value, char up_flag, struct
710 711
711static void k_pad(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs) 712static void k_pad(struct vc_data *vc, unsigned char value, char up_flag, struct pt_regs *regs)
712{ 713{
713 static const char *pad_chars = "0123456789+-*/\015,.?()#"; 714 static const char pad_chars[] = "0123456789+-*/\015,.?()#";
714 static const char *app_map = "pqrstuvwxylSRQMnnmPQS"; 715 static const char app_map[] = "pqrstuvwxylSRQMnnmPQS";
715 716
716 if (up_flag) 717 if (up_flag)
717 return; /* no action, if this is a key release */ 718 return; /* no action, if this is a key release */
@@ -1036,7 +1037,7 @@ static void kbd_refresh_leds(struct input_handle *handle)
1036#define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\ 1037#define HW_RAW(dev) (test_bit(EV_MSC, dev->evbit) && test_bit(MSC_RAW, dev->mscbit) &&\
1037 ((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001)) 1038 ((dev)->id.bustype == BUS_I8042) && ((dev)->id.vendor == 0x0001) && ((dev)->id.product == 0x0001))
1038 1039
1039static unsigned short x86_keycodes[256] = 1040static const unsigned short x86_keycodes[256] =
1040 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 1041 { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
1041 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 1042 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
1042 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 1043 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
@@ -1074,11 +1075,13 @@ static int emulate_raw(struct vc_data *vc, unsigned int keycode,
1074 put_queue(vc, 0x1d | up_flag); 1075 put_queue(vc, 0x1d | up_flag);
1075 put_queue(vc, 0x45 | up_flag); 1076 put_queue(vc, 0x45 | up_flag);
1076 return 0; 1077 return 0;
1077 case KEY_HANGUEL: 1078 case KEY_HANGEUL:
1078 if (!up_flag) put_queue(vc, 0xf1); 1079 if (!up_flag)
1080 put_queue(vc, 0xf2);
1079 return 0; 1081 return 0;
1080 case KEY_HANJA: 1082 case KEY_HANJA:
1081 if (!up_flag) put_queue(vc, 0xf2); 1083 if (!up_flag)
1084 put_queue(vc, 0xf1);
1082 return 0; 1085 return 0;
1083 } 1086 }
1084 1087
@@ -1143,7 +1146,7 @@ static void kbd_keycode(unsigned int keycode, int down,
1143 kbd = kbd_table + fg_console; 1146 kbd = kbd_table + fg_console;
1144 1147
1145 if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT) 1148 if (keycode == KEY_LEFTALT || keycode == KEY_RIGHTALT)
1146 sysrq_alt = down; 1149 sysrq_alt = down ? keycode : 0;
1147#ifdef CONFIG_SPARC 1150#ifdef CONFIG_SPARC
1148 if (keycode == KEY_STOP) 1151 if (keycode == KEY_STOP)
1149 sparc_l1_a_state = down; 1152 sparc_l1_a_state = down;
@@ -1163,9 +1166,14 @@ static void kbd_keycode(unsigned int keycode, int down,
1163 1166
1164#ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */ 1167#ifdef CONFIG_MAGIC_SYSRQ /* Handle the SysRq Hack */
1165 if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) { 1168 if (keycode == KEY_SYSRQ && (sysrq_down || (down == 1 && sysrq_alt))) {
1166 sysrq_down = down; 1169 if (!sysrq_down) {
1170 sysrq_down = down;
1171 sysrq_alt_use = sysrq_alt;
1172 }
1167 return; 1173 return;
1168 } 1174 }
1175 if (sysrq_down && !down && keycode == sysrq_alt_use)
1176 sysrq_down = 0;
1169 if (sysrq_down && down && !rep) { 1177 if (sysrq_down && down && !rep) {
1170 handle_sysrq(kbd_sysrq_xlate[keycode], regs, tty); 1178 handle_sysrq(kbd_sysrq_xlate[keycode], regs, tty);
1171 return; 1179 return;
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 6c94879e0b99..714d95ff2f1e 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -98,7 +98,22 @@
98#include <asm/system.h> 98#include <asm/system.h>
99#include <asm/uaccess.h> 99#include <asm/uaccess.h>
100 100
101#define MAX_NR_CON_DRIVER 16
101 102
103#define CON_DRIVER_FLAG_MODULE 1
104#define CON_DRIVER_FLAG_INIT 2
105
106struct con_driver {
107 const struct consw *con;
108 const char *desc;
109 struct class_device *class_dev;
110 int node;
111 int first;
112 int last;
113 int flag;
114};
115
116static struct con_driver registered_con_driver[MAX_NR_CON_DRIVER];
102const struct consw *conswitchp; 117const struct consw *conswitchp;
103 118
104/* A bitmap for codes <32. A bit of 1 indicates that the code 119/* A bitmap for codes <32. A bit of 1 indicates that the code
@@ -2557,7 +2572,7 @@ static int __init con_init(void)
2557{ 2572{
2558 const char *display_desc = NULL; 2573 const char *display_desc = NULL;
2559 struct vc_data *vc; 2574 struct vc_data *vc;
2560 unsigned int currcons = 0; 2575 unsigned int currcons = 0, i;
2561 2576
2562 acquire_console_sem(); 2577 acquire_console_sem();
2563 2578
@@ -2569,6 +2584,22 @@ static int __init con_init(void)
2569 return 0; 2584 return 0;
2570 } 2585 }
2571 2586
2587 for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
2588 struct con_driver *con_driver = &registered_con_driver[i];
2589
2590 if (con_driver->con == NULL) {
2591 con_driver->con = conswitchp;
2592 con_driver->desc = display_desc;
2593 con_driver->flag = CON_DRIVER_FLAG_INIT;
2594 con_driver->first = 0;
2595 con_driver->last = MAX_NR_CONSOLES - 1;
2596 break;
2597 }
2598 }
2599
2600 for (i = 0; i < MAX_NR_CONSOLES; i++)
2601 con_driver_map[i] = conswitchp;
2602
2572 init_timer(&console_timer); 2603 init_timer(&console_timer);
2573 console_timer.function = blank_screen_t; 2604 console_timer.function = blank_screen_t;
2574 if (blankinterval) { 2605 if (blankinterval) {
@@ -2656,38 +2687,53 @@ int __init vty_init(void)
2656} 2687}
2657 2688
2658#ifndef VT_SINGLE_DRIVER 2689#ifndef VT_SINGLE_DRIVER
2690#include <linux/device.h>
2659 2691
2660/* 2692static struct class *vtconsole_class;
2661 * If we support more console drivers, this function is used
2662 * when a driver wants to take over some existing consoles
2663 * and become default driver for newly opened ones.
2664 */
2665 2693
2666int take_over_console(const struct consw *csw, int first, int last, int deflt) 2694static int bind_con_driver(const struct consw *csw, int first, int last,
2695 int deflt)
2667{ 2696{
2668 int i, j = -1; 2697 struct module *owner = csw->owner;
2669 const char *desc; 2698 const char *desc = NULL;
2670 struct module *owner; 2699 struct con_driver *con_driver;
2700 int i, j = -1, k = -1, retval = -ENODEV;
2671 2701
2672 owner = csw->owner;
2673 if (!try_module_get(owner)) 2702 if (!try_module_get(owner))
2674 return -ENODEV; 2703 return -ENODEV;
2675 2704
2676 acquire_console_sem(); 2705 acquire_console_sem();
2677 2706
2678 desc = csw->con_startup(); 2707 /* check if driver is registered */
2679 if (!desc) { 2708 for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
2680 release_console_sem(); 2709 con_driver = &registered_con_driver[i];
2681 module_put(owner); 2710
2682 return -ENODEV; 2711 if (con_driver->con == csw) {
2712 desc = con_driver->desc;
2713 retval = 0;
2714 break;
2715 }
2716 }
2717
2718 if (retval)
2719 goto err;
2720
2721 if (!(con_driver->flag & CON_DRIVER_FLAG_INIT)) {
2722 csw->con_startup();
2723 con_driver->flag |= CON_DRIVER_FLAG_INIT;
2683 } 2724 }
2725
2684 if (deflt) { 2726 if (deflt) {
2685 if (conswitchp) 2727 if (conswitchp)
2686 module_put(conswitchp->owner); 2728 module_put(conswitchp->owner);
2729
2687 __module_get(owner); 2730 __module_get(owner);
2688 conswitchp = csw; 2731 conswitchp = csw;
2689 } 2732 }
2690 2733
2734 first = max(first, con_driver->first);
2735 last = min(last, con_driver->last);
2736
2691 for (i = first; i <= last; i++) { 2737 for (i = first; i <= last; i++) {
2692 int old_was_color; 2738 int old_was_color;
2693 struct vc_data *vc = vc_cons[i].d; 2739 struct vc_data *vc = vc_cons[i].d;
@@ -2701,15 +2747,17 @@ int take_over_console(const struct consw *csw, int first, int last, int deflt)
2701 continue; 2747 continue;
2702 2748
2703 j = i; 2749 j = i;
2704 if (CON_IS_VISIBLE(vc)) 2750
2751 if (CON_IS_VISIBLE(vc)) {
2752 k = i;
2705 save_screen(vc); 2753 save_screen(vc);
2754 }
2755
2706 old_was_color = vc->vc_can_do_color; 2756 old_was_color = vc->vc_can_do_color;
2707 vc->vc_sw->con_deinit(vc); 2757 vc->vc_sw->con_deinit(vc);
2708 vc->vc_origin = (unsigned long)vc->vc_screenbuf; 2758 vc->vc_origin = (unsigned long)vc->vc_screenbuf;
2709 vc->vc_visible_origin = vc->vc_origin;
2710 vc->vc_scr_end = vc->vc_origin + vc->vc_screenbuf_size;
2711 vc->vc_pos = vc->vc_origin + vc->vc_size_row * vc->vc_y + 2 * vc->vc_x;
2712 visual_init(vc, i, 0); 2759 visual_init(vc, i, 0);
2760 set_origin(vc);
2713 update_attr(vc); 2761 update_attr(vc);
2714 2762
2715 /* If the console changed between mono <-> color, then 2763 /* If the console changed between mono <-> color, then
@@ -2718,36 +2766,506 @@ int take_over_console(const struct consw *csw, int first, int last, int deflt)
2718 */ 2766 */
2719 if (old_was_color != vc->vc_can_do_color) 2767 if (old_was_color != vc->vc_can_do_color)
2720 clear_buffer_attributes(vc); 2768 clear_buffer_attributes(vc);
2721
2722 if (CON_IS_VISIBLE(vc))
2723 update_screen(vc);
2724 } 2769 }
2770
2725 printk("Console: switching "); 2771 printk("Console: switching ");
2726 if (!deflt) 2772 if (!deflt)
2727 printk("consoles %d-%d ", first+1, last+1); 2773 printk("consoles %d-%d ", first+1, last+1);
2728 if (j >= 0) 2774 if (j >= 0) {
2775 struct vc_data *vc = vc_cons[j].d;
2776
2729 printk("to %s %s %dx%d\n", 2777 printk("to %s %s %dx%d\n",
2730 vc_cons[j].d->vc_can_do_color ? "colour" : "mono", 2778 vc->vc_can_do_color ? "colour" : "mono",
2731 desc, vc_cons[j].d->vc_cols, vc_cons[j].d->vc_rows); 2779 desc, vc->vc_cols, vc->vc_rows);
2732 else 2780
2781 if (k >= 0) {
2782 vc = vc_cons[k].d;
2783 update_screen(vc);
2784 }
2785 } else
2733 printk("to %s\n", desc); 2786 printk("to %s\n", desc);
2734 2787
2788 retval = 0;
2789err:
2735 release_console_sem(); 2790 release_console_sem();
2791 module_put(owner);
2792 return retval;
2793};
2794
2795#ifdef CONFIG_VT_HW_CONSOLE_BINDING
2796static int con_is_graphics(const struct consw *csw, int first, int last)
2797{
2798 int i, retval = 0;
2799
2800 for (i = first; i <= last; i++) {
2801 struct vc_data *vc = vc_cons[i].d;
2802
2803 if (vc && vc->vc_mode == KD_GRAPHICS) {
2804 retval = 1;
2805 break;
2806 }
2807 }
2808
2809 return retval;
2810}
2811
2812static int unbind_con_driver(const struct consw *csw, int first, int last,
2813 int deflt)
2814{
2815 struct module *owner = csw->owner;
2816 const struct consw *defcsw = NULL;
2817 struct con_driver *con_driver = NULL, *con_back = NULL;
2818 int i, retval = -ENODEV;
2819
2820 if (!try_module_get(owner))
2821 return -ENODEV;
2822
2823 acquire_console_sem();
2824
2825 /* check if driver is registered and if it is unbindable */
2826 for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
2827 con_driver = &registered_con_driver[i];
2828
2829 if (con_driver->con == csw &&
2830 con_driver->flag & CON_DRIVER_FLAG_MODULE) {
2831 retval = 0;
2832 break;
2833 }
2834 }
2835
2836 if (retval) {
2837 release_console_sem();
2838 goto err;
2839 }
2840
2841 retval = -ENODEV;
2842
2843 /* check if backup driver exists */
2844 for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
2845 con_back = &registered_con_driver[i];
2846
2847 if (con_back->con &&
2848 !(con_back->flag & CON_DRIVER_FLAG_MODULE)) {
2849 defcsw = con_back->con;
2850 retval = 0;
2851 break;
2852 }
2853 }
2854
2855 if (retval) {
2856 release_console_sem();
2857 goto err;
2858 }
2859
2860 if (!con_is_bound(csw)) {
2861 release_console_sem();
2862 goto err;
2863 }
2864
2865 first = max(first, con_driver->first);
2866 last = min(last, con_driver->last);
2867
2868 for (i = first; i <= last; i++) {
2869 if (con_driver_map[i] == csw) {
2870 module_put(csw->owner);
2871 con_driver_map[i] = NULL;
2872 }
2873 }
2874
2875 if (!con_is_bound(defcsw)) {
2876 const struct consw *defconsw = conswitchp;
2877
2878 defcsw->con_startup();
2879 con_back->flag |= CON_DRIVER_FLAG_INIT;
2880 /*
2881 * vgacon may change the default driver to point
2882 * to dummycon, we restore it here...
2883 */
2884 conswitchp = defconsw;
2885 }
2886
2887 if (!con_is_bound(csw))
2888 con_driver->flag &= ~CON_DRIVER_FLAG_INIT;
2736 2889
2890 release_console_sem();
2891 /* ignore return value, binding should not fail */
2892 bind_con_driver(defcsw, first, last, deflt);
2893err:
2737 module_put(owner); 2894 module_put(owner);
2895 return retval;
2896
2897}
2898
2899static int vt_bind(struct con_driver *con)
2900{
2901 const struct consw *defcsw = NULL, *csw = NULL;
2902 int i, more = 1, first = -1, last = -1, deflt = 0;
2903
2904 if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE) ||
2905 con_is_graphics(con->con, con->first, con->last))
2906 goto err;
2907
2908 csw = con->con;
2909
2910 for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
2911 struct con_driver *con = &registered_con_driver[i];
2912
2913 if (con->con && !(con->flag & CON_DRIVER_FLAG_MODULE)) {
2914 defcsw = con->con;
2915 break;
2916 }
2917 }
2918
2919 if (!defcsw)
2920 goto err;
2921
2922 while (more) {
2923 more = 0;
2924
2925 for (i = con->first; i <= con->last; i++) {
2926 if (con_driver_map[i] == defcsw) {
2927 if (first == -1)
2928 first = i;
2929 last = i;
2930 more = 1;
2931 } else if (first != -1)
2932 break;
2933 }
2934
2935 if (first == 0 && last == MAX_NR_CONSOLES -1)
2936 deflt = 1;
2937
2938 if (first != -1)
2939 bind_con_driver(csw, first, last, deflt);
2940
2941 first = -1;
2942 last = -1;
2943 deflt = 0;
2944 }
2945
2946err:
2738 return 0; 2947 return 0;
2739} 2948}
2740 2949
2741void give_up_console(const struct consw *csw) 2950static int vt_unbind(struct con_driver *con)
2951{
2952 const struct consw *csw = NULL;
2953 int i, more = 1, first = -1, last = -1, deflt = 0;
2954
2955 if (!con->con || !(con->flag & CON_DRIVER_FLAG_MODULE) ||
2956 con_is_graphics(con->con, con->first, con->last))
2957 goto err;
2958
2959 csw = con->con;
2960
2961 while (more) {
2962 more = 0;
2963
2964 for (i = con->first; i <= con->last; i++) {
2965 if (con_driver_map[i] == csw) {
2966 if (first == -1)
2967 first = i;
2968 last = i;
2969 more = 1;
2970 } else if (first != -1)
2971 break;
2972 }
2973
2974 if (first == 0 && last == MAX_NR_CONSOLES -1)
2975 deflt = 1;
2976
2977 if (first != -1)
2978 unbind_con_driver(csw, first, last, deflt);
2979
2980 first = -1;
2981 last = -1;
2982 deflt = 0;
2983 }
2984
2985err:
2986 return 0;
2987}
2988#else
2989static inline int vt_bind(struct con_driver *con)
2990{
2991 return 0;
2992}
2993static inline int vt_unbind(struct con_driver *con)
2994{
2995 return 0;
2996}
2997#endif /* CONFIG_VT_HW_CONSOLE_BINDING */
2998
2999static ssize_t store_bind(struct class_device *class_device,
3000 const char *buf, size_t count)
3001{
3002 struct con_driver *con = class_get_devdata(class_device);
3003 int bind = simple_strtoul(buf, NULL, 0);
3004
3005 if (bind)
3006 vt_bind(con);
3007 else
3008 vt_unbind(con);
3009
3010 return count;
3011}
3012
3013static ssize_t show_bind(struct class_device *class_device, char *buf)
3014{
3015 struct con_driver *con = class_get_devdata(class_device);
3016 int bind = con_is_bound(con->con);
3017
3018 return snprintf(buf, PAGE_SIZE, "%i\n", bind);
3019}
3020
3021static ssize_t show_name(struct class_device *class_device, char *buf)
3022{
3023 struct con_driver *con = class_get_devdata(class_device);
3024
3025 return snprintf(buf, PAGE_SIZE, "%s %s\n",
3026 (con->flag & CON_DRIVER_FLAG_MODULE) ? "(M)" : "(S)",
3027 con->desc);
3028
3029}
3030
3031static struct class_device_attribute class_device_attrs[] = {
3032 __ATTR(bind, S_IRUGO|S_IWUSR, show_bind, store_bind),
3033 __ATTR(name, S_IRUGO, show_name, NULL),
3034};
3035
3036static int vtconsole_init_class_device(struct con_driver *con)
3037{
3038 int i;
3039
3040 class_set_devdata(con->class_dev, con);
3041 for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
3042 class_device_create_file(con->class_dev,
3043 &class_device_attrs[i]);
3044
3045 return 0;
3046}
3047
3048static void vtconsole_deinit_class_device(struct con_driver *con)
2742{ 3049{
2743 int i; 3050 int i;
2744 3051
2745 for(i = 0; i < MAX_NR_CONSOLES; i++) 3052 for (i = 0; i < ARRAY_SIZE(class_device_attrs); i++)
3053 class_device_remove_file(con->class_dev,
3054 &class_device_attrs[i]);
3055}
3056
3057/**
3058 * con_is_bound - checks if driver is bound to the console
3059 * @csw: console driver
3060 *
3061 * RETURNS: zero if unbound, nonzero if bound
3062 *
3063 * Drivers can call this and if zero, they should release
3064 * all resources allocated on con_startup()
3065 */
3066int con_is_bound(const struct consw *csw)
3067{
3068 int i, bound = 0;
3069
3070 for (i = 0; i < MAX_NR_CONSOLES; i++) {
2746 if (con_driver_map[i] == csw) { 3071 if (con_driver_map[i] == csw) {
2747 module_put(csw->owner); 3072 bound = 1;
2748 con_driver_map[i] = NULL; 3073 break;
3074 }
3075 }
3076
3077 return bound;
3078}
3079EXPORT_SYMBOL(con_is_bound);
3080
3081/**
3082 * register_con_driver - register console driver to console layer
3083 * @csw: console driver
3084 * @first: the first console to take over, minimum value is 0
3085 * @last: the last console to take over, maximum value is MAX_NR_CONSOLES -1
3086 *
3087 * DESCRIPTION: This function registers a console driver which can later
3088 * bind to a range of consoles specified by @first and @last. It will
3089 * also initialize the console driver by calling con_startup().
3090 */
3091int register_con_driver(const struct consw *csw, int first, int last)
3092{
3093 struct module *owner = csw->owner;
3094 struct con_driver *con_driver;
3095 const char *desc;
3096 int i, retval = 0;
3097
3098 if (!try_module_get(owner))
3099 return -ENODEV;
3100
3101 acquire_console_sem();
3102
3103 for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
3104 con_driver = &registered_con_driver[i];
3105
3106 /* already registered */
3107 if (con_driver->con == csw)
3108 retval = -EINVAL;
3109 }
3110
3111 if (retval)
3112 goto err;
3113
3114 desc = csw->con_startup();
3115
3116 if (!desc)
3117 goto err;
3118
3119 retval = -EINVAL;
3120
3121 for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
3122 con_driver = &registered_con_driver[i];
3123
3124 if (con_driver->con == NULL) {
3125 con_driver->con = csw;
3126 con_driver->desc = desc;
3127 con_driver->node = i;
3128 con_driver->flag = CON_DRIVER_FLAG_MODULE |
3129 CON_DRIVER_FLAG_INIT;
3130 con_driver->first = first;
3131 con_driver->last = last;
3132 retval = 0;
3133 break;
3134 }
3135 }
3136
3137 if (retval)
3138 goto err;
3139
3140 con_driver->class_dev = class_device_create(vtconsole_class, NULL,
3141 MKDEV(0, con_driver->node),
3142 NULL, "vtcon%i",
3143 con_driver->node);
3144
3145 if (IS_ERR(con_driver->class_dev)) {
3146 printk(KERN_WARNING "Unable to create class_device for %s; "
3147 "errno = %ld\n", con_driver->desc,
3148 PTR_ERR(con_driver->class_dev));
3149 con_driver->class_dev = NULL;
3150 } else {
3151 vtconsole_init_class_device(con_driver);
3152 }
3153err:
3154 release_console_sem();
3155 module_put(owner);
3156 return retval;
3157}
3158EXPORT_SYMBOL(register_con_driver);
3159
3160/**
3161 * unregister_con_driver - unregister console driver from console layer
3162 * @csw: console driver
3163 *
3164 * DESCRIPTION: All drivers that registers to the console layer must
3165 * call this function upon exit, or if the console driver is in a state
3166 * where it won't be able to handle console services, such as the
3167 * framebuffer console without loaded framebuffer drivers.
3168 *
3169 * The driver must unbind first prior to unregistration.
3170 */
3171int unregister_con_driver(const struct consw *csw)
3172{
3173 int i, retval = -ENODEV;
3174
3175 acquire_console_sem();
3176
3177 /* cannot unregister a bound driver */
3178 if (con_is_bound(csw))
3179 goto err;
3180
3181 for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
3182 struct con_driver *con_driver = &registered_con_driver[i];
3183
3184 if (con_driver->con == csw &&
3185 con_driver->flag & CON_DRIVER_FLAG_MODULE) {
3186 vtconsole_deinit_class_device(con_driver);
3187 class_device_destroy(vtconsole_class,
3188 MKDEV(0, con_driver->node));
3189 con_driver->con = NULL;
3190 con_driver->desc = NULL;
3191 con_driver->class_dev = NULL;
3192 con_driver->node = 0;
3193 con_driver->flag = 0;
3194 con_driver->first = 0;
3195 con_driver->last = 0;
3196 retval = 0;
3197 break;
3198 }
3199 }
3200err:
3201 release_console_sem();
3202 return retval;
3203}
3204EXPORT_SYMBOL(unregister_con_driver);
3205
3206/*
3207 * If we support more console drivers, this function is used
3208 * when a driver wants to take over some existing consoles
3209 * and become default driver for newly opened ones.
3210 *
3211 * take_over_console is basically a register followed by unbind
3212 */
3213int take_over_console(const struct consw *csw, int first, int last, int deflt)
3214{
3215 int err;
3216
3217 err = register_con_driver(csw, first, last);
3218
3219 if (!err)
3220 bind_con_driver(csw, first, last, deflt);
3221
3222 return err;
3223}
3224
3225/*
3226 * give_up_console is a wrapper to unregister_con_driver. It will only
3227 * work if driver is fully unbound.
3228 */
3229void give_up_console(const struct consw *csw)
3230{
3231 unregister_con_driver(csw);
3232}
3233
3234static int __init vtconsole_class_init(void)
3235{
3236 int i;
3237
3238 vtconsole_class = class_create(THIS_MODULE, "vtconsole");
3239 if (IS_ERR(vtconsole_class)) {
3240 printk(KERN_WARNING "Unable to create vt console class; "
3241 "errno = %ld\n", PTR_ERR(vtconsole_class));
3242 vtconsole_class = NULL;
3243 }
3244
3245 /* Add system drivers to sysfs */
3246 for (i = 0; i < MAX_NR_CON_DRIVER; i++) {
3247 struct con_driver *con = &registered_con_driver[i];
3248
3249 if (con->con && !con->class_dev) {
3250 con->class_dev =
3251 class_device_create(vtconsole_class, NULL,
3252 MKDEV(0, con->node), NULL,
3253 "vtcon%i", con->node);
3254
3255 if (IS_ERR(con->class_dev)) {
3256 printk(KERN_WARNING "Unable to create "
3257 "class_device for %s; errno = %ld\n",
3258 con->desc, PTR_ERR(con->class_dev));
3259 con->class_dev = NULL;
3260 } else {
3261 vtconsole_init_class_device(con);
3262 }
2749 } 3263 }
3264 }
3265
3266 return 0;
2750} 3267}
3268postcore_initcall(vtconsole_class_init);
2751 3269
2752#endif 3270#endif
2753 3271