/*
 * Wrap-around code for a console using the
 * DECstation PROM io-routines.
 *
 * Copyright (c) 1998 Harald Koerfgen
 */

#include <linux/tty.h>
#include <linux/ptrace.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/fs.h>
#include <asm/io.h>

#define	NDS_CTRLBASE	0x04000000		/* Register IO base */
#define	NDS_PALBASE	0x05000000		/* Pallete RAM base */
#define	NDS_VIDBASE	0x06000000		/* Video RAM base */

#define NDS_DISPCNT	(NDS_CTRLBASE + 0x00)
/* NDS_BGnCNT */
#define NDS_BG_CNT(n)	(NDS_CTRLBASE + 0x08 + 2*(n))
/* NDS_BGnHOFS */
#define NDS_BG_HOFS(n)	(NDS_CTRLBASE + 0x10 + 4*(n))
/* NDS_BGnVOFS */
#define NDS_BG_VOFS(n)	(NDS_CTRLBASE + 0x12 + 4*(n))

/* 16 16-colour palettes */
#define NDS_BG_COL16	(0<<7)

/* 15-bit colour */
#define NDS_RGB(r,g,b)	((((b<<5)|g)<<5)|r)

/* white */
#define NDS_COL_WHITE	NDS_RGB(31,31,31)
/* grey */
#define NDS_COL_GREY	NDS_RGB(23,23,23)
/* bright green */
#define NDS_COL_GREEN_L	NDS_RGB( 0,31, 0)
/* medium green */
#define NDS_COL_GREEN_M	NDS_RGB( 0,23, 0)
/* dark green */
#define NDS_COL_GREEN_D	NDS_RGB( 0,15, 0)
/* bright red */
#define NDS_COL_RED_L	NDS_RGB(31, 0, 0)
/* medium red */
#define NDS_COL_RED_M	NDS_RGB(23, 0, 0)
/* dark red */
#define NDS_COL_RED_D	NDS_RGB(15, 0, 0)
/* bright blue */
#define NDS_COL_BLUE_L	NDS_RGB(0, 0, 31)
/* medium blue */
#define NDS_COL_BLUE_M	NDS_RGB(0, 0, 23)
/* dark blue */
#define NDS_COL_BLUE_D	NDS_RGB(0, 0, 15)
/* black (very dark ;-) */
#define NDS_COL_BLACK	NDS_RGB( 0, 0, 0)

/* 
 * Choose palette entry for character colour
 * Must be different from 0 (= backdrop colour)
 */
#define NDS_TXT_COL_IDX	1
#if NDS_TXT_COL_IDX == 0
#error NDS palette entry 0 is reserved for backdrop colour
#endif

#define NDS_TXT_COL0	NDS_COL_WHITE
#define NDS_TXT_COL1	NDS_COL_GREEN_L
#define NDS_TXT_COL2	NDS_COL_RED_L
#define NDS_TXT_COL3	NDS_COL_BLUE_L
#define NDS_TXT_COL4	NDS_COL_GREEN_M
#define NDS_TXT_COL5	NDS_COL_RED_M
#define NDS_TXT_COL6	NDS_COL_BLUE_M
#define NDS_TXT_COL7	NDS_COL_GREEN_D
#define NDS_TXT_COL8	NDS_COL_RED_D
#define NDS_TXT_COL9	NDS_COL_BLUE_D
#define NDS_TXT_COL10	NDS_COL_GREY
#define NDS_TXT_COL11	NDS_COL_GREY
#define NDS_TXT_COL12	NDS_COL_GREY
#define NDS_TXT_COL13	NDS_COL_GREY
#define NDS_TXT_COL14	NDS_COL_GREY
#define NDS_TXT_COL15	NDS_COL_GREY
#define NDS_TXT_COL(i)	NDS_TXT_COL##i

/* NDS text screen number */
#define NDS_TXT_BG	0

/* Text mode */
#define NDS_BG_MODE	0
#define NDS_BG_ACTIVE(n)	(1<<(8+n))

/* Screen size 256x256 (BG0 only) */
#define NDS_SC_SIZE	0
#define NDS_TILE_OFF	(0<<14)
#define NDS_TILE	(NDS_VIDBASE + NDS_TILE_OFF)
/* 32 kB offset (configurable in units of 2 kB */
#define NDS_BGMAP_OFF	(16<<11)
/* add a 2 kB offset for each BG map */
#define NDS_BGMAP(n)	(NDS_VIDBASE + NDS_BGMAP_OFF + (1<<11)*(n))
/* Priority = [0;3], 0=Highest */
#define NDS_BG_PRI(n)	(n)
/* Palette */
#define NDS_COL		16
#define NDS_BG_COL	(NDS_BG_COL16)
#if NDS_TXT_COL_IDX < 0 || NDS_TXT_COL_IDX > 15
#error NDS Text colour index must be in range [1;15]
#endif

/* Flags for DISPCNT register */
/* Activate NDS_TXT_BG */
#define NDS_DISPCNT_F	(NDS_BG_MODE | NDS_BG_ACTIVE(NDS_TXT_BG))
/* Flags for NDS_BG_CNT(NDS_TXT_BG) register */
/* BG1-3 automatically use the correct offset from NDS_MAP(0) (2kB each) */
#define NDS_TXT_BG_CNT_F	(NDS_BG_PRI(0) | NDS_BG_COL | ((NDS_BGMAP_OFF>>11)<<8) | NDS_SC_SIZE)

/****************************************************************************/

/*
 *	Screen dimensions. Need to allow for screen overshoot regions too.
 *	Also keep track of current cursor postion (x,y).
 */
#define	NDS_XORD	5
#define	NDS_XMAX	(1<<NDS_XORD)
#define	NDS_XLEN	32
#define	NDS_YORD	5
#define	NDS_YMAX	(1<<NDS_YORD)
#define	NDS_YLEN	24

int	nds_console_x;
int	nds_console_y;

/****************************************************************************/

static signed short vert_offset = 0;

#ifndef MIN
#define MIN(a,b)	((a) < (b) ? (a) : (b))
#endif

/****************************************************************************/

void nds_console_console_print(char *s);
void nds_console_console_putc(char c);

/****************************************************************************/

/****************************************************************************/

/****************************************************************************/

/****************************************************************************/

struct charmap {
	unsigned char	bitmap[8];
};

const struct charmap	nds_console_charmap[] = {
/*00*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*01*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*02*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*03*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*04*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*05*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*06*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*07*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*08*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*09*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*0a*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*0b*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*0c*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*0d*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*0e*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*0f*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*10*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*11*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*12*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*13*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*14*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*15*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*16*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*17*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*18*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*19*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*1a*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*1b*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*1c*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*1d*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*1e*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*1f*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*20*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*21*/	{ { 0x10, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x00 } },
/*22*/	{ { 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*23*/	{ { 0x28, 0x28, 0xfe, 0x28, 0xfe, 0x28, 0x28, 0x00 } },
/*24*/	{ { 0x10, 0x7c, 0x80, 0x7c, 0x02, 0x7c, 0x10, 0x00 } },
/*25*/	{ { 0xc2, 0xc4, 0x08, 0x10, 0x20, 0x46, 0x86, 0x00 } },
/*26*/	{ { 0x60, 0x90, 0x60, 0x90, 0x88, 0x84, 0x7a, 0x00 } },
/*27*/	{ { 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*28*/	{ { 0x08, 0x10, 0x20, 0x20, 0x20, 0x10, 0x08, 0x00 } },
/*29*/	{ { 0x20, 0x10, 0x08, 0x08, 0x08, 0x10, 0x20, 0x00 } },
/*2a*/	{ { 0x44, 0x28, 0x10, 0xfe, 0x10, 0x28, 0x44, 0x00 } },
/*2b*/	{ { 0x00, 0x10, 0x10, 0x7c, 0x10, 0x10, 0x00, 0x00 } },
/*2c*/	{ { 0x00, 0x00, 0x00, 0x00, 0x18, 0x08, 0x10, 0x00 } },
/*2d*/	{ { 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00 } },
/*2e*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00 } },
/*2f*/	{ { 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00 } },
/*30*/	{ { 0x7c, 0x86, 0x8a, 0x92, 0xa2, 0xc2, 0x7c, 0x00 } },
/*31*/	{ { 0x10, 0x30, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00 } },
/*32*/	{ { 0x7c, 0x82, 0x04, 0x08, 0x10, 0x20, 0xfe, 0x00 } },
/*33*/	{ { 0x7c, 0x82, 0x02, 0x3c, 0x02, 0x82, 0x7c, 0x00 } },
/*34*/	{ { 0x40, 0x40, 0x84, 0x84, 0xfe, 0x04, 0x04, 0x00 } },
/*35*/	{ { 0xfe, 0x80, 0x80, 0xfc, 0x02, 0x82, 0x7c, 0x00 } },
/*36*/	{ { 0x10, 0x20, 0x40, 0xfc, 0x82, 0x82, 0x7c, 0x00 } },
/*37*/	{ { 0xfe, 0x02, 0x04, 0x08, 0x10, 0x10, 0x10, 0x00 } },
/*38*/	{ { 0x7c, 0x82, 0x82, 0x7c, 0x82, 0x82, 0x7c, 0x00 } },
/*39*/	{ { 0x7c, 0x82, 0x82, 0x7e, 0x04, 0x08, 0x10, 0x00 } },
/*3a*/	{ { 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0x00, 0x00 } },
/*3b*/	{ { 0x00, 0x00, 0x10, 0x00, 0x10, 0x10, 0x20, 0x00 } },
/*3c*/	{ { 0x04, 0x08, 0x10, 0x20, 0x10, 0x08, 0x04, 0x00 } },
/*3d*/	{ { 0x00, 0x00, 0x7c, 0x00, 0x7c, 0x00, 0x00, 0x00 } },
/*3e*/	{ { 0x40, 0x20, 0x10, 0x08, 0x10, 0x20, 0x40, 0x00 } },
/*3f*/	{ { 0x7c, 0x82, 0x04, 0x08, 0x10, 0x00, 0x10, 0x00 } },
/*40*/	{ { 0x7c, 0x82, 0xbe, 0xa2, 0xbe, 0x80, 0x7e, 0x00 } },
/*41*/	{ { 0x10, 0x28, 0x44, 0x82, 0xfe, 0x82, 0x82, 0x00 } },
/*42*/	{ { 0xfc, 0x82, 0x82, 0xfc, 0x82, 0x82, 0xfc, 0x00 } },
/*43*/	{ { 0x7c, 0x82, 0x80, 0x80, 0x80, 0x82, 0x7c, 0x00 } },
/*44*/	{ { 0xfc, 0x82, 0x82, 0x82, 0x82, 0x82, 0xfc, 0x00 } },
/*45*/	{ { 0xfe, 0x80, 0x80, 0xfc, 0x80, 0x80, 0xfe, 0x00 } },
/*46*/	{ { 0xfe, 0x80, 0x80, 0xfc, 0x80, 0x80, 0x80, 0x00 } },
/*47*/	{ { 0x7c, 0x82, 0x80, 0x8e, 0x82, 0x82, 0x7e, 0x00 } },
/*48*/	{ { 0x82, 0x82, 0x82, 0xfe, 0x82, 0x82, 0x82, 0x00 } },
/*49*/	{ { 0x38, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00 } },
/*4a*/	{ { 0x02, 0x02, 0x02, 0x02, 0x02, 0x82, 0x7c, 0x00 } },
/*4b*/	{ { 0x82, 0x8c, 0xb0, 0xc0, 0xb0, 0x8c, 0x82, 0x00 } },
/*4c*/	{ { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xfe, 0x00 } },
/*4d*/	{ { 0x82, 0xc6, 0xaa, 0x92, 0x82, 0x82, 0x82, 0x00 } },
/*4e*/	{ { 0x82, 0xc2, 0xa2, 0x92, 0x8a, 0x86, 0x82, 0x00 } },
/*4f*/	{ { 0x7c, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c, 0x00 } },
/*50*/	{ { 0xfc, 0x82, 0x82, 0xfc, 0x80, 0x80, 0x80, 0x00 } },
/*51*/	{ { 0x7c, 0x82, 0x82, 0x82, 0x82, 0x84, 0x7a, 0x00 } },
/*52*/	{ { 0xfc, 0x82, 0x82, 0xfc, 0x88, 0x84, 0x82, 0x00 } },
/*53*/	{ { 0x7c, 0x82, 0x80, 0x7c, 0x02, 0x82, 0x7c, 0x00 } },
/*54*/	{ { 0xfe, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00 } },
/*55*/	{ { 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x7c, 0x00 } },
/*56*/	{ { 0x82, 0x82, 0x82, 0x82, 0x44, 0x28, 0x10, 0x00 } },
/*57*/	{ { 0x82, 0x82, 0x82, 0x92, 0x92, 0x54, 0x28, 0x00 } },
/*58*/	{ { 0x82, 0x44, 0x28, 0x10, 0x28, 0x44, 0x82, 0x00 } },
/*59*/	{ { 0x82, 0x82, 0x44, 0x28, 0x10, 0x10, 0x10, 0x00 } },
/*5a*/	{ { 0xfe, 0x04, 0x08, 0x10, 0x20, 0x40, 0xfe, 0x00 } },
/*5b*/	{ { 0x38, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x00 } },
/*5c*/	{ { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x00 } },
/*5d*/	{ { 0x38, 0x08, 0x08, 0x08, 0x08, 0x08, 0x38, 0x00 } },
/*5e*/	{ { 0x10, 0x28, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*5f*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00 } },
/*60*/	{ { 0x20, 0x10, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*61*/	{ { 0x00, 0x00, 0x7e, 0x82, 0x82, 0x86, 0x7a, 0x00 } },
/*62*/	{ { 0x80, 0x80, 0xfc, 0x82, 0x82, 0x82, 0xfc, 0x00 } },
/*63*/	{ { 0x00, 0x00, 0x7e, 0x80, 0x80, 0x80, 0x7e, 0x00 } },
/*64*/	{ { 0x02, 0x02, 0x7e, 0x82, 0x82, 0x82, 0x7e, 0x00 } },
/*65*/	{ { 0x00, 0x00, 0x7c, 0x82, 0xfe, 0x80, 0x7c, 0x00 } },
/*66*/	{ { 0x0e, 0x10, 0x7c, 0x10, 0x10, 0x10, 0x10, 0x00 } },
/*67*/	{ { 0x00, 0x00, 0x7e, 0x82, 0x7e, 0x02, 0x7c, 0x00 } },
/*68*/	{ { 0x80, 0x80, 0xfc, 0x82, 0x82, 0x82, 0x82, 0x00 } },
/*69*/	{ { 0x10, 0x00, 0x30, 0x10, 0x10, 0x10, 0x38, 0x00 } },
/*6a*/	{ { 0x08, 0x00, 0x18, 0x08, 0x08, 0x08, 0x70, 0x00 } },
/*6b*/	{ { 0x80, 0x80, 0x86, 0x98, 0xe0, 0x98, 0x86, 0x00 } },
/*6c*/	{ { 0x30, 0x10, 0x10, 0x10, 0x10, 0x10, 0x38, 0x00 } },
/*6d*/	{ { 0x00, 0x00, 0xec, 0x92, 0x92, 0x92, 0x82, 0x00 } },
/*6e*/	{ { 0x00, 0x00, 0xbc, 0xc2, 0x82, 0x82, 0x82, 0x00 } },
/*6f*/	{ { 0x00, 0x00, 0x7c, 0x82, 0x82, 0x82, 0x7c, 0x00 } },
/*70*/	{ { 0x00, 0x00, 0xfc, 0x82, 0xfc, 0x80, 0x80, 0x00 } },
/*71*/	{ { 0x00, 0x00, 0x7e, 0x82, 0x7e, 0x02, 0x02, 0x00 } },
/*72*/	{ { 0x00, 0x00, 0xbe, 0xc0, 0x80, 0x80, 0x80, 0x00 } },
/*73*/	{ { 0x00, 0x00, 0x7e, 0x80, 0x7c, 0x02, 0xfc, 0x00 } },
/*74*/	{ { 0x10, 0x10, 0x7c, 0x10, 0x10, 0x10, 0x0c, 0x00 } },
/*75*/	{ { 0x00, 0x00, 0x82, 0x82, 0x82, 0x86, 0x7a, 0x00 } },
/*76*/	{ { 0x00, 0x00, 0x82, 0x82, 0x44, 0x28, 0x10, 0x00 } },
/*77*/	{ { 0x00, 0x00, 0x92, 0x92, 0x92, 0x92, 0x6c, 0x00 } },
/*78*/	{ { 0x00, 0x00, 0x82, 0x44, 0x38, 0x44, 0x82, 0x00 } },
/*79*/	{ { 0x00, 0x00, 0x82, 0x82, 0x7e, 0x02, 0x7c, 0x00 } },
/*7a*/	{ { 0x00, 0x00, 0xfe, 0x0c, 0x30, 0xc0, 0xfe, 0x00 } },
/*7b*/	{ { 0x0c, 0x10, 0x10, 0x20, 0x10, 0x10, 0x0c, 0x00 } },
/*7c*/	{ { 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x00 } },
/*7d*/	{ { 0x60, 0x10, 0x10, 0x08, 0x10, 0x10, 0x60, 0x00 } },
/*7e*/	{ { 0x34, 0x2c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
/*7f*/	{ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } },
};

/*
 *	Create text tiles in tile map. this is a simple bit conversion
 *	from the base character map table.
 */

void nds_console_inittext(void)
{
	volatile unsigned short	*vp = (volatile unsigned short *) NDS_TILE;
	struct charmap	*cp;
	unsigned char	bits;
	int		i, j, r, b;

	for (j = 0; (j < 2); j++) {
		cp = (struct charmap *) &nds_console_charmap[0];
		for (i = 0; i < sizeof(nds_console_charmap)/sizeof(struct charmap); i++, cp++) {
			for (r = 0; (r < 8); r++) {
				bits = cp->bitmap[r];
				for (b = 0; b < 8; b += 4) {
					*vp++ = ((bits & (0x80>>b)) ? (((unsigned short)NDS_TXT_COL_IDX)<< 0) : 0) |
						((bits & (0x40>>b)) ? (((unsigned short)NDS_TXT_COL_IDX)<< 4) : 0) |
						((bits & (0x20>>b)) ? (((unsigned short)NDS_TXT_COL_IDX)<< 8) : 0) |
						((bits & (0x10>>b)) ? (((unsigned short)NDS_TXT_COL_IDX)<<12) : 0);
				}
			}
		}
	}
}

/****************************************************************************/

/*
 *	Scroll one screen line.
 */

void nds_console_scroll(void)
{
	unsigned short* vert_offset_reg = (unsigned short *) (NDS_BG_VOFS(NDS_TXT_BG));

	/* scroll up 1 line, wrap around at 32 lines */
	vert_offset = (vert_offset + 1) & (NDS_YMAX-1);
	
	/* 8 dots makes 1 character line */
	*vert_offset_reg = vert_offset << 3;
}

/****************************************************************************/

void nds_console_console_putc(char c)
{
	/* 
	 * Note that this works because the BG maps are
	 * always aligned at a 2 kB boundary
	 */
	unsigned short *vp = (unsigned short*) 
		(NDS_BGMAP(NDS_TXT_BG) |
		 (((((nds_console_y + vert_offset) & (NDS_YMAX-1)) << NDS_XORD) |
		   nds_console_x) << 1)
		);
	unsigned int i;
	/* choose colour for the character */
	unsigned short nds_palette = 0;	/* white */

	/* don't print special characters */
	if (c != '\r' && c != '\n')
		*vp = (nds_palette << 12) | (((unsigned short)c) & 0x1ff);

	nds_console_x++;
	if ((nds_console_x >= NDS_XLEN) || (c == '\n')) {
		nds_console_x = 0;
		if (nds_console_y < NDS_YLEN - 1) {
		nds_console_y++;
		} else {
			/* blank out new line */
			vp = (unsigned short*) 
				(NDS_BGMAP(NDS_TXT_BG) |
				 (((NDS_YLEN + vert_offset) & (NDS_YMAX-1)) << (NDS_XORD + 1))
				);
			for (i = NDS_XLEN; i; i--)
				*vp++ = ' ';
			nds_console_scroll();
		}
	}
	else if (c == '\r')
		nds_console_x = 0;
}

/****************************************************************************/

extern void nds_console_write(struct console *co, const char *s,
			       unsigned count)
{
	unsigned i;

	/*
	 *    Now, do each character
	 */
	for (i = 0; i < count; i++) {
		nds_console_console_putc(*s++);	
	}
#ifdef CONFIG_NDS_TEXT_CONSOLE_STEP_BY_STEP
	/* Step-by-step mode (press A button for next line of output).
	 * This is really ugly but really useful at times :) */
	while ( (*(volatile u16*)0x04000130 & 1));
	while (!(*(volatile u16*)0x04000130 & 1));
#endif
}

/*
 *	Initialize the NDS screen into mode 0. That is a simple tiled
 *	mode, nice and easy to do conventional text.
 */
static int __init nds_console_setup(struct console *co, char *options)
{
	volatile unsigned short	*pp;
	int			i;

	/* VRAM setup */
	writel(0x00010100, 0x04000000);
	writeb(0x81, 0x04000240);

	/* Enable mode 0 */
	*((unsigned short *) NDS_DISPCNT) = NDS_DISPCNT_F;	/*MODE0|BG0*/
	/* BG0: 256 colour palette, 32kB BG Map Data */
	*((unsigned short *) NDS_BG_CNT(NDS_TXT_BG)) = NDS_TXT_BG_CNT_F;

	/* Default palete, everything is white :-) */
	pp = (volatile unsigned short *) NDS_PALBASE;
	for (i = 255; i; i--)
		pp[i] = NDS_COL_WHITE;

	/* text colours */
	pp[16* 0 + NDS_TXT_COL_IDX] = NDS_TXT_COL( 0);
	pp[16* 1 + NDS_TXT_COL_IDX] = NDS_TXT_COL( 1);
	pp[16* 2 + NDS_TXT_COL_IDX] = NDS_TXT_COL( 2);
	pp[16* 3 + NDS_TXT_COL_IDX] = NDS_TXT_COL( 3);
	pp[16* 4 + NDS_TXT_COL_IDX] = NDS_TXT_COL( 4);
	pp[16* 5 + NDS_TXT_COL_IDX] = NDS_TXT_COL( 5);
	pp[16* 6 + NDS_TXT_COL_IDX] = NDS_TXT_COL( 6);
	pp[16* 7 + NDS_TXT_COL_IDX] = NDS_TXT_COL( 7);
	pp[16* 8 + NDS_TXT_COL_IDX] = NDS_TXT_COL( 8);
	pp[16* 9 + NDS_TXT_COL_IDX] = NDS_TXT_COL( 9);
	pp[16*10 + NDS_TXT_COL_IDX] = NDS_TXT_COL(10);
	pp[16*11 + NDS_TXT_COL_IDX] = NDS_TXT_COL(11);
	pp[16*12 + NDS_TXT_COL_IDX] = NDS_TXT_COL(12);
	pp[16*13 + NDS_TXT_COL_IDX] = NDS_TXT_COL(13);
	pp[16*14 + NDS_TXT_COL_IDX] = NDS_TXT_COL(14);
	pp[16*15 + NDS_TXT_COL_IDX] = NDS_TXT_COL(15);

	/* backdrop colour */
	pp[0] = NDS_COL_BLACK;

	nds_console_x = 0;
	nds_console_y = 0;

	nds_console_inittext();

	return 0;
}

static struct console sercons =
{
	.name	= "ttyS",
	.write	= nds_console_write,
	.setup	= nds_console_setup,
	.flags	= CON_PRINTBUFFER,
	.index	= -1,
};

/*
 *    Register console.
 */

extern int __init nds_console_init(void)
{
//	register_console(&sercons);
	nds_console_setup(NULL,NULL);

	return 0;
}

//console_initcall(nds_console_init);

