--- linux-2.2.1_ps2.orig/arch/mips/defconfig	Tue Sep 17 14:38:06 2002
+++ linux-2.2.1_ps2/arch/mips/defconfig	Tue Sep 17 18:23:18 2002
@@ -248,7 +248,7 @@
 CONFIG_VT=y
 CONFIG_VT_CONSOLE=y
 # CONFIG_PROM_PRINTK is not set
-# CONFIG_SERIAL is not set
+CONFIG_SERIAL=m
 # CONFIG_SERIAL_EXTENDED is not set
 # CONFIG_SERIAL_NONSTANDARD is not set
 CONFIG_UNIX98_PTYS=y
--- linux-2.2.1_ps2.orig/arch/mips/ps2/kernel/irq.c	Tue Sep 17 14:38:08 2002
+++ linux-2.2.1_ps2/arch/mips/ps2/kernel/irq.c	Tue Sep 17 16:51:10 2002
@@ -31,6 +31,7 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 #include <asm/ps2/irq.h>
+#include <asm/ps2/speed.h>
 
 atomic_t __mips_bh_counter;
 
@@ -147,7 +148,6 @@
 #define SBUS_PCIC_IMR1	((volatile u16 *)0xbf801468)
 #define SBUS_PCIC_TIMR	((volatile u16 *)0xbf80147e)
 #define SBUS_PCIC3_TIMR	((volatile u16 *)0xbf801466)
-#define SPD_R_INTR_ENA	((volatile u16 *)0xb400002a)
 
 extern int ps2_pccard_present;
 extern int ps2_pcic_type;
--- linux-2.2.1_ps2.orig/drivers/block/ide.c	Tue Sep 17 14:38:14 2002
+++ linux-2.2.1_ps2/drivers/block/ide.c	Tue Sep 17 16:53:05 2002
@@ -126,6 +126,7 @@
 
 #ifdef CONFIG_PS2
 #include <asm/ps2/irq.h>
+#include <asm/ps2/speed.h>
 #endif
 
 #include "ide.h"
@@ -1345,7 +1346,6 @@
 	ide_handler_t *handler;
 #ifdef CONFIG_PS2
 	extern int ps2_pccard_present;
-#define SPD_R_INTR_STAT	((volatile u16 *)0xb4000028)
 
 	/* If HDD interrupt status is not asserted, just ignore it. */
 	if (ps2_pccard_present == 0x0100 && irq == IRQ_SBUS_PCIC
--- linux-2.2.1_ps2.orig/drivers/block/ps2dma.c	Tue Sep 17 14:38:15 2002
+++ linux-2.2.1_ps2/drivers/block/ps2dma.c	Tue Sep 17 16:54:39 2002
@@ -30,12 +30,10 @@
 
 #include <asm/ps2/sifdefs.h>
 #include <asm/ps2/dmarelay.h>
+#include <asm/ps2/speed.h>
 
 #include "ide.h"
 
-#define SPD_R_INTR_STAT	(volatile unsigned short *)0xb4000028
-#define SPD_R_XFR_CTRL	(volatile unsigned char *)0xb4000032
-#define SPD_R_IF_CTRL	(volatile unsigned char *)0xb4000064
 #define IFC_ATA_RST	0x80
 #define IFC_DMA_EN	0x04
 
--- linux-2.2.1_ps2.orig/drivers/char/serial.c	Tue Sep 17 14:38:19 2002
+++ linux-2.2.1_ps2/drivers/char/serial.c	Tue Sep 17 16:50:47 2002
@@ -151,6 +151,21 @@
 #include <asm/bitops.h>
 #include <asm/serial.h>
 
+#ifdef CONFIG_PS2
+#include <asm/ps2/irq.h>
+#include <asm/ps2/speed.h>
+
+//#define PS2UART_DEBUG(a...)   printk(a)
+#define PS2UART_DEBUG(a...)
+
+#define PS2UART_CR1     0xb4000090
+#define PS2UART_CR2     0xb4000092
+
+#define irq_cannonicalize(a) (a)
+#undef IRQ_T
+#define IRQ_T(state)    (SA_SHIRQ|SA_INTERRUPT)
+#endif  /* CONFIG_PS2 */
+
 #ifdef SERIAL_INLINE
 #define _INLINE_ inline
 #endif
@@ -252,6 +267,9 @@
 
 static inline unsigned int serial_in(struct async_struct *info, int offset)
 {
+#ifdef CONFIG_PS2
+        offset <<= 1;
+#endif
 #ifdef CONFIG_HUB6
     if (info->hub6) {
 	outb(info->hub6 - 1 + offset, info->port);
@@ -268,6 +286,9 @@
 
 static inline unsigned int serial_inp(struct async_struct *info, int offset)
 {
+#ifdef CONFIG_PS2
+        offset <<= 1;
+#endif
 #ifdef CONFIG_HUB6
     if (info->hub6) {
 	outb(info->hub6 - 1 + offset, info->port);
@@ -288,6 +309,9 @@
 
 static inline void serial_out(struct async_struct *info, int offset, int value)
 {
+#ifdef CONFIG_PS2
+        offset <<= 1;
+#endif
 #ifdef CONFIG_HUB6
     if (info->hub6) {
 	outb(info->hub6 - 1 + offset, info->port);
@@ -305,6 +329,9 @@
 static inline void serial_outp(struct async_struct *info, int offset,
 			       int value)
 {
+#ifdef CONFIG_PS2
+        offset <<= 1;
+#endif
 #ifdef CONFIG_HUB6
     if (info->hub6) {
 	outb(info->hub6 - 1 + offset, info->port);
@@ -676,6 +703,10 @@
 	int first_multi = 0;
 	struct rs_multiport_struct *multi;
 #endif
+
+#ifdef CONFIG_PS2
+        if (!(*SPD_R_INTR_STAT & (1<<12))) return;
+#endif
 	
 #ifdef SERIAL_DEBUG_INTR
 	printk("rs_interrupt_single(%d)...", irq);
@@ -732,6 +763,10 @@
 	int first_multi= 0;
 	struct rs_multiport_struct *multi;
 
+#ifdef CONFIG_PS2
+        if (!(*SPD_R_INTR_STAT & (1<<12))) return;
+#endif
+
 #ifdef SERIAL_DEBUG_INTR
 	printk("rs_interrupt_multi(%d)...", irq);
 #endif
@@ -1136,6 +1171,9 @@
 
 	info->flags |= ASYNC_INITIALIZED;
 	restore_flags(flags);
+#ifdef CONFIG_PS2
+        PS2UART_DEBUG("SERIAL startup() return 0\n");
+#endif
 	return 0;
 	
 errout:
@@ -2968,7 +3006,9 @@
 	 */
 	scratch = serial_inp(info, UART_IER);
 	serial_outp(info, UART_IER, 0);
+#ifndef CONFIG_PS2
 	outb(0xff, 0x080);
+#endif
 	scratch2 = serial_inp(info, UART_IER);
 	serial_outp(info, UART_IER, scratch);
 	if (scratch2) {
@@ -3099,6 +3139,27 @@
 	extern void atomwide_serial_init (void);
 	extern void dualsp_serial_init (void);
 
+#ifdef CONFIG_PS2
+        extern int ps2_pccard_present;
+        if (ps2_pccard_present != 0x0100) {     /* PS2 HDD & Ether unit */
+                printk("PS2_SPD not found. type=%04x\n", ps2_pccard_present);
+                return -ENODEV;
+        }
+        if ((*SPD_R_REV_3 & 0x08) == 0) {
+                printk("PlayStation2 MODEM not found.\n");
+                return -ENODEV;
+        }
+        PS2UART_DEBUG("PlayStation2 MODEM found. Spd-Rev-3=%02x", *SPD_R_REV_3);
+        outb(0x1b, PS2UART_CR1);
+        outb(0x04, PS2UART_CR2);
+        udelay(10*1000);                // 10ms
+
+        // enable UART interrupt
+        PS2UART_DEBUG("  IER = %x -->", *SPD_R_INTR_ENA);
+        *SPD_R_INTR_ENA |= (1<<12);
+        PS2UART_DEBUG(" %x\n", *SPD_R_INTR_ENA);
+#endif
+
 #ifdef CONFIG_ATOMWIDE_SERIAL
 	atomwide_serial_init ();
 #endif
@@ -3207,6 +3268,11 @@
 			continue;
 		if (state->flags & ASYNC_BOOT_AUTOCONF)
 			autoconfig(state);
+#ifdef CONFIG_PS2
+                PS2UART_DEBUG("SERIAL ttyS%02d at 0x%x (irq = %d) is a %s\n",
+                       state->line, state->port, state->irq,
+                       uart_config[state->type].name);
+#endif
 	}
 	/*
 	 * Detect the IRQ only once every port is initialised,
@@ -3322,6 +3388,12 @@
 		printk("SERIAL: failed to unregister callout driver (%d)\n", 
 		       e2);
 	restore_flags(flags);
+
+#ifdef CONFIG_PS2
+        // disable UART interrupt
+        PS2UART_DEBUG("Serial Module unloading. IER = %x -->", *SPD_R_INTR_ENA);        *SPD_R_INTR_ENA &= ~(1<<12);
+        PS2UART_DEBUG(" %x\n", *SPD_R_INTR_ENA);
+#endif
 
 	for (i = 0; i < NR_PORTS; i++) {
 		if (rs_table[i].type != PORT_UNKNOWN)
--- linux-2.2.1_ps2.orig/include/asm-mips/serial.h	Mon Oct 21 18:28:50 2002
+++ linux-2.2.1_ps2/include/asm-mips/serial.h	Mon Oct 21 18:29:09 2002
@@ -142,8 +142,17 @@
 #define MCA_SERIAL_PORT_DFNS
 #endif
 
+#ifdef CONFIG_PS2
+#define PS2_SERIAL_PORT_DFNS			\
+	{ 0, BASE_BAUD, 0xb4000080, IRQ_SBUS_PCIC,	\
+	  ASYNC_BOOT_AUTOCONF | ASYNC_SKIP_TEST },	/* DEV9M,UART */
+#else
+#define PS2_SERIAL_PORT_DFNS
+#endif
+
 #define SERIAL_PORT_DFNS		\
 	JAZZ_SERIAL_PORT_DEFNS		\
 	STD_SERIAL_PORT_DEFNS		\
 	EXTRA_SERIAL_PORT_DEFNS		\
-	HUB6_SERIAL_PORT_DFNS
+	HUB6_SERIAL_PORT_DFNS		\
+	PS2_SERIAL_PORT_DFNS
--- linux-2.2.1_ps2.orig/include/asm-mips/ps2/speed.h	Thu Aug 30 16:30:55 2001
+++ linux-2.2.1_ps2/include/asm-mips/ps2/speed.h	Sun Jul  7 12:01:28 2002
@@ -0,0 +1,28 @@
+/*
+ * linux/include/asm-mips/ps2/speed.h
+ *
+ *	Copyright (C) 2001  Sony Computer Entertainment Inc.
+ *
+ * This file is subject to the terms and conditions of the GNU General
+ * Public License Version 2. See the file "COPYING" in the main
+ * directory of this archive for more details.
+ *
+ * $Id: speed.h,v 1.1 2001/10/31 00:31:57 namihara Exp $
+ */
+
+#ifndef __ASM_PS2_SPEED_H
+#define __ASM_PS2_SPEED_H
+
+#define DEV9M_BASE		0xb4000000
+
+#define SPD_R_REV		((volatile u8  *) (DEV9M_BASE + 0x00))
+#define SPD_R_REV_1		((volatile u8  *) (DEV9M_BASE + 0x00))
+#define SPD_R_REV_3		((volatile u8  *) (DEV9M_BASE + 0x04))
+
+#define SPD_R_INTR_STAT		((volatile u16 *) (DEV9M_BASE + 0x28))
+#define SPD_R_INTR_ENA		((volatile u16 *) (DEV9M_BASE + 0x2a))
+#define SPD_R_XFR_CTRL		((volatile u8  *) (DEV9M_BASE + 0x32))
+#define SPD_R_IF_CTRL		((volatile u8  *) (DEV9M_BASE + 0x64))
+
+#endif /* __ASM_PS2_SPEED_H */
+
