Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | /* * ARAnyM console driver * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive * for more details. */ #include <linux/module.h> #include <linux/init.h> #include <linux/console.h> #include <linux/tty.h> #include <linux/tty_driver.h> #include <linux/tty_flip.h> #include <linux/slab.h> #include <linux/err.h> #include <linux/uaccess.h> #include <linux/io.h> #include <asm/natfeat.h> static int stderr_id; static struct tty_port nfcon_tty_port; static struct tty_driver *nfcon_tty_driver; static void nfputs(const char *str, unsigned int count) { char buf[68]; unsigned long phys = virt_to_phys(buf); buf[64] = 0; while (count > 64) { memcpy(buf, str, 64); nf_call(stderr_id, phys); str += 64; count -= 64; } memcpy(buf, str, count); buf[count] = 0; nf_call(stderr_id, phys); } static void nfcon_write(struct console *con, const char *str, unsigned int count) { nfputs(str, count); } static struct tty_driver *nfcon_device(struct console *con, int *index) { *index = 0; return (con->flags & CON_ENABLED) ? nfcon_tty_driver : NULL; } static struct console nf_console = { .name = "nfcon", .write = nfcon_write, .device = nfcon_device, .flags = CON_PRINTBUFFER, .index = -1, }; static int nfcon_tty_open(struct tty_struct *tty, struct file *filp) { return 0; } static void nfcon_tty_close(struct tty_struct *tty, struct file *filp) { } static int nfcon_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) { nfputs(buf, count); return count; } static int nfcon_tty_put_char(struct tty_struct *tty, unsigned char ch) { char temp[2] = { ch, 0 }; nf_call(stderr_id, virt_to_phys(temp)); return 1; } static unsigned int nfcon_tty_write_room(struct tty_struct *tty) { return 64; } static const struct tty_operations nfcon_tty_ops = { .open = nfcon_tty_open, .close = nfcon_tty_close, .write = nfcon_tty_write, .put_char = nfcon_tty_put_char, .write_room = nfcon_tty_write_room, }; #ifndef MODULE static int __init nf_debug_setup(char *arg) { if (strcmp(arg, "nfcon")) return 0; stderr_id = nf_get_id("NF_STDERR"); if (stderr_id) { nf_console.flags |= CON_ENABLED; register_console(&nf_console); } return 0; } early_param("debug", nf_debug_setup); #endif /* !MODULE */ static int __init nfcon_init(void) { struct tty_driver *driver; int res; stderr_id = nf_get_id("NF_STDERR"); if (!stderr_id) return -ENODEV; driver = tty_alloc_driver(1, TTY_DRIVER_REAL_RAW); if (IS_ERR(driver)) return PTR_ERR(driver); tty_port_init(&nfcon_tty_port); driver->driver_name = "nfcon"; driver->name = "nfcon"; driver->type = TTY_DRIVER_TYPE_SYSTEM; driver->subtype = SYSTEM_TYPE_TTY; driver->init_termios = tty_std_termios; tty_set_operations(driver, &nfcon_tty_ops); tty_port_link_device(&nfcon_tty_port, driver, 0); res = tty_register_driver(driver); if (res) { pr_err("failed to register nfcon tty driver\n"); tty_driver_kref_put(driver); tty_port_destroy(&nfcon_tty_port); return res; } nfcon_tty_driver = driver; if (!(nf_console.flags & CON_ENABLED)) register_console(&nf_console); return 0; } static void __exit nfcon_exit(void) { unregister_console(&nf_console); tty_unregister_driver(nfcon_tty_driver); tty_driver_kref_put(nfcon_tty_driver); tty_port_destroy(&nfcon_tty_port); } module_init(nfcon_init); module_exit(nfcon_exit); MODULE_LICENSE("GPL"); |