0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/kmod.h>
0011 #include <linux/console.h>
0012 #include <linux/init.h>
0013 #include <linux/panic_notifier.h>
0014 #include <linux/timer.h>
0015 #include <linux/jiffies.h>
0016 #include <linux/termios.h>
0017 #include <linux/err.h>
0018 #include <linux/reboot.h>
0019 #include <linux/gfp.h>
0020
0021 #include "sclp.h"
0022 #include "sclp_rw.h"
0023 #include "sclp_tty.h"
0024
0025 #define sclp_console_major 4
0026 #define sclp_console_minor 64
0027 #define sclp_console_name "ttyS"
0028
0029
0030 static DEFINE_SPINLOCK(sclp_con_lock);
0031
0032 static LIST_HEAD(sclp_con_pages);
0033
0034 static LIST_HEAD(sclp_con_outqueue);
0035
0036 static struct sclp_buffer *sclp_conbuf;
0037
0038 static struct timer_list sclp_con_timer;
0039
0040 static int sclp_con_queue_running;
0041
0042
0043 #define SCLP_CON_COLUMNS 320
0044 #define SPACES_PER_TAB 8
0045
0046 static void
0047 sclp_conbuf_callback(struct sclp_buffer *buffer, int rc)
0048 {
0049 unsigned long flags;
0050 void *page;
0051
0052 do {
0053 page = sclp_unmake_buffer(buffer);
0054 spin_lock_irqsave(&sclp_con_lock, flags);
0055
0056
0057 list_del(&buffer->list);
0058 list_add_tail((struct list_head *) page, &sclp_con_pages);
0059
0060
0061 buffer = NULL;
0062 if (!list_empty(&sclp_con_outqueue))
0063 buffer = list_first_entry(&sclp_con_outqueue,
0064 struct sclp_buffer, list);
0065 if (!buffer) {
0066 sclp_con_queue_running = 0;
0067 spin_unlock_irqrestore(&sclp_con_lock, flags);
0068 break;
0069 }
0070 spin_unlock_irqrestore(&sclp_con_lock, flags);
0071 } while (sclp_emit_buffer(buffer, sclp_conbuf_callback));
0072 }
0073
0074
0075
0076
0077 static void sclp_conbuf_emit(void)
0078 {
0079 struct sclp_buffer* buffer;
0080 unsigned long flags;
0081 int rc;
0082
0083 spin_lock_irqsave(&sclp_con_lock, flags);
0084 if (sclp_conbuf)
0085 list_add_tail(&sclp_conbuf->list, &sclp_con_outqueue);
0086 sclp_conbuf = NULL;
0087 if (sclp_con_queue_running)
0088 goto out_unlock;
0089 if (list_empty(&sclp_con_outqueue))
0090 goto out_unlock;
0091 buffer = list_first_entry(&sclp_con_outqueue, struct sclp_buffer,
0092 list);
0093 sclp_con_queue_running = 1;
0094 spin_unlock_irqrestore(&sclp_con_lock, flags);
0095
0096 rc = sclp_emit_buffer(buffer, sclp_conbuf_callback);
0097 if (rc)
0098 sclp_conbuf_callback(buffer, rc);
0099 return;
0100 out_unlock:
0101 spin_unlock_irqrestore(&sclp_con_lock, flags);
0102 }
0103
0104
0105
0106
0107 static void sclp_console_sync_queue(void)
0108 {
0109 unsigned long flags;
0110
0111 spin_lock_irqsave(&sclp_con_lock, flags);
0112 del_timer(&sclp_con_timer);
0113 while (sclp_con_queue_running) {
0114 spin_unlock_irqrestore(&sclp_con_lock, flags);
0115 sclp_sync_wait();
0116 spin_lock_irqsave(&sclp_con_lock, flags);
0117 }
0118 spin_unlock_irqrestore(&sclp_con_lock, flags);
0119 }
0120
0121
0122
0123
0124
0125 static void
0126 sclp_console_timeout(struct timer_list *unused)
0127 {
0128 sclp_conbuf_emit();
0129 }
0130
0131
0132
0133
0134 static int
0135 sclp_console_drop_buffer(void)
0136 {
0137 struct list_head *list;
0138 struct sclp_buffer *buffer;
0139 void *page;
0140
0141 if (!sclp_console_drop)
0142 return 0;
0143 list = sclp_con_outqueue.next;
0144 if (sclp_con_queue_running)
0145
0146 list = list->next;
0147 if (list == &sclp_con_outqueue)
0148 return 0;
0149 list_del(list);
0150 buffer = list_entry(list, struct sclp_buffer, list);
0151 page = sclp_unmake_buffer(buffer);
0152 list_add_tail((struct list_head *) page, &sclp_con_pages);
0153 return 1;
0154 }
0155
0156
0157
0158
0159 static void
0160 sclp_console_write(struct console *console, const char *message,
0161 unsigned int count)
0162 {
0163 unsigned long flags;
0164 void *page;
0165 int written;
0166
0167 if (count == 0)
0168 return;
0169 spin_lock_irqsave(&sclp_con_lock, flags);
0170
0171
0172
0173
0174 do {
0175
0176 if (sclp_conbuf == NULL) {
0177 if (list_empty(&sclp_con_pages))
0178 sclp_console_full++;
0179 while (list_empty(&sclp_con_pages)) {
0180 if (sclp_console_drop_buffer())
0181 break;
0182 spin_unlock_irqrestore(&sclp_con_lock, flags);
0183 sclp_sync_wait();
0184 spin_lock_irqsave(&sclp_con_lock, flags);
0185 }
0186 page = sclp_con_pages.next;
0187 list_del((struct list_head *) page);
0188 sclp_conbuf = sclp_make_buffer(page, SCLP_CON_COLUMNS,
0189 SPACES_PER_TAB);
0190 }
0191
0192 written = sclp_write(sclp_conbuf, (const unsigned char *)
0193 message, count);
0194 if (written == count)
0195 break;
0196
0197
0198
0199
0200
0201 spin_unlock_irqrestore(&sclp_con_lock, flags);
0202 sclp_conbuf_emit();
0203 spin_lock_irqsave(&sclp_con_lock, flags);
0204 message += written;
0205 count -= written;
0206 } while (count > 0);
0207
0208 if (sclp_conbuf != NULL && sclp_chars_in_buffer(sclp_conbuf) != 0 &&
0209 !timer_pending(&sclp_con_timer)) {
0210 mod_timer(&sclp_con_timer, jiffies + HZ / 10);
0211 }
0212 spin_unlock_irqrestore(&sclp_con_lock, flags);
0213 }
0214
0215 static struct tty_driver *
0216 sclp_console_device(struct console *c, int *index)
0217 {
0218 *index = c->index;
0219 return sclp_tty_driver;
0220 }
0221
0222
0223
0224
0225
0226 static int sclp_console_notify(struct notifier_block *self,
0227 unsigned long event, void *data)
0228 {
0229
0230
0231
0232
0233
0234 if (spin_is_locked(&sclp_con_lock))
0235 return NOTIFY_DONE;
0236
0237 sclp_conbuf_emit();
0238 sclp_console_sync_queue();
0239
0240 return NOTIFY_DONE;
0241 }
0242
0243 static struct notifier_block on_panic_nb = {
0244 .notifier_call = sclp_console_notify,
0245 .priority = INT_MIN + 1,
0246 };
0247
0248 static struct notifier_block on_reboot_nb = {
0249 .notifier_call = sclp_console_notify,
0250 .priority = INT_MIN + 1,
0251 };
0252
0253
0254
0255
0256
0257 static struct console sclp_console =
0258 {
0259 .name = sclp_console_name,
0260 .write = sclp_console_write,
0261 .device = sclp_console_device,
0262 .flags = CON_PRINTBUFFER,
0263 .index = 0
0264 };
0265
0266
0267
0268
0269 static int __init
0270 sclp_console_init(void)
0271 {
0272 void *page;
0273 int i;
0274 int rc;
0275
0276
0277 if (!(CONSOLE_IS_SCLP || CONSOLE_IS_VT220))
0278 return 0;
0279 rc = sclp_rw_init();
0280 if (rc)
0281 return rc;
0282
0283 for (i = 0; i < sclp_console_pages; i++) {
0284 page = (void *) get_zeroed_page(GFP_KERNEL | GFP_DMA);
0285 list_add_tail(page, &sclp_con_pages);
0286 }
0287 sclp_conbuf = NULL;
0288 timer_setup(&sclp_con_timer, sclp_console_timeout, 0);
0289
0290
0291 atomic_notifier_chain_register(&panic_notifier_list, &on_panic_nb);
0292 register_reboot_notifier(&on_reboot_nb);
0293 register_console(&sclp_console);
0294 return 0;
0295 }
0296
0297 console_initcall(sclp_console_init);