diff options
-rw-r--r-- | arch/ppc64/kernel/hvconsole.c | 33 | ||||
-rw-r--r-- | drivers/char/Makefile | 2 | ||||
-rw-r--r-- | drivers/char/hvc_console.c | 50 | ||||
-rw-r--r-- | drivers/char/hvc_vio.c | 125 | ||||
-rw-r--r-- | include/asm-ppc64/hvconsole.h | 9 |
5 files changed, 145 insertions, 74 deletions
diff --git a/arch/ppc64/kernel/hvconsole.c b/arch/ppc64/kernel/hvconsole.c index 94fb06198ea2..9d8876d92eb9 100644 --- a/arch/ppc64/kernel/hvconsole.c +++ b/arch/ppc64/kernel/hvconsole.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <asm/hvcall.h> | 28 | #include <asm/hvcall.h> |
29 | #include <asm/hvconsole.h> | 29 | #include <asm/hvconsole.h> |
30 | #include <asm/prom.h> | ||
31 | 30 | ||
32 | /** | 31 | /** |
33 | * hvc_get_chars - retrieve characters from firmware for denoted vterm adatper | 32 | * hvc_get_chars - retrieve characters from firmware for denoted vterm adatper |
@@ -88,35 +87,3 @@ int hvc_put_chars(uint32_t vtermno, const char *buf, int count) | |||
88 | } | 87 | } |
89 | 88 | ||
90 | EXPORT_SYMBOL(hvc_put_chars); | 89 | EXPORT_SYMBOL(hvc_put_chars); |
91 | |||
92 | /* | ||
93 | * We hope/assume that the first vty found corresponds to the first console | ||
94 | * device. | ||
95 | */ | ||
96 | static int hvc_find_vtys(void) | ||
97 | { | ||
98 | struct device_node *vty; | ||
99 | int num_found = 0; | ||
100 | |||
101 | for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL; | ||
102 | vty = of_find_node_by_name(vty, "vty")) { | ||
103 | uint32_t *vtermno; | ||
104 | |||
105 | /* We have statically defined space for only a certain number of | ||
106 | * console adapters. */ | ||
107 | if (num_found >= MAX_NR_HVC_CONSOLES) | ||
108 | break; | ||
109 | |||
110 | vtermno = (uint32_t *)get_property(vty, "reg", NULL); | ||
111 | if (!vtermno) | ||
112 | continue; | ||
113 | |||
114 | if (device_is_compatible(vty, "hvterm1")) { | ||
115 | hvc_instantiate(*vtermno, num_found); | ||
116 | ++num_found; | ||
117 | } | ||
118 | } | ||
119 | |||
120 | return num_found; | ||
121 | } | ||
122 | console_initcall(hvc_find_vtys); | ||
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 1aff819f3832..08f69287ea36 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
@@ -40,7 +40,7 @@ obj-$(CONFIG_N_HDLC) += n_hdlc.o | |||
40 | obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o | 40 | obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o |
41 | obj-$(CONFIG_SX) += sx.o generic_serial.o | 41 | obj-$(CONFIG_SX) += sx.o generic_serial.o |
42 | obj-$(CONFIG_RIO) += rio/ generic_serial.o | 42 | obj-$(CONFIG_RIO) += rio/ generic_serial.o |
43 | obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o hvsi.o | 43 | obj-$(CONFIG_HVC_CONSOLE) += hvc_console.o hvc_vio.o hvsi.o |
44 | obj-$(CONFIG_RAW_DRIVER) += raw.o | 44 | obj-$(CONFIG_RAW_DRIVER) += raw.o |
45 | obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o | 45 | obj-$(CONFIG_SGI_SNSC) += snsc.o snsc_event.o |
46 | obj-$(CONFIG_MMTIMER) += mmtimer.o | 46 | obj-$(CONFIG_MMTIMER) += mmtimer.o |
diff --git a/drivers/char/hvc_console.c b/drivers/char/hvc_console.c index d59c642f9654..df282cc9a7ab 100644 --- a/drivers/char/hvc_console.c +++ b/drivers/char/hvc_console.c | |||
@@ -41,7 +41,6 @@ | |||
41 | #include <linux/delay.h> | 41 | #include <linux/delay.h> |
42 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
43 | #include <asm/hvconsole.h> | 43 | #include <asm/hvconsole.h> |
44 | #include <asm/vio.h> | ||
45 | 44 | ||
46 | #define HVC_MAJOR 229 | 45 | #define HVC_MAJOR 229 |
47 | #define HVC_MINOR 0 | 46 | #define HVC_MINOR 0 |
@@ -90,7 +89,6 @@ struct hvc_struct { | |||
90 | int irq; | 89 | int irq; |
91 | struct list_head next; | 90 | struct list_head next; |
92 | struct kobject kobj; /* ref count & hvc_struct lifetime */ | 91 | struct kobject kobj; /* ref count & hvc_struct lifetime */ |
93 | struct vio_dev *vdev; | ||
94 | }; | 92 | }; |
95 | 93 | ||
96 | /* dynamic list of hvc_struct instances */ | 94 | /* dynamic list of hvc_struct instances */ |
@@ -279,6 +277,7 @@ int hvc_instantiate(uint32_t vtermno, int index) | |||
279 | 277 | ||
280 | return 0; | 278 | return 0; |
281 | } | 279 | } |
280 | EXPORT_SYMBOL(hvc_instantiate); | ||
282 | 281 | ||
283 | /* Wake the sleeping khvcd */ | 282 | /* Wake the sleeping khvcd */ |
284 | static void hvc_kick(void) | 283 | static void hvc_kick(void) |
@@ -738,26 +737,19 @@ static struct kobj_type hvc_kobj_type = { | |||
738 | .release = destroy_hvc_struct, | 737 | .release = destroy_hvc_struct, |
739 | }; | 738 | }; |
740 | 739 | ||
741 | static int __devinit hvc_probe( | 740 | struct hvc_struct __devinit *hvc_alloc(uint32_t vtermno, int irq) |
742 | struct vio_dev *dev, | ||
743 | const struct vio_device_id *id) | ||
744 | { | 741 | { |
745 | struct hvc_struct *hp; | 742 | struct hvc_struct *hp; |
746 | int i; | 743 | int i; |
747 | 744 | ||
748 | /* probed with invalid parameters. */ | ||
749 | if (!dev || !id) | ||
750 | return -EPERM; | ||
751 | |||
752 | hp = kmalloc(sizeof(*hp), GFP_KERNEL); | 745 | hp = kmalloc(sizeof(*hp), GFP_KERNEL); |
753 | if (!hp) | 746 | if (!hp) |
754 | return -ENOMEM; | 747 | return ERR_PTR(-ENOMEM); |
755 | 748 | ||
756 | memset(hp, 0x00, sizeof(*hp)); | 749 | memset(hp, 0x00, sizeof(*hp)); |
757 | hp->vtermno = dev->unit_address; | 750 | |
758 | hp->vdev = dev; | 751 | hp->vtermno = vtermno; |
759 | hp->vdev->dev.driver_data = hp; | 752 | hp->irq = irq; |
760 | hp->irq = dev->irq; | ||
761 | 753 | ||
762 | kobject_init(&hp->kobj); | 754 | kobject_init(&hp->kobj); |
763 | hp->kobj.ktype = &hvc_kobj_type; | 755 | hp->kobj.ktype = &hvc_kobj_type; |
@@ -782,12 +774,12 @@ static int __devinit hvc_probe( | |||
782 | list_add_tail(&(hp->next), &hvc_structs); | 774 | list_add_tail(&(hp->next), &hvc_structs); |
783 | spin_unlock(&hvc_structs_lock); | 775 | spin_unlock(&hvc_structs_lock); |
784 | 776 | ||
785 | return 0; | 777 | return hp; |
786 | } | 778 | } |
779 | EXPORT_SYMBOL(hvc_alloc); | ||
787 | 780 | ||
788 | static int __devexit hvc_remove(struct vio_dev *dev) | 781 | int __devexit hvc_remove(struct hvc_struct *hp) |
789 | { | 782 | { |
790 | struct hvc_struct *hp = dev->dev.driver_data; | ||
791 | unsigned long flags; | 783 | unsigned long flags; |
792 | struct kobject *kobjp; | 784 | struct kobject *kobjp; |
793 | struct tty_struct *tty; | 785 | struct tty_struct *tty; |
@@ -820,28 +812,12 @@ static int __devexit hvc_remove(struct vio_dev *dev) | |||
820 | tty_hangup(tty); | 812 | tty_hangup(tty); |
821 | return 0; | 813 | return 0; |
822 | } | 814 | } |
823 | 815 | EXPORT_SYMBOL(hvc_remove); | |
824 | char hvc_driver_name[] = "hvc_console"; | ||
825 | |||
826 | static struct vio_device_id hvc_driver_table[] __devinitdata= { | ||
827 | {"serial", "hvterm1"}, | ||
828 | { NULL, } | ||
829 | }; | ||
830 | MODULE_DEVICE_TABLE(vio, hvc_driver_table); | ||
831 | |||
832 | static struct vio_driver hvc_vio_driver = { | ||
833 | .name = hvc_driver_name, | ||
834 | .id_table = hvc_driver_table, | ||
835 | .probe = hvc_probe, | ||
836 | .remove = hvc_remove, | ||
837 | }; | ||
838 | 816 | ||
839 | /* Driver initialization. Follow console initialization. This is where the TTY | 817 | /* Driver initialization. Follow console initialization. This is where the TTY |
840 | * interfaces start to become available. */ | 818 | * interfaces start to become available. */ |
841 | int __init hvc_init(void) | 819 | int __init hvc_init(void) |
842 | { | 820 | { |
843 | int rc; | ||
844 | |||
845 | /* We need more than hvc_count adapters due to hotplug additions. */ | 821 | /* We need more than hvc_count adapters due to hotplug additions. */ |
846 | hvc_driver = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS); | 822 | hvc_driver = alloc_tty_driver(HVC_ALLOC_TTY_ADAPTERS); |
847 | if (!hvc_driver) | 823 | if (!hvc_driver) |
@@ -870,10 +846,7 @@ int __init hvc_init(void) | |||
870 | return -EIO; | 846 | return -EIO; |
871 | } | 847 | } |
872 | 848 | ||
873 | /* Register as a vio device to receive callbacks */ | 849 | return 0; |
874 | rc = vio_register_driver(&hvc_vio_driver); | ||
875 | |||
876 | return rc; | ||
877 | } | 850 | } |
878 | module_init(hvc_init); | 851 | module_init(hvc_init); |
879 | 852 | ||
@@ -884,7 +857,6 @@ static void __exit hvc_exit(void) | |||
884 | { | 857 | { |
885 | kthread_stop(hvc_task); | 858 | kthread_stop(hvc_task); |
886 | 859 | ||
887 | vio_unregister_driver(&hvc_vio_driver); | ||
888 | tty_unregister_driver(hvc_driver); | 860 | tty_unregister_driver(hvc_driver); |
889 | /* return tty_struct instances allocated in hvc_init(). */ | 861 | /* return tty_struct instances allocated in hvc_init(). */ |
890 | put_tty_driver(hvc_driver); | 862 | put_tty_driver(hvc_driver); |
diff --git a/drivers/char/hvc_vio.c b/drivers/char/hvc_vio.c new file mode 100644 index 000000000000..d2928f90ab51 --- /dev/null +++ b/drivers/char/hvc_vio.c | |||
@@ -0,0 +1,125 @@ | |||
1 | /* | ||
2 | * vio driver interface to hvc_console.c | ||
3 | * | ||
4 | * This code was moved here to allow the remaing code to be reused as a | ||
5 | * generic polling mode with semi-reliable transport driver core to the | ||
6 | * console and tty subsystems. | ||
7 | * | ||
8 | * | ||
9 | * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM | ||
10 | * Copyright (C) 2001 Paul Mackerras <paulus@au.ibm.com>, IBM | ||
11 | * Copyright (C) 2004 Benjamin Herrenschmidt <benh@kernel.crashing.org>, IBM Corp. | ||
12 | * Copyright (C) 2004 IBM Corporation | ||
13 | * | ||
14 | * Additional Author(s): | ||
15 | * Ryan S. Arnold <rsa@us.ibm.com> | ||
16 | * | ||
17 | * This program is free software; you can redistribute it and/or modify | ||
18 | * it under the terms of the GNU General Public License as published by | ||
19 | * the Free Software Foundation; either version 2 of the License, or | ||
20 | * (at your option) any later version. | ||
21 | * | ||
22 | * This program is distributed in the hope that it will be useful, | ||
23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
25 | * GNU General Public License for more details. | ||
26 | * | ||
27 | * You should have received a copy of the GNU General Public License | ||
28 | * along with this program; if not, write to the Free Software | ||
29 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
30 | */ | ||
31 | |||
32 | #include <linux/types.h> | ||
33 | #include <linux/init.h> | ||
34 | #include <asm/hvconsole.h> | ||
35 | #include <asm/vio.h> | ||
36 | #include <asm/prom.h> | ||
37 | |||
38 | char hvc_driver_name[] = "hvc_console"; | ||
39 | |||
40 | static struct vio_device_id hvc_driver_table[] __devinitdata = { | ||
41 | {"serial", "hvterm1"}, | ||
42 | { NULL, } | ||
43 | }; | ||
44 | MODULE_DEVICE_TABLE(vio, hvc_driver_table); | ||
45 | |||
46 | static int __devinit hvc_vio_probe(struct vio_dev *vdev, | ||
47 | const struct vio_device_id *id) | ||
48 | { | ||
49 | struct hvc_struct *hp; | ||
50 | |||
51 | /* probed with invalid parameters. */ | ||
52 | if (!vdev || !id) | ||
53 | return -EPERM; | ||
54 | |||
55 | hp = hvc_alloc(vdev->unit_address, vdev->irq); | ||
56 | if (IS_ERR(hp)) | ||
57 | return PTR_ERR(hp); | ||
58 | dev_set_drvdata(&vdev->dev, hp); | ||
59 | |||
60 | return 0; | ||
61 | } | ||
62 | |||
63 | static int __devexit hvc_vio_remove(struct vio_dev *vdev) | ||
64 | { | ||
65 | struct hvc_struct *hp = dev_get_drvdata(&vdev->dev); | ||
66 | |||
67 | return hvc_remove(hp); | ||
68 | } | ||
69 | |||
70 | static struct vio_driver hvc_vio_driver = { | ||
71 | .name = hvc_driver_name, | ||
72 | .id_table = hvc_driver_table, | ||
73 | .probe = hvc_vio_probe, | ||
74 | .remove = hvc_vio_remove, | ||
75 | .driver = { | ||
76 | .owner = THIS_MODULE, | ||
77 | } | ||
78 | }; | ||
79 | |||
80 | static int hvc_vio_init(void) | ||
81 | { | ||
82 | int rc; | ||
83 | |||
84 | /* Register as a vio device to receive callbacks */ | ||
85 | rc = vio_register_driver(&hvc_vio_driver); | ||
86 | |||
87 | return rc; | ||
88 | } | ||
89 | module_init(hvc_vio_init); /* after drivers/char/hvc_console.c */ | ||
90 | |||
91 | static void hvc_vio_exit(void) | ||
92 | { | ||
93 | vio_unregister_driver(&hvc_vio_driver); | ||
94 | } | ||
95 | module_exit(hvc_vio_exit); | ||
96 | |||
97 | /* the device tree order defines our numbering */ | ||
98 | static int hvc_find_vtys(void) | ||
99 | { | ||
100 | struct device_node *vty; | ||
101 | int num_found = 0; | ||
102 | |||
103 | for (vty = of_find_node_by_name(NULL, "vty"); vty != NULL; | ||
104 | vty = of_find_node_by_name(vty, "vty")) { | ||
105 | uint32_t *vtermno; | ||
106 | |||
107 | /* We have statically defined space for only a certain number | ||
108 | * of console adapters. | ||
109 | */ | ||
110 | if (num_found >= MAX_NR_HVC_CONSOLES) | ||
111 | break; | ||
112 | |||
113 | vtermno = (uint32_t *)get_property(vty, "reg", NULL); | ||
114 | if (!vtermno) | ||
115 | continue; | ||
116 | |||
117 | if (device_is_compatible(vty, "hvterm1")) { | ||
118 | hvc_instantiate(*vtermno, num_found); | ||
119 | ++num_found; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | return num_found; | ||
124 | } | ||
125 | console_initcall(hvc_find_vtys); | ||
diff --git a/include/asm-ppc64/hvconsole.h b/include/asm-ppc64/hvconsole.h index 91c2414ac00b..14667a78716d 100644 --- a/include/asm-ppc64/hvconsole.h +++ b/include/asm-ppc64/hvconsole.h | |||
@@ -29,9 +29,16 @@ | |||
29 | */ | 29 | */ |
30 | #define MAX_NR_HVC_CONSOLES 16 | 30 | #define MAX_NR_HVC_CONSOLES 16 |
31 | 31 | ||
32 | /* implemented by a low level driver */ | ||
32 | extern int hvc_get_chars(uint32_t vtermno, char *buf, int count); | 33 | extern int hvc_get_chars(uint32_t vtermno, char *buf, int count); |
33 | extern int hvc_put_chars(uint32_t vtermno, const char *buf, int count); | 34 | extern int hvc_put_chars(uint32_t vtermno, const char *buf, int count); |
34 | 35 | ||
35 | /* Register a vterm and a slot index for use as a console */ | 36 | struct hvc_struct; |
37 | |||
38 | /* Register a vterm and a slot index for use as a console (console_init) */ | ||
36 | extern int hvc_instantiate(uint32_t vtermno, int index); | 39 | extern int hvc_instantiate(uint32_t vtermno, int index); |
40 | /* register a vterm for hvc tty operation (module_init or hotplug add) */ | ||
41 | extern struct hvc_struct * __devinit hvc_alloc(uint32_t vtermno, int irq); | ||
42 | /* remove a vterm from hvc tty operation (modele_exit or hotplug remove) */ | ||
43 | extern int __devexit hvc_remove(struct hvc_struct *hp); | ||
37 | #endif /* _PPC64_HVCONSOLE_H */ | 44 | #endif /* _PPC64_HVCONSOLE_H */ |