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 172 173 174 175 176 | /* * 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 u8 *str, size_t count) { u8 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 console_is_registered(con) ? 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 ssize_t nfcon_tty_write(struct tty_struct *tty, const u8 *buf, size_t count) { nfputs(buf, count); return count; } static int nfcon_tty_put_char(struct tty_struct *tty, u8 ch) { u8 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) { /* * The console will be enabled when debug=nfcon is specified * as a kernel parameter. Since this is a non-standard way * of enabling consoles, it must be explicitly enabled. */ 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 (!console_is_registered(&nf_console)) 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"); |