494 lines
14 KiB
Diff
Executable File
494 lines
14 KiB
Diff
Executable File
Index: linux-2.6.25.20-source/drivers/video/console/cocon.c
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ linux-2.6.25.20-source/drivers/video/console/cocon.c
|
|
@@ -0,0 +1,488 @@
|
|
+/*
|
|
+ * linux/drivers/video/cocon.c -- Cooperative Linux console VGA 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.
|
|
+ *
|
|
+ * Based on code copied from vgacon.c.
|
|
+ *
|
|
+ * Dan Aloni <da-x@gmx.net>, 2003-2004 (c)
|
|
+ */
|
|
+
|
|
+#include <linux/module.h>
|
|
+#include <linux/types.h>
|
|
+#include <linux/sched.h>
|
|
+#include <linux/fs.h>
|
|
+#include <linux/kernel.h>
|
|
+#include <linux/tty.h>
|
|
+#include <linux/console.h>
|
|
+#include <linux/string.h>
|
|
+#include <linux/kd.h>
|
|
+#include <linux/slab.h>
|
|
+#include <linux/vt_kern.h>
|
|
+#include <linux/selection.h>
|
|
+#include <linux/init.h>
|
|
+
|
|
+#include <linux/cooperative_internal.h>
|
|
+
|
|
+/*
|
|
+ * Interface used by the world
|
|
+ */
|
|
+
|
|
+static int cocon_cols = 80;
|
|
+static int cocon_rows = 25;
|
|
+static int cocon_attr = 0x07; /* fg=white, bg=black */
|
|
+
|
|
+static const char __init *cocon_startup(void)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ co_console_message_t *message;
|
|
+ co_message_t *co_message;
|
|
+
|
|
+ co_message = co_send_message_save(&flags);
|
|
+ if (co_message) {
|
|
+ message = (co_console_message_t *)co_message->data;
|
|
+ co_message->from = CO_MODULE_LINUX;
|
|
+ co_message->to = CO_MODULE_CONSOLE;
|
|
+ co_message->priority = CO_PRIORITY_DISCARDABLE;
|
|
+ co_message->type = CO_MESSAGE_TYPE_STRING;
|
|
+ co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
|
|
+ message->type = CO_OPERATION_CONSOLE_STARTUP;
|
|
+ co_switch_wrapper();
|
|
+ if (message->type == CO_OPERATION_CONSOLE_CONFIG) {
|
|
+ cocon_cols = message->config.cols;
|
|
+ cocon_rows = message->config.rows;
|
|
+ cocon_attr = message->config.attr;
|
|
+ }
|
|
+ co_passage_page_release(flags);
|
|
+ }
|
|
+
|
|
+ return "CoCON";
|
|
+}
|
|
+
|
|
+static void cocon_init(struct vc_data *c, int init)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ co_console_message_t *message;
|
|
+ co_message_t *co_message;
|
|
+
|
|
+ /* We cannot be loaded as a module, therefore init is always 1 */
|
|
+ c->vc_can_do_color = 1;
|
|
+ c->vc_cols = cocon_cols;
|
|
+ c->vc_rows = cocon_rows;
|
|
+
|
|
+ /* drivers/char/vt.c: Must hack vc_init() for vc_def_color */
|
|
+ c->vc_def_color = cocon_attr;
|
|
+
|
|
+ c->vc_complement_mask = 0x7700;
|
|
+ c->vc_visible_origin = 0;
|
|
+ c->vc_origin = 0;
|
|
+
|
|
+ co_message = co_send_message_save(&flags);
|
|
+ if (!co_message)
|
|
+ return;
|
|
+
|
|
+ message = (co_console_message_t *)co_message->data;
|
|
+ co_message->from = CO_MODULE_LINUX;
|
|
+ co_message->to = CO_MODULE_CONSOLE;
|
|
+ co_message->priority = CO_PRIORITY_DISCARDABLE;
|
|
+ co_message->type = CO_MESSAGE_TYPE_STRING;
|
|
+ co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
|
|
+ message->type = CO_OPERATION_CONSOLE_INIT;
|
|
+ co_send_message_restore(flags);
|
|
+}
|
|
+
|
|
+static void cocon_deinit(struct vc_data *c)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ co_console_message_t *message;
|
|
+ co_message_t *co_message;
|
|
+
|
|
+ co_message = co_send_message_save(&flags);
|
|
+ if (!co_message)
|
|
+ return;
|
|
+
|
|
+ message = (co_console_message_t *)co_message->data;
|
|
+ co_message->from = CO_MODULE_LINUX;
|
|
+ co_message->to = CO_MODULE_CONSOLE;
|
|
+ co_message->priority = CO_PRIORITY_DISCARDABLE;
|
|
+ co_message->type = CO_MESSAGE_TYPE_STRING;
|
|
+ co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
|
|
+ message->type = CO_OPERATION_CONSOLE_DEINIT;
|
|
+ co_send_message_restore(flags);
|
|
+
|
|
+}
|
|
+
|
|
+static void cocon_clear(struct vc_data *c, int top, int left, int rows, int cols)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ co_console_message_t *message;
|
|
+ co_message_t *co_message;
|
|
+
|
|
+ co_message = co_send_message_save(&flags);
|
|
+ if (!co_message)
|
|
+ return;
|
|
+
|
|
+ message = (co_console_message_t *)co_message->data;
|
|
+ co_message->from = CO_MODULE_LINUX;
|
|
+ co_message->to = CO_MODULE_CONSOLE;
|
|
+ co_message->priority = CO_PRIORITY_DISCARDABLE;
|
|
+ co_message->type = CO_MESSAGE_TYPE_STRING;
|
|
+ co_message->size = ((char *)(&message->clear + 1)) - ((char *)message);
|
|
+ message->type = CO_OPERATION_CONSOLE_CLEAR;
|
|
+ message->clear.top = top;
|
|
+ message->clear.left = left;
|
|
+ message->clear.bottom = top + rows - 1;
|
|
+ message->clear.right = left + cols - 1;
|
|
+ message->clear.charattr = c->vc_video_erase_char;
|
|
+ co_send_message_restore(flags);
|
|
+}
|
|
+
|
|
+static void cocon_putc(struct vc_data *c, int charattr, int y, int x)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ co_message_t *co_message;
|
|
+ co_console_message_t *message;
|
|
+
|
|
+ co_message = co_send_message_save(&flags);
|
|
+ if (!co_message)
|
|
+ return;
|
|
+
|
|
+ message = (co_console_message_t *)co_message->data;
|
|
+ co_message->from = CO_MODULE_LINUX;
|
|
+ co_message->to = CO_MODULE_CONSOLE;
|
|
+ co_message->priority = CO_PRIORITY_DISCARDABLE;
|
|
+ co_message->type = CO_MESSAGE_TYPE_STRING;
|
|
+ co_message->size = ((char *)(&message->putc + 1)) - ((char *)message);
|
|
+ message->type = CO_OPERATION_CONSOLE_PUTC;
|
|
+ message->putc.x = x;
|
|
+ message->putc.y = y;
|
|
+ message->putc.charattr = charattr;
|
|
+ co_send_message_restore(flags);
|
|
+}
|
|
+
|
|
+
|
|
+static void cocon_putcs(struct vc_data *conp,
|
|
+ const unsigned short *s, int count, int yy, int xx)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ co_console_message_t *message;
|
|
+ co_message_t *co_message;
|
|
+
|
|
+ if (count > CO_MAX_PARAM_SIZE/2 - 16)
|
|
+ return;
|
|
+
|
|
+ co_message = co_send_message_save(&flags);
|
|
+ if (!co_message)
|
|
+ return;
|
|
+
|
|
+ message = (co_console_message_t *)co_message->data;
|
|
+ co_message->from = CO_MODULE_LINUX;
|
|
+ co_message->to = CO_MODULE_CONSOLE;
|
|
+ co_message->priority = CO_PRIORITY_DISCARDABLE;
|
|
+ co_message->type = CO_MESSAGE_TYPE_STRING;
|
|
+ co_message->size = ((char *)(&message->putcs + 1)) - ((char *)message) +
|
|
+ count * sizeof(unsigned short);
|
|
+ message->type = CO_OPERATION_CONSOLE_PUTCS;
|
|
+ message->putcs.x = xx;
|
|
+ message->putcs.y = yy;
|
|
+ message->putcs.count = count;
|
|
+ memcpy(&message->putcs.data, s, count * sizeof(unsigned short));
|
|
+ co_send_message_restore(flags);
|
|
+}
|
|
+
|
|
+static u8 cocon_build_attr(struct vc_data *c, u8 color, u8 intensity, u8 blink, u8 underline, u8 reverse, u8 italic)
|
|
+{
|
|
+ u8 attr = color;
|
|
+
|
|
+ if (underline)
|
|
+ attr = (attr & 0xf0) | c->vc_ulcolor;
|
|
+ else if (intensity == 0)
|
|
+ attr = (attr & 0xf0) | c->vc_halfcolor;
|
|
+ if (reverse)
|
|
+ attr = ((attr) & 0x88) | ((((attr) >> 4) | ((attr) << 4)) & 0x77);
|
|
+ if (blink)
|
|
+ attr ^= 0x80;
|
|
+ if (intensity == 2)
|
|
+ attr ^= 0x08;
|
|
+
|
|
+ return attr;
|
|
+}
|
|
+
|
|
+static void cocon_invert_region(struct vc_data *c, u16 *p, int count)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ co_message_t *co_message;
|
|
+ co_console_message_t *message;
|
|
+ unsigned long x = (unsigned long)(p - c->vc_origin); // UPDATE: vc_origin = 0; but not yet
|
|
+
|
|
+ co_message = co_send_message_save(&flags);
|
|
+ if (co_message) {
|
|
+ message = (co_console_message_t *)co_message->data;
|
|
+ co_message->from = CO_MODULE_LINUX;
|
|
+ co_message->to = CO_MODULE_CONSOLE;
|
|
+ co_message->priority = CO_PRIORITY_DISCARDABLE;
|
|
+ co_message->type = CO_MESSAGE_TYPE_STRING;
|
|
+ co_message->size = ((char *)(&message->invert + 1)) - ((char *)message);
|
|
+ message->type = CO_OPERATION_CONSOLE_INVERT_REGION;
|
|
+ message->invert.y = ((unsigned)x)/c->vc_cols;
|
|
+ message->invert.x = ((unsigned)x)-(message->invert.y);
|
|
+ message->invert.count = count;
|
|
+ co_send_message_restore(flags);
|
|
+ }
|
|
+
|
|
+ while (count--) {
|
|
+ u16 a = scr_readw(p);
|
|
+ a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4);
|
|
+ scr_writew(a, p++);
|
|
+ }
|
|
+
|
|
+}
|
|
+
|
|
+static void cocon_cursor(struct vc_data *c, int mode)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ co_console_message_t *message;
|
|
+ co_message_t *co_message;
|
|
+
|
|
+ co_message = co_send_message_save(&flags);
|
|
+ if (!co_message)
|
|
+ return;
|
|
+
|
|
+ message = (co_console_message_t *)co_message->data;
|
|
+ co_message->from = CO_MODULE_LINUX;
|
|
+ co_message->to = CO_MODULE_CONSOLE;
|
|
+ co_message->priority = CO_PRIORITY_DISCARDABLE;
|
|
+ co_message->type = CO_MESSAGE_TYPE_STRING;
|
|
+ co_message->size = ((char *)(&message->cursor + 1)) - ((char *)message);;
|
|
+ if (mode==CM_ERASE) {
|
|
+ message->type = CO_OPERATION_CONSOLE_CURSOR_ERASE;
|
|
+ message->cursor.height = CUR_NONE;
|
|
+ co_send_message_restore(flags);
|
|
+ return;
|
|
+ }
|
|
+
|
|
+ if(mode==CM_MOVE) {
|
|
+ message->type = CO_OPERATION_CONSOLE_CURSOR_MOVE;
|
|
+ } else /*(mode==CM_DRAW)*/ {
|
|
+ message->type = CO_OPERATION_CONSOLE_CURSOR_DRAW;
|
|
+ }
|
|
+ message->cursor.x = c->vc_x;
|
|
+ message->cursor.y = c->vc_y;
|
|
+ message->cursor.height = c->vc_cursor_type & CUR_HWMASK;
|
|
+
|
|
+ co_send_message_restore(flags);
|
|
+}
|
|
+
|
|
+static int cocon_switch(struct vc_data *c)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ co_console_message_t *message;
|
|
+ co_message_t *co_message;
|
|
+
|
|
+ co_message = co_send_message_save(&flags);
|
|
+ if (co_message) {
|
|
+ message = (co_console_message_t *)co_message->data;
|
|
+ co_message->from = CO_MODULE_LINUX;
|
|
+ co_message->to = CO_MODULE_CONSOLE;
|
|
+ co_message->priority = CO_PRIORITY_DISCARDABLE;
|
|
+ co_message->type = CO_MESSAGE_TYPE_STRING;
|
|
+ co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
|
|
+ message->type = CO_OPERATION_CONSOLE_SWITCH;
|
|
+ co_send_message_restore(flags);
|
|
+ }
|
|
+
|
|
+ return 1; /* Redrawing not needed */
|
|
+}
|
|
+
|
|
+static int cocon_set_palette(struct vc_data *c, unsigned char *table)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ co_console_message_t *message;
|
|
+ co_message_t *co_message;
|
|
+
|
|
+ co_message = co_send_message_save(&flags);
|
|
+ if (co_message) {
|
|
+ message = (co_console_message_t *)co_message->data;
|
|
+ co_message->from = CO_MODULE_LINUX;
|
|
+ co_message->to = CO_MODULE_CONSOLE;
|
|
+ co_message->priority = CO_PRIORITY_DISCARDABLE;
|
|
+ co_message->type = CO_MESSAGE_TYPE_STRING;
|
|
+ co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
|
|
+ message->type = CO_OPERATION_CONSOLE_SET_PALETTE;
|
|
+ co_send_message_restore(flags);
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static int cocon_blank(struct vc_data *c, int blank, int mode_switchg)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ co_console_message_t *message;
|
|
+ co_message_t *co_message;
|
|
+
|
|
+ co_message = co_send_message_save(&flags);
|
|
+ if (co_message) {
|
|
+ message = (co_console_message_t *)co_message->data;
|
|
+ co_message->from = CO_MODULE_LINUX;
|
|
+ co_message->to = CO_MODULE_CONSOLE;
|
|
+ co_message->priority = CO_PRIORITY_DISCARDABLE;
|
|
+ co_message->type = CO_MESSAGE_TYPE_STRING;
|
|
+ co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
|
|
+ message->type = CO_OPERATION_CONSOLE_BLANK;
|
|
+ co_send_message_restore(flags);
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+
|
|
+static int cocon_scrolldelta(struct vc_data *c, int lines)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ co_console_message_t *message;
|
|
+ co_message_t *co_message;
|
|
+
|
|
+ co_message = co_send_message_save(&flags);
|
|
+ if (co_message) {
|
|
+ message = (co_console_message_t *)co_message->data;
|
|
+ co_message->from = CO_MODULE_LINUX;
|
|
+ co_message->to = CO_MODULE_CONSOLE;
|
|
+ co_message->priority = CO_PRIORITY_DISCARDABLE;
|
|
+ co_message->type = CO_MESSAGE_TYPE_STRING;
|
|
+ co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
|
|
+ message->type = CO_OPERATION_CONSOLE_SCROLLDELTA;
|
|
+ co_send_message_restore(flags);
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static int cocon_set_origin(struct vc_data *c)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ co_console_message_t *message;
|
|
+ co_message_t *co_message;
|
|
+
|
|
+ co_message = co_send_message_save(&flags);
|
|
+ if (co_message) {
|
|
+ message = (co_console_message_t *)co_message->data;
|
|
+ co_message->from = CO_MODULE_LINUX;
|
|
+ co_message->to = CO_MODULE_CONSOLE;
|
|
+ co_message->priority = CO_PRIORITY_DISCARDABLE;
|
|
+ co_message->type = CO_MESSAGE_TYPE_STRING;
|
|
+ co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
|
|
+ message->type = CO_OPERATION_CONSOLE_SET_ORIGIN;
|
|
+ co_send_message_restore(flags);
|
|
+ }
|
|
+
|
|
+ return 1;
|
|
+}
|
|
+
|
|
+static void cocon_save_screen(struct vc_data *c)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ co_console_message_t *message;
|
|
+ co_message_t *co_message;
|
|
+
|
|
+ co_message = co_send_message_save(&flags);
|
|
+ if (co_message) {
|
|
+ message = (co_console_message_t *)co_message->data;
|
|
+ co_message->from = CO_MODULE_LINUX;
|
|
+ co_message->to = CO_MODULE_CONSOLE;
|
|
+ co_message->priority = CO_PRIORITY_DISCARDABLE;
|
|
+ co_message->type = CO_MESSAGE_TYPE_STRING;
|
|
+ co_message->size = ((char *)(&message->type + 1)) - ((char *)message);
|
|
+ message->type = CO_OPERATION_CONSOLE_SAVE_SCREEN;
|
|
+ co_send_message_restore(flags);
|
|
+ }
|
|
+}
|
|
+
|
|
+static int cocon_scroll(struct vc_data *c, int t, int b, int dir, int lines)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ co_console_message_t *message;
|
|
+ co_message_t *co_message;
|
|
+
|
|
+ co_message = co_send_message_save(&flags);
|
|
+ if (co_message) {
|
|
+ message = (co_console_message_t *)co_message->data;
|
|
+ co_message->from = CO_MODULE_LINUX;
|
|
+ co_message->to = CO_MODULE_CONSOLE;
|
|
+ co_message->priority = CO_PRIORITY_DISCARDABLE;
|
|
+ co_message->type = CO_MESSAGE_TYPE_STRING;
|
|
+ co_message->size = ((char *)(&message->scroll + 1)) - ((char *)message);
|
|
+ if (dir == SM_UP)
|
|
+ message->type = CO_OPERATION_CONSOLE_SCROLL_UP;
|
|
+ else
|
|
+ message->type = CO_OPERATION_CONSOLE_SCROLL_DOWN;
|
|
+ message->scroll.top = t;
|
|
+ message->scroll.bottom = b-1;
|
|
+ message->scroll.lines = lines;
|
|
+ message->scroll.charattr = c->vc_video_erase_char;
|
|
+ co_send_message_restore(flags);
|
|
+ }
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static void cocon_bmove(struct vc_data *c, int sy, int sx, int dy, int dx, int h, int w)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ co_console_message_t *message;
|
|
+ co_message_t *co_message;
|
|
+
|
|
+ co_message = co_send_message_save(&flags);
|
|
+ if (!co_message)
|
|
+ return;
|
|
+
|
|
+ message = (co_console_message_t *)co_message->data;
|
|
+ co_message->from = CO_MODULE_LINUX;
|
|
+ co_message->to = CO_MODULE_CONSOLE;
|
|
+ co_message->priority = CO_PRIORITY_DISCARDABLE;
|
|
+ co_message->type = CO_MESSAGE_TYPE_STRING;
|
|
+ co_message->size = ((char *)(&message->bmove + 1)) - ((char *)message);
|
|
+ message->type = CO_OPERATION_CONSOLE_BMOVE;
|
|
+ message->bmove.row = dy;
|
|
+ message->bmove.column = dx;
|
|
+ message->bmove.top = sy;
|
|
+ message->bmove.left = sx;
|
|
+ message->bmove.bottom = sy + h - 1;
|
|
+ message->bmove.right = sx + w - 1;
|
|
+ co_send_message_restore(flags);
|
|
+}
|
|
+
|
|
+static int cocon_resize(struct vc_data *c, unsigned int width,
|
|
+ unsigned int height)
|
|
+{
|
|
+ return -EINVAL;
|
|
+}
|
|
+
|
|
+/*
|
|
+ * The console `switch' structure for the VGA based console
|
|
+ */
|
|
+
|
|
+const struct consw colinux_con = {
|
|
+ con_startup: cocon_startup,
|
|
+ con_init: cocon_init,
|
|
+ con_deinit: cocon_deinit,
|
|
+ con_clear: cocon_clear,
|
|
+ con_putc: cocon_putc,
|
|
+ con_putcs: cocon_putcs,
|
|
+ con_cursor: cocon_cursor,
|
|
+ con_scroll: cocon_scroll,
|
|
+ con_bmove: cocon_bmove,
|
|
+ con_switch: cocon_switch,
|
|
+ con_blank: cocon_blank,
|
|
+ con_resize: cocon_resize,
|
|
+ con_set_palette: cocon_set_palette,
|
|
+ con_scrolldelta: cocon_scrolldelta,
|
|
+ con_set_origin: cocon_set_origin,
|
|
+ con_save_screen: cocon_save_screen,
|
|
+ con_build_attr: cocon_build_attr,
|
|
+ con_invert_region: cocon_invert_region,
|
|
+};
|
|
+
|
|
+MODULE_LICENSE("GPL");
|