hi all,
i hope this is the right place to send this. comments and corrections are
welcome.
regards,
ladis
Index: drivers/video/newport_con.c
===================================================================
RCS file: /cvs/linux/drivers/video/newport_con.c,v
retrieving revision 1.23
diff -a -u -r1.23 newport_con.c
--- drivers/video/newport_con.c 2000/11/23 02:00:54 1.23
+++ drivers/video/newport_con.c 2001/03/28 19:12:34
@@ -20,6 +20,7 @@
#include <linux/vt_kern.h>
#include <linux/mm.h>
#include <linux/module.h>
+#include <linux/slab.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -38,6 +39,14 @@
#define FONT_DATA ((unsigned char *)font_vga_8x16.data)
+/* borrowed from fbcon.c */
+#define REFCOUNT(fd) (((int *)(fd))[-1])
+#define FNTSIZE(fd) (((int *)(fd))[-2])
+#define FNTCHARCNT(fd) (((int *)(fd))[-3])
+#define FONT_EXTRA_WORDS 3
+
+static unsigned char *font_data[MAX_NR_CONSOLES];
+
extern struct newport_regs *npregs;
static int logo_active;
@@ -274,6 +283,7 @@
static const char * __init newport_startup(void)
#endif
{
+ int i;
struct newport_regs *p;
npregs = (struct newport_regs *) (KSEG1 + 0x1f0f0000);
@@ -289,11 +299,14 @@
return NULL;
}
+ for (i = 0; i < MAX_NR_CONSOLES; i++)
+ font_data[i] = FONT_DATA;
+
newport_reset ();
newport_get_revisions();
newport_get_screensize();
- // gfx_init (display_desc);
+ /* gfx_init (display_desc); */
return "SGI Newport";
}
@@ -329,7 +342,7 @@
{
unsigned char *p;
- p = &FONT_DATA[(charattr & 0xff) << 4];
+ p = &font_data[vc->vc_num][(charattr & 0xff) << 4];
charattr = (charattr >> 8) & 0xff;
xpos <<= 3;
ypos <<= 4;
@@ -378,7 +391,7 @@
NPORT_DMODE0_L32);
for (i = 0; i < count; i++, xpos += 8) {
- p = &FONT_DATA[(s[i] & 0xff) << 4];
+ p = &font_data[vc->vc_num][(s[i] & 0xff) << 4];
newport_wait();
@@ -446,11 +459,82 @@
return 1;
}
-static int newport_font_op(struct vc_data *vc, struct console_font_op *f)
+static int newport_set_font(int unit, struct console_font_op *op)
{
- return -ENOSYS;
+ int w = op->width;
+ int h = op->height;
+ int size = h * op->charcount;
+ int i;
+ unsigned char *new_data, *data = op->data, *p;
+
+ /* ladis: when I grow up, there will be a day... and more sizes will
+ * be supported ;-) */
+ if ((w != 8) || (h != 16) || (op->charcount != 256 && op->charcount !=
512))
+ return -EINVAL;
+
+ if (!(new_data = kmalloc(FONT_EXTRA_WORDS * sizeof(int) + size,
GFP_USER)))
+ return -ENOMEM;
+
+ new_data += FONT_EXTRA_WORDS * sizeof(int);
+ FNTSIZE(new_data) = size;
+ FNTCHARCNT(new_data) = op->charcount;
+ REFCOUNT(new_data) = 0; /* usage counter */
+
+ p = new_data;
+ for (i = 0; i < op->charcount; i++) {
+ memcpy(p, data, h);
+ data += 32;
+ p += h;
+ }
+
+ /* check if font is already used by other console */
+ for (i = 0; i < MAX_NR_CONSOLES; i++) {
+ if (font_data[i] != FONT_DATA && FNTSIZE(font_data[i]) == size
+ && !memcmp(font_data[i], new_data, size)) {
+ kfree(new_data - FONT_EXTRA_WORDS * sizeof(int));
+ /* current font is the same as the new one */
+ if (i == unit)
+ return 0;
+ new_data = font_data[i];
+ break;
+ }
+ }
+ /* old font is user font */
+ if (font_data[unit] != FONT_DATA) {
+ if (--REFCOUNT(font_data[unit]) == 0)
+ kfree(font_data[unit] - FONT_EXTRA_WORDS * sizeof(int));
+ }
+ REFCOUNT(new_data)++;
+ font_data[unit] = new_data;
+
+ return 0;
}
+static int newport_set_def_font(int unit, struct console_font_op *op)
+{
+ if (font_data[unit] != FONT_DATA) {
+ if (--REFCOUNT(font_data[unit]) == 0)
+ kfree(font_data[unit] - FONT_EXTRA_WORDS * sizeof(int));
+ font_data[unit] = FONT_DATA;
+ }
+
+ return 0;
+}
+
+static int newport_font_op(struct vc_data *vc, struct console_font_op *op)
+{
+ int unit = vc->vc_num;
+
+ switch (op->op) {
+ case KD_FONT_OP_SET:
+ return newport_set_font(unit, op);
+ case KD_FONT_OP_SET_DEFAULT:
+ return newport_set_def_font(unit, op);
+ default:
+ return -ENOSYS;
+ }
+}
+
static int newport_set_palette(struct vc_data *vc, unsigned char *table)
{
return -EINVAL;
@@ -594,21 +678,21 @@
};
#ifdef MODULE
-
-int init_module(void) {
- if (!newport_startup())
- printk("Error loading SGI Newport Console driver\n");
- else
- printk("Loading SGI Newport Console Driver\n");
- take_over_console(&newport_con,0,MAX_NR_CONSOLES-1,1);
-
- return 0;
+int init_module(void)
+{
+ if (!newport_startup())
+ printk("Error loading SGI Newport Console driver\n");
+ else
+ printk("Loading SGI Newport Console Driver\n");
+ take_over_console(&newport_con,0,MAX_NR_CONSOLES-1,1);
+ return 0;
}
-int cleanup_module(void) {
- printk("Unloading SGI Newport Console Driver\n");
- return 0;
+int cleanup_module(void)
+{
+ printk("Unloading SGI Newport Console Driver\n");
+ return 0;
}
#endif
|